You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
776 lines
18 KiB
776 lines
18 KiB
7 years ago
|
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);
|