Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/netstat/route.c
Show First 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <stdbool.h> | #include <stdbool.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <sysexits.h> | #include <sysexits.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <libxo/xo.h> | #include <libxo/xo.h> | ||||
#include "netstat.h" | #include "netstat.h" | ||||
#include "common.h" | |||||
#include "nl_defs.h" | #include "nl_defs.h" | ||||
/* | /* | ||||
* Definitions for showing gateway flags. | * Definitions for showing gateway flags. | ||||
*/ | */ | ||||
static struct bits { | struct bits rt_bits[] = { | ||||
u_long b_mask; | |||||
char b_val; | |||||
const char *b_name; | |||||
} bits[] = { | |||||
{ RTF_UP, 'U', "up" }, | { RTF_UP, 'U', "up" }, | ||||
{ RTF_GATEWAY, 'G', "gateway" }, | { RTF_GATEWAY, 'G', "gateway" }, | ||||
{ RTF_HOST, 'H', "host" }, | { RTF_HOST, 'H', "host" }, | ||||
{ RTF_REJECT, 'R', "reject" }, | { RTF_REJECT, 'R', "reject" }, | ||||
{ RTF_DYNAMIC, 'D', "dynamic" }, | { RTF_DYNAMIC, 'D', "dynamic" }, | ||||
{ RTF_MODIFIED, 'M', "modified" }, | { RTF_MODIFIED, 'M', "modified" }, | ||||
{ RTF_DONE, 'd', "done" }, /* Completed -- for routing msgs only */ | { RTF_DONE, 'd', "done" }, /* Completed -- for routing msgs only */ | ||||
{ RTF_XRESOLVE, 'X', "xresolve" }, | { RTF_XRESOLVE, 'X', "xresolve" }, | ||||
{ RTF_STATIC, 'S', "static" }, | { RTF_STATIC, 'S', "static" }, | ||||
{ RTF_PROTO1, '1', "proto1" }, | { RTF_PROTO1, '1', "proto1" }, | ||||
{ RTF_PROTO2, '2', "proto2" }, | { RTF_PROTO2, '2', "proto2" }, | ||||
{ RTF_PROTO3, '3', "proto3" }, | { RTF_PROTO3, '3', "proto3" }, | ||||
{ RTF_BLACKHOLE,'B', "blackhole" }, | { RTF_BLACKHOLE,'B', "blackhole" }, | ||||
{ RTF_BROADCAST,'b', "broadcast" }, | { RTF_BROADCAST,'b', "broadcast" }, | ||||
#ifdef RTF_LLINFO | #ifdef RTF_LLINFO | ||||
{ RTF_LLINFO, 'L', "llinfo" }, | { RTF_LLINFO, 'L', "llinfo" }, | ||||
#endif | #endif | ||||
{ 0 , 0, NULL } | { 0 , 0, NULL } | ||||
}; | }; | ||||
struct ifmap_entry { | |||||
char ifname[IFNAMSIZ]; | |||||
}; | |||||
static struct ifmap_entry *ifmap; | static struct ifmap_entry *ifmap; | ||||
static int ifmap_size; | static size_t ifmap_size; | ||||
static struct timespec uptime; | static struct timespec uptime; | ||||
static const char *netname4(in_addr_t, in_addr_t); | static const char *netname4(in_addr_t, in_addr_t); | ||||
#ifdef INET6 | #ifdef INET6 | ||||
static const char *netname6(struct sockaddr_in6 *, struct sockaddr_in6 *); | static const char *netname6(struct sockaddr_in6 *, struct sockaddr_in6 *); | ||||
#endif | #endif | ||||
static void p_rtable_sysctl(int, int); | static void p_rtable_sysctl(int, int); | ||||
static void p_rtentry_sysctl(const char *name, struct rt_msghdr *); | static void p_rtentry_sysctl(const char *name, struct rt_msghdr *); | ||||
static int p_sockaddr(const char *name, struct sockaddr *, struct sockaddr *, | |||||
int, int); | |||||
static const char *fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, | |||||
int flags); | |||||
static void p_flags(int, const char *); | static void p_flags(int, const char *); | ||||
static const char *fmt_flags(int f); | |||||
static void domask(char *, size_t, u_long); | static void domask(char *, size_t, u_long); | ||||
/* | /* | ||||
* Print routing tables. | * Print routing tables. | ||||
*/ | */ | ||||
void | void | ||||
routepr(int fibnum, int af) | routepr(int fibnum, int af) | ||||
▲ Show 20 Lines • Show All 95 Lines • ▼ Show 20 Lines | |||||
{ | { | ||||
if (Wflag) { | if (Wflag) { | ||||
xo_emit("{T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%*.*s} " | xo_emit("{T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%*.*s} " | ||||
"{T:/%*.*s} {T:/%*.*s} {T:/%*s}\n", | "{T:/%*.*s} {T:/%*.*s} {T:/%*s}\n", | ||||
wid_dst, wid_dst, "Destination", | wid_dst, wid_dst, "Destination", | ||||
wid_gw, wid_gw, "Gateway", | wid_gw, wid_gw, "Gateway", | ||||
wid_flags, wid_flags, "Flags", | wid_flags, wid_flags, "Flags", | ||||
wid_pksent, wid_pksent, "Use", | wid_mtu, wid_mtu, "Nhop#", | ||||
wid_mtu, wid_mtu, "Mtu", | wid_mtu, wid_mtu, "Mtu", | ||||
wid_if, wid_if, "Netif", | wid_if, wid_if, "Netif", | ||||
wid_expire, "Expire"); | wid_expire, "Expire"); | ||||
} else { | } else { | ||||
xo_emit("{T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%*.*s} " | xo_emit("{T:/%-*.*s} {T:/%-*.*s} {T:/%-*.*s} {T:/%*.*s} " | ||||
"{T:/%*s}\n", | "{T:/%*s}\n", | ||||
wid_dst, wid_dst, "Destination", | wid_dst, wid_dst, "Destination", | ||||
wid_gw, wid_gw, "Gateway", | wid_gw, wid_gw, "Gateway", | ||||
wid_flags, wid_flags, "Flags", | wid_flags, wid_flags, "Flags", | ||||
wid_if, wid_if, "Netif", | wid_if, wid_if, "Netif", | ||||
wid_expire, "Expire"); | wid_expire, "Expire"); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
p_rtable_sysctl(int fibnum, int af) | p_rtable_sysctl(int fibnum, int af) | ||||
{ | { | ||||
size_t needed; | size_t needed; | ||||
int mib[7]; | int mib[7]; | ||||
char *buf, *next, *lim; | char *buf, *next, *lim; | ||||
struct rt_msghdr *rtm; | struct rt_msghdr *rtm; | ||||
struct sockaddr *sa; | struct sockaddr *sa; | ||||
int fam = AF_UNSPEC, ifindex = 0, size; | int fam = AF_UNSPEC; | ||||
int need_table_close = false; | int need_table_close = false; | ||||
struct ifaddrs *ifap, *ifa; | ifmap = prepare_ifmap(&ifmap_size); | ||||
struct sockaddr_dl *sdl; | |||||
/* | |||||
* Retrieve interface list at first | |||||
* since we need #ifindex -> if_xname match | |||||
*/ | |||||
if (getifaddrs(&ifap) != 0) | |||||
err(EX_OSERR, "getifaddrs"); | |||||
for (ifa = ifap; ifa; ifa = ifa->ifa_next) { | |||||
if (ifa->ifa_addr->sa_family != AF_LINK) | |||||
continue; | |||||
sdl = (struct sockaddr_dl *)ifa->ifa_addr; | |||||
ifindex = sdl->sdl_index; | |||||
if (ifindex >= ifmap_size) { | |||||
size = roundup(ifindex + 1, 32) * | |||||
sizeof(struct ifmap_entry); | |||||
if ((ifmap = realloc(ifmap, size)) == NULL) | |||||
errx(2, "realloc(%d) failed", size); | |||||
memset(&ifmap[ifmap_size], 0, | |||||
size - ifmap_size * | |||||
sizeof(struct ifmap_entry)); | |||||
ifmap_size = roundup(ifindex + 1, 32); | |||||
} | |||||
if (*ifmap[ifindex].ifname != '\0') | |||||
continue; | |||||
strlcpy(ifmap[ifindex].ifname, ifa->ifa_name, IFNAMSIZ); | |||||
} | |||||
freeifaddrs(ifap); | |||||
mib[0] = CTL_NET; | mib[0] = CTL_NET; | ||||
mib[1] = PF_ROUTE; | mib[1] = PF_ROUTE; | ||||
mib[2] = 0; | mib[2] = 0; | ||||
mib[3] = af; | mib[3] = af; | ||||
mib[4] = NET_RT_DUMP; | mib[4] = NET_RT_DUMP; | ||||
mib[5] = 0; | mib[5] = 0; | ||||
mib[6] = fibnum; | mib[6] = fibnum; | ||||
if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) | if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | protrusion = p_sockaddr("destination", addr[RTAX_DST], | ||||
addr[RTAX_NETMASK], | addr[RTAX_NETMASK], | ||||
rtm->rtm_flags, wid_dst); | rtm->rtm_flags, wid_dst); | ||||
protrusion = p_sockaddr("gateway", addr[RTAX_GATEWAY], NULL, RTF_HOST, | protrusion = p_sockaddr("gateway", addr[RTAX_GATEWAY], NULL, RTF_HOST, | ||||
wid_gw - protrusion); | wid_gw - protrusion); | ||||
snprintf(buffer, sizeof(buffer), "{[:-%d}{:flags/%%s}{]:} ", | snprintf(buffer, sizeof(buffer), "{[:-%d}{:flags/%%s}{]:} ", | ||||
wid_flags - protrusion); | wid_flags - protrusion); | ||||
p_flags(rtm->rtm_flags, buffer); | p_flags(rtm->rtm_flags, buffer); | ||||
if (Wflag) { | if (Wflag) { | ||||
xo_emit("{t:use/%*lu} ", wid_pksent, rtm->rtm_rmx.rmx_pksent); | /* XXX: use=0? */ | ||||
xo_emit("{t:nhop/%*lu} ", wid_mtu, rtm->rtm_rmx.rmx_nhidx); | |||||
if (rtm->rtm_rmx.rmx_mtu != 0) | if (rtm->rtm_rmx.rmx_mtu != 0) | ||||
xo_emit("{t:mtu/%*lu} ", wid_mtu, rtm->rtm_rmx.rmx_mtu); | xo_emit("{t:mtu/%*lu} ", wid_mtu, rtm->rtm_rmx.rmx_mtu); | ||||
else | else | ||||
xo_emit("{P:/%*s} ", wid_mtu, ""); | xo_emit("{P:/%*s} ", wid_mtu, ""); | ||||
} | } | ||||
memset(prettyname, 0, sizeof(prettyname)); | memset(prettyname, 0, sizeof(prettyname)); | ||||
Show All 16 Lines | if ((expire_time = rtm->rtm_rmx.rmx_expire - uptime.tv_sec) > 0) | ||||
xo_emit(" {:expire-time/%*d}", wid_expire, | xo_emit(" {:expire-time/%*d}", wid_expire, | ||||
(int)expire_time); | (int)expire_time); | ||||
} | } | ||||
xo_emit("\n"); | xo_emit("\n"); | ||||
xo_close_instance(name); | xo_close_instance(name); | ||||
} | } | ||||
static int | int | ||||
p_sockaddr(const char *name, struct sockaddr *sa, struct sockaddr *mask, | p_sockaddr(const char *name, struct sockaddr *sa, struct sockaddr *mask, | ||||
int flags, int width) | int flags, int width) | ||||
{ | { | ||||
const char *cp; | const char *cp; | ||||
char buf[128]; | char buf[128]; | ||||
int protrusion; | int protrusion; | ||||
cp = fmt_sockaddr(sa, mask, flags); | cp = fmt_sockaddr(sa, mask, flags); | ||||
Show All 15 Lines | if (Wflag != 0 || numeric_addr) { | ||||
-width, name); | -width, name); | ||||
xo_emit(buf, width, cp); | xo_emit(buf, width, cp); | ||||
protrusion = 0; | protrusion = 0; | ||||
} | } | ||||
} | } | ||||
return (protrusion); | return (protrusion); | ||||
} | } | ||||
static const char * | const char * | ||||
fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags) | fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags) | ||||
{ | { | ||||
static char buf[128]; | static char buf[128]; | ||||
const char *cp; | const char *cp; | ||||
if (sa == NULL) | if (sa == NULL) | ||||
return ("null"); | return ("null"); | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | #endif | ||||
} | } | ||||
return (cp); | return (cp); | ||||
} | } | ||||
static void | static void | ||||
p_flags(int f, const char *format) | p_flags(int f, const char *format) | ||||
{ | { | ||||
struct bits *p; | |||||
xo_emit(format, fmt_flags(f)); | print_flags_generic(f, rt_bits, format, "flags_pretty"); | ||||
xo_open_list("flags_pretty"); | |||||
for (p = bits; p->b_mask; p++) | |||||
if (p->b_mask & f) | |||||
xo_emit("{le:flags_pretty/%s}", p->b_name); | |||||
xo_close_list("flags_pretty"); | |||||
} | } | ||||
static const char * | |||||
fmt_flags(int f) | |||||
{ | |||||
static char name[33]; | |||||
char *flags; | |||||
struct bits *p = bits; | |||||
for (flags = name; p->b_mask; p++) | |||||
if (p->b_mask & f) | |||||
*flags++ = p->b_val; | |||||
*flags = '\0'; | |||||
return (name); | |||||
} | |||||
char * | char * | ||||
routename(struct sockaddr *sa, int flags) | routename(struct sockaddr *sa, int flags) | ||||
{ | { | ||||
static char line[NI_MAXHOST]; | static char line[NI_MAXHOST]; | ||||
int error, f; | int error, f; | ||||
f = (flags) ? NI_NUMERICHOST : 0; | f = (flags) ? NI_NUMERICHOST : 0; | ||||
▲ Show 20 Lines • Show All 249 Lines • Show Last 20 Lines |