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

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