summaryrefslogtreecommitdiffstats
path: root/ipv6nd.c
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2015-06-05 14:55:08 +0000
committerRoy Marples <roy@marples.name>2015-06-05 14:55:08 +0000
commita708c891a72608be87a8150abd700bc173afcba9 (patch)
tree4677d5438b1450c84230dc1c8cdfb99804403c9d /ipv6nd.c
parentf572315de673651e8e7e44ec3f5a523b3f667d58 (diff)
downloaddhcpcd-a708c891a72608be87a8150abd700bc173afcba9.tar.xz
Reject any NA/RA message with a hoplimit not equal to 255 as per RFC 4861 7.1.2.
Diffstat (limited to 'ipv6nd.c')
-rw-r--r--ipv6nd.c45
1 files changed, 31 insertions, 14 deletions
diff --git a/ipv6nd.c b/ipv6nd.c
index eebf8679..f2fd963e 100644
--- a/ipv6nd.c
+++ b/ipv6nd.c
@@ -759,7 +759,7 @@ ipv6nd_ra_has_public_addr(const struct ra *rap)
static void
ipv6nd_handlera(struct dhcpcd_ctx *dctx, struct interface *ifp,
- struct icmp6_hdr *icp, size_t len)
+ struct icmp6_hdr *icp, size_t len, int hoplimit)
{
struct ipv6_ctx *ctx = dctx->ipv6;
size_t i, olen;
@@ -780,25 +780,33 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx, struct interface *ifp,
uint8_t new_ap;
#endif
+ if (ifp == NULL) {
+#ifdef DEBUG_RS
+ logger(dctx, LOG_DEBUG,
+ "RA for unexpected interface from %s", ctx->sfrom);
+#endif
+ return;
+ }
+
if (len < sizeof(struct nd_router_advert)) {
logger(dctx, LOG_ERR,
"IPv6 RA packet too short from %s", ctx->sfrom);
return;
}
- if (!IN6_IS_ADDR_LINKLOCAL(&ctx->from.sin6_addr)) {
+ /* RFC 4861 7.1.2 */
+ if (hoplimit != 255) {
logger(dctx, LOG_ERR,
- "RA from non local address %s", ctx->sfrom);
+ "invalid hoplimit(%d) in RA from %s", hoplimit, ctx->sfrom);
return;
}
- if (ifp == NULL) {
-#ifdef DEBUG_RS
- logger(dctx, LOG_DEBUG,
- "RA for unexpected interface from %s", ctx->sfrom);
-#endif
+ if (!IN6_IS_ADDR_LINKLOCAL(&ctx->from.sin6_addr)) {
+ logger(dctx, LOG_ERR,
+ "RA from non local address %s", ctx->sfrom);
return;
}
+
if (!(ifp->options->options & DHCPCD_IPV6RS)) {
#ifdef DEBUG_RS
logger(ifp->ctx, LOG_DEBUG, "%s: unexpected RA from %s",
@@ -926,7 +934,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx, struct interface *ifp,
if (dho->option == ndo->nd_opt_type)
break;
}
- if (dho != NULL)
+ if (dho != NULL)
logger(ifp->ctx, LOG_WARNING,
"%s: reject RA (option %s) from %s",
ifp->name, dho->var, ctx->sfrom);
@@ -1497,7 +1505,7 @@ ipv6nd_drop(struct interface *ifp)
static void
ipv6nd_handlena(struct dhcpcd_ctx *dctx, struct interface *ifp,
- struct icmp6_hdr *icp, size_t len)
+ struct icmp6_hdr *icp, size_t len, int hoplimit)
{
struct ipv6_ctx *ctx = dctx->ipv6;
struct nd_neighbor_advert *nd_na;
@@ -1520,6 +1528,13 @@ ipv6nd_handlena(struct dhcpcd_ctx *dctx, struct interface *ifp,
return;
}
+ /* RFC 4861 7.1.2 */
+ if (hoplimit != 255) {
+ logger(dctx, LOG_ERR,
+ "invalid hoplimit(%d) in NA from %s", hoplimit, ctx->sfrom);
+ return;
+ }
+
nd_na = (struct nd_neighbor_advert *)icp;
is_router = nd_na->nd_na_flags_reserved & ND_NA_FLAG_ROUTER;
is_solicited = nd_na->nd_na_flags_reserved & ND_NA_FLAG_SOLICITED;
@@ -1623,9 +1638,9 @@ ipv6nd_handledata(void *arg)
}
}
- if (pkt.ipi6_ifindex == 0 || hoplimit == 0) {
+ if (pkt.ipi6_ifindex == 0) {
logger(dctx, LOG_ERR,
- "IPv6 RA/NA did not contain index or hop limit from %s",
+ "IPv6 RA/NA did not contain index from %s",
ctx->sfrom);
return;
}
@@ -1644,10 +1659,12 @@ ipv6nd_handledata(void *arg)
if (icp->icmp6_code == 0) {
switch(icp->icmp6_type) {
case ND_NEIGHBOR_ADVERT:
- ipv6nd_handlena(dctx, ifp, icp, (size_t)len);
+ ipv6nd_handlena(dctx, ifp, icp, (size_t)len,
+ hoplimit);
return;
case ND_ROUTER_ADVERT:
- ipv6nd_handlera(dctx, ifp, icp, (size_t)len);
+ ipv6nd_handlera(dctx, ifp, icp, (size_t)len,
+ hoplimit);
return;
}
}