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 " 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 +#include + +#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 +#include +#include /* The L2 protocols */ +#include +#include +#else /* USE_KERNEL_HEADERS */ +#include +#include +//#include "wireless_copy.h" +#endif /* USE_KERNEL_HEADERS */ + +//#include + + +#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; iu.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(%lu)!!\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,%lu, 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);