[ Pobierz całość w formacie PDF ]
.Also see RFC1379.** Note the funny way we go back to the top of this function for* this case ("goto try_next_socket").That also takes care of* checking "sk->users" for the new socket as well as doing all* the normal tests on the packet.*/#define BSD_TIME_WAIT#ifdef BSD_TIME_WAITif (sk->state == TCP_TIME_WAIT && th->syn && sk->dead &&after(skb->seq, sk->acked_seq) && !th->rst){u32 seq = sk->write_seq;if(sk->debug)printk("Doing a BSD time wait\n");tcp_statistics.TcpEstabResets++;atomic_sub(skb->truesize, &sk->rmem_alloc);skb->sk = NULL;sk->err=ECONNRESET;tcp_set_state(sk, TCP_CLOSE);sk->shutdown = SHUTDOWN_MASK;sk=get_sock(&tcp_prot, th->dest, saddr, th->source, daddr, dev->pa_addr, skb->redirport);/* this is not really correct: we should check sk->users */if (sk && sk->state==TCP_LISTEN){skb->sk = sk;atomic_add(skb->truesize, &sk->rmem_alloc);tcp_conn_request(sk, skb, daddr, saddr,opt, dev,seq+128000);return 0;}kfree_skb(skb, FREE_READ);return 0;}#endif}/** We are now in normal data flow (see the step list in the RFC)* Note most of these are inline now.I'll inline the lot when* I have time to test it hard and look at what gcc outputs*/if (!tcp_sequence(sk, skb->seq, skb->end_seq-th->syn)){bad_tcp_sequence(sk, th, skb->end_seq-th->syn, dev);kfree_skb(skb, FREE_READ);return 0;}if(th->rst)return tcp_reset(sk,skb);/** Check for a SYN, and ensure it matches the SYN we were* first sent.We have to handle the rather unusual (but valid)* sequence that KA9Q derived products may generate of** SYN* SYN|ACK Data* ACK (lost)* SYN|ACK Data + More Data*.we must ACK not RST.** We keep syn_seq as the sequence space occupied by the* original syn.*/if(th->syn && skb->seq!=sk->syn_seq){tcp_send_reset(daddr,saddr,th, &tcp_prot, opt, dev,0, 255);return tcp_reset(sk,skb);}/** Process the ACK*/if(th->ack && !tcp_ack(sk,th,skb->ack_seq,len)){/** Our three way handshake failed.*/if(sk->state==TCP_SYN_RECV){tcp_send_reset(daddr, saddr, th,sk->prot, opt, dev,0,255);}kfree_skb(skb, FREE_READ);return 0;}rfc_step6: /* I'll clean this up later *//** If the accepted buffer put us over our queue size we* now drop it (we must process the ack first to avoid* deadlock cases).*//** Process urgent data*/tcp_urg(sk, th, len);/** Process the encapsulated data*/if(tcp_data(skb,sk, saddr, len))kfree_skb(skb, FREE_READ);/** If our receive queue has grown past its limits,* try to prune away duplicates etc.*/if (sk->rmem_alloc > sk->rcvbuf)prune_queue(&sk->receive_queue);/** And done*/return 0;no_tcp_socket:/** No such TCB.If th->rst is 0 send a reset (checked in tcp_send_reset)*/tcp_send_reset(daddr, saddr, th, &tcp_prot, opt,dev,0,255);discard_it:/** Discard frame*/skb->sk = NULL;kfree_skb(skb, FREE_READ);return 0;}
[ Pobierz całość w formacie PDF ]