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.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/net/wireless/wext.c b/net/wireless/wext.c
index ee35e6422f1f..3fe3c2c0ce11 100644
--- a/net/wireless/wext.c
+++ b/net/wireless/wext.c
@@ -417,6 +417,21 @@ static const int event_type_size[] = {
417 IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */ 417 IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */
418}; 418};
419 419
420#ifdef CONFIG_COMPAT
421static const int compat_event_type_size[] = {
422 IW_EV_COMPAT_LCP_LEN, /* IW_HEADER_TYPE_NULL */
423 0,
424 IW_EV_COMPAT_CHAR_LEN, /* IW_HEADER_TYPE_CHAR */
425 0,
426 IW_EV_COMPAT_UINT_LEN, /* IW_HEADER_TYPE_UINT */
427 IW_EV_COMPAT_FREQ_LEN, /* IW_HEADER_TYPE_FREQ */
428 IW_EV_COMPAT_ADDR_LEN, /* IW_HEADER_TYPE_ADDR */
429 0,
430 IW_EV_COMPAT_POINT_LEN, /* Without variable payload */
431 IW_EV_COMPAT_PARAM_LEN, /* IW_HEADER_TYPE_PARAM */
432 IW_EV_COMPAT_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */
433};
434#endif
420 435
421/************************ COMMON SUBROUTINES ************************/ 436/************************ COMMON SUBROUTINES ************************/
422/* 437/*
@@ -1348,6 +1363,22 @@ void wireless_send_event(struct net_device * dev,
1348 struct sk_buff *skb; 1363 struct sk_buff *skb;
1349 struct nlmsghdr *nlh; 1364 struct nlmsghdr *nlh;
1350 struct nlattr *nla; 1365 struct nlattr *nla;
1366#ifdef CONFIG_COMPAT
1367 struct __compat_iw_event *compat_event;
1368 struct compat_iw_point compat_wrqu;
1369 struct sk_buff *compskb;
1370#endif
1371
1372 /*
1373 * Nothing in the kernel sends scan events with data, be safe.
1374 * This is necessary because we cannot fix up scan event data
1375 * for compat, due to being contained in 'extra', but normally
1376 * applications are required to retrieve the scan data anyway
1377 * and no data is included in the event, this codifies that
1378 * practice.
1379 */
1380 if (WARN_ON(cmd == SIOCGIWSCAN && extra))
1381 extra = NULL;
1351 1382
1352 /* Get the description of the Event */ 1383 /* Get the description of the Event */
1353 if (cmd <= SIOCIWLAST) { 1384 if (cmd <= SIOCIWLAST) {
@@ -1446,7 +1477,54 @@ void wireless_send_event(struct net_device * dev,
1446 memcpy(((char *) event) + hdr_len, extra, extra_len); 1477 memcpy(((char *) event) + hdr_len, extra, extra_len);
1447 1478
1448 nlmsg_end(skb, nlh); 1479 nlmsg_end(skb, nlh);
1480#ifdef CONFIG_COMPAT
1481 hdr_len = compat_event_type_size[descr->header_type];
1482 event_len = hdr_len + extra_len;
1449 1483
1484 compskb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
1485 if (!compskb) {
1486 kfree_skb(skb);
1487 return;
1488 }
1489
1490 /* Send via the RtNetlink event channel */
1491 nlh = rtnetlink_ifinfo_prep(dev, compskb);
1492 if (WARN_ON(!nlh)) {
1493 kfree_skb(skb);
1494 kfree_skb(compskb);
1495 return;
1496 }
1497
1498 /* Add the wireless events in the netlink packet */
1499 nla = nla_reserve(compskb, IFLA_WIRELESS, event_len);
1500 if (!nla) {
1501 kfree_skb(skb);
1502 kfree_skb(compskb);
1503 return;
1504 }
1505 compat_event = nla_data(nla);
1506
1507 compat_event->len = event_len;
1508 compat_event->cmd = cmd;
1509 if (descr->header_type == IW_HEADER_TYPE_POINT) {
1510 compat_wrqu.length = wrqu->data.length;
1511 compat_wrqu.flags = wrqu->data.flags;
1512 memcpy(&compat_event->pointer,
1513 ((char *) &compat_wrqu) + IW_EV_COMPAT_POINT_OFF,
1514 hdr_len - IW_EV_COMPAT_LCP_LEN);
1515 if (extra_len)
1516 memcpy(((char *) compat_event) + hdr_len,
1517 extra, extra_len);
1518 } else {
1519 /* extra_len must be zero, so no if (extra) needed */
1520 memcpy(&compat_event->pointer, wrqu,
1521 hdr_len - IW_EV_COMPAT_LCP_LEN);
1522 }
1523
1524 nlmsg_end(compskb, nlh);
1525
1526 skb_shinfo(skb)->frag_list = compskb;
1527#endif
1450 skb_queue_tail(&dev_net(dev)->wext_nlevents, skb); 1528 skb_queue_tail(&dev_net(dev)->wext_nlevents, skb);
1451 schedule_work(&wireless_nlevent_work); 1529 schedule_work(&wireless_nlevent_work);
1452} 1530}