Reputation: 954
I'm writing a DNS query client and can't understand how my data is being sent and how to make it work correctly.
In Wireshark, I'm getting a lot of random data with MALFORMED PACKET warnings, and no response from the DNS server I'm testing with. (currently Google's DNS... 8.8.8.8)
A snippet...
typedef struct DNS_HEADER {
// id to identify the request
int16_t id;
// query or response flag; default is 0
uint8_t qr :1;
// type of query; default is 0
uint8_t opcode :4;
// authoritative answer
uint8_t aa :1;
// message was truncated
uint8_t tc :1;
// recursion desired; default is yes
uint8_t rd :1;
// recursion available
uint8_t ra :1;
// unused
uint8_t z :1;
// response code
uint8_t rcode :4;
// entries in the question section; default is 1
uint16_t qdcount;
// resource records
uint16_t ancount;
// server resource records (in the authority section)
uint16_t nscount;
// resource records (in addl. section)
uint16_t arcount;
} dns_h;
header->qr = 0;
header->opcode = 0;
...
header->qdcount = htons(1);
...
And my sendto...
char buffer[sizeof(*header) * sizeof(*question) * 2];
int offset = 0;
memcpy(buffer, header, sizeof(*header));
offset += sizeof(*header);
memcpy(buffer + offset, question, sizeof(*question));
ssize_t sent = sendto(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)addr, sizeof(*addr));
What am I doing wrong? Is this the recommended way to send a struct over a socket? I've set most fields in the header to 0 and anything I've set to 1 I've used htons
Upvotes: 0
Views: 157
Reputation: 223872
Two problems with your header struct:
z
field is 3 bits, not 1. So the rcode
field is two bits left of where it should be. You don't show the code where you're creating the header, but make sure you use htons
when setting the fields so that the values are in network byte order.
Also, take a close look at the binary data in the packet in Wireshark. Compare that with the values you put in to see what's out of place.
Upvotes: 2