776d31c9827ef62e97b7a9c6c0e1f35f70b3d861
[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 //HKEY hKey;
148 //LPCTSTR lpSubKey = _T("SYSTEM\\ControlSet\\Control\\Network");
149
150 _tprintf(_T("\nReactOS IP Configuration\n\n"));
151
152 while (pAdapter)
153 {
154 if (bAll)
155 {
156 _tprintf(_T("\tHost Name . . . . . . . . . . . . : %s\n"), pFixedInfo->HostName);
157 _tprintf(_T("\tPrimary DNS Suffix. . . . . . . . : \n"));
158 _tprintf(_T("\tNode Type . . . . . . . . . . . . : %s\n"), GetNodeTypeName(pFixedInfo->NodeType));
159 if (pFixedInfo->EnableRouting)
160 _tprintf(_T("\tIP Routing Enabled. . . . . . . . : Yes\n"));
161 else
162 _tprintf(_T("\tIP Routing Enabled. . . . . . . . : No\n"));
163 if (pAdapter->HaveWins)
164 _tprintf(_T("\tWINS Proxy enabled. . . . . . . . : Yes\n"));
165 else
166 _tprintf(_T("\tWINS Proxy enabled. . . . . . . . : No\n"));
167 _tprintf(_T("\tDNS Suffix Search List. . . . . . : %s\n"), pFixedInfo->DomainName);
168 }
169
170 _tprintf(_T("\n%s ...... : \n\n"), GetInterfaceTypeName(pAdapter->Type));
171
172 /* check if the adapter is connected to the media */
173 if (_tcscmp(pAdapter->IpAddressList.IpAddress.String, "0.0.0.0") == 0)
174 {
175 _tprintf(_T("\tMedia State . . . . . . . . . . . : Media disconnected\n"));
176 pAdapter = pAdapter->Next;
177 continue;
178 }
179
180 _tprintf(_T("\tConnection-specific DNS Suffix. . : %s\n"), pFixedInfo->DomainName);
181
182 if (bAll)
183 {
184 _tprintf(_T("\tDescription . . . . . . . . . . . : %s\n"), pAdapter->Description);
185 _tprintf(_T("\tPhysical Address. . . . . . . . . : %s\n"), PrintMacAddr(pAdapter->Address));
186 if (pAdapter->DhcpEnabled)
187 _tprintf(_T("\tDHCP Enabled. . . . . . . . . . . : Yes\n"));
188 else
189 _tprintf(_T("\tDHCP Enabled. . . . . . . . . . . : No\n"));
190 _tprintf(_T("\tAutoconfiguration Enabled . . . . : \n"));
191 }
192
193 _tprintf(_T("\tIP Address. . . . . . . . . . . . : %s\n"), pAdapter->IpAddressList.IpAddress.String);
194 _tprintf(_T("\tSubnet Mask . . . . . . . . . . . : %s\n"), pAdapter->IpAddressList.IpMask.String);
195 _tprintf(_T("\tDefault Gateway . . . . . . . . . : %s\n"), pAdapter->GatewayList.IpAddress.String);
196
197 if (bAll)
198 {
199 if (pAdapter->DhcpEnabled)
200 _tprintf(_T("\tDHCP Server . . . . . . . . . . . : %s\n"), pAdapter->DhcpServer.IpAddress.String);
201
202 _tprintf(_T("\tDNS Servers . . . . . . . . . . . : "));
203 _tprintf(_T("%s\n"), pFixedInfo->DnsServerList.IpAddress.String);
204 pIPAddr = pFixedInfo -> DnsServerList.Next;
205 while (pIPAddr)
206 {
207 _tprintf(_T("\t\t\t\t\t %s\n"), pIPAddr ->IpAddress.String );
208 pIPAddr = pIPAddr ->Next;
209 }
210 if (pAdapter->HaveWins)
211 {
212 _tprintf(_T("\tPrimary WINS Server . . . . . . . : %s\n"), pAdapter->PrimaryWinsServer.IpAddress.String);
213 _tprintf(_T("\tSecondard WINS Server . . . . . . : %s\n"), pAdapter->SecondaryWinsServer.IpAddress.String);
214 }
215 if (pAdapter->DhcpEnabled)
216 {
217 _tprintf(_T("\tLease Obtained. . . . . . . . . . : %s"), _tasctime(localtime(&pAdapter->LeaseObtained)));
218 _tprintf(_T("\tLease Expires . . . . . . . . . . : %s"), _tasctime(localtime(&pAdapter->LeaseExpires)));
219 }
220 }
221 _tprintf(_T("\n"));
222
223 pAdapter = pAdapter->Next;
224
225 }
226
227 return 0;
228 }
229
230 INT Release(TCHAR Index)
231 {
232 IP_ADAPTER_INDEX_MAP AdapterInfo;
233 DWORD dwRetVal = 0;
234
235 /* if interface is not given, query GetInterfaceInfo */
236 if (Index == (TCHAR)NULL)
237 {
238 PIP_INTERFACE_INFO pInfo;
239 ULONG ulOutBufLen;
240 pInfo = (IP_INTERFACE_INFO *) malloc(sizeof(IP_INTERFACE_INFO));
241 ulOutBufLen = 0;
242
243 /* Make an initial call to GetInterfaceInfo to get
244 * the necessary size into the ulOutBufLen variable */
245 if ( GetInterfaceInfo(pInfo, &ulOutBufLen) == ERROR_INSUFFICIENT_BUFFER)
246 {
247 GlobalFree(pInfo);
248 pInfo = (IP_INTERFACE_INFO *) malloc (ulOutBufLen);
249 }
250
251 /* Make a second call to GetInterfaceInfo to get the actual data we want */
252 if ((dwRetVal = GetInterfaceInfo(pInfo, &ulOutBufLen)) == NO_ERROR )
253 {
254 AdapterInfo = pInfo->Adapter[0];
255 _tprintf(_T("name - %S\n"), pInfo->Adapter[0].Name);
256 }
257 else
258 {
259 _tprintf(_T("\nGetInterfaceInfo failed : "));
260 DoFormatMessage(dwRetVal);
261 }
262 }
263 else
264 {
265 ;
266 /* we need to be able to release connections by name with support for globbing
267 * i.e. ipconfig /release Eth* will release all cards starting with Eth...
268 * ipconfig /release *con* will release all cards with 'con' in their name
269 */
270 }
271
272
273 /* Call IpReleaseAddress to release the IP address on the specified adapter. */
274 if ((dwRetVal = IpReleaseAddress(&AdapterInfo)) != NO_ERROR)
275 {
276 _tprintf(_T("\nAn error occured while releasing interface %s : "), _T("*name*"));
277 DoFormatMessage(dwRetVal);
278 }
279 return 0;
280 }
281
282
283
284
285 INT Renew(TCHAR Index)
286 {
287 IP_ADAPTER_INDEX_MAP AdapterInfo;
288 DWORD dwRetVal = 0;
289
290 /* if interface is not given, query GetInterfaceInfo */
291 if (Index == (TCHAR)NULL)
292 {
293 PIP_INTERFACE_INFO pInfo;
294 ULONG ulOutBufLen;
295 pInfo = (IP_INTERFACE_INFO *) malloc(sizeof(IP_INTERFACE_INFO));
296 ulOutBufLen = 0;
297
298 /* Make an initial call to GetInterfaceInfo to get
299 * the necessary size into the ulOutBufLen variable */
300 if ( GetInterfaceInfo(pInfo, &ulOutBufLen) == ERROR_INSUFFICIENT_BUFFER)
301 {
302 GlobalFree(pInfo);
303 pInfo = (IP_INTERFACE_INFO *) malloc (ulOutBufLen);
304 }
305
306 /* Make a second call to GetInterfaceInfo to get the actual data we want */
307 if ((dwRetVal = GetInterfaceInfo(pInfo, &ulOutBufLen)) == NO_ERROR )
308 {
309 AdapterInfo = pInfo->Adapter[0];
310 _tprintf(_T("name - %S\n"), pInfo->Adapter[0].Name);
311 } else {
312 _tprintf(_T("\nGetInterfaceInfo failed : "));
313 DoFormatMessage(dwRetVal);
314 }
315 }
316 else
317 {
318 ;
319 /* we need to be able to renew connections by name with support for globbing
320 * i.e. ipconfig /renew Eth* will renew all cards starting with Eth...
321 * ipconfig /renew *con* will renew all cards with 'con' in their name
322 */
323 }
324
325
326 /* Call IpRenewAddress to renew the IP address on the specified adapter. */
327 if ((dwRetVal = IpRenewAddress(&AdapterInfo)) != NO_ERROR)
328 {
329 _tprintf(_T("\nAn error occured while renew interface %s : "), _T("*name*"));
330 DoFormatMessage(dwRetVal);
331 }
332 return 0;
333 }
334
335 /* temp func for testing purposes */
336 VOID Info()
337 {
338 // Declare and initialize variables
339 PIP_INTERFACE_INFO pInfo;
340 ULONG ulOutBufLen;
341 DWORD dwRetVal;
342
343 pInfo = (IP_INTERFACE_INFO *) malloc( sizeof(IP_INTERFACE_INFO) );
344 ulOutBufLen = sizeof(IP_INTERFACE_INFO);
345 dwRetVal = 0;
346
347
348 // Make an initial call to GetInterfaceInfo to get
349 // the necessary size in the ulOutBufLen variable
350 if ( GetInterfaceInfo(pInfo, &ulOutBufLen) == ERROR_INSUFFICIENT_BUFFER)
351 {
352 free(pInfo);
353 pInfo = (IP_INTERFACE_INFO *) malloc (ulOutBufLen);
354 }
355
356 // Make a second call to GetInterfaceInfo to get
357 // the actual data we need
358 if ((dwRetVal = GetInterfaceInfo(pInfo, &ulOutBufLen)) == NO_ERROR )
359 {
360 int i;
361 for (i=0; i<pInfo->NumAdapters; i++)
362 {
363 printf("\tAdapter Name: %S\n", pInfo->Adapter[i].Name);
364 printf("\tAdapter Index: %ld\n", pInfo->Adapter[i].Index);
365 printf("\tNum Adapters: %ld\n", pInfo->NumAdapters);
366 }
367 }
368 else
369 {
370 printf("GetInterfaceInfo failed.\n");
371 DoFormatMessage(dwRetVal);
372 }
373 }
374
375
376 VOID Usage(VOID)
377 {
378 _tprintf(_T("\nUSAGE:\n"
379 " ipconfig [/? | /all | /renew [adapter] | /release [adapter] |\n"
380 " /flushdns | /displaydns | /registerdns |\n"
381 " /showclassid adapter |\n"
382 " /setclassid adapter [classid] ]\n"
383 "\n"
384 "where\n"
385 " adapter Connection name\n"
386 " (wildcard characters * and ? allowed, see examples)\n"
387 "\n"
388 " Options:\n"
389 " /? Display this help message\n"
390 " /all Display full configuration information.\n"
391 " /release Release the IP address for the specified adapter.\n"
392 " /renew Renew the IP address for the specified adapter.\n"
393 " /flushdns Purges the DNS Resolver cache.\n"
394 " /registerdns Refreshes all DHCP leases and re-registers DNS names.\n"
395 " /displaydns Display the contents of the DNS Resolver Cache.\n"
396 " /showclassid Displays all the dhcp class IDs allowed for adapter.\n"
397 " /setclassid Modifies the dhcp class id.\n"
398 "\n"
399 "The default is to display only the IP address, subnet mask and\n"
400 "default gateway for each adapter bound to TCP/IP.\n"
401 "\n"
402 "For Release and Renew, if no adapter name is specified, then the IP address\n"
403 "leases for all adapters bound to TCP/IP will be released or renewed.\n"
404 "\n"
405 "For Setclassid, if no ClassId is specified, then the ClassId is removed.\n"
406 "\n"
407 "Examples:\n"
408 " > ipconfig ... Show information.\n"
409 " > ipconfig /all ... Show detailed information\n"
410 " > ipconfig /renew ... renew all adapters\n"
411 " > ipconfig /renew EL* ... renew any connection that has its\n"
412 " name starting with EL\n"
413 " > ipconfig /release *Con* ... release all matching connections,\n"
414 " eg. \"Local Area Connection 1\" or\n"
415 " \"Local Area Connection 2\"\n"));
416 }
417
418 int main(int argc, char *argv[])
419 {
420 BOOL DoUsage=FALSE;
421 BOOL DoAll=FALSE;
422 BOOL DoRelease=FALSE;
423 BOOL DoRenew=FALSE;
424 BOOL DoFlushdns=FALSE;
425 BOOL DoRegisterdns=FALSE;
426 BOOL DoDisplaydns=FALSE;
427 BOOL DoShowclassid=FALSE;
428 BOOL DoSetclassid=FALSE;
429
430 /* Parse command line for options we have been given. */
431 if ( (argc > 1)&&(argv[1][0]=='/') )
432 {
433 if( !_tcsicmp( &argv[1][1], _T("?") ))
434 {
435 DoUsage = TRUE;
436 }
437 else if( !_tcsnicmp( &argv[1][1], _T("ALL"), _tcslen(&argv[1][1]) ))
438 {
439 DoAll = TRUE;
440 }
441 else if( !_tcsnicmp( &argv[1][1], _T("RELEASE"), _tcslen(&argv[1][1]) ))
442 {
443 DoRelease = TRUE;
444 }
445 else if( ! _tcsnicmp( &argv[1][1], _T("RENEW"), _tcslen(&argv[1][1]) ))
446 {
447 DoRenew = TRUE;
448 }
449 else if( ! _tcsnicmp( &argv[1][1], _T("FLUSHDNS"), _tcslen(&argv[1][1]) ))
450 {
451 DoFlushdns = TRUE;
452 }
453 else if( ! _tcsnicmp( &argv[1][1], _T("FLUSHREGISTERDNS"), _tcslen(&argv[1][1]) ))
454 {
455 DoRegisterdns = TRUE;
456 }
457 else if( ! _tcsnicmp( &argv[1][1], _T("DISPLAYDNS"), _tcslen(&argv[1][1]) ))
458 {
459 DoDisplaydns = TRUE;
460 }
461 else if( ! _tcsnicmp( &argv[1][1], _T("SHOWCLASSID"), _tcslen(&argv[1][1]) ))
462 {
463 DoShowclassid = TRUE;
464 }
465 else if( ! _tcsnicmp( &argv[1][1], _T("SETCLASSID"), _tcslen(&argv[1][1]) ))
466 {
467 DoSetclassid = TRUE;
468 }
469 }
470
471 switch (argc)
472 {
473 case 1: /* Default behaviour if no options are given*/
474 ShowInfo(FALSE);
475 break;
476 case 2: /* Process all the options that take no paramiters */
477 if (DoUsage)
478 Usage();
479 else if (DoAll)
480 ShowInfo(TRUE);
481 else if (DoRelease)
482 Release((TCHAR)NULL);
483 else if (DoRenew)
484 Renew((TCHAR)NULL);
485 else if (DoFlushdns)
486 _tprintf(_T("\nSorry /flushdns is not implemented yet\n"));
487 else if (DoRegisterdns)
488 _tprintf(_T("\nSorry /registerdns is not implemented yet\n"));
489 else if (DoDisplaydns)
490 _tprintf(_T("\nSorry /displaydns is not implemented yet\n"));
491 else
492 Usage();
493 break;
494 case 3: /* Process all the options that can have 1 paramiters */
495 if (DoRelease)
496 _tprintf(_T("\nSorry /release [adapter] is not implemented yet\n"));
497 //Release(argv[2]);
498 else if (DoRenew)
499 _tprintf(_T("\nSorry /renew [adapter] is not implemented yet\n"));
500 else if (DoShowclassid)
501 _tprintf(_T("\nSorry /showclassid adapter is not implemented yet\n"));
502 else if (DoSetclassid)
503 _tprintf(_T("\nSorry /setclassid adapter is not implemented yet\n"));
504 else
505 Usage();
506 break;
507 case 4: /* Process all the options that can have 2 paramiters */
508 if (DoSetclassid)
509 _tprintf(_T("\nSorry /setclassid adapter [classid]is not implemented yet\n"));
510 else
511 Usage();
512 break;
513 default:
514 Usage();
515 }
516
517 return 0;
518 }