Merge to Fedora kernel-2.6.17-1.2187_FC5 patched with stable patch-2.6.17.13-vs2...
[linux-2.6.git] / net / ipx / af_ipx.c
index 344be7e..e6a50e8 100644 (file)
@@ -29,6 +29,7 @@
  */
 
 #include <linux/config.h>
+#include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/if_arp.h>
 #include <linux/if_ether.h>
@@ -44,7 +45,6 @@
 #include <linux/socket.h>
 #include <linux/sockios.h>
 #include <linux/string.h>
-#include <linux/tcp.h>
 #include <linux/types.h>
 #include <linux/termios.h>
 
@@ -52,6 +52,7 @@
 #include <net/p8022.h>
 #include <net/psnap.h>
 #include <net/sock.h>
+#include <net/tcp_states.h>
 
 #include <asm/uaccess.h>
 
@@ -75,13 +76,11 @@ static struct datalink_proto *pEII_datalink;
 static struct datalink_proto *p8023_datalink;
 static struct datalink_proto *pSNAP_datalink;
 
-static struct proto_ops ipx_dgram_ops;
+static const struct proto_ops ipx_dgram_ops;
 
 LIST_HEAD(ipx_interfaces);
 DEFINE_SPINLOCK(ipx_interfaces_lock);
 
-static kmem_cache_t *ipx_sk_slab;
-
 struct ipx_interface *ipx_primary_net;
 struct ipx_interface *ipx_internal_net;
 
@@ -310,7 +309,7 @@ static void __ipxitf_down(struct ipx_interface *intrfc)
                s->sk_error_report(s);
                ipxs->intrfc = NULL;
                ipxs->port   = 0;
-               s->sk_zapped = 1;       /* Indicates it is no longer bound */
+               sock_set_flag(s, SOCK_ZAPPED); /* Indicates it is no longer bound */
                sk_del_node_init(s);
        }
        INIT_HLIST_HEAD(&intrfc->if_sklist);
@@ -945,9 +944,9 @@ out:
        return rc;
 }
 
-static int ipx_map_frame_type(unsigned char type)
+static __be16 ipx_map_frame_type(unsigned char type)
 {
-       int rc = 0;
+       __be16 rc = 0;
 
        switch (type) {
        case IPX_FRAME_ETHERII: rc = htons(ETH_P_IPX);          break;
@@ -1347,6 +1346,12 @@ out:
        return rc;
 }
 
+static struct proto ipx_proto = {
+       .name     = "IPX",
+       .owner    = THIS_MODULE,
+       .obj_size = sizeof(struct ipx_sock),
+};
+
 static int ipx_create(struct socket *sock, int protocol)
 {
        int rc = -ESOCKTNOSUPPORT;
@@ -1361,8 +1366,8 @@ static int ipx_create(struct socket *sock, int protocol)
        if (sock->type != SOCK_DGRAM)
                goto out;
 
-       sk = sk_alloc(PF_IPX, GFP_KERNEL, sizeof(struct ipx_sock), ipx_sk_slab);
                rc = -ENOMEM;
+       sk = sk_alloc(PF_IPX, GFP_KERNEL, &ipx_proto, 1);
        if (!sk)
                goto out;
 #ifdef IPX_REFCNT_DEBUG
@@ -1371,7 +1376,6 @@ static int ipx_create(struct socket *sock, int protocol)
                        atomic_read(&ipx_sock_nr));
 #endif
        sock_init_data(sock, sk);
-       sk_set_owner(sk, THIS_MODULE);
        sk->sk_no_check = 1;            /* Checksum off by default */
        sock->ops = &ipx_dgram_ops;
        rc = 0;
@@ -1427,7 +1431,7 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        struct sockaddr_ipx *addr = (struct sockaddr_ipx *)uaddr;
        int rc = -EINVAL;
 
-       if (!sk->sk_zapped || addr_len != sizeof(struct sockaddr_ipx))
+       if (!sock_flag(sk, SOCK_ZAPPED) || addr_len != sizeof(struct sockaddr_ipx))
                goto out;
 
        intrfc = ipxitf_find_using_net(addr->sipx_network);
@@ -1505,7 +1509,7 @@ static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 #endif /* CONFIG_IPX_INTERN */
 
        ipxitf_insert_socket(intrfc, sk);
-       sk->sk_zapped = 0;
+       sock_reset_flag(sk, SOCK_ZAPPED);
 
        rc = 0;
 out_put:
@@ -1624,7 +1628,7 @@ out:
        return rc;
 }
 
-static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt)
+static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
 {
        /* NULL here for pt means the packet was looped back */
        struct ipx_interface *intrfc;
@@ -1643,7 +1647,8 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
        ipx_pktsize     = ntohs(ipx->ipx_pktsize);
        
        /* Too small or invalid header? */
-       if (ipx_pktsize < sizeof(struct ipxhdr) || ipx_pktsize > skb->len)
+       if (ipx_pktsize < sizeof(struct ipxhdr)
+          || !pskb_may_pull(skb, ipx_pktsize))
                goto drop;
                         
        if (ipx->ipx_checksum != IPX_NO_CHECKSUM &&
@@ -1774,7 +1779,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
        }
        
        rc = -ENOTCONN;
-       if (sk->sk_zapped)
+       if (sock_flag(sk, SOCK_ZAPPED))
                goto out;
 
        skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
@@ -1793,8 +1798,8 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
                                     copied);
        if (rc)
                goto out_free;
-       if (skb->stamp.tv_sec)
-               sk->sk_stamp = skb->stamp;
+       if (skb->tstamp.off_sec)
+               skb_get_timestamp(skb, &sk->sk_stamp);
 
        msg->msg_namelen = sizeof(*sipx);
 
@@ -1881,13 +1886,36 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                rc = -EINVAL;
                break;
        default:
-               rc = dev_ioctl(cmd, argp);
+               rc = -ENOIOCTLCMD;
                break;
        }
 
        return rc;
 }
 
+
+#ifdef CONFIG_COMPAT
+static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
+{
+       /*
+        * These 4 commands use same structure on 32bit and 64bit.  Rest of IPX
+        * commands is handled by generic ioctl code.  As these commands are
+        * SIOCPROTOPRIVATE..SIOCPROTOPRIVATE+3, they cannot be handled by generic
+        * code.
+        */
+       switch (cmd) {
+       case SIOCAIPXITFCRT:
+       case SIOCAIPXPRISLT:
+       case SIOCIPXCFGDATA:
+       case SIOCIPXNCPCONN:
+               return ipx_ioctl(sock, cmd, arg);
+       default:
+               return -ENOIOCTLCMD;
+       }
+}
+#endif
+
+
 /*
  * Socket family declarations
  */
@@ -1898,7 +1926,7 @@ static struct net_proto_family ipx_family_ops = {
        .owner          = THIS_MODULE,
 };
 
-static struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
+static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
        .family         = PF_IPX,
        .owner          = THIS_MODULE,
        .release        = ipx_release,
@@ -1909,6 +1937,9 @@ static struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
        .getname        = ipx_getname,
        .poll           = datagram_poll,
        .ioctl          = ipx_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = ipx_compat_ioctl,
+#endif
        .listen         = sock_no_listen,
        .shutdown       = sock_no_shutdown, /* FIXME: support shutdown */
        .setsockopt     = ipx_setsockopt,
@@ -1937,9 +1968,7 @@ static struct notifier_block ipx_dev_notifier = {
 };
 
 extern struct datalink_proto *make_EII_client(void);
-extern struct datalink_proto *make_8023_client(void);
 extern void destroy_EII_client(struct datalink_proto *);
-extern void destroy_8023_client(struct datalink_proto *);
 
 static unsigned char ipx_8022_type = 0xE0;
 static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
@@ -1954,12 +1983,10 @@ static char ipx_snap_err_msg[] __initdata =
 
 static int __init ipx_init(void)
 {
-       ipx_sk_slab = kmem_cache_create("ipx_sock",
-                                       sizeof(struct ipx_sock), 0,
-                                       SLAB_HWCACHE_ALIGN, NULL, NULL);
+       int rc = proto_register(&ipx_proto, 1);
 
-       if (ipx_sk_slab == NULL)
-               return -ENOMEM;
+       if (rc != 0)
+               goto out;
 
        sock_register(&ipx_family_ops);
 
@@ -1986,7 +2013,8 @@ static int __init ipx_init(void)
        register_netdevice_notifier(&ipx_dev_notifier);
        ipx_register_sysctl();
        ipx_proc_init();
-       return 0;
+out:
+       return rc;
 }
 
 static void __exit ipx_proto_finito(void)
@@ -2012,11 +2040,7 @@ static void __exit ipx_proto_finito(void)
        destroy_EII_client(pEII_datalink);
        pEII_datalink = NULL;
 
-       if (ipx_sk_slab != NULL) {
-               kmem_cache_destroy(ipx_sk_slab);
-               ipx_sk_slab = NULL;
-       }
-
+       proto_unregister(&ipx_proto);
        sock_unregister(ipx_family_ops.family);
 }