Index: hostapd-rtk-0.6.10/hostapd/driver_realtek.c =================================================================== --- /dev/null +++ hostapd-rtk-0.6.10/hostapd/driver_realtek.c @@ -0,0 +1,3251 @@ +/* + * hostapd / Driver interaction with Realtek 802.11 driver + * Copyright (c) + * + * 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. + */ + +#include "includes.h" +#include "common.h" +#include +#include + +#include +#ifdef WME_NUM_AC +/* Assume this is built against BSD branch of realtek driver. */ +#define REALTEK_BSD +#include +#endif /* WME_NUM_AC */ +#include +#include + +#ifdef IEEE80211_IOCTL_SETWMMPARAMS +/* Assume this is built against realtek-ng */ +#define REALTEK_NG +#endif /* IEEE80211_IOCTL_SETWMMPARAMS */ + +#include +#include "wireless_copy.h" +//#include + +//#include + +#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 "eapol_sm.h" +#include "wpa.h" +#include "radius/radius.h" +#include "ieee802_11.h" +#include "accounting.h" +#include "common.h" +#include "wps_hostapd.h" + +#ifndef EAP_WPS +#define EAP_WPS +#endif + +#include "./driver_realtek.h" + +#ifdef CONFIG_WPS +#ifdef IEEE80211_IOCTL_FILTERFRAME +//#include +#ifndef __LINUX_IF_PACKET_H +//#ifndef __NETPACKET_PACKET_H +#include +//#include +#endif + +#ifndef ETH_P_80211_RAW +#define ETH_P_80211_RAW 0x0019 +#endif +#endif /* IEEE80211_IOCTL_FILTERFRAME */ +#endif /* CONFIG_WPS */ + +/* + * Avoid conflicts with hostapd definitions by undefining couple of defines + * from madwifi header files. + */ +#undef RSN_VERSION +#undef WPA_VERSION +#undef WPA_OUI_TYPE +#undef WME_OUI_TYPE + +#if defined(INBAND_CTRL) +#ifndef __IOH_H +#include +#endif +#define INBAND_INTF "br0" +#define INBAND_SLAVE ("001234567899") +#define INBAND_IOCTL_TYPE 0x8899 +#define INBAND_NETLINK_TYPE 0x9000 +#define INBAND_DEBUG 0 +#define INBAND_IOCTLPKT_DUMP //hex_dump +#undef STAND_ALONE +#define IWREQ_LEN 32 +#define INBAND_IOCTLTYPE_LEN 4 +#define INBAND_IOCTLHDR_LEN 6 +#define INBAND_PENDING_START(data) data+INBAND_IOCTLHDR_LEN+IWREQ_LEN +#define INBAND_IOCTLRET_PTR(data) data+INBAND_IOCTLTYPE_LEN +#define IOH_HDR_LEN sizeof(struct ioh_header) +#else +#define STAND_ALONE +#endif + +//#define HOST_LITTLE_ENDIAN 1 //mark_endian + +#ifdef RTK_MBSSID + +struct i802_bss { + //void *ctx; //back pointer to hapd per bss data + struct realtek_driver_data *drv; + struct i802_bss *next; + int ifindex; + char ifname[IFNAMSIZ + 1]; + struct l2_packet_data *sock_xmit; /* raw packet xmit socket */ + //unsigned int beacon_set:1; +}; + +#endif + + +struct realtek_driver_data { + //struct driver_ops ops; /* base class */ + struct hostapd_data *hapd; /* back pointer */ + + char iface[IFNAMSIZ + 1]; + int ifindex; + struct l2_packet_data *sock_xmit; /* raw packet xmit socket */ +#ifdef RTK_MBSSID + int sock_recv; +#else + struct l2_packet_data *sock_recv; /* raw packet recv socket */ +#endif + int ioctl_sock; /* socket for ioctl() use */ + int wext_sock; /* socket for wireless events */ + int we_version; + u8 acct_mac[ETH_ALEN]; + struct hostap_sta_driver_data acct_data; +#if defined(INBAND_CTRL) + struct ioh_class netlink_ioh_obj; +#endif + +#ifdef RTK_MBSSID + struct i802_bss first_bss; + int if_indices[RTK_MAX_IF_INDEX]; + int num_if_indices; +#endif +}; + +struct rtk_hapd_config rtk_config; + +const struct wpa_driver_ops wpa_driver_realtek_ops; + +static void realtek_deinit(void *priv); +static int realtek_sta_deauth(void *priv, const u8 *addr, int reason_code); + +#ifdef EAP_WPS +static int realtek_set_wps_beacon_ie(const char *ifname, void *priv, const u8 *iebuf, size_t iebuflen); +static int realtek_set_wps_probe_resp_ie(const char *ifname, void *priv, const u8 *iebuf, size_t iebuflen); +static int realtek_set_wps_assoc_resp_ie(const char *ifname, void *priv, const u8 *iebuf, size_t iebuflen); +static int realtek_start_receive_prob_req(void *priv); +#endif /* EAP_WPS */ + +#ifdef RTK_HAPD +static int realtek_driver_on(void *priv, int on); +static int realtek_hapd_config(void *priv); +#endif + +static int realtek_read_priv_vap_cfg(const char *ifname,void *priv, struct rtk_hapd_config* config); +static int realtek_config_rate(int *rate_list, unsigned int *rate_config); +static int realtek_read_hapd_cfg(struct hostapd_data *hapd,void *priv, struct rtk_hapd_config* config); + + +#ifdef MODIFIED_BY_SONY +static int wext_set_key(void *priv, int alg, + const u8 *addr, int key_idx, + int set_tx, const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len); +#endif /* MODIFIED_BY_SONY */ + +#ifdef RTK_MBSSID +static int add_ifidx(struct realtek_driver_data *drv, int ifidx) +{ + int i; + wpa_printf(MSG_DEBUG, "nl80211: Add own interface ifindex %d", + ifidx); + for (i = 0; i < drv->num_if_indices; i++) { + if (drv->if_indices[i] == 0) { + drv->if_indices[i] = ifidx; + return; + } + } + + return -1; +} + +static int have_ifidx(struct realtek_driver_data *drv, int ifidx) +{ + int i; + + for (i = 0; i < drv->num_if_indices; i++) + if (drv->if_indices[i] == ifidx) + return 1; + return 0; +} + + +static struct hostapd_data *find_hapd_by_ifname(void *priv,const char *ifname) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd,*bss_hapd=hapd; + struct hostapd_iface *iface = hapd->iface; + struct hostapd_bss_config *conf; + int j; + + + for (j = 0; j < iface->num_bss; j++) + { + bss_hapd = iface->bss[j] ; + conf = bss_hapd->conf; + if(os_strcmp(conf->iface, ifname) == 0) //find the entry + break; + + } + + return bss_hapd; +} + +static struct hostapd_data *find_hapd_by_ifindex(void *priv,int ifindex) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + struct i802_bss *tbss = &drv->first_bss,*bss; + + + if( drv->ifindex == ifindex) //if it's for Root AP + goto end; + + while (tbss) { //find the VAP + + bss = tbss->next; + + if(bss == NULL) + break; + + if( bss->ifindex == ifindex ) //find the entry + { + hapd = (struct hostapd_data *)find_hapd_by_ifname(drv,bss->ifname); + break; + } + tbss = tbss->next; + } +end: + return hapd; +} + +static struct hostapd_data *find_hapd_by_sta(void *priv,u8 *sta_addr) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + struct hostapd_iface *iface = hapd->iface; + int j; + + for (j = 0; j < iface->num_bss; j++) { + if (ap_get_sta(iface->bss[j], sta_addr)) { + hapd = iface->bss[j]; + break; + } + } + + return hapd; +} + +static int rtk_free_bss_by_ifname(void *priv, const char *ifname) +{ + struct realtek_driver_data *drv = priv; + struct i802_bss *tbss = &drv->first_bss,*bss; + + while (tbss) { + + bss = tbss->next; + if(bss == NULL) + break; + if(os_strcmp(bss->ifname, ifname) == 0) //find the entry + { + if (bss->sock_xmit != NULL) //deinit socket + l2_packet_deinit(bss->sock_xmit); + + tbss->next = bss->next; + os_free(bss); + break; + } + tbss = tbss->next ; + } + return 0; +} + +static struct l2_packet_data *rtk_find_l2sock_by_ifname(void *priv, const char *ifname) +{ + struct realtek_driver_data *drv = priv; + struct i802_bss *tbss = &drv->first_bss,*bss; + struct l2_packet_data *eapol_sock=drv->sock_xmit; + + if(os_strcmp(drv->iface,ifname)==0) //if it's for Root AP + goto end; + + + while (tbss) { //find the VAP + + bss = tbss->next; + + if(bss == NULL) + break; + + if(os_strcmp(bss->ifname, ifname) == 0) //find the entry + { + eapol_sock = bss->sock_xmit; + break; + } + tbss = tbss->next; + } + +end: + return eapol_sock; +} + +static void handle_eapol(int sock, void *eloop_ctx, void *sock_ctx) +{ + struct realtek_driver_data *drv = eloop_ctx; + struct hostapd_data *hapd = drv->hapd; + struct sockaddr_ll lladdr; + unsigned char buf[3000]; + int len,j; + socklen_t fromlen = sizeof(lladdr); + struct hostapd_iface *iface = hapd->iface; + unsigned char *sa; + len = recvfrom(sock, buf, sizeof(buf), 0, + (struct sockaddr *)&lladdr, &fromlen); + + if (len < 0) { + perror("recv"); + return; + } + sa = (unsigned char *)lladdr.sll_addr; + //if (have_ifidx(drv, lladdr.sll_ifindex)) //mark_mbssid , if br0 rcv?? + //{ + for (j = 0; j < iface->num_bss; j++) { + if (ap_get_sta(iface->bss[j], sa)) { + hapd = iface->bss[j]; + break; + } + } + + /*printf("handle_eapol if=%s src_mac=%x:%x:%x:%x:%x:%x\n",hapd->conf->iface, + sa[0],sa[1],sa[2],sa[3],sa[4],sa[5]);*/ + ieee802_1x_receive(hapd, sa, buf, len); + //} +} +#endif + +#ifdef INBAND_CTRL // HOST_LITTLE_ENDIAN +static void rtk_cfg_to_bigEndian(struct rtk_hapd_config *config_ptr) +{ + config_ptr->band = htonl(config_ptr->band); + config_ptr->channel = htonl(config_ptr->channel); + config_ptr->bcnint = htonl(config_ptr->bcnint); + config_ptr->dtimperiod = htonl(config_ptr->dtimperiod); + config_ptr->stanum = htonl(config_ptr->stanum); + config_ptr->rtsthres = htonl(config_ptr->rtsthres); + config_ptr->fragthres = htonl(config_ptr->fragthres); + config_ptr->oprates = htonl(config_ptr->oprates); + config_ptr->basicrates = htonl(config_ptr->basicrates); + config_ptr->preamble = htonl(config_ptr->preamble); + config_ptr->aclmode = htonl(config_ptr->aclmode); + config_ptr->aclnum = htonl(config_ptr->aclnum); + config_ptr->hiddenAP = htonl(config_ptr->hiddenAP); + config_ptr->qos_enable = htonl(config_ptr->qos_enable); + config_ptr->expired_time = htonl(config_ptr->expired_time); + config_ptr->block_relay = htonl(config_ptr->block_relay); + config_ptr->shortGI20M = htonl(config_ptr->shortGI20M); + config_ptr->shortGI40M = htonl(config_ptr->shortGI40M); + //Above are for Hostapd owned configurations //==================================================== + config_ptr->phyBandSelect = htonl(config_ptr->phyBandSelect); + config_ptr->ther = htonl(config_ptr->ther); + config_ptr->swcrypto = htonl(config_ptr->swcrypto); + config_ptr->regdomain = htonl(config_ptr->regdomain); + config_ptr->autorate = htonl(config_ptr->autorate); + config_ptr->fixrate = htonl(config_ptr->fixrate); + config_ptr->disable_protection = htonl(config_ptr->disable_protection); + config_ptr->disable_olbc = htonl(config_ptr->disable_olbc); + config_ptr->deny_legacy = htonl(config_ptr->deny_legacy); + config_ptr->opmode = htonl(config_ptr->opmode); + config_ptr->vap_enable = htonl(config_ptr->vap_enable); + config_ptr->use40M = htonl(config_ptr->use40M); + config_ptr->_2ndchoffset = htonl(config_ptr->_2ndchoffset); + config_ptr->ampdu = htonl(config_ptr->ampdu); + config_ptr->coexist = htonl(config_ptr->coexist); + config_ptr->rssi_dump = htonl(config_ptr->rssi_dump); + config_ptr->mp_specific = htonl(config_ptr->mp_specific); + config_ptr->use_ext_pa = htonl(config_ptr->use_ext_pa); + config_ptr->macPhyMode = htonl(config_ptr->macPhyMode); + //Below are for RTK private configurations + } +#endif + + +static int +set80211priv(const char *ifname,struct realtek_driver_data *drv, int op, void *data, int len) +{ + struct iwreq iwr; + int do_inline = (len < IFNAMSIZ); + + /* Poorly thought out inteface -- certain ioctls MUST use + * the non-inline method: + */ + if ( + #ifdef IEEE80211_IOCTL_SET_APPIEBUF + op == IEEE80211_IOCTL_SET_APPIEBUF || + #endif + #ifdef IEEE80211_IOCTL_FILTERFRAME + op == IEEE80211_IOCTL_FILTERFRAME || + #endif + 0 + ) { + do_inline = 0; + } + + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, ifname, IFNAMSIZ); + + if (do_inline) { + memcpy(iwr.u.name, data, len); + } else { + /* + * Argument data MAY BE too big for inline transfer; setup a + * parameter block instead; the kernel will transfer + * the data for the driver. + */ + iwr.u.data.pointer = data; + iwr.u.data.length = len; + } + +#ifdef STAND_ALONE + if (ioctl(drv->ioctl_sock, op, &iwr) < 0) { + { + int err = errno; + perror("set80211priv ioctl failed"); + wpa_printf(MSG_ERROR, "ioctl 0x%x failed errno=%d", + op, err); + } + return -1; + } +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr)); + + if ( inband_ioctl(op, &iwr) < 0) { + perror("set80211priv ioctl failed"); + wpa_printf(MSG_ERROR, "ioctl 0x%x failed", op); + return -1; + } +#endif + + + return 0; +} + +static int +set80211param(const char *ifname,struct realtek_driver_data *drv, int op, int arg) +{ + struct iwreq iwr; + + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, ifname, IFNAMSIZ); +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN +// int need endian swap + op = htonl(op); + arg = htonl(arg); +#endif + iwr.u.mode = op; + memcpy(iwr.u.name+sizeof(__u32), &arg, sizeof(arg)); + +#ifdef STAND_ALONE + if (ioctl(drv->ioctl_sock, IEEE80211_IOCTL_SETPARAM, &iwr) < 0) { + perror("ioctl[IEEE80211_IOCTL_SETPARAM]"); + wpa_printf(MSG_DEBUG, "%s: Failed to set parameter (op %d " + "arg %d)", __func__, op, arg); + return -1; + } +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr)); + if (inband_ioctl(IEEE80211_IOCTL_SETPARAM, &iwr) < 0) { + perror("ioctl[IEEE80211_IOCTL_SETPARAM]"); + wpa_printf(MSG_DEBUG, "%s: Failed to set parameter (op %d " + "arg %d)", __func__, op, arg); + return -1; + } +#endif + + return 0; +} + +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; +} + + +static int +realtek_set_wpa(char *ifname,struct realtek_driver_data *drv, int wpa, int psk, int cipher) +{ + + if(psk & WPA_KEY_MGMT_PSK) + {//PSK mode, set PSK & cipher + if (set80211param(ifname,drv, IEEE80211_PARAM_KEYMGTALGS, wpa)) + { + wpa_printf(MSG_ERROR, "Unable to set key management algorithms"); + return -1; + } + if (set80211param(ifname,drv, IEEE80211_PARAM_UCASTCIPHERS, cipher)) + { + wpa_printf(MSG_ERROR, "Unable to set pairwise key ciphers"); + return -1; + } + + } + else + {//Enterprise mode, Disable PSK & set cipher. + if (set80211param(ifname,drv, IEEE80211_PARAM_KEYMGTALGS, 0)) + { + wpa_printf(MSG_ERROR, "Unable to set key management algorithms"); + return -1; + } + if (set80211param(ifname,drv, IEEE80211_PARAM_UCASTCIPHERS, cipher)) + { + wpa_printf(MSG_ERROR, "Unable to set pairwise key ciphers"); + return -1; + } + + } + + if (set80211param(ifname,drv, IEEE80211_PARAM_WPA, wpa)) + { + wpa_printf(MSG_ERROR, "Unable to set WPA"); + return -1; + } + + return set80211param(ifname,drv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_WPA); + +} + +/* + * Configure WPA parameters. + */ +static int +realtek_configure_wpa(struct hostapd_data *hapd,struct realtek_driver_data *drv) +{ + struct hostapd_bss_config *conf = hapd->conf; + int v; + + //delete conf->wpa_group & conf->rsn_preauth related parts (like ralink) + + wpa_printf(MSG_DEBUG, "realtek_configure_wpa +++ wpa=0x%x, psk=0x%x, cipher=0x%x", + conf->wpa, conf->wpa_key_mgmt, conf->wpa_pairwise); + + v = 0; + if (conf->wpa_pairwise & WPA_CIPHER_CCMP) + v |= 1<wpa_pairwise & WPA_CIPHER_TKIP) + v |= 1<wpa_pairwise & WPA_CIPHER_NONE) + v |= 1<wpa == 0) || (conf->wpa > (HOSTAPD_WPA_VERSION_WPA|HOSTAPD_WPA_VERSION_WPA2))) + return -1; + else + return realtek_set_wpa(conf->iface,drv, conf->wpa , conf->wpa_key_mgmt, v); + +} + +static int +realtek_set_iface_hwMac(const char *ifname,void *priv, char *addr) +{ + struct realtek_driver_data *drv = priv; + struct ifreq ifreq; + + if (drv->ioctl_sock < 0) + return -1; + + os_memset(&ifreq, 0, sizeof(ifreq)); + os_strlcpy(ifreq.ifr_name, ifname, IFNAMSIZ); + + memcpy(ifreq.ifr_hwaddr.sa_data, addr, ETH_ALEN); + ifreq.ifr_hwaddr.sa_family = ARPHRD_ETHER; + +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&ifreq,sizeof(ifreq)); + if (inband_ioctl(SIOCSIFHWADDR, &ifreq) < 0) { + perror("inband_ioctl[SIOCSIFHWADDR]"); + return -1; + } +#else + if (ioctl(drv->ioctl_sock, SIOCSIFHWADDR, &ifreq) != 0) { + perror("ioctl[SIOCSIFHWADDR]"); + return -1; + } +#endif + + + return 0; +} + +static int +realtek_set_iface_flags(const char *ifname,void *priv, int dev_up) +{ + struct realtek_driver_data *drv = priv; + struct ifreq ifr; + + wpa_printf(MSG_DEBUG, "realtek_set_iface_flags +++ dev_up = %d", dev_up); + + if (drv->ioctl_sock < 0) + return -1; + + if (dev_up) { + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, IFNAMSIZ, "%s", ifname); + ifr.ifr_mtu = HOSTAPD_MTU; +#ifdef STAND_ALONE + if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) { + perror("ioctl[SIOCSIFMTU]"); + printf("Setting MTU failed - trying to survive with " + "current value\n"); + } +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&ifr,sizeof(ifr)); + if (inband_ioctl(SIOCSIFMTU, &ifr) < 0) { + perror("inband_ioctl[SIOCSIFMTU]"); + printf("Setting MTU failed - trying to survive with " + "current value\n"); + } +#endif + } + + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, IFNAMSIZ, "%s", ifname); +#ifdef STAND_ALONE + if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) { + perror("ioctl[SIOCGIFFLAGS]"); + return -1; + } +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&ifr,sizeof(ifr)); + if (inband_ioctl(SIOCGIFFLAGS, &ifr) < 0) { + perror("inband_ioctl[SIOCGIFFLAGS]"); + printf("inband_ioctl[SIOCGIFFLAGS] fail"); + return -1; + } +#endif + + if (dev_up) + ifr.ifr_flags |= IFF_UP; + else + ifr.ifr_flags &= ~IFF_UP; +#ifdef STAND_ALONE + if (ioctl(drv->ioctl_sock, SIOCSIFFLAGS, &ifr) != 0) { + perror("ioctl[SIOCSIFFLAGS]"); + return -1; + } +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&ifr,sizeof(ifr)); + if (inband_ioctl(SIOCSIFFLAGS, &ifr) < 0) { + perror("inband_ioctl[SIOCSIFFLAGS]"); + printf("inband_ioctl[SIOCGIFFLAGS] fail"); + return -1; + } +#endif + + wpa_printf(MSG_DEBUG, "realtek_set_iface_flags ---"); + return 0; +} + +static int realtek_set_ieee8021x(const char *ifname, void *priv, int enabled) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + struct hostapd_bss_config *conf = hapd->conf; + struct hostapd_wep_keys wep = conf->ssid.wep; + +#ifdef RTK_MBSSID //find the real VAP + hapd =(struct hostapd_data *) find_hapd_by_ifname(priv,ifname); + conf = hapd->conf; + wep = conf->ssid.wep; +#endif + + wpa_printf(MSG_DEBUG, "realtek_set_ieee8021x+++ \n" + "enabled=%d, conf->auth_algs=%d, wep.keys_set=%d, conf->ieee802_1x=%d" + ,enabled, conf->auth_algs, wep.keys_set, conf->ieee802_1x); + + if(set80211param(ifname,priv, IEEE80211_PARAM_UCASTKEYLEN, conf->individual_wep_key_len)) + return -1; + + if (!enabled) { + wpa_printf(MSG_DEBUG, "set WEP"); + /* Set interface up flags after setting authentication modes, + done atlast in realtek_commit() */ + if(conf->auth_algs==1 && wep.keys_set==0) + return set80211param(ifname,priv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_OPEN); + else if(conf->auth_algs==1 && wep.keys_set==1){ + return set80211param(ifname,priv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_OPEN); + /*Fix for open wep when run using hostapd*/ + //return set80211param(priv, IEEE80211_PARAM_PRIVACY, 1); + } + else if(conf->auth_algs==2) + return set80211param(ifname,priv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_SHARED); + else if(conf->auth_algs==3) + return set80211param(ifname,priv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_AUTO); + else if(conf->auth_algs==8) //RTK_HAPD, add auth_algs=BIT(3) as value of none authentication. + return set80211param(ifname,priv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_NONE); + } + + if (!conf->wpa && !conf->ieee802_1x) { + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_DRIVER, + HOSTAPD_LEVEL_WARNING, "No 802.1X or WPA enabled!"); + return -1; + } + + if((conf->wpa == 0) && (conf->ieee802_1x)) + { + if(set80211param(ifname,priv, IEEE80211_PARAM_AUTHMODE, IEEE80211_AUTH_8021X)) + return -1; + } + + if (conf->wpa) + { + return realtek_configure_wpa(hapd,drv); + } + + return 0; +} + +static int +realtek_set_privacy(const char *ifname, void *priv, int enabled) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + + wpa_printf(MSG_DEBUG, "realtek_set_privacy +++"); + + return set80211param(ifname,priv, IEEE80211_PARAM_PRIVACY, enabled); +} + +static int +realtek_set_sta_authorized(void *priv, const u8 *addr, int authorized) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + struct hostapd_bss_config *conf = hapd->conf; + struct ieee80211req_mlme mlme; + int ret; + +#ifdef RTK_MBSSID + hapd = (struct hostapd_data *)find_hapd_by_sta(priv,addr); + conf = hapd->conf; +#endif + + if (authorized) + mlme.im_op = IEEE80211_MLME_AUTHORIZE; + else + mlme.im_op = IEEE80211_MLME_UNAUTHORIZE; + mlme.im_reason = 0; + memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); + ret = set80211priv(conf->iface,priv, IEEE80211_IOCTL_SETMLME, &mlme, + sizeof(mlme)); + if (ret < 0) { + wpa_printf(MSG_DEBUG, "%s: Failed to %sauthorize STA " MACSTR, + __func__, authorized ? "" : "un", MAC2STR(addr)); + } + + return ret; +} + +static int +realtek_sta_set_flags(void *priv, const u8 *addr, int flags_or, int flags_and) +{ + + wpa_printf(MSG_DEBUG, "realtek_sta_set_flags +++"); + + /* For now, only support setting Authorized flag */ + if (flags_or & WLAN_STA_AUTHORIZED) + return realtek_set_sta_authorized(priv, addr, 1); + if (!(flags_and & WLAN_STA_AUTHORIZED)) + return realtek_set_sta_authorized(priv, addr, 0); + return 0; +} + +static int +realtek_del_key(const char *ifname,void *priv, const u8 *addr, int key_idx) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + struct ieee80211req_del_key wk; + int ret; + + wpa_printf(MSG_DEBUG, "realtek_del_key +++"); + + memset(&wk, 0, sizeof(wk)); + if (addr != NULL) { + memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); + wk.idk_keyix = (u8) IEEE80211_KEYIX_NONE; + } else { + wk.idk_keyix = key_idx; + } + + ret = set80211priv(ifname ,priv, IEEE80211_IOCTL_DELKEY, &wk, sizeof(wk)); + if (ret < 0) { + wpa_printf(MSG_DEBUG, "%s: Failed to delete key (addr %s" + " key_idx %d)", __func__, ether_sprintf(addr), + key_idx); + } + + wpa_printf(MSG_DEBUG, "realtek_del_key ---"); + return ret; +} + +static int +realtek_set_key(const char *ifname, void *priv, const char *alg, + const u8 *addr, int key_idx, + const u8 *key, size_t key_len, int txkey) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + struct hostapd_bss_config *conf = hapd->conf; + struct hostapd_wep_keys wep = conf->ssid.wep; + struct ieee80211req_key wk; + u_int8_t cipher; + int ret; + +#ifdef RTK_MBSSID //find the real VAP + hapd = (struct hostapd_data *)find_hapd_by_ifname(priv,ifname); + conf = hapd->conf; + wep = conf->ssid.wep; +#endif + + wpa_printf(MSG_DEBUG, "realtek_set_key +++"); + wpa_printf(MSG_DEBUG, "alg = %s\n, addr = %s\n, key_index = %d", alg, ether_sprintf(addr), key_idx); + + if (strcmp(alg, "none") == 0) + return realtek_del_key(ifname,priv, addr, key_idx); + + if ((strcmp(alg, "WEP") == 0) && ((wep.keys_set >= 1) && (wep.keys_set <= 4))) + cipher = IEEE80211_CIPHER_WEP; + else if (strcmp(alg, "TKIP") == 0) + cipher = IEEE80211_CIPHER_TKIP; + else if (strcmp(alg, "CCMP") == 0) + cipher = IEEE80211_CIPHER_AES_CCM; + else { + printf("%s: unknown/unsupported algorithm %s\n", + __func__, alg); + return -1; + } + + if (key_len > sizeof(wk.ik_keydata)) { + printf("%s: key length %lu too big\n", __func__, + (unsigned long) key_len); + return -3; + } + + memset(&wk, 0, sizeof(wk)); + wk.ik_type = cipher; + wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT; + if (addr == NULL) { + memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); + wk.ik_keyix = key_idx; + wk.ik_flags |= IEEE80211_KEY_DEFAULT; + } else { + memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); + wk.ik_keyix = key_idx; + //wk.ik_keyix = IEEE80211_KEYIX_NONE; + } + wk.ik_keylen = key_len; + memcpy(wk.ik_keydata, key, key_len); + +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN + // ik_keyix int16 need endian-swap + wk.ik_keyix = htons(wk.ik_keyix); + wk.ik_keylen = htonl(key_len); +#endif + ret = set80211priv(ifname,priv, IEEE80211_IOCTL_SETKEY, &wk, sizeof(wk)); + if (ret < 0) { + wpa_printf(MSG_DEBUG, "%s: Failed to set key (addr %s" + " key_idx %d alg '%s' key_len %lu txkey %d)", + __func__, ether_sprintf(wk.ik_macaddr), key_idx, + alg, (unsigned long) key_len, txkey); + } + + wpa_printf(MSG_DEBUG, "realtek_set_key ---"); + return ret; +} + + +static int +realtek_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, + u8 *seq) +{ +//do nothing like broadcom & ralink, even madwifi did not call back for hosapd. + + wpa_printf(MSG_DEBUG, "realtek_get_seqnum +++"); + wpa_printf(MSG_DEBUG, "realtek_get_seqnum ---"); + + return 0; +} + + +static int +realtek_flush(void *priv) +{ +//do nothing like broadcom & ralink + wpa_printf(MSG_DEBUG, "realtek_flush +++"); + wpa_printf(MSG_DEBUG, "realtek_flush ---"); + return 0; +} + + +static int +realtek_read_sta_driver_data(void *priv, struct hostap_sta_driver_data *data, + const u8 *addr) +{ +#if 0 //not use now + struct realtek_driver_data *drv = priv; + wpa_printf(MSG_DEBUG, "realtek_read_sta_driver_data +++"); + +#ifdef REALTEK_BSD + struct ieee80211req_sta_stats stats; + + memset(data, 0, sizeof(*data)); + + /* + * Fetch statistics for station from the system. + */ + memset(&stats, 0, sizeof(stats)); + memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); + if (set80211priv(drv, +#ifdef REALTEK_NG + IEEE80211_IOCTL_STA_STATS, +#else /* REALTEK_NG */ + IEEE80211_IOCTL_GETSTASTATS, +#endif /* REALTEK_NG */ + &stats, sizeof(stats))) { + wpa_printf(MSG_DEBUG, "%s: Failed to fetch STA stats (addr " + MACSTR ")", __func__, MAC2STR(addr)); + if (memcmp(addr, drv->acct_mac, ETH_ALEN) == 0) { + memcpy(data, &drv->acct_data, sizeof(*data)); + return 0; + } + + printf("Failed to get station stats information element.\n"); + return -1; + } +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN + stats.is_stats.ns_rx_data = ntohl(stats.is_stats.ns_rx_data); + stats.is_stats.ns_rx_bytes = ntohl(stats.is_stats.ns_rx_bytes); + stats.is_stats.ns_tx_data = ntohl(stats.is_stats.ns_tx_data); + stats.is_stats.ns_tx_bytes = ntohl(stats.is_stats.ns_tx_bytes); +#endif + data->rx_packets = stats.is_stats.ns_rx_data; + data->rx_bytes = stats.is_stats.ns_rx_bytes; + data->tx_packets = stats.is_stats.ns_tx_data; + data->tx_bytes = stats.is_stats.ns_tx_bytes; + return 0; + +#else /* REALTEK_BSD */ + + char buf[1024], line[128], *pos; + FILE *f; + unsigned long val; + + memset(data, 0, sizeof(*data)); + snprintf(buf, sizeof(buf), "/proc/net/realtek/%s/" MACSTR, + drv->iface, MAC2STR(addr)); + + f = fopen(buf, "r"); + if (!f) { + if (memcmp(addr, drv->acct_mac, ETH_ALEN) != 0) + return -1; + memcpy(data, &drv->acct_data, sizeof(*data)); + return 0; + } + /* Need to read proc file with in one piece, so use large enough + * buffer. */ + setbuffer(f, buf, sizeof(buf)); + + while (fgets(line, sizeof(line), f)) { + pos = strchr(line, '='); + if (!pos) + continue; + *pos++ = '\0'; + val = strtoul(pos, NULL, 10); + if (strcmp(line, "rx_packets") == 0) + data->rx_packets = val; + else if (strcmp(line, "tx_packets") == 0) + data->tx_packets = val; + else if (strcmp(line, "rx_bytes") == 0) + data->rx_bytes = val; + else if (strcmp(line, "tx_bytes") == 0) + data->tx_bytes = val; + } + + fclose(f); + + return 0; +#endif /* REALTEK_BSD */ +#endif +return 0; +} + + +static int +realtek_sta_clear_stats(void *priv, const u8 *addr) +{ +#if 0 //not support now +#if defined(REALTEK_BSD) && defined(IEEE80211_MLME_CLEAR_STATS) + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + struct ieee80211req_mlme mlme; + int ret; + + wpa_printf(MSG_DEBUG, "realtek_sta_clear_stats (BSD) +++"); + + mlme.im_op = IEEE80211_MLME_CLEAR_STATS; + memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); + ret = set80211priv(priv, IEEE80211_IOCTL_SETMLME, &mlme, + sizeof(mlme)); + if (ret < 0) { + wpa_printf(MSG_DEBUG, "%s: Failed to clear STA stats (addr " + MACSTR ")", __func__, MAC2STR(addr)); + } + + return ret; +#else /* REALTEK_BSD && IEEE80211_MLME_CLEAR_STATS */ + wpa_printf(MSG_DEBUG, "realtek_sta_clear_stats +++"); + return 0; /* FIX */ +#endif /* REALTEK_BSD && IEEE80211_MLME_CLEAR_STATS */ +#endif +return 0; +} + + +static int +realtek_set_opt_ie(const char *ifname, void *priv, const u8 *ie, size_t ie_len) +{ +//do nothing like broadcom & ralink & madwifi + + wpa_printf(MSG_DEBUG, "realtek_set_opt_ie +++"); + wpa_printf(MSG_DEBUG, "realtek_set_opt_ie ---"); + return 0; +} + +static int +realtek_is_ifup(const char *ifname,struct realtek_driver_data *drv) +{ + struct ifreq ifr; + + if (drv->ioctl_sock < 0) + return 0; + + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, IFNAMSIZ, "%s", ifname); +#ifdef STAND_ALONE + if (ioctl(drv->ioctl_sock, SIOCGIFFLAGS, &ifr) != 0) { + perror("ioctl[SIOCGIFFLAGS]"); + return 0; + } +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&ifr,sizeof(ifr)); + if (inband_ioctl(SIOCGIFFLAGS, &ifr) < 0) { + perror("ioctl[SIOCGIFFLAGS]"); + return 0; + } +#endif + + return ((ifr.ifr_flags & IFF_UP) == IFF_UP); +} + +static int +realtek_sta_deauth(void *priv, const u8 *addr, int reason_code) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + struct hostapd_bss_config *conf = hapd->conf; + struct ieee80211req_mlme mlme; + int ret; + +#ifdef RTK_MBSSID //find the sta belong to which MBSSID + hapd = (struct hostapd_data *)find_hapd_by_sta(priv,addr); + conf = hapd->conf; +#endif + + wpa_printf(MSG_DEBUG, "realtek_sta_deauth +++"); + + mlme.im_op = IEEE80211_MLME_DEAUTH; + mlme.im_reason = reason_code; + memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); + if (!realtek_is_ifup(conf->iface,drv)) { + return EINVAL; + } +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN + //im_reason need swap + mlme.im_reason = htons(mlme.im_reason); +#endif + ret = set80211priv(conf->iface,priv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); + if (ret < 0) { + wpa_printf(MSG_DEBUG, "%s: Failed to deauth STA (addr " MACSTR + " reason %d)", + __func__, MAC2STR(addr), reason_code); + } + + return ret; +} + +static int +realtek_sta_disassoc(void *priv, const u8 *addr, int reason_code) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + struct hostapd_bss_config *conf = hapd->conf; + struct ieee80211req_mlme mlme; + int ret; + +#ifdef RTK_MBSSID //find the sta belong to which MBSSID + hapd = (struct hostapd_data *)find_hapd_by_sta(priv,addr); + conf = hapd->conf; +#endif + + wpa_printf(MSG_DEBUG, "realtek_sta_disassoc +++"); + + mlme.im_op = IEEE80211_MLME_DISASSOC; + mlme.im_reason = reason_code; + memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN + //im_reason need swap + mlme.im_reason = htons(mlme.im_reason); +#endif + ret = set80211priv(conf->iface,priv, IEEE80211_IOCTL_SETMLME, &mlme, sizeof(mlme)); + if (ret < 0) { + wpa_printf(MSG_DEBUG, "%s: Failed to disassoc STA (addr " + MACSTR " reason %d)", + __func__, MAC2STR(addr), reason_code); + } + + return ret; +} + +#ifdef RTK_HAPD +//Announce driver to remove sta list for IAPP function +static int +realtek_sta_remove(void *priv, const u8 *addr) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + struct hostapd_bss_config *conf = hapd->conf; + unsigned char para[32]; + struct iwreq wrq; + +#ifdef RTK_MBSSID //find the sta belong to which MBSSID + hapd = (struct hostapd_data *)find_hapd_by_sta(priv,addr); + conf = hapd->conf; +#endif + wpa_printf(MSG_DEBUG, "realtek_sta_remove +++"); + memset(para, 0, 32); + sprintf(para, "%02x%02x%02x%02x%02x%02x", addr[0], addr[1], + addr[2], addr[3], addr[4], addr[5]); + wrq.u.data.pointer = para; + wrq.u.data.length = strlen(para); + strncpy(wrq.ifr_name, conf->iface, IFNAMSIZ); +#ifdef STAND_ALONE + ioctl(drv->ioctl_sock, RTL8192CD_IOCTL_DEL_STA, &wrq); +#endif +#ifdef INBAND_CTRL + inband_ioctl(RTL8192CD_IOCTL_DEL_STA, &wrq); +#endif + + wpa_printf(MSG_DEBUG, "realtek_sta_remove ---"); + + return 0; +} +#endif + +static int +realtek_del_sta(struct hostapd_data *hapd,struct realtek_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN]) +{ + 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); + } + return 0; +} + +static int +realtek_process_wpa_ie(struct hostapd_data *hapd,struct realtek_driver_data *drv, struct sta_info *sta) +{ + struct ieee80211req_wpaie ie; + int ielen, res; + u8 *iebuf = NULL; + struct hostapd_bss_config *conf = hapd->conf; + + wpa_printf(MSG_DEBUG, "realtek_process_wpa_ie +++"); + + /* + * Fetch negotiated WPA/RSN parameters from the system. + */ + memset(&ie, 0, sizeof(ie)); + memcpy(ie.wpa_macaddr, sta->addr, IEEE80211_ADDR_LEN); + + if (set80211priv(conf->iface,drv, HAPD_IOCTL_GETWPAIE, &ie, sizeof(ie))) + { + wpa_printf(MSG_ERROR, "%s: Failed to get WPA/RSN IE", __func__); + printf("Failed to get WPA/RSN information element.\n"); + return -1; + } + + //wpa_printf(MSG_DEBUG, "get wpa_ie = 0x%02x, 0x%02x, 0x%02x", ie.wpa_ie[0], ie.wpa_ie[1], ie.wpa_ie[2]); + //wpa_printf(MSG_DEBUG, "get wps_ie = 0x%02x, 0x%02x, 0x%02x", ie.wps_ie[0], ie.wps_ie[1], ie.wps_ie[2]); + + do { + iebuf = 0; ielen = 0; + if (conf->wpa & HOSTAPD_WPA_VERSION_WPA) { + iebuf = ie.wpa_ie; ielen = 0; + if ((iebuf[0] == WLAN_EID_VENDOR_SPECIFIC) && iebuf[1]) { + wpa_printf(MSG_DEBUG, "get wpa_ie"); + ielen = iebuf[1]; + break; + } + } + if (conf->wpa & HOSTAPD_WPA_VERSION_WPA2) { + iebuf = ie.rsn_ie; ielen = 0; + if ((iebuf[0] == WLAN_EID_RSN) && iebuf[1]) { + wpa_printf(MSG_DEBUG, "get rsn_ie"); + ielen = iebuf[1]; + break; + } + } + } while (0); + + wpabuf_free(sta->wps_ie); + if ((ie.wps_ie[0] == WLAN_EID_VENDOR_SPECIFIC) && ie.wps_ie[1]) + { + //Test rtl8192su usb-dongle wps_pbc/wps_pin ok via here. + wpa_printf(MSG_DEBUG, "get wps_ie"); + ielen = ie.wps_ie[1] + 2; + + sta->wps_ie = wpabuf_alloc(0); + sta->wps_ie->size = ielen; + sta->wps_ie->used = ielen; + sta->wps_ie->ext_data = os_malloc(ielen); + memcpy(sta->wps_ie->ext_data, ie.wps_ie, ielen); + + sta->flags |= WLAN_STA_WPS; + return 0; + } + else + { + sta->wps_ie = wpabuf_alloc(0); + sta->wps_ie->used = 0; + sta->wps_ie->ext_data = NULL; + + sta->flags &= ~WLAN_STA_WPS; + + + if((ielen == 0) && (conf->wps_state)){ + wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN/WPS IE in (Re)Association Request " + "but WPS enabled at hostapd conf file - possible WPS use"); + sta->flags |= WLAN_STA_MAYBE_WPS; // Test dwa140 and wn111 wps_pbc/wps_pin ok because of here!!!! --zj + } + else{ + sta->flags &= ~WLAN_STA_MAYBE_WPS; + } + } + + if(ielen != 0) //_For WPS, neglect wpa_ie?? + { + 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; + } + + ielen += 2; + res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, iebuf, ielen, NULL, 0); + + if (res != WPA_IE_OK) + { + wpa_printf(MSG_ERROR, "WPA/RSN information element rejected? (res %u)", res); + return -1; + } + else + wpa_printf(MSG_DEBUG, "WPA_IE_OK"); + } + + + return 0; +} + +static int +realtek_issue_asocrsp(char *ifname,struct realtek_driver_data *drv, struct sta_info *sta) +{ + int retVal = 0; + struct iwreq iwr; + DOT11_ASSOCIATION_RSP Association_Rsp; + + wpa_printf(MSG_DEBUG, "realtek_issue_asocrsp +++"); + + strncpy(iwr.ifr_name, ifname, IFNAMSIZ); + + iwr.u.data.pointer = (caddr_t)&Association_Rsp; + iwr.u.data.length = sizeof(DOT11_ASSOCIATION_RSP); + + Association_Rsp.EventId = DOT11_EVENT_ASSOCIATION_RSP; + + //?? Re-Association case?? + //Association_Rsp.EventId = DOT11_EVENT_REASSOCIATION_RSP; + + Association_Rsp.IsMoreEvent = FALSE; + Association_Rsp.Status = _STATS_SUCCESSFUL_; + memcpy(&Association_Rsp.MACAddr, sta->addr, IEEE80211_ADDR_LEN); + +#ifdef STAND_ALONE + if(ioctl(drv->ioctl_sock, SIOCGIWIND, &iwr) < 0) + retVal = -1; + else + retVal = 0; +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr)); + if (inband_ioctl(SIOCGIWIND, &iwr) < 0) + retVal = -1; + else + retVal = 0; +#endif + return retVal; + +} + + +static int +realtek_new_sta(struct hostapd_data *hapd,struct realtek_driver_data *drv, u8 addr[IEEE80211_ADDR_LEN]) +{ + struct hostapd_bss_config *conf = hapd->conf; + struct sta_info *sta; + int new_assoc; + + 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 { + //printf("realtek_new_sta hapd=%s \n",conf->iface); + sta = ap_sta_add(hapd, addr); + if (sta == NULL) + return -1; + } + //mark_mbssid , acct_mac ? per VAP? + 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)); + } + accounting_sta_get_id(hapd, sta); + + if (hapd->conf->wpa || hapd->conf->wps_state) { + if (realtek_process_wpa_ie(hapd,drv, sta)) + return -1; + if((sta->wps_ie->used == 0) && ((conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) == 0) && (conf->ieee802_1x != 0)) + {//do issue Association response just for RADIUS authentication. + if(realtek_issue_asocrsp(hapd->conf->iface,drv, sta)) + return -1; + } + } + else + { + if(conf->ieee802_1x != 0) + if(realtek_issue_asocrsp(hapd->conf->iface,drv, sta)) + return -1; + } + + /* + * Now that the internal station state is setup + * kick the authenticator into action. + */ + + wpa_printf(MSG_DEBUG, "Try to kick the authenticator into action"); + + 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; +} + + + +int realtek_set_wds(void *priv, struct rtk_wds_config wds) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + struct hostapd_bss_config *conf = hapd->conf; + struct iwreq iwr; + int op = 0; + + wpa_printf(MSG_DEBUG, "realtek_set_wds +++"); + + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ); + + iwr.u.data.pointer = &wds; + iwr.u.data.length = sizeof(struct rtk_wds_config); + + if(wds.wdsEnabled) + op = IEEE80211_IOCTL_WDSADDMAC; + else + op = IEEE80211_IOCTL_WDSDELMAC; +#ifdef STAND_ALONE + if (ioctl(drv->ioctl_sock, op, &iwr) < 0) + { + { + int err = errno; + perror("set WDS ioctl failed"); + wpa_printf(MSG_ERROR, "ioctl 0x%x failed errno=%d", + op, err); + } + return -1; + } +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr)); + if (inband_ioctl(op, &iwr) < 0) + { + { + perror("set80211priv ioctl failed"); + wpa_printf(MSG_ERROR, "ioctl 0x%x failed", op); + } + return -1; + } +#endif + + + return 0; +} + + +static void +realtek_wireless_event_wireless_custom(struct hostapd_data *hapd,struct realtek_driver_data *drv, u16 flags, char * custom, size_t len) +{ + wpa_printf(MSG_DEBUG, "custom event =%d, len=%d", flags, len); + + switch(flags) + { + case HAPD_MIC_FAILURE: + { + unsigned char * mac = (unsigned char *)custom; + wpa_printf(MSG_DEBUG, "MIC failed sta: %02x %02x %02x %02x %02x %02x" + , mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + ieee80211_michael_mic_failure(hapd, mac, 1); + break; + } + case HAPD_WPS_PROBEREQ: + { + struct _DOT11_PROBE_REQUEST_IND *wps_ie = (struct _DOT11_PROBE_REQUEST_IND *) custom; + wpa_printf(MSG_DEBUG, "IsMoreEvent =%d, ProbeIELen =%d", wps_ie->IsMoreEvent, wps_ie->ProbeIELen); + hostapd_wps_probe_req_rx(hapd, wps_ie->MACAddr, wps_ie->ProbeIE, wps_ie->ProbeIELen); + break; + } + } + +} + + +static void +realtek_wireless_event_wireless(struct hostapd_data *hapd,struct realtek_driver_data *drv, + u8 *data, int len) +{ + struct iw_event iwe_buf, *iwe = &iwe_buf; + u8 *pos, *end, *custom, *buf; + u8 macaddr[ETH_ALEN] = {}; + + pos = data; + end = data + len; + + wpa_printf(MSG_DEBUG, "realtek_wireless_event_wireless +++"); + + 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); + +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN + iwe->len = ntohs(iwe->len); + iwe->cmd = ntohs(iwe->cmd); +#endif + if (iwe->len <= IW_EV_LCP_LEN) + return; + + custom = pos + IW_EV_POINT_LEN; + if (drv->we_version > 18 && + (iwe->cmd == IWEVMICHAELMICFAILURE || + iwe->cmd == SIOCGIWESSID || + iwe->cmd == SIOCGIWENCODE || + iwe->cmd == IWEVGENIE || + iwe->cmd == IWEVASSOCREQIE || + iwe->cmd == IWEVASSOCRESPIE || + 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; +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN + iwe->len = ntohs(iwe->len); + iwe->cmd = ntohs(iwe->cmd); +#endif + } + + switch (iwe->cmd) { + case IWEVEXPIRED: + wpa_printf(MSG_DEBUG, "case IWEVEXPIRED"); + realtek_del_sta(hapd,drv, (u8 *) iwe->u.addr.sa_data); + break; + case IWEVREGISTERED: + wpa_printf(MSG_DEBUG, "case IWEVREGISTERED"); + realtek_new_sta(hapd,drv, (u8 *) iwe->u.addr.sa_data); + break; + case IWEVCUSTOM: + case IWEVGENIE: + wpa_printf(MSG_DEBUG, "case IWEVCUSTOM|IWEVGENIE"); +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN + iwe->u.data.length = ntohs(iwe->u.data.length); + iwe->u.data.flags = ntohs(iwe->u.data.flags); +#endif + 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'; + realtek_wireless_event_wireless_custom(hapd,drv, iwe->u.data.flags, buf, iwe->u.data.length); + free(buf); + break; + } + pos += iwe->len; + } +} + + +static void +realtek_wireless_event_rtm_newlink(struct realtek_driver_data *drv, + struct nlmsghdr *h, int len) +{ + struct ifinfomsg *ifi; + int attrlen, nlmsg_len, rta_len; + struct rtattr * attr; + struct hostapd_data *hapd = drv->hapd; + + wpa_printf(MSG_DEBUG, "realtek_wireless_event_rtm_newlink +++"); + + if (len < (int) sizeof(*ifi)) + return; + + ifi = NLMSG_DATA(h); +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN + ifi->ifi_index = ntohl(ifi->ifi_index); +#endif +#ifdef RTK_MBSSID + if(!have_ifidx(drv, ifi->ifi_index)) + return; + hapd = find_hapd_by_ifindex(drv,ifi->ifi_index); +#else + if (ifi->ifi_index != drv->ifindex) + return; +#endif + nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); + + attrlen = h->nlmsg_len - nlmsg_len; + if (attrlen < 0) + return; + + attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); + +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN + attr->rta_len = ntohs(attr->rta_len); + attr->rta_type = ntohs(attr->rta_type); +#endif + rta_len = RTA_ALIGN(sizeof(struct rtattr)); + while (RTA_OK(attr, attrlen)) { + if (attr->rta_type == IFLA_WIRELESS) { + realtek_wireless_event_wireless(hapd, + drv, ((u8 *) attr) + rta_len, + attr->rta_len - rta_len); + } + attr = RTA_NEXT(attr, attrlen); +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN + attr->rta_len = ntohs(attr->rta_len); + attr->rta_type = ntohs(attr->rta_type); +#endif + } +} + + +static void +realtek_wireless_event_receive(int sock, void *eloop_ctx, void *sock_ctx) +{ + //char buf[256]; + char buf[1024], cmd_type=0x01; //increse size for IWEVGENIE event + int left; + struct sockaddr_nl from; + socklen_t fromlen; + struct nlmsghdr *h; + struct realtek_driver_data *drv = eloop_ctx; +#ifdef INBAND_CTRL + left = ioh_recv(&drv->netlink_ioh_obj, 3000); + if (left < 0) { + perror("recvfrom(rawsock)"); + return; + } + INBAND_IOCTLPKT_DUMP(drv->netlink_ioh_obj.rx_data,left); + left -= IOH_HDR_LEN; + + h = (struct nlmsghdr *)drv->netlink_ioh_obj.rx_data ; +#else + 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; +#endif + while (left >= (int) sizeof(*h)) { + int len, plen; +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN //mark_x86 + h->nlmsg_len = ntohl(h->nlmsg_len); + h->nlmsg_type = ntohs(h->nlmsg_type); + h->nlmsg_flags = ntohs(h->nlmsg_flags); + h->nlmsg_seq = ntohl(h->nlmsg_seq); + h->nlmsg_pid = ntohl(h->nlmsg_pid); +#endif + len = h->nlmsg_len; + plen = len - sizeof(*h); + 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: + realtek_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 +realtek_get_we_version(struct realtek_driver_data *drv) +{ + struct iw_range *range; + struct iwreq iwr; + int minlen; + size_t buflen; + + drv->we_version = 0; + + /* + * Use larger buffer than struct iw_range in order to allow the + * structure to grow in the future. + */ + buflen = sizeof(struct iw_range) + 500; + range = os_zalloc(buflen); + if (range == NULL) + return -1; + + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ); + iwr.u.data.pointer = (caddr_t) range; + iwr.u.data.length = buflen; + + minlen = ((char *) &range->enc_capa) - (char *) range + + sizeof(range->enc_capa); +#ifdef STAND_ALONE + if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) { + perror("ioctl[SIOCGIWRANGE]"); + free(range); + return -1; + } + else if (iwr.u.data.length >= minlen && + range->we_version_compiled >= 18) { + wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " + "WE(source)=%d enc_capa=0x%x", + range->we_version_compiled, + range->we_version_source, + range->enc_capa); + drv->we_version = range->we_version_compiled; + } +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr)); + if (inband_ioctl(SIOCGIWRANGE, &iwr) < 0) { + perror("inband_ioctl[SIOCGIWRANGE]"); + free(range); + return -1; + } else if (iwr.u.data.length >= minlen && + range->we_version_compiled >= 18) { + wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d " + "WE(source)=%d enc_capa=0x%x", + range->we_version_compiled, + range->we_version_source, + range->enc_capa); + drv->we_version = range->we_version_compiled; + } +#endif + + + free(range); + return 0; +} + + +static int +realtek_wireless_event_init(void *priv) +{ + struct realtek_driver_data *drv = priv; + int s; + struct sockaddr_nl local; + + realtek_get_we_version(drv); + + drv->wext_sock = -1; +#ifdef INBAND_CTRL + s = ioh_open(&drv->netlink_ioh_obj,INBAND_INTF,INBAND_SLAVE,INBAND_NETLINK_TYPE,INBAND_DEBUG); + if (s < 0) { + perror("socket(PF_PACKET,SOCK_RAW,INBAND_NETLINK_TYPE)"); + return -1; + } +#else + 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; + } +#endif + +#ifdef INBAND_CTRL + eloop_register_read_sock(drv->netlink_ioh_obj.sockfd, realtek_wireless_event_receive, drv, NULL); +#else + eloop_register_read_sock(s, realtek_wireless_event_receive, drv, NULL); +#endif +#ifdef INBAND_CTRL + drv->wext_sock = drv->netlink_ioh_obj.sockfd; +#else + drv->wext_sock = 0; +#endif + + return 0; +} + + +static void +realtek_wireless_event_deinit(void *priv) +{ + struct realtek_driver_data *drv = priv; + + wpa_printf(MSG_DEBUG, "realtek_wireless_event_deinit +++"); + + if (drv != NULL) { + if (drv->wext_sock < 0) + return; + eloop_unregister_read_sock(drv->wext_sock); + close(drv->wext_sock); + } +} + + +static int +realtek_send_eapol(void *priv, const u8 *addr, const u8 *data, size_t data_len, + int encrypt, const u8 *own_addr) +{ + struct realtek_driver_data *drv = priv; + unsigned char buf[3000]; + unsigned char *bp = buf; + struct l2_ethhdr *eth; + size_t len; + int status; + struct l2_packet_data *eapol_sock=drv->sock_xmit; +#ifdef RTK_MBSSID +#ifndef INBAND_CTRL + struct hostapd_data *hapd = drv->hapd; + + hapd = (struct hostapd_data *)find_hapd_by_sta(priv,addr); + eapol_sock = (struct l2_packet_data *)rtk_find_l2sock_by_ifname(priv,hapd->conf->iface); +#endif +#endif + wpa_printf(MSG_DEBUG, "realtek_send_eapol +++"); + + /* + * 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, drv->hapd->own_addr, ETH_ALEN); + eth->h_proto = htons(ETH_P_EAPOL); + memcpy(eth+1, data, data_len); + + //mark wpa_hexdump because both ralink & broadcom NOT call this function + //wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", bp, len); + + status = l2_packet_send(eapol_sock, addr, ETH_P_EAPOL, bp, len); + if (bp != buf) + free(bp); + return status; +} + +static void +handle_read(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) +{ + struct realtek_driver_data *drv = ctx; + struct hostapd_data *hapd = drv->hapd; + struct sta_info *sta; + + //printf("handle_read +++"); +#ifndef RTK_MBSSID + 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)); +#else + return; // do nothing here , all handle in handle_eapol +#endif +} + +#ifdef INBAND_CTRL +static int rtk_l2_packet_get_own_addr(struct realtek_driver_data *drv, u8 *addr) +{ + unsigned char cmd[100]; + struct ifreq ifr; + + os_memset(&ifr, 0, sizeof(ifr)); + os_strlcpy(ifr.ifr_name, INBAND_INTF, sizeof(INBAND_INTF)); + + if(ioctl(drv->ioctl_sock,SIOCGIFHWADDR, &ifr ) < 0){ + return -1; + } + + sprintf(cmd,"echo %d:%d:%d:%d:%d:%d > /proc/br_hostmac",ifr.ifr_hwaddr.sa_data[0], + ifr.ifr_hwaddr.sa_data[1],ifr.ifr_hwaddr.sa_data[2],ifr.ifr_hwaddr.sa_data[3], + ifr.ifr_hwaddr.sa_data[4],ifr.ifr_hwaddr.sa_data[5]); + + if (inband_remote_cmd(cmd) < 0) + return -1; + + os_strlcpy(ifr.ifr_name, drv->iface, sizeof(ifr.ifr_name)); + if (inband_ioctl(SIOCGIFHWADDR,&ifr) < 0) + return -1; + else + os_memcpy(addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); + return 0; +} +#endif + +#ifdef RTK_MBSSID +static int realtek_bss_add(void *priv, const char *ifname, const u8 *bssid) +{ + struct realtek_driver_data *drv = priv; + struct i802_bss *new_bss = NULL; + struct ifreq ifr; + struct rtk_hapd_config config; + struct hostapd_data *hapd = drv->hapd; + + //printf("realtek_bss_add : ifname = %s\n",ifname); + + new_bss = os_zalloc(sizeof(*new_bss)); + if (new_bss == NULL) + return -1; + + + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", ifname); +#ifdef STAND_ALONE + if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) { + perror("ioctl(SIOCGIFINDEX)"); + goto bad; + } +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&ifr,sizeof(ifr)); + if (inband_ioctl(SIOCGIFINDEX, &ifr) < 0) { + perror("inband_ioctl(SIOCGIFINDEX)"); + goto bad; + } +#endif + os_strlcpy(new_bss->ifname, ifname, IFNAMSIZ); + +#ifdef INBAND_CTRL + new_bss->sock_xmit = drv->sock_xmit; +#else + new_bss->sock_xmit = l2_packet_init(new_bss->ifname, NULL, ETH_P_EAPOL, handle_read, drv, 1); +#endif + if (new_bss->sock_xmit == NULL) + goto bad; + + //do we nee to set HW addr to VAP?? + realtek_set_iface_flags(new_bss->ifname,drv, 0); //down the interface ...... , bring up in realtek_commit!! + + if (bssid[0] | bssid[1] | bssid[2] | bssid[3] | bssid[4] | bssid[5]) + realtek_set_iface_hwMac(new_bss->ifname,drv, bssid); + else + printf("Warning !!! VAP no HW addr setting \n"); + + //memset(&config, 0, sizeof(struct rtk_hapd_config)); + os_memcpy(&config, &rtk_config, sizeof(struct rtk_hapd_config)); //get some val from root + hapd =(struct hostapd_data *) find_hapd_by_ifname(priv,ifname); + + realtek_set_privacy(ifname, drv, 0); /* default to no privacy */ + + if(realtek_read_hapd_cfg(hapd,priv, &config)) + goto bad; + + //if(realtek_read_priv_cfg(priv, &config)) //already read in init + // goto bad; + if(realtek_read_priv_vap_cfg(ifname,priv, &config)) //already read in init + goto bad; + + +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN + // rtk_hapd_config need to swap , write a function to do it + rtk_cfg_to_bigEndian(&config); +#endif + + if(set80211priv(ifname,drv, HAPD_IOCTL_SETCONFIG, &config, sizeof(config))) + { + wpa_printf(MSG_ERROR, "%s: Failed to set Configurations", __func__); + goto bad; + } + + /*if(realtek_read_wds_cfg(priv, &wds)) //mark_mbssid , wds for vap ?? + return -1;*/ + + if((hapd->conf->wpa == 0) && (hapd->conf->ieee802_1x == 0 )) + realtek_set_ieee8021x(ifname, drv, 0); + + new_bss->ifindex = ifr.ifr_ifindex; + new_bss->drv = drv; + new_bss->next = drv->first_bss.next; + drv->first_bss.next = new_bss; + add_ifidx(drv, new_bss->ifindex); + + return 0; + +bad : + os_free(new_bss); + return -1; +} + +static int realtek_bss_remove(void *priv, const char *ifname) +{ + + //printf("realtek_bss_remove : ifname = %s\n",ifname); + + rtk_free_bss_by_ifname(priv,ifname); + + realtek_set_iface_flags(ifname,priv, 0); //down VAP + + return 0; +} + +static void * +realtek_driver_init(struct hostapd_data *hapd) +{ + struct realtek_driver_data *drv; + struct ifreq ifr; + struct iwreq iwr; + struct i802_bss *bss; + + wpa_printf(MSG_DEBUG, "realtek_init +++"); + + drv = os_zalloc(sizeof(struct realtek_driver_data)); + if (drv == NULL) { + printf("Could not allocate memory for realtek driver data\n"); + goto bad; + } + + drv->hapd = hapd; + bss = &drv->first_bss; + bss->drv = drv; + os_strlcpy(bss->ifname, hapd->conf->iface, sizeof(bss->ifname)); + + drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); + if (drv->ioctl_sock < 0) { + perror("socket[PF_INET,SOCK_DGRAM]"); + goto bad; + } + memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface)); + + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", drv->iface); +#ifdef STAND_ALONE + if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) { + perror("ioctl(SIOCGIFINDEX)"); + goto bad; + } +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&ifr,sizeof(ifr)); + if (inband_ioctl(SIOCGIFINDEX, &ifr) < 0) { + perror("inband_ioctl(SIOCGIFINDEX)"); + goto bad; + } +#endif + drv->ifindex = ifr.ifr_ifindex; + bss->ifindex = drv->ifindex; +#ifdef INBAND_CTRL + drv->sock_xmit = l2_packet_init(INBAND_INTF, NULL, ETH_P_EAPOL, handle_read, drv, 1); +#else + drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL, handle_read, drv, 1); +#endif + if (drv->sock_xmit == NULL) + goto bad; +#ifdef INBAND_CTRL + if( rtk_l2_packet_get_own_addr(drv,hapd->own_addr) ) +#else + if (l2_packet_get_own_addr(drv->sock_xmit, hapd->own_addr)) +#endif + goto bad; + + //mark_mbssid , now recv all EAPOL from one socket + drv->sock_recv = socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_EAPOL)); + if (drv->sock_recv < 0) { + perror("socket(PF_PACKET, SOCK_DGRAM, ETH_P_EAPOL)"); + goto bad; + } + if (eloop_register_read_sock(drv->sock_recv, handle_eapol, drv, NULL)) + { + printf("Could not register read socket for eapol\n"); + goto bad; + } + + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ); + + realtek_set_iface_flags(drv->iface,drv, 0); /* mark down during setup */ + realtek_set_privacy(drv->iface, drv, 0); /* default to no privacy */ + + if(realtek_hapd_config(drv)) + goto bad; + + if((hapd->conf->wpa == 0) && (hapd->conf->ieee802_1x == 0 )) + realtek_set_ieee8021x(drv->iface, drv, 0); + + wpa_printf(MSG_DEBUG, "realtek_init ---"); + return bss; +bad: + wpa_printf(MSG_ERROR, "realtek_init failed!"); + + if (drv != NULL) + realtek_deinit(drv); + + return NULL; +} + +static void * +realtek_init(struct hostapd_data *hapd) +{ + struct realtek_driver_data *drv; + struct i802_bss *bss; + int i; + + bss = realtek_driver_init(hapd); + + if (bss == NULL) + return NULL; + + drv = bss->drv; + + drv->num_if_indices = RTK_MAX_IF_INDEX; + for(i=0;inum_if_indices;i++) + drv->if_indices[i]=0; + + add_ifidx(drv, drv->ifindex); + + //below maybe add bridge control in the future + //return bss; + return drv; + +} + +#else //mark_mbssid , remove below in future + +static void * +realtek_init(struct hostapd_data *hapd) +{ + struct realtek_driver_data *drv; + struct ifreq ifr; + struct iwreq iwr; + + wpa_printf(MSG_DEBUG, "realtek_init +++"); + + drv = os_zalloc(sizeof(struct realtek_driver_data)); + if (drv == NULL) { + printf("Could not allocate memory for realtek driver data\n"); + goto bad; + } + + 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; + } + memcpy(drv->iface, hapd->conf->iface, sizeof(drv->iface)); + + memset(&ifr, 0, sizeof(ifr)); + snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", drv->iface); +#ifdef STAND_ALONE + if (ioctl(drv->ioctl_sock, SIOCGIFINDEX, &ifr) != 0) { + perror("ioctl(SIOCGIFINDEX)"); + goto bad; + } +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&ifr,sizeof(ifr)); + if (inband_ioctl(SIOCGIFINDEX, &ifr) < 0) { + perror("inband_ioctl(SIOCGIFINDEX)"); + goto bad; + } +#endif + drv->ifindex = ifr.ifr_ifindex; +#ifdef INBAND_CTRL + drv->sock_xmit = l2_packet_init(INBAND_INTF, NULL, ETH_P_EAPOL, handle_read, drv, 1); +#else + drv->sock_xmit = l2_packet_init(drv->iface, NULL, ETH_P_EAPOL, handle_read, drv, 1); +#endif + if (drv->sock_xmit == NULL) + goto bad; +#ifdef INBAND_CTRL + if( rtk_l2_packet_get_own_addr(drv,hapd->own_addr) ) +#else + if (l2_packet_get_own_addr(drv->sock_xmit, hapd->own_addr)) +#endif + goto bad; + if (hapd->conf->bridge[0] != '\0') { + drv->sock_recv = l2_packet_init(hapd->conf->bridge, NULL, + ETH_P_EAPOL, handle_read, drv, + 1); //fix receive sock?? + if (drv->sock_recv == NULL) + goto bad; + } else + drv->sock_recv = drv->sock_xmit; + + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ); + + realtek_set_iface_flags(drv->iface,drv, 0); /* mark down during setup */ + realtek_set_privacy(drv->iface, drv, 0); /* default to no privacy */ + + if(realtek_hapd_config(drv)) + goto bad; + + if((hapd->conf->wpa == 0) && (hapd->conf->ieee802_1x == 0 )) + realtek_set_ieee8021x(drv->iface, drv, 0); + + wpa_printf(MSG_DEBUG, "realtek_init ---"); + return drv; +bad: + wpa_printf(MSG_ERROR, "realtek_init failed!"); + + if (drv != NULL) + realtek_deinit(drv); + + return -1; +} +#endif + +static void +realtek_deinit(void *priv) +{ + struct realtek_driver_data *drv = priv; + + wpa_printf(MSG_DEBUG, "realtek_deinit +++"); + + drv->hapd->driver = NULL; + + realtek_set_iface_flags(drv->iface,drv, 0); + #if 0 /* OLD */ + if (drv->probe_recv != NULL) + l2_packet_deinit(drv->probe_recv); + #endif + if (drv->ioctl_sock >= 0) + close(drv->ioctl_sock); +#ifdef RTK_MBSSID + if (drv->sock_recv >= 0) { + eloop_unregister_read_sock(drv->sock_recv); + close(drv->sock_recv); + } +#else + if (drv->sock_recv != NULL && drv->sock_recv != drv->sock_xmit) + l2_packet_deinit(drv->sock_recv); +#endif + if (drv->sock_xmit != NULL) + l2_packet_deinit(drv->sock_xmit); + free(drv); + + wpa_printf(MSG_DEBUG, "realtek_deinit ---"); +} + +static int +realtek_set_ssid(const char *ifname, void *priv, const u8 *buf, int len) +{ + struct realtek_driver_data *drv = priv; + struct iwreq iwr; + + wpa_printf(MSG_DEBUG, "realtek_set_ssid +++"); + + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, ifname, IFNAMSIZ); + iwr.u.essid.flags = 1; /* SSID active */ + iwr.u.essid.pointer = (caddr_t) buf; + iwr.u.essid.length = len + 1; +#ifdef STAND_ALONE + if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) { + perror("ioctl[SIOCSIWESSID]"); + printf("len=%d\n", len); + return -1; + } +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr)); + if (inband_ioctl(SIOCSIWESSID, &iwr) < 0) { + perror("inband_ioctl[SIOCSIWESSID]"); + printf("len=%d\n", len); + return -1; + } +#endif + return 0; +} + +static int +realtek_get_ssid(const char *ifname, void *priv, u8 *buf, int len) +{ + struct realtek_driver_data *drv = priv; + struct iwreq iwr; + int ret = 0; + + wpa_printf(MSG_DEBUG, "realtek_get_ssid +++"); + + memset(&iwr, 0, sizeof(iwr)); + strncpy(iwr.ifr_name, ifname, IFNAMSIZ); + iwr.u.essid.pointer = (caddr_t) buf; + iwr.u.essid.length = len; +#ifdef STAND_ALONE + if (ioctl(drv->ioctl_sock, SIOCGIWESSID, &iwr) < 0) { + perror("ioctl[SIOCGIWESSID]"); + ret = -1; + } else + ret = iwr.u.essid.length; +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr)); + if (inband_ioctl(SIOCGIWESSID, &iwr) < 0) { + perror("ioctl[SIOCGIWESSID]"); + ret = -1; + } +#endif + return ret; +} + +static int +realtek_set_countermeasures(void *priv, int enabled) +{ + struct realtek_driver_data *drv = priv; + wpa_printf(MSG_DEBUG, "realtek_set_countermeasures +++"); + wpa_printf(MSG_DEBUG, "%s: enabled=%d", __FUNCTION__, enabled); + return set80211param(drv->iface,drv, IEEE80211_PARAM_COUNTERMEASURES, enabled); +} + +#ifdef INBAND_CTRL +/* inband ioctl start */ +inline void realtek_priviwr(struct iwreq *iwr, unsigned char *param, void *value) +{ + unsigned char buf[1024] = {0}; + + sprintf(buf,"%s=%d",param,*(unsigned int *)value); + iwr->u.data.length = os_strlen(buf); + iwr->u.data.pointer = os_malloc(iwr->u.data.length+1); + if( iwr->u.data.pointer ) + os_memcpy(iwr->u.data.pointer,buf,iwr->u.data.length+1); + else + printf("Err: Alloc memory failed while %s\n",__FUNCTION__); +} +#endif + + +static int +realtek_commit(void *priv) +{ + struct realtek_driver_data *drv = priv; +#ifdef RTK_MBSSID + struct i802_bss *tbss = &drv->first_bss,*bss; + wpa_printf(MSG_DEBUG, "realtek_commit +++"); + + //up root interface here + if(realtek_set_iface_flags(drv->iface,priv, 1) < 0) + return -1; + //up other VAP + while (tbss) { + + bss = tbss->next; + if(bss == NULL) + break; + + if(realtek_set_iface_flags(bss->ifname,priv, 1)<0) + return -1; + tbss = tbss->next ; + } + return 0; +#else + return realtek_set_iface_flags(drv->iface,priv, 1); +#endif +} + +#ifdef EAP_WPS +static int +realtek_set_wps_ie(const char *ifname,void *priv, u8 *iebuf, int iebuflen, u32 frametype) +{ + struct realtek_driver_data *drv = priv; + u8 buf[256]; + struct ieee80211req_getset_appiebuf * ie; + // int i; + + ie = (struct ieee80211req_getset_appiebuf *) buf; + ie->app_frmtype = frametype; + ie->app_buflen = iebuflen; + if (iebuflen > 0) + os_memcpy(&(ie->app_buf[0]), iebuf, iebuflen); + +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN + // int32 need to swap + ie->app_frmtype = htonl(ie->app_frmtype); + ie->app_buflen = htonl(ie->app_buflen); +#endif + return set80211priv(ifname,priv, IEEE80211_IOCTL_SET_APPIEBUF, ie, + sizeof(struct ieee80211req_getset_appiebuf) + iebuflen); +} + + +static int +realtek_set_wps_beacon_ie(const char *ifname, void *priv, const u8 *iebuf, size_t iebuflen) +{ + wpa_printf(MSG_DEBUG, "realtek_set_wps_beacon_ie +++"); + return realtek_set_wps_ie(ifname,priv, iebuf, iebuflen, + IEEE80211_APPIE_FRAME_BEACON); +} + + +static int +realtek_set_wps_probe_resp_ie(const char *ifname, void *priv, const u8 *iebuf, size_t iebuflen) +{ + wpa_printf(MSG_DEBUG, "realtek_set_wps_probe_resp_ie +++"); + return realtek_set_wps_ie(ifname,priv, iebuf, iebuflen, + IEEE80211_APPIE_FRAME_PROBE_RESP); +} + + +static int +realtek_set_wps_assoc_resp_ie(const char *ifname, void *priv, const u8 *iebuf, size_t iebuflen) +{ + wpa_printf(MSG_DEBUG, "realtek_set_wps_assoc_resp_ie +++"); + return realtek_set_wps_ie(ifname,priv, iebuf, iebuflen, + IEEE80211_APPIE_FRAME_ASSOC_RESP); +} + + +/* Ask to receive copies of all probe requests received. + */ +static int +realtek_start_receive_prob_req(void *priv) +{ +#if 0 //this function is not used now!! + struct ieee80211req_set_filter filt; + + wpa_printf(MSG_DEBUG, "%s Enter\n", __FUNCTION__); + filt.app_filterype = IEEE80211_FILTER_TYPE_PROBE_REQ; +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN + // int32 need to swap + filt.app_filterype = htonl(filt.app_filterype); +#endif + return set80211priv(priv, IEEE80211_IOCTL_FILTERFRAME, &filt, + sizeof(struct ieee80211req_set_filter)); +#endif + return 0; +} + +#endif /* EAP_WPS */ + +#ifdef RTK_HAPD +//Turn ON|OFF driver for hostapd reload. +//mark_mbssid , realtek_driver_on , it's only for WPS in root hapd reload +static int realtek_driver_on(void *priv, int on) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + + wpa_printf(MSG_DEBUG, "realtek_driver_on = %d +++", on); + + if((hapd->conf->wpa == 0) && (hapd->conf->ieee802_1x ==0 ) && (on == 1)) + realtek_set_ieee8021x(drv->iface, drv, 0); + + return realtek_set_iface_flags(drv->iface,priv, on); +} + +static int realtek_config_rate(int *rate_list, unsigned int *rate_config) +{ + // bit mask value. bit0-bit11 as 1,2,5.5,11,6,9,12,18,24,36,48,54 + int temp = 0; + + while(1) + { + int rate; + rate = rate_list[temp]; + if((rate == -1) || (rate == 0)) + break; + + if(rate == 10) + *rate_config |= BIT(0); + else if(rate == 20) + *rate_config |= BIT(1); + else if(rate == 55) + *rate_config |= BIT(2); + else if(rate == 110) + *rate_config |= BIT(3); + else if(rate == 60) + *rate_config |= BIT(4); + else if(rate == 90) + *rate_config |= BIT(5); + else if(rate == 120) + *rate_config |= BIT(6); + else if(rate == 180) + *rate_config |= BIT(7); + else if(rate == 240) + *rate_config |= BIT(8); + else if(rate == 360) + *rate_config |= BIT(9); + else if(rate == 480) + *rate_config |= BIT(10); + else if(rate == 540) + *rate_config |= BIT(11); + + temp++; + + if(temp > 12) + { + wpa_printf(MSG_ERROR, "Config Rates NUM > 12!!!"); + return -1; + } + + } + + return 0; + +} + +static int realtek_parse_pwrlevel(unsigned char* pwr_list, char *val) +{ + int count; + char *pos, *end; + + pos = val; + count = 0; + while (*pos != '\0') { + if (*pos == ' ') + count++; + pos++; + } + + pos = val; + count = 0; + + while (*pos != '\0') { + end = os_strchr(pos, ' '); + if (end) + *end = '\0'; + + pwr_list[count] = atoi(pos); + + if (!end) + break; + + count ++; + if(count >=MAX_2G_CHANNEL_NUM) + break; + + pos = end + 1; + } + + return 0; +} + + +static int realtek_read_hapd_cfg(struct hostapd_data *hapd,void *priv, struct rtk_hapd_config* config) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_config *iconf = hapd->iconf; + struct hostapd_bss_config *conf = hapd->conf; + + int temp = 0; + + wpa_printf(MSG_DEBUG, "realtek_read_hapd_cfg +++"); + + config->band |= BIT(iconf->hw_mode); + if(iconf->ieee80211n) + config->band |= BIT(3); + + config->channel = iconf->channel; + + config->bcnint = iconf->beacon_int; + + config->dtimperiod = conf->dtim_period; + + //if(conf->max_num_sta > RTK_MAX_STA)//mark_mbssid ,issue how to sync conf and rtk real support + config->stanum = conf->max_num_sta; + + config->rtsthres = iconf->rts_threshold; + + config->fragthres = iconf->fragm_threshold; + + if(realtek_config_rate(iconf->supported_rates, &(config->oprates))) + return -1; + + if(realtek_config_rate(iconf->basic_rates, &(config->basicrates))) + return -1; + + config->preamble = iconf->preamble; + + config->aclmode = conf->macaddr_acl; + + if(config->aclmode == ACCEPT_UNLESS_DENIED) + { + int x = 0, y =0; + config->aclnum = conf->num_deny_mac; + + if(config->aclnum > 0) + { + for(x=0; x < config->aclnum; x++) + { + struct mac_acl_entry *deny_mac = &conf->deny_mac[x]; + for(y=0; yacladdr[x][y] = deny_mac->addr[y]; + } + wpa_printf(MSG_DEBUG, "DENY ACL# %d = %s", x, ether_sprintf(config->acladdr[x])); + } + } + } + else if(config->aclmode == DENY_UNLESS_ACCEPTED) + { + int x = 0, y = 0; + config->aclnum = conf->num_accept_mac; + + if(config->aclnum > 0) + { + for(x=0; xaclnum; x++) + { + struct mac_acl_entry *accept_mac = &conf->accept_mac[x]; + for(y=0; yacladdr[x][y] = accept_mac->addr[y]; + } + wpa_printf(MSG_DEBUG, "ACCEPT ACL# %d = %s", x, ether_sprintf(config->acladdr[x])); + } + } + } + + config->hiddenAP = conf->ignore_broadcast_ssid; + + config->qos_enable = conf->wmm_enabled; + + config->expired_time = conf->ap_max_inactivity; + + config->block_relay = iconf->bridge_packets; + + if(iconf->ht_capab &= HT_CAP_INFO_SHORT_GI20MHZ) + config->shortGI20M = 1; + + if(iconf->ht_capab &= HT_CAP_INFO_SHORT_GI40MHZ) + config->shortGI40M = 1; + + wpa_printf(MSG_DEBUG, "realtek_read_hapd_cfg ---"); + + return 0; + +} + +static int realtek_read_priv_vap_cfg(const char *ifname,void *priv, struct rtk_hapd_config* config) +{ + + struct realtek_driver_data *drv = priv; + FILE *f; + char buf[256], *pos; + int errors = 0; + int line = 0; + int in_bss_section=0; + + f = fopen(drv->hapd->iface->config_fname, "r"); + if (f == NULL) + { + wpa_printf(MSG_ERROR, "Could not open configuration file '%s' " + "for reading.", drv->hapd->iface->config_fname); + return -1; + } + + while (fgets(buf, sizeof(buf), f)) + { + line++; + if (buf[0] == '#') + continue; + pos = buf; + while (*pos != '\0') + { + if (*pos == '\n') + { + *pos = '\0'; + break; + } + pos++; + } + + if (buf[0] == '\0') + continue; + + pos = os_strchr(buf, '='); + if (pos == NULL) + { + wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'", line, buf); + errors++; + continue; + } + *pos = '\0'; + pos++; + if (os_strcmp(buf, "bss") == 0) { + + if(in_bss_section) //already in section , then scan finished; + break; + if(os_strcmp(pos, ifname) == 0) + { + in_bss_section = 1; + } + continue; + } + //below is the rtk parameter for per VAP + if(in_bss_section){ + /*else if (os_strcmp(buf, "autorate") == 0) { //mark_issue + config->autorate = atoi(pos); + }*/ + if (os_strcmp(buf, "fixrate") == 0) { + unsigned int select=0; + select = atoi(pos); + if(select == 0) + { + config->autorate = 1; + config->fixrate = 0; + } + else + { + config->autorate = 0; + config->fixrate = (1 << (select-1)); + } + //mark_issue , need to validate the rate with hw_mode(G? , N?) + }else if (os_strcmp(buf, "guest_access") == 0) { + config->guest_access= atoi(pos); + } + } + } + + fclose(f); + + if (errors) + wpa_printf(MSG_ERROR, "%d errors found in configuration file " + "'%s'", errors, drv->hapd->iface->config_fname); + + return errors; + +} + + +static int realtek_read_priv_cfg(void *priv, struct rtk_hapd_config* config) +{ + + struct realtek_driver_data *drv = priv; + FILE *f; + char buf[256], *pos; + int errors = 0; + int line = 0; + + wpa_printf(MSG_DEBUG, "realtek_read_priv_cfg +++"); + + f = fopen(drv->hapd->iface->config_fname, "r"); + if (f == NULL) + { + wpa_printf(MSG_ERROR, "Could not open configuration file '%s' " + "for reading.", drv->hapd->iface->config_fname); + return -1; + } + + while (fgets(buf, sizeof(buf), f)) + { + line++; + if (buf[0] == '#') + continue; + pos = buf; + while (*pos != '\0') + { + if (*pos == '\n') + { + *pos = '\0'; + break; + } + pos++; + } + + if (buf[0] == '\0') + continue; + + pos = os_strchr(buf, '='); + if (pos == NULL) + { + wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'", line, buf); + errors++; + continue; + } + *pos = '\0'; + pos++; + if (os_strcmp(buf, "bss") == 0) { + break; //only read interface section + } + if (os_strcmp(buf, "pwrlevelCCK_A") == 0) { + realtek_parse_pwrlevel(config->pwrlevelCCK_A, pos); + } + else if (os_strcmp(buf, "pwrlevelCCK_B") == 0) { + realtek_parse_pwrlevel(config->pwrlevelCCK_B, pos); + } + else if (os_strcmp(buf, "pwrlevelHT40_1S_A") == 0) { + realtek_parse_pwrlevel(config->pwrlevelHT40_1S_A, pos); + } + else if (os_strcmp(buf, "pwrlevelHT40_1S_B") == 0) { + realtek_parse_pwrlevel(config->pwrlevelHT40_1S_B, pos); + } + else if (os_strcmp(buf, "pwrdiffHT40_2S") == 0) { + realtek_parse_pwrlevel(config->pwrdiffHT40_2S, pos); + } + else if (os_strcmp(buf, "pwrdiffHT20") == 0) { + realtek_parse_pwrlevel(config->pwrdiffHT20, pos); + } + else if (os_strcmp(buf, "pwrdiffOFDM") == 0) { + realtek_parse_pwrlevel(config->pwrdiffOFDM, pos); + } + else if (os_strcmp(buf, "phyBandSelect") == 0) { + config->phyBandSelect = atoi(pos); + } + else if (os_strcmp(buf, "macPhyMode") == 0) { + config->macPhyMode = atoi(pos); + } + else if (os_strcmp(buf, "ther") == 0) { + config->ther = atoi(pos); + } + else if (os_strcmp(buf, "swcrypto") == 0) { + config->swcrypto = atoi(pos); + } + else if (os_strcmp(buf, "regdomain") == 0) { + config->regdomain = atoi(pos); + } + /*else if (os_strcmp(buf, "autorate") == 0) { //mark_issue + config->autorate = atoi(pos); + }*/ + else if (os_strcmp(buf, "fixrate") == 0) { + unsigned int select=0; + select = atoi(pos); + if(select == 0) + { + config->autorate = 1; + config->fixrate = 0; + } + else + { + config->autorate = 0; + config->fixrate = (1 << (select-1)); + } + //mark_issue , need to validate the rate with hw_mode(G? , N?) + } + else if (os_strcmp(buf, "disable_protection") == 0) { + config->disable_protection = atoi(pos); + } + else if (os_strcmp(buf, "disable_olbc") == 0) { + config->disable_olbc = atoi(pos); + } + else if (os_strcmp(buf, "deny_legacy") == 0) { + config->deny_legacy = atoi(pos); + } + else if (os_strcmp(buf, "opmode") == 0) { + config->opmode = atoi(pos); + } + else if (os_strcmp(buf, "vap_enable") == 0) { + config->vap_enable = atoi(pos); + } + else if (os_strcmp(buf, "use40M") == 0) { + config->use40M = atoi(pos); + } + else if (os_strcmp(buf, "2ndchoffset") == 0) { + config->_2ndchoffset = atoi(pos); + } + else if (os_strcmp(buf, "ampdu") == 0) { + config->ampdu = atoi(pos); + } + else if (os_strcmp(buf, "coexist") == 0) { + config->coexist = atoi(pos); + } + else if (os_strcmp(buf, "rssi_dump") == 0) { + config->rssi_dump = atoi(pos); + } + else if (os_strcmp(buf, "mp_specific") == 0) { + config->mp_specific = atoi(pos); + } + else if (os_strcmp(buf, "use_ext_pa") == 0) { + config->use_ext_pa = atoi(pos); + } + else if (os_strcmp(buf, "guest_access") == 0) { + config->guest_access= atoi(pos); + } + + } + + fclose(f); + + if (errors) + wpa_printf(MSG_ERROR, "%d errors found in configuration file " + "'%s'", errors, drv->hapd->iface->config_fname); + + wpa_printf(MSG_DEBUG, "realtek_read_priv_cfg ---"); + + return errors; + +} + + + +static int realtek_read_wds_cfg(void *priv, struct rtk_wds_config* wds) +{ + + struct realtek_driver_data *drv = priv; + FILE *f; + char buf[256], *pos; + int errors = 0; + int line = 0; + + wpa_printf(MSG_DEBUG, "realtek_read_wds_cfg +++"); + + f = fopen(drv->hapd->iface->config_fname, "r"); + if (f == NULL) + { + wpa_printf(MSG_ERROR, "Could not open configuration file '%s' " + "for reading.", drv->hapd->iface->config_fname); + return -1; + } + + while (fgets(buf, sizeof(buf), f)) + { + line++; + if (buf[0] == '#') + continue; + pos = buf; + while (*pos != '\0') + { + if (*pos == '\n') + { + *pos = '\0'; + break; + } + pos++; + } + + if (buf[0] == '\0') + continue; + + pos = os_strchr(buf, '='); + if (pos == NULL) + { + wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'", line, buf); + errors++; + continue; + } + *pos = '\0'; + pos++; + + if (strcmp(buf, "wds_enable") == 0) { + wds->wdsEnabled = atoi(pos); + } + else if (strcmp(buf, "wds_num") == 0) { + wds->wdsNum = atoi(pos); + } + else if (strcmp(buf, "wds_mac1") == 0) { + if (hwaddr_aton(pos, wds->macAddr[0])) { + wpa_printf(MSG_ERROR, "Line %d: invalid MAC address '%s'\n", line, pos); + errors++; + } + } + else if (strcmp(buf, "wds_mac2") == 0) { + if (hwaddr_aton(pos, wds->macAddr[1])) { + wpa_printf(MSG_ERROR, "Line %d: invalid MAC address '%s'\n", line, pos); + errors++; + } + } + else if (strcmp(buf, "wds_mac3") == 0) { + if (hwaddr_aton(pos, wds->macAddr[2])) { + wpa_printf(MSG_ERROR, "Line %d: invalid MAC address '%s'\n", line, pos); + errors++; + } + } + else if (strcmp(buf, "wds_mac4") == 0) { + if (hwaddr_aton(pos, wds->macAddr[3])) { + wpa_printf(MSG_ERROR, "Line %d: invalid MAC address '%s'\n", line, pos); + errors++; + } + } + else if (strcmp(buf, "wds_ssid") == 0) { + int ssid_len = strlen(pos); + if (ssid_len > HOSTAPD_MAX_SSID_LEN || ssid_len < 1) { + wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'\n", line, pos); + errors++; + } else { + memcpy(wds->ssid, pos, ssid_len); + wds->ssid[ssid_len] = '\0'; + } + } + else if (strcmp(buf, "wds_enc_type") == 0) { + wds->wdsPrivacy = atoi(pos); + } + else if (strcmp(buf, "wds_wepkey") == 0) { + int len = strlen(pos); + int tmp_error = 0; + + //free(wds->wdsWepKey); + wds->wdsWepKey = NULL; + wds->wdsWepKeyLen = 0; + + if (pos[0] == '"') { + if (len < 2 || pos[len - 1] != '"') + tmp_error++; + else{ + len -= 2; + if (len > 0) { + wds->wdsWepKey = malloc(len); + if (wds->wdsWepKey == NULL) + tmp_error++; + else + memcpy(wds->wdsWepKey, pos + 1, len); + } + } + } + else + { + if (len & 1) + tmp_error++; + + len /= 2; + if (len > 0) + { + wds->wdsWepKey = malloc(len); + if (wds->wdsWepKey == NULL) + tmp_error++; + + if (hexstr2bin(pos, wds->wdsWepKey, len) < 0) + tmp_error++; + } + } + + wds->wdsWepKeyLen = len; + + if(tmp_error) + { + wpa_printf(MSG_ERROR, "Line %d: invalid wds_wepkey '%s'\n", line, pos); + errors++; + } + } + else if (strcmp(buf, "wds_passphrase") == 0) { + int len = strlen(pos); + //free(wds->wdsPskPassPhrase); + wds->wdsPskPassPhrase = NULL; + if (len < 8 || len > 63) { + wpa_printf(MSG_ERROR, "Line %d: invalid WPA passphrase length" + " %d (expected 8..63)\n", line, len); + errors++; + } else { + if ((wds->wdsPskPassPhrase = strdup(pos)) == NULL) + errors++; + } + } + + } + + fclose(f); + + if (errors) + wpa_printf(MSG_ERROR, "%d errors found in configuration file " + "'%s'", errors, drv->hapd->iface->config_fname); + + wpa_printf(MSG_DEBUG, "realtek_read_wds_cfg ---"); + + return errors; + +} + +static int realtek_hapd_config(void *priv) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + struct rtk_hapd_config *config=&rtk_config; + struct rtk_wds_config wds; + + wpa_printf(MSG_DEBUG, "realtek_hapd_config +++"); + + memset(config, 0, sizeof(struct rtk_hapd_config)); + + config->is_hapd = 1; //RTK_WPAS + + if(realtek_read_hapd_cfg(hapd,priv, config)) + return -1; + + if(realtek_read_priv_cfg(priv, config)) + return -1; + +#ifdef INBAND_CTRL //HOST_LITTLE_ENDIAN + // rtk_hapd_config need to swap , write a function to do it + rtk_cfg_to_bigEndian(config); +#endif + + if(set80211priv(drv->iface,drv, HAPD_IOCTL_SETCONFIG, config, sizeof(struct rtk_hapd_config))) + { + wpa_printf(MSG_ERROR, "%s: Failed to set Configurations", __func__); + return -1; + } + + if(realtek_read_wds_cfg(priv, &wds)) //mark_mbssid , wds for vap ?? + return -1; + + /* + if(realtek_set_wds(priv, wds)) + return -1; + */ + + wpa_printf(MSG_DEBUG, "realtek_hapd_config ---"); + + return 0; + +} + + +#endif + + +const struct wpa_driver_ops wpa_driver_realtek_ops = { + .name = "realtek", + .init = realtek_init, + .deinit = realtek_deinit, + .set_ieee8021x = realtek_set_ieee8021x, + .set_privacy = realtek_set_privacy, + .set_encryption = realtek_set_key, + .get_seqnum = realtek_get_seqnum, + .flush = realtek_flush, + .set_generic_elem = realtek_set_opt_ie, + .wireless_event_init = realtek_wireless_event_init, + .wireless_event_deinit = realtek_wireless_event_deinit, + .sta_set_flags = realtek_sta_set_flags, + //mark read_sta_data because both ralink & broadcom NOT support + //.read_sta_data = realtek_read_sta_driver_data, + .send_eapol = realtek_send_eapol, + .sta_disassoc = realtek_sta_disassoc, + .sta_deauth = realtek_sta_deauth, +#ifdef RTK_MBSSID + .bss_add = realtek_bss_add, + .bss_remove = realtek_bss_remove, +#endif +#ifdef RTK_HAPD + .sta_remove = realtek_sta_remove, +#endif + .set_ssid = realtek_set_ssid, + .get_ssid = realtek_get_ssid, + .set_countermeasures = realtek_set_countermeasures, + //mark sta_clear_stats because both ralink & broadcom NOT support + //.sta_clear_stats = realtek_sta_clear_stats, + .commit = realtek_commit, +#ifdef EAP_WPS + .set_wps_beacon_ie = realtek_set_wps_beacon_ie, + .set_wps_probe_resp_ie = realtek_set_wps_probe_resp_ie, + //.set_wps_assoc_resp_ie = realtek_set_wps_assoc_resp_ie, +#endif /* EAP_WPS */ +#ifdef RTK_HAPD + .driver_on = realtek_driver_on, +#endif +}; + +#ifdef MODIFIED_BY_SONY +int wext_set_key(void *priv, int alg, + const u8 *addr, int key_idx, + int set_tx, const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len) +{ + struct realtek_driver_data *drv = priv; + struct hostapd_data *hapd = drv->hapd; + struct hostapd_bss_config *conf = hapd->conf; + struct iwreq iwr; + int ret = 0; + int ioctl_sock; + + wpa_printf(MSG_DEBUG,"%s: alg=%d key_idx=%d set_tx=%d seq_len=%lu " + "key_len=%lu", __FUNCTION__, alg, key_idx, set_tx, + (unsigned long) seq_len, (unsigned long) key_len); + + ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0); + if (ioctl_sock < 0) { + perror("socket(PF_INET,SOCK_DGRAM)"); + return -1; + } + + os_memset(&iwr, 0, sizeof(iwr)); + os_strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ); + iwr.u.encoding.flags = key_idx + 1; + if (alg == WPA_ALG_NONE) + iwr.u.encoding.flags |= IW_ENCODE_DISABLED; + if (conf->auth_algs & HOSTAPD_AUTH_OPEN) + iwr.u.encoding.flags |= IW_ENCODE_OPEN; + if (conf->auth_algs & HOSTAPD_AUTH_SHARED_KEY) + iwr.u.encoding.flags |= IW_ENCODE_RESTRICTED; + iwr.u.encoding.pointer = (caddr_t) key; + iwr.u.encoding.length = key_len; +#ifdef STAND_ALONE + if (ioctl(ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { + perror("ioctl[SIOCSIWENCODE]"); + ret = -1; + } +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr)); + if (inband_ioctl(&drv->ioctl_ioh_obj,SIOCSIWENCODE, &iwr) < 0) { + perror("inband_ioctl[SIOCSIWENCODE]"); + ret = -1; + } +#endif + + if (set_tx && alg != WPA_ALG_NONE) { + os_memset(&iwr, 0, sizeof(iwr)); + os_strncpy(iwr.ifr_name, drv->iface, IFNAMSIZ); + iwr.u.encoding.flags = key_idx + 1; + iwr.u.encoding.pointer = (caddr_t) key; + iwr.u.encoding.length = 0; +#ifdef STAND_ALONE + if (ioctl(ioctl_sock, SIOCSIWENCODE, &iwr) < 0) { + perror("ioctl[SIOCSIWENCODE] (set_tx)"); + ret = -1; + } +#endif +#if defined(INBAND_CTRL) + INBAND_IOCTLPKT_DUMP(&iwr,sizeof(iwr)); + if (inband_ioctl(&drv->ioctl_ioh_obj,SIOCSIWENCODE, &iwr) < 0) { + perror("inband_ioctl[SIOCSIWENCODE] (set_tx)"); + ret = -1; + } +#endif + + } + close(ioctl_sock); + return ret; +} +#endif /* MODIFIED_BY_SONY */ Index: hostapd-rtk-0.6.10/hostapd/driver_realtek.h =================================================================== --- /dev/null +++ hostapd-rtk-0.6.10/hostapd/driver_realtek.h @@ -0,0 +1,147 @@ + +#define MACADDRLEN 6 +#define PROBEIELEN 260 + +#define HAPD_IOCTL_GETWPAIE IEEE80211_IOCTL_GET_APPIEBUF +#define HAPD_IOCTL_SETCONFIG SIOCIWLASTPRIV +#define RTL8192CD_IOCTL_DEL_STA 0x89f7 +#define SIOCGIWIND 0x89ff + +#define HOSTAPD_WPA_VERSION_WPA BIT(0) +#define HOSTAPD_WPA_VERSION_WPA2 BIT(1) + +#define RTK_MBSSID 1 +#define RTK_MAX_STA 32 +#define RTK_MAX_IF_INDEX 16 + +enum HAPD_EVENT{ + HAPD_EXIRED = 0, + HAPD_REGISTERED = 1, + HAPD_MIC_FAILURE = 2, + HAPD_TRAFFIC_STAT = 3, + HAPD_PUSH_BUTTON = 4, + HAPD_WPS_PROBEREQ = 5, + HAPD_WDS_SETWPA = 6 +}; + +enum WIFI_STATUS_CODE { + _STATS_SUCCESSFUL_ = 0, // Success. + _STATS_FAILURE_ = 1, // Failure. + _STATS_CAP_FAIL_ = 10, // Capability too wide, can't support + _STATS_NO_ASOC_ = 11, // Denial reassociate + _STATS_OTHER_ = 12, // Denial connect, not 802.11 standard. + _STATS_NO_SUPP_ALG_ = 13, // Authenticate algorithm not support . + _STATS_OUT_OF_AUTH_SEQ_ = 14, // Out of authenticate sequence number. + _STATS_CHALLENGE_FAIL_ = 15, // Denial authenticate, Response message fail. + _STATS_AUTH_TIMEOUT_ = 16, // Denial authenticate, timeout. + _STATS_UNABLE_HANDLE_STA_ = 17, // Denial authenticate, BS resoruce insufficient. + _STATS_RATE_FAIL_ = 18, // Denial authenticate, STA not support BSS request datarate. + _STATS_REQ_DECLINED_ = 37, +/*#if defined(CONFIG_RTL_WAPI_SUPPORT)*/ + __STATS_INVALID_IE_ = 40, + __STATS_INVALID_AKMP_ = 43, + __STATS_CIPER_REJECT_ = 46, + __STATS_INVALID_USK_ = 47, + __STATS_INVALID_MSK_ = 48, + __STATS_INVALID_WAPI_VERSION_ = 49, + __STATS_INVALID_WAPI_CAPABILITY_ = 50, +/*#endif*/ + +#ifdef CONFIG_RTK_MESH // CATUTION: below undefine !! (Refer: Draft 1.06, Page 17, 7.3.1.9, Table 7-23, 2007/08/13 by popen) + _STATS_MESH_LINK_ESTABLISHED_ = 55, //The mesh peer link has been successfully + _STATS_MESH_LINK_CLOSED_ = 56, // The mesh peer link has been closed completely + _STATS_MESH_UNDEFINE1_ = 57, // No listed Key Holder Transport type is supported. + _STATS_MESH_UNDEFINE2_ = 58, // The Mesh Key Holder Security Handshake message was malformed. +#endif +}; + +typedef enum{ + DOT11_EVENT_NO_EVENT = 1, + DOT11_EVENT_REQUEST = 2, + DOT11_EVENT_ASSOCIATION_IND = 3, + DOT11_EVENT_ASSOCIATION_RSP = 4, + DOT11_EVENT_AUTHENTICATION_IND = 5, + DOT11_EVENT_REAUTHENTICATION_IND = 6, + DOT11_EVENT_DEAUTHENTICATION_IND = 7, + DOT11_EVENT_DISASSOCIATION_IND = 8, + DOT11_EVENT_DISCONNECT_REQ = 9, + DOT11_EVENT_SET_802DOT11 = 10, + DOT11_EVENT_SET_KEY = 11, + DOT11_EVENT_SET_PORT = 12, + DOT11_EVENT_DELETE_KEY = 13, + DOT11_EVENT_SET_RSNIE = 14, + DOT11_EVENT_GKEY_TSC = 15, + DOT11_EVENT_MIC_FAILURE = 16, + DOT11_EVENT_ASSOCIATION_INFO = 17, + DOT11_EVENT_INIT_QUEUE = 18, + DOT11_EVENT_EAPOLSTART = 19, +//2003-07-30 ------------ + DOT11_EVENT_ACC_SET_EXPIREDTIME = 31, + DOT11_EVENT_ACC_QUERY_STATS = 32, + DOT11_EVENT_ACC_QUERY_STATS_ALL = 33, +//----------------------- + +// --- 2003-08-04 --- + DOT11_EVENT_REASSOCIATION_IND = 34, + DOT11_EVENT_REASSOCIATION_RSP = 35, +//----------------------- + DOT11_EVENT_STA_QUERY_BSSID = 36, + DOT11_EVENT_STA_QUERY_SSID = 37, + +// jimmylin: pass EAP packet by event queue + DOT11_EVENT_EAP_PACKET = 41, + +#ifdef RTL_WPA2 + DOT11_EVENT_EAPOLSTART_PREAUTH = 45, + DOT11_EVENT_EAP_PACKET_PREAUTH = 46, +#endif + +#ifdef RTL_WPA2_CLIENT + DOT11_EVENT_WPA2_MULTICAST_CIPHER = 47, +#endif + + DOT11_EVENT_WPA_MULTICAST_CIPHER = 48, + +#ifdef AUTO_CONFIG + DOT11_EVENT_AUTOCONF_ASSOCIATION_IND = 50, + DOT11_EVENT_AUTOCONF_ASSOCIATION_CONFIRM = 51, + DOT11_EVENT_AUTOCONF_PACKET = 52, + DOT11_EVENT_AUTOCONF_LINK_IND = 53, +#endif + +#ifdef WIFI_SIMPLE_CONFIG + DOT11_EVENT_WSC_SET_IE = 55, + DOT11_EVENT_WSC_PROBE_REQ_IND = 56, + DOT11_EVENT_WSC_PIN_IND = 57, + DOT11_EVENT_WSC_ASSOC_REQ_IE_IND = 58, +#ifdef CONFIG_IWPRIV_INTF + DOT11_EVENT_WSC_START_IND = 70, + //EV_MODE, EV_STATUS, EV_MEHOD, EV_STEP, EV_OOB + DOT11_EVENT_WSC_MODE_IND = 71, + DOT11_EVENT_WSC_STATUS_IND = 72, + DOT11_EVENT_WSC_METHOD_IND = 73, + DOT11_EVENT_WSC_STEP_IND = 74, + DOT11_EVENT_WSC_OOB_IND = 75, +#endif //ifdef CONFIG_IWPRIV_INTF +#endif + + DOT11_EVENT_MAX = 59, +} DOT11_EVENT; + + +typedef struct _DOT11_PROBE_REQUEST_IND{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; + unsigned short ProbeIELen; + char ProbeIE[PROBEIELEN]; +}DOT11_PROBE_REQUEST_IND; + + +typedef struct _DOT11_ASSOCIATION_RSP{ + unsigned char EventId; + unsigned char IsMoreEvent; + char MACAddr[MACADDRLEN]; + unsigned char Status; +}DOT11_ASSOCIATION_RSP; + Index: hostapd-rtk-0.6.10/hostapd/README-REALTEK_WIFI =================================================================== --- /dev/null +++ hostapd-rtk-0.6.10/hostapd/README-REALTEK_WIFI @@ -0,0 +1,116 @@ +================================================================================== +Introduction + This document is the guideline for building/using/porting the Hostapd +application to support Realtek's Wifi device. + +================================================================================== + +1.Build the hostapd daemon +----------------------------- + If the Wifi device is connected to your platform using GMII/MII interface +then the inband libary must be built and enabled in hostapd.control. Please follow +the steps below to build the hostapd daemon.() + + a. Build the inband libary (#This step can be skipped,if you dont need inband-cotrol) + + - Enter the inband_dir directory.(default:../../inband_dir) + + - Modify the definition of CC and LD in /inband_lib/Makefile to fit your + toolchain setting. + + - type make and the inband.a libray will be built on your platform. + + b. Enable/Disable the inband-control support in Hostapd. + + - Enable the lines below in hostapd-0.6.10/hostapd/Makefile to enable the + inband-support.In the other hand,disable these lines to disable the inband-control. + + CFLAGS += -DINBAND_CTRL + CFLAGS += -I../../inband_lib + LIBS += ../../inband_lib/inband.a + + c. Make the Hostapd + + - enter the directory : hostapd-0.6.10/hostapd/ + + - Modify hostapd-0.6.10/hostapd/Makefile to include your openssl libary.Below + lines are the default setting in Realtek's WIFI-AP SDK. + + LIBS += -ldl ../../openssl-0.9.8b/libssl.a ../../openssl-0.9.8b/libcrypto.a + LIBS_p += ../../openssl-0.9.8b/libcrypto.a + LIBS_h += ../../openssl-0.9.8b/libcrypto.a + + - Modify the definition of CC and LD in hostapd-0.6.10/hostapd/Makefile to + fit your toolchain setting. + + - type 'make' under hostapd-0.6.10/hostapd ,then the hostapd daemon will be built. + +NOTEs: + - Because of the ethernet type 0x8899 and 0x9000 is used for inband control + please do not use them in other applications. + + - The default local interface for inband control is "br0', you can change the definition + in drv_realtek.c(the line list below) to fit your MII interface setting. + + #define INBAND_INTF "br0" + + - The default MAC address for inband-control is "00:12:34:56:78:99", it + can be changed in drv_realtek.c. + +================================================================================== + +2.Realtek proprietary configuration options +---------------------------- + + - Please refer to file hostapd.test_conf(under hostapd-0.6.10/hostapd/conf) + for detail descriptions about the new added realtek private configurations. All these + configurations are directly mapped to realtek WiFi mibs. + + - Other inherently hostapd configurations are same as before. + + - 'auth_algs' has new values for supporting Open Networking & WEP+802.1x + ## ======== Modify auth_algs support========== + ## bit 0 = Open System Authentication + ## bit 1 = Shared Key Authentication (requires WEP) + ## bit 0 + bit 1 = Auto WEP mode + ## bit 2 = WEP + 802.1x + ## bit 3 = Open Networking(no security) + + - These hostapd configuration files(under /hostapd-0.6.10/hostapd/conf) can be examples for testing + - hostapd.none_security :WPS configured, Open Networking. + - hostapd.wpa_psk :WPS configured, WPA-PSK CCMP. + - NOT Supported yet: + - Some IEEE 802.11 related configurations + - IEEE 802.11r configuration + - Passive scanning + - Multiple BSSID support + + +================================================================================== + +3.Porting notes +----------------------------- + The Hostapd for Realtek WiFi device is based on hostapd 0.6.10 and patch the realtek's implementation. +Some notes are listed below to help you to port this package to your platform(for example , +you are using hostapd 0.6.9 on your platform not 0.6.10). + + - Driver_realtek.c & Driver_realtek.h under /hostapd-0.6.10/hostapd are the main added files + for supporting realtek WiFi device. + + - Other modifications about Hostapd-0.6.10 were labeled with compile tag 'RTK_HAPD'. + You can check these patches by searching the keyword 'RTK_HAPD'. + + - List of modified source files in hostapd v0.6.10: + - Config.c + - Driver.h + - Hostapd.c + - Hostapd.h + - Iapp.c + - Os_unix.c + - Wps.h + - Wps_hostapd.c + - Wps_registrar.c + - Wps_upnp_event.c + - Wps_upnp_web.c + +=================================================================================