|
|
@@ -0,0 +1,2722 @@
|
|
|
+diff --git a/hostapd/main.c b/hostapd/main.c
|
|
|
+index 2c8dbd3..9c12191 100644
|
|
|
+--- a/hostapd/main.c
|
|
|
++++ b/hostapd/main.c
|
|
|
+@@ -448,7 +448,7 @@ static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize,
|
|
|
+ static void show_version(void)
|
|
|
+ {
|
|
|
+ fprintf(stderr,
|
|
|
+- "hostapd v" VERSION_STR "\n"
|
|
|
++ "hostapd v" VERSION_STR " for Realtek rtl871xdrv\n"
|
|
|
+ "User space daemon for IEEE 802.11 AP management,\n"
|
|
|
+ "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n"
|
|
|
+ "Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> "
|
|
|
+diff --git a/src/ap/beacon.c b/src/ap/beacon.c
|
|
|
+index 233320d..49b5b1e 100644
|
|
|
+--- a/src/ap/beacon.c
|
|
|
++++ b/src/ap/beacon.c
|
|
|
+@@ -1126,6 +1126,11 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd,
|
|
|
+
|
|
|
+ tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
|
|
|
+ tailpos = hostapd_eid_ht_operation(hapd, tailpos);
|
|
|
++
|
|
|
++ //DRIVER_RTW ADD
|
|
|
++ if(hapd->iconf->ieee80211n)
|
|
|
++ hapd->conf->wmm_enabled = 1;
|
|
|
++
|
|
|
+ #endif /* CONFIG_IEEE80211N */
|
|
|
+
|
|
|
+ tailpos = hostapd_eid_ext_capab(hapd, tailpos);
|
|
|
+diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c
|
|
|
+index 16887ac..aa1f572 100644
|
|
|
+--- a/src/ap/hw_features.c
|
|
|
++++ b/src/ap/hw_features.c
|
|
|
+@@ -496,7 +496,10 @@ static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
|
|
|
+ iface->num_ht40_scan_tries = 1;
|
|
|
+ eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL);
|
|
|
+ eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL);
|
|
|
+- return 1;
|
|
|
++
|
|
|
++ //DRIVER_RTW Modify
|
|
|
++ //return -1;
|
|
|
++ return 0;//ignore this error
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ret < 0) {
|
|
|
+diff --git a/src/drivers/driver.h b/src/drivers/driver.h
|
|
|
+index a449cc9..3b9629c 100644
|
|
|
+--- a/src/drivers/driver.h
|
|
|
++++ b/src/drivers/driver.h
|
|
|
+@@ -4984,5 +4984,8 @@ extern const struct wpa_driver_ops wpa_driver_atheros_ops;
|
|
|
+ #ifdef CONFIG_DRIVER_NONE
|
|
|
+ extern const struct wpa_driver_ops wpa_driver_none_ops; /* driver_none.c */
|
|
|
+ #endif /* CONFIG_DRIVER_NONE */
|
|
|
++#ifdef CONFIG_DRIVER_RTW
|
|
|
++extern const struct wpa_driver_ops wpa_driver_rtw_ops; /* driver_rtw.c */
|
|
|
++#endif /* CONFIG_DRIVER_RTW */
|
|
|
+
|
|
|
+ #endif /* DRIVER_H */
|
|
|
+diff --git a/src/drivers/driver_bsd.c b/src/drivers/driver_bsd.c
|
|
|
+index 2afd7df..0bd7fb2 100644
|
|
|
+--- a/src/drivers/driver_bsd.c
|
|
|
++++ b/src/drivers/driver_bsd.c
|
|
|
+@@ -56,6 +56,12 @@ struct bsd_driver_global {
|
|
|
+ struct dl_list ifaces; /* list of interfaces */
|
|
|
+ };
|
|
|
+
|
|
|
++#ifdef HOSTAPD
|
|
|
++#ifdef CONFIG_SUPPORT_RTW_DRIVER
|
|
|
++#define RTW_BSD_HOSTAPD_SET_BEACON (1100)
|
|
|
++#endif
|
|
|
++#endif
|
|
|
++
|
|
|
+ struct bsd_driver_data {
|
|
|
+ struct dl_list list;
|
|
|
+ struct bsd_driver_global *global;
|
|
|
+@@ -846,6 +852,296 @@ handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
|
|
|
+ drv_event_eapol_rx(drv->hapd, src_addr, buf, len);
|
|
|
+ }
|
|
|
+
|
|
|
++#ifdef CONFIG_SUPPORT_RTW_DRIVER
|
|
|
++static int rtw_set_beacon_ops(void *priv, const u8 *head, size_t head_len,
|
|
|
++ const u8 *tail, size_t tail_len, int dtim_period,
|
|
|
++ int beacon_int)
|
|
|
++{
|
|
|
++ int ret=0;
|
|
|
++ u8 *pbuf;
|
|
|
++ size_t sz;
|
|
|
++ struct bsd_driver_data *drv = priv;
|
|
|
++
|
|
|
++ if((head_len<24) ||(!head))
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ sz = head_len+tail_len - 24; // 24 = wlan hdr
|
|
|
++
|
|
|
++ printf("%s, beacon_sz=%d\n", __func__, sz);
|
|
|
++
|
|
|
++ pbuf = os_zalloc(sz);
|
|
|
++ if (pbuf == NULL) {
|
|
|
++ return -ENOMEM;
|
|
|
++ }
|
|
|
++
|
|
|
++ os_memcpy(pbuf, (head+24), (head_len-24));// 24=beacon header len.
|
|
|
++
|
|
|
++ os_memcpy(&pbuf[head_len-24], tail, tail_len);
|
|
|
++
|
|
|
++ ret = set80211var(drv, RTW_BSD_HOSTAPD_SET_BEACON, pbuf, sz);
|
|
|
++
|
|
|
++ os_free(pbuf);
|
|
|
++
|
|
|
++ return ret;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++static struct hostapd_hw_modes *rtw_get_hw_feature_data_ops(
|
|
|
++ void *priv, u16 *num_modes, u16 *flags)
|
|
|
++{
|
|
|
++
|
|
|
++#define MAX_NUM_CHANNEL (14)
|
|
|
++#define MAX_NUM_CHANNEL_5G (24)
|
|
|
++
|
|
|
++ struct hostapd_hw_modes *modes;
|
|
|
++ size_t i;
|
|
|
++ int k;
|
|
|
++
|
|
|
++ printf("%s\n", __func__);
|
|
|
++
|
|
|
++ *num_modes = 3;
|
|
|
++ *flags = 0;
|
|
|
++
|
|
|
++ modes = os_zalloc(*num_modes * sizeof(struct hostapd_hw_modes));
|
|
|
++ if (modes == NULL)
|
|
|
++ return NULL;
|
|
|
++
|
|
|
++ //.1
|
|
|
++ modes[0].mode = HOSTAPD_MODE_IEEE80211G;
|
|
|
++ modes[0].num_channels = MAX_NUM_CHANNEL;
|
|
|
++ modes[0].num_rates = 12;
|
|
|
++ modes[0].channels =
|
|
|
++ os_zalloc(MAX_NUM_CHANNEL * sizeof(struct hostapd_channel_data));
|
|
|
++ modes[0].rates = os_zalloc(modes[0].num_rates * sizeof(int));
|
|
|
++ if (modes[0].channels == NULL || modes[0].rates == NULL)
|
|
|
++ goto fail;
|
|
|
++ for (i = 0; i < MAX_NUM_CHANNEL; i++) {
|
|
|
++ modes[0].channels[i].chan = i + 1;
|
|
|
++ modes[0].channels[i].freq = 2412 + 5 * i;
|
|
|
++ modes[0].channels[i].flag = 0;
|
|
|
++ if (i >= 13)
|
|
|
++ modes[0].channels[i].flag = HOSTAPD_CHAN_DISABLED;
|
|
|
++ }
|
|
|
++ modes[0].rates[0] = 10;
|
|
|
++ modes[0].rates[1] = 20;
|
|
|
++ modes[0].rates[2] = 55;
|
|
|
++ modes[0].rates[3] = 110;
|
|
|
++ modes[0].rates[4] = 60;
|
|
|
++ modes[0].rates[5] = 90;
|
|
|
++ modes[0].rates[6] = 120;
|
|
|
++ modes[0].rates[7] = 180;
|
|
|
++ modes[0].rates[8] = 240;
|
|
|
++ modes[0].rates[9] = 360;
|
|
|
++ modes[0].rates[10] = 480;
|
|
|
++ modes[0].rates[11] = 540;
|
|
|
++
|
|
|
++
|
|
|
++ //.2
|
|
|
++ modes[1].mode = HOSTAPD_MODE_IEEE80211B;
|
|
|
++ modes[1].num_channels = MAX_NUM_CHANNEL;
|
|
|
++ modes[1].num_rates = 4;
|
|
|
++ modes[1].channels =
|
|
|
++ os_zalloc(MAX_NUM_CHANNEL * sizeof(struct hostapd_channel_data));
|
|
|
++ modes[1].rates = os_zalloc(modes[1].num_rates * sizeof(int));
|
|
|
++ if (modes[1].channels == NULL || modes[1].rates == NULL)
|
|
|
++ goto fail;
|
|
|
++ for (i = 0; i < MAX_NUM_CHANNEL; i++) {
|
|
|
++ modes[1].channels[i].chan = i + 1;
|
|
|
++ modes[1].channels[i].freq = 2412 + 5 * i;
|
|
|
++ modes[1].channels[i].flag = 0;
|
|
|
++ if (i >= 11)
|
|
|
++ modes[1].channels[i].flag = HOSTAPD_CHAN_DISABLED;
|
|
|
++ }
|
|
|
++ modes[1].rates[0] = 10;
|
|
|
++ modes[1].rates[1] = 20;
|
|
|
++ modes[1].rates[2] = 55;
|
|
|
++ modes[1].rates[3] = 110;
|
|
|
++
|
|
|
++
|
|
|
++ //.3
|
|
|
++ modes[2].mode = HOSTAPD_MODE_IEEE80211A;
|
|
|
++#ifdef CONFIG_DRIVER_RTL_DFS
|
|
|
++ modes[2].num_channels = MAX_NUM_CHANNEL_5G;
|
|
|
++#else /* CONFIG_DRIVER_RTL_DFS */
|
|
|
++ modes[2].num_channels = 9;
|
|
|
++#endif /* CONFIG_DRIVER_RTL_DFS */
|
|
|
++
|
|
|
++ modes[2].num_rates = 8;
|
|
|
++ modes[2].channels = os_zalloc(modes[2].num_channels * sizeof(struct hostapd_channel_data));
|
|
|
++ modes[2].rates = os_zalloc(modes[2].num_rates * sizeof(int));
|
|
|
++ if (modes[2].channels == NULL || modes[2].rates == NULL)
|
|
|
++ goto fail;
|
|
|
++
|
|
|
++
|
|
|
++ k = 0;
|
|
|
++ // 5G band1 Channel: 36, 40, 44, 48
|
|
|
++ for (i=0; i < 4; i++) {
|
|
|
++ modes[2].channels[k].chan = 36+(i*4);
|
|
|
++ modes[2].channels[k].freq = 5180+(i*20);
|
|
|
++ modes[2].channels[k].flag = 0;
|
|
|
++ k++;
|
|
|
++ }
|
|
|
++
|
|
|
++#ifdef CONFIG_DRIVER_RTL_DFS
|
|
|
++ // 5G band2 Channel: 52, 56, 60, 64
|
|
|
++ for (i=0; i < 4; i++) {
|
|
|
++ modes[2].channels[k].chan = 52+(i*4);
|
|
|
++ modes[2].channels[k].freq = 5260+(i*20);
|
|
|
++ modes[2].channels[k].flag = 0;
|
|
|
++ k++;
|
|
|
++ }
|
|
|
++
|
|
|
++ // 5G band3 Channel: 100, 104, 108. 112, 116, 120, 124, 128, 132, 136, 140
|
|
|
++ for (i=0; i < 11; i++) {
|
|
|
++ modes[2].channels[k].chan = 100+(i*4);
|
|
|
++ modes[2].channels[k].freq = 5500+(i*20);
|
|
|
++ modes[2].channels[k].flag = 0;
|
|
|
++ k++;
|
|
|
++ }
|
|
|
++#endif /* CONFIG_DRIVER_RTL_DFS */
|
|
|
++
|
|
|
++ // 5G band4 Channel: 149, 153, 157, 161, 165
|
|
|
++ for (i=0; i < 5; i++) {
|
|
|
++ modes[2].channels[k].chan = 149+(i*4);
|
|
|
++ modes[2].channels[k].freq = 5745+(i*20);
|
|
|
++ modes[2].channels[k].flag = 0;
|
|
|
++ k++;
|
|
|
++ }
|
|
|
++
|
|
|
++ modes[2].rates[0] = 60;
|
|
|
++ modes[2].rates[1] = 90;
|
|
|
++ modes[2].rates[2] = 120;
|
|
|
++ modes[2].rates[3] = 180;
|
|
|
++ modes[2].rates[4] = 240;
|
|
|
++ modes[2].rates[5] = 360;
|
|
|
++ modes[2].rates[6] = 480;
|
|
|
++ modes[2].rates[7] = 540;
|
|
|
++
|
|
|
++
|
|
|
++ //
|
|
|
++#if 0
|
|
|
++#define HT_CAP_INFO_LDPC_CODING_CAP ((u16) BIT(0))
|
|
|
++#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET ((u16) BIT(1))
|
|
|
++#define HT_CAP_INFO_SMPS_MASK ((u16) (BIT(2) | BIT(3)))
|
|
|
++#define HT_CAP_INFO_SMPS_STATIC ((u16) 0)
|
|
|
++#define HT_CAP_INFO_SMPS_DYNAMIC ((u16) BIT(2))
|
|
|
++#define HT_CAP_INFO_SMPS_DISABLED ((u16) (BIT(2) | BIT(3)))
|
|
|
++#define HT_CAP_INFO_GREEN_FIELD ((u16) BIT(4))
|
|
|
++#define HT_CAP_INFO_SHORT_GI20MHZ ((u16) BIT(5))
|
|
|
++#define HT_CAP_INFO_SHORT_GI40MHZ ((u16) BIT(6))
|
|
|
++#define HT_CAP_INFO_TX_STBC ((u16) BIT(7))
|
|
|
++#define HT_CAP_INFO_RX_STBC_MASK ((u16) (BIT(8) | BIT(9)))
|
|
|
++#define HT_CAP_INFO_RX_STBC_1 ((u16) BIT(8))
|
|
|
++#define HT_CAP_INFO_RX_STBC_12 ((u16) BIT(9))
|
|
|
++#define HT_CAP_INFO_RX_STBC_123 ((u16) (BIT(8) | BIT(9)))
|
|
|
++#define HT_CAP_INFO_DELAYED_BA ((u16) BIT(10))
|
|
|
++#define HT_CAP_INFO_MAX_AMSDU_SIZE ((u16) BIT(11))
|
|
|
++#define HT_CAP_INFO_DSSS_CCK40MHZ ((u16) BIT(12))
|
|
|
++#define HT_CAP_INFO_PSMP_SUPP ((u16) BIT(13))
|
|
|
++#define HT_CAP_INFO_40MHZ_INTOLERANT ((u16) BIT(14))
|
|
|
++#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT ((u16) BIT(15))
|
|
|
++#endif
|
|
|
++
|
|
|
++ //HOSTAPD_MODE_IEEE80211G
|
|
|
++ modes[0].ht_capab = HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET|HT_CAP_INFO_SHORT_GI20MHZ|
|
|
|
++ HT_CAP_INFO_SHORT_GI40MHZ|HT_CAP_INFO_MAX_AMSDU_SIZE|HT_CAP_INFO_DSSS_CCK40MHZ;
|
|
|
++
|
|
|
++ modes[0].mcs_set[0]= 0xff;
|
|
|
++ modes[0].mcs_set[1]= 0xff;
|
|
|
++
|
|
|
++ //HOSTAPD_MODE_IEEE80211B
|
|
|
++ modes[1].ht_capab = 0;
|
|
|
++
|
|
|
++ //HOSTAPD_MODE_IEEE80211A
|
|
|
++ modes[2].ht_capab = modes[0].ht_capab;
|
|
|
++
|
|
|
++ modes[2].mcs_set[0]= 0xff;
|
|
|
++ modes[2].mcs_set[1]= 0xff;
|
|
|
++
|
|
|
++ return modes;
|
|
|
++
|
|
|
++fail:
|
|
|
++ if (modes) {
|
|
|
++ for (i = 0; i < *num_modes; i++) {
|
|
|
++ os_free(modes[i].channels);
|
|
|
++ os_free(modes[i].rates);
|
|
|
++ }
|
|
|
++ os_free(modes);
|
|
|
++ }
|
|
|
++
|
|
|
++ return NULL;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++#if 0
|
|
|
++#define IEEE80211_FC0_TYPE_MASK 0x0c
|
|
|
++#define IEEE80211_FC0_TYPE_SHIFT 2
|
|
|
++#define IEEE80211_FC0_TYPE_MGT 0x00
|
|
|
++#define IEEE80211_FC0_TYPE_CTL 0x04
|
|
|
++#define IEEE80211_FC0_TYPE_DATA 0x08
|
|
|
++#define IEEE80211_FC0_SUBTYPE_MASK 0xf0
|
|
|
++#define IEEE80211_FC0_SUBTYPE_SHIFT 4
|
|
|
++#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00
|
|
|
++#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10
|
|
|
++#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20
|
|
|
++#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30
|
|
|
++#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40
|
|
|
++#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50
|
|
|
++#define IEEE80211_FC0_SUBTYPE_BEACON 0x80
|
|
|
++#define IEEE80211_FC0_SUBTYPE_ATIM 0x90
|
|
|
++#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0
|
|
|
++#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0
|
|
|
++#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0
|
|
|
++#define IEEE80211_FC0_SUBTYPE_ACTION 0xd0
|
|
|
++#define IEEE80211_FC0_SUBTYPE_ACTION_NOACK 0xe0
|
|
|
++
|
|
|
++#define IEEE80211_APPIE_WPA (IEEE80211_FC0_TYPE_MGT | IEEE80211_FC0_SUBTYPE_BEACON | \
|
|
|
++ IEEE80211_FC0_SUBTYPE_PROBE_RESP)
|
|
|
++
|
|
|
++#endif
|
|
|
++
|
|
|
++#define RTW_IEEE80211_APPIE_BEACON (IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_BEACON)
|
|
|
++#define RTW_IEEE80211_APPIE_PROBE_RESP (IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_PROBE_RESP)
|
|
|
++#define RTW_IEEE80211_APPIE_ASSOC_RESP (IEEE80211_FC0_TYPE_MGT|IEEE80211_FC0_SUBTYPE_ASSOC_RESP)
|
|
|
++
|
|
|
++
|
|
|
++static int rtw_set_wps_assoc_resp_ie(void *priv, const void *ie, size_t len)
|
|
|
++{
|
|
|
++ return bsd_set80211(priv, IEEE80211_IOC_APPIE, RTW_IEEE80211_APPIE_ASSOC_RESP,
|
|
|
++ ie, len);
|
|
|
++}
|
|
|
++
|
|
|
++static int rtw_set_wps_beacon_ie(void *priv, const void *ie, size_t len)
|
|
|
++{
|
|
|
++ return bsd_set80211(priv, IEEE80211_IOC_APPIE, RTW_IEEE80211_APPIE_BEACON,
|
|
|
++ ie, len);
|
|
|
++}
|
|
|
++
|
|
|
++static int rtw_set_wps_probe_resp_ie(void *priv, const void *ie, size_t len)
|
|
|
++{
|
|
|
++ return bsd_set80211(priv, IEEE80211_IOC_APPIE, RTW_IEEE80211_APPIE_PROBE_RESP,
|
|
|
++ ie, len);
|
|
|
++}
|
|
|
++
|
|
|
++static int rtw_set_ap_wps_ie_ops(void *priv, const struct wpabuf *beacon,
|
|
|
++ const struct wpabuf *proberesp, const struct wpabuf *assocresp)
|
|
|
++{
|
|
|
++ if (rtw_set_wps_assoc_resp_ie(priv, assocresp ? wpabuf_head(assocresp) : NULL,
|
|
|
++ assocresp ? wpabuf_len(assocresp) : 0))
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ if (rtw_set_wps_beacon_ie(priv, beacon ? wpabuf_head(beacon) : NULL,
|
|
|
++ beacon ? wpabuf_len(beacon) : 0))
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ return rtw_set_wps_probe_resp_ie(priv,
|
|
|
++ proberesp ? wpabuf_head(proberesp) : NULL,
|
|
|
++ proberesp ? wpabuf_len(proberesp): 0);
|
|
|
++
|
|
|
++}
|
|
|
++#endif
|
|
|
++
|
|
|
++
|
|
|
+ static void *
|
|
|
+ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
|
|
|
+ {
|
|
|
+@@ -887,6 +1183,12 @@ bsd_init(struct hostapd_data *hapd, struct wpa_init_params *params)
|
|
|
+
|
|
|
+ dl_list_add(&drv->global->ifaces, &drv->list);
|
|
|
+
|
|
|
++#ifdef CONFIG_SUPPORT_RTW_DRIVER
|
|
|
++ /* mark up after init */
|
|
|
++ if (bsd_ctrl_iface(drv, 1) < 0)
|
|
|
++ goto bad;
|
|
|
++#endif
|
|
|
++
|
|
|
+ return drv;
|
|
|
+ bad:
|
|
|
+ if (drv->sock_xmit != NULL)
|
|
|
+@@ -1330,6 +1632,15 @@ wpa_driver_bsd_event_receive(int sock, void *ctx, void *sock_ctx)
|
|
|
+ EVENT_MICHAEL_MIC_FAILURE, &event);
|
|
|
+ break;
|
|
|
+ }
|
|
|
++ else{
|
|
|
++ os_strlcpy(event.interface_status.ifname, drv->ifname,
|
|
|
++ sizeof(event.interface_status.ifname));
|
|
|
++ event.interface_status.ievent = EVENT_INTERFACE_ADDED;
|
|
|
++ wpa_printf(MSG_DEBUG, "RTM_IFINFO: Interface '%s' UP",
|
|
|
++ event.interface_status.ifname);
|
|
|
++ wpa_supplicant_event(ctx, EVENT_INTERFACE_STATUS, &event);
|
|
|
++ }
|
|
|
++
|
|
|
+ break;
|
|
|
+ case RTM_IFINFO:
|
|
|
+ ifm = (struct if_msghdr *) rtm;
|
|
|
+@@ -1719,7 +2030,52 @@ bsd_global_deinit(void *priv)
|
|
|
+ os_free(global);
|
|
|
+ }
|
|
|
+
|
|
|
+-
|
|
|
++#ifdef CONFIG_SUPPORT_RTW_DRIVER
|
|
|
++const struct wpa_driver_ops wpa_driver_bsd_ops = {
|
|
|
++ .name = "bsd",
|
|
|
++ .desc = "BSD 802.11 support",
|
|
|
++#ifdef HOSTAPD
|
|
|
++ .hapd_init = bsd_init,
|
|
|
++ .hapd_deinit = bsd_deinit,
|
|
|
++ .set_privacy = bsd_set_privacy,//del ?
|
|
|
++ .get_seqnum = bsd_get_seqnum,//del ?
|
|
|
++ .flush = bsd_flush,
|
|
|
++ .read_sta_data = bsd_read_sta_driver_data,//del ?
|
|
|
++ .sta_disassoc = bsd_sta_disassoc,
|
|
|
++ .sta_deauth = bsd_sta_deauth,
|
|
|
++ .get_hw_feature_data = rtw_get_hw_feature_data_ops,//add
|
|
|
++ //.sta_remove = rtl871x_sta_remove_ops,//add
|
|
|
++ .set_beacon = rtw_set_beacon_ops, //add
|
|
|
++ .set_ap_wps_ie = rtw_set_ap_wps_ie_ops,//add
|
|
|
++#else /* HOSTAPD */
|
|
|
++ .init = wpa_driver_bsd_init,
|
|
|
++ .deinit = wpa_driver_bsd_deinit,
|
|
|
++ .get_bssid = wpa_driver_bsd_get_bssid,
|
|
|
++ .get_ssid = wpa_driver_bsd_get_ssid,
|
|
|
++ .set_countermeasures = wpa_driver_bsd_set_countermeasures,
|
|
|
++ .scan2 = wpa_driver_bsd_scan,
|
|
|
++ .get_scan_results2 = wpa_driver_bsd_get_scan_results2,
|
|
|
++ .deauthenticate = wpa_driver_bsd_deauthenticate,
|
|
|
++ .disassociate = wpa_driver_bsd_disassociate,
|
|
|
++ .associate = wpa_driver_bsd_associate,
|
|
|
++ .get_capa = wpa_driver_bsd_get_capa,
|
|
|
++ .set_freq = bsd_set_freq, //only for wpa_supplicant
|
|
|
++ .set_ieee8021x = bsd_set_ieee8021x,//only for wpa_supplicant
|
|
|
++ .hapd_set_ssid = bsd_set_ssid,//only for wpa_supplicant
|
|
|
++ .hapd_get_ssid = bsd_get_ssid,//only for wpa_supplicant
|
|
|
++ .sta_set_flags = bsd_set_sta_authorized, //only for wpa_supplicant
|
|
|
++ .set_generic_elem = bsd_set_opt_ie, //only for wpa_supplicant
|
|
|
++#endif /* HOSTAPD */
|
|
|
++ //.set_freq = bsd_set_freq, //only for wpa_supplicant
|
|
|
++ .set_key = bsd_set_key,
|
|
|
++ //.set_ieee8021x = bsd_set_ieee8021x, //only for wpa_supplicant
|
|
|
++ //.hapd_set_ssid = bsd_set_ssid, //only for wpa_supplicant
|
|
|
++ //.hapd_get_ssid = bsd_get_ssid, //only for wpa_supplicant
|
|
|
++ .hapd_send_eapol = bsd_send_eapol, //only for wpa_supplicant
|
|
|
++ //.sta_set_flags = bsd_set_sta_authorized, //only for wpa_supplicant
|
|
|
++ //.set_generic_elem = bsd_set_opt_ie, //only for wpa_supplicant
|
|
|
++};
|
|
|
++#else
|
|
|
+ const struct wpa_driver_ops wpa_driver_bsd_ops = {
|
|
|
+ .name = "bsd",
|
|
|
+ .desc = "BSD 802.11 support",
|
|
|
+@@ -1756,3 +2112,4 @@ const struct wpa_driver_ops wpa_driver_bsd_ops = {
|
|
|
+ .hapd_send_eapol = bsd_send_eapol,
|
|
|
+ .set_generic_elem = bsd_set_opt_ie,
|
|
|
+ };
|
|
|
++#endif
|
|
|
+diff --git a/src/drivers/driver_rtl.h b/src/drivers/driver_rtl.h
|
|
|
+new file mode 100644
|
|
|
+index 0000000..c5ee335
|
|
|
+--- /dev/null
|
|
|
++++ b/src/drivers/driver_rtl.h
|
|
|
+@@ -0,0 +1,114 @@
|
|
|
++
|
|
|
++#ifndef _DRIVER_RTL_H_
|
|
|
++#define _DRIVER_RTL_H_
|
|
|
++
|
|
|
++
|
|
|
++#define RTL_IOCTL_HOSTAPD (SIOCIWFIRSTPRIV + 28)
|
|
|
++
|
|
|
++#define IEEE_CRYPT_ALG_NAME_LEN (16)
|
|
|
++
|
|
|
++/* RTL871X_IOCTL_HOSTAPD ioctl() cmd: */
|
|
|
++enum {
|
|
|
++ RTL871X_HOSTAPD_FLUSH = 1,
|
|
|
++ RTL871X_HOSTAPD_ADD_STA = 2,
|
|
|
++ RTL871X_HOSTAPD_REMOVE_STA = 3,
|
|
|
++ RTL871X_HOSTAPD_GET_INFO_STA = 4,
|
|
|
++ /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */
|
|
|
++ RTL871X_HOSTAPD_GET_WPAIE_STA = 5,
|
|
|
++ RTL871X_SET_ENCRYPTION = 6,
|
|
|
++ RTL871X_GET_ENCRYPTION = 7,
|
|
|
++ RTL871X_HOSTAPD_SET_FLAGS_STA = 8,
|
|
|
++ RTL871X_HOSTAPD_GET_RID = 9,
|
|
|
++ RTL871X_HOSTAPD_SET_RID = 10,
|
|
|
++ RTL871X_HOSTAPD_SET_ASSOC_AP_ADDR = 11,
|
|
|
++ RTL871X_HOSTAPD_SET_GENERIC_ELEMENT = 12,
|
|
|
++ RTL871X_HOSTAPD_MLME = 13,
|
|
|
++ RTL871X_HOSTAPD_SCAN_REQ = 14,
|
|
|
++ RTL871X_HOSTAPD_STA_CLEAR_STATS = 15,
|
|
|
++ RTL871X_HOSTAPD_SET_BEACON = 16,
|
|
|
++ RTL871X_HOSTAPD_SET_WPS_BEACON = 17,
|
|
|
++ RTL871X_HOSTAPD_SET_WPS_PROBE_RESP = 18,
|
|
|
++ RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP = 19,
|
|
|
++ RTL871X_HOSTAPD_SET_HIDDEN_SSID = 20,
|
|
|
++};
|
|
|
++
|
|
|
++typedef struct ieee_param {
|
|
|
++ u32 cmd;
|
|
|
++ u8 sta_addr[ETH_ALEN];
|
|
|
++ union {
|
|
|
++ struct {
|
|
|
++ u8 name;
|
|
|
++ u32 value;
|
|
|
++ } wpa_param;
|
|
|
++ struct {
|
|
|
++ u32 len;
|
|
|
++ u8 reserved[32];
|
|
|
++ u8 data[0];
|
|
|
++ } wpa_ie;
|
|
|
++ struct{
|
|
|
++ int command;
|
|
|
++ int reason_code;
|
|
|
++ } mlme;
|
|
|
++ struct {
|
|
|
++ u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
|
|
|
++ u8 set_tx;
|
|
|
++ u32 err;
|
|
|
++ u8 idx;
|
|
|
++ u8 seq[8]; /* sequence counter (set: RX, get: TX) */
|
|
|
++ u16 key_len;
|
|
|
++ u8 key[0];
|
|
|
++ } crypt;
|
|
|
++ struct {
|
|
|
++ u16 aid;
|
|
|
++ u16 capability;
|
|
|
++ int flags;
|
|
|
++ u8 tx_supp_rates[16];
|
|
|
++ //struct ieee80211_ht_capability ht_cap;
|
|
|
++ struct ieee80211_ht_capabilities ht_cap;
|
|
|
++ } add_sta;
|
|
|
++ struct {
|
|
|
++ u8 reserved[2];//for set max_num_sta
|
|
|
++ u8 buf[0];
|
|
|
++ } bcn_ie;
|
|
|
++
|
|
|
++ } u;
|
|
|
++
|
|
|
++} ieee_param;
|
|
|
++
|
|
|
++
|
|
|
++
|
|
|
++#define IEEE80211_CCK_RATE_LEN 4
|
|
|
++#define IEEE80211_OFDM_RATE_LEN 8
|
|
|
++
|
|
|
++#define IEEE80211_CCK_RATE_1MB 0x02
|
|
|
++#define IEEE80211_CCK_RATE_2MB 0x04
|
|
|
++#define IEEE80211_CCK_RATE_5MB 0x0B
|
|
|
++#define IEEE80211_CCK_RATE_11MB 0x16
|
|
|
++#define IEEE80211_OFDM_RATE_6MB 0x0C
|
|
|
++#define IEEE80211_OFDM_RATE_9MB 0x12
|
|
|
++#define IEEE80211_OFDM_RATE_12MB 0x18
|
|
|
++#define IEEE80211_OFDM_RATE_18MB 0x24
|
|
|
++#define IEEE80211_OFDM_RATE_24MB 0x30
|
|
|
++#define IEEE80211_OFDM_RATE_36MB 0x48
|
|
|
++#define IEEE80211_OFDM_RATE_48MB 0x60
|
|
|
++#define IEEE80211_OFDM_RATE_54MB 0x6C
|
|
|
++#define IEEE80211_BASIC_RATE_MASK 0x80
|
|
|
++
|
|
|
++#define IEEE80211_CCK_RATE_1MB_MASK (1<<0)
|
|
|
++#define IEEE80211_CCK_RATE_2MB_MASK (1<<1)
|
|
|
++#define IEEE80211_CCK_RATE_5MB_MASK (1<<2)
|
|
|
++#define IEEE80211_CCK_RATE_11MB_MASK (1<<3)
|
|
|
++#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4)
|
|
|
++#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5)
|
|
|
++#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6)
|
|
|
++#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7)
|
|
|
++#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8)
|
|
|
++#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9)
|
|
|
++#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10)
|
|
|
++#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11)
|
|
|
++
|
|
|
++#define IEEE80211_CCK_RATES_MASK 0x0000000F
|
|
|
++#define IEEE80211_OFDM_RATES_MASK 0x00000FF0
|
|
|
++
|
|
|
++#endif
|
|
|
++
|
|
|
+diff --git a/src/drivers/driver_rtw.c b/src/drivers/driver_rtw.c
|
|
|
+new file mode 100644
|
|
|
+index 0000000..c10b9cc
|
|
|
+--- /dev/null
|
|
|
++++ b/src/drivers/driver_rtw.c
|
|
|
+@@ -0,0 +1,1971 @@
|
|
|
++/*
|
|
|
++ * hostapd / Driver interface for rtl871x driver
|
|
|
++ * Copyright (c) 2010,
|
|
|
++ *
|
|
|
++ * This program is free software; you can redistribute it and/or modify
|
|
|
++ * it under the terms of the GNU General Public License version 2 as
|
|
|
++ * published by the Free Software Foundation.
|
|
|
++ *
|
|
|
++ * Alternatively, this software may be distributed under the terms of BSD
|
|
|
++ * license.
|
|
|
++ *
|
|
|
++ * See README and COPYING for more details.
|
|
|
++ */
|
|
|
++
|
|
|
++//#define CONFIG_MGNT_L2SOCK 1
|
|
|
++#define CONFIG_MLME_OFFLOAD 1
|
|
|
++
|
|
|
++
|
|
|
++#include "includes.h"
|
|
|
++#include <net/if.h>
|
|
|
++#include <sys/ioctl.h>
|
|
|
++
|
|
|
++#include "common.h"
|
|
|
++
|
|
|
++/*#include "wireless_copy.h"*/
|
|
|
++#include "linux_wext.h"
|
|
|
++
|
|
|
++#include "driver.h"
|
|
|
++#include "eloop.h"
|
|
|
++#include "priv_netlink.h"
|
|
|
++#include "l2_packet/l2_packet.h"
|
|
|
++#include "common/ieee802_11_defs.h"
|
|
|
++#include "netlink.h"
|
|
|
++#include "linux_ioctl.h"
|
|
|
++
|
|
|
++//#include "../src/ap/hostapd.h"
|
|
|
++//#include "../src/ap/ap_config.h"
|
|
|
++#include "ap/hostapd.h"
|
|
|
++#include "ap/ap_config.h"
|
|
|
++
|
|
|
++#ifdef USE_KERNEL_HEADERS
|
|
|
++/* compat-wireless does not include linux/compiler.h to define __user, so
|
|
|
++ * define it here */
|
|
|
++#ifndef __user
|
|
|
++#define __user
|
|
|
++#endif /* __user */
|
|
|
++#include <asm/types.h>
|
|
|
++#include <linux/if_packet.h>
|
|
|
++#include <linux/if_ether.h> /* The L2 protocols */
|
|
|
++#include <linux/if_arp.h>
|
|
|
++#include <linux/wireless.h>
|
|
|
++#else /* USE_KERNEL_HEADERS */
|
|
|
++#include <net/if_arp.h>
|
|
|
++#include <netpacket/packet.h>
|
|
|
++//#include "wireless_copy.h"
|
|
|
++#endif /* USE_KERNEL_HEADERS */
|
|
|
++
|
|
|
++//#include <net/if.h>
|
|
|
++
|
|
|
++
|
|
|
++#ifndef ETH_P_80211_RAW
|
|
|
++#define ETH_P_80211_RAW 0x0019
|
|
|
++#endif
|
|
|
++
|
|
|
++#if 0
|
|
|
++#include "hostapd.h"
|
|
|
++#include "driver.h"
|
|
|
++#include "ieee802_1x.h"
|
|
|
++#include "eloop.h"
|
|
|
++#include "priv_netlink.h"
|
|
|
++#include "sta_info.h"
|
|
|
++#include "l2_packet/l2_packet.h"
|
|
|
++
|
|
|
++#include "wpa.h"
|
|
|
++#include "accounting.h"
|
|
|
++#include "ieee802_11.h"
|
|
|
++#include "hw_features.h"
|
|
|
++#include "radius/radius.h"
|
|
|
++#endif
|
|
|
++
|
|
|
++#include "driver_rtl.h"
|
|
|
++
|
|
|
++
|
|
|
++//static int rtl871x_sta_remove_ops(void *priv, const u8 *addr);
|
|
|
++
|
|
|
++struct rtl871x_driver_data {
|
|
|
++ struct hostapd_data *hapd;
|
|
|
++
|
|
|
++ char iface[IFNAMSIZ + 1];
|
|
|
++ int ifindex;
|
|
|
++ struct l2_packet_data *l2_sock;/* socket for sending eapol frames*/
|
|
|
++ struct l2_packet_data *l2_sock_recv;/* raw packet recv socket from bridge interface*/
|
|
|
++#ifdef CONFIG_MGNT_L2SOCK
|
|
|
++ struct l2_packet_data *mgnt_l2_sock; /* socket for tx/rx management frames*/
|
|
|
++#else
|
|
|
++ int mgnt_sock;/* socket for tx/rx management frames*/
|
|
|
++#endif
|
|
|
++ int ioctl_sock; /* socket for ioctl() use */
|
|
|
++ int wext_sock; /* socket for wireless events */
|
|
|
++
|
|
|
++ struct netlink_data *netlink;
|
|
|
++
|
|
|
++ int we_version;
|
|
|
++
|
|
|
++ u8 hw_mac[ETH_ALEN];
|
|
|
++
|
|
|
++ u8 acct_mac[ETH_ALEN];
|
|
|
++
|
|
|
++ struct hostap_sta_driver_data acct_data;
|
|
|
++
|
|
|
++};
|
|
|
++
|
|
|
++/*
|
|
|
++static const char *ether_sprintf(const u8 *addr)
|
|
|
++{
|
|
|
++ static char buf[sizeof(MACSTR)];
|
|
|
++
|
|
|
++ if (addr != NULL)
|
|
|
++ snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
|
|
|
++ else
|
|
|
++ snprintf(buf, sizeof(buf), MACSTR, 0,0,0,0,0,0);
|
|
|
++
|
|
|
++ return buf;
|
|
|
++}
|
|
|
++*/
|
|
|
++
|
|
|
++#ifndef CONFIG_MLME_OFFLOAD
|
|
|
++static int rtl871x_set_iface_flags(void *priv, int dev_up)
|
|
|
++{
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++ struct ifreq ifr;
|
|
|
++
|
|
|
++ wpa_printf(MSG_DEBUG, "%s: dev_up=%d", __func__, dev_up);
|
|
|
++
|
|
|
++ if (drv->mgnt_sock < 0)
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ memset(&ifr, 0, sizeof(ifr));
|
|
|
++ //os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
|
|
|
++ //os_strlcpy(ifr.ifr_name, "mgnt.wlan", IFNAMSIZ);
|
|
|
++ snprintf(ifr.ifr_name, IFNAMSIZ, "mgnt.%s", "wlan0");
|
|
|
++
|
|
|
++ if (ioctl(drv->mgnt_sock, SIOCGIFFLAGS, &ifr) != 0) {
|
|
|
++ perror("ioctl[SIOCGIFFLAGS]");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ if (dev_up)
|
|
|
++ ifr.ifr_flags |= IFF_UP;
|
|
|
++ else
|
|
|
++ ifr.ifr_flags &= ~IFF_UP;
|
|
|
++
|
|
|
++ if (ioctl(drv->mgnt_sock, SIOCSIFFLAGS, &ifr) != 0) {
|
|
|
++ perror("ioctl[SIOCSIFFLAGS]");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++#if 0
|
|
|
++ if (dev_up) {
|
|
|
++ memset(&ifr, 0, sizeof(ifr));
|
|
|
++ os_strlcpy(ifr.ifr_name, drv->iface, IFNAMSIZ);
|
|
|
++ ifr.ifr_mtu = HOSTAPD_MTU;
|
|
|
++ if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) {
|
|
|
++ perror("ioctl[SIOCSIFMTU]");
|
|
|
++ printf("Setting MTU failed - trying to survive with "
|
|
|
++ "current value\n");
|
|
|
++ }
|
|
|
++ }
|
|
|
++#endif
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++#endif
|
|
|
++
|
|
|
++static int rtl871x_hostapd_ioctl(struct rtl871x_driver_data *drv, ieee_param *param, int len)
|
|
|
++{
|
|
|
++ struct iwreq iwr;
|
|
|
++
|
|
|
++ memset(&iwr, 0, sizeof(iwr));
|
|
|
++ os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
|
|
|
++ iwr.u.data.pointer = (caddr_t) param;
|
|
|
++ iwr.u.data.length = len;
|
|
|
++
|
|
|
++ if (ioctl(drv->ioctl_sock, RTL_IOCTL_HOSTAPD, &iwr) < 0) {
|
|
|
++ perror("ioctl[RTL_IOCTL_HOSTAPD]");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++static int rtl871x_set_mode(struct rtl871x_driver_data *drv, u32 mode)
|
|
|
++{
|
|
|
++ struct iwreq iwr;
|
|
|
++
|
|
|
++ if (drv->ioctl_sock < 0)
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ memset(&iwr, 0, sizeof(iwr));
|
|
|
++
|
|
|
++ os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
|
|
|
++
|
|
|
++ //iwr.u.mode = IW_MODE_MASTER;
|
|
|
++ iwr.u.mode = mode;
|
|
|
++
|
|
|
++ if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
|
|
|
++ perror("ioctl[SIOCSIWMODE]");
|
|
|
++ printf("Could not set interface to mode(%d)!\n", mode);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ return 0;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++/*
|
|
|
++static int rtl871x_notif_assoc(struct hostapd_data *hapd, const u8 *addr,
|
|
|
++ const u8 *ie, size_t ielen)
|
|
|
++{
|
|
|
++ struct sta_info *sta;
|
|
|
++ int new_assoc, res;
|
|
|
++
|
|
|
++ //hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
|
|
++ // HOSTAPD_LEVEL_INFO, "associated");
|
|
|
++
|
|
|
++ sta = ap_get_sta(hapd, addr);
|
|
|
++ if (sta) {
|
|
|
++ accounting_sta_stop(hapd, sta);
|
|
|
++ } else {
|
|
|
++ sta = ap_sta_add(hapd, addr);
|
|
|
++ if (sta == NULL)
|
|
|
++ {
|
|
|
++ rtl871x_sta_remove_ops(hapd->drv_priv, addr);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++ }
|
|
|
++ sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
|
|
|
++
|
|
|
++ if (hapd->conf->wpa) {
|
|
|
++ if (ie == NULL || ielen == 0) {
|
|
|
++ if (hapd->conf->wps_state) {
|
|
|
++ wpa_printf(MSG_DEBUG, "STA did not include "
|
|
|
++ "WPA/RSN IE in (Re)Association "
|
|
|
++ "Request - possible WPS use");
|
|
|
++ sta->flags |= WLAN_STA_MAYBE_WPS;
|
|
|
++ goto skip_wpa_check;
|
|
|
++ }
|
|
|
++
|
|
|
++ wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++ if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 &&
|
|
|
++ os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
|
|
++ sta->flags |= WLAN_STA_WPS;
|
|
|
++ goto skip_wpa_check;
|
|
|
++ }
|
|
|
++
|
|
|
++ if (sta->wpa_sm == NULL)
|
|
|
++ sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth,
|
|
|
++ sta->addr);
|
|
|
++ if (sta->wpa_sm == NULL) {
|
|
|
++ wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
|
|
|
++ "machine");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++ res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm,
|
|
|
++ ie, ielen, NULL, 0);
|
|
|
++ if (res != WPA_IE_OK) {
|
|
|
++ wpa_printf(MSG_DEBUG, "WPA/RSN information element "
|
|
|
++ "rejected? (res %u)", res);
|
|
|
++ wpa_hexdump(MSG_DEBUG, "IE", ie, ielen);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++ } else if (hapd->conf->wps_state) {
|
|
|
++ if (ie && ielen > 4 && ie[0] == 0xdd && ie[1] >= 4 &&
|
|
|
++ os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) {
|
|
|
++ sta->flags |= WLAN_STA_WPS;
|
|
|
++ } else
|
|
|
++ sta->flags |= WLAN_STA_MAYBE_WPS;
|
|
|
++ }
|
|
|
++skip_wpa_check:
|
|
|
++
|
|
|
++ new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0;
|
|
|
++ sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC;
|
|
|
++ wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC);
|
|
|
++
|
|
|
++ hostapd_new_assoc_sta(hapd, sta, !new_assoc);
|
|
|
++
|
|
|
++ ieee802_1x_notify_port_enabled(sta->eapol_sm, 1);
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++*/
|
|
|
++
|
|
|
++static int rtl871x_get_sta_wpaie(struct rtl871x_driver_data *drv, u8 *iebuf, u8 *addr)
|
|
|
++{
|
|
|
++ struct ieee_param param;
|
|
|
++
|
|
|
++ printf("+%s, " MACSTR " is sta's address\n", __func__, MAC2STR(addr));
|
|
|
++
|
|
|
++ memset(¶m, 0, sizeof(param));
|
|
|
++
|
|
|
++ param.cmd = RTL871X_HOSTAPD_GET_WPAIE_STA;
|
|
|
++
|
|
|
++ memcpy(param.sta_addr, addr, ETH_ALEN);
|
|
|
++
|
|
|
++ if (rtl871x_hostapd_ioctl(drv, ¶m, sizeof(param))) {
|
|
|
++ printf("Could not get sta wpaie from kernel driver.\n");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++
|
|
|
++ if(param.u.wpa_ie.len > 32)
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ memcpy(iebuf, param.u.wpa_ie.reserved, param.u.wpa_ie.len);
|
|
|
++
|
|
|
++ return 0;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++static int rtl871x_del_sta(struct rtl871x_driver_data *drv, u8 *addr)
|
|
|
++{
|
|
|
++ struct hostapd_data *hapd = drv->hapd;
|
|
|
++
|
|
|
++#if 1
|
|
|
++
|
|
|
++ //union wpa_event_data event;
|
|
|
++ //os_memset(&event, 0, sizeof(event));
|
|
|
++ //event.disassoc_info.addr = addr;
|
|
|
++ //wpa_supplicant_event(hapd, EVENT_DISASSOC, &event);
|
|
|
++
|
|
|
++ drv_event_disassoc(hapd, addr);
|
|
|
++
|
|
|
++#else
|
|
|
++
|
|
|
++ struct sta_info *sta;
|
|
|
++
|
|
|
++ //hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211,
|
|
|
++ // HOSTAPD_LEVEL_INFO, "disassociated");
|
|
|
++
|
|
|
++ sta = ap_get_sta(hapd, addr);
|
|
|
++ if (sta != NULL)
|
|
|
++ {
|
|
|
++ sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC);
|
|
|
++ wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC);
|
|
|
++ sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST;
|
|
|
++ ieee802_1x_notify_port_enabled(sta->eapol_sm, 0);
|
|
|
++ ap_free_sta(hapd, sta);
|
|
|
++ }
|
|
|
++ else
|
|
|
++ {
|
|
|
++ wpa_printf(MSG_DEBUG, "Disassociation notification for "
|
|
|
++ "unknown STA " MACSTR, MAC2STR(addr));
|
|
|
++ }
|
|
|
++#endif
|
|
|
++
|
|
|
++ return 0;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++static int rtl871x_new_sta(struct rtl871x_driver_data *drv, u8 *addr)
|
|
|
++{
|
|
|
++ struct hostapd_data *hapd = drv->hapd;
|
|
|
++ //struct ieee80211req_wpaie ie;
|
|
|
++ int ielen = 0, res=0;
|
|
|
++ //u8 *iebuf = NULL;
|
|
|
++ u8 iebuf[32], *piebuf=NULL;
|
|
|
++
|
|
|
++ /*
|
|
|
++ * Fetch negotiated WPA/RSN parameters from the driver.
|
|
|
++ */
|
|
|
++ //memset(&ie, 0, sizeof(ie));
|
|
|
++ //memcpy(ie.wpa_macaddr, addr, IEEE80211_ADDR_LEN);
|
|
|
++ memset(iebuf, 0 , sizeof(iebuf));
|
|
|
++ if (rtl871x_get_sta_wpaie(drv, iebuf, addr)) {
|
|
|
++ //if (set80211priv(drv, IEEE80211_IOCTL_GETWPAIE, &ie, sizeof(ie))) {
|
|
|
++
|
|
|
++ wpa_printf(MSG_DEBUG, "%s: Failed to get WPA/RSN IE: %s",
|
|
|
++ __func__, strerror(errno));
|
|
|
++ goto no_ie;
|
|
|
++ }
|
|
|
++
|
|
|
++ //wpa_hexdump(MSG_MSGDUMP, "req WPA IE",
|
|
|
++ // ie.wpa_ie, IEEE80211_MAX_OPT_IE);
|
|
|
++
|
|
|
++ //wpa_hexdump(MSG_MSGDUMP, "req RSN IE",
|
|
|
++ // ie.rsn_ie, IEEE80211_MAX_OPT_IE);
|
|
|
++
|
|
|
++ //iebuf = ie.wpa_ie;
|
|
|
++
|
|
|
++/*
|
|
|
++ if (iebuf[0] != WLAN_EID_VENDOR_SPECIFIC)
|
|
|
++ iebuf[1] = 0;
|
|
|
++ if (iebuf[1] == 0 && ie.rsn_ie[1] > 0) {
|
|
|
++ iebuf = ie.rsn_ie;
|
|
|
++ if (iebuf[0] != WLAN_EID_RSN)
|
|
|
++ iebuf[1] = 0;
|
|
|
++ }
|
|
|
++*/
|
|
|
++
|
|
|
++ if ((iebuf[0] == WLAN_EID_VENDOR_SPECIFIC) || (iebuf[0] == WLAN_EID_RSN) )
|
|
|
++ {
|
|
|
++ piebuf = iebuf;
|
|
|
++ ielen = iebuf[1];
|
|
|
++
|
|
|
++ if (ielen == 0)
|
|
|
++ piebuf = NULL;
|
|
|
++ else
|
|
|
++ ielen += 2;
|
|
|
++ }
|
|
|
++
|
|
|
++no_ie:
|
|
|
++
|
|
|
++ //res = rtl871x_notif_assoc(hapd, addr, piebuf, ielen);
|
|
|
++ //drv_event_assoc(hapd, addr, piebuf, ielen);
|
|
|
++ drv_event_assoc(hapd, addr, piebuf, ielen, 0);
|
|
|
++
|
|
|
++ if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) {
|
|
|
++ /* Cached accounting data is not valid anymore. */
|
|
|
++ memset(drv->acct_mac, 0, ETH_ALEN);
|
|
|
++ memset(&drv->acct_data, 0, sizeof(drv->acct_data));
|
|
|
++ }
|
|
|
++
|
|
|
++ return res;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++static void rtl871x_wireless_event_wireless(struct rtl871x_driver_data *drv,
|
|
|
++ char *data, int len)
|
|
|
++{
|
|
|
++ struct iw_event iwe_buf, *iwe = &iwe_buf;
|
|
|
++ char *pos, *end, *custom, *buf;
|
|
|
++
|
|
|
++ pos = data;
|
|
|
++ end = data + len;
|
|
|
++
|
|
|
++ while (pos + IW_EV_LCP_LEN <= end) {
|
|
|
++ /* Event data may be unaligned, so make a local, aligned copy
|
|
|
++ * before processing. */
|
|
|
++ memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
|
|
|
++ wpa_printf(MSG_MSGDUMP, "Wireless event: cmd=0x%x len=%d",
|
|
|
++ iwe->cmd, iwe->len);
|
|
|
++ if (iwe->len <= IW_EV_LCP_LEN)
|
|
|
++ return;
|
|
|
++
|
|
|
++ custom = pos + IW_EV_POINT_LEN;
|
|
|
++ if (drv->we_version > 18 &&
|
|
|
++ (iwe->cmd == IWEVMICHAELMICFAILURE ||
|
|
|
++ iwe->cmd == IWEVCUSTOM)) {
|
|
|
++ /* WE-19 removed the pointer from struct iw_point */
|
|
|
++ char *dpos = (char *) &iwe_buf.u.data.length;
|
|
|
++ int dlen = dpos - (char *) &iwe_buf;
|
|
|
++ memcpy(dpos, pos + IW_EV_LCP_LEN,
|
|
|
++ sizeof(struct iw_event) - dlen);
|
|
|
++ } else {
|
|
|
++ memcpy(&iwe_buf, pos, sizeof(struct iw_event));
|
|
|
++ custom += IW_EV_POINT_OFF;
|
|
|
++ }
|
|
|
++
|
|
|
++ //printf("got wireless event, iwe->cmd=%d\n", iwe->cmd);
|
|
|
++
|
|
|
++ switch (iwe->cmd) {
|
|
|
++ case IWEVEXPIRED:
|
|
|
++ rtl871x_del_sta(drv, (u8 *)iwe->u.addr.sa_data);
|
|
|
++ break;
|
|
|
++ case IWEVREGISTERED:
|
|
|
++ if(rtl871x_new_sta(drv, (u8 *)iwe->u.addr.sa_data))
|
|
|
++ {
|
|
|
++ printf("Failed to add new sta: "MACSTR" \n", MAC2STR((u8 *)iwe->u.addr.sa_data));
|
|
|
++ }
|
|
|
++ break;
|
|
|
++ case IWEVCUSTOM:
|
|
|
++ if (custom + iwe->u.data.length > end)
|
|
|
++ return;
|
|
|
++ buf = malloc(iwe->u.data.length + 1);
|
|
|
++ if (buf == NULL)
|
|
|
++ return; /* XXX */
|
|
|
++ memcpy(buf, custom, iwe->u.data.length);
|
|
|
++ buf[iwe->u.data.length] = '\0';
|
|
|
++ //madwifi_wireless_event_wireless_custom(drv, buf);
|
|
|
++ free(buf);
|
|
|
++ break;
|
|
|
++ }
|
|
|
++
|
|
|
++ pos += iwe->len;
|
|
|
++ }
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++#if 1
|
|
|
++static void rtl871x_wireless_event_rtm_newlink(void *ctx,
|
|
|
++ struct ifinfomsg *ifi, u8 *buf, size_t len)
|
|
|
++{
|
|
|
++ struct rtl871x_driver_data *drv = ctx;
|
|
|
++ int attrlen, rta_len;
|
|
|
++ struct rtattr *attr;
|
|
|
++
|
|
|
++ if (ifi->ifi_index != drv->ifindex)
|
|
|
++ return;
|
|
|
++
|
|
|
++ attrlen = len;
|
|
|
++ attr = (struct rtattr *) buf;
|
|
|
++
|
|
|
++ rta_len = RTA_ALIGN(sizeof(struct rtattr));
|
|
|
++ while (RTA_OK(attr, attrlen)) {
|
|
|
++ if (attr->rta_type == IFLA_WIRELESS) {
|
|
|
++ rtl871x_wireless_event_wireless(
|
|
|
++ drv, ((char *) attr) + rta_len,
|
|
|
++ attr->rta_len - rta_len);
|
|
|
++ }
|
|
|
++ attr = RTA_NEXT(attr, attrlen);
|
|
|
++ }
|
|
|
++}
|
|
|
++
|
|
|
++#else
|
|
|
++static void rtl871x_wireless_event_rtm_newlink(struct rtl871x_driver_data *drv,
|
|
|
++ struct nlmsghdr *h, int len)
|
|
|
++{
|
|
|
++ struct ifinfomsg *ifi;
|
|
|
++ int attrlen, nlmsg_len, rta_len;
|
|
|
++ struct rtattr * attr;
|
|
|
++
|
|
|
++ if (len < (int) sizeof(*ifi))
|
|
|
++ return;
|
|
|
++
|
|
|
++ ifi = NLMSG_DATA(h);
|
|
|
++
|
|
|
++ if (ifi->ifi_index != drv->ifindex)
|
|
|
++ return;
|
|
|
++
|
|
|
++ nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
|
|
|
++
|
|
|
++ attrlen = h->nlmsg_len - nlmsg_len;
|
|
|
++ if (attrlen < 0)
|
|
|
++ return;
|
|
|
++
|
|
|
++ attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
|
|
|
++
|
|
|
++ rta_len = RTA_ALIGN(sizeof(struct rtattr));
|
|
|
++ while (RTA_OK(attr, attrlen)) {
|
|
|
++ if (attr->rta_type == IFLA_WIRELESS) {
|
|
|
++ rtl871x_wireless_event_wireless(
|
|
|
++ drv, ((char *) attr) + rta_len,
|
|
|
++ attr->rta_len - rta_len);
|
|
|
++ }
|
|
|
++ attr = RTA_NEXT(attr, attrlen);
|
|
|
++ }
|
|
|
++}
|
|
|
++#endif
|
|
|
++
|
|
|
++/*
|
|
|
++static void rtl871x_wireless_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
|
|
|
++{
|
|
|
++ char buf[256];//!!!
|
|
|
++ int left;
|
|
|
++ struct sockaddr_nl from;
|
|
|
++ socklen_t fromlen;
|
|
|
++ struct nlmsghdr *h;
|
|
|
++ struct rtl871x_driver_data *drv = eloop_ctx;
|
|
|
++
|
|
|
++ //printf("+rtl871x_wireless_event_receive\n");
|
|
|
++
|
|
|
++ fromlen = sizeof(from);
|
|
|
++ left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
|
|
|
++ (struct sockaddr *) &from, &fromlen);
|
|
|
++ if (left < 0) {
|
|
|
++ if (errno != EINTR && errno != EAGAIN)
|
|
|
++ perror("recvfrom(netlink)");
|
|
|
++ return;
|
|
|
++ }
|
|
|
++
|
|
|
++ h = (struct nlmsghdr *)buf;
|
|
|
++ while (left >= (int) sizeof(*h)) {
|
|
|
++ int len, plen;
|
|
|
++
|
|
|
++ len = h->nlmsg_len;
|
|
|
++ plen = len - sizeof(*h);//payload len
|
|
|
++ if (len > left || plen < 0) {
|
|
|
++ printf("Malformed netlink message: "
|
|
|
++ "len=%d left=%d plen=%d\n",
|
|
|
++ len, left, plen);
|
|
|
++ break;
|
|
|
++ }
|
|
|
++
|
|
|
++ switch (h->nlmsg_type) {
|
|
|
++ case RTM_NEWLINK:
|
|
|
++ rtl871x_wireless_event_rtm_newlink(drv, h, plen);
|
|
|
++ break;
|
|
|
++ }
|
|
|
++
|
|
|
++ len = NLMSG_ALIGN(len);
|
|
|
++ left -= len;
|
|
|
++ h = (struct nlmsghdr *) ((char *) h + len);
|
|
|
++ }
|
|
|
++
|
|
|
++ if (left > 0) {
|
|
|
++ printf("%d extra bytes in the end of netlink message\n", left);
|
|
|
++ }
|
|
|
++
|
|
|
++}
|
|
|
++*/
|
|
|
++
|
|
|
++static int rtl871x_wireless_event_init(struct rtl871x_driver_data *drv)
|
|
|
++{
|
|
|
++ struct netlink_config *cfg;
|
|
|
++
|
|
|
++ //madwifi_get_we_version(drv);
|
|
|
++
|
|
|
++ cfg = os_zalloc(sizeof(*cfg));
|
|
|
++ if (cfg == NULL)
|
|
|
++ return -1;
|
|
|
++ cfg->ctx = drv;
|
|
|
++ cfg->newlink_cb = rtl871x_wireless_event_rtm_newlink;
|
|
|
++ drv->netlink = netlink_init(cfg);
|
|
|
++ if (drv->netlink == NULL) {
|
|
|
++ os_free(cfg);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++/*
|
|
|
++static int rtl871x_wireless_event_init_ops(void *priv)
|
|
|
++{
|
|
|
++ int s;
|
|
|
++ struct sockaddr_nl local;
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++
|
|
|
++ //madwifi_get_we_version(drv);
|
|
|
++
|
|
|
++ drv->wext_sock = -1;
|
|
|
++
|
|
|
++ s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
|
|
++ if (s < 0) {
|
|
|
++ perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ memset(&local, 0, sizeof(local));
|
|
|
++ local.nl_family = AF_NETLINK;
|
|
|
++ local.nl_groups = RTMGRP_LINK;
|
|
|
++ if (bind(s, (struct sockaddr *) &local, sizeof(local)) < 0) {
|
|
|
++ perror("bind(netlink)");
|
|
|
++ close(s);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ eloop_register_read_sock(s, rtl871x_wireless_event_receive, drv, NULL);
|
|
|
++ drv->wext_sock = s;
|
|
|
++
|
|
|
++ return 0;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++static void rtl871x_wireless_event_deinit_ops(void *priv)
|
|
|
++{
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++
|
|
|
++ if (drv != NULL) {
|
|
|
++ if (drv->wext_sock < 0)
|
|
|
++ return;
|
|
|
++ eloop_unregister_read_sock(drv->wext_sock);
|
|
|
++ close(drv->wext_sock);
|
|
|
++ }
|
|
|
++}
|
|
|
++*/
|
|
|
++
|
|
|
++#if 1
|
|
|
++static void rtl871x_handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
|
|
|
++{
|
|
|
++ struct rtl871x_driver_data *drv = ctx;
|
|
|
++ drv_event_eapol_rx(drv->hapd, src_addr, buf + sizeof(struct l2_ethhdr),
|
|
|
++ len - sizeof(struct l2_ethhdr));
|
|
|
++}
|
|
|
++#else
|
|
|
++static void rtl871x_handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len)
|
|
|
++{
|
|
|
++ struct rtl871x_driver_data *drv = ctx;
|
|
|
++ struct hostapd_data *hapd = drv->hapd;
|
|
|
++ struct sta_info *sta;
|
|
|
++
|
|
|
++ sta = ap_get_sta(hapd, src_addr);
|
|
|
++ if (!sta || !(sta->flags & WLAN_STA_ASSOC)) {
|
|
|
++ printf("Data frame from not associated STA %s\n",
|
|
|
++ ether_sprintf(src_addr));
|
|
|
++ /* XXX cannot happen */
|
|
|
++ return;
|
|
|
++ }
|
|
|
++ ieee802_1x_receive(hapd, src_addr, buf + sizeof(struct l2_ethhdr),
|
|
|
++ len - sizeof(struct l2_ethhdr));
|
|
|
++}
|
|
|
++#endif
|
|
|
++
|
|
|
++static int rtl871x_send_eapol_ops(void *priv, const u8 *addr, const u8 *data, size_t data_len,
|
|
|
++ int encrypt, const u8 *own_addr, u32 flags)
|
|
|
++{
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++ unsigned char buf[3000];
|
|
|
++ unsigned char *bp = buf;
|
|
|
++ struct l2_ethhdr *eth;
|
|
|
++ size_t len;
|
|
|
++ int status;
|
|
|
++
|
|
|
++ printf("+rtl871x_send_eapol\n");
|
|
|
++
|
|
|
++ /*
|
|
|
++ * Prepend the Ethernet header. If the caller left us
|
|
|
++ * space at the front we could just insert it but since
|
|
|
++ * we don't know we copy to a local buffer. Given the frequency
|
|
|
++ * and size of frames this probably doesn't matter.
|
|
|
++ */
|
|
|
++ len = data_len + sizeof(struct l2_ethhdr);
|
|
|
++ if (len > sizeof(buf)) {
|
|
|
++ bp = malloc(len);
|
|
|
++ if (bp == NULL) {
|
|
|
++ printf("EAPOL frame discarded, cannot malloc temp "
|
|
|
++ "buffer of size %lu!\n", (unsigned long) len);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++ }
|
|
|
++
|
|
|
++ eth = (struct l2_ethhdr *) bp;
|
|
|
++ memcpy(eth->h_dest, addr, ETH_ALEN);
|
|
|
++ memcpy(eth->h_source, own_addr, ETH_ALEN);
|
|
|
++ eth->h_proto = htons(ETH_P_EAPOL);
|
|
|
++ memcpy(eth+1, data, data_len);
|
|
|
++
|
|
|
++ wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len);
|
|
|
++
|
|
|
++ status = l2_packet_send(drv->l2_sock, addr, ETH_P_EAPOL, bp, len);
|
|
|
++
|
|
|
++ if (bp != buf)
|
|
|
++ free(bp);
|
|
|
++
|
|
|
++ return status;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++#ifndef CONFIG_MLME_OFFLOAD
|
|
|
++static void rtl871x_receive_mgnt(struct rtl871x_driver_data *drv , const u8 *buf, size_t len)
|
|
|
++{
|
|
|
++ const struct ieee80211_mgmt *mgmt;
|
|
|
++ //const u8 *end, *ie;
|
|
|
++ u16 fc, type, stype;
|
|
|
++ //size_t ie_len;
|
|
|
++ struct hostapd_data *hapd = drv->hapd;
|
|
|
++
|
|
|
++ //printf("+rtl871x_receive_mgnt, " MACSTR " is our address\n", MAC2STR(hapd->own_addr));
|
|
|
++
|
|
|
++
|
|
|
++#if 0
|
|
|
++ {
|
|
|
++ int i;
|
|
|
++ for(i=0; i<len; i+=8)
|
|
|
++ {
|
|
|
++ printf("%x:%x:%x:%x:%x:%x:%x:%x\n", buf[i], buf[i+1], buf[i+2], buf[i+3], buf[i+4], buf[i+5], buf[i+6], buf[i+7]);
|
|
|
++ }
|
|
|
++
|
|
|
++ }
|
|
|
++#endif
|
|
|
++
|
|
|
++ if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
|
|
|
++ return;
|
|
|
++
|
|
|
++ mgmt = (const struct ieee80211_mgmt *)buf;
|
|
|
++
|
|
|
++ fc = le_to_host16(mgmt->frame_control);
|
|
|
++ type = WLAN_FC_GET_TYPE(fc);
|
|
|
++ stype = WLAN_FC_GET_STYPE(fc);
|
|
|
++
|
|
|
++#if 1
|
|
|
++ if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT &&
|
|
|
++ WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_RESP)
|
|
|
++ {
|
|
|
++ //printf("MGNT Frame - PROBE_RESP Frame\n");
|
|
|
++ }
|
|
|
++#endif
|
|
|
++
|
|
|
++ //end = buf + len;
|
|
|
++ //ie = mgmt->u.probe_req.variable;
|
|
|
++ //ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
|
|
|
++ //hostapd_wps_probe_req_rx(drv->hapd, mgmt->sa, ie, ie_len);
|
|
|
++
|
|
|
++ switch (type) {
|
|
|
++ case WLAN_FC_TYPE_MGMT:
|
|
|
++ if (stype != WLAN_FC_STYPE_BEACON)
|
|
|
++ wpa_printf(MSG_MSGDUMP, "MGMT");
|
|
|
++
|
|
|
++
|
|
|
++
|
|
|
++ if (stype == WLAN_FC_STYPE_PROBE_REQ)
|
|
|
++ {
|
|
|
++
|
|
|
++ }
|
|
|
++ else
|
|
|
++ {
|
|
|
++ //printf("rtl871x_receive_mgnt, type=0x%x, stype=0x%x\n", type, stype);
|
|
|
++ }
|
|
|
++
|
|
|
++
|
|
|
++ //ieee802_11_mgmt(hapd, (u8 *)buf, len, stype, NULL);
|
|
|
++
|
|
|
++ break;
|
|
|
++ case WLAN_FC_TYPE_CTRL:
|
|
|
++ printf("rtl871x_receive_mgnt, CTRL\n");
|
|
|
++ break;
|
|
|
++ case WLAN_FC_TYPE_DATA:
|
|
|
++ printf("rtl871x_receive_mgnt, DATA\n");
|
|
|
++ //handle_data(hapd, buf, data_len, stype);
|
|
|
++ break;
|
|
|
++ default:
|
|
|
++ printf("unknown frame type %d\n", type);
|
|
|
++ break;
|
|
|
++ }
|
|
|
++
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++#ifdef CONFIG_MGNT_L2SOCK
|
|
|
++static void rtl871x_recvive_mgmt_frame(void *ctx, const u8 *src_addr, const u8 *buf,
|
|
|
++ size_t len)
|
|
|
++{
|
|
|
++ struct rtl871x_driver_data *drv = ctx;
|
|
|
++
|
|
|
++ rtl871x_receive_mgnt(drv, buf, len);
|
|
|
++}
|
|
|
++#else
|
|
|
++static void rtl871x_recvive_mgmt_frame(int sock, void *eloop_ctx, void *sock_ctx)
|
|
|
++{
|
|
|
++#if 0
|
|
|
++ int len;
|
|
|
++ unsigned char buf[1024];
|
|
|
++ struct hostapd_data *hapd = (struct hostapd_data *)eloop_ctx;
|
|
|
++ struct rtl871x_driver_data *drv = (struct rtl871x_driver_data *)hapd->drv_priv;
|
|
|
++
|
|
|
++ len = recv(sock, buf, sizeof(buf), 0);
|
|
|
++ if (len < 0) {
|
|
|
++ perror("recv");
|
|
|
++ return;
|
|
|
++ }
|
|
|
++
|
|
|
++ rtl871x_receive_mgnt(drv, buf, len);
|
|
|
++#endif
|
|
|
++}
|
|
|
++
|
|
|
++static int rtl871x_mgnt_sock_init(struct rtl871x_driver_data *drv, const char *name)
|
|
|
++{
|
|
|
++ int sock;
|
|
|
++ struct ifreq ifr;
|
|
|
++ struct sockaddr_ll addr;
|
|
|
++
|
|
|
++ sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
|
|
|
++ if (sock < 0) {
|
|
|
++ perror("socket[PF_PACKET,SOCK_RAW]");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ if (eloop_register_read_sock(sock, rtl871x_recvive_mgmt_frame, drv->hapd, NULL))
|
|
|
++ {
|
|
|
++ printf("Could not register read socket\n");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ memset(&ifr, 0, sizeof(ifr));
|
|
|
++ //snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface);
|
|
|
++ os_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
|
|
|
++ if (ioctl(sock, SIOCGIFINDEX, &ifr) != 0) {
|
|
|
++ perror("ioctl(SIOCGIFINDEX)");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ //if (rtl871x_set_iface_flags(drv, 1)) {
|
|
|
++ // return -1;
|
|
|
++ //}
|
|
|
++
|
|
|
++ memset(&addr, 0, sizeof(addr));
|
|
|
++ addr.sll_family = AF_PACKET;
|
|
|
++ addr.sll_ifindex = ifr.ifr_ifindex;
|
|
|
++ wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
|
|
|
++ addr.sll_ifindex);
|
|
|
++
|
|
|
++ if (bind(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
|
|
|
++ perror("bind");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ memset(&ifr, 0, sizeof(ifr));
|
|
|
++ os_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
|
|
|
++ if (ioctl(sock, SIOCGIFHWADDR, &ifr) != 0) {
|
|
|
++ perror("ioctl(SIOCGIFHWADDR)");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++
|
|
|
++ if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
|
|
|
++ printf("Invalid HW-addr family 0x%04x\n",
|
|
|
++ ifr.ifr_hwaddr.sa_family);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ //memcpy(drv->hapd->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
|
|
|
++
|
|
|
++ return sock;
|
|
|
++
|
|
|
++}
|
|
|
++#endif
|
|
|
++#endif
|
|
|
++
|
|
|
++static void rtl871x_handle_tx_callback(struct hostapd_data *hapd, u8 *buf, size_t len,
|
|
|
++ int ok)
|
|
|
++{
|
|
|
++#if 0
|
|
|
++ struct ieee80211_hdr *hdr;
|
|
|
++ u16 fc, type, stype;
|
|
|
++ struct sta_info *sta;
|
|
|
++
|
|
|
++ //printf("%s\n", __func__);
|
|
|
++
|
|
|
++ hdr = (struct ieee80211_hdr *) buf;
|
|
|
++ fc = le_to_host16(hdr->frame_control);
|
|
|
++
|
|
|
++ type = WLAN_FC_GET_TYPE(fc);
|
|
|
++ stype = WLAN_FC_GET_STYPE(fc);
|
|
|
++
|
|
|
++ switch (type) {
|
|
|
++ case WLAN_FC_TYPE_MGMT:
|
|
|
++ //printf("MGMT (TX callback) %s\n",
|
|
|
++ // ok ? "ACK" : "fail");
|
|
|
++ ieee802_11_mgmt_cb(hapd, buf, len, stype, ok);
|
|
|
++ break;
|
|
|
++ case WLAN_FC_TYPE_CTRL:
|
|
|
++ printf("CTRL (TX callback) %s\n",
|
|
|
++ ok ? "ACK" : "fail");
|
|
|
++ break;
|
|
|
++ case WLAN_FC_TYPE_DATA:
|
|
|
++ printf("DATA (TX callback) %s\n",
|
|
|
++ ok ? "ACK" : "fail");
|
|
|
++ sta = ap_get_sta(hapd, hdr->addr1);
|
|
|
++ if (sta && sta->flags & WLAN_STA_PENDING_POLL) {
|
|
|
++ wpa_printf(MSG_DEBUG, "STA " MACSTR
|
|
|
++ " %s pending activity poll",
|
|
|
++ MAC2STR(sta->addr),
|
|
|
++ ok ? "ACKed" : "did not ACK");
|
|
|
++ if (ok)
|
|
|
++ sta->flags &= ~WLAN_STA_PENDING_POLL;
|
|
|
++ }
|
|
|
++ if (sta)
|
|
|
++ ieee802_1x_tx_status(hapd, sta, buf, len, ok);
|
|
|
++ break;
|
|
|
++ default:
|
|
|
++ printf("unknown TX callback frame type %d\n", type);
|
|
|
++ break;
|
|
|
++ }
|
|
|
++#endif
|
|
|
++}
|
|
|
++
|
|
|
++static int rtl871x_send_mgnt(struct rtl871x_driver_data *drv, const void *msg, size_t len)
|
|
|
++{
|
|
|
++ int res=0;
|
|
|
++
|
|
|
++ return res;
|
|
|
++}
|
|
|
++
|
|
|
++static int rtl871x_send_mgmt_frame_ops(void *priv, const void *msg, size_t len,
|
|
|
++ int flags)
|
|
|
++{
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++ //struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)msg;
|
|
|
++ int res=0;
|
|
|
++
|
|
|
++ //printf("%s\n", __func__);
|
|
|
++
|
|
|
++
|
|
|
++ //hdr->frame_control |= host_to_le16(BIT(1));/* Request TX callback */
|
|
|
++#ifdef CONFIG_MGNT_L2SOCK
|
|
|
++ //res = send(drv->mgnt_l2_sock, msg, len, flags);
|
|
|
++ //res = l2_packet_send(drv->mgnt_l2_sock, addr, ETH_P_EAPOL, msg, len);
|
|
|
++ if(drv->mgnt_l2_sock == NULL)
|
|
|
++ return res;
|
|
|
++
|
|
|
++ res = l2_packet_send(drv->mgnt_l2_sock, NULL, ETH_P_80211_RAW, msg, len);
|
|
|
++#else
|
|
|
++
|
|
|
++ if(drv->mgnt_sock < 0)
|
|
|
++ return res;
|
|
|
++
|
|
|
++ res = send(drv->mgnt_sock, msg, len, flags);
|
|
|
++#endif
|
|
|
++ //hdr->frame_control &= ~host_to_le16(BIT(1));
|
|
|
++
|
|
|
++
|
|
|
++ rtl871x_send_mgnt(drv, msg, len);
|
|
|
++
|
|
|
++ rtl871x_handle_tx_callback(drv->hapd, (u8*)msg, len, 1);
|
|
|
++
|
|
|
++ return res;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++/*
|
|
|
++static int rtl871x_driver_send_ether_ops(void *priv, const u8 *dst, const u8 *src,
|
|
|
++ u16 proto, const u8 *data, size_t data_len)
|
|
|
++{
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++*/
|
|
|
++
|
|
|
++static struct hostapd_hw_modes *rtl871x_get_hw_feature_data_ops(void *priv,
|
|
|
++ u16 *num_modes,
|
|
|
++ u16 *flags)
|
|
|
++{
|
|
|
++
|
|
|
++#define MAX_NUM_CHANNEL (14)
|
|
|
++#define MAX_NUM_CHANNEL_5G (24)
|
|
|
++
|
|
|
++ struct hostapd_hw_modes *modes;
|
|
|
++ size_t i;
|
|
|
++ int k;
|
|
|
++
|
|
|
++ *num_modes = 3;
|
|
|
++ *flags = 0;
|
|
|
++
|
|
|
++ modes = os_zalloc(*num_modes * sizeof(struct hostapd_hw_modes));
|
|
|
++ if (modes == NULL)
|
|
|
++ return NULL;
|
|
|
++
|
|
|
++ //.1
|
|
|
++ modes[0].mode = HOSTAPD_MODE_IEEE80211G;
|
|
|
++ modes[0].num_channels = MAX_NUM_CHANNEL;
|
|
|
++ modes[0].num_rates = 12;
|
|
|
++ modes[0].channels =
|
|
|
++ os_zalloc(MAX_NUM_CHANNEL * sizeof(struct hostapd_channel_data));
|
|
|
++ modes[0].rates = os_zalloc(modes[0].num_rates * sizeof(int));
|
|
|
++ if (modes[0].channels == NULL || modes[0].rates == NULL)
|
|
|
++ goto fail;
|
|
|
++ for (i = 0; i < MAX_NUM_CHANNEL; i++) {
|
|
|
++ modes[0].channels[i].chan = i + 1;
|
|
|
++ modes[0].channels[i].freq = 2412 + 5 * i;
|
|
|
++ modes[0].channels[i].flag = 0;
|
|
|
++ if (i >= 13)
|
|
|
++ modes[0].channels[i].flag = HOSTAPD_CHAN_DISABLED;
|
|
|
++ }
|
|
|
++ modes[0].rates[0] = 10;
|
|
|
++ modes[0].rates[1] = 20;
|
|
|
++ modes[0].rates[2] = 55;
|
|
|
++ modes[0].rates[3] = 110;
|
|
|
++ modes[0].rates[4] = 60;
|
|
|
++ modes[0].rates[5] = 90;
|
|
|
++ modes[0].rates[6] = 120;
|
|
|
++ modes[0].rates[7] = 180;
|
|
|
++ modes[0].rates[8] = 240;
|
|
|
++ modes[0].rates[9] = 360;
|
|
|
++ modes[0].rates[10] = 480;
|
|
|
++ modes[0].rates[11] = 540;
|
|
|
++
|
|
|
++
|
|
|
++ //.2
|
|
|
++ modes[1].mode = HOSTAPD_MODE_IEEE80211B;
|
|
|
++ modes[1].num_channels = MAX_NUM_CHANNEL;
|
|
|
++ modes[1].num_rates = 4;
|
|
|
++ modes[1].channels =
|
|
|
++ os_zalloc(MAX_NUM_CHANNEL * sizeof(struct hostapd_channel_data));
|
|
|
++ modes[1].rates = os_zalloc(modes[1].num_rates * sizeof(int));
|
|
|
++ if (modes[1].channels == NULL || modes[1].rates == NULL)
|
|
|
++ goto fail;
|
|
|
++ for (i = 0; i < MAX_NUM_CHANNEL; i++) {
|
|
|
++ modes[1].channels[i].chan = i + 1;
|
|
|
++ modes[1].channels[i].freq = 2412 + 5 * i;
|
|
|
++ modes[1].channels[i].flag = 0;
|
|
|
++ if (i >= 11)
|
|
|
++ modes[1].channels[i].flag = HOSTAPD_CHAN_DISABLED;
|
|
|
++ }
|
|
|
++ modes[1].rates[0] = 10;
|
|
|
++ modes[1].rates[1] = 20;
|
|
|
++ modes[1].rates[2] = 55;
|
|
|
++ modes[1].rates[3] = 110;
|
|
|
++
|
|
|
++
|
|
|
++ //.3
|
|
|
++ modes[2].mode = HOSTAPD_MODE_IEEE80211A;
|
|
|
++#ifdef CONFIG_DRIVER_RTL_DFS
|
|
|
++ modes[2].num_channels = MAX_NUM_CHANNEL_5G;
|
|
|
++#else /* CONFIG_DRIVER_RTL_DFS */
|
|
|
++ modes[2].num_channels = 9;
|
|
|
++#endif /* CONFIG_DRIVER_RTL_DFS */
|
|
|
++
|
|
|
++ modes[2].num_rates = 8;
|
|
|
++ modes[2].channels = os_zalloc(modes[2].num_channels * sizeof(struct hostapd_channel_data));
|
|
|
++ modes[2].rates = os_zalloc(modes[2].num_rates * sizeof(int));
|
|
|
++ if (modes[2].channels == NULL || modes[2].rates == NULL)
|
|
|
++ goto fail;
|
|
|
++
|
|
|
++
|
|
|
++ k = 0;
|
|
|
++ // 5G band1 Channel: 36, 40, 44, 48
|
|
|
++ for (i=0; i < 4; i++) {
|
|
|
++ modes[2].channels[k].chan = 36+(i*4);
|
|
|
++ modes[2].channels[k].freq = 5180+(i*20);
|
|
|
++ modes[2].channels[k].flag = 0;
|
|
|
++ k++;
|
|
|
++ }
|
|
|
++
|
|
|
++#ifdef CONFIG_DRIVER_RTL_DFS
|
|
|
++ // 5G band2 Channel: 52, 56, 60, 64
|
|
|
++ for (i=0; i < 4; i++) {
|
|
|
++ modes[2].channels[k].chan = 52+(i*4);
|
|
|
++ modes[2].channels[k].freq = 5260+(i*20);
|
|
|
++ modes[2].channels[k].flag = 0;
|
|
|
++ k++;
|
|
|
++ }
|
|
|
++
|
|
|
++ // 5G band3 Channel: 100, 104, 108. 112, 116, 120, 124, 128, 132, 136, 140
|
|
|
++ for (i=0; i < 11; i++) {
|
|
|
++ modes[2].channels[k].chan = 100+(i*4);
|
|
|
++ modes[2].channels[k].freq = 5500+(i*20);
|
|
|
++ modes[2].channels[k].flag = 0;
|
|
|
++ k++;
|
|
|
++ }
|
|
|
++#endif /* CONFIG_DRIVER_RTL_DFS */
|
|
|
++
|
|
|
++ // 5G band4 Channel: 149, 153, 157, 161, 165
|
|
|
++ for (i=0; i < 5; i++) {
|
|
|
++ modes[2].channels[k].chan = 149+(i*4);
|
|
|
++ modes[2].channels[k].freq = 5745+(i*20);
|
|
|
++ modes[2].channels[k].flag = 0;
|
|
|
++ k++;
|
|
|
++ }
|
|
|
++
|
|
|
++ modes[2].rates[0] = 60;
|
|
|
++ modes[2].rates[1] = 90;
|
|
|
++ modes[2].rates[2] = 120;
|
|
|
++ modes[2].rates[3] = 180;
|
|
|
++ modes[2].rates[4] = 240;
|
|
|
++ modes[2].rates[5] = 360;
|
|
|
++ modes[2].rates[6] = 480;
|
|
|
++ modes[2].rates[7] = 540;
|
|
|
++
|
|
|
++
|
|
|
++ //
|
|
|
++#if 0
|
|
|
++#define HT_CAP_INFO_LDPC_CODING_CAP ((u16) BIT(0))
|
|
|
++#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET ((u16) BIT(1))
|
|
|
++#define HT_CAP_INFO_SMPS_MASK ((u16) (BIT(2) | BIT(3)))
|
|
|
++#define HT_CAP_INFO_SMPS_STATIC ((u16) 0)
|
|
|
++#define HT_CAP_INFO_SMPS_DYNAMIC ((u16) BIT(2))
|
|
|
++#define HT_CAP_INFO_SMPS_DISABLED ((u16) (BIT(2) | BIT(3)))
|
|
|
++#define HT_CAP_INFO_GREEN_FIELD ((u16) BIT(4))
|
|
|
++#define HT_CAP_INFO_SHORT_GI20MHZ ((u16) BIT(5))
|
|
|
++#define HT_CAP_INFO_SHORT_GI40MHZ ((u16) BIT(6))
|
|
|
++#define HT_CAP_INFO_TX_STBC ((u16) BIT(7))
|
|
|
++#define HT_CAP_INFO_RX_STBC_MASK ((u16) (BIT(8) | BIT(9)))
|
|
|
++#define HT_CAP_INFO_RX_STBC_1 ((u16) BIT(8))
|
|
|
++#define HT_CAP_INFO_RX_STBC_12 ((u16) BIT(9))
|
|
|
++#define HT_CAP_INFO_RX_STBC_123 ((u16) (BIT(8) | BIT(9)))
|
|
|
++#define HT_CAP_INFO_DELAYED_BA ((u16) BIT(10))
|
|
|
++#define HT_CAP_INFO_MAX_AMSDU_SIZE ((u16) BIT(11))
|
|
|
++#define HT_CAP_INFO_DSSS_CCK40MHZ ((u16) BIT(12))
|
|
|
++#define HT_CAP_INFO_PSMP_SUPP ((u16) BIT(13))
|
|
|
++#define HT_CAP_INFO_40MHZ_INTOLERANT ((u16) BIT(14))
|
|
|
++#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT ((u16) BIT(15))
|
|
|
++#endif
|
|
|
++
|
|
|
++ //HOSTAPD_MODE_IEEE80211G
|
|
|
++ modes[0].ht_capab = HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET|HT_CAP_INFO_SHORT_GI20MHZ|
|
|
|
++ HT_CAP_INFO_SHORT_GI40MHZ|HT_CAP_INFO_MAX_AMSDU_SIZE|HT_CAP_INFO_DSSS_CCK40MHZ;
|
|
|
++
|
|
|
++ modes[0].mcs_set[0]= 0xff;
|
|
|
++ modes[0].mcs_set[1]= 0xff;
|
|
|
++
|
|
|
++ //HOSTAPD_MODE_IEEE80211B
|
|
|
++ modes[1].ht_capab = 0;
|
|
|
++
|
|
|
++ //HOSTAPD_MODE_IEEE80211A
|
|
|
++ modes[2].ht_capab = modes[0].ht_capab;
|
|
|
++
|
|
|
++ modes[2].mcs_set[0]= 0xff;
|
|
|
++ modes[2].mcs_set[1]= 0xff;
|
|
|
++
|
|
|
++ return modes;
|
|
|
++
|
|
|
++fail:
|
|
|
++ if (modes) {
|
|
|
++ for (i = 0; i < *num_modes; i++) {
|
|
|
++ os_free(modes[i].channels);
|
|
|
++ os_free(modes[i].rates);
|
|
|
++ }
|
|
|
++ os_free(modes);
|
|
|
++ }
|
|
|
++
|
|
|
++ return NULL;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++#if 0
|
|
|
++static int rtl871x_sta_add_ops(const char *ifname, void *priv, const u8 *addr,
|
|
|
++ u16 aid, u16 capability, u8 *supp_rates,
|
|
|
++ size_t supp_rates_len, int flags,
|
|
|
++ u16 listen_interval)
|
|
|
++{
|
|
|
++
|
|
|
++#if 1
|
|
|
++ printf("+%s, " MACSTR " is new sta address added\n", __func__, MAC2STR(addr));
|
|
|
++ return 0;
|
|
|
++#else
|
|
|
++ struct hostap_driver_data *drv = priv;
|
|
|
++ struct prism2_hostapd_param param;
|
|
|
++ int tx_supp_rates = 0;
|
|
|
++ size_t i;
|
|
|
++
|
|
|
++#define WLAN_RATE_1M BIT(0)
|
|
|
++#define WLAN_RATE_2M BIT(1)
|
|
|
++#define WLAN_RATE_5M5 BIT(2)
|
|
|
++#define WLAN_RATE_11M BIT(3)
|
|
|
++
|
|
|
++ for (i = 0; i < supp_rates_len; i++) {
|
|
|
++ if ((supp_rates[i] & 0x7f) == 2)
|
|
|
++ tx_supp_rates |= WLAN_RATE_1M;
|
|
|
++ if ((supp_rates[i] & 0x7f) == 4)
|
|
|
++ tx_supp_rates |= WLAN_RATE_2M;
|
|
|
++ if ((supp_rates[i] & 0x7f) == 11)
|
|
|
++ tx_supp_rates |= WLAN_RATE_5M5;
|
|
|
++ if ((supp_rates[i] & 0x7f) == 22)
|
|
|
++ tx_supp_rates |= WLAN_RATE_11M;
|
|
|
++ }
|
|
|
++
|
|
|
++ memset(¶m, 0, sizeof(param));
|
|
|
++ param.cmd = PRISM2_HOSTAPD_ADD_STA;
|
|
|
++ memcpy(param.sta_addr, addr, ETH_ALEN);
|
|
|
++ param.u.add_sta.aid = aid;
|
|
|
++ param.u.add_sta.capability = capability;
|
|
|
++ param.u.add_sta.tx_supp_rates = tx_supp_rates;
|
|
|
++ return hostapd_ioctl(drv, ¶m, sizeof(param));
|
|
|
++#endif
|
|
|
++}
|
|
|
++
|
|
|
++static int rtl871x_sta_add2_ops(const char *ifname, void *priv,
|
|
|
++ struct hostapd_sta_add_params *params)
|
|
|
++{
|
|
|
++#if 0
|
|
|
++ ieee_param param;
|
|
|
++ //int i, tx_supp_rates = 0;
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++
|
|
|
++ printf("%s\n", __func__);
|
|
|
++
|
|
|
++ memset(¶m, 0, sizeof(param));
|
|
|
++ param.cmd = RTL871X_HOSTAPD_ADD_STA;
|
|
|
++ memcpy(param.sta_addr, params->addr, ETH_ALEN);
|
|
|
++ param.u.add_sta.aid = params->aid;
|
|
|
++ param.u.add_sta.capability = params->capability;
|
|
|
++ param.u.add_sta.flags = params->flags;
|
|
|
++
|
|
|
++ memcpy(param.u.add_sta.tx_supp_rates, params->supp_rates, params->supp_rates_len);
|
|
|
++
|
|
|
++/*
|
|
|
++ for (i = 0; i < params->supp_rates_len; i++)
|
|
|
++ {
|
|
|
++ if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_1MB)
|
|
|
++ tx_supp_rates |= IEEE80211_CCK_RATE_1MB_MASK;
|
|
|
++ if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_2MB)
|
|
|
++ tx_supp_rates |= IEEE80211_CCK_RATE_2MB_MASK;
|
|
|
++ if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_5MB)
|
|
|
++ tx_supp_rates |= IEEE80211_CCK_RATE_5MB_MASK;
|
|
|
++ if ((params->supp_rates[i] & 0x7f) == IEEE80211_CCK_RATE_11MB)
|
|
|
++ tx_supp_rates |= IEEE80211_CCK_RATE_11MB_MASK;
|
|
|
++
|
|
|
++ if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_6MB)
|
|
|
++ tx_supp_rates |= IEEE80211_OFDM_RATE_6MB_MASK;
|
|
|
++ if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_9MB)
|
|
|
++ tx_supp_rates |= IEEE80211_OFDM_RATE_9MB_MASK;
|
|
|
++ if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_12MB)
|
|
|
++ tx_supp_rates |= IEEE80211_OFDM_RATE_12MB_MASK;
|
|
|
++ if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_18MB)
|
|
|
++ tx_supp_rates |= IEEE80211_OFDM_RATE_18MB_MASK;
|
|
|
++
|
|
|
++ if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_24MB)
|
|
|
++ tx_supp_rates |= IEEE80211_OFDM_RATE_24MB_MASK;
|
|
|
++ if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_36MB)
|
|
|
++ tx_supp_rates |= IEEE80211_OFDM_RATE_36MB_MASK;
|
|
|
++ if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_48MB)
|
|
|
++ tx_supp_rates |= IEEE80211_OFDM_RATE_48MB_MASK;
|
|
|
++ if ((params->supp_rates[i] & 0x7f) == IEEE80211_OFDM_RATE_54MB)
|
|
|
++ tx_supp_rates |= IEEE80211_OFDM_RATE_54MB_MASK;
|
|
|
++
|
|
|
++ }
|
|
|
++
|
|
|
++ param.u.add_sta.tx_supp_rates = tx_supp_rates;
|
|
|
++*/
|
|
|
++
|
|
|
++#ifdef CONFIG_IEEE80211N
|
|
|
++ if (params->ht_capabilities && params->ht_capabilities->length>0)
|
|
|
++ {
|
|
|
++ struct ieee80211_ht_capability *pht_cap = (struct ieee80211_ht_capability *)¶ms->ht_capabilities->data;
|
|
|
++ memcpy((u8*)¶m.u.add_sta.ht_cap, (u8*)pht_cap, sizeof(struct ieee80211_ht_capability));
|
|
|
++
|
|
|
++ }
|
|
|
++#endif /* CONFIG_IEEE80211N */
|
|
|
++
|
|
|
++ return rtl871x_hostapd_ioctl(drv, ¶m, sizeof(param));
|
|
|
++#else
|
|
|
++ return 0;
|
|
|
++#endif
|
|
|
++}
|
|
|
++#endif
|
|
|
++
|
|
|
++static int rtl871x_sta_remove_ops(void *priv, const u8 *addr)
|
|
|
++{
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++ struct ieee_param param;
|
|
|
++
|
|
|
++ printf("+%s, " MACSTR " is sta address removed\n", __func__, MAC2STR(addr));
|
|
|
++
|
|
|
++ //hostap_sta_set_flags(drv, addr, 0, 0, ~WLAN_STA_AUTHORIZED);
|
|
|
++
|
|
|
++ memset(¶m, 0, sizeof(param));
|
|
|
++ param.cmd = RTL871X_HOSTAPD_REMOVE_STA;
|
|
|
++ memcpy(param.sta_addr, addr, ETH_ALEN);
|
|
|
++ if (rtl871x_hostapd_ioctl(drv, ¶m, sizeof(param))) {
|
|
|
++ printf("Could not remove station from kernel driver.\n");
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ return 0;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++#define RTL871X_HIDDEN_SSID_SUPPORT
|
|
|
++#ifdef RTL871X_HIDDEN_SSID_SUPPORT
|
|
|
++static int rtl871x_set_hidden_ssid_ops(const char *iface, void *priv, u8 value)
|
|
|
++{
|
|
|
++ int ret;
|
|
|
++ ieee_param pparam;
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++
|
|
|
++ printf("%s\n", __func__);
|
|
|
++
|
|
|
++ pparam.cmd = RTL871X_HOSTAPD_SET_HIDDEN_SSID;
|
|
|
++ pparam.u.wpa_param.name = 0;
|
|
|
++ pparam.u.wpa_param.value = value;
|
|
|
++
|
|
|
++ ret = rtl871x_hostapd_ioctl(drv, &pparam, sizeof(ieee_param));
|
|
|
++
|
|
|
++ return ret;
|
|
|
++}
|
|
|
++#endif //RTL871X_HIDDEN_SSID_SUPPORT
|
|
|
++
|
|
|
++static int rtl871x_set_beacon_ops(void *priv, struct wpa_driver_ap_params *params)
|
|
|
++{
|
|
|
++ int ret;
|
|
|
++ size_t sz;
|
|
|
++ ieee_param *pparam;
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++ struct hostapd_data *hapd = drv->hapd;
|
|
|
++
|
|
|
++ u8 *ssid_ie;
|
|
|
++ u8 ssid_len;
|
|
|
++ u8 expend_len = 0;
|
|
|
++
|
|
|
++ if((params->head_len<24) ||(!params->head))
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ printf("%s\n", __func__);
|
|
|
++
|
|
|
++
|
|
|
++#ifdef RTL871X_HIDDEN_SSID_SUPPORT
|
|
|
++ rtl871x_set_hidden_ssid_ops(drv->iface, priv, hapd->conf->ignore_broadcast_ssid);
|
|
|
++
|
|
|
++ ssid_ie = (u8 *)get_ie((params->head+24+12), (params->head_len-24-12), WLAN_EID_SSID);
|
|
|
++
|
|
|
++ if(hapd->conf->ignore_broadcast_ssid == 2)
|
|
|
++ {
|
|
|
++ ssid_len = ssid_ie[1];
|
|
|
++
|
|
|
++ //confirm the ssid_len
|
|
|
++ if(ssid_len != hapd->conf->ssid.ssid_len)
|
|
|
++ {
|
|
|
++ printf("%s ssid_len(%u) != hapd->conf->ssid.ssid_len(%u)!!\n", __func__
|
|
|
++ , ssid_len, hapd->conf->ssid.ssid_len
|
|
|
++ );
|
|
|
++ }
|
|
|
++
|
|
|
++ memcpy(ssid_ie+2, hapd->conf->ssid.ssid, ssid_len);
|
|
|
++ }
|
|
|
++ else if(hapd->conf->ignore_broadcast_ssid == 1)
|
|
|
++ {
|
|
|
++ expend_len = hapd->conf->ssid.ssid_len;
|
|
|
++ printf("%s ignore_broadcast_ssid:%d, %s,%u, expend_len:%u\n", __func__
|
|
|
++ , hapd->conf->ignore_broadcast_ssid
|
|
|
++ , hapd->conf->ssid.ssid
|
|
|
++ , hapd->conf->ssid.ssid_len
|
|
|
++ , expend_len
|
|
|
++ );
|
|
|
++ }
|
|
|
++#endif //RTL871X_HIDDEN_SSID_SUPPORT
|
|
|
++
|
|
|
++ sz = params->head_len+params->tail_len+12-24 + 2 + expend_len;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed
|
|
|
++ pparam = os_zalloc(sz);
|
|
|
++ if (pparam == NULL) {
|
|
|
++ return -ENOMEM;
|
|
|
++ }
|
|
|
++
|
|
|
++ pparam->cmd = RTL871X_HOSTAPD_SET_BEACON;
|
|
|
++
|
|
|
++ memcpy(pparam->u.bcn_ie.reserved, &hapd->conf->max_num_sta, 2);//for set max_num_sta
|
|
|
++
|
|
|
++#ifdef RTL871X_HIDDEN_SSID_SUPPORT
|
|
|
++ if(hapd->conf->ignore_broadcast_ssid == 1)
|
|
|
++ {
|
|
|
++ u8 *ssid_ie_next = params->head+24+12+2;
|
|
|
++ size_t head_remain_len = params->head_len-24-12-2;
|
|
|
++
|
|
|
++ memcpy(pparam->u.bcn_ie.buf, (params->head+24), 12);
|
|
|
++
|
|
|
++ pparam->u.bcn_ie.buf[12] = WLAN_EID_SSID;
|
|
|
++ pparam->u.bcn_ie.buf[13] = expend_len;
|
|
|
++ memcpy(pparam->u.bcn_ie.buf+12+2, hapd->conf->ssid.ssid, expend_len);
|
|
|
++
|
|
|
++ memcpy(pparam->u.bcn_ie.buf+12+2+expend_len, ssid_ie_next, head_remain_len);// 24=beacon header len.
|
|
|
++ memcpy(&pparam->u.bcn_ie.buf[params->head_len-24+expend_len], params->tail, params->tail_len);
|
|
|
++ }
|
|
|
++ else
|
|
|
++#endif //RTL871X_HIDDEN_SSID_SUPPORT
|
|
|
++ {
|
|
|
++ memcpy(pparam->u.bcn_ie.buf, (params->head+24), (params->head_len-24));// 24=beacon header len.
|
|
|
++ memcpy(&pparam->u.bcn_ie.buf[params->head_len-24], params->tail, params->tail_len);
|
|
|
++ }
|
|
|
++
|
|
|
++ ret = rtl871x_hostapd_ioctl(drv, pparam, sz);
|
|
|
++
|
|
|
++ os_free(pparam);
|
|
|
++
|
|
|
++ //rtl871x_set_max_num_sta(drv);
|
|
|
++
|
|
|
++ return ret;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++/*
|
|
|
++enum wpa_alg {
|
|
|
++ WPA_ALG_NONE,
|
|
|
++ WPA_ALG_WEP,
|
|
|
++ WPA_ALG_TKIP,
|
|
|
++ WPA_ALG_CCMP,
|
|
|
++ WPA_ALG_IGTK,
|
|
|
++ WPA_ALG_PMK
|
|
|
++};
|
|
|
++*/
|
|
|
++static int rtl871x_set_key_ops(const char *ifname, void *priv, enum wpa_alg alg,
|
|
|
++ const u8 *addr, int idx, int txkey, const u8 *seq,
|
|
|
++ size_t seq_len, const u8 *key, size_t key_len)
|
|
|
++{
|
|
|
++ ieee_param *param;
|
|
|
++ u8 *buf;
|
|
|
++ char *alg_str;
|
|
|
++ size_t blen;
|
|
|
++ int ret = 0;
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++
|
|
|
++ printf("%s\n", __func__);
|
|
|
++
|
|
|
++ blen = sizeof(*param) + key_len;
|
|
|
++ buf = os_zalloc(blen);
|
|
|
++ if (buf == NULL)
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ param = (ieee_param *)buf;
|
|
|
++ param->cmd = RTL871X_SET_ENCRYPTION;
|
|
|
++ if (addr == NULL)
|
|
|
++ memset(param->sta_addr, 0xff, ETH_ALEN);
|
|
|
++ else
|
|
|
++ memcpy(param->sta_addr, addr, ETH_ALEN);
|
|
|
++
|
|
|
++
|
|
|
++ switch (alg) {
|
|
|
++ case WPA_ALG_NONE:
|
|
|
++ alg_str = "none";
|
|
|
++ break;
|
|
|
++ case WPA_ALG_WEP:
|
|
|
++ //cipher = IEEE80211_CIPHER_WEP;
|
|
|
++ alg_str = "WEP";
|
|
|
++ break;
|
|
|
++ case WPA_ALG_TKIP:
|
|
|
++ //cipher = IEEE80211_CIPHER_TKIP;
|
|
|
++ alg_str = "TKIP";
|
|
|
++ break;
|
|
|
++ case WPA_ALG_CCMP:
|
|
|
++ //cipher = IEEE80211_CIPHER_AES_CCM;
|
|
|
++ alg_str = "CCMP";
|
|
|
++ break;
|
|
|
++ default:
|
|
|
++ printf("%s: unknown/unsupported algorithm %d\n",
|
|
|
++ __func__, alg);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ os_strlcpy((char *) param->u.crypt.alg, alg_str,
|
|
|
++ IEEE_CRYPT_ALG_NAME_LEN);
|
|
|
++
|
|
|
++ //param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
|
|
|
++ param->u.crypt.set_tx = txkey ? 1 : 0;
|
|
|
++ param->u.crypt.idx = idx;
|
|
|
++ param->u.crypt.key_len = key_len;
|
|
|
++
|
|
|
++ //memcpy((u8 *) (param + 1), key, key_len);
|
|
|
++ memcpy(param->u.crypt.key, key, key_len);
|
|
|
++
|
|
|
++ if (rtl871x_hostapd_ioctl(drv, param, blen)) {
|
|
|
++ printf("Failed to set encryption.\n");
|
|
|
++ ret = -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ os_free(buf);
|
|
|
++
|
|
|
++ return ret;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++/*
|
|
|
++static int rtl871x_set_encryption_ops(const char *ifname, void *priv,
|
|
|
++ const char *alg, const u8 *addr,
|
|
|
++ int idx, const u8 *key, size_t key_len,
|
|
|
++ int txkey)
|
|
|
++{
|
|
|
++ ieee_param *param;
|
|
|
++ u8 *buf;
|
|
|
++ size_t blen;
|
|
|
++ int ret = 0;
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++
|
|
|
++ printf("%s\n", __func__);
|
|
|
++#if 0
|
|
|
++ blen = sizeof(*param) + key_len;
|
|
|
++ buf = os_zalloc(blen);
|
|
|
++ if (buf == NULL)
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ param = (ieee_param *)buf;
|
|
|
++ param->cmd = RTL871X_SET_ENCRYPTION;
|
|
|
++ if (addr == NULL)
|
|
|
++ memset(param->sta_addr, 0xff, ETH_ALEN);
|
|
|
++ else
|
|
|
++ memcpy(param->sta_addr, addr, ETH_ALEN);
|
|
|
++
|
|
|
++ os_strlcpy((char *) param->u.crypt.alg, alg,
|
|
|
++ IEEE_CRYPT_ALG_NAME_LEN);
|
|
|
++
|
|
|
++ //param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
|
|
|
++ param->u.crypt.set_tx = txkey ? 1 : 0;
|
|
|
++ param->u.crypt.idx = idx;
|
|
|
++ param->u.crypt.key_len = key_len;
|
|
|
++
|
|
|
++ //memcpy((u8 *) (param + 1), key, key_len);
|
|
|
++ memcpy(param->u.crypt.key, key, key_len);
|
|
|
++
|
|
|
++ if (rtl871x_hostapd_ioctl(drv, param, blen)) {
|
|
|
++ printf("Failed to set encryption.\n");
|
|
|
++ ret = -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ os_free(buf);
|
|
|
++#endif
|
|
|
++ return ret;
|
|
|
++
|
|
|
++}
|
|
|
++*/
|
|
|
++
|
|
|
++//static int rtl871x_sta_deauth_ops(void *priv, const u8 *addr, int reason)
|
|
|
++static int rtl871x_sta_deauth_ops(void *priv, const u8 *own_addr, const u8 *addr,
|
|
|
++ int reason)
|
|
|
++{
|
|
|
++ printf("+%s, " MACSTR " is deauth, reason=%d\n", __func__, MAC2STR(addr), reason);
|
|
|
++
|
|
|
++ //struct hostap_driver_data *drv = priv;
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++ struct ieee80211_mgmt mgmt;
|
|
|
++
|
|
|
++ memset(&mgmt, 0, sizeof(mgmt));
|
|
|
++ mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
|
|
++ WLAN_FC_STYPE_DEAUTH);
|
|
|
++
|
|
|
++ memcpy(mgmt.da, addr, ETH_ALEN);
|
|
|
++ //memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN);
|
|
|
++ //memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN);
|
|
|
++ memcpy(mgmt.sa, own_addr, ETH_ALEN);
|
|
|
++ memcpy(mgmt.bssid, own_addr, ETH_ALEN);
|
|
|
++ mgmt.u.deauth.reason_code = host_to_le16(reason);
|
|
|
++
|
|
|
++ return rtl871x_send_mgmt_frame_ops(drv, &mgmt, IEEE80211_HDRLEN +
|
|
|
++ sizeof(mgmt.u.deauth), 0);
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
++//static int rtl871x_sta_disassoc_ops(void *priv, const u8 *addr, int reason)
|
|
|
++static int rtl871x_sta_disassoc_ops(void *priv, const u8 *own_addr, const u8 *addr,
|
|
|
++ int reason)
|
|
|
++{
|
|
|
++ printf("+%s, " MACSTR " is disassoc, reason=%d\n", __func__, MAC2STR(addr), reason);
|
|
|
++
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++ struct ieee80211_mgmt mgmt;
|
|
|
++
|
|
|
++ memset(&mgmt, 0, sizeof(mgmt));
|
|
|
++ mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
|
|
|
++ WLAN_FC_STYPE_DISASSOC);
|
|
|
++
|
|
|
++ memcpy(mgmt.da, addr, ETH_ALEN);
|
|
|
++ //memcpy(mgmt.sa, drv->hapd->own_addr, ETH_ALEN);
|
|
|
++ //memcpy(mgmt.bssid, drv->hapd->own_addr, ETH_ALEN);
|
|
|
++ memcpy(mgmt.sa, own_addr, ETH_ALEN);
|
|
|
++ memcpy(mgmt.bssid, own_addr, ETH_ALEN);
|
|
|
++
|
|
|
++ mgmt.u.disassoc.reason_code = host_to_le16(reason);
|
|
|
++
|
|
|
++ return rtl871x_send_mgmt_frame_ops(drv, &mgmt, IEEE80211_HDRLEN +
|
|
|
++ sizeof(mgmt.u.disassoc), 0);
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++static int rtl871x_set_wps_assoc_resp_ie(struct rtl871x_driver_data *drv, const void *ie, size_t len)
|
|
|
++{
|
|
|
++ int ret;
|
|
|
++ size_t sz;
|
|
|
++ ieee_param *pparam;
|
|
|
++
|
|
|
++
|
|
|
++ printf("%s\n", __func__);
|
|
|
++
|
|
|
++ sz = len + 12 + 2;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed
|
|
|
++ pparam = os_zalloc(sz);
|
|
|
++ if (pparam == NULL) {
|
|
|
++ return -ENOMEM;
|
|
|
++ }
|
|
|
++
|
|
|
++ pparam->cmd = RTL871X_HOSTAPD_SET_WPS_ASSOC_RESP;
|
|
|
++
|
|
|
++ if(ie && len>0)
|
|
|
++ {
|
|
|
++ memcpy(pparam->u.bcn_ie.buf, ie, len);
|
|
|
++ }
|
|
|
++
|
|
|
++ ret = rtl871x_hostapd_ioctl(drv, pparam, sz);
|
|
|
++
|
|
|
++ os_free(pparam);
|
|
|
++
|
|
|
++ return ret;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++static int rtl871x_set_wps_beacon_ie(struct rtl871x_driver_data *drv, const void *ie, size_t len)
|
|
|
++{
|
|
|
++ int ret;
|
|
|
++ size_t sz;
|
|
|
++ ieee_param *pparam;
|
|
|
++
|
|
|
++
|
|
|
++ printf("%s\n", __func__);
|
|
|
++
|
|
|
++ sz = len + 12 + 2;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed
|
|
|
++ pparam = os_zalloc(sz);
|
|
|
++ if (pparam == NULL) {
|
|
|
++ return -ENOMEM;
|
|
|
++ }
|
|
|
++
|
|
|
++ pparam->cmd = RTL871X_HOSTAPD_SET_WPS_BEACON;
|
|
|
++
|
|
|
++ if(ie && len>0)
|
|
|
++ {
|
|
|
++ memcpy(pparam->u.bcn_ie.buf, ie, len);
|
|
|
++ }
|
|
|
++
|
|
|
++ ret = rtl871x_hostapd_ioctl(drv, pparam, sz);
|
|
|
++
|
|
|
++ os_free(pparam);
|
|
|
++
|
|
|
++ return ret;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++static int rtl871x_set_wps_probe_resp_ie(struct rtl871x_driver_data *drv, const void *ie, size_t len)
|
|
|
++{
|
|
|
++ int ret;
|
|
|
++ size_t sz;
|
|
|
++ ieee_param *pparam;
|
|
|
++
|
|
|
++
|
|
|
++ printf("%s\n", __func__);
|
|
|
++
|
|
|
++ sz = len + 12 + 2;// 12+2 = cmd+sta_addr+reserved, sizeof(ieee_param)=64, no packed
|
|
|
++ pparam = os_zalloc(sz);
|
|
|
++ if (pparam == NULL) {
|
|
|
++ return -ENOMEM;
|
|
|
++ }
|
|
|
++
|
|
|
++ pparam->cmd = RTL871X_HOSTAPD_SET_WPS_PROBE_RESP;
|
|
|
++
|
|
|
++ if(ie && len>0)
|
|
|
++ {
|
|
|
++ memcpy(pparam->u.bcn_ie.buf, ie, len);
|
|
|
++ }
|
|
|
++
|
|
|
++ ret = rtl871x_hostapd_ioctl(drv, pparam, sz);
|
|
|
++
|
|
|
++ os_free(pparam);
|
|
|
++
|
|
|
++ return ret;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++static int rtl871x_set_ap_wps_ie(void *priv, const struct wpabuf *beacon,
|
|
|
++ const struct wpabuf *proberesp, const struct wpabuf *assocresp)
|
|
|
++{
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++
|
|
|
++ if (rtl871x_set_wps_assoc_resp_ie(drv, assocresp ? wpabuf_head(assocresp) : NULL,
|
|
|
++ assocresp ? wpabuf_len(assocresp) : 0))
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ if (rtl871x_set_wps_beacon_ie(drv, beacon ? wpabuf_head(beacon) : NULL,
|
|
|
++ beacon ? wpabuf_len(beacon) : 0))
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ return rtl871x_set_wps_probe_resp_ie(drv,
|
|
|
++ proberesp ? wpabuf_head(proberesp) : NULL,
|
|
|
++ proberesp ? wpabuf_len(proberesp): 0);
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++static int rtl871x_sta_flush_ops(void *priv)
|
|
|
++{
|
|
|
++ ieee_param param;
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++
|
|
|
++ memset(¶m, 0, sizeof(param));
|
|
|
++
|
|
|
++ param.cmd = RTL871X_HOSTAPD_FLUSH;
|
|
|
++
|
|
|
++ return rtl871x_hostapd_ioctl(drv, ¶m, sizeof(param));
|
|
|
++}
|
|
|
++
|
|
|
++static void *rtl871x_driver_init_ops(struct hostapd_data *hapd, struct wpa_init_params *params)
|
|
|
++{
|
|
|
++ struct rtl871x_driver_data *drv;
|
|
|
++ struct ifreq ifr;
|
|
|
++ //struct iwreq iwr;
|
|
|
++ char ifrn_name[IFNAMSIZ + 1];//for mgnt_l2_sock/mgnt_sock
|
|
|
++ char brname[IFNAMSIZ];
|
|
|
++
|
|
|
++ drv = os_zalloc(sizeof(struct rtl871x_driver_data));
|
|
|
++ if (drv == NULL) {
|
|
|
++ printf("Could not allocate memory for rtl871x driver data\n");
|
|
|
++ return NULL;
|
|
|
++ }
|
|
|
++
|
|
|
++ drv->hapd = hapd;
|
|
|
++ drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
|
|
|
++ if (drv->ioctl_sock < 0) {
|
|
|
++ perror("socket[PF_INET,SOCK_DGRAM]");
|
|
|
++ goto bad;
|
|
|
++ }
|
|
|
++ os_memcpy(drv->iface, params->ifname, sizeof(drv->iface));
|
|
|
++
|
|
|
++ linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1);/*set interface up*/
|
|
|
++
|
|
|
++ os_memset(&ifr, 0, sizeof(ifr));
|
|
|
++ os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name));
|
|
|
++ if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) {
|
|
|
++ perror("ioctl(SIOCGIFINDEX)");
|
|
|
++ goto bad;
|
|
|
++ }
|
|
|
++ drv->ifindex = ifr.ifr_ifindex;
|
|
|
++ printf("drv->ifindex=%d\n", drv->ifindex);
|
|
|
++
|
|
|
++ drv->l2_sock = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL,
|
|
|
++ rtl871x_handle_read, drv, 1);
|
|
|
++
|
|
|
++ if (drv->l2_sock == NULL)
|
|
|
++ goto bad;
|
|
|
++
|
|
|
++ if (l2_packet_get_own_addr(drv->l2_sock, params->own_addr))
|
|
|
++ goto bad;
|
|
|
++
|
|
|
++
|
|
|
++ if (params->bridge[0]) {
|
|
|
++ wpa_printf(MSG_DEBUG, "Configure bridge %s for EAPOL traffic.",
|
|
|
++ params->bridge[0]);
|
|
|
++ drv->l2_sock_recv = l2_packet_init(params->bridge[0], NULL,
|
|
|
++ ETH_P_EAPOL, rtl871x_handle_read, drv,
|
|
|
++ 1);
|
|
|
++ if (drv->l2_sock_recv == NULL)
|
|
|
++ {
|
|
|
++ //goto bad;
|
|
|
++ drv->l2_sock_recv = drv->l2_sock;
|
|
|
++ printf("no br0 interface , let l2_sock_recv==l2_sock_xmit=0x%p\n", drv->l2_sock);
|
|
|
++ }
|
|
|
++
|
|
|
++ } else if (linux_br_get(brname, drv->iface) == 0) {
|
|
|
++ wpa_printf(MSG_DEBUG, "Interface in bridge %s; configure for "
|
|
|
++ "EAPOL receive", brname);
|
|
|
++ drv->l2_sock_recv = l2_packet_init(brname, NULL, ETH_P_EAPOL,
|
|
|
++ rtl871x_handle_read, drv, 1);
|
|
|
++ if (drv->l2_sock_recv == NULL)
|
|
|
++ goto bad;
|
|
|
++ }
|
|
|
++ else
|
|
|
++ {
|
|
|
++ drv->l2_sock_recv = drv->l2_sock;
|
|
|
++ printf("l2_sock_recv==l2_sock_xmit=0x%p\n", drv->l2_sock);
|
|
|
++ }
|
|
|
++
|
|
|
++
|
|
|
++ os_memset(ifrn_name, 0, sizeof(ifrn_name));
|
|
|
++ //snprintf(ifrn_name, sizeof(ifrn_name), "mgnt.%s_rena", drv->iface);
|
|
|
++ snprintf(ifrn_name, sizeof(ifrn_name), "mgnt.%s", "wlan0"/*drv->iface*/);
|
|
|
++#ifdef CONFIG_MGNT_L2SOCK
|
|
|
++ drv->mgnt_l2_sock = NULL;
|
|
|
++ drv->mgnt_l2_sock = l2_packet_init(ifrn_name, NULL, ETH_P_80211_RAW,
|
|
|
++ rtl871x_recvive_mgmt_frame, drv, 1);
|
|
|
++ if (drv->mgnt_l2_sock == NULL)
|
|
|
++ goto bad;
|
|
|
++
|
|
|
++#else
|
|
|
++
|
|
|
++#ifdef CONFIG_MLME_OFFLOAD
|
|
|
++ drv->mgnt_sock = -1;
|
|
|
++#else
|
|
|
++ drv->mgnt_sock = rtl871x_mgnt_sock_init(drv, ifrn_name);
|
|
|
++ if (drv->mgnt_sock < 0) {
|
|
|
++ goto bad;
|
|
|
++ }
|
|
|
++#endif
|
|
|
++
|
|
|
++#endif
|
|
|
++
|
|
|
++
|
|
|
++ //madwifi_set_iface_flags(drv, 0); /* mark down during setup */
|
|
|
++ //madwifi_set_privacy(drv->iface, drv, 0); /* default to no privacy */
|
|
|
++
|
|
|
++
|
|
|
++ //linux_set_iface_flags(drv->ioctl_sock, drv->iface, 1);/*set interface up*/
|
|
|
++
|
|
|
++
|
|
|
++ //enter MASTER MODE when init.
|
|
|
++ if(rtl871x_set_mode(drv, IW_MODE_MASTER)<0)
|
|
|
++ {
|
|
|
++ printf("Could not set interface to master mode!\n");
|
|
|
++ goto bad;
|
|
|
++ }
|
|
|
++
|
|
|
++/*
|
|
|
++ memset(&iwr, 0, sizeof(iwr));
|
|
|
++ os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
|
|
|
++ iwr.u.mode = IW_MODE_MASTER;
|
|
|
++ if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
|
|
|
++ perror("ioctl[SIOCSIWMODE]");
|
|
|
++ printf("Could not set interface to master mode!\n");
|
|
|
++ goto bad;
|
|
|
++ }
|
|
|
++*/
|
|
|
++
|
|
|
++#ifndef CONFIG_MLME_OFFLOAD
|
|
|
++ rtl871x_set_iface_flags(drv, 1); /*set mgnt interface up*/
|
|
|
++#endif
|
|
|
++
|
|
|
++
|
|
|
++ if (rtl871x_wireless_event_init(drv))
|
|
|
++ goto bad;
|
|
|
++
|
|
|
++
|
|
|
++ os_memcpy(drv->hw_mac, params->own_addr, ETH_ALEN);
|
|
|
++
|
|
|
++ return drv;
|
|
|
++
|
|
|
++bad:
|
|
|
++
|
|
|
++ if (drv->l2_sock_recv != NULL && drv->l2_sock_recv != drv->l2_sock)
|
|
|
++ l2_packet_deinit(drv->l2_sock_recv);
|
|
|
++
|
|
|
++ if (drv->l2_sock != NULL)
|
|
|
++ l2_packet_deinit(drv->l2_sock);
|
|
|
++
|
|
|
++ if (drv->ioctl_sock >= 0)
|
|
|
++ close(drv->ioctl_sock);
|
|
|
++
|
|
|
++#ifdef CONFIG_MGNT_L2SOCK
|
|
|
++ if ( drv->mgnt_l2_sock != NULL)
|
|
|
++ l2_packet_deinit(drv->mgnt_l2_sock);
|
|
|
++#else
|
|
|
++ if (drv->mgnt_sock >= 0)
|
|
|
++ close(drv->mgnt_sock);
|
|
|
++#endif
|
|
|
++
|
|
|
++ if (drv != NULL)
|
|
|
++ free(drv);
|
|
|
++
|
|
|
++ return NULL;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++static void rtl871x_driver_deinit_ops(void *priv)
|
|
|
++{
|
|
|
++ //struct iwreq iwr;
|
|
|
++ struct rtl871x_driver_data *drv = priv;
|
|
|
++
|
|
|
++ //back to INFRA MODE when exit.
|
|
|
++/*
|
|
|
++ memset(&iwr, 0, sizeof(iwr));
|
|
|
++ os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
|
|
|
++ iwr.u.mode = IW_MODE_INFRA;
|
|
|
++ if (ioctl(drv->ioctl_sock, SIOCSIWMODE, &iwr) < 0) {
|
|
|
++ perror("ioctl[SIOCSIWMODE]");
|
|
|
++ }
|
|
|
++*/
|
|
|
++ rtl871x_set_mode(drv, IW_MODE_INFRA);
|
|
|
++
|
|
|
++
|
|
|
++ if (drv->ioctl_sock >= 0)
|
|
|
++ close(drv->ioctl_sock);
|
|
|
++
|
|
|
++
|
|
|
++ if (drv->l2_sock_recv != NULL && drv->l2_sock_recv != drv->l2_sock)
|
|
|
++ l2_packet_deinit(drv->l2_sock_recv);
|
|
|
++
|
|
|
++ if(drv->l2_sock)
|
|
|
++ l2_packet_deinit(drv->l2_sock);
|
|
|
++
|
|
|
++ //if (drv->sock_xmit != NULL)
|
|
|
++ // l2_packet_deinit(drv->sock_xmit);
|
|
|
++
|
|
|
++#ifdef CONFIG_MGNT_L2SOCK
|
|
|
++ if (drv->mgnt_l2_sock)
|
|
|
++ l2_packet_deinit(drv->mgnt_l2_sock);
|
|
|
++#else
|
|
|
++ if (drv->mgnt_sock >= 0)
|
|
|
++ close(drv->mgnt_sock);
|
|
|
++#endif
|
|
|
++
|
|
|
++ os_free(drv);
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
++
|
|
|
++const struct wpa_driver_ops wpa_driver_rtw_ops = {
|
|
|
++ .name = "rtl871xdrv",
|
|
|
++ //.init = rtl871x_driver_init_ops,
|
|
|
++ //.deinit = rtl871x_driver_deinit_ops,
|
|
|
++ .hapd_init = rtl871x_driver_init_ops,
|
|
|
++ .hapd_deinit = rtl871x_driver_deinit_ops,
|
|
|
++ //.wireless_event_init = rtl871x_wireless_event_init_ops,
|
|
|
++ //.wireless_event_deinit = rtl871x_wireless_event_deinit_ops,
|
|
|
++ //.send_eapol = rtl871x_send_eapol_ops,
|
|
|
++ .hapd_send_eapol = rtl871x_send_eapol_ops,
|
|
|
++ //.send_ether = rtl871x_driver_send_ether_ops,
|
|
|
++ //.send_mgmt_frame = rtl871x_send_mgmt_frame_ops,
|
|
|
++ .get_hw_feature_data = rtl871x_get_hw_feature_data_ops,
|
|
|
++ //.sta_add = rtl871x_sta_add_ops,
|
|
|
++ //.sta_add2 = rtl871x_sta_add2_ops,
|
|
|
++ .sta_remove = rtl871x_sta_remove_ops,
|
|
|
++ .set_ap = rtl871x_set_beacon_ops,
|
|
|
++ //.set_encryption = rtl871x_set_encryption_ops,
|
|
|
++ .set_key = rtl871x_set_key_ops,
|
|
|
++ .sta_deauth = rtl871x_sta_deauth_ops,
|
|
|
++ .sta_disassoc = rtl871x_sta_disassoc_ops,
|
|
|
++ //.set_wps_beacon_ie = rtl871x_set_wps_beacon_ie_ops,
|
|
|
++ //.set_wps_probe_resp_ie = rtl871x_set_wps_probe_resp_ie_ops,
|
|
|
++ .set_ap_wps_ie = rtl871x_set_ap_wps_ie,
|
|
|
++ .flush = rtl871x_sta_flush_ops,
|
|
|
++};
|
|
|
++
|
|
|
+diff --git a/src/drivers/driver_wext.c b/src/drivers/driver_wext.c
|
|
|
+index 791cd5d..c8cb71b 100644
|
|
|
+--- a/src/drivers/driver_wext.c
|
|
|
++++ b/src/drivers/driver_wext.c
|
|
|
+@@ -1081,6 +1081,38 @@ void wpa_driver_wext_scan_timeout(void *eloop_ctx, void *timeout_ctx)
|
|
|
+ wpa_supplicant_event(timeout_ctx, EVENT_SCAN_RESULTS, NULL);
|
|
|
+ }
|
|
|
+
|
|
|
++//added for wps2.0 @20110519
|
|
|
++static int wpa_driver_wext_set_probe_req_ie(struct wpa_driver_wext_data *drv, const u8 *extra_ies,
|
|
|
++ size_t extra_ies_len)
|
|
|
++{
|
|
|
++ unsigned char *pbuf;
|
|
|
++ struct iwreq iwr;
|
|
|
++ int ret = 0;
|
|
|
++
|
|
|
++ pbuf = os_malloc(extra_ies_len);
|
|
|
++ os_memset(pbuf, 0, extra_ies_len);
|
|
|
++
|
|
|
++ os_memset(&iwr, 0, sizeof(iwr));
|
|
|
++ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
|
|
|
++
|
|
|
++ os_memcpy(pbuf, extra_ies, extra_ies_len);
|
|
|
++
|
|
|
++ iwr.u.data.pointer = (caddr_t)pbuf;
|
|
|
++ iwr.u.data.length = extra_ies_len;
|
|
|
++ iwr.u.data.flags = 0x8766;//magic number
|
|
|
++
|
|
|
++ if (ioctl(drv->ioctl_sock, SIOCSIWPRIV, &iwr) < 0) {
|
|
|
++ perror("ioctl[SIOCSIWMLME]");
|
|
|
++ ret = -1;
|
|
|
++ }
|
|
|
++
|
|
|
++ if(pbuf)
|
|
|
++ os_free(pbuf);
|
|
|
++
|
|
|
++ return ret;
|
|
|
++
|
|
|
++}
|
|
|
++
|
|
|
+
|
|
|
+ /**
|
|
|
+ * wpa_driver_wext_scan - Request the driver to initiate scan
|
|
|
+@@ -1103,6 +1135,10 @@ int wpa_driver_wext_scan(void *priv, struct wpa_driver_scan_params *params)
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
++ //added for wps2.0 @20110519
|
|
|
++ wpa_driver_wext_set_probe_req_ie(drv, params->extra_ies,
|
|
|
++ params->extra_ies_len);
|
|
|
++
|
|
|
+ os_memset(&iwr, 0, sizeof(iwr));
|
|
|
+ os_strlcpy(iwr.ifr_name, drv->ifname, IFNAMSIZ);
|
|
|
+
|
|
|
+diff --git a/src/drivers/drivers.c b/src/drivers/drivers.c
|
|
|
+index 00773a7..f422c95 100644
|
|
|
+--- a/src/drivers/drivers.c
|
|
|
++++ b/src/drivers/drivers.c
|
|
|
+@@ -46,5 +46,8 @@ const struct wpa_driver_ops *const wpa_drivers[] =
|
|
|
+ #ifdef CONFIG_DRIVER_NONE
|
|
|
+ &wpa_driver_none_ops,
|
|
|
+ #endif /* CONFIG_DRIVER_NONE */
|
|
|
++#ifdef CONFIG_DRIVER_RTW
|
|
|
++ &wpa_driver_rtw_ops,
|
|
|
++#endif /* CONFIG_DRIVER_RTW */
|
|
|
+ NULL
|
|
|
+ };
|
|
|
+diff --git a/src/drivers/drivers.mak b/src/drivers/drivers.mak
|
|
|
+index c6d3f81..a784e03 100644
|
|
|
+--- a/src/drivers/drivers.mak
|
|
|
++++ b/src/drivers/drivers.mak
|
|
|
+@@ -79,6 +79,10 @@ DRV_CFLAGS += -DCONFIG_DRIVER_BSD
|
|
|
+ DRV_OBJS += ../src/drivers/driver_bsd.o
|
|
|
+ CONFIG_L2_FREEBSD=y
|
|
|
+ CONFIG_DNET_PCAP=y
|
|
|
++ifdef CONFIG_SUPPORT_RTW_DRIVER
|
|
|
++DRV_CFLAGS += -DCONFIG_SUPPORT_RTW_DRIVER -DCONFIG_DRIVER_RTL_DFS
|
|
|
++NEED_AP_MLME=y
|
|
|
++endif
|
|
|
+ endif
|
|
|
+
|
|
|
+ ifdef CONFIG_DRIVER_OPENBSD
|
|
|
+@@ -89,6 +93,17 @@ DRV_CFLAGS += -DCONFIG_DRIVER_OPENBSD
|
|
|
+ DRV_OBJS += ../src/drivers/driver_openbsd.o
|
|
|
+ endif
|
|
|
+
|
|
|
++ifdef CONFIG_DRIVER_RTW
|
|
|
++#CFLAGS += -DCONFIG_DRIVER_RTL
|
|
|
++#OBJS += driver_rtl.o
|
|
|
++DRV_AP_CFLAGS += -DCONFIG_DRIVER_RTW -DCONFIG_DRIVER_RTL_DFS
|
|
|
++DRV_AP_OBJS += ../src/drivers/driver_rtw.o
|
|
|
++CONFIG_L2_PACKET=linux
|
|
|
++NEED_NETLINK=y
|
|
|
++NEED_LINUX_IOCTL=y
|
|
|
++NEED_AP_MLME=y
|
|
|
++endif
|
|
|
++
|
|
|
+ ifdef CONFIG_DRIVER_NONE
|
|
|
+ DRV_CFLAGS += -DCONFIG_DRIVER_NONE
|
|
|
+ DRV_OBJS += ../src/drivers/driver_none.o
|
|
|
+diff --git a/src/eap_peer/eap_wsc.c b/src/eap_peer/eap_wsc.c
|
|
|
+index d140c88..df71540 100644
|
|
|
+--- a/src/eap_peer/eap_wsc.c
|
|
|
++++ b/src/eap_peer/eap_wsc.c
|
|
|
+@@ -565,8 +565,13 @@ send_msg:
|
|
|
+ r = eap_wsc_build_msg(data, ret, id);
|
|
|
+ if (data->state == FAIL && ret->methodState == METHOD_DONE) {
|
|
|
+ /* Use reduced client timeout for WPS to avoid long wait */
|
|
|
++#if 0 /* Aries add, 2012/06/12, extend timeout for AP IOT */
|
|
|
++ if (sm->ClientTimeout > 4)
|
|
|
++ sm->ClientTimeout = 4;
|
|
|
++#else
|
|
|
+ if (sm->ClientTimeout > 2)
|
|
|
+ sm->ClientTimeout = 2;
|
|
|
++#endif
|
|
|
+ }
|
|
|
+ return r;
|
|
|
+ }
|
|
|
+diff --git a/src/wps/wps.c b/src/wps/wps.c
|
|
|
+index fade6b6..36cb3de 100644
|
|
|
+--- a/src/wps/wps.c
|
|
|
++++ b/src/wps/wps.c
|
|
|
+@@ -325,11 +325,15 @@ int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr,
|
|
|
+ if (wps_parse_msg(msg, &attr) < 0)
|
|
|
+ return 0;
|
|
|
+
|
|
|
++ return is_selected_pin_registrar(&attr);
|
|
|
++// Marked by Albert 2011/11/17
|
|
|
++// Some APs won't carry the AuthorizedMACs in the probe response.
|
|
|
++// So, skip this check will speed up the process to find the current AP out for WPS handshake.
|
|
|
++/*
|
|
|
+ if (!attr.version2 && ver1_compat) {
|
|
|
+ /*
|
|
|
+ * Version 1.0 AP - AuthorizedMACs not used, so revert back to
|
|
|
+ * old mechanism of using SelectedRegistrar.
|
|
|
+- */
|
|
|
+ return is_selected_pin_registrar(&attr);
|
|
|
+ }
|
|
|
+
|
|
|
+@@ -346,6 +350,7 @@ int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr,
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
++*/
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c
|
|
|
+index fac8bd8..7b41c90 100644
|
|
|
+--- a/src/wps/wps_registrar.c
|
|
|
++++ b/src/wps/wps_registrar.c
|
|
|
+@@ -589,9 +589,10 @@ static int wps_build_probe_config_methods(struct wps_registrar *reg,
|
|
|
+ * These are the methods that the AP supports as an Enrollee for adding
|
|
|
+ * external Registrars.
|
|
|
+ */
|
|
|
+- methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
|
|
|
+- methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
|
|
|
+- WPS_CONFIG_PHY_PUSHBUTTON);
|
|
|
++ methods = reg->wps->config_methods;
|
|
|
++ //methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
|
|
|
++ //methods &= ~(WPS_CONFIG_VIRT_PUSHBUTTON |
|
|
|
++ // WPS_CONFIG_PHY_PUSHBUTTON);
|
|
|
+ wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods);
|
|
|
+ wpabuf_put_be16(msg, ATTR_CONFIG_METHODS);
|
|
|
+ wpabuf_put_be16(msg, 2);
|