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 "linux_ioctl.h"
34 #include "common/ieee802_11_defs.h"
37 /* MTU to be set for the wlan#ap device; this is mainly needed for IEEE 802.1X
38 * frames that might be longer than normal default MTU and they are not
40 #define HOSTAPD_MTU 2290
42 static const u8 rfc1042_header
[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
44 struct hostap_driver_data
{
45 struct hostapd_data
*hapd
;
47 char iface
[IFNAMSIZ
+ 1];
48 int sock
; /* raw packet socket for driver access */
49 int ioctl_sock
; /* socket for ioctl() use */
50 struct netlink_data
*netlink
;
55 size_t generic_ie_len
;
61 static int hostapd_ioctl(void *priv
, struct prism2_hostapd_param
*param
,
63 static int hostap_set_iface_flags(void *priv
, int dev_up
);
65 static void handle_data(struct hostap_driver_data
*drv
, u8
*buf
, size_t len
,
68 struct ieee80211_hdr
*hdr
;
72 union wpa_event_data event
;
74 if (len
< sizeof(struct ieee80211_hdr
))
77 hdr
= (struct ieee80211_hdr
*) buf
;
78 fc
= le_to_host16(hdr
->frame_control
);
80 if ((fc
& (WLAN_FC_FROMDS
| WLAN_FC_TODS
)) != WLAN_FC_TODS
) {
81 printf("Not ToDS data frame (fc=0x%04x)\n", fc
);
86 os_memset(&event
, 0, sizeof(event
));
87 event
.rx_from_unknown
.frame
= buf
;
88 event
.rx_from_unknown
.len
= len
;
89 wpa_supplicant_event(drv
->hapd
, EVENT_RX_FROM_UNKNOWN
, &event
);
91 pos
= (u8
*) (hdr
+ 1);
92 left
= len
- sizeof(*hdr
);
94 if (left
< sizeof(rfc1042_header
)) {
95 printf("Too short data frame\n");
99 if (memcmp(pos
, rfc1042_header
, sizeof(rfc1042_header
)) != 0) {
100 printf("Data frame with no RFC1042 header\n");
103 pos
+= sizeof(rfc1042_header
);
104 left
-= sizeof(rfc1042_header
);
107 printf("No ethertype in data frame\n");
111 ethertype
= WPA_GET_BE16(pos
);
116 drv_event_eapol_rx(drv
->hapd
, sa
, pos
, left
);
120 printf("Unknown ethertype 0x%04x in data frame\n", ethertype
);
126 static void handle_tx_callback(struct hostap_driver_data
*drv
, u8
*buf
,
129 struct ieee80211_hdr
*hdr
;
131 union wpa_event_data event
;
133 hdr
= (struct ieee80211_hdr
*) buf
;
134 fc
= le_to_host16(hdr
->frame_control
);
136 os_memset(&event
, 0, sizeof(event
));
137 event
.tx_status
.type
= WLAN_FC_GET_TYPE(fc
);
138 event
.tx_status
.stype
= WLAN_FC_GET_STYPE(fc
);
139 event
.tx_status
.dst
= hdr
->addr1
;
140 event
.tx_status
.data
= buf
;
141 event
.tx_status
.data_len
= len
;
142 event
.tx_status
.ack
= ok
;
143 wpa_supplicant_event(drv
->hapd
, EVENT_TX_STATUS
, &event
);
147 static void handle_frame(struct hostap_driver_data
*drv
, u8
*buf
, size_t len
)
149 struct ieee80211_hdr
*hdr
;
150 u16 fc
, extra_len
, type
, stype
;
151 unsigned char *extra
= NULL
;
152 size_t data_len
= len
;
154 union wpa_event_data event
;
156 /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass
157 * these to user space */
159 wpa_printf(MSG_MSGDUMP
, "handle_frame: too short (%lu)",
160 (unsigned long) len
);
164 hdr
= (struct ieee80211_hdr
*) buf
;
165 fc
= le_to_host16(hdr
->frame_control
);
166 type
= WLAN_FC_GET_TYPE(fc
);
167 stype
= WLAN_FC_GET_STYPE(fc
);
169 if (type
!= WLAN_FC_TYPE_MGMT
|| stype
!= WLAN_FC_STYPE_BEACON
) {
170 wpa_hexdump(MSG_MSGDUMP
, "Received management frame",
174 ver
= fc
& WLAN_FC_PVER
;
176 /* protocol version 3 is reserved for indicating extra data after the
177 * payload, version 2 for indicating ACKed frame (TX callbacks), and
178 * version 1 for indicating failed frame (no ACK, TX callbacks) */
180 u8
*pos
= buf
+ len
- 2;
181 extra_len
= WPA_GET_LE16(pos
);
182 printf("extra data in frame (elen=%d)\n", extra_len
);
183 if ((size_t) extra_len
+ 2 > len
) {
184 printf(" extra data overflow\n");
187 len
-= extra_len
+ 2;
189 } else if (ver
== 1 || ver
== 2) {
190 handle_tx_callback(drv
, buf
, data_len
, ver
== 2 ? 1 : 0);
192 } else if (ver
!= 0) {
193 printf("unknown protocol version %d\n", ver
);
198 case WLAN_FC_TYPE_MGMT
:
199 os_memset(&event
, 0, sizeof(event
));
200 event
.rx_mgmt
.frame
= buf
;
201 event
.rx_mgmt
.frame_len
= data_len
;
202 wpa_supplicant_event(drv
->hapd
, EVENT_RX_MGMT
, &event
);
204 case WLAN_FC_TYPE_CTRL
:
205 wpa_printf(MSG_DEBUG
, "CTRL");
207 case WLAN_FC_TYPE_DATA
:
208 wpa_printf(MSG_DEBUG
, "DATA");
209 handle_data(drv
, buf
, data_len
, stype
);
212 wpa_printf(MSG_DEBUG
, "unknown frame type %d", type
);
218 static void handle_read(int sock
, void *eloop_ctx
, void *sock_ctx
)
220 struct hostap_driver_data
*drv
= eloop_ctx
;
222 unsigned char buf
[3000];
224 len
= recv(sock
, buf
, sizeof(buf
), 0);
230 handle_frame(drv
, buf
, len
);
234 static int hostap_init_sockets(struct hostap_driver_data
*drv
, u8
*own_addr
)
237 struct sockaddr_ll addr
;
239 drv
->sock
= socket(PF_PACKET
, SOCK_RAW
, htons(ETH_P_ALL
));
241 perror("socket[PF_PACKET,SOCK_RAW]");
245 if (eloop_register_read_sock(drv
->sock
, handle_read
, drv
, NULL
)) {
246 printf("Could not register read socket\n");
250 memset(&ifr
, 0, sizeof(ifr
));
251 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%sap", drv
->iface
);
252 if (ioctl(drv
->sock
, SIOCGIFINDEX
, &ifr
) != 0) {
253 perror("ioctl(SIOCGIFINDEX)");
257 if (hostap_set_iface_flags(drv
, 1)) {
261 memset(&addr
, 0, sizeof(addr
));
262 addr
.sll_family
= AF_PACKET
;
263 addr
.sll_ifindex
= ifr
.ifr_ifindex
;
264 wpa_printf(MSG_DEBUG
, "Opening raw packet socket for ifindex %d",
267 if (bind(drv
->sock
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
272 return linux_get_ifhwaddr(drv
->sock
, drv
->iface
, own_addr
);
276 static int hostap_send_mlme(void *priv
, const u8
*msg
, size_t len
)
278 struct hostap_driver_data
*drv
= priv
;
279 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*) msg
;
282 /* Request TX callback */
283 hdr
->frame_control
|= host_to_le16(BIT(1));
284 res
= send(drv
->sock
, msg
, len
, 0);
285 hdr
->frame_control
&= ~host_to_le16(BIT(1));
291 static int hostap_send_eapol(void *priv
, const u8
*addr
, const u8
*data
,
292 size_t data_len
, int encrypt
, const u8
*own_addr
)
294 struct hostap_driver_data
*drv
= priv
;
295 struct ieee80211_hdr
*hdr
;
300 len
= sizeof(*hdr
) + sizeof(rfc1042_header
) + 2 + data_len
;
301 hdr
= os_zalloc(len
);
303 printf("malloc() failed for hostapd_send_data(len=%lu)\n",
304 (unsigned long) len
);
309 IEEE80211_FC(WLAN_FC_TYPE_DATA
, WLAN_FC_STYPE_DATA
);
310 hdr
->frame_control
|= host_to_le16(WLAN_FC_FROMDS
);
312 hdr
->frame_control
|= host_to_le16(WLAN_FC_ISWEP
);
313 memcpy(hdr
->IEEE80211_DA_FROMDS
, addr
, ETH_ALEN
);
314 memcpy(hdr
->IEEE80211_BSSID_FROMDS
, own_addr
, ETH_ALEN
);
315 memcpy(hdr
->IEEE80211_SA_FROMDS
, own_addr
, ETH_ALEN
);
317 pos
= (u8
*) (hdr
+ 1);
318 memcpy(pos
, rfc1042_header
, sizeof(rfc1042_header
));
319 pos
+= sizeof(rfc1042_header
);
320 *((u16
*) pos
) = htons(ETH_P_PAE
);
322 memcpy(pos
, data
, data_len
);
324 res
= hostap_send_mlme(drv
, (u8
*) hdr
, len
);
326 wpa_printf(MSG_ERROR
, "hostap_send_eapol - packet len: %lu - "
328 (unsigned long) len
, errno
, strerror(errno
));
336 static int hostap_sta_set_flags(void *priv
, const u8
*addr
,
337 int total_flags
, int flags_or
, int flags_and
)
339 struct hostap_driver_data
*drv
= priv
;
340 struct prism2_hostapd_param param
;
342 if (flags_or
& WPA_STA_AUTHORIZED
)
343 flags_or
= BIT(5); /* WLAN_STA_AUTHORIZED */
344 if (!(flags_and
& WPA_STA_AUTHORIZED
))
348 memset(¶m
, 0, sizeof(param
));
349 param
.cmd
= PRISM2_HOSTAPD_SET_FLAGS_STA
;
350 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
351 param
.u
.set_flags_sta
.flags_or
= flags_or
;
352 param
.u
.set_flags_sta
.flags_and
= flags_and
;
353 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
357 static int hostap_set_iface_flags(void *priv
, int dev_up
)
359 struct hostap_driver_data
*drv
= priv
;
361 char ifname
[IFNAMSIZ
];
363 os_snprintf(ifname
, IFNAMSIZ
, "%sap", drv
->iface
);
364 if (linux_set_iface_flags(drv
->ioctl_sock
, ifname
, dev_up
) < 0)
368 memset(&ifr
, 0, sizeof(ifr
));
369 os_strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
370 ifr
.ifr_mtu
= HOSTAPD_MTU
;
371 if (ioctl(drv
->ioctl_sock
, SIOCSIFMTU
, &ifr
) != 0) {
372 perror("ioctl[SIOCSIFMTU]");
373 printf("Setting MTU failed - trying to survive with "
382 static int hostapd_ioctl(void *priv
, struct prism2_hostapd_param
*param
,
385 struct hostap_driver_data
*drv
= priv
;
388 memset(&iwr
, 0, sizeof(iwr
));
389 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
390 iwr
.u
.data
.pointer
= (caddr_t
) param
;
391 iwr
.u
.data
.length
= len
;
393 if (ioctl(drv
->ioctl_sock
, PRISM2_IOCTL_HOSTAPD
, &iwr
) < 0) {
394 perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
402 static int wpa_driver_hostap_set_key(const char *ifname
, void *priv
,
403 enum wpa_alg alg
, const u8
*addr
,
404 int key_idx
, int set_tx
,
405 const u8
*seq
, size_t seq_len
,
406 const u8
*key
, size_t key_len
)
408 struct hostap_driver_data
*drv
= priv
;
409 struct prism2_hostapd_param
*param
;
414 blen
= sizeof(*param
) + key_len
;
415 buf
= os_zalloc(blen
);
419 param
= (struct prism2_hostapd_param
*) buf
;
420 param
->cmd
= PRISM2_SET_ENCRYPTION
;
422 memset(param
->sta_addr
, 0xff, ETH_ALEN
);
424 memcpy(param
->sta_addr
, addr
, ETH_ALEN
);
427 os_strlcpy((char *) param
->u
.crypt
.alg
, "NONE",
428 HOSTAP_CRYPT_ALG_NAME_LEN
);
431 os_strlcpy((char *) param
->u
.crypt
.alg
, "WEP",
432 HOSTAP_CRYPT_ALG_NAME_LEN
);
435 os_strlcpy((char *) param
->u
.crypt
.alg
, "TKIP",
436 HOSTAP_CRYPT_ALG_NAME_LEN
);
439 os_strlcpy((char *) param
->u
.crypt
.alg
, "CCMP",
440 HOSTAP_CRYPT_ALG_NAME_LEN
);
446 param
->u
.crypt
.flags
= set_tx
? HOSTAP_CRYPT_FLAG_SET_TX_KEY
: 0;
447 param
->u
.crypt
.idx
= key_idx
;
448 param
->u
.crypt
.key_len
= key_len
;
449 memcpy((u8
*) (param
+ 1), key
, key_len
);
451 if (hostapd_ioctl(drv
, param
, blen
)) {
452 printf("Failed to set encryption.\n");
461 static int hostap_get_seqnum(const char *ifname
, void *priv
, const u8
*addr
,
464 struct hostap_driver_data
*drv
= priv
;
465 struct prism2_hostapd_param
*param
;
470 blen
= sizeof(*param
) + 32;
471 buf
= os_zalloc(blen
);
475 param
= (struct prism2_hostapd_param
*) buf
;
476 param
->cmd
= PRISM2_GET_ENCRYPTION
;
478 memset(param
->sta_addr
, 0xff, ETH_ALEN
);
480 memcpy(param
->sta_addr
, addr
, ETH_ALEN
);
481 param
->u
.crypt
.idx
= idx
;
483 if (hostapd_ioctl(drv
, param
, blen
)) {
484 printf("Failed to get encryption.\n");
487 memcpy(seq
, param
->u
.crypt
.seq
, 8);
495 static int hostap_ioctl_prism2param(void *priv
, int param
, int value
)
497 struct hostap_driver_data
*drv
= priv
;
501 memset(&iwr
, 0, sizeof(iwr
));
502 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
503 i
= (int *) iwr
.u
.name
;
507 if (ioctl(drv
->ioctl_sock
, PRISM2_IOCTL_PRISM2_PARAM
, &iwr
) < 0) {
508 perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
516 static int hostap_set_ieee8021x(void *priv
, struct wpa_bss_params
*params
)
518 struct hostap_driver_data
*drv
= priv
;
519 int enabled
= params
->enabled
;
521 /* enable kernel driver support for IEEE 802.1X */
522 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_IEEE_802_1X
, enabled
)) {
523 printf("Could not setup IEEE 802.1X support in kernel driver."
531 /* use host driver implementation of encryption to allow
532 * individual keys and passing plaintext EAPOL frames */
533 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOST_DECRYPT
, 1) ||
534 hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOST_ENCRYPT
, 1)) {
535 printf("Could not setup host-based encryption in kernel "
544 static int hostap_set_privacy(void *priv
, int enabled
)
546 struct hostap_drvier_data
*drv
= priv
;
548 return hostap_ioctl_prism2param(drv
, PRISM2_PARAM_PRIVACY_INVOKED
,
553 static int hostap_set_ssid(void *priv
, const u8
*buf
, int len
)
555 struct hostap_driver_data
*drv
= priv
;
558 memset(&iwr
, 0, sizeof(iwr
));
559 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
560 iwr
.u
.essid
.flags
= 1; /* SSID active */
561 iwr
.u
.essid
.pointer
= (caddr_t
) buf
;
562 iwr
.u
.essid
.length
= len
+ 1;
564 if (ioctl(drv
->ioctl_sock
, SIOCSIWESSID
, &iwr
) < 0) {
565 perror("ioctl[SIOCSIWESSID]");
566 printf("len=%d\n", len
);
574 static int hostap_flush(void *priv
)
576 struct hostap_driver_data
*drv
= priv
;
577 struct prism2_hostapd_param param
;
579 memset(¶m
, 0, sizeof(param
));
580 param
.cmd
= PRISM2_HOSTAPD_FLUSH
;
581 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
585 static int hostap_read_sta_data(void *priv
,
586 struct hostap_sta_driver_data
*data
,
589 struct hostap_driver_data
*drv
= priv
;
590 char buf
[1024], line
[128], *pos
;
594 memset(data
, 0, sizeof(*data
));
595 snprintf(buf
, sizeof(buf
), "/proc/net/hostap/%s/" MACSTR
,
596 drv
->iface
, MAC2STR(addr
));
601 /* Need to read proc file with in one piece, so use large enough
603 setbuffer(f
, buf
, sizeof(buf
));
605 while (fgets(line
, sizeof(line
), f
)) {
606 pos
= strchr(line
, '=');
610 val
= strtoul(pos
, NULL
, 10);
611 if (strcmp(line
, "rx_packets") == 0)
612 data
->rx_packets
= val
;
613 else if (strcmp(line
, "tx_packets") == 0)
614 data
->tx_packets
= val
;
615 else if (strcmp(line
, "rx_bytes") == 0)
616 data
->rx_bytes
= val
;
617 else if (strcmp(line
, "tx_bytes") == 0)
618 data
->tx_bytes
= val
;
627 static int hostap_sta_add(void *priv
, struct hostapd_sta_add_params
*params
)
629 struct hostap_driver_data
*drv
= priv
;
630 struct prism2_hostapd_param param
;
631 int tx_supp_rates
= 0;
634 #define WLAN_RATE_1M BIT(0)
635 #define WLAN_RATE_2M BIT(1)
636 #define WLAN_RATE_5M5 BIT(2)
637 #define WLAN_RATE_11M BIT(3)
639 for (i
= 0; i
< params
->supp_rates_len
; i
++) {
640 if ((params
->supp_rates
[i
] & 0x7f) == 2)
641 tx_supp_rates
|= WLAN_RATE_1M
;
642 if ((params
->supp_rates
[i
] & 0x7f) == 4)
643 tx_supp_rates
|= WLAN_RATE_2M
;
644 if ((params
->supp_rates
[i
] & 0x7f) == 11)
645 tx_supp_rates
|= WLAN_RATE_5M5
;
646 if ((params
->supp_rates
[i
] & 0x7f) == 22)
647 tx_supp_rates
|= WLAN_RATE_11M
;
650 memset(¶m
, 0, sizeof(param
));
651 param
.cmd
= PRISM2_HOSTAPD_ADD_STA
;
652 memcpy(param
.sta_addr
, params
->addr
, ETH_ALEN
);
653 param
.u
.add_sta
.aid
= params
->aid
;
654 param
.u
.add_sta
.capability
= params
->capability
;
655 param
.u
.add_sta
.tx_supp_rates
= tx_supp_rates
;
656 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
660 static int hostap_sta_remove(void *priv
, const u8
*addr
)
662 struct hostap_driver_data
*drv
= priv
;
663 struct prism2_hostapd_param param
;
665 hostap_sta_set_flags(drv
, addr
, 0, 0, ~WPA_STA_AUTHORIZED
);
667 memset(¶m
, 0, sizeof(param
));
668 param
.cmd
= PRISM2_HOSTAPD_REMOVE_STA
;
669 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
670 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
671 printf("Could not remove station from kernel driver.\n");
678 static int hostap_get_inact_sec(void *priv
, const u8
*addr
)
680 struct hostap_driver_data
*drv
= priv
;
681 struct prism2_hostapd_param param
;
683 memset(¶m
, 0, sizeof(param
));
684 param
.cmd
= PRISM2_HOSTAPD_GET_INFO_STA
;
685 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
686 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
690 return param
.u
.get_info_sta
.inactive_sec
;
694 static int hostap_sta_clear_stats(void *priv
, const u8
*addr
)
696 struct hostap_driver_data
*drv
= priv
;
697 struct prism2_hostapd_param param
;
699 memset(¶m
, 0, sizeof(param
));
700 param
.cmd
= PRISM2_HOSTAPD_STA_CLEAR_STATS
;
701 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
702 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
710 static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data
*drv
)
712 struct prism2_hostapd_param
*param
;
714 size_t blen
, elem_len
;
716 elem_len
= drv
->generic_ie_len
+ drv
->wps_ie_len
;
717 blen
= PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN
+ elem_len
;
718 if (blen
< sizeof(*param
))
719 blen
= sizeof(*param
);
721 param
= os_zalloc(blen
);
725 param
->cmd
= PRISM2_HOSTAPD_SET_GENERIC_ELEMENT
;
726 param
->u
.generic_elem
.len
= elem_len
;
727 if (drv
->generic_ie
) {
728 os_memcpy(param
->u
.generic_elem
.data
, drv
->generic_ie
,
729 drv
->generic_ie_len
);
732 os_memcpy(¶m
->u
.generic_elem
.data
[drv
->generic_ie_len
],
733 drv
->wps_ie
, drv
->wps_ie_len
);
735 wpa_hexdump(MSG_DEBUG
, "hostap: Set generic IE",
736 param
->u
.generic_elem
.data
, elem_len
);
737 res
= hostapd_ioctl(drv
, param
, blen
);
745 static int hostap_set_generic_elem(void *priv
,
746 const u8
*elem
, size_t elem_len
)
748 struct hostap_driver_data
*drv
= priv
;
750 os_free(drv
->generic_ie
);
751 drv
->generic_ie
= NULL
;
752 drv
->generic_ie_len
= 0;
754 drv
->generic_ie
= os_malloc(elem_len
);
755 if (drv
->generic_ie
== NULL
)
757 os_memcpy(drv
->generic_ie
, elem
, elem_len
);
758 drv
->generic_ie_len
= elem_len
;
761 return hostapd_ioctl_set_generic_elem(drv
);
765 static int hostap_set_ap_wps_ie(void *priv
, const struct wpabuf
*beacon
,
766 const struct wpabuf
*proberesp
)
768 struct hostap_driver_data
*drv
= priv
;
771 * Host AP driver supports only one set of extra IEs, so we need to
772 * use the Probe Response IEs also for Beacon frames since they include
776 os_free(drv
->wps_ie
);
780 drv
->wps_ie
= os_malloc(wpabuf_len(proberesp
));
781 if (drv
->wps_ie
== NULL
)
783 os_memcpy(drv
->wps_ie
, wpabuf_head(proberesp
),
784 wpabuf_len(proberesp
));
785 drv
->wps_ie_len
= wpabuf_len(proberesp
);
788 return hostapd_ioctl_set_generic_elem(drv
);
793 hostapd_wireless_event_wireless_custom(struct hostap_driver_data
*drv
,
796 wpa_printf(MSG_DEBUG
, "Custom wireless event: '%s'", custom
);
798 if (strncmp(custom
, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
801 pos
= strstr(custom
, "addr=");
803 wpa_printf(MSG_DEBUG
,
804 "MLME-MICHAELMICFAILURE.indication "
805 "without sender address ignored");
809 if (hwaddr_aton(pos
, addr
) == 0) {
810 union wpa_event_data data
;
811 os_memset(&data
, 0, sizeof(data
));
812 data
.michael_mic_failure
.unicast
= 1;
813 data
.michael_mic_failure
.src
= addr
;
814 wpa_supplicant_event(drv
->hapd
,
815 EVENT_MICHAEL_MIC_FAILURE
, &data
);
817 wpa_printf(MSG_DEBUG
,
818 "MLME-MICHAELMICFAILURE.indication "
819 "with invalid MAC address");
825 static void hostapd_wireless_event_wireless(struct hostap_driver_data
*drv
,
828 struct iw_event iwe_buf
, *iwe
= &iwe_buf
;
829 char *pos
, *end
, *custom
, *buf
;
834 while (pos
+ IW_EV_LCP_LEN
<= end
) {
835 /* Event data may be unaligned, so make a local, aligned copy
836 * before processing. */
837 memcpy(&iwe_buf
, pos
, IW_EV_LCP_LEN
);
838 wpa_printf(MSG_DEBUG
, "Wireless event: cmd=0x%x len=%d",
840 if (iwe
->len
<= IW_EV_LCP_LEN
)
843 custom
= pos
+ IW_EV_POINT_LEN
;
844 if (drv
->we_version
> 18 &&
845 (iwe
->cmd
== IWEVMICHAELMICFAILURE
||
846 iwe
->cmd
== IWEVCUSTOM
)) {
847 /* WE-19 removed the pointer from struct iw_point */
848 char *dpos
= (char *) &iwe_buf
.u
.data
.length
;
849 int dlen
= dpos
- (char *) &iwe_buf
;
850 memcpy(dpos
, pos
+ IW_EV_LCP_LEN
,
851 sizeof(struct iw_event
) - dlen
);
853 memcpy(&iwe_buf
, pos
, sizeof(struct iw_event
));
854 custom
+= IW_EV_POINT_OFF
;
859 if (custom
+ iwe
->u
.data
.length
> end
)
861 buf
= malloc(iwe
->u
.data
.length
+ 1);
864 memcpy(buf
, custom
, iwe
->u
.data
.length
);
865 buf
[iwe
->u
.data
.length
] = '\0';
866 hostapd_wireless_event_wireless_custom(drv
, buf
);
876 static void hostapd_wireless_event_rtm_newlink(void *ctx
,
877 struct ifinfomsg
*ifi
,
880 struct hostap_driver_data
*drv
= ctx
;
881 int attrlen
, rta_len
;
884 /* TODO: use ifi->ifi_index to filter out wireless events from other
888 attr
= (struct rtattr
*) buf
;
890 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
891 while (RTA_OK(attr
, attrlen
)) {
892 if (attr
->rta_type
== IFLA_WIRELESS
) {
893 hostapd_wireless_event_wireless(
894 drv
, ((char *) attr
) + rta_len
,
895 attr
->rta_len
- rta_len
);
897 attr
= RTA_NEXT(attr
, attrlen
);
902 static int hostap_get_we_version(struct hostap_driver_data
*drv
)
904 struct iw_range
*range
;
912 * Use larger buffer than struct iw_range in order to allow the
913 * structure to grow in the future.
915 buflen
= sizeof(struct iw_range
) + 500;
916 range
= os_zalloc(buflen
);
920 memset(&iwr
, 0, sizeof(iwr
));
921 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
922 iwr
.u
.data
.pointer
= (caddr_t
) range
;
923 iwr
.u
.data
.length
= buflen
;
925 minlen
= ((char *) &range
->enc_capa
) - (char *) range
+
926 sizeof(range
->enc_capa
);
928 if (ioctl(drv
->ioctl_sock
, SIOCGIWRANGE
, &iwr
) < 0) {
929 perror("ioctl[SIOCGIWRANGE]");
932 } else if (iwr
.u
.data
.length
>= minlen
&&
933 range
->we_version_compiled
>= 18) {
934 wpa_printf(MSG_DEBUG
, "SIOCGIWRANGE: WE(compiled)=%d "
935 "WE(source)=%d enc_capa=0x%x",
936 range
->we_version_compiled
,
937 range
->we_version_source
,
939 drv
->we_version
= range
->we_version_compiled
;
947 static int hostap_wireless_event_init(struct hostap_driver_data
*drv
)
949 struct netlink_config
*cfg
;
951 hostap_get_we_version(drv
);
953 cfg
= os_zalloc(sizeof(*cfg
));
957 cfg
->newlink_cb
= hostapd_wireless_event_rtm_newlink
;
958 drv
->netlink
= netlink_init(cfg
);
959 if (drv
->netlink
== NULL
) {
968 static void * hostap_init(struct hostapd_data
*hapd
,
969 struct wpa_init_params
*params
)
971 struct hostap_driver_data
*drv
;
973 drv
= os_zalloc(sizeof(struct hostap_driver_data
));
975 printf("Could not allocate memory for hostapd driver data\n");
980 drv
->ioctl_sock
= drv
->sock
= -1;
981 memcpy(drv
->iface
, params
->ifname
, sizeof(drv
->iface
));
983 drv
->ioctl_sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
984 if (drv
->ioctl_sock
< 0) {
985 perror("socket[PF_INET,SOCK_DGRAM]");
990 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD
, 1)) {
991 printf("Could not enable hostapd mode for interface %s\n",
993 close(drv
->ioctl_sock
);
998 if (hostap_init_sockets(drv
, params
->own_addr
) ||
999 hostap_wireless_event_init(drv
)) {
1000 close(drv
->ioctl_sock
);
1009 static void hostap_driver_deinit(void *priv
)
1011 struct hostap_driver_data
*drv
= priv
;
1013 netlink_deinit(drv
->netlink
);
1014 (void) hostap_set_iface_flags(drv
, 0);
1015 (void) hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD
, 0);
1016 (void) hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD_STA
, 0);
1018 if (drv
->ioctl_sock
>= 0)
1019 close(drv
->ioctl_sock
);
1024 os_free(drv
->generic_ie
);
1025 os_free(drv
->wps_ie
);
1031 static int hostap_sta_deauth(void *priv
, const u8
*own_addr
, const u8
*addr
,
1034 struct hostap_driver_data
*drv
= priv
;
1035 struct ieee80211_mgmt mgmt
;
1037 memset(&mgmt
, 0, sizeof(mgmt
));
1038 mgmt
.frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
1039 WLAN_FC_STYPE_DEAUTH
);
1040 memcpy(mgmt
.da
, addr
, ETH_ALEN
);
1041 memcpy(mgmt
.sa
, own_addr
, ETH_ALEN
);
1042 memcpy(mgmt
.bssid
, own_addr
, ETH_ALEN
);
1043 mgmt
.u
.deauth
.reason_code
= host_to_le16(reason
);
1044 return hostap_send_mlme(drv
, (u8
*) &mgmt
, IEEE80211_HDRLEN
+
1045 sizeof(mgmt
.u
.deauth
));
1049 static int hostap_sta_disassoc(void *priv
, const u8
*own_addr
, const u8
*addr
,
1052 struct hostap_driver_data
*drv
= priv
;
1053 struct ieee80211_mgmt mgmt
;
1055 memset(&mgmt
, 0, sizeof(mgmt
));
1056 mgmt
.frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
1057 WLAN_FC_STYPE_DISASSOC
);
1058 memcpy(mgmt
.da
, addr
, ETH_ALEN
);
1059 memcpy(mgmt
.sa
, own_addr
, ETH_ALEN
);
1060 memcpy(mgmt
.bssid
, own_addr
, ETH_ALEN
);
1061 mgmt
.u
.disassoc
.reason_code
= host_to_le16(reason
);
1062 return hostap_send_mlme(drv
, (u8
*) &mgmt
, IEEE80211_HDRLEN
+
1063 sizeof(mgmt
.u
.disassoc
));
1067 static struct hostapd_hw_modes
* hostap_get_hw_feature_data(void *priv
,
1071 struct hostapd_hw_modes
*mode
;
1073 const short chan2freq
[14] = {
1074 2412, 2417, 2422, 2427, 2432, 2437, 2442,
1075 2447, 2452, 2457, 2462, 2467, 2472, 2484
1078 mode
= os_zalloc(sizeof(struct hostapd_hw_modes
));
1085 mode
->mode
= HOSTAPD_MODE_IEEE80211B
;
1086 mode
->num_channels
= 14;
1087 mode
->num_rates
= 4;
1089 clen
= mode
->num_channels
* sizeof(struct hostapd_channel_data
);
1090 rlen
= mode
->num_rates
* sizeof(int);
1092 mode
->channels
= os_zalloc(clen
);
1093 mode
->rates
= os_zalloc(rlen
);
1094 if (mode
->channels
== NULL
|| mode
->rates
== NULL
) {
1095 os_free(mode
->channels
);
1096 os_free(mode
->rates
);
1101 for (i
= 0; i
< 14; i
++) {
1102 mode
->channels
[i
].chan
= i
+ 1;
1103 mode
->channels
[i
].freq
= chan2freq
[i
];
1104 /* TODO: Get allowed channel list from the driver */
1106 mode
->channels
[i
].flag
= HOSTAPD_CHAN_DISABLED
;
1109 mode
->rates
[0] = 10;
1110 mode
->rates
[1] = 20;
1111 mode
->rates
[2] = 55;
1112 mode
->rates
[3] = 110;
1119 struct wpa_driver_hostap_data
{
1120 void *wext
; /* private data for driver_wext */
1122 char ifname
[IFNAMSIZ
+ 1];
1124 int current_mode
; /* infra/adhoc */
1128 static int wpa_driver_hostap_set_auth_alg(void *priv
, int auth_alg
);
1131 static int hostapd_ioctl(struct wpa_driver_hostap_data
*drv
,
1132 struct prism2_hostapd_param
*param
,
1133 int len
, int show_err
)
1137 os_memset(&iwr
, 0, sizeof(iwr
));
1138 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1139 iwr
.u
.data
.pointer
= (caddr_t
) param
;
1140 iwr
.u
.data
.length
= len
;
1142 if (ioctl(drv
->sock
, PRISM2_IOCTL_HOSTAPD
, &iwr
) < 0) {
1145 perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
1153 static int wpa_driver_hostap_set_wpa_ie(struct wpa_driver_hostap_data
*drv
,
1154 const u8
*wpa_ie
, size_t wpa_ie_len
)
1156 struct prism2_hostapd_param
*param
;
1158 size_t blen
= PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN
+ wpa_ie_len
;
1159 if (blen
< sizeof(*param
))
1160 blen
= sizeof(*param
);
1162 param
= os_zalloc(blen
);
1166 param
->cmd
= PRISM2_HOSTAPD_SET_GENERIC_ELEMENT
;
1167 param
->u
.generic_elem
.len
= wpa_ie_len
;
1168 os_memcpy(param
->u
.generic_elem
.data
, wpa_ie
, wpa_ie_len
);
1169 res
= hostapd_ioctl(drv
, param
, blen
, 1);
1177 static int prism2param(struct wpa_driver_hostap_data
*drv
, int param
,
1183 os_memset(&iwr
, 0, sizeof(iwr
));
1184 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1185 i
= (int *) iwr
.u
.name
;
1189 if (ioctl(drv
->sock
, PRISM2_IOCTL_PRISM2_PARAM
, &iwr
) < 0) {
1190 perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
1197 static int wpa_driver_hostap_set_wpa(void *priv
, int enabled
)
1199 struct wpa_driver_hostap_data
*drv
= priv
;
1202 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __FUNCTION__
, enabled
);
1204 if (!enabled
&& wpa_driver_hostap_set_wpa_ie(drv
, NULL
, 0) < 0)
1206 if (prism2param(drv
, PRISM2_PARAM_HOST_ROAMING
, enabled
? 2 : 0) < 0)
1208 if (prism2param(drv
, PRISM2_PARAM_WPA
, enabled
) < 0)
1215 static void show_set_key_error(struct prism2_hostapd_param
*param
)
1217 switch (param
->u
.crypt
.err
) {
1218 case HOSTAP_CRYPT_ERR_UNKNOWN_ALG
:
1219 wpa_printf(MSG_INFO
, "Unknown algorithm '%s'.",
1220 param
->u
.crypt
.alg
);
1221 wpa_printf(MSG_INFO
, "You may need to load kernel module to "
1222 "register that algorithm.");
1223 wpa_printf(MSG_INFO
, "E.g., 'modprobe hostap_crypt_wep' for "
1226 case HOSTAP_CRYPT_ERR_UNKNOWN_ADDR
:
1227 wpa_printf(MSG_INFO
, "Unknown address " MACSTR
".",
1228 MAC2STR(param
->sta_addr
));
1230 case HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED
:
1231 wpa_printf(MSG_INFO
, "Crypt algorithm initialization failed.");
1233 case HOSTAP_CRYPT_ERR_KEY_SET_FAILED
:
1234 wpa_printf(MSG_INFO
, "Key setting failed.");
1236 case HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED
:
1237 wpa_printf(MSG_INFO
, "TX key index setting failed.");
1239 case HOSTAP_CRYPT_ERR_CARD_CONF_FAILED
:
1240 wpa_printf(MSG_INFO
, "Card configuration failed.");
1246 static int wpa_driver_hostap_set_key(const char *ifname
, void *priv
,
1247 enum wpa_alg alg
, const u8
*addr
,
1248 int key_idx
, int set_tx
,
1249 const u8
*seq
, size_t seq_len
,
1250 const u8
*key
, size_t key_len
)
1252 struct wpa_driver_hostap_data
*drv
= priv
;
1253 struct prism2_hostapd_param
*param
;
1276 wpa_printf(MSG_DEBUG
, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
1277 "key_len=%lu", __FUNCTION__
, alg_name
, key_idx
, set_tx
,
1278 (unsigned long) seq_len
, (unsigned long) key_len
);
1283 blen
= sizeof(*param
) + key_len
;
1284 buf
= os_zalloc(blen
);
1288 param
= (struct prism2_hostapd_param
*) buf
;
1289 param
->cmd
= PRISM2_SET_ENCRYPTION
;
1290 /* TODO: In theory, STA in client mode can use five keys; four default
1291 * keys for receiving (with keyidx 0..3) and one individual key for
1292 * both transmitting and receiving (keyidx 0) _unicast_ packets. Now,
1293 * keyidx 0 is reserved for this unicast use and default keys can only
1294 * use keyidx 1..3 (i.e., default key with keyidx 0 is not supported).
1295 * This should be fine for more or less all cases, but for completeness
1296 * sake, the driver could be enhanced to support the missing key. */
1299 os_memset(param
->sta_addr
, 0xff, ETH_ALEN
);
1301 os_memcpy(param
->sta_addr
, addr
, ETH_ALEN
);
1303 os_memset(param
->sta_addr
, 0xff, ETH_ALEN
);
1305 os_strlcpy((char *) param
->u
.crypt
.alg
, alg_name
,
1306 HOSTAP_CRYPT_ALG_NAME_LEN
);
1307 param
->u
.crypt
.flags
= set_tx
? HOSTAP_CRYPT_FLAG_SET_TX_KEY
: 0;
1308 param
->u
.crypt
.idx
= key_idx
;
1309 os_memcpy(param
->u
.crypt
.seq
, seq
, seq_len
);
1310 param
->u
.crypt
.key_len
= key_len
;
1311 os_memcpy((u8
*) (param
+ 1), key
, key_len
);
1313 if (hostapd_ioctl(drv
, param
, blen
, 1)) {
1314 wpa_printf(MSG_WARNING
, "Failed to set encryption.");
1315 show_set_key_error(param
);
1324 static int wpa_driver_hostap_set_countermeasures(void *priv
, int enabled
)
1326 struct wpa_driver_hostap_data
*drv
= priv
;
1327 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __FUNCTION__
, enabled
);
1328 return prism2param(drv
, PRISM2_PARAM_TKIP_COUNTERMEASURES
, enabled
);
1332 static int wpa_driver_hostap_reset(struct wpa_driver_hostap_data
*drv
,
1338 wpa_printf(MSG_DEBUG
, "%s: type=%d", __FUNCTION__
, type
);
1340 os_memset(&iwr
, 0, sizeof(iwr
));
1341 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1342 i
= (int *) iwr
.u
.name
;
1345 if (ioctl(drv
->sock
, PRISM2_IOCTL_RESET
, &iwr
) < 0) {
1346 perror("ioctl[PRISM2_IOCTL_RESET]");
1353 static int wpa_driver_hostap_mlme(struct wpa_driver_hostap_data
*drv
,
1354 const u8
*addr
, int cmd
, int reason_code
)
1356 struct prism2_hostapd_param param
;
1359 /* There does not seem to be a better way of deauthenticating or
1360 * disassociating with Prism2/2.5/3 than sending the management frame
1361 * and then resetting the Port0 to make sure both the AP and the STA
1362 * end up in disconnected state. */
1363 os_memset(¶m
, 0, sizeof(param
));
1364 param
.cmd
= PRISM2_HOSTAPD_MLME
;
1365 os_memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
1366 param
.u
.mlme
.cmd
= cmd
;
1367 param
.u
.mlme
.reason_code
= reason_code
;
1368 ret
= hostapd_ioctl(drv
, ¶m
, sizeof(param
), 1);
1370 os_sleep(0, 100000);
1371 ret
= wpa_driver_hostap_reset(drv
, 2);
1377 static int wpa_driver_hostap_deauthenticate(void *priv
, const u8
*addr
,
1380 struct wpa_driver_hostap_data
*drv
= priv
;
1381 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1382 return wpa_driver_hostap_mlme(drv
, addr
, MLME_STA_DEAUTH
,
1387 static int wpa_driver_hostap_disassociate(void *priv
, const u8
*addr
,
1390 struct wpa_driver_hostap_data
*drv
= priv
;
1391 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1392 return wpa_driver_hostap_mlme(drv
, addr
, MLME_STA_DISASSOC
,
1398 wpa_driver_hostap_associate(void *priv
,
1399 struct wpa_driver_associate_params
*params
)
1401 struct wpa_driver_hostap_data
*drv
= priv
;
1403 int allow_unencrypted_eapol
;
1405 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1407 if (prism2param(drv
, PRISM2_PARAM_DROP_UNENCRYPTED
,
1408 params
->drop_unencrypted
) < 0)
1410 if (wpa_driver_hostap_set_auth_alg(drv
, params
->auth_alg
) < 0)
1412 if (params
->mode
!= drv
->current_mode
) {
1413 /* At the moment, Host AP driver requires host_roaming=2 for
1414 * infrastructure mode and host_roaming=0 for adhoc. */
1415 if (prism2param(drv
, PRISM2_PARAM_HOST_ROAMING
,
1416 params
->mode
== IEEE80211_MODE_IBSS
? 0 : 2) <
1418 wpa_printf(MSG_DEBUG
, "%s: failed to set host_roaming",
1421 drv
->current_mode
= params
->mode
;
1424 if (prism2param(drv
, PRISM2_PARAM_PRIVACY_INVOKED
,
1425 params
->key_mgmt_suite
!= KEY_MGMT_NONE
) < 0)
1427 if (wpa_driver_hostap_set_wpa_ie(drv
, params
->wpa_ie
,
1428 params
->wpa_ie_len
) < 0)
1430 if (wpa_driver_wext_set_mode(drv
->wext
, params
->mode
) < 0)
1433 wpa_driver_wext_set_freq(drv
->wext
, params
->freq
) < 0)
1435 if (wpa_driver_wext_set_ssid(drv
->wext
, params
->ssid
, params
->ssid_len
)
1438 if (wpa_driver_wext_set_bssid(drv
->wext
, params
->bssid
) < 0)
1441 /* Allow unencrypted EAPOL messages even if pairwise keys are set when
1442 * not using WPA. IEEE 802.1X specifies that these frames are not
1443 * encrypted, but WPA encrypts them when pairwise keys are in use. */
1444 if (params
->key_mgmt_suite
== KEY_MGMT_802_1X
||
1445 params
->key_mgmt_suite
== KEY_MGMT_PSK
)
1446 allow_unencrypted_eapol
= 0;
1448 allow_unencrypted_eapol
= 1;
1450 if (prism2param(drv
, PRISM2_PARAM_IEEE_802_1X
,
1451 allow_unencrypted_eapol
) < 0) {
1452 wpa_printf(MSG_DEBUG
, "hostap: Failed to configure "
1453 "ieee_802_1x param");
1454 /* Ignore this error.. driver_hostap.c can also be used with
1455 * other drivers that do not support this prism2_param. */
1462 static int wpa_driver_hostap_scan(void *priv
,
1463 struct wpa_driver_scan_params
*params
)
1465 struct wpa_driver_hostap_data
*drv
= priv
;
1466 struct prism2_hostapd_param param
;
1468 const u8
*ssid
= params
->ssids
[0].ssid
;
1469 size_t ssid_len
= params
->ssids
[0].ssid_len
;
1472 /* Use standard Linux Wireless Extensions ioctl if possible
1473 * because some drivers using hostap code in wpa_supplicant
1474 * might not support Host AP specific scan request (with SSID
1476 return wpa_driver_wext_scan(drv
->wext
, params
);
1482 os_memset(¶m
, 0, sizeof(param
));
1483 param
.cmd
= PRISM2_HOSTAPD_SCAN_REQ
;
1484 param
.u
.scan_req
.ssid_len
= ssid_len
;
1485 os_memcpy(param
.u
.scan_req
.ssid
, ssid
, ssid_len
);
1486 ret
= hostapd_ioctl(drv
, ¶m
, sizeof(param
), 1);
1488 /* Not all drivers generate "scan completed" wireless event, so try to
1489 * read results after a timeout. */
1490 eloop_cancel_timeout(wpa_driver_wext_scan_timeout
, drv
->wext
,
1492 eloop_register_timeout(3, 0, wpa_driver_wext_scan_timeout
, drv
->wext
,
1499 static int wpa_driver_hostap_set_auth_alg(void *priv
, int auth_alg
)
1501 struct wpa_driver_hostap_data
*drv
= priv
;
1504 if (auth_alg
& WPA_AUTH_ALG_OPEN
)
1506 if (auth_alg
& WPA_AUTH_ALG_SHARED
)
1508 if (auth_alg
& WPA_AUTH_ALG_LEAP
)
1511 algs
= 1; /* at least one algorithm should be set */
1513 return prism2param(drv
, PRISM2_PARAM_AP_AUTH_ALGS
, algs
);
1517 static int wpa_driver_hostap_get_bssid(void *priv
, u8
*bssid
)
1519 struct wpa_driver_hostap_data
*drv
= priv
;
1520 return wpa_driver_wext_get_bssid(drv
->wext
, bssid
);
1524 static int wpa_driver_hostap_get_ssid(void *priv
, u8
*ssid
)
1526 struct wpa_driver_hostap_data
*drv
= priv
;
1527 return wpa_driver_wext_get_ssid(drv
->wext
, ssid
);
1531 static struct wpa_scan_results
* wpa_driver_hostap_get_scan_results(void *priv
)
1533 struct wpa_driver_hostap_data
*drv
= priv
;
1534 return wpa_driver_wext_get_scan_results(drv
->wext
);
1538 static int wpa_driver_hostap_set_operstate(void *priv
, int state
)
1540 struct wpa_driver_hostap_data
*drv
= priv
;
1541 return wpa_driver_wext_set_operstate(drv
->wext
, state
);
1545 static void * wpa_driver_hostap_init(void *ctx
, const char *ifname
)
1547 struct wpa_driver_hostap_data
*drv
;
1549 drv
= os_zalloc(sizeof(*drv
));
1552 drv
->wext
= wpa_driver_wext_init(ctx
, ifname
);
1553 if (drv
->wext
== NULL
) {
1559 os_strlcpy(drv
->ifname
, ifname
, sizeof(drv
->ifname
));
1560 drv
->sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
1561 if (drv
->sock
< 0) {
1563 wpa_driver_wext_deinit(drv
->wext
);
1568 if (os_strncmp(ifname
, "wlan", 4) == 0) {
1570 * Host AP driver may use both wlan# and wifi# interface in
1573 char ifname2
[IFNAMSIZ
+ 1];
1574 os_strlcpy(ifname2
, ifname
, sizeof(ifname2
));
1575 os_memcpy(ifname2
, "wifi", 4);
1576 wpa_driver_wext_alternative_ifindex(drv
->wext
, ifname2
);
1579 wpa_driver_hostap_set_wpa(drv
, 1);
1585 static void wpa_driver_hostap_deinit(void *priv
)
1587 struct wpa_driver_hostap_data
*drv
= priv
;
1588 wpa_driver_hostap_set_wpa(drv
, 0);
1589 wpa_driver_wext_deinit(drv
->wext
);
1594 #endif /* HOSTAPD */
1597 const struct wpa_driver_ops wpa_driver_hostap_ops
= {
1599 .desc
= "Host AP driver (Intersil Prism2/2.5/3)",
1600 .set_key
= wpa_driver_hostap_set_key
,
1602 .hapd_init
= hostap_init
,
1603 .hapd_deinit
= hostap_driver_deinit
,
1604 .set_ieee8021x
= hostap_set_ieee8021x
,
1605 .set_privacy
= hostap_set_privacy
,
1606 .get_seqnum
= hostap_get_seqnum
,
1607 .flush
= hostap_flush
,
1608 .set_generic_elem
= hostap_set_generic_elem
,
1609 .read_sta_data
= hostap_read_sta_data
,
1610 .hapd_send_eapol
= hostap_send_eapol
,
1611 .sta_set_flags
= hostap_sta_set_flags
,
1612 .sta_deauth
= hostap_sta_deauth
,
1613 .sta_disassoc
= hostap_sta_disassoc
,
1614 .sta_remove
= hostap_sta_remove
,
1615 .hapd_set_ssid
= hostap_set_ssid
,
1616 .send_mlme
= hostap_send_mlme
,
1617 .sta_add
= hostap_sta_add
,
1618 .get_inact_sec
= hostap_get_inact_sec
,
1619 .sta_clear_stats
= hostap_sta_clear_stats
,
1620 .get_hw_feature_data
= hostap_get_hw_feature_data
,
1621 .set_ap_wps_ie
= hostap_set_ap_wps_ie
,
1623 .get_bssid
= wpa_driver_hostap_get_bssid
,
1624 .get_ssid
= wpa_driver_hostap_get_ssid
,
1625 .set_countermeasures
= wpa_driver_hostap_set_countermeasures
,
1626 .scan2
= wpa_driver_hostap_scan
,
1627 .get_scan_results2
= wpa_driver_hostap_get_scan_results
,
1628 .deauthenticate
= wpa_driver_hostap_deauthenticate
,
1629 .disassociate
= wpa_driver_hostap_disassociate
,
1630 .associate
= wpa_driver_hostap_associate
,
1631 .init
= wpa_driver_hostap_init
,
1632 .deinit
= wpa_driver_hostap_deinit
,
1633 .set_operstate
= wpa_driver_hostap_set_operstate
,
1634 #endif /* HOSTAPD */