Main Page | Modules | Class List | Directories | File List | Class Members | File Members | Related Pages

route-win32.c

Go to the documentation of this file.
00001 /*
00002  * route-win32.c
00003  *
00004  * Copyright (c) 2002 Dug Song <dugsong@monkey.org>
00005  *
00006  * $Id: route-win32.c,v 1.12 2005/02/15 07:11:32 dugsong Exp $
00007  */
00008 
00009 #include "config.h"
00010 
00011 #include <ws2tcpip.h>
00012 #include <iphlpapi.h>
00013 
00014 #include <errno.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017 
00018 #include "dnet.h"
00019 
00020 struct route_handle {
00021         MIB_IPFORWARDTABLE *ipftable;
00022 };
00023 
00024 route_t *
00025 route_open(void)
00026 {
00027         return (calloc(1, sizeof(route_t)));
00028 }
00029 
00030 int
00031 route_add(route_t *route, const struct route_entry *entry)
00032 {
00033         MIB_IPFORWARDROW ipfrow;
00034         struct addr net;
00035 
00036         memset(&ipfrow, 0, sizeof(ipfrow));
00037 
00038         if (GetBestInterface(entry->route_gw.addr_ip,
00039             &ipfrow.dwForwardIfIndex) != NO_ERROR)
00040                 return (-1);
00041 
00042         if (addr_net(&entry->route_dst, &net) < 0 ||
00043             net.addr_type != ADDR_TYPE_IP)
00044                 return (-1);
00045         
00046         ipfrow.dwForwardDest = net.addr_ip;
00047         addr_btom(entry->route_dst.addr_bits,
00048             &ipfrow.dwForwardMask, IP_ADDR_LEN);
00049         ipfrow.dwForwardNextHop = entry->route_gw.addr_ip;
00050         ipfrow.dwForwardType = 4;       /* XXX - next hop != final dest */
00051         ipfrow.dwForwardProto = 3;      /* XXX - MIB_PROTO_NETMGMT */
00052         
00053         if (CreateIpForwardEntry(&ipfrow) != NO_ERROR)
00054                 return (-1);
00055         
00056         return (0);
00057 }
00058 
00059 int
00060 route_delete(route_t *route, const struct route_entry *entry)
00061 {
00062         MIB_IPFORWARDROW ipfrow;
00063         DWORD mask;
00064         
00065         if (entry->route_dst.addr_type != ADDR_TYPE_IP ||
00066             GetBestRoute(entry->route_dst.addr_ip,
00067             IP_ADDR_ANY, &ipfrow) != NO_ERROR)
00068                 return (-1);
00069 
00070         addr_btom(entry->route_dst.addr_bits, &mask, IP_ADDR_LEN);
00071         
00072         if (ipfrow.dwForwardDest != entry->route_dst.addr_ip ||
00073             ipfrow.dwForwardMask != mask) {
00074                 errno = ENXIO;
00075                 SetLastError(ERROR_NO_DATA);
00076                 return (-1);
00077         }
00078         if (DeleteIpForwardEntry(&ipfrow) != NO_ERROR)
00079                 return (-1);
00080         
00081         return (0);
00082 }
00083 
00084 int
00085 route_get(route_t *route, struct route_entry *entry)
00086 {
00087         MIB_IPFORWARDROW ipfrow;
00088         DWORD mask;
00089 
00090         if (entry->route_dst.addr_type != ADDR_TYPE_IP ||
00091             GetBestRoute(entry->route_dst.addr_ip,
00092             IP_ADDR_ANY, &ipfrow) != NO_ERROR)
00093                 return (-1);
00094 
00095         if (ipfrow.dwForwardProto == 2 &&       /* XXX - MIB_IPPROTO_LOCAL */
00096             (ipfrow.dwForwardNextHop|IP_CLASSA_NET) !=
00097             (IP_ADDR_LOOPBACK|IP_CLASSA_NET) &&
00098             !IP_LOCAL_GROUP(ipfrow.dwForwardNextHop)) { 
00099                 errno = ENXIO;
00100                 SetLastError(ERROR_NO_DATA);
00101                 return (-1);
00102         }
00103         addr_btom(entry->route_dst.addr_bits, &mask, IP_ADDR_LEN);
00104         
00105         entry->route_gw.addr_type = ADDR_TYPE_IP;
00106         entry->route_gw.addr_bits = IP_ADDR_BITS;
00107         entry->route_gw.addr_ip = ipfrow.dwForwardNextHop;
00108         
00109         return (0);
00110 }
00111 
00112 int
00113 route_loop(route_t *r, route_handler callback, void *arg)
00114 {
00115         struct route_entry entry;
00116         ULONG len;
00117         int i, ret;
00118         
00119         for (len = sizeof(r->ipftable[0]); ; ) {
00120                 if (r->ipftable)
00121                         free(r->ipftable);
00122                 r->ipftable = malloc(len);
00123                 ret = GetIpForwardTable(r->ipftable, &len, FALSE);
00124                 if (ret == NO_ERROR)
00125                         break;
00126                 else if (ret != ERROR_INSUFFICIENT_BUFFER)
00127                         return (-1);
00128         }
00129         entry.route_dst.addr_type = ADDR_TYPE_IP;
00130         entry.route_dst.addr_bits = IP_ADDR_BITS;
00131         
00132         entry.route_gw.addr_type = ADDR_TYPE_IP;
00133         entry.route_gw.addr_bits = IP_ADDR_BITS;
00134         
00135         for (i = 0; i < (int)r->ipftable->dwNumEntries; i++) {
00136                 entry.route_dst.addr_ip = r->ipftable->table[i].dwForwardDest;
00137                 addr_mtob(&r->ipftable->table[i].dwForwardMask, IP_ADDR_LEN,
00138                     &entry.route_dst.addr_bits);
00139                 entry.route_gw.addr_ip =
00140                     r->ipftable->table[i].dwForwardNextHop;
00141                 
00142                 if ((ret = (*callback)(&entry, arg)) != 0)
00143                         return (ret);
00144         }
00145         return (0);
00146 }
00147 
00148 route_t *
00149 route_close(route_t *r)
00150 {
00151         if (r != NULL) {
00152                 if (r->ipftable != NULL)
00153                         free(r->ipftable);
00154                 free(r);
00155         }
00156         return (NULL);
00157 }

Generated on Sun May 14 14:51:12 2006 by  doxygen 1.4.2