Like it was already done for 'netstat -i', drop the kvm(3) support

in 'netstat -r'.

The netstat/route.c was the last abuser of struct ifnet and struct
rtentry in the tree. With this change if_var.h can become kernel
only include, _WANT_RTENTRY can go away and projects/ifnet and
projects/routing can go forward.

Differential Revision:	https://reviews.freebsd.org/D2242
Reviewed by:		melifaro, gnn
Sponsored by:		Nginx, Inc.
Sponsored by:		Netflix
This commit is contained in:
Gleb Smirnoff 2015-04-07 05:50:45 +00:00
parent 34d8b7ea3b
commit 6fe1796015
2 changed files with 14 additions and 394 deletions

View File

@ -78,11 +78,9 @@
.Op Fl I Ar interface
.It Nm Fl r
.Op Fl -libxo
.Op Fl 46AnW
.Op Fl 46nW
.Op Fl F Ar fibnum
.Op Fl f Ar address_family
.Op Fl M Ar core
.Op Fl N Ar system
.It Nm Fl rs
.Op Fl -libxo
.Op Fl s
@ -581,9 +579,6 @@ See
Show IPv6 only.
See
.Sx GENERAL OPTIONS .
.It Fl A
Show the contents of the internal Patricia tree
structures; used for debugging.
.It Fl n
Do not resolve numeric addresses and port numbers to names.
See

View File

@ -40,22 +40,18 @@ __FBSDID("$FreeBSD$");
#include <sys/protosw.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/time.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <net/if_var.h>
#include <net/if_dl.h>
#include <net/if_types.h>
#include <net/radix.h>
#define _WANT_RTENTRY
#include <net/route.h>
#include <netinet/in.h>
#include <netgraph/ng_socket.h>
#include <sys/sysctl.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <libutil.h>
@ -72,8 +68,6 @@ __FBSDID("$FreeBSD$");
#include <libxo/xo.h>
#include "netstat.h"
#define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d)))
/*
* Definitions for showing gateway flags.
*/
@ -108,9 +102,7 @@ struct bits {
static struct nlist rl[] = {
#define N_RTSTAT 0
{ .n_name = "_rtstat" },
#define N_RTREE 1
{ .n_name = "_rt_tables"},
#define N_RTTRASH 2
#define N_RTTRASH 1
{ .n_name = "_rttrash" },
{ .n_name = NULL },
};
@ -121,33 +113,14 @@ typedef union {
u_short u_data[128];
} sa_u;
static sa_u pt_u;
struct ifmap_entry {
char ifname[IFNAMSIZ];
};
static struct ifmap_entry *ifmap;
static int ifmap_size;
int do_rtent = 0;
struct rtentry rtentry;
struct radix_node rnode;
struct radix_mask rmask;
int NewTree = 1;
struct timespec uptime;
static struct sockaddr *kgetsa(struct sockaddr *);
static void size_cols(int ef, struct radix_node *rn);
static void size_cols_tree(struct radix_node *rn);
static void size_cols_rtentry(struct rtentry *rt);
static void p_rtnode_kvm(void);
static void p_rtable_sysctl(int, int);
static void p_rtable_kvm(int, int );
static void p_rtree_kvm(const char *name, struct radix_node *);
static void p_rtentry_kvm(const char *name, struct rtentry *);
static void p_rtentry_sysctl(const char *name, struct rt_msghdr *);
static void p_sockaddr(const char *name, struct sockaddr *, struct sockaddr *,
int, int);
@ -166,6 +139,9 @@ routepr(int fibnum, int af)
size_t intsize;
int numfibs;
if (live == 0)
return;
intsize = sizeof(int);
if (fibnum == -1 &&
sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1)
@ -187,11 +163,7 @@ routepr(int fibnum, int af)
if (fibnum)
xo_emit(" ({L:fib}: {:fib/%d})", fibnum);
xo_emit("\n");
if (Aflag == 0 && live != 0 && NewTree)
p_rtable_sysctl(fibnum, af);
else
p_rtable_kvm(fibnum, af);
p_rtable_sysctl(fibnum, af);
xo_close_container("route-information");
}
@ -253,100 +225,6 @@ static int wid_mtu;
static int wid_if;
static int wid_expire;
static void
size_cols(int ef, struct radix_node *rn)
{
wid_dst = WID_DST_DEFAULT(ef);
wid_gw = WID_GW_DEFAULT(ef);
wid_flags = 6;
wid_pksent = 8;
wid_mtu = 6;
wid_if = WID_IF_DEFAULT(ef);
wid_expire = 6;
if (Wflag && rn != NULL)
size_cols_tree(rn);
}
static void
size_cols_tree(struct radix_node *rn)
{
again:
if (kget(rn, rnode) != 0)
return;
if (!(rnode.rn_flags & RNF_ACTIVE))
return;
if (rnode.rn_bit < 0) {
if ((rnode.rn_flags & RNF_ROOT) == 0) {
if (kget(rn, rtentry) != 0)
return;
size_cols_rtentry(&rtentry);
}
if ((rn = rnode.rn_dupedkey))
goto again;
} else {
rn = rnode.rn_right;
size_cols_tree(rnode.rn_left);
size_cols_tree(rn);
}
}
static void
size_cols_rtentry(struct rtentry *rt)
{
static struct ifnet ifnet, *lastif;
static char buffer[100];
const char *bp;
struct sockaddr *sa;
sa_u addr, mask;
int len;
bzero(&addr, sizeof(addr));
if ((sa = kgetsa(rt_key(rt))))
bcopy(sa, &addr, sa->sa_len);
bzero(&mask, sizeof(mask));
if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt))))
bcopy(sa, &mask, sa->sa_len);
bp = fmt_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags);
len = strlen(bp);
wid_dst = MAX(len, wid_dst);
bp = fmt_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST);
len = strlen(bp);
wid_gw = MAX(len, wid_gw);
bp = fmt_flags(rt->rt_flags);
len = strlen(bp);
wid_flags = MAX(len, wid_flags);
if (Wflag) {
len = snprintf(buffer, sizeof(buffer), "%ju",
(uintmax_t )kread_counter((u_long )rt->rt_pksent));
wid_pksent = MAX(len, wid_pksent);
}
if (rt->rt_ifp) {
if (rt->rt_ifp != lastif) {
if (kget(rt->rt_ifp, ifnet) == 0)
len = strlen(ifnet.if_xname);
else
len = strlen("---");
lastif = rt->rt_ifp;
wid_if = MAX(len, wid_if);
}
if (rt->rt_expire) {
time_t expire_time;
if ((expire_time =
rt->rt_expire - uptime.tv_sec) > 0) {
len = snprintf(buffer, sizeof(buffer), "%d",
(int)expire_time);
wid_expire = MAX(len, wid_expire);
}
}
}
}
/*
* Print header for routing table columns.
*/
@ -377,210 +255,6 @@ pr_rthdr(int af1)
}
}
static struct sockaddr *
kgetsa(struct sockaddr *dst)
{
if (kget(dst, pt_u.u_sa) != 0)
return (NULL);
if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa))
kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len);
return (&pt_u.u_sa);
}
/*
* Print kernel routing tables for given fib
* using debugging kvm(3) interface.
*/
static void
p_rtable_kvm(int fibnum, int af)
{
struct radix_node_head **rnhp, *rnh, head;
struct radix_node_head **rt_tables;
u_long rtree;
int fam, af_size;
bool did_rt_family = false;
kresolve_list(rl);
if ((rtree = rl[N_RTREE].n_value) == 0) {
xo_emit("rt_tables: symbol not in namelist\n");
return;
}
af_size = (AF_MAX + 1) * sizeof(struct radix_node_head *);
rt_tables = calloc(1, af_size);
if (rt_tables == NULL)
err(EX_OSERR, "memory allocation failed");
if (kread((u_long)(rtree), (char *)(rt_tables) + fibnum * af_size,
af_size) != 0)
err(EX_OSERR, "error retrieving radix pointers");
xo_open_container("route-table");
for (fam = 0; fam <= AF_MAX; fam++) {
int tmpfib;
switch (fam) {
case AF_INET6:
case AF_INET:
tmpfib = fibnum;
break;
default:
tmpfib = 0;
}
rnhp = (struct radix_node_head **)*rt_tables;
/* Calculate the in-kernel address. */
rnhp += tmpfib * (AF_MAX + 1) + fam;
/* Read the in kernel rhn pointer. */
if (kget(rnhp, rnh) != 0)
continue;
if (rnh == NULL)
continue;
/* Read the rnh data. */
if (kget(rnh, head) != 0)
continue;
if (fam == AF_UNSPEC) {
if (Aflag && af == 0) {
xo_emit("{T:Netmasks}:\n");
xo_open_list("netmasks");
p_rtree_kvm("netmasks", head.rnh_treetop);
xo_close_list("netmasks");
}
} else if (af == AF_UNSPEC || af == fam) {
if (!did_rt_family) {
xo_open_list("rt-family");
did_rt_family = true;
}
size_cols(fam, head.rnh_treetop);
xo_open_instance("rt-family");
pr_family(fam);
do_rtent = 1;
xo_open_list("rt-entry");
pr_rthdr(fam);
p_rtree_kvm("rt-entry", head.rnh_treetop);
xo_close_list("rt-entry");
xo_close_instance("rt-family");
}
}
if (did_rt_family)
xo_close_list("rt-family");
xo_close_container("route-table");
free(rt_tables);
}
/*
* Print given kernel radix tree using
* debugging kvm(3) interface.
*/
static void
p_rtree_kvm(const char *name, struct radix_node *rn)
{
bool opened;
opened = false;
#define DOOPEN() do { \
if (!opened) { xo_open_instance(name); opened = true; } \
} while (0)
#define DOCLOSE() do { \
if (opened) { opened = false; xo_close_instance(name); } \
} while(0)
again:
if (kget(rn, rnode) != 0)
return;
if (!(rnode.rn_flags & RNF_ACTIVE))
return;
if (rnode.rn_bit < 0) {
if (Aflag) {
DOOPEN();
xo_emit("{q:radix-node/%-8.8lx} ", (u_long)rn);
}
if (rnode.rn_flags & RNF_ROOT) {
if (Aflag) {
DOOPEN();
xo_emit("({:root/root} node){L:/%s}",
rnode.rn_dupedkey ? " =>\n" : "\n");
}
} else if (do_rtent) {
if (kget(rn, rtentry) == 0) {
DOOPEN();
p_rtentry_kvm(name, &rtentry);
if (Aflag) {
DOOPEN();
p_rtnode_kvm();
DOCLOSE();
}
}
} else {
DOOPEN();
p_sockaddr("address",
kgetsa((struct sockaddr *)rnode.rn_key),
NULL, 0, 44);
xo_emit("\n");
}
DOCLOSE();
if ((rn = rnode.rn_dupedkey))
goto again;
} else {
if (Aflag && do_rtent) {
DOOPEN();
xo_emit("{q:radix-node/%-8.8lx} ", (u_long)rn);
p_rtnode_kvm();
DOCLOSE();
}
rn = rnode.rn_right;
p_rtree_kvm(name, rnode.rn_left);
p_rtree_kvm(name, rn);
}
}
char nbuf[20];
static void
p_rtnode_kvm(void)
{
struct radix_mask *rm = rnode.rn_mklist;
if (rnode.rn_bit < 0) {
if (rnode.rn_mask) {
xo_emit("\t {L:mask} ");
p_sockaddr("netmask",
kgetsa((struct sockaddr *)rnode.rn_mask),
NULL, 0, -1);
} else if (rm == 0)
return;
} else {
xo_emit("{[:6}{:bit/(%d)}{]:} {q:left-node/%8.8lx} "
": {q:right-node/%8.8lx}", rnode.rn_bit,
(u_long)rnode.rn_left, (u_long)rnode.rn_right);
}
while (rm) {
if (kget(rm, rmask) != 0)
break;
sprintf(nbuf, " %d refs, ", rmask.rm_refs);
xo_emit(" mk = {q:node/%8.8lx} \\{({:bit/%d}),{nbufs/%s}",
(u_long)rm, -1 - rmask.rm_bit, rmask.rm_refs ? nbuf : " ");
if (rmask.rm_flags & RNF_NORMAL) {
struct radix_node rnode_aux;
xo_emit(" <{:mode/normal}>, ");
if (kget(rmask.rm_leaf, rnode_aux) == 0)
p_sockaddr("netmask",
kgetsa(/*XXX*/(void *)rnode_aux.rn_mask),
NULL, 0, -1);
else
p_sockaddr(NULL, NULL, NULL, 0, -1);
} else
p_sockaddr("netmask",
kgetsa((struct sockaddr *)rmask.rm_mask),
NULL, 0, -1);
xo_emit("\\}");
if ((rm = rmask.rm_mklist))
xo_emit(" {D:->}");
}
xo_emit("\n");
}
static void
p_rtable_sysctl(int fibnum, int af)
{
@ -664,7 +338,13 @@ p_rtable_sysctl(int fibnum, int af)
need_table_close = true;
fam = sa->sa_family;
size_cols(fam, NULL);
wid_dst = WID_DST_DEFAULT(fam);
wid_gw = WID_GW_DEFAULT(fam);
wid_flags = 6;
wid_pksent = 8;
wid_mtu = 6;
wid_if = WID_IF_DEFAULT(fam);
wid_expire = 6;
xo_open_instance("rt-family");
pr_family(fam);
xo_open_list("rt-entry");
@ -905,61 +585,6 @@ fmt_flags(int f)
return (name);
}
static void
p_rtentry_kvm(const char *name, struct rtentry *rt)
{
static struct ifnet ifnet, *lastif;
static char buffer[128];
static char prettyname[128];
struct sockaddr *sa;
sa_u addr, mask;
bzero(&addr, sizeof(addr));
if ((sa = kgetsa(rt_key(rt))))
bcopy(sa, &addr, sa->sa_len);
bzero(&mask, sizeof(mask));
if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt))))
bcopy(sa, &mask, sa->sa_len);
p_sockaddr("destination", &addr.u_sa, &mask.u_sa, rt->rt_flags,
wid_dst);
p_sockaddr("gateway", kgetsa(rt->rt_gateway), NULL, RTF_HOST, wid_gw);
snprintf(buffer, sizeof(buffer), "{[:-%d}{:flags/%%s}{]:}",
wid_flags);
p_flags(rt->rt_flags, buffer);
if (Wflag) {
xo_emit("{[:%d}{t:use/%ju}{]:} ", -wid_pksent,
(uintmax_t )kread_counter((u_long )rt->rt_pksent));
if (rt->rt_mtu != 0)
xo_emit("{t:mtu/%*lu} ", wid_mtu, rt->rt_mtu);
else
xo_emit("{P:/%*s} ", wid_mtu, "");
}
if (rt->rt_ifp) {
if (rt->rt_ifp != lastif) {
if (kget(rt->rt_ifp, ifnet) == 0)
strlcpy(prettyname, ifnet.if_xname,
sizeof(prettyname));
else
strlcpy(prettyname, "---", sizeof(prettyname));
lastif = rt->rt_ifp;
}
xo_emit("{t:interface-name/%*.*s}", wid_if, wid_if, prettyname);
if (rt->rt_expire) {
time_t expire_time;
if ((expire_time =
rt->rt_expire - uptime.tv_sec) > 0)
xo_emit(" {:expire-time/%*d}",
wid_expire, (int)expire_time);
}
if (rt->rt_nodes[0].rn_dupedkey)
xo_emit(" =>");
}
xo_emit("\n");
}
char *
routename(in_addr_t in)
{