PERFORCE change 164301 for review

Gabor Pali pgj at FreeBSD.org
Sat Jun 13 22:39:37 UTC 2009


http://perforce.freebsd.org/chv.cgi?CH=164301

Change 164301 by pgj at 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');
 }


More information about the p4-projects mailing list