This commit is contained in:
roy 2014-07-14 11:49:48 +00:00
parent 9d162be235
commit 1f96c74429
8 changed files with 406 additions and 285 deletions

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: dhcp.c,v 1.13 2014/06/14 20:55:37 roy Exp $");
__RCSID("$NetBSD: dhcp.c,v 1.14 2014/07/14 11:49:48 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -128,16 +128,24 @@ static const size_t udp_dhcp_len = sizeof(struct udp_dhcp_packet);
static int dhcp_open(struct interface *);
void
dhcp_printoptions(const struct dhcpcd_ctx *ctx)
dhcp_printoptions(const struct dhcpcd_ctx *ctx,
const struct dhcp_opt *opts, size_t opts_len)
{
const char * const *p;
size_t i;
const struct dhcp_opt *opt;
size_t i, j;
const struct dhcp_opt *opt, *opt2;
for (p = dhcp_params; *p; p++)
printf(" %s\n", *p);
for (i = 0, opt = ctx->dhcp_opts; i < ctx->dhcp_opts_len; i++, opt++)
for (i = 0, opt = ctx->dhcp_opts; i < ctx->dhcp_opts_len; i++, opt++) {
for (j = 0, opt2 = opts; j < opts_len; j++, opt2++)
if (opt->option == opt2->option)
break;
if (j == opts_len)
printf("%03d %s\n", opt->option, opt->var);
}
for (i = 0, opt = opts; i < opts_len; i++, opt++)
printf("%03d %s\n", opt->option, opt->var);
}
@ -289,7 +297,7 @@ decode_rfc3442(char *out, size_t len, const uint8_t *p, size_t pl)
errno = EINVAL;
return -1;
}
ocets = (cidr + 7) / 8;
ocets = (cidr + 7) / NBBY;
if (!out) {
p += 4 + ocets;
bytes += ((4 * 4) * 2) + 4;
@ -360,7 +368,7 @@ decode_rfc3442_rt(const uint8_t *data, size_t dl)
}
TAILQ_INSERT_TAIL(routes, rt, next);
ocets = (cidr + 7) / 8;
ocets = (cidr + 7) / NBBY;
/* If we have ocets then we have a destination and netmask */
if (ocets > 0) {
memcpy(&rt->dest.s_addr, p, ocets);
@ -946,6 +954,30 @@ make_message(struct dhcp_message **message,
goto toobig;
*p++ = (uint8_t)opt->option;
}
for (i = 0, opt = ifo->dhcp_override;
i < ifo->dhcp_override_len;
i++, opt++)
{
/* Check if added above */
for (lp = n_params + 1; lp < p; lp++)
if (*lp == (uint8_t)opt->option)
break;
if (lp < p)
continue;
if (!(opt->type & REQUEST ||
has_option_mask(ifo->requestmask, opt->option)))
continue;
if (opt->type & NOREQ)
continue;
if (type == DHCP_INFORM &&
(opt->option == DHO_RENEWALTIME ||
opt->option == DHO_REBINDTIME))
continue;
len = (size_t)((p - m) + 2);
if (len > sizeof(*dhcp))
goto toobig;
*p++ = (uint8_t)opt->option;
}
*n_params = (uint8_t)(p - n_params - 1);
}
@ -2736,40 +2768,23 @@ dhcp_open(struct interface *ifp)
}
int
dhcp_dump(struct dhcpcd_ctx *ctx, const char *ifname)
dhcp_dump(struct interface *ifp)
{
struct interface *ifp;
struct dhcp_state *state;
if (ctx->ifaces == NULL) {
ctx->ifaces = malloc(sizeof(*ctx->ifaces));
if (ctx->ifaces == NULL)
return -1;
TAILQ_INIT(ctx->ifaces);
}
state = NULL;
ifp = calloc(1, sizeof(*ifp));
if (ifp == NULL)
goto eexit;
ifp->ctx = ctx;
TAILQ_INSERT_HEAD(ctx->ifaces, ifp, next);
ifp->if_data[IF_DATA_DHCP] = state = calloc(1, sizeof(*state));
if (state == NULL)
goto eexit;
ifp->options = calloc(1, sizeof(*ifp->options));
if (ifp->options == NULL)
goto eexit;
strlcpy(ifp->name, ifname, sizeof(ifp->name));
snprintf(state->leasefile, sizeof(state->leasefile),
LEASEFILE, ifp->name);
state->new = read_lease(ifp);
if (state->new == NULL && errno == ENOENT) {
strlcpy(state->leasefile, ifname, sizeof(state->leasefile));
strlcpy(state->leasefile, ifp->name, sizeof(state->leasefile));
state->new = read_lease(ifp);
}
if (state->new == NULL) {
if (errno == ENOENT)
syslog(LOG_ERR, "%s: no lease to dump", ifname);
syslog(LOG_ERR, "%s: no lease to dump", ifp->name);
return -1;
}
state->reason = "DUMP";
@ -3018,13 +3033,22 @@ dhcp_start(struct interface *ifp)
if (!(ifp->options->options & DHCPCD_IPV4))
return;
tv.tv_sec = DHCP_MIN_DELAY;
tv.tv_usec = (suseconds_t)arc4random_uniform(
(DHCP_MAX_DELAY - DHCP_MIN_DELAY) * 1000000);
timernorm(&tv);
syslog(LOG_DEBUG,
"%s: delaying DHCP for %0.1f seconds",
ifp->name, timeval_to_double(&tv));
/* No point in delaying a static configuration */
if (ifp->options->options & DHCPCD_STATIC &&
!(ifp->options->options & DHCPCD_INFORM))
{
tv.tv_sec = 0;
tv.tv_usec = 0;
} else {
tv.tv_sec = DHCP_MIN_DELAY;
tv.tv_usec = (suseconds_t)arc4random_uniform(
(DHCP_MAX_DELAY - DHCP_MIN_DELAY) * 1000000);
timernorm(&tv);
syslog(LOG_DEBUG,
"%s: delaying DHCP for %0.1f seconds",
ifp->name, timeval_to_double(&tv));
}
eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcp_start1, ifp);
}

View File

@ -1,4 +1,4 @@
.\" $NetBSD: dhcpcd.8.in,v 1.28 2014/06/14 20:55:37 roy Exp $
.\" $NetBSD: dhcpcd.8.in,v 1.29 2014/07/14 11:49:48 roy Exp $
.\" Copyright (c) 2006-2014 Roy Marples
.\" All rights reserved
.\"
@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd June 2, 2014
.Dd July 7, 2014
.Dt DHCPCD 8
.Os
.Sh NAME
@ -76,7 +76,7 @@
.Sh DESCRIPTION
.Nm
is an implementation of the DHCP client specified in
.%R RFC 2131 .
.Li RFC 2131 .
.Nm
gets the host information
.Po
@ -104,17 +104,17 @@ to renew early.
.Pp
.Nm
is also an implementation of the BOOTP client specified in
.%R RFC 951 .
.Li RFC 951 .
.Pp
.Nm
is also an implementation of the IPv6 Router Solicitor as specified in
.%R RFC 4861
.Li RFC 4861
and
.%R RFC 6106 .
.Li RFC 6106 .
.Pp
.Nm
is also an implemenation of the DHCPv6 client as specified in
.%R RFC 3315 .
.Li RFC 3315 .
By default,
.Nm
only starts DHCPv6 when instructed to do so by an IPV6 Router Advertisement.
@ -212,7 +212,7 @@ instead of the default
.Pa @SCRIPT@ .
.It Fl D , Fl Fl duid
Generate an
.%R RFC 4361
.Li RFC 4361
compliant clientid.
This requires persistent storage and not all DHCP servers work with it so it
is not enabled by default.
@ -260,7 +260,7 @@ are disable, none, ptr and both.
itself never does any DNS updates.
.Nm
encodes the FQDN hostname as specified in
.%R RFC1035 .
.Li RFC1035 .
.It Fl f , Fl Fl config Ar file
Specify a config to load instead of
.Pa @SYSCONFDIR@/dhcpcd.conf .
@ -553,6 +553,14 @@ Dumps the last lease for the
to stdout.
.Ar interface
could also be a path to a DHCP wire formatted file.
Use the
.Fl 4
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 and the associated variable for use in
.Xr dhcpcd-run-hooks 8 .
@ -672,7 +680,8 @@ RFC\ 951, RFC\ 1534, RFC\ 2104, RFC\ 2131, RFC\ 2132, RFC\ 2563, RFC\ 2855,
RFC\ 3004, RFC\ 3118, RFC\ 3203, RFC\ 3315, RFC\ 3361, RFC\ 3633, RFC\ 3396,
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\ 5227, RFC\ 5942, RFC\ 5969, RFC\ 6106, RFC\ 6334, RFC\ 6704, RFC\ 7217.
RFC\ 5227, RFC\ 5942, RFC\ 5969, RFC\ 6106, RFC\ 6334, RFC\ 6603, RFC\ 6704,
RFC\ 7217.
.Sh AUTHORS
.An Roy Marples Aq Mt roy@marples.name
.Sh BUGS

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: dhcpcd.c,v 1.5 2014/06/14 20:55:37 roy Exp $");
__RCSID("$NetBSD: dhcpcd.c,v 1.6 2014/07/14 11:49:48 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -142,14 +142,14 @@ free_globals(struct dhcpcd_ctx *ctx)
struct dhcp_opt *opt;
if (ctx->ifac) {
for (ctx->ifac--; ctx->ifac >= 0; ctx->ifac--)
free(ctx->ifav[ctx->ifac]);
for (; ctx->ifac > 0; ctx->ifac--)
free(ctx->ifav[ctx->ifac - 1]);
free(ctx->ifav);
ctx->ifav = NULL;
}
if (ctx->ifdc) {
for (ctx->ifdc--; ctx->ifdc >= 0; ctx->ifdc--)
free(ctx->ifdv[ctx->ifdc]);
for (; ctx->ifdc > 0; ctx->ifdc--)
free(ctx->ifdv[ctx->ifdc - 1]);
free(ctx->ifdv);
ctx->ifdv = NULL;
}
@ -326,6 +326,9 @@ configure_interface1(struct interface *ifp)
{
struct if_options *ifo = ifp->options;
int ra_global, ra_iface;
#ifdef INET6
size_t i;
#endif
/* Do any platform specific configuration */
if_conf(ifp);
@ -342,7 +345,7 @@ configure_interface1(struct interface *ifp)
ifo->options &= ~(DHCPCD_ARP | DHCPCD_IPV4LL);
if (!(ifp->flags & (IFF_POINTOPOINT | IFF_LOOPBACK | IFF_MULTICAST)))
ifo->options &= ~DHCPCD_IPV6RS;
if (ifo->options & DHCPCD_LINK && if_carrier(ifp) == LINK_UNKNOWN)
if (ifo->options & DHCPCD_LINK && ifp->carrier == LINK_UNKNOWN)
ifo->options &= ~DHCPCD_LINK;
if (ifo->metric != -1)
@ -434,17 +437,27 @@ configure_interface1(struct interface *ifp)
}
#ifdef INET6
if (ifo->ia == NULL && ifo->options & DHCPCD_IPV6) {
ifo->ia = malloc(sizeof(*ifo->ia));
if (ifo->ia == NULL)
syslog(LOG_ERR, "%s: %m", __func__);
else {
if (ifo->ia_type == 0)
ifo->ia_type = D6_OPTION_IA_NA;
memcpy(ifo->ia->iaid, ifo->iaid, sizeof(ifo->iaid));
ifo->ia_len = 1;
ifo->ia->sla = NULL;
ifo->ia->sla_len = 0;
if (ifo->options & DHCPCD_IPV6) {
if (ifo->ia == NULL) {
ifo->ia = malloc(sizeof(*ifo->ia));
if (ifo->ia == NULL)
syslog(LOG_ERR, "%s: %m", __func__);
else {
ifo->ia_len = 1;
ifo->ia->ia_type = D6_OPTION_IA_NA;
memcpy(ifo->ia->iaid, ifo->iaid,
sizeof(ifo->iaid));
memset(&ifo->ia->addr, 0,
sizeof(ifo->ia->addr));
ifo->ia->sla = NULL;
ifo->ia->sla_len = 0;
}
} else {
for (i = 0; i < ifo->ia_len; i++) {
if (!ifo->ia[i].iaid_set)
memcpy(ifo->ia->iaid, ifo->iaid,
sizeof(ifo->iaid));
}
}
}
#endif
@ -496,10 +509,23 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
if (ifp == NULL || !(ifp->options->options & DHCPCD_LINK))
return;
if (carrier == LINK_UNKNOWN)
switch(carrier) {
case LINK_UNKNOWN:
carrier = if_carrier(ifp); /* will set ifp->flags */
else
break;
case LINK_UP:
/* we have a carrier! however, we need to ignore the flags
* set in the kernel message as sometimes this message is
* reported before IFF_UP is set by the kernel even though
* dhcpcd has already set it.
*
* So we check the flags now. If IFF_UP is still not set
* then we should expect an accompanying link_down message */
if_setflag(ifp, 0); /* will set ifp->flags */
break;
default:
ifp->flags = flags;
}
if (carrier == LINK_UNKNOWN)
syslog(LOG_ERR, "%s: carrier_status: %m", ifname);
@ -547,6 +573,8 @@ warn_iaid_conflict(struct interface *ifp, uint8_t *iaid)
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;
@ -558,12 +586,26 @@ warn_iaid_conflict(struct interface *ifp, uint8_t *iaid)
}
/* This is only a problem if the interfaces are on the same network. */
if (ifn)
if (ifn && strcmp(ifp->name, ifn->name))
syslog(LOG_ERR,
"%s: IAID conflicts with one assigned to %s",
ifp->name, ifn->name);
}
static void
pre_start(struct interface *ifp)
{
/* Add our link-local address before upping the interface
* so our RFC7217 address beats the hwaddr based one.
* This is also a safety check incase it was ripped out
* from under us. */
if (ifp->options->options & DHCPCD_IPV6 && ipv6_start(ifp) == -1) {
syslog(LOG_ERR, "%s: ipv6_start: %m", ifp->name);
ifp->options->options &= DHCPCD_IPV6;
}
}
void
dhcpcd_startinterface(void *arg)
{
@ -572,24 +614,11 @@ dhcpcd_startinterface(void *arg)
size_t i;
char buf[DUID_LEN * 3];
/* Add our link-local address before upping the interface
* so our RFC7217 address beats the hwaddr based one.
* This is also a safety check incase it was ripped out
* from under us. */
if (ifo->options & DHCPCD_IPV6 && ipv6_start(ifp) == -1) {
syslog(LOG_ERR, "%s: ipv6_start: %m", ifp->name);
ifo->options &= DHCPCD_IPV6;
}
pre_start(ifp);
if (if_up(ifp) == -1)
syslog(LOG_ERR, "%s: if_up: %m", ifp->name);
if (!(ifp->flags & IFF_UP) && if_carrier(ifp) != LINK_UNKNOWN) {
if (if_up(ifp) == -1)
syslog(LOG_ERR, "%s: if_up: %m",
ifp->name);
}
if (ifp->carrier == LINK_UNKNOWN)
dhcpcd_handlecarrier(ifp->ctx, LINK_UNKNOWN, 0, ifp->name);
if (ifp->carrier == LINK_DOWN) {
if (ifp->carrier == LINK_DOWN && ifo->options & DHCPCD_LINK) {
syslog(LOG_INFO, "%s: waiting for carrier", ifp->name);
return;
}
@ -599,11 +628,17 @@ dhcpcd_startinterface(void *arg)
if (ifp->ctx->duid == NULL) {
if (duid_init(ifp) == 0)
return;
syslog(LOG_INFO, "DUID %s",
hwaddr_ntoa(ifp->ctx->duid, ifp->ctx->duid_len,
buf, sizeof(buf)));
if (!(ifo->options & DHCPCD_PFXDLGONLY))
syslog(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))
{
/* Report IAIDs */
syslog(LOG_INFO, "%s: IAID %s", ifp->name,
hwaddr_ntoa(ifo->iaid, sizeof(ifo->iaid),
@ -624,10 +659,12 @@ dhcpcd_startinterface(void *arg)
if (ifo->options & DHCPCD_IPV6) {
if (ifo->options & DHCPCD_IPV6RS &&
!(ifo->options & DHCPCD_INFORM))
!(ifo->options & (DHCPCD_INFORM | DHCPCD_PFXDLGONLY)))
ipv6nd_startrs(ifp);
if (!(ifo->options & DHCPCD_IPV6RS)) {
if (!(ifo->options & DHCPCD_IPV6RS) ||
ifo->options & DHCPCD_IA_FORCED)
{
ssize_t nolease;
if (ifo->options & DHCPCD_IA_FORCED)
@ -654,6 +691,8 @@ dhcpcd_startinterface(void *arg)
"%s: dhcp6_start: %m", ifp->name);
}
}
if (ifo->options & DHCPCD_PFXDLGONLY)
return;
if (ifo->options & DHCPCD_IPV4)
dhcp_start(ifp);
@ -674,7 +713,7 @@ handle_link(void *arg)
}
static void
init_state(struct interface *ifp, int argc, char **argv)
dhcpcd_initstate1(struct interface *ifp, int argc, char **argv)
{
struct if_options *ifo;
@ -700,34 +739,27 @@ init_state(struct interface *ifp, int argc, char **argv)
}
}
void
dhcpcd_initstate(struct interface *ifp)
{
dhcpcd_initstate1(ifp, ifp->ctx->argc, ifp->ctx->argv);
}
static void
run_preinit(struct interface *ifp)
{
const char *reason;
reason = NULL; /* appease gcc */
if (ifp->options->options & DHCPCD_LINK) {
switch (if_carrier(ifp)) {
case LINK_DOWN:
ifp->carrier = LINK_DOWN;
reason = "NOCARRIER";
break;
case LINK_UP:
ifp->carrier = LINK_UP;
reason = "CARRIER";
break;
default:
ifp->carrier = LINK_UNKNOWN;
return;
}
} else
ifp->carrier = LINK_UNKNOWN;
pre_start(ifp);
if (ifp->ctx->options & DHCPCD_TEST)
return;
if (!(ifp->ctx->options & DHCPCD_TEST))
script_runreason(ifp, "PREINIT");
script_runreason(ifp, "PREINIT");
if (ifp->carrier != LINK_UNKNOWN && !(ifp->ctx->options & DHCPCD_TEST))
script_runreason(ifp, reason);
if (ifp->carrier != LINK_UNKNOWN &&
ifp->options->options & DHCPCD_LINK)
script_runreason(ifp,
ifp->carrier == LINK_UP ? "CARRIER" : "NOCARRIER");
}
int
@ -735,7 +767,7 @@ dhcpcd_handleinterface(void *arg, int action, const char *ifname)
{
struct dhcpcd_ctx *ctx;
struct if_head *ifs;
struct interface *ifp, *ifn, *ifl = NULL;
struct interface *ifp, *iff, *ifn;
const char * const argv[] = { ifname };
int i;
@ -746,6 +778,7 @@ dhcpcd_handleinterface(void *arg, int action, const char *ifname)
errno = ESRCH;
return -1;
}
syslog(LOG_DEBUG, "%s: interface departed", ifp->name);
ifp->options->options |= DHCPCD_DEPARTED;
stop_interface(ifp);
return 0;
@ -767,22 +800,24 @@ dhcpcd_handleinterface(void *arg, int action, const char *ifname)
continue;
i = 0;
/* Check if we already have the interface */
ifl = if_find(ctx, ifp->name);
if (ifl) {
iff = if_find(ctx, ifp->name);
if (iff) {
syslog(LOG_DEBUG, "%s: interface updated", iff->name);
/* The flags and hwaddr could have changed */
ifl->flags = ifp->flags;
ifl->hwlen = ifp->hwlen;
iff->flags = ifp->flags;
iff->hwlen = ifp->hwlen;
if (ifp->hwlen != 0)
memcpy(ifl->hwaddr, ifp->hwaddr, ifl->hwlen);
memcpy(iff->hwaddr, ifp->hwaddr, iff->hwlen);
} else {
syslog(LOG_DEBUG, "%s: interface added", ifp->name);
TAILQ_REMOVE(ifs, ifp, next);
TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
}
if (action > 0) {
init_state(ifp, ctx->argc, ctx->argv);
dhcpcd_initstate(ifp);
run_preinit(ifp);
dhcpcd_startinterface(ifp);
iff = ifp;
}
if (action > 0)
dhcpcd_startinterface(iff);
}
/* Free our discovered list */
@ -857,7 +892,7 @@ reconf_reboot(struct dhcpcd_ctx *ctx, int action, int argc, char **argv, int oi)
if_free(ifp);
} else {
TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
init_state(ifp, argc, argv);
dhcpcd_initstate1(ifp, argc, argv);
run_preinit(ifp);
dhcpcd_startinterface(ifp);
}
@ -870,7 +905,7 @@ reconf_reboot(struct dhcpcd_ctx *ctx, int action, int argc, char **argv, int oi)
static void
stop_all_interfaces(struct dhcpcd_ctx *ctx, int do_release)
{
struct interface *ifp;
struct interface *ifp, *ifpm;
/* drop_dhcp could change the order, so we do it like this. */
for (;;) {
@ -878,6 +913,10 @@ stop_all_interfaces(struct dhcpcd_ctx *ctx, int do_release)
ifp = TAILQ_LAST(ctx->ifaces, if_head);
if (ifp == NULL)
break;
/* Stop the master interface only */
ifpm = if_find(ifp->ctx, ifp->name);
if (ifpm)
ifp = ifpm;
if (do_release) {
ifp->options->options |= DHCPCD_RELEASE;
ifp->options->options &= ~DHCPCD_PERSISTENT;
@ -1250,10 +1289,13 @@ main(int argc, char **argv)
i = 1;
break;
case 'U':
i = 2;
if (i == 3)
i = 4;
else if (i != 4)
i = 3;
break;
case 'V':
i = 3;
i = 2;
break;
case '?':
usage();
@ -1267,25 +1309,36 @@ main(int argc, char **argv)
ctx.ifv = argv + optind;
ifo = read_config(&ctx, NULL, NULL, NULL);
if (ifo == NULL)
goto exit_failure;
opt = add_options(&ctx, NULL, ifo, argc, argv);
if (opt != 1) {
if (opt == 0)
usage();
goto exit_failure;
}
if (i == 3) {
if (i == 2) {
printf("Interface options:\n");
if (optind == argc - 1) {
free_options(ifo);
ifo = read_config(&ctx, argv[optind], NULL, NULL);
if (ifo == NULL)
goto exit_failure;
add_options(&ctx, NULL, ifo, argc, argv);
}
if_printoptions();
#ifdef INET
if (family == 0 || family == AF_INET) {
printf("\nDHCPv4 options:\n");
dhcp_printoptions(&ctx);
dhcp_printoptions(&ctx,
ifo->dhcp_override, ifo->dhcp_override_len);
}
#endif
#ifdef INET6
if (family == 0 || family == AF_INET6) {
printf("\nDHCPv6 options:\n");
dhcp6_printoptions(&ctx);
dhcp6_printoptions(&ctx,
ifo->dhcp6_override, ifo->dhcp6_override_len);
}
#endif
goto exit_success;
@ -1296,6 +1349,8 @@ main(int argc, char **argv)
ctx.options |= DHCPCD_TEST;
else
ctx.options |= DHCPCD_DUMPLEASE;
if (i == 4)
ctx.options |= DHCPCD_PFXDLGONLY;
ctx.options |= DHCPCD_PERSISTENT;
ctx.options &= ~DHCPCD_DAEMONISE;
}
@ -1344,8 +1399,7 @@ main(int argc, char **argv)
}
snprintf(pidfile, sizeof(pidfile),
PIDFILE, "-", argv[optind], per);
}
else {
} else {
snprintf(pidfile, sizeof(pidfile), PIDFILE, "", "", "");
ctx.options |= DHCPCD_MASTER;
}
@ -1354,12 +1408,48 @@ main(int argc, char **argv)
if (chdir("/") == -1)
syslog(LOG_ERR, "chdir `/': %m");
/* Freeing allocated addresses from dumping leases can trigger
* eloop removals as well, so init here. */
ctx.eloop = eloop_init();
if (ctx.eloop == NULL) {
syslog(LOG_ERR, "%s: %m", __func__);
goto exit_failure;
}
if (ctx.options & DHCPCD_DUMPLEASE) {
if (optind != argc - 1) {
syslog(LOG_ERR, "dumplease requires an interface");
goto exit_failure;
}
if (dhcp_dump(&ctx, argv[optind]) == -1)
i = 0;
/* We need to try and find the interface so we can
* load the hardware address to compare automated IAID */
ctx.ifaces = if_discover(&ctx, 1, argv + optind);
if (ctx.ifaces == NULL)
goto exit_failure;
ifp = TAILQ_FIRST(ctx.ifaces);
if (ifp == NULL) {
ifp = calloc(1, sizeof(*ifp));
if (ifp == NULL) {
syslog(LOG_ERR, "%s: %m", __func__);
goto exit_failure;
}
strlcpy(ifp->name, argv[optind], sizeof(ifp->name));
ifp->ctx = &ctx;
TAILQ_INSERT_HEAD(ctx.ifaces, ifp, next);
}
configure_interface(ifp, ctx.argc, ctx.argv);
if (ctx.options & DHCPCD_PFXDLGONLY)
ifp->options->options |= DHCPCD_PFXDLGONLY;
if (family == 0 || family == AF_INET) {
if (dhcp_dump(ifp) == -1)
i = 1;
}
if (family == 0 || family == AF_INET6) {
if (dhcp6_dump(ifp) == -1)
i = 1;
}
if (i == -1)
goto exit_failure;
goto exit_success;
}
@ -1399,12 +1489,6 @@ main(int argc, char **argv)
syslog(LOG_WARNING,
PACKAGE " will not work correctly unless run as root");
ctx.eloop = eloop_init();
if (ctx.eloop == NULL) {
syslog(LOG_ERR, "%s: %m", __func__);
goto exit_failure;
}
#ifdef USE_SIGNALS
if (sig != 0) {
pid = read_pid(pidfile);
@ -1556,7 +1640,7 @@ main(int argc, char **argv)
}
TAILQ_FOREACH(ifp, ctx.ifaces, next) {
init_state(ifp, argc, argv);
dhcpcd_initstate1(ifp, argc, argv);
}
if (ctx.options & DHCPCD_BACKGROUND && dhcpcd_daemonise(&ctx))
@ -1625,7 +1709,6 @@ exit1:
free_options(ifo);
free_globals(&ctx);
if_rarestore(&ctx);
ipv4_ctxfree(&ctx);
ipv6_ctxfree(&ctx);
dev_stop(&ctx, !(ctx.options & DHCPCD_FORKED));

View File

@ -1,4 +1,4 @@
.\" $NetBSD: dhcpcd.conf.5.in,v 1.8 2014/06/14 20:55:37 roy Exp $
.\" $NetBSD: dhcpcd.conf.5.in,v 1.9 2014/07/14 11:49:48 roy Exp $
.\" Copyright (c) 2006-2014 Roy Marples
.\" All rights reserved
.\"
@ -23,7 +23,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd June 6, 2014
.Dd July 7, 2014
.Dt DHCPCD.CONF 5
.Os
.Sh NAME
@ -215,7 +215,7 @@ DNS if the domain part does not match theirs.
Also, see the
.Ic env
option above to control how the hostname is set on the host.
.It Ic ia_na Op Ar iaid
.It Ic ia_na Op Ar iaid Op / address
Request a DHCPv6 Normal Address for
.Ar iaid .
.Ar iaid
@ -231,7 +231,7 @@ Request a DHCPv6 Temporary Address for
You can request more than one ia_ta by specifying a unique
.Ar iaid
for each one.
.It Ic ia_pd Op Ar iaid Op Ar interface Op / Ar sla_id Op / Ar prefix_len
.It Ic ia_pd Op Ar iaid Oo / Ar prefix / Ar prefix_len Oc Op Ar interface Op / Ar sla_id Op / Ar prefix_len
Request a DHCPv6 Delegated Prefix for
.Ar iaid .
This option must be used in an
@ -251,7 +251,10 @@ Otherwise addresses are only assigned for each
and
.Ar sla_id .
Each assigned address will have a suffix of 1.
You cannot assign a prefix to the requesting interface.
You cannot assign a prefix to the requesting interface unless the
DHCPv6 server supports
.Li RFC6603
Prefix Exclude Option.
.Nm dhcpcd
has to be running for all the interfaces it is delegating to.
A default
@ -291,6 +294,18 @@ IPv6RS should be disabled globally when requesting a Prefix Delegation like so:
.D1 interface eth1
.D1 ipv4
.D1 ipv6rs
.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
@ -458,6 +473,9 @@ Subsequent options are only parsed for this wireless
.Ar ssid .
.It Ic slaac Op Ar hwaddr | Ar private
Selects the interface identifier used for SLAAC generated IPv6 addresses.
If
.Ar private
is used, a RFC7217 address is generated.
.It Ic static Ar value
Configures a static
.Ar value .
@ -740,11 +758,5 @@ Same as
.Sh AUTHORS
.An Roy Marples Aq Mt roy@marples.name
.Sh BUGS
When configuring DHCPv6 you can only select one IA type.
I can't think of a use case where you would want different types,
so if you have one then please bring it up for discussion on the
.Aq Mt dhcpcd-discuss@marples.name
mailing list.
.Pp
Please report them to
.Lk http://roy.marples.name/projects/dhcpcd

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: if-bsd.c,v 1.6 2014/06/14 20:55:37 roy Exp $");
__RCSID("$NetBSD: if-bsd.c,v 1.7 2014/07/14 11:49:48 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -891,9 +891,7 @@ if_managelink(struct dhcpcd_ctx *ctx)
case AF_INET6:
sin6 = (struct sockaddr_in6*)(void *)
rti_info[RTAX_IFA];
memcpy(ia6.s6_addr,
sin6->sin6_addr.s6_addr,
sizeof(ia6.s6_addr));
ia6 = sin6->sin6_addr;
if (rtm->rtm_type == RTM_NEWADDR) {
ifa_flags = if_addrflags6(ifname, &ia6);
if (ifa_flags == -1)
@ -1022,45 +1020,6 @@ if_nd6reachable(const char *ifname, struct in6_addr *addr)
return flags;
}
void
if_rarestore(struct dhcpcd_ctx *ctx)
{
if (ctx->options & DHCPCD_FORKED)
return;
for (; ctx->ra_restore_len > 0; ctx->ra_restore_len--) {
#ifdef ND6_IFF_ACCEPT_RTADV
if (!(ctx->options & DHCPCD_FORKED)) {
syslog(LOG_DEBUG,
"%s: restoring kernel IPv6 RA support",
ctx->ra_restore[ctx->ra_restore_len - 1]);
if (set_if_nd6_flag(
ctx->ra_restore[ctx->ra_restore_len -1],
ND6_IFF_ACCEPT_RTADV) == -1)
syslog(LOG_ERR, "%s: set_if_nd6_flag: %m",
ctx->ra_restore[ctx->ra_restore_len - 1]);
#ifdef ND6_IFF_OVERRIDE_RTADV
if (ctx->ra_kernel_set == 0 && del_if_nd6_flag(
ctx->ra_restore[ctx->ra_restore_len -1],
ND6_IFF_OVERRIDE_RTADV) == -1)
syslog(LOG_ERR, "%s: del_if_nd6_flag: %m",
ctx->ra_restore[ctx->ra_restore_len - 1]);
#endif
}
#endif
free(ctx->ra_restore[ctx->ra_restore_len - 1]);
}
free(ctx->ra_restore);
ctx->ra_restore = NULL;
if (ctx->ra_kernel_set) {
syslog(LOG_DEBUG, "restoring kernel IPv6 RA support");
if (set_inet6_sysctl(IPV6CTL_ACCEPT_RTADV, 1) == -1)
syslog(LOG_ERR, "IPV6CTL_ACCEPT_RTADV: %m");
}
}
static int
if_raflush(void)
{
@ -1088,10 +1047,6 @@ if_checkipv6(struct dhcpcd_ctx *ctx, const char *ifname, int own)
#ifdef ND6_IFF_OVERRIDE_RTADV
int override;
#endif
#ifdef ND6_IFF_ACCEPT_RTADV
size_t i;
char *p, **nrest;
#endif
#ifdef ND6_IFF_IFDISABLED
if (del_if_nd6_flag(ifname, ND6_IFF_IFDISABLED) == -1) {
@ -1169,7 +1124,7 @@ if_checkipv6(struct dhcpcd_ctx *ctx, const char *ifname, int own)
return ra;
}
#ifdef ND6_IFF_OVERRIDE_RTADV
if (override == 0 && ctx->ra_kernel_set == 0 &&
if (override == 0 &&
set_if_nd6_flag(ifname, ND6_IFF_OVERRIDE_RTADV)
== -1)
{
@ -1180,25 +1135,6 @@ if_checkipv6(struct dhcpcd_ctx *ctx, const char *ifname, int own)
return ra;
}
#endif
for (i = 0; i < ctx->ra_restore_len; i++)
if (strcmp(ctx->ra_restore[i], ifname) == 0)
break;
if (i == ctx->ra_restore_len) {
p = strdup(ifname);
if (p == NULL) {
syslog(LOG_ERR, "%s: %m", __func__);
return 0;
}
nrest = realloc(ctx->ra_restore,
(ctx->ra_restore_len + 1) * sizeof(char *));
if (nrest == NULL) {
syslog(LOG_ERR, "%s: %m", __func__);
free(p);
return 0;
}
ctx->ra_restore = nrest;
ctx->ra_restore[ctx->ra_restore_len++] = p;
}
return 0;
}
return ra;
@ -1220,7 +1156,6 @@ if_checkipv6(struct dhcpcd_ctx *ctx, const char *ifname, int own)
return ra;
}
ra = 0;
ctx->ra_kernel_set = 1;
/* Flush the kernel knowledge of advertised routers
* and prefixes so the kernel does not expire prefixes

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: if-options.c,v 1.9 2014/06/14 20:55:37 roy Exp $");
__RCSID("$NetBSD: if-options.c,v 1.10 2014/07/14 11:49:48 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -96,6 +96,7 @@
#define O_CONTROLGRP O_BASE + 34
#define O_SLAAC O_BASE + 35
#define O_GATEWAY O_BASE + 36
#define O_PFXDLGMIX O_BASE + 37
const struct option cf_options[] = {
{"background", no_argument, NULL, 'b'},
@ -182,6 +183,7 @@ const struct option cf_options[] = {
{"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},
{NULL, 0, NULL, '\0'}
};
@ -521,7 +523,9 @@ parse_addr(__unused struct in_addr *addr, __unused struct in_addr *net,
static const char *
set_option_space(struct dhcpcd_ctx *ctx,
const char *arg, const struct dhcp_opt **d, size_t *dl,
const char *arg,
const struct dhcp_opt **d, size_t *dl,
const struct dhcp_opt **od, size_t *odl,
struct if_options *ifo,
uint8_t *request[], uint8_t *require[], uint8_t *no[])
{
@ -530,6 +534,8 @@ set_option_space(struct dhcpcd_ctx *ctx,
if (strncmp(arg, "dhcp6_", strlen("dhcp6_")) == 0) {
*d = ctx->dhcp6_opts;
*dl = ctx->dhcp6_opts_len;
*od = ifo->dhcp6_override;
*odl = ifo->dhcp6_override_len;
*request = ifo->requestmask6;
*require = ifo->requiremask6;
*no = ifo->nomask6;
@ -540,9 +546,13 @@ set_option_space(struct dhcpcd_ctx *ctx,
#ifdef INET
*d = ctx->dhcp_opts;
*dl = ctx->dhcp_opts_len;
*od = ifo->dhcp_override;
*odl = ifo->dhcp_override_len;
#else
*d = NULL;
*dl = 0;
*od = NULL;
*odl = 0;
#endif
*request = ifo->requestmask;
*require = ifo->requiremask;
@ -633,15 +643,14 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
struct in_addr addr, addr2;
in_addr_t *naddr;
struct rt *rt;
const struct dhcp_opt *d;
const struct dhcp_opt *d, *od;
uint8_t *request, *require, *no;
struct dhcp_opt **dop, *ndop;
size_t *dop_len, dl;
size_t *dop_len, dl, odl;
struct vivco *vivco;
struct token *token;
struct group *grp;
#ifdef _REENTRANT
#error foo
struct group grpbuf;
#endif
#ifdef INET6
@ -736,10 +745,10 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
}
break;
case 'o':
arg = set_option_space(ctx, arg, &d, &dl, ifo,
arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
&request, &require, &no);
if (make_option_mask(d, dl, request, arg, 1) != 0 ||
make_option_mask(d, dl, no, arg, -1) != 0)
if (make_option_mask(d, dl, od, odl, request, arg, 1) != 0 ||
make_option_mask(d, dl, od, odl, no, arg, -1) != 0)
{
syslog(LOG_ERR, "unknown option `%s'", arg);
return -1;
@ -955,22 +964,22 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
ifo->options |= DHCPCD_MASTER;
break;
case 'O':
arg = set_option_space(ctx, arg, &d, &dl, ifo,
arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
&request, &require, &no);
if (make_option_mask(d, dl, request, arg, -1) != 0 ||
make_option_mask(d, dl, require, arg, -1) != 0 ||
make_option_mask(d, dl, no, arg, 1) != 0)
if (make_option_mask(d, dl, od, odl, request, arg, -1) != 0 ||
make_option_mask(d, dl, od, odl, require, arg, -1) != 0 ||
make_option_mask(d, dl, od, odl, no, arg, 1) != 0)
{
syslog(LOG_ERR, "unknown option `%s'", arg);
return -1;
}
break;
case 'Q':
arg = set_option_space(ctx, arg, &d, &dl, ifo,
arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
&request, &require, &no);
if (make_option_mask(d, dl, require, arg, 1) != 0 ||
make_option_mask(d, dl, request, arg, 1) != 0 ||
make_option_mask(d, dl, no, arg, -1) != 0)
if (make_option_mask(d, dl, od, odl, require, arg, 1) != 0 ||
make_option_mask(d, dl, od, odl, request, arg, 1) != 0 ||
make_option_mask(d, dl, od, odl, no, arg, -1) != 0)
{
syslog(LOG_ERR, "unknown option `%s'", arg);
return -1;
@ -1159,8 +1168,11 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
}
break;
case O_DESTINATION:
if (make_option_mask(ctx->dhcp_opts, ctx->dhcp_opts_len,
ifo->dstmask, arg, 2) != 0) {
arg = set_option_space(ctx, arg, &d, &dl, &od, &odl, ifo,
&request, &require, &no);
if (make_option_mask(d, dl, od, odl,
ifo->dstmask, arg, 2) != 0)
{
if (errno == EINVAL)
syslog(LOG_ERR, "option `%s' does not take"
" an IPv4 address", arg);
@ -1223,35 +1235,41 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
}
i = D6_OPTION_IA_PD;
}
if (arg != NULL && ifname == NULL) {
if (ifname == NULL && arg) {
syslog(LOG_ERR,
"IA with IAID must belong in an interface block");
return -1;
}
ifo->options |= DHCPCD_IA_FORCED;
if (ifo->ia_type != 0 && ifo->ia_type != i) {
syslog(LOG_ERR, "cannot specify a different IA type");
return -1;
}
ifo->ia_type = (uint16_t)i;
if (arg == NULL)
break;
fp = strwhite(arg);
if (fp)
if (fp) {
*fp++ = '\0';
if (parse_iaid(iaid, arg, sizeof(iaid)) == -1)
return -1;
fp = strskipwhite(fp);
}
if (arg) {
p = strchr(arg, '/');
if (p)
*p++ = '\0';
if (parse_iaid(iaid, arg, sizeof(iaid)) == -1)
return -1;
}
ia = NULL;
for (sl = 0; sl < ifo->ia_len; sl++) {
if (ifo->ia[sl].iaid[0] == iaid[0] &&
if ((arg == NULL && !ifo->ia[sl].iaid_set) ||
(ifo->ia[sl].iaid_set &&
ifo->ia[sl].iaid[0] == iaid[0] &&
ifo->ia[sl].iaid[1] == iaid[1] &&
ifo->ia[sl].iaid[2] == iaid[2] &&
ifo->ia[sl].iaid[3] == iaid[3])
ifo->ia[sl].iaid[3] == iaid[3]))
{
ia = &ifo->ia[sl];
break;
}
}
if (ia && ia->ia_type != (uint16_t)i) {
syslog(LOG_ERR, "Cannot mix IA for the same IAID");
break;
}
if (ia == NULL) {
ia = realloc(ifo->ia,
sizeof(*ifo->ia) * (ifo->ia_len + 1));
@ -1261,14 +1279,47 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
}
ifo->ia = ia;
ia = &ifo->ia[ifo->ia_len++];
ia->iaid[0] = iaid[0];
ia->iaid[1] = iaid[1];
ia->iaid[2] = iaid[2];
ia->iaid[3] = iaid[3];
ia->sla = NULL;
ia->ia_type = (uint16_t)i;
if (arg) {
ia->iaid[0] = iaid[0];
ia->iaid[1] = iaid[1];
ia->iaid[2] = iaid[2];
ia->iaid[3] = iaid[3];
ia->iaid_set = 1;
} else
ia->iaid_set = 0;
if (!ia->iaid_set ||
p == NULL ||
ia->ia_type == D6_OPTION_IA_TA)
{
memset(&ia->addr, 0, sizeof(ia->addr));
ia->prefix_len = 0;
} else {
arg = p;
p = strchr(arg, '/');
if (p)
*p++ = '\0';
if (inet_pton(AF_INET6, arg, &ia->addr) == -1) {
syslog(LOG_ERR, "%s: %m", arg);
memset(&ia->addr, 0, sizeof(ia->addr));
}
if (p && ia->ia_type == D6_OPTION_IA_PD) {
i = atoint(p);
if (i != -1 && (i < 8 || i > 120)) {
errno = EINVAL;
i = -1;
}
if (i == -1) {
syslog(LOG_ERR, "%s: %m", p);
ia->prefix_len = 0;
} else
ia->prefix_len = (uint8_t)i;
}
}
ia->sla_len = 0;
ia->sla = NULL;
}
if (ifo->ia_type != D6_OPTION_IA_PD)
if (ia->ia_type != D6_OPTION_IA_PD)
break;
for (p = fp; p; p = fp) {
fp = strwhite(p);
@ -1287,12 +1338,6 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
np = strchr(p, '/');
if (np)
*np++ = '\0';
if (strcmp(ifname, p) == 0) {
syslog(LOG_ERR,
"%s: cannot assign IA_PD to itself",
ifname);
goto err_sla;
}
if (strlcpy(sla->ifname, p,
sizeof(sla->ifname)) >= sizeof(sla->ifname))
{
@ -1856,6 +1901,9 @@ err_sla:
else
ifo->options &= ~DHCPCD_SLAACPRIVATE;
break;
case O_PFXDLGMIX:
ifo->options |= DHCPCD_PFXDLGMIX;
break;
default:
return 0;
}
@ -2127,6 +2175,10 @@ read_config(struct dhcpcd_ctx *ctx,
skip = 1;
continue;
}
/* Skip arping if we have selected a profile but not parsing
* one. */
if (profile && !have_profile && strcmp(option, "arping") == 0)
continue;
if (skip)
continue;
parse_config_line(ctx, ifname, ifo, option, line, &ldop, &edop);

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: ipv6nd.c,v 1.8 2014/06/14 20:55:37 roy Exp $");
__RCSID("$NetBSD: ipv6nd.c,v 1.9 2014/07/14 11:49:48 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -282,7 +282,7 @@ ipv6nd_sendrsprobe(void *arg)
dst.sin6_len = sizeof(dst);
#endif
dst.sin6_scope_id = ifp->index;
if (inet_pton(AF_INET6, ALLROUTERS, &dst.sin6_addr.s6_addr) != 1) {
if (inet_pton(AF_INET6, ALLROUTERS, &dst.sin6_addr) != 1) {
syslog(LOG_ERR, "%s: %m", __func__);
return;
}
@ -627,8 +627,7 @@ ipv6nd_dadcallback(void *arg)
ap->dadcounter = dadcounter;
ap->flags &= ~(IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED);
ap->flags |= IPV6_AF_NEW;
p = inet_ntop(AF_INET6, ap->addr.s6_addr,
buf, sizeof(buf));
p = inet_ntop(AF_INET6, &ap->addr, buf, sizeof(buf));
if (p)
snprintf(ap->saddr,
sizeof(ap->saddr),
@ -734,8 +733,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, struct interface *ifp,
TAILQ_FOREACH(rap, ctx->ra_routers, next) {
if (ifp == rap->iface &&
memcmp(rap->from.s6_addr, ctx->from.sin6_addr.s6_addr,
sizeof(rap->from.s6_addr)) == 0)
IN6_ARE_ADDR_EQUAL(&rap->from, &ctx->from.sin6_addr))
break;
}
@ -764,8 +762,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, struct interface *ifp,
return;
}
rap->iface = ifp;
memcpy(rap->from.s6_addr, ctx->from.sin6_addr.s6_addr,
sizeof(rap->from.s6_addr));
rap->from = ctx->from.sin6_addr;
strlcpy(rap->sfrom, ctx->sfrom, sizeof(rap->sfrom));
TAILQ_INIT(&rap->addrs);
TAILQ_INIT(&rap->options);
@ -852,9 +849,8 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, struct interface *ifp,
}
TAILQ_FOREACH(ap, &rap->addrs, next)
if (ap->prefix_len ==pi->nd_opt_pi_prefix_len &&
memcmp(ap->prefix.s6_addr,
pi->nd_opt_pi_prefix.s6_addr,
sizeof(ap->prefix.s6_addr)) == 0)
IN6_ARE_ADDR_EQUAL(&ap->prefix,
&pi->nd_opt_pi_prefix))
break;
if (ap == NULL) {
if (!(pi->nd_opt_pi_flags_reserved &
@ -868,9 +864,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, struct interface *ifp,
ap->iface = rap->iface;
ap->flags = IPV6_AF_NEW;
ap->prefix_len = pi->nd_opt_pi_prefix_len;
memcpy(ap->prefix.s6_addr,
pi->nd_opt_pi_prefix.s6_addr,
sizeof(ap->prefix.s6_addr));
ap->prefix = pi->nd_opt_pi_prefix;
if (pi->nd_opt_pi_flags_reserved &
ND_OPT_PI_FLAG_AUTO)
{
@ -884,7 +878,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, struct interface *ifp,
break;
}
cbp = inet_ntop(AF_INET6,
ap->addr.s6_addr,
&ap->addr,
buf, sizeof(buf));
if (cbp)
snprintf(ap->saddr,
@ -947,7 +941,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, struct interface *ifp,
op += sizeof(rdnss->nd_opt_rdnss_lifetime);
l = 0;
for (n = ndo->nd_opt_len - 1; n > 1; n -= 2,
op += sizeof(addr.s6_addr))
op += sizeof(addr))
{
r = ipv6_printaddr(NULL, 0, op, ifp->name);
if (r != -1)
@ -961,7 +955,7 @@ ipv6nd_handlera(struct ipv6_ctx *ctx, struct interface *ifp,
if (opt == NULL)
continue;
for (n = ndo->nd_opt_len - 1; n > 1; n -= 2,
op += sizeof(addr.s6_addr))
op += sizeof(addr))
{
r = ipv6_printaddr(tmp, l, op,
ifp->name);
@ -1401,8 +1395,7 @@ ipv6nd_handlena(struct ipv6_ctx *ctx, struct interface *ifp,
TAILQ_FOREACH(rap, ctx->ra_routers, next) {
if (rap->iface == ifp &&
memcmp(rap->from.s6_addr, nd_na->nd_na_target.s6_addr,
sizeof(rap->from.s6_addr)) == 0)
IN6_ARE_ADDR_EQUAL(&rap->from, &nd_na->nd_na_target))
break;
}
if (rap == NULL) {

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: script.c,v 1.6 2014/06/14 20:55:37 roy Exp $");
__RCSID("$NetBSD: script.c,v 1.7 2014/07/14 11:49:48 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -315,7 +315,8 @@ make_env(const struct interface *ifp, const char *reason, char ***argv)
snprintf(env[7], e, "ifmtu=%d", if_getmtu(ifp->name));
l = e = strlen("interface_order=");
TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
e += strlen(ifp2->name) + 1;
if (!(ifp2->options->options & DHCPCD_PFXDLGONLY))
e += strlen(ifp2->name) + 1;
}
EMALLOC(8, e);
p = env[8];
@ -323,11 +324,13 @@ make_env(const struct interface *ifp, const char *reason, char ***argv)
e -= l;
p += l;
TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
l = strlcpy(p, ifp2->name, e);
p += l;
e -= l;
*p++ = ' ';
e--;
if (!(ifp2->options->options & DHCPCD_PFXDLGONLY)) {
l = strlcpy(p, ifp2->name, e);
p += l;
e -= l;
*p++ = ' ';
e--;
}
}
*--p = '\0';
if (strcmp(reason, "TEST") == 0) {
@ -396,6 +399,16 @@ make_env(const struct interface *ifp, const char *reason, char ***argv)
}
#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);