Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[safe/jmp/linux-2.6] / net / sctp / protocol.c
index d50f610..25be8f0 100644 (file)
@@ -1,4 +1,4 @@
-/* SCTP kernel reference Implementation
+/* SCTP kernel implementation
  * (C) Copyright IBM Corp. 2001, 2004
  * Copyright (c) 1999-2000 Cisco, Inc.
  * Copyright (c) 1999-2001 Motorola, Inc.
@@ -6,17 +6,17 @@
  * Copyright (c) 2001 Nokia, Inc.
  * Copyright (c) 2001 La Monte H.P. Yarroll
  *
- * This file is part of the SCTP kernel reference Implementation
+ * This file is part of the SCTP kernel implementation
  *
  * Initialization/cleanup for SCTP protocol support.
  *
- * The SCTP reference implementation is free software;
+ * This SCTP implementation is free software;
  * you can redistribute it and/or modify it under the terms of
  * the GNU General Public License as published by
  * the Free Software Foundation; either version 2, or (at your option)
  * any later version.
  *
- * The SCTP reference implementation is distributed in the hope that it
+ * This SCTP implementation is distributed in the hope that it
  * will be useful, but WITHOUT ANY WARRANTY; without even the implied
  *                 ************************
  * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
@@ -229,8 +229,8 @@ int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope,
                            (((AF_INET6 == addr->a.sa.sa_family) &&
                              (copy_flags & SCTP_ADDR6_ALLOWED) &&
                              (copy_flags & SCTP_ADDR6_PEERSUPP)))) {
-                               error = sctp_add_bind_addr(bp, &addr->a, 1,
-                                                   GFP_ATOMIC);
+                               error = sctp_add_bind_addr(bp, &addr->a,
+                                                   SCTP_ADDR_SRC, GFP_ATOMIC);
                                if (error)
                                        goto end_copy;
                        }
@@ -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
@@ -359,11 +359,11 @@ static int sctp_v4_addr_valid(union sctp_addr *addr,
                              const struct sk_buff *skb)
 {
        /* Is this a non-unicast address or a unusable SCTP address? */
-       if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr))
+       if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_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;
@@ -372,10 +372,10 @@ static int sctp_v4_addr_valid(union sctp_addr *addr,
 /* Should this be available for binding?   */
 static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
 {
-       int ret = inet_addr_type(addr->v4.sin_addr.s_addr);
+       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)
@@ -408,13 +408,15 @@ static sctp_scope_t sctp_v4_scope(union sctp_addr *addr)
         */
 
        /* Check for unusable SCTP addresses. */
-       if (IS_IPV4_UNUSABLE_ADDRESS(&addr->v4.sin_addr.s_addr)) {
+       if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr)) {
                retval =  SCTP_SCOPE_UNUSABLE;
-       } else if (LOOPBACK(addr->v4.sin_addr.s_addr)) {
+       } else if (ipv4_is_loopback(addr->v4.sin_addr.s_addr)) {
                retval = SCTP_SCOPE_LOOPBACK;
-       } else if (IS_IPV4_LINK_ADDRESS(&addr->v4.sin_addr.s_addr)) {
+       } else if (ipv4_is_linklocal_169(addr->v4.sin_addr.s_addr)) {
                retval = SCTP_SCOPE_LINK;
-       } else if (IS_IPV4_PRIVATE_ADDRESS(&addr->v4.sin_addr.s_addr)) {
+       } else if (ipv4_is_private_10(addr->v4.sin_addr.s_addr) ||
+                  ipv4_is_private_172(addr->v4.sin_addr.s_addr) ||
+                  ipv4_is_private_192(addr->v4.sin_addr.s_addr)) {
                retval = SCTP_SCOPE_PRIVATE;
        } else {
                retval = SCTP_SCOPE_GLOBAL;
@@ -449,10 +451,10 @@ 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(&rt, &fl)) {
+       if (!ip_route_output_key(&init_net, &rt, &fl)) {
                dst = &rt->u.dst;
        }
 
@@ -470,7 +472,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
                 */
                rcu_read_lock();
                list_for_each_entry_rcu(laddr, &bp->address_list, list) {
-                       if (!laddr->valid || !laddr->use_as_src)
+                       if (!laddr->valid || (laddr->state != SCTP_ADDR_SRC))
                                continue;
                        sctp_v4_dst_saddr(&dst_saddr, dst, htons(bp->port));
                        if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a))
@@ -492,10 +494,10 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc,
        list_for_each_entry_rcu(laddr, &bp->address_list, list) {
                if (!laddr->valid)
                        continue;
-               if ((laddr->use_as_src) &&
+               if ((laddr->state == SCTP_ADDR_SRC) &&
                    (AF_INET == laddr->a.sa.sa_family)) {
                        fl.fl4_src = laddr->a.v4.sin_addr.s_addr;
-                       if (!ip_route_output_key(&rt, &fl)) {
+                       if (!ip_route_output_key(&init_net, &rt, &fl)) {
                                dst = &rt->u.dst;
                                goto out_unlock;
                        }
@@ -537,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? */
@@ -626,6 +628,10 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
        struct in_ifaddr *ifa = (struct in_ifaddr *)ptr;
        struct sctp_sockaddr_entry *addr = NULL;
        struct sctp_sockaddr_entry *temp;
+       int found = 0;
+
+       if (ifa->ifa_dev->dev->nd_net != &init_net)
+               return NOTIFY_DONE;
 
        switch (ev) {
        case NETDEV_UP:
@@ -645,13 +651,14 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
                list_for_each_entry_safe(addr, temp,
                                        &sctp_local_addr_list, list) {
                        if (addr->a.v4.sin_addr.s_addr == ifa->ifa_local) {
+                               found = 1;
                                addr->valid = 0;
                                list_del_rcu(&addr->list);
                                break;
                        }
                }
                spin_unlock_bh(&sctp_local_addr_lock);
-               if (addr && !addr->valid)
+               if (found)
                        call_rcu(&addr->rcu, sctp_local_addr_free);
                break;
        }
@@ -781,8 +788,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;
@@ -822,15 +829,15 @@ 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);
 }
 
-static struct sctp_af sctp_ipv4_specific;
+static struct sctp_af sctp_af_inet;
 
 static struct sctp_pf sctp_pf_inet = {
        .event_msgname = sctp_inet_event_msgname,
@@ -842,7 +849,7 @@ static struct sctp_pf sctp_pf_inet = {
        .supported_addrs = sctp_inet_supported_addrs,
        .create_accept_sk = sctp_v4_create_accept_sk,
        .addr_v4map     = sctp_v4_addr_v4map,
-       .af            = &sctp_ipv4_specific,
+       .af            = &sctp_af_inet
 };
 
 /* Notifier for inetaddr addition/deletion events.  */
@@ -904,7 +911,7 @@ static struct net_protocol sctp_protocol = {
 };
 
 /* IPv4 address related functions.  */
-static struct sctp_af sctp_ipv4_specific = {
+static struct sctp_af sctp_af_inet = {
        .sa_family         = AF_INET,
        .sctp_xmit         = sctp_v4_xmit,
        .setsockopt        = ip_setsockopt,
@@ -1107,7 +1114,7 @@ SCTP_STATIC __init int sctp_init(void)
        sysctl_sctp_rmem[1] = (1500 *(sizeof(struct sk_buff) + 1));
        sysctl_sctp_rmem[2] = max(sysctl_sctp_rmem[1], max_share);
 
-       sysctl_sctp_wmem[0] = SK_STREAM_MEM_QUANTUM;
+       sysctl_sctp_wmem[0] = SK_MEM_QUANTUM;
        sysctl_sctp_wmem[1] = 16*1024;
        sysctl_sctp_wmem[2] = max(64*1024, max_share);
 
@@ -1190,7 +1197,7 @@ SCTP_STATIC __init int sctp_init(void)
        sctp_sysctl_register();
 
        INIT_LIST_HEAD(&sctp_address_families);
-       sctp_register_af(&sctp_ipv4_specific);
+       sctp_register_af(&sctp_af_inet);
 
        status = proto_register(&sctp_prot, 1);
        if (status)
@@ -1247,7 +1254,7 @@ err_v6_init:
        proto_unregister(&sctp_prot);
 err_proto_register:
        sctp_sysctl_unregister();
-       list_del(&sctp_ipv4_specific.list);
+       list_del(&sctp_af_inet.list);
        free_pages((unsigned long)sctp_port_hashtable,
                   get_order(sctp_port_hashsize *
                             sizeof(struct sctp_bind_hashbucket)));
@@ -1297,7 +1304,7 @@ SCTP_STATIC __exit void sctp_exit(void)
        inet_unregister_protosw(&sctp_seqpacket_protosw);
 
        sctp_sysctl_unregister();
-       list_del(&sctp_ipv4_specific.list);
+       list_del(&sctp_af_inet.list);
 
        free_pages((unsigned long)sctp_assoc_hashtable,
                   get_order(sctp_assoc_hashsize *