Home | History | Annotate | Line # | Download | only in ifmcstat
ifmcstat.c revision 1.5
      1 /*	$NetBSD: ifmcstat.c,v 1.5 1999/12/09 15:34:19 itojun Exp $	*/
      2 
      3 /*
      4  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the project nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 #include <stdio.h>
     33 #include <stdlib.h>
     34 #include <fcntl.h>
     35 #include <kvm.h>
     36 #include <nlist.h>
     37 #include <string.h>
     38 #include <limits.h>
     39 
     40 #include <sys/types.h>
     41 #include <sys/socket.h>
     42 #include <net/if.h>
     43 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
     44 # include <net/if_var.h>
     45 #endif
     46 #include <net/if_types.h>
     47 #include <net/if_dl.h>
     48 #include <netinet/in.h>
     49 #ifndef __NetBSD__
     50 # ifdef	__FreeBSD__
     51 #  define	KERNEL
     52 # endif
     53 # include <netinet/if_ether.h>
     54 # ifdef	__FreeBSD__
     55 #  undef	KERNEL
     56 # endif
     57 #else
     58 # include <net/if_ether.h>
     59 #endif
     60 #include <netinet/in_var.h>
     61 #include <arpa/inet.h>
     62 
     63 kvm_t	*kvmd;
     64 
     65 struct	nlist nl[] = {
     66 #define	N_IFNET	0
     67 	{ "_ifnet" },
     68 	{ "" },
     69 };
     70 
     71 const char *inet6_n2a __P((struct in6_addr *));
     72 int main __P((void));
     73 char *ifname __P((struct ifnet *));
     74 void kread __P((u_long, void *, int));
     75 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
     76 void acmc __P((struct ether_multi *));
     77 #endif
     78 void if6_addrlist __P((struct ifaddr *));
     79 void in6_multilist __P((struct in6_multi *));
     80 struct in6_multi * in6_multientry __P((struct in6_multi *));
     81 
     82 #if !defined(__NetBSD__) && !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__OpenBSD__)
     83 #ifdef __bsdi__
     84 struct ether_addr {
     85 	u_int8_t ether_addr_octet[6];
     86 };
     87 #endif
     88 static char *ether_ntoa __P((struct ether_addr *));
     89 #endif
     90 
     91 #define	KREAD(addr, buf, type) \
     92 	kread((u_long)addr, (void *)buf, sizeof(type))
     93 
     94 const char *inet6_n2a(p)
     95 	struct in6_addr *p;
     96 {
     97 	static char buf[BUFSIZ];
     98 
     99 	if (IN6_IS_ADDR_UNSPECIFIED(p))
    100 		return "*";
    101 	return inet_ntop(AF_INET6, (void *)p, buf, sizeof(buf));
    102 }
    103 
    104 int main()
    105 {
    106 	char	buf[_POSIX2_LINE_MAX], ifname[IFNAMSIZ];
    107 	struct	ifnet	*ifp, *nifp, ifnet;
    108 #ifndef __NetBSD__
    109 	struct	arpcom	arpcom;
    110 #else
    111 	struct ethercom ec;
    112 	struct sockaddr_dl sdl;
    113 #endif
    114 
    115 	if ((kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf)) == NULL) {
    116 		perror("kvm_openfiles");
    117 		exit(1);
    118 	}
    119 	if (kvm_nlist(kvmd, nl) < 0) {
    120 		perror("kvm_nlist");
    121 		exit(1);
    122 	}
    123 	if (nl[N_IFNET].n_value == 0) {
    124 		printf("symbol %s not found\n", nl[N_IFNET].n_name);
    125 		exit(1);
    126 	}
    127 	KREAD(nl[N_IFNET].n_value, &ifp, struct ifnet *);
    128 	while (ifp) {
    129 		KREAD(ifp, &ifnet, struct ifnet);
    130 		printf("%s:\n", if_indextoname(ifnet.if_index, ifname));
    131 
    132 #if defined(__NetBSD__) || defined(__OpenBSD__)
    133 		if6_addrlist(ifnet.if_addrlist.tqh_first);
    134 		nifp = ifnet.if_list.tqe_next;
    135 #elif defined(__FreeBSD__) && __FreeBSD__ >= 3
    136 		if6_addrlist(TAILQ_FIRST(&ifnet.if_addrhead));
    137 		nifp = ifnet.if_link.tqe_next;
    138 #else
    139 		if6_addrlist(ifnet.if_addrlist);
    140 		nifp = ifnet.if_next;
    141 #endif
    142 
    143 #ifdef __NetBSD__
    144 		KREAD(ifnet.if_sadl, &sdl, struct sockaddr_dl);
    145 		if (sdl.sdl_type == IFT_ETHER) {
    146 			printf("\tenaddr %s",
    147 			       ether_ntoa((struct ether_addr *)LLADDR(&sdl)));
    148 			KREAD(ifp, &ec, struct ethercom);
    149 			printf(" multicnt %d", ec.ec_multicnt);
    150 			acmc(ec.ec_multiaddrs.lh_first);
    151 			printf("\n");
    152 		}
    153 #elif defined(__FreeBSD__) && __FreeBSD__ >= 3
    154 		/* not supported */
    155 #else
    156 		if (ifnet.if_type == IFT_ETHER) {
    157 			KREAD(ifp, &arpcom, struct arpcom);
    158 			printf("\tenaddr %s",
    159 			    ether_ntoa((struct ether_addr *)arpcom.ac_enaddr));
    160 			KREAD(ifp, &arpcom, struct arpcom);
    161 			printf(" multicnt %d", arpcom.ac_multicnt);
    162 #ifdef __OpenBSD__
    163 			acmc(arpcom.ac_multiaddrs.lh_first);
    164 #else
    165 			acmc(arpcom.ac_multiaddrs);
    166 #endif
    167 			printf("\n");
    168 		}
    169 #endif
    170 
    171 		ifp = nifp;
    172 	}
    173 
    174 	exit(0);
    175 	/*NOTREACHED*/
    176 }
    177 
    178 char *ifname(ifp)
    179 	struct ifnet *ifp;
    180 {
    181 	static char buf[BUFSIZ];
    182 
    183 #if defined(__NetBSD__) || defined(__OpenBSD__)
    184 	KREAD(ifp->if_xname, buf, IFNAMSIZ);
    185 #else
    186 	KREAD(ifp->if_name, buf, IFNAMSIZ);
    187 #endif
    188 	return buf;
    189 }
    190 
    191 void kread(addr, buf, len)
    192 	u_long addr;
    193 	void *buf;
    194 	int len;
    195 {
    196 	if (kvm_read(kvmd, addr, buf, len) != len) {
    197 		perror("kvm_read");
    198 		exit(1);
    199 	}
    200 }
    201 
    202 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
    203 void acmc(am)
    204 	struct ether_multi *am;
    205 {
    206 	struct ether_multi em;
    207 
    208 	while (am) {
    209 		KREAD(am, &em, struct ether_multi);
    210 
    211 		printf("\n\t\t");
    212 		printf("%s -- ", ether_ntoa((struct ether_addr *)em.enm_addrlo));
    213 		printf("%s ", ether_ntoa((struct ether_addr *)&em.enm_addrhi));
    214 		printf("%d", em.enm_refcount);
    215 #if !defined(__NetBSD__) && !defined(__OpenBSD__)
    216 		am = em.enm_next;
    217 #else
    218 		am = em.enm_list.le_next;
    219 #endif
    220 	}
    221 }
    222 #endif
    223 
    224 void
    225 if6_addrlist(ifap)
    226 	struct ifaddr *ifap;
    227 {
    228 	static char in6buf[BUFSIZ];
    229 	struct ifaddr ifa;
    230 	struct sockaddr sa;
    231 	struct in6_ifaddr if6a;
    232 	struct in6_multi *mc = 0;
    233 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
    234 	struct ifaddr *ifap0;
    235 #endif /* __FreeBSD__ >= 3 */
    236 
    237 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
    238 	ifap0 = ifap;
    239 #endif /* __FreeBSD__ >= 3 */
    240 	while (ifap) {
    241 		KREAD(ifap, &ifa, struct ifaddr);
    242 		if (ifa.ifa_addr == NULL)
    243 			goto nextifap;
    244 		KREAD(ifa.ifa_addr, &sa, struct sockaddr);
    245 		if (sa.sa_family != PF_INET6)
    246 			goto nextifap;
    247 		KREAD(ifap, &if6a, struct in6_ifaddr);
    248 		printf("\tinet6 %s\n",
    249 		       inet_ntop(AF_INET6,
    250 				 (const void *)&if6a.ia_addr.sin6_addr,
    251 				 in6buf, sizeof(in6buf)));
    252 #if !(defined(__FreeBSD__) && __FreeBSD__ >= 3)
    253 		mc = mc ? mc : if6a.ia6_multiaddrs.lh_first;
    254 #endif
    255 	nextifap:
    256 #if defined(__NetBSD__) || defined(__OpenBSD__)
    257 		ifap = ifa.ifa_list.tqe_next;
    258 #elif defined(__FreeBSD__) && __FreeBSD__ >= 3
    259 		ifap = ifa.ifa_link.tqe_next;
    260 #else
    261 		ifap = ifa.ifa_next;
    262 #endif /* __FreeBSD__ >= 3 */
    263 	}
    264 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
    265 	if (ifap0) {
    266 		struct ifnet ifnet;
    267 		struct ifmultiaddr ifm, *ifmp = 0;
    268 		struct sockaddr_in6 sin6;
    269 		struct in6_multi in6m;
    270 		struct sockaddr_dl sdl;
    271 		int in6_multilist_done = 0;
    272 
    273 		KREAD(ifap0, &ifa, struct ifaddr);
    274 		KREAD(ifa.ifa_ifp, &ifnet, struct ifnet);
    275 		if (ifnet.if_multiaddrs.lh_first)
    276 			ifmp = ifnet.if_multiaddrs.lh_first;
    277 		while (ifmp) {
    278 			KREAD(ifmp, &ifm, struct ifmultiaddr);
    279 			if (ifm.ifma_addr == NULL)
    280 				goto nextmulti;
    281 			KREAD(ifm.ifma_addr, &sa, struct sockaddr);
    282 			if (sa.sa_family != AF_INET6)
    283 				goto nextmulti;
    284 			(void)in6_multientry((struct in6_multi *)
    285 					     ifm.ifma_protospec);
    286 			if (ifm.ifma_lladdr == 0)
    287 				goto nextmulti;
    288 			KREAD(ifm.ifma_lladdr, &sdl, struct sockaddr_dl);
    289 			printf("\t\t\tmcast-macaddr %s multicnt %d\n",
    290 			       ether_ntoa((struct ether_addr *)LLADDR(&sdl)),
    291 			       ifm.ifma_refcount);
    292 		    nextmulti:
    293 			ifmp = ifm.ifma_link.le_next;
    294 		}
    295 	}
    296 #else
    297 	if (mc)
    298 		in6_multilist(mc);
    299 #endif
    300 }
    301 
    302 struct in6_multi *
    303 in6_multientry(mc)
    304 	struct in6_multi *mc;
    305 {
    306 	static char mcbuf[BUFSIZ];
    307 	struct in6_multi multi;
    308 
    309 	KREAD(mc, &multi, struct in6_multi);
    310 	printf("\t\tgroup %s\n", inet_ntop(AF_INET6,
    311 					   (const void *)&multi.in6m_addr,
    312 					   mcbuf, sizeof(mcbuf)));
    313 	return(multi.in6m_entry.le_next);
    314 }
    315 
    316 void
    317 in6_multilist(mc)
    318 	struct in6_multi *mc;
    319 {
    320 	while (mc)
    321 		mc = in6_multientry(mc);
    322 }
    323 
    324 #if !defined(__NetBSD__) && !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__OpenBSD__)
    325 static char *
    326 ether_ntoa(e)
    327 	struct ether_addr *e;
    328 {
    329 	static char buf[20];
    330 	u_char *p;
    331 
    332 	p = (u_char *)e;
    333 
    334 	snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
    335 		p[0], p[1], p[2], p[3], p[4], p[5]);
    336 	return buf;
    337 }
    338 #endif
    339