2 * hostapd / Kernel driver communication for wired (Ethernet) drivers
3 * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
4 * Copyright (c) 2004, Gunter Burchardt <tira@isx.de>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * Alternatively, this software may be distributed under the terms of BSD
13 * See README and COPYING for more details.
17 #include <sys/ioctl.h>
19 #ifdef USE_KERNEL_HEADERS
20 #include <asm/types.h>
21 #include <linux/if_packet.h>
22 #include <linux/if_ether.h> /* The L2 protocols */
23 #include <linux/if_arp.h>
25 #else /* USE_KERNEL_HEADERS */
26 #include <net/if_arp.h>
28 #include <netpacket/packet.h>
29 #endif /* USE_KERNEL_HEADERS */
32 #include "ieee802_1x.h"
36 #include "accounting.h"
39 struct wired_driver_data
{
40 struct driver_ops ops
;
41 struct hostapd_data
*hapd
;
43 int sock
; /* raw packet socket for driver access */
44 int dhcp_sock
; /* socket for dhcp packets */
45 int use_pae_group_addr
;
48 static const struct driver_ops wired_driver_ops
;
51 #define WIRED_EAPOL_MULTICAST_GROUP {0x01,0x80,0xc2,0x00,0x00,0x03}
54 /* TODO: detecting new devices should eventually be changed from using DHCP
55 * snooping to trigger on any packet from a new layer 2 MAC address, e.g.,
56 * based on ebtables, etc. */
74 u_int8_t options
[308]; /* 312 - cookie */
78 static void wired_possible_new_sta(struct hostapd_data
*hapd
, u8
*addr
)
82 sta
= ap_get_sta(hapd
, addr
);
86 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
, "Data frame from unknown STA "
87 MACSTR
" - adding a new STA\n", MAC2STR(addr
));
88 sta
= ap_sta_add(hapd
, addr
);
90 hostapd_new_assoc_sta(hapd
, sta
, 0);
91 accounting_sta_get_id(hapd
, sta
);
93 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
, "Failed to add STA entry "
94 "for " MACSTR
"\n", MAC2STR(addr
));
99 static void handle_data(struct hostapd_data
*hapd
, unsigned char *buf
,
102 struct ieee8023_hdr
*hdr
;
106 /* must contain at least ieee8023_hdr 6 byte source, 6 byte dest,
107 * 2 byte ethertype */
109 HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE
, "handle_data: too short "
110 "(%lu)\n", (unsigned long) len
);
114 hdr
= (struct ieee8023_hdr
*) buf
;
116 switch (ntohs(hdr
->ethertype
)) {
118 HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE
,
119 "Received EAPOL packet\n");
121 wired_possible_new_sta(hapd
, sa
);
123 pos
= (u8
*) (hdr
+ 1);
124 left
= len
- sizeof(*hdr
);
126 ieee802_1x_receive(hapd
, sa
, pos
, left
);
130 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
,
131 "Unknown ethertype 0x%04x in data frame\n",
132 ntohs(hdr
->ethertype
));
138 static void handle_read(int sock
, void *eloop_ctx
, void *sock_ctx
)
140 struct hostapd_data
*hapd
= (struct hostapd_data
*) eloop_ctx
;
142 unsigned char buf
[3000];
144 len
= recv(sock
, buf
, sizeof(buf
), 0);
150 handle_data(hapd
, buf
, len
);
154 static void handle_dhcp(int sock
, void *eloop_ctx
, void *sock_ctx
)
156 struct hostapd_data
*hapd
= (struct hostapd_data
*) eloop_ctx
;
158 unsigned char buf
[3000];
159 struct dhcp_message
*msg
;
162 len
= recv(sock
, buf
, sizeof(buf
), 0);
168 /* must contain at least dhcp_message->chaddr */
170 HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE
, "handle_dhcp: too short "
175 msg
= (struct dhcp_message
*) buf
;
176 mac_address
= (u8
*) &(msg
->chaddr
);
178 HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE
,
179 "Got DHCP broadcast packet from " MACSTR
"\n",
180 MAC2STR(mac_address
));
182 wired_possible_new_sta(hapd
, mac_address
);
186 static int wired_init_sockets(struct wired_driver_data
*drv
)
188 struct hostapd_data
*hapd
= drv
->hapd
;
190 struct sockaddr_ll addr
;
191 struct sockaddr_in addr2
;
192 struct packet_mreq mreq
;
193 u8 multicastgroup_eapol
[6] = WIRED_EAPOL_MULTICAST_GROUP
;
196 drv
->sock
= socket(PF_PACKET
, SOCK_RAW
, htons(ETH_P_PAE
));
198 perror("socket[PF_PACKET,SOCK_RAW]");
202 if (eloop_register_read_sock(drv
->sock
, handle_read
, hapd
, NULL
)) {
203 printf("Could not register read socket\n");
207 memset(&ifr
, 0, sizeof(ifr
));
208 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s",
210 if (ioctl(drv
->sock
, SIOCGIFINDEX
, &ifr
) != 0) {
211 perror("ioctl(SIOCGIFINDEX)");
216 memset(&addr
, 0, sizeof(addr
));
217 addr
.sll_family
= AF_PACKET
;
218 addr
.sll_ifindex
= ifr
.ifr_ifindex
;
219 HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL
,
220 "Opening raw packet socket for ifindex %d\n",
223 if (bind(drv
->sock
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
228 /* filter multicast address */
229 memset(&mreq
, 0, sizeof(mreq
));
230 mreq
.mr_ifindex
= ifr
.ifr_ifindex
;
231 mreq
.mr_type
= PACKET_MR_MULTICAST
;
233 memcpy(mreq
.mr_address
, multicastgroup_eapol
, mreq
.mr_alen
);
235 if (setsockopt(drv
->sock
, SOL_PACKET
, PACKET_ADD_MEMBERSHIP
, &mreq
,
237 perror("setsockopt[SOL_SOCKET,PACKET_ADD_MEMBERSHIP]");
241 memset(&ifr
, 0, sizeof(ifr
));
242 snprintf(ifr
.ifr_name
, sizeof(ifr
.ifr_name
), "%s", hapd
->conf
->iface
);
243 if (ioctl(drv
->sock
, SIOCGIFHWADDR
, &ifr
) != 0) {
244 perror("ioctl(SIOCGIFHWADDR)");
248 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) {
249 printf("Invalid HW-addr family 0x%04x\n",
250 ifr
.ifr_hwaddr
.sa_family
);
253 memcpy(hapd
->own_addr
, ifr
.ifr_hwaddr
.sa_data
, ETH_ALEN
);
255 /* setup dhcp listen socket for sta detection */
256 if ((drv
->dhcp_sock
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0) {
257 perror("socket call failed for dhcp");
261 if (eloop_register_read_sock(drv
->dhcp_sock
, handle_dhcp
, hapd
, NULL
))
263 printf("Could not register read socket\n");
267 memset(&addr2
, 0, sizeof(addr2
));
268 addr2
.sin_family
= AF_INET
;
269 addr2
.sin_port
= htons(67);
270 addr2
.sin_addr
.s_addr
= INADDR_ANY
;
272 if (setsockopt(drv
->dhcp_sock
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &n
,
274 perror("setsockopt[SOL_SOCKET,SO_REUSEADDR]");
277 if (setsockopt(drv
->dhcp_sock
, SOL_SOCKET
, SO_BROADCAST
, (char *) &n
,
279 perror("setsockopt[SOL_SOCKET,SO_BROADCAST]");
283 memset(&ifr
, 0, sizeof(ifr
));
284 strncpy(ifr
.ifr_ifrn
.ifrn_name
, hapd
->conf
->iface
, IFNAMSIZ
);
285 if (setsockopt(drv
->dhcp_sock
, SOL_SOCKET
, SO_BINDTODEVICE
,
286 (char *) &ifr
, sizeof(ifr
)) < 0) {
287 perror("setsockopt[SOL_SOCKET,SO_BINDTODEVICE]");
291 if (bind(drv
->dhcp_sock
, (struct sockaddr
*) &addr2
,
292 sizeof(struct sockaddr
)) == -1) {
301 static int wired_send_eapol(void *priv
, const u8
*addr
,
302 const u8
*data
, size_t data_len
, int encrypt
,
305 struct wired_driver_data
*drv
= priv
;
306 u8 pae_group_addr
[ETH_ALEN
] = WIRED_EAPOL_MULTICAST_GROUP
;
307 struct ieee8023_hdr
*hdr
;
312 len
= sizeof(*hdr
) + data_len
;
313 hdr
= wpa_zalloc(len
);
315 printf("malloc() failed for wired_send_eapol(len=%lu)\n",
316 (unsigned long) len
);
320 memcpy(hdr
->dest
, drv
->use_pae_group_addr
? pae_group_addr
: addr
,
322 memcpy(hdr
->src
, own_addr
, ETH_ALEN
);
323 hdr
->ethertype
= htons(ETH_P_PAE
);
325 pos
= (u8
*) (hdr
+ 1);
326 memcpy(pos
, data
, data_len
);
328 res
= send(drv
->sock
, (u8
*) hdr
, len
, 0);
332 perror("wired_send_eapol: send");
333 printf("wired_send_eapol - packet len: %lu - failed\n",
334 (unsigned long) len
);
341 static int wired_driver_init(struct hostapd_data
*hapd
)
343 struct wired_driver_data
*drv
;
345 drv
= wpa_zalloc(sizeof(struct wired_driver_data
));
347 printf("Could not allocate memory for wired driver data\n");
351 drv
->ops
= wired_driver_ops
;
353 drv
->use_pae_group_addr
= hapd
->conf
->use_pae_group_addr
;
355 if (wired_init_sockets(drv
)) {
360 hapd
->driver
= &drv
->ops
;
365 static void wired_driver_deinit(void *priv
)
367 struct wired_driver_data
*drv
= priv
;
369 drv
->hapd
->driver
= NULL
;
374 if (drv
->dhcp_sock
>= 0)
375 close(drv
->dhcp_sock
);
381 static const struct driver_ops wired_driver_ops
= {
383 .init
= wired_driver_init
,
384 .deinit
= wired_driver_deinit
,
385 .send_eapol
= wired_send_eapol
,
388 void wired_driver_register(void)
390 driver_register(wired_driver_ops
.name
, &wired_driver_ops
);