aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/wext.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/wext.c')
-rw-r--r--net/wireless/wext.c114
1 files changed, 57 insertions, 57 deletions
diff --git a/net/wireless/wext.c b/net/wireless/wext.c
index db8351a5a87d..ee35e6422f1f 100644
--- a/net/wireless/wext.c
+++ b/net/wireless/wext.c
@@ -1300,22 +1300,15 @@ static void wireless_nlevent_process(struct work_struct *work)
1300 1300
1301static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process); 1301static DECLARE_WORK(wireless_nlevent_work, wireless_nlevent_process);
1302 1302
1303/* ---------------------------------------------------------------- */ 1303static struct nlmsghdr *rtnetlink_ifinfo_prep(struct net_device *dev,
1304/* 1304 struct sk_buff *skb)
1305 * Fill a rtnetlink message with our event data.
1306 * Note that we propage only the specified event and don't dump the
1307 * current wireless config. Dumping the wireless config is far too
1308 * expensive (for each parameter, the driver need to query the hardware).
1309 */
1310static int rtnetlink_fill_iwinfo(struct sk_buff *skb, struct net_device *dev,
1311 int type, char *event, int event_len)
1312{ 1305{
1313 struct ifinfomsg *r; 1306 struct ifinfomsg *r;
1314 struct nlmsghdr *nlh; 1307 struct nlmsghdr *nlh;
1315 1308
1316 nlh = nlmsg_put(skb, 0, 0, type, sizeof(*r), 0); 1309 nlh = nlmsg_put(skb, 0, 0, RTM_NEWLINK, sizeof(*r), 0);
1317 if (nlh == NULL) 1310 if (!nlh)
1318 return -EMSGSIZE; 1311 return NULL;
1319 1312
1320 r = nlmsg_data(nlh); 1313 r = nlmsg_data(nlh);
1321 r->ifi_family = AF_UNSPEC; 1314 r->ifi_family = AF_UNSPEC;
@@ -1326,45 +1319,14 @@ static int rtnetlink_fill_iwinfo(struct sk_buff *skb, struct net_device *dev,
1326 r->ifi_change = 0; /* Wireless changes don't affect those flags */ 1319 r->ifi_change = 0; /* Wireless changes don't affect those flags */
1327 1320
1328 NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name); 1321 NLA_PUT_STRING(skb, IFLA_IFNAME, dev->name);
1329 /* Add the wireless events in the netlink packet */
1330 NLA_PUT(skb, IFLA_WIRELESS, event_len, event);
1331
1332 return nlmsg_end(skb, nlh);
1333 1322
1334nla_put_failure: 1323 return nlh;
1324 nla_put_failure:
1335 nlmsg_cancel(skb, nlh); 1325 nlmsg_cancel(skb, nlh);
1336 return -EMSGSIZE; 1326 return NULL;
1337} 1327}
1338 1328
1339/* ---------------------------------------------------------------- */
1340/*
1341 * Create and broadcast and send it on the standard rtnetlink socket
1342 * This is a pure clone rtmsg_ifinfo() in net/core/rtnetlink.c
1343 * Andrzej Krzysztofowicz mandated that I used a IFLA_XXX field
1344 * within a RTM_NEWLINK event.
1345 */
1346static void rtmsg_iwinfo(struct net_device *dev, char *event, int event_len)
1347{
1348 struct sk_buff *skb;
1349 int err;
1350
1351 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
1352 if (!skb)
1353 return;
1354 1329
1355 err = rtnetlink_fill_iwinfo(skb, dev, RTM_NEWLINK, event, event_len);
1356 if (err < 0) {
1357 WARN_ON(err == -EMSGSIZE);
1358 kfree_skb(skb);
1359 return;
1360 }
1361
1362 NETLINK_CB(skb).dst_group = RTNLGRP_LINK;
1363 skb_queue_tail(&dev_net(dev)->wext_nlevents, skb);
1364 schedule_work(&wireless_nlevent_work);
1365}
1366
1367/* ---------------------------------------------------------------- */
1368/* 1330/*
1369 * Main event dispatcher. Called from other parts and drivers. 1331 * Main event dispatcher. Called from other parts and drivers.
1370 * Send the event on the appropriate channels. 1332 * Send the event on the appropriate channels.
@@ -1383,6 +1345,9 @@ void wireless_send_event(struct net_device * dev,
1383 int wrqu_off = 0; /* Offset in wrqu */ 1345 int wrqu_off = 0; /* Offset in wrqu */
1384 /* Don't "optimise" the following variable, it will crash */ 1346 /* Don't "optimise" the following variable, it will crash */
1385 unsigned cmd_index; /* *MUST* be unsigned */ 1347 unsigned cmd_index; /* *MUST* be unsigned */
1348 struct sk_buff *skb;
1349 struct nlmsghdr *nlh;
1350 struct nlattr *nla;
1386 1351
1387 /* Get the description of the Event */ 1352 /* Get the description of the Event */
1388 if (cmd <= SIOCIWLAST) { 1353 if (cmd <= SIOCIWLAST) {
@@ -1430,25 +1395,60 @@ void wireless_send_event(struct net_device * dev,
1430 hdr_len = event_type_size[descr->header_type]; 1395 hdr_len = event_type_size[descr->header_type];
1431 event_len = hdr_len + extra_len; 1396 event_len = hdr_len + extra_len;
1432 1397
1433 /* Create temporary buffer to hold the event */ 1398 /*
1434 event = kmalloc(event_len, GFP_ATOMIC); 1399 * The problem for 64/32 bit.
1435 if (event == NULL) 1400 *
1401 * On 64-bit, a regular event is laid out as follows:
1402 * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
1403 * | event.len | event.cmd | p a d d i n g |
1404 * | wrqu data ... (with the correct size) |
1405 *
1406 * This padding exists because we manipulate event->u,
1407 * and 'event' is not packed.
1408 *
1409 * An iw_point event is laid out like this instead:
1410 * | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
1411 * | event.len | event.cmd | p a d d i n g |
1412 * | iwpnt.len | iwpnt.flg | p a d d i n g |
1413 * | extra data ...
1414 *
1415 * The second padding exists because struct iw_point is extended,
1416 * but this depends on the platform...
1417 *
1418 * On 32-bit, all the padding shouldn't be there.
1419 */
1420
1421 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
1422 if (!skb)
1423 return;
1424
1425 /* Send via the RtNetlink event channel */
1426 nlh = rtnetlink_ifinfo_prep(dev, skb);
1427 if (WARN_ON(!nlh)) {
1428 kfree_skb(skb);
1429 return;
1430 }
1431
1432 /* Add the wireless events in the netlink packet */
1433 nla = nla_reserve(skb, IFLA_WIRELESS, event_len);
1434 if (!nla) {
1435 kfree_skb(skb);
1436 return; 1436 return;
1437 }
1438 event = nla_data(nla);
1437 1439
1438 /* Fill event */ 1440 /* Fill event - first clear to avoid data leaking */
1441 memset(event, 0, hdr_len);
1439 event->len = event_len; 1442 event->len = event_len;
1440 event->cmd = cmd; 1443 event->cmd = cmd;
1441 memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN); 1444 memcpy(&event->u, ((char *) wrqu) + wrqu_off, hdr_len - IW_EV_LCP_LEN);
1442 if (extra) 1445 if (extra_len)
1443 memcpy(((char *) event) + hdr_len, extra, extra_len); 1446 memcpy(((char *) event) + hdr_len, extra, extra_len);
1444 1447
1445 /* Send via the RtNetlink event channel */ 1448 nlmsg_end(skb, nlh);
1446 rtmsg_iwinfo(dev, (char *) event, event_len);
1447
1448 /* Cleanup */
1449 kfree(event);
1450 1449
1451 return; /* Always success, I guess ;-) */ 1450 skb_queue_tail(&dev_net(dev)->wext_nlevents, skb);
1451 schedule_work(&wireless_nlevent_work);
1452} 1452}
1453EXPORT_SYMBOL(wireless_send_event); 1453EXPORT_SYMBOL(wireless_send_event);
1454 1454