aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/feature-removal-schedule.txt12
-rw-r--r--include/net/iw_handler.h10
-rw-r--r--net/core/rtnetlink.c31
-rw-r--r--net/core/wireless.c735
-rw-r--r--net/wireless/Kconfig10
5 files changed, 0 insertions, 798 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index 9817b60e70a3..976c8a1bd7cd 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -285,18 +285,6 @@ Who: Richard Purdie <rpurdie@rpsys.net>
285 285
286--------------------------- 286---------------------------
287 287
288What: Wireless extensions over netlink (CONFIG_NET_WIRELESS_RTNETLINK)
289When: with the merge of wireless-dev, 2.6.22 or later
290Why: The option/code is
291 * not enabled on most kernels
292 * not required by any userspace tools (except an experimental one,
293 and even there only for some parts, others use ioctl)
294 * pointless since wext is no longer evolving and the ioctl
295 interface needs to be kept
296Who: Johannes Berg <johannes@sipsolutions.net>
297
298---------------------------
299
300What: i8xx_tco watchdog driver 288What: i8xx_tco watchdog driver
301When: in 2.6.22 289When: in 2.6.22
302Why: the i8xx_tco watchdog driver has been replaced by the iTCO_wdt 290Why: the i8xx_tco watchdog driver has been replaced by the iTCO_wdt
diff --git a/include/net/iw_handler.h b/include/net/iw_handler.h
index 8a830188354d..909ca87d13b7 100644
--- a/include/net/iw_handler.h
+++ b/include/net/iw_handler.h
@@ -440,16 +440,6 @@ extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
440/* Handle IOCTLs, called in net/core/dev.c */ 440/* Handle IOCTLs, called in net/core/dev.c */
441extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd); 441extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd);
442 442
443/* Handle RtNetlink requests, called in net/core/rtnetlink.c */
444extern int wireless_rtnetlink_set(struct net_device * dev,
445 char * data,
446 int len);
447extern int wireless_rtnetlink_get(struct net_device * dev,
448 char * data,
449 int len,
450 char ** p_buf,
451 int * p_len);
452
453/* Second : functions that may be called by driver modules */ 443/* Second : functions that may be called by driver modules */
454 444
455/* Send a single event to user space */ 445/* Send a single event to user space */
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 75cea8ea4cf3..4fe0f4b3a345 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -51,10 +51,6 @@
51#include <net/pkt_sched.h> 51#include <net/pkt_sched.h>
52#include <net/fib_rules.h> 52#include <net/fib_rules.h>
53#include <net/rtnetlink.h> 53#include <net/rtnetlink.h>
54#ifdef CONFIG_NET_WIRELESS_RTNETLINK
55#include <linux/wireless.h>
56#include <net/iw_handler.h>
57#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
58 54
59struct rtnl_link 55struct rtnl_link
60{ 56{
@@ -684,17 +680,6 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
684 modified = 1; 680 modified = 1;
685 } 681 }
686 682
687#ifdef CONFIG_NET_WIRELESS_RTNETLINK
688 if (tb[IFLA_WIRELESS]) {
689 /* Call Wireless Extensions.
690 * Various stuff checked in there... */
691 err = wireless_rtnetlink_set(dev, nla_data(tb[IFLA_WIRELESS]),
692 nla_len(tb[IFLA_WIRELESS]));
693 if (err < 0)
694 goto errout_dev;
695 }
696#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
697
698 if (tb[IFLA_BROADCAST]) { 683 if (tb[IFLA_BROADCAST]) {
699 nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len); 684 nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len);
700 send_addr_notify = 1; 685 send_addr_notify = 1;
@@ -758,22 +743,6 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
758 } else 743 } else
759 return -EINVAL; 744 return -EINVAL;
760 745
761
762#ifdef CONFIG_NET_WIRELESS_RTNETLINK
763 if (tb[IFLA_WIRELESS]) {
764 /* Call Wireless Extensions. We need to know the size before
765 * we can alloc. Various stuff checked in there... */
766 err = wireless_rtnetlink_get(dev, nla_data(tb[IFLA_WIRELESS]),
767 nla_len(tb[IFLA_WIRELESS]),
768 &iw_buf, &iw_buf_len);
769 if (err < 0)
770 goto errout;
771
772 /* Payload is at an offset in buffer */
773 iw = iw_buf + IW_EV_POINT_OFF;
774 }
775#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
776
777 nskb = nlmsg_new(if_nlmsg_size(iw_buf_len), GFP_KERNEL); 746 nskb = nlmsg_new(if_nlmsg_size(iw_buf_len), GFP_KERNEL);
778 if (nskb == NULL) { 747 if (nskb == NULL) {
779 err = -ENOBUFS; 748 err = -ENOBUFS;
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 86db63d7f760..fba295e05e7a 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -104,12 +104,10 @@
104 104
105/* Debugging stuff */ 105/* Debugging stuff */
106#undef WE_IOCTL_DEBUG /* Debug IOCTL API */ 106#undef WE_IOCTL_DEBUG /* Debug IOCTL API */
107#undef WE_RTNETLINK_DEBUG /* Debug RtNetlink API */
108#undef WE_EVENT_DEBUG /* Debug Event dispatcher */ 107#undef WE_EVENT_DEBUG /* Debug Event dispatcher */
109#undef WE_SPY_DEBUG /* Debug enhanced spy support */ 108#undef WE_SPY_DEBUG /* Debug enhanced spy support */
110 109
111/* Options */ 110/* Options */
112//CONFIG_NET_WIRELESS_RTNETLINK /* Wireless requests over RtNetlink */
113#define WE_EVENT_RTNETLINK /* Propagate events using RtNetlink */ 111#define WE_EVENT_RTNETLINK /* Propagate events using RtNetlink */
114#define WE_SET_EVENT /* Generate an event on some set commands */ 112#define WE_SET_EVENT /* Generate an event on some set commands */
115 113
@@ -1145,739 +1143,6 @@ int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
1145 return -EINVAL; 1143 return -EINVAL;
1146} 1144}
1147 1145
1148/********************** RTNETLINK REQUEST API **********************/
1149/*
1150 * The alternate user space API to configure all those Wireless Extensions
1151 * is through RtNetlink.
1152 * This API support only the new driver API (iw_handler).
1153 *
1154 * This RtNetlink API use the same query/reply model as the ioctl API.
1155 * Maximum effort has been done to fit in the RtNetlink model, and
1156 * we support both RtNetlink Set and RtNelink Get operations.
1157 * On the other hand, we don't offer Dump operations because of the
1158 * following reasons :
1159 * o Large number of parameters, most optional
1160 * o Large size of some parameters (> 100 bytes)
1161 * o Each parameters need to be extracted from hardware
1162 * o Scan requests can take seconds and disable network activity.
1163 * Because of this high cost/overhead, we want to return only the
1164 * parameters the user application is really interested in.
1165 * We could offer partial Dump using the IW_DESCR_FLAG_DUMP flag.
1166 *
1167 * The API uses the standard RtNetlink socket. When the RtNetlink code
1168 * find a IFLA_WIRELESS field in a RtNetlink SET_LINK request,
1169 * it calls here.
1170 */
1171
1172#ifdef CONFIG_NET_WIRELESS_RTNETLINK
1173/* ---------------------------------------------------------------- */
1174/*
1175 * Wrapper to call a standard Wireless Extension GET handler.
1176 * We do various checks and call the handler with the proper args.
1177 */
1178static int rtnetlink_standard_get(struct net_device * dev,
1179 struct iw_event * request,
1180 int request_len,
1181 iw_handler handler,
1182 char ** p_buf,
1183 int * p_len)
1184{
1185 const struct iw_ioctl_description * descr = NULL;
1186 unsigned int cmd;
1187 union iwreq_data * wrqu;
1188 int hdr_len;
1189 struct iw_request_info info;
1190 char * buffer = NULL;
1191 int buffer_size = 0;
1192 int ret = -EINVAL;
1193
1194 /* Get the description of the Request */
1195 cmd = request->cmd;
1196 if ((cmd - SIOCIWFIRST) >= standard_ioctl_num)
1197 return -EOPNOTSUPP;
1198 descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
1199
1200#ifdef WE_RTNETLINK_DEBUG
1201 printk(KERN_DEBUG "%s (WE.r) : Found standard handler for 0x%04X\n",
1202 dev->name, cmd);
1203 printk(KERN_DEBUG "%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens);
1204#endif /* WE_RTNETLINK_DEBUG */
1205
1206 /* Check if wrqu is complete */
1207 hdr_len = event_type_size[descr->header_type];
1208 if (request_len < hdr_len) {
1209#ifdef WE_RTNETLINK_DEBUG
1210 printk(KERN_DEBUG
1211 "%s (WE.r) : Wireless request too short (%d)\n",
1212 dev->name, request_len);
1213#endif /* WE_RTNETLINK_DEBUG */
1214 return -EINVAL;
1215 }
1216
1217 /* Prepare the call */
1218 info.cmd = cmd;
1219 info.flags = 0;
1220
1221 /* Check if we have extra data in the reply or not */
1222 if (descr->header_type != IW_HEADER_TYPE_POINT) {
1223
1224 /* Create the kernel buffer that we will return.
1225 * It's at an offset to match the TYPE_POINT case... */
1226 buffer_size = request_len + IW_EV_POINT_OFF;
1227 buffer = kmalloc(buffer_size, GFP_KERNEL);
1228 if (buffer == NULL) {
1229 return -ENOMEM;
1230 }
1231 /* Copy event data */
1232 memcpy(buffer + IW_EV_POINT_OFF, request, request_len);
1233 /* Use our own copy of wrqu */
1234 wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF
1235 + IW_EV_LCP_PK_LEN);
1236
1237 /* No extra arguments. Trivial to handle */
1238 ret = handler(dev, &info, wrqu, NULL);
1239
1240 } else {
1241 union iwreq_data wrqu_point;
1242 char * extra = NULL;
1243 int extra_size = 0;
1244
1245 /* Get a temp copy of wrqu (skip pointer) */
1246 memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
1247 ((char *) request) + IW_EV_LCP_PK_LEN,
1248 IW_EV_POINT_LEN - IW_EV_LCP_PK_LEN);
1249
1250 /* Calculate space needed by arguments. Always allocate
1251 * for max space. Easier, and won't last long... */
1252 extra_size = descr->max_tokens * descr->token_size;
1253 /* Support for very large requests */
1254 if ((descr->flags & IW_DESCR_FLAG_NOMAX) &&
1255 (wrqu_point.data.length > descr->max_tokens))
1256 extra_size = (wrqu_point.data.length
1257 * descr->token_size);
1258 buffer_size = extra_size + IW_EV_POINT_PK_LEN + IW_EV_POINT_OFF;
1259#ifdef WE_RTNETLINK_DEBUG
1260 printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n",
1261 dev->name, extra_size, buffer_size);
1262#endif /* WE_RTNETLINK_DEBUG */
1263
1264 /* Create the kernel buffer that we will return */
1265 buffer = kmalloc(buffer_size, GFP_KERNEL);
1266 if (buffer == NULL) {
1267 return -ENOMEM;
1268 }
1269
1270 /* Put wrqu in the right place (just before extra).
1271 * Leave space for IWE header and dummy pointer...
1272 * Note that IW_EV_LCP_PK_LEN==4 bytes, so it's still aligned.
1273 */
1274 memcpy(buffer + IW_EV_LCP_PK_LEN + IW_EV_POINT_OFF,
1275 ((char *) &wrqu_point) + IW_EV_POINT_OFF,
1276 IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
1277 wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_PK_LEN);
1278
1279 /* Extra comes logically after that. Offset +12 bytes. */
1280 extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_PK_LEN;
1281
1282 /* Call the handler */
1283 ret = handler(dev, &info, wrqu, extra);
1284
1285 /* Calculate real returned length */
1286 extra_size = (wrqu->data.length * descr->token_size);
1287 /* Re-adjust reply size */
1288 request->len = extra_size + IW_EV_POINT_PK_LEN;
1289
1290 /* Put the iwe header where it should, i.e. scrap the
1291 * dummy pointer. */
1292 memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_PK_LEN);
1293
1294#ifdef WE_RTNETLINK_DEBUG
1295 printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size);
1296#endif /* WE_RTNETLINK_DEBUG */
1297
1298 /* Check if there is enough buffer up there */
1299 if (wrqu_point.data.length < wrqu->data.length)
1300 ret = -E2BIG;
1301 }
1302
1303 /* Return the buffer to the caller */
1304 if (!ret) {
1305 *p_buf = buffer;
1306 *p_len = request->len;
1307 } else {
1308 /* Cleanup */
1309 if (buffer)
1310 kfree(buffer);
1311 }
1312
1313 return ret;
1314}
1315
1316/* ---------------------------------------------------------------- */
1317/*
1318 * Wrapper to call a standard Wireless Extension SET handler.
1319 * We do various checks and call the handler with the proper args.
1320 */
1321static inline int rtnetlink_standard_set(struct net_device * dev,
1322 struct iw_event * request,
1323 int request_len,
1324 iw_handler handler)
1325{
1326 const struct iw_ioctl_description * descr = NULL;
1327 unsigned int cmd;
1328 union iwreq_data * wrqu;
1329 union iwreq_data wrqu_point;
1330 int hdr_len;
1331 char * extra = NULL;
1332 int extra_size = 0;
1333 struct iw_request_info info;
1334 int ret = -EINVAL;
1335
1336 /* Get the description of the Request */
1337 cmd = request->cmd;
1338 if ((cmd - SIOCIWFIRST) >= standard_ioctl_num)
1339 return -EOPNOTSUPP;
1340 descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
1341
1342#ifdef WE_RTNETLINK_DEBUG
1343 printk(KERN_DEBUG "%s (WE.r) : Found standard SET handler for 0x%04X\n",
1344 dev->name, cmd);
1345 printk(KERN_DEBUG "%s (WE.r) : Header type : %d, Token type : %d, size : %d, token : %d\n", dev->name, descr->header_type, descr->token_type, descr->token_size, descr->max_tokens);
1346#endif /* WE_RTNETLINK_DEBUG */
1347
1348 /* Extract fixed header from request. This is properly aligned. */
1349 wrqu = (union iwreq_data *) (((char *) request) + IW_EV_LCP_PK_LEN);
1350
1351 /* Check if wrqu is complete */
1352 hdr_len = event_type_pk_size[descr->header_type];
1353 if (request_len < hdr_len) {
1354#ifdef WE_RTNETLINK_DEBUG
1355 printk(KERN_DEBUG
1356 "%s (WE.r) : Wireless request too short (%d)\n",
1357 dev->name, request_len);
1358#endif /* WE_RTNETLINK_DEBUG */
1359 return -EINVAL;
1360 }
1361
1362 /* Prepare the call */
1363 info.cmd = cmd;
1364 info.flags = 0;
1365
1366 /* Check if we have extra data in the request or not */
1367 if (descr->header_type != IW_HEADER_TYPE_POINT) {
1368
1369 /* No extra arguments. Trivial to handle */
1370 ret = handler(dev, &info, wrqu, NULL);
1371
1372 } else {
1373 int extra_len;
1374
1375 /* Put wrqu in the right place (skip pointer) */
1376 memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
1377 wrqu, IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
1378 /* Don't forget about the event code... */
1379 wrqu = &wrqu_point;
1380
1381 /* Check if number of token fits within bounds */
1382 if (wrqu_point.data.length > descr->max_tokens)
1383 return -E2BIG;
1384 if (wrqu_point.data.length < descr->min_tokens)
1385 return -EINVAL;
1386
1387 /* Real length of payload */
1388 extra_len = wrqu_point.data.length * descr->token_size;
1389
1390 /* Check if request is self consistent */
1391 if ((request_len - hdr_len) < extra_len) {
1392#ifdef WE_RTNETLINK_DEBUG
1393 printk(KERN_DEBUG "%s (WE.r) : Wireless request data too short (%d)\n",
1394 dev->name, extra_size);
1395#endif /* WE_RTNETLINK_DEBUG */
1396 return -EINVAL;
1397 }
1398
1399#ifdef WE_RTNETLINK_DEBUG
1400 printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes\n",
1401 dev->name, extra_size);
1402#endif /* WE_RTNETLINK_DEBUG */
1403
1404 /* Always allocate for max space. Easier, and won't last
1405 * long... */
1406 extra_size = descr->max_tokens * descr->token_size;
1407 extra = kmalloc(extra_size, GFP_KERNEL);
1408 if (extra == NULL)
1409 return -ENOMEM;
1410
1411 /* Copy extra in aligned buffer */
1412 memcpy(extra, ((char *) request) + hdr_len, extra_len);
1413
1414 /* Call the handler */
1415 ret = handler(dev, &info, &wrqu_point, extra);
1416 }
1417
1418#ifdef WE_SET_EVENT
1419 /* Generate an event to notify listeners of the change */
1420 if ((descr->flags & IW_DESCR_FLAG_EVENT) &&
1421 ((ret == 0) || (ret == -EIWCOMMIT))) {
1422 if (descr->flags & IW_DESCR_FLAG_RESTRICT)
1423 /* If the event is restricted, don't
1424 * export the payload */
1425 wireless_send_event(dev, cmd, wrqu, NULL);
1426 else
1427 wireless_send_event(dev, cmd, wrqu, extra);
1428 }
1429#endif /* WE_SET_EVENT */
1430
1431 /* Cleanup - I told you it wasn't that long ;-) */
1432 if (extra)
1433 kfree(extra);
1434
1435 /* Call commit handler if needed and defined */
1436 if (ret == -EIWCOMMIT)
1437 ret = call_commit_handler(dev);
1438
1439 return ret;
1440}
1441
1442/* ---------------------------------------------------------------- */
1443/*
1444 * Wrapper to call a private Wireless Extension GET handler.
1445 * Same as above...
1446 * It's not as nice and slimline as the standard wrapper. The cause
1447 * is struct iw_priv_args, which was not really designed for the
1448 * job we are going here.
1449 *
1450 * IMPORTANT : This function prevent to set and get data on the same
1451 * IOCTL and enforce the SET/GET convention. Not doing it would be
1452 * far too hairy...
1453 * If you need to set and get data at the same time, please don't use
1454 * a iw_handler but process it in your ioctl handler (i.e. use the
1455 * old driver API).
1456 */
1457static inline int rtnetlink_private_get(struct net_device * dev,
1458 struct iw_event * request,
1459 int request_len,
1460 iw_handler handler,
1461 char ** p_buf,
1462 int * p_len)
1463{
1464 const struct iw_priv_args * descr = NULL;
1465 unsigned int cmd;
1466 union iwreq_data * wrqu;
1467 int hdr_len;
1468 struct iw_request_info info;
1469 int extra_size = 0;
1470 int i;
1471 char * buffer = NULL;
1472 int buffer_size = 0;
1473 int ret = -EINVAL;
1474
1475 /* Get the description of the Request */
1476 cmd = request->cmd;
1477 for (i = 0; i < dev->wireless_handlers->num_private_args; i++)
1478 if (cmd == dev->wireless_handlers->private_args[i].cmd) {
1479 descr = &(dev->wireless_handlers->private_args[i]);
1480 break;
1481 }
1482 if (descr == NULL)
1483 return -EOPNOTSUPP;
1484
1485#ifdef WE_RTNETLINK_DEBUG
1486 printk(KERN_DEBUG "%s (WE.r) : Found private handler for 0x%04X\n",
1487 dev->name, cmd);
1488 printk(KERN_DEBUG "%s (WE.r) : Name %s, set %X, get %X\n",
1489 dev->name, descr->name, descr->set_args, descr->get_args);
1490#endif /* WE_RTNETLINK_DEBUG */
1491
1492 /* Compute the max size of the get arguments */
1493 extra_size = get_priv_size(descr->get_args);
1494
1495 /* Does it fits in wrqu ? */
1496 if ((descr->get_args & IW_PRIV_SIZE_FIXED) &&
1497 (extra_size <= IFNAMSIZ)) {
1498 hdr_len = extra_size;
1499 extra_size = 0;
1500 } else {
1501 hdr_len = IW_EV_POINT_PK_LEN;
1502 }
1503
1504 /* Check if wrqu is complete */
1505 if (request_len < hdr_len) {
1506#ifdef WE_RTNETLINK_DEBUG
1507 printk(KERN_DEBUG
1508 "%s (WE.r) : Wireless request too short (%d)\n",
1509 dev->name, request_len);
1510#endif /* WE_RTNETLINK_DEBUG */
1511 return -EINVAL;
1512 }
1513
1514 /* Prepare the call */
1515 info.cmd = cmd;
1516 info.flags = 0;
1517
1518 /* Check if we have a pointer to user space data or not. */
1519 if (extra_size == 0) {
1520
1521 /* Create the kernel buffer that we will return.
1522 * It's at an offset to match the TYPE_POINT case... */
1523 buffer_size = request_len + IW_EV_POINT_OFF;
1524 buffer = kmalloc(buffer_size, GFP_KERNEL);
1525 if (buffer == NULL) {
1526 return -ENOMEM;
1527 }
1528 /* Copy event data */
1529 memcpy(buffer + IW_EV_POINT_OFF, request, request_len);
1530 /* Use our own copy of wrqu */
1531 wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF
1532 + IW_EV_LCP_PK_LEN);
1533
1534 /* No extra arguments. Trivial to handle */
1535 ret = handler(dev, &info, wrqu, (char *) wrqu);
1536
1537 } else {
1538 char * extra;
1539
1540 /* Buffer for full reply */
1541 buffer_size = extra_size + IW_EV_POINT_PK_LEN + IW_EV_POINT_OFF;
1542
1543#ifdef WE_RTNETLINK_DEBUG
1544 printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n",
1545 dev->name, extra_size, buffer_size);
1546#endif /* WE_RTNETLINK_DEBUG */
1547
1548 /* Create the kernel buffer that we will return */
1549 buffer = kmalloc(buffer_size, GFP_KERNEL);
1550 if (buffer == NULL) {
1551 return -ENOMEM;
1552 }
1553
1554 /* Put wrqu in the right place (just before extra).
1555 * Leave space for IWE header and dummy pointer...
1556 * Note that IW_EV_LCP_PK_LEN==4 bytes, so it's still aligned.
1557 */
1558 memcpy(buffer + IW_EV_LCP_PK_LEN + IW_EV_POINT_OFF,
1559 ((char *) request) + IW_EV_LCP_PK_LEN,
1560 IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
1561 wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_PK_LEN);
1562
1563 /* Extra comes logically after that. Offset +12 bytes. */
1564 extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_PK_LEN;
1565
1566 /* Call the handler */
1567 ret = handler(dev, &info, wrqu, extra);
1568
1569 /* Adjust for the actual length if it's variable,
1570 * avoid leaking kernel bits outside. */
1571 if (!(descr->get_args & IW_PRIV_SIZE_FIXED))
1572 extra_size = adjust_priv_size(descr->get_args, wrqu);
1573 /* Re-adjust reply size */
1574 request->len = extra_size + IW_EV_POINT_PK_LEN;
1575
1576 /* Put the iwe header where it should, i.e. scrap the
1577 * dummy pointer. */
1578 memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_PK_LEN);
1579
1580#ifdef WE_RTNETLINK_DEBUG
1581 printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size);
1582#endif /* WE_RTNETLINK_DEBUG */
1583 }
1584
1585 /* Return the buffer to the caller */
1586 if (!ret) {
1587 *p_buf = buffer;
1588 *p_len = request->len;
1589 } else {
1590 /* Cleanup */
1591 if (buffer)
1592 kfree(buffer);
1593 }
1594
1595 return ret;
1596}
1597
1598/* ---------------------------------------------------------------- */
1599/*
1600 * Wrapper to call a private Wireless Extension SET handler.
1601 * Same as above...
1602 * It's not as nice and slimline as the standard wrapper. The cause
1603 * is struct iw_priv_args, which was not really designed for the
1604 * job we are going here.
1605 *
1606 * IMPORTANT : This function prevent to set and get data on the same
1607 * IOCTL and enforce the SET/GET convention. Not doing it would be
1608 * far too hairy...
1609 * If you need to set and get data at the same time, please don't use
1610 * a iw_handler but process it in your ioctl handler (i.e. use the
1611 * old driver API).
1612 */
1613static inline int rtnetlink_private_set(struct net_device * dev,
1614 struct iw_event * request,
1615 int request_len,
1616 iw_handler handler)
1617{
1618 const struct iw_priv_args * descr = NULL;
1619 unsigned int cmd;
1620 union iwreq_data * wrqu;
1621 union iwreq_data wrqu_point;
1622 int hdr_len;
1623 char * extra = NULL;
1624 int extra_size = 0;
1625 int offset = 0; /* For sub-ioctls */
1626 struct iw_request_info info;
1627 int i;
1628 int ret = -EINVAL;
1629
1630 /* Get the description of the Request */
1631 cmd = request->cmd;
1632 for (i = 0; i < dev->wireless_handlers->num_private_args; i++)
1633 if (cmd == dev->wireless_handlers->private_args[i].cmd) {
1634 descr = &(dev->wireless_handlers->private_args[i]);
1635 break;
1636 }
1637 if (descr == NULL)
1638 return -EOPNOTSUPP;
1639
1640#ifdef WE_RTNETLINK_DEBUG
1641 printk(KERN_DEBUG "%s (WE.r) : Found private handler for 0x%04X\n",
1642 ifr->ifr_name, cmd);
1643 printk(KERN_DEBUG "%s (WE.r) : Name %s, set %X, get %X\n",
1644 dev->name, descr->name, descr->set_args, descr->get_args);
1645#endif /* WE_RTNETLINK_DEBUG */
1646
1647 /* Compute the size of the set arguments */
1648 /* Check for sub-ioctl handler */
1649 if (descr->name[0] == '\0')
1650 /* Reserve one int for sub-ioctl index */
1651 offset = sizeof(__u32);
1652
1653 /* Size of set arguments */
1654 extra_size = get_priv_size(descr->set_args);
1655
1656 /* Does it fits in wrqu ? */
1657 if ((descr->set_args & IW_PRIV_SIZE_FIXED) &&
1658 (extra_size <= IFNAMSIZ)) {
1659 hdr_len = IW_EV_LCP_PK_LEN + extra_size;
1660 extra_size = 0;
1661 } else {
1662 hdr_len = IW_EV_POINT_PK_LEN;
1663 }
1664
1665 /* Extract fixed header from request. This is properly aligned. */
1666 wrqu = (union iwreq_data *) (((char *) request) + IW_EV_LCP_PK_LEN);
1667
1668 /* Check if wrqu is complete */
1669 if (request_len < hdr_len) {
1670#ifdef WE_RTNETLINK_DEBUG
1671 printk(KERN_DEBUG
1672 "%s (WE.r) : Wireless request too short (%d)\n",
1673 dev->name, request_len);
1674#endif /* WE_RTNETLINK_DEBUG */
1675 return -EINVAL;
1676 }
1677
1678 /* Prepare the call */
1679 info.cmd = cmd;
1680 info.flags = 0;
1681
1682 /* Check if we have a pointer to user space data or not. */
1683 if (extra_size == 0) {
1684
1685 /* No extra arguments. Trivial to handle */
1686 ret = handler(dev, &info, wrqu, (char *) wrqu);
1687
1688 } else {
1689 int extra_len;
1690
1691 /* Put wrqu in the right place (skip pointer) */
1692 memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
1693 wrqu, IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
1694
1695 /* Does it fits within bounds ? */
1696 if (wrqu_point.data.length > (descr->set_args &
1697 IW_PRIV_SIZE_MASK))
1698 return -E2BIG;
1699
1700 /* Real length of payload */
1701 extra_len = adjust_priv_size(descr->set_args, &wrqu_point);
1702
1703 /* Check if request is self consistent */
1704 if ((request_len - hdr_len) < extra_len) {
1705#ifdef WE_RTNETLINK_DEBUG
1706 printk(KERN_DEBUG "%s (WE.r) : Wireless request data too short (%d)\n",
1707 dev->name, extra_size);
1708#endif /* WE_RTNETLINK_DEBUG */
1709 return -EINVAL;
1710 }
1711
1712#ifdef WE_RTNETLINK_DEBUG
1713 printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes\n",
1714 dev->name, extra_size);
1715#endif /* WE_RTNETLINK_DEBUG */
1716
1717 /* Always allocate for max space. Easier, and won't last
1718 * long... */
1719 extra = kmalloc(extra_size, GFP_KERNEL);
1720 if (extra == NULL)
1721 return -ENOMEM;
1722
1723 /* Copy extra in aligned buffer */
1724 memcpy(extra, ((char *) request) + hdr_len, extra_len);
1725
1726 /* Call the handler */
1727 ret = handler(dev, &info, &wrqu_point, extra);
1728
1729 /* Cleanup - I told you it wasn't that long ;-) */
1730 kfree(extra);
1731 }
1732
1733 /* Call commit handler if needed and defined */
1734 if (ret == -EIWCOMMIT)
1735 ret = call_commit_handler(dev);
1736
1737 return ret;
1738}
1739
1740/* ---------------------------------------------------------------- */
1741/*
1742 * Main RtNetlink dispatcher. Called from the main networking code
1743 * (do_getlink() in net/core/rtnetlink.c).
1744 * Check the type of Request and call the appropriate wrapper...
1745 */
1746int wireless_rtnetlink_get(struct net_device * dev,
1747 char * data,
1748 int len,
1749 char ** p_buf,
1750 int * p_len)
1751{
1752 struct iw_event * request = (struct iw_event *) data;
1753 iw_handler handler;
1754
1755 /* Check length */
1756 if (len < IW_EV_LCP_PK_LEN) {
1757 printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n",
1758 dev->name, len);
1759 return -EINVAL;
1760 }
1761
1762 /* ReCheck length (len may have padding) */
1763 if (request->len > len) {
1764 printk(KERN_DEBUG "%s (WE.r) : RtNetlink request len invalid (%d-%d)\n",
1765 dev->name, request->len, len);
1766 return -EINVAL;
1767 }
1768
1769 /* Only accept GET requests in here */
1770 if (!IW_IS_GET(request->cmd))
1771 return -EOPNOTSUPP;
1772
1773 /* If command is `get the encoding parameters', check if
1774 * the user has the right to do it */
1775 if (request->cmd == SIOCGIWENCODE ||
1776 request->cmd == SIOCGIWENCODEEXT) {
1777 if (!capable(CAP_NET_ADMIN))
1778 return -EPERM;
1779 }
1780
1781 /* Special cases */
1782 if (request->cmd == SIOCGIWSTATS)
1783 /* Get Wireless Stats */
1784 return rtnetlink_standard_get(dev,
1785 request,
1786 request->len,
1787 &iw_handler_get_iwstats,
1788 p_buf, p_len);
1789 if (request->cmd == SIOCGIWPRIV) {
1790 /* Check if we have some wireless handlers defined */
1791 if (dev->wireless_handlers == NULL)
1792 return -EOPNOTSUPP;
1793 /* Get Wireless Stats */
1794 return rtnetlink_standard_get(dev,
1795 request,
1796 request->len,
1797 &iw_handler_get_private,
1798 p_buf, p_len);
1799 }
1800
1801 /* Basic check */
1802 if (!netif_device_present(dev))
1803 return -ENODEV;
1804
1805 /* Try to find the handler */
1806 handler = get_handler(dev, request->cmd);
1807 if (handler != NULL) {
1808 /* Standard and private are not the same */
1809 if (request->cmd < SIOCIWFIRSTPRIV)
1810 return rtnetlink_standard_get(dev,
1811 request,
1812 request->len,
1813 handler,
1814 p_buf, p_len);
1815 else
1816 return rtnetlink_private_get(dev,
1817 request,
1818 request->len,
1819 handler,
1820 p_buf, p_len);
1821 }
1822
1823 return -EOPNOTSUPP;
1824}
1825
1826/* ---------------------------------------------------------------- */
1827/*
1828 * Main RtNetlink dispatcher. Called from the main networking code
1829 * (do_setlink() in net/core/rtnetlink.c).
1830 * Check the type of Request and call the appropriate wrapper...
1831 */
1832int wireless_rtnetlink_set(struct net_device * dev,
1833 char * data,
1834 int len)
1835{
1836 struct iw_event * request = (struct iw_event *) data;
1837 iw_handler handler;
1838
1839 /* Check length */
1840 if (len < IW_EV_LCP_PK_LEN) {
1841 printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n",
1842 dev->name, len);
1843 return -EINVAL;
1844 }
1845
1846 /* ReCheck length (len may have padding) */
1847 if (request->len > len) {
1848 printk(KERN_DEBUG "%s (WE.r) : RtNetlink request len invalid (%d-%d)\n",
1849 dev->name, request->len, len);
1850 return -EINVAL;
1851 }
1852
1853 /* Only accept SET requests in here */
1854 if (!IW_IS_SET(request->cmd))
1855 return -EOPNOTSUPP;
1856
1857 /* Basic check */
1858 if (!netif_device_present(dev))
1859 return -ENODEV;
1860
1861 /* New driver API : try to find the handler */
1862 handler = get_handler(dev, request->cmd);
1863 if (handler != NULL) {
1864 /* Standard and private are not the same */
1865 if (request->cmd < SIOCIWFIRSTPRIV)
1866 return rtnetlink_standard_set(dev,
1867 request,
1868 request->len,
1869 handler);
1870 else
1871 return rtnetlink_private_set(dev,
1872 request,
1873 request->len,
1874 handler);
1875 }
1876
1877 return -EOPNOTSUPP;
1878}
1879#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
1880
1881 1146
1882/************************* EVENT PROCESSING *************************/ 1147/************************* EVENT PROCESSING *************************/
1883/* 1148/*
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 1863c0b07d45..a228d56a91b8 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -14,13 +14,3 @@ config WIRELESS_EXT
14 14
15 Say N (if you can) unless you know you need wireless 15 Say N (if you can) unless you know you need wireless
16 extensions for external modules. 16 extensions for external modules.
17
18config NET_WIRELESS_RTNETLINK
19 bool "Wireless Extension API over RtNetlink"
20 depends on WIRELESS_EXT
21 ---help---
22 Support the Wireless Extension API over the RtNetlink socket
23 in addition to the traditional ioctl interface (selected above).
24
25 For now, few tools use this facility, but it might grow in the
26 future. The only downside is that it adds 4.5 kB to your kernel.