diff options
Diffstat (limited to 'net/wireless/wext.c')
-rw-r--r-- | net/wireless/wext.c | 78 |
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 | ||
421 | static 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 | } |