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 } 855