Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 26 Jun 2009 03:42:45 GMT
From:      Gabor Pali <pgj@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 165231 for review
Message-ID:  <200906260342.n5Q3gjOh035845@repoman.freebsd.org>

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

Change 165231 by pgj@petymeg-current on 2009/06/26 03:42:23

	Introduce spcblist sysctl(8) variable for unix domain sockets, a
	stream format version of passing pcb lists from kernel to user
	applications.

Affected files ...

.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat.c#35 edit
.. //depot/projects/soc2009/pgj_libstat/src/sys/kern/uipc_usrreq.c#3 edit
.. //depot/projects/soc2009/pgj_libstat/src/sys/sys/unpcb.h#3 edit

Differences ...

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

@@ -51,6 +51,7 @@
     { "_tcbinfo", "_udbinfo", "_divcbinfo", "_ripcbinfo" };
 
 static void extract_xunpcb_data(struct xunpcb *, struct socket_type *);
+static void extract_unpcb_data(struct unpcb_data *, struct socket_type *);
 static void extract_inet_data(struct tcpcb *, struct inpcb *,
     struct xsocket *, struct socket_type *);
 
@@ -75,15 +76,19 @@
 net_local_pcblist_sysctl(int family, int type, struct socket_type_list *list,
     __unused int flags)
 {
-	char	*buf;
+	char	*buf, *p;
 	size_t	len;
 	char	mibvar[64];
 
-	struct	xunpgen	    *xug, *oxug;
-	struct	xunpcb	    *xunp;
+	int	    count, i;
+	unp_gen_t   gencnt;
+
+	struct	unpcb_stream *usp;
+	struct	unpcb_data *udp;
 	struct	socket_type *stp;
 
-	sprintf(mibvar, "net.local.%s.pcblist", socktype[type]);
+	/* XXX: Should "spcblist" be renamed to "pcblist"? */
+	sprintf(mibvar, "net.local.%s.spcblist", socktype[type]);
 
 	len = 0;
 	if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
@@ -100,20 +105,36 @@
 		free(buf);
 		return (-2);
 	}
+	if (len < sizeof(*usp)) {
+		list->stl_error = NETSTAT_ERROR_VERSION;
+		free(buf);
+		return (-2);
+	}
+
+	p = buf;
+	usp = (struct unpcb_stream *)p;
+	p += sizeof(*usp);
+
+	if (usp->us_version != UNPCB_STREAM_VERSION) {
+		list->stl_error = NETSTAT_ERROR_VERSION;
+		free(buf);
+		return (-1);
+	}
 
-	oxug = xug = (struct xunpgen *)buf;
-	for (xug = (struct xunpgen *)((char *)xug + xug->xug_len);
-	    xug->xug_len > sizeof(struct xunpgen);
-	    xug = (struct xunpgen *)((char *)xug + xug->xug_len)) {
-		xunp = (struct xunpcb *)xug;
+	count = usp->us_count;
+	gencnt = usp->us_gencnt;
+
+	for (i = 0; i < count; i++) {
+		udp = (struct unpcb_data *)p;
+		p += sizeof(*udp);
 		/* Keep active PCBs only. */
-		if (xunp->xu_unp.unp_gencnt <= oxug->xug_gen) {
+		if (udp->ud_gencnt <= usp->us_gencnt) {
 			stp = _netstat_st_allocate(list, family, type,
 			    socktype[type]);
-			extract_xunpcb_data(xunp, stp);
+			extract_unpcb_data(udp, stp);
 		}
 	}
-	
+
 	free(buf);
 	return (0);
 }
@@ -234,7 +255,6 @@
 
 #define KREAD(off, buf, len) do {				    \
 	if (kread(kvm, (uintptr_t)(off), (buf), (len)) != 0) {	    \
-		list->stl_error = NETSTAT_ERROR_UNDEFINED;	    \
 		return (-1);					    \
 	}							    \
 } while (0);
@@ -396,7 +416,6 @@
 #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)
@@ -404,7 +423,6 @@
 #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);						    \
 	}								    \
 } while (0)
@@ -619,6 +637,46 @@
 }
 
 void
+extract_unpcb_data(struct unpcb_data *udp, struct socket_type *stp)
+{
+	strlcpy(stp->st_extname, stp->st_name, SOCKTYPE_MAXNAME);
+	stp->st_qlen = udp->ud_qlen;
+	stp->st_incqlen = udp->ud_incqlen;
+	stp->st_qlimit = udp->ud_qlimit;
+	stp->st_snd.sbt_cc = udp->ud_snd_cc;
+	stp->st_snd.sbt_mcnt = udp->ud_snd_mcnt;
+	stp->st_snd.sbt_ccnt = udp->ud_snd_ccnt;
+	stp->st_snd.sbt_hiwat = udp->ud_snd_hiwat;
+	stp->st_snd.sbt_lowat = udp->ud_snd_lowat;
+	stp->st_snd.sbt_mbcnt = udp->ud_snd_mbcnt;
+	stp->st_snd.sbt_mbmax = udp->ud_snd_mbmax;
+	stp->st_rcv.sbt_cc = udp->ud_rcv_cc;
+	stp->st_rcv.sbt_mcnt = udp->ud_rcv_mcnt;
+	stp->st_rcv.sbt_ccnt = udp->ud_rcv_ccnt;
+	stp->st_rcv.sbt_hiwat = udp->ud_rcv_hiwat;
+	stp->st_rcv.sbt_lowat = udp->ud_rcv_lowat;
+	stp->st_rcv.sbt_mbcnt = udp->ud_rcv_mbcnt;
+	stp->st_rcv.sbt_mbmax = udp->ud_rcv_mbmax;
+	stp->st_pcb = udp->ud_pcb;
+	stp->st_vnode = udp->ud_vnode;
+	stp->st_conn = udp->ud_conn;
+	stp->st_refs = udp->ud_refs;
+	stp->st_reflink = udp->ud_reflink;
+	stp->st_flags = SOCKTYPE_VNODE | SOCKTYPE_CONN | SOCKTYPE_REFS;
+	stp->st_addrcnt = 0;
+	if (udp->ud_address_len > 0) {
+		stp->st_address[stp->st_addrcnt] =
+		    _netstat_at_allocate(stp, NETSTAT_ADDRTYPE_LOCAL,
+			udp->ud_address, NULL, 0);
+		stp->st_address[stp->st_addrcnt]->at_port = 0;
+		strcpy(stp->st_address[stp->st_addrcnt]->at_portname, "*");
+		stp->st_address[stp->st_addrcnt]->at_numeric[0] = '\0';
+		stp->st_addrcnt += 1;   
+	}
+	stp->st_tcpstate[0] = '\0';
+}
+
+void
 extract_inet_data(struct tcpcb *tp, struct inpcb *inp, struct xsocket *so,
     struct socket_type *stp)
 {

==== //depot/projects/soc2009/pgj_libstat/src/sys/kern/uipc_usrreq.c#3 (text+ko) ====

@@ -71,6 +71,7 @@
 #include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/lock.h>
+#include <sys/malloc.h>
 #include <sys/mbuf.h>
 #include <sys/mount.h>
 #include <sys/mutex.h>
@@ -79,6 +80,7 @@
 #include <sys/protosw.h>
 #include <sys/resourcevar.h>
 #include <sys/rwlock.h>
+#include <sys/sbuf.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/signalvar.h>
@@ -1485,6 +1487,125 @@
 	    (caddr_t)(long)SOCK_STREAM, 0, unp_pcblist, "S,xunpcb",
 	    "List of active local stream sockets");
 
+static int
+unp_spcblist(SYSCTL_HANDLER_ARGS)
+{
+	struct unpcb_stream us;
+	struct unpcb_data ud;
+	struct sbuf sbuf;
+	int error, i, buflen;
+	int freeunp;
+	char *buffer;
+
+	struct unpcb *unp, **unp_list;
+	struct unp_head *head;
+	struct socket *sock;
+
+	error = 0;
+	head = ((intptr_t)arg1 == SOCK_DGRAM ? &unp_dhead : &unp_shead);
+
+	bzero(&us, sizeof(us));
+	us.us_version = UNPCB_STREAM_VERSION;
+
+	UNP_LIST_LOCK();
+	us.us_gencnt = unp_gencnt;
+	us.us_count = unp_count;
+	UNP_LIST_UNLOCK();
+
+	unp_list = malloc(us.us_count * sizeof(*unp_list), M_TEMP, M_WAITOK);
+
+	UNP_LIST_LOCK();
+	for (unp = LIST_FIRST(head), i = 0; (unp != NULL) && (i < us.us_count);
+	     unp = LIST_NEXT(unp, unp_link)) {
+		UNP_PCB_LOCK(unp);
+		if (unp->unp_gencnt <= us.us_gencnt) {
+			if (cr_cansee(req->td->td_ucred,
+			    unp->unp_socket->so_cred) == 0) {
+				unp_list[i++] = unp;
+				unp->unp_refcount++;
+			}
+		}
+		UNP_PCB_UNLOCK(unp);
+	}
+	UNP_LIST_UNLOCK();
+	us.us_count = i;
+
+	buflen = sizeof(us) + us.us_count * sizeof(ud) + 1;
+	buffer = malloc(buflen, M_TEMP, M_WAITOK | M_ZERO);
+	sbuf_new(&sbuf, buffer, buflen, SBUF_FIXEDLEN);
+
+	if (sbuf_bcat(&sbuf, &us, sizeof(us)) < 0) {
+		error = ENOMEM;
+		goto out;
+	}
+
+	for (i = 0; i < us.us_count; i++) {
+		unp = unp_list[i];
+		UNP_PCB_LOCK(unp);
+		unp->unp_refcount--;
+		if (unp->unp_refcount != 0 && unp->unp_gencnt <= us.us_gencnt) {
+			bzero(&ud, sizeof(ud));
+			sock = unp->unp_socket;
+			ud.ud_gencnt = unp->unp_gencnt;
+			ud.ud_qlen = sock->so_qlen;
+			ud.ud_incqlen = sock->so_incqlen;
+			ud.ud_qlimit = sock->so_qlimit;
+			ud.ud_snd_cc = sock->so_snd.sb_cc;
+			ud.ud_snd_mcnt = sock->so_snd.sb_mcnt;
+			ud.ud_snd_ccnt = sock->so_snd.sb_ccnt;
+			ud.ud_snd_hiwat = sock->so_snd.sb_hiwat;
+			ud.ud_snd_lowat = sock->so_snd.sb_lowat;
+			ud.ud_snd_mbcnt = sock->so_snd.sb_mbcnt;
+			ud.ud_snd_mbmax = sock->so_snd.sb_mbmax;
+			ud.ud_rcv_cc = sock->so_rcv.sb_cc;
+			ud.ud_rcv_mcnt = sock->so_rcv.sb_mcnt;
+			ud.ud_rcv_ccnt = sock->so_rcv.sb_ccnt;
+			ud.ud_rcv_hiwat = sock->so_rcv.sb_hiwat;
+			ud.ud_rcv_lowat = sock->so_rcv.sb_lowat;
+			ud.ud_rcv_mbcnt = sock->so_rcv.sb_mbcnt;
+			ud.ud_rcv_mbmax = sock->so_rcv.sb_mbmax;
+			ud.ud_pcb = (u_long)sock->so_pcb;
+			ud.ud_vnode = (u_long)unp->unp_vnode;
+			ud.ud_conn = (u_long)unp->unp_conn;
+			ud.ud_refs = (u_long)LIST_FIRST(&unp->unp_refs);
+			ud.ud_reflink = (u_long)LIST_NEXT(unp, unp_reflink);
+			ud.ud_address_len = (unp->unp_addr != NULL) ?
+			    unp->unp_addr->sun_len : 0;
+			if (ud.ud_address_len > 0) {
+				bcopy(ud.ud_address, unp->unp_addr,
+				    ud.ud_address_len);
+			}
+			UNP_PCB_UNLOCK(unp);
+			if (sbuf_bcat(&sbuf, &ud, sizeof(ud)) < 0) {
+				error = ENOMEM;
+				goto uout;
+			}
+		} else {
+			freeunp = (unp->unp_refcount == 0);
+			UNP_PCB_UNLOCK(unp);
+			if (freeunp) {
+				UNP_PCB_LOCK_DESTROY(unp);
+				uma_zfree(unp_zone, unp);
+			}
+		}
+	}
+	sbuf_finish(&sbuf);
+	error = SYSCTL_OUT(req, sbuf_data(&sbuf), sbuf_len(&sbuf));
+uout:
+	free(unp_list, M_TEMP);
+out:
+	free(buffer, M_TEMP);
+	return (error);
+}
+
+SYSCTL_PROC(_net_local_dgram, OID_AUTO, spcblist, CTLFLAG_RD|CTLTYPE_STRUCT,
+	    (caddr_t)(long)SOCK_DGRAM, 0, unp_spcblist, "s,struct unpcb_data",
+	    "List of active local datagram sockets (stream)");
+
+SYSCTL_PROC(_net_local_stream, OID_AUTO, spcblist, CTLFLAG_RD|CTLTYPE_STRUCT,
+	    (caddr_t)(long)SOCK_STREAM, 0, unp_spcblist, "s,struct unpcb_data",
+	    "List of active local stream sockets (stream)");
+
 static void
 unp_shutdown(struct unpcb *unp)
 {

==== //depot/projects/soc2009/pgj_libstat/src/sys/sys/unpcb.h#3 (text+ko) ====

@@ -151,27 +151,17 @@
 
 #define UNPCB_STREAM_VERSION	0x00000001
 
-/*
- * Stream structure:
- *  (unpcb_stream) (unpcb_gen) (unpcb_data [unpcb_address]) ... (unpcb_gen)
- *
- */
-
 struct unpcb_stream {
 	u_int32_t	us_version;	/* Stream format version. */
-	u_int32_t	us_count;	/* Number of records. */
-	u_int32_t	_us_pad[2];	/* Padding. */
+	u_int32_t	us_count;
+	u_int64_t	us_gencnt;
 };
 
-struct unpcb_gen {
-	u_int64_t	ug_gen;
-	u_int64_t	ug_sogen;
-	u_int64_t	_ug_pad[6];
-};
-
 /* Exported data for user applications (not complete) */
 struct unpcb_data {
-	uint16_t	ud_address_len;	/* 0: no address associated. */
+	u_int64_t	ud_gencnt;
+	uint8_t		ud_address_len;
+	char		ud_address[104];
 	uint16_t	ud_qlen;
 	uint16_t	ud_incqlen;
 	uint16_t	ud_qlimit;
@@ -194,7 +184,6 @@
 	u_int64_t	ud_conn;
 	u_int64_t	ud_refs;
 	u_int64_t	ud_reflink;
-	uint16_t	_ud_pad[22];
 };
 
 #endif /* _SYS_UNPCB_H_ */



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