From owner-p4-projects@FreeBSD.ORG Mon Jul 20 17:15:36 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 9158710656F7; Mon, 20 Jul 2009 17:15:36 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4C6AD10656F2 for ; Mon, 20 Jul 2009 17:15:36 +0000 (UTC) (envelope-from pgj@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 389908FC20 for ; Mon, 20 Jul 2009 17:15:36 +0000 (UTC) (envelope-from pgj@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n6KHFang075665 for ; Mon, 20 Jul 2009 17:15:36 GMT (envelope-from pgj@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n6KHFaV6075663 for perforce@freebsd.org; Mon, 20 Jul 2009 17:15:36 GMT (envelope-from pgj@FreeBSD.org) Date: Mon, 20 Jul 2009 17:15:36 GMT Message-Id: <200907201715.n6KHFaV6075663@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to pgj@FreeBSD.org using -f From: Gabor Pali To: Perforce Change Reviews Cc: Subject: PERFORCE change 166312 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 20 Jul 2009 17:15:37 -0000 http://perforce.freebsd.org/chv.cgi?CH=166312 Change 166312 by pgj@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 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 #include #include + +#include +#include + #include +#include +#include +#include #include #include @@ -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