2013-04-26 1 views
1

Je souhaite construire manuellement une requête DNS vers le serveur DNS à l'aide des API socket (cela fait partie du projet et ne peut pas être modifié). Donc, je veux copier un struct comme:Copie d'une structure avec un tableau dynamique dans un tampon en c

typedef struct {   
    uint16_t dns_id; /* identification number */  
    uint16_t dns_flags; /* DNS flags */   
    uint16_t dns_qdc; /* number of question entries */  
    uint16_t dns_anc; /* number of answer entries */ 
    uint16_t dns_nsc; /* number of authority entries */  
    uint16_t dns_arc; /* number of resource entries */ 
    unsigned char *host; 
    unsigned short qtype; 
    unsigned short qclass;  
} DNS_QUERY; 


DNS_QUERY* dns_query = (DNS_QUERY *) malloc(sizeof(DNS_QUERY)); 

dans un tampon comme:

char* dns_buf = malloc(500); 

mais quand je fais ça, rien a été copié dans le tampon. Lorsque j'insère différentes chaînes dans l'élément * host, sizeof (dns_query) reste le même. Quand j'utilise

memcpy(dns_buf, dns_query, sizeof(DNS_QUERY)); 

donne une sortie comme:

dns_buf:
strlen (dns_buf) = 0

Aussi quand j'imprimer à l'aide de la boucle comme:

for (i = 0 ; i<strlen(dns_buf) ; i++){ 
     printf("%c", dns_buf[i]); 
    } 

il ne sort rien

Quand je utiliser des pointeurs au lieu de memcpy, comme:

dns_buf = dns_query;

lui donne la même sortie. Quelqu'un pourrait-il m'indiquer ce que je devrais faire?

Ceci est le code complet:

int udp_connect(char *hostname, char *dns_name, char buf[]){ 

    int sockfd; 
    int num_bytes; 
    struct sockaddr_in servaddr; 
    char str[INET_ADDRSTRLEN]; 
    struct hostent *hptr; /* For gethostbyname() */ 
    char **pptr; /* For inet_ntop() */ 
    char* dns_buf, recv_buf = NULL; 
    int len = 0; 
    int i = 0; 
    static unsigned short id = 0; /* For the query ID */ 

    /* Allocating memory for structs */ 
    DNS_QUERY* dns_query = malloc(sizeof(DNS_QUERY)); 
    /* QUESTION *dns_question = malloc(sizeof(QUESTION));*/ 
    recv_buf = malloc(MAXDATASIZE); 

    if((hptr = gethostbyname(dns_name)) == NULL){ 
     perror("Error in gethostbyname()\n"); 
     exit(1); 
    } 

    if ((pptr = hptr->h_addr_list) != NULL) { /* (hptr->h_addrtype == AF_INET) && */ 
     printf("The address is: %s\n", inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str))); 
    } else { 
     perror("Error in inet_ntop() \n"); 
    } 

    memset(&servaddr, 0, sizeof (servaddr)); 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_port = htons(DNS_PORT); 
    inet_pton(AF_INET, str, &servaddr.sin_addr); 

    if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1){ 
     perror("Error while making a socket"); 
     return -1; 
    } 

    /* Setting hostname into the name segment of the query */ 
    ChangetoDnsNameFormat(hostname); 
    dns_query->host = hostname; 
    printf("\ndns_query->host: %s\n", dns_query->host); 


    /* memcpy(dns_buf, dns_query, sizeof(DNS_QUERY)); */  

    /* setting up the header */ 
    dns_query->dns_id = htons(id); /* id */ 
    dns_query->dns_flags = htons(0x10); /* 0000000100000000 recursion is desired*/ 
    dns_query->dns_qdc = htons(0x01); /* We have one question */ 
    dns_query->dns_anc = htons(0x00); 
    dns_query->dns_nsc = htons(0x00); 
    dns_query->dns_arc = htons(0x00); 

    dns_query->qtype = htons(1); /* For IPv4 */ 
    dns_query->qclass = htons(1); /* For internet */ 

    len = sizeof(DNS_QUERY) + strlen(hostname); /* Calculating the length to use it in sendto() */ 

    dns_buf = malloc(len); 

    dns_buf = dns_query; 
    /* memcpy(dns_buf, dns_query, sizeof(DNS_QUERY)); */ 

    for (i = 0 ; i<sizeof(DNS_QUERY) ; i++){ 
      printf("%02X", dns_buf[i]); 
    } 

    /* to check if the same as dns_query, use the following print also */ 
    for (i = 0 ; i<sizeof(DNS_QUERY) ; i++){ 
      printf("%02X", dns_query[i]); 
     } 
    print("\n"); 

    /* Sending the datagram to the dns server */ 
    printf("\n--------------------\nSending datagram: \n%s\n", dns_buf); 
    if ((num_bytes = sendto(sockfd, dns_buf, len, 0, (struct sockaddr *) &servaddr, sizeof(servaddr))) == -1){ 
     perror("Error in sendto"); 
     exit(1); 
    } 

    /* Receiving the datagram from the dns server */ 
    printf("Receiving datagram...\n"); 
    num_bytes = recvfrom(sockfd, recv_buf, MAXDATASIZE, 0, NULL, NULL); 
    printf("Received %i bytes of datagram...\n", num_bytes); 

    printf("dns_buf in udp connect: %s\n", recv_buf); 

    id = id + 1; 

    free(dns_query); 
    freeaddrinfo((struct addrinfo *) &servaddr); 
    close(sockfd); 

    return sockfd; 
} 
/******************************************************************************/ 
void ChangetoDnsNameFormat(char *hostname) 
{ 
    int walker=0; 
    int i; 
    int counter = 0; 
    char tmp[40]; 

    strcat(hostname, "$"); /* For having a $ at the end of the dns name format */ 

    for(i=0 ; i< (int) strlen((char*)hostname) ; i++) 
    { 
     if(hostname[i]=='.') 
     { 
      tmp[walker] = (char) counter + 48; 
      /*printf("%s\n", tmp);*/ 

      for(; walker < i ; walker++) 
      { 
       tmp[walker + 1] = hostname[walker]; 
      } 

      walker++; 
      counter = -1; 
     }else if(hostname[i]=='$'){ 

      tmp[walker] = (char) counter + 47; 
      /*printf("%s\n", tmp);*/ 

      for(; walker < i ; walker++) 
      { 
       tmp[walker + 1] = hostname[walker]; 
      } 

      walker++; 
      counter = -1; 
     } 
     counter++; 
    } 
    walker--; 
    tmp[walker] = '\0'; /* Terminate the string */ 

    strcat(tmp, "0"); /* For having a 0 at the end of the dns name format */ 

    strcpy(hostname, tmp); 
} 
+0

MISES À JOUR: J'ai corrigé la boucle for. Le fichier dns_buf contient maintenant la bonne information mais je ne sais pas pourquoi la sortie de dns_buf et dns_query ne sont pas les mêmes. De toute façon, maintenant quand j'envoie la requête au serveur DNS, il ne retournera rien (parfois il renvoie -1). Quelqu'un pourrait-il m'aider? – Gholi

Répondre

1

dns_buf est pas une chaîne (qui termine avec charcter null).

il est un pointeur (comme char *) à un espace de mémoire et la mémoire pourrait contient 0 comme des valeurs au début et c'est pourquoi lorsque vous utilisez strlen(dns_buf) vous obtenez = 0 cela signifie que l'élément fisrt dans le dns_buf est 0

pour voir le contenu dns_buf vous pouvez utiliser:

for (i = 0 ; i<sizeof(DNS_QUERY) ; i++){ 
     printf("%02X", dns_buf[i]); 
    } 
print("\n"); 

// to check if the same as dns_query, use the following print also 
for (i = 0 ; i<sizeof(DNS_QUERY) ; i++){ 
     printf("%02X", dns_query[i]); 
    } 
print("\n"); 
+0

Je l'ai fait mais ils n'étaient pas les mêmes! Pourquoi donc? (quand je l'envoie au serveur DNS, il ne renvoie rien, donc quelque chose ne va pas). – Gholi

+0

il est tout à fait impossible de connaître la cause sans avoir vu le code. fournir le code entier yhis aidera à détecter le problème – MOHAMED

+0

J'ai ajouté le code; ce serait gentil de votre part de le regarder. – Gholi

1

le struct ne contient pas vraiment le tableau de caractère host mais plutôt un pointeur vers le premier élément. Cela signifie que, bien que vous copiiez la structure entière, il vous suffit de copier le pointeur sur les données contenues dans l'hôte (qui pointe alors vers la même chaîne). Ce que vous devez faire est quelque chose comme:

DNS_QUERY *dns_buf = malloc(sizeof(DNS_QUERY)); 
memcpy(dns_buf, dns_query, sizeof(DNS_QUERY)); 
dns_buf.host = "yourmodifiedhost"; 
Questions connexes