2 * WPA Supplicant - Layer2 packet handling with libpcap/libdnet and WinPcap
3 * Copyright (c) 2003-2006, 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 #ifndef CONFIG_NATIVE_WINDOWS
17 #include <sys/ioctl.h>
18 #endif /* CONFIG_NATIVE_WINDOWS */
20 #ifndef CONFIG_WINPCAP
22 #endif /* CONFIG_WINPCAP */
26 #include "l2_packet.h"
29 static const u8 pae_group_addr
[ETH_ALEN
] =
30 { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
32 struct l2_packet_data
{
35 unsigned int num_fast_poll
;
36 #else /* CONFIG_WINPCAP */
38 #endif /* CONFIG_WINPCAP */
40 u8 own_addr
[ETH_ALEN
];
41 void (*rx_callback
)(void *ctx
, const u8
*src_addr
,
42 const u8
*buf
, size_t len
);
43 void *rx_callback_ctx
;
44 int l2_hdr
; /* whether to include layer 2 (Ethernet) header in calls
49 int l2_packet_get_own_addr(struct l2_packet_data
*l2
, u8
*addr
)
51 os_memcpy(addr
, l2
->own_addr
, ETH_ALEN
);
56 #ifndef CONFIG_WINPCAP
57 static int l2_packet_init_libdnet(struct l2_packet_data
*l2
)
61 l2
->eth
= eth_open(l2
->ifname
);
63 printf("Failed to open interface '%s'.\n", l2
->ifname
);
68 if (eth_get(l2
->eth
, &own_addr
) < 0) {
69 printf("Failed to get own hw address from interface '%s'.\n",
76 os_memcpy(l2
->own_addr
, own_addr
.data
, ETH_ALEN
);
80 #endif /* CONFIG_WINPCAP */
83 int l2_packet_send(struct l2_packet_data
*l2
, const u8
*dst_addr
, u16 proto
,
84 const u8
*buf
, size_t len
)
87 struct l2_ethhdr
*eth
;
94 ret
= pcap_sendpacket(l2
->pcap
, buf
, len
);
95 #else /* CONFIG_WINPCAP */
96 ret
= eth_send(l2
->eth
, buf
, len
);
97 #endif /* CONFIG_WINPCAP */
99 size_t mlen
= sizeof(*eth
) + len
;
100 eth
= os_malloc(mlen
);
104 os_memcpy(eth
->h_dest
, dst_addr
, ETH_ALEN
);
105 os_memcpy(eth
->h_source
, l2
->own_addr
, ETH_ALEN
);
106 eth
->h_proto
= htons(proto
);
107 os_memcpy(eth
+ 1, buf
, len
);
109 #ifdef CONFIG_WINPCAP
110 ret
= pcap_sendpacket(l2
->pcap
, (u8
*) eth
, mlen
);
111 #else /* CONFIG_WINPCAP */
112 ret
= eth_send(l2
->eth
, (u8
*) eth
, mlen
);
113 #endif /* CONFIG_WINPCAP */
122 #ifndef CONFIG_WINPCAP
123 static void l2_packet_receive(int sock
, void *eloop_ctx
, void *sock_ctx
)
125 struct l2_packet_data
*l2
= eloop_ctx
;
126 pcap_t
*pcap
= sock_ctx
;
127 struct pcap_pkthdr hdr
;
128 const u_char
*packet
;
129 struct l2_ethhdr
*ethhdr
;
133 packet
= pcap_next(pcap
, &hdr
);
135 if (packet
== NULL
|| hdr
.caplen
< sizeof(*ethhdr
))
138 ethhdr
= (struct l2_ethhdr
*) packet
;
140 buf
= (unsigned char *) ethhdr
;
143 buf
= (unsigned char *) (ethhdr
+ 1);
144 len
= hdr
.caplen
- sizeof(*ethhdr
);
146 l2
->rx_callback(l2
->rx_callback_ctx
, ethhdr
->h_source
, buf
, len
);
148 #endif /* CONFIG_WINPCAP */
151 #ifdef CONFIG_WINPCAP
152 static void l2_packet_receive_cb(u_char
*user
, const struct pcap_pkthdr
*hdr
,
153 const u_char
*pkt_data
)
155 struct l2_packet_data
*l2
= (struct l2_packet_data
*) user
;
156 struct l2_ethhdr
*ethhdr
;
160 if (pkt_data
== NULL
|| hdr
->caplen
< sizeof(*ethhdr
))
163 ethhdr
= (struct l2_ethhdr
*) pkt_data
;
165 buf
= (unsigned char *) ethhdr
;
168 buf
= (unsigned char *) (ethhdr
+ 1);
169 len
= hdr
->caplen
- sizeof(*ethhdr
);
171 l2
->rx_callback(l2
->rx_callback_ctx
, ethhdr
->h_source
, buf
, len
);
173 * Use shorter poll interval for 3 seconds to reduce latency during key
176 l2
->num_fast_poll
= 3 * 50;
180 static void l2_packet_receive_timeout(void *eloop_ctx
, void *timeout_ctx
)
182 struct l2_packet_data
*l2
= eloop_ctx
;
183 pcap_t
*pcap
= timeout_ctx
;
186 if (l2
->num_fast_poll
> 0) {
192 /* Register new timeout before calling l2_packet_receive() since
193 * receive handler may free this l2_packet instance (which will
194 * cancel this timeout). */
195 eloop_register_timeout(0, timeout
, l2_packet_receive_timeout
,
197 pcap_dispatch(pcap
, 10, l2_packet_receive_cb
, (u_char
*) l2
);
199 #endif /* CONFIG_WINPCAP */
202 static int l2_packet_init_libpcap(struct l2_packet_data
*l2
,
203 unsigned short protocol
)
205 bpf_u_int32 pcap_maskp
, pcap_netp
;
206 char pcap_filter
[200], pcap_err
[PCAP_ERRBUF_SIZE
];
207 struct bpf_program pcap_fp
;
209 #ifdef CONFIG_WINPCAP
211 os_snprintf(ifname
, sizeof(ifname
), "\\Device\\NPF_%s", l2
->ifname
);
212 pcap_lookupnet(ifname
, &pcap_netp
, &pcap_maskp
, pcap_err
);
213 l2
->pcap
= pcap_open_live(ifname
, 2500, 0, 10, pcap_err
);
214 if (l2
->pcap
== NULL
) {
215 fprintf(stderr
, "pcap_open_live: %s\n", pcap_err
);
216 fprintf(stderr
, "ifname='%s'\n", ifname
);
219 if (pcap_setnonblock(l2
->pcap
, 1, pcap_err
) < 0)
220 fprintf(stderr
, "pcap_setnonblock: %s\n",
221 pcap_geterr(l2
->pcap
));
222 #else /* CONFIG_WINPCAP */
223 pcap_lookupnet(l2
->ifname
, &pcap_netp
, &pcap_maskp
, pcap_err
);
224 l2
->pcap
= pcap_open_live(l2
->ifname
, 2500, 0, 10, pcap_err
);
225 if (l2
->pcap
== NULL
) {
226 fprintf(stderr
, "pcap_open_live: %s\n", pcap_err
);
227 fprintf(stderr
, "ifname='%s'\n", l2
->ifname
);
230 if (pcap_datalink(l2
->pcap
) != DLT_EN10MB
&&
231 pcap_set_datalink(l2
->pcap
, DLT_EN10MB
) < 0) {
232 fprintf(stderr
, "pcap_set_datalink(DLT_EN10MB): %s\n",
233 pcap_geterr(l2
->pcap
));
236 #endif /* CONFIG_WINPCAP */
237 os_snprintf(pcap_filter
, sizeof(pcap_filter
),
238 "not ether src " MACSTR
" and "
239 "( ether dst " MACSTR
" or ether dst " MACSTR
" ) and "
241 MAC2STR(l2
->own_addr
), /* do not receive own packets */
242 MAC2STR(l2
->own_addr
), MAC2STR(pae_group_addr
),
244 if (pcap_compile(l2
->pcap
, &pcap_fp
, pcap_filter
, 1, pcap_netp
) < 0) {
245 fprintf(stderr
, "pcap_compile: %s\n", pcap_geterr(l2
->pcap
));
249 if (pcap_setfilter(l2
->pcap
, &pcap_fp
) < 0) {
250 fprintf(stderr
, "pcap_setfilter: %s\n", pcap_geterr(l2
->pcap
));
254 pcap_freecode(&pcap_fp
);
257 * When libpcap uses BPF we must enable "immediate mode" to
258 * receive frames right away; otherwise the system may
259 * buffer them for us.
263 if (ioctl(pcap_fileno(l2
->pcap
), BIOCIMMEDIATE
, &on
) < 0) {
264 fprintf(stderr
, "%s: cannot enable immediate mode on "
265 "interface %s: %s\n",
266 __func__
, l2
->ifname
, strerror(errno
));
267 /* XXX should we fail? */
270 #endif /* BIOCIMMEDIATE */
272 #ifdef CONFIG_WINPCAP
273 eloop_register_timeout(0, 100000, l2_packet_receive_timeout
,
275 #else /* CONFIG_WINPCAP */
276 eloop_register_read_sock(pcap_get_selectable_fd(l2
->pcap
),
277 l2_packet_receive
, l2
, l2
->pcap
);
278 #endif /* CONFIG_WINPCAP */
284 struct l2_packet_data
* l2_packet_init(
285 const char *ifname
, const u8
*own_addr
, unsigned short protocol
,
286 void (*rx_callback
)(void *ctx
, const u8
*src_addr
,
287 const u8
*buf
, size_t len
),
288 void *rx_callback_ctx
, int l2_hdr
)
290 struct l2_packet_data
*l2
;
292 l2
= os_zalloc(sizeof(struct l2_packet_data
));
295 os_strlcpy(l2
->ifname
, ifname
, sizeof(l2
->ifname
));
296 l2
->rx_callback
= rx_callback
;
297 l2
->rx_callback_ctx
= rx_callback_ctx
;
300 #ifdef CONFIG_WINPCAP
302 os_memcpy(l2
->own_addr
, own_addr
, ETH_ALEN
);
303 #else /* CONFIG_WINPCAP */
304 if (l2_packet_init_libdnet(l2
))
306 #endif /* CONFIG_WINPCAP */
308 if (l2_packet_init_libpcap(l2
, protocol
)) {
309 #ifndef CONFIG_WINPCAP
311 #endif /* CONFIG_WINPCAP */
320 void l2_packet_deinit(struct l2_packet_data
*l2
)
325 #ifdef CONFIG_WINPCAP
326 eloop_cancel_timeout(l2_packet_receive_timeout
, l2
, l2
->pcap
);
327 #else /* CONFIG_WINPCAP */
330 eloop_unregister_read_sock(pcap_get_selectable_fd(l2
->pcap
));
331 #endif /* CONFIG_WINPCAP */
333 pcap_close(l2
->pcap
);
338 int l2_packet_get_ip_addr(struct l2_packet_data
*l2
, char *buf
, size_t len
)
340 pcap_if_t
*devs
, *dev
;
341 struct pcap_addr
*addr
;
342 struct sockaddr_in
*saddr
;
344 char err
[PCAP_ERRBUF_SIZE
+ 1];
346 if (pcap_findalldevs(&devs
, err
) < 0) {
347 wpa_printf(MSG_DEBUG
, "pcap_findalldevs: %s\n", err
);
351 for (dev
= devs
; dev
&& !found
; dev
= dev
->next
) {
352 if (os_strcmp(dev
->name
, l2
->ifname
) != 0)
355 addr
= dev
->addresses
;
357 saddr
= (struct sockaddr_in
*) addr
->addr
;
358 if (saddr
&& saddr
->sin_family
== AF_INET
) {
359 os_strlcpy(buf
, inet_ntoa(saddr
->sin_addr
),
368 pcap_freealldevs(devs
);
370 return found
? 0 : -1;
374 void l2_packet_notify_auth_start(struct l2_packet_data
*l2
)
376 #ifdef CONFIG_WINPCAP
378 * Use shorter poll interval for 3 seconds to reduce latency during key
381 l2
->num_fast_poll
= 3 * 50;
382 eloop_cancel_timeout(l2_packet_receive_timeout
, l2
, l2
->pcap
);
383 eloop_register_timeout(0, 10000, l2_packet_receive_timeout
,
385 #endif /* CONFIG_WINPCAP */