问题
I am currently working on a school project which asks me to implement a DNS client, without using any library functions.
I have got to the point where i send a DNS request and Receive the Reply. I'm getting stuck at the parsing of the reply. I receive the reply in a char* array and i want to convert it into some meaningful structure, from which i can parse the answer. I went through the RFC and i read about the packet structure, but implementing it in C is giving me problems.
Can anyone give me any examples, in C, or maybe in any other language that explains how this is done. Or any reference to a book is also fine.
Additional Details:
So, the following are the structures that i'm using.
struct result{
int type;
struct res_ip_cname ip_cname;
struct res_error error;
struct res_mx_ns mx_ns;
};
struct res_ip_cname{
char* lst;
int sec;
char* auth_flag;
};
struct res_error{
char * info;
};
struct res_mx_ns{
char * name;
unsigned short pref;
int sec;
char* auth_flag;
};
I have a char* buffer[], where im storing the response the i receive from the server. And, i need to extract information from this buffer and populate the structure result.
Thanks, Chander
回答1:
Your structures don't look like anything I recognise from the RFCs (yes, I've written lots of DNS packet decoding software).
Look at RFC 1035 in particular - most of the structures you need can be mapped directly from the field layouts show therein.
For example, you need a header (see s4.1.1):
struct dns_header {
uint16_t query_id;
uint16_t flags;
uint16_t qdcount;
uint16_t ancount;
uint16_t nscount;
uint16_t arcount;
};
Don't forget to use ntohs()
to convert the wire format of these fields into your machine's native byte order. The network order is big-endian, and most machines these days are little-endian.
You'll need a "question" structure (see s4.1.2), and a generic "resource record" structure too (see s4.1.3).
Note however that the wire format of both of these starts with a variable length "label", which can also include compression pointers (see s4.1.4). This means that you can't in these cases trivially map the whole wire block onto a C structure.
Hope this helps...
回答2:
If I were you I'd be using wireshark (in combination with the RFC) to inspect the packet structure. Wireshark captures and displays the network packets flowing through your computer. It lets you see both the raw data you will be receiving, and the decoded packet structure.
For example, in the screenshot below you can see the IP address of chat.meta.stackoverflow.com
returned in a DNS Response packet, rendered in three different ways. Firstly, you can see a human readable version, in the middle pane of the screen. Secondly, the highlighted text in the lower left pane shows the raw DNS packet as a series of hexadecimal bytes. Thirdly, in the highlighted text in the lower left pane, you can see the packet rendered as ASCII text (in this case, mostly but not entirely, gobbledigook).

回答3:
The request format and response format are quite similar - both contain variable length fields, which I guess is what you're stuck on - but if you've managed to form a request properly, you shouldn't have too much trouble parsing the response. If you can post some more details, like where exactly you're stuck, we could help better.
回答4:
My advice is don't make a meal of it. Extract QDCOUNT
and ANCOUNT
from the header, then skip over the header, skip QDCOUNT
questions, and start parsing answers. Skipping a label is easy (just look for the first byte that's 0 or has the high bit set), but decoding one is a little bit more work (you need to follow and validate "pointers" and make sure you don't get stuck in a loop). If you're only looking up addresses (and not PTR
records) then you really never need to decode labels at all.
来源:https://stackoverflow.com/questions/4181504/dns-client-in-c