Browse Source

Added support for setting VLAN ID for STAs based on local MAC ACL

This allows the accept_mac_file to be used as an alternative for RADIUS
server-based configuration. This is mainly to ease VLAN testing (i.e., no
need to set up RADIUS server for this anymore).
Jouni Malinen 16 years ago
parent
commit
271d2830ff
7 changed files with 55 additions and 20 deletions
  1. 3 0
      hostapd/ChangeLog
  2. 32 9
      hostapd/config.c
  3. 9 3
      hostapd/config.h
  4. 3 2
      hostapd/hostapd.accept
  5. 2 1
      hostapd/hostapd.conf
  6. 2 2
      hostapd/ieee802_11_auth.c
  7. 4 3
      hostapd/reconfig.c

+ 3 - 0
hostapd/ChangeLog

@@ -7,6 +7,9 @@ ChangeLog for hostapd
 	  identity lengths)
 	* fixed internal TLSv1 implementation for abbreviated handshake (used
 	  by EAP-FAST server)
+	* added support for setting VLAN ID for STAs based on local MAC ACL
+	  (accept_mac_file) as an alternative for RADIUS server-based
+	  configuration
 
 2008-08-10 - v0.6.4
 	* added peer identity into EAP-FAST PAC-Opaque and skip Phase 2

+ 32 - 9
hostapd/config.c

@@ -270,14 +270,23 @@ int hostapd_mac_comp_empty(const void *a)
 }
 
 
-static int hostapd_config_read_maclist(const char *fname, macaddr **acl,
-				       int *num)
+static int hostapd_acl_comp(const void *a, const void *b)
+{
+	const struct mac_acl_entry *aa = a;
+	const struct mac_acl_entry *bb = b;
+	return os_memcmp(aa->addr, bb->addr, sizeof(macaddr));
+}
+
+
+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];
-	macaddr *newacl;
+	struct mac_acl_entry *newacl;
+	int vlan_id;
 
 	if (!fname)
 		return 0;
@@ -311,7 +320,16 @@ static int hostapd_config_read_maclist(const char *fname, macaddr **acl,
 			return -1;
 		}
 
-		newacl = os_realloc(*acl, (*num + 1) * ETH_ALEN);
+		vlan_id = 0;
+		pos = buf;
+		while (*pos != '\0' && *pos != ' ' && *pos != '\t')
+			pos++;
+		while (*pos == ' ' || *pos == '\t')
+			pos++;
+		if (*pos != '\0')
+			vlan_id = atoi(pos);
+
+		newacl = os_realloc(*acl, (*num + 1) * sizeof(**acl));
 		if (newacl == NULL) {
 			printf("MAC list reallocation failed\n");
 			fclose(f);
@@ -319,13 +337,14 @@ static int hostapd_config_read_maclist(const char *fname, macaddr **acl,
 		}
 
 		*acl = newacl;
-		os_memcpy((*acl)[*num], addr, ETH_ALEN);
+		os_memcpy((*acl)[*num].addr, addr, ETH_ALEN);
+		(*acl)[*num].vlan_id = vlan_id;
 		(*num)++;
 	}
 
 	fclose(f);
 
-	qsort(*acl, *num, sizeof(macaddr), hostapd_mac_comp);
+	qsort(*acl, *num, sizeof(**acl), hostapd_acl_comp);
 
 	return 0;
 }
@@ -2167,7 +2186,8 @@ void hostapd_config_free(struct hostapd_config *conf)
 
 /* Perform a binary search for given MAC address from a pre-sorted list.
  * Returns 1 if address is in the list or 0 if not. */
-int hostapd_maclist_found(macaddr *list, int num_entries, const u8 *addr)
+int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
+			  const u8 *addr, int *vlan_id)
 {
 	int start, end, middle, res;
 
@@ -2176,9 +2196,12 @@ int hostapd_maclist_found(macaddr *list, int num_entries, const u8 *addr)
 
 	while (start <= end) {
 		middle = (start + end) / 2;
-		res = os_memcmp(list[middle], addr, ETH_ALEN);
-		if (res == 0)
+		res = os_memcmp(list[middle].addr, addr, ETH_ALEN);
+		if (res == 0) {
+			if (vlan_id)
+				*vlan_id = list[middle].vlan_id;
 			return 1;
+		}
 		if (res < 0)
 			start = middle + 1;
 		else

+ 9 - 3
hostapd/config.h

@@ -26,6 +26,11 @@
 
 typedef u8 macaddr[ETH_ALEN];
 
+struct mac_acl_entry {
+	macaddr addr;
+	int vlan_id;
+};
+
 struct hostapd_radius_servers;
 struct ft_remote_r0kh;
 struct ft_remote_r1kh;
@@ -192,9 +197,9 @@ struct hostapd_bss_config {
 		DENY_UNLESS_ACCEPTED = 1,
 		USE_EXTERNAL_RADIUS_AUTH = 2
 	} macaddr_acl;
-	macaddr *accept_mac;
+	struct mac_acl_entry *accept_mac;
 	int num_accept_mac;
-	macaddr *deny_mac;
+	struct mac_acl_entry *deny_mac;
 	int num_deny_mac;
 
 	int auth_algs; /* bitfield of allowed IEEE 802.11 authentication
@@ -359,7 +364,8 @@ int hostapd_mac_comp(const void *a, const void *b);
 int hostapd_mac_comp_empty(const void *a);
 struct hostapd_config * hostapd_config_read(const char *fname);
 void hostapd_config_free(struct hostapd_config *conf);
-int hostapd_maclist_found(macaddr *list, int num_entries, const u8 *addr);
+int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries,
+			  const u8 *addr, int *vlan_id);
 int hostapd_rate_found(int *list, int rate);
 int hostapd_wep_key_cmp(struct hostapd_wep_keys *a,
 			struct hostapd_wep_keys *b);

+ 3 - 2
hostapd/hostapd.accept

@@ -1,5 +1,6 @@
 # List of MAC addresses that are allowed to authenticate (IEEE 802.11)
-# with the AP.
+# with the AP. Optional VLAN ID can be assigned for clients based on the
+# MAC address if dynamic VLANs (hostapd.conf dynamic_vlan option) are used.
 00:11:22:33:44:55
 00:66:77:88:99:aa
-00:00:22:33:44:55
+00:00:22:33:44:55	1

+ 2 - 1
hostapd/hostapd.conf

@@ -583,7 +583,8 @@ own_ip_addr=127.0.0.1
 # attributes based on RFC 3580 and RFC 2868: Tunnel-Type (value 13 = VLAN),
 # Tunnel-Medium-Type (value 6 = IEEE 802), Tunnel-Private-Group-ID (value
 # VLANID as a string). vlan_file option below must be configured if dynamic
-# VLANs are used.
+# VLANs are used. Optionally, the local MAC ACL list (accept_mac_file) can be
+# used to set static client MAC address to VLAN ID mapping.
 # 0 = disabled (default)
 # 1 = option; use default interface if RADIUS server does not include VLAN ID
 # 2 = required; reject authentication if RADIUS server does not include VLAN ID

+ 2 - 2
hostapd/ieee802_11_auth.c

@@ -205,11 +205,11 @@ int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr,
 		*vlan_id = 0;
 
 	if (hostapd_maclist_found(hapd->conf->accept_mac,
-				  hapd->conf->num_accept_mac, addr))
+				  hapd->conf->num_accept_mac, addr, vlan_id))
 		return HOSTAPD_ACL_ACCEPT;
 
 	if (hostapd_maclist_found(hapd->conf->deny_mac,
-				  hapd->conf->num_deny_mac, addr))
+				  hapd->conf->num_deny_mac, addr, vlan_id))
 		return HOSTAPD_ACL_REJECT;
 
 	if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED)

+ 4 - 3
hostapd/reconfig.c

@@ -211,13 +211,14 @@ static int hostapd_acl_diff(struct hostapd_bss_config *a,
 		return 1;
 
 	for (i = 0; i < a->num_accept_mac; i++) {
-		if (os_memcmp(a->accept_mac[i], b->accept_mac[i], ETH_ALEN) !=
-		    0)
+		if (os_memcmp(a->accept_mac[i].addr, b->accept_mac[i].addr,
+			      ETH_ALEN) != 0)
 			return 1;
 	}
 
 	for (i = 0; i < a->num_deny_mac; i++) {
-		if (os_memcmp(a->deny_mac[i], b->deny_mac[i], ETH_ALEN) != 0)
+		if (os_memcmp(a->deny_mac[i].addr, b->deny_mac[i].addr,
+			      ETH_ALEN) != 0)
 			return 1;
 	}