xref: /freebsd/usr.sbin/mld6query/mld6.c (revision 4d65a7c6951cea0333f1a0c1b32c38489cdfa6c5)
1f95d4633SHajimu UMEMOTO /*	$KAME: mld6.c,v 1.15 2003/04/02 11:29:54 suz Exp $	*/
233841545SHajimu UMEMOTO 
38a16b7a1SPedro F. Giffuni /*-
48a16b7a1SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
58a16b7a1SPedro F. Giffuni  *
6a61156e3SHajimu UMEMOTO  * Copyright (C) 1998 WIDE Project.
7a61156e3SHajimu UMEMOTO  * All rights reserved.
8a61156e3SHajimu UMEMOTO  *
9a61156e3SHajimu UMEMOTO  * Redistribution and use in source and binary forms, with or without
10a61156e3SHajimu UMEMOTO  * modification, are permitted provided that the following conditions
11a61156e3SHajimu UMEMOTO  * are met:
12a61156e3SHajimu UMEMOTO  * 1. Redistributions of source code must retain the above copyright
13a61156e3SHajimu UMEMOTO  *    notice, this list of conditions and the following disclaimer.
14a61156e3SHajimu UMEMOTO  * 2. Redistributions in binary form must reproduce the above copyright
15a61156e3SHajimu UMEMOTO  *    notice, this list of conditions and the following disclaimer in the
16a61156e3SHajimu UMEMOTO  *    documentation and/or other materials provided with the distribution.
17a61156e3SHajimu UMEMOTO  * 3. Neither the name of the project nor the names of its contributors
18a61156e3SHajimu UMEMOTO  *    may be used to endorse or promote products derived from this software
19a61156e3SHajimu UMEMOTO  *    without specific prior written permission.
20a61156e3SHajimu UMEMOTO  *
21a61156e3SHajimu UMEMOTO  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22a61156e3SHajimu UMEMOTO  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23a61156e3SHajimu UMEMOTO  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24a61156e3SHajimu UMEMOTO  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25a61156e3SHajimu UMEMOTO  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26a61156e3SHajimu UMEMOTO  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27a61156e3SHajimu UMEMOTO  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28a61156e3SHajimu UMEMOTO  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29a61156e3SHajimu UMEMOTO  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30a61156e3SHajimu UMEMOTO  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31a61156e3SHajimu UMEMOTO  * SUCH DAMAGE.
32a61156e3SHajimu UMEMOTO  */
338e724c68SPhilippe Charnier 
34a61156e3SHajimu UMEMOTO #include <sys/param.h>
35a61156e3SHajimu UMEMOTO #include <sys/uio.h>
36a61156e3SHajimu UMEMOTO #include <sys/socket.h>
37a61156e3SHajimu UMEMOTO #include <sys/types.h>
38a61156e3SHajimu UMEMOTO #include <sys/time.h>
39f95d4633SHajimu UMEMOTO #include <ifaddrs.h>
40a61156e3SHajimu UMEMOTO #include <unistd.h>
41a61156e3SHajimu UMEMOTO #include <signal.h>
42a61156e3SHajimu UMEMOTO 
43a61156e3SHajimu UMEMOTO #include <net/if.h>
44a61156e3SHajimu UMEMOTO 
45a61156e3SHajimu UMEMOTO #include <netinet/in.h>
46a61156e3SHajimu UMEMOTO #include <netinet/ip6.h>
47a61156e3SHajimu UMEMOTO #include <netinet/icmp6.h>
48a61156e3SHajimu UMEMOTO 
49a61156e3SHajimu UMEMOTO #include  <arpa/inet.h>
50a61156e3SHajimu UMEMOTO 
51a61156e3SHajimu UMEMOTO #include <stdlib.h>
52a61156e3SHajimu UMEMOTO #include <stdio.h>
53a61156e3SHajimu UMEMOTO #include <string.h>
54a61156e3SHajimu UMEMOTO #include <err.h>
55a61156e3SHajimu UMEMOTO 
56f95d4633SHajimu UMEMOTO /* portability with older KAME headers */
57f95d4633SHajimu UMEMOTO #ifndef MLD_LISTENER_QUERY
58f95d4633SHajimu UMEMOTO #define MLD_LISTENER_QUERY	MLD6_LISTENER_QUERY
59f95d4633SHajimu UMEMOTO #define MLD_LISTENER_REPORT	MLD6_LISTENER_REPORT
60f95d4633SHajimu UMEMOTO #define MLD_LISTENER_DONE	MLD6_LISTENER_DONE
61f95d4633SHajimu UMEMOTO #define MLD_MTRACE_RESP		MLD6_MTRACE_RESP
62f95d4633SHajimu UMEMOTO #define MLD_MTRACE		MLD6_MTRACE
63f95d4633SHajimu UMEMOTO #define mld_hdr		mld6_hdr
64f95d4633SHajimu UMEMOTO #define mld_type	mld6_type
65f95d4633SHajimu UMEMOTO #define mld_code	mld6_code
66f95d4633SHajimu UMEMOTO #define mld_cksum	mld6_cksum
67f95d4633SHajimu UMEMOTO #define mld_maxdelay	mld6_maxdelay
68f95d4633SHajimu UMEMOTO #define mld_reserved	mld6_reserved
69f95d4633SHajimu UMEMOTO #define mld_addr	mld6_addr
70f95d4633SHajimu UMEMOTO #endif
71f95d4633SHajimu UMEMOTO #ifndef IP6OPT_ROUTER_ALERT
72f95d4633SHajimu UMEMOTO #define IP6OPT_ROUTER_ALERT	IP6OPT_RTALERT
73f95d4633SHajimu UMEMOTO #endif
74f95d4633SHajimu UMEMOTO 
75a61156e3SHajimu UMEMOTO struct msghdr m;
76a61156e3SHajimu UMEMOTO struct sockaddr_in6 dst;
77f95d4633SHajimu UMEMOTO struct mld_hdr mldh;
78a61156e3SHajimu UMEMOTO struct in6_addr maddr = IN6ADDR_ANY_INIT, any = IN6ADDR_ANY_INIT;
79a61156e3SHajimu UMEMOTO struct ipv6_mreq mreq;
80a61156e3SHajimu UMEMOTO u_short ifindex;
81a61156e3SHajimu UMEMOTO int s;
82a61156e3SHajimu UMEMOTO 
83a61156e3SHajimu UMEMOTO #define QUERY_RESPONSE_INTERVAL 10000
84a61156e3SHajimu UMEMOTO 
8571cf0564SStephen Hurd void make_msg(int index, struct in6_addr *addr, u_int type, struct in6_addr *qaddr);
86a61156e3SHajimu UMEMOTO void usage(void);
87a61156e3SHajimu UMEMOTO void dump(int);
88a61156e3SHajimu UMEMOTO void quit(int);
89a61156e3SHajimu UMEMOTO 
90a61156e3SHajimu UMEMOTO int
main(int argc,char * argv[])91a61156e3SHajimu UMEMOTO main(int argc, char *argv[])
92a61156e3SHajimu UMEMOTO {
93a61156e3SHajimu UMEMOTO 	int i;
94a61156e3SHajimu UMEMOTO 	struct icmp6_filter filt;
95a61156e3SHajimu UMEMOTO 	u_int hlim = 1;
96a61156e3SHajimu UMEMOTO 	fd_set fdset;
97a61156e3SHajimu UMEMOTO 	struct itimerval itimer;
98a61156e3SHajimu UMEMOTO 	u_int type;
99a61156e3SHajimu UMEMOTO 	int ch;
10071cf0564SStephen Hurd 	struct in6_addr *qaddr = &maddr;
101a61156e3SHajimu UMEMOTO 
102f95d4633SHajimu UMEMOTO 	type = MLD_LISTENER_QUERY;
10371cf0564SStephen Hurd 	while ((ch = getopt(argc, argv, "dgr")) != -1) {
104a61156e3SHajimu UMEMOTO 		switch (ch) {
105a61156e3SHajimu UMEMOTO 		case 'd':
10671cf0564SStephen Hurd 			if (type != MLD_LISTENER_QUERY) {
107*1e95a9a4SElyes Haouas 				printf("Can not specify -d with -r\n");
10871cf0564SStephen Hurd 				return 1;
10971cf0564SStephen Hurd 			}
110f95d4633SHajimu UMEMOTO 			type = MLD_LISTENER_DONE;
111a61156e3SHajimu UMEMOTO 			break;
11271cf0564SStephen Hurd 		case 'g':
11371cf0564SStephen Hurd 			qaddr = &any;
11471cf0564SStephen Hurd 			break;
115a61156e3SHajimu UMEMOTO 		case 'r':
11671cf0564SStephen Hurd 			if (type != MLD_LISTENER_QUERY) {
117*1e95a9a4SElyes Haouas 				printf("Can not specify -r with -d\n");
11871cf0564SStephen Hurd 				return 1;
11971cf0564SStephen Hurd 			}
120f95d4633SHajimu UMEMOTO 			type = MLD_LISTENER_REPORT;
121a61156e3SHajimu UMEMOTO 			break;
122a61156e3SHajimu UMEMOTO 		default:
123a61156e3SHajimu UMEMOTO 			usage();
124a61156e3SHajimu UMEMOTO 			/*NOTREACHED*/
125a61156e3SHajimu UMEMOTO 		}
126a61156e3SHajimu UMEMOTO 	}
127a61156e3SHajimu UMEMOTO 
128a61156e3SHajimu UMEMOTO 	argv += optind;
129a61156e3SHajimu UMEMOTO 	argc -= optind;
130a61156e3SHajimu UMEMOTO 
131a61156e3SHajimu UMEMOTO 	if (argc != 1 && argc != 2)
132a61156e3SHajimu UMEMOTO 		usage();
133a61156e3SHajimu UMEMOTO 
134a61156e3SHajimu UMEMOTO 	ifindex = (u_short)if_nametoindex(argv[0]);
135a61156e3SHajimu UMEMOTO 	if (ifindex == 0)
136a61156e3SHajimu UMEMOTO 		usage();
13733841545SHajimu UMEMOTO 	if (argc == 2 && inet_pton(AF_INET6, argv[1], &maddr) != 1)
138a61156e3SHajimu UMEMOTO 		usage();
13971cf0564SStephen Hurd 	if (type != MLD_LISTENER_QUERY && qaddr != &maddr) {
140*1e95a9a4SElyes Haouas 		printf("Can not specify -g with -d or -r\n");
14171cf0564SStephen Hurd 		return 1;
14271cf0564SStephen Hurd 	}
143a61156e3SHajimu UMEMOTO 
144a61156e3SHajimu UMEMOTO 	if ((s = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0)
145a61156e3SHajimu UMEMOTO 		err(1, "socket");
146a61156e3SHajimu UMEMOTO 
147a61156e3SHajimu UMEMOTO 	if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hlim,
148a61156e3SHajimu UMEMOTO 		       sizeof(hlim)) == -1)
149a61156e3SHajimu UMEMOTO 		err(1, "setsockopt(IPV6_MULTICAST_HOPS)");
150a61156e3SHajimu UMEMOTO 
15171cf0564SStephen Hurd 	if (IN6_IS_ADDR_UNSPECIFIED(&maddr)) {
15271cf0564SStephen Hurd 		if (inet_pton(AF_INET6, "ff02::1", &maddr) != 1)
15371cf0564SStephen Hurd 			errx(1, "inet_pton failed");
15471cf0564SStephen Hurd 	}
15571cf0564SStephen Hurd 
15671cf0564SStephen Hurd 	mreq.ipv6mr_multiaddr = maddr;
157a61156e3SHajimu UMEMOTO 	mreq.ipv6mr_interface = ifindex;
158a61156e3SHajimu UMEMOTO 	if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
159a61156e3SHajimu UMEMOTO 		       sizeof(mreq)) == -1)
160a61156e3SHajimu UMEMOTO 		err(1, "setsockopt(IPV6_JOIN_GROUP)");
161a61156e3SHajimu UMEMOTO 
162a61156e3SHajimu UMEMOTO 	ICMP6_FILTER_SETBLOCKALL(&filt);
163a61156e3SHajimu UMEMOTO 	ICMP6_FILTER_SETPASS(ICMP6_MEMBERSHIP_QUERY, &filt);
164a61156e3SHajimu UMEMOTO 	ICMP6_FILTER_SETPASS(ICMP6_MEMBERSHIP_REPORT, &filt);
165a61156e3SHajimu UMEMOTO 	ICMP6_FILTER_SETPASS(ICMP6_MEMBERSHIP_REDUCTION, &filt);
166a61156e3SHajimu UMEMOTO 	if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
167a61156e3SHajimu UMEMOTO 			sizeof(filt)) < 0)
168a61156e3SHajimu UMEMOTO 		err(1, "setsockopt(ICMP6_FILTER)");
169a61156e3SHajimu UMEMOTO 
17071cf0564SStephen Hurd 	make_msg(ifindex, &maddr, type, qaddr);
171a61156e3SHajimu UMEMOTO 
172a61156e3SHajimu UMEMOTO 	if (sendmsg(s, &m, 0) < 0)
173a61156e3SHajimu UMEMOTO 		err(1, "sendmsg");
174a61156e3SHajimu UMEMOTO 
175a61156e3SHajimu UMEMOTO 	itimer.it_value.tv_sec =  QUERY_RESPONSE_INTERVAL / 1000;
176a61156e3SHajimu UMEMOTO 	itimer.it_interval.tv_sec = 0;
177a61156e3SHajimu UMEMOTO 	itimer.it_interval.tv_usec = 0;
178a61156e3SHajimu UMEMOTO 	itimer.it_value.tv_usec = 0;
179a61156e3SHajimu UMEMOTO 
180a61156e3SHajimu UMEMOTO 	(void)signal(SIGALRM, quit);
181a61156e3SHajimu UMEMOTO 	(void)setitimer(ITIMER_REAL, &itimer, NULL);
182a61156e3SHajimu UMEMOTO 
183a61156e3SHajimu UMEMOTO 	FD_ZERO(&fdset);
184f95d4633SHajimu UMEMOTO 	if (s >= FD_SETSIZE)
185f95d4633SHajimu UMEMOTO 		errx(1, "descriptor too big");
186a61156e3SHajimu UMEMOTO 	for (;;) {
187a61156e3SHajimu UMEMOTO 		FD_SET(s, &fdset);
188a61156e3SHajimu UMEMOTO 		if ((i = select(s + 1, &fdset, NULL, NULL, NULL)) < 0)
189a61156e3SHajimu UMEMOTO 			perror("select");
190a61156e3SHajimu UMEMOTO 		if (i == 0)
191a61156e3SHajimu UMEMOTO 			continue;
192a61156e3SHajimu UMEMOTO 		else
193a61156e3SHajimu UMEMOTO 			dump(s);
194a61156e3SHajimu UMEMOTO 	}
195a61156e3SHajimu UMEMOTO }
196a61156e3SHajimu UMEMOTO 
197a61156e3SHajimu UMEMOTO void
make_msg(int index,struct in6_addr * addr,u_int type,struct in6_addr * qaddr)19871cf0564SStephen Hurd make_msg(int index, struct in6_addr *addr, u_int type, struct in6_addr *qaddr)
199a61156e3SHajimu UMEMOTO {
200a61156e3SHajimu UMEMOTO 	static struct iovec iov[2];
201a61156e3SHajimu UMEMOTO 	static u_char *cmsgbuf;
202a61156e3SHajimu UMEMOTO 	int cmsglen, hbhlen = 0;
203f95d4633SHajimu UMEMOTO 	void *hbhbuf = NULL, *optp = NULL;
204f95d4633SHajimu UMEMOTO 	int currentlen;
205a61156e3SHajimu UMEMOTO 	struct in6_pktinfo *pi;
206a61156e3SHajimu UMEMOTO 	struct cmsghdr *cmsgp;
207a61156e3SHajimu UMEMOTO 	u_short rtalert_code = htons(IP6OPT_RTALERT_MLD);
208f95d4633SHajimu UMEMOTO 	struct ifaddrs *ifa, *ifap;
209f95d4633SHajimu UMEMOTO 	struct in6_addr src;
210a61156e3SHajimu UMEMOTO 
211a61156e3SHajimu UMEMOTO 	dst.sin6_len = sizeof(dst);
212a61156e3SHajimu UMEMOTO 	dst.sin6_family = AF_INET6;
213a61156e3SHajimu UMEMOTO 	dst.sin6_addr = *addr;
214a61156e3SHajimu UMEMOTO 	m.msg_name = (caddr_t)&dst;
215a61156e3SHajimu UMEMOTO 	m.msg_namelen = dst.sin6_len;
216a61156e3SHajimu UMEMOTO 	iov[0].iov_base = (caddr_t)&mldh;
217a61156e3SHajimu UMEMOTO 	iov[0].iov_len = sizeof(mldh);
218a61156e3SHajimu UMEMOTO 	m.msg_iov = iov;
219a61156e3SHajimu UMEMOTO 	m.msg_iovlen = 1;
220a61156e3SHajimu UMEMOTO 
221a61156e3SHajimu UMEMOTO 	bzero(&mldh, sizeof(mldh));
222f95d4633SHajimu UMEMOTO 	mldh.mld_type = type & 0xff;
223f95d4633SHajimu UMEMOTO 	mldh.mld_maxdelay = htons(QUERY_RESPONSE_INTERVAL);
22471cf0564SStephen Hurd 	mldh.mld_addr = *qaddr;
225a61156e3SHajimu UMEMOTO 
226f95d4633SHajimu UMEMOTO 	/* MLD packet should be advertised from linklocal address */
227f95d4633SHajimu UMEMOTO 	getifaddrs(&ifa);
228f95d4633SHajimu UMEMOTO 	for (ifap = ifa; ifap; ifap = ifap->ifa_next) {
229f95d4633SHajimu UMEMOTO 		if (index != if_nametoindex(ifap->ifa_name))
230f95d4633SHajimu UMEMOTO 			continue;
231f95d4633SHajimu UMEMOTO 
232f95d4633SHajimu UMEMOTO 		if (ifap->ifa_addr->sa_family != AF_INET6)
233f95d4633SHajimu UMEMOTO 			continue;
234f95d4633SHajimu UMEMOTO 		if (!IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)
235f95d4633SHajimu UMEMOTO 					    ifap->ifa_addr)->sin6_addr))
236f95d4633SHajimu UMEMOTO 			continue;
237f95d4633SHajimu UMEMOTO 		break;
238f95d4633SHajimu UMEMOTO 	}
239f95d4633SHajimu UMEMOTO 	if (ifap == NULL)
240fa7c4b1cSKoichiro Iwao 		errx(1, "no linklocal address is available");
241f95d4633SHajimu UMEMOTO 	memcpy(&src, &((struct sockaddr_in6 *)ifap->ifa_addr)->sin6_addr,
242f95d4633SHajimu UMEMOTO 	       sizeof(src));
243f95d4633SHajimu UMEMOTO 	freeifaddrs(ifa);
244f95d4633SHajimu UMEMOTO #ifdef __KAME__
245f95d4633SHajimu UMEMOTO 	/* remove embedded ifindex */
246f95d4633SHajimu UMEMOTO 	src.s6_addr[2] = src.s6_addr[3] = 0;
247f95d4633SHajimu UMEMOTO #endif
248f95d4633SHajimu UMEMOTO 
249f95d4633SHajimu UMEMOTO 	if ((hbhlen = inet6_opt_init(NULL, 0)) == -1)
250f95d4633SHajimu UMEMOTO 		errx(1, "inet6_opt_init(0) failed");
251f95d4633SHajimu UMEMOTO 	if ((hbhlen = inet6_opt_append(NULL, 0, hbhlen, IP6OPT_ROUTER_ALERT, 2,
252f95d4633SHajimu UMEMOTO 				       2, NULL)) == -1)
253f95d4633SHajimu UMEMOTO 		errx(1, "inet6_opt_append(0) failed");
254f95d4633SHajimu UMEMOTO 	if ((hbhlen = inet6_opt_finish(NULL, 0, hbhlen)) == -1)
255f95d4633SHajimu UMEMOTO 		errx(1, "inet6_opt_finish(0) failed");
256f95d4633SHajimu UMEMOTO 	cmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(hbhlen);
257a61156e3SHajimu UMEMOTO 
258a61156e3SHajimu UMEMOTO 	if ((cmsgbuf = malloc(cmsglen)) == NULL)
259a61156e3SHajimu UMEMOTO 		errx(1, "can't allocate enough memory for cmsg");
260a61156e3SHajimu UMEMOTO 	cmsgp = (struct cmsghdr *)cmsgbuf;
261a61156e3SHajimu UMEMOTO 	m.msg_control = (caddr_t)cmsgbuf;
262a61156e3SHajimu UMEMOTO 	m.msg_controllen = cmsglen;
263a61156e3SHajimu UMEMOTO 	/* specify the outgoing interface */
26433841545SHajimu UMEMOTO 	cmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
265a61156e3SHajimu UMEMOTO 	cmsgp->cmsg_level = IPPROTO_IPV6;
266a61156e3SHajimu UMEMOTO 	cmsgp->cmsg_type = IPV6_PKTINFO;
267a61156e3SHajimu UMEMOTO 	pi = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
268a61156e3SHajimu UMEMOTO 	pi->ipi6_ifindex = index;
269f95d4633SHajimu UMEMOTO 	memcpy(&pi->ipi6_addr, &src, sizeof(pi->ipi6_addr));
270*1e95a9a4SElyes Haouas 	/* specify to insert router alert option in a hop-by-hop opt hdr. */
271a61156e3SHajimu UMEMOTO 	cmsgp = CMSG_NXTHDR(&m, cmsgp);
272f95d4633SHajimu UMEMOTO 	cmsgp->cmsg_len = CMSG_LEN(hbhlen);
273f95d4633SHajimu UMEMOTO 	cmsgp->cmsg_level = IPPROTO_IPV6;
274f95d4633SHajimu UMEMOTO 	cmsgp->cmsg_type = IPV6_HOPOPTS;
275f95d4633SHajimu UMEMOTO 	hbhbuf = CMSG_DATA(cmsgp);
276f95d4633SHajimu UMEMOTO 	if ((currentlen = inet6_opt_init(hbhbuf, hbhlen)) == -1)
277f95d4633SHajimu UMEMOTO 		errx(1, "inet6_opt_init(len = %d) failed", hbhlen);
278f95d4633SHajimu UMEMOTO 	if ((currentlen = inet6_opt_append(hbhbuf, hbhlen, currentlen,
279f95d4633SHajimu UMEMOTO 					   IP6OPT_ROUTER_ALERT, 2,
280f95d4633SHajimu UMEMOTO 					   2, &optp)) == -1)
281f95d4633SHajimu UMEMOTO 		errx(1, "inet6_opt_append(currentlen = %d, hbhlen = %d) failed",
282f95d4633SHajimu UMEMOTO 		     currentlen, hbhlen);
283f95d4633SHajimu UMEMOTO 	(void)inet6_opt_set_val(optp, 0, &rtalert_code, sizeof(rtalert_code));
284f95d4633SHajimu UMEMOTO 	if ((currentlen = inet6_opt_finish(hbhbuf, hbhlen, currentlen)) == -1)
285f95d4633SHajimu UMEMOTO 		errx(1, "inet6_opt_finish(buf) failed");
286a61156e3SHajimu UMEMOTO }
287a61156e3SHajimu UMEMOTO 
288a61156e3SHajimu UMEMOTO void
dump(int s)289a61156e3SHajimu UMEMOTO dump(int s)
290a61156e3SHajimu UMEMOTO {
291a61156e3SHajimu UMEMOTO 	int i;
292f95d4633SHajimu UMEMOTO 	struct mld_hdr *mld;
293a61156e3SHajimu UMEMOTO 	u_char buf[1024];
294a61156e3SHajimu UMEMOTO 	struct sockaddr_in6 from;
295a61156e3SHajimu UMEMOTO 	int from_len = sizeof(from);
296a61156e3SHajimu UMEMOTO 	char ntop_buf[256];
297a61156e3SHajimu UMEMOTO 
298a61156e3SHajimu UMEMOTO 	if ((i = recvfrom(s, buf, sizeof(buf), 0,
299a61156e3SHajimu UMEMOTO 			  (struct sockaddr *)&from,
300a61156e3SHajimu UMEMOTO 			  &from_len)) < 0)
301a61156e3SHajimu UMEMOTO 		return;
302a61156e3SHajimu UMEMOTO 
303f95d4633SHajimu UMEMOTO 	if (i < sizeof(struct mld_hdr)) {
304a61156e3SHajimu UMEMOTO 		printf("too short!\n");
305a61156e3SHajimu UMEMOTO 		return;
306a61156e3SHajimu UMEMOTO 	}
307a61156e3SHajimu UMEMOTO 
308f95d4633SHajimu UMEMOTO 	mld = (struct mld_hdr *)buf;
309a61156e3SHajimu UMEMOTO 
310a61156e3SHajimu UMEMOTO 	printf("from %s, ", inet_ntop(AF_INET6, &from.sin6_addr,
311a61156e3SHajimu UMEMOTO 				      ntop_buf, sizeof(ntop_buf)));
312a61156e3SHajimu UMEMOTO 
313f95d4633SHajimu UMEMOTO 	switch (mld->mld_type) {
314a61156e3SHajimu UMEMOTO 	case ICMP6_MEMBERSHIP_QUERY:
315a61156e3SHajimu UMEMOTO 		printf("type=Multicast Listener Query, ");
316a61156e3SHajimu UMEMOTO 		break;
317a61156e3SHajimu UMEMOTO 	case ICMP6_MEMBERSHIP_REPORT:
318a61156e3SHajimu UMEMOTO 		printf("type=Multicast Listener Report, ");
319a61156e3SHajimu UMEMOTO 		break;
320a61156e3SHajimu UMEMOTO 	case ICMP6_MEMBERSHIP_REDUCTION:
321a61156e3SHajimu UMEMOTO 		printf("type=Multicast Listener Done, ");
322a61156e3SHajimu UMEMOTO 		break;
323a61156e3SHajimu UMEMOTO 	}
324f95d4633SHajimu UMEMOTO 	printf("addr=%s\n", inet_ntop(AF_INET6, &mld->mld_addr,
325a61156e3SHajimu UMEMOTO 				    ntop_buf, sizeof(ntop_buf)));
326a61156e3SHajimu UMEMOTO 
327a61156e3SHajimu UMEMOTO 	fflush(stdout);
328a61156e3SHajimu UMEMOTO }
329a61156e3SHajimu UMEMOTO 
330a61156e3SHajimu UMEMOTO void
quit(int signum __unused)3318e724c68SPhilippe Charnier quit(int signum __unused)
332f95d4633SHajimu UMEMOTO {
33371cf0564SStephen Hurd 	mreq.ipv6mr_multiaddr = maddr;
334a61156e3SHajimu UMEMOTO 	mreq.ipv6mr_interface = ifindex;
335a61156e3SHajimu UMEMOTO 	if (setsockopt(s, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq,
336a61156e3SHajimu UMEMOTO 		       sizeof(mreq)) == -1)
337a61156e3SHajimu UMEMOTO 		err(1, "setsockopt(IPV6_LEAVE_GROUP)");
338a61156e3SHajimu UMEMOTO 
339a61156e3SHajimu UMEMOTO 	exit(0);
340a61156e3SHajimu UMEMOTO }
341a61156e3SHajimu UMEMOTO 
342a61156e3SHajimu UMEMOTO void
usage(void)3438e724c68SPhilippe Charnier usage(void)
344a61156e3SHajimu UMEMOTO {
34571cf0564SStephen Hurd 	(void)fprintf(stderr, "usage: mld6query [-dgr] ifname [addr]\n");
346a61156e3SHajimu UMEMOTO 	exit(1);
347a61156e3SHajimu UMEMOTO }
348