Commit 2c8503f5 authored by Pablo Neira Ayuso's avatar Pablo Neira Ayuso

netfilter: nf_conntrack: pass timeout array to l4->new and l4->packet

This patch defines a new interface for l4 protocol trackers:

unsigned int *(*get_timeouts)(struct net *net);

that is used to return the array of unsigned int that contains
the timeouts that will be applied for this flow. This is passed
to the l4proto->new(...) and l4proto->packet(...) functions to
specify the timeout policy.

This interface allows per-net global timeout configuration
(although only DCCP supports this by now) and it will allow
custom custom timeout configuration by means of follow-up
patches.
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
parent b888341c
...@@ -39,12 +39,13 @@ struct nf_conntrack_l4proto { ...@@ -39,12 +39,13 @@ struct nf_conntrack_l4proto {
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
u_int8_t pf, u_int8_t pf,
unsigned int hooknum); unsigned int hooknum,
unsigned int *timeouts);
/* Called when a new connection for this protocol found; /* Called when a new connection for this protocol found;
* returns TRUE if it's OK. If so, packet() called next. */ * returns TRUE if it's OK. If so, packet() called next. */
bool (*new)(struct nf_conn *ct, const struct sk_buff *skb, bool (*new)(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff); unsigned int dataoff, unsigned int *timeouts);
/* Called when a conntrack entry is destroyed */ /* Called when a conntrack entry is destroyed */
void (*destroy)(struct nf_conn *ct); void (*destroy)(struct nf_conn *ct);
...@@ -60,6 +61,9 @@ struct nf_conntrack_l4proto { ...@@ -60,6 +61,9 @@ struct nf_conntrack_l4proto {
/* Print out the private part of the conntrack. */ /* Print out the private part of the conntrack. */
int (*print_conntrack)(struct seq_file *s, struct nf_conn *); int (*print_conntrack)(struct seq_file *s, struct nf_conn *);
/* Return the array of timeouts for this protocol. */
unsigned int *(*get_timeouts)(struct net *net);
/* convert protoinfo to nfnetink attributes */ /* convert protoinfo to nfnetink attributes */
int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla, int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla,
struct nf_conn *ct); struct nf_conn *ct);
......
...@@ -75,25 +75,31 @@ static int icmp_print_tuple(struct seq_file *s, ...@@ -75,25 +75,31 @@ static int icmp_print_tuple(struct seq_file *s,
ntohs(tuple->src.u.icmp.id)); ntohs(tuple->src.u.icmp.id));
} }
static unsigned int *icmp_get_timeouts(struct net *net)
{
return &nf_ct_icmp_timeout;
}
/* Returns verdict for packet, or -1 for invalid. */ /* Returns verdict for packet, or -1 for invalid. */
static int icmp_packet(struct nf_conn *ct, static int icmp_packet(struct nf_conn *ct,
const struct sk_buff *skb, const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
u_int8_t pf, u_int8_t pf,
unsigned int hooknum) unsigned int hooknum,
unsigned int *timeout)
{ {
/* Do not immediately delete the connection after the first /* Do not immediately delete the connection after the first
successful reply to avoid excessive conntrackd traffic successful reply to avoid excessive conntrackd traffic
and also to handle correctly ICMP echo reply duplicates. */ and also to handle correctly ICMP echo reply duplicates. */
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmp_timeout); nf_ct_refresh_acct(ct, ctinfo, skb, *timeout);
return NF_ACCEPT; return NF_ACCEPT;
} }
/* Called when a new connection for this protocol found. */ /* Called when a new connection for this protocol found. */
static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb, static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff) unsigned int dataoff, unsigned int *timeouts)
{ {
static const u_int8_t valid_new[] = { static const u_int8_t valid_new[] = {
[ICMP_ECHO] = 1, [ICMP_ECHO] = 1,
...@@ -298,6 +304,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = ...@@ -298,6 +304,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly =
.invert_tuple = icmp_invert_tuple, .invert_tuple = icmp_invert_tuple,
.print_tuple = icmp_print_tuple, .print_tuple = icmp_print_tuple,
.packet = icmp_packet, .packet = icmp_packet,
.get_timeouts = icmp_get_timeouts,
.new = icmp_new, .new = icmp_new,
.error = icmp_error, .error = icmp_error,
.destroy = NULL, .destroy = NULL,
......
...@@ -88,25 +88,31 @@ static int icmpv6_print_tuple(struct seq_file *s, ...@@ -88,25 +88,31 @@ static int icmpv6_print_tuple(struct seq_file *s,
ntohs(tuple->src.u.icmp.id)); ntohs(tuple->src.u.icmp.id));
} }
static unsigned int *icmpv6_get_timeouts(struct net *net)
{
return &nf_ct_icmpv6_timeout;
}
/* Returns verdict for packet, or -1 for invalid. */ /* Returns verdict for packet, or -1 for invalid. */
static int icmpv6_packet(struct nf_conn *ct, static int icmpv6_packet(struct nf_conn *ct,
const struct sk_buff *skb, const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
u_int8_t pf, u_int8_t pf,
unsigned int hooknum) unsigned int hooknum,
unsigned int *timeout)
{ {
/* Do not immediately delete the connection after the first /* Do not immediately delete the connection after the first
successful reply to avoid excessive conntrackd traffic successful reply to avoid excessive conntrackd traffic
and also to handle correctly ICMP echo reply duplicates. */ and also to handle correctly ICMP echo reply duplicates. */
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_icmpv6_timeout); nf_ct_refresh_acct(ct, ctinfo, skb, *timeout);
return NF_ACCEPT; return NF_ACCEPT;
} }
/* Called when a new connection for this protocol found. */ /* Called when a new connection for this protocol found. */
static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb, static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff) unsigned int dataoff, unsigned int *timeouts)
{ {
static const u_int8_t valid_new[] = { static const u_int8_t valid_new[] = {
[ICMPV6_ECHO_REQUEST - 128] = 1, [ICMPV6_ECHO_REQUEST - 128] = 1,
...@@ -293,6 +299,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly = ...@@ -293,6 +299,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 __read_mostly =
.invert_tuple = icmpv6_invert_tuple, .invert_tuple = icmpv6_invert_tuple,
.print_tuple = icmpv6_print_tuple, .print_tuple = icmpv6_print_tuple,
.packet = icmpv6_packet, .packet = icmpv6_packet,
.get_timeouts = icmpv6_get_timeouts,
.new = icmpv6_new, .new = icmpv6_new,
.error = icmpv6_error, .error = icmpv6_error,
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
......
...@@ -763,7 +763,8 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, ...@@ -763,7 +763,8 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
struct nf_conntrack_l3proto *l3proto, struct nf_conntrack_l3proto *l3proto,
struct nf_conntrack_l4proto *l4proto, struct nf_conntrack_l4proto *l4proto,
struct sk_buff *skb, struct sk_buff *skb,
unsigned int dataoff, u32 hash) unsigned int dataoff, u32 hash,
unsigned int *timeouts)
{ {
struct nf_conn *ct; struct nf_conn *ct;
struct nf_conn_help *help; struct nf_conn_help *help;
...@@ -782,7 +783,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, ...@@ -782,7 +783,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,
if (IS_ERR(ct)) if (IS_ERR(ct))
return (struct nf_conntrack_tuple_hash *)ct; return (struct nf_conntrack_tuple_hash *)ct;
if (!l4proto->new(ct, skb, dataoff)) { if (!l4proto->new(ct, skb, dataoff, timeouts)) {
nf_conntrack_free(ct); nf_conntrack_free(ct);
pr_debug("init conntrack: can't track with proto module\n"); pr_debug("init conntrack: can't track with proto module\n");
return NULL; return NULL;
...@@ -848,7 +849,8 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, ...@@ -848,7 +849,8 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
struct nf_conntrack_l3proto *l3proto, struct nf_conntrack_l3proto *l3proto,
struct nf_conntrack_l4proto *l4proto, struct nf_conntrack_l4proto *l4proto,
int *set_reply, int *set_reply,
enum ip_conntrack_info *ctinfo) enum ip_conntrack_info *ctinfo,
unsigned int *timeouts)
{ {
struct nf_conntrack_tuple tuple; struct nf_conntrack_tuple tuple;
struct nf_conntrack_tuple_hash *h; struct nf_conntrack_tuple_hash *h;
...@@ -868,7 +870,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl, ...@@ -868,7 +870,7 @@ resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
h = __nf_conntrack_find_get(net, zone, &tuple, hash); h = __nf_conntrack_find_get(net, zone, &tuple, hash);
if (!h) { if (!h) {
h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto, h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto,
skb, dataoff, hash); skb, dataoff, hash, timeouts);
if (!h) if (!h)
return NULL; return NULL;
if (IS_ERR(h)) if (IS_ERR(h))
...@@ -909,6 +911,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, ...@@ -909,6 +911,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conntrack_l3proto *l3proto; struct nf_conntrack_l3proto *l3proto;
struct nf_conntrack_l4proto *l4proto; struct nf_conntrack_l4proto *l4proto;
unsigned int *timeouts;
unsigned int dataoff; unsigned int dataoff;
u_int8_t protonum; u_int8_t protonum;
int set_reply = 0; int set_reply = 0;
...@@ -955,8 +958,11 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, ...@@ -955,8 +958,11 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
goto out; goto out;
} }
timeouts = l4proto->get_timeouts(net);
ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum, ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum,
l3proto, l4proto, &set_reply, &ctinfo); l3proto, l4proto, &set_reply, &ctinfo,
timeouts);
if (!ct) { if (!ct) {
/* Not valid part of a connection */ /* Not valid part of a connection */
NF_CT_STAT_INC_ATOMIC(net, invalid); NF_CT_STAT_INC_ATOMIC(net, invalid);
...@@ -973,7 +979,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, ...@@ -973,7 +979,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
NF_CT_ASSERT(skb->nfct); NF_CT_ASSERT(skb->nfct);
ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum); ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum, timeouts);
if (ret <= 0) { if (ret <= 0) {
/* Invalid: inverse of the return code tells /* Invalid: inverse of the return code tells
* the netfilter core what to do */ * the netfilter core what to do */
......
...@@ -423,7 +423,7 @@ static bool dccp_invert_tuple(struct nf_conntrack_tuple *inv, ...@@ -423,7 +423,7 @@ static bool dccp_invert_tuple(struct nf_conntrack_tuple *inv,
} }
static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb, static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff) unsigned int dataoff, unsigned int *timeouts)
{ {
struct net *net = nf_ct_net(ct); struct net *net = nf_ct_net(ct);
struct dccp_net *dn; struct dccp_net *dn;
...@@ -472,12 +472,17 @@ static u64 dccp_ack_seq(const struct dccp_hdr *dh) ...@@ -472,12 +472,17 @@ static u64 dccp_ack_seq(const struct dccp_hdr *dh)
ntohl(dhack->dccph_ack_nr_low); ntohl(dhack->dccph_ack_nr_low);
} }
static unsigned int *dccp_get_timeouts(struct net *net)
{
return dccp_pernet(net)->dccp_timeout;
}
static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff, enum ip_conntrack_info ctinfo, unsigned int dataoff, enum ip_conntrack_info ctinfo,
u_int8_t pf, unsigned int hooknum) u_int8_t pf, unsigned int hooknum,
unsigned int *timeouts)
{ {
struct net *net = nf_ct_net(ct); struct net *net = nf_ct_net(ct);
struct dccp_net *dn;
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
struct dccp_hdr _dh, *dh; struct dccp_hdr _dh, *dh;
u_int8_t type, old_state, new_state; u_int8_t type, old_state, new_state;
...@@ -559,8 +564,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, ...@@ -559,8 +564,7 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
if (new_state != old_state) if (new_state != old_state)
nf_conntrack_event_cache(IPCT_PROTOINFO, ct); nf_conntrack_event_cache(IPCT_PROTOINFO, ct);
dn = dccp_pernet(net); nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]);
nf_ct_refresh_acct(ct, ctinfo, skb, dn->dccp_timeout[new_state]);
return NF_ACCEPT; return NF_ACCEPT;
} }
...@@ -767,6 +771,7 @@ static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = { ...@@ -767,6 +771,7 @@ static struct nf_conntrack_l4proto dccp_proto4 __read_mostly = {
.invert_tuple = dccp_invert_tuple, .invert_tuple = dccp_invert_tuple,
.new = dccp_new, .new = dccp_new,
.packet = dccp_packet, .packet = dccp_packet,
.get_timeouts = dccp_get_timeouts,
.error = dccp_error, .error = dccp_error,
.print_tuple = dccp_print_tuple, .print_tuple = dccp_print_tuple,
.print_conntrack = dccp_print_conntrack, .print_conntrack = dccp_print_conntrack,
...@@ -789,6 +794,7 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = { ...@@ -789,6 +794,7 @@ static struct nf_conntrack_l4proto dccp_proto6 __read_mostly = {
.invert_tuple = dccp_invert_tuple, .invert_tuple = dccp_invert_tuple,
.new = dccp_new, .new = dccp_new,
.packet = dccp_packet, .packet = dccp_packet,
.get_timeouts = dccp_get_timeouts,
.error = dccp_error, .error = dccp_error,
.print_tuple = dccp_print_tuple, .print_tuple = dccp_print_tuple,
.print_conntrack = dccp_print_conntrack, .print_conntrack = dccp_print_conntrack,
......
...@@ -40,21 +40,27 @@ static int generic_print_tuple(struct seq_file *s, ...@@ -40,21 +40,27 @@ static int generic_print_tuple(struct seq_file *s,
return 0; return 0;
} }
static unsigned int *generic_get_timeouts(struct net *net)
{
return &nf_ct_generic_timeout;
}
/* Returns verdict for packet, or -1 for invalid. */ /* Returns verdict for packet, or -1 for invalid. */
static int packet(struct nf_conn *ct, static int generic_packet(struct nf_conn *ct,
const struct sk_buff *skb, const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
u_int8_t pf, u_int8_t pf,
unsigned int hooknum) unsigned int hooknum,
unsigned int *timeout)
{ {
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_generic_timeout); nf_ct_refresh_acct(ct, ctinfo, skb, *timeout);
return NF_ACCEPT; return NF_ACCEPT;
} }
/* Called when a new connection for this protocol found. */ /* Called when a new connection for this protocol found. */
static bool new(struct nf_conn *ct, const struct sk_buff *skb, static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff) unsigned int dataoff, unsigned int *timeouts)
{ {
return true; return true;
} }
...@@ -93,8 +99,9 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly = ...@@ -93,8 +99,9 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_generic __read_mostly =
.pkt_to_tuple = generic_pkt_to_tuple, .pkt_to_tuple = generic_pkt_to_tuple,
.invert_tuple = generic_invert_tuple, .invert_tuple = generic_invert_tuple,
.print_tuple = generic_print_tuple, .print_tuple = generic_print_tuple,
.packet = packet, .packet = generic_packet,
.new = new, .get_timeouts = generic_get_timeouts,
.new = generic_new,
#ifdef CONFIG_SYSCTL #ifdef CONFIG_SYSCTL
.ctl_table_header = &generic_sysctl_header, .ctl_table_header = &generic_sysctl_header,
.ctl_table = generic_sysctl_table, .ctl_table = generic_sysctl_table,
......
...@@ -235,13 +235,19 @@ static int gre_print_conntrack(struct seq_file *s, struct nf_conn *ct) ...@@ -235,13 +235,19 @@ static int gre_print_conntrack(struct seq_file *s, struct nf_conn *ct)
(ct->proto.gre.stream_timeout / HZ)); (ct->proto.gre.stream_timeout / HZ));
} }
static unsigned int *gre_get_timeouts(struct net *net)
{
return gre_timeouts;
}
/* Returns verdict for packet, and may modify conntrack */ /* Returns verdict for packet, and may modify conntrack */
static int gre_packet(struct nf_conn *ct, static int gre_packet(struct nf_conn *ct,
const struct sk_buff *skb, const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
u_int8_t pf, u_int8_t pf,
unsigned int hooknum) unsigned int hooknum,
unsigned int *timeouts)
{ {
/* If we've seen traffic both ways, this is a GRE connection. /* If we've seen traffic both ways, this is a GRE connection.
* Extend timeout. */ * Extend timeout. */
...@@ -260,15 +266,15 @@ static int gre_packet(struct nf_conn *ct, ...@@ -260,15 +266,15 @@ static int gre_packet(struct nf_conn *ct,
/* Called when a new connection for this protocol found. */ /* Called when a new connection for this protocol found. */
static bool gre_new(struct nf_conn *ct, const struct sk_buff *skb, static bool gre_new(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff) unsigned int dataoff, unsigned int *timeouts)
{ {
pr_debug(": "); pr_debug(": ");
nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); nf_ct_dump_tuple(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
/* initialize to sane value. Ideally a conntrack helper /* initialize to sane value. Ideally a conntrack helper
* (e.g. in case of pptp) is increasing them */ * (e.g. in case of pptp) is increasing them */
ct->proto.gre.stream_timeout = gre_timeouts[GRE_CT_REPLIED]; ct->proto.gre.stream_timeout = timeouts[GRE_CT_REPLIED];
ct->proto.gre.timeout = gre_timeouts[GRE_CT_UNREPLIED]; ct->proto.gre.timeout = timeouts[GRE_CT_UNREPLIED];
return true; return true;
} }
...@@ -295,6 +301,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = { ...@@ -295,6 +301,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 __read_mostly = {
.invert_tuple = gre_invert_tuple, .invert_tuple = gre_invert_tuple,
.print_tuple = gre_print_tuple, .print_tuple = gre_print_tuple,
.print_conntrack = gre_print_conntrack, .print_conntrack = gre_print_conntrack,
.get_timeouts = gre_get_timeouts,
.packet = gre_packet, .packet = gre_packet,
.new = gre_new, .new = gre_new,
.destroy = gre_destroy, .destroy = gre_destroy,
......
...@@ -279,13 +279,19 @@ static int sctp_new_state(enum ip_conntrack_dir dir, ...@@ -279,13 +279,19 @@ static int sctp_new_state(enum ip_conntrack_dir dir,
return sctp_conntracks[dir][i][cur_state]; return sctp_conntracks[dir][i][cur_state];
} }
static unsigned int *sctp_get_timeouts(struct net *net)
{
return sctp_timeouts;
}
/* Returns verdict for packet, or -NF_ACCEPT for invalid. */ /* Returns verdict for packet, or -NF_ACCEPT for invalid. */
static int sctp_packet(struct nf_conn *ct, static int sctp_packet(struct nf_conn *ct,
const struct sk_buff *skb, const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
u_int8_t pf, u_int8_t pf,
unsigned int hooknum) unsigned int hooknum,
unsigned int *timeouts)
{ {
enum sctp_conntrack new_state, old_state; enum sctp_conntrack new_state, old_state;
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
...@@ -370,7 +376,7 @@ static int sctp_packet(struct nf_conn *ct, ...@@ -370,7 +376,7 @@ static int sctp_packet(struct nf_conn *ct,
} }
spin_unlock_bh(&ct->lock); spin_unlock_bh(&ct->lock);
nf_ct_refresh_acct(ct, ctinfo, skb, sctp_timeouts[new_state]); nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]);
if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED && if (old_state == SCTP_CONNTRACK_COOKIE_ECHOED &&
dir == IP_CT_DIR_REPLY && dir == IP_CT_DIR_REPLY &&
...@@ -390,7 +396,7 @@ static int sctp_packet(struct nf_conn *ct, ...@@ -390,7 +396,7 @@ static int sctp_packet(struct nf_conn *ct,
/* Called when a new connection for this protocol found. */ /* Called when a new connection for this protocol found. */
static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb, static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff) unsigned int dataoff, unsigned int *timeouts)
{ {
enum sctp_conntrack new_state; enum sctp_conntrack new_state;
const struct sctphdr *sh; const struct sctphdr *sh;
...@@ -664,6 +670,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = { ...@@ -664,6 +670,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 __read_mostly = {
.print_tuple = sctp_print_tuple, .print_tuple = sctp_print_tuple,
.print_conntrack = sctp_print_conntrack, .print_conntrack = sctp_print_conntrack,
.packet = sctp_packet, .packet = sctp_packet,
.get_timeouts = sctp_get_timeouts,
.new = sctp_new, .new = sctp_new,
.me = THIS_MODULE, .me = THIS_MODULE,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
...@@ -694,6 +701,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = { ...@@ -694,6 +701,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 __read_mostly = {
.print_tuple = sctp_print_tuple, .print_tuple = sctp_print_tuple,
.print_conntrack = sctp_print_conntrack, .print_conntrack = sctp_print_conntrack,
.packet = sctp_packet, .packet = sctp_packet,
.get_timeouts = sctp_get_timeouts,
.new = sctp_new, .new = sctp_new,
.me = THIS_MODULE, .me = THIS_MODULE,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
......
...@@ -813,13 +813,19 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl, ...@@ -813,13 +813,19 @@ static int tcp_error(struct net *net, struct nf_conn *tmpl,
return NF_ACCEPT; return NF_ACCEPT;
} }
static unsigned int *tcp_get_timeouts(struct net *net)
{
return tcp_timeouts;
}
/* Returns verdict for packet, or -1 for invalid. */ /* Returns verdict for packet, or -1 for invalid. */
static int tcp_packet(struct nf_conn *ct, static int tcp_packet(struct nf_conn *ct,
const struct sk_buff *skb, const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
u_int8_t pf, u_int8_t pf,
unsigned int hooknum) unsigned int hooknum,
unsigned int *timeouts)
{ {
struct net *net = nf_ct_net(ct); struct net *net = nf_ct_net(ct);
struct nf_conntrack_tuple *tuple; struct nf_conntrack_tuple *tuple;
...@@ -1014,14 +1020,14 @@ static int tcp_packet(struct nf_conn *ct, ...@@ -1014,14 +1020,14 @@ static int tcp_packet(struct nf_conn *ct,
ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT; ct->proto.tcp.seen[dir].flags |= IP_CT_TCP_FLAG_CLOSE_INIT;
if (ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans && if (ct->proto.tcp.retrans >= nf_ct_tcp_max_retrans &&
tcp_timeouts[new_state] > tcp_timeouts[TCP_CONNTRACK_RETRANS]) timeouts[new_state] > timeouts[TCP_CONNTRACK_RETRANS])
timeout = tcp_timeouts[TCP_CONNTRACK_RETRANS]; timeout = timeouts[TCP_CONNTRACK_RETRANS];
else if ((ct->proto.tcp.seen[0].flags | ct->proto.tcp.seen[1].flags) & else if ((ct->proto.tcp.seen[0].flags | ct->proto.tcp.seen[1].flags) &
IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED && IP_CT_TCP_FLAG_DATA_UNACKNOWLEDGED &&
tcp_timeouts[new_state] > tcp_timeouts[TCP_CONNTRACK_UNACK]) timeouts[new_state] > timeouts[TCP_CONNTRACK_UNACK])
timeout = tcp_timeouts[TCP_CONNTRACK_UNACK]; timeout = timeouts[TCP_CONNTRACK_UNACK];
else else
timeout = tcp_timeouts[new_state]; timeout = timeouts[new_state];
spin_unlock_bh(&ct->lock); spin_unlock_bh(&ct->lock);
if (new_state != old_state) if (new_state != old_state)
...@@ -1053,7 +1059,7 @@ static int tcp_packet(struct nf_conn *ct, ...@@ -1053,7 +1059,7 @@ static int tcp_packet(struct nf_conn *ct,
/* Called when a new connection for this protocol found. */ /* Called when a new connection for this protocol found. */
static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb, static bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff) unsigned int dataoff, unsigned int *timeouts)
{ {
enum tcp_conntrack new_state; enum tcp_conntrack new_state;
const struct tcphdr *th; const struct tcphdr *th;
...@@ -1444,6 +1450,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly = ...@@ -1444,6 +1450,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4 __read_mostly =
.print_tuple = tcp_print_tuple, .print_tuple = tcp_print_tuple,
.print_conntrack = tcp_print_conntrack, .print_conntrack = tcp_print_conntrack,
.packet = tcp_packet, .packet = tcp_packet,
.get_timeouts = tcp_get_timeouts,
.new = tcp_new, .new = tcp_new,
.error = tcp_error, .error = tcp_error,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
...@@ -1476,6 +1483,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly = ...@@ -1476,6 +1483,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6 __read_mostly =
.print_tuple = tcp_print_tuple, .print_tuple = tcp_print_tuple,
.print_conntrack = tcp_print_conntrack, .print_conntrack = tcp_print_conntrack,
.packet = tcp_packet, .packet = tcp_packet,
.get_timeouts = tcp_get_timeouts,
.new = tcp_new, .new = tcp_new,
.error = tcp_error, .error = tcp_error,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
......
...@@ -71,32 +71,38 @@ static int udp_print_tuple(struct seq_file *s, ...@@ -71,32 +71,38 @@ static int udp_print_tuple(struct seq_file *s,
ntohs(tuple->dst.u.udp.port)); ntohs(tuple->dst.u.udp.port));
} }
static unsigned int *udp_get_timeouts(struct net *net)
{
return udp_timeouts;
}
/* Returns verdict for packet, and may modify conntracktype */ /* Returns verdict for packet, and may modify conntracktype */
static int udp_packet(struct nf_conn *ct, static int udp_packet(struct nf_conn *ct,
const struct sk_buff *skb, const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
u_int8_t pf, u_int8_t pf,
unsigned int hooknum) unsigned int hooknum,
unsigned int *timeouts)
{ {
/* If we've seen traffic both ways, this is some kind of UDP /* If we've seen traffic both ways, this is some kind of UDP
stream. Extend timeout. */ stream. Extend timeout. */
if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_refresh_acct(ct, ctinfo, skb,
udp_timeouts[UDP_CT_REPLIED]); timeouts[UDP_CT_REPLIED]);
/* Also, more likely to be important, and not a probe */ /* Also, more likely to be important, and not a probe */
if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
nf_conntrack_event_cache(IPCT_ASSURED, ct); nf_conntrack_event_cache(IPCT_ASSURED, ct);
} else { } else {
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_refresh_acct(ct, ctinfo, skb,
udp_timeouts[UDP_CT_UNREPLIED]); timeouts[UDP_CT_UNREPLIED]);
} }
return NF_ACCEPT; return NF_ACCEPT;
} }
/* Called when a new connection for this protocol found. */ /* Called when a new connection for this protocol found. */
static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb, static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff) unsigned int dataoff, unsigned int *timeouts)
{ {
return true; return true;
} }
...@@ -196,6 +202,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly = ...@@ -196,6 +202,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4 __read_mostly =
.invert_tuple = udp_invert_tuple, .invert_tuple = udp_invert_tuple,
.print_tuple = udp_print_tuple, .print_tuple = udp_print_tuple,
.packet = udp_packet, .packet = udp_packet,
.get_timeouts = udp_get_timeouts,
.new = udp_new, .new = udp_new,
.error = udp_error, .error = udp_error,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
...@@ -224,6 +231,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly = ...@@ -224,6 +231,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6 __read_mostly =
.invert_tuple = udp_invert_tuple, .invert_tuple = udp_invert_tuple,
.print_tuple = udp_print_tuple, .print_tuple = udp_print_tuple,
.packet = udp_packet, .packet = udp_packet,
.get_timeouts = udp_get_timeouts,
.new = udp_new, .new = udp_new,
.error = udp_error, .error = udp_error,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
......
...@@ -68,32 +68,38 @@ static int udplite_print_tuple(struct seq_file *s, ...@@ -68,32 +68,38 @@ static int udplite_print_tuple(struct seq_file *s,
ntohs(tuple->dst.u.udp.port)); ntohs(tuple->dst.u.udp.port));
} }
static unsigned int *udplite_get_timeouts(struct net *net)
{
return udplite_timeouts;
}
/* Returns verdict for packet, and may modify conntracktype */ /* Returns verdict for packet, and may modify conntracktype */
static int udplite_packet(struct nf_conn *ct, static int udplite_packet(struct nf_conn *ct,
const struct sk_buff *skb, const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
u_int8_t pf, u_int8_t pf,
unsigned int hooknum) unsigned int hooknum,
unsigned int *timeouts)
{ {
/* If we've seen traffic both ways, this is some kind of UDP /* If we've seen traffic both ways, this is some kind of UDP
stream. Extend timeout. */ stream. Extend timeout. */
if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) { if (test_bit(IPS_SEEN_REPLY_BIT, &ct->status)) {
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_refresh_acct(ct, ctinfo, skb,
udplite_timeouts[UDPLITE_CT_REPLIED]); timeouts[UDPLITE_CT_REPLIED]);
/* Also, more likely to be important, and not a probe */ /* Also, more likely to be important, and not a probe */
if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
nf_conntrack_event_cache(IPCT_ASSURED, ct); nf_conntrack_event_cache(IPCT_ASSURED, ct);
} else { } else {
nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_refresh_acct(ct, ctinfo, skb,
udplite_timeouts[UDPLITE_CT_UNREPLIED]); timeouts[UDPLITE_CT_UNREPLIED]);
} }
return NF_ACCEPT; return NF_ACCEPT;
} }
/* Called when a new connection for this protocol found. */ /* Called when a new connection for this protocol found. */
static bool udplite_new(struct nf_conn *ct, const struct sk_buff *skb, static bool udplite_new(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff) unsigned int dataoff, unsigned int *timeouts)
{ {
return true; return true;
} }
...@@ -181,6 +187,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly = ...@@ -181,6 +187,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4 __read_mostly =
.invert_tuple = udplite_invert_tuple, .invert_tuple = udplite_invert_tuple,
.print_tuple = udplite_print_tuple, .print_tuple = udplite_print_tuple,
.packet = udplite_packet, .packet = udplite_packet,
.get_timeouts = udplite_get_timeouts,
.new = udplite_new, .new = udplite_new,
.error = udplite_error, .error = udplite_error,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
...@@ -205,6 +212,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly = ...@@ -205,6 +212,7 @@ static struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6 __read_mostly =
.invert_tuple = udplite_invert_tuple, .invert_tuple = udplite_invert_tuple,
.print_tuple = udplite_print_tuple, .print_tuple = udplite_print_tuple,
.packet = udplite_packet, .packet = udplite_packet,
.get_timeouts = udplite_get_timeouts,
.new = udplite_new, .new = udplite_new,
.error = udplite_error, .error = udplite_error,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
......
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