~ubuntu-branches/ubuntu/oneiric/wpasupplicant/oneiric

« back to all changes in this revision

Viewing changes to l2_packet.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2006-10-05 08:04:01 UTC
  • mfrom: (1.2.1 upstream) (2.1.14 edgy)
  • Revision ID: james.westby@ubuntu.com-20061005080401-myfwjtq7di70dyeo
* Update madwifi headers to latest SVN. (Closes: #388316)
* Remove failed attempt at action locking. [debian/functions.sh,
  debian/wpa_action.sh]
* Add hysteresis checking functions, to avoid "event loops" while
  using wpa-roam. [debian/functions.sh, debian/wpa_action.sh]
* Change of co-maintainer email address.
* Add ishex() function to functions.sh to determine wpa-psk value type in
  plaintext or hex. This effectively eliminates the need for the bogus and
  somewhat confusing wpa-passphrase contruct specific to our scripts and
  allows wpa-psk to work with either a 8 to 63 character long plaintext
  string or 64 character long hex string.
* Adjust README.modes to not refer to the redundant wpa-passphrase stuff.
* Add big fat NOTE about acceptable wpa-psk's to top of example gallery.
* Strip surrounding quotes from wpa-ssid if present, instead of just whining
  about them.
* Update email address in copyright blurb of functions.sh, ifupdown.sh and
  wpa_action.sh.  

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * WPA Supplicant - Layer2 packet handling
3
 
 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi>
4
 
 *
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.
8
 
 *
9
 
 * Alternatively, this software may be distributed under the terms of BSD
10
 
 * license.
11
 
 *
12
 
 * See README and COPYING for more details.
13
 
 */
14
 
 
15
 
#include <stdlib.h>
16
 
#include <stdio.h>
17
 
#include <string.h>
18
 
#ifndef CONFIG_NATIVE_WINDOWS
19
 
#include <sys/ioctl.h>
20
 
#endif /* CONFIG_NATIVE_WINDOWS */
21
 
#include <errno.h>
22
 
#ifdef USE_DNET_PCAP
23
 
#include <pcap.h>
24
 
#ifndef CONFIG_WINPCAP
25
 
#include <dnet.h>
26
 
#endif
27
 
#else /* USE_DNET_PCAP */
28
 
#include <unistd.h>
29
 
#include <sys/types.h>
30
 
#include <sys/socket.h>
31
 
#include <netinet/in.h>
32
 
#include <netpacket/packet.h>
33
 
#include <net/if.h>
34
 
#endif /* USE_DNET_PCAP */
35
 
 
36
 
#include "common.h"
37
 
#include "eloop.h"
38
 
#include "l2_packet.h"
39
 
 
40
 
 
41
 
struct l2_packet_data {
42
 
#ifdef USE_DNET_PCAP
43
 
        pcap_t *pcap;
44
 
#ifndef CONFIG_WINPCAP
45
 
        eth_t *eth;
46
 
#endif
47
 
#else /* USE_DNET_PCAP */
48
 
        int fd; /* packet socket for EAPOL frames */
49
 
#endif /* USE_DNET_PCAP */
50
 
        char ifname[100];
51
 
        u8 own_addr[ETH_ALEN];
52
 
        void (*rx_callback)(void *ctx, unsigned char *src_addr,
53
 
                            unsigned char *buf, size_t len);
54
 
        void *rx_callback_ctx;
55
 
        int rx_l2_hdr; /* whether to include layer 2 (Ethernet) header in calls
56
 
                        * to rx_callback */
57
 
};
58
 
 
59
 
 
60
 
int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr)
61
 
{
62
 
        memcpy(addr, l2->own_addr, ETH_ALEN);
63
 
        return 0;
64
 
}
65
 
 
66
 
 
67
 
void l2_packet_set_rx_l2_hdr(struct l2_packet_data *l2, int rx_l2_hdr)
68
 
{
69
 
        l2->rx_l2_hdr = rx_l2_hdr;
70
 
}
71
 
 
72
 
 
73
 
#ifdef USE_DNET_PCAP
74
 
 
75
 
#ifndef CONFIG_WINPCAP
76
 
static int l2_packet_init_libdnet(struct l2_packet_data *l2)
77
 
{
78
 
        eth_addr_t own_addr;
79
 
 
80
 
        l2->eth = eth_open(l2->ifname);
81
 
        if (!l2->eth) {
82
 
                printf("Failed to open interface '%s'.\n", l2->ifname);
83
 
                perror("eth_open");
84
 
                return -1;
85
 
        }
86
 
 
87
 
        if (eth_get(l2->eth, &own_addr) < 0) {
88
 
                printf("Failed to get own hw address from interface '%s'.\n",
89
 
                       l2->ifname);
90
 
                perror("eth_get");
91
 
                eth_close(l2->eth);
92
 
                l2->eth = NULL;
93
 
                return -1;
94
 
        }
95
 
        memcpy(l2->own_addr, own_addr.data, ETH_ALEN);
96
 
 
97
 
        return 0;
98
 
}
99
 
#endif
100
 
 
101
 
 
102
 
#ifdef CONFIG_WINPCAP
103
 
int pcap_sendpacket(pcap_t *p, u_char *buf, int size);
104
 
#endif
105
 
 
106
 
int l2_packet_send(struct l2_packet_data *l2, u8 *buf, size_t len)
107
 
{
108
 
#ifdef CONFIG_WINPCAP
109
 
        return pcap_sendpacket(l2->pcap, buf, len);
110
 
#else
111
 
        return eth_send(l2->eth, buf, len);
112
 
#endif
113
 
}
114
 
 
115
 
 
116
 
static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx)
117
 
{
118
 
        struct l2_packet_data *l2 = eloop_ctx;
119
 
        pcap_t *pcap = sock_ctx;
120
 
        struct pcap_pkthdr hdr;
121
 
        const u_char *packet;
122
 
        struct l2_ethhdr *ethhdr;
123
 
        unsigned char *buf;
124
 
        size_t len;
125
 
 
126
 
        packet = pcap_next(pcap, &hdr);
127
 
 
128
 
        if (packet == NULL || hdr.caplen < sizeof(*ethhdr))
129
 
                return;
130
 
 
131
 
        ethhdr = (struct l2_ethhdr *) packet;
132
 
        if (l2->rx_l2_hdr) {
133
 
                buf = (unsigned char *) ethhdr;
134
 
                len = hdr.caplen;
135
 
        } else {
136
 
                buf = (unsigned char *) (ethhdr + 1);
137
 
                len = hdr.caplen - sizeof(*ethhdr);
138
 
        }
139
 
        l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len);
140
 
}
141
 
 
142
 
 
143
 
#ifdef CONFIG_WINPCAP
144
 
static void l2_packet_receive_timeout(void *eloop_ctx, void *timeout_ctx)
145
 
{
146
 
        struct l2_packet_data *l2 = eloop_ctx;
147
 
        pcap_t *pcap = timeout_ctx;
148
 
        /* Register new timeout before calling l2_packet_receive() since
149
 
         * receive handler may free this l2_packet instance (which will
150
 
         * cancel this timeout). */
151
 
        eloop_register_timeout(0, 100000, l2_packet_receive_timeout,
152
 
                               l2, pcap);
153
 
        l2_packet_receive(-1, eloop_ctx, timeout_ctx);
154
 
}
155
 
#endif /* CONFIG_WINPCAP */
156
 
 
157
 
 
158
 
static int l2_packet_init_libpcap(struct l2_packet_data *l2,
159
 
                                  unsigned short protocol)
160
 
{
161
 
        bpf_u_int32 pcap_maskp, pcap_netp;
162
 
        char pcap_filter[100], pcap_err[PCAP_ERRBUF_SIZE];
163
 
        struct bpf_program pcap_fp;
164
 
 
165
 
        pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err);
166
 
        l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 10, pcap_err);
167
 
        if (l2->pcap == NULL) {
168
 
                fprintf(stderr, "pcap_open_live: %s\n", pcap_err);
169
 
                fprintf(stderr, "ifname='%s'\n", l2->ifname);
170
 
                return -1;
171
 
        }
172
 
#ifndef CONFIG_WINPCAP
173
 
        if (pcap_datalink(l2->pcap) != DLT_EN10MB) {
174
 
                if (pcap_set_datalink(l2->pcap, DLT_EN10MB) < 0) {
175
 
                        fprintf(stderr, "pcap_set_datalinke(DLT_EN10MB): %s\n",
176
 
                                pcap_geterr(l2->pcap));
177
 
                        return -1;
178
 
                }
179
 
        }
180
 
#endif /* CONFIG_WINPCAP */
181
 
        snprintf(pcap_filter, sizeof(pcap_filter),
182
 
                 "ether dst " MACSTR " and ether proto 0x%x",
183
 
                 MAC2STR(l2->own_addr), protocol);
184
 
        if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0)
185
 
        {
186
 
                fprintf(stderr, "pcap_compile: %s\n",
187
 
                        pcap_geterr(l2->pcap));
188
 
                return -1;
189
 
        }
190
 
 
191
 
        if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) {
192
 
                fprintf(stderr, "pcap_setfilter: %s\n",
193
 
                        pcap_geterr(l2->pcap));
194
 
                return -1;
195
 
        }
196
 
 
197
 
        pcap_freecode(&pcap_fp);
198
 
#ifdef BIOCIMMEDIATE
199
 
        /*
200
 
         * When libpcap uses BPF we must enable "immediate mode" to
201
 
         * receive frames right away; otherwise the system may
202
 
         * buffer them for us.
203
 
         */
204
 
        {
205
 
                unsigned int on = 1;
206
 
                if (ioctl(pcap_fileno(l2->pcap), BIOCIMMEDIATE, &on) < 0) {
207
 
                        fprintf(stderr, "%s: cannot enable immediate mode on "
208
 
                                "interface %s: %s\n",
209
 
                                __func__, l2->ifname, strerror(errno));
210
 
                        /* XXX should we fail? */
211
 
                }
212
 
        }
213
 
#endif /* BIOCIMMEDIATE */
214
 
 
215
 
#ifdef CONFIG_WINPCAP
216
 
        eloop_register_timeout(0, 100000, l2_packet_receive_timeout,
217
 
                               l2, l2->pcap);
218
 
#else
219
 
        eloop_register_read_sock(pcap_get_selectable_fd(l2->pcap),
220
 
                                 l2_packet_receive, l2, l2->pcap);
221
 
#endif
222
 
 
223
 
        return 0;
224
 
}
225
 
 
226
 
 
227
 
 
228
 
struct l2_packet_data * l2_packet_init(
229
 
        const char *ifname, const u8 *own_addr, unsigned short protocol,
230
 
        void (*rx_callback)(void *ctx, unsigned char *src_addr,
231
 
                            unsigned char *buf, size_t len),
232
 
        void *rx_callback_ctx)
233
 
{
234
 
        struct l2_packet_data *l2;
235
 
 
236
 
        l2 = malloc(sizeof(struct l2_packet_data));
237
 
        if (l2 == NULL)
238
 
                return NULL;
239
 
        memset(l2, 0, sizeof(*l2));
240
 
        strncpy(l2->ifname, ifname, sizeof(l2->ifname));
241
 
        l2->rx_callback = rx_callback;
242
 
        l2->rx_callback_ctx = rx_callback_ctx;
243
 
 
244
 
#ifdef CONFIG_WINPCAP
245
 
        if (own_addr)
246
 
                memcpy(l2->own_addr, own_addr, ETH_ALEN);
247
 
#else
248
 
        if (l2_packet_init_libdnet(l2))
249
 
                return NULL;
250
 
#endif
251
 
 
252
 
        if (l2_packet_init_libpcap(l2, protocol)) {
253
 
#ifndef CONFIG_WINPCAP
254
 
                eth_close(l2->eth);
255
 
#endif
256
 
                free(l2);
257
 
                return NULL;
258
 
        }
259
 
 
260
 
        return l2;
261
 
}
262
 
 
263
 
 
264
 
void l2_packet_deinit(struct l2_packet_data *l2)
265
 
{
266
 
        if (l2 == NULL)
267
 
                return;
268
 
 
269
 
        if (l2->pcap)
270
 
                pcap_close(l2->pcap);
271
 
#ifdef CONFIG_WINPCAP
272
 
        eloop_cancel_timeout(l2_packet_receive_timeout, l2, l2->pcap);
273
 
#else
274
 
        if (l2->eth)
275
 
                eth_close(l2->eth);
276
 
#endif
277
 
        free(l2);
278
 
}
279
 
 
280
 
#else /* USE_DNET_PCAP */
281
 
 
282
 
int l2_packet_send(struct l2_packet_data *l2, u8 *buf, size_t len)
283
 
{
284
 
        int ret;
285
 
        ret = send(l2->fd, buf, len, 0);
286
 
        if (ret < 0)
287
 
                perror("l2_packet_send - send");
288
 
        return ret;
289
 
}
290
 
 
291
 
 
292
 
static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx)
293
 
{
294
 
        struct l2_packet_data *l2 = eloop_ctx;
295
 
        u8 buf[2300];
296
 
        int res;
297
 
        struct l2_ethhdr *ethhdr;
298
 
        unsigned char *pos;
299
 
        size_t len;
300
 
 
301
 
        res = recv(sock, buf, sizeof(buf), 0);
302
 
        if (res < 0) {
303
 
                perror("l2_packet_receive - recv");
304
 
                return;
305
 
        }
306
 
        if (res < sizeof(*ethhdr)) {
307
 
                printf("l2_packet_receive: Dropped too short %d packet\n",
308
 
                       res);
309
 
                return;
310
 
        }
311
 
 
312
 
        ethhdr = (struct l2_ethhdr *) buf;
313
 
 
314
 
        if (l2->rx_l2_hdr) {
315
 
                pos = (unsigned char *) buf;
316
 
                len = res;
317
 
        } else {
318
 
                pos = (unsigned char *) (ethhdr + 1);
319
 
                len = res - sizeof(*ethhdr);
320
 
        }
321
 
        l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, pos, len);
322
 
}
323
 
 
324
 
 
325
 
struct l2_packet_data * l2_packet_init(
326
 
        const char *ifname, const u8 *own_addr, unsigned short protocol,
327
 
        void (*rx_callback)(void *ctx, unsigned char *src_addr,
328
 
                            unsigned char *buf, size_t len),
329
 
        void *rx_callback_ctx)
330
 
{
331
 
        struct l2_packet_data *l2;
332
 
        struct ifreq ifr;
333
 
        struct sockaddr_ll ll;
334
 
 
335
 
        l2 = malloc(sizeof(struct l2_packet_data));
336
 
        if (l2 == NULL)
337
 
                return NULL;
338
 
        memset(l2, 0, sizeof(*l2));
339
 
        strncpy(l2->ifname, ifname, sizeof(l2->ifname));
340
 
        l2->rx_callback = rx_callback;
341
 
        l2->rx_callback_ctx = rx_callback_ctx;
342
 
 
343
 
        l2->fd = socket(PF_PACKET, SOCK_RAW, htons(protocol));
344
 
        if (l2->fd < 0) {
345
 
                perror("socket(PF_PACKET, SOCK_RAW)");
346
 
                free(l2);
347
 
                return NULL;
348
 
        }
349
 
        strncpy(ifr.ifr_name, l2->ifname, sizeof(ifr.ifr_name));
350
 
        if (ioctl(l2->fd, SIOCGIFINDEX, &ifr) < 0) {
351
 
                perror("ioctl[SIOCGIFINDEX]");
352
 
                close(l2->fd);
353
 
                free(l2);
354
 
                return NULL;
355
 
        }
356
 
 
357
 
        memset(&ll, 0, sizeof(ll));
358
 
        ll.sll_family = PF_PACKET;
359
 
        ll.sll_ifindex = ifr.ifr_ifindex;
360
 
        ll.sll_protocol = htons(protocol);
361
 
        if (bind(l2->fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
362
 
                perror("bind[PF_PACKET]");
363
 
                close(l2->fd);
364
 
                free(l2);
365
 
                return NULL;
366
 
        }
367
 
 
368
 
        if (ioctl(l2->fd, SIOCGIFHWADDR, &ifr) < 0) {
369
 
                perror("ioctl[SIOCGIFHWADDR]");
370
 
                close(l2->fd);
371
 
                free(l2);
372
 
                return NULL;
373
 
        }
374
 
        memcpy(l2->own_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
375
 
 
376
 
        eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL);
377
 
 
378
 
        return l2;
379
 
}
380
 
 
381
 
 
382
 
void l2_packet_deinit(struct l2_packet_data *l2)
383
 
{
384
 
        if (l2 == NULL)
385
 
                return;
386
 
 
387
 
        if (l2->fd >= 0) {
388
 
                eloop_unregister_read_sock(l2->fd);
389
 
                close(l2->fd);
390
 
        }
391
 
                
392
 
        free(l2);
393
 
}
394
 
 
395
 
#endif /* USE_DNET_PCAP */