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

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