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