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