Re: Bug in TCP stack: RST has wrong sequence number?
site_archiver@lists.apple.com Delivered-To: darwin-dev@lists.apple.com Resent-date: Tue, 20 Feb 2007 00:43:31 +0100 Resent-from: dhartmei@benzedrine.cx Resent-message-id: <20070219234331.GG24501@insomnia.benzedrine.cx> Resent-to: darwin-dev@lists.apple.com User-agent: Mutt/1.5.12-2006-07-14 On Mon, Feb 19, 2007 at 09:26:04PM +0100, Axel Rau wrote:
This is perhaps a corner case in the protocol spec. I'm not sure I buy the conclusion above, but it would be good to hear from the experts.
As I read 793, the reset is generated with the current state of the window as the sequence number. From your trace, it looks like the sender (.106) sent data and then immediately reset the connection. The last ack from the receiver (.20) was ...252, so using ...252 seems right to me (the sender can't assume that the ...290 segment was/will be received). Judging from the following resets, the stack will use the last-acked sequence number. Any comments, Daniel?
RFC 793 seems to imply that reset generation should be using SND.NXT as sequence number, which isn't the last-acked sequence number, but the next sequence number to be used for further segments. But if we look at how Darwin checks th_seq on reset reception, we see if (thflags & TH_RST) { if ((SEQ_GEQ(th->th_seq, tp->last_ack_sent) && SEQ_LT(th->th_seq, tp->last_ack_sent + tp->rcv_wnd)) || (tp->rcv_wnd == 0 && tp->last_ack_sent == th->th_seq)) { and there's a difference between this and other BSDs, which use if (tiflags & TH_RST) { if (th->th_seq != tp->last_ack_sent && th->th_seq != tp->rcv_nxt && th->th_seq != (tp->rcv_nxt + 1)) goto drop; This is more strict than the RFC suggests, not allowing the broader range of "whatever is inside the window", but requiring an exact (or at most off-by-one) match, to make RST attacks (guessing sequence numbers) harder. But it also allows last_ack_sent, which at least acknowledges that some stacks use the last-acked sequence number in reset generation. What I don't understand is how Darwin's tcp_output() is intentionally using the last-acked value for reset generation. Looking at tcp_output.c, it does if (len || (flags & (TH_SYN|TH_FIN)) || tp->t_timer[TCPT_PERSIST]) th->th_seq = htonl(tp->snd_nxt); else th->th_seq = htonl(tp->snd_max); And snd_nxt/_max should not be tracking last-acked, but the right edge, i.e. tcp_input() is not updating snd_nxt/_max based on ACKs, but only tcp_output() is updating it, based on segments sent (even if not acknowledged). In our example, the right edge should definitely be ...290, no? Daniel _______________________________________________ Do not post admin requests to the list. They will be ignored. Darwin-dev mailing list (Darwin-dev@lists.apple.com) Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/darwin-dev/site_archiver%40lists.appl... This email sent to site_archiver@lists.apple.com
participants (1)
-
Daniel Hartmeier