Date: Sat, 13 Jun 2009 22:39:36 GMT From: Gabor Pali <pgj@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 164301 for review Message-ID: <200906132239.n5DMdax3085906@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=164301 Change 164301 by pgj@petymeg-current on 2009/06/13 22:39:26 - Add a simple version of addr_type (inside socket_type) as an abstraction for addresses connected to a connection (max. 2 addresses per socket at the moment). - Use addr_type for unix domain sockets and inet socket, however the latter one needs some work (no support for getting address in numeric format yet). Affected files ... .. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat.c#26 edit .. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat.h#17 edit .. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_internal.h#15 edit .. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_util.c#17 edit .. //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/inet.c#14 edit .. //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/unix.c#13 edit Differences ... ==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat.c#26 (text+ko) ==== @@ -10,6 +10,8 @@ #include <err.h> #include <errno.h> #include <kvm.h> +#include <libutil.h> +#include <netdb.h> #include <netinet/in.h> #include <netinet/in_pcb.h> #include <netinet/tcp_var.h> @@ -20,6 +22,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <unistd.h> #include "netstat.h" #include "netstat_internal.h" @@ -50,6 +53,14 @@ static void extract_xunpcb_data(struct xunpcb *, struct socket_type *); static void extract_inet_data(struct tcpcb *, struct inpcb *, struct xsocket *, struct socket_type *); + +static char ntop_buf[INET6_ADDRSTRLEN]; + +static struct addr_type *extract_inet_address(int type, const char *proto, + struct in_addr *in, u_short port, int anonport); +static struct addr_type *extract_inet6_address(int type, const char *proto, + struct in6_addr *in, u_short port); + static int netstat_local_sockets(int, struct socket_type_list *, kvm_t *, struct nlist *, int); static int netstat_inet_sockets(int, int, struct socket_type_list *, @@ -557,6 +568,7 @@ extract_xunpcb_data(struct xunpcb *xpcb, struct socket_type *stp) { struct sockaddr_un *sa; + char address[1024]; strlcpy(stp->st_extname, stp->st_name, SOCKTYPE_MAXNAME); stp->st_qlen = xpcb->xu_socket.so_qlen; @@ -582,13 +594,17 @@ stp->st_refs = (u_long)LIST_FIRST(&xpcb->xu_unp.unp_refs); stp->st_reflink = (u_long)LIST_NEXT(&xpcb->xu_unp, unp_reflink); stp->st_flags = SOCKTYPE_VNODE | SOCKTYPE_CONN | SOCKTYPE_REFS; + stp->st_addrcnt = 0; if (xpcb->xu_unp.unp_addr) { sa = (struct sockaddr_un *)&xpcb->xu_addr; - sprintf(stp->st_address, "%.*s", + sprintf(address, "%.*s", (int)(sa->sun_len - offsetof(struct sockaddr_un, sun_path)), sa->sun_path); - } else { - stp->st_address[0] = '\0'; + stp->st_address[stp->st_addrcnt] = + _netstat_at_allocate(NETSTAT_ADDRTYPE_LOCAL, address, NULL); + stp->st_address[stp->st_addrcnt]->at_port = 0; + strcpy(stp->st_address[stp->st_addrcnt]->at_portname, "*"); + stp->st_addrcnt += 1; } stp->st_tcpstate[0] = '\0'; } @@ -623,10 +639,7 @@ stp->st_refs = (u_long)0; stp->st_reflink = (u_long)0; stp->st_flags = 0; - /* XXX: Remove this. */ - stp->XXX_inpcb = *inp; - /* XXX: address is missing. */ - stp->st_address[0] = '\0'; + stp->st_addrcnt = 0; if (tp != NULL) { if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES) sprintf(stp->st_tcpstate, "%d", tp->t_state); @@ -654,4 +667,132 @@ vchar = ((inp->inp_vflag & INP_IPV4) != 0) ? "4 " : " "; sprintf(stp->st_extname, "%-3.3s%-2.2s", stp->st_name, vchar); + /* local address */ + if (inp->inp_vflag & INP_IPV4) { + stp->st_address[stp->st_addrcnt] = + extract_inet_address(NETSTAT_ADDRTYPE_INET_LOCAL, + stp->st_name, &inp->inp_laddr, inp->inp_lport, + inp->inp_vflag & INP_ANONPORT); + } +#ifdef INET6 + else if (inp->inp_vflag & INP_IPV6) { + stp->st_address[stp->st_addrcnt] = + extract_inet6_address(NETSTAT_ADDRTYPE_INET6_LOCAL, + stp->st_name, &inp->in6p_laddr, inp->inp_lport); + } +#endif + stp->st_addrcnt += 1; + /* foreign address */ + if (inp->inp_vflag & INP_IPV6) { + stp->st_address[stp->st_addrcnt] = + extract_inet_address(NETSTAT_ADDRTYPE_INET_FOREIGN, + stp->st_name, &inp->inp_faddr, inp->inp_fport, + inp->inp_vflag & INP_ANONPORT); + } +#ifdef INET6 + else if (inp->inp_vflag & INP_IPV6) { + stp->st_address[stp->st_addrcnt] = + extract_inet6_address(NETSTAT_ADDRTYPE_INET6_FOREIGN, + stp->st_name, &inp->in6p_faddr, inp->inp_fport); + } +#endif + stp->st_addrcnt += 1; +} + +struct addr_type * +extract_inet_address(int type, const char *proto, struct in_addr *in, + u_short port, int anonport) +{ + struct addr_type *result; + char address[256]; + struct hostent *hp; + struct netent *np; + struct servent *sp = NULL; + int net, lna; + char *cp; + + cp = NULL; + if (in->s_addr != INADDR_ANY) { + net = inet_netof(*in); + lna = inet_lnaof(*in); + + if (lna == INADDR_ANY) { + np = getnetbyaddr(net, AF_INET); + if (np != NULL) + cp = np->n_name; + } + if (cp == NULL) { + hp = gethostbyaddr((char *)in, sizeof(*in), AF_INET); + if (hp != NULL) { + cp = hp->h_name; + trimdomain(cp, strlen(cp)); + } + } + } + if (in->s_addr == INADDR_ANY) + strcpy(address, "*"); + else if (cp) { + strlcpy(address, cp, sizeof(address)); + } else { + in->s_addr = ntohl(in->s_addr); +#define C(x) ((u_int)((x) & 0xff)) + sprintf(address, "%u.%u.%u.%u", C(in->s_addr >> 24), + C(in->s_addr >> 16), C(in->s_addr >> 8), + C(in->s_addr)); + } + result = _netstat_at_allocate(type, address, NULL); + result->at_port = port; + sp = getservbyport((int)port, proto); + if ((sp != NULL || port == 0) && !anonport) + sprintf(result->at_portname, "%.15s", sp ? sp->s_name : "*"); + else + sprintf(result->at_portname, "%d", ntohs(port)); + + return (result); +#undef C +} + +struct addr_type * +extract_inet6_address(int type, const char *proto, struct in6_addr *in, + u_short port) +{ + struct addr_type *result; + char address[256], domain[MAXHOSTNAMELEN]; + struct hostent *hp; + struct servent *sp = NULL; + char *cp; + + if (gethostname(domain, MAXHOSTNAMELEN) == 0 && + (cp = index(domain, '.'))) + strcpy(domain, cp + 1); + else + domain[0] = '\0'; + cp = NULL; + if (!IN6_IS_ADDR_UNSPECIFIED(in)) { + hp = gethostbyaddr((char *)in, sizeof(*in), AF_INET6); + if (hp != NULL) { + if ((cp = index(hp->h_name, '.')) && + !strcmp(cp + 1, domain)) + *cp = '\0'; + cp = hp->h_name; + } + } + if (IN6_IS_ADDR_UNSPECIFIED(in)) + strcpy(address, "*"); + else if (cp) + strcpy(address, cp); + else + sprintf(address, "%s", + inet_ntop(AF_INET6, (void *)in, ntop_buf, + sizeof(ntop_buf))); + + result = _netstat_at_allocate(type, address, NULL); + result->at_port = port; + sp = getservbyport((int)port, proto); + if (sp != NULL || port == 0) + sprintf(result->at_portname, "%.15s", sp ? sp->s_name : "*"); + else + sprintf(result->at_portname, "%d", ntohs(port)); + + return (result); } ==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat.h#17 (text+ko) ==== @@ -9,6 +9,7 @@ #define SOCKTYPE_MAXNAME 32 #define SOCKTYPE_MAXADDR SOCK_MAXADDRLEN +#define SOCKTYPE_MAXADDRCNT 2 #define NETSTAT_ERROR_UNDEFINED 0 #define NETSTAT_ERROR_NOMEMORY 1 @@ -26,6 +27,8 @@ struct socket_type_list; struct socket_type_iterator; +struct addr_type; + __BEGIN_DECLS const char *netstat_strerror(int); @@ -49,6 +52,7 @@ void netstat_sti_free(struct socket_type_iterator *iterator); void netstat_st_free(struct socket_type *stp); +void netstat_at_free(struct addr_type *atp); int netstat_socket(int domain, int type, int protocol, struct socket_type_list *, int flags, void *kvm_handle); @@ -81,10 +85,17 @@ u_long netstat_st_get_conn(const struct socket_type *stp); u_long netstat_st_get_refs(const struct socket_type *stp); u_long netstat_st_get_reflink(const struct socket_type *stp); -const char *netstat_st_get_address(const struct socket_type *stp); const char *netstat_st_get_tcpstate(const struct socket_type *stp); -/* XXX: Remove this hacks. */ -struct inpcb XXX_netstat_st_get_inpcb(const struct socket_type *stp); +/* Addresses: */ +int netstat_st_get_addrcnt(const struct socket_type *stp); +struct addr_type *netstat_st_get_address(const struct socket_type *stp, + int index); + +const char *netstat_at_get_name(const struct addr_type *atp); +void netstat_at_get_address(const struct addr_type *atp, + void *addr); +u_short netstat_at_get_port(const struct addr_type *atp); +const char *netstat_at_get_portname(const struct addr_type *atp); __END_DECLS #endif /* !_NETSTAT_H_ */ ==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_internal.h#15 (text+ko) ==== @@ -13,15 +13,28 @@ #include <netinet/in_pcb.h> #include <netinet/tcp_var.h> -/* XXX: not used yet */ +#include "netstat.h" + /* Address type: * local, foreign, node (Netgraph), raw (domain) */ -struct address_type { +struct addr_type { + /* XXX: this should be an enum? */ int at_type; - struct sockaddr_storage at_address; + char at_name[1024]; + void *at_address; + u_short at_port; + char at_portname[32]; }; +#define NETSTAT_ADDRTYPE_LOCAL 0 +#define NETSTAT_ADDRTYPE_INET_LOCAL 1 +#define NETSTAT_ADDRTYPE_INET_FOREIGN 2 +#define NETSTAT_ADDRTYPE_INET46_LOCAL 3 +#define NETSTAT_ADDRTYPE_INET46_FOREIGN 4 +#define NETSTAT_ADDRTYPE_INET6_LOCAL 5 +#define NETSTAT_ADDRTYPE_INET6_FOREIGN 6 + /* Socket (PCB) type: a connection. */ struct socket_type { /* Static properties. */ @@ -31,11 +44,9 @@ char st_name[SOCKTYPE_MAXNAME]; char st_extname[SOCKTYPE_MAXNAME]; -#if 0 - /* XXX: not used yet */ - struct address_type *st_address; /* address(es) */ - int st_addrcnt; /* address count */ -#endif + /* address(es) */ + struct addr_type *st_address[SOCKTYPE_MAXADDRCNT]; + int st_addrcnt; /* address count */ u_int st_snd_cc; /* actual chars in the send buffer */ u_int st_snd_mcnt; @@ -60,12 +71,8 @@ u_long st_conn; /* control block of connected socket */ u_long st_refs; /* referencing socket linked list */ u_long st_reflink; /* link in references list */ - char st_address[SOCKTYPE_MAXADDR]; char st_tcpstate[16]; - /* XXX: Removables. */ - struct inpcb XXX_inpcb; - /* list of types */ LIST_ENTRY(socket_type) st_list; }; @@ -96,5 +103,8 @@ const char *name); void _netstat_st_reset_stats(struct socket_type *list); +struct addr_type *_netstat_at_allocate(int type, const char *name, + void *address); + int sotoxsocket(kvm_t * kvm, struct socket *so, struct xsocket *xso); #endif /* !_NETSTAT_INTERNAL_H_ */ ==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_util.c#17 (text+ko) ==== @@ -155,6 +155,10 @@ void netstat_st_free(struct socket_type *stp) { + int i; + + for (i = 0; i < stp->st_addrcnt; i++) + netstat_at_free(stp->st_address[i]); free(stp); } @@ -285,6 +289,28 @@ free(iterator); } +/* Address type */ +struct addr_type * +_netstat_at_allocate(int type, const char *name, void __unused *address) +{ + struct addr_type *atp; + + atp = malloc(sizeof(*atp)); + if (atp == NULL) + return (NULL); + + bzero(atp, sizeof(*atp)); + atp->at_type = type; + strlcpy(atp->at_name, name, 1024); + return (atp); +} + +void +netstat_at_free(struct addr_type *atp) +{ + free(atp); +} + /* Accessor functions. */ int netstat_st_get_family(const struct socket_type *stp) @@ -443,20 +469,55 @@ } const char * -netstat_st_get_address(const struct socket_type *stp) +netstat_st_get_tcpstate(const struct socket_type *stp) +{ + return (stp->st_tcpstate); +} + +int +netstat_st_get_addrcnt(const struct socket_type *stp) +{ + + return (stp->st_addrcnt); +} + +struct addr_type * +netstat_st_get_address(const struct socket_type *stp, + int index) { - return (stp->st_address); + struct addr_type *result = NULL; + + if (0 <= index && index < stp->st_addrcnt) { + result = (struct addr_type *)malloc(sizeof(struct addr_type)); + if (result != NULL) { + memcpy(result, stp->st_address[index], + sizeof(struct addr_type)); + } + } + + return (result); } const char * -netstat_st_get_tcpstate(const struct socket_type *stp) +netstat_at_get_name(const struct addr_type *atp) +{ + return (atp->at_name); +} + +void +netstat_at_get_address(const struct addr_type *atp, void *addr) +{ + /* XXX: stub */ +} + +u_short +netstat_at_get_port(const struct addr_type *atp) { - return (stp->st_tcpstate); + return (atp->at_port); } -/* XXX: Remove this hacks. */ -struct inpcb -XXX_netstat_st_get_inpcb(const struct socket_type *stp) +const char * +netstat_at_get_portname(const struct addr_type *atp) { - return (stp->XXX_inpcb); + return (atp->at_portname); } ==== //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/inet.c#14 (text+ko) ==== @@ -95,6 +95,8 @@ #ifdef INET6 static int udp_done, tcp_done; #endif /* INET6 */ +void addr_print(const struct addr_type *atp, const char *proto, + int numeric); /* * Print a summary of connections related to an Internet @@ -157,9 +159,8 @@ { static int first = 1; char buf1[15]; - struct inpcb inp; + struct addr_type *laddr, *faddr; - inp = XXX_netstat_st_get_inpcb(stp); if (first) { if (!Lflag) { printf("Active Internet connections"); @@ -206,66 +207,16 @@ printf("%6u %6u ", netstat_st_get_rcv_cc(stp), netstat_st_get_snd_cc(stp)); } - if (numeric_port) { - if (inp.inp_vflag & INP_IPV4) { - inetprint(&inp.inp_laddr, (int)inp.inp_lport, - netstat_st_get_name(stp), 1); - if (!Lflag) - inetprint(&inp.inp_faddr, - (int)inp.inp_fport, - netstat_st_get_name(stp), 1); - } -#ifdef INET6 - else if (inp.inp_vflag & INP_IPV6) { - inet6print(&inp.in6p_laddr, - (int)inp.inp_lport, netstat_st_get_name(stp), 1); - if (!Lflag) - inet6print(&inp.in6p_faddr, - (int)inp.inp_fport, - netstat_st_get_name(stp), 1); - } /* else nothing printed now */ -#endif /* INET6 */ - } else if (inp.inp_flags & INP_ANONPORT) { - if (inp.inp_vflag & INP_IPV4) { - inetprint(&inp.inp_laddr, (int)inp.inp_lport, - netstat_st_get_name(stp), 1); - if (!Lflag) - inetprint(&inp.inp_faddr, - (int)inp.inp_fport, - netstat_st_get_name(stp), 0); - } -#ifdef INET6 - else if (inp.inp_vflag & INP_IPV6) { - inet6print(&inp.in6p_laddr, - (int)inp.inp_lport, netstat_st_get_name(stp), 1); - if (!Lflag) - inet6print(&inp.in6p_faddr, - (int)inp.inp_fport, - netstat_st_get_name(stp), 0); - } /* else nothing printed now */ -#endif /* INET6 */ - } else { - if (inp.inp_vflag & INP_IPV4) { - inetprint(&inp.inp_laddr, (int)inp.inp_lport, - netstat_st_get_name(stp), 0); - if (!Lflag) - inetprint(&inp.inp_faddr, - (int)inp.inp_fport, - netstat_st_get_name(stp), - inp.inp_lport != inp.inp_fport); - } -#ifdef INET6 - else if (inp.inp_vflag & INP_IPV6) { - inet6print(&inp.in6p_laddr, - (int)inp.inp_lport, netstat_st_get_name(stp), 0); - if (!Lflag) - inet6print(&inp.in6p_faddr, - (int)inp.inp_fport, - netstat_st_get_name(stp), - inp.inp_lport != inp.inp_fport); - } /* else nothing printed now */ -#endif /* INET6 */ + laddr = netstat_st_get_address(stp, 0); /* local */ + faddr = netstat_st_get_address(stp, 1); /* foreign */ + addr_print(laddr, netstat_st_get_name(stp), numeric_port); + if (!Lflag) { + addr_print(faddr, netstat_st_get_name(stp), + numeric_port || + netstat_at_get_port(laddr) != netstat_at_get_port(faddr)); } + netstat_at_free(laddr); + netstat_at_free(faddr); if (xflag) { if (Lflag) printf("%21s", " "); @@ -971,3 +922,18 @@ } return (line); } + +void +addr_print(const struct addr_type *atp, const char *proto, int numeric) +{ + int width; + char line[80], *cp; + + /* XXX: Respect numeric for getting name. */ + sprintf(line, "%.*s", Wflag ? 39 : (Aflag && !numeric) ? 12 : 16, + netstat_at_get_name(atp)); + cp = index(line, '\0'); + sprintf(cp, "%.15s ", netstat_at_get_portname(atp)); + width = Wflag ? 45 : Aflag ? 18 : 22; + printf("%-*.*s", width, width, line); +} ==== //depot/projects/soc2009/pgj_libstat/src/usr.bin/netstat/unix.c#13 (text+ko) ==== @@ -115,6 +115,7 @@ { static int first = 1; char buf1[15]; + struct addr_type *addr; if (first && !Lflag) { printf("Active UNIX domain sockets\n"); @@ -139,5 +140,10 @@ netstat_st_get_vnode(stp), netstat_st_get_conn(stp), netstat_st_get_refs(stp), netstat_st_get_reflink(stp)); } - printf(" %s\n", netstat_st_get_address(stp)); + if (netstat_st_get_addrcnt(stp) > 0) { + addr = netstat_st_get_address(stp, 0); + printf(" %s", netstat_at_get_name(addr)); + netstat_at_free(addr); + } + putchar('\n'); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200906132239.n5DMdax3085906>