diff --git a/usr.sbin/mld6query/mld6.c b/usr.sbin/mld6query/mld6.c index dcdd15a9b0d0..0bf964ac4f82 100644 --- a/usr.sbin/mld6query/mld6.c +++ b/usr.sbin/mld6query/mld6.c @@ -85,7 +85,7 @@ int s; #define QUERY_RESPONSE_INTERVAL 10000 -void make_msg(int index, struct in6_addr *addr, u_int type); +void make_msg(int index, struct in6_addr *addr, u_int type, struct in6_addr *qaddr); void usage(void); void dump(int); void quit(int); @@ -100,14 +100,26 @@ main(int argc, char *argv[]) struct itimerval itimer; u_int type; int ch; + struct in6_addr *qaddr = &maddr; type = MLD_LISTENER_QUERY; - while ((ch = getopt(argc, argv, "dr")) != -1) { + while ((ch = getopt(argc, argv, "dgr")) != -1) { switch (ch) { case 'd': + if (type != MLD_LISTENER_QUERY) { + printf("Can not specifiy -d with -r\n"); + return 1; + } type = MLD_LISTENER_DONE; break; + case 'g': + qaddr = &any; + break; case 'r': + if (type != MLD_LISTENER_QUERY) { + printf("Can not specifiy -r with -d\n"); + return 1; + } type = MLD_LISTENER_REPORT; break; default: @@ -127,6 +139,10 @@ main(int argc, char *argv[]) usage(); if (argc == 2 && inet_pton(AF_INET6, argv[1], &maddr) != 1) usage(); + if (type != MLD_LISTENER_QUERY && qaddr != &maddr) { + printf("Can not specifiy -g with -d or -r\n"); + return 1; + } if ((s = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) err(1, "socket"); @@ -135,7 +151,12 @@ main(int argc, char *argv[]) sizeof(hlim)) == -1) err(1, "setsockopt(IPV6_MULTICAST_HOPS)"); - mreq.ipv6mr_multiaddr = any; + if (IN6_IS_ADDR_UNSPECIFIED(&maddr)) { + if (inet_pton(AF_INET6, "ff02::1", &maddr) != 1) + errx(1, "inet_pton failed"); + } + + mreq.ipv6mr_multiaddr = maddr; mreq.ipv6mr_interface = ifindex; if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq)) == -1) @@ -149,7 +170,7 @@ main(int argc, char *argv[]) sizeof(filt)) < 0) err(1, "setsockopt(ICMP6_FILTER)"); - make_msg(ifindex, &maddr, type); + make_msg(ifindex, &maddr, type, qaddr); if (sendmsg(s, &m, 0) < 0) err(1, "sendmsg"); @@ -177,7 +198,7 @@ main(int argc, char *argv[]) } void -make_msg(int index, struct in6_addr *addr, u_int type) +make_msg(int index, struct in6_addr *addr, u_int type, struct in6_addr *qaddr) { static struct iovec iov[2]; static u_char *cmsgbuf; @@ -196,12 +217,7 @@ make_msg(int index, struct in6_addr *addr, u_int type) dst.sin6_len = sizeof(dst); dst.sin6_family = AF_INET6; - if (IN6_IS_ADDR_UNSPECIFIED(addr)) { - if (inet_pton(AF_INET6, "ff02::1", &dst.sin6_addr) != 1) - errx(1, "inet_pton failed"); - } - else - dst.sin6_addr = *addr; + dst.sin6_addr = *addr; m.msg_name = (caddr_t)&dst; m.msg_namelen = dst.sin6_len; iov[0].iov_base = (caddr_t)&mldh; @@ -212,7 +228,7 @@ make_msg(int index, struct in6_addr *addr, u_int type) bzero(&mldh, sizeof(mldh)); mldh.mld_type = type & 0xff; mldh.mld_maxdelay = htons(QUERY_RESPONSE_INTERVAL); - mldh.mld_addr = *addr; + mldh.mld_addr = *qaddr; /* MLD packet should be advertised from linklocal address */ getifaddrs(&ifa); @@ -337,7 +353,7 @@ dump(int s) void quit(int signum __unused) { - mreq.ipv6mr_multiaddr = any; + mreq.ipv6mr_multiaddr = maddr; mreq.ipv6mr_interface = ifindex; if (setsockopt(s, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq)) == -1) @@ -349,6 +365,6 @@ quit(int signum __unused) void usage(void) { - (void)fprintf(stderr, "usage: mld6query ifname [addr]\n"); + (void)fprintf(stderr, "usage: mld6query [-dgr] ifname [addr]\n"); exit(1); } diff --git a/usr.sbin/mld6query/mld6query.8 b/usr.sbin/mld6query/mld6query.8 index 1516c2e6d786..1f75e0e60518 100644 --- a/usr.sbin/mld6query/mld6query.8 +++ b/usr.sbin/mld6query/mld6query.8 @@ -39,7 +39,7 @@ .\" .Sh SYNOPSIS .Nm -.Op Fl dr +.Op Fl dgr .Ar intface .Op Ar maddr .\" @@ -66,6 +66,10 @@ This program is provided only for debugging. It is not necessary for normal use. .Pp With +.Fl g , +.Nm +will transmit a General Query instead of the default Multicast-Address-Specific Query. +With .Fl d , .Nm will transmit MLD done packet instead of MLD query packet.