]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - net/ipv4/tcp_ipv4.c
[NETFILTER]: nf_nat: remove obsolete check for ICMP redirects
[mv-sheeva.git] / net / ipv4 / tcp_ipv4.c
index 46847e600a463b3f62365b4450604b85b84c955d..02519730e0d5a129e8e3f752167cfed1ae560f93 100644 (file)
@@ -88,9 +88,6 @@ int sysctl_tcp_low_latency __read_mostly;
 /* Check TCP sequence numbers in ICMP packets. */
 #define ICMP_MIN_LENGTH 8
 
-/* Socket used for sending RSTs */
-static struct socket *tcp_socket __read_mostly;
-
 void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb);
 
 #ifdef CONFIG_TCP_MD5SIG
@@ -598,7 +595,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
                                      sizeof(struct tcphdr), IPPROTO_TCP, 0);
        arg.csumoffset = offsetof(struct tcphdr, check) / 2;
 
-       ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
+       ip_send_reply(dev_net(skb->dst->dev)->ipv4.tcp_sock, skb,
+                     &arg, arg.iov[0].iov_len);
 
        TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
        TCP_INC_STATS_BH(TCP_MIB_OUTRSTS);
@@ -693,7 +691,8 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
        if (twsk)
                arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if;
 
-       ip_send_reply(tcp_socket->sk, skb, &arg, arg.iov[0].iov_len);
+       ip_send_reply(dev_net(skb->dev)->ipv4.tcp_sock, skb,
+                     &arg, arg.iov[0].iov_len);
 
        TCP_INC_STATS_BH(TCP_MIB_OUTSEGS);
 }
@@ -1300,10 +1299,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
 
        tcp_parse_options(skb, &tmp_opt, 0);
 
-       if (want_cookie) {
+       if (want_cookie && !tmp_opt.saw_tstamp)
                tcp_clear_options(&tmp_opt);
-               tmp_opt.saw_tstamp = 0;
-       }
 
        if (tmp_opt.saw_tstamp && !tmp_opt.rcv_tsval) {
                /* Some OSes (unknown ones, but I see them on web server, which
@@ -1331,6 +1328,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        if (want_cookie) {
 #ifdef CONFIG_SYN_COOKIES
                syn_flood_warning(skb);
+               req->cookie_ts = tmp_opt.tstamp_ok;
 #endif
                isn = cookie_v4_init_sequence(sk, skb, &req->mss);
        } else if (!isn) {
@@ -1956,7 +1954,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
        struct hlist_node *node;
        struct sock *sk = cur;
        struct tcp_iter_state* st = seq->private;
-       struct net *net = st->net;
+       struct net *net = seq_file_net(seq);
 
        if (!sk) {
                st->bucket = 0;
@@ -1974,7 +1972,7 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
                while (1) {
                        while (req) {
                                if (req->rsk_ops->family == st->family &&
-                                   sock_net(req->sk) == net) {
+                                   net_eq(sock_net(req->sk), net)) {
                                        cur = req;
                                        goto out;
                                }
@@ -1998,7 +1996,7 @@ get_req:
        }
 get_sk:
        sk_for_each_from(sk, node) {
-               if (sk->sk_family == st->family && sock_net(sk) == net) {
+               if (sk->sk_family == st->family && net_eq(sock_net(sk), net)) {
                        cur = sk;
                        goto out;
                }
@@ -2037,7 +2035,7 @@ static void *listening_get_idx(struct seq_file *seq, loff_t *pos)
 static void *established_get_first(struct seq_file *seq)
 {
        struct tcp_iter_state* st = seq->private;
-       struct net *net = st->net;
+       struct net *net = seq_file_net(seq);
        void *rc = NULL;
 
        for (st->bucket = 0; st->bucket < tcp_hashinfo.ehash_size; ++st->bucket) {
@@ -2049,7 +2047,7 @@ static void *established_get_first(struct seq_file *seq)
                read_lock_bh(lock);
                sk_for_each(sk, node, &tcp_hashinfo.ehash[st->bucket].chain) {
                        if (sk->sk_family != st->family ||
-                           sock_net(sk) != net) {
+                           !net_eq(sock_net(sk), net)) {
                                continue;
                        }
                        rc = sk;
@@ -2059,7 +2057,7 @@ static void *established_get_first(struct seq_file *seq)
                inet_twsk_for_each(tw, node,
                                   &tcp_hashinfo.ehash[st->bucket].twchain) {
                        if (tw->tw_family != st->family ||
-                           twsk_net(tw) != net) {
+                           !net_eq(twsk_net(tw), net)) {
                                continue;
                        }
                        rc = tw;
@@ -2078,7 +2076,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
        struct inet_timewait_sock *tw;
        struct hlist_node *node;
        struct tcp_iter_state* st = seq->private;
-       struct net *net = st->net;
+       struct net *net = seq_file_net(seq);
 
        ++st->num;
 
@@ -2086,7 +2084,7 @@ static void *established_get_next(struct seq_file *seq, void *cur)
                tw = cur;
                tw = tw_next(tw);
 get_tw:
-               while (tw && (tw->tw_family != st->family || twsk_net(tw) != net)) {
+               while (tw && (tw->tw_family != st->family || !net_eq(twsk_net(tw), net))) {
                        tw = tw_next(tw);
                }
                if (tw) {
@@ -2107,7 +2105,7 @@ get_tw:
                sk = sk_next(sk);
 
        sk_for_each_from(sk, node) {
-               if (sk->sk_family == st->family && sock_net(sk) == net)
+               if (sk->sk_family == st->family && net_eq(sock_net(sk), net))
                        goto found;
        }
 
@@ -2213,51 +2211,19 @@ static void tcp_seq_stop(struct seq_file *seq, void *v)
 static int tcp_seq_open(struct inode *inode, struct file *file)
 {
        struct tcp_seq_afinfo *afinfo = PDE(inode)->data;
-       struct seq_file *seq;
        struct tcp_iter_state *s;
-       struct net *net;
-       int rc;
+       int err;
 
        if (unlikely(afinfo == NULL))
                return -EINVAL;
 
-       s = kzalloc(sizeof(*s), GFP_KERNEL);
-       if (!s)
-               return -ENOMEM;
-
-       rc = -ENXIO;
-       net = get_proc_net(inode);
-       if (!net)
-               goto out_kfree;
+       err = seq_open_net(inode, file, &afinfo->seq_ops,
+                         sizeof(struct tcp_iter_state));
+       if (err < 0)
+               return err;
 
+       s = ((struct seq_file *)file->private_data)->private;
        s->family               = afinfo->family;
-       s->seq_ops.start        = tcp_seq_start;
-       s->seq_ops.next         = tcp_seq_next;
-       s->seq_ops.show         = afinfo->seq_show;
-       s->seq_ops.stop         = tcp_seq_stop;
-       s->net                  = net;
-
-       rc = seq_open(file, &s->seq_ops);
-       if (rc)
-               goto out_put_net;
-       seq = file->private_data;
-       seq->private = s;
-out:
-       return rc;
-out_put_net:
-       put_net(net);
-out_kfree:
-       kfree(s);
-       goto out;
-}
-
-static int tcp_seq_release(struct inode *inode, struct file *file)
-{
-       struct seq_file *seq = file->private_data;
-       struct tcp_iter_state *s = seq->private;
-
-       put_net(s->net);
-       seq_release_private(inode, file);
        return 0;
 }
 
@@ -2266,15 +2232,16 @@ int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo)
        int rc = 0;
        struct proc_dir_entry *p;
 
-       if (!afinfo)
-               return -EINVAL;
-       afinfo->seq_fops->owner         = afinfo->owner;
-       afinfo->seq_fops->open          = tcp_seq_open;
-       afinfo->seq_fops->read          = seq_read;
-       afinfo->seq_fops->llseek        = seq_lseek;
-       afinfo->seq_fops->release       = tcp_seq_release;
+       afinfo->seq_fops.open           = tcp_seq_open;
+       afinfo->seq_fops.read           = seq_read;
+       afinfo->seq_fops.llseek         = seq_lseek;
+       afinfo->seq_fops.release        = seq_release_net;
+
+       afinfo->seq_ops.start           = tcp_seq_start;
+       afinfo->seq_ops.next            = tcp_seq_next;
+       afinfo->seq_ops.stop            = tcp_seq_stop;
 
-       p = proc_net_fops_create(net, afinfo->name, S_IRUGO, afinfo->seq_fops);
+       p = proc_net_fops_create(net, afinfo->name, S_IRUGO, &afinfo->seq_fops);
        if (p)
                p->data = afinfo;
        else
@@ -2284,10 +2251,7 @@ int tcp_proc_register(struct net *net, struct tcp_seq_afinfo *afinfo)
 
 void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo)
 {
-       if (!afinfo)
-               return;
        proc_net_remove(net, afinfo->name);
-       memset(afinfo->seq_fops, 0, sizeof(*afinfo->seq_fops));
 }
 
 static void get_openreq4(struct sock *sk, struct request_sock *req,
@@ -2416,13 +2380,15 @@ out:
        return 0;
 }
 
-static struct file_operations tcp4_seq_fops;
 static struct tcp_seq_afinfo tcp4_seq_afinfo = {
-       .owner          = THIS_MODULE,
        .name           = "tcp",
        .family         = AF_INET,
-       .seq_show       = tcp4_seq_show,
-       .seq_fops       = &tcp4_seq_fops,
+       .seq_fops       = {
+               .owner          = THIS_MODULE,
+       },
+       .seq_ops        = {
+               .show           = tcp4_seq_show,
+       },
 };
 
 static int tcp4_proc_init_net(struct net *net)
@@ -2451,8 +2417,6 @@ void tcp4_proc_exit(void)
 }
 #endif /* CONFIG_PROC_FS */
 
-DEFINE_PROTO_INUSE(tcp)
-
 struct proto tcp_prot = {
        .name                   = "TCP",
        .owner                  = THIS_MODULE,
@@ -2488,13 +2452,28 @@ struct proto tcp_prot = {
        .compat_setsockopt      = compat_tcp_setsockopt,
        .compat_getsockopt      = compat_tcp_getsockopt,
 #endif
-       REF_PROTO_INUSE(tcp)
+};
+
+
+static int __net_init tcp_sk_init(struct net *net)
+{
+       return inet_ctl_sock_create(&net->ipv4.tcp_sock,
+                                   PF_INET, SOCK_RAW, IPPROTO_TCP, net);
+}
+
+static void __net_exit tcp_sk_exit(struct net *net)
+{
+       inet_ctl_sock_destroy(net->ipv4.tcp_sock);
+}
+
+static struct pernet_operations __net_initdata tcp_sk_ops = {
+       .init = tcp_sk_init,
+       .exit = tcp_sk_exit,
 };
 
 void __init tcp_v4_init(void)
 {
-       if (inet_csk_ctl_sock_create(&tcp_socket, PF_INET, SOCK_RAW,
-                                    IPPROTO_TCP) < 0)
+       if (register_pernet_device(&tcp_sk_ops))
                panic("Failed to create the TCP control socket.\n");
 }