2013-04-26 95 views
1

我想使用套接字API(它是項目的一部分,無法更改)手動建立一個dns查詢到DNS服務器。所以我想複製一個結構類似:複製一個結構與動態數組到一個緩衝區在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)); 

到像一個緩衝區:

char* dns_buf = malloc(500); 

,但是當我這樣做,一切都沒有被複制到緩衝區。當我向* host元素輸入不同的字符串時,sizeof(dns_query)保持不變。當我使用

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

它給輸出像:

dns_buf:
的strlen(dns_buf)= 0

此外,當我打印它使用用於像循環:

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

它不輸出任何東西

當我使用指針,而不是memcpy的,如:

dns_buf = dns_query;

它給出了相同的輸出。有人能指示我該怎麼做嗎?

這是整個代碼:

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

更新:我修正了for循環。 dns_buf現在包含正確的信息,但我不知道爲什麼dns_buf和dns_query的輸出不相同。無論如何,現在當我將查詢發送到DNS服務器時,它不會返回任何內容(有時它會返回-1)。有人可以幫忙嗎? – Gholi 2013-04-27 07:16:19

回答

1

dns_buf是不是一個串(其與空字符內完成)。

這是一個指針(爲char *)的存儲空間和內存可以在起步階段,所以這就是爲什麼當你使用strlen(dns_buf)你得到它= 0,這意味着在dns_buf最前一頁元素是0包含0的值

dns_buf內容,您可以使用:

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

我做了,但他們不一樣!這是爲什麼? (當我發送到DNS服務器它不會返回任何東西,所以仍然有錯誤)。 – Gholi 2013-04-26 16:30:12

+0

不知道代碼就知道原因是不可能的。提供整個代碼yhis將有助於檢測問題 – MOHAMED 2013-04-26 16:50:57

+0

我添加了代碼;你可以看看它。 – Gholi 2013-04-26 17:05:14

1

的結構並沒有真正包含字符host的陣列,而是一個指向第一個元素。

這意味着,雖然您正在複製整個結構,但您只需將指針複製到包含在主機中的數據(然後指向相同的字符串)即可。你應該做的是這樣的:

DNS_QUERY *dns_buf = malloc(sizeof(DNS_QUERY)); 
memcpy(dns_buf, dns_query, sizeof(DNS_QUERY)); 
dns_buf.host = "yourmodifiedhost"; 
相關問題