[PATCH] getting dynamic vlans working with nl80211 [Re: dynamic vlans and hostap (HEAD) on nl80211 broken]

michael-dev at fami-braun.de michael-dev at fami-braun.de
Sun Mar 14 20:22:30 EDT 2010


Hi,

I've been trying to get dynamic vlans working on current git
hostapd. Doing so, I've encountered several issues, some of them
needed patch (patches attached). I've been using ath9k (nl80211).

1. attaching sta to vlan failes because the vlan device
   is not up. This needs vlan_init.c patching.
2. adding bridge brvlanXX interface id to list of known
   interfaces (addifx). Otherwise the EAPOL messages will
   be dropped. This requires driver_nl80211.c patching.
3. make addifx not forget all the entries in default_ifaces
   if that array overflows and is reallocated.
4. make the per vlan wlan device carry the correct MAC.
   Currently, the code always uses the mac of the first ssid,
   but the nl80211 driver won't deliver EAPOL packages
   there if they are headed of a different mac.
   This can be achieved by makeing the wpa enterprise network
   the first bssid in the config file.
5. prevent the linux bridge from staying in learning state
   for too long, otherwise EAPOL keying times out and
   needs another connect to succeed.

I can confirm that it works with the attached configuration file
using hostapd with an extra ipv6 link local addresses patch applied.

Sincerely,
 M. Braun
--

diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index 56032ab..e506f1a 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -246,6 +246,16 @@ static int br_addbr(const char *br_name)
                }
        }

+  struct ifreq ifr;
+  unsigned long args[4] = { BRCTL_SET_BRIDGE_FORWARD_DELAY, 1 /* value
*/, 0, 0 };
+  strncpy(ifr.ifr_name, br_name, IFNAMSIZ);
+  ifr.ifr_data = (char *) &args;
+  if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
+
perror("ioctl[SIOCDEVPRIVATE,BRCTL_SET_BRIDGE_FORWARD_DELAY]");
+               close(fd);
+               return -1;
+  }
+
        close(fd);
        return 0;
 }
@@ -783,6 +793,7 @@ struct hostapd_vlan * vlan_add_dynamic(struct
hostapd_data *hapd,

        n->next = hapd->conf->vlan;
        hapd->conf->vlan = n;
+       ifconfig_up(n->ifname);

        return n;
 }
@@ -807,6 +818,8 @@ int vlan_remove_dynamic(struct hostapd_data *hapd,
int vlan_id)
        if (vlan == NULL)
                return 1;

+  ifconfig_down(vlan->ifname);
+
        if (vlan->dynamic_vlan == 0)
                hapd->drv.vlan_if_remove(hapd, vlan->ifname);



diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 5759760..61048f5 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -139,6 +139,7 @@ static void nl80211_remove_monitor_interface(
 #ifdef HOSTAPD
 static void add_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
 static void del_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
+static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
 static int i802_set_freq(void *priv, struct hostapd_freq_params *freq);
 static int wpa_driver_nl80211_if_remove(void *priv,
 					enum wpa_driver_if_type type,
@@ -388,8 +390,9 @@ static void
wpa_driver_nl80211_event_rtm_newlink(void *ctx,
 	struct wpa_driver_nl80211_data *drv = ctx;
 	int attrlen, rta_len;
 	struct rtattr *attr;
+  uint32_t brid=0;

-	if (!wpa_driver_nl80211_own_ifindex(drv, ifi->ifi_index, buf, len)) {
+	if (!wpa_driver_nl80211_own_ifindex(drv, ifi->ifi_index, buf, len) &&
!have_ifidx(drv, ifi->ifi_index)) {
 		wpa_printf(MSG_DEBUG, "Ignore event for foreign ifindex %d",
 			   ifi->ifi_index);
 		return;
@@ -423,9 +426,20 @@ static void
wpa_driver_nl80211_event_rtm_newlink(void *ctx,
 				drv,
 				((char *) attr) + rta_len,
 				attr->rta_len - rta_len, 0);
-		}
+		} else if (attr->rta_type == IFLA_MASTER) {
+       brid = nla_get_u32((struct nlattr*)attr);
+    }
 		attr = RTA_NEXT(attr, attrlen);
 	}
+
+  if (ifi->ifi_family == AF_BRIDGE) {
+    /* device has been added to bridge */
+		char namebuf[IF_NAMESIZE];
+    if_indextoname(brid, namebuf);
+		wpa_printf(MSG_DEBUG, "nl80211: Add ifindex %u for bridge %s", brid,
namebuf);
+		add_ifidx(drv, brid);
+  }
+
 }


@@ -436,6 +450,7 @@ static void
wpa_driver_nl80211_event_rtm_dellink(void *ctx,
 	struct wpa_driver_nl80211_data *drv = ctx;
 	int attrlen, rta_len;
 	struct rtattr *attr;
+  uint32_t brid=0;

 	attrlen = len;
 	attr = (struct rtattr *) buf;
@@ -447,9 +462,19 @@ static void
wpa_driver_nl80211_event_rtm_dellink(void *ctx,
 				drv,
 				((char *) attr) + rta_len,
 				attr->rta_len - rta_len, 1);
+		} else if (attr->rta_type == IFLA_MASTER) {
+       brid = nla_get_u32((struct nlattr*)attr);
 		}
 		attr = RTA_NEXT(attr, attrlen);
 	}
+
+  if (ifi->ifi_family == AF_BRIDGE) {
+    /* device has been removed from bridge */
+		char namebuf[IF_NAMESIZE];
+    if_indextoname(brid, namebuf);
+		wpa_printf(MSG_DEBUG, "nl80211: Remove ifindex %u for bridge %s",
brid, namebuf);
+		del_ifidx(drv, brid);
+  }
 }


@@ -860,7 +885,7 @@ static int process_event(struct nl_msg *msg, void *arg)

 	if (tb[NL80211_ATTR_IFINDEX]) {
 		int ifindex = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
-		if (ifindex != drv->ifindex) {
+		if (ifindex != drv->ifindex && !have_ifidx(drv, ifindex)) {
 			wpa_printf(MSG_DEBUG, "nl80211: Ignored event (cmd=%d)"
 				   " for foreign interface (ifindex %d)",
 				   gnlh->cmd, ifindex);
@@ -4016,7 +4183,9 @@ static void add_ifidx(struct
wpa_driver_nl80211_data *drv, int ifidx)
 			   "interfaces");
 		wpa_printf(MSG_ERROR, "Ignoring EAPOL on interface %d", ifidx);
 		return;
-	}
+	} else if (!old) {
+		memcpy(drv->if_indices, drv->default_if_indices,
sizeof(drv->default_if_indices));
+  }
 	drv->if_indices[drv->num_if_indices] = ifidx;
 	drv->num_if_indices++;
 }


hostapd.conf
hw_mode=g
channel=1
ieee80211n=1

interface=wlan0

# 802.1X Login
ssid=private
wpa=2
wpa_key_mgmt=WPA-EAP WPA-PSK
ieee8021x=1
wpa_pairwise=CCMP
rsn_pairwise=CCMP

# replace with wpa_psk_file + vlans
wpa_passphrase=femfemfem

nas_identifier=fem-net.de
own_ip_addr=127.0.0.1

auth_server_addr=fe80::252%tinc
auth_server_shared_secret=$KEY$

acct_server_addr=fe80::252%tinc
acct_server_shared_secret=$KEY$

auth_server_addr=fe80::251%tinc
auth_server_shared_secret=$KEY$

acct_server_addr=fe80::251%tinc
acct_server_shared_secret=$KEY$

dynamic_vlan=2
vlan_tagged_interface=tinc
vlan_file=/etc/hostapd/hostapd-wlan0.vlan

rsn_preauth=1
rsn_preauth_interfaces=tinc

bss=wlan0_1
ssid=public
wpa=0
ieee8021x=0
bridge=br0

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 260 bytes
Desc: OpenPGP digital signature
Url : http://lists.shmoo.com/pipermail/hostap/attachments/20100315/d12890c8/attachment.pgp 


More information about the HostAP mailing list