~ubuntu-branches/ubuntu/vivid/wpasupplicant/vivid

« back to all changes in this revision

Viewing changes to l2_packet_freebsd.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2008-03-12 20:03:04 UTC
  • mfrom: (1.1.10 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080312200304-4331y9wj46pdd34z
Tags: 0.6.3-1
* New upstream release.
* Drop patches applied upstream:
  - debian/patches/30_wpa_gui_qt4_eventhistoryui_rework.patch
  - debian/patches/31_wpa_gui_qt4_eventhistory_always_scrollbar.patch
  - debian/patches/32_wpa_gui_qt4_eventhistory_scroll_with_events.patch
  - debian/patches/40_dbus_ssid_data.patch
* Tidy up the clean target of debian/rules. Now that the madwifi headers are
  handled differently we no longer need to do any cleanup.
* Fix formatting error in debian/ifupdown/wpa_action.8 to make lintian
  quieter.
* Add patch to fix formatting errors in manpages build from sgml source. Use
  <emphasis> tags to hightlight keywords instead of surrounding them in
  strong quotes.
  - debian/patches/41_manpage_format_fixes.patch
* wpasupplicant binary package no longer suggests pcscd, guessnet, iproute
  or wireless-tools, nor does it recommend dhcp3-client. These are not
  needed.
* Add debian/patches/10_silence_siocsiwauth_icotl_failure.patch to disable
  ioctl failure messages that occur under normal conditions.
* Cherry pick two upstream git commits concerning the dbus interface:
  - debian/patches/11_avoid_dbus_version_namespace.patch
  - debian/patches/12_fix_potential_use_after_free.patch
* Add debian/patches/42_manpage_explain_available_drivers.patch to explain
  that not all of the driver backends are available in the provided
  wpa_supplicant binary, and that the canonical list of supported driver
  backends can be retrieved from the wpa_supplicant -h (help) output.
  (Closes: #466910)
* Add debian/patches/20_wpa_gui_qt4_disable_link_prl.patch to remove
  link_prl CONFIG compile flag added by qmake-qt4 >= 4.3.4-2 to avoid excess
  linking.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * WPA Supplicant - Layer2 packet handling with FreeBSD
3
 
 * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
4
 
 * Copyright (c) 2005, Sam Leffler <sam@errno.com>
5
 
 *
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.
9
 
 *
10
 
 * Alternatively, this software may be distributed under the terms of BSD
11
 
 * license.
12
 
 *
13
 
 * See README and COPYING for more details.
14
 
 */
15
 
 
16
 
#include "includes.h"
17
 
#include <pcap.h>
18
 
 
19
 
#include <sys/ioctl.h>
20
 
#include <sys/sysctl.h>
21
 
 
22
 
#include <net/if.h>
23
 
#include <net/if_dl.h>
24
 
#include <net/route.h>
25
 
#include <netinet/in.h>
26
 
 
27
 
#include "common.h"
28
 
#include "eloop.h"
29
 
#include "l2_packet.h"
30
 
 
31
 
 
32
 
static const u8 pae_group_addr[ETH_ALEN] =
33
 
{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
34
 
 
35
 
struct l2_packet_data {
36
 
        pcap_t *pcap;
37
 
        char ifname[100];
38
 
        u8 own_addr[ETH_ALEN];
39
 
        void (*rx_callback)(void *ctx, const u8 *src_addr,
40
 
                            const u8 *buf, size_t len);
41
 
        void *rx_callback_ctx;
42
 
        int l2_hdr; /* whether to include layer 2 (Ethernet) header data
43
 
                     * buffers */
44
 
};
45
 
 
46
 
 
47
 
int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr)
48
 
{
49
 
        os_memcpy(addr, l2->own_addr, ETH_ALEN);
50
 
        return 0;
51
 
}
52
 
 
53
 
 
54
 
int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto,
55
 
                   const u8 *buf, size_t len)
56
 
{
57
 
        if (!l2->l2_hdr) {
58
 
                int ret;
59
 
                struct l2_ethhdr *eth = os_malloc(sizeof(*eth) + len);
60
 
                if (eth == NULL)
61
 
                        return -1;
62
 
                os_memcpy(eth->h_dest, dst_addr, ETH_ALEN);
63
 
                os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN);
64
 
                eth->h_proto = htons(proto);
65
 
                os_memcpy(eth + 1, buf, len);
66
 
                ret = pcap_inject(l2->pcap, (u8 *) eth, len + sizeof(*eth));
67
 
                os_free(eth);
68
 
                return ret;
69
 
        } else
70
 
                return pcap_inject(l2->pcap, buf, len);
71
 
}
72
 
 
73
 
 
74
 
static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx)
75
 
{
76
 
        struct l2_packet_data *l2 = eloop_ctx;
77
 
        pcap_t *pcap = sock_ctx;
78
 
        struct pcap_pkthdr hdr;
79
 
        const u_char *packet;
80
 
        struct l2_ethhdr *ethhdr;
81
 
        unsigned char *buf;
82
 
        size_t len;
83
 
 
84
 
        packet = pcap_next(pcap, &hdr);
85
 
 
86
 
        if (packet == NULL || hdr.caplen < sizeof(*ethhdr))
87
 
                return;
88
 
 
89
 
        ethhdr = (struct l2_ethhdr *) packet;
90
 
        if (l2->l2_hdr) {
91
 
                buf = (unsigned char *) ethhdr;
92
 
                len = hdr.caplen;
93
 
        } else {
94
 
                buf = (unsigned char *) (ethhdr + 1);
95
 
                len = hdr.caplen - sizeof(*ethhdr);
96
 
        }
97
 
        l2->rx_callback(l2->rx_callback_ctx, ethhdr->h_source, buf, len);
98
 
}
99
 
 
100
 
 
101
 
static int l2_packet_init_libpcap(struct l2_packet_data *l2,
102
 
                                  unsigned short protocol)
103
 
{
104
 
        bpf_u_int32 pcap_maskp, pcap_netp;
105
 
        char pcap_filter[200], pcap_err[PCAP_ERRBUF_SIZE];
106
 
        struct bpf_program pcap_fp;
107
 
 
108
 
        pcap_lookupnet(l2->ifname, &pcap_netp, &pcap_maskp, pcap_err);
109
 
        l2->pcap = pcap_open_live(l2->ifname, 2500, 0, 10, pcap_err);
110
 
        if (l2->pcap == NULL) {
111
 
                fprintf(stderr, "pcap_open_live: %s\n", pcap_err);
112
 
                fprintf(stderr, "ifname='%s'\n", l2->ifname);
113
 
                return -1;
114
 
        }
115
 
        if (pcap_datalink(l2->pcap) != DLT_EN10MB &&
116
 
            pcap_set_datalink(l2->pcap, DLT_EN10MB) < 0) {
117
 
                fprintf(stderr, "pcap_set_datalink(DLT_EN10MB): %s\n",
118
 
                        pcap_geterr(l2->pcap));
119
 
                return -1;
120
 
        }
121
 
        os_snprintf(pcap_filter, sizeof(pcap_filter),
122
 
                    "not ether src " MACSTR " and "
123
 
                    "( ether dst " MACSTR " or ether dst " MACSTR " ) and "
124
 
                    "ether proto 0x%x",
125
 
                    MAC2STR(l2->own_addr), /* do not receive own packets */
126
 
                    MAC2STR(l2->own_addr), MAC2STR(pae_group_addr),
127
 
                    protocol);
128
 
        if (pcap_compile(l2->pcap, &pcap_fp, pcap_filter, 1, pcap_netp) < 0) {
129
 
                fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(l2->pcap));
130
 
                return -1;
131
 
        }
132
 
 
133
 
        if (pcap_setfilter(l2->pcap, &pcap_fp) < 0) {
134
 
                fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(l2->pcap));
135
 
                return -1;
136
 
        }
137
 
 
138
 
        pcap_freecode(&pcap_fp);
139
 
        /*
140
 
         * When libpcap uses BPF we must enable "immediate mode" to
141
 
         * receive frames right away; otherwise the system may
142
 
         * buffer them for us.
143
 
         */
144
 
        {
145
 
                unsigned int on = 1;
146
 
                if (ioctl(pcap_fileno(l2->pcap), BIOCIMMEDIATE, &on) < 0) {
147
 
                        fprintf(stderr, "%s: cannot enable immediate mode on "
148
 
                                "interface %s: %s\n",
149
 
                                __func__, l2->ifname, strerror(errno));
150
 
                        /* XXX should we fail? */
151
 
                }
152
 
        }
153
 
 
154
 
        eloop_register_read_sock(pcap_get_selectable_fd(l2->pcap),
155
 
                                 l2_packet_receive, l2, l2->pcap);
156
 
 
157
 
        return 0;
158
 
}
159
 
 
160
 
 
161
 
static int eth_get(const char *device, u8 ea[ETH_ALEN])
162
 
{
163
 
        struct if_msghdr *ifm;
164
 
        struct sockaddr_dl *sdl;
165
 
        u_char *p, *buf;
166
 
        size_t len;
167
 
        int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 };
168
 
 
169
 
        if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0)
170
 
                return -1;
171
 
        if ((buf = os_malloc(len)) == NULL)
172
 
                return -1;
173
 
        if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
174
 
                os_free(buf);
175
 
                return -1;
176
 
        }
177
 
        for (p = buf; p < buf + len; p += ifm->ifm_msglen) {
178
 
                ifm = (struct if_msghdr *)p;
179
 
                sdl = (struct sockaddr_dl *)(ifm + 1);
180
 
                if (ifm->ifm_type != RTM_IFINFO ||
181
 
                    (ifm->ifm_addrs & RTA_IFP) == 0)
182
 
                        continue;
183
 
                if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 ||
184
 
                    os_memcmp(sdl->sdl_data, device, sdl->sdl_nlen) != 0)
185
 
                        continue;
186
 
                os_memcpy(ea, LLADDR(sdl), sdl->sdl_alen);
187
 
                break;
188
 
        }
189
 
        os_free(buf);
190
 
 
191
 
        if (p >= buf + len) {
192
 
                errno = ESRCH;
193
 
                return -1;
194
 
        }
195
 
        return 0;
196
 
}
197
 
 
198
 
 
199
 
struct l2_packet_data * l2_packet_init(
200
 
        const char *ifname, const u8 *own_addr, unsigned short protocol,
201
 
        void (*rx_callback)(void *ctx, const u8 *src_addr,
202
 
                            const u8 *buf, size_t len),
203
 
        void *rx_callback_ctx, int l2_hdr)
204
 
{
205
 
        struct l2_packet_data *l2;
206
 
 
207
 
        l2 = os_zalloc(sizeof(struct l2_packet_data));
208
 
        if (l2 == NULL)
209
 
                return NULL;
210
 
        os_strncpy(l2->ifname, ifname, sizeof(l2->ifname));
211
 
        l2->rx_callback = rx_callback;
212
 
        l2->rx_callback_ctx = rx_callback_ctx;
213
 
        l2->l2_hdr = l2_hdr;
214
 
 
215
 
        if (eth_get(l2->ifname, l2->own_addr) < 0) {
216
 
                fprintf(stderr, "Failed to get link-level address for "
217
 
                        "interface '%s'.\n", l2->ifname);
218
 
                os_free(l2);
219
 
                return NULL;
220
 
        }
221
 
 
222
 
        if (l2_packet_init_libpcap(l2, protocol)) {
223
 
                os_free(l2);
224
 
                return NULL;
225
 
        }
226
 
 
227
 
        return l2;
228
 
}
229
 
 
230
 
 
231
 
void l2_packet_deinit(struct l2_packet_data *l2)
232
 
{
233
 
        if (l2 != NULL) {
234
 
                if (l2->pcap)
235
 
                        pcap_close(l2->pcap);
236
 
                os_free(l2);
237
 
        }
238
 
}
239
 
 
240
 
 
241
 
int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len)
242
 
{
243
 
        pcap_if_t *devs, *dev;
244
 
        struct pcap_addr *addr;
245
 
        struct sockaddr_in *saddr;
246
 
        int found = 0;
247
 
        char err[PCAP_ERRBUF_SIZE + 1];
248
 
 
249
 
        if (pcap_findalldevs(&devs, err) < 0) {
250
 
                wpa_printf(MSG_DEBUG, "pcap_findalldevs: %s\n", err);
251
 
                return -1;
252
 
        }
253
 
 
254
 
        for (dev = devs; dev && !found; dev = dev->next) {
255
 
                if (os_strcmp(dev->name, l2->ifname) != 0)
256
 
                        continue;
257
 
 
258
 
                addr = dev->addresses;
259
 
                while (addr) {
260
 
                        saddr = (struct sockaddr_in *) addr->addr;
261
 
                        if (saddr && saddr->sin_family == AF_INET) {
262
 
                                os_snprintf(buf, len, "%s",
263
 
                                            inet_ntoa(saddr->sin_addr));
264
 
                                found = 1;
265
 
                                break;
266
 
                        }
267
 
                        addr = addr->next;
268
 
                }
269
 
        }
270
 
 
271
 
        pcap_freealldevs(devs);
272
 
 
273
 
        return found ? 0 : -1;
274
 
}
275
 
 
276
 
 
277
 
void l2_packet_notify_auth_start(struct l2_packet_data *l2)
278
 
{
279
 
}