Blame SOURCES/autofs-5.0.9-amd-lookup-add-selector-handling.patch

306fa1
autofs-5.0.9 - amd lookup add selector handling
306fa1
306fa1
From: Ian Kent <raven@themaw.net>
306fa1
306fa1
306fa1
---
306fa1
 include/parse_subs.h |    2 
306fa1
 lib/parse_subs.c     |  127 ++++++++++++++++++
306fa1
 modules/amd_parse.y  |   49 ++++++-
306fa1
 modules/amd_tok.l    |   73 ++++++++++
306fa1
 modules/parse_amd.c  |  348 ++++++++++++++++++++++++++++++++++++++++++++++++++
306fa1
 5 files changed, 586 insertions(+), 13 deletions(-)
306fa1
306fa1
diff --git a/include/parse_subs.h b/include/parse_subs.h
306fa1
index a416c59..43da182 100644
306fa1
--- a/include/parse_subs.h
306fa1
+++ b/include/parse_subs.h
306fa1
@@ -111,6 +111,8 @@ struct map_type_info {
306fa1
 };
306fa1
 
306fa1
 unsigned int get_proximity(struct sockaddr *);
306fa1
+unsigned int get_network_proximity(const char *);
306fa1
+unsigned int in_network(char *);
306fa1
 const char *skipspace(const char *);
306fa1
 int check_colon(const char *);
306fa1
 int chunklen(const char *, int);
306fa1
diff --git a/lib/parse_subs.c b/lib/parse_subs.c
306fa1
index f485a4c..de5319f 100644
306fa1
--- a/lib/parse_subs.c
306fa1
+++ b/lib/parse_subs.c
306fa1
@@ -19,9 +19,13 @@
306fa1
 #include <string.h>
306fa1
 #include <ctype.h>
306fa1
 #include <sys/types.h>
306fa1
+#include <sys/socket.h>
306fa1
 #include <ifaddrs.h>
306fa1
 #include <libgen.h>
306fa1
 #include <net/if.h>
306fa1
+#include <arpa/inet.h>
306fa1
+#include <netdb.h>
306fa1
+
306fa1
 #include "automount.h"
306fa1
 
306fa1
 #define MAX_OPTIONS_LEN		256
306fa1
@@ -370,6 +374,129 @@ unsigned int get_proximity(struct sockaddr *host_addr)
306fa1
 	return PROXIMITY_OTHER;
306fa1
 }
306fa1
 
306fa1
+static char *inet_fill_net(const char *net_num, char *net)
306fa1
+{
306fa1
+	char *np;
306fa1
+	unsigned int dots = 3;
306fa1
+
306fa1
+	if (strlen(net_num) > INET_ADDRSTRLEN)
306fa1
+		return NULL;
306fa1
+
306fa1
+	if (!isdigit(*net_num))
306fa1
+		return NULL;
306fa1
+
306fa1
+	*net = '\0';
306fa1
+	strcpy(net, net_num);
306fa1
+
306fa1
+	np = net;
306fa1
+	while (*np++) {
306fa1
+		if (*np == '.') {
306fa1
+			np++;
306fa1
+			dots--;
306fa1
+			if (!*np && dots)
306fa1
+				strcat(net, "0");
306fa1
+			continue;
306fa1
+		}
306fa1
+
306fa1
+		if ((*np && !isdigit(*np)) || dots < 0) {
306fa1
+			*net = '\0';
306fa1
+			return NULL;
306fa1
+		}
306fa1
+	}
306fa1
+
306fa1
+	while (dots--)
306fa1
+		strcat(net, ".0");
306fa1
+
306fa1
+	return net;
306fa1
+}
306fa1
+
306fa1
+static char *get_network_number(const char *network)
306fa1
+{
306fa1
+	struct netent *netent;
306fa1
+	char cnet[MAX_NETWORK_LEN];
306fa1
+	uint32_t h_net;
306fa1
+	size_t len;
306fa1
+
306fa1
+	len = strlen(network) + 1;
306fa1
+	if (len > MAX_NETWORK_LEN)
306fa1
+		return NULL;
306fa1
+
306fa1
+	netent = getnetbyname(network);
306fa1
+	if (!netent)
306fa1
+		return NULL;
306fa1
+	h_net = ntohl(netent->n_net);
306fa1
+
306fa1
+	if (!inet_ntop(AF_INET, &h_net, cnet, INET_ADDRSTRLEN))
306fa1
+		return NULL;
306fa1
+
306fa1
+	return strdup(cnet);
306fa1
+}
306fa1
+
306fa1
+unsigned int get_network_proximity(const char *name)
306fa1
+{
306fa1
+	struct addrinfo hints;
306fa1
+	struct addrinfo *ni, *this;
306fa1
+	char name_or_num[NI_MAXHOST];
306fa1
+	unsigned int proximity;
306fa1
+	char *net;
306fa1
+	int ret;
306fa1
+
306fa1
+	if (!name)
306fa1
+		return PROXIMITY_ERROR;
306fa1
+
306fa1
+	net = get_network_number(name);
306fa1
+	if (net)
306fa1
+		strcpy(name_or_num, net);
306fa1
+	else {
306fa1
+		char this[NI_MAXHOST];
306fa1
+		char *mask;
306fa1
+
306fa1
+		strcpy(this, name);
306fa1
+		if ((mask = strchr(this, '/')))
306fa1
+			*mask++ = '\0';
306fa1
+		if (!strchr(this, '.'))
306fa1
+			strcpy(name_or_num, this);
306fa1
+		else {
306fa1
+			char buf[NI_MAXHOST], *new;
306fa1
+			new = inet_fill_net(this, buf);
306fa1
+			if (!new)
306fa1
+				return PROXIMITY_ERROR;
306fa1
+			strcpy(name_or_num, new);
306fa1
+		}
306fa1
+	}
306fa1
+
306fa1
+	memset(&hints, 0, sizeof(struct addrinfo));
306fa1
+	hints.ai_family = AF_UNSPEC;
306fa1
+	hints.ai_socktype = SOCK_DGRAM;
306fa1
+
306fa1
+	ret = getaddrinfo(name_or_num, NULL, &hints, &ni);
306fa1
+	if (ret) {
306fa1
+		logerr("getaddrinfo: %s", gai_strerror(ret));
306fa1
+		return PROXIMITY_ERROR;
306fa1
+	}
306fa1
+
306fa1
+	proximity = PROXIMITY_OTHER;
306fa1
+
306fa1
+	this = ni;
306fa1
+	while (this) {
306fa1
+		unsigned int prx = get_proximity(this->ai_addr);
306fa1
+		if (prx < proximity)
306fa1
+			proximity = prx;
306fa1
+		this = this->ai_next;
306fa1
+	}
306fa1
+
306fa1
+	return proximity;
306fa1
+}
306fa1
+
306fa1
+unsigned int in_network(char *network)
306fa1
+{
306fa1
+	unsigned int proximity = get_network_proximity(network);
306fa1
+	if (proximity == PROXIMITY_ERROR ||
306fa1
+	    proximity > PROXIMITY_SUBNET)
306fa1
+		return 0;
306fa1
+	return 1;
306fa1
+}
306fa1
+
306fa1
 /*
306fa1
  * Skip whitespace in a string; if we hit a #, consider the rest of the
306fa1
  * entry a comment.
306fa1
diff --git a/modules/amd_parse.y b/modules/amd_parse.y
306fa1
index 33106a1..71fd569 100644
306fa1
--- a/modules/amd_parse.y
306fa1
+++ b/modules/amd_parse.y
306fa1
@@ -92,6 +92,9 @@ static int amd_fprintf(FILE *, char *, ...);
306fa1
 %token NOT_EQUAL
306fa1
 %token COMMA
306fa1
 %token OPTION_ASSIGN
306fa1
+%token LBRACKET
306fa1
+%token RBRACKET
306fa1
+%token NOT
306fa1
 %token NILL
306fa1
 
306fa1
 %token <strtype> MAP_OPTION
306fa1
@@ -102,6 +105,7 @@ static int amd_fprintf(FILE *, char *, ...);
306fa1
 %token <strtype> MNT_OPTION
306fa1
 %token <strtype> SELECTOR
306fa1
 %token <strtype> SELECTOR_VALUE
306fa1
+%token <strtype> SEL_ARG_VALUE
306fa1
 %token <strtype> OPTION
306fa1
 %token <strtype> MACRO
306fa1
 %token <strtype> OTHER
306fa1
@@ -187,18 +191,46 @@ selector_or_option: selection
306fa1
 
306fa1
 selection: SELECTOR IS_EQUAL SELECTOR_VALUE
306fa1
 	{
306fa1
-		if (!make_selector($1, $3, NULL, SEL_TYPE_EQUAL)) {
306fa1
+		if (!make_selector($1, $3, NULL, SEL_COMP_EQUAL)) {
306fa1
 			amd_notify($1);
306fa1
 			YYABORT;
306fa1
 		}
306fa1
 	}
306fa1
 	| SELECTOR NOT_EQUAL SELECTOR_VALUE
306fa1
 	{
306fa1
-		if (!make_selector($1, $3, NULL, SEL_TYPE_NOTEQUAL)) {
306fa1
+		if (!make_selector($1, $3, NULL, SEL_COMP_NOTEQUAL)) {
306fa1
 			amd_notify($1);
306fa1
 			YYABORT;
306fa1
 		}
306fa1
 	}
306fa1
+	| SELECTOR LBRACKET SEL_ARG_VALUE RBRACKET
306fa1
+	{
306fa1
+		if (!make_selector($1, $3, NULL, SEL_COMP_NONE)) {
306fa1
+			amd_notify($1);
306fa1
+			YYABORT;
306fa1
+		}
306fa1
+	}
306fa1
+	| SELECTOR LBRACKET SEL_ARG_VALUE COMMA SEL_ARG_VALUE RBRACKET
306fa1
+	{
306fa1
+		if (!make_selector($1, $3, $5, SEL_COMP_NONE)) {
306fa1
+			amd_notify($1);
306fa1
+			YYABORT;
306fa1
+		}
306fa1
+	}
306fa1
+	| NOT SELECTOR LBRACKET SEL_ARG_VALUE RBRACKET
306fa1
+	{
306fa1
+		if (!make_selector($2, $4, NULL, SEL_COMP_NOT)) {
306fa1
+			amd_notify($2);
306fa1
+			YYABORT;
306fa1
+		}
306fa1
+	}
306fa1
+	| NOT SELECTOR LBRACKET SEL_ARG_VALUE COMMA SEL_ARG_VALUE RBRACKET
306fa1
+	{
306fa1
+		if (!make_selector($2, $4, $6, SEL_COMP_NOT)) {
306fa1
+			amd_notify($2);
306fa1
+			YYABORT;
306fa1
+		}
306fa1
+	}
306fa1
 	;
306fa1
 
306fa1
 option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE
306fa1
@@ -388,9 +420,6 @@ static int make_selector(char *name,
306fa1
 	if (!sel_lookup(name))
306fa1
 		return 0;
306fa1
 
306fa1
-	if (!value1)
306fa1
-		return 0;
306fa1
-
306fa1
 	s = get_selector(name);
306fa1
 	if (!s)
306fa1
 		return 0;
306fa1
@@ -401,9 +430,13 @@ static int make_selector(char *name,
306fa1
 			goto error;
306fa1
 		s->comp.value = tmp;
306fa1
 	} else if (s->sel->flags & SEL_FLAG_FUNC1) {
306fa1
-		char *tmp = amd_strdup(value1);
306fa1
-		if (!tmp)
306fa1
-			goto error;
306fa1
+		if (!value1)
306fa1
+			tmp = NULL;
306fa1
+		else {
306fa1
+			char *tmp = amd_strdup(value1);
306fa1
+			if (!tmp)
306fa1
+				goto error;
306fa1
+		}
306fa1
 		s->func.arg1 = tmp;
306fa1
 	} else if (s->sel->flags & SEL_FLAG_FUNC2) {
306fa1
 		char *tmp = amd_strdup(value1);
306fa1
diff --git a/modules/amd_tok.l b/modules/amd_tok.l
306fa1
index afa3a87..cea9ea5 100644
306fa1
--- a/modules/amd_tok.l
306fa1
+++ b/modules/amd_tok.l
306fa1
@@ -70,22 +70,29 @@ int amd_yyinput(char *, int);
306fa1
 
306fa1
 %option nounput
306fa1
 
306fa1
-%x MAPOPTVAL FSOPTVAL MNTOPTVAL SELOPTVAL
306fa1
+%x MAPOPTVAL FSOPTVAL MNTOPTVAL SELOPTVAL SELARGVAL
306fa1
 
306fa1
 NL		\r?\n
306fa1
 OPTWS		[[:blank:]]*
306fa1
 OTHR		[^!;:=/|\- \t\r\n#]*
306fa1
 
306fa1
+V4NUM		([01]?[0-9][0-9]?|2[0-4][0-9]|25[0-5])
306fa1
+
306fa1
 MACRO		(\$\{([[:alpha:]_/]([[:alnum:]_\-])([[:alnum:]_\-/])*)\})
306fa1
 QSTR		(\"([^"\\]|\\.)*\")
306fa1
 OSTR		([[:alpha:]]([[:alnum:]_\-])+)
306fa1
 FSTR		([[:alnum:]_/\.]([[:alnum:]_\-/\.]|(\\.))*)
306fa1
 VSTR		(([[:alnum:]_\-\:/\.])+)
306fa1
 SSTR		([[:alpha:]]([[:alnum:]\-\.])+)
306fa1
+IP4ADDR		({V4NUM}\.((({V4NUM}\.){0,2}){V4NUM}?))
306fa1
+V4MASK		({IP4ADDR}|([1-2][0-9]|3[0-2]|[1-9]))
306fa1
+IP6ADDR		((([A-Fa-f0-9]{1,4}\:\:?){1,7}[A-Fa-f0-9]{1,4})|(\:\:1))
306fa1
+V6MASK		(12[0-8]|1[0-1][0-9]|[1-9][0-9]|[1-9])
306fa1
 
306fa1
 FOPT		(({QSTR}|{FSTR}|{MACRO})+)
306fa1
 OPTS		({OSTR}(=({VSTR}|{QSTR}|{MACRO})+)?)
306fa1
 SOPT		(({SSTR}|{QSTR}|{MACRO})+)
306fa1
+NOPT		({SSTR}|(({IP4ADDR}(\/{V4MASK})?)|({IP6ADDR}(\/{V6MASK})?)))
306fa1
 
306fa1
 MAPOPT		(fs|type|maptype|pref|sublink|delay)
306fa1
 MNTOPT		(opts|addopts|remopts)
306fa1
@@ -94,13 +101,16 @@ MAPTYPE		(file|nis|nisplus|ldap|hesiod|exec|ndbm|passwd|union)
306fa1
 FSTYPE		(auto|nfs|link|host|nfsx|ufs|xfs|efs)
306fa1
 
306fa1
 OSSEL		(arch|karch|os|osver|full_os|vendor)
306fa1
-HSTSEL		(host|hostd|xhost|domain|byte|cluster)
306fa1
-NETSEL		(netnumber|network|wire|netgrp|netgrpd|in_network)
306fa1
+HSTSEL		(host|hostd|domain|byte|cluster)
306fa1
+NETSEL		(netnumber|network|wire|in_network)
306fa1
 USRSEL		(uid|gid)
306fa1
 MAPSEL		(key|map|path)
306fa1
-OTRSEL		(exists|autodir|dollar)
306fa1
+OTRSEL		(autodir|dollar)
306fa1
 BOLSEL		(true|false)
306fa1
-SELOPT		({OSSEL}|{HSTSEL}|{NETSEL}|{BOLSEL}|{USRSEL}|{MAPSEL}|{OTRSEL})
306fa1
+
306fa1
+SELOPT		({OSSEL}|{HSTSEL}|{USRSEL}|{MAPSEL}|{OTRSEL})
306fa1
+SEL1ARG		(xhost|exists|{NETSEL}|{BOLSEL})
306fa1
+SEL2ARG		(netgrp|netgrpd)
306fa1
 
306fa1
 CUTSEP		(\|\||\/)
306fa1
 
306fa1
@@ -135,6 +145,20 @@ CUTSEP		(\|\||\/)
306fa1
 		return SELECTOR;
306fa1
 	}
306fa1
 
306fa1
+	"!"/({SEL1ARG}|{SEL2ARG}) { return NOT; }
306fa1
+
306fa1
+	{SEL1ARG} {
306fa1
+		BEGIN(SELARGVAL);
306fa1
+		strcpy(amd_lval.strtype, amd_text);
306fa1
+		return SELECTOR;
306fa1
+	}
306fa1
+
306fa1
+	{SEL2ARG} {
306fa1
+		BEGIN(SELARGVAL);
306fa1
+		strcpy(amd_lval.strtype, amd_text);
306fa1
+		return SELECTOR;
306fa1
+	}
306fa1
+
306fa1
 	{CUTSEP} { return CUT; }
306fa1
 
306fa1
 	"-" { return HYPHEN; }
306fa1
@@ -263,6 +287,45 @@ CUTSEP		(\|\||\/)
306fa1
 	}
306fa1
 }
306fa1
 
306fa1
+<SELARGVAL>{
306fa1
+	{NL} |
306fa1
+	\x00 {
306fa1
+		BEGIN(INITIAL);
306fa1
+		yyless(1);
306fa1
+	}
306fa1
+
306fa1
+	";" {
306fa1
+		BEGIN(INITIAL);
306fa1
+		return SEPERATOR;
306fa1
+	}
306fa1
+
306fa1
+	"(" { return LBRACKET; }
306fa1
+
306fa1
+	{NOPT} {
306fa1
+		strcpy(amd_lval.strtype, amd_text);
306fa1
+		return SEL_ARG_VALUE;
306fa1
+	}
306fa1
+
306fa1
+	{SOPT}/"," {
306fa1
+		strcpy(amd_lval.strtype, amd_text);
306fa1
+		return SEL_ARG_VALUE;
306fa1
+	}
306fa1
+
306fa1
+	"," { return COMMA; }
306fa1
+
306fa1
+	{SOPT} {
306fa1
+		strcpy(amd_lval.strtype, amd_text);
306fa1
+		return SEL_ARG_VALUE;
306fa1
+	}
306fa1
+
306fa1
+	{FOPT} {
306fa1
+		strcpy(amd_lval.strtype, amd_text);
306fa1
+		return SEL_ARG_VALUE;
306fa1
+	}
306fa1
+
306fa1
+	")" { return RBRACKET; }
306fa1
+}
306fa1
+
306fa1
 %%
306fa1
 
306fa1
 #include "automount.h"
306fa1
diff --git a/modules/parse_amd.c b/modules/parse_amd.c
306fa1
index 35cc5dc..d9c7d9b 100644
306fa1
--- a/modules/parse_amd.c
306fa1
+++ b/modules/parse_amd.c
306fa1
@@ -223,6 +223,307 @@ static struct substvar *add_lookup_vars(struct autofs_point *ap,
306fa1
 	return list;
306fa1
 }
306fa1
 
306fa1
+static int match_my_name(unsigned int logopt, const char *name, struct substvar *sv)
306fa1
+{
306fa1
+	struct addrinfo hints, *cni, *ni, *haddr;
306fa1
+	char host[NI_MAXHOST + 1], numeric[NI_MAXHOST + 1];
306fa1
+	const struct substvar *v;
306fa1
+	int rv = 0, ret;
306fa1
+
306fa1
+	v = macro_findvar(sv, "host", 4);
306fa1
+	if (v) {
306fa1
+		if (!strcmp(v->val, name))
306fa1
+			return 1;
306fa1
+	}
306fa1
+
306fa1
+	/* Check if comparison value is an alias */
306fa1
+
306fa1
+	memset(&hints, 0, sizeof(hints));
306fa1
+	hints.ai_flags = AI_CANONNAME;
306fa1
+	hints.ai_family = AF_UNSPEC;
306fa1
+	hints.ai_socktype = SOCK_DGRAM;
306fa1
+
306fa1
+	/* Get host canonical name */
306fa1
+	ret = getaddrinfo(v->val, NULL, &hints, &cni);
306fa1
+	if (ret) {
306fa1
+		error(logopt,
306fa1
+		      "hostname lookup failed: %s\n", gai_strerror(ret));
306fa1
+		goto out;
306fa1
+	}
306fa1
+
306fa1
+	hints.ai_flags = 0;
306fa1
+
306fa1
+	/* Resolve comparison name to its names and compare */
306fa1
+	ret = getaddrinfo(name, NULL, &hints, &ni);
306fa1
+	if (ret) {
306fa1
+		error(logopt,
306fa1
+		      "hostname lookup failed: %s\n", gai_strerror(ret));
306fa1
+		freeaddrinfo(cni);
306fa1
+		goto out;
306fa1
+	}
306fa1
+
306fa1
+	haddr = ni;
306fa1
+	while (haddr) {
306fa1
+		/* Translate the host address into a numeric string form */
306fa1
+		ret = getnameinfo(haddr->ai_addr, haddr->ai_addrlen,
306fa1
+				  numeric, sizeof(numeric), NULL, 0,
306fa1
+				  NI_NUMERICHOST);
306fa1
+		if (ret) {
306fa1
+			error(logopt,
306fa1
+			      "host address info lookup failed: %s\n",
306fa1
+			      gai_strerror(ret));
306fa1
+			freeaddrinfo(cni);
306fa1
+			goto next;
306fa1
+		}
306fa1
+
306fa1
+		/* Try to resolve back again to get the canonical name */
306fa1
+		ret = getnameinfo(haddr->ai_addr, haddr->ai_addrlen,
306fa1
+				  host, NI_MAXHOST, NULL, 0, 0);
306fa1
+		if (ret) {
306fa1
+			error(logopt,
306fa1
+			      "host address info lookup failed: %s\n",
306fa1
+			      gai_strerror(ret));
306fa1
+			freeaddrinfo(cni);
306fa1
+			goto next;
306fa1
+		}
306fa1
+
306fa1
+		if (!strcmp(host, cni->ai_canonname)) {
306fa1
+			rv = 1;
306fa1
+			break;
306fa1
+		}
306fa1
+next:
306fa1
+		haddr = haddr->ai_next;
306fa1
+	}
306fa1
+	freeaddrinfo(ni);
306fa1
+	freeaddrinfo(cni);
306fa1
+out:
306fa1
+	return rv;
306fa1
+}
306fa1
+
306fa1
+static int eval_selector(unsigned int logopt,
306fa1
+			 struct amd_entry *this, struct substvar *sv)
306fa1
+{
306fa1
+	struct selector *s = this->selector;
306fa1
+	const struct substvar *v;
306fa1
+	unsigned int s_type;
306fa1
+	unsigned int v_type;
306fa1
+	struct stat st;
306fa1
+	char *host;
306fa1
+	int res, val, ret = 0;
306fa1
+
306fa1
+	s_type = s->sel->flags & SEL_FLAGS_TYPE_MASK;
306fa1
+
306fa1
+	switch (s_type) {
306fa1
+	case SEL_FLAG_MACRO:
306fa1
+		v = macro_findvar(sv, s->sel->name, strlen(s->sel->name));
306fa1
+		if (!v) {
306fa1
+			error(logopt, "failed to get selector %s", s->sel->name);
306fa1
+			return 0;
306fa1
+		}
306fa1
+
306fa1
+		v_type = s->sel->flags & SEL_FLAGS_VALUE_MASK;
306fa1
+
306fa1
+		switch (v_type) {
306fa1
+		case SEL_FLAG_STR:
306fa1
+			res = strcmp(v->val, s->comp.value);
306fa1
+			if (s->compare & SEL_COMP_EQUAL && !res) {
306fa1
+				debug(logopt, MODPREFIX
306fa1
+				      "matched selector %s(%s) == %s",
306fa1
+				      v->def, v->val, s->comp.value);
306fa1
+				ret = 1;
306fa1
+				break;
306fa1
+			} else if (s->compare & SEL_COMP_NOTEQUAL && res) {
306fa1
+				debug(logopt, MODPREFIX
306fa1
+				      "matched selector %s(%s) != %s",
306fa1
+				      v->def, v->val, s->comp.value);
306fa1
+				ret = 1;
306fa1
+				break;
306fa1
+			}
306fa1
+
306fa1
+			debug(logopt, MODPREFIX
306fa1
+				      "did not match selector %s(%s) %s %s",
306fa1
+				      v->def, v->val,
306fa1
+				      (s->compare & SEL_COMP_EQUAL ? "==" : "!="),
306fa1
+				      s->comp.value);
306fa1
+			break;
306fa1
+
306fa1
+		case SEL_FLAG_NUM:
306fa1
+			res = atoi(v->val);
306fa1
+			val = atoi(s->comp.value);
306fa1
+			if (s->compare & SEL_COMP_EQUAL && res == val) {
306fa1
+				debug(logopt, MODPREFIX
306fa1
+				      "matched selector %s(%s) equal to %s",
306fa1
+				      v->def, v->val, s->comp.value);
306fa1
+				ret = 1;
306fa1
+				break;
306fa1
+			} else if (s->compare & SEL_COMP_NOTEQUAL && res != val) {
306fa1
+				debug(logopt, MODPREFIX
306fa1
+				      "matched selector %s(%s) not equal to %s",
306fa1
+				      v->def, v->val, s->comp.value);
306fa1
+				ret = 1;
306fa1
+				break;
306fa1
+			}
306fa1
+
306fa1
+			debug(logopt, MODPREFIX
306fa1
+				      "did not match selector %s(%s) %s %s",
306fa1
+				      v->def, v->val,
306fa1
+				      (s->compare & SEL_COMP_EQUAL ? "==" : "!="),
306fa1
+				      s->comp.value);
306fa1
+			break;
306fa1
+
306fa1
+		default:
306fa1
+			break;
306fa1
+		}
306fa1
+		break;
306fa1
+
306fa1
+	case SEL_FLAG_FUNC1:
306fa1
+		if (s->sel->selector != SEL_TRUE &&
306fa1
+		    s->sel->selector != SEL_FALSE &&
306fa1
+		    !s->func.arg1) {
306fa1
+			error(logopt, MODPREFIX
306fa1
+			      "expected argument missing for selector %s",
306fa1
+			      s->sel->name);
306fa1
+			break;
306fa1
+		}
306fa1
+
306fa1
+		switch (s->sel->selector) {
306fa1
+		case SEL_TRUE:
306fa1
+			ret = 1;
306fa1
+			if (s->compare == SEL_COMP_NOT)
306fa1
+				ret = !ret;
306fa1
+			if (ret)
306fa1
+				debug(logopt, MODPREFIX
306fa1
+				      "matched selector %s(%s)",
306fa1
+				      s->sel->name, s->func.arg1);
306fa1
+			else
306fa1
+				debug(logopt, MODPREFIX
306fa1
+				      "did not match selector %s(%s)",
306fa1
+				      s->sel->name, s->func.arg1);
306fa1
+			break;
306fa1
+
306fa1
+		case SEL_FALSE:
306fa1
+			if (s->compare == SEL_COMP_NOT)
306fa1
+				ret = !ret;
306fa1
+			if (ret)
306fa1
+				debug(logopt, MODPREFIX
306fa1
+				      "matched selector %s(%s)",
306fa1
+				      s->sel->name, s->func.arg1);
306fa1
+			else
306fa1
+				debug(logopt, MODPREFIX
306fa1
+				      "did not match selector %s(%s)",
306fa1
+				      s->sel->name, s->func.arg1);
306fa1
+			break;
306fa1
+
306fa1
+		case SEL_XHOST:
306fa1
+			ret = match_my_name(logopt, s->func.arg1, sv);
306fa1
+			if (s->compare == SEL_COMP_NOT)
306fa1
+				ret = !ret;
306fa1
+			if (ret)
306fa1
+				debug(logopt, MODPREFIX
306fa1
+				      "matched selector %s(%s) to host name",
306fa1
+				      s->sel->name, s->func.arg1);
306fa1
+			else
306fa1
+				debug(logopt, MODPREFIX
306fa1
+				      "did not match selector %s(%s) to host name",
306fa1
+				      s->sel->name, s->func.arg1);
306fa1
+			break;
306fa1
+
306fa1
+		case SEL_EXISTS:
306fa1
+			/* Sould be OK to fail on any error here */
306fa1
+			ret = !lstat(s->func.arg1, &st);
306fa1
+			if (s->compare == SEL_COMP_NOT)
306fa1
+				ret = !ret;
306fa1
+			if (ret)
306fa1
+				debug(logopt, MODPREFIX
306fa1
+				      "matched selector %s(%s)",
306fa1
+				      s->sel->name, s->func.arg1);
306fa1
+			else
306fa1
+				debug(logopt, MODPREFIX
306fa1
+				      "did not match selector %s(%s)",
306fa1
+				      s->sel->name, s->func.arg1);
306fa1
+			break;
306fa1
+
306fa1
+		case SEL_IN_NETWORK:
306fa1
+			ret = in_network(s->func.arg1);
306fa1
+			if (s->compare == SEL_COMP_NOT)
306fa1
+				ret = !ret;
306fa1
+			if (ret)
306fa1
+				debug(logopt, MODPREFIX
306fa1
+				      "matched selector %s(%s)",
306fa1
+				      s->sel->name, s->func.arg1);
306fa1
+			else
306fa1
+				debug(logopt, MODPREFIX
306fa1
+				      "did not match selector %s(%s)",
306fa1
+				      s->sel->name, s->func.arg1);
306fa1
+			break;
306fa1
+
306fa1
+		default:
306fa1
+			break;
306fa1
+		}
306fa1
+		break;
306fa1
+
306fa1
+	case SEL_FLAG_FUNC2:
306fa1
+		if (!s->func.arg1) {
306fa1
+			error(logopt, MODPREFIX
306fa1
+			      "expected argument missing for selector %s",
306fa1
+			      s->sel->name);
306fa1
+			break;
306fa1
+		}
306fa1
+
306fa1
+		switch (s->sel->selector) {
306fa1
+		case SEL_NETGRP:
306fa1
+		case SEL_NETGRPD:
306fa1
+			if (s->func.arg2)
306fa1
+				host = s->func.arg2;
306fa1
+			else {
306fa1
+				if (s->sel->selector == SEL_NETGRP)
306fa1
+					v = macro_findvar(sv, "host", 4);
306fa1
+				else
306fa1
+					v = macro_findvar(sv, "hostd", 5);
306fa1
+				if (!v || !*v->val) {
306fa1
+					error(logopt,
306fa1
+					     "failed to get value of ${host}");
306fa1
+					break;
306fa1
+				}
306fa1
+				host = v->val;
306fa1
+			}
306fa1
+			ret = innetgr(s->func.arg1, host, NULL, NULL);
306fa1
+			if (s->compare == SEL_COMP_NOT)
306fa1
+				ret = !ret;
306fa1
+			if (ret) {
306fa1
+				if (!s->func.arg2)
306fa1
+					debug(logopt, MODPREFIX
306fa1
+					      "matched selector %s(%s)",
306fa1
+					      s->sel->name, s->func.arg1);
306fa1
+				else
306fa1
+					debug(logopt, MODPREFIX
306fa1
+					      "matched selector %s(%s,%s)",
306fa1
+					      s->sel->name, s->func.arg1,
306fa1
+					      s->func.arg2);
306fa1
+			} else {
306fa1
+				if (!s->func.arg2)
306fa1
+					debug(logopt, MODPREFIX
306fa1
+					      "did not match selector %s(%s)",
306fa1
+					      s->sel->name, s->func.arg1);
306fa1
+				else
306fa1
+					debug(logopt, MODPREFIX
306fa1
+					      "did not match selector %s(%s,%s)",
306fa1
+					      s->sel->name, s->func.arg1, s->func.arg2);
306fa1
+			}
306fa1
+			break;
306fa1
+
306fa1
+		default:
306fa1
+			break;
306fa1
+		}
306fa1
+		break;
306fa1
+
306fa1
+	default:
306fa1
+		break;
306fa1
+	}
306fa1
+
306fa1
+	return ret;
306fa1
+}
306fa1
+
306fa1
 static void update_with_defaults(struct amd_entry *defaults,
306fa1
 				 struct amd_entry *entry,
306fa1
 				 struct substvar *sv)
306fa1
@@ -884,6 +1185,33 @@ static void update_prefix(struct autofs_point *ap,
306fa1
 	return;
306fa1
 }
306fa1
 
306fa1
+static int match_selectors(unsigned int logopt,
306fa1
+			   struct amd_entry *entry, struct substvar *sv)
306fa1
+{
306fa1
+	struct selector *s = entry->selector;
306fa1
+	int ret;
306fa1
+
306fa1
+	/* No selectors, always match */
306fa1
+	if (!s) {
306fa1
+		debug(logopt, "no selectors found in location");
306fa1
+		return 1;
306fa1
+	}
306fa1
+
306fa1
+	ret = 0;
306fa1
+
306fa1
+	/* All selectors must match */
306fa1
+	while (s) {
306fa1
+		ret = eval_selector(logopt, entry, sv);
306fa1
+		if (!ret)
306fa1
+			break;
306fa1
+		s = s->next;
306fa1
+	}
306fa1
+	if (!s)
306fa1
+		ret = 1;
306fa1
+
306fa1
+	return ret;
306fa1
+}
306fa1
+
306fa1
 static struct amd_entry *dup_defaults_entry(struct amd_entry *defaults)
306fa1
 {
306fa1
 	struct amd_entry *entry;
306fa1
@@ -1008,6 +1336,23 @@ static struct amd_entry *select_default_entry(struct autofs_point *ap,
306fa1
 			free_amd_entry(this);
306fa1
 			continue;
306fa1
 		}
306fa1
+
306fa1
+		/*
306fa1
+		 * This probably should be a fail since we expect
306fa1
+		 * selectors to pick the default entry.
306fa1
+		 */
306fa1
+		if (!this->selector)
306fa1
+			continue;
306fa1
+
306fa1
+		if (match_selectors(ap->logopt, this, sv)) {
306fa1
+			if (entry_default) {
306fa1
+				/*update_with_defaults(entry_default, this, sv);*/
306fa1
+				free_amd_entry(entry_default);
306fa1
+			}
306fa1
+			list_del_init(&this->list);
306fa1
+			defaults_entry = this;
306fa1
+			break;
306fa1
+		}
306fa1
 	}
306fa1
 
306fa1
 	/* Not strickly amd semantics but ... */
306fa1
@@ -1195,6 +1540,9 @@ int parse_mount(struct autofs_point *ap, const char *name,
306fa1
 			continue;
306fa1
 		}
306fa1
 
306fa1
+		if (!match_selectors(ap->logopt, this, sv))
306fa1
+			continue;
306fa1
+
306fa1
 		update_with_defaults(cur_defaults, this, sv);
306fa1
 		sv = expand_entry(ap, this, flags, sv);
306fa1
 		sv = merge_entry_options(ap, this, sv);