Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 172151
b: refs/heads/master
c: c4832c7
h: refs/heads/master
i:
  172149: 3133d84
  172147: 61a7171
  172143: b6602fa
v: v3
  • Loading branch information
Pablo Neira Ayuso authored and Patrick McHardy committed Nov 23, 2009
1 parent 7d35f11 commit 5542060
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: dee5817e88ac8195e5938d6671f434a071e35698
refs/heads/master: c4832c7bbc3f7a4813347e871d7238651bf437d3
3 changes: 3 additions & 0 deletions trunk/include/linux/netfilter/nf_conntrack_tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ struct ip_ct_tcp
u_int32_t last_ack; /* Last sequence number seen in opposite dir */
u_int32_t last_end; /* Last seq + len */
u_int16_t last_win; /* Last window advertisement seen in dir */
/* For SYN packets while we may be out-of-sync */
u_int8_t last_wscale; /* Last window scaling factor seen */
u_int8_t last_flags; /* Last flags set */
};

#endif /* __KERNEL__ */
Expand Down
51 changes: 41 additions & 10 deletions trunk/net/netfilter/nf_conntrack_proto_tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -908,23 +908,54 @@ static int tcp_packet(struct nf_conn *ct,
/* b) This SYN/ACK acknowledges a SYN that we earlier
* ignored as invalid. This means that the client and
* the server are both in sync, while the firewall is
* not. We kill this session and block the SYN/ACK so
* that the client cannot but retransmit its SYN and
* thus initiate a clean new session.
* not. We get in sync from the previously annotated
* values.
*/
spin_unlock_bh(&ct->lock);
if (LOG_INVALID(net, IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
"nf_ct_tcp: killing out of sync session ");
nf_ct_kill(ct);
return NF_DROP;
old_state = TCP_CONNTRACK_SYN_SENT;
new_state = TCP_CONNTRACK_SYN_RECV;
ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_end =
ct->proto.tcp.last_end;
ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_maxend =
ct->proto.tcp.last_end;
ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_maxwin =
ct->proto.tcp.last_win == 0 ?
1 : ct->proto.tcp.last_win;
ct->proto.tcp.seen[ct->proto.tcp.last_dir].td_scale =
ct->proto.tcp.last_wscale;
ct->proto.tcp.seen[ct->proto.tcp.last_dir].flags =
ct->proto.tcp.last_flags;
memset(&ct->proto.tcp.seen[dir], 0,
sizeof(struct ip_ct_tcp_state));
break;
}
ct->proto.tcp.last_index = index;
ct->proto.tcp.last_dir = dir;
ct->proto.tcp.last_seq = ntohl(th->seq);
ct->proto.tcp.last_end =
segment_seq_plus_len(ntohl(th->seq), skb->len, dataoff, th);

ct->proto.tcp.last_win = ntohs(th->window);

/* a) This is a SYN in ORIGINAL. The client and the server
* may be in sync but we are not. In that case, we annotate
* the TCP options and let the packet go through. If it is a
* valid SYN packet, the server will reply with a SYN/ACK, and
* then we'll get in sync. Otherwise, the server ignores it. */
if (index == TCP_SYN_SET && dir == IP_CT_DIR_ORIGINAL) {
struct ip_ct_tcp_state seen = {};

ct->proto.tcp.last_flags =
ct->proto.tcp.last_wscale = 0;
tcp_options(skb, dataoff, th, &seen);
if (seen.flags & IP_CT_TCP_FLAG_WINDOW_SCALE) {
ct->proto.tcp.last_flags |=
IP_CT_TCP_FLAG_WINDOW_SCALE;
ct->proto.tcp.last_wscale = seen.td_scale;
}
if (seen.flags & IP_CT_TCP_FLAG_SACK_PERM) {
ct->proto.tcp.last_flags |=
IP_CT_TCP_FLAG_SACK_PERM;
}
}
spin_unlock_bh(&ct->lock);
if (LOG_INVALID(net, IPPROTO_TCP))
nf_log_packet(pf, 0, skb, NULL, NULL, NULL,
Expand Down

0 comments on commit 5542060

Please sign in to comment.