from now on, master branch will hold www only.
[libicd-wpa] / patches / cx3110-module-src-2.0.15.patch
1 diff -rup src.orig/sm_drv_ioctl_umac.c src/sm_drv_ioctl_umac.c
2 --- src.orig/sm_drv_ioctl_umac.c        2009-02-16 23:51:34.000000000 +0100
3 +++ src/sm_drv_ioctl_umac.c     2009-02-23 00:19:10.000000000 +0100
4 @@ -1928,6 +1928,435 @@ static int sm_drv_set_pmk(struct net_dev
5                               (void *)&key, sizeof(struct obj_stakey));
6  }
7  
8 +static int sm_drv_set_auth(struct net_device *dev,
9 +                          struct iw_request_info *info,
10 +                          union iwreq_data *wrqu, char *extra)
11 +{
12 +       struct net_local *priv = netdev_priv(dev);
13 +       struct iw_param *param = &wrqu->param;
14 +       u32 authen = 0, dot1x = 0;
15 +       u32 exunencrypt = 0, privinvoked = 0, wpa = 0;
16 +       u32 old_wpa;
17 +       int ret = 0;
18 +
19 +       DEBUG(DBG_IOCTL, "SET AUTH\n");
20 +
21 +       /* first get the flags */
22 +       down(&priv->wpa_sem);
23 +       wpa = old_wpa = priv->wpa;
24 +       up(&priv->wpa_sem);
25 +       ret = sm_drv_oid_get(dev, DOT11_OID_AUTHENABLE,
26 +                            (void *)&authen, sizeof(uint32_t));
27 +       ret |= sm_drv_oid_get(dev, DOT11_OID_PRIVACYINVOKED,
28 +                             (void *)&privinvoked, sizeof(uint32_t));
29 +       ret |= sm_drv_oid_get(dev, DOT11_OID_EXUNENCRYPTED,
30 +                             (void *)&exunencrypt, sizeof(uint32_t));
31 +       ret |= sm_drv_oid_get(dev, DOT11_OID_DOT1XENABLE,
32 +                             (void *)&dot1x, sizeof(uint32_t));
33 +
34 +       if (ret < 0)
35 +               goto out;
36 +
37 +       switch (param->flags & IW_AUTH_INDEX) {
38 +       case IW_AUTH_CIPHER_PAIRWISE:
39 +       case IW_AUTH_CIPHER_GROUP:
40 +       case IW_AUTH_KEY_MGMT:
41 +               break;
42 +
43 +       case IW_AUTH_WPA_ENABLED:
44 +               /* Do the same thing as IW_AUTH_WPA_VERSION */
45 +               if (param->value) {
46 +                       wpa = DOT11_PRIV_INV_TKIP;
47 +                       privinvoked = 1; /* For privacy invoked */
48 +                       exunencrypt = 1; /* Filter out all unencrypted frames */
49 +                       dot1x = 0x01; /* To enable eap filter */
50 +                       authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */
51 +               } else {
52 +                       wpa = DOT11_PRIV_INV_NONE;
53 +                       privinvoked = 0;
54 +                       exunencrypt = 0; /* Do not filter un-encrypted data */
55 +                       dot1x = 0;
56 +               }
57 +               break;
58 +
59 +       case IW_AUTH_WPA_VERSION:
60 +               if (param->value & IW_AUTH_WPA_VERSION_DISABLED) {
61 +                       wpa = DOT11_PRIV_INV_NONE;
62 +                       privinvoked = 0;
63 +                       exunencrypt = 0; /* Do not filter un-encrypted data */
64 +                       dot1x = 0;
65 +               } else {
66 +                       if (param->value & IW_AUTH_WPA_VERSION_WPA)
67 +                               wpa = DOT11_PRIV_INV_TKIP;
68 +                       else if (param->value & IW_AUTH_WPA_VERSION_WPA2)
69 +                               wpa = DOT11_PRIV_INV_AES_CCMP;
70 +                       privinvoked = 1; /* For privacy invoked */
71 +                       exunencrypt = 1; /* Filter out all unencrypted frames */
72 +                       dot1x = 0x01; /* To enable eap filter */
73 +                       authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */
74 +               }
75 +               break;
76 +
77 +       case IW_AUTH_RX_UNENCRYPTED_EAPOL:
78 +               /* dot1x should be the opposite of RX_UNENCRYPTED_EAPOL;
79 +                * turn off dot1x when allowing receipt of unencrypted EAPOL
80 +                * frames, turn on dot1x when receipt should be disallowed
81 +                */
82 +               dot1x = param->value ? 0 : 0x01;
83 +               break;
84 +
85 +       case IW_AUTH_PRIVACY_INVOKED:
86 +               privinvoked = param->value ? 1 : 0;
87 +               break;
88 +
89 +       case IW_AUTH_DROP_UNENCRYPTED:
90 +               exunencrypt = param->value ? 1 : 0;
91 +               break;
92 +
93 +       case IW_AUTH_80211_AUTH_ALG:
94 +               if (param->value & IW_AUTH_ALG_SHARED_KEY) {
95 +                       /* Only WEP uses _SK and _BOTH */
96 +                       if (wpa > 0) {
97 +                               ret = -EINVAL;
98 +                               goto out;
99 +                       }
100 +                       authen = DOT11_AUTH_SK;
101 +               } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
102 +                       authen = DOT11_AUTH_OS;
103 +               } else {
104 +                       ret = -EINVAL;
105 +                       goto out;
106 +               }
107 +               break;
108 +
109 +       default:
110 +               return -EOPNOTSUPP;
111 +       }
112 +
113 +       /* Set all the values */
114 +       down(&priv->wpa_sem);
115 +       priv->wpa = wpa;
116 +       up(&priv->wpa_sem);
117 +
118 +       sm_drv_oid_set(dev, DOT11_OID_AUTHENABLE,
119 +                      (void *)&authen, sizeof(uint32_t));
120 +       sm_drv_oid_set(dev, DOT11_OID_PRIVACYINVOKED,
121 +                      (void *)&privinvoked, sizeof(uint32_t));
122 +       sm_drv_oid_set(dev, DOT11_OID_EXUNENCRYPTED,
123 +                      (void *)&exunencrypt, sizeof(uint32_t));
124 +       sm_drv_oid_set(dev, DOT11_OID_DOT1XENABLE,
125 +                      (void *)&dot1x, sizeof(uint32_t));
126 +
127 + out:
128 +       return ret;
129 +}
130 +
131 +static int sm_drv_get_auth(struct net_device *dev,
132 +                          struct iw_request_info *info,
133 +                          union iwreq_data *wrqu, char *extra)
134 +{
135 +       struct net_local *priv = netdev_priv(dev);
136 +       struct iw_param *param = &wrqu->param;
137 +       u32 authen = 0, dot1x = 0;
138 +       u32 exunencrypt = 0, privinvoked = 0, wpa = 0;
139 +       int ret = 0;
140 +
141 +       DEBUG(DBG_IOCTL, "GET AUTH\n");
142 +
143 +       /* first get the flags */
144 +       down(&priv->wpa_sem);
145 +       wpa = priv->wpa;
146 +       up(&priv->wpa_sem);
147 +
148 +       switch (param->flags & IW_AUTH_INDEX) {
149 +       case IW_AUTH_CIPHER_PAIRWISE:
150 +       case IW_AUTH_CIPHER_GROUP:
151 +       case IW_AUTH_KEY_MGMT:
152 +               /*
153 +                * wpa_supplicant will control these internally
154 +                */
155 +               ret = -EOPNOTSUPP;
156 +               break;
157 +
158 +       case IW_AUTH_WPA_VERSION:
159 +               switch (wpa) {
160 +               case DOT11_PRIV_INV_TKIP:
161 +                       param->value = IW_AUTH_WPA_VERSION_WPA;
162 +                       break;
163 +               case DOT11_PRIV_INV_AES_CCMP:
164 +                       param->value = IW_AUTH_WPA_VERSION_WPA2;
165 +                       break;
166 +               default:
167 +                       param->value = IW_AUTH_WPA_VERSION_DISABLED;
168 +                       break;
169 +               }
170 +               break;
171 +
172 +       case IW_AUTH_DROP_UNENCRYPTED:
173 +               ret = sm_drv_oid_get(dev, DOT11_OID_EXUNENCRYPTED,
174 +                                    (void *)&exunencrypt, sizeof(uint32_t));
175 +               if (ret >= 0)
176 +                       param->value = exunencrypt > 0 ? 1 : 0;
177 +               break;
178 +
179 +       case IW_AUTH_80211_AUTH_ALG:
180 +               ret = sm_drv_oid_get(dev, DOT11_OID_AUTHENABLE,
181 +                                    (void *)&authen, sizeof(uint32_t));
182 +               if (ret >= 0) {
183 +                       switch (authen) {
184 +                       case DOT11_AUTH_OS:
185 +                               param->value = IW_AUTH_ALG_OPEN_SYSTEM;
186 +                               break;
187 +                       case DOT11_AUTH_BOTH:
188 +                       case DOT11_AUTH_SK:
189 +                               param->value = IW_AUTH_ALG_SHARED_KEY;
190 +                       case DOT11_AUTH_NONE:
191 +                       default:
192 +                               param->value = 0;
193 +                               break;
194 +                       }
195 +               }
196 +               break;
197 +
198 +       case IW_AUTH_WPA_ENABLED:
199 +               param->value = wpa > 0 ? 1 : 0;
200 +               break;
201 +
202 +       case IW_AUTH_RX_UNENCRYPTED_EAPOL:
203 +               ret = sm_drv_oid_get(dev, DOT11_OID_DOT1XENABLE,
204 +                                    (void *)&dot1x, sizeof(uint32_t));
205 +               if (ret >= 0)
206 +                       param->value = dot1x > 0 ? 1 : 0;
207 +               break;
208 +
209 +       case IW_AUTH_PRIVACY_INVOKED:
210 +               ret = sm_drv_oid_get(dev, DOT11_OID_PRIVACYINVOKED,
211 +                                    (void *)&privinvoked, sizeof(uint32_t));
212 +               if (ret >= 0)
213 +                       param->value = privinvoked > 0 ? 1 : 0;
214 +               break;
215 +
216 +       default:
217 +               return -EOPNOTSUPP;
218 +       }
219 +       return ret;
220 +}
221 +
222 +#define KEY_SIZE_WEP104 13     /* 104/128-bit WEP keys */
223 +#define KEY_SIZE_WEP40  5      /* 40/64-bit WEP keys */
224 +#define KEY_SIZE_TKIP   32     /* TKIP keys */
225 +
226 +static int sm_drv_set_encodeext(struct net_device *dev,
227 +                               struct iw_request_info *info,
228 +                               union iwreq_data *wrqu,
229 +                               char *extra)
230 +{
231 +       struct iw_point *encoding = &wrqu->encoding;
232 +       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
233 +       int idx, alg = ext->alg, set_key = 1;
234 +       int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0;
235 +       int ret = 0;
236 +
237 +       DEBUG(DBG_IOCTL, "SET ENCODEEXT\n");
238 +
239 +       /* Determine and validate the key index */
240 +       idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
241 +       if (idx) {
242 +               if (idx < 0 || idx > 3)
243 +                       return -EINVAL;
244 +       } else {
245 +               ret = sm_drv_oid_get(dev, DOT11_OID_DEFKEYID,
246 +                                    (void *)&idx, sizeof(uint32_t));
247 +               if (ret < 0)
248 +                       goto out;
249 +       }
250 +
251 +       if (encoding->flags & IW_ENCODE_DISABLED)
252 +               alg = IW_ENCODE_ALG_NONE;
253 +
254 +       if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
255 +               /* Only set transmit key index here, actual
256 +                * key is set below if needed.
257 +                */
258 +               ret = sm_drv_oid_set(dev, DOT11_OID_DEFKEYID,
259 +                                    (void *)&idx, sizeof(uint32_t));
260 +               set_key = ext->key_len > 0 ? 1 : 0;
261 +       }
262 +
263 +       if (set_key) {
264 +               switch (alg) {
265 +               case IW_ENCODE_ALG_NONE:
266 +                       break;
267 +               case IW_ENCODE_ALG_WEP: {
268 +                       struct obj_key key = { DOT11_PRIV_WEP, 0, "" };
269 +                       memset(key.key, 0, sizeof(key.key));
270 +                       if (ext->key_len > KEY_SIZE_WEP104) {
271 +                               ret = -EINVAL;
272 +                               goto out;
273 +                       }
274 +                       if (ext->key_len > KEY_SIZE_WEP40)
275 +                               key.length = KEY_SIZE_WEP104;
276 +                       else
277 +                               key.length = KEY_SIZE_WEP40;
278 +                       memcpy(key.key, ext->key, ext->key_len);
279 +                       ret = sm_drv_oid_set(dev, DOT11_OID_DEFKEYID + idx + 1,
280 +                                            (void *)&key,
281 +                                            sizeof(struct obj_key));
282 +                       break;
283 +               }
284 +               case IW_ENCODE_ALG_TKIP:
285 +               case IW_ENCODE_ALG_CCMP: {
286 +                       struct obj_stakey key;
287 +                       memset(key.key, 0, sizeof(key.key));
288 +                       if (alg == IW_ENCODE_ALG_TKIP)
289 +                               key.type = DOT11_PRIV_TKIP;
290 +                       else
291 +                               key.type = DOT11_PRIV_AES_CCMP;
292 +                       memcpy(key.address, ext->addr.sa_data, ETH_ALEN);
293 +                       key.length = ext->key_len;
294 +                       key.keyid = idx;
295 +                       key.ext = 0;
296 +                       memcpy(key.key, ext->key, ext->key_len);
297 +                       ret = sm_drv_oid_set(dev, DOT11_OID_STAKEY,
298 +                                            (void *)&key,
299 +                                            sizeof(struct obj_stakey));
300 +                       break;
301 +               }
302 +               default:
303 +                       return -EINVAL;
304 +               }
305 +
306 +               if (ret < 0)
307 +                       goto out;
308 +
309 +       }
310 +
311 +       /* Read the flags */
312 +       if (encoding->flags & IW_ENCODE_DISABLED) {
313 +               /* Encoding disabled,
314 +                * authen = DOT11_AUTH_OS;
315 +                * invoke = 0;
316 +                * exunencrypt = 0; */
317 +       }
318 +       if (encoding->flags & IW_ENCODE_OPEN) {
319 +               /* Encode but accept non-encoded packets. No auth */
320 +               invoke = 1;
321 +       }
322 +       if (encoding->flags & IW_ENCODE_RESTRICTED) {
323 +               /* Refuse non-encoded packets. Auth */
324 +               authen = DOT11_AUTH_BOTH;
325 +               invoke = 1;
326 +               exunencrypt = 1;
327 +       }
328 +
329 +       /* do the change if requested  */
330 +       if (encoding->flags & IW_ENCODE_MODE) {
331 +               sm_drv_oid_set(dev, DOT11_OID_AUTHENABLE,
332 +                              (void *)&authen, sizeof(uint32_t));
333 +               sm_drv_oid_set(dev, DOT11_OID_PRIVACYINVOKED,
334 +                              (void *)&invoke, sizeof(uint32_t));
335 +               sm_drv_oid_set(dev, DOT11_OID_EXUNENCRYPTED,
336 +                              (void *)&exunencrypt, sizeof(uint32_t));
337 +       }
338 +
339 + out:
340 +       return ret;
341 +}
342 +
343 +
344 +static int sm_drv_get_encodeext(struct net_device *dev,
345 +                               struct iw_request_info *info,
346 +                               union iwreq_data *wrqu,
347 +                               char *extra)
348 +{
349 +       struct net_local *priv = netdev_priv(dev);
350 +       struct iw_point *encoding = &wrqu->encoding;
351 +       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
352 +       int idx, max_key_len;
353 +       int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0, wpa = 0;
354 +       int ret = 0;
355 +
356 +       DEBUG(DBG_IOCTL, "GET ENCODEEXT\n");
357 +
358 +       /* first get the flags */
359 +       ret = sm_drv_oid_get(dev, DOT11_OID_AUTHENABLE,
360 +                            (void *)&authen, sizeof(uint32_t));
361 +       ret |= sm_drv_oid_get(dev, DOT11_OID_PRIVACYINVOKED,
362 +                             (void *)&invoke, sizeof(uint32_t));
363 +       ret |= sm_drv_oid_get(dev, DOT11_OID_EXUNENCRYPTED,
364 +                             (void *)&exunencrypt, sizeof(uint32_t));
365 +       if (ret < 0)
366 +               goto out;
367 +
368 +       max_key_len = encoding->length - sizeof(*ext);
369 +       if (max_key_len < 0)
370 +               return -EINVAL;
371 +
372 +       idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
373 +       if (idx) {
374 +               if (idx < 0 || idx > 3)
375 +                       return -EINVAL;
376 +       } else {
377 +               ret = sm_drv_oid_get(dev, DOT11_OID_DEFKEYID,
378 +                                    (void *)&idx, sizeof(uint32_t));
379 +               if (ret < 0)
380 +                       goto out;
381 +       }
382 +
383 +       encoding->flags = idx + 1;
384 +       memset(ext, 0, sizeof(*ext));
385 +
386 +       switch (authen) {
387 +       case DOT11_AUTH_BOTH:
388 +       case DOT11_AUTH_SK:
389 +               wrqu->encoding.flags |= IW_ENCODE_RESTRICTED;
390 +       case DOT11_AUTH_OS:
391 +       default:
392 +               wrqu->encoding.flags |= IW_ENCODE_OPEN;
393 +               break;
394 +       }
395 +
396 +       down(&priv->wpa_sem);
397 +       wpa = priv->wpa;
398 +       up(&priv->wpa_sem);
399 +
400 +       if (authen == DOT11_AUTH_OS && !exunencrypt && !invoke && !wpa) {
401 +               /* No encryption */
402 +               ext->alg = IW_ENCODE_ALG_NONE;
403 +               ext->key_len = 0;
404 +               wrqu->encoding.flags |= IW_ENCODE_DISABLED;
405 +       } else {
406 +               struct obj_key *key;
407 +
408 +               ret = sm_drv_oid_get(dev, DOT11_OID_DEFKEYID + idx + 1,
409 +                                    (void *)&key, sizeof(struct obj_key));
410 +               if (ret < 0)
411 +                       goto out;
412 +               if (max_key_len < key->length) {
413 +                       ret = -E2BIG;
414 +                       goto out;
415 +               }
416 +               memcpy(ext->key, key->key, key->length);
417 +               ext->key_len = key->length;
418 +
419 +               switch (key->type) {
420 +               case DOT11_PRIV_TKIP:
421 +                       ext->alg = IW_ENCODE_ALG_TKIP;
422 +                       break;
423 +               case DOT11_PRIV_AES_CCMP:
424 +                       ext->alg = IW_ENCODE_ALG_CCMP;
425 +                       break;
426 +               default:
427 +               case DOT11_PRIV_WEP:
428 +                       ext->alg = IW_ENCODE_ALG_WEP;
429 +                       break;
430 +               }
431 +               wrqu->encoding.flags |= IW_ENCODE_ENABLED;
432 +       }
433 +
434 + out:
435 +       return ret;
436 +}
437  
438  /* Private handlers */
439  
440 @@ -2473,10 +2902,10 @@ const iw_handler sm_drv_we_handler[] = {
441         (iw_handler) NULL,                      /* -- hole -- */
442         (iw_handler) sm_drv_set_genie,          /* SIOCSIWGENIE*/
443         (iw_handler) NULL,                      /* SIOCGIWGENIE */
444 -       (iw_handler) NULL,                      /* SIOCSIWAUTH */
445 -       (iw_handler) NULL,                      /* SIOCGIWAUTH */
446 -       (iw_handler) NULL,                      /* SIOCSIWENCODEEXT */
447 -       (iw_handler) NULL,                      /* SIOCGIWENCODEEXT */
448 +       (iw_handler) sm_drv_set_auth,           /* SIOCSIWAUTH */
449 +       (iw_handler) sm_drv_get_auth,           /* SIOCGIWAUTH */
450 +       (iw_handler) sm_drv_set_encodeext,      /* SIOCSIWENCODEEXT */
451 +       (iw_handler) sm_drv_get_encodeext,      /* SIOCGIWENCODEEXT */
452         (iw_handler) sm_drv_set_pmk,            /* SIOCSIWPMKSA */
453  };
454