Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygennslookup.c
Go to the documentation of this file.
00001 /* 00002 * PROJECT: ReactOS nslookup utility 00003 * LICENSE: GPL - See COPYING in the top level directory 00004 * FILE: applications/network/nslookup/nslookup.c 00005 * PURPOSE: Perform DNS lookups 00006 * COPYRIGHT: Copyright 2009 Lucas Suggs <lucas.suggs@gmail.com> 00007 */ 00008 00009 #include "nslookup.h" 00010 00011 STATE State; 00012 HANDLE ProcessHeap; 00013 ULONG RequestID; 00014 00015 void PrintState() 00016 { 00017 _tprintf( _T("Default Server: (null)\n\n") ); 00018 _tprintf( _T("Set options:\n") ); 00019 00020 _tprintf( _T(" ") ); 00021 if( !State.debug ) _tprintf( _T("no") ); 00022 _tprintf( _T("debug\n") ); 00023 00024 _tprintf( _T(" ") ); 00025 if( !State.defname ) _tprintf( _T("no") ); 00026 _tprintf( _T("defname\n") ); 00027 00028 _tprintf( _T(" ") ); 00029 if( !State.search ) _tprintf( _T("no") ); 00030 _tprintf( _T("search\n") ); 00031 00032 _tprintf( _T(" ") ); 00033 if( !State.recurse ) _tprintf( _T("no") ); 00034 _tprintf( _T("recurse\n") ); 00035 00036 _tprintf( _T(" ") ); 00037 if( !State.d2 ) _tprintf( _T("no") ); 00038 _tprintf( _T("d2\n") ); 00039 00040 _tprintf( _T(" ") ); 00041 if( !State.vc ) _tprintf( _T("no") ); 00042 _tprintf( _T("vc\n") ); 00043 00044 _tprintf( _T(" ") ); 00045 if( !State.ignoretc ) _tprintf( _T("no") ); 00046 _tprintf( _T("ignoretc\n") ); 00047 00048 _tprintf( _T(" port=%d\n"), State.port ); 00049 _tprintf( _T(" type=%s\n"), State.type ); 00050 _tprintf( _T(" class=%s\n"), State.Class ); 00051 _tprintf( _T(" timeout=%d\n"), (int)State.timeout ); 00052 _tprintf( _T(" retry=%d\n"), (int)State.retry ); 00053 _tprintf( _T(" root=%s\n"), State.root ); 00054 _tprintf( _T(" domain=%s\n"), State.domain ); 00055 00056 _tprintf( _T(" ") ); 00057 if( !State.MSxfr ) _tprintf( _T("no") ); 00058 _tprintf( _T("MSxfr\n") ); 00059 00060 _tprintf( _T(" IXFRversion=%d\n"), (int)State.ixfrver ); 00061 00062 _tprintf( _T(" srchlist=%s\n\n"), State.srchlist[0] ); 00063 } 00064 00065 void PrintUsage() 00066 { 00067 _tprintf( _T("Usage:\n" 00068 " nslookup [-opt ...] # interactive mode using" 00069 " default server\n nslookup [-opt ...] - server #" 00070 " interactive mode using 'server'\n nslookup [-opt ...]" 00071 " host # just look up 'host' using default server\n" 00072 " nslookup [-opt ...] host server # just look up 'host'" 00073 " using 'server'\n") ); 00074 } 00075 00076 BOOL PerformInternalLookup( PCHAR pAddr, PCHAR pResult ) 00077 { 00078 /* Needed to issue DNS packets and parse them. */ 00079 PCHAR Buffer = NULL, RecBuffer = NULL; 00080 CHAR pResolve[256]; 00081 ULONG BufferLength = 0, RecBufferLength = 512; 00082 int i = 0, j = 0, k = 0, d = 0; 00083 BOOL bOk = FALSE; 00084 00085 /* Makes things easier when parsing the response packet. */ 00086 USHORT NumQuestions; 00087 USHORT Type; 00088 00089 if( (strlen( pAddr ) + 1) > 255 ) return FALSE; 00090 00091 Type = TYPE_A; 00092 if( IsValidIP( pAddr ) ) Type = TYPE_PTR; 00093 00094 /* If it's a PTR lookup then append the ARPA sig to the end. */ 00095 if( Type == TYPE_PTR ) 00096 { 00097 ReverseIP( pAddr, pResolve ); 00098 strcat( pResolve, ARPA_SIG ); 00099 } 00100 else 00101 { 00102 strcpy( pResolve, pAddr ); 00103 } 00104 00105 /* Base header length + length of QNAME + length of QTYPE and QCLASS */ 00106 BufferLength = 12 + (strlen( pResolve ) + 2) + 4; 00107 00108 /* Allocate memory for the buffer. */ 00109 Buffer = HeapAlloc( ProcessHeap, 0, BufferLength ); 00110 if( !Buffer ) 00111 { 00112 _tprintf( _T("ERROR: Out of memory\n") ); 00113 goto cleanup; 00114 } 00115 00116 /* Allocate the receiving buffer. */ 00117 RecBuffer = HeapAlloc( ProcessHeap, 0, RecBufferLength ); 00118 if( !RecBuffer ) 00119 { 00120 _tprintf( _T("ERROR: Out of memory\n") ); 00121 goto cleanup; 00122 } 00123 00124 /* Insert the ID field. */ 00125 ((PSHORT)&Buffer[i])[0] = htons( RequestID ); 00126 i += 2; 00127 00128 /* Bits 0-7 of the second 16 are all 0, except for when recursion is 00129 desired. */ 00130 Buffer[i] = 0x00; 00131 if( State.recurse) Buffer[i] |= 0x01; 00132 i += 1; 00133 00134 /* Bits 8-15 of the second 16 are 0 for a query. */ 00135 Buffer[i] = 0x00; 00136 i += 1; 00137 00138 /* Only 1 question. */ 00139 ((PSHORT)&Buffer[i])[0] = htons( 1 ); 00140 i += 2; 00141 00142 /* We aren't sending a response, so 0 out the rest of the header. */ 00143 Buffer[i] = 0x00; 00144 Buffer[i + 1] = 0x00; 00145 Buffer[i + 2] = 0x00; 00146 Buffer[i + 3] = 0x00; 00147 Buffer[i + 4] = 0x00; 00148 Buffer[i + 5] = 0x00; 00149 i += 6; 00150 00151 /* Walk through the query address. Split each section delimited by '.'. 00152 Format of the QNAME section is length|data, etc. Last one is null */ 00153 j = i; 00154 i += 1; 00155 00156 for( k = 0; k < strlen( pResolve ); k += 1 ) 00157 { 00158 if( pResolve[k] != '.' ) 00159 { 00160 Buffer[i] = pResolve[k]; 00161 i += 1; 00162 } 00163 else 00164 { 00165 Buffer[j] = (i - j) - 1; 00166 j = i; 00167 i += 1; 00168 } 00169 } 00170 00171 Buffer[j] = (i - j) - 1; 00172 Buffer[i] = 0x00; 00173 i += 1; 00174 00175 /* QTYPE */ 00176 ((PSHORT)&Buffer[i])[0] = htons( Type ); 00177 i += 2; 00178 00179 /* QCLASS */ 00180 ((PSHORT)&Buffer[i])[0] = htons( CLASS_IN ); 00181 00182 /* Ship the request off to the DNS server. */ 00183 bOk = SendRequest( Buffer, 00184 BufferLength, 00185 RecBuffer, 00186 &RecBufferLength ); 00187 if( !bOk ) goto cleanup; 00188 00189 /* Start parsing the received packet. */ 00190 NumQuestions = ntohs( ((PSHORT)&RecBuffer[4])[0] ); 00191 00192 k = 12; 00193 00194 /* We don't care about the questions section, blow through it. */ 00195 if( NumQuestions ) 00196 { 00197 for( i = 0; i < NumQuestions; i += 1 ) 00198 { 00199 /* Quick way to skip the domain name section. */ 00200 k += ExtractName( RecBuffer, pResult, k, 0 ); 00201 k += 4; 00202 } 00203 } 00204 00205 /* Skip the answer name. */ 00206 k += ExtractName( RecBuffer, pResult, k, 0 ); 00207 00208 Type = ntohs( ((PUSHORT)&RecBuffer[k])[0] ); 00209 k += 8; 00210 00211 d = ntohs( ((PUSHORT)&RecBuffer[k])[0] ); 00212 k += 2; 00213 00214 if( TYPE_PTR == Type ) 00215 { 00216 k += ExtractName( RecBuffer, pResult, k, d ); 00217 } 00218 else if( TYPE_A == Type ) 00219 { 00220 k += ExtractIP( RecBuffer, pResult, k ); 00221 } 00222 00223 cleanup: 00224 /* Free memory. */ 00225 if( Buffer ) HeapFree( ProcessHeap, 0, Buffer ); 00226 if( RecBuffer ) HeapFree( ProcessHeap, 0, RecBuffer ); 00227 00228 RequestID += 1; 00229 00230 return bOk; 00231 } 00232 00233 void PerformLookup( PCHAR pAddr ) 00234 { 00235 /* Needed to issue DNS packets and parse them. */ 00236 PCHAR Buffer = NULL, RecBuffer = NULL; 00237 CHAR pResolve[256]; 00238 CHAR pResult[256]; 00239 ULONG BufferLength = 0, RecBufferLength = 512; 00240 int i = 0, j = 0, k = 0, d = 0; 00241 BOOL bOk = FALSE; 00242 00243 /* Makes things easier when parsing the response packet. */ 00244 UCHAR Header2; 00245 USHORT NumQuestions; 00246 USHORT NumAnswers; 00247 USHORT NumAuthority; 00248 USHORT Type; 00249 00250 if( (strlen( pAddr ) + 1) > 255 ) return; 00251 00252 _tprintf( _T("Server: %s\n"), State.DefaultServer ); 00253 _tprintf( _T("Address: %s\n\n"), State.DefaultServerAddress ); 00254 00255 if( !strcmp( TypeA, State.type ) 00256 || !strcmp( TypeAAAA, State.type ) 00257 || !strcmp( TypeBoth, State.type ) ) 00258 { 00259 Type = TYPE_A; 00260 if( IsValidIP( pAddr ) ) Type = TYPE_PTR; 00261 } 00262 else 00263 Type = TypeNametoTypeID( State.type ); 00264 00265 /* If it's a PTR lookup then append the ARPA sig to the end. */ 00266 if( (Type == TYPE_PTR) && IsValidIP( pAddr ) ) 00267 { 00268 ReverseIP( pAddr, pResolve ); 00269 strcat( pResolve, ARPA_SIG ); 00270 } 00271 else 00272 { 00273 strcpy( pResolve, pAddr ); 00274 } 00275 00276 /* Base header length + length of QNAME + length of QTYPE and QCLASS */ 00277 BufferLength = 12 + (strlen( pResolve ) + 2) + 4; 00278 00279 /* Allocate memory for the buffer. */ 00280 Buffer = HeapAlloc( ProcessHeap, 0, BufferLength ); 00281 if( !Buffer ) 00282 { 00283 _tprintf( _T("ERROR: Out of memory\n") ); 00284 goto cleanup; 00285 } 00286 00287 /* Allocate memory for the return buffer. */ 00288 RecBuffer = HeapAlloc( ProcessHeap, 0, RecBufferLength ); 00289 if( !RecBuffer ) 00290 { 00291 _tprintf( _T("ERROR: Out of memory\n") ); 00292 goto cleanup; 00293 } 00294 00295 /* Insert the ID field. */ 00296 ((PSHORT)&Buffer[i])[0] = htons( RequestID ); 00297 i += 2; 00298 00299 /* Bits 0-7 of the second 16 are all 0, except for when recursion is 00300 desired. */ 00301 Buffer[i] = 0x00; 00302 if( State.recurse) Buffer[i] |= 0x01; 00303 i += 1; 00304 00305 /* Bits 8-15 of the second 16 are 0 for a query. */ 00306 Buffer[i] = 0x00; 00307 i += 1; 00308 00309 /* Only 1 question. */ 00310 ((PSHORT)&Buffer[i])[0] = htons( 1 ); 00311 i += 2; 00312 00313 /* We aren't sending a response, so 0 out the rest of the header. */ 00314 Buffer[i] = 0x00; 00315 Buffer[i + 1] = 0x00; 00316 Buffer[i + 2] = 0x00; 00317 Buffer[i + 3] = 0x00; 00318 Buffer[i + 4] = 0x00; 00319 Buffer[i + 5] = 0x00; 00320 i += 6; 00321 00322 /* Walk through the query address. Split each section delimited by '.'. 00323 Format of the QNAME section is length|data, etc. Last one is null */ 00324 j = i; 00325 i += 1; 00326 00327 for( k = 0; k < strlen( pResolve ); k += 1 ) 00328 { 00329 if( pResolve[k] != '.' ) 00330 { 00331 Buffer[i] = pResolve[k]; 00332 i += 1; 00333 } 00334 else 00335 { 00336 Buffer[j] = (i - j) - 1; 00337 j = i; 00338 i += 1; 00339 } 00340 } 00341 00342 Buffer[j] = (i - j) - 1; 00343 Buffer[i] = 0x00; 00344 i += 1; 00345 00346 /* QTYPE */ 00347 ((PSHORT)&Buffer[i])[0] = htons( Type ); 00348 i += 2; 00349 00350 /* QCLASS */ 00351 ((PSHORT)&Buffer[i])[0] = htons( ClassNametoClassID( State.Class ) ); 00352 00353 /* Ship off the request to the DNS server. */ 00354 bOk = SendRequest( Buffer, 00355 BufferLength, 00356 RecBuffer, 00357 &RecBufferLength ); 00358 if( !bOk ) goto cleanup; 00359 00360 /* Start parsing the received packet. */ 00361 Header2 = RecBuffer[3]; 00362 NumQuestions = ntohs( ((PSHORT)&RecBuffer[4])[0] ); 00363 NumAnswers = ntohs( ((PSHORT)&RecBuffer[6])[0] ); 00364 NumAuthority = ntohs( ((PUSHORT)&RecBuffer[8])[0] ); 00365 Type = 0; 00366 00367 /* Check the RCODE for failure. */ 00368 d = Header2 & 0x0F; 00369 if( d != RCODE_NOERROR ) 00370 { 00371 switch( d ) 00372 { 00373 case RCODE_NXDOMAIN: 00374 _tprintf( _T("*** %s can't find %s: Non-existant domain\n"), State.DefaultServer, pAddr ); 00375 break; 00376 00377 case RCODE_REFUSED: 00378 _tprintf( _T("*** %s can't find %s: Query refused\n"), State.DefaultServer, pAddr ); 00379 break; 00380 00381 default: 00382 _tprintf( _T("*** %s can't find %s: Unknown RCODE\n"), State.DefaultServer, pAddr ); 00383 } 00384 00385 goto cleanup; 00386 } 00387 00388 k = 12; 00389 00390 if( NumQuestions ) 00391 { 00392 /* Blow through the questions section since we don't care about it. */ 00393 for( i = 0; i < NumQuestions; i += 1 ) 00394 { 00395 k += ExtractName( RecBuffer, pResult, k, 0 ); 00396 k += 4; 00397 } 00398 } 00399 00400 if( NumAnswers ) 00401 { 00402 /* Skip the name. */ 00403 k += ExtractName( RecBuffer, pResult, k, 0 ); 00404 00405 Type = ntohs( ((PUSHORT)&RecBuffer[k])[0] ); 00406 k += 8; 00407 00408 d = ntohs( ((PUSHORT)&RecBuffer[k])[0] ); 00409 k += 2; 00410 00411 if( TYPE_PTR == Type ) 00412 { 00413 k += ExtractName( RecBuffer, pResult, k, d ); 00414 } 00415 else if( TYPE_A == Type ) 00416 { 00417 k += ExtractIP( RecBuffer, pResult, k ); 00418 } 00419 } 00420 00421 /* FIXME: This'll need to support more than PTR and A at some point. */ 00422 if( !strcmp( State.type, TypePTR ) ) 00423 { 00424 if( TYPE_PTR == Type ) 00425 { 00426 _tprintf( _T("%s name = %s\n"), pResolve, pResult ); 00427 } 00428 else 00429 { 00430 } 00431 } 00432 else if( !strcmp( State.type, TypeA ) 00433 || !strcmp( State.type, TypeAAAA ) 00434 || !strcmp( State.type, TypeBoth ) ) 00435 { 00436 if( (TYPE_A == Type) /*|| (TYPE_AAAA == Type)*/ ) 00437 { 00438 if( 0 == NumAuthority ) 00439 _tprintf( _T("Non-authoritative answer:\n") ); 00440 00441 _tprintf( _T("Name: %s\n"), pAddr ); 00442 _tprintf( _T("Address: %s\n\n"), pResult ); 00443 } 00444 else 00445 { 00446 _tprintf( _T("Name: %s\n"), pResult ); 00447 _tprintf( _T("Address: %s\n\n"), pAddr ); 00448 } 00449 } 00450 00451 cleanup: 00452 /* Free memory. */ 00453 if( Buffer ) HeapFree( ProcessHeap, 0, Buffer ); 00454 if( RecBuffer ) HeapFree( ProcessHeap, 0, RecBuffer ); 00455 00456 RequestID += 1; 00457 } 00458 00459 BOOL ParseCommandLine( int argc, char* argv[] ) 00460 { 00461 int i; 00462 BOOL NoMoreOptions = FALSE; 00463 BOOL Interactive = FALSE; 00464 CHAR AddrToResolve[256]; 00465 CHAR Server[256]; 00466 00467 RtlZeroMemory( AddrToResolve, 256 ); 00468 RtlZeroMemory( Server, 256 ); 00469 00470 if( 2 == argc ) 00471 { 00472 /* In the Windows nslookup, usage is only displayed if /? is the only 00473 option specified on the command line. */ 00474 if( !strncmp( "/?", argv[1], 2 ) ) 00475 { 00476 PrintUsage(); 00477 return 0; 00478 } 00479 } 00480 00481 if( argc > 1 ) 00482 { 00483 for( i = 1; i < argc; i += 1 ) 00484 { 00485 if( NoMoreOptions ) 00486 { 00487 strncpy( Server, argv[i], 255 ); 00488 00489 /* Determine which one to resolve. This is based on whether the 00490 DNS server provided was an IP or an FQDN. */ 00491 if( IsValidIP( Server ) ) 00492 { 00493 strncpy( State.DefaultServerAddress, Server, 16 ); 00494 00495 PerformInternalLookup( State.DefaultServerAddress, 00496 State.DefaultServer ); 00497 } 00498 else 00499 { 00500 strncpy( State.DefaultServer, Server, 255 ); 00501 00502 PerformInternalLookup( State.DefaultServer, 00503 State.DefaultServerAddress ); 00504 } 00505 00506 if( Interactive ) return 1; 00507 00508 PerformLookup( AddrToResolve ); 00509 00510 return 0; 00511 } 00512 else 00513 { 00514 if( !strncmp( "-all", argv[i], 4 ) ) 00515 { 00516 PrintState(); 00517 } 00518 else if( !strncmp( "-type=", argv[i], 6 ) ) 00519 { 00520 if( !strncmp( TypeA, &argv[i][6], strlen( TypeA ) ) ) 00521 { 00522 State.type = TypeA; 00523 } 00524 else if( !strncmp( TypeAAAA, &argv[i][6], strlen( TypeAAAA ) ) ) 00525 { 00526 State.type = TypeAAAA; 00527 } 00528 else if( !strncmp( TypeBoth, &argv[i][6], strlen( TypeBoth ) ) ) 00529 { 00530 State.type = TypeBoth; 00531 } 00532 else if( !strncmp( TypeAny, &argv[i][6], strlen( TypeAny ) ) ) 00533 { 00534 State.type = TypeAny; 00535 } 00536 else if( !strncmp( TypeCNAME, &argv[i][6], strlen( TypeCNAME ) ) ) 00537 { 00538 State.type = TypeCNAME; 00539 } 00540 else if( !strncmp( TypeMX, &argv[i][6], strlen( TypeMX ) ) ) 00541 { 00542 State.type = TypeMX; 00543 } 00544 else if( !strncmp( TypeNS, &argv[i][6], strlen( TypeNS ) ) ) 00545 { 00546 State.type = TypeNS; 00547 } 00548 else if( !strncmp( TypePTR, &argv[i][6], strlen( TypePTR ) ) ) 00549 { 00550 State.type = TypePTR; 00551 } 00552 else if( !strncmp( TypeSOA, &argv[i][6], strlen( TypeSOA ) ) ) 00553 { 00554 State.type = TypeSOA; 00555 } 00556 else if( !strncmp( TypeSRV, &argv[i][6], strlen( TypeSRV ) ) ) 00557 { 00558 State.type = TypeSRV; 00559 } 00560 else 00561 { 00562 _tprintf( _T("unknown query type: %s"), &argv[i][6] ); 00563 } 00564 } 00565 else if( !strncmp( "-domain=", argv[i], 8 ) ) 00566 { 00567 strcpy( State.domain, &argv[i][8] ); 00568 } 00569 else if( !strncmp( "-srchlist=", argv[i], 10 ) ) 00570 { 00571 } 00572 else if( !strncmp( "-root=", argv[i], 6 ) ) 00573 { 00574 strcpy( State.root, &argv[i][6] ); 00575 } 00576 else if( !strncmp( "-retry=", argv[i], 7 ) ) 00577 { 00578 } 00579 else if( !strncmp( "-timeout=", argv[i], 9 ) ) 00580 { 00581 } 00582 else if( !strncmp( "-querytype=", argv[i], 11 ) ) 00583 { 00584 if( !strncmp( TypeA, &argv[i][11], strlen( TypeA ) ) ) 00585 { 00586 State.type = TypeA; 00587 } 00588 else if( !strncmp( TypeAAAA, &argv[i][11], strlen( TypeAAAA ) ) ) 00589 { 00590 State.type = TypeAAAA; 00591 } 00592 else if( !strncmp( TypeBoth, &argv[i][11], strlen( TypeBoth ) ) ) 00593 { 00594 State.type = TypeBoth; 00595 } 00596 else if( !strncmp( TypeAny, &argv[i][11], strlen( TypeAny ) ) ) 00597 { 00598 State.type = TypeAny; 00599 } 00600 else if( !strncmp( TypeCNAME, &argv[i][11], strlen( TypeCNAME ) ) ) 00601 { 00602 State.type = TypeCNAME; 00603 } 00604 else if( !strncmp( TypeMX, &argv[i][11], strlen( TypeMX ) ) ) 00605 { 00606 State.type = TypeMX; 00607 } 00608 else if( !strncmp( TypeNS, &argv[i][11], strlen( TypeNS ) ) ) 00609 { 00610 State.type = TypeNS; 00611 } 00612 else if( !strncmp( TypePTR, &argv[i][11], strlen( TypePTR ) ) ) 00613 { 00614 State.type = TypePTR; 00615 } 00616 else if( !strncmp( TypeSOA, &argv[i][11], strlen( TypeSOA ) ) ) 00617 { 00618 State.type = TypeSOA; 00619 } 00620 else if( !strncmp( TypeSRV, &argv[i][11], strlen( TypeSRV ) ) ) 00621 { 00622 State.type = TypeSRV; 00623 } 00624 else 00625 { 00626 _tprintf( _T("unknown query type: %s"), &argv[i][6] ); 00627 } 00628 } 00629 else if( !strncmp( "-class=", argv[i], 7 ) ) 00630 { 00631 if( !strncmp( ClassIN, &argv[i][7], strlen( ClassIN ) ) ) 00632 { 00633 State.Class = ClassIN; 00634 } 00635 else if( !strncmp( ClassAny, &argv[i][7], strlen( ClassAny ) ) ) 00636 { 00637 State.Class = ClassAny; 00638 } 00639 else 00640 { 00641 _tprintf( _T("unknown query class: %s"), &argv[i][7] ); 00642 } 00643 } 00644 else if( !strncmp( "-ixfrver=", argv[i], 9 ) ) 00645 { 00646 } 00647 else if( !strncmp( "-debug", argv[i], 6 ) ) 00648 { 00649 State.debug = TRUE; 00650 } 00651 else if( !strncmp( "-nodebug", argv[i], 8 ) ) 00652 { 00653 State.debug = FALSE; 00654 State.d2 = FALSE; 00655 } 00656 else if( !strncmp( "-d2", argv[i], 3 ) ) 00657 { 00658 State.d2 = TRUE; 00659 State.debug = TRUE; 00660 } 00661 else if( !strncmp( "-nod2", argv[i], 5 ) ) 00662 { 00663 if( State.debug ) _tprintf( _T("d2 mode disabled; still in debug mode\n") ); 00664 00665 State.d2 = FALSE; 00666 } 00667 else if( !strncmp( "-defname", argv[i], 8 ) ) 00668 { 00669 State.defname = TRUE; 00670 } 00671 else if( !strncmp( "-noddefname", argv[i], 10 ) ) 00672 { 00673 State.defname = FALSE; 00674 } 00675 else if( !strncmp( "-recurse", argv[i], 8 ) ) 00676 { 00677 State.recurse = TRUE; 00678 } 00679 else if( !strncmp( "-norecurse", argv[i], 10 ) ) 00680 { 00681 State.recurse = FALSE; 00682 } 00683 else if( !strncmp( "-search", argv[i], 7 ) ) 00684 { 00685 State.search = TRUE; 00686 } 00687 else if( !strncmp( "-nosearch", argv[i], 9 ) ) 00688 { 00689 State.search = FALSE; 00690 } 00691 else if( !strncmp( "-vc", argv[i], 3 ) ) 00692 { 00693 State.vc = TRUE; 00694 } 00695 else if( !strncmp( "-novc", argv[i], 5 ) ) 00696 { 00697 State.vc = FALSE; 00698 } 00699 else if( !strncmp( "-msxfr", argv[i], 6 ) ) 00700 { 00701 State.MSxfr = TRUE; 00702 } 00703 else if( !strncmp( "-nomsxfr", argv[i], 8 ) ) 00704 { 00705 State.MSxfr = FALSE; 00706 } 00707 else if( !strncmp( "-", argv[i], 1 ) && (strlen( argv[i] ) == 1) ) 00708 { 00709 /* Since we received just the plain - switch, we are going 00710 to be entering interactive mode. We also will not be 00711 parsing any more options. */ 00712 NoMoreOptions = TRUE; 00713 Interactive = TRUE; 00714 } 00715 else 00716 { 00717 /* Grab the address to resolve. No more options accepted 00718 past this point. */ 00719 strncpy( AddrToResolve, argv[i], 255 ); 00720 NoMoreOptions = TRUE; 00721 } 00722 } 00723 } 00724 00725 if( NoMoreOptions && !Interactive ) 00726 { 00727 /* Get the FQDN of the DNS server. */ 00728 PerformInternalLookup( State.DefaultServerAddress, 00729 State.DefaultServer ); 00730 00731 PerformLookup( AddrToResolve ); 00732 00733 return 0; 00734 } 00735 } 00736 00737 /* Get the FQDN of the DNS server. */ 00738 PerformInternalLookup( State.DefaultServerAddress, 00739 State.DefaultServer ); 00740 00741 return 1; 00742 } 00743 00744 void InteractiveMode() 00745 { 00746 _tprintf( _T("Default Server: %s\n"), State.DefaultServer ); 00747 _tprintf( _T("Address: %s\n\n"), State.DefaultServerAddress ); 00748 00749 /* TODO: Implement interactive mode. */ 00750 00751 _tprintf( _T("ERROR: Feature not implemented.\n") ); 00752 } 00753 00754 int main( int argc, char* argv[] ) 00755 { 00756 int i; 00757 ULONG Status; 00758 PFIXED_INFO pNetInfo = NULL; 00759 ULONG NetBufLen = 0; 00760 WSADATA wsaData; 00761 00762 ProcessHeap = GetProcessHeap(); 00763 RequestID = 1; 00764 00765 /* Set up the initial state. */ 00766 State.debug = FALSE; 00767 State.defname = TRUE; 00768 State.search = TRUE; 00769 State.recurse = TRUE; 00770 State.d2 = FALSE; 00771 State.vc = FALSE; 00772 State.ignoretc = FALSE; 00773 State.port = 53; 00774 State.type = TypeBoth; 00775 State.Class = ClassIN; 00776 State.timeout = 2; 00777 State.retry = 1; 00778 State.MSxfr = TRUE; 00779 State.ixfrver = 1; 00780 00781 RtlZeroMemory( State.root, 256 ); 00782 RtlZeroMemory( State.domain, 256 ); 00783 for( i = 0; i < 6; i += 1 ) RtlZeroMemory( State.srchlist[i], 256 ); 00784 RtlZeroMemory( State.DefaultServer, 256 ); 00785 RtlZeroMemory( State.DefaultServerAddress, 16 ); 00786 00787 memcpy( State.root, DEFAULT_ROOT, sizeof(DEFAULT_ROOT) ); 00788 00789 /* We don't know how long of a buffer it will want to return. So we'll 00790 pass an empty one now and let it fail only once, instead of guessing. */ 00791 Status = GetNetworkParams( pNetInfo, &NetBufLen ); 00792 if( Status == ERROR_BUFFER_OVERFLOW ) 00793 { 00794 pNetInfo = (PFIXED_INFO)HeapAlloc( ProcessHeap, 0, NetBufLen ); 00795 if( pNetInfo == NULL ) 00796 { 00797 _tprintf( _T("ERROR: Out of memory\n") ); 00798 00799 return -1; 00800 } 00801 00802 /* For real this time. */ 00803 Status = GetNetworkParams( pNetInfo, &NetBufLen ); 00804 if( Status != NO_ERROR ) 00805 { 00806 _tprintf( _T("Error in GetNetworkParams call\n") ); 00807 00808 HeapFree( ProcessHeap, 0, pNetInfo ); 00809 00810 return -2; 00811 } 00812 } 00813 00814 strncpy( State.domain, pNetInfo->DomainName, 255 ); 00815 strncpy( State.srchlist[0], pNetInfo->DomainName, 255 ); 00816 strncpy( State.DefaultServerAddress, 00817 pNetInfo->DnsServerList.IpAddress.String, 00818 15 ); 00819 00820 HeapFree( ProcessHeap, 0, pNetInfo ); 00821 00822 WSAStartup( MAKEWORD(2,2), &wsaData ); 00823 00824 switch( ParseCommandLine( argc, argv ) ) 00825 { 00826 case 0: 00827 /* This means that it was a /? parameter. */ 00828 break; 00829 00830 default: 00831 /* Anything else means we enter interactive mode. The only exception 00832 to this is when the host to resolve was provided on the command 00833 line. */ 00834 InteractiveMode(); 00835 } 00836 00837 WSACleanup(); 00838 return 0; 00839 } Generated on Sat May 26 2012 04:16:10 for ReactOS by
1.7.6.1
|