]> err.no Git - linux-2.6/blobdiff - net/appletalk/ddp.c
Merge branch 'upstream-linus' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[linux-2.6] / net / appletalk / ddp.c
index 1d31b3a3f1e598c2da003d9dd4e5c50551719e39..7b1eb9a4fc96881a68f9c23e92ea1679edc8cb4d 100644 (file)
@@ -52,6 +52,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/if_arp.h>
 #include <linux/termios.h>     /* For TIOCOUTQ/INQ */
@@ -63,7 +64,7 @@
 #include <linux/atalk.h>
 
 struct datalink_proto *ddp_dl, *aarp_dl;
-static struct proto_ops atalk_dgram_ops;
+static const struct proto_ops atalk_dgram_ops;
 
 /**************************************************************************\
 *                                                                          *
@@ -100,8 +101,7 @@ static struct sock *atalk_search_socket(struct sockaddr_at *to,
                        continue;
 
                if (to->sat_addr.s_net == ATADDR_ANYNET &&
-                   to->sat_addr.s_node == ATADDR_BCAST &&
-                   at->src_net == atif->address.s_net)
+                   to->sat_addr.s_node == ATADDR_BCAST)
                        goto found;
 
                if (to->sat_addr.s_net == at->src_net &&
@@ -1443,8 +1443,10 @@ static int atalk_rcv(struct sk_buff *skb, struct net_device *dev,
        else
                atif = atalk_find_interface(ddp->deh_dnet, ddp->deh_dnode);
 
-       /* Not ours, so we route the packet via the correct AppleTalk iface */
        if (!atif) {
+               /* Not ours, so we route the packet via the correct
+                * AppleTalk iface
+                */
                atalk_route_packet(skb, dev, ddp, &ddphv, origlen);
                goto out;
        }
@@ -1592,9 +1594,6 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 
        if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) {
                rt = atrtr_find(&usat->sat_addr);
-               if (!rt)
-                       return -ENETUNREACH;
-
                dev = rt->dev;
        } else {
                struct atalk_addr at_hint;
@@ -1603,11 +1602,12 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
                at_hint.s_net  = at->src_net;
 
                rt = atrtr_find(&at_hint);
-               if (!rt)
-                       return -ENETUNREACH;
-
                dev = rt->dev;
        }
+       if (!rt)
+               return -ENETUNREACH;
+
+       dev = rt->dev;
 
        SOCK_DEBUG(sk, "SK %p: Size needed %d, device %s\n",
                        sk, size, dev->name);
@@ -1677,6 +1677,20 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
                SOCK_DEBUG(sk, "SK %p: Loop back.\n", sk);
                /* loop back */
                skb_orphan(skb);
+               if (ddp->deh_dnode == ATADDR_BCAST) {
+                       struct atalk_addr at_lo;
+
+                       at_lo.s_node = 0;
+                       at_lo.s_net  = 0;
+
+                       rt = atrtr_find(&at_lo);
+                       if (!rt) {
+                               kfree_skb(skb);
+                               return -ENETUNREACH;
+                       }
+                       dev = rt->dev;
+                       skb->dev = dev;
+               }
                ddp_dl->request(ddp_dl, skb, dev->dev_addr);
        } else {
                SOCK_DEBUG(sk, "SK %p: send out.\n", sk);
@@ -1750,7 +1764,7 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
  */
 static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 {
-       int rc = -EINVAL;
+       int rc = -ENOIOCTLCMD;
        struct sock *sk = sock->sk;
        void __user *argp = (void __user *)arg;
 
@@ -1800,35 +1814,34 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                        rc = atif_ioctl(cmd, argp);
                        rtnl_unlock();
                        break;
-               /* Physical layer ioctl calls */
-               case SIOCSIFLINK:
-               case SIOCGIFHWADDR:
-               case SIOCSIFHWADDR:
-               case SIOCGIFFLAGS:
-               case SIOCSIFFLAGS:
-               case SIOCGIFTXQLEN:
-               case SIOCSIFTXQLEN:
-               case SIOCGIFMTU:
-               case SIOCGIFCONF:
-               case SIOCADDMULTI:
-               case SIOCDELMULTI:
-               case SIOCGIFCOUNT:
-               case SIOCGIFINDEX:
-               case SIOCGIFNAME:
-                       rc = dev_ioctl(cmd, argp);
-                       break;
        }
 
        return rc;
 }
 
+
+#ifdef CONFIG_COMPAT
+static int atalk_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+       /*
+        * All Appletalk ioctls except SIOCATALKDIFADDR are standard.  And
+        * SIOCATALKDIFADDR is handled by upper layer as well, so there is
+        * nothing to do.  Eventually SIOCATALKDIFADDR should be moved
+        * here so there is no generic SIOCPROTOPRIVATE translation in the
+        * system.
+        */
+       return -ENOIOCTLCMD;
+}
+#endif
+
+
 static struct net_proto_family atalk_family_ops = {
        .family         = PF_APPLETALK,
        .create         = atalk_create,
        .owner          = THIS_MODULE,
 };
 
-static struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
+static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
        .family         = PF_APPLETALK,
        .owner          = THIS_MODULE,
        .release        = atalk_release,
@@ -1839,6 +1852,9 @@ static struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
        .getname        = atalk_getname,
        .poll           = datagram_poll,
        .ioctl          = atalk_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = atalk_compat_ioctl,
+#endif
        .listen         = sock_no_listen,
        .shutdown       = sock_no_shutdown,
        .setsockopt     = sock_no_setsockopt,