/** * @file net/rt.c Generic routing table code * * Copyright (C) 2010 Creytiv.com */ #define _BSD_SOURCE 1 #include #include #include #include #include struct net_rt { int af; char *ifname; size_t size; int prefix; }; static bool rt_debug_handler(const char *ifname, const struct sa *dst, int dstlen, const struct sa *gw, void *arg) { char addr[64]; struct re_printf *pf = arg; int err = 0; (void)re_snprintf(addr, sizeof(addr), "%j/%d", dst, dstlen); err |= re_hprintf(pf, " %-44s", addr); err |= re_hprintf(pf, "%-40j", gw); err |= re_hprintf(pf, " %-15s ", ifname); #ifdef HAVE_INET6 if (AF_INET6 == sa_af(dst)) { const struct sockaddr_in6 *sin6 = &dst->u.in6; const struct in6_addr *in6 = &sin6->sin6_addr; if (IN6_IS_ADDR_MULTICAST(in6)) err |= re_hprintf(pf, " MULTICAST"); if (IN6_IS_ADDR_LINKLOCAL(in6)) err |= re_hprintf(pf, " LINKLOCAL"); if (IN6_IS_ADDR_SITELOCAL(in6)) err |= re_hprintf(pf, " SITELOCAL"); } #endif err |= re_hprintf(pf, "\n"); return 0 != err; } /** * Dump the routing table * * @param pf Print function for output * @param unused Unused parameter * * @return 0 if success, otherwise errorcode */ int net_rt_debug(struct re_printf *pf, void *unused) { int err = 0; (void)unused; err |= re_hprintf(pf, "net routes:\n"); err |= re_hprintf(pf, " Destination " "Next Hop" " Iface " "Type\n"); err |= net_rt_list(rt_debug_handler, pf); return err; } static bool rt_default_get_handler(const char *_ifname, const struct sa *dst, int dstlen, const struct sa *gw, void *arg) { struct net_rt *rt = arg; (void)dstlen; (void)gw; if (sa_af(dst) != rt->af) return false; switch (rt->af) { case AF_INET: if (0 == sa_in(dst)) { str_ncpy(rt->ifname, _ifname, rt->size); return true; } break; #ifdef HAVE_INET6 case AF_INET6: if (IN6_IS_ADDR_MULTICAST(&dst->u.in6.sin6_addr)) return false; if (IN6_IS_ADDR_LINKLOCAL(&dst->u.in6.sin6_addr)) return false; if (dstlen < rt->prefix) { rt->prefix = dstlen; str_ncpy(rt->ifname, _ifname, rt->size); return false; } break; #endif } return false; } /** * Get the interface name of the default route * * @param af Address family * @param ifname Buffer for returned interface name * @param size Size of buffer * * @return 0 if success, otherwise errorcode */ int net_rt_default_get(int af, char *ifname, size_t size) { struct net_rt rt; int err; rt.af = af; rt.ifname = ifname; rt.size = size; rt.prefix = 256; err = net_rt_list(rt_default_get_handler, &rt); if (err) return err; return '\0' != ifname[0] ? 0 : EINVAL; } #ifndef HAVE_ROUTE_LIST /* We must provide a stub */ int net_rt_list(net_rt_h *rth, void *arg) { (void)rth; (void)arg; return ENOSYS; } #endif