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