1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
|
diff -u -p linux/include/linux/wireless.14.h linux/include/linux/wireless.h
--- linux/include/linux/wireless.14.h Mon Dec 2 18:51:00 2002
+++ linux/include/linux/wireless.h Mon Dec 2 18:53:35 2002
@@ -1,7 +1,7 @@
/*
* This file define a set of standard wireless extensions
*
- * Version : 14 25.1.02
+ * Version : 15 12.7.02
*
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Copyright (c) 1997-2002 Jean Tourrilhes, All Rights Reserved.
@@ -80,7 +80,7 @@
* (there is some stuff that will be added in the future...)
* I just plan to increment with each new version.
*/
-#define WIRELESS_EXT 14
+#define WIRELESS_EXT 15
/*
* Changes :
@@ -153,17 +153,32 @@
* - Define additional specific event numbers
* - Add "addr" and "param" fields in union iwreq_data
* - AP scanning stuff (SIOCSIWSCAN and friends)
+ *
+ * V14 to V15
+ * ----------
+ * - Add IW_PRIV_TYPE_ADDR for struct sockaddr private arg
+ * - Make struct iw_freq signed (both m & e), add explicit padding
+ * - Add IWEVCUSTOM for driver specific event/scanning token
+ * - Add IW_MAX_GET_SPY for driver returning a lot of addresses
+ * - Add IW_TXPOW_RANGE for range of Tx Powers
+ * - Add IWEVREGISTERED & IWEVEXPIRED events for Access Points
+ * - Add IW_MODE_MONITOR for passive monitor
*/
/**************************** CONSTANTS ****************************/
/* -------------------------- IOCTL LIST -------------------------- */
-/* Basic operations */
+/* Wireless Identification */
#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */
#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
-#define SIOCSIWNWID 0x8B02 /* set network id (the cell) */
-#define SIOCGIWNWID 0x8B03 /* get network id */
+/* SIOCGIWNAME is used to verify the presence of Wireless Extensions.
+ * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"...
+ * Don't put the name of your driver there, it's useless. */
+
+/* Basic operations */
+#define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */
+#define SIOCGIWNWID 0x8B03 /* get network id (the cell) */
#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */
#define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */
#define SIOCSIWMODE 0x8B06 /* set operation mode */
@@ -178,16 +193,18 @@
#define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */
#define SIOCSIWSTATS 0x8B0E /* Unused */
#define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */
+/* SIOCGIWSTATS is strictly used between user space and the kernel, and
+ * is never passed to the driver (i.e. the driver will never see it). */
-/* Mobile IP support */
+/* Mobile IP support (statistics per MAC address) */
#define SIOCSIWSPY 0x8B10 /* set spy addresses */
#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */
/* Access Point manipulation */
#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */
#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */
-#define SIOCGIWAPLIST 0x8B17 /* get list of access point in range */
-#define SIOCSIWSCAN 0x8B18 /* trigger scanning */
+#define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */
+#define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */
#define SIOCGIWSCAN 0x8B19 /* get scanning results */
/* 802.11 specific support */
@@ -197,9 +214,7 @@
#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */
/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit
* within the 'iwreq' structure, so we need to use the 'data' member to
- * point to a string in user space, like it is done for RANGE...
- * The "flags" member indicate if the ESSID is active or not (promiscuous).
- */
+ * point to a string in user space, like it is done for RANGE... */
/* Other parameters useful in 802.11 and some other devices */
#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */
@@ -257,7 +272,10 @@
/* Most events use the same identifier as ioctl requests */
#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */
-#define IWEVQUAL 0x8C01 /* Quality part of statistics */
+#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */
+#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */
+#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */
+#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */
#define IWEVFIRST 0x8C00
@@ -273,7 +291,8 @@
#define IW_PRIV_TYPE_BYTE 0x1000 /* Char as number */
#define IW_PRIV_TYPE_CHAR 0x2000 /* Char as character */
#define IW_PRIV_TYPE_INT 0x4000 /* 32 bits int */
-#define IW_PRIV_TYPE_FLOAT 0x5000
+#define IW_PRIV_TYPE_FLOAT 0x5000 /* struct iw_freq */
+#define IW_PRIV_TYPE_ADDR 0x6000 /* struct sockaddr */
#define IW_PRIV_SIZE_FIXED 0x0800 /* Variable or fixed nuber of args */
@@ -297,13 +316,16 @@
/* Maximum tx powers in the range struct */
#define IW_MAX_TXPOWER 8
+/* Note : if you more than 8 TXPowers, just set the max and min or
+ * a few of them in the struct iw_range. */
/* Maximum of address that you may set with SPY */
-#define IW_MAX_SPY 8
+#define IW_MAX_SPY 8 /* set */
+#define IW_MAX_GET_SPY 64 /* get */
/* Maximum of address that you may get in the
list of access points in range */
-#define IW_MAX_AP 8
+#define IW_MAX_AP 64
/* Maximum size of the ESSID and NICKN strings */
#define IW_ESSID_MAX_SIZE 32
@@ -315,6 +337,7 @@
#define IW_MODE_MASTER 3 /* Synchronisation master or Access Point */
#define IW_MODE_REPEAT 4 /* Wireless Repeater (forwarder) */
#define IW_MODE_SECOND 5 /* Secondary master/repeater (backup) */
+#define IW_MODE_MONITOR 6 /* Passive monitor (listen only) */
/* Maximum number of size of encoding token available
* they are listed in the range structure */
@@ -350,8 +373,10 @@
#define IW_POWER_RELATIVE 0x0004 /* Value is not in seconds/ms/us */
/* Transmit Power flags available */
+#define IW_TXPOW_TYPE 0x00FF /* Type of value */
#define IW_TXPOW_DBM 0x0000 /* Value is in dBm */
#define IW_TXPOW_MWATT 0x0001 /* Value is in mW */
+#define IW_TXPOW_RANGE 0x1000 /* Range of value between min/max */
/* Retry limits and lifetime flags available */
#define IW_RETRY_ON 0x0000 /* No details... */
@@ -376,6 +401,9 @@
/* Maximum size of returned data */
#define IW_SCAN_MAX_DATA 4096 /* In bytes */
+/* Max number of char in custom event - use multiple of them if needed */
+#define IW_CUSTOM_MAX 256 /* In bytes */
+
/****************************** TYPES ******************************/
/* --------------------------- SUBTYPES --------------------------- */
@@ -411,9 +439,10 @@ struct iw_point
*/
struct iw_freq
{
- __u32 m; /* Mantissa */
- __u16 e; /* Exponent */
+ __s32 m; /* Mantissa */
+ __s16 e; /* Exponent */
__u8 i; /* List index (when in range struct) */
+ __u8 pad; /* Unused - just for alignement */
};
/*
diff -u -p linux/include/net/iw_handler.14.h linux/include/net/iw_handler.h
--- linux/include/net/iw_handler.14.h Mon Dec 2 18:51:17 2002
+++ linux/include/net/iw_handler.h Mon Dec 2 18:54:51 2002
@@ -1,7 +1,7 @@
/*
* This file define the new driver API for Wireless Extensions
*
- * Version : 3 17.1.02
+ * Version : 4 21.6.02
*
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
* Copyright (c) 2001-2002 Jean Tourrilhes, All Rights Reserved.
@@ -206,7 +206,7 @@
* will be needed...
* I just plan to increment with each new version.
*/
-#define IW_HANDLER_VERSION 3
+#define IW_HANDLER_VERSION 4
/*
* Changes :
@@ -217,6 +217,9 @@
* - Add Wireless Event support :
* o wireless_send_event() prototype
* o iwe_stream_add_event/point() inline functions
+ * V3 to V4
+ * --------
+ * - Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
*/
/**************************** CONSTANTS ****************************/
@@ -233,10 +236,10 @@
#define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */
#define IW_HEADER_TYPE_UINT 4 /* __u32 */
#define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */
-#define IW_HEADER_TYPE_POINT 6 /* struct iw_point */
-#define IW_HEADER_TYPE_PARAM 7 /* struct iw_param */
-#define IW_HEADER_TYPE_ADDR 8 /* struct sockaddr */
-#define IW_HEADER_TYPE_QUAL 9 /* struct iw_quality */
+#define IW_HEADER_TYPE_ADDR 6 /* struct sockaddr */
+#define IW_HEADER_TYPE_POINT 8 /* struct iw_point */
+#define IW_HEADER_TYPE_PARAM 9 /* struct iw_param */
+#define IW_HEADER_TYPE_QUAL 10 /* struct iw_quality */
/* Handling flags */
/* Most are not implemented. I just use them as a reminder of some
diff -u -p linux/net/core/wireless.14.c linux/net/core/wireless.c
--- linux/net/core/wireless.14.c Mon Dec 2 18:51:35 2002
+++ linux/net/core/wireless.c Mon Dec 2 18:53:10 2002
@@ -33,8 +33,16 @@
* o Propagate events as rtnetlink IFLA_WIRELESS option
* o Generate event on selected SET requests
*
- * v4 - 18.04.01 - Jean II
+ * v4 - 18.04.02 - Jean II
* o Fix stupid off by one in iw_ioctl_description : IW_ESSID_MAX_SIZE + 1
+ *
+ * v5 - 21.06.02 - Jean II
+ * o Add IW_PRIV_TYPE_ADDR in priv_type_size (+cleanup)
+ * o Reshuffle IW_HEADER_TYPE_XXX to map IW_PRIV_TYPE_XXX changes
+ * o Add IWEVCUSTOM for driver specific event/scanning token
+ * o Turn on WE_STRICT_WRITE by default + kernel warning
+ * o Fix WE_STRICT_WRITE in ioctl_export_private() (32 => iw_num)
+ * o Fix off-by-one in test (extra_size <= IFNAMSIZ)
*/
/***************************** INCLUDES *****************************/
@@ -50,8 +58,9 @@
/**************************** CONSTANTS ****************************/
-/* This will be turned on later on... */
-#undef WE_STRICT_WRITE /* Check write buffer size */
+/* Enough lenience, let's make sure things are proper... */
+#define WE_STRICT_WRITE /* Check write buffer size */
+/* I'll probably drop both the define and kernel message in the next version */
/* Debuging stuff */
#undef WE_IOCTL_DEBUG /* Debug IOCTL API */
@@ -106,7 +115,7 @@ static const struct iw_ioctl_description
/* SIOCSIWSPY */
{ IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0},
/* SIOCGIWSPY */
- { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_SPY, 0},
+ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_GET_SPY, 0},
/* -- hole -- */
{ IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
/* -- hole -- */
@@ -176,25 +185,41 @@ static const struct iw_ioctl_description
{ IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
/* IWEVQUAL */
{ IW_HEADER_TYPE_QUAL, 0, 0, 0, 0, 0},
+ /* IWEVCUSTOM */
+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_CUSTOM_MAX, 0},
+ /* IWEVREGISTERED */
+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
+ /* IWEVEXPIRED */
+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
};
static const int standard_event_num = (sizeof(standard_event) /
sizeof(struct iw_ioctl_description));
/* Size (in bytes) of the various private data types */
-static const char priv_type_size[] = { 0, 1, 1, 0, 4, 4, 0, 0 };
+static const char priv_type_size[] = {
+ 0, /* IW_PRIV_TYPE_NONE */
+ 1, /* IW_PRIV_TYPE_BYTE */
+ 1, /* IW_PRIV_TYPE_CHAR */
+ 0, /* Not defined */
+ sizeof(__u32), /* IW_PRIV_TYPE_INT */
+ sizeof(struct iw_freq), /* IW_PRIV_TYPE_FLOAT */
+ sizeof(struct sockaddr), /* IW_PRIV_TYPE_ADDR */
+ 0, /* Not defined */
+};
/* Size (in bytes) of various events */
static const int event_type_size[] = {
- IW_EV_LCP_LEN,
+ IW_EV_LCP_LEN, /* IW_HEADER_TYPE_NULL */
+ 0,
+ IW_EV_CHAR_LEN, /* IW_HEADER_TYPE_CHAR */
0,
- IW_EV_CHAR_LEN,
+ IW_EV_UINT_LEN, /* IW_HEADER_TYPE_UINT */
+ IW_EV_FREQ_LEN, /* IW_HEADER_TYPE_FREQ */
+ IW_EV_ADDR_LEN, /* IW_HEADER_TYPE_ADDR */
0,
- IW_EV_UINT_LEN,
- IW_EV_FREQ_LEN,
IW_EV_POINT_LEN, /* Without variable payload */
- IW_EV_PARAM_LEN,
- IW_EV_ADDR_LEN,
- IW_EV_QUAL_LEN,
+ IW_EV_PARAM_LEN, /* IW_HEADER_TYPE_PARAM */
+ IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */
};
/************************ COMMON SUBROUTINES ************************/
@@ -440,8 +465,10 @@ static inline int ioctl_export_private(s
return -EFAULT;
#ifdef WE_STRICT_WRITE
/* Check if there is enough buffer up there */
- if(iwr->u.data.length < (SIOCIWLASTPRIV - SIOCIWFIRSTPRIV + 1))
+ if(iwr->u.data.length < dev->wireless_handlers->num_private_args) {
+ printk(KERN_ERR "%s (WE) : Buffer for request SIOCGIWPRIV too small (%d<%d)\n", dev->name, iwr->u.data.length, dev->wireless_handlers->num_private_args);
return -E2BIG;
+ }
#endif /* WE_STRICT_WRITE */
/* Set the number of available ioctls. */
@@ -471,6 +498,7 @@ static inline int ioctl_standard_call(st
const struct iw_ioctl_description * descr;
struct iw_request_info info;
int ret = -EINVAL;
+ int user_size = 0;
/* Get the description of the IOCTL */
if((cmd - SIOCIWFIRST) >= standard_ioctl_num)
@@ -518,11 +546,8 @@ static inline int ioctl_standard_call(st
/* Check NULL pointer */
if(iwr->u.data.pointer == NULL)
return -EFAULT;
-#ifdef WE_STRICT_WRITE
- /* Check if there is enough buffer up there */
- if(iwr->u.data.length < descr->max_tokens)
- return -E2BIG;
-#endif /* WE_STRICT_WRITE */
+ /* Save user space buffer size for checking */
+ user_size = iwr->u.data.length;
}
#ifdef WE_IOCTL_DEBUG
@@ -559,6 +584,15 @@ static inline int ioctl_standard_call(st
/* If we have something to return to the user */
if (!ret && IW_IS_GET(cmd)) {
+#ifdef WE_STRICT_WRITE
+ /* Check if there is enough buffer up there */
+ if(user_size < iwr->u.data.length) {
+ printk(KERN_ERR "%s (WE) : Buffer for request %04X too small (%d<%d)\n", dev->name, cmd, user_size, iwr->u.data.length);
+ kfree(extra);
+ return -E2BIG;
+ }
+#endif /* WE_STRICT_WRITE */
+
err = copy_to_user(iwr->u.data.pointer, extra,
iwr->u.data.length *
descr->token_size);
@@ -646,12 +680,18 @@ static inline int ioctl_private_call(str
/* Compute the size of the set/get arguments */
if(descr != NULL) {
if(IW_IS_SET(cmd)) {
+ int offset = 0; /* For sub-ioctls */
+ /* Check for sub-ioctl handler */
+ if(descr->name[0] == '\0')
+ /* Reserve one int for sub-ioctl index */
+ offset = sizeof(__u32);
+
/* Size of set arguments */
extra_size = get_priv_size(descr->set_args);
/* Does it fits in iwr ? */
if((descr->set_args & IW_PRIV_SIZE_FIXED) &&
- (extra_size < IFNAMSIZ))
+ ((extra_size + offset) <= IFNAMSIZ))
extra_size = 0;
} else {
/* Size of set arguments */
@@ -659,7 +699,7 @@ static inline int ioctl_private_call(str
/* Does it fits in iwr ? */
if((descr->get_args & IW_PRIV_SIZE_FIXED) &&
- (extra_size < IFNAMSIZ))
+ (extra_size <= IFNAMSIZ))
extra_size = 0;
}
}
@@ -925,7 +965,7 @@ void wireless_send_event(struct net_devi
* The best the driver could do is to log an error message.
* We will do it ourselves instead...
*/
- printk(KERN_ERR "%s (WE) : Invalid Wireless Event (0x%04X)\n",
+ printk(KERN_ERR "%s (WE) : Invalid/Unknown Wireless Event (0x%04X)\n",
dev->name, cmd);
return;
}
|