Add driver ops for allocating interface addresses
This adds placeholder code for allowing the virtual interfaces to be pre-allocated a MAC address before the interface type is known with drivers that do not handle interface type changes.
This commit is contained in:
parent
504e905c6e
commit
7bfc47c34f
5 changed files with 98 additions and 4 deletions
|
@ -1519,6 +1519,36 @@ struct wpa_driver_ops {
|
||||||
*/
|
*/
|
||||||
int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val);
|
int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* alloc_interface_addr - Allocate a virtual interface address
|
||||||
|
* @priv: Private driver interface data
|
||||||
|
* @addr: Buffer for returning the address
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* The allocated address can be used in a bss_add() call to request a
|
||||||
|
* specific bssid.
|
||||||
|
*/
|
||||||
|
int (*alloc_interface_addr)(void *priv, u8 *addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 bss_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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* probe_req_report - Request Probe Request frames to be indicated
|
* probe_req_report - Request Probe Request frames to be indicated
|
||||||
* @priv: Private driver interface data
|
* @priv: Private driver interface data
|
||||||
|
|
|
@ -3246,5 +3246,7 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
|
||||||
NULL /* set_ap_wps_ie */,
|
NULL /* set_ap_wps_ie */,
|
||||||
NULL /* set_supp_port */,
|
NULL /* set_supp_port */,
|
||||||
NULL /* set_wds_sta */,
|
NULL /* set_wds_sta */,
|
||||||
|
NULL /* alloc_interface_addr */,
|
||||||
|
NULL /* release_interface_addr */,
|
||||||
NULL /* probe_req_report */
|
NULL /* probe_req_report */
|
||||||
};
|
};
|
||||||
|
|
|
@ -266,7 +266,6 @@ nla_put_failure:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef HOSTAPD
|
|
||||||
static int get_ifhwaddr(struct wpa_driver_nl80211_data *drv,
|
static int get_ifhwaddr(struct wpa_driver_nl80211_data *drv,
|
||||||
const char *ifname, u8 *addr)
|
const char *ifname, u8 *addr)
|
||||||
{
|
{
|
||||||
|
@ -309,7 +308,6 @@ static int set_ifhwaddr(struct wpa_driver_nl80211_data *drv,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* HOSTAPD */
|
|
||||||
|
|
||||||
|
|
||||||
static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid)
|
static int wpa_driver_nl80211_get_bssid(void *priv, u8 *bssid)
|
||||||
|
@ -2661,13 +2659,13 @@ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
|
||||||
#ifdef HOSTAPD
|
#ifdef HOSTAPD
|
||||||
/* start listening for EAPOL on this interface */
|
/* start listening for EAPOL on this interface */
|
||||||
add_ifidx(drv, ifidx);
|
add_ifidx(drv, ifidx);
|
||||||
|
#endif /* HOSTAPD */
|
||||||
|
|
||||||
if (addr && iftype == NL80211_IFTYPE_AP &&
|
if (addr && iftype != NL80211_IFTYPE_MONITOR &&
|
||||||
set_ifhwaddr(drv, ifname, addr)) {
|
set_ifhwaddr(drv, ifname, addr)) {
|
||||||
nl80211_remove_iface(drv, ifidx);
|
nl80211_remove_iface(drv, ifidx);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif /* HOSTAPD */
|
|
||||||
|
|
||||||
return ifidx;
|
return ifidx;
|
||||||
}
|
}
|
||||||
|
@ -4473,6 +4471,30 @@ static int wpa_driver_nl80211_probe_req_report(void *priv, int report)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_driver_nl80211_alloc_interface_addr(void *priv, u8 *addr)
|
||||||
|
{
|
||||||
|
struct wpa_driver_nl80211_data *drv = priv;
|
||||||
|
|
||||||
|
if (get_ifhwaddr(drv, drv->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 */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
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",
|
||||||
|
@ -4522,4 +4544,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
|
||||||
.set_wds_sta = i802_set_wds_sta,
|
.set_wds_sta = i802_set_wds_sta,
|
||||||
#endif /* HOSTAPD */
|
#endif /* HOSTAPD */
|
||||||
.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,
|
||||||
};
|
};
|
||||||
|
|
|
@ -101,6 +101,8 @@ struct wpa_driver_test_data {
|
||||||
struct test_driver_bss *bss;
|
struct test_driver_bss *bss;
|
||||||
int udp_port;
|
int udp_port;
|
||||||
|
|
||||||
|
int alloc_iface_idx;
|
||||||
|
|
||||||
int probe_req_report;
|
int probe_req_report;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2462,6 +2464,24 @@ fail:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int wpa_driver_test_alloc_interface_addr(void *priv, u8 *addr)
|
||||||
|
{
|
||||||
|
struct wpa_driver_test_data *drv = priv;
|
||||||
|
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 int wpa_driver_test_probe_req_report(void *priv, int report)
|
static int wpa_driver_test_probe_req_report(void *priv, int report)
|
||||||
{
|
{
|
||||||
struct wpa_driver_test_data *drv = priv;
|
struct wpa_driver_test_data *drv = priv;
|
||||||
|
@ -2514,5 +2534,7 @@ const struct wpa_driver_ops wpa_driver_test_ops = {
|
||||||
.init2 = wpa_driver_test_init2,
|
.init2 = wpa_driver_test_init2,
|
||||||
.get_interfaces = wpa_driver_test_get_interfaces,
|
.get_interfaces = wpa_driver_test_get_interfaces,
|
||||||
.scan2 = wpa_driver_test_scan,
|
.scan2 = wpa_driver_test_scan,
|
||||||
|
.alloc_interface_addr = wpa_driver_test_alloc_interface_addr,
|
||||||
|
.release_interface_addr = wpa_driver_test_release_interface_addr,
|
||||||
.probe_req_report = wpa_driver_test_probe_req_report,
|
.probe_req_report = wpa_driver_test_probe_req_report,
|
||||||
};
|
};
|
||||||
|
|
|
@ -383,6 +383,22 @@ static inline int wpa_drv_set_supp_port(struct wpa_supplicant *wpa_s,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int wpa_drv_alloc_interface_addr(struct wpa_supplicant *wpa_s,
|
||||||
|
u8 *addr)
|
||||||
|
{
|
||||||
|
if (wpa_s->driver->alloc_interface_addr)
|
||||||
|
return wpa_s->driver->alloc_interface_addr(wpa_s->drv_priv,
|
||||||
|
addr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void wpa_drv_release_interface_addr(struct wpa_supplicant *wpa_s,
|
||||||
|
const u8 *addr)
|
||||||
|
{
|
||||||
|
if (wpa_s->driver->release_interface_addr)
|
||||||
|
wpa_s->driver->release_interface_addr(wpa_s->drv_priv, addr);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int wpa_drv_probe_req_report(struct wpa_supplicant *wpa_s,
|
static inline int wpa_drv_probe_req_report(struct wpa_supplicant *wpa_s,
|
||||||
int report)
|
int report)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue