mirror of
				https://github.com/Telecominfraproject/wlan-ap.git
				synced 2025-10-31 02:17:58 +00:00 
			
		
		
		
	wifi-1704: Wifi6 Add missing hostapd patch for client events
Added missing client events support to wifi6-hostapd Signed-off-by: Yashvardhan <yashvardhan@netexperience.com>
This commit is contained in:
		 Yashvardhan
					Yashvardhan
				
			
				
					committed by
					
						 Rick Sommerville
						Rick Sommerville
					
				
			
			
				
	
			
			
			 Rick Sommerville
						Rick Sommerville
					
				
			
						parent
						
							9d13fc7330
						
					
				
				
					commit
					ca7b766171
				
			
							
								
								
									
										881
									
								
								feeds/wifi-ax/hostapd/patches/900-hapd-netlink-ubus-bridge.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										881
									
								
								feeds/wifi-ax/hostapd/patches/900-hapd-netlink-ubus-bridge.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,881 @@ | ||||
| --- a/hostapd/main.c | ||||
| +++ b/hostapd/main.c | ||||
| @@ -41,7 +41,7 @@ struct hapd_global { | ||||
|  static struct hapd_global global; | ||||
|  static int daemonize = 0; | ||||
|  static char *pid_file = NULL; | ||||
| - | ||||
| +uint32_t cached_events_nr = 0; | ||||
|   | ||||
|  #ifndef CONFIG_NO_HOSTAPD_LOGGER | ||||
|  static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module, | ||||
| --- a/src/ap/hostapd.h | ||||
| +++ b/src/ap/hostapd.h | ||||
| @@ -97,6 +97,10 @@ struct hostapd_probereq_cb { | ||||
|  }; | ||||
|   | ||||
|  #define HOSTAPD_RATE_BASIC 0x00000001 | ||||
| +/* max number of cached events */ | ||||
| +#define HOSTAPD_MAX_CACHED_EVENTS 500 | ||||
| +/* event counter */ | ||||
| +uint32_t cached_events_nr; | ||||
|   | ||||
|  struct hostapd_rate_data { | ||||
|  	int rate; /* rate in 100 kbps */ | ||||
| --- a/src/ap/ieee802_11.c | ||||
| +++ b/src/ap/ieee802_11.c | ||||
| @@ -4908,6 +4908,7 @@ int ieee802_11_mgmt(struct hostapd_data | ||||
|  	int ret = 0; | ||||
|  	unsigned int freq; | ||||
|  	int ssi_signal = fi ? fi->ssi_signal : 0; | ||||
| +	int ubus_resp; | ||||
|   | ||||
|  	if (len < 24) | ||||
|  		return 0; | ||||
| @@ -4977,25 +4978,52 @@ int ieee802_11_mgmt(struct hostapd_data | ||||
|  	if (hapd->iconf->track_sta_max_num) | ||||
|  		sta_track_add(hapd->iface, mgmt->sa, ssi_signal); | ||||
|   | ||||
| +	/* ubus request */ | ||||
| +	struct hostapd_ubus_request req = { | ||||
| +		.type = HOSTAPD_UBUS_TYPE_MAX, | ||||
| +		.mgmt_frame = mgmt, | ||||
| +		.ssi_signal = ssi_signal | ||||
| +	}; | ||||
| + | ||||
|  	switch (stype) { | ||||
|  	case WLAN_FC_STYPE_AUTH: | ||||
|  		wpa_printf(MSG_DEBUG, "mgmt::auth"); | ||||
|  		handle_auth(hapd, mgmt, len, ssi_signal, 0); | ||||
| +		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, | ||||
| +			       HOSTAPD_LEVEL_DEBUG, "mgmt: [%d] [%s]", | ||||
| +				   stype, | ||||
| +			       "AUTH"); | ||||
| +		req.type = HOSTAPD_UBUS_AUTH_REQ; | ||||
|  		ret = 1; | ||||
|  		break; | ||||
|  	case WLAN_FC_STYPE_ASSOC_REQ: | ||||
|  		wpa_printf(MSG_DEBUG, "mgmt::assoc_req"); | ||||
|  		handle_assoc(hapd, mgmt, len, 0, ssi_signal); | ||||
| +		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, | ||||
| +			       HOSTAPD_LEVEL_DEBUG, "mgmt: [%d] [%s]", | ||||
| +				   stype, | ||||
| +			       "ASSOC"); | ||||
| +		req.type = HOSTAPD_UBUS_ASSOC_REQ; | ||||
|  		ret = 1; | ||||
|  		break; | ||||
|  	case WLAN_FC_STYPE_REASSOC_REQ: | ||||
|  		wpa_printf(MSG_DEBUG, "mgmt::reassoc_req"); | ||||
|  		handle_assoc(hapd, mgmt, len, 1, ssi_signal); | ||||
| +		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, | ||||
| +			       HOSTAPD_LEVEL_DEBUG, "mgmt: [%d] [%s]", | ||||
| +				   stype, | ||||
| +			       "RE-ASSOC"); | ||||
| +		req.type = HOSTAPD_UBUS_REASSOC_REQ; | ||||
|  		ret = 1; | ||||
|  		break; | ||||
|  	case WLAN_FC_STYPE_DISASSOC: | ||||
|  		wpa_printf(MSG_DEBUG, "mgmt::disassoc"); | ||||
|  		handle_disassoc(hapd, mgmt, len); | ||||
| +		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, | ||||
| +			       HOSTAPD_LEVEL_DEBUG, "mgmt: [%d] [%s]", | ||||
| +				   stype, | ||||
| +			       "DISASSOC"); | ||||
| +		req.type = HOSTAPD_UBUS_DISASSOC_REQ; | ||||
|  		ret = 1; | ||||
|  		break; | ||||
|  	case WLAN_FC_STYPE_DEAUTH: | ||||
| @@ -5014,6 +5042,15 @@ int ieee802_11_mgmt(struct hostapd_data | ||||
|  		break; | ||||
|  	} | ||||
|   | ||||
| +	/* ubus send */ | ||||
| +	if (req.type != HOSTAPD_UBUS_TYPE_MAX) { | ||||
| +		ubus_resp = hostapd_ubus_handle_rt_event(hapd, &req); | ||||
| +		if (ubus_resp) { | ||||
| +			hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, | ||||
| +				       HOSTAPD_LEVEL_INFO, | ||||
| +				       "hostapd_ubus_handle_rt_event: ERROR"); | ||||
| +		} | ||||
| +	} | ||||
|  	return ret; | ||||
|  } | ||||
|   | ||||
| --- a/src/ap/sta_info.c | ||||
| +++ b/src/ap/sta_info.c | ||||
| @@ -423,8 +423,14 @@ void ap_handle_timer(void *eloop_ctx, vo | ||||
|  		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, | ||||
|  			       HOSTAPD_LEVEL_INFO, "deauthenticated due to " | ||||
|  			       "local deauth request"); | ||||
| -		ap_free_sta(hapd, sta); | ||||
|  		hostapd_ubus_notify(hapd, "local-deauth", sta->addr); | ||||
| +		struct hostapd_ubus_request req = { | ||||
| +			.type = HOSTAPD_UBUS_DISASSOC_REQ, | ||||
| +			.sta = sta, | ||||
| +			.reason = sta->deauth_reason | ||||
| +		}; | ||||
| +		hostapd_ubus_handle_rt_event(hapd, &req); | ||||
| +		ap_free_sta(hapd, sta); | ||||
|  		return; | ||||
|  	} | ||||
|   | ||||
| @@ -530,6 +536,14 @@ skip_poll: | ||||
|  				WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY : | ||||
|  				WLAN_REASON_PREV_AUTH_NOT_VALID; | ||||
|   | ||||
| +			/* sessions */ | ||||
| +			struct hostapd_ubus_request req = { | ||||
| +				.type = HOSTAPD_UBUS_DISASSOC_REQ, | ||||
| +				.sta = sta, | ||||
| +				.reason = reason | ||||
| +			}; | ||||
| +			hostapd_ubus_handle_rt_event(hapd, &req); | ||||
| + | ||||
|  			hostapd_drv_sta_disassoc(hapd, sta->addr, reason); | ||||
|  		} | ||||
|  	} | ||||
| @@ -566,6 +580,15 @@ skip_poll: | ||||
|  			   __func__, MAC2STR(sta->addr), AP_DEAUTH_DELAY); | ||||
|  		eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, | ||||
|  				       hapd, sta); | ||||
| + | ||||
| +		/* sessions */ | ||||
| +		struct hostapd_ubus_request req = { | ||||
| +			.type = HOSTAPD_UBUS_DISASSOC_REQ, | ||||
| +			.sta = sta, | ||||
| +			.reason = reason | ||||
| +		}; | ||||
| +		hostapd_ubus_handle_rt_event(hapd, &req); | ||||
| + | ||||
|  		mlme_disassociate_indication(hapd, sta, reason); | ||||
|  		break; | ||||
|  	case STA_DEAUTH: | ||||
| --- a/src/ap/sta_info.h | ||||
| +++ b/src/ap/sta_info.h | ||||
| @@ -77,6 +77,9 @@ struct sta_info { | ||||
|  	u8 supported_rates[WLAN_SUPP_RATES_MAX]; | ||||
|  	int supported_rates_len; | ||||
|  	u8 qosinfo; /* Valid when WLAN_STA_WMM is set */ | ||||
| +	u64 cl_session_id; /* client fnv1a 64bit session id */ | ||||
| +	u8 fdata; /* client first data flag */ | ||||
| +	u8 first_ip; /* client first ip flag */ | ||||
|   | ||||
|  #ifdef CONFIG_MESH | ||||
|  	enum mesh_plink_state plink_state; | ||||
| --- a/src/ap/ubus.c | ||||
| +++ b/src/ap/ubus.c | ||||
| @@ -24,7 +24,10 @@ | ||||
|   | ||||
|  static struct ubus_context *ctx; | ||||
|  static struct blob_buf b; | ||||
| +static struct blob_buf b_ev; | ||||
|  static int ctx_ref; | ||||
| +static char** bss_lst = NULL; | ||||
| +static size_t bss_nr = 0; | ||||
|   | ||||
|  static inline struct hapd_interfaces *get_hapd_interfaces_from_object(struct ubus_object *obj) | ||||
|  { | ||||
| @@ -63,6 +66,21 @@ static void hostapd_ubus_connection_lost | ||||
|  	eloop_register_timeout(1, 0, ubus_reconnect_timeout, ctx, NULL); | ||||
|  } | ||||
|   | ||||
| +static int avl_compare_sess_id(const void *k1, const void *k2, void *ptr) | ||||
| +{ | ||||
| +	const uint32_t *id1 = k1, *id2 = k2; | ||||
| + | ||||
| +	if (*id1 < *id2) | ||||
| +		return -1; | ||||
| +	else | ||||
| +		return *id1 > *id2; | ||||
| +} | ||||
| + | ||||
| +uint64_t get_time_in_ms(struct timespec *ts) | ||||
| +{ | ||||
| +    return (uint64_t) ts->tv_sec * 1000 + ts->tv_nsec / 1000000; | ||||
| +} | ||||
| + | ||||
|  static bool hostapd_ubus_init(void) | ||||
|  { | ||||
|  	if (ctx) | ||||
| @@ -525,6 +543,177 @@ static const struct blobmsg_policy csa_p | ||||
|  }; | ||||
|   | ||||
|  #ifdef NEED_AP_MLME | ||||
| +enum { CSESS_REQ_SESS_ID, | ||||
| +       __CSESS_REQ_MAX, | ||||
| +}; | ||||
| + | ||||
| +static const struct blobmsg_policy client_session_del_policy[__CSESS_REQ_MAX] = { | ||||
| +	[CSESS_REQ_SESS_ID] = { .name = "session_id", .type = BLOBMSG_TYPE_INT64 }, | ||||
| +}; | ||||
| + | ||||
| +static int hostapd_clear_session(struct ubus_context *ctx, | ||||
| +				 struct ubus_object *obj, | ||||
| +				 struct ubus_request_data *req, | ||||
| +				 const char *method, | ||||
| +				 struct blob_attr *msg) | ||||
| +{ | ||||
| +	struct blob_attr *tb[__CSESS_REQ_MAX]; | ||||
| +	struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); | ||||
| +	struct hostapd_event_avl_rec *rec = NULL; | ||||
| +	struct hostapd_event_avl_rec *rec_next = NULL; | ||||
| +	uint64_t session_id = 0; | ||||
| + | ||||
| +	blobmsg_parse(client_session_del_policy, __CSESS_REQ_MAX, tb, | ||||
| +		      blob_data(msg), blob_len(msg)); | ||||
| + | ||||
| +	if (!tb[CSESS_REQ_SESS_ID]) | ||||
| +		return UBUS_STATUS_INVALID_ARGUMENT; | ||||
| + | ||||
| +	session_id = blobmsg_get_u64(tb[CSESS_REQ_SESS_ID]); | ||||
| +	/* remove from AVL and ubus session object) */ | ||||
| +	avl_for_each_element_safe(&hapd->ubus.rt_events, rec, avl, rec_next) | ||||
| +	{ | ||||
| +		if (session_id == rec->session_id) { | ||||
| +			/* dec counter and delete */ | ||||
| +			cached_events_nr -= rec->rec_nr; | ||||
| +			avl_delete(&hapd->ubus.rt_events, &rec->avl); | ||||
| +			os_free(rec->records); | ||||
| +			os_free(rec); | ||||
| +		} | ||||
| +	} | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int hostapd_clear_sessions(struct ubus_context *ctx, | ||||
| +				  struct ubus_object *obj, | ||||
| +				  struct ubus_request_data *req, | ||||
| +				  const char *method, | ||||
| +				  struct blob_attr *msg) | ||||
| +{ | ||||
| +	struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); | ||||
| +	struct hostapd_event_avl_rec *rec = NULL; | ||||
| +	struct hostapd_event_avl_rec *rec_n = NULL; | ||||
| + | ||||
| +	avl_remove_all_elements(&hapd->ubus.rt_events, rec, avl, rec_n) | ||||
| +	{ | ||||
| +		/* free events array */ | ||||
| +		os_free(rec->records); | ||||
| +		os_free(rec); | ||||
| +	} | ||||
| +	/* reset counter */ | ||||
| +	cached_events_nr = 0; | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int hostapd_sessions(struct ubus_context *ctx, | ||||
| +			struct ubus_object *obj, | ||||
| +		        struct ubus_request_data *req, | ||||
| +			const char *method, | ||||
| +                        struct blob_attr *msg) | ||||
| +{ | ||||
| +	struct hostapd_data *hapd = container_of(obj, struct hostapd_data, ubus.obj); | ||||
| +	void *a = NULL; | ||||
| +	void *t = NULL; | ||||
| +	void *t_msg = NULL; | ||||
| +	struct hostapd_event_avl_rec *rec = NULL; | ||||
| +	struct client_session_record *c_rec = NULL; | ||||
| + | ||||
| +	blob_buf_init(&b_ev, 0); | ||||
| +	a = blobmsg_open_table(&b_ev, "sessions"); | ||||
| +	avl_for_each_element(&hapd->ubus.rt_events, rec, avl) | ||||
| +	{ | ||||
| +		/* open session */ | ||||
| +		t = blobmsg_open_table(&b_ev, "ClientSession"); | ||||
| +		blobmsg_add_u64(&b_ev, "session_id", rec->session_id); | ||||
| +		/* messages for current session */ | ||||
| +		for (size_t i = 0; i < rec->rec_nr; i++) { | ||||
| +			c_rec = &rec->records[i]; | ||||
| +			/* check message type */ | ||||
| +			switch (c_rec->type) { | ||||
| +			/* ClientAuthEvent */ | ||||
| +			case CST_AUTH: { | ||||
| +				struct client_auth_event *p = &c_rec->u.auth; | ||||
| +				t_msg = blobmsg_open_table(&b_ev, "ClientAuthEvent"); | ||||
| +				blobmsg_add_u64(&b_ev, "session_id", rec->session_id); | ||||
| +				blobmsg_add_u64(&b_ev, "timestamp", c_rec->timestamp); | ||||
| +				blobmsg_add_string(&b_ev, "sta_mac", p->sta_mac); | ||||
| +				blobmsg_add_u32(&b_ev, "band", p->band); | ||||
| +				blobmsg_add_u32(&b_ev, "auth_status", p->auth_status); | ||||
| +				blobmsg_add_string(&b_ev, "ssid", p->ssid); | ||||
| +				blobmsg_close_table(&b_ev, t_msg); | ||||
| +				break; | ||||
| +			} | ||||
| + | ||||
| +			/* ClientAssocEvent */ | ||||
| +			case CST_ASSOC: { | ||||
| +				struct client_assoc_event *p = &c_rec->u.assoc; | ||||
| +				t_msg = blobmsg_open_table(&b_ev, "ClientAssocEvent"); | ||||
| +				blobmsg_add_u64(&b_ev, "session_id", rec->session_id); | ||||
| +				blobmsg_add_u64(&b_ev, "timestamp", c_rec->timestamp); | ||||
| +				blobmsg_add_string(&b_ev, "sta_mac", p->sta_mac); | ||||
| +				blobmsg_add_u32(&b_ev, "band", p->band); | ||||
| +				blobmsg_add_u32(&b_ev, "assoc_type", 0); | ||||
| +				blobmsg_add_u32(&b_ev, "rssi", p->rssi); | ||||
| +				blobmsg_add_u32(&b_ev, "internal_sc", 0); | ||||
| +				blobmsg_add_u8(&b_ev, "using11k", p->using11k); | ||||
| +				blobmsg_add_u8(&b_ev, "using11r", p->using11r); | ||||
| +				blobmsg_add_u8(&b_ev, "using11v", p->using11v); | ||||
| +				blobmsg_add_string(&b_ev, "ssid", p->ssid); | ||||
| +				blobmsg_close_table(&b_ev, t_msg); | ||||
| +				break; | ||||
| +			} | ||||
| + | ||||
| +			/* ClientDisconnectEvent */ | ||||
| +			case CST_DISASSOC: { | ||||
| +				struct client_disassoc_event *p = &c_rec->u.disassoc; | ||||
| +				t_msg = blobmsg_open_table(&b_ev, "ClientDisconnectEvent"); | ||||
| +				blobmsg_add_u64(&b_ev, "session_id", rec->session_id); | ||||
| +				blobmsg_add_u64(&b_ev, "timestamp", c_rec->timestamp); | ||||
| +				blobmsg_add_string(&b_ev, "sta_mac", p->sta_mac); | ||||
| +				blobmsg_add_u32(&b_ev, "band", p->band); | ||||
| +				blobmsg_add_u32(&b_ev, "rssi", p->rssi); | ||||
| +				blobmsg_add_u32(&b_ev, "internal_rc", p->internal_rc); | ||||
| +				blobmsg_add_string(&b_ev, "ssid", p->ssid); | ||||
| +				blobmsg_close_table(&b_ev, t_msg); | ||||
| +				break; | ||||
| +			} | ||||
| + | ||||
| +			/* ClientFirstDataEvent */ | ||||
| +			case CST_FDATA: { | ||||
| +				struct client_fdata_event *p = &c_rec->u.fdata; | ||||
| +				t_msg = blobmsg_open_table(&b_ev, "ClientFirstDataEvent"); | ||||
| +				blobmsg_add_u64(&b_ev, "session_id", rec->session_id); | ||||
| +				blobmsg_add_u64(&b_ev, "timestamp", c_rec->timestamp); | ||||
| +				blobmsg_add_string(&b_ev, "sta_mac", p->sta_mac); | ||||
| +				blobmsg_add_u64(&b_ev, "fdata_tx_up_ts_in_us", p->tx_ts.tv_sec * (uint64_t)1000000); | ||||
| +				blobmsg_add_u64(&b_ev, "fdata_rx_up_ts_in_us", p->rx_ts.tv_sec * (uint64_t)1000000); | ||||
| +				blobmsg_close_table(&b_ev, t_msg); | ||||
| +				break; | ||||
| +			} | ||||
| + | ||||
| +			/* ClientIpEvent */ | ||||
| +			case CST_IP: { | ||||
| +				struct client_ip_event *p = &c_rec->u.ip; | ||||
| +				t_msg = blobmsg_open_table(&b_ev, "ClientIpEvent"); | ||||
| +				blobmsg_add_u64(&b_ev, "session_id", rec->session_id); | ||||
| +				blobmsg_add_u64(&b_ev, "timestamp", c_rec->timestamp); | ||||
| +				blobmsg_add_string(&b_ev, "sta_mac", p->sta_mac); | ||||
| +				blobmsg_add_string(&b_ev, "ip_address", p->ip_addr); | ||||
| +				blobmsg_close_table(&b_ev, t_msg); | ||||
| +				break; | ||||
| +			} | ||||
| + | ||||
| +			default: | ||||
| +				break; | ||||
| +			} | ||||
| +		} | ||||
| +		blobmsg_close_table(&b_ev, t); | ||||
| +	} | ||||
| +	blobmsg_close_table(&b_ev, a); | ||||
| +	ubus_send_reply(ctx, req, b_ev.head); | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
|  static int | ||||
|  hostapd_switch_chan(struct ubus_context *ctx, struct ubus_object *obj, | ||||
|  		    struct ubus_request_data *req, const char *method, | ||||
| @@ -1148,6 +1337,9 @@ static const struct ubus_method bss_meth | ||||
|  	UBUS_METHOD_NOARG("get_features", hostapd_bss_get_features), | ||||
|  #ifdef NEED_AP_MLME | ||||
|  	UBUS_METHOD("switch_chan", hostapd_switch_chan, csa_policy), | ||||
| +	UBUS_METHOD_NOARG("get_sessions", hostapd_sessions), | ||||
| +	UBUS_METHOD_NOARG("clear_sessions", hostapd_clear_sessions), | ||||
| +	UBUS_METHOD("clear_session", hostapd_clear_session, client_session_del_policy), | ||||
|  #endif | ||||
|  	UBUS_METHOD("set_vendor_elements", hostapd_vendor_elements, ve_policy), | ||||
|  	UBUS_METHOD("notify_response", hostapd_notify_response, notify_policy), | ||||
| @@ -1187,6 +1379,7 @@ void hostapd_ubus_add_bss(struct hostapd | ||||
|  	if (asprintf(&name, "hostapd.%s", hapd->conf->iface) < 0) | ||||
|  		return; | ||||
|   | ||||
| +	avl_init(&hapd->ubus.rt_events, avl_compare_sess_id, false, NULL); | ||||
|  	avl_init(&hapd->ubus.banned, avl_compare_macaddr, false, NULL); | ||||
|  	obj->name = name; | ||||
|  	obj->type = &bss_object_type; | ||||
| @@ -1194,6 +1387,9 @@ void hostapd_ubus_add_bss(struct hostapd | ||||
|  	obj->n_methods = bss_object_type.n_methods; | ||||
|  	ret = ubus_add_object(ctx, obj); | ||||
|  	hostapd_ubus_ref_inc(); | ||||
| +	bss_nr++; | ||||
| +	bss_lst = os_realloc(bss_lst, sizeof(char *) * bss_nr); | ||||
| +	bss_lst[bss_nr - 1] = strdup(name); | ||||
|  	if (hapd->conf->signal_stay_min > -128) | ||||
|  		eloop_register_timeout(3, 0, hostapd_bss_signal_check, NULL, hapd);  /* Start up the poll timer. */ | ||||
|  } | ||||
| @@ -1212,11 +1408,42 @@ void hostapd_ubus_free_bss(struct hostap | ||||
|  	} | ||||
|   | ||||
|  	free(name); | ||||
| +	for (size_t i = 0; i < bss_nr; i++) | ||||
| +		os_free(bss_lst[i]); | ||||
| +	free(bss_lst); | ||||
| +	bss_lst = NULL; | ||||
| +} | ||||
| + | ||||
| +static int hostapd_get_bss_list(struct ubus_context *ctx, | ||||
| +				struct ubus_object *obj, | ||||
| +				struct ubus_request_data *req, | ||||
| +				const char *method, | ||||
| +				struct blob_attr *msg) | ||||
| +{ | ||||
| +	if (!bss_lst) | ||||
| +		return 0; | ||||
| + | ||||
| +	void *a = NULL; | ||||
| +	void *b = NULL; | ||||
| + | ||||
| +	/* create reply */ | ||||
| +	blob_buf_init(&b_ev, 0); | ||||
| +	a = blobmsg_open_array(&b_ev, "bss_list"); | ||||
| +	/* check bss list from hapd */ | ||||
| +	for (size_t i = 0; i < bss_nr; i++) { | ||||
| +		b = blobmsg_open_table(&b_ev, NULL); | ||||
| +		blobmsg_add_string(&b_ev, "name", bss_lst[i]); | ||||
| +		blobmsg_close_table(&b_ev, b); | ||||
| +	} | ||||
| +	blobmsg_close_array(&b_ev, a); | ||||
| +	ubus_send_reply(ctx, req, b_ev.head); | ||||
| +	return 0; | ||||
|  } | ||||
|   | ||||
|  static const struct ubus_method daemon_methods[] = { | ||||
|  	UBUS_METHOD("config_add", hostapd_config_add, config_add_policy), | ||||
|  	UBUS_METHOD("config_remove", hostapd_config_remove, config_remove_policy), | ||||
| +	UBUS_METHOD_NOARG("get_bss_list", hostapd_get_bss_list), | ||||
|  }; | ||||
|   | ||||
|  static struct ubus_object_type daemon_object_type = | ||||
| @@ -1260,6 +1487,18 @@ struct ubus_event_req { | ||||
|  	int resp; | ||||
|  }; | ||||
|   | ||||
| +static uint64_t hash_fnv1a_64bit(const void *key, int len) | ||||
| +{ | ||||
| +	if (key == NULL) | ||||
| +		return 0; | ||||
| +	unsigned char *p = (unsigned char *)key; | ||||
| +	uint64_t h = 14695981039346656037UL; | ||||
| +	int i; | ||||
| +	for (i = 0; i < len; i++) | ||||
| +		h = (h ^ p[i]) * 1099511628211UL; | ||||
| +	return h; | ||||
| +} | ||||
| + | ||||
|  static void | ||||
|  ubus_event_cb(struct ubus_notify_request *req, int idx, int ret) | ||||
|  { | ||||
| @@ -1268,6 +1507,224 @@ ubus_event_cb(struct ubus_notify_request | ||||
|  	ureq->resp = ret; | ||||
|  } | ||||
|   | ||||
| +int hostapd_ubus_handle_rt_event(struct hostapd_data *hapd, | ||||
| +				 struct hostapd_ubus_request *req) | ||||
| +{ | ||||
| +	/* check event counter */ | ||||
| +	if (cached_events_nr > HOSTAPD_MAX_CACHED_EVENTS) { | ||||
| +		hostapd_logger( | ||||
| +			hapd, NULL, HOSTAPD_MODULE_IEEE80211, | ||||
| +			HOSTAPD_LEVEL_WARNING, | ||||
| +			"hostapd_ubus_handle_rt_event: HOSTAPD_MAX_CACHED_EVENTS [%d] exceeded", | ||||
| +			HOSTAPD_MAX_CACHED_EVENTS); | ||||
| +		return WLAN_STATUS_SUCCESS; | ||||
| +	} | ||||
| +	struct hostapd_event_avl_rec *rec = NULL; | ||||
| +	struct timespec ts; | ||||
| +	uint64_t timestamp = 0; | ||||
| +	clock_gettime(CLOCK_REALTIME, &ts); | ||||
| +	timestamp = get_time_in_ms(&ts); | ||||
| +	uint64_t session_id = 0; | ||||
| +	uint8_t new_rec = 0; | ||||
| +	const struct ieee80211_mgmt *mgmt = req->mgmt_frame; | ||||
| +	struct sta_info *sta = req->sta ? (void *)req->sta : ap_get_sta(hapd, mgmt->sa); | ||||
| +	/* null pointer check */ | ||||
| +	if (!sta) return WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; | ||||
| + | ||||
| +	struct hostapd_bss_config *bss_conf = hapd->conf; | ||||
| +	session_id = sta->cl_session_id; | ||||
| + | ||||
| +	/* find by session id */ | ||||
| +	rec = avl_find_element(&hapd->ubus.rt_events, &session_id, rec, avl); | ||||
| + | ||||
| +	/* prepare rec if not found */ | ||||
| +	if (!rec) { | ||||
| +		new_rec = 1; | ||||
| +		rec = os_zalloc(sizeof(struct hostapd_event_avl_rec)); | ||||
| +		session_id = hash_fnv1a_64bit(&ts, sizeof(struct timespec)); | ||||
| +	} | ||||
| +	hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, | ||||
| +		       HOSTAPD_LEVEL_DEBUG, | ||||
| +		       "hostapd_ubus_handle_rt_event: REQ TYPE [%d]", | ||||
| +		       req->type); | ||||
| + | ||||
| +	switch (req->type) { | ||||
| +	case HOSTAPD_UBUS_AUTH_REQ: { | ||||
| +		/* session id */ | ||||
| +		rec->session_id = session_id; | ||||
| +		rec->rec_nr++; | ||||
| +		rec->records = os_realloc(rec->records, | ||||
| +					  sizeof(struct client_session_record) * rec->rec_nr); | ||||
| +		struct client_session_record *rp = &rec->records[rec->rec_nr - 1]; | ||||
| +		rp->type = CST_AUTH; | ||||
| +		rp->u.auth.session_id = rec->session_id; | ||||
| + | ||||
| +		/* timestamp */ | ||||
| +		rp->timestamp = timestamp; | ||||
| +		/* frequency */ | ||||
| +		rp->u.auth.band = hapd->iface->freq; | ||||
| +		/* STA MAC */ | ||||
| +		sprintf(rp->u.auth.sta_mac, MACSTR, MAC2STR(sta->addr)); | ||||
| +		/* ssid */ | ||||
| +		rp->u.auth.ssid[0] = 0; | ||||
| +		printf_encode(rp->u.auth.ssid, sizeof(rp->u.auth.ssid), | ||||
| +			      bss_conf->ssid.ssid, bss_conf->ssid.ssid_len); | ||||
| +		/* auth status */ | ||||
| +		rp->u.auth.auth_status = le_to_host16(mgmt->u.auth.status_code); | ||||
| +		hostapd_logger( | ||||
| +			hapd, NULL, HOSTAPD_MODULE_IEEE80211, | ||||
| +			HOSTAPD_LEVEL_DEBUG, | ||||
| +			"hostapd_ubus_handle_rt_event:HOSTAPD_UBUS_AUTH_REQ"); | ||||
| +		/* inc counter */ | ||||
| +		cached_events_nr++; | ||||
| +		break; | ||||
| +	} | ||||
| +	case HOSTAPD_UBUS_ASSOC_REQ: { | ||||
| +		/* session id */ | ||||
| +		rec->session_id = session_id; | ||||
| +		rec->rec_nr++; | ||||
| +		rec->records = os_realloc(rec->records, | ||||
| +					  sizeof(struct client_session_record) * rec->rec_nr); | ||||
| +		struct client_session_record *rp = &rec->records[rec->rec_nr - 1]; | ||||
| +		rp->type = CST_ASSOC; | ||||
| +		rp->u.assoc.session_id = rec->session_id; | ||||
| +		/* timestamp */ | ||||
| +		rp->timestamp = timestamp; | ||||
| +		/* frequency */ | ||||
| +		rp->u.assoc.band = hapd->iface->freq; | ||||
| +		/* STA MAC */ | ||||
| +		sprintf(rp->u.assoc.sta_mac, MACSTR, MAC2STR(sta->addr)); | ||||
| +		/* ssid */ | ||||
| +		rp->u.assoc.ssid[0] = 0; | ||||
| +		printf_encode(rp->u.assoc.ssid, sizeof(rp->u.assoc.ssid), | ||||
| +			      bss_conf->ssid.ssid, bss_conf->ssid.ssid_len); | ||||
| +		/* rssi */ | ||||
| +		rp->u.assoc.rssi = req->ssi_signal; | ||||
| +		/* using 11r */ | ||||
| +		rp->u.assoc.using11r = (sta->auth_alg & WPA_AUTH_ALG_FT); | ||||
| +		/* using 11k */ | ||||
| +		if (sta->rrm_enabled_capa[0] || sta->rrm_enabled_capa[1] || | ||||
| +		    sta->rrm_enabled_capa[2] || sta->rrm_enabled_capa[3] || | ||||
| +		    sta->rrm_enabled_capa[4]) | ||||
| +			rp->u.assoc.using11k = 1; | ||||
| +		else | ||||
| +			rp->u.assoc.using11k = 0; | ||||
| +		/* using 11v */ | ||||
| +		if (bss_conf->time_advertisement || bss_conf->wnm_sleep_mode || | ||||
| +		    bss_conf->bss_transition) | ||||
| +			rp->u.assoc.using11v = 1; | ||||
| +		else | ||||
| +			rp->u.assoc.using11v = 0; | ||||
| +		hostapd_logger( | ||||
| +			hapd, NULL, HOSTAPD_MODULE_IEEE80211, | ||||
| +			HOSTAPD_LEVEL_DEBUG, | ||||
| +			"hostapd_ubus_handle_rt_event:HOSTAPD_UBUS_ASSOC_REQ"); | ||||
| +		/* inc counter */ | ||||
| +		cached_events_nr++; | ||||
| +		break; | ||||
| +	} | ||||
| +	case HOSTAPD_UBUS_DISASSOC_REQ: { | ||||
| +		/* session id */ | ||||
| +		rec->session_id = session_id; | ||||
| +		rec->rec_nr++; | ||||
| +		rec->records = os_realloc(rec->records, | ||||
| +					  sizeof(struct client_session_record) * rec->rec_nr); | ||||
| +		struct client_session_record *rp = &rec->records[rec->rec_nr - 1]; | ||||
| +		rp->type = CST_DISASSOC; | ||||
| +		rp->u.disassoc.session_id = rec->session_id; | ||||
| +		/* timestamp */ | ||||
| +		rp->timestamp = timestamp; | ||||
| +		/* frequency */ | ||||
| +		rp->u.disassoc.band = hapd->iface->freq; | ||||
| +		/* STA MAC */ | ||||
| +		sprintf(rp->u.disassoc.sta_mac, MACSTR, MAC2STR(sta->addr)); | ||||
| +		/* ssid */ | ||||
| +		rp->u.disassoc.ssid[0] = 0; | ||||
| +		printf_encode(rp->u.disassoc.ssid, sizeof(rp->u.disassoc.ssid), | ||||
| +			      bss_conf->ssid.ssid, bss_conf->ssid.ssid_len); | ||||
| +		/* rssi */ | ||||
| +		rp->u.disassoc.rssi = req->ssi_signal; | ||||
| +		/* internal_rc */ | ||||
| +		rp->u.disassoc.internal_rc = req->reason; | ||||
| +		hostapd_logger( | ||||
| +			hapd, NULL, HOSTAPD_MODULE_IEEE80211, | ||||
| +			HOSTAPD_LEVEL_DEBUG, | ||||
| +			"hostapd_ubus_handle_rt_event:HOSTAPD_UBUS_DISASSOC_REQ"); | ||||
| +		/* inc counter */ | ||||
| +		cached_events_nr++; | ||||
| +		break; | ||||
| +	} | ||||
| +	case HOSTAPD_UBUS_FDATA_REQ: { | ||||
| +		/* session id */ | ||||
| +		rec->session_id = session_id; | ||||
| +		rec->rec_nr++; | ||||
| +		rec->records = os_realloc(rec->records, | ||||
| +					  sizeof(struct client_session_record) * rec->rec_nr); | ||||
| +		struct client_session_record *rp = &rec->records[rec->rec_nr - 1]; | ||||
| +		rp->type = CST_FDATA; | ||||
| +		rp->u.fdata.session_id = rec->session_id; | ||||
| +		/* timestamp */ | ||||
| +		rp->timestamp = timestamp; | ||||
| +		/* STA MAC */ | ||||
| +		sprintf(rp->u.fdata.sta_mac, MACSTR, MAC2STR(sta->addr)); | ||||
| +		/* rx ts */ | ||||
| +		rp->u.fdata.rx_ts = ts; | ||||
| +		/* tx ts */ | ||||
| +		rp->u.fdata.tx_ts = ts; | ||||
| +		/* single event only */ | ||||
| +		sta->fdata = 1; | ||||
| +		hostapd_logger( | ||||
| +			hapd, NULL, HOSTAPD_MODULE_IEEE80211, | ||||
| +			HOSTAPD_LEVEL_DEBUG, | ||||
| +			"hostapd_ubus_handle_rt_event:HOSTAPD_UBUS_FDATA_REQ"); | ||||
| +		/* inc counter */ | ||||
| +		cached_events_nr++; | ||||
| +		break; | ||||
| +	} | ||||
| +	case HOSTAPD_UBUS_IP_REQ: { | ||||
| +		if(sta->first_ip) break; | ||||
| +		/* session id */ | ||||
| +		rec->session_id = session_id; | ||||
| +		rec->rec_nr++; | ||||
| +		rec->records = os_realloc(rec->records, | ||||
| +					  sizeof(struct client_session_record) * rec->rec_nr); | ||||
| +		struct client_session_record *rp = &rec->records[rec->rec_nr - 1]; | ||||
| +		rp->type = CST_IP; | ||||
| +		rp->u.ip.session_id = rec->session_id; | ||||
| +		/* timestamp */ | ||||
| +		rp->timestamp = timestamp; | ||||
| +		/* STA MAC */ | ||||
| +		sprintf(rp->u.ip.sta_mac, MACSTR, MAC2STR(sta->addr)); | ||||
| +		/* ip address */ | ||||
| +		snprintf(rp->u.ip.ip_addr, 20, "%u.%u.%u.%u", | ||||
| +			 (req->ipaddr >> 24) & 0xFF, | ||||
| +			 (req->ipaddr >> 16) & 0xFF, | ||||
| +			 (req->ipaddr >> 8) & 0xFF, | ||||
| +			 req->ipaddr & 0xFF); | ||||
| +		/* single event only */ | ||||
| +		sta->first_ip = 1; | ||||
| +		/* inc counter */ | ||||
| +		cached_events_nr++; | ||||
| +		break; | ||||
| +	} | ||||
| +	default: | ||||
| +		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, | ||||
| +			       HOSTAPD_LEVEL_DEBUG, | ||||
| +			       "hostapd_ubus_handle_rt_event:UNKNOWN"); | ||||
| +		new_rec = 0; | ||||
| +		break; | ||||
| +	} | ||||
| +	if (new_rec) { | ||||
| +		/* insert new client session */ | ||||
| +		rec->avl.key = &rec->session_id; | ||||
| +		sta->cl_session_id = session_id; | ||||
| +		if (avl_insert(&hapd->ubus.rt_events, &rec->avl)) | ||||
| +			return WLAN_STATUS_UNSPECIFIED_FAILURE; | ||||
| +	} | ||||
| + | ||||
| +	return WLAN_STATUS_SUCCESS; | ||||
| +} | ||||
| + | ||||
|  int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req) | ||||
|  { | ||||
|  	struct ubus_banned_client *ban; | ||||
| --- a/src/ap/ubus.h | ||||
| +++ b/src/ap/ubus.h | ||||
| @@ -12,6 +12,11 @@ enum hostapd_ubus_event_type { | ||||
|  	HOSTAPD_UBUS_PROBE_REQ, | ||||
|  	HOSTAPD_UBUS_AUTH_REQ, | ||||
|  	HOSTAPD_UBUS_ASSOC_REQ, | ||||
| +	HOSTAPD_UBUS_REASSOC_REQ, | ||||
| +	HOSTAPD_UBUS_DISASSOC_REQ, | ||||
| +	HOSTAPD_UBUS_DEAUTH_REQ, | ||||
| +	HOSTAPD_UBUS_FDATA_REQ, | ||||
| +	HOSTAPD_UBUS_IP_REQ, | ||||
|  	HOSTAPD_UBUS_TYPE_MAX | ||||
|  }; | ||||
|   | ||||
| @@ -19,8 +24,11 @@ struct hostapd_ubus_request { | ||||
|  	enum hostapd_ubus_event_type type; | ||||
|  	const struct ieee80211_mgmt *mgmt_frame; | ||||
|  	const struct ieee802_11_elems *elems; | ||||
| +	const struct sta_info *sta; | ||||
|  	int ssi_signal; /* dBm */ | ||||
| +	int reason; | ||||
|  	const u8 *addr; | ||||
| +	be32 ipaddr; | ||||
|  }; | ||||
|   | ||||
|  struct hostapd_iface; | ||||
| @@ -37,6 +45,80 @@ struct hostapd_ubus_bss { | ||||
|  	struct ubus_object obj; | ||||
|  	struct avl_tree banned; | ||||
|  	int notify_response; | ||||
| +	struct avl_tree rt_events; | ||||
| +}; | ||||
| + | ||||
| +enum client_sess_type { | ||||
| +	CST_ASSOC, | ||||
| +	CST_AUTH, | ||||
| +	CST_DISASSOC, | ||||
| +	CST_FDATA, | ||||
| +	CST_IP | ||||
| +}; | ||||
| + | ||||
| +struct client_assoc_event { | ||||
| +	unsigned char sta_mac[20]; | ||||
| +	uint64_t session_id; | ||||
| +	char ssid[SSID_MAX_LEN]; | ||||
| +	int band; | ||||
| +	int assoc_type; | ||||
| +	int status; | ||||
| +	int rssi; | ||||
| +	int internal_sc; | ||||
| +	uint8_t using11k; | ||||
| +	uint8_t using11r; | ||||
| +	uint8_t using11v; | ||||
| +}; | ||||
| + | ||||
| +struct client_disassoc_event { | ||||
| +	unsigned char sta_mac[20]; | ||||
| +	uint64_t session_id; | ||||
| +	char ssid[SSID_MAX_LEN]; | ||||
| +	int band; | ||||
| +	int assoc_type; | ||||
| +	int status; | ||||
| +	int rssi; | ||||
| +	int internal_rc; | ||||
| +}; | ||||
| + | ||||
| +struct client_auth_event { | ||||
| +	unsigned char sta_mac[20]; | ||||
| +	uint64_t session_id; | ||||
| +	char ssid[SSID_MAX_LEN]; | ||||
| +	int band; | ||||
| +	uint32_t auth_status; | ||||
| +}; | ||||
| + | ||||
| +struct client_fdata_event { | ||||
| +	unsigned char sta_mac[20]; | ||||
| +	uint64_t session_id; | ||||
| +	struct timespec rx_ts; | ||||
| +	struct timespec tx_ts; | ||||
| +}; | ||||
| + | ||||
| +struct client_ip_event { | ||||
| +	unsigned char sta_mac[20]; | ||||
| +	uint64_t session_id; | ||||
| +	unsigned char ip_addr[16]; | ||||
| +}; | ||||
| + | ||||
| +struct client_session_record { | ||||
| +	int type; | ||||
| +	uint64_t timestamp; | ||||
| +	union { | ||||
| +		struct client_assoc_event assoc; | ||||
| +		struct client_disassoc_event disassoc; | ||||
| +		struct client_auth_event auth; | ||||
| +		struct client_fdata_event fdata; | ||||
| +		struct client_ip_event ip; | ||||
| +	} u; | ||||
| +}; | ||||
| + | ||||
| +struct hostapd_event_avl_rec { | ||||
| +	uint64_t session_id; | ||||
| +	struct client_session_record *records; | ||||
| +	size_t rec_nr; | ||||
| +	struct avl_node avl; | ||||
|  }; | ||||
|   | ||||
|  void hostapd_ubus_add_iface(struct hostapd_iface *iface); | ||||
| @@ -45,6 +127,7 @@ void hostapd_ubus_add_bss(struct hostapd | ||||
|  void hostapd_ubus_free_bss(struct hostapd_data *hapd); | ||||
|   | ||||
|  int hostapd_ubus_handle_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req); | ||||
| +int hostapd_ubus_handle_rt_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req); | ||||
|  void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac); | ||||
|  void hostapd_ubus_notify_beacon_report(struct hostapd_data *hapd, | ||||
|  				       const u8 *addr, u8 token, u8 rep_mode, | ||||
| @@ -78,6 +161,11 @@ static inline int hostapd_ubus_handle_ev | ||||
|  { | ||||
|  	return 0; | ||||
|  } | ||||
| + | ||||
| +static inline int hostapd_ubus_handle_rt_event(struct hostapd_data *hapd, struct hostapd_ubus_request *req) | ||||
| +{ | ||||
| +	return 0; | ||||
| +} | ||||
|   | ||||
|  static inline void hostapd_ubus_notify(struct hostapd_data *hapd, const char *type, const u8 *mac) | ||||
|  { | ||||
| --- a/src/ap/hostapd.c | ||||
| +++ b/src/ap/hostapd.c | ||||
| @@ -1406,19 +1406,22 @@ static int hostapd_setup_bss(struct host | ||||
|  				   "Generic snooping infrastructure initialization failed"); | ||||
|  			return -1; | ||||
|  		} | ||||
| - | ||||
| -		if (dhcp_snoop_init(hapd)) { | ||||
| -			wpa_printf(MSG_ERROR, | ||||
| -				   "DHCP snooping initialization failed"); | ||||
| -			return -1; | ||||
| -		} | ||||
| - | ||||
|  		if (ndisc_snoop_init(hapd)) { | ||||
|  			wpa_printf(MSG_ERROR, | ||||
|  				   "Neighbor Discovery snooping initialization failed"); | ||||
|  			return -1; | ||||
|  		} | ||||
|  	} | ||||
| +	if (dhcp_snoop_init(hapd)) { | ||||
| +		wpa_printf(MSG_ERROR, | ||||
| +			   "DHCP snooping initialization failed"); | ||||
| +		hostapd_logger( | ||||
| +			hapd, NULL, HOSTAPD_MODULE_IEEE80211, | ||||
| +			HOSTAPD_LEVEL_DEBUG, | ||||
| +			"dfranusic:DHCP snooping initialization failed"); | ||||
| + | ||||
| +		return -1; | ||||
| +	} | ||||
|   | ||||
|  	if (!hostapd_drv_none(hapd) && vlan_init(hapd)) { | ||||
|  		wpa_printf(MSG_ERROR, "VLAN initialization failed."); | ||||
| --- a/src/ap/dhcp_snoop.c | ||||
| +++ b/src/ap/dhcp_snoop.c | ||||
| @@ -40,6 +40,7 @@ static void handle_dhcp(void *ctx, const | ||||
|  	int res, msgtype = 0, prefixlen = 32; | ||||
|  	u32 subnet_mask = 0; | ||||
|  	u16 ip_len; | ||||
| +	int ubus_resp; | ||||
|   | ||||
|  	exten_len = len - ETH_HLEN - (sizeof(*b) - sizeof(b->exten)); | ||||
|  	if (exten_len < 4) | ||||
| @@ -112,6 +113,19 @@ static void handle_dhcp(void *ctx, const | ||||
|  			   ipaddr_str(be_to_host32(b->your_ip)), | ||||
|  			   prefixlen); | ||||
|   | ||||
| +			struct hostapd_ubus_request req = { | ||||
| +				.type = HOSTAPD_UBUS_IP_REQ, | ||||
| +				.sta = sta, | ||||
| +				.ipaddr = be_to_host32(b->your_ip) | ||||
| +			}; | ||||
| +			ubus_resp = hostapd_ubus_handle_rt_event(hapd, &req); | ||||
| +			if (ubus_resp) { | ||||
| +				hostapd_logger( | ||||
| +					hapd, NULL, HOSTAPD_MODULE_IEEE80211, | ||||
| +					HOSTAPD_LEVEL_DEBUG, | ||||
| +					"hostapd_ubus_handle_rt_event: ERROR"); | ||||
| +			} | ||||
| + | ||||
|  		if (sta->ipaddr == b->your_ip) | ||||
|  			return; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user