upgrade to fedora-2.6.12-1.1398.FC4 + vserver 2.0.rc7
[linux-2.6.git] / net / ipx / af_ipx.c
index e88d37f..5a27e5d 100644 (file)
@@ -78,7 +78,7 @@ static struct datalink_proto *pSNAP_datalink;
 static struct proto_ops ipx_dgram_ops;
 
 LIST_HEAD(ipx_interfaces);
-spinlock_t ipx_interfaces_lock = SPIN_LOCK_UNLOCKED;
+DEFINE_SPINLOCK(ipx_interfaces_lock);
 
 struct ipx_interface *ipx_primary_net;
 struct ipx_interface *ipx_internal_net;
@@ -277,7 +277,7 @@ static struct sock *ipxitf_find_internal_socket(struct ipx_interface *intrfc,
        spin_lock_bh(&intrfc->if_sklist_lock);
 
        sk_for_each(s, node, &intrfc->if_sklist) {
-               struct ipx_opt *ipxs = ipx_sk(s);
+               struct ipx_sock *ipxs = ipx_sk(s);
 
                if (ipxs->port == port &&
                    !memcmp(ipx_node, ipxs->node, IPX_NODE_LEN))
@@ -291,7 +291,7 @@ found:
 }
 #endif
 
-void __ipxitf_down(struct ipx_interface *intrfc)
+static void __ipxitf_down(struct ipx_interface *intrfc)
 {
        struct sock *s;
        struct hlist_node *node, *t;
@@ -302,13 +302,13 @@ void __ipxitf_down(struct ipx_interface *intrfc)
        spin_lock_bh(&intrfc->if_sklist_lock);
        /* error sockets */
        sk_for_each_safe(s, node, t, &intrfc->if_sklist) {
-               struct ipx_opt *ipxs = ipx_sk(s);
+               struct ipx_sock *ipxs = ipx_sk(s);
 
                s->sk_err = ENOLINK;
                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);
@@ -335,6 +335,12 @@ void ipxitf_down(struct ipx_interface *intrfc)
        spin_unlock_bh(&ipx_interfaces_lock);
 }
 
+static __inline__ void __ipxitf_put(struct ipx_interface *intrfc)
+{
+       if (atomic_dec_and_test(&intrfc->refcnt))
+               __ipxitf_down(intrfc);
+}
+
 static int ipxitf_device_event(struct notifier_block *notifier,
                                unsigned long event, void *ptr)
 {
@@ -394,7 +400,7 @@ static int ipxitf_demux_socket(struct ipx_interface *intrfc,
        spin_lock_bh(&intrfc->if_sklist_lock);
 
        sk_for_each(s, node, &intrfc->if_sklist) {
-               struct ipx_opt *ipxs = ipx_sk(s);
+               struct ipx_sock *ipxs = ipx_sk(s);
 
                if (ipxs->port == ipx->ipx_dest.sock &&
                    (is_broadcast || !memcmp(ipx->ipx_dest.node,
@@ -1339,49 +1345,41 @@ 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;
-       struct ipx_opt *ipx = NULL;
        struct sock *sk;
 
-       switch (sock->type) {
-       case SOCK_DGRAM:
-               sk = sk_alloc(PF_IPX, GFP_KERNEL, 1, NULL);
-               rc = -ENOMEM;
-               if (!sk)
-                       goto out;
-               ipx = sk->sk_protinfo = kmalloc(sizeof(*ipx), GFP_KERNEL);
-               if (!ipx)
-                       goto outsk;
-               memset(ipx, 0, sizeof(*ipx));
-                sock->ops = &ipx_dgram_ops;
-                break;
-       case SOCK_SEQPACKET:
-               /*
-                * SPX support is not anymore in the kernel sources. If
-                * you want to ressurrect it, completing it and making
-                * it understand shared skbs, be fully multithreaded,
-                * etc, grab the sources in an early 2.5 kernel tree.
-                */
-       case SOCK_STREAM:       /* Allow higher levels to piggyback */
-       default:
+       /*
+        * SPX support is not anymore in the kernel sources. If you want to
+        * ressurrect it, completing it and making it understand shared skbs,
+        * be fully multithreaded, etc, grab the sources in an early 2.5 kernel
+        * tree.
+        */
+       if (sock->type != SOCK_DGRAM)
+               goto out;
+
+               rc = -ENOMEM;
+       sk = sk_alloc(PF_IPX, GFP_KERNEL, &ipx_proto, 1);
+       if (!sk)
                goto out;
-       }
 #ifdef IPX_REFCNT_DEBUG
         atomic_inc(&ipx_sock_nr);
         printk(KERN_DEBUG "IPX socket %p created, now we have %d alive\n", sk,
                        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;
 out:
        return rc;
-outsk:
-       sk_free(sk);
-       goto out;
 }
 
 static int ipx_release(struct socket *sock)
@@ -1427,12 +1425,12 @@ static unsigned short ipx_first_free_socketnum(struct ipx_interface *intrfc)
 static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
        struct sock *sk = sock->sk;
-       struct ipx_opt *ipxs = ipx_sk(sk);
+       struct ipx_sock *ipxs = ipx_sk(sk);
        struct ipx_interface *intrfc;
        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);
@@ -1510,7 +1508,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:
@@ -1523,7 +1521,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
        int addr_len, int flags)
 {
        struct sock *sk = sock->sk;
-       struct ipx_opt *ipxs = ipx_sk(sk);
+       struct ipx_sock *ipxs = ipx_sk(sk);
        struct sockaddr_ipx *addr;
        int rc = -EINVAL;
        struct ipx_route *rt;
@@ -1587,7 +1585,7 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
        struct ipx_address *addr;
        struct sockaddr_ipx sipx;
        struct sock *sk = sock->sk;
-       struct ipx_opt *ipxs = ipx_sk(sk);
+       struct ipx_sock *ipxs = ipx_sk(sk);
        int rc;
 
        *uaddr_len = sizeof(struct sockaddr_ipx);
@@ -1629,7 +1627,7 @@ out:
        return rc;
 }
 
-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)
 {
        /* NULL here for pt means the packet was looped back */
        struct ipx_interface *intrfc;
@@ -1687,7 +1685,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
        struct msghdr *msg, size_t len)
 {
        struct sock *sk = sock->sk;
-       struct ipx_opt *ipxs = ipx_sk(sk);
+       struct ipx_sock *ipxs = ipx_sk(sk);
        struct sockaddr_ipx *usipx = (struct sockaddr_ipx *)msg->msg_name;
        struct sockaddr_ipx local_sipx;
        int rc = -EINVAL;
@@ -1752,7 +1750,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
                struct msghdr *msg, size_t size, int flags)
 {
        struct sock *sk = sock->sk;
-       struct ipx_opt *ipxs = ipx_sk(sk);
+       struct ipx_sock *ipxs = ipx_sk(sk);
        struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)msg->msg_name;
        struct ipxhdr *ipx = NULL;
        struct sk_buff *skb;
@@ -1779,7 +1777,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,
@@ -1959,6 +1957,11 @@ static char ipx_snap_err_msg[] __initdata =
 
 static int __init ipx_init(void)
 {
+       int rc = proto_register(&ipx_proto, 1);
+
+       if (rc != 0)
+               goto out;
+
        sock_register(&ipx_family_ops);
 
        pEII_datalink = make_EII_client();
@@ -1984,7 +1987,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)
@@ -2010,6 +2014,7 @@ static void __exit ipx_proto_finito(void)
        destroy_EII_client(pEII_datalink);
        pEII_datalink = NULL;
 
+       proto_unregister(&ipx_proto);
        sock_unregister(ipx_family_ops.family);
 }