aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2007-04-23 15:20:55 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-04-26 01:29:42 -0400
commit9e101eab153073d8a1fc7ea22b20af65de8ab44b (patch)
treefb438ff40a479b289ea8b92707f9a629fb6abbd0 /net/core
parent704232c2718c9d4b3375ec15a14fc0397970c449 (diff)
[WIRELESS]: Remove wext over netlink.
As scheduled, this patch removes the pointless wext over netlink code. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/rtnetlink.c31
-rw-r--r--net/core/wireless.c735
2 files changed, 0 insertions, 766 deletions
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/*