2 * hostapd / Kernel driver communication with Linux Host AP driver
3 * Copyright (c) 2002-2007, 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 #ifdef USE_KERNEL_HEADERS
19 /* compat-wireless does not include linux/compiler.h to define __user, so
24 #include <asm/types.h>
25 #include <linux/if_packet.h>
26 #include <linux/if_ether.h> /* The L2 protocols */
27 #include <linux/if_arp.h>
28 #include <linux/wireless.h>
29 #else /* USE_KERNEL_HEADERS */
30 #include <net/if_arp.h>
31 #include <netpacket/packet.h>
32 #include "wireless_copy.h"
33 #endif /* USE_KERNEL_HEADERS */
37 #include "ieee802_1x.h"
39 #include "priv_netlink.h"
40 #include "ieee802_11.h"
42 #include "hostap_common.h"
43 #include "hw_features.h"
46 struct hostap_driver_data
{
47 struct hostapd_data
*hapd
;
49 char iface
[IFNAMSIZ
+ 1];
50 int sock
; /* raw packet socket for driver access */
51 int ioctl_sock
; /* socket for ioctl() use */
52 int wext_sock
; /* socket for wireless events */
57 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 hostapd_data
*hapd
, u8
*buf
, size_t len
,
68 struct ieee80211_hdr
*hdr
;
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 sta
= ap_get_sta(hapd
, sa
);
87 if (!sta
|| !(sta
->flags
& WLAN_STA_ASSOC
)) {
88 printf("Data frame from not associated STA " MACSTR
"\n",
90 if (sta
&& (sta
->flags
& WLAN_STA_AUTH
))
93 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA
);
97 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA
);
101 pos
= (u8
*) (hdr
+ 1);
102 left
= len
- sizeof(*hdr
);
104 if (left
< sizeof(rfc1042_header
)) {
105 printf("Too short data frame\n");
109 if (memcmp(pos
, rfc1042_header
, sizeof(rfc1042_header
)) != 0) {
110 printf("Data frame with no RFC1042 header\n");
113 pos
+= sizeof(rfc1042_header
);
114 left
-= sizeof(rfc1042_header
);
117 printf("No ethertype in data frame\n");
121 ethertype
= WPA_GET_BE16(pos
);
126 ieee802_1x_receive(hapd
, sa
, pos
, left
);
130 printf("Unknown ethertype 0x%04x in data frame\n", ethertype
);
136 static void handle_tx_callback(struct hostapd_data
*hapd
, u8
*buf
, size_t len
,
139 struct ieee80211_hdr
*hdr
;
141 struct sta_info
*sta
;
143 hdr
= (struct ieee80211_hdr
*) buf
;
144 fc
= le_to_host16(hdr
->frame_control
);
146 type
= WLAN_FC_GET_TYPE(fc
);
147 stype
= WLAN_FC_GET_STYPE(fc
);
150 case WLAN_FC_TYPE_MGMT
:
151 wpa_printf(MSG_DEBUG
, "MGMT (TX callback) %s",
152 ok
? "ACK" : "fail");
153 ieee802_11_mgmt_cb(hapd
, buf
, len
, stype
, ok
);
155 case WLAN_FC_TYPE_CTRL
:
156 wpa_printf(MSG_DEBUG
, "CTRL (TX callback) %s",
157 ok
? "ACK" : "fail");
159 case WLAN_FC_TYPE_DATA
:
160 wpa_printf(MSG_DEBUG
, "DATA (TX callback) %s",
161 ok
? "ACK" : "fail");
162 sta
= ap_get_sta(hapd
, hdr
->addr1
);
163 if (sta
&& sta
->flags
& WLAN_STA_PENDING_POLL
) {
164 wpa_printf(MSG_DEBUG
, "STA " MACSTR
165 " %s pending activity poll",
167 ok
? "ACKed" : "did not ACK");
169 sta
->flags
&= ~WLAN_STA_PENDING_POLL
;
172 ieee802_1x_tx_status(hapd
, sta
, buf
, len
, ok
);
175 printf("unknown TX callback frame type %d\n", type
);
181 static void handle_frame(struct hostapd_data
*hapd
, u8
*buf
, size_t len
)
183 struct ieee80211_hdr
*hdr
;
184 u16 fc
, extra_len
, type
, stype
;
185 unsigned char *extra
= NULL
;
186 size_t data_len
= len
;
189 /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass
190 * these to user space */
192 wpa_printf(MSG_MSGDUMP
, "handle_frame: too short (%lu)",
193 (unsigned long) len
);
197 hdr
= (struct ieee80211_hdr
*) buf
;
198 fc
= le_to_host16(hdr
->frame_control
);
199 type
= WLAN_FC_GET_TYPE(fc
);
200 stype
= WLAN_FC_GET_STYPE(fc
);
202 if (type
!= WLAN_FC_TYPE_MGMT
|| stype
!= WLAN_FC_STYPE_BEACON
) {
203 wpa_hexdump(MSG_MSGDUMP
, "Received management frame",
207 ver
= fc
& WLAN_FC_PVER
;
209 /* protocol version 3 is reserved for indicating extra data after the
210 * payload, version 2 for indicating ACKed frame (TX callbacks), and
211 * version 1 for indicating failed frame (no ACK, TX callbacks) */
213 u8
*pos
= buf
+ len
- 2;
214 extra_len
= WPA_GET_LE16(pos
);
215 printf("extra data in frame (elen=%d)\n", extra_len
);
216 if ((size_t) extra_len
+ 2 > len
) {
217 printf(" extra data overflow\n");
220 len
-= extra_len
+ 2;
222 } else if (ver
== 1 || ver
== 2) {
223 handle_tx_callback(hapd
, buf
, data_len
, ver
== 2 ? 1 : 0);
225 } else if (ver
!= 0) {
226 printf("unknown protocol version %d\n", ver
);
231 case WLAN_FC_TYPE_MGMT
:
232 if (stype
!= WLAN_FC_STYPE_BEACON
)
233 wpa_printf(MSG_MSGDUMP
, "MGMT");
234 ieee802_11_mgmt(hapd
, buf
, data_len
, stype
, NULL
);
236 case WLAN_FC_TYPE_CTRL
:
237 wpa_printf(MSG_DEBUG
, "CTRL");
239 case WLAN_FC_TYPE_DATA
:
240 wpa_printf(MSG_DEBUG
, "DATA");
241 handle_data(hapd
, buf
, data_len
, stype
);
244 wpa_printf(MSG_DEBUG
, "unknown frame type %d", type
);
250 static void handle_read(int sock
, void *eloop_ctx
, void *sock_ctx
)
252 struct hostapd_data
*hapd
= (struct hostapd_data
*) eloop_ctx
;
254 unsigned char buf
[3000];
256 len
= recv(sock
, buf
, sizeof(buf
), 0);
262 handle_frame(hapd
, buf
, len
);
266 static int hostap_init_sockets(struct hostap_driver_data
*drv
)
269 struct sockaddr_ll addr
;
271 drv
->sock
= socket(PF_PACKET
, SOCK_RAW
, htons(ETH_P_ALL
));
273 perror("socket[PF_PACKET,SOCK_RAW]");
277 if (eloop_register_read_sock(drv
->sock
, handle_read
, drv
->hapd
, NULL
))
279 printf("Could not register read socket\n");
283 memset(&ifr
, 0, sizeof(ifr
));
284 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%sap", drv
->iface
);
285 if (ioctl(drv
->sock
, SIOCGIFINDEX
, &ifr
) != 0) {
286 perror("ioctl(SIOCGIFINDEX)");
290 if (hostap_set_iface_flags(drv
, 1)) {
294 memset(&addr
, 0, sizeof(addr
));
295 addr
.sll_family
= AF_PACKET
;
296 addr
.sll_ifindex
= ifr
.ifr_ifindex
;
297 wpa_printf(MSG_DEBUG
, "Opening raw packet socket for ifindex %d",
300 if (bind(drv
->sock
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
305 memset(&ifr
, 0, sizeof(ifr
));
306 os_strlcpy(ifr
.ifr_name
, drv
->iface
, sizeof(ifr
.ifr_name
));
307 if (ioctl(drv
->sock
, SIOCGIFHWADDR
, &ifr
) != 0) {
308 perror("ioctl(SIOCGIFHWADDR)");
312 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) {
313 printf("Invalid HW-addr family 0x%04x\n",
314 ifr
.ifr_hwaddr
.sa_family
);
317 memcpy(drv
->hapd
->own_addr
, ifr
.ifr_hwaddr
.sa_data
, ETH_ALEN
);
323 static int hostap_send_mgmt_frame(void *priv
, const void *msg
, size_t len
,
326 struct hostap_driver_data
*drv
= priv
;
328 return send(drv
->sock
, msg
, len
, flags
);
332 static int hostap_send_eapol(void *priv
, const u8
*addr
, const u8
*data
,
333 size_t data_len
, int encrypt
, const u8
*own_addr
)
335 struct hostap_driver_data
*drv
= priv
;
336 struct ieee80211_hdr
*hdr
;
341 len
= sizeof(*hdr
) + sizeof(rfc1042_header
) + 2 + data_len
;
342 hdr
= os_zalloc(len
);
344 printf("malloc() failed for hostapd_send_data(len=%lu)\n",
345 (unsigned long) len
);
350 IEEE80211_FC(WLAN_FC_TYPE_DATA
, WLAN_FC_STYPE_DATA
);
351 hdr
->frame_control
|= host_to_le16(WLAN_FC_FROMDS
);
352 /* Request TX callback */
353 hdr
->frame_control
|= host_to_le16(BIT(1));
355 hdr
->frame_control
|= host_to_le16(WLAN_FC_ISWEP
);
356 memcpy(hdr
->IEEE80211_DA_FROMDS
, addr
, ETH_ALEN
);
357 memcpy(hdr
->IEEE80211_BSSID_FROMDS
, own_addr
, ETH_ALEN
);
358 memcpy(hdr
->IEEE80211_SA_FROMDS
, own_addr
, ETH_ALEN
);
360 pos
= (u8
*) (hdr
+ 1);
361 memcpy(pos
, rfc1042_header
, sizeof(rfc1042_header
));
362 pos
+= sizeof(rfc1042_header
);
363 *((u16
*) pos
) = htons(ETH_P_PAE
);
365 memcpy(pos
, data
, data_len
);
367 res
= hostap_send_mgmt_frame(drv
, (u8
*) hdr
, len
, 0);
371 perror("hostapd_send_eapol: send");
372 printf("hostapd_send_eapol - packet len: %lu - failed\n",
373 (unsigned long) len
);
380 static int hostap_sta_set_flags(void *priv
, const u8
*addr
,
381 int total_flags
, int flags_or
, int flags_and
)
383 struct hostap_driver_data
*drv
= priv
;
384 struct prism2_hostapd_param param
;
386 memset(¶m
, 0, sizeof(param
));
387 param
.cmd
= PRISM2_HOSTAPD_SET_FLAGS_STA
;
388 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
389 param
.u
.set_flags_sta
.flags_or
= flags_or
;
390 param
.u
.set_flags_sta
.flags_and
= flags_and
;
391 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
395 static int hostap_set_iface_flags(void *priv
, int dev_up
)
397 struct hostap_driver_data
*drv
= priv
;
400 if (drv
->ioctl_sock
< 0)
403 memset(&ifr
, 0, sizeof(ifr
));
404 snprintf(ifr
.ifr_name
, IFNAMSIZ
, "%sap", drv
->iface
);
406 if (ioctl(drv
->ioctl_sock
, SIOCGIFFLAGS
, &ifr
) != 0) {
407 perror("ioctl[SIOCGIFFLAGS]");
412 ifr
.ifr_flags
|= IFF_UP
;
414 ifr
.ifr_flags
&= ~IFF_UP
;
416 if (ioctl(drv
->ioctl_sock
, SIOCSIFFLAGS
, &ifr
) != 0) {
417 perror("ioctl[SIOCSIFFLAGS]");
422 memset(&ifr
, 0, sizeof(ifr
));
423 snprintf(ifr
.ifr_name
, IFNAMSIZ
, "%sap", drv
->iface
);
424 ifr
.ifr_mtu
= HOSTAPD_MTU
;
425 if (ioctl(drv
->ioctl_sock
, SIOCSIFMTU
, &ifr
) != 0) {
426 perror("ioctl[SIOCSIFMTU]");
427 printf("Setting MTU failed - trying to survive with "
436 static int hostapd_ioctl(void *priv
, struct prism2_hostapd_param
*param
,
439 struct hostap_driver_data
*drv
= priv
;
442 memset(&iwr
, 0, sizeof(iwr
));
443 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
444 iwr
.u
.data
.pointer
= (caddr_t
) param
;
445 iwr
.u
.data
.length
= len
;
447 if (ioctl(drv
->ioctl_sock
, PRISM2_IOCTL_HOSTAPD
, &iwr
) < 0) {
448 perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
456 static int hostap_set_encryption(const char *ifname
, void *priv
,
457 const char *alg
, const u8
*addr
,
458 int idx
, const u8
*key
, size_t key_len
,
461 struct hostap_driver_data
*drv
= priv
;
462 struct prism2_hostapd_param
*param
;
467 blen
= sizeof(*param
) + key_len
;
468 buf
= os_zalloc(blen
);
472 param
= (struct prism2_hostapd_param
*) buf
;
473 param
->cmd
= PRISM2_SET_ENCRYPTION
;
475 memset(param
->sta_addr
, 0xff, ETH_ALEN
);
477 memcpy(param
->sta_addr
, addr
, ETH_ALEN
);
478 os_strlcpy((char *) param
->u
.crypt
.alg
, alg
,
479 HOSTAP_CRYPT_ALG_NAME_LEN
);
480 param
->u
.crypt
.flags
= txkey
? HOSTAP_CRYPT_FLAG_SET_TX_KEY
: 0;
481 param
->u
.crypt
.idx
= idx
;
482 param
->u
.crypt
.key_len
= key_len
;
483 memcpy((u8
*) (param
+ 1), key
, key_len
);
485 if (hostapd_ioctl(drv
, param
, blen
)) {
486 printf("Failed to set encryption.\n");
495 static int hostap_get_seqnum(const char *ifname
, void *priv
, const u8
*addr
,
498 struct hostap_driver_data
*drv
= priv
;
499 struct prism2_hostapd_param
*param
;
504 blen
= sizeof(*param
) + 32;
505 buf
= os_zalloc(blen
);
509 param
= (struct prism2_hostapd_param
*) buf
;
510 param
->cmd
= PRISM2_GET_ENCRYPTION
;
512 memset(param
->sta_addr
, 0xff, ETH_ALEN
);
514 memcpy(param
->sta_addr
, addr
, ETH_ALEN
);
515 param
->u
.crypt
.idx
= idx
;
517 if (hostapd_ioctl(drv
, param
, blen
)) {
518 printf("Failed to get encryption.\n");
521 memcpy(seq
, param
->u
.crypt
.seq
, 8);
529 static int hostap_ioctl_prism2param(void *priv
, int param
, int value
)
531 struct hostap_driver_data
*drv
= priv
;
535 memset(&iwr
, 0, sizeof(iwr
));
536 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
537 i
= (int *) iwr
.u
.name
;
541 if (ioctl(drv
->ioctl_sock
, PRISM2_IOCTL_PRISM2_PARAM
, &iwr
) < 0) {
542 perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
550 static int hostap_set_ieee8021x(const char *ifname
, void *priv
, int enabled
)
552 struct hostap_driver_data
*drv
= priv
;
554 /* enable kernel driver support for IEEE 802.1X */
555 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_IEEE_802_1X
, enabled
)) {
556 printf("Could not setup IEEE 802.1X support in kernel driver."
564 /* use host driver implementation of encryption to allow
565 * individual keys and passing plaintext EAPOL frames */
566 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOST_DECRYPT
, 1) ||
567 hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOST_ENCRYPT
, 1)) {
568 printf("Could not setup host-based encryption in kernel "
577 static int hostap_set_privacy(const char *ifname
, void *priv
, int enabled
)
579 struct hostap_drvier_data
*drv
= priv
;
581 return hostap_ioctl_prism2param(drv
, PRISM2_PARAM_PRIVACY_INVOKED
,
586 static int hostap_set_ssid(const char *ifname
, void *priv
, const u8
*buf
,
589 struct hostap_driver_data
*drv
= priv
;
592 memset(&iwr
, 0, sizeof(iwr
));
593 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
594 iwr
.u
.essid
.flags
= 1; /* SSID active */
595 iwr
.u
.essid
.pointer
= (caddr_t
) buf
;
596 iwr
.u
.essid
.length
= len
+ 1;
598 if (ioctl(drv
->ioctl_sock
, SIOCSIWESSID
, &iwr
) < 0) {
599 perror("ioctl[SIOCSIWESSID]");
600 printf("len=%d\n", len
);
608 static int hostap_flush(void *priv
)
610 struct hostap_driver_data
*drv
= priv
;
611 struct prism2_hostapd_param param
;
613 memset(¶m
, 0, sizeof(param
));
614 param
.cmd
= PRISM2_HOSTAPD_FLUSH
;
615 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
619 static int hostap_read_sta_data(void *priv
,
620 struct hostap_sta_driver_data
*data
,
623 struct hostap_driver_data
*drv
= priv
;
624 char buf
[1024], line
[128], *pos
;
628 memset(data
, 0, sizeof(*data
));
629 snprintf(buf
, sizeof(buf
), "/proc/net/hostap/%s/" MACSTR
,
630 drv
->iface
, MAC2STR(addr
));
635 /* Need to read proc file with in one piece, so use large enough
637 setbuffer(f
, buf
, sizeof(buf
));
639 while (fgets(line
, sizeof(line
), f
)) {
640 pos
= strchr(line
, '=');
644 val
= strtoul(pos
, NULL
, 10);
645 if (strcmp(line
, "rx_packets") == 0)
646 data
->rx_packets
= val
;
647 else if (strcmp(line
, "tx_packets") == 0)
648 data
->tx_packets
= val
;
649 else if (strcmp(line
, "rx_bytes") == 0)
650 data
->rx_bytes
= val
;
651 else if (strcmp(line
, "tx_bytes") == 0)
652 data
->tx_bytes
= val
;
661 static int hostap_sta_add(const char *ifname
, void *priv
, const u8
*addr
,
662 u16 aid
, u16 capability
, u8
*supp_rates
,
663 size_t supp_rates_len
, int flags
,
666 struct hostap_driver_data
*drv
= priv
;
667 struct prism2_hostapd_param param
;
668 int tx_supp_rates
= 0;
671 #define WLAN_RATE_1M BIT(0)
672 #define WLAN_RATE_2M BIT(1)
673 #define WLAN_RATE_5M5 BIT(2)
674 #define WLAN_RATE_11M BIT(3)
676 for (i
= 0; i
< supp_rates_len
; i
++) {
677 if ((supp_rates
[i
] & 0x7f) == 2)
678 tx_supp_rates
|= WLAN_RATE_1M
;
679 if ((supp_rates
[i
] & 0x7f) == 4)
680 tx_supp_rates
|= WLAN_RATE_2M
;
681 if ((supp_rates
[i
] & 0x7f) == 11)
682 tx_supp_rates
|= WLAN_RATE_5M5
;
683 if ((supp_rates
[i
] & 0x7f) == 22)
684 tx_supp_rates
|= WLAN_RATE_11M
;
687 memset(¶m
, 0, sizeof(param
));
688 param
.cmd
= PRISM2_HOSTAPD_ADD_STA
;
689 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
690 param
.u
.add_sta
.aid
= aid
;
691 param
.u
.add_sta
.capability
= capability
;
692 param
.u
.add_sta
.tx_supp_rates
= tx_supp_rates
;
693 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
697 static int hostap_sta_remove(void *priv
, const u8
*addr
)
699 struct hostap_driver_data
*drv
= priv
;
700 struct prism2_hostapd_param param
;
702 hostap_sta_set_flags(drv
, addr
, 0, 0, ~WLAN_STA_AUTHORIZED
);
704 memset(¶m
, 0, sizeof(param
));
705 param
.cmd
= PRISM2_HOSTAPD_REMOVE_STA
;
706 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
707 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
708 printf("Could not remove station from kernel driver.\n");
715 static int hostap_get_inact_sec(void *priv
, const u8
*addr
)
717 struct hostap_driver_data
*drv
= priv
;
718 struct prism2_hostapd_param param
;
720 memset(¶m
, 0, sizeof(param
));
721 param
.cmd
= PRISM2_HOSTAPD_GET_INFO_STA
;
722 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
723 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
727 return param
.u
.get_info_sta
.inactive_sec
;
731 static int hostap_sta_clear_stats(void *priv
, const u8
*addr
)
733 struct hostap_driver_data
*drv
= priv
;
734 struct prism2_hostapd_param param
;
736 memset(¶m
, 0, sizeof(param
));
737 param
.cmd
= PRISM2_HOSTAPD_STA_CLEAR_STATS
;
738 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
739 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
747 static int hostap_set_assoc_ap(void *priv
, const u8
*addr
)
749 struct hostap_driver_data
*drv
= priv
;
750 struct prism2_hostapd_param param
;
752 memset(¶m
, 0, sizeof(param
));
753 param
.cmd
= PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR
;
754 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
755 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
)))
762 static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data
*drv
)
764 struct prism2_hostapd_param
*param
;
766 size_t blen
, elem_len
;
768 elem_len
= drv
->generic_ie_len
;
769 blen
= PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN
+ elem_len
;
770 if (blen
< sizeof(*param
))
771 blen
= sizeof(*param
);
773 param
= os_zalloc(blen
);
777 param
->cmd
= PRISM2_HOSTAPD_SET_GENERIC_ELEMENT
;
778 param
->u
.generic_elem
.len
= elem_len
;
779 if (drv
->generic_ie
) {
780 os_memcpy(param
->u
.generic_elem
.data
, drv
->generic_ie
,
781 drv
->generic_ie_len
);
783 wpa_hexdump(MSG_DEBUG
, "hostap: Set generic IE",
784 param
->u
.generic_elem
.data
, elem_len
);
785 res
= hostapd_ioctl(drv
, param
, blen
);
793 static int hostap_set_generic_elem(const char *ifname
, void *priv
,
794 const u8
*elem
, size_t elem_len
)
796 struct hostap_driver_data
*drv
= priv
;
798 os_free(drv
->generic_ie
);
799 drv
->generic_ie
= NULL
;
800 drv
->generic_ie_len
= 0;
802 drv
->generic_ie
= os_malloc(elem_len
);
803 if (drv
->generic_ie
== NULL
)
805 os_memcpy(drv
->generic_ie
, elem
, elem_len
);
806 drv
->generic_ie_len
= elem_len
;
809 return hostapd_ioctl_set_generic_elem(drv
);
814 hostapd_wireless_event_wireless_custom(struct hostap_driver_data
*drv
,
817 wpa_printf(MSG_DEBUG
, "Custom wireless event: '%s'", custom
);
819 if (strncmp(custom
, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
822 pos
= strstr(custom
, "addr=");
824 wpa_printf(MSG_DEBUG
,
825 "MLME-MICHAELMICFAILURE.indication "
826 "without sender address ignored");
830 if (hwaddr_aton(pos
, addr
) == 0) {
831 ieee80211_michael_mic_failure(drv
->hapd
, addr
, 1);
833 wpa_printf(MSG_DEBUG
,
834 "MLME-MICHAELMICFAILURE.indication "
835 "with invalid MAC address");
841 static void hostapd_wireless_event_wireless(struct hostap_driver_data
*drv
,
844 struct iw_event iwe_buf
, *iwe
= &iwe_buf
;
845 char *pos
, *end
, *custom
, *buf
;
850 while (pos
+ IW_EV_LCP_LEN
<= end
) {
851 /* Event data may be unaligned, so make a local, aligned copy
852 * before processing. */
853 memcpy(&iwe_buf
, pos
, IW_EV_LCP_LEN
);
854 wpa_printf(MSG_DEBUG
, "Wireless event: cmd=0x%x len=%d",
856 if (iwe
->len
<= IW_EV_LCP_LEN
)
859 custom
= pos
+ IW_EV_POINT_LEN
;
860 if (drv
->we_version
> 18 &&
861 (iwe
->cmd
== IWEVMICHAELMICFAILURE
||
862 iwe
->cmd
== IWEVCUSTOM
)) {
863 /* WE-19 removed the pointer from struct iw_point */
864 char *dpos
= (char *) &iwe_buf
.u
.data
.length
;
865 int dlen
= dpos
- (char *) &iwe_buf
;
866 memcpy(dpos
, pos
+ IW_EV_LCP_LEN
,
867 sizeof(struct iw_event
) - dlen
);
869 memcpy(&iwe_buf
, pos
, sizeof(struct iw_event
));
870 custom
+= IW_EV_POINT_OFF
;
875 if (custom
+ iwe
->u
.data
.length
> end
)
877 buf
= malloc(iwe
->u
.data
.length
+ 1);
880 memcpy(buf
, custom
, iwe
->u
.data
.length
);
881 buf
[iwe
->u
.data
.length
] = '\0';
882 hostapd_wireless_event_wireless_custom(drv
, buf
);
892 static void hostapd_wireless_event_rtm_newlink(struct hostap_driver_data
*drv
,
893 struct nlmsghdr
*h
, int len
)
895 struct ifinfomsg
*ifi
;
896 int attrlen
, nlmsg_len
, rta_len
;
897 struct rtattr
* attr
;
899 if (len
< (int) sizeof(*ifi
))
904 /* TODO: use ifi->ifi_index to filter out wireless events from other
907 nlmsg_len
= NLMSG_ALIGN(sizeof(struct ifinfomsg
));
909 attrlen
= h
->nlmsg_len
- nlmsg_len
;
913 attr
= (struct rtattr
*) (((char *) ifi
) + nlmsg_len
);
915 rta_len
= RTA_ALIGN(sizeof(struct rtattr
));
916 while (RTA_OK(attr
, attrlen
)) {
917 if (attr
->rta_type
== IFLA_WIRELESS
) {
918 hostapd_wireless_event_wireless(
919 drv
, ((char *) attr
) + rta_len
,
920 attr
->rta_len
- rta_len
);
922 attr
= RTA_NEXT(attr
, attrlen
);
927 static void hostapd_wireless_event_receive(int sock
, void *eloop_ctx
,
932 struct sockaddr_nl from
;
935 struct hostap_driver_data
*drv
= eloop_ctx
;
937 fromlen
= sizeof(from
);
938 left
= recvfrom(sock
, buf
, sizeof(buf
), MSG_DONTWAIT
,
939 (struct sockaddr
*) &from
, &fromlen
);
941 if (errno
!= EINTR
&& errno
!= EAGAIN
)
942 perror("recvfrom(netlink)");
946 h
= (struct nlmsghdr
*) buf
;
947 while (left
>= (int) sizeof(*h
)) {
951 plen
= len
- sizeof(*h
);
952 if (len
> left
|| plen
< 0) {
953 printf("Malformed netlink message: "
954 "len=%d left=%d plen=%d\n",
959 switch (h
->nlmsg_type
) {
961 hostapd_wireless_event_rtm_newlink(drv
, h
, plen
);
965 len
= NLMSG_ALIGN(len
);
967 h
= (struct nlmsghdr
*) ((char *) h
+ len
);
971 printf("%d extra bytes in the end of netlink message\n", left
);
976 static int hostap_get_we_version(struct hostap_driver_data
*drv
)
978 struct iw_range
*range
;
986 * Use larger buffer than struct iw_range in order to allow the
987 * structure to grow in the future.
989 buflen
= sizeof(struct iw_range
) + 500;
990 range
= os_zalloc(buflen
);
994 memset(&iwr
, 0, sizeof(iwr
));
995 os_strlcpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
996 iwr
.u
.data
.pointer
= (caddr_t
) range
;
997 iwr
.u
.data
.length
= buflen
;
999 minlen
= ((char *) &range
->enc_capa
) - (char *) range
+
1000 sizeof(range
->enc_capa
);
1002 if (ioctl(drv
->ioctl_sock
, SIOCGIWRANGE
, &iwr
) < 0) {
1003 perror("ioctl[SIOCGIWRANGE]");
1006 } else if (iwr
.u
.data
.length
>= minlen
&&
1007 range
->we_version_compiled
>= 18) {
1008 wpa_printf(MSG_DEBUG
, "SIOCGIWRANGE: WE(compiled)=%d "
1009 "WE(source)=%d enc_capa=0x%x",
1010 range
->we_version_compiled
,
1011 range
->we_version_source
,
1013 drv
->we_version
= range
->we_version_compiled
;
1021 static int hostap_wireless_event_init(void *priv
)
1023 struct hostap_driver_data
*drv
= priv
;
1025 struct sockaddr_nl local
;
1027 hostap_get_we_version(drv
);
1029 drv
->wext_sock
= -1;
1031 s
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_ROUTE
);
1033 perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
1037 memset(&local
, 0, sizeof(local
));
1038 local
.nl_family
= AF_NETLINK
;
1039 local
.nl_groups
= RTMGRP_LINK
;
1040 if (bind(s
, (struct sockaddr
*) &local
, sizeof(local
)) < 0) {
1041 perror("bind(netlink)");
1046 eloop_register_read_sock(s
, hostapd_wireless_event_receive
, drv
,
1054 static void hostap_wireless_event_deinit(void *priv
)
1056 struct hostap_driver_data
*drv
= priv
;
1057 if (drv
->wext_sock
< 0)
1059 eloop_unregister_read_sock(drv
->wext_sock
);
1060 close(drv
->wext_sock
);
1064 static void * hostap_init(struct hostapd_data
*hapd
)
1066 struct hostap_driver_data
*drv
;
1068 drv
= os_zalloc(sizeof(struct hostap_driver_data
));
1070 printf("Could not allocate memory for hostapd driver data\n");
1075 drv
->ioctl_sock
= drv
->sock
= -1;
1076 memcpy(drv
->iface
, hapd
->conf
->iface
, sizeof(drv
->iface
));
1078 drv
->ioctl_sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
1079 if (drv
->ioctl_sock
< 0) {
1080 perror("socket[PF_INET,SOCK_DGRAM]");
1085 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD
, 1)) {
1086 printf("Could not enable hostapd mode for interface %s\n",
1088 close(drv
->ioctl_sock
);
1093 if (hapd
->conf
->assoc_ap
&&
1094 hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD_STA
, 1)) {
1095 printf("Could not enable hostapd STA mode for interface %s\n",
1097 close(drv
->ioctl_sock
);
1102 if (hostap_init_sockets(drv
)) {
1103 close(drv
->ioctl_sock
);
1112 static void hostap_driver_deinit(void *priv
)
1114 struct hostap_driver_data
*drv
= priv
;
1116 (void) hostap_set_iface_flags(drv
, 0);
1117 (void) hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD
, 0);
1118 (void) hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD_STA
, 0);
1120 if (drv
->ioctl_sock
>= 0)
1121 close(drv
->ioctl_sock
);
1126 os_free(drv
->generic_ie
);
1132 static int hostap_sta_deauth(void *priv
, const u8
*addr
, int reason
)
1134 struct hostap_driver_data
*drv
= priv
;
1135 struct ieee80211_mgmt mgmt
;
1137 memset(&mgmt
, 0, sizeof(mgmt
));
1138 mgmt
.frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
1139 WLAN_FC_STYPE_DEAUTH
);
1140 memcpy(mgmt
.da
, addr
, ETH_ALEN
);
1141 memcpy(mgmt
.sa
, drv
->hapd
->own_addr
, ETH_ALEN
);
1142 memcpy(mgmt
.bssid
, drv
->hapd
->own_addr
, ETH_ALEN
);
1143 mgmt
.u
.deauth
.reason_code
= host_to_le16(reason
);
1144 return hostap_send_mgmt_frame(drv
, &mgmt
, IEEE80211_HDRLEN
+
1145 sizeof(mgmt
.u
.deauth
), 0);
1149 static int hostap_sta_disassoc(void *priv
, const u8
*addr
, int reason
)
1151 struct hostap_driver_data
*drv
= priv
;
1152 struct ieee80211_mgmt mgmt
;
1154 memset(&mgmt
, 0, sizeof(mgmt
));
1155 mgmt
.frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
1156 WLAN_FC_STYPE_DISASSOC
);
1157 memcpy(mgmt
.da
, addr
, ETH_ALEN
);
1158 memcpy(mgmt
.sa
, drv
->hapd
->own_addr
, ETH_ALEN
);
1159 memcpy(mgmt
.bssid
, drv
->hapd
->own_addr
, ETH_ALEN
);
1160 mgmt
.u
.disassoc
.reason_code
= host_to_le16(reason
);
1161 return hostap_send_mgmt_frame(drv
, &mgmt
, IEEE80211_HDRLEN
+
1162 sizeof(mgmt
.u
.disassoc
), 0);
1166 static struct hostapd_hw_modes
* hostap_get_hw_feature_data(void *priv
,
1170 struct hostapd_hw_modes
*mode
;
1172 const short chan2freq
[14] = {
1173 2412, 2417, 2422, 2427, 2432, 2437, 2442,
1174 2447, 2452, 2457, 2462, 2467, 2472, 2484
1177 mode
= os_zalloc(sizeof(struct hostapd_hw_modes
));
1184 mode
->mode
= HOSTAPD_MODE_IEEE80211B
;
1185 mode
->num_channels
= 14;
1186 mode
->num_rates
= 4;
1188 clen
= mode
->num_channels
* sizeof(struct hostapd_channel_data
);
1189 rlen
= mode
->num_rates
* sizeof(struct hostapd_rate_data
);
1191 mode
->channels
= os_zalloc(clen
);
1192 mode
->rates
= os_zalloc(rlen
);
1193 if (mode
->channels
== NULL
|| mode
->rates
== NULL
) {
1194 hostapd_free_hw_features(mode
, *num_modes
);
1198 for (i
= 0; i
< 14; i
++) {
1199 mode
->channels
[i
].chan
= i
+ 1;
1200 mode
->channels
[i
].freq
= chan2freq
[i
];
1203 mode
->rates
[0].rate
= 10;
1204 mode
->rates
[0].flags
= HOSTAPD_RATE_CCK
;
1205 mode
->rates
[1].rate
= 20;
1206 mode
->rates
[1].flags
= HOSTAPD_RATE_CCK
;
1207 mode
->rates
[2].rate
= 55;
1208 mode
->rates
[2].flags
= HOSTAPD_RATE_CCK
;
1209 mode
->rates
[3].rate
= 110;
1210 mode
->rates
[3].flags
= HOSTAPD_RATE_CCK
;
1216 const struct wpa_driver_ops wpa_driver_hostap_ops
= {
1218 .init
= hostap_init
,
1219 .deinit
= hostap_driver_deinit
,
1220 .wireless_event_init
= hostap_wireless_event_init
,
1221 .wireless_event_deinit
= hostap_wireless_event_deinit
,
1222 .set_ieee8021x
= hostap_set_ieee8021x
,
1223 .set_privacy
= hostap_set_privacy
,
1224 .set_encryption
= hostap_set_encryption
,
1225 .get_seqnum
= hostap_get_seqnum
,
1226 .flush
= hostap_flush
,
1227 .set_generic_elem
= hostap_set_generic_elem
,
1228 .read_sta_data
= hostap_read_sta_data
,
1229 .send_eapol
= hostap_send_eapol
,
1230 .sta_set_flags
= hostap_sta_set_flags
,
1231 .sta_deauth
= hostap_sta_deauth
,
1232 .sta_disassoc
= hostap_sta_disassoc
,
1233 .sta_remove
= hostap_sta_remove
,
1234 .set_ssid
= hostap_set_ssid
,
1235 .send_mgmt_frame
= hostap_send_mgmt_frame
,
1236 .set_assoc_ap
= hostap_set_assoc_ap
,
1237 .sta_add
= hostap_sta_add
,
1238 .get_inact_sec
= hostap_get_inact_sec
,
1239 .sta_clear_stats
= hostap_sta_clear_stats
,
1240 .get_hw_feature_data
= hostap_get_hw_feature_data
,