15090768aa7d50b0474502d4b6c9fc03e7167825
[reactos.git] / base / applications / network / nslookup / utility.c
1 /*
2 * PROJECT: ReactOS nslookup utility
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/network/nslookup/utility.c
5 * PURPOSE: Support functions for nslookup.c
6 * COPYRIGHT: Copyright 2009 Lucas Suggs <lucas.suggs@gmail.com>
7 */
8
9 #include "nslookup.h"
10
11 BOOL SendRequest( PCHAR pInBuffer,
12 ULONG InBufferLength,
13 PCHAR pOutBuffer,
14 PULONG pOutBufferLength )
15 {
16 int j;
17 USHORT RequestID, ResponseID;
18 BOOL bWait;
19 SOCKET s;
20 SOCKADDR_IN RecAddr, RecAddr2, SendAddr;
21 int SendAddrLen = sizeof(SendAddr);
22
23 RtlZeroMemory( &RecAddr, sizeof(SOCKADDR_IN) );
24 RtlZeroMemory( &RecAddr2, sizeof(SOCKADDR_IN) );
25 RtlZeroMemory( &SendAddr, sizeof(SOCKADDR_IN) );
26
27 /* Pull the request ID from the buffer. */
28 RequestID = ntohs( ((PSHORT)&pInBuffer[0])[0] );
29
30 /* If D2 flags is enabled, then display D2 information. */
31 if( State.d2 ) PrintD2( pInBuffer, InBufferLength );
32
33 /* Create the sockets for both send and receive. */
34 s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
35
36 if (s == INVALID_SOCKET)
37 return FALSE;
38
39 /* Set up the structure to tell it where we are going. */
40 RecAddr.sin_family = AF_INET;
41 RecAddr.sin_port = htons( State.port );
42 RecAddr.sin_addr.s_addr = inet_addr( State.DefaultServerAddress );
43
44 /* Set up the structure to tell it what port to listen on. */
45 RecAddr2.sin_family = AF_INET;
46 RecAddr2.sin_port = htons( State.port );
47 RecAddr2.sin_addr.s_addr = htonl( INADDR_ANY );
48
49 /* Bind the receive socket. */
50 bind( s, (SOCKADDR*)&RecAddr2, sizeof(RecAddr2) );
51
52 /* Send the datagram to the DNS server. */
53 j = sendto( s,
54 pInBuffer,
55 InBufferLength,
56 0,
57 (SOCKADDR*)&RecAddr,
58 sizeof(RecAddr) );
59 if( j == SOCKET_ERROR )
60 {
61 switch( WSAGetLastError() )
62 {
63 case WSANOTINITIALISED:
64 _tprintf( _T("sendto() failed with WSANOTINITIALIZED\n") );
65 break;
66 case WSAENETDOWN:
67 _tprintf( _T("sendto() failed with WSAENETDOWN\n") );
68 break;
69 case WSAEACCES:
70 _tprintf( _T("sendto() failed with WSAEACCES\n") );
71 break;
72 case WSAEINVAL:
73 _tprintf( _T("sendto() failed with WSAEINVAL\n") );
74 break;
75 case WSAEINTR:
76 _tprintf( _T("sendto() failed with WSAEINTR\n") );
77 break;
78 case WSAEINPROGRESS:
79 _tprintf( _T("sendto() failed with WSAEINPROGRESS\n") );
80 break;
81 case WSAEFAULT:
82 _tprintf( _T("sendto() failed with WSAEFAULT\n") );
83 break;
84 case WSAENETRESET:
85 _tprintf( _T("sendto() failed with WSAENETRESET\n") );
86 break;
87 case WSAENOBUFS:
88 _tprintf( _T("sendto() failed with WSAENOBUFS\n") );
89 break;
90 case WSAENOTCONN:
91 _tprintf( _T("sendto() failed with WSAENOTCONN\n") );
92 break;
93 case WSAENOTSOCK:
94 _tprintf( _T("sendto() failed with WSAENOTSOCK\n") );
95 break;
96 case WSAEOPNOTSUPP:
97 _tprintf( _T("sendto() failed with WSAEOPNOTSUPP\n") );
98 break;
99 case WSAESHUTDOWN:
100 _tprintf( _T("sendto() failed with WSAESHUTDOWN\n") );
101 break;
102 case WSAEWOULDBLOCK:
103 _tprintf( _T("sendto() failed with WSAEWOULDBLOCK\n") );
104 break;
105 case WSAEMSGSIZE:
106 _tprintf( _T("sendto() failed with WSAEMSGSIZE\n") );
107 break;
108 case WSAEHOSTUNREACH:
109 _tprintf( _T("sendto() failed with WSAEHOSTUNREACH\n") );
110 break;
111 case WSAECONNABORTED:
112 _tprintf( _T("sendto() failed with WSAECONNABORTED\n") );
113 break;
114 case WSAECONNRESET:
115 _tprintf( _T("sendto() failed with WSAECONNRESET\n") );
116 break;
117 case WSAEADDRNOTAVAIL:
118 _tprintf( _T("sendto() failed with WSAEADDRNOTAVAIL\n") );
119 break;
120 case WSAEAFNOSUPPORT:
121 _tprintf( _T("sendto() failed with WSAEAFNOSUPPORT\n") );
122 break;
123 case WSAEDESTADDRREQ:
124 _tprintf( _T("sendto() failed with WSAEDESTADDRREQ\n") );
125 break;
126 case WSAENETUNREACH:
127 _tprintf( _T("sendto() failed with WSAENETUNREACH\n") );
128 break;
129 case WSAETIMEDOUT:
130 _tprintf( _T("sendto() failed with WSAETIMEDOUT\n") );
131 break;
132 default:
133 _tprintf( _T("sendto() failed with unknown error\n") );
134 }
135
136 closesocket( s );
137 return FALSE;
138 }
139
140 bWait = TRUE;
141
142 while( bWait )
143 {
144 /* Wait for the DNS reply. */
145 j = recvfrom( s,
146 pOutBuffer,
147 *pOutBufferLength,
148 0,
149 (SOCKADDR*)&SendAddr,
150 &SendAddrLen );
151 if( j == SOCKET_ERROR )
152 {
153 switch( WSAGetLastError() )
154 {
155 case WSANOTINITIALISED:
156 _tprintf( _T("recvfrom() failed with WSANOTINITIALIZED\n") );
157 break;
158 case WSAENETDOWN:
159 _tprintf( _T("recvfrom() failed with WSAENETDOWN\n") );
160 break;
161 case WSAEACCES:
162 _tprintf( _T("recvfrom() failed with WSAEACCES\n") );
163 break;
164 case WSAEINVAL:
165 _tprintf( _T("recvfrom() failed with WSAEINVAL\n") );
166 break;
167 case WSAEINTR:
168 _tprintf( _T("recvfrom() failed with WSAEINTR\n") );
169 break;
170 case WSAEINPROGRESS:
171 _tprintf( _T("recvfrom() failed with WSAEINPROGRESS\n") );
172 break;
173 case WSAEFAULT:
174 _tprintf( _T("recvfrom() failed with WSAEFAULT\n") );
175 break;
176 case WSAENETRESET:
177 _tprintf( _T("recvfrom() failed with WSAENETRESET\n") );
178 break;
179 case WSAENOBUFS:
180 _tprintf( _T("recvfrom() failed with WSAENOBUFS\n") );
181 break;
182 case WSAENOTCONN:
183 _tprintf( _T("recvfrom() failed with WSAENOTCONN\n") );
184 break;
185 case WSAENOTSOCK:
186 _tprintf( _T("recvfrom() failed with WSAENOTSOCK\n") );
187 break;
188 case WSAEOPNOTSUPP:
189 _tprintf( _T("recvfrom() failed with WSAEOPNOTSUPP\n") );
190 break;
191 case WSAESHUTDOWN:
192 _tprintf( _T("recvfrom() failed with WSAESHUTDOWN\n") );
193 break;
194 case WSAEWOULDBLOCK:
195 _tprintf( _T("recvfrom() failed with WSAEWOULDBLOCK\n") );
196 break;
197 case WSAEMSGSIZE:
198 _tprintf( _T("recvfrom() failed with WSAEMSGSIZE\n") );
199 break;
200 case WSAEHOSTUNREACH:
201 _tprintf( _T("recvfrom() failed with WSAEHOSTUNREACH\n") );
202 break;
203 case WSAECONNABORTED:
204 _tprintf( _T("recvfrom() failed with WSAECONNABORTED\n") );
205 break;
206 case WSAECONNRESET:
207 _tprintf( _T("recvfrom() failed with WSAECONNRESET\n") );
208 break;
209 case WSAEADDRNOTAVAIL:
210 _tprintf( _T("recvfrom() failed with WSAEADDRNOTAVAIL\n") );
211 break;
212 case WSAEAFNOSUPPORT:
213 _tprintf( _T("recvfrom() failed with WSAEAFNOSUPPORT\n") );
214 break;
215 case WSAEDESTADDRREQ:
216 _tprintf( _T("recvfrom() failed with WSAEDESTADDRREQ\n") );
217 break;
218 case WSAENETUNREACH:
219 _tprintf( _T("recvfrom() failed with WSAENETUNREACH\n") );
220 break;
221 case WSAETIMEDOUT:
222 _tprintf( _T("recvfrom() failed with WSAETIMEDOUT\n") );
223 break;
224 default:
225 _tprintf( _T("recvfrom() failed with unknown error\n") );
226 }
227
228 closesocket( s );
229 return FALSE;
230 }
231
232 ResponseID = ntohs( ((PSHORT)&pOutBuffer[0])[0] );
233
234 if( ResponseID == RequestID ) bWait = FALSE;
235 }
236
237 /* We don't need the sockets anymore. */
238 closesocket( s );
239
240 /* If debug information then display debug information. */
241 if( State.debug ) PrintDebug( pOutBuffer, j );
242
243 /* Return the real output buffer length. */
244 *pOutBufferLength = j;
245
246 return TRUE;
247 }
248
249 void ReverseIP( PCHAR pIP, PCHAR pReturn )
250 {
251 int i;
252 int j;
253 int k = 0;
254
255 j = strlen( pIP ) - 1;
256 i = j;
257
258 /* We have A.B.C.D
259 We will turn this into D.C.B.A and stick it in pReturn */
260
261 /* A */
262 for( ; i > 0; i -= 1 ) if( '.' == pIP[i] ) break;
263
264 strncpy( &pReturn[k], &pIP[i + 1], (j - i) );
265 k += (j - i);
266
267 pReturn[k] = '.';
268 k += 1;
269
270 i -= 1;
271 j = i;
272
273 /* B */
274 for( ; i > 0; i -= 1 ) if( '.' == pIP[i] ) break;
275
276 strncpy( &pReturn[k], &pIP[i + 1], (j - i) );
277 k += (j - i);
278
279 pReturn[k] = '.';
280 k += 1;
281
282 i -= 1;
283 j = i;
284
285 /* C */
286 for( ; i > 0; i -= 1 ) if( '.' == pIP[i] ) break;
287
288 strncpy( &pReturn[k], &pIP[i + 1], (j - i) );
289 k += (j - i);
290
291 pReturn[k] = '.';
292 k += 1;
293
294 i -= 1;
295 j = i;
296
297 /* D */
298 for( ; i > 0; i -= 1 );
299
300 strncpy( &pReturn[k], &pIP[i], (j - i) + 1 );
301 k += (j - i) + 1;
302
303 pReturn[k] = '\0';
304 }
305
306 BOOL IsValidIP( PCHAR pInput )
307 {
308 int i = 0, l = 0, b = 0, c = 1;
309
310 /* Max length of an IP, e.g. 255.255.255.255, is 15 characters. */
311 l = strlen( pInput );
312 if( l > 15 ) return FALSE;
313
314 /* 'b' is the count of the current segment. It gets reset after seeing a
315 '.'. */
316 for( ; i < l; i += 1 )
317 {
318 if( '.' == pInput[i] )
319 {
320 if( !b ) return FALSE;
321 if( b > 3 ) return FALSE;
322
323 b = 0;
324 c += 1;
325 }
326 else
327 {
328 b += 1;
329
330 if( (pInput[i] < '0') || (pInput[i] > '9') ) return FALSE;
331 }
332 }
333
334 if( b > 3 ) return FALSE;
335
336 /* 'c' is the number of segments seen. If it's less than 4, then it's not
337 a valid IP. */
338 if( c < 4 ) return FALSE;
339
340 return TRUE;
341 }
342
343 int ExtractName( PCHAR pBuffer, PCHAR pOutput, USHORT Offset, UCHAR Limit )
344 {
345 int c = 0, d = 0, i = 0, j = 0, k = 0, l = 0, m = 0;
346
347 i = Offset;
348
349 /* If Limit == 0, then we assume "no" limit. */
350 d = Limit;
351 if( 0 == Limit ) d = 255;
352
353 while( d > 0 )
354 {
355 l = pBuffer[i] & 0xFF;
356 i += 1;
357 if( !m ) c += 1;
358
359 if( 0xC0 == l )
360 {
361 if( !m ) c += 1;
362 m = 1;
363 d += (255 - Limit);
364 i = pBuffer[i];
365 }
366 else
367 {
368 for( j = 0; j < l; j += 1 )
369 {
370 pOutput[k] = pBuffer[i];
371
372 i += 1;
373 if( !m ) c += 1;
374 k += 1;
375 d -= 1;
376 }
377
378 d -= 1;
379
380 if( !pBuffer[i] || (d < 1) ) break;
381
382 pOutput[k] = '.';
383 k += 1;
384 }
385 };
386
387 if( !m )
388 {
389 if( !Limit ) c += 1;
390 }
391
392 pOutput[k] = '\0';
393
394 return c;
395 }
396
397 int ExtractIP( PCHAR pBuffer, PCHAR pOutput, USHORT Offset )
398 {
399 int c = 0, l = 0, i = 0, v = 0;
400
401 i = Offset;
402
403 v = (UCHAR)pBuffer[i];
404 l += 1;
405 i += 1;
406
407 sprintf( &pOutput[c], "%d.", v );
408 c += strlen( &pOutput[c] );
409
410 v = (UCHAR)pBuffer[i];
411 l += 1;
412 i += 1;
413
414 sprintf( &pOutput[c], "%d.", v );
415 c += strlen( &pOutput[c] );
416
417 v = (UCHAR)pBuffer[i];
418 l += 1;
419 i += 1;
420
421 sprintf( &pOutput[c], "%d.", v );
422 c += strlen( &pOutput[c] );
423
424 v = (UCHAR)pBuffer[i];
425 l += 1;
426 i += 1;
427
428 sprintf( &pOutput[c], "%d", v );
429 c += strlen( &pOutput[c] );
430
431 pOutput[c] = '\0';
432
433 return l;
434 }
435
436 void PrintD2( PCHAR pBuffer, DWORD BufferLength )
437 {
438 USHORT RequestID;
439 UCHAR Header1, Header2;
440 USHORT NumQuestions, NumAnswers, NumAuthority, NumAdditional;
441 USHORT Type, Class;
442 CHAR pName[255];
443 int i = 0, k = 0;
444
445 RequestID = ntohs( ((PUSHORT)&pBuffer[i])[0] );
446 i += 2;
447
448 Header1 = pBuffer[i];
449 i += 1;
450
451 Header2 = pBuffer[i];
452 i += 1;
453
454 NumQuestions = ntohs( ((PSHORT)&pBuffer[i])[0] );
455 i += 2;
456
457 NumAnswers = ntohs( ((PSHORT)&pBuffer[i])[0] );
458 i += 2;
459
460 NumAuthority = ntohs( ((PUSHORT)&pBuffer[i])[0] );
461 i += 2;
462
463 NumAdditional = ntohs( ((PUSHORT)&pBuffer[i])[0] );
464 i += 2;
465
466 _tprintf( _T("------------\n") );
467 _tprintf( _T("SendRequest(), len %d\n"), (int)BufferLength );
468 _tprintf( _T(" HEADER:\n") );
469 _tprintf( _T(" opcode = %s, id = %d, rcode = %s\n"),
470 OpcodeIDtoOpcodeName( (Header1 & 0x78) >> 3 ),
471 (int)RequestID,
472 RCodeIDtoRCodeName( Header2 & 0x0F ) );
473
474 _tprintf( _T(" header flags: query") );
475 if( Header1 & 0x01 ) _tprintf( _T(", want recursion") );
476 _tprintf( _T("\n") );
477
478 _tprintf( _T(" questions = %d, answers = %d,"
479 " authority records = %d, additional = %d\n\n"),
480 (int)NumQuestions,
481 (int)NumAnswers,
482 (int)NumAuthority,
483 (int)NumAdditional );
484
485 if( NumQuestions )
486 {
487 _tprintf( _T(" QUESTIONS:\n") );
488
489 for( k = 0; k < NumQuestions; k += 1 )
490 {
491 i += ExtractName( pBuffer, pName, i, 0 );
492
493 _tprintf( _T(" %s"), pName );
494
495 Type = ntohs( ((PUSHORT)&pBuffer[i])[0] );
496 i += 2;
497
498 Class = ntohs( ((PUSHORT)&pBuffer[i])[0] );
499 i += 2;
500
501 _tprintf( _T(", type = %s, class = %s\n"),
502 TypeIDtoTypeName( Type ),
503 ClassIDtoClassName( Class ) );
504 }
505 }
506
507 _tprintf( _T("\n------------\n") );
508 }
509
510 void PrintDebug( PCHAR pBuffer, DWORD BufferLength )
511 {
512 USHORT ResponseID;
513 UCHAR Header1, Header2;
514 USHORT NumQuestions, NumAnswers, NumAuthority, NumAdditional;
515 USHORT Type, Class;
516 ULONG TTL;
517 CHAR pName[255];
518 int d = 0, i = 0, k = 0;
519
520 ResponseID = ntohs( ((PUSHORT)&pBuffer[i])[0] );
521 i += 2;
522
523 Header1 = pBuffer[i];
524 i += 1;
525
526 Header2 = pBuffer[i];
527 i += 1;
528
529 NumQuestions = ntohs( ((PSHORT)&pBuffer[i])[0] );
530 i += 2;
531
532 NumAnswers = ntohs( ((PSHORT)&pBuffer[i])[0] );
533 i += 2;
534
535 NumAuthority = ntohs( ((PUSHORT)&pBuffer[i])[0] );
536 i += 2;
537
538 NumAdditional = ntohs( ((PUSHORT)&pBuffer[i])[0] );
539 i += 2;
540
541 _tprintf( _T("------------\n") );
542 _tprintf( _T("Got answer (%d bytes):\n"), (int)BufferLength );
543 _tprintf( _T(" HEADER:\n") );
544 _tprintf( _T(" opcode = %s, id = %d, rcode = %s\n"),
545 OpcodeIDtoOpcodeName( (Header1 & 0x78) >> 3 ),
546 (int)ResponseID,
547 RCodeIDtoRCodeName( Header2 & 0x0F ) );
548
549 _tprintf( _T(" header flags: response") );
550 if( Header1 & 0x01 ) _tprintf( _T(", want recursion") );
551 if( Header2 & 0x80 ) _tprintf( _T(", recursion avail.") );
552 _tprintf( _T("\n") );
553
554 _tprintf( _T(" questions = %d, answers = %d, "
555 "authority records = %d, additional = %d\n\n"),
556 (int)NumQuestions,
557 (int)NumAnswers,
558 (int)NumAuthority,
559 (int)NumAdditional );
560
561 if( NumQuestions )
562 {
563 _tprintf( _T(" QUESTIONS:\n") );
564
565 for( k = 0; k < NumQuestions; k += 1 )
566 {
567 i += ExtractName( pBuffer, pName, i, 0 );
568
569 _tprintf( _T(" %s"), pName );
570
571 Type = ntohs( ((PUSHORT)&pBuffer[i])[0] );
572 i += 2;
573
574 Class = ntohs( ((PUSHORT)&pBuffer[i])[0] );
575 i += 2;
576
577 _tprintf( _T(", type = %s, class = %s\n"),
578 TypeIDtoTypeName( Type ),
579 ClassIDtoClassName( Class ) );
580 }
581 }
582
583 if( NumAnswers )
584 {
585 _tprintf( _T(" ANSWERS:\n") );
586
587 for( k = 0; k < NumAnswers; k += 1 )
588 {
589 _tprintf( _T(" -> ") );
590
591 /* Print out the name. */
592 i += ExtractName( pBuffer, pName, i, 0 );
593
594 _tprintf( _T("%s\n"), pName );
595
596 /* Print out the type, class and data length. */
597 Type = ntohs( ((PUSHORT)&pBuffer[i])[0] );
598 i += 2;
599
600 Class = ntohs( ((PUSHORT)&pBuffer[i])[0] );
601 i += 2;
602
603 TTL = ntohl( ((PULONG)&pBuffer[i])[0] );
604 i += 4;
605
606 d = ntohs( ((PUSHORT)&pBuffer[i])[0] );
607 i += 2;
608
609 _tprintf( _T(" type = %s, class = %s, dlen = %d\n"),
610 TypeIDtoTypeName( Type ),
611 ClassIDtoClassName( Class ),
612 d );
613
614 /* Print out the answer. */
615 if( TYPE_A == Type )
616 {
617 i += ExtractIP( pBuffer, pName, i );
618
619 _tprintf( _T(" internet address = %s\n"), pName );
620 }
621 else
622 {
623 i += ExtractName( pBuffer, pName, i, d );
624
625 _tprintf( _T(" name = %s\n"), pName );
626 }
627
628 _tprintf( _T(" ttl = %d ()\n"), (int)TTL );
629 }
630 }
631
632 if( NumAuthority )
633 {
634 _tprintf( _T(" AUTHORITY RECORDS:\n") );
635
636 for( k = 0; k < NumAuthority; k += 1 )
637 {
638 /* Print out the zone name. */
639 i += ExtractName( pBuffer, pName, i, 0 );
640
641 _tprintf( _T(" -> %s\n"), pName );
642
643 /* Print out the type, class, data length and TTL. */
644 Type = ntohs( ((PUSHORT)&pBuffer[i])[0] );
645 i += 2;
646
647 Class = ntohs( ((PUSHORT)&pBuffer[i])[0] );
648 i += 2;
649
650 TTL = ntohl( ((PULONG)&pBuffer[i])[0] );
651 i += 4;
652
653 d = ntohs( ((PUSHORT)&pBuffer[i])[0] );
654 i += 2;
655
656 _tprintf( _T(" type = %s, class = %s, dlen = %d\n"),
657 TypeIDtoTypeName( Type ),
658 ClassIDtoClassName( Class ),
659 d );
660
661 /* TODO: There might be more types? */
662 if( TYPE_NS == Type )
663 {
664 /* Print out the NS. */
665 i += ExtractName( pBuffer, pName, i, d );
666
667 _tprintf( _T(" nameserver = %s\n"), pName );
668
669 _tprintf( _T(" ttl = %d ()\n"), (int)TTL );
670 }
671 else if( TYPE_SOA == Type )
672 {
673 _tprintf( _T(" ttl = %d ()\n"), (int)TTL );
674
675 /* Print out the primary NS. */
676 i += ExtractName( pBuffer, pName, i, 0 );
677
678 _tprintf( _T(" primary name server = %s\n"), pName );
679
680 /* Print out the responsible mailbox. */
681 i += ExtractName( pBuffer, pName, i, 0 );
682
683 _tprintf( _T(" responsible mail addr = %s\n"), pName );
684
685 /* Print out the serial, refresh, retry, expire and default TTL. */
686 _tprintf( _T(" serial = ()\n") );
687 _tprintf( _T(" refresh = ()\n") );
688 _tprintf( _T(" retry = ()\n") );
689 _tprintf( _T(" expire = ()\n") );
690 _tprintf( _T(" default TTL = ()\n") );
691 i += 20;
692 }
693 }
694 }
695
696 if( NumAdditional )
697 {
698 _tprintf( _T(" ADDITIONAL:\n") );
699
700 for( k = 0; k < NumAdditional; k += 1 )
701 {
702 /* Print the name. */
703 i += ExtractName( pBuffer, pName, i, 0 );
704
705 _tprintf( _T(" -> %s\n"), pName );
706
707 /* Print out the type, class, data length and TTL. */
708 Type = ntohs( ((PUSHORT)&pBuffer[i])[0] );
709 i += 2;
710
711 Class = ntohs( ((PUSHORT)&pBuffer[i])[0] );
712 i += 2;
713
714 TTL = ntohl( ((PULONG)&pBuffer[i])[0] );
715 i += 4;
716
717 d = ntohs( ((PUSHORT)&pBuffer[i])[0] );
718 i += 2;
719
720 _tprintf( _T(" type = %s, class = %s, dlen = %d\n"),
721 TypeIDtoTypeName( Type ),
722 ClassIDtoClassName( Class ),
723 d );
724
725 /* TODO: There might be more types? */
726 if( TYPE_A == Type )
727 {
728 /* Print out the NS. */
729 i += ExtractIP( pBuffer, pName, i );
730
731 _tprintf( _T(" internet address = %s\n"), pName );
732
733 _tprintf( _T(" ttl = %d ()\n"), (int)TTL );
734 }
735 }
736 }
737
738 _tprintf( _T("\n------------\n") );
739 }
740
741 PCHAR OpcodeIDtoOpcodeName( UCHAR Opcode )
742 {
743 switch( Opcode & 0x0F )
744 {
745 case OPCODE_QUERY:
746 return OpcodeQuery;
747
748 case OPCODE_IQUERY:
749 return OpcodeIQuery;
750
751 case OPCODE_STATUS:
752 return OpcodeStatus;
753
754 default:
755 return OpcodeReserved;
756 }
757 }
758
759 PCHAR RCodeIDtoRCodeName( UCHAR RCode )
760 {
761 switch( RCode & 0x0F )
762 {
763 case RCODE_NOERROR:
764 return RCodeNOERROR;
765
766 case RCODE_FORMERR:
767 return RCodeFORMERR;
768
769 case RCODE_FAILURE:
770 return RCodeFAILURE;
771
772 case RCODE_NXDOMAIN:
773 return RCodeNXDOMAIN;
774
775 case RCODE_NOTIMP:
776 return RCodeNOTIMP;
777
778 case RCODE_REFUSED:
779 return RCodeREFUSED;
780
781 default:
782 return RCodeReserved;
783 }
784 }
785
786 PCHAR TypeIDtoTypeName( USHORT TypeID )
787 {
788 switch( TypeID )
789 {
790 case TYPE_A:
791 return TypeA;
792
793 case TYPE_NS:
794 return TypeNS;
795
796 case TYPE_CNAME:
797 return TypeCNAME;
798
799 case TYPE_SOA:
800 return TypeSOA;
801
802 case TYPE_WKS:
803 return TypeSRV;
804
805 case TYPE_PTR:
806 return TypePTR;
807
808 case TYPE_MX:
809 return TypeMX;
810
811 case TYPE_ANY:
812 return TypeAny;
813
814 default:
815 return "Unknown";
816 }
817 }
818
819 USHORT TypeNametoTypeID( PCHAR TypeName )
820 {
821 if( !strncmp( TypeName, TypeA, strlen( TypeA ) ) ) return TYPE_A;
822 if( !strncmp( TypeName, TypeNS, strlen( TypeNS ) ) ) return TYPE_NS;
823 if( !strncmp( TypeName, TypeCNAME, strlen( TypeCNAME ) ) ) return TYPE_CNAME;
824 if( !strncmp( TypeName, TypeSOA, strlen( TypeSOA ) ) ) return TYPE_SOA;
825 if( !strncmp( TypeName, TypeSRV, strlen( TypeSRV ) ) ) return TYPE_WKS;
826 if( !strncmp( TypeName, TypePTR, strlen( TypePTR ) ) ) return TYPE_PTR;
827 if( !strncmp( TypeName, TypeMX, strlen( TypeMX ) ) ) return TYPE_MX;
828 if( !strncmp( TypeName, TypeAny, strlen( TypeAny ) ) ) return TYPE_ANY;
829
830 return 0;
831 }
832
833 PCHAR ClassIDtoClassName( USHORT ClassID )
834 {
835 switch( ClassID )
836 {
837 case CLASS_IN:
838 return ClassIN;
839
840 case CLASS_ANY:
841 return ClassAny;
842
843 default:
844 return "Unknown";
845 }
846 }
847
848 USHORT ClassNametoClassID( PCHAR ClassName )
849 {
850 if( !strncmp( ClassName, ClassIN, strlen( ClassIN ) ) ) return CLASS_IN;
851 if( !strncmp( ClassName, ClassAny, strlen( ClassAny ) ) ) return CLASS_ANY;
852
853 return 0;
854 }