Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenarp.c
Go to the documentation of this file.
00001 /* 00002 * ReactOS Win32 Applications 00003 * Copyright (C) 2005 ReactOS Team 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License as published by 00007 * the Free Software Foundation; either version 2 of the License, or 00008 * (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU General Public License along 00016 * with this program; if not, write to the Free Software Foundation, Inc., 00017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00018 */ 00019 00020 /* 00021 * COPYRIGHT: See COPYING in the top level directory 00022 * PROJECT: ReactOS arp utility 00023 * FILE: apps/utils/net/arp/arp.c 00024 * PURPOSE: view and manipulate the ARP cache 00025 * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com) 00026 * REVISIONS: 00027 * GM 27/06/05 Created 00028 * 00029 */ 00030 00031 #define WIN32_LEAN_AND_MEAN 00032 #include <windows.h> 00033 #include <stdio.h> 00034 #include <stdlib.h> 00035 #include <tchar.h> 00036 #include <string.h> 00037 #include <ctype.h> 00038 #include <winsock2.h> 00039 #include <iphlpapi.h> 00040 00041 #define UNICODE 00042 #define _UNICODE 00043 00044 /* 00045 * Globals 00046 */ 00047 const char SEPERATOR = '-'; 00048 int _CRT_glob = 0; // stop * from listing dir files in arp -d * 00049 00050 00051 /* 00052 * function declerations 00053 */ 00054 DWORD DoFormatMessage(VOID); 00055 INT PrintEntries(PMIB_IPNETROW pIpAddRow); 00056 INT DisplayArpEntries(PTCHAR pszInetAddr, PTCHAR pszIfAddr); 00057 INT Addhost(PTCHAR pszInetAddr, PTCHAR pszEthAddr, PTCHAR pszIfAddr); 00058 INT Deletehost(PTCHAR pszInetAddr, PTCHAR pszIfAddr); 00059 VOID Usage(VOID); 00060 00061 00062 /* 00063 * convert error code into meaningful message 00064 */ 00065 DWORD DoFormatMessage(VOID) 00066 { 00067 LPVOID lpMsgBuf; 00068 DWORD RetVal; 00069 00070 DWORD ErrorCode = GetLastError(); 00071 00072 if (ErrorCode != ERROR_SUCCESS) 00073 { 00074 RetVal = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | 00075 FORMAT_MESSAGE_FROM_SYSTEM | 00076 FORMAT_MESSAGE_IGNORE_INSERTS, 00077 NULL, 00078 ErrorCode, 00079 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */ 00080 (LPTSTR) &lpMsgBuf, 00081 0, 00082 NULL ); 00083 00084 if (RetVal != 0) 00085 { 00086 _tprintf(_T("%s"), (LPTSTR)lpMsgBuf); 00087 00088 LocalFree(lpMsgBuf); 00089 /* return number of TCHAR's stored in output buffer 00090 * excluding '\0' - as FormatMessage does*/ 00091 return RetVal; 00092 } 00093 } 00094 return 0; 00095 } 00096 00097 00098 00099 /* 00100 * 00101 * Takes an ARP entry and prints the IP address, 00102 * the MAC address and the entry type to screen 00103 * 00104 */ 00105 INT PrintEntries(PMIB_IPNETROW pIpAddRow) 00106 { 00107 IN_ADDR inaddr; 00108 TCHAR cMacAddr[20]; 00109 00110 /* print IP addresses */ 00111 inaddr.S_un.S_addr = pIpAddRow->dwAddr; 00112 _tprintf(_T(" %-22s"), inet_ntoa(inaddr)); 00113 00114 /* print MAC address */ 00115 _stprintf(cMacAddr, _T("%02x-%02x-%02x-%02x-%02x-%02x"), 00116 pIpAddRow->bPhysAddr[0], 00117 pIpAddRow->bPhysAddr[1], 00118 pIpAddRow->bPhysAddr[2], 00119 pIpAddRow->bPhysAddr[3], 00120 pIpAddRow->bPhysAddr[4], 00121 pIpAddRow->bPhysAddr[5]); 00122 _tprintf(_T("%-22s"), cMacAddr); 00123 00124 /* print cache type */ 00125 switch (pIpAddRow->dwType) 00126 { 00127 case MIB_IPNET_TYPE_DYNAMIC : _tprintf(_T("dynamic\n")); 00128 break; 00129 case MIB_IPNET_TYPE_STATIC : _tprintf(_T("static\n")); 00130 break; 00131 case MIB_IPNET_TYPE_INVALID : _tprintf(_T("invalid\n")); 00132 break; 00133 case MIB_IPNET_TYPE_OTHER : _tprintf(_T("other\n")); 00134 break; 00135 } 00136 return EXIT_SUCCESS; 00137 } 00138 00139 00140 /* 00141 * 00142 * Takes optional parameters of an internet address and interface address. 00143 * Retrieve all entries in the ARP cache. If an internet address is 00144 * specified, display the ARP entry relating to that address. If an 00145 * interface address is specified, display all entries relating to 00146 * that interface. 00147 * 00148 */ 00149 /* FIXME: allow user to specify an interface address, via pszIfAddr */ 00150 INT DisplayArpEntries(PTCHAR pszInetAddr, PTCHAR pszIfAddr) 00151 { 00152 INT iRet; 00153 UINT i, k; 00154 PMIB_IPNETTABLE pIpNetTable = NULL; 00155 PMIB_IPADDRTABLE pIpAddrTable = NULL; 00156 ULONG Size = 0; 00157 struct in_addr inaddr, inaddr2; 00158 PTCHAR pszIpAddr; 00159 TCHAR szIntIpAddr[20]; 00160 00161 /* retrieve the IP-to-physical address mapping table */ 00162 00163 /* get table size */ 00164 GetIpNetTable(pIpNetTable, &Size, 0); 00165 00166 /* allocate memory for ARP address table */ 00167 pIpNetTable = (PMIB_IPNETTABLE) HeapAlloc(GetProcessHeap(), 0, Size); 00168 if (pIpNetTable == NULL) 00169 goto cleanup; 00170 00171 ZeroMemory(pIpNetTable, sizeof(*pIpNetTable)); 00172 00173 if (GetIpNetTable(pIpNetTable, &Size, TRUE) != NO_ERROR) 00174 { 00175 _tprintf(_T("failed to allocate memory for GetIpNetTable\n")); 00176 DoFormatMessage(); 00177 goto cleanup; 00178 } 00179 00180 /* check there are entries in the table */ 00181 if (pIpNetTable->dwNumEntries == 0) 00182 { 00183 _tprintf(_T("No ARP entires found\n")); 00184 goto cleanup; 00185 } 00186 00187 00188 00189 /* Retrieve the interface-to-ip address mapping 00190 * table to get the IP address for adapter */ 00191 00192 /* get table size */ 00193 Size = 0; 00194 GetIpAddrTable(pIpAddrTable, &Size, 0); 00195 00196 pIpAddrTable = (MIB_IPADDRTABLE *) HeapAlloc(GetProcessHeap(), 0, Size); 00197 if (pIpAddrTable == NULL) 00198 goto cleanup; 00199 00200 ZeroMemory(pIpAddrTable, sizeof(*pIpAddrTable)); 00201 00202 if ((iRet = GetIpAddrTable(pIpAddrTable, &Size, TRUE)) != NO_ERROR) 00203 { 00204 _tprintf(_T("GetIpAddrTable failed: %d\n"), iRet); 00205 DoFormatMessage(); 00206 goto cleanup; 00207 } 00208 00209 00210 for (k=0; k < pIpAddrTable->dwNumEntries; k++) 00211 { 00212 if (pIpNetTable->table[0].dwIndex == pIpAddrTable->table[k].dwIndex) 00213 { 00214 //printf("debug print: pIpAddrTable->table[?].dwIndex = %lx\n", pIpNetTable->table[k].dwIndex); 00215 inaddr2.s_addr = pIpAddrTable->table[k].dwAddr; 00216 pszIpAddr = inet_ntoa(inaddr2); 00217 strcpy(szIntIpAddr, pszIpAddr); 00218 } 00219 } 00220 00221 00222 /* print header, including interface IP address and index number */ 00223 _tprintf(_T("\nInterface: %s --- 0x%lx \n"), szIntIpAddr, pIpNetTable->table[0].dwIndex); 00224 _tprintf(_T(" Internet Address Physical Address Type\n")); 00225 00226 /* go through all ARP entries */ 00227 for (i=0; i < pIpNetTable->dwNumEntries; i++) 00228 { 00229 00230 /* if the user has supplied their own internet addesss * 00231 * only print the arp entry which matches that */ 00232 if (pszInetAddr) 00233 { 00234 inaddr.S_un.S_addr = pIpNetTable->table[i].dwAddr; 00235 pszIpAddr = inet_ntoa(inaddr); 00236 00237 /* check if it matches, print it */ 00238 if (strcmp(pszIpAddr, pszInetAddr) == 0) 00239 PrintEntries(&pIpNetTable->table[i]); 00240 } 00241 else 00242 /* if an address is not supplied, print all entries */ 00243 PrintEntries(&pIpNetTable->table[i]); 00244 } 00245 00246 return EXIT_SUCCESS; 00247 00248 cleanup: 00249 if (pIpNetTable != NULL) 00250 HeapFree(GetProcessHeap(), 0, pIpNetTable); 00251 if (pIpAddrTable != NULL) 00252 HeapFree(GetProcessHeap(), 0, pIpAddrTable); 00253 return EXIT_FAILURE; 00254 } 00255 00256 00257 /* 00258 * 00259 * Takes an internet address, a MAC address and an optional interface 00260 * address as arguments and checks their validity. 00261 * Fill out an MIB_IPNETROW structure and insert the data into the 00262 * ARP cache as a static entry. 00263 * 00264 */ 00265 INT Addhost(PTCHAR pszInetAddr, PTCHAR pszEthAddr, PTCHAR pszIfAddr) 00266 { 00267 PMIB_IPNETROW pAddHost = NULL; 00268 PMIB_IPNETTABLE pIpNetTable = NULL; 00269 DWORD dwIpAddr = 0; 00270 ULONG Size = 0; 00271 INT i, val, c; 00272 00273 /* error checking */ 00274 00275 /* check IP address */ 00276 if (pszInetAddr != NULL) 00277 { 00278 if ((dwIpAddr = inet_addr(pszInetAddr)) == INADDR_NONE) 00279 { 00280 _tprintf(_T("ARP: bad IP address: %s\n"), pszInetAddr); 00281 return EXIT_FAILURE; 00282 } 00283 } 00284 else 00285 { 00286 Usage(); 00287 return EXIT_FAILURE; 00288 } 00289 00290 /* check MAC address */ 00291 if (strlen(pszEthAddr) != 17) 00292 { 00293 _tprintf(_T("ARP: bad argument: %s\n"), pszEthAddr); 00294 return EXIT_FAILURE; 00295 } 00296 for (i=0; i<17; i++) 00297 { 00298 if (pszEthAddr[i] == SEPERATOR) 00299 continue; 00300 00301 if (!isxdigit(pszEthAddr[i])) 00302 { 00303 _tprintf(_T("ARP: bad argument: %s\n"), pszEthAddr); 00304 return EXIT_FAILURE; 00305 } 00306 } 00307 00308 /* We need the IpNetTable to get the adapter index */ 00309 /* Return required buffer size */ 00310 GetIpNetTable(pIpNetTable, &Size, 0); 00311 00312 /* allocate memory for ARP address table */ 00313 pIpNetTable = (PMIB_IPNETTABLE) HeapAlloc(GetProcessHeap(), 0, Size); 00314 if (pIpNetTable == NULL) 00315 goto cleanup; 00316 00317 ZeroMemory(pIpNetTable, sizeof(*pIpNetTable)); 00318 00319 if (GetIpNetTable(pIpNetTable, &Size, TRUE) != NO_ERROR) 00320 { 00321 _tprintf(_T("failed to allocate memory for GetIpNetTable\n")); 00322 DoFormatMessage(); 00323 goto cleanup; 00324 } 00325 00326 00327 /* reserve memory on heap and zero */ 00328 pAddHost = (MIB_IPNETROW *) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_IPNETROW)); 00329 if (pAddHost == NULL) 00330 goto cleanup; 00331 00332 ZeroMemory(pAddHost, sizeof(MIB_IPNETROW)); 00333 00334 /* set dwIndex field to the index of a local IP address to 00335 * indicate the network on which the ARP entry applies */ 00336 if (pszIfAddr) 00337 { 00338 if (sscanf(pszIfAddr, "%lx", &pAddHost->dwIndex) == EOF) 00339 { 00340 goto cleanup; 00341 } 00342 } 00343 else 00344 { 00345 //printf("debug print: pIpNetTable->table[0].dwIndex = %lx\n", pIpNetTable->table[0].dwIndex); 00346 /* needs testing. I get the correct index on my machine, but need others 00347 * to test their card index. Any problems and we can use GetAdaptersInfo instead */ 00348 pAddHost->dwIndex = pIpNetTable->table[0].dwIndex; 00349 } 00350 00351 /* Set MAC address to 6 bytes (typical) */ 00352 pAddHost->dwPhysAddrLen = 6; 00353 00354 00355 /* Encode bPhysAddr into correct byte array */ 00356 for (i=0; i<6; i++) 00357 { 00358 val =0; 00359 c = toupper(pszEthAddr[i*3]); 00360 c = c - (isdigit(c) ? '0' : ('A' - 10)); 00361 val += c; 00362 val = (val << 4); 00363 c = toupper(pszEthAddr[i*3 + 1]); 00364 c = c - (isdigit(c) ? '0' : ('A' - 10)); 00365 val += c; 00366 pAddHost->bPhysAddr[i] = (BYTE)val; 00367 } 00368 00369 00370 /* copy converted IP address */ 00371 pAddHost->dwAddr = dwIpAddr; 00372 00373 00374 /* set type to static */ 00375 pAddHost->dwType = MIB_IPNET_TYPE_STATIC; 00376 00377 00378 /* Add the ARP entry */ 00379 if (SetIpNetEntry(pAddHost) != NO_ERROR) 00380 { 00381 DoFormatMessage(); 00382 goto cleanup; 00383 } 00384 00385 HeapFree(GetProcessHeap(), 0, pAddHost); 00386 00387 return EXIT_SUCCESS; 00388 00389 cleanup: 00390 if (pIpNetTable != NULL) 00391 HeapFree(GetProcessHeap(), 0, pIpNetTable); 00392 if (pAddHost != NULL) 00393 HeapFree(GetProcessHeap(), 0, pAddHost); 00394 return EXIT_FAILURE; 00395 } 00396 00397 00398 /* 00399 * 00400 * Takes an internet address and an optional interface address as 00401 * arguments and checks their validity. 00402 * Add the interface number and IP to an MIB_IPNETROW structure 00403 * and remove the entry from the ARP cache. 00404 * 00405 */ 00406 INT Deletehost(PTCHAR pszInetAddr, PTCHAR pszIfAddr) 00407 { 00408 PMIB_IPNETROW pDelHost = NULL; 00409 PMIB_IPNETTABLE pIpNetTable = NULL; 00410 ULONG Size = 0; 00411 DWORD dwIpAddr = 0; 00412 BOOL bFlushTable = FALSE; 00413 00414 /* error checking */ 00415 00416 /* check IP address */ 00417 if (pszInetAddr != NULL) 00418 { 00419 /* if wildcard is given, set flag to delete all hosts */ 00420 if (strncmp(pszInetAddr, "*", 1) == 0) 00421 bFlushTable = TRUE; 00422 else if ((dwIpAddr = inet_addr(pszInetAddr)) == INADDR_NONE) 00423 { 00424 _tprintf(_T("ARP: bad IP address: %s\n"), pszInetAddr); 00425 exit(EXIT_FAILURE); 00426 } 00427 } 00428 else 00429 { 00430 Usage(); 00431 exit(EXIT_FAILURE); 00432 } 00433 00434 /* We need the IpNetTable to get the adapter index */ 00435 /* Return required buffer size */ 00436 GetIpNetTable(NULL, &Size, 0); 00437 00438 /* allocate memory for ARP address table */ 00439 pIpNetTable = (PMIB_IPNETTABLE) HeapAlloc(GetProcessHeap(), 0, Size); 00440 if (pIpNetTable == NULL) 00441 goto cleanup; 00442 00443 ZeroMemory(pIpNetTable, sizeof(*pIpNetTable)); 00444 00445 if (GetIpNetTable(pIpNetTable, &Size, TRUE) != NO_ERROR) 00446 { 00447 _tprintf(_T("failed to allocate memory for GetIpNetTable\n")); 00448 DoFormatMessage(); 00449 goto cleanup; 00450 } 00451 00452 /* reserve memory on heap and zero */ 00453 pDelHost = (MIB_IPNETROW *) HeapAlloc(GetProcessHeap(), 0, sizeof(MIB_IPNETROW)); 00454 if (pDelHost == NULL) 00455 goto cleanup; 00456 00457 ZeroMemory(pDelHost, sizeof(MIB_IPNETROW)); 00458 00459 00460 /* set dwIndex field to the index of a local IP address to 00461 * indicate the network on which the ARP entry applies */ 00462 if (pszIfAddr) 00463 { 00464 if (sscanf(pszIfAddr, "%lx", &pDelHost->dwIndex) == EOF) 00465 { 00466 goto cleanup; 00467 } 00468 } 00469 else 00470 { 00471 /* needs testing. I get the correct index on my machine, but need others 00472 * to test their card index. Any problems and we can use GetAdaptersInfo instead */ 00473 pDelHost->dwIndex = pIpNetTable->table[0].dwIndex; 00474 } 00475 00476 if (bFlushTable == TRUE) 00477 { 00478 /* delete arp cache */ 00479 if (FlushIpNetTable(pDelHost->dwIndex) != NO_ERROR) 00480 { 00481 DoFormatMessage(); 00482 goto cleanup; 00483 } 00484 else 00485 { 00486 HeapFree(GetProcessHeap(), 0, pDelHost); 00487 return EXIT_SUCCESS; 00488 } 00489 } 00490 else 00491 /* copy converted IP address */ 00492 pDelHost->dwAddr = dwIpAddr; 00493 00494 /* Add the ARP entry */ 00495 if (DeleteIpNetEntry(pDelHost) != NO_ERROR) 00496 { 00497 DoFormatMessage(); 00498 goto cleanup; 00499 } 00500 00501 HeapFree(GetProcessHeap(), 0, pDelHost); 00502 00503 return EXIT_SUCCESS; 00504 00505 cleanup: 00506 if (pIpNetTable != NULL) 00507 HeapFree(GetProcessHeap(), 0, pIpNetTable); 00508 if (pDelHost != NULL) 00509 HeapFree(GetProcessHeap(), 0, pDelHost); 00510 return EXIT_FAILURE; 00511 } 00512 00513 00514 00515 /* 00516 * 00517 * print program usage to screen 00518 * 00519 */ 00520 VOID Usage(VOID) 00521 { 00522 _tprintf(_T("\nDisplays and modifies the IP-to-Physical address translation tables used by\n" 00523 "address resolution protocol (ARP).\n" 00524 "\n" 00525 "ARP -s inet_addr eth_addr [if_addr]\n" 00526 "ARP -d inet_addr [if_addr]\n" 00527 "ARP -a [inet_addr] [-N if_addr]\n" 00528 "\n" 00529 " -a Displays current ARP entries by interrogating the current\n" 00530 " protocol data. If inet_addr is specified, the IP and Physical\n" 00531 " addresses for only the specified computer are displayed. If\n" 00532 " more than one network interface uses ARP, entries for each ARP\n" 00533 " table are displayed.\n" 00534 " -g Same as -a.\n" 00535 " inet_addr Specifies an internet address.\n" 00536 " -N if_addr Displays the ARP entries for the network interface specified\n" 00537 " by if_addr.\n" 00538 " -d Deletes the host specified by inet_addr. inet_addr may be\n" 00539 " wildcarded with * to delete all hosts.\n" 00540 " -s Adds the host and associates the Internet address inet_addr\n" 00541 " with the Physical address eth_addr. The Physical address is\n" 00542 " given as 6 hexadecimal bytes separated by hyphens. The entry\n" 00543 " is permanent.\n" 00544 " eth_addr Specifies a physical address.\n" 00545 " if_addr If present, this specifies the Internet address of the\n" 00546 " interface whose address translation table should be modified.\n" 00547 " If not present, the first applicable interface will be used.\n" 00548 "Example:\n" 00549 " > arp -s 157.55.85.212 00-aa-00-62-c6-09 .... Adds a static entry.\n" 00550 " > arp -a .... Displays the arp table.\n\n")); 00551 } 00552 00553 00554 00555 /* 00556 * 00557 * Program entry. 00558 * Parse command line and call the required function 00559 * 00560 */ 00561 INT main(int argc, char* argv[]) 00562 { 00563 if ((argc < 2) || (argc > 5)) 00564 { 00565 Usage(); 00566 return EXIT_FAILURE; 00567 } 00568 00569 if (argv[1][0] == '-') 00570 { 00571 switch (argv[1][1]) 00572 { 00573 case 'a': /* fall through */ 00574 case 'g': 00575 if (argc == 2) 00576 DisplayArpEntries(NULL, NULL); 00577 else if (argc == 3) 00578 DisplayArpEntries(argv[2], NULL); 00579 else if ((argc == 4) && ((strcmp(argv[2], "-N")) == 0)) 00580 DisplayArpEntries(NULL, argv[3]); 00581 else if ((argc == 5) && ((strcmp(argv[3], "-N")) == 0)) 00582 DisplayArpEntries(argv[2], argv[4]); 00583 else 00584 Usage(); 00585 return EXIT_FAILURE; 00586 break; 00587 case 'd': if (argc == 3) 00588 Deletehost(argv[2], NULL); 00589 else if (argc == 4) 00590 Deletehost(argv[2], argv[3]); 00591 else 00592 Usage(); 00593 return EXIT_FAILURE; 00594 break; 00595 case 's': if (argc == 4) 00596 Addhost(argv[2], argv[3], NULL); 00597 else if (argc == 5) 00598 Addhost(argv[2], argv[3], argv[4]); 00599 else 00600 Usage(); 00601 return EXIT_FAILURE; 00602 break; 00603 default: 00604 Usage(); 00605 return EXIT_FAILURE; 00606 } 00607 } 00608 else 00609 Usage(); 00610 00611 return EXIT_SUCCESS; 00612 } Generated on Sun May 27 2012 04:17:12 for ReactOS by
1.7.6.1
|