ap: Pass "ops" struct to ap_start()

Pass the event callback function pointer in a "struct ap_ops" instead of
as individual ap_start() argument to make adding new callbacks easier.
This commit is contained in:
Andrew Zaborowski 2020-09-16 11:17:49 +02:00 committed by Denis Kenzior
parent 766257c5d6
commit 1f68696578
2 changed files with 42 additions and 32 deletions

View File

@ -53,7 +53,7 @@
struct ap_state { struct ap_state {
struct netdev *netdev; struct netdev *netdev;
struct l_genl_family *nl80211; struct l_genl_family *nl80211;
ap_event_func_t event_func; const struct ap_ops *ops;
ap_stopped_func_t stopped_func; ap_stopped_func_t stopped_func;
void *user_data; void *user_data;
struct ap_config *config; struct ap_config *config;
@ -211,7 +211,7 @@ static void ap_del_station(struct sta_state *sta, uint16_t reason,
sta->associated = false; sta->associated = false;
if (sta->rsna) { if (sta->rsna) {
if (ap->event_func) { if (ap->ops->handle_event) {
memset(&event_data, 0, sizeof(event_data)); memset(&event_data, 0, sizeof(event_data));
event_data.mac = sta->addr; event_data.mac = sta->addr;
event_data.reason = reason; event_data.reason = reason;
@ -229,8 +229,8 @@ static void ap_del_station(struct sta_state *sta, uint16_t reason,
ap_stop_handshake(sta); ap_stop_handshake(sta);
if (send_event) if (send_event)
ap->event_func(AP_EVENT_STATION_REMOVED, &event_data, ap->ops->handle_event(AP_EVENT_STATION_REMOVED, &event_data,
ap->user_data); ap->user_data);
} }
static bool ap_sta_match_addr(const void *a, const void *b) static bool ap_sta_match_addr(const void *a, const void *b)
@ -270,12 +270,12 @@ static void ap_new_rsna(struct sta_state *sta)
sta->rsna = true; sta->rsna = true;
if (ap->event_func) { if (ap->ops->handle_event) {
struct ap_event_station_added_data event_data = {}; struct ap_event_station_added_data event_data = {};
event_data.mac = sta->addr; event_data.mac = sta->addr;
event_data.rsn_ie = sta->assoc_rsne; event_data.rsn_ie = sta->assoc_rsne;
ap->event_func(AP_EVENT_STATION_ADDED, &event_data, ap->ops->handle_event(AP_EVENT_STATION_ADDED, &event_data,
ap->user_data); ap->user_data);
} }
} }
@ -309,11 +309,11 @@ static void ap_drop_rsna(struct sta_state *sta)
ap_stop_handshake(sta); ap_stop_handshake(sta);
if (ap->event_func) { if (ap->ops->handle_event) {
struct ap_event_station_removed_data event_data = {}; struct ap_event_station_removed_data event_data = {};
event_data.mac = sta->addr; event_data.mac = sta->addr;
ap->event_func(AP_EVENT_STATION_REMOVED, &event_data, ap->ops->handle_event(AP_EVENT_STATION_REMOVED, &event_data,
ap->user_data); ap->user_data);
} }
} }
@ -544,7 +544,7 @@ static void ap_wsc_exit_pbc(struct ap_state *ap)
ap->wsc_dpid = 0; ap->wsc_dpid = 0;
ap_update_beacon(ap); ap_update_beacon(ap);
ap->event_func(AP_EVENT_PBC_MODE_EXIT, NULL, ap->user_data); ap->ops->handle_event(AP_EVENT_PBC_MODE_EXIT, NULL, ap->user_data);
} }
static uint32_t ap_send_mgmt_frame(struct ap_state *ap, static uint32_t ap_send_mgmt_frame(struct ap_state *ap,
@ -751,8 +751,9 @@ static void ap_wsc_handshake_event(struct handshake_state *hs,
&expiry_data); &expiry_data);
event_data.mac = sta->addr; event_data.mac = sta->addr;
sta->ap->event_func(AP_EVENT_REGISTRATION_SUCCESS, &event_data, sta->ap->ops->handle_event(AP_EVENT_REGISTRATION_SUCCESS,
sta->ap->user_data); &event_data,
sta->ap->user_data);
break; break;
default: default:
break; break;
@ -1330,8 +1331,8 @@ static void ap_assoc_reassoc(struct sta_state *sta, bool reassoc,
sta->wsc_v2 = wsc_req.version2; sta->wsc_v2 = wsc_req.version2;
event_data.mac = sta->addr; event_data.mac = sta->addr;
ap->event_func(AP_EVENT_REGISTRATION_START, &event_data, ap->ops->handle_event(AP_EVENT_REGISTRATION_START, &event_data,
ap->user_data); ap->user_data);
/* /*
* Since we're starting the PBC Registration Protocol * Since we're starting the PBC Registration Protocol
@ -1914,7 +1915,8 @@ static void ap_start_cb(struct l_genl_msg *msg, void *user_data)
if (l_genl_msg_get_error(msg) < 0) { if (l_genl_msg_get_error(msg) < 0) {
l_error("START_AP failed: %i", l_genl_msg_get_error(msg)); l_error("START_AP failed: %i", l_genl_msg_get_error(msg));
ap->event_func(AP_EVENT_START_FAILED, NULL, ap->user_data); ap->ops->handle_event(AP_EVENT_START_FAILED, NULL,
ap->user_data);
ap_reset(ap); ap_reset(ap);
l_genl_family_free(ap->nl80211); l_genl_family_free(ap->nl80211);
l_free(ap); l_free(ap);
@ -1922,7 +1924,7 @@ static void ap_start_cb(struct l_genl_msg *msg, void *user_data)
} }
ap->started = true; ap->started = true;
ap->event_func(AP_EVENT_STARTED, NULL, ap->user_data); ap->ops->handle_event(AP_EVENT_STARTED, NULL, ap->user_data);
} }
static struct l_genl_msg *ap_build_cmd_start_ap(struct ap_state *ap) static struct l_genl_msg *ap_build_cmd_start_ap(struct ap_state *ap)
@ -2009,11 +2011,12 @@ static void ap_mlme_notify(struct l_genl_msg *msg, void *user_data)
l_genl_family_cancel(ap->nl80211, l_genl_family_cancel(ap->nl80211,
ap->start_stop_cmd_id); ap->start_stop_cmd_id);
ap->start_stop_cmd_id = 0; ap->start_stop_cmd_id = 0;
ap->event_func(AP_EVENT_START_FAILED, NULL, ap->ops->handle_event(AP_EVENT_START_FAILED, NULL,
ap->user_data); ap->user_data);
} else if (ap->started) { } else if (ap->started) {
ap->started = false; ap->started = false;
ap->event_func(AP_EVENT_STOPPING, NULL, ap->user_data); ap->ops->handle_event(AP_EVENT_STOPPING, NULL,
ap->user_data);
} }
ap_reset(ap); ap_reset(ap);
@ -2026,17 +2029,17 @@ static void ap_mlme_notify(struct l_genl_msg *msg, void *user_data)
/* /*
* Start a simple independent WPA2 AP on given netdev. * Start a simple independent WPA2 AP on given netdev.
* *
* @event_func is required and must react to AP_EVENT_START_FAILED * @ops.handle_event is required and must react to AP_EVENT_START_FAILED
* and AP_EVENT_STOPPING by forgetting the ap_state struct, which * and AP_EVENT_STOPPING by forgetting the ap_state struct, which is
* is going to be freed automatically. * going to be freed automatically.
* In the @config struct only .ssid and .psk need to be non-NUL, * In the @config struct only .ssid and .psk need to be non-NULL,
* other fields are optional. If @ap_start succeeds, the returned * other fields are optional. If @ap_start succeeds, the returned
* ap_state takes ownership of @config and the caller shouldn't * ap_state takes ownership of @config and the caller shouldn't
* free it or any of the memory pointed to by its members (they * free it or any of the memory pointed to by its members (they
* also can't be static). * also can't be static).
*/ */
struct ap_state *ap_start(struct netdev *netdev, struct ap_config *config, struct ap_state *ap_start(struct netdev *netdev, struct ap_config *config,
ap_event_func_t event_func, void *user_data) const struct ap_ops *ops, void *user_data)
{ {
struct ap_state *ap; struct ap_state *ap;
struct wiphy *wiphy = netdev_get_wiphy(netdev); struct wiphy *wiphy = netdev_get_wiphy(netdev);
@ -2047,7 +2050,7 @@ struct ap_state *ap_start(struct netdev *netdev, struct ap_config *config,
ap->nl80211 = l_genl_family_new(iwd_get_genl(), NL80211_GENL_NAME); ap->nl80211 = l_genl_family_new(iwd_get_genl(), NL80211_GENL_NAME);
ap->config = config; ap->config = config;
ap->netdev = netdev; ap->netdev = netdev;
ap->event_func = event_func; ap->ops = ops;
ap->user_data = user_data; ap->user_data = user_data;
if (!config->channel) if (!config->channel)
@ -2178,7 +2181,7 @@ static struct l_genl_msg *ap_build_cmd_stop_ap(struct ap_state *ap)
/* /*
* Schedule the running @ap to be stopped and freed. The original * Schedule the running @ap to be stopped and freed. The original
* event_func and user_data are forgotten and a new callback can be * ops and user_data are forgotten and a new callback can be
* provided if the caller needs to know when the interface becomes * provided if the caller needs to know when the interface becomes
* free, for example for a new ap_start call. * free, for example for a new ap_start call.
* *
@ -2195,7 +2198,7 @@ void ap_shutdown(struct ap_state *ap, ap_stopped_func_t stopped_func,
if (ap->started) { if (ap->started) {
ap->started = false; ap->started = false;
ap->event_func(AP_EVENT_STOPPING, NULL, ap->user_data); ap->ops->handle_event(AP_EVENT_STOPPING, NULL, ap->user_data);
} }
ap_reset(ap); ap_reset(ap);
@ -2365,6 +2368,10 @@ static void ap_if_event_func(enum ap_event_type type, const void *event_data,
} }
} }
static const struct ap_ops ap_dbus_ops = {
.handle_event = ap_if_event_func,
};
static struct l_dbus_message *ap_dbus_start(struct l_dbus *dbus, static struct l_dbus_message *ap_dbus_start(struct l_dbus *dbus,
struct l_dbus_message *message, void *user_data) struct l_dbus_message *message, void *user_data)
{ {
@ -2385,7 +2392,7 @@ static struct l_dbus_message *ap_dbus_start(struct l_dbus *dbus,
config->ssid = l_strdup(ssid); config->ssid = l_strdup(ssid);
config->psk = l_strdup(wpa2_psk); config->psk = l_strdup(wpa2_psk);
ap_if->ap = ap_start(ap_if->netdev, config, ap_if_event_func, ap_if); ap_if->ap = ap_start(ap_if->netdev, config, &ap_dbus_ops, ap_if);
if (!ap_if->ap) { if (!ap_if->ap) {
ap_config_free(config); ap_config_free(config);
return dbus_error_invalid_args(message); return dbus_error_invalid_args(message);

View File

@ -52,8 +52,6 @@ struct ap_event_registration_success_data {
const uint8_t *mac; const uint8_t *mac;
}; };
typedef void (*ap_event_func_t)(enum ap_event_type type, const void *event_data,
void *user_data);
typedef void (*ap_stopped_func_t)(void *user_data); typedef void (*ap_stopped_func_t)(void *user_data);
struct ap_config { struct ap_config {
@ -67,10 +65,15 @@ struct ap_config {
bool no_cck_rates : 1; bool no_cck_rates : 1;
}; };
struct ap_ops {
void (*handle_event)(enum ap_event_type type, const void *event_data,
void *user_data);
};
void ap_config_free(struct ap_config *config); void ap_config_free(struct ap_config *config);
struct ap_state *ap_start(struct netdev *netdev, struct ap_config *config, struct ap_state *ap_start(struct netdev *netdev, struct ap_config *config,
ap_event_func_t event_func, void *user_data); const struct ap_ops *ops, void *user_data);
void ap_shutdown(struct ap_state *ap, ap_stopped_func_t stopped_func, void ap_shutdown(struct ap_state *ap, ap_stopped_func_t stopped_func,
void *user_data); void *user_data);
void ap_free(struct ap_state *ap); void ap_free(struct ap_state *ap);