读书人

请问:C代码基于wpa_supplicant怎么编

发布时间: 2013-05-02 09:39:29 作者: rapoo

请教:C代码基于wpa_supplicant如何编写无线连接程序
各位大侠好,我是一个c代码新手
目前需要制作一个无线连接程序,驱动什么的已经搞好了
目前我基于wpa_supplicant和wireless tools做了一个,感觉好像很别扭

首先,对于wpa_supplicant需要的配置文件,我使用fopen创建文件,把配置在一个字符串数组里组装好,然后fwrite到配置文件里,然后使用system执行 wpa_supplicant -B -iwlan0 -c/etc/wpa_supplicant.conf -Dwext 这样的命令来进行无线连接。

搜索过程,我就是使用system执行 iwlist ra0 scan >tmp_file,把结果写到文件里,fopen后,用ftell一句一句的分析,把需要的essid,加密方式这些参数提取出来

对于连接的情况,也是通过执行相关命令把命令结果存在文件中,然后fopen后,读出来检查。

因为没有参加太多的软件开发,所以,目前我只想了这么一个办法。

这个办法很别扭,如果完全都是正确的话,那直接就连接了,没什么问题。
但是如果wpa_supplicant命令执行错了,比如密码有问题等,没法反馈出来
特别是wep方式,密码错了,完全没有打印反馈回来的,我也没法准确的提示出连接正确还是错误。

特地来请教各位大侠,有没有更好的办法?我感觉我这个办法,那是相当的费时费力啊。。。

万分感谢了!!
[解决办法]
顶。是android环境还是linux环境呀?android下应该有参考源码呀。linux环境命令行模式下不懂怎么搞。
[解决办法]
可以把密码保存到一个文件,再和获取的密码比较啊,比较字符串还不会吗?
[解决办法]
基本就是LZ的做法了,可以根据需求慢慢改善。

[解决办法]
system执行 iwlis
[解决办法]
1. 使能 WIFI
2. 查找 AP
3. 配置 AP 参数
4. 连接
5. 配置 IP 地址
基本流程就这样吧。
[解决办法]
一、WIFI的基本架构
1、wifi用户空间的程序和库:
external/wpa_supplicant/
生成库libwpaclient.so和守护进程wpa_supplicant。
2、hardware/libhardware_legary/wifi/是wifi管理库。
3、JNI部分:
frameworks/base/core/jni/android_net_wifi_Wifi.cpp
4、JAVA部分:
frameworks/base/services/java/com/android/server/
frameworks/base/wifi/java/android/net/wifi/
5、WIFI Settings应用程序位于:
packages/apps/Settings/src/com/android/settings/wifi/
二、WIFI在Android中如何工作
Android使用一个修改版wpa_supplicant作为daemon来控制WIFI,代码位于
external/wpa_supplicant。wpa_supplicant是通过socket与
hardware/libhardware_legacy/wifi/wifi.c通信。UI通过android.net.wifi package
(frameworks/base/wifi/java/android/net/wifi/)发送命令给wifi.c。
相应的JNI实现位于frameworks/base/core/jni/android_net_wifi_Wifi.cpp。
更高一级的网络管理位于frameworks/base/core/java/android/net。
三、配置Android支持WIFI
在BoardConfig.mk中添加:
BOARD_HAVE_WIFI := true
BOARD_WPA_SUPPLICANT_DRIVER := WEXT
这将在external/wpa_supplicant/Android.mk设置WPA_BUILD_SUPPLICANT为true,
默认使用驱动driver_wext.c。
如果使用定制的wpa_supplicant驱动(例如 madwifi),可以设置:
BOARD_WPA_SUPPLICANT_DRIVER := MADWIFI
四、使能wpa_supplicant调试信息
默认wpa_supplicant设置为MSG_INFO,为了输出更多信息,可修改:
1、在common.c中设置wpa_debug_level = MSG_DEBUG;
2、在common.c中把#define wpa_printf宏中的
if ((level) >= MSG_INFO)
改为
if ((level) >= MSG_DEBUG)



五、配置wpa_supplicant.conf
wpa_supplicant是通过wpa_supplicant.conf中的ctrl_interface=来指定控制socket的,应该在
AndroidBoard.mk中配置好复制到$(TARGET_OUT_ETC)/wifi(也就是
/system/etc/wifi/wpa_supplicant.conf)
这个位置会在init.rc中再次检测的。
一般的wpa_supplicant.conf配置为:
ctrl_interface=DIR=/data/system/wpa_supplicant GROUP=wifi
update_config=1
fast_reauth=1
有时,驱动需要增加:
ap_scan=1
如果遇到AP连接问题,需要修改ap_scan=0来让驱动连接,代替wpa_supplicant。
如果要连接到non-WPA or open wireless networks,要增加:
network={
key_mgmt=NONE
}
六、配置路径和权限
Google修改的wpa_supplicant要运行在wifi用户和组下的。代码可见wpa_supplicant/os_unix.c
中的os_program_init()函数。 如果配置不对,会出现下面错误:
E/WifiHW ( ): Unable to open connection to supplicant on
"/data/system/wpa_supplicant/wlan0": No such file or directory will appear.
确认init.rc中有如下配置:
mkdir /system/etc/wifi 0770 wifi wifi
chmod 0770 /system/etc/wifi
chmod 0660 /system/etc/wifi/wpa_supplicant.conf
chown wifi wifi /system/etc/wifi/wpa_supplicant.conf
# wpa_supplicant socket
mkdir /data/system/wpa_supplicant 0771 wifi wifi
chmod 0771 /data/system/wpa_supplicant
#wpa_supplicant control socket for android wifi.c
mkdir /data/misc/wifi 0770 wifi wifi
mkdir /data/misc/wifi/sockets 0770 wifi wifi
chmod 0770 /data/misc/wifi
chmod 0660 /data/misc/wifi/wpa_supplicant.conf
如果系统的/system目录为只读,那应该使用路径/data/misc/wifi/wpa_supplicant.conf。
七、运行wpa_supplicant和dhcpcd
在init.rc中确保有如下语句:
service wpa_supplicant /system/bin/logwrapper /system/bin/wpa_supplicant -dd
-Dwext -iwlan0 -c /data/misc/wifi/wpa_supplicant.conf
user root
group wifi inet
socket wpa_wlan0 dgram 660 wifi wifi
oneshot
service dhcpcd /system/bin/logwrapper /system/bin/dhcpcd -d -B wlan0
disabled
oneshot

根据所用的WIFI驱动名字,修改wlan0为自己驱动的名字。

七、编译WIFI驱动为module或kernel built in


1、编译为module
在BoardConfig.mk中添加:
WIFI_DRIVER_MODULE_PATH := "/system/lib/modules/ar6000.ko"
WIFI_DRIVER_MODULE_ARG := "" #for example nohwcrypt
WIFI_DRIVER_MODULE_NAME := "ar6000" #for example wlan0
WIFI_FIRMWARE_LOADER := ""
2、编译为kernel built in
1)在hardware/libhardware_legacy/wifi/wifi.c要修改interface名字,
2)在init.rc中添加:
setprop wifi.interface "wlan0"
3)在hardware/libhardware_legacy/wifi/wifi.c中当insmod/rmmod时,
直接return 0。
八、WIFI需要的firmware
Android不使用标准的hotplug binary,WIFI需要的firmware要复制到/etc/firmware。 或者复制到WIFI驱动指定的位置,然后WIFI驱动会自动加载。

九、修改WIFI驱动适合Android
Google修改的wpa_supplicant要求SIOCSIWPRIV ioctl发送命令到驱动,及接收信息,例如signal
strength, mac address of the AP, link speed等。所以要正确实现WIFI驱动,需要从
SIOCSIWPRIV ioctl返回RSSI (signal strength)和MACADDR信息。
如果没实现这个ioctl,会出现如下错误:
E/wpa_supplicant( ): wpa_driver_priv_driver_cmd failed
wpa_driver_priv_driver_cmd RSSI len = 4096
E/wpa_supplicant( ): wpa_driver_priv_driver_cmd failed
D/wpa_supplicant( ): wpa_driver_priv_driver_cmd LINKSPEED len = 4096
E/wpa_supplicant( ): wpa_driver_priv_driver_cmd failed
I/wpa_supplicant( ): CTRL-EVENT-DRIVER-STATE HANGED

十、设置dhcpcd.conf
一般/system/etc/dhcpcd/dhcpcd.conf的配置为:
interface wlan0
option subnet_mask, routers, domain_name_servers

[解决办法]
我来说一下吧..不知道你那行不行,不过应该是一样的....当你的密码啥啥的,都正确的时候,那么你建立socket之后,你可以用ioctl获取到网卡的信息,里面就有关于连接是否成功的数据,连接完成...
typedef enum {
WPA_DISCONNECTED, // Disconnected state
WPA_INACTIVE, // Inactive state (wpa_supplicant disabled)
WPA_SCANNING, // Scanning for a network
WPA_ASSOCIATING, // Trying to associate with a BSS/SSID
WPA_ASSOCIATED, // Association completed
WPA_4WAY_HANDSHAKE, // WPA 4-Way Key Handshake in progress
WPA_GROUP_HANDSHAKE, // WPA Group Key Handshake in progress


WPA_COMPLETED, // All authentication completed
} wpa_states;

这部分是获取AP的信号强度
struct iwreq iwr;
memset(&iwr, 0, sizeof(iwr));
strlcpy(iwr.ifr_ifrn.ifrn_name, ifname, sizeof(iwr.ifr_ifrn.ifrn_name) - 1);
iwr.u.data.pointer = (caddr_t) stats;
iwr.u.data.length = sizeof(*stats);
iwr.u.data.flags = 1;
ret = ioctl(sock, SIOCGIWSTATS, &iwr);
[解决办法]
我做了一套WIFI的接口,通过SOCKET与WPA_SUSPPLICANT通信,当连接后,不管成功与否,直接发STATUS给WPA_SUSPPLICANT获取状态, 然后就能判断是否连接上了。 ASSOCIATING-》ASSOCIATED-》4WAY_HANDSHAKE-》GROUP_HANDSHAKE-》COMPLETED这就是它连接过程中的状态变化过程。你如果密码失败,在四次握手的阶段就会失败了。
[解决办法]

引用:
这个问题目前我想到一个办法,参照安卓的无线实现部分
直接把wpa_supplicant加到代码里面,调用它的接口
不过目前还没实现成功,把wpa_supplicant放到自己的代码里面编到一起,没那么容易。。。

你觉得难点在哪?参照android的做法,你的wpa_supplicant会编成一个可执行文件,你开两个socket一个下命令一个监控。如果你只要求使用wpa_supplicant来连接和断开wifi的话其实不难,难的是对于网络出错或者验证出错的处理。
[解决办法]
如果移植wpa_suppliacant源码困难的话,不妨试试下面官方提倡的做法:

来自于wpa_supplicant-devel文档
3、控制接口
wpa_supplicant实现了一个由外部程序使用来控制wpa_supplicant守护程序操作和得到状态信息和事件通知的控制接口。有一个单独文件的小C库wpa_ctrl.c提供辅助函数来方便使用这个控制接口。外部程序可以把这个文件链接到他们并使用wpa_ctrl.h中提供的函数来与wpa_supplicant交互。这个库也可以被C++使用。wpa_cli.c和wpa_gui 是使用这个库的实例。
[解决办法]
wpa_supplicant编译生成wpa_supplicant和wpa_cli时,
编译过程会生成每个文件的.o文件,
用ar -rsv libwpa.a wpa_supplicant.o ctrl_interface.o driver_wext.o ....就可以生成静态链接库.a。
用gcc -fPIC -shared 生成动态链接库.so。

后面的,你懂得。。。。

读书人网 >驱动开发

热点推荐