Sync
This commit is contained in:
parent
cdfaff8fa4
commit
5520e60803
|
@ -215,6 +215,12 @@ get_option(struct dhcpcd_ctx *ctx,
|
|||
}
|
||||
l = *p++;
|
||||
|
||||
/* Check we can read the option data, if present */
|
||||
if (p + l > e) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (o == DHO_OPTSOVERLOADED) {
|
||||
/* Ensure we only get this option once by setting
|
||||
* the last bit as well as the value.
|
||||
|
@ -249,10 +255,6 @@ get_option(struct dhcpcd_ctx *ctx,
|
|||
bp += ol;
|
||||
}
|
||||
ol = l;
|
||||
if (p + ol >= e) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
op = p;
|
||||
bl += ol;
|
||||
}
|
||||
|
@ -2075,7 +2077,7 @@ dhcp_arp_probed(struct arp_state *astate)
|
|||
ifp->name, inet_ntoa(astate->addr));
|
||||
if (!(ifo->options & DHCPCD_INFORM))
|
||||
dhcp_bind(ifp);
|
||||
#ifndef IN_IFF_TENTATIVE
|
||||
#ifndef IN_IFF_DUPLICATED
|
||||
else {
|
||||
struct bootp *bootp;
|
||||
size_t len;
|
||||
|
@ -2429,7 +2431,7 @@ dhcp_arp_address(struct interface *ifp)
|
|||
if (astate == NULL)
|
||||
return -1;
|
||||
|
||||
#ifdef IN_IFF_TENTATIVE
|
||||
#ifdef IN_IFF_NOTUSEABLE
|
||||
if (ia == NULL || ia->addr_flags & IN_IFF_NOTUSEABLE) {
|
||||
state->state = DHS_PROBE;
|
||||
if (ia == NULL) {
|
||||
|
|
|
@ -2029,12 +2029,12 @@ dhcp6_findna(struct interface *ifp, uint16_t ot, const uint8_t *iaid,
|
|||
nd = o + ol;
|
||||
l -= (size_t)(nd - d);
|
||||
d = nd;
|
||||
if (ol < 24) {
|
||||
if (ol < sizeof(ia)) {
|
||||
errno = EINVAL;
|
||||
logerrx("%s: IA Address option truncated", ifp->name);
|
||||
continue;
|
||||
}
|
||||
memcpy(&ia, o, ol);
|
||||
memcpy(&ia, o, sizeof(ia));
|
||||
ia.pltime = ntohl(ia.pltime);
|
||||
ia.vltime = ntohl(ia.vltime);
|
||||
/* RFC 3315 22.6 */
|
||||
|
@ -3035,7 +3035,7 @@ dhcp6_bind(struct interface *ifp, const char *op, const char *sfrom)
|
|||
* unless those values in those fields are 0.
|
||||
*/
|
||||
logwarnx("%s: ignoring T1 %"PRIu32
|
||||
" to due address expiry",
|
||||
" due to address expiry",
|
||||
ifp->name, state->renew);
|
||||
state->renew = state->rebind = 0;
|
||||
}
|
||||
|
|
|
@ -943,10 +943,15 @@ if_getlifetime6(struct ipv6_addr *ia)
|
|||
priv = (struct priv *)ia->iface->ctx->priv;
|
||||
if (ioctl(priv->pf_inet6_fd, SIOCGIFALIFETIME_IN6, &ifr6) == -1)
|
||||
return -1;
|
||||
clock_gettime(CLOCK_MONOTONIC, &ia->created);
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
t = ia->created.tv_sec;
|
||||
#else
|
||||
t = time(NULL);
|
||||
lifetime = &ifr6.ifr_ifru.ifru_lifetime;
|
||||
#endif
|
||||
|
||||
lifetime = &ifr6.ifr_ifru.ifru_lifetime;
|
||||
if (lifetime->ia6t_preferred)
|
||||
ia->prefix_pltime = (uint32_t)(lifetime->ia6t_preferred -
|
||||
MIN(t, lifetime->ia6t_preferred));
|
||||
|
@ -956,7 +961,6 @@ if_getlifetime6(struct ipv6_addr *ia)
|
|||
ia->prefix_vltime = (uint32_t)(lifetime->ia6t_expire -
|
||||
MIN(t, lifetime->ia6t_expire));
|
||||
/* Calculate the created time */
|
||||
clock_gettime(CLOCK_MONOTONIC, &ia->created);
|
||||
ia->created.tv_sec -= lifetime->ia6t_vltime - ia->prefix_vltime;
|
||||
} else
|
||||
ia->prefix_vltime = ND6_INFINITE_LIFETIME;
|
||||
|
|
|
@ -190,54 +190,106 @@ ipv6nd_printoptions(const struct dhcpcd_ctx *ctx,
|
|||
}
|
||||
|
||||
static int
|
||||
ipv6nd_open(struct dhcpcd_ctx *ctx)
|
||||
ipv6nd_open0(void)
|
||||
{
|
||||
int on;
|
||||
int s, on;
|
||||
struct icmp6_filter filt;
|
||||
|
||||
if (ctx->nd_fd != -1)
|
||||
return ctx->nd_fd;
|
||||
#define SOCK_FLAGS SOCK_CLOEXEC | SOCK_NONBLOCK
|
||||
ctx->nd_fd = xsocket(PF_INET6, SOCK_RAW | SOCK_FLAGS, IPPROTO_ICMPV6);
|
||||
s = xsocket(PF_INET6, SOCK_RAW | SOCK_FLAGS, IPPROTO_ICMPV6);
|
||||
#undef SOCK_FLAGS
|
||||
if (ctx->nd_fd == -1)
|
||||
if (s == -1)
|
||||
return -1;
|
||||
|
||||
/* RFC4861 4.1 */
|
||||
on = 255;
|
||||
if (setsockopt(ctx->nd_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
|
||||
&on, sizeof(on)) == -1)
|
||||
goto eexit;
|
||||
|
||||
on = 1;
|
||||
if (setsockopt(ctx->nd_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
|
||||
&on, sizeof(on)) == -1)
|
||||
goto eexit;
|
||||
|
||||
on = 1;
|
||||
if (setsockopt(ctx->nd_fd, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT,
|
||||
&on, sizeof(on)) == -1)
|
||||
goto eexit;
|
||||
|
||||
ICMP6_FILTER_SETBLOCKALL(&filt);
|
||||
ICMP6_FILTER_SETPASS(ND_NEIGHBOR_ADVERT, &filt);
|
||||
ICMP6_FILTER_SETPASS(ND_ROUTER_ADVERT, &filt);
|
||||
if (setsockopt(ctx->nd_fd, IPPROTO_ICMPV6, ICMP6_FILTER,
|
||||
if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER,
|
||||
&filt, sizeof(filt)) == -1)
|
||||
goto eexit;
|
||||
|
||||
eloop_event_add(ctx->eloop, ctx->nd_fd, ipv6nd_handledata, ctx);
|
||||
return ctx->nd_fd;
|
||||
return s;
|
||||
|
||||
eexit:
|
||||
if (ctx->nd_fd != -1) {
|
||||
eloop_event_delete(ctx->eloop, ctx->nd_fd);
|
||||
close(ctx->nd_fd);
|
||||
ctx->nd_fd = -1;
|
||||
}
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __sun
|
||||
static int
|
||||
ipv6nd_open(struct interface *ifp)
|
||||
{
|
||||
int s;
|
||||
struct ipv6_mreq mreq = {
|
||||
.ipv6mr_multiaddr = IN6ADDR_LINKLOCAL_ALLNODES_INIT,
|
||||
.ipv6mr_interface = ifp->index
|
||||
};
|
||||
struct rs_state *state = RS_STATE(ifp);
|
||||
uint_t ifindex = ifp->index;
|
||||
|
||||
if (state->nd_fd != -1)
|
||||
return state->nd_fd;
|
||||
|
||||
s = ipv6nd_open0();
|
||||
if (s == -1)
|
||||
return -1;
|
||||
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_BOUND_IF,
|
||||
&ifindex, sizeof(ifindex)) == -1)
|
||||
{
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP,
|
||||
&mreq, sizeof(mreq)) == -1)
|
||||
{
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
state->nd_fd = s;
|
||||
eloop_event_add(ifp->ctx->eloop, s, ipv6nd_handledata, ifp);
|
||||
return s;
|
||||
}
|
||||
#else
|
||||
static int
|
||||
ipv6nd_open(struct dhcpcd_ctx *ctx)
|
||||
{
|
||||
int s, on;
|
||||
|
||||
if (ctx->nd_fd != -1)
|
||||
return ctx->nd_fd;
|
||||
|
||||
s = ipv6nd_open0();
|
||||
if (s == -1)
|
||||
return -1;
|
||||
|
||||
on = 1;
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO,
|
||||
&on, sizeof(on)) == -1)
|
||||
{
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->nd_fd = s;
|
||||
eloop_event_add(ctx->eloop, s, ipv6nd_handledata, ctx);
|
||||
return s;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
ipv6nd_makersprobe(struct interface *ifp)
|
||||
{
|
||||
|
@ -273,9 +325,12 @@ static void
|
|||
ipv6nd_sendrsprobe(void *arg)
|
||||
{
|
||||
struct interface *ifp = arg;
|
||||
struct dhcpcd_ctx *ctx;
|
||||
struct rs_state *state = RS_STATE(ifp);
|
||||
struct sockaddr_in6 dst = { .sin6_family = AF_INET6 };
|
||||
struct sockaddr_in6 dst = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_addr = IN6ADDR_LINKLOCAL_ALLROUTERS_INIT,
|
||||
.sin6_scope_id = ifp->index,
|
||||
};
|
||||
struct iovec iov = { .iov_base = state->rs, .iov_len = state->rslen };
|
||||
unsigned char ctl[CMSG_SPACE(sizeof(struct in6_pktinfo))] = { 0 };
|
||||
struct msghdr msg = {
|
||||
|
@ -285,6 +340,7 @@ ipv6nd_sendrsprobe(void *arg)
|
|||
};
|
||||
struct cmsghdr *cm;
|
||||
struct in6_pktinfo pi = { .ipi6_ifindex = ifp->index };
|
||||
int s;
|
||||
|
||||
if (ipv6_linklocal(ifp) == NULL) {
|
||||
logdebugx("%s: delaying Router Solicitation for LL address",
|
||||
|
@ -296,13 +352,6 @@ ipv6nd_sendrsprobe(void *arg)
|
|||
#ifdef HAVE_SA_LEN
|
||||
dst.sin6_len = sizeof(dst);
|
||||
#endif
|
||||
dst.sin6_scope_id = ifp->index;
|
||||
if (inet_pton(AF_INET6, ALLROUTERS, &dst.sin6_addr) != 1) {
|
||||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
ctx = ifp->ctx;
|
||||
|
||||
/* Set the outbound interface */
|
||||
cm = CMSG_FIRSTHDR(&msg);
|
||||
|
@ -314,7 +363,12 @@ ipv6nd_sendrsprobe(void *arg)
|
|||
memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
|
||||
|
||||
logdebugx("%s: sending Router Solicitation", ifp->name);
|
||||
if (sendmsg(ctx->nd_fd, &msg, 0) == -1) {
|
||||
#ifdef __sun
|
||||
s = state->nd_fd;
|
||||
#else
|
||||
s = ifp->ctx->nd_fd;
|
||||
#endif
|
||||
if (sendmsg(s, &msg, 0) == -1) {
|
||||
logerr(__func__);
|
||||
/* Allow IPv6ND to continue .... at most a few errors
|
||||
* would be logged.
|
||||
|
@ -342,6 +396,7 @@ ipv6nd_sendadvertisement(void *arg)
|
|||
struct dhcpcd_ctx *ctx = ifp->ctx;
|
||||
struct sockaddr_in6 dst = {
|
||||
.sin6_family = AF_INET6,
|
||||
.sin6_addr = IN6ADDR_LINKLOCAL_ALLNODES_INIT,
|
||||
.sin6_scope_id = ifp->index,
|
||||
};
|
||||
struct iovec iov = { .iov_base = ia->na, .iov_len = ia->na_len };
|
||||
|
@ -354,6 +409,7 @@ ipv6nd_sendadvertisement(void *arg)
|
|||
struct cmsghdr *cm;
|
||||
struct in6_pktinfo pi = { .ipi6_ifindex = ifp->index };
|
||||
const struct rs_state *state = RS_CSTATE(ifp);
|
||||
int s;
|
||||
|
||||
if (state == NULL || ifp->carrier <= LINK_DOWN)
|
||||
goto freeit;
|
||||
|
@ -361,10 +417,6 @@ ipv6nd_sendadvertisement(void *arg)
|
|||
#ifdef SIN6_LEN
|
||||
dst.sin6_len = sizeof(dst);
|
||||
#endif
|
||||
if (inet_pton(AF_INET6, ALLNODES, &dst.sin6_addr) != 1) {
|
||||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Set the outbound interface. */
|
||||
cm = CMSG_FIRSTHDR(&msg);
|
||||
|
@ -373,10 +425,20 @@ ipv6nd_sendadvertisement(void *arg)
|
|||
cm->cmsg_type = IPV6_PKTINFO;
|
||||
cm->cmsg_len = CMSG_LEN(sizeof(pi));
|
||||
memcpy(CMSG_DATA(cm), &pi, sizeof(pi));
|
||||
|
||||
logdebugx("%s: sending NA for %s", ifp->name, ia->saddr);
|
||||
if (sendmsg(ctx->nd_fd, &msg, 0) == -1)
|
||||
#ifdef __sun
|
||||
s = state->nd_fd;
|
||||
#else
|
||||
s = ctx->nd_fd;
|
||||
#endif
|
||||
if (sendmsg(s, &msg, 0) == -1)
|
||||
#ifdef __OpenBSD__
|
||||
/* This isn't too critical as they don't support IPv6 address sharing */
|
||||
#warning Cannot send NA messages on OpenBSD
|
||||
logdebug(__func__);
|
||||
#else
|
||||
logerr(__func__);
|
||||
#endif
|
||||
|
||||
if (++ia->na_count < MAX_NEIGHBOR_ADVERTISEMENT) {
|
||||
eloop_timeout_add_sec(ctx->eloop,
|
||||
|
@ -619,6 +681,11 @@ ipv6nd_free(struct interface *ifp)
|
|||
if (state == NULL)
|
||||
return 0;
|
||||
|
||||
ctx = ifp->ctx;
|
||||
#ifdef __sun
|
||||
eloop_event_delete(ctx->eloop, state->nd_fd);
|
||||
close(state->nd_fd);
|
||||
#endif
|
||||
free(state->rs);
|
||||
free(state);
|
||||
ifp->if_data[IF_DATA_IPV6ND] = NULL;
|
||||
|
@ -630,9 +697,9 @@ ipv6nd_free(struct interface *ifp)
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef __sun
|
||||
/* If we don't have any more IPv6 enabled interfaces,
|
||||
* close the global socket and release resources */
|
||||
ctx = ifp->ctx;
|
||||
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
|
||||
if (RS_STATE(ifp))
|
||||
break;
|
||||
|
@ -644,6 +711,7 @@ ipv6nd_free(struct interface *ifp)
|
|||
ctx->nd_fd = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return n;
|
||||
}
|
||||
|
@ -1659,6 +1727,7 @@ static void
|
|||
ipv6nd_handledata(void *arg)
|
||||
{
|
||||
struct dhcpcd_ctx *ctx;
|
||||
int s;
|
||||
struct sockaddr_in6 from;
|
||||
unsigned char buf[64 * 1024]; /* Maximum ICMPv6 size */
|
||||
struct iovec iov = {
|
||||
|
@ -1677,8 +1746,18 @@ ipv6nd_handledata(void *arg)
|
|||
struct icmp6_hdr *icp;
|
||||
struct interface *ifp;
|
||||
|
||||
#ifdef __sun
|
||||
struct rs_state *state;
|
||||
|
||||
ifp = arg;
|
||||
state = RS_STATE(ifp);
|
||||
ctx = ifp->ctx;
|
||||
s = state->nd_fd;
|
||||
#else
|
||||
ctx = arg;
|
||||
len = recvmsg(ctx->nd_fd, &msg, 0);
|
||||
s = ctx->nd_fd;
|
||||
#endif
|
||||
len = recvmsg(s, &msg, 0);
|
||||
if (len == -1) {
|
||||
logerr(__func__);
|
||||
return;
|
||||
|
@ -1689,11 +1768,15 @@ ipv6nd_handledata(void *arg)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef __sun
|
||||
if_findifpfromcmsg(ctx, &msg, &hoplimit);
|
||||
#else
|
||||
ifp = if_findifpfromcmsg(ctx, &msg, &hoplimit);
|
||||
if (ifp == NULL) {
|
||||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Don't do anything if the user hasn't configured it. */
|
||||
if (ifp->active != IF_ACTIVE_USER ||
|
||||
|
@ -1725,11 +1808,6 @@ ipv6nd_startrs1(void *arg)
|
|||
struct rs_state *state;
|
||||
|
||||
loginfox("%s: soliciting an IPv6 router", ifp->name);
|
||||
if (ipv6nd_open(ifp->ctx) == -1) {
|
||||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
state = RS_STATE(ifp);
|
||||
if (state == NULL) {
|
||||
ifp->if_data[IF_DATA_IPV6ND] = calloc(1, sizeof(*state));
|
||||
|
@ -1738,8 +1816,23 @@ ipv6nd_startrs1(void *arg)
|
|||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
#ifdef __sun
|
||||
state->nd_fd = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __sun
|
||||
if (ipv6nd_open(ifp) == -1) {
|
||||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (ipv6nd_open(ifp->ctx) == -1) {
|
||||
logerr(__func__);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Always make a new probe as the underlying hardware
|
||||
* address could have changed. */
|
||||
ipv6nd_makersprobe(ifp);
|
||||
|
|
Loading…
Reference in New Issue