Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F162282223
D58096.id181536.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D58096.id181536.diff
View Options
diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c
--- a/sys/netinet6/icmp6.c
+++ b/sys/netinet6/icmp6.c
@@ -2169,7 +2169,8 @@
union nd_opts ndopts;
char ip6buf[INET6_ADDRSTRLEN];
char *lladdr;
- int icmp6len, is_onlink, is_router, lladdrlen;
+ int icmp6len, is_onlink, is_router;
+ u_int lladdr_pad, lladdrlen;
M_ASSERTPKTHDR(m);
KASSERT(m->m_pkthdr.rcvif != NULL, ("%s: no rcvif", __func__));
@@ -2296,16 +2297,18 @@
lladdr = NULL;
lladdrlen = 0;
+ lladdr_pad = nd6_lladdr_opt_pad(ifp);
if (ndopts.nd_opts_tgt_lladdr) {
- lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
+ lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1) + lladdr_pad;
lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
}
- if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
+ if (lladdr && ((ifp->if_addrlen + lladdr_pad + 2 + 7) & ~7) !=
+ lladdrlen) {
nd6log((LOG_INFO, "%s: lladdrlen mismatch for %s "
- "(if %d, icmp6 packet %d): %s\n",
+ "(if %d, icmp6 packet %u): %s\n",
__func__, ip6_sprintf(ip6buf, &redtgt6),
- ifp->if_addrlen, lladdrlen - 2,
+ ifp->if_addrlen, lladdrlen - 2 - lladdr_pad,
icmp6_redirect_diag(&src6, &reddst6, &redtgt6)));
goto bad;
}
@@ -2492,6 +2495,7 @@
{
/* target lladdr option */
int len;
+ u_int pad;
struct nd_opt_hdr *nd_opt;
char *lladdr;
@@ -2499,7 +2503,8 @@
if (ln == NULL)
goto nolladdropt;
- len = sizeof(*nd_opt) + ifp->if_addrlen;
+ pad = nd6_lladdr_opt_pad(ifp);
+ len = sizeof(*nd_opt) + pad + ifp->if_addrlen;
len = (len + 7) & ~7; /* round by 8 */
/* safety check */
if (len + (p - (u_char *)ip6) > maxlen)
@@ -2507,9 +2512,10 @@
if (ln->la_flags & LLE_VALID) {
nd_opt = (struct nd_opt_hdr *)p;
+ bzero(nd_opt, len);
nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
nd_opt->nd_opt_len = len >> 3;
- lladdr = (char *)(nd_opt + 1);
+ lladdr = (char *)(nd_opt + 1) + pad;
bcopy(ln->ll_addr, lladdr, ifp->if_addrlen);
p += len;
}
diff --git a/sys/netinet6/nd6.h b/sys/netinet6/nd6.h
--- a/sys/netinet6/nd6.h
+++ b/sys/netinet6/nd6.h
@@ -380,6 +380,7 @@
void nd6_ns_output(struct ifnet *, const struct in6_addr *,
const struct in6_addr *, const struct in6_addr *, uint8_t *);
caddr_t nd6_ifptomac(struct ifnet *);
+u_int nd6_lladdr_opt_pad(struct ifnet *);
void nd6_dad_init(void);
void nd6_dad_start(struct ifaddr *, int);
void nd6_dad_stop(struct ifaddr *);
diff --git a/sys/netinet6/nd6_nbr.c b/sys/netinet6/nd6_nbr.c
--- a/sys/netinet6/nd6_nbr.c
+++ b/sys/netinet6/nd6_nbr.c
@@ -151,7 +151,8 @@
union nd_opts ndopts;
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
char *lladdr;
- int lladdrlen, rflag, tentative, tlladdr;
+ int rflag, tentative, tlladdr;
+ u_int lladdr_pad, lladdrlen;
uint32_t dflags;
ifa = NULL;
@@ -240,8 +241,9 @@
lladdr = NULL;
lladdrlen = 0;
+ lladdr_pad = nd6_lladdr_opt_pad(ifp);
if (ndopts.nd_opts_src_lladdr) {
- lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
+ lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1) + lladdr_pad;
lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
}
@@ -300,11 +302,12 @@
if (((struct in6_ifaddr *)ifa)->ia6_flags & IN6_IFF_DUPLICATED)
goto freeit;
- if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
+ if (lladdr && ((ifp->if_addrlen + lladdr_pad + 2 + 7) & ~7) !=
+ lladdrlen) {
nd6log((LOG_INFO, "nd6_ns_input: lladdrlen mismatch for %s "
- "(if %d, NS packet %d)\n",
+ "(if %d, NS packet %u)\n",
ip6_sprintf(ip6bufs, &taddr6),
- ifp->if_addrlen, lladdrlen - 2));
+ ifp->if_addrlen, lladdrlen - 2 - lladdr_pad));
goto bad;
}
@@ -449,7 +452,8 @@
/* estimate the size of message */
maxlen = sizeof(*ip6) + sizeof(*nd_ns);
- maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
+ maxlen += (sizeof(struct nd_opt_hdr) + nd6_lladdr_opt_pad(ifp) +
+ ifp->if_addrlen + 7) & ~7;
KASSERT(max_linkhdr + maxlen <= MCLBYTES, (
"%s: max_linkhdr + maxlen > MCLBYTES (%d + %d > %d)",
__func__, max_linkhdr, maxlen, MCLBYTES));
@@ -582,6 +586,7 @@
struct nd_opt_hdr *nd_opt;
char *mac;
int optlen;
+ u_int pad;
mac = NULL;
if (ifp->if_carp)
@@ -591,7 +596,9 @@
if (mac != NULL) {
nd_opt = (struct nd_opt_hdr *)(nd_ns + 1);
- optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
+ pad = nd6_lladdr_opt_pad(ifp);
+ optlen = sizeof(struct nd_opt_hdr) + pad +
+ ifp->if_addrlen;
/* 8 byte alignments... */
optlen = (optlen + 7) & ~7;
m->m_pkthdr.len += optlen;
@@ -600,7 +607,8 @@
bzero(nd_opt, optlen);
nd_opt->nd_opt_type = ND_OPT_SOURCE_LINKADDR;
nd_opt->nd_opt_len = optlen >> 3;
- bcopy(mac, nd_opt + 1, ifp->if_addrlen);
+ bcopy(mac, (char *)(nd_opt + 1) + pad,
+ ifp->if_addrlen);
}
}
/*
@@ -680,7 +688,8 @@
char *lladdr;
size_t linkhdrsize;
int flags, is_override, is_router, is_solicited;
- int lladdr_off, lladdrlen, checklink;
+ int lladdr_off, checklink;
+ u_int lladdr_pad, lladdrlen;
bool flush_holdchain = false;
NET_EPOCH_ASSERT();
@@ -749,8 +758,9 @@
lladdr = NULL;
lladdrlen = 0;
+ lladdr_pad = nd6_lladdr_opt_pad(ifp);
if (ndopts.nd_opts_tgt_lladdr) {
- lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1);
+ lladdr = (char *)(ndopts.nd_opts_tgt_lladdr + 1) + lladdr_pad;
lladdrlen = ndopts.nd_opts_tgt_lladdr->nd_opt_len << 3;
}
@@ -793,10 +803,11 @@
goto freeit;
}
- if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
+ if (lladdr && ((ifp->if_addrlen + lladdr_pad + 2 + 7) & ~7) !=
+ lladdrlen) {
nd6log((LOG_INFO, "nd6_na_input: lladdrlen mismatch for %s "
- "(if %d, NA packet %d)\n", ip6_sprintf(ip6bufs, &taddr6),
- ifp->if_addrlen, lladdrlen - 2));
+ "(if %d, NA packet %u)\n", ip6_sprintf(ip6bufs, &taddr6),
+ ifp->if_addrlen, lladdrlen - 2 - lladdr_pad));
goto bad;
}
@@ -1003,7 +1014,8 @@
/* estimate the size of message */
maxlen = sizeof(*ip6) + sizeof(*nd_na);
- maxlen += (sizeof(struct nd_opt_hdr) + ifp->if_addrlen + 7) & ~7;
+ maxlen += (sizeof(struct nd_opt_hdr) + nd6_lladdr_opt_pad(ifp) +
+ ifp->if_addrlen + 7) & ~7;
KASSERT(max_linkhdr + maxlen <= MCLBYTES, (
"%s: max_linkhdr + maxlen > MCLBYTES (%d + %d > %d)",
__func__, max_linkhdr, maxlen, MCLBYTES));
@@ -1087,7 +1099,9 @@
}
}
if ((tlladdr & ND6_NA_OPT_LLA) && mac != NULL) {
- int optlen = sizeof(struct nd_opt_hdr) + ifp->if_addrlen;
+ u_int pad = nd6_lladdr_opt_pad(ifp);
+ int optlen = sizeof(struct nd_opt_hdr) + pad +
+ ifp->if_addrlen;
struct nd_opt_hdr *nd_opt = (struct nd_opt_hdr *)(nd_na + 1);
/* roundup to 8 bytes alignment! */
@@ -1099,7 +1113,7 @@
bzero((caddr_t)nd_opt, optlen);
nd_opt->nd_opt_type = ND_OPT_TARGET_LINKADDR;
nd_opt->nd_opt_len = optlen >> 3;
- bcopy(mac, (caddr_t)(nd_opt + 1), ifp->if_addrlen);
+ bcopy(mac, (char *)(nd_opt + 1) + pad, ifp->if_addrlen);
} else
flags &= ~ND_NA_FLAG_OVERRIDE;
@@ -1156,6 +1170,25 @@
}
}
+/*
+ * Number of reserved octets between the header of an ND link-layer
+ * address option and the link-layer address itself. On IPoIB links
+ * two zero octets are prepended to the 20-octet link-layer address
+ * to fill the 24-octet option (RFC 4391, section 9.3); on all other
+ * link types the address immediately follows the option header.
+ */
+u_int
+nd6_lladdr_opt_pad(struct ifnet *ifp)
+{
+ switch (ifp->if_type) {
+ case IFT_INFINIBAND:
+ case IFT_INFINIBANDLAG:
+ return (2);
+ default:
+ return (0);
+ }
+}
+
struct dadq {
TAILQ_ENTRY(dadq) dad_list;
struct ifaddr *dad_ifa;
diff --git a/sys/netinet6/nd6_rtr.c b/sys/netinet6/nd6_rtr.c
--- a/sys/netinet6/nd6_rtr.c
+++ b/sys/netinet6/nd6_rtr.c
@@ -171,7 +171,7 @@
union nd_opts ndopts;
char ip6bufs[INET6_ADDRSTRLEN], ip6bufd[INET6_ADDRSTRLEN];
char *lladdr;
- int lladdrlen;
+ u_int lladdr_pad, lladdrlen;
ifp = m->m_pkthdr.rcvif;
@@ -226,16 +226,18 @@
lladdr = NULL;
lladdrlen = 0;
+ lladdr_pad = nd6_lladdr_opt_pad(ifp);
if (ndopts.nd_opts_src_lladdr) {
- lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1);
+ lladdr = (char *)(ndopts.nd_opts_src_lladdr + 1) + lladdr_pad;
lladdrlen = ndopts.nd_opts_src_lladdr->nd_opt_len << 3;
}
- if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
+ if (lladdr && ((ifp->if_addrlen + lladdr_pad + 2 + 7) & ~7) !=
+ lladdrlen) {
nd6log((LOG_INFO,
- "%s: lladdrlen mismatch for %s (if %d, RS packet %d)\n",
+ "%s: lladdrlen mismatch for %s (if %d, RS packet %u)\n",
__func__, ip6_sprintf(ip6bufs, &saddr6),
- ifp->if_addrlen, lladdrlen - 2));
+ ifp->if_addrlen, lladdrlen - 2 - lladdr_pad));
goto bad;
}
@@ -467,18 +469,20 @@
{
char ip6bufs[INET6_ADDRSTRLEN];
char *lladdr = NULL;
- int lladdrlen = 0;
+ u_int lladdr_pad = nd6_lladdr_opt_pad(ifp);
+ u_int lladdrlen = 0;
if (opthdr != NULL) {
- lladdr = (char *)(opthdr + 1);
+ lladdr = (char *)(opthdr + 1) + lladdr_pad;
lladdrlen = opthdr->nd_opt_len << 3;
}
- if (lladdr && ((ifp->if_addrlen + 2 + 7) & ~7) != lladdrlen) {
+ if (lladdr && ((ifp->if_addrlen + lladdr_pad + 2 + 7) & ~7) !=
+ lladdrlen) {
nd6log((LOG_INFO,
- "%s: lladdrlen mismatch for %s (if %d, RA packet %d)\n",
+ "%s: lladdrlen mismatch for %s (if %d, RA packet %u)\n",
__func__, ip6_sprintf(ip6bufs, &saddr6),
- ifp->if_addrlen, lladdrlen - 2));
+ ifp->if_addrlen, lladdrlen - 2 - lladdr_pad));
return (-1);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Jul 12, 4:27 PM (30 m, 18 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35002819
Default Alt Text
D58096.id181536.diff (9 KB)
Attached To
Mode
D58096: netinet6: fix ND link-layer address option layout for IPoIB
Attached
Detach File
Event Timeline
Log In to Comment