[NETFILTER]: ctnetlink: add support for internal tcp connection tracking flags handling

This patch let userspace programs set the IP_CT_TCP_BE_LIBERAL flag to
force the pickup of established connections.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Pablo Neira Ayuso 2007-03-14 16:45:19 -07:00 committed by David S. Miller
parent 5c8ce7c921
commit c8e2078cfe
3 changed files with 53 additions and 1 deletions

View File

@ -30,6 +30,11 @@ enum tcp_conntrack {
/* Be liberal in window checking */
#define IP_CT_TCP_FLAG_BE_LIBERAL 0x08
struct nf_ct_tcp_flags {
u_int8_t flags;
u_int8_t mask;
};
#ifdef __KERNEL__
struct ip_ct_tcp_state {

View File

@ -83,6 +83,10 @@ enum ctattr_protoinfo {
enum ctattr_protoinfo_tcp {
CTA_PROTOINFO_TCP_UNSPEC,
CTA_PROTOINFO_TCP_STATE,
CTA_PROTOINFO_TCP_WSCALE_ORIGINAL,
CTA_PROTOINFO_TCP_WSCALE_REPLY,
CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
CTA_PROTOINFO_TCP_FLAGS_REPLY,
__CTA_PROTOINFO_TCP_MAX
};
#define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1)

View File

@ -1101,11 +1101,26 @@ static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
const struct nf_conn *ct)
{
struct nfattr *nest_parms;
struct nf_ct_tcp_flags tmp = {};
read_lock_bh(&tcp_lock);
nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP);
NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
&ct->proto.tcp.state);
NFA_PUT(skb, CTA_PROTOINFO_TCP_WSCALE_ORIGINAL, sizeof(u_int8_t),
&ct->proto.tcp.seen[0].td_scale);
NFA_PUT(skb, CTA_PROTOINFO_TCP_WSCALE_REPLY, sizeof(u_int8_t),
&ct->proto.tcp.seen[1].td_scale);
tmp.flags = ct->proto.tcp.seen[0].flags;
NFA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
sizeof(struct nf_ct_tcp_flags), &tmp);
tmp.flags = ct->proto.tcp.seen[1].flags;
NFA_PUT(skb, CTA_PROTOINFO_TCP_FLAGS_REPLY,
sizeof(struct nf_ct_tcp_flags), &tmp);
read_unlock_bh(&tcp_lock);
NFA_NEST_END(skb, nest_parms);
@ -1118,7 +1133,11 @@ nfattr_failure:
}
static const size_t cta_min_tcp[CTA_PROTOINFO_TCP_MAX] = {
[CTA_PROTOINFO_TCP_STATE-1] = sizeof(u_int8_t),
[CTA_PROTOINFO_TCP_STATE-1] = sizeof(u_int8_t),
[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL-1] = sizeof(u_int8_t),
[CTA_PROTOINFO_TCP_WSCALE_REPLY-1] = sizeof(u_int8_t),
[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL-1] = sizeof(struct nf_ct_tcp_flags),
[CTA_PROTOINFO_TCP_FLAGS_REPLY-1] = sizeof(struct nf_ct_tcp_flags)
};
static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct)
@ -1142,6 +1161,30 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct)
write_lock_bh(&tcp_lock);
ct->proto.tcp.state =
*(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]);
if (tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL-1]) {
struct nf_ct_tcp_flags *attr =
NFA_DATA(tb[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL-1]);
ct->proto.tcp.seen[0].flags &= ~attr->mask;
ct->proto.tcp.seen[0].flags |= attr->flags & attr->mask;
}
if (tb[CTA_PROTOINFO_TCP_FLAGS_REPLY-1]) {
struct nf_ct_tcp_flags *attr =
NFA_DATA(tb[CTA_PROTOINFO_TCP_FLAGS_REPLY-1]);
ct->proto.tcp.seen[1].flags &= ~attr->mask;
ct->proto.tcp.seen[1].flags |= attr->flags & attr->mask;
}
if (tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL-1] &&
tb[CTA_PROTOINFO_TCP_WSCALE_REPLY-1] &&
ct->proto.tcp.seen[0].flags & IP_CT_TCP_FLAG_WINDOW_SCALE &&
ct->proto.tcp.seen[1].flags & IP_CT_TCP_FLAG_WINDOW_SCALE) {
ct->proto.tcp.seen[0].td_scale = *(u_int8_t *)
NFA_DATA(tb[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL-1]);
ct->proto.tcp.seen[1].td_scale = *(u_int8_t *)
NFA_DATA(tb[CTA_PROTOINFO_TCP_WSCALE_REPLY-1]);
}
write_unlock_bh(&tcp_lock);
return 0;