~ubuntu-branches/ubuntu/hardy/wpasupplicant/hardy

« back to all changes in this revision

Viewing changes to src/drivers/driver_wired.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

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