1 #include "dnsparser.h"
2 #include "dnsgenerator.h"
3 #include "utils.h"
4
DNSJumpOverName(char * NameStart)5 char *DNSJumpOverName(char *NameStart)
6 {
7 return NameStart + DNSGetHostName(NULL, INT_MAX, NameStart, NULL, 0);
8 }
9
10 /* Labels length returned */
DNSGetHostName(const char * DNSBody,int DNSBodyLength,const char * NameStart,char * buffer,int BufferLength)11 int DNSGetHostName(const char *DNSBody, int DNSBodyLength, const char *NameStart, char *buffer, int BufferLength)
12 {
13 char *BufferItr = buffer;
14 const char *NameItr = NameStart;
15 int LabelsLength = 0;
16 BOOL Redirected = FALSE;
17 int LabelCount = GET_8_BIT_U_INT(NameItr); /* The amount of characters of the next label */
18 while( LabelCount != 0 )
19 {
20 if( DNSIsLabelPointerStart(LabelCount) )
21 {
22 int LabelPointer = 0;
23 if( Redirected == FALSE )
24 {
25 LabelsLength += 2;
26 Redirected = TRUE;
27 }
28 if( buffer == NULL )
29 {
30 break;
31 }
32 LabelPointer = DNSLabelGetPointer(NameItr);
33 if( LabelPointer > DNSBodyLength )
34 {
35 return -1;
36 }
37 NameItr = DNSBody + DNSLabelGetPointer(NameItr);
38 } else {
39 if( DNSBody != NULL &&
40 NameItr + LabelCount > DNSBody + DNSBodyLength
41 )
42 {
43 return -1;
44 }
45
46 if( buffer != NULL )
47 {
48 if( BufferItr + LabelCount + 1 - buffer <= BufferLength )
49 {
50 memcpy(BufferItr, NameItr + 1, LabelCount);
51 } else {
52 if( BufferItr == buffer )
53 {
54 if( BufferLength > 0 )
55 {
56 *BufferItr = '\0';
57 }
58 } else {
59 *(BufferItr - 1) = '\0';
60 }
61 return -1;
62 }
63 }
64
65 if( Redirected == FALSE )
66 {
67 LabelsLength += (LabelCount + 1);
68 }
69 NameItr += (1 + LabelCount);
70 if( buffer != NULL )
71 {
72 BufferItr += LabelCount;
73 *BufferItr = '.';
74 ++BufferItr;
75 }
76 }
77
78 LabelCount = GET_8_BIT_U_INT(NameItr);
79 }
80
81 if( buffer != NULL )
82 {
83 if( BufferItr == buffer )
84 {
85 if( BufferLength > 0 )
86 {
87 *BufferItr = '\0';
88 } else {
89 return -1;
90 }
91 } else {
92 *(BufferItr - 1) = '\0';
93 }
94 }
95
96 if( Redirected == FALSE )
97 {
98 ++LabelsLength;
99 }
100
101 return LabelsLength;
102 }
103
104 /* including terminated-zero */
DNSGetHostNameLength(const char * DNSBody,int DNSBodyLength,const char * NameStart)105 int DNSGetHostNameLength(const char *DNSBody, int DNSBodyLength, const char *NameStart)
106 {
107 const char *NameItr = NameStart;
108 int NameLength = 0;
109 int LabelCount = GET_8_BIT_U_INT(NameItr); /* The amount of characters of the next label */
110 while( LabelCount != 0 )
111 {
112 if( DNSIsLabelPointerStart(LabelCount) )
113 {
114 if( DNSLabelGetPointer(NameItr) > DNSBodyLength )
115 {
116 return INT_MAX; /* Error detected */
117 }
118 NameItr = DNSBody + DNSLabelGetPointer(NameItr);
119 } else {
120 if( NameItr + LabelCount > DNSBody + DNSBodyLength )
121 {
122 return INT_MAX; /* Error detected */
123 }
124 NameLength += (LabelCount + 1);
125 NameItr += (1 + LabelCount);
126 }
127
128 LabelCount = GET_8_BIT_U_INT(NameItr);
129
130 if( NameLength > DNSBodyLength )
131 {
132 return INT_MAX; /* Error detected */
133 }
134 }
135
136 if( NameLength == 0 )
137 {
138 return 1;
139 } else {
140 return NameLength;
141 }
142 }
143
GetAllAnswers(char * DNSBody,int DNSBodyLength,char * Buffer,int BufferLength)144 char *GetAllAnswers(char *DNSBody, int DNSBodyLength, char *Buffer, int BufferLength)
145 {
146 DnsSimpleParser p;
147 DnsSimpleParserIterator i;
148 int ANACount;
149
150 static const char *Tail = " And More ...\n";
151 char *BufferItr = Buffer;
152 int BufferLeft = BufferLength - strlen(Tail);
153
154 if( BufferLeft <= 0 )
155 {
156 return NULL;
157 }
158
159 if( DnsSimpleParser_Init(&p, DNSBody, DNSBodyLength, FALSE) != 0 )
160 {
161 return NULL;
162 }
163
164 if( DnsSimpleParserIterator_Init(&i, &p) != 0 )
165 {
166 return NULL;
167 }
168
169 ANACount = p.AnswerCount(&p) + p.NameServerCount(&p) + p.AdditionalCount(&p);
170
171 if( ANACount == 0 )
172 {
173 strcpy(BufferItr, " Nothing.\n");
174 }
175
176 i.GotoAnswers(&i);
177
178 while( i.Next(&i) != NULL &&
179 i.Purpose != DNS_RECORD_PURPOSE_QUESTION &&
180 i.Purpose != DNS_RECORD_PURPOSE_UNKNOWN
181 )
182 {
183 if( i.TextifyData(&i, " %t:%v\n", BufferItr, BufferLeft) == 0 )
184 {
185 sprintf(BufferItr, " And %d More ...\n", ANACount);
186
187 break;
188 } else {
189 int StageLength = strlen(BufferItr);
190
191 BufferItr += StageLength;
192 BufferLeft -= StageLength;
193
194 --ANACount;
195 }
196 }
197
198 return Buffer;
199 }
200
201 /* Full label length returned, including terminated-zero */
DNSCopyLable(const char * DNSBody,char * here,const char * src)202 int DNSCopyLable(const char *DNSBody, char *here, const char *src)
203 {
204 int FullLength = 0;
205
206 while( TRUE )
207 {
208 if( DNSIsLabelPointerStart(GET_8_BIT_U_INT(src)) )
209 {
210 src = DNSBody + DNSLabelGetPointer(src);
211 } else {
212 ++FullLength;
213
214 if( here != NULL )
215 {
216 *here = *src;
217 ++here;
218 }
219
220 if( *src == '\0' )
221 {
222 break;
223 }
224
225 ++src;
226 }
227 }
228
229 return FullLength;
230 }
231
232 /**
233 New Implementation
234 */
235
236 /* Converted to host byte order */
DnsSimpleParser_QueryIdentifier(DnsSimpleParser * p)237 static uint16_t DnsSimpleParser_QueryIdentifier(DnsSimpleParser *p)
238 {
239 return DNSGetQueryIdentifier(p->RawDns);
240 }
241
DnsSimpleParser_Flags_Direction(DnsSimpleParser * p)242 static DnsDirection DnsSimpleParser_Flags_Direction(DnsSimpleParser *p)
243 {
244 return (DnsDirection)(p->_Flags.Flags->Direction);
245 }
246
DnsSimpleParser_Flags_Operation(DnsSimpleParser * p)247 static DnsOperation DnsSimpleParser_Flags_Operation(DnsSimpleParser *p)
248 {
249 return (DnsOperation)(p->_Flags.Flags->Type);
250 }
251
DnsSimpleParser_Flags_IsAuthoritative(DnsSimpleParser * p)252 static BOOL DnsSimpleParser_Flags_IsAuthoritative(DnsSimpleParser *p)
253 {
254 return !!(p->_Flags.Flags->AuthoritativeAnswer);
255 }
256
DnsSimpleParser_Flags_Truncated(DnsSimpleParser * p)257 static BOOL DnsSimpleParser_Flags_Truncated(DnsSimpleParser *p)
258 {
259 return !!(p->_Flags.Flags->TrunCation);
260 }
261
DnsSimpleParser_Flags_RecursionDesired(DnsSimpleParser * p)262 static BOOL DnsSimpleParser_Flags_RecursionDesired(DnsSimpleParser *p)
263 {
264 return !!(p->_Flags.Flags->RecursionDesired);
265 }
266
DnsSimpleParser_Flags_RecursionAvailable(DnsSimpleParser * p)267 static BOOL DnsSimpleParser_Flags_RecursionAvailable(DnsSimpleParser *p)
268 {
269 return !!(p->_Flags.Flags->RecursionAvailable);
270 }
271
DnsSimpleParser_Flags_ResponseCode(DnsSimpleParser * p)272 static ResponseCode DnsSimpleParser_Flags_ResponseCode(DnsSimpleParser *p)
273 {
274 return (ResponseCode)(p->_Flags.Flags->ResponseCode);
275 }
276
DnsSimpleParser_QuestionCount(DnsSimpleParser * p)277 static int DnsSimpleParser_QuestionCount(DnsSimpleParser *p)
278 {
279 return DNSGetQuestionCount(p->RawDns);
280 }
281
DnsSimpleParser_AnswerCount(DnsSimpleParser * p)282 static int DnsSimpleParser_AnswerCount(DnsSimpleParser *p)
283 {
284 return DNSGetAnswerCount(p->RawDns);
285 }
286
DnsSimpleParser_NameServerCount(DnsSimpleParser * p)287 static int DnsSimpleParser_NameServerCount(DnsSimpleParser *p)
288 {
289 return DNSGetNameServerCount(p->RawDns);
290 }
291
DnsSimpleParser_AdditionalCount(DnsSimpleParser * p)292 static int DnsSimpleParser_AdditionalCount(DnsSimpleParser *p)
293 {
294 return DNSGetAdditionalCount(p->RawDns);
295 }
296
DnsSimpleParser_HasType(DnsSimpleParser * p,DnsRecordPurpose Purpose,DNSRecordClass Klass,DNSRecordType Type)297 static BOOL DnsSimpleParser_HasType(DnsSimpleParser *p,
298 DnsRecordPurpose Purpose,
299 DNSRecordClass Klass,
300 DNSRecordType Type
301 )
302 {
303 DnsSimpleParserIterator i;
304
305 if( DnsSimpleParserIterator_Init(&i, p) != 0 )
306 {
307 return FALSE;
308 }
309
310 while( i.Next(&i) != NULL )
311 {
312 if( (Purpose == DNS_RECORD_PURPOSE_UNKNOWN || i.Purpose == Purpose) &&
313 (Klass == DNS_CLASS_UNKNOWN || i.Klass == Klass) &&
314 i.Type == Type
315 )
316 {
317 return TRUE;
318 }
319 }
320
321 return FALSE;
322 }
323
DnsSimpleParser_Init(DnsSimpleParser * p,char * RawDns,int Length,BOOL IsTcp)324 int DnsSimpleParser_Init(DnsSimpleParser *p,
325 char *RawDns,
326 int Length,
327 BOOL IsTcp)
328 {
329 if( RawDns == NULL || Length < DNS_HEADER_LENGTH )
330 {
331 return -1;
332 }
333
334 if( IsTcp )
335 {
336 p->RawDns = RawDns + 2;
337 p->RawDnsLength = Length - 2;
338 } else {
339 p->RawDns = RawDns;
340 p->RawDnsLength = Length;
341 }
342
343 p->_Flags.Flags = (DNSFlags *)(p->RawDns + 2);
344
345 p->QueryIdentifier = DnsSimpleParser_QueryIdentifier;
346
347 p->_Flags.Direction = DnsSimpleParser_Flags_Direction;
348 p->_Flags.Operation = DnsSimpleParser_Flags_Operation;
349 p->_Flags.IsAuthoritative = DnsSimpleParser_Flags_IsAuthoritative;
350 p->_Flags.Truncated = DnsSimpleParser_Flags_Truncated;
351 p->_Flags.RecursionDesired = DnsSimpleParser_Flags_RecursionDesired;
352 p->_Flags.RecursionAvailable = DnsSimpleParser_Flags_RecursionAvailable;
353 p->_Flags.ResponseCode = DnsSimpleParser_Flags_ResponseCode;
354
355 p->QuestionCount = DnsSimpleParser_QuestionCount;
356 p->AnswerCount = DnsSimpleParser_AnswerCount;
357 p->NameServerCount = DnsSimpleParser_NameServerCount;
358 p->AdditionalCount = DnsSimpleParser_AdditionalCount;
359 p->HasType = DnsSimpleParser_HasType;
360
361 return 0;
362 }
363
364 /**
365 Iterator
366 */
DnsSimpleParserIterator_DeterminePurpose(DnsSimpleParserIterator * i,int RecordPosition)367 static DnsRecordPurpose DnsSimpleParserIterator_DeterminePurpose(
368 DnsSimpleParserIterator *i,
369 int RecordPosition)
370 {
371 if( i->QuestionFirst != 0 &&
372 RecordPosition >= i->QuestionFirst &&
373 RecordPosition <= i->QuestionLast
374 )
375 {
376 return DNS_RECORD_PURPOSE_QUESTION;
377 }
378
379 if( i->AnswerFirst != 0 &&
380 RecordPosition >= i->AnswerFirst &&
381 RecordPosition <= i->AnswerLast
382 )
383 {
384 return DNS_RECORD_PURPOSE_ANSWER;
385 }
386
387 if( i->NameServerFirst != 0 &&
388 RecordPosition >= i->NameServerFirst &&
389 RecordPosition <= i->NameServerLast
390 )
391 {
392 return DNS_RECORD_PURPOSE_NAME_SERVER;
393 }
394
395 if( i->AdditionalFirst != 0 &&
396 RecordPosition >= i->AdditionalFirst &&
397 RecordPosition <= i->AdditionalLast
398 )
399 {
400 return DNS_RECORD_PURPOSE_ADDITIONAL;
401 }
402
403 return DNS_RECORD_PURPOSE_UNKNOWN;
404 }
405
DnsSimpleParserIterator_Next(DnsSimpleParserIterator * i)406 static char *DnsSimpleParserIterator_Next(DnsSimpleParserIterator *i)
407 {
408 if( i->CurrentPosition == NULL )
409 {
410 i->CurrentPosition = i->Parser->RawDns + DNS_HEADER_LENGTH;
411 i->RecordPosition = 1;
412 } else if( i->RecordPosition < i->AllRecordCount ){
413 /* The record length excluding its labeled name at the beginning. */
414 int ExLength = i->Purpose == DNS_RECORD_PURPOSE_QUESTION ?
415 /* For a question record, there are only 4 bytes */
416 4 :
417 /* For an other types of record, there are many things */
418 10 + i->DataLength;
419
420 /* The length of all labels in the beginning of current record
421 plus `ExLength'
422 */
423
424 int FullLength = DNSGetHostName(NULL,
425 INT_MAX,
426 i->CurrentPosition,
427 NULL,
428 0)
429 + ExLength;
430
431 if( FullLength < ExLength )
432 {
433 return NULL;
434 }
435
436 i->CurrentPosition += FullLength;
437
438 i->RecordPosition += 1;
439 } else {
440 i->CurrentPosition = NULL;
441 i->RecordPosition = 0;
442 return NULL;
443 }
444
445 if( (i->RecordPosition > i->AllRecordCount) ||
446 (i->CurrentPosition - i->Parser->RawDns > i->Parser->RawDnsLength)
447 )
448 {
449 i->CurrentPosition = NULL;
450 i->RecordPosition = 0;
451 return NULL;
452 }
453
454 /* Update record informations */
455 i->Purpose = DnsSimpleParserIterator_DeterminePurpose(i, i->RecordPosition);
456 i->Type = DNSGetRecordType(i->CurrentPosition);
457 i->Klass = DNSGetRecordClass(i->CurrentPosition);
458
459 if( i->Purpose != DNS_RECORD_PURPOSE_UNKNOWN &&
460 i->Type != DNS_TYPE_UNKNOWN &&
461 i->Klass != DNS_CLASS_UNKNOWN
462 )
463 {
464 if( i->Purpose != DNS_RECORD_PURPOSE_QUESTION )
465 {
466 i->DataLength = DNSGetResourceDataLength(i->CurrentPosition);
467 }
468
469 return i->CurrentPosition;
470 } else {
471 i->CurrentPosition = NULL;
472 i->RecordPosition = 0;
473 return NULL;
474 }
475 }
476
DnsSimpleParserIterator_GotoAnswers(DnsSimpleParserIterator * i)477 static void DnsSimpleParserIterator_GotoAnswers(DnsSimpleParserIterator *i)
478 {
479 i->CurrentPosition = NULL;
480
481 if( i->QuestionFirst > 0 )
482 {
483 while( DnsSimpleParserIterator_Next(i) != NULL )
484 {
485 if( i->RecordPosition == i->QuestionLast )
486 {
487 break;
488 }
489 }
490 }
491 }
492
DnsSimpleParserIterator_GetName(DnsSimpleParserIterator * i,char * Buffer,int BufferLength)493 static int DnsSimpleParserIterator_GetName(DnsSimpleParserIterator *i,
494 char *Buffer, /* Could be NULL */
495 int BufferLength
496 )
497 {
498 return DNSGetHostName(i->Parser->RawDns,
499 i->Parser->RawDnsLength,
500 i->CurrentPosition,
501 Buffer,
502 BufferLength
503 );
504 }
505
DnsSimpleParserIterator_GetNameLength(DnsSimpleParserIterator * i)506 static int DnsSimpleParserIterator_GetNameLength(DnsSimpleParserIterator *i)
507 {
508 return DNSGetHostNameLength(i->Parser->RawDns,
509 i->Parser->RawDnsLength,
510 i->CurrentPosition
511 );
512 }
513
DnsSimpleParserIterator_RowData(DnsSimpleParserIterator * i)514 static char *DnsSimpleParserIterator_RowData(DnsSimpleParserIterator *i)
515 {
516 if( i->Purpose != DNS_RECORD_PURPOSE_QUESTION )
517 {
518 return DNSGetResourceDataPos(i->CurrentPosition);
519 } else {
520 return NULL;
521 }
522 }
523
524 /* Number of items generated returned */
DnsSimpleParserIterator_ParseIPv4(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength,const char * Text,int * AcutalDataLength)525 static int DnsSimpleParserIterator_ParseIPv4(DnsSimpleParserIterator *i,
526 const char *Data,
527 int DataLength,
528 const char *Format, /* "%t:%v\n" */
529 char *Buffer,
530 int BufferLength,
531 const char *Text,
532 int *AcutalDataLength
533 )
534 {
535 char Example[LENGTH_OF_IPV4_ADDRESS_ASCII];
536
537 if( DataLength < 4 || strlen(Format) + 1 > BufferLength )
538 {
539 return 0;
540 }
541
542 if( Text == NULL )
543 {
544 Text = "";
545 }
546
547 strcpy(Buffer, Format);
548
549 if( ReplaceStr_WithLengthChecking(Buffer,
550 "%t",
551 Text,
552 BufferLength
553 )
554 == NULL )
555 {
556 *Buffer = '\0';
557 return 0;
558 }
559
560 IPv4AddressToAsc(Data, Example);
561
562 if( ReplaceStr_WithLengthChecking(Buffer,
563 "%v",
564 Example,
565 BufferLength
566 )
567 == NULL )
568 {
569 *Buffer = '\0';
570 return 0;
571 }
572
573 if( AcutalDataLength != NULL )
574 {
575 *AcutalDataLength = 4;
576 }
577
578 return 1;
579 }
580
DnsSimpleParserIterator_ParseA(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength)581 static int DnsSimpleParserIterator_ParseA(DnsSimpleParserIterator *i,
582 const char *Data,
583 int DataLength,
584 const char *Format, /* "%t:%v\n" */
585 char *Buffer,
586 int BufferLength
587 )
588 {
589 return DnsSimpleParserIterator_ParseIPv4(i,
590 Data,
591 DataLength,
592 Format,
593 Buffer,
594 BufferLength,
595 "IPv4 Address",
596 NULL
597 );
598 }
599
DnsSimpleParserIterator_ParseIPv6(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength,const char * Text,int * AcutalDataLength)600 static int DnsSimpleParserIterator_ParseIPv6(DnsSimpleParserIterator *i,
601 const char *Data,
602 int DataLength,
603 const char *Format, /* "%t:%v\n" */
604 char *Buffer,
605 int BufferLength,
606 const char *Text,
607 int *AcutalDataLength
608 )
609 {
610 char Example[LENGTH_OF_IPV6_ADDRESS_ASCII];
611
612 if( DataLength < 16 || strlen(Format) + 1 > BufferLength )
613 {
614 return 0;
615 }
616
617 if( Text == NULL )
618 {
619 Text = "";
620 }
621
622 strcpy(Buffer, Format);
623
624 if( ReplaceStr_WithLengthChecking(Buffer,
625 "%t",
626 Text,
627 BufferLength
628 )
629 == NULL )
630 {
631 *Buffer = '\0';
632 return 0;
633 }
634
635 IPv6AddressToAsc(Data, Example);
636
637 if( ReplaceStr_WithLengthChecking(Buffer,
638 "%v",
639 Example,
640 BufferLength
641 )
642 == NULL )
643 {
644 *Buffer = '\0';
645 return 0;
646 }
647
648 if( AcutalDataLength != NULL )
649 {
650 *AcutalDataLength = 16;
651 }
652
653 return 1;
654 }
655
DnsSimpleParserIterator_ParseAAAA(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength)656 static int DnsSimpleParserIterator_ParseAAAA(DnsSimpleParserIterator *i,
657 const char *Data,
658 int DataLength,
659 const char *Format, /* "%t:%v\n" */
660 char *Buffer,
661 int BufferLength
662 )
663 {
664 return DnsSimpleParserIterator_ParseIPv6(i,
665 Data,
666 DataLength,
667 Format,
668 Buffer,
669 BufferLength,
670 "IPv6 Address",
671 NULL
672 );
673 }
674
DnsSimpleParserIterator_ParseLabeledName(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength,const char * Text,int * AcutalDataLength)675 static int DnsSimpleParserIterator_ParseLabeledName(DnsSimpleParserIterator *i,
676 const char *Data,
677 int DataLength,
678 const char *Format, /* "%t:%v\n" */
679 char *Buffer,
680 int BufferLength,
681 const char *Text,
682 int *AcutalDataLength
683 )
684 {
685 /* Static max length assumed to be 127+1 */
686 char Example[128];
687 char *Resulting;
688
689 int HostNameLength; /* Including terminated-zero */
690 int LabelLength;
691
692 if( strlen(Format) + 1 > BufferLength )
693 {
694 return 0;
695 }
696
697 if( Text == NULL )
698 {
699 Text = "";
700 }
701
702 strcpy(Buffer, Format);
703
704 if( ReplaceStr_WithLengthChecking(Buffer,
705 "%t",
706 Text,
707 BufferLength
708 )
709 == NULL )
710 {
711 *Buffer = '\0';
712 return 0;
713 }
714
715 HostNameLength = DNSGetHostNameLength(i->Parser->RawDns,
716 i->Parser->RawDnsLength,
717 Data
718 );
719
720 if( HostNameLength == INT_MAX )
721 {
722 *Buffer = '\0';
723 return 0;
724 }
725
726 if( HostNameLength > sizeof(Example) )
727 {
728 Resulting = SafeMalloc(HostNameLength);
729 } else {
730 Resulting = Example;
731 }
732
733 LabelLength = DNSGetHostName(i->Parser->RawDns,
734 i->Parser->RawDnsLength,
735 Data,
736 Resulting,
737 HostNameLength
738 );
739
740 if( LabelLength < 0 )
741 {
742 if( Resulting != Example )
743 {
744 SafeFree(Resulting);
745 }
746
747 *Buffer = '\0';
748 return 0;
749 }
750
751 if( ReplaceStr_WithLengthChecking(Buffer,
752 "%v",
753 Resulting,
754 BufferLength
755 )
756 == NULL )
757 {
758 if( Resulting != Example )
759 {
760 SafeFree(Resulting);
761 }
762
763 *Buffer = '\0';
764 return 0;
765 }
766
767 if( Resulting != Example )
768 {
769 SafeFree(Resulting);
770 }
771
772 if( AcutalDataLength != NULL )
773 {
774 *AcutalDataLength = LabelLength;
775 }
776
777 return 1;
778 }
779
DnsSimpleParserIterator_ParseCName(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength)780 static int DnsSimpleParserIterator_ParseCName(DnsSimpleParserIterator *i,
781 const char *Data,
782 int DataLength,
783 const char *Format, /* "%t:%v\n" */
784 char *Buffer,
785 int BufferLength
786 )
787 {
788 return DnsSimpleParserIterator_ParseLabeledName(i,
789 Data,
790 DataLength,
791 Format,
792 Buffer,
793 BufferLength,
794 "Canonical Name",
795 NULL
796 );
797 }
798
DnsSimpleParserIterator_Parse32Uint(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength,const char * Text,int * AcutalDataLength)799 static int DnsSimpleParserIterator_Parse32Uint(DnsSimpleParserIterator *i,
800 const char *Data,
801 int DataLength,
802 const char *Format, /* "%t:%v\n" */
803 char *Buffer,
804 int BufferLength,
805 const char *Text,
806 int *AcutalDataLength
807 )
808 {
809 char Example[] = "4294967295";
810 uint32_t u;
811
812 if( DataLength < 4 || strlen(Format) + 1 > BufferLength )
813 {
814 return 0;
815 }
816
817 if( Text == NULL )
818 {
819 Text = "";
820 }
821
822 strcpy(Buffer, Format);
823
824 if( ReplaceStr_WithLengthChecking(Buffer,
825 "%t",
826 Text,
827 BufferLength
828 )
829 == NULL )
830 {
831 *Buffer = '\0';
832 return 0;
833 }
834
835 u = GET_32_BIT_U_INT(Data);
836
837 sprintf(Example, "%u", u);
838
839 if( ReplaceStr_WithLengthChecking(Buffer,
840 "%v",
841 Example,
842 BufferLength
843 )
844 == NULL )
845 {
846 *Buffer = '\0';
847 return 0;
848 }
849
850 if( AcutalDataLength != NULL )
851 {
852 *AcutalDataLength = 4;
853 }
854
855 return 1;
856 }
857
DnsSimpleParserIterator_Parse16Uint(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength,const char * Text,int * AcutalDataLength)858 static int DnsSimpleParserIterator_Parse16Uint(DnsSimpleParserIterator *i,
859 const char *Data,
860 int DataLength,
861 const char *Format, /* "%t:%v\n" */
862 char *Buffer,
863 int BufferLength,
864 const char *Text,
865 int *AcutalDataLength
866 )
867 {
868 char Example[] = "4294967295";
869 uint32_t u;
870
871 if( DataLength < 2 || strlen(Format) + 1 > BufferLength )
872 {
873 return 0;
874 }
875
876 if( Text == NULL )
877 {
878 Text = "";
879 }
880
881 strcpy(Buffer, Format);
882
883 if( ReplaceStr_WithLengthChecking(Buffer,
884 "%t",
885 Text,
886 BufferLength
887 )
888 == NULL )
889 {
890 *Buffer = '\0';
891 return 0;
892 }
893
894 u = GET_16_BIT_U_INT(Data);
895
896 sprintf(Example, "%d", (int)u);
897
898 if( ReplaceStr_WithLengthChecking(Buffer,
899 "%v",
900 Example,
901 BufferLength
902 )
903 == NULL )
904 {
905 *Buffer = '\0';
906 return 0;
907 }
908
909 if( AcutalDataLength != NULL )
910 {
911 *AcutalDataLength = 2;
912 }
913
914 return 1;
915 }
916
DnsSimpleParserIterator_ParseSingleTxt(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength,const char * Text,int * AcutalDataLength)917 static int DnsSimpleParserIterator_ParseSingleTxt(DnsSimpleParserIterator *i,
918 const char *Data,
919 int DataLength,
920 const char *Format, /* "%t:%v\n" */
921 char *Buffer,
922 int BufferLength,
923 const char *Text,
924 int *AcutalDataLength
925 )
926 {
927 /* Static max length assumed to be 127+1 */
928 char Example[128];
929 char *Resulting;
930
931 int StringLength = GET_8_BIT_U_INT(Data);
932
933 if( strlen(Format) + 1 > BufferLength )
934 {
935 return 0;
936 }
937
938 if( Text == NULL )
939 {
940 Text = "";
941 }
942
943 strcpy(Buffer, Format);
944
945 if( ReplaceStr_WithLengthChecking(Buffer,
946 "%t",
947 Text,
948 BufferLength
949 )
950 == NULL )
951 {
952 *Buffer = '\0';
953 return 0;
954 }
955
956 if( StringLength + 1 > sizeof(Example) )
957 {
958 Resulting = SafeMalloc(StringLength + 1);
959 } else {
960 Resulting = Example;
961 }
962
963 memcpy(Resulting, Data + 1, StringLength);
964 Resulting[StringLength] = '\0';
965
966 if( ReplaceStr_WithLengthChecking(Buffer,
967 "%v",
968 Resulting,
969 BufferLength
970 )
971 == NULL )
972 {
973 *Buffer = '\0';
974
975 if( Resulting != Example )
976 {
977 SafeFree(Resulting);
978 }
979 return 0;
980 }
981
982 if( AcutalDataLength != NULL )
983 {
984 *AcutalDataLength = StringLength + 1;
985 }
986
987 if( Resulting != Example )
988 {
989 SafeFree(Resulting);
990 }
991 return 1;
992 }
993
994 typedef int (*Parser)(DnsSimpleParserIterator *i,
995 const char *Data,
996 int DataLength,
997 const char *Format, /* "%t:%v\n" */
998 char *Buffer,
999 int BufferLength,
1000 const char *Text,
1001 int *AcutalDataLength
1002 );
1003
1004 typedef struct {
1005 const char *Text;
1006 Parser ps;
1007 } ParserProjector;
1008
DnsSimpleParserIterator_ParseData(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength,const ParserProjector * pp)1009 static int DnsSimpleParserIterator_ParseData(DnsSimpleParserIterator *i,
1010 const char *Data,
1011 int DataLength,
1012 const char *Format, /* "%t:%v\n" */
1013 char *Buffer,
1014 int BufferLength,
1015 const ParserProjector *pp
1016 )
1017 {
1018 int n = 0;
1019
1020 const char *DataItr = Data;
1021 int LeftDataLength = DataLength;
1022
1023 char *BufferItr = Buffer;
1024 int LeftBufferLength = BufferLength;
1025
1026 while( pp[n].Text != NULL )
1027 {
1028 int Stage;
1029 int ActualLength;
1030 Stage = pp[n].ps(i,
1031 DataItr,
1032 LeftDataLength,
1033 Format,
1034 BufferItr,
1035 LeftBufferLength,
1036 pp[n].Text,
1037 &ActualLength
1038 );
1039 if( Stage <= 0 )
1040 {
1041 break;
1042 } else {
1043 int ResultLength = strlen(BufferItr);
1044
1045 BufferItr += ResultLength;
1046 LeftBufferLength -= ResultLength;
1047
1048 DataItr += ActualLength;
1049 LeftDataLength -= ActualLength;
1050 ++n;
1051 }
1052 }
1053
1054 return n;
1055 }
1056
DnsSimpleParserIterator_ParseSOA(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength)1057 static int DnsSimpleParserIterator_ParseSOA(DnsSimpleParserIterator *i,
1058 const char *Data,
1059 int DataLength,
1060 const char *Format, /* "%t:%v\n" */
1061 char *Buffer,
1062 int BufferLength
1063 )
1064 {
1065 ParserProjector pp[] = {
1066 {"(SOA)primary name server", DnsSimpleParserIterator_ParseLabeledName},
1067 {"(SOA)responsible mail addr", DnsSimpleParserIterator_ParseLabeledName},
1068 {"(SOA)serial", DnsSimpleParserIterator_Parse32Uint},
1069 {"(SOA)refresh", DnsSimpleParserIterator_Parse32Uint},
1070 {"(SOA)retry", DnsSimpleParserIterator_Parse32Uint},
1071 {"(SOA)expire", DnsSimpleParserIterator_Parse32Uint},
1072 {"(SOA)default TTL", DnsSimpleParserIterator_Parse32Uint},
1073
1074 {NULL, NULL},
1075 };
1076
1077 return DnsSimpleParserIterator_ParseData(i,
1078 Data,
1079 DataLength,
1080 Format,
1081 Buffer,
1082 BufferLength,
1083 pp
1084 ) == 7 ? 7 : 0;
1085 }
1086
DnsSimpleParserIterator_ParseDomainPtr(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength)1087 static int DnsSimpleParserIterator_ParseDomainPtr(DnsSimpleParserIterator *i,
1088 const char *Data,
1089 int DataLength,
1090 const char *Format, /* "%t:%v\n" */
1091 char *Buffer,
1092 int BufferLength
1093 )
1094 {
1095 return DnsSimpleParserIterator_ParseLabeledName(i,
1096 Data,
1097 DataLength,
1098 Format,
1099 Buffer,
1100 BufferLength,
1101 "name",
1102 NULL
1103 );
1104 }
1105
DnsSimpleParserIterator_ParseNameServer(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength)1106 static int DnsSimpleParserIterator_ParseNameServer(DnsSimpleParserIterator *i,
1107 const char *Data,
1108 int DataLength,
1109 const char *Format, /* "%t:%v\n" */
1110 char *Buffer,
1111 int BufferLength
1112 )
1113 {
1114 return DnsSimpleParserIterator_ParseLabeledName(i,
1115 Data,
1116 DataLength,
1117 Format,
1118 Buffer,
1119 BufferLength,
1120 "Name Server",
1121 NULL
1122 );
1123 }
1124
DnsSimpleParserIterator_ParseMailEx(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength)1125 static int DnsSimpleParserIterator_ParseMailEx(DnsSimpleParserIterator *i,
1126 const char *Data,
1127 int DataLength,
1128 const char *Format, /* "%t:%v\n" */
1129 char *Buffer,
1130 int BufferLength
1131 )
1132 {
1133 ParserProjector pp[] = {
1134 {"preference", DnsSimpleParserIterator_Parse16Uint},
1135 {"mail exchanger", DnsSimpleParserIterator_ParseLabeledName},
1136
1137 {NULL, NULL},
1138 };
1139
1140 return DnsSimpleParserIterator_ParseData(i,
1141 Data,
1142 DataLength,
1143 Format,
1144 Buffer,
1145 BufferLength,
1146 pp
1147 ) == 2 ? 2 : 0;
1148 }
1149
DnsSimpleParserIterator_ParseTxt(DnsSimpleParserIterator * i,const char * Data,int DataLength,const char * Format,char * Buffer,int BufferLength)1150 static int DnsSimpleParserIterator_ParseTxt(DnsSimpleParserIterator *i,
1151 const char *Data,
1152 int DataLength,
1153 const char *Format, /* "%t:%v\n" */
1154 char *Buffer,
1155 int BufferLength
1156 )
1157 {
1158 const char *DataItr = Data;
1159 int DataLeft = DataLength;
1160
1161 char *BufferItr = Buffer;
1162 int BufferLeft = BufferLength;
1163
1164 int n = 0;
1165
1166 while( DataItr < Data + DataLength )
1167 {
1168 int Stage;
1169 int ActualLength;
1170
1171 Stage = DnsSimpleParserIterator_ParseSingleTxt(i,
1172 DataItr,
1173 DataLeft,
1174 Format,
1175 BufferItr,
1176 BufferLeft,
1177 "TXT",
1178 &ActualLength
1179 );
1180
1181 if( Stage <= 0 )
1182 {
1183 break;
1184 } else {
1185 int StageLength = strlen(BufferItr);
1186
1187 DataItr += ActualLength;
1188 DataLeft -= ActualLength;
1189
1190 BufferItr += StageLength;
1191 BufferLeft -= StageLength;
1192
1193 ++n;
1194 }
1195 }
1196
1197 return n;
1198 }
1199
DnsSimpleParserIterator_Unparsable(const char * Format,char * Buffer,int BufferLength,DNSRecordType Type)1200 static int DnsSimpleParserIterator_Unparsable(const char *Format, /* "%t:%v\n" */
1201 char *Buffer,
1202 int BufferLength,
1203 DNSRecordType Type
1204 )
1205 {
1206 char a[] = "4294967295";
1207
1208 strcpy(Buffer, Format);
1209
1210 if( ReplaceStr_WithLengthChecking(Buffer,
1211 "%t",
1212 "Unparsable type",
1213 BufferLength
1214 )
1215 == NULL )
1216 {
1217 return 0;
1218 }
1219
1220 sprintf(a, "%d", (int)Type);
1221
1222 if( ReplaceStr_WithLengthChecking(Buffer,
1223 "%v",
1224 a,
1225 BufferLength
1226 )
1227 == NULL )
1228 {
1229 return 0;
1230 }
1231
1232 return 1;
1233 }
1234
1235 /* Number of items generated returned */
DnsSimpleParserIterator_TextifyData(DnsSimpleParserIterator * i,const char * Format,char * Buffer,int BufferLength)1236 static int DnsSimpleParserIterator_TextifyData(DnsSimpleParserIterator *i,
1237 const char *Format, /* "%t:%v\n" */
1238 char *Buffer,
1239 int BufferLength
1240 )
1241 {
1242 const char *Data = DNSGetResourceDataPos(i->CurrentPosition);
1243
1244 int (*RecordParser)(DnsSimpleParserIterator *i,
1245 const char *Data,
1246 int DataLength,
1247 const char *Format, /* "%t:%v\n" */
1248 char *Buffer,
1249 int BufferLength
1250 ) = NULL;
1251
1252 if( i->Type != DNS_TYPE_OPT &&
1253 i->Klass != DNS_CLASS_IN
1254 )
1255 {
1256 return 0; /* Unparsable */
1257 }
1258
1259 switch( i->Type )
1260 {
1261 case DNS_TYPE_A:
1262 RecordParser = DnsSimpleParserIterator_ParseA;
1263 break;
1264
1265 case DNS_TYPE_AAAA:
1266 RecordParser = DnsSimpleParserIterator_ParseAAAA;
1267 break;
1268
1269 case DNS_TYPE_CNAME:
1270 RecordParser = DnsSimpleParserIterator_ParseCName;
1271 break;
1272
1273 case DNS_TYPE_PTR:
1274 RecordParser = DnsSimpleParserIterator_ParseDomainPtr;
1275 break;
1276
1277 case DNS_TYPE_SOA:
1278 RecordParser = DnsSimpleParserIterator_ParseSOA;
1279 break;
1280
1281 case DNS_TYPE_TXT:
1282 RecordParser = DnsSimpleParserIterator_ParseTxt;
1283 break;
1284
1285 case DNS_TYPE_MX:
1286 RecordParser = DnsSimpleParserIterator_ParseMailEx;
1287 break;
1288
1289 case DNS_TYPE_NS:
1290 RecordParser = DnsSimpleParserIterator_ParseNameServer;
1291 break;
1292
1293 default:
1294 RecordParser = NULL;
1295 break;
1296 }
1297
1298 if( RecordParser != NULL )
1299 {
1300 return RecordParser(i,
1301 Data,
1302 i->DataLength,
1303 Format,
1304 Buffer,
1305 BufferLength
1306 );
1307 } else {
1308 return DnsSimpleParserIterator_Unparsable(Format,
1309 Buffer,
1310 BufferLength,
1311 i->Type
1312 );
1313 }
1314 }
1315
DnsSimpleParserIterator_GetTTL(DnsSimpleParserIterator * i)1316 static uint32_t DnsSimpleParserIterator_GetTTL(DnsSimpleParserIterator *i)
1317 {
1318 return DNSGetTTL(i->CurrentPosition);
1319 }
1320
DnsSimpleParserIterator_Init(DnsSimpleParserIterator * i,DnsSimpleParser * p)1321 int DnsSimpleParserIterator_Init(DnsSimpleParserIterator *i, DnsSimpleParser *p)
1322 {
1323 int QuestionCount, AnswerCount, NameServerCount, AdditionalCount;
1324
1325 if( i == NULL || p == NULL )
1326 {
1327 return -1;
1328 }
1329
1330 QuestionCount = p->QuestionCount(p);
1331 AnswerCount = p->AnswerCount(p);
1332 NameServerCount = p->NameServerCount(p);
1333 AdditionalCount = p->AdditionalCount(p);
1334
1335 i->Parser = p;
1336 i->CurrentPosition = NULL;
1337 i->RecordPosition = 0;
1338
1339 i->AllRecordCount = QuestionCount +
1340 AnswerCount +
1341 NameServerCount +
1342 AdditionalCount;
1343
1344 i->QuestionFirst = QuestionCount == 0 ? 0 : 1;
1345 i->QuestionLast = i->QuestionFirst + QuestionCount - 1;
1346
1347 i->AnswerFirst = AnswerCount == 0 ?
1348 0 :
1349 i->QuestionFirst + QuestionCount;
1350 i->AnswerLast = i->AnswerFirst + AnswerCount - 1;
1351
1352 i->NameServerFirst = NameServerCount == 0 ?
1353 0 :
1354 i->QuestionFirst +
1355 QuestionCount +
1356 AnswerCount;
1357 i->NameServerLast = i->NameServerFirst + NameServerCount - 1;
1358
1359 i->AdditionalFirst = AdditionalCount == 0 ?
1360 0 :
1361 i->QuestionFirst +
1362 QuestionCount +
1363 AnswerCount +
1364 NameServerCount;
1365 i->AdditionalLast = i->AdditionalFirst + AdditionalCount - 1;
1366
1367 i->Next = DnsSimpleParserIterator_Next;
1368 i->GotoAnswers = DnsSimpleParserIterator_GotoAnswers;
1369 i->GetName = DnsSimpleParserIterator_GetName;
1370 i->GetNameLength = DnsSimpleParserIterator_GetNameLength;
1371 i->RowData = DnsSimpleParserIterator_RowData;
1372 i->TextifyData = DnsSimpleParserIterator_TextifyData;
1373 i->GetTTL = DnsSimpleParserIterator_GetTTL;
1374
1375 return 0;
1376 }
1377