ifmcstat.c revision 55163
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 * $FreeBSD: head/usr.sbin/ifmcstat/ifmcstat.c 55163 1999-12-28 02:37:14Z shin $ 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 63kvm_t *kvmd; 64 65struct nlist nl[] = { 66#define N_IFNET 0 67 { "_ifnet" }, 68 { "" }, 69}; 70 71const char *inet6_n2a __P((struct in6_addr *)); 72int main __P((void)); 73char *ifname __P((struct ifnet *)); 74void kread __P((u_long, void *, int)); 75#if !(defined(__FreeBSD__) && __FreeBSD__ >= 3) 76void acmc __P((struct ether_multi *)); 77#endif 78void if6_addrlist __P((struct ifaddr *)); 79void in6_multilist __P((struct in6_multi *)); 80struct in6_multi * in6_multientry __P((struct in6_multi *)); 81 82#if !defined(__NetBSD__) && !(defined(__FreeBSD__) && __FreeBSD__ >= 3) && !defined(__OpenBSD__) 83#ifdef __bsdi__ 84struct ether_addr { 85 u_int8_t ether_addr_octet[6]; 86}; 87#endif 88static 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 94const 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 104int 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 178char *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 191void 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) 203void 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 224void 225if6_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 302struct in6_multi * 303in6_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 316void 317in6_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__) 325static char * 326ether_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