11048e675SBruce M Simpson /* $KAME: ifmcstat.c,v 1.48 2006/11/15 05:13:59 itojun Exp $ */
21048e675SBruce M Simpson
3*8a16b7a1SPedro F. Giffuni /*-
4*8a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
5*8a16b7a1SPedro F. Giffuni *
6d508ff40SBruce M Simpson * Copyright (c) 2007-2009 Bruce Simpson.
77d56d374SYoshinobu Inoue * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
87d56d374SYoshinobu Inoue * All rights reserved.
97d56d374SYoshinobu Inoue *
107d56d374SYoshinobu Inoue * Redistribution and use in source and binary forms, with or without
117d56d374SYoshinobu Inoue * modification, are permitted provided that the following conditions
127d56d374SYoshinobu Inoue * are met:
137d56d374SYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright
147d56d374SYoshinobu Inoue * notice, this list of conditions and the following disclaimer.
157d56d374SYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright
167d56d374SYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the
177d56d374SYoshinobu Inoue * documentation and/or other materials provided with the distribution.
187d56d374SYoshinobu Inoue * 3. Neither the name of the project nor the names of its contributors
197d56d374SYoshinobu Inoue * may be used to endorse or promote products derived from this software
207d56d374SYoshinobu Inoue * without specific prior written permission.
217d56d374SYoshinobu Inoue *
227d56d374SYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
237d56d374SYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
247d56d374SYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
257d56d374SYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
267d56d374SYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
277d56d374SYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
287d56d374SYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
297d56d374SYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
307d56d374SYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
317d56d374SYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
327d56d374SYoshinobu Inoue * SUCH DAMAGE.
337d56d374SYoshinobu Inoue */
347d56d374SYoshinobu Inoue
35cb48db9cSBruce M Simpson #include <sys/types.h>
36cb48db9cSBruce M Simpson #include <sys/param.h>
37d10910e6SBruce M Simpson #include <sys/sysctl.h>
38cb48db9cSBruce M Simpson #include <sys/socket.h>
39cb48db9cSBruce M Simpson #include <sys/queue.h>
40d10910e6SBruce M Simpson #include <sys/tree.h>
41cb48db9cSBruce M Simpson
42cb48db9cSBruce M Simpson #include <net/if.h>
43cb48db9cSBruce M Simpson #include <net/if_types.h>
44cb48db9cSBruce M Simpson #include <net/if_dl.h>
45cb48db9cSBruce M Simpson #include <net/route.h>
46cb48db9cSBruce M Simpson
47cb48db9cSBruce M Simpson #include <netinet/in.h>
48cb48db9cSBruce M Simpson #include <netinet/in_var.h>
49cb48db9cSBruce M Simpson #include <netinet/in_systm.h>
50cb48db9cSBruce M Simpson #include <netinet/ip.h>
51cb48db9cSBruce M Simpson #include <netinet/igmp.h>
52cb48db9cSBruce M Simpson #include <netinet/if_ether.h>
53cb48db9cSBruce M Simpson #include <netinet/igmp_var.h>
54cb48db9cSBruce M Simpson
55cb48db9cSBruce M Simpson #ifdef INET6
56cb48db9cSBruce M Simpson #include <netinet/icmp6.h>
57cb48db9cSBruce M Simpson #include <netinet6/mld6_var.h>
58cb48db9cSBruce M Simpson #endif /* INET6 */
591048e675SBruce M Simpson
607d56d374SYoshinobu Inoue #include <arpa/inet.h>
619bdd4811SHajimu UMEMOTO #include <netdb.h>
629bdd4811SHajimu UMEMOTO
6360dd8da7SBruce M Simpson #include <stddef.h>
6460dd8da7SBruce M Simpson #include <stdarg.h>
6560dd8da7SBruce M Simpson #include <stdint.h>
6660dd8da7SBruce M Simpson #include <stdio.h>
6760dd8da7SBruce M Simpson #include <stdlib.h>
6860dd8da7SBruce M Simpson #include <string.h>
6960dd8da7SBruce M Simpson
7060dd8da7SBruce M Simpson #include <ctype.h>
7160dd8da7SBruce M Simpson #include <err.h>
72d10910e6SBruce M Simpson #include <errno.h>
7360dd8da7SBruce M Simpson #include <fcntl.h>
7460dd8da7SBruce M Simpson #include <limits.h>
7560dd8da7SBruce M Simpson #include <ifaddrs.h>
7660dd8da7SBruce M Simpson #include <sysexits.h>
7760dd8da7SBruce M Simpson #include <unistd.h>
7860dd8da7SBruce M Simpson
79b1499febSGleb Smirnoff #ifdef KVM
80b1499febSGleb Smirnoff /*
81b1499febSGleb Smirnoff * Currently the KVM build is broken. To be fixed it requires uncovering
82b1499febSGleb Smirnoff * large amount of _KERNEL code in include files, and it is also very
83b1499febSGleb Smirnoff * tentative to internal kernel ABI changes. If anyone wishes to restore
84b1499febSGleb Smirnoff * it, please move it out of src/usr.sbin to src/tools/tools.
85b1499febSGleb Smirnoff */
86b1499febSGleb Smirnoff #include <kvm.h>
87b1499febSGleb Smirnoff #include <nlist.h>
88b1499febSGleb Smirnoff #endif
89b1499febSGleb Smirnoff
90b1499febSGleb Smirnoff /* XXX: This file currently assumes INET support in the base system. */
9160dd8da7SBruce M Simpson #ifndef INET
9260dd8da7SBruce M Simpson #define INET
9360dd8da7SBruce M Simpson #endif
9460dd8da7SBruce M Simpson
95d10910e6SBruce M Simpson extern void printb(const char *, unsigned int, const char *);
96d10910e6SBruce M Simpson
9760dd8da7SBruce M Simpson union sockunion {
9860dd8da7SBruce M Simpson struct sockaddr_storage ss;
9960dd8da7SBruce M Simpson struct sockaddr sa;
10060dd8da7SBruce M Simpson struct sockaddr_dl sdl;
10160dd8da7SBruce M Simpson #ifdef INET
10260dd8da7SBruce M Simpson struct sockaddr_in sin;
10360dd8da7SBruce M Simpson #endif
10460dd8da7SBruce M Simpson #ifdef INET6
10560dd8da7SBruce M Simpson struct sockaddr_in6 sin6;
10660dd8da7SBruce M Simpson #endif
10760dd8da7SBruce M Simpson };
10860dd8da7SBruce M Simpson typedef union sockunion sockunion_t;
10960dd8da7SBruce M Simpson
11060dd8da7SBruce M Simpson uint32_t ifindex = 0;
1111048e675SBruce M Simpson int af = AF_UNSPEC;
112d10910e6SBruce M Simpson #ifdef WITH_KVM
113d10910e6SBruce M Simpson int Kflag = 0;
114d10910e6SBruce M Simpson #endif
115d508ff40SBruce M Simpson int vflag = 0;
1167d56d374SYoshinobu Inoue
11760dd8da7SBruce M Simpson #define sa_dl_equal(a1, a2) \
11860dd8da7SBruce M Simpson ((((struct sockaddr_dl *)(a1))->sdl_len == \
11960dd8da7SBruce M Simpson ((struct sockaddr_dl *)(a2))->sdl_len) && \
12060dd8da7SBruce M Simpson (bcmp(LLADDR((struct sockaddr_dl *)(a1)), \
12160dd8da7SBruce M Simpson LLADDR((struct sockaddr_dl *)(a2)), \
12260dd8da7SBruce M Simpson ((struct sockaddr_dl *)(a1))->sdl_alen) == 0))
12360dd8da7SBruce M Simpson
12460dd8da7SBruce M Simpson /*
12560dd8da7SBruce M Simpson * Most of the code in this utility is to support the use of KVM for
12660dd8da7SBruce M Simpson * post-mortem debugging of the multicast code.
12760dd8da7SBruce M Simpson */
12860dd8da7SBruce M Simpson #ifdef WITH_KVM
12960dd8da7SBruce M Simpson
13060dd8da7SBruce M Simpson #ifdef INET
13160dd8da7SBruce M Simpson static void if_addrlist(struct ifaddr *);
13260dd8da7SBruce M Simpson static struct in_multi *
13360dd8da7SBruce M Simpson in_multientry(struct in_multi *);
13460dd8da7SBruce M Simpson #endif /* INET */
13560dd8da7SBruce M Simpson
13660dd8da7SBruce M Simpson #ifdef INET6
13760dd8da7SBruce M Simpson static void if6_addrlist(struct ifaddr *);
13860dd8da7SBruce M Simpson static struct in6_multi *
13960dd8da7SBruce M Simpson in6_multientry(struct in6_multi *);
14060dd8da7SBruce M Simpson #endif /* INET6 */
14160dd8da7SBruce M Simpson
14260dd8da7SBruce M Simpson static void kread(u_long, void *, int);
143d508ff40SBruce M Simpson static void ll_addrlist(struct ifaddr *);
144d508ff40SBruce M Simpson
14560dd8da7SBruce M Simpson static int ifmcstat_kvm(const char *kernel, const char *core);
1467d56d374SYoshinobu Inoue
1477d56d374SYoshinobu Inoue #define KREAD(addr, buf, type) \
1487d56d374SYoshinobu Inoue kread((u_long)addr, (void *)buf, sizeof(type))
1497d56d374SYoshinobu Inoue
15060dd8da7SBruce M Simpson kvm_t *kvmd;
15160dd8da7SBruce M Simpson struct nlist nl[] = {
15260dd8da7SBruce M Simpson { "_ifnet", 0, 0, 0, 0, },
15360dd8da7SBruce M Simpson { "", 0, 0, 0, 0, },
15460dd8da7SBruce M Simpson };
15560dd8da7SBruce M Simpson #define N_IFNET 0
15660dd8da7SBruce M Simpson
15760dd8da7SBruce M Simpson #endif /* WITH_KVM */
15860dd8da7SBruce M Simpson
15960dd8da7SBruce M Simpson static int ifmcstat_getifmaddrs(void);
160d10910e6SBruce M Simpson #ifdef INET
161d10910e6SBruce M Simpson static void in_ifinfo(struct igmp_ifinfo *);
162d10910e6SBruce M Simpson static const char * inm_mode(u_int mode);
163d10910e6SBruce M Simpson #endif
164d508ff40SBruce M Simpson #ifdef INET6
16533cde130SBruce M Simpson static void in6_ifinfo(struct mld_ifinfo *);
166a038519eSHiroki Sato static const char * inet6_n2a(struct in6_addr *, uint32_t);
167d508ff40SBruce M Simpson #endif
16860dd8da7SBruce M Simpson int main(int, char **);
16960dd8da7SBruce M Simpson
170d508ff40SBruce M Simpson static void
usage()171d508ff40SBruce M Simpson usage()
172d508ff40SBruce M Simpson {
173d508ff40SBruce M Simpson
174d508ff40SBruce M Simpson fprintf(stderr,
175d508ff40SBruce M Simpson "usage: ifmcstat [-i interface] [-f address family]"
176d508ff40SBruce M Simpson " [-v]"
177d508ff40SBruce M Simpson #ifdef WITH_KVM
178d10910e6SBruce M Simpson " [-K] [-M core] [-N system]"
179d508ff40SBruce M Simpson #endif
180d508ff40SBruce M Simpson "\n");
181d508ff40SBruce M Simpson exit(EX_USAGE);
182d508ff40SBruce M Simpson }
183d508ff40SBruce M Simpson
184d10910e6SBruce M Simpson static const char *options = "i:f:vM:N:"
185d10910e6SBruce M Simpson #ifdef WITH_KVM
186d10910e6SBruce M Simpson "K"
187d10910e6SBruce M Simpson #endif
188d10910e6SBruce M Simpson ;
189d10910e6SBruce M Simpson
19060dd8da7SBruce M Simpson int
main(int argc,char ** argv)19160dd8da7SBruce M Simpson main(int argc, char **argv)
19260dd8da7SBruce M Simpson {
19360dd8da7SBruce M Simpson int c, error;
19460dd8da7SBruce M Simpson #ifdef WITH_KVM
19560dd8da7SBruce M Simpson const char *kernel = NULL;
19660dd8da7SBruce M Simpson const char *core = NULL;
19760dd8da7SBruce M Simpson #endif
19860dd8da7SBruce M Simpson
199d10910e6SBruce M Simpson while ((c = getopt(argc, argv, options)) != -1) {
20060dd8da7SBruce M Simpson switch (c) {
20160dd8da7SBruce M Simpson case 'i':
20260dd8da7SBruce M Simpson if ((ifindex = if_nametoindex(optarg)) == 0) {
20360dd8da7SBruce M Simpson fprintf(stderr, "%s: unknown interface\n",
20460dd8da7SBruce M Simpson optarg);
2053f3d246fSBruce M Simpson exit(EX_NOHOST);
20660dd8da7SBruce M Simpson }
20760dd8da7SBruce M Simpson break;
20860dd8da7SBruce M Simpson
20960dd8da7SBruce M Simpson case 'f':
21060dd8da7SBruce M Simpson #ifdef INET
21160dd8da7SBruce M Simpson if (strcmp(optarg, "inet") == 0) {
21260dd8da7SBruce M Simpson af = AF_INET;
21360dd8da7SBruce M Simpson break;
21460dd8da7SBruce M Simpson }
21560dd8da7SBruce M Simpson #endif
21660dd8da7SBruce M Simpson #ifdef INET6
21760dd8da7SBruce M Simpson if (strcmp(optarg, "inet6") == 0) {
21860dd8da7SBruce M Simpson af = AF_INET6;
21960dd8da7SBruce M Simpson break;
22060dd8da7SBruce M Simpson }
22160dd8da7SBruce M Simpson #endif
222d508ff40SBruce M Simpson if (strcmp(optarg, "link") == 0) {
223d508ff40SBruce M Simpson af = AF_LINK;
224d508ff40SBruce M Simpson break;
225d508ff40SBruce M Simpson }
22660dd8da7SBruce M Simpson fprintf(stderr, "%s: unknown address family\n", optarg);
2273f3d246fSBruce M Simpson exit(EX_USAGE);
22860dd8da7SBruce M Simpson /*NOTREACHED*/
22960dd8da7SBruce M Simpson break;
23060dd8da7SBruce M Simpson
231d10910e6SBruce M Simpson #ifdef WITH_KVM
232d10910e6SBruce M Simpson case 'K':
233d10910e6SBruce M Simpson ++Kflag;
234d10910e6SBruce M Simpson break;
235d10910e6SBruce M Simpson #endif
236d10910e6SBruce M Simpson
237d508ff40SBruce M Simpson case 'v':
238d10910e6SBruce M Simpson ++vflag;
239d508ff40SBruce M Simpson break;
240d508ff40SBruce M Simpson
24160dd8da7SBruce M Simpson #ifdef WITH_KVM
24260dd8da7SBruce M Simpson case 'M':
24360dd8da7SBruce M Simpson core = strdup(optarg);
24460dd8da7SBruce M Simpson break;
24560dd8da7SBruce M Simpson
24660dd8da7SBruce M Simpson case 'N':
24760dd8da7SBruce M Simpson kernel = strdup(optarg);
24860dd8da7SBruce M Simpson break;
24960dd8da7SBruce M Simpson #endif
25060dd8da7SBruce M Simpson
25160dd8da7SBruce M Simpson default:
252d508ff40SBruce M Simpson usage();
25360dd8da7SBruce M Simpson break;
25460dd8da7SBruce M Simpson /*NOTREACHED*/
25560dd8da7SBruce M Simpson }
25660dd8da7SBruce M Simpson }
25760dd8da7SBruce M Simpson
258d508ff40SBruce M Simpson if (af == AF_LINK && vflag)
259d508ff40SBruce M Simpson usage();
260d508ff40SBruce M Simpson
26160dd8da7SBruce M Simpson #ifdef WITH_KVM
26229dc7bc6SBruce M Simpson if (Kflag)
26360dd8da7SBruce M Simpson error = ifmcstat_kvm(kernel, core);
26460dd8da7SBruce M Simpson /*
26560dd8da7SBruce M Simpson * If KVM failed, and user did not explicitly specify a core file,
266d10910e6SBruce M Simpson * or force KVM backend to be disabled, try the sysctl backend.
26760dd8da7SBruce M Simpson */
26829dc7bc6SBruce M Simpson if (!Kflag || (error != 0 && (core == NULL && kernel == NULL)))
26960dd8da7SBruce M Simpson #endif
27060dd8da7SBruce M Simpson error = ifmcstat_getifmaddrs();
27160dd8da7SBruce M Simpson if (error != 0)
2723f3d246fSBruce M Simpson exit(EX_OSERR);
27360dd8da7SBruce M Simpson
2743f3d246fSBruce M Simpson exit(EX_OK);
27560dd8da7SBruce M Simpson /*NOTREACHED*/
27660dd8da7SBruce M Simpson }
27760dd8da7SBruce M Simpson
278d10910e6SBruce M Simpson #ifdef INET
279d10910e6SBruce M Simpson
280d10910e6SBruce M Simpson static void
in_ifinfo(struct igmp_ifinfo * igi)281d10910e6SBruce M Simpson in_ifinfo(struct igmp_ifinfo *igi)
282d10910e6SBruce M Simpson {
283d10910e6SBruce M Simpson
284d10910e6SBruce M Simpson printf("\t");
285d10910e6SBruce M Simpson switch (igi->igi_version) {
286d10910e6SBruce M Simpson case IGMP_VERSION_1:
287d10910e6SBruce M Simpson case IGMP_VERSION_2:
288d10910e6SBruce M Simpson case IGMP_VERSION_3:
289d10910e6SBruce M Simpson printf("igmpv%d", igi->igi_version);
290d10910e6SBruce M Simpson break;
291d10910e6SBruce M Simpson default:
292d10910e6SBruce M Simpson printf("igmpv?(%d)", igi->igi_version);
293d10910e6SBruce M Simpson break;
294d10910e6SBruce M Simpson }
295e0418c03SHiroki Sato if (igi->igi_flags)
296d10910e6SBruce M Simpson printb(" flags", igi->igi_flags, "\020\1SILENT\2LOOPBACK");
297d10910e6SBruce M Simpson if (igi->igi_version == IGMP_VERSION_3) {
298d10910e6SBruce M Simpson printf(" rv %u qi %u qri %u uri %u",
299d10910e6SBruce M Simpson igi->igi_rv, igi->igi_qi, igi->igi_qri, igi->igi_uri);
300d10910e6SBruce M Simpson }
301d10910e6SBruce M Simpson if (vflag >= 2) {
302d10910e6SBruce M Simpson printf(" v1timer %u v2timer %u v3timer %u",
303d10910e6SBruce M Simpson igi->igi_v1_timer, igi->igi_v2_timer, igi->igi_v3_timer);
304d10910e6SBruce M Simpson }
305d10910e6SBruce M Simpson printf("\n");
306d10910e6SBruce M Simpson }
307d10910e6SBruce M Simpson
308d10910e6SBruce M Simpson static const char *inm_modes[] = {
309d10910e6SBruce M Simpson "undefined",
310d10910e6SBruce M Simpson "include",
311d10910e6SBruce M Simpson "exclude",
312d10910e6SBruce M Simpson };
313d10910e6SBruce M Simpson
314d10910e6SBruce M Simpson static const char *
inm_mode(u_int mode)315d10910e6SBruce M Simpson inm_mode(u_int mode)
316d10910e6SBruce M Simpson {
317d10910e6SBruce M Simpson
318d10910e6SBruce M Simpson if (mode >= MCAST_UNDEFINED && mode <= MCAST_EXCLUDE)
319d10910e6SBruce M Simpson return (inm_modes[mode]);
320d10910e6SBruce M Simpson return (NULL);
321d10910e6SBruce M Simpson }
322d10910e6SBruce M Simpson
323d10910e6SBruce M Simpson #endif /* INET */
324d10910e6SBruce M Simpson
32560dd8da7SBruce M Simpson #ifdef WITH_KVM
32660dd8da7SBruce M Simpson
32760dd8da7SBruce M Simpson static int
ifmcstat_kvm(const char * kernel,const char * core)32860dd8da7SBruce M Simpson ifmcstat_kvm(const char *kernel, const char *core)
32960dd8da7SBruce M Simpson {
33060dd8da7SBruce M Simpson char buf[_POSIX2_LINE_MAX], ifname[IFNAMSIZ];
33160dd8da7SBruce M Simpson struct ifnet *ifp, *nifp, ifnet;
33260dd8da7SBruce M Simpson
33360dd8da7SBruce M Simpson if ((kvmd = kvm_openfiles(kernel, core, NULL, O_RDONLY, buf)) ==
33460dd8da7SBruce M Simpson NULL) {
33560dd8da7SBruce M Simpson perror("kvm_openfiles");
33660dd8da7SBruce M Simpson return (-1);
33760dd8da7SBruce M Simpson }
33860dd8da7SBruce M Simpson if (kvm_nlist(kvmd, nl) < 0) {
33960dd8da7SBruce M Simpson perror("kvm_nlist");
34060dd8da7SBruce M Simpson return (-1);
34160dd8da7SBruce M Simpson }
34260dd8da7SBruce M Simpson if (nl[N_IFNET].n_value == 0) {
34360dd8da7SBruce M Simpson printf("symbol %s not found\n", nl[N_IFNET].n_name);
34460dd8da7SBruce M Simpson return (-1);
34560dd8da7SBruce M Simpson }
34660dd8da7SBruce M Simpson KREAD(nl[N_IFNET].n_value, &ifp, struct ifnet *);
34760dd8da7SBruce M Simpson while (ifp) {
34860dd8da7SBruce M Simpson KREAD(ifp, &ifnet, struct ifnet);
34960dd8da7SBruce M Simpson nifp = ifnet.if_link.tqe_next;
35060dd8da7SBruce M Simpson if (ifindex && ifindex != ifnet.if_index)
35160dd8da7SBruce M Simpson goto next;
35260dd8da7SBruce M Simpson
35360dd8da7SBruce M Simpson printf("%s:\n", if_indextoname(ifnet.if_index, ifname));
35460dd8da7SBruce M Simpson #ifdef INET
35560dd8da7SBruce M Simpson if_addrlist(TAILQ_FIRST(&ifnet.if_addrhead));
35660dd8da7SBruce M Simpson #endif
35760dd8da7SBruce M Simpson #ifdef INET6
35860dd8da7SBruce M Simpson if6_addrlist(TAILQ_FIRST(&ifnet.if_addrhead));
35960dd8da7SBruce M Simpson #endif
360d508ff40SBruce M Simpson if (vflag)
361d508ff40SBruce M Simpson ll_addrlist(TAILQ_FIRST(&ifnet.if_addrhead));
36260dd8da7SBruce M Simpson next:
36360dd8da7SBruce M Simpson ifp = nifp;
36460dd8da7SBruce M Simpson }
36560dd8da7SBruce M Simpson
36660dd8da7SBruce M Simpson return (0);
36760dd8da7SBruce M Simpson }
36860dd8da7SBruce M Simpson
36960dd8da7SBruce M Simpson static void
kread(u_long addr,void * buf,int len)37060dd8da7SBruce M Simpson kread(u_long addr, void *buf, int len)
37160dd8da7SBruce M Simpson {
37260dd8da7SBruce M Simpson
37360dd8da7SBruce M Simpson if (kvm_read(kvmd, addr, buf, len) != len) {
37460dd8da7SBruce M Simpson perror("kvm_read");
3753f3d246fSBruce M Simpson exit(EX_OSERR);
37660dd8da7SBruce M Simpson }
37760dd8da7SBruce M Simpson }
37860dd8da7SBruce M Simpson
379d508ff40SBruce M Simpson static void
ll_addrlist(struct ifaddr * ifap)380d508ff40SBruce M Simpson ll_addrlist(struct ifaddr *ifap)
3817d56d374SYoshinobu Inoue {
382d508ff40SBruce M Simpson char addrbuf[NI_MAXHOST];
383d508ff40SBruce M Simpson struct ifaddr ifa;
384d508ff40SBruce M Simpson struct sockaddr sa;
385d508ff40SBruce M Simpson struct sockaddr_dl sdl;
386d508ff40SBruce M Simpson struct ifaddr *ifap0;
3877d56d374SYoshinobu Inoue
388d508ff40SBruce M Simpson if (af && af != AF_LINK)
389d508ff40SBruce M Simpson return;
390d508ff40SBruce M Simpson
391d508ff40SBruce M Simpson ifap0 = ifap;
392d508ff40SBruce M Simpson while (ifap) {
393d508ff40SBruce M Simpson KREAD(ifap, &ifa, struct ifaddr);
394d508ff40SBruce M Simpson if (ifa.ifa_addr == NULL)
395d508ff40SBruce M Simpson goto nextifap;
396d508ff40SBruce M Simpson KREAD(ifa.ifa_addr, &sa, struct sockaddr);
397d508ff40SBruce M Simpson if (sa.sa_family != PF_LINK)
398d508ff40SBruce M Simpson goto nextifap;
399d508ff40SBruce M Simpson KREAD(ifa.ifa_addr, &sdl, struct sockaddr_dl);
400d508ff40SBruce M Simpson if (sdl.sdl_alen == 0)
401d508ff40SBruce M Simpson goto nextifap;
402d508ff40SBruce M Simpson addrbuf[0] = '\0';
4034ab8581bSEitan Adler getnameinfo((struct sockaddr *)&sdl, sdl.sdl_len,
404d508ff40SBruce M Simpson addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
405d508ff40SBruce M Simpson printf("\tlink %s\n", addrbuf);
406d508ff40SBruce M Simpson nextifap:
407d508ff40SBruce M Simpson ifap = ifa.ifa_link.tqe_next;
408d508ff40SBruce M Simpson }
409d508ff40SBruce M Simpson if (ifap0) {
410d508ff40SBruce M Simpson struct ifnet ifnet;
411d508ff40SBruce M Simpson struct ifmultiaddr ifm, *ifmp = 0;
412d508ff40SBruce M Simpson
413d508ff40SBruce M Simpson KREAD(ifap0, &ifa, struct ifaddr);
414d508ff40SBruce M Simpson KREAD(ifa.ifa_ifp, &ifnet, struct ifnet);
415d508ff40SBruce M Simpson if (TAILQ_FIRST(&ifnet.if_multiaddrs))
416d508ff40SBruce M Simpson ifmp = TAILQ_FIRST(&ifnet.if_multiaddrs);
417d508ff40SBruce M Simpson while (ifmp) {
418d508ff40SBruce M Simpson KREAD(ifmp, &ifm, struct ifmultiaddr);
419d508ff40SBruce M Simpson if (ifm.ifma_addr == NULL)
420d508ff40SBruce M Simpson goto nextmulti;
421d508ff40SBruce M Simpson KREAD(ifm.ifma_addr, &sa, struct sockaddr);
422d508ff40SBruce M Simpson if (sa.sa_family != AF_LINK)
423d508ff40SBruce M Simpson goto nextmulti;
424d508ff40SBruce M Simpson KREAD(ifm.ifma_addr, &sdl, struct sockaddr_dl);
425d508ff40SBruce M Simpson addrbuf[0] = '\0';
4264ab8581bSEitan Adler getnameinfo((struct sockaddr *)&sdl,
427d508ff40SBruce M Simpson sdl.sdl_len, addrbuf, sizeof(addrbuf),
428d508ff40SBruce M Simpson NULL, 0, NI_NUMERICHOST);
429d508ff40SBruce M Simpson printf("\t\tgroup %s refcnt %d\n",
430d508ff40SBruce M Simpson addrbuf, ifm.ifma_refcount);
431d508ff40SBruce M Simpson nextmulti:
432d508ff40SBruce M Simpson ifmp = TAILQ_NEXT(&ifm, ifma_link);
4339bdd4811SHajimu UMEMOTO }
4349bdd4811SHajimu UMEMOTO }
4357d56d374SYoshinobu Inoue }
4367d56d374SYoshinobu Inoue
437d508ff40SBruce M Simpson #ifdef INET6
438d508ff40SBruce M Simpson
43960dd8da7SBruce M Simpson static void
if6_addrlist(struct ifaddr * ifap)44060dd8da7SBruce M Simpson if6_addrlist(struct ifaddr *ifap)
4417d56d374SYoshinobu Inoue {
44233cde130SBruce M Simpson struct ifnet ifnet;
4437d56d374SYoshinobu Inoue struct ifaddr ifa;
44404e87720SYoshinobu Inoue struct sockaddr sa;
4459bdd4811SHajimu UMEMOTO struct in6_ifaddr if6a;
4469bdd4811SHajimu UMEMOTO struct ifaddr *ifap0;
4477d56d374SYoshinobu Inoue
4481048e675SBruce M Simpson if (af && af != AF_INET6)
4491048e675SBruce M Simpson return;
4507d56d374SYoshinobu Inoue ifap0 = ifap;
4519bdd4811SHajimu UMEMOTO while (ifap) {
4527d56d374SYoshinobu Inoue KREAD(ifap, &ifa, struct ifaddr);
4537d56d374SYoshinobu Inoue if (ifa.ifa_addr == NULL)
4549bdd4811SHajimu UMEMOTO goto nextifap;
4557d56d374SYoshinobu Inoue KREAD(ifa.ifa_addr, &sa, struct sockaddr);
4567d56d374SYoshinobu Inoue if (sa.sa_family != PF_INET6)
4579bdd4811SHajimu UMEMOTO goto nextifap;
4587d56d374SYoshinobu Inoue KREAD(ifap, &if6a, struct in6_ifaddr);
459a038519eSHiroki Sato printf("\tinet6 %s\n", inet6_n2a(&if6a.ia_addr.sin6_addr,
460a038519eSHiroki Sato if6a.ia_addr.sin6_scope_id));
46133cde130SBruce M Simpson /*
46233cde130SBruce M Simpson * Print per-link MLD information, if available.
46333cde130SBruce M Simpson */
46433cde130SBruce M Simpson if (ifa.ifa_ifp != NULL) {
46533cde130SBruce M Simpson struct in6_ifextra ie;
46633cde130SBruce M Simpson struct mld_ifinfo mli;
46733cde130SBruce M Simpson
46833cde130SBruce M Simpson KREAD(ifa.ifa_ifp, &ifnet, struct ifnet);
46933cde130SBruce M Simpson KREAD(ifnet.if_afdata[AF_INET6], &ie,
47033cde130SBruce M Simpson struct in6_ifextra);
47133cde130SBruce M Simpson if (ie.mld_ifinfo != NULL) {
47233cde130SBruce M Simpson KREAD(ie.mld_ifinfo, &mli, struct mld_ifinfo);
47333cde130SBruce M Simpson in6_ifinfo(&mli);
47433cde130SBruce M Simpson }
47533cde130SBruce M Simpson }
4769bdd4811SHajimu UMEMOTO nextifap:
4771048e675SBruce M Simpson ifap = ifa.ifa_link.tqe_next;
4789bdd4811SHajimu UMEMOTO }
4799bdd4811SHajimu UMEMOTO if (ifap0) {
4809bdd4811SHajimu UMEMOTO struct ifnet ifnet;
4819bdd4811SHajimu UMEMOTO struct ifmultiaddr ifm, *ifmp = 0;
4829bdd4811SHajimu UMEMOTO struct sockaddr_dl sdl;
4837d56d374SYoshinobu Inoue
4847d56d374SYoshinobu Inoue KREAD(ifap0, &ifa, struct ifaddr);
4857d56d374SYoshinobu Inoue KREAD(ifa.ifa_ifp, &ifnet, struct ifnet);
4866817526dSPoul-Henning Kamp if (TAILQ_FIRST(&ifnet.if_multiaddrs))
4876817526dSPoul-Henning Kamp ifmp = TAILQ_FIRST(&ifnet.if_multiaddrs);
4889bdd4811SHajimu UMEMOTO while (ifmp) {
4897d56d374SYoshinobu Inoue KREAD(ifmp, &ifm, struct ifmultiaddr);
4907d56d374SYoshinobu Inoue if (ifm.ifma_addr == NULL)
4919bdd4811SHajimu UMEMOTO goto nextmulti;
4927d56d374SYoshinobu Inoue KREAD(ifm.ifma_addr, &sa, struct sockaddr);
4937d56d374SYoshinobu Inoue if (sa.sa_family != AF_INET6)
4949bdd4811SHajimu UMEMOTO goto nextmulti;
4959bdd4811SHajimu UMEMOTO (void)in6_multientry((struct in6_multi *)
4969bdd4811SHajimu UMEMOTO ifm.ifma_protospec);
4977d56d374SYoshinobu Inoue if (ifm.ifma_lladdr == 0)
4989bdd4811SHajimu UMEMOTO goto nextmulti;
4997d56d374SYoshinobu Inoue KREAD(ifm.ifma_lladdr, &sdl, struct sockaddr_dl);
50060dd8da7SBruce M Simpson printf("\t\t\tmcast-macaddr %s refcnt %d\n",
5017d56d374SYoshinobu Inoue ether_ntoa((struct ether_addr *)LLADDR(&sdl)),
5027d56d374SYoshinobu Inoue ifm.ifma_refcount);
5039bdd4811SHajimu UMEMOTO nextmulti:
5046817526dSPoul-Henning Kamp ifmp = TAILQ_NEXT(&ifm, ifma_link);
5059bdd4811SHajimu UMEMOTO }
5069bdd4811SHajimu UMEMOTO }
5079bdd4811SHajimu UMEMOTO }
5089bdd4811SHajimu UMEMOTO
50960dd8da7SBruce M Simpson static struct in6_multi *
in6_multientry(struct in6_multi * mc)51060dd8da7SBruce M Simpson in6_multientry(struct in6_multi *mc)
5117d56d374SYoshinobu Inoue {
5127d56d374SYoshinobu Inoue struct in6_multi multi;
5137d56d374SYoshinobu Inoue
5147d56d374SYoshinobu Inoue KREAD(mc, &multi, struct in6_multi);
515a038519eSHiroki Sato printf("\t\tgroup %s", inet6_n2a(&multi.in6m_addr, 0));
5169bdd4811SHajimu UMEMOTO printf(" refcnt %u\n", multi.in6m_refcount);
5171048e675SBruce M Simpson
5181048e675SBruce M Simpson return (multi.in6m_entry.le_next);
5191048e675SBruce M Simpson }
5201048e675SBruce M Simpson
521cb48db9cSBruce M Simpson #endif /* INET6 */
522cb48db9cSBruce M Simpson
52360dd8da7SBruce M Simpson #ifdef INET
52460dd8da7SBruce M Simpson
52560dd8da7SBruce M Simpson static void
if_addrlist(struct ifaddr * ifap)52660dd8da7SBruce M Simpson if_addrlist(struct ifaddr *ifap)
5271048e675SBruce M Simpson {
5281048e675SBruce M Simpson struct ifaddr ifa;
529d10910e6SBruce M Simpson struct ifnet ifnet;
5301048e675SBruce M Simpson struct sockaddr sa;
5311048e675SBruce M Simpson struct in_ifaddr ia;
5321048e675SBruce M Simpson struct ifaddr *ifap0;
5331048e675SBruce M Simpson
5341048e675SBruce M Simpson if (af && af != AF_INET)
5351048e675SBruce M Simpson return;
5361048e675SBruce M Simpson ifap0 = ifap;
5371048e675SBruce M Simpson while (ifap) {
5381048e675SBruce M Simpson KREAD(ifap, &ifa, struct ifaddr);
5391048e675SBruce M Simpson if (ifa.ifa_addr == NULL)
5401048e675SBruce M Simpson goto nextifap;
5411048e675SBruce M Simpson KREAD(ifa.ifa_addr, &sa, struct sockaddr);
5421048e675SBruce M Simpson if (sa.sa_family != PF_INET)
5431048e675SBruce M Simpson goto nextifap;
5441048e675SBruce M Simpson KREAD(ifap, &ia, struct in_ifaddr);
5451048e675SBruce M Simpson printf("\tinet %s\n", inet_ntoa(ia.ia_addr.sin_addr));
546d10910e6SBruce M Simpson /*
547d10910e6SBruce M Simpson * Print per-link IGMP information, if available.
548d10910e6SBruce M Simpson */
549d10910e6SBruce M Simpson if (ifa.ifa_ifp != NULL) {
550d10910e6SBruce M Simpson struct in_ifinfo ii;
551d10910e6SBruce M Simpson struct igmp_ifinfo igi;
552d10910e6SBruce M Simpson
553d10910e6SBruce M Simpson KREAD(ifa.ifa_ifp, &ifnet, struct ifnet);
554d10910e6SBruce M Simpson KREAD(ifnet.if_afdata[AF_INET], &ii, struct in_ifinfo);
555d10910e6SBruce M Simpson if (ii.ii_igmp != NULL) {
556d10910e6SBruce M Simpson KREAD(ii.ii_igmp, &igi, struct igmp_ifinfo);
557d10910e6SBruce M Simpson in_ifinfo(&igi);
558d10910e6SBruce M Simpson }
559d10910e6SBruce M Simpson }
5601048e675SBruce M Simpson nextifap:
5611048e675SBruce M Simpson ifap = ifa.ifa_link.tqe_next;
5621048e675SBruce M Simpson }
5631048e675SBruce M Simpson if (ifap0) {
5641048e675SBruce M Simpson struct ifmultiaddr ifm, *ifmp = 0;
5651048e675SBruce M Simpson struct sockaddr_dl sdl;
5661048e675SBruce M Simpson
5671048e675SBruce M Simpson KREAD(ifap0, &ifa, struct ifaddr);
5681048e675SBruce M Simpson KREAD(ifa.ifa_ifp, &ifnet, struct ifnet);
5691048e675SBruce M Simpson if (TAILQ_FIRST(&ifnet.if_multiaddrs))
5701048e675SBruce M Simpson ifmp = TAILQ_FIRST(&ifnet.if_multiaddrs);
5711048e675SBruce M Simpson while (ifmp) {
5721048e675SBruce M Simpson KREAD(ifmp, &ifm, struct ifmultiaddr);
5731048e675SBruce M Simpson if (ifm.ifma_addr == NULL)
5741048e675SBruce M Simpson goto nextmulti;
5751048e675SBruce M Simpson KREAD(ifm.ifma_addr, &sa, struct sockaddr);
5761048e675SBruce M Simpson if (sa.sa_family != AF_INET)
5771048e675SBruce M Simpson goto nextmulti;
5781048e675SBruce M Simpson (void)in_multientry((struct in_multi *)
5791048e675SBruce M Simpson ifm.ifma_protospec);
5801048e675SBruce M Simpson if (ifm.ifma_lladdr == 0)
5811048e675SBruce M Simpson goto nextmulti;
5821048e675SBruce M Simpson KREAD(ifm.ifma_lladdr, &sdl, struct sockaddr_dl);
58360dd8da7SBruce M Simpson printf("\t\t\tmcast-macaddr %s refcnt %d\n",
5841048e675SBruce M Simpson ether_ntoa((struct ether_addr *)LLADDR(&sdl)),
5851048e675SBruce M Simpson ifm.ifma_refcount);
5861048e675SBruce M Simpson nextmulti:
5871048e675SBruce M Simpson ifmp = TAILQ_NEXT(&ifm, ifma_link);
5881048e675SBruce M Simpson }
5891048e675SBruce M Simpson }
5901048e675SBruce M Simpson }
5911048e675SBruce M Simpson
592d10910e6SBruce M Simpson static const char *inm_states[] = {
593d10910e6SBruce M Simpson "not-member",
594d10910e6SBruce M Simpson "silent",
595d10910e6SBruce M Simpson "idle",
596d10910e6SBruce M Simpson "lazy",
597d10910e6SBruce M Simpson "sleeping",
598d10910e6SBruce M Simpson "awakening",
599d10910e6SBruce M Simpson "query-pending",
600d10910e6SBruce M Simpson "sg-query-pending",
601d10910e6SBruce M Simpson "leaving"
602d10910e6SBruce M Simpson };
603d10910e6SBruce M Simpson
604d10910e6SBruce M Simpson static const char *
inm_state(u_int state)605d10910e6SBruce M Simpson inm_state(u_int state)
6061048e675SBruce M Simpson {
6071048e675SBruce M Simpson
608d10910e6SBruce M Simpson if (state >= IGMP_NOT_MEMBER && state <= IGMP_LEAVING_MEMBER)
609d10910e6SBruce M Simpson return (inm_states[state]);
6101048e675SBruce M Simpson return (NULL);
6111048e675SBruce M Simpson }
6121048e675SBruce M Simpson
613d10910e6SBruce M Simpson #if 0
614d10910e6SBruce M Simpson static struct ip_msource *
615d10910e6SBruce M Simpson ims_min_kvm(struct in_multi *pinm)
6161048e675SBruce M Simpson {
617d10910e6SBruce M Simpson struct ip_msource ims0;
618d10910e6SBruce M Simpson struct ip_msource *tmp, *parent;
6191048e675SBruce M Simpson
620d10910e6SBruce M Simpson parent = NULL;
621d10910e6SBruce M Simpson tmp = RB_ROOT(&pinm->inm_srcs);
622d10910e6SBruce M Simpson while (tmp) {
623d10910e6SBruce M Simpson parent = tmp;
624d10910e6SBruce M Simpson KREAD(tmp, &ims0, struct ip_msource);
625d10910e6SBruce M Simpson tmp = RB_LEFT(&ims0, ims_link);
6261048e675SBruce M Simpson }
627d10910e6SBruce M Simpson return (parent); /* kva */
6281048e675SBruce M Simpson }
6291048e675SBruce M Simpson
630d10910e6SBruce M Simpson /* XXX This routine is buggy. See RB_NEXT in sys/tree.h. */
631d10910e6SBruce M Simpson static struct ip_msource *
632d10910e6SBruce M Simpson ims_next_kvm(struct ip_msource *ims)
633d10910e6SBruce M Simpson {
634d10910e6SBruce M Simpson struct ip_msource ims0, ims1;
635d10910e6SBruce M Simpson struct ip_msource *tmp;
636d10910e6SBruce M Simpson
637d10910e6SBruce M Simpson KREAD(ims, &ims0, struct ip_msource);
638d10910e6SBruce M Simpson if (RB_RIGHT(&ims0, ims_link)) {
639d10910e6SBruce M Simpson ims = RB_RIGHT(&ims0, ims_link);
640d10910e6SBruce M Simpson KREAD(ims, &ims1, struct ip_msource);
641d10910e6SBruce M Simpson while ((tmp = RB_LEFT(&ims1, ims_link))) {
642d10910e6SBruce M Simpson KREAD(tmp, &ims0, struct ip_msource);
643d10910e6SBruce M Simpson ims = RB_LEFT(&ims0, ims_link);
644d10910e6SBruce M Simpson }
645d10910e6SBruce M Simpson } else {
646d10910e6SBruce M Simpson tmp = RB_PARENT(&ims0, ims_link);
647d10910e6SBruce M Simpson if (tmp) {
648d10910e6SBruce M Simpson KREAD(tmp, &ims1, struct ip_msource);
649d10910e6SBruce M Simpson if (ims == RB_LEFT(&ims1, ims_link))
650d10910e6SBruce M Simpson ims = tmp;
651d10910e6SBruce M Simpson } else {
652d10910e6SBruce M Simpson while ((tmp = RB_PARENT(&ims0, ims_link))) {
653d10910e6SBruce M Simpson KREAD(tmp, &ims1, struct ip_msource);
654d10910e6SBruce M Simpson if (ims == RB_RIGHT(&ims1, ims_link)) {
655d10910e6SBruce M Simpson ims = tmp;
656d10910e6SBruce M Simpson KREAD(ims, &ims0, struct ip_msource);
657d10910e6SBruce M Simpson } else
6581048e675SBruce M Simpson break;
659d10910e6SBruce M Simpson }
660d10910e6SBruce M Simpson ims = RB_PARENT(&ims0, ims_link);
6611048e675SBruce M Simpson }
6621048e675SBruce M Simpson }
663d10910e6SBruce M Simpson return (ims); /* kva */
664d10910e6SBruce M Simpson }
665d10910e6SBruce M Simpson
666d10910e6SBruce M Simpson static void
667d10910e6SBruce M Simpson inm_print_sources_kvm(struct in_multi *pinm)
668d10910e6SBruce M Simpson {
669d10910e6SBruce M Simpson struct ip_msource ims0;
670d10910e6SBruce M Simpson struct ip_msource *ims;
671d10910e6SBruce M Simpson struct in_addr src;
672d10910e6SBruce M Simpson int cnt;
673d10910e6SBruce M Simpson uint8_t fmode;
674d10910e6SBruce M Simpson
675d10910e6SBruce M Simpson cnt = 0;
676d10910e6SBruce M Simpson fmode = pinm->inm_st[1].iss_fmode;
677d10910e6SBruce M Simpson if (fmode == MCAST_UNDEFINED)
678d10910e6SBruce M Simpson return;
679d10910e6SBruce M Simpson for (ims = ims_min_kvm(pinm); ims != NULL; ims = ims_next_kvm(ims)) {
680d10910e6SBruce M Simpson if (cnt == 0)
681d10910e6SBruce M Simpson printf(" srcs ");
682d10910e6SBruce M Simpson KREAD(ims, &ims0, struct ip_msource);
683d10910e6SBruce M Simpson /* Only print sources in-mode at t1. */
684d10910e6SBruce M Simpson if (fmode != ims_get_mode(pinm, ims, 1))
685d10910e6SBruce M Simpson continue;
686d10910e6SBruce M Simpson src.s_addr = htonl(ims0.ims_haddr);
687d10910e6SBruce M Simpson printf("%s%s", (cnt++ == 0 ? "" : ","), inet_ntoa(src));
688d10910e6SBruce M Simpson }
689d10910e6SBruce M Simpson }
690d10910e6SBruce M Simpson #endif
691d10910e6SBruce M Simpson
692d10910e6SBruce M Simpson static struct in_multi *
in_multientry(struct in_multi * pinm)693d10910e6SBruce M Simpson in_multientry(struct in_multi *pinm)
694d10910e6SBruce M Simpson {
695d10910e6SBruce M Simpson struct in_multi inm;
696d10910e6SBruce M Simpson const char *state, *mode;
697d10910e6SBruce M Simpson
698d10910e6SBruce M Simpson KREAD(pinm, &inm, struct in_multi);
699d10910e6SBruce M Simpson printf("\t\tgroup %s", inet_ntoa(inm.inm_addr));
700d10910e6SBruce M Simpson printf(" refcnt %u", inm.inm_refcount);
701d10910e6SBruce M Simpson
702d10910e6SBruce M Simpson state = inm_state(inm.inm_state);
703d10910e6SBruce M Simpson if (state)
704d10910e6SBruce M Simpson printf(" state %s", state);
705d10910e6SBruce M Simpson else
706d10910e6SBruce M Simpson printf(" state (%d)", inm.inm_state);
707d10910e6SBruce M Simpson
708d10910e6SBruce M Simpson mode = inm_mode(inm.inm_st[1].iss_fmode);
709d10910e6SBruce M Simpson if (mode)
710d10910e6SBruce M Simpson printf(" mode %s", mode);
711d10910e6SBruce M Simpson else
712d10910e6SBruce M Simpson printf(" mode (%d)", inm.inm_st[1].iss_fmode);
713d10910e6SBruce M Simpson
714d10910e6SBruce M Simpson if (vflag >= 2) {
715d10910e6SBruce M Simpson printf(" asm %u ex %u in %u rec %u",
716d10910e6SBruce M Simpson (u_int)inm.inm_st[1].iss_asm,
717d10910e6SBruce M Simpson (u_int)inm.inm_st[1].iss_ex,
718d10910e6SBruce M Simpson (u_int)inm.inm_st[1].iss_in,
719d10910e6SBruce M Simpson (u_int)inm.inm_st[1].iss_rec);
720d10910e6SBruce M Simpson }
721d10910e6SBruce M Simpson
722d10910e6SBruce M Simpson #if 0
723d10910e6SBruce M Simpson /* Buggy. */
724d10910e6SBruce M Simpson if (vflag)
725d10910e6SBruce M Simpson inm_print_sources_kvm(&inm);
726d10910e6SBruce M Simpson #endif
727d10910e6SBruce M Simpson
728d10910e6SBruce M Simpson printf("\n");
729d10910e6SBruce M Simpson return (NULL);
730d10910e6SBruce M Simpson }
73160dd8da7SBruce M Simpson
73260dd8da7SBruce M Simpson #endif /* INET */
73360dd8da7SBruce M Simpson
73460dd8da7SBruce M Simpson #endif /* WITH_KVM */
73560dd8da7SBruce M Simpson
736d508ff40SBruce M Simpson #ifdef INET6
73710fa36f0SMaxim Konovalov
73810fa36f0SMaxim Konovalov static void
in6_ifinfo(struct mld_ifinfo * mli)73910fa36f0SMaxim Konovalov in6_ifinfo(struct mld_ifinfo *mli)
74010fa36f0SMaxim Konovalov {
74110fa36f0SMaxim Konovalov
74210fa36f0SMaxim Konovalov printf("\t");
74310fa36f0SMaxim Konovalov switch (mli->mli_version) {
74410fa36f0SMaxim Konovalov case MLD_VERSION_1:
74510fa36f0SMaxim Konovalov case MLD_VERSION_2:
74610fa36f0SMaxim Konovalov printf("mldv%d", mli->mli_version);
74710fa36f0SMaxim Konovalov break;
74810fa36f0SMaxim Konovalov default:
74910fa36f0SMaxim Konovalov printf("mldv?(%d)", mli->mli_version);
75010fa36f0SMaxim Konovalov break;
75110fa36f0SMaxim Konovalov }
752e0418c03SHiroki Sato if (mli->mli_flags)
753a038519eSHiroki Sato printb(" flags", mli->mli_flags, "\020\1SILENT\2USEALLOW");
75410fa36f0SMaxim Konovalov if (mli->mli_version == MLD_VERSION_2) {
75510fa36f0SMaxim Konovalov printf(" rv %u qi %u qri %u uri %u",
75610fa36f0SMaxim Konovalov mli->mli_rv, mli->mli_qi, mli->mli_qri, mli->mli_uri);
75710fa36f0SMaxim Konovalov }
75810fa36f0SMaxim Konovalov if (vflag >= 2) {
75910fa36f0SMaxim Konovalov printf(" v1timer %u v2timer %u", mli->mli_v1_timer,
76010fa36f0SMaxim Konovalov mli->mli_v2_timer);
76110fa36f0SMaxim Konovalov }
76210fa36f0SMaxim Konovalov printf("\n");
76310fa36f0SMaxim Konovalov }
76410fa36f0SMaxim Konovalov
765d508ff40SBruce M Simpson static const char *
inet6_n2a(struct in6_addr * p,uint32_t scope_id)766a038519eSHiroki Sato inet6_n2a(struct in6_addr *p, uint32_t scope_id)
767d508ff40SBruce M Simpson {
768d508ff40SBruce M Simpson static char buf[NI_MAXHOST];
769d508ff40SBruce M Simpson struct sockaddr_in6 sin6;
770d508ff40SBruce M Simpson const int niflags = NI_NUMERICHOST;
771d508ff40SBruce M Simpson
772d508ff40SBruce M Simpson memset(&sin6, 0, sizeof(sin6));
773d508ff40SBruce M Simpson sin6.sin6_family = AF_INET6;
774d508ff40SBruce M Simpson sin6.sin6_len = sizeof(struct sockaddr_in6);
775d508ff40SBruce M Simpson sin6.sin6_addr = *p;
776a038519eSHiroki Sato sin6.sin6_scope_id = scope_id;
777d508ff40SBruce M Simpson if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
7783f3d246fSBruce M Simpson buf, sizeof(buf), NULL, 0, niflags) == 0) {
7793f3d246fSBruce M Simpson return (buf);
7803f3d246fSBruce M Simpson } else {
7813f3d246fSBruce M Simpson return ("(invalid)");
7823f3d246fSBruce M Simpson }
783d508ff40SBruce M Simpson }
784d508ff40SBruce M Simpson #endif /* INET6 */
785d508ff40SBruce M Simpson
786d10910e6SBruce M Simpson #ifdef INET
787d10910e6SBruce M Simpson /*
788d10910e6SBruce M Simpson * Retrieve per-group source filter mode and lists via sysctl.
789d10910e6SBruce M Simpson */
790d10910e6SBruce M Simpson static void
inm_print_sources_sysctl(uint32_t ifindex,struct in_addr gina)791d10910e6SBruce M Simpson inm_print_sources_sysctl(uint32_t ifindex, struct in_addr gina)
792d10910e6SBruce M Simpson {
793d10910e6SBruce M Simpson #define MAX_SYSCTL_TRY 5
794d10910e6SBruce M Simpson int mib[7];
795d10910e6SBruce M Simpson int ntry = 0;
796d10910e6SBruce M Simpson size_t mibsize;
797d10910e6SBruce M Simpson size_t len;
798d10910e6SBruce M Simpson size_t needed;
799d10910e6SBruce M Simpson size_t cnt;
800d10910e6SBruce M Simpson int i;
801d10910e6SBruce M Simpson char *buf;
802d10910e6SBruce M Simpson struct in_addr *pina;
803d10910e6SBruce M Simpson uint32_t *p;
804d10910e6SBruce M Simpson uint32_t fmode;
805d10910e6SBruce M Simpson const char *modestr;
806d10910e6SBruce M Simpson
807bd4862e5SMarcelo Araujo mibsize = nitems(mib);
808d10910e6SBruce M Simpson if (sysctlnametomib("net.inet.ip.mcast.filters", mib, &mibsize) == -1) {
809d10910e6SBruce M Simpson perror("sysctlnametomib");
810d10910e6SBruce M Simpson return;
811d10910e6SBruce M Simpson }
812d10910e6SBruce M Simpson
813d10910e6SBruce M Simpson needed = 0;
814d10910e6SBruce M Simpson mib[5] = ifindex;
815d10910e6SBruce M Simpson mib[6] = gina.s_addr; /* 32 bits wide */
816bd4862e5SMarcelo Araujo mibsize = nitems(mib);
817d10910e6SBruce M Simpson do {
818d10910e6SBruce M Simpson if (sysctl(mib, mibsize, NULL, &needed, NULL, 0) == -1) {
819d10910e6SBruce M Simpson perror("sysctl net.inet.ip.mcast.filters");
820d10910e6SBruce M Simpson return;
821d10910e6SBruce M Simpson }
822d10910e6SBruce M Simpson if ((buf = malloc(needed)) == NULL) {
823d10910e6SBruce M Simpson perror("malloc");
824d10910e6SBruce M Simpson return;
825d10910e6SBruce M Simpson }
826d10910e6SBruce M Simpson if (sysctl(mib, mibsize, buf, &needed, NULL, 0) == -1) {
827d10910e6SBruce M Simpson if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
828d10910e6SBruce M Simpson perror("sysctl");
829d10910e6SBruce M Simpson goto out_free;
830d10910e6SBruce M Simpson }
831d10910e6SBruce M Simpson free(buf);
832d10910e6SBruce M Simpson buf = NULL;
833d10910e6SBruce M Simpson }
834d10910e6SBruce M Simpson } while (buf == NULL);
835d10910e6SBruce M Simpson
836d10910e6SBruce M Simpson len = needed;
837d10910e6SBruce M Simpson if (len < sizeof(uint32_t)) {
838d10910e6SBruce M Simpson perror("sysctl");
839d10910e6SBruce M Simpson goto out_free;
840d10910e6SBruce M Simpson }
841d10910e6SBruce M Simpson
842d10910e6SBruce M Simpson p = (uint32_t *)buf;
843d10910e6SBruce M Simpson fmode = *p++;
844d10910e6SBruce M Simpson len -= sizeof(uint32_t);
845d10910e6SBruce M Simpson
846d10910e6SBruce M Simpson modestr = inm_mode(fmode);
847d10910e6SBruce M Simpson if (modestr)
848d10910e6SBruce M Simpson printf(" mode %s", modestr);
849d10910e6SBruce M Simpson else
850d10910e6SBruce M Simpson printf(" mode (%u)", fmode);
851d10910e6SBruce M Simpson
852d10910e6SBruce M Simpson if (vflag == 0)
853d10910e6SBruce M Simpson goto out_free;
854d10910e6SBruce M Simpson
855d10910e6SBruce M Simpson cnt = len / sizeof(struct in_addr);
856d10910e6SBruce M Simpson pina = (struct in_addr *)p;
857d10910e6SBruce M Simpson
858d10910e6SBruce M Simpson for (i = 0; i < cnt; i++) {
859d10910e6SBruce M Simpson if (i == 0)
860d10910e6SBruce M Simpson printf(" srcs ");
861d10910e6SBruce M Simpson fprintf(stdout, "%s%s", (i == 0 ? "" : ","),
862d10910e6SBruce M Simpson inet_ntoa(*pina++));
863d10910e6SBruce M Simpson len -= sizeof(struct in_addr);
864d10910e6SBruce M Simpson }
865d10910e6SBruce M Simpson if (len > 0) {
866d10910e6SBruce M Simpson fprintf(stderr, "warning: %u trailing bytes from %s\n",
867d10910e6SBruce M Simpson (unsigned int)len, "net.inet.ip.mcast.filters");
868d10910e6SBruce M Simpson }
869d10910e6SBruce M Simpson
870d10910e6SBruce M Simpson out_free:
871d10910e6SBruce M Simpson free(buf);
872d10910e6SBruce M Simpson #undef MAX_SYSCTL_TRY
873d10910e6SBruce M Simpson }
874d10910e6SBruce M Simpson
875d10910e6SBruce M Simpson #endif /* INET */
876d10910e6SBruce M Simpson
87733cde130SBruce M Simpson #ifdef INET6
87833cde130SBruce M Simpson /*
87933cde130SBruce M Simpson * Retrieve MLD per-group source filter mode and lists via sysctl.
88033cde130SBruce M Simpson *
8813df5ecacSUlrich Spörlein * Note: The 128-bit IPv6 group address needs to be segmented into
88233cde130SBruce M Simpson * 32-bit pieces for marshaling to sysctl. So the MIB name ends
88333cde130SBruce M Simpson * up looking like this:
88433cde130SBruce M Simpson * a.b.c.d.e.ifindex.g[0].g[1].g[2].g[3]
88533cde130SBruce M Simpson * Assumes that pgroup originated from the kernel, so its components
88633cde130SBruce M Simpson * are already in network-byte order.
88733cde130SBruce M Simpson */
88833cde130SBruce M Simpson static void
in6m_print_sources_sysctl(uint32_t ifindex,struct in6_addr * pgroup)88933cde130SBruce M Simpson in6m_print_sources_sysctl(uint32_t ifindex, struct in6_addr *pgroup)
89033cde130SBruce M Simpson {
89133cde130SBruce M Simpson #define MAX_SYSCTL_TRY 5
89233cde130SBruce M Simpson char addrbuf[INET6_ADDRSTRLEN];
89333cde130SBruce M Simpson int mib[10];
89433cde130SBruce M Simpson int ntry = 0;
89533cde130SBruce M Simpson int *pi;
89633cde130SBruce M Simpson size_t mibsize;
89733cde130SBruce M Simpson size_t len;
89833cde130SBruce M Simpson size_t needed;
89933cde130SBruce M Simpson size_t cnt;
90033cde130SBruce M Simpson int i;
90133cde130SBruce M Simpson char *buf;
90233cde130SBruce M Simpson struct in6_addr *pina;
90333cde130SBruce M Simpson uint32_t *p;
90433cde130SBruce M Simpson uint32_t fmode;
90533cde130SBruce M Simpson const char *modestr;
90633cde130SBruce M Simpson
907bd4862e5SMarcelo Araujo mibsize = nitems(mib);
90833cde130SBruce M Simpson if (sysctlnametomib("net.inet6.ip6.mcast.filters", mib,
90933cde130SBruce M Simpson &mibsize) == -1) {
91033cde130SBruce M Simpson perror("sysctlnametomib");
91133cde130SBruce M Simpson return;
91233cde130SBruce M Simpson }
91333cde130SBruce M Simpson
91433cde130SBruce M Simpson needed = 0;
91533cde130SBruce M Simpson mib[5] = ifindex;
91633cde130SBruce M Simpson pi = (int *)pgroup;
91733cde130SBruce M Simpson for (i = 0; i < 4; i++)
91833cde130SBruce M Simpson mib[6 + i] = *pi++;
91933cde130SBruce M Simpson
920bd4862e5SMarcelo Araujo mibsize = nitems(mib);
92133cde130SBruce M Simpson do {
92233cde130SBruce M Simpson if (sysctl(mib, mibsize, NULL, &needed, NULL, 0) == -1) {
92333cde130SBruce M Simpson perror("sysctl net.inet6.ip6.mcast.filters");
92433cde130SBruce M Simpson return;
92533cde130SBruce M Simpson }
92633cde130SBruce M Simpson if ((buf = malloc(needed)) == NULL) {
92733cde130SBruce M Simpson perror("malloc");
92833cde130SBruce M Simpson return;
92933cde130SBruce M Simpson }
93033cde130SBruce M Simpson if (sysctl(mib, mibsize, buf, &needed, NULL, 0) == -1) {
93133cde130SBruce M Simpson if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
93233cde130SBruce M Simpson perror("sysctl");
93333cde130SBruce M Simpson goto out_free;
93433cde130SBruce M Simpson }
93533cde130SBruce M Simpson free(buf);
93633cde130SBruce M Simpson buf = NULL;
93733cde130SBruce M Simpson }
93833cde130SBruce M Simpson } while (buf == NULL);
93933cde130SBruce M Simpson
94033cde130SBruce M Simpson len = needed;
94133cde130SBruce M Simpson if (len < sizeof(uint32_t)) {
94233cde130SBruce M Simpson perror("sysctl");
94333cde130SBruce M Simpson goto out_free;
94433cde130SBruce M Simpson }
94533cde130SBruce M Simpson
94633cde130SBruce M Simpson p = (uint32_t *)buf;
94733cde130SBruce M Simpson fmode = *p++;
94833cde130SBruce M Simpson len -= sizeof(uint32_t);
94933cde130SBruce M Simpson
95033cde130SBruce M Simpson modestr = inm_mode(fmode);
95133cde130SBruce M Simpson if (modestr)
95233cde130SBruce M Simpson printf(" mode %s", modestr);
95333cde130SBruce M Simpson else
95433cde130SBruce M Simpson printf(" mode (%u)", fmode);
95533cde130SBruce M Simpson
95633cde130SBruce M Simpson if (vflag == 0)
95733cde130SBruce M Simpson goto out_free;
95833cde130SBruce M Simpson
95933cde130SBruce M Simpson cnt = len / sizeof(struct in6_addr);
96033cde130SBruce M Simpson pina = (struct in6_addr *)p;
96133cde130SBruce M Simpson
96233cde130SBruce M Simpson for (i = 0; i < cnt; i++) {
96333cde130SBruce M Simpson if (i == 0)
96433cde130SBruce M Simpson printf(" srcs ");
96533cde130SBruce M Simpson inet_ntop(AF_INET6, (const char *)pina++, addrbuf,
96633cde130SBruce M Simpson INET6_ADDRSTRLEN);
96733cde130SBruce M Simpson fprintf(stdout, "%s%s", (i == 0 ? "" : ","), addrbuf);
96833cde130SBruce M Simpson len -= sizeof(struct in6_addr);
96933cde130SBruce M Simpson }
97033cde130SBruce M Simpson if (len > 0) {
97133cde130SBruce M Simpson fprintf(stderr, "warning: %u trailing bytes from %s\n",
97233cde130SBruce M Simpson (unsigned int)len, "net.inet6.ip6.mcast.filters");
97333cde130SBruce M Simpson }
97433cde130SBruce M Simpson
97533cde130SBruce M Simpson out_free:
97633cde130SBruce M Simpson free(buf);
97733cde130SBruce M Simpson #undef MAX_SYSCTL_TRY
97833cde130SBruce M Simpson }
97933cde130SBruce M Simpson #endif /* INET6 */
98033cde130SBruce M Simpson
98160dd8da7SBruce M Simpson static int
ifmcstat_getifmaddrs(void)98260dd8da7SBruce M Simpson ifmcstat_getifmaddrs(void)
98360dd8da7SBruce M Simpson {
98460dd8da7SBruce M Simpson char thisifname[IFNAMSIZ];
985d508ff40SBruce M Simpson char addrbuf[NI_MAXHOST];
98660dd8da7SBruce M Simpson struct ifaddrs *ifap, *ifa;
98760dd8da7SBruce M Simpson struct ifmaddrs *ifmap, *ifma;
98860dd8da7SBruce M Simpson sockunion_t lastifasa;
98960dd8da7SBruce M Simpson sockunion_t *psa, *pgsa, *pllsa, *pifasa;
99060dd8da7SBruce M Simpson char *pcolon;
99160dd8da7SBruce M Simpson char *pafname;
99260dd8da7SBruce M Simpson uint32_t lastifindex, thisifindex;
99360dd8da7SBruce M Simpson int error;
99460dd8da7SBruce M Simpson
99560dd8da7SBruce M Simpson error = 0;
99660dd8da7SBruce M Simpson ifap = NULL;
99760dd8da7SBruce M Simpson ifmap = NULL;
99860dd8da7SBruce M Simpson lastifindex = 0;
99960dd8da7SBruce M Simpson thisifindex = 0;
100060dd8da7SBruce M Simpson lastifasa.ss.ss_family = AF_UNSPEC;
100160dd8da7SBruce M Simpson
100260dd8da7SBruce M Simpson if (getifaddrs(&ifap) != 0) {
100360dd8da7SBruce M Simpson warn("getifmaddrs");
100460dd8da7SBruce M Simpson return (-1);
100560dd8da7SBruce M Simpson }
100660dd8da7SBruce M Simpson
100760dd8da7SBruce M Simpson if (getifmaddrs(&ifmap) != 0) {
100860dd8da7SBruce M Simpson warn("getifmaddrs");
100960dd8da7SBruce M Simpson error = -1;
101060dd8da7SBruce M Simpson goto out;
101160dd8da7SBruce M Simpson }
101260dd8da7SBruce M Simpson
101360dd8da7SBruce M Simpson for (ifma = ifmap; ifma; ifma = ifma->ifma_next) {
101460dd8da7SBruce M Simpson error = 0;
101560dd8da7SBruce M Simpson if (ifma->ifma_name == NULL || ifma->ifma_addr == NULL)
101660dd8da7SBruce M Simpson continue;
101760dd8da7SBruce M Simpson
101860dd8da7SBruce M Simpson psa = (sockunion_t *)ifma->ifma_name;
101960dd8da7SBruce M Simpson if (psa->sa.sa_family != AF_LINK) {
102060dd8da7SBruce M Simpson fprintf(stderr,
102160dd8da7SBruce M Simpson "WARNING: Kernel returned invalid data.\n");
102260dd8da7SBruce M Simpson error = -1;
102360dd8da7SBruce M Simpson break;
102460dd8da7SBruce M Simpson }
102560dd8da7SBruce M Simpson
102660dd8da7SBruce M Simpson /* Filter on interface name. */
102760dd8da7SBruce M Simpson thisifindex = psa->sdl.sdl_index;
102860dd8da7SBruce M Simpson if (ifindex != 0 && thisifindex != ifindex)
102960dd8da7SBruce M Simpson continue;
103060dd8da7SBruce M Simpson
103160dd8da7SBruce M Simpson /* Filter on address family. */
103260dd8da7SBruce M Simpson pgsa = (sockunion_t *)ifma->ifma_addr;
103360dd8da7SBruce M Simpson if (af != 0 && pgsa->sa.sa_family != af)
103460dd8da7SBruce M Simpson continue;
103560dd8da7SBruce M Simpson
103660dd8da7SBruce M Simpson strlcpy(thisifname, link_ntoa(&psa->sdl), IFNAMSIZ);
103760dd8da7SBruce M Simpson pcolon = strchr(thisifname, ':');
103860dd8da7SBruce M Simpson if (pcolon)
103960dd8da7SBruce M Simpson *pcolon = '\0';
104060dd8da7SBruce M Simpson
104160dd8da7SBruce M Simpson /* Only print the banner for the first ifmaddrs entry. */
104260dd8da7SBruce M Simpson if (lastifindex == 0 || lastifindex != thisifindex) {
104360dd8da7SBruce M Simpson lastifindex = thisifindex;
104460dd8da7SBruce M Simpson fprintf(stdout, "%s:\n", thisifname);
104560dd8da7SBruce M Simpson }
104660dd8da7SBruce M Simpson
104760dd8da7SBruce M Simpson /*
104860dd8da7SBruce M Simpson * Currently, multicast joins only take place on the
104960dd8da7SBruce M Simpson * primary IPv4 address, and only on the link-local IPv6
105060dd8da7SBruce M Simpson * address, as per IGMPv2/3 and MLDv1/2 semantics.
105160dd8da7SBruce M Simpson * Therefore, we only look up the primary address on
105260dd8da7SBruce M Simpson * the first pass.
105360dd8da7SBruce M Simpson */
105460dd8da7SBruce M Simpson pifasa = NULL;
105560dd8da7SBruce M Simpson for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
105660dd8da7SBruce M Simpson if ((strcmp(ifa->ifa_name, thisifname) != 0) ||
105760dd8da7SBruce M Simpson (ifa->ifa_addr == NULL) ||
105860dd8da7SBruce M Simpson (ifa->ifa_addr->sa_family != pgsa->sa.sa_family))
105960dd8da7SBruce M Simpson continue;
106060dd8da7SBruce M Simpson /*
106160dd8da7SBruce M Simpson * For AF_INET6 only the link-local address should
1062d508ff40SBruce M Simpson * be returned. If built without IPv6 support,
1063d508ff40SBruce M Simpson * skip this address entirely.
106460dd8da7SBruce M Simpson */
106560dd8da7SBruce M Simpson pifasa = (sockunion_t *)ifa->ifa_addr;
1066d508ff40SBruce M Simpson if (pifasa->sa.sa_family == AF_INET6
1067d508ff40SBruce M Simpson #ifdef INET6
1068d508ff40SBruce M Simpson && !IN6_IS_ADDR_LINKLOCAL(&pifasa->sin6.sin6_addr)
1069d508ff40SBruce M Simpson #endif
1070d508ff40SBruce M Simpson ) {
107160dd8da7SBruce M Simpson pifasa = NULL;
107260dd8da7SBruce M Simpson continue;
107360dd8da7SBruce M Simpson }
107460dd8da7SBruce M Simpson break;
107560dd8da7SBruce M Simpson }
107660dd8da7SBruce M Simpson if (pifasa == NULL)
107760dd8da7SBruce M Simpson continue; /* primary address not found */
107860dd8da7SBruce M Simpson
1079d508ff40SBruce M Simpson if (!vflag && pifasa->sa.sa_family == AF_LINK)
1080d508ff40SBruce M Simpson continue;
1081d508ff40SBruce M Simpson
108260dd8da7SBruce M Simpson /* Parse and print primary address, if not already printed. */
108360dd8da7SBruce M Simpson if (lastifasa.ss.ss_family == AF_UNSPEC ||
108460dd8da7SBruce M Simpson ((lastifasa.ss.ss_family == AF_LINK &&
108560dd8da7SBruce M Simpson !sa_dl_equal(&lastifasa.sa, &pifasa->sa)) ||
108660dd8da7SBruce M Simpson !sa_equal(&lastifasa.sa, &pifasa->sa))) {
108760dd8da7SBruce M Simpson
108860dd8da7SBruce M Simpson switch (pifasa->sa.sa_family) {
108960dd8da7SBruce M Simpson case AF_INET:
109060dd8da7SBruce M Simpson pafname = "inet";
109160dd8da7SBruce M Simpson break;
109260dd8da7SBruce M Simpson case AF_INET6:
109360dd8da7SBruce M Simpson pafname = "inet6";
109460dd8da7SBruce M Simpson break;
109560dd8da7SBruce M Simpson case AF_LINK:
109660dd8da7SBruce M Simpson pafname = "link";
109760dd8da7SBruce M Simpson break;
109860dd8da7SBruce M Simpson default:
109960dd8da7SBruce M Simpson pafname = "unknown";
110060dd8da7SBruce M Simpson break;
110160dd8da7SBruce M Simpson }
110260dd8da7SBruce M Simpson
110360dd8da7SBruce M Simpson switch (pifasa->sa.sa_family) {
110460dd8da7SBruce M Simpson case AF_INET6:
1105d508ff40SBruce M Simpson #ifdef INET6
1106d508ff40SBruce M Simpson {
1107d508ff40SBruce M Simpson const char *p =
1108a038519eSHiroki Sato inet6_n2a(&pifasa->sin6.sin6_addr,
1109a038519eSHiroki Sato pifasa->sin6.sin6_scope_id);
1110d508ff40SBruce M Simpson strlcpy(addrbuf, p, sizeof(addrbuf));
1111d508ff40SBruce M Simpson break;
1112d508ff40SBruce M Simpson }
1113d508ff40SBruce M Simpson #else
1114d508ff40SBruce M Simpson /* FALLTHROUGH */
1115d508ff40SBruce M Simpson #endif
1116d508ff40SBruce M Simpson case AF_INET:
111760dd8da7SBruce M Simpson case AF_LINK:
111860dd8da7SBruce M Simpson error = getnameinfo(&pifasa->sa,
111960dd8da7SBruce M Simpson pifasa->sa.sa_len,
112060dd8da7SBruce M Simpson addrbuf, sizeof(addrbuf), NULL, 0,
112160dd8da7SBruce M Simpson NI_NUMERICHOST);
112260dd8da7SBruce M Simpson if (error)
112360dd8da7SBruce M Simpson perror("getnameinfo");
112460dd8da7SBruce M Simpson break;
112560dd8da7SBruce M Simpson default:
112660dd8da7SBruce M Simpson addrbuf[0] = '\0';
112760dd8da7SBruce M Simpson break;
112860dd8da7SBruce M Simpson }
112960dd8da7SBruce M Simpson
1130e0418c03SHiroki Sato fprintf(stdout, "\t%s %s", pafname, addrbuf);
1131e0418c03SHiroki Sato #ifdef INET6
1132e0418c03SHiroki Sato if (pifasa->sa.sa_family == AF_INET6 &&
1133e0418c03SHiroki Sato pifasa->sin6.sin6_scope_id)
1134e0418c03SHiroki Sato fprintf(stdout, " scopeid 0x%x",
1135e0418c03SHiroki Sato pifasa->sin6.sin6_scope_id);
1136e0418c03SHiroki Sato #endif
1137e0418c03SHiroki Sato fprintf(stdout, "\n");
1138d10910e6SBruce M Simpson #ifdef INET
1139d10910e6SBruce M Simpson /*
1140d10910e6SBruce M Simpson * Print per-link IGMP information, if available.
1141d10910e6SBruce M Simpson */
1142d10910e6SBruce M Simpson if (pifasa->sa.sa_family == AF_INET) {
1143d10910e6SBruce M Simpson struct igmp_ifinfo igi;
1144d10910e6SBruce M Simpson size_t mibsize, len;
1145d10910e6SBruce M Simpson int mib[5];
1146d10910e6SBruce M Simpson
1147bd4862e5SMarcelo Araujo mibsize = nitems(mib);
1148d10910e6SBruce M Simpson if (sysctlnametomib("net.inet.igmp.ifinfo",
1149d10910e6SBruce M Simpson mib, &mibsize) == -1) {
1150d10910e6SBruce M Simpson perror("sysctlnametomib");
1151d10910e6SBruce M Simpson goto next_ifnet;
1152d10910e6SBruce M Simpson }
1153d10910e6SBruce M Simpson mib[mibsize] = thisifindex;
1154d10910e6SBruce M Simpson len = sizeof(struct igmp_ifinfo);
1155d10910e6SBruce M Simpson if (sysctl(mib, mibsize + 1, &igi, &len, NULL,
1156d10910e6SBruce M Simpson 0) == -1) {
1157d10910e6SBruce M Simpson perror("sysctl net.inet.igmp.ifinfo");
1158d10910e6SBruce M Simpson goto next_ifnet;
1159d10910e6SBruce M Simpson }
1160d10910e6SBruce M Simpson in_ifinfo(&igi);
1161d10910e6SBruce M Simpson }
116233cde130SBruce M Simpson #endif /* INET */
116333cde130SBruce M Simpson #ifdef INET6
116433cde130SBruce M Simpson /*
116533cde130SBruce M Simpson * Print per-link MLD information, if available.
116633cde130SBruce M Simpson */
116733cde130SBruce M Simpson if (pifasa->sa.sa_family == AF_INET6) {
116833cde130SBruce M Simpson struct mld_ifinfo mli;
116933cde130SBruce M Simpson size_t mibsize, len;
117033cde130SBruce M Simpson int mib[5];
117133cde130SBruce M Simpson
1172bd4862e5SMarcelo Araujo mibsize = nitems(mib);
117333cde130SBruce M Simpson if (sysctlnametomib("net.inet6.mld.ifinfo",
117433cde130SBruce M Simpson mib, &mibsize) == -1) {
117533cde130SBruce M Simpson perror("sysctlnametomib");
117633cde130SBruce M Simpson goto next_ifnet;
117733cde130SBruce M Simpson }
117833cde130SBruce M Simpson mib[mibsize] = thisifindex;
117933cde130SBruce M Simpson len = sizeof(struct mld_ifinfo);
118033cde130SBruce M Simpson if (sysctl(mib, mibsize + 1, &mli, &len, NULL,
118133cde130SBruce M Simpson 0) == -1) {
118233cde130SBruce M Simpson perror("sysctl net.inet6.mld.ifinfo");
118333cde130SBruce M Simpson goto next_ifnet;
118433cde130SBruce M Simpson }
118533cde130SBruce M Simpson in6_ifinfo(&mli);
118633cde130SBruce M Simpson }
118733cde130SBruce M Simpson #endif /* INET6 */
118833cde130SBruce M Simpson #if defined(INET) || defined(INET6)
1189d10910e6SBruce M Simpson next_ifnet:
1190d10910e6SBruce M Simpson #endif
119160dd8da7SBruce M Simpson lastifasa = *pifasa;
119260dd8da7SBruce M Simpson }
119360dd8da7SBruce M Simpson
119460dd8da7SBruce M Simpson /* Print this group address. */
1195d508ff40SBruce M Simpson #ifdef INET6
1196d508ff40SBruce M Simpson if (pgsa->sa.sa_family == AF_INET6) {
1197a038519eSHiroki Sato const char *p = inet6_n2a(&pgsa->sin6.sin6_addr,
1198a038519eSHiroki Sato pgsa->sin6.sin6_scope_id);
1199d508ff40SBruce M Simpson strlcpy(addrbuf, p, sizeof(addrbuf));
1200d508ff40SBruce M Simpson } else
1201d508ff40SBruce M Simpson #endif
1202d508ff40SBruce M Simpson {
1203d508ff40SBruce M Simpson error = getnameinfo(&pgsa->sa, pgsa->sa.sa_len,
1204d508ff40SBruce M Simpson addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
120560dd8da7SBruce M Simpson if (error)
120660dd8da7SBruce M Simpson perror("getnameinfo");
1207d508ff40SBruce M Simpson }
1208d508ff40SBruce M Simpson
1209d10910e6SBruce M Simpson fprintf(stdout, "\t\tgroup %s", addrbuf);
1210e0418c03SHiroki Sato #ifdef INET6
1211e0418c03SHiroki Sato if (pgsa->sa.sa_family == AF_INET6 &&
1212e0418c03SHiroki Sato pgsa->sin6.sin6_scope_id)
1213e0418c03SHiroki Sato fprintf(stdout, " scopeid 0x%x",
1214e0418c03SHiroki Sato pgsa->sin6.sin6_scope_id);
1215e0418c03SHiroki Sato #endif
1216d10910e6SBruce M Simpson #ifdef INET
1217d10910e6SBruce M Simpson if (pgsa->sa.sa_family == AF_INET) {
1218d10910e6SBruce M Simpson inm_print_sources_sysctl(thisifindex,
1219d10910e6SBruce M Simpson pgsa->sin.sin_addr);
1220d10910e6SBruce M Simpson }
1221d10910e6SBruce M Simpson #endif
122233cde130SBruce M Simpson #ifdef INET6
122333cde130SBruce M Simpson if (pgsa->sa.sa_family == AF_INET6) {
122433cde130SBruce M Simpson in6m_print_sources_sysctl(thisifindex,
122533cde130SBruce M Simpson &pgsa->sin6.sin6_addr);
122633cde130SBruce M Simpson }
122733cde130SBruce M Simpson #endif
1228d10910e6SBruce M Simpson fprintf(stdout, "\n");
122960dd8da7SBruce M Simpson
123060dd8da7SBruce M Simpson /* Link-layer mapping, if present. */
123160dd8da7SBruce M Simpson pllsa = (sockunion_t *)ifma->ifma_lladdr;
123260dd8da7SBruce M Simpson if (pllsa != NULL) {
123315c83493SBruce M Simpson error = getnameinfo(&pllsa->sa, pllsa->sa.sa_len,
123460dd8da7SBruce M Simpson addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
123560dd8da7SBruce M Simpson fprintf(stdout, "\t\t\tmcast-macaddr %s\n", addrbuf);
123660dd8da7SBruce M Simpson }
123760dd8da7SBruce M Simpson }
123860dd8da7SBruce M Simpson out:
123960dd8da7SBruce M Simpson if (ifmap != NULL)
124060dd8da7SBruce M Simpson freeifmaddrs(ifmap);
124160dd8da7SBruce M Simpson if (ifap != NULL)
124260dd8da7SBruce M Simpson freeifaddrs(ifap);
124360dd8da7SBruce M Simpson
124460dd8da7SBruce M Simpson return (error);
124560dd8da7SBruce M Simpson }
1246