Patchwork IAPP: Send layer 2 updates to the bridge, not the IAPP interface

login
register
mail settings
Submitter Alban Bedel
Date April 12, 2013, 10:46 p.m.
Message ID <1365806793-18914-1-git-send-email-albeu@free.fr>
Download mbox | patch
Permalink /patch/236255/
State New
Headers show

Comments

Alban Bedel - April 12, 2013, 10:46 p.m.
Layer 2 updates only make sense if the wifi interface is bridged and
should be sent to the bridge, not the IAPP interface. This is important
in setups where the wifi clients are in a different layer 2 network
than the one used for RADIUS, IAPP, etc.

Signed-hostap: Alban Bedel <albeu@free.fr>
---
 src/ap/hostapd.c |    4 +++-
 src/ap/iapp.c    |   54 +++++++++++++++++++++++++++++++++++++++---------------
 src/ap/iapp.h    |    6 ++++--
 3 files changed, 46 insertions(+), 18 deletions(-)

Patch

diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index a0ac38c..f200156 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -781,7 +781,9 @@  static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
 	}
 
 	if (hapd->conf->ieee802_11f &&
-	    (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface)) == NULL) {
+	    (hapd->iapp = iapp_init(hapd, hapd->conf->iapp_iface,
+				    hapd->conf->bridge[0] ? hapd->conf->bridge :
+				    NULL)) == NULL) {
 		wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization "
 			   "failed.");
 		return -1;
diff --git a/src/ap/iapp.c b/src/ap/iapp.c
index be55c69..346e659 100644
--- a/src/ap/iapp.c
+++ b/src/ap/iapp.c
@@ -214,6 +214,8 @@  static void iapp_send_layer2_update(struct iapp_data *iapp, u8 *addr)
 
 	/* Send Level 2 Update Frame to update forwarding tables in layer 2
 	 * bridge devices */
+	if (iapp->packet_sock < 0)
+		return;
 
 	/* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
 	 * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */
@@ -382,11 +384,46 @@  static void iapp_receive_udp(int sock, void *eloop_ctx, void *sock_ctx)
 }
 
 
-struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface)
+static int iapp_init_layer2(struct iapp_data *iapp, const char *bridge)
 {
 	struct ifreq ifr;
 	struct sockaddr_ll addr;
 	int ifindex;
+
+	/* Layer 2 updates only make sense when the wifi interface is bridged */
+	if (!bridge)
+		return 0;
+
+	iapp->packet_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+	if (iapp->packet_sock < 0) {
+		perror("socket[PF_PACKET,SOCK_RAW]");
+		return -1;
+	}
+
+	os_memset(&ifr, 0, sizeof(ifr));
+	os_strlcpy(ifr.ifr_name, bridge, sizeof(ifr.ifr_name));
+	if (ioctl(iapp->packet_sock, SIOCGIFINDEX, &ifr) != 0) {
+		perror("ioctl(SIOCGIFINDEX)");
+		return -1;
+	}
+	ifindex = ifr.ifr_ifindex;
+
+	os_memset(&addr, 0, sizeof(addr));
+	addr.sll_family = AF_PACKET;
+	addr.sll_ifindex = ifindex;
+	if (bind(iapp->packet_sock, (struct sockaddr *) &addr,
+		 sizeof(addr)) < 0) {
+		perror("bind[PACKET]");
+		return -1;
+	}
+
+	return 0;
+}
+
+struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface,
+			     const char *bridge)
+{
+	struct ifreq ifr;
 	struct sockaddr_in *paddr, uaddr;
 	struct iapp_data *iapp;
 	struct ip_mreqn mreq;
@@ -415,7 +452,6 @@  struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface)
 		iapp_deinit(iapp);
 		return NULL;
 	}
-	ifindex = ifr.ifr_ifindex;
 
 	if (ioctl(iapp->udp_sock, SIOCGIFADDR, &ifr) != 0) {
 		perror("ioctl(SIOCGIFADDR)");
@@ -466,19 +502,7 @@  struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface)
 		return NULL;
 	}
 
-	iapp->packet_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
-	if (iapp->packet_sock < 0) {
-		perror("socket[PF_PACKET,SOCK_RAW]");
-		iapp_deinit(iapp);
-		return NULL;
-	}
-
-	os_memset(&addr, 0, sizeof(addr));
-	addr.sll_family = AF_PACKET;
-	addr.sll_ifindex = ifindex;
-	if (bind(iapp->packet_sock, (struct sockaddr *) &addr,
-		 sizeof(addr)) < 0) {
-		perror("bind[PACKET]");
+	if (iapp_init_layer2(iapp, bridge) < 0) {
 		iapp_deinit(iapp);
 		return NULL;
 	}
diff --git a/src/ap/iapp.h b/src/ap/iapp.h
index c221183..fa47356 100644
--- a/src/ap/iapp.h
+++ b/src/ap/iapp.h
@@ -14,7 +14,8 @@  struct iapp_data;
 #ifdef CONFIG_IAPP
 
 void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta);
-struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface);
+struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface,
+			     const char *bridge);
 void iapp_deinit(struct iapp_data *iapp);
 
 #else /* CONFIG_IAPP */
@@ -25,7 +26,8 @@  static inline void iapp_new_station(struct iapp_data *iapp,
 }
 
 static inline struct iapp_data * iapp_init(struct hostapd_data *hapd,
-					   const char *iface)
+					   const char *iface,
+					   const char *bridge)
 {
 	return NULL;
 }