ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

arp.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.