wpa_supplicant 和hostpad让WiFi模块同时工作在AP+STA模式(转)

https://blog.csdn.net/leumber/article/details/85337891

本文将介绍如何使用 wpa_supplicant服务程序和wpa_cli 客户端程序,让嵌入式设备的WIFI模块工作在station模式并连接网络,以及如何使用hostapdudhcpd创建一个WIFI热点,并且解决如何让这两种工作模式共存。

WLAN一般有四种工作模式

Master(AP)        成为无线接入点提供无线接入服务
Managed(STA)    作为客户端连接其他无线接入点
Monitor            监听附近所有无线流量
Ad-hoc            多台计算机直接相连

网卡一般是工作在Managed(STA)模式,使用 wpa_supplicant服务程序和wpa_cli 客户端程序,要使用AP模式需要使用hostapd这个服务程序
因为我手里用的是Realetk 的RTL8188EU模块,所以在该模块的基础上来做的测试

一、准备工作
要编译出wpa_supplicant 、wpa_cli 和hostapd这几个程序,首先要编译OpenSSL库和netlink库
从官网下载对应的源码
https://www.openssl.org/source/
http://www.infradead.org/~tgr/libnl/

1.编译openssl
./config no-asm -shared  --prefix=$PWD/build --cross-compile-prefix=arm-linux-
make
make install

有的ubuntu系统是64位的编译的时候会报错 “-m64” 在Makefile文件中去掉这个参数,共有两处

2.编译libnl
./configure --host=arm-linux --prefix=$PWD/build CC=arm-linux-gcc
make
make install

3.交叉编译 wpa_supplicant
cp defconfig .config
修改.config 添加libnl 和openssl 的头文件和库
添加CC 交叉编译链

#CFLAGS += -I$<path to libnl include files>
#LIBS += -L$<path to libnl library files>
CFLAGS += -I/home/linux/Tools/libnl-1.1.4/build/include
LIBS += -L/home/linux/Tools/libnl-1.1.4/build/lib
CFLAGS += -I/home/linux/Tools/openssl-1.0.2q/build/include
LIBS += -L/home/linux/Tools/openssl-1.0.2q/build/lib
CC=arm-linux-gcc

然后make编译,得到wpa_supplicant和 wpa_cli 还有配置文件 wpa_supplicant.conf

4.编译8188eu模块的内核驱动文件
在板子上加载该模块

insmod 8188eu.ko

5.交叉编译hostapd
cp defconfig .config

修改.config 添加libnl 和openssl 的头文件和库
添加CC 交叉编译链

#CFLAGS += -I$<path to libnl include files>
#LIBS += -L$<path to libnl library files>
CFLAGS += -I/home/linux/Tools/libnl-1.1.4/build/include
LIBS += -L/home/linux/Tools/libnl-1.1.4/build/lib
CFLAGS += -I/home/linux/Tools/openssl-1.0.2q/build/include
LIBS += -L/home/linux/Tools/openssl-1.0.2q/build/lib
CC=arm-linux-gcc

然后make编译,得到hostapd 和 hostapd_cli 还有配置文件 hostapd.conf

有的要去掉IPV6,因为有的嵌入式设备不支持IPV6也没有这个环境,执行程序时会报 ‘in6addr_any’ 的错

#CONFIG_IPV6=y 

二.Managed(STA)模式
1.首先启动wpa_supplicant服务
wpa_supplicant  -B -Dwext -iwlan0 -c /etc/wpa_supplicant.conf

wpa_supplicant命令的参数如下:

drivers:
  wext = Linux wireless extensions (generic)
options:
  -b = optional bridge interface name
  -B = run daemon in the background
  -c = Configuration file
  -C = ctrl_interface parameter (only used if -c is not)
  -i = interface name
  -d = increase debugging verbosity (-dd even more)
  -D = driver name (can be multiple drivers: nl80211,wext)
  -g = global ctrl_interface
  -K = include keys (passwords, etc.) in debug output
  -t = include timestamp in debug messages
  -h = show this help text
  -L = show license (GPL and BSD)
  -o = override driver parameter for new interfaces
  -O = override ctrl_interface parameter for new interfaces
  -p = driver parameters
  -P = PID file
  -q = decrease debugging verbosity (-qq even less)
  -v = show version
  -W = wait for a control interface monitor before starting
  -N = start describing new interface
example:
  wpa_supplicant -Dwext -iwlan0 -c/etc/wpa_supplicant.conf

/etc/wpa_supplicant.conf这个文件就是我们保存的wifi账号和密码,其实在Android手机中如果要看你连接过的WiFi和密码,就是看这个文件
内容如下:

ctrl_interface=/var/run/wpa_supplicant
eapol_version=1
ap_scan=1
fast_reauth=1
blob-base64-exampleblob={
SGVsbG8gV29ybGQhCg==
}

network={
   ssid="wifi_test"
   scan_ssid=1
   psk="1234567890"
   priority=5
}

2.启动客户服务程序wpa_cli连接网络
wpa_cli 这个程序相对复杂一点,参数比较多,命令更多,这里只列出常用的这几个

wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] [-a<action file>] \
[-P<pid file>] [-g<global ctrl>] [-G<ping interval>]  [command..]
  -h = help (show this usage text)
  -v = shown version information
  -a = run in daemon mode executing the action file based on events from
   wpa_supplicant
  -B = run a daemon in the background
  default path: /var/run/wpa_supplicant
  default interface: first interface found in socket path
commands:
  scan = request new BSS scan
  scan_results = get latest scan results
  add_network = add a network
  select_network <network id> = select a network (disable others)
  enable_network <network id> = enable a network
  disable_network <network id> = disable a network
  remove_network <network id> = remove a network
  
  set_network <network id> <variable> <value> = set network variables (shows
list of variables when run without arguments)

wpa_cli是可以进入交互模式,在这中可以通过命令来连接网络和具体配置,但是一般的,我们都是直接使用命令,放在脚本或程序中去执行的

#wpa_cli
>add_network  (It will display a network id for you, assume it returns 0)
>set_network 0 ssid "wifi_test"
>set_network 0 key_mgmt NONE
>enable_network 0
>quit

1.扫描网络
scan是扫描网络
scan_results 是列出扫描的网络状态列表

wpa_cli -iwlan0 -p /var/run/wpa_supplicant scan
wpa_cli -iwlan0 -p /var/run/wpa_supplicant scan_reault

这两句一般是连着使用

2.添加网络
然后就是使用add_network添加一个网络

wpa_cli -iwlan0 -p /var/run/wpa_supplicant add_network

这里会返回一个ID,后边的操作都是用这个ID去识别的这里假设是0

3.设置网络
之后就是去操作新添加的这个网络,从而完成联网操作
set_network 是设置网络的相关信息,如ssid,加密方式及密码

如果要连接加密方式是[WPA-PSK-CCMP+TKIP][WPA2-PSK-CCMP+TKIP][ESS] (wpa加密)

wpa_cli -iwlan0 -p /var/run/wpa_supplicant set_network 0 ssid '"name"'
wpa_cli -iwlan0 -p /var/run/wpa_supplicant set_network 0 psk '"psk"'

如果要连接加密方式是[WEP][ESS] (wep加密),wifi名称是name,wifi密码是wep_key0

wpa_cli -iwlan0 -p /var/run/wpa_supplicant set_network 0 ssid '"name"'
wpa_cli -iwlan0 -p /var/run/wpa_supplicant set_network 0 key_mgmt NONE
wpa_cli -iwlan0 -p /var/run/wpa_supplicant set_network 0 wep_key0 '"psk"'

如果要连接加密方式是[ESS] (无加密),wifi名称是name

wpa_cli -iwlan0 -p /var/run/wpa_supplicant set_network 0 ssid '"name"'
wpa_cli -iwlan0 -p /var/run/wpa_supplicant set_network 0 key_mgmt NONE

4.连接网络
wpa_cli -iwlan0 -p /var/run/wpa_supplicant select_network 0
wpa_cli -iwlan0 -p /var/run/wpa_supplicant enable_network 0

5.断开连接
wpa_cli -iwlan0 -p /var/run/wpa_supplicant disable_network 0
wpa_cli -iwlan0 -p /var/run/wpa_supplicant remove_network 0

6.获取IP
可以使用udhcpc自动获取IP也可以手动配置固定IP

udhcpc -i wlan0 -q

ifconfig wlan0 192.168.101.12

三.Master(AP)模式
1.启动hostapd
hostapd是一个用户态用于AP和认证服务器的守护进程,Linux下支持的驱动有:Host AP,madwifi,基于mac80211的驱动

usage: hostapd [-hdBKtv] [-P <PID file>] <configuration file(s)>

options:
   -h   show this usage
   -d   show more debug messages (-dd for even more)
   -B   run daemon in the background
   -P   PID file
   -K   include key data in debug messages
   -t   include timestamps in some debug messages
   -v   show hostapd version

hostapd -d /etc/hostapd.conf -B

hostapd.conf配置文件如下,这个文件中的内容也比较多,但是很多都是默认的,详细的可以看源码中提供的hostapd.conf

##### hostapd configuration file ##############################################
interface=wlan0
ctrl_interface=/var/run/hostapd
ssid=LP_WIFI
channel=6
wpa=2
wpa_passphrase=963852741
#bridge=br0

##### default configuration #######################################
driver=rtl871xdrv
beacon_int=100
hw_mode=g
ieee80211n=1
wme_enabled=1
ht_capab=[SHORT-GI-20][SHORT-GI-40][HT40+]
wpa_key_mgmt=WPA-PSK
wpa_pairwise=CCMP
max_num_sta=8
wpa_group_rekey=8640

开启hostapd让模块工作在AP模式,开启后其他设备能够搜索到该热点,但是无法获取到IP地址,仍然无法连接
此时就需要启动udhcpd服务(这是嵌入式设备上的,PC上应该是dhcp),用于分配IP地址

2.启动udhcpd
该程序在busybox编译的时候可以配置生成的,如果没有则需要编译源码来移植该程序
下载 udhcp-0.9.8.tar.gz
修改Makefile
CROSS_COMPILE=arm-linux
make
即可编译得到udhcpc 和udhcpd
复制源码下的 samples/udhcpd.conf 到ARM板/etc/udhcpd.conf下

基本配置如下,具体上网的IP、DNS这些都在这里修改

# The start and end of the IP lease block

start   192.168.0.20#default: 192.168.0.20
end     192.168.0.254   #default: 192.168.0.254

# The interface that udhcpd will use

interface   wlan0   #default: eth0

#Examles
opt router  192.168.0.1
opt dns 192.168.10.2 192.168.10.10
option  subnet  255.255.255.0
#optwins192.168.10.10
option  dns 129.219.13.81   # appened to above DNS servers for a total of 3
option  domain  local
option  lease   864000  # 10 days of seconds

配置完之后,在板子上执行udhcpd就可以了

udhcpd & 

我写的启动AP服务的脚本:

insmod /opt/vendor/8188eu.ko
sleep 2

ifconfig wlan0 up
ifconfig wlan0 192.168.0.1
hostapd -d /etc/hostapd.conf -B
touch /var/lib/misc/udhcpd.leases
udhcpd &

这里的192.168.0.1 这个IP是等于当前wlan0的IP

四.AP+STA模式
在嵌入式设备中使用时往往是需要WiFi模块既能上网也能做一个热点,可能用于web配置,或者控制一些子模块,就像物联网的一些WiFi芯片ESP32、ESP8266
而且在安卓手机中很多的设备也是同时支持者两种模式的(后期很多厂家给阉割了)
所以WiFi模块同事支持这两种工作模式还是很有必要的

其实也很简单,只需要修改驱动配置文件,重新编译ko文件即可

1.修改驱动程序
修改驱动配置文件

vi include/autoconf.h
找到如下部分,并修改
//#define CONFIG_CONCURRENT_MODE 
#ifdef CONFIG_CONCURRENT_MODE
//#define CONFIG_HWPORT_SWAP//Port0->Sec , Port1 -> Pri
#define CONFIG_RUNTIME_PORT_SWITCH
//#define DBG_RUNTIME_PORT_SWITCH
#define CONFIG_STA_MODE_SCAN_UNDER_AP_MODE
#define CONFIG_TSF_RESET_OFFLOAD// For 2 PORT TSF SYNC.
#endif

修改如下:
#define CONFIG_CONCURRENT_MODE 1
#ifdef CONFIG_CONCURRENT_MODE
    #define CONFIG_HWPORT_SWAP  //Port0->Sec , Port1 ->Pri 
    #define CONFIG_RUNTIME_PORT_SWITCH
    //#define DBG_RUNTIME_PORT_SWITCH
    #define CONFIG_STA_MODE_SCAN_UNDER_AP_MODE
    #define CONFIG_TSF_RESET_OFFLOAD1   // For 2 PORT TSF SYNC.
#endif

重新加载8188eu.ko模块后,内核中就会多一个设备节点wlan1(安卓可能是p2p0),如果没有请使用ifconfig

ifconfig wlan0 up
ifconfig wlan1 up

如果还没有,说明你的驱动文件编译的有问题,还是没有支持共存
在之前AP和STA模式工作的时候都是使用接口wlan0,所以两个模式是不可能共存,要能共存,必须要让内核虚拟出更多的设备节点,其实底层的物理硬件是同一个,这里就是驱动做的事了

2.修改配置文件
当有了wlan1后,我们就让station模式在wlan0上干活,让AP模式在wlan1上工作
所以这里就要修改AP模式的两个配置文件

修改之前使用的两个配置文件,将wlan0修改成wlan1即可
/etc/hostapd.conf
interface=wlan1

/etc/udhcpd.conf
interface   wlan1   #default: eth0

然后脚本也得改改
insmod /opt/vendor/8188eu.ko
sleep 2

ifconfig wlan0 up
ifconfig wlan1 up
ifconfig wlan1 192.168.0.1
hostapd -d /etc/hostapd.conf -B
touch /var/lib/misc/udhcpd.leases
udhcpd &
————————————————

原文链接:https://blog.csdn.net/leumber/article/details/85337891

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值