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