2 * Driver interaction with Linux Host AP driver
3 * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
16 #include <sys/ioctl.h>
18 #include "wireless_copy.h"
21 #include "driver_wext.h"
23 #include "driver_hostap.h"
28 #include <net/if_arp.h>
29 #include <netpacket/packet.h>
31 #include "priv_netlink.h"
33 #include "common/ieee802_11_defs.h"
36 /* MTU to be set for the wlan#ap device; this is mainly needed for IEEE 802.1X
37 * frames that might be longer than normal default MTU and they are not
39 #define HOSTAPD_MTU 2290
41 static const u8 rfc1042_header
[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
43 struct hostap_driver_data
{
44 struct hostapd_data
*hapd
;
46 char iface
[IFNAMSIZ
+ 1];
47 int sock
; /* raw packet socket for driver access */
48 int ioctl_sock
; /* socket for ioctl() use */
49 struct netlink_data
*netlink
;
54 size_t generic_ie_len
;
60 static int hostapd_ioctl(void *priv
, struct prism2_hostapd_param
*param
,
62 static int hostap_set_iface_flags(void *priv
, int dev_up
);
64 static void handle_data(struct hostap_driver_data
*drv
, u8
*buf
, size_t len
,
67 struct ieee80211_hdr
*hdr
;
71 union wpa_event_data event
;
73 if (len
< sizeof(struct ieee80211_hdr
))
76 hdr
= (struct ieee80211_hdr
*) buf
;
77 fc
= le_to_host16(hdr
->frame_control
);
79 if ((fc
& (WLAN_FC_FROMDS
| WLAN_FC_TODS
)) != WLAN_FC_TODS
) {
80 printf("Not ToDS data frame (fc=0x%04x)\n", fc
);
85 os_memset(&event
, 0, sizeof(event
));
86 event
.rx_from_unknown
.hdr
= hdr
;
87 event
.rx_from_unknown
.len
= len
;
88 wpa_supplicant_event(drv
->hapd
, EVENT_RX_FROM_UNKNOWN
, &event
);
90 pos
= (u8
*) (hdr
+ 1);
91 left
= len
- sizeof(*hdr
);
93 if (left
< sizeof(rfc1042_header
)) {
94 printf("Too short data frame\n");
98 if (memcmp(pos
, rfc1042_header
, sizeof(rfc1042_header
)) != 0) {
99 printf("Data frame with no RFC1042 header\n");
102 pos
+= sizeof(rfc1042_header
);
103 left
-= sizeof(rfc1042_header
);
106 printf("No ethertype in data frame\n");
110 ethertype
= WPA_GET_BE16(pos
);
115 hostapd_eapol_receive(drv
->hapd
, sa
, pos
, left
);
119 printf("Unknown ethertype 0x%04x in data frame\n", ethertype
);
125 static void handle_tx_callback(struct hostap_driver_data
*drv
, u8
*buf
,
128 struct ieee80211_hdr
*hdr
;
130 union wpa_event_data event
;
132 hdr
= (struct ieee80211_hdr
*) buf
;
133 fc
= le_to_host16(hdr
->frame_control
);
135 os_memset(&event
, 0, sizeof(event
));
136 event
.tx_status
.type
= WLAN_FC_GET_TYPE(fc
);
137 event
.tx_status
.stype
= WLAN_FC_GET_STYPE(fc
);
138 event
.tx_status
.dst
= hdr
->addr1
;
139 event
.tx_status
.data
= buf
;
140 event
.tx_status
.data_len
= len
;
141 event
.tx_status
.ack
= ok
;
142 wpa_supplicant_event(drv
->hapd
, EVENT_TX_STATUS
, &event
);
146 static void handle_frame(struct hostap_driver_data
*drv
, u8
*buf
, size_t len
)
148 struct ieee80211_hdr
*hdr
;
149 u16 fc
, extra_len
, type
, stype
;
150 unsigned char *extra
= NULL
;
151 size_t data_len
= len
;
153 union wpa_event_data event
;
155 /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass
156 * these to user space */
158 wpa_printf(MSG_MSGDUMP
, "handle_frame: too short (%lu)",
159 (unsigned long) len
);
163 hdr
= (struct ieee80211_hdr
*) buf
;
164 fc
= le_to_host16(hdr
->frame_control
);
165 type
= WLAN_FC_GET_TYPE(fc
);
166 stype
= WLAN_FC_GET_STYPE(fc
);
168 if (type
!= WLAN_FC_TYPE_MGMT
|| stype
!= WLAN_FC_STYPE_BEACON
) {
169 wpa_hexdump(MSG_MSGDUMP
, "Received management frame",
173 ver
= fc
& WLAN_FC_PVER
;
175 /* protocol version 3 is reserved for indicating extra data after the
176 * payload, version 2 for indicating ACKed frame (TX callbacks), and
177 * version 1 for indicating failed frame (no ACK, TX callbacks) */
179 u8
*pos
= buf
+ len
- 2;
180 extra_len
= WPA_GET_LE16(pos
);
181 printf("extra data in frame (elen=%d)\n", extra_len
);
182 if ((size_t) extra_len
+ 2 > len
) {
183 printf(" extra data overflow\n");
186 len
-= extra_len
+ 2;
188 } else if (ver
== 1 || ver
== 2) {
189 handle_tx_callback(drv
, buf
, data_len
, ver
== 2 ? 1 : 0);
191 } else if (ver
!= 0) {
192 printf("unknown protocol version %d\n", ver
);
197 case WLAN_FC_TYPE_MGMT
:
198 os_memset(&event
, 0, sizeof(event
));
199 event
.rx_mgmt
.frame
= buf
;
200 event
.rx_mgmt
.frame_len
= data_len
;
201 wpa_supplicant_event(drv
->hapd
, EVENT_RX_MGMT
, &event
);
203 case WLAN_FC_TYPE_CTRL
:
204 wpa_printf(MSG_DEBUG
, "CTRL");
206 case WLAN_FC_TYPE_DATA
:
207 wpa_printf(MSG_DEBUG
, "DATA");
208 handle_data(drv
, buf
, data_len
, stype
);
211 wpa_printf(MSG_DEBUG
, "unknown frame type %d", type
);
217 static void handle_read(int sock
, void *eloop_ctx
, void *sock_ctx
)
219 struct hostap_driver_data
*drv
= eloop_ctx
;
221 unsigned char buf
[3000];
223 len
= recv(sock
, buf
, sizeof(buf
), 0);
229 handle_frame(drv
, buf
, len
);
233 static int hostap_init_sockets(struct hostap_driver_data
*drv
, u8
*own_addr
)
236 struct sockaddr_ll addr
;
238 drv
->sock
= socket(PF_PACKET
, SOCK_RAW
, htons(ETH_P_ALL
));
240 perror("socket[PF_PACKET,SOCK_RAW]");
244 if (eloop_register_read_sock(drv
->sock
, handle_read
, drv
, NULL
)) {
245 printf("Could not register read socket\n");
249 memset(&ifr
, 0, sizeof(ifr
));
250 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%sap", drv
->iface
);
251 if (ioctl(drv
->sock
, SIOCGIFINDEX
, &ifr
) != 0) {
252 perror("ioctl(SIOCGIFINDEX)");
256 if (hostap_set_iface_flags(drv
, 1)) {
260 memset(&addr
, 0, sizeof(addr
));
261 addr
.sll_family
= AF_PACKET
;
262 addr
.sll_ifindex
= ifr
.ifr_ifindex
;
263 wpa_printf(MSG_DEBUG
, "Opening raw packet socket for ifindex %d",
266 if (bind(drv
->sock
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
271 memset(&ifr
, 0, sizeof(ifr
));
272 os_strlcpy(ifr
.ifr_name
, drv
->iface
, sizeof(ifr
.ifr_name
));
273 if (ioctl(drv
->sock
, SIOCGIFHWADDR
, &ifr
) != 0) {
274 perror("ioctl(SIOCGIFHWADDR)");
278 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) {
279 printf("Invalid HW-addr family 0x%04x\n",
280 ifr
.ifr_hwaddr
.sa_family
);
283 os_memcpy(own_addr
, ifr
.ifr_hwaddr
.sa_data
, ETH_ALEN
);
289 static int hostap_send_mlme(void *priv
, const u8
*msg
, size_t len
)
291 struct hostap_driver_data
*drv
= priv
;
292 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*) msg
;
295 /* Request TX callback */
296 hdr
->frame_control
|= host_to_le16(BIT(1));
297 res
= send(drv
->sock
, msg
, len
, 0);
298 hdr
->frame_control
&= ~host_to_le16(BIT(1));
304 static int hostap_send_eapol(void *priv
, const u8
*addr
, const u8
*data
,
305 size_t data_len
, int encrypt
, const u8
*own_addr
)
307 struct hostap_driver_data
*drv
= priv
;
308 struct ieee80211_hdr
*hdr
;
313 len
= sizeof(*hdr
) + sizeof(rfc1042_header
) + 2 + data_len
;
314 hdr
= os_zalloc(len
);
316 printf("malloc() failed for hostapd_send_data(len=%lu)\n",
317 (unsigned long) len
);
322 IEEE80211_FC(WLAN_FC_TYPE_DATA
, WLAN_FC_STYPE_DATA
);
323 hdr
->frame_control
|= host_to_le16(WLAN_FC_FROMDS
);
325 hdr
->frame_control
|= host_to_le16(WLAN_FC_ISWEP
);
326 memcpy(hdr
->IEEE80211_DA_FROMDS
, addr
, ETH_ALEN
);
327 memcpy(hdr
->IEEE80211_BSSID_FROMDS
, own_addr
, ETH_ALEN
);
328 memcpy(hdr
->IEEE80211_SA_FROMDS
, own_addr
, ETH_ALEN
);
330 pos
= (u8
*) (hdr
+ 1);
331 memcpy(pos
, rfc1042_header
, sizeof(rfc1042_header
));
332 pos
+= sizeof(rfc1042_header
);
333 *((u16
*) pos
) = htons(ETH_P_PAE
);
335 memcpy(pos
, data
, data_len
);
337 res
= hostap_send_mlme(drv
, (u8
*) hdr
, len
);
339 wpa_printf(MSG_ERROR
, "hostap_send_eapol - packet len: %lu - "
341 (unsigned long) len
, errno
, strerror(errno
));
349 static int hostap_sta_set_flags(void *priv
, const u8
*addr
,
350 int total_flags
, int flags_or
, int flags_and
)
352 struct hostap_driver_data
*drv
= priv
;
353 struct prism2_hostapd_param param
;
355 if (flags_or
& WPA_STA_AUTHORIZED
)
356 flags_or
= BIT(5); /* WLAN_STA_AUTHORIZED */
357 if (!(flags_and
& WPA_STA_AUTHORIZED
))
361 memset(¶m
, 0, sizeof(param
));
362 param
.cmd
= PRISM2_HOSTAPD_SET_FLAGS_STA
;
363 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
364 param
.u
.set_flags_sta
.flags_or
= flags_or
;
365 param
.u
.set_flags_sta
.flags_and
= flags_and
;
366 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
370 static int hostap_set_iface_flags(void *priv
, int dev_up
)
372 struct hostap_driver_data
*drv
= priv
;
375 if (drv
->ioctl_sock
< 0)
378 memset(&ifr
, 0, sizeof(ifr
));
379 snprintf(ifr
.ifr_name
, IFNAMSIZ
, "%sap", drv
->iface
);
381 if (ioctl(drv
->ioctl_sock
, SIOCGIFFLAGS
, &ifr
) != 0) {
382 perror("ioctl[SIOCGIFFLAGS]");
387 ifr
.ifr_flags
|= IFF_UP
;
389 ifr
.ifr_flags
&= ~IFF_UP
;
391 if (ioctl(drv
->ioctl_sock
, SIOCSIFFLAGS
, &ifr
) != 0) {
392 perror("ioctl[SIOCSIFFLAGS]");
397 memset(&ifr
, 0, sizeof(ifr
));
398 snprintf(ifr
.ifr_name
, IFNAMSIZ
, "%sap", drv
->iface
);
399 ifr
.ifr_mtu
= HOSTAPD_MTU
;
400 if (ioctl(drv
->ioctl_sock
, SIOCSIFMTU
, &ifr
) != 0) {
401 perror("ioctl[SIOCSIFMTU]");
402 printf("Setting MTU failed - trying to survive with "
411 static int hostapd_ioctl(void *priv
, struct prism2_hostapd_param
*param
,
414 struct hostap_driver_data
*drv
= priv
;
417 memset(&iwr
, 0, sizeof(iwr
));
418 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
419 iwr
.u
.data
.pointer
= (caddr_t
) param
;
420 iwr
.u
.data
.length
= len
;
422 if (ioctl(drv
->ioctl_sock
, PRISM2_IOCTL_HOSTAPD
, &iwr
) < 0) {
423 perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
431 static int wpa_driver_hostap_set_key(const char *ifname
, void *priv
,
432 enum wpa_alg alg
, const u8
*addr
,
433 int key_idx
, int set_tx
,
434 const u8
*seq
, size_t seq_len
,
435 const u8
*key
, size_t key_len
)
437 struct hostap_driver_data
*drv
= priv
;
438 struct prism2_hostapd_param
*param
;
443 blen
= sizeof(*param
) + key_len
;
444 buf
= os_zalloc(blen
);
448 param
= (struct prism2_hostapd_param
*) buf
;
449 param
->cmd
= PRISM2_SET_ENCRYPTION
;
451 memset(param
->sta_addr
, 0xff, ETH_ALEN
);
453 memcpy(param
->sta_addr
, addr
, ETH_ALEN
);
456 os_strlcpy((char *) param
->u
.crypt
.alg
, "NONE",
457 HOSTAP_CRYPT_ALG_NAME_LEN
);
460 os_strlcpy((char *) param
->u
.crypt
.alg
, "WEP",
461 HOSTAP_CRYPT_ALG_NAME_LEN
);
464 os_strlcpy((char *) param
->u
.crypt
.alg
, "TKIP",
465 HOSTAP_CRYPT_ALG_NAME_LEN
);
468 os_strlcpy((char *) param
->u
.crypt
.alg
, "CCMP",
469 HOSTAP_CRYPT_ALG_NAME_LEN
);
475 param
->u
.crypt
.flags
= set_tx
? HOSTAP_CRYPT_FLAG_SET_TX_KEY
: 0;
476 param
->u
.crypt
.idx
= key_idx
;
477 param
->u
.crypt
.key_len
= key_len
;
478 memcpy((u8
*) (param
+ 1), key
, key_len
);
480 if (hostapd_ioctl(drv
, param
, blen
)) {
481 printf("Failed to set encryption.\n");
490 static int hostap_get_seqnum(const char *ifname
, void *priv
, const u8
*addr
,
493 struct hostap_driver_data
*drv
= priv
;
494 struct prism2_hostapd_param
*param
;
499 blen
= sizeof(*param
) + 32;
500 buf
= os_zalloc(blen
);
504 param
= (struct prism2_hostapd_param
*) buf
;
505 param
->cmd
= PRISM2_GET_ENCRYPTION
;
507 memset(param
->sta_addr
, 0xff, ETH_ALEN
);
509 memcpy(param
->sta_addr
, addr
, ETH_ALEN
);
510 param
->u
.crypt
.idx
= idx
;
512 if (hostapd_ioctl(drv
, param
, blen
)) {
513 printf("Failed to get encryption.\n");
516 memcpy(seq
, param
->u
.crypt
.seq
, 8);
524 static int hostap_ioctl_prism2param(void *priv
, int param
, int value
)
526 struct hostap_driver_data
*drv
= priv
;
530 memset(&iwr
, 0, sizeof(iwr
));
531 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
532 i
= (int *) iwr
.u
.name
;
536 if (ioctl(drv
->ioctl_sock
, PRISM2_IOCTL_PRISM2_PARAM
, &iwr
) < 0) {
537 perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
545 static int hostap_set_ieee8021x(void *priv
, struct wpa_bss_params
*params
)
547 struct hostap_driver_data
*drv
= priv
;
548 int enabled
= params
->enabled
;
550 /* enable kernel driver support for IEEE 802.1X */
551 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_IEEE_802_1X
, enabled
)) {
552 printf("Could not setup IEEE 802.1X support in kernel driver."
560 /* use host driver implementation of encryption to allow
561 * individual keys and passing plaintext EAPOL frames */
562 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOST_DECRYPT
, 1) ||
563 hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOST_ENCRYPT
, 1)) {
564 printf("Could not setup host-based encryption in kernel "
573 static int hostap_set_privacy(const char *ifname
, void *priv
, int enabled
)
575 struct hostap_drvier_data
*drv
= priv
;
577 return hostap_ioctl_prism2param(drv
, PRISM2_PARAM_PRIVACY_INVOKED
,
582 static int hostap_set_ssid(const char *ifname
, void *priv
, const u8
*buf
,
585 struct hostap_driver_data
*drv
= priv
;
588 memset(&iwr
, 0, sizeof(iwr
));
589 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
590 iwr
.u
.essid
.flags
= 1; /* SSID active */
591 iwr
.u
.essid
.pointer
= (caddr_t
) buf
;
592 iwr
.u
.essid
.length
= len
+ 1;
594 if (ioctl(drv
->ioctl_sock
, SIOCSIWESSID
, &iwr
) < 0) {
595 perror("ioctl[SIOCSIWESSID]");
596 printf("len=%d\n", len
);
604 static int hostap_flush(void *priv
)
606 struct hostap_driver_data
*drv
= priv
;
607 struct prism2_hostapd_param param
;
609 memset(¶m
, 0, sizeof(param
));
610 param
.cmd
= PRISM2_HOSTAPD_FLUSH
;
611 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
615 static int hostap_read_sta_data(void *priv
,
616 struct hostap_sta_driver_data
*data
,
619 struct hostap_driver_data
*drv
= priv
;
620 char buf
[1024], line
[128], *pos
;
624 memset(data
, 0, sizeof(*data
));
625 snprintf(buf
, sizeof(buf
), "/proc/net/hostap/%s/" MACSTR
,
626 drv
->iface
, MAC2STR(addr
));
631 /* Need to read proc file with in one piece, so use large enough
633 setbuffer(f
, buf
, sizeof(buf
));
635 while (fgets(line
, sizeof(line
), f
)) {
636 pos
= strchr(line
, '=');
640 val
= strtoul(pos
, NULL
, 10);
641 if (strcmp(line
, "rx_packets") == 0)
642 data
->rx_packets
= val
;
643 else if (strcmp(line
, "tx_packets") == 0)
644 data
->tx_packets
= val
;
645 else if (strcmp(line
, "rx_bytes") == 0)
646 data
->rx_bytes
= val
;
647 else if (strcmp(line
, "tx_bytes") == 0)
648 data
->tx_bytes
= val
;
657 static int hostap_sta_add(const char *ifname
, void *priv
,
658 struct hostapd_sta_add_params
*params
)
660 struct hostap_driver_data
*drv
= priv
;
661 struct prism2_hostapd_param param
;
662 int tx_supp_rates
= 0;
665 #define WLAN_RATE_1M BIT(0)
666 #define WLAN_RATE_2M BIT(1)
667 #define WLAN_RATE_5M5 BIT(2)
668 #define WLAN_RATE_11M BIT(3)
670 for (i
= 0; i
< params
->supp_rates_len
; i
++) {
671 if ((params
->supp_rates
[i
] & 0x7f) == 2)
672 tx_supp_rates
|= WLAN_RATE_1M
;
673 if ((params
->supp_rates
[i
] & 0x7f) == 4)
674 tx_supp_rates
|= WLAN_RATE_2M
;
675 if ((params
->supp_rates
[i
] & 0x7f) == 11)
676 tx_supp_rates
|= WLAN_RATE_5M5
;
677 if ((params
->supp_rates
[i
] & 0x7f) == 22)
678 tx_supp_rates
|= WLAN_RATE_11M
;
681 memset(¶m
, 0, sizeof(param
));
682 param
.cmd
= PRISM2_HOSTAPD_ADD_STA
;
683 memcpy(param
.sta_addr
, params
->addr
, ETH_ALEN
);
684 param
.u
.add_sta
.aid
= params
->aid
;
685 param
.u
.add_sta
.capability
= params
->capability
;
686 param
.u
.add_sta
.tx_supp_rates
= tx_supp_rates
;
687 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
691 static int hostap_sta_remove(void *priv
, const u8
*addr
)
693 struct hostap_driver_data
*drv
= priv
;
694 struct prism2_hostapd_param param
;
696 hostap_sta_set_flags(drv
, addr
, 0, 0, ~WPA_STA_AUTHORIZED
);
698 memset(¶m
, 0, sizeof(param
));
699 param
.cmd
= PRISM2_HOSTAPD_REMOVE_STA
;
700 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
701 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
702 printf("Could not remove station from kernel driver.\n");
709 static int hostap_get_inact_sec(void *priv
, const u8
*addr
)
711 struct hostap_driver_data
*drv
= priv
;
712 struct prism2_hostapd_param param
;
714 memset(¶m
, 0, sizeof(param
));
715 param
.cmd
= PRISM2_HOSTAPD_GET_INFO_STA
;
716 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
717 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
721 return param
.u
.get_info_sta
.inactive_sec
;
725 static int hostap_sta_clear_stats(void *priv
, const u8
*addr
)
727 struct hostap_driver_data
*drv
= priv
;
728 struct prism2_hostapd_param param
;
730 memset(¶m
, 0, sizeof(param
));
731 param
.cmd
= PRISM2_HOSTAPD_STA_CLEAR_STATS
;
732 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
733 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
741 static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data
*drv
)
743 struct prism2_hostapd_param
*param
;
745 size_t blen
, elem_len
;
747 elem_len
= drv
->generic_ie_len
+ drv
->wps_ie_len
;
748 blen
= PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN
+ elem_len
;
749 if (blen
< sizeof(*param
))
750 blen
= sizeof(*param
);
752 param
= os_zalloc(blen
);
756 param
->cmd
= PRISM2_HOSTAPD_SET_GENERIC_ELEMENT
;
757 param
->u
.generic_elem
.len
= elem_len
;
758 if (drv
->generic_ie
) {
759 os_memcpy(param
->u
.generic_elem
.data
, drv
->generic_ie
,
760 drv
->generic_ie_len
);
763 os_memcpy(¶m
->u
.generic_elem
.data
[drv
->generic_ie_len
],
764 drv
->wps_ie
, drv
->wps_ie_len
);
766 wpa_hexdump(MSG_DEBUG
, "hostap: Set generic IE",
767 param
->u
.generic_elem
.data
, elem_len
);
768 res
= hostapd_ioctl(drv
, param
, blen
);
776 static int hostap_set_generic_elem(const char *ifname
, void *priv
,
777 const u8
*elem
, size_t elem_len
)
779 struct hostap_driver_data
*drv
= priv
;
781 os_free(drv
->generic_ie
);
782 drv
->generic_ie
= NULL
;
783 drv
->generic_ie_len
= 0;
785 drv
->generic_ie
= os_malloc(elem_len
);
786 if (drv
->generic_ie
== NULL
)
788 os_memcpy(drv
->generic_ie
, elem
, elem_len
);
789 drv
->generic_ie_len
= elem_len
;
792 return hostapd_ioctl_set_generic_elem(drv
);
796 static int hostap_set_ap_wps_ie(const char *ifname
, void *priv
,
797 const struct wpabuf
*beacon
,
798 const struct wpabuf
*proberesp
)
800 struct hostap_driver_data
*drv
= priv
;
803 * Host AP driver supports only one set of extra IEs, so we need to
804 * use the Probe Response IEs also for Beacon frames since they include
808 os_free(drv
->wps_ie
);
812 drv
->wps_ie
= os_malloc(wpabuf_len(proberesp
));
813 if (drv
->wps_ie
== NULL
)
815 os_memcpy(drv
->wps_ie
, wpabuf_head(proberesp
),
816 wpabuf_len(proberesp
));
817 drv
->wps_ie_len
= wpabuf_len(proberesp
);
820 return hostapd_ioctl_set_generic_elem(drv
);
825 hostapd_wireless_event_wireless_custom(struct hostap_driver_data
*drv
,
828 wpa_printf(MSG_DEBUG
, "Custom wireless event: '%s'", custom
);
830 if (strncmp(custom
, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
833 pos
= strstr(custom
, "addr=");
835 wpa_printf(MSG_DEBUG
,
836 "MLME-MICHAELMICFAILURE.indication "
837 "without sender address ignored");
841 if (hwaddr_aton(pos
, addr
) == 0) {
842 union wpa_event_data data
;
843 os_memset(&data
, 0, sizeof(data
));
844 data
.michael_mic_failure
.unicast
= 1;
845 data
.michael_mic_failure
.src
= addr
;
846 wpa_supplicant_event(drv
->hapd
,
847 EVENT_MICHAEL_MIC_FAILURE
, &data
);
849 wpa_printf(MSG_DEBUG
,
850 "MLME-MICHAELMICFAILURE.indication "
851 "with invalid MAC address");
857 static void hostapd_wireless_event_wireless(struct hostap_driver_data
*drv
,
860 struct iw_event iwe_buf
, *iwe
= &iwe_buf
;
861 char *pos
, *end
, *custom
, *buf
;
866 while (pos
+ IW_EV_LCP_LEN
<= end
) {
867 /* Event data may be unaligned, so make a local, aligned copy
868 * before processing. */
869 memcpy(&iwe_buf
, pos
, IW_EV_LCP_LEN
);
870 wpa_printf(MSG_DEBUG
, "Wireless event: cmd=0x%x len=%d",
872 if (iwe
->len
<= IW_EV_LCP_LEN
)
875 custom
= pos
+ IW_EV_POINT_LEN
;
876 if (drv
->we_version
> 18 &&
877 (iwe
->cmd
== IWEVMICHAELMICFAILURE
||
878 iwe
->cmd
== IWEVCUSTOM
)) {
879 /* WE-19 removed the pointer from struct iw_point */
880 char *dpos
= (char *) &iwe_buf
.u
.data
.length
;
881 int dlen
= dpos
- (char *) &iwe_buf
;
882 memcpy(dpos
, pos
+ IW_EV_LCP_LEN
,
883 sizeof(struct iw_event
) - dlen
);
885 memcpy(&iwe_buf
, pos
, sizeof(struct iw_event
));
886 custom
+= IW_EV_POINT_OFF
;
891 if (custom
+ iwe
->u
.data
.length
> end
)
893 buf
= malloc(iwe
->u
.data
.length
+ 1);
896 memcpy(buf
, custom
, iwe
->u
.data
.length
);
897 buf
[iwe
->u
.data
.length
] = '\0';
898 hostapd_wireless_event_wireless_custom(drv
, buf
);
908 static void hostapd_wireless_event_rtm_newlink(void *ctx
,
909 struct ifinfomsg
*ifi
,
912 struct hostap_driver_data
*drv
= ctx
;
913 int attrlen
, rta_len
;
916 /* TODO: use ifi->ifi_index to filter out wireless events from other
920 attr
= (struct rtattr
*) buf
;
922 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
923 while (RTA_OK(attr
, attrlen
)) {
924 if (attr
->rta_type
== IFLA_WIRELESS
) {
925 hostapd_wireless_event_wireless(
926 drv
, ((char *) attr
) + rta_len
,
927 attr
->rta_len
- rta_len
);
929 attr
= RTA_NEXT(attr
, attrlen
);
934 static int hostap_get_we_version(struct hostap_driver_data
*drv
)
936 struct iw_range
*range
;
944 * Use larger buffer than struct iw_range in order to allow the
945 * structure to grow in the future.
947 buflen
= sizeof(struct iw_range
) + 500;
948 range
= os_zalloc(buflen
);
952 memset(&iwr
, 0, sizeof(iwr
));
953 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
954 iwr
.u
.data
.pointer
= (caddr_t
) range
;
955 iwr
.u
.data
.length
= buflen
;
957 minlen
= ((char *) &range
->enc_capa
) - (char *) range
+
958 sizeof(range
->enc_capa
);
960 if (ioctl(drv
->ioctl_sock
, SIOCGIWRANGE
, &iwr
) < 0) {
961 perror("ioctl[SIOCGIWRANGE]");
964 } else if (iwr
.u
.data
.length
>= minlen
&&
965 range
->we_version_compiled
>= 18) {
966 wpa_printf(MSG_DEBUG
, "SIOCGIWRANGE: WE(compiled)=%d "
967 "WE(source)=%d enc_capa=0x%x",
968 range
->we_version_compiled
,
969 range
->we_version_source
,
971 drv
->we_version
= range
->we_version_compiled
;
979 static int hostap_wireless_event_init(struct hostap_driver_data
*drv
)
981 struct netlink_config
*cfg
;
983 hostap_get_we_version(drv
);
985 cfg
= os_zalloc(sizeof(*cfg
));
989 cfg
->newlink_cb
= hostapd_wireless_event_rtm_newlink
;
990 drv
->netlink
= netlink_init(cfg
);
991 if (drv
->netlink
== NULL
) {
1000 static void * hostap_init(struct hostapd_data
*hapd
,
1001 struct wpa_init_params
*params
)
1003 struct hostap_driver_data
*drv
;
1005 drv
= os_zalloc(sizeof(struct hostap_driver_data
));
1007 printf("Could not allocate memory for hostapd driver data\n");
1012 drv
->ioctl_sock
= drv
->sock
= -1;
1013 memcpy(drv
->iface
, params
->ifname
, sizeof(drv
->iface
));
1015 drv
->ioctl_sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
1016 if (drv
->ioctl_sock
< 0) {
1017 perror("socket[PF_INET,SOCK_DGRAM]");
1022 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD
, 1)) {
1023 printf("Could not enable hostapd mode for interface %s\n",
1025 close(drv
->ioctl_sock
);
1030 if (hostap_init_sockets(drv
, params
->own_addr
) ||
1031 hostap_wireless_event_init(drv
)) {
1032 close(drv
->ioctl_sock
);
1041 static void hostap_driver_deinit(void *priv
)
1043 struct hostap_driver_data
*drv
= priv
;
1045 netlink_deinit(drv
->netlink
);
1046 (void) hostap_set_iface_flags(drv
, 0);
1047 (void) hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD
, 0);
1048 (void) hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD_STA
, 0);
1050 if (drv
->ioctl_sock
>= 0)
1051 close(drv
->ioctl_sock
);
1056 os_free(drv
->generic_ie
);
1057 os_free(drv
->wps_ie
);
1063 static int hostap_sta_deauth(void *priv
, const u8
*own_addr
, const u8
*addr
,
1066 struct hostap_driver_data
*drv
= priv
;
1067 struct ieee80211_mgmt mgmt
;
1069 memset(&mgmt
, 0, sizeof(mgmt
));
1070 mgmt
.frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
1071 WLAN_FC_STYPE_DEAUTH
);
1072 memcpy(mgmt
.da
, addr
, ETH_ALEN
);
1073 memcpy(mgmt
.sa
, own_addr
, ETH_ALEN
);
1074 memcpy(mgmt
.bssid
, own_addr
, ETH_ALEN
);
1075 mgmt
.u
.deauth
.reason_code
= host_to_le16(reason
);
1076 return hostap_send_mlme(drv
, (u8
*) &mgmt
, IEEE80211_HDRLEN
+
1077 sizeof(mgmt
.u
.deauth
));
1081 static int hostap_sta_disassoc(void *priv
, const u8
*own_addr
, const u8
*addr
,
1084 struct hostap_driver_data
*drv
= priv
;
1085 struct ieee80211_mgmt mgmt
;
1087 memset(&mgmt
, 0, sizeof(mgmt
));
1088 mgmt
.frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
1089 WLAN_FC_STYPE_DISASSOC
);
1090 memcpy(mgmt
.da
, addr
, ETH_ALEN
);
1091 memcpy(mgmt
.sa
, own_addr
, ETH_ALEN
);
1092 memcpy(mgmt
.bssid
, own_addr
, ETH_ALEN
);
1093 mgmt
.u
.disassoc
.reason_code
= host_to_le16(reason
);
1094 return hostap_send_mlme(drv
, (u8
*) &mgmt
, IEEE80211_HDRLEN
+
1095 sizeof(mgmt
.u
.disassoc
));
1099 static struct hostapd_hw_modes
* hostap_get_hw_feature_data(void *priv
,
1103 struct hostapd_hw_modes
*mode
;
1105 const short chan2freq
[14] = {
1106 2412, 2417, 2422, 2427, 2432, 2437, 2442,
1107 2447, 2452, 2457, 2462, 2467, 2472, 2484
1110 mode
= os_zalloc(sizeof(struct hostapd_hw_modes
));
1117 mode
->mode
= HOSTAPD_MODE_IEEE80211B
;
1118 mode
->num_channels
= 14;
1119 mode
->num_rates
= 4;
1121 clen
= mode
->num_channels
* sizeof(struct hostapd_channel_data
);
1122 rlen
= mode
->num_rates
* sizeof(int);
1124 mode
->channels
= os_zalloc(clen
);
1125 mode
->rates
= os_zalloc(rlen
);
1126 if (mode
->channels
== NULL
|| mode
->rates
== NULL
) {
1127 os_free(mode
->channels
);
1128 os_free(mode
->rates
);
1133 for (i
= 0; i
< 14; i
++) {
1134 mode
->channels
[i
].chan
= i
+ 1;
1135 mode
->channels
[i
].freq
= chan2freq
[i
];
1136 /* TODO: Get allowed channel list from the driver */
1138 mode
->channels
[i
].flag
= HOSTAPD_CHAN_DISABLED
;
1141 mode
->rates
[0] = 10;
1142 mode
->rates
[1] = 20;
1143 mode
->rates
[2] = 55;
1144 mode
->rates
[3] = 110;
1151 struct wpa_driver_hostap_data
{
1152 void *wext
; /* private data for driver_wext */
1154 char ifname
[IFNAMSIZ
+ 1];
1156 int current_mode
; /* infra/adhoc */
1160 static int wpa_driver_hostap_set_auth_alg(void *priv
, int auth_alg
);
1163 static int hostapd_ioctl(struct wpa_driver_hostap_data
*drv
,
1164 struct prism2_hostapd_param
*param
,
1165 int len
, int show_err
)
1169 os_memset(&iwr
, 0, sizeof(iwr
));
1170 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1171 iwr
.u
.data
.pointer
= (caddr_t
) param
;
1172 iwr
.u
.data
.length
= len
;
1174 if (ioctl(drv
->sock
, PRISM2_IOCTL_HOSTAPD
, &iwr
) < 0) {
1177 perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
1185 static int wpa_driver_hostap_set_wpa_ie(struct wpa_driver_hostap_data
*drv
,
1186 const u8
*wpa_ie
, size_t wpa_ie_len
)
1188 struct prism2_hostapd_param
*param
;
1190 size_t blen
= PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN
+ wpa_ie_len
;
1191 if (blen
< sizeof(*param
))
1192 blen
= sizeof(*param
);
1194 param
= os_zalloc(blen
);
1198 param
->cmd
= PRISM2_HOSTAPD_SET_GENERIC_ELEMENT
;
1199 param
->u
.generic_elem
.len
= wpa_ie_len
;
1200 os_memcpy(param
->u
.generic_elem
.data
, wpa_ie
, wpa_ie_len
);
1201 res
= hostapd_ioctl(drv
, param
, blen
, 1);
1209 static int prism2param(struct wpa_driver_hostap_data
*drv
, int param
,
1215 os_memset(&iwr
, 0, sizeof(iwr
));
1216 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1217 i
= (int *) iwr
.u
.name
;
1221 if (ioctl(drv
->sock
, PRISM2_IOCTL_PRISM2_PARAM
, &iwr
) < 0) {
1222 perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
1229 static int wpa_driver_hostap_set_wpa(void *priv
, int enabled
)
1231 struct wpa_driver_hostap_data
*drv
= priv
;
1234 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __FUNCTION__
, enabled
);
1236 if (!enabled
&& wpa_driver_hostap_set_wpa_ie(drv
, NULL
, 0) < 0)
1238 if (prism2param(drv
, PRISM2_PARAM_HOST_ROAMING
, enabled
? 2 : 0) < 0)
1240 if (prism2param(drv
, PRISM2_PARAM_WPA
, enabled
) < 0)
1247 static void show_set_key_error(struct prism2_hostapd_param
*param
)
1249 switch (param
->u
.crypt
.err
) {
1250 case HOSTAP_CRYPT_ERR_UNKNOWN_ALG
:
1251 wpa_printf(MSG_INFO
, "Unknown algorithm '%s'.",
1252 param
->u
.crypt
.alg
);
1253 wpa_printf(MSG_INFO
, "You may need to load kernel module to "
1254 "register that algorithm.");
1255 wpa_printf(MSG_INFO
, "E.g., 'modprobe hostap_crypt_wep' for "
1258 case HOSTAP_CRYPT_ERR_UNKNOWN_ADDR
:
1259 wpa_printf(MSG_INFO
, "Unknown address " MACSTR
".",
1260 MAC2STR(param
->sta_addr
));
1262 case HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED
:
1263 wpa_printf(MSG_INFO
, "Crypt algorithm initialization failed.");
1265 case HOSTAP_CRYPT_ERR_KEY_SET_FAILED
:
1266 wpa_printf(MSG_INFO
, "Key setting failed.");
1268 case HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED
:
1269 wpa_printf(MSG_INFO
, "TX key index setting failed.");
1271 case HOSTAP_CRYPT_ERR_CARD_CONF_FAILED
:
1272 wpa_printf(MSG_INFO
, "Card configuration failed.");
1278 static int wpa_driver_hostap_set_key(const char *ifname
, void *priv
,
1279 enum wpa_alg alg
, const u8
*addr
,
1280 int key_idx
, int set_tx
,
1281 const u8
*seq
, size_t seq_len
,
1282 const u8
*key
, size_t key_len
)
1284 struct wpa_driver_hostap_data
*drv
= priv
;
1285 struct prism2_hostapd_param
*param
;
1308 wpa_printf(MSG_DEBUG
, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
1309 "key_len=%lu", __FUNCTION__
, alg_name
, key_idx
, set_tx
,
1310 (unsigned long) seq_len
, (unsigned long) key_len
);
1315 blen
= sizeof(*param
) + key_len
;
1316 buf
= os_zalloc(blen
);
1320 param
= (struct prism2_hostapd_param
*) buf
;
1321 param
->cmd
= PRISM2_SET_ENCRYPTION
;
1322 /* TODO: In theory, STA in client mode can use five keys; four default
1323 * keys for receiving (with keyidx 0..3) and one individual key for
1324 * both transmitting and receiving (keyidx 0) _unicast_ packets. Now,
1325 * keyidx 0 is reserved for this unicast use and default keys can only
1326 * use keyidx 1..3 (i.e., default key with keyidx 0 is not supported).
1327 * This should be fine for more or less all cases, but for completeness
1328 * sake, the driver could be enhanced to support the missing key. */
1331 os_memset(param
->sta_addr
, 0xff, ETH_ALEN
);
1333 os_memcpy(param
->sta_addr
, addr
, ETH_ALEN
);
1335 os_memset(param
->sta_addr
, 0xff, ETH_ALEN
);
1337 os_strlcpy((char *) param
->u
.crypt
.alg
, alg_name
,
1338 HOSTAP_CRYPT_ALG_NAME_LEN
);
1339 param
->u
.crypt
.flags
= set_tx
? HOSTAP_CRYPT_FLAG_SET_TX_KEY
: 0;
1340 param
->u
.crypt
.idx
= key_idx
;
1341 os_memcpy(param
->u
.crypt
.seq
, seq
, seq_len
);
1342 param
->u
.crypt
.key_len
= key_len
;
1343 os_memcpy((u8
*) (param
+ 1), key
, key_len
);
1345 if (hostapd_ioctl(drv
, param
, blen
, 1)) {
1346 wpa_printf(MSG_WARNING
, "Failed to set encryption.");
1347 show_set_key_error(param
);
1356 static int wpa_driver_hostap_set_countermeasures(void *priv
, int enabled
)
1358 struct wpa_driver_hostap_data
*drv
= priv
;
1359 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __FUNCTION__
, enabled
);
1360 return prism2param(drv
, PRISM2_PARAM_TKIP_COUNTERMEASURES
, enabled
);
1364 static int wpa_driver_hostap_reset(struct wpa_driver_hostap_data
*drv
,
1370 wpa_printf(MSG_DEBUG
, "%s: type=%d", __FUNCTION__
, type
);
1372 os_memset(&iwr
, 0, sizeof(iwr
));
1373 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1374 i
= (int *) iwr
.u
.name
;
1377 if (ioctl(drv
->sock
, PRISM2_IOCTL_RESET
, &iwr
) < 0) {
1378 perror("ioctl[PRISM2_IOCTL_RESET]");
1385 static int wpa_driver_hostap_mlme(struct wpa_driver_hostap_data
*drv
,
1386 const u8
*addr
, int cmd
, int reason_code
)
1388 struct prism2_hostapd_param param
;
1391 /* There does not seem to be a better way of deauthenticating or
1392 * disassociating with Prism2/2.5/3 than sending the management frame
1393 * and then resetting the Port0 to make sure both the AP and the STA
1394 * end up in disconnected state. */
1395 os_memset(¶m
, 0, sizeof(param
));
1396 param
.cmd
= PRISM2_HOSTAPD_MLME
;
1397 os_memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
1398 param
.u
.mlme
.cmd
= cmd
;
1399 param
.u
.mlme
.reason_code
= reason_code
;
1400 ret
= hostapd_ioctl(drv
, ¶m
, sizeof(param
), 1);
1402 os_sleep(0, 100000);
1403 ret
= wpa_driver_hostap_reset(drv
, 2);
1409 static int wpa_driver_hostap_deauthenticate(void *priv
, const u8
*addr
,
1412 struct wpa_driver_hostap_data
*drv
= priv
;
1413 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1414 return wpa_driver_hostap_mlme(drv
, addr
, MLME_STA_DEAUTH
,
1419 static int wpa_driver_hostap_disassociate(void *priv
, const u8
*addr
,
1422 struct wpa_driver_hostap_data
*drv
= priv
;
1423 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1424 return wpa_driver_hostap_mlme(drv
, addr
, MLME_STA_DISASSOC
,
1430 wpa_driver_hostap_associate(void *priv
,
1431 struct wpa_driver_associate_params
*params
)
1433 struct wpa_driver_hostap_data
*drv
= priv
;
1435 int allow_unencrypted_eapol
;
1437 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1439 if (prism2param(drv
, PRISM2_PARAM_DROP_UNENCRYPTED
,
1440 params
->drop_unencrypted
) < 0)
1442 if (wpa_driver_hostap_set_auth_alg(drv
, params
->auth_alg
) < 0)
1444 if (params
->mode
!= drv
->current_mode
) {
1445 /* At the moment, Host AP driver requires host_roaming=2 for
1446 * infrastructure mode and host_roaming=0 for adhoc. */
1447 if (prism2param(drv
, PRISM2_PARAM_HOST_ROAMING
,
1448 params
->mode
== IEEE80211_MODE_IBSS
? 0 : 2) <
1450 wpa_printf(MSG_DEBUG
, "%s: failed to set host_roaming",
1453 drv
->current_mode
= params
->mode
;
1456 if (prism2param(drv
, PRISM2_PARAM_PRIVACY_INVOKED
,
1457 params
->key_mgmt_suite
!= KEY_MGMT_NONE
) < 0)
1459 if (wpa_driver_hostap_set_wpa_ie(drv
, params
->wpa_ie
,
1460 params
->wpa_ie_len
) < 0)
1462 if (wpa_driver_wext_set_mode(drv
->wext
, params
->mode
) < 0)
1465 wpa_driver_wext_set_freq(drv
->wext
, params
->freq
) < 0)
1467 if (wpa_driver_wext_set_ssid(drv
->wext
, params
->ssid
, params
->ssid_len
)
1470 if (wpa_driver_wext_set_bssid(drv
->wext
, params
->bssid
) < 0)
1473 /* Allow unencrypted EAPOL messages even if pairwise keys are set when
1474 * not using WPA. IEEE 802.1X specifies that these frames are not
1475 * encrypted, but WPA encrypts them when pairwise keys are in use. */
1476 if (params
->key_mgmt_suite
== KEY_MGMT_802_1X
||
1477 params
->key_mgmt_suite
== KEY_MGMT_PSK
)
1478 allow_unencrypted_eapol
= 0;
1480 allow_unencrypted_eapol
= 1;
1482 if (prism2param(drv
, PRISM2_PARAM_IEEE_802_1X
,
1483 allow_unencrypted_eapol
) < 0) {
1484 wpa_printf(MSG_DEBUG
, "hostap: Failed to configure "
1485 "ieee_802_1x param");
1486 /* Ignore this error.. driver_hostap.c can also be used with
1487 * other drivers that do not support this prism2_param. */
1494 static int wpa_driver_hostap_scan(void *priv
,
1495 struct wpa_driver_scan_params
*params
)
1497 struct wpa_driver_hostap_data
*drv
= priv
;
1498 struct prism2_hostapd_param param
;
1500 const u8
*ssid
= params
->ssids
[0].ssid
;
1501 size_t ssid_len
= params
->ssids
[0].ssid_len
;
1504 /* Use standard Linux Wireless Extensions ioctl if possible
1505 * because some drivers using hostap code in wpa_supplicant
1506 * might not support Host AP specific scan request (with SSID
1508 return wpa_driver_wext_scan(drv
->wext
, params
);
1514 os_memset(¶m
, 0, sizeof(param
));
1515 param
.cmd
= PRISM2_HOSTAPD_SCAN_REQ
;
1516 param
.u
.scan_req
.ssid_len
= ssid_len
;
1517 os_memcpy(param
.u
.scan_req
.ssid
, ssid
, ssid_len
);
1518 ret
= hostapd_ioctl(drv
, ¶m
, sizeof(param
), 1);
1520 /* Not all drivers generate "scan completed" wireless event, so try to
1521 * read results after a timeout. */
1522 eloop_cancel_timeout(wpa_driver_wext_scan_timeout
, drv
->wext
,
1524 eloop_register_timeout(3, 0, wpa_driver_wext_scan_timeout
, drv
->wext
,
1531 static int wpa_driver_hostap_set_auth_alg(void *priv
, int auth_alg
)
1533 struct wpa_driver_hostap_data
*drv
= priv
;
1536 if (auth_alg
& AUTH_ALG_OPEN_SYSTEM
)
1538 if (auth_alg
& AUTH_ALG_SHARED_KEY
)
1540 if (auth_alg
& AUTH_ALG_LEAP
)
1543 algs
= 1; /* at least one algorithm should be set */
1545 return prism2param(drv
, PRISM2_PARAM_AP_AUTH_ALGS
, algs
);
1549 static int wpa_driver_hostap_get_bssid(void *priv
, u8
*bssid
)
1551 struct wpa_driver_hostap_data
*drv
= priv
;
1552 return wpa_driver_wext_get_bssid(drv
->wext
, bssid
);
1556 static int wpa_driver_hostap_get_ssid(void *priv
, u8
*ssid
)
1558 struct wpa_driver_hostap_data
*drv
= priv
;
1559 return wpa_driver_wext_get_ssid(drv
->wext
, ssid
);
1563 static struct wpa_scan_results
* wpa_driver_hostap_get_scan_results(void *priv
)
1565 struct wpa_driver_hostap_data
*drv
= priv
;
1566 return wpa_driver_wext_get_scan_results(drv
->wext
);
1570 static int wpa_driver_hostap_set_operstate(void *priv
, int state
)
1572 struct wpa_driver_hostap_data
*drv
= priv
;
1573 return wpa_driver_wext_set_operstate(drv
->wext
, state
);
1577 static void * wpa_driver_hostap_init(void *ctx
, const char *ifname
)
1579 struct wpa_driver_hostap_data
*drv
;
1581 drv
= os_zalloc(sizeof(*drv
));
1584 drv
->wext
= wpa_driver_wext_init(ctx
, ifname
);
1585 if (drv
->wext
== NULL
) {
1591 os_strlcpy(drv
->ifname
, ifname
, sizeof(drv
->ifname
));
1592 drv
->sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
1593 if (drv
->sock
< 0) {
1595 wpa_driver_wext_deinit(drv
->wext
);
1600 if (os_strncmp(ifname
, "wlan", 4) == 0) {
1602 * Host AP driver may use both wlan# and wifi# interface in
1605 char ifname2
[IFNAMSIZ
+ 1];
1606 os_strlcpy(ifname2
, ifname
, sizeof(ifname2
));
1607 os_memcpy(ifname2
, "wifi", 4);
1608 wpa_driver_wext_alternative_ifindex(drv
->wext
, ifname2
);
1611 wpa_driver_hostap_set_wpa(drv
, 1);
1617 static void wpa_driver_hostap_deinit(void *priv
)
1619 struct wpa_driver_hostap_data
*drv
= priv
;
1620 wpa_driver_hostap_set_wpa(drv
, 0);
1621 wpa_driver_wext_deinit(drv
->wext
);
1626 #endif /* HOSTAPD */
1629 const struct wpa_driver_ops wpa_driver_hostap_ops
= {
1631 .desc
= "Host AP driver (Intersil Prism2/2.5/3)",
1632 .set_key
= wpa_driver_hostap_set_key
,
1634 .hapd_init
= hostap_init
,
1635 .hapd_deinit
= hostap_driver_deinit
,
1636 .set_ieee8021x
= hostap_set_ieee8021x
,
1637 .set_privacy
= hostap_set_privacy
,
1638 .get_seqnum
= hostap_get_seqnum
,
1639 .flush
= hostap_flush
,
1640 .set_generic_elem
= hostap_set_generic_elem
,
1641 .read_sta_data
= hostap_read_sta_data
,
1642 .hapd_send_eapol
= hostap_send_eapol
,
1643 .sta_set_flags
= hostap_sta_set_flags
,
1644 .sta_deauth
= hostap_sta_deauth
,
1645 .sta_disassoc
= hostap_sta_disassoc
,
1646 .sta_remove
= hostap_sta_remove
,
1647 .hapd_set_ssid
= hostap_set_ssid
,
1648 .send_mlme
= hostap_send_mlme
,
1649 .sta_add
= hostap_sta_add
,
1650 .get_inact_sec
= hostap_get_inact_sec
,
1651 .sta_clear_stats
= hostap_sta_clear_stats
,
1652 .get_hw_feature_data
= hostap_get_hw_feature_data
,
1653 .set_ap_wps_ie
= hostap_set_ap_wps_ie
,
1655 .get_bssid
= wpa_driver_hostap_get_bssid
,
1656 .get_ssid
= wpa_driver_hostap_get_ssid
,
1657 .set_countermeasures
= wpa_driver_hostap_set_countermeasures
,
1658 .scan2
= wpa_driver_hostap_scan
,
1659 .get_scan_results2
= wpa_driver_hostap_get_scan_results
,
1660 .deauthenticate
= wpa_driver_hostap_deauthenticate
,
1661 .disassociate
= wpa_driver_hostap_disassociate
,
1662 .associate
= wpa_driver_hostap_associate
,
1663 .init
= wpa_driver_hostap_init
,
1664 .deinit
= wpa_driver_hostap_deinit
,
1665 .set_operstate
= wpa_driver_hostap_set_operstate
,
1666 #endif /* HOSTAPD */