PERFORCE change 166312 for review

Gabor Pali pgj at FreeBSD.org
Mon Jul 20 17:15:37 UTC 2009


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

Change 166312 by pgj at petymeg-current on 2009/07/20 17:15:00

	Introduce a very initial version of netstat_interface() -- a function
	for listing network interfaces.

Affected files ...

.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/Makefile#11 edit
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat.h#29 edit
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_if.c#1 add
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_internal.h#27 edit
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_util.c#32 edit

Differences ...

==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/Makefile#11 (text+ko) ====

@@ -3,7 +3,7 @@
 .include <bsd.own.mk>
 
 LIB=	netstat
-SRCS=	netstat_socket.c netstat_mbuf.c netstat_util.c
+SRCS=	netstat_socket.c netstat_mbuf.c netstat_if.c netstat_util.c
 
 INCS=	netstat.h
 

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

@@ -38,6 +38,9 @@
 #define SOCKTYPE_MAXADDR	    SOCK_MAXADDRLEN
 #define SOCKTYPE_MAXADDRCNT	    2
 
+#define IFTYPE_MAXNAME		    32
+#define	IFTYPE_MAXADDRCNT	    8
+
 #define NETSTAT_ERROR_UNDEFINED	    0
 #define NETSTAT_ERROR_NOMEMORY	    1
 #define NETSTAT_ERROR_VERSION	    2
@@ -53,6 +56,13 @@
 /* netstat_mbuf(): */
 #define NETSTAT_MBUF_KVM	    0x01
 
+/* netstat_interface(): */
+#define NETSTAT_INTERFACE_KVM	    0x01
+#define NETSTAT_INTERFACE_ALL	    0x02
+
+/* Testing flags for interface_type: */
+#define NETSTAT_IF_UP		    0x01	/* interface is up */
+
 /* Enum for TCP states: */
 enum tcp_state {
     tcps_Closed,
@@ -71,6 +81,13 @@
     tcps_MAX,
 };
 
+enum intfaddr_layer {
+    layer_None,
+    layer_Link,
+    layer_Network,
+    layer_MAX,
+};
+
 struct socket_type;
 struct sockaddr_type;
 struct sockbuf_type;
@@ -80,7 +97,14 @@
 
 struct mbuf_type;
 
+struct interface_type;
+struct intfaddr_type;
+struct face_type;
+
+struct interface_type_list;
+struct interface_type_iterator;
 
+
 __BEGIN_DECLS
 const char		    *netstat_strerror(int);
 
@@ -180,4 +204,40 @@
 u_int64_t   netstat_bt_get_size(const struct buffer_type *);
 u_int64_t   netstat_bt_get_limit(const struct buffer_type *);
 
+/* Interfaces: */
+struct interface_type_list  *netstat_itl_alloc(void);
+void	netstat_itl_free(struct interface_type_list *);
+int	netstat_itl_geterror(const struct interface_type_list *);
+int	netstat_itl_length(const struct interface_type_list *);
+
+int	netstat_iti_alloc(struct interface_type_list *list,
+			struct interface_type_iterator **iterator);
+const struct interface_type *netstat_iti_first(struct interface_type_iterator *);
+const struct interface_type *netstat_iti_next(struct interface_type_iterator *);
+void	netstat_iti_free(struct interface_type_iterator *iterator);
+
+void	netstat_it_free(struct interface_type *);
+void	netstat_iat_free(struct intfaddr_type *);
+
+int	netstat_interface(const char *name, int domain,
+	    struct interface_type_list *list, int flags, void *kvm_handle);
+
+const char  *netstat_it_get_name(const struct interface_type *);
+u_int64_t   netstat_it_get_mtu(const struct interface_type *);
+int	    netstat_it_get_flags(const struct interface_type *);
+u_int64_t   netstat_it_get_collisions(const struct interface_type *);
+u_int64_t   netstat_it_get_drops(const struct interface_type *);
+u_int16_t   netstat_it_get_timer(const struct interface_type *);
+const struct face_type	*netstat_it_get_in(const struct interface_type *);
+const struct face_type	*netstat_it_get_out(const struct interface_type *);
+
+u_int64_t   netstat_ft_get_packets(const struct face_type *);
+u_int64_t   netstat_ft_get_bytes(const struct face_type *);
+u_int64_t   netstat_ft_get_mcasts(const struct face_type *);
+u_int64_t   netstat_ft_get_errors(const struct face_type *);
+
+enum intfaddr_layer netstat_iat_get_layer(const struct intfaddr_type *);
+
+/* Interface addresses: */
+
 #endif /* !_NETSTAT_H_ */

==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_internal.h#27 (text+ko) ====

@@ -83,6 +83,9 @@
 #define NETSTAT_ADDRTYPE_INET6_LOCAL	    5
 #define NETSTAT_ADDRTYPE_INET6_FOREIGN	    6
 
+#define NETSTAT_IF_IFADDR		    0
+#define NETSTAT_IF_IFMULTIADDR		    1
+
 /* Socket (PCB) type: a connection. */
 struct socket_type {
 	/* Static properties. */
@@ -170,6 +173,71 @@
 	int		    mbt_error;
 };
 
+/* General interface statistics. */
+struct face_type {
+	u_int64_t	    ft_packets;
+	u_int64_t	    ft_bytes;
+	u_int64_t	    ft_mcasts;
+	u_int64_t	    ft_errors;
+};
+
+/* Interface address. */
+struct intfaddr_type {
+	int			iat_family; /* protocol family */
+	enum intfaddr_layer	iat_layer;
+	int			iat_type; /* ifa, ifma */
+	char			iat_name[20];
+	char			iat_subnet[16];
+	void			*iat_address; /* raw address */
+	void			*iat_network; /* raw network */
+	int			iat_address_len;
+	u_int64_t		iat_network_mask;
+	u_int32_t		iat_refcount; /* ifma */
+	/* for network-layer addresses: */
+	u_int64_t		iat_opackets;
+	u_int64_t		iat_ipackets;
+	u_int64_t		iat_obytes;
+	u_int64_t		iat_ibytes;
+};
+
+/* Interface. */
+struct interface_type {
+	int		    it_type; /* ethernet, tokenring, etc. */
+	int		    it_physical; /* AUI, Thinnet, 10base-T, etc. */
+	char		    it_name[IFTYPE_MAXNAME];
+	u_int64_t	    it_mtu; /* maximum transmission unit */
+	int		    it_flags;
+
+	struct face_type    it_in;
+	struct face_type    it_out;
+
+	u_int64_t	    it_collisions;
+	u_int64_t	    it_drops;
+	u_int16_t	    it_timer; /* time until watchdog called */
+
+	/* Addresses. */
+	struct intfaddr_type	*it_address[IFTYPE_MAXADDRCNT];
+	int			it_addrcnt;
+
+	/* Multicast addresses. */
+	struct intfaddr_type	*it_maddress[IFTYPE_MAXADDRCNT];
+	int			it_maddrcnt;
+
+	LIST_ENTRY(interface_type)  it_list;
+};
+
+struct interface_type_list {
+	LIST_HEAD(, interface_type) itl_list;
+	int			    itl_length;
+	int			    itl_error;
+};
+
+struct interface_type_iterator {
+	struct interface_type_list  *iti_list;
+	struct interface_type	    *iti_first;
+	struct interface_type	    *iti_next;
+};
+
 int kread_data(kvm_t *kvm, u_long kvm_pointer, void *address, size_t size);
 int kread_string(kvm_t *kvm, u_long kvm_pointer, char *buffer, int buflen);
 
@@ -185,4 +253,20 @@
 void		    _netstat_sat_resolve_portname(struct sockaddr_type *addr);
 
 int	sotoxsocket(kvm_t * kvm, struct socket *so, struct xsocket *xso);
+
+void _netstat_itl_empty(struct interface_type_list *list);
+struct interface_type *_netstat_it_allocate(struct interface_type_list *list,
+	    int type, int physical, const char *name);
+struct intfaddr_type *_netstat_iat_allocate(int family, int type);
+
+
+/* XXX: merge these into a common address resolution routine. */
+const char	*routename(in_addr_t *in, int numeric);
+const char	*netname(in_addr_t *in, u_long mask, int numeric);
+#ifdef INET6
+const char	*routename6(struct sockaddr_in6 *in6, int numeric);
+const char	*netname6(struct sockaddr_in6 *in6, struct in6_addr *mask,
+		    int numeric);
+#endif
+
 #endif /* !_NETSTAT_INTERNAL_H_ */

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

@@ -31,7 +31,14 @@
 #include <sys/types.h>
 #include <sys/protosw.h>
 #include <sys/domain.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
 #include <kvm.h>
+#include <libutil.h>
+#include <netdb.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -708,3 +715,397 @@
 {
 	return (btp->bt_limit);
 }
+
+struct interface_type *
+_netstat_it_allocate(struct interface_type_list *list, int type, int physical,
+    const char *name)
+{
+	struct interface_type *itp;
+
+	itp = malloc(sizeof(*itp));
+	if (itp == NULL)
+		return (NULL);
+
+	bzero(itp, sizeof(*itp));
+
+	itp->it_type = type;
+	itp->it_physical = physical;
+	strlcpy(itp->it_name, name, IFTYPE_MAXNAME);
+	LIST_INSERT_HEAD(&list->itl_list, itp, it_list);
+	list->itl_length += 1;
+	return (itp);
+}
+
+struct intfaddr_type *
+_netstat_iat_allocate(int family, int type)
+{
+	struct intfaddr_type *iatp;
+
+	iatp = malloc(sizeof(*iatp));
+	if (iatp == NULL)
+		return (NULL);
+
+	bzero(iatp, sizeof(*iatp));
+	iatp->iat_family = family;
+	iatp->iat_type = type;
+	iatp->iat_layer = layer_None;
+	return (iatp);
+}
+
+struct interface_type_list *
+netstat_itl_alloc(void)
+{
+	struct interface_type_list *itlp;
+
+	itlp = malloc(sizeof(*itlp));
+	if (itlp == NULL)
+		return (NULL);
+
+	LIST_INIT(&itlp->itl_list);
+	itlp->itl_error = NETSTAT_ERROR_UNDEFINED;
+	itlp->itl_length = 0;
+	return (itlp);
+}
+
+void
+_netstat_itl_empty(struct interface_type_list *list)
+{
+	struct interface_type	*itp;
+
+	while ((itp = LIST_FIRST(&list->itl_list))) {
+		LIST_REMOVE(itp, it_list);
+		netstat_it_free(itp);
+	}
+
+	list->itl_length = 0;
+}
+
+void
+netstat_itl_free(struct interface_type_list *list)
+{
+	_netstat_itl_empty(list);
+	free(list);
+}
+
+int
+netstat_itl_geterror(const struct interface_type_list *list)
+{
+	return (list->itl_error);
+}
+
+int
+netstat_itl_length(const struct interface_type_list *list)
+{
+	return (list->itl_length);
+}
+
+int
+netstat_iti_alloc(struct interface_type_list *list,
+    struct interface_type_iterator **iterator)
+{
+	struct interface_type_iterator *itp;
+
+	itp = malloc(sizeof(*itp));
+	if (itp == NULL)
+		return (-1);
+
+	bzero(itp, sizeof(*itp));
+
+	itp->iti_list = list;
+	itp->iti_first = LIST_FIRST(&list->itl_list);
+	if (itp->iti_first != NULL)
+		itp->iti_next = LIST_NEXT(itp->iti_first, it_list);
+	*iterator = itp;
+	return (0);
+}
+
+const struct interface_type *
+netstat_iti_first(struct interface_type_iterator *itip)
+{
+	itip->iti_next = LIST_NEXT(itip->iti_first, it_list);
+	return (itip->iti_first);
+}
+
+const struct interface_type *
+netstat_iti_next(struct interface_type_iterator *itip)
+{
+	const struct interface_type *itp;
+
+	itp = itip->iti_next;
+	if (itip->iti_next != NULL)
+		itip->iti_next = LIST_NEXT(itip->iti_next, it_list);
+
+	return (itp);
+}
+
+void
+netstat_iti_free(struct interface_type_iterator *itip)
+{
+	free(itip);
+}
+
+void
+netstat_it_free(struct interface_type *itp)
+{
+	int i;
+
+	for (i = 0; itp->it_address[i] != NULL && i < IFTYPE_MAXADDRCNT; i++)
+		netstat_iat_free(itp->it_address[i]);
+
+	for (i = 0; itp->it_maddress[i] != NULL && i < IFTYPE_MAXADDRCNT; i++)
+		netstat_iat_free(itp->it_maddress[i]);
+
+	free(itp);
+}
+
+void
+netstat_iat_free(struct intfaddr_type *iatp)
+{
+	free(iatp->iat_address);
+	free(iatp->iat_network);
+	free(iatp);
+}
+
+const char *
+netstat_it_get_name(const struct interface_type *itp)
+{
+	return (itp->it_name);
+}
+
+u_int64_t
+netstat_it_get_mtu(const struct interface_type *itp)
+{
+	return (itp->it_mtu);
+}
+
+int
+netstat_it_get_flags(const struct interface_type *itp)
+{
+	return (itp->it_flags);
+}
+
+u_int64_t
+netstat_it_get_collisions(const struct interface_type *itp)
+{
+	return (itp->it_collisions);
+}
+
+u_int64_t
+netstat_it_get_drops(const struct interface_type *itp)
+{
+	return (itp->it_drops);
+}
+
+u_int16_t
+netstat_it_get_timer(const struct interface_type *itp)
+{
+	return (itp->it_timer);
+}
+
+const struct face_type *
+netstat_it_get_in(const struct interface_type *itp)
+{
+	return (&itp->it_in);
+}
+
+const struct face_type *
+netstat_it_get_out(const struct interface_type *itp)
+{
+	return (&itp->it_out);
+}
+
+u_int64_t
+netstat_ft_get_packets(const struct face_type *ftp)
+{
+	return (ftp->ft_packets);
+}
+
+u_int64_t
+netstat_ft_get_bytes(const struct face_type *ftp)
+{
+	return (ftp->ft_bytes);
+}
+
+u_int64_t
+netstat_ft_get_mcasts(const struct face_type *ftp)
+{
+	return (ftp->ft_mcasts);
+}
+
+u_int64_t
+netstat_ft_get_errors(const struct face_type *ftp)
+{
+	return (ftp->ft_errors);
+}
+
+enum intfaddr_layer
+netstat_iat_get_layer(const struct intfaddr_type *iatp)
+{
+	return (iatp->iat_layer);
+}
+
+const char *
+routename(in_addr_t *in, int numeric)
+{
+	char *cp;
+	static char line[MAXHOSTNAMELEN];
+	struct hostent *hp;
+	in_addr_t tin;
+
+	cp = NULL;
+	if (!numeric) {
+		hp = gethostbyaddr(in, sizeof(struct in_addr), PF_INET);
+		if (hp != NULL) {
+			cp = hp->h_name;
+			trimdomain(cp, strlen(cp));
+		}
+	}
+	if (cp != NULL) {
+		strlcpy(line, cp, sizeof(line));
+	} else {
+#define C(x)	((x) & 0xff)
+		tin = ntohl(*in);
+		sprintf(line, "%u.%u.%u.%u",
+		    C(tin >> 24), C(tin >> 16), C(tin >> 8), C(tin));
+	}
+	return (line);
+}
+
+#define NSHIFT(m) (				    \
+	(m) == IN_CLASSA_NET ? IN_CLASSA_NSHIFT :   \
+	(m) == IN_CLASSB_NET ? IN_CLASSB_NSHIFT :   \
+	(m) == IN_CLASSC_NET ? IN_CLASSC_NSHIFT :   \
+	0)
+
+static void
+domask(char *dst, in_addr_t addr __unused, u_long mask, int numeric)
+{
+	int b, i;
+
+	if (mask == 0 || (!numeric && NSHIFT(mask) != 0)) {
+		*dst = '\0';
+		return;
+	}
+	i = 0;
+	for (b = 0; b < 32; b++)
+		if (mask & (1 << b)) {
+			int bb;
+
+			i = b;
+			for (bb = b + 1; bb < 32; bb++)
+				if (!(mask & (1 << b))) {
+					i = -1; /* noncontig */
+				}
+			break;
+		}
+	if (i == -1)
+		sprintf(dst, "&0x%lx", mask);
+	else
+		sprintf(dst, "/%d", 32 - i);
+}
+
+const char *
+netname(in_addr_t *in, u_long mask, int numeric)
+{
+	char *cp = NULL;
+	static char line[MAXHOSTNAMELEN];
+	struct netent *np = NULL;
+	in_addr_t i;
+
+	i = ntohl(*in);
+	if (!numeric && i != 0) {
+		np = getnetbyaddr(i >> NSHIFT(mask), PF_INET);
+		if (np != NULL) {
+			cp = np->n_name;
+			trimdomain(cp, strlen(cp));
+		}
+	}
+	if (cp != NULL)
+		strlcpy(line, cp, sizeof(line));
+	else
+		inet_ntop(PF_INET, &in, line, sizeof(line) - 1);
+	domask(line + strlen(line), i, mask, numeric);
+	return (line);
+}
+
+#undef NSHIFT
+
+#ifdef INET6
+const char *
+routename6(struct sockaddr_in6 *in6, int numeric)
+{
+	static char line[MAXHOSTNAMELEN];
+	int flag = 0;
+	struct sockaddr_in6 in6_local;
+
+	in6_local.sin6_family = PF_INET6;
+	in6_local.sin6_len = sizeof(in6_local);
+	in6_local.sin6_addr = in6->sin6_addr;
+	in6_local.sin6_scope_id = in6->sin6_scope_id;
+
+	if (numeric)
+		flag |= NI_NUMERICHOST;
+
+	getnameinfo((struct sockaddr *)&in6_local, in6_local.sin6_len,
+	    line, sizeof(line), NULL, 0, flag);
+
+	return (line);
+}
+
+const char *
+netname6(struct sockaddr_in6 *in6, struct in6_addr *mask, int numeric)
+{
+	static char line[MAXHOSTNAMELEN];
+	u_char *p = (u_char *)mask;
+	u_char *lim;
+	int masklen, flag = 0;
+
+	if (mask) {
+		for (masklen = 0, lim = p + 16; p < lim; p++) {
+			switch (*p) {
+			case 0xff:
+				masklen += 8;
+				break;
+			case 0xfe:
+				masklen += 7;
+				break;
+			case 0xfc:
+				masklen += 6;
+				break;
+			case 0xf8:
+				masklen += 5;
+				break;
+			case 0xf0:
+				masklen += 4;
+				break;
+			case 0xe0:
+				masklen += 3;
+				break;
+			case 0xc0:
+				masklen += 2;
+				break;
+			case 0x80:
+				masklen += 1;
+				break;
+			case 0x00:
+				break;
+			}
+		}
+	}
+	else
+		masklen = 128;
+
+	if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr))
+		return ("default");
+
+	if (numeric != 0)
+		flag |= NI_NUMERICHOST;
+	getnameinfo((struct sockaddr *)in6, in6->sin6_len, line, sizeof(line),
+	    NULL, 0, flag);
+
+	if (numeric != 0)
+		sprintf(&line[strlen(line)], "/%d", masklen);
+
+	return (line);
+}
+#endif


More information about the p4-projects mailing list