PERFORCE change 167493 for review
Gabor Pali
pgj at FreeBSD.org
Wed Aug 19 03:11:28 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=167493
Change 167493 by pgj at petymeg-current on 2009/08/19 03:10:40
- Add mroute_type for representing multicast forwarding table
entries.
- Add netstat_mroute(), a function for collecting multicast forwarding
information.
- Add code for both PF_INET and PF_INET6. Note that bandwidth meters
are not included yet.
Affected files ...
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat.h#64 edit
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_internal.h#60 edit
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_mroute.c#2 edit
.. //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_util.c#69 edit
Differences ...
==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat.h#64 (text+ko) ====
@@ -50,6 +50,7 @@
#define BPFTYPE_MAXNAME IFNAMSIZ
#define MIFTYPE_MAXNAME IFNAMSIZ
+#define MRTTYPE_MAXVIFS MAXVIFS
#define NETSTAT_ERROR_UNDEFINED 0
#define NETSTAT_ERROR_NOMEMORY 1
@@ -131,6 +132,8 @@
#define NETSTAT_MIF_SRCRT 0x02
#define NETSTAT_MIF_REGISTER 0x04
+#define NETSTAT_MROUTE_INCOMPLETE_PARENT MF6C_INCOMPLETE_PARENT
+
/* Enum for TCP states: */
enum tcp_state {
tcps_Closed,
@@ -278,6 +281,10 @@
struct mcastif_type_list;
struct mcastif_type_iterator;
+struct mroute_type;
+struct mroute_type_list;
+struct mroute_type_iterator;
+
__BEGIN_DECLS
const char *netstat_strerror(int);
const char *netstat_kvmerror(const struct session_type *);
@@ -1303,4 +1310,29 @@
u_int64_t netstat_mit_get_bytes_in(const struct mcastif_type *);
u_int64_t netstat_mit_get_bytes_out(const struct mcastif_type *);
const char *netstat_mit_get_ifname(const struct mcastif_type *);
+
+
+/* Multicast routing: */
+struct mroute_type_list *netstat_mrtl_alloc(void);
+void netstat_mrtl_free(struct mroute_type_list *);
+int netstat_mrtl_geterror(const struct mroute_type_list *);
+int netstat_mrtl_length(const struct mroute_type_list *);
+
+int netstat_mrti_alloc(struct mroute_type_list *list,
+ struct mroute_type_iterator **iterator);
+const struct mroute_type *netstat_mrti_first(struct mroute_type_iterator *);
+const struct mroute_type *netstat_mrti_next(struct mroute_type_iterator *);
+void netstat_mrti_free(struct mroute_type_iterator *);
+
+int netstat_mroute(const struct session_type *, int domain,
+ struct mroute_type_list *list, int flags);
+
+const struct routeaddr_type *netstat_mrt_get_origin(const struct mroute_type *);
+const struct routeaddr_type *netstat_mrt_get_group(const struct mroute_type *);
+u_int64_t netstat_mrt_get_packets(const struct mroute_type *);
+u_int64_t netstat_mrt_get_bytes(const struct mroute_type *);
+u_int64_t netstat_mrt_get_waitings(const struct mroute_type *);
+u_int32_t netstat_mrt_get_parent(const struct mroute_type *);
+u_int8_t netstat_mrt_get_ttl(const struct mroute_type *, int);
+int netstat_mrt_get_is_mif_set(const struct mroute_type *, u_int32_t);
#endif /* !_NETSTAT_H_ */
==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_internal.h#60 (text+ko) ====
@@ -528,6 +528,34 @@
struct mcastif_type *miti_next;
};
+
+/* Multicast route type. */
+struct mroute_type {
+ struct routeaddr_type *mrt_origin;
+ struct routeaddr_type *mrt_group;
+ u_int64_t mrt_pkt_cnt;
+ u_int64_t mrt_byte_cnt;
+ u_int64_t mrt_nstall;
+ u_int32_t mrt_parent;
+ u_int8_t mrt_ttls[MRTTYPE_MAXVIFS];
+ struct if_set mrt_ifset;
+
+ TAILQ_ENTRY(mroute_type) mrt_list;
+};
+
+struct mroute_type_list {
+ TAILQ_HEAD(, mroute_type) mrtl_list;
+ int mrtl_length;
+ int mrtl_error;
+};
+
+struct mroute_type_iterator {
+ struct mroute_type_list *mrti_list;
+ struct mroute_type *mrti_first;
+ struct mroute_type *mrti_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);
@@ -563,6 +591,13 @@
void _netstat_mit_free(struct mcastif_type *);
struct mcastif_type *_netstat_mit_allocate(struct mcastif_type_list *);
+void _netstat_mrtl_empty(struct mroute_type_list *);
+void _netstat_mrt_free(struct mroute_type *);
+struct mroute_type *_netstat_mrt_allocate(struct mroute_type_list *);
+#ifdef INET6
+int _mrt6_get_nstall_kvm(kvm_t *, struct mf6c *);
+#endif /* !INET6 */
+
struct routeaddr_type *extract_address(void *, void *, int);
const char *resolve_val2str_name(int, const struct val2str *);
/* XXX: merge these into a common address resolution routine. */
==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_mroute.c#2 (text+ko) ====
@@ -63,6 +63,15 @@
static const char *const mif_symbol[] =
{ "_viftable" };
+enum nlMRT {
+ nlMRT_mfchashtbl = 0,
+ nlMRT_mfctablesize,
+ nlMRT_MAX,
+};
+
+static const char *const mrt_symbol[] =
+ { "_mfchashtbl", "_mfctablesize" };
+
#ifdef INET6
enum nlMIF6 {
nlMIF6_mif6table = 0,
@@ -71,20 +80,36 @@
static const char *const mif6_symbol[] =
{ "_mif6table" };
+
+enum nlMRT6 {
+ nlMRT6_mf6ctable = 0,
+ nlMRT6_MAX,
+};
+
+static const char *const mrt6_symbol[] =
+ { "_mf6ctable" };
#endif /* !INET6 */
static int mif_kvm(struct mcastif_type_list *, kvm_t *, struct nlist *);
static int mif_sysctl(struct mcastif_type_list *);
+static int mrt_kvm(struct mroute_type_list *, kvm_t *, struct nlist *);
+static int mrt_sysctl(struct mroute_type_list *);
#ifdef INET6
static int mif6_kvm(struct mcastif_type_list *, kvm_t *, struct nlist *);
static int mif6_sysctl(struct mcastif_type_list *);
+static int mrt6_kvm(struct mroute_type_list *, kvm_t *, struct nlist *);
+static int mrt6_sysctl(struct mroute_type_list *);
#endif /* !INET6 */
static void extract_vif_data(int, struct vif *, struct mcastif_type *);
static void extract_svif_data(int, struct vif_data *, struct mcastif_type *);
+static void extract_mfc_data(struct mfc *, struct mroute_type *);
+static void extract_smfc_data(struct mfc_data *, struct mroute_type *);
#ifdef INET6
static void extract_mif6_data(int, struct mif6 *, struct mcastif_type *);
static void extract_smif6_data(int, struct mif6_data *, struct mcastif_type *);
+static void extract_mf6c_data(int, struct mf6c *, struct mroute_type *);
+static void extract_smf6c_data(struct mf6c_data *, struct mroute_type *);
#endif /* !INET6 */
#ifdef INET6
@@ -165,6 +190,7 @@
free(nls[i].n_name);
return (result);
}
+#undef nls_size
int
mif_kvm(struct mcastif_type_list *list, kvm_t *kvm, struct nlist *nlp)
@@ -474,5 +500,341 @@
}
#undef CNV_FLAG
+#endif /* !INET6 */
+
+
+#ifdef INET6
+#define nls_size (nlMRT_MAX + nlMRT6_MAX + 1)
+#else
+#define nls_size (nlMRT_MAX + 1)
+#endif /* !INET6 */
+
+int
+netstat_mroute(const struct session_type *session, int domain,
+ struct mroute_type_list *list, __unused int flags)
+{
+ int result, use_kvm, i;
+ struct nlist nls[nls_size];
+
+ result = -1;
+ use_kvm = session->sst_flags & NETSTAT_SESSION_KVM;
+ bzero(nls, sizeof(nls));
+
+ if (use_kvm) {
+ switch (domain) {
+ case PF_UNSPEC:
+ for (i = 0; i < nlMRT_MAX; i++)
+ nls[i].n_name = strdup(mrt_symbol[i]);
+ for (i = nlMRT_MAX; i < nls_size; i++)
+ nls[i].n_name =
+ strdup(mrt6_symbol[i - nlMRT_MAX]);
+ break;
+ case PF_INET:
+ for (i = 0; i < nlMRT_MAX; i++)
+ nls[i].n_name = strdup(mrt_symbol[i]);
+ break;
+#ifdef INET6
+ case PF_INET6:
+ for (i = 0; i < nlMRT6_MAX; i++)
+ nls[i].n_name = strdup(mrt6_symbol[i]);
+ break;
+#endif /* !INET6 */
+ default:
+ break;
+ }
+ if (kvm_nlist(session->sst_kvm, nls) < 0) {
+ list->mrtl_error = NETSTAT_ERROR_KVM;
+ goto end;
+ }
+ }
+
+ switch (domain) {
+ case PF_UNSPEC:
+ result = use_kvm ?
+ mrt_kvm(list, session->sst_kvm, nls) :
+ mrt_sysctl(list);
+ if (result < 0)
+ goto end;
+ result = use_kvm ?
+ mrt6_kvm(list, session->sst_kvm, &nls[nlMRT_MAX]) :
+ mrt6_sysctl(list);
+ break;
+ case PF_INET:
+ result = use_kvm ?
+ mrt_kvm(list, session->sst_kvm, nls) :
+ mrt_sysctl(list);
+ break;
+#ifdef INET6
+ case PF_INET6:
+ result = use_kvm ?
+ mrt6_kvm(list, session->sst_kvm, nls) :
+ mrt6_sysctl(list);
+ break;
+#endif /* !INET6 */
+ default:
+ list->mrtl_error = NETSTAT_ERROR_UNSUPPORTED;
+ break;
+ }
+
+end:
+ for (i = 0; nls[i].n_name != NULL && i < nls_size; i++)
+ free(nls[i].n_name);
+ return (result);
+}
+#undef nls_size
+
+int
+mrt_kvm(struct mroute_type_list *list, kvm_t *kvm, struct nlist *nlp)
+{
+ u_long mfctablesize, i;
+ LIST_HEAD(, mfc) *mfchashtbl;
+ struct mfc mfc, *m;
+ struct mroute_type *mrtp;
+ size_t len;
+
+ if (kread_data(kvm, (uintptr_t)nlp[nlMRT_mfctablesize].n_value,
+ &mfctablesize, sizeof(mfctablesize)) != 0) {
+ list->mrtl_error = NETSTAT_ERROR_KVM;
+ return (-1);
+ }
+
+ len = sizeof(*mfchashtbl) * mfctablesize;
+ mfchashtbl = malloc(len);
+ if (mfchashtbl == NULL) {
+ list->mrtl_error = NETSTAT_ERROR_NOMEMORY;
+ return (-1);
+ }
+
+ if (kread_data(kvm, (uintptr_t)nlp[nlMRT_mfchashtbl].n_value,
+ mfchashtbl, len) != 0) {
+ list->mrtl_error = NETSTAT_ERROR_KVM;
+ return (-1);
+ }
+
+ for (i = 0; i < mfctablesize; i++) {
+ LIST_FOREACH(m, &mfchashtbl[i], mfc_hash) {
+ if (kread_data(kvm, (uintptr_t)m, &mfc,
+ sizeof(mfc)) != 0)
+ continue;
+ mrtp = _netstat_mrt_allocate(list);
+ extract_mfc_data(&mfc, mrtp);
+ }
+ }
+
+ free(mfchashtbl);
+ return (0);
+}
+
+int
+mrt_sysctl(struct mroute_type_list *list)
+{
+ const char *mibvar = "net.inet.ip.smfctable";
+
+ struct mfc_stream *msp;
+ struct mfc_data *mdp;
+ struct mroute_type *mrtp;
+ char *buf, *p;
+ size_t len;
+ int result;
+ u_int32_t i;
+
+ result = -1;
+ len = 0;
+ if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: %s", mibvar);
+ goto out2;
+ }
+ if ((buf = malloc(len)) == 0) {
+ warnx("malloc %lu bytes", (u_long)len);
+ goto out2;
+ }
+ if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+ warn("sysctl: %s", mibvar);
+ goto out1;
+ }
+ if (len < sizeof(*msp)) {
+ list->mrtl_error = NETSTAT_ERROR_VERSION;
+ goto out1;
+ }
+
+ p = buf;
+ msp = (struct mfc_stream *)p;
+ p+= sizeof(*msp);
+
+ if (msp->ms_version != MFC_STREAM_VERSION) {
+ list->mrtl_error = NETSTAT_ERROR_VERSION;
+ goto out1;
+ }
+
+ for (i = 0; i < msp->ms_count; i++) {
+ mdp = (struct mfc_data *)p;
+ p += sizeof(*mdp);
+ mrtp = _netstat_mrt_allocate(list);
+ extract_smfc_data(mdp, mrtp);
+ }
+
+ result = 0;
+
+out1: free(buf);
+out2: return (result);
+}
+
+#ifdef INET6
+int
+mrt6_kvm(struct mroute_type_list *list, kvm_t *kvm, struct nlist *nlp)
+{
+ struct mf6c *mf6ctable[MF6CTBLSIZ], *mfcp;
+ struct mf6c mfc;
+ struct mroute_type *mrtp;
+ int i;
+ if (kread_data(kvm, (uintptr_t)nlp[nlMRT6_mf6ctable].n_value,
+ mf6ctable, sizeof(mf6ctable)) != 0) {
+ list->mrtl_error = NETSTAT_ERROR_KVM;
+ return (-1);
+ }
+
+ for (i = 0; i < MF6CTBLSIZ; ++i) {
+ for (mfcp = mf6ctable[i]; mfcp != NULL; mfcp = mfc.mf6c_next) {
+ kread_data(kvm, (uintptr_t)mfcp, &mfc, sizeof(mfc));
+ mrtp = _netstat_mrt_allocate(list);
+ extract_mf6c_data(_mrt6_get_nstall_kvm(kvm, &mfc),
+ &mfc, mrtp);
+ }
+ }
+
+ return (0);
+}
+
+int
+mrt6_sysctl(struct mroute_type_list *list)
+{
+ const char *mibvar = "net.inet6.ip6.smf6ctable";
+
+ struct mf6c_stream *msp;
+ struct mf6c_data *mdp;
+ struct mroute_type *mrtp;
+ char *buf, *p;
+ size_t len;
+ int result;
+ u_int32_t i;
+
+ result = -1;
+ len = 0;
+ if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: %s", mibvar);
+ goto out2;
+ }
+ if ((buf = malloc(len)) == 0) {
+ warnx("malloc %lu bytes", (u_long)len);
+ goto out2;
+ }
+ if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+ warn("sysctl: %s", mibvar);
+ goto out1;
+ }
+ if (len < sizeof(*msp)) {
+ list->mrtl_error = NETSTAT_ERROR_VERSION;
+ goto out1;
+ }
+
+ p = buf;
+ msp = (struct mf6c_stream *)p;
+ p+= sizeof(*msp);
+
+ if (msp->ms_version != MF6C_STREAM_VERSION) {
+ list->mrtl_error = NETSTAT_ERROR_VERSION;
+ goto out1;
+ }
+
+ for (i = 0; i < msp->ms_count; i++) {
+ mdp = (struct mf6c_data *)p;
+ p += sizeof(*mdp);
+ mrtp = _netstat_mrt_allocate(list);
+ extract_smf6c_data(mdp, mrtp);
+ }
+
+ result = 0;
+
+out1: free(buf);
+out2: return (result);
+}
+#endif /* !INET6 */
+
+void
+extract_mfc_data(struct mfc *m, struct mroute_type *mrtp)
+{
+ int i;
+ struct sockaddr_in sa_in;
+
+ bzero(&sa_in, sizeof(struct sockaddr_in));
+ sa_in.sin_len = sizeof(struct sockaddr_in);
+ sa_in.sin_family = PF_INET;
+ sa_in.sin_addr = m->mfc_origin;
+
+ mrtp->mrt_origin = extract_address(&sa_in, NULL, 0);
+ sa_in.sin_addr = m->mfc_mcastgrp;
+ mrtp->mrt_group = extract_address(&sa_in, NULL, 0);
+ mrtp->mrt_pkt_cnt = m->mfc_pkt_cnt;
+ mrtp->mrt_byte_cnt = m->mfc_byte_cnt;
+ mrtp->mrt_nstall = m->mfc_nstall;
+ mrtp->mrt_parent = m->mfc_parent;
+ for (i = 0; i < MAXVIFS; i++)
+ mrtp->mrt_ttls[i] = m->mfc_ttls[i];
+}
+
+void
+extract_smfc_data(struct mfc_data *md, struct mroute_type *mrtp)
+{
+ struct sockaddr_in sa_in;
+
+ bzero(&sa_in, sizeof(struct sockaddr_in));
+ sa_in.sin_len = sizeof(struct sockaddr_in);
+ sa_in.sin_family = PF_INET;
+ sa_in.sin_addr.s_addr = md->md_origin;
+
+ mrtp->mrt_origin = extract_address(&sa_in, NULL, 0);
+ sa_in.sin_addr.s_addr = md->md_mcastgrp;
+ mrtp->mrt_group = extract_address(&sa_in, NULL, 0);
+ mrtp->mrt_pkt_cnt = md->md_pkt_cnt;
+ mrtp->mrt_byte_cnt = md->md_byte_cnt;
+ mrtp->mrt_nstall = md->md_nstall;
+ mrtp->mrt_parent = md->md_parent;
+ bcopy(md->md_ttls, mrtp->mrt_ttls, sizeof(md->md_ttls));
+}
+
+#ifdef INET6
+void
+extract_mf6c_data(int nstall, struct mf6c *m, struct mroute_type *mrtp)
+{
+ mrtp->mrt_origin = extract_address(&m->mf6c_origin, NULL, 0);
+ mrtp->mrt_group = extract_address(&m->mf6c_mcastgrp, NULL, 0);
+ mrtp->mrt_pkt_cnt = m->mf6c_pkt_cnt;
+ mrtp->mrt_byte_cnt = m->mf6c_byte_cnt;
+ mrtp->mrt_nstall = nstall;
+ mrtp->mrt_parent = m->mf6c_parent;
+ mrtp->mrt_ifset = m->mf6c_ifset;
+}
+
+void
+extract_smf6c_data(struct mf6c_data *md, struct mroute_type *mrtp)
+{
+ struct sockaddr_in6 sa_in6;
+
+ bzero(&sa_in6, sizeof(struct sockaddr_in6));
+ sa_in6.sin6_len = sizeof(struct sockaddr_in6);
+ sa_in6.sin6_family = PF_INET6;
+ sa_in6.sin6_addr = *((struct in6_addr *)md->md_origin);
+
+ mrtp->mrt_origin = extract_address(&sa_in6, NULL, 0);
+ sa_in6.sin6_addr = *((struct in6_addr *)md->md_mcastgrp);
+ mrtp->mrt_group = extract_address(&sa_in6, NULL, 0);
+ mrtp->mrt_pkt_cnt = md->md_pkt_cnt;
+ mrtp->mrt_byte_cnt = md->md_byte_cnt;
+ mrtp->mrt_nstall = md->md_nstall;
+ mrtp->mrt_parent = md->md_parent;
+ bcopy(&md->md_ifs_bits, &mrtp->mrt_ifset, sizeof(md->md_ifs_bits));
+}
#endif /* !INET6 */
==== //depot/projects/soc2009/pgj_libstat/src/lib/libnetstat/netstat_util.c#69 (text+ko) ====
@@ -31,11 +31,18 @@
#include <sys/types.h>
#include <sys/protosw.h>
#include <sys/domain.h>
+#include <sys/param.h>
#include <net/pfkeyv2.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#ifdef INET6
+#define _KERNEL
+#include <netinet6/ip6_mroute.h>
+#undef _KERNEL
+#endif /* !INET6 */
+
#include <kvm.h>
#include <libutil.h>
#include <netdb.h>
@@ -130,6 +137,23 @@
return (0);
}
+#ifdef INET6
+int
+_mrt6_get_nstall_kvm(kvm_t *kvm, struct mf6c *m)
+{
+ int result;
+ struct rtdetq rte, *rtep;
+
+ result = 0;
+ for (rtep = m->mf6c_stall; rtep != NULL; rtep = rte.next) {
+ kread_data(kvm, (uintptr_t)rtep, &rte, sizeof(rte));
+ result++;
+ }
+
+ return (result);
+}
+#endif /* !INET6 */
+
const char *
netstat_strerror(int error)
{
@@ -2739,6 +2763,172 @@
}
+void
+_netstat_mrtl_empty(struct mroute_type_list *list)
+{
+ struct mroute_type *mrtp;
+
+ while ((mrtp = TAILQ_FIRST(&list->mrtl_list)) ) {
+ TAILQ_REMOVE(&list->mrtl_list, mrtp, mrt_list);
+ _netstat_mrt_free(mrtp);
+ }
+
+ list->mrtl_length = 0;
+}
+
+void
+_netstat_mrt_free(struct mroute_type *mrtp)
+{
+ _netstat_rat_free(mrtp->mrt_origin);
+ _netstat_rat_free(mrtp->mrt_group);
+ free(mrtp);
+}
+
+struct mroute_type *
+_netstat_mrt_allocate(struct mroute_type_list *list)
+{
+ struct mroute_type *mrtp;
+
+ mrtp = malloc(sizeof(*mrtp));
+ if (mrtp == NULL)
+ return (NULL);
+
+ bzero(mrtp, sizeof(*mrtp));
+ TAILQ_INSERT_TAIL(&list->mrtl_list, mrtp, mrt_list);
+ list->mrtl_length += 1;
+ return (mrtp);
+}
+
+struct mroute_type_list *
+netstat_mrtl_alloc(void)
+{
+ struct mroute_type_list *mrtlp;
+
+ mrtlp = malloc(sizeof(*mrtlp));
+ if (mrtlp == NULL)
+ return (NULL);
+
+ TAILQ_INIT(&mrtlp->mrtl_list);
+ mrtlp->mrtl_error = NETSTAT_ERROR_UNDEFINED;
+ mrtlp->mrtl_length = 0;
+ return (mrtlp);
+}
+
+void
+netstat_mrtl_free(struct mroute_type_list *mrtlp)
+{
+ _netstat_mrtl_empty(mrtlp);
+ free(mrtlp);
+}
+
+int
+netstat_mrtl_geterror(const struct mroute_type_list *mrtlp)
+{
+ return (mrtlp->mrtl_error);
+}
+
+int
+netstat_mrtl_length(const struct mroute_type_list *mrtlp)
+{
+ return (mrtlp->mrtl_length);
+}
+
+int
+netstat_mrti_alloc(struct mroute_type_list *list,
+ struct mroute_type_iterator **iterator)
+{
+ struct mroute_type_iterator *mrtip;
+
+ mrtip = malloc(sizeof(*mrtip));
+ if (mrtip == NULL)
+ return (-1);
+
+ bzero(mrtip, sizeof(*mrtip));
+ mrtip->mrti_list = list;
+ mrtip->mrti_first = TAILQ_FIRST(&list->mrtl_list);
+ if (mrtip->mrti_first != NULL)
+ mrtip->mrti_next = TAILQ_NEXT(mrtip->mrti_first, mrt_list);
+ *iterator = mrtip;
+ return (0);
+}
+
+const struct mroute_type *
+netstat_mrti_first(struct mroute_type_iterator *mrtip)
+{
+ if (mrtip->mrti_first != NULL)
+ mrtip->mrti_next = TAILQ_NEXT(mrtip->mrti_first, mrt_list);
+ return (mrtip->mrti_first);
+}
+
+const struct mroute_type *
+netstat_mrti_next(struct mroute_type_iterator *mrtip)
+{
+ const struct mroute_type *mrtp;
+
+ mrtp = mrtip->mrti_next;
+ if (mrtip->mrti_next != NULL)
+ mrtip->mrti_next = TAILQ_NEXT(mrtip->mrti_next, mrt_list);
+
+ return (mrtp);
+}
+
+void
+netstat_mrti_free(struct mroute_type_iterator *mrtip)
+{
+ free(mrtip);
+}
+
+const struct routeaddr_type *
+netstat_mrt_get_origin(const struct mroute_type *mrtp)
+{
+ return (mrtp->mrt_origin);
+}
+
+const struct routeaddr_type *
+netstat_mrt_get_group(const struct mroute_type *mrtp)
+{
+ return (mrtp->mrt_group);
+}
+
+u_int64_t
+netstat_mrt_get_packets(const struct mroute_type *mrtp)
+{
+ return (mrtp->mrt_pkt_cnt);
+}
+
+u_int64_t
+netstat_mrt_get_bytes(const struct mroute_type *mrtp)
+{
+ return (mrtp->mrt_byte_cnt);
+}
+
+u_int64_t
+netstat_mrt_get_waitings(const struct mroute_type *mrtp)
+{
+ return (mrtp->mrt_nstall);
+}
+
+u_int32_t
+netstat_mrt_get_parent(const struct mroute_type *mrtp)
+{
+ return (mrtp->mrt_parent);
+}
+
+u_int8_t
+netstat_mrt_get_ttl(const struct mroute_type *mrtp, int i)
+{
+ if (0 <= i && i < MRTTYPE_MAXVIFS)
+ return (mrtp->mrt_ttls[i]);
+ return (0);
+}
+
+int
+netstat_mrt_get_is_mif_set(const struct mroute_type *mrtp, u_int32_t mifi)
+{
+ return (IF_ISSET(mifi, &mrtp->mrt_ifset));
+}
+
+
static const char *icmpnames[ICMP_MAXTYPE + 1] = {
"echo reply", /* RFC 792 */
"#1",
More information about the p4-projects
mailing list