Merge r259562,r259566,r259638,r259645,r260124 by melifaro:
Switch netstat -rn to use standard API for retrieving list of routes instead of peeking inside in-kernel radix via kget.
This commit is contained in:
parent
73a339242d
commit
78bde64905
@ -224,7 +224,7 @@ next_ifma(struct ifmaddrs *ifma, const char *name, const sa_family_t family)
|
||||
* Print a description of the network interfaces.
|
||||
*/
|
||||
void
|
||||
intpr(int interval, void (*pfunc)(char *))
|
||||
intpr(int interval, void (*pfunc)(char *), int af)
|
||||
{
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
struct ifmaddrs *ifmap, *ifma;
|
||||
|
@ -552,41 +552,41 @@ main(int argc, char *argv[])
|
||||
* used for the queries, which is slower.
|
||||
*/
|
||||
#endif
|
||||
kread(0, NULL, 0);
|
||||
if (iflag && !sflag) {
|
||||
intpr(interval, NULL);
|
||||
intpr(interval, NULL, af);
|
||||
exit(0);
|
||||
}
|
||||
if (rflag) {
|
||||
if (sflag) {
|
||||
rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
|
||||
rt_stats();
|
||||
flowtable_stats();
|
||||
} else
|
||||
routepr(nl[N_RTREE].n_value, fib);
|
||||
routepr(fib, af);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (gflag) {
|
||||
if (sflag) {
|
||||
if (af == AF_INET || af == AF_UNSPEC)
|
||||
mrt_stats(nl[N_MRTSTAT].n_value);
|
||||
mrt_stats();
|
||||
#ifdef INET6
|
||||
if (af == AF_INET6 || af == AF_UNSPEC)
|
||||
mrt6_stats(nl[N_MRT6STAT].n_value);
|
||||
mrt6_stats();
|
||||
#endif
|
||||
} else {
|
||||
if (af == AF_INET || af == AF_UNSPEC)
|
||||
mroutepr(nl[N_MFCHASHTBL].n_value,
|
||||
nl[N_MFCTABLESIZE].n_value,
|
||||
nl[N_VIFTABLE].n_value);
|
||||
mroutepr();
|
||||
#ifdef INET6
|
||||
if (af == AF_INET6 || af == AF_UNSPEC)
|
||||
mroute6pr(nl[N_MF6CTABLE].n_value,
|
||||
nl[N_MIF6TABLE].n_value);
|
||||
mroute6pr();
|
||||
#endif
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* Load all necessary kvm symbols */
|
||||
kresolve_list(nl);
|
||||
|
||||
if (tp) {
|
||||
printproto(tp, tp->pr_name);
|
||||
exit(0);
|
||||
@ -639,7 +639,7 @@ printproto(struct protox *tp, const char *name)
|
||||
if (sflag) {
|
||||
if (iflag) {
|
||||
if (tp->pr_istats)
|
||||
intpr(interval, tp->pr_istats);
|
||||
intpr(interval, tp->pr_istats, af);
|
||||
else if (pflag)
|
||||
printf("%s: no per-interface stats routine\n",
|
||||
tp->pr_name);
|
||||
@ -702,7 +702,23 @@ kvmd_init(void)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (kvm_nlist(kvmd, nl) < 0) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Resolve symbol list, return 0 on success.
|
||||
*/
|
||||
int
|
||||
kresolve_list(struct nlist *_nl)
|
||||
{
|
||||
|
||||
if ((kvmd == NULL) && (kvmd_init() != 0))
|
||||
return (-1);
|
||||
|
||||
if (_nl[0].n_type != 0)
|
||||
return (0);
|
||||
|
||||
if (kvm_nlist(kvmd, _nl) < 0) {
|
||||
if (nlistf)
|
||||
errx(1, "%s: kvm_nlist: %s", nlistf,
|
||||
kvm_geterr(kvmd));
|
||||
@ -710,13 +726,6 @@ kvmd_init(void)
|
||||
errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
|
||||
}
|
||||
|
||||
if (nl[0].n_type == 0) {
|
||||
if (nlistf)
|
||||
errx(1, "%s: no namelist", nlistf);
|
||||
else
|
||||
errx(1, "no namelist");
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
@ -65,11 +65,26 @@ __FBSDID("$FreeBSD$");
|
||||
#undef _KERNEL
|
||||
|
||||
#include <err.h>
|
||||
#include <nlist.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "netstat.h"
|
||||
|
||||
/*
|
||||
* kvm(3) bindings for every needed symbol
|
||||
*/
|
||||
static struct nlist mrl[] = {
|
||||
#define N_MRTSTAT 0
|
||||
{ .n_name = "_mrtstat" },
|
||||
#define N_MFCHASHTBL 1
|
||||
{ .n_name = "_mfchashtbl" },
|
||||
#define N_VIFTABLE 2
|
||||
{ .n_name = "_viftable" },
|
||||
#define N_MFCTABLESIZE 3
|
||||
{ .n_name = "_mfctablesize" },
|
||||
{ .n_name = NULL },
|
||||
};
|
||||
|
||||
static void print_bw_meter(struct bw_meter *, int *);
|
||||
static void print_mfc(struct mfc *, int, int *);
|
||||
@ -193,11 +208,12 @@ print_mfc(struct mfc *m, int maxvif, int *banner_printed)
|
||||
}
|
||||
|
||||
void
|
||||
mroutepr(u_long pmfchashtbl, u_long pmfctablesize, u_long pviftbl)
|
||||
mroutepr()
|
||||
{
|
||||
struct vif viftable[MAXVIFS];
|
||||
struct vif *v;
|
||||
struct mfc *m;
|
||||
u_long pmfchashtbl, pmfctablesize, pviftbl;
|
||||
int banner_printed;
|
||||
int saved_numeric_addr;
|
||||
size_t len;
|
||||
@ -221,6 +237,16 @@ mroutepr(u_long pmfchashtbl, u_long pmfctablesize, u_long pviftbl)
|
||||
*/
|
||||
maxvif = 0;
|
||||
|
||||
kresolve_list(mrl);
|
||||
pmfchashtbl = mrl[N_MFCHASHTBL].n_value;
|
||||
pmfctablesize = mrl[N_MFCTABLESIZE].n_value;
|
||||
pviftbl = mrl[N_VIFTABLE].n_value;
|
||||
|
||||
if (pmfchashtbl == 0 || pmfctablesize == 0 || pviftbl == 0) {
|
||||
fprintf(stderr, "No IPv4 MROUTING kernel support.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
len = sizeof(viftable);
|
||||
if (live) {
|
||||
if (sysctlbyname("net.inet.ip.viftable", viftable, &len, NULL,
|
||||
@ -338,15 +364,24 @@ mroutepr(u_long pmfchashtbl, u_long pmfctablesize, u_long pviftbl)
|
||||
}
|
||||
|
||||
void
|
||||
mrt_stats(u_long mstaddr)
|
||||
mrt_stats()
|
||||
{
|
||||
struct mrtstat mrtstat;
|
||||
size_t len = sizeof mrtstat;
|
||||
u_long mstaddr;
|
||||
size_t len = sizeof(mrtstat);
|
||||
|
||||
kresolve_list(mrl);
|
||||
mstaddr = mrl[N_MRTSTAT].n_value;
|
||||
|
||||
if (mstaddr == 0) {
|
||||
fprintf(stderr, "No IPv4 MROUTING kernel support.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (live) {
|
||||
if (sysctlbyname("net.inet.ip.mrtstat", &mrtstat, &len, NULL,
|
||||
0) < 0) {
|
||||
warn("sysctl: net.inet.ip.mrtstat");
|
||||
warn("sysctl: net.inet.ip.mrtstat failed.");
|
||||
return;
|
||||
}
|
||||
} else
|
||||
|
@ -85,6 +85,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <nlist.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -95,17 +96,32 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "netstat.h"
|
||||
|
||||
/*
|
||||
* kvm(3) bindings for every needed symbol
|
||||
*/
|
||||
static struct nlist mrl[] = {
|
||||
#define N_MF6CTABLE 0
|
||||
{ .n_name = "_mf6ctable" },
|
||||
#define N_MIF6TABLE 1
|
||||
{ .n_name = "_mif6table" },
|
||||
#define N_MRT6STAT 2
|
||||
{ .n_name = "_mrt6stat" },
|
||||
{ .n_name = NULL },
|
||||
};
|
||||
|
||||
|
||||
#define WID_ORG (Wflag ? 39 : (numeric_addr ? 29 : 18)) /* width of origin column */
|
||||
#define WID_GRP (Wflag ? 18 : (numeric_addr ? 16 : 18)) /* width of group column */
|
||||
|
||||
void
|
||||
mroute6pr(u_long mfcaddr, u_long mifaddr)
|
||||
mroute6pr()
|
||||
{
|
||||
struct mf6c *mf6ctable[MF6CTBLSIZ], *mfcp;
|
||||
struct mif6 mif6table[MAXMIFS];
|
||||
struct mf6c mfc;
|
||||
struct rtdetq rte, *rtep;
|
||||
struct mif6 *mifp;
|
||||
u_long mfcaddr, mifaddr;
|
||||
mifi_t mifi;
|
||||
int i;
|
||||
int banner_printed;
|
||||
@ -114,6 +130,15 @@ mroute6pr(u_long mfcaddr, u_long mifaddr)
|
||||
long int waitings;
|
||||
size_t len;
|
||||
|
||||
kresolve_list(mrl);
|
||||
mfcaddr = mrl[N_MF6CTABLE].n_value;
|
||||
mifaddr = mrl[N_MIF6TABLE].n_value;
|
||||
|
||||
if (mfcaddr == 0 || mifaddr == 0) {
|
||||
fprintf(stderr, "No IPv6 MROUTING kernel support.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
len = sizeof(mif6table);
|
||||
if (live) {
|
||||
if (sysctlbyname("net.inet6.ip6.mif6table", mif6table, &len,
|
||||
@ -217,11 +242,20 @@ mroute6pr(u_long mfcaddr, u_long mifaddr)
|
||||
}
|
||||
|
||||
void
|
||||
mrt6_stats(u_long mstaddr)
|
||||
mrt6_stats()
|
||||
{
|
||||
struct mrt6stat mrtstat;
|
||||
u_long mstaddr;
|
||||
size_t len = sizeof mrtstat;
|
||||
|
||||
kresolve_list(mrl);
|
||||
mstaddr = mrl[N_MRT6STAT].n_value;
|
||||
|
||||
if (mstaddr == 0) {
|
||||
fprintf(stderr, "No IPv6 MROUTING kernel support.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (live) {
|
||||
if (sysctlbyname("net.inet6.ip6.mrt6stat", &mrtstat, &len,
|
||||
NULL, 0) < 0) {
|
||||
|
@ -72,53 +72,10 @@ netgraphprotopr(u_long off, const char *name, int af1 __unused,
|
||||
|
||||
/* If symbol not found, try looking in the KLD module */
|
||||
if (off == 0) {
|
||||
const char *const modname = "ng_socket.ko";
|
||||
/* XXX We should get "mpath" from "sysctl kern.module_path" */
|
||||
const char *mpath[] = { "/", "/boot/", "/modules/", NULL };
|
||||
struct nlist sym[] = { { .n_name = "_ngsocklist" },
|
||||
{ .n_name = NULL } };
|
||||
const char **pre;
|
||||
struct kld_file_stat ks;
|
||||
int fileid;
|
||||
|
||||
/* Can't do this for core dumps. */
|
||||
if (!live)
|
||||
return;
|
||||
|
||||
/* See if module is loaded */
|
||||
if ((fileid = kldfind(modname)) < 0) {
|
||||
if (debug)
|
||||
warn("kldfind(%s)", modname);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get module info */
|
||||
memset(&ks, 0, sizeof(ks));
|
||||
ks.version = sizeof(struct kld_file_stat);
|
||||
if (kldstat(fileid, &ks) < 0) {
|
||||
if (debug)
|
||||
warn("kldstat(%d)", fileid);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get symbol table from module file */
|
||||
for (pre = mpath; *pre; pre++) {
|
||||
char path[MAXPATHLEN];
|
||||
|
||||
snprintf(path, sizeof(path), "%s%s", *pre, modname);
|
||||
if (nlist(path, sym) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Did we find it? */
|
||||
if (sym[0].n_value == 0) {
|
||||
if (debug)
|
||||
warnx("%s not found", modname);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Symbol found at load address plus symbol offset */
|
||||
off = (u_long) ks.address + sym[0].n_value;
|
||||
if (debug)
|
||||
fprintf(stderr,
|
||||
"Error reading symbols from ng_socket.ko");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Get pointer to first socket */
|
||||
|
@ -56,11 +56,12 @@ extern int interval; /* repeat interval for i/f stats */
|
||||
extern char *interface; /* desired i/f for stats, or NULL for all i/fs */
|
||||
extern int unit; /* unit number for above */
|
||||
|
||||
extern int af; /* address family */
|
||||
extern int live; /* true if we are examining a live system */
|
||||
|
||||
struct nlist;
|
||||
int kread(u_long addr, void *buf, size_t size);
|
||||
int kread_counters(u_long addr, void *buf, size_t size);
|
||||
int kresolve_list(struct nlist *);
|
||||
const char *plural(uintmax_t);
|
||||
const char *plurales(uintmax_t);
|
||||
const char *pluralies(uintmax_t);
|
||||
@ -97,8 +98,8 @@ void icmp6_stats(u_long, const char *, int, int);
|
||||
void icmp6_ifstats(char *);
|
||||
void pim6_stats(u_long, const char *, int, int);
|
||||
void rip6_stats(u_long, const char *, int, int);
|
||||
void mroute6pr(u_long, u_long);
|
||||
void mrt6_stats(u_long);
|
||||
void mroute6pr(void);
|
||||
void mrt6_stats(void);
|
||||
|
||||
struct sockaddr_in6;
|
||||
struct in6_addr;
|
||||
@ -119,11 +120,11 @@ void netisr_stats(void *);
|
||||
void hostpr(u_long, u_long);
|
||||
void impstats(u_long, u_long);
|
||||
|
||||
void intpr(int, void (*)(char *));
|
||||
void intpr(int, void (*)(char *), int);
|
||||
|
||||
void pr_rthdr(int);
|
||||
void pr_family(int);
|
||||
void rt_stats(u_long, u_long);
|
||||
void rt_stats(void);
|
||||
void flowtable_stats(void);
|
||||
char *ipx_pnet(struct sockaddr *);
|
||||
char *ipx_phost(struct sockaddr *);
|
||||
@ -136,7 +137,7 @@ char *atalk_print(struct sockaddr *, int);
|
||||
char *atalk_print2(struct sockaddr *, struct sockaddr *, int);
|
||||
char *ipx_print(struct sockaddr *);
|
||||
char *ns_print(struct sockaddr *);
|
||||
void routepr(u_long, int);
|
||||
void routepr(int, int);
|
||||
|
||||
void ipxprotopr(u_long, const char *, int, int);
|
||||
void spx_stats(u_long, const char *, int, int);
|
||||
@ -166,6 +167,6 @@ void tp_protopr(u_long, const char *, int, int);
|
||||
void tp_inproto(u_long);
|
||||
void tp_stats(caddr_t, caddr_t);
|
||||
|
||||
void mroutepr(u_long, u_long, u_long);
|
||||
void mrt_stats(u_long);
|
||||
void mroutepr(void);
|
||||
void mrt_stats(void);
|
||||
void bpf_stats(char *);
|
||||
|
@ -58,8 +58,10 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <libutil.h>
|
||||
#include <netdb.h>
|
||||
#include <nlist.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -105,6 +107,19 @@ struct bits {
|
||||
{ 0 , 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* kvm(3) bindings for every needed symbol
|
||||
*/
|
||||
static struct nlist rl[] = {
|
||||
#define N_RTSTAT 0
|
||||
{ .n_name = "_rtstat" },
|
||||
#define N_RTREE 1
|
||||
{ .n_name = "_rt_tables"},
|
||||
#define N_RTTRASH 2
|
||||
{ .n_name = "_rttrash" },
|
||||
{ .n_name = NULL },
|
||||
};
|
||||
|
||||
typedef union {
|
||||
long dummy; /* Helps align structure. */
|
||||
struct sockaddr u_sa;
|
||||
@ -113,13 +128,19 @@ typedef union {
|
||||
|
||||
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;
|
||||
struct radix_node_head **rt_tables;
|
||||
|
||||
int NewTree = 0;
|
||||
int NewTree = 1;
|
||||
|
||||
struct timespec uptime;
|
||||
|
||||
@ -127,27 +148,27 @@ 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_tree(struct radix_node *);
|
||||
static void p_rtnode(void);
|
||||
static void ntreestuff(void);
|
||||
static void np_rtentry(struct rt_msghdr *);
|
||||
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(struct radix_node *);
|
||||
static void p_rtentry_sysctl(struct rt_msghdr *);
|
||||
static void p_sockaddr(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 const char *fmt_flags(int f);
|
||||
static void p_rtentry(struct rtentry *);
|
||||
static void p_rtentry_kvm(struct rtentry *);
|
||||
static void domask(char *, in_addr_t, u_long);
|
||||
|
||||
/*
|
||||
* Print routing tables.
|
||||
*/
|
||||
void
|
||||
routepr(u_long rtree, int fibnum)
|
||||
routepr(int fibnum, int af)
|
||||
{
|
||||
struct radix_node_head **rnhp, *rnh, head;
|
||||
size_t intsize;
|
||||
int fam, numfibs;
|
||||
int numfibs;
|
||||
|
||||
intsize = sizeof(int);
|
||||
if (fibnum == -1 &&
|
||||
@ -157,10 +178,6 @@ routepr(u_long rtree, int fibnum)
|
||||
numfibs = 1;
|
||||
if (fibnum < 0 || fibnum > numfibs - 1)
|
||||
errx(EX_USAGE, "%d: invalid fib", fibnum);
|
||||
rt_tables = calloc(numfibs * (AF_MAX+1),
|
||||
sizeof(struct radix_node_head *));
|
||||
if (rt_tables == NULL)
|
||||
err(EX_OSERR, "memory allocation failed");
|
||||
/*
|
||||
* Since kernel & userland use different timebase
|
||||
* (time_uptime vs time_second) and we are reading kernel memory
|
||||
@ -174,55 +191,13 @@ routepr(u_long rtree, int fibnum)
|
||||
printf(" (fib: %d)", fibnum);
|
||||
printf("\n");
|
||||
|
||||
if (Aflag == 0 && NewTree)
|
||||
ntreestuff();
|
||||
else {
|
||||
if (rtree == 0) {
|
||||
printf("rt_tables: symbol not in namelist\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (kread((u_long)(rtree), (char *)(rt_tables), (numfibs *
|
||||
(AF_MAX+1) * sizeof(struct radix_node_head *))) != 0)
|
||||
return;
|
||||
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) {
|
||||
printf("Netmasks:\n");
|
||||
p_tree(head.rnh_treetop);
|
||||
}
|
||||
} else if (af == AF_UNSPEC || af == fam) {
|
||||
size_cols(fam, head.rnh_treetop);
|
||||
pr_family(fam);
|
||||
do_rtent = 1;
|
||||
pr_rthdr(fam);
|
||||
p_tree(head.rnh_treetop);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Aflag == 0 && live != 0 && NewTree)
|
||||
p_rtable_sysctl(fibnum, af);
|
||||
else
|
||||
p_rtable_kvm(fibnum, af);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Print address family header before a section of the routing table.
|
||||
*/
|
||||
@ -288,7 +263,7 @@ static int wid_if;
|
||||
static int wid_expire;
|
||||
|
||||
static void
|
||||
size_cols(int ef __unused, struct radix_node *rn)
|
||||
size_cols(int ef, struct radix_node *rn)
|
||||
{
|
||||
wid_dst = WID_DST_DEFAULT(ef);
|
||||
wid_gw = WID_GW_DEFAULT(ef);
|
||||
@ -299,7 +274,7 @@ size_cols(int ef __unused, struct radix_node *rn)
|
||||
wid_if = WID_IF_DEFAULT(ef);
|
||||
wid_expire = 6;
|
||||
|
||||
if (Wflag)
|
||||
if (Wflag && rn != NULL)
|
||||
size_cols_tree(rn);
|
||||
}
|
||||
|
||||
@ -397,27 +372,14 @@ pr_rthdr(int af1)
|
||||
|
||||
if (Aflag)
|
||||
printf("%-8.8s ","Address");
|
||||
if (af1 == AF_INET || Wflag) {
|
||||
if (Wflag) {
|
||||
printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*.*s %*s\n",
|
||||
wid_dst, wid_dst, "Destination",
|
||||
wid_gw, wid_gw, "Gateway",
|
||||
wid_flags, wid_flags, "Flags",
|
||||
wid_refs, wid_refs, "Refs",
|
||||
wid_use, wid_use, "Use",
|
||||
wid_mtu, wid_mtu, "Mtu",
|
||||
wid_if, wid_if, "Netif",
|
||||
wid_expire, "Expire");
|
||||
} else {
|
||||
printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*s\n",
|
||||
wid_dst, wid_dst, "Destination",
|
||||
wid_gw, wid_gw, "Gateway",
|
||||
wid_flags, wid_flags, "Flags",
|
||||
wid_refs, wid_refs, "Refs",
|
||||
wid_use, wid_use, "Use",
|
||||
wid_if, wid_if, "Netif",
|
||||
wid_expire, "Expire");
|
||||
}
|
||||
if (Wflag) {
|
||||
printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*s\n",
|
||||
wid_dst, wid_dst, "Destination",
|
||||
wid_gw, wid_gw, "Gateway",
|
||||
wid_flags, wid_flags, "Flags",
|
||||
wid_mtu, wid_mtu, "Mtu",
|
||||
wid_if, wid_if, "Netif",
|
||||
wid_expire, "Expire");
|
||||
} else {
|
||||
printf("%-*.*s %-*.*s %-*.*s %*.*s %*s\n",
|
||||
wid_dst, wid_dst, "Destination",
|
||||
@ -439,8 +401,77 @@ kgetsa(struct sockaddr *dst)
|
||||
return (&pt_u.u_sa);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print kernel routing tables for given fib
|
||||
* using debugging kvm(3) interface.
|
||||
*/
|
||||
static void
|
||||
p_tree(struct radix_node *rn)
|
||||
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;
|
||||
|
||||
kresolve_list(rl);
|
||||
if ((rtree = rl[N_RTREE].n_value) == 0) {
|
||||
printf("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");
|
||||
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) {
|
||||
printf("Netmasks:\n");
|
||||
p_rtree_kvm(head.rnh_treetop);
|
||||
}
|
||||
} else if (af == AF_UNSPEC || af == fam) {
|
||||
size_cols(fam, head.rnh_treetop);
|
||||
pr_family(fam);
|
||||
do_rtent = 1;
|
||||
pr_rthdr(fam);
|
||||
p_rtree_kvm(head.rnh_treetop);
|
||||
}
|
||||
}
|
||||
|
||||
free(rt_tables);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print given kernel radix tree using
|
||||
* debugging kvm(3) interface.
|
||||
*/
|
||||
static void
|
||||
p_rtree_kvm(struct radix_node *rn)
|
||||
{
|
||||
|
||||
again:
|
||||
@ -457,9 +488,9 @@ again:
|
||||
rnode.rn_dupedkey ? " =>\n" : "\n");
|
||||
} else if (do_rtent) {
|
||||
if (kget(rn, rtentry) == 0) {
|
||||
p_rtentry(&rtentry);
|
||||
p_rtentry_kvm(&rtentry);
|
||||
if (Aflag)
|
||||
p_rtnode();
|
||||
p_rtnode_kvm();
|
||||
}
|
||||
} else {
|
||||
p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key),
|
||||
@ -471,18 +502,18 @@ again:
|
||||
} else {
|
||||
if (Aflag && do_rtent) {
|
||||
printf("%-8.8lx ", (u_long)rn);
|
||||
p_rtnode();
|
||||
p_rtnode_kvm();
|
||||
}
|
||||
rn = rnode.rn_right;
|
||||
p_tree(rnode.rn_left);
|
||||
p_tree(rn);
|
||||
p_rtree_kvm(rnode.rn_left);
|
||||
p_rtree_kvm(rn);
|
||||
}
|
||||
}
|
||||
|
||||
char nbuf[20];
|
||||
|
||||
static void
|
||||
p_rtnode(void)
|
||||
p_rtnode_kvm(void)
|
||||
{
|
||||
struct radix_mask *rm = rnode.rn_mklist;
|
||||
|
||||
@ -522,72 +553,137 @@ p_rtnode(void)
|
||||
}
|
||||
|
||||
static void
|
||||
ntreestuff(void)
|
||||
p_rtable_sysctl(int fibnum, int af)
|
||||
{
|
||||
size_t needed;
|
||||
int mib[6];
|
||||
int mib[7];
|
||||
char *buf, *next, *lim;
|
||||
struct rt_msghdr *rtm;
|
||||
struct sockaddr *sa;
|
||||
int fam = 0, ifindex = 0, size;
|
||||
|
||||
struct ifaddrs *ifap, *ifa;
|
||||
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[1] = PF_ROUTE;
|
||||
mib[2] = 0;
|
||||
mib[3] = 0;
|
||||
mib[3] = af;
|
||||
mib[4] = NET_RT_DUMP;
|
||||
mib[5] = 0;
|
||||
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
|
||||
err(1, "sysctl: net.route.0.0.dump estimate");
|
||||
mib[6] = fibnum;
|
||||
if (sysctl(mib, 7, NULL, &needed, NULL, 0) < 0) {
|
||||
err(1, "sysctl: net.route.0.%d.dump.%d estimate", af, fibnum);
|
||||
}
|
||||
|
||||
if ((buf = malloc(needed)) == 0) {
|
||||
errx(2, "malloc(%lu)", (unsigned long)needed);
|
||||
}
|
||||
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
|
||||
err(1, "sysctl: net.route.0.0.dump");
|
||||
err(1, "sysctl: net.route.0.%d.dump.%d", af, fibnum);
|
||||
}
|
||||
lim = buf + needed;
|
||||
for (next = buf; next < lim; next += rtm->rtm_msglen) {
|
||||
rtm = (struct rt_msghdr *)next;
|
||||
np_rtentry(rtm);
|
||||
/*
|
||||
* Peek inside header to determine AF
|
||||
*/
|
||||
sa = (struct sockaddr *)(rtm + 1);
|
||||
if (fam != sa->sa_family) {
|
||||
fam = sa->sa_family;
|
||||
size_cols(fam, NULL);
|
||||
pr_family(fam);
|
||||
pr_rthdr(fam);
|
||||
}
|
||||
p_rtentry_sysctl(rtm);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
np_rtentry(struct rt_msghdr *rtm)
|
||||
p_rtentry_sysctl(struct rt_msghdr *rtm)
|
||||
{
|
||||
struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
|
||||
#ifdef notdef
|
||||
static int masks_done, banner_printed;
|
||||
#endif
|
||||
static int old_af;
|
||||
int af1 = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
|
||||
char buffer[128];
|
||||
char prettyname[128];
|
||||
sa_u addr, mask, gw;
|
||||
unsigned int l;
|
||||
|
||||
#ifdef notdef
|
||||
/* for the moment, netmasks are skipped over */
|
||||
if (!banner_printed) {
|
||||
printf("Netmasks:\n");
|
||||
banner_printed = 1;
|
||||
#define GETSA(_s, _f) { \
|
||||
bzero(&(_s), sizeof(_s)); \
|
||||
if (rtm->rtm_addrs & _f) { \
|
||||
l = roundup(sa->sa_len, sizeof(long)); \
|
||||
memcpy(&(_s), sa, (l > sizeof(_s)) ? sizeof(_s) : l); \
|
||||
sa = (struct sockaddr *)((char *)sa + l); \
|
||||
} \
|
||||
}
|
||||
|
||||
GETSA(addr, RTA_DST);
|
||||
GETSA(gw, RTA_GATEWAY);
|
||||
GETSA(mask, RTA_NETMASK);
|
||||
p_sockaddr(&addr.u_sa, &mask.u_sa, rtm->rtm_flags, wid_dst);
|
||||
p_sockaddr(&gw.u_sa, NULL, RTF_HOST, wid_gw);
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags);
|
||||
p_flags(rtm->rtm_flags, buffer);
|
||||
if (Wflag) {
|
||||
if (rtm->rtm_rmx.rmx_mtu != 0)
|
||||
printf("%*lu ", wid_mtu, rtm->rtm_rmx.rmx_mtu);
|
||||
else
|
||||
printf("%*s ", wid_mtu, "");
|
||||
}
|
||||
if (masks_done == 0) {
|
||||
if (rtm->rtm_addrs != RTA_DST ) {
|
||||
masks_done = 1;
|
||||
af1 = sa->sa_family;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
af1 = sa->sa_family;
|
||||
if (af1 != old_af) {
|
||||
pr_family(af1);
|
||||
old_af = af1;
|
||||
|
||||
memset(prettyname, 0, sizeof(prettyname));
|
||||
if (rtm->rtm_index < ifmap_size) {
|
||||
strlcpy(prettyname, ifmap[rtm->rtm_index].ifname,
|
||||
sizeof(prettyname));
|
||||
if (*prettyname == '\0')
|
||||
strlcpy(prettyname, "---", sizeof(prettyname));
|
||||
}
|
||||
if (rtm->rtm_addrs == RTA_DST)
|
||||
p_sockaddr(sa, NULL, 0, 36);
|
||||
else {
|
||||
p_sockaddr(sa, NULL, rtm->rtm_flags, 16);
|
||||
sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa);
|
||||
p_sockaddr(sa, NULL, 0, 18);
|
||||
|
||||
printf("%*.*s", wid_if, wid_if, prettyname);
|
||||
if (rtm->rtm_rmx.rmx_expire) {
|
||||
time_t expire_time;
|
||||
|
||||
if ((expire_time =
|
||||
rtm->rtm_rmx.rmx_expire - uptime.tv_sec) > 0)
|
||||
printf(" %*d", wid_expire, (int)expire_time);
|
||||
}
|
||||
p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
@ -756,7 +852,7 @@ fmt_flags(int f)
|
||||
}
|
||||
|
||||
static void
|
||||
p_rtentry(struct rtentry *rt)
|
||||
p_rtentry_kvm(struct rtentry *rt)
|
||||
{
|
||||
static struct ifnet ifnet, *lastif;
|
||||
static char buffer[128];
|
||||
@ -775,8 +871,10 @@ p_rtentry(struct rtentry *rt)
|
||||
snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags);
|
||||
p_flags(rt->rt_flags, buffer);
|
||||
if (addr.u_sa.sa_family == AF_INET || Wflag) {
|
||||
#if 0
|
||||
printf("%*d %*lu ", wid_refs, rt->rt_refcnt,
|
||||
wid_use, rt->rt_use);
|
||||
#endif
|
||||
if (Wflag) {
|
||||
if (rt->rt_rmx.rmx_mtu != 0)
|
||||
printf("%*lu ", wid_mtu, rt->rt_rmx.rmx_mtu);
|
||||
@ -1009,16 +1107,19 @@ routename6(struct sockaddr_in6 *sa6)
|
||||
* Print routing statistics
|
||||
*/
|
||||
void
|
||||
rt_stats(u_long rtsaddr, u_long rttaddr)
|
||||
rt_stats(void)
|
||||
{
|
||||
struct rtstat rtstat;
|
||||
u_long rtsaddr, rttaddr;
|
||||
int rttrash;
|
||||
|
||||
if (rtsaddr == 0) {
|
||||
kresolve_list(rl);
|
||||
|
||||
if ((rtsaddr = rl[N_RTSTAT].n_value) == 0) {
|
||||
printf("rtstat: symbol not in namelist\n");
|
||||
return;
|
||||
}
|
||||
if (rttaddr == 0) {
|
||||
if ((rttaddr = rl[N_RTTRASH].n_value) == 0) {
|
||||
printf("rttrash: symbol not in namelist\n");
|
||||
return;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user