]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - net/sctp/protocol.c
[NETNS]: Inet control socket should not hold a namespace.
[net-next-2.6.git] / net / sctp / protocol.c
index ad0a4069b95be0b78a3c54dc1f4b205d77cde3a2..067c8a1658d6fbf0872129baeb07ba0f0d7656d6 100644 (file)
@@ -74,7 +74,7 @@ DEFINE_SPINLOCK(sctp_assocs_id_lock);
  * the Out-of-the-blue (OOTB) packets.  A control sock will be created
  * for this socket at the initialization time.
  */
-static struct socket *sctp_ctl_socket;
+static struct sock *sctp_ctl_sock;
 
 static struct sctp_pf *sctp_pf_inet6_specific;
 static struct sctp_pf *sctp_pf_inet_specific;
@@ -91,7 +91,7 @@ int sysctl_sctp_wmem[3];
 /* Return the address of the control sock. */
 struct sock *sctp_get_ctl_sock(void)
 {
-       return sctp_ctl_socket->sk;
+       return sctp_ctl_sock;
 }
 
 /* Set up the proc fs entry for the SCTP protocol. */
@@ -337,14 +337,14 @@ static int sctp_v4_cmp_addr(const union sctp_addr *addr1,
 static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port)
 {
        addr->v4.sin_family = AF_INET;
-       addr->v4.sin_addr.s_addr = INADDR_ANY;
+       addr->v4.sin_addr.s_addr = htonl(INADDR_ANY);
        addr->v4.sin_port = port;
 }
 
 /* Is this a wildcard address? */
 static int sctp_v4_is_any(const union sctp_addr *addr)
 {
-       return INADDR_ANY == addr->v4.sin_addr.s_addr;
+       return htonl(INADDR_ANY) == addr->v4.sin_addr.s_addr;
 }
 
 /* This function checks if the address is a valid address to be used for
@@ -363,7 +363,7 @@ static int sctp_v4_addr_valid(union sctp_addr *addr,
                return 0;
 
        /* Is this a broadcast address? */
-       if (skb && ((struct rtable *)skb->dst)->rt_flags & RTCF_BROADCAST)
+       if (skb && skb->rtable->rt_flags & RTCF_BROADCAST)
                return 0;
 
        return 1;
@@ -375,7 +375,7 @@ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
        int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr);
 
 
-       if (addr->v4.sin_addr.s_addr != INADDR_ANY &&
+       if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) &&
           ret != RTN_LOCAL &&
           !sp->inet.freebind &&
           !sysctl_ip_nonlocal_bind)
@@ -451,7 +451,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
                fl.fl4_src = saddr->v4.sin_addr.s_addr;
 
        SCTP_DEBUG_PRINTK("%s: DST:%u.%u.%u.%u, SRC:%u.%u.%u.%u - ",
-                         __FUNCTION__, NIPQUAD(fl.fl4_dst),
+                         __func__, NIPQUAD(fl.fl4_dst),
                          NIPQUAD(fl.fl4_src));
 
        if (!ip_route_output_key(&init_net, &rt, &fl)) {
@@ -539,7 +539,7 @@ static void sctp_v4_get_saddr(struct sctp_association *asoc,
 /* What interface did this skb arrive on? */
 static int sctp_v4_skb_iif(const struct sk_buff *skb)
 {
-       return ((struct rtable *)skb->dst)->rt_iif;
+       return skb->rtable->rt_iif;
 }
 
 /* Was this packet marked by Explicit Congestion Notification? */
@@ -554,7 +554,7 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
 {
        struct inet_sock *inet = inet_sk(sk);
        struct inet_sock *newinet;
-       struct sock *newsk = sk_alloc(sk->sk_net, PF_INET, GFP_KERNEL,
+       struct sock *newsk = sk_alloc(sock_net(sk), PF_INET, GFP_KERNEL,
                        sk->sk_prot);
 
        if (!newsk)
@@ -630,6 +630,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
        struct sctp_sockaddr_entry *temp;
        int found = 0;
 
+       if (dev_net(ifa->ifa_dev->dev) != &init_net)
+               return NOTIFY_DONE;
+
        switch (ev) {
        case NETDEV_UP:
                addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
@@ -677,16 +680,13 @@ static int sctp_ctl_sock_init(void)
        else
                family = PF_INET;
 
-       err = sock_create_kern(family, SOCK_SEQPACKET, IPPROTO_SCTP,
-                              &sctp_ctl_socket);
+       err = inet_ctl_sock_create(&sctp_ctl_sock, family,
+                                  SOCK_SEQPACKET, IPPROTO_SCTP, &init_net);
        if (err < 0) {
                printk(KERN_ERR
                       "SCTP: Failed to create the SCTP control socket.\n");
                return err;
        }
-       sctp_ctl_socket->sk->sk_allocation = GFP_ATOMIC;
-       inet_sk(sctp_ctl_socket->sk)->uc_ttl = -1;
-
        return 0;
 }
 
@@ -785,8 +785,8 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1,
        /* PF_INET only supports AF_INET addresses. */
        if (addr1->sa.sa_family != addr2->sa.sa_family)
                return 0;
-       if (INADDR_ANY == addr1->v4.sin_addr.s_addr ||
-           INADDR_ANY == addr2->v4.sin_addr.s_addr)
+       if (htonl(INADDR_ANY) == addr1->v4.sin_addr.s_addr ||
+           htonl(INADDR_ANY) == addr2->v4.sin_addr.s_addr)
                return 1;
        if (addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr)
                return 1;
@@ -826,9 +826,9 @@ static inline int sctp_v4_xmit(struct sk_buff *skb,
 {
        SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, "
                          "src:%u.%u.%u.%u, dst:%u.%u.%u.%u\n",
-                         __FUNCTION__, skb, skb->len,
-                         NIPQUAD(((struct rtable *)skb->dst)->rt_src),
-                         NIPQUAD(((struct rtable *)skb->dst)->rt_dst));
+                         __func__, skb, skb->len,
+                         NIPQUAD(skb->rtable->rt_src),
+                         NIPQUAD(skb->rtable->rt_dst));
 
        SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS);
        return ip_queue_xmit(skb, ipfragok);
@@ -992,6 +992,58 @@ static void cleanup_sctp_mibs(void)
        free_percpu(sctp_statistics[1]);
 }
 
+static void sctp_v4_pf_init(void)
+{
+       /* Initialize the SCTP specific PF functions. */
+       sctp_register_pf(&sctp_pf_inet, PF_INET);
+       sctp_register_af(&sctp_af_inet);
+}
+
+static void sctp_v4_pf_exit(void)
+{
+       list_del(&sctp_af_inet.list);
+}
+
+static int sctp_v4_protosw_init(void)
+{
+       int rc;
+
+       rc = proto_register(&sctp_prot, 1);
+       if (rc)
+               return rc;
+
+       /* Register SCTP(UDP and TCP style) with socket layer.  */
+       inet_register_protosw(&sctp_seqpacket_protosw);
+       inet_register_protosw(&sctp_stream_protosw);
+
+       return 0;
+}
+
+static void sctp_v4_protosw_exit(void)
+{
+       inet_unregister_protosw(&sctp_stream_protosw);
+       inet_unregister_protosw(&sctp_seqpacket_protosw);
+       proto_unregister(&sctp_prot);
+}
+
+static int sctp_v4_add_protocol(void)
+{
+       /* Register notifier for inet address additions/deletions. */
+       register_inetaddr_notifier(&sctp_inetaddr_notifier);
+
+       /* Register SCTP with inet layer.  */
+       if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0)
+               return -EAGAIN;
+
+       return 0;
+}
+
+static void sctp_v4_del_protocol(void)
+{
+       inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
+       unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
+}
+
 /* Initialize the universe into something sensible.  */
 SCTP_STATIC __init int sctp_init(void)
 {
@@ -1035,8 +1087,6 @@ SCTP_STATIC __init int sctp_init(void)
        /* Initialize object count debugging.  */
        sctp_dbg_objcnt_init();
 
-       /* Initialize the SCTP specific PF functions. */
-       sctp_register_pf(&sctp_pf_inet, PF_INET);
        /*
         * 14. Suggested SCTP Protocol Parameter Values
         */
@@ -1194,19 +1244,22 @@ SCTP_STATIC __init int sctp_init(void)
        sctp_sysctl_register();
 
        INIT_LIST_HEAD(&sctp_address_families);
-       sctp_register_af(&sctp_af_inet);
+       sctp_v4_pf_init();
+       sctp_v6_pf_init();
 
-       status = proto_register(&sctp_prot, 1);
-       if (status)
-               goto err_proto_register;
+       /* Initialize the local address list. */
+       INIT_LIST_HEAD(&sctp_local_addr_list);
+       spin_lock_init(&sctp_local_addr_lock);
+       sctp_get_local_addr_list();
 
-       /* Register SCTP(UDP and TCP style) with socket layer.  */
-       inet_register_protosw(&sctp_seqpacket_protosw);
-       inet_register_protosw(&sctp_stream_protosw);
+       status = sctp_v4_protosw_init();
 
-       status = sctp_v6_init();
        if (status)
-               goto err_v6_init;
+               goto err_protosw_init;
+
+       status = sctp_v6_protosw_init();
+       if (status)
+               goto err_v6_protosw_init;
 
        /* Initialize the control inode/socket for handling OOTB packets.  */
        if ((status = sctp_ctl_sock_init())) {
@@ -1215,19 +1268,9 @@ SCTP_STATIC __init int sctp_init(void)
                goto err_ctl_sock_init;
        }
 
-       /* Initialize the local address list. */
-       INIT_LIST_HEAD(&sctp_local_addr_list);
-       spin_lock_init(&sctp_local_addr_lock);
-       sctp_get_local_addr_list();
-
-       /* Register notifier for inet address additions/deletions. */
-       register_inetaddr_notifier(&sctp_inetaddr_notifier);
-
-       /* Register SCTP with inet layer.  */
-       if (inet_add_protocol(&sctp_protocol, IPPROTO_SCTP) < 0) {
-               status = -EAGAIN;
+       status = sctp_v4_add_protocol();
+       if (status)
                goto err_add_protocol;
-       }
 
        /* Register SCTP with inet6 layer.  */
        status = sctp_v6_add_protocol();
@@ -1238,18 +1281,18 @@ SCTP_STATIC __init int sctp_init(void)
 out:
        return status;
 err_v6_add_protocol:
-       inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
-       unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
+       sctp_v6_del_protocol();
 err_add_protocol:
-       sctp_free_local_addr_list();
-       sock_release(sctp_ctl_socket);
+       sctp_v4_del_protocol();
+       inet_ctl_sock_destroy(sctp_ctl_sock);
 err_ctl_sock_init:
-       sctp_v6_exit();
-err_v6_init:
-       inet_unregister_protosw(&sctp_stream_protosw);
-       inet_unregister_protosw(&sctp_seqpacket_protosw);
-       proto_unregister(&sctp_prot);
-err_proto_register:
+       sctp_v6_protosw_exit();
+err_v6_protosw_init:
+       sctp_v4_protosw_exit();
+err_protosw_init:
+       sctp_free_local_addr_list();
+       sctp_v4_pf_exit();
+       sctp_v6_pf_exit();
        sctp_sysctl_unregister();
        list_del(&sctp_af_inet.list);
        free_pages((unsigned long)sctp_port_hashtable,
@@ -1282,23 +1325,21 @@ SCTP_STATIC __exit void sctp_exit(void)
 
        /* Unregister with inet6/inet layers. */
        sctp_v6_del_protocol();
-       inet_del_protocol(&sctp_protocol, IPPROTO_SCTP);
+       sctp_v4_del_protocol();
 
-       /* Unregister notifier for inet address additions/deletions. */
-       unregister_inetaddr_notifier(&sctp_inetaddr_notifier);
+       /* Free the control endpoint.  */
+       inet_ctl_sock_destroy(sctp_ctl_sock);
+
+       /* Free protosw registrations */
+       sctp_v6_protosw_exit();
+       sctp_v4_protosw_exit();
 
        /* Free the local address list.  */
        sctp_free_local_addr_list();
 
-       /* Free the control endpoint.  */
-       sock_release(sctp_ctl_socket);
-
-       /* Cleanup v6 initializations. */
-       sctp_v6_exit();
-
        /* Unregister with socket layer. */
-       inet_unregister_protosw(&sctp_stream_protosw);
-       inet_unregister_protosw(&sctp_seqpacket_protosw);
+       sctp_v6_pf_exit();
+       sctp_v4_pf_exit();
 
        sctp_sysctl_unregister();
        list_del(&sctp_af_inet.list);
@@ -1317,8 +1358,6 @@ SCTP_STATIC __exit void sctp_exit(void)
 
        kmem_cache_destroy(sctp_chunk_cachep);
        kmem_cache_destroy(sctp_bucket_cachep);
-
-       proto_unregister(&sctp_prot);
 }
 
 module_init(sctp_init);