diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 165bc96..142346b 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -26,13 +26,140 @@ extern struct wpa_driver_ops *wpa_drivers[];
 
 
 #ifndef CONFIG_NO_VLAN
+/**
+ * Parses current line.
+ * @param vlan: where the new VLAN is written to. 
+ *
+ * Returns -1 on fatal error.
+ * Returns 0 else
+ *         *vlan = NULL if no VLAN is found.
+ */
+int hostapd_config_parse_vlan(char* buf, const int line, const char *fname,
+                              struct hostapd_vlan **vlan)
+{
+	char *pos, *pos2;
+	vlan_t vlan_id = VLAN_NULL;
+#ifdef CONFIG_VLAN_TAGGED
+	int i;
+#endif
+
+	*vlan = NULL;
+
+	if (buf[0] == '#')
+		return 0;
+	pos = buf;
+	while (*pos != '\0') {
+		if (*pos == '\n') {
+			*pos = '\0';
+			break;
+		}
+		pos++;
+	}
+	if (buf[0] == '\0')
+		return 0;
+		
+	if (buf[0] == '*') {
+		vlan_alloc(&vlan_id, VLAN_ID_WILDCARD, 0, NULL);
+		pos = buf + 1;
+	} else {
+		int untagged = 0;
+		int num_tagged = 0;
+		int *tagged = NULL;
+
+		pos = buf;
+#ifdef CONFIG_VLAN_TAGGED
+		/* count number of tagged vlans, separated by minus */
+		pos2 = pos;
+		while (*pos2 != '\0' && *pos2 != ' ' && *pos2 != '\t') {
+			if (*pos2 == 't')
+				num_tagged++;
+			pos2++;
+		}
+		/* replace first minus with \0 for atoi */
+		pos2 = pos;
+		while (*pos2 != '\0' && *pos2 != ' ' &&
+		       *pos2 != '\t' && *pos2 != 't')
+			pos2++;
+		*pos2 = '\0'; pos2++;
+#endif /* CONFIG_VLAN_TAGGED */
+		untagged = atoi(pos);
+		if (untagged < 0 && untagged > MAX_VLAN_ID) {
+			wpa_printf(MSG_ERROR, "Invalid VLAN ID %d at "
+				   "line %d in '%s'", untagged, line, fname);
+			return -1;
+		}
+#ifndef CONFIG_VLAN_TAGGED
+		while (*pos != '\0' && *pos != ' ' && *pos != '\t')
+			pos++;
+#else
+		pos = pos2;
+		if (num_tagged > 0) {
+			tagged = os_zalloc(sizeof(*tagged) * num_tagged);
+			if (!tagged) {
+				wpa_printf(MSG_ERROR, "Out of memory parsing "
+				           "'%s' at line %d in '%s'", buf,
+					   line, fname);
+				return -1;
+			}
+			for (i=0; i < num_tagged; i++) {
+				while (*pos2 != '\0' && *pos2 != ' ' &&
+				       *pos2 != '\t' && *pos2 != 't')
+					pos2++;
+				*pos2 = '\0'; pos2++;
+				tagged[i] = atoi(pos);
+				if (tagged[i] < 1 || tagged[i] > MAX_VLAN_ID) {
+					wpa_printf(MSG_ERROR, "Invalid tagged "
+					           "VLAN ID %d at line %d in "
+						   "'%s'", tagged[i], line,
+							   fname);
+					return -1;
+				}
+				pos = pos2;
+			}
+		}
+#endif /* CONFIG_VLAN_TAGGED */
+		if (!untagged && !num_tagged) {
+			wpa_printf(MSG_ERROR, "No VLAN ID at line %d in '%s'",
+			           line, fname);
+			return -1;
+		}
+		vlan_alloc(&vlan_id, untagged, num_tagged, tagged);
+		os_free(tagged);
+	}
+
+	while (*pos == ' ' || *pos == '\t')
+		pos++;
+	pos2 = pos;
+	while (*pos2 != ' ' && *pos2 != '\t' && *pos2 != '\0')
+		pos2++;
+	*pos2 = '\0';
+	if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) {
+		wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d in '%s'",
+		           line, fname);
+		return -1;
+	}
+
+	*vlan = os_zalloc(sizeof(**vlan));
+	if (*vlan == NULL) {
+		wpa_printf(MSG_ERROR, "Out of memory while reading VLAN "
+		                      "interfaces from '%s'", fname);
+		return -1;
+	}
+
+	vlan_alloc_copy(&((*vlan)->vlan_id), &vlan_id);
+	vlan_free(&vlan_id);
+	os_strlcpy((*vlan)->ifname, pos, sizeof((*vlan)->ifname));
+
+	return 0;
+}
+
+
 static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
 					 const char *fname)
 {
 	FILE *f;
-	char buf[128], *pos, *pos2;
-	int line = 0;
-	vlan_t vlan_id = VLAN_NULL;
+	char buf[128];
+	int line = 0, ret;
 	struct hostapd_vlan *vlan;
 
 	f = fopen(fname, "r");
@@ -43,59 +170,14 @@ static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
 
 	while (fgets(buf, sizeof(buf), f)) {
 		line++;
-
-		if (buf[0] == '#')
-			continue;
-		pos = buf;
-		while (*pos != '\0') {
-			if (*pos == '\n') {
-				*pos = '\0';
-				break;
-			}
-			pos++;
-		}
-		if (buf[0] == '\0')
-			continue;
-
-		if (buf[0] == '*') {
-			vlan_alloc(&vlan_id, VLAN_ID_WILDCARD, 0, NULL);
-			pos = buf + 1;
-		} else {
-			int untagged_vlan_id = strtol(buf, &pos, 10);
-			if (buf == pos || untagged_vlan_id < 1 ||
-			    untagged_vlan_id > MAX_VLAN_ID) {
-				wpa_printf(MSG_ERROR, "Invalid VLAN ID at "
-					   "line %d in '%s'", line, fname);
-				fclose(f);
-				return -1;
-			}
-			vlan_alloc(&vlan_id, untagged_vlan_id, 0, NULL);
-		}
-
-		while (*pos == ' ' || *pos == '\t')
-			pos++;
-		pos2 = pos;
-		while (*pos2 != ' ' && *pos2 != '\t' && *pos2 != '\0')
-			pos2++;
-		*pos2 = '\0';
-		if (*pos == '\0' || os_strlen(pos) > IFNAMSIZ) {
-			wpa_printf(MSG_ERROR, "Invalid VLAN ifname at line %d "
-				   "in '%s'", line, fname);
-			fclose(f);
-			return -1;
-		}
-
-		vlan = os_zalloc(sizeof(*vlan));
-		if (vlan == NULL) {
-			wpa_printf(MSG_ERROR, "Out of memory while reading "
-				   "VLAN interfaces from '%s'", fname);
+		ret = hostapd_config_parse_vlan(buf, line, fname, &vlan);
+		if (ret < 0) {
 			fclose(f);
-			return -1;
+			return ret;
 		}
+		if (!vlan)
+			continue;
 
-		vlan_alloc_copy(&vlan->vlan_id, &vlan_id);
-		vlan_free(&vlan_id);
-		os_strlcpy(vlan->ifname, pos, sizeof(vlan->ifname));
 		vlan->next = bss->vlan;
 		bss->vlan = vlan;
 	}
@@ -115,15 +197,122 @@ static int hostapd_acl_comp(const void *a, const void *b)
 }
 
 
+/**
+ * Parses current line.
+ * Returns -1 on fatal error.
+ * Returns 0 if no acl is found
+ * Returns 1 else
+ */
+static int hostapd_config_parse_mac(char* buf, const char *fname,
+                                    const int line, struct mac_acl_entry *acl)
+{
+	char *pos;
+	u8 addr[ETH_ALEN];
+#ifdef CONFIG_VLAN_TAGGED
+	int i;
+	char *pos2;
+	int untagged = 0;
+	int num_tagged = 0;
+	int *tagged = NULL;
+#endif /* CONFIG_VLAN_TAGGED */
+
+	if (buf[0] == '#')
+		return 0;
+
+	pos = buf;
+	while (*pos != '\0') {
+		if (*pos == '\n') {
+			*pos = '\0';
+			break;
+		}
+		pos++;
+	}
+	if (buf[0] == '\0')
+		return 0;
+
+	if (hwaddr_aton(buf, addr)) {
+		wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at line %d in "
+		           "'%s'", buf, line, fname);
+		return -1;
+	}
+
+	os_memset(acl, 0, sizeof(*acl));
+	os_memcpy(acl->addr, addr, ETH_ALEN);
+	acl->vlan_id = VLAN_NULL;
+
+#ifndef CONFIG_NO_VLAN
+	pos = buf;
+	while (*pos != '\0' && *pos != ' ' && *pos != '\t')
+		pos++;
+	while (*pos == ' ' || *pos == '\t')
+		pos++;
+	if (*pos == '\0')
+		return 1; // no VLAN
+
+#ifdef CONFIG_VLAN_TAGGED
+	/* count number of tagged vlans, separated by minus */
+	pos2 = pos;
+	while (*pos2 != '\0' && *pos2 != ' ' &&
+	       *pos2 != '\t') {
+		if (*pos2 == 't')
+			num_tagged++;
+		pos2++;
+	}
+	/* replace first minus with \0 for atoi */
+	pos2 = pos;
+	while (*pos2 != '\0' && *pos2 != ' ' &&
+	       *pos2 != '\t' && *pos2 != 't')
+		pos2++;
+	*pos2 = '\0'; pos2++;
+#endif /* CONFIG_VLAN_TAGGED */
+	untagged = atoi(pos);
+	if (untagged < 0 && untagged > MAX_VLAN_ID) {
+		wpa_printf(MSG_ERROR, "Invalid VLAN ID %d at line %d in '%s'", 
+		           untagged, line, fname);
+		return -1;
+	}
+#ifdef CONFIG_VLAN_TAGGED
+	if (num_tagged == 0) {
+		vlan_alloc(&(acl->vlan_id), untagged, num_tagged, tagged);
+		return 1;
+	}
+	tagged = os_zalloc(sizeof(*tagged) * num_tagged);
+	if (!tagged) {
+		wpa_printf(MSG_ERROR, "Out of memory parsing '%s' at line %d "
+		           "in '%s'", buf, line, fname);
+		return -1;
+	}
+	for (i=0; i < num_tagged; i++) {
+		pos = pos2;
+		while (*pos2 != '\0' && *pos2 != ' ' &&
+		       *pos2 != '\t' && *pos2 != 't')
+			pos2++;
+		*pos2 = '\0'; pos2++;
+		tagged[i] = atoi(pos);
+		if (tagged[i] < 1 && tagged[i] > MAX_VLAN_ID) {
+			wpa_printf(MSG_ERROR, "Invalid tagged VLAN ID %d at "
+			           "line %d in '%s'", tagged[i], line, fname);
+			return -1;
+		}
+	}
+#endif /* CONFIG_VLAN_TAGGED */
+	vlan_alloc(&(acl->vlan_id), untagged, num_tagged, tagged);
+#ifdef CONFIG_VLAN_TAGGED
+	os_free(tagged);
+#endif /* CONFIG_VLAN_TAGGED */
+#endif /* CONFIG_NO_VLAN */
+
+	return 1;
+}
+
+
 static int hostapd_config_read_maclist(const char *fname,
 				       struct mac_acl_entry **acl, int *num)
 {
 	FILE *f;
-	char buf[128], *pos;
-	int line = 0;
-	u8 addr[ETH_ALEN];
-	struct mac_acl_entry *newacl;
-	vlan_t vlan_id = VLAN_NULL;
+	char buf[128];
+	int line = 0, ret;
+	struct mac_acl_entry *newacl, aclentry;
 
 	if (!fname)
 		return 0;
@@ -136,35 +325,13 @@ static int hostapd_config_read_maclist(const char *fname,
 
 	while (fgets(buf, sizeof(buf), f)) {
 		line++;
-
-		if (buf[0] == '#')
-			continue;
-		pos = buf;
-		while (*pos != '\0') {
-			if (*pos == '\n') {
-				*pos = '\0';
-				break;
-			}
-			pos++;
-		}
-		if (buf[0] == '\0')
-			continue;
-
-		if (hwaddr_aton(buf, addr)) {
-			wpa_printf(MSG_ERROR, "Invalid MAC address '%s' at "
-				   "line %d in '%s'", buf, line, fname);
+		ret = hostapd_config_parse_mac(buf, fname, line, &aclentry);
+		if (ret < 0) {
 			fclose(f);
-			return -1;
+			return ret;
 		}
-
-		vlan_id = VLAN_NULL;
-		pos = buf;
-		while (*pos != '\0' && *pos != ' ' && *pos != '\t')
-			pos++;
-		while (*pos == ' ' || *pos == '\t')
-			pos++;
-		if (*pos != '\0')
-			vlan_alloc(&vlan_id, atoi(pos), 0, NULL);
+		if (ret == 0)
+			continue;
 
 		newacl = os_realloc_array(*acl, *num + 1, sizeof(**acl));
 		if (newacl == NULL) {
@@ -172,12 +339,9 @@ static int hostapd_config_read_maclist(const char *fname,
 			fclose(f);
 			return -1;
 		}
-
 		*acl = newacl;
-		os_memcpy((*acl)[*num].addr, addr, ETH_ALEN);
-		vlan_alloc_copy(&(*acl)[*num].vlan_id, &vlan_id);
+		os_memcpy(&((*acl)[*num]), &aclentry, sizeof(aclentry));
 		(*num)++;
-		vlan_free(&vlan_id);
 	}
 
 	fclose(f);
