1 /*
2 * Wired Ethernet driver interface
3 * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
4 * Copyright (c) 2004, Gunter Burchardt <tira@isx.de>
5 *
6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
8 */
9
10 #include "includes.h"
11
12 #include "common.h"
13 #include "eloop.h"
14 #include "driver.h"
15 #include "driver_wired_common.h"
16
17 #include <sys/ioctl.h>
18 #ifdef __linux__
19 #include <netpacket/packet.h>
20 #include <net/if_arp.h>
21 #endif /* __linux__ */
22 #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
23 #include <net/if_dl.h>
24 #include <net/if_media.h>
25 #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */
26 #ifdef __sun__
27 #include <sys/sockio.h>
28 #endif /* __sun__ */
29
30 #ifdef _MSC_VER
31 #pragma pack(push, 1)
32 #endif /* _MSC_VER */
33
34 struct ieee8023_hdr {
35 u8 dest[6];
36 u8 src[6];
37 u16 ethertype;
38 } STRUCT_PACKED;
39
40 #ifdef _MSC_VER
41 #pragma pack(pop)
42 #endif /* _MSC_VER */
43
44
45 struct wpa_driver_wired_data {
46 struct driver_wired_common_data common;
47
48 int dhcp_sock; /* socket for dhcp packets */
49 int use_pae_group_addr;
50 };
51
52
53 /* TODO: detecting new devices should eventually be changed from using DHCP
54 * snooping to trigger on any packet from a new layer 2 MAC address, e.g.,
55 * based on ebtables, etc. */
56
57 struct dhcp_message {
58 u_int8_t op;
59 u_int8_t htype;
60 u_int8_t hlen;
61 u_int8_t hops;
62 u_int32_t xid;
63 u_int16_t secs;
64 u_int16_t flags;
65 u_int32_t ciaddr;
66 u_int32_t yiaddr;
67 u_int32_t siaddr;
68 u_int32_t giaddr;
69 u_int8_t chaddr[16];
70 u_int8_t sname[64];
71 u_int8_t file[128];
72 u_int32_t cookie;
73 u_int8_t options[308]; /* 312 - cookie */
74 };
75
76
77 #ifdef __linux__
handle_data(void * ctx,unsigned char * buf,size_t len)78 static void handle_data(void *ctx, unsigned char *buf, size_t len)
79 {
80 #ifdef HOSTAPD
81 struct ieee8023_hdr *hdr;
82 u8 *pos, *sa;
83 size_t left;
84 union wpa_event_data event;
85
86 /* must contain at least ieee8023_hdr 6 byte source, 6 byte dest,
87 * 2 byte ethertype */
88 if (len < 14) {
89 wpa_printf(MSG_MSGDUMP, "handle_data: too short (%lu)",
90 (unsigned long) len);
91 return;
92 }
93
94 hdr = (struct ieee8023_hdr *) buf;
95
96 switch (ntohs(hdr->ethertype)) {
97 case ETH_P_PAE:
98 wpa_printf(MSG_MSGDUMP, "Received EAPOL packet");
99 sa = hdr->src;
100 os_memset(&event, 0, sizeof(event));
101 event.new_sta.addr = sa;
102 wpa_supplicant_event(ctx, EVENT_NEW_STA, &event);
103
104 pos = (u8 *) (hdr + 1);
105 left = len - sizeof(*hdr);
106 drv_event_eapol_rx(ctx, sa, pos, left);
107 break;
108
109 default:
110 wpa_printf(MSG_DEBUG, "Unknown ethertype 0x%04x in data frame",
111 ntohs(hdr->ethertype));
112 break;
113 }
114 #endif /* HOSTAPD */
115 }
116
117
handle_read(int sock,void * eloop_ctx,void * sock_ctx)118 static void handle_read(int sock, void *eloop_ctx, void *sock_ctx)
119 {
120 int len;
121 unsigned char buf[3000];
122
123 len = recv(sock, buf, sizeof(buf), 0);
124 if (len < 0) {
125 wpa_printf(MSG_ERROR, "recv: %s", strerror(errno));
126 return;
127 }
128
129 handle_data(eloop_ctx, buf, len);
130 }
131
132
handle_dhcp(int sock,void * eloop_ctx,void * sock_ctx)133 static void handle_dhcp(int sock, void *eloop_ctx, void *sock_ctx)
134 {
135 int len;
136 unsigned char buf[3000];
137 struct dhcp_message *msg;
138 u8 *mac_address;
139 union wpa_event_data event;
140
141 len = recv(sock, buf, sizeof(buf), 0);
142 if (len < 0) {
143 wpa_printf(MSG_ERROR, "recv: %s", strerror(errno));
144 return;
145 }
146
147 /* must contain at least dhcp_message->chaddr */
148 if (len < 44) {
149 wpa_printf(MSG_MSGDUMP, "handle_dhcp: too short (%d)", len);
150 return;
151 }
152
153 msg = (struct dhcp_message *) buf;
154 mac_address = (u8 *) &(msg->chaddr);
155
156 wpa_printf(MSG_MSGDUMP, "Got DHCP broadcast packet from " MACSTR,
157 MAC2STR(mac_address));
158
159 os_memset(&event, 0, sizeof(event));
160 event.new_sta.addr = mac_address;
161 wpa_supplicant_event(eloop_ctx, EVENT_NEW_STA, &event);
162 }
163 #endif /* __linux__ */
164
165
wired_init_sockets(struct wpa_driver_wired_data * drv,u8 * own_addr)166 static int wired_init_sockets(struct wpa_driver_wired_data *drv, u8 *own_addr)
167 {
168 #ifdef __linux__
169 struct ifreq ifr;
170 struct sockaddr_ll addr;
171 struct sockaddr_in addr2;
172 int n = 1;
173
174 drv->common.sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_PAE));
175 if (drv->common.sock < 0) {
176 wpa_printf(MSG_ERROR, "socket[PF_PACKET,SOCK_RAW]: %s",
177 strerror(errno));
178 return -1;
179 }
180
181 if (eloop_register_read_sock(drv->common.sock, handle_read,
182 drv->common.ctx, NULL)) {
183 wpa_printf(MSG_INFO, "Could not register read socket");
184 return -1;
185 }
186
187 os_memset(&ifr, 0, sizeof(ifr));
188 os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name));
189 if (ioctl(drv->common.sock, SIOCGIFINDEX, &ifr) != 0) {
190 wpa_printf(MSG_ERROR, "ioctl(SIOCGIFINDEX): %s",
191 strerror(errno));
192 return -1;
193 }
194
195 os_memset(&addr, 0, sizeof(addr));
196 addr.sll_family = AF_PACKET;
197 addr.sll_ifindex = ifr.ifr_ifindex;
198 wpa_printf(MSG_DEBUG, "Opening raw packet socket for ifindex %d",
199 addr.sll_ifindex);
200
201 if (bind(drv->common.sock, (struct sockaddr *) &addr, sizeof(addr)) < 0)
202 {
203 wpa_printf(MSG_ERROR, "bind: %s", strerror(errno));
204 return -1;
205 }
206
207 /* filter multicast address */
208 if (wired_multicast_membership(drv->common.sock, ifr.ifr_ifindex,
209 pae_group_addr, 1) < 0) {
210 wpa_printf(MSG_ERROR, "wired: Failed to add multicast group "
211 "membership");
212 return -1;
213 }
214
215 os_memset(&ifr, 0, sizeof(ifr));
216 os_strlcpy(ifr.ifr_name, drv->common.ifname, sizeof(ifr.ifr_name));
217 if (ioctl(drv->common.sock, SIOCGIFHWADDR, &ifr) != 0) {
218 wpa_printf(MSG_ERROR, "ioctl(SIOCGIFHWADDR): %s",
219 strerror(errno));
220 return -1;
221 }
222
223 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) {
224 wpa_printf(MSG_INFO, "Invalid HW-addr family 0x%04x",
225 ifr.ifr_hwaddr.sa_family);
226 return -1;
227 }
228 os_memcpy(own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
229
230 /* setup dhcp listen socket for sta detection */
231 if ((drv->dhcp_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
232 wpa_printf(MSG_ERROR, "socket call failed for dhcp: %s",
233 strerror(errno));
234 return -1;
235 }
236
237 if (eloop_register_read_sock(drv->dhcp_sock, handle_dhcp,
238 drv->common.ctx, NULL)) {
239 wpa_printf(MSG_INFO, "Could not register read socket");
240 return -1;
241 }
242
243 os_memset(&addr2, 0, sizeof(addr2));
244 addr2.sin_family = AF_INET;
245 addr2.sin_port = htons(67);
246 addr2.sin_addr.s_addr = INADDR_ANY;
247
248 if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_REUSEADDR, (char *) &n,
249 sizeof(n)) == -1) {
250 wpa_printf(MSG_ERROR, "setsockopt[SOL_SOCKET,SO_REUSEADDR]: %s",
251 strerror(errno));
252 return -1;
253 }
254 if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BROADCAST, (char *) &n,
255 sizeof(n)) == -1) {
256 wpa_printf(MSG_ERROR, "setsockopt[SOL_SOCKET,SO_BROADCAST]: %s",
257 strerror(errno));
258 return -1;
259 }
260
261 os_memset(&ifr, 0, sizeof(ifr));
262 os_strlcpy(ifr.ifr_ifrn.ifrn_name, drv->common.ifname, IFNAMSIZ);
263 if (setsockopt(drv->dhcp_sock, SOL_SOCKET, SO_BINDTODEVICE,
264 (char *) &ifr, sizeof(ifr)) < 0) {
265 wpa_printf(MSG_ERROR,
266 "setsockopt[SOL_SOCKET,SO_BINDTODEVICE]: %s",
267 strerror(errno));
268 return -1;
269 }
270
271 if (bind(drv->dhcp_sock, (struct sockaddr *) &addr2,
272 sizeof(struct sockaddr)) == -1) {
273 wpa_printf(MSG_ERROR, "bind: %s", strerror(errno));
274 return -1;
275 }
276
277 return 0;
278 #else /* __linux__ */
279 return -1;
280 #endif /* __linux__ */
281 }
282
283
wired_send_eapol(void * priv,const u8 * addr,const u8 * data,size_t data_len,int encrypt,const u8 * own_addr,u32 flags)284 static int wired_send_eapol(void *priv, const u8 *addr,
285 const u8 *data, size_t data_len, int encrypt,
286 const u8 *own_addr, u32 flags)
287 {
288 struct wpa_driver_wired_data *drv = priv;
289 struct ieee8023_hdr *hdr;
290 size_t len;
291 u8 *pos;
292 int res;
293
294 len = sizeof(*hdr) + data_len;
295 hdr = os_zalloc(len);
296 if (hdr == NULL) {
297 wpa_printf(MSG_INFO,
298 "malloc() failed for wired_send_eapol(len=%lu)",
299 (unsigned long) len);
300 return -1;
301 }
302
303 os_memcpy(hdr->dest, drv->use_pae_group_addr ? pae_group_addr : addr,
304 ETH_ALEN);
305 os_memcpy(hdr->src, own_addr, ETH_ALEN);
306 hdr->ethertype = htons(ETH_P_PAE);
307
308 pos = (u8 *) (hdr + 1);
309 os_memcpy(pos, data, data_len);
310
311 res = send(drv->common.sock, (u8 *) hdr, len, 0);
312 os_free(hdr);
313
314 if (res < 0) {
315 wpa_printf(MSG_ERROR,
316 "wired_send_eapol - packet len: %lu - failed: send: %s",
317 (unsigned long) len, strerror(errno));
318 }
319
320 return res;
321 }
322
323
wired_driver_hapd_init(struct hostapd_data * hapd,struct wpa_init_params * params)324 static void * wired_driver_hapd_init(struct hostapd_data *hapd,
325 struct wpa_init_params *params)
326 {
327 struct wpa_driver_wired_data *drv;
328
329 drv = os_zalloc(sizeof(struct wpa_driver_wired_data));
330 if (drv == NULL) {
331 wpa_printf(MSG_INFO,
332 "Could not allocate memory for wired driver data");
333 return NULL;
334 }
335
336 drv->common.ctx = hapd;
337 os_strlcpy(drv->common.ifname, params->ifname,
338 sizeof(drv->common.ifname));
339 drv->use_pae_group_addr = params->use_pae_group_addr;
340
341 if (wired_init_sockets(drv, params->own_addr)) {
342 os_free(drv);
343 return NULL;
344 }
345
346 return drv;
347 }
348
349
wired_driver_hapd_deinit(void * priv)350 static void wired_driver_hapd_deinit(void *priv)
351 {
352 struct wpa_driver_wired_data *drv = priv;
353
354 if (drv->common.sock >= 0) {
355 eloop_unregister_read_sock(drv->common.sock);
356 close(drv->common.sock);
357 }
358
359 if (drv->dhcp_sock >= 0) {
360 eloop_unregister_read_sock(drv->dhcp_sock);
361 close(drv->dhcp_sock);
362 }
363
364 os_free(drv);
365 }
366
367
wpa_driver_wired_init(void * ctx,const char * ifname)368 static void * wpa_driver_wired_init(void *ctx, const char *ifname)
369 {
370 struct wpa_driver_wired_data *drv;
371
372 drv = os_zalloc(sizeof(*drv));
373 if (drv == NULL)
374 return NULL;
375
376 if (driver_wired_init_common(&drv->common, ifname, ctx) < 0) {
377 os_free(drv);
378 return NULL;
379 }
380
381 return drv;
382 }
383
384
wpa_driver_wired_deinit(void * priv)385 static void wpa_driver_wired_deinit(void *priv)
386 {
387 struct wpa_driver_wired_data *drv = priv;
388
389 driver_wired_deinit_common(&drv->common);
390 os_free(drv);
391 }
392
393
394 const struct wpa_driver_ops wpa_driver_wired_ops = {
395 .name = "wired",
396 .desc = "Wired Ethernet driver",
397 .hapd_init = wired_driver_hapd_init,
398 .hapd_deinit = wired_driver_hapd_deinit,
399 .hapd_send_eapol = wired_send_eapol,
400 .get_ssid = driver_wired_get_ssid,
401 .get_bssid = driver_wired_get_bssid,
402 .get_capa = driver_wired_get_capa,
403 .init = wpa_driver_wired_init,
404 .deinit = wpa_driver_wired_deinit,
405 };
406