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
2021-03-08 23:53:09 -08:00
committed by Rick Sommerville
parent 9d13fc7330
commit ca7b766171

View 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;