]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/ipv4/tcp_ipv4.c
tcpv[46]: fix md5 pseudoheader address field ordering
[linux-2.6-omap-h63xx.git] / net / ipv4 / tcp_ipv4.c
index 37ca3843c40b2a60da712afc4fb943816af5761e..5c8fa7f1e327821dbcb378244e8674183025906c 100644 (file)
@@ -583,14 +583,15 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
                rep.th.doff = arg.iov[0].iov_len / 4;
 
                tcp_v4_md5_hash_hdr((__u8 *) &rep.opt[1],
-                                    key, ip_hdr(skb)->daddr,
-                                    ip_hdr(skb)->saddr, &rep.th);
+                                    key, ip_hdr(skb)->saddr,
+                                    ip_hdr(skb)->daddr, &rep.th);
        }
 #endif
        arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
                                      ip_hdr(skb)->saddr, /* XXX */
-                                     sizeof(struct tcphdr), IPPROTO_TCP, 0);
+                                     arg.iov[0].iov_len, IPPROTO_TCP, 0);
        arg.csumoffset = offsetof(struct tcphdr, check) / 2;
+       arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
 
        net = dev_net(skb->dst->dev);
        ip_send_reply(net->ipv4.tcp_sock, skb,
@@ -606,7 +607,8 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
 
 static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
                            u32 win, u32 ts, int oif,
-                           struct tcp_md5sig_key *key)
+                           struct tcp_md5sig_key *key,
+                           int reply_flags)
 {
        struct tcphdr *th = tcp_hdr(skb);
        struct {
@@ -618,7 +620,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
                        ];
        } rep;
        struct ip_reply_arg arg;
-       struct net *net = dev_net(skb->dev);
+       struct net *net = dev_net(skb->dst->dev);
 
        memset(&rep.th, 0, sizeof(struct tcphdr));
        memset(&arg, 0, sizeof(arg));
@@ -659,6 +661,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack,
                                    ip_hdr(skb)->daddr, &rep.th);
        }
 #endif
+       arg.flags = reply_flags;
        arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
                                      ip_hdr(skb)->saddr, /* XXX */
                                      arg.iov[0].iov_len, IPPROTO_TCP, 0);
@@ -681,7 +684,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
                        tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
                        tcptw->tw_ts_recent,
                        tw->tw_bound_dev_if,
-                       tcp_twsk_md5_key(tcptw)
+                       tcp_twsk_md5_key(tcptw),
+                       tw->tw_transparent ? IP_REPLY_ARG_NOSRCCHECK : 0
                        );
 
        inet_twsk_put(tw);
@@ -694,7 +698,8 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb,
                        tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
                        req->ts_recent,
                        0,
-                       tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr));
+                       tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr),
+                       inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0);
 }
 
 /*
@@ -1244,6 +1249,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
        ireq = inet_rsk(req);
        ireq->loc_addr = daddr;
        ireq->rmt_addr = saddr;
+       ireq->no_srccheck = inet_sk(sk)->transparent;
        ireq->opt = tcp_v4_save_options(sk, skb);
        if (!want_cookie)
                TCP_ECN_create_request(req, tcp_hdr(skb));
@@ -1364,6 +1370,10 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
        tcp_mtup_init(newsk);
        tcp_sync_mss(newsk, dst_mtu(dst));
        newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
+       if (tcp_sk(sk)->rx_opt.user_mss &&
+           tcp_sk(sk)->rx_opt.user_mss < newtp->advmss)
+               newtp->advmss = tcp_sk(sk)->rx_opt.user_mss;
+
        tcp_initialize_rcv_mss(newsk);
 
 #ifdef CONFIG_TCP_MD5SIG
@@ -1567,8 +1577,7 @@ int tcp_v4_rcv(struct sk_buff *skb)
        TCP_SKB_CB(skb)->flags   = iph->tos;
        TCP_SKB_CB(skb)->sacked  = 0;
 
-       sk = __inet_lookup(net, &tcp_hashinfo, iph->saddr,
-                       th->source, iph->daddr, th->dest, inet_iif(skb));
+       sk = __inet_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest);
        if (!sk)
                goto no_tcp_socket;
 
@@ -2388,6 +2397,7 @@ static int __net_init tcp_sk_init(struct net *net)
 static void __net_exit tcp_sk_exit(struct net *net)
 {
        inet_ctl_sock_destroy(net->ipv4.tcp_sock);
+       inet_twsk_purge(net, &tcp_hashinfo, &tcp_death_row, AF_INET);
 }
 
 static struct pernet_operations __net_initdata tcp_sk_ops = {