diff options
| author | Roy Marples <roy@marples.name> | 2015-06-05 14:55:08 +0000 |
|---|---|---|
| committer | Roy Marples <roy@marples.name> | 2015-06-05 14:55:08 +0000 |
| commit | a708c891a72608be87a8150abd700bc173afcba9 (patch) | |
| tree | 4677d5438b1450c84230dc1c8cdfb99804403c9d /ipv6nd.c | |
| parent | f572315de673651e8e7e44ec3f5a523b3f667d58 (diff) | |
| download | dhcpcd-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.c | 45 |
1 files changed, 31 insertions, 14 deletions
@@ -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; } } |
