Blob Blame History Raw
autofs-5.0.9 - amd lookup add selector handling

From: Ian Kent <raven@themaw.net>


---
 include/parse_subs.h |    2 
 lib/parse_subs.c     |  127 ++++++++++++++++++
 modules/amd_parse.y  |   49 ++++++-
 modules/amd_tok.l    |   73 ++++++++++
 modules/parse_amd.c  |  348 ++++++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 586 insertions(+), 13 deletions(-)

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