|
|
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);
|