Compile wpa_supplicant2.0 for IPNC

1 Download wpa_supplicant2.0

Download Page:
http://hostap.epitest.fi/wpa_supplicant/
Download URL:
http://hostap.epitest.fi/releases/wpa_supplicant-2.0.tar.gz

untar the compressed file:
# tar -zxvf wpa_supplicant-2.0.tar.gz


2 Build openssl for wpa_supplicant2.0

Download openssl-0.9.8d.tar.gz(version must be0.9.8d)

Download Page:
http://www.openssl.org/source/
Download URL:
http://www.openssl.org/source/openssl-0.9.8d.tar.gz

untar the compressed file:
# tar -zxvf openssl-0.9.8d.tar.gz
Patch the diff file
# cd openssl-0.9.8d
# patch -Np1 -i ../wpa_supplicant-2.0/patches/openssl-0.9.8d-tls-extensions.patc

the options '-Np1' is number '1',not letter 'l'

configure && make openssl

Configured as shared library
# ./config --prefix=`pwd`/build4wpa_supplicant2 --openssldir=`pwd`/build4wpa_supplicant2/ssl shared zlib-dynamic no-asm no-sse2
# vim Makefile
edit Makefile file :
L16: remove -march=pentium
L17: remove -march=pentium
L62: CC= arm_v5t_le-gcc
L63: remove build option -mcpu=pentium
L69: AR= arm_v5t_le-ar $(ARFLAGS) r
L70: RANLIB= arm_v5t_le-ranlib
L74: MAKEDEPPROG= arm_v5t_le-gcc

# make
# make install

3 Build wap_supplicant2.0

# cd wpa_supplicant-2.0
Create an initial configuration file for the build process.
Run the following command to create a build configuration file:
# cat > wpa_supplicant/.config << "EOF"
CFLAGS += -I../../openssl-0.9.8d/build4wpa_supplicant2/include
LIBS += -L../../openssl-0.9.8d/build4wpa_supplicant2/lib -lssl
CONFIG_DRIVER_HOSTAP=y
CONFIG_DRIVER_WEXT=y
CONFIG_IEEE8021X_EAPOL=y
CONFIG_EAP_MD5=y
CONFIG_EAP_MSCHAPV2=y
CONFIG_EAP_TLS=y
CONFIG_EAP_PEAP=y
CONFIG_EAP_TTLS=y
CONFIG_EAP_FAST=y
CONFIG_EAP_GTC=y
CONFIG_EAP_OTP=y
CONFIG_EAP_PSK=y
CONFIG_EAP_PWD=y
CONFIG_EAP_PAX=y
CONFIG_EAP_LEAP=y
CONFIG_EAP_SAKE=y
CONFIG_PKCS12=y
CONFIG_SMARTCARD=y
CONFIG_CTRL_IFACE=udp-remote
CONFIG_NO_STDOUT_DEBUG=y
CONFIG_BACKEND=file
CONFIG_PEERKEY=y
CONFIG_TLS=openssl
CONFIG_IEEE80211R=y
CONFIG_IEEE80211N=y
CONFIG_AP=y
CONFIG_P2P=y
EOF
# cd wpa_supplicant/
# make clean
# make CC=arm_v5t_le-gcc



<think>我们有一个具体需求:在wpa_supplicant触发扫描时,只扫描虚拟接口所保存的信道(这些信道信息由iwinfo提供)。这需要我们在wpa_supplicant的扫描配置中动态设置信道列表。 分析: 1. wpa_supplicant的扫描配置通常通过`wpa_supplicant.conf`文件设置,但该文件不支持动态信道设置(比如根据虚拟接口的信道动态调整)。 2. 我们需要在启动扫描前获取虚拟接口的信道信息(通过iwinfo),然后将这些信道设置到wpa_supplicant的扫描请求中。 解决方案: 由于wpa_supplicant本身没有内置对iwinfo的支持,我们需要修改wpa_supplicant的源码,在扫描前调用iwinfo库获取虚拟接口的信道,然后设置扫描信道。 步骤: 1.wpa_supplicant中集成iwinfo库。 2. 在启动扫描的函数中(如`wpa_supplicant_req_scan`),获取虚拟接口的信道列表。 3. 将信道列表设置到扫描参数中。 详细代码修改: 步骤一:在wpa_supplicant的构建系统中添加iwinfo链接。 修改`wpa_supplicant/Makefile`,在适当位置添加: ``` LIBS += -liwinfo ``` 步骤二:在代码中包含iwinfo头文件。 在需要调用iwinfo的地方(比如`scan.c`)添加: ```c #include <iwinfo.h> ``` 步骤三:修改扫描请求函数,获取虚拟接口的信道并设置扫描参数。 以`wpa_supplicant_req_scan`函数为例(实际修改点可能需要根据具体流程选择,比如在`wpa_supplicant_trigger_scan`中): ```c // 在wpa_supplicant_trigger_scan函数中,设置扫描参数之前 struct wpa_driver_scan_params *params = ...; // 已有的扫描参数 // 获取虚拟接口的名称(这里假设我们关注的是当前接口的虚拟接口,具体需要根据你的设计) const char *ifname = wpa_s->ifname; // 使用iwinfo获取该接口支持的信道列表 const struct iwinfo_ops *iw = iwinfo_backend(ifname); if (iw) { char buf[IWINFO_BUFSIZE]; int len = iw->freqlist(ifname, buf, sizeof(buf)); if (len > 0) { // 解析buf中的信道列表,buf中是一组频率值(以MHz为单位) // 注意:wpa_supplicant的扫描参数需要的是信道号(channel number)数组 // 所以我们需要将频率转换为信道号(可以使用ieee80211_freq_to_chan函数) int *freqs = (int *)buf; int num = len / sizeof(int); int *channels = os_malloc(num * sizeof(int)); int i, count = 0; for (i = 0; i < num; i++) { int chan = ieee80211_freq_to_chan(freqs[i]); if (chan) { channels[count++] = chan; } } // 设置扫描信道 params->freqs = channels; params->num_freqs = count; // 注意:这里需要记得在扫描完成后释放channels(或者可以将其生命周期延长到扫描完成) } } ``` 但是,上述代码有几个问题: 1. `iw->freqlist`返回的并不是一个整数数组,而是以字符串形式返回(每个频率之间用空格分隔)?根据iwinfo的文档和代码,实际上`freqlist`函数返回的是整数数组,但是通过buf返回,并且每个整数是4字节(int)。 2. 频率转换为信道:使用`ieee80211_freq_to_chan`函数(在wpa_supplicant中已经存在,位于`utils/common.c`中)。 然而,我们这里的需求是只扫描虚拟接口保存的信道。注意,虚拟接口可能是在一个多接口的环境中,我们可能需要获取这个虚拟接口的父接口的信道?或者虚拟接口本身就有信道限制?这里需要明确。 另外,我们可能不需要获取所有支持的信道,而是获取虚拟接口当前配置的信道(或者关联的信道)?但是扫描通常需要扫描多个信道(比如虚拟接口可能支持多个信道,但只保存了某些信道)。所以,我们需要明确“虚拟口信道”具体指什么? 假设我们的需求是:虚拟接口当前关联的信道(如果已关联)或者虚拟接口配置的信道(如果没有关联)。但是,虚拟接口可能同时支持多个信道,我们可能希望扫描所有虚拟接口支持的信道(即虚拟接口所在物理接口所支持的信道,并且是虚拟接口允许的信道)? 根据问题描述,我们由iwinfo提供,那么我们可以使用iwinfo的`freqlist`来获取虚拟接口支持的所有信道(频率),然后转换为信道号。 步骤四:处理内存。 上面的例子中,我们分配了channels数组,但是扫描完成后需要释放。我们可以修改扫描参数的内存管理,在扫描完成后释放这个数组。 在`wpa_supplicant_trigger_scan`函数中,在调用`wpa_drv_scan`之后,我们可以释放params->freqs(因为params是栈上分配的,但是它的freqs指向堆内存)?但是注意,params结构体中的freqs在扫描请求完成后,通常会被wpa_supplicant在内部清理(在`wpa_scan`函数中)?我们需要检查现有的代码是否释放freqs。如果现有代码不会释放,那么我们需要在扫描完成后释放。 实际上,在`wpa_supplicant_trigger_scan`函数中,params是局部变量,但是它的freqs指向我们分配的内存。在调用`wpa_drv_scan`之后,params的内容已经被使用(复制到驱动),所以我们可以立即释放: ```c if (params.freqs) { os_free(params.freqs); } ``` 但是,注意:在`wpa_drv_scan`中,可能会将freqs数组复制到驱动中,所以我们在函数返回前释放是安全的。 然而,我们修改的是`wpa_supplicant_trigger_scan`函数,这个函数在wpa_supplicant中会多次调用,我们需要确保只在需要的时候(即虚拟接口存在并且我们成功获取信道列表时)才设置freqs,并且在设置后记得释放。 但是,注意:在`wpa_supplicant_trigger_scan`函数中,params.freqs可能原本就有值(比如来自配置的扫描信道),我们覆盖它之前需要先释放原来的吗?原代码中,params.freqs在初始化时是NULL,所以我们可以直接覆盖。 步骤五:错误处理。 如果获取信道失败,则按原有方式扫描(即不限制信道)。 完整修改示例(在`wpa_supplicant_trigger_scan`函数中): ```c // 在函数开头,声明变量 int *channels = NULL; int num_channels = 0; // 在调用wpa_drv_scan之前,准备扫描参数 struct wpa_driver_scan_params params; os_memset(&params, 0, sizeof(params)); // ... 原有代码设置扫描参数 // 尝试获取虚拟接口的信道 const struct iwinfo_ops *iw = iwinfo_backend(wpa_s->ifname); if (iw) { char buf[IWINFO_BUFSIZE]; // 注意:iwinfo的freqlist函数返回的是整数数组,buf中存储的是多个int int len = iw->freqlist(wpa_s->ifname, buf, sizeof(buf)); if (len > 0) { int *freqs = (int *)buf; int num_freqs = len / sizeof(int); int i; channels = os_malloc(num_freqs * sizeof(int)); if (channels) { for (i = 0; i < num_freqs; i++) { int chan = ieee80211_freq_to_chan(freqs[i]); if (chan) { channels[num_channels++] = chan; } } } } } // 如果我们成功获取了信道,则设置扫描信道 if (num_channels > 0) { params.freqs = channels; params.num_freqs = num_channels; } else { // 否则,使用默认的扫描信道(不限制) params.freqs = NULL; params.num_freqs = 0; } // 调用驱动扫描 ret = wpa_drv_scan(wpa_s, &params); // 释放我们分配的信道数组 if (channels) { os_free(channels); } // ... 后续代码 ``` 注意:这个修改会每次扫描都获取一次信道列表。如果频繁扫描可能会影响性能,但考虑到扫描本身是耗时操作,这个开销可以接受。 步骤六:编译和测试。 按照之前的方法,在OpenWrt环境中重新编译wpa_supplicant,并安装测试。 注意事项: 1. 确保iwinfo库在目标设备上可用。 2. 确保虚拟接口的名称正确传递(wpa_s->ifname)。 3. 注意频率转换为信道的准确性(不同频段可能转换方式不同,但ieee80211_freq_to_chan函数已经处理了)。 替代方案: 如果不希望修改wpa_supplicant源码,也可以考虑通过外部脚本控制: 1. 使用wpa_cli和iwinfo命令,先获取信道,然后通过wpa_cli设置扫描信道,再触发扫描。 2. 但是这种方法需要外部管理,而且扫描请求可能来自wpa_supplicant内部(比如自动重连),所以可能不适用。 因此,修改源码是更直接的方法。 相关问题: 1. 如何获取虚拟接口的信道列表(包括2.4GHz和5GHz)? 2.wpa_supplicant中动态设置扫描信道有哪些注意事项? 3. 如何避免频繁获取信道列表带来的性能开销?</think>要在 `wpa_supplicant` 中配置扫描使其仅扫描虚拟接口保存的信道(由 `iwinfo` 提供),需要修改源码并集成 `iwinfo` 功能。以下是具体实现方案: ### 1. **修改扫描配置逻辑** 在 `wpa_supplicant/scan.c` 的扫描初始化函数中添加信道过滤: ```c #include <iwinfo.h> // 添加iwinfo头文件 static int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params) { // 获取虚拟接口名称(如vif0) const char *vif_name = wpa_s->ifname; // 调用iwinfo获取虚拟接口保存的信道 const struct iwinfo_ops *iw = iwinfo_backend(vif_name); if (iw) { int chan_list[20]; // 存储信道列表 int chan_count = 0; // 获取虚拟接口支持的信道[^2] char buf[IWINFO_BUFSIZE]; if (iw->freqlist(vif_name, buf, sizeof(buf)) == 0) { // 解析信道数据(示例:buf="2412 2437 2462") char *freq = strtok(buf, " "); while (freq && chan_count < 20) { int freq_val = atoi(freq); // 将频率转换为信道号 int chan = ieee80211_freq_to_channel(freq_val); if (chan > 0) chan_list[chan_count++] = chan; freq = strtok(NULL, " "); } } // 设置扫描信道过滤 if (chan_count > 0) { params->freqs = os_malloc(chan_count * sizeof(int)); os_memcpy(params->freqs, chan_list, chan_count * sizeof(int)); params->num_freqs = chan_count; wpa_printf(MSG_DEBUG, "SCAN: Restrict to %d vif channels", chan_count); } } // ...原有扫描逻辑... } ``` ### 2. **关键修改点说明** 1. **信道获取**: - 使用 `iwinfo_backend()` 获取接口操作句柄 - 通过 `freqlist()` 获取虚拟接口支持的信道频率列表[^2] - 使用 `ieee80211_freq_to_channel()`(在 `utils/common.c` 中)转换为信道号 2. **扫描过滤**: - 将信道列表存入 `params->freqs` - 设置 `params->num_freqs` 限制扫描范围 - 原有未修改逻辑会扫描全信道 3. **虚拟接口识别**: - 通过 `wpa_s->ifname` 获取当前虚拟接口名 - 确保 `iwinfo` 支持该虚拟接口类型(如 `mac80211`) ### 3. **编译配置** 1. **修改 Makefile**: ```makefile # 在wpa_supplicant/Makefile中添加 CFLAGS += -I$(STAGING_DIR)/usr/include/iwinfo LIBS += -liwinfo ``` 2. **编译安装**: ```bash # OpenWrt环境 make package/wpa-supplicant/{clean,compile} V=s opkg install --force-reinstall wpa-supplicant_*.ipk ``` ### 4. **验证配置** 1. **测试扫描**: ```bash wpa_cli -i vif0 scan # 触发虚拟接口扫描 wpa_cli scan_results # 检查结果信道范围 ``` 2. **查看日志**: ```bash logread | grep "SCAN: Restrict" # 应显示:SCAN: Restrict to 3 vif channels ``` ### 5. **注意事项** 1. **虚拟接口支持**: - 确认 `iwinfo` 支持该虚拟接口类型: ```bash iwinfo vif0 info # 检查是否返回有效数据[^2] ``` - 若不支持需在 `iwinfo` 中添加对应后端驱动 2. **动态信道更新**: - 若虚拟接口信道变化,需在 `wpa_supplicant_event()` 中添加 `EVENT_CHANNEL_CHANGE` 处理 - 调用 `wpa_supplicant_req_scan()` 重新触发扫描 3. **备选方案**: ```bash # 不修改源码时通过脚本控制 CHANS=$(iwinfo vif0 freqlist | awk '{print $1}') wpa_cli -i vif0 set scan_freq $CHANS wpa_cli -i vif0 scan ``` > **关键提示**:此方案假设虚拟接口已绑定特定信道。若需同时管理多个虚拟接口,需在 `struct wpa_supplicant` 中添加信道缓存字段,并在接口切换时更新扫描配置[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值