ifmcstat.c revision 167706
1167706Sbms/* $KAME: ifmcstat.c,v 1.48 2006/11/15 05:13:59 itojun Exp $ */ 2167706Sbms 355163Sshin/* 455163Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 555163Sshin * All rights reserved. 662785Sume * 755163Sshin * Redistribution and use in source and binary forms, with or without 855163Sshin * modification, are permitted provided that the following conditions 955163Sshin * are met: 1055163Sshin * 1. Redistributions of source code must retain the above copyright 1155163Sshin * notice, this list of conditions and the following disclaimer. 1255163Sshin * 2. Redistributions in binary form must reproduce the above copyright 1355163Sshin * notice, this list of conditions and the following disclaimer in the 1455163Sshin * documentation and/or other materials provided with the distribution. 1555163Sshin * 3. Neither the name of the project nor the names of its contributors 1655163Sshin * may be used to endorse or promote products derived from this software 1755163Sshin * without specific prior written permission. 1862785Sume * 1955163Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 2055163Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2155163Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2255163Sshin * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2355163Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2455163Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2555163Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2655163Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2755163Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2855163Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2955163Sshin * SUCH DAMAGE. 3055163Sshin */ 3155163Sshin 32167706Sbms#ifdef __FreeBSD__ 33167706Sbms#include <sys/cdefs.h> 34167706Sbms__FBSDID("$FreeBSD: head/usr.sbin/ifmcstat/ifmcstat.c 167706 2007-03-19 16:45:06Z bms $"); 35167706Sbms#endif 36167706Sbms 3755163Sshin#include <stdio.h> 3855163Sshin#include <stdlib.h> 3955163Sshin#include <fcntl.h> 4055163Sshin#include <kvm.h> 4155163Sshin#include <nlist.h> 4255163Sshin#include <string.h> 4355163Sshin#include <limits.h> 44167706Sbms#include <unistd.h> 4555163Sshin 4655163Sshin#include <sys/types.h> 47167706Sbms#include <sys/param.h> 4855163Sshin#include <sys/socket.h> 4978064Sume#include <sys/queue.h> 5078064Sume 5155163Sshin#include <net/if.h> 52167706Sbms#ifdef __FreeBSD__ 53167706Sbms# include <net/if_var.h> 54167706Sbms#endif 5555163Sshin#include <net/if_types.h> 5655163Sshin#include <net/if_dl.h> 57167706Sbms#include <net/route.h> 5855163Sshin#include <netinet/in.h> 59167706Sbms#include <netinet/in_systm.h> 60167706Sbms#include <netinet/ip.h> 61167706Sbms#include <netinet/igmp.h> 62167706Sbms#ifdef HAVE_IGMPV3 63167706Sbms#include <netinet/in_msf.h> 64167706Sbms#endif 65167706Sbms#ifdef HAVE_MLDV2 66167706Sbms#include <net/route.h> 67167706Sbms#include <netinet6/in6_msf.h> 68167706Sbms#endif 69167706Sbms#ifndef __NetBSD__ 70167706Sbms# ifdef __FreeBSD__ 71167706Sbms# define KERNEL 72167706Sbms# endif 73167706Sbms# include <netinet/if_ether.h> 74167706Sbms# ifdef __FreeBSD__ 75167706Sbms# undef KERNEL 76167706Sbms# endif 77167706Sbms#else 78167706Sbms# include <net/if_ether.h> 79167706Sbms#endif 8055163Sshin#include <netinet/in_var.h> 81167706Sbms#include <netinet/icmp6.h> 82167706Sbms#define _KERNEL 83167706Sbms/* defined _KERNEL only to define IGMP_v?_ROUTER and MLD_V?_ROUTER */ 84167706Sbms#ifdef __FreeBSD__ 85167706Sbms#include <sys/sysctl.h> 86167706Sbms#endif 87167706Sbms#include <netinet/igmp_var.h> 88167706Sbms#include <netinet6/mld6_var.h> 89167706Sbms#ifdef __FreeBSD__ 90167706Sbms#define IGMP_v1_ROUTER IGMP_V1_ROUTER 91167706Sbms#define IGMP_v2_ROUTER IGMP_V2_ROUTER 92167706Sbms#define IGMP_v3_ROUTER IGMP_V3_ROUTER 93167706Sbms#endif 94167706Sbms#undef _KERNEL 9555163Sshin#include <arpa/inet.h> 9655163Sshin 9762785Sume#include <netdb.h> 9862785Sume 9955163Sshinkvm_t *kvmd; 100167706Sbmsint ifindex = 0; 101167706Sbmsint af = AF_UNSPEC; 10255163Sshin 10355163Sshinstruct nlist nl[] = { 10455163Sshin#define N_IFNET 0 10555163Sshin { "_ifnet" }, 106167706Sbms#ifndef __FreeBSD__ 107167706Sbms#define N_IN6_MK 1 108167706Sbms { "_in6_mk" }, 109167706Sbms#endif 11055163Sshin { "" }, 11155163Sshin}; 11255163Sshin 11355163Sshinconst char *inet6_n2a __P((struct in6_addr *)); 114167706Sbmsint main __P((int, char **)); 11555163Sshinchar *ifname __P((struct ifnet *)); 11655163Sshinvoid kread __P((u_long, void *, int)); 117167706Sbms#ifndef __FreeBSD__ 118167706Sbmsvoid acmc __P((struct ether_multi *)); 119167706Sbms#endif 12055163Sshinvoid if6_addrlist __P((struct ifaddr *)); 12155163Sshinvoid in6_multilist __P((struct in6_multi *)); 12262785Sumestruct in6_multi * in6_multientry __P((struct in6_multi *)); 123167706Sbmsvoid if_addrlist(struct ifaddr *); 124167706Sbmsvoid in_multilist(struct in_multi *); 125167706Sbmsstruct in_multi * in_multientry(struct in_multi *); 126167706Sbms#ifdef HAVE_IGMPV3 127167706Sbmsvoid in_addr_slistentry(struct in_addr_slist *ias, char *heading); 128167706Sbms#endif 129167706Sbms#ifdef HAVE_MLDV2 130167706Sbmsvoid in6_addr_slistentry(struct in6_addr_slist *ias, char *heading); 131167706Sbms#endif 13255163Sshin 13355163Sshin#define KREAD(addr, buf, type) \ 13455163Sshin kread((u_long)addr, (void *)buf, sizeof(type)) 13555163Sshin 13662785Sume#ifdef N_IN6_MK 13762785Sumestruct multi6_kludge { 13862785Sume LIST_ENTRY(multi6_kludge) mk_entry; 13962785Sume struct ifnet *mk_ifp; 14062785Sume struct in6_multihead mk_head; 14162785Sume}; 14262785Sume#endif 14362785Sume 14455163Sshinconst char *inet6_n2a(p) 14555163Sshin struct in6_addr *p; 14655163Sshin{ 14762785Sume static char buf[NI_MAXHOST]; 14862785Sume struct sockaddr_in6 sin6; 14962785Sume u_int32_t scopeid; 15062785Sume const int niflags = NI_NUMERICHOST; 15155163Sshin 15262785Sume memset(&sin6, 0, sizeof(sin6)); 15362785Sume sin6.sin6_family = AF_INET6; 15462785Sume sin6.sin6_len = sizeof(struct sockaddr_in6); 15562785Sume sin6.sin6_addr = *p; 156167706Sbms if (IN6_IS_ADDR_LINKLOCAL(p) || IN6_IS_ADDR_MC_LINKLOCAL(p) || 157167706Sbms IN6_IS_ADDR_MC_NODELOCAL(p)) { 15862785Sume scopeid = ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]); 15962785Sume if (scopeid) { 16062785Sume sin6.sin6_scope_id = scopeid; 16162785Sume sin6.sin6_addr.s6_addr[2] = 0; 16262785Sume sin6.sin6_addr.s6_addr[3] = 0; 16362785Sume } 16462785Sume } 16562785Sume if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 16662785Sume buf, sizeof(buf), NULL, 0, niflags) == 0) 16762785Sume return buf; 16862785Sume else 16962785Sume return "(invalid)"; 17055163Sshin} 17155163Sshin 172167706Sbmsint main(argc, argv) 173167706Sbms int argc; 174167706Sbms char **argv; 17555163Sshin{ 17655163Sshin char buf[_POSIX2_LINE_MAX], ifname[IFNAMSIZ]; 177167706Sbms int c; 17855163Sshin struct ifnet *ifp, *nifp, ifnet; 179167706Sbms#ifndef __FreeBSD__ 180167706Sbms#ifndef __NetBSD__ 181167706Sbms struct arpcom arpcom; 182167706Sbms#else 183167706Sbms struct ethercom ec; 184167706Sbms struct sockaddr_dl sdl; 185167706Sbms#endif 186167706Sbms#endif 187167706Sbms const char *kernel = NULL; 18855163Sshin 189167706Sbms /* "ifmcstat [kernel]" format is supported for backward compatiblity */ 190167706Sbms if (argc == 2) 191167706Sbms kernel = argv[1]; 192167706Sbms 193167706Sbms while ((c = getopt(argc, argv, "i:f:k:")) != -1) { 194167706Sbms switch (c) { 195167706Sbms case 'i': 196167706Sbms if ((ifindex = if_nametoindex(optarg)) == 0) { 197167706Sbms fprintf(stderr, "%s: unknown interface\n", optarg); 198167706Sbms exit(1); 199167706Sbms } 200167706Sbms break; 201167706Sbms case 'f': 202167706Sbms if (strcmp(optarg, "inet") == 0) { 203167706Sbms af = AF_INET; 204167706Sbms break; 205167706Sbms } 206167706Sbms if (strcmp(optarg, "inet6") == 0) { 207167706Sbms af = AF_INET6; 208167706Sbms break; 209167706Sbms } 210167706Sbms fprintf(stderr, "%s: unknown address family\n", optarg); 211167706Sbms exit(1); 212167706Sbms /*NOTREACHED*/ 213167706Sbms case 'k': 214167706Sbms kernel = strdup(optarg); 215167706Sbms break; 216167706Sbms default: 217167706Sbms fprintf(stderr, "usage: ifmcstat [-i interface] [-f address family] [-k kernel]\n"); 218167706Sbms exit(1); 219167706Sbms /*NOTREACHED*/ 220167706Sbms } 221167706Sbms } 222167706Sbms 223167706Sbms if ((kvmd = kvm_openfiles(kernel, NULL, NULL, O_RDONLY, buf)) == NULL) { 22455163Sshin perror("kvm_openfiles"); 22555163Sshin exit(1); 22655163Sshin } 22755163Sshin if (kvm_nlist(kvmd, nl) < 0) { 22855163Sshin perror("kvm_nlist"); 22955163Sshin exit(1); 23055163Sshin } 23155163Sshin if (nl[N_IFNET].n_value == 0) { 23255163Sshin printf("symbol %s not found\n", nl[N_IFNET].n_name); 23355163Sshin exit(1); 23455163Sshin } 23555163Sshin KREAD(nl[N_IFNET].n_value, &ifp, struct ifnet *); 23655163Sshin while (ifp) { 23755163Sshin KREAD(ifp, &ifnet, struct ifnet); 238167706Sbms#if defined(__NetBSD__) || defined(__OpenBSD__) 239167706Sbms nifp = ifnet.if_list.tqe_next; 240167706Sbms#else 241167706Sbms nifp = ifnet.if_link.tqe_next; 242167706Sbms#endif 243167706Sbms if (ifindex && ifindex != ifnet.if_index) 244167706Sbms goto next; 245167706Sbms 24655163Sshin printf("%s:\n", if_indextoname(ifnet.if_index, ifname)); 247167706Sbms#if defined(__NetBSD__) || defined(__OpenBSD__) 248167706Sbms if_addrlist(ifnet.if_addrlist.tqh_first); 249167706Sbms if6_addrlist(ifnet.if_addrlist.tqh_first); 250167706Sbms#else 251167706Sbms if_addrlist(TAILQ_FIRST(&ifnet.if_addrhead)); 25255163Sshin if6_addrlist(TAILQ_FIRST(&ifnet.if_addrhead)); 253167706Sbms#endif 25462785Sume 255167706Sbms#ifdef __NetBSD__ 256167706Sbms KREAD(ifnet.if_sadl, &sdl, struct sockaddr_dl); 257167706Sbms if (sdl.sdl_type == IFT_ETHER) { 258167706Sbms printf("\tenaddr %s", 259167706Sbms ether_ntoa((struct ether_addr *)LLADDR(&sdl))); 260167706Sbms KREAD(ifp, &ec, struct ethercom); 261167706Sbms printf(" multicnt %d", ec.ec_multicnt); 262167706Sbms acmc(ec.ec_multiaddrs.lh_first); 263167706Sbms printf("\n"); 264167706Sbms } 265167706Sbms#elif defined(__FreeBSD__) 26662785Sume /* not supported */ 267167706Sbms#else /* __OpenBSD__ */ 268167706Sbms if (ifnet.if_type == IFT_ETHER) { 269167706Sbms KREAD(ifp, &arpcom, struct arpcom); 270167706Sbms printf("\tenaddr %s", 271167706Sbms ether_ntoa((struct ether_addr *)arpcom.ac_enaddr)); 272167706Sbms KREAD(ifp, &arpcom, struct arpcom); 273167706Sbms printf(" multicnt %d", arpcom.ac_multicnt); 274167706Sbms acmc(arpcom.ac_multiaddrs.lh_first); 275167706Sbms printf("\n"); 276167706Sbms } 277167706Sbms#endif 27862785Sume 279167706Sbmsnext: 28062785Sume ifp = nifp; 28155163Sshin } 28255163Sshin 28355163Sshin exit(0); 28455163Sshin /*NOTREACHED*/ 28555163Sshin} 28655163Sshin 28755163Sshinchar *ifname(ifp) 28855163Sshin struct ifnet *ifp; 28955163Sshin{ 29055163Sshin static char buf[BUFSIZ]; 29162785Sume struct ifnet ifnet; 29255163Sshin 29362785Sume KREAD(ifp, &ifnet, struct ifnet); 294121816Sbrooks strlcpy(buf, ifnet.if_xname, sizeof(buf)); 29555163Sshin return buf; 29655163Sshin} 29755163Sshin 29855163Sshinvoid kread(addr, buf, len) 29955163Sshin u_long addr; 30055163Sshin void *buf; 30155163Sshin int len; 30255163Sshin{ 30355163Sshin if (kvm_read(kvmd, addr, buf, len) != len) { 30455163Sshin perror("kvm_read"); 30555163Sshin exit(1); 30655163Sshin } 30755163Sshin} 30855163Sshin 309167706Sbms#ifndef __FreeBSD__ 310167706Sbmsvoid acmc(am) 311167706Sbms struct ether_multi *am; 312167706Sbms{ 313167706Sbms struct ether_multi em; 314167706Sbms 315167706Sbms while (am) { 316167706Sbms KREAD(am, &em, struct ether_multi); 317167706Sbms 318167706Sbms printf("\n\t\t"); 319167706Sbms printf("%s -- ", ether_ntoa((struct ether_addr *)em.enm_addrlo)); 320167706Sbms printf("%s ", ether_ntoa((struct ether_addr *)&em.enm_addrhi)); 321167706Sbms printf("%d", em.enm_refcount); 322167706Sbms#if !defined(__NetBSD__) && !defined(__OpenBSD__) 323167706Sbms am = em.enm_next; 324167706Sbms#else 325167706Sbms am = em.enm_list.le_next; 326167706Sbms#endif 327167706Sbms } 328167706Sbms} 329167706Sbms#endif 330167706Sbms 33155163Sshinvoid 33255163Sshinif6_addrlist(ifap) 33355163Sshin struct ifaddr *ifap; 33455163Sshin{ 33555163Sshin struct ifaddr ifa; 33662785Sume struct sockaddr sa; 33762785Sume struct in6_ifaddr if6a; 338167706Sbms#ifndef __FreeBSD__ 339167706Sbms struct in6_multi *mc = 0; 340167706Sbms#endif 34155543Sshin struct ifaddr *ifap0; 34255163Sshin 343167706Sbms if (af && af != AF_INET6) 344167706Sbms return; 34555163Sshin ifap0 = ifap; 34662785Sume while (ifap) { 34755163Sshin KREAD(ifap, &ifa, struct ifaddr); 34855163Sshin if (ifa.ifa_addr == NULL) 34962785Sume goto nextifap; 35055163Sshin KREAD(ifa.ifa_addr, &sa, struct sockaddr); 35155163Sshin if (sa.sa_family != PF_INET6) 35262785Sume goto nextifap; 35355163Sshin KREAD(ifap, &if6a, struct in6_ifaddr); 35462785Sume printf("\tinet6 %s\n", inet6_n2a(&if6a.ia_addr.sin6_addr)); 355167706Sbms#ifndef __FreeBSD__ 356167706Sbms mc = mc ? mc : if6a.ia6_multiaddrs.lh_first; 357167706Sbms#endif 35862785Sume nextifap: 359167706Sbms#if defined(__NetBSD__) || defined(__OpenBSD__) 360167706Sbms ifap = ifa.ifa_list.tqe_next; 361167706Sbms#else 362167706Sbms ifap = ifa.ifa_link.tqe_next; 363167706Sbms#endif 36462785Sume } 365167706Sbms#ifdef __FreeBSD__ 36662785Sume if (ifap0) { 36762785Sume struct ifnet ifnet; 36862785Sume struct ifmultiaddr ifm, *ifmp = 0; 36962785Sume struct sockaddr_dl sdl; 37055163Sshin 37162785Sume KREAD(ifap0, &ifa, struct ifaddr); 37262785Sume KREAD(ifa.ifa_ifp, &ifnet, struct ifnet); 37372084Sphk if (TAILQ_FIRST(&ifnet.if_multiaddrs)) 37472084Sphk ifmp = TAILQ_FIRST(&ifnet.if_multiaddrs); 37562785Sume while (ifmp) { 37662785Sume KREAD(ifmp, &ifm, struct ifmultiaddr); 37762785Sume if (ifm.ifma_addr == NULL) 37862785Sume goto nextmulti; 37962785Sume KREAD(ifm.ifma_addr, &sa, struct sockaddr); 38062785Sume if (sa.sa_family != AF_INET6) 38162785Sume goto nextmulti; 38262785Sume (void)in6_multientry((struct in6_multi *) 38362785Sume ifm.ifma_protospec); 38462785Sume if (ifm.ifma_lladdr == 0) 38562785Sume goto nextmulti; 38662785Sume KREAD(ifm.ifma_lladdr, &sdl, struct sockaddr_dl); 38762785Sume printf("\t\t\tmcast-macaddr %s multicnt %d\n", 38862785Sume ether_ntoa((struct ether_addr *)LLADDR(&sdl)), 38962785Sume ifm.ifma_refcount); 39062785Sume nextmulti: 39172084Sphk ifmp = TAILQ_NEXT(&ifm, ifma_link); 39262785Sume } 39362785Sume } 394167706Sbms#else 395167706Sbms if (mc) 396167706Sbms in6_multilist(mc); 397167706Sbms#endif 39862785Sume#ifdef N_IN6_MK 39962785Sume if (nl[N_IN6_MK].n_value != 0) { 40062785Sume LIST_HEAD(in6_mktype, multi6_kludge) in6_mk; 40162785Sume struct multi6_kludge *mkp, mk; 40262785Sume char *nam; 40362785Sume 40462785Sume KREAD(nl[N_IN6_MK].n_value, &in6_mk, struct in6_mktype); 40562785Sume KREAD(ifap0, &ifa, struct ifaddr); 40662785Sume 40762785Sume nam = strdup(ifname(ifa.ifa_ifp)); 40878064Sume if (!nam) { 40978064Sume fprintf(stderr, "ifmcstat: not enough core\n"); 41078064Sume exit(1); 41178064Sume } 41262785Sume 413167706Sbms for (mkp = in6_mk.lh_first; mkp; mkp = mk.mk_entry.le_next) { 41462785Sume KREAD(mkp, &mk, struct multi6_kludge); 41562785Sume if (strcmp(nam, ifname(mk.mk_ifp)) == 0 && 416167706Sbms mk.mk_head.lh_first) { 41762785Sume printf("\t(on kludge entry for %s)\n", nam); 418167706Sbms in6_multilist(mk.mk_head.lh_first); 41962785Sume } 42062785Sume } 42162785Sume 42262785Sume free(nam); 42362785Sume } 42462785Sume#endif 42555163Sshin} 42655163Sshin 42762785Sumestruct in6_multi * 42855163Sshinin6_multientry(mc) 42955163Sshin struct in6_multi *mc; 43055163Sshin{ 43155163Sshin struct in6_multi multi; 432167706Sbms#ifdef HAVE_MLDV2 433167706Sbms struct in6_multi_source src; 434167706Sbms struct router6_info rt6i; 435167706Sbms#endif 43655163Sshin 43755163Sshin KREAD(mc, &multi, struct in6_multi); 43862785Sume printf("\t\tgroup %s", inet6_n2a(&multi.in6m_addr)); 43962785Sume printf(" refcnt %u\n", multi.in6m_refcount); 440167706Sbms 441167706Sbms#ifdef HAVE_MLDV2 442167706Sbms if (multi.in6m_rti != NULL) { 443167706Sbms KREAD(multi.in6m_rti, &rt6i, struct router_info); 444167706Sbms printf("\t\t\t"); 445167706Sbms switch (rt6i.rt6i_type) { 446167706Sbms case MLD_V1_ROUTER: 447167706Sbms printf("mldv1"); 448167706Sbms break; 449167706Sbms case MLD_V2_ROUTER: 450167706Sbms printf("mldv2"); 451167706Sbms break; 452167706Sbms default: 453167706Sbms printf("mldv?(%d)", rt6i.rt6i_type); 454167706Sbms break; 455167706Sbms } 456167706Sbms 457167706Sbms if (multi.in6m_source == NULL) { 458167706Sbms printf("\n"); 459167706Sbms return(multi.in6m_entry.le_next); 460167706Sbms } 461167706Sbms 462167706Sbms KREAD(multi.in6m_source, &src, struct in6_multi_source); 463167706Sbms printf(" mode=%s grpjoin=%d\n", 464167706Sbms src.i6ms_mode == MCAST_INCLUDE ? "include" : 465167706Sbms src.i6ms_mode == MCAST_EXCLUDE ? "exclude" : 466167706Sbms "???", 467167706Sbms src.i6ms_grpjoin); 468167706Sbms in6_addr_slistentry(src.i6ms_cur, "current"); 469167706Sbms in6_addr_slistentry(src.i6ms_rec, "recorded"); 470167706Sbms in6_addr_slistentry(src.i6ms_in, "included"); 471167706Sbms in6_addr_slistentry(src.i6ms_ex, "excluded"); 472167706Sbms in6_addr_slistentry(src.i6ms_alw, "allowed"); 473167706Sbms in6_addr_slistentry(src.i6ms_blk, "blocked"); 474167706Sbms in6_addr_slistentry(src.i6ms_toin, "to-include"); 475167706Sbms in6_addr_slistentry(src.i6ms_ex, "to-exclude"); 476167706Sbms } 477167706Sbms#endif 478167706Sbms return(multi.in6m_entry.le_next); 47955163Sshin} 48062785Sume 481167706Sbms#ifdef HAVE_MLDV2 48262785Sumevoid 483167706Sbmsin6_addr_slistentry(struct in6_addr_slist *ias, char *heading) 484167706Sbms{ 485167706Sbms struct in6_addr_slist slist; 486167706Sbms struct i6as_head head; 487167706Sbms struct in6_addr_source src; 488167706Sbms 489167706Sbms if (ias == NULL) { 490167706Sbms printf("\t\t\t\t%s (none)\n", heading); 491167706Sbms return; 492167706Sbms } 493167706Sbms memset(&slist, 0, sizeof(slist)); 494167706Sbms KREAD(ias, &slist, struct in6_addr_source); 495167706Sbms printf("\t\t\t\t%s (entry num=%d)\n", heading, slist.numsrc); 496167706Sbms if (slist.numsrc == 0) { 497167706Sbms return; 498167706Sbms } 499167706Sbms KREAD(slist.head, &head, struct i6as_head); 500167706Sbms 501167706Sbms KREAD(head.lh_first, &src, struct in6_addr_source); 502167706Sbms while (1) { 503167706Sbms printf("\t\t\t\t\tsource %s (ref=%d)\n", 504167706Sbms inet6_n2a(&src.i6as_addr.sin6_addr), 505167706Sbms src.i6as_refcount); 506167706Sbms if (src.i6as_list.le_next == NULL) 507167706Sbms break; 508167706Sbms KREAD(src.i6as_list.le_next, &src, struct in6_addr_source); 509167706Sbms } 510167706Sbms return; 511167706Sbms} 512167706Sbms#endif 513167706Sbms 514167706Sbmsvoid 51562785Sumein6_multilist(mc) 51662785Sume struct in6_multi *mc; 51762785Sume{ 51862785Sume while (mc) 51962785Sume mc = in6_multientry(mc); 52062785Sume} 521167706Sbms 522167706Sbmsvoid 523167706Sbmsif_addrlist(ifap) 524167706Sbms struct ifaddr *ifap; 525167706Sbms{ 526167706Sbms struct ifaddr ifa; 527167706Sbms struct sockaddr sa; 528167706Sbms struct in_ifaddr ia; 529167706Sbms#ifndef __FreeBSD__ 530167706Sbms struct in_multi *mc = 0; 531167706Sbms#endif 532167706Sbms struct ifaddr *ifap0; 533167706Sbms 534167706Sbms if (af && af != AF_INET) 535167706Sbms return; 536167706Sbms ifap0 = ifap; 537167706Sbms while (ifap) { 538167706Sbms KREAD(ifap, &ifa, struct ifaddr); 539167706Sbms if (ifa.ifa_addr == NULL) 540167706Sbms goto nextifap; 541167706Sbms KREAD(ifa.ifa_addr, &sa, struct sockaddr); 542167706Sbms if (sa.sa_family != PF_INET) 543167706Sbms goto nextifap; 544167706Sbms KREAD(ifap, &ia, struct in_ifaddr); 545167706Sbms printf("\tinet %s\n", inet_ntoa(ia.ia_addr.sin_addr)); 546167706Sbms#ifndef __FreeBSD__ 547167706Sbms mc = mc ? mc : ia.ia_multiaddrs.lh_first; 548167706Sbms#endif 549167706Sbms nextifap: 550167706Sbms#if defined(__NetBSD__) || defined(__OpenBSD__) 551167706Sbms ifap = ifa.ifa_list.tqe_next; 552167706Sbms#else 553167706Sbms ifap = ifa.ifa_link.tqe_next; 554167706Sbms#endif 555167706Sbms } 556167706Sbms#ifdef __FreeBSD__ 557167706Sbms if (ifap0) { 558167706Sbms struct ifnet ifnet; 559167706Sbms struct ifmultiaddr ifm, *ifmp = 0; 560167706Sbms struct sockaddr_dl sdl; 561167706Sbms 562167706Sbms KREAD(ifap0, &ifa, struct ifaddr); 563167706Sbms KREAD(ifa.ifa_ifp, &ifnet, struct ifnet); 564167706Sbms if (TAILQ_FIRST(&ifnet.if_multiaddrs)) 565167706Sbms ifmp = TAILQ_FIRST(&ifnet.if_multiaddrs); 566167706Sbms while (ifmp) { 567167706Sbms KREAD(ifmp, &ifm, struct ifmultiaddr); 568167706Sbms if (ifm.ifma_addr == NULL) 569167706Sbms goto nextmulti; 570167706Sbms KREAD(ifm.ifma_addr, &sa, struct sockaddr); 571167706Sbms if (sa.sa_family != AF_INET) 572167706Sbms goto nextmulti; 573167706Sbms (void)in_multientry((struct in_multi *) 574167706Sbms ifm.ifma_protospec); 575167706Sbms if (ifm.ifma_lladdr == 0) 576167706Sbms goto nextmulti; 577167706Sbms KREAD(ifm.ifma_lladdr, &sdl, struct sockaddr_dl); 578167706Sbms printf("\t\t\tmcast-macaddr %s multicnt %d\n", 579167706Sbms ether_ntoa((struct ether_addr *)LLADDR(&sdl)), 580167706Sbms ifm.ifma_refcount); 581167706Sbms nextmulti: 582167706Sbms ifmp = TAILQ_NEXT(&ifm, ifma_link); 583167706Sbms } 584167706Sbms } 585167706Sbms#else /* !FreeBSD */ 586167706Sbms if (mc) 587167706Sbms in_multilist(mc); 588167706Sbms#endif 589167706Sbms} 590167706Sbms 591167706Sbmsvoid 592167706Sbmsin_multilist(mc) 593167706Sbms struct in_multi *mc; 594167706Sbms{ 595167706Sbms while (mc) 596167706Sbms mc = in_multientry(mc); 597167706Sbms} 598167706Sbms 599167706Sbmsstruct in_multi * 600167706Sbmsin_multientry(mc) 601167706Sbms struct in_multi *mc; 602167706Sbms{ 603167706Sbms struct in_multi multi; 604167706Sbms struct router_info rti; 605167706Sbms#ifdef HAVE_IGMPV3 606167706Sbms struct in_multi_source src; 607167706Sbms#endif 608167706Sbms 609167706Sbms KREAD(mc, &multi, struct in_multi); 610167706Sbms printf("\t\tgroup %s\n", inet_ntoa(multi.inm_addr)); 611167706Sbms 612167706Sbms if (multi.inm_rti != NULL) { 613167706Sbms KREAD(multi.inm_rti, &rti, struct router_info); 614167706Sbms printf("\t\t\t"); 615167706Sbms switch (rti.rti_type) { 616167706Sbms case IGMP_v1_ROUTER: 617167706Sbms printf("igmpv1"); 618167706Sbms break; 619167706Sbms case IGMP_v2_ROUTER: 620167706Sbms printf("igmpv2"); 621167706Sbms break; 622167706Sbms#ifdef HAVE_IGMPV3 623167706Sbms case IGMP_v3_ROUTER: 624167706Sbms printf("igmpv3"); 625167706Sbms break; 626167706Sbms#endif 627167706Sbms default: 628167706Sbms printf("igmpv?(%d)", rti.rti_type); 629167706Sbms break; 630167706Sbms } 631167706Sbms 632167706Sbms#ifdef HAVE_IGMPV3 633167706Sbms if (multi.inm_source == NULL) { 634167706Sbms printf("\n"); 635167706Sbms return (multi.inm_list.le_next); 636167706Sbms } 637167706Sbms 638167706Sbms KREAD(multi.inm_source, &src, struct in_multi_source); 639167706Sbms printf(" mode=%s grpjoin=%d\n", 640167706Sbms src.ims_mode == MCAST_INCLUDE ? "include" : 641167706Sbms src.ims_mode == MCAST_EXCLUDE ? "exclude" : 642167706Sbms "???", 643167706Sbms src.ims_grpjoin); 644167706Sbms in_addr_slistentry(src.ims_cur, "current"); 645167706Sbms in_addr_slistentry(src.ims_rec, "recorded"); 646167706Sbms in_addr_slistentry(src.ims_in, "included"); 647167706Sbms in_addr_slistentry(src.ims_ex, "excluded"); 648167706Sbms in_addr_slistentry(src.ims_alw, "allowed"); 649167706Sbms in_addr_slistentry(src.ims_blk, "blocked"); 650167706Sbms in_addr_slistentry(src.ims_toin, "to-include"); 651167706Sbms in_addr_slistentry(src.ims_ex, "to-exclude"); 652167706Sbms#else 653167706Sbms printf("\n"); 654167706Sbms#endif 655167706Sbms } 656167706Sbms 657167706Sbms#ifdef __FreeBSD__ 658167706Sbms return (NULL); 659167706Sbms#else 660167706Sbms return (multi.inm_list.le_next); 661167706Sbms#endif 662167706Sbms} 663167706Sbms 664167706Sbms#ifdef HAVE_IGMPV3 665167706Sbmsvoid 666167706Sbmsin_addr_slistentry(struct in_addr_slist *ias, char *heading) 667167706Sbms{ 668167706Sbms struct in_addr_slist slist; 669167706Sbms struct ias_head head; 670167706Sbms struct in_addr_source src; 671167706Sbms 672167706Sbms if (ias == NULL) { 673167706Sbms printf("\t\t\t\t%s (none)\n", heading); 674167706Sbms return; 675167706Sbms } 676167706Sbms memset(&slist, 0, sizeof(slist)); 677167706Sbms KREAD(ias, &slist, struct in_addr_source); 678167706Sbms printf("\t\t\t\t%s (entry num=%d)\n", heading, slist.numsrc); 679167706Sbms if (slist.numsrc == 0) { 680167706Sbms return; 681167706Sbms } 682167706Sbms KREAD(slist.head, &head, struct ias_head); 683167706Sbms 684167706Sbms KREAD(head.lh_first, &src, struct in_addr_source); 685167706Sbms while (1) { 686167706Sbms printf("\t\t\t\t\tsource %s (ref=%d)\n", 687167706Sbms inet_ntoa(src.ias_addr.sin_addr), src.ias_refcount); 688167706Sbms if (src.ias_list.le_next == NULL) 689167706Sbms break; 690167706Sbms KREAD(src.ias_list.le_next, &src, struct in_addr_source); 691167706Sbms } 692167706Sbms return; 693167706Sbms} 694167706Sbms#endif 695