ifmcstat.c revision 1.3 1 /* $NetBSD: ifmcstat.c,v 1.3 1999/07/07 00:28:29 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 #include <net/if_dl.h>
46 #endif /* __FreeBSD__ >= 3 */
47 #include <netinet/in.h>
48 #ifndef __NetBSD__
49 #ifdef __FreeBSD__
50 #define KERNEL
51 #endif
52 #include <netinet/if_ether.h>
53 #ifdef __FreeBSD__
54 #undef KERNEL
55 #endif
56 #else /* __NetBSD__ */
57 #include <net/if_ether.h>
58 #include <net/if_dl.h>
59 #include <net/if_types.h>
60 #endif /* __NetBSD__ */
61 #include <netinet/in_var.h>
62 #include <arpa/inet.h>
63
64 kvm_t *kvmd;
65
66 struct nlist nl[] = {
67 #define N_IFNET 0
68 { "_ifnet" },
69 { "" },
70 };
71
72 const char *inet6_n2a __P((struct in6_addr *));
73 int main __P((void));
74 char *ifname __P((struct ifnet *));
75 #ifndef __NetBSD__
76 int havearpcom __P((char *));
77 #endif /* __NetBSD__ */
78 void kread __P((u_long, void *, int));
79 #if !defined(__FreeBSD__) || __FreeBSD__ < 3
80 void acmc __P((struct ether_multi *));
81 #else
82 void ifmamc __P((struct ifmultiaddr *ifma_p));
83 #endif /* __FreeBSD__ < 3 */
84 void if6_addrlist __P((struct ifaddr *));
85 void in6_multilist __P((struct in6_multi *));
86 struct in6_multi * in6_multientry __P((struct in6_multi *));
87
88 #define KREAD(addr, buf, type) \
89 kread((u_long)addr, (void *)buf, sizeof(type))
90
91 const char *inet6_n2a(p)
92 struct in6_addr *p;
93 {
94 static char buf[BUFSIZ];
95
96 if (IN6_IS_ADDR_ANY(p))
97 return "*";
98 return inet_ntop(AF_INET6, (void *)p, buf, sizeof(buf));
99 }
100
101 int main()
102 {
103 char buf[_POSIX2_LINE_MAX], ifname[IFNAMSIZ];
104 struct ifnet *ifp, ifnet;
105 #ifndef __NetBSD__
106 struct arpcom arpcom;
107 #else
108 struct ethercom ec;
109 struct sockaddr_dl sdl;
110 #endif
111
112 if ((kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf)) == NULL) {
113 perror("kvm_openfiles");
114 exit(1);
115 }
116 if (kvm_nlist(kvmd, nl) < 0) {
117 perror("kvm_nlist");
118 exit(1);
119 }
120 if (nl[N_IFNET].n_value == 0) {
121 printf("symbol %s not found\n", nl[N_IFNET].n_name);
122 exit(1);
123 }
124 KREAD(nl[N_IFNET].n_value, &ifp, struct ifnet *);
125 while (ifp) {
126 KREAD(ifp, &ifnet, struct ifnet);
127 printf("%s:\n", if_indextoname(ifnet.if_index, ifname));
128
129 #ifndef __NetBSD__
130 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
131 if6_addrlist(TAILQ_FIRST(&ifnet.if_addrhead));
132 ifp = ifnet.if_link.tqe_next;
133 #else /* __FreeBSD__ >= 3 */
134 if6_addrlist(ifnet.if_addrlist);
135
136 if (havearpcom(ifname)) {
137 KREAD(ifp, &arpcom, struct arpcom);
138 printf("\tenaddr %02x:%02x:%02x:%02x:%02x:%02x",
139 arpcom.ac_enaddr[0], arpcom.ac_enaddr[1],
140 arpcom.ac_enaddr[2], arpcom.ac_enaddr[3],
141 arpcom.ac_enaddr[4], arpcom.ac_enaddr[5]);
142 printf(" multicnt %d", arpcom.ac_multicnt);
143 acmc(arpcom.ac_multiaddrs);
144 printf("\n");
145 }
146
147 ifp = ifnet.if_next;
148 #endif /* __FreeBSD__ >= 3 */
149 #else
150 if6_addrlist(ifnet.if_addrlist.tqh_first);
151
152 KREAD(ifnet.if_sadl, &sdl, struct sockaddr_dl);
153 if (sdl.sdl_type == IFT_ETHER) {
154 printf("\tenaddr %s",
155 ether_ntoa((struct ether_addr *)LLADDR(&sdl)));
156 KREAD(ifp, &ec, struct ethercom);
157 printf(" multicnt %d", ec.ec_multicnt);
158 acmc(ec.ec_multiaddrs.lh_first);
159 printf("\n");
160 }
161
162 ifp = ifnet.if_list.tqe_next;
163 #endif
164 }
165
166 exit(0);
167 /*NOTREACHED*/
168 }
169
170 char *ifname(ifp)
171 struct ifnet *ifp;
172 {
173 static char buf[BUFSIZ];
174
175 #ifndef __NetBSD__
176 KREAD(ifp->if_name, buf, IFNAMSIZ);
177 #else
178 KREAD(ifp->if_xname, buf, IFNAMSIZ);
179 #endif
180 return buf;
181 }
182
183 void kread(addr, buf, len)
184 u_long addr;
185 void *buf;
186 int len;
187 {
188 if (kvm_read(kvmd, addr, buf, len) != len) {
189 perror("kvm_read");
190 exit(1);
191 }
192 }
193
194 #ifndef __NetBSD__
195 int havearpcom(p)
196 char *p;
197 {
198 if (strncmp(p, "ne", 2) == 0) return 1;
199 if (strncmp(p, "eo", 2) == 0) return 1;
200 if (strncmp(p, "ep", 2) == 0) return 1;
201 if (strncmp(p, "tn", 2) == 0) return 1;
202 if (strncmp(p, "de", 2) == 0) return 1;
203 if (strncmp(p, "hpp", 3) == 0) return 1;
204 if (strncmp(p, "re", 2) == 0) return 1;
205 if (strncmp(p, "ef", 2) == 0) return 1;
206 if (strncmp(p, "di", 2) == 0) return 1;
207 if (strncmp(p, "we", 2) == 0) return 1;
208 if (strncmp(p, "el", 2) == 0) return 1;
209 if (strncmp(p, "ex", 2) == 0) return 1;
210 if (strncmp(p, "pe", 2) == 0) return 1;
211 if (strncmp(p, "xir", 3) == 0) return 1;
212 if (strncmp(p, "fxp", 2) == 0) return 1;
213 if (strncmp(p, "fe", 2) == 0) return 1;
214 if (strncmp(p, "cnw", 2) == 0) return 1;
215 /* if (strncmp(p, "tr", 2) == 0) return 1; ??? */
216 /* if (strncmp(p, "fea", 3) == 0) return 1; ??? */
217 /* if (strncmp(p, "fpa", 3) == 0) return 1; ??? */
218 /* if (strncmp(p, "te", 2) == 0) return 1; ??? */
219 return 0;
220 }
221 #endif
222
223 #if !defined(__FreeBSD__) || __FreeBSD__ < 3
224 void acmc(am)
225 struct ether_multi *am;
226 {
227 struct ether_multi em;
228
229 while (am) {
230 KREAD(am, &em, struct ether_multi);
231
232 printf("\n\t\t");
233 #ifndef __NetBSD__
234 printf("%02x:%02x:%02x:%02x:%02x:%02x--",
235 em.enm_addrlo[0], em.enm_addrlo[1],
236 em.enm_addrlo[2], em.enm_addrlo[3],
237 em.enm_addrlo[4], em.enm_addrlo[5]);
238 printf("%02x:%02x:%02x:%02x:%02x:%02x",
239 em.enm_addrhi[0], em.enm_addrhi[1],
240 em.enm_addrhi[2], em.enm_addrhi[3],
241 em.enm_addrhi[4], em.enm_addrhi[5]);
242 printf(" %d", em.enm_refcount);
243 am = em.enm_next;
244 #else
245 printf("%s -- ", ether_ntoa((struct ether_addr *)&em.enm_addrlo));
246 printf("%s ", ether_ntoa((struct ether_addr *)&em.enm_addrhi));
247 printf("%d", em.enm_refcount);
248 am = em.enm_list.le_next;
249 #endif
250 }
251 }
252 #endif /* __FreeBSD__ < 3 */
253
254 void
255 if6_addrlist(ifap)
256 struct ifaddr *ifap;
257 {
258 static char in6buf[BUFSIZ];
259 struct ifaddr ifa;
260 struct sockaddr sa;
261 struct in6_ifaddr if6a;
262 struct in6_multi *mc = 0;
263 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
264 struct ifaddr *ifap0;
265 #endif /* __FreeBSD__ >= 3 */
266
267 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
268 ifap0 = ifap;
269 #endif /* __FreeBSD__ >= 3 */
270 while (ifap) {
271 KREAD(ifap, &ifa, struct ifaddr);
272 if (ifa.ifa_addr == NULL)
273 goto nextifap;
274 KREAD(ifa.ifa_addr, &sa, struct sockaddr);
275 if (sa.sa_family != PF_INET6)
276 goto nextifap;
277 KREAD(ifap, &if6a, struct in6_ifaddr);
278 printf("\tinet6 %s\n",
279 inet_ntop(AF_INET6,
280 (const void *)&if6a.ia_addr.sin6_addr,
281 in6buf, sizeof(in6buf)));
282 #if !defined(__FreeBSD__) || __FreeBSD__ < 3
283 mc = mc ? mc : if6a.ia6_multiaddrs.lh_first;
284 #endif /* !__FreeBSD__ || __FreeBSD__ < 3 */
285 nextifap:
286 #ifndef __NetBSD__
287 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
288 ifap = ifa.ifa_link.tqe_next;
289 #else
290 ifap = ifa.ifa_next;
291 #endif /* __FreeBSD__ >= 3 */
292 #else
293 ifap = ifa.ifa_list.tqe_next;
294 #endif
295 }
296 #if defined(__FreeBSD__) && __FreeBSD__ >= 3
297 if (ifap0) {
298 struct ifnet ifnet;
299 struct ifmultiaddr ifm, *ifmp = 0;
300 struct sockaddr_in6 sin6;
301 struct in6_multi in6m;
302 struct sockaddr_dl sdl;
303 int in6_multilist_done = 0;
304
305 KREAD(ifap0, &ifa, struct ifaddr);
306 KREAD(ifa.ifa_ifp, &ifnet, struct ifnet);
307 if (ifnet.if_multiaddrs.lh_first)
308 ifmp = ifnet.if_multiaddrs.lh_first;
309 while (ifmp) {
310 KREAD(ifmp, &ifm, struct ifmultiaddr);
311 if (ifm.ifma_addr == NULL)
312 goto nextmulti;
313 KREAD(ifm.ifma_addr, &sa, struct sockaddr);
314 if (sa.sa_family != AF_INET6)
315 goto nextmulti;
316 (void)in6_multientry((struct in6_multi *)
317 ifm.ifma_protospec);
318 if (ifm.ifma_lladdr == 0)
319 goto nextmulti;
320 KREAD(ifm.ifma_lladdr, &sdl, struct sockaddr_dl);
321 printf("\t\t\tmcast-macaddr %s multicnt %d\n",
322 ether_ntoa((struct ether_addr *)LLADDR(&sdl)),
323 ifm.ifma_refcount);
324 nextmulti:
325 ifmp = ifm.ifma_link.le_next;
326 }
327 }
328 #else
329 if (mc)
330 in6_multilist(mc);
331 #endif /* !__FreeBSD__ || __FreeBSD__ < 3 */
332 }
333
334 struct in6_multi *
335 in6_multientry(mc)
336 struct in6_multi *mc;
337 {
338 static char mcbuf[BUFSIZ];
339 struct in6_multi multi;
340
341 KREAD(mc, &multi, struct in6_multi);
342 printf("\t\tgroup %s\n", inet_ntop(AF_INET6,
343 (const void *)&multi.in6m_addr,
344 mcbuf, sizeof(mcbuf)));
345 return(multi.in6m_entry.le_next);
346 }
347
348 void
349 in6_multilist(mc)
350 struct in6_multi *mc;
351 {
352 while (mc)
353 mc = in6_multientry(mc);
354 }
355