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

« back to all changes in this revision

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