diff options
Diffstat (limited to 'libnetutils')
-rw-r--r-- | libnetutils/dhcp_utils.c | 132 | ||||
-rw-r--r-- | libnetutils/dhcpclient.c | 15 | ||||
-rw-r--r-- | libnetutils/ifc_utils.c | 251 |
3 files changed, 217 insertions, 181 deletions
diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c index 064eb0c..8496725 100644 --- a/libnetutils/dhcp_utils.c +++ b/libnetutils/dhcp_utils.c @@ -18,6 +18,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <netinet/in.h> @@ -28,9 +29,9 @@ static const char DAEMON_NAME[] = "dhcpcd"; static const char DAEMON_PROP_NAME[] = "init.svc.dhcpcd"; static const char HOSTNAME_PROP_NAME[] = "net.hostname"; static const char DHCP_PROP_NAME_PREFIX[] = "dhcp"; -static const char DAEMON_NAME_RENEW[] = "iprenew"; -static const int NAP_TIME = 1; /* wait for 1 second at a time */ +static const int NAP_TIME = 200; /* wait for 200ms at a time */ /* when polling for property values */ +static const char DAEMON_NAME_RENEW[] = "iprenew"; static char errmsg[100]; /* @@ -42,14 +43,14 @@ static char errmsg[100]; static int wait_for_property(const char *name, const char *desired_value, int maxwait) { char value[PROPERTY_VALUE_MAX] = {'\0'}; - int maxnaps = maxwait / NAP_TIME; + int maxnaps = (maxwait * 1000) / NAP_TIME; if (maxnaps < 1) { maxnaps = 1; } while (maxnaps-- > 0) { - usleep(1000000); + usleep(NAP_TIME * 1000); if (property_get(name, value, NULL)) { if (desired_value == NULL || strcmp(value, desired_value) == 0) { @@ -60,60 +61,66 @@ static int wait_for_property(const char *name, const char *desired_value, int ma return -1; /* failure */ } -static void fill_ip_info(const char *interface, - in_addr_t *ipaddr, - in_addr_t *gateway, - in_addr_t *mask, - in_addr_t *dns1, - in_addr_t *dns2, - in_addr_t *server, +static int fill_ip_info(const char *interface, + char *ipaddr, + char *gateway, + uint32_t *prefixLength, + char *dns1, + char *dns2, + char *server, uint32_t *lease) { char prop_name[PROPERTY_KEY_MAX]; char prop_value[PROPERTY_VALUE_MAX]; - struct in_addr addr; - in_addr_t iaddr; snprintf(prop_name, sizeof(prop_name), "%s.%s.ipaddress", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *ipaddr = addr.s_addr; - } else { - *ipaddr = 0; - } + property_get(prop_name, ipaddr, NULL); + snprintf(prop_name, sizeof(prop_name), "%s.%s.gateway", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *gateway = addr.s_addr; - } else { - *gateway = 0; + property_get(prop_name, gateway, NULL); + + snprintf(prop_name, sizeof(prop_name), "%s.%s.server", DHCP_PROP_NAME_PREFIX, interface); + property_get(prop_name, server, NULL); + + //TODO: Handle IPv6 when we change system property usage + if (strcmp(gateway, "0.0.0.0") == 0) { + //DHCP server is our best bet as gateway + strncpy(gateway, server, PROPERTY_VALUE_MAX); } + snprintf(prop_name, sizeof(prop_name), "%s.%s.mask", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *mask = addr.s_addr; - } else { - *mask = 0; + if (property_get(prop_name, prop_value, NULL)) { + int p; + // this conversion is v4 only, but this dhcp client is v4 only anyway + in_addr_t mask = ntohl(inet_addr(prop_value)); + // Check netmask is a valid IP address. ntohl gives NONE response (all 1's) for + // non 255.255.255.255 inputs. if we get that value check if it is legit.. + if (mask == INADDR_NONE && strcmp(prop_value, "255.255.255.255") != 0) { + snprintf(errmsg, sizeof(errmsg), "DHCP gave invalid net mask %s", prop_value); + return -1; + } + for (p = 0; p < 32; p++) { + if (mask == 0) break; + // check for non-contiguous netmask, e.g., 255.254.255.0 + if ((mask & 0x80000000) == 0) { + snprintf(errmsg, sizeof(errmsg), "DHCP gave invalid net mask %s", prop_value); + return -1; + } + mask = mask << 1; + } + *prefixLength = p; } snprintf(prop_name, sizeof(prop_name), "%s.%s.dns1", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *dns1 = addr.s_addr; - } else { - *dns1 = 0; - } + property_get(prop_name, dns1, NULL); + snprintf(prop_name, sizeof(prop_name), "%s.%s.dns2", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *dns2 = addr.s_addr; - } else { - *dns2 = 0; - } - snprintf(prop_name, sizeof(prop_name), "%s.%s.server", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *server = addr.s_addr; - } else { - *server = 0; - } + property_get(prop_name, dns2, NULL); + snprintf(prop_name, sizeof(prop_name), "%s.%s.leasetime", DHCP_PROP_NAME_PREFIX, interface); if (property_get(prop_name, prop_value, NULL)) { *lease = atol(prop_value); } + return 0; } static const char *ipaddr_to_string(in_addr_t addr) @@ -129,12 +136,12 @@ static const char *ipaddr_to_string(in_addr_t addr) * configuring the interface. */ int dhcp_do_request(const char *interface, - in_addr_t *ipaddr, - in_addr_t *gateway, - in_addr_t *mask, - in_addr_t *dns1, - in_addr_t *dns2, - in_addr_t *server, + char *ipaddr, + char *gateway, + uint32_t *prefixLength, + char *dns1, + char *dns2, + char *server, uint32_t *lease) { char result_prop_name[PROPERTY_KEY_MAX]; @@ -181,8 +188,13 @@ int dhcp_do_request(const char *interface, } if (strcmp(prop_value, "ok") == 0) { char dns_prop_name[PROPERTY_KEY_MAX]; - fill_ip_info(interface, ipaddr, gateway, mask, dns1, dns2, server, lease); - /* copy the dhcp.XXX.dns properties to net.XXX.dns */ + if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns1, dns2, server, lease) + == -1) { + return -1; + } + + /* copy dns data to system properties - TODO - remove this after we have async + * notification of renewal's */ snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", interface); property_set(dns_prop_name, *dns1 ? ipaddr_to_string(*dns1) : ""); snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", interface); @@ -253,16 +265,15 @@ char *dhcp_get_errmsg() { } /** - * Run WiMAX dhcp renew service. - * "wimax_renew" service shoud be included in init.rc. + * DHCP renewal request */ int dhcp_do_request_renew(const char *interface, - in_addr_t *ipaddr, - in_addr_t *gateway, - in_addr_t *mask, - in_addr_t *dns1, - in_addr_t *dns2, - in_addr_t *server, + char *ipaddr, + char *gateway, + uint32_t *prefixLength, + char *dns1, + char *dns2, + char *server, uint32_t *lease) { char result_prop_name[PROPERTY_KEY_MAX]; @@ -294,7 +305,10 @@ int dhcp_do_request_renew(const char *interface, return -1; } if (strcmp(prop_value, "ok") == 0) { - fill_ip_info(interface, ipaddr, gateway, mask, dns1, dns2, server, lease); + if(fill_ip_info(interface, ipaddr, gateway, prefixLength, dns1, dns2, server, lease) + == -1) { + return -1; + } return 0; } else { snprintf(errmsg, sizeof(errmsg), "DHCP Renew result was %s", prop_value); diff --git a/libnetutils/dhcpclient.c b/libnetutils/dhcpclient.c index ff00432..5039e26 100644 --- a/libnetutils/dhcpclient.c +++ b/libnetutils/dhcpclient.c @@ -93,6 +93,8 @@ const char *ipaddr(in_addr_t addr) return inet_ntoa(in_addr); } +extern int ipv4NetmaskToPrefixLength(in_addr_t mask); + typedef struct dhcp_info dhcp_info; struct dhcp_info { @@ -100,7 +102,7 @@ struct dhcp_info { uint32_t ipaddr; uint32_t gateway; - uint32_t netmask; + uint32_t prefixLength; uint32_t dns1; uint32_t dns2; @@ -111,13 +113,13 @@ struct dhcp_info { dhcp_info last_good_info; -void get_dhcp_info(uint32_t *ipaddr, uint32_t *gateway, uint32_t *mask, +void get_dhcp_info(uint32_t *ipaddr, uint32_t *gateway, uint32_t *prefixLength, uint32_t *dns1, uint32_t *dns2, uint32_t *server, uint32_t *lease) { *ipaddr = last_good_info.ipaddr; *gateway = last_good_info.gateway; - *mask = last_good_info.netmask; + *prefixLength = last_good_info.prefixLength; *dns1 = last_good_info.dns1; *dns2 = last_good_info.dns2; *server = last_good_info.serveraddr; @@ -127,7 +129,7 @@ void get_dhcp_info(uint32_t *ipaddr, uint32_t *gateway, uint32_t *mask, static int dhcp_configure(const char *ifname, dhcp_info *info) { last_good_info = *info; - return ifc_configure(ifname, info->ipaddr, info->netmask, info->gateway, + return ifc_configure(ifname, info->ipaddr, info->prefixLength, info->gateway, info->dns1, info->dns2); } @@ -153,8 +155,7 @@ void dump_dhcp_info(dhcp_info *info) dhcp_type_to_name(info->type), info->type); strcpy(addr, ipaddr(info->ipaddr)); strcpy(gway, ipaddr(info->gateway)); - strcpy(mask, ipaddr(info->netmask)); - LOGD("ip %s gw %s mask %s", addr, gway, mask); + LOGD("ip %s gw %s prefixLength %d", addr, gway, info->prefixLength); if (info->dns1) LOGD("dns1: %s", ipaddr(info->dns1)); if (info->dns2) LOGD("dns2: %s", ipaddr(info->dns2)); LOGD("server %s, lease %d seconds", @@ -196,7 +197,7 @@ int decode_dhcp_msg(dhcp_msg *msg, int len, dhcp_info *info) } switch(opt) { case OPT_SUBNET_MASK: - if (optlen >= 4) memcpy(&info->netmask, x, 4); + if (optlen >= 4) info->prefixLength = ipv4NetmaskToPrefixLength((int)x); break; case OPT_GATEWAY: if (optlen >= 4) memcpy(&info->gateway, x, 4); diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c index 0ca5fe6..c9d6ed2 100644 --- a/libnetutils/ifc_utils.c +++ b/libnetutils/ifc_utils.c @@ -25,6 +25,7 @@ #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> +#include <net/if.h> #include <linux/if.h> #include <linux/if_ether.h> @@ -50,6 +51,33 @@ static int ifc_ctl_sock = -1; static int ifc_ctl_sock6 = -1; void printerr(char *fmt, ...); +in_addr_t prefixLengthToIpv4Netmask(int prefix_length) +{ + in_addr_t mask = 0; + + // C99 (6.5.7): shifts of 32 bits have undefined results + if (prefix_length <= 0 || prefix_length > 32) { + return 0; + } + + mask = ~mask << (32 - prefix_length); + mask = htonl(mask); + + return mask; +} + +int ipv4NetmaskToPrefixLength(in_addr_t mask) +{ + mask = ntohl(mask); + int prefixLength = 0; + uint32_t m = (uint32_t)mask; + while (m & 0x80000000) { + prefixLength++; + m = m << 1; + } + return prefixLength; +} + static const char *ipaddr_to_string(in_addr_t addr) { struct in_addr in_addr; @@ -126,7 +154,7 @@ int ifc_get_ifindex(const char *name, int *if_indexp) if(r < 0) return -1; *if_indexp = ifr.ifr_ifindex; - return 0; + return 0; } static int ifc_set_flags(const char *name, unsigned set, unsigned clr) @@ -163,7 +191,7 @@ int ifc_set_addr(const char *name, in_addr_t addr) ifc_init_ifr(name, &ifr); init_sockaddr_in(&ifr.ifr_addr, addr); - + return ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr); } @@ -178,17 +206,37 @@ int ifc_set_hwaddr(const char *name, const void *ptr) return ioctl(ifc_ctl_sock, SIOCSIFHWADDR, &ifr); } -int ifc_set_mask(const char *name, in_addr_t mask) +int ifc_set_prefixLength(const char *name, int prefixLength) { struct ifreq ifr; + // TODO - support ipv6 + if (prefixLength > 32 || prefixLength < 0) return -1; + in_addr_t mask = prefixLengthToIpv4Netmask(prefixLength); ifc_init_ifr(name, &ifr); init_sockaddr_in(&ifr.ifr_addr, mask); - + return ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr); } -int ifc_get_info(const char *name, in_addr_t *addr, in_addr_t *mask, unsigned *flags) +int ifc_get_addr(const char *name, in_addr_t *addr) +{ + struct ifreq ifr; + int ret = 0; + + ifc_init_ifr(name, &ifr); + if (addr != NULL) { + ret = ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr); + if (ret < 0) { + *addr = 0; + } else { + *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; + } + } + return ret; +} + +int ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength, unsigned *flags) { struct ifreq ifr; ifc_init_ifr(name, &ifr); @@ -200,12 +248,13 @@ int ifc_get_info(const char *name, in_addr_t *addr, in_addr_t *mask, unsigned *f *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; } } - - if (mask != NULL) { + + if (prefixLength != NULL) { if(ioctl(ifc_ctl_sock, SIOCGIFNETMASK, &ifr) < 0) { - *mask = 0; + *prefixLength = 0; } else { - *mask = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; + *prefixLength = ipv4NetmaskToPrefixLength((int) + ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr); } } @@ -220,17 +269,7 @@ int ifc_get_info(const char *name, in_addr_t *addr, in_addr_t *mask, unsigned *f return 0; } -in_addr_t get_ipv4_netmask(int prefix_length) -{ - in_addr_t mask = 0; - - mask = ~mask << (32 - prefix_length); - mask = htonl(mask); - - return mask; -} - -int ifc_add_ipv4_route(const char *ifname, struct in_addr dst, int prefix_length, +int ifc_act_on_ipv4_route(int action, const char *ifname, struct in_addr dst, int prefix_length, struct in_addr gw) { struct rtentry rt; @@ -242,7 +281,7 @@ int ifc_add_ipv4_route(const char *ifname, struct in_addr dst, int prefix_length rt.rt_dst.sa_family = AF_INET; rt.rt_dev = (void*) ifname; - netmask = get_ipv4_netmask(prefix_length); + netmask = prefixLengthToIpv4Netmask(prefix_length); init_sockaddr_in(&rt.rt_genmask, netmask); init_sockaddr_in(&rt.rt_dst, dst.s_addr); rt.rt_flags = RTF_UP; @@ -262,7 +301,7 @@ int ifc_add_ipv4_route(const char *ifname, struct in_addr dst, int prefix_length return -errno; } - result = ioctl(ifc_ctl_sock, SIOCADDRT, &rt); + result = ioctl(ifc_ctl_sock, action, &rt); if (result < 0) { if (errno == EEXIST) { result = 0; @@ -281,17 +320,7 @@ int ifc_create_default_route(const char *name, in_addr_t gw) in_dst.s_addr = 0; in_gw.s_addr = gw; - return ifc_add_ipv4_route(name, in_dst, 0, in_gw); -} - -int ifc_add_host_route(const char *name, in_addr_t dst) -{ - struct in_addr in_dst, in_gw; - - in_dst.s_addr = dst; - in_gw.s_addr = 0; - - return ifc_add_ipv4_route(name, in_dst, 32, in_gw); + return ifc_act_on_route(SIOCADDRT, name, in_dst, 0, in_gw); } int ifc_enable(const char *ifname) @@ -306,29 +335,65 @@ int ifc_enable(const char *ifname) int ifc_disable(const char *ifname) { + unsigned addr, count; int result; ifc_init(); result = ifc_down(ifname); + ifc_set_addr(ifname, 0); + for (count=0, addr=1;((addr != 0) && (count < 255)); count++) { + if (ifc_get_addr(ifname, &addr) < 0) + break; + if (addr) + ifc_set_addr(ifname, 0); + } + ifc_close(); return result; } -int ifc_reset_connections(const char *ifname) +#define RESET_IPV4_ADDRESSES 0x01 +#define RESET_IPV6_ADDRESSES 0x02 +#define RESET_ALL_ADDRESSES (RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES) + +int ifc_reset_connections(const char *ifname, const int reset_mask) { #ifdef HAVE_ANDROID_OS - int result; + int result, success; in_addr_t myaddr; struct ifreq ifr; + struct in6_ifreq ifr6; + + if (reset_mask & RESET_IPV4_ADDRESSES) { + /* IPv4. Clear connections on the IP address. */ + ifc_init(); + ifc_get_info(ifname, &myaddr, NULL, NULL); + ifc_init_ifr(ifname, &ifr); + init_sockaddr_in(&ifr.ifr_addr, myaddr); + result = ioctl(ifc_ctl_sock, SIOCKILLADDR, &ifr); + ifc_close(); + } else { + result = 0; + } + + if (reset_mask & RESET_IPV6_ADDRESSES) { + /* + * IPv6. On Linux, when an interface goes down it loses all its IPv6 + * addresses, so we don't know which connections belonged to that interface + * So we clear all unused IPv6 connections on the device by specifying an + * empty IPv6 address. + */ + ifc_init6(); + // This implicitly specifies an address of ::, i.e., kill all IPv6 sockets. + memset(&ifr6, 0, sizeof(ifr6)); + success = ioctl(ifc_ctl_sock6, SIOCKILLADDR, &ifr6); + if (result == 0) { + result = success; + } + ifc_close6(); + } - ifc_init(); - ifc_get_info(ifname, &myaddr, NULL, NULL); - ifc_init_ifr(ifname, &ifr); - init_sockaddr_in(&ifr.ifr_addr, myaddr); - result = ioctl(ifc_ctl_sock, SIOCKILLADDR, &ifr); - ifc_close(); - return result; #else return 0; @@ -384,67 +449,6 @@ int ifc_remove_host_routes(const char *name) } /* - * Return the address of the default gateway - * - * TODO: factor out common code from this and remove_host_routes() - * so that we only scan /proc/net/route in one place. - */ -int ifc_get_default_route(const char *ifname) -{ - char name[64]; - in_addr_t dest, gway, mask; - int flags, refcnt, use, metric, mtu, win, irtt; - int result; - FILE *fp; - - fp = fopen("/proc/net/route", "r"); - if (fp == NULL) - return 0; - /* Skip the header line */ - if (fscanf(fp, "%*[^\n]\n") < 0) { - fclose(fp); - return 0; - } - ifc_init(); - result = 0; - for (;;) { - int nread = fscanf(fp, "%63s%X%X%X%d%d%d%X%d%d%d\n", - name, &dest, &gway, &flags, &refcnt, &use, &metric, &mask, - &mtu, &win, &irtt); - if (nread != 11) { - break; - } - if ((flags & (RTF_UP|RTF_GATEWAY)) == (RTF_UP|RTF_GATEWAY) - && dest == 0 - && strcmp(ifname, name) == 0) { - result = gway; - break; - } - } - fclose(fp); - ifc_close(); - return result; -} - -/* - * Sets the specified gateway as the default route for the named interface. - */ -int ifc_set_default_route(const char *ifname, in_addr_t gateway) -{ - struct in_addr addr; - int result; - - ifc_init(); - addr.s_addr = gateway; - if ((result = ifc_create_default_route(ifname, gateway)) < 0) { - LOGD("failed to add %s as default route for %s: %s", - inet_ntoa(addr), ifname, strerror(errno)); - } - ifc_close(); - return result; -} - -/* * Removes the default route for the named interface. */ int ifc_remove_default_route(const char *ifname) @@ -467,7 +471,7 @@ int ifc_remove_default_route(const char *ifname) int ifc_configure(const char *ifname, in_addr_t address, - in_addr_t netmask, + uint32_t prefixLength, in_addr_t gateway, in_addr_t dns1, in_addr_t dns2) { @@ -486,8 +490,8 @@ ifc_configure(const char *ifname, ifc_close(); return -1; } - if (ifc_set_mask(ifname, netmask)) { - printerr("failed to set netmask %s: %s\n", ipaddr_to_string(netmask), strerror(errno)); + if (ifc_set_prefixLength(ifname, prefixLength)) { + printerr("failed to set prefixLength %d: %s\n", prefixLength, strerror(errno)); ifc_close(); return -1; } @@ -507,7 +511,7 @@ ifc_configure(const char *ifname, return 0; } -int ifc_add_ipv6_route(const char *ifname, struct in6_addr dst, int prefix_length, +int ifc_act_on_ipv6_route(int action, const char *ifname, struct in6_addr dst, int prefix_length, struct in6_addr gw) { struct in6_rtmsg rtmsg; @@ -542,7 +546,7 @@ int ifc_add_ipv6_route(const char *ifname, struct in6_addr dst, int prefix_lengt return -errno; } - result = ioctl(ifc_ctl_sock6, SIOCADDRT, &rtmsg); + result = ioctl(ifc_ctl_sock6, action, &rtmsg); if (result < 0) { if (errno == EEXIST) { result = 0; @@ -554,8 +558,8 @@ int ifc_add_ipv6_route(const char *ifname, struct in6_addr dst, int prefix_lengt return result; } -int ifc_add_route(const char *ifname, const char *dst, int prefix_length, - const char *gw) +int ifc_act_on_route(int action, const char *ifname, const char *dst, int prefix_length, + const char *gw) { int ret = 0; struct sockaddr_in ipv4_dst, ipv4_gw; @@ -573,7 +577,7 @@ int ifc_add_route(const char *ifname, const char *dst, int prefix_length, return -EINVAL; } - if (gw == NULL) { + if (gw == NULL || (strlen(gw) == 0)) { if (addr_ai->ai_family == AF_INET6) { gw = "::"; } else if (addr_ai->ai_family == AF_INET) { @@ -581,6 +585,13 @@ int ifc_add_route(const char *ifname, const char *dst, int prefix_length, } } + if (((addr_ai->ai_family == AF_INET6) && (prefix_length < 0 || prefix_length > 128)) || + ((addr_ai->ai_family == AF_INET) && (prefix_length < 0 || prefix_length > 32))) { + printerr("ifc_add_route: invalid prefix length"); + freeaddrinfo(addr_ai); + return -EINVAL; + } + ret = getaddrinfo(gw, NULL, &hints, &gw_ai); if (ret != 0) { printerr("getaddrinfo failed: invalid gateway %s\n", gw); @@ -598,13 +609,13 @@ int ifc_add_route(const char *ifname, const char *dst, int prefix_length, if (addr_ai->ai_family == AF_INET6) { memcpy(&ipv6_dst, addr_ai->ai_addr, sizeof(struct sockaddr_in6)); memcpy(&ipv6_gw, gw_ai->ai_addr, sizeof(struct sockaddr_in6)); - ret = ifc_add_ipv6_route(ifname, ipv6_dst.sin6_addr, prefix_length, - ipv6_gw.sin6_addr); + ret = ifc_act_on_ipv6_route(action, ifname, ipv6_dst.sin6_addr, + prefix_length, ipv6_gw.sin6_addr); } else if (addr_ai->ai_family == AF_INET) { memcpy(&ipv4_dst, addr_ai->ai_addr, sizeof(struct sockaddr_in)); memcpy(&ipv4_gw, gw_ai->ai_addr, sizeof(struct sockaddr_in)); - ret = ifc_add_ipv4_route(ifname, ipv4_dst.sin_addr, prefix_length, - ipv4_gw.sin_addr); + ret = ifc_act_on_ipv4_route(action, ifname, ipv4_dst.sin_addr, + prefix_length, ipv4_gw.sin_addr); } else { printerr("ifc_add_route: getaddrinfo returned un supported address family %d\n", addr_ai->ai_family); @@ -615,3 +626,13 @@ int ifc_add_route(const char *ifname, const char *dst, int prefix_length, freeaddrinfo(gw_ai); return ret; } + +int ifc_add_route(const char *ifname, const char *dst, int prefix_length, const char *gw) +{ + return ifc_act_on_route(SIOCADDRT, ifname, dst, prefix_length, gw); +} + +int ifc_remove_route(const char *ifname, const char*dst, int prefix_length, const char *gw) +{ + return ifc_act_on_route(SIOCDELRT, ifname, dst, prefix_length, gw); +} |