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

« back to all changes in this revision

Viewing changes to driver_wired.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 - wired Ethernet driver interface
3
 
 * Copyright (c) 2005-2007, Jouni Malinen <j@w1.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 "includes.h"
16
 
#include <sys/ioctl.h>
17
 
#include <net/if.h>
18
 
#ifdef __linux__
19
 
#include <netpacket/packet.h>
20
 
#endif /* __linux__ */
21
 
#ifdef __FreeBSD__
22
 
#include <net/if_dl.h>
23
 
#endif /* __FreeBSD__ */
24
 
 
25
 
#include "common.h"
26
 
#include "driver.h"
27
 
#include "wpa_supplicant.h"
28
 
 
29
 
 
30
 
static const u8 pae_group_addr[ETH_ALEN] =
31
 
{ 0x01, 0x80, 0xc2, 0x00, 0x00, 0x03 };
32
 
 
33
 
 
34
 
struct wpa_driver_wired_data {
35
 
        void *ctx;
36
 
        int pf_sock;
37
 
        char ifname[IFNAMSIZ + 1];
38
 
        int membership, multi, iff_allmulti, iff_up;
39
 
};
40
 
 
41
 
 
42
 
static int wpa_driver_wired_get_ssid(void *priv, u8 *ssid)
43
 
{
44
 
        ssid[0] = 0;
45
 
        return 0;
46
 
}
47
 
 
48
 
 
49
 
static int wpa_driver_wired_get_bssid(void *priv, u8 *bssid)
50
 
{
51
 
        /* Report PAE group address as the "BSSID" for wired connection. */
52
 
        os_memcpy(bssid, pae_group_addr, ETH_ALEN);
53
 
        return 0;
54
 
}
55
 
 
56
 
 
57
 
static int wpa_driver_wired_get_ifflags(const char *ifname, int *flags)
58
 
{
59
 
        struct ifreq ifr;
60
 
        int s;
61
 
 
62
 
        s = socket(PF_INET, SOCK_DGRAM, 0);
63
 
        if (s < 0) {
64
 
                perror("socket");
65
 
                return -1;
66
 
        }
67
 
 
68
 
        os_memset(&ifr, 0, sizeof(ifr));
69
 
        os_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
70
 
        if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
71
 
                perror("ioctl[SIOCGIFFLAGS]");
72
 
                close(s);
73
 
                return -1;
74
 
        }
75
 
        close(s);
76
 
        *flags = ifr.ifr_flags & 0xffff;
77
 
        return 0;
78
 
}
79
 
 
80
 
 
81
 
static int wpa_driver_wired_set_ifflags(const char *ifname, int flags)
82
 
{
83
 
        struct ifreq ifr;
84
 
        int s;
85
 
 
86
 
        s = socket(PF_INET, SOCK_DGRAM, 0);
87
 
        if (s < 0) {
88
 
                perror("socket");
89
 
                return -1;
90
 
        }
91
 
 
92
 
        os_memset(&ifr, 0, sizeof(ifr));
93
 
        os_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
94
 
        ifr.ifr_flags = flags & 0xffff;
95
 
        if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
96
 
                perror("ioctl[SIOCSIFFLAGS]");
97
 
                close(s);
98
 
                return -1;
99
 
        }
100
 
        close(s);
101
 
        return 0;
102
 
}
103
 
 
104
 
 
105
 
static int wpa_driver_wired_multi(const char *ifname, const u8 *addr, int add)
106
 
{
107
 
        struct ifreq ifr;
108
 
        int s;
109
 
 
110
 
        s = socket(PF_INET, SOCK_DGRAM, 0);
111
 
        if (s < 0) {
112
 
                perror("socket");
113
 
                return -1;
114
 
        }
115
 
 
116
 
        os_memset(&ifr, 0, sizeof(ifr));
117
 
        os_strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
118
 
#ifdef __linux__
119
 
        ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
120
 
        os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
121
 
#endif /* __linux__ */
122
 
#ifdef __FreeBSD__
123
 
        {
124
 
                struct sockaddr_dl *dlp;
125
 
                dlp = (struct sockaddr_dl *) &ifr.ifr_addr;
126
 
                dlp->sdl_len = sizeof(struct sockaddr_dl);
127
 
                dlp->sdl_family = AF_LINK;
128
 
                dlp->sdl_index = 0;
129
 
                dlp->sdl_nlen = 0;
130
 
                dlp->sdl_alen = ETH_ALEN;
131
 
                dlp->sdl_slen = 0;
132
 
                os_memcpy(LLADDR(dlp), addr, ETH_ALEN); 
133
 
        }
134
 
#endif /* __FreeBSD__ */
135
 
 
136
 
        if (ioctl(s, add ? SIOCADDMULTI : SIOCDELMULTI, (caddr_t) &ifr) < 0) {
137
 
                perror("ioctl[SIOC{ADD/DEL}MULTI]");
138
 
                close(s);
139
 
                return -1;
140
 
        }
141
 
        close(s);
142
 
        return 0;
143
 
}
144
 
 
145
 
 
146
 
static int wpa_driver_wired_membership(struct wpa_driver_wired_data *drv,
147
 
                                       const u8 *addr, int add)
148
 
{
149
 
#ifdef __linux__
150
 
        struct packet_mreq mreq;
151
 
 
152
 
        if (drv->pf_sock == -1)
153
 
                return -1;
154
 
 
155
 
        os_memset(&mreq, 0, sizeof(mreq));
156
 
        mreq.mr_ifindex = if_nametoindex(drv->ifname);
157
 
        mreq.mr_type = PACKET_MR_MULTICAST;
158
 
        mreq.mr_alen = ETH_ALEN;
159
 
        os_memcpy(mreq.mr_address, addr, ETH_ALEN);
160
 
 
161
 
        if (setsockopt(drv->pf_sock, SOL_PACKET,
162
 
                       add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
163
 
                       &mreq, sizeof(mreq)) < 0) {
164
 
                perror("setsockopt");
165
 
                return -1;
166
 
        }
167
 
        return 0;
168
 
#else /* __linux__ */
169
 
        return -1;
170
 
#endif /* __linux__ */
171
 
}
172
 
 
173
 
 
174
 
static void * wpa_driver_wired_init(void *ctx, const char *ifname)
175
 
{
176
 
        struct wpa_driver_wired_data *drv;
177
 
        int flags;
178
 
 
179
 
        drv = os_zalloc(sizeof(*drv));
180
 
        if (drv == NULL)
181
 
                return NULL;
182
 
        os_strncpy(drv->ifname, ifname, sizeof(drv->ifname));
183
 
        drv->ctx = ctx;
184
 
 
185
 
#ifdef __linux__
186
 
        drv->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
187
 
        if (drv->pf_sock < 0)
188
 
                perror("socket(PF_PACKET)");
189
 
#else /* __linux__ */
190
 
        drv->pf_sock = -1;       
191
 
#endif /* __linux__ */
192
 
        
193
 
        if (wpa_driver_wired_get_ifflags(ifname, &flags) == 0 &&
194
 
            !(flags & IFF_UP) &&
195
 
            wpa_driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0) {
196
 
                drv->iff_up = 1;
197
 
        }
198
 
 
199
 
        if (wpa_driver_wired_membership(drv, pae_group_addr, 1) == 0) {
200
 
                wpa_printf(MSG_DEBUG, "%s: Added multicast membership with "
201
 
                           "packet socket", __func__);
202
 
                drv->membership = 1;
203
 
        } else if (wpa_driver_wired_multi(ifname, pae_group_addr, 1) == 0) {
204
 
                wpa_printf(MSG_DEBUG, "%s: Added multicast membership with "
205
 
                           "SIOCADDMULTI", __func__);
206
 
                drv->multi = 1;
207
 
        } else if (wpa_driver_wired_get_ifflags(ifname, &flags) < 0) {
208
 
                wpa_printf(MSG_INFO, "%s: Could not get interface "
209
 
                           "flags", __func__);
210
 
                os_free(drv);
211
 
                return NULL;
212
 
        } else if (flags & IFF_ALLMULTI) {
213
 
                wpa_printf(MSG_DEBUG, "%s: Interface is already configured "
214
 
                           "for multicast", __func__);
215
 
        } else if (wpa_driver_wired_set_ifflags(ifname,
216
 
                                                flags | IFF_ALLMULTI) < 0) {
217
 
                wpa_printf(MSG_INFO, "%s: Failed to enable allmulti",
218
 
                           __func__);
219
 
                os_free(drv);
220
 
                return NULL;
221
 
        } else {
222
 
                wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode",
223
 
                           __func__);
224
 
                drv->iff_allmulti = 1;
225
 
        }
226
 
 
227
 
        return drv;
228
 
}
229
 
 
230
 
 
231
 
static void wpa_driver_wired_deinit(void *priv)
232
 
{
233
 
        struct wpa_driver_wired_data *drv = priv;
234
 
        int flags;
235
 
 
236
 
        if (drv->membership &&
237
 
            wpa_driver_wired_membership(drv, pae_group_addr, 0) < 0) {
238
 
                wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast "
239
 
                           "group (PACKET)", __func__);
240
 
        }
241
 
 
242
 
        if (drv->multi &&
243
 
            wpa_driver_wired_multi(drv->ifname, pae_group_addr, 0) < 0) {
244
 
                wpa_printf(MSG_DEBUG, "%s: Failed to remove PAE multicast "
245
 
                           "group (SIOCDELMULTI)", __func__);
246
 
        }
247
 
 
248
 
        if (drv->iff_allmulti &&
249
 
            (wpa_driver_wired_get_ifflags(drv->ifname, &flags) < 0 ||
250
 
             wpa_driver_wired_set_ifflags(drv->ifname,
251
 
                                          flags & ~IFF_ALLMULTI) < 0)) {
252
 
                wpa_printf(MSG_DEBUG, "%s: Failed to disable allmulti mode",
253
 
                           __func__);
254
 
        }
255
 
 
256
 
        if (drv->iff_up &&
257
 
            wpa_driver_wired_get_ifflags(drv->ifname, &flags) == 0 &&
258
 
            (flags & IFF_UP) &&
259
 
            wpa_driver_wired_set_ifflags(drv->ifname, flags & ~IFF_UP) < 0) {
260
 
                wpa_printf(MSG_DEBUG, "%s: Failed to set the interface down",
261
 
                           __func__);
262
 
        }
263
 
 
264
 
        if (drv->pf_sock != -1)
265
 
                close(drv->pf_sock);
266
 
        
267
 
        os_free(drv);
268
 
}
269
 
 
270
 
 
271
 
const struct wpa_driver_ops wpa_driver_wired_ops = {
272
 
        .name = "wired",
273
 
        .desc = "wpa_supplicant wired Ethernet driver",
274
 
        .get_ssid = wpa_driver_wired_get_ssid,
275
 
        .get_bssid = wpa_driver_wired_get_bssid,
276
 
        .init = wpa_driver_wired_init,
277
 
        .deinit = wpa_driver_wired_deinit,
278
 
};