diff options
Diffstat (limited to 'rtems/rtems_showroute.c')
-rw-r--r-- | rtems/rtems_showroute.c | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/rtems/rtems_showroute.c b/rtems/rtems_showroute.c new file mode 100644 index 0000000..971c364 --- /dev/null +++ b/rtems/rtems_showroute.c @@ -0,0 +1,240 @@ +#include <machine/rtems-bsd-kernel-space.h> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <sys/param.h> +#include <sys/queue.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/sysctl.h> +#include <sys/proc.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/socketvar.h> +#include <sys/domain.h> + +#include <net/if.h> +#include <net/if_var.h> +#include <net/if_dl.h> +#include <net/route.h> + +#include <netinet/in.h> + +/* + * We'll use the application versions of realloc and free. + */ +#undef free +#undef malloc +#undef random +#include <stdlib.h> + +#include <rtems/rtems_bsdnet.h> + +/* + * Information per route + */ +struct rinfo { + struct sockaddr dst; + union { + struct sockaddr sa; + struct sockaddr_in sin; + struct sockaddr_dl sdl; + } un; + unsigned long pksent; + unsigned long expire; + int flags; + char ifname[16]; + short ifunit; + short refcnt; +}; + +/* + * Information per display + */ +struct dinfo { + int capacity; + int count; + struct rinfo *routes; +}; + +/* + * Copy address + */ +static void +copyAddress (void *to, void *from, int tolen) +{ + int ncopy; + struct sockaddr dummy; + + if (from == NULL) { + /* + * Create a fake address of unspecified type + */ + from = &dummy; + dummy.sa_len = 4; + dummy.sa_family = AF_UNSPEC; + } + ncopy = ((struct sockaddr *)from)->sa_len; + if (ncopy > tolen) + ncopy = tolen; + memcpy (to, from, ncopy); +} + +/* + * Package everything up before printing it. + * We don't want to block all network operations till + * the printing completes! + */ +static int +show_inet_route ( + struct radix_node *rn, + void *vw ) +{ + struct rtentry *rt = (struct rtentry *)rn; + struct ifnet *ifp; + struct dinfo *dp = (struct dinfo *)vw; + struct rinfo *r; + + /* + * Get a pointer to a new route info structure + */ + if (dp->count >= dp->capacity) { + r = realloc (dp->routes, (sizeof *r) * (dp->capacity + 20)); + if (r == 0) + return ENOMEM; + dp->capacity += 20; + dp->routes = r; + } + r = dp->routes + dp->count++; + + /* + * Fill in the route info structure + */ + copyAddress (&r->dst, rt_key(rt), sizeof r->dst); + if (rt->rt_flags & (RTF_GATEWAY | RTF_HOST)) { + copyAddress (&r->un, rt->rt_gateway, sizeof r->un); + } + else { + /* + * Create a fake address to hold the mask + */ + struct sockaddr_in dummy; + + dummy.sin_family = AF_INET; + dummy.sin_len = sizeof dummy; + dummy.sin_addr = ((struct sockaddr_in *)rt_mask(rt))->sin_addr; + copyAddress (&r->un, &dummy, sizeof r->un); + } + r->flags = rt->rt_flags; + r->refcnt = rt->rt_refcnt; + r->pksent = rt->rt_rmx.rmx_pksent; + r->expire = rt->rt_rmx.rmx_expire; + ifp = rt->rt_ifp; + strncpy (r->ifname, (ifp->if_name ? ifp->if_name : ""), sizeof r->ifname); + r->ifunit = ifp->if_unit; + return 0; +} + +/* + * Convert link address to ASCII + */ +static char * +link_ascii (struct sockaddr_dl *sdl, char *buf, int bufsize) +{ + char *cp; + int i; + int first = 1; + int nleft = sdl->sdl_alen; + char *ap = LLADDR (sdl); + static const char hextab[16] = "0123456789ABCDEF"; + + cp = buf; + while (nleft && (bufsize > 4)) { + if (first) { + first = 0; + } + else { + *cp++ = ':'; + bufsize--; + } + i = *ap++; + *cp++ = hextab[(i >> 4) & 0xf]; + *cp++ = hextab[i & 0xf]; + nleft--; + bufsize -= 2; + } + *cp = '\0'; + return buf; +} + +void +rtems_bsdnet_show_inet_routes (void) +{ + struct radix_node_head *rnh; + struct dinfo d; + struct rinfo *r; + int i, error; + + /* + * For now we'll handle only AF_INET + */ + rnh = rt_tables[AF_INET]; + if (!rnh) + return; + d.count = d.capacity = 0; + d.routes = NULL; + rtems_bsdnet_semaphore_obtain (); + error = rnh->rnh_walktree(rnh, show_inet_route, &d); + rtems_bsdnet_semaphore_release (); + if (error) { + printf ("Can't get route info: %s\n", strerror (error)); + return; + } + if (d.count == 0) { + printf ("No routes!\n"); + return; + } + printf ("Destination Gateway/Mask/Hw Flags Refs Use Expire Interface\n"); + for (i = 0, r = d.routes ; i < d.count ; i++, r++) { + char buf[30]; + char *cp, *fc, flagbuf[10]; + const char *addr; + unsigned long flagbit; + struct sockaddr_in *sin; + + sin = (struct sockaddr_in *)&r->dst; + if (sin->sin_addr.s_addr == INADDR_ANY) + addr = "default"; + else + addr = inet_ntop (AF_INET, &sin->sin_addr, buf, sizeof buf); + printf ("%-16s", addr); + switch (r->un.sa.sa_family) { + case AF_INET: + addr = inet_ntop (AF_INET, &r->un.sin.sin_addr, buf, sizeof buf); + break; + + case AF_LINK: + addr = link_ascii (&r->un.sdl, buf, sizeof buf); + break; + + default: + addr = ""; + break; + } + printf ("%-19s", addr); + fc = "UGHRDM XLS"; + for (flagbit = 0x1, cp = flagbuf ; *fc ; flagbit <<= 1, fc++) { + if ((r->flags & flagbit) && (*fc != ' ')) + *cp++ = *fc; + } + *cp = '\0'; + printf ("%-10s%3d%9ld%7ld %.*s%d\n", flagbuf, + r->refcnt, r->pksent, + r->expire, + (int)sizeof r->ifname, r->ifname, + r->ifunit); + } + free (d.routes); +} |