Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 12 Jun 2009 11:13:44 GMT
From:      Gabor Pali <pgj@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 164165 for review
Message-ID:  <200906121113.n5CBDi1g051450@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=164165

Change 164165 by pgj@petymeg-current on 2009/06/12 11:13:28

	- Add KVM extraction code for inet
	- Refine NPCB_### macros
	- Refine ipproto

Affected files ...

.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat.c#21 edit

Differences ...

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

@@ -55,7 +55,8 @@
     { "#0", "stream", "dgram", "raw", "rdm", "seqpacket" }; 
 
 static int
-net_local_pcblist_sysctl(int type, struct socket_type_list *list, int flags)
+net_local_pcblist_sysctl(int family, int type, struct socket_type_list *list,
+    int flags)
 {
 	char	*buf;
 	size_t	len;
@@ -90,7 +91,7 @@
 		xunp = (struct xunpcb *)xug;
 		/* Keep active PCBs only. */
 		if (xunp->xu_unp.unp_gencnt <= oxug->xug_gen) {
-			stp = _netstat_st_allocate(list, PF_LOCAL, type,
+			stp = _netstat_st_allocate(list, family, type,
 			    socktype[type]);
 			extract_xunpcb_data(xunp, stp);
 		}
@@ -100,38 +101,46 @@
 	return (0);
 }
 
-static int
-net_inet_pcblist_sysctl(int protocol, struct socket_type_list *list, int flags)
+static const char *
+ipproto(int protocol)
 {
-	char	*buf;
-	size_t	len;
-	char	mibvar[64];
-	const char *ipproto;
-
-	struct	xinpgen	    *xig, *oxig;
-	struct	tcpcb	    *tp = NULL;
-	struct	inpcb	    *inp;
-	struct	xsocket	    *so;
-
-	struct	socket_type *stp;
+	const char * result;
 
 	switch (protocol) {
 	case IPPROTO_TCP:
-		ipproto = "tcp";
+		result = "tcp";
 		break;
 	case IPPROTO_UDP:
-		ipproto = "udp";
+		result = "udp";
 		break;
 	case IPPROTO_DIVERT:
-		ipproto = "divert";
+		result = "divert";
 		break;
 	default:
 	case IPPROTO_RAW:
-		ipproto = "raw";
+		result = "raw";
 		break;
 	}
 
-	sprintf(mibvar, "net.inet.%s.pcblist", ipproto);
+	return (result);
+}
+
+static int
+net_inet_pcblist_sysctl(int family, int protocol,
+    struct socket_type_list *list, int flags)
+{
+	char	*buf;
+	size_t	len;
+	char	mibvar[64];
+
+	struct	xinpgen	    *xig, *oxig;
+	struct	tcpcb	    *tp = NULL;
+	struct	inpcb	    *inp;
+	struct	xsocket	    *so;
+
+	struct	socket_type *stp;
+
+	sprintf(mibvar, "net.inet.%s.pcblist", ipproto(protocol));
 
 	len = 0;
 	if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
@@ -191,8 +200,8 @@
 		   ))
 			continue;
 
-		stp = _netstat_st_allocate(list, PF_INET, protocol,
-		    ipproto);
+		stp = _netstat_st_allocate(list, family, protocol,
+		    ipproto(protocol));
 		extract_inet_data(tp, inp, so, stp);
 	}
 	
@@ -208,7 +217,7 @@
 } while (0);
 
 static int
-net_local_pcblist_kvm(int type, struct socket_type_list *list,
+net_local_pcblist_kvm(int family, int type, struct socket_type_list *list,
     kvm_t *kvm, struct nlist *nlistp, int flags)
 {
 	struct unp_head head;
@@ -270,7 +279,7 @@
 			list->stl_error = NETSTAT_ERROR_UNDEFINED;
 			return (-1);
 		}
-		stp = _netstat_st_allocate(list, PF_LOCAL, type,
+		stp = _netstat_st_allocate(list, family, type,
 		    socktype[type]);
 		extract_xunpcb_data(&xu, stp);
 	}
@@ -279,10 +288,83 @@
 }
 
 static int
-net_inet_pcblist_kvm(int protocol, struct socket_type_list *list,
+net_inet_pcblist_kvm(int family, int protocol, struct socket_type_list *list,
     kvm_t *kvm, struct nlist *nlistp, int flags)
 {
-	/* XXX: to be filled in. */
+	struct inpcbinfo pcbinfo;
+	struct inpcbhead listhead;
+	struct inpcb *inp;
+	struct xinpcb xi;
+	struct xinpgen xig;
+	struct xtcpcb xt;
+	struct tcpcb *tcb = NULL;
+	struct socket so;
+	struct xsocket *xso;
+	u_long off;
+
+	struct socket_type  *stp;
+
+	switch (protocol) {
+	case IPPROTO_TCP:
+		off = nlistp[X_TCBINFO].n_value;
+		break;
+	case IPPROTO_UDP:
+		off = nlistp[X_UDBINFO].n_value;
+		break;
+	case IPPROTO_DIVERT:
+		off = nlistp[X_DIVCBINFO].n_value;
+		break;
+	case IPPROTO_RAW:
+	case IPPROTO_ICMP:
+	case IPPROTO_IGMP:
+	case IPPROTO_PIM:
+		off = nlistp[X_RIPCBINFO].n_value;
+		break;
+	default:
+		list->stl_error = NETSTAT_ERROR_UNDEFINED;
+		return (-1);
+	}
+
+	KREAD(off, &pcbinfo, sizeof(pcbinfo));
+	LIST_FOREACH(inp, &listhead, inp_list) {
+		if (protocol == IPPROTO_TCP) {
+			KREAD(inp, &xt.xt_inp, sizeof(*inp));
+			inp = &xt.xt_inp;
+		} else {
+			KREAD(inp, &xi.xi_inp, sizeof(*inp));
+			inp = &xi.xi_inp;
+		}
+
+		/* Keep active PCBs only. */
+		if (inp->inp_gencnt > pcbinfo.ipi_gencnt)
+			continue;
+
+		if (protocol == IPPROTO_TCP) {
+			if (inp->inp_ppcb == NULL)
+				bzero(&xt.xt_tp, sizeof(xt.xt_tp));
+			else if (inp->inp_flags & INP_TIMEWAIT) {
+				bzero(&xt.xt_tp, sizeof(xt.xt_tp));
+				xt.xt_tp.t_state = TCPS_TIME_WAIT;
+			} else
+				KREAD(inp->inp_ppcb, &xt.xt_tp,
+				    sizeof(xt.xt_tp));
+		}
+		if (inp->inp_socket) {
+			KREAD(inp->inp_socket, &so, sizeof(so));
+			if (sotoxsocket(kvm, &so, xso) != 0) {
+				list->stl_error = NETSTAT_ERROR_UNDEFINED;
+				return (-1);
+			}
+		} else {
+			bzero(xso, sizeof(*xso));
+			if (protocol == IPPROTO_TCP)
+				xso->xso_protocol = protocol;
+		}
+		stp = _netstat_st_allocate(list, family, protocol,
+		   ipproto(protocol));
+		extract_inet_data(tcb, inp, xso, stp);
+	}
+
 	return (0);
 }
 
@@ -305,16 +387,17 @@
 		}
 	}
 
-#define NPCB_KVM(family, type, list, kvm, nl, flags) do {		    \
-	if (net_##family##_pcblist_kvm((type), (list), (kvm), (nl),	    \
+#define NPCB_KVM(proc, family, type, list, kvm, nl, flags) do {		    \
+	if (net_##proc##_pcblist_kvm((family), (type), (list), (kvm), (nl), \
 	    (flags)) != 0) {						    \
 		list->stl_error = NETSTAT_ERROR_UNDEFINED;		    \
 		return (-1);						    \
 	}								    \
 } while (0)
 
-#define NPCB_SCT(family, type, list, flags) do {			    \
-	if (net_##family##_pcblist_sysctl((type), (list), (flags)) != 0) {  \
+#define NPCB_SCT(proc, family, type, list, flags) do {			    \
+	if (net_##proc##_pcblist_sysctl((family), (type), (list),	    \
+	    (flags)) != 0) {						    \
 		list->stl_error = NETSTAT_ERROR_UNDEFINED;		    \
 		return (-1);						    \
 	}								    \
@@ -326,21 +409,24 @@
 		case SOCK_STREAM:
 		case SOCK_DGRAM:
 			if (use_kvm)
-				NPCB_KVM(local, type, list, kvm, nl, flags);
+				NPCB_KVM(local, domain, type, list, kvm, nl,
+				    flags);
 			else
 				/* Use sysctl (or something else). */
-				NPCB_SCT(local, type, list, flags);
+				NPCB_SCT(local, domain, type, list, flags);
 			break;
 		/* All PF_LOCAL */
 		case 0:
 			if (use_kvm) {
-				NPCB_KVM(local, SOCK_STREAM, list, kvm, nl,
+				NPCB_KVM(local, domain, SOCK_STREAM, list, kvm,
+				    nl, flags);
+				NPCB_KVM(local, domain, SOCK_DGRAM, list, kvm,
+				    nl, flags);
+			} else {
+				NPCB_SCT(local, domain, SOCK_STREAM, list,
 				    flags);
-				NPCB_KVM(local, SOCK_DGRAM, list, kvm, nl,
+				NPCB_SCT(local, domain, SOCK_DGRAM, list,
 				    flags);
-			} else {
-				NPCB_SCT(local, SOCK_STREAM, list, flags);
-				NPCB_SCT(local, SOCK_DGRAM, list, flags);
 			}
 			break;
 		default:
@@ -360,26 +446,31 @@
 		case IPPROTO_PIM:
 		case IPPROTO_ICMPV6:
 			if (use_kvm)
-				NPCB_KVM(inet, protocol, list, kvm, nl, flags);
+				NPCB_KVM(inet, domain, protocol, list, kvm, nl,
+				    flags);
 			else
-				NPCB_SCT(inet, protocol, list, flags);
+				NPCB_SCT(inet, domain, protocol, list, flags);
 			break;
 		/* All PF_INET */
 		case 0:
 			if (use_kvm) {
-				NPCB_KVM(inet, IPPROTO_TCP, list, kvm, nl,
+				NPCB_KVM(inet, domain, IPPROTO_TCP, list, kvm,
+				    nl, flags);
+				NPCB_KVM(inet, domain, IPPROTO_UDP, list, kvm,
+				    nl, flags);
+				NPCB_KVM(inet, domain, IPPROTO_DIVERT, list,
+				    kvm, nl, flags);
+				NPCB_KVM(inet, domain, IPPROTO_RAW, list, kvm,
+				    nl, flags);
+			} else {
+				NPCB_SCT(inet, domain, IPPROTO_TCP, list,
 				    flags);
-				NPCB_KVM(inet, IPPROTO_UDP, list, kvm, nl,
+				NPCB_SCT(inet, domain, IPPROTO_UDP, list,
 				    flags);
-				NPCB_KVM(inet, IPPROTO_DIVERT, list, kvm, nl,
+				NPCB_SCT(inet, domain, IPPROTO_DIVERT, list,
 				    flags);
-				NPCB_KVM(inet, IPPROTO_RAW, list, kvm, nl,
+				NPCB_SCT(inet, domain, IPPROTO_RAW, list,
 				    flags);
-			} else {
-				NPCB_SCT(inet, IPPROTO_TCP, list, flags);
-				NPCB_SCT(inet, IPPROTO_UDP, list, flags);
-				NPCB_SCT(inet, IPPROTO_DIVERT, list, flags);
-				NPCB_SCT(inet, IPPROTO_RAW, list, flags);
 			}
 			break;
 		default:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906121113.n5CBDi1g051450>