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