Merge bss_add/bss_remove drivers ops into if_add/if_remove

if_add/if_remove can now be used as the generic driver ops for adding
and removing virtual interfaces of various types. In addition,
driver_nl80211.c is now including this code unconditionally, so that
the functions are not limited only for hostapd.
This commit is contained in:
Jouni Malinen 2009-12-09 16:49:28 +02:00 committed by Jouni Malinen
parent b5996353e7
commit 22a7c9d735
7 changed files with 154 additions and 125 deletions

View file

@ -371,22 +371,6 @@ hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs,
cw_min, cw_max, burst_time); cw_min, cw_max, burst_time);
} }
static inline int
hostapd_bss_add(struct hostapd_data *hapd, const char *ifname, const u8 *bssid)
{
if (hapd->driver == NULL || hapd->driver->bss_add == NULL)
return 0;
return hapd->driver->bss_add(hapd->drv_priv, ifname, bssid);
}
static inline int
hostapd_bss_remove(struct hostapd_data *hapd, const char *ifname)
{
if (hapd->driver == NULL || hapd->driver->bss_remove == NULL)
return 0;
return hapd->driver->bss_remove(hapd->drv_priv, ifname);
}
static inline int static inline int
hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr, hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
const u8 *mask) const u8 *mask)
@ -397,8 +381,8 @@ hostapd_valid_bss_mask(struct hostapd_data *hapd, const u8 *addr,
} }
static inline int static inline int
hostapd_if_add(struct hostapd_data *hapd, enum hostapd_driver_if_type type, hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
char *ifname, const u8 *addr) const char *ifname, const u8 *addr)
{ {
if (hapd->driver == NULL || hapd->driver->if_add == NULL) if (hapd->driver == NULL || hapd->driver->if_add == NULL)
return -1; return -1;
@ -407,12 +391,12 @@ hostapd_if_add(struct hostapd_data *hapd, enum hostapd_driver_if_type type,
} }
static inline int static inline int
hostapd_if_remove(struct hostapd_data *hapd, enum hostapd_driver_if_type type, hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
char *ifname, const u8 *addr) const char *ifname)
{ {
if (hapd->driver == NULL || hapd->driver->if_remove == NULL) if (hapd->driver == NULL || hapd->driver->if_remove == NULL)
return -1; return -1;
return hapd->driver->if_remove(hapd->drv_priv, type, ifname, addr); return hapd->driver->if_remove(hapd->drv_priv, type, ifname);
} }
static inline struct hostapd_hw_modes * static inline struct hostapd_hw_modes *

View file

@ -340,7 +340,7 @@ static void hostapd_cleanup(struct hostapd_data *hapd)
#endif /* EAP_SERVER_SIM || EAP_SERVER_AKA */ #endif /* EAP_SERVER_SIM || EAP_SERVER_AKA */
if (hapd->interface_added && if (hapd->interface_added &&
hostapd_bss_remove(hapd, hapd->conf->iface)) { hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) {
wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s", wpa_printf(MSG_WARNING, "Failed to remove BSS interface %s",
hapd->conf->iface); hapd->conf->iface);
} }
@ -1048,8 +1048,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
} }
hapd->interface_added = 1; hapd->interface_added = 1;
if (hostapd_bss_add(hapd->iface->bss[0], hapd->conf->iface, if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
hapd->own_addr)) { hapd->conf->iface, hapd->own_addr)) {
wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID=" wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID="
MACSTR ")", MAC2STR(hapd->own_addr)); MACSTR ")", MAC2STR(hapd->own_addr));
return -1; return -1;

View file

@ -680,8 +680,7 @@ static int vlan_dynamic_add(struct hostapd_data *hapd,
{ {
while (vlan) { while (vlan) {
if (vlan->vlan_id != VLAN_ID_WILDCARD && if (vlan->vlan_id != VLAN_ID_WILDCARD &&
hostapd_if_add(hapd, HOSTAPD_IF_VLAN, vlan->ifname, NULL)) hostapd_if_add(hapd, WPA_IF_AP_VLAN, vlan->ifname, NULL)) {
{
if (errno != EEXIST) { if (errno != EEXIST) {
printf("Could not add VLAN iface: %s: %s\n", printf("Could not add VLAN iface: %s: %s\n",
vlan->ifname, strerror(errno)); vlan->ifname, strerror(errno));
@ -705,8 +704,7 @@ static void vlan_dynamic_remove(struct hostapd_data *hapd,
next = vlan->next; next = vlan->next;
if (vlan->vlan_id != VLAN_ID_WILDCARD && if (vlan->vlan_id != VLAN_ID_WILDCARD &&
hostapd_if_remove(hapd, HOSTAPD_IF_VLAN, vlan->ifname, hostapd_if_remove(hapd, WPA_IF_AP_VLAN, vlan->ifname)) {
NULL)) {
printf("Could not remove VLAN iface: %s: %s\n", printf("Could not remove VLAN iface: %s: %s\n",
vlan->ifname, strerror(errno)); vlan->ifname, strerror(errno));
} }
@ -777,7 +775,7 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
pos); pos);
os_free(ifname); os_free(ifname);
if (hostapd_if_add(hapd, HOSTAPD_IF_VLAN, n->ifname, NULL)) { if (hostapd_if_add(hapd, WPA_IF_AP_VLAN, n->ifname, NULL)) {
os_free(n); os_free(n);
return NULL; return NULL;
} }
@ -809,7 +807,7 @@ int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
return 1; return 1;
if (vlan->dynamic_vlan == 0) if (vlan->dynamic_vlan == 0)
hostapd_if_remove(hapd, HOSTAPD_IF_VLAN, vlan->ifname, NULL); hostapd_if_remove(hapd, WPA_IF_AP_VLAN, vlan->ifname);
return 0; return 0;
} }

View file

@ -458,8 +458,26 @@ struct hostapd_freq_params {
* enabled, secondary channel above primary */ * enabled, secondary channel above primary */
}; };
enum hostapd_driver_if_type { enum wpa_driver_if_type {
HOSTAPD_IF_VLAN /**
* WPA_IF_STATION - Station mode interface
*/
WPA_IF_STATION,
/**
* WPA_IF_AP_VLAN - AP mode VLAN interface
*
* This interface shares its address and Beacon frame with the main
* BSS.
*/
WPA_IF_AP_VLAN,
/**
* WPA_IF_AP_BSS - AP mode BSS interface
*
* This interface has its own address and Beacon frame.
*/
WPA_IF_AP_BSS,
}; };
struct wpa_init_params { struct wpa_init_params {
@ -1117,14 +1135,31 @@ struct wpa_driver_ops {
int (*set_short_slot_time)(void *priv, int value); int (*set_short_slot_time)(void *priv, int value);
int (*set_tx_queue_params)(void *priv, int queue, int aifs, int cw_min, int (*set_tx_queue_params)(void *priv, int queue, int aifs, int cw_min,
int cw_max, int burst_time); int cw_max, int burst_time);
int (*bss_add)(void *priv, const char *ifname, const u8 *bssid);
int (*bss_remove)(void *priv, const char *ifname);
int (*valid_bss_mask)(void *priv, const u8 *addr, const u8 *mask); int (*valid_bss_mask)(void *priv, const u8 *addr, const u8 *mask);
/**
* if_add - Add a virtual interface
* @priv: Private driver interface data
* @iface: Parent interface name
* @type: Interface type
* @ifname: Interface name for the new virtual interface
* @addr: Local address to use for the interface or %NULL to use the
* parent interface address
* Returns: 0 on success, -1 on failure
*/
int (*if_add)(const char *iface, void *priv, int (*if_add)(const char *iface, void *priv,
enum hostapd_driver_if_type type, char *ifname, enum wpa_driver_if_type type, const char *ifname,
const u8 *addr); const u8 *addr);
int (*if_remove)(void *priv, enum hostapd_driver_if_type type,
const char *ifname, const u8 *addr); /**
* if_remove - Remove a virtual interface
* @priv: Private driver interface data
* @type: Interface type
* @ifname: Interface name of the virtual interface to be removed
* Returns: 0 on success, -1 on failure
*/
int (*if_remove)(void *priv, enum wpa_driver_if_type type,
const char *ifname);
int (*set_sta_vlan)(void *priv, const u8 *addr, const char *ifname, int (*set_sta_vlan)(void *priv, const u8 *addr, const char *ifname,
int vlan_id); int vlan_id);
/** /**

View file

@ -3235,8 +3235,6 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
NULL /* set_preamble */, NULL /* set_preamble */,
NULL /* set_short_slot_time */, NULL /* set_short_slot_time */,
NULL /* set_tx_queue_params */, NULL /* set_tx_queue_params */,
NULL /* bss_add */,
NULL /* bss_remove */,
NULL /* valid_bss_mask */, NULL /* valid_bss_mask */,
NULL /* if_add */, NULL /* if_add */,
NULL /* if_remove */, NULL /* if_remove */,

View file

@ -2743,6 +2743,8 @@ static int wpa_driver_nl80211_sta_remove(void *priv, const u8 *addr)
return -ENOBUFS; return -ENOBUFS;
} }
#endif /* CONFIG_AP || HOSTAPD */
static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv,
int ifidx) int ifidx)
@ -2832,6 +2834,8 @@ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
return ifidx; return ifidx;
} }
static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv, static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
const char *ifname, enum nl80211_iftype iftype, const char *ifname, enum nl80211_iftype iftype,
const u8 *addr) const u8 *addr)
@ -2854,7 +2858,6 @@ static int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
return ret; return ret;
} }
#endif /* CONFIG_AP || HOSTAPD */
#ifdef CONFIG_AP #ifdef CONFIG_AP
@ -4257,54 +4260,6 @@ static int i802_set_tx_queue_params(void *priv, int queue, int aifs,
} }
static int i802_bss_add(void *priv, const char *ifname, const u8 *bssid)
{
struct wpa_driver_nl80211_data *drv = priv;
int ifidx;
struct i802_bss *bss;
bss = os_zalloc(sizeof(*bss));
if (bss == NULL)
return -1;
ifidx = nl80211_create_iface(priv, ifname, NL80211_IFTYPE_AP, bssid);
if (ifidx < 0) {
os_free(bss);
return -1;
}
bss->ifindex = ifidx;
if (hostapd_set_iface_flags(priv, ifname, 1)) {
nl80211_remove_iface(priv, ifidx);
os_free(bss);
return -1;
}
bss->next = drv->bss.next;
drv->bss.next = bss;
return 0;
}
static int i802_bss_remove(void *priv, const char *ifname)
{
struct wpa_driver_nl80211_data *drv = priv;
struct i802_bss *bss, *prev;
int ifindex = if_nametoindex(ifname);
nl80211_remove_iface(priv, ifindex);
prev = &drv->bss;
bss = drv->bss.next;
while (bss) {
if (ifindex == bss->ifindex) {
prev->next = bss->next;
os_free(bss);
break;
}
prev = bss;
bss = bss->next;
}
return 0;
}
static int i802_set_bss(void *priv, int cts, int preamble, int slot) static int i802_set_bss(void *priv, int cts, int preamble, int slot)
{ {
struct wpa_driver_nl80211_data *drv = priv; struct wpa_driver_nl80211_data *drv = priv;
@ -4351,34 +4306,6 @@ static int i802_set_short_slot_time(void *priv, int value)
} }
static enum nl80211_iftype i802_if_type(enum hostapd_driver_if_type type)
{
switch (type) {
case HOSTAPD_IF_VLAN:
return NL80211_IFTYPE_AP_VLAN;
}
return -1;
}
static int i802_if_add(const char *iface, void *priv,
enum hostapd_driver_if_type type, char *ifname,
const u8 *addr)
{
if (nl80211_create_iface(priv, ifname, i802_if_type(type), addr) < 0)
return -1;
return 0;
}
static int i802_if_remove(void *priv, enum hostapd_driver_if_type type,
const char *ifname, const u8 *addr)
{
nl80211_remove_iface(priv, if_nametoindex(ifname));
return 0;
}
static int i802_set_sta_vlan(void *priv, const u8 *addr, static int i802_set_sta_vlan(void *priv, const u8 *addr,
const char *ifname, int vlan_id) const char *ifname, int vlan_id)
{ {
@ -4568,6 +4495,93 @@ static void i802_deinit(void *priv)
#endif /* HOSTAPD */ #endif /* HOSTAPD */
static enum nl80211_iftype wpa_driver_nl80211_if_type(
enum wpa_driver_if_type type)
{
switch (type) {
case WPA_IF_STATION:
return NL80211_IFTYPE_STATION;
case WPA_IF_AP_VLAN:
return NL80211_IFTYPE_AP_VLAN;
case WPA_IF_AP_BSS:
return NL80211_IFTYPE_AP;
}
return -1;
}
static int wpa_driver_nl80211_if_add(const char *iface, void *priv,
enum wpa_driver_if_type type,
const char *ifname, const u8 *addr)
{
struct wpa_driver_nl80211_data *drv = priv;
int ifidx;
#ifdef HOSTAPD
struct i802_bss *bss = NULL;
if (type == WPA_IF_AP_BSS) {
bss = os_zalloc(sizeof(*bss));
if (bss == NULL)
return -1;
}
#endif /* HOSTAPD */
ifidx = nl80211_create_iface(drv, ifname,
wpa_driver_nl80211_if_type(type), addr);
if (ifidx < 0) {
#ifdef HOSTAPD
os_free(bss);
#endif /* HOSTAPD */
return -1;
}
#ifdef HOSTAPD
if (type == WPA_IF_AP_BSS) {
if (hostapd_set_iface_flags(priv, ifname, 1)) {
nl80211_remove_iface(priv, ifidx);
os_free(bss);
return -1;
}
bss->ifindex = ifidx;
bss->next = drv->bss.next;
drv->bss.next = bss;
}
#endif /* HOSTAPD */
return 0;
}
static int wpa_driver_nl80211_if_remove(void *priv,
enum wpa_driver_if_type type,
const char *ifname)
{
struct wpa_driver_nl80211_data *drv = priv;
int ifindex = if_nametoindex(ifname);
nl80211_remove_iface(drv, ifindex);
#ifdef HOSTAPD
if (type == WPA_IF_AP_BSS) {
struct i802_bss *bss, *prev;
prev = &drv->bss;
bss = drv->bss.next;
while (bss) {
if (ifindex == bss->ifindex) {
prev->next = bss->next;
os_free(bss);
break;
}
prev = bss;
bss = bss->next;
}
}
#endif /* HOSTAPD */
return 0;
}
const struct wpa_driver_ops wpa_driver_nl80211_ops = { const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.name = "nl80211", .name = "nl80211",
.desc = "Linux nl80211/cfg80211", .desc = "Linux nl80211/cfg80211",
@ -4587,6 +4601,8 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.set_supp_port = wpa_driver_nl80211_set_supp_port, .set_supp_port = wpa_driver_nl80211_set_supp_port,
.set_country = wpa_driver_nl80211_set_country, .set_country = wpa_driver_nl80211_set_country,
.set_beacon = wpa_driver_nl80211_set_beacon, .set_beacon = wpa_driver_nl80211_set_beacon,
.if_add = wpa_driver_nl80211_if_add,
.if_remove = wpa_driver_nl80211_if_remove,
#if defined(CONFIG_AP) || defined(HOSTAPD) #if defined(CONFIG_AP) || defined(HOSTAPD)
.send_mlme = wpa_driver_nl80211_send_mlme, .send_mlme = wpa_driver_nl80211_send_mlme,
.get_hw_feature_data = wpa_driver_nl80211_get_hw_feature_data, .get_hw_feature_data = wpa_driver_nl80211_get_hw_feature_data,
@ -4613,10 +4629,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.set_preamble = i802_set_preamble, .set_preamble = i802_set_preamble,
.set_short_slot_time = i802_set_short_slot_time, .set_short_slot_time = i802_set_short_slot_time,
.set_tx_queue_params = i802_set_tx_queue_params, .set_tx_queue_params = i802_set_tx_queue_params,
.bss_add = i802_bss_add,
.bss_remove = i802_bss_remove,
.if_add = i802_if_add,
.if_remove = i802_if_remove,
.set_sta_vlan = i802_set_sta_vlan, .set_sta_vlan = i802_set_sta_vlan,
#endif /* HOSTAPD */ #endif /* HOSTAPD */
}; };

View file

@ -1044,19 +1044,23 @@ static int test_driver_bss_remove(void *priv, const char *ifname)
static int test_driver_if_add(const char *iface, void *priv, static int test_driver_if_add(const char *iface, void *priv,
enum hostapd_driver_if_type type, char *ifname, enum wpa_driver_if_type type, const char *ifname,
const u8 *addr) const u8 *addr)
{ {
wpa_printf(MSG_DEBUG, "%s(iface=%s type=%d ifname=%s)", wpa_printf(MSG_DEBUG, "%s(iface=%s type=%d ifname=%s)",
__func__, iface, type, ifname); __func__, iface, type, ifname);
if (type == WPA_IF_AP_BSS)
return test_driver_bss_add(priv, ifname, addr);
return 0; return 0;
} }
static int test_driver_if_remove(void *priv, enum hostapd_driver_if_type type, static int test_driver_if_remove(void *priv, enum wpa_driver_if_type type,
const char *ifname, const u8 *addr) const char *ifname)
{ {
wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s)", __func__, type, ifname); wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s)", __func__, type, ifname);
if (type == WPA_IF_AP_BSS)
return test_driver_bss_remove(priv, ifname);
return 0; return 0;
} }
@ -2473,8 +2477,6 @@ const struct wpa_driver_ops wpa_driver_test_ops = {
.sta_deauth = test_driver_sta_deauth, .sta_deauth = test_driver_sta_deauth,
.sta_disassoc = test_driver_sta_disassoc, .sta_disassoc = test_driver_sta_disassoc,
.get_hw_feature_data = wpa_driver_test_get_hw_feature_data, .get_hw_feature_data = wpa_driver_test_get_hw_feature_data,
.bss_add = test_driver_bss_add,
.bss_remove = test_driver_bss_remove,
.if_add = test_driver_if_add, .if_add = test_driver_if_add,
.if_remove = test_driver_if_remove, .if_remove = test_driver_if_remove,
.valid_bss_mask = test_driver_valid_bss_mask, .valid_bss_mask = test_driver_valid_bss_mask,