Fix mld6query(8) and add a new -g option
The mld6query command relies on KAME behaviour which allows the ipv6mr_multiaddr member of the request object in a IPV6_JOIN_GROUP setsockopt() call to be INADDR6_ANY. The FreeBSD stack doesn't allow this, so mld6query has been non-functional. Also, add a -g option which sends a General Query (query INADDR6_ANY) Reviewed by: sbruno, mmacy Sponsored by: Limelight Networks Differential Revision: https://reviews.freebsd.org/D15384
This commit is contained in:
parent
8dcbd0eae6
commit
71cf0564f8
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user