dhcpcd-discuss

[RFC PATCH v3] Add option to omit link configuration for IPv4

Philipp Gesang

Mon Jan 30 08:46:37 2017

Adds a command line option --noconfigure and checks at relevant
locations immediately before calling out into platform specific
code to configure a link.

This patch is incomplete in that it only covers the bits dealing
with IPv4.

Signed-off-by: Philipp Gesang <philipp.gesang@xxxxxxxxxxxxx>
---
 dhcp.c           |  2 +-
 dhcpcd.8.in      | 16 ++++++++++++++++
 dhcpcd.conf.5.in | 20 +++++++++++++++-----
 if-linux.c       |  6 ++++++
 if-options.c     | 10 +++++++++-
 if-options.h     |  1 +
 ipv4.c           | 29 ++++++++++++++++++++---------
 route.c          |  4 ++++
 8 files changed, 72 insertions(+), 16 deletions(-)

diff --git a/dhcp.c b/dhcp.c
index f2ee5044..37c98863 100644
--- a/dhcp.c
+++ b/dhcp.c
@@ -760,7 +760,7 @@ make_message(struct bootp **bootpm, const struct interface *ifp, uint8_t type)
 	if ((mtu = if_getmtu(ifp)) == -1)
 		logger(ifp->ctx, LOG_ERR,
 		    "%s: if_getmtu: %m", ifp->name);
-	else if (mtu < MTU_MIN) {
+	else if (mtu < MTU_MIN && ifo->options & DHCPCD_CONFIGURE_LINK) {
 		if (if_setmtu(ifp, MTU_MIN) == -1)
 			logger(ifp->ctx, LOG_ERR,
 			    "%s: if_setmtu: %m", ifp->name);
diff --git a/dhcpcd.8.in b/dhcpcd.8.in
index 6fccbdca..222f515b 100644
--- a/dhcpcd.8.in
+++ b/dhcpcd.8.in
@@ -60,6 +60,7 @@
 .Op Fl Z , Fl Fl denyinterfaces Ar pattern
 .Op Fl z , Fl Fl allowinterfaces Ar pattern
 .Op Fl Fl inactive
+.Op Fl Fl noconfigure
 .Op interface
 .Op ...
 .Nm
@@ -193,6 +194,11 @@ To force starting in Master mode with only one interface, the
 .Fl M , Fl Fl master
 option can be used.
 .Pp
+Note that when active on a single interface or a list of interfaces,
+.Nm
+will still affect interfaces not specified to prevent conflicts of a lease
+with their configuration.
+.Pp
 Interfaces are preferred by carrier, DHCP lease/IPv4LL and then lowest metric.
 For systems that support route metrics, each route will be tagged with the
 metric, otherwise
@@ -715,6 +721,16 @@ commands to start each interface as required.
 Don't load any
 .Pa /dev
 management modules.
+.It Fl Fl noconfigure
+Don't change the configuration of any interfaces and routes. Normally,
+.Nm
+will apply a lease it receives to the respective interface and resolve
+potential conflicts by removing addresses from other interfaces. Use
+.Fl Fl noconfigure
+if the link configuration is handled elsewhere, for example by another process
+that receives the lease data from the script.
+.Pp
+Currently affects only DHCPv4.
 .El
 .Sh 3RDPARTY LINK MANAGEMENT
 Some interfaces require configuration by 3rd parties, such as PPP or VPN.
diff --git a/dhcpcd.conf.5.in b/dhcpcd.conf.5.in
index d8176c0e..5e378d21 100644
--- a/dhcpcd.conf.5.in
+++ b/dhcpcd.conf.5.in
@@ -453,6 +453,16 @@ 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 noconfigure
+Don't change the configuration of any interfaces and routes. Normally,
+.Nm dhcpcd
+will apply a lease it receives to the respective interface and resolve
+potential conflicts by removing addresses from other interfaces. Use
+.Fl Fl noconfigure
+if the link configuration is handled elsewhere, for example by another process
+that receives the lease data from the script.
+.Pp
+Currently affects only DHCPv4.
 .It Ic nodelay
 Don't delay for an initial randomised time when starting protocols.
 .It Ic nodev
@@ -496,9 +506,9 @@ You should only set this for buggy interface drivers.
 .It Ic noup
 Don't bring the interface up when in master mode.
 If
-.Nm
+.Nm dhcpcd
 cannot determine the carrier state,
-.Nm
+.Nm dhcpcd
 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
@@ -555,7 +565,7 @@ This is useful when you cannot use
 to select / de-select BOOTP messages.
 .It Ic destination Ar option
 If
-.Nm
+.Nm dhcpcd
 detects an address added to a point to point interface (PPP, TUN, etc) then
 it will set the listed DHCP options to the destination address of the
 interface.
@@ -695,10 +705,10 @@ Wait for an address to be assigned before forking to the background.
 4 means wait for an IPv4 address to be assigned.
 6 means wait for an IPv6 address to be assigned.
 If no argument is given,
-.Nm
+.Nm dhcpcd
 will wait for any address protocol to be assigned.
 It is possible to wait for more than one address protocol and
-.Nm
+.Nm dhcpcd
 will only fork to the background when all waiting conditions are satisfied.
 .It Ic xidhwaddr
 Use the last four bytes of the hardware address as the DHCP xid instead
diff --git a/if-linux.c b/if-linux.c
index 26f4d3ca..1957c6a8 100644
--- a/if-linux.c
+++ b/if-linux.c
@@ -226,6 +226,12 @@ if_init(struct interface *ifp)
 		return errno == ENOENT ? 0 : -1;
 	if (n == 1)
 		return 0;
+	if (!(ifp->ctx->options & DHCPCD_CONFIGURE_LINK)) {
+		logger(ifp->ctx, LOG_DEBUG,
+		       "%s: leaving IPv4 sysctl promote_secondaries unset",
+		       ifp->name);
+		return 0;
+	}
 	return write_path(path, "1") == -1 ? -1 : 0;
 }
 
diff --git a/if-options.c b/if-options.c
index 7dd6a439..44340a93 100644
--- a/if-options.c
+++ b/if-options.c
@@ -104,6 +104,7 @@
 #define O_LASTLEASE_EXTEND	O_BASE + 46
 #define O_INACTIVE		O_BASE + 47
 #define	O_MUDURL		O_BASE + 48
+#define	O_NOCONFIGURE		O_BASE + 49
 
 const struct option cf_options[] = {
 	{"background",      no_argument,       NULL, 'b'},
@@ -205,6 +206,7 @@ const struct option cf_options[] = {
 	{"lastleaseextend", no_argument,       NULL, O_LASTLEASE_EXTEND},
 	{"inactive",        no_argument,       NULL, O_INACTIVE},
 	{"mudurl",          required_argument, NULL, O_MUDURL},
+	{"noconfigure",     no_argument,       NULL, O_NOCONFIGURE},
 	{NULL,              0,                 NULL, '\0'}
 };
 
@@ -2146,6 +2148,11 @@ err_sla:
 		}
 		*ifo->mudurl = (uint8_t)s;
 		break;
+	case O_NOCONFIGURE:
+		logger(ctx, LOG_DEBUG,
+                       "noconfigure: suppressing link configuration");
+		ifo->options &= ~DHCPCD_CONFIGURE_LINK;
+		break;
 	default:
 		return 0;
 	}
@@ -2251,7 +2258,8 @@ default_config(struct dhcpcd_ctx *ctx)
 		logger(ctx, LOG_ERR, "%s: %m", __func__);
 		return NULL;
 	}
-	ifo->options |= DHCPCD_IF_UP | DHCPCD_LINK | DHCPCD_INITIAL_DELAY;
+	ifo->options |= DHCPCD_IF_UP | DHCPCD_LINK | DHCPCD_INITIAL_DELAY
+		| DHCPCD_CONFIGURE_LINK;
 	ifo->timeout = DEFAULT_TIMEOUT;
 	ifo->reboot = DEFAULT_REBOOT;
 	ifo->metric = -1;
diff --git a/if-options.h b/if-options.h
index 3f2eb04d..93216f66 100644
--- a/if-options.h
+++ b/if-options.h
@@ -118,6 +118,7 @@
 #define DHCPCD_PRINT_PIDFILE		(1ULL << 59)
 #define DHCPCD_ONESHOT			(1ULL << 60)
 #define DHCPCD_INACTIVE			(1ULL << 61)
+#define DHCPCD_CONFIGURE_LINK		(1ULL << 62)
 
 #define DHCPCD_NODROP	(DHCPCD_EXITING | DHCPCD_PERSISTENT)
 
diff --git a/ipv4.c b/ipv4.c
index 57a19dfe..bdddcbc2 100644
--- a/ipv4.c
+++ b/ipv4.c
@@ -465,6 +465,12 @@ ipv4_deladdr(struct ipv4_addr *addr, int keeparp)
 	UNUSED(keeparp);
 #endif
 
+	if (!(addr->iface->ctx->options & DHCPCD_CONFIGURE_LINK)) {
+		logger(addr->iface->ctx, LOG_DEBUG,
+		       "%s: noconfigure: not deleting IP address %s",
+		       addr->iface->name, addr->saddr);
+		return 0;
+	}
 	logger(addr->iface->ctx, LOG_DEBUG,
 	    "%s: deleting IP address %s", addr->iface->name, addr->saddr);
 
@@ -638,15 +644,20 @@ ipv4_addaddr(struct interface *ifp, const struct in_addr *addr,
 		    ia->alias, ia->saddr);
 #endif
 
-	logger(ifp->ctx, LOG_DEBUG, "%s: adding IP address %s broadcast %s",
-	    ifp->name, ia->saddr, inet_ntoa(*bcast));
-	if (if_address(RTM_NEWADDR, ia) == -1) {
-		if (errno != EEXIST)
-			logger(ifp->ctx, LOG_ERR, "%s: if_addaddress: %m",
-			    __func__);
-		free(ia);
-		return NULL;
-	}
+	if (ifp->options->options & DHCPCD_CONFIGURE_LINK) {
+		logger(ifp->ctx, LOG_DEBUG, "%s: adding IP address %s broadcast %s",
+		       ifp->name, ia->saddr, inet_ntoa(*bcast));
+		if (if_address(RTM_NEWADDR, ia) == -1) {
+			if (errno != EEXIST)
+				logger(ifp->ctx, LOG_ERR, "%s: if_addaddress: %m",
+				       __func__);
+			free(ia);
+			return NULL;
+		}
+	} else
+		logger(ifp->ctx, LOG_DEBUG,
+		       "%s: noconfigure: skipping IP address %s broadcast %s",
+		       ifp->name, ia->saddr, inet_ntoa(*bcast));
 
 #ifdef ALIAS_ADDR
 	if (replaced) {
diff --git a/route.c b/route.c
index 1e6bd84e..3da6cde9 100644
--- a/route.c
+++ b/route.c
@@ -290,6 +290,8 @@ rt_add(struct rt *nrt, struct rt *ort)
 	    sa_is_unspecified(&nrt->rt_dest) &&
 	    sa_is_unspecified(&nrt->rt_netmask))
 		return false;
+	if (!(options & DHCPCD_CONFIGURE_LINK))
+		return false;
 
 	rt_desc(ort == NULL ? "adding" : "changing", nrt);
 
@@ -394,6 +396,8 @@ rt_delete(struct rt *rt)
 {
 	int retval;
 
+	if (!(rt->rt_ifp->options->options &  DHCPCD_CONFIGURE_LINK))
+		return false;
 	rt_desc("deleting", rt);
 	retval = if_route(RTM_DELETE, rt) == -1 ? false : true;
 	if (!retval && errno != ENOENT && errno != ESRCH)
-- 
2.11.0


References:
Re: [RFC PATCH v2] Add option to omit link configuration for IPv4Roy Marples
Archive administrator: postmaster@marples.name