ifmcstat.c revision 55163
155163Sshin/* 255163Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 355163Sshin * All rights reserved. 455163Sshin * 555163Sshin * Redistribution and use in source and binary forms, with or without 655163Sshin * modification, are permitted provided that the following conditions 755163Sshin * are met: 855163Sshin * 1. Redistributions of source code must retain the above copyright 955163Sshin * notice, this list of conditions and the following disclaimer. 1055163Sshin * 2. Redistributions in binary form must reproduce the above copyright 1155163Sshin * notice, this list of conditions and the following disclaimer in the 1255163Sshin * documentation and/or other materials provided with the distribution. 1355163Sshin * 3. Neither the name of the project nor the names of its contributors 1455163Sshin * may be used to endorse or promote products derived from this software 1555163Sshin * without specific prior written permission. 1655163Sshin * 1755163Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 1855163Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1955163Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2055163Sshin * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2155163Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2255163Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2355163Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2455163Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2555163Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2655163Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2755163Sshin * SUCH DAMAGE. 2855163Sshin * 2955163Sshin * $FreeBSD: head/usr.sbin/ifmcstat/ifmcstat.c 55163 1999-12-28 02:37:14Z shin $ 3055163Sshin */ 3155163Sshin 3255163Sshin#include <stdio.h> 3355163Sshin#include <stdlib.h> 3455163Sshin#include <fcntl.h> 3555163Sshin#include <kvm.h> 3655163Sshin#include <nlist.h> 3755163Sshin#include <string.h> 3855163Sshin#include <limits.h> 3955163Sshin 4055163Sshin#include <sys/types.h> 4155163Sshin#include <sys/socket.h> 4255163Sshin#include <net/if.h> 4355163Sshin#if defined(__FreeBSD__) && __FreeBSD__ >= 3 4455163Sshin# include <net/if_var.h> 4555163Sshin#endif 4655163Sshin#include <net/if_types.h> 4755163Sshin#include <net/if_dl.h> 4855163Sshin#include <netinet/in.h> 4955163Sshin#ifndef __NetBSD__ 5055163Sshin# ifdef __FreeBSD__ 5155163Sshin# define KERNEL 5255163Sshin# endif 5355163Sshin# include <netinet/if_ether.h> 5455163Sshin# ifdef __FreeBSD__ 5555163Sshin# undef KERNEL 5655163Sshin# endif 5755163Sshin#else 5855163Sshin# include <net/if_ether.h> 5955163Sshin#endif 6055163Sshin#include <netinet/in_var.h> 6155163Sshin#include <arpa/inet.h> 6255163Sshin 6355163Sshinkvm_t *kvmd; 6455163Sshin 6555163Sshinstruct nlist nl[] = { 6655163Sshin#define N_IFNET 0 6755163Sshin { "_ifnet" }, 6855163Sshin { "" }, 6955163Sshin}; 7055163Sshin 7155163Sshinconst char *inet6_n2a __P((struct in6_addr *)); 7255163Sshinint main __P((void)); 7355163Sshinchar *ifname __P((struct ifnet *)); 7455163Sshinvoid kread __P((u_long, void *, int)); 7555163Sshin#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) 7655163Sshinvoid acmc __P((struct ether_multi *)); 7755163Sshin#endif 7855163Sshinvoid if6_addrlist __P((struct ifaddr *)); 7955163Sshinvoid in6_multilist __P((struct in6_multi *)); 8055163Sshinstruct in6_multi * in6_multientry __P((struct in6_multi *)); 8155163Sshin 8255163Sshin#if !defined(__NetBSD__) && !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__OpenBSD__) 8355163Sshin#ifdef __bsdi__ 8455163Sshinstruct ether_addr { 8555163Sshin u_int8_t ether_addr_octet[6]; 8655163Sshin}; 8755163Sshin#endif 8855163Sshinstatic char *ether_ntoa __P((struct ether_addr *)); 8955163Sshin#endif 9055163Sshin 9155163Sshin#define KREAD(addr, buf, type) \ 9255163Sshin kread((u_long)addr, (void *)buf, sizeof(type)) 9355163Sshin 9455163Sshinconst char *inet6_n2a(p) 9555163Sshin struct in6_addr *p; 9655163Sshin{ 9755163Sshin static char buf[BUFSIZ]; 9855163Sshin 9955163Sshin if (IN6_IS_ADDR_UNSPECIFIED(p)) 10055163Sshin return "*"; 10155163Sshin return inet_ntop(AF_INET6, (void *)p, buf, sizeof(buf)); 10255163Sshin} 10355163Sshin 10455163Sshinint main() 10555163Sshin{ 10655163Sshin char buf[_POSIX2_LINE_MAX], ifname[IFNAMSIZ]; 10755163Sshin struct ifnet *ifp, *nifp, ifnet; 10855163Sshin#ifndef __NetBSD__ 10955163Sshin struct arpcom arpcom; 11055163Sshin#else 11155163Sshin struct ethercom ec; 11255163Sshin struct sockaddr_dl sdl; 11355163Sshin#endif 11455163Sshin 11555163Sshin if ((kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf)) == NULL) { 11655163Sshin perror("kvm_openfiles"); 11755163Sshin exit(1); 11855163Sshin } 11955163Sshin if (kvm_nlist(kvmd, nl) < 0) { 12055163Sshin perror("kvm_nlist"); 12155163Sshin exit(1); 12255163Sshin } 12355163Sshin if (nl[N_IFNET].n_value == 0) { 12455163Sshin printf("symbol %s not found\n", nl[N_IFNET].n_name); 12555163Sshin exit(1); 12655163Sshin } 12755163Sshin KREAD(nl[N_IFNET].n_value, &ifp, struct ifnet *); 12855163Sshin while (ifp) { 12955163Sshin KREAD(ifp, &ifnet, struct ifnet); 13055163Sshin printf("%s:\n", if_indextoname(ifnet.if_index, ifname)); 13155163Sshin 13255163Sshin#if defined(__NetBSD__) || defined(__OpenBSD__) 13355163Sshin if6_addrlist(ifnet.if_addrlist.tqh_first); 13455163Sshin nifp = ifnet.if_list.tqe_next; 13555163Sshin#elif defined(__FreeBSD__) && __FreeBSD__ >= 3 13655163Sshin if6_addrlist(TAILQ_FIRST(&ifnet.if_addrhead)); 13755163Sshin nifp = ifnet.if_link.tqe_next; 13855163Sshin#else 13955163Sshin if6_addrlist(ifnet.if_addrlist); 14055163Sshin nifp = ifnet.if_next; 14155163Sshin#endif 14255163Sshin 14355163Sshin#ifdef __NetBSD__ 14455163Sshin KREAD(ifnet.if_sadl, &sdl, struct sockaddr_dl); 14555163Sshin if (sdl.sdl_type == IFT_ETHER) { 14655163Sshin printf("\tenaddr %s", 14755163Sshin ether_ntoa((struct ether_addr *)LLADDR(&sdl))); 14855163Sshin KREAD(ifp, &ec, struct ethercom); 14955163Sshin printf(" multicnt %d", ec.ec_multicnt); 15055163Sshin acmc(ec.ec_multiaddrs.lh_first); 15155163Sshin printf("\n"); 15255163Sshin } 15355163Sshin#elif defined(__FreeBSD__) && __FreeBSD__ >= 3 15455163Sshin /* not supported */ 15555163Sshin#else 15655163Sshin if (ifnet.if_type == IFT_ETHER) { 15755163Sshin KREAD(ifp, &arpcom, struct arpcom); 15855163Sshin printf("\tenaddr %s", 15955163Sshin ether_ntoa((struct ether_addr *)arpcom.ac_enaddr)); 16055163Sshin KREAD(ifp, &arpcom, struct arpcom); 16155163Sshin printf(" multicnt %d", arpcom.ac_multicnt); 16255163Sshin#ifdef __OpenBSD__ 16355163Sshin acmc(arpcom.ac_multiaddrs.lh_first); 16455163Sshin#else 16555163Sshin acmc(arpcom.ac_multiaddrs); 16655163Sshin#endif 16755163Sshin printf("\n"); 16855163Sshin } 16955163Sshin#endif 17055163Sshin 17155163Sshin ifp = nifp; 17255163Sshin } 17355163Sshin 17455163Sshin exit(0); 17555163Sshin /*NOTREACHED*/ 17655163Sshin} 17755163Sshin 17855163Sshinchar *ifname(ifp) 17955163Sshin struct ifnet *ifp; 18055163Sshin{ 18155163Sshin static char buf[BUFSIZ]; 18255163Sshin 18355163Sshin#if defined(__NetBSD__) || defined(__OpenBSD__) 18455163Sshin KREAD(ifp->if_xname, buf, IFNAMSIZ); 18555163Sshin#else 18655163Sshin KREAD(ifp->if_name, buf, IFNAMSIZ); 18755163Sshin#endif 18855163Sshin return buf; 18955163Sshin} 19055163Sshin 19155163Sshinvoid kread(addr, buf, len) 19255163Sshin u_long addr; 19355163Sshin void *buf; 19455163Sshin int len; 19555163Sshin{ 19655163Sshin if (kvm_read(kvmd, addr, buf, len) != len) { 19755163Sshin perror("kvm_read"); 19855163Sshin exit(1); 19955163Sshin } 20055163Sshin} 20155163Sshin 20255163Sshin#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) 20355163Sshinvoid acmc(am) 20455163Sshin struct ether_multi *am; 20555163Sshin{ 20655163Sshin struct ether_multi em; 20755163Sshin 20855163Sshin while (am) { 20955163Sshin KREAD(am, &em, struct ether_multi); 21055163Sshin 21155163Sshin printf("\n\t\t"); 21255163Sshin printf("%s -- ", ether_ntoa((struct ether_addr *)em.enm_addrlo)); 21355163Sshin printf("%s ", ether_ntoa((struct ether_addr *)&em.enm_addrhi)); 21455163Sshin printf("%d", em.enm_refcount); 21555163Sshin#if !defined(__NetBSD__) && !defined(__OpenBSD__) 21655163Sshin am = em.enm_next; 21755163Sshin#else 21855163Sshin am = em.enm_list.le_next; 21955163Sshin#endif 22055163Sshin } 22155163Sshin} 22255163Sshin#endif 22355163Sshin 22455163Sshinvoid 22555163Sshinif6_addrlist(ifap) 22655163Sshin struct ifaddr *ifap; 22755163Sshin{ 22855163Sshin static char in6buf[BUFSIZ]; 22955163Sshin struct ifaddr ifa; 23055163Sshin struct sockaddr sa; 23155163Sshin struct in6_ifaddr if6a; 23255163Sshin struct in6_multi *mc = 0; 23355163Sshin#if defined(__FreeBSD__) && __FreeBSD__ >= 3 23455163Sshin struct ifaddr *ifap0; 23555163Sshin#endif /* __FreeBSD__ >= 3 */ 23655163Sshin 23755163Sshin#if defined(__FreeBSD__) && __FreeBSD__ >= 3 23855163Sshin ifap0 = ifap; 23955163Sshin#endif /* __FreeBSD__ >= 3 */ 24055163Sshin while (ifap) { 24155163Sshin KREAD(ifap, &ifa, struct ifaddr); 24255163Sshin if (ifa.ifa_addr == NULL) 24355163Sshin goto nextifap; 24455163Sshin KREAD(ifa.ifa_addr, &sa, struct sockaddr); 24555163Sshin if (sa.sa_family != PF_INET6) 24655163Sshin goto nextifap; 24755163Sshin KREAD(ifap, &if6a, struct in6_ifaddr); 24855163Sshin printf("\tinet6 %s\n", 24955163Sshin inet_ntop(AF_INET6, 25055163Sshin (const void *)&if6a.ia_addr.sin6_addr, 25155163Sshin in6buf, sizeof(in6buf))); 25255163Sshin#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) 25355163Sshin mc = mc ? mc : if6a.ia6_multiaddrs.lh_first; 25455163Sshin#endif 25555163Sshin nextifap: 25655163Sshin#if defined(__NetBSD__) || defined(__OpenBSD__) 25755163Sshin ifap = ifa.ifa_list.tqe_next; 25855163Sshin#elif defined(__FreeBSD__) && __FreeBSD__ >= 3 25955163Sshin ifap = ifa.ifa_link.tqe_next; 26055163Sshin#else 26155163Sshin ifap = ifa.ifa_next; 26255163Sshin#endif /* __FreeBSD__ >= 3 */ 26355163Sshin } 26455163Sshin#if defined(__FreeBSD__) && __FreeBSD__ >= 3 26555163Sshin if (ifap0) { 26655163Sshin struct ifnet ifnet; 26755163Sshin struct ifmultiaddr ifm, *ifmp = 0; 26855163Sshin struct sockaddr_in6 sin6; 26955163Sshin struct in6_multi in6m; 27055163Sshin struct sockaddr_dl sdl; 27155163Sshin int in6_multilist_done = 0; 27255163Sshin 27355163Sshin KREAD(ifap0, &ifa, struct ifaddr); 27455163Sshin KREAD(ifa.ifa_ifp, &ifnet, struct ifnet); 27555163Sshin if (ifnet.if_multiaddrs.lh_first) 27655163Sshin ifmp = ifnet.if_multiaddrs.lh_first; 27755163Sshin while (ifmp) { 27855163Sshin KREAD(ifmp, &ifm, struct ifmultiaddr); 27955163Sshin if (ifm.ifma_addr == NULL) 28055163Sshin goto nextmulti; 28155163Sshin KREAD(ifm.ifma_addr, &sa, struct sockaddr); 28255163Sshin if (sa.sa_family != AF_INET6) 28355163Sshin goto nextmulti; 28455163Sshin (void)in6_multientry((struct in6_multi *) 28555163Sshin ifm.ifma_protospec); 28655163Sshin if (ifm.ifma_lladdr == 0) 28755163Sshin goto nextmulti; 28855163Sshin KREAD(ifm.ifma_lladdr, &sdl, struct sockaddr_dl); 28955163Sshin printf("\t\t\tmcast-macaddr %s multicnt %d\n", 29055163Sshin ether_ntoa((struct ether_addr *)LLADDR(&sdl)), 29155163Sshin ifm.ifma_refcount); 29255163Sshin nextmulti: 29355163Sshin ifmp = ifm.ifma_link.le_next; 29455163Sshin } 29555163Sshin } 29655163Sshin#else 29755163Sshin if (mc) 29855163Sshin in6_multilist(mc); 29955163Sshin#endif 30055163Sshin} 30155163Sshin 30255163Sshinstruct in6_multi * 30355163Sshinin6_multientry(mc) 30455163Sshin struct in6_multi *mc; 30555163Sshin{ 30655163Sshin static char mcbuf[BUFSIZ]; 30755163Sshin struct in6_multi multi; 30855163Sshin 30955163Sshin KREAD(mc, &multi, struct in6_multi); 31055163Sshin printf("\t\tgroup %s\n", inet_ntop(AF_INET6, 31155163Sshin (const void *)&multi.in6m_addr, 31255163Sshin mcbuf, sizeof(mcbuf))); 31355163Sshin return(multi.in6m_entry.le_next); 31455163Sshin} 31555163Sshin 31655163Sshinvoid 31755163Sshinin6_multilist(mc) 31855163Sshin struct in6_multi *mc; 31955163Sshin{ 32055163Sshin while (mc) 32155163Sshin mc = in6_multientry(mc); 32255163Sshin} 32355163Sshin 32455163Sshin#if !defined(__NetBSD__) && !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__OpenBSD__) 32555163Sshinstatic char * 32655163Sshinether_ntoa(e) 32755163Sshin struct ether_addr *e; 32855163Sshin{ 32955163Sshin static char buf[20]; 33055163Sshin u_char *p; 33155163Sshin 33255163Sshin p = (u_char *)e; 33355163Sshin 33455163Sshin snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", 33555163Sshin p[0], p[1], p[2], p[3], p[4], p[5]); 33655163Sshin return buf; 33755163Sshin} 33855163Sshin#endif 339