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