2 * Host AP (software wireless LAN access point) user space daemon for
3 * Host AP kernel driver / Kernel driver communication
4 * Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi>
5 * Copyright (c) 2004, Gunter Burchardt <tira@isx.de>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Alternatively, this software may be distributed under the terms of BSD
14 * See README and COPYING for more details.
22 #include <sys/ioctl.h>
23 #include <netinet/in.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
28 #ifdef USE_KERNEL_HEADERS
29 #include <asm/types.h>
30 #include <linux/if_packet.h>
31 #include <linux/if_ether.h> /* The L2 protocols */
32 #include <linux/if_arp.h>
34 #else /* USE_KERNEL_HEADERS */
35 #include <net/if_arp.h>
37 #include <netpacket/packet.h>
38 #endif /* USE_KERNEL_HEADERS */
41 #include "ieee802_1x.h"
45 #include "accounting.h"
48 struct wired_driver_data
{
49 struct driver_ops ops
;
50 struct hostapd_data
*hapd
;
52 int sock
; /* raw packet socket for driver access */
53 int dhcp_sock
; /* socket for dhcp packets */
54 int use_pae_group_addr
;
57 static const struct driver_ops wired_driver_ops
;
60 #define WIRED_EAPOL_MULTICAST_GROUP {0x01,0x80,0xc2,0x00,0x00,0x03}
63 /* TODO: detecting new devices should eventually be changed from using DHCP
64 * snooping to trigger on any packet from a new layer 2 MAC address, e.g.,
65 * based on ebtables, etc. */
83 u_int8_t options
[308]; /* 312 - cookie */
87 static void wired_possible_new_sta(struct hostapd_data
*hapd
, u8
*addr
)
91 sta
= ap_get_sta(hapd
, addr
);
95 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
, "Data frame from unknown STA "
96 MACSTR
" - adding a new STA\n", MAC2STR(addr
));
97 sta
= ap_sta_add(hapd
, addr
);
99 hostapd_new_assoc_sta(hapd
, sta
, 0);
100 accounting_sta_get_id(hapd
, sta
);
102 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
, "Failed to add STA entry "
103 "for " MACSTR
"\n", MAC2STR(addr
));
108 static void handle_data(struct hostapd_data
*hapd
, unsigned char *buf
,
111 struct ieee8023_hdr
*hdr
;
115 /* must contain at least ieee8023_hdr 6 byte source, 6 byte dest,
116 * 2 byte ethertype */
118 HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE
, "handle_data: too short "
119 "(%lu)\n", (unsigned long) len
);
123 hdr
= (struct ieee8023_hdr
*) buf
;
125 switch (ntohs(hdr
->ethertype
)) {
127 HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE
,
128 "Received EAPOL packet\n");
130 wired_possible_new_sta(hapd
, sa
);
132 pos
= (u8
*) (hdr
+ 1);
133 left
= len
- sizeof(*hdr
);
135 ieee802_1x_receive(hapd
, sa
, pos
, left
);
139 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
,
140 "Unknown ethertype 0x%04x in data frame\n",
141 ntohs(hdr
->ethertype
));
147 static void handle_read(int sock
, void *eloop_ctx
, void *sock_ctx
)
149 struct hostapd_data
*hapd
= (struct hostapd_data
*) eloop_ctx
;
151 unsigned char buf
[3000];
153 len
= recv(sock
, buf
, sizeof(buf
), 0);
159 handle_data(hapd
, buf
, len
);
163 static void handle_dhcp(int sock
, void *eloop_ctx
, void *sock_ctx
)
165 struct hostapd_data
*hapd
= (struct hostapd_data
*) eloop_ctx
;
167 unsigned char buf
[3000];
168 struct dhcp_message
*msg
;
171 len
= recv(sock
, buf
, sizeof(buf
), 0);
177 /* must contain at least dhcp_message->chaddr */
179 HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE
, "handle_dhcp: too short "
184 msg
= (struct dhcp_message
*) buf
;
185 mac_address
= (u8
*) &(msg
->chaddr
);
187 HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE
,
188 "Got DHCP broadcast packet from " MACSTR
"\n",
189 MAC2STR(mac_address
));
191 wired_possible_new_sta(hapd
, mac_address
);
195 static int wired_init_sockets(struct wired_driver_data
*drv
)
197 struct hostapd_data
*hapd
= drv
->hapd
;
199 struct sockaddr_ll addr
;
200 struct sockaddr_in addr2
;
201 struct packet_mreq mreq
;
202 u8 multicastgroup_eapol
[6] = WIRED_EAPOL_MULTICAST_GROUP
;
205 drv
->sock
= socket(PF_PACKET
, SOCK_RAW
, htons(ETH_P_PAE
));
207 perror("socket[PF_PACKET,SOCK_RAW]");
211 if (eloop_register_read_sock(drv
->sock
, handle_read
, hapd
, NULL
)) {
212 printf("Could not register read socket\n");
216 memset(&ifr
, 0, sizeof(ifr
));
217 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s",
219 if (ioctl(drv
->sock
, SIOCGIFINDEX
, &ifr
) != 0) {
220 perror("ioctl(SIOCGIFINDEX)");
225 memset(&addr
, 0, sizeof(addr
));
226 addr
.sll_family
= AF_PACKET
;
227 addr
.sll_ifindex
= ifr
.ifr_ifindex
;
228 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
,
229 "Opening raw packet socket for ifindex %d\n",
232 if (bind(drv
->sock
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
237 /* filter multicast address */
238 memset(&mreq
, 0, sizeof(mreq
));
239 mreq
.mr_ifindex
= ifr
.ifr_ifindex
;
240 mreq
.mr_type
= PACKET_MR_MULTICAST
;
242 memcpy(mreq
.mr_address
, multicastgroup_eapol
, mreq
.mr_alen
);
244 if (setsockopt(drv
->sock
, SOL_PACKET
, PACKET_ADD_MEMBERSHIP
, &mreq
,
246 perror("setsockopt[SOL_SOCKET,PACKET_ADD_MEMBERSHIP]");
250 memset(&ifr
, 0, sizeof(ifr
));
251 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s", hapd
->conf
->iface
);
252 if (ioctl(drv
->sock
, SIOCGIFHWADDR
, &ifr
) != 0) {
253 perror("ioctl(SIOCGIFHWADDR)");
257 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) {
258 printf("Invalid HW-addr family 0x%04x\n",
259 ifr
.ifr_hwaddr
.sa_family
);
262 memcpy(hapd
->own_addr
, ifr
.ifr_hwaddr
.sa_data
, ETH_ALEN
);
264 /* setup dhcp listen socket for sta detection */
265 if ((drv
->dhcp_sock
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0) {
266 perror("socket call failed for dhcp");
270 if (eloop_register_read_sock(drv
->dhcp_sock
, handle_dhcp
, hapd
, NULL
))
272 printf("Could not register read socket\n");
276 memset(&addr2
, 0, sizeof(addr2
));
277 addr2
.sin_family
= AF_INET
;
278 addr2
.sin_port
= htons(67);
279 addr2
.sin_addr
.s_addr
= INADDR_ANY
;
281 if (setsockopt(drv
->dhcp_sock
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &n
,
283 perror("setsockopt[SOL_SOCKET,SO_REUSEADDR]");
286 if (setsockopt(drv
->dhcp_sock
, SOL_SOCKET
, SO_BROADCAST
, (char *) &n
,
288 perror("setsockopt[SOL_SOCKET,SO_BROADCAST]");
292 memset(&ifr
, 0, sizeof(ifr
));
293 strncpy(ifr
.ifr_ifrn
.ifrn_name
, hapd
->conf
->iface
, IFNAMSIZ
);
294 if (setsockopt(drv
->dhcp_sock
, SOL_SOCKET
, SO_BINDTODEVICE
,
295 (char *) &ifr
, sizeof(ifr
)) < 0) {
296 perror("setsockopt[SOL_SOCKET,SO_BINDTODEVICE]");
300 if (bind(drv
->dhcp_sock
, (struct sockaddr
*) &addr2
,
301 sizeof(struct sockaddr
)) == -1) {
310 static int wired_send_eapol(void *priv
, u8
*addr
,
311 u8
*data
, size_t data_len
, int encrypt
)
313 struct wired_driver_data
*drv
= priv
;
314 u8 pae_group_addr
[ETH_ALEN
] = WIRED_EAPOL_MULTICAST_GROUP
;
315 struct ieee8023_hdr
*hdr
;
320 len
= sizeof(*hdr
) + data_len
;
323 printf("malloc() failed for wired_send_eapol(len=%lu)\n",
324 (unsigned long) len
);
329 memcpy(hdr
->dest
, drv
->use_pae_group_addr
? pae_group_addr
: addr
,
331 memcpy(hdr
->src
, drv
->hapd
->own_addr
, ETH_ALEN
);
332 hdr
->ethertype
= htons(ETH_P_PAE
);
334 pos
= (u8
*) (hdr
+ 1);
335 memcpy(pos
, data
, data_len
);
337 res
= send(drv
->sock
, (u8
*) hdr
, len
, 0);
341 perror("wired_send_eapol: send");
342 printf("wired_send_eapol - packet len: %lu - failed\n",
343 (unsigned long) len
);
350 static int wired_driver_init(struct hostapd_data
*hapd
)
352 struct wired_driver_data
*drv
;
354 drv
= malloc(sizeof(struct wired_driver_data
));
356 printf("Could not allocate memory for wired driver data\n");
360 memset(drv
, 0, sizeof(*drv
));
361 drv
->ops
= wired_driver_ops
;
363 drv
->use_pae_group_addr
= hapd
->conf
->use_pae_group_addr
;
365 if (wired_init_sockets(drv
))
368 hapd
->driver
= &drv
->ops
;
373 static void wired_driver_deinit(void *priv
)
375 struct wired_driver_data
*drv
= priv
;
377 drv
->hapd
->driver
= NULL
;
382 if (drv
->dhcp_sock
>= 0)
383 close(drv
->dhcp_sock
);
389 static const struct driver_ops wired_driver_ops
= {
391 .init
= wired_driver_init
,
392 .deinit
= wired_driver_deinit
,
393 .send_eapol
= wired_send_eapol
,
396 void wired_driver_register(void)
398 driver_register(wired_driver_ops
.name
, &wired_driver_ops
);