2010-11-03 11:34:14 +00:00
|
|
|
/**
|
|
|
|
* @file net/rt.c Generic routing table code
|
|
|
|
*
|
|
|
|
* Copyright (C) 2010 Creytiv.com
|
|
|
|
*/
|
2012-06-11 05:38:38 +00:00
|
|
|
#define _BSD_SOURCE 1
|
2010-11-03 11:34:14 +00:00
|
|
|
#include <re_types.h>
|
|
|
|
#include <re_fmt.h>
|
|
|
|
#include <re_mbuf.h>
|
|
|
|
#include <re_sa.h>
|
|
|
|
#include <re_net.h>
|
|
|
|
|
|
|
|
|
|
|
|
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
|