mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-30 01:52:51 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			731 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			731 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| --- a/hostapd/Makefile
 | |
| +++ b/hostapd/Makefile
 | |
| @@ -168,9 +168,21 @@ OBJS += ../src/eapol_auth/eapol_auth_sm.
 | |
|  
 | |
|  ifdef CONFIG_UBUS
 | |
|  CFLAGS += -DUBUS_SUPPORT
 | |
| -OBJS += ../src/utils/uloop.o
 | |
|  OBJS += ../src/ap/ubus.o
 | |
| -LIBS += -lubox -lubus
 | |
| +LIBS += -lubus
 | |
| +NEED_ULOOP:=y
 | |
| +endif
 | |
| +
 | |
| +ifdef CONFIG_UCODE
 | |
| +CFLAGS += -DUCODE_SUPPORT
 | |
| +OBJS += ../src/utils/ucode.o
 | |
| +OBJS += ../src/ap/ucode.o
 | |
| +NEED_ULOOP:=y
 | |
| +endif
 | |
| +
 | |
| +ifdef NEED_ULOOP
 | |
| +OBJS += ../src/utils/uloop.o
 | |
| +LIBS += -lubox
 | |
|  endif
 | |
|  
 | |
|  ifdef CONFIG_CODE_COVERAGE
 | |
| --- a/hostapd/main.c
 | |
| +++ b/hostapd/main.c
 | |
| @@ -898,6 +898,7 @@ int main(int argc, char *argv[])
 | |
|  	}
 | |
|  
 | |
|  	hostapd_global_ctrl_iface_init(&interfaces);
 | |
| +	hostapd_ucode_init(&interfaces);
 | |
|  
 | |
|  	if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
 | |
|  		wpa_printf(MSG_ERROR, "Failed to start eloop");
 | |
| @@ -907,6 +908,7 @@ int main(int argc, char *argv[])
 | |
|  	ret = 0;
 | |
|  
 | |
|   out:
 | |
| +	hostapd_ucode_free();
 | |
|  	hostapd_global_ctrl_iface_deinit(&interfaces);
 | |
|  	/* Deinitialize all interfaces */
 | |
|  	for (i = 0; i < interfaces.count; i++) {
 | |
| --- a/src/ap/hostapd.h
 | |
| +++ b/src/ap/hostapd.h
 | |
| @@ -18,6 +18,7 @@
 | |
|  #include "ap_config.h"
 | |
|  #include "drivers/driver.h"
 | |
|  #include "ubus.h"
 | |
| +#include "ucode.h"
 | |
|  
 | |
|  #define OCE_STA_CFON_ENABLED(hapd) \
 | |
|  	((hapd->conf->oce & OCE_STA_CFON) && \
 | |
| @@ -50,6 +51,10 @@ struct hapd_interfaces {
 | |
|  	struct hostapd_config * (*config_read_cb)(const char *config_fname);
 | |
|  	int (*ctrl_iface_init)(struct hostapd_data *hapd);
 | |
|  	void (*ctrl_iface_deinit)(struct hostapd_data *hapd);
 | |
| +	int (*ctrl_iface_recv)(struct hostapd_data *hapd,
 | |
| +			       char *buf, char *reply, int reply_size,
 | |
| +			       struct sockaddr_storage *from,
 | |
| +			       socklen_t fromlen);
 | |
|  	int (*for_each_interface)(struct hapd_interfaces *interfaces,
 | |
|  				  int (*cb)(struct hostapd_iface *iface,
 | |
|  					    void *ctx), void *ctx);
 | |
| @@ -171,6 +176,7 @@ struct hostapd_data {
 | |
|  	struct hostapd_config *iconf;
 | |
|  	struct hostapd_bss_config *conf;
 | |
|  	struct hostapd_ubus_bss ubus;
 | |
| +	struct hostapd_ucode_bss ucode;
 | |
|  	int interface_added; /* virtual interface added for this BSS */
 | |
|  	unsigned int started:1;
 | |
|  	unsigned int disabled:1;
 | |
| @@ -463,6 +469,7 @@ struct hostapd_sta_info {
 | |
|   */
 | |
|  struct hostapd_iface {
 | |
|  	struct hapd_interfaces *interfaces;
 | |
| +	struct hostapd_ucode_iface ucode;
 | |
|  	void *owner;
 | |
|  	char *config_fname;
 | |
|  	struct hostapd_config *conf;
 | |
| @@ -637,6 +644,8 @@ struct hostapd_iface * hostapd_init(stru
 | |
|  struct hostapd_iface *
 | |
|  hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy,
 | |
|  			   const char *config_fname, int debug);
 | |
| +int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool start_beacon);
 | |
| +void hostapd_bss_deinit(struct hostapd_data *hapd);
 | |
|  void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
 | |
|  			   int reassoc);
 | |
|  void hostapd_interface_deinit_free(struct hostapd_iface *iface);
 | |
| @@ -662,6 +671,7 @@ hostapd_switch_channel_fallback(struct h
 | |
|  void hostapd_cleanup_cs_params(struct hostapd_data *hapd);
 | |
|  void hostapd_periodic_iface(struct hostapd_iface *iface);
 | |
|  int hostapd_owe_trans_get_info(struct hostapd_data *hapd);
 | |
| +void hostapd_owe_update_trans(struct hostapd_iface *iface);
 | |
|  void hostapd_ocv_check_csa_sa_query(void *eloop_ctx, void *timeout_ctx);
 | |
|  
 | |
|  /* utils.c */
 | |
| --- a/src/ap/hostapd.c
 | |
| +++ b/src/ap/hostapd.c
 | |
| @@ -216,6 +216,8 @@ int hostapd_reload_config(struct hostapd
 | |
|  	struct hostapd_config *newconf, *oldconf;
 | |
|  	size_t j;
 | |
|  
 | |
| +	hostapd_ucode_reload_bss(hapd);
 | |
| +
 | |
|  	if (iface->config_fname == NULL) {
 | |
|  		/* Only in-memory config in use - assume it has been updated */
 | |
|  		hostapd_clear_old(iface);
 | |
| @@ -376,6 +378,7 @@ void hostapd_free_hapd_data(struct hosta
 | |
|  	hapd->beacon_set_done = 0;
 | |
|  
 | |
|  	wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface);
 | |
| +	hostapd_ucode_free_bss(hapd);
 | |
|  	hostapd_ubus_free_bss(hapd);
 | |
|  	accounting_deinit(hapd);
 | |
|  	hostapd_deinit_wpa(hapd);
 | |
| @@ -531,6 +534,7 @@ void hostapd_cleanup_iface_partial(struc
 | |
|  static void hostapd_cleanup_iface(struct hostapd_iface *iface)
 | |
|  {
 | |
|  	wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface);
 | |
| +	hostapd_ucode_free_iface(iface);
 | |
|  	eloop_cancel_timeout(hostapd_interface_setup_failure_handler, iface,
 | |
|  			     NULL);
 | |
|  
 | |
| @@ -1104,7 +1108,7 @@ static int db_table_create_radius_attrib
 | |
|   * initialized. Most of the modules that are initialized here will be
 | |
|   * deinitialized in hostapd_cleanup().
 | |
|   */
 | |
| -static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
 | |
| +int hostapd_setup_bss(struct hostapd_data *hapd, int first, bool set_beacon)
 | |
|  {
 | |
|  	struct hostapd_bss_config *conf = hapd->conf;
 | |
|  	u8 ssid[SSID_MAX_LEN + 1];
 | |
| @@ -1400,6 +1404,7 @@ static int hostapd_setup_bss(struct host
 | |
|  		hapd->driver->set_operstate(hapd->drv_priv, 1);
 | |
|  
 | |
|  	hostapd_ubus_add_bss(hapd);
 | |
| +	hostapd_ucode_add_bss(hapd);
 | |
|  
 | |
|  	return 0;
 | |
|  }
 | |
| @@ -1945,7 +1950,7 @@ static int hostapd_owe_iface_iter2(struc
 | |
|  #endif /* CONFIG_OWE */
 | |
|  
 | |
|  
 | |
| -static void hostapd_owe_update_trans(struct hostapd_iface *iface)
 | |
| +void hostapd_owe_update_trans(struct hostapd_iface *iface)
 | |
|  {
 | |
|  #ifdef CONFIG_OWE
 | |
|  	/* Check whether the enabled BSS can complete OWE transition mode
 | |
| @@ -2090,7 +2095,7 @@ static int hostapd_setup_interface_compl
 | |
|  		hapd = iface->bss[j];
 | |
|  		if (j)
 | |
|  			os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
 | |
| -		if (hostapd_setup_bss(hapd, j == 0)) {
 | |
| +		if (hostapd_setup_bss(hapd, j == 0, true)) {
 | |
|  			for (;;) {
 | |
|  				hapd = iface->bss[j];
 | |
|  				hostapd_bss_deinit_no_free(hapd);
 | |
| @@ -2368,7 +2373,7 @@ hostapd_alloc_bss_data(struct hostapd_if
 | |
|  }
 | |
|  
 | |
|  
 | |
| -static void hostapd_bss_deinit(struct hostapd_data *hapd)
 | |
| +void hostapd_bss_deinit(struct hostapd_data *hapd)
 | |
|  {
 | |
|  	if (!hapd)
 | |
|  		return;
 | |
| @@ -2985,7 +2990,7 @@ int hostapd_add_iface(struct hapd_interf
 | |
|  
 | |
|  			if (start_ctrl_iface_bss(hapd) < 0 ||
 | |
|  			    (hapd_iface->state == HAPD_IFACE_ENABLED &&
 | |
| -			     hostapd_setup_bss(hapd, -1))) {
 | |
| +			     hostapd_setup_bss(hapd, -1, true))) {
 | |
|  				hostapd_cleanup(hapd);
 | |
|  				hapd_iface->bss[hapd_iface->num_bss - 1] = NULL;
 | |
|  				hapd_iface->conf->num_bss--;
 | |
| @@ -3137,7 +3142,8 @@ int hostapd_remove_iface(struct hapd_int
 | |
|  		hapd_iface = interfaces->iface[i];
 | |
|  		if (hapd_iface == NULL)
 | |
|  			return -1;
 | |
| -		if (!os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
 | |
| +		if (!os_strcmp(hapd_iface->phy, buf) ||
 | |
| +		    !os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) {
 | |
|  			wpa_printf(MSG_INFO, "Remove interface '%s'", buf);
 | |
|  			hapd_iface->driver_ap_teardown =
 | |
|  				!!(hapd_iface->drv_flags &
 | |
| --- a/wpa_supplicant/Makefile
 | |
| +++ b/wpa_supplicant/Makefile
 | |
| @@ -172,8 +172,20 @@ endif
 | |
|  ifdef CONFIG_UBUS
 | |
|  CFLAGS += -DUBUS_SUPPORT
 | |
|  OBJS += ubus.o
 | |
| +LIBS += -lubus
 | |
| +NEED_ULOOP:=y
 | |
| +endif
 | |
| +
 | |
| +ifdef CONFIG_UCODE
 | |
| +CFLAGS += -DUCODE_SUPPORT
 | |
| +OBJS += ../src/utils/ucode.o
 | |
| +OBJS += ucode.o
 | |
| +NEED_ULOOP:=y
 | |
| +endif
 | |
| +
 | |
| +ifdef NEED_ULOOP
 | |
|  OBJS += ../src/utils/uloop.o
 | |
| -LIBS += -lubox -lubus
 | |
| +LIBS += -lubox
 | |
|  endif
 | |
|  
 | |
|  ifdef CONFIG_CODE_COVERAGE
 | |
| @@ -956,6 +968,9 @@ OBJS += ../src/ap/ctrl_iface_ap.o
 | |
|  ifdef CONFIG_UBUS
 | |
|  OBJS += ../src/ap/ubus.o
 | |
|  endif
 | |
| +ifdef CONFIG_UCODE
 | |
| +OBJS += ../src/ap/ucode.o
 | |
| +endif
 | |
|  endif
 | |
|  
 | |
|  CFLAGS += -DEAP_SERVER -DEAP_SERVER_IDENTITY
 | |
| --- a/wpa_supplicant/wpa_supplicant.c
 | |
| +++ b/wpa_supplicant/wpa_supplicant.c
 | |
| @@ -1025,6 +1025,7 @@ void wpa_supplicant_set_state(struct wpa
 | |
|  		sme_sched_obss_scan(wpa_s, 0);
 | |
|  	}
 | |
|  	wpa_s->wpa_state = state;
 | |
| +	wpas_ucode_update_state(wpa_s);
 | |
|  
 | |
|  #ifdef CONFIG_BGSCAN
 | |
|  	if (state == WPA_COMPLETED && wpa_s->current_ssid != wpa_s->bgscan_ssid)
 | |
| @@ -6944,6 +6945,7 @@ struct wpa_supplicant * wpa_supplicant_a
 | |
|  #endif /* CONFIG_P2P */
 | |
|  
 | |
|  	wpas_ubus_add_bss(wpa_s);
 | |
| +	wpas_ucode_add_bss(wpa_s);
 | |
|  
 | |
|  	return wpa_s;
 | |
|  }
 | |
| @@ -6971,6 +6973,7 @@ int wpa_supplicant_remove_iface(struct w
 | |
|  	struct wpa_supplicant *parent = wpa_s->parent;
 | |
|  #endif /* CONFIG_MESH */
 | |
|  
 | |
| +	wpas_ucode_free_bss(wpa_s);
 | |
|  	wpas_ubus_free_bss(wpa_s);
 | |
|  
 | |
|  	/* Remove interface from the global list of interfaces */
 | |
| @@ -7238,6 +7241,7 @@ struct wpa_global * wpa_supplicant_init(
 | |
|  
 | |
|  	eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0,
 | |
|  			       wpas_periodic, global, NULL);
 | |
| +	wpas_ucode_init(global);
 | |
|  
 | |
|  	return global;
 | |
|  }
 | |
| @@ -7276,12 +7280,8 @@ int wpa_supplicant_run(struct wpa_global
 | |
|  	eloop_register_signal_terminate(wpa_supplicant_terminate, global);
 | |
|  	eloop_register_signal_reconfig(wpa_supplicant_reconfig, global);
 | |
|  
 | |
| -	wpas_ubus_add(global);
 | |
| -
 | |
|  	eloop_run();
 | |
|  
 | |
| -	wpas_ubus_free(global);
 | |
| -
 | |
|  	return 0;
 | |
|  }
 | |
|  
 | |
| @@ -7314,6 +7314,8 @@ void wpa_supplicant_deinit(struct wpa_gl
 | |
|  
 | |
|  	wpas_notify_supplicant_deinitialized(global);
 | |
|  
 | |
| +	wpas_ucode_free();
 | |
| +
 | |
|  	eap_peer_unregister_methods();
 | |
|  #ifdef CONFIG_AP
 | |
|  	eap_server_unregister_methods();
 | |
| --- a/wpa_supplicant/wpa_supplicant_i.h
 | |
| +++ b/wpa_supplicant/wpa_supplicant_i.h
 | |
| @@ -20,6 +20,7 @@
 | |
|  #include "config_ssid.h"
 | |
|  #include "wmm_ac.h"
 | |
|  #include "ubus.h"
 | |
| +#include "ucode.h"
 | |
|  
 | |
|  extern const char *const wpa_supplicant_version;
 | |
|  extern const char *const wpa_supplicant_license;
 | |
| @@ -600,6 +601,7 @@ struct wpa_supplicant {
 | |
|  	unsigned char perm_addr[ETH_ALEN];
 | |
|  	char ifname[100];
 | |
|  	struct wpas_ubus_bss ubus;
 | |
| +	struct wpas_ucode_bss ucode;
 | |
|  #ifdef CONFIG_MATCH_IFACE
 | |
|  	int matched;
 | |
|  #endif /* CONFIG_MATCH_IFACE */
 | |
| --- a/hostapd/ctrl_iface.c
 | |
| +++ b/hostapd/ctrl_iface.c
 | |
| @@ -4877,6 +4877,7 @@ try_again:
 | |
|  		return -1;
 | |
|  	}
 | |
|  
 | |
| +	interface->ctrl_iface_recv = hostapd_ctrl_iface_receive_process;
 | |
|  	wpa_msg_register_cb(hostapd_ctrl_iface_msg_cb);
 | |
|  
 | |
|  	return 0;
 | |
| @@ -4978,6 +4979,7 @@ fail:
 | |
|  	os_free(fname);
 | |
|  
 | |
|  	interface->global_ctrl_sock = s;
 | |
| +	interface->ctrl_iface_recv = hostapd_ctrl_iface_receive_process;
 | |
|  	eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
 | |
|  				 interface, NULL);
 | |
|  
 | |
| --- a/src/drivers/driver.h
 | |
| +++ b/src/drivers/driver.h
 | |
| @@ -3357,6 +3357,25 @@ struct wpa_driver_ops {
 | |
|  			 const char *ifname);
 | |
|  
 | |
|  	/**
 | |
| +	 * if_rename - Rename a virtual interface
 | |
| +	 * @priv: Private driver interface data
 | |
| +	 * @type: Interface type
 | |
| +	 * @ifname: Interface name of the virtual interface to be renamed
 | |
| +	 *	    (NULL when renaming the AP BSS interface)
 | |
| +	 * @new_name: New interface name of the virtual interface
 | |
| +	 * Returns: 0 on success, -1 on failure
 | |
| +	 */
 | |
| +	int (*if_rename)(void *priv, enum wpa_driver_if_type type,
 | |
| +			 const char *ifname, const char *new_name);
 | |
| +
 | |
| +	/**
 | |
| +	 * set_first_bss - Make a virtual interface the first (primary) bss
 | |
| +	 * @priv: Private driver interface data
 | |
| +	 * Returns: 0 on success, -1 on failure
 | |
| +	 */
 | |
| +	int (*set_first_bss)(void *priv);
 | |
| +
 | |
| +	/**
 | |
|  	 * set_sta_vlan - Bind a station into a specific interface (AP only)
 | |
|  	 * @priv: Private driver interface data
 | |
|  	 * @ifname: Interface (main or virtual BSS or VLAN)
 | |
| @@ -5827,6 +5846,7 @@ union wpa_event_data {
 | |
|  
 | |
|  	/**
 | |
|  	 * struct ch_switch
 | |
| +	 * @count: Count until channel switch activates
 | |
|  	 * @freq: Frequency of new channel in MHz
 | |
|  	 * @ht_enabled: Whether this is an HT channel
 | |
|  	 * @ch_offset: Secondary channel offset
 | |
| @@ -5835,6 +5855,7 @@ union wpa_event_data {
 | |
|  	 * @cf2: Center frequency 2
 | |
|  	 */
 | |
|  	struct ch_switch {
 | |
| +		int count;
 | |
|  		int freq;
 | |
|  		int ht_enabled;
 | |
|  		int ch_offset;
 | |
| --- a/src/drivers/driver_nl80211_event.c
 | |
| +++ b/src/drivers/driver_nl80211_event.c
 | |
| @@ -655,6 +655,7 @@ static void mlme_event_ch_switch(struct
 | |
|  				 struct nlattr *ifindex, struct nlattr *freq,
 | |
|  				 struct nlattr *type, struct nlattr *bw,
 | |
|  				 struct nlattr *cf1, struct nlattr *cf2,
 | |
| +				 struct nlattr *count,
 | |
|  				 int finished)
 | |
|  {
 | |
|  	struct i802_bss *bss;
 | |
| @@ -714,6 +715,8 @@ static void mlme_event_ch_switch(struct
 | |
|  		data.ch_switch.cf1 = nla_get_u32(cf1);
 | |
|  	if (cf2)
 | |
|  		data.ch_switch.cf2 = nla_get_u32(cf2);
 | |
| +	if (count)
 | |
| +		data.ch_switch.count = nla_get_u32(count);
 | |
|  
 | |
|  	if (finished)
 | |
|  		bss->freq = data.ch_switch.freq;
 | |
| @@ -2886,6 +2889,7 @@ static void do_process_drv_event(struct
 | |
|  				     tb[NL80211_ATTR_CHANNEL_WIDTH],
 | |
|  				     tb[NL80211_ATTR_CENTER_FREQ1],
 | |
|  				     tb[NL80211_ATTR_CENTER_FREQ2],
 | |
| +				     tb[NL80211_ATTR_CH_SWITCH_COUNT],
 | |
|  				     0);
 | |
|  		break;
 | |
|  	case NL80211_CMD_CH_SWITCH_NOTIFY:
 | |
| @@ -2896,6 +2900,7 @@ static void do_process_drv_event(struct
 | |
|  				     tb[NL80211_ATTR_CHANNEL_WIDTH],
 | |
|  				     tb[NL80211_ATTR_CENTER_FREQ1],
 | |
|  				     tb[NL80211_ATTR_CENTER_FREQ2],
 | |
| +					 NULL,
 | |
|  				     1);
 | |
|  		break;
 | |
|  	case NL80211_CMD_DISCONNECT:
 | |
| --- a/wpa_supplicant/events.c
 | |
| +++ b/wpa_supplicant/events.c
 | |
| @@ -4702,6 +4702,7 @@ void supplicant_event(void *ctx, enum wp
 | |
|  		event_to_string(event), event);
 | |
|  #endif /* CONFIG_NO_STDOUT_DEBUG */
 | |
|  
 | |
| +	wpas_ucode_event(wpa_s, event, data);
 | |
|  	switch (event) {
 | |
|  	case EVENT_AUTH:
 | |
|  #ifdef CONFIG_FST
 | |
| --- a/src/ap/ap_drv_ops.h
 | |
| +++ b/src/ap/ap_drv_ops.h
 | |
| @@ -367,6 +367,23 @@ static inline int hostapd_drv_stop_ap(st
 | |
|  	return hapd->driver->stop_ap(hapd->drv_priv);
 | |
|  }
 | |
|  
 | |
| +static inline int hostapd_drv_if_rename(struct hostapd_data *hapd,
 | |
| +					enum wpa_driver_if_type type,
 | |
| +					const char *ifname,
 | |
| +					const char *new_name)
 | |
| +{
 | |
| +	if (!hapd->driver || !hapd->driver->if_rename || !hapd->drv_priv)
 | |
| +		return -1;
 | |
| +	return hapd->driver->if_rename(hapd->drv_priv, type, ifname, new_name);
 | |
| +}
 | |
| +
 | |
| +static inline int hostapd_drv_set_first_bss(struct hostapd_data *hapd)
 | |
| +{
 | |
| +	if (!hapd->driver || !hapd->driver->set_first_bss || !hapd->drv_priv)
 | |
| +		return 0;
 | |
| +	return hapd->driver->set_first_bss(hapd->drv_priv);
 | |
| +}
 | |
| +
 | |
|  static inline int hostapd_drv_channel_info(struct hostapd_data *hapd,
 | |
|  					   struct wpa_channel_info *ci)
 | |
|  {
 | |
| --- a/src/drivers/driver_nl80211.c
 | |
| +++ b/src/drivers/driver_nl80211.c
 | |
| @@ -1224,7 +1224,7 @@ static void wpa_driver_nl80211_event_rtm
 | |
|  		}
 | |
|  		wpa_printf(MSG_DEBUG, "nl80211: Interface down (%s/%s)",
 | |
|  			   namebuf, ifname);
 | |
| -		if (os_strcmp(drv->first_bss->ifname, ifname) != 0) {
 | |
| +		if (drv->first_bss->ifindex != ifi->ifi_index) {
 | |
|  			wpa_printf(MSG_DEBUG,
 | |
|  				   "nl80211: Not the main interface (%s) - do not indicate interface down",
 | |
|  				   drv->first_bss->ifname);
 | |
| @@ -1260,7 +1260,7 @@ static void wpa_driver_nl80211_event_rtm
 | |
|  		}
 | |
|  		wpa_printf(MSG_DEBUG, "nl80211: Interface up (%s/%s)",
 | |
|  			   namebuf, ifname);
 | |
| -		if (os_strcmp(drv->first_bss->ifname, ifname) != 0) {
 | |
| +		if (drv->first_bss->ifindex != ifi->ifi_index) {
 | |
|  			wpa_printf(MSG_DEBUG,
 | |
|  				   "nl80211: Not the main interface (%s) - do not indicate interface up",
 | |
|  				   drv->first_bss->ifname);
 | |
| @@ -7614,6 +7614,7 @@ static void *i802_init(struct hostapd_da
 | |
|  	char master_ifname[IFNAMSIZ];
 | |
|  	int ifindex, br_ifindex = 0;
 | |
|  	int br_added = 0;
 | |
| +	int err;
 | |
|  
 | |
|  	bss = wpa_driver_nl80211_drv_init(hapd, params->ifname,
 | |
|  					  params->global_priv, 1,
 | |
| @@ -7673,21 +7674,17 @@ static void *i802_init(struct hostapd_da
 | |
|  	    (params->num_bridge == 0 || !params->bridge[0]))
 | |
|  		add_ifidx(drv, br_ifindex, drv->ifindex);
 | |
|  
 | |
| -	if (bss->added_if_into_bridge || bss->already_in_bridge) {
 | |
| -		int err;
 | |
| -
 | |
| -		drv->rtnl_sk = nl_socket_alloc();
 | |
| -		if (drv->rtnl_sk == NULL) {
 | |
| -			wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
 | |
| -			goto failed;
 | |
| -		}
 | |
| +	drv->rtnl_sk = nl_socket_alloc();
 | |
| +	if (drv->rtnl_sk == NULL) {
 | |
| +		wpa_printf(MSG_ERROR, "nl80211: Failed to allocate nl_sock");
 | |
| +		goto failed;
 | |
| +	}
 | |
|  
 | |
| -		err = nl_connect(drv->rtnl_sk, NETLINK_ROUTE);
 | |
| -		if (err) {
 | |
| -			wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
 | |
| -				   nl_geterror(err));
 | |
| -			goto failed;
 | |
| -		}
 | |
| +	err = nl_connect(drv->rtnl_sk, NETLINK_ROUTE);
 | |
| +	if (err) {
 | |
| +		wpa_printf(MSG_ERROR, "nl80211: Failed to connect nl_sock to NETLINK_ROUTE: %s",
 | |
| +			   nl_geterror(err));
 | |
| +		goto failed;
 | |
|  	}
 | |
|  
 | |
|  	if (drv->capa.flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX) {
 | |
| @@ -8047,6 +8044,50 @@ static int wpa_driver_nl80211_if_remove(
 | |
|  	return 0;
 | |
|  }
 | |
|  
 | |
| +static int wpa_driver_nl80211_if_rename(struct i802_bss *bss,
 | |
| +					enum wpa_driver_if_type type,
 | |
| +					const char *ifname, const char *new_name)
 | |
| +{
 | |
| +	struct wpa_driver_nl80211_data *drv = bss->drv;
 | |
| +	struct ifinfomsg ifi = {
 | |
| +		.ifi_family = AF_UNSPEC,
 | |
| +		.ifi_index = bss->ifindex,
 | |
| +	};
 | |
| +	struct nl_msg *msg;
 | |
| +	int res = -ENOMEM;
 | |
| +
 | |
| +	if (ifname)
 | |
| +		ifi.ifi_index = if_nametoindex(ifname);
 | |
| +
 | |
| +	msg = nlmsg_alloc_simple(RTM_SETLINK, 0);
 | |
| +	if (!msg)
 | |
| +		return res;
 | |
| +
 | |
| +	if (nlmsg_append(msg, &ifi, sizeof(ifi), NLMSG_ALIGNTO) < 0)
 | |
| +		goto out;
 | |
| +
 | |
| +	if (nla_put_string(msg, IFLA_IFNAME, new_name))
 | |
| +		goto out;
 | |
| +
 | |
| +	res = nl_send_auto_complete(drv->rtnl_sk, msg);
 | |
| +	if (res < 0)
 | |
| +		goto out;
 | |
| +
 | |
| +	res = nl_wait_for_ack(drv->rtnl_sk);
 | |
| +	if (res) {
 | |
| +		wpa_printf(MSG_INFO,
 | |
| +			   "nl80211: Renaming device %s to %s failed: %s",
 | |
| +			   ifname ? ifname : bss->ifname, new_name, nl_geterror(res));
 | |
| +		goto out;
 | |
| +	}
 | |
| +
 | |
| +	if (type == WPA_IF_AP_BSS && !ifname)
 | |
| +		os_strlcpy(bss->ifname, new_name, sizeof(bss->ifname));
 | |
| +
 | |
| +out:
 | |
| +	nlmsg_free(msg);
 | |
| +	return res;
 | |
| +}
 | |
|  
 | |
|  static int cookie_handler(struct nl_msg *msg, void *arg)
 | |
|  {
 | |
| @@ -9391,6 +9432,37 @@ static int driver_nl80211_if_remove(void
 | |
|  }
 | |
|  
 | |
|  
 | |
| +static int driver_nl80211_if_rename(void *priv, enum wpa_driver_if_type type,
 | |
| +				    const char *ifname, const char *new_name)
 | |
| +{
 | |
| +	struct i802_bss *bss = priv;
 | |
| +	return wpa_driver_nl80211_if_rename(bss, type, ifname, new_name);
 | |
| +}
 | |
| +
 | |
| +
 | |
| +static int driver_nl80211_set_first_bss(void *priv)
 | |
| +{
 | |
| +	struct i802_bss *bss = priv, *tbss;
 | |
| +	struct wpa_driver_nl80211_data *drv = bss->drv;
 | |
| +
 | |
| +	if (drv->first_bss == bss)
 | |
| +		return 0;
 | |
| +
 | |
| +	for (tbss = drv->first_bss; tbss; tbss = tbss->next) {
 | |
| +		if (tbss->next != bss)
 | |
| +			continue;
 | |
| +
 | |
| +		tbss->next = bss->next;
 | |
| +		bss->next = drv->first_bss;
 | |
| +		drv->first_bss = bss;
 | |
| +		drv->ctx = bss->ctx;
 | |
| +		return 0;
 | |
| +	}
 | |
| +
 | |
| +	return -1;
 | |
| +}
 | |
| +
 | |
| +
 | |
|  static int driver_nl80211_send_mlme(void *priv, const u8 *data,
 | |
|  				    size_t data_len, int noack,
 | |
|  				    unsigned int freq,
 | |
| @@ -11973,6 +12045,8 @@ const struct wpa_driver_ops wpa_driver_n
 | |
|  	.set_acl = wpa_driver_nl80211_set_acl,
 | |
|  	.if_add = wpa_driver_nl80211_if_add,
 | |
|  	.if_remove = driver_nl80211_if_remove,
 | |
| +	.if_rename = driver_nl80211_if_rename,
 | |
| +	.set_first_bss = driver_nl80211_set_first_bss,
 | |
|  	.send_mlme = driver_nl80211_send_mlme,
 | |
|  	.get_hw_feature_data = nl80211_get_hw_feature_data,
 | |
|  	.sta_add = wpa_driver_nl80211_sta_add,
 | |
| --- a/src/ap/ieee802_11.c
 | |
| +++ b/src/ap/ieee802_11.c
 | |
| @@ -494,11 +494,17 @@ static const char * sae_get_password(str
 | |
|  				     struct sae_pt **s_pt,
 | |
|  				     const struct sae_pk **s_pk)
 | |
|  {
 | |
| +	struct hostapd_bss_config *conf = hapd->conf;
 | |
| +	struct hostapd_ssid *ssid = &conf->ssid;
 | |
| +	struct hostapd_sta_wpa_psk_short *psk;
 | |
|  	const char *password = NULL;
 | |
| -	struct sae_password_entry *pw;
 | |
| +	struct sae_password_entry *pw = NULL;
 | |
|  	struct sae_pt *pt = NULL;
 | |
|  	const struct sae_pk *pk = NULL;
 | |
|  
 | |
| +	if (sta && sta->use_sta_psk)
 | |
| +		goto use_sta_psk;
 | |
| +
 | |
|  	for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) {
 | |
|  		if (!is_broadcast_ether_addr(pw->peer_addr) &&
 | |
|  		    os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0)
 | |
| @@ -519,6 +525,33 @@ static const char * sae_get_password(str
 | |
|  		pt = hapd->conf->ssid.pt;
 | |
|  	}
 | |
|  
 | |
| +use_sta_psk:
 | |
| +	if (!password && sta) {
 | |
| +		sta->psk_idx = 0;
 | |
| +		for (psk = sta->psk; psk; psk = psk->next) {
 | |
| +			if (!psk->is_passphrase)
 | |
| +				continue;
 | |
| +
 | |
| +			password = psk->passphrase;
 | |
| +			if (!sta->use_sta_psk)
 | |
| +				break;
 | |
| +
 | |
| +			sta->psk_idx = 1;
 | |
| +			if (sta->sae_pt) {
 | |
| +				pt = sta->sae_pt;
 | |
| +				break;
 | |
| +			}
 | |
| +
 | |
| +			pt = sae_derive_pt(conf->sae_groups, ssid->ssid,
 | |
| +					   ssid->ssid_len,
 | |
| +					   (const u8 *) password,
 | |
| +					   os_strlen(password),
 | |
| +					   NULL);
 | |
| +			sta->sae_pt = pt;
 | |
| +			break;
 | |
| +		}
 | |
| +	}
 | |
| +
 | |
|  	if (pw_entry)
 | |
|  		*pw_entry = pw;
 | |
|  	if (s_pt)
 | |
| @@ -3698,6 +3731,12 @@ static void handle_auth(struct hostapd_d
 | |
|  		goto fail;
 | |
|  	}
 | |
|  
 | |
| +	res = hostapd_ucode_sta_auth(hapd, sta);
 | |
| +	if (res) {
 | |
| +		resp = res;
 | |
| +		goto fail;
 | |
| +	}
 | |
| +
 | |
|  	sta->flags &= ~WLAN_STA_PREAUTH;
 | |
|  	ieee802_1x_notify_pre_auth(sta->eapol_sm, 0);
 | |
|  
 | |
| --- a/src/ap/sta_info.c
 | |
| +++ b/src/ap/sta_info.c
 | |
| @@ -412,6 +412,9 @@ void ap_free_sta(struct hostapd_data *ha
 | |
|  	os_free(sta->sae_postponed_commit);
 | |
|  #endif /* CONFIG_TESTING_OPTIONS */
 | |
|  
 | |
| +	if (sta->sae_pt)
 | |
| +		sae_deinit_pt(sta->sae_pt);
 | |
| +
 | |
|  	os_free(sta);
 | |
|  }
 | |
|  
 | |
| @@ -1280,6 +1283,8 @@ void ap_sta_set_authorized(struct hostap
 | |
|  	else
 | |
|  		sta->flags &= ~WLAN_STA_AUTHORIZED;
 | |
|  
 | |
| +	if (authorized)
 | |
| +		hostapd_ucode_sta_connected(hapd, sta);
 | |
|  #ifdef CONFIG_P2P
 | |
|  	if (hapd->p2p_group == NULL) {
 | |
|  		if (sta->p2p_ie != NULL &&
 | |
| --- a/src/ap/sta_info.h
 | |
| +++ b/src/ap/sta_info.h
 | |
| @@ -201,6 +201,9 @@ struct sta_info {
 | |
|  	int vlan_id_bound; /* updated by ap_sta_bind_vlan() */
 | |
|  	 /* PSKs from RADIUS authentication server */
 | |
|  	struct hostapd_sta_wpa_psk_short *psk;
 | |
| +	struct sae_pt *sae_pt;
 | |
| +	int use_sta_psk;
 | |
| +	int psk_idx;
 | |
|  
 | |
|  	char *identity; /* User-Name from RADIUS */
 | |
|  	char *radius_cui; /* Chargeable-User-Identity from RADIUS */
 | |
| --- a/src/ap/wpa_auth_glue.c
 | |
| +++ b/src/ap/wpa_auth_glue.c
 | |
| @@ -355,6 +355,7 @@ static const u8 * hostapd_wpa_auth_get_p
 | |
|  	}
 | |
|  #endif /* CONFIG_SAE */
 | |
|  
 | |
| +	sta->psk_idx = 0;
 | |
|  #ifdef CONFIG_OWE
 | |
|  	if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) &&
 | |
|  	    sta && sta->owe_pmk) {
 | |
| @@ -381,12 +382,17 @@ static const u8 * hostapd_wpa_auth_get_p
 | |
|  	 * returned psk which should not be returned again.
 | |
|  	 * logic list (all hostapd_get_psk; all sta->psk)
 | |
|  	 */
 | |
| +	if (sta && sta->use_sta_psk)
 | |
| +		psk = NULL;
 | |
|  	if (sta && sta->psk && !psk) {
 | |
|  		struct hostapd_sta_wpa_psk_short *pos;
 | |
| +		int psk_idx = 1;
 | |
|  
 | |
|  		if (vlan_id)
 | |
|  			*vlan_id = 0;
 | |
|  		psk = sta->psk->psk;
 | |
| +		if (vlan_id)
 | |
| +			sta->psk_idx = psk_idx;
 | |
|  		for (pos = sta->psk; pos; pos = pos->next) {
 | |
|  			if (pos->is_passphrase) {
 | |
|  				pbkdf2_sha1(pos->passphrase,
 | |
| @@ -397,9 +403,13 @@ static const u8 * hostapd_wpa_auth_get_p
 | |
|  			}
 | |
|  			if (pos->psk == prev_psk) {
 | |
|  				psk = pos->next ? pos->next->psk : NULL;
 | |
| +				if (vlan_id)
 | |
| +					sta->psk_idx = psk_idx + 1;
 | |
|  				break;
 | |
|  			}
 | |
|  		}
 | |
| +		if (vlan_id && !psk)
 | |
| +			sta->psk_idx = 0;
 | |
|  	}
 | |
|  	return psk;
 | |
|  }
 | 
