[PATCH 10/44] FT: RRB messages can be exchanged in a separate interface/VLAN
michael-dev at fami-braun.de
michael-dev at fami-braun.de
Wed Feb 24 03:53:16 PST 2016
From: Michael Braun <michael-dev at fami-braun.de>
To receive messages in a separate FT-RRB-VLAN for the local bssid,
the bridge code needs to have a local fdb entry for the bssid.
This is achieved by adding dummy interfaces to ft_bridge.
Signed-off-by: Michael Braun <michael-dev at fami-braun.de>
---
hostapd/Makefile | 5 +++
hostapd/config_file.c | 2 +
hostapd/hostapd.conf | 27 +++++++++++
src/ap/ap_config.h | 1 +
src/ap/dummy.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++
src/ap/dummy.h | 10 +++++
src/ap/wpa_auth_glue.c | 50 +++++++++++++++++++--
7 files changed, 210 insertions(+), 3 deletions(-)
create mode 100644 src/ap/dummy.c
create mode 100644 src/ap/dummy.h
diff --git a/hostapd/Makefile b/hostapd/Makefile
index 1c1e98f..47587e6 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -190,6 +190,10 @@ else
OBJS += ../src/ap/accounting.o
endif
+ifdef CONFIG_80211R
+NEED_BRIDGE=y
+NEED_IFCONFIG=y
+endif
ifndef CONFIG_NO_VLAN
NEED_BRIDGE=y
NEED_IFCONFIG=y
@@ -269,6 +273,7 @@ endif
ifdef CONFIG_IEEE80211R
CFLAGS += -DCONFIG_IEEE80211R
OBJS += ../src/ap/wpa_auth_ft.o
+OBJS += ../src/ap/dummy.o
NEED_SHA256=y
NEED_AES_OMAC1=y
NEED_AES_UNWRAP=y
diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index a157a74..1531c59 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -2000,6 +2000,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
os_strlcpy(bss->vlan_bridge, pos, sizeof(bss->vlan_bridge));
} else if (os_strcmp(buf, "wds_bridge") == 0) {
os_strlcpy(bss->wds_bridge, pos, sizeof(bss->wds_bridge));
+ } else if (os_strcmp(buf, "ft_bridge") == 0) {
+ os_strlcpy(bss->ft_bridge, pos, sizeof(bss->ft_bridge));
} else if (os_strcmp(buf, "driver") == 0) {
int j;
/* clear to get error below if setting is invalid */
diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
index d535eec..2c18495 100644
--- a/hostapd/hostapd.conf
+++ b/hostapd/hostapd.conf
@@ -1266,6 +1266,33 @@ own_ip_addr=127.0.0.1
# (dot11FTReassociationDeadline)
#reassociation_deadline=1000
+# 802.11r Inter-AP communication
+# When a station roams, it is connected to a current AP and wants to connect to
+# a target AP (R1KH). The station initially connected to an AP (R0KH) before
+# it roams around to the current AP.
+#
+# Now there are two communication patterns you need to be aware of:
+# Over-Air: STA <--> target AP (R1KH) <--> initial AP (R0KH)
+# Over-DS: STA <--> current AP <--> target AP (R1KH) <--> initial AP (R0KH)
+#
+# Communication between the APs is done using a layer-2 protocol, that is to
+# say that addressing is done using MAC addresses.
+# The current AP <--> target AP communication uses the BSSID for addressing and
+# is unencrypted. Thus, both ends need to be listening to their BSSID.
+# The R1KH <--> R0KH communication uses the mac addresses and keys given in the
+# r0kh and r1kh lists below. R1KH looks up the R0KH configuration using R0KH-ID
+# when sending and using MAC address when receiving. Thus both need to be
+# unique. R0KH looks up r1kh configuration using mac address when receiving and
+# replying; it will use R1KH-ID to derive 802.11r data only when pushing to all
+# R1KH in its list.
+# Sending and receiving is done using ft_bridge, which defaults to bridge or
+# iface if unset.
+
+# Use a different Bridge for 802.11r inter-AP communication
+# This bridge needs to listen to packets destined for BSSID, so when set,
+# hostapd will add dummy ft%iface interfaces to bridge to ensure that.
+#ft_bridge=
+
# List of R0KHs in the same Mobility Domain
# format: <MAC address> <NAS Identifier> <128-bit key as hex string>
# This list is used to map R0KH-ID (NAS Identifier) to a destination MAC
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index 4b039b4..64143e5 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -224,6 +224,7 @@ struct hostapd_bss_config {
char bridge[IFNAMSIZ + 1];
char vlan_bridge[IFNAMSIZ + 1];
char wds_bridge[IFNAMSIZ + 1];
+ char ft_bridge[IFNAMSIZ + 1];
enum hostapd_logger_level logger_syslog_level, logger_stdout_level;
diff --git a/src/ap/dummy.c b/src/ap/dummy.c
new file mode 100644
index 0000000..642348d
--- /dev/null
+++ b/src/ap/dummy.c
@@ -0,0 +1,118 @@
+/*
+ * hostapd / WPA authenticator glue code
+ * Copyright (c) 2002-2012, Jouni Malinen <j at w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+
+#include "utils/common.h"
+
+#ifdef CONFIG_LIBNL3_ROUTE
+#include <netlink/route/link.h>
+#include "dummy.h"
+
+
+int dummy_add(const char *if_name, const u8 *addr)
+{
+ int err;
+ struct rtnl_link *link = NULL;
+ struct nl_addr *nl_addr = NULL;
+ struct nl_sock *handle = NULL;
+ int ret = -1;
+
+ handle = nl_socket_alloc();
+ if (!handle) {
+ wpa_printf(MSG_ERROR, "DUMMY: failed to open netlink socket");
+ goto dummy_add_error;
+ }
+
+ if (nl_connect(handle, NETLINK_ROUTE) < 0) {
+ wpa_printf(MSG_ERROR, "DUMMY: failed to connect to netlink");
+ goto dummy_add_error;
+ }
+
+ link = rtnl_link_alloc();
+ if (!link) {
+ wpa_printf(MSG_ERROR, "DUMMY: failed to allocate link");
+ goto dummy_add_error;
+ }
+
+ err = rtnl_link_set_type(link, "dummy");
+ if (err < 0) {
+ wpa_printf(MSG_ERROR,
+ "DUMMY: failed to set link type to dummy");
+ goto dummy_add_error;
+ }
+
+ nl_addr = nl_addr_build(AF_BRIDGE, (void *) addr, ETH_ALEN);
+ if (!nl_addr) {
+ wpa_printf(MSG_ERROR, "DUMMY: failed to parse addr");
+ goto dummy_add_error;
+ }
+ rtnl_link_set_addr(link, nl_addr);
+ nl_addr_put(nl_addr);
+
+ rtnl_link_set_name(link, if_name);
+
+ err = rtnl_link_add(handle, link, NLM_F_CREATE);
+ if (err < 0) {
+ wpa_printf(MSG_ERROR, "DUMMY: failed to create link");
+ goto dummy_add_error;
+ }
+ ret = 0;
+
+dummy_add_error:
+ if (link)
+ rtnl_link_put(link);
+
+ if (handle)
+ nl_socket_free(handle);
+ return ret;
+}
+
+
+int dummy_del(const char *if_name)
+{
+ int ret = -1;
+ struct nl_sock *handle = NULL;
+ struct rtnl_link *rlink = NULL;
+
+ wpa_printf(MSG_DEBUG, "DUMMY: dummy_del(if_name=%s)", if_name);
+
+ handle = nl_socket_alloc();
+ if (!handle) {
+ wpa_printf(MSG_ERROR, "DUMMY: failed to open netlink socket");
+ goto dummy_del_error;
+ }
+
+ if (nl_connect(handle, NETLINK_ROUTE) < 0) {
+ wpa_printf(MSG_ERROR, "DUMMY: failed to connect to netlink");
+ goto dummy_del_error;
+ }
+
+ if (rtnl_link_get_kernel(handle, 0, if_name, &rlink) < 0) {
+ /* link does not exist */
+ wpa_printf(MSG_ERROR, "DUMMY: interface %s does not exists",
+ if_name);
+ goto dummy_del_error;
+ }
+
+ if (rtnl_link_delete(handle, rlink) < 0) {
+ wpa_printf(MSG_ERROR, "DUMMY: failed to remove link %s",
+ if_name);
+ goto dummy_del_error;
+ }
+
+ ret = 0;
+
+dummy_del_error:
+ if (rlink)
+ rtnl_link_put(rlink);
+ if (handle)
+ nl_socket_free(handle);
+ return ret;
+}
+#endif /* CONFIG_LIBNL3_ROUTE */
diff --git a/src/ap/dummy.h b/src/ap/dummy.h
new file mode 100644
index 0000000..619bf3f
--- /dev/null
+++ b/src/ap/dummy.h
@@ -0,0 +1,10 @@
+#ifndef HOSTAPD_DUMMY_H
+#define HOSTAPD_DUMMY_H
+
+#ifdef CONFIG_LIBNL3_ROUTE
+int dummy_add(const char *if_name, const u8 *addr);
+int dummy_del(const char *if_name);
+#endif /* CONFIG_LIBNL3_ROUTE */
+
+#endif
+
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index e7042ef..ec82080 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -25,6 +25,13 @@
#include "ap_config.h"
#include "wpa_auth.h"
#include "wpa_auth_glue.h"
+#include <stdlib.h>
+
+#ifdef CONFIG_IEEE80211R
+#include "bridge.h"
+#include "dummy.h"
+#include "ifconfig.h"
+#endif /* CONFIG_IEEE80211R */
static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
@@ -697,6 +704,12 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
struct wpa_auth_callbacks cb;
const u8 *wpa_ie;
size_t wpa_ie_len;
+#ifdef CONFIG_IEEE80211R
+ const char *ft_iface;
+#ifdef CONFIG_LIBNL3_ROUTE
+ char dummy_iface[IFNAMSIZ+1];
+#endif /* CONFIG_LIBNL3_ROUTE */
+#endif /* CONFIG_IEEE80211R */
hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &_conf);
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS)
@@ -754,9 +767,25 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
#ifdef CONFIG_IEEE80211R
if (!hostapd_drv_none(hapd) && hapd->conf->ft_over_ds &&
wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt)) {
- hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ?
- hapd->conf->bridge :
- hapd->conf->iface, NULL, ETH_P_RRB,
+ ft_iface = hapd->conf->iface;
+ if (hapd->conf->bridge[0])
+ ft_iface = hapd->conf->bridge;
+ if (hapd->conf->ft_bridge[0]) {
+ ft_iface = hapd->conf->ft_bridge;
+#ifdef CONFIG_LIBNL3_ROUTE
+ snprintf(dummy_iface, sizeof(dummy_iface), "ft%s",
+ hapd->conf->iface);
+ if (dummy_add(dummy_iface, hapd->own_addr) < 0 ||
+ ifconfig_up(dummy_iface) < 0 ||
+ br_addif(ft_iface, dummy_iface) < 0)
+ wpa_printf(MSG_ERROR, "Failed to add bssid to "
+ "ft_bridge %s", ft_iface);
+#else
+ wpa_printf(MSG_ERROR, "Missing libnl3 - bssid not added"
+ " to ft_bridge %s", ft_iface);
+#endif /* CONFIG_LIBNL3_ROUTE */
+ }
+ hapd->l2 = l2_packet_init(ft_iface, NULL, ETH_P_RRB,
hostapd_rrb_receive, hapd, 1);
if (hapd->l2 == NULL &&
(hapd->driver == NULL ||
@@ -783,6 +812,12 @@ void hostapd_reconfig_wpa(struct hostapd_data *hapd)
void hostapd_deinit_wpa(struct hostapd_data *hapd)
{
+#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_LIBNL3_ROUTE
+ char dummy_iface[IFNAMSIZ+1];
+#endif /* CONFIG_LIBNL3_ROUTE */
+#endif /* CONFIG_IEEE80211R */
+
ieee80211_tkip_countermeasures_deinit(hapd);
rsn_preauth_iface_deinit(hapd);
if (hapd->wpa_auth) {
@@ -805,6 +840,15 @@ void hostapd_deinit_wpa(struct hostapd_data *hapd)
ieee802_1x_deinit(hapd);
#ifdef CONFIG_IEEE80211R
+#ifdef CONFIG_LIBNL3_ROUTE
+ if (hapd->conf->ft_bridge[0]) {
+ snprintf(dummy_iface, sizeof(dummy_iface), "ft%s",
+ hapd->conf->iface);
+ ifconfig_down(dummy_iface);
+ br_delif(hapd->conf->ft_bridge, dummy_iface);
+ dummy_del(dummy_iface);
+ }
+#endif /* CONFIG_LIBNL3_ROUTE */
l2_packet_deinit(hapd->l2);
hapd->l2 = NULL;
#endif /* CONFIG_IEEE80211R */
--
1.9.1
More information about the Hostap
mailing list