Make netstat -rn more resilient to having the routing table change out from
under it while running. Note that this is still not perfect: - Try to do something intelligent if kvm_read() fails to read a routing table structure such as an rtentry, radix_node, or ifnet. - Don't follow left and right node pointers in radix_nodes unless RNF_ACTIVE is set in rn_flags. This avoids walking through freed radix_nodes. MFC after: 1 week
This commit is contained in:
parent
af176d7306
commit
2e4760b66b
@ -164,11 +164,13 @@ routepr(u_long rtree)
|
||||
return;
|
||||
}
|
||||
|
||||
kget(rtree, rt_tables);
|
||||
if (kget(rtree, rt_tables) != 0)
|
||||
return;
|
||||
for (i = 0; i <= AF_MAX; i++) {
|
||||
if ((rnh = rt_tables[i]) == 0)
|
||||
continue;
|
||||
kget(rnh, head);
|
||||
if (kget(rnh, head) != 0)
|
||||
continue;
|
||||
if (i == AF_UNSPEC) {
|
||||
if (Aflag && af == 0) {
|
||||
printf("Netmasks:\n");
|
||||
@ -269,10 +271,14 @@ static void
|
||||
size_cols_tree(struct radix_node *rn)
|
||||
{
|
||||
again:
|
||||
kget(rn, rnode);
|
||||
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) {
|
||||
kget(rn, rtentry);
|
||||
if (kget(rn, rtentry) != 0)
|
||||
return;
|
||||
size_cols_rtentry(&rtentry);
|
||||
}
|
||||
if ((rn = rnode.rn_dupedkey))
|
||||
@ -299,7 +305,8 @@ size_cols_rtentry(struct rtentry *rt)
|
||||
* Don't print protocol-cloned routes unless -a.
|
||||
*/
|
||||
if (rt->rt_flags & RTF_WASCLONED && !aflag) {
|
||||
kget(rt->rt_parent, parent);
|
||||
if (kget(rt->rt_parent, parent) != 0)
|
||||
return;
|
||||
if (parent.rt_flags & RTF_PRCLONING)
|
||||
return;
|
||||
}
|
||||
@ -335,9 +342,11 @@ size_cols_rtentry(struct rtentry *rt)
|
||||
}
|
||||
if (rt->rt_ifp) {
|
||||
if (rt->rt_ifp != lastif) {
|
||||
kget(rt->rt_ifp, ifnet);
|
||||
if (kget(rt->rt_ifp, ifnet) == 0)
|
||||
len = strlen(ifnet.if_xname);
|
||||
else
|
||||
len = strlen("---");
|
||||
lastif = rt->rt_ifp;
|
||||
len = strlen(ifnet.if_xname);
|
||||
wid_if = MAX(len, wid_if);
|
||||
}
|
||||
if (rt->rt_rmx.rmx_expire) {
|
||||
@ -398,7 +407,8 @@ static struct sockaddr *
|
||||
kgetsa(struct sockaddr *dst)
|
||||
{
|
||||
|
||||
kget(dst, pt_u.u_sa);
|
||||
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);
|
||||
@ -409,7 +419,10 @@ p_tree(struct radix_node *rn)
|
||||
{
|
||||
|
||||
again:
|
||||
kget(rn, rnode);
|
||||
if (kget(rn, rnode) != 0)
|
||||
return;
|
||||
if (!(rnode.rn_flags & RNF_ACTIVE))
|
||||
return;
|
||||
if (rnode.rn_bit < 0) {
|
||||
if (Aflag)
|
||||
printf("%-8.8lx ", (u_long)rn);
|
||||
@ -418,10 +431,11 @@ again:
|
||||
printf("(root node)%s",
|
||||
rnode.rn_dupedkey ? " =>\n" : "\n");
|
||||
} else if (do_rtent) {
|
||||
kget(rn, rtentry);
|
||||
p_rtentry(&rtentry);
|
||||
if (Aflag)
|
||||
p_rtnode();
|
||||
if (kget(rn, rtentry) == 0) {
|
||||
p_rtentry(&rtentry);
|
||||
if (Aflag)
|
||||
p_rtnode();
|
||||
}
|
||||
} else {
|
||||
p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key),
|
||||
NULL, 0, 44);
|
||||
@ -459,16 +473,19 @@ p_rtnode(void)
|
||||
printf("%6.6s %8.8lx : %8.8lx", nbuf, (u_long)rnode.rn_left, (u_long)rnode.rn_right);
|
||||
}
|
||||
while (rm) {
|
||||
kget(rm, rmask);
|
||||
if (kget(rm, rmask) != 0)
|
||||
break;
|
||||
sprintf(nbuf, " %d refs, ", rmask.rm_refs);
|
||||
printf(" mk = %8.8lx {(%d),%s",
|
||||
(u_long)rm, -1 - rmask.rm_bit, rmask.rm_refs ? nbuf : " ");
|
||||
if (rmask.rm_flags & RNF_NORMAL) {
|
||||
struct radix_node rnode_aux;
|
||||
printf(" <normal>, ");
|
||||
kget(rmask.rm_leaf, rnode_aux);
|
||||
p_sockaddr(kgetsa((struct sockaddr *)rnode_aux.rn_mask),
|
||||
if (kget(rmask.rm_leaf, rnode_aux) == 0)
|
||||
p_sockaddr(kgetsa((struct sockaddr *)rnode_aux.rn_mask),
|
||||
NULL, 0, -1);
|
||||
else
|
||||
p_sockaddr(NULL, NULL, 0, -1);
|
||||
} else
|
||||
p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask),
|
||||
NULL, 0, -1);
|
||||
@ -572,6 +589,9 @@ fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags)
|
||||
static char workbuf[128];
|
||||
const char *cp;
|
||||
|
||||
if (sa == NULL)
|
||||
return ("null");
|
||||
|
||||
switch(sa->sa_family) {
|
||||
case AF_INET:
|
||||
{
|
||||
@ -729,7 +749,8 @@ p_rtentry(struct rtentry *rt)
|
||||
* Don't print protocol-cloned routes unless -a.
|
||||
*/
|
||||
if (rt->rt_flags & RTF_WASCLONED && !aflag) {
|
||||
kget(rt->rt_parent, parent);
|
||||
if (kget(rt->rt_parent, parent) != 0)
|
||||
return;
|
||||
if (parent.rt_flags & RTF_PRCLONING)
|
||||
return;
|
||||
}
|
||||
@ -756,9 +777,12 @@ p_rtentry(struct rtentry *rt)
|
||||
}
|
||||
if (rt->rt_ifp) {
|
||||
if (rt->rt_ifp != lastif) {
|
||||
kget(rt->rt_ifp, ifnet);
|
||||
if (kget(rt->rt_ifp, ifnet) == 0)
|
||||
strlcpy(prettyname, ifnet.if_xname,
|
||||
sizeof(prettyname));
|
||||
else
|
||||
strlcpy(prettyname, "---", sizeof(prettyname));
|
||||
lastif = rt->rt_ifp;
|
||||
strlcpy(prettyname, ifnet.if_xname, sizeof(prettyname));
|
||||
}
|
||||
printf("%*.*s", wid_if, wid_if, prettyname);
|
||||
if (rt->rt_rmx.rmx_expire) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user