1 #ifndef _DNS_PARSER_H_
2 #define _DNS_PARSER_H_
3 
4 #include <limits.h>
5 #include "common.h"
6 #include "dnsrelated.h"
7 
8 #define GET_16_BIT_U_INT(ptr)	(ntohs(*(int16_t *)(ptr)))
9 #define GET_32_BIT_U_INT(ptr)		(ntohl(*(int32_t *)(ptr)))
10 #define GET_8_BIT_U_INT(ptr)		(*(unsigned char*)(ptr))
11 
12 #define DNS_HEADER_LENGTH	12
13 
14 /* Handle DNS header*/
15 #define DNSGetTCPLength(dns_over_tcp_ptr)	GET_16_BIT_U_INT(dns_over_tcp_ptr)
16 
17 #define DNSGetQueryIdentifier(dns_body)		GET_16_BIT_U_INT((char *)(dns_body))
18 
19 #define DNSGetFlags(dns_body)				GET_16_BIT_U_INT((char *)(dns_body) + 2)
20 
21 #define DNSGetQuestionCount(dns_body)		GET_16_BIT_U_INT((char *)(dns_body) + 4)
22 
23 #define DNSGetAnswerCount(dns_body)			GET_16_BIT_U_INT((char *)(dns_body) + 6)
24 
25 #define DNSGetNameServerCount(dns_body)		GET_16_BIT_U_INT((char *)(dns_body) + 8)
26 
27 #define DNSGetAdditionalCount(dns_body)		GET_16_BIT_U_INT((char *)(dns_body) + 10)
28 
29 #define DNSJumpHeader(dns_body)				((char *)(dns_body) + DNS_HEADER_LENGTH)
30 
31 #define DNSGetTTL(ans_start_ptr)				GET_32_BIT_U_INT(DNSJumpOverName(ans_start_ptr) + 4)
32 
33 #define DNSGetResourceDataLength(ans_start_ptr)	GET_16_BIT_U_INT(DNSJumpOverName(ans_start_ptr) + 8)
34 
35 #define DNSGetResourceDataPos(ans_start_ptr)	(DNSJumpOverName((char *)(ans_start_ptr)) + 10)
36 
37 /* Common */
38 char *DNSJumpOverName(char *NameStart);
39 
40 int DNSGetHostName(const char *DNSBody, int DNSBodyLength, const char *NameStart, char *buffer, int BufferLength);
41 
42 int DNSGetHostNameLength(const char *DNSBody, int DNSBodyLength, const char *NameStart);
43 
44 #define DNSGetRecordType(rec_start_ptr)		((rec_start_ptr) == NULL ? DNS_TYPE_UNKNOWN : GET_16_BIT_U_INT(DNSJumpOverName(rec_start_ptr)))
45 
46 #define DNSIsLabelPointerStart(num)			(((num) & 0xC0) == 0xC0)
47 
48 #define DNSLabelGetPointer(rec_start_ptr)	((rec_start_ptr) == NULL ? 0 : (int)((unsigned char *)(rec_start_ptr))[1] + (int)(((unsigned char *)(rec_start_ptr))[0] - 192) * 256)
49 
50 #define DNSGetRecordClass(rec_start_ptr)	((rec_start_ptr) == NULL ? DNS_CLASS_UNKNOWN : GET_16_BIT_U_INT(DNSJumpOverName(rec_start_ptr) + 2))
51 
52 #ifdef HOST_BIG_ENDIAN
53 /* DNSMessageFlags, at 2-byte offset of a DNS header, is 2 bytes length.
54  * https://tools.ietf.org/html/rfc6895
55  */
56 typedef struct _DNSMessageProperties{
57 	uint16_t	Direction	:	1; /* query (0), or response (1) */
58 
59 	/* Type:
60 	 * 0	a standard query (QUERY).
61 	 * 1	an inverse query (IQUERY).
62 	 * 2	a server status request (STATUS).
63 	 * 3-15	reserved for future use  */
64 	uint16_t Type			:	4;
65 
66 	uint16_t	AuthoritativeAnswer:1;
67 
68 	uint16_t	TrunCation		:	1;
69 
70 	uint16_t	RecursionDesired:	1; /* 0 no, 1 yes */
71 
72 	uint16_t	RecursionAvailable:	1; /* 0 no, 1 yes */
73 
74 	uint16_t	Unused			:	1;
75 
76 	uint16_t AuthenticData	:	1;
77 
78 	uint16_t CheckingDisabled:	1;
79 
80 	/* ResponseCode:
81 	 * 0	No error condition.
82 	 * 1	Format error - The name server was unable to interpret the query.
83 	 * 2	Server failure - The name server was unable to process this query due to a problem with the name server.
84 	 * 3	Name Error - Meaningful only for responses from an authoritative name server, this code signifies that the domain name referenced in the query does not exist.
85 	 * 4	Not Implemented - The name server does not support the requested kind of query.
86 	 * 5	Refused - The name server refuses to perform the specified operation for policy reasons. For example, a name server may not wish to provide the information to the particular requester, or a name server may not wish to perform a particular operation (e.g., zone transfer) for particular data.
87 	 * 6-15	Reserved for future use. */
88 	uint16_t	ResponseCode	:	4;
89 
90 }DNSFlags;
91 #else
92 typedef struct _DNSMessageProperties{
93 	uint16_t	RecursionDesired:	1; /* 0 no, 1 yes */
94 
95 	uint16_t	TrunCation		:	1;
96 
97 	uint16_t	AuthoritativeAnswer:1;
98 
99 	/* Type:
100 	 * 0	a standard query (QUERY).
101 	 * 1	an inverse query (IQUERY).
102 	 * 2	a server status request (STATUS).
103 	 * 3-15	reserved for future use  */
104 	uint16_t Type			:	4;
105 
106 	uint16_t	Direction	:	1; /* query (0), or response (1) */
107 
108 
109 	/* ResponseCode:
110 	 * 0	No error condition.
111 	 * 1	Format error - The name server was unable to interpret the query.
112 	 * 2	Server failure - The name server was unable to process this query due to a problem with the name server.
113 	 * 3	Name Error - Meaningful only for responses from an authoritative name server, this code signifies that the domain name referenced in the query does not exist.
114 	 * 4	Not Implemented - The name server does not support the requested kind of query.
115 	 * 5	Refused - The name server refuses to perform the specified operation for policy reasons. For example, a name server may not wish to provide the information to the particular requester, or a name server may not wish to perform a particular operation (e.g., zone transfer) for particular data.
116 	 * 6-15	Reserved for future use. */
117 	uint16_t	ResponseCode	:	4;
118 
119 	uint16_t CheckingDisabled:	1;
120 
121 	uint16_t AuthenticData	:	1;
122 
123 	uint16_t	Unused			:	1;
124 
125 	uint16_t	RecursionAvailable:	1; /* 0 no, 1 yes */
126 
127 }DNSFlags;
128 #endif
129 
130 typedef struct _DNSHeader{
131 	uint16_t		Identifier;
132 	DNSFlags		Flags;
133 	uint16_t		QuestionCount;
134 	uint16_t		AnswerCount;
135 	uint16_t		NameServerCount;
136 	uint16_t		AdditionalCount;
137 }DNSHeader;
138 
139 #define DNSGetHeader(dns_body_ptr)	((DNSHeader *)(dns_body_ptr))
140 
141 /* Convert a DNS message to text */
142 char *GetAllAnswers(char *DNSBody, int DNSBodyLength, char *Buffer, int BufferLength);
143 
144 int DNSCopyLable(const char *DNSBody, char *here, const char *src);
145 
146 /**
147   New Implementation
148 */
149 
150 typedef enum _DnsDirection{
151     DNS_DIRECTION_QUERY = 0,
152     DNS_DIRECTION_RESPONSE = 1,
153 } DnsDirection;
154 
155 typedef enum _DnsOperation{
156     DNS_OPERATION_QUERY = 0,
157     DNS_OPERATION_IQUERY = 1,
158     DNS_OPERATION_STATUS = 2,
159 } DnsOperation;
160 
161 typedef enum _ResponseCode{
162     RESPONSE_CODE_NO_ERROR = 0,
163     RESPONSE_CODE_FORMAT_ERROR = 1,
164     RESPONSE_CODE_SERVER_FAILURE = 2,
165     RESPONSE_CODE_NAME_ERROR = 3,
166     RESPONSE_CODE_NOT_IMPLEMENTED = 4,
167     RESPONSE_CODE_REFUSED = 5,
168 } ResponseCode;
169 
170 typedef enum _DnsRecordPurpose{
171     /* Their values are not important */
172     DNS_RECORD_PURPOSE_UNKNOWN = 0,
173     DNS_RECORD_PURPOSE_QUESTION,
174     DNS_RECORD_PURPOSE_ANSWER,
175     DNS_RECORD_PURPOSE_NAME_SERVER,
176     DNS_RECORD_PURPOSE_ADDITIONAL,
177 } DnsRecordPurpose;
178 
179 typedef struct _DnsSimpleParser DnsSimpleParser;
180 
181 struct _DnsSimpleParser{
182     /* public, but don't modify outside, unless you know what are you doing */
183     char *RawDns;
184     int  RawDnsLength;
185 
186     struct {
187         /* private */
188         const DNSFlags    *Flags;
189 
190         /* public */
191         DnsDirection    (*Direction)(DnsSimpleParser *p);
192         DnsOperation    (*Operation)(DnsSimpleParser *p);
193         BOOL            (*IsAuthoritative)(DnsSimpleParser *p);
194         BOOL            (*Truncated)(DnsSimpleParser *p);
195         BOOL            (*RecursionDesired)(DnsSimpleParser *p);
196         BOOL            (*RecursionAvailable)(DnsSimpleParser *p);
197         ResponseCode    (*ResponseCode)(DnsSimpleParser *p);
198     } _Flags;
199 
200     /* public */
201     uint16_t    (*QueryIdentifier)(DnsSimpleParser *p);
202     int         (*QuestionCount)(DnsSimpleParser *p);
203     int         (*AnswerCount)(DnsSimpleParser *p);
204     int         (*NameServerCount)(DnsSimpleParser *p);
205     int         (*AdditionalCount)(DnsSimpleParser *p);
206 
207     BOOL        (*HasType)(DnsSimpleParser *p,
208                            DnsRecordPurpose Purpose,
209                            DNSRecordClass Klass,
210                            DNSRecordType Type
211                            );
212 };
213 
214 int DnsSimpleParser_Init(DnsSimpleParser *p,
215                          char *RawDns,
216                          int Length,
217                          BOOL IsTcp);
218 
219 /**
220   Iterator
221 */
222 typedef struct _DnsSimpleParserIterator DnsSimpleParserIterator;
223 
224 struct _DnsSimpleParserIterator{
225     /* public, but don't modify outside */
226     DnsSimpleParser *Parser;
227 
228     /* private */
229     char        *CurrentPosition;
230     int         RecordPosition; /* Starts at 1 */
231 
232     int         QuestionFirst; /* Starts at 1; 0 means no such record */
233     int         QuestionLast;
234 
235     int         AnswerFirst; /* Starts at 1; 0 means no such record */
236     int         AnswerLast;
237 
238     int         NameServerFirst; /* Starts at 1; 0 means no such record */
239     int         NameServerLast;
240 
241     int         AdditionalFirst; /* Starts at 1; 0 means no such record */
242     int         AdditionalLast;
243 
244     int         AllRecordCount;
245 
246     /* public, but don't modify outside */
247     /* Current record informations */
248     DnsRecordPurpose    Purpose;
249     DNSRecordType       Type;
250     DNSRecordClass      Klass;
251     int                 DataLength;
252 
253     char *(*Next)(DnsSimpleParserIterator *i);
254     void (*GotoAnswers)(DnsSimpleParserIterator *i);
255     int (*GetName)(DnsSimpleParserIterator *i,
256                    char *Buffer, /* Could be NULL */
257                    int BufferLength
258                    );
259     int (*GetNameLength)(DnsSimpleParserIterator *i);
260     char *(*RowData)(DnsSimpleParserIterator *i);
261     int (*TextifyData)(DnsSimpleParserIterator *i,
262                        const char *Format, /* "%t:%v\n" */
263                        char *Buffer,
264                        int BufferLength
265                        );
266 
267     uint32_t (*GetTTL)(DnsSimpleParserIterator *i);
268 };
269 
270 int DnsSimpleParserIterator_Init(DnsSimpleParserIterator *i,
271                                  DnsSimpleParser *p
272                                  );
273 
274 #endif /* _DNS_PARSER_H_ */
275