2 * hostapd / Kernel driver communication for wired (Ethernet) drivers
3 * Copyright (c) 2002-2007, 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 hostapd_data
*hapd
;
42 int sock
; /* raw packet socket for driver access */
43 int dhcp_sock
; /* socket for dhcp packets */
44 int use_pae_group_addr
;
48 #define WIRED_EAPOL_MULTICAST_GROUP {0x01,0x80,0xc2,0x00,0x00,0x03}
51 /* TODO: detecting new devices should eventually be changed from using DHCP
52 * snooping to trigger on any packet from a new layer 2 MAC address, e.g.,
53 * based on ebtables, etc. */
71 u_int8_t options
[308]; /* 312 - cookie */
75 static void wired_possible_new_sta(struct hostapd_data
*hapd
, u8
*addr
)
79 sta
= ap_get_sta(hapd
, addr
);
83 wpa_printf(MSG_DEBUG
, "Data frame from unknown STA " MACSTR
84 " - adding a new STA", MAC2STR(addr
));
85 sta
= ap_sta_add(hapd
, addr
);
87 hostapd_new_assoc_sta(hapd
, sta
, 0);
88 accounting_sta_get_id(hapd
, sta
);
90 wpa_printf(MSG_DEBUG
, "Failed to add STA entry for " MACSTR
,
96 static void handle_data(struct hostapd_data
*hapd
, unsigned char *buf
,
99 struct ieee8023_hdr
*hdr
;
103 /* must contain at least ieee8023_hdr 6 byte source, 6 byte dest,
104 * 2 byte ethertype */
106 wpa_printf(MSG_MSGDUMP
, "handle_data: too short (%lu)",
107 (unsigned long) len
);
111 hdr
= (struct ieee8023_hdr
*) buf
;
113 switch (ntohs(hdr
->ethertype
)) {
115 wpa_printf(MSG_MSGDUMP
, "Received EAPOL packet");
117 wired_possible_new_sta(hapd
, sa
);
119 pos
= (u8
*) (hdr
+ 1);
120 left
= len
- sizeof(*hdr
);
122 ieee802_1x_receive(hapd
, sa
, pos
, left
);
126 wpa_printf(MSG_DEBUG
, "Unknown ethertype 0x%04x in data frame",
127 ntohs(hdr
->ethertype
));
133 static void handle_read(int sock
, void *eloop_ctx
, void *sock_ctx
)
135 struct hostapd_data
*hapd
= (struct hostapd_data
*) eloop_ctx
;
137 unsigned char buf
[3000];
139 len
= recv(sock
, buf
, sizeof(buf
), 0);
145 handle_data(hapd
, buf
, len
);
149 static void handle_dhcp(int sock
, void *eloop_ctx
, void *sock_ctx
)
151 struct hostapd_data
*hapd
= (struct hostapd_data
*) eloop_ctx
;
153 unsigned char buf
[3000];
154 struct dhcp_message
*msg
;
157 len
= recv(sock
, buf
, sizeof(buf
), 0);
163 /* must contain at least dhcp_message->chaddr */
165 wpa_printf(MSG_MSGDUMP
, "handle_dhcp: too short (%d)", len
);
169 msg
= (struct dhcp_message
*) buf
;
170 mac_address
= (u8
*) &(msg
->chaddr
);
172 wpa_printf(MSG_MSGDUMP
, "Got DHCP broadcast packet from " MACSTR
,
173 MAC2STR(mac_address
));
175 wired_possible_new_sta(hapd
, mac_address
);
179 static int wired_init_sockets(struct wired_driver_data
*drv
)
181 struct hostapd_data
*hapd
= drv
->hapd
;
183 struct sockaddr_ll addr
;
184 struct sockaddr_in addr2
;
185 struct packet_mreq mreq
;
186 u8 multicastgroup_eapol
[6] = WIRED_EAPOL_MULTICAST_GROUP
;
189 drv
->sock
= socket(PF_PACKET
, SOCK_RAW
, htons(ETH_P_PAE
));
191 perror("socket[PF_PACKET,SOCK_RAW]");
195 if (eloop_register_read_sock(drv
->sock
, handle_read
, hapd
, NULL
)) {
196 printf("Could not register read socket\n");
200 memset(&ifr
, 0, sizeof(ifr
));
201 os_strlcpy(ifr
.ifr_name
, hapd
->conf
->iface
, sizeof(ifr
.ifr_name
));
202 if (ioctl(drv
->sock
, SIOCGIFINDEX
, &ifr
) != 0) {
203 perror("ioctl(SIOCGIFINDEX)");
208 memset(&addr
, 0, sizeof(addr
));
209 addr
.sll_family
= AF_PACKET
;
210 addr
.sll_ifindex
= ifr
.ifr_ifindex
;
211 wpa_printf(MSG_DEBUG
, "Opening raw packet socket for ifindex %d",
214 if (bind(drv
->sock
, (struct sockaddr
*) &addr
, sizeof(addr
)) < 0) {
219 /* filter multicast address */
220 memset(&mreq
, 0, sizeof(mreq
));
221 mreq
.mr_ifindex
= ifr
.ifr_ifindex
;
222 mreq
.mr_type
= PACKET_MR_MULTICAST
;
224 memcpy(mreq
.mr_address
, multicastgroup_eapol
, mreq
.mr_alen
);
226 if (setsockopt(drv
->sock
, SOL_PACKET
, PACKET_ADD_MEMBERSHIP
, &mreq
,
228 perror("setsockopt[SOL_SOCKET,PACKET_ADD_MEMBERSHIP]");
232 memset(&ifr
, 0, sizeof(ifr
));
233 os_strlcpy(ifr
.ifr_name
, hapd
->conf
->iface
, sizeof(ifr
.ifr_name
));
234 if (ioctl(drv
->sock
, SIOCGIFHWADDR
, &ifr
) != 0) {
235 perror("ioctl(SIOCGIFHWADDR)");
239 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) {
240 printf("Invalid HW-addr family 0x%04x\n",
241 ifr
.ifr_hwaddr
.sa_family
);
244 memcpy(hapd
->own_addr
, ifr
.ifr_hwaddr
.sa_data
, ETH_ALEN
);
246 /* setup dhcp listen socket for sta detection */
247 if ((drv
->dhcp_sock
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
)) < 0) {
248 perror("socket call failed for dhcp");
252 if (eloop_register_read_sock(drv
->dhcp_sock
, handle_dhcp
, hapd
, NULL
))
254 printf("Could not register read socket\n");
258 memset(&addr2
, 0, sizeof(addr2
));
259 addr2
.sin_family
= AF_INET
;
260 addr2
.sin_port
= htons(67);
261 addr2
.sin_addr
.s_addr
= INADDR_ANY
;
263 if (setsockopt(drv
->dhcp_sock
, SOL_SOCKET
, SO_REUSEADDR
, (char *) &n
,
265 perror("setsockopt[SOL_SOCKET,SO_REUSEADDR]");
268 if (setsockopt(drv
->dhcp_sock
, SOL_SOCKET
, SO_BROADCAST
, (char *) &n
,
270 perror("setsockopt[SOL_SOCKET,SO_BROADCAST]");
274 memset(&ifr
, 0, sizeof(ifr
));
275 os_strlcpy(ifr
.ifr_ifrn
.ifrn_name
, hapd
->conf
->iface
, IFNAMSIZ
);
276 if (setsockopt(drv
->dhcp_sock
, SOL_SOCKET
, SO_BINDTODEVICE
,
277 (char *) &ifr
, sizeof(ifr
)) < 0) {
278 perror("setsockopt[SOL_SOCKET,SO_BINDTODEVICE]");
282 if (bind(drv
->dhcp_sock
, (struct sockaddr
*) &addr2
,
283 sizeof(struct sockaddr
)) == -1) {
292 static int wired_send_eapol(void *priv
, const u8
*addr
,
293 const u8
*data
, size_t data_len
, int encrypt
,
296 struct wired_driver_data
*drv
= priv
;
297 u8 pae_group_addr
[ETH_ALEN
] = WIRED_EAPOL_MULTICAST_GROUP
;
298 struct ieee8023_hdr
*hdr
;
303 len
= sizeof(*hdr
) + data_len
;
304 hdr
= os_zalloc(len
);
306 printf("malloc() failed for wired_send_eapol(len=%lu)\n",
307 (unsigned long) len
);
311 memcpy(hdr
->dest
, drv
->use_pae_group_addr
? pae_group_addr
: addr
,
313 memcpy(hdr
->src
, own_addr
, ETH_ALEN
);
314 hdr
->ethertype
= htons(ETH_P_PAE
);
316 pos
= (u8
*) (hdr
+ 1);
317 memcpy(pos
, data
, data_len
);
319 res
= send(drv
->sock
, (u8
*) hdr
, len
, 0);
323 perror("wired_send_eapol: send");
324 printf("wired_send_eapol - packet len: %lu - failed\n",
325 (unsigned long) len
);
332 static void * wired_driver_init(struct hostapd_data
*hapd
)
334 struct wired_driver_data
*drv
;
336 drv
= os_zalloc(sizeof(struct wired_driver_data
));
338 printf("Could not allocate memory for wired driver data\n");
343 drv
->use_pae_group_addr
= hapd
->conf
->use_pae_group_addr
;
345 if (wired_init_sockets(drv
)) {
354 static void wired_driver_deinit(void *priv
)
356 struct wired_driver_data
*drv
= priv
;
361 if (drv
->dhcp_sock
>= 0)
362 close(drv
->dhcp_sock
);
368 const struct wpa_driver_ops wpa_driver_wired_ops
= {
370 .init
= wired_driver_init
,
371 .deinit
= wired_driver_deinit
,
372 .send_eapol
= wired_send_eapol
,