patch-2.1.9 linux/net/ipv6/tcp_ipv6.c
Next file: linux/net/ipv6/udp.c
Previous file: linux/net/ipv6/sit.c
Back to the patch index
Back to the overall index
- Lines: 135
- Date:
Sun Nov 10 19:53:14 1996
- Orig file:
v2.1.8/linux/net/ipv6/tcp_ipv6.c
- Orig date:
Sun Nov 10 20:12:31 1996
diff -u --recursive --new-file v2.1.8/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c
@@ -779,6 +779,87 @@
tcp_statistics.TcpOutSegs++;
}
+struct sock *tcp_v6_check_req(struct sock *sk, struct sk_buff *skb)
+{
+ struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
+ struct open_request *req;
+
+
+ /*
+ * assumption: the socket is not in use.
+ * as we checked the user count on tcp_rcv and we're
+ * running from a soft interrupt.
+ */
+
+ req = tp->syn_wait_queue;
+
+
+ if (!req)
+ {
+ return sk;
+ }
+
+ do {
+ struct tcp_v6_open_req *af_req;
+
+ af_req = (struct tcp_v6_open_req *) req;
+
+ if (!ipv6_addr_cmp(&af_req->rmt_addr, &skb->ipv6_hdr->saddr) &&
+ !ipv6_addr_cmp(&af_req->loc_addr, &skb->ipv6_hdr->daddr) &&
+ req->rmt_port == skb->h.th->source)
+ {
+ u32 flg;
+
+ if (req->sk)
+ {
+ printk(KERN_DEBUG "BUG: syn_recv:"
+ "socket exists\n");
+ break;
+ }
+
+ /* match */
+
+ /*
+ * Check for syn retransmission
+ */
+ flg = *(((u32 *)skb->h.th) + 3);
+ flg &= __constant_htonl(0x002f0000);
+
+ if ((flg == __constant_htonl(0x00020000)) &&
+ (!after(skb->seq, req->rcv_isn)))
+ {
+ /*
+ * retransmited syn
+ * FIXME: must send an ack
+ */
+ return NULL;
+ }
+
+ atomic_sub(skb->truesize, &sk->rmem_alloc);
+ sk = tp->af_specific->syn_recv_sock(sk, skb, req);
+
+ tcp_dec_slow_timer(TCP_SLT_SYNACK);
+
+ if (sk == NULL)
+ {
+ return NULL;
+ }
+
+ atomic_add(skb->truesize, &sk->rmem_alloc);
+ req->expires = 0UL;
+ req->sk = sk;
+ skb->sk = sk;
+ break;
+ }
+
+ req = req->dl_next;
+ } while (req != tp->syn_wait_queue);
+
+
+ return sk;
+
+}
+
int tcp_v6_rcv(struct sk_buff *skb, struct device *dev,
struct in6_addr *saddr, struct in6_addr *daddr,
struct ipv6_options *opt, unsigned short len,
@@ -890,40 +971,14 @@
if (sk->state == TCP_LISTEN)
{
- struct tcp_opt *tp = &(sk->tp_pinfo.af_tcp);
- struct open_request *req;
- struct tcp_v6_open_req *af_req;
+ /*
+ * find possible connection requests
+ */
+ sk = tcp_v6_check_req(sk, skb);
- req = tp->syn_wait_queue;
- af_req = (struct tcp_v6_open_req *) req;
-
- if (req)
+ if (sk == NULL)
{
- do {
- if (!ipv6_addr_cmp(&af_req->rmt_addr, saddr) &&
- !ipv6_addr_cmp(&af_req->loc_addr, daddr) &&
- req->rmt_port == th->source)
- {
- /* match */
-
- atomic_sub(skb->truesize, &sk->rmem_alloc);
- sk = tp->af_specific->syn_recv_sock(sk, skb,
- req);
- tcp_dec_slow_timer(TCP_SLT_SYNACK);
-
- if (sk == NULL)
- {
- goto no_tcp_socket;
- }
-
- atomic_add(skb->truesize, &sk->rmem_alloc);
- req->sk = sk;
- skb->sk = sk;
- break;
- }
-
- req = req->dl_next;
- } while (req != tp->syn_wait_queue);
+ goto discard_it;
}
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov