00001
00002
00003
00004
00005
00006
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;
00051 ipfrow.dwForwardProto = 3;
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 &&
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 }