net, compat_ioctl: handle socket ioctl abuses in tty drivers
[safe/jmp/linux-2.6] / drivers / net / wireless / strip.c
index b7b0c46..698aade 100644 (file)
@@ -106,6 +106,7 @@ static const char StripVersion[] = "1.3A-STUART.CHESHIRE";
 #include <linux/serial.h>
 #include <linux/serialP.h>
 #include <linux/rcupdate.h>
+#include <linux/compat.h>
 #include <net/arp.h>
 #include <net/net_namespace.h>
 
@@ -1533,14 +1534,14 @@ static void strip_send(struct strip *strip_info, struct sk_buff *skb)
 }
 
 /* Encapsulate a datagram and kick it into a TTY queue. */
-static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t strip_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct strip *strip_info = netdev_priv(dev);
 
        if (!netif_running(dev)) {
                printk(KERN_ERR "%s: xmit call when iface is down\n",
                       dev->name);
-               return (1);
+               return NETDEV_TX_BUSY;
        }
 
        netif_stop_queue(dev);
@@ -1550,9 +1551,12 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
 
        if (time_after(jiffies, strip_info->pps_timer + HZ)) {
                unsigned long t = jiffies - strip_info->pps_timer;
-               unsigned long rx_pps_count = (strip_info->rx_pps_count * HZ * 8 + t / 2) / t;
-               unsigned long tx_pps_count = (strip_info->tx_pps_count * HZ * 8 + t / 2) / t;
-               unsigned long sx_pps_count = (strip_info->sx_pps_count * HZ * 8 + t / 2) / t;
+               unsigned long rx_pps_count =
+                       DIV_ROUND_CLOSEST(strip_info->rx_pps_count*HZ*8, t);
+               unsigned long tx_pps_count =
+                       DIV_ROUND_CLOSEST(strip_info->tx_pps_count*HZ*8, t);
+               unsigned long sx_pps_count =
+                       DIV_ROUND_CLOSEST(strip_info->sx_pps_count*HZ*8, t);
 
                strip_info->pps_timer = jiffies;
                strip_info->rx_pps_count = 0;
@@ -1582,7 +1586,7 @@ static int strip_xmit(struct sk_buff *skb, struct net_device *dev)
 
        if (skb)
                dev_kfree_skb(skb);
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 /*
@@ -2722,6 +2726,19 @@ static int strip_ioctl(struct tty_struct *tty, struct file *file,
        return 0;
 }
 
+#ifdef CONFIG_COMPAT
+static long strip_compat_ioctl(struct tty_struct *tty, struct file *file,
+                      unsigned int cmd, unsigned long arg)
+{
+       switch (cmd) {
+       case SIOCGIFNAME:
+       case SIOCSIFHWADDR:
+               return strip_ioctl(tty, file, cmd,
+                       (unsigned long)compat_ptr(arg));
+       }
+       return -ENOIOCTLCMD;
+}
+#endif
 
 /************************************************************************/
 /* Initialization                                                      */
@@ -2733,6 +2750,9 @@ static struct tty_ldisc_ops strip_ldisc = {
        .open = strip_open,
        .close = strip_close,
        .ioctl = strip_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = strip_compat_ioctl,
+#endif
        .receive_buf = strip_receive_buf,
        .write_wakeup = strip_write_some_more,
 };