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