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