From 00fc1df9598f1de727051a6e1dd263837293af43 Mon Sep 17 00:00:00 2001 From: Ashish Shukla Date: Tue, 7 Oct 2008 16:24:56 +0530 Subject: [PATCH] 2008-10-07 Ashish Shukla * libroute/route_bsd.h: Removed flags parameter from 'bsd_add' function prototype. * libroute/route_bsd.c (bsd_add): Implemented. * libroute/bsd_add.c, libroute/bsd_delete.c, libroute/bsd_show.c: Merged into libroute/route_bsd.c and removed. * libroute/Makefile.am: Updated. --- ChangeLog | 12 ++ libroute/Makefile.am | 3 +- libroute/bsd_add.c | 33 ---- libroute/bsd_delete.c | 28 --- libroute/bsd_show.c | 310 ------------------------------- libroute/route_bsd.c | 484 +++++++++++++++++++++++++++++++++++++++++++++++++ libroute/route_bsd.h | 3 +- 7 files changed, 498 insertions(+), 375 deletions(-) delete mode 100644 libroute/bsd_add.c delete mode 100644 libroute/bsd_delete.c delete mode 100644 libroute/bsd_show.c diff --git a/ChangeLog b/ChangeLog index 3173ccd..bdd00db 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,17 @@ 2008-10-07 Ashish Shukla + * libroute/route_bsd.h: Removed flags parameter from 'bsd_add' + function prototype. + + * libroute/route_bsd.c (bsd_add): Implemented. + + * libroute/bsd_add.c, libroute/bsd_delete.c, libroute/bsd_show.c: + Merged into libroute/route_bsd.c and removed. + + * libroute/Makefile.am: Updated. + +2008-10-07 Ashish Shukla + * libroute/route_common.c (conv_name_to_addr): Support IPv6 addresses. Use `gethostbyname2' instead of `gethostbyname'. diff --git a/libroute/Makefile.am b/libroute/Makefile.am index 52c5216..33c1b48 100644 --- a/libroute/Makefile.am +++ b/libroute/Makefile.am @@ -22,8 +22,7 @@ EXTRA_LTLIBRARIES = libroute.la libroute_la_SOURCES = route_backend.c route_common.c route_$(KERNEL).c -EXTRA_libroute_la_SOURCES = bsd_add.c bsd_delete.c bsd_show.c route_bsd.c \ - route_linux.c +EXTRA_libroute_la_SOURCES = route_bsd.c route_linux.c noinst_HEADERS = route.h route_bsd.h route_linux.h diff --git a/libroute/bsd_add.c b/libroute/bsd_add.c deleted file mode 100644 index 299d9c9..0000000 --- a/libroute/bsd_add.c +++ /dev/null @@ -1,33 +0,0 @@ -/* Copyright (C) 2008 Free Software Foundation, Inc. - - This file is part of Netutils. - - Netutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - Netutils is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Netutils; see the file COPYING. If not, write - to the Free Software Foundation, Inc., 51 Franklin Street, - Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include -#include - -void -bsd_add (const int format, - const uint16_t flags, - const void *const dest_addr, - const size_t dest_addr_size, - const unsigned char dest_addr_len, - const void *const gw_addr, - const size_t gw_addr_size, - const unsigned int iface) -{ -} diff --git a/libroute/bsd_delete.c b/libroute/bsd_delete.c deleted file mode 100644 index 2c88055..0000000 --- a/libroute/bsd_delete.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (C) 2008 Free Software Foundation, Inc. - - This file is part of Netutils. - - Netutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - Netutils is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Netutils; see the file COPYING. If not, write - to the Free Software Foundation, Inc., 51 Franklin Street, - Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include - -void -bsd_delete (const int format, - const void *const dest_addr, - const size_t dest_addr_size, - const unsigned char dest_len) -{ -} diff --git a/libroute/bsd_show.c b/libroute/bsd_show.c deleted file mode 100644 index 327a691..0000000 --- a/libroute/bsd_show.c +++ /dev/null @@ -1,310 +0,0 @@ -/* Copyright (C) 2008 Free Software Foundation, Inc. - - This file is part of Netutils. - - Netutils is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3, or (at your option) - any later version. - - Netutils is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Netutils; see the file COPYING. If not, write - to the Free Software Foundation, Inc., 51 Franklin Street, - Fifth Floor, Boston, MA 02110-1301 USA. */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "route.h" -#include "xalloc.h" - -enum -{ - K_INET = 20, - K_INET6 = 21 -}; - -struct flag -{ - int mask; - char * str; -}; -typedef struct flag flag_t; - -void bsd_conv_addr_to_name (const struct sockaddr *const sock, - char *const buffer, const size_t buffer_size, - const short int resolve_names); -void bsd_flags (const int field, char *const buffer, size_t size); -const route_info_t * bsd_parse_msg (const sa_family_t sa_family, - const struct rt_msghdr *msg, size_t nread, - const short int resolve_names); -size_t bsd_sysctl (void ** buffer, size_t *const size); -struct rt_msghdr * rt_msg_next (const struct rt_msghdr *rtm, - size_t *const length); - -void -bsd_conv_addr_to_name (const struct sockaddr *const sock, - char *const buffer, const size_t buffer_size, - const short int resolve_names) -{ - if (sock->sa_family == AF_LINK) - conv_link_addr_to_name (sock, sock->sa_len, buffer, buffer_size, - resolve_names); - else if (sock->sa_family == AF_INET || sock->sa_family == AF_INET6) - { - void *addr; - size_t addr_size; - - if (sock->sa_family == AF_INET) - { - addr = &(((struct sockaddr_in *) sock)->sin_addr); - addr_size = sizeof (struct in_addr); - } - else /* AF_INET */ - { - addr = &(((struct sockaddr_in6 *) sock)->sin6_addr); - addr_size = sizeof (struct in6_addr); - } - - conv_inet_addr_to_name (sock->sa_family, addr, addr_size, - buffer, buffer_size, resolve_names); - } - else - printf ("%u\n", sock->sa_family); -} - -void -bsd_flags (const int field, char *const buffer, size_t size) -{ - const flag_t flags[] = { - {RTF_UP, "U"}, - {RTF_GATEWAY, "G"}, - {RTF_HOST, "H"}, - {RTF_REJECT, "R"}, - {RTF_DYNAMIC, "D"}, - {RTF_LLINFO, "L"}, - {RTF_STATIC, "S"}, - {RTF_WASCLONED, "W"}, - }; - int i; - - memset ((void*) buffer, 0, size); - for (i = 0; i < sizeof (flags) / sizeof (flags[0]); i++) - { - if ((field & flags[i].mask) != 0) - { - strncat (buffer, flags[i].str, size - 1); - size -= strlen (flags[i].str); - } - } -} - -const route_info_t * -bsd_show (const sa_family_t sa_family, const short int resolve_names) -{ - const route_info_t *list; - size_t nread; - size_t size; - struct rt_msghdr *msg; - - nread = bsd_sysctl ((void **) &msg, &size); - list = bsd_parse_msg (sa_family, msg, nread, resolve_names); - free (msg); - return list; -} - -const route_info_t * -bsd_parse_msg (const sa_family_t sa_family, - const struct rt_msghdr *msg, size_t nread, - const short int resolve_names) -{ - const route_info_t *list = NULL; - route_info_t *route_info = NULL; - const struct sockaddr *sock_addr; - - while (msg != NULL) - { - sock_addr = (struct sockaddr *) (msg + 1); - if (sock_addr->sa_family != sa_family) - goto next; - - route_info = route_info_append (route_info); - if (list == NULL) - list = route_info; - route_info_init (route_info, resolve_names); - - if_indextoname (msg->rtm_index, route_info->oif_name); - bsd_flags (msg->rtm_flags, route_info->flag_str, - sizeof (route_info->flag_str)); - - if ((msg->rtm_addrs & RTA_DST) != 0) - { -#ifdef __KAME__ - /* Remove embedded scope id-field added by KAME implementation. */ - if(sa_family == AF_INET6) - { - struct in6_addr *addr_6 - = &(((struct sockaddr_in6 *) sock_addr)->sin6_addr); - - if((IN6_IS_ADDR_LINKLOCAL (addr_6) - || IN6_IS_ADDR_MC_LINKLOCAL (addr_6)) - && ((struct sockaddr_in6 *) sock_addr)->sin6_scope_id == 0) - { - addr_6->s6_addr[2] = 0; - addr_6->s6_addr[3] = 0; - } - } -#endif /* __KAME__ */ - route_info->dest_present = 1; - bsd_conv_addr_to_name (sock_addr, route_info->dest, - sizeof (route_info->dest), resolve_names); - } - - sock_addr = (struct sockaddr *) ((char *) sock_addr - + SA_SIZE(sock_addr)); - - if ((msg->rtm_addrs & RTA_GATEWAY) != 0) - { -#ifdef __KAME__ - /* Remove embedded scope id-field added by KAME implementation. */ - if(sa_family == AF_INET6) - { - struct in6_addr *addr_6 - = &(((struct sockaddr_in6 *) sock_addr)->sin6_addr); - - if((IN6_IS_ADDR_LINKLOCAL (addr_6) - || IN6_IS_ADDR_MC_LINKLOCAL(addr_6)) - && ((struct sockaddr_in6 *)sock_addr)->sin6_scope_id == 0) - { - addr_6->s6_addr[2] = 0; - addr_6->s6_addr[3] = 0; - } - } -#endif /* __KAME__ */ - route_info->gateway_present = 1; - bsd_conv_addr_to_name (sock_addr, route_info->gateway, - sizeof (route_info->gateway), resolve_names); - } - - sock_addr = (struct sockaddr *) ((char *) sock_addr - + SA_SIZE(sock_addr)); - if ((msg->rtm_addrs & RTA_NETMASK) != 0) - { - char buffer[sizeof (struct sockaddr_in6)]; - unsigned char* s_addr; - socklen_t s_len; - - memset (buffer, 0, sizeof (struct sockaddr_in6)); - strncpy (buffer, (char *) sock_addr, sock_addr->sa_len); - ((struct sockaddr *) buffer)->sa_family = sa_family; - - s_addr = &(sock_addr->sa_data[2]); - s_len = sock_addr->sa_len; - route_info->dest_len = 0; - - if (s_len != 0) - { - /* Figure out the length of address in the sockaddr structure, - * by subtracting the offset portion of the address (in - * sockaddr structure) from the length of sockaddr structure. - * NOTE: the length will be dynamic as this is a netmask - * represented in a sockaddr. - */ - s_len -= (sa_family == AF_INET) ? - (socklen_t) ((char *) (&((struct sockaddr_in *) - sock_addr)->sin_addr) - (char *) sock_addr): - (socklen_t) ((char *) (&((struct sockaddr_in6 *) - sock_addr)->sin6_addr) - (char *) sock_addr); - } - - bsd_conv_addr_to_name ((struct sockaddr *) buffer, - route_info->dest_mask, - sizeof(route_info->dest_mask), 0); - - while (s_len != 0) - { - while ((*s_addr & 0x80) != 0) - { - route_info->dest_len++; - *s_addr <<= 1; - } - s_addr++; - s_len--; - } - } - - next: - msg = rt_msg_next (msg, &nread); - } - - return list; -} - -size_t -bsd_sysctl (void ** buffer, size_t *const size) -{ - int mib[6]; - int status; - size_t length; - - mib[0] = CTL_NET; - mib[1] = PF_ROUTE; - mib[2] = 0; - mib[3] = 0; - mib[4] = NET_RT_DUMP; - mib[5] = 0; - - status = sysctl (mib, 6, NULL, &length, NULL, 0); - if (status == -1 || length == 0) - error (EXIT_FAILURE, errno, "sysctl"); - - *buffer = xmalloc (length); - *size = length; - - status = sysctl (mib, 6, *buffer, &length, NULL, 0); - if (status == -1) - error (EXIT_FAILURE, errno, "sysctl"); - - return length; -} - -struct rt_msghdr * -rt_msg_next (const struct rt_msghdr *rtm, size_t *const length) -{ - struct rt_msghdr * next - = (struct rt_msghdr *) ((char *) rtm + rtm->rtm_msglen); - - *length -= rtm->rtm_msglen; - if (*length <= 0) - return NULL; - else if (*length < next->rtm_msglen) - return NULL; - - return next; -} diff --git a/libroute/route_bsd.c b/libroute/route_bsd.c index 86b9da9..c660d81 100644 --- a/libroute/route_bsd.c +++ b/libroute/route_bsd.c @@ -17,8 +17,37 @@ to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include "route.h" #include "route_bsd.h" +#include "xalloc.h" const route_backend_t bsd_backend = { @@ -30,3 +59,458 @@ const route_backend_t bsd_backend = bsd_add, bsd_show }; + +#define RT_HDR_BUFFER_SIZE 512 + +/** TODO: find a better way to track sequence no.s */ +int seq_rtm = 0; + +typedef struct pf_route_message { + struct sockaddr* addr[RTAX_MAX]; +} pf_route_message_t; + +typedef struct flag +{ + int mask; + char * str; +} flag_t; + +/* empty sockaddr */ +const struct sockaddr sa_empty = { + sizeof(struct sockaddr), +}; + +static void bsd_rt_msg_send(int msg_type, + int msg_iface, + int msg_seq, + int msg_flags, + pf_route_message_t* message); +static void bsd_conv_addr_to_name (const struct sockaddr *const sock, + char *const buffer, const size_t buffer_size, + const short int resolve_names); +static void bsd_flags (const int field, char *const buffer, size_t size); +static const route_info_t * bsd_parse_msg (const sa_family_t sa_family, + const struct rt_msghdr *msg, size_t nread, + const short int resolve_names); +static size_t bsd_sysctl (void ** buffer, size_t *const size); +static struct rt_msghdr * bsd_rt_msg_next (const struct rt_msghdr *rtm, + size_t *const length); + +void +bsd_add (const int address_family, + const void *const dest_addr, + const size_t dest_addr_size, + const unsigned char dest_addr_len, + const void *const gw_addr, + const size_t gw_addr_size, + const unsigned int iface) +{ + pf_route_message_t msg; + struct ifaddrs* ifas; + int i; + int flags = RTF_STATIC; + + memset(&msg, 0, sizeof(pf_route_message_t)); + + if(iface) + if(getifaddrs(&ifas) == -1) + return; + + if(address_family == AF_INET) + { + char* p; + int len = dest_addr_len; + + msg.addr[RTAX_NETMASK] = (struct sockaddr*)xcalloc(1, sizeof(struct sockaddr_in)); + ((struct sockaddr_in*)msg.addr[RTAX_NETMASK])->sin_family = AF_INET; + ((struct sockaddr_in*)msg.addr[RTAX_NETMASK])->sin_len = sizeof(struct sockaddr_in); + p = (char*)&((struct sockaddr_in*)msg.addr[RTAX_NETMASK])->sin_addr; + + for(i = 1; i <= len; i++) + { + *p >>= 1; + *p |= 0x80; + + if(!(i & 7)) + p++; + } + + if(dest_addr) + { + msg.addr[RTAX_DST] = (struct sockaddr*)xcalloc(1, sizeof(struct sockaddr_in)); + ((struct sockaddr_in*)msg.addr[RTAX_DST])->sin_family = AF_INET; + ((struct sockaddr_in*)msg.addr[RTAX_DST])->sin_len = sizeof(struct sockaddr_in); + memcpy(&((struct sockaddr_in*)msg.addr[RTAX_DST])->sin_addr, dest_addr, dest_addr_size); + } + + if(gw_addr) + { + msg.addr[RTAX_GATEWAY] = (struct sockaddr*)xcalloc(1, sizeof(struct sockaddr_in)); + ((struct sockaddr_in*)msg.addr[RTAX_GATEWAY])->sin_family = AF_INET; + ((struct sockaddr_in*)msg.addr[RTAX_GATEWAY])->sin_len = sizeof(struct sockaddr_in); + memcpy(&((struct sockaddr_in*)msg.addr[RTAX_GATEWAY])->sin_addr, gw_addr, gw_addr_size); + flags |= RTF_GATEWAY; + } + } + else if(address_family == AF_INET6) + { + char* p; + int len = dest_addr_len; + + msg.addr[RTAX_NETMASK] = (struct sockaddr*)xcalloc(1, sizeof(struct sockaddr_in6)); + ((struct sockaddr_in6*)msg.addr[RTAX_NETMASK])->sin6_family = AF_INET6; + ((struct sockaddr_in6*)msg.addr[RTAX_NETMASK])->sin6_len = sizeof(struct sockaddr_in6); + p = (char*)&((struct sockaddr_in6*)msg.addr[RTAX_NETMASK])->sin6_addr; + + for(i = 1; i <= len; i++) + { + *p >>= 1; + *p |= 0x80; + + if(!(i & 7)) + p++; + } + + if(dest_addr) + { + msg.addr[RTAX_DST] = (struct sockaddr*)xcalloc(1, sizeof(struct sockaddr_in6)); + ((struct sockaddr_in6*)msg.addr[RTAX_DST])->sin6_family = AF_INET6; + ((struct sockaddr_in6*)msg.addr[RTAX_DST])->sin6_len = sizeof(struct sockaddr_in6); + memcpy(&((struct sockaddr_in6*)msg.addr[RTAX_DST])->sin6_addr, dest_addr, dest_addr_size); + } + + if(gw_addr) + { + msg.addr[RTAX_GATEWAY] = (struct sockaddr*)xcalloc(1, sizeof(struct sockaddr_in6)); + ((struct sockaddr_in6*)msg.addr[RTAX_GATEWAY])->sin6_family = AF_INET6; + ((struct sockaddr_in6*)msg.addr[RTAX_GATEWAY])->sin6_len = sizeof(struct sockaddr_in6); + memcpy(&((struct sockaddr_in6*)msg.addr[RTAX_GATEWAY])->sin6_addr, gw_addr, gw_addr_size); + flags |= RTF_GATEWAY; + } + } + + if(iface) + { + struct ifaddrs* ifa = ifas; + while(ifa) + { + if(((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index == iface) + { + msg.addr[RTAX_GATEWAY] = xmalloc(SA_SIZE(ifa->ifa_addr)); + memcpy(msg.addr[RTAX_GATEWAY], ifa->ifa_addr, SA_SIZE(ifa->ifa_addr)); + break; + } + ifa = ifa->ifa_next; + } + flags &= ~RTF_GATEWAY; + } + + bsd_rt_msg_send(RTM_ADD, iface, 0, flags, &msg); + + for(i = 0; i < RTAX_MAX; i++) + if(msg.addr[i]) + { + free(msg.addr[i]); + msg.addr[i] = NULL; + } + + if(iface) + freeifaddrs(ifas); + + return; +} + +static void +bsd_rt_msg_send(int msg_type, int msg_iface, int msg_seq, + int msg_flags, pf_route_message_t* message) +{ + char* buffer; + struct rt_msghdr* rtm; + struct sockaddr* addr; + int i; + int len = sizeof(struct rt_msghdr); + int fd; + + buffer = xcalloc(1, RT_HDR_BUFFER_SIZE); + rtm = (struct rt_msghdr*)buffer; + + rtm->rtm_version = RTM_VERSION; + rtm->rtm_type = msg_type; + rtm->rtm_index = msg_iface; + rtm->rtm_pid = getpid(); + rtm->rtm_seq = msg_seq; + rtm->rtm_flags = msg_flags; + + addr = (struct sockaddr*)(rtm+1); + + for(i = 0; i < RTAX_MAX; i++) + { + if(message->addr[i]) + { + memcpy(addr, message->addr[i], SA_SIZE(message->addr[i])); + rtm->rtm_addrs |= (1 << i); + } + else + memcpy(addr, &sa_empty, SA_SIZE(&sa_empty)); + len += SA_SIZE(addr); + addr = (struct sockaddr*)(((char*)addr) + SA_SIZE(addr)); + } + + rtm->rtm_msglen = len; + + if((fd = socket(PF_ROUTE, SOCK_RAW, 0)) == -1) + return; + + if(write(fd, rtm, rtm->rtm_msglen) == -1) + return; + + close(fd); + free(rtm); +} + +static void +bsd_conv_addr_to_name (const struct sockaddr *const sock, + char *const buffer, const size_t buffer_size, + const short int resolve_names) +{ + if (sock->sa_family == AF_LINK) + conv_link_addr_to_name (sock, sock->sa_len, buffer, buffer_size, + resolve_names); + else if (sock->sa_family == AF_INET || sock->sa_family == AF_INET6) + { + void *addr; + size_t addr_size; + + if (sock->sa_family == AF_INET) + { + addr = &(((struct sockaddr_in *) sock)->sin_addr); + addr_size = sizeof (struct in_addr); + } + else /* AF_INET */ + { + addr = &(((struct sockaddr_in6 *) sock)->sin6_addr); + addr_size = sizeof (struct in6_addr); + } + + conv_inet_addr_to_name (sock->sa_family, addr, addr_size, + buffer, buffer_size, resolve_names); + } + else + printf ("%u\n", sock->sa_family); +} + +static void +bsd_flags (const int field, char *const buffer, size_t size) +{ + const flag_t flags[] = { + {RTF_UP, "U"}, + {RTF_GATEWAY, "G"}, + {RTF_HOST, "H"}, + {RTF_REJECT, "R"}, + {RTF_DYNAMIC, "D"}, + {RTF_LLINFO, "L"}, + {RTF_STATIC, "S"}, + {RTF_WASCLONED, "W"}, + }; + int i; + + memset ((void*) buffer, 0, size); + for (i = 0; i < sizeof (flags) / sizeof (flags[0]); i++) + { + if ((field & flags[i].mask) != 0) + { + strncat (buffer, flags[i].str, size - 1); + size -= strlen (flags[i].str); + } + } +} + +const route_info_t * +bsd_show (const sa_family_t sa_family, const short int resolve_names) +{ + const route_info_t *list; + size_t nread; + size_t size; + struct rt_msghdr *msg; + + nread = bsd_sysctl ((void **) &msg, &size); + list = bsd_parse_msg (sa_family, msg, nread, resolve_names); + free (msg); + return list; +} + +static const route_info_t * +bsd_parse_msg (const sa_family_t sa_family, + const struct rt_msghdr *msg, size_t nread, + const short int resolve_names) +{ + const route_info_t *list = NULL; + route_info_t *route_info = NULL; + const struct sockaddr *sock_addr; + + while (msg != NULL) + { + sock_addr = (struct sockaddr *) (msg + 1); + if (sock_addr->sa_family != sa_family) + goto next; + + route_info = route_info_append (route_info); + if (list == NULL) + list = route_info; + route_info_init (route_info, resolve_names); + + if_indextoname (msg->rtm_index, route_info->oif_name); + bsd_flags (msg->rtm_flags, route_info->flag_str, + sizeof (route_info->flag_str)); + + if ((msg->rtm_addrs & RTA_DST) != 0) + { +#ifdef __KAME__ + /* Remove embedded scope id-field added by KAME implementation. */ + if(sa_family == AF_INET6) + { + struct in6_addr *addr_6 + = &(((struct sockaddr_in6 *) sock_addr)->sin6_addr); + + if((IN6_IS_ADDR_LINKLOCAL (addr_6) + || IN6_IS_ADDR_MC_LINKLOCAL (addr_6)) + && ((struct sockaddr_in6 *) sock_addr)->sin6_scope_id == 0) + { + addr_6->s6_addr[2] = 0; + addr_6->s6_addr[3] = 0; + } + } +#endif /* __KAME__ */ + route_info->dest_present = 1; + bsd_conv_addr_to_name (sock_addr, route_info->dest, + sizeof (route_info->dest), resolve_names); + } + + sock_addr = (struct sockaddr *) ((char *) sock_addr + + SA_SIZE(sock_addr)); + + if ((msg->rtm_addrs & RTA_GATEWAY) != 0) + { +#ifdef __KAME__ + /* Remove embedded scope id-field added by KAME implementation. */ + if(sa_family == AF_INET6) + { + struct in6_addr *addr_6 + = &(((struct sockaddr_in6 *) sock_addr)->sin6_addr); + + if((IN6_IS_ADDR_LINKLOCAL (addr_6) + || IN6_IS_ADDR_MC_LINKLOCAL(addr_6)) + && ((struct sockaddr_in6 *)sock_addr)->sin6_scope_id == 0) + { + addr_6->s6_addr[2] = 0; + addr_6->s6_addr[3] = 0; + } + } +#endif /* __KAME__ */ + route_info->gateway_present = 1; + bsd_conv_addr_to_name (sock_addr, route_info->gateway, + sizeof (route_info->gateway), resolve_names); + } + + sock_addr = (struct sockaddr *) ((char *) sock_addr + + SA_SIZE(sock_addr)); + if ((msg->rtm_addrs & RTA_NETMASK) != 0) + { + char buffer[sizeof(struct sockaddr_in6)]; + unsigned char* s_addr; + socklen_t s_len; + + memset (buffer, 0, sizeof(struct sockaddr_in6)); + strncpy (buffer, (char *) sock_addr, sock_addr->sa_len); + ((struct sockaddr *) buffer)->sa_family = sa_family; + + s_addr = ((sa_family == AF_INET) ? + (unsigned char*)&((struct sockaddr_in*)sock_addr)->sin_addr: + (unsigned char*)&((struct sockaddr_in6*)sock_addr)->sin6_addr); + + s_len = sock_addr->sa_len; + route_info->dest_len = 0; + + if(s_len) + { + /* Figure out the length of address in the sockaddr structure, by subtracting + * the offset portion of the address (in sockaddr structure) from the length + * of sockaddr structure. + * NOTE: the length will be dynamic as this is a netmask represented in a sockaddr. + */ + s_len -= (socklen_t)((char*)s_addr - (char*)sock_addr); + } + + bsd_conv_addr_to_name ((struct sockaddr *) buffer, + route_info->dest_mask, + sizeof(route_info->dest_mask), 0); + + while(s_len--) + { + while(*s_addr & 0x80) + { + route_info->dest_len++; + *s_addr <<= 1; + } + s_addr++; + } + } + + next: + msg = bsd_rt_msg_next (msg, &nread); + } + + return list; +} + +static size_t +bsd_sysctl (void ** buffer, size_t *const size) +{ + int mib[6]; + int status; + size_t length; + + mib[0] = CTL_NET; + mib[1] = PF_ROUTE; + mib[2] = 0; + mib[3] = 0; + mib[4] = NET_RT_DUMP; + mib[5] = 0; + + status = sysctl (mib, 6, NULL, &length, NULL, 0); + if (status == -1 || length == 0) + error (EXIT_FAILURE, errno, "sysctl"); + + *buffer = xmalloc (length); + *size = length; + + status = sysctl (mib, 6, *buffer, &length, NULL, 0); + if (status == -1) + error (EXIT_FAILURE, errno, "sysctl"); + + return length; +} + +static struct rt_msghdr * +bsd_rt_msg_next (const struct rt_msghdr *rtm, size_t *const length) +{ + struct rt_msghdr * next + = (struct rt_msghdr *) ((char *) rtm + rtm->rtm_msglen); + + *length -= rtm->rtm_msglen; + if (*length <= 0) + return NULL; + else if (*length < next->rtm_msglen) + return NULL; + + return next; +} + +void +bsd_delete (const int format, + const void *const dest_addr, + const size_t dest_addr_size, + const unsigned char dest_len) +{ + /* TODO */ +} diff --git a/libroute/route_bsd.h b/libroute/route_bsd.h index 6ef1a45..8a38f79 100644 --- a/libroute/route_bsd.h +++ b/libroute/route_bsd.h @@ -24,8 +24,7 @@ #include "route.h" -extern void bsd_add (const int format, - const uint16_t flags, +extern void bsd_add (const int address_family, const void *const dest_addr, const size_t dest_addr_size, const unsigned char dest_addr_len, -- 1.6.0.2