changeset 2446:6cde5389810b draft

Namespace all public dhcpcd.c functions. Add ipv4, ipv6, dhcp and dhcp6 options to re-enable if disabled globally. Try and load a delegated interface if not running on all interfaces. Fix delegated interfaces without a prefix set.
author Roy Marples <roy@marples.name>
date Mon, 28 Apr 2014 12:02:12 +0000
parents 7fea68938e29
children e21f40456cd0
files arp.c control.c dhcp.c dhcp6.c dhcpcd.c dhcpcd.conf.5.in dhcpcd.h if-bsd.c if-linux.c if-options.c if.c if.h ipv6.c ipv6nd.c script.c
diffstat 15 files changed, 162 insertions(+), 112 deletions(-) [+]
line wrap: on
line diff
--- a/arp.c	Fri Apr 25 13:14:21 2014 +0000
+++ b/arp.c	Mon Apr 28 12:02:12 2014 +0000
@@ -113,10 +113,10 @@
 		dhcp_decline(ifp);
 	eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
 	if (state->lease.frominfo)
-		start_interface(ifp);
+		dhcpcd_startinterface(ifp);
 	else
 		eloop_timeout_add_sec(ifp->ctx->eloop,
-		    DHCP_ARP_FAIL, start_interface, ifp);
+		    DHCP_ARP_FAIL, dhcpcd_startinterface, ifp);
 }
 
 static void
@@ -183,8 +183,8 @@
 			syslog(LOG_INFO,
 			    "%s: found %s on hardware address %s",
 			    ifp->name, inet_ntoa(ina), hwaddr);
-			if (select_profile(ifp, hwaddr) == -1 &&
-			    select_profile(ifp, inet_ntoa(ina)) == -1)
+			if (dhcpcd_selectprofile(ifp, hwaddr) == -1 &&
+			    dhcpcd_selectprofile(ifp, inet_ntoa(ina)) == -1)
 			{
 				state->probes = 0;
 				/* We didn't find a profile for this
@@ -199,7 +199,7 @@
 			}
 			dhcp_close(ifp);
 			eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
-			start_interface(ifp);
+			dhcpcd_startinterface(ifp);
 			return;
 		}
 
@@ -337,7 +337,7 @@
 				    &tv, arp_probe, ifp);
 			else
 				eloop_timeout_add_tv(ifp->ctx->eloop,
-				    &tv, start_interface, ifp);
+				    &tv, dhcpcd_startinterface, ifp);
 		} else
 			eloop_timeout_add_tv(ifp->ctx->eloop,
 			    &tv, dhcp_bind, ifp);
--- a/control.c	Fri Apr 25 13:14:21 2014 +0000
+++ b/control.c	Mon Apr 28 12:02:12 2014 +0000
@@ -85,7 +85,7 @@
 		*ap++ = p;
 		p += strlen(p) + 1;
 	}
-	handle_args(l->ctx, l, argc, argvp);
+	dhcpcd_handleargs(l->ctx, l, argc, argvp);
 }
 
 static void
--- a/dhcp.c	Fri Apr 25 13:14:21 2014 +0000
+++ b/dhcp.c	Mon Apr 28 12:02:12 2014 +0000
@@ -1317,8 +1317,8 @@
 	struct interface *iface;
 
 	iface = (struct interface *)arg;
-	select_profile(iface, iface->options->fallback);
-	start_interface(iface);
+	dhcpcd_selectprofile(iface, iface->options->fallback);
+	dhcpcd_startinterface(iface);
 }
 
 uint32_t
@@ -1882,7 +1882,7 @@
 		    iface->name, lease->renewaltime, lease->rebindtime);
 	}
 	ipv4_applyaddr(iface);
-	if (daemonise(iface->ctx) == 0) {
+	if (dhcpcd_daemonise(iface->ctx) == 0) {
 		if (!ipv4ll)
 			arp_close(iface);
 		state->state = DHS_BOUND;
--- a/dhcp6.c	Fri Apr 25 13:14:21 2014 +0000
+++ b/dhcp6.c	Mon Apr 28 12:02:12 2014 +0000
@@ -53,6 +53,8 @@
 #include "dhcp6.h"
 #include "duid.h"
 #include "eloop.h"
+#include "if.h"
+#include "if-options.h"
 #include "ipv6nd.h"
 #include "script.h"
 
@@ -1288,7 +1290,7 @@
 				syslog(LOG_DEBUG, "%s: DHCPv6 DAD completed",
 				    ifp->name);
 				script_runreason(ifp, state->reason);
-				daemonise(ifp->ctx);
+				dhcpcd_daemonise(ifp->ctx);
 			}
 		}
 	}
@@ -1756,7 +1758,7 @@
 		state->reason = "DELEGATED6";
 	}
 
-	if (sla == NULL) {
+	if (sla == NULL || sla->sla_set == 0) {
 		struct interface *ifi;
 		unsigned int idx;
 		int bits;
@@ -1780,6 +1782,7 @@
 				asla.prefix_len = 64;
 			else
 				asla.prefix_len = ROUNDUP8(asla.prefix_len);
+
 		}
 		sla = &asla;
 	}
@@ -1846,6 +1849,30 @@
 
 	ifo = ifp->options;
 	state = D6_STATE(ifp);
+
+	/* Try to load configured interfaces for delegation that do not exist */
+	for (i = 0; i < ifo->ia_len; i++) {
+		ia = &ifo->ia[i];
+		for (j = 0; j < ia->sla_len; j++) {
+			sla = &ia->sla[j];
+			for (k = 0; k < i; j++)
+				if (strcmp(sla->ifname, ia->sla[j].ifname) == 0)
+					break;
+			if (j >= i &&
+			    if_find(ifp->ctx, sla->ifname) == NULL)
+			{
+				syslog(LOG_INFO,
+				    "%s: loading for delegation", sla->ifname);
+				if (dhcpcd_handleinterface(ifp->ctx, 2,
+				    sla->ifname) == -1)
+					syslog(LOG_ERR,
+					    "%s: interface does not exist"
+					    " for delegation",
+					    sla->ifname);
+			}
+		}
+	}
+
 	TAILQ_FOREACH(ifd, ifp->ctx->ifaces, next) {
 		k = 0;
 		carrier_warned = abrt = 0;
@@ -1917,23 +1944,6 @@
 			ipv6_addaddrs(&ifd_state->addrs);
 		}
 	}
-
-	/* Warn about configured interfaces for delegation that do not exist */
-	for (i = 0; i < ifo->ia_len; i++) {
-		ia = &ifo->ia[i];
-		for (j = 0; j < ia->sla_len; j++) {
-			sla = &ia->sla[j];
-			for (k = 0; k < i; j++)
-				if (strcmp(sla->ifname, ia->sla[j].ifname) == 0)
-					break;
-			if (j >= i &&
-			    find_interface(ifp->ctx, sla->ifname) == NULL)
-				syslog(LOG_ERR,
-				    "%s: interface does not exist"
-				    " for delegation",
-				    sla->ifname);
-		}
-	}
 }
 
 static void
@@ -2449,7 +2459,7 @@
 		}
 		if (len) {
 			script_runreason(ifp, state->reason);
-			daemonise(ifp->ctx);
+			dhcpcd_daemonise(ifp->ctx);
 		} else
 			syslog(LOG_DEBUG,
 			    "%s: waiting for DHCPv6 DAD to complete",
--- a/dhcpcd.c	Fri Apr 25 13:14:21 2014 +0000
+++ b/dhcpcd.c	Mon Apr 28 12:02:12 2014 +0000
@@ -69,7 +69,7 @@
 #include "script.h"
 
 #ifdef USE_SIGNALS
-const int handle_sigs[] = {
+const int dhcpcd_handlesigs[] = {
 	SIGALRM,
 	SIGHUP,
 	SIGINT,
@@ -199,7 +199,7 @@
 			 * an infinite timeout. */
 			ctx->options &=
 			    ~(DHCPCD_WAITIP | DHCPCD_WAITIP4 | DHCPCD_WAITIP6);
-			daemonise(ctx);
+			dhcpcd_daemonise(ctx);
 		} else
 			eloop_exit(ctx->eloop, EXIT_FAILURE);
 		return;
@@ -212,7 +212,7 @@
 
 /* Returns the pid of the child, otherwise 0. */
 pid_t
-daemonise(struct dhcpcd_ctx *ctx)
+dhcpcd_daemonise(struct dhcpcd_ctx *ctx)
 {
 #ifdef THERE_IS_NO_FORK
 	eloop_timeout_delete(ctx->eloop, handle_exit_timeout, ctx);
@@ -293,20 +293,6 @@
 #endif
 }
 
-struct interface *
-find_interface(struct dhcpcd_ctx *ctx, const char *ifname)
-{
-	struct interface *ifp;
-
-	if (ctx != NULL && ctx->ifaces != NULL) {
-		TAILQ_FOREACH(ifp, ctx->ifaces, next) {
-			if (strcmp(ifp->name, ifname) == 0)
-				return ifp;
-		}
-	}
-	return NULL;
-}
-
 static void
 stop_interface(struct interface *ifp)
 {
@@ -461,7 +447,7 @@
 }
 
 int
-select_profile(struct interface *ifp, const char *profile)
+dhcpcd_selectprofile(struct interface *ifp, const char *profile)
 {
 	struct if_options *ifo;
 
@@ -487,18 +473,18 @@
 configure_interface(struct interface *ifp, int argc, char **argv)
 {
 
-	select_profile(ifp, NULL);
+	dhcpcd_selectprofile(ifp, NULL);
 	add_options(ifp->ctx, ifp->name, ifp->options, argc, argv);
 	configure_interface1(ifp);
 }
 
 void
-handle_carrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
+dhcpcd_handlecarrier(struct dhcpcd_ctx *ctx, int carrier, unsigned int flags,
     const char *ifname)
 {
 	struct interface *ifp;
 
-	ifp = find_interface(ctx, ifname);
+	ifp = if_find(ctx, ifname);
 	if (ifp == NULL || !(ifp->options->options & DHCPCD_LINK))
 		return;
 
@@ -533,13 +519,13 @@
 			/* BSD does not emit RTM_NEWADDR or RTM_CHGADDR when the
 			 * hardware address changes so we have to go
 			 * through the disovery process to work it out. */
-			handle_interface(ctx, 0, ifp->name);
+			dhcpcd_handleinterface(ctx, 0, ifp->name);
 #endif
 			if (ifp->wireless)
 				if_getssid(ifp->name, ifp->ssid);
 			configure_interface(ifp, ctx->argc, ctx->argv);
 			script_runreason(ifp, "CARRIER");
-			start_interface(ifp);
+			dhcpcd_startinterface(ifp);
 		}
 	}
 }
@@ -571,7 +557,7 @@
 }
 
 void
-start_interface(void *arg)
+dhcpcd_startinterface(void *arg)
 {
 	struct interface *ifp = arg;
 	struct if_options *ifo = ifp->options;
@@ -579,7 +565,7 @@
 	char buf[DUID_LEN * 3];
 
 	if (ifp->carrier == LINK_UNKNOWN)
-		handle_carrier(ifp->ctx, LINK_UNKNOWN, 0, ifp->name);
+		dhcpcd_handlecarrier(ifp->ctx, LINK_UNKNOWN, 0, ifp->name);
 	if (ifp->carrier == LINK_DOWN) {
 		syslog(LOG_INFO, "%s: waiting for carrier", ifp->name);
 		return;
@@ -703,8 +689,8 @@
 		script_runreason(ifp, reason);
 }
 
-void
-handle_interface(void *arg, int action, const char *ifname)
+int
+dhcpcd_handleinterface(void *arg, int action, const char *ifname)
 {
 	struct dhcpcd_ctx *ctx;
 	struct if_head *ifs;
@@ -714,29 +700,33 @@
 
 	ctx = arg;
 	if (action == -1) {
-		ifp = find_interface(ctx, ifname);
-		if (ifp != NULL) {
-			ifp->options->options |= DHCPCD_DEPARTED;
-			stop_interface(ifp);
+		ifp = if_find(ctx, ifname);
+		if (ifp == NULL) {
+			errno = ESRCH;
+			return -1;
 		}
-		return;
+		ifp->options->options |= DHCPCD_DEPARTED;
+		stop_interface(ifp);
+		return 0;
 	}
 
 	/* If running off an interface list, check it's in it. */
-	if (ctx->ifc) {
+	if (ctx->ifc && action != 2) {
 		for (i = 0; i < ctx->ifc; i++)
 			if (strcmp(ctx->ifv[i], ifname) == 0)
 				break;
 		if (i >= ctx->ifc)
-			return;
+			return 0;
 	}
 
+	i = -1;
 	ifs = if_discover(ctx, -1, UNCONST(argv));
 	TAILQ_FOREACH_SAFE(ifp, ifs, next, ifn) {
 		if (strcmp(ifp->name, ifname) != 0)
 			continue;
+		i = 0;
 		/* Check if we already have the interface */
-		ifl = find_interface(ctx, ifp->name);
+		ifl = if_find(ctx, ifp->name);
 		if (ifl) {
 			/* The flags and hwaddr could have changed */
 			ifl->flags = ifp->flags;
@@ -747,9 +737,9 @@
 			TAILQ_REMOVE(ifs, ifp, next);
 			TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
 		}
-		if (action == 1) {
+		if (action > 0) {
 			init_state(ifp, ctx->argc, ctx->argv);
-			start_interface(ifp);
+			dhcpcd_startinterface(ifp);
 		}
 	}
 
@@ -759,16 +749,20 @@
 		if_free(ifp);
 	}
 	free(ifs);
+
+	if (i == -1)
+		errno = ENOENT;
+	return i;
 }
 
 void
-handle_hwaddr(struct dhcpcd_ctx *ctx, const char *ifname,
+dhcpcd_handlehwaddr(struct dhcpcd_ctx *ctx, const char *ifname,
     const uint8_t *hwaddr, uint8_t hwlen)
 {
 	struct interface *ifp;
 	char buf[sizeof(ifp->hwaddr) * 3];
 
-	ifp = find_interface(ctx, ifname);
+	ifp = if_find(ctx, ifname);
 	if (ifp == NULL)
 		return;
 
@@ -797,7 +791,7 @@
 	configure_interface(ifp, argc, argv);
 	dhcp_reboot_newopts(ifp, oldopts);
 	dhcp6_reboot(ifp);
-	start_interface(ifp);
+	dhcpcd_startinterface(ifp);
 }
 
 static void
@@ -812,7 +806,7 @@
 
 	while ((ifp = TAILQ_FIRST(ifs))) {
 		TAILQ_REMOVE(ifs, ifp, next);
-		ifn = find_interface(ctx, ifp->name);
+		ifn = if_find(ctx, ifp->name);
 		if (ifn) {
 			if (action)
 				if_reboot(ifn, argc, argv);
@@ -822,7 +816,7 @@
 		} else {
 			init_state(ifp, argc, argv);
 			TAILQ_INSERT_TAIL(ctx->ifaces, ifp, next);
-			start_interface(ifp);
+			dhcpcd_startinterface(ifp);
 		}
 	}
 	free(ifs);
@@ -948,8 +942,8 @@
 	sa.sa_flags = SA_SIGINFO;
 	sigemptyset(&sa.sa_mask);
 
-	for (i = 0; handle_sigs[i]; i++) {
-		if (sigaction(handle_sigs[i], &sa, NULL) == -1)
+	for (i = 0; dhcpcd_handlesigs[i]; i++) {
+		if (sigaction(dhcpcd_handlesigs[i], &sa, NULL) == -1)
 			return -1;
 	}
 	return 0;
@@ -957,7 +951,8 @@
 #endif
 
 int
-handle_args(struct dhcpcd_ctx *ctx, struct fd_list *fd, int argc, char **argv)
+dhcpcd_handleargs(struct dhcpcd_ctx *ctx, struct fd_list *fd,
+    int argc, char **argv)
 {
 	struct interface *ifp;
 	int do_exit = 0, do_release = 0, do_reboot = 0;
@@ -1083,7 +1078,7 @@
 			return 0;
 		}
 		for (oi = optind; oi < argc; oi++) {
-			if ((ifp = find_interface(ctx, argv[oi])) == NULL)
+			if ((ifp = if_find(ctx, argv[oi])) == NULL)
 				continue;
 			if (do_release) {
 				ifp->options->options |= DHCPCD_RELEASE;
@@ -1455,7 +1450,7 @@
 
 	ctx.ifaces = if_discover(&ctx, ctx.ifc, ctx.ifv);
 	for (i = 0; i < ctx.ifc; i++) {
-		if (find_interface(&ctx, ctx.ifv[i]) == NULL)
+		if (if_find(&ctx, ctx.ifv[i]) == NULL)
 			syslog(LOG_ERR, "%s: interface not found or invalid",
 			    ctx.ifv[i]);
 	}
@@ -1471,7 +1466,7 @@
 		}
 	}
 
-	if (ctx.options & DHCPCD_BACKGROUND && daemonise(&ctx))
+	if (ctx.options & DHCPCD_BACKGROUND && dhcpcd_daemonise(&ctx))
 		goto exit_success;
 
 	opt = 0;
@@ -1493,7 +1488,7 @@
 			ts.tv_nsec = 0;
 			nanosleep(&ts, NULL);
 			TAILQ_FOREACH(ifp, ctx.ifaces, next) {
-				handle_carrier(&ctx, LINK_UNKNOWN, 0,
+				dhcpcd_handlecarrier(&ctx, LINK_UNKNOWN, 0,
 				    ifp->name);
 				if (ifp->carrier != LINK_DOWN) {
 					opt = 1;
@@ -1512,7 +1507,7 @@
 		    !(ctx.options & DHCPCD_WAITIP))
 		{
 			syslog(LOG_WARNING, "no interfaces have a carrier");
-			if (daemonise(&ctx))
+			if (dhcpcd_daemonise(&ctx))
 				goto exit_success;
 		} else if (t > 0) {
 			if (ctx.options & DHCPCD_IPV4LL)
@@ -1526,7 +1521,7 @@
 
 	sort_interfaces(&ctx);
 	TAILQ_FOREACH(ifp, ctx.ifaces, next) {
-		eloop_timeout_add_sec(ctx.eloop, 0, start_interface, ifp);
+		eloop_timeout_add_sec(ctx.eloop, 0, dhcpcd_startinterface, ifp);
 	}
 
 	i = eloop_start(&ctx);
--- a/dhcpcd.conf.5.in	Fri Apr 25 13:14:21 2014 +0000
+++ b/dhcpcd.conf.5.in	Mon Apr 28 12:02:12 2014 +0000
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd April 6, 2014
+.Dd April 28, 2014
 .Dt DHCPCD.CONF 5
 .Os
 .Sh NAME
@@ -173,6 +173,14 @@
 warns if a conflict is detected.
 If there is a conflict, it is only a problem if the conflicted IAIDs are
 used on the same network.
+.It Ic dhcp
+Enable DHCP on the interface, on by default.
+.It Ic dhcp6
+Enable DHCPv6 on the interface, on by default.
+.It Ic ipv4
+Enable IPv4 on the interface, on by default.
+.It Ic ipv6
+Enable IPv6 on the interface, on by default.
 .It Ic persistent
 .Nm dhcpcd
 normally de-configures the interface and configuration when it exits.
@@ -263,6 +271,8 @@
 space separated.
 IPv6RS should be disabled globally when requesting a Prefix Delegation like so:
 .Pp
+.D1 # Global settings, disable IPv4 and IPv6RS
+.D1 noipv4
 .D1 noipv6rs
 .D1 # Don't touch eth3 at all
 .D1 denyinterfaces eth3 
@@ -270,11 +280,11 @@
 .D1 interface eth0
 .D1 ia_pd 1 eth1/1 eth2/2
 .Pp
-.D1 # Disable automatic address configuration for eth1
+.D1 # Enable automatic address configuration for eth1
 .D1 # eth1 still gets a delegated prefix
 .D1 interface eth1
-.D1 noipv4
-.D1 noipv6
+.D1 ipv4
+.D1 ipv6rs
 .It Ic ipv4only
 Only configure IPv4.
 .It Ic ipv6only
--- a/dhcpcd.h	Fri Apr 25 13:14:21 2014 +0000
+++ b/dhcpcd.h	Mon Apr 28 12:02:12 2014 +0000
@@ -135,20 +135,19 @@
 };
 
 #ifdef USE_SIGNALS
-extern const int handle_sigs[];
+extern const int dhcpcd_handlesigs[];
 #endif
 
-pid_t daemonise(struct dhcpcd_ctx *);
+pid_t dhcpcd_daemonise(struct dhcpcd_ctx *);
 
-struct interface *find_interface(struct dhcpcd_ctx *, const char *);
-int handle_args(struct dhcpcd_ctx *, struct fd_list *, int, char **);
-void handle_carrier(struct dhcpcd_ctx *, int, unsigned int, const char *);
-void handle_interface(void *, int, const char *);
-void handle_hwaddr(struct dhcpcd_ctx *, const char *,
+int dhcpcd_handleargs(struct dhcpcd_ctx *, struct fd_list *, int, char **);
+void dhcpcd_handlecarrier(struct dhcpcd_ctx *, int, unsigned int, const char *);
+int dhcpcd_handleinterface(void *, int, const char *);
+void dhcpcd_handlehwaddr(struct dhcpcd_ctx *, const char *,
     const unsigned char *, uint8_t);
-void drop_interface(struct interface *, const char *);
-int select_profile(struct interface *, const char *);
+void dhcpcd_dropinterface(struct interface *, const char *);
+int dhcpcd_selectprofile(struct interface *, const char *);
 
-void start_interface(void *);
+void dhcpcd_startinterface(void *);
 
 #endif
--- a/if-bsd.c	Fri Apr 25 13:14:21 2014 +0000
+++ b/if-bsd.c	Mon Apr 28 12:02:12 2014 +0000
@@ -793,11 +793,11 @@
 				ifan = (struct if_announcemsghdr *)(void *)p;
 				switch(ifan->ifan_what) {
 				case IFAN_ARRIVAL:
-					handle_interface(ctx, 1,
+					dhcpcd_handleinterface(ctx, 1,
 					    ifan->ifan_name);
 					break;
 				case IFAN_DEPARTURE:
-					handle_interface(ctx, -1,
+					dhcpcd_handleinterface(ctx, -1,
 					    ifan->ifan_name);
 					break;
 				}
@@ -826,7 +826,7 @@
 					len = LINK_UNKNOWN;
 					break;
 				}
-				handle_carrier(ctx, len,
+				dhcpcd_handlecarrier(ctx, len,
 				    (unsigned int)ifm->ifm_flags, ifname);
 				break;
 			case RTM_DELETE:
@@ -870,7 +870,7 @@
 #endif
 					memcpy(&sdl, rti_info[RTAX_IFA],
 					    rti_info[RTAX_IFA]->sa_len);
-					handle_hwaddr(ctx, ifname,
+					dhcpcd_handlehwaddr(ctx, ifname,
 					    (const unsigned char*)CLLADDR(&sdl),
 					    sdl.sdl_alen);
 					break;
--- a/if-linux.c	Fri Apr 25 13:14:21 2014 +0000
+++ b/if-linux.c	Mon Apr 28 12:02:12 2014 +0000
@@ -412,7 +412,7 @@
 		case RTA_OIF:
 			idx = *(unsigned int *)RTA_DATA(rta);
 			if (if_indextoname(idx, ifn))
-				rt.iface = find_interface(ctx, ifn);
+				rt.iface = if_find(ctx, ifn);
 			break;
 		case RTA_PRIORITY:
 			metric = *(unsigned int *)RTA_DATA(rta);
@@ -457,7 +457,7 @@
 	ifa = NLMSG_DATA(nlm);
 	if (if_indextoname(ifa->ifa_index, ifn) == NULL)
 		return -1;
-	iface = find_interface(ctx, ifn);
+	iface = if_find(ctx, ifn);
 	if (iface == NULL)
 		return 1;
 	rta = (struct rtattr *) IFA_RTA(ifa);
@@ -533,10 +533,10 @@
 
 	TAILQ_FOREACH(ifp, ctx->ifaces, next) {
 		if (ifp->index == ifindex && strcmp(ifp->name, ifname)) {
-			handle_interface(ctx, -1, ifp->name);
+			dhcpcd_handleinterface(ctx, -1, ifp->name);
 			/* Let dev announce the interface for renaming */
 			if (!dev_listening(ctx))
-				handle_interface(ctx, 1, ifname);
+				dhcpcd_handleinterface(ctx, 1, ifname);
 			return 1;
 		}
 	}
@@ -594,7 +594,7 @@
 	}
 
 	if (nlm->nlmsg_type == RTM_DELLINK) {
-		handle_interface(ctx, -1, ifn);
+		dhcpcd_handleinterface(ctx, -1, ifn);
 		return 1;
 	}
 
@@ -603,7 +603,7 @@
 	 * To trigger a valid hardware address pickup we need to pretend
 	 * that that don't exist until they have one. */
 	if (ifi->ifi_flags & IFF_MASTER && !hwaddr) {
-		handle_interface(ctx, -1, ifn);
+		dhcpcd_handleinterface(ctx, -1, ifn);
 		return 1;
 	}
 
@@ -612,12 +612,12 @@
 		    return 1;
 
 	/* Check for a new interface */
-	ifp = find_interface(ctx, ifn);
+	ifp = if_find(ctx, ifn);
 	if (ifp == NULL) {
 		/* If are listening to a dev manager, let that announce
 		 * the interface rather than the kernel. */
 		if (dev_listening(ctx) < 1)
-			handle_interface(ctx, 1, ifn);
+			dhcpcd_handleinterface(ctx, 1, ifn);
 		return 1;
 	}
 
@@ -630,7 +630,8 @@
 			handle_hwaddr(ctx, ifn, RTA_DATA(hwaddr), l);
 	}
 
-	handle_carrier(ctx, ifi->ifi_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN,
+	dhcpcd_handlecarrier(ctx,
+	    ifi->ifi_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN,
 	    ifi->ifi_flags, ifn);
 	return 1;
 }
--- a/if-options.c	Fri Apr 25 13:14:21 2014 +0000
+++ b/if-options.c	Mon Apr 28 12:02:12 2014 +0000
@@ -85,6 +85,10 @@
 #define O_AUTHNOTREQUIRED	O_BASE + 27
 #define O_NODHCP		O_BASE + 28
 #define O_NODHCP6		O_BASE + 29
+#define O_DHCP			O_BASE + 30
+#define O_DHCP6			O_BASE + 31
+#define O_IPV4			O_BASE + 32
+#define O_IPV6			O_BASE + 33
 
 const struct option cf_options[] = {
 	{"background",      no_argument,       NULL, 'b'},
@@ -143,7 +147,9 @@
 	{"ipv6ra_own_default", no_argument,    NULL, O_IPV6RA_OWN_D},
 	{"ipv4only",        no_argument,       NULL, '4'},
 	{"ipv6only",        no_argument,       NULL, '6'},
+	{"ipv4",            no_argument,       NULL, O_IPV4},
 	{"noipv4",          no_argument,       NULL, O_NOIPV4},
+	{"ipv6",            no_argument,       NULL, O_IPV6},
 	{"noipv6",          no_argument,       NULL, O_NOIPV6},
 	{"noalias",         no_argument,       NULL, O_NOALIAS},
 	{"iaid",            required_argument, NULL, O_IAID},
@@ -162,7 +168,9 @@
 	{"authprotocol",    required_argument, NULL, O_AUTHPROTOCOL},
 	{"authtoken",       required_argument, NULL, O_AUTHTOKEN},
 	{"noauthrequired",  no_argument,       NULL, O_AUTHNOTREQUIRED},
+	{"dhcp",            no_argument,       NULL, O_DHCP},
 	{"nodhcp",          no_argument,       NULL, O_NODHCP},
+	{"dhcp6",           no_argument,       NULL, O_DHCP6},
 	{"nodhcp6",         no_argument,       NULL, O_NODHCP6},
 	{NULL,              0,                 NULL, '\0'}
 };
@@ -1100,9 +1108,15 @@
 		ifo->options &= ~DHCPCD_IPV4;
 		ifo->options |= DHCPCD_IPV6;
 		break;
+	case O_IPV4:
+		ifo->options |= DHCPCD_IPV4;
+		break;
 	case O_NOIPV4:
 		ifo->options &= ~DHCPCD_IPV4;
 		break;
+	case O_IPV6:
+		ifo->options |= DHCPCD_IPV6;
+		break;
 	case O_NOIPV6:
 		ifo->options &= ~DHCPCD_IPV6;
 		break;
@@ -1746,9 +1760,15 @@
 	case O_AUTHNOTREQUIRED:
 		ifo->auth.options &= ~DHCPCD_AUTH_REQUIRE;
 		break;
+	case O_DHCP:
+		ifo->options |= DHCPCD_DHCP | DHCPCD_IPV4;
+		break;
 	case O_NODHCP:
 		ifo->options &= ~DHCPCD_DHCP;
 		break;
+	case O_DHCP6:
+		ifo->options |= DHCPCD_DHCP6 | DHCPCD_IPV6;
+		break;
 	case O_NODHCP6:
 		ifo->options &= ~DHCPCD_DHCP6;
 		break;
--- a/if.c	Fri Apr 25 13:14:21 2014 +0000
+++ b/if.c	Mon Apr 28 12:02:12 2014 +0000
@@ -482,6 +482,20 @@
 	return ifs;
 }
 
+struct interface *
+if_find(struct dhcpcd_ctx *ctx, const char *ifname)
+{
+	struct interface *ifp;
+
+	if (ctx != NULL && ctx->ifaces != NULL) {
+		TAILQ_FOREACH(ifp, ctx->ifaces, next) {
+			if (strcmp(ifp->name, ifname) == 0)
+				return ifp;
+		}
+	}
+	return NULL;
+}
+
 int
 if_domtu(const char *ifname, short int mtu)
 {
--- a/if.h	Fri Apr 25 13:14:21 2014 +0000
+++ b/if.h	Mon Apr 28 12:02:12 2014 +0000
@@ -81,6 +81,7 @@
 #endif
 
 struct if_head *if_discover(struct dhcpcd_ctx *, int, char * const *);
+struct interface *if_find(struct dhcpcd_ctx *, const char *);
 void if_free(struct interface *);
 int if_domtu(const char *, short int);
 #define if_getmtu(iface) if_domtu(iface, 0)
--- a/ipv6.c	Fri Apr 25 13:14:21 2014 +0000
+++ b/ipv6.c	Mon Apr 28 12:02:12 2014 +0000
@@ -746,7 +746,7 @@
 			break;
 		case RTM_NEWADDR:
 			/* Safety - ignore tentative announcements */
-			if (flags & IN6_IFF_TENTATIVE)
+			if (flags & (IN6_IFF_DETACHED |IN6_IFF_TENTATIVE))
 				break;
 			if ((ap->flags & IPV6_AF_DADCOMPLETED) == 0) {
 				found++;
--- a/ipv6nd.c	Fri Apr 25 13:14:21 2014 +0000
+++ b/ipv6nd.c	Mon Apr 28 12:02:12 2014 +0000
@@ -483,7 +483,7 @@
 	pid = 0;
 	if (hasdns && (hasaddress ||
 	    !(rap->flags & (ND_RA_FLAG_MANAGED | ND_RA_FLAG_OTHER))))
-		pid = daemonise(rap->iface->ctx);
+		pid = dhcpcd_daemonise(rap->iface->ctx);
 #if 0
 	else if (options & DHCPCD_DAEMONISE &&
 	    !(options & DHCPCD_DAEMONISED) && new_data)
--- a/script.c	Fri Apr 25 13:14:21 2014 +0000
+++ b/script.c	Mon Apr 28 12:02:12 2014 +0000
@@ -108,8 +108,8 @@
 	flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF;
 	posix_spawnattr_setflags(&attr, flags);
 	sigemptyset(&defsigs);
-	for (i = 0; i < handle_sigs[i]; i++)
-		sigaddset(&defsigs, handle_sigs[i]);
+	for (i = 0; i < dhcpcd_handlesigs[i]; i++)
+		sigaddset(&defsigs, dhcpcd_handlesigs[i]);
 	posix_spawnattr_setsigdefault(&attr, &defsigs);
 	posix_spawnattr_setsigmask(&attr, &ctx->sigset);
 #endif