Skip to content

Instantly share code, notes, and snippets.

@gvanem
Last active August 15, 2016 09:02
Show Gist options
  • Select an option

  • Save gvanem/2a0915e13f208fd150b8 to your computer and use it in GitHub Desktop.

Select an option

Save gvanem/2a0915e13f208fd150b8 to your computer and use it in GitHub Desktop.
Modified libdnet + Nmap route-win32.c file for those MinGW-distros which doesn't have <NetioApi.h>. Also uses some IpHlpAPI functions dynamically to better support Win-XP. The .diff at bottom.
/*
* 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"
#if defined(_MSC_VER) && 0 && (_WIN32_WINNT >= 0x0600) /* 0x0600 == _WIN32_WINNT_VISTA */
#include <netioapi.h>
#define HAVE_NETIOAPI_H
typedef DWORD (WINAPI *GETIPFORWARDTABLE2)(ADDRESS_FAMILY, PMIB_IPFORWARD_TABLE2 *);
#else
typedef DWORD (WINAPI *GETIPFORWARDTABLE2)(void *, void *);
#endif
typedef VOID (WINAPI *FREEMIBTABLE) (void *);
struct route_handle { /* the implementation details of 'route_t' in <dnet.h> */
HINSTANCE iphlpapi;
GETIPFORWARDTABLE2 p_GetIpForwardTable2;
FREEMIBTABLE p_FreeMibTable;
MIB_IPFORWARDTABLE *ipftable;
#ifdef HAVE_NETIOAPI_H
MIB_IPFORWARD_TABLE2 *ipftable2;
#endif
};
route_t *
route_open(void)
{
route_t *r;
r = calloc(1, sizeof(route_t));
if (r == NULL)
return NULL;
r->iphlpapi = GetModuleHandle("iphlpapi.dll");
/* GetIpForwardTable2 + FreeMibTable are only available on Vista and later, dynamic load. */
if (r->iphlpapi) {
r->p_GetIpForwardTable2 = (GETIPFORWARDTABLE2) GetProcAddress(r->iphlpapi, "GetIpForwardTable2");
r->p_FreeMibTable = (FREEMIBTABLE) GetProcAddress(r->iphlpapi, "FreeMibTable");
}
return r;
}
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;
intf_t *intf;
struct intf_entry intf_entry;
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;
entry->metric = ipfrow.dwForwardMetric1;
entry->intf_name[0] = '\0';
intf = intf_open();
if (intf_get_index(intf, &intf_entry,
AF_INET, ipfrow.dwForwardIfIndex) == 0) {
strlcpy(entry->intf_name, intf_entry.intf_name, sizeof(entry->intf_name));
}
intf_close(intf);
return (0);
}
static int
route_loop_getipforwardtable(route_t *r, route_handler callback, void *arg)
{
struct route_entry entry;
intf_t *intf;
ULONG len;
int i, ret;
for (len = sizeof(r->ipftable[0]); ; ) {
if (r->ipftable)
free(r->ipftable);
r->ipftable = malloc(len);
if (r->ipftable == NULL)
return (-1);
ret = GetIpForwardTable(r->ipftable, &len, FALSE);
if (ret == NO_ERROR)
break;
else if (ret != ERROR_INSUFFICIENT_BUFFER)
return (-1);
}
intf = intf_open();
ret = 0;
for (i = 0; i < (int)r->ipftable->dwNumEntries; i++) {
struct intf_entry intf_entry;
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;
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;
entry.metric = r->ipftable->table[i].dwForwardMetric1;
/* Look up the interface name. */
entry.intf_name[0] = '\0';
intf_entry.intf_len = sizeof(intf_entry);
if (intf_get_index(intf, &intf_entry,
AF_INET, r->ipftable->table[i].dwForwardIfIndex) == 0) {
strlcpy(entry.intf_name, intf_entry.intf_name, sizeof(entry.intf_name));
}
if ((ret = (*callback)(&entry, arg)) != 0)
break;
}
intf_close(intf);
return ret;
}
#ifdef HAVE_NETIOAPI_H
static int
route_loop_getipforwardtable2(GETIPFORWARDTABLE2 p_GetIpForwardTable2,
route_t *r, route_handler callback, void *arg)
{
struct route_entry entry;
intf_t *intf;
ULONG i;
int ret;
ret = (*p_GetIpForwardTable2)(AF_UNSPEC, &r->ipftable2);
if (ret != NO_ERROR)
return (-1);
intf = intf_open();
ret = 0;
for (i = 0; i < r->ipftable2->NumEntries; i++) {
struct intf_entry intf_entry;
MIB_IPFORWARD_ROW2 *row;
MIB_IPINTERFACE_ROW ifrow;
ULONG metric;
row = &r->ipftable2->Table[i];
addr_ston((struct sockaddr *) &row->DestinationPrefix.Prefix, &entry.route_dst);
entry.route_dst.addr_bits = row->DestinationPrefix.PrefixLength;
addr_ston((struct sockaddr *) &row->NextHop, &entry.route_gw);
/* Look up the interface name. */
entry.intf_name[0] = '\0';
intf_entry.intf_len = sizeof(intf_entry);
if (intf_get_index(intf, &intf_entry,
row->DestinationPrefix.Prefix.si_family,
row->InterfaceIndex) == 0) {
strlcpy(entry.intf_name, intf_entry.intf_name, sizeof(entry.intf_name));
}
ifrow.Family = row->DestinationPrefix.Prefix.si_family;
ifrow.InterfaceLuid = row->InterfaceLuid;
ifrow.InterfaceIndex = row->InterfaceIndex;
if (GetIpInterfaceEntry(&ifrow) != NO_ERROR) {
return (-1);
}
metric = ifrow.Metric + row->Metric;
if (metric < INT_MAX)
entry.metric = metric;
else
entry.metric = INT_MAX;
if ((ret = (*callback)(&entry, arg)) != 0)
break;
}
intf_close(intf);
return ret;
}
#endif /* HAVE_NETIOAPI_H */
int
route_loop(route_t *r, route_handler callback, void *arg)
{
#ifdef HAVE_NETIOAPI_H
if (r->p_GetIpForwardTable2)
return route_loop_getipforwardtable2(r->p_GetIpForwardTable2, r, callback, arg);
#endif
return route_loop_getipforwardtable(r, callback, arg);
}
route_t *
route_close(route_t *r)
{
if (r != NULL) {
if (r->iphlpapi != NULL)
FreeLibrary(r->iphlpapi);
if (r->ipftable != NULL)
free(r->ipftable);
#ifdef HAVE_NETIOAPI_H
if (r->ipftable2 != NULL && r->p_FreeMibTable)
(*r->p_FreeMibTable) (r->ipftable2);
#endif
free(r);
}
return (NULL);
}
--- a/libdnet-stripped/src/route-win32.c 2015-02-10 02:27:30 +0000
+++ b/libdnet-stripped/src/route-win32.c 2015-03-04 23:03:27 +0000
@@ -21,12 +21,25 @@
#include "dnet.h"
-typedef DWORD (WINAPI *GETIPFORWARDTABLE2)(ADDRESS_FAMILY, PMIB_IPFORWARD_TABLE2 *);
+#if defined(_MSC_VER) && 0 && (_WIN32_WINNT >= 0x0600) /* 0x0600 == _WIN32_WINNT_VISTA */
+ #include <netioapi.h>
+ #define HAVE_NETIOAPI_H
+
+ typedef DWORD (WINAPI *GETIPFORWARDTABLE2)(ADDRESS_FAMILY, PMIB_IPFORWARD_TABLE2 *);
+#else
+ typedef DWORD (WINAPI *GETIPFORWARDTABLE2)(void *, void *);
+#endif
-struct route_handle {
+typedef VOID (WINAPI *FREEMIBTABLE) (void *);
+
+struct route_handle { /* the implementation details of 'route_t' in <dnet.h> */
HINSTANCE iphlpapi;
+ GETIPFORWARDTABLE2 p_GetIpForwardTable2;
+ FREEMIBTABLE p_FreeMibTable;
MIB_IPFORWARDTABLE *ipftable;
+#ifdef HAVE_NETIOAPI_H
MIB_IPFORWARD_TABLE2 *ipftable2;
+#endif
};
route_t *
@@ -39,6 +52,11 @@
return NULL;
r->iphlpapi = GetModuleHandle("iphlpapi.dll");
+ /* GetIpForwardTable2 + FreeMibTable are only available on Vista and later, dynamic load. */
+ if (r->iphlpapi) {
+ r->p_GetIpForwardTable2 = (GETIPFORWARDTABLE2) GetProcAddress(r->iphlpapi, "GetIpForwardTable2");
+ r->p_FreeMibTable = (FREEMIBTABLE) GetProcAddress(r->iphlpapi, "FreeMibTable");
+ }
return r;
}
@@ -192,8 +210,9 @@
return ret;
}
+#ifdef HAVE_NETIOAPI_H
static int
-route_loop_getipforwardtable2(GETIPFORWARDTABLE2 GetIpForwardTable2,
+route_loop_getipforwardtable2(GETIPFORWARDTABLE2 p_GetIpForwardTable2,
route_t *r, route_handler callback, void *arg)
{
struct route_entry entry;
@@ -201,7 +220,7 @@
ULONG i;
int ret;
- ret = GetIpForwardTable2(AF_UNSPEC, &r->ipftable2);
+ ret = (*p_GetIpForwardTable2)(AF_UNSPEC, &r->ipftable2);
if (ret != NO_ERROR)
return (-1);
@@ -248,21 +267,16 @@
return ret;
}
+#endif /* HAVE_NETIOAPI_H */
int
route_loop(route_t *r, route_handler callback, void *arg)
{
- GETIPFORWARDTABLE2 GetIpForwardTable2;
-
- /* GetIpForwardTable2 is only available on Vista and later, dynamic load. */
- GetIpForwardTable2 = NULL;
- if (r->iphlpapi != NULL)
- GetIpForwardTable2 = (GETIPFORWARDTABLE2) GetProcAddress(r->iphlpapi, "GetIpForwardTable2");
-
- if (GetIpForwardTable2 == NULL)
+#ifdef HAVE_NETIOAPI_H
+ if (r->p_GetIpForwardTable2)
+ return route_loop_getipforwardtable2(r->p_GetIpForwardTable2, r, callback, arg);
+#endif
return route_loop_getipforwardtable(r, callback, arg);
- else
- return route_loop_getipforwardtable2(GetIpForwardTable2, r, callback, arg);
}
route_t *
@@ -273,8 +287,10 @@
FreeLibrary(r->iphlpapi);
if (r->ipftable != NULL)
free(r->ipftable);
- if (r->ipftable2 != NULL)
- FreeMibTable(r->ipftable2);
+#ifdef HAVE_NETIOAPI_H
+ if (r->ipftable2 != NULL && r->p_FreeMibTable)
+ (*r->p_FreeMibTable) (r->ipftable2);
+#endif
free(r);
}
return (NULL);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment