Simplify driver_ops for virtual interface add/remove
authorJouni Malinen <jouni.malinen@atheros.com>
Sun, 11 Apr 2010 16:23:09 +0000 (19:23 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 11 Apr 2010 16:23:09 +0000 (19:23 +0300)
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.

src/ap/ap_drv_ops.c
src/ap/ap_drv_ops.h
src/ap/hostapd.c
src/drivers/driver.h
src/drivers/driver_ndis.c
src/drivers/driver_nl80211.c
src/drivers/driver_test.c
wpa_supplicant/driver_i.h

index 7a62d73..5b0a506 100644 (file)
@@ -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)
 {
-       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,
@@ -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,
                   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);
 }
 
 
index 0e8f9cc..9b75d09 100644 (file)
@@ -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_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,
index bf60570..35ac468 100644 (file)
@@ -468,6 +468,8 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
        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) {
@@ -492,7 +494,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
                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;
index 39bbcd9..8e7dc96 100644 (file)
@@ -1490,11 +1490,16 @@ struct wpa_driver_ops {
         * @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
@@ -1636,40 +1641,6 @@ struct wpa_driver_ops {
                           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
         * @freq: Frequency (in MHz) of the channel
index 6d7a1fc..462dd81 100644 (file)
@@ -3266,8 +3266,6 @@ const struct wpa_driver_ops wpa_driver_ndis_ops = {
        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 */,
index 547da01..d7bfd32 100644 (file)
@@ -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,
                                     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;
@@ -4775,6 +4776,8 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
        }
 #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);
@@ -4785,6 +4788,10 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
                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)) {
@@ -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,
                                     int ifindex, int disabled)
 {
@@ -5312,8 +5290,6 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        .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,
index 4a57b30..338bc76 100644 (file)
@@ -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,
                              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;
 }
@@ -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)
 {
        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,
        .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,
index 71240c3..fa2ae4f 100644 (file)
@@ -394,20 +394,26 @@ static inline int wpa_drv_send_action(struct wpa_supplicant *wpa_s,
        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,