From owner-p4-projects@FreeBSD.ORG Tue Aug 11 23:21:05 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 6C1A41065672; Tue, 11 Aug 2009 23:21:05 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 29DB9106566C for ; Tue, 11 Aug 2009 23:21:05 +0000 (UTC) (envelope-from pgj@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 17AD08FC3D for ; Tue, 11 Aug 2009 23:21:05 +0000 (UTC) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n7BNL5fJ079780 for ; Tue, 11 Aug 2009 23:21:05 GMT (envelope-from pgj@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n7BNL5to079778 for perforce@freebsd.org; Tue, 11 Aug 2009 23:21:05 GMT (envelope-from pgj@FreeBSD.org) Date: Tue, 11 Aug 2009 23:21:05 GMT Message-Id: <200908112321.n7BNL5to079778@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to pgj@FreeBSD.org using -f From: Gabor Pali To: Perforce Change Reviews Cc: Subject: PERFORCE change 167228 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 11 Aug 2009 23:21:06 -0000 http://perforce.freebsd.org/chv.cgi?CH=167228 Change 167228 by pgj@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 *