2 * hostapd / Kernel driver communication with Linux Host AP driver
3 * Copyright (c) 2002-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 #ifdef USE_KERNEL_HEADERS
19 #include <asm/types.h>
20 #include <linux/if_packet.h>
21 #include <linux/if_ether.h> /* The L2 protocols */
22 #include <linux/if_arp.h>
23 #include <linux/wireless.h>
24 #else /* USE_KERNEL_HEADERS */
25 #include <net/if_arp.h>
26 #include <netpacket/packet.h>
27 #include "wireless_copy.h"
28 #endif /* USE_KERNEL_HEADERS */
32 #include "ieee802_1x.h"
34 #include "priv_netlink.h"
35 #include "ieee802_11.h"
37 #include "hostap_common.h"
38 #include "hw_features.h"
41 struct hostap_driver_data
{
42 struct driver_ops ops
;
43 struct hostapd_data
*hapd
;
45 char iface
[IFNAMSIZ
+ 1];
46 int sock
; /* raw packet socket for driver access */
47 int ioctl_sock
; /* socket for ioctl() use */
48 int wext_sock
; /* socket for wireless events */
53 static const struct driver_ops hostap_driver_ops
;
56 static int hostapd_ioctl(void *priv
, struct prism2_hostapd_param
*param
,
58 static int hostap_set_iface_flags(void *priv
, int dev_up
);
60 static void handle_data(struct hostapd_data
*hapd
, u8
*buf
, size_t len
,
63 struct ieee80211_hdr
*hdr
;
69 if (len
< sizeof(struct ieee80211_hdr
))
72 hdr
= (struct ieee80211_hdr
*) buf
;
73 fc
= le_to_host16(hdr
->frame_control
);
75 if ((fc
& (WLAN_FC_FROMDS
| WLAN_FC_TODS
)) != WLAN_FC_TODS
) {
76 printf("Not ToDS data frame (fc=0x%04x)\n", fc
);
81 sta
= ap_get_sta(hapd
, sa
);
82 if (!sta
|| !(sta
->flags
& WLAN_STA_ASSOC
)) {
83 printf("Data frame from not associated STA " MACSTR
"\n",
85 if (sta
&& (sta
->flags
& WLAN_STA_AUTH
))
88 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA
);
92 WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA
);
96 pos
= (u8
*) (hdr
+ 1);
97 left
= len
- sizeof(*hdr
);
99 if (left
< sizeof(rfc1042_header
)) {
100 printf("Too short data frame\n");
104 if (memcmp(pos
, rfc1042_header
, sizeof(rfc1042_header
)) != 0) {
105 printf("Data frame with no RFC1042 header\n");
108 pos
+= sizeof(rfc1042_header
);
109 left
-= sizeof(rfc1042_header
);
112 printf("No ethertype in data frame\n");
116 ethertype
= *pos
++ << 8;
121 ieee802_1x_receive(hapd
, sa
, pos
, left
);
125 printf("Unknown ethertype 0x%04x in data frame\n", ethertype
);
131 static void handle_tx_callback(struct hostapd_data
*hapd
, u8
*buf
, size_t len
,
134 struct ieee80211_hdr
*hdr
;
136 struct sta_info
*sta
;
138 hdr
= (struct ieee80211_hdr
*) buf
;
139 fc
= le_to_host16(hdr
->frame_control
);
141 type
= WLAN_FC_GET_TYPE(fc
);
142 stype
= WLAN_FC_GET_STYPE(fc
);
145 case WLAN_FC_TYPE_MGMT
:
146 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
,
147 "MGMT (TX callback) %s\n", ok
? "ACK" : "fail");
148 ieee802_11_mgmt_cb(hapd
, buf
, len
, stype
, ok
);
150 case WLAN_FC_TYPE_CTRL
:
151 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
,
152 "CTRL (TX callback) %s\n", ok
? "ACK" : "fail");
154 case WLAN_FC_TYPE_DATA
:
155 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
,
156 "DATA (TX callback) %s\n", ok
? "ACK" : "fail");
157 sta
= ap_get_sta(hapd
, hdr
->addr1
);
158 if (sta
&& sta
->flags
& WLAN_STA_PENDING_POLL
) {
159 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
, "STA " MACSTR
160 " %s pending activity poll\n",
162 ok
? "ACKed" : "did not ACK");
164 sta
->flags
&= ~WLAN_STA_PENDING_POLL
;
167 ieee802_1x_tx_status(hapd
, sta
, buf
, len
, ok
);
170 printf("unknown TX callback frame type %d\n", type
);
176 static void handle_frame(struct hostapd_data
*hapd
, u8
*buf
, size_t len
)
178 struct ieee80211_hdr
*hdr
;
179 u16 fc
, extra_len
, type
, stype
;
180 unsigned char *extra
= NULL
;
181 size_t data_len
= len
;
184 /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass
185 * these to user space */
187 HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE
, "handle_frame: too short "
188 "(%lu)\n", (unsigned long) len
);
192 hdr
= (struct ieee80211_hdr
*) buf
;
193 fc
= le_to_host16(hdr
->frame_control
);
194 type
= WLAN_FC_GET_TYPE(fc
);
195 stype
= WLAN_FC_GET_STYPE(fc
);
197 if (type
!= WLAN_FC_TYPE_MGMT
|| stype
!= WLAN_FC_STYPE_BEACON
||
198 hapd
->conf
->debug
>= HOSTAPD_DEBUG_EXCESSIVE
) {
199 wpa_hexdump(MSG_MSGDUMP
, "Received management frrame",
203 ver
= fc
& WLAN_FC_PVER
;
205 /* protocol version 3 is reserved for indicating extra data after the
206 * payload, version 2 for indicating ACKed frame (TX callbacks), and
207 * version 1 for indicating failed frame (no ACK, TX callbacks) */
209 u8
*pos
= buf
+ len
- 2;
210 extra_len
= (u16
) pos
[1] << 8 | pos
[0];
211 printf("extra data in frame (elen=%d)\n", extra_len
);
212 if ((size_t) extra_len
+ 2 > len
) {
213 printf(" extra data overflow\n");
216 len
-= extra_len
+ 2;
218 } else if (ver
== 1 || ver
== 2) {
219 handle_tx_callback(hapd
, buf
, data_len
, ver
== 2 ? 1 : 0);
221 } else if (ver
!= 0) {
222 printf("unknown protocol version %d\n", ver
);
227 case WLAN_FC_TYPE_MGMT
:
228 HOSTAPD_DEBUG(stype
== WLAN_FC_STYPE_BEACON
?
229 HOSTAPD_DEBUG_EXCESSIVE
: HOSTAPD_DEBUG_VERBOSE
,
231 ieee802_11_mgmt(hapd
, buf
, data_len
, stype
, NULL
);
233 case WLAN_FC_TYPE_CTRL
:
234 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
, "CTRL\n");
236 case WLAN_FC_TYPE_DATA
:
237 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
, "DATA\n");
238 handle_data(hapd
, buf
, data_len
, stype
);
241 printf("unknown frame type %d\n", type
);
247 static void handle_read(int sock
, void *eloop_ctx
, void *sock_ctx
)
249 struct hostapd_data
*hapd
= (struct hostapd_data
*) eloop_ctx
;
251 unsigned char buf
[3000];
253 len
= recv(sock
, buf
, sizeof(buf
), 0);
259 handle_frame(hapd
, buf
, len
);
263 static int hostap_init_sockets(struct hostap_driver_data
*drv
)
265 struct hostapd_data
*hapd
= drv
->hapd
;
267 struct sockaddr_ll addr
;
269 drv
->sock
= socket(PF_PACKET
, SOCK_RAW
, htons(ETH_P_ALL
));
271 perror("socket[PF_PACKET,SOCK_RAW]");
275 if (eloop_register_read_sock(drv
->sock
, handle_read
, drv
->hapd
, NULL
))
277 printf("Could not register read socket\n");
281 memset(&ifr
, 0, sizeof(ifr
));
282 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%sap", drv
->iface
);
283 if (ioctl(drv
->sock
, SIOCGIFINDEX
, &ifr
) != 0) {
284 perror("ioctl(SIOCGIFINDEX)");
288 if (hostap_set_iface_flags(drv
, 1)) {
292 memset(&addr
, 0, sizeof(addr
));
293 addr
.sll_family
= AF_PACKET
;
294 addr
.sll_ifindex
= ifr
.ifr_ifindex
;
295 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
,
296 "Opening raw packet socket for ifindex %d\n",
299 if (bind(drv
->sock
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
304 memset(&ifr
, 0, sizeof(ifr
));
305 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s", drv
->iface
);
306 if (ioctl(drv
->sock
, SIOCGIFHWADDR
, &ifr
) != 0) {
307 perror("ioctl(SIOCGIFHWADDR)");
311 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) {
312 printf("Invalid HW-addr family 0x%04x\n",
313 ifr
.ifr_hwaddr
.sa_family
);
316 memcpy(drv
->hapd
->own_addr
, ifr
.ifr_hwaddr
.sa_data
, ETH_ALEN
);
322 static int hostap_send_mgmt_frame(void *priv
, const void *msg
, size_t len
,
325 struct hostap_driver_data
*drv
= priv
;
327 return send(drv
->sock
, msg
, len
, flags
);
331 static int hostap_send_eapol(void *priv
, const u8
*addr
, const u8
*data
,
332 size_t data_len
, int encrypt
, const u8
*own_addr
)
334 struct hostap_driver_data
*drv
= priv
;
335 struct ieee80211_hdr
*hdr
;
340 len
= sizeof(*hdr
) + sizeof(rfc1042_header
) + 2 + data_len
;
341 hdr
= wpa_zalloc(len
);
343 printf("malloc() failed for hostapd_send_data(len=%lu)\n",
344 (unsigned long) len
);
349 IEEE80211_FC(WLAN_FC_TYPE_DATA
, WLAN_FC_STYPE_DATA
);
350 hdr
->frame_control
|= host_to_le16(WLAN_FC_FROMDS
);
351 /* Request TX callback */
352 hdr
->frame_control
|= host_to_le16(BIT(1));
354 hdr
->frame_control
|= host_to_le16(WLAN_FC_ISWEP
);
355 memcpy(hdr
->IEEE80211_DA_FROMDS
, addr
, ETH_ALEN
);
356 memcpy(hdr
->IEEE80211_BSSID_FROMDS
, own_addr
, ETH_ALEN
);
357 memcpy(hdr
->IEEE80211_SA_FROMDS
, own_addr
, ETH_ALEN
);
359 pos
= (u8
*) (hdr
+ 1);
360 memcpy(pos
, rfc1042_header
, sizeof(rfc1042_header
));
361 pos
+= sizeof(rfc1042_header
);
362 *((u16
*) pos
) = htons(ETH_P_PAE
);
364 memcpy(pos
, data
, data_len
);
366 res
= hostap_send_mgmt_frame(drv
, (u8
*) hdr
, len
, 0);
370 perror("hostapd_send_eapol: send");
371 printf("hostapd_send_eapol - packet len: %lu - failed\n",
372 (unsigned long) len
);
379 static int hostap_sta_set_flags(void *priv
, const u8
*addr
,
380 int flags_or
, int flags_and
)
382 struct hostap_driver_data
*drv
= priv
;
383 struct prism2_hostapd_param param
;
385 memset(¶m
, 0, sizeof(param
));
386 param
.cmd
= PRISM2_HOSTAPD_SET_FLAGS_STA
;
387 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
388 param
.u
.set_flags_sta
.flags_or
= flags_or
;
389 param
.u
.set_flags_sta
.flags_and
= flags_and
;
390 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
394 static int hostap_set_iface_flags(void *priv
, int dev_up
)
396 struct hostap_driver_data
*drv
= priv
;
399 if (drv
->ioctl_sock
< 0)
402 memset(&ifr
, 0, sizeof(ifr
));
403 snprintf(ifr
.ifr_name
, IFNAMSIZ
, "%sap", drv
->iface
);
405 if (ioctl(drv
->ioctl_sock
, SIOCGIFFLAGS
, &ifr
) != 0) {
406 perror("ioctl[SIOCGIFFLAGS]");
411 ifr
.ifr_flags
|= IFF_UP
;
413 ifr
.ifr_flags
&= ~IFF_UP
;
415 if (ioctl(drv
->ioctl_sock
, SIOCSIFFLAGS
, &ifr
) != 0) {
416 perror("ioctl[SIOCSIFFLAGS]");
421 memset(&ifr
, 0, sizeof(ifr
));
422 snprintf(ifr
.ifr_name
, IFNAMSIZ
, "%sap", drv
->iface
);
423 ifr
.ifr_mtu
= HOSTAPD_MTU
;
424 if (ioctl(drv
->ioctl_sock
, SIOCSIFMTU
, &ifr
) != 0) {
425 perror("ioctl[SIOCSIFMTU]");
426 printf("Setting MTU failed - trying to survive with "
435 static int hostapd_ioctl(void *priv
, struct prism2_hostapd_param
*param
,
438 struct hostap_driver_data
*drv
= priv
;
441 memset(&iwr
, 0, sizeof(iwr
));
442 strncpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
443 iwr
.u
.data
.pointer
= (caddr_t
) param
;
444 iwr
.u
.data
.length
= len
;
446 if (ioctl(drv
->ioctl_sock
, PRISM2_IOCTL_HOSTAPD
, &iwr
) < 0) {
447 perror("ioctl[PRISM2_IOCTL_HOSTAPD]");
455 static int hostap_set_encryption(const char *ifname
, void *priv
,
456 const char *alg
, const u8
*addr
,
457 int idx
, const u8
*key
, size_t key_len
,
460 struct hostap_driver_data
*drv
= priv
;
461 struct prism2_hostapd_param
*param
;
466 blen
= sizeof(*param
) + key_len
;
467 buf
= wpa_zalloc(blen
);
471 param
= (struct prism2_hostapd_param
*) buf
;
472 param
->cmd
= PRISM2_SET_ENCRYPTION
;
474 memset(param
->sta_addr
, 0xff, ETH_ALEN
);
476 memcpy(param
->sta_addr
, addr
, ETH_ALEN
);
477 strncpy((char *) param
->u
.crypt
.alg
, alg
, HOSTAP_CRYPT_ALG_NAME_LEN
);
478 param
->u
.crypt
.flags
= txkey
? HOSTAP_CRYPT_FLAG_SET_TX_KEY
: 0;
479 param
->u
.crypt
.idx
= idx
;
480 param
->u
.crypt
.key_len
= key_len
;
481 memcpy((u8
*) (param
+ 1), key
, key_len
);
483 if (hostapd_ioctl(drv
, param
, blen
)) {
484 printf("Failed to set encryption.\n");
493 static int hostap_get_seqnum(const char *ifname
, void *priv
, const u8
*addr
,
496 struct hostap_driver_data
*drv
= priv
;
497 struct prism2_hostapd_param
*param
;
502 blen
= sizeof(*param
) + 32;
503 buf
= wpa_zalloc(blen
);
507 param
= (struct prism2_hostapd_param
*) buf
;
508 param
->cmd
= PRISM2_GET_ENCRYPTION
;
510 memset(param
->sta_addr
, 0xff, ETH_ALEN
);
512 memcpy(param
->sta_addr
, addr
, ETH_ALEN
);
513 param
->u
.crypt
.idx
= idx
;
515 if (hostapd_ioctl(drv
, param
, blen
)) {
516 printf("Failed to get encryption.\n");
519 memcpy(seq
, param
->u
.crypt
.seq
, 8);
527 static int hostap_ioctl_prism2param(void *priv
, int param
, int value
)
529 struct hostap_driver_data
*drv
= priv
;
533 memset(&iwr
, 0, sizeof(iwr
));
534 strncpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
535 i
= (int *) iwr
.u
.name
;
539 if (ioctl(drv
->ioctl_sock
, PRISM2_IOCTL_PRISM2_PARAM
, &iwr
) < 0) {
540 perror("ioctl[PRISM2_IOCTL_PRISM2_PARAM]");
548 static int hostap_set_ieee8021x(const char *ifname
, void *priv
, int enabled
)
550 struct hostap_driver_data
*drv
= priv
;
552 /* enable kernel driver support for IEEE 802.1X */
553 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_IEEE_802_1X
, enabled
)) {
554 printf("Could not setup IEEE 802.1X support in kernel driver."
562 /* use host driver implementation of encryption to allow
563 * individual keys and passing plaintext EAPOL frames */
564 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOST_DECRYPT
, 1) ||
565 hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOST_ENCRYPT
, 1)) {
566 printf("Could not setup host-based encryption in kernel "
575 static int hostap_set_privacy(const char *ifname
, void *priv
, int enabled
)
577 struct hostap_drvier_data
*drv
= priv
;
579 return hostap_ioctl_prism2param(drv
, PRISM2_PARAM_PRIVACY_INVOKED
,
584 static int hostap_set_ssid(const char *ifname
, void *priv
, const u8
*buf
,
587 struct hostap_driver_data
*drv
= priv
;
590 memset(&iwr
, 0, sizeof(iwr
));
591 strncpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
592 iwr
.u
.essid
.flags
= 1; /* SSID active */
593 iwr
.u
.essid
.pointer
= (caddr_t
) buf
;
594 iwr
.u
.essid
.length
= len
+ 1;
596 if (ioctl(drv
->ioctl_sock
, SIOCSIWESSID
, &iwr
) < 0) {
597 perror("ioctl[SIOCSIWESSID]");
598 printf("len=%d\n", len
);
606 static int hostap_flush(void *priv
)
608 struct hostap_driver_data
*drv
= priv
;
609 struct prism2_hostapd_param param
;
611 memset(¶m
, 0, sizeof(param
));
612 param
.cmd
= PRISM2_HOSTAPD_FLUSH
;
613 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
617 static int hostap_read_sta_data(void *priv
,
618 struct hostap_sta_driver_data
*data
,
621 struct hostap_driver_data
*drv
= priv
;
622 char buf
[1024], line
[128], *pos
;
626 memset(data
, 0, sizeof(*data
));
627 snprintf(buf
, sizeof(buf
), "/proc/net/hostap/%s/" MACSTR
,
628 drv
->iface
, MAC2STR(addr
));
633 /* Need to read proc file with in one piece, so use large enough
635 setbuffer(f
, buf
, sizeof(buf
));
637 while (fgets(line
, sizeof(line
), f
)) {
638 pos
= strchr(line
, '=');
642 val
= strtoul(pos
, NULL
, 10);
643 if (strcmp(line
, "rx_packets") == 0)
644 data
->rx_packets
= val
;
645 else if (strcmp(line
, "tx_packets") == 0)
646 data
->tx_packets
= val
;
647 else if (strcmp(line
, "rx_bytes") == 0)
648 data
->rx_bytes
= val
;
649 else if (strcmp(line
, "tx_bytes") == 0)
650 data
->tx_bytes
= val
;
659 static int hostap_sta_add(const char *ifname
, void *priv
, const u8
*addr
,
660 u16 aid
, u16 capability
, u8
*supp_rates
,
661 size_t supp_rates_len
, int flags
)
663 struct hostap_driver_data
*drv
= priv
;
664 struct prism2_hostapd_param param
;
665 int tx_supp_rates
= 0;
668 #define WLAN_RATE_1M BIT(0)
669 #define WLAN_RATE_2M BIT(1)
670 #define WLAN_RATE_5M5 BIT(2)
671 #define WLAN_RATE_11M BIT(3)
673 for (i
= 0; i
< supp_rates_len
; i
++) {
674 if ((supp_rates
[i
] & 0x7f) == 2)
675 tx_supp_rates
|= WLAN_RATE_1M
;
676 if ((supp_rates
[i
] & 0x7f) == 4)
677 tx_supp_rates
|= WLAN_RATE_2M
;
678 if ((supp_rates
[i
] & 0x7f) == 11)
679 tx_supp_rates
|= WLAN_RATE_5M5
;
680 if ((supp_rates
[i
] & 0x7f) == 22)
681 tx_supp_rates
|= WLAN_RATE_11M
;
684 memset(¶m
, 0, sizeof(param
));
685 param
.cmd
= PRISM2_HOSTAPD_ADD_STA
;
686 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
687 param
.u
.add_sta
.aid
= aid
;
688 param
.u
.add_sta
.capability
= capability
;
689 param
.u
.add_sta
.tx_supp_rates
= tx_supp_rates
;
690 return hostapd_ioctl(drv
, ¶m
, sizeof(param
));
694 static int hostap_sta_remove(void *priv
, const u8
*addr
)
696 struct hostap_driver_data
*drv
= priv
;
697 struct prism2_hostapd_param param
;
699 hostap_sta_set_flags(drv
, addr
, 0, ~WLAN_STA_AUTHORIZED
);
701 memset(¶m
, 0, sizeof(param
));
702 param
.cmd
= PRISM2_HOSTAPD_REMOVE_STA
;
703 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
704 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
705 printf("Could not remove station from kernel driver.\n");
712 static int hostap_get_inact_sec(void *priv
, const u8
*addr
)
714 struct hostap_driver_data
*drv
= priv
;
715 struct prism2_hostapd_param param
;
717 memset(¶m
, 0, sizeof(param
));
718 param
.cmd
= PRISM2_HOSTAPD_GET_INFO_STA
;
719 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
720 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
724 return param
.u
.get_info_sta
.inactive_sec
;
728 static int hostap_sta_clear_stats(void *priv
, const u8
*addr
)
730 struct hostap_driver_data
*drv
= priv
;
731 struct prism2_hostapd_param param
;
733 memset(¶m
, 0, sizeof(param
));
734 param
.cmd
= PRISM2_HOSTAPD_STA_CLEAR_STATS
;
735 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
736 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
))) {
744 static int hostap_set_assoc_ap(void *priv
, const u8
*addr
)
746 struct hostap_driver_data
*drv
= priv
;
747 struct prism2_hostapd_param param
;
749 memset(¶m
, 0, sizeof(param
));
750 param
.cmd
= PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR
;
751 memcpy(param
.sta_addr
, addr
, ETH_ALEN
);
752 if (hostapd_ioctl(drv
, ¶m
, sizeof(param
)))
759 static int hostap_set_generic_elem(const char *ifname
, void *priv
,
760 const u8
*elem
, size_t elem_len
)
762 struct hostap_driver_data
*drv
= priv
;
763 struct prism2_hostapd_param
*param
;
765 size_t blen
= PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN
+ elem_len
;
766 if (blen
< sizeof(*param
))
767 blen
= sizeof(*param
);
769 param
= wpa_zalloc(blen
);
773 param
->cmd
= PRISM2_HOSTAPD_SET_GENERIC_ELEMENT
;
774 param
->u
.generic_elem
.len
= elem_len
;
775 memcpy(param
->u
.generic_elem
.data
, elem
, elem_len
);
776 res
= hostapd_ioctl(drv
, param
, blen
);
785 hostapd_wireless_event_wireless_custom(struct hostap_driver_data
*drv
,
788 struct hostapd_data
*hapd
= drv
->hapd
;
790 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
, "Custom wireless event: '%s'\n",
793 if (strncmp(custom
, "MLME-MICHAELMICFAILURE.indication", 33) == 0) {
796 pos
= strstr(custom
, "addr=");
798 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
,
799 "MLME-MICHAELMICFAILURE.indication "
800 "without sender address ignored\n");
804 if (hwaddr_aton(pos
, addr
) == 0) {
805 ieee80211_michael_mic_failure(drv
->hapd
, addr
, 1);
807 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
,
808 "MLME-MICHAELMICFAILURE.indication "
809 "with invalid MAC address");
815 static void hostapd_wireless_event_wireless(struct hostap_driver_data
*drv
,
818 struct hostapd_data
*hapd
= drv
->hapd
;
819 struct iw_event iwe_buf
, *iwe
= &iwe_buf
;
820 char *pos
, *end
, *custom
, *buf
;
825 while (pos
+ IW_EV_LCP_LEN
<= end
) {
826 /* Event data may be unaligned, so make a local, aligned copy
827 * before processing. */
828 memcpy(&iwe_buf
, pos
, IW_EV_LCP_LEN
);
829 HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE
, "Wireless event: "
830 "cmd=0x%x len=%d\n", iwe
->cmd
, iwe
->len
);
831 if (iwe
->len
<= IW_EV_LCP_LEN
)
834 custom
= pos
+ IW_EV_POINT_LEN
;
835 if (drv
->we_version
> 18 &&
836 (iwe
->cmd
== IWEVMICHAELMICFAILURE
||
837 iwe
->cmd
== IWEVCUSTOM
)) {
838 /* WE-19 removed the pointer from struct iw_point */
839 char *dpos
= (char *) &iwe_buf
.u
.data
.length
;
840 int dlen
= dpos
- (char *) &iwe_buf
;
841 memcpy(dpos
, pos
+ IW_EV_LCP_LEN
,
842 sizeof(struct iw_event
) - dlen
);
844 memcpy(&iwe_buf
, pos
, sizeof(struct iw_event
));
845 custom
+= IW_EV_POINT_OFF
;
850 if (custom
+ iwe
->u
.data
.length
> end
)
852 buf
= malloc(iwe
->u
.data
.length
+ 1);
855 memcpy(buf
, custom
, iwe
->u
.data
.length
);
856 buf
[iwe
->u
.data
.length
] = '\0';
857 hostapd_wireless_event_wireless_custom(drv
, buf
);
867 static void hostapd_wireless_event_rtm_newlink(struct hostap_driver_data
*drv
,
868 struct nlmsghdr
*h
, int len
)
870 struct ifinfomsg
*ifi
;
871 int attrlen
, nlmsg_len
, rta_len
;
872 struct rtattr
* attr
;
874 if (len
< (int) sizeof(*ifi
))
879 /* TODO: use ifi->ifi_index to filter out wireless events from other
882 nlmsg_len
= NLMSG_ALIGN(sizeof(struct ifinfomsg
));
884 attrlen
= h
->nlmsg_len
- nlmsg_len
;
888 attr
= (struct rtattr
*) (((char *) ifi
) + nlmsg_len
);
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 void hostapd_wireless_event_receive(int sock
, void *eloop_ctx
,
907 struct sockaddr_nl from
;
910 struct hostap_driver_data
*drv
= eloop_ctx
;
912 fromlen
= sizeof(from
);
913 left
= recvfrom(sock
, buf
, sizeof(buf
), MSG_DONTWAIT
,
914 (struct sockaddr
*) &from
, &fromlen
);
916 if (errno
!= EINTR
&& errno
!= EAGAIN
)
917 perror("recvfrom(netlink)");
921 h
= (struct nlmsghdr
*) buf
;
922 while (left
>= (int) sizeof(*h
)) {
926 plen
= len
- sizeof(*h
);
927 if (len
> left
|| plen
< 0) {
928 printf("Malformed netlink message: "
929 "len=%d left=%d plen=%d\n",
934 switch (h
->nlmsg_type
) {
936 hostapd_wireless_event_rtm_newlink(drv
, h
, plen
);
940 len
= NLMSG_ALIGN(len
);
942 h
= (struct nlmsghdr
*) ((char *) h
+ len
);
946 printf("%d extra bytes in the end of netlink message\n", left
);
951 static int hostap_get_we_version(struct hostap_driver_data
*drv
)
953 struct iw_range
*range
;
961 * Use larger buffer than struct iw_range in order to allow the
962 * structure to grow in the future.
964 buflen
= sizeof(struct iw_range
) + 500;
965 range
= wpa_zalloc(buflen
);
969 memset(&iwr
, 0, sizeof(iwr
));
970 strncpy(iwr
.ifr_name
, drv
->iface
, IFNAMSIZ
);
971 iwr
.u
.data
.pointer
= (caddr_t
) range
;
972 iwr
.u
.data
.length
= buflen
;
974 minlen
= ((char *) &range
->enc_capa
) - (char *) range
+
975 sizeof(range
->enc_capa
);
977 if (ioctl(drv
->ioctl_sock
, SIOCGIWRANGE
, &iwr
) < 0) {
978 perror("ioctl[SIOCGIWRANGE]");
981 } else if (iwr
.u
.data
.length
>= minlen
&&
982 range
->we_version_compiled
>= 18) {
983 wpa_printf(MSG_DEBUG
, "SIOCGIWRANGE: WE(compiled)=%d "
984 "WE(source)=%d enc_capa=0x%x",
985 range
->we_version_compiled
,
986 range
->we_version_source
,
988 drv
->we_version
= range
->we_version_compiled
;
996 static int hostap_wireless_event_init(void *priv
)
998 struct hostap_driver_data
*drv
= priv
;
1000 struct sockaddr_nl local
;
1002 hostap_get_we_version(drv
);
1004 drv
->wext_sock
= -1;
1006 s
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_ROUTE
);
1008 perror("socket(PF_NETLINK,SOCK_RAW,NETLINK_ROUTE)");
1012 memset(&local
, 0, sizeof(local
));
1013 local
.nl_family
= AF_NETLINK
;
1014 local
.nl_groups
= RTMGRP_LINK
;
1015 if (bind(s
, (struct sockaddr
*) &local
, sizeof(local
)) < 0) {
1016 perror("bind(netlink)");
1021 eloop_register_read_sock(s
, hostapd_wireless_event_receive
, drv
,
1029 static void hostap_wireless_event_deinit(void *priv
)
1031 struct hostap_driver_data
*drv
= priv
;
1032 if (drv
->wext_sock
< 0)
1034 eloop_unregister_read_sock(drv
->wext_sock
);
1035 close(drv
->wext_sock
);
1039 static int hostap_init(struct hostapd_data
*hapd
)
1041 struct hostap_driver_data
*drv
;
1043 drv
= wpa_zalloc(sizeof(struct hostap_driver_data
));
1045 printf("Could not allocate memory for hostapd driver data\n");
1049 drv
->ops
= hostap_driver_ops
;
1051 drv
->ioctl_sock
= drv
->sock
= -1;
1052 memcpy(drv
->iface
, hapd
->conf
->iface
, sizeof(drv
->iface
));
1054 drv
->ioctl_sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
1055 if (drv
->ioctl_sock
< 0) {
1056 perror("socket[PF_INET,SOCK_DGRAM]");
1061 if (hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD
, 1)) {
1062 printf("Could not enable hostapd mode for interface %s\n",
1064 close(drv
->ioctl_sock
);
1069 if (hapd
->conf
->assoc_ap
&&
1070 hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD_STA
, 1)) {
1071 printf("Could not enable hostapd STA mode for interface %s\n",
1073 close(drv
->ioctl_sock
);
1078 if (hostap_init_sockets(drv
)) {
1079 close(drv
->ioctl_sock
);
1084 hapd
->driver
= &drv
->ops
;
1089 static void hostap_driver_deinit(void *priv
)
1091 struct hostap_driver_data
*drv
= priv
;
1093 drv
->hapd
->driver
= NULL
;
1095 (void) hostap_set_iface_flags(drv
, 0);
1096 (void) hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD
, 0);
1097 (void) hostap_ioctl_prism2param(drv
, PRISM2_PARAM_HOSTAPD_STA
, 0);
1099 if (drv
->ioctl_sock
>= 0)
1100 close(drv
->ioctl_sock
);
1109 static int hostap_sta_deauth(void *priv
, const u8
*addr
, int reason
)
1111 struct hostap_driver_data
*drv
= priv
;
1112 struct ieee80211_mgmt mgmt
;
1114 memset(&mgmt
, 0, sizeof(mgmt
));
1115 mgmt
.frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
1116 WLAN_FC_STYPE_DEAUTH
);
1117 memcpy(mgmt
.da
, addr
, ETH_ALEN
);
1118 memcpy(mgmt
.sa
, drv
->hapd
->own_addr
, ETH_ALEN
);
1119 memcpy(mgmt
.bssid
, drv
->hapd
->own_addr
, ETH_ALEN
);
1120 mgmt
.u
.deauth
.reason_code
= host_to_le16(reason
);
1121 return hostap_send_mgmt_frame(drv
, &mgmt
, IEEE80211_HDRLEN
+
1122 sizeof(mgmt
.u
.deauth
), 0);
1126 static int hostap_sta_disassoc(void *priv
, const u8
*addr
, int reason
)
1128 struct hostap_driver_data
*drv
= priv
;
1129 struct ieee80211_mgmt mgmt
;
1131 memset(&mgmt
, 0, sizeof(mgmt
));
1132 mgmt
.frame_control
= IEEE80211_FC(WLAN_FC_TYPE_MGMT
,
1133 WLAN_FC_STYPE_DISASSOC
);
1134 memcpy(mgmt
.da
, addr
, ETH_ALEN
);
1135 memcpy(mgmt
.sa
, drv
->hapd
->own_addr
, ETH_ALEN
);
1136 memcpy(mgmt
.bssid
, drv
->hapd
->own_addr
, ETH_ALEN
);
1137 mgmt
.u
.disassoc
.reason_code
= host_to_le16(reason
);
1138 return hostap_send_mgmt_frame(drv
, &mgmt
, IEEE80211_HDRLEN
+
1139 sizeof(mgmt
.u
.disassoc
), 0);
1143 static struct hostapd_hw_modes
* hostap_get_hw_feature_data(void *priv
,
1147 struct hostapd_hw_modes
*mode
;
1149 const short chan2freq
[14] = {
1150 2412, 2417, 2422, 2427, 2432, 2437, 2442,
1151 2447, 2452, 2457, 2462, 2467, 2472, 2484
1154 mode
= wpa_zalloc(sizeof(struct hostapd_hw_modes
));
1161 mode
->mode
= HOSTAPD_MODE_IEEE80211B
;
1162 mode
->num_channels
= 14;
1163 mode
->num_rates
= 4;
1165 clen
= mode
->num_channels
* sizeof(struct hostapd_channel_data
);
1166 rlen
= mode
->num_rates
* sizeof(struct hostapd_rate_data
);
1168 mode
->channels
= wpa_zalloc(clen
);
1169 mode
->rates
= wpa_zalloc(rlen
);
1170 if (mode
->channels
== NULL
|| mode
->rates
== NULL
) {
1171 hostapd_free_hw_features(mode
, *num_modes
);
1175 for (i
= 0; i
< 14; i
++) {
1176 mode
->channels
[i
].chan
= i
+ 1;
1177 mode
->channels
[i
].freq
= chan2freq
[i
];
1180 mode
->rates
[0].rate
= 10;
1181 mode
->rates
[0].flags
= HOSTAPD_RATE_CCK
;
1182 mode
->rates
[1].rate
= 20;
1183 mode
->rates
[1].flags
= HOSTAPD_RATE_CCK
;
1184 mode
->rates
[2].rate
= 55;
1185 mode
->rates
[2].flags
= HOSTAPD_RATE_CCK
;
1186 mode
->rates
[3].rate
= 110;
1187 mode
->rates
[3].flags
= HOSTAPD_RATE_CCK
;
1193 static const struct driver_ops hostap_driver_ops
= {
1195 .init
= hostap_init
,
1196 .deinit
= hostap_driver_deinit
,
1197 .wireless_event_init
= hostap_wireless_event_init
,
1198 .wireless_event_deinit
= hostap_wireless_event_deinit
,
1199 .set_ieee8021x
= hostap_set_ieee8021x
,
1200 .set_privacy
= hostap_set_privacy
,
1201 .set_encryption
= hostap_set_encryption
,
1202 .get_seqnum
= hostap_get_seqnum
,
1203 .flush
= hostap_flush
,
1204 .set_generic_elem
= hostap_set_generic_elem
,
1205 .read_sta_data
= hostap_read_sta_data
,
1206 .send_eapol
= hostap_send_eapol
,
1207 .sta_set_flags
= hostap_sta_set_flags
,
1208 .sta_deauth
= hostap_sta_deauth
,
1209 .sta_disassoc
= hostap_sta_disassoc
,
1210 .sta_remove
= hostap_sta_remove
,
1211 .set_ssid
= hostap_set_ssid
,
1212 .send_mgmt_frame
= hostap_send_mgmt_frame
,
1213 .set_assoc_ap
= hostap_set_assoc_ap
,
1214 .sta_add
= hostap_sta_add
,
1215 .get_inact_sec
= hostap_get_inact_sec
,
1216 .sta_clear_stats
= hostap_sta_clear_stats
,
1217 .get_hw_feature_data
= hostap_get_hw_feature_data
,
1221 void hostap_driver_register(void)
1223 driver_register(hostap_driver_ops
.name
, &hostap_driver_ops
);