summaryrefslogtreecommitdiffstats
path: root/usr.sbin/mld6query
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/mld6query')
-rw-r--r--usr.sbin/mld6query/Makefile2
-rw-r--r--usr.sbin/mld6query/mld6.c113
2 files changed, 98 insertions, 17 deletions
diff --git a/usr.sbin/mld6query/Makefile b/usr.sbin/mld6query/Makefile
index 66f2a5e..7100520 100644
--- a/usr.sbin/mld6query/Makefile
+++ b/usr.sbin/mld6query/Makefile
@@ -18,6 +18,6 @@ PROG= mld6query
MAN= mld6query.8
SRCS= mld6.c
-CFLAGS+= -DINET6 -DIPSEC
+CFLAGS+= -DINET6 -DIPSEC -DUSE_RFC2292BIS
.include <bsd.prog.mk>
diff --git a/usr.sbin/mld6query/mld6.c b/usr.sbin/mld6query/mld6.c
index 9b0b30a..1f73203 100644
--- a/usr.sbin/mld6query/mld6.c
+++ b/usr.sbin/mld6query/mld6.c
@@ -1,4 +1,4 @@
-/* $KAME: mld6.c,v 1.11 2001/05/13 15:45:07 suz Exp $ */
+/* $KAME: mld6.c,v 1.15 2003/04/02 11:29:54 suz Exp $ */
/* $FreeBSD$ */
/*
@@ -34,6 +34,7 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
+#include <ifaddrs.h>
#include <unistd.h>
#include <signal.h>
@@ -51,9 +52,28 @@
#include <string.h>
#include <err.h>
+/* portability with older KAME headers */
+#ifndef MLD_LISTENER_QUERY
+#define MLD_LISTENER_QUERY MLD6_LISTENER_QUERY
+#define MLD_LISTENER_REPORT MLD6_LISTENER_REPORT
+#define MLD_LISTENER_DONE MLD6_LISTENER_DONE
+#define MLD_MTRACE_RESP MLD6_MTRACE_RESP
+#define MLD_MTRACE MLD6_MTRACE
+#define mld_hdr mld6_hdr
+#define mld_type mld6_type
+#define mld_code mld6_code
+#define mld_cksum mld6_cksum
+#define mld_maxdelay mld6_maxdelay
+#define mld_reserved mld6_reserved
+#define mld_addr mld6_addr
+#endif
+#ifndef IP6OPT_ROUTER_ALERT
+#define IP6OPT_ROUTER_ALERT IP6OPT_RTALERT
+#endif
+
struct msghdr m;
struct sockaddr_in6 dst;
-struct mld6_hdr mldh;
+struct mld_hdr mldh;
struct in6_addr maddr = IN6ADDR_ANY_INIT, any = IN6ADDR_ANY_INIT;
struct ipv6_mreq mreq;
u_short ifindex;
@@ -77,14 +97,14 @@ main(int argc, char *argv[])
u_int type;
int ch;
- type = MLD6_LISTENER_QUERY;
+ type = MLD_LISTENER_QUERY;
while ((ch = getopt(argc, argv, "dr")) != -1) {
switch (ch) {
case 'd':
- type = MLD6_LISTENER_DONE;
+ type = MLD_LISTENER_DONE;
break;
case 'r':
- type = MLD6_LISTENER_REPORT;
+ type = MLD_LISTENER_REPORT;
break;
default:
usage();
@@ -139,6 +159,8 @@ main(int argc, char *argv[])
(void)setitimer(ITIMER_REAL, &itimer, NULL);
FD_ZERO(&fdset);
+ if (s >= FD_SETSIZE)
+ errx(1, "descriptor too big");
for (;;) {
FD_SET(s, &fdset);
if ((i = select(s + 1, &fdset, NULL, NULL, NULL)) < 0)
@@ -156,10 +178,17 @@ make_msg(int index, struct in6_addr *addr, u_int type)
static struct iovec iov[2];
static u_char *cmsgbuf;
int cmsglen, hbhlen = 0;
+#ifdef USE_RFC2292BIS
+ void *hbhbuf = NULL, *optp = NULL;
+ int currentlen;
+#else
u_int8_t raopt[IP6OPT_RTALERT_LEN];
+#endif
struct in6_pktinfo *pi;
struct cmsghdr *cmsgp;
u_short rtalert_code = htons(IP6OPT_RTALERT_MLD);
+ struct ifaddrs *ifa, *ifap;
+ struct in6_addr src;
dst.sin6_len = sizeof(dst);
dst.sin6_family = AF_INET6;
@@ -177,13 +206,47 @@ make_msg(int index, struct in6_addr *addr, u_int type)
m.msg_iovlen = 1;
bzero(&mldh, sizeof(mldh));
- mldh.mld6_type = type & 0xff;
- mldh.mld6_maxdelay = htons(QUERY_RESPONSE_INTERVAL);
- mldh.mld6_addr = *addr;
+ mldh.mld_type = type & 0xff;
+ mldh.mld_maxdelay = htons(QUERY_RESPONSE_INTERVAL);
+ mldh.mld_addr = *addr;
+
+ /* MLD packet should be advertised from linklocal address */
+ getifaddrs(&ifa);
+ for (ifap = ifa; ifap; ifap = ifap->ifa_next) {
+ if (index != if_nametoindex(ifap->ifa_name))
+ continue;
+ if (ifap->ifa_addr->sa_family != AF_INET6)
+ continue;
+ if (!IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)
+ ifap->ifa_addr)->sin6_addr))
+ continue;
+ break;
+ }
+ if (ifap == NULL)
+ errx(1, "no linkocal address is available");
+ memcpy(&src, &((struct sockaddr_in6 *)ifap->ifa_addr)->sin6_addr,
+ sizeof(src));
+ freeifaddrs(ifa);
+#ifdef __KAME__
+ /* remove embedded ifindex */
+ src.s6_addr[2] = src.s6_addr[3] = 0;
+#endif
+
+#ifdef USE_RFC2292BIS
+ if ((hbhlen = inet6_opt_init(NULL, 0)) == -1)
+ errx(1, "inet6_opt_init(0) failed");
+ if ((hbhlen = inet6_opt_append(NULL, 0, hbhlen, IP6OPT_ROUTER_ALERT, 2,
+ 2, NULL)) == -1)
+ errx(1, "inet6_opt_append(0) failed");
+ if ((hbhlen = inet6_opt_finish(NULL, 0, hbhlen)) == -1)
+ errx(1, "inet6_opt_finish(0) failed");
+ cmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(hbhlen);
+#else
hbhlen = sizeof(raopt);
cmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
inet6_option_space(hbhlen);
+#endif
if ((cmsgbuf = malloc(cmsglen)) == NULL)
errx(1, "can't allocate enough memory for cmsg");
@@ -196,23 +259,40 @@ make_msg(int index, struct in6_addr *addr, u_int type)
cmsgp->cmsg_type = IPV6_PKTINFO;
pi = (struct in6_pktinfo *)CMSG_DATA(cmsgp);
pi->ipi6_ifindex = index;
- memset(&pi->ipi6_addr, 0, sizeof(pi->ipi6_addr));
+ memcpy(&pi->ipi6_addr, &src, sizeof(pi->ipi6_addr));
/* specifiy to insert router alert option in a hop-by-hop opt hdr. */
cmsgp = CMSG_NXTHDR(&m, cmsgp);
+#ifdef USE_RFC2292BIS
+ cmsgp->cmsg_len = CMSG_LEN(hbhlen);
+ cmsgp->cmsg_level = IPPROTO_IPV6;
+ cmsgp->cmsg_type = IPV6_HOPOPTS;
+ hbhbuf = CMSG_DATA(cmsgp);
+ if ((currentlen = inet6_opt_init(hbhbuf, hbhlen)) == -1)
+ errx(1, "inet6_opt_init(len = %d) failed", hbhlen);
+ if ((currentlen = inet6_opt_append(hbhbuf, hbhlen, currentlen,
+ IP6OPT_ROUTER_ALERT, 2,
+ 2, &optp)) == -1)
+ errx(1, "inet6_opt_append(currentlen = %d, hbhlen = %d) failed",
+ currentlen, hbhlen);
+ (void)inet6_opt_set_val(optp, 0, &rtalert_code, sizeof(rtalert_code));
+ if ((currentlen = inet6_opt_finish(hbhbuf, hbhlen, currentlen)) == -1)
+ errx(1, "inet6_opt_finish(buf) failed");
+#else /* old advanced API */
if (inet6_option_init((void *)cmsgp, &cmsgp, IPV6_HOPOPTS))
errx(1, "inet6_option_init failed\n");
- raopt[0] = IP6OPT_RTALERT;
+ raopt[0] = IP6OPT_ROUTER_ALERT;
raopt[1] = IP6OPT_RTALERT_LEN - 2;
memcpy(&raopt[2], (caddr_t)&rtalert_code, sizeof(u_short));
if (inet6_option_append(cmsgp, raopt, 4, 0))
errx(1, "inet6_option_append failed\n");
+#endif
}
void
dump(int s)
{
int i;
- struct mld6_hdr *mld;
+ struct mld_hdr *mld;
u_char buf[1024];
struct sockaddr_in6 from;
int from_len = sizeof(from);
@@ -223,17 +303,17 @@ dump(int s)
&from_len)) < 0)
return;
- if (i < sizeof(struct mld6_hdr)) {
+ if (i < sizeof(struct mld_hdr)) {
printf("too short!\n");
return;
}
- mld = (struct mld6_hdr *)buf;
+ mld = (struct mld_hdr *)buf;
printf("from %s, ", inet_ntop(AF_INET6, &from.sin6_addr,
ntop_buf, sizeof(ntop_buf)));
- switch (mld->mld6_type) {
+ switch (mld->mld_type) {
case ICMP6_MEMBERSHIP_QUERY:
printf("type=Multicast Listener Query, ");
break;
@@ -244,7 +324,7 @@ dump(int s)
printf("type=Multicast Listener Done, ");
break;
}
- printf("addr=%s\n", inet_ntop(AF_INET6, &mld->mld6_addr,
+ printf("addr=%s\n", inet_ntop(AF_INET6, &mld->mld_addr,
ntop_buf, sizeof(ntop_buf)));
fflush(stdout);
@@ -252,7 +332,8 @@ dump(int s)
/* ARGSUSED */
void
-quit(int signum) {
+quit(int signum)
+{
mreq.ipv6mr_multiaddr = any;
mreq.ipv6mr_interface = ifindex;
if (setsockopt(s, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq,
OpenPOWER on IntegriCloud