流程介绍:
wpa_supplicant源程序可以看到两个主要的可执行工具:wpa_supplicant和wpa_cli。wpa_supplicant是核心程序,它和wpa_cli的关系就是服务和客户端的关系:后台运行wpa_supplicant,使用wpa_cli来搜索、设置、和连接网络。
以Realtek的wext接口为例。
wpa_client下行创建socket通过ioctrl控制wifi行为,上行wifi连接断开消息通过netlink发个wpa,对于eapol报文,驱动传递给内核,wpa建立raw socket监听和发送回应的握手报文。
流程图主要代码:
dev->wireless_handlers = (struct iw_handler_def *) &rtl8192cd_iw_handler_def;
const struct iw_handler_def rtl8192cd_iw_handler_def =
{
.standard = (iw_handler *) rtl_iwhandler,
.num_standard = sizeof(rtl_iwhandler) / sizeof(iw_handler),
.private = rtl_private_handler,
.private_args = (struct iw_priv_args *)privtab,
.num_private = sizeof(rtl_private_handler) / sizeof(iw_handler),
.num_private_args = sizeof(privtab) / sizeof(struct iw_priv_args),
};
static const struct file_operations socket_file_ops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.aio_read = sock_aio_read,
.aio_write = sock_aio_write,
.poll = sock_poll,
.unlocked_ioctl = sock_ioctl,
...
filp->f_op->unlocked_ioctl
sock_ioctl
dev_ioctl
wext_handle_ioctl
wext_ioctl_dispatch(net, ifr, cmd, &info,ioctl_standard_call,ioctl_private_call);
wireless_process_ioctl
standard(dev, iwr, cmd, info, handler);
ioctl_standard_call
dev->wireless_handlers
handlers->standard[index];
驱动代码:
wpa和底层驱动接口类型挂接
Z:\sourcecode\7520v3\ap\linux_plat\base\linux\user\zte_apps\wlan\wpa_supplicant-2.6\wpa_supplicant\main.c
main 根据参数确定驱动接口-->wpa_supplicant -Dwext -iwlan0-vxd -c/mnt/jffs2/wifi/wpa_supplicant.conf –dd
wpa_priv_interface_init
wpa_supplicant_run(global)
结构体:
结构体握手包交互:
图片.png一次连接的主要代码:
一次连接的主要代码秘钥交互:
秘钥交互四步握手参考csd: lee244868149/article/details/52743302
bcm或者rda之类的wifi,他们使用的是80211的接口,他们上下行交互靠的都是netlink消息。
wpa_supplicant -iwlan0 -Dnl80211 -c /wifi/wpa_supplicant.conf -O /wifi/wpa_supplicant&
wpa_cli -i wlan0 -p /wifi/wpa_supplicant status
wpa_cli -i wlan0 -p /wifi/wpa_supplicant add_network
wpa_cli -i wlan0 -p /wifi/wpa_supplicant set_network 0 ssid '"XXXXX"'
wpa_cli -i wlan0 -p /wifi/wpa_supplicant set_network 0 key_mgmt WPA-PSK
wpa_cli -i wlan0 -p /wifi/wpa_supplicant set_network 0 proto WPA2
wpa_cli -i wlan0 -p /wifi/wpa_supplicant set_network 0 pairwise CCMP
wpa_cli -i wlan0 -p /wifi/wpa_supplicant set_network 0 psk '"********"'
wpa_cli -i wlan0 -p /wifi/wpa_supplicant set_network 0 scan_ssid 1
wpa_cli -i wlan0 -p /wifi/wpa_supplicant enable_network 0
nl80211.c使用的genetlink.c参考
csd: cuijiyue/article/details/51602314
csd: xpbob/article/details/52415370
wiphy_new(&wl_cfg80211_ops, sizeof(struct wland_cfg80211_info));
nl80211.cgenl_register_family_with_ops(&nl80211_fam, nl80211_ops, ARRAY_SIZE(nl80211_ops));
nl80211_init
net->genl_sock = netlink_kernel_create(net, NETLINK_GENERIC, 0,
genl_rcv, &genl_mutex,
THIS_MODULE);
nlk_sk(sk)->netlink_rcv = input;
static const struct proto_ops netlink_ops = {
.family = PF_NETLINK,
.owner = THIS_MODULE,
.release = netlink_release,
.bind = netlink_bind,
.connect = netlink_connect,
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.getname = netlink_getname,
.poll = datagram_poll,
.ioctl = sock_no_ioctl,
.listen = sock_no_listen,
.shutdown = sock_no_shutdown,
.setsockopt = netlink_setsockopt,
.getsockopt = netlink_getsockopt,
.sendmsg = netlink_sendmsg,
.recvmsg = netlink_recvmsg,
.mmap = sock_no_mmap,
.sendpage = sock_no_sendpage,
};
# 下行命令调用流程
sock_sendmsg
sock->ops->sendmsg
netlink_sendmsg
netlink_unicast
netlink_unicast_kernel
netlink_rcv
genl_rcv
netlink_rcv_skb
genl_rcv_msg
ops->doit(skb, &info);
文 | 力卉编程
网友评论