- Display a temporary note in ipconfig to avoid user confusion.
[reactos.git] / reactos / apps / utils / net / ipconfig / ipconfig.c
1 /*
2 * ReactOS Win32 Applications
3 * Copyright (C) 2005 ReactOS Team
4 *
5 * COPYRIGHT: See COPYING in the top level directory
6 * PROJECT: ReactOS arp utility
7 * FILE: apps/utils/net/ipconfig/ipconfig.c
8 * PURPOSE:
9 * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
10 * REVISIONS:
11 * GM 14/09/05 Created
12 *
13 */
14 /*
15 * TODO:
16 * fix renew / release
17 * implement flushdns, registerdns, displaydns, showclassid, setclassid
18 * allow globbing on adapter names
19 */
20 #define WIN32_LEAN_AND_MEAN
21 #include <windows.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <time.h>
25 #include <tchar.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <winsock2.h>
29 #include <iphlpapi.h>
30
31 #define UNICODE
32 #define _UNICODE
33
34
35
36 LPCTSTR GetNodeTypeName(UINT NodeType)
37 {
38 switch (NodeType) {
39 case 1: return _T("Broadcast");
40 case 2: return _T("Peer To Peer");
41 case 4: return _T("Mixed");
42 case 8: return _T("Hybrid");
43 default : return _T("unknown");
44 }
45 }
46
47 LPCTSTR GetInterfaceTypeName(UINT InterfaceType)
48 {
49 switch (InterfaceType) {
50 case MIB_IF_TYPE_OTHER: return _T("Other Type Of Adapter");
51 case MIB_IF_TYPE_ETHERNET: return _T("Ethernet Adapter");
52 case MIB_IF_TYPE_TOKENRING: return _T("Token Ring Adapter");
53 case MIB_IF_TYPE_FDDI: return _T("FDDI Adapter");
54 case MIB_IF_TYPE_PPP: return _T("PPP Adapter");
55 case MIB_IF_TYPE_LOOPBACK: return _T("Loopback Adapter");
56 case MIB_IF_TYPE_SLIP: return _T("SLIP Adapter");
57 default: return _T("unknown");
58 }
59 }
60
61 /* print MAC address */
62 PTCHAR PrintMacAddr(PBYTE Mac)
63 {
64 static TCHAR MacAddr[20];
65
66 _stprintf(MacAddr, _T("%02x-%02x-%02x-%02x-%02x-%02x"),
67 Mac[0], Mac[1], Mac[2], Mac[3], Mac[4], Mac[5]);
68
69 return MacAddr;
70 }
71
72 DWORD DoFormatMessage(DWORD ErrorCode)
73 {
74 LPVOID lpMsgBuf;
75 DWORD RetVal;
76
77 if ((RetVal = FormatMessage(
78 FORMAT_MESSAGE_ALLOCATE_BUFFER |
79 FORMAT_MESSAGE_FROM_SYSTEM |
80 FORMAT_MESSAGE_IGNORE_INSERTS,
81 NULL,
82 ErrorCode,
83 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
84 (LPTSTR) &lpMsgBuf,
85 0,
86 NULL ))) {
87 _tprintf(_T("%s"), (LPTSTR)lpMsgBuf);
88
89 LocalFree(lpMsgBuf);
90 /* return number of TCHAR's stored in output buffer
91 * excluding '\0' - as FormatMessage does*/
92 return RetVal;
93 }
94 else
95 return 0;
96 }
97
98 INT ShowInfo(BOOL bAll)
99 {
100 PIP_ADAPTER_INFO pAdapterInfo = NULL;
101 PIP_ADAPTER_INFO pAdapter = NULL;
102 ULONG adaptOutBufLen;
103
104 PFIXED_INFO pFixedInfo;
105 ULONG netOutBufLen;
106 PIP_ADDR_STRING pIPAddr = NULL;
107
108 DWORD ErrRet = 0;
109
110 /* assign memory for call to GetNetworkParams */
111 pFixedInfo = (FIXED_INFO *) GlobalAlloc( GPTR, sizeof( FIXED_INFO ) );
112 netOutBufLen = sizeof(FIXED_INFO);
113
114 /* assign memory for call to GetAdapterInfo */
115 pAdapterInfo = (IP_ADAPTER_INFO *) malloc( sizeof(IP_ADAPTER_INFO) );
116 adaptOutBufLen = sizeof(IP_ADAPTER_INFO);
117
118 /* set required buffer size */
119 if(GetNetworkParams(pFixedInfo, &netOutBufLen) == ERROR_BUFFER_OVERFLOW)
120 {
121 GlobalFree(pFixedInfo);
122 pFixedInfo = (FIXED_INFO *) GlobalAlloc(GPTR, netOutBufLen);
123 }
124
125 /* set required buffer size */
126 if (GetAdaptersInfo( pAdapterInfo, &adaptOutBufLen) == ERROR_BUFFER_OVERFLOW)
127 {
128 free(pAdapterInfo);
129 pAdapterInfo = (IP_ADAPTER_INFO *) malloc (adaptOutBufLen);
130 }
131
132 if ((ErrRet = GetAdaptersInfo(pAdapterInfo, &adaptOutBufLen)) != NO_ERROR)
133 {
134 _tprintf(_T("GetAdaptersInfo failed : "));
135 DoFormatMessage(ErrRet);
136 return EXIT_FAILURE;
137 }
138
139 if ((ErrRet = GetNetworkParams(pFixedInfo, &netOutBufLen)) != NO_ERROR)
140 {
141 _tprintf(_T("GetNetworkParams failed : "));
142 DoFormatMessage(ErrRet);
143 return EXIT_FAILURE;
144 }
145
146 pAdapter = pAdapterInfo;
147
148 /* temp note until GetAdatersInfo is fixed */
149 _tprintf(_T("Note - ipconfig is currently returning incorrect information\n"));
150 _tprintf(_T("If your adapter is configured correctly, it will usually \n"));
151 _tprintf(_T("display the loopback, otherwise an error will be displayed\n\n"));
152
153 _tprintf(_T("\nReactOS IP Configuration\n\n"));
154
155 if (bAll)
156 {
157 _tprintf(_T("\tHost Name . . . . . . . . . . . . : %s\n"), pFixedInfo->HostName);
158 _tprintf(_T("\tPrimary DNS Suffix. . . . . . . . : \n"));
159 _tprintf(_T("\tNode Type . . . . . . . . . . . . : %s\n"), GetNodeTypeName(pFixedInfo->NodeType));
160 if (pFixedInfo->EnableRouting)
161 _tprintf(_T("\tIP Routing Enabled. . . . . . . . : Yes\n"));
162 else
163 _tprintf(_T("\tIP Routing Enabled. . . . . . . . : No\n"));
164 if (pAdapter->HaveWins)
165 _tprintf(_T("\tWINS Proxy enabled. . . . . . . . : Yes\n"));
166 else
167 _tprintf(_T("\tWINS Proxy enabled. . . . . . . . : No\n"));
168 _tprintf(_T("\tDNS Suffix Search List. . . . . . : %s\n"), pFixedInfo->DomainName);
169 }
170
171 while (pAdapter)
172 {
173
174 _tprintf(_T("\n%s ...... : \n\n"), GetInterfaceTypeName(pAdapter->Type));
175
176 /* check if the adapter is connected to the media */
177 if (_tcscmp(pAdapter->IpAddressList.IpAddress.String, "0.0.0.0") == 0)
178 {
179 _tprintf(_T("\tMedia State . . . . . . . . . . . : Media disconnected\n"));
180 pAdapter = pAdapter->Next;
181 continue;
182 }
183
184 _tprintf(_T("\tConnection-specific DNS Suffix. . : %s\n"), pFixedInfo->DomainName);
185
186 if (bAll)
187 {
188 _tprintf(_T("\tDescription . . . . . . . . . . . : %s\n"), pAdapter->Description);
189 _tprintf(_T("\tPhysical Address. . . . . . . . . : %s\n"), PrintMacAddr(pAdapter->Address));
190 if (pAdapter->DhcpEnabled)
191 _tprintf(_T("\tDHCP Enabled. . . . . . . . . . . : Yes\n"));
192 else
193 _tprintf(_T("\tDHCP Enabled. . . . . . . . . . . : No\n"));
194 _tprintf(_T("\tAutoconfiguration Enabled . . . . : \n"));
195 }
196
197 _tprintf(_T("\tIP Address. . . . . . . . . . . . : %s\n"), pAdapter->IpAddressList.IpAddress.String);
198 _tprintf(_T("\tSubnet Mask . . . . . . . . . . . : %s\n"), pAdapter->IpAddressList.IpMask.String);
199 _tprintf(_T("\tDefault Gateway . . . . . . . . . : %s\n"), pAdapter->GatewayList.IpAddress.String);
200
201 if (bAll)
202 {
203 if (pAdapter->DhcpEnabled)
204 _tprintf(_T("\tDHCP Server . . . . . . . . . . . : %s\n"), pAdapter->DhcpServer.IpAddress.String);
205
206 _tprintf(_T("\tDNS Servers . . . . . . . . . . . : "));
207 _tprintf(_T("%s\n"), pFixedInfo->DnsServerList.IpAddress.String);
208 pIPAddr = pFixedInfo -> DnsServerList.Next;
209 while (pIPAddr)
210 {
211 _tprintf(_T("\t\t\t\t\t %s\n"), pIPAddr ->IpAddress.String );
212 pIPAddr = pIPAddr ->Next;
213 }
214 if (pAdapter->HaveWins)
215 {
216 _tprintf(_T("\tPrimary WINS Server . . . . . . . : %s\n"), pAdapter->PrimaryWinsServer.IpAddress.String);
217 _tprintf(_T("\tSecondard WINS Server . . . . . . : %s\n"), pAdapter->SecondaryWinsServer.IpAddress.String);
218 }
219 if (pAdapter->DhcpEnabled)
220 {
221 _tprintf(_T("\tLease Obtained. . . . . . . . . . : %s"), _tasctime(localtime(&pAdapter->LeaseObtained)));
222 _tprintf(_T("\tLease Expires . . . . . . . . . . : %s"), _tasctime(localtime(&pAdapter->LeaseExpires)));
223 }
224 }
225 _tprintf(_T("\n"));
226
227 pAdapter = pAdapter->Next;
228
229 }
230
231 return 0;
232 }
233
234 INT Release(TCHAR Index)
235 {
236 IP_ADAPTER_INDEX_MAP AdapterInfo;
237 DWORD dwRetVal = 0;
238
239 /* if interface is not given, query GetInterfaceInfo */
240 if (Index == (TCHAR)NULL)
241 {
242 PIP_INTERFACE_INFO pInfo;
243 ULONG ulOutBufLen;
244 pInfo = (IP_INTERFACE_INFO *) malloc(sizeof(IP_INTERFACE_INFO));
245 ulOutBufLen = 0;
246
247 /* Make an initial call to GetInterfaceInfo to get
248 * the necessary size into the ulOutBufLen variable */
249 if ( GetInterfaceInfo(pInfo, &ulOutBufLen) == ERROR_INSUFFICIENT_BUFFER)
250 {
251 GlobalFree(pInfo);
252 pInfo = (IP_INTERFACE_INFO *) malloc (ulOutBufLen);
253 }
254
255 /* Make a second call to GetInterfaceInfo to get the actual data we want */
256 if ((dwRetVal = GetInterfaceInfo(pInfo, &ulOutBufLen)) == NO_ERROR )
257 {
258 AdapterInfo = pInfo->Adapter[0];
259 _tprintf(_T("name - %S\n"), pInfo->Adapter[0].Name);
260 }
261 else
262 {
263 _tprintf(_T("\nGetInterfaceInfo failed : "));
264 DoFormatMessage(dwRetVal);
265 }
266 }
267 else
268 {
269 ;
270 /* we need to be able to release connections by name with support for globbing
271 * i.e. ipconfig /release Eth* will release all cards starting with Eth...
272 * ipconfig /release *con* will release all cards with 'con' in their name
273 */
274 }
275
276
277 /* Call IpReleaseAddress to release the IP address on the specified adapter. */
278 if ((dwRetVal = IpReleaseAddress(&AdapterInfo)) != NO_ERROR)
279 {
280 _tprintf(_T("\nAn error occured while releasing interface %s : "), _T("*name*"));
281 DoFormatMessage(dwRetVal);
282 }
283 return 0;
284 }
285
286
287
288
289 INT Renew(TCHAR Index)
290 {
291 IP_ADAPTER_INDEX_MAP AdapterInfo;
292 DWORD dwRetVal = 0;
293
294 /* if interface is not given, query GetInterfaceInfo */
295 if (Index == (TCHAR)NULL)
296 {
297 PIP_INTERFACE_INFO pInfo;
298 ULONG ulOutBufLen;
299 pInfo = (IP_INTERFACE_INFO *) malloc(sizeof(IP_INTERFACE_INFO));
300 ulOutBufLen = 0;
301
302 /* Make an initial call to GetInterfaceInfo to get
303 * the necessary size into the ulOutBufLen variable */
304 if ( GetInterfaceInfo(pInfo, &ulOutBufLen) == ERROR_INSUFFICIENT_BUFFER)
305 {
306 GlobalFree(pInfo);
307 pInfo = (IP_INTERFACE_INFO *) malloc (ulOutBufLen);
308 }
309
310 /* Make a second call to GetInterfaceInfo to get the actual data we want */
311 if ((dwRetVal = GetInterfaceInfo(pInfo, &ulOutBufLen)) == NO_ERROR )
312 {
313 AdapterInfo = pInfo->Adapter[0];
314 _tprintf(_T("name - %S\n"), pInfo->Adapter[0].Name);
315 } else {
316 _tprintf(_T("\nGetInterfaceInfo failed : "));
317 DoFormatMessage(dwRetVal);
318 }
319 }
320 else
321 {
322 ;
323 /* we need to be able to renew connections by name with support for globbing
324 * i.e. ipconfig /renew Eth* will renew all cards starting with Eth...
325 * ipconfig /renew *con* will renew all cards with 'con' in their name
326 */
327 }
328
329
330 /* Call IpRenewAddress to renew the IP address on the specified adapter. */
331 if ((dwRetVal = IpRenewAddress(&AdapterInfo)) != NO_ERROR)
332 {
333 _tprintf(_T("\nAn error occured while renew interface %s : "), _T("*name*"));
334 DoFormatMessage(dwRetVal);
335 }
336 return 0;
337 }
338
339 /* temp func for testing purposes */
340 VOID Info()
341 {
342 // Declare and initialize variables
343 PIP_INTERFACE_INFO pInfo;
344 ULONG ulOutBufLen;
345 DWORD dwRetVal;
346
347 pInfo = (IP_INTERFACE_INFO *) malloc( sizeof(IP_INTERFACE_INFO) );
348 ulOutBufLen = sizeof(IP_INTERFACE_INFO);
349 dwRetVal = 0;
350
351
352 // Make an initial call to GetInterfaceInfo to get
353 // the necessary size in the ulOutBufLen variable
354 if ( GetInterfaceInfo(pInfo, &ulOutBufLen) == ERROR_INSUFFICIENT_BUFFER)
355 {
356 free(pInfo);
357 pInfo = (IP_INTERFACE_INFO *) malloc (ulOutBufLen);
358 }
359
360 // Make a second call to GetInterfaceInfo to get
361 // the actual data we need
362 if ((dwRetVal = GetInterfaceInfo(pInfo, &ulOutBufLen)) == NO_ERROR )
363 {
364 int i;
365 for (i=0; i<pInfo->NumAdapters; i++)
366 {
367 printf("\tAdapter Name: %S\n", pInfo->Adapter[i].Name);
368 printf("\tAdapter Index: %ld\n", pInfo->Adapter[i].Index);
369 printf("\tNum Adapters: %ld\n", pInfo->NumAdapters);
370 }
371 }
372 else
373 {
374 printf("GetInterfaceInfo failed.\n");
375 DoFormatMessage(dwRetVal);
376 }
377 }
378
379
380 VOID Usage(VOID)
381 {
382 _tprintf(_T("\nUSAGE:\n"
383 " ipconfig [/? | /all | /renew [adapter] | /release [adapter] |\n"
384 " /flushdns | /displaydns | /registerdns |\n"
385 " /showclassid adapter |\n"
386 " /setclassid adapter [classid] ]\n"
387 "\n"
388 "where\n"
389 " adapter Connection name\n"
390 " (wildcard characters * and ? allowed, see examples)\n"
391 "\n"
392 " Options:\n"
393 " /? Display this help message\n"
394 " /all Display full configuration information.\n"
395 " /release Release the IP address for the specified adapter.\n"
396 " /renew Renew the IP address for the specified adapter.\n"
397 " /flushdns Purges the DNS Resolver cache.\n"
398 " /registerdns Refreshes all DHCP leases and re-registers DNS names.\n"
399 " /displaydns Display the contents of the DNS Resolver Cache.\n"
400 " /showclassid Displays all the dhcp class IDs allowed for adapter.\n"
401 " /setclassid Modifies the dhcp class id.\n"
402 "\n"
403 "The default is to display only the IP address, subnet mask and\n"
404 "default gateway for each adapter bound to TCP/IP.\n"
405 "\n"
406 "For Release and Renew, if no adapter name is specified, then the IP address\n"
407 "leases for all adapters bound to TCP/IP will be released or renewed.\n"
408 "\n"
409 "For Setclassid, if no ClassId is specified, then the ClassId is removed.\n"
410 "\n"
411 "Examples:\n"
412 " > ipconfig ... Show information.\n"
413 " > ipconfig /all ... Show detailed information\n"
414 " > ipconfig /renew ... renew all adapters\n"
415 " > ipconfig /renew EL* ... renew any connection that has its\n"
416 " name starting with EL\n"
417 " > ipconfig /release *Con* ... release all matching connections,\n"
418 " eg. \"Local Area Connection 1\" or\n"
419 " \"Local Area Connection 2\"\n"));
420 }
421
422 int main(int argc, char *argv[])
423 {
424 BOOL DoUsage=FALSE;
425 BOOL DoAll=FALSE;
426 BOOL DoRelease=FALSE;
427 BOOL DoRenew=FALSE;
428 BOOL DoFlushdns=FALSE;
429 BOOL DoRegisterdns=FALSE;
430 BOOL DoDisplaydns=FALSE;
431 BOOL DoShowclassid=FALSE;
432 BOOL DoSetclassid=FALSE;
433
434 /* Parse command line for options we have been given. */
435 if ( (argc > 1)&&(argv[1][0]=='/') )
436 {
437 if( !_tcsicmp( &argv[1][1], _T("?") ))
438 {
439 DoUsage = TRUE;
440 }
441 else if( !_tcsnicmp( &argv[1][1], _T("ALL"), _tcslen(&argv[1][1]) ))
442 {
443 DoAll = TRUE;
444 }
445 else if( !_tcsnicmp( &argv[1][1], _T("RELEASE"), _tcslen(&argv[1][1]) ))
446 {
447 DoRelease = TRUE;
448 }
449 else if( ! _tcsnicmp( &argv[1][1], _T("RENEW"), _tcslen(&argv[1][1]) ))
450 {
451 DoRenew = TRUE;
452 }
453 else if( ! _tcsnicmp( &argv[1][1], _T("FLUSHDNS"), _tcslen(&argv[1][1]) ))
454 {
455 DoFlushdns = TRUE;
456 }
457 else if( ! _tcsnicmp( &argv[1][1], _T("FLUSHREGISTERDNS"), _tcslen(&argv[1][1]) ))
458 {
459 DoRegisterdns = TRUE;
460 }
461 else if( ! _tcsnicmp( &argv[1][1], _T("DISPLAYDNS"), _tcslen(&argv[1][1]) ))
462 {
463 DoDisplaydns = TRUE;
464 }
465 else if( ! _tcsnicmp( &argv[1][1], _T("SHOWCLASSID"), _tcslen(&argv[1][1]) ))
466 {
467 DoShowclassid = TRUE;
468 }
469 else if( ! _tcsnicmp( &argv[1][1], _T("SETCLASSID"), _tcslen(&argv[1][1]) ))
470 {
471 DoSetclassid = TRUE;
472 }
473 }
474
475 switch (argc)
476 {
477 case 1: /* Default behaviour if no options are given*/
478 ShowInfo(FALSE);
479 break;
480 case 2: /* Process all the options that take no paramiters */
481 if (DoUsage)
482 Usage();
483 else if (DoAll)
484 ShowInfo(TRUE);
485 else if (DoRelease)
486 Release((TCHAR)NULL);
487 else if (DoRenew)
488 Renew((TCHAR)NULL);
489 else if (DoFlushdns)
490 _tprintf(_T("\nSorry /flushdns is not implemented yet\n"));
491 else if (DoRegisterdns)
492 _tprintf(_T("\nSorry /registerdns is not implemented yet\n"));
493 else if (DoDisplaydns)
494 _tprintf(_T("\nSorry /displaydns is not implemented yet\n"));
495 else
496 Usage();
497 break;
498 case 3: /* Process all the options that can have 1 paramiters */
499 if (DoRelease)
500 _tprintf(_T("\nSorry /release [adapter] is not implemented yet\n"));
501 //Release(argv[2]);
502 else if (DoRenew)
503 _tprintf(_T("\nSorry /renew [adapter] is not implemented yet\n"));
504 else if (DoShowclassid)
505 _tprintf(_T("\nSorry /showclassid adapter is not implemented yet\n"));
506 else if (DoSetclassid)
507 _tprintf(_T("\nSorry /setclassid adapter is not implemented yet\n"));
508 else
509 Usage();
510 break;
511 case 4: /* Process all the options that can have 2 paramiters */
512 if (DoSetclassid)
513 _tprintf(_T("\nSorry /setclassid adapter [classid]is not implemented yet\n"));
514 else
515 Usage();
516 break;
517 default:
518 Usage();
519 }
520
521 return 0;
522 }