From: Jouni Malinen Date: Fri, 17 Apr 2009 13:27:38 +0000 (+0300) Subject: nl80211: Add/remove monitor interface dynamically based on mode X-Git-Url: https://vcs.maemo.org/git/?p=wpasupplicant;a=commitdiff_plain;h=460456f8325a578f714a7ea0f84ea08e6410deb5 nl80211: Add/remove monitor interface dynamically based on mode --- diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 9413575..0fcd4f0 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -130,6 +130,11 @@ static int wpa_driver_nl80211_set_mode(void *priv, int mode); static int wpa_driver_nl80211_finish_drv_init(struct wpa_driver_nl80211_data *drv); +#if defined(CONFIG_AP) || defined(HOSTAPD) +static void nl80211_remove_monitor_interface( + struct wpa_driver_nl80211_data *drv); +#endif /* CONFIG_AP || HOSTAPD */ + #ifdef CONFIG_AP static void nl80211_remove_iface(struct wpa_driver_nl80211_data *drv, int ifidx); @@ -1294,8 +1299,7 @@ static void wpa_driver_nl80211_deinit(void *priv) struct wpa_driver_nl80211_data *drv = priv; #if defined(CONFIG_AP) || defined(HOSTAPD) - if (drv->monitor_ifidx >= 0) - nl80211_remove_iface(drv, drv->monitor_ifidx); + nl80211_remove_monitor_interface(drv); if (drv->monitor_sock >= 0) { eloop_unregister_read_sock(drv->monitor_sock); close(drv->monitor_sock); @@ -2742,6 +2746,16 @@ static int add_monitor_filter(int s) } +static void nl80211_remove_monitor_interface( + struct wpa_driver_nl80211_data *drv) +{ + if (drv->monitor_ifidx >= 0) { + nl80211_remove_iface(drv, drv->monitor_ifidx); + drv->monitor_ifidx = -1; + } +} + + static int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv) { @@ -2798,7 +2812,7 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv) return 0; error: - nl80211_remove_iface(drv, drv->monitor_ifidx); + nl80211_remove_monitor_interface(drv); return -1; } @@ -2809,14 +2823,9 @@ nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv) static int wpa_driver_nl80211_ap(struct wpa_driver_nl80211_data *drv, struct wpa_driver_associate_params *params) { - if (drv->monitor_ifidx < 0 && - nl80211_create_monitor_interface(drv)) - return -1; - if (wpa_driver_nl80211_set_mode(drv, params->mode) || wpa_driver_nl80211_set_freq(drv, params->freq, 0, 0)) { - nl80211_remove_iface(drv, drv->monitor_ifidx); - drv->monitor_ifidx = -1; + nl80211_remove_monitor_interface(drv); return -1; } @@ -2947,11 +2956,14 @@ static int wpa_driver_nl80211_set_mode(void *priv, int mode) if (nl80211_set_mode(drv, drv->ifindex, nlmode) == 0) { drv->nlmode = nlmode; - return 0; + ret = 0; + goto done; } - if (nlmode == drv->nlmode) - return 0; /* Already in the requested mode */ + if (nlmode == drv->nlmode) { + ret = 0; + goto done; /* Already in the requested mode */ + } /* mac80211 doesn't allow mode changes while the device is up, so * take the device down, try to set the mode again, and bring the @@ -2967,6 +2979,19 @@ static int wpa_driver_nl80211_set_mode(void *priv, int mode) if (!ret) drv->nlmode = nlmode; +done: +#if defined(CONFIG_AP) || defined(HOSTAPD) + if (!ret && nlmode == NL80211_IFTYPE_AP) { + /* Setup additional AP mode functionality if needed */ + if (drv->monitor_ifidx < 0 && + nl80211_create_monitor_interface(drv)) + return -1; + } else if (!ret && nlmode != NL80211_IFTYPE_AP) { + /* Remove additional AP mode functionality */ + nl80211_remove_monitor_interface(drv); + } +#endif /* CONFIG_AP || HOSTAPD */ + return ret; } @@ -3855,15 +3880,13 @@ static void *i802_init(struct hostapd_data *hapd, /* start listening for EAPOL on the default AP interface */ add_ifidx(drv, drv->ifindex); - if (hostapd_set_iface_flags(drv, drv->ifname, 0)) - goto failed; - - if (params->bssid && set_ifhwaddr(drv, drv->ifname, params->bssid)) - goto failed; + if (params->bssid) { + if (hostapd_set_iface_flags(drv, drv->ifname, 0)) + goto failed; - /* Initialise a monitor interface */ - if (nl80211_create_monitor_interface(drv)) - goto failed; + if (set_ifhwaddr(drv, drv->ifname, params->bssid)) + goto failed; + } if (nl80211_set_mode(drv, drv->ifindex, NL80211_IFTYPE_AP)) { wpa_printf(MSG_ERROR, "nl80211: Failed to set interface %s " @@ -3892,8 +3915,7 @@ static void *i802_init(struct hostapd_data *hapd, return drv; failed: - if (drv->monitor_ifidx >= 0) - nl80211_remove_iface(drv, drv->monitor_ifidx); + nl80211_remove_monitor_interface(drv); if (drv->ioctl_sock >= 0) close(drv->ioctl_sock);