1 autofs-5.0.4 - ipv6 parse
3 From: Ian Kent <raven@themaw.net>
5 Since ipv6 addresses use a colon separator and we use the colon quite a
6 bit as a delimiting character we need to distinguish between when the
7 colon is the delimeter we are looking for and when it is part of an ipv6
8 address. Since there is widespread use of "[" and "]" to provide the
9 ability to separate a port specification from an ipv6 address this
10 convention has also been used in autofs.
13 include/parse_subs.h | 8 ++++
14 lib/master_tok.l | 10 +++--
15 lib/parse_subs.c | 99 +++++++++++++++++++++++++++++++++++++++++++++---
16 modules/lookup_file.c | 40 +++++++------------
17 modules/lookup_ldap.c | 21 +++++++++-
18 modules/mount_autofs.c | 29 ++++++--------
19 modules/parse_sun.c | 16 +++++---
20 modules/replicated.c | 26 ++++++++++++-
21 8 files changed, 186 insertions(+), 63 deletions(-)
24 diff --git a/include/parse_subs.h b/include/parse_subs.h
25 index 643ad68..ecc712d 100644
26 --- a/include/parse_subs.h
27 +++ b/include/parse_subs.h
32 +struct map_type_info {
38 const char *skipspace(const char *);
39 int check_colon(const char *);
40 int chunklen(const char *, int);
41 @@ -27,5 +33,7 @@ int strmcmp(const char *, const char *, int);
42 char *dequote(const char *, int, unsigned int);
43 int span_space(const char *, unsigned int);
44 char *sanitize_path(const char *, int, unsigned int, unsigned int);
45 +void free_map_type_info(struct map_type_info *);
46 +struct map_type_info *parse_map_type_info(const char *);
49 diff --git a/lib/master_tok.l b/lib/master_tok.l
50 index 801aa6f..b6cc8be 100644
51 --- a/lib/master_tok.l
52 +++ b/lib/master_tok.l
53 @@ -96,10 +96,12 @@ SLASHIFYSTR (--(no-)?slashify-colons)
56 DNSERVSTR1 ([[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?:)
57 -DNSERVSTR2 (\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/)
58 -DNSERVSTR3 (([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:)
59 -DNSERVSTR4 (\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/)
60 -DNSERVERSTR ({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4})
61 +DNSERVSTR2 (\[([[:xdigit:]]:.)+\](:[0-9]+)?:)
62 +DNSERVSTR3 (\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/)
63 +DNSERVSTR4 (\/\/\[([[:xdigit:]]:.)+\](:[0-9]+)?\/)
64 +DNSERVSTR5 (([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:)
65 +DNSERVSTR6 (\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/)
66 +DNSERVERSTR ({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4}|{DNSERVSTR5}|{DNSERVSTR6})
69 AT_NMN ([nN][iI][sS][Mm][aA][pP][Nn][aA][mM][eE])
70 diff --git a/lib/parse_subs.c b/lib/parse_subs.c
71 index 8a032e8..0cba95a 100644
72 --- a/lib/parse_subs.c
73 +++ b/lib/parse_subs.c
74 @@ -56,14 +56,13 @@ int check_colon(const char *str)
75 char *ptr = (char *) str;
79 + if (!strncmp(ptr, ":/", 2))
82 - while (*ptr && *ptr != ':' && *ptr != '/') {
83 + while (*ptr && strncmp(ptr, ":/", 2))
87 - if (!*ptr || *ptr == '/')
92 @@ -93,12 +92,12 @@ int chunklen(const char *whence, int expect_colon)
97 + if (!strncmp(str, ":/", 2))
103 + if (expect_colon && !strncmp(str, ":/", 2))
107 @@ -300,3 +299,91 @@ char *sanitize_path(const char *path, int origlen, unsigned int type, unsigned i
111 +void free_map_type_info(struct map_type_info *info)
116 + free(info->format);
123 +struct map_type_info *parse_map_type_info(const char *str)
125 + struct map_type_info *info;
126 + char *buf, *type, *fmt, *map, *tmp;
132 + info = malloc(sizeof(struct map_type_info));
137 + memset(info, 0, sizeof(struct map_type_info));
141 + /* Look for space terminator - ignore local options */
143 + for (tmp = buf; *tmp; tmp++) {
147 + } else if (*tmp == ',') {
151 + } else if (*tmp == ':') {
156 + } else if (*tmp == '[') {
158 + * Unescaped '[' is a syntax error here as only
159 + * an ldap map with a type specified should contain
170 + info->type = strdup(type);
173 + free_map_type_info(info);
179 + info->format = strdup(fmt);
180 + if (!info->format) {
182 + free_map_type_info(info);
187 + info->map = strdup(map);
190 + free_map_type_info(info);
199 diff --git a/modules/lookup_file.c b/modules/lookup_file.c
200 index ba80f2a..ec78090 100644
201 --- a/modules/lookup_file.c
202 +++ b/modules/lookup_file.c
203 @@ -523,10 +523,10 @@ prepare_plus_include(struct autofs_point *ap, time_t age, char *key, unsigned in
205 struct map_source *current;
206 struct map_source *source;
207 - char *type, *map, *fmt;
208 + struct map_type_info *info;
214 current = ap->entry->current;
215 ap->entry->current = NULL;
216 @@ -548,33 +548,19 @@ prepare_plus_include(struct autofs_point *ap, time_t age, char *key, unsigned in
222 - /* Look for space terminator - ignore local options */
224 - for (tmp = buf; *tmp; tmp++) {
228 - } else if (*tmp == ',') {
232 - } else if (*tmp == ':') {
240 + if (!(info = parse_map_type_info(buf))) {
241 + error(ap->logopt, MODPREFIX "failed to parse map info");
248 + argv[0] = info->map;
251 - source = master_find_source_instance(current, type, fmt, argc, argv);
252 + source = master_find_source_instance(current,
253 + info->type, info->format,
257 * Make sure included map age is in sync with its owner
258 @@ -582,8 +568,11 @@ prepare_plus_include(struct autofs_point *ap, time_t age, char *key, unsigned in
262 - source = master_add_source_instance(current, type, fmt, age, argc, argv);
263 + source = master_add_source_instance(current,
264 + info->type, info->format,
267 + free_map_type_info(info);
269 error(ap->logopt, "failed to add included map instance");
271 @@ -594,6 +583,7 @@ prepare_plus_include(struct autofs_point *ap, time_t age, char *key, unsigned in
275 + free_map_type_info(info);
279 diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c
280 index 094cbdc..7845bcf 100644
281 --- a/modules/lookup_ldap.c
282 +++ b/modules/lookup_ldap.c
283 @@ -1119,11 +1119,26 @@ static int parse_server_string(unsigned logopt, const char *url, struct lookup_c
284 memcpy(ctxt->server, s, l);
287 - } else if (strchr(ptr, ':') != NULL) {
289 + } else if (strchr(ptr, ':') != NULL || *ptr == '[') {
290 + const char *q = NULL;
292 /* Isolate the server. Include the port spec */
293 - q = strchr(ptr, ':');
295 + q = strchr(ptr, ':');
298 + while (*q == ':' || isxdigit(*q))
301 + crit(logopt, MODPREFIX
302 + "invalid LDAP map syntax %s", ptr);
313 diff --git a/modules/mount_autofs.c b/modules/mount_autofs.c
314 index fab2906..14d6307 100644
315 --- a/modules/mount_autofs.c
316 +++ b/modules/mount_autofs.c
317 @@ -50,7 +50,7 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
318 int argc, status, ghost = ap->flags & MOUNT_FLAG_GHOST;
319 time_t timeout = ap->exp_timeout;
320 unsigned logopt = ap->logopt;
321 - char *type, *format, *tmp, *tmp2;
322 + struct map_type_info *info;
323 struct master *master;
324 struct master_mapent *entry;
325 struct map_source *source;
326 @@ -174,21 +174,12 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
333 - tmp = strchr(what, ':');
336 - tmp2 = strchr(what, ',');
341 - type = (char *) what;
344 - argv[0] = (char *) what;
345 + if (!(info = parse_map_type_info(what))) {
346 + error(ap->logopt, MODPREFIX "failed to parse map info");
347 + master_free_mapent(entry);
350 + argv[0] = info->map;
354 @@ -202,13 +193,17 @@ int mount_mount(struct autofs_point *ap, const char *root, const char *name,
358 - source = master_add_map_source(entry, type, format, time(NULL), argc, argv);
359 + source = master_add_map_source(entry,
360 + info->type, info->format,
361 + time(NULL), argc, argv);
364 MODPREFIX "failed to add map source to entry");
365 master_free_mapent(entry);
366 + free_map_type_info(info);
369 + free_map_type_info(info);
371 source->mc = cache_init(entry->ap, source);
373 diff --git a/modules/parse_sun.c b/modules/parse_sun.c
374 index ed73e46..65417e1 100644
375 --- a/modules/parse_sun.c
376 +++ b/modules/parse_sun.c
377 @@ -245,7 +245,9 @@ int expandsunent(const char *src, char *dst, const char *key,
379 (seen_colons && slashify_colons) ? '/' : ':';
382 + /* Were looking for the colon preceeding a path */
388 @@ -814,21 +816,23 @@ static int validate_location(char *loc)
392 - * If a ':' is present now it must be a host name, except
393 + * If a ':/' is present now it must be a host name, except
394 * for those special file systems like sshfs which use "#"
395 - * and "@" in the host name part.
396 + * and "@" in the host name part and ipv6 addresses that
397 + * have ":", "[" and "]".
399 if (check_colon(ptr)) {
400 - while (*ptr && *ptr != ':') {
401 + while (*ptr && strncmp(ptr, ":/", 2)) {
402 if (!(isalnum(*ptr) ||
403 *ptr == '-' || *ptr == '.' || *ptr == '_' ||
404 *ptr == ',' || *ptr == '(' || *ptr == ')' ||
405 - *ptr == '#' || *ptr == '@'))
406 + *ptr == '#' || *ptr == '@' || *ptr == ':' ||
407 + *ptr == '[' || *ptr == ']'))
412 - if (*ptr && *ptr == ':')
413 + if (*ptr && !strncmp(ptr, ":/", 2))
417 diff --git a/modules/replicated.c b/modules/replicated.c
418 index 9e85c00..79845d0 100644
419 --- a/modules/replicated.c
420 +++ b/modules/replicated.c
421 @@ -1168,6 +1168,28 @@ static int add_local_path(struct host **hosts, const char *path)
425 +static char *seek_delim(const char *s)
430 + delim = strpbrk(p, "(, \t:");
431 + if (delim && *delim != ':')
439 + if (!strncmp(p, ":/", 2))
447 int parse_location(unsigned logopt, struct host **hosts, const char *list)
449 char *str, *p, *delim;
450 @@ -1187,7 +1209,7 @@ int parse_location(unsigned logopt, struct host **hosts, const char *list)
453 p += strspn(p, " \t,");
454 - delim = strpbrk(p, "(, \t:");
455 + delim = seek_delim(p);
459 @@ -1211,7 +1233,7 @@ int parse_location(unsigned logopt, struct host **hosts, const char *list)
461 /* Oh boy - might have spaces in the path */
463 - while (*next && *next != ':')
464 + while (*next && strncmp(next, ":/", 2))
467 /* No spaces in host names at least */