PERFORCE change 166340 for review

Gabor Pali pgj at FreeBSD.org
Tue Jul 21 01:02:09 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=166340

Change 166340 by pgj at petymeg-current on 2009/07/21 01:01:29

	Some netstat_interface() improvements:
	- Eliminate the need for extract_if_maddress()
	- Add support for PF_INET, PF_INET6
	- Fix the problem of sockaddr types of different sizes
	- Fix & improve address resolution
	- Add further accessor functions 

Affected files ...

.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat.h#31 edit
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_if.c#3 edit
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_internal.h#28 edit
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_util.c#34 edit

Differences ...

==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat.h#31 (text+ko) ====

@@ -245,9 +245,14 @@
 u_int64_t   netstat_ft_get_errors(const struct face_type *);
 
 int	    netstat_iat_get_family(const struct intfaddr_type *);
-const char  *netstat_iat_get_name(const struct intfaddr_type *);
-const char  *netstat_iat_get_subnet(const struct intfaddr_type *);
+const char  *netstat_iat_get_address(const struct intfaddr_type *, int numeric);
+const char  *netstat_iat_get_network(const struct intfaddr_type *, int numeric);
 enum intfaddr_layer netstat_iat_get_layer(const struct intfaddr_type *);
+u_int64_t   netstat_iat_get_ipackets(const struct intfaddr_type *);
+u_int64_t   netstat_iat_get_ibytes(const struct intfaddr_type *);
+u_int64_t   netstat_iat_get_opackets(const struct intfaddr_type *);
+u_int64_t   netstat_iat_get_obytes(const struct intfaddr_type *);
+u_int32_t   netstat_iat_get_refcount(const struct intfaddr_type *);
 
 /* Interface addresses: */
 

==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_if.c#3 (text+ko) ====

@@ -37,6 +37,7 @@
 #include <netinet/in_var.h>
 #include <netipx/ipx.h>
 #include <netipx/ipx_if.h>
+#include <arpa/inet.h>
 
 #include <err.h>
 #include <stdint.h>
@@ -56,9 +57,8 @@
 static const char *const if_symbol[] = { "_ifnet" };
 
 static void extract_if_data(struct ifnet *ifp, struct interface_type *itp);
-static void extract_if_address(struct ifaddr *ifa, struct interface_type *itp);
-static void extract_if_maddress(struct ifmultiaddr *ifma,
-    struct interface_type *itp);
+static struct intfaddr_type *extract_if_address(int type, void *ifaddr,
+    void *saddr, struct interface_type *itp);
 
 #define KREAD(off, dst) do {						    \
 	if ((list->itl_error = (kread_data(kvm, (uintptr_t)(off), &(dst),   \
@@ -78,7 +78,14 @@
 
 	struct ifnethead    ifnethead;
 	struct ifnet	    ifnet;
-	struct ifaddr	    ifaddr;
+	union {
+		struct ifaddr	    ifa;
+		struct in_ifaddr    in;
+#ifdef INET6
+		struct in6_ifaddr   in6;
+#endif
+		struct ipx_ifaddr   ipx;
+	} ifaddr;
 	union {
 		struct sockaddr	    sa;
 		struct sockaddr_dl  dl;
@@ -126,15 +133,19 @@
 			/* Interface addresses. */
 			for (ifa_addr = (u_long)TAILQ_FIRST(&ifnet.if_addrhead);
 			    ifa_addr != 0;
-			    ifa_addr = (u_long)TAILQ_NEXT(&ifaddr, ifa_link)) {
+			    ifa_addr = (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link)) {
 				KREAD(ifa_addr, ifaddr);
-				KREAD(ifaddr.ifa_addr, sa);
-				ifaddr.ifa_addr = &sa.sa;
+				KREAD(ifaddr.ifa.ifa_addr, sa);
+				ifaddr.ifa.ifa_addr = &sa.sa;
 				/* List addresses with the given protocol. */
 				if (domain != PF_UNSPEC &&
-				    domain != ifaddr.ifa_addr->sa_family)
+				    domain != ifaddr.ifa.ifa_addr->sa_family)
 				    	continue;
-				extract_if_address(&ifaddr, itp);
+				if (itp->it_addrcnt >= IFTYPE_MAXADDRCNT)
+					continue;
+				itp->it_address[itp->it_addrcnt++] =
+				    extract_if_address(NETSTAT_IF_IFADDR,
+					&ifaddr.ifa, ifaddr.ifa.ifa_addr, itp);
 			}
 
 			/* Multicast addresses. */
@@ -147,7 +158,11 @@
 				if (domain != PF_UNSPEC &&
 				    domain != ifmultiaddr.ifma_addr->sa_family)
 					continue;
-				extract_if_maddress(&ifmultiaddr, itp);
+				if (itp->it_maddrcnt >= IFTYPE_MAXADDRCNT)
+					continue;
+				itp->it_maddress[itp->it_maddrcnt++] =
+				    extract_if_address(NETSTAT_IF_IFMULTIADDR,
+					&ifmultiaddr, ifmultiaddr.ifma_addr, itp);
 			}
 		}
 	} else {
@@ -184,11 +199,15 @@
 		itp->it_flags |= NETSTAT_IF_UP;
 }
 
-void
-extract_if_address(struct ifaddr *ifa, struct interface_type *itp)
+struct intfaddr_type *
+extract_if_address(int type, void *ifaddr, void *saddr,
+    struct interface_type *itp)
 {
 	struct sockaddr	    *sa;
 	struct sockaddr_in  *sa_in;
+#ifdef INET6
+	struct sockaddr_in6 *sa_in6;
+#endif
 	struct sockaddr_dl  *sa_dl;
 	struct in_ifaddr    *in;
 #ifdef INET6
@@ -196,34 +215,94 @@
 #endif
 	struct ipx_ifaddr   *ipx;
 
+	struct ifmultiaddr   *ifma;
 	struct intfaddr_type *ifap;
 
 	char *cp, *p;
 	int n;
 
-	sa = (struct sockaddr *)ifa->ifa_addr;
+	sa = (struct sockaddr *)saddr;
 	sa_in = (struct sockaddr_in *)sa;
+	sa_in6 = (struct sockaddr_in6 *)sa;
 	sa_dl = (struct sockaddr_dl *)sa;
-	in = (struct in_ifaddr *)sa;
-	in6 = (struct in6_ifaddr *)sa;
-	ipx = (struct ipx_ifaddr *)sa;
 
-	/* Cannot store more addresses. */ 
-	if (itp->it_addrcnt == IFTYPE_MAXADDRCNT)
-		return;
+	in = (struct in_ifaddr *)ifaddr;
+	in6 = (struct in6_ifaddr *)in;
+	ipx = (struct ipx_ifaddr *)in;
+	ifma = (struct ifmultiaddr *)ifaddr;
 
-	ifap = itp->it_address[itp->it_addrcnt] =
-	    _netstat_iat_allocate(sa->sa_family, NETSTAT_IF_IFADDR);
+	ifap = _netstat_iat_allocate(sa->sa_family, type);
 	if (ifap == NULL)
-		return;
+		return (NULL);
 
 	switch (sa->sa_family) {
 	case PF_UNSPEC:
+		ifap->iat_address = strdup("none");
+		ifap->iat_network = strdup("none");
 		break;
 	case PF_INET:
+		ifap->iat_sockaddr_len = sizeof(struct sockaddr_in);
+		ifap->iat_sockaddr = malloc(ifap->iat_sockaddr_len);
+		if (ifap->iat_sockaddr != NULL)
+			memcpy(ifap->iat_sockaddr, sa_in,
+			    ifap->iat_sockaddr_len);
+		ifap->iat_ifaddr_len = sizeof(struct in_ifaddr);
+		if (ifap->iat_ifaddr != NULL)
+			memcpy(ifap->iat_ifaddr, in, ifap->iat_ifaddr_len);
+		strlcpy(ifap->iat_ni_network,
+		    netname(htonl(in->ia_subnet), in->ia_subnetmask, 1),
+		    sizeof(ifap->iat_ni_network));
+ 		ifap->iat_network = strdup(netname(htonl(in->ia_subnet),
+		    in->ia_subnetmask, 0));
+ 		inet_ntop(PF_INET, &sa_in->sin_addr, ifap->iat_ni_address,
+		    sizeof(ifap->iat_ni_address));
+		ifap->iat_address = strdup(routename(sa_in->sin_addr.s_addr, 0));
+		ifap->iat_layer = layer_Network;
+		switch (type) {
+		case NETSTAT_IF_IFADDR:
+			ifap->iat_refcount = in->ia_ifa.ifa_refcnt;
+			break;
+		case NETSTAT_IF_IFMULTIADDR:
+			ifap->iat_refcount = ifma->ifma_refcount;
+			break;
+		}
+		ifap->iat_opackets = in->ia_ifa.if_opackets;
+		ifap->iat_ipackets = in->ia_ifa.if_ipackets;
+		ifap->iat_obytes = in->ia_ifa.if_obytes;
+		ifap->iat_ibytes = in->ia_ifa.if_ibytes;
 		break;
 #ifdef INET6
 	case PF_INET6:
+		ifap->iat_sockaddr_len = sizeof(struct sockaddr_in6);
+		ifap->iat_sockaddr = malloc(ifap->iat_sockaddr_len);
+		if (ifap->iat_sockaddr != NULL)
+			memcpy(ifap->iat_sockaddr, sa_in6,
+			    ifap->iat_sockaddr_len);
+		ifap->iat_ifaddr_len = sizeof(struct in6_ifaddr);
+		if (ifap->iat_ifaddr != NULL)
+			memcpy(ifap->iat_ifaddr, in6, ifap->iat_ifaddr_len);
+		strlcpy(ifap->iat_ni_network,
+		    netname6(&in6->ia_addr, &in6->ia_prefixmask.sin6_addr, 1),
+		    sizeof(ifap->iat_ni_network));
+		ifap->iat_network =
+		    strdup(netname6(&in6->ia_addr,
+		    &in6->ia_prefixmask.sin6_addr, 0));
+		inet_ntop(PF_INET6, &sa_in6->sin6_addr, ifap->iat_ni_address,
+		    sizeof(ifap->iat_ni_address));
+		ifap->iat_address = strdup(routename6(sa_in6, 0));
+		ifap->iat_layer = layer_Network;
+		switch (type) {
+		case NETSTAT_IF_IFADDR:
+			ifap->iat_refcount = in->ia_ifa.ifa_refcnt;
+			break;
+		case NETSTAT_IF_IFMULTIADDR:
+			ifap->iat_refcount = ifma->ifma_refcount;
+			break;
+		}
+		ifap->iat_opackets = in6->ia_ifa.if_opackets;
+		ifap->iat_ipackets = in6->ia_ifa.if_ipackets;
+		ifap->iat_obytes = in6->ia_ifa.if_obytes;
+		ifap->iat_ibytes = in6->ia_ifa.if_ibytes;
 		break;
 #endif /* INET6 */
 	case PF_IPX:
@@ -231,74 +310,26 @@
 	case PF_APPLETALK:
 		break;
 	case PF_LINK:
-		ifap->iat_address_len = sizeof(struct sockaddr_dl);
-		ifap->iat_address = malloc(ifap->iat_address_len);
-		if (ifap->iat_address != NULL)
-			memcpy(ifap->iat_address, sa_dl, ifap->iat_address_len);
-		ifap->iat_network = NULL;
-		sprintf(ifap->iat_subnet, "<Link#%d>", sa_dl->sdl_index);
+		ifap->iat_sockaddr_len = sizeof(struct sockaddr_dl);
+		ifap->iat_sockaddr = malloc(ifap->iat_sockaddr_len);
+		if (ifap->iat_sockaddr != NULL)
+			memcpy(ifap->iat_sockaddr, sa_dl,
+			    ifap->iat_sockaddr_len);
+		sprintf(ifap->iat_ni_network, "<Link#%d>", sa_dl->sdl_index);
+		ifap->iat_network = strdup(ifap->iat_ni_network);
 		cp = (char *)LLADDR(sa_dl);
 		n = sa_dl->sdl_alen;
-		p = ifap->iat_name;
+		p = ifap->iat_ni_address;
 		while (--n >= 0) {
 			sprintf(p, "%02x%s", *cp++ & 0xff, n > 0 ? ":" : "");
 			p += 3;
 		}
+		ifap->iat_address = strdup(ifap->iat_ni_address);
 		ifap->iat_layer = layer_Link;
 		break;
 	default:
 		break;
 	}
 
-	itp->it_addrcnt += 1;
-}
-
-void
-extract_if_maddress(struct ifmultiaddr *ifma, struct interface_type *itp)
-{
-	struct sockaddr	*sa;
-	struct sockaddr_dl  *sa_dl;
-	struct intfaddr_type *ifap;
-
-	char *cp, *p;
-	int n;
-
-	sa = ifma->ifma_addr;
-	sa_dl = (struct sockaddr_dl *)sa;
-
-	/* Cannot store more addresses. */ 
-	if (itp->it_maddrcnt == IFTYPE_MAXADDRCNT)
-		return;
-
-	ifap = itp->it_maddress[itp->it_maddrcnt] =
-	    _netstat_iat_allocate(sa->sa_family, NETSTAT_IF_IFMULTIADDR);
-	if (ifap == NULL)
-		return;
-
-	switch (sa->sa_family) {
-	case PF_INET:
-		break;
-#ifdef INET6
-	case PF_INET6:
-		break;
-#endif /* INET6 */
-	case PF_LINK:
-		ifap->iat_address_len = sizeof(struct sockaddr_dl);
-		ifap->iat_address = malloc(ifap->iat_address_len);
-		if (ifap->iat_address != NULL)
-			memcpy(ifap->iat_address, sa_dl, ifap->iat_address_len);
-		ifap->iat_network = NULL;
-		sprintf(ifap->iat_subnet, "<Link#%d>", sa_dl->sdl_index);
-		cp = (char *)LLADDR(sa_dl);
-		n = sa_dl->sdl_alen;
-		p = ifap->iat_name;
-		while (--n >= 0) {
-			sprintf(p, "%02x%s", *cp++ & 0xff, n > 0 ? ":" : "");
-			p += 3;
-		}
-		ifap->iat_layer = layer_Link;
-		break;
-	}
-
-	itp->it_maddrcnt += 1;
+	return (ifap);
 }

==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_internal.h#28 (text+ko) ====

@@ -186,13 +186,15 @@
 	int			iat_family; /* protocol family */
 	enum intfaddr_layer	iat_layer;
 	int			iat_type; /* ifa, ifma */
-	char			iat_name[20];
-	char			iat_subnet[16];
-	void			*iat_address; /* raw address */
-	void			*iat_network; /* raw network */
-	int			iat_address_len;
-	u_int64_t		iat_network_mask;
-	u_int32_t		iat_refcount; /* ifma */
+	char			*iat_address;
+	char			iat_ni_address[20]; /* numeric */
+	char			*iat_network;
+	char			iat_ni_network[16]; /* numeric */
+	void			*iat_sockaddr;
+	void			*iat_ifaddr;
+	int			iat_sockaddr_len;
+	int			iat_ifaddr_len;
+	u_int32_t		iat_refcount;
 	/* for network-layer addresses: */
 	u_int64_t		iat_opackets;
 	u_int64_t		iat_ipackets;
@@ -261,8 +263,8 @@
 
 
 /* XXX: merge these into a common address resolution routine. */
-const char	*routename(in_addr_t *in, int numeric);
-const char	*netname(in_addr_t *in, u_long mask, int numeric);
+const char	*routename(in_addr_t in, int numeric);
+const char	*netname(in_addr_t in, u_long mask, int numeric);
 #ifdef INET6
 const char	*routename6(struct sockaddr_in6 *in6, int numeric);
 const char	*netname6(struct sockaddr_in6 *in6, struct in6_addr *mask,

==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_util.c#34 (text+ko) ====

@@ -863,6 +863,8 @@
 {
 	free(iatp->iat_address);
 	free(iatp->iat_network);
+	free(iatp->iat_sockaddr);
+	free(iatp->iat_ifaddr);
 	free(iatp);
 }
 
@@ -973,15 +975,19 @@
 }
 
 const char *
-netstat_iat_get_name(const struct intfaddr_type *iatp)
+netstat_iat_get_address(const struct intfaddr_type *iatp, int numeric)
 {
-	return (iatp->iat_name);
+	if (numeric)
+		return (iatp->iat_ni_address);
+	return (iatp->iat_address);
 }
 
 const char *
-netstat_iat_get_subnet(const struct intfaddr_type *iatp)
+netstat_iat_get_network(const struct intfaddr_type *iatp, int numeric)
 {
-	return (iatp->iat_subnet);
+	if (numeric)
+		return (iatp->iat_ni_network);
+	return (iatp->iat_network);
 }
 
 enum intfaddr_layer
@@ -990,17 +996,46 @@
 	return (iatp->iat_layer);
 }
 
+u_int64_t
+netstat_iat_get_ipackets(const struct intfaddr_type *iatp)
+{
+	return (iatp->iat_ipackets);
+}
+
+u_int64_t
+netstat_iat_get_ibytes(const struct intfaddr_type *iatp)
+{
+	return (iatp->iat_ibytes);
+}
+
+u_int64_t
+netstat_iat_get_opackets(const struct intfaddr_type *iatp)
+{
+	return (iatp->iat_opackets);
+}
+
+u_int64_t
+netstat_iat_get_obytes(const struct intfaddr_type *iatp)
+{
+	return (iatp->iat_obytes);
+}
+
+u_int32_t
+netstat_iat_get_refcount(const struct intfaddr_type *iatp)
+{
+	return (iatp->iat_refcount);
+}
+
 const char *
-routename(in_addr_t *in, int numeric)
+routename(in_addr_t in, int numeric)
 {
 	char *cp;
 	static char line[MAXHOSTNAMELEN];
 	struct hostent *hp;
-	in_addr_t tin;
 
 	cp = NULL;
 	if (!numeric) {
-		hp = gethostbyaddr(in, sizeof(struct in_addr), PF_INET);
+		hp = gethostbyaddr(&in, sizeof(struct in_addr), PF_INET);
 		if (hp != NULL) {
 			cp = hp->h_name;
 			trimdomain(cp, strlen(cp));
@@ -1010,9 +1045,9 @@
 		strlcpy(line, cp, sizeof(line));
 	} else {
 #define C(x)	((x) & 0xff)
-		tin = ntohl(*in);
+		in = ntohl(in);
 		sprintf(line, "%u.%u.%u.%u",
-		    C(tin >> 24), C(tin >> 16), C(tin >> 8), C(tin));
+		    C(in >> 24), C(in >> 16), C(in >> 8), C(in));
 	}
 	return (line);
 }
@@ -1039,8 +1074,9 @@
 
 			i = b;
 			for (bb = b + 1; bb < 32; bb++)
-				if (!(mask & (1 << b))) {
+				if (!(mask & (1 << bb))) {
 					i = -1; /* noncontig */
+					break;
 				}
 			break;
 		}
@@ -1051,15 +1087,15 @@
 }
 
 const char *
-netname(in_addr_t *in, u_long mask, int numeric)
+netname(in_addr_t in, u_long mask, int numeric)
 {
 	char *cp = NULL;
 	static char line[MAXHOSTNAMELEN];
 	struct netent *np = NULL;
 	in_addr_t i;
 
-	i = ntohl(*in);
-	if (!numeric && i != 0) {
+	i = ntohl(in);
+	if (!numeric && i) {
 		np = getnetbyaddr(i >> NSHIFT(mask), PF_INET);
 		if (np != NULL) {
 			cp = np->n_name;


More information about the p4-projects mailing list