PERFORCE change 165231 for review
Gabor Pali
pgj at FreeBSD.org
Fri Jun 26 03:42:48 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=165231
Change 165231 by pgj at 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_ */
More information about the p4-projects
mailing list