diff options
author | hrs <hrs@FreeBSD.org> | 2013-05-04 19:16:26 +0000 |
---|---|---|
committer | hrs <hrs@FreeBSD.org> | 2013-05-04 19:16:26 +0000 |
commit | d9d71436d975a7ec598297c564219c530aa41138 (patch) | |
tree | aa5ae7e9839ddc5bfbdcadec3937869568f4e33f | |
parent | bf7b6b6227253281ec4cfedd2f8c95e19532acb3 (diff) | |
download | FreeBSD-src-d9d71436d975a7ec598297c564219c530aa41138.zip FreeBSD-src-d9d71436d975a7ec598297c564219c530aa41138.tar.gz |
Use FF02:0:0:0:0:2:FF00::/104 prefix for IPv6 Node Information Group
Address. Although KAME implementation used FF02:0:0:0:0:2::/96 based on
older versions of draft-ietf-ipngwg-icmp-name-lookup, it has been changed
in RFC 4620.
The kernel always joins the /104-prefixed address, and additionally does
/96-prefixed one only when net.inet6.icmp6.nodeinfo_oldmcprefix=1.
The default value of the sysctl is 1.
ping6(8) -N flag now uses /104-prefixed one. When this flag is specified
twice, it uses /96-prefixed one instead.
Reviewed by: ume
Based on work by: Thomas Scheffler
PR: conf/174957
MFC after: 2 weeks
-rw-r--r-- | sbin/ping6/ping6.8 | 15 | ||||
-rw-r--r-- | sbin/ping6/ping6.c | 29 | ||||
-rw-r--r-- | sys/netinet/icmp6.h | 3 | ||||
-rw-r--r-- | sys/netinet6/in6.c | 14 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.c | 38 | ||||
-rw-r--r-- | sys/netinet6/in6_ifattach.h | 1 | ||||
-rw-r--r-- | sys/netinet6/in6_proto.c | 6 |
7 files changed, 90 insertions, 16 deletions
diff --git a/sbin/ping6/ping6.8 b/sbin/ping6/ping6.8 index b720aef..0d1e5f0 100644 --- a/sbin/ping6/ping6.8 +++ b/sbin/ping6/ping6.8 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 20, 2010 +.Dd May 5, 2013 .Dt PING6 8 .Os .Sh NAME @@ -215,8 +215,8 @@ unicast and multicast packets. Numeric output only. No attempt will be made to lookup symbolic names from addresses in the reply. .It Fl N -Probe node information multicast group -.Pq Li ff02::2:xxxx:xxxx . +Probe node information multicast group address +.Pq Li ff02::2:ffxx:xxxx . .Ar host must be string hostname of the target (must not be a numeric IPv6 address). @@ -227,6 +227,15 @@ Since node information multicast group is a link-local multicast group, outgoing interface needs to be specified by .Fl I option. +.Pp +When specified twice, the address +.Pq Li ff02::2:xxxx:xxxx +is used instead. +The former is in RFC 4620, the latter is in an old Internet Draft +draft-ietf-ipngwg-icmp-name-lookup. +Note that KAME-derived implementations including +.Fx +use the latter. .It Fl o Exit successfully after receiving one reply packet. .It Fl p Ar pattern diff --git a/sbin/ping6/ping6.c b/sbin/ping6/ping6.c index 8c3e16b..01e29a1 100644 --- a/sbin/ping6/ping6.c +++ b/sbin/ping6/ping6.c @@ -287,7 +287,7 @@ void pr_retip(struct ip6_hdr *, u_char *); void summary(void); void tvsub(struct timeval *, struct timeval *); int setpolicy(int, char *); -char *nigroup(char *); +char *nigroup(char *, int); void usage(void); int @@ -306,6 +306,7 @@ main(int argc, char *argv[]) struct addrinfo hints; int cc, i; int ch, hold, packlen, preload, optval, ret_ga; + int nig_oldmcprefix = -1; u_char *datap; char *e, *target, *ifname = NULL, *gateway = NULL; int ip6optlen = 0; @@ -490,6 +491,7 @@ main(int argc, char *argv[]) break; case 'N': options |= F_NIGROUP; + nig_oldmcprefix++; break; case 'o': options |= F_ONCE; @@ -605,7 +607,7 @@ main(int argc, char *argv[]) } if (options & F_NIGROUP) { - target = nigroup(argv[argc - 1]); + target = nigroup(argv[argc - 1], nig_oldmcprefix); if (target == NULL) { usage(); /*NOTREACHED*/ @@ -2723,7 +2725,7 @@ setpolicy(int so __unused, char *policy) #endif char * -nigroup(char *name) +nigroup(char *name, int nig_oldmcprefix) { char *p; char *q; @@ -2733,6 +2735,7 @@ nigroup(char *name) size_t l; char hbuf[NI_MAXHOST]; struct in6_addr in6; + int valid; p = strchr(name, '.'); if (!p) @@ -2748,7 +2751,7 @@ nigroup(char *name) *q = tolower(*(unsigned char *)q); } - /* generate 8 bytes of pseudo-random value. */ + /* generate 16 bytes of pseudo-random value. */ memset(&ctxt, 0, sizeof(ctxt)); MD5Init(&ctxt); c = l & 0xff; @@ -2756,9 +2759,23 @@ nigroup(char *name) MD5Update(&ctxt, (unsigned char *)name, l); MD5Final(digest, &ctxt); - if (inet_pton(AF_INET6, "ff02::2:0000:0000", &in6) != 1) + if (nig_oldmcprefix) { + /* draft-ietf-ipngwg-icmp-name-lookup */ + valid = inet_pton(AF_INET6, "ff02::2:0000:0000", &in6); + } else { + /* RFC 4620 */ + valid = inet_pton(AF_INET6, "ff02::2:ff00:0000", &in6); + } + if (valid != 1) return NULL; /*XXX*/ - bcopy(digest, &in6.s6_addr[12], 4); + + if (nig_oldmcprefix) { + /* draft-ietf-ipngwg-icmp-name-lookup */ + bcopy(digest, &in6.s6_addr[12], 4); + } else { + /* RFC 4620 */ + bcopy(digest, &in6.s6_addr[13], 3); + } if (inet_ntop(AF_INET6, &in6, hbuf, sizeof(hbuf)) == NULL) return NULL; diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h index a6e6886..5483721 100644 --- a/sys/netinet/icmp6.h +++ b/sys/netinet/icmp6.h @@ -659,7 +659,8 @@ void kmod_icmp6stat_inc(int statnum); #define ICMPV6CTL_MLD_SOMAXSRC 22 #define ICMPV6CTL_MLD_VERSION 23 #define ICMPV6CTL_ND6_MAXQLEN 24 -#define ICMPV6CTL_MAXID 25 +#define ICMPV6CTL_NODEINFO_OLDMCPREFIX 25 +#define ICMPV6CTL_MAXID 26 #define RTF_PROBEMTU RTF_PROTO1 diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c index 934665c..5a90111 100644 --- a/sys/netinet6/in6.c +++ b/sys/netinet6/in6.c @@ -106,6 +106,9 @@ __FBSDID("$FreeBSD$"); #include <netinet6/scope6_var.h> #include <netinet6/in6_pcb.h> +VNET_DECLARE(int, icmp6_nodeinfo_oldmcprefix); +#define V_icmp6_nodeinfo_oldmcprefix VNET(icmp6_nodeinfo_oldmcprefix) + /* * Definitions of some costant IP6 addresses. */ @@ -947,6 +950,17 @@ in6_update_ifa_join_mc(struct ifnet *ifp, struct in6_aliasreq *ifra, else LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); } + if (V_icmp6_nodeinfo_oldmcprefix && + in6_nigroup_oldmcprefix(ifp, NULL, -1, &mltaddr.sin6_addr) == 0) { + imm = in6_joingroup(ifp, &mltaddr.sin6_addr, &error, delay); + if (imm == NULL) + nd6log((LOG_WARNING, "%s: addmulti failed for %s on %s " + "(errno=%d)\n", __func__, ip6_sprintf(ip6buf, + &mltaddr.sin6_addr), if_name(ifp), error)); + /* XXX not very fatal, go on... */ + else + LIST_INSERT_HEAD(&ia->ia6_memberships, imm, i6mm_chain); + } /* * Join interface-local all-nodes address. diff --git a/sys/netinet6/in6_ifattach.c b/sys/netinet6/in6_ifattach.c index 28ec920..85890ab 100644 --- a/sys/netinet6/in6_ifattach.c +++ b/sys/netinet6/in6_ifattach.c @@ -616,13 +616,16 @@ in6_ifattach_loopback(struct ifnet *ifp) /* * compute NI group address, based on the current hostname setting. - * see draft-ietf-ipngwg-icmp-name-lookup-* (04 and later). + * see RFC 4620. * * when ifp == NULL, the caller is responsible for filling scopeid. + * + * If oldmcprefix == 1, FF02:0:0:0:0:2::/96 is used for NI group address + * while it is FF02:0:0:0:0:2:FF00::/104 in RFC 4620. */ -int -in6_nigroup(struct ifnet *ifp, const char *name, int namelen, - struct in6_addr *in6) +static int +in6_nigroup0(struct ifnet *ifp, const char *name, int namelen, + struct in6_addr *in6, int oldmcprefix) { struct prison *pr; const char *p; @@ -667,7 +670,7 @@ in6_nigroup(struct ifnet *ifp, const char *name, int namelen, *q = *q - 'A' + 'a'; } - /* generate 8 bytes of pseudo-random value. */ + /* generate 16 bytes of pseudo-random value. */ bzero(&ctxt, sizeof(ctxt)); MD5Init(&ctxt); MD5Update(&ctxt, &l, sizeof(l)); @@ -677,13 +680,36 @@ in6_nigroup(struct ifnet *ifp, const char *name, int namelen, bzero(in6, sizeof(*in6)); in6->s6_addr16[0] = IPV6_ADDR_INT16_MLL; in6->s6_addr8[11] = 2; - bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3])); + if (oldmcprefix == 0) { + in6->s6_addr8[12] = 0xff; + /* Copy the first 24 bits of 128-bit hash into the address. */ + bcopy(digest, &in6->s6_addr8[13], 3); + } else { + /* Copy the first 32 bits of 128-bit hash into the address. */ + bcopy(digest, &in6->s6_addr32[3], sizeof(in6->s6_addr32[3])); + } if (in6_setscope(in6, ifp, NULL)) return (-1); /* XXX: should not fail */ return 0; } +int +in6_nigroup(struct ifnet *ifp, const char *name, int namelen, + struct in6_addr *in6) +{ + + return (in6_nigroup0(ifp, name, namelen, in6, 0)); +} + +int +in6_nigroup_oldmcprefix(struct ifnet *ifp, const char *name, int namelen, + struct in6_addr *in6) +{ + + return (in6_nigroup0(ifp, name, namelen, in6, 1)); +} + /* * XXX multiple loopback interface needs more care. for instance, * nodelocal address needs to be configured onto only one of them. diff --git a/sys/netinet6/in6_ifattach.h b/sys/netinet6/in6_ifattach.h index 113c427..af62731 100644 --- a/sys/netinet6/in6_ifattach.h +++ b/sys/netinet6/in6_ifattach.h @@ -40,6 +40,7 @@ int in6_get_tmpifid(struct ifnet *, u_int8_t *, const u_int8_t *, int); void in6_tmpaddrtimer(void *); int in6_get_hw_ifid(struct ifnet *, struct in6_addr *); int in6_nigroup(struct ifnet *, const char *, int, struct in6_addr *); +int in6_nigroup_oldmcprefix(struct ifnet *, const char *, int, struct in6_addr *); #endif /* _KERNEL */ #endif /* _NETINET6_IN6_IFATTACH_H_ */ diff --git a/sys/netinet6/in6_proto.c b/sys/netinet6/in6_proto.c index ede1f9d..a1efac4 100644 --- a/sys/netinet6/in6_proto.c +++ b/sys/netinet6/in6_proto.c @@ -438,6 +438,7 @@ VNET_DEFINE(int, icmp6errppslim) = 100; /* 100pps */ /* control how to respond to NI queries */ VNET_DEFINE(int, icmp6_nodeinfo) = (ICMP6_NODEINFO_FQDNOK|ICMP6_NODEINFO_NODEADDROK); +VNET_DEFINE(int, icmp6_nodeinfo_oldmcprefix) = 1; /* * sysctl related items. @@ -602,6 +603,11 @@ SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_USELOOPBACK, nd6_useloopback, CTLFLAG_RW, &VNET_NAME(nd6_useloopback), 0, ""); SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_NODEINFO, nodeinfo, CTLFLAG_RW, &VNET_NAME(icmp6_nodeinfo), 0, ""); +SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_NODEINFO_OLDMCPREFIX, + nodeinfo_oldmcprefix, CTLFLAG_RW, + &VNET_NAME(icmp6_nodeinfo_oldmcprefix), 0, + "Join old IPv6 NI group address in draft-ietf-ipngwg-icmp-name-lookup" + " for compatibility with KAME implememtation."); SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ERRPPSLIMIT, errppslimit, CTLFLAG_RW, &VNET_NAME(icmp6errppslim), 0, ""); SYSCTL_VNET_INT(_net_inet6_icmp6, ICMPV6CTL_ND6_MAXNUDHINT, nd6_maxnudhint, |