linux WPA_supplicant

1.wpa_supplicant软件架构分析
https://www.cnblogs.com/oracleloyal/p/5564786.html
2.wpa_supplicant-2.6移植
2.1libnl-1.1.4
(1)source code:
https://pan.baidu.com/s/1mwni0CtOFA7tcPJFGg3F7Q
(2)解压
$sudo tar -xvf *.gz
(3)$sudo mkdir build.sh
##################################################
export PATH=$PATH:/opt/Embedsky/gcc-4.6.2-glibc-2.13-linaro-multilib-2011.12/tq-linaro-toolchain/bin
export AR=arm-none-gnueabi-ar LD=arm-none-linux-gnueabi-ld
./configure --host=arm-none-linux-gnueabi- CC=arm-none-linux-gnueabi-gcc --prefix=/home/jason/E9/wpa/package/out   //这条命令自动生成Makefile 文件,需要重新配置,直接删除Makefile 再./configure即可
#make CC=arm-none-linux-gnueabi-gcc AR=arm-none-linux-gnueabi-ar LD=arm-none-linux-gnueabi-ld
make
make install
##################################################
(4)out
/wpa/package/out/lib$ ls
libnl.a  libnl.so  libnl.so.1  libnl.so.1.1.4  pkgconfig


2.2openssl-1.0.1s
(1)source code
https://pan.baidu.com/s/1h1vsm9y4-EbtVyMV8Gfw1Q
(2)解压
$sudo tar -xvf *.gz
(3)$sudo mkdir build.sh
================================
export PATH=$PATH:/opt/Embedsky/gcc-4.6.2-glibc-2.13-linaro-multilib-2011.12/tq-linaro-toolchain/bin
./config no-asm --cross-compile-prefix=arm-none-linux-gnueabi-   --prefix=/home/jason/E9/wpa/package/out
#./Configure no-asm  --cross-compile-prefix=arm-none-linux-gnueabi-   --prefix=/home/jason/E9/wpa/package/out
make
make install
================================


Problem:

Solution: 
step1:Remove the all "-m64" of Makefile
step2: remove line ./config in build.sh
step3: sudo ./build.sh
 //make again,don't run ./config no-asm --cross-compile-prefix=arm-none-linux-gnueabi-   --prefix=/home/jason/E9/wpa/package/out anymore

Note: after remove "-m64" of Makefile,don't run ./config anymore,otherwise "-m64" issue can't be solved

(4)out


2.3wpa_supplicant-2.6
(1)source code
https://w1.fi/releases/
(2)解压
$sudo tar -xvf *.gz
(3)编译
step1: $sudo cp defconfig .config
step2: 修改.config文件
# Additional directories for cross-compilation on Linux host for mingw target
CFLAGS += -I/home/jason/E9/wpa/package/out/include
LIBS += -L/home/jason/E9/wpa/package/out/lib
CC=arm-none-linux-gnueabi-gcc
AR=arm-none-gnueabi-ar
LD=arm-none-linux-gnueabi-ld
step3: 
export ARCH=arm
export PATH=$PATH:/opt/Embedsky/gcc-4.6.2-glibc-2.13-linaro-multilib-2011.12/tq-linaro-toolchain/bin/
make 

Problem:
/wpa/package/out/lib/libnl.a: could not read symbols: File in wrong format
Solve:
add -ldl to Makefile

3.部署文件到目标板
3.1 cp wpa_cli/wpa_supplicant/wpa_passphrase 到目标板 usr/sbin
3.2 cp libnl.so.1 到目标板 lib/
3.3 cp libgcc_s.so.1到目标板 lib/ 

4.应用

问题1:
# wpa_supplicant -D nl80211 -i mlan0 -c /etc/wpa_supplicant.conf

Successfully initialized wpa_supplicant

nl80211: deinit ifname=mlan0 disabled_11b_rates=0

mlan0: Failed to initialize driver interface
# wpa_supplicant -D wext -i mlan0 -c /etc/wpa_supplicant.conf

Successfully initialized wpa_supplicant

rfkill: Cannot get wiphy information

wlan: SCAN COMPLETED: scanned AP count=0

ioctl[SIOCSIWESSID]: Bad address

mkdir[ctrl_interface=/var/run/wpa_supplicant]: No such file or directory

Failed to initialize control interface '/var/run/wpa_supplicant'.
解决1:
(1)要建立文件/var/run/wpa_supplicant    在etc/wpa_supplicant.conf有指定wpa_cli的文件夹
(2)驱动不对, nl80211找不到,要用wext驱动

 

===========================代码架构==============================
1.主线
wpa_supplicant是一个单线程的运行方式,靠事件event驱动,eloop_run()主循环通过select的方式不断监控不同事件event的变化相应调用处函数.

2.重要结构体
2.1 wpa_interface:  Parameters for wpa_supplicant_add_iface() 与网口有关
2.2 wpa_params:    Parameters for wpa_supplicant_init()  与wpa_supplicant -imlan0 -Dnl80211 ....命令的传入参数有关
2.3 wpa_global:      Internal, global data for all %wpa_supplicant interfaces
2.4 wpa_supplicant:
2.5 l2_packet_data

3.初始化
3.1wpa_supplicant_init
      3.1.1 eap_register_methods
      3.1.2 eloop_init
                初始化主线程eloop_data结构体,主要是通过各种事件event驱动,各类事件如下
     (1)socket 事件
         不同的socket事件通过放到fd_table里进行select监控.
          如:priv->sock,netlink->sock,global->nl_event,l2->fd
     (2)signal 事件
     (3)timeout 事件   

struct eloop_data {
    int max_sock;
   int count; /* sum of all table counts */
#if defined(CONFIG_ELOOP_EPOLL) || defined(CONFIG_ELOOP_KQUEUE)
    int max_fd;
    struct eloop_sock *fd_table;  
#endif /* CONFIG_ELOOP_EPOLL || CONFIG_ELOOP_KQUEUE */   
    struct eloop_sock_table readers;     //socket event
    struct eloop_sock_table writers;
    struct eloop_sock_table exceptions;

    struct dl_list timeout;     //time event 

    int signal_count;           //signal event
    struct eloop_signal *signals;
}; 

    3.1.3 wpa_supplicant_global_ctrl_iface_init()
            (1)wpas_global_ctrl_iface_open_sock() 
                     eloop_register_read_sock(priv->sock,wpa_supplicant_global_ctrl_iface_receive,global, priv);
              创建wpa server并将此socket放到fd_table里进行select监控同时注册接收函数wpa_supplicant_global_ctrl_iface_receive
               即wpa_cli发的命令都是通过此接受函数处理.
           (2)wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
               注册wpa_server的发送函数wpa_supplicant_ctrl_iface_msg_cb最终调用wpa_supplicant_ctrl_iface_send函数
               即wpa_server发送数据给wpa_cli

3.2 wpa_supplicant_add_iface  
       3.2.1wpa_supplicant_init_iface   //very important
               (1)wpa_config_read(wpa_s->confname, NULL);     //read file  /etc/wpa_supplicant.conf 
                       wpas_init_driver(wpa_s, iface) 
                             wpa_supplicant_set_driver    
                                     global->drv_priv[i] = wpa_drivers[i]->global_init(global);      // wpa_driver_nl80211_ops={}
                                             .global_init = nl80211_global_init,
nl80211_global_init 创建3种不同类型的socket, 1.rtnetlinks socket 2. generic netlink socket 3. ictrl socket,用于与kernel交互.
1. rknetlink类型,用来处理网卡的路由,如新建,删除。
    >netlink_init->netlink->sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);       //NETLINK_ROUTE
    >eloop_register_read_sock(netlink->sock, netlink_receive, netlink,NULL);     -->wpa_driver_nl80211_event_rtm_newlink()
     建立了netlink->sock并注册了来自kernel事件的接收函数同是将此socket放到eloop fd_table里select监控

2. generic netlink类型: 创建了连个socket,一个收,一个发。收的socket对应的回调函数过程是wpa_driver_nl80211_event_receive() -> process_global_event(),而发的handler根据命令的不同而不同。
>global->nl = nl_create_handle(global->nl_cb, "nl");
>global->nl_event = nl_create_handle(global->nl_cb, "event");
>nl_cb_set(global->nl_cb, NL_CB_VALID, NL_CB_CUSTOM,process_global_event, global);
>nl80211_register_eloop_read(&global->nl_event,wpa_driver_nl80211_event_receive,global->nl_cb);
将socket "global->nl_event" 放到eloop fd_table里select监控,并注册接收函数
wpa_driver_nl80211_event_receive()->process_global_event()
nl80211主要是通过发不同的命令cmd给到kernel的nl80211_cmd_msg,process_global_event()会接受cmd并调用不同处理函数

3. ioctl socket: 用来控制网口的up/down, 获取和设置hwaddr。
>global->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
int linux_set_iface_flags(int sock, const char *ifname, int dev_up);
int linux_iface_up(int sock, const char *ifname);
int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr);
int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr);
int linux_br_add(int sock, const char *brname);
int linux_br_del(int sock, const char *brname);
int linux_br_add_if(int sock, const char *brname, const char *ifname);
int linux_br_del_if(int sock, const char *brname, const char *ifname);
int linux_br_get(char *brname, const char *ifname); 

       (2)wpa_supplicant_init_wpa
              l2_packet_init()                  //L2 packet 
                     l2->fd = socket(PF_PACKET, l2_hdr ? SOCK_RAW : SOCK_DGRAM,htons(protocol));
                     ioctl(l2->fd, SIOCGIFINDEX, &ifr) 
                     ioctl(l2->fd, SIOCGIFHWADDR, &ifr)
                     eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);
      L2 packet主要通过ioctrl控制,注册了回调函数l2_packet_receive并放到eloop fd_table去select监控
      l2_packet_receive->wpa_supplicant_rx_eapol

3.3wpa_supplicant_run
            eloop_run
    主线程,程序不断循环监控以上所说的几种类型的事件的变化来相应处理.                
                                                    
               
      
     

               

猜你喜欢

转载自blog.csdn.net/fanxianchao_2012/article/details/102793490