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