LCOV - code coverage report
Current view: top level - src/drivers - driver_hostap.c (source / functions) Hit Total Coverage
Test: hostapd/hlr_auc_gw (AS) hwsim test run 1388167526 Lines: 0 591 0.0 %
Date: 2013-12-27 Functions: 0 37 0.0 %
Branches: 0 207 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Driver interaction with Linux Host AP driver
       3                 :            :  * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
       4                 :            :  *
       5                 :            :  * This software may be distributed under the terms of the BSD license.
       6                 :            :  * See README for more details.
       7                 :            :  */
       8                 :            : 
       9                 :            : #include "includes.h"
      10                 :            : #include <sys/ioctl.h>
      11                 :            : 
      12                 :            : #include "linux_wext.h"
      13                 :            : #include "common.h"
      14                 :            : #include "driver.h"
      15                 :            : #include "driver_wext.h"
      16                 :            : #include "eloop.h"
      17                 :            : #include "driver_hostap.h"
      18                 :            : 
      19                 :            : 
      20                 :            : #include <net/if_arp.h>
      21                 :            : #include <netpacket/packet.h>
      22                 :            : 
      23                 :            : #include "priv_netlink.h"
      24                 :            : #include "netlink.h"
      25                 :            : #include "linux_ioctl.h"
      26                 :            : #include "common/ieee802_11_defs.h"
      27                 :            : #include "common/ieee802_11_common.h"
      28                 :            : 
      29                 :            : 
      30                 :            : /* MTU to be set for the wlan#ap device; this is mainly needed for IEEE 802.1X
      31                 :            :  * frames that might be longer than normal default MTU and they are not
      32                 :            :  * fragmented */
      33                 :            : #define HOSTAPD_MTU 2290
      34                 :            : 
      35                 :            : static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
      36                 :            : 
      37                 :            : struct hostap_driver_data {
      38                 :            :         struct hostapd_data *hapd;
      39                 :            : 
      40                 :            :         char iface[IFNAMSIZ + 1];
      41                 :            :         int sock; /* raw packet socket for driver access */
      42                 :            :         int ioctl_sock; /* socket for ioctl() use */
      43                 :            :         struct netlink_data *netlink;
      44                 :            : 
      45                 :            :         int we_version;
      46                 :            : 
      47                 :            :         u8 *generic_ie;
      48                 :            :         size_t generic_ie_len;
      49                 :            :         u8 *wps_ie;
      50                 :            :         size_t wps_ie_len;
      51                 :            : };
      52                 :            : 
      53                 :            : 
      54                 :            : static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param,
      55                 :            :                          int len);
      56                 :            : static int hostap_set_iface_flags(void *priv, int dev_up);
      57                 :            : 
      58                 :          0 : static void handle_data(struct hostap_driver_data *drv, u8 *buf, size_t len,
      59                 :            :                         u16 stype)
      60                 :            : {
      61                 :            :         struct ieee80211_hdr *hdr;
      62                 :            :         u16 fc, ethertype;
      63                 :            :         u8 *pos, *sa;
      64                 :            :         size_t left;
      65                 :            :         union wpa_event_data event;
      66                 :            : 
      67         [ #  # ]:          0 :         if (len < sizeof(struct ieee80211_hdr))
      68                 :          0 :                 return;
      69                 :            : 
      70                 :          0 :         hdr = (struct ieee80211_hdr *) buf;
      71                 :          0 :         fc = le_to_host16(hdr->frame_control);
      72                 :            : 
      73         [ #  # ]:          0 :         if ((fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) != WLAN_FC_TODS) {
      74                 :          0 :                 printf("Not ToDS data frame (fc=0x%04x)\n", fc);
      75                 :          0 :                 return;
      76                 :            :         }
      77                 :            : 
      78                 :          0 :         sa = hdr->addr2;
      79                 :          0 :         os_memset(&event, 0, sizeof(event));
      80                 :          0 :         event.rx_from_unknown.bssid = get_hdr_bssid(hdr, len);
      81                 :          0 :         event.rx_from_unknown.addr = sa;
      82                 :          0 :         wpa_supplicant_event(drv->hapd, EVENT_RX_FROM_UNKNOWN, &event);
      83                 :            : 
      84                 :          0 :         pos = (u8 *) (hdr + 1);
      85                 :          0 :         left = len - sizeof(*hdr);
      86                 :            : 
      87         [ #  # ]:          0 :         if (left < sizeof(rfc1042_header)) {
      88                 :          0 :                 printf("Too short data frame\n");
      89                 :          0 :                 return;
      90                 :            :         }
      91                 :            : 
      92         [ #  # ]:          0 :         if (memcmp(pos, rfc1042_header, sizeof(rfc1042_header)) != 0) {
      93                 :          0 :                 printf("Data frame with no RFC1042 header\n");
      94                 :          0 :                 return;
      95                 :            :         }
      96                 :          0 :         pos += sizeof(rfc1042_header);
      97                 :          0 :         left -= sizeof(rfc1042_header);
      98                 :            : 
      99         [ #  # ]:          0 :         if (left < 2) {
     100                 :          0 :                 printf("No ethertype in data frame\n");
     101                 :          0 :                 return;
     102                 :            :         }
     103                 :            : 
     104                 :          0 :         ethertype = WPA_GET_BE16(pos);
     105                 :          0 :         pos += 2;
     106                 :          0 :         left -= 2;
     107         [ #  # ]:          0 :         switch (ethertype) {
     108                 :            :         case ETH_P_PAE:
     109                 :          0 :                 drv_event_eapol_rx(drv->hapd, sa, pos, left);
     110                 :          0 :                 break;
     111                 :            : 
     112                 :            :         default:
     113                 :          0 :                 printf("Unknown ethertype 0x%04x in data frame\n", ethertype);
     114                 :          0 :                 break;
     115                 :            :         }
     116                 :            : }
     117                 :            : 
     118                 :            : 
     119                 :          0 : static void handle_tx_callback(struct hostap_driver_data *drv, u8 *buf,
     120                 :            :                                size_t len, int ok)
     121                 :            : {
     122                 :            :         struct ieee80211_hdr *hdr;
     123                 :            :         u16 fc;
     124                 :            :         union wpa_event_data event;
     125                 :            : 
     126                 :          0 :         hdr = (struct ieee80211_hdr *) buf;
     127                 :          0 :         fc = le_to_host16(hdr->frame_control);
     128                 :            : 
     129                 :          0 :         os_memset(&event, 0, sizeof(event));
     130                 :          0 :         event.tx_status.type = WLAN_FC_GET_TYPE(fc);
     131                 :          0 :         event.tx_status.stype = WLAN_FC_GET_STYPE(fc);
     132                 :          0 :         event.tx_status.dst = hdr->addr1;
     133                 :          0 :         event.tx_status.data = buf;
     134                 :          0 :         event.tx_status.data_len = len;
     135                 :          0 :         event.tx_status.ack = ok;
     136                 :          0 :         wpa_supplicant_event(drv->hapd, EVENT_TX_STATUS, &event);
     137                 :          0 : }
     138                 :            : 
     139                 :            : 
     140                 :          0 : static void handle_frame(struct hostap_driver_data *drv, u8 *buf, size_t len)
     141                 :            : {
     142                 :            :         struct ieee80211_hdr *hdr;
     143                 :            :         u16 fc, extra_len, type, stype;
     144                 :          0 :         size_t data_len = len;
     145                 :            :         int ver;
     146                 :            :         union wpa_event_data event;
     147                 :            : 
     148                 :            :         /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass
     149                 :            :          * these to user space */
     150         [ #  # ]:          0 :         if (len < 24) {
     151                 :          0 :                 wpa_printf(MSG_MSGDUMP, "handle_frame: too short (%lu)",
     152                 :            :                            (unsigned long) len);
     153                 :          0 :                 return;
     154                 :            :         }
     155                 :            : 
     156                 :          0 :         hdr = (struct ieee80211_hdr *) buf;
     157                 :          0 :         fc = le_to_host16(hdr->frame_control);
     158                 :          0 :         type = WLAN_FC_GET_TYPE(fc);
     159                 :          0 :         stype = WLAN_FC_GET_STYPE(fc);
     160                 :            : 
     161 [ #  # ][ #  # ]:          0 :         if (type != WLAN_FC_TYPE_MGMT || stype != WLAN_FC_STYPE_BEACON) {
     162                 :          0 :                 wpa_hexdump(MSG_MSGDUMP, "Received management frame",
     163                 :            :                             buf, len);
     164                 :            :         }
     165                 :            : 
     166                 :          0 :         ver = fc & WLAN_FC_PVER;
     167                 :            : 
     168                 :            :         /* protocol version 3 is reserved for indicating extra data after the
     169                 :            :          * payload, version 2 for indicating ACKed frame (TX callbacks), and
     170                 :            :          * version 1 for indicating failed frame (no ACK, TX callbacks) */
     171         [ #  # ]:          0 :         if (ver == 3) {
     172                 :          0 :                 u8 *pos = buf + len - 2;
     173                 :          0 :                 extra_len = WPA_GET_LE16(pos);
     174                 :          0 :                 printf("extra data in frame (elen=%d)\n", extra_len);
     175         [ #  # ]:          0 :                 if ((size_t) extra_len + 2 > len) {
     176                 :          0 :                         printf("  extra data overflow\n");
     177                 :          0 :                         return;
     178                 :            :                 }
     179                 :          0 :                 len -= extra_len + 2;
     180 [ #  # ][ #  # ]:          0 :         } else if (ver == 1 || ver == 2) {
     181                 :          0 :                 handle_tx_callback(drv, buf, data_len, ver == 2 ? 1 : 0);
     182                 :          0 :                 return;
     183         [ #  # ]:          0 :         } else if (ver != 0) {
     184                 :          0 :                 printf("unknown protocol version %d\n", ver);
     185                 :          0 :                 return;
     186                 :            :         }
     187                 :            : 
     188   [ #  #  #  # ]:          0 :         switch (type) {
     189                 :            :         case WLAN_FC_TYPE_MGMT:
     190                 :          0 :                 os_memset(&event, 0, sizeof(event));
     191                 :          0 :                 event.rx_mgmt.frame = buf;
     192                 :          0 :                 event.rx_mgmt.frame_len = data_len;
     193                 :          0 :                 wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event);
     194                 :          0 :                 break;
     195                 :            :         case WLAN_FC_TYPE_CTRL:
     196                 :          0 :                 wpa_printf(MSG_DEBUG, "CTRL");
     197                 :          0 :                 break;
     198                 :            :         case WLAN_FC_TYPE_DATA:
     199                 :          0 :                 wpa_printf(MSG_DEBUG, "DATA");
     200                 :          0 :                 handle_data(drv, buf, data_len, stype);
     201                 :          0 :                 break;
     202                 :            :         default:
     203                 :          0 :                 wpa_printf(MSG_DEBUG, "unknown frame type %d", type);
     204                 :          0 :                 break;
     205                 :            :         }
     206                 :            : }
     207                 :            : 
     208                 :            : 
     209                 :          0 : static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
     210                 :            : {
     211                 :          0 :         struct hostap_driver_data *drv = eloop_ctx;
     212                 :            :         int len;
     213                 :            :         unsigned char buf[3000];
     214                 :            : 
     215                 :          0 :         len = recv(sock, buf, sizeof(buf), 0);
     216         [ #  # ]:          0 :         if (len < 0) {
     217                 :          0 :                 perror("recv");
     218                 :          0 :                 return;
     219                 :            :         }
     220                 :            : 
     221                 :          0 :         handle_frame(drv, buf, len);
     222                 :            : }
     223                 :            : 
     224                 :            : 
     225                 :          0 : static int hostap_init_sockets(struct hostap_driver_data *drv, u8 *own_addr)
     226                 :            : {
     227                 :            :         struct ifreq ifr;
     228                 :            :         struct sockaddr_ll addr;
     229                 :            : 
     230                 :          0 :         drv->sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
     231         [ #  # ]:          0 :         if (drv->sock < 0) {
     232                 :          0 :                 perror("socket[PF_PACKET,SOCK_RAW]");
     233                 :          0 :                 return -1;
     234                 :            :         }
     235                 :            : 
     236         [ #  # ]:          0 :         if (eloop_register_read_sock(drv->sock, handle_read, drv, NULL)) {
     237                 :          0 :                 printf("Could not register read socket\n");
     238                 :          0 :                 return -1;
     239                 :            :         }
     240                 :            : 
     241                 :          0 :         memset(&ifr, 0, sizeof(ifr));
     242                 :          0 :         snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%sap", drv->iface);
     243         [ #  # ]:          0 :         if (ioctl(drv->sock, SIOCGIFINDEX, &ifr) != 0) {
     244                 :          0 :                 perror("ioctl(SIOCGIFINDEX)");
     245                 :          0 :                 return -1;
     246                 :            :         }
     247                 :            : 
     248         [ #  # ]:          0 :         if (hostap_set_iface_flags(drv, 1)) {
     249                 :          0 :                 return -1;
     250                 :            :         }
     251                 :            : 
     252                 :          0 :         memset(&addr, 0, sizeof(addr));
     253                 :          0 :         addr.sll_family = AF_PACKET;
     254                 :          0 :         addr.sll_ifindex = ifr.ifr_ifindex;
     255                 :          0 :         wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
     256                 :            :                    addr.sll_ifindex);
     257                 :            : 
     258         [ #  # ]:          0 :         if (bind(drv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
     259                 :          0 :                 perror("bind");
     260                 :          0 :                 return -1;
     261                 :            :         }
     262                 :            : 
     263                 :          0 :         return linux_get_ifhwaddr(drv->sock, drv->iface, own_addr);
     264                 :            : }
     265                 :            : 
     266                 :            : 
     267                 :          0 : static int hostap_send_mlme(void *priv, const u8 *msg, size_t len, int noack)
     268                 :            : {
     269                 :          0 :         struct hostap_driver_data *drv = priv;
     270                 :          0 :         struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg;
     271                 :            :         int res;
     272                 :            : 
     273                 :            :         /* Request TX callback */
     274                 :          0 :         hdr->frame_control |= host_to_le16(BIT(1));
     275                 :          0 :         res = send(drv->sock, msg, len, 0);
     276                 :          0 :         hdr->frame_control &= ~host_to_le16(BIT(1));
     277                 :            : 
     278                 :          0 :         return res;
     279                 :            : }
     280                 :            : 
     281                 :            : 
     282                 :          0 : static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data,
     283                 :            :                              size_t data_len, int encrypt, const u8 *own_addr,
     284                 :            :                              u32 flags)
     285                 :            : {
     286                 :          0 :         struct hostap_driver_data *drv = priv;
     287                 :            :         struct ieee80211_hdr *hdr;
     288                 :            :         size_t len;
     289                 :            :         u8 *pos;
     290                 :            :         int res;
     291                 :            : 
     292                 :          0 :         len = sizeof(*hdr) + sizeof(rfc1042_header) + 2 + data_len;
     293                 :          0 :         hdr = os_zalloc(len);
     294         [ #  # ]:          0 :         if (hdr == NULL) {
     295                 :          0 :                 printf("malloc() failed for hostapd_send_data(len=%lu)\n",
     296                 :            :                        (unsigned long) len);
     297                 :          0 :                 return -1;
     298                 :            :         }
     299                 :            : 
     300                 :          0 :         hdr->frame_control =
     301                 :            :                 IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA);
     302                 :          0 :         hdr->frame_control |= host_to_le16(WLAN_FC_FROMDS);
     303         [ #  # ]:          0 :         if (encrypt)
     304                 :          0 :                 hdr->frame_control |= host_to_le16(WLAN_FC_ISWEP);
     305                 :          0 :         memcpy(hdr->IEEE80211_DA_FROMDS, addr, ETH_ALEN);
     306                 :          0 :         memcpy(hdr->IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
     307                 :          0 :         memcpy(hdr->IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
     308                 :            : 
     309                 :          0 :         pos = (u8 *) (hdr + 1);
     310                 :          0 :         memcpy(pos, rfc1042_header, sizeof(rfc1042_header));
     311                 :          0 :         pos += sizeof(rfc1042_header);
     312                 :          0 :         *((u16 *) pos) = htons(ETH_P_PAE);
     313                 :          0 :         pos += 2;
     314                 :          0 :         memcpy(pos, data, data_len);
     315                 :            : 
     316                 :          0 :         res = hostap_send_mlme(drv, (u8 *) hdr, len, 0);
     317         [ #  # ]:          0 :         if (res < 0) {
     318                 :          0 :                 wpa_printf(MSG_ERROR, "hostap_send_eapol - packet len: %lu - "
     319                 :            :                            "failed: %d (%s)",
     320                 :          0 :                            (unsigned long) len, errno, strerror(errno));
     321                 :            :         }
     322                 :          0 :         free(hdr);
     323                 :            : 
     324                 :          0 :         return res;
     325                 :            : }
     326                 :            : 
     327                 :            : 
     328                 :          0 : static int hostap_sta_set_flags(void *priv, const u8 *addr,
     329                 :            :                                 int total_flags, int flags_or, int flags_and)
     330                 :            : {
     331                 :          0 :         struct hostap_driver_data *drv = priv;
     332                 :            :         struct prism2_hostapd_param param;
     333                 :            : 
     334         [ #  # ]:          0 :         if (flags_or & WPA_STA_AUTHORIZED)
     335                 :          0 :                 flags_or = BIT(5); /* WLAN_STA_AUTHORIZED */
     336         [ #  # ]:          0 :         if (!(flags_and & WPA_STA_AUTHORIZED))
     337                 :          0 :                 flags_and = ~BIT(5);
     338                 :            :         else
     339                 :          0 :                 flags_and = ~0;
     340                 :          0 :         memset(&param, 0, sizeof(param));
     341                 :          0 :         param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA;
     342                 :          0 :         memcpy(param.sta_addr, addr, ETH_ALEN);
     343                 :          0 :         param.u.set_flags_sta.flags_or = flags_or;
     344                 :          0 :         param.u.set_flags_sta.flags_and = flags_and;
     345                 :          0 :         return hostapd_ioctl(drv, &param, sizeof(param));
     346                 :            : }
     347                 :            : 
     348                 :            : 
     349                 :          0 : static int hostap_set_iface_flags(void *priv, int dev_up)
     350                 :            : {
     351                 :          0 :         struct hostap_driver_data *drv = priv;
     352                 :            :         struct ifreq ifr;
     353                 :            :         char ifname[IFNAMSIZ];
     354                 :            : 
     355                 :          0 :         os_snprintf(ifname, IFNAMSIZ, "%sap", drv->iface);
     356         [ #  # ]:          0 :         if (linux_set_iface_flags(drv->ioctl_sock, ifname, dev_up) < 0)
     357                 :          0 :                 return -1;
     358                 :            : 
     359         [ #  # ]:          0 :         if (dev_up) {
     360                 :          0 :                 memset(&ifr, 0, sizeof(ifr));
     361                 :          0 :                 os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
     362                 :          0 :                 ifr.ifr_mtu = HOSTAPD_MTU;
     363         [ #  # ]:          0 :                 if (ioctl(drv->ioctl_sock, SIOCSIFMTU, &ifr) != 0) {
     364                 :          0 :                         perror("ioctl[SIOCSIFMTU]");
     365                 :          0 :                         printf("Setting MTU failed - trying to survive with "
     366                 :            :                                "current value\n");
     367                 :            :                 }
     368                 :            :         }
     369                 :            : 
     370                 :          0 :         return 0;
     371                 :            : }
     372                 :            : 
     373                 :            : 
     374                 :          0 : static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param,
     375                 :            :                          int len)
     376                 :            : {
     377                 :          0 :         struct hostap_driver_data *drv = priv;
     378                 :            :         struct iwreq iwr;
     379                 :            : 
     380                 :          0 :         memset(&iwr, 0, sizeof(iwr));
     381                 :          0 :         os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
     382                 :          0 :         iwr.u.data.pointer = (caddr_t) param;
     383                 :          0 :         iwr.u.data.length = len;
     384                 :            : 
     385         [ #  # ]:          0 :         if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_HOSTAPD, &iwr) < 0) {
     386                 :          0 :                 perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
     387                 :          0 :                 return -1;
     388                 :            :         }
     389                 :            : 
     390                 :          0 :         return 0;
     391                 :            : }
     392                 :            : 
     393                 :            : 
     394                 :          0 : static int wpa_driver_hostap_set_key(const char *ifname, void *priv,
     395                 :            :                                      enum wpa_alg alg, const u8 *addr,
     396                 :            :                                      int key_idx, int set_tx,
     397                 :            :                                      const u8 *seq, size_t seq_len,
     398                 :            :                                      const u8 *key, size_t key_len)
     399                 :            : {
     400                 :          0 :         struct hostap_driver_data *drv = priv;
     401                 :            :         struct prism2_hostapd_param *param;
     402                 :            :         u8 *buf;
     403                 :            :         size_t blen;
     404                 :          0 :         int ret = 0;
     405                 :            : 
     406                 :          0 :         blen = sizeof(*param) + key_len;
     407                 :          0 :         buf = os_zalloc(blen);
     408         [ #  # ]:          0 :         if (buf == NULL)
     409                 :          0 :                 return -1;
     410                 :            : 
     411                 :          0 :         param = (struct prism2_hostapd_param *) buf;
     412                 :          0 :         param->cmd = PRISM2_SET_ENCRYPTION;
     413         [ #  # ]:          0 :         if (addr == NULL)
     414                 :          0 :                 memset(param->sta_addr, 0xff, ETH_ALEN);
     415                 :            :         else
     416                 :          0 :                 memcpy(param->sta_addr, addr, ETH_ALEN);
     417   [ #  #  #  #  :          0 :         switch (alg) {
                      # ]
     418                 :            :         case WPA_ALG_NONE:
     419                 :          0 :                 os_strlcpy((char *) param->u.crypt.alg, "NONE",
     420                 :            :                            HOSTAP_CRYPT_ALG_NAME_LEN);
     421                 :          0 :                 break;
     422                 :            :         case WPA_ALG_WEP:
     423                 :          0 :                 os_strlcpy((char *) param->u.crypt.alg, "WEP",
     424                 :            :                            HOSTAP_CRYPT_ALG_NAME_LEN);
     425                 :          0 :                 break;
     426                 :            :         case WPA_ALG_TKIP:
     427                 :          0 :                 os_strlcpy((char *) param->u.crypt.alg, "TKIP",
     428                 :            :                            HOSTAP_CRYPT_ALG_NAME_LEN);
     429                 :          0 :                 break;
     430                 :            :         case WPA_ALG_CCMP:
     431                 :          0 :                 os_strlcpy((char *) param->u.crypt.alg, "CCMP",
     432                 :            :                            HOSTAP_CRYPT_ALG_NAME_LEN);
     433                 :          0 :                 break;
     434                 :            :         default:
     435                 :          0 :                 os_free(buf);
     436                 :          0 :                 return -1;
     437                 :            :         }
     438                 :          0 :         param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0;
     439                 :          0 :         param->u.crypt.idx = key_idx;
     440                 :          0 :         param->u.crypt.key_len = key_len;
     441                 :          0 :         memcpy((u8 *) (param + 1), key, key_len);
     442                 :            : 
     443         [ #  # ]:          0 :         if (hostapd_ioctl(drv, param, blen)) {
     444                 :          0 :                 printf("Failed to set encryption.\n");
     445                 :          0 :                 ret = -1;
     446                 :            :         }
     447                 :          0 :         free(buf);
     448                 :            : 
     449                 :          0 :         return ret;
     450                 :            : }
     451                 :            : 
     452                 :            : 
     453                 :          0 : static int hostap_get_seqnum(const char *ifname, void *priv, const u8 *addr,
     454                 :            :                              int idx, u8 *seq)
     455                 :            : {
     456                 :          0 :         struct hostap_driver_data *drv = priv;
     457                 :            :         struct prism2_hostapd_param *param;
     458                 :            :         u8 *buf;
     459                 :            :         size_t blen;
     460                 :          0 :         int ret = 0;
     461                 :            : 
     462                 :          0 :         blen = sizeof(*param) + 32;
     463                 :          0 :         buf = os_zalloc(blen);
     464         [ #  # ]:          0 :         if (buf == NULL)
     465                 :          0 :                 return -1;
     466                 :            : 
     467                 :          0 :         param = (struct prism2_hostapd_param *) buf;
     468                 :          0 :         param->cmd = PRISM2_GET_ENCRYPTION;
     469         [ #  # ]:          0 :         if (addr == NULL)
     470                 :          0 :                 memset(param->sta_addr, 0xff, ETH_ALEN);
     471                 :            :         else
     472                 :          0 :                 memcpy(param->sta_addr, addr, ETH_ALEN);
     473                 :          0 :         param->u.crypt.idx = idx;
     474                 :            : 
     475         [ #  # ]:          0 :         if (hostapd_ioctl(drv, param, blen)) {
     476                 :          0 :                 printf("Failed to get encryption.\n");
     477                 :          0 :                 ret = -1;
     478                 :            :         } else {
     479                 :          0 :                 memcpy(seq, param->u.crypt.seq, 8);
     480                 :            :         }
     481                 :          0 :         free(buf);
     482                 :            : 
     483                 :          0 :         return ret;
     484                 :            : }
     485                 :            : 
     486                 :            : 
     487                 :          0 : static int hostap_ioctl_prism2param(void *priv, int param, int value)
     488                 :            : {
     489                 :          0 :         struct hostap_driver_data *drv = priv;
     490                 :            :         struct iwreq iwr;
     491                 :            :         int *i;
     492                 :            : 
     493                 :          0 :         memset(&iwr, 0, sizeof(iwr));
     494                 :          0 :         os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
     495                 :          0 :         i = (int *) iwr.u.name;
     496                 :          0 :         *i++ = param;
     497                 :          0 :         *i++ = value;
     498                 :            : 
     499         [ #  # ]:          0 :         if (ioctl(drv->ioctl_sock, PRISM2_IOCTL_PRISM2_PARAM, &iwr) < 0) {
     500                 :          0 :                 perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
     501                 :          0 :                 return -1;
     502                 :            :         }
     503                 :            : 
     504                 :          0 :         return 0;
     505                 :            : }
     506                 :            : 
     507                 :            : 
     508                 :          0 : static int hostap_set_ieee8021x(void *priv, struct wpa_bss_params *params)
     509                 :            : {
     510                 :          0 :         struct hostap_driver_data *drv = priv;
     511                 :          0 :         int enabled = params->enabled;
     512                 :            : 
     513                 :            :         /* enable kernel driver support for IEEE 802.1X */
     514         [ #  # ]:          0 :         if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_IEEE_802_1X, enabled)) {
     515                 :          0 :                 printf("Could not setup IEEE 802.1X support in kernel driver."
     516                 :            :                        "\n");
     517                 :          0 :                 return -1;
     518                 :            :         }
     519                 :            : 
     520         [ #  # ]:          0 :         if (!enabled)
     521                 :          0 :                 return 0;
     522                 :            : 
     523                 :            :         /* use host driver implementation of encryption to allow
     524                 :            :          * individual keys and passing plaintext EAPOL frames */
     525   [ #  #  #  # ]:          0 :         if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_DECRYPT, 1) ||
     526                 :          0 :             hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_ENCRYPT, 1)) {
     527                 :          0 :                 printf("Could not setup host-based encryption in kernel "
     528                 :            :                        "driver.\n");
     529                 :          0 :                 return -1;
     530                 :            :         }
     531                 :            : 
     532                 :          0 :         return 0;
     533                 :            : }
     534                 :            : 
     535                 :            : 
     536                 :          0 : static int hostap_set_privacy(void *priv, int enabled)
     537                 :            : {
     538                 :          0 :         struct hostap_drvier_data *drv = priv;
     539                 :            : 
     540                 :          0 :         return hostap_ioctl_prism2param(drv, PRISM2_PARAM_PRIVACY_INVOKED,
     541                 :            :                                         enabled);
     542                 :            : }
     543                 :            : 
     544                 :            : 
     545                 :          0 : static int hostap_set_ssid(void *priv, const u8 *buf, int len)
     546                 :            : {
     547                 :          0 :         struct hostap_driver_data *drv = priv;
     548                 :            :         struct iwreq iwr;
     549                 :            : 
     550                 :          0 :         memset(&iwr, 0, sizeof(iwr));
     551                 :          0 :         os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
     552                 :          0 :         iwr.u.essid.flags = 1; /* SSID active */
     553                 :          0 :         iwr.u.essid.pointer = (caddr_t) buf;
     554                 :          0 :         iwr.u.essid.length = len + 1;
     555                 :            : 
     556         [ #  # ]:          0 :         if (ioctl(drv->ioctl_sock, SIOCSIWESSID, &iwr) < 0) {
     557                 :          0 :                 perror("ioctl[SIOCSIWESSID]");
     558                 :          0 :                 printf("len=%d\n", len);
     559                 :          0 :                 return -1;
     560                 :            :         }
     561                 :            : 
     562                 :          0 :         return 0;
     563                 :            : }
     564                 :            : 
     565                 :            : 
     566                 :          0 : static int hostap_flush(void *priv)
     567                 :            : {
     568                 :          0 :         struct hostap_driver_data *drv = priv;
     569                 :            :         struct prism2_hostapd_param param;
     570                 :            : 
     571                 :          0 :         memset(&param, 0, sizeof(param));
     572                 :          0 :         param.cmd = PRISM2_HOSTAPD_FLUSH;
     573                 :          0 :         return hostapd_ioctl(drv, &param, sizeof(param));
     574                 :            : }
     575                 :            : 
     576                 :            : 
     577                 :          0 : static int hostap_read_sta_data(void *priv,
     578                 :            :                                 struct hostap_sta_driver_data *data,
     579                 :            :                                 const u8 *addr)
     580                 :            : {
     581                 :          0 :         struct hostap_driver_data *drv = priv;
     582                 :            :         char buf[1024], line[128], *pos;
     583                 :            :         FILE *f;
     584                 :            :         unsigned long val;
     585                 :            : 
     586                 :          0 :         memset(data, 0, sizeof(*data));
     587                 :          0 :         snprintf(buf, sizeof(buf), "/proc/net/hostap/%s/" MACSTR,
     588                 :          0 :                  drv->iface, MAC2STR(addr));
     589                 :            : 
     590                 :          0 :         f = fopen(buf, "r");
     591         [ #  # ]:          0 :         if (!f)
     592                 :          0 :                 return -1;
     593                 :            :         /* Need to read proc file with in one piece, so use large enough
     594                 :            :          * buffer. */
     595                 :          0 :         setbuffer(f, buf, sizeof(buf));
     596                 :            : 
     597         [ #  # ]:          0 :         while (fgets(line, sizeof(line), f)) {
     598                 :          0 :                 pos = strchr(line, '=');
     599         [ #  # ]:          0 :                 if (!pos)
     600                 :          0 :                         continue;
     601                 :          0 :                 *pos++ = '\0';
     602                 :          0 :                 val = strtoul(pos, NULL, 10);
     603         [ #  # ]:          0 :                 if (strcmp(line, "rx_packets") == 0)
     604                 :          0 :                         data->rx_packets = val;
     605         [ #  # ]:          0 :                 else if (strcmp(line, "tx_packets") == 0)
     606                 :          0 :                         data->tx_packets = val;
     607         [ #  # ]:          0 :                 else if (strcmp(line, "rx_bytes") == 0)
     608                 :          0 :                         data->rx_bytes = val;
     609         [ #  # ]:          0 :                 else if (strcmp(line, "tx_bytes") == 0)
     610                 :          0 :                         data->tx_bytes = val;
     611                 :            :         }
     612                 :            : 
     613                 :          0 :         fclose(f);
     614                 :            : 
     615                 :          0 :         return 0;
     616                 :            : }
     617                 :            : 
     618                 :            : 
     619                 :          0 : static int hostap_sta_add(void *priv, struct hostapd_sta_add_params *params)
     620                 :            : {
     621                 :          0 :         struct hostap_driver_data *drv = priv;
     622                 :            :         struct prism2_hostapd_param param;
     623                 :          0 :         int tx_supp_rates = 0;
     624                 :            :         size_t i;
     625                 :            : 
     626                 :            : #define WLAN_RATE_1M BIT(0)
     627                 :            : #define WLAN_RATE_2M BIT(1)
     628                 :            : #define WLAN_RATE_5M5 BIT(2)
     629                 :            : #define WLAN_RATE_11M BIT(3)
     630                 :            : 
     631         [ #  # ]:          0 :         for (i = 0; i < params->supp_rates_len; i++) {
     632         [ #  # ]:          0 :                 if ((params->supp_rates[i] & 0x7f) == 2)
     633                 :          0 :                         tx_supp_rates |= WLAN_RATE_1M;
     634         [ #  # ]:          0 :                 if ((params->supp_rates[i] & 0x7f) == 4)
     635                 :          0 :                         tx_supp_rates |= WLAN_RATE_2M;
     636         [ #  # ]:          0 :                 if ((params->supp_rates[i] & 0x7f) == 11)
     637                 :          0 :                         tx_supp_rates |= WLAN_RATE_5M5;
     638         [ #  # ]:          0 :                 if ((params->supp_rates[i] & 0x7f) == 22)
     639                 :          0 :                         tx_supp_rates |= WLAN_RATE_11M;
     640                 :            :         }
     641                 :            : 
     642                 :          0 :         memset(&param, 0, sizeof(param));
     643                 :          0 :         param.cmd = PRISM2_HOSTAPD_ADD_STA;
     644                 :          0 :         memcpy(param.sta_addr, params->addr, ETH_ALEN);
     645                 :          0 :         param.u.add_sta.aid = params->aid;
     646                 :          0 :         param.u.add_sta.capability = params->capability;
     647                 :          0 :         param.u.add_sta.tx_supp_rates = tx_supp_rates;
     648                 :          0 :         return hostapd_ioctl(drv, &param, sizeof(param));
     649                 :            : }
     650                 :            : 
     651                 :            : 
     652                 :          0 : static int hostap_sta_remove(void *priv, const u8 *addr)
     653                 :            : {
     654                 :          0 :         struct hostap_driver_data *drv = priv;
     655                 :            :         struct prism2_hostapd_param param;
     656                 :            : 
     657                 :          0 :         hostap_sta_set_flags(drv, addr, 0, 0, ~WPA_STA_AUTHORIZED);
     658                 :            : 
     659                 :          0 :         memset(&param, 0, sizeof(param));
     660                 :          0 :         param.cmd = PRISM2_HOSTAPD_REMOVE_STA;
     661                 :          0 :         memcpy(param.sta_addr, addr, ETH_ALEN);
     662         [ #  # ]:          0 :         if (hostapd_ioctl(drv, &param, sizeof(param))) {
     663                 :          0 :                 printf("Could not remove station from kernel driver.\n");
     664                 :          0 :                 return -1;
     665                 :            :         }
     666                 :          0 :         return 0;
     667                 :            : }
     668                 :            : 
     669                 :            : 
     670                 :          0 : static int hostap_get_inact_sec(void *priv, const u8 *addr)
     671                 :            : {
     672                 :          0 :         struct hostap_driver_data *drv = priv;
     673                 :            :         struct prism2_hostapd_param param;
     674                 :            : 
     675                 :          0 :         memset(&param, 0, sizeof(param));
     676                 :          0 :         param.cmd = PRISM2_HOSTAPD_GET_INFO_STA;
     677                 :          0 :         memcpy(param.sta_addr, addr, ETH_ALEN);
     678         [ #  # ]:          0 :         if (hostapd_ioctl(drv, &param, sizeof(param))) {
     679                 :          0 :                 return -1;
     680                 :            :         }
     681                 :            : 
     682                 :          0 :         return param.u.get_info_sta.inactive_sec;
     683                 :            : }
     684                 :            : 
     685                 :            : 
     686                 :          0 : static int hostap_sta_clear_stats(void *priv, const u8 *addr)
     687                 :            : {
     688                 :          0 :         struct hostap_driver_data *drv = priv;
     689                 :            :         struct prism2_hostapd_param param;
     690                 :            : 
     691                 :          0 :         memset(&param, 0, sizeof(param));
     692                 :          0 :         param.cmd = PRISM2_HOSTAPD_STA_CLEAR_STATS;
     693                 :          0 :         memcpy(param.sta_addr, addr, ETH_ALEN);
     694         [ #  # ]:          0 :         if (hostapd_ioctl(drv, &param, sizeof(param))) {
     695                 :          0 :                 return -1;
     696                 :            :         }
     697                 :            : 
     698                 :          0 :         return 0;
     699                 :            : }
     700                 :            : 
     701                 :            : 
     702                 :          0 : static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data *drv)
     703                 :            : {
     704                 :            :         struct prism2_hostapd_param *param;
     705                 :            :         int res;
     706                 :            :         size_t blen, elem_len;
     707                 :            : 
     708                 :          0 :         elem_len = drv->generic_ie_len + drv->wps_ie_len;
     709                 :          0 :         blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + elem_len;
     710         [ #  # ]:          0 :         if (blen < sizeof(*param))
     711                 :          0 :                 blen = sizeof(*param);
     712                 :            : 
     713                 :          0 :         param = os_zalloc(blen);
     714         [ #  # ]:          0 :         if (param == NULL)
     715                 :          0 :                 return -1;
     716                 :            : 
     717                 :          0 :         param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT;
     718                 :          0 :         param->u.generic_elem.len = elem_len;
     719         [ #  # ]:          0 :         if (drv->generic_ie) {
     720                 :          0 :                 os_memcpy(param->u.generic_elem.data, drv->generic_ie,
     721                 :            :                           drv->generic_ie_len);
     722                 :            :         }
     723         [ #  # ]:          0 :         if (drv->wps_ie) {
     724                 :          0 :                 os_memcpy(&param->u.generic_elem.data[drv->generic_ie_len],
     725                 :            :                           drv->wps_ie, drv->wps_ie_len);
     726                 :            :         }
     727                 :          0 :         wpa_hexdump(MSG_DEBUG, "hostap: Set generic IE",
     728                 :          0 :                     param->u.generic_elem.data, elem_len);
     729                 :          0 :         res = hostapd_ioctl(drv, param, blen);
     730                 :            : 
     731                 :          0 :         os_free(param);
     732                 :            : 
     733                 :          0 :         return res;
     734                 :            : }
     735                 :            : 
     736                 :            : 
     737                 :          0 : static int hostap_set_generic_elem(void *priv,
     738                 :            :                                    const u8 *elem, size_t elem_len)
     739                 :            : {
     740                 :          0 :         struct hostap_driver_data *drv = priv;
     741                 :            : 
     742                 :          0 :         os_free(drv->generic_ie);
     743                 :          0 :         drv->generic_ie = NULL;
     744                 :          0 :         drv->generic_ie_len = 0;
     745         [ #  # ]:          0 :         if (elem) {
     746                 :          0 :                 drv->generic_ie = os_malloc(elem_len);
     747         [ #  # ]:          0 :                 if (drv->generic_ie == NULL)
     748                 :          0 :                         return -1;
     749                 :          0 :                 os_memcpy(drv->generic_ie, elem, elem_len);
     750                 :          0 :                 drv->generic_ie_len = elem_len;
     751                 :            :         }
     752                 :            : 
     753                 :          0 :         return hostapd_ioctl_set_generic_elem(drv);
     754                 :            : }
     755                 :            : 
     756                 :            : 
     757                 :          0 : static int hostap_set_ap_wps_ie(void *priv, const struct wpabuf *beacon,
     758                 :            :                                 const struct wpabuf *proberesp,
     759                 :            :                                 const struct wpabuf *assocresp)
     760                 :            : {
     761                 :          0 :         struct hostap_driver_data *drv = priv;
     762                 :            : 
     763                 :            :         /*
     764                 :            :          * Host AP driver supports only one set of extra IEs, so we need to
     765                 :            :          * use the Probe Response IEs also for Beacon frames since they include
     766                 :            :          * more information.
     767                 :            :          */
     768                 :            : 
     769                 :          0 :         os_free(drv->wps_ie);
     770                 :          0 :         drv->wps_ie = NULL;
     771                 :          0 :         drv->wps_ie_len = 0;
     772         [ #  # ]:          0 :         if (proberesp) {
     773                 :          0 :                 drv->wps_ie = os_malloc(wpabuf_len(proberesp));
     774         [ #  # ]:          0 :                 if (drv->wps_ie == NULL)
     775                 :          0 :                         return -1;
     776                 :          0 :                 os_memcpy(drv->wps_ie, wpabuf_head(proberesp),
     777                 :            :                           wpabuf_len(proberesp));
     778                 :          0 :                 drv->wps_ie_len = wpabuf_len(proberesp);
     779                 :            :         }
     780                 :            : 
     781                 :          0 :         return hostapd_ioctl_set_generic_elem(drv);
     782                 :            : }
     783                 :            : 
     784                 :            : 
     785                 :            : static void
     786                 :          0 : hostapd_wireless_event_wireless_custom(struct hostap_driver_data *drv,
     787                 :            :                                        char *custom)
     788                 :            : {
     789                 :          0 :         wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom);
     790                 :            : 
     791         [ #  # ]:          0 :         if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
     792                 :            :                 char *pos;
     793                 :            :                 u8 addr[ETH_ALEN];
     794                 :          0 :                 pos = strstr(custom, "addr=");
     795         [ #  # ]:          0 :                 if (pos == NULL) {
     796                 :          0 :                         wpa_printf(MSG_DEBUG,
     797                 :            :                                    "MLME-MICHAELMICFAILURE.indication "
     798                 :            :                                    "without sender address ignored");
     799                 :          0 :                         return;
     800                 :            :                 }
     801                 :          0 :                 pos += 5;
     802         [ #  # ]:          0 :                 if (hwaddr_aton(pos, addr) == 0) {
     803                 :            :                         union wpa_event_data data;
     804                 :          0 :                         os_memset(&data, 0, sizeof(data));
     805                 :          0 :                         data.michael_mic_failure.unicast = 1;
     806                 :          0 :                         data.michael_mic_failure.src = addr;
     807                 :          0 :                         wpa_supplicant_event(drv->hapd,
     808                 :            :                                              EVENT_MICHAEL_MIC_FAILURE, &data);
     809                 :            :                 } else {
     810                 :          0 :                         wpa_printf(MSG_DEBUG,
     811                 :            :                                    "MLME-MICHAELMICFAILURE.indication "
     812                 :            :                                    "with invalid MAC address");
     813                 :            :                 }
     814                 :            :         }
     815                 :            : }
     816                 :            : 
     817                 :            : 
     818                 :          0 : static void hostapd_wireless_event_wireless(struct hostap_driver_data *drv,
     819                 :            :                                             char *data, int len)
     820                 :            : {
     821                 :          0 :         struct iw_event iwe_buf, *iwe = &iwe_buf;
     822                 :            :         char *pos, *end, *custom, *buf;
     823                 :            : 
     824                 :          0 :         pos = data;
     825                 :          0 :         end = data + len;
     826                 :            : 
     827         [ #  # ]:          0 :         while (pos + IW_EV_LCP_LEN <= end) {
     828                 :            :                 /* Event data may be unaligned, so make a local, aligned copy
     829                 :            :                  * before processing. */
     830                 :          0 :                 memcpy(&iwe_buf, pos, IW_EV_LCP_LEN);
     831                 :          0 :                 wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d",
     832                 :          0 :                            iwe->cmd, iwe->len);
     833         [ #  # ]:          0 :                 if (iwe->len <= IW_EV_LCP_LEN)
     834                 :          0 :                         return;
     835                 :            : 
     836                 :          0 :                 custom = pos + IW_EV_POINT_LEN;
     837 [ #  # ][ #  # ]:          0 :                 if (drv->we_version > 18 &&
     838         [ #  # ]:          0 :                     (iwe->cmd == IWEVMICHAELMICFAILURE ||
     839                 :          0 :                      iwe->cmd == IWEVCUSTOM)) {
     840                 :            :                         /* WE-19 removed the pointer from struct iw_point */
     841                 :          0 :                         char *dpos = (char *) &iwe_buf.u.data.length;
     842                 :          0 :                         int dlen = dpos - (char *) &iwe_buf;
     843                 :          0 :                         memcpy(dpos, pos + IW_EV_LCP_LEN,
     844                 :            :                                sizeof(struct iw_event) - dlen);
     845                 :            :                 } else {
     846                 :          0 :                         memcpy(&iwe_buf, pos, sizeof(struct iw_event));
     847                 :          0 :                         custom += IW_EV_POINT_OFF;
     848                 :            :                 }
     849                 :            : 
     850         [ #  # ]:          0 :                 switch (iwe->cmd) {
     851                 :            :                 case IWEVCUSTOM:
     852         [ #  # ]:          0 :                         if (custom + iwe->u.data.length > end)
     853                 :          0 :                                 return;
     854                 :          0 :                         buf = malloc(iwe->u.data.length + 1);
     855         [ #  # ]:          0 :                         if (buf == NULL)
     856                 :          0 :                                 return;
     857                 :          0 :                         memcpy(buf, custom, iwe->u.data.length);
     858                 :          0 :                         buf[iwe->u.data.length] = '\0';
     859                 :          0 :                         hostapd_wireless_event_wireless_custom(drv, buf);
     860                 :          0 :                         free(buf);
     861                 :          0 :                         break;
     862                 :            :                 }
     863                 :            : 
     864                 :          0 :                 pos += iwe->len;
     865                 :            :         }
     866                 :            : }
     867                 :            : 
     868                 :            : 
     869                 :          0 : static void hostapd_wireless_event_rtm_newlink(void *ctx,
     870                 :            :                                                struct ifinfomsg *ifi,
     871                 :            :                                                u8 *buf, size_t len)
     872                 :            : {
     873                 :          0 :         struct hostap_driver_data *drv = ctx;
     874                 :            :         int attrlen, rta_len;
     875                 :            :         struct rtattr *attr;
     876                 :            : 
     877                 :            :         /* TODO: use ifi->ifi_index to filter out wireless events from other
     878                 :            :          * interfaces */
     879                 :            : 
     880                 :          0 :         attrlen = len;
     881                 :          0 :         attr = (struct rtattr *) buf;
     882                 :            : 
     883                 :          0 :         rta_len = RTA_ALIGN(sizeof(struct rtattr));
     884 [ #  # ][ #  # ]:          0 :         while (RTA_OK(attr, attrlen)) {
                 [ #  # ]
     885         [ #  # ]:          0 :                 if (attr->rta_type == IFLA_WIRELESS) {
     886                 :          0 :                         hostapd_wireless_event_wireless(
     887                 :          0 :                                 drv, ((char *) attr) + rta_len,
     888                 :          0 :                                 attr->rta_len - rta_len);
     889                 :            :                 }
     890                 :          0 :                 attr = RTA_NEXT(attr, attrlen);
     891                 :            :         }
     892                 :          0 : }
     893                 :            : 
     894                 :            : 
     895                 :          0 : static int hostap_get_we_version(struct hostap_driver_data *drv)
     896                 :            : {
     897                 :            :         struct iw_range *range;
     898                 :            :         struct iwreq iwr;
     899                 :            :         int minlen;
     900                 :            :         size_t buflen;
     901                 :            : 
     902                 :          0 :         drv->we_version = 0;
     903                 :            : 
     904                 :            :         /*
     905                 :            :          * Use larger buffer than struct iw_range in order to allow the
     906                 :            :          * structure to grow in the future.
     907                 :            :          */
     908                 :          0 :         buflen = sizeof(struct iw_range) + 500;
     909                 :          0 :         range = os_zalloc(buflen);
     910         [ #  # ]:          0 :         if (range == NULL)
     911                 :          0 :                 return -1;
     912                 :            : 
     913                 :          0 :         memset(&iwr, 0, sizeof(iwr));
     914                 :          0 :         os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
     915                 :          0 :         iwr.u.data.pointer = (caddr_t) range;
     916                 :          0 :         iwr.u.data.length = buflen;
     917                 :            : 
     918                 :          0 :         minlen = ((char *) &range->enc_capa) - (char *) range +
     919                 :            :                 sizeof(range->enc_capa);
     920                 :            : 
     921         [ #  # ]:          0 :         if (ioctl(drv->ioctl_sock, SIOCGIWRANGE, &iwr) < 0) {
     922                 :          0 :                 perror("ioctl[SIOCGIWRANGE]");
     923                 :          0 :                 free(range);
     924                 :          0 :                 return -1;
     925 [ #  # ][ #  # ]:          0 :         } else if (iwr.u.data.length >= minlen &&
     926                 :          0 :                    range->we_version_compiled >= 18) {
     927                 :          0 :                 wpa_printf(MSG_DEBUG, "SIOCGIWRANGE: WE(compiled)=%d "
     928                 :            :                            "WE(source)=%d enc_capa=0x%x",
     929                 :          0 :                            range->we_version_compiled,
     930                 :          0 :                            range->we_version_source,
     931                 :            :                            range->enc_capa);
     932                 :          0 :                 drv->we_version = range->we_version_compiled;
     933                 :            :         }
     934                 :            : 
     935                 :          0 :         free(range);
     936                 :          0 :         return 0;
     937                 :            : }
     938                 :            : 
     939                 :            : 
     940                 :          0 : static int hostap_wireless_event_init(struct hostap_driver_data *drv)
     941                 :            : {
     942                 :            :         struct netlink_config *cfg;
     943                 :            : 
     944                 :          0 :         hostap_get_we_version(drv);
     945                 :            : 
     946                 :          0 :         cfg = os_zalloc(sizeof(*cfg));
     947         [ #  # ]:          0 :         if (cfg == NULL)
     948                 :          0 :                 return -1;
     949                 :          0 :         cfg->ctx = drv;
     950                 :          0 :         cfg->newlink_cb = hostapd_wireless_event_rtm_newlink;
     951                 :          0 :         drv->netlink = netlink_init(cfg);
     952         [ #  # ]:          0 :         if (drv->netlink == NULL) {
     953                 :          0 :                 os_free(cfg);
     954                 :          0 :                 return -1;
     955                 :            :         }
     956                 :            : 
     957                 :          0 :         return 0;
     958                 :            : }
     959                 :            : 
     960                 :            : 
     961                 :          0 : static void * hostap_init(struct hostapd_data *hapd,
     962                 :            :                           struct wpa_init_params *params)
     963                 :            : {
     964                 :            :         struct hostap_driver_data *drv;
     965                 :            : 
     966                 :          0 :         drv = os_zalloc(sizeof(struct hostap_driver_data));
     967         [ #  # ]:          0 :         if (drv == NULL) {
     968                 :          0 :                 printf("Could not allocate memory for hostapd driver data\n");
     969                 :          0 :                 return NULL;
     970                 :            :         }
     971                 :            : 
     972                 :          0 :         drv->hapd = hapd;
     973                 :          0 :         drv->ioctl_sock = drv->sock = -1;
     974                 :          0 :         memcpy(drv->iface, params->ifname, sizeof(drv->iface));
     975                 :            : 
     976                 :          0 :         drv->ioctl_sock = socket(PF_INET, SOCK_DGRAM, 0);
     977         [ #  # ]:          0 :         if (drv->ioctl_sock < 0) {
     978                 :          0 :                 perror("socket[PF_INET,SOCK_DGRAM]");
     979                 :          0 :                 free(drv);
     980                 :          0 :                 return NULL;
     981                 :            :         }
     982                 :            : 
     983         [ #  # ]:          0 :         if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 1)) {
     984                 :          0 :                 printf("Could not enable hostapd mode for interface %s\n",
     985                 :          0 :                        drv->iface);
     986                 :          0 :                 close(drv->ioctl_sock);
     987                 :          0 :                 free(drv);
     988                 :          0 :                 return NULL;
     989                 :            :         }
     990                 :            : 
     991   [ #  #  #  # ]:          0 :         if (hostap_init_sockets(drv, params->own_addr) ||
     992                 :          0 :             hostap_wireless_event_init(drv)) {
     993                 :          0 :                 close(drv->ioctl_sock);
     994                 :          0 :                 free(drv);
     995                 :          0 :                 return NULL;
     996                 :            :         }
     997                 :            : 
     998                 :          0 :         return drv;
     999                 :            : }
    1000                 :            : 
    1001                 :            : 
    1002                 :          0 : static void hostap_driver_deinit(void *priv)
    1003                 :            : {
    1004                 :          0 :         struct hostap_driver_data *drv = priv;
    1005                 :            : 
    1006                 :          0 :         netlink_deinit(drv->netlink);
    1007                 :          0 :         (void) hostap_set_iface_flags(drv, 0);
    1008                 :          0 :         (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 0);
    1009                 :          0 :         (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD_STA, 0);
    1010                 :            : 
    1011         [ #  # ]:          0 :         if (drv->ioctl_sock >= 0)
    1012                 :          0 :                 close(drv->ioctl_sock);
    1013                 :            : 
    1014         [ #  # ]:          0 :         if (drv->sock >= 0)
    1015                 :          0 :                 close(drv->sock);
    1016                 :            : 
    1017                 :          0 :         os_free(drv->generic_ie);
    1018                 :          0 :         os_free(drv->wps_ie);
    1019                 :            : 
    1020                 :          0 :         free(drv);
    1021                 :          0 : }
    1022                 :            : 
    1023                 :            : 
    1024                 :          0 : static int hostap_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr,
    1025                 :            :                              int reason)
    1026                 :            : {
    1027                 :          0 :         struct hostap_driver_data *drv = priv;
    1028                 :            :         struct ieee80211_mgmt mgmt;
    1029                 :            : 
    1030         [ #  # ]:          0 :         if (is_broadcast_ether_addr(addr)) {
    1031                 :            :                 /*
    1032                 :            :                  * New Prism2.5/3 STA firmware versions seem to have issues
    1033                 :            :                  * with this broadcast deauth frame. This gets the firmware in
    1034                 :            :                  * odd state where nothing works correctly, so let's skip
    1035                 :            :                  * sending this for the hostap driver.
    1036                 :            :                  */
    1037                 :          0 :                 return 0;
    1038                 :            :         }
    1039                 :            : 
    1040                 :          0 :         memset(&mgmt, 0, sizeof(mgmt));
    1041                 :          0 :         mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
    1042                 :            :                                           WLAN_FC_STYPE_DEAUTH);
    1043                 :          0 :         memcpy(mgmt.da, addr, ETH_ALEN);
    1044                 :          0 :         memcpy(mgmt.sa, own_addr, ETH_ALEN);
    1045                 :          0 :         memcpy(mgmt.bssid, own_addr, ETH_ALEN);
    1046                 :          0 :         mgmt.u.deauth.reason_code = host_to_le16(reason);
    1047                 :          0 :         return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN +
    1048                 :            :                                 sizeof(mgmt.u.deauth), 0);
    1049                 :            : }
    1050                 :            : 
    1051                 :            : 
    1052                 :          0 : static int hostap_set_freq(void *priv, struct hostapd_freq_params *freq)
    1053                 :            : {
    1054                 :          0 :         struct hostap_driver_data *drv = priv;
    1055                 :            :         struct iwreq iwr;
    1056                 :            : 
    1057                 :          0 :         os_memset(&iwr, 0, sizeof(iwr));
    1058                 :          0 :         os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ);
    1059                 :          0 :         iwr.u.freq.m = freq->channel;
    1060                 :          0 :         iwr.u.freq.e = 0;
    1061                 :            : 
    1062         [ #  # ]:          0 :         if (ioctl(drv->ioctl_sock, SIOCSIWFREQ, &iwr) < 0) {
    1063                 :          0 :                 perror("ioctl[SIOCSIWFREQ]");
    1064                 :          0 :                 return -1;
    1065                 :            :         }
    1066                 :            : 
    1067                 :          0 :         return 0;
    1068                 :            : }
    1069                 :            : 
    1070                 :            : 
    1071                 :          0 : static int hostap_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr,
    1072                 :            :                                int reason)
    1073                 :            : {
    1074                 :          0 :         struct hostap_driver_data *drv = priv;
    1075                 :            :         struct ieee80211_mgmt mgmt;
    1076                 :            : 
    1077                 :          0 :         memset(&mgmt, 0, sizeof(mgmt));
    1078                 :          0 :         mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
    1079                 :            :                                           WLAN_FC_STYPE_DISASSOC);
    1080                 :          0 :         memcpy(mgmt.da, addr, ETH_ALEN);
    1081                 :          0 :         memcpy(mgmt.sa, own_addr, ETH_ALEN);
    1082                 :          0 :         memcpy(mgmt.bssid, own_addr, ETH_ALEN);
    1083                 :          0 :         mgmt.u.disassoc.reason_code = host_to_le16(reason);
    1084                 :          0 :         return  hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN +
    1085                 :            :                                  sizeof(mgmt.u.disassoc), 0);
    1086                 :            : }
    1087                 :            : 
    1088                 :            : 
    1089                 :          0 : static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv,
    1090                 :            :                                                             u16 *num_modes,
    1091                 :            :                                                             u16 *flags)
    1092                 :            : {
    1093                 :            :         struct hostapd_hw_modes *mode;
    1094                 :            :         int i, clen, rlen;
    1095                 :          0 :         const short chan2freq[14] = {
    1096                 :            :                 2412, 2417, 2422, 2427, 2432, 2437, 2442,
    1097                 :            :                 2447, 2452, 2457, 2462, 2467, 2472, 2484
    1098                 :            :         };
    1099                 :            : 
    1100                 :          0 :         mode = os_zalloc(sizeof(struct hostapd_hw_modes));
    1101         [ #  # ]:          0 :         if (mode == NULL)
    1102                 :          0 :                 return NULL;
    1103                 :            : 
    1104                 :          0 :         *num_modes = 1;
    1105                 :          0 :         *flags = 0;
    1106                 :            : 
    1107                 :          0 :         mode->mode = HOSTAPD_MODE_IEEE80211B;
    1108                 :          0 :         mode->num_channels = 14;
    1109                 :          0 :         mode->num_rates = 4;
    1110                 :            : 
    1111                 :          0 :         clen = mode->num_channels * sizeof(struct hostapd_channel_data);
    1112                 :          0 :         rlen = mode->num_rates * sizeof(int);
    1113                 :            : 
    1114                 :          0 :         mode->channels = os_zalloc(clen);
    1115                 :          0 :         mode->rates = os_zalloc(rlen);
    1116 [ #  # ][ #  # ]:          0 :         if (mode->channels == NULL || mode->rates == NULL) {
    1117                 :          0 :                 os_free(mode->channels);
    1118                 :          0 :                 os_free(mode->rates);
    1119                 :          0 :                 os_free(mode);
    1120                 :          0 :                 return NULL;
    1121                 :            :         }
    1122                 :            : 
    1123         [ #  # ]:          0 :         for (i = 0; i < 14; i++) {
    1124                 :          0 :                 mode->channels[i].chan = i + 1;
    1125                 :          0 :                 mode->channels[i].freq = chan2freq[i];
    1126                 :            :                 /* TODO: Get allowed channel list from the driver */
    1127         [ #  # ]:          0 :                 if (i >= 11)
    1128                 :          0 :                         mode->channels[i].flag = HOSTAPD_CHAN_DISABLED;
    1129                 :            :         }
    1130                 :            : 
    1131                 :          0 :         mode->rates[0] = 10;
    1132                 :          0 :         mode->rates[1] = 20;
    1133                 :          0 :         mode->rates[2] = 55;
    1134                 :          0 :         mode->rates[3] = 110;
    1135                 :            : 
    1136                 :          0 :         return mode;
    1137                 :            : }
    1138                 :            : 
    1139                 :            : 
    1140                 :          0 : static void wpa_driver_hostap_poll_client(void *priv, const u8 *own_addr,
    1141                 :            :                                           const u8 *addr, int qos)
    1142                 :            : {
    1143                 :            :         struct ieee80211_hdr hdr;
    1144                 :            : 
    1145                 :          0 :         os_memset(&hdr, 0, sizeof(hdr));
    1146                 :            : 
    1147                 :            :         /*
    1148                 :            :          * WLAN_FC_STYPE_NULLFUNC would be more appropriate,
    1149                 :            :          * but it is apparently not retried so TX Exc events
    1150                 :            :          * are not received for it.
    1151                 :            :          * This is the reason the driver overrides the default
    1152                 :            :          * handling.
    1153                 :            :          */
    1154                 :          0 :         hdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA,
    1155                 :            :                                          WLAN_FC_STYPE_DATA);
    1156                 :            : 
    1157                 :          0 :         hdr.frame_control |=
    1158                 :            :                 host_to_le16(WLAN_FC_FROMDS);
    1159                 :          0 :         os_memcpy(hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN);
    1160                 :          0 :         os_memcpy(hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN);
    1161                 :          0 :         os_memcpy(hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN);
    1162                 :            : 
    1163                 :          0 :         hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr), 0);
    1164                 :          0 : }
    1165                 :            : 
    1166                 :            : 
    1167                 :            : const struct wpa_driver_ops wpa_driver_hostap_ops = {
    1168                 :            :         .name = "hostap",
    1169                 :            :         .desc = "Host AP driver (Intersil Prism2/2.5/3)",
    1170                 :            :         .set_key = wpa_driver_hostap_set_key,
    1171                 :            :         .hapd_init = hostap_init,
    1172                 :            :         .hapd_deinit = hostap_driver_deinit,
    1173                 :            :         .set_ieee8021x = hostap_set_ieee8021x,
    1174                 :            :         .set_privacy = hostap_set_privacy,
    1175                 :            :         .get_seqnum = hostap_get_seqnum,
    1176                 :            :         .flush = hostap_flush,
    1177                 :            :         .set_generic_elem = hostap_set_generic_elem,
    1178                 :            :         .read_sta_data = hostap_read_sta_data,
    1179                 :            :         .hapd_send_eapol = hostap_send_eapol,
    1180                 :            :         .sta_set_flags = hostap_sta_set_flags,
    1181                 :            :         .sta_deauth = hostap_sta_deauth,
    1182                 :            :         .sta_disassoc = hostap_sta_disassoc,
    1183                 :            :         .sta_remove = hostap_sta_remove,
    1184                 :            :         .hapd_set_ssid = hostap_set_ssid,
    1185                 :            :         .send_mlme = hostap_send_mlme,
    1186                 :            :         .sta_add = hostap_sta_add,
    1187                 :            :         .get_inact_sec = hostap_get_inact_sec,
    1188                 :            :         .sta_clear_stats = hostap_sta_clear_stats,
    1189                 :            :         .get_hw_feature_data = hostap_get_hw_feature_data,
    1190                 :            :         .set_ap_wps_ie = hostap_set_ap_wps_ie,
    1191                 :            :         .set_freq = hostap_set_freq,
    1192                 :            :         .poll_client = wpa_driver_hostap_poll_client,
    1193                 :            : };

Generated by: LCOV version 1.9