Mercurial > hg > dhcpcd
changeset 4233:c2a1efc6b19a draft
dhcp6: deny unicast in non master mode
It seems that some DHCP6 servers or firewalls really insist on the
client sending from the correct source port.
This is the safest thing for the time being.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Sat, 10 Mar 2018 11:50:08 +0000 |
| parents | 8b92c1844860 |
| children | 56c1ab3b654e |
| files | src/dhcp6.c |
| diffstat | 1 files changed, 36 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
--- a/src/dhcp6.c Tue Mar 06 08:55:11 2018 +0000 +++ b/src/dhcp6.c Sat Mar 10 11:50:08 2018 +0000 @@ -777,6 +777,15 @@ return -1; } + /* In non master mode we listen and send from fixed addresses. + * We should try and match an address we have to unicast to, + * but for now this is the safest policy. */ + if (unicast != NULL && !(ifp->ctx->options & DHCPCD_MASTER)) { + logdebugx("%s: ignoring unicast option as not master", + ifp->name); + unicast = NULL; + } + #ifdef AUTH auth_len = 0; if (ifo->auth.options & DHCPCD_AUTH_SEND) { @@ -1092,6 +1101,8 @@ uint8_t neg; const char *broad_uni; const struct in6_addr alldhcp = IN6ADDR_LINKLOCAL_ALLDHCP_INIT; + struct ipv6_addr *lla; + int s; if (!callback && ifp->carrier == LINK_DOWN) return 0; @@ -1104,12 +1115,13 @@ #endif state = D6_STATE(ifp); + lla = ipv6_linklocal(ifp); /* We need to ensure we have sufficient scope to unicast the address */ /* XXX FIXME: We should check any added addresses we have like from * a Router Advertisement */ if (IN6_IS_ADDR_UNSPECIFIED(&state->unicast) || (state->state == DH6S_REQUEST && - (!IN6_IS_ADDR_LINKLOCAL(&state->unicast) || !ipv6_linklocal(ifp)))) + (!IN6_IS_ADDR_LINKLOCAL(&state->unicast) || lla == NULL))) { dst.sin6_addr = alldhcp; broad_uni = "broadcasting"; @@ -1251,7 +1263,16 @@ ctx->sndhdr.msg_controllen = 0; } - if (sendmsg(ctx->dhcp6_fd, &ctx->sndhdr, 0) == -1) { + if (ctx->dhcp6_fd != -1) + s = ctx->dhcp6_fd; + else if (lla != NULL && lla->dhcp6_fd != -1) + s = lla->dhcp6_fd; + else { + logerrx("%s: no socket to send from", ifp->name); + return -1; + } + + if (sendmsg(s, &ctx->sndhdr, 0) == -1) { logerr("%s: %s: sendmsg", __func__, ifp->name); /* Allow DHCPv6 to continue .... the errors * would be rate limited by the protocol. @@ -3551,19 +3572,16 @@ if (ia != NULL) { memcpy(&sa.sin6_addr, &ia->addr, sizeof(sa.sin6_addr)); sa.sin6_scope_id = ia->iface->index; - } else if (!(ctx->options & DHCPCD_MASTER)) - /* This socket is only used for sending. */ - return s; + } if (bind(s, (struct sockaddr *)&sa, sizeof(sa)) == -1) goto errexit; - if (ia == NULL) { - n = 1; - if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, - &n, sizeof(n)) == -1) - goto errexit; - } else { + n = 1; + if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &n, sizeof(n)) == -1) + goto errexit; + + if (ia != NULL) { ia->dhcp6_fd = s; eloop_event_add(ctx->eloop, s, dhcp6_recvaddr, ia); } @@ -3577,18 +3595,6 @@ return -1; } -static int -dhcp6_open(struct dhcpcd_ctx *ctx) -{ - - /* Open an unbound socket to send from. */ - ctx->dhcp6_fd = dhcp6_listen(ctx, NULL); - if (ctx->dhcp6_fd != -1 && (ctx->options & DHCPCD_MASTER)) - eloop_event_add(ctx->eloop, ctx->dhcp6_fd, dhcp6_recvctx, ctx); - - return ctx->dhcp6_fd; -} - #ifndef SMALL static void dhcp6_activateinterfaces(struct interface *ifp) @@ -3623,13 +3629,18 @@ dhcp6_start1(void *arg) { struct interface *ifp = arg; + struct dhcpcd_ctx *ctx = ifp->ctx; struct if_options *ifo = ifp->options; struct dhcp6_state *state; size_t i; const struct dhcp_compat *dhc; - if (ifp->ctx->dhcp6_fd == -1 && dhcp6_open(ifp->ctx) == -1) - return; + if (ctx->dhcp6_fd == -1 && ctx->options & DHCPCD_MASTER) { + ctx->dhcp6_fd = dhcp6_listen(ctx, NULL); + if (ctx->dhcp6_fd == -1) + return; + eloop_event_add(ctx->eloop, ctx->dhcp6_fd, dhcp6_recvctx, ctx); + } state = D6_STATE(ifp); /* If no DHCPv6 options are configured,
