Macvlan does not permit multiple BRIDGE type interfaces on the same lowerdev to share their mac address. So in order to share the lowerdev of the macvlan interfaces required by ft_iface and rsn_preauth_interfaces, they need to share their macvlan interface as well. Signed-off-by: Michael Braun <michael-dev@xxxxxxxxxxxxx> --- hostapd/Makefile | 1 + src/ap/hostapd.h | 3 ++ src/ap/macvlan.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++-- src/ap/macvlan.h | 16 +++++- src/ap/preauth_auth.c | 5 +- src/ap/wpa_auth_glue.c | 6 ++- 6 files changed, 162 insertions(+), 10 deletions(-) diff --git a/hostapd/Makefile b/hostapd/Makefile index 349d302..158fb6e 100644 --- a/hostapd/Makefile +++ b/hostapd/Makefile @@ -867,6 +867,7 @@ endif ifdef NEED_MACVLAN ifdef CONFIG_LIBNL32 ifdef CONFIG_LIBNL3_ROUTE +CFLAGS += -DCONFIG_NEED_MACVLAN OBJS += ../src/ap/macvlan.o LIBS += -lnl-3 LIBS += -lnl-genl-3 diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 22aa6fa..74919a2 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -53,6 +53,9 @@ struct hapd_interfaces { #ifndef CONFIG_NO_VLAN struct dynamic_iface *vlan_priv; #endif /* CONFIG_NO_VLAN */ +#ifdef CONFIG_NEED_MACVLAN + struct macvlan_iface *macvlan_priv; +#endif /* CONFIG_NEED_MACVLAN */ int eloop_initialized; }; diff --git a/src/ap/macvlan.c b/src/ap/macvlan.c index 683d632..06fdb9f 100644 --- a/src/ap/macvlan.c +++ b/src/ap/macvlan.c @@ -7,16 +7,109 @@ */ #include "utils/includes.h" - #include "utils/common.h" +#include "hostapd.h" #ifdef CONFIG_LIBNL3_ROUTE #include <netlink/route/link.h> #include <netlink/route/link/macvlan.h> +#endif /* CONFIG_LIBNL3_ROUTE */ + #include "macvlan.h" -int macvlan_add(const char *if_name, const u8 *addr, const char *if_base) +struct macvlan_iface { + char if_name[IFNAMSIZ + 1]; + char if_base[IFNAMSIZ + 1]; + u8 addr[ETH_ALEN]; + int usage; + struct macvlan_iface *next; +}; + + +/* Increment ref counter for if_name */ +static struct macvlan_iface * macvlan_list_get(struct hostapd_data *hapd, + const char *if_base, + const u8 *addr) +{ + struct macvlan_iface *next, **macvlan_ifaces; + struct hapd_interfaces *interfaces; + + interfaces = hapd->iface->interfaces; + macvlan_ifaces = &interfaces->macvlan_priv; + + for (next = *macvlan_ifaces; next; next = next->next) { + if (os_strcmp(if_base, next->if_base) == 0 && + os_memcmp(addr, next->addr, sizeof(next->addr)) == 0) + break; + } + + if (next) + next->usage++; + + return next; +} + + +static void macvlan_list_add(struct hostapd_data *hapd, const char *if_name, + const char *if_base, const u8 *addr) +{ + struct macvlan_iface *next, **macvlan_ifaces; + struct hapd_interfaces *interfaces; + + interfaces = hapd->iface->interfaces; + macvlan_ifaces = &interfaces->macvlan_priv; + + next = os_zalloc(sizeof(*next)); + if (!next) + return; + + os_strlcpy(next->if_name, if_name, sizeof(next->if_name)); + os_strlcpy(next->if_base, if_base, sizeof(next->if_base)); + os_memcpy(next->addr, addr, sizeof(next->addr)); + next->usage = 1; + next->next = *macvlan_ifaces; + *macvlan_ifaces = next; +} + + +/* Decrement reference counter for given if_name. + * Return 1 iff reference counter was decreased to zero, else zero + */ +static int macvlan_list_put(struct hostapd_data *hapd, const char *if_name) +{ + struct macvlan_iface *next, *prev = NULL, **macvlan_ifaces; + struct hapd_interfaces *interfaces; + + interfaces = hapd->iface->interfaces; + macvlan_ifaces = &interfaces->macvlan_priv; + + for (next = *macvlan_ifaces; next; next = next->next) { + if (os_strcmp(if_name, next->if_name) == 0) + break; + prev = next; + } + + if (!next) + return 0; + + next->usage--; + if (next->usage) + return 0; + + if (prev) + prev->next = next->next; + else + *macvlan_ifaces = next->next; + os_free(next); + + return 1; +} + + +#ifdef CONFIG_LIBNL3_ROUTE +static int macvlan_iface_add(const char *if_name, const u8 *addr, + const char *if_base) { int err; struct rtnl_link *link = NULL; @@ -86,13 +179,14 @@ macvlan_add_error: } -int macvlan_del(const char *if_name) +static int macvlan_iface_del(const char *if_name) { int ret = -1; struct nl_sock *handle = NULL; struct rtnl_link *rlink = NULL; - wpa_printf(MSG_DEBUG, "MACVLAN: macvlan_del(if_name=%s)", if_name); + wpa_printf(MSG_DEBUG, "MACVLAN: macvlan_iface_del(if_name=%s)", + if_name); handle = nl_socket_alloc(); if (!handle) { @@ -128,3 +222,42 @@ macvlan_del_error: return ret; } #endif /* CONFIG_LIBNL3_ROUTE */ + + +/* create or reuse macvlan interface + * @param if_name proposed name, may be altered if required + * @param addr mac-address + * @param if_base macvlan lowerdev + * + * @returns 0 on success, negative error code else + */ +int macvlan_add(struct hostapd_data *hapd, char *if_name, size_t len, + const u8 *addr, const char *if_base) +{ + struct macvlan_iface *info; + int ret; + + info = macvlan_list_get(hapd, if_base, addr); + + if (info) { + os_strlcpy(if_name, info->if_name, len); + return 0; + } + + ret = macvlan_iface_add(if_name, addr, if_base); + if (ret == 0) + macvlan_list_add(hapd, if_name, if_base, addr); + + return ret; +} + + +int macvlan_del(struct hostapd_data *hapd, const char *if_name) +{ + wpa_printf(MSG_DEBUG, "MACVLAN: macvlan_del(if_name=%s)", if_name); + + if (macvlan_list_put(hapd, if_name)) + return macvlan_iface_del(if_name); + else + return 0; +} diff --git a/src/ap/macvlan.h b/src/ap/macvlan.h index c97373b..49f91f9 100644 --- a/src/ap/macvlan.h +++ b/src/ap/macvlan.h @@ -2,8 +2,20 @@ #define HOSTAPD_MACVLAN_H #ifdef CONFIG_LIBNL3_ROUTE -int macvlan_add(const char *if_name, const u8 *addr, const char *if_base); -int macvlan_del(const char *if_name); + +/* create or reuse macvlan interface if_name + * @param if_name macvlan interface name, may be altered + * @param len size of if_name buffer + * @param addr hw ether address + * @param if_base macvlan lowerdev + * + * @returns negative error code or 0 on success + */ +int macvlan_add(struct hostapd_data *hapd, char *if_name, size_t len, + const u8 *addr, const char *if_base); + +int macvlan_del(struct hostapd_data *hapd, const char *if_name); + #endif /* CONFIG_LIBNL3_ROUTE */ #endif diff --git a/src/ap/preauth_auth.c b/src/ap/preauth_auth.c index 7ff4323..835f0bc 100644 --- a/src/ap/preauth_auth.c +++ b/src/ap/preauth_auth.c @@ -140,7 +140,8 @@ static int rsn_preauth_iface_add(struct hostapd_data *hapd, const char *ifname, #ifdef CONFIG_RSN_PREAUTH_MACVLAN snprintf(macvlan_iface, sizeof(macvlan_iface), "pre%d%s", idx, hapd->conf->iface); - if (macvlan_add(macvlan_iface, hapd->own_addr, ifname) < 0 || + if (macvlan_add(hapd, macvlan_iface, sizeof(macvlan_iface), + hapd->own_addr, ifname) < 0 || ifconfig_up(macvlan_iface) < 0) { wpa_printf(MSG_ERROR, "Failed to add bssid to " "rsn_preauth_interface %s", ifname); @@ -188,7 +189,7 @@ void rsn_preauth_iface_deinit(struct hostapd_data *hapd) #ifdef CONFIG_RSN_PREAUTH_MACVLAN if (prev->is_macvlan) { ifconfig_down(prev->ifname); - macvlan_del(prev->ifname); + macvlan_del(hapd, prev->ifname); } #endif /* CONFIG_RSN_PREAUTH_MACVLAN */ l2_packet_deinit(prev->l2); diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 2d80714..7161913 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -1045,7 +1045,9 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) snprintf(hapd->conf->ft_macvlan, sizeof(hapd->conf->ft_macvlan), "ft%s", hapd->conf->iface); - if (macvlan_add(hapd->conf->ft_macvlan, + if (macvlan_add(hapd, + hapd->conf->ft_macvlan, + sizeof(hapd->conf->ft_macvlan), hapd->own_addr, ft_iface) < 0 || ifconfig_up(hapd->conf->ft_macvlan) < 0) { wpa_printf(MSG_ERROR, "Failed to add bssid to " @@ -1109,7 +1111,7 @@ void hostapd_deinit_wpa(struct hostapd_data *hapd) #ifdef CONFIG_IEEE80211R_MACVLAN if (hapd->conf->ft_macvlan[0]) { ifconfig_down(hapd->conf->ft_macvlan); - macvlan_del(hapd->conf->ft_macvlan); + macvlan_del(hapd, hapd->conf->ft_macvlan); } #endif /* CONFIG_IEEE80211R_MACVLAN */ l2_packet_deinit(hapd->l2); -- 2.1.4 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap