1 #include "hostsutils.h"
2 #include "dnsgenerator.h"
3 #include "mmgr.h"
4 #include "goodiplist.h"
5
HostsUtils_GetCName_Callback(int Number,HostsRecordType Type,const char * Data,char * Buffer)6 static int HostsUtils_GetCName_Callback(int Number,
7 HostsRecordType Type,
8 const char *Data,
9 char *Buffer
10 )
11 {
12 strcpy(Buffer, Data);
13 return 0;
14 }
15
HostsUtils_GetCName(const char * Domain,char * Buffer,HostsContainer * Container)16 int HostsUtils_GetCName(const char *Domain,
17 char *Buffer,
18 HostsContainer *Container
19 )
20 {
21 return Container->Find(Container,
22 Domain,
23 HOSTS_TYPE_CNAME,
24 (HostsFindFunc)HostsUtils_GetCName_Callback,
25 Buffer
26 )
27 == NULL;
28 }
29
HostsUtils_TypeExisting(HostsContainer * Container,const char * Domain,HostsRecordType Type)30 BOOL HostsUtils_TypeExisting(HostsContainer *Container,
31 const char *Domain,
32 HostsRecordType Type
33 )
34 {
35 return Container->Find(Container,
36 Domain,
37 Type,
38 NULL,
39 NULL
40 )
41 != NULL;
42 }
43
HostsUtils_Generate(int Number,HostsRecordType Type,const void * Data,DnsGenerator * g)44 static int HostsUtils_Generate(int Number,
45 HostsRecordType Type,
46 const void *Data,
47 DnsGenerator *g /* Inited */
48 )
49 {
50 switch( Type )
51 {
52 case HOSTS_TYPE_CNAME:
53 if( g->CName(g, "a", Data, 60) != 0 )
54 {
55 return -26;
56 }
57 break;
58
59 case HOSTS_TYPE_A:
60 if( g->RawData(g,
61 "a",
62 DNS_TYPE_A,
63 DNS_CLASS_IN,
64 Data,
65 4,
66 60
67 )
68 != 0 )
69 {
70 return -41;
71 }
72 break;
73
74 case HOSTS_TYPE_AAAA:
75 if( g->RawData(g,
76 "a",
77 DNS_TYPE_AAAA,
78 DNS_CLASS_IN,
79 Data,
80 16,
81 60
82 )
83 != 0 )
84 {
85 return -56;
86 }
87 break;
88
89 case HOSTS_TYPE_GOOD_IP_LIST:
90 {
91 const char *ActuallData;
92
93 ActuallData = GoodIpList_Get(Data);
94 if( ActuallData == NULL )
95 {
96 return -96;
97 }
98
99 if( g->RawData(g,
100 "a",
101 DNS_TYPE_A,
102 DNS_CLASS_IN,
103 ActuallData,
104 4,
105 60
106 )
107 != 0 )
108 {
109 return -109;
110 }
111 }
112 break;
113
114 default:
115 return -61;
116 break;
117 }
118
119 return 0;
120 }
121
HostsUtils_Try(IHeader * Header,int BufferLength,HostsContainer * Container)122 HostsUtilsTryResult HostsUtils_Try(IHeader *Header,
123 int BufferLength,
124 HostsContainer *Container
125 )
126 {
127 char *RequestEntity = (char *)(Header + 1);
128 const char *MatchState;
129 HostsRecordType Type;
130
131 if( Header->Type != DNS_TYPE_CNAME &&
132 HostsUtils_TypeExisting(Container, Header->Domain, HOSTS_TYPE_CNAME)
133 )
134 {
135 return HOSTSUTILS_TRY_RECURSED;
136 }
137
138 switch( Header->Type )
139 {
140 case DNS_TYPE_CNAME:
141 Type = HOSTS_TYPE_CNAME;
142 MatchState = Container->Find(Container,
143 Header->Domain,
144 HOSTS_TYPE_CNAME,
145 NULL,
146 NULL
147 );
148 break;
149
150 case DNS_TYPE_A:
151 MatchState = Container->Find(Container,
152 Header->Domain,
153 HOSTS_TYPE_A,
154 NULL,
155 NULL
156 );
157 if( MatchState != NULL )
158 {
159 Type = HOSTS_TYPE_A;
160 } else {
161 Type = HOSTS_TYPE_GOOD_IP_LIST;
162 MatchState = Container->Find(Container,
163 Header->Domain,
164 HOSTS_TYPE_GOOD_IP_LIST,
165 NULL,
166 NULL
167 );
168 }
169 break;
170
171 case DNS_TYPE_AAAA:
172 Type = HOSTS_TYPE_AAAA;
173 MatchState = Container->Find(Container,
174 Header->Domain,
175 HOSTS_TYPE_AAAA,
176 NULL,
177 NULL
178 );
179 break;
180
181 default:
182 return HOSTSUTILS_TRY_NONE;
183 break;
184 }
185
186 if( MatchState != NULL )
187 {
188 DnsGenerator g;
189
190 char *HereToGenerate = RequestEntity + Header->EntityLength;
191 int LeftBufferLength =
192 BufferLength - sizeof(IHeader) - Header->EntityLength;
193
194 int ResultLength;
195
196 if( DnsGenerator_Init(&g,
197 HereToGenerate,
198 LeftBufferLength,
199 RequestEntity,
200 Header->EntityLength,
201 TRUE
202 )
203 != 0)
204 {
205 return HOSTSUTILS_TRY_NONE;
206 }
207
208 g.Header->Flags.Direction = 1;
209 g.Header->Flags.AuthoritativeAnswer = 0;
210 g.Header->Flags.RecursionAvailable = 1;
211 g.Header->Flags.ResponseCode = 0;
212 g.Header->Flags.Type = 0;
213
214 if( g.NextPurpose(&g) != DNS_RECORD_PURPOSE_ANSWER )
215 {
216 return HOSTSUTILS_TRY_NONE;
217 }
218
219 if( Container->Find(Container,
220 Header->Domain,
221 Type,
222 (HostsFindFunc)HostsUtils_Generate,
223 &g
224 )
225 == NULL )
226 {
227 return HOSTSUTILS_TRY_NONE;
228 }
229
230 if( Header->EDNSEnabled )
231 {
232 while( g.NextPurpose(&g) != DNS_RECORD_PURPOSE_ADDITIONAL );
233 if( g.EDns(&g, 1280) != 0 )
234 {
235 return HOSTSUTILS_TRY_NONE;
236 }
237 }
238
239 /* g will no longer be needed, and can be crapped */
240 ResultLength = DNSCompress(HereToGenerate, g.Length(&g));
241 if( ResultLength < 0 )
242 {
243 return HOSTSUTILS_TRY_NONE;
244 }
245
246 Header->EntityLength = ResultLength;
247 memmove(RequestEntity, HereToGenerate, ResultLength);
248
249 IHeader_SendBack(Header);
250
251 return HOSTSUTILS_TRY_OK;
252 } else {
253 return HOSTSUTILS_TRY_NONE;
254 }
255 }
256
HostsUtils_Query(SOCKET Socket,Address_Type * BackAddress,int Identifier,const char * Name,DNSRecordType Type)257 int HostsUtils_Query(SOCKET Socket, /* Both for sending and receiving */
258 Address_Type *BackAddress,
259 int Identifier,
260 const char *Name,
261 DNSRecordType Type
262 )
263 {
264 static const char DNSHeader[DNS_HEADER_LENGTH] = {
265 00, 00, /* QueryIdentifier */
266 01, 00, /* Flags */
267 00, 00, /* QuestionCount */
268 00, 00, /* AnswerCount */
269 00, 00, /* NameServerCount */
270 00, 00, /* AdditionalCount */
271 };
272
273 char RequestBuffer[2048];
274 IHeader *Header = (IHeader *)RequestBuffer;
275 char *RequestEntity = RequestBuffer + sizeof(IHeader);
276
277 DnsGenerator g;
278
279 if( DnsGenerator_Init(&g,
280 RequestEntity,
281 sizeof(RequestBuffer) - sizeof(IHeader),
282 DNSHeader,
283 DNS_HEADER_LENGTH,
284 FALSE
285 )
286 != 0 )
287 {
288 return -323;
289 }
290
291 g.CopyIdentifier(&g, Identifier);
292
293 if( g.Question(&g, Name, Type, DNS_CLASS_IN) != 0 )
294 {
295 return -328;
296 }
297
298 if( IHeader_Fill(Header,
299 TRUE,
300 RequestEntity,
301 g.Length(&g),
302 (struct sockaddr *)&(BackAddress->Addr),
303 Socket,
304 BackAddress->family,
305 "CNameRedirect"
306 )
307 != 0 )
308 {
309 return -309;
310 }
311
312 return MMgr_Send(Header, sizeof(RequestBuffer));
313 }
314
315 /* Error code returned */
HostsUtils_CombineRecursedResponse(void * Buffer,int Bufferlength,char * RecursedEntity,int EntityLength,const char * RecursedDomain)316 int HostsUtils_CombineRecursedResponse(void *Buffer, /* Include IHeader */
317 int Bufferlength,
318 char *RecursedEntity,
319 int EntityLength,
320 const char *RecursedDomain
321 )
322 {
323 IHeader *NewHeader = (IHeader *)Buffer;
324 char *NewEntity = Buffer + sizeof(IHeader);
325
326 DnsSimpleParser p;
327 DnsSimpleParserIterator i;
328 DnsGenerator g;
329
330 uint16_t OriginalIdentifier = *(uint16_t *)NewEntity;
331
332 int CompressedLength;
333
334 if( DnsSimpleParser_Init(&p,
335 RecursedEntity,
336 EntityLength,
337 FALSE
338 ) != 0
339 )
340 {
341 return -268;
342 }
343
344 if( DnsSimpleParserIterator_Init(&i, &p) != 0 )
345 {
346 return -273;
347 }
348
349 if( DnsGenerator_Init(&g,
350 NewEntity,
351 Bufferlength - sizeof(IHeader),
352 NULL,
353 0,
354 FALSE
355 )
356 != 0 )
357 {
358 return -285;
359 }
360
361 g.CopyHeader(&g, RecursedEntity, FALSE);
362 g.CopyIdentifier(&g, OriginalIdentifier);
363
364 if( g.Question(&g,
365 NewHeader->Domain,
366 NewHeader->Type,
367 DNS_CLASS_IN
368 )
369 != 0 )
370 {
371 return -298;
372 }
373
374 if( g.NextPurpose(&g) != DNS_RECORD_PURPOSE_ANSWER )
375 {
376 return -303;
377 }
378
379 if( g.CName(&g, NewHeader->Domain, RecursedDomain, 60) != 0 )
380 {
381 return -309;
382 }
383
384 i.GotoAnswers(&i);
385
386 while( i.Next(&i) != NULL && i.Purpose == DNS_RECORD_PURPOSE_ANSWER )
387 {
388 switch( i.Type )
389 {
390 case DNS_TYPE_CNAME:
391 if( g.CopyCName(&g, &i) != 0 )
392 {
393 return -321;
394 }
395 break;
396
397 case DNS_TYPE_A:
398 if( g.CopyA(&g, &i) != 0 )
399 {
400 return -328;
401 }
402 break;
403
404 case DNS_TYPE_AAAA:
405 if( g.CopyAAAA(&g, &i) != 0 )
406 {
407 return -335;
408 }
409 break;
410
411 default:
412 break;
413 }
414 }
415
416 if( NewHeader->EDNSEnabled )
417 {
418 while( g.NextPurpose(&g) != DNS_RECORD_PURPOSE_ADDITIONAL );
419
420 if( g.EDns(&g, 1280) != 0 )
421 {
422 return -351;
423 }
424 }
425
426 CompressedLength = DNSCompress(g.Buffer, g.Length(&g));
427 if( CompressedLength < 0 )
428 {
429 return -343;
430 }
431
432 NewHeader->EntityLength = CompressedLength;
433
434 return 0;
435 }
436