wpa_supplicant下行接口

Wpa_supplicant提供的下行接口主要用于和kernel(driver)进行通信,下发命令和获取信息。

Wpa_supplicant下行接口主要包括三种重要的接口:

    1.    PF_INET socket接口,主要用于向kernel 发送ioctl命令,控制并获取相应信息。

    2.    PF_NETLINK socket接口,主要用于接收kernel发送上来的event 事件。

    3.    PF_PACKET socket接口,主要用于向driver传递802.1X报文。


在android6.0平台,使用的文件如下:


wpa_supplicant/src/drivers/drivers.c;   wpa_supplicant/src/drivers/driver_nl80211.c


一、定义和初始化:

const struct wpa_driver_ops *const wpa_drivers[] =
{
#ifdef CONFIG_DRIVER_NL80211
	&wpa_driver_nl80211_ops,
#endif /* CONFIG_DRIVER_NL80211 */
#ifdef CONFIG_DRIVER_WEXT
	&wpa_driver_wext_ops,
#endif /* CONFIG_DRIVER_WEXT */
#ifdef CONFIG_DRIVER_HOSTAP
	&wpa_driver_hostap_ops,
#endif /* CONFIG_DRIVER_HOSTAP */
#ifdef CONFIG_DRIVER_BSD
	&wpa_driver_bsd_ops,
#endif /* CONFIG_DRIVER_BSD */
#ifdef CONFIG_DRIVER_OPENBSD
	&wpa_driver_openbsd_ops,
#endif /* CONFIG_DRIVER_OPENBSD */
#ifdef CONFIG_DRIVER_NDIS
	&wpa_driver_ndis_ops,
#endif /* CONFIG_DRIVER_NDIS */
#ifdef CONFIG_DRIVER_WIRED
	&wpa_driver_wired_ops,
#endif /* CONFIG_DRIVER_WIRED */
#ifdef CONFIG_DRIVER_MACSEC_QCA
	&wpa_driver_macsec_qca_ops,
#endif /* CONFIG_DRIVER_MACSEC_QCA */
#ifdef CONFIG_DRIVER_ROBOSWITCH
	&wpa_driver_roboswitch_ops,
#endif /* CONFIG_DRIVER_ROBOSWITCH */
#ifdef CONFIG_DRIVER_ATHEROS
	&wpa_driver_atheros_ops,
#endif /* CONFIG_DRIVER_ATHEROS */
#ifdef CONFIG_DRIVER_NONE
	&wpa_driver_none_ops,
#endif /* CONFIG_DRIVER_NONE */
	NULL
};


注册各个功能函数。

const struct wpa_driver_ops wpa_driver_nl80211_ops = {
	.name = "nl80211",
	.desc = "Linux nl80211/cfg80211",
	.get_bssid = wpa_driver_nl80211_get_bssid,
	.get_ssid = wpa_driver_nl80211_get_ssid,
	.set_key = driver_nl80211_set_key,
	.scan2 = driver_nl80211_scan2,
	.sched_scan = wpa_driver_nl80211_sched_scan,
	.stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
	.get_scan_results2 = wpa_driver_nl80211_get_scan_results,
	.deauthenticate = driver_nl80211_deauthenticate,
	.authenticate = driver_nl80211_authenticate,
	.associate = wpa_driver_nl80211_associate,
	.global_init = nl80211_global_init,
	.global_deinit = nl80211_global_deinit,
	.init2 = wpa_driver_nl80211_init,
	.deinit = driver_nl80211_deinit,
	.get_capa = wpa_driver_nl80211_get_capa,
	.set_operstate = wpa_driver_nl80211_set_operstate,
	.set_supp_port = wpa_driver_nl80211_set_supp_port,
	.set_country = wpa_driver_nl80211_set_country,
	.get_country = wpa_driver_nl80211_get_country,
	.set_ap = wpa_driver_nl80211_set_ap,
	.set_acl = wpa_driver_nl80211_set_acl,
	.if_add = wpa_driver_nl80211_if_add,
	.if_remove = driver_nl80211_if_remove,
	.send_mlme = driver_nl80211_send_mlme,
	.get_hw_feature_data = nl80211_get_hw_feature_data,
	.sta_add = wpa_driver_nl80211_sta_add,
	.sta_remove = driver_nl80211_sta_remove,
	.hapd_send_eapol = wpa_driver_nl80211_hapd_send_eapol,
	.sta_set_flags = wpa_driver_nl80211_sta_set_flags,
	.hapd_init = i802_init,
	.hapd_deinit = i802_deinit,
	.set_wds_sta = i802_set_wds_sta,
	.get_seqnum = i802_get_seqnum,
	.flush = i802_flush,
	.get_inact_sec = i802_get_inact_sec,
	.sta_clear_stats = i802_sta_clear_stats,
	.set_rts = i802_set_rts,
	.set_frag = i802_set_frag,
	.set_tx_queue_params = i802_set_tx_queue_params,
	.set_sta_vlan = driver_nl80211_set_sta_vlan,
	.sta_deauth = i802_sta_deauth,
	.sta_disassoc = i802_sta_disassoc,
	.read_sta_data = driver_nl80211_read_sta_data,
	.set_freq = i802_set_freq,
	.send_action = driver_nl80211_send_action,
	.send_action_cancel_wait = wpa_driver_nl80211_send_action_cancel_wait,
	.remain_on_channel = wpa_driver_nl80211_remain_on_channel,
	.cancel_remain_on_channel =
	wpa_driver_nl80211_cancel_remain_on_channel,
	.probe_req_report = driver_nl80211_probe_req_report,
	.deinit_ap = wpa_driver_nl80211_deinit_ap,
	.deinit_p2p_cli = wpa_driver_nl80211_deinit_p2p_cli,
	.resume = wpa_driver_nl80211_resume,
	.signal_monitor = nl80211_signal_monitor,
	.signal_poll = nl80211_signal_poll,
	.send_frame = nl80211_send_frame,
	.set_param = nl80211_set_param,
	.get_radio_name = nl80211_get_radio_name,
	.add_pmkid = nl80211_add_pmkid,
	.remove_pmkid = nl80211_remove_pmkid,
	.flush_pmkid = nl80211_flush_pmkid,
	.set_rekey_info = nl80211_set_rekey_info,
	.poll_client = nl80211_poll_client,
	.set_p2p_powersave = nl80211_set_p2p_powersave,
	.start_dfs_cac = nl80211_start_radar_detection,
	.stop_ap = wpa_driver_nl80211_stop_ap,
#ifdef CONFIG_TDLS
	.send_tdls_mgmt = nl80211_send_tdls_mgmt,
	.tdls_oper = nl80211_tdls_oper,
	.tdls_enable_channel_switch = nl80211_tdls_enable_channel_switch,
	.tdls_disable_channel_switch = nl80211_tdls_disable_channel_switch,
#endif /* CONFIG_TDLS */
	.update_ft_ies = wpa_driver_nl80211_update_ft_ies,
	.get_mac_addr = wpa_driver_nl80211_get_macaddr,
	.get_survey = wpa_driver_nl80211_get_survey,
	.status = wpa_driver_nl80211_status,
	.switch_channel = nl80211_switch_channel,
#ifdef ANDROID_P2P
	.set_noa = wpa_driver_set_p2p_noa,
	.get_noa = wpa_driver_get_p2p_noa,
	.set_ap_wps_ie = wpa_driver_set_ap_wps_p2p_ie,
#endif /* ANDROID_P2P */
#ifdef ANDROID
#ifndef ANDROID_LIB_STUB
	.driver_cmd = wpa_driver_nl80211_driver_cmd,
#endif /* !ANDROID_LIB_STUB */
#endif /* ANDROID */
	.vendor_cmd = nl80211_vendor_cmd,
	.set_qos_map = nl80211_set_qos_map,
	.set_wowlan = nl80211_set_wowlan,
	.roaming = nl80211_roaming,
	.set_mac_addr = nl80211_set_mac_addr,
#ifdef CONFIG_MESH
	.init_mesh = wpa_driver_nl80211_init_mesh,
	.join_mesh = wpa_driver_nl80211_join_mesh,
	.leave_mesh = wpa_driver_nl80211_leave_mesh,
#endif /* CONFIG_MESH */
	.br_add_ip_neigh = wpa_driver_br_add_ip_neigh,
	.br_delete_ip_neigh = wpa_driver_br_delete_ip_neigh,
	.br_port_set_attr = wpa_driver_br_port_set_attr,
	.br_set_net_param = wpa_driver_br_set_net_param,
	.add_tx_ts = nl80211_add_ts,
	.del_tx_ts = nl80211_del_ts,
	.do_acs = wpa_driver_do_acs,
	.set_band = nl80211_set_band,
};

二、使用

上面注册后,从各个函数的名字上就能看出各个函数的功能;

    例如:当wpa_supplicant需要认证时,把处理过后的密码从下面函数送入驱动层;


static int driver_nl80211_set_key(const char *ifname, void *priv,
				  enum wpa_alg alg, const u8 *addr,
				  int key_idx, int set_tx,
				  const u8 *seq, size_t seq_len,
				  const u8 *key, size_t key_len)
{
	struct i802_bss *bss = priv;

	wpa_printf(MSG_DEBUG, "zsm %s", __FUNCTION__);

	return wpa_driver_nl80211_set_key(ifname, bss, alg, addr, key_idx,
					  set_tx, seq, seq_len, key, key_len);
}

进而调用函数 wpa_driver_nl80211_set_key();  从这个函数可以打印出向下传送的是什么数据;只是已经是经过处理后的密码;因此看不出什么来。

static int wpa_driver_nl80211_set_key(const char *ifname, struct i802_bss *bss,
				      enum wpa_alg alg, const u8 *addr,
				      int key_idx, int set_tx,
				      const u8 *seq, size_t seq_len,
				      const u8 *key, size_t key_len)
{
	struct wpa_driver_nl80211_data *drv = bss->drv;
	int ifindex;
	struct nl_msg *msg = NULL;
	int ret;
	int tdls = 0;
	char key_buf[30]= {0};
	char kk;

	/* Ignore for P2P Device */
	if (drv->nlmode == NL80211_IFTYPE_P2P_DEVICE)
		return 0;

	ifindex = if_nametoindex(ifname);
	wpa_printf(MSG_DEBUG, "zsm %s: ifindex=%d (%s) alg=%d addr=%p key_idx=%d "
		   "set_tx=%d seq_len=%lu key_len=%lu",
		   __func__, ifindex, ifname, alg, addr, key_idx, set_tx,
		   (unsigned long) seq_len, (unsigned long) key_len);

	memcpy(key_buf, key, key_len);
	key_buf[key_len] = '\0';
	wpa_printf(MSG_DEBUG, "zsm key =");

	for(kk = 0; kk < key_len+2; kk++)
	{
		wpa_printf(MSG_DEBUG, "%x", key_buf[kk]);
	}

#ifdef CONFIG_TDLS
	if (key_idx == -1) {
		key_idx = 0;
		tdls = 1;
	}
#endif /* CONFIG_TDLS */

	if (alg == WPA_ALG_PMK &&
	    (drv->capa.flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) {
		wpa_printf(MSG_DEBUG, "%s: calling issue_key_mgmt_set_key",
			   __func__);
		ret = issue_key_mgmt_set_key(drv, key, key_len);
		return ret;
	}

	if (alg == WPA_ALG_NONE) {
		msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_DEL_KEY);
		if (!msg)
			return -ENOBUFS;
	} else {
		u32 suite;

		suite = wpa_alg_to_cipher_suite(alg, key_len);
		if (!suite)
			goto fail;
		msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_NEW_KEY);
		if (!msg ||
		    nla_put(msg, NL80211_ATTR_KEY_DATA, key_len, key) ||
		    nla_put_u32(msg, NL80211_ATTR_KEY_CIPHER, suite))
			goto fail;
		wpa_hexdump_key(MSG_DEBUG, "nl80211: KEY_DATA", key, key_len);
	}

	if (seq && seq_len) {
		if (nla_put(msg, NL80211_ATTR_KEY_SEQ, seq_len, seq))
			goto fail;
		wpa_hexdump(MSG_DEBUG, "nl80211: KEY_SEQ", seq, seq_len);
	}

	if (addr && !is_broadcast_ether_addr(addr)) {
		wpa_printf(MSG_DEBUG, "   addr=" MACSTR, MAC2STR(addr));
		if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr))
			goto fail;

		if (alg != WPA_ALG_WEP && key_idx && !set_tx) {
			wpa_printf(MSG_DEBUG, "   RSN IBSS RX GTK");
			if (nla_put_u32(msg, NL80211_ATTR_KEY_TYPE,
					NL80211_KEYTYPE_GROUP))
				goto fail;
		}
	} else if (addr && is_broadcast_ether_addr(addr)) {
		struct nlattr *types;

		wpa_printf(MSG_DEBUG, "   broadcast key");

		types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
		if (!types ||
		    nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
			goto fail;
		nla_nest_end(msg, types);
	}
	if (nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx))
		goto fail;

	ret = send_and_recv_msgs(drv, msg, NULL, key ? (void *) -1 : NULL);
	if ((ret == -ENOENT || ret == -ENOLINK) && alg == WPA_ALG_NONE)
		ret = 0;
	if (ret)
		wpa_printf(MSG_DEBUG, "nl80211: set_key failed; err=%d %s)",
			   ret, strerror(-ret));

	/*
	 * If we failed or don't need to set the default TX key (below),
	 * we're done here.
	 */
	if (ret || !set_tx || alg == WPA_ALG_NONE || tdls)
		return ret;
	if (is_ap_interface(drv->nlmode) && addr &&
	    !is_broadcast_ether_addr(addr))
		return ret;

	msg = nl80211_ifindex_msg(drv, ifindex, 0, NL80211_CMD_SET_KEY);
	if (!msg ||
	    nla_put_u8(msg, NL80211_ATTR_KEY_IDX, key_idx) ||
	    nla_put_flag(msg, (alg == WPA_ALG_IGTK ||
			       alg == WPA_ALG_BIP_GMAC_128 ||
			       alg == WPA_ALG_BIP_GMAC_256 ||
			       alg == WPA_ALG_BIP_CMAC_256) ?
			 NL80211_ATTR_KEY_DEFAULT_MGMT :
			 NL80211_ATTR_KEY_DEFAULT))
		goto fail;
	if (addr && is_broadcast_ether_addr(addr)) {
		struct nlattr *types;

		types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
		if (!types ||
		    nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_MULTICAST))
			goto fail;
		nla_nest_end(msg, types);
	} else if (addr) {
		struct nlattr *types;

		types = nla_nest_start(msg, NL80211_ATTR_KEY_DEFAULT_TYPES);
		if (!types ||
		    nla_put_flag(msg, NL80211_KEY_DEFAULT_TYPE_UNICAST))
			goto fail;
		nla_nest_end(msg, types);
	}

	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
	if (ret == -ENOENT)
		ret = 0;
	if (ret)
		wpa_printf(MSG_DEBUG, "nl80211: set_key default failed; "
			   "err=%d %s)", ret, strerror(-ret));
	return ret;

fail:
	nl80211_nlmsg_clear(msg);
	nlmsg_free(msg);
	return -ENOBUFS;
}

在链接AP过程中,如果没有曾经链接过,则需要wifi apk部分传入用户ap的密码;然后通过命令传入wpa_supplicant,在wpa_supplicant里面进行处理,然后通过上面函数传入底层驱动;在传到driver的时候,会传输两次,至于为什么,我还不清楚。

例如:当用户AP密码是”87654321“ 时, wpa_supplicant向下传输的数据是:

D wpa_supplicant: zsm wpa_driver_nl80211_set_key: ifindex=3 (wlan0) alg=3 addr=0xb6a941dc key_idx=0 set_tx=1 seq_len=6 key_len=16
D wpa_supplicant: zsm key = 3c 6d a6 ea 73 e5 55 03 8f c4 dd f1 5f c3 93 70
   ... ...
D wpa_supplicant: zsm wpa_driver_nl80211_set_key: ifindex=3 (wlan0) alg=3 addr=0x7f627e0a key_idx=1 set_tx=0 seq_len=6 key_len=16
D wpa_supplicant: zsm key = 4b 00 e2 72 6d 04 62 de 5c a3 23 6a 47 9a 72 23

当断开连接时,会传输三次密码为空的数据,如下:

D wpa_supplicant: wpa_driver_nl80211_set_key: ifindex=3 (wlan0) alg=0 addr=0x0 key_idx=0 set_tx=0 seq_len=0 key_len=0
D wpa_supplicant: key =
D wpa_supplicant: wpa_driver_nl80211_set_key: ifindex=3 (wlan0) alg=0 addr=0x0 key_idx=1 set_tx=0 seq_len=0 key_len=0
D wpa_supplicant: key =
D wpa_supplicant: wpa_driver_nl80211_set_key: ifindex=3 (wlan0) alg=0 addr=0xb6af50b8 key_idx=0 set_tx=0 seq_len=0 key_len=0
D wpa_supplicant: key =


当重新链接时,因为密码已经保存,所以不需要apk输入密码,wpa_supplicant会从conf文件里读取密码,进行处理后,直接发送到底层driver;也是发送两次,只是在密码不变的情况下,第一个数据会有变化,但第二个数据始终不变,和输入的密码对应。如下:


D wpa_supplicant: zsm wpa_driver_nl80211_set_key: ifindex=3 (wlan0) alg=3 addr=0xb6a941dc key_idx=0 set_tx=1 seq_len=6 key_len=16
D wpa_supplicant: zsm key = 4c 89 b5 b4 58 44 a1 28 ff f1 2f fb fb 99 84 1a
   ... ...
D wpa_supplicant: zsm wpa_driver_nl80211_set_key: ifindex=3 (wlan0) alg=3 addr=0x7f627e0a key_idx=1 set_tx=0 seq_len=6 key_len=16
D wpa_supplicant: zsm key = 4b 00 e2 72 6d 04 62 de 5c a3 23 6a 47 9a 72 23



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值