changeset 968:fda8caac3a0c draft

Add allowinterfaces and denyinterfaces options to dhcpcd.conf for better multiple interface support.
author Roy Marples <roy@marples.name>
date Thu, 11 Sep 2008 09:38:02 +0000
parents 862f53237052
children f5c92b2d9e46
files dhcpcd.8.in dhcpcd.c dhcpcd.conf.5.in dhcpcd.h if-linux.c if-options.c if-options.h net.c
diffstat 8 files changed, 150 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/dhcpcd.8.in	Thu Sep 11 08:28:39 2008 +0000
+++ b/dhcpcd.8.in	Thu Sep 11 09:38:02 2008 +0000
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd September 3, 2008
+.Dd September 11, 2008
 .Dt DHCPCD 8 SMM
 .Sh NAME
 .Nm dhcpcd
@@ -42,12 +42,14 @@
 .Op Fl t , -timeout Ar seconds
 .Op Fl u , -userclass Ar class
 .Op Fl v , -vendor Ar code , Ar value
+.Op Fl z , -allowinterfaces Ar pattern
 .Op Fl C , -nohook Ar hook
 .Op Fl F , -fqdn Ar FQDN
 .Op Fl I , -clientid Ar clientid
 .Op Fl O , -nooption Ar option
 .Op Fl Q , -require Ar option
 .Op Fl X , -blacklist Ar address
+.Op Fl Z , -denyinterfaces Ar pattern
 .Op interface
 .Op ...
 .Nm
@@ -104,8 +106,10 @@
 If a list of interfaces are given on the command line, then
 .Nm
 only works with those interfaces.
-If no interfaces are given then we detect all available interfaces and
+If no interfaces are given then we discover available interfaces and
 attempt to configure all of them.
+See options below for controlling what interfaces we allow and deny through
+the use of patterns.
 .Ss Hooking into DHCP events
 .Nm
 runs
@@ -349,6 +353,14 @@
 .Nm
 on the command line, only warnings and errors will be displayed.
 The messages are still logged though.
+.It Fl z , -allowinterfaces Ar pattern
+When discovering interfaces, the interface name must match
+.Ar pattern
+which is a space or comma separated list of patterns passed to
+.Xr fnmatch 3 .
+If the same interface is matched in
+.Fl Z , -denyinterfaces
+then it is still denied.
 .It Fl A , -noarp
 Don't request or claim the address by ARP.
 This also disables IPv4LL.
@@ -397,6 +409,11 @@
 This may be expanded in future releases to ignore all packets
 matching either the IP or hardware
 .Ar address .
+.It Fl Z , -denyinterfaces Ar pattern
+When discovering interfaces, the interface name must not match
+.Ar pattern
+which is a space or comma separated list of patterns passed to
+.Xr fnmatch 3 .
 .El
 .Sh NOTES
 .Nm
@@ -430,6 +447,7 @@
 .Xr dhcpcd-run-hooks 8 ,
 .Xr resolv.conf 5 ,
 .Xr resolvconf 8 ,
+.Xr fnmatch 3
 .Sh STANDARDS
 RFC 2131, RFC 2132, RFC 2855, RFC 3004, RFC 3361, RFC 3396, RFC 3397,
 RFC 3442, RFC 3927, RFC 4361, RFC 4390, RFC 4702.
--- a/dhcpcd.c	Thu Sep 11 08:28:39 2008 +0000
+++ b/dhcpcd.c	Thu Sep 11 09:38:02 2008 +0000
@@ -68,6 +68,10 @@
 int options = 0;
 int pidfd = -1;
 struct interface *ifaces = NULL;
+int ifac = 0;
+char **ifav = NULL;
+int ifdc = 0;
+char **ifdv = NULL;
 
 static char **ifv = NULL;
 static int ifc = 0;
@@ -134,12 +138,20 @@
 {
 #ifdef DEBUG_MEMORY
 	struct interface *iface;
+	int i;
 
 	while (ifaces) {
 		iface = ifaces;
 		ifaces = iface->next;
 		free_interface(iface);
 	}
+
+	for (i = 0; i < ifac; i++)
+		free(ifav[i]);
+	free(ifav);
+	for (i = 0; i < ifdc; i++)
+		free(ifdv[i]);
+	free(ifdv);
 #endif
 
 	if (linkfd != -1)
@@ -986,7 +998,6 @@
 	closefrom(3);
 	openlog(PACKAGE, LOG_PERROR, LOG_DAEMON);
 	setlogmask(LOG_UPTO(LOG_INFO));
-	options = DHCPCD_DAEMONISE;
 
 	/* Test for --help and --version */
 	if (argc > 1) {
@@ -999,6 +1010,7 @@
 		}
 	}
 
+	i = 0;
 	while ((opt = getopt_long(argc, argv, IF_OPTS, cf_options, &oi)) != -1)
 	{
 		switch (opt) {
@@ -1018,7 +1030,7 @@
 			sig = SIGTERM;
 			break;
 		case 'T':
-			options |= DHCPCD_TEST | DHCPCD_PERSISTENT;
+			i = 1;
 			break;
 		case 'V':
 			print_options();
@@ -1036,12 +1048,15 @@
 			usage();
 		exit(EXIT_FAILURE);
 	}
+	options = ifo->options;
+	if (i)
+		options |= DHCPCD_TEST | DHCPCD_PERSISTENT;
 
 #ifdef THERE_IS_NO_FORK
 	options &= ~DHCPCD_DAEMONISE;
 #endif
 
-	if (ifo->options & DHCPCD_QUIET)
+	if (options & DHCPCD_QUIET)
 		setlogmask(LOG_UPTO(LOG_WARNING));
 
 	/* If we have any other args, we should run as a single dhcpcd instance
--- a/dhcpcd.conf.5.in	Thu Sep 11 08:28:39 2008 +0000
+++ b/dhcpcd.conf.5.in	Thu Sep 11 09:38:02 2008 +0000
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd August 18, 2008
+.Dd September 11, 2008
 .Dt DHCPCD.CONF 5 SMM
 .Sh NAME
 .Nm dhcpcd.conf
@@ -43,6 +43,19 @@
 .Pp
 Here's a list of available options:
 .Bl -tag -width indent
+.It Ic allowinterfaces Ar pattern
+When discovering interfaces, the interface name must match
+.Ar pattern
+which is a space or comma separated list of patterns passed to
+.Xr fnmatch 3 .
+If the same interface is matched in
+.Ic denyinterfaces
+then it is still denied.
+.It Ic denyinterfaces Ar pattern
+When discovering interfaces, the interface name must not match
+.Ar pattern
+which is a space or comma separated list of patterns passed to
+.Xr fnmatch 3 .
 .It Ic background
 Background immediately.
 This is useful for startup scripts which don't disable link messages for
@@ -148,7 +161,8 @@
 .El
 .Sh SEE ALSO
 .Xr dhcpcd-run-hooks 8 ,
-.Xr dhcpcd 8
+.Xr dhcpcd 8 ,
+.Xr fnmatch 3
 .Sh AUTHORS
 .An Roy Marples <roy@marples.name>
 .Sh BUGS
--- a/dhcpcd.h	Thu Sep 11 08:28:39 2008 +0000
+++ b/dhcpcd.h	Thu Sep 11 09:38:02 2008 +0000
@@ -106,6 +106,10 @@
 
 extern int pidfd;
 extern int options;
+extern int ifac;
+extern char **ifav;
+extern int ifdc;
+extern char **ifdv;
 extern struct interface *ifaces;
 
 int handle_args(int, char **);
--- a/if-linux.c	Thu Sep 11 08:28:39 2008 +0000
+++ b/if-linux.c	Thu Sep 11 09:38:02 2008 +0000
@@ -41,6 +41,7 @@
 
 #include <errno.h>
 #include <ctype.h>
+#include <fnmatch.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -397,7 +398,6 @@
 	FILE *f;
 	char *buffer = NULL, *p;
 	size_t len = 0, ln = 0, n;
-	int i;
 	struct interface *ifs = NULL, *ifp, *ifl;
 
 	if ((f = fopen("/proc/net/dev", "r"))) {
@@ -418,10 +418,21 @@
 			if (ifp)
 				continue;
 			if (argc > 0) {
-				for (i = 0; i < argc; i++)
-					if (strcmp(argv[i], p) == 0)
+				for (n = 0; n < argc; n++)
+					if (strcmp(argv[n], p) == 0)
 						break;
-				if (i == argc)
+				if (n == argc)
+					continue;
+			} else {
+				for (n = 0; n < ifdc; n++)
+					if (!fnmatch(ifdv[n], ifr->ifr_name, 0))
+						break;
+				if (n < ifdc)
+					continue;
+				for (n = 0; n < ifac; n++)
+					if (!fnmatch(ifav[n], ifr->ifr_name, 0))
+						break;
+				if (ifac && n == ifac)
 					continue;
 			}
 			if ((ifp = init_interface(p))) {
--- a/if-options.c	Thu Sep 11 08:28:39 2008 +0000
+++ b/if-options.c	Thu Sep 11 09:38:02 2008 +0000
@@ -51,41 +51,43 @@
 #define OPTS "bc:df:h:i:kl:m:no:pqr:s:t:u:v:xABC:DEF:GI:KLO:Q:TVX:"
 
 const struct option cf_options[] = {
-	{"background",    no_argument,        NULL, 'b'},
-	{"script",        required_argument,  NULL, 'c'},
-	{"debug",         no_argument,        NULL, 'd'},
-	{"config",        required_argument,  NULL, 'f'},
-	{"hostname",      optional_argument,  NULL, 'h'},
-	{"vendorclassid", optional_argument,  NULL, 'i'},
-	{"release",       no_argument,        NULL, 'k'},
-	{"leasetime",     required_argument,  NULL, 'l'},
-	{"metric",        required_argument,  NULL, 'm'},
-	{"rebind",        no_argument,        NULL, 'n'},
-	{"option",        required_argument,  NULL, 'o'},
-	{"persistent",    no_argument,        NULL, 'p'},
-	{"quiet",         no_argument,        NULL, 'q'},
-	{"request",       optional_argument,  NULL, 'r'},
-	{"inform",        optional_argument,  NULL, 's'},
-	{"timeout",       required_argument,  NULL, 't'},
-	{"userclass",     required_argument,  NULL, 'u'},
-	{"vendor",        required_argument,  NULL, 'v'},
-	{"exit",          no_argument,        NULL, 'x'},
-	{"noarp",         no_argument,        NULL, 'A'},
-	{"nobackground",  no_argument,        NULL, 'B'},
-	{"nohook",	  required_argument,  NULL, 'C'},
-	{"duid",          no_argument,        NULL, 'D'},
-	{"lastlease",     no_argument,        NULL, 'E'},
-	{"fqdn",          optional_argument,  NULL, 'F'},
-	{"nogateway",     no_argument,        NULL, 'G'},
-	{"clientid",      optional_argument,  NULL, 'I'},
-	{"nolink",        no_argument,        NULL, 'K'},
-	{"noipv4ll",      no_argument,        NULL, 'L'},
-	{"nooption",      optional_argument,  NULL, 'O'},
-	{"require",       required_argument,  NULL, 'Q'},
-	{"test",          no_argument,        NULL, 'T'},
-	{"variables",     no_argument,        NULL, 'V'},
-	{"blacklist",     required_argument,  NULL, 'X'},
-	{NULL,            0,                  NULL, '\0'}
+	{"background",      no_argument,       NULL, 'b'},
+	{"script",          required_argument, NULL, 'c'},
+	{"debug",           no_argument,       NULL, 'd'},
+	{"config",          required_argument, NULL, 'f'},
+	{"hostname",        optional_argument, NULL, 'h'},
+	{"vendorclassid",   optional_argument, NULL, 'i'},
+	{"release",         no_argument,       NULL, 'k'},
+	{"leasetime",       required_argument, NULL, 'l'},
+	{"metric",          required_argument, NULL, 'm'},
+	{"rebind",          no_argument,       NULL, 'n'},
+	{"option",          required_argument, NULL, 'o'},
+	{"persistent",      no_argument,       NULL, 'p'},
+	{"quiet",           no_argument,       NULL, 'q'},
+	{"request",         optional_argument, NULL, 'r'},
+	{"inform",          optional_argument, NULL, 's'},
+	{"timeout",         required_argument, NULL, 't'},
+	{"userclass",       required_argument, NULL, 'u'},
+	{"vendor",          required_argument, NULL, 'v'},
+	{"exit",            no_argument,       NULL, 'x'},
+	{"allowinterfaces", required_argument, NULL, 'z'},
+	{"noarp",           no_argument,       NULL, 'A'},
+	{"nobackground",    no_argument,       NULL, 'B'},
+	{"nohook",          required_argument, NULL, 'C'},
+	{"duid",            no_argument,       NULL, 'D'},
+	{"lastlease",       no_argument,       NULL, 'E'},
+	{"fqdn",            optional_argument, NULL, 'F'},
+	{"nogateway",       no_argument,       NULL, 'G'},
+	{"clientid",        optional_argument, NULL, 'I'},
+	{"nolink",          no_argument,       NULL, 'K'},
+	{"noipv4ll",        no_argument,       NULL, 'L'},
+	{"nooption",        optional_argument, NULL, 'O'},
+	{"require",         required_argument, NULL, 'Q'},
+	{"test",            no_argument,       NULL, 'T'},
+	{"variables",       no_argument,       NULL, 'V'},
+	{"blacklist",       required_argument, NULL, 'X'},
+	{"denyinterfaces",  required_argument, NULL, 'Z'},
+	{NULL,              0,                 NULL, '\0'}
 };
 
 static int
@@ -248,6 +250,22 @@
 	return l;
 }
 
+static char **
+splitv(int *argc, char **argv, const char *arg)
+{
+	char **v = argv;
+	char *o = xstrdup(arg), *p, *t;
+
+	p = o;
+	while ((t = strsep(&p, ", "))) {
+		(*argc)++;
+		v = xrealloc(v, *argc);
+		v[(*argc) - 1] = xstrdup(t);
+	}
+	free(o);
+	return v;	
+}
+
 static int
 parse_option(struct if_options *ifo, int opt, const char *arg)
 {
@@ -417,6 +435,11 @@
 			ifo->vendor[0] += s + 2;
 		}
 		break;
+	case 'z':
+		/* We only set this if we haven't got any interfaces */
+		if (!ifaces)
+			ifav = splitv(&ifac, ifav, arg);
+		break;
 	case 'A':
 		ifo->options &= ~DHCPCD_ARP;
 		/* IPv4LL requires ARP */
@@ -514,6 +537,11 @@
 		ifo->blacklist[ifo->blacklist_len] = addr.s_addr;
 		ifo->blacklist_len++;
 		break;
+	case 'Z':
+		/* We only set this if we haven't got any interfaces */
+		if (!ifaces)
+			ifdv = splitv(&ifdc, ifdv, arg);
+		break;
 	default:
 		return 0;
 	}
--- a/if-options.h	Thu Sep 11 08:28:39 2008 +0000
+++ b/if-options.h	Thu Sep 11 09:38:02 2008 +0000
@@ -36,8 +36,8 @@
 #include <limits.h>
 
 /* Don't set any optional arguments here so we retain POSIX
- *  * compatibility with getopt */
-#define IF_OPTS "bc:df:h:i:kl:m:no:pqr:s:t:u:v:xABC:DEF:GI:KLO:Q:TVX:"
+ * compatibility with getopt */
+#define IF_OPTS "bc:df:h:i:kl:m:no:pqr:s:t:u:v:xz:ABC:DEF:GI:KLO:Q:TVX:Z:"
 
 #define DEFAULT_TIMEOUT		30
 #define DEFAULT_LEASETIME	3600	/* 1 hour */
--- a/net.c	Thu Sep 11 08:28:39 2008 +0000
+++ b/net.c	Thu Sep 11 09:38:02 2008 +0000
@@ -61,6 +61,7 @@
 
 #include <ctype.h>
 #include <errno.h>
+#include <fnmatch.h>
 #include <stddef.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -398,6 +399,17 @@
 						break;
 				if (n == argc)
 					continue;
+			} else {
+				for (n = 0; n < ifdc; n++)
+					if (!fnmatch(ifdv[n], ifr->ifr_name, 0))
+						break;
+				if (n < ifdc)
+					continue;
+				for (n = 0; n < ifac; n++)
+					if (!fnmatch(ifav[n], ifr->ifr_name, 0))
+						break;
+				if (ifac && n == ifac)
+					continue;
 			}
 			ifn = init_interface(ifr->ifr_name);
 			if (!ifn)