在WifiService的startSoftAp流程中我们分析了HAL层以上的流程,最终framework层会调用IHostapd的addAccessPoint方法,IHostapd为AIDL接口,由hostapd HAL的addAccessPoint实现,我们继续分析hostapd HAL流程:
wpa_supplicant/hostapd/hostapd.cpp
::ndk::ScopedAStatus Hostapd::addAccessPoint(
const IfaceParams& iface_params, const NetworkParams& nw_params)
{
return addAccessPointInternal(iface_params, nw_params);
}
::ndk::ScopedAStatus Hostapd::addAccessPointInternal(
const IfaceParams& iface_params,
const NetworkParams& nw_params)
{
int channelParamsSize = iface_params.channelParams.size();
if (channelParamsSize == 1) {
// Single AP
wpa_printf(MSG_INFO, "AddSingleAccessPoint, iface=%s",
iface_params.name.c_str());
return addSingleAccessPoint(iface_params, iface_params.channelParams[0],
nw_params, "", ""); //添加单个接入点
} else if (channelParamsSize == 2) {
// Concurrent APs
wpa_printf(MSG_INFO, "AddDualAccessPoint, iface=%s",
iface_params.name.c_str());
return addConcurrentAccessPoints(iface_params, nw_params); //添加并发接入点
}
return createStatus(HostapdStatusCode::FAILURE_ARGS_INVALID);
}
addAccessPoint会调用addAccessPointInternal,addAccessPointInternal根据channelParamsSize调用addSingleAccessPoint或addConcurrentAccessPoints来添加接入点,我们来分析addSingleAccessPoint的情况:
wpa_supplicant/hostapd/hostapd.cpp
::ndk::ScopedAStatus Hostapd::addSingleAccessPoint(
const IfaceParams& iface_params,
const ChannelParams& channelParams,
const NetworkParams& nw_params,
const std::string br_name,
const std::string owe_transition_ifname)
{
if (hostapd_get_iface(interfaces_, iface_params.name.c_str())) {
wpa_printf(
MSG_ERROR, "Interface %s already present",
iface_params.name.c_str());
return createStatus(HostapdStatusCode::FAILURE_IFACE_EXISTS);
}
const auto conf_params = CreateHostapdConfig(iface_params, channelParams, nw_params,
br_name, owe_transition_ifname);
if (conf_params.empty()) {
wpa_printf(MSG_ERROR, "Failed to create config params");
return createStatus(HostapdStatusCode::FAILURE_ARGS_INVALID);
}
const auto conf_file_path =
WriteHostapdConfig(iface_params.name, conf_params);
if (conf_file_path.empty()) {
wpa_printf(MSG_ERROR, "Failed to write config file");
return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
}
std::string add_iface_param_str = StringPrintf(
"%s config=%s", iface_params.name.c_str(),
conf_file_path.c_str());
std::vector<char> add_iface_param_vec(
add_iface_param_str.begin(), add_iface_param_str.end() + 1);
if (hostapd_add_iface(interfaces_, add_iface_param_vec.data()) < 0) {
wpa_printf(
MSG_ERROR, "Adding interface %s failed",
add_iface_param_str.c_str());
return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
}
struct hostapd_data* iface_hapd =
hostapd_get_iface(interfaces_, iface_params.name.c_str());
WPA_ASSERT(iface_hapd != nullptr && iface_hapd->iface != nullptr);
// Register the setup complete callbacks
on_setup_complete_internal_callback =
[this](struct hostapd_data* iface_hapd) {
wpa_printf(
MSG_INFO, "AP interface setup completed - state %s",
hostapd_state_text(iface_hapd->iface->state));
if (iface_hapd->iface->state == HAPD_IFACE_DISABLED) {
// Invoke the failure callback on all registered
// clients.
for (const auto& callback : callbacks_) {
callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
iface_hapd->conf->bridge : iface_hapd->conf->iface,
iface_hapd->conf->iface);
}
}
};
// Register for new client connect/disconnect indication.
on_sta_authorized_internal_callback =
[this](struct hostapd_data* iface_hapd, const u8 *mac_addr,
int authorized, const u8 *p2p_dev_addr) {
wpa_printf(MSG_DEBUG, "notify client " MACSTR " %s",
MAC2STR(mac_addr),
(authorized) ? "Connected" : "Disconnected");
ClientInfo info;
info.ifaceName = strlen(iface_hapd->conf->bridge) > 0 ?
iface_hapd->conf->bridge : iface_hapd->conf->iface;
info.apIfaceInstance = iface_hapd->conf->iface;
info.clientAddress.assign(mac_addr, mac_addr + ETH_ALEN);
info.isConnected = authorized;
for (const auto &callback : callbacks_) {
callback->onConnectedClientsChanged(info);
}
};
// Register for wpa_event which used to get channel switch event
on_wpa_msg_internal_callback =
[this](struct hostapd_data* iface_hapd, int level,
enum wpa_msg_type type, const char *txt,
size_t len) {
wpa_printf(MSG_DEBUG, "Receive wpa msg : %s", txt);
if (os_strncmp(txt, AP_EVENT_ENABLED,
strlen(AP_EVENT_ENABLED)) == 0 ||
os_strncmp(txt, WPA_EVENT_CHANNEL_SWITCH,
strlen(WPA_EVENT_CHANNEL_SWITCH)) == 0) {
ApInfo info;
info.ifaceName = strlen(iface_hapd->conf->bridge) > 0 ?
iface_hapd->conf->bridge : iface_hapd->conf->iface,
info.apIfaceInstance = iface_hapd->conf->iface;
info.freqMhz = iface_hapd->iface->freq;
info.channelBandwidth = getChannelBandwidth(iface_hapd->iconf);
info.generation = getGeneration(iface_hapd->iface->current_mode);
info.apIfaceInstanceMacAddress.assign(iface_hapd->own_addr,
iface_hapd->own_addr + ETH_ALEN);
for (const auto &callback : callbacks_) {
callback->onApInstanceInfoChanged(info);
}
} else if (os_strncmp(txt, AP_EVENT_DISABLED, strlen(AP_EVENT_DISABLED)) == 0
|| os_strncmp(txt, INTERFACE_DISABLED, strlen(INTERFACE_DISABLED)) == 0)
{
// Invoke the failure callback on all registered clients.
for (const auto& callback : callbacks_) {
callback->onFailure(strlen(iface_hapd->conf->bridge) > 0 ?
iface_hapd->conf->bridge : iface_hapd->conf->iface,
iface_hapd->conf->iface);
}
}
};
// Setup callback
iface_hapd->setup_complete_cb = onAsyncSetupCompleteCb;
iface_hapd->setup_complete_cb_ctx = iface_hapd;
iface_hapd->sta_authorized_cb = onAsyncStaAuthorizedCb;
iface_hapd->sta_authorized_cb_ctx = iface_hapd;
wpa_msg_register_cb(onAsyncWpaEventCb);
if (hostapd_enable_iface(iface_hapd->iface) < 0) {
wpa_printf(
MSG_ERROR, "Enabling interface %s failed",
iface_params.name.c_str());
return createStatus(HostapdStatusCode::FAILURE_UNKNOWN);
}
return ndk::ScopedAStatus::ok();
}
这个函数主要调用如下几个函数:
hostapd_get_iface:获取接口
hostapd_add_iface:增加接口
hostapd_enable_iface:使能接口 其中hostapd_enable_iface的代码如下:
wpa_supplicant/hostapd/hostapd.cpp
int hostapd_enable_iface(struct hostapd_iface *hapd_iface)
{
size_t j;
if (!hapd_iface)
return -1;
if (hapd_iface->enable_iface_cb)
return hapd_iface->enable_iface_cb(hapd_iface); //调用hapd_iface的enable_iface_cb
if (hapd_iface->bss[0]->drv_priv != NULL) {
wpa_printf(MSG_ERROR, "Interface %s already enabled",
hapd_iface->conf->bss[0]->iface);
return -1;
}
wpa_printf(MSG_DEBUG, "Enable interface %s",
hapd_iface->conf->bss[0]->iface);
for (j = 0; j < hapd_iface->num_bss; j++)
hostapd_set_security_params(hapd_iface->conf->bss[j], 1);
if (hostapd_config_check(hapd_iface->conf, 1) < 0) {
wpa_printf(MSG_INFO, "Invalid configuration - cannot enable");
return -1;
}
if (hapd_iface->interfaces == NULL ||
hapd_iface->interfaces->driver_init == NULL ||
hapd_iface->interfaces->driver_init(hapd_iface))
return -1;
if (hostapd_setup_interface(hapd_iface)) {
hostapd_deinit_driver(hapd_iface->bss[0]->driver,
hapd_iface->bss[0]->drv_priv,
hapd_iface);
return -1;
}
return 0;
}
调用hapd_iface的enable_iface_cb函数,hapd_iface->enable_iface_cb在初始化赋值为wpa_supplicant_mesh_enable_iface_cb,因此会调用wpa_supplicant_mesh_enable_iface_cb函数:
wpa_supplicant_8/wpa_supplicant/mesh.c
static int wpa_supplicant_mesh_enable_iface_cb(struct hostapd_iface *ifmsh)
{
struct wpa_supplicant *wpa_s = ifmsh->owner;
struct hostapd_data *bss;
ifmsh->mconf = mesh_config_create(wpa_s, wpa_s->current_ssid);
bss = ifmsh->bss[0];
bss->msg_ctx = wpa_s;
os_memcpy(bss->own_addr, wpa_s->own_addr, ETH_ALEN);
bss->driver = wpa_s->driver;
bss->drv_priv = wpa_s->drv_priv;
bss->iface = ifmsh;
bss->mesh_sta_free_cb = mesh_mpm_free_sta;
bss->setup_complete_cb = wpas_mesh_complete_cb;
bss->setup_complete_cb_ctx = wpa_s;
bss->conf->start_disabled = 1;
bss->conf->mesh = MESH_ENABLED;
bss->conf->ap_max_inactivity = wpa_s->conf->mesh_max_inactivity;
if (wpa_drv_init_mesh(wpa_s)) {
wpa_msg(wpa_s, MSG_ERROR, "Failed to init mesh in driver");
return -1;
}
if (hostapd_setup_interface(ifmsh)) { //调用hostapd_setup_interface
wpa_printf(MSG_ERROR,
"Failed to initialize hostapd interface for mesh");
return -1;
}
return 0;
}
调用hostapd_setup_interface函数:
wpa_supplicant/hostapd/hostapd.cpp
int hostapd_setup_interface(struct hostapd_iface *iface)
{
int ret;
if (!iface->conf)
return -1;
ret = setup_interface(iface);
if (ret) {
wpa_printf(MSG_ERROR, "%s: Unable to setup interface.",
iface->conf->bss[0]->iface);
return -1;
}
return 0;
}
调用setup_interface函数:
wpa_supplicant/hostapd/hostapd.cpp
static int setup_interface(struct hostapd_iface *iface)
{
struct hostapd_data *hapd = iface->bss[0];
size_t i;
/*
* It is possible that setup_interface() is called after the interface
* was disabled etc., in which case driver_ap_teardown is possibly set
* to 1. Clear it here so any other key/station deletion, which is not
* part of a teardown flow, would also call the relevant driver
* callbacks.
*/
iface->driver_ap_teardown = 0;
if (!iface->phy[0]) {
const char *phy = hostapd_drv_get_radio_name(hapd);
if (phy) {
wpa_printf(MSG_DEBUG, "phy: %s", phy);
os_strlcpy(iface->phy, phy, sizeof(iface->phy));
}
}
/*
* Make sure that all BSSes get configured with a pointer to the same
* driver interface.
*/
for (i = 1; i < iface->num_bss; i++) {
iface->bss[i]->driver = hapd->driver;
iface->bss[i]->drv_priv = hapd->drv_priv;
}
if (hostapd_validate_bssid_configuration(iface))
return -1;
/*
* Initialize control interfaces early to allow external monitoring of
* channel setup operations that may take considerable amount of time
* especially for DFS cases.
*/
if (start_ctrl_iface(iface))
return -1;
if (hapd->iconf->country[0] && hapd->iconf->country[1]) {
char country[4], previous_country[4];
hostapd_set_state(iface, HAPD_IFACE_COUNTRY_UPDATE);
if (hostapd_get_country(hapd, previous_country) < 0)
previous_country[0] = '\0';
os_memcpy(country, hapd->iconf->country, 3);
country[3] = '\0';
if (hostapd_set_country(hapd, country) < 0) {
wpa_printf(MSG_ERROR, "Failed to set country code");
return -1;
}
wpa_printf(MSG_DEBUG, "Previous country code %s, new country code %s",
previous_country, country);
if (os_strncmp(previous_country, country, 2) != 0) {
wpa_printf(MSG_DEBUG, "Continue interface setup after channel list update");
iface->wait_channel_update = 1;
eloop_register_timeout(5, 0,
channel_list_update_timeout,
iface, NULL);
return 0;
}
}
return setup_interface2(iface); //调用setup_interface2
}
调用setup_interface2函数:
wpa_supplicant/hostapd/hostapd.cpp
static int setup_interface2(struct hostapd_iface *iface)
{
iface->wait_channel_update = 0;
if (hostapd_get_hw_features(iface)) {
/* Not all drivers support this yet, so continue without hw
* feature data. */
} else {
int ret;
ret = configured_fixed_chan_to_freq(iface);
if (ret < 0)
goto fail;
if (iface->conf->op_class) {
int ch_width;
ch_width = op_class_to_ch_width(iface->conf->op_class);
hostapd_set_oper_chwidth(iface->conf, ch_width);
hostapd_set_6ghz_sec_chan(iface);
}
ret = hostapd_select_hw_mode(iface);
if (ret < 0) {
wpa_printf(MSG_ERROR, "Could not select hw_mode and "
"channel. (%d)", ret);
goto fail;
}
if (ret == 1) {
wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback (ACS)");
return 0;
}
ret = hostapd_check_edmg_capab(iface);
if (ret < 0)
goto fail;
ret = hostapd_check_he_6ghz_capab(iface);
if (ret < 0)
goto fail;
ret = hostapd_check_ht_capab(iface);
if (ret < 0)
goto fail;
if (ret == 1) {
wpa_printf(MSG_DEBUG, "Interface initialization will "
"be completed in a callback");
return 0;
}
if (iface->conf->ieee80211h)
wpa_printf(MSG_DEBUG, "DFS support is enabled");
}
return hostapd_setup_interface_complete(iface, 0); //调用hostapd_setup_interface_complete函数
fail:
hostapd_set_state(iface, HAPD_IFACE_DISABLED);
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
if (iface->interfaces && iface->interfaces->terminate_on_error)
eloop_terminate();
return -1;
}
在setup_interface2中会检查一些参数,然后调用hostapd_setup_interface_complete函数:
wpa_supplicant/hostapd/hostapd.cpp
int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err)
{
struct hapd_interfaces *interfaces = iface->interfaces;
struct hostapd_data *hapd = iface->bss[0];
unsigned int i;
int not_ready_in_sync_ifaces = 0;
if (!iface->need_to_start_in_sync)
return hostapd_setup_interface_complete_sync(iface, err);
if (err) {
wpa_printf(MSG_ERROR, "Interface initialization failed");
hostapd_set_state(iface, HAPD_IFACE_DISABLED);
iface->need_to_start_in_sync = 0;
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
if (interfaces && interfaces->terminate_on_error)
eloop_terminate();
return -1;
}
if (iface->ready_to_start_in_sync) {
/* Already in ready and waiting. should never happpen */
return 0;
}
for (i = 0; i < interfaces->count; i++) {
if (interfaces->iface[i]->need_to_start_in_sync &&
!interfaces->iface[i]->ready_to_start_in_sync)
not_ready_in_sync_ifaces++;
}
/*
* Check if this is the last interface, if yes then start all the other
* waiting interfaces. If not, add this interface to the waiting list.
*/
if (not_ready_in_sync_ifaces > 1 && iface->state == HAPD_IFACE_DFS) {
/*
* If this interface went through CAC, do not synchronize, just
* start immediately.
*/
iface->need_to_start_in_sync = 0;
wpa_printf(MSG_INFO,
"%s: Finished CAC - bypass sync and start interface",
iface->bss[0]->conf->iface);
return hostapd_setup_interface_complete_sync(iface, err);
}
if (not_ready_in_sync_ifaces > 1) {
/* need to wait as there are other interfaces still coming up */
iface->ready_to_start_in_sync = 1;
wpa_printf(MSG_INFO,
"%s: Interface waiting to sync with other interfaces",
iface->bss[0]->conf->iface);
return 0;
}
wpa_printf(MSG_INFO,
"%s: Last interface to sync - starting all interfaces",
iface->bss[0]->conf->iface);
iface->need_to_start_in_sync = 0;
hostapd_setup_interface_complete_sync(iface, err);
for (i = 0; i < interfaces->count; i++) {
if (interfaces->iface[i]->need_to_start_in_sync &&
interfaces->iface[i]->ready_to_start_in_sync) {
hostapd_setup_interface_complete_sync(
interfaces->iface[i], 0);
/* Only once the interfaces are sync started */
interfaces->iface[i]->need_to_start_in_sync = 0;
}
}
return 0;
}
调用hostapd_setup_interface_complete_sync函数:
wpa_supplicant/hostapd/hostapd.cpp
static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface,
int err)
{
struct hostapd_data *hapd = iface->bss[0];
size_t j;
u8 *prev_addr;
int delay_apply_cfg = 0;
int res_dfs_offload = 0;
if (err)
goto fail;
wpa_printf(MSG_DEBUG, "Completing interface initialization");
if (iface->freq) {
#ifdef NEED_AP_MLME
int res;
#endif /* NEED_AP_MLME */
wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d "
"Frequency: %d MHz",
hostapd_hw_mode_txt(iface->conf->hw_mode),
iface->conf->channel, iface->freq);
#ifdef NEED_AP_MLME
/* Handle DFS only if it is not offloaded to the driver */
if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) {
/* Check DFS */
res = hostapd_handle_dfs(iface);
if (res <= 0) {
if (res < 0)
goto fail;
return res;
}
} else {
/* If DFS is offloaded to the driver */
res_dfs_offload = hostapd_handle_dfs_offload(iface);
if (res_dfs_offload <= 0) {
if (res_dfs_offload < 0)
goto fail;
} else {
wpa_printf(MSG_DEBUG,
"Proceed with AP/channel setup");
/*
* If this is a DFS channel, move to completing
* AP setup.
*/
if (res_dfs_offload == 1)
goto dfs_offload;
/* Otherwise fall through. */
}
}
#endif /* NEED_AP_MLME */
#ifdef CONFIG_MESH
if (iface->mconf != NULL) {
wpa_printf(MSG_DEBUG,
"%s: Mesh configuration will be applied while joining the mesh network",
iface->bss[0]->conf->iface);
delay_apply_cfg = 1;
}
#endif /* CONFIG_MESH */
if (!delay_apply_cfg &&
hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq,
hapd->iconf->channel,
hapd->iconf->enable_edmg,
hapd->iconf->edmg_channel,
hapd->iconf->ieee80211n,
hapd->iconf->ieee80211ac,
hapd->iconf->ieee80211ax,
hapd->iconf->secondary_channel,
hostapd_get_oper_chwidth(hapd->iconf),
hostapd_get_oper_centr_freq_seg0_idx(
hapd->iconf),
hostapd_get_oper_centr_freq_seg1_idx(
hapd->iconf))) {
wpa_printf(MSG_ERROR, "Could not set channel for "
"kernel driver");
goto fail;
}
}
if (iface->current_mode) {
if (hostapd_prepare_rates(iface, iface->current_mode)) {
wpa_printf(MSG_ERROR, "Failed to prepare rates "
"table.");
hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
HOSTAPD_LEVEL_WARNING,
"Failed to prepare rates table.");
goto fail;
}
}
if (hapd->iconf->rts_threshold >= -1 &&
hostapd_set_rts(hapd, hapd->iconf->rts_threshold) &&
hapd->iconf->rts_threshold >= -1) {
wpa_printf(MSG_ERROR, "Could not set RTS threshold for "
"kernel driver");
goto fail;
}
if (hapd->iconf->fragm_threshold >= -1 &&
hostapd_set_frag(hapd, hapd->iconf->fragm_threshold) &&
hapd->iconf->fragm_threshold != -1) {
wpa_printf(MSG_ERROR, "Could not set fragmentation threshold "
"for kernel driver");
goto fail;
}
prev_addr = hapd->own_addr;
for (j = 0; j < iface->num_bss; j++) {
hapd = iface->bss[j];
if (j)
os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN);
if (hostapd_setup_bss(hapd, j == 0)) {
for (;;) {
hapd = iface->bss[j];
hostapd_bss_deinit_no_free(hapd);
hostapd_free_hapd_data(hapd);
if (j == 0)
break;
j--;
}
goto fail;
}
if (is_zero_ether_addr(hapd->conf->bssid))
prev_addr = hapd->own_addr;
}
hapd = iface->bss[0];
hostapd_tx_queue_params(iface);
ap_list_init(iface);
hostapd_set_acl(hapd);
if (hostapd_driver_commit(hapd) < 0) {
wpa_printf(MSG_ERROR, "%s: Failed to commit driver "
"configuration", __func__);
goto fail;
}
/*
* WPS UPnP module can be initialized only when the "upnp_iface" is up.
* If "interface" and "upnp_iface" are the same (e.g., non-bridge
* mode), the interface is up only after driver_commit, so initialize
* WPS after driver_commit.
*/
for (j = 0; j < iface->num_bss; j++) {
if (hostapd_init_wps_complete(iface->bss[j]))
goto fail;
}
if ((iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) &&
!res_dfs_offload) {
/*
* If freq is DFS, and DFS is offloaded to the driver, then wait
* for CAC to complete.
*/
wpa_printf(MSG_DEBUG, "%s: Wait for CAC to complete", __func__);
return res_dfs_offload;
}
#ifdef NEED_AP_MLME
dfs_offload:
#endif /* NEED_AP_MLME */
#ifdef CONFIG_FST
if (hapd->iconf->fst_cfg.group_id[0]) {
struct fst_wpa_obj iface_obj;
fst_hostapd_fill_iface_obj(hapd, &iface_obj);
iface->fst = fst_attach(hapd->conf->iface, hapd->own_addr,
&iface_obj, &hapd->iconf->fst_cfg);
if (!iface->fst) {
wpa_printf(MSG_ERROR, "Could not attach to FST %s",
hapd->iconf->fst_cfg.group_id);
goto fail;
}
}
#endif /* CONFIG_FST */
hostapd_set_state(iface, HAPD_IFACE_ENABLED);
hostapd_owe_update_trans(iface);
airtime_policy_update_init(iface);
wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_ENABLED);
if (hapd->setup_complete_cb)
hapd->setup_complete_cb(hapd->setup_complete_cb_ctx);
#ifdef CONFIG_MESH
if (delay_apply_cfg && !iface->mconf) {
wpa_printf(MSG_ERROR, "Error while completing mesh init");
goto fail;
}
#endif /* CONFIG_MESH */
wpa_printf(MSG_DEBUG, "%s: Setup of interface done.",
iface->bss[0]->conf->iface);
if (iface->interfaces && iface->interfaces->terminate_on_error > 0)
iface->interfaces->terminate_on_error--;
for (j = 0; j < iface->num_bss; j++)
hostapd_neighbor_set_own_report(iface->bss[j]);
return 0;
fail:
wpa_printf(MSG_ERROR, "Interface initialization failed");
hostapd_set_state(iface, HAPD_IFACE_DISABLED);
wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED);
#ifdef CONFIG_FST
if (iface->fst) {
fst_detach(iface->fst);
iface->fst = NULL;
}
#endif /* CONFIG_FST */
if (iface->interfaces && iface->interfaces->terminate_on_error) {
eloop_terminate();
} else if (hapd->setup_complete_cb) {
/*
* Calling hapd->setup_complete_cb directly may cause iface
* deinitialization which may be accessed later by the caller.
*/
eloop_register_timeout(0, 0,
hostapd_interface_setup_failure_handler,
iface, NULL);
}
return -1;
}
hostapd_setup_interface_complete_sync函数主要调用了如下函数:
hostapd_set_freq
hostapd_prepare_rates
hostapd_set_rts
hostapd_set_frag
hostapd_setup_bss
hostapd_tx_queue_params
hostapd_set_acl
hostapd_driver_commit
hostapd_owe_update_trans
我们看一下hostapd_set_freq的处理:
wpa_supplicant/srv/ap/ap_drv_ops.c
int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode,
int freq, int channel, int edmg, u8 edmg_channel,
int ht_enabled, int vht_enabled,
int he_enabled,
int sec_channel_offset, int oper_chwidth,
int center_segment0, int center_segment1)
{
struct hostapd_freq_params data;
struct hostapd_hw_modes *cmode = hapd->iface->current_mode;
if (hostapd_set_freq_params(&data, mode, freq, channel, edmg,
edmg_channel, ht_enabled,
vht_enabled, he_enabled, sec_channel_offset,
oper_chwidth,
center_segment0, center_segment1,
cmode ? cmode->vht_capab : 0,
cmode ?
&cmode->he_capab[IEEE80211_MODE_AP] : NULL)) //设置freq参数
return -1;
if (hapd->driver == NULL)
return 0;
if (hapd->driver->set_freq == NULL)
return 0;
return hapd->driver->set_freq(hapd->drv_priv, &data); //调用driver的set_freq方法设置freq
}
hostapd_set_freq设置freq参数,将参数数据整合到data中,然后调用hapd->driver->set_freq到kernel驱动,通过搜索代码得知hapd->driver->set_freq的指向为bsd_set_freq:
wpa_supplicant_8/wpa_supplicant/driver/driver_bsd.c
static int bsd_set_freq(void *priv, struct hostapd_freq_params *freq)
{
struct bsd_driver_data *drv = priv;
#ifdef SIOCS80211CHANNEL
struct ieee80211chanreq creq;
#endif /* SIOCS80211CHANNEL */
u32 mode;
int channel = freq->channel;
if (channel < 14) {
mode =
freq->ht_enabled ? IFM_IEEE80211_11NG :
IFM_IEEE80211_11G;
} else if (channel == 14) {
mode = IFM_IEEE80211_11B;
} else {
mode =
freq->ht_enabled ? IFM_IEEE80211_11NA :
IFM_IEEE80211_11A;
}
if (bsd_set_mediaopt(drv, IFM_MMASK, mode) < 0) {
wpa_printf(MSG_ERROR, "%s: failed to set modulation mode",
__func__);
return -1;
}
#ifdef SIOCS80211CHANNEL
os_memset(&creq, 0, sizeof(creq));
os_strlcpy(creq.i_name, drv->ifname, sizeof(creq.i_name));
creq.i_channel = (u_int16_t)channel;
return ioctl(drv->global->sock, SIOCS80211CHANNEL, &creq);
#else /* SIOCS80211CHANNEL */
return set80211param(priv, IEEE80211_IOC_CHANNEL, channel); //调用set80211param函数
#endif /* SIOCS80211CHANNEL */
}
调用set80211param函数:
static int set80211param(struct bsd_driver_data *drv, int op, int arg)
{
return bsd_set80211(drv, op, arg, NULL, 0);
}
static int bsd_set80211(void *priv, int op, int val, const void *arg, int arg_len)
{
struct bsd_driver_data *drv = priv;
struct ieee80211req ireq;
if (drv->ifindex == 0 || drv->if_removed)
return -1;
os_memset(&ireq, 0, sizeof(ireq));
os_strlcpy(ireq.i_name, drv->ifname, sizeof(ireq.i_name));
ireq.i_type = op;
ireq.i_val = val;
ireq.i_data = (void *) arg;
ireq.i_len = arg_len;
if (ioctl(drv->global->sock, SIOCS80211, &ireq) < 0) { //通过ioctl向SIOCS80211发消息
wpa_printf(MSG_ERROR, "ioctl[SIOCS80211, op=%u, val=%u, "
"arg_len=%u]: %s", op, val, arg_len,
strerror(errno));
return -1;
}
return 0;
}