summaryrefslogtreecommitdiffstats
path: root/usr.bin
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-02-14 20:01:52 +0000
committerjhb <jhb@FreeBSD.org>2008-02-14 20:01:52 +0000
commit0d1deccf8cf1c11e820910032c00c267a4d66387 (patch)
treec339ac06b1ff84bfb0aa5d4eaeeb85e76246ae6a /usr.bin
parentecd7efd2413b82b2b5506ff7046d6b39f9933a8b (diff)
downloadFreeBSD-src-0d1deccf8cf1c11e820910032c00c267a4d66387.zip
FreeBSD-src-0d1deccf8cf1c11e820910032c00c267a4d66387.tar.gz
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
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/netstat/route.c62
1 files changed, 43 insertions, 19 deletions
diff --git a/usr.bin/netstat/route.c b/usr.bin/netstat/route.c
index 561638d..629cab0 100644
--- a/usr.bin/netstat/route.c
+++ b/usr.bin/netstat/route.c
@@ -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) {
OpenPOWER on IntegriCloud