This commit is contained in:
roy 2015-08-21 10:39:00 +00:00
parent 13da755153
commit d5314d23aa
26 changed files with 662 additions and 511 deletions

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: control.c,v 1.9 2015/05/16 23:31:32 roy Exp $");
__RCSID("$NetBSD: control.c,v 1.10 2015/08/21 10:39:00 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -46,6 +46,7 @@
#include "dhcpcd.h"
#include "control.h"
#include "eloop.h"
#include "if.h"
#ifndef SUN_LEN
#define SUN_LEN(su) \
@ -210,28 +211,8 @@ make_sock(struct sockaddr_un *sa, const char *ifname, int unpriv)
{
int fd;
#ifdef SOCK_CLOEXEC
if ((fd = socket(AF_UNIX,
SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) == -1)
if ((fd = xsocket(AF_UNIX, SOCK_STREAM, 0, O_NONBLOCK|O_CLOEXEC)) == -1)
return -1;
#else
int flags;
if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1)
return -1;
if ((flags = fcntl(fd, F_GETFD, 0)) == -1 ||
fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
{
close(fd);
return -1;
}
if ((flags = fcntl(fd, F_GETFL, 0)) == -1 ||
fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1)
{
close(fd);
return -1;
}
#endif
memset(sa, 0, sizeof(*sa));
sa->sun_family = AF_UNIX;
if (unpriv)

View File

@ -1,4 +1,4 @@
/* $NetBSD: defs.h,v 1.19 2015/07/09 10:15:34 roy Exp $ */
/* $NetBSD: defs.h,v 1.20 2015/08/21 10:39:00 roy Exp $ */
/*
* dhcpcd - DHCP client daemon
@ -30,7 +30,7 @@
#define CONFIG_H
#define PACKAGE "dhcpcd"
#define VERSION "6.9.1"
#define VERSION "6.9.2"
#ifndef CONFIG
# define CONFIG SYSCONFDIR "/" PACKAGE ".conf"

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: dhcp.c,v 1.32 2015/07/09 10:15:34 roy Exp $");
__RCSID("$NetBSD: dhcp.c,v 1.33 2015/08/21 10:39:00 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -278,6 +278,23 @@ get_option_uint32(struct dhcpcd_ctx *ctx,
return 0;
}
static int
get_option_uint16(struct dhcpcd_ctx *ctx,
uint16_t *i, const struct dhcp_message *dhcp, uint8_t option)
{
const uint8_t *p;
size_t len;
uint16_t d;
p = get_option(ctx, dhcp, option, &len);
if (!p || len < (ssize_t)sizeof(d))
return -1;
memcpy(&d, p, sizeof(d));
if (i)
*i = ntohs(d);
return 0;
}
static int
get_option_uint8(struct dhcpcd_ctx *ctx,
uint8_t *i, const struct dhcp_message *dhcp, uint8_t option)
@ -586,7 +603,7 @@ route_netmask(uint32_t ip_in)
/* We need to obey routing options.
* If we have a CSR then we only use that.
* Otherwise we add static routes and then routers. */
struct rt_head *
static struct rt_head *
get_option_routes(struct interface *ifp, const struct dhcp_message *dhcp)
{
struct if_options *ifo = ifp->options;
@ -692,6 +709,40 @@ get_option_routes(struct interface *ifp, const struct dhcp_message *dhcp)
return routes;
}
uint16_t
dhcp_get_mtu(const struct interface *ifp)
{
const struct dhcp_message *dhcp;
uint16_t mtu;
if ((dhcp = D_CSTATE(ifp)->new) == NULL ||
has_option_mask(ifp->options->nomask, DHO_MTU) ||
get_option_uint16(ifp->ctx, &mtu, dhcp, DHO_MTU) == -1)
return 0;
return mtu;
}
/* Grab our routers from the DHCP message and apply any MTU value
* the message contains */
struct rt_head *
dhcp_get_routes(struct interface *ifp)
{
struct rt_head *routes;
uint16_t mtu;
const struct dhcp_message *dhcp;
dhcp = D_CSTATE(ifp)->new;
routes = get_option_routes(ifp, dhcp);
if ((mtu = dhcp_get_mtu(ifp)) != 0) {
struct rt *rt;
TAILQ_FOREACH(rt, routes, next) {
rt->mtu = mtu;
}
}
return routes;
}
#define PUTADDR(_type, _val) \
{ \
*p++ = _type; \
@ -852,21 +903,27 @@ make_message(struct dhcp_message **message,
if (!(ifo->options & DHCPCD_BOOTP)) {
int mtu;
*p++ = DHO_MAXMESSAGESIZE;
*p++ = 2;
mtu = if_getmtu(ifp->name);
if (mtu < MTU_MIN) {
if (if_setmtu(ifp->name, MTU_MIN) == 0)
sz = MTU_MIN;
if ((mtu = if_getmtu(ifp)) == -1)
logger(ifp->ctx, LOG_ERR,
"%s: if_getmtu: %m", ifp->name);
else if (mtu < MTU_MIN) {
if (if_setmtu(ifp, MTU_MIN) == -1)
logger(ifp->ctx, LOG_ERR,
"%s: if_setmtu: %m", ifp->name);
mtu = MTU_MIN;
} else if (mtu > MTU_MAX) {
/* Even though our MTU could be greater than
* MTU_MAX (1500) dhcpcd does not presently
* handle DHCP packets any bigger. */
mtu = MTU_MAX;
}
sz = htons((uint16_t)mtu);
memcpy(p, &sz, 2);
p += 2;
if (mtu != -1) {
*p++ = DHO_MAXMESSAGESIZE;
*p++ = 2;
sz = htons((uint16_t)mtu);
memcpy(p, &sz, 2);
p += 2;
}
}
if (ifo->userclass[0]) {
@ -1184,6 +1241,13 @@ read_lease(struct interface *ifp)
else
logger(ifp->ctx, LOG_DEBUG,
"%s: accepted reconfigure key", ifp->name);
} else if ((ifp->options->auth.options & DHCPCD_AUTH_SENDREQUIRE) ==
DHCPCD_AUTH_SENDREQUIRE)
{
logger(ifp->ctx, LOG_ERR,
"%s: authentication now required", ifp->name);
free(dhcp);
return NULL;
}
return dhcp;
@ -1483,19 +1547,8 @@ dhcp_openudp(struct interface *ifp)
char *p;
#endif
#ifdef SOCK_CLOEXEC
if ((s = socket(PF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP)) == -1)
if ((s = xsocket(PF_INET, SOCK_DGRAM, IPPROTO_UDP, O_CLOEXEC)) == -1)
return -1;
#else
if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
return -1;
if ((n = fcntl(s, F_GETFD, 0)) == -1 ||
fcntl(s, F_SETFD, n | FD_CLOEXEC) == -1)
{
close(s);
return -1;
}
#endif
n = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1)
@ -2325,6 +2378,8 @@ dhcp_drop(struct interface *ifp, const char *reason)
dhcp_auth_reset(&state->auth);
dhcp_close(ifp);
free(state->offer);
state->offer = NULL;
free(state->old);
state->old = state->new;
state->new = NULL;
@ -2481,12 +2536,15 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp,
else
logger(ifp->ctx, LOG_DEBUG,
"%s: accepted reconfigure key", ifp->name);
} else if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) {
log_dhcp1(LOG_ERR, "no authentication", ifp, dhcp, from, 0);
return;
} else if (ifo->auth.options & DHCPCD_AUTH_SEND)
} else if (ifo->auth.options & DHCPCD_AUTH_SEND) {
if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) {
log_dhcp1(LOG_ERR, "no authentication",
ifp, dhcp, from, 0);
return;
}
log_dhcp1(LOG_WARNING, "no authentication",
ifp, dhcp, from, 0);
}
/* RFC 3203 */
if (type == DHCP_FORCERENEW) {
@ -2500,7 +2558,8 @@ dhcp_handledhcp(struct interface *ifp, struct dhcp_message **dhcpp,
if (auth == NULL) {
log_dhcp(LOG_ERR, "unauthenticated Force Renew",
ifp, dhcp, from);
return;
if (ifo->auth.options & DHCPCD_AUTH_REQUIRE)
return;
}
if (state->state != DHS_BOUND && state->state != DHS_INFORM) {
log_dhcp(LOG_DEBUG, "not bound, ignoring Force Renew",
@ -3203,7 +3262,7 @@ dhcp_start1(void *arg)
}
/* We don't want to read the old lease if we NAK an old test */
nolease = state->offer && ifp->ctx->options & DHCPCD_TEST;
if (!nolease) {
if (!nolease && ifo->options & DHCPCD_DHCP) {
state->offer = read_lease(ifp);
/* Check the saved lease matches the type we want */
if (state->offer) {
@ -3294,13 +3353,8 @@ dhcp_start1(void *arg)
}
if (!(ifo->options & DHCPCD_DHCP)) {
if (ifo->options & DHCPCD_IPV4LL) {
if (state->offer && state->offer->cookie != 0) {
free(state->offer);
state->offer = NULL;
}
if (ifo->options & DHCPCD_IPV4LL)
ipv4ll_start(ifp);
}
return;
}
@ -3337,6 +3391,13 @@ dhcp_start(struct interface *ifp)
eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcp_start1, ifp);
}
void
dhcp_abort(struct interface *ifp)
{
eloop_timeout_delete(ifp->ctx->eloop, dhcp_start1, ifp);
}
void
dhcp_handleifa(int cmd, struct interface *ifp,
const struct in_addr *addr,

View File

@ -1,4 +1,4 @@
/* $NetBSD: dhcp.h,v 1.10 2015/07/09 10:15:34 roy Exp $ */
/* $NetBSD: dhcp.h,v 1.11 2015/08/21 10:39:00 roy Exp $ */
/*
* dhcpcd - DHCP client daemon
@ -247,8 +247,8 @@ int get_option_addr(struct dhcpcd_ctx *,struct in_addr *,
const struct dhcp_message *, uint8_t);
#define IS_BOOTP(i, m) ((m) != NULL && \
get_option_uint8((i)->ctx, NULL, (m), DHO_MESSAGETYPE) == -1)
struct rt_head *get_option_routes(struct interface *,
const struct dhcp_message *);
uint16_t dhcp_get_mtu(const struct interface *);
struct rt_head *dhcp_get_routes(struct interface *);
ssize_t dhcp_env(char **, const char *, const struct dhcp_message *,
const struct interface *);
@ -266,7 +266,7 @@ void dhcp_handleifa(int, struct interface *,
void dhcp_drop(struct interface *, const char *);
void dhcp_start(struct interface *);
void dhcp_stop(struct interface *);
void dhcp_abort(struct interface *);
void dhcp_discover(void *);
void dhcp_inform(struct interface *);
void dhcp_bind(struct interface *);
@ -277,6 +277,7 @@ int dhcp_dump(struct interface *);
#else
#define dhcp_drop(a, b) {}
#define dhcp_start(a) {}
#define dhcp_abort(a) {}
#define dhcp_reboot(a, b) (b = b)
#define dhcp_reboot_newopts(a, b) (b = b)
#define dhcp_close(a) {}

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: dhcp6.c,v 1.14 2015/07/09 10:15:34 roy Exp $");
__RCSID("$NetBSD: dhcp6.c,v 1.15 2015/08/21 10:39:00 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -43,6 +43,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#define ELOOP_QUEUE 4
#include "config.h"
@ -2247,7 +2248,9 @@ auth:
else
logger(ifp->ctx, LOG_DEBUG,
"%s: accepted reconfigure key", ifp->name);
} else if (ifp->options->auth.options & DHCPCD_AUTH_REQUIRE) {
} else if ((ifp->options->auth.options & DHCPCD_AUTH_SENDREQUIRE) ==
DHCPCD_AUTH_SENDREQUIRE)
{
logger(ifp->ctx, LOG_ERR,
"%s: authentication now required", ifp->name);
goto ex;
@ -2753,13 +2756,16 @@ dhcp6_handledata(void *arg)
else
logger(ifp->ctx, LOG_DEBUG,
"%s: accepted reconfigure key", ifp->name);
} else if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) {
logger(ifp->ctx, LOG_ERR,
"%s: no authentication from %s", ifp->name, ctx->sfrom);
return;
} else if (ifo->auth.options & DHCPCD_AUTH_SEND)
} else if (ifo->auth.options & DHCPCD_AUTH_SEND) {
if (ifo->auth.options & DHCPCD_AUTH_REQUIRE) {
logger(ifp->ctx, LOG_ERR,
"%s: no authentication from %s",
ifp->name, ctx->sfrom);
return;
}
logger(ifp->ctx, LOG_WARNING,
"%s: no authentication from %s", ifp->name, ctx->sfrom);
}
op = dhcp6_get_op(r->type);
switch(r->type) {
@ -2863,7 +2869,8 @@ dhcp6_handledata(void *arg)
logger(ifp->ctx, LOG_ERR,
"%s: unauthenticated %s from %s",
ifp->name, op, ctx->sfrom);
return;
if (ifo->auth.options & DHCPCD_AUTH_REQUIRE)
return;
}
logger(ifp->ctx, LOG_INFO, "%s: %s from %s",
ifp->name, op, ctx->sfrom);
@ -3073,30 +3080,10 @@ dhcp6_open(struct dhcpcd_ctx *dctx)
#endif
ctx = dctx->ipv6;
#ifdef SOCK_CLOEXEC
ctx->dhcp_fd = socket(PF_INET6,
SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
IPPROTO_UDP);
ctx->dhcp_fd = xsocket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP,
O_NONBLOCK|O_CLOEXEC);
if (ctx->dhcp_fd == -1)
return -1;
#else
if ((ctx->dhcp_fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) == -1)
return -1;
if ((n = fcntl(ctx->dhcp_fd, F_GETFD, 0)) == -1 ||
fcntl(ctx->dhcp_fd, F_SETFD, n | FD_CLOEXEC) == -1)
{
close(ctx->dhcp_fd);
ctx->dhcp_fd = -1;
return -1;
}
if ((n = fcntl(ctx->dhcp_fd, F_GETFL, 0)) == -1 ||
fcntl(ctx->dhcp_fd, F_SETFL, n | O_NONBLOCK) == -1)
{
close(ctx->dhcp_fd);
ctx->dhcp_fd = -1;
return -1;
}
#endif
n = 1;
if (setsockopt(ctx->dhcp_fd, SOL_SOCKET, SO_REUSEADDR,
@ -3143,8 +3130,8 @@ dhcp6_start1(void *arg)
const struct dhcp_compat *dhc;
state = D6_STATE(ifp);
/* Match any DHCPv4 opton to DHCPv6 options if given for easy
* configuration */
/* If no DHCPv6 options are configured,
match configured DHCPv4 options to DHCPv6 equivalents. */
for (i = 0; i < sizeof(ifo->requestmask6); i++) {
if (ifo->requestmask6[i] != '\0')
break;
@ -3160,7 +3147,7 @@ dhcp6_start1(void *arg)
add_option_mask(ifo->requestmask6, D6_OPTION_FQDN);
}
/* Rapid commit won't wor with Prefix Delegation Exclusion */
/* Rapid commit won't work with Prefix Delegation Exclusion */
if (dhcp6_findselfsla(ifp, NULL))
del_option_mask(ifo->requestmask6, D6_OPTION_RAPID_COMMIT);

View File

@ -1,40 +0,0 @@
# $NetBSD: 10-mtu,v 1.6 2014/11/07 20:51:03 roy Exp $
# Configure the MTU for the interface
mtu_dir="$state_dir/mtu"
set_mtu()
{
local mtu=$1
if [ -w /sys/class/net/$interface/mtu ]; then
echo "$mtu" >/sys/class/net/$interface/mtu
else
ifconfig "$interface" mtu "$mtu"
fi
}
if [ "$reason" = PREINIT -a -e "$mtu_dir/$interface" ]; then
rm "$mtu_dir/$interface"
elif [ -n "$new_interface_mtu" ] && $if_up; then
# The smalled MTU dhcpcd can work with is 576
if [ "$new_interface_mtu" -ge 576 ]; then
if set_mtu "$new_interface_mtu"; then
syslog info "MTU set to $new_interface_mtu"
# Save the MTU so we can restore it later
if [ ! -e "$mtu_dir/$interface" ]; then
mkdir -p "$mtu_dir"
echo "$ifmtu" > "$mtu_dir/$interface"
fi
fi
fi
elif [ -e "$mtu_dir/$interface" ]; then
if $if_up || $if_down; then
# No MTU in this state, so restore the prior MTU
mtu=$(cat "$mtu_dir/$interface")
syslog info "MTU restored to $mtu"
set_mtu "$mtu"
rm "$mtu_dir/$interface"
fi
fi

View File

@ -1,4 +1,4 @@
# $NetBSD: 20-resolv.conf,v 1.7 2015/05/16 23:31:32 roy Exp $
# $NetBSD: 20-resolv.conf,v 1.8 2015/08/21 10:39:00 roy Exp $
# Generate /etc/resolv.conf
# Support resolvconf(8) if available
@ -119,14 +119,6 @@ add_resolv_conf()
new_domain_name_servers="$new_domain_name_servers${new_domain_name_servers:+ }$new_rdnss"
new_domain_search="$new_domain_search${new_domain_search:+ }$new_dnssl"
# If we don't have any configuration, remove it
if [ -z "$new_domain_name_servers" -a \
-z "$new_domain_name" -a \
-z "$new_domain_search" ]; then
remove_resolv_conf
return $?
fi
# Derive a new domain from our various hostname options
if [ -z "$new_domain_name" ]; then
if [ "$new_dhcp6_fqdn" != "${new_dhcp6_fqdn#*.}" ]; then
@ -138,6 +130,14 @@ add_resolv_conf()
fi
fi
# If we don't have any configuration, remove it
if [ -z "$new_domain_name_servers" -a \
-z "$new_domain_name" -a \
-z "$new_domain_search" ]; then
remove_resolv_conf
return $?
fi
if [ -n "$new_domain_name" ]; then
set -- $new_domain_name
if valid_domainname "$1"; then

View File

@ -1,4 +1,4 @@
# $NetBSD: 30-hostname,v 1.6 2014/11/07 20:51:03 roy Exp $
# $NetBSD: 30-hostname,v 1.7 2015/08/21 10:39:00 roy Exp $
# Set the hostname from DHCP data if required
@ -148,6 +148,7 @@ set_hostname()
case "$reason" in
BOUND6|RENEW6|REBIND6|REBOOT6|INFORM6)
new_fqdn="$new_dhcp6_fqdn"
old_fqdn="$old_dhcp6_fqdn"
;;
esac

View File

@ -1,5 +1,5 @@
#!/bin/sh
# $NetBSD: dhcpcd-run-hooks.in,v 1.10 2015/07/09 10:15:34 roy Exp $
# $NetBSD: dhcpcd-run-hooks.in,v 1.11 2015/08/21 10:39:00 roy Exp $
# dhcpcd client configuration script
@ -120,8 +120,7 @@ remove_markers()
comp_file()
{
[ -e "$1" ] || return 1
[ -e "$2" ] || return 1
[ -e "$1" -a -e "$2" ] || return 1
if type cmp >/dev/null 2>&1; then
cmp -s "$1" "$2"

View File

@ -1,4 +1,4 @@
.\" $NetBSD: dhcpcd.8.in,v 1.43 2015/07/09 10:15:34 roy Exp $
.\" $NetBSD: dhcpcd.8.in,v 1.44 2015/08/21 10:39:00 roy Exp $
.\" Copyright (c) 2006-2015 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 July 3, 2015
.Dd August 21, 2015
.Dt DHCPCD 8
.Os
.Sh NAME
@ -204,7 +204,7 @@ This script runs each script found in
in a lexical order.
The default installation supplies the scripts
.Pa 01-test ,
.Pa 10-mtu ,
.Pa 02-dump ,
.Pa 10-wpa_supplicant ,
.Pa 15-timezone ,
.Pa 20-resolv.conf
@ -552,8 +552,8 @@ Matches full name, or prefixed with 2 numbers optionally ending with
.Pp
So to stop
.Nm
from touching your DNS or MTU settings you would do:-
.D1 dhcpcd -C resolv.conf -C mtu eth0
from touching your DNS settings you would do:-
.D1 dhcpcd -C resolv.conf eth0
.It Fl G , Fl Fl nogateway
Don't set any default routes.
.It Fl H , Fl Fl xidhwaddr

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: dhcpcd.c,v 1.26 2015/07/09 10:15:34 roy Exp $");
__RCSID("$NetBSD: dhcpcd.c,v 1.27 2015/08/21 10:39:00 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -575,10 +575,6 @@ configure_interface1(struct interface *ifp)
}
}
#endif
/* If we are not sending an authentication option, don't require it */
if (!(ifo->auth.options & DHCPCD_AUTH_SEND))
ifo->auth.options &= ~DHCPCD_AUTH_REQUIRE;
}
int
@ -703,6 +699,7 @@ dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
script_runreason(ifp, "NOCARRIER");
#ifdef NOCARRIER_PRESERVE_IP
arp_close(ifp);
dhcp_abort(ifp);
if_sortinterfaces(ctx);
ipv4_preferanother(ifp);
ipv6nd_expire(ifp, 0);
@ -907,7 +904,9 @@ dhcpcd_prestartinterface(void *arg)
struct interface *ifp = arg;
pre_start(ifp);
if (if_up(ifp) == -1)
if ((!(ifp->ctx->options & DHCPCD_MASTER) ||
ifp->options->options & DHCPCD_IF_UP) &&
if_up(ifp) == -1)
logger(ifp->ctx, LOG_ERR, "%s: if_up: %m", ifp->name);
if (ifp->options->options & DHCPCD_LINK &&
@ -1395,6 +1394,14 @@ main(int argc, char **argv)
ifo = NULL;
ctx.cffile = CONFIG;
ctx.pid_fd = ctx.control_fd = ctx.control_unpriv_fd = ctx.link_fd = -1;
ctx.pf_inet_fd = -1;
#if defined(INET6) && defined(BSD)
ctx.pf_inet6_fd = -1;
#endif
#ifdef IFLR_ACTIVE
ctx.pf_link_fd = -1;
#endif
TAILQ_INIT(&ctx.control_fds);
#ifdef PLUGIN_DEV
ctx.dev_fd = -1;
@ -1760,17 +1767,12 @@ main(int argc, char **argv)
if (ctx.ifc == 1 && !(ctx.options & DHCPCD_BACKGROUND))
ctx.options |= DHCPCD_WAITIP;
/* RTM_NEWADDR goes through the link socket as well which we
* need for IPv6 DAD, so we check for DHCPCD_LINK in
* dhcpcd_handlecarrier instead.
* We also need to open this before checking for interfaces below
* so that we pickup any new addresses during the discover phase. */
ctx.link_fd = if_openlinksocket();
if (ctx.link_fd == -1)
logger(&ctx, LOG_ERR, "open_link_socket: %m");
else
eloop_event_add(ctx.eloop, ctx.link_fd,
handle_link, &ctx, NULL, NULL);
/* Open our persistent sockets. */
if (if_opensockets(&ctx) == -1) {
logger(&ctx, LOG_ERR, "if_opensockets: %m");
goto exit_failure;
}
eloop_event_add(ctx.eloop, ctx.link_fd, handle_link, &ctx, NULL, NULL);
/* Start any dev listening plugin which may want to
* change the interface name provided by the kernel */
@ -1875,6 +1877,17 @@ exit1:
eloop_event_delete(ctx.eloop, ctx.link_fd);
close(ctx.link_fd);
}
if (ctx.pf_inet_fd != -1)
close(ctx.pf_inet_fd);
#if defined(INET6) && defined(BSD)
if (ctx.pf_inet6_fd != -1)
close(ctx.pf_inet6_fd);
#endif
#ifdef IFLR_ACTIVE
if (ctx.pf_link_fd != -1)
close(ctx.pf_link_fd);
#endif
free_options(ifo);
free_globals(&ctx);

View File

@ -1,4 +1,4 @@
# $NetBSD: dhcpcd.conf,v 1.16 2015/03/26 10:26:37 roy Exp $
# $NetBSD: dhcpcd.conf,v 1.17 2015/08/21 10:39:00 roy Exp $
# A sample configuration for dhcpcd.
# See dhcpcd.conf(5) for details.
@ -30,9 +30,8 @@ option domain_name_servers, domain_name, domain_search, host_name
option classless_static_routes
# Most distributions have NTP support.
option ntp_servers
# Respect the network MTU.
# Some interface drivers reset when changing the MTU so disabled by default.
#option interface_mtu
# Respect the network MTU. This is applied to DHCP routes.
option interface_mtu
# A ServerID is required by RFC2131.
require dhcp_server_identifier

View File

@ -1,4 +1,4 @@
.\" $NetBSD: dhcpcd.conf.5.in,v 1.22 2015/07/09 10:15:34 roy Exp $
.\" $NetBSD: dhcpcd.conf.5.in,v 1.23 2015/08/21 10:39:00 roy Exp $
.\" Copyright (c) 2006-2015 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 July 9, 2015
.Dd August 1, 2015
.Dt DHCPCD.CONF 5
.Os
.Sh NAME
@ -408,6 +408,7 @@ Don't send any ARP requests.
This also disables IPv4LL.
.It Ic noauthrequired
Don't require authentication even though we requested it.
Also allows FORCERENEW and RECONFIGURE messages without authentication.
.It Ic nodelay
Don't delay for an initial randomised time when starting protocols.
.It Ic nodev
@ -431,8 +432,8 @@ Matches full name, or prefixed with 2 numbers optionally ending with
.Pp
So to stop
.Nm dhcpcd
from touching your DNS or MTU settings you would do:-
.D1 nohook resolv.conf, mtu
from touching your DNS settings or starting wpa_supplicant you would do:-
.D1 nohook resolv.conf, wpa_supplicant
.It Ic noipv4
Don't attempt to configure an IPv4 address.
.It Ic noipv4ll
@ -448,6 +449,14 @@ Disable solicitation and receipt of IPv6 Router Advertisements.
.It Ic nolink
Don't receive link messages about carrier status.
You should only set this for buggy interface drivers.
.It Ic noup
Don't bring the interface up when in master mode.
If
.Nm
cannot determine the carrier state,
.Nm
will enter a tight polling loop until the interface is marked up and running
or a valid carrier state is reported.
.It Ic option Ar option
Requests the
.Ar option
@ -464,7 +473,8 @@ lines.
Prepend dhcp6_ to
.Ar option
to request a DHCPv6 option.
DHCPv4 options are mapped to DHCPv6 where applicable.
If no DHCPv6 options are configured,
then DHCPv4 options are mapped to equivalent DHCPv6 options.
.Pp
Prepend nd_ to
.Ar option

View File

@ -1,4 +1,4 @@
/* $NetBSD: dhcpcd.h,v 1.12 2015/07/09 10:15:34 roy Exp $ */
/* $NetBSD: dhcpcd.h,v 1.13 2015/08/21 10:39:00 roy Exp $ */
/*
* dhcpcd - DHCP client daemon
@ -64,6 +64,11 @@
* dhcpcd can poll it for the relevant flags periodically */
#define IF_POLL_UP 100 /* milliseconds */
#ifdef __QNX__
/* QNX carries defines for, but does not actually support PF_LINK */
#undef IFLR_ACTIVE
#endif
struct interface {
struct dhcpcd_ctx *ctx;
TAILQ_ENTRY(interface) next;
@ -107,9 +112,17 @@ struct dhcpcd_ctx {
char **ifcv; /* configured interfaces */
unsigned char *duid;
size_t duid_len;
int link_fd;
struct if_head *ifaces;
int pf_inet_fd;
#if defined(INET6) && defined(BSD)
int pf_inet6_fd;
#endif
#ifdef IFLR_ACTIVE
int pf_link_fd;
#endif
int link_fd;
#ifdef USE_SIGNALS
sigset_t sigset;
#endif
@ -125,6 +138,8 @@ struct dhcpcd_ctx {
struct dhcp_opt *vivso;
size_t vivso_len;
char *randomstate; /* original state */
#ifdef INET
struct dhcp_opt *dhcp_opts;
size_t dhcp_opts_len;

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: if-bsd.c,v 1.22 2015/07/09 10:15:34 roy Exp $");
__RCSID("$NetBSD: if-bsd.c,v 1.23 2015/08/21 10:39:00 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -84,6 +84,7 @@
#include "if.h"
#include "if-options.h"
#include "ipv4.h"
#include "ipv4ll.h"
#include "ipv6.h"
#include "ipv6nd.h"
@ -127,27 +128,7 @@ int
if_openlinksocket(void)
{
#ifdef SOCK_CLOEXEC
return socket(PF_ROUTE, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
#else
int s, flags;
if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
return -1;
if ((flags = fcntl(s, F_GETFD, 0)) == -1 ||
fcntl(s, F_SETFD, flags | FD_CLOEXEC) == -1)
{
close(s);
return -1;
}
if ((flags = fcntl(s, F_GETFL, 0)) == -1 ||
fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
{
close(s);
return -1;
}
return s;
#endif
return xsocket(PF_ROUTE, SOCK_RAW, 0, O_NONBLOCK|O_CLOEXEC);
}
#if defined(INET) || defined(INET6)
@ -164,9 +145,9 @@ if_linkaddr(struct sockaddr_dl *sdl, const struct interface *ifp)
#endif
static int
if_getssid1(const char *ifname, uint8_t *ssid)
if_getssid1(int s, const char *ifname, uint8_t *ssid)
{
int s, retval = -1;
int retval = -1;
#if defined(SIOCG80211NWID)
struct ifreq ifr;
struct ieee80211_nwid nwid;
@ -175,9 +156,6 @@ if_getssid1(const char *ifname, uint8_t *ssid)
char nwid[IEEE80211_NWID_LEN + 1];
#endif
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return -1;
#if defined(SIOCG80211NWID) /* NetBSD */
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
@ -216,7 +194,6 @@ if_getssid1(const char *ifname, uint8_t *ssid)
}
#endif
close(s);
return retval;
}
@ -225,7 +202,7 @@ if_getssid(struct interface *ifp)
{
int r;
r = if_getssid1(ifp->name, ifp->ssid);
r = if_getssid1(ifp->ctx->pf_inet_fd, ifp->name, ifp->ssid);
if (r != -1)
ifp->ssid_len = (unsigned int)r;
return r;
@ -239,23 +216,20 @@ if_getssid(struct interface *ifp)
* returning the SSID gives an error.
*/
int
if_vimaster(const char *ifname)
if_vimaster(const struct dhcpcd_ctx *ctx, const char *ifname)
{
int s, r;
int r;
struct ifmediareq ifmr;
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return -1;
memset(&ifmr, 0, sizeof(ifmr));
strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
r = ioctl(s, SIOCGIFMEDIA, &ifmr);
close(s);
r = ioctl(ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr);
if (r == -1)
return -1;
if (ifmr.ifm_status & IFM_AVALID &&
IFM_TYPE(ifmr.ifm_active) == IFM_IEEE80211)
{
if (if_getssid1(ifname, NULL) == -1)
if (if_getssid1(ctx->pf_inet_fd, ifname, NULL) == -1)
return 1;
}
return 0;
@ -450,12 +424,9 @@ if_address(const struct interface *ifp, const struct in_addr *address,
const struct in_addr *netmask, const struct in_addr *broadcast,
int action)
{
int s, r;
int r;
struct in_aliasreq ifra;
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return -1;
memset(&ifra, 0, sizeof(ifra));
strlcpy(ifra.ifra_name, ifp->name, sizeof(ifra.ifra_name));
@ -470,9 +441,8 @@ if_address(const struct interface *ifp, const struct in_addr *address,
ADDADDR(&ifra.ifra_broadaddr, broadcast);
#undef ADDADDR
r = ioctl(s,
r = ioctl(ifp->ctx->pf_inet_fd,
action < 0 ? SIOCDIFADDR : SIOCAIFADDR, &ifra);
close(s);
return r;
}
@ -503,6 +473,7 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm)
get_addrs(rtm->rtm_addrs, cp, rti_info);
memset(rt, 0, sizeof(*rt));
rt->flags = (unsigned int)rtm->rtm_flags;
COPYOUT(rt->dest, rti_info[RTAX_DST]);
if (rtm->rtm_addrs & RTA_NETMASK)
COPYOUT(rt->net, rti_info[RTAX_NETMASK]);
@ -511,6 +482,9 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm)
COPYOUT(rt->gate, rti_info[RTAX_GATEWAY]);
COPYOUT(rt->src, rti_info[RTAX_IFA]);
if (rtm->rtm_inits & RTV_MTU)
rt->mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
if (rtm->rtm_index)
rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index);
else if (rtm->rtm_addrs & RTA_IFP) {
@ -519,6 +493,7 @@ if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct rt_msghdr *rtm)
sdl = (struct sockaddr_dl *)(void *)rti_info[RTAX_IFP];
rt->iface = if_findsdl(ctx, sdl);
}
/* If we don't have an interface and it's a host route, it maybe
* to a local ip via the loopback interface. */
if (rt->iface == NULL &&
@ -537,6 +512,7 @@ int
if_route(unsigned char cmd, const struct rt *rt)
{
const struct dhcp_state *state;
const struct ipv4ll_state *istate;
union sockunion {
struct sockaddr sa;
struct sockaddr_in sin;
@ -549,10 +525,6 @@ if_route(unsigned char cmd, const struct rt *rt)
} rtm;
char *bp = rtm.buffer;
size_t l;
int s, retval;
if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
return -1;
#define ADDSU { \
l = RT_ROUNDUP(su.sa.sa_len); \
@ -563,14 +535,18 @@ if_route(unsigned char cmd, const struct rt *rt)
memset(&su, 0, sizeof(su)); \
su.sin.sin_family = AF_INET; \
su.sin.sin_len = sizeof(su.sin); \
(&su.sin)->sin_addr = *addr; \
(&su.sin)->sin_addr = *(addr); \
ADDSU; \
}
if (cmd != RTM_DELETE)
if (cmd != RTM_DELETE) {
state = D_CSTATE(rt->iface);
else /* appease GCC */
istate = IPV4LL_CSTATE(rt->iface);
} else {
/* appease GCC */
state = NULL;
istate = NULL;
}
memset(&rtm, 0, sizeof(rtm));
rtm.hdr.rtm_version = RTM_VERSION;
rtm.hdr.rtm_seq = 1;
@ -587,9 +563,14 @@ if_route(unsigned char cmd, const struct rt *rt)
if (cmd != RTM_DELETE) {
rtm.hdr.rtm_addrs |= RTA_IFA | RTA_IFP;
/* None interface subnet routes are static. */
if (rt->gate.s_addr != INADDR_ANY ||
if ((rt->gate.s_addr != INADDR_ANY ||
rt->net.s_addr != state->net.s_addr ||
rt->dest.s_addr != (state->addr.s_addr & state->net.s_addr))
rt->dest.s_addr !=
(state->addr.s_addr & state->net.s_addr)) &&
(istate == NULL ||
rt->dest.s_addr !=
(istate->addr.s_addr & inaddr_llmask.s_addr) ||
rt->net.s_addr != inaddr_llmask.s_addr))
rtm.hdr.rtm_flags |= RTF_STATIC;
else {
#ifdef RTF_CLONING
@ -660,16 +641,20 @@ if_route(unsigned char cmd, const struct rt *rt)
}
if (rtm.hdr.rtm_addrs & RTA_IFA)
ADDADDR(&state->addr);
ADDADDR(istate == NULL ? &state->addr : &istate->addr);
if (rt->mtu) {
rtm.hdr.rtm_inits |= RTV_MTU;
rtm.hdr.rtm_rmx.rmx_mtu = rt->mtu;
}
}
#undef ADDADDR
#undef ADDSU
rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm);
retval = write(s, &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0;
close(s);
return retval;
return write(rt->iface->ctx->link_fd,
&rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0;
}
int
@ -713,23 +698,17 @@ if_initrt(struct interface *ifp)
int
if_addrflags(const struct in_addr *addr, const struct interface *ifp)
{
int s, flags;
struct ifreq ifr;
struct sockaddr_in *sin;
s = socket(PF_INET, SOCK_DGRAM, 0);
flags = -1;
if (s != -1) {
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
sin = (struct sockaddr_in *)(void *)&ifr.ifr_addr;
sin->sin_family = AF_INET;
sin->sin_addr = *addr;
if (ioctl(s, SIOCGIFAFLAG_IN, &ifr) != -1)
flags = ifr.ifr_addrflags;
close(s);
}
return flags;
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
sin = (struct sockaddr_in *)(void *)&ifr.ifr_addr;
sin->sin_family = AF_INET;
sin->sin_addr = *addr;
if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFAFLAG_IN, &ifr) == -1)
return -1;
return ifr.ifr_addrflags;
}
#else
int
@ -775,17 +754,13 @@ ifa_scope(struct sockaddr_in6 *sin, unsigned int ifindex)
#endif
int
if_address6(const struct ipv6_addr *a, int action)
if_address6(const struct ipv6_addr *ia, int action)
{
int s, r;
struct in6_aliasreq ifa;
struct in6_addr mask;
if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) == -1)
return -1;
memset(&ifa, 0, sizeof(ifa));
strlcpy(ifa.ifra_name, a->iface->name, sizeof(ifa.ifra_name));
strlcpy(ifa.ifra_name, ia->iface->name, sizeof(ifa.ifra_name));
/*
* We should not set IN6_IFF_TENTATIVE as the kernel should be
* able to work out if it's a new address or not.
@ -795,31 +770,30 @@ if_address6(const struct ipv6_addr *a, int action)
* either.
*/
#if 0
if (a->autoconf)
if (ia->autoconf)
ifa.ifra_flags |= IN6_IFF_AUTOCONF;
#endif
#ifdef IPV6_MANGETEMPADDR
if (a->flags & IPV6_AF_TEMPORARY)
if (ia->flags & IPV6_AF_TEMPORARY)
ifa.ifra_flags |= IN6_IFF_TEMPORARY;
#endif
#define ADDADDR(v, addr) { \
(v)->sin6_family = AF_INET6; \
(v)->sin6_len = sizeof(*v); \
(v)->sin6_addr = *addr; \
(v)->sin6_addr = *(addr); \
}
ADDADDR(&ifa.ifra_addr, &a->addr);
ifa_scope(&ifa.ifra_addr, a->iface->index);
ipv6_mask(&mask, a->prefix_len);
ADDADDR(&ifa.ifra_addr, &ia->addr);
ifa_scope(&ifa.ifra_addr, ia->iface->index);
ipv6_mask(&mask, ia->prefix_len);
ADDADDR(&ifa.ifra_prefixmask, &mask);
ifa.ifra_lifetime.ia6t_vltime = a->prefix_vltime;
ifa.ifra_lifetime.ia6t_pltime = a->prefix_pltime;
ifa.ifra_lifetime.ia6t_vltime = ia->prefix_vltime;
ifa.ifra_lifetime.ia6t_pltime = ia->prefix_pltime;
#undef ADDADDR
r = ioctl(s, action < 0 ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
close(s);
return r;
return ioctl(ia->iface->ctx->pf_inet6_fd,
action < 0 ? SIOCDIFADDR_IN6 : SIOCAIFADDR_IN6, &ifa);
}
@ -900,6 +874,9 @@ if_copyrt6(struct dhcpcd_ctx *ctx, struct rt6 *rt, struct rt_msghdr *rtm)
ipv6_mask(&rt->net, 128);
COPYOUT6(rt->gate, rti_info[RTAX_GATEWAY]);
if (rtm->rtm_inits & RTV_MTU)
rt->mtu = (unsigned int)rtm->rtm_rmx.rmx_mtu;
if (rtm->rtm_index)
rt->iface = if_findindex(ctx->ifaces, rtm->rtm_index);
else if (rtm->rtm_addrs & RTA_IFP) {
@ -937,10 +914,6 @@ if_route6(unsigned char cmd, const struct rt6 *rt)
} rtm;
char *bp = rtm.buffer;
size_t l;
int s, retval;
if ((s = socket(PF_ROUTE, SOCK_RAW, 0)) == -1)
return -1;
#define ADDSU { \
l = RT_ROUNDUP(su.sa.sa_len); \
@ -1025,9 +998,8 @@ if_route6(unsigned char cmd, const struct rt6 *rt)
#undef ADDSU
rtm.hdr.rtm_msglen = (unsigned short)(bp - (char *)&rtm);
retval = write(s, &rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0;
close(s);
return retval;
return write(rt->iface->ctx->link_fd,
&rtm, rtm.hdr.rtm_msglen) == -1 ? -1 : 0;
}
int
@ -1070,67 +1042,56 @@ if_initrt6(struct interface *ifp)
int
if_addrflags6(const struct in6_addr *addr, const struct interface *ifp)
{
int s, flags;
int flags;
struct in6_ifreq ifr6;
s = socket(PF_INET6, SOCK_DGRAM, 0);
flags = -1;
if (s != -1) {
memset(&ifr6, 0, sizeof(ifr6));
strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr.sin6_family = AF_INET6;
ifr6.ifr_addr.sin6_addr = *addr;
ifa_scope(&ifr6.ifr_addr, ifp->index);
if (ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) != -1)
flags = ifr6.ifr_ifru.ifru_flags6;
close(s);
}
memset(&ifr6, 0, sizeof(ifr6));
strlcpy(ifr6.ifr_name, ifp->name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr.sin6_family = AF_INET6;
ifr6.ifr_addr.sin6_addr = *addr;
ifa_scope(&ifr6.ifr_addr, ifp->index);
if (ioctl(ifp->ctx->pf_inet6_fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
flags = ifr6.ifr_ifru.ifru_flags6;
else
flags = -1;
return flags;
}
int
if_getlifetime6(struct ipv6_addr *ia)
{
int s, r;
int r;
struct in6_ifreq ifr6;
time_t t;
struct in6_addrlifetime *lifetime;
s = socket(PF_INET6, SOCK_DGRAM, 0);
r = -1;
if (s != -1) {
memset(&ifr6, 0, sizeof(ifr6));
strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr.sin6_family = AF_INET6;
ifr6.ifr_addr.sin6_addr = ia->addr;
ifa_scope(&ifr6.ifr_addr, ia->iface->index);
if (ioctl(s, SIOCGIFALIFETIME_IN6, &ifr6) != -1) {
time_t t;
struct in6_addrlifetime *lifetime;
memset(&ifr6, 0, sizeof(ifr6));
strlcpy(ifr6.ifr_name, ia->iface->name, sizeof(ifr6.ifr_name));
ifr6.ifr_addr.sin6_family = AF_INET6;
ifr6.ifr_addr.sin6_addr = ia->addr;
ifa_scope(&ifr6.ifr_addr, ia->iface->index);
if (ioctl(ia->iface->ctx->pf_inet6_fd,
SIOCGIFALIFETIME_IN6, &ifr6) == -1)
return -1;
t = time(NULL);
lifetime = &ifr6.ifr_ifru.ifru_lifetime;
t = time(NULL);
lifetime = &ifr6.ifr_ifru.ifru_lifetime;
if (lifetime->ia6t_preferred)
ia->prefix_pltime =
(uint32_t)(lifetime->ia6t_preferred -
MIN(t, lifetime->ia6t_preferred));
else
ia->prefix_pltime = ND6_INFINITE_LIFETIME;
if (lifetime->ia6t_expire) {
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;
r = 0;
}
close(s);
}
return r;
if (lifetime->ia6t_preferred)
ia->prefix_pltime = (uint32_t)(lifetime->ia6t_preferred -
MIN(t, lifetime->ia6t_preferred));
else
ia->prefix_pltime = ND6_INFINITE_LIFETIME;
if (lifetime->ia6t_expire) {
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;
return 0;
}
#endif
@ -1670,12 +1631,7 @@ _if_checkipv6(int s, struct dhcpcd_ctx *ctx,
int
if_checkipv6(struct dhcpcd_ctx *ctx, const struct interface *ifp, int own)
{
int s, r;
if ((s = socket(PF_INET6, SOCK_DGRAM, 0)) == -1)
return -1;
r = _if_checkipv6(s, ctx, ifp, own);
close(s);
return r;
return _if_checkipv6(ctx->pf_inet6_fd, ctx, ifp, own);
}
#endif

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: if-options.c,v 1.25 2015/07/09 10:15:34 roy Exp $");
__RCSID("$NetBSD: if-options.c,v 1.26 2015/08/21 10:39:00 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -97,7 +97,7 @@
#define O_CONTROLGRP O_BASE + 34
#define O_SLAAC O_BASE + 35
#define O_GATEWAY O_BASE + 36
// unassigned O_BASE + 37
#define O_NOUP O_BASE + 37
#define O_IPV6RA_AUTOCONF O_BASE + 38
#define O_IPV6RA_NOAUTOCONF O_BASE + 39
#define O_REJECT O_BASE + 40
@ -199,6 +199,7 @@ const struct option cf_options[] = {
{"reject", required_argument, NULL, O_REJECT},
{"bootp", no_argument, NULL, O_BOOTP},
{"nodelay", no_argument, NULL, O_NODELAY},
{"noup", no_argument, NULL, O_NOUP},
{NULL, 0, NULL, '\0'}
};
@ -2006,6 +2007,9 @@ err_sla:
case O_GATEWAY:
ifo->options |= DHCPCD_GATEWAY;
break;
case O_NOUP:
ifo->options &= ~DHCPCD_IF_UP;
break;
case O_SLAAC:
if (strcmp(arg, "private") == 0 ||
strcmp(arg, "stableprivate") == 0 ||
@ -2120,6 +2124,7 @@ read_config(struct dhcpcd_ctx *ctx,
return NULL;
}
ifo->options |= DHCPCD_DAEMONISE | DHCPCD_LINK | DHCPCD_INITIAL_DELAY;
ifo->options |= DHCPCD_IF_UP;
#ifdef PLUGIN_DEV
ifo->options |= DHCPCD_DEV;
#endif

View File

@ -1,4 +1,4 @@
/* $NetBSD: if-options.h,v 1.12 2015/07/09 10:15:34 roy Exp $ */
/* $NetBSD: if-options.h,v 1.13 2015/08/21 10:39:00 roy Exp $ */
/*
* dhcpcd - DHCP client daemon
@ -106,7 +106,7 @@
#define DHCPCD_IAID (1ULL << 48)
#define DHCPCD_DHCP (1ULL << 49)
#define DHCPCD_DHCP6 (1ULL << 50)
// unassigned (1ULL << 51)
#define DHCPCD_IF_UP (1ULL << 51)
// unassigned (1ULL << 52)
// unassinged (1ULL << 53)
#define DHCPCD_IPV6RA_AUTOCONF (1ULL << 54)

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: if.c,v 1.14 2015/07/09 10:15:34 roy Exp $");
__RCSID("$NetBSD: if.c,v 1.15 2015/08/21 10:39:00 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -61,6 +61,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "config.h"
#include "common.h"
@ -73,11 +74,6 @@
#include "ipv4ll.h"
#include "ipv6nd.h"
#ifdef __QNX__
/* QNX carries defines for, but does not actually support PF_LINK */
#undef IFLR_ACTIVE
#endif
void
if_free(struct interface *ifp)
{
@ -95,28 +91,50 @@ if_free(struct interface *ifp)
}
int
if_carrier(struct interface *iface)
if_opensockets(struct dhcpcd_ctx *ctx)
{
int s, r;
if ((ctx->link_fd = if_openlinksocket()) == -1)
return -1;
ctx->pf_inet_fd = xsocket(PF_INET, SOCK_DGRAM, 0, O_CLOEXEC);
if (ctx->pf_inet_fd == -1)
return -1;
#if defined(INET6) && defined(BSD)
ctx->pf_inet6_fd = xsocket(PF_INET6, SOCK_DGRAM, 0, O_CLOEXEC);
if (ctx->pf_inet6_fd == -1)
return -1;
#endif
#ifdef IFLR_ACTIVE
ctx->pf_link_fd = xsocket(PF_LINK, SOCK_DGRAM, 0, O_CLOEXEC);
if (ctx->pf_link_fd == -1)
return -1;
#endif
return 0;
}
int
if_carrier(struct interface *ifp)
{
int r;
struct ifreq ifr;
#ifdef SIOCGIFMEDIA
struct ifmediareq ifmr;
#endif
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return LINK_UNKNOWN;
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
if (ioctl(s, SIOCGIFFLAGS, &ifr) == -1) {
close(s);
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == -1)
return LINK_UNKNOWN;
}
iface->flags = (unsigned int)ifr.ifr_flags;
ifp->flags = (unsigned int)ifr.ifr_flags;
#ifdef SIOCGIFMEDIA
memset(&ifmr, 0, sizeof(ifmr));
strlcpy(ifmr.ifm_name, iface->name, sizeof(ifmr.ifm_name));
if (ioctl(s, SIOCGIFMEDIA, &ifmr) != -1 &&
strlcpy(ifmr.ifm_name, ifp->name, sizeof(ifmr.ifm_name));
if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFMEDIA, &ifmr) != -1 &&
ifmr.ifm_status & IFM_AVALID)
r = (ifmr.ifm_status & IFM_ACTIVE) ? LINK_UP : LINK_DOWN;
else
@ -124,7 +142,6 @@ if_carrier(struct interface *iface)
#else
r = ifr.ifr_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN;
#endif
close(s);
return r;
}
@ -132,24 +149,21 @@ int
if_setflag(struct interface *ifp, short flag)
{
struct ifreq ifr;
int s, r;
int r;
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return -1;
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
r = -1;
if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) {
if (ioctl(ifp->ctx->pf_inet_fd, SIOCGIFFLAGS, &ifr) == 0) {
if (flag == 0 || (ifr.ifr_flags & flag) == flag)
r = 0;
else {
ifr.ifr_flags |= flag;
if (ioctl(s, SIOCSIFFLAGS, &ifr) == 0)
if (ioctl(ifp->ctx->pf_inet_fd, SIOCSIFFLAGS, &ifr) ==0)
r = 0;
}
ifp->flags = (unsigned int)ifr.ifr_flags;
}
close(s);
return r;
}
@ -241,24 +255,12 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv)
const struct sockaddr_dl *sdl;
#ifdef SIOCGIFPRIORITY
struct ifreq ifr;
int s_inet;
#endif
#ifdef IFLR_ACTIVE
struct if_laddrreq iflr;
int s_link;
#endif
#ifdef SIOCGIFPRIORITY
if ((s_inet = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return NULL;
#endif
#ifdef IFLR_ACTIVE
if ((s_link = socket(PF_LINK, SOCK_DGRAM, 0)) == -1) {
#ifdef SIOCGIFPRIORITY
close(s_inet);
#endif
return NULL;
}
memset(&iflr, 0, sizeof(iflr));
#endif
#elif AF_PACKET
@ -343,7 +345,7 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv)
continue;
}
if (if_vimaster(p) == 1) {
if (if_vimaster(ctx, p) == 1) {
logger(ctx, argc ? LOG_ERR : LOG_DEBUG,
"%s: is a Virtual Interface Master, skipping", p);
continue;
@ -376,7 +378,7 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv)
MIN(ifa->ifa_addr->sa_len, sizeof(iflr.addr)));
iflr.flags = IFLR_PREFIX;
iflr.prefixlen = (unsigned int)sdl->sdl_alen * NBBY;
if (ioctl(s_link, SIOCGLIFADDR, &iflr) == -1 ||
if (ioctl(ctx->pf_link_fd, SIOCGLIFADDR, &iflr) == -1 ||
!(iflr.flags & IFLR_ACTIVE))
{
if_free(ifp);
@ -497,27 +499,30 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv)
}
}
/* Handle any platform init for the interface */
if (if_init(ifp) == -1) {
logger(ifp->ctx, LOG_ERR, "%s: if_init: %m", p);
if_free(ifp);
continue;
}
if (!(ctx->options & (DHCPCD_DUMPLEASE | DHCPCD_TEST))) {
/* Handle any platform init for the interface */
if (if_init(ifp) == -1) {
logger(ifp->ctx, LOG_ERR, "%s: if_init: %m", p);
if_free(ifp);
continue;
}
/* Ensure that the MTU is big enough for DHCP */
if (if_getmtu(ifp->name) < MTU_MIN &&
if_setmtu(ifp->name, MTU_MIN) == -1)
{
logger(ifp->ctx, LOG_ERR, "%s: set_mtu: %m", p);
if_free(ifp);
continue;
/* Ensure that the MTU is big enough for DHCP */
if (if_getmtu(ifp) < MTU_MIN &&
if_setmtu(ifp, MTU_MIN) == -1)
{
logger(ifp->ctx, LOG_ERR,
"%s: if_setmtu: %m", p);
if_free(ifp);
continue;
}
}
#ifdef SIOCGIFPRIORITY
/* Respect the interface priority */
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
if (ioctl(s_inet, SIOCGIFPRIORITY, &ifr) == 0)
if (ioctl(ctx->pf_inet_fd, SIOCGIFPRIORITY, &ifr) == 0)
ifp->metric = ifr.ifr_metric;
#else
/* We reserve the 100 range for virtual interfaces, if and when
@ -535,13 +540,6 @@ if_discover(struct dhcpcd_ctx *ctx, int argc, char * const *argv)
if_learnaddrs1(ctx, ifs, ifaddrs);
freeifaddrs(ifaddrs);
#ifdef SIOCGIFPRIORITY
close(s_inet);
#endif
#ifdef IFLR_ACTIVE
close(s_link);
#endif
return ifs;
}
@ -581,18 +579,15 @@ if_findindex(struct if_head *ifaces, unsigned int idx)
}
int
if_domtu(const char *ifname, short int mtu)
if_domtu(const struct interface *ifp, short int mtu)
{
int s, r;
int r;
struct ifreq ifr;
if ((s = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
return -1;
memset(&ifr, 0, sizeof(ifr));
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
ifr.ifr_mtu = mtu;
r = ioctl(s, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr);
close(s);
r = ioctl(ifp->ctx->pf_inet_fd, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr);
if (r == -1)
return -1;
return ifr.ifr_mtu;
@ -667,3 +662,31 @@ if_sortinterfaces(struct dhcpcd_ctx *ctx)
}
TAILQ_CONCAT(ctx->ifaces, &sorted, next);
}
int
xsocket(int domain, int type, int protocol, int flags)
{
#ifdef SOCK_CLOEXEC
if (flags & O_CLOEXEC)
type |= SOCK_CLOEXEC;
if (flags & O_NONBLOCK)
type |= SOCK_NONBLOCK;
return socket(domain, type, protocol);
#else
int s, xflags;
if ((s = socket(domain, type, protocol)) == -1)
return -1;
if ((flags & O_CLOEXEC) && (xflags = fcntl(s, F_GETFD, 0)) == -1 ||
fcntl(s, F_SETFD, xlags | FD_CLOEXEC) == -1)
goto out;
if ((flags & O_NONBLOCK) && (xflags = fcntl(s, F_GETFL, 0)) == -1 ||
fcntl(s, F_SETFL, xflags | O_NONBLOCK) == -1)
goto out;
return s;
out:
close(s);
return -1;
#endif
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: if.h,v 1.11 2015/07/09 10:15:34 roy Exp $ */
/* $NetBSD: if.h,v 1.12 2015/08/21 10:39:00 roy Exp $ */
/*
* dhcpcd - DHCP client daemon
@ -95,16 +95,17 @@ struct interface *if_find(struct if_head *, const char *);
struct interface *if_findindex(struct if_head *, unsigned int);
void if_sortinterfaces(struct dhcpcd_ctx *);
void if_free(struct interface *);
int if_domtu(const char *, short int);
#define if_getmtu(iface) if_domtu(iface, 0)
#define if_setmtu(iface, mtu) if_domtu(iface, mtu)
int if_domtu(const struct interface *, short int);
#define if_getmtu(ifp) if_domtu((ifp), 0)
#define if_setmtu(ifp, mtu) if_domtu((ifp), (mtu))
int if_carrier(struct interface *);
/* The below functions are provided by if-KERNEL.c */
int if_conf(struct interface *);
int if_init(struct interface *);
int if_getssid(struct interface *);
int if_vimaster(const char *);
int if_vimaster(const struct dhcpcd_ctx *ctx, const char *);
int if_opensockets(struct dhcpcd_ctx *);
int if_openlinksocket(void);
int if_managelink(struct dhcpcd_ctx *);
@ -163,4 +164,5 @@ int if_initrt6(struct interface *);
#endif
int if_machinearch(char *, size_t);
int xsocket(int, int, int, int);
#endif

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: ipv4.c,v 1.16 2015/07/09 10:15:34 roy Exp $");
__RCSID("$NetBSD: ipv4.c,v 1.17 2015/08/21 10:39:00 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -296,6 +296,11 @@ desc_route(const char *cmd, const struct rt *rt)
else if (rt->net.s_addr == htonl(INADDR_BROADCAST))
logger(ctx, LOG_INFO, "%s: %s host route to %s via %s",
ifname, cmd, addr, inet_ntoa(rt->gate));
else if (rt->dest.s_addr == htonl(INADDR_ANY) &&
rt->net.s_addr == htonl(INADDR_ANY) &&
rt->gate.s_addr == htonl(INADDR_ANY))
logger(ctx, LOG_INFO, "%s: %s default route",
ifname, cmd);
else if (rt->gate.s_addr == htonl(INADDR_ANY))
logger(ctx, LOG_INFO, "%s: %s route to %s/%d",
ifname, cmd, addr, inet_ntocidr(rt->net));
@ -383,6 +388,7 @@ ipv4_handlert(struct dhcpcd_ctx *ctx, int cmd, struct rt *rt)
static int
nc_route(struct rt *ort, struct rt *nrt)
{
int change;
/* Don't set default routes if not asked to */
if (nrt->dest.s_addr == 0 &&
@ -392,6 +398,7 @@ nc_route(struct rt *ort, struct rt *nrt)
desc_route(ort == NULL ? "adding" : "changing", nrt);
change = 0;
if (ort == NULL) {
ort = ipv4_findrt(nrt->iface->ctx, nrt, 0);
if (ort &&
@ -401,8 +408,12 @@ nc_route(struct rt *ort, struct rt *nrt)
ort->metric == nrt->metric &&
#endif
ort->gate.s_addr == nrt->gate.s_addr)))
return 0;
} else if (ort->flags & STATE_FAKE && !(nrt->flags & STATE_FAKE) &&
{
if (ort->mtu == nrt->mtu)
return 0;
change = 1;
}
} else if (ort->state & STATE_FAKE && !(nrt->state & STATE_FAKE) &&
ort->iface == nrt->iface &&
#ifdef HAVE_ROUTE_METRIC
ort->metric == nrt->metric &&
@ -410,12 +421,32 @@ nc_route(struct rt *ort, struct rt *nrt)
ort->dest.s_addr == nrt->dest.s_addr &&
ort->net.s_addr == nrt->net.s_addr &&
ort->gate.s_addr == nrt->gate.s_addr)
return 0;
{
if (ort->mtu == nrt->mtu)
return 0;
change = 1;
}
#ifdef RTF_CLONING
/* BSD can set routes to be cloning routes.
* Cloned routes inherit the parent flags.
* As such, we need to delete and re-add the route to flush children
* to correct the flags. */
if (change && ort != NULL && ort->flags & RTF_CLONING)
change = 0;
#endif
if (change) {
if (if_route(RTM_CHANGE, nrt) == 0)
return 0;
if (errno != ESRCH)
logger(nrt->iface->ctx, LOG_ERR, "if_route (CHG): %m");
}
#ifdef HAVE_ROUTE_METRIC
/* With route metrics, we can safely add the new route before
* deleting the old route. */
if (if_route(RTM_ADD, nrt) == 0) {
if (if_route(RTM_ADD, nrt) == 0) {
if (ort && if_route(RTM_DELETE, ort) == -1 && errno != ESRCH)
logger(nrt->iface->ctx, LOG_ERR, "if_route (DEL): %m");
return 0;
@ -472,7 +503,7 @@ add_subnet_route(struct rt_head *rt, const struct interface *ifp)
return rt;
#endif
if ((r = malloc(sizeof(*r))) == NULL) {
if ((r = calloc(1, sizeof(*r))) == NULL) {
logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
ipv4_freeroutes(rt);
return NULL;
@ -480,6 +511,7 @@ add_subnet_route(struct rt_head *rt, const struct interface *ifp)
r->dest.s_addr = s->addr.s_addr & s->net.s_addr;
r->net.s_addr = s->net.s_addr;
r->gate.s_addr = INADDR_ANY;
r->mtu = dhcp_get_mtu(ifp);
r->src = s->addr;
TAILQ_INSERT_HEAD(rt, r, next);
@ -500,8 +532,7 @@ add_loopback_route(struct rt_head *rt, const struct interface *ifp)
if (s->addr.s_addr == INADDR_ANY)
return rt;
r = malloc(sizeof(*r));
if (r == NULL) {
if ((r = calloc(1, sizeof(*r))) == NULL) {
logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
ipv4_freeroutes(rt);
return NULL;
@ -509,6 +540,7 @@ add_loopback_route(struct rt_head *rt, const struct interface *ifp)
r->dest = s->addr;
r->net.s_addr = INADDR_BROADCAST;
r->gate.s_addr = htonl(INADDR_LOOPBACK);
r->mtu = dhcp_get_mtu(ifp);
r->src = s->addr;
TAILQ_INSERT_HEAD(rt, r, next);
return rt;
@ -529,8 +561,7 @@ get_routes(struct interface *ifp)
TAILQ_FOREACH(rt, ifp->options->routes, next) {
if (rt->gate.s_addr == 0)
break;
r = malloc(sizeof(*r));
if (r == NULL) {
if ((r = calloc(1, sizeof(*r))) == NULL) {
logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
ipv4_freeroutes(nrt);
return NULL;
@ -539,7 +570,7 @@ get_routes(struct interface *ifp)
TAILQ_INSERT_TAIL(nrt, r, next);
}
} else
nrt = get_option_routes(ifp, D_STATE(ifp)->new);
nrt = dhcp_get_routes(ifp);
/* Copy our address as the source address */
if (nrt) {
@ -564,8 +595,7 @@ add_destination_route(struct rt_head *rt, const struct interface *ifp)
(state = D_CSTATE(ifp)) == NULL)
return rt;
r = malloc(sizeof(*r));
if (r == NULL) {
if ((r = calloc(1, sizeof(*r))) == NULL) {
logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
ipv4_freeroutes(rt);
return NULL;
@ -573,6 +603,8 @@ add_destination_route(struct rt_head *rt, const struct interface *ifp)
r->dest.s_addr = INADDR_ANY;
r->net.s_addr = INADDR_ANY;
r->gate.s_addr = state->dst.s_addr;
r->mtu = dhcp_get_mtu(ifp);
r->src = state->addr;
TAILQ_INSERT_HEAD(rt, r, next);
return rt;
}
@ -637,8 +669,7 @@ add_router_host_route(struct rt_head *rt, const struct interface *ifp)
"%s: router %s requires a host route",
ifp->name, inet_ntoa(rtp->gate));
}
rtn = malloc(sizeof(*rtn));
if (rtn == NULL) {
if ((rtn = calloc(1, sizeof(*rtn))) == NULL) {
logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
ipv4_freeroutes(rt);
return NULL;
@ -646,18 +677,72 @@ add_router_host_route(struct rt_head *rt, const struct interface *ifp)
rtn->dest.s_addr = rtp->gate.s_addr;
rtn->net.s_addr = htonl(INADDR_BROADCAST);
rtn->gate.s_addr = htonl(INADDR_ANY);
rtn->mtu = dhcp_get_mtu(ifp);
rtn->src = state->addr;
TAILQ_INSERT_BEFORE(rtp, rtn, next);
}
return rt;
}
static int
ipv4_doroute(struct rt *rt, struct rt_head *nrs)
{
const struct dhcp_state *state;
struct rt *or;
state = D_CSTATE(rt->iface);
rt->state = state->added & STATE_FAKE;
#ifdef HAVE_ROUTE_METRIC
rt->metric = rt->iface->metric;
#endif
/* Is this route already in our table? */
if ((find_route(nrs, rt, NULL)) != NULL)
return 0;
/* Do we already manage it? */
if ((or = find_route(rt->iface->ctx->ipv4_routes, rt, NULL))) {
if (state->added & STATE_FAKE)
return 0;
if (or->state & STATE_FAKE ||
or->iface != rt->iface ||
#ifdef HAVE_ROUTE_METRIC
rt->metric != or->metric ||
#endif
rt->src.s_addr != or->src.s_addr ||
rt->gate.s_addr != or->gate.s_addr ||
rt->mtu != or->mtu)
{
if (c_route(or, rt) != 0)
return 0;
}
TAILQ_REMOVE(rt->iface->ctx->ipv4_routes, or, next);
free(or);
} else {
if (state->added & STATE_FAKE) {
if ((or = ipv4_findrt(rt->iface->ctx, rt, 1)) == NULL)
return 0;
rt->iface = or->iface;
rt->gate.s_addr = or->gate.s_addr;
#ifdef HAVE_ROUTE_METRIC
rt->metric = or->metric;
#endif
rt->mtu = or->mtu;
rt->flags = or->flags;
} else {
if (n_route(rt) != 0)
return 0;
}
}
return 1;
}
void
ipv4_buildroutes(struct dhcpcd_ctx *ctx)
{
struct rt_head *nrs, *dnr;
struct rt *or, *rt, *rtn;
struct rt *rt, *rtn;
struct interface *ifp;
const struct dhcp_state *state;
int has_default;
/* We need to have the interfaces in the correct order to ensure
* our routes are managed correctly. */
@ -669,6 +754,7 @@ ipv4_buildroutes(struct dhcpcd_ctx *ctx)
}
TAILQ_INIT(nrs);
has_default = 0;
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
state = D_CSTATE(ifp);
if (state != NULL && state->new != NULL && state->added) {
@ -700,48 +786,29 @@ ipv4_buildroutes(struct dhcpcd_ctx *ctx)
continue;
TAILQ_FOREACH_SAFE(rt, dnr, next, rtn) {
rt->iface = ifp;
#ifdef HAVE_ROUTE_METRIC
rt->metric = ifp->metric;
#endif
rt->flags = state->added & STATE_FAKE;
/* Is this route already in our table? */
if ((find_route(nrs, rt, NULL)) != NULL)
continue;
/* Do we already manage it? */
if ((or = find_route(ctx->ipv4_routes, rt, NULL))) {
if (state->added & STATE_FAKE)
continue;
if (or->flags & STATE_FAKE ||
or->iface != ifp ||
#ifdef HAVE_ROUTE_METRIC
rt->metric != or->metric ||
#endif
rt->src.s_addr != or->src.s_addr ||
rt->gate.s_addr != or->gate.s_addr)
{
if (c_route(or, rt) != 0)
continue;
}
TAILQ_REMOVE(ctx->ipv4_routes, or, next);
free(or);
} else {
if (state->added & STATE_FAKE) {
or = ipv4_findrt(ctx, rt, 1);
if (or == NULL ||
or->gate.s_addr != rt->gate.s_addr)
continue;
} else {
if (n_route(rt) != 0)
continue;
}
if (ipv4_doroute(rt, nrs) == 1) {
TAILQ_REMOVE(dnr, rt, next);
TAILQ_INSERT_TAIL(nrs, rt, next);
if (rt->dest.s_addr == INADDR_ANY)
has_default = 1;
}
rt->flags |= STATE_ADDED;
TAILQ_REMOVE(dnr, rt, next);
TAILQ_INSERT_TAIL(nrs, rt, next);
}
ipv4_freeroutes(dnr);
}
/* If we don't manage a default route, grab one without a
* gateway for any IPv4LL enabled interfaces. */
if (!has_default) {
TAILQ_FOREACH(ifp, ctx->ifaces, next) {
if ((rt = ipv4ll_default_route(ifp)) != NULL) {
if (ipv4_doroute(rt, nrs) == 1)
TAILQ_INSERT_TAIL(nrs, rt, next);
else
free(rt);
}
}
}
/* Remove old routes we used to manage */
if (ctx->ipv4_routes) {
TAILQ_FOREACH(rt, ctx->ipv4_routes, next) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: ipv4.h,v 1.12 2015/07/09 10:15:34 roy Exp $ */
/* $NetBSD: ipv4.h,v 1.13 2015/08/21 10:39:00 roy Exp $ */
/*
* dhcpcd - DHCP client daemon
@ -63,8 +63,10 @@ struct rt {
#ifdef HAVE_ROUTE_METRIC
unsigned int metric;
#endif
unsigned int mtu;
struct in_addr src;
unsigned int flags;
unsigned int state;
};
TAILQ_HEAD(rt_head, rt);

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: ipv4ll.c,v 1.11 2015/07/09 10:15:34 roy Exp $");
__RCSID("$NetBSD: ipv4ll.c,v 1.12 2015/08/21 10:39:00 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -48,13 +48,17 @@
#include "ipv4ll.h"
#include "script.h"
static const struct in_addr inaddr_llmask = { HTONL(LINKLOCAL_MASK) };
static const struct in_addr inaddr_llbcast = { HTONL(LINKLOCAL_BRDC) };
const struct in_addr inaddr_llmask = { HTONL(LINKLOCAL_MASK) };
const struct in_addr inaddr_llbcast = { HTONL(LINKLOCAL_BRDC) };
static in_addr_t
ipv4ll_pick_addr(const struct arp_state *astate)
{
struct in_addr addr;
struct ipv4ll_state *istate;
istate = IPV4LL_STATE(astate->iface);
setstate(istate->randomstate);
do {
/* RFC 3927 Section 2.1 states that the first 256 and
@ -69,6 +73,9 @@ ipv4ll_pick_addr(const struct arp_state *astate)
/* Ensure we don't have the address on another interface */
} while (ipv4_findaddr(astate->iface->ctx, &addr) != NULL);
/* Restore the original random state */
setstate(astate->iface->ctx->randomstate);
return addr.s_addr;
}
@ -83,7 +90,7 @@ ipv4ll_subnet_route(const struct interface *ifp)
state->addr.s_addr == INADDR_ANY)
return NULL;
if ((rt = malloc(sizeof(*rt))) == NULL) {
if ((rt = calloc(1, sizeof(*rt))) == NULL) {
logger(ifp->ctx, LOG_ERR, "%s: malloc: %m", __func__);
return NULL;
}
@ -95,6 +102,29 @@ ipv4ll_subnet_route(const struct interface *ifp)
return rt;
}
struct rt *
ipv4ll_default_route(const struct interface *ifp)
{
const struct ipv4ll_state *state;
struct rt *rt;
assert(ifp != NULL);
if ((state = IPV4LL_CSTATE(ifp)) == NULL ||
state->addr.s_addr == INADDR_ANY)
return NULL;
if ((rt = calloc(1, sizeof(*rt))) == NULL) {
logger(ifp->ctx, LOG_ERR, "%s: malloc: %m", __func__);
return NULL;
}
rt->iface = ifp;
rt->dest.s_addr = INADDR_ANY;
rt->net.s_addr = INADDR_ANY;
rt->gate.s_addr = INADDR_ANY;
rt->src = state->addr;
return rt;
}
ssize_t
ipv4ll_env(char **env, const char *prefix, const struct interface *ifp)
{
@ -162,6 +192,7 @@ ipv4ll_probed(struct arp_state *astate)
#endif
state->addr = astate->addr;
timespecclear(&state->defend);
if_initrt(ifp);
ipv4_buildroutes(ifp->ctx);
arp_announce(astate);
script_runreason(ifp, "IPV4LL");
@ -295,6 +326,7 @@ ipv4ll_start(void *arg)
* the same address without persistent storage. */
if (state->conflicts == 0) {
unsigned int seed;
char *orig;
if (sizeof(seed) > ifp->hwlen) {
seed = 0;
@ -302,7 +334,15 @@ ipv4ll_start(void *arg)
} else
memcpy(&seed, ifp->hwaddr + ifp->hwlen - sizeof(seed),
sizeof(seed));
initstate(seed, state->randomstate, sizeof(state->randomstate));
orig = initstate(seed,
state->randomstate, sizeof(state->randomstate));
/* Save the original state. */
if (ifp->ctx->randomstate == NULL)
ifp->ctx->randomstate = orig;
/* Set back the original state until we need the seeded one. */
setstate(ifp->ctx->randomstate);
}
if ((astate = arp_new(ifp, NULL)) == NULL)
@ -338,7 +378,6 @@ ipv4ll_start(void *arg)
return;
}
setstate(state->randomstate);
logger(ifp->ctx, LOG_INFO, "%s: probing for an IPv4LL address",
ifp->name);
astate->addr.s_addr = ipv4ll_pick_addr(astate);
@ -353,9 +392,11 @@ void
ipv4ll_freedrop(struct interface *ifp, int drop)
{
struct ipv4ll_state *state;
int dropped;
assert(ifp != NULL);
state = IPV4LL_STATE(ifp);
dropped = 0;
/* Free ARP state first because ipv4_deladdr might also ... */
if (state && state->arp) {
@ -370,6 +411,7 @@ ipv4ll_freedrop(struct interface *ifp, int drop)
if (state && state->addr.s_addr != INADDR_ANY) {
ipv4_deladdr(ifp, &state->addr, &inaddr_llmask, 1);
state->addr.s_addr = INADDR_ANY;
dropped = 1;
}
/* Free any other link local addresses that might exist. */
@ -377,18 +419,22 @@ ipv4ll_freedrop(struct interface *ifp, int drop)
struct ipv4_addr *ia, *ian;
TAILQ_FOREACH_SAFE(ia, &istate->addrs, next, ian) {
if (IN_LINKLOCAL(ntohl(ia->addr.s_addr)))
if (IN_LINKLOCAL(ntohl(ia->addr.s_addr))) {
ipv4_deladdr(ifp, &ia->addr,
&ia->net, 0);
dropped = 1;
}
}
}
script_runreason(ifp, "IPV4LL");
}
if (state) {
free(state);
ifp->if_data[IF_DATA_IPV4LL] = NULL;
ipv4_buildroutes(ifp->ctx);
if (dropped) {
ipv4_buildroutes(ifp->ctx);
script_runreason(ifp, "IPV4LL");
}
}
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: ipv4ll.h,v 1.9 2015/07/09 10:15:34 roy Exp $ */
/* $NetBSD: ipv4ll.h,v 1.10 2015/08/21 10:39:00 roy Exp $ */
/*
* dhcpcd - DHCP client daemon
@ -32,6 +32,9 @@
#include "arp.h"
extern const struct in_addr inaddr_llmask;
extern const struct in_addr inaddr_llbcast;
#define LINKLOCAL_ADDR 0xa9fe0000
#define LINKLOCAL_MASK IN_CLASSB_NET
#define LINKLOCAL_BRDC (LINKLOCAL_ADDR | ~LINKLOCAL_MASK)
@ -58,6 +61,7 @@ struct ipv4ll_state {
IN_LINKLOCAL(ntohl(IPV4LL_CSTATE((ifp))->addr.s_addr)))
struct rt* ipv4ll_subnet_route(const struct interface *);
struct rt* ipv4ll_default_route(const struct interface *);
ssize_t ipv4ll_env(char **, const char *, const struct interface *);
void ipv4ll_start(void *);
void ipv4ll_claimed(void *);

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: ipv6.c,v 1.13 2015/07/09 10:15:34 roy Exp $");
__RCSID("$NetBSD: ipv6.c,v 1.14 2015/08/21 10:39:00 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -647,7 +647,13 @@ ipv6_addaddr(struct ipv6_addr *ap, const struct timespec *now)
ap->flags |= IPV6_AF_DADCOMPLETED;
logger(ap->iface->ctx, ap->flags & IPV6_AF_NEW ? LOG_INFO : LOG_DEBUG,
"%s: adding address %s", ap->iface->name, ap->saddr);
"%s: adding %saddress %s", ap->iface->name,
#ifdef IPV6_AF_TEMPORARY
ap->flags & IPV6_AF_TEMPORARY ? "temporary " : "",
#else
"",
#endif
ap->saddr);
if (ap->prefix_pltime == ND6_INFINITE_LIFETIME &&
ap->prefix_vltime == ND6_INFINITE_LIFETIME)
logger(ap->iface->ctx, LOG_DEBUG,
@ -881,17 +887,22 @@ ipv6_freedrop_addrs(struct ipv6_addrhead *addrs, int drop,
{
if (drop == 2)
TAILQ_REMOVE(addrs, ap, next);
/* Find the same address somewhere else */
apf = ipv6_findaddr(ap->iface->ctx, &ap->addr, 0);
if (apf == NULL ||
(apf->iface != ap->iface))
ipv6_deleteaddr(ap);
if (!(ap->iface->options->options &
DHCPCD_EXITING) && apf)
{
if (!timespecisset(&now))
clock_gettime(CLOCK_MONOTONIC, &now);
ipv6_addaddr(apf, &now);
/* Don't drop link-local addresses. */
if (!IN6_IS_ADDR_LINKLOCAL(&ap->addr)) {
/* Find the same address somewhere else */
apf = ipv6_findaddr(ap->iface->ctx, &ap->addr,
0);
if ((apf == NULL ||
(apf->iface != ap->iface)))
ipv6_deleteaddr(ap);
if (!(ap->iface->options->options &
DHCPCD_EXITING) && apf)
{
if (!timespecisset(&now))
clock_gettime(CLOCK_MONOTONIC,
&now);
ipv6_addaddr(apf, &now);
}
}
if (drop == 2)
ipv6_freeaddr(ap);
@ -1850,6 +1861,7 @@ ipv6_handlert(struct dhcpcd_ctx *ctx, int cmd, struct rt6 *rt)
static int
nc_route(struct rt6 *ort, struct rt6 *nrt)
{
int change;
/* Don't set default routes if not asked to */
if (IN6_IS_ADDR_UNSPECIFIED(&nrt->dest) &&
@ -1859,6 +1871,7 @@ nc_route(struct rt6 *ort, struct rt6 *nrt)
desc_route(ort == NULL ? "adding" : "changing", nrt);
change = 0;
if (ort == NULL) {
ort = ipv6_findrt(nrt->iface->ctx, nrt, 0);
if (ort &&
@ -1868,7 +1881,27 @@ nc_route(struct rt6 *ort, struct rt6 *nrt)
ort->metric == nrt->metric &&
#endif
IN6_ARE_ADDR_EQUAL(&ort->gate, &nrt->gate))))
{
if (ort->mtu == nrt->mtu)
return 0;
change = 1;
}
}
#ifdef RTF_CLONING
/* BSD can set routes to be cloning routes.
* Cloned routes inherit the parent flags.
* As such, we need to delete and re-add the route to flush children
* to correct the flags. */
if (change && ort != NULL && ort->flags & RTF_CLONING)
change = 0;
#endif
if (change) {
if (if_route6(RTM_CHANGE, nrt) == 0)
return 0;
if (errno != ESRCH)
logger(nrt->iface->ctx, LOG_ERR, "if_route6 (CHG): %m");
}
#ifdef HAVE_ROUTE_METRIC

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: ipv6nd.c,v 1.25 2015/07/09 10:15:34 roy Exp $");
__RCSID("$NetBSD: ipv6nd.c,v 1.26 2015/08/21 10:39:00 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -192,29 +192,10 @@ ipv6nd_open(struct dhcpcd_ctx *dctx)
ctx = dctx->ipv6;
if (ctx->nd_fd != -1)
return ctx->nd_fd;
#ifdef SOCK_CLOEXEC
ctx->nd_fd = socket(PF_INET6, SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK,
IPPROTO_ICMPV6);
ctx->nd_fd = xsocket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6,
O_NONBLOCK|O_CLOEXEC);
if (ctx->nd_fd == -1)
return -1;
#else
if ((ctx->nd_fd = socket(PF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) == -1)
return -1;
if ((on = fcntl(ctx->nd_fd, F_GETFD, 0)) == -1 ||
fcntl(ctx->nd_fd, F_SETFD, on | FD_CLOEXEC) == -1)
{
close(ctx->nd_fd);
ctx->nd_fd = -1;
return -1;
}
if ((on = fcntl(ctx->nd_fd, F_GETFL, 0)) == -1 ||
fcntl(ctx->nd_fd, F_SETFL, on | O_NONBLOCK) == -1)
{
close(ctx->nd_fd);
ctx->nd_fd = -1;
return -1;
}
#endif
/* RFC4861 4.1 */
on = 255;
@ -735,14 +716,19 @@ try_script:
}
static int
ipv6nd_ra_has_public_addr(const struct ra *rap)
ipv6nd_has_public_addr(const struct interface *ifp)
{
const struct ra *rap;
const struct ipv6_addr *ia;
TAILQ_FOREACH(ia, &rap->addrs, next) {
if (ia->flags & IPV6_AF_AUTOCONF &&
ipv6_publicaddr(ia))
return 1;
TAILQ_FOREACH(rap, ifp->ctx->ipv6->ra_routers, next) {
if (rap->iface == ifp) {
TAILQ_FOREACH(ia, &rap->addrs, next) {
if (ia->flags & IPV6_AF_AUTOCONF &&
ipv6_publicaddr(ia))
return 1;
}
}
}
return 0;
}
@ -1109,7 +1095,7 @@ ipv6nd_handlera(struct dhcpcd_ctx *dctx, struct interface *ifp,
if (new_rap)
add_router(ifp->ctx->ipv6, rap);
if (!ipv6nd_ra_has_public_addr(rap) &&
if (!ipv6nd_has_public_addr(rap->iface) &&
!(rap->iface->options->options & DHCPCD_IPV6RA_ACCEPT_NOPUBLIC) &&
(!(rap->flags & ND_RA_FLAG_MANAGED) ||
!dhcp6_has_public_addr(rap->iface)))

View File

@ -1,5 +1,5 @@
#include <sys/cdefs.h>
__RCSID("$NetBSD: script.c,v 1.21 2015/07/09 10:15:34 roy Exp $");
__RCSID("$NetBSD: script.c,v 1.22 2015/08/21 10:39:00 roy Exp $");
/*
* dhcpcd - DHCP client daemon
@ -325,7 +325,7 @@ make_env(const struct interface *ifp, const char *reason, char ***argv)
EMALLOC(6, e);
snprintf(env[6], e, "ifflags=%u", ifp->flags);
EMALLOC(7, e);
snprintf(env[7], e, "ifmtu=%d", if_getmtu(ifp->name));
snprintf(env[7], e, "ifmtu=%d", if_getmtu(ifp));
l = e = strlen("interface_order=");
TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
e += strlen(ifp2->name) + 1;