前面讲了的初始,这一节将介绍interface的初始化
关于interface这个词在这里具体指的是什么,开始的时候自己也很模糊,经过多次询问和验证,个人将这个interface理解为无线网卡物理口,即我们用ifconfig打印出的wifi0和wifi1这样的接口。我们知道,hostapd的一个主要功能是将一个无线网卡切换成ap模式,让它以server端的角色运行,能够让其他无线设备连接上来。现在的路由器一般都支持2.4G和5G两种无线频段,所以在硬件上自然会有两块无线网卡,那么在这两块无线网卡都运行的时候,能够在ifconfig中看到wifi0和wifi1的状态都是up的,使用ps -w | grep hostapd 也能够查看到,hostapd到底使用的是哪个网卡的配置文件,到底启动了那块网卡。
这里需要辨别一下物理网卡口和空中接口的区别,空中接口多以ath0,ath1等字样命名,它们作为无线用户的接入点,可以创建多个,甚至多于网卡的数量,比如在路由器启动guest network功能的时候,用iwconfig命令可以查看到4个空中接口,这些都可以作为用户的接入点,他们主要是需要使用不同的用户名和密码进行认证,但最终数据包的处理还是经过实际的两块网卡进行的。
下面说一下,程序时怎么初始化interface的。
for (i = 0; i < interfaces.count; i++) {
interfaces.iface[i] = hostapd_interface_init(&interfaces,
argv[optind + i],
debug);
if (!interfaces.iface[i]) {
wpa_printf(MSG_ERROR, "Failed to initialize interface");
goto out;
}
}
hostapd -B -e /etc/entropy /etc/ath1.conf /etc/ath0.conf
以这样的参数运行hostapd时,argc=6 optind=4,那么count的值将等于2,其实也可以这样理解:argc - optind就是非选项参数的个数,比如上面 -B是不带参数的选项,-e是带一个参数/etc/entropy的选项,那么剩下的/etc/ath1.conf /etc/ath0.conf不是某个选项的参数,所以不需要经过getopt类似函数的处理,不会使optind的值加一,所以差计算后他们的个数是2.
接下来好好说一下hostapd_interface_init这个函数。
static struct hostapd_iface *
hostapd_interface_init(struct hapd_interfaces *interfaces,
const char *config_fname, int debug)
{
struct hostapd_iface *iface;
int k;
wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname);
iface = hostapd_init(interfaces, config_fname);
if (!iface)
return NULL;
iface->interfaces = interfaces;
for (k = 0; k < debug; k++) {
if (iface->bss[0]->conf->logger_stdout_level > 0)
iface->bss[0]->conf->logger_stdout_level--;
}
if (iface->conf->bss[0]->iface[0] == '\0' &&
!hostapd_drv_none(iface->bss[0])) {
wpa_printf(MSG_ERROR, "Interface name not specified in %s",
config_fname);
hostapd_interface_deinit_free(iface);
return NULL;
}
return iface;
}
1. 先看struct hostapd_iface 对interface的操作函数以及标示变量的封装
struct hostapd_iface {
struct hapd_interfaces *interfaces;
void *owner;
char *config_fname; // 这里存放配置文件路径和文件名
struct hostapd_config *conf; //将配置文件中的信息读取后,将存放在这个结构体中
char phy[16]; /* Name of the PHY (radio) */ //无线网卡芯片名
enum hostapd_iface_state { //描述接口状态
HAPD_IFACE_UNINITIALIZED,
HAPD_IFACE_DISABLED,
HAPD_IFACE_COUNTRY_UPDATE,
HAPD_IFACE_ACS,
HAPD_IFACE_HT_SCAN,
HAPD_IFACE_DFS,
HAPD_IFACE_ENABLED
} state;
size_t num_bss; //基础服务集合个数
struct hostapd_data **bss; //存放bss数据
unsigned int wait_channel_update:1;
unsigned int cac_started:1;
/*
* When set, indicates that the driver will handle the AP
* teardown: delete global keys, station keys, and stations.
*/
unsigned int driver_ap_teardown:1;
int num_ap; /* number of entries in ap_list */
struct ap_info *ap_list; /* AP info list head */
struct ap_info *ap_hash[STA_HASH_SIZE];
unsigned int drv_flags;
/*
* A bitmap of supported protocols for probe response offload. See
* struct wpa_driver_capa in driver.h
*/
unsigned int probe_resp_offloads;
/* extended capabilities supported by the driver */
const u8 *extended_capa, *extended_capa_mask;
unsigned int extended_capa_len;
unsigned int drv_max_acl_mac_addrs;
struct hostapd_hw_modes *hw_features;
int num_hw_features;
struct hostapd_hw_modes *current_mode;
/* Rates that are currently used (i.e., filtered copy of
* current_mode->channels */
int num_rates;
struct hostapd_rate_data *current_rates;
int *basic_rates;
int freq;
u16 hw_flags;
/* Number of associated Non-ERP stations (i.e., stations using 802.11b
* in 802.11g BSS) */
int num_sta_non_erp;
/* Number of associated stations that do not support Short Slot Time */
int num_sta_no_short_slot_time;
/* Number of associated stations that do not support Short Preamble */
int num_sta_no_short_preamble;
int olbc; /* Overlapping Legacy BSS Condition */
/* Number of HT associated stations that do not support greenfield */
int num_sta_ht_no_gf;
/* Number of associated non-HT stations */
int num_sta_no_ht;
/* Number of HT associated stations 20 MHz */
int num_sta_ht_20mhz;
/* Number of HT40 intolerant stations */
int num_sta_ht40_intolerant;
/* Overlapping BSS information */
int olbc_ht;
u16 ht_op_mode;
/* surveying helpers */
/* number of channels surveyed */
unsigned int chans_surveyed;
/* lowest observed noise floor in dBm */
s8 lowest_nf;
unsigned int dfs_cac_ms;
struct os_reltime dfs_cac_start;
/* Latched with the actual secondary channel information and will be
* used while juggling between HT20 and HT40 modes. */
int secondary_ch;
#ifdef CONFIG_ACS
unsigned int acs_num_completed_scans;
#endif /* CONFIG_ACS */
void (*scan_cb)(struct hostapd_iface *iface);
int num_ht40_scan_tries;
2. hostapd_init()函数
struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces,
const char *config_file)
{
struct hostapd_iface *hapd_iface = NULL;
struct hostapd_config *conf = NULL;
struct hostapd_data *hapd; //这个结构体很重要,存放了数据以及一些报文相关的操作和信息
size_t i;
hapd_iface = os_zalloc(sizeof(*hapd_iface));
if (hapd_iface == NULL)
goto fail;
hapd_iface->config_fname = os_strdup(config_file);
if (hapd_iface->config_fname == NULL)
goto fail;
interfaces->config_read_cb=hostapd_config_read
conf = interfaces->config_read_cb(hapd_iface->config_fname);
if (conf == NULL)
goto fail;
hapd_iface->conf = conf;
hapd_iface->num_bss = conf->num_bss;
hapd_iface->bss = os_calloc(conf->num_bss,
sizeof(struct hostapd_data *));
if (hapd_iface->bss == NULL)
goto fail;
for (i = 0; i < conf->num_bss; i++) {
hapd = hapd_iface->bss[i] =
hostapd_alloc_bss_data(hapd_iface, conf,
conf->bss[i]);
if (hapd == NULL)
goto fail;
hapd->msg_ctx = hapd;
}
return hapd_iface;
其中hostapd_alloc_bss_data的定义为
static struct hostapd_data *hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, struct hostapd_config *conf, struct hostapd_bss_config *bss)
三个参数分别为本interface信息,本interface的配置信息,本interface配置信息中第i个bss的配置部分。
其中代码 (struct hostapd_data *hapd)
hapd->iconf = conf;
hapd->conf = bss;
hapd->iface = hapd_iface;
使得hostapd_data中均有指向这几个配置的指针了。
既有:
hapd_iface->bss[i]->iconf == hapd_iface->conf
hapd_iface->bss[i]->conf == &hapd_iface->conf->bss[i]
hapd_iface->bss[i]->iface == hapd_iface
所以struct hostapd_data, struct hostapd_iface, struct hostapd_config, struct hostapd_bss_config之间是相互联系的。