Date: Wed, 19 Aug 2009 03:11:27 GMT From: Gabor Pali <pgj@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 167493 for review Message-ID: <200908190311.n7J3BRLl066587@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=167493 Change 167493 by pgj@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",
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200908190311.n7J3BRLl066587>