PERFORCE change 167228 for review
Gabor Pali
pgj at FreeBSD.org
Tue Aug 11 23:21:06 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=167228
Change 167228 by pgj at petymeg-current on 2009/08/11 23:20:37
Improve netstat_route() by providing access to further routing
details (suitable for netstat -A):
- Add routenode_type -- a routing node.
- Add routemask_type -- a routing mask.
- Embed routenode_type into route_type.
- Add a general case for address resolution.
Affected files ...
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat.h#62 edit
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_internal.h#58 edit
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_route.c#4 edit
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_util.c#67 edit
Differences ...
==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat.h#62 (text+ko) ====
@@ -118,6 +118,13 @@
#define NETSTAT_RT_CLONING 0x20000
#define NETSTAT_RT_EXPIRES 0x40000 /* has expire time */
+/* Testing flags for routenode_type: */
+#define NETSTAT_RTN_ROOT 0x01
+#define NETSTAT_RTN_DUPEDKEY 0x02
+
+/* Testing flags for routemask_type: */
+#define NETSTAT_RTM_NORMAL 0x01
+
/* Enum for TCP states: */
enum tcp_state {
tcps_Closed,
@@ -1234,7 +1241,27 @@
const char *netstat_rt_get_interface(const struct route_type *);
u_int64_t netstat_rt_get_expire(const struct route_type *);
u_int32_t netstat_rt_get_mtu(const struct route_type *);
-u_int64_t netstat_rt_get_address(const struct route_type *);
+const struct routenode_type *netstat_rt_get_node(const struct route_type *);
+
+/* Routing nodes: */
+int netstat_rnt_get_bit(const struct routenode_type *);
+int netstat_rnt_get_flags(const struct routenode_type *);
+u_int64_t netstat_rnt_get_address(const struct routenode_type *);
+u_int64_t netstat_rnt_get_left(const struct routenode_type *);
+u_int64_t netstat_rnt_get_right(const struct routenode_type *);
+const struct routeaddr_type *
+ netstat_rnt_get_netmask(const struct routenode_type *);
+int netstat_rnt_get_mkcnt(const struct routenode_type *);
+const struct routemask_type *
+ netstat_rnt_get_mask(const struct routenode_type *, int);
+
+/* Routing masks: */
+int netstat_rmt_get_flags(const struct routemask_type *);
+int netstat_rmt_get_bit(const struct routemask_type *);
+u_int64_t netstat_rmt_get_address(const struct routemask_type *);
+u_int64_t netstat_rmt_get_refs(const struct routemask_type *);
+const struct routeaddr_type *
+ netstat_rmt_get_netmask(const struct routemask_type *);
/* Routing addresses: */
const char *netstat_rat_get_name(const struct routeaddr_type *, int);
==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_internal.h#58 (text+ko) ====
@@ -450,6 +450,27 @@
size_t rat_data_len;
};
+struct routemask_type {
+ int rmt_flags;
+ int rmt_bit;
+ u_int64_t rmt_address;
+ u_int64_t rmt_refs;
+ struct routeaddr_type *rmt_mask;
+};
+
+struct routenode_type {
+ int rnt_flags;
+ int rnt_bit;
+ u_int64_t rnt_address;
+ u_int64_t rnt_left;
+ u_int64_t rnt_right;
+ u_int64_t rnt_key;
+ u_int64_t rnt_dupedkey;
+ struct routeaddr_type *rnt_mask;
+ int rnt_mkcnt;
+ struct routemask_type *rnt_mklist;
+};
+
struct route_type {
int rt_fib; /* FIB instance */
int rt_family; /* protocol family */
@@ -461,7 +482,7 @@
char *rt_interface; /* routing interface name */
u_int64_t rt_expire; /* sec */
u_int32_t rt_mtu; /* bytes */
- u_int64_t rt_address; /* opaque pointer */
+ struct routenode_type rt_node;
TAILQ_ENTRY(route_type) rt_list;
};
==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_route.c#4 (text+ko) ====
@@ -58,10 +58,11 @@
static int read_kvm(kvm_t *, const char *, void *, size_t);
static int route_tree_kvm(struct route_type_list *, int, int, kvm_t *, int);
static int route_tree_sysctl(struct route_type_list *, int, int, int);
-static void process_tree(kvm_t *, struct route_type_list *, struct radix_node *);
+static void process_tree(kvm_t *, struct route_type_list *,
+ struct radix_node *, int, int);
static void extract_rtentry_data(struct rtentry *, struct route_type *);
-static struct routeaddr_type *extract_address(struct sockaddr*,
- struct sockaddr*, int);
+static struct routeaddr_type *extract_address(void *, void *, int);
+static void extract_node(struct radix_node *, struct routenode_type *, int);
int
netstat_route(const struct session_type *session, int fib, int domain,
@@ -128,7 +129,6 @@
goto out;
}
-
if (read_kvm(kvm, rt_symbol[nlRT_rt_tables], rt_tables, treesize) < 0) {
list->rtl_error = NETSTAT_ERROR_KVM;
goto out;
@@ -143,14 +143,15 @@
continue;
KREAD(rnh, head);
- process_tree(kvm, list, head.rnh_treetop);
+ process_tree(kvm, list, head.rnh_treetop, i, flags);
}
else {
tmpfib = (domain != PF_INET) ? 0 : fibnum;
rnh = rt_tables[tmpfib].tables[domain];
if (rnh != NULL) {
KREAD(rnh, head);
- process_tree(kvm, list, head.rnh_treetop);
+ process_tree(kvm, list, head.rnh_treetop, domain,
+ flags);
}
}
@@ -168,20 +169,24 @@
} while (0);
void
-process_tree(kvm_t *kvm, struct route_type_list *list, struct radix_node *rn)
+process_tree(kvm_t *kvm, struct route_type_list *list, struct radix_node *rn,
+ int domain, int flags)
{
struct rtentry rtentry;
- struct radix_node *rnode;
+ struct radix_node *rnode, *rnp;
struct ifnet iface;
struct route_type *rtp;
- struct sockaddr sa, mk, sagw;
+ struct radix_mask rm, *rmp, *next, **oldptr;
+ struct radix_node rmn;
+ sa_u sa, mk, sagw;
+ int cnt;
again:
if (rn == NULL)
return;
KREAD(rn, rtentry);
- rnode = &rtentry.rt_nodes[0];
+ rnode = rtentry.rt_nodes;
if (!(rnode->rn_flags & RNF_ACTIVE))
return;
@@ -191,34 +196,87 @@
rtentry.rt_ifp = &iface;
}
+ cnt = 0;
+ if ((flags & NETSTAT_ROUTE_ALL) && (rnode->rn_mklist != NULL)) {
+ rmp = rnode->rn_mklist;
+ oldptr = &rnode->rn_mklist;
+ while (rmp != NULL) {
+ KREAD(rmp, rm);
+ rmp = malloc(sizeof(rm));
+ bcopy(&rm, rmp, sizeof(rm));
+ KREAD(rmp->rm_leaf, rmn);
+ rmp->rm_leaf = malloc(sizeof(rmn));
+ bcopy(&rmn, rmp->rm_leaf, sizeof(rmn));
+ rnp = rmp->rm_leaf;
+ if (rmn.rn_mask != NULL) {
+ KREAD(rmn.rn_mask, rm);
+ rnp->rn_mask = malloc(sizeof(rm));
+ bcopy(&rm, rnp->rn_mask, sizeof(rm));
+ }
+ *oldptr = rmp;
+ oldptr = &rmp->rm_mklist;
+ rmp = rmp->rm_mklist;
+ cnt += 1;
+ }
+ }
if (rnode->rn_bit < 0) {
if (rnode->rn_flags & RNF_ROOT) {
- /* root node */
+ if (flags & NETSTAT_ROUTE_ALL) {
+ rtp = _netstat_rt_allocate(list);
+ rtp->rt_family = domain;
+ rtp->rt_node.rnt_address = (int)rn;
+ rtp->rt_node.rnt_flags |= NETSTAT_RTN_ROOT;
+ extract_node(rnode, &rtp->rt_node, cnt);
+ }
} else {
if (rnode->rn_key != NULL) {
KREAD(rnode->rn_key, sa);
- rtentry.rt_nodes->rn_key = (caddr_t)&sa;
+ rtentry.rt_nodes->rn_key = (caddr_t)&sa.u_sa;
}
if (rnode->rn_mask != NULL) {
KREAD(rnode->rn_mask, mk);
- rtentry.rt_nodes->rn_mask = (caddr_t)&mk;
+ rtentry.rt_nodes->rn_mask = (caddr_t)&mk.u_sa;
}
if (rtentry.rt_gateway != NULL) {
KREAD(rtentry.rt_gateway, sagw);
- rtentry.rt_gateway = &sagw;
+ rtentry.rt_gateway = &sagw.u_sa;
}
rtp = _netstat_rt_allocate(list);
+ rtp->rt_node.rnt_address = (int)rn;
+ rtp->rt_node.rnt_mask =
+ extract_address(rnode->rn_mask, NULL, 0);
extract_rtentry_data(&rtentry, rtp);
+ extract_node(rnode, &rtp->rt_node, cnt);
}
if ((rn = rnode->rn_dupedkey))
goto again;
} else {
- process_tree(kvm, list, rnode->rn_left);
- process_tree(kvm, list, rnode->rn_right);
+ if (flags & NETSTAT_ROUTE_ALL) {
+ rtp = _netstat_rt_allocate(list);
+ rtp->rt_family = domain;
+ rtp->rt_node.rnt_address = (int)rn;
+ extract_node(rnode, &rtp->rt_node, cnt);
+ }
+ rn = rnode->rn_right;
+ process_tree(kvm, list, rnode->rn_left, domain, flags);
+ process_tree(kvm, list, rn, domain, flags);
+ }
+
+ if (flags & NETSTAT_ROUTE_ALL) {
+ rmp = rnode->rn_mklist;
+ while (rmp != NULL) {
+ next = rmp->rm_mklist;
+ rnp = rmp->rm_leaf;
+ if (rnp != NULL && rnp->rn_mask != NULL)
+ free(rnp->rn_mask);
+ free(rmp->rm_leaf);
+ free(rmp);
+ rmp = next;
+ }
}
}
#undef KREAD
@@ -263,7 +321,7 @@
{
time_t expire_time;
struct timespec uptime;
- struct sockaddr *sa, *mask;
+ struct sockaddr *sa, *mk;
CNV_FLAG(RTF_UP, NETSTAT_RT_UP);
CNV_FLAG(RTF_GATEWAY, NETSTAT_RT_GATEWAY);
@@ -282,9 +340,9 @@
CNV_FLAG(RTF_BROADCAST, NETSTAT_RT_BROADCAST);
rtp->rt_fib = rte->rt_fibnum;
sa = (struct sockaddr *)rte->rt_nodes->rn_key;
- mask = (struct sockaddr *)rte->rt_nodes->rn_mask;
+ mk = (struct sockaddr *)rte->rt_nodes->rn_mask;
rtp->rt_family = sa->sa_family;
- rtp->rt_destination = extract_address(sa, mask, rte->rt_flags);
+ rtp->rt_destination = extract_address(sa, mk, rte->rt_flags);
rtp->rt_gateway = extract_address(rte->rt_gateway, NULL, RTF_HOST);
rtp->rt_refs = rte->rt_refcnt;
rtp->rt_used = rte->rt_use;
@@ -304,26 +362,35 @@
}
rtp->rt_mtu = rte->rt_rmx.rmx_mtu;
rtp->rt_fib = rte->rt_fibnum;
- rtp->rt_address = (int)rte;
}
#undef CNV_FLAG
struct routeaddr_type *
-extract_address(struct sockaddr *sa, struct sockaddr *mask, int flags)
+extract_address(void *saddr, void *maddr, int flags)
{
struct routeaddr_type *rap;
+ struct sockaddr *sa, *mask;
struct sockaddr_in *sa_in, *mk_in;
#ifdef INET6
struct sockaddr_in6 *sa_in6, *mk_in6;
+ struct in6_addr *in6;
#endif
struct sockaddr_dl *sa_dl;
- char *cp, *p;
+ char *cp, *cq, *cqlim, *p;
int n;
+ char workbuf[128];
+ u_char *s, *slim;
+
+ if (saddr == NULL)
+ return (NULL);
+ sa = (struct sockaddr *)saddr;
+ mask = (struct sockaddr *)maddr;
sa_in = (struct sockaddr_in *)sa;
mk_in = (struct sockaddr_in *)mask;
#ifdef INET6
sa_in6 = (struct sockaddr_in6 *)sa;
+ in6 = &sa_in6->sin6_addr;
mk_in6 = (struct sockaddr_in6 *)mask;
#endif
sa_dl = (struct sockaddr_dl *)sa;
@@ -333,16 +400,6 @@
return (NULL);
switch (sa->sa_family) {
- case PF_UNSPEC:
- rap->rat_address = strdup("none");
- strlcpy(rap->rat_ni_address, "none",
- sizeof(rap->rat_ni_address));
- rap->rat_data = malloc(sizeof(struct sockaddr));
- if (rap->rat_data != NULL) {
- rap->rat_data_len = sizeof(struct sockaddr);
- memcpy(rap->rat_data, sa, rap->rat_data_len);
- }
- break;
case PF_INET:
if ((sa_in->sin_addr.s_addr == INADDR_ANY) &&
(mask != NULL) &&
@@ -409,8 +466,66 @@
}
break;
default:
+ s = (u_char *)sa->sa_data;
+ cq = workbuf;
+ slim = sa->sa_len + (u_char *)sa;
+ cqlim = cq + sizeof(workbuf) - 6;
+ cq += sprintf(cq, "(%d)", sa->sa_family);
+ while (s < slim && cq < cqlim) {
+ cq += sprintf(cq, " %02x", *s++);
+ if (s < slim)
+ cq += sprintf(cq, "%02x", *s++);
+ }
+ rap->rat_address = strdup(workbuf);
+ strlcpy(rap->rat_ni_address, workbuf,
+ sizeof(rap->rat_ni_address));
+ rap->rat_data = malloc(sizeof(struct sockaddr));
+ if (rap->rat_data != NULL) {
+ rap->rat_data_len = sizeof(struct sockaddr);
+ memcpy(rap->rat_data, sa, rap->rat_data_len);
+ }
break;
}
return (rap);
}
+
+void
+extract_node(struct radix_node *rn, struct routenode_type *rnp, int mkcnt)
+{
+ struct radix_mask *rmp;
+ struct radix_node *rnode;
+ int i;
+
+ rnp->rnt_bit = rn->rn_bit;
+ rnp->rnt_left = (int)rn->rn_left;
+ rnp->rnt_right = (int)rn->rn_right;
+ rnp->rnt_key = (int)rn->rn_key;
+ rnp->rnt_dupedkey = (int)rn->rn_dupedkey;
+ if (rn->rn_dupedkey != 0)
+ rnp->rnt_flags |= NETSTAT_RTN_DUPEDKEY;
+ rnp->rnt_mkcnt = mkcnt;
+
+ if (rnp->rnt_mkcnt == 0)
+ return;
+
+ rnp->rnt_mklist = malloc(sizeof(struct routemask_type) * rnp->rnt_mkcnt);
+ rmp = rn->rn_mklist;
+ i = 0;
+
+ while (rmp != NULL) {
+ rnp->rnt_mklist[i].rmt_address = 0;
+ rnp->rnt_mklist[i].rmt_flags = 0;
+ if (rmp->rm_flags & RNF_NORMAL)
+ rnp->rnt_mklist[i].rmt_flags |= NETSTAT_RTM_NORMAL;
+ rnp->rnt_mklist[i].rmt_bit = rmp->rm_bit;
+ rnp->rnt_mklist[i].rmt_refs = rmp->rm_refs;
+ rnode = rmp->rm_leaf;
+ rnp->rnt_mklist[i].rmt_mask =
+ (rmp->rm_flags & RNF_NORMAL && rnode->rn_mask != NULL) ?
+ extract_address(rnode->rn_mask, NULL, 0) :
+ extract_address(rmp->rm_mask, NULL, 0);
+ rmp = rmp->rm_mklist;
+ i += 1;
+ }
+}
==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_util.c#67 (text+ko) ====
@@ -2249,8 +2249,13 @@
void
_netstat_rt_free(struct route_type *rtp)
{
+ int i;
_netstat_rat_free(rtp->rt_destination);
_netstat_rat_free(rtp->rt_gateway);
+ for (i = 0; i < rtp->rt_node.rnt_mkcnt; i++)
+ _netstat_rat_free(rtp->rt_node.rnt_mklist[i].rmt_mask);
+ if (rtp->rt_node.rnt_mklist != NULL)
+ free(rtp->rt_node.rnt_mklist);
free(rtp->rt_interface);
free(rtp);
}
@@ -2258,6 +2263,8 @@
void
_netstat_rat_free(struct routeaddr_type *ratp)
{
+ if (ratp == NULL)
+ return;
free(ratp->rat_address);
free(ratp->rat_data);
free(ratp);
@@ -2441,10 +2448,90 @@
return (rtp->rt_mtu);
}
+const struct routenode_type *
+netstat_rt_get_node(const struct route_type *rtp)
+{
+ return (&rtp->rt_node);
+}
+
+int
+netstat_rnt_get_bit(const struct routenode_type *rntp)
+{
+ return (rntp->rnt_bit);
+}
+
+int
+netstat_rnt_get_flags(const struct routenode_type *rntp)
+{
+ return (rntp->rnt_flags);
+}
+
+u_int64_t
+netstat_rnt_get_address(const struct routenode_type *rntp)
+{
+ return (rntp->rnt_address);
+}
+
u_int64_t
-netstat_rt_get_address(const struct route_type *rtp)
+netstat_rnt_get_left(const struct routenode_type *rntp)
+{
+ return (rntp->rnt_left);
+}
+
+u_int64_t
+netstat_rnt_get_right(const struct routenode_type *rntp)
+{
+ return (rntp->rnt_right);
+}
+
+const struct routeaddr_type *
+netstat_rnt_get_netmask(const struct routenode_type *rntp)
+{
+ return (rntp->rnt_mask);
+}
+
+int
+netstat_rnt_get_mkcnt(const struct routenode_type *rntp)
+{
+ return (rntp->rnt_mkcnt);
+}
+
+const struct routemask_type *
+netstat_rnt_get_mask(const struct routenode_type *rntp, int i)
+{
+ if (0 <= i && i < rntp->rnt_mkcnt)
+ return (&rntp->rnt_mklist[i]);
+ return (NULL);
+}
+
+int
+netstat_rmt_get_flags(const struct routemask_type *rmtp)
+{
+ return (rmtp->rmt_flags);
+}
+
+int
+netstat_rmt_get_bit(const struct routemask_type *rmtp)
+{
+ return (rmtp->rmt_bit);
+}
+
+u_int64_t
+netstat_rmt_get_address(const struct routemask_type *rmtp)
+{
+ return (rmtp->rmt_address);
+}
+
+u_int64_t
+netstat_rmt_get_refs(const struct routemask_type *rmtp)
+{
+ return (rmtp->rmt_refs);
+}
+
+const struct routeaddr_type *
+netstat_rmt_get_netmask(const struct routemask_type *rmtp)
{
- return (rtp->rt_address);
+ return (rmtp->rmt_mask);
}
const char *
More information about the p4-projects
mailing list