diff options
author | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 1999-12-08 12:34:25 +0000 |
---|---|---|
committer | Jun-ichiro itojun Hagino <itojun@cvs.openbsd.org> | 1999-12-08 12:34:25 +0000 |
commit | aa65718cad2b6a15bce9c1c4ec03903f42539558 (patch) | |
tree | 43d9527e15a5f023acf33c37132bfc0867e8e6d3 /usr.sbin/ifmcstat | |
parent | 3fc9404f57dc2e084f8ed46c43c04334ed1c83dd (diff) |
add ifmcstat(8), a program to check multicast group status on interfaces.
Diffstat (limited to 'usr.sbin/ifmcstat')
-rw-r--r-- | usr.sbin/ifmcstat/Makefile | 11 | ||||
-rw-r--r-- | usr.sbin/ifmcstat/ifmcstat.8 | 33 | ||||
-rw-r--r-- | usr.sbin/ifmcstat/ifmcstat.c | 338 |
3 files changed, 382 insertions, 0 deletions
diff --git a/usr.sbin/ifmcstat/Makefile b/usr.sbin/ifmcstat/Makefile new file mode 100644 index 00000000000..b838a07d608 --- /dev/null +++ b/usr.sbin/ifmcstat/Makefile @@ -0,0 +1,11 @@ +PROG= ifmcstat +MAN= ifmcstat.8 + +BINGRP= kmem +BINMODE=2555 +LDADD= -lkvm +DPADD= ${LIBKVM} + +CPPFLAGS+= -DINET6 + +.include <bsd.prog.mk> diff --git a/usr.sbin/ifmcstat/ifmcstat.8 b/usr.sbin/ifmcstat/ifmcstat.8 new file mode 100644 index 00000000000..c4cfab87ccb --- /dev/null +++ b/usr.sbin/ifmcstat/ifmcstat.8 @@ -0,0 +1,33 @@ +.\" $OpenBSD: ifmcstat.8,v 1.1 1999/12/08 12:34:24 itojun Exp $ +.\" +.\" Copyright (c) 1996 WIDE Project. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modifications, are permitted provided that the above copyright notice +.\" and this paragraph are duplicated in all such forms and that any +.\" documentation, advertising materials, and other materials related to +.\" such distribution and use acknowledge that the software was developed +.\" by the WIDE Project, Japan. The name of the Project may not be used to +.\" endorse or promote products derived from this software without +.\" specific prior written permission. THIS SOFTWARE IS PROVIDED ``AS IS'' +.\" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT +.\" LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +.\" A PARTICULAR PURPOSE. +.Dd May 21, 1998 +.Dt IFMCSTAT 8 +.Os +.Sh NAME +.Nm ifmcstat +.Nd dump multicast group management statistics per interface +.Sh SYNOPSIS +.Nm +.\" +.Sh DESCRIPTION +The +.Nm Ifmcstat +dumps multicast group information in the kernel. +.Pp +There are no command-line options. +.\" +.\" .Sh SEE ALSO +.\" RFC2080 -- IPng for IPv6. G. Malkin, R. Minnear. January 1997. diff --git a/usr.sbin/ifmcstat/ifmcstat.c b/usr.sbin/ifmcstat/ifmcstat.c new file mode 100644 index 00000000000..cb81de1e022 --- /dev/null +++ b/usr.sbin/ifmcstat/ifmcstat.c @@ -0,0 +1,338 @@ +/* $OpenBSD: ifmcstat.c,v 1.1 1999/12/08 12:34:24 itojun Exp $ */ + +/* + * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <kvm.h> +#include <nlist.h> +#include <string.h> +#include <limits.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <net/if.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +# include <net/if_var.h> +#endif +#include <net/if_types.h> +#include <net/if_dl.h> +#include <netinet/in.h> +#ifndef __NetBSD__ +# ifdef __FreeBSD__ +# define KERNEL +# endif +# include <netinet/if_ether.h> +# ifdef __FreeBSD__ +# undef KERNEL +# endif +#else +# include <net/if_ether.h> +#endif +#include <netinet/in_var.h> +#include <arpa/inet.h> + +kvm_t *kvmd; + +struct nlist nl[] = { +#define N_IFNET 0 + { "_ifnet" }, + { "" }, +}; + +const char *inet6_n2a __P((struct in6_addr *)); +int main __P((void)); +char *ifname __P((struct ifnet *)); +void kread __P((u_long, void *, int)); +#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) +void acmc __P((struct ether_multi *)); +#endif +void if6_addrlist __P((struct ifaddr *)); +void in6_multilist __P((struct in6_multi *)); +struct in6_multi * in6_multientry __P((struct in6_multi *)); + +#if !defined(__NetBSD__) && !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__OpenBSD__) +#ifdef __bsdi__ +struct ether_addr { + u_int8_t ether_addr_octet[6]; +}; +#endif +static char *ether_ntoa __P((struct ether_addr *)); +#endif + +#define KREAD(addr, buf, type) \ + kread((u_long)addr, (void *)buf, sizeof(type)) + +const char *inet6_n2a(p) + struct in6_addr *p; +{ + static char buf[BUFSIZ]; + + if (IN6_IS_ADDR_UNSPECIFIED(p)) + return "*"; + return inet_ntop(AF_INET6, (void *)p, buf, sizeof(buf)); +} + +int main() +{ + char buf[_POSIX2_LINE_MAX], ifname[IFNAMSIZ]; + struct ifnet *ifp, *nifp, ifnet; +#ifndef __NetBSD__ + struct arpcom arpcom; +#else + struct ethercom ec; + struct sockaddr_dl sdl; +#endif + + if ((kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf)) == NULL) { + perror("kvm_openfiles"); + exit(1); + } + if (kvm_nlist(kvmd, nl) < 0) { + perror("kvm_nlist"); + exit(1); + } + if (nl[N_IFNET].n_value == 0) { + printf("symbol %s not found\n", nl[N_IFNET].n_name); + exit(1); + } + KREAD(nl[N_IFNET].n_value, &ifp, struct ifnet *); + while (ifp) { + KREAD(ifp, &ifnet, struct ifnet); + printf("%s:\n", if_indextoname(ifnet.if_index, ifname)); + +#if defined(__NetBSD__) || defined(__OpenBSD__) + if6_addrlist(ifnet.if_addrlist.tqh_first); + nifp = ifnet.if_list.tqe_next; +#elif defined(__FreeBSD__) && __FreeBSD__ >= 3 + if6_addrlist(TAILQ_FIRST(&ifnet.if_addrhead)); + nifp = ifnet.if_link.tqe_next; +#else + if6_addrlist(ifnet.if_addrlist); + nifp = ifnet.if_next; +#endif + +#ifdef __NetBSD__ + KREAD(ifnet.if_sadl, &sdl, struct sockaddr_dl); + if (sdl.sdl_type == IFT_ETHER) { + printf("\tenaddr %s", + ether_ntoa((struct ether_addr *)LLADDR(&sdl))); + KREAD(ifp, &ec, struct ethercom); + printf(" multicnt %d", ec.ec_multicnt); + acmc(ec.ec_multiaddrs.lh_first); + printf("\n"); + } +#elif defined(__FreeBSD__) && __FreeBSD__ >= 3 + /* not supported */ +#else + if (ifnet.if_type == IFT_ETHER) { + KREAD(ifp, &arpcom, struct arpcom); + printf("\tenaddr %s", + ether_ntoa((struct ether_addr *)arpcom.ac_enaddr)); + KREAD(ifp, &arpcom, struct arpcom); + printf(" multicnt %d", arpcom.ac_multicnt); +#ifdef __OpenBSD__ + acmc(arpcom.ac_multiaddrs.lh_first); +#else + acmc(arpcom.ac_multiaddrs); +#endif + printf("\n"); + } +#endif + + ifp = nifp; + } + + exit(0); + /*NOTREACHED*/ +} + +char *ifname(ifp) + struct ifnet *ifp; +{ + static char buf[BUFSIZ]; + +#if defined(__NetBSD__) || defined(__OpenBSD__) + KREAD(ifp->if_xname, buf, IFNAMSIZ); +#else + KREAD(ifp->if_name, buf, IFNAMSIZ); +#endif + return buf; +} + +void kread(addr, buf, len) + u_long addr; + void *buf; + int len; +{ + if (kvm_read(kvmd, addr, buf, len) != len) { + perror("kvm_read"); + exit(1); + } +} + +#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) +void acmc(am) + struct ether_multi *am; +{ + struct ether_multi em; + + while (am) { + KREAD(am, &em, struct ether_multi); + + printf("\n\t\t"); + printf("%s -- ", ether_ntoa((struct ether_addr *)em.enm_addrlo)); + printf("%s ", ether_ntoa((struct ether_addr *)&em.enm_addrhi)); + printf("%d", em.enm_refcount); +#if !defined(__NetBSD__) && !defined(__OpenBSD__) + am = em.enm_next; +#else + am = em.enm_list.le_next; +#endif + } +} +#endif + +void +if6_addrlist(ifap) + struct ifaddr *ifap; +{ + static char in6buf[BUFSIZ]; + struct ifaddr ifa; + struct sockaddr sa; + struct in6_ifaddr if6a; + struct in6_multi *mc = 0; +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 + struct ifaddr *ifap0; +#endif /* __FreeBSD__ >= 3 */ + +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 + ifap0 = ifap; +#endif /* __FreeBSD__ >= 3 */ + while (ifap) { + KREAD(ifap, &ifa, struct ifaddr); + if (ifa.ifa_addr == NULL) + goto nextifap; + KREAD(ifa.ifa_addr, &sa, struct sockaddr); + if (sa.sa_family != PF_INET6) + goto nextifap; + KREAD(ifap, &if6a, struct in6_ifaddr); + printf("\tinet6 %s\n", + inet_ntop(AF_INET6, + (const void *)&if6a.ia_addr.sin6_addr, + in6buf, sizeof(in6buf))); +#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) + mc = mc ? mc : if6a.ia6_multiaddrs.lh_first; +#endif + nextifap: +#if defined(__NetBSD__) || defined(__OpenBSD__) + ifap = ifa.ifa_list.tqe_next; +#elif defined(__FreeBSD__) && __FreeBSD__ >= 3 + ifap = ifa.ifa_link.tqe_next; +#else + ifap = ifa.ifa_next; +#endif /* __FreeBSD__ >= 3 */ + } +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 + if (ifap0) { + struct ifnet ifnet; + struct ifmultiaddr ifm, *ifmp = 0; + struct sockaddr_in6 sin6; + struct in6_multi in6m; + struct sockaddr_dl sdl; + int in6_multilist_done = 0; + + KREAD(ifap0, &ifa, struct ifaddr); + KREAD(ifa.ifa_ifp, &ifnet, struct ifnet); + if (ifnet.if_multiaddrs.lh_first) + ifmp = ifnet.if_multiaddrs.lh_first; + while (ifmp) { + KREAD(ifmp, &ifm, struct ifmultiaddr); + if (ifm.ifma_addr == NULL) + goto nextmulti; + KREAD(ifm.ifma_addr, &sa, struct sockaddr); + if (sa.sa_family != AF_INET6) + goto nextmulti; + (void)in6_multientry((struct in6_multi *) + ifm.ifma_protospec); + if (ifm.ifma_lladdr == 0) + goto nextmulti; + KREAD(ifm.ifma_lladdr, &sdl, struct sockaddr_dl); + printf("\t\t\tmcast-macaddr %s multicnt %d\n", + ether_ntoa((struct ether_addr *)LLADDR(&sdl)), + ifm.ifma_refcount); + nextmulti: + ifmp = ifm.ifma_link.le_next; + } + } +#else + if (mc) + in6_multilist(mc); +#endif +} + +struct in6_multi * +in6_multientry(mc) + struct in6_multi *mc; +{ + static char mcbuf[BUFSIZ]; + struct in6_multi multi; + + KREAD(mc, &multi, struct in6_multi); + printf("\t\tgroup %s\n", inet_ntop(AF_INET6, + (const void *)&multi.in6m_addr, + mcbuf, sizeof(mcbuf))); + return(multi.in6m_entry.le_next); +} + +void +in6_multilist(mc) + struct in6_multi *mc; +{ + while (mc) + mc = in6_multientry(mc); +} + +#if !defined(__NetBSD__) && !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__OpenBSD__) +static char * +ether_ntoa(e) + struct ether_addr *e; +{ + static char buf[20]; + u_char *p; + + p = (u_char *)e; + + snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", + p[0], p[1], p[2], p[3], p[4], p[5]); + return buf; +} +#endif |