Commit c8e2078c authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso Committed by David S. Miller

[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: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: default avatarPatrick McHardy <kaber@trash.net>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5c8ce7c9
...@@ -30,6 +30,11 @@ enum tcp_conntrack { ...@@ -30,6 +30,11 @@ enum tcp_conntrack {
/* Be liberal in window checking */ /* Be liberal in window checking */
#define IP_CT_TCP_FLAG_BE_LIBERAL 0x08 #define IP_CT_TCP_FLAG_BE_LIBERAL 0x08
struct nf_ct_tcp_flags {
u_int8_t flags;
u_int8_t mask;
};
#ifdef __KERNEL__ #ifdef __KERNEL__
struct ip_ct_tcp_state { struct ip_ct_tcp_state {
......
...@@ -83,6 +83,10 @@ enum ctattr_protoinfo { ...@@ -83,6 +83,10 @@ enum ctattr_protoinfo {
enum ctattr_protoinfo_tcp { enum ctattr_protoinfo_tcp {
CTA_PROTOINFO_TCP_UNSPEC, CTA_PROTOINFO_TCP_UNSPEC,
CTA_PROTOINFO_TCP_STATE, 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 __CTA_PROTOINFO_TCP_MAX
}; };
#define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1) #define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1)
......
...@@ -1101,11 +1101,26 @@ static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa, ...@@ -1101,11 +1101,26 @@ static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
const struct nf_conn *ct) const struct nf_conn *ct)
{ {
struct nfattr *nest_parms; struct nfattr *nest_parms;
struct nf_ct_tcp_flags tmp = {};
read_lock_bh(&tcp_lock); read_lock_bh(&tcp_lock);
nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP); nest_parms = NFA_NEST(skb, CTA_PROTOINFO_TCP);
NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t), NFA_PUT(skb, CTA_PROTOINFO_TCP_STATE, sizeof(u_int8_t),
&ct->proto.tcp.state); &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); read_unlock_bh(&tcp_lock);
NFA_NEST_END(skb, nest_parms); NFA_NEST_END(skb, nest_parms);
...@@ -1119,6 +1134,10 @@ static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa, ...@@ -1119,6 +1134,10 @@ static int tcp_to_nfattr(struct sk_buff *skb, struct nfattr *nfa,
static const size_t cta_min_tcp[CTA_PROTOINFO_TCP_MAX] = { 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) 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) ...@@ -1142,6 +1161,30 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct nf_conn *ct)
write_lock_bh(&tcp_lock); write_lock_bh(&tcp_lock);
ct->proto.tcp.state = ct->proto.tcp.state =
*(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_TCP_STATE-1]); *(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); write_unlock_bh(&tcp_lock);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment