507 lines
15 KiB
C++
507 lines
15 KiB
C++
/*---------------------------------------------------------------------------
|
|
Copyright (c) 1998 - 2000 Microsoft Corporation
|
|
Module Name: IpRoute.exe
|
|
File : IpRoute.cpp
|
|
Description: This file demonstrates the use of IP Helper APIs to
|
|
manipulate routing table.
|
|
Author:
|
|
Frank Li April 18, 1998
|
|
|
|
Revision History:
|
|
Who When What
|
|
-------- -------- ----------------------------------
|
|
Frank Li 04-18-98 created
|
|
---------------------------------------------------------------------------*/
|
|
|
|
#include "IpRoute.h"
|
|
|
|
void Usage(char * pszProgramName)
|
|
{
|
|
printf("Manipulates network routing tables.\n\n");
|
|
|
|
printf("%s -p ...Prints route table.\n", pszProgramName);
|
|
printf("%s -a destination netmask gateway interface [metric]...Adds a route.\n", pszProgramName);
|
|
printf("%s -d destination ...Deletes routes to\n", pszProgramName);
|
|
printf(" destination.\n\n");
|
|
|
|
printf("destination Specifies the destination host.\n\n");
|
|
|
|
printf("netmask Specifies a subnet mask value to be associated\n");
|
|
printf(" with this route entry.\n\n");
|
|
|
|
printf("gateway Specifies gateway.\n\n");
|
|
|
|
printf("interface Specifies the interface ip.\n\n");
|
|
|
|
printf("metric The cost for this destination\n\n");
|
|
|
|
printf("Diagnostic Notes:\n\n");
|
|
printf("Invalid MASK generates an error, that is when (DEST & MASK) != DEST.\n");
|
|
printf("Example> IpRoute -a 157.0.0.0 155.0.0.0 157.55.80.1 157.55.80.9\n");
|
|
printf(" IpRoute: Invalid Mask 155.0.0.0\n\n");
|
|
|
|
printf("Examples:\n\n");
|
|
|
|
printf("> IpRoute -p\n");
|
|
printf("> IpRoute -a 157.0.0.0 255.0.0.0 157.55.80.1 157.55.80.9 1\n");
|
|
printf(" ^destination ^mask ^gateway ^existing interface ^metric\n");
|
|
printf("> IpRoute -p\n");
|
|
printf("> IpRoute -d 157.0.0.0\n");
|
|
printf("> IpRoute -p\n");
|
|
|
|
WSACleanup();
|
|
exit(1);
|
|
}
|
|
|
|
|
|
void _cdecl main(int argc, char **argv)
|
|
{
|
|
WORD wVersionRequested = MAKEWORD(1,1);
|
|
WSADATA wsaData;
|
|
int nRet;
|
|
|
|
nRet = WSAStartup(wVersionRequested, &wsaData);
|
|
if (wsaData.wVersion != wVersionRequested)
|
|
{
|
|
fprintf(stderr,"\n Wrong version\n");
|
|
return;
|
|
}
|
|
|
|
if ((argc < 2) || (argv[1][0] != '-'))
|
|
Usage("IpRoute");
|
|
if (strlen(argv[1]) > 2)
|
|
Usage("IpRoute");
|
|
|
|
switch(argv[1][1])
|
|
{
|
|
case 'p':
|
|
// Print routing table
|
|
DoGetIpForwardTable();
|
|
break;
|
|
case 'a':
|
|
//Adds an entry into routing table
|
|
if (argc == 6)
|
|
DoSetIpForwardEntry(argv[2], argv[3], argv[4], argv[5]); // dest mask gateway if
|
|
else if (argc == 7)
|
|
{
|
|
DWORD dwMetric;
|
|
if (sscanf_s(argv[6], "%u", &dwMetric ) == 1)
|
|
DoSetIpForwardEntry(argv[2], argv[3], argv[4], argv[5], dwMetric);
|
|
else
|
|
printf("IpRoute: Bad argument %s\n", argv[6]);
|
|
}
|
|
else
|
|
Usage("IpRoute");
|
|
break;
|
|
|
|
case 'd':
|
|
//Delete an entry from the routing table
|
|
if (argc == 3)
|
|
DoDeleteIpForwardEntry(argv[2]);
|
|
else
|
|
Usage("IpRoute");
|
|
break;
|
|
default:
|
|
// help
|
|
Usage("IpRoute");
|
|
break;
|
|
}
|
|
WSACleanup();
|
|
}
|
|
|
|
void DoGetIpForwardTable()
|
|
{
|
|
DWORD dwStatus;
|
|
PMIB_IPFORWARDTABLE pIpRouteTab = NULL; // Ip routing table
|
|
|
|
|
|
if ( (dwStatus = MyGetIpForwardTable(pIpRouteTab, TRUE)) == NO_ERROR)
|
|
{
|
|
PrintIpForwardTable(pIpRouteTab);
|
|
free(pIpRouteTab);
|
|
return;
|
|
}
|
|
else if ( dwStatus == ERROR_NO_DATA)
|
|
{
|
|
printf("No entries in route table.\n");
|
|
if (pIpRouteTab)
|
|
free (pIpRouteTab);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (pIpRouteTab)
|
|
free (pIpRouteTab);
|
|
printf("IpRoute returned 0x%x\n", dwStatus);
|
|
return;
|
|
}
|
|
}
|
|
|
|
void DoSetIpForwardEntry(char* pszDest, char* pszNetMask, char* pszGateway, char* pszInterface, DWORD dwMetric)
|
|
{
|
|
DWORD dwStatus;
|
|
|
|
MIB_IPFORWARDROW routeEntry; // Ip routing table row entry
|
|
PMIB_IPADDRTABLE pIpAddrTable = NULL; // Ip Addr Table
|
|
DWORD dwIfIndex; // Interface index number
|
|
DWORD dwIfMask; // Interface Subnet Mask
|
|
DWORD dwIfIpAddr; // Interface Ip Address
|
|
|
|
memset(&routeEntry, 0, sizeof(MIB_IPFORWARDROW));
|
|
|
|
|
|
// converting and checking input arguments...
|
|
if (pszDest == NULL || pszNetMask == NULL || pszGateway == NULL)
|
|
{
|
|
printf("IpRoute: Bad Argument\n");
|
|
return;
|
|
}
|
|
|
|
routeEntry.dwForwardDest = inet_addr(pszDest); // convert dotted ip addr. to ip addr.
|
|
if (routeEntry.dwForwardDest == INADDR_NONE)
|
|
{
|
|
printf("IpRoute: Bad Destination %s\n", pszDest);
|
|
return;
|
|
}
|
|
|
|
routeEntry.dwForwardMask = inet_addr(pszNetMask);
|
|
if ( (routeEntry.dwForwardMask == INADDR_NONE) &&
|
|
(strcmp("255.255.255.255", pszNetMask) != 0) )
|
|
{
|
|
printf("IpRoute: Bad Mask %s\n", pszNetMask);
|
|
return;
|
|
}
|
|
|
|
routeEntry.dwForwardNextHop = inet_addr(pszGateway);
|
|
if (routeEntry.dwForwardNextHop == INADDR_NONE)
|
|
{
|
|
printf("IpRoute: Bad Gateway %s\n", pszGateway);
|
|
return;
|
|
}
|
|
|
|
if ( (routeEntry.dwForwardDest & routeEntry.dwForwardMask) != routeEntry.dwForwardDest)
|
|
{
|
|
printf("IpRoute: Invalid Mask %s\n", pszNetMask);
|
|
return;
|
|
|
|
}
|
|
|
|
dwIfIpAddr = inet_addr(pszInterface);
|
|
if (dwIfIpAddr == INADDR_NONE)
|
|
{
|
|
printf("IpRoute: Bad Interface %s\n", pszInterface);
|
|
return;
|
|
}
|
|
|
|
|
|
// Check if we have the given interface
|
|
if ( (dwStatus = MyGetIpAddrTable(pIpAddrTable)) != NO_ERROR)
|
|
{
|
|
printf("GetIpAddrTable returned 0x%x\n", dwStatus);
|
|
if (pIpAddrTable)
|
|
free(pIpAddrTable);
|
|
return;
|
|
}
|
|
assert(pIpAddrTable);
|
|
if ( InterfaceIpToIdxAndMask(pIpAddrTable, pszInterface, dwIfIndex, dwIfMask) == FALSE)
|
|
{
|
|
printf("IpRoute: Bad Argument %s\n", pszInterface);
|
|
return;
|
|
}
|
|
free(pIpAddrTable);
|
|
|
|
|
|
if ( (routeEntry.dwForwardNextHop & dwIfMask) != (dwIfIpAddr & dwIfMask) )
|
|
{
|
|
printf("IpRoute: Gateway %s and Interface %s are not in the same subnet.\n", pszGateway, pszInterface);
|
|
return;
|
|
}
|
|
|
|
routeEntry.dwForwardIfIndex = dwIfIndex;
|
|
|
|
routeEntry.dwForwardMetric1 = dwMetric;
|
|
|
|
// some default values
|
|
routeEntry.dwForwardProto = MIB_IPPROTO_NETMGMT;
|
|
routeEntry.dwForwardMetric2 = (DWORD)-1;
|
|
routeEntry.dwForwardMetric3 = (DWORD)-1;
|
|
routeEntry.dwForwardMetric4 = (DWORD)-1;
|
|
|
|
dwStatus = SetIpForwardEntry(&routeEntry);
|
|
if (dwStatus != NO_ERROR)
|
|
{
|
|
printf("IpRoute: couldn't add (%s), dwStatus = %lu.\n",
|
|
pszDest, dwStatus);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void DoDeleteIpForwardEntry(char* pszDest)
|
|
{
|
|
DWORD dwStatus, dwDelStatus, i;
|
|
PMIB_IPFORWARDTABLE pIpRouteTab = NULL; // Ip routing table
|
|
MIB_IPFORWARDROW routeEntry; // Ip routing table row entry
|
|
DWORD dwForwardDest = 0;
|
|
bool fDeleted = FALSE;
|
|
|
|
|
|
memset(&routeEntry, 0, sizeof(MIB_IPFORWARDROW));
|
|
dwForwardDest = inet_addr(pszDest); // convert dotted ip addr. to ip addr.
|
|
if (dwForwardDest == INADDR_NONE)
|
|
{
|
|
printf("IpRoute: Bad Destination %s\n", pszDest);
|
|
return;
|
|
}
|
|
|
|
|
|
if ( (dwStatus = MyGetIpForwardTable(pIpRouteTab, TRUE)) == NO_ERROR)
|
|
{
|
|
for (i = 0; i < pIpRouteTab->dwNumEntries; i++)
|
|
{
|
|
if (dwForwardDest == pIpRouteTab->table[i].dwForwardDest)
|
|
{
|
|
memcpy(&routeEntry, &(pIpRouteTab->table[i]), sizeof(MIB_IPFORWARDROW));
|
|
dwDelStatus = DeleteIpForwardEntry(&routeEntry);
|
|
if (dwDelStatus != NO_ERROR)
|
|
{
|
|
printf("IpRoute: couldn't delete (%s), dwStatus = %lu.\n",
|
|
pszDest, dwDelStatus);
|
|
return;
|
|
}
|
|
else
|
|
fDeleted = TRUE;
|
|
}
|
|
}
|
|
free(pIpRouteTab);
|
|
if (! fDeleted)
|
|
printf("IpRoute: The route specified was not found.\n");
|
|
return;
|
|
}
|
|
else if ( dwStatus == ERROR_NO_DATA)
|
|
{
|
|
printf("IpRoute: No entries in route table.\n");
|
|
if (pIpRouteTab)
|
|
free (pIpRouteTab);
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if (pIpRouteTab)
|
|
free (pIpRouteTab);
|
|
printf("IpRoute returned 0x%x\n", dwStatus);
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// If returned status is NO_ERROR, then pIpRouteTab points to a routing
|
|
// table.
|
|
//----------------------------------------------------------------------------
|
|
DWORD MyGetIpForwardTable(PMIB_IPFORWARDTABLE& pIpRouteTab, BOOL fOrder)
|
|
{
|
|
DWORD status = NO_ERROR;
|
|
DWORD statusRetry = NO_ERROR;
|
|
DWORD dwActualSize = 0;
|
|
|
|
// query for buffer size needed
|
|
status = GetIpForwardTable(pIpRouteTab, &dwActualSize, fOrder);
|
|
|
|
if (status == NO_ERROR)
|
|
{
|
|
printf("No error\n");
|
|
return status;
|
|
}
|
|
else if (status == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
// need more space
|
|
|
|
pIpRouteTab = (PMIB_IPFORWARDTABLE) malloc(dwActualSize);
|
|
assert(pIpRouteTab);
|
|
|
|
statusRetry = GetIpForwardTable(pIpRouteTab, &dwActualSize, fOrder);
|
|
return statusRetry;
|
|
}
|
|
else
|
|
{
|
|
return status;
|
|
}
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Print out ip routing table in the following format:
|
|
//Active Routes:
|
|
//
|
|
// Network Address Netmask Gateway Address Interface Metric
|
|
// 0.0.0.0 0.0.0.0 157.54.176.1 157.54.177.149 1
|
|
// 127.0.0.0 255.0.0.0 127.0.0.1 127.0.0.1 1
|
|
// 157.54.176.0 255.255.252.0 157.54.177.149 157.54.177.149 1
|
|
// 157.54.177.149 255.255.255.255 127.0.0.1 127.0.0.1 1
|
|
// 157.54.255.255 255.255.255.255 157.54.177.149 157.54.177.149 1
|
|
// 224.0.0.0 224.0.0.0 157.54.177.149 157.54.177.149 1
|
|
// 255.255.255.255 255.255.255.255 157.54.177.149 157.54.177.149 1
|
|
//----------------------------------------------------------------------------
|
|
void PrintIpForwardTable(PMIB_IPFORWARDTABLE pIpRouteTable)
|
|
{
|
|
DWORD i, dwStatus, dwCurrIndex;
|
|
struct in_addr inadDest;
|
|
struct in_addr inadMask;
|
|
struct in_addr inadGateway;
|
|
char szIpAddr[128]; // ip address of an interface index
|
|
PMIB_IPADDRTABLE pIpAddrTable = NULL;
|
|
|
|
char szDestIp[128];
|
|
char szMaskIp[128];
|
|
char szGatewayIp[128];
|
|
|
|
if (pIpRouteTable == NULL)
|
|
{
|
|
printf( "pIpRouteTable == NULL in line %d\n", __LINE__);
|
|
return;
|
|
}
|
|
// get IP Address Table for mapping interface index number to ip address
|
|
if ( (dwStatus = MyGetIpAddrTable(pIpAddrTable)) != NO_ERROR)
|
|
{
|
|
printf("GetIpAddrTable returned 0x%x\n", dwStatus);
|
|
if (pIpAddrTable)
|
|
free(pIpAddrTable);
|
|
return;
|
|
}
|
|
assert(pIpAddrTable);
|
|
|
|
|
|
printf("Active Routes:\n\n");
|
|
|
|
printf(" Network Address Netmask Gateway Address Interface Metric\n");
|
|
for (i = 0; i < pIpRouteTable->dwNumEntries; i++)
|
|
{
|
|
dwCurrIndex = pIpRouteTable->table[i].dwForwardIfIndex;
|
|
if (InterfaceIdxToInterfaceIp(pIpAddrTable, dwCurrIndex, szIpAddr) == FALSE)
|
|
{
|
|
printf("Error: Could not convert Interface number 0x%X to IP address.\n",dwCurrIndex);
|
|
if (pIpAddrTable)
|
|
free(pIpAddrTable);
|
|
return;
|
|
}
|
|
|
|
inadDest.s_addr = pIpRouteTable->table[i].dwForwardDest;
|
|
inadMask.s_addr = pIpRouteTable->table[i].dwForwardMask;
|
|
inadGateway.s_addr = pIpRouteTable->table[i].dwForwardNextHop;
|
|
|
|
strcpy_s(szDestIp, sizeof(szDestIp), inet_ntoa(inadDest));
|
|
strcpy_s(szMaskIp, sizeof(szDestIp), inet_ntoa(inadMask));
|
|
strcpy_s(szGatewayIp, sizeof(szDestIp), inet_ntoa(inadGateway));
|
|
printf(" %15s %16s %16s %16s %7d\n",
|
|
szDestIp,
|
|
szMaskIp,
|
|
szGatewayIp,
|
|
szIpAddr,
|
|
pIpRouteTable->table[i].dwForwardMetric1);
|
|
|
|
}
|
|
|
|
if (pIpAddrTable)
|
|
free(pIpAddrTable);
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Inputs: pIpAddrTable is the IP address table
|
|
// dwIndex is the Interface Number
|
|
// Output: If it returns TRUE, str contains the ip address of the interface
|
|
//----------------------------------------------------------------------------
|
|
bool InterfaceIdxToInterfaceIp(PMIB_IPADDRTABLE pIpAddrTable, DWORD dwIndex, char str[])
|
|
{
|
|
struct in_addr inadTmp;
|
|
char* szIpAddr2;
|
|
|
|
if (pIpAddrTable == NULL || str == NULL)
|
|
return FALSE;
|
|
str[0] = '\0';
|
|
for (DWORD dwIdx = 0; dwIdx < pIpAddrTable->dwNumEntries; dwIdx++)
|
|
{
|
|
if (dwIndex == pIpAddrTable->table[dwIdx].dwIndex)
|
|
{
|
|
inadTmp.s_addr = pIpAddrTable->table[dwIdx].dwAddr;
|
|
szIpAddr2 = inet_ntoa(inadTmp);
|
|
if (szIpAddr2)
|
|
{
|
|
strcpy_s(str, 128, szIpAddr2);
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Inputs: pIpAddrTable is the IP address table
|
|
// str is the Interface Ip address in dotted decimal format
|
|
// Output: If it returns TRUE, dwIndex contains the interface index number
|
|
// and dwMask contains the corresponding subnet mask.
|
|
//----------------------------------------------------------------------------
|
|
bool InterfaceIpToIdxAndMask(PMIB_IPADDRTABLE pIpAddrTable, char str[], DWORD& dwIndex, DWORD& dwMask)
|
|
{
|
|
DWORD dwIfIpAddr; // Interface Ip Address
|
|
|
|
if (pIpAddrTable == NULL)
|
|
return FALSE;
|
|
|
|
dwIfIpAddr = inet_addr(str);
|
|
if (dwIfIpAddr == INADDR_NONE)
|
|
return FALSE;
|
|
|
|
for (DWORD dwIdx = 0; dwIdx < pIpAddrTable->dwNumEntries; dwIdx++)
|
|
{
|
|
if (dwIfIpAddr == pIpAddrTable->table[dwIdx].dwAddr)
|
|
{
|
|
dwIndex = pIpAddrTable->table[dwIdx].dwIndex;
|
|
dwMask = pIpAddrTable->table[dwIdx].dwMask;
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// If returned status is NO_ERROR, then pIpAddrTable points to a Ip Address
|
|
// table.
|
|
//----------------------------------------------------------------------------
|
|
DWORD MyGetIpAddrTable(PMIB_IPADDRTABLE& pIpAddrTable, BOOL fOrder)
|
|
{
|
|
DWORD status = NO_ERROR;
|
|
DWORD statusRetry = NO_ERROR;
|
|
DWORD dwActualSize = 0;
|
|
|
|
// query for buffer size needed
|
|
status = GetIpAddrTable(pIpAddrTable, &dwActualSize, fOrder);
|
|
|
|
if (status == NO_ERROR)
|
|
{
|
|
printf("No error\n");
|
|
return status;
|
|
}
|
|
else if (status == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
// need more space
|
|
|
|
pIpAddrTable = (PMIB_IPADDRTABLE) malloc(dwActualSize);
|
|
assert(pIpAddrTable);
|
|
|
|
statusRetry = GetIpAddrTable(pIpAddrTable, &dwActualSize, fOrder);
|
|
return statusRetry;
|
|
}
|
|
else
|
|
{
|
|
return status;
|
|
}
|
|
}
|
|
|