Merge master.kernel.org:/pub/scm/linux/kernel/git/davej/agpgart
[powerpc.git] / net / ipv4 / af_inet.c
index 461216b..edcf093 100644 (file)
@@ -67,7 +67,6 @@
  *             2 of the License, or (at your option) any later version.
  */
 
-#include <linux/config.h>
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/types.h>
@@ -392,7 +391,7 @@ int inet_release(struct socket *sock)
 }
 
 /* It is off by default, see below. */
-int sysctl_ip_nonlocal_bind;
+int sysctl_ip_nonlocal_bind __read_mostly;
 
 int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 {
@@ -988,7 +987,7 @@ void inet_unregister_protosw(struct inet_protosw *p)
  *      Shall we try to damage output packets if routing dev changes?
  */
 
-int sysctl_ip_dynaddr;
+int sysctl_ip_dynaddr __read_mostly;
 
 static int inet_sk_reselect_saddr(struct sock *sk)
 {
@@ -997,7 +996,7 @@ static int inet_sk_reselect_saddr(struct sock *sk)
        struct rtable *rt;
        __u32 old_saddr = inet->saddr;
        __u32 new_saddr;
-       __u32 daddr = inet->daddr;
+       __be32 daddr = inet->daddr;
 
        if (inet->opt && inet->opt->srr)
                daddr = inet->opt->faddr;
@@ -1044,7 +1043,7 @@ int inet_sk_rebuild_header(struct sock *sk)
 {
        struct inet_sock *inet = inet_sk(sk);
        struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0);
-       u32 daddr;
+       __be32 daddr;
        int err;
 
        /* Route is OK, nothing to do. */
@@ -1074,6 +1073,7 @@ int inet_sk_rebuild_header(struct sock *sk)
                },
        };
                                                
+       security_sk_classify_flow(sk, &fl);
        err = ip_route_output_flow(&rt, &fl, sk, 0);
 }
        if (!err)
@@ -1097,7 +1097,41 @@ int inet_sk_rebuild_header(struct sock *sk)
 
 EXPORT_SYMBOL(inet_sk_rebuild_header);
 
-static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg)
+static int inet_gso_send_check(struct sk_buff *skb)
+{
+       struct iphdr *iph;
+       struct net_protocol *ops;
+       int proto;
+       int ihl;
+       int err = -EINVAL;
+
+       if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
+               goto out;
+
+       iph = skb->nh.iph;
+       ihl = iph->ihl * 4;
+       if (ihl < sizeof(*iph))
+               goto out;
+
+       if (unlikely(!pskb_may_pull(skb, ihl)))
+               goto out;
+
+       skb->h.raw = __skb_pull(skb, ihl);
+       iph = skb->nh.iph;
+       proto = iph->protocol & (MAX_INET_PROTOS - 1);
+       err = -EPROTONOSUPPORT;
+
+       rcu_read_lock();
+       ops = rcu_dereference(inet_protos[proto]);
+       if (likely(ops && ops->gso_send_check))
+               err = ops->gso_send_check(skb);
+       rcu_read_unlock();
+
+out:
+       return err;
+}
+
+static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int features)
 {
        struct sk_buff *segs = ERR_PTR(-EINVAL);
        struct iphdr *iph;
@@ -1106,7 +1140,15 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg)
        int ihl;
        int id;
 
-       if (!pskb_may_pull(skb, sizeof(*iph)))
+       if (unlikely(skb_shinfo(skb)->gso_type &
+                    ~(SKB_GSO_TCPV4 |
+                      SKB_GSO_UDP |
+                      SKB_GSO_DODGY |
+                      SKB_GSO_TCP_ECN |
+                      0)))
+               goto out;
+
+       if (unlikely(!pskb_may_pull(skb, sizeof(*iph))))
                goto out;
 
        iph = skb->nh.iph;
@@ -1114,7 +1156,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg)
        if (ihl < sizeof(*iph))
                goto out;
 
-       if (!pskb_may_pull(skb, ihl))
+       if (unlikely(!pskb_may_pull(skb, ihl)))
                goto out;
 
        skb->h.raw = __skb_pull(skb, ihl);
@@ -1125,11 +1167,11 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, int sg)
 
        rcu_read_lock();
        ops = rcu_dereference(inet_protos[proto]);
-       if (ops && ops->gso_segment)
-               segs = ops->gso_segment(skb, sg);
+       if (likely(ops && ops->gso_segment))
+               segs = ops->gso_segment(skb, features);
        rcu_read_unlock();
 
-       if (IS_ERR(segs))
+       if (!segs || unlikely(IS_ERR(segs)))
                goto out;
 
        skb = segs;
@@ -1154,6 +1196,7 @@ static struct net_protocol igmp_protocol = {
 static struct net_protocol tcp_protocol = {
        .handler =      tcp_v4_rcv,
        .err_handler =  tcp_v4_err,
+       .gso_send_check = tcp_v4_gso_send_check,
        .gso_segment =  tcp_tso_segment,
        .no_policy =    1,
 };
@@ -1200,6 +1243,7 @@ static int ipv4_proc_init(void);
 static struct packet_type ip_packet_type = {
        .type = __constant_htons(ETH_P_IP),
        .func = ip_rcv,
+       .gso_send_check = inet_gso_send_check,
        .gso_segment = inet_gso_segment,
 };
 
@@ -1210,10 +1254,7 @@ static int __init inet_init(void)
        struct list_head *r;
        int rc = -EINVAL;
 
-       if (sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb)) {
-               printk(KERN_CRIT "%s: panic\n", __FUNCTION__);
-               goto out;
-       }
+       BUILD_BUG_ON(sizeof(struct inet_skb_parm) > sizeof(dummy_skb->cb));
 
        rc = proto_register(&tcp_prot, 1);
        if (rc)
@@ -1301,10 +1342,10 @@ static int __init inet_init(void)
        rc = 0;
 out:
        return rc;
-out_unregister_tcp_proto:
-       proto_unregister(&tcp_prot);
 out_unregister_udp_proto:
        proto_unregister(&udp_prot);
+out_unregister_tcp_proto:
+       proto_unregister(&tcp_prot);
        goto out;
 }