1c2c66affSColin Finck /*
2c2c66affSColin Finck  * PROJECT:     ReactOS nslookup utility
3c2c66affSColin Finck  * LICENSE:     GPL - See COPYING in the top level directory
4c2c66affSColin Finck  * FILE:        base/applications/network/nslookup/nslookup.c
5c2c66affSColin Finck  * PURPOSE:     Perform DNS lookups
6c2c66affSColin Finck  * COPYRIGHT:   Copyright 2009 Lucas Suggs <lucas.suggs@gmail.com>
7c2c66affSColin Finck  */
8c2c66affSColin Finck 
9c2c66affSColin Finck #include "nslookup.h"
10c2c66affSColin Finck 
11c2c66affSColin Finck #include <winbase.h>
12c2c66affSColin Finck #include <iphlpapi.h>
13c2c66affSColin Finck 
14c2c66affSColin Finck STATE   State;
15c2c66affSColin Finck HANDLE  ProcessHeap;
16c2c66affSColin Finck ULONG   RequestID;
17c2c66affSColin Finck 
PrintState()18c2c66affSColin Finck void PrintState()
19c2c66affSColin Finck {
20c2c66affSColin Finck     _tprintf( _T("Default Server:  (null)\n\n") );
21c2c66affSColin Finck     _tprintf( _T("Set options:\n") );
22c2c66affSColin Finck 
23c2c66affSColin Finck     _tprintf( _T("  ") );
24c2c66affSColin Finck     if( !State.debug ) _tprintf( _T("no") );
25c2c66affSColin Finck     _tprintf( _T("debug\n") );
26c2c66affSColin Finck 
27c2c66affSColin Finck     _tprintf( _T("  ") );
28c2c66affSColin Finck     if( !State.defname ) _tprintf( _T("no") );
29c2c66affSColin Finck     _tprintf( _T("defname\n") );
30c2c66affSColin Finck 
31c2c66affSColin Finck     _tprintf( _T("  ") );
32c2c66affSColin Finck     if( !State.search ) _tprintf( _T("no") );
33c2c66affSColin Finck     _tprintf( _T("search\n") );
34c2c66affSColin Finck 
35c2c66affSColin Finck     _tprintf( _T("  ") );
36c2c66affSColin Finck     if( !State.recurse ) _tprintf( _T("no") );
37c2c66affSColin Finck     _tprintf( _T("recurse\n") );
38c2c66affSColin Finck 
39c2c66affSColin Finck     _tprintf( _T("  ") );
40c2c66affSColin Finck     if( !State.d2 ) _tprintf( _T("no") );
41c2c66affSColin Finck     _tprintf( _T("d2\n") );
42c2c66affSColin Finck 
43c2c66affSColin Finck     _tprintf( _T("  ") );
44c2c66affSColin Finck     if( !State.vc ) _tprintf( _T("no") );
45c2c66affSColin Finck     _tprintf( _T("vc\n") );
46c2c66affSColin Finck 
47c2c66affSColin Finck     _tprintf( _T("  ") );
48c2c66affSColin Finck     if( !State.ignoretc ) _tprintf( _T("no") );
49c2c66affSColin Finck     _tprintf( _T("ignoretc\n") );
50c2c66affSColin Finck 
51c2c66affSColin Finck     _tprintf( _T("  port=%d\n"), State.port );
52c2c66affSColin Finck     _tprintf( _T("  type=%s\n"), State.type );
53c2c66affSColin Finck     _tprintf( _T("  class=%s\n"), State.Class );
54c2c66affSColin Finck     _tprintf( _T("  timeout=%d\n"), (int)State.timeout );
55c2c66affSColin Finck     _tprintf( _T("  retry=%d\n"), (int)State.retry );
56c2c66affSColin Finck     _tprintf( _T("  root=%s\n"), State.root );
57c2c66affSColin Finck     _tprintf( _T("  domain=%s\n"), State.domain );
58c2c66affSColin Finck 
59c2c66affSColin Finck     _tprintf( _T("  ") );
60c2c66affSColin Finck     if( !State.MSxfr ) _tprintf( _T("no") );
61c2c66affSColin Finck     _tprintf( _T("MSxfr\n") );
62c2c66affSColin Finck 
63c2c66affSColin Finck     _tprintf( _T("  IXFRversion=%d\n"), (int)State.ixfrver );
64c2c66affSColin Finck 
65c2c66affSColin Finck     _tprintf( _T("  srchlist=%s\n\n"), State.srchlist[0] );
66c2c66affSColin Finck }
67c2c66affSColin Finck 
PrintUsage()68c2c66affSColin Finck void PrintUsage()
69c2c66affSColin Finck {
70c2c66affSColin Finck     _tprintf( _T("Usage:\n"
71c2c66affSColin Finck                  "   nslookup [-opt ...]             # interactive mode using"
72c2c66affSColin Finck                  " default server\n   nslookup [-opt ...] - server    #"
73c2c66affSColin Finck                  " interactive mode using 'server'\n   nslookup [-opt ...]"
74c2c66affSColin Finck                  " host        # just look up 'host' using default server\n"
75c2c66affSColin Finck                  "   nslookup [-opt ...] host server # just look up 'host'"
76c2c66affSColin Finck                  " using 'server'\n") );
77c2c66affSColin Finck }
78c2c66affSColin Finck 
PerformInternalLookup(PCHAR pAddr,PCHAR pResult)79c2c66affSColin Finck BOOL PerformInternalLookup( PCHAR pAddr, PCHAR pResult )
80c2c66affSColin Finck {
81c2c66affSColin Finck     /* Needed to issue DNS packets and parse them. */
82c2c66affSColin Finck     PCHAR Buffer = NULL, RecBuffer = NULL;
83c2c66affSColin Finck     CHAR pResolve[256];
84c2c66affSColin Finck     ULONG BufferLength = 0, RecBufferLength = 512;
85c2c66affSColin Finck     int i = 0, j = 0, k = 0, d = 0;
86c2c66affSColin Finck     BOOL bOk = FALSE;
87c2c66affSColin Finck 
88c2c66affSColin Finck     /* Makes things easier when parsing the response packet. */
89c2c66affSColin Finck     USHORT NumQuestions;
90c2c66affSColin Finck     USHORT Type;
91c2c66affSColin Finck 
92c2c66affSColin Finck     if( (strlen( pAddr ) + 1) > 255 ) return FALSE;
93c2c66affSColin Finck 
94c2c66affSColin Finck     Type = TYPE_A;
95c2c66affSColin Finck     if( IsValidIP( pAddr ) ) Type = TYPE_PTR;
96c2c66affSColin Finck 
97c2c66affSColin Finck     /* If it's a PTR lookup then append the ARPA sig to the end. */
98c2c66affSColin Finck     if( Type == TYPE_PTR )
99c2c66affSColin Finck     {
100c2c66affSColin Finck         ReverseIP( pAddr, pResolve );
101c2c66affSColin Finck         strcat( pResolve, ARPA_SIG );
102c2c66affSColin Finck     }
103c2c66affSColin Finck     else
104c2c66affSColin Finck     {
105c2c66affSColin Finck         strcpy( pResolve, pAddr );
106c2c66affSColin Finck     }
107c2c66affSColin Finck 
108c2c66affSColin Finck     /* Base header length + length of QNAME + length of QTYPE and QCLASS */
109c2c66affSColin Finck     BufferLength = 12 + (strlen( pResolve ) + 2) + 4;
110c2c66affSColin Finck 
111c2c66affSColin Finck     /* Allocate memory for the buffer. */
112c2c66affSColin Finck     Buffer = HeapAlloc( ProcessHeap, 0, BufferLength );
113c2c66affSColin Finck     if( !Buffer )
114c2c66affSColin Finck     {
115c2c66affSColin Finck         _tprintf( _T("ERROR: Out of memory\n") );
116c2c66affSColin Finck         goto cleanup;
117c2c66affSColin Finck     }
118c2c66affSColin Finck 
119c2c66affSColin Finck     /* Allocate the receiving buffer. */
120c2c66affSColin Finck     RecBuffer = HeapAlloc( ProcessHeap, 0, RecBufferLength );
121c2c66affSColin Finck     if( !RecBuffer )
122c2c66affSColin Finck     {
123c2c66affSColin Finck         _tprintf( _T("ERROR: Out of memory\n") );
124c2c66affSColin Finck         goto cleanup;
125c2c66affSColin Finck     }
126c2c66affSColin Finck 
127c2c66affSColin Finck     /* Insert the ID field. */
128c2c66affSColin Finck     ((PSHORT)&Buffer[i])[0] = htons( RequestID );
129c2c66affSColin Finck     i += 2;
130c2c66affSColin Finck 
131c2c66affSColin Finck     /* Bits 0-7 of the second 16 are all 0, except for when recursion is
132c2c66affSColin Finck        desired. */
133c2c66affSColin Finck     Buffer[i] = 0x00;
134c2c66affSColin Finck     if( State.recurse) Buffer[i] |= 0x01;
135c2c66affSColin Finck     i += 1;
136c2c66affSColin Finck 
137c2c66affSColin Finck     /* Bits 8-15 of the second 16 are 0 for a query. */
138c2c66affSColin Finck     Buffer[i] = 0x00;
139c2c66affSColin Finck     i += 1;
140c2c66affSColin Finck 
141c2c66affSColin Finck     /* Only 1 question. */
142c2c66affSColin Finck     ((PSHORT)&Buffer[i])[0] = htons( 1 );
143c2c66affSColin Finck     i += 2;
144c2c66affSColin Finck 
145c2c66affSColin Finck     /* We aren't sending a response, so 0 out the rest of the header. */
146c2c66affSColin Finck     Buffer[i] = 0x00;
147c2c66affSColin Finck     Buffer[i + 1] = 0x00;
148c2c66affSColin Finck     Buffer[i + 2] = 0x00;
149c2c66affSColin Finck     Buffer[i + 3] = 0x00;
150c2c66affSColin Finck     Buffer[i + 4] = 0x00;
151c2c66affSColin Finck     Buffer[i + 5] = 0x00;
152c2c66affSColin Finck     i += 6;
153c2c66affSColin Finck 
154c2c66affSColin Finck     /* Walk through the query address. Split each section delimited by '.'.
155c2c66affSColin Finck        Format of the QNAME section is length|data, etc. Last one is null */
156c2c66affSColin Finck     j = i;
157c2c66affSColin Finck     i += 1;
158c2c66affSColin Finck 
159c2c66affSColin Finck     for( k = 0; k < strlen( pResolve ); k += 1 )
160c2c66affSColin Finck     {
161c2c66affSColin Finck         if( pResolve[k] != '.' )
162c2c66affSColin Finck         {
163c2c66affSColin Finck             Buffer[i] = pResolve[k];
164c2c66affSColin Finck             i += 1;
165c2c66affSColin Finck         }
166c2c66affSColin Finck         else
167c2c66affSColin Finck         {
168c2c66affSColin Finck             Buffer[j] = (i - j) - 1;
169c2c66affSColin Finck             j = i;
170c2c66affSColin Finck             i += 1;
171c2c66affSColin Finck         }
172c2c66affSColin Finck     }
173c2c66affSColin Finck 
174c2c66affSColin Finck     Buffer[j] = (i - j) - 1;
175c2c66affSColin Finck     Buffer[i] = 0x00;
176c2c66affSColin Finck     i += 1;
177c2c66affSColin Finck 
178c2c66affSColin Finck     /* QTYPE */
179c2c66affSColin Finck     ((PSHORT)&Buffer[i])[0] = htons( Type );
180c2c66affSColin Finck     i += 2;
181c2c66affSColin Finck 
182c2c66affSColin Finck     /* QCLASS */
183c2c66affSColin Finck     ((PSHORT)&Buffer[i])[0] = htons( CLASS_IN );
184c2c66affSColin Finck 
185c2c66affSColin Finck     /* Ship the request off to the DNS server. */
186c2c66affSColin Finck     bOk = SendRequest( Buffer,
187c2c66affSColin Finck                        BufferLength,
188c2c66affSColin Finck                        RecBuffer,
189c2c66affSColin Finck                        &RecBufferLength );
190c2c66affSColin Finck     if( !bOk ) goto cleanup;
191c2c66affSColin Finck 
192c2c66affSColin Finck     /* Start parsing the received packet. */
193c2c66affSColin Finck     NumQuestions = ntohs( ((PSHORT)&RecBuffer[4])[0] );
194c2c66affSColin Finck 
195c2c66affSColin Finck     k = 12;
196c2c66affSColin Finck 
197c2c66affSColin Finck     /* We don't care about the questions section, blow through it. */
198c2c66affSColin Finck     if( NumQuestions )
199c2c66affSColin Finck     {
200c2c66affSColin Finck         for( i = 0; i < NumQuestions; i += 1 )
201c2c66affSColin Finck         {
202c2c66affSColin Finck             /* Quick way to skip the domain name section. */
203c2c66affSColin Finck             k += ExtractName( RecBuffer, pResult, k, 0 );
204c2c66affSColin Finck             k += 4;
205c2c66affSColin Finck         }
206c2c66affSColin Finck     }
207c2c66affSColin Finck 
208c2c66affSColin Finck     /* Skip the answer name. */
209c2c66affSColin Finck     k += ExtractName( RecBuffer, pResult, k, 0 );
210c2c66affSColin Finck 
211c2c66affSColin Finck     Type = ntohs( ((PUSHORT)&RecBuffer[k])[0] );
212c2c66affSColin Finck     k += 8;
213c2c66affSColin Finck 
214c2c66affSColin Finck     d = ntohs( ((PUSHORT)&RecBuffer[k])[0] );
215c2c66affSColin Finck     k += 2;
216c2c66affSColin Finck 
217c2c66affSColin Finck     if( TYPE_PTR == Type )
218c2c66affSColin Finck     {
219c2c66affSColin Finck         k += ExtractName( RecBuffer, pResult, k, d );
220c2c66affSColin Finck     }
221c2c66affSColin Finck     else if( TYPE_A == Type )
222c2c66affSColin Finck     {
223c2c66affSColin Finck         k += ExtractIP( RecBuffer, pResult, k );
224c2c66affSColin Finck     }
225c2c66affSColin Finck 
226c2c66affSColin Finck cleanup:
227c2c66affSColin Finck     /* Free memory. */
228c2c66affSColin Finck     if( Buffer ) HeapFree( ProcessHeap, 0, Buffer );
229c2c66affSColin Finck     if( RecBuffer ) HeapFree( ProcessHeap, 0, RecBuffer );
230c2c66affSColin Finck 
231c2c66affSColin Finck     RequestID += 1;
232c2c66affSColin Finck 
233c2c66affSColin Finck     return bOk;
234c2c66affSColin Finck }
235c2c66affSColin Finck 
PerformLookup(PCHAR pAddr)236c2c66affSColin Finck void PerformLookup( PCHAR pAddr )
237c2c66affSColin Finck {
238c2c66affSColin Finck     /* Needed to issue DNS packets and parse them. */
239c2c66affSColin Finck     PCHAR Buffer = NULL, RecBuffer = NULL;
240c2c66affSColin Finck     CHAR pResolve[256];
241c2c66affSColin Finck     CHAR pResult[256];
242c2c66affSColin Finck     ULONG BufferLength = 0, RecBufferLength = 512;
243c2c66affSColin Finck     int i = 0, j = 0, k = 0, d = 0;
244c2c66affSColin Finck     BOOL bOk = FALSE;
245c2c66affSColin Finck 
246c2c66affSColin Finck     /* Makes things easier when parsing the response packet. */
247c2c66affSColin Finck     UCHAR Header2;
248c2c66affSColin Finck     USHORT NumQuestions;
249c2c66affSColin Finck     USHORT NumAnswers;
250c2c66affSColin Finck     USHORT NumAuthority;
251c2c66affSColin Finck     USHORT Type;
252c2c66affSColin Finck 
253c2c66affSColin Finck     if( (strlen( pAddr ) + 1) > 255 ) return;
254c2c66affSColin Finck 
255c2c66affSColin Finck     _tprintf( _T("Server:  %s\n"), State.DefaultServer );
256c2c66affSColin Finck     _tprintf( _T("Address:  %s\n\n"), State.DefaultServerAddress );
257c2c66affSColin Finck 
258c2c66affSColin Finck     if( !strcmp( TypeA, State.type )
259c2c66affSColin Finck         || !strcmp( TypeAAAA, State.type )
260c2c66affSColin Finck         || !strcmp( TypeBoth, State.type ) )
261c2c66affSColin Finck     {
262c2c66affSColin Finck         Type = TYPE_A;
263c2c66affSColin Finck         if( IsValidIP( pAddr ) ) Type = TYPE_PTR;
264c2c66affSColin Finck     }
265c2c66affSColin Finck     else
266c2c66affSColin Finck         Type = TypeNametoTypeID( State.type );
267c2c66affSColin Finck 
268c2c66affSColin Finck     /* If it's a PTR lookup then append the ARPA sig to the end. */
269c2c66affSColin Finck     if( (Type == TYPE_PTR) && IsValidIP( pAddr ) )
270c2c66affSColin Finck     {
271c2c66affSColin Finck         ReverseIP( pAddr, pResolve );
272c2c66affSColin Finck         strcat( pResolve, ARPA_SIG );
273c2c66affSColin Finck     }
274c2c66affSColin Finck     else
275c2c66affSColin Finck     {
276c2c66affSColin Finck         strcpy( pResolve, pAddr );
277c2c66affSColin Finck     }
278c2c66affSColin Finck 
279c2c66affSColin Finck     /* Base header length + length of QNAME + length of QTYPE and QCLASS */
280c2c66affSColin Finck     BufferLength = 12 + (strlen( pResolve ) + 2) + 4;
281c2c66affSColin Finck 
282c2c66affSColin Finck     /* Allocate memory for the buffer. */
283c2c66affSColin Finck     Buffer = HeapAlloc( ProcessHeap, 0, BufferLength );
284c2c66affSColin Finck     if( !Buffer )
285c2c66affSColin Finck     {
286c2c66affSColin Finck         _tprintf( _T("ERROR: Out of memory\n") );
287c2c66affSColin Finck         goto cleanup;
288c2c66affSColin Finck     }
289c2c66affSColin Finck 
290c2c66affSColin Finck     /* Allocate memory for the return buffer. */
291c2c66affSColin Finck     RecBuffer = HeapAlloc( ProcessHeap, 0, RecBufferLength );
292c2c66affSColin Finck     if( !RecBuffer )
293c2c66affSColin Finck     {
294c2c66affSColin Finck         _tprintf( _T("ERROR: Out of memory\n") );
295c2c66affSColin Finck         goto cleanup;
296c2c66affSColin Finck     }
297c2c66affSColin Finck 
298c2c66affSColin Finck     /* Insert the ID field. */
299c2c66affSColin Finck     ((PSHORT)&Buffer[i])[0] = htons( RequestID );
300c2c66affSColin Finck     i += 2;
301c2c66affSColin Finck 
302c2c66affSColin Finck     /* Bits 0-7 of the second 16 are all 0, except for when recursion is
303c2c66affSColin Finck     desired. */
304c2c66affSColin Finck     Buffer[i] = 0x00;
305c2c66affSColin Finck     if( State.recurse) Buffer[i] |= 0x01;
306c2c66affSColin Finck     i += 1;
307c2c66affSColin Finck 
308c2c66affSColin Finck     /* Bits 8-15 of the second 16 are 0 for a query. */
309c2c66affSColin Finck     Buffer[i] = 0x00;
310c2c66affSColin Finck     i += 1;
311c2c66affSColin Finck 
312c2c66affSColin Finck     /* Only 1 question. */
313c2c66affSColin Finck     ((PSHORT)&Buffer[i])[0] = htons( 1 );
314c2c66affSColin Finck     i += 2;
315c2c66affSColin Finck 
316c2c66affSColin Finck     /* We aren't sending a response, so 0 out the rest of the header. */
317c2c66affSColin Finck     Buffer[i] = 0x00;
318c2c66affSColin Finck     Buffer[i + 1] = 0x00;
319c2c66affSColin Finck     Buffer[i + 2] = 0x00;
320c2c66affSColin Finck     Buffer[i + 3] = 0x00;
321c2c66affSColin Finck     Buffer[i + 4] = 0x00;
322c2c66affSColin Finck     Buffer[i + 5] = 0x00;
323c2c66affSColin Finck     i += 6;
324c2c66affSColin Finck 
325c2c66affSColin Finck     /* Walk through the query address. Split each section delimited by '.'.
326c2c66affSColin Finck        Format of the QNAME section is length|data, etc. Last one is null */
327c2c66affSColin Finck     j = i;
328c2c66affSColin Finck     i += 1;
329c2c66affSColin Finck 
330c2c66affSColin Finck     for( k = 0; k < strlen( pResolve ); k += 1 )
331c2c66affSColin Finck     {
332c2c66affSColin Finck         if( pResolve[k] != '.' )
333c2c66affSColin Finck         {
334c2c66affSColin Finck             Buffer[i] = pResolve[k];
335c2c66affSColin Finck             i += 1;
336c2c66affSColin Finck         }
337c2c66affSColin Finck         else
338c2c66affSColin Finck         {
339c2c66affSColin Finck             Buffer[j] = (i - j) - 1;
340c2c66affSColin Finck             j = i;
341c2c66affSColin Finck             i += 1;
342c2c66affSColin Finck         }
343c2c66affSColin Finck     }
344c2c66affSColin Finck 
345c2c66affSColin Finck     Buffer[j] = (i - j) - 1;
346c2c66affSColin Finck     Buffer[i] = 0x00;
347c2c66affSColin Finck     i += 1;
348c2c66affSColin Finck 
349c2c66affSColin Finck     /* QTYPE */
350c2c66affSColin Finck     ((PSHORT)&Buffer[i])[0] = htons( Type );
351c2c66affSColin Finck     i += 2;
352c2c66affSColin Finck 
353c2c66affSColin Finck     /* QCLASS */
354c2c66affSColin Finck     ((PSHORT)&Buffer[i])[0] = htons( ClassNametoClassID( State.Class ) );
355c2c66affSColin Finck 
356c2c66affSColin Finck     /* Ship off the request to the DNS server. */
357c2c66affSColin Finck     bOk = SendRequest( Buffer,
358c2c66affSColin Finck                        BufferLength,
359c2c66affSColin Finck                        RecBuffer,
360c2c66affSColin Finck                        &RecBufferLength );
361c2c66affSColin Finck     if( !bOk ) goto cleanup;
362c2c66affSColin Finck 
363c2c66affSColin Finck     /* Start parsing the received packet. */
364c2c66affSColin Finck     Header2 = RecBuffer[3];
365c2c66affSColin Finck     NumQuestions = ntohs( ((PSHORT)&RecBuffer[4])[0] );
366c2c66affSColin Finck     NumAnswers = ntohs( ((PSHORT)&RecBuffer[6])[0] );
367c2c66affSColin Finck     NumAuthority = ntohs( ((PUSHORT)&RecBuffer[8])[0] );
368c2c66affSColin Finck     Type = 0;
369c2c66affSColin Finck 
370c2c66affSColin Finck     /* Check the RCODE for failure. */
371c2c66affSColin Finck     d = Header2 & 0x0F;
372c2c66affSColin Finck     if( d != RCODE_NOERROR )
373c2c66affSColin Finck     {
374c2c66affSColin Finck         switch( d )
375c2c66affSColin Finck         {
376c2c66affSColin Finck         case RCODE_NXDOMAIN:
377c2c66affSColin Finck             _tprintf( _T("*** %s can't find %s: Non-existant domain\n"), State.DefaultServer, pAddr );
378c2c66affSColin Finck             break;
379c2c66affSColin Finck 
380c2c66affSColin Finck         case RCODE_REFUSED:
381c2c66affSColin Finck             _tprintf( _T("*** %s can't find %s: Query refused\n"), State.DefaultServer, pAddr );
382c2c66affSColin Finck             break;
383c2c66affSColin Finck 
384c2c66affSColin Finck         default:
385c2c66affSColin Finck             _tprintf( _T("*** %s can't find %s: Unknown RCODE\n"), State.DefaultServer, pAddr );
386c2c66affSColin Finck         }
387c2c66affSColin Finck 
388c2c66affSColin Finck         goto cleanup;
389c2c66affSColin Finck     }
390c2c66affSColin Finck 
391c2c66affSColin Finck     k = 12;
392c2c66affSColin Finck 
393c2c66affSColin Finck     if( NumQuestions )
394c2c66affSColin Finck     {
395c2c66affSColin Finck         /* Blow through the questions section since we don't care about it. */
396c2c66affSColin Finck         for( i = 0; i < NumQuestions; i += 1 )
397c2c66affSColin Finck         {
398c2c66affSColin Finck             k += ExtractName( RecBuffer, pResult, k, 0 );
399c2c66affSColin Finck             k += 4;
400c2c66affSColin Finck         }
401c2c66affSColin Finck     }
402c2c66affSColin Finck 
403c2c66affSColin Finck     if( NumAnswers )
404c2c66affSColin Finck     {
405c2c66affSColin Finck         /* Skip the name. */
406c2c66affSColin Finck         k += ExtractName( RecBuffer, pResult, k, 0 );
407c2c66affSColin Finck 
408c2c66affSColin Finck         Type = ntohs( ((PUSHORT)&RecBuffer[k])[0] );
409c2c66affSColin Finck         k += 8;
410c2c66affSColin Finck 
411c2c66affSColin Finck         d = ntohs( ((PUSHORT)&RecBuffer[k])[0] );
412c2c66affSColin Finck         k += 2;
413c2c66affSColin Finck 
414c2c66affSColin Finck         if( TYPE_PTR == Type )
415c2c66affSColin Finck         {
416c2c66affSColin Finck             k += ExtractName( RecBuffer, pResult, k, d );
417c2c66affSColin Finck         }
418c2c66affSColin Finck         else if( TYPE_A == Type )
419c2c66affSColin Finck         {
420c2c66affSColin Finck             k += ExtractIP( RecBuffer, pResult, k );
421c2c66affSColin Finck         }
422c2c66affSColin Finck     }
423c2c66affSColin Finck 
424c2c66affSColin Finck     /* FIXME: This'll need to support more than PTR and A at some point. */
425c2c66affSColin Finck     if( !strcmp( State.type, TypePTR ) )
426c2c66affSColin Finck     {
427c2c66affSColin Finck         if( TYPE_PTR == Type )
428c2c66affSColin Finck         {
429c2c66affSColin Finck             _tprintf( _T("%s     name = %s\n"), pResolve, pResult );
430c2c66affSColin Finck         }
431c2c66affSColin Finck         else
432c2c66affSColin Finck         {
433c2c66affSColin Finck         }
434c2c66affSColin Finck     }
435c2c66affSColin Finck     else if( !strcmp( State.type, TypeA )
436c2c66affSColin Finck           || !strcmp( State.type, TypeAAAA )
437c2c66affSColin Finck           || !strcmp( State.type, TypeBoth ) )
438c2c66affSColin Finck     {
439c2c66affSColin Finck         if( (TYPE_A == Type) /*|| (TYPE_AAAA == Type)*/ )
440c2c66affSColin Finck         {
441c2c66affSColin Finck             if( 0 == NumAuthority )
442c2c66affSColin Finck                 _tprintf( _T("Non-authoritative answer:\n") );
443c2c66affSColin Finck 
444c2c66affSColin Finck             _tprintf( _T("Name:    %s\n"), pAddr );
445c2c66affSColin Finck             _tprintf( _T("Address:  %s\n\n"), pResult );
446c2c66affSColin Finck         }
447c2c66affSColin Finck         else
448c2c66affSColin Finck         {
449c2c66affSColin Finck             _tprintf( _T("Name:    %s\n"), pResult );
450c2c66affSColin Finck             _tprintf( _T("Address:  %s\n\n"), pAddr );
451c2c66affSColin Finck         }
452c2c66affSColin Finck     }
453c2c66affSColin Finck 
454c2c66affSColin Finck cleanup:
455c2c66affSColin Finck     /* Free memory. */
456c2c66affSColin Finck     if( Buffer ) HeapFree( ProcessHeap, 0, Buffer );
457c2c66affSColin Finck     if( RecBuffer ) HeapFree( ProcessHeap, 0, RecBuffer );
458c2c66affSColin Finck 
459c2c66affSColin Finck     RequestID += 1;
460c2c66affSColin Finck }
461c2c66affSColin Finck 
ParseCommandLine(int argc,char * argv[])462c2c66affSColin Finck BOOL ParseCommandLine( int argc, char* argv[] )
463c2c66affSColin Finck {
464c2c66affSColin Finck     int i;
465c2c66affSColin Finck     BOOL NoMoreOptions = FALSE;
466c2c66affSColin Finck     BOOL Interactive = FALSE;
467c2c66affSColin Finck     CHAR AddrToResolve[256];
468c2c66affSColin Finck     CHAR Server[256];
469c2c66affSColin Finck 
470c2c66affSColin Finck     RtlZeroMemory( AddrToResolve, 256 );
471c2c66affSColin Finck     RtlZeroMemory( Server, 256 );
472c2c66affSColin Finck 
473c2c66affSColin Finck     if( 2 == argc )
474c2c66affSColin Finck     {
475c2c66affSColin Finck         /* In the Windows nslookup, usage is only displayed if /? is the only
476c2c66affSColin Finck            option specified on the command line. */
477c2c66affSColin Finck         if( !strncmp( "/?", argv[1], 2 ) )
478c2c66affSColin Finck         {
479c2c66affSColin Finck             PrintUsage();
480c2c66affSColin Finck             return 0;
481c2c66affSColin Finck         }
482c2c66affSColin Finck     }
483c2c66affSColin Finck 
484c2c66affSColin Finck     if( argc > 1 )
485c2c66affSColin Finck     {
486c2c66affSColin Finck         for( i = 1; i < argc; i += 1 )
487c2c66affSColin Finck         {
488c2c66affSColin Finck             if( NoMoreOptions )
489c2c66affSColin Finck             {
490c2c66affSColin Finck                 strncpy( Server, argv[i], 255 );
491c2c66affSColin Finck 
492c2c66affSColin Finck                 /* Determine which one to resolve. This is based on whether the
493c2c66affSColin Finck                    DNS server provided was an IP or an FQDN. */
494c2c66affSColin Finck                 if( IsValidIP( Server ) )
495c2c66affSColin Finck                 {
496c2c66affSColin Finck                     strncpy( State.DefaultServerAddress, Server, 16 );
497c2c66affSColin Finck 
498c2c66affSColin Finck                     PerformInternalLookup( State.DefaultServerAddress,
499c2c66affSColin Finck                                            State.DefaultServer );
500c2c66affSColin Finck                 }
501c2c66affSColin Finck                 else
502c2c66affSColin Finck                 {
503c2c66affSColin Finck                     strncpy( State.DefaultServer, Server, 255 );
504c2c66affSColin Finck 
505c2c66affSColin Finck                     PerformInternalLookup( State.DefaultServer,
506c2c66affSColin Finck                                            State.DefaultServerAddress );
507c2c66affSColin Finck                 }
508c2c66affSColin Finck 
509c2c66affSColin Finck                 if( Interactive ) return 1;
510c2c66affSColin Finck 
511c2c66affSColin Finck                 PerformLookup( AddrToResolve );
512c2c66affSColin Finck 
513c2c66affSColin Finck                 return 0;
514c2c66affSColin Finck             }
515c2c66affSColin Finck             else
516c2c66affSColin Finck             {
517c2c66affSColin Finck                 if( !strncmp( "-all", argv[i], 4 ) )
518c2c66affSColin Finck                 {
519c2c66affSColin Finck                     PrintState();
520c2c66affSColin Finck                 }
521c2c66affSColin Finck                 else if( !strncmp( "-type=", argv[i], 6 ) )
522c2c66affSColin Finck                 {
523c2c66affSColin Finck                     if( !strncmp( TypeA, &argv[i][6], strlen( TypeA ) ) )
524c2c66affSColin Finck                     {
525c2c66affSColin Finck                         State.type = TypeA;
526c2c66affSColin Finck                     }
527c2c66affSColin Finck                     else if( !strncmp( TypeAAAA, &argv[i][6], strlen( TypeAAAA ) ) )
528c2c66affSColin Finck                     {
529c2c66affSColin Finck                         State.type = TypeAAAA;
530c2c66affSColin Finck                     }
531c2c66affSColin Finck                     else if( !strncmp( TypeBoth, &argv[i][6], strlen( TypeBoth ) ) )
532c2c66affSColin Finck                     {
533c2c66affSColin Finck                         State.type = TypeBoth;
534c2c66affSColin Finck                     }
535c2c66affSColin Finck                     else if( !strncmp( TypeAny, &argv[i][6], strlen( TypeAny ) ) )
536c2c66affSColin Finck                     {
537c2c66affSColin Finck                         State.type = TypeAny;
538c2c66affSColin Finck                     }
539c2c66affSColin Finck                     else if( !strncmp( TypeCNAME, &argv[i][6], strlen( TypeCNAME ) ) )
540c2c66affSColin Finck                     {
541c2c66affSColin Finck                         State.type = TypeCNAME;
542c2c66affSColin Finck                     }
543c2c66affSColin Finck                     else if( !strncmp( TypeMX, &argv[i][6], strlen( TypeMX ) ) )
544c2c66affSColin Finck                     {
545c2c66affSColin Finck                         State.type = TypeMX;
546c2c66affSColin Finck                     }
547c2c66affSColin Finck                     else if( !strncmp( TypeNS, &argv[i][6], strlen( TypeNS ) ) )
548c2c66affSColin Finck                     {
549c2c66affSColin Finck                         State.type = TypeNS;
550c2c66affSColin Finck                     }
551c2c66affSColin Finck                     else if( !strncmp( TypePTR, &argv[i][6], strlen( TypePTR ) ) )
552c2c66affSColin Finck                     {
553c2c66affSColin Finck                         State.type = TypePTR;
554c2c66affSColin Finck                     }
555c2c66affSColin Finck                     else if( !strncmp( TypeSOA, &argv[i][6], strlen( TypeSOA ) ) )
556c2c66affSColin Finck                     {
557c2c66affSColin Finck                         State.type = TypeSOA;
558c2c66affSColin Finck                     }
559c2c66affSColin Finck                     else if( !strncmp( TypeSRV, &argv[i][6], strlen( TypeSRV ) ) )
560c2c66affSColin Finck                     {
561c2c66affSColin Finck                         State.type = TypeSRV;
562c2c66affSColin Finck                     }
563c2c66affSColin Finck                     else
564c2c66affSColin Finck                     {
565c2c66affSColin Finck                         _tprintf( _T("unknown query type: %s"), &argv[i][6] );
566c2c66affSColin Finck                     }
567c2c66affSColin Finck                 }
568c2c66affSColin Finck                 else if( !strncmp( "-domain=", argv[i], 8 ) )
569c2c66affSColin Finck                 {
570c2c66affSColin Finck                     strcpy( State.domain, &argv[i][8] );
571c2c66affSColin Finck                 }
572c2c66affSColin Finck                 else if( !strncmp( "-srchlist=", argv[i], 10 ) )
573c2c66affSColin Finck                 {
574c2c66affSColin Finck                 }
575c2c66affSColin Finck                 else if( !strncmp( "-root=", argv[i], 6 ) )
576c2c66affSColin Finck                 {
577c2c66affSColin Finck                     strcpy( State.root, &argv[i][6] );
578c2c66affSColin Finck                 }
579c2c66affSColin Finck                 else if( !strncmp( "-retry=", argv[i], 7 ) )
580c2c66affSColin Finck                 {
581c2c66affSColin Finck                 }
582c2c66affSColin Finck                 else if( !strncmp( "-timeout=", argv[i], 9 ) )
583c2c66affSColin Finck                 {
584c2c66affSColin Finck                 }
585c2c66affSColin Finck                 else if( !strncmp( "-querytype=", argv[i], 11 ) )
586c2c66affSColin Finck                 {
587c2c66affSColin Finck                     if( !strncmp( TypeA, &argv[i][11], strlen( TypeA ) ) )
588c2c66affSColin Finck                     {
589c2c66affSColin Finck                         State.type = TypeA;
590c2c66affSColin Finck                     }
591c2c66affSColin Finck                     else if( !strncmp( TypeAAAA, &argv[i][11], strlen( TypeAAAA ) ) )
592c2c66affSColin Finck                     {
593c2c66affSColin Finck                         State.type = TypeAAAA;
594c2c66affSColin Finck                     }
595c2c66affSColin Finck                     else if( !strncmp( TypeBoth, &argv[i][11], strlen( TypeBoth ) ) )
596c2c66affSColin Finck                     {
597c2c66affSColin Finck                         State.type = TypeBoth;
598c2c66affSColin Finck                     }
599c2c66affSColin Finck                     else if( !strncmp( TypeAny, &argv[i][11], strlen( TypeAny ) ) )
600c2c66affSColin Finck                     {
601c2c66affSColin Finck                         State.type = TypeAny;
602c2c66affSColin Finck                     }
603c2c66affSColin Finck                     else if( !strncmp( TypeCNAME, &argv[i][11], strlen( TypeCNAME ) ) )
604c2c66affSColin Finck                     {
605c2c66affSColin Finck                         State.type = TypeCNAME;
606c2c66affSColin Finck                     }
607c2c66affSColin Finck                     else if( !strncmp( TypeMX, &argv[i][11], strlen( TypeMX ) ) )
608c2c66affSColin Finck                     {
609c2c66affSColin Finck                         State.type = TypeMX;
610c2c66affSColin Finck                     }
611c2c66affSColin Finck                     else if( !strncmp( TypeNS, &argv[i][11], strlen( TypeNS ) ) )
612c2c66affSColin Finck                     {
613c2c66affSColin Finck                         State.type = TypeNS;
614c2c66affSColin Finck                     }
615c2c66affSColin Finck                     else if( !strncmp( TypePTR, &argv[i][11], strlen( TypePTR ) ) )
616c2c66affSColin Finck                     {
617c2c66affSColin Finck                         State.type = TypePTR;
618c2c66affSColin Finck                     }
619c2c66affSColin Finck                     else if( !strncmp( TypeSOA, &argv[i][11], strlen( TypeSOA ) ) )
620c2c66affSColin Finck                     {
621c2c66affSColin Finck                         State.type = TypeSOA;
622c2c66affSColin Finck                     }
623c2c66affSColin Finck                     else if( !strncmp( TypeSRV, &argv[i][11], strlen( TypeSRV ) ) )
624c2c66affSColin Finck                     {
625c2c66affSColin Finck                         State.type = TypeSRV;
626c2c66affSColin Finck                     }
627c2c66affSColin Finck                     else
628c2c66affSColin Finck                     {
629c2c66affSColin Finck                         _tprintf( _T("unknown query type: %s"), &argv[i][6] );
630c2c66affSColin Finck                     }
631c2c66affSColin Finck                 }
632c2c66affSColin Finck                 else if( !strncmp( "-class=", argv[i], 7 ) )
633c2c66affSColin Finck                 {
634c2c66affSColin Finck                     if( !strncmp( ClassIN, &argv[i][7], strlen( ClassIN ) ) )
635c2c66affSColin Finck                     {
636c2c66affSColin Finck                         State.Class = ClassIN;
637c2c66affSColin Finck                     }
638c2c66affSColin Finck                     else if( !strncmp( ClassAny, &argv[i][7], strlen( ClassAny ) ) )
639c2c66affSColin Finck                     {
640c2c66affSColin Finck                         State.Class = ClassAny;
641c2c66affSColin Finck                     }
642c2c66affSColin Finck                     else
643c2c66affSColin Finck                     {
644c2c66affSColin Finck                         _tprintf( _T("unknown query class: %s"), &argv[i][7] );
645c2c66affSColin Finck                     }
646c2c66affSColin Finck                 }
647c2c66affSColin Finck                 else if( !strncmp( "-ixfrver=", argv[i], 9 ) )
648c2c66affSColin Finck                 {
649c2c66affSColin Finck                 }
650c2c66affSColin Finck                 else if( !strncmp( "-debug", argv[i], 6 ) )
651c2c66affSColin Finck                 {
652c2c66affSColin Finck                     State.debug = TRUE;
653c2c66affSColin Finck                 }
654c2c66affSColin Finck                 else if( !strncmp( "-nodebug", argv[i], 8 ) )
655c2c66affSColin Finck                 {
656c2c66affSColin Finck                     State.debug = FALSE;
657c2c66affSColin Finck                     State.d2 = FALSE;
658c2c66affSColin Finck                 }
659c2c66affSColin Finck                 else if( !strncmp( "-d2", argv[i], 3 ) )
660c2c66affSColin Finck                 {
661c2c66affSColin Finck                     State.d2 = TRUE;
662c2c66affSColin Finck                     State.debug = TRUE;
663c2c66affSColin Finck                 }
664c2c66affSColin Finck                 else if( !strncmp( "-nod2", argv[i], 5 ) )
665c2c66affSColin Finck                 {
666c2c66affSColin Finck                     if( State.debug ) _tprintf( _T("d2 mode disabled; still in debug mode\n") );
667c2c66affSColin Finck 
668c2c66affSColin Finck                     State.d2 = FALSE;
669c2c66affSColin Finck                 }
670c2c66affSColin Finck                 else if( !strncmp( "-defname", argv[i], 8 ) )
671c2c66affSColin Finck                 {
672c2c66affSColin Finck                     State.defname = TRUE;
673c2c66affSColin Finck                 }
674c2c66affSColin Finck                 else if( !strncmp( "-noddefname", argv[i], 10 ) )
675c2c66affSColin Finck                 {
676c2c66affSColin Finck                     State.defname = FALSE;
677c2c66affSColin Finck                 }
678c2c66affSColin Finck                 else if( !strncmp( "-recurse", argv[i], 8 ) )
679c2c66affSColin Finck                 {
680c2c66affSColin Finck                     State.recurse = TRUE;
681c2c66affSColin Finck                 }
682c2c66affSColin Finck                 else if( !strncmp( "-norecurse", argv[i], 10 ) )
683c2c66affSColin Finck                 {
684c2c66affSColin Finck                     State.recurse = FALSE;
685c2c66affSColin Finck                 }
686c2c66affSColin Finck                 else if( !strncmp( "-search", argv[i], 7 ) )
687c2c66affSColin Finck                 {
688c2c66affSColin Finck                     State.search = TRUE;
689c2c66affSColin Finck                 }
690c2c66affSColin Finck                 else if( !strncmp( "-nosearch", argv[i], 9 ) )
691c2c66affSColin Finck                 {
692c2c66affSColin Finck                     State.search = FALSE;
693c2c66affSColin Finck                 }
694c2c66affSColin Finck                 else if( !strncmp( "-vc", argv[i], 3 ) )
695c2c66affSColin Finck                 {
696c2c66affSColin Finck                     State.vc = TRUE;
697c2c66affSColin Finck                 }
698c2c66affSColin Finck                 else if( !strncmp( "-novc", argv[i], 5 ) )
699c2c66affSColin Finck                 {
700c2c66affSColin Finck                     State.vc = FALSE;
701c2c66affSColin Finck                 }
702c2c66affSColin Finck                 else if( !strncmp( "-msxfr", argv[i], 6 ) )
703c2c66affSColin Finck                 {
704c2c66affSColin Finck                     State.MSxfr = TRUE;
705c2c66affSColin Finck                 }
706c2c66affSColin Finck                 else if( !strncmp( "-nomsxfr", argv[i], 8 ) )
707c2c66affSColin Finck                 {
708c2c66affSColin Finck                     State.MSxfr = FALSE;
709c2c66affSColin Finck                 }
710c2c66affSColin Finck                 else if( !strncmp( "-", argv[i], 1 ) && (strlen( argv[i] ) == 1) )
711c2c66affSColin Finck                 {
712c2c66affSColin Finck                     /* Since we received just the plain - switch, we are going
713c2c66affSColin Finck                        to be entering interactive mode. We also will not be
714c2c66affSColin Finck                        parsing any more options. */
715c2c66affSColin Finck                     NoMoreOptions = TRUE;
716c2c66affSColin Finck                     Interactive = TRUE;
717c2c66affSColin Finck                 }
718c2c66affSColin Finck                 else
719c2c66affSColin Finck                 {
720c2c66affSColin Finck                     /* Grab the address to resolve. No more options accepted
721c2c66affSColin Finck                        past this point. */
722c2c66affSColin Finck                     strncpy( AddrToResolve, argv[i], 255 );
723c2c66affSColin Finck                     NoMoreOptions = TRUE;
724c2c66affSColin Finck                 }
725c2c66affSColin Finck             }
726c2c66affSColin Finck         }
727c2c66affSColin Finck 
728c2c66affSColin Finck         if( NoMoreOptions && !Interactive )
729c2c66affSColin Finck         {
730c2c66affSColin Finck             /* Get the FQDN of the DNS server. */
731c2c66affSColin Finck             PerformInternalLookup( State.DefaultServerAddress,
732c2c66affSColin Finck                                    State.DefaultServer );
733c2c66affSColin Finck 
734c2c66affSColin Finck             PerformLookup( AddrToResolve );
735c2c66affSColin Finck 
736c2c66affSColin Finck             return 0;
737c2c66affSColin Finck         }
738c2c66affSColin Finck     }
739c2c66affSColin Finck 
740c2c66affSColin Finck     /* Get the FQDN of the DNS server. */
741c2c66affSColin Finck     PerformInternalLookup( State.DefaultServerAddress,
742c2c66affSColin Finck                            State.DefaultServer );
743c2c66affSColin Finck 
744c2c66affSColin Finck     return 1;
745c2c66affSColin Finck }
746c2c66affSColin Finck 
InteractiveMode()747c2c66affSColin Finck void InteractiveMode()
748c2c66affSColin Finck {
749c2c66affSColin Finck     _tprintf( _T("Default Server:  %s\n"), State.DefaultServer );
750c2c66affSColin Finck     _tprintf( _T("Address:  %s\n\n"), State.DefaultServerAddress );
751c2c66affSColin Finck 
752c2c66affSColin Finck     /* TODO: Implement interactive mode. */
753c2c66affSColin Finck 
754c2c66affSColin Finck     _tprintf( _T("ERROR: Feature not implemented.\n") );
755c2c66affSColin Finck }
756c2c66affSColin Finck 
main(int argc,char * argv[])757c2c66affSColin Finck int main( int argc, char* argv[] )
758c2c66affSColin Finck {
759c2c66affSColin Finck     int i;
760c2c66affSColin Finck     ULONG Status;
761c2c66affSColin Finck     PFIXED_INFO pNetInfo = NULL;
762c2c66affSColin Finck     ULONG NetBufLen = 0;
763c2c66affSColin Finck     WSADATA wsaData;
764*e9619588SJérôme Gardou     int ret;
765c2c66affSColin Finck 
766c2c66affSColin Finck     ProcessHeap = GetProcessHeap();
767c2c66affSColin Finck     RequestID = 1;
768c2c66affSColin Finck 
769c2c66affSColin Finck     /* Set up the initial state. */
770c2c66affSColin Finck     State.debug = FALSE;
771c2c66affSColin Finck     State.defname = TRUE;
772c2c66affSColin Finck     State.search = TRUE;
773c2c66affSColin Finck     State.recurse = TRUE;
774c2c66affSColin Finck     State.d2 = FALSE;
775c2c66affSColin Finck     State.vc = FALSE;
776c2c66affSColin Finck     State.ignoretc = FALSE;
777c2c66affSColin Finck     State.port = 53;
778c2c66affSColin Finck     State.type = TypeBoth;
779c2c66affSColin Finck     State.Class = ClassIN;
780c2c66affSColin Finck     State.timeout = 2;
781c2c66affSColin Finck     State.retry = 1;
782c2c66affSColin Finck     State.MSxfr = TRUE;
783c2c66affSColin Finck     State.ixfrver = 1;
784c2c66affSColin Finck 
785c2c66affSColin Finck     RtlZeroMemory( State.root, 256 );
786c2c66affSColin Finck     RtlZeroMemory( State.domain, 256 );
787c2c66affSColin Finck     for( i = 0; i < 6; i += 1 ) RtlZeroMemory( State.srchlist[i], 256 );
788c2c66affSColin Finck     RtlZeroMemory( State.DefaultServer, 256 );
789c2c66affSColin Finck     RtlZeroMemory( State.DefaultServerAddress, 16 );
790c2c66affSColin Finck 
791c2c66affSColin Finck     memcpy( State.root, DEFAULT_ROOT, sizeof(DEFAULT_ROOT) );
792c2c66affSColin Finck 
793c2c66affSColin Finck     /* We don't know how long of a buffer it will want to return. So we'll
794c2c66affSColin Finck        pass an empty one now and let it fail only once, instead of guessing. */
795c2c66affSColin Finck     Status = GetNetworkParams( pNetInfo, &NetBufLen );
79642515190SJulian Kirsch 
79742515190SJulian Kirsch     if( Status != ERROR_BUFFER_OVERFLOW )
798c2c66affSColin Finck     {
79942515190SJulian Kirsch         _tprintf( _T("Error in GetNetworkParams call\n") );
80042515190SJulian Kirsch 
80142515190SJulian Kirsch         return -2;
80242515190SJulian Kirsch     }
80342515190SJulian Kirsch 
804c2c66affSColin Finck     pNetInfo = (PFIXED_INFO)HeapAlloc( ProcessHeap, 0, NetBufLen );
805c2c66affSColin Finck     if( pNetInfo == NULL )
806c2c66affSColin Finck     {
807c2c66affSColin Finck         _tprintf( _T("ERROR: Out of memory\n") );
808c2c66affSColin Finck 
809c2c66affSColin Finck         return -1;
810c2c66affSColin Finck     }
811c2c66affSColin Finck 
812c2c66affSColin Finck     /* For real this time. */
813c2c66affSColin Finck     Status = GetNetworkParams( pNetInfo, &NetBufLen );
814c2c66affSColin Finck     if( Status != NO_ERROR )
815c2c66affSColin Finck     {
816c2c66affSColin Finck         _tprintf( _T("Error in GetNetworkParams call\n") );
817c2c66affSColin Finck 
818c2c66affSColin Finck         HeapFree( ProcessHeap, 0, pNetInfo );
819c2c66affSColin Finck 
820c2c66affSColin Finck         return -2;
821c2c66affSColin Finck     }
822c2c66affSColin Finck 
823c2c66affSColin Finck     strncpy( State.domain, pNetInfo->DomainName, 255 );
824c2c66affSColin Finck     strncpy( State.srchlist[0], pNetInfo->DomainName, 255 );
825c2c66affSColin Finck     strncpy( State.DefaultServerAddress,
826c2c66affSColin Finck              pNetInfo->DnsServerList.IpAddress.String,
827c2c66affSColin Finck              15 );
828c2c66affSColin Finck 
829c2c66affSColin Finck     HeapFree( ProcessHeap, 0, pNetInfo );
830c2c66affSColin Finck 
831*e9619588SJérôme Gardou     ret = WSAStartup( MAKEWORD(2, 2), &wsaData );
832*e9619588SJérôme Gardou     if (ret != 0)
833*e9619588SJérôme Gardou     {
834*e9619588SJérôme Gardou         _tprintf( _T("Winsock initialization failed: %d\n"), ret );
835*e9619588SJérôme Gardou         return ret;
836*e9619588SJérôme Gardou     }
837c2c66affSColin Finck 
838c2c66affSColin Finck     switch( ParseCommandLine( argc, argv ) )
839c2c66affSColin Finck     {
840c2c66affSColin Finck     case 0:
841c2c66affSColin Finck         /* This means that it was a /? parameter. */
842c2c66affSColin Finck         break;
843c2c66affSColin Finck 
844c2c66affSColin Finck     default:
845c2c66affSColin Finck         /* Anything else means we enter interactive mode. The only exception
846c2c66affSColin Finck            to this is when the host to resolve was provided on the command
847c2c66affSColin Finck            line. */
848c2c66affSColin Finck         InteractiveMode();
849c2c66affSColin Finck     }
850c2c66affSColin Finck 
851c2c66affSColin Finck     WSACleanup();
852c2c66affSColin Finck     return 0;
853c2c66affSColin Finck }
854