1
0
mirror of https://github.com/nmap/nmap.git synced 2026-01-16 19:39:03 +00:00
Files
nmap/libdnet-stripped/src/route-win32.c
2008-09-19 06:12:25 +00:00

162 lines
3.5 KiB
C

/*
* route-win32.c
*
* Copyright (c) 2002 Dug Song <dugsong@monkey.org>
*
* $Id: route-win32.c 589 2005-02-15 07:11:32Z dugsong $
*/
#ifdef _WIN32
#include "dnet_winconfig.h"
#else
#include "config.h"
#endif
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "dnet.h"
struct route_handle {
MIB_IPFORWARDTABLE *ipftable;
};
route_t *
route_open(void)
{
return (calloc(1, sizeof(route_t)));
}
int
route_add(route_t *route, const struct route_entry *entry)
{
MIB_IPFORWARDROW ipfrow;
struct addr net;
memset(&ipfrow, 0, sizeof(ipfrow));
if (GetBestInterface(entry->route_gw.addr_ip,
&ipfrow.dwForwardIfIndex) != NO_ERROR)
return (-1);
if (addr_net(&entry->route_dst, &net) < 0 ||
net.addr_type != ADDR_TYPE_IP)
return (-1);
ipfrow.dwForwardDest = net.addr_ip;
addr_btom(entry->route_dst.addr_bits,
&ipfrow.dwForwardMask, IP_ADDR_LEN);
ipfrow.dwForwardNextHop = entry->route_gw.addr_ip;
ipfrow.dwForwardType = 4; /* XXX - next hop != final dest */
ipfrow.dwForwardProto = 3; /* XXX - MIB_PROTO_NETMGMT */
if (CreateIpForwardEntry(&ipfrow) != NO_ERROR)
return (-1);
return (0);
}
int
route_delete(route_t *route, const struct route_entry *entry)
{
MIB_IPFORWARDROW ipfrow;
DWORD mask;
if (entry->route_dst.addr_type != ADDR_TYPE_IP ||
GetBestRoute(entry->route_dst.addr_ip,
IP_ADDR_ANY, &ipfrow) != NO_ERROR)
return (-1);
addr_btom(entry->route_dst.addr_bits, &mask, IP_ADDR_LEN);
if (ipfrow.dwForwardDest != entry->route_dst.addr_ip ||
ipfrow.dwForwardMask != mask) {
errno = ENXIO;
SetLastError(ERROR_NO_DATA);
return (-1);
}
if (DeleteIpForwardEntry(&ipfrow) != NO_ERROR)
return (-1);
return (0);
}
int
route_get(route_t *route, struct route_entry *entry)
{
MIB_IPFORWARDROW ipfrow;
DWORD mask;
if (entry->route_dst.addr_type != ADDR_TYPE_IP ||
GetBestRoute(entry->route_dst.addr_ip,
IP_ADDR_ANY, &ipfrow) != NO_ERROR)
return (-1);
if (ipfrow.dwForwardProto == 2 && /* XXX - MIB_IPPROTO_LOCAL */
(ipfrow.dwForwardNextHop|IP_CLASSA_NET) !=
(IP_ADDR_LOOPBACK|IP_CLASSA_NET) &&
!IP_LOCAL_GROUP(ipfrow.dwForwardNextHop)) {
errno = ENXIO;
SetLastError(ERROR_NO_DATA);
return (-1);
}
addr_btom(entry->route_dst.addr_bits, &mask, IP_ADDR_LEN);
entry->route_gw.addr_type = ADDR_TYPE_IP;
entry->route_gw.addr_bits = IP_ADDR_BITS;
entry->route_gw.addr_ip = ipfrow.dwForwardNextHop;
return (0);
}
int
route_loop(route_t *r, route_handler callback, void *arg)
{
struct route_entry entry;
ULONG len;
int i, ret;
for (len = sizeof(r->ipftable[0]); ; ) {
if (r->ipftable)
free(r->ipftable);
r->ipftable = malloc(len);
ret = GetIpForwardTable(r->ipftable, &len, FALSE);
if (ret == NO_ERROR)
break;
else if (ret != ERROR_INSUFFICIENT_BUFFER)
return (-1);
}
entry.route_dst.addr_type = ADDR_TYPE_IP;
entry.route_dst.addr_bits = IP_ADDR_BITS;
entry.route_gw.addr_type = ADDR_TYPE_IP;
entry.route_gw.addr_bits = IP_ADDR_BITS;
for (i = 0; i < (int)r->ipftable->dwNumEntries; i++) {
entry.route_dst.addr_ip = r->ipftable->table[i].dwForwardDest;
addr_mtob(&r->ipftable->table[i].dwForwardMask, IP_ADDR_LEN,
&entry.route_dst.addr_bits);
entry.route_gw.addr_ip =
r->ipftable->table[i].dwForwardNextHop;
if ((ret = (*callback)(&entry, arg)) != 0)
return (ret);
}
return (0);
}
route_t *
route_close(route_t *r)
{
if (r != NULL) {
if (r->ipftable != NULL)
free(r->ipftable);
free(r);
}
return (NULL);
}