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,
int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type,
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)
return -1;
return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr,
- bss_ctx, drv_priv);
+ bss_ctx, drv_priv, force_ifname, if_addr);
}
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,
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,
const char *ifname);
int hostapd_set_ieee8021x(struct hostapd_data *hapd,
struct hostapd_bss_config *conf = hapd->conf;
u8 ssid[HOSTAPD_MAX_SSID_LEN + 1];
int ssid_len, set_ssid;
+ char force_ifname[IFNAMSIZ];
+ u8 if_addr[ETH_ALEN];
if (!first) {
if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) {
hapd->interface_added = 1;
if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS,
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="
MACSTR ")", MAC2STR(hapd->own_addr));
return -1;
* @bss_ctx: BSS context for %WPA_IF_AP_BSS interfaces
* @drv_priv: Pointer for overwriting the driver context or %NULL if
* 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
*/
int (*if_add)(void *priv, enum wpa_driver_if_type type,
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
const u8 *dst, const u8 *src, const u8 *bssid,
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
* @priv: Private driver interface data
NULL /* set_supp_port */,
NULL /* set_wds_sta */,
NULL /* send_action */,
- NULL /* alloc_interface_addr */,
- NULL /* release_interface_addr */,
NULL /* remain_on_channel */,
NULL /* cancel_remain_on_channel */,
NULL /* probe_req_report */,
static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
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 wpa_driver_nl80211_data *drv = bss->drv;
}
#endif /* HOSTAPD */
+ if (addr)
+ os_memcpy(if_addr, addr, ETH_ALEN);
ifidx = nl80211_create_iface(drv, ifname,
wpa_driver_nl80211_if_type(type), addr,
0);
return -1;
}
+ if (!addr &&
+ linux_get_ifhwaddr(drv->ioctl_sock, bss->ifname, if_addr) < 0)
+ return -1;
+
#ifdef HOSTAPD
if (type == WPA_IF_AP_BSS) {
if (linux_set_iface_flags(drv->ioctl_sock, ifname, 1)) {
}
-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,
int ifindex, int disabled)
{
.cancel_remain_on_channel =
wpa_driver_nl80211_cancel_remain_on_channel,
.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,
.deinit_ap = wpa_driver_nl80211_deinit_ap,
.resume = wpa_driver_nl80211_resume,
static int test_driver_if_add(void *priv, enum wpa_driver_if_type type,
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)",
__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)
- return test_driver_bss_add(priv, ifname, addr, bss_ctx,
+ return test_driver_bss_add(priv, ifname, if_addr, bss_ctx,
drv_priv);
return 0;
}
}
-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)
{
struct wpa_driver_test_data *drv = eloop_ctx;
.scan2 = wpa_driver_test_scan,
.set_freq = wpa_driver_test_set_freq,
.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,
.cancel_remain_on_channel = wpa_driver_test_cancel_remain_on_channel,
.probe_req_report = wpa_driver_test_probe_req_report,
return -1;
}
-static inline int wpa_drv_alloc_interface_addr(struct wpa_supplicant *wpa_s,
- u8 *addr, char *ifname)
+static inline int wpa_drv_if_add(struct wpa_supplicant *wpa_s,
+ 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)
- return wpa_s->driver->alloc_interface_addr(wpa_s->drv_priv,
- addr, ifname);
+ if (wpa_s->driver->if_add)
+ return wpa_s->driver->if_add(wpa_s->drv_priv, type, ifname,
+ addr, bss_ctx, NULL, force_ifname,
+ if_addr);
return -1;
}
-static inline void wpa_drv_release_interface_addr(struct wpa_supplicant *wpa_s,
- const u8 *addr)
+static inline int wpa_drv_if_remove(struct wpa_supplicant *wpa_s,
+ enum wpa_driver_if_type type,
+ const char *ifname)
{
- if (wpa_s->driver->release_interface_addr)
- wpa_s->driver->release_interface_addr(wpa_s->drv_priv, addr);
+ if (wpa_s->driver->if_remove)
+ 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,