Blob Blame History Raw
autofs-5.0.4 - ipv6 parse

From: Ian Kent <raven@themaw.net>

Since ipv6 addresses use a colon separator and we use the colon quite a
bit as a delimiting character we need to distinguish between when the
colon is the delimeter we are looking for and when it is part of an ipv6
address. Since there is widespread use of "[" and "]" to provide the
ability to separate a port specification from an ipv6 address this
convention has also been used in autofs.
---

 CHANGELOG              |    1 
 include/parse_subs.h   |    8 +++
 lib/master_tok.l       |   10 ++--
 lib/parse_subs.c       |   99 ++++++++++++++++++++++++++++++++++++++++++++++---
 modules/lookup_file.c  |   40 +++++++------------
 modules/lookup_ldap.c  |   21 ++++++++--
 modules/mount_autofs.c |   29 +++++---------
 modules/parse_sun.c    |   16 ++++---
 modules/replicated.c   |   26 +++++++++++-
 9 files changed, 187 insertions(+), 63 deletions(-)


--- autofs-5.0.4.orig/include/parse_subs.h
+++ autofs-5.0.4/include/parse_subs.h
@@ -20,6 +20,12 @@
 
 struct mapent;
 
+struct map_type_info {
+	char *type;
+	char *format;
+	char *map;
+};
+
 const char *skipspace(const char *);
 int check_colon(const char *);
 int chunklen(const char *, int);
@@ -27,5 +33,7 @@ int strmcmp(const char *, const char *, 
 char *dequote(const char *, int, unsigned int);
 int span_space(const char *, unsigned int);
 char *sanitize_path(const char *, int, unsigned int, unsigned int);
+void free_map_type_info(struct map_type_info *);
+struct map_type_info *parse_map_type_info(const char *);
 
 #endif
--- autofs-5.0.4.orig/lib/master_tok.l
+++ autofs-5.0.4/lib/master_tok.l
@@ -96,10 +96,12 @@ SLASHIFYSTR	(--(no-)?slashify-colons)
 NUMBER		[0-9]+
 
 DNSERVSTR1	([[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?:)
-DNSERVSTR2	(\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/)
-DNSERVSTR3	(([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:)
-DNSERVSTR4	(\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/)
-DNSERVERSTR	({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4})
+DNSERVSTR2	(\[([[:xdigit:]]:.)+\](:[0-9]+)?:)
+DNSERVSTR3	(\/\/[[:alpha:]][[:alnum:]\-.]*(:[0-9]+)?\/)
+DNSERVSTR4	(\/\/\[([[:xdigit:]]:.)+\](:[0-9]+)?\/)
+DNSERVSTR5	(([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?:)
+DNSERVSTR6	(\/\/([[:digit:]]{1,3}\.){3}[[:digit:]]{1,3}(:[0-9]+)?\/)
+DNSERVERSTR	({DNSERVSTR1}|{DNSERVSTR2}|{DNSERVSTR3}|{DNSERVSTR4}|{DNSERVSTR5}|{DNSERVSTR6})
 
 AT_CN		([cC][[nN])
 AT_NMN		([nN][iI][sS][Mm][aA][pP][Nn][aA][mM][eE])
--- autofs-5.0.4.orig/lib/parse_subs.c
+++ autofs-5.0.4/lib/parse_subs.c
@@ -56,14 +56,13 @@ int check_colon(const char *str)
 	char *ptr = (char *) str;
 
 	/* Colon escape */
-	if (*ptr == ':')
+	if (!strncmp(ptr, ":/", 2))
 		return 1;
 
-	while (*ptr && *ptr != ':' && *ptr != '/') {
+	while (*ptr && strncmp(ptr, ":/", 2))
 		ptr++;
-	}
 
-	if (!*ptr || *ptr == '/')
+	if (!*ptr)
 		return 0;
 
 	return 1;
@@ -93,12 +92,12 @@ int chunklen(const char *whence, int exp
 				n++;
 				if (*str == '"')
 					break;
-				if (*str == ':')
+				if (!strncmp(str, ":/", 2))
 					expect_colon = 0;
 			}
 			break;
 		case ':':
-			if (expect_colon)
+			if (expect_colon && !strncmp(str, ":/", 2))
 				expect_colon = 0;
 			continue;
 		case ' ':
@@ -300,3 +299,91 @@ char *sanitize_path(const char *path, in
 	return s_path;
 }
 
+void free_map_type_info(struct map_type_info *info)
+{
+	if (info->type)
+		free(info->type);
+	if (info->format)
+		free(info->format);
+	if (info->map)
+		free(info->map);
+	free(info);
+	return;
+}
+
+struct map_type_info *parse_map_type_info(const char *str)
+{
+	struct map_type_info *info;
+	char *buf, *type, *fmt, *map, *tmp;
+
+	buf = strdup(str);
+	if (!buf)
+		return NULL;
+
+	info = malloc(sizeof(struct map_type_info));
+	if (!info) {
+		free(buf);
+		return NULL;
+	}
+	memset(info, 0, sizeof(struct map_type_info));
+
+	type = fmt = NULL;
+
+	/* Look for space terminator - ignore local options */
+	map = buf;
+	for (tmp = buf; *tmp; tmp++) {
+		if (*tmp == ' ') {
+			*tmp = '\0';
+			break;
+		} else if (*tmp == ',') {
+			type = buf;
+			*tmp++ = '\0';
+			fmt = tmp;
+		} else if (*tmp == ':') {
+			if (!fmt)
+				type = buf;
+			*tmp++ = '\0';
+			map = tmp;
+		} else if (*tmp == '[') {
+			/*
+			 * Unescaped '[' is a syntax error here as only
+			 * an ldap map with a type specified should contain
+			 * them. 
+			 */
+			free(buf);
+			return 0;
+		}
+		if (*tmp == '\\')
+			tmp++;
+	}
+
+	if (type) {
+		info->type = strdup(type);
+		if (!info->type) {
+			free(buf);
+			free_map_type_info(info);
+			return NULL;
+		}
+	}
+
+	if (fmt) {
+		info->format = strdup(fmt);
+		if (!info->format) {
+			free(buf);
+			free_map_type_info(info);
+			return NULL;
+		}
+	}
+
+	info->map = strdup(map);
+	if (!info->map) {
+		free(buf);
+		free_map_type_info(info);
+		return NULL;
+	}
+
+	free(buf);
+
+	return info;
+}
+
--- autofs-5.0.4.orig/modules/lookup_file.c
+++ autofs-5.0.4/modules/lookup_file.c
@@ -523,10 +523,10 @@ prepare_plus_include(struct autofs_point
 {
 	struct map_source *current;
 	struct map_source *source;
-	char *type, *map, *fmt;
+	struct map_type_info *info;
 	const char *argv[2];
 	int argc;
-	char *buf, *tmp;
+	char *buf;
 
 	current = ap->entry->current;
 	ap->entry->current = NULL;
@@ -548,33 +548,19 @@ prepare_plus_include(struct autofs_point
 		return NULL;
 	}
 
-	type = fmt = NULL;
-
-	/* Look for space terminator - ignore local options */
-	map = buf;
-	for (tmp = buf; *tmp; tmp++) {
-		if (*tmp == ' ') {
-			*tmp = '\0';
-			break;
-		} else if (*tmp == ',') {
-			type = buf;
-			*tmp++ = '\0';
-			fmt = tmp;
-		} else if (*tmp == ':') {
-			if (!fmt)
-				type = buf;
-			*tmp++ = '\0';
-			map = tmp;
-		}
-		if (*tmp == '\\')
-			tmp++;
+	if (!(info = parse_map_type_info(buf))) {
+		error(ap->logopt, MODPREFIX "failed to parse map info");
+		free(buf);
+		return NULL;
 	}
 
 	argc = 1;
-	argv[0] = map;
+	argv[0] = info->map;
 	argv[1] = NULL;
 
-	source = master_find_source_instance(current, type, fmt, argc, argv);
+	source = master_find_source_instance(current,
+					     info->type, info->format,
+					     argc, argv);
 	if (source)
 		/*
 		 * Make sure included map age is in sync with its owner
@@ -582,8 +568,11 @@ prepare_plus_include(struct autofs_point
 		 */
 		source->age = age;
 	else {
-		source = master_add_source_instance(current, type, fmt, age, argc, argv);
+		source = master_add_source_instance(current,
+						    info->type, info->format,
+						    age, argc, argv);
 		if (!source) {
+			free_map_type_info(info);
 			free(buf);
 			error(ap->logopt, "failed to add included map instance");
 			return NULL;
@@ -594,6 +583,7 @@ prepare_plus_include(struct autofs_point
 	if (inc)
 		source->recurse = 1;
 
+	free_map_type_info(info);
 	free(buf);
 
 	return source;
--- autofs-5.0.4.orig/modules/lookup_ldap.c
+++ autofs-5.0.4/modules/lookup_ldap.c
@@ -1119,11 +1119,26 @@ static int parse_server_string(unsigned 
 			memcpy(ctxt->server, s, l);
 */
 		}
-	} else if (strchr(ptr, ':') != NULL) {
-		char *q = NULL;
+	} else if (strchr(ptr, ':') != NULL || *ptr == '[') {
+		const char *q = NULL;
 
 		/* Isolate the server. Include the port spec */
-		q = strchr(ptr, ':');
+		if (*ptr != '[')
+			q = strchr(ptr, ':');
+		else {
+			q = ++ptr;
+			while (*q == ':' || isxdigit(*q))
+				q++;
+			if (*q != ']') {
+				crit(logopt, MODPREFIX
+				     "invalid LDAP map syntax %s", ptr);
+				return 0;
+			}
+			q++;
+			if (*q == ':')
+				q++;
+		}
+
 		if (isdigit(*q))
 			while (isdigit(*q))
 				q++;
--- autofs-5.0.4.orig/modules/mount_autofs.c
+++ autofs-5.0.4/modules/mount_autofs.c
@@ -50,7 +50,7 @@ int mount_mount(struct autofs_point *ap,
 	int argc, status, ghost = ap->flags & MOUNT_FLAG_GHOST;
 	time_t timeout = ap->exp_timeout;
 	unsigned logopt = ap->logopt;
-	char *type, *format, *tmp, *tmp2;
+	struct map_type_info *info;
 	struct master *master;
 	struct master_mapent *entry;
 	struct map_source *source;
@@ -174,21 +174,12 @@ int mount_mount(struct autofs_point *ap,
 
 	argc = 1;
 
-	type = NULL;
-	format = NULL;
-
-	tmp = strchr(what, ':');
-	if (tmp) {
-		*tmp++ = '\0';
-		tmp2 = strchr(what, ',');
-		if (tmp2) {
-			*tmp2++ = '\0';
-			format = tmp2;
-		}
-		type = (char *) what;
-		argv[0] = tmp;
-	} else
-		argv[0] = (char *) what;
+	if (!(info = parse_map_type_info(what))) {
+		error(ap->logopt, MODPREFIX "failed to parse map info");
+		master_free_mapent(entry);
+		return 1;
+	}
+	argv[0] = info->map;
 
 	if (options) {
 		p = options;
@@ -202,13 +193,17 @@ int mount_mount(struct autofs_point *ap,
 	}
 	argv[argc] = NULL;
 
-	source = master_add_map_source(entry, type, format, time(NULL), argc, argv);
+	source = master_add_map_source(entry,
+				       info->type, info->format,
+				       time(NULL), argc, argv);
 	if (!source) {
 		error(ap->logopt,
 		      MODPREFIX "failed to add map source to entry");
 		master_free_mapent(entry);
+		free_map_type_info(info);
 		return 1;
 	}
+	free_map_type_info(info);
 
 	source->mc = cache_init(entry->ap, source);
 	if (!source->mc) {
--- autofs-5.0.4.orig/modules/parse_sun.c
+++ autofs-5.0.4/modules/parse_sun.c
@@ -245,7 +245,9 @@ int expandsunent(const char *src, char *
 				*(dst++) = 
 				  (seen_colons && slashify_colons) ? '/' : ':';
 			len++;
-			seen_colons = 1;
+			/* Were looking for the colon preceeding a path */
+			if (*src == '/')
+				seen_colons = 1;
 			break;
 
 		default:
@@ -814,21 +816,23 @@ static int validate_location(char *loc)
 		return 1;
 
 	/*
-	 * If a ':' is present now it must be a host name, except
+	 * If a ':/' is present now it must be a host name, except
 	 * for those special file systems like sshfs which use "#"
-	 * and "@" in the host name part.
+	 * and "@" in the host name part and ipv6 addresses that
+	 * have ":", "[" and "]".
 	 */
 	if (check_colon(ptr)) {
-		while (*ptr && *ptr != ':') {
+		while (*ptr && strncmp(ptr, ":/", 2)) {
 			if (!(isalnum(*ptr) ||
 			    *ptr == '-' || *ptr == '.' || *ptr == '_' ||
 			    *ptr == ',' || *ptr == '(' || *ptr == ')' ||
-			    *ptr == '#' || *ptr == '@'))
+			    *ptr == '#' || *ptr == '@' || *ptr == ':' ||
+			    *ptr == '[' || *ptr == ']'))
 				return 0;
 			ptr++;
 		}
 
-		if (*ptr && *ptr == ':')
+		if (*ptr && !strncmp(ptr, ":/", 2))
 			ptr++;
 	}
 
--- autofs-5.0.4.orig/modules/replicated.c
+++ autofs-5.0.4/modules/replicated.c
@@ -1168,6 +1168,28 @@ static int add_local_path(struct host **
 	return 1;
 }
 
+static char *seek_delim(const char *s)
+{
+	const char *p = s;
+	char *delim;
+
+	delim = strpbrk(p, "(, \t:");
+	if (delim && *delim != ':')
+		return delim;
+
+	while (*p) {
+		if (*p != ':') {
+			p++;
+			continue;
+		}
+		if (!strncmp(p, ":/", 2))
+			return (char *) p;
+		p++;
+	}
+
+	return NULL;
+}
+
 int parse_location(unsigned logopt, struct host **hosts, const char *list)
 {
 	char *str, *p, *delim;
@@ -1187,7 +1209,7 @@ int parse_location(unsigned logopt, stru
 		int weight = 0;
 
 		p += strspn(p, " \t,");
-		delim = strpbrk(p, "(, \t:");
+		delim = seek_delim(p);
 
 		if (delim) {
 			if (*delim == '(') {
@@ -1211,7 +1233,7 @@ int parse_location(unsigned logopt, stru
 
 				/* Oh boy - might have spaces in the path */
 				next = path;
-				while (*next && *next != ':')
+				while (*next && strncmp(next, ":/", 2))
 					next++;
 
 				/* No spaces in host names at least */
--- autofs-5.0.4.orig/CHANGELOG
+++ autofs-5.0.4/CHANGELOG
@@ -19,6 +19,7 @@
 - make some easy alloca replacements (Valerie Aurora Henson).
 - update to configure libtirpc if present.
 - update to provide ipv6 name and address support.
+- update to provide ipv6 address parsing.
 
 4/11/2008 autofs-5.0.4
 -----------------------