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