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