Make netstat use sysctl when dumping routing tables/stats.
Heavily based on similar code from Claudio Jeker (at OpenBSD). While here, fix inet/inet6 sysctl stuff commited previously to actually work, and some other nits to make netstat more sysctl friendly. One step closer to losing setgid kmem on this one...
This commit is contained in:
parent
ad560fa074
commit
5d7aa1a613
|
@ -1,11 +1,11 @@
|
|||
# $NetBSD: Makefile,v 1.25 2005/08/04 19:40:00 rpaulo Exp $
|
||||
# $NetBSD: Makefile,v 1.26 2006/05/28 16:51:40 elad Exp $
|
||||
# from: @(#)Makefile 8.1 (Berkeley) 6/12/93
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
PROG= netstat
|
||||
SRCS= atalk.c bpf.c fast_ipsec.c if.c inet.c inet6.c ipsec.c iso.c \
|
||||
main.c mbuf.c mroute.c mroute6.c ns.c route.c tp_astring.c \
|
||||
main.c mbuf.c mroute.c mroute6.c ns.c show.c route.c tp_astring.c \
|
||||
unix.c
|
||||
.PATH: ${NETBSDSRCDIR}/sys/netiso
|
||||
BINGRP= kmem
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: if.c,v 1.59 2005/08/04 19:41:28 rpaulo Exp $ */
|
||||
/* $NetBSD: if.c,v 1.60 2006/05/28 16:51:40 elad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1988, 1993
|
||||
|
@ -34,7 +34,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "from: @(#)if.c 8.2 (Berkeley) 2/21/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: if.c,v 1.59 2005/08/04 19:41:28 rpaulo Exp $");
|
||||
__RCSID("$NetBSD: if.c,v 1.60 2006/05/28 16:51:40 elad Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -199,10 +199,10 @@ intpr(interval, ifnetaddr, pfunc)
|
|||
*/
|
||||
in = inet_makeaddr(ifaddr.in.ia_subnet,
|
||||
INADDR_ANY);
|
||||
cp = netname(in.s_addr,
|
||||
cp = netname4(in.s_addr,
|
||||
ifaddr.in.ia_subnetmask);
|
||||
#else
|
||||
cp = netname(ifaddr.in.ia_subnet,
|
||||
cp = netname4(ifaddr.in.ia_subnet,
|
||||
ifaddr.in.ia_subnetmask);
|
||||
#endif
|
||||
if (vflag)
|
||||
|
@ -210,7 +210,7 @@ intpr(interval, ifnetaddr, pfunc)
|
|||
else
|
||||
n = 13;
|
||||
printf("%-*.*s ", n, n, cp);
|
||||
cp = routename(sin->sin_addr.s_addr);
|
||||
cp = routename4(sin->sin_addr.s_addr);
|
||||
if (vflag)
|
||||
n = strlen(cp) < 17 ? 17 : strlen(cp);
|
||||
else
|
||||
|
@ -226,7 +226,7 @@ intpr(interval, ifnetaddr, pfunc)
|
|||
kread(multiaddr, (char *)&inm,
|
||||
sizeof inm);
|
||||
printf("\n%25s %-17.17s ", "",
|
||||
routename(
|
||||
routename4(
|
||||
inm.inm_addr.s_addr));
|
||||
multiaddr =
|
||||
(u_long)inm.inm_list.le_next;
|
||||
|
@ -249,7 +249,7 @@ intpr(interval, ifnetaddr, pfunc)
|
|||
}
|
||||
#endif
|
||||
cp = netname6(&ifaddr.in6.ia_addr,
|
||||
&ifaddr.in6.ia_prefixmask.sin6_addr);
|
||||
&ifaddr.in6.ia_prefixmask);
|
||||
if (vflag)
|
||||
n = strlen(cp) < 13 ? 13 : strlen(cp);
|
||||
else
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: inet.c,v 1.71 2006/05/21 21:01:55 liamjfoy Exp $ */
|
||||
/* $NetBSD: inet.c,v 1.72 2006/05/28 16:51:40 elad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1988, 1993
|
||||
|
@ -34,7 +34,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: inet.c,v 1.71 2006/05/21 21:01:55 liamjfoy Exp $");
|
||||
__RCSID("$NetBSD: inet.c,v 1.72 2006/05/28 16:51:40 elad Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -168,14 +168,6 @@ protopr(off, name)
|
|||
int istcp;
|
||||
static int first = 1;
|
||||
|
||||
if (off == 0)
|
||||
return;
|
||||
istcp = strcmp(name, "tcp") == 0;
|
||||
kread(off, (char *)&table, sizeof table);
|
||||
prev = head =
|
||||
(struct inpcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first;
|
||||
next = (struct inpcb *)table.inpt_queue.cqh_first;
|
||||
|
||||
compact = 0;
|
||||
if (Aflag) {
|
||||
if (!numeric_addr)
|
||||
|
@ -239,6 +231,14 @@ protopr(off, name)
|
|||
return;
|
||||
}
|
||||
|
||||
if (off == 0)
|
||||
return;
|
||||
istcp = strcmp(name, "tcp") == 0;
|
||||
kread(off, (char *)&table, sizeof table);
|
||||
prev = head =
|
||||
(struct inpcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first;
|
||||
next = (struct inpcb *)table.inpt_queue.cqh_first;
|
||||
|
||||
while (next != head) {
|
||||
kread((u_long)next, (char *)&inpcb, sizeof inpcb);
|
||||
if ((struct inpcb *)inpcb.inp_queue.cqe_prev != prev) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: inet6.c,v 1.37 2006/05/21 21:01:56 liamjfoy Exp $ */
|
||||
/* $NetBSD: inet6.c,v 1.38 2006/05/28 16:51:40 elad Exp $ */
|
||||
/* BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp */
|
||||
|
||||
/*
|
||||
|
@ -64,7 +64,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "@(#)inet.c 8.4 (Berkeley) 4/20/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: inet6.c,v 1.37 2006/05/21 21:01:56 liamjfoy Exp $");
|
||||
__RCSID("$NetBSD: inet6.c,v 1.38 2006/05/28 16:51:40 elad Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -224,14 +224,6 @@ ip6protopr(off, name)
|
|||
int istcp;
|
||||
static int first = 1;
|
||||
|
||||
if (off == 0)
|
||||
return;
|
||||
istcp = strcmp(name, "tcp6") == 0;
|
||||
kread(off, (char *)&table, sizeof (table));
|
||||
head = prev =
|
||||
(struct in6pcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first;
|
||||
next = (struct in6pcb *)table.inpt_queue.cqh_first;
|
||||
|
||||
compact = 0;
|
||||
if (Aflag) {
|
||||
if (!numeric_addr)
|
||||
|
@ -295,6 +287,14 @@ ip6protopr(off, name)
|
|||
return;
|
||||
}
|
||||
|
||||
if (off == 0)
|
||||
return;
|
||||
istcp = strcmp(name, "tcp6") == 0;
|
||||
kread(off, (char *)&table, sizeof (table));
|
||||
head = prev =
|
||||
(struct in6pcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first;
|
||||
next = (struct in6pcb *)table.inpt_queue.cqh_first;
|
||||
|
||||
while (next != head) {
|
||||
kread((u_long)next, (char *)&in6pcb, sizeof in6pcb);
|
||||
if ((struct in6pcb *)in6pcb.in6p_queue.cqe_prev != prev) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: main.c,v 1.52 2006/05/18 09:05:51 liamjfoy Exp $ */
|
||||
/* $NetBSD: main.c,v 1.53 2006/05/28 16:51:40 elad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1988, 1993
|
||||
|
@ -39,7 +39,7 @@ __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993\n\
|
|||
#if 0
|
||||
static char sccsid[] = "from: @(#)main.c 8.4 (Berkeley) 3/1/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: main.c,v 1.52 2006/05/18 09:05:51 liamjfoy Exp $");
|
||||
__RCSID("$NetBSD: main.c,v 1.53 2006/05/28 16:51:40 elad Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -450,7 +450,7 @@ main(argc, argv)
|
|||
nlistf = optarg;
|
||||
break;
|
||||
case 'n':
|
||||
numeric_addr = numeric_port = 1;
|
||||
numeric_addr = numeric_port = nflag = 1;
|
||||
break;
|
||||
case 'P':
|
||||
errno = 0;
|
||||
|
@ -529,7 +529,7 @@ main(argc, argv)
|
|||
|
||||
use_sysctl = (nlistf == NULL && memf == NULL);
|
||||
|
||||
if ((kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY,
|
||||
if (!use_sysctl && (kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY,
|
||||
buf)) == NULL)
|
||||
errx(1, "%s", buf);
|
||||
|
||||
|
@ -547,7 +547,7 @@ main(argc, argv)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0) {
|
||||
if (!use_sysctl && (kvm_nlist(kvmd, nl) < 0 || nl[0].n_type == 0)) {
|
||||
if (nlistf)
|
||||
errx(1, "%s: no namelist", nlistf);
|
||||
else
|
||||
|
@ -599,9 +599,13 @@ main(argc, argv)
|
|||
}
|
||||
if (rflag) {
|
||||
if (sflag)
|
||||
rt_stats(nl[N_RTSTAT].n_value);
|
||||
else
|
||||
routepr(nl[N_RTREE].n_value);
|
||||
rt_stats(use_sysctl ? 0 : nl[N_RTSTAT].n_value);
|
||||
else {
|
||||
if (use_sysctl)
|
||||
p_rttables(af);
|
||||
else
|
||||
routepr(nl[N_RTREE].n_value);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
#ifndef SMALL
|
||||
|
@ -708,8 +712,9 @@ printproto(tp, name)
|
|||
pr = tp->pr_cblocks;
|
||||
off = nl[tp->pr_index].n_value;
|
||||
}
|
||||
if (pr != NULL && (off || af != AF_UNSPEC))
|
||||
if (pr != NULL && ((off || af != AF_UNSPEC) || use_sysctl)) {
|
||||
(*pr)(off, name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: mroute.c,v 1.20 2005/08/04 19:41:28 rpaulo Exp $ */
|
||||
/* $NetBSD: mroute.c,v 1.21 2006/05/28 16:51:40 elad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -76,7 +76,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "from: @(#)mroute.c 8.1 (Berkeley) 6/6/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: mroute.c,v 1.20 2005/08/04 19:41:28 rpaulo Exp $");
|
||||
__RCSID("$NetBSD: mroute.c,v 1.21 2006/05/28 16:51:40 elad Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -198,9 +198,9 @@ mroutepr(mrpaddr, mfchashtbladdr, mfchashaddr, vifaddr)
|
|||
|
||||
printf(" %3u %3u %5u %-15.15s",
|
||||
vifi, v->v_threshold, v->v_rate_limit,
|
||||
routename(v->v_lcl_addr.s_addr));
|
||||
routename4(v->v_lcl_addr.s_addr));
|
||||
printf(" %-15.15s %6lu %7lu\n", (v->v_flags & VIFF_TUNNEL) ?
|
||||
routename(v->v_rmt_addr.s_addr) : "",
|
||||
routename4(v->v_rmt_addr.s_addr) : "",
|
||||
v->v_pkt_in, v->v_pkt_out);
|
||||
}
|
||||
if (!banner_printed)
|
||||
|
@ -225,9 +225,9 @@ mroutepr(mrpaddr, mfchashtbladdr, mfchashaddr, vifaddr)
|
|||
|
||||
kread((u_long)mfcp, (char *)&mfc, sizeof(mfc));
|
||||
printf(" %3u %-15.15s",
|
||||
i, routename(mfc.mfc_origin.s_addr));
|
||||
i, routename4(mfc.mfc_origin.s_addr));
|
||||
printf(" %-15.15s %7s %3u ",
|
||||
routename(mfc.mfc_mcastgrp.s_addr),
|
||||
routename4(mfc.mfc_mcastgrp.s_addr),
|
||||
pktscale(mfc.mfc_pkt_cnt), mfc.mfc_parent);
|
||||
for (vifi = 0; vifi <= numvifs; ++vifi)
|
||||
if (mfc.mfc_ttls[vifi])
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: netstat.h,v 1.34 2006/05/23 14:31:11 rpaulo Exp $ */
|
||||
/* $NetBSD: netstat.h,v 1.35 2006/05/28 16:51:40 elad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1992, 1993
|
||||
|
@ -47,6 +47,7 @@ int lflag; /* show routing table with use and ref */
|
|||
int mflag; /* show memory stats */
|
||||
int numeric_addr; /* show addresses numerically */
|
||||
int numeric_port; /* show ports numerically */
|
||||
int nflag; /* same as above, for show.c compat */
|
||||
int Pflag; /* dump a PCB */
|
||||
int pflag; /* show given protocol */
|
||||
int qflag; /* show softintrq */
|
||||
|
@ -114,16 +115,26 @@ void mbpr(u_long, u_long, u_long, u_long, u_long);
|
|||
void hostpr __P((u_long, u_long));
|
||||
void impstats __P((u_long, u_long));
|
||||
|
||||
void pr_rthdr __P((int));
|
||||
void pr_rthdr __P((int, int));
|
||||
void pr_family __P((int));
|
||||
void rt_stats __P((u_long));
|
||||
char *ns_phost __P((struct sockaddr *));
|
||||
void upHex __P((char *));
|
||||
|
||||
char *routename __P((u_int32_t));
|
||||
char *netname __P((u_int32_t, u_int32_t));
|
||||
void p_rttables(int);
|
||||
void p_flags(int, char *);
|
||||
void p_addr(struct sockaddr *, struct sockaddr *, int);
|
||||
void p_gwaddr(struct sockaddr *, int);
|
||||
void p_sockaddr(struct sockaddr *, struct sockaddr *, int, int);
|
||||
char *routename(struct sockaddr *);
|
||||
char *routename4(in_addr_t);
|
||||
char *netname(struct sockaddr *, struct sockaddr *);
|
||||
char *netname4(in_addr_t, in_addr_t);
|
||||
|
||||
/* char *routename __P((u_int32_t)); */
|
||||
/* char *netname __P((u_int32_t, u_int32_t)); */
|
||||
#ifdef INET6
|
||||
char *netname6 __P((struct sockaddr_in6 *, struct in6_addr *));
|
||||
char *netname6 __P((struct sockaddr_in6 *, struct sockaddr_in6 *));
|
||||
#endif
|
||||
char *atalk_print __P((const struct sockaddr *, int));
|
||||
char *atalk_print2 __P((const struct sockaddr *, const struct sockaddr *,
|
||||
|
@ -157,3 +168,5 @@ void mrt_stats __P((u_long, u_long));
|
|||
|
||||
void bpf_stats(void);
|
||||
void bpf_dump(char *);
|
||||
|
||||
#define PLEN (LONG_BIT / 4 + 2)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: route.c,v 1.66 2005/08/04 19:41:28 rpaulo Exp $ */
|
||||
/* $NetBSD: route.c,v 1.67 2006/05/28 16:51:40 elad Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1988, 1993
|
||||
|
@ -34,7 +34,7 @@
|
|||
#if 0
|
||||
static char sccsid[] = "from: @(#)route.c 8.3 (Berkeley) 3/9/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: route.c,v 1.66 2005/08/04 19:41:28 rpaulo Exp $");
|
||||
__RCSID("$NetBSD: route.c,v 1.67 2006/05/28 16:51:40 elad Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
|
@ -77,32 +77,6 @@ __RCSID("$NetBSD: route.c,v 1.66 2005/08/04 19:41:28 rpaulo Exp $");
|
|||
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
||||
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
|
||||
|
||||
/*
|
||||
* Definitions for showing gateway flags.
|
||||
*/
|
||||
struct bits {
|
||||
short b_mask;
|
||||
char b_val;
|
||||
} bits[] = {
|
||||
{ RTF_UP, 'U' },
|
||||
{ RTF_GATEWAY, 'G' },
|
||||
{ RTF_HOST, 'H' },
|
||||
{ RTF_REJECT, 'R' },
|
||||
{ RTF_DYNAMIC, 'D' },
|
||||
{ RTF_MODIFIED, 'M' },
|
||||
{ RTF_DONE, 'd' }, /* Completed -- for routing messages only */
|
||||
{ RTF_MASK, 'm' }, /* Mask Present -- for routing messages only */
|
||||
{ RTF_CLONING, 'C' },
|
||||
{ RTF_XRESOLVE, 'X' },
|
||||
{ RTF_LLINFO, 'L' },
|
||||
{ RTF_STATIC, 'S' },
|
||||
{ RTF_BLACKHOLE,'B' },
|
||||
{ RTF_CLONED, 'c' },
|
||||
{ RTF_PROTO1, '1' },
|
||||
{ RTF_PROTO2, '2' },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* XXX we put all of the sockaddr types in here to force the alignment
|
||||
* to be correct.
|
||||
|
@ -124,20 +98,10 @@ struct rtentry rtentry;
|
|||
struct radix_node rnode;
|
||||
struct radix_mask rmask;
|
||||
|
||||
int NewTree = 0;
|
||||
|
||||
static struct sockaddr *kgetsa __P((struct sockaddr *));
|
||||
static void p_tree __P((struct radix_node *));
|
||||
static void p_rtnode __P((void));
|
||||
static void ntreestuff __P((void));
|
||||
static void np_rtentry __P((struct rt_msghdr *));
|
||||
static void p_sockaddr __P((const struct sockaddr *,
|
||||
const struct sockaddr *, int, int));
|
||||
static void p_flags __P((int));
|
||||
static void p_rtentry __P((struct rtentry *));
|
||||
static void ntreestuff __P((void));
|
||||
static u_long forgemask __P((u_long));
|
||||
static void domask __P((char *, size_t, u_long, u_long));
|
||||
static struct sockaddr *kgetsa(struct sockaddr *);
|
||||
static void p_tree(struct radix_node *);
|
||||
static void p_rtnode(void);
|
||||
static void p_krtentry(struct rtentry *);
|
||||
|
||||
/*
|
||||
* Print routing tables.
|
||||
|
@ -152,107 +116,30 @@ routepr(rtree)
|
|||
|
||||
printf("Routing tables\n");
|
||||
|
||||
if (Aflag == 0 && NewTree)
|
||||
ntreestuff();
|
||||
else {
|
||||
if (rtree == 0) {
|
||||
printf("rt_tables: symbol not in namelist\n");
|
||||
return;
|
||||
}
|
||||
if (rtree == 0) {
|
||||
printf("rt_tables: symbol not in namelist\n");
|
||||
return;
|
||||
}
|
||||
|
||||
kget(rtree, rt_tables);
|
||||
for (i = 0; i <= AF_MAX; i++) {
|
||||
if ((rnh = rt_tables[i]) == 0)
|
||||
continue;
|
||||
kget(rnh, head);
|
||||
if (i == AF_UNSPEC) {
|
||||
if (Aflag && af == 0) {
|
||||
printf("Netmasks:\n");
|
||||
p_tree(head.rnh_treetop);
|
||||
}
|
||||
} else if (af == AF_UNSPEC || af == i) {
|
||||
pr_family(i);
|
||||
do_rtent = 1;
|
||||
pr_rthdr(i);
|
||||
kget(rtree, rt_tables);
|
||||
for (i = 0; i <= AF_MAX; i++) {
|
||||
if ((rnh = rt_tables[i]) == 0)
|
||||
continue;
|
||||
kget(rnh, head);
|
||||
if (i == AF_UNSPEC) {
|
||||
if (Aflag && (af == 0 || af == 0xff)) {
|
||||
printf("Netmasks:\n");
|
||||
p_tree(head.rnh_treetop);
|
||||
}
|
||||
} else if (af == AF_UNSPEC || af == i) {
|
||||
pr_family(i);
|
||||
do_rtent = 1;
|
||||
pr_rthdr(i, Aflag);
|
||||
p_tree(head.rnh_treetop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print address family header before a section of the routing table.
|
||||
*/
|
||||
void
|
||||
pr_family(af)
|
||||
int af;
|
||||
{
|
||||
char *afname;
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
afname = "Internet";
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
afname = "Internet6";
|
||||
break;
|
||||
#endif
|
||||
case AF_NS:
|
||||
afname = "XNS";
|
||||
break;
|
||||
case AF_ISO:
|
||||
afname = "ISO";
|
||||
break;
|
||||
case AF_APPLETALK:
|
||||
afname = "AppleTalk";
|
||||
break;
|
||||
case AF_CCITT:
|
||||
afname = "X.25";
|
||||
break;
|
||||
default:
|
||||
afname = NULL;
|
||||
break;
|
||||
}
|
||||
if (afname)
|
||||
printf("\n%s:\n", afname);
|
||||
else
|
||||
printf("\nProtocol Family %d:\n", af);
|
||||
}
|
||||
|
||||
/* column widths; each followed by one space */
|
||||
#ifndef INET6
|
||||
#define WID_DST(af) 18 /* width of destination column */
|
||||
#define WID_GW(af) 18 /* width of gateway column */
|
||||
#else
|
||||
/* width of destination/gateway column */
|
||||
#if 1
|
||||
/* strlen("fe80::aaaa:bbbb:cccc:dddd@gif0") == 30, strlen("/128") == 4 */
|
||||
#define WID_DST(af) ((af) == AF_INET6 ? (numeric_addr ? 34 : 18) : 18)
|
||||
#define WID_GW(af) ((af) == AF_INET6 ? (numeric_addr ? 30 : 18) : 18)
|
||||
#else
|
||||
/* strlen("fe80::aaaa:bbbb:cccc:dddd") == 25, strlen("/128") == 4 */
|
||||
#define WID_DST(af) ((af) == AF_INET6 ? (numeric_addr ? 29 : 18) : 18)
|
||||
#define WID_GW(af) ((af) == AF_INET6 ? (numeric_addr ? 25 : 18) : 18)
|
||||
#endif
|
||||
#endif /* INET6 */
|
||||
|
||||
/*
|
||||
* Print header for routing table columns.
|
||||
*/
|
||||
void
|
||||
pr_rthdr(af)
|
||||
int af;
|
||||
{
|
||||
|
||||
if (Aflag)
|
||||
printf("%-8.8s ","Address");
|
||||
printf("%-*.*s %-*.*s %-6.6s %6.6s%8.8s %6.6s %s\n",
|
||||
WID_DST(af), WID_DST(af), "Destination",
|
||||
WID_GW(af), WID_GW(af), "Gateway",
|
||||
"Flags", "Refs", "Use", "Mtu", "Interface");
|
||||
}
|
||||
|
||||
static struct sockaddr *
|
||||
kgetsa(dst)
|
||||
struct sockaddr *dst;
|
||||
|
@ -280,7 +167,7 @@ again:
|
|||
rnode.rn_dupedkey ? " =>\n" : "\n");
|
||||
} else if (do_rtent) {
|
||||
kget(rn, rtentry);
|
||||
p_rtentry(&rtentry);
|
||||
p_krtentry(&rtentry);
|
||||
if (Aflag)
|
||||
p_rtnode();
|
||||
} else {
|
||||
|
@ -340,212 +227,6 @@ p_rtnode()
|
|||
putchar('\n');
|
||||
}
|
||||
|
||||
static void
|
||||
ntreestuff()
|
||||
{
|
||||
size_t needed;
|
||||
int mib[6];
|
||||
char *buf, *next, *lim;
|
||||
struct rt_msghdr *rtm;
|
||||
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = PF_ROUTE;
|
||||
mib[2] = 0;
|
||||
mib[3] = 0;
|
||||
mib[4] = NET_RT_DUMP;
|
||||
mib[5] = 0;
|
||||
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
|
||||
err(1, "route sysctl estimate");
|
||||
if ((buf = malloc(needed)) == 0)
|
||||
errx(1, "out of space");
|
||||
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
|
||||
err(1, "sysctl of routing table");
|
||||
lim = buf + needed;
|
||||
for (next = buf; next < lim; next += rtm->rtm_msglen) {
|
||||
rtm = (struct rt_msghdr *)next;
|
||||
np_rtentry(rtm);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
np_rtentry(rtm)
|
||||
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 af = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
|
||||
|
||||
if (Lflag && (rtm->rtm_flags & RTF_LLINFO))
|
||||
return;
|
||||
#ifdef notdef
|
||||
/* for the moment, netmasks are skipped over */
|
||||
if (!banner_printed) {
|
||||
printf("Netmasks:\n");
|
||||
banner_printed = 1;
|
||||
}
|
||||
if (masks_done == 0) {
|
||||
if (rtm->rtm_addrs != RTA_DST ) {
|
||||
masks_done = 1;
|
||||
af = sa->sa_family;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
af = sa->sa_family;
|
||||
if (af != old_af) {
|
||||
pr_family(af);
|
||||
old_af = af;
|
||||
}
|
||||
if (rtm->rtm_addrs == RTA_DST)
|
||||
p_sockaddr(sa, NULL, 0, 36);
|
||||
else {
|
||||
p_sockaddr(sa, NULL, rtm->rtm_flags, 16);
|
||||
#if 0
|
||||
if (sa->sa_len == 0)
|
||||
sa->sa_len = sizeof(long);
|
||||
#endif
|
||||
sa = (struct sockaddr *)(ROUNDUP(sa->sa_len) + (char *)sa);
|
||||
p_sockaddr(sa, NULL, 0, 18);
|
||||
}
|
||||
p_flags(rtm->rtm_flags & interesting);
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
static void
|
||||
p_sockaddr(sa, mask, flags, width)
|
||||
const struct sockaddr *sa, *mask;
|
||||
int flags, width;
|
||||
{
|
||||
char workbuf[128], *cplim;
|
||||
char *cp = workbuf;
|
||||
char *ep = workbuf + sizeof(workbuf);
|
||||
int n;
|
||||
|
||||
switch(sa->sa_family) {
|
||||
case AF_INET:
|
||||
{
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
|
||||
|
||||
if ((sin->sin_addr.s_addr == INADDR_ANY) &&
|
||||
(mask != NULL) &&
|
||||
(((struct sockaddr_in *)mask)->sin_addr.s_addr == 0))
|
||||
cp = "default";
|
||||
else if (flags & RTF_HOST)
|
||||
cp = routename(sin->sin_addr.s_addr);
|
||||
else if (mask)
|
||||
cp = netname(sin->sin_addr.s_addr,
|
||||
((struct sockaddr_in *)mask)->sin_addr.s_addr);
|
||||
else
|
||||
cp = netname(sin->sin_addr.s_addr, INADDR_ANY);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
|
||||
#ifdef __KAME__
|
||||
struct in6_addr *in6 = &sa6->sin6_addr;
|
||||
|
||||
/*
|
||||
* XXX: This is a special workaround for KAME kernels.
|
||||
* sin6_scope_id field of SA should be set in the future.
|
||||
*/
|
||||
if (IN6_IS_ADDR_LINKLOCAL(in6) ||
|
||||
IN6_IS_ADDR_MC_LINKLOCAL(in6)) {
|
||||
/* XXX: override is ok? */
|
||||
sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)&in6->s6_addr[2]);
|
||||
*(u_short *)&in6->s6_addr[2] = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (flags & RTF_HOST)
|
||||
cp = routename6(sa6);
|
||||
else if (mask) {
|
||||
cp = netname6(sa6,
|
||||
&((struct sockaddr_in6 *)mask)->sin6_addr);
|
||||
} else
|
||||
cp = netname6(sa6, NULL);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SMALL
|
||||
case AF_APPLETALK:
|
||||
case 0:
|
||||
{
|
||||
if (!(flags & RTF_HOST) && mask)
|
||||
cp = atalk_print2(sa,mask,11);
|
||||
else
|
||||
cp = atalk_print(sa,11);
|
||||
break;
|
||||
}
|
||||
case AF_NS:
|
||||
cp = ns_print((struct sockaddr *)sa);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case AF_LINK:
|
||||
if (getnameinfo(sa, sa->sa_len, workbuf, sizeof(workbuf),
|
||||
NULL, 0, NI_NUMERICHOST) != 0)
|
||||
strlcpy(workbuf, "invalid", sizeof(workbuf));
|
||||
cp = workbuf;
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
u_char *s = (u_char *)sa->sa_data, *slim;
|
||||
|
||||
slim = sa->sa_len + (u_char *) sa;
|
||||
cplim = cp + sizeof(workbuf) - 6;
|
||||
n = snprintf(cp, ep - cp, "(%d)", sa->sa_family);
|
||||
if (n >= ep - cp)
|
||||
n = ep - cp - 1;
|
||||
if (n > 0)
|
||||
cp += n;
|
||||
while (s < slim && cp < cplim) {
|
||||
n = snprintf(cp, ep - cp, " %02x", *s++);
|
||||
if (n >= ep - cp)
|
||||
n = ep - cp - 1;
|
||||
if (n > 0)
|
||||
cp += n;
|
||||
if (s < slim) {
|
||||
n = snprintf(cp, ep - cp, "%02x", *s++);
|
||||
if (n >= ep - cp)
|
||||
n = ep - cp - 1;
|
||||
if (n > 0)
|
||||
cp += n;
|
||||
}
|
||||
}
|
||||
cp = workbuf;
|
||||
}
|
||||
}
|
||||
if (width < 0 )
|
||||
printf("%s ", cp);
|
||||
else {
|
||||
if (numeric_addr)
|
||||
printf("%-*s ", width, cp);
|
||||
else
|
||||
printf("%-*.*s ", width, width, cp);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
p_flags(f)
|
||||
int f;
|
||||
{
|
||||
char name[33], *flags;
|
||||
struct bits *p = bits;
|
||||
|
||||
for (flags = name; p->b_mask && flags - name < sizeof(name); p++)
|
||||
if (p->b_mask & f)
|
||||
*flags++ = p->b_val;
|
||||
*flags = '\0';
|
||||
printf("%-6.6s ", name);
|
||||
}
|
||||
|
||||
static struct sockaddr *sockcopy __P((struct sockaddr *,
|
||||
union sockaddr_union *));
|
||||
|
||||
|
@ -570,7 +251,7 @@ sockcopy(sp, dp)
|
|||
}
|
||||
|
||||
static void
|
||||
p_rtentry(rt)
|
||||
p_krtentry(rt)
|
||||
struct rtentry *rt;
|
||||
{
|
||||
static struct ifnet ifnet, *lastif;
|
||||
|
@ -589,9 +270,9 @@ p_rtentry(rt)
|
|||
mask = sockcopy(kgetsa(rt_mask(rt)), &mask_un);
|
||||
else
|
||||
mask = sockcopy(NULL, &mask_un);
|
||||
p_sockaddr(addr, mask, rt->rt_flags, WID_DST(af));
|
||||
p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, WID_GW(af));
|
||||
p_flags(rt->rt_flags);
|
||||
p_addr(addr, mask, rt->rt_flags);
|
||||
p_gwaddr(kgetsa(rt->rt_gateway), kgetsa(rt->rt_gateway)->sa_family);
|
||||
p_flags(rt->rt_flags, "%-6.6s ");
|
||||
printf("%6d %8lu ", rt->rt_refcnt, rt->rt_use);
|
||||
if (rt->rt_rmx.rmx_mtu)
|
||||
printf("%6lu", rt->rt_rmx.rmx_mtu);
|
||||
|
@ -630,286 +311,6 @@ p_rtentry(rt)
|
|||
}
|
||||
}
|
||||
|
||||
char *
|
||||
routename(in)
|
||||
u_int32_t in;
|
||||
{
|
||||
char *cp;
|
||||
static char line[MAXHOSTNAMELEN + 1];
|
||||
struct hostent *hp;
|
||||
static char domain[MAXHOSTNAMELEN + 1];
|
||||
static int first = 1;
|
||||
|
||||
if (first) {
|
||||
first = 0;
|
||||
if (gethostname(domain, MAXHOSTNAMELEN) == 0) {
|
||||
domain[sizeof(domain) - 1] = '\0';
|
||||
if ((cp = strchr(domain, '.')))
|
||||
(void)strlcpy(domain, cp + 1, sizeof(domain));
|
||||
else
|
||||
domain[0] = 0;
|
||||
} else
|
||||
domain[0] = 0;
|
||||
}
|
||||
cp = 0;
|
||||
if (!numeric_addr) {
|
||||
hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
|
||||
AF_INET);
|
||||
if (hp) {
|
||||
if ((cp = strchr(hp->h_name, '.')) &&
|
||||
!strcmp(cp + 1, domain))
|
||||
*cp = 0;
|
||||
cp = hp->h_name;
|
||||
}
|
||||
}
|
||||
if (cp)
|
||||
strlcpy(line, cp, sizeof(line));
|
||||
else {
|
||||
#define C(x) ((x) & 0xff)
|
||||
in = ntohl(in);
|
||||
snprintf(line, sizeof line, "%u.%u.%u.%u",
|
||||
C(in >> 24), C(in >> 16), C(in >> 8), C(in));
|
||||
}
|
||||
return (line);
|
||||
}
|
||||
|
||||
static u_long
|
||||
forgemask(a)
|
||||
u_long a;
|
||||
{
|
||||
u_long m;
|
||||
|
||||
if (IN_CLASSA(a))
|
||||
m = IN_CLASSA_NET;
|
||||
else if (IN_CLASSB(a))
|
||||
m = IN_CLASSB_NET;
|
||||
else
|
||||
m = IN_CLASSC_NET;
|
||||
return (m);
|
||||
}
|
||||
|
||||
static void
|
||||
domask(dst, dlen, addr, mask)
|
||||
char *dst;
|
||||
size_t dlen;
|
||||
u_long addr, mask;
|
||||
{
|
||||
int b, i;
|
||||
|
||||
if (!mask) {
|
||||
*dst = '\0';
|
||||
return;
|
||||
}
|
||||
i = 0;
|
||||
for (b = 0; b < 32; b++)
|
||||
if (mask & (1 << b)) {
|
||||
int bb;
|
||||
|
||||
i = b;
|
||||
for (bb = b+1; bb < 32; bb++)
|
||||
if (!(mask & (1 << bb))) {
|
||||
i = -1; /* noncontig */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (i == -1)
|
||||
(void)snprintf(dst, dlen, "&0x%lx", mask);
|
||||
else
|
||||
(void)snprintf(dst, dlen, "/%d", 32-i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the name of the network whose address is given.
|
||||
* The address is assumed to be that of a net or subnet, not a host.
|
||||
*/
|
||||
char *
|
||||
netname(in, mask)
|
||||
u_int32_t in, mask;
|
||||
{
|
||||
char *cp = 0;
|
||||
static char line[MAXHOSTNAMELEN + 4];
|
||||
struct netent *np = 0;
|
||||
u_int32_t net, omask;
|
||||
u_int32_t i;
|
||||
int subnetshift;
|
||||
|
||||
i = ntohl(in);
|
||||
omask = mask = ntohl(mask);
|
||||
if (!numeric_addr && i != INADDR_ANY) {
|
||||
if (mask == INADDR_ANY) {
|
||||
switch (mask = forgemask(i)) {
|
||||
case IN_CLASSA_NET:
|
||||
subnetshift = 8;
|
||||
break;
|
||||
case IN_CLASSB_NET:
|
||||
subnetshift = 8;
|
||||
break;
|
||||
case IN_CLASSC_NET:
|
||||
subnetshift = 4;
|
||||
break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
/*
|
||||
* If there are more bits than the standard mask
|
||||
* would suggest, subnets must be in use.
|
||||
* Guess at the subnet mask, assuming reasonable
|
||||
* width subnet fields.
|
||||
*/
|
||||
while (i &~ mask)
|
||||
mask = (long)mask >> subnetshift;
|
||||
}
|
||||
net = i & mask;
|
||||
/*
|
||||
* Note: shift the hosts bits out in octet units, since
|
||||
* not all versions of getnetbyaddr() do this for us (e.g.
|
||||
* the current `etc/networks' parser).
|
||||
*/
|
||||
while ((mask & 0xff) == 0)
|
||||
mask >>= 8, net >>= 8;
|
||||
np = getnetbyaddr(net, AF_INET);
|
||||
if (np)
|
||||
cp = np->n_name;
|
||||
}
|
||||
if (cp)
|
||||
strlcpy(line, cp, sizeof(line));
|
||||
else if ((i & 0xffffff) == 0)
|
||||
(void)snprintf(line, sizeof line, "%u", C(i >> 24));
|
||||
else if ((i & 0xffff) == 0)
|
||||
(void)snprintf(line, sizeof line, "%u.%u", C(i >> 24)
|
||||
, C(i >> 16));
|
||||
else if ((i & 0xff) == 0)
|
||||
(void)snprintf(line, sizeof line, "%u.%u.%u", C(i >> 24),
|
||||
C(i >> 16), C(i >> 8));
|
||||
else
|
||||
(void)snprintf(line, sizeof line, "%u.%u.%u.%u", C(i >> 24),
|
||||
C(i >> 16), C(i >> 8), C(i));
|
||||
domask(line + strlen(line), sizeof(line) - strlen(line), i, omask);
|
||||
return (line);
|
||||
}
|
||||
|
||||
#ifdef INET6
|
||||
char *
|
||||
netname6(sa6, mask)
|
||||
struct sockaddr_in6 *sa6;
|
||||
struct in6_addr *mask;
|
||||
{
|
||||
static char line[NI_MAXHOST];
|
||||
u_char *p, *q;
|
||||
u_char *lim;
|
||||
int masklen, final = 0, illegal = 0;
|
||||
int flag = 0;
|
||||
int error;
|
||||
struct sockaddr_in6 sin6;
|
||||
|
||||
sin6 = *sa6;
|
||||
if (mask) {
|
||||
masklen = 0;
|
||||
lim = (u_char *)(mask + 1);
|
||||
for (p = (u_char *)mask, q = (u_char *)&sin6.sin6_addr;
|
||||
p < lim;
|
||||
p++, q++) {
|
||||
if (final && *p) {
|
||||
illegal++;
|
||||
*q = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (*p & 0xff) {
|
||||
case 0xff:
|
||||
masklen += 8;
|
||||
break;
|
||||
case 0xfe:
|
||||
masklen += 7;
|
||||
final++;
|
||||
break;
|
||||
case 0xfc:
|
||||
masklen += 6;
|
||||
final++;
|
||||
break;
|
||||
case 0xf8:
|
||||
masklen += 5;
|
||||
final++;
|
||||
break;
|
||||
case 0xf0:
|
||||
masklen += 4;
|
||||
final++;
|
||||
break;
|
||||
case 0xe0:
|
||||
masklen += 3;
|
||||
final++;
|
||||
break;
|
||||
case 0xc0:
|
||||
masklen += 2;
|
||||
final++;
|
||||
break;
|
||||
case 0x80:
|
||||
masklen += 1;
|
||||
final++;
|
||||
break;
|
||||
case 0x00:
|
||||
final++;
|
||||
break;
|
||||
default:
|
||||
final++;
|
||||
illegal++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!illegal)
|
||||
*q &= *p;
|
||||
else
|
||||
*q = 0;
|
||||
}
|
||||
} else
|
||||
masklen = 128;
|
||||
|
||||
if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr))
|
||||
return("default");
|
||||
|
||||
if (numeric_addr)
|
||||
flag |= NI_NUMERICHOST;
|
||||
error = getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
|
||||
line, sizeof(line), NULL, 0, flag);
|
||||
if (error)
|
||||
strlcpy(line, "invalid", sizeof(line));
|
||||
|
||||
if (numeric_addr)
|
||||
snprintf(&line[strlen(line)], sizeof(line) - strlen(line),
|
||||
"/%d", masklen);
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
char *
|
||||
routename6(sa6)
|
||||
struct sockaddr_in6 *sa6;
|
||||
{
|
||||
static char line[NI_MAXHOST];
|
||||
int flag = 0;
|
||||
/* use local variable for safety */
|
||||
struct sockaddr_in6 sa6_local;
|
||||
int error;
|
||||
|
||||
memset(&sa6_local, 0, sizeof(sa6_local));
|
||||
sa6_local.sin6_family = AF_INET6;
|
||||
sa6_local.sin6_len = sizeof(struct sockaddr_in6);
|
||||
sa6_local.sin6_addr = sa6->sin6_addr;
|
||||
sa6_local.sin6_scope_id = sa6->sin6_scope_id;
|
||||
|
||||
if (numeric_addr)
|
||||
flag |= NI_NUMERICHOST;
|
||||
|
||||
error = getnameinfo((struct sockaddr *)&sa6_local, sa6_local.sin6_len,
|
||||
line, sizeof(line), NULL, 0, flag);
|
||||
if (error)
|
||||
strlcpy(line, "invalid", sizeof(line));
|
||||
|
||||
return line;
|
||||
}
|
||||
#endif /*INET6*/
|
||||
|
||||
/*
|
||||
* Print routing statistics
|
||||
*/
|
||||
|
@ -919,11 +320,18 @@ rt_stats(off)
|
|||
{
|
||||
struct rtstat rtstat;
|
||||
|
||||
if (off == 0) {
|
||||
if (use_sysctl) {
|
||||
size_t rtsize = sizeof(rtstat);
|
||||
|
||||
if (sysctlbyname("net.route.stats", &rtstat, &rtsize,
|
||||
NULL, 0) == -1)
|
||||
err(1, "rt_stats: sysctl");
|
||||
} else if (off == 0) {
|
||||
printf("rtstat: symbol not in namelist\n");
|
||||
return;
|
||||
}
|
||||
kread(off, (char *)&rtstat, sizeof (rtstat));
|
||||
} else
|
||||
kread(off, (char *)&rtstat, sizeof (rtstat));
|
||||
|
||||
printf("routing:\n");
|
||||
printf("\t%llu bad routing redirect%s\n",
|
||||
(unsigned long long)rtstat.rts_badredirect,
|
||||
|
@ -941,6 +349,7 @@ rt_stats(off)
|
|||
(unsigned long long)rtstat.rts_wildcard,
|
||||
plural(rtstat.rts_wildcard));
|
||||
}
|
||||
|
||||
short ns_nullh[] = {0,0,0};
|
||||
short ns_bh[] = {-1,-1,-1};
|
||||
|
||||
|
@ -1032,3 +441,5 @@ upHex(p0)
|
|||
*p += ('A' - 'a');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,678 @@
|
|||
/* $NetBSD: show.c,v 1.1 2006/05/28 16:51:40 elad Exp $ */
|
||||
/* $OpenBSD: show.c,v 1.1 2006/05/27 19:16:37 claudio Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1983, 1988, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_dl.h>
|
||||
#include <net/if_types.h>
|
||||
#include <net/pfvar.h>
|
||||
#include <net/pfkeyv2.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/if_ether.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "netstat.h"
|
||||
|
||||
char *any_ntoa(const struct sockaddr *);
|
||||
char *link_print(struct sockaddr *);
|
||||
|
||||
#define ROUNDUP(a) \
|
||||
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
||||
#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
|
||||
|
||||
#define PFKEYV2_CHUNK sizeof(u_int64_t)
|
||||
|
||||
/*
|
||||
* Definitions for showing gateway flags.
|
||||
*/
|
||||
struct bits {
|
||||
int b_mask;
|
||||
char b_val;
|
||||
};
|
||||
static const struct bits bits[] = {
|
||||
{ RTF_UP, 'U' },
|
||||
{ RTF_GATEWAY, 'G' },
|
||||
{ RTF_HOST, 'H' },
|
||||
{ RTF_REJECT, 'R' },
|
||||
{ RTF_BLACKHOLE, 'B' },
|
||||
{ RTF_DYNAMIC, 'D' },
|
||||
{ RTF_MODIFIED, 'M' },
|
||||
{ RTF_DONE, 'd' }, /* Completed -- for routing messages only */
|
||||
{ RTF_MASK, 'm' }, /* Mask Present -- for routing messages only */
|
||||
{ RTF_CLONING, 'C' },
|
||||
{ RTF_XRESOLVE, 'X' },
|
||||
{ RTF_LLINFO, 'L' },
|
||||
{ RTF_STATIC, 'S' },
|
||||
{ RTF_PROTO1, '1' },
|
||||
{ RTF_PROTO2, '2' },
|
||||
/* { RTF_PROTO3, '3' }, */
|
||||
{ RTF_CLONED, 'c' },
|
||||
/* { RTF_JUMBO, 'J' }, */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
void pr_rthdr(int, int);
|
||||
void p_rtentry(struct rt_msghdr *);
|
||||
void pr_family(int);
|
||||
void p_sockaddr(struct sockaddr *, struct sockaddr *, int, int);
|
||||
void p_flags(int, char *);
|
||||
char *routename4(in_addr_t);
|
||||
char *routename6(struct sockaddr_in6 *);
|
||||
|
||||
/*
|
||||
* Print routing tables.
|
||||
*/
|
||||
void
|
||||
p_rttables(int af)
|
||||
{
|
||||
struct rt_msghdr *rtm;
|
||||
char *buf = NULL, *next, *lim = NULL;
|
||||
size_t needed;
|
||||
int mib[6];
|
||||
struct sockaddr *sa;
|
||||
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = PF_ROUTE;
|
||||
mib[2] = 0;
|
||||
mib[3] = af;
|
||||
mib[4] = NET_RT_DUMP;
|
||||
mib[5] = 0;
|
||||
if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
|
||||
err(1, "route-sysctl-estimate");
|
||||
if (needed > 0) {
|
||||
if ((buf = malloc(needed)) == 0)
|
||||
err(1, NULL);
|
||||
if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0)
|
||||
err(1, "sysctl of routing table");
|
||||
lim = buf + needed;
|
||||
}
|
||||
|
||||
printf("Routing tables\n");
|
||||
|
||||
if (buf) {
|
||||
for (next = buf; next < lim; next += rtm->rtm_msglen) {
|
||||
rtm = (struct rt_msghdr *)next;
|
||||
sa = (struct sockaddr *)(rtm + 1);
|
||||
if (af != AF_UNSPEC && sa->sa_family != af)
|
||||
continue;
|
||||
p_rtentry(rtm);
|
||||
}
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
if (af != 0 && af != PF_KEY)
|
||||
return;
|
||||
|
||||
#ifdef notyet /* XXX elad */
|
||||
mib[0] = CTL_NET;
|
||||
mib[1] = PF_KEY;
|
||||
mib[2] = PF_KEY_V2;
|
||||
mib[3] = NET_KEY_SPD_DUMP;
|
||||
mib[4] = mib[5] = 0;
|
||||
|
||||
if (sysctl(mib, 4, NULL, &needed, NULL, 0) == -1) {
|
||||
if (errno == ENOPROTOOPT)
|
||||
return;
|
||||
err(1, "spd-sysctl-estimate");
|
||||
}
|
||||
if (needed > 0) {
|
||||
if ((buf = malloc(needed)) == 0)
|
||||
err(1, NULL);
|
||||
if (sysctl(mib, 4, buf, &needed, NULL, 0) == -1)
|
||||
err(1,"sysctl of spd");
|
||||
lim = buf + needed;
|
||||
}
|
||||
|
||||
if (buf) {
|
||||
printf("\nEncap:\n");
|
||||
|
||||
for (next = buf; next < lim; next += msg->sadb_msg_len *
|
||||
PFKEYV2_CHUNK) {
|
||||
msg = (struct sadb_msg *)next;
|
||||
if (msg->sadb_msg_len == 0)
|
||||
break;
|
||||
p_pfkentry(msg);
|
||||
}
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* column widths; each followed by one space
|
||||
* width of destination/gateway column
|
||||
* strlen("fe80::aaaa:bbbb:cccc:dddd@gif0") == 30, strlen("/128") == 4
|
||||
*/
|
||||
#define WID_DST(af) ((af) == AF_INET6 ? (nflag ? 34 : 18) : 18)
|
||||
#define WID_GW(af) ((af) == AF_INET6 ? (nflag ? 30 : 18) : 18)
|
||||
|
||||
/*
|
||||
* Print header for routing table columns.
|
||||
*/
|
||||
void
|
||||
pr_rthdr(int af, int Aflag)
|
||||
{
|
||||
if (Aflag)
|
||||
printf("%-*.*s ", PLEN, PLEN, "Address");
|
||||
if (af != PF_KEY)
|
||||
printf("%-*.*s %-*.*s %-6.6s %6.6s %8.8s %6.6s %s\n",
|
||||
WID_DST(af), WID_DST(af), "Destination",
|
||||
WID_GW(af), WID_GW(af), "Gateway",
|
||||
"Flags", "Refs", "Use", "Mtu", "Interface");
|
||||
else
|
||||
printf("%-18s %-5s %-18s %-5s %-5s %-22s\n",
|
||||
"Source", "Port", "Destination",
|
||||
"Port", "Proto", "SA(Address/Proto/Type/Direction)");
|
||||
}
|
||||
|
||||
static void
|
||||
get_rtaddrs(int addrs, struct sockaddr *sa, struct sockaddr **rti_info)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < RTAX_MAX; i++) {
|
||||
if (addrs & (1 << i)) {
|
||||
rti_info[i] = sa;
|
||||
sa = (struct sockaddr *)((char *)(sa) +
|
||||
ROUNDUP(sa->sa_len));
|
||||
} else
|
||||
rti_info[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Print a routing table entry.
|
||||
*/
|
||||
void
|
||||
p_rtentry(struct rt_msghdr *rtm)
|
||||
{
|
||||
static int old_af = -1;
|
||||
struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
|
||||
struct sockaddr *mask, *rti_info[RTAX_MAX];
|
||||
char ifbuf[IF_NAMESIZE];
|
||||
|
||||
|
||||
if (old_af != sa->sa_family) {
|
||||
old_af = sa->sa_family;
|
||||
pr_family(sa->sa_family);
|
||||
pr_rthdr(sa->sa_family, 0);
|
||||
}
|
||||
get_rtaddrs(rtm->rtm_addrs, sa, rti_info);
|
||||
|
||||
mask = rti_info[RTAX_NETMASK];
|
||||
if ((sa = rti_info[RTAX_DST]) == NULL)
|
||||
return;
|
||||
|
||||
p_sockaddr(sa, mask, rtm->rtm_flags, WID_DST(sa->sa_family));
|
||||
p_sockaddr(rti_info[RTAX_GATEWAY], NULL, RTF_HOST,
|
||||
WID_GW(sa->sa_family));
|
||||
p_flags(rtm->rtm_flags, "%-6.6s ");
|
||||
#ifdef notyet /* XXX elad */
|
||||
printf("%6d %8ld ", (int)rtm->rtm_rmx.rmx_refcnt,
|
||||
rtm->rtm_rmx.rmx_pksent);
|
||||
#endif
|
||||
if (rtm->rtm_rmx.rmx_mtu)
|
||||
printf("%6ld ", rtm->rtm_rmx.rmx_mtu);
|
||||
else
|
||||
printf("%6s ", "-");
|
||||
putchar((rtm->rtm_rmx.rmx_locks & RTV_MTU) ? 'L' : ' ');
|
||||
printf(" %.16s", if_indextoname(rtm->rtm_index, ifbuf));
|
||||
putchar('\n');
|
||||
}
|
||||
|
||||
/*
|
||||
* Print address family header before a section of the routing table.
|
||||
*/
|
||||
void
|
||||
pr_family(int af)
|
||||
{
|
||||
char *afname;
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
afname = "Internet";
|
||||
break;
|
||||
case AF_INET6:
|
||||
afname = "Internet6";
|
||||
break;
|
||||
case PF_KEY:
|
||||
afname = "Encap";
|
||||
break;
|
||||
case AF_APPLETALK:
|
||||
afname = "AppleTalk";
|
||||
break;
|
||||
default:
|
||||
afname = NULL;
|
||||
break;
|
||||
}
|
||||
if (afname)
|
||||
printf("\n%s:\n", afname);
|
||||
else
|
||||
printf("\nProtocol Family %d:\n", af);
|
||||
}
|
||||
|
||||
void
|
||||
p_addr(struct sockaddr *sa, struct sockaddr *mask, int flags)
|
||||
{
|
||||
p_sockaddr(sa, mask, flags, WID_DST(sa->sa_family));
|
||||
}
|
||||
|
||||
void
|
||||
p_gwaddr(struct sockaddr *sa, int af)
|
||||
{
|
||||
p_sockaddr(sa, 0, RTF_HOST, WID_GW(af));
|
||||
}
|
||||
|
||||
void
|
||||
p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
switch (sa->sa_family) {
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
|
||||
struct in6_addr *in6 = &sa6->sin6_addr;
|
||||
|
||||
/*
|
||||
* XXX: This is a special workaround for KAME kernels.
|
||||
* sin6_scope_id field of SA should be set in the future.
|
||||
*/
|
||||
if (IN6_IS_ADDR_LINKLOCAL(in6) ||
|
||||
IN6_IS_ADDR_MC_LINKLOCAL(in6)) {
|
||||
/* XXX: override is ok? */
|
||||
sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)
|
||||
&in6->s6_addr[2]);
|
||||
*(u_short *)&in6->s6_addr[2] = 0;
|
||||
}
|
||||
if (flags & RTF_HOST)
|
||||
cp = routename((struct sockaddr *)sa6);
|
||||
else
|
||||
cp = netname((struct sockaddr *)sa6, mask);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
if ((flags & RTF_HOST) || mask == NULL)
|
||||
cp = routename(sa);
|
||||
else
|
||||
cp = netname(sa, mask);
|
||||
break;
|
||||
}
|
||||
if (width < 0)
|
||||
printf("%s", cp);
|
||||
else {
|
||||
if (nflag)
|
||||
printf("%-*s ", width, cp);
|
||||
else
|
||||
printf("%-*.*s ", width, width, cp);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
p_flags(int f, char *format)
|
||||
{
|
||||
char name[33], *flags;
|
||||
const struct bits *p = bits;
|
||||
|
||||
for (flags = name; p->b_mask && flags < &name[sizeof(name) - 2]; p++)
|
||||
if (p->b_mask & f)
|
||||
*flags++ = p->b_val;
|
||||
*flags = '\0';
|
||||
printf(format, name);
|
||||
}
|
||||
|
||||
static char line[MAXHOSTNAMELEN];
|
||||
static char domain[MAXHOSTNAMELEN];
|
||||
|
||||
char *
|
||||
routename(struct sockaddr *sa)
|
||||
{
|
||||
char *cp = NULL;
|
||||
static int first = 1;
|
||||
|
||||
if (first) {
|
||||
first = 0;
|
||||
if (gethostname(domain, sizeof(domain)) == 0 &&
|
||||
(cp = strchr(domain, '.')))
|
||||
(void)strlcpy(domain, cp + 1, sizeof(domain));
|
||||
else
|
||||
domain[0] = '\0';
|
||||
cp = NULL;
|
||||
}
|
||||
|
||||
if (sa->sa_len == 0) {
|
||||
(void)strlcpy(line, "default", sizeof(line));
|
||||
return (line);
|
||||
}
|
||||
|
||||
switch (sa->sa_family) {
|
||||
case AF_INET:
|
||||
return
|
||||
(routename4(((struct sockaddr_in *)sa)->sin_addr.s_addr));
|
||||
|
||||
case AF_INET6:
|
||||
{
|
||||
struct sockaddr_in6 sin6;
|
||||
|
||||
memset(&sin6, 0, sizeof(sin6));
|
||||
memcpy(&sin6, sa, sa->sa_len);
|
||||
sin6.sin6_len = sizeof(struct sockaddr_in6);
|
||||
sin6.sin6_family = AF_INET6;
|
||||
if (sa->sa_len == sizeof(struct sockaddr_in6) &&
|
||||
(IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
|
||||
IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) &&
|
||||
sin6.sin6_scope_id == 0) {
|
||||
sin6.sin6_scope_id =
|
||||
ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
|
||||
sin6.sin6_addr.s6_addr[2] = 0;
|
||||
sin6.sin6_addr.s6_addr[3] = 0;
|
||||
}
|
||||
return (routename6(&sin6));
|
||||
}
|
||||
|
||||
case AF_LINK:
|
||||
return (link_print(sa));
|
||||
|
||||
#ifdef notyet /* XXX elad */
|
||||
case AF_UNSPEC:
|
||||
if (sa->sa_len == sizeof(struct sockaddr_rtlabel)) {
|
||||
static char name[RTLABEL_LEN];
|
||||
struct sockaddr_rtlabel *sr;
|
||||
|
||||
sr = (struct sockaddr_rtlabel *)sa;
|
||||
strlcpy(name, sr->sr_label, sizeof(name));
|
||||
return (name);
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
#endif
|
||||
default:
|
||||
(void)snprintf(line, sizeof(line), "(%d) %s",
|
||||
sa->sa_family, any_ntoa(sa));
|
||||
break;
|
||||
}
|
||||
return (line);
|
||||
}
|
||||
|
||||
char *
|
||||
routename4(in_addr_t in)
|
||||
{
|
||||
char *cp = NULL;
|
||||
struct in_addr ina;
|
||||
struct hostent *hp;
|
||||
|
||||
if (in == INADDR_ANY)
|
||||
cp = "default";
|
||||
if (!cp && !nflag) {
|
||||
if ((hp = gethostbyaddr((char *)&in,
|
||||
sizeof(in), AF_INET)) != NULL) {
|
||||
if ((cp = strchr(hp->h_name, '.')) &&
|
||||
!strcmp(cp + 1, domain))
|
||||
*cp = '\0';
|
||||
cp = hp->h_name;
|
||||
}
|
||||
}
|
||||
ina.s_addr = in;
|
||||
strlcpy(line, cp ? cp : inet_ntoa(ina), sizeof(line));
|
||||
|
||||
return (line);
|
||||
}
|
||||
|
||||
char *
|
||||
routename6(struct sockaddr_in6 *sin6)
|
||||
{
|
||||
int niflags = 0;
|
||||
|
||||
if (nflag)
|
||||
niflags |= NI_NUMERICHOST;
|
||||
else
|
||||
niflags |= NI_NOFQDN;
|
||||
|
||||
if (getnameinfo((struct sockaddr *)sin6, sin6->sin6_len,
|
||||
line, sizeof(line), NULL, 0, niflags) != 0)
|
||||
strncpy(line, "invalid", sizeof(line));
|
||||
|
||||
return (line);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the name of the network whose address is given.
|
||||
* The address is assumed to be that of a net or subnet, not a host.
|
||||
*/
|
||||
char *
|
||||
netname4(in_addr_t in, in_addr_t mask)
|
||||
{
|
||||
char *cp = NULL;
|
||||
struct netent *np = NULL;
|
||||
int mbits;
|
||||
|
||||
in = ntohl(in);
|
||||
mask = ntohl(mask);
|
||||
if (!nflag && in != INADDR_ANY) {
|
||||
if ((np = getnetbyaddr(in, AF_INET)) != NULL)
|
||||
cp = np->n_name;
|
||||
}
|
||||
if (in == INADDR_ANY)
|
||||
cp = "default";
|
||||
mbits = mask ? 33 - ffs(mask) : 0;
|
||||
if (cp)
|
||||
strlcpy(line, cp, sizeof(line));
|
||||
#define C(x) ((x) & 0xff)
|
||||
else if (mbits < 9)
|
||||
snprintf(line, sizeof(line), "%u/%d", C(in >> 24), mbits);
|
||||
else if (mbits < 17)
|
||||
snprintf(line, sizeof(line), "%u.%u/%d",
|
||||
C(in >> 24) , C(in >> 16), mbits);
|
||||
else if (mbits < 25)
|
||||
snprintf(line, sizeof(line), "%u.%u.%u/%d",
|
||||
C(in >> 24), C(in >> 16), C(in >> 8), mbits);
|
||||
else
|
||||
snprintf(line, sizeof(line), "%u.%u.%u.%u/%d", C(in >> 24),
|
||||
C(in >> 16), C(in >> 8), C(in), mbits);
|
||||
#undef C
|
||||
return (line);
|
||||
}
|
||||
|
||||
char *
|
||||
netname6(struct sockaddr_in6 *sa6, struct sockaddr_in6 *mask)
|
||||
{
|
||||
struct sockaddr_in6 sin6;
|
||||
u_char *p;
|
||||
int masklen, final = 0, illegal = 0;
|
||||
int i, lim, flag, error;
|
||||
char hbuf[NI_MAXHOST];
|
||||
|
||||
sin6 = *sa6;
|
||||
|
||||
flag = 0;
|
||||
masklen = 0;
|
||||
if (mask) {
|
||||
lim = mask->sin6_len - offsetof(struct sockaddr_in6, sin6_addr);
|
||||
lim = lim < sizeof(struct in6_addr) ?
|
||||
lim : sizeof(struct in6_addr);
|
||||
for (p = (u_char *)&mask->sin6_addr, i = 0; i < lim; p++) {
|
||||
if (final && *p) {
|
||||
illegal++;
|
||||
sin6.sin6_addr.s6_addr[i++] = 0x00;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (*p & 0xff) {
|
||||
case 0xff:
|
||||
masklen += 8;
|
||||
break;
|
||||
case 0xfe:
|
||||
masklen += 7;
|
||||
final++;
|
||||
break;
|
||||
case 0xfc:
|
||||
masklen += 6;
|
||||
final++;
|
||||
break;
|
||||
case 0xf8:
|
||||
masklen += 5;
|
||||
final++;
|
||||
break;
|
||||
case 0xf0:
|
||||
masklen += 4;
|
||||
final++;
|
||||
break;
|
||||
case 0xe0:
|
||||
masklen += 3;
|
||||
final++;
|
||||
break;
|
||||
case 0xc0:
|
||||
masklen += 2;
|
||||
final++;
|
||||
break;
|
||||
case 0x80:
|
||||
masklen += 1;
|
||||
final++;
|
||||
break;
|
||||
case 0x00:
|
||||
final++;
|
||||
break;
|
||||
default:
|
||||
final++;
|
||||
illegal++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!illegal)
|
||||
sin6.sin6_addr.s6_addr[i++] &= *p;
|
||||
else
|
||||
sin6.sin6_addr.s6_addr[i++] = 0x00;
|
||||
}
|
||||
while (i < sizeof(struct in6_addr))
|
||||
sin6.sin6_addr.s6_addr[i++] = 0x00;
|
||||
} else
|
||||
masklen = 128;
|
||||
|
||||
if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sin6.sin6_addr))
|
||||
return ("default");
|
||||
|
||||
if (illegal)
|
||||
warnx("illegal prefixlen");
|
||||
|
||||
if (nflag)
|
||||
flag |= NI_NUMERICHOST;
|
||||
error = getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
|
||||
hbuf, sizeof(hbuf), NULL, 0, flag);
|
||||
if (error)
|
||||
snprintf(hbuf, sizeof(hbuf), "invalid");
|
||||
|
||||
snprintf(line, sizeof(line), "%s/%d", hbuf, masklen);
|
||||
return (line);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the name of the network whose address is given.
|
||||
* The address is assumed to be that of a net or subnet, not a host.
|
||||
*/
|
||||
char *
|
||||
netname(struct sockaddr *sa, struct sockaddr *mask)
|
||||
{
|
||||
switch (sa->sa_family) {
|
||||
|
||||
case AF_INET:
|
||||
return netname4(((struct sockaddr_in *)sa)->sin_addr.s_addr,
|
||||
((struct sockaddr_in *)mask)->sin_addr.s_addr);
|
||||
case AF_INET6:
|
||||
return netname6((struct sockaddr_in6 *)sa,
|
||||
(struct sockaddr_in6 *)mask);
|
||||
case AF_LINK:
|
||||
return (link_print(sa));
|
||||
default:
|
||||
snprintf(line, sizeof(line), "af %d: %s",
|
||||
sa->sa_family, any_ntoa(sa));
|
||||
break;
|
||||
}
|
||||
return (line);
|
||||
}
|
||||
|
||||
static const char hexlist[] = "0123456789abcdef";
|
||||
|
||||
char *
|
||||
any_ntoa(const struct sockaddr *sa)
|
||||
{
|
||||
static char obuf[240];
|
||||
const char *in = sa->sa_data;
|
||||
char *out = obuf;
|
||||
int len = sa->sa_len - offsetof(struct sockaddr, sa_data);
|
||||
|
||||
*out++ = 'Q';
|
||||
do {
|
||||
*out++ = hexlist[(*in >> 4) & 15];
|
||||
*out++ = hexlist[(*in++) & 15];
|
||||
*out++ = '.';
|
||||
} while (--len > 0 && (out + 3) < &obuf[sizeof(obuf) - 1]);
|
||||
out[-1] = '\0';
|
||||
return (obuf);
|
||||
}
|
||||
|
||||
char *
|
||||
link_print(struct sockaddr *sa)
|
||||
{
|
||||
struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
|
||||
u_char *lla = (u_char *)sdl->sdl_data + sdl->sdl_nlen;
|
||||
|
||||
if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
|
||||
sdl->sdl_slen == 0) {
|
||||
(void)snprintf(line, sizeof(line), "link#%d", sdl->sdl_index);
|
||||
return (line);
|
||||
}
|
||||
switch (sdl->sdl_type) {
|
||||
case IFT_ETHER:
|
||||
#ifdef notyet /* XXX elad */
|
||||
case IFT_CARP:
|
||||
#endif
|
||||
return (ether_ntoa((struct ether_addr *)lla));
|
||||
default:
|
||||
return (link_ntoa(sdl));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue