IA options in one DHCP state as recommended by RFC 7550.
Hopefully this will simplify support a great deal.
# define SECRET SYSCONFDIR "/" PACKAGE ".secret"
#endif
#ifndef LEASEFILE
-# define LEASEFILE DBDIR "/" PACKAGE "-%s%s%s.lease"
+# define LEASEFILE DBDIR "/" PACKAGE "-%s%s.lease"
#endif
#ifndef LEASEFILE6
# define LEASEFILE6 LEASEFILE "6"
int
dhcp_set_leasefile(char *leasefile, size_t len, int family,
- const struct interface *ifp, const char *extra)
+ const struct interface *ifp)
{
char ssid[len];
ssid[0] = '\0';
return snprintf(leasefile, len,
family == AF_INET ? LEASEFILE : LEASEFILE6,
- ifp->name, ssid, extra);
+ ifp->name, ssid);
}
static size_t
size_t encode_rfc1035(const char *src, uint8_t *dst);
ssize_t decode_rfc3397(char *, size_t, const uint8_t *, size_t);
ssize_t print_string(char *, size_t, int, const uint8_t *, size_t);
-int dhcp_set_leasefile(char *, size_t, int,
- const struct interface *, const char *);
+int dhcp_set_leasefile(char *, size_t, int, const struct interface *);
size_t dhcp_envoption(struct dhcpcd_ctx *,
char **, const char *, const char *, struct dhcp_opt *,
state->raw_fd = state->arp_fd = -1;
TAILQ_INIT(&state->arp_states);
dhcp_set_leasefile(state->leasefile, sizeof(state->leasefile),
- AF_INET, ifp, "");
+ AF_INET, ifp);
state->new = read_lease(ifp);
if (state->new == NULL) {
logger(ifp->ctx, LOG_ERR, "%s: %s: %m",
state->reason = "PREINIT";
state->nakoff = 0;
dhcp_set_leasefile(state->leasefile, sizeof(state->leasefile),
- AF_INET, ifp, "");
+ AF_INET, ifp);
ifo = ifp->options;
/* We need to drop the leasefile so that dhcp_start
#include <netinet/in.h>
+#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
!(ap->flags & IPV6_AF_REQUEST))
continue;
if (ap->ia_type == D6_OPTION_IA_PD) {
- if (!(ifo->options & DHCPCD_NOPFXDLG)) {
- len += sizeof(*o) + sizeof(u8) +
- sizeof(u32) + sizeof(u32) +
- sizeof(ap->prefix);
- if (ap->prefix_exclude_len)
- len += sizeof(*o) + 1 +
- (uint8_t)((ap->prefix_exclude_len -
- ap->prefix_len - 1) / NBBY)
- + 1;
-
- }
- } else if (!(ifo->options & DHCPCD_PFXDLGONLY))
+ len += sizeof(*o) + sizeof(u8) +
+ sizeof(u32) + sizeof(u32) +
+ sizeof(ap->prefix);
+ if (ap->prefix_exclude_len)
+ len += sizeof(*o) + 1 +
+ (uint8_t)((ap->prefix_exclude_len -
+ ap->prefix_len - 1) / NBBY) + 1;
+ } else
len += sizeof(*o) + sizeof(ap->addr) +
sizeof(u32) + sizeof(u32);
}
/* FALLTHROUGH */
case DH6S_INIT:
- for (l = 0; l < ifo->ia_len; l++) {
- if (ifo->ia[l].ia_type == D6_OPTION_IA_PD) {
- if (ifo->options & DHCPCD_NOPFXDLG)
- continue;
- } else if (ifo->options & DHCPCD_PFXDLGONLY)
- continue;
- len += sizeof(*o) + (sizeof(u32) * 3);
- }
+ len += ifo->ia_len * (sizeof(*o) + (sizeof(u32) * 3));
IA = 1;
break;
default:
}
for (l = 0; IA && l < ifo->ia_len; l++) {
- if (ifo->ia[l].ia_type == D6_OPTION_IA_PD) {
- if (ifo->options & DHCPCD_NOPFXDLG)
- continue;
- } else if (ifo->options & DHCPCD_PFXDLGONLY)
- continue;
o = D6_NEXT_OPTION(o);
o->code = htons(ifo->ia[l].ia_type);
o->len = htons(sizeof(u32) + sizeof(u32) + sizeof(u32));
state->send->xid[2],
timespec_to_double(&state->RT));
+ /* This sometimes happens when we delegate to this interface
+ * AND run DHCPv6 on it normally. */
+ assert(timespec_to_double(&state->RT) != 0);
+
/* Wait the initial delay */
- if (state->IMD) {
+ if (state->IMD != 0) {
state->IMD = 0;
eloop_timeout_add_tv(ifp->ctx->eloop,
&state->RT, callback, ifp);
size_t i;
uint16_t t;
- if (ifp->options->options & DHCPCD_NOPFXDLG)
- return 0;
-
t = 0;
for (i = 0; i < ifp->options->ia_len; i++) {
if (t && t != ifp->options->ia[i].ia_type) {
continue;
}
if (code == D6_OPTION_IA_PD) {
- if (!(ifo->options & DHCPCD_NOPFXDLG) &&
- dhcp6_findpd(ifp, iaid, p, ol, acquired) == 0)
- {
+ if (dhcp6_findpd(ifp, iaid, p, ol, acquired) == 0) {
logger(ifp->ctx, LOG_WARNING,
"%s: %s: DHCPv6 REPLY missing Prefix",
ifp->name, sfrom);
continue;
}
- } else if (!(ifo->options & DHCPCD_PFXDLGONLY)) {
+ } else {
if (dhcp6_findna(ifp, code, iaid, p, ol, acquired) == 0)
{
logger(ifp->ctx, LOG_WARNING,
}
TAILQ_FOREACH(ifd, ifp->ctx->ifaces, next) {
- if (ifd->options->options & DHCPCD_NOPFXDLG)
- continue;
k = 0;
carrier_warned = abrt = 0;
TAILQ_FOREACH(ap, &state->addrs, next) {
return k;
}
-static struct interface *
-dhcp6_findpfxdlgif(struct interface *ifp)
-{
- struct interface *ifn;
-
- if (ifp->options && ifp->options->options & DHCPCD_PFXDLGONLY)
- return NULL;
-
- if (ifp->ctx && ifp->ctx->ifaces) {
- TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
- if (strcmp(ifn->name, ifp->name) == 0 &&
- ifn->options->options & DHCPCD_PFXDLGONLY)
- return ifn;
- }
- }
- return NULL;
-}
-
/* ARGSUSED */
static void
dhcp6_handledata(void *arg)
ssize_t bytes;
struct cmsghdr *cm;
struct in6_pktinfo pkt;
- struct interface *ifp, *ifpx;
+ struct interface *ifp;
const char *op;
struct dhcp6_message *r;
struct dhcp6_state *state;
}
TAILQ_FOREACH(ifp, dctx->ifaces, next) {
- /* Ensure we work on the master interface */
- if (ifp->index == (unsigned int)pkt.ipi6_ifindex &&
- !(ifp->options->options & DHCPCD_PFXDLGONLY))
+ if (ifp->index == (unsigned int)pkt.ipi6_ifindex)
break;
}
if (ifp == NULL) {
return;
}
- r = (struct dhcp6_message *)ctx->rcvhdr.msg_iov[0].iov_base;
-
- /* Which interface state is the IAID for? */
- ifpx = dhcp6_findpfxdlgif(ifp);
- if (ifpx && D6_STATE(ifpx)) {
- state = D6_STATE(ifpx);
- if (r->xid[0] == state->send->xid[0] &&
- r->xid[1] == state->send->xid[1] &&
- r->xid[2] == state->send->xid[2])
- ifp = ifpx;
- }
-
state = D6_STATE(ifp);
if (state == NULL || state->send == NULL) {
logger(ifp->ctx, LOG_DEBUG,
return;
}
+ r = (struct dhcp6_message *)ctx->rcvhdr.msg_iov[0].iov_base;
/* We're already bound and this message is for another machine */
/* XXX DELEGATED? */
if (r->type != DHCP6_RECONFIGURE &&
if (dhcp6_findselfsla(ifp, NULL))
del_option_mask(ifo->requestmask6, D6_OPTION_RAPID_COMMIT);
- /* Create a 2nd interface to handle the PD state */
- if (!(ifo->options & (DHCPCD_PFXDLGONLY | DHCPCD_PFXDLGMIX)) &&
- dhcp6_hasprefixdelegation(ifp) > 1)
- {
- const char * const argv[] = { ifp->name };
- struct if_head *ifs;
- struct interface *ifn;
-
- ifn = dhcp6_findpfxdlgif(ifp);
- if (ifn == NULL) {
- ifs = if_discover(ifp->ctx, -1, UNCONST(argv));
- if (ifs) {
- ifn = TAILQ_FIRST(ifs);
- if (ifn) {
- logger(ifp->ctx, LOG_INFO,
- "%s: creating pseudo interface"
- " to handle Prefix Delegation",
- ifp->name);
- ifp->options->options |=
- DHCPCD_NOPFXDLG;
- TAILQ_REMOVE(ifs, ifn, next);
- TAILQ_INSERT_AFTER(ifp->ctx->ifaces,
- ifp, ifn, next);
- dhcpcd_initstate(ifn,
- DHCPCD_PFXDLGONLY);
- eloop_timeout_add_sec(ifp->ctx->eloop,
- 0, dhcpcd_startinterface, ifn);
- }
- while ((ifn = TAILQ_FIRST(ifs))) {
- TAILQ_REMOVE(ifs, ifn, next);
- if_free(ifn);
- }
- free(ifs);
- }
- }
- }
-
if (state->state == DH6S_INFORM) {
add_option_mask(ifo->requestmask6, D6_OPTION_INFO_REFRESH_TIME);
dhcp6_startinform(ifp);
gogogo:
state->state = init_state;
dhcp_set_leasefile(state->leasefile, sizeof(state->leasefile),
- AF_INET6, ifp,
- ifp->options->options & DHCPCD_PFXDLGONLY ? ".pd" : "");
+ AF_INET6, ifp);
if (ipv6_linklocal(ifp) == NULL) {
logger(ifp->ctx, LOG_DEBUG,
"%s: delaying DHCPv6 soliciation for LL address",
static void
dhcp6_freedrop(struct interface *ifp, int drop, const char *reason)
{
- struct interface *ifpx;
struct dhcp6_state *state;
struct dhcpcd_ctx *ctx;
unsigned long long options;
(DHCPCD_EXITING | DHCPCD_PERSISTENT)) !=
(DHCPCD_EXITING | DHCPCD_PERSISTENT));
- ifpx = dhcp6_findpfxdlgif(ifp);
- if (ifpx) {
- if (options & DHCPCD_EXITING)
- ifpx->options->options |= DHCPCD_EXITING;
- dhcp6_freedrop(ifpx, dropdele ? 1 : drop, reason);
- TAILQ_REMOVE(ifp->ctx->ifaces, ifpx, next);
- if_free(ifpx);
- }
-
if (ifp->ctx->eloop)
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
}
TAILQ_INIT(&state->addrs);
dhcp_set_leasefile(state->leasefile, sizeof(state->leasefile),
- AF_INET6, ifp,
- ifp->options->options & DHCPCD_PFXDLGONLY ? ".pd" : "");
+ AF_INET6, ifp);
if (dhcp6_readlease(ifp, 0) == -1) {
logger(ifp->ctx, LOG_ERR, "%s: %s: %m",
*ifp->name ? ifp->name : state->leasefile, __func__);
*)
ifsuffix=".dhcp";;
esac
-ifname="$interface$ifsuffix${ifclass+.}$ifclass"
+ifname="$interface$ifsuffix"
from=from
signature_base="# Generated by dhcpcd"
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd May 9, 2015
+.Dd June 5, 2015
.Dt DHCPCD 8
.Os
.Sh NAME
or
.Fl 6
flags to specify an address family.
-Pass a 2nd
-.Fl U, Fl Fl dumplease option to dump a secondary lease, such as
-DHCPv6 Prefix Delegation when not being mixed with another IA type.
.It Fl V, Fl Fl variables
Display a list of option codes, the associated variable and encoding for use in
.Xr dhcpcd-run-hooks 8 .
RFC\ 3397, RFC\ 3442, RFC\ 3495, RFC\ 3925, RFC\ 3927, RFC\ 4039, RFC\ 4075,
RFC\ 4242, RFC\ 4361, RFC\ 4390, RFC\ 4702, RFC\ 4074, RFC\ 4861, RFC\ 4833,
RFC\ 4941, RFC\ 5227, RFC\ 5942, RFC\ 5969, RFC\ 6106, RFC\ 6334, RFC\ 6603,
-RFC\ 6704, RFC\ 7217.
+RFC\ 6704, RFC\ 7217, RFC\ 7550.
.Sh AUTHORS
.An Roy Marples Aq Mt roy@marples.name
.Sh BUGS
if (ifo->metric != -1)
ifp->metric = (unsigned int)ifo->metric;
- /* If we're a psuedo interface, ensure we disable as much as we can */
- if (ifp->options->options & DHCPCD_PFXDLGONLY)
- ifp->options->options &=
- ~(DHCPCD_IPV4 | DHCPCD_IPV6RS | DHCPCD_WAITIP | DHCPCD_WAITIP6);
-
if (!(ifo->options & DHCPCD_IPV4))
ifo->options &= ~(DHCPCD_DHCP | DHCPCD_IPV4LL | DHCPCD_WAITIP4);
TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
if (ifn == ifp)
continue;
- if (ifn->options->options & DHCPCD_PFXDLGONLY)
- continue;
if (memcmp(ifn->options->iaid, iaid,
sizeof(ifn->options->iaid)) == 0)
break;
}
/* This is only a problem if the interfaces are on the same network. */
- if (ifn && strcmp(ifp->name, ifn->name))
+ if (ifn)
logger(ifp->ctx, LOG_ERR,
"%s: IAID conflicts with one assigned to %s",
ifp->name, ifn->name);
if (ifp->ctx->duid == NULL) {
if (duid_init(ifp) == 0)
return;
- if (!(ifo->options & DHCPCD_PFXDLGONLY))
- logger(ifp->ctx, LOG_INFO, "DUID %s",
- hwaddr_ntoa(ifp->ctx->duid,
- ifp->ctx->duid_len,
- buf, sizeof(buf)));
+ logger(ifp->ctx, LOG_INFO, "DUID %s",
+ hwaddr_ntoa(ifp->ctx->duid,
+ ifp->ctx->duid_len,
+ buf, sizeof(buf)));
}
}
- if (ifo->options & (DHCPCD_DUID | DHCPCD_IPV6) &&
- !(ifo->options & DHCPCD_PFXDLGONLY))
- {
+ if (ifo->options & (DHCPCD_DUID | DHCPCD_IPV6)) {
/* Report IAIDs */
logger(ifp->ctx, LOG_INFO, "%s: IAID %s", ifp->name,
hwaddr_ntoa(ifo->iaid, sizeof(ifo->iaid),
{
struct interface *ifp;
- /* drop_dhcp could change the order, so we do it like this. */
- for (;;) {
- /* Be sane and drop the last config first,
- * skipping any pseudo interfaces */
- TAILQ_FOREACH_REVERSE(ifp, ctx->ifaces, if_head, next) {
- if (!(ifp->options->options & DHCPCD_PFXDLGONLY))
- break;
- }
- if (ifp == NULL)
- break;
+ /* Drop the last interface first */
+ while ((ifp = TAILQ_LAST(ctx->ifaces, if_head)) != NULL) {
if (do_release) {
ifp->options->options |= DHCPCD_RELEASE;
ifp->options->options &= ~DHCPCD_PERSISTENT;
i = 1;
break;
case 'U':
- if (i == 3)
- i = 4;
- else if (i != 4)
- i = 3;
+ i = 3;
break;
case 'V':
i = 2;
ctx.options |= DHCPCD_TEST;
else
ctx.options |= DHCPCD_DUMPLEASE;
- if (i == 4)
- ctx.options |= DHCPCD_PFXDLGONLY;
ctx.options |= DHCPCD_PERSISTENT;
ctx.options &= ~DHCPCD_DAEMONISE;
}
}
}
configure_interface(ifp, ctx.argc, ctx.argv, 0);
- if (ctx.options & DHCPCD_PFXDLGONLY)
- ifp->options->options |= DHCPCD_PFXDLGONLY;
if (family == 0 || family == AF_INET) {
if (dhcp_dump(ifp) == -1)
i = 1;
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd June 3, 2015
+.Dd June 5, 2015
.Dt DHCPCD.CONF 5
.Os
.Sh NAME
ia_na 1 # request an IPv6 address
ia_pd 2 eth1/0 # get a /64 and assign it to eth1
.Ed
-.It Ic ia_pd_mix
-To be RFC compliant,
-.Nm dhcpcd
-cannot mix Prefix Delegation with other DHCPv6 address types in the same
-session.
-This has a number of issues: additional DHCP traffic and potential collisions
-between options.
-.Ic ia_pd_mix
-enables
-.Li draft-ietf-dhc-dhcpv6-stateful-issues-06
-support so that Prefix Delegation can be mixed with other address types in
-the same session.
.It Ic ipv4only
Only configure IPv4.
.It Ic ipv6only
#define O_CONTROLGRP O_BASE + 34
#define O_SLAAC O_BASE + 35
#define O_GATEWAY O_BASE + 36
-#define O_PFXDLGMIX O_BASE + 37
+// unassigned O_BASE + 37
#define O_IPV6RA_AUTOCONF O_BASE + 38
#define O_IPV6RA_NOAUTOCONF O_BASE + 39
#define O_REJECT O_BASE + 40
{"controlgroup", required_argument, NULL, O_CONTROLGRP},
{"slaac", required_argument, NULL, O_SLAAC},
{"gateway", no_argument, NULL, O_GATEWAY},
- {"ia_pd_mix", no_argument, NULL, O_PFXDLGMIX},
{"reject", required_argument, NULL, O_REJECT},
{"bootp", no_argument, NULL, O_BOOTP},
{"nodelay", no_argument, NULL, O_NODELAY},
else
ifo->options &= ~DHCPCD_SLAACPRIVATE;
break;
- case O_PFXDLGMIX:
- ifo->options |= DHCPCD_PFXDLGMIX;
- break;
case O_BOOTP:
ifo->options |= DHCPCD_BOOTP;
break;
#define DHCPCD_IAID (1ULL << 48)
#define DHCPCD_DHCP (1ULL << 49)
#define DHCPCD_DHCP6 (1ULL << 50)
-#define DHCPCD_NOPFXDLG (1ULL << 51)
-#define DHCPCD_PFXDLGONLY (1ULL << 52)
-#define DHCPCD_PFXDLGMIX (1ULL << 53)
+// unassigned (1ULL << 51)
+// unassigned (1ULL << 52)
+// unassinged (1ULL << 53)
#define DHCPCD_IPV6RA_AUTOCONF (1ULL << 54)
#define DHCPCD_ROUTER_HOST_ROUTE_WARNED (1ULL << 55)
#define DHCPCD_IPV6RA_ACCEPT_NOPUBLIC (1ULL << 56)
#define DHCPCD_WARNINGS (DHCPCD_CSR_WARNED | \
DHCPCD_ROUTER_HOST_ROUTE_WARNED)
-#define DHCPCD_CONF (DHCPCD_NOPFXDLG | DHCPCD_PFXDLGONLY)
extern const struct option cf_options[];
struct interface *ifp;
TAILQ_FOREACH(ifp, ifaces, next) {
- if ((ifp->options == NULL ||
- !(ifp->options->options & DHCPCD_PFXDLGONLY)) &&
- ((name && strcmp(ifp->name, name) == 0) ||
+ if ((name && strcmp(ifp->name, name) == 0) ||
#ifdef __linux__
(name && strcmp(ifp->alias, name) == 0) ||
#endif
- (!name && ifp->index == idx)))
+ (!name && ifp->index == idx))
return ifp;
}
}
int r;
#endif
- /* Always prefer master interfaces */
- if (!(si->options->options & DHCPCD_PFXDLGONLY) &&
- ti->options->options & DHCPCD_PFXDLGONLY)
- return -1;
- if (si->options->options & DHCPCD_PFXDLGONLY &&
- !(ti->options->options & DHCPCD_PFXDLGONLY))
- return 1;
-
/* Check carrier status first */
if (si->carrier > ti->carrier)
return -1;
goto out;
TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
- if (ifn == ifp || strcmp(ifn->name, ifp->name) == 0)
+ if (ifn == ifp)
break; /* We are already the most preferred */
nstate = D_STATE(ifn);
if (nstate && !nstate->added &&
/* Ensure only one interface has the address */
r = 0;
TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
- if (ifn == ifp || strcmp(ifn->name, ifp->name) == 0) {
+ if (ifn == ifp) {
r = 1; /* past ourselves */
continue;
}
/* Does another interface already have the address from a prior boot? */
if (ifn == NULL) {
TAILQ_FOREACH(ifn, ifp->ctx->ifaces, next) {
- if (ifn == ifp || strcmp(ifn->name, ifp->name) == 0)
+ if (ifn == ifp)
continue;
ap = ipv4_iffindaddr(ifn, &lease->addr, NULL);
if (ap)
/* Ensure no other interface has this address */
TAILQ_FOREACH(ifp, ap->iface->ctx->ifaces, next) {
- if (ifp == ap->iface || strcmp(ifp->name, ap->iface->name) == 0)
+ if (ifp == ap->iface)
continue;
state = IPV6_STATE(ifp);
if (state == NULL)
{
apf = ipv6_findaddr(ap->iface->ctx,
&ap->addr, IPV6_AF_ADDED);
- if (apf && apf->iface != ap->iface &&
- strcmp(apf->iface->name, ap->iface->name))
- {
+ if (apf && apf->iface != ap->iface) {
if (apf->iface->metric <= ap->iface->metric) {
logger(apf->iface->ctx, LOG_INFO,
"%s: preferring %s on %s",
/* Find the same address somewhere else */
apf = ipv6_findaddr(ap->iface->ctx, &ap->addr, 0);
if (apf == NULL ||
- (apf->iface != ap->iface &&
- strcmp(apf->iface->name, ap->iface->name)))
+ (apf->iface != ap->iface))
ipv6_deleteaddr(ap);
if (!(ap->iface->options->options &
DHCPCD_EXITING) && apf)
errno = ESRCH;
return;
}
- TAILQ_FOREACH(ifp, ifs, next) {
- /* Each psuedo interface also stores addresses */
- if (strcmp(ifp->name, ifname))
- continue;
- state = ipv6_getstate(ifp);
- if (state == NULL)
- continue;
-
- if (!IN6_IS_ADDR_LINKLOCAL(addr)) {
- ipv6nd_handleifa(ctx, cmd, ifname, addr, flags);
- dhcp6_handleifa(ctx, cmd, ifname, addr, flags);
- }
+ if ((ifp = if_find(ifs, ifname)) == NULL)
+ return;
+ if ((state = ipv6_getstate(ifp)) == NULL)
+ return;
- TAILQ_FOREACH(ap, &state->addrs, next) {
- if (IN6_ARE_ADDR_EQUAL(&ap->addr, addr))
- break;
- }
+ if (!IN6_IS_ADDR_LINKLOCAL(addr)) {
+ ipv6nd_handleifa(ctx, cmd, ifname, addr, flags);
+ dhcp6_handleifa(ctx, cmd, ifname, addr, flags);
+ }
- switch (cmd) {
- case RTM_DELADDR:
- if (ap) {
- TAILQ_REMOVE(&state->addrs, ap, next);
- ipv6_freeaddr(ap);
- }
+ TAILQ_FOREACH(ap, &state->addrs, next) {
+ if (IN6_ARE_ADDR_EQUAL(&ap->addr, addr))
break;
- case RTM_NEWADDR:
- if (ap == NULL) {
- char buf[INET6_ADDRSTRLEN];
- const char *cbp;
-
- ap = calloc(1, sizeof(*ap));
- ap->iface = ifp;
- ap->addr = *addr;
- ap->prefix_len = prefix_len;
- ipv6_makeprefix(&ap->prefix, &ap->addr,
- ap->prefix_len);
- cbp = inet_ntop(AF_INET6, &addr->s6_addr,
- buf, sizeof(buf));
- if (cbp)
- snprintf(ap->saddr, sizeof(ap->saddr),
- "%s/%d", cbp, prefix_len);
- if (if_getlifetime6(ap) == -1) {
- /* No support or address vanished.
- * Either way, just set a deprecated
- * infinite time lifetime and continue.
- * This is fine because we only want
- * to know this when trying to extend
- * temporary addresses.
- * As we can't extend infinite, we'll
- * create a new temporary address. */
- ap->prefix_pltime = 0;
- ap->prefix_vltime =
- ND6_INFINITE_LIFETIME;
- }
- /* This is a minor regression against RFC 4941
- * because the kernel only knows when the
- * lifetimes were last updated, not when the
- * address was initially created.
- * Provided dhcpcd is not restarted, this
- * won't be a problem.
- * If we don't like it, we can always
- * pretend lifetimes are infinite and always
- * generate a new temporary address on
- * restart. */
- ap->acquired = ap->created;
- TAILQ_INSERT_TAIL(&state->addrs,
- ap, next);
+ }
+
+ switch (cmd) {
+ case RTM_DELADDR:
+ if (ap) {
+ TAILQ_REMOVE(&state->addrs, ap, next);
+ ipv6_freeaddr(ap);
+ }
+ break;
+ case RTM_NEWADDR:
+ if (ap == NULL) {
+ char buf[INET6_ADDRSTRLEN];
+ const char *cbp;
+
+ ap = calloc(1, sizeof(*ap));
+ ap->iface = ifp;
+ ap->addr = *addr;
+ ap->prefix_len = prefix_len;
+ ipv6_makeprefix(&ap->prefix, &ap->addr,
+ ap->prefix_len);
+ cbp = inet_ntop(AF_INET6, &addr->s6_addr,
+ buf, sizeof(buf));
+ if (cbp)
+ snprintf(ap->saddr, sizeof(ap->saddr),
+ "%s/%d", cbp, prefix_len);
+ if (if_getlifetime6(ap) == -1) {
+ /* No support or address vanished.
+ * Either way, just set a deprecated
+ * infinite time lifetime and continue.
+ * This is fine because we only want
+ * to know this when trying to extend
+ * temporary addresses.
+ * As we can't extend infinite, we'll
+ * create a new temporary address. */
+ ap->prefix_pltime = 0;
+ ap->prefix_vltime =
+ ND6_INFINITE_LIFETIME;
}
- ap->addr_flags = flags;
+ /* This is a minor regression against RFC 4941
+ * because the kernel only knows when the
+ * lifetimes were last updated, not when the
+ * address was initially created.
+ * Provided dhcpcd is not restarted, this
+ * won't be a problem.
+ * If we don't like it, we can always
+ * pretend lifetimes are infinite and always
+ * generate a new temporary address on
+ * restart. */
+ ap->acquired = ap->created;
+ TAILQ_INSERT_TAIL(&state->addrs,
+ ap, next);
+ }
+ ap->addr_flags = flags;
#ifdef IPV6_MANAGETEMPADDR
- if (ap->addr_flags & IN6_IFF_TEMPORARY)
- ap->flags |= IPV6_AF_TEMPORARY;
+ if (ap->addr_flags & IN6_IFF_TEMPORARY)
+ ap->flags |= IPV6_AF_TEMPORARY;
#endif
- if (IN6_IS_ADDR_LINKLOCAL(&ap->addr)) {
+ if (IN6_IS_ADDR_LINKLOCAL(&ap->addr)) {
#ifdef IPV6_POLLADDRFLAG
- if (ap->addr_flags & IN6_IFF_TENTATIVE) {
- struct timespec tv;
-
- ms_to_ts(&tv, RETRANS_TIMER / 2);
- eloop_timeout_add_tv(
- ap->iface->ctx->eloop,
- &tv, ipv6_checkaddrflags, ap);
- break;
- }
+ if (ap->addr_flags & IN6_IFF_TENTATIVE) {
+ struct timespec tv;
+
+ ms_to_ts(&tv, RETRANS_TIMER / 2);
+ eloop_timeout_add_tv(
+ ap->iface->ctx->eloop,
+ &tv, ipv6_checkaddrflags, ap);
+ break;
+ }
#endif
- if (!(ap->addr_flags & IN6_IFF_NOTUSEABLE)) {
- /* Now run any callbacks.
- * Typically IPv6RS or DHCPv6 */
- while ((cb =
- TAILQ_FIRST(&state->ll_callbacks)))
- {
- TAILQ_REMOVE(
- &state->ll_callbacks,
- cb, next);
- cb->callback(cb->arg);
- free(cb);
- }
+ if (!(ap->addr_flags & IN6_IFF_NOTUSEABLE)) {
+ /* Now run any callbacks.
+ * Typically IPv6RS or DHCPv6 */
+ while ((cb =
+ TAILQ_FIRST(&state->ll_callbacks)))
+ {
+ TAILQ_REMOVE(
+ &state->ll_callbacks,
+ cb, next);
+ cb->callback(cb->arg);
+ free(cb);
}
}
- break;
}
+ break;
}
}
}
TAILQ_FOREACH(ifp, dctx->ifaces, next) {
- if (ifp->index == (unsigned int)pkt.ipi6_ifindex &&
- !(ifp->options->options & DHCPCD_PFXDLGONLY))
- {
+ if (ifp->index == (unsigned int)pkt.ipi6_ifindex) {
if (!(ifp->options->options & DHCPCD_IPV6))
return;
break;
snprintf(env[7], e, "ifmtu=%d", if_getmtu(ifp->name));
l = e = strlen("interface_order=");
TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
- if (!(ifp2->options->options & DHCPCD_PFXDLGONLY))
- e += strlen(ifp2->name) + 1;
+ e += strlen(ifp2->name) + 1;
}
EMALLOC(8, e);
p = env[8];
e -= l;
p += l;
TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
- if (!(ifp2->options->options & DHCPCD_PFXDLGONLY)) {
- l = strlcpy(p, ifp2->name, e);
- p += l;
- e -= l;
- *p++ = ' ';
- e--;
- }
+ l = strlcpy(p, ifp2->name, e);
+ p += l;
+ e -= l;
+ *p++ = ' ';
+ e--;
}
*--p = '\0';
if (strcmp(reason, "STOPPED") == 0) {
}
#endif
#ifdef INET6
- if (dhcp6 && d6_state && ifo->options & DHCPCD_PFXDLGONLY) {
- nenv = realloc(env, sizeof(char *) * (elen + 2));
- if (nenv == NULL)
- goto eexit;
- env = nenv;
- env[elen] = strdup("ifclass=pd");
- if (env[elen] == NULL)
- goto eexit;
- elen++;
- }
if (dhcp6 && d6_state && d6_state->old) {
n = dhcp6_env(NULL, NULL, ifp,
d6_state->old, d6_state->old_len);