Simplify driver_ops for virtual interface add/remove
There is no absolute requirement for separating address allocation into separate functions, so simplify the driver wrapper interface to use just if_add and if_remove instead of adding the new alloc_interface_addr() and release_interface_addr() functions. if_add() can now indicate if the driver forced a different interface name or address on the virtual interface.
This commit is contained in:
parent
977b11747f
commit
f3585c8a85
8 changed files with 56 additions and 111 deletions
|
@ -242,7 +242,10 @@ static int hostapd_set_beacon(struct hostapd_data *hapd,
|
||||||
|
|
||||||
static int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
|
static int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname)
|
||||||
{
|
{
|
||||||
return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL, NULL);
|
char force_ifname[IFNAMSIZ];
|
||||||
|
u8 if_addr[ETH_ALEN];
|
||||||
|
return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, NULL, NULL, NULL,
|
||||||
|
force_ifname, if_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hostapd_vlan_if_remove(struct hostapd_data *hapd,
|
static int hostapd_vlan_if_remove(struct hostapd_data *hapd,
|
||||||
|
@ -404,12 +407,12 @@ int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len)
|
||||||
|
|
||||||
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||||
const char *ifname, const u8 *addr, void *bss_ctx,
|
const char *ifname, const u8 *addr, void *bss_ctx,
|
||||||
void **drv_priv)
|
void **drv_priv, char *force_ifname, u8 *if_addr)
|
||||||
{
|
{
|
||||||
if (hapd->driver == NULL || hapd->driver->if_add == NULL)
|
if (hapd->driver == NULL || hapd->driver->if_add == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
|
return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
|
||||||
bss_ctx, drv_priv);
|
bss_ctx, drv_priv, force_ifname, if_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len);
|
||||||
int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len);
|
int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len);
|
||||||
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||||
const char *ifname, const u8 *addr, void *bss_ctx,
|
const char *ifname, const u8 *addr, void *bss_ctx,
|
||||||
void **drv_priv);
|
void **drv_priv, char *force_ifname, u8 *if_addr);
|
||||||
int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type,
|
||||||
const char *ifname);
|
const char *ifname);
|
||||||
int hostapd_set_ieee8021x(struct hostapd_data *hapd,
|
int hostapd_set_ieee8021x(struct hostapd_data *hapd,
|
||||||
|
|
|
@ -468,6 +468,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
||||||
struct hostapd_bss_config *conf = hapd->conf;
|
struct hostapd_bss_config *conf = hapd->conf;
|
||||||
u8 ssid[HOSTAPD_MAX_SSID_LEN + 1];
|
u8 ssid[HOSTAPD_MAX_SSID_LEN + 1];
|
||||||
int ssid_len, set_ssid;
|
int ssid_len, set_ssid;
|
||||||
|
char force_ifname[IFNAMSIZ];
|
||||||
|
u8 if_addr[ETH_ALEN];
|
||||||
|
|
||||||
if (!first) {
|
if (!first) {
|
||||||
if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) {
|
if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) {
|
||||||
|
@ -492,7 +494,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
|
||||||
hapd->interface_added = 1;
|
hapd->interface_added = 1;
|
||||||
if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
|
if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
|
||||||
hapd->conf->iface, hapd->own_addr, hapd,
|
hapd->conf->iface, hapd->own_addr, hapd,
|
||||||
&hapd->drv_priv)) {
|
&hapd->drv_priv, force_ifname, if_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;
|
||||||
|
|
|
@ -1490,11 +1490,16 @@ struct wpa_driver_ops {
|
||||||
* @bss_ctx: BSS context for %WPA_IF_AP_BSS interfaces
|
* @bss_ctx: BSS context for %WPA_IF_AP_BSS interfaces
|
||||||
* @drv_priv: Pointer for overwriting the driver context or %NULL if
|
* @drv_priv: Pointer for overwriting the driver context or %NULL if
|
||||||
* not allowed (applies only to %WPA_IF_AP_BSS type)
|
* not allowed (applies only to %WPA_IF_AP_BSS type)
|
||||||
|
* @force_ifname: Buffer for returning an interface name that the
|
||||||
|
* driver ended up using if it differs from the requested ifname
|
||||||
|
* @if_addr: Buffer for returning the allocated interface address
|
||||||
|
* (this may differ from the requested addr if the driver cannot
|
||||||
|
* change interface address)
|
||||||
* Returns: 0 on success, -1 on failure
|
* Returns: 0 on success, -1 on failure
|
||||||
*/
|
*/
|
||||||
int (*if_add)(void *priv, enum wpa_driver_if_type type,
|
int (*if_add)(void *priv, enum wpa_driver_if_type type,
|
||||||
const char *ifname, const u8 *addr, void *bss_ctx,
|
const char *ifname, const u8 *addr, void *bss_ctx,
|
||||||
void **drv_priv);
|
void **drv_priv, char *force_ifname, u8 *if_addr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* if_remove - Remove a virtual interface
|
* if_remove - Remove a virtual interface
|
||||||
|
@ -1635,40 +1640,6 @@ struct wpa_driver_ops {
|
||||||
const u8 *dst, const u8 *src, const u8 *bssid,
|
const u8 *dst, const u8 *src, const u8 *bssid,
|
||||||
const u8 *data, size_t data_len);
|
const u8 *data, size_t data_len);
|
||||||
|
|
||||||
/**
|
|
||||||
* alloc_interface_addr - Allocate a virtual interface address
|
|
||||||
* @priv: Private driver interface data
|
|
||||||
* @addr: Buffer for returning the address
|
|
||||||
* @ifname: Buffer for returning interface name (if needed)
|
|
||||||
* Returns: 0 on success, -1 on failure
|
|
||||||
*
|
|
||||||
* This command pre-allocates an interface address for a new virtual
|
|
||||||
* interface. This can be used before creating a virtual interface if
|
|
||||||
* the interface mode (e.g., AP vs. station) is not yet known, but the
|
|
||||||
* address of the virtual interface is already needed. This helps with
|
|
||||||
* drivers that cannot change interface mode without destroying and
|
|
||||||
* re-creating the interface. If the driver requires a specific
|
|
||||||
* interface name to be used, the ifname buffer (up to IFNAMSIZ
|
|
||||||
* characters) will be used to indicate which name must be used for
|
|
||||||
* this virtual interface.
|
|
||||||
*
|
|
||||||
* The allocated address can be used in a if_add() call to request a
|
|
||||||
* specific bssid.
|
|
||||||
*/
|
|
||||||
int (*alloc_interface_addr)(void *priv, u8 *addr, char *ifname);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* release_interface_addr - Release a virtual interface address
|
|
||||||
* @priv: Private driver interface data
|
|
||||||
* @addr: Address to be freed from alloc_interface_addr()
|
|
||||||
*
|
|
||||||
* This command is used to release a virtual interface address that was
|
|
||||||
* allocated with alloc_interface_addr(), but has not yet been used
|
|
||||||
* with if_add() to actually create the interface. This allows the
|
|
||||||
* driver to release the pending allocation for a new interface.
|
|
||||||
*/
|
|
||||||
void (*release_interface_addr)(void *priv, const u8 *addr);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* remain_on_channel - Remain awake on a channel
|
* remain_on_channel - Remain awake on a channel
|
||||||
* @priv: Private driver interface data
|
* @priv: Private driver interface data
|
||||||
|
|
|
@ -3266,8 +3266,6 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
|
||||||
NULL /* set_supp_port */,
|
NULL /* set_supp_port */,
|
||||||
NULL /* set_wds_sta */,
|
NULL /* set_wds_sta */,
|
||||||
NULL /* send_action */,
|
NULL /* send_action */,
|
||||||
NULL /* alloc_interface_addr */,
|
|
||||||
NULL /* release_interface_addr */,
|
|
||||||
NULL /* remain_on_channel */,
|
NULL /* remain_on_channel */,
|
||||||
NULL /* cancel_remain_on_channel */,
|
NULL /* cancel_remain_on_channel */,
|
||||||
NULL /* probe_req_report */,
|
NULL /* probe_req_report */,
|
||||||
|
|
|
@ -4760,7 +4760,8 @@ static enum nl80211_iftype wpa_driver_nl80211_if_type(
|
||||||
|
|
||||||
static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
|
static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
|
||||||
const char *ifname, const u8 *addr,
|
const char *ifname, const u8 *addr,
|
||||||
void *bss_ctx, void **drv_priv)
|
void *bss_ctx, void **drv_priv,
|
||||||
|
char *force_ifname, u8 *if_addr)
|
||||||
{
|
{
|
||||||
struct i802_bss *bss = priv;
|
struct i802_bss *bss = priv;
|
||||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
struct wpa_driver_nl80211_data *drv = bss->drv;
|
||||||
|
@ -4775,6 +4776,8 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
|
||||||
}
|
}
|
||||||
#endif /* HOSTAPD */
|
#endif /* HOSTAPD */
|
||||||
|
|
||||||
|
if (addr)
|
||||||
|
os_memcpy(if_addr, addr, ETH_ALEN);
|
||||||
ifidx = nl80211_create_iface(drv, ifname,
|
ifidx = nl80211_create_iface(drv, ifname,
|
||||||
wpa_driver_nl80211_if_type(type), addr,
|
wpa_driver_nl80211_if_type(type), addr,
|
||||||
0);
|
0);
|
||||||
|
@ -4785,6 +4788,10 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!addr &&
|
||||||
|
linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, if_addr) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
#ifdef HOSTAPD
|
#ifdef HOSTAPD
|
||||||
if (type == WPA_IF_AP_BSS) {
|
if (type == WPA_IF_AP_BSS) {
|
||||||
if (linux_set_iface_flags(drv->ioctl_sock, ifname, 1)) {
|
if (linux_set_iface_flags(drv->ioctl_sock, ifname, 1)) {
|
||||||
|
@ -5054,35 +5061,6 @@ static int wpa_driver_nl80211_probe_req_report(void *priv, int report)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpa_driver_nl80211_alloc_interface_addr(void *priv, u8 *addr,
|
|
||||||
char *ifname)
|
|
||||||
{
|
|
||||||
struct i802_bss *bss = priv;
|
|
||||||
struct wpa_driver_nl80211_data *drv = bss->drv;
|
|
||||||
|
|
||||||
if (ifname)
|
|
||||||
ifname[0] = '\0';
|
|
||||||
|
|
||||||
if (linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, addr) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (addr[0] & 0x02) {
|
|
||||||
/* TODO: add support for generating multiple addresses */
|
|
||||||
addr[0] ^= 0x80;
|
|
||||||
} else
|
|
||||||
addr[0] = 0x02; /* locally administered */
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void wpa_driver_nl80211_release_interface_addr(void *priv,
|
|
||||||
const u8 *addr)
|
|
||||||
{
|
|
||||||
/* TODO: keep list of allocated address and release them here */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
|
static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
|
||||||
int ifindex, int disabled)
|
int ifindex, int disabled)
|
||||||
{
|
{
|
||||||
|
@ -5312,8 +5290,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||||
.cancel_remain_on_channel =
|
.cancel_remain_on_channel =
|
||||||
wpa_driver_nl80211_cancel_remain_on_channel,
|
wpa_driver_nl80211_cancel_remain_on_channel,
|
||||||
.probe_req_report = wpa_driver_nl80211_probe_req_report,
|
.probe_req_report = wpa_driver_nl80211_probe_req_report,
|
||||||
.alloc_interface_addr = wpa_driver_nl80211_alloc_interface_addr,
|
|
||||||
.release_interface_addr = wpa_driver_nl80211_release_interface_addr,
|
|
||||||
.disable_11b_rates = wpa_driver_nl80211_disable_11b_rates,
|
.disable_11b_rates = wpa_driver_nl80211_disable_11b_rates,
|
||||||
.deinit_ap = wpa_driver_nl80211_deinit_ap,
|
.deinit_ap = wpa_driver_nl80211_deinit_ap,
|
||||||
.resume = wpa_driver_nl80211_resume,
|
.resume = wpa_driver_nl80211_resume,
|
||||||
|
|
|
@ -1014,12 +1014,27 @@ static int test_driver_bss_remove(void *priv, const char *ifname)
|
||||||
|
|
||||||
static int test_driver_if_add(void *priv, enum wpa_driver_if_type type,
|
static int test_driver_if_add(void *priv, enum wpa_driver_if_type type,
|
||||||
const char *ifname, const u8 *addr,
|
const char *ifname, const u8 *addr,
|
||||||
void *bss_ctx, void **drv_priv)
|
void *bss_ctx, void **drv_priv,
|
||||||
|
char *force_ifname, u8 *if_addr)
|
||||||
{
|
{
|
||||||
|
struct test_driver_bss *dbss = priv;
|
||||||
|
struct wpa_driver_test_data *drv = dbss->drv;
|
||||||
|
|
||||||
wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s bss_ctx=%p)",
|
wpa_printf(MSG_DEBUG, "%s(type=%d ifname=%s bss_ctx=%p)",
|
||||||
__func__, type, ifname, bss_ctx);
|
__func__, type, ifname, bss_ctx);
|
||||||
|
if (addr)
|
||||||
|
os_memcpy(if_addr, addr, ETH_ALEN);
|
||||||
|
else {
|
||||||
|
drv->alloc_iface_idx++;
|
||||||
|
if_addr[0] = 0x02; /* locally administered */
|
||||||
|
sha1_prf(drv->own_addr, ETH_ALEN,
|
||||||
|
"hostapd test addr generation",
|
||||||
|
(const u8 *) &drv->alloc_iface_idx,
|
||||||
|
sizeof(drv->alloc_iface_idx),
|
||||||
|
if_addr + 1, ETH_ALEN - 1);
|
||||||
|
}
|
||||||
if (type == WPA_IF_AP_BSS)
|
if (type == WPA_IF_AP_BSS)
|
||||||
return test_driver_bss_add(priv, ifname, addr, bss_ctx,
|
return test_driver_bss_add(priv, ifname, if_addr, bss_ctx,
|
||||||
drv_priv);
|
drv_priv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2616,30 +2631,6 @@ static int wpa_driver_test_send_action(void *priv, unsigned int freq,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int wpa_driver_test_alloc_interface_addr(void *priv, u8 *addr,
|
|
||||||
char *ifname)
|
|
||||||
{
|
|
||||||
struct test_driver_bss *dbss = priv;
|
|
||||||
struct wpa_driver_test_data *drv = dbss->drv;
|
|
||||||
|
|
||||||
if (ifname)
|
|
||||||
ifname[0] = '\0';
|
|
||||||
|
|
||||||
drv->alloc_iface_idx++;
|
|
||||||
addr[0] = 0x02; /* locally administered */
|
|
||||||
sha1_prf(drv->own_addr, ETH_ALEN, "hostapd test addr generation",
|
|
||||||
(const u8 *) &drv->alloc_iface_idx,
|
|
||||||
sizeof(drv->alloc_iface_idx),
|
|
||||||
addr + 1, ETH_ALEN - 1);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void wpa_driver_test_release_interface_addr(void *priv, const u8 *addr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx)
|
static void test_remain_on_channel_timeout(void *eloop_ctx, void *timeout_ctx)
|
||||||
{
|
{
|
||||||
struct wpa_driver_test_data *drv = eloop_ctx;
|
struct wpa_driver_test_data *drv = eloop_ctx;
|
||||||
|
@ -2755,8 +2746,6 @@ const struct wpa_driver_ops wpa_driver_test_ops = {
|
||||||
.scan2 = wpa_driver_test_scan,
|
.scan2 = wpa_driver_test_scan,
|
||||||
.set_freq = wpa_driver_test_set_freq,
|
.set_freq = wpa_driver_test_set_freq,
|
||||||
.send_action = wpa_driver_test_send_action,
|
.send_action = wpa_driver_test_send_action,
|
||||||
.alloc_interface_addr = wpa_driver_test_alloc_interface_addr,
|
|
||||||
.release_interface_addr = wpa_driver_test_release_interface_addr,
|
|
||||||
.remain_on_channel = wpa_driver_test_remain_on_channel,
|
.remain_on_channel = wpa_driver_test_remain_on_channel,
|
||||||
.cancel_remain_on_channel = wpa_driver_test_cancel_remain_on_channel,
|
.cancel_remain_on_channel = wpa_driver_test_cancel_remain_on_channel,
|
||||||
.probe_req_report = wpa_driver_test_probe_req_report,
|
.probe_req_report = wpa_driver_test_probe_req_report,
|
||||||
|
|
|
@ -394,20 +394,26 @@ static inline int wpa_drv_send_action(struct wpa_supplicant *wpa_s,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int wpa_drv_alloc_interface_addr(struct wpa_supplicant *wpa_s,
|
static inline int wpa_drv_if_add(struct wpa_supplicant *wpa_s,
|
||||||
u8 *addr, char *ifname)
|
enum wpa_driver_if_type type,
|
||||||
|
const char *ifname, const u8 *addr,
|
||||||
|
void *bss_ctx, char *force_ifname,
|
||||||
|
u8 *if_addr)
|
||||||
{
|
{
|
||||||
if (wpa_s->driver->alloc_interface_addr)
|
if (wpa_s->driver->if_add)
|
||||||
return wpa_s->driver->alloc_interface_addr(wpa_s->drv_priv,
|
return wpa_s->driver->if_add(wpa_s->drv_priv, type, ifname,
|
||||||
addr, ifname);
|
addr, bss_ctx, NULL, force_ifname,
|
||||||
|
if_addr);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void wpa_drv_release_interface_addr(struct wpa_supplicant *wpa_s,
|
static inline int wpa_drv_if_remove(struct wpa_supplicant *wpa_s,
|
||||||
const u8 *addr)
|
enum wpa_driver_if_type type,
|
||||||
|
const char *ifname)
|
||||||
{
|
{
|
||||||
if (wpa_s->driver->release_interface_addr)
|
if (wpa_s->driver->if_remove)
|
||||||
wpa_s->driver->release_interface_addr(wpa_s->drv_priv, addr);
|
return wpa_s->driver->if_remove(wpa_s->drv_priv, type, ifname);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int wpa_drv_remain_on_channel(struct wpa_supplicant *wpa_s,
|
static inline int wpa_drv_remain_on_channel(struct wpa_supplicant *wpa_s,
|
||||||
|
|
Loading…
Reference in a new issue