[PATCH v5 15/22] parse untagged/tagged VLANs from config files
Michael Braun
michael-dev
Tue Nov 19 11:47:55 PST 2013
Signed-hostap: Michael Braun <michael-dev at fami-braun.de>
---
hostapd/config_file.c | 348 ++++++++++++++++++++++++++++++++++++-------------
1 file changed, 259 insertions(+), 89 deletions(-)
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 7926931..c6adbd8 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -26,76 +26,158 @@ extern struct wpa_driver_ops *wpa_drivers[];
#ifndef CONFIG_NO_VLAN
-static int hostapd_config_read_vlan_file(struct hostapd_bss_config *bss,
- const char *fname)
+/**
+ * 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)
{
- FILE *f;
- char buf[128], *pos, *pos2;
- int line = 0;
+ char *pos, *pos2;
struct vlan_description vlan_id = VLAN_NULL;
- struct hostapd_vlan *vlan;
+#ifdef CONFIG_VLAN_TAGGED
+ int i;
+#endif
- f = fopen(fname, "r");
- if (!f) {
- wpa_printf(MSG_ERROR, "VLAN file '%s' not readable.", fname);
- return -1;
+ *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;
- while (fgets(buf, sizeof(buf), f)) {
- line++;
+ 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;
- if (buf[0] == '#')
- continue;
pos = buf;
- while (*pos != '\0') {
- if (*pos == '\n') {
- *pos = '\0';
- break;
- }
- pos++;
+#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++;
}
- 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);
+ /* 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;
}
- vlan_alloc(&vlan_id, untagged_vlan_id, 0, NULL);
+ 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;
+ }
}
-
- 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);
+#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];
+ int line = 0, ret;
+ struct hostapd_vlan *vlan;
+
+ f = fopen(fname, "r");
+ if (!f) {
+ wpa_printf(MSG_ERROR, "VLAN file '%s' not readable.", 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);
+ while (fgets(buf, sizeof(buf), f)) {
+ line++;
+ 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,128 @@ 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];
+#ifndef CONFIG_NO_VLAN
+ int untagged = 0;
+#ifdef CONFIG_VLAN_TAGGED
+ int i;
+ char *pos2;
+ int num_tagged = 0;
+ int *tagged = NULL;
+#endif /* CONFIG_VLAN_TAGGED */
+#endif /* CONFIG_NO_VLAN */
+
+ 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 */
+#ifdef CONFIG_VLAN_TAGGED
+ vlan_alloc(&(acl->vlan_id), untagged, num_tagged, tagged);
+#else
+ vlan_alloc(&(acl->vlan_id), untagged, 0, NULL);
+#endif
+#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;
- struct vlan_description vlan_id = VLAN_NULL;
+ char buf[128];
+ int line = 0, ret;
+ struct mac_acl_entry *newacl, aclentry;
if (!fname)
return 0;
@@ -136,35 +331,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 +345,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);
More information about the Hostap
mailing list