From owner-svn-src-projects@FreeBSD.ORG Thu Jul 16 09:00:41 2009 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8EE09106564A; Thu, 16 Jul 2009 09:00:41 +0000 (UTC) (envelope-from stas@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 7C2968FC25; Thu, 16 Jul 2009 09:00:41 +0000 (UTC) (envelope-from stas@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n6G90fT9017898; Thu, 16 Jul 2009 09:00:41 GMT (envelope-from stas@svn.freebsd.org) Received: (from stas@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n6G90fti017893; Thu, 16 Jul 2009 09:00:41 GMT (envelope-from stas@svn.freebsd.org) Message-Id: <200907160900.n6G90fti017893@svn.freebsd.org> From: Stanislav Sedov Date: Thu, 16 Jul 2009 09:00:41 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r195715 - projects/libprocstat/usr.bin/fstat X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 16 Jul 2009 09:00:41 -0000 Author: stas Date: Thu Jul 16 09:00:41 2009 New Revision: 195715 URL: http://svn.freebsd.org/changeset/base/195715 Log: - Add socket support. Modified: projects/libprocstat/usr.bin/fstat/common.h projects/libprocstat/usr.bin/fstat/fstat.c projects/libprocstat/usr.bin/fstat/libprocstat.c projects/libprocstat/usr.bin/fstat/libprocstat.h Modified: projects/libprocstat/usr.bin/fstat/common.h ============================================================================== --- projects/libprocstat/usr.bin/fstat/common.h Thu Jul 16 08:27:12 2009 (r195714) +++ projects/libprocstat/usr.bin/fstat/common.h Thu Jul 16 09:00:41 2009 (r195715) @@ -36,40 +36,6 @@ #ifndef __COMMON_H__ #define __COMMON_H__ -#if 0 -struct filestat { - union { - struct { - long fsid; - long fileid; - mode_t mode; - u_long size; - dev_t rdev; - dev_t dev; - int vtype; - char *mntdir; - } vnode; -// struct pipe pipe; - dev_t ttydev; - struct { - int type; - char *domain_name; - int dom_family; - int proto; - caddr_t so_pcb; - caddr_t tcpcb; - caddr_t conntcb; - caddr_t sockaddr; -// struct socket sock; - } socket; - }; - int type; - int flags; - int fflags; - int fd; -}; -#endif - struct filestat { int fs_type; /* Descriptor type. */ int fs_flags; /* filestat specific flags. */ @@ -99,6 +65,19 @@ struct pipestat { size_t buffer_cnt; }; +struct sockstat { + int type; + int proto; + int dom_family; + caddr_t so_addr; + caddr_t so_pcb; + caddr_t inp_ppcb; + caddr_t unp_conn; + int so_snd_sb_state; + int so_rcv_sb_state; + char dname[32]; +}; + STAILQ_HEAD(filestat_list, filestat); extern int vflg; Modified: projects/libprocstat/usr.bin/fstat/fstat.c ============================================================================== --- projects/libprocstat/usr.bin/fstat/fstat.c Thu Jul 16 08:27:12 2009 (r195714) +++ projects/libprocstat/usr.bin/fstat/fstat.c Thu Jul 16 09:00:41 2009 (r195715) @@ -376,10 +376,83 @@ print_file_info(struct procstat *procsta } static void -print_socket_info(struct procstat *procstat __unused, struct filestat *fst __unused) +print_socket_info(struct procstat *procstat, struct filestat *fst) { + static const char *stypename[] = { + "unused", /* 0 */ + "stream", /* 1 */ + "dgram", /* 2 */ + "raw", /* 3 */ + "rdm", /* 4 */ + "seqpak" /* 5 */ + }; +#define STYPEMAX 5 + struct sockstat sock; + char errbuf[_POSIX2_LINE_MAX]; + static int isopen; + struct protoent *pe; + int error; + + error = procstat_get_socket_info(procstat, fst, &sock, errbuf); + if (error != 0) { + printf("* error"); + return; + } + if (sock.type > STYPEMAX) + printf("* %s ?%d", sock.dname, sock.type); + else + printf("* %s %s", sock.dname, stypename[sock.type]); - printf(" not implemented\n"); + /* + * protocol specific formatting + * + * Try to find interesting things to print. For tcp, the interesting + * thing is the address of the tcpcb, for udp and others, just the + * inpcb (socket pcb). For unix domain, its the address of the socket + * pcb and the address of the connected pcb (if connected). Otherwise + * just print the protocol number and address of the socket itself. + * The idea is not to duplicate netstat, but to make available enough + * information for further analysis. + */ + switch (sock.dom_family) { + case AF_INET: + case AF_INET6: + if (!isopen) + setprotoent(++isopen); + if ((pe = getprotobynumber(sock.proto)) != NULL) + printf(" %s", pe->p_name); + else + printf(" %d", sock.proto); + if (sock.proto == IPPROTO_TCP ) { + if (sock.inp_ppcb != 0) + printf(" %lx", (u_long)sock.inp_ppcb); + } + else if (sock.so_pcb != 0) + printf(" %lx", (u_long)sock.so_pcb); + break; + case AF_UNIX: + /* print address of pcb and connected pcb */ + if (sock.so_pcb != 0) { + printf(" %lx", (u_long)sock.so_pcb); + if (sock.unp_conn) { + char shoconn[4], *cp; + + cp = shoconn; + if (!(sock.so_rcv_sb_state & SBS_CANTRCVMORE)) + *cp++ = '<'; + *cp++ = '-'; + if (!(sock.so_snd_sb_state & SBS_CANTSENDMORE)) + *cp++ = '>'; + *cp = '\0'; + printf(" %s %lx", shoconn, + (u_long)sock.unp_conn); + } + } + break; + default: + /* print protocol number and socket address */ + printf(" %d %lx", sock.proto, (u_long)sock.so_addr); + } } static void Modified: projects/libprocstat/usr.bin/fstat/libprocstat.c ============================================================================== --- projects/libprocstat/usr.bin/fstat/libprocstat.c Thu Jul 16 08:27:12 2009 (r195714) +++ projects/libprocstat/usr.bin/fstat/libprocstat.c Thu Jul 16 09:00:41 2009 (r195715) @@ -112,6 +112,10 @@ int procstat_get_pts_info_sysctl(struct char *errbuf); int procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst, struct ptsstat *pts, char *errbuf); +int procstat_get_socket_info_sysctl(struct filestat *fst, struct sockstat *sock, + char *errbuf); +int procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst, + struct sockstat *sock, char *errbuf); static int to_filestat_flags(int flags); @@ -464,132 +468,6 @@ getmnton(kvm_t *kd, struct mount *m) return (mt->mntonname); } -void -socktrans(kvm_t *kd __unused, struct socket *sock __unused, int fd __unused, int flags __unused, struct filestat *fst __unused) -{ - -#if 0 - static const char *stypename[] = { - "unused", /* 0 */ - "stream", /* 1 */ - "dgram", /* 2 */ - "raw", /* 3 */ - "rdm", /* 4 */ - "seqpak" /* 5 */ - }; -#define STYPEMAX 5 - struct socket so; - struct protosw proto; - struct domain dom; - struct inpcb inpcb; - struct unpcb unpcb; - int len; - char dname[32]; - - bzero(fst, sizeof(*fst)); - - /* fill in socket */ - if (!kvm_read_all(kd, (unsigned long)sock, &so, - sizeof(struct socket))) { - warnx("can't read sock at %p\n", (void *)sock); - goto bad; - } - /* fill in protosw entry */ - if (!kvm_read_all(kd, (unsigned long)so.so_proto, &proto, - sizeof(struct protosw))) { - dprintf(stderr, "can't read protosw at %p", - (void *)so.so_proto); - goto bad; - } - /* fill in domain */ - if (!kvm_read_all(kd, (unsigned long)proto.pr_domain, &dom, - sizeof(struct domain))) { - dprintf(stderr, "can't read domain at %p\n", - (void *)proto.pr_domain); - goto bad; - } - if ((len = kvm_read(kd, (unsigned long)dom.dom_name, dname, - sizeof(dname) - 1)) < 0) { - dprintf(stderr, "can't read domain name at %p\n", - (void *)dom.dom_name); - dname[0] = '\0'; - } - else - dname[len] = '\0'; - - fst->sock_type = so.so_type; - fst->sock_dname = strdup(dname) - fst->sock_protocol = proto.pr_protocol; - fst->sock = sock; - fst->fflags = flags; - - /* - * protocol specific formatting - * - * Try to find interesting things to print. For tcp, the interesting - * thing is the address of the tcpcb, for udp and others, just the - * inpcb (socket pcb). For unix domain, its the address of the socket - * pcb and the address of the connected pcb (if connected). Otherwise - * just print the protocol number and address of the socket itself. - * The idea is not to duplicate netstat, but to make available enough - * information for further analysis. - */ - switch(dom.dom_family) { - case AF_INET: - case AF_INET6: - getinetproto(proto.pr_protocol); - if (proto.pr_protocol == IPPROTO_TCP ) { - if (so.so_pcb) { - if (kvm_read(kd, (u_long)so.so_pcb, - (char *)&inpcb, sizeof(struct inpcb)) - != sizeof(struct inpcb)) { - dprintf(stderr, - "can't read inpcb at %p\n", - (void *)so.so_pcb); - goto bad; - } - printf(" %lx", (u_long)inpcb.inp_ppcb); - } - } - else if (so.so_pcb) - printf(" %lx", (u_long)so.so_pcb); - break; - case AF_UNIX: - /* print address of pcb and connected pcb */ - if (so.so_pcb) { - printf(" %lx", (u_long)so.so_pcb); - if (kvm_read(kd, (u_long)so.so_pcb, (char *)&unpcb, - sizeof(struct unpcb)) != sizeof(struct unpcb)){ - dprintf(stderr, "can't read unpcb at %p\n", - (void *)so.so_pcb); - goto bad; - } - if (unpcb.unp_conn) { - char shoconn[4], *cp; - - cp = shoconn; - if (!(so.so_rcv.sb_state & SBS_CANTRCVMORE)) - *cp++ = '<'; - *cp++ = '-'; - if (!(so.so_snd.sb_state & SBS_CANTSENDMORE)) - *cp++ = '>'; - *cp = '\0'; - printf(" %s %lx", shoconn, - (u_long)unpcb.unp_conn); - } - } - break; - default: - /* print protocol number and socket address */ - printf(" %d %lx", proto.pr_protocol, (u_long)sock); - } - printf("\n"); - return; -bad: - fst->flags |= PS_FST_FLAG_ERROR; -#endif -} - int procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst, struct pipestat *pipe, char *errbuf) @@ -781,3 +659,127 @@ procstat_get_vnode_info_sysctl(struct fi snprintf(errbuf, _POSIX2_LINE_MAX, "error"); return (1); } + +int +procstat_get_socket_info(struct procstat *procstat, struct filestat *fst, + struct sockstat *sock, char *errbuf) +{ + + assert(sock); + if (procstat->type == PROCSTAT_KVM) { + return (procstat_get_socket_info_kvm(procstat->kd, fst, sock, + errbuf)); + } else if (procstat->type == PROCSTAT_SYSCTL) { + return (procstat_get_socket_info_sysctl(fst, sock, errbuf)); + } else { + warnx("unknow access method: %d", procstat->type); + snprintf(errbuf, _POSIX2_LINE_MAX, "error"); + return (1); + } +} +int +procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst, + struct sockstat *sock, char *errbuf) +{ + struct socket s; + struct protosw proto; + struct domain dom; + struct inpcb inpcb; + struct unpcb unpcb; + ssize_t len; + void *so; + + assert(kd); + assert(sock); + assert(fst); + bzero(sock, sizeof(*sock)); + so = fst->fs_typedep; + if (so == NULL) + goto fail; + sock->so_addr = (caddr_t)so; + /* fill in socket */ + if (!kvm_read_all(kd, (unsigned long)so, &s, + sizeof(struct socket))) { + warnx("can't read sock at %p", (void *)so); + goto fail; + } + /* fill in protosw entry */ + if (!kvm_read_all(kd, (unsigned long)s.so_proto, &proto, + sizeof(struct protosw))) { + warnx("can't read protosw at %p", (void *)s.so_proto); + goto fail; + } + /* fill in domain */ + if (!kvm_read_all(kd, (unsigned long)proto.pr_domain, &dom, + sizeof(struct domain))) { + warnx("can't read domain at %p", + (void *)proto.pr_domain); + goto fail; + } + if ((len = kvm_read(kd, (unsigned long)dom.dom_name, sock->dname, + sizeof(sock->dname) - 1)) < 0) { + warnx("can't read domain name at %p", (void *)dom.dom_name); + sock->dname[0] = '\0'; + } + else + sock->dname[len] = '\0'; + + /* + * Fill in known data. + */ + sock->type = s.so_type; + sock->proto = proto.pr_protocol; + sock->dom_family = dom.dom_family; + sock->so_pcb = s.so_pcb; + + /* + * Protocol specific data. + */ + switch(dom.dom_family) { + case AF_INET: + case AF_INET6: + if (proto.pr_protocol == IPPROTO_TCP ) { + if (s.so_pcb) { + if (kvm_read(kd, (u_long)s.so_pcb, + (char *)&inpcb, sizeof(struct inpcb)) + != sizeof(struct inpcb)) { + warnx("can't read inpcb at %p\n", + (void *)s.so_pcb); + } else + sock->inp_ppcb = + (caddr_t)inpcb.inp_ppcb; + } + } + break; + case AF_UNIX: + if (s.so_pcb) { + if (kvm_read(kd, (u_long)s.so_pcb, (char *)&unpcb, + sizeof(struct unpcb)) != sizeof(struct unpcb)){ + warnx("can't read unpcb at %p\n", + (void *)s.so_pcb); + } else if (unpcb.unp_conn) { + sock->so_rcv_sb_state = s.so_rcv.sb_state; + sock->so_snd_sb_state = s.so_snd.sb_state; + sock->unp_conn = (caddr_t)unpcb.unp_conn; + } + } + break; + default: + break; + } + return (0); + +fail: + snprintf(errbuf, _POSIX2_LINE_MAX, "error"); + return (1); +} + +int +procstat_get_socket_info_sysctl(struct filestat *fst, struct sockstat *sock, + char *errbuf) +{ + + warnx("not implemented: %s:%d", __FUNCTION__, __LINE__); + snprintf(errbuf, _POSIX2_LINE_MAX, "error"); + return (1); +} Modified: projects/libprocstat/usr.bin/fstat/libprocstat.h ============================================================================== --- projects/libprocstat/usr.bin/fstat/libprocstat.h Thu Jul 16 08:27:12 2009 (r195714) +++ projects/libprocstat/usr.bin/fstat/libprocstat.h Thu Jul 16 09:00:41 2009 (r195715) @@ -60,3 +60,5 @@ int procstat_get_pts_info(struct procsta struct ptsstat *pts, char *errbuf); int procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst, struct pipestat *pipe, char *errbuf); +int procstat_get_socket_info(struct procstat *procstat, struct filestat *fst, + struct sockstat *sock, char *errbuf);