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 memset(&ifr
, 0, sizeof(ifr
));
273 os_strlcpy(ifr
.ifr_name
, drv
->iface
, sizeof(ifr
.ifr_name
));
274 if (ioctl(drv
->sock
, SIOCGIFHWADDR
, &ifr
) != 0) {
275 perror("ioctl(SIOCGIFHWADDR)");
279 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) {
280 printf("Invalid HW-addr family 0x%04x\n",
281 ifr
.ifr_hwaddr
.sa_family
);
284 os_memcpy(own_addr
, ifr
.ifr_hwaddr
.sa_data
, ETH_ALEN
);
290 static int hostap_send_mlme(void *priv
, const u8
*msg
, size_t len
)
292 struct hostap_driver_data
*drv
= priv
;
293 struct ieee80211_hdr
*hdr
= (struct ieee80211_hdr
*) msg
;
296 /* Request TX callback */
297 hdr
->frame_control
|= host_to_le16(BIT(1));
298 res
= send(drv
->sock
, msg
, len
, 0);
299 hdr
->frame_control
&= ~host_to_le16(BIT(1));
305 static int hostap_send_eapol(void *priv
, const u8
*addr
, const u8
*data
,
306 size_t data_len
, int encrypt
, const u8
*own_addr
)
308 struct hostap_driver_data
*drv
= priv
;
309 struct ieee80211_hdr
*hdr
;
314 len
= sizeof(*hdr
) + sizeof(rfc1042_header
) + 2 + data_len
;
315 hdr
= os_zalloc(len
);
317 printf("malloc() failed for hostapd_send_data(len=%lu)\n",
318 (unsigned long) len
);
323 IEEE80211_FC(WLAN_FC_TYPE_DATA
, WLAN_FC_STYPE_DATA
);
324 hdr
->frame_control
|= host_to_le16(WLAN_FC_FROMDS
);
326 hdr
->frame_control
|= host_to_le16(WLAN_FC_ISWEP
);
327 memcpy(hdr
->IEEE80211_DA_FROMDS
, addr
, ETH_ALEN
);
328 memcpy(hdr
->IEEE80211_BSSID_FROMDS
, own_addr
, ETH_ALEN
);
329 memcpy(hdr
->IEEE80211_SA_FROMDS
, own_addr
, ETH_ALEN
);
331 pos
= (u8
*) (hdr
+ 1);
332 memcpy(pos
, rfc1042_header
, sizeof(rfc1042_header
));
333 pos
+= sizeof(rfc1042_header
);
334 *((u16
*) pos
) = htons(ETH_P_PAE
);
336 memcpy(pos
, data
, data_len
);
338 res
= hostap_send_mlme(drv
, (u8
*) hdr
, len
);
340 wpa_printf(MSG_ERROR
, "hostap_send_eapol - packet len: %lu - "
342 (unsigned long) len
, errno
, strerror(errno
));
350 static int hostap_sta_set_flags(void *priv
, const u8
*addr
,
351 int total_flags
, int flags_or
, int flags_and
)
353 struct hostap_driver_data
*drv
= priv
;
354 struct prism2_hostapd_param param
;
356 if (flags_or
& WPA_STA_AUTHORIZED
)
357 flags_or
= BIT(5); /* WLAN_STA_AUTHORIZED */
358 if (!(flags_and
& WPA_STA_AUTHORIZED
))
362 memset(¶m
, 0, sizeof(param
));
363 param
.cmd
= PRISM2_HOSTAPD_SET_FLAGS_STA
;
364 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
365 param
.u
.set_flags_sta
.flags_or
= flags_or
;
366 param
.u
.set_flags_sta
.flags_and
= flags_and
;
367 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
371 static int hostap_set_iface_flags(void *priv
, int dev_up
)
373 struct hostap_driver_data
*drv
= priv
;
375 char ifname
[IFNAMSIZ
];
377 os_snprintf(ifname
, IFNAMSIZ
, "%sap", drv
->iface
);
378 if (linux_set_iface_flags(drv
->ioctl_sock
, ifname
, dev_up
) < 0)
382 memset(&ifr
, 0, sizeof(ifr
));
383 os_strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
384 ifr
.ifr_mtu
= HOSTAPD_MTU
;
385 if (ioctl(drv
->ioctl_sock
, SIOCSIFMTU
, &ifr
) != 0) {
386 perror("ioctl[SIOCSIFMTU]");
387 printf("Setting MTU failed - trying to survive with "
396 static int hostapd_ioctl(void *priv
, struct prism2_hostapd_param
*param
,
399 struct hostap_driver_data
*drv
= priv
;
402 memset(&iwr
, 0, sizeof(iwr
));
403 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
404 iwr
.u
.data
.pointer
= (caddr_t
) param
;
405 iwr
.u
.data
.length
= len
;
407 if (ioctl(drv
->ioctl_sock
, PRISM2_IOCTL_HOSTAPD
, &iwr
) < 0) {
408 perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
416 static int wpa_driver_hostap_set_key(const char *ifname
, void *priv
,
417 enum wpa_alg alg
, const u8
*addr
,
418 int key_idx
, int set_tx
,
419 const u8
*seq
, size_t seq_len
,
420 const u8
*key
, size_t key_len
)
422 struct hostap_driver_data
*drv
= priv
;
423 struct prism2_hostapd_param
*param
;
428 blen
= sizeof(*param
) + key_len
;
429 buf
= os_zalloc(blen
);
433 param
= (struct prism2_hostapd_param
*) buf
;
434 param
->cmd
= PRISM2_SET_ENCRYPTION
;
436 memset(param
->sta_addr
, 0xff, ETH_ALEN
);
438 memcpy(param
->sta_addr
, addr
, ETH_ALEN
);
441 os_strlcpy((char *) param
->u
.crypt
.alg
, "NONE",
442 HOSTAP_CRYPT_ALG_NAME_LEN
);
445 os_strlcpy((char *) param
->u
.crypt
.alg
, "WEP",
446 HOSTAP_CRYPT_ALG_NAME_LEN
);
449 os_strlcpy((char *) param
->u
.crypt
.alg
, "TKIP",
450 HOSTAP_CRYPT_ALG_NAME_LEN
);
453 os_strlcpy((char *) param
->u
.crypt
.alg
, "CCMP",
454 HOSTAP_CRYPT_ALG_NAME_LEN
);
460 param
->u
.crypt
.flags
= set_tx
? HOSTAP_CRYPT_FLAG_SET_TX_KEY
: 0;
461 param
->u
.crypt
.idx
= key_idx
;
462 param
->u
.crypt
.key_len
= key_len
;
463 memcpy((u8
*) (param
+ 1), key
, key_len
);
465 if (hostapd_ioctl(drv
, param
, blen
)) {
466 printf("Failed to set encryption.\n");
475 static int hostap_get_seqnum(const char *ifname
, void *priv
, const u8
*addr
,
478 struct hostap_driver_data
*drv
= priv
;
479 struct prism2_hostapd_param
*param
;
484 blen
= sizeof(*param
) + 32;
485 buf
= os_zalloc(blen
);
489 param
= (struct prism2_hostapd_param
*) buf
;
490 param
->cmd
= PRISM2_GET_ENCRYPTION
;
492 memset(param
->sta_addr
, 0xff, ETH_ALEN
);
494 memcpy(param
->sta_addr
, addr
, ETH_ALEN
);
495 param
->u
.crypt
.idx
= idx
;
497 if (hostapd_ioctl(drv
, param
, blen
)) {
498 printf("Failed to get encryption.\n");
501 memcpy(seq
, param
->u
.crypt
.seq
, 8);
509 static int hostap_ioctl_prism2param(void *priv
, int param
, int value
)
511 struct hostap_driver_data
*drv
= priv
;
515 memset(&iwr
, 0, sizeof(iwr
));
516 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
517 i
= (int *) iwr
.u
.name
;
521 if (ioctl(drv
->ioctl_sock
, PRISM2_IOCTL_PRISM2_PARAM
, &iwr
) < 0) {
522 perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
530 static int hostap_set_ieee8021x(void *priv
, struct wpa_bss_params
*params
)
532 struct hostap_driver_data
*drv
= priv
;
533 int enabled
= params
->enabled
;
535 /* enable kernel driver support for IEEE 802.1X */
536 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_IEEE_802_1X
, enabled
)) {
537 printf("Could not setup IEEE 802.1X support in kernel driver."
545 /* use host driver implementation of encryption to allow
546 * individual keys and passing plaintext EAPOL frames */
547 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOST_DECRYPT
, 1) ||
548 hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOST_ENCRYPT
, 1)) {
549 printf("Could not setup host-based encryption in kernel "
558 static int hostap_set_privacy(const char *ifname
, void *priv
, int enabled
)
560 struct hostap_drvier_data
*drv
= priv
;
562 return hostap_ioctl_prism2param(drv
, PRISM2_PARAM_PRIVACY_INVOKED
,
567 static int hostap_set_ssid(const char *ifname
, void *priv
, const u8
*buf
,
570 struct hostap_driver_data
*drv
= priv
;
573 memset(&iwr
, 0, sizeof(iwr
));
574 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
575 iwr
.u
.essid
.flags
= 1; /* SSID active */
576 iwr
.u
.essid
.pointer
= (caddr_t
) buf
;
577 iwr
.u
.essid
.length
= len
+ 1;
579 if (ioctl(drv
->ioctl_sock
, SIOCSIWESSID
, &iwr
) < 0) {
580 perror("ioctl[SIOCSIWESSID]");
581 printf("len=%d\n", len
);
589 static int hostap_flush(void *priv
)
591 struct hostap_driver_data
*drv
= priv
;
592 struct prism2_hostapd_param param
;
594 memset(¶m
, 0, sizeof(param
));
595 param
.cmd
= PRISM2_HOSTAPD_FLUSH
;
596 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
600 static int hostap_read_sta_data(void *priv
,
601 struct hostap_sta_driver_data
*data
,
604 struct hostap_driver_data
*drv
= priv
;
605 char buf
[1024], line
[128], *pos
;
609 memset(data
, 0, sizeof(*data
));
610 snprintf(buf
, sizeof(buf
), "/proc/net/hostap/%s/" MACSTR
,
611 drv
->iface
, MAC2STR(addr
));
616 /* Need to read proc file with in one piece, so use large enough
618 setbuffer(f
, buf
, sizeof(buf
));
620 while (fgets(line
, sizeof(line
), f
)) {
621 pos
= strchr(line
, '=');
625 val
= strtoul(pos
, NULL
, 10);
626 if (strcmp(line
, "rx_packets") == 0)
627 data
->rx_packets
= val
;
628 else if (strcmp(line
, "tx_packets") == 0)
629 data
->tx_packets
= val
;
630 else if (strcmp(line
, "rx_bytes") == 0)
631 data
->rx_bytes
= val
;
632 else if (strcmp(line
, "tx_bytes") == 0)
633 data
->tx_bytes
= val
;
642 static int hostap_sta_add(const char *ifname
, void *priv
,
643 struct hostapd_sta_add_params
*params
)
645 struct hostap_driver_data
*drv
= priv
;
646 struct prism2_hostapd_param param
;
647 int tx_supp_rates
= 0;
650 #define WLAN_RATE_1M BIT(0)
651 #define WLAN_RATE_2M BIT(1)
652 #define WLAN_RATE_5M5 BIT(2)
653 #define WLAN_RATE_11M BIT(3)
655 for (i
= 0; i
< params
->supp_rates_len
; i
++) {
656 if ((params
->supp_rates
[i
] & 0x7f) == 2)
657 tx_supp_rates
|= WLAN_RATE_1M
;
658 if ((params
->supp_rates
[i
] & 0x7f) == 4)
659 tx_supp_rates
|= WLAN_RATE_2M
;
660 if ((params
->supp_rates
[i
] & 0x7f) == 11)
661 tx_supp_rates
|= WLAN_RATE_5M5
;
662 if ((params
->supp_rates
[i
] & 0x7f) == 22)
663 tx_supp_rates
|= WLAN_RATE_11M
;
666 memset(¶m
, 0, sizeof(param
));
667 param
.cmd
= PRISM2_HOSTAPD_ADD_STA
;
668 memcpy(param
.sta_addr
, params
->addr
, ETH_ALEN
);
669 param
.u
.add_sta
.aid
= params
->aid
;
670 param
.u
.add_sta
.capability
= params
->capability
;
671 param
.u
.add_sta
.tx_supp_rates
= tx_supp_rates
;
672 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
676 static int hostap_sta_remove(void *priv
, const u8
*addr
)
678 struct hostap_driver_data
*drv
= priv
;
679 struct prism2_hostapd_param param
;
681 hostap_sta_set_flags(drv
, addr
, 0, 0, ~WPA_STA_AUTHORIZED
);
683 memset(¶m
, 0, sizeof(param
));
684 param
.cmd
= PRISM2_HOSTAPD_REMOVE_STA
;
685 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
686 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
687 printf("Could not remove station from kernel driver.\n");
694 static int hostap_get_inact_sec(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_GET_INFO_STA
;
701 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
702 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
706 return param
.u
.get_info_sta
.inactive_sec
;
710 static int hostap_sta_clear_stats(void *priv
, const u8
*addr
)
712 struct hostap_driver_data
*drv
= priv
;
713 struct prism2_hostapd_param param
;
715 memset(¶m
, 0, sizeof(param
));
716 param
.cmd
= PRISM2_HOSTAPD_STA_CLEAR_STATS
;
717 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
718 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
726 static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data
*drv
)
728 struct prism2_hostapd_param
*param
;
730 size_t blen
, elem_len
;
732 elem_len
= drv
->generic_ie_len
+ drv
->wps_ie_len
;
733 blen
= PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN
+ elem_len
;
734 if (blen
< sizeof(*param
))
735 blen
= sizeof(*param
);
737 param
= os_zalloc(blen
);
741 param
->cmd
= PRISM2_HOSTAPD_SET_GENERIC_ELEMENT
;
742 param
->u
.generic_elem
.len
= elem_len
;
743 if (drv
->generic_ie
) {
744 os_memcpy(param
->u
.generic_elem
.data
, drv
->generic_ie
,
745 drv
->generic_ie_len
);
748 os_memcpy(¶m
->u
.generic_elem
.data
[drv
->generic_ie_len
],
749 drv
->wps_ie
, drv
->wps_ie_len
);
751 wpa_hexdump(MSG_DEBUG
, "hostap: Set generic IE",
752 param
->u
.generic_elem
.data
, elem_len
);
753 res
= hostapd_ioctl(drv
, param
, blen
);
761 static int hostap_set_generic_elem(const char *ifname
, void *priv
,
762 const u8
*elem
, size_t elem_len
)
764 struct hostap_driver_data
*drv
= priv
;
766 os_free(drv
->generic_ie
);
767 drv
->generic_ie
= NULL
;
768 drv
->generic_ie_len
= 0;
770 drv
->generic_ie
= os_malloc(elem_len
);
771 if (drv
->generic_ie
== NULL
)
773 os_memcpy(drv
->generic_ie
, elem
, elem_len
);
774 drv
->generic_ie_len
= elem_len
;
777 return hostapd_ioctl_set_generic_elem(drv
);
781 static int hostap_set_ap_wps_ie(const char *ifname
, void *priv
,
782 const struct wpabuf
*beacon
,
783 const struct wpabuf
*proberesp
)
785 struct hostap_driver_data
*drv
= priv
;
788 * Host AP driver supports only one set of extra IEs, so we need to
789 * use the Probe Response IEs also for Beacon frames since they include
793 os_free(drv
->wps_ie
);
797 drv
->wps_ie
= os_malloc(wpabuf_len(proberesp
));
798 if (drv
->wps_ie
== NULL
)
800 os_memcpy(drv
->wps_ie
, wpabuf_head(proberesp
),
801 wpabuf_len(proberesp
));
802 drv
->wps_ie_len
= wpabuf_len(proberesp
);
805 return hostapd_ioctl_set_generic_elem(drv
);
810 hostapd_wireless_event_wireless_custom(struct hostap_driver_data
*drv
,
813 wpa_printf(MSG_DEBUG
, "Custom wireless event: '%s'", custom
);
815 if (strncmp(custom
, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
818 pos
= strstr(custom
, "addr=");
820 wpa_printf(MSG_DEBUG
,
821 "MLME-MICHAELMICFAILURE.indication "
822 "without sender address ignored");
826 if (hwaddr_aton(pos
, addr
) == 0) {
827 union wpa_event_data data
;
828 os_memset(&data
, 0, sizeof(data
));
829 data
.michael_mic_failure
.unicast
= 1;
830 data
.michael_mic_failure
.src
= addr
;
831 wpa_supplicant_event(drv
->hapd
,
832 EVENT_MICHAEL_MIC_FAILURE
, &data
);
834 wpa_printf(MSG_DEBUG
,
835 "MLME-MICHAELMICFAILURE.indication "
836 "with invalid MAC address");
842 static void hostapd_wireless_event_wireless(struct hostap_driver_data
*drv
,
845 struct iw_event iwe_buf
, *iwe
= &iwe_buf
;
846 char *pos
, *end
, *custom
, *buf
;
851 while (pos
+ IW_EV_LCP_LEN
<= end
) {
852 /* Event data may be unaligned, so make a local, aligned copy
853 * before processing. */
854 memcpy(&iwe_buf
, pos
, IW_EV_LCP_LEN
);
855 wpa_printf(MSG_DEBUG
, "Wireless event: cmd=0x%x len=%d",
857 if (iwe
->len
<= IW_EV_LCP_LEN
)
860 custom
= pos
+ IW_EV_POINT_LEN
;
861 if (drv
->we_version
> 18 &&
862 (iwe
->cmd
== IWEVMICHAELMICFAILURE
||
863 iwe
->cmd
== IWEVCUSTOM
)) {
864 /* WE-19 removed the pointer from struct iw_point */
865 char *dpos
= (char *) &iwe_buf
.u
.data
.length
;
866 int dlen
= dpos
- (char *) &iwe_buf
;
867 memcpy(dpos
, pos
+ IW_EV_LCP_LEN
,
868 sizeof(struct iw_event
) - dlen
);
870 memcpy(&iwe_buf
, pos
, sizeof(struct iw_event
));
871 custom
+= IW_EV_POINT_OFF
;
876 if (custom
+ iwe
->u
.data
.length
> end
)
878 buf
= malloc(iwe
->u
.data
.length
+ 1);
881 memcpy(buf
, custom
, iwe
->u
.data
.length
);
882 buf
[iwe
->u
.data
.length
] = '\0';
883 hostapd_wireless_event_wireless_custom(drv
, buf
);
893 static void hostapd_wireless_event_rtm_newlink(void *ctx
,
894 struct ifinfomsg
*ifi
,
897 struct hostap_driver_data
*drv
= ctx
;
898 int attrlen
, rta_len
;
901 /* TODO: use ifi->ifi_index to filter out wireless events from other
905 attr
= (struct rtattr
*) buf
;
907 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
908 while (RTA_OK(attr
, attrlen
)) {
909 if (attr
->rta_type
== IFLA_WIRELESS
) {
910 hostapd_wireless_event_wireless(
911 drv
, ((char *) attr
) + rta_len
,
912 attr
->rta_len
- rta_len
);
914 attr
= RTA_NEXT(attr
, attrlen
);
919 static int hostap_get_we_version(struct hostap_driver_data
*drv
)
921 struct iw_range
*range
;
929 * Use larger buffer than struct iw_range in order to allow the
930 * structure to grow in the future.
932 buflen
= sizeof(struct iw_range
) + 500;
933 range
= os_zalloc(buflen
);
937 memset(&iwr
, 0, sizeof(iwr
));
938 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
939 iwr
.u
.data
.pointer
= (caddr_t
) range
;
940 iwr
.u
.data
.length
= buflen
;
942 minlen
= ((char *) &range
->enc_capa
) - (char *) range
+
943 sizeof(range
->enc_capa
);
945 if (ioctl(drv
->ioctl_sock
, SIOCGIWRANGE
, &iwr
) < 0) {
946 perror("ioctl[SIOCGIWRANGE]");
949 } else if (iwr
.u
.data
.length
>= minlen
&&
950 range
->we_version_compiled
>= 18) {
951 wpa_printf(MSG_DEBUG
, "SIOCGIWRANGE: WE(compiled)=%d "
952 "WE(source)=%d enc_capa=0x%x",
953 range
->we_version_compiled
,
954 range
->we_version_source
,
956 drv
->we_version
= range
->we_version_compiled
;
964 static int hostap_wireless_event_init(struct hostap_driver_data
*drv
)
966 struct netlink_config
*cfg
;
968 hostap_get_we_version(drv
);
970 cfg
= os_zalloc(sizeof(*cfg
));
974 cfg
->newlink_cb
= hostapd_wireless_event_rtm_newlink
;
975 drv
->netlink
= netlink_init(cfg
);
976 if (drv
->netlink
== NULL
) {
985 static void * hostap_init(struct hostapd_data
*hapd
,
986 struct wpa_init_params
*params
)
988 struct hostap_driver_data
*drv
;
990 drv
= os_zalloc(sizeof(struct hostap_driver_data
));
992 printf("Could not allocate memory for hostapd driver data\n");
997 drv
->ioctl_sock
= drv
->sock
= -1;
998 memcpy(drv
->iface
, params
->ifname
, sizeof(drv
->iface
));
1000 drv
->ioctl_sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
1001 if (drv
->ioctl_sock
< 0) {
1002 perror("socket[PF_INET,SOCK_DGRAM]");
1007 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD
, 1)) {
1008 printf("Could not enable hostapd mode for interface %s\n",
1010 close(drv
->ioctl_sock
);
1015 if (hostap_init_sockets(drv
, params
->own_addr
) ||
1016 hostap_wireless_event_init(drv
)) {
1017 close(drv
->ioctl_sock
);
1026 static void hostap_driver_deinit(void *priv
)
1028 struct hostap_driver_data
*drv
= priv
;
1030 netlink_deinit(drv
->netlink
);
1031 (void) hostap_set_iface_flags(drv
, 0);
1032 (void) hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD
, 0);
1033 (void) hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD_STA
, 0);
1035 if (drv
->ioctl_sock
>= 0)
1036 close(drv
->ioctl_sock
);
1041 os_free(drv
->generic_ie
);
1042 os_free(drv
->wps_ie
);
1048 static int hostap_sta_deauth(void *priv
, const u8
*own_addr
, const u8
*addr
,
1051 struct hostap_driver_data
*drv
= priv
;
1052 struct ieee80211_mgmt mgmt
;
1054 memset(&mgmt
, 0, sizeof(mgmt
));
1055 mgmt
.frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
1056 WLAN_FC_STYPE_DEAUTH
);
1057 memcpy(mgmt
.da
, addr
, ETH_ALEN
);
1058 memcpy(mgmt
.sa
, own_addr
, ETH_ALEN
);
1059 memcpy(mgmt
.bssid
, own_addr
, ETH_ALEN
);
1060 mgmt
.u
.deauth
.reason_code
= host_to_le16(reason
);
1061 return hostap_send_mlme(drv
, (u8
*) &mgmt
, IEEE80211_HDRLEN
+
1062 sizeof(mgmt
.u
.deauth
));
1066 static int hostap_sta_disassoc(void *priv
, const u8
*own_addr
, const u8
*addr
,
1069 struct hostap_driver_data
*drv
= priv
;
1070 struct ieee80211_mgmt mgmt
;
1072 memset(&mgmt
, 0, sizeof(mgmt
));
1073 mgmt
.frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
1074 WLAN_FC_STYPE_DISASSOC
);
1075 memcpy(mgmt
.da
, addr
, ETH_ALEN
);
1076 memcpy(mgmt
.sa
, own_addr
, ETH_ALEN
);
1077 memcpy(mgmt
.bssid
, own_addr
, ETH_ALEN
);
1078 mgmt
.u
.disassoc
.reason_code
= host_to_le16(reason
);
1079 return hostap_send_mlme(drv
, (u8
*) &mgmt
, IEEE80211_HDRLEN
+
1080 sizeof(mgmt
.u
.disassoc
));
1084 static struct hostapd_hw_modes
* hostap_get_hw_feature_data(void *priv
,
1088 struct hostapd_hw_modes
*mode
;
1090 const short chan2freq
[14] = {
1091 2412, 2417, 2422, 2427, 2432, 2437, 2442,
1092 2447, 2452, 2457, 2462, 2467, 2472, 2484
1095 mode
= os_zalloc(sizeof(struct hostapd_hw_modes
));
1102 mode
->mode
= HOSTAPD_MODE_IEEE80211B
;
1103 mode
->num_channels
= 14;
1104 mode
->num_rates
= 4;
1106 clen
= mode
->num_channels
* sizeof(struct hostapd_channel_data
);
1107 rlen
= mode
->num_rates
* sizeof(int);
1109 mode
->channels
= os_zalloc(clen
);
1110 mode
->rates
= os_zalloc(rlen
);
1111 if (mode
->channels
== NULL
|| mode
->rates
== NULL
) {
1112 os_free(mode
->channels
);
1113 os_free(mode
->rates
);
1118 for (i
= 0; i
< 14; i
++) {
1119 mode
->channels
[i
].chan
= i
+ 1;
1120 mode
->channels
[i
].freq
= chan2freq
[i
];
1121 /* TODO: Get allowed channel list from the driver */
1123 mode
->channels
[i
].flag
= HOSTAPD_CHAN_DISABLED
;
1126 mode
->rates
[0] = 10;
1127 mode
->rates
[1] = 20;
1128 mode
->rates
[2] = 55;
1129 mode
->rates
[3] = 110;
1136 struct wpa_driver_hostap_data
{
1137 void *wext
; /* private data for driver_wext */
1139 char ifname
[IFNAMSIZ
+ 1];
1141 int current_mode
; /* infra/adhoc */
1145 static int wpa_driver_hostap_set_auth_alg(void *priv
, int auth_alg
);
1148 static int hostapd_ioctl(struct wpa_driver_hostap_data
*drv
,
1149 struct prism2_hostapd_param
*param
,
1150 int len
, int show_err
)
1154 os_memset(&iwr
, 0, sizeof(iwr
));
1155 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1156 iwr
.u
.data
.pointer
= (caddr_t
) param
;
1157 iwr
.u
.data
.length
= len
;
1159 if (ioctl(drv
->sock
, PRISM2_IOCTL_HOSTAPD
, &iwr
) < 0) {
1162 perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
1170 static int wpa_driver_hostap_set_wpa_ie(struct wpa_driver_hostap_data
*drv
,
1171 const u8
*wpa_ie
, size_t wpa_ie_len
)
1173 struct prism2_hostapd_param
*param
;
1175 size_t blen
= PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN
+ wpa_ie_len
;
1176 if (blen
< sizeof(*param
))
1177 blen
= sizeof(*param
);
1179 param
= os_zalloc(blen
);
1183 param
->cmd
= PRISM2_HOSTAPD_SET_GENERIC_ELEMENT
;
1184 param
->u
.generic_elem
.len
= wpa_ie_len
;
1185 os_memcpy(param
->u
.generic_elem
.data
, wpa_ie
, wpa_ie_len
);
1186 res
= hostapd_ioctl(drv
, param
, blen
, 1);
1194 static int prism2param(struct wpa_driver_hostap_data
*drv
, int param
,
1200 os_memset(&iwr
, 0, sizeof(iwr
));
1201 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1202 i
= (int *) iwr
.u
.name
;
1206 if (ioctl(drv
->sock
, PRISM2_IOCTL_PRISM2_PARAM
, &iwr
) < 0) {
1207 perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
1214 static int wpa_driver_hostap_set_wpa(void *priv
, int enabled
)
1216 struct wpa_driver_hostap_data
*drv
= priv
;
1219 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __FUNCTION__
, enabled
);
1221 if (!enabled
&& wpa_driver_hostap_set_wpa_ie(drv
, NULL
, 0) < 0)
1223 if (prism2param(drv
, PRISM2_PARAM_HOST_ROAMING
, enabled
? 2 : 0) < 0)
1225 if (prism2param(drv
, PRISM2_PARAM_WPA
, enabled
) < 0)
1232 static void show_set_key_error(struct prism2_hostapd_param
*param
)
1234 switch (param
->u
.crypt
.err
) {
1235 case HOSTAP_CRYPT_ERR_UNKNOWN_ALG
:
1236 wpa_printf(MSG_INFO
, "Unknown algorithm '%s'.",
1237 param
->u
.crypt
.alg
);
1238 wpa_printf(MSG_INFO
, "You may need to load kernel module to "
1239 "register that algorithm.");
1240 wpa_printf(MSG_INFO
, "E.g., 'modprobe hostap_crypt_wep' for "
1243 case HOSTAP_CRYPT_ERR_UNKNOWN_ADDR
:
1244 wpa_printf(MSG_INFO
, "Unknown address " MACSTR
".",
1245 MAC2STR(param
->sta_addr
));
1247 case HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED
:
1248 wpa_printf(MSG_INFO
, "Crypt algorithm initialization failed.");
1250 case HOSTAP_CRYPT_ERR_KEY_SET_FAILED
:
1251 wpa_printf(MSG_INFO
, "Key setting failed.");
1253 case HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED
:
1254 wpa_printf(MSG_INFO
, "TX key index setting failed.");
1256 case HOSTAP_CRYPT_ERR_CARD_CONF_FAILED
:
1257 wpa_printf(MSG_INFO
, "Card configuration failed.");
1263 static int wpa_driver_hostap_set_key(const char *ifname
, void *priv
,
1264 enum wpa_alg alg
, const u8
*addr
,
1265 int key_idx
, int set_tx
,
1266 const u8
*seq
, size_t seq_len
,
1267 const u8
*key
, size_t key_len
)
1269 struct wpa_driver_hostap_data
*drv
= priv
;
1270 struct prism2_hostapd_param
*param
;
1293 wpa_printf(MSG_DEBUG
, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu "
1294 "key_len=%lu", __FUNCTION__
, alg_name
, key_idx
, set_tx
,
1295 (unsigned long) seq_len
, (unsigned long) key_len
);
1300 blen
= sizeof(*param
) + key_len
;
1301 buf
= os_zalloc(blen
);
1305 param
= (struct prism2_hostapd_param
*) buf
;
1306 param
->cmd
= PRISM2_SET_ENCRYPTION
;
1307 /* TODO: In theory, STA in client mode can use five keys; four default
1308 * keys for receiving (with keyidx 0..3) and one individual key for
1309 * both transmitting and receiving (keyidx 0) _unicast_ packets. Now,
1310 * keyidx 0 is reserved for this unicast use and default keys can only
1311 * use keyidx 1..3 (i.e., default key with keyidx 0 is not supported).
1312 * This should be fine for more or less all cases, but for completeness
1313 * sake, the driver could be enhanced to support the missing key. */
1316 os_memset(param
->sta_addr
, 0xff, ETH_ALEN
);
1318 os_memcpy(param
->sta_addr
, addr
, ETH_ALEN
);
1320 os_memset(param
->sta_addr
, 0xff, ETH_ALEN
);
1322 os_strlcpy((char *) param
->u
.crypt
.alg
, alg_name
,
1323 HOSTAP_CRYPT_ALG_NAME_LEN
);
1324 param
->u
.crypt
.flags
= set_tx
? HOSTAP_CRYPT_FLAG_SET_TX_KEY
: 0;
1325 param
->u
.crypt
.idx
= key_idx
;
1326 os_memcpy(param
->u
.crypt
.seq
, seq
, seq_len
);
1327 param
->u
.crypt
.key_len
= key_len
;
1328 os_memcpy((u8
*) (param
+ 1), key
, key_len
);
1330 if (hostapd_ioctl(drv
, param
, blen
, 1)) {
1331 wpa_printf(MSG_WARNING
, "Failed to set encryption.");
1332 show_set_key_error(param
);
1341 static int wpa_driver_hostap_set_countermeasures(void *priv
, int enabled
)
1343 struct wpa_driver_hostap_data
*drv
= priv
;
1344 wpa_printf(MSG_DEBUG
, "%s: enabled=%d", __FUNCTION__
, enabled
);
1345 return prism2param(drv
, PRISM2_PARAM_TKIP_COUNTERMEASURES
, enabled
);
1349 static int wpa_driver_hostap_reset(struct wpa_driver_hostap_data
*drv
,
1355 wpa_printf(MSG_DEBUG
, "%s: type=%d", __FUNCTION__
, type
);
1357 os_memset(&iwr
, 0, sizeof(iwr
));
1358 os_strlcpy(iwr
.ifr_name
, drv
->ifname
, IFNAMSIZ
);
1359 i
= (int *) iwr
.u
.name
;
1362 if (ioctl(drv
->sock
, PRISM2_IOCTL_RESET
, &iwr
) < 0) {
1363 perror("ioctl[PRISM2_IOCTL_RESET]");
1370 static int wpa_driver_hostap_mlme(struct wpa_driver_hostap_data
*drv
,
1371 const u8
*addr
, int cmd
, int reason_code
)
1373 struct prism2_hostapd_param param
;
1376 /* There does not seem to be a better way of deauthenticating or
1377 * disassociating with Prism2/2.5/3 than sending the management frame
1378 * and then resetting the Port0 to make sure both the AP and the STA
1379 * end up in disconnected state. */
1380 os_memset(¶m
, 0, sizeof(param
));
1381 param
.cmd
= PRISM2_HOSTAPD_MLME
;
1382 os_memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
1383 param
.u
.mlme
.cmd
= cmd
;
1384 param
.u
.mlme
.reason_code
= reason_code
;
1385 ret
= hostapd_ioctl(drv
, ¶m
, sizeof(param
), 1);
1387 os_sleep(0, 100000);
1388 ret
= wpa_driver_hostap_reset(drv
, 2);
1394 static int wpa_driver_hostap_deauthenticate(void *priv
, const u8
*addr
,
1397 struct wpa_driver_hostap_data
*drv
= priv
;
1398 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1399 return wpa_driver_hostap_mlme(drv
, addr
, MLME_STA_DEAUTH
,
1404 static int wpa_driver_hostap_disassociate(void *priv
, const u8
*addr
,
1407 struct wpa_driver_hostap_data
*drv
= priv
;
1408 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1409 return wpa_driver_hostap_mlme(drv
, addr
, MLME_STA_DISASSOC
,
1415 wpa_driver_hostap_associate(void *priv
,
1416 struct wpa_driver_associate_params
*params
)
1418 struct wpa_driver_hostap_data
*drv
= priv
;
1420 int allow_unencrypted_eapol
;
1422 wpa_printf(MSG_DEBUG
, "%s", __FUNCTION__
);
1424 if (prism2param(drv
, PRISM2_PARAM_DROP_UNENCRYPTED
,
1425 params
->drop_unencrypted
) < 0)
1427 if (wpa_driver_hostap_set_auth_alg(drv
, params
->auth_alg
) < 0)
1429 if (params
->mode
!= drv
->current_mode
) {
1430 /* At the moment, Host AP driver requires host_roaming=2 for
1431 * infrastructure mode and host_roaming=0 for adhoc. */
1432 if (prism2param(drv
, PRISM2_PARAM_HOST_ROAMING
,
1433 params
->mode
== IEEE80211_MODE_IBSS
? 0 : 2) <
1435 wpa_printf(MSG_DEBUG
, "%s: failed to set host_roaming",
1438 drv
->current_mode
= params
->mode
;
1441 if (prism2param(drv
, PRISM2_PARAM_PRIVACY_INVOKED
,
1442 params
->key_mgmt_suite
!= KEY_MGMT_NONE
) < 0)
1444 if (wpa_driver_hostap_set_wpa_ie(drv
, params
->wpa_ie
,
1445 params
->wpa_ie_len
) < 0)
1447 if (wpa_driver_wext_set_mode(drv
->wext
, params
->mode
) < 0)
1450 wpa_driver_wext_set_freq(drv
->wext
, params
->freq
) < 0)
1452 if (wpa_driver_wext_set_ssid(drv
->wext
, params
->ssid
, params
->ssid_len
)
1455 if (wpa_driver_wext_set_bssid(drv
->wext
, params
->bssid
) < 0)
1458 /* Allow unencrypted EAPOL messages even if pairwise keys are set when
1459 * not using WPA. IEEE 802.1X specifies that these frames are not
1460 * encrypted, but WPA encrypts them when pairwise keys are in use. */
1461 if (params
->key_mgmt_suite
== KEY_MGMT_802_1X
||
1462 params
->key_mgmt_suite
== KEY_MGMT_PSK
)
1463 allow_unencrypted_eapol
= 0;
1465 allow_unencrypted_eapol
= 1;
1467 if (prism2param(drv
, PRISM2_PARAM_IEEE_802_1X
,
1468 allow_unencrypted_eapol
) < 0) {
1469 wpa_printf(MSG_DEBUG
, "hostap: Failed to configure "
1470 "ieee_802_1x param");
1471 /* Ignore this error.. driver_hostap.c can also be used with
1472 * other drivers that do not support this prism2_param. */
1479 static int wpa_driver_hostap_scan(void *priv
,
1480 struct wpa_driver_scan_params
*params
)
1482 struct wpa_driver_hostap_data
*drv
= priv
;
1483 struct prism2_hostapd_param param
;
1485 const u8
*ssid
= params
->ssids
[0].ssid
;
1486 size_t ssid_len
= params
->ssids
[0].ssid_len
;
1489 /* Use standard Linux Wireless Extensions ioctl if possible
1490 * because some drivers using hostap code in wpa_supplicant
1491 * might not support Host AP specific scan request (with SSID
1493 return wpa_driver_wext_scan(drv
->wext
, params
);
1499 os_memset(¶m
, 0, sizeof(param
));
1500 param
.cmd
= PRISM2_HOSTAPD_SCAN_REQ
;
1501 param
.u
.scan_req
.ssid_len
= ssid_len
;
1502 os_memcpy(param
.u
.scan_req
.ssid
, ssid
, ssid_len
);
1503 ret
= hostapd_ioctl(drv
, ¶m
, sizeof(param
), 1);
1505 /* Not all drivers generate "scan completed" wireless event, so try to
1506 * read results after a timeout. */
1507 eloop_cancel_timeout(wpa_driver_wext_scan_timeout
, drv
->wext
,
1509 eloop_register_timeout(3, 0, wpa_driver_wext_scan_timeout
, drv
->wext
,
1516 static int wpa_driver_hostap_set_auth_alg(void *priv
, int auth_alg
)
1518 struct wpa_driver_hostap_data
*drv
= priv
;
1521 if (auth_alg
& WPA_AUTH_ALG_OPEN
)
1523 if (auth_alg
& WPA_AUTH_ALG_SHARED
)
1525 if (auth_alg
& WPA_AUTH_ALG_LEAP
)
1528 algs
= 1; /* at least one algorithm should be set */
1530 return prism2param(drv
, PRISM2_PARAM_AP_AUTH_ALGS
, algs
);
1534 static int wpa_driver_hostap_get_bssid(void *priv
, u8
*bssid
)
1536 struct wpa_driver_hostap_data
*drv
= priv
;
1537 return wpa_driver_wext_get_bssid(drv
->wext
, bssid
);
1541 static int wpa_driver_hostap_get_ssid(void *priv
, u8
*ssid
)
1543 struct wpa_driver_hostap_data
*drv
= priv
;
1544 return wpa_driver_wext_get_ssid(drv
->wext
, ssid
);
1548 static struct wpa_scan_results
* wpa_driver_hostap_get_scan_results(void *priv
)
1550 struct wpa_driver_hostap_data
*drv
= priv
;
1551 return wpa_driver_wext_get_scan_results(drv
->wext
);
1555 static int wpa_driver_hostap_set_operstate(void *priv
, int state
)
1557 struct wpa_driver_hostap_data
*drv
= priv
;
1558 return wpa_driver_wext_set_operstate(drv
->wext
, state
);
1562 static void * wpa_driver_hostap_init(void *ctx
, const char *ifname
)
1564 struct wpa_driver_hostap_data
*drv
;
1566 drv
= os_zalloc(sizeof(*drv
));
1569 drv
->wext
= wpa_driver_wext_init(ctx
, ifname
);
1570 if (drv
->wext
== NULL
) {
1576 os_strlcpy(drv
->ifname
, ifname
, sizeof(drv
->ifname
));
1577 drv
->sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
1578 if (drv
->sock
< 0) {
1580 wpa_driver_wext_deinit(drv
->wext
);
1585 if (os_strncmp(ifname
, "wlan", 4) == 0) {
1587 * Host AP driver may use both wlan# and wifi# interface in
1590 char ifname2
[IFNAMSIZ
+ 1];
1591 os_strlcpy(ifname2
, ifname
, sizeof(ifname2
));
1592 os_memcpy(ifname2
, "wifi", 4);
1593 wpa_driver_wext_alternative_ifindex(drv
->wext
, ifname2
);
1596 wpa_driver_hostap_set_wpa(drv
, 1);
1602 static void wpa_driver_hostap_deinit(void *priv
)
1604 struct wpa_driver_hostap_data
*drv
= priv
;
1605 wpa_driver_hostap_set_wpa(drv
, 0);
1606 wpa_driver_wext_deinit(drv
->wext
);
1611 #endif /* HOSTAPD */
1614 const struct wpa_driver_ops wpa_driver_hostap_ops
= {
1616 .desc
= "Host AP driver (Intersil Prism2/2.5/3)",
1617 .set_key
= wpa_driver_hostap_set_key
,
1619 .hapd_init
= hostap_init
,
1620 .hapd_deinit
= hostap_driver_deinit
,
1621 .set_ieee8021x
= hostap_set_ieee8021x
,
1622 .set_privacy
= hostap_set_privacy
,
1623 .get_seqnum
= hostap_get_seqnum
,
1624 .flush
= hostap_flush
,
1625 .set_generic_elem
= hostap_set_generic_elem
,
1626 .read_sta_data
= hostap_read_sta_data
,
1627 .hapd_send_eapol
= hostap_send_eapol
,
1628 .sta_set_flags
= hostap_sta_set_flags
,
1629 .sta_deauth
= hostap_sta_deauth
,
1630 .sta_disassoc
= hostap_sta_disassoc
,
1631 .sta_remove
= hostap_sta_remove
,
1632 .hapd_set_ssid
= hostap_set_ssid
,
1633 .send_mlme
= hostap_send_mlme
,
1634 .sta_add
= hostap_sta_add
,
1635 .get_inact_sec
= hostap_get_inact_sec
,
1636 .sta_clear_stats
= hostap_sta_clear_stats
,
1637 .get_hw_feature_data
= hostap_get_hw_feature_data
,
1638 .set_ap_wps_ie
= hostap_set_ap_wps_ie
,
1640 .get_bssid
= wpa_driver_hostap_get_bssid
,
1641 .get_ssid
= wpa_driver_hostap_get_ssid
,
1642 .set_countermeasures
= wpa_driver_hostap_set_countermeasures
,
1643 .scan2
= wpa_driver_hostap_scan
,
1644 .get_scan_results2
= wpa_driver_hostap_get_scan_results
,
1645 .deauthenticate
= wpa_driver_hostap_deauthenticate
,
1646 .disassociate
= wpa_driver_hostap_disassociate
,
1647 .associate
= wpa_driver_hostap_associate
,
1648 .init
= wpa_driver_hostap_init
,
1649 .deinit
= wpa_driver_hostap_deinit
,
1650 .set_operstate
= wpa_driver_hostap_set_operstate
,
1651 #endif /* HOSTAPD */