- 论坛徽章:
- 0
|
内核版本: 2.6.21-RC5-rt12
我觉得, 你对tcp_v4_hnd_req()的理解有问题:
tcp_v4_hnd_req()会返回以下三种值, 分别代表三类情况:
1. == NULL, 报文有问题, 一般是安全问题, 如, 攻击listen socket, 落在窗口外, 等.
2. != sk, 接收到的是客户端发送的三次握手中的最后一次, 就是ack报文. 处理在tcp_v4_hnd_req() -- >tcp_check_req()中
3. == sk, 接收到的是三次握手中的第一个报文, 就是syn报文, 这时会落到tcp_rcv_state_process()中处理, 也就是说tcp_rcv_state_process() 在TCP_LISTEN状态时, 只处理syn报文, 其他都是出错情况, 因为ack在tcp_v4_hnd_req()处理完了.
代码分析:
static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb)
{
struct tcphdr *th = skb->h.th;
struct iphdr *iph = skb->nh.iph;
struct sock *nsk;
struct request_sock **prev;
/* 查找出于半连接状态的请求 */
struct request_sock *req = inet_csk_search_req(sk, &prev, th->source,
iph->saddr, iph->daddr);
/* 如果找到,检查报文是否符合协议标准和安全规则, 如果符合所有规则,
会将连接放到listen complete队列中(accept()需要)。*/
if (req)
return tcp_check_req(sk, skb, req, prev);
/* 如果没有找到, 检查是否在已经建立好的连接表或者time_wait表中能找到连接 */
nsk = inet_lookup_established(&tcp_hashinfo, skb->nh.iph->saddr,
th->source, skb->nh.iph->daddr,
th->dest, inet_iif(skb));
/* 如果可以,可能是错误,为了安全,需要关闭这个连接,或者继续处理?? */
if (nsk) {
if (nsk->sk_state != TCP_TIME_WAIT) {
bh_lock_sock(nsk);
return nsk;
}
inet_twsk_put(inet_twsk(nsk));
return NULL;
}
/* 防止DDos攻击 */
#ifdef CONFIG_SYN_COOKIES
if (!th->rst && !th->syn && th->ack)
sk = cookie_v4_check(sk, skb, &(IPCB(skb)->opt));
#endif
/* 注意, 最后所有情况都正常,返回sk */
return sk;
} |
|