1 /* 2 * PROJECT: ReactOS ipconfig utility 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: base/applications/network/ipconfig/ipconfig.c 5 * PURPOSE: Display IP info for net adapters 6 * PROGRAMMERS: Copyright 2005 - 2006 Ged Murphy (gedmurphy@gmail.com) 7 */ 8 /* 9 * TODO: 10 * fix renew / release 11 * implement registerdns, showclassid, setclassid 12 * allow globbing on adapter names 13 */ 14 15 #define WIN32_NO_STATUS 16 #include <stdarg.h> 17 #include <windef.h> 18 #include <winbase.h> 19 #include <winuser.h> 20 #include <winreg.h> 21 #include <stdio.h> 22 #include <tchar.h> 23 #include <time.h> 24 #include <iphlpapi.h> 25 #include <ndk/rtlfuncs.h> 26 #include <inaddr.h> 27 #include <windns.h> 28 #include <windns_undoc.h> 29 30 #include "resource.h" 31 32 typedef struct _RECORDTYPE 33 { 34 WORD wRecordType; 35 LPTSTR pszRecordName; 36 } RECORDTYPE, *PRECORDTYPE; 37 38 #define GUID_LEN 40 39 40 HINSTANCE hInstance; 41 HANDLE ProcessHeap; 42 43 RECORDTYPE TypeArray[] = 44 { 45 {DNS_TYPE_ZERO, _T("ZERO")}, 46 {DNS_TYPE_A, _T("A")}, 47 {DNS_TYPE_NS, _T("NS")}, 48 {DNS_TYPE_MD, _T("MD")}, 49 {DNS_TYPE_MF, _T("MF")}, 50 {DNS_TYPE_CNAME, _T("CNAME")}, 51 {DNS_TYPE_SOA, _T("SOA")}, 52 {DNS_TYPE_MB, _T("MB")}, 53 {DNS_TYPE_MG, _T("MG")}, 54 {DNS_TYPE_MR, _T("MR")}, 55 {DNS_TYPE_NULL, _T("NULL")}, 56 {DNS_TYPE_WKS, _T("WKS")}, 57 {DNS_TYPE_PTR, _T("PTR")}, 58 {DNS_TYPE_HINFO, _T("HINFO")}, 59 {DNS_TYPE_MINFO, _T("MINFO")}, 60 {DNS_TYPE_MX, _T("MX")}, 61 {DNS_TYPE_TEXT, _T("TXT")}, 62 {DNS_TYPE_RP, _T("RP")}, 63 {DNS_TYPE_AFSDB, _T("AFSDB")}, 64 {DNS_TYPE_X25, _T("X25")}, 65 {DNS_TYPE_ISDN, _T("ISDN")}, 66 {DNS_TYPE_RT, _T("RT")}, 67 {DNS_TYPE_NSAP, _T("NSAP")}, 68 {DNS_TYPE_NSAPPTR, _T("NSAPPTR")}, 69 {DNS_TYPE_SIG, _T("SIG")}, 70 {DNS_TYPE_KEY, _T("KEY")}, 71 {DNS_TYPE_PX, _T("PX")}, 72 {DNS_TYPE_GPOS, _T("GPOS")}, 73 {DNS_TYPE_AAAA, _T("AAAA")}, 74 {DNS_TYPE_LOC, _T("LOC")}, 75 {DNS_TYPE_NXT, _T("NXT")}, 76 {DNS_TYPE_EID, _T("EID")}, 77 {DNS_TYPE_NIMLOC, _T("NIMLOC")}, 78 {DNS_TYPE_SRV, _T("SRV")}, 79 {DNS_TYPE_ATMA, _T("ATMA")}, 80 {DNS_TYPE_NAPTR, _T("NAPTR")}, 81 {DNS_TYPE_KX, _T("KX")}, 82 {DNS_TYPE_CERT, _T("CERT")}, 83 {DNS_TYPE_A6, _T("A6")}, 84 {DNS_TYPE_DNAME, _T("DNAME")}, 85 {DNS_TYPE_SINK, _T("SINK")}, 86 {DNS_TYPE_OPT, _T("OPT")}, 87 {DNS_TYPE_UINFO, _T("UINFO")}, 88 {DNS_TYPE_UID, _T("UID")}, 89 {DNS_TYPE_GID, _T("GID")}, 90 {DNS_TYPE_UNSPEC, _T("UNSPEC")}, 91 {DNS_TYPE_ADDRS, _T("ADDRS")}, 92 {DNS_TYPE_TKEY, _T("TKEY")}, 93 {DNS_TYPE_TSIG, _T("TSIG")}, 94 {DNS_TYPE_IXFR, _T("IXFR")}, 95 {DNS_TYPE_AXFR, _T("AXFR")}, 96 {DNS_TYPE_MAILB, _T("MAILB")}, 97 {DNS_TYPE_MAILA, _T("MAILA")}, 98 {DNS_TYPE_ALL, _T("ALL")}, 99 {0, NULL} 100 }; 101 102 LPTSTR 103 GetRecordTypeName(WORD wType) 104 { 105 static TCHAR szType[8]; 106 INT i; 107 108 for (i = 0; ; i++) 109 { 110 if (TypeArray[i].pszRecordName == NULL) 111 break; 112 113 if (TypeArray[i].wRecordType == wType) 114 return TypeArray[i].pszRecordName; 115 } 116 117 _stprintf(szType, _T("%hu"), wType); 118 119 return szType; 120 } 121 122 int LoadStringAndOem(HINSTANCE hInst, 123 UINT uID, 124 LPTSTR szNode, 125 int byteSize) 126 { 127 TCHAR *szTmp; 128 int res; 129 130 szTmp = (LPTSTR)HeapAlloc(ProcessHeap, 0, byteSize); 131 if (szTmp == NULL) 132 { 133 return 0; 134 } 135 136 res = LoadString(hInst, uID, szTmp, byteSize); 137 CharToOem(szTmp, szNode); 138 HeapFree(ProcessHeap, 0, szTmp); 139 return res; 140 } 141 142 LPTSTR GetNodeTypeName(UINT NodeType) 143 { 144 static TCHAR szNode[14]; 145 146 switch (NodeType) 147 { 148 case 1: 149 if (!LoadStringAndOem(hInstance, IDS_BCAST, szNode, sizeof(szNode))) 150 return NULL; 151 break; 152 153 case 2: 154 if (!LoadStringAndOem(hInstance, IDS_P2P, szNode, sizeof(szNode))) 155 return NULL; 156 break; 157 158 case 4: 159 if (!LoadStringAndOem(hInstance, IDS_MIXED, szNode, sizeof(szNode))) 160 return NULL; 161 break; 162 163 case 8: 164 if (!LoadStringAndOem(hInstance, IDS_HYBRID, szNode, sizeof(szNode))) 165 return NULL; 166 break; 167 168 default : 169 if (!LoadStringAndOem(hInstance, IDS_UNKNOWN, szNode, sizeof(szNode))) 170 return NULL; 171 break; 172 } 173 174 return szNode; 175 } 176 177 178 LPTSTR GetInterfaceTypeName(UINT InterfaceType) 179 { 180 static TCHAR szIntType[25]; 181 182 switch (InterfaceType) 183 { 184 case MIB_IF_TYPE_OTHER: 185 if (!LoadStringAndOem(hInstance, IDS_OTHER, szIntType, sizeof(szIntType))) 186 return NULL; 187 break; 188 189 case MIB_IF_TYPE_ETHERNET: 190 if (!LoadStringAndOem(hInstance, IDS_ETH, szIntType, sizeof(szIntType))) 191 return NULL; 192 break; 193 194 case MIB_IF_TYPE_TOKENRING: 195 if (!LoadStringAndOem(hInstance, IDS_TOKEN, szIntType, sizeof(szIntType))) 196 return NULL; 197 break; 198 199 case MIB_IF_TYPE_FDDI: 200 if (!LoadStringAndOem(hInstance, IDS_FDDI, szIntType, sizeof(szIntType))) 201 return NULL; 202 break; 203 204 case MIB_IF_TYPE_PPP: 205 if (!LoadStringAndOem(hInstance, IDS_PPP, szIntType, sizeof(szIntType))) 206 return NULL; 207 break; 208 209 case MIB_IF_TYPE_LOOPBACK: 210 if (!LoadStringAndOem(hInstance, IDS_LOOP, szIntType, sizeof(szIntType))) 211 return NULL; 212 break; 213 214 case MIB_IF_TYPE_SLIP: 215 if (!LoadStringAndOem(hInstance, IDS_SLIP, szIntType, sizeof(szIntType))) 216 return NULL; 217 break; 218 219 default: 220 if (!LoadStringAndOem(hInstance, IDS_UNKNOWN, szIntType, sizeof(szIntType))) 221 return NULL; 222 break; 223 } 224 225 return szIntType; 226 } 227 228 229 /* print MAC address */ 230 PTCHAR PrintMacAddr(PBYTE Mac) 231 { 232 static TCHAR MacAddr[20]; 233 234 _stprintf(MacAddr, _T("%02x-%02x-%02x-%02x-%02x-%02x"), 235 Mac[0], Mac[1], Mac[2], Mac[3], Mac[4], Mac[5]); 236 237 return MacAddr; 238 } 239 240 241 VOID DoFormatMessage(LONG ErrorCode) 242 { 243 LPVOID lpMsgBuf; 244 //DWORD ErrorCode; 245 246 if (ErrorCode == 0) 247 ErrorCode = GetLastError(); 248 249 if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 250 FORMAT_MESSAGE_FROM_SYSTEM | 251 FORMAT_MESSAGE_IGNORE_INSERTS, 252 NULL, 253 ErrorCode, 254 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ 255 (LPTSTR) &lpMsgBuf, 256 0, 257 NULL)) 258 { 259 _tprintf(_T("%s"), (LPTSTR)lpMsgBuf); 260 LocalFree(lpMsgBuf); 261 } 262 } 263 264 265 LPTSTR GetConnectionType(LPTSTR lpClass) 266 { 267 HKEY hKey = NULL; 268 LPTSTR ConType = NULL; 269 LPTSTR ConTypeTmp = NULL; 270 TCHAR Path[256]; 271 LPTSTR PrePath = _T("SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\"); 272 LPTSTR PostPath = _T("\\Connection"); 273 DWORD PathSize; 274 DWORD dwType; 275 DWORD dwDataSize; 276 277 /* don't overflow the buffer */ 278 PathSize = lstrlen(PrePath) + lstrlen(lpClass) + lstrlen(PostPath) + 1; 279 if (PathSize >= 255) 280 return NULL; 281 282 wsprintf(Path, _T("%s%s%s"), PrePath, lpClass, PostPath); 283 284 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 285 Path, 286 0, 287 KEY_READ, 288 &hKey) == ERROR_SUCCESS) 289 { 290 if (RegQueryValueEx(hKey, 291 _T("Name"), 292 NULL, 293 &dwType, 294 NULL, 295 &dwDataSize) == ERROR_SUCCESS) 296 { 297 ConTypeTmp = (LPTSTR)HeapAlloc(ProcessHeap, 298 0, 299 dwDataSize); 300 301 if (ConTypeTmp == NULL) 302 return NULL; 303 304 ConType = (LPTSTR)HeapAlloc(ProcessHeap, 305 0, 306 dwDataSize); 307 308 if (ConType == NULL) 309 { 310 HeapFree(ProcessHeap, 0, ConTypeTmp); 311 return NULL; 312 } 313 314 if (RegQueryValueEx(hKey, 315 _T("Name"), 316 NULL, 317 &dwType, 318 (PBYTE)ConTypeTmp, 319 &dwDataSize) != ERROR_SUCCESS) 320 { 321 HeapFree(ProcessHeap, 322 0, 323 ConType); 324 325 ConType = NULL; 326 } 327 328 if (ConType) 329 CharToOem(ConTypeTmp, ConType); 330 HeapFree(ProcessHeap, 0, ConTypeTmp); 331 } 332 } 333 334 if (hKey != NULL) 335 RegCloseKey(hKey); 336 337 return ConType; 338 } 339 340 341 LPTSTR GetConnectionDescription(LPTSTR lpClass) 342 { 343 HKEY hBaseKey = NULL; 344 HKEY hClassKey = NULL; 345 LPTSTR lpKeyClass = NULL; 346 LPTSTR lpConDesc = NULL; 347 LPTSTR lpPath = NULL; 348 TCHAR szPrePath[] = _T("SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002bE10318}\\"); 349 DWORD dwType; 350 DWORD dwDataSize; 351 INT i; 352 353 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 354 szPrePath, 355 0, 356 KEY_READ, 357 &hBaseKey) != ERROR_SUCCESS) 358 { 359 return NULL; 360 } 361 362 for (i = 0; ; i++) 363 { 364 DWORD PathSize; 365 LONG Status; 366 TCHAR szName[10]; 367 DWORD NameLen = 9; 368 369 if ((Status = RegEnumKeyEx(hBaseKey, 370 i, 371 szName, 372 &NameLen, 373 NULL, 374 NULL, 375 NULL, 376 NULL)) != ERROR_SUCCESS) 377 { 378 if (Status == ERROR_NO_MORE_ITEMS) 379 { 380 DoFormatMessage(Status); 381 lpConDesc = NULL; 382 goto CLEANUP; 383 } 384 else 385 continue; 386 } 387 388 PathSize = lstrlen(szPrePath) + lstrlen(szName) + 1; 389 lpPath = (LPTSTR)HeapAlloc(ProcessHeap, 390 0, 391 PathSize * sizeof(TCHAR)); 392 if (lpPath == NULL) 393 goto CLEANUP; 394 395 wsprintf(lpPath, _T("%s%s"), szPrePath, szName); 396 397 //MessageBox(NULL, lpPath, NULL, 0); 398 399 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, 400 lpPath, 401 0, 402 KEY_READ, 403 &hClassKey) != ERROR_SUCCESS) 404 { 405 goto CLEANUP; 406 } 407 408 HeapFree(ProcessHeap, 0, lpPath); 409 lpPath = NULL; 410 411 if (RegQueryValueEx(hClassKey, 412 _T("NetCfgInstanceId"), 413 NULL, 414 &dwType, 415 NULL, 416 &dwDataSize) == ERROR_SUCCESS) 417 { 418 lpKeyClass = (LPTSTR)HeapAlloc(ProcessHeap, 419 0, 420 dwDataSize); 421 if (lpKeyClass == NULL) 422 goto CLEANUP; 423 424 if (RegQueryValueEx(hClassKey, 425 _T("NetCfgInstanceId"), 426 NULL, 427 &dwType, 428 (PBYTE)lpKeyClass, 429 &dwDataSize) != ERROR_SUCCESS) 430 { 431 HeapFree(ProcessHeap, 0, lpKeyClass); 432 lpKeyClass = NULL; 433 continue; 434 } 435 } 436 else 437 continue; 438 439 if (!lstrcmp(lpClass, lpKeyClass)) 440 { 441 HeapFree(ProcessHeap, 0, lpKeyClass); 442 lpKeyClass = NULL; 443 444 if (RegQueryValueEx(hClassKey, 445 _T("DriverDesc"), 446 NULL, 447 &dwType, 448 NULL, 449 &dwDataSize) == ERROR_SUCCESS) 450 { 451 lpConDesc = (LPTSTR)HeapAlloc(ProcessHeap, 452 0, 453 dwDataSize); 454 if (lpConDesc == NULL) 455 goto CLEANUP; 456 457 if (RegQueryValueEx(hClassKey, 458 _T("DriverDesc"), 459 NULL, 460 &dwType, 461 (PBYTE)lpConDesc, 462 &dwDataSize) != ERROR_SUCCESS) 463 { 464 HeapFree(ProcessHeap, 0, lpConDesc); 465 lpConDesc = NULL; 466 goto CLEANUP; 467 } 468 } 469 else 470 { 471 lpConDesc = NULL; 472 } 473 474 break; 475 } 476 } 477 478 CLEANUP: 479 if (hBaseKey != NULL) 480 RegCloseKey(hBaseKey); 481 if (hClassKey != NULL) 482 RegCloseKey(hClassKey); 483 if (lpPath != NULL) 484 HeapFree(ProcessHeap, 0, lpPath); 485 if (lpKeyClass != NULL) 486 HeapFree(ProcessHeap, 0, lpKeyClass); 487 488 return lpConDesc; 489 } 490 491 492 VOID ShowInfo(BOOL bAll) 493 { 494 MIB_IFROW mibEntry; 495 PIP_ADAPTER_INFO pAdapterInfo = NULL; 496 PIP_ADAPTER_INFO pAdapter = NULL; 497 ULONG adaptOutBufLen = 0; 498 PFIXED_INFO pFixedInfo = NULL; 499 ULONG netOutBufLen = 0; 500 PIP_PER_ADAPTER_INFO pPerAdapterInfo = NULL; 501 ULONG ulPerAdapterInfoLength = 0; 502 PSTR pszDomainName = NULL; 503 DWORD dwDomainNameSize = 0; 504 ULONG ret = 0; 505 506 GetComputerNameExA(ComputerNameDnsDomain, 507 NULL, 508 &dwDomainNameSize); 509 if (dwDomainNameSize > 0) 510 { 511 pszDomainName = HeapAlloc(ProcessHeap, 512 0, 513 dwDomainNameSize * sizeof(TCHAR)); 514 if (pszDomainName != NULL) 515 GetComputerNameExA(ComputerNameDnsDomain, 516 pszDomainName, 517 &dwDomainNameSize); 518 } 519 520 /* call GetAdaptersInfo to obtain the adapter info */ 521 ret = GetAdaptersInfo(pAdapterInfo, &adaptOutBufLen); 522 if (ret == ERROR_BUFFER_OVERFLOW) 523 { 524 pAdapterInfo = (IP_ADAPTER_INFO *)HeapAlloc(ProcessHeap, 0, adaptOutBufLen); 525 if (pAdapterInfo == NULL) 526 goto done; 527 528 ret = GetAdaptersInfo(pAdapterInfo, &adaptOutBufLen); 529 if (ret != NO_ERROR) 530 { 531 DoFormatMessage(0); 532 goto done; 533 } 534 } 535 else 536 { 537 if (ret != ERROR_NO_DATA) 538 { 539 DoFormatMessage(0); 540 goto done; 541 } 542 } 543 544 /* call GetNetworkParams to obtain the network info */ 545 if (GetNetworkParams(pFixedInfo, &netOutBufLen) == ERROR_BUFFER_OVERFLOW) 546 { 547 pFixedInfo = (FIXED_INFO *)HeapAlloc(ProcessHeap, 0, netOutBufLen); 548 if (pFixedInfo == NULL) 549 { 550 goto done; 551 } 552 if (GetNetworkParams(pFixedInfo, &netOutBufLen) != NO_ERROR) 553 { 554 DoFormatMessage(0); 555 goto done; 556 } 557 } 558 else 559 { 560 DoFormatMessage(0); 561 goto done; 562 } 563 564 pAdapter = pAdapterInfo; 565 566 _tprintf(_T("\nReactOS IP Configuration\n\n")); 567 if (bAll) 568 { 569 _tprintf(_T("\tHost Name . . . . . . . . . . . . : %s\n"), pFixedInfo->HostName); 570 _tprintf(_T("\tPrimary DNS Suffix. . . . . . . . : %s\n"), (pszDomainName != NULL) ? pszDomainName : ""); 571 _tprintf(_T("\tNode Type . . . . . . . . . . . . : %s\n"), GetNodeTypeName(pFixedInfo->NodeType)); 572 if (pFixedInfo->EnableRouting) 573 _tprintf(_T("\tIP Routing Enabled. . . . . . . . : Yes\n")); 574 else 575 _tprintf(_T("\tIP Routing Enabled. . . . . . . . : No\n")); 576 if (pAdapter && pAdapter->HaveWins) 577 _tprintf(_T("\tWINS Proxy enabled. . . . . . . . : Yes\n")); 578 else 579 _tprintf(_T("\tWINS Proxy enabled. . . . . . . . : No\n")); 580 if (pszDomainName != NULL && pszDomainName[0] != 0) 581 { 582 _tprintf(_T("\tDNS Suffix Search List. . . . . . : %s\n"), pszDomainName); 583 _tprintf(_T("\t %s\n"), pFixedInfo->DomainName); 584 } 585 else 586 { 587 _tprintf(_T("\tDNS Suffix Search List. . . . . . : %s\n"), pFixedInfo->DomainName); 588 } 589 } 590 591 while (pAdapter) 592 { 593 LPTSTR IntType, myConType; 594 BOOLEAN bConnected = TRUE; 595 596 mibEntry.dwIndex = pAdapter->Index; 597 GetIfEntry(&mibEntry); 598 599 IntType = GetInterfaceTypeName(pAdapter->Type); 600 myConType = GetConnectionType(pAdapter->AdapterName); 601 602 _tprintf(_T("\n%s %s: \n\n"), IntType , myConType); 603 604 if (myConType != NULL) HeapFree(ProcessHeap, 0, myConType); 605 606 if (GetPerAdapterInfo(pAdapter->Index, pPerAdapterInfo, &ulPerAdapterInfoLength) == ERROR_BUFFER_OVERFLOW) 607 { 608 pPerAdapterInfo = (PIP_PER_ADAPTER_INFO)HeapAlloc(ProcessHeap, 0, ulPerAdapterInfoLength); 609 if (pPerAdapterInfo != NULL) 610 { 611 GetPerAdapterInfo(pAdapter->Index, pPerAdapterInfo, &ulPerAdapterInfoLength); 612 } 613 } 614 615 /* check if the adapter is connected to the media */ 616 if (mibEntry.dwOperStatus != MIB_IF_OPER_STATUS_CONNECTED && mibEntry.dwOperStatus != MIB_IF_OPER_STATUS_OPERATIONAL) 617 { 618 bConnected = FALSE; 619 _tprintf(_T("\tMedia State . . . . . . . . . . . : Media disconnected\n")); 620 } 621 else 622 { 623 _tprintf(_T("\tConnection-specific DNS Suffix. . : %s\n"), pFixedInfo->DomainName); 624 } 625 626 if (bAll) 627 { 628 LPTSTR lpDesc = GetConnectionDescription(pAdapter->AdapterName); 629 _tprintf(_T("\tDescription . . . . . . . . . . . : %s\n"), lpDesc); 630 HeapFree(ProcessHeap, 0, lpDesc); 631 _tprintf(_T("\tPhysical Address. . . . . . . . . : %s\n"), PrintMacAddr(pAdapter->Address)); 632 if (bConnected) 633 { 634 if (pAdapter->DhcpEnabled) 635 { 636 _tprintf(_T("\tDHCP Enabled. . . . . . . . . . . : Yes\n")); 637 if (pPerAdapterInfo != NULL) 638 { 639 if (pPerAdapterInfo->AutoconfigEnabled) 640 _tprintf(_T("\tAutoconfiguration Enabled . . . . : Yes\n")); 641 else 642 _tprintf(_T("\tAutoconfiguration Enabled . . . . : No\n")); 643 } 644 } 645 else 646 { 647 _tprintf(_T("\tDHCP Enabled. . . . . . . . . . . : No\n")); 648 } 649 } 650 } 651 652 if (!bConnected) 653 { 654 pAdapter = pAdapter->Next; 655 continue; 656 } 657 658 _tprintf(_T("\tIP Address. . . . . . . . . . . . : %s\n"), pAdapter->IpAddressList.IpAddress.String); 659 _tprintf(_T("\tSubnet Mask . . . . . . . . . . . : %s\n"), pAdapter->IpAddressList.IpMask.String); 660 if (pAdapter->GatewayList.IpAddress.String[0] != '0') 661 _tprintf(_T("\tDefault Gateway . . . . . . . . . : %s\n"), pAdapter->GatewayList.IpAddress.String); 662 else 663 _tprintf(_T("\tDefault Gateway . . . . . . . . . :\n")); 664 665 if (bAll) 666 { 667 PIP_ADDR_STRING pIPAddr; 668 669 if (pAdapter->DhcpEnabled) 670 _tprintf(_T("\tDHCP Server . . . . . . . . . . . : %s\n"), pAdapter->DhcpServer.IpAddress.String); 671 672 _tprintf(_T("\tDNS Servers . . . . . . . . . . . : ")); 673 _tprintf(_T("%s\n"), pFixedInfo->DnsServerList.IpAddress.String); 674 pIPAddr = pFixedInfo->DnsServerList.Next; 675 while (pIPAddr) 676 { 677 _tprintf(_T("\t\t\t\t\t %s\n"), pIPAddr ->IpAddress.String ); 678 pIPAddr = pIPAddr->Next; 679 } 680 681 if (pAdapter->HaveWins) 682 { 683 _tprintf(_T("\tPrimary WINS Server . . . . . . . : %s\n"), pAdapter->PrimaryWinsServer.IpAddress.String); 684 _tprintf(_T("\tSecondary WINS Server . . . . . . : %s\n"), pAdapter->SecondaryWinsServer.IpAddress.String); 685 } 686 687 if (pAdapter->DhcpEnabled && _tcscmp(pAdapter->DhcpServer.IpAddress.String, _T("255.255.255.255"))) 688 { 689 _tprintf(_T("\tLease Obtained. . . . . . . . . . : %s"), _tasctime(localtime(&pAdapter->LeaseObtained))); 690 _tprintf(_T("\tLease Expires . . . . . . . . . . : %s"), _tasctime(localtime(&pAdapter->LeaseExpires))); 691 } 692 } 693 _tprintf(_T("\n")); 694 695 HeapFree(ProcessHeap, 0, pPerAdapterInfo); 696 pPerAdapterInfo = NULL; 697 698 pAdapter = pAdapter->Next; 699 } 700 701 done: 702 if (pszDomainName) 703 HeapFree(ProcessHeap, 0, pszDomainName); 704 if (pFixedInfo) 705 HeapFree(ProcessHeap, 0, pFixedInfo); 706 if (pAdapterInfo) 707 HeapFree(ProcessHeap, 0, pAdapterInfo); 708 } 709 710 VOID Release(LPTSTR Index) 711 { 712 IP_ADAPTER_INDEX_MAP AdapterInfo; 713 DWORD ret; 714 DWORD i; 715 716 /* if interface is not given, query GetInterfaceInfo */ 717 if (Index == NULL) 718 { 719 PIP_INTERFACE_INFO pInfo = NULL; 720 ULONG ulOutBufLen = 0; 721 722 if (GetInterfaceInfo(pInfo, &ulOutBufLen) == ERROR_INSUFFICIENT_BUFFER) 723 { 724 pInfo = (IP_INTERFACE_INFO *)HeapAlloc(ProcessHeap, 0, ulOutBufLen); 725 if (pInfo == NULL) 726 return; 727 728 if (GetInterfaceInfo(pInfo, &ulOutBufLen) == NO_ERROR ) 729 { 730 for (i = 0; i < pInfo->NumAdapters; i++) 731 { 732 CopyMemory(&AdapterInfo, &pInfo->Adapter[i], sizeof(IP_ADAPTER_INDEX_MAP)); 733 _tprintf(_T("name - %ls\n"), pInfo->Adapter[i].Name); 734 735 /* Call IpReleaseAddress to release the IP address on the specified adapter. */ 736 if ((ret = IpReleaseAddress(&AdapterInfo)) != NO_ERROR) 737 { 738 _tprintf(_T("\nAn error occured while releasing interface %ls : \n"), AdapterInfo.Name); 739 DoFormatMessage(ret); 740 } 741 } 742 743 HeapFree(ProcessHeap, 0, pInfo); 744 } 745 else 746 { 747 DoFormatMessage(0); 748 HeapFree(ProcessHeap, 0, pInfo); 749 return; 750 } 751 } 752 else 753 { 754 DoFormatMessage(0); 755 return; 756 } 757 } 758 else 759 { 760 ; 761 /* FIXME: 762 * we need to be able to release connections by name with support for globbing 763 * i.e. ipconfig /release Eth* will release all cards starting with Eth... 764 * ipconfig /release *con* will release all cards with 'con' in their name 765 */ 766 } 767 } 768 769 770 771 772 VOID Renew(LPTSTR Index) 773 { 774 IP_ADAPTER_INDEX_MAP AdapterInfo; 775 DWORD i; 776 777 /* if interface is not given, query GetInterfaceInfo */ 778 if (Index == NULL) 779 { 780 PIP_INTERFACE_INFO pInfo; 781 ULONG ulOutBufLen = 0; 782 783 pInfo = (IP_INTERFACE_INFO *)HeapAlloc(ProcessHeap, 0, sizeof(IP_INTERFACE_INFO)); 784 if (pInfo == NULL) 785 { 786 _tprintf(_T("memory allocation error")); 787 return; 788 } 789 790 /* Make an initial call to GetInterfaceInfo to get 791 * the necessary size into the ulOutBufLen variable */ 792 if (GetInterfaceInfo(pInfo, &ulOutBufLen) == ERROR_INSUFFICIENT_BUFFER) 793 { 794 HeapFree(ProcessHeap, 0, pInfo); 795 pInfo = (IP_INTERFACE_INFO *)HeapAlloc(ProcessHeap, 0, ulOutBufLen); 796 if (pInfo == NULL) 797 { 798 _tprintf(_T("memory allocation error")); 799 return; 800 } 801 } 802 803 /* Make a second call to GetInterfaceInfo to get the actual data we want */ 804 if (GetInterfaceInfo(pInfo, &ulOutBufLen) == NO_ERROR) 805 { 806 for (i = 0; i < pInfo->NumAdapters; i++) 807 { 808 CopyMemory(&AdapterInfo, &pInfo->Adapter[i], sizeof(IP_ADAPTER_INDEX_MAP)); 809 _tprintf(_T("name - %ls\n"), pInfo->Adapter[i].Name); 810 811 /* Call IpRenewAddress to renew the IP address on the specified adapter. */ 812 if (IpRenewAddress(&AdapterInfo) != NO_ERROR) 813 { 814 _tprintf(_T("\nAn error occured while renew interface %s : "), _T("*name*")); 815 DoFormatMessage(0); 816 } 817 } 818 } 819 else 820 { 821 _tprintf(_T("\nGetInterfaceInfo failed : ")); 822 DoFormatMessage(0); 823 } 824 825 HeapFree(ProcessHeap, 0, pInfo); 826 } 827 else 828 { 829 ; 830 /* FIXME: 831 * we need to be able to renew connections by name with support for globbing 832 * i.e. ipconfig /renew Eth* will renew all cards starting with Eth... 833 * ipconfig /renew *con* will renew all cards with 'con' in their name 834 */ 835 } 836 } 837 838 VOID 839 FlushDns(VOID) 840 { 841 _tprintf(_T("\nReactOS IP Configuration\n\n")); 842 843 if (DnsFlushResolverCache()) 844 _tprintf(_T("The DNS Resolver Cache has been deleted.\n")); 845 else 846 DoFormatMessage(GetLastError()); 847 } 848 849 VOID 850 RegisterDns(VOID) 851 { 852 /* FIXME */ 853 _tprintf(_T("\nSorry /registerdns is not implemented yet\n")); 854 } 855 856 static 857 VOID 858 DisplayDnsRecord( 859 PWSTR pszName, 860 WORD wType) 861 { 862 PDNS_RECORDW pQueryResults = NULL, pThisRecord, pNextRecord; 863 WCHAR szBuffer[48]; 864 IN_ADDR Addr4; 865 IN6_ADDR Addr6; 866 DNS_STATUS Status; 867 868 pQueryResults = NULL; 869 Status = DnsQuery_W(pszName, 870 wType, 871 DNS_QUERY_NO_WIRE_QUERY, 872 NULL, 873 (PDNS_RECORD *)&pQueryResults, 874 NULL); 875 if (Status != ERROR_SUCCESS) 876 { 877 if (Status == DNS_ERROR_RCODE_NAME_ERROR) 878 { 879 _tprintf(_T("\t%S\n"), pszName); 880 _tprintf(_T("\t----------------------------------------\n")); 881 _tprintf(_T("\tName does not exist\n\n")); 882 } 883 else if (Status == DNS_INFO_NO_RECORDS) 884 { 885 _tprintf(_T("\t%S\n"), pszName); 886 _tprintf(_T("\t----------------------------------------\n")); 887 _tprintf(_T("\tNo records of type %s\n\n"), GetRecordTypeName(wType)); 888 } 889 return; 890 } 891 892 _tprintf(_T("\t%S\n"), pszName); 893 _tprintf(_T("\t----------------------------------------\n")); 894 895 pThisRecord = pQueryResults; 896 while (pThisRecord != NULL) 897 { 898 pNextRecord = pThisRecord->pNext; 899 900 _tprintf(_T("\tRecord Name . . . . . : %S\n"), pThisRecord->pName); 901 _tprintf(_T("\tRecord Type . . . . . : %hu\n"), pThisRecord->wType); 902 _tprintf(_T("\tTime To Live. . . . . : %lu\n"), pThisRecord->dwTtl); 903 _tprintf(_T("\tData Length . . . . . : %hu\n"), pThisRecord->wDataLength); 904 905 switch (pThisRecord->Flags.S.Section) 906 { 907 case DnsSectionQuestion: 908 _tprintf(_T("\tSection . . . . . . . : Question\n")); 909 break; 910 911 case DnsSectionAnswer: 912 _tprintf(_T("\tSection . . . . . . . : Answer\n")); 913 break; 914 915 case DnsSectionAuthority: 916 _tprintf(_T("\tSection . . . . . . . : Authority\n")); 917 break; 918 919 case DnsSectionAdditional: 920 _tprintf(_T("\tSection . . . . . . . : Additional\n")); 921 break; 922 } 923 924 switch (pThisRecord->wType) 925 { 926 case DNS_TYPE_A: 927 Addr4.S_un.S_addr = pThisRecord->Data.A.IpAddress; 928 RtlIpv4AddressToStringW(&Addr4, szBuffer); 929 _tprintf(_T("\tA (Host) Record . . . : %S\n"), szBuffer); 930 break; 931 932 case DNS_TYPE_NS: 933 _tprintf(_T("\tNS Record . . . . . . : %S\n"), pThisRecord->Data.NS.pNameHost); 934 break; 935 936 case DNS_TYPE_CNAME: 937 _tprintf(_T("\tCNAME Record. . . . . : %S\n"), pThisRecord->Data.CNAME.pNameHost); 938 break; 939 940 case DNS_TYPE_SOA: 941 _tprintf(_T("\tSOA Record. . . . . . : \n")); 942 break; 943 944 case DNS_TYPE_PTR: 945 _tprintf(_T("\tPTR Record. . . . . . : %S\n"), pThisRecord->Data.PTR.pNameHost); 946 break; 947 948 case DNS_TYPE_MX: 949 _tprintf(_T("\tMX Record . . . . . . : \n")); 950 break; 951 952 case DNS_TYPE_AAAA: 953 RtlCopyMemory(&Addr6, &pThisRecord->Data.AAAA.Ip6Address, sizeof(IN6_ADDR)); 954 RtlIpv6AddressToStringW(&Addr6, szBuffer); 955 _tprintf(_T("\tAAAA Record . . . . . : %S\n"), szBuffer); 956 break; 957 958 case DNS_TYPE_ATMA: 959 _tprintf(_T("\tATMA Record . . . . . : \n")); 960 break; 961 962 case DNS_TYPE_SRV: 963 _tprintf(_T("\tSRV Record. . . . . . : \n")); 964 break; 965 } 966 _tprintf(_T("\n\n")); 967 968 pThisRecord = pNextRecord; 969 } 970 971 DnsRecordListFree((PDNS_RECORD)pQueryResults, DnsFreeRecordList); 972 } 973 974 975 VOID 976 DisplayDns(VOID) 977 { 978 PDNS_CACHE_ENTRY DnsEntry = NULL, pThisEntry, pNextEntry; 979 980 _tprintf(_T("\nReactOS IP Configuration\n\n")); 981 982 if (!DnsGetCacheDataTable(&DnsEntry)) 983 { 984 DoFormatMessage(GetLastError()); 985 return; 986 } 987 988 if (DnsEntry == NULL) 989 return; 990 991 pThisEntry = DnsEntry; 992 while (pThisEntry != NULL) 993 { 994 pNextEntry = pThisEntry->pNext; 995 996 if (pThisEntry->wType1 != 0) 997 DisplayDnsRecord(pThisEntry->pszName, pThisEntry->wType1); 998 999 if (pThisEntry->wType2 != 0) 1000 DisplayDnsRecord(pThisEntry->pszName, pThisEntry->wType2); 1001 1002 if (pThisEntry->pszName) 1003 LocalFree(pThisEntry->pszName); 1004 LocalFree(pThisEntry); 1005 1006 pThisEntry = pNextEntry; 1007 } 1008 } 1009 1010 VOID Usage(VOID) 1011 { 1012 HRSRC hRes; 1013 LPTSTR lpUsage; 1014 DWORD Size; 1015 1016 LPTSTR lpName = (LPTSTR)MAKEINTRESOURCE((IDS_USAGE >> 4) + 1); 1017 1018 hRes = FindResource(hInstance, 1019 lpName, 1020 RT_STRING); 1021 if (hRes != NULL) 1022 { 1023 if ((Size = SizeofResource(hInstance, 1024 hRes))) 1025 { 1026 lpUsage = (LPTSTR)HeapAlloc(ProcessHeap, 1027 0, 1028 Size); 1029 if (lpUsage == NULL) 1030 return; 1031 1032 if (LoadStringAndOem(hInstance, 1033 IDS_USAGE, 1034 lpUsage, 1035 Size)) 1036 { 1037 _tprintf(_T("%s"), lpUsage); 1038 } 1039 1040 HeapFree(ProcessHeap, 0, lpUsage); 1041 } 1042 } 1043 } 1044 1045 int main(int argc, char *argv[]) 1046 { 1047 BOOL DoUsage=FALSE; 1048 BOOL DoAll=FALSE; 1049 BOOL DoRelease=FALSE; 1050 BOOL DoRenew=FALSE; 1051 BOOL DoFlushdns=FALSE; 1052 BOOL DoRegisterdns=FALSE; 1053 BOOL DoDisplaydns=FALSE; 1054 BOOL DoShowclassid=FALSE; 1055 BOOL DoSetclassid=FALSE; 1056 1057 hInstance = GetModuleHandle(NULL); 1058 ProcessHeap = GetProcessHeap(); 1059 1060 /* Parse command line for options we have been given. */ 1061 if ((argc > 1) && (argv[1][0]=='/' || argv[1][0]=='-')) 1062 { 1063 if (!_tcsicmp(&argv[1][1], _T("?"))) 1064 { 1065 DoUsage = TRUE; 1066 } 1067 else if (!_tcsnicmp(&argv[1][1], _T("ALL"), _tcslen(&argv[1][1]))) 1068 { 1069 DoAll = TRUE; 1070 } 1071 else if (!_tcsnicmp(&argv[1][1], _T("RELEASE"), _tcslen(&argv[1][1]))) 1072 { 1073 DoRelease = TRUE; 1074 } 1075 else if (!_tcsnicmp(&argv[1][1], _T("RENEW"), _tcslen(&argv[1][1]))) 1076 { 1077 DoRenew = TRUE; 1078 } 1079 else if (!_tcsnicmp(&argv[1][1], _T("FLUSHDNS"), _tcslen(&argv[1][1]))) 1080 { 1081 DoFlushdns = TRUE; 1082 } 1083 else if (!_tcsnicmp(&argv[1][1], _T("FLUSHREGISTERDNS"), _tcslen(&argv[1][1]))) 1084 { 1085 DoRegisterdns = TRUE; 1086 } 1087 else if (!_tcsnicmp(&argv[1][1], _T("DISPLAYDNS"), _tcslen(&argv[1][1]))) 1088 { 1089 DoDisplaydns = TRUE; 1090 } 1091 else if (!_tcsnicmp(&argv[1][1], _T("SHOWCLASSID"), _tcslen(&argv[1][1]))) 1092 { 1093 DoShowclassid = TRUE; 1094 } 1095 else if (!_tcsnicmp(&argv[1][1], _T("SETCLASSID"), _tcslen(&argv[1][1]))) 1096 { 1097 DoSetclassid = TRUE; 1098 } 1099 } 1100 1101 switch (argc) 1102 { 1103 case 1: /* Default behaviour if no options are given*/ 1104 ShowInfo(FALSE); 1105 break; 1106 case 2: /* Process all the options that take no parameters */ 1107 if (DoUsage) 1108 Usage(); 1109 else if (DoAll) 1110 ShowInfo(TRUE); 1111 else if (DoRelease) 1112 Release(NULL); 1113 else if (DoRenew) 1114 Renew(NULL); 1115 else if (DoFlushdns) 1116 FlushDns(); 1117 else if (DoRegisterdns) 1118 RegisterDns(); 1119 else if (DoDisplaydns) 1120 DisplayDns(); 1121 else 1122 Usage(); 1123 break; 1124 case 3: /* Process all the options that can have 1 parameter */ 1125 if (DoRelease) 1126 _tprintf(_T("\nSorry /release [adapter] is not implemented yet\n")); 1127 //Release(argv[2]); 1128 else if (DoRenew) 1129 _tprintf(_T("\nSorry /renew [adapter] is not implemented yet\n")); 1130 else if (DoShowclassid) 1131 _tprintf(_T("\nSorry /showclassid adapter is not implemented yet\n")); 1132 else if (DoSetclassid) 1133 _tprintf(_T("\nSorry /setclassid adapter is not implemented yet\n")); 1134 else 1135 Usage(); 1136 break; 1137 case 4: /* Process all the options that can have 2 parameters */ 1138 if (DoSetclassid) 1139 _tprintf(_T("\nSorry /setclassid adapter [classid]is not implemented yet\n")); 1140 else 1141 Usage(); 1142 break; 1143 default: 1144 Usage(); 1145 } 1146 1147 return 0; 1148 } 1149