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