@@ -1300,22 +1300,15 @@ static void wireless_nlevent_process(struct work_struct *work)
13001300
13011301static DECLARE_WORK (wireless_nlevent_work , wireless_nlevent_process ) ;
13021302
1303- /* ---------------------------------------------------------------- */
1304- /*
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- */
1310- static int rtnetlink_fill_iwinfo (struct sk_buff * skb , struct net_device * dev ,
1311- int type , char * event , int event_len )
1303+ static struct nlmsghdr * rtnetlink_ifinfo_prep (struct net_device * dev ,
1304+ struct sk_buff * skb )
13121305{
13131306 struct ifinfomsg * r ;
13141307 struct nlmsghdr * nlh ;
13151308
1316- nlh = nlmsg_put (skb , 0 , 0 , type , sizeof (* r ), 0 );
1317- if (nlh == NULL )
1318- return - EMSGSIZE ;
1309+ nlh = nlmsg_put (skb , 0 , 0 , RTM_NEWLINK , sizeof (* r ), 0 );
1310+ if (! nlh )
1311+ return NULL ;
13191312
13201313 r = nlmsg_data (nlh );
13211314 r -> ifi_family = AF_UNSPEC ;
@@ -1326,45 +1319,14 @@ static int rtnetlink_fill_iwinfo(struct sk_buff *skb, struct net_device *dev,
13261319 r -> ifi_change = 0 ; /* Wireless changes don't affect those flags */
13271320
13281321 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 );
13331322
1334- nla_put_failure :
1323+ return nlh ;
1324+ nla_put_failure :
13351325 nlmsg_cancel (skb , nlh );
1336- return - EMSGSIZE ;
1326+ return NULL ;
13371327}
13381328
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- */
1346- static 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 ;
13541329
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- /* ---------------------------------------------------------------- */
13681330/*
13691331 * Main event dispatcher. Called from other parts and drivers.
13701332 * Send the event on the appropriate channels.
@@ -1383,6 +1345,9 @@ void wireless_send_event(struct net_device * dev,
13831345 int wrqu_off = 0 ; /* Offset in wrqu */
13841346 /* Don't "optimise" the following variable, it will crash */
13851347 unsigned cmd_index ; /* *MUST* be unsigned */
1348+ struct sk_buff * skb ;
1349+ struct nlmsghdr * nlh ;
1350+ struct nlattr * nla ;
13861351
13871352 /* Get the description of the Event */
13881353 if (cmd <= SIOCIWLAST ) {
@@ -1430,25 +1395,60 @@ void wireless_send_event(struct net_device * dev,
14301395 hdr_len = event_type_size [descr -> header_type ];
14311396 event_len = hdr_len + extra_len ;
14321397
1433- /* Create temporary buffer to hold the event */
1434- event = kmalloc (event_len , GFP_ATOMIC );
1435- if (event == NULL )
1398+ /*
1399+ * The problem for 64/32 bit.
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 );
14361436 return ;
1437+ }
1438+ event = nla_data (nla );
14371439
1438- /* Fill event */
1440+ /* Fill event - first clear to avoid data leaking */
1441+ memset (event , 0 , hdr_len );
14391442 event -> len = event_len ;
14401443 event -> cmd = cmd ;
14411444 memcpy (& event -> u , ((char * ) wrqu ) + wrqu_off , hdr_len - IW_EV_LCP_LEN );
1442- if (extra )
1445+ if (extra_len )
14431446 memcpy (((char * ) event ) + hdr_len , extra , extra_len );
14441447
1445- /* Send via the RtNetlink event channel */
1446- rtmsg_iwinfo (dev , (char * ) event , event_len );
1447-
1448- /* Cleanup */
1449- kfree (event );
1448+ nlmsg_end (skb , nlh );
14501449
1451- return ; /* Always success, I guess ;-) */
1450+ skb_queue_tail (& dev_net (dev )-> wext_nlevents , skb );
1451+ schedule_work (& wireless_nlevent_work );
14521452}
14531453EXPORT_SYMBOL (wireless_send_event );
14541454
0 commit comments