ifmcstat.c revision 78064
155163Sshin/* 255163Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 355163Sshin * All rights reserved. 462785Sume * 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. 1662785Sume * 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 78064 2001-06-11 12:39:29Z ume $ 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> 4278064Sume#include <sys/queue.h> 4378064Sume 4455163Sshin#include <net/if.h> 4555543Sshin#include <net/if_var.h> 4655163Sshin#include <net/if_types.h> 4755163Sshin#include <net/if_dl.h> 4855163Sshin#include <netinet/in.h> 4962785Sume#define _KERNEL 5055543Sshin#include <netinet/if_ether.h> 5162785Sume#undef _KERNEL 5255163Sshin#include <netinet/in_var.h> 5355163Sshin#include <arpa/inet.h> 5455163Sshin 5562785Sume#include <netdb.h> 5662785Sume 5755163Sshinkvm_t *kvmd; 5855163Sshin 5955163Sshinstruct nlist nl[] = { 6055163Sshin#define N_IFNET 0 6155163Sshin { "_ifnet" }, 6255163Sshin { "" }, 6355163Sshin}; 6455163Sshin 6555163Sshinconst char *inet6_n2a __P((struct in6_addr *)); 6655163Sshinint main __P((void)); 6755163Sshinchar *ifname __P((struct ifnet *)); 6855163Sshinvoid kread __P((u_long, void *, int)); 6955163Sshinvoid if6_addrlist __P((struct ifaddr *)); 7055163Sshinvoid in6_multilist __P((struct in6_multi *)); 7162785Sumestruct in6_multi * in6_multientry __P((struct in6_multi *)); 7255163Sshin 7355163Sshin#define KREAD(addr, buf, type) \ 7455163Sshin kread((u_long)addr, (void *)buf, sizeof(type)) 7555163Sshin 7662785Sume#ifdef N_IN6_MK 7762785Sumestruct multi6_kludge { 7862785Sume LIST_ENTRY(multi6_kludge) mk_entry; 7962785Sume struct ifnet *mk_ifp; 8062785Sume struct in6_multihead mk_head; 8162785Sume}; 8262785Sume#endif 8362785Sume 8455163Sshinconst char *inet6_n2a(p) 8555163Sshin struct in6_addr *p; 8655163Sshin{ 8762785Sume static char buf[NI_MAXHOST]; 8862785Sume struct sockaddr_in6 sin6; 8962785Sume u_int32_t scopeid; 9062785Sume#ifdef NI_WITHSCOPEID 9162785Sume const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID; 9262785Sume#else 9362785Sume const int niflags = NI_NUMERICHOST; 9462785Sume#endif 9555163Sshin 9662785Sume memset(&sin6, 0, sizeof(sin6)); 9762785Sume sin6.sin6_family = AF_INET6; 9862785Sume sin6.sin6_len = sizeof(struct sockaddr_in6); 9962785Sume sin6.sin6_addr = *p; 10062785Sume if (IN6_IS_ADDR_LINKLOCAL(p) || IN6_IS_ADDR_MC_LINKLOCAL(p)) { 10162785Sume scopeid = ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]); 10262785Sume if (scopeid) { 10362785Sume sin6.sin6_scope_id = scopeid; 10462785Sume sin6.sin6_addr.s6_addr[2] = 0; 10562785Sume sin6.sin6_addr.s6_addr[3] = 0; 10662785Sume } 10762785Sume } 10862785Sume if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len, 10962785Sume buf, sizeof(buf), NULL, 0, niflags) == 0) 11062785Sume return buf; 11162785Sume else 11262785Sume return "(invalid)"; 11355163Sshin} 11455163Sshin 11555163Sshinint main() 11655163Sshin{ 11755163Sshin char buf[_POSIX2_LINE_MAX], ifname[IFNAMSIZ]; 11855163Sshin struct ifnet *ifp, *nifp, ifnet; 11955163Sshin struct arpcom arpcom; 12055163Sshin 12155163Sshin if ((kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf)) == NULL) { 12255163Sshin perror("kvm_openfiles"); 12355163Sshin exit(1); 12455163Sshin } 12555163Sshin if (kvm_nlist(kvmd, nl) < 0) { 12655163Sshin perror("kvm_nlist"); 12755163Sshin exit(1); 12855163Sshin } 12955163Sshin if (nl[N_IFNET].n_value == 0) { 13055163Sshin printf("symbol %s not found\n", nl[N_IFNET].n_name); 13155163Sshin exit(1); 13255163Sshin } 13355163Sshin KREAD(nl[N_IFNET].n_value, &ifp, struct ifnet *); 13455163Sshin while (ifp) { 13555163Sshin KREAD(ifp, &ifnet, struct ifnet); 13655163Sshin printf("%s:\n", if_indextoname(ifnet.if_index, ifname)); 13762785Sume 13855163Sshin if6_addrlist(TAILQ_FIRST(&ifnet.if_addrhead)); 13970520Sphk nifp = TAILQ_NEXT(&ifnet, if_link); 14062785Sume 14162785Sume /* not supported */ 14262785Sume 14362785Sume ifp = nifp; 14455163Sshin } 14555163Sshin 14655163Sshin exit(0); 14755163Sshin /*NOTREACHED*/ 14855163Sshin} 14955163Sshin 15055163Sshinchar *ifname(ifp) 15155163Sshin struct ifnet *ifp; 15255163Sshin{ 15355163Sshin static char buf[BUFSIZ]; 15462785Sume struct ifnet ifnet; 15562785Sume char ifnamebuf[IFNAMSIZ]; 15655163Sshin 15762785Sume KREAD(ifp, &ifnet, struct ifnet); 15862785Sume KREAD(ifnet.if_name, ifnamebuf, sizeof(ifnamebuf)); 15962785Sume snprintf(buf, sizeof(buf), "%s%d", ifnamebuf, 16062785Sume ifnet.if_unit); /* does snprintf allow overlap copy?? */ 16155163Sshin return buf; 16255163Sshin} 16355163Sshin 16455163Sshinvoid kread(addr, buf, len) 16555163Sshin u_long addr; 16655163Sshin void *buf; 16755163Sshin int len; 16855163Sshin{ 16955163Sshin if (kvm_read(kvmd, addr, buf, len) != len) { 17055163Sshin perror("kvm_read"); 17155163Sshin exit(1); 17255163Sshin } 17355163Sshin} 17455163Sshin 17555163Sshinvoid 17655163Sshinif6_addrlist(ifap) 17755163Sshin struct ifaddr *ifap; 17855163Sshin{ 17955163Sshin struct ifaddr ifa; 18062785Sume struct sockaddr sa; 18162785Sume struct in6_ifaddr if6a; 18262785Sume struct in6_multi *mc = 0; 18355543Sshin struct ifaddr *ifap0; 18455163Sshin 18555163Sshin ifap0 = ifap; 18662785Sume while (ifap) { 18755163Sshin KREAD(ifap, &ifa, struct ifaddr); 18855163Sshin if (ifa.ifa_addr == NULL) 18962785Sume goto nextifap; 19055163Sshin KREAD(ifa.ifa_addr, &sa, struct sockaddr); 19155163Sshin if (sa.sa_family != PF_INET6) 19262785Sume goto nextifap; 19355163Sshin KREAD(ifap, &if6a, struct in6_ifaddr); 19462785Sume printf("\tinet6 %s\n", inet6_n2a(&if6a.ia_addr.sin6_addr)); 19562785Sume nextifap: 19670520Sphk ifap = TAILQ_NEXT(&ifa, ifa_link); 19762785Sume } 19862785Sume if (ifap0) { 19962785Sume struct ifnet ifnet; 20062785Sume struct ifmultiaddr ifm, *ifmp = 0; 20162785Sume struct sockaddr_in6 sin6; 20262785Sume struct in6_multi in6m; 20362785Sume struct sockaddr_dl sdl; 20462785Sume int in6_multilist_done = 0; 20555163Sshin 20662785Sume KREAD(ifap0, &ifa, struct ifaddr); 20762785Sume KREAD(ifa.ifa_ifp, &ifnet, struct ifnet); 20872084Sphk if (TAILQ_FIRST(&ifnet.if_multiaddrs)) 20972084Sphk ifmp = TAILQ_FIRST(&ifnet.if_multiaddrs); 21062785Sume while (ifmp) { 21162785Sume KREAD(ifmp, &ifm, struct ifmultiaddr); 21262785Sume if (ifm.ifma_addr == NULL) 21362785Sume goto nextmulti; 21462785Sume KREAD(ifm.ifma_addr, &sa, struct sockaddr); 21562785Sume if (sa.sa_family != AF_INET6) 21662785Sume goto nextmulti; 21762785Sume (void)in6_multientry((struct in6_multi *) 21862785Sume ifm.ifma_protospec); 21962785Sume if (ifm.ifma_lladdr == 0) 22062785Sume goto nextmulti; 22162785Sume KREAD(ifm.ifma_lladdr, &sdl, struct sockaddr_dl); 22262785Sume printf("\t\t\tmcast-macaddr %s multicnt %d\n", 22362785Sume ether_ntoa((struct ether_addr *)LLADDR(&sdl)), 22462785Sume ifm.ifma_refcount); 22562785Sume nextmulti: 22672084Sphk ifmp = TAILQ_NEXT(&ifm, ifma_link); 22762785Sume } 22862785Sume } 22962785Sume#ifdef N_IN6_MK 23062785Sume if (nl[N_IN6_MK].n_value != 0) { 23162785Sume LIST_HEAD(in6_mktype, multi6_kludge) in6_mk; 23262785Sume struct multi6_kludge *mkp, mk; 23362785Sume char *nam; 23462785Sume 23562785Sume KREAD(nl[N_IN6_MK].n_value, &in6_mk, struct in6_mktype); 23662785Sume KREAD(ifap0, &ifa, struct ifaddr); 23762785Sume 23862785Sume nam = strdup(ifname(ifa.ifa_ifp)); 23978064Sume if (!nam) { 24078064Sume fprintf(stderr, "ifmcstat: not enough core\n"); 24178064Sume exit(1); 24278064Sume } 24362785Sume 24470520Sphk LIST_FOREACH(mkp, &in6_mk, mk_entry) { 24562785Sume KREAD(mkp, &mk, struct multi6_kludge); 24662785Sume if (strcmp(nam, ifname(mk.mk_ifp)) == 0 && 24770520Sphk LIST_FIRST(&mk.mk_head)) { 24862785Sume printf("\t(on kludge entry for %s)\n", nam); 24970520Sphk in6_multilist(LIST_FIRST(&mk.mk_head)); 25062785Sume } 25162785Sume } 25262785Sume 25362785Sume free(nam); 25462785Sume } 25562785Sume#endif 25655163Sshin} 25755163Sshin 25862785Sumestruct in6_multi * 25955163Sshinin6_multientry(mc) 26055163Sshin struct in6_multi *mc; 26155163Sshin{ 26255163Sshin struct in6_multi multi; 26355163Sshin 26455163Sshin KREAD(mc, &multi, struct in6_multi); 26562785Sume printf("\t\tgroup %s", inet6_n2a(&multi.in6m_addr)); 26662785Sume printf(" refcnt %u\n", multi.in6m_refcount); 26770520Sphk return(LIST_NEXT(&multi, in6m_entry)); 26855163Sshin} 26962785Sume 27062785Sumevoid 27162785Sumein6_multilist(mc) 27262785Sume struct in6_multi *mc; 27362785Sume{ 27462785Sume while (mc) 27562785Sume mc = in6_multientry(mc); 27662785Sume} 277