Commit 99d20a46 authored by David S. Miller's avatar David S. Miller

Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next

Pablo Neira Ayuso says:

====================
Netfilter/IPVS updates for net-next

The following patchset contains Netfilter/IPVS updates for your net-next
tree:

1) No need to set ttl from reject action for the bridge family, from
   Taehee Yoo.

2) Use a fixed timeout for flow that are passed up from the flowtable
   to conntrack, from Florian Westphal.

3) More preparation patches for tproxy support for nf_tables, from Mate
   Eckl.

4) Remove unnecessary indirection in core IPv6 checksum function, from
   Florian Westphal.

5) Use nf_ct_get_tuplepr() from openvswitch, instead of opencoding it.
   From Florian Westphal.

6) socket match now selects socket infrastructure, instead of depending
   on it. From Mate Eckl.

7) Patch series to simplify conntrack tuple building/parsing from packet
   path and ctnetlink, from Florian Westphal.

8) Fetch timeout policy from protocol helpers, instead of doing it from
   core, from Florian Westphal.

9) Merge IPv4 and IPv6 protocol trackers into conntrack core, from
   Florian Westphal.

10) Depend on CONFIG_NF_TABLES_IPV6 and CONFIG_IP6_NF_IPTABLES
    respectively, instead of IPV6. Patch from Mate Eckl.

11) Add specific function for garbage collection in conncount,
    from Yi-Hung Wei.

12) Catch number of elements in the connlimit list, from Yi-Hung Wei.

13) Move locking to nf_conncount, from Yi-Hung Wei.

14) Series of patches to add lockless tree traversal in nf_conncount,
    from Yi-Hung Wei.

15) Resolve clash in matching conntracks when race happens, from
    Martynas Pumputis.

16) If connection entry times out, remove template entry from the
    ip_vs_conn_tab table to improve behaviour under flood, from
    Julian Anastasov.

17) Remove useless parameter from nf_ct_helper_ext_add(), from Gao feng.

18) Call abort from 2-phase commit protocol before requesting modules,
    make sure this is done under the mutex, from Florian Westphal.

19) Grab module reference when starting transaction, also from Florian.

20) Dynamically allocate expression info array for pre-parsing, from
    Florian.

21) Add per netns mutex for nf_tables, from Florian Westphal.

22) A couple of patches to simplify and refactor nf_osf code to prepare
    for nft_osf support.

23) Break evaluation on missing socket, from Mate Eckl.

24) Allow to match socket mark from nft_socket, from Mate Eckl.

25) Remove dependency on nf_defrag_ipv6, now that IPv6 tracker is
    built-in into nf_conntrack. From Florian Westphal.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c4c5551d 24c458c4
...@@ -29,6 +29,7 @@ struct nfnetlink_subsystem { ...@@ -29,6 +29,7 @@ struct nfnetlink_subsystem {
__u8 subsys_id; /* nfnetlink subsystem ID */ __u8 subsys_id; /* nfnetlink subsystem ID */
__u8 cb_count; /* number of callbacks */ __u8 cb_count; /* number of callbacks */
const struct nfnl_callback *cb; /* callback for individual types */ const struct nfnl_callback *cb; /* callback for individual types */
struct module *owner;
int (*commit)(struct net *net, struct sk_buff *skb); int (*commit)(struct net *net, struct sk_buff *skb);
int (*abort)(struct net *net, struct sk_buff *skb); int (*abort)(struct net *net, struct sk_buff *skb);
void (*cleanup)(struct net *net); void (*cleanup)(struct net *net);
......
...@@ -23,9 +23,6 @@ struct nf_queue_entry; ...@@ -23,9 +23,6 @@ struct nf_queue_entry;
#ifdef CONFIG_INET #ifdef CONFIG_INET
__sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol); unsigned int dataoff, u_int8_t protocol);
__sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, unsigned int len,
u_int8_t protocol);
int nf_ip_route(struct net *net, struct dst_entry **dst, struct flowi *fl, int nf_ip_route(struct net *net, struct dst_entry **dst, struct flowi *fl,
bool strict); bool strict);
int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry); int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry);
...@@ -35,14 +32,6 @@ static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, ...@@ -35,14 +32,6 @@ static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
{ {
return 0; return 0;
} }
static inline __sum16 nf_ip_checksum_partial(struct sk_buff *skb,
unsigned int hook,
unsigned int dataoff,
unsigned int len,
u_int8_t protocol)
{
return 0;
}
static inline int nf_ip_route(struct net *net, struct dst_entry **dst, static inline int nf_ip_route(struct net *net, struct dst_entry **dst,
struct flowi *fl, bool strict) struct flowi *fl, bool strict)
{ {
......
...@@ -30,11 +30,6 @@ struct nf_ipv6_ops { ...@@ -30,11 +30,6 @@ struct nf_ipv6_ops {
void (*route_input)(struct sk_buff *skb); void (*route_input)(struct sk_buff *skb);
int (*fragment)(struct net *net, struct sock *sk, struct sk_buff *skb, int (*fragment)(struct net *net, struct sock *sk, struct sk_buff *skb,
int (*output)(struct net *, struct sock *, struct sk_buff *)); int (*output)(struct net *, struct sock *, struct sk_buff *));
__sum16 (*checksum)(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol);
__sum16 (*checksum_partial)(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, unsigned int len,
u_int8_t protocol);
int (*route)(struct net *net, struct dst_entry **dst, struct flowi *fl, int (*route)(struct net *net, struct dst_entry **dst, struct flowi *fl,
bool strict); bool strict);
int (*reroute)(struct sk_buff *skb, const struct nf_queue_entry *entry); int (*reroute)(struct sk_buff *skb, const struct nf_queue_entry *entry);
......
...@@ -335,6 +335,11 @@ enum ip_vs_sctp_states { ...@@ -335,6 +335,11 @@ enum ip_vs_sctp_states {
IP_VS_SCTP_S_LAST IP_VS_SCTP_S_LAST
}; };
/* Connection templates use bits from state */
#define IP_VS_CTPL_S_NONE 0x0000
#define IP_VS_CTPL_S_ASSURED 0x0001
#define IP_VS_CTPL_S_LAST 0x0002
/* Delta sequence info structure /* Delta sequence info structure
* Each ip_vs_conn has 2 (output AND input seq. changes). * Each ip_vs_conn has 2 (output AND input seq. changes).
* Only used in the VS/NAT. * Only used in the VS/NAT.
...@@ -1221,7 +1226,7 @@ struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af, ...@@ -1221,7 +1226,7 @@ struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af,
struct ip_vs_dest *dest, __u32 fwmark); struct ip_vs_dest *dest, __u32 fwmark);
void ip_vs_conn_expire_now(struct ip_vs_conn *cp); void ip_vs_conn_expire_now(struct ip_vs_conn *cp);
const char *ip_vs_state_name(__u16 proto, int state); const char *ip_vs_state_name(const struct ip_vs_conn *cp);
void ip_vs_tcp_conn_listen(struct ip_vs_conn *cp); void ip_vs_tcp_conn_listen(struct ip_vs_conn *cp);
int ip_vs_check_template(struct ip_vs_conn *ct, struct ip_vs_dest *cdest); int ip_vs_check_template(struct ip_vs_conn *ct, struct ip_vs_dest *cdest);
...@@ -1289,6 +1294,17 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp) ...@@ -1289,6 +1294,17 @@ ip_vs_control_add(struct ip_vs_conn *cp, struct ip_vs_conn *ctl_cp)
atomic_inc(&ctl_cp->n_control); atomic_inc(&ctl_cp->n_control);
} }
/* Mark our template as assured */
static inline void
ip_vs_control_assure_ct(struct ip_vs_conn *cp)
{
struct ip_vs_conn *ct = cp->control;
if (ct && !(ct->state & IP_VS_CTPL_S_ASSURED) &&
(ct->flags & IP_VS_CONN_F_TEMPLATE))
ct->state |= IP_VS_CTPL_S_ASSURED;
}
/* IPVS netns init & cleanup functions */ /* IPVS netns init & cleanup functions */
int ip_vs_estimator_net_init(struct netns_ipvs *ipvs); int ip_vs_estimator_net_init(struct netns_ipvs *ipvs);
int ip_vs_control_net_init(struct netns_ipvs *ipvs); int ip_vs_control_net_init(struct netns_ipvs *ipvs);
......
...@@ -574,34 +574,6 @@ static inline bool ipv6_prefix_equal(const struct in6_addr *addr1, ...@@ -574,34 +574,6 @@ static inline bool ipv6_prefix_equal(const struct in6_addr *addr1,
} }
#endif #endif
struct inet_frag_queue;
enum ip6_defrag_users {
IP6_DEFRAG_LOCAL_DELIVER,
IP6_DEFRAG_CONNTRACK_IN,
__IP6_DEFRAG_CONNTRACK_IN = IP6_DEFRAG_CONNTRACK_IN + USHRT_MAX,
IP6_DEFRAG_CONNTRACK_OUT,
__IP6_DEFRAG_CONNTRACK_OUT = IP6_DEFRAG_CONNTRACK_OUT + USHRT_MAX,
IP6_DEFRAG_CONNTRACK_BRIDGE_IN,
__IP6_DEFRAG_CONNTRACK_BRIDGE_IN = IP6_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX,
};
void ip6_frag_init(struct inet_frag_queue *q, const void *a);
extern const struct rhashtable_params ip6_rhash_params;
/*
* Equivalent of ipv4 struct ip
*/
struct frag_queue {
struct inet_frag_queue q;
int iif;
__u16 nhoffset;
u8 ecn;
};
void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq);
static inline bool ipv6_addr_any(const struct in6_addr *a) static inline bool ipv6_addr_any(const struct in6_addr *a)
{ {
#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && BITS_PER_LONG == 64
......
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _IPV6_FRAG_H
#define _IPV6_FRAG_H
#include <linux/kernel.h>
#include <net/addrconf.h>
#include <net/ipv6.h>
#include <net/inet_frag.h>
enum ip6_defrag_users {
IP6_DEFRAG_LOCAL_DELIVER,
IP6_DEFRAG_CONNTRACK_IN,
__IP6_DEFRAG_CONNTRACK_IN = IP6_DEFRAG_CONNTRACK_IN + USHRT_MAX,
IP6_DEFRAG_CONNTRACK_OUT,
__IP6_DEFRAG_CONNTRACK_OUT = IP6_DEFRAG_CONNTRACK_OUT + USHRT_MAX,
IP6_DEFRAG_CONNTRACK_BRIDGE_IN,
__IP6_DEFRAG_CONNTRACK_BRIDGE_IN = IP6_DEFRAG_CONNTRACK_BRIDGE_IN + USHRT_MAX,
};
/*
* Equivalent of ipv4 struct ip
*/
struct frag_queue {
struct inet_frag_queue q;
int iif;
__u16 nhoffset;
u8 ecn;
};
#if IS_ENABLED(CONFIG_IPV6)
static inline void ip6frag_init(struct inet_frag_queue *q, const void *a)
{
struct frag_queue *fq = container_of(q, struct frag_queue, q);
const struct frag_v6_compare_key *key = a;
q->key.v6 = *key;
fq->ecn = 0;
}
static inline u32 ip6frag_key_hashfn(const void *data, u32 len, u32 seed)
{
return jhash2(data,
sizeof(struct frag_v6_compare_key) / sizeof(u32), seed);
}
static inline u32 ip6frag_obj_hashfn(const void *data, u32 len, u32 seed)
{
const struct inet_frag_queue *fq = data;
return jhash2((const u32 *)&fq->key.v6,
sizeof(struct frag_v6_compare_key) / sizeof(u32), seed);
}
static inline int
ip6frag_obj_cmpfn(struct rhashtable_compare_arg *arg, const void *ptr)
{
const struct frag_v6_compare_key *key = arg->key;
const struct inet_frag_queue *fq = ptr;
return !!memcmp(&fq->key, key, sizeof(*key));
}
static inline void
ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq)
{
struct net_device *dev = NULL;
struct sk_buff *head;
rcu_read_lock();
spin_lock(&fq->q.lock);
if (fq->q.flags & INET_FRAG_COMPLETE)
goto out;
inet_frag_kill(&fq->q);
dev = dev_get_by_index_rcu(net, fq->iif);
if (!dev)
goto out;
__IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS);
__IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT);
/* Don't send error if the first segment did not arrive. */
head = fq->q.fragments;
if (!(fq->q.flags & INET_FRAG_FIRST_IN) || !head)
goto out;
head->dev = dev;
skb_get(head);
spin_unlock(&fq->q.lock);
icmpv6_send(head, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0);
kfree_skb(head);
goto out_rcu_unlock;
out:
spin_unlock(&fq->q.lock);
out_rcu_unlock:
rcu_read_unlock();
inet_frag_put(&fq->q);
}
#endif
#endif
...@@ -10,9 +10,6 @@ ...@@ -10,9 +10,6 @@
#ifndef _NF_CONNTRACK_IPV4_H #ifndef _NF_CONNTRACK_IPV4_H
#define _NF_CONNTRACK_IPV4_H #define _NF_CONNTRACK_IPV4_H
const extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4; extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4; extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp; extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
......
...@@ -41,6 +41,11 @@ union nf_conntrack_expect_proto { ...@@ -41,6 +41,11 @@ union nf_conntrack_expect_proto {
/* insert expect proto private data here */ /* insert expect proto private data here */
}; };
struct nf_conntrack_net {
unsigned int users4;
unsigned int users6;
};
#include <linux/types.h> #include <linux/types.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#define _NF_CONNTRACK_CORE_H #define _NF_CONNTRACK_CORE_H
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_ecache.h> #include <net/netfilter/nf_conntrack_ecache.h>
...@@ -40,16 +39,8 @@ void nf_conntrack_cleanup_start(void); ...@@ -40,16 +39,8 @@ void nf_conntrack_cleanup_start(void);
void nf_conntrack_init_end(void); void nf_conntrack_init_end(void);
void nf_conntrack_cleanup_end(void); void nf_conntrack_cleanup_end(void);
bool nf_ct_get_tuple(const struct sk_buff *skb, unsigned int nhoff,
unsigned int dataoff, u_int16_t l3num, u_int8_t protonum,
struct net *net,
struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_l3proto *l3proto,
const struct nf_conntrack_l4proto *l4proto);
bool nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse, bool nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig, const struct nf_conntrack_tuple *orig,
const struct nf_conntrack_l3proto *l3proto,
const struct nf_conntrack_l4proto *l4proto); const struct nf_conntrack_l4proto *l4proto);
/* Find a connection corresponding to a tuple. */ /* Find a connection corresponding to a tuple. */
...@@ -75,10 +66,8 @@ static inline int nf_conntrack_confirm(struct sk_buff *skb) ...@@ -75,10 +66,8 @@ static inline int nf_conntrack_confirm(struct sk_buff *skb)
return ret; return ret;
} }
void void print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_l4proto *proto);
const struct nf_conntrack_l3proto *l3proto,
const struct nf_conntrack_l4proto *proto);
#define CONNTRACK_LOCKS 1024 #define CONNTRACK_LOCKS 1024
......
#ifndef _NF_CONNTRACK_COUNT_H #ifndef _NF_CONNTRACK_COUNT_H
#define _NF_CONNTRACK_COUNT_H #define _NF_CONNTRACK_COUNT_H
#include <linux/list.h>
struct nf_conncount_data; struct nf_conncount_data;
enum nf_conncount_list_add {
NF_CONNCOUNT_ADDED, /* list add was ok */
NF_CONNCOUNT_ERR, /* -ENOMEM, must drop skb */
NF_CONNCOUNT_SKIP, /* list is already reclaimed by gc */
};
struct nf_conncount_list {
spinlock_t list_lock;
struct list_head head; /* connections with the same filtering key */
unsigned int count; /* length of list */
bool dead;
};
struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family, struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family,
unsigned int keylen); unsigned int keylen);
void nf_conncount_destroy(struct net *net, unsigned int family, void nf_conncount_destroy(struct net *net, unsigned int family,
...@@ -14,15 +29,21 @@ unsigned int nf_conncount_count(struct net *net, ...@@ -14,15 +29,21 @@ unsigned int nf_conncount_count(struct net *net,
const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_zone *zone); const struct nf_conntrack_zone *zone);
unsigned int nf_conncount_lookup(struct net *net, struct hlist_head *head, void nf_conncount_lookup(struct net *net, struct nf_conncount_list *list,
const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_zone *zone, const struct nf_conntrack_zone *zone,
bool *addit); bool *addit);
void nf_conncount_list_init(struct nf_conncount_list *list);
enum nf_conncount_list_add
nf_conncount_add(struct nf_conncount_list *list,
const struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_zone *zone);
bool nf_conncount_add(struct hlist_head *head, bool nf_conncount_gc_list(struct net *net,
const struct nf_conntrack_tuple *tuple, struct nf_conncount_list *list);
const struct nf_conntrack_zone *zone);
void nf_conncount_cache_free(struct hlist_head *hhead); void nf_conncount_cache_free(struct nf_conncount_list *list);
#endif #endif
...@@ -103,9 +103,7 @@ int nf_conntrack_helpers_register(struct nf_conntrack_helper *, unsigned int); ...@@ -103,9 +103,7 @@ int nf_conntrack_helpers_register(struct nf_conntrack_helper *, unsigned int);
void nf_conntrack_helpers_unregister(struct nf_conntrack_helper *, void nf_conntrack_helpers_unregister(struct nf_conntrack_helper *,
unsigned int); unsigned int);
struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp);
struct nf_conntrack_helper *helper,
gfp_t gfp);
int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
gfp_t flags); gfp_t flags);
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C)2003,2004 USAGI/WIDE Project
*
* Header for use in defining a given L3 protocol for connection tracking.
*
* Author:
* Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
*
* Derived from include/netfilter_ipv4/ip_conntrack_protocol.h
*/
#ifndef _NF_CONNTRACK_L3PROTO_H
#define _NF_CONNTRACK_L3PROTO_H
#include <linux/netlink.h>
#include <net/netlink.h>
#include <linux/seq_file.h>
#include <net/netfilter/nf_conntrack.h>
struct nf_conntrack_l3proto {
/* L3 Protocol Family number. ex) PF_INET */
u_int16_t l3proto;
/* size of tuple nlattr, fills a hole */
u16 nla_size;
/*
* Try to fill in the third arg: nhoff is offset of l3 proto
* hdr. Return true if possible.
*/
bool (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int nhoff,
struct nf_conntrack_tuple *tuple);
/*
* Invert the per-proto part of the tuple: ie. turn xmit into reply.
* Some packets can't be inverted: return 0 in that case.
*/
bool (*invert_tuple)(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig);
/*
* Called before tracking.
* *dataoff: offset of protocol header (TCP, UDP,...) in skb
* *protonum: protocol number
*/
int (*get_l4proto)(const struct sk_buff *skb, unsigned int nhoff,
unsigned int *dataoff, u_int8_t *protonum);
#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
int (*tuple_to_nlattr)(struct sk_buff *skb,
const struct nf_conntrack_tuple *t);
int (*nlattr_to_tuple)(struct nlattr *tb[],
struct nf_conntrack_tuple *t);
const struct nla_policy *nla_policy;
#endif
/* Called when netns wants to use connection tracking */
int (*net_ns_get)(struct net *);
void (*net_ns_put)(struct net *);
/* Module (if any) which this is connected to. */
struct module *me;
};
extern struct nf_conntrack_l3proto __rcu *nf_ct_l3protos[NFPROTO_NUMPROTO];
/* Protocol global registration. */
int nf_ct_l3proto_register(const struct nf_conntrack_l3proto *proto);
void nf_ct_l3proto_unregister(const struct nf_conntrack_l3proto *proto);
const struct nf_conntrack_l3proto *nf_ct_l3proto_find_get(u_int16_t l3proto);
/* Existing built-in protocols */
extern struct nf_conntrack_l3proto nf_conntrack_l3proto_generic;
static inline struct nf_conntrack_l3proto *
__nf_ct_l3proto_find(u_int16_t l3proto)
{
if (unlikely(l3proto >= NFPROTO_NUMPROTO))
return &nf_conntrack_l3proto_generic;
return rcu_dereference(nf_ct_l3protos[l3proto]);
}
#endif /*_NF_CONNTRACK_L3PROTO_H*/
...@@ -36,7 +36,7 @@ struct nf_conntrack_l4proto { ...@@ -36,7 +36,7 @@ struct nf_conntrack_l4proto {
struct net *net, struct nf_conntrack_tuple *tuple); struct net *net, struct nf_conntrack_tuple *tuple);
/* Invert the per-proto part of the tuple: ie. turn xmit into reply. /* Invert the per-proto part of the tuple: ie. turn xmit into reply.
* Some packets can't be inverted: return 0 in that case. * Only used by icmp, most protocols use a generic version.
*/ */
bool (*invert_tuple)(struct nf_conntrack_tuple *inverse, bool (*invert_tuple)(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig); const struct nf_conntrack_tuple *orig);
...@@ -45,13 +45,12 @@ struct nf_conntrack_l4proto { ...@@ -45,13 +45,12 @@ struct nf_conntrack_l4proto {
int (*packet)(struct nf_conn *ct, int (*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);
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 *timeouts); unsigned int dataoff);
/* 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);
...@@ -63,9 +62,6 @@ struct nf_conntrack_l4proto { ...@@ -63,9 +62,6 @@ struct nf_conntrack_l4proto {
/* called by gc worker if table is full */ /* called by gc worker if table is full */
bool (*can_early_drop)(const struct nf_conn *ct); bool (*can_early_drop)(const struct nf_conn *ct);
/* 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);
...@@ -134,10 +130,6 @@ void nf_ct_l4proto_pernet_unregister(struct net *net, ...@@ -134,10 +130,6 @@ void nf_ct_l4proto_pernet_unregister(struct net *net,
/* Protocol global registration. */ /* Protocol global registration. */
int nf_ct_l4proto_register_one(const struct nf_conntrack_l4proto *proto); int nf_ct_l4proto_register_one(const struct nf_conntrack_l4proto *proto);
void nf_ct_l4proto_unregister_one(const struct nf_conntrack_l4proto *proto); void nf_ct_l4proto_unregister_one(const struct nf_conntrack_l4proto *proto);
int nf_ct_l4proto_register(const struct nf_conntrack_l4proto * const proto[],
unsigned int num_proto);
void nf_ct_l4proto_unregister(const struct nf_conntrack_l4proto * const proto[],
unsigned int num_proto);
/* Generic netlink helpers */ /* Generic netlink helpers */
int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb, int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
......
...@@ -67,27 +67,17 @@ struct nf_conn_timeout *nf_ct_timeout_ext_add(struct nf_conn *ct, ...@@ -67,27 +67,17 @@ struct nf_conn_timeout *nf_ct_timeout_ext_add(struct nf_conn *ct,
#endif #endif
}; };
static inline unsigned int * static inline unsigned int *nf_ct_timeout_lookup(const struct nf_conn *ct)
nf_ct_timeout_lookup(struct net *net, struct nf_conn *ct,
const struct nf_conntrack_l4proto *l4proto)
{ {
unsigned int *timeouts = NULL;
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
struct nf_conn_timeout *timeout_ext; struct nf_conn_timeout *timeout_ext;
unsigned int *timeouts;
timeout_ext = nf_ct_timeout_find(ct); timeout_ext = nf_ct_timeout_find(ct);
if (timeout_ext) { if (timeout_ext)
timeouts = nf_ct_timeout_data(timeout_ext); timeouts = nf_ct_timeout_data(timeout_ext);
if (unlikely(!timeouts))
timeouts = l4proto->get_timeouts(net);
} else {
timeouts = l4proto->get_timeouts(net);
}
return timeouts;
#else
return l4proto->get_timeouts(net);
#endif #endif
return timeouts;
} }
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
......
...@@ -17,6 +17,14 @@ static inline bool nf_tproxy_sk_is_transparent(struct sock *sk) ...@@ -17,6 +17,14 @@ static inline bool nf_tproxy_sk_is_transparent(struct sock *sk)
return false; return false;
} }
/* assign a socket to the skb -- consumes sk */
static inline void nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk)
{
skb_orphan(skb);
skb->sk = sk;
skb->destructor = sock_edemux;
}
__be32 nf_tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr); __be32 nf_tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr);
/** /**
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
struct netns_nftables { struct netns_nftables {
struct list_head tables; struct list_head tables;
struct list_head commit_list; struct list_head commit_list;
struct mutex commit_mutex;
unsigned int base_seq; unsigned int base_seq;
u8 gencursor; u8 gencursor;
u8 validate_state; u8 validate_state;
......
...@@ -16,9 +16,14 @@ ...@@ -16,9 +16,14 @@
#define NF_OSF_TTL_TRUE 0 /* True ip and fingerprint TTL comparison */ #define NF_OSF_TTL_TRUE 0 /* True ip and fingerprint TTL comparison */
/* Check if ip TTL is less than fingerprint one */
#define NF_OSF_TTL_LESS 1
/* Do not compare ip and fingerprint TTL at all */ /* Do not compare ip and fingerprint TTL at all */
#define NF_OSF_TTL_NOCHECK 2 #define NF_OSF_TTL_NOCHECK 2
#define NF_OSF_FLAGMASK (NF_OSF_GENRE | NF_OSF_TTL | \
NF_OSF_LOG | NF_OSF_INVERT)
/* Wildcard MSS (kind of). /* Wildcard MSS (kind of).
* It is used to implement a state machine for the different wildcard values * It is used to implement a state machine for the different wildcard values
* of the MSS and window sizes. * of the MSS and window sizes.
...@@ -83,4 +88,10 @@ enum iana_options { ...@@ -83,4 +88,10 @@ enum iana_options {
OSFOPT_EMPTY = 255, OSFOPT_EMPTY = 255,
}; };
enum nf_osf_attr_type {
OSF_ATTR_UNSPEC,
OSF_ATTR_FINGER,
OSF_ATTR_MAX,
};
#endif /* _NF_OSF_H */ #endif /* _NF_OSF_H */
...@@ -921,10 +921,12 @@ enum nft_socket_attributes { ...@@ -921,10 +921,12 @@ enum nft_socket_attributes {
/* /*
* enum nft_socket_keys - nf_tables socket expression keys * enum nft_socket_keys - nf_tables socket expression keys
* *
* @NFT_SOCKET_TRANSPARENT: Value of the IP(V6)_TRANSPARENT socket option_ * @NFT_SOCKET_TRANSPARENT: Value of the IP(V6)_TRANSPARENT socket option
* @NFT_SOCKET_MARK: Value of the socket mark
*/ */
enum nft_socket_keys { enum nft_socket_keys {
NFT_SOCKET_TRANSPARENT, NFT_SOCKET_TRANSPARENT,
NFT_SOCKET_MARK,
__NFT_SOCKET_MAX __NFT_SOCKET_MAX
}; };
#define NFT_SOCKET_MAX (__NFT_SOCKET_MAX - 1) #define NFT_SOCKET_MAX (__NFT_SOCKET_MAX - 1)
......
...@@ -37,8 +37,7 @@ ...@@ -37,8 +37,7 @@
#define XT_OSF_TTL_TRUE NF_OSF_TTL_TRUE #define XT_OSF_TTL_TRUE NF_OSF_TTL_TRUE
#define XT_OSF_TTL_NOCHECK NF_OSF_TTL_NOCHECK #define XT_OSF_TTL_NOCHECK NF_OSF_TTL_NOCHECK
#define XT_OSF_TTL_LESS NF_OSF_TTL_LESS
#define XT_OSF_TTL_LESS 1 /* Check if ip TTL is less than fingerprint one */
#define xt_osf_wc nf_osf_wc #define xt_osf_wc nf_osf_wc
#define xt_osf_opt nf_osf_opt #define xt_osf_opt nf_osf_opt
...@@ -47,6 +46,7 @@ ...@@ -47,6 +46,7 @@
#define xt_osf_finger nf_osf_finger #define xt_osf_finger nf_osf_finger
#define xt_osf_nlmsg nf_osf_nlmsg #define xt_osf_nlmsg nf_osf_nlmsg
#define xt_osf_attr_type nf_osf_attr_type
/* /*
* Add/remove fingerprint from the kernel. * Add/remove fingerprint from the kernel.
*/ */
...@@ -56,10 +56,4 @@ enum xt_osf_msg_types { ...@@ -56,10 +56,4 @@ enum xt_osf_msg_types {
OSF_MSG_MAX, OSF_MSG_MAX,
}; };
enum xt_osf_attr_type {
OSF_ATTR_UNSPEC,
OSF_ATTR_FINGER,
OSF_ATTR_MAX,
};
#endif /* _XT_OSF_H */ #endif /* _XT_OSF_H */
...@@ -89,8 +89,7 @@ static void nft_reject_br_send_v4_tcp_reset(struct net *net, ...@@ -89,8 +89,7 @@ static void nft_reject_br_send_v4_tcp_reset(struct net *net,
niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP, niph = nf_reject_iphdr_put(nskb, oldskb, IPPROTO_TCP,
net->ipv4.sysctl_ip_default_ttl); net->ipv4.sysctl_ip_default_ttl);
nf_reject_ip_tcphdr_put(nskb, oldskb, oth); nf_reject_ip_tcphdr_put(nskb, oldskb, oth);
niph->ttl = net->ipv4.sysctl_ip_default_ttl; niph->tot_len = htons(nskb->len);
niph->tot_len = htons(nskb->len);
ip_send_check(niph); ip_send_check(niph);
nft_reject_br_push_etherhdr(oldskb, nskb); nft_reject_br_push_etherhdr(oldskb, nskb);
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <net/ieee802154_netdev.h> #include <net/ieee802154_netdev.h>
#include <net/6lowpan.h> #include <net/6lowpan.h>
#include <net/ipv6.h> #include <net/ipv6_frag.h>
#include <net/inet_frag.h> #include <net/inet_frag.h>
#include "6lowpan_i.h" #include "6lowpan_i.h"
......
...@@ -98,59 +98,6 @@ int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry) ...@@ -98,59 +98,6 @@ int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry)
} }
EXPORT_SYMBOL_GPL(nf_ip_reroute); EXPORT_SYMBOL_GPL(nf_ip_reroute);
__sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol)
{
const struct iphdr *iph = ip_hdr(skb);
__sum16 csum = 0;
switch (skb->ip_summed) {
case CHECKSUM_COMPLETE:
if (hook != NF_INET_PRE_ROUTING && hook != NF_INET_LOCAL_IN)
break;
if ((protocol == 0 && !csum_fold(skb->csum)) ||
!csum_tcpudp_magic(iph->saddr, iph->daddr,
skb->len - dataoff, protocol,
skb->csum)) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
break;
}
/* fall through */
case CHECKSUM_NONE:
if (protocol == 0)
skb->csum = 0;
else
skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr,
skb->len - dataoff,
protocol, 0);
csum = __skb_checksum_complete(skb);
}
return csum;
}
EXPORT_SYMBOL(nf_ip_checksum);
__sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, unsigned int len,
u_int8_t protocol)
{
const struct iphdr *iph = ip_hdr(skb);
__sum16 csum = 0;
switch (skb->ip_summed) {
case CHECKSUM_COMPLETE:
if (len == skb->len - dataoff)
return nf_ip_checksum(skb, hook, dataoff, protocol);
/* fall through */
case CHECKSUM_NONE:
skb->csum = csum_tcpudp_nofold(iph->saddr, iph->daddr, protocol,
skb->len - dataoff, 0);
skb->ip_summed = CHECKSUM_NONE;
return __skb_checksum_complete_head(skb, dataoff + len);
}
return csum;
}
EXPORT_SYMBOL_GPL(nf_ip_checksum_partial);
int nf_ip_route(struct net *net, struct dst_entry **dst, struct flowi *fl, int nf_ip_route(struct net *net, struct dst_entry **dst, struct flowi *fl,
bool strict __always_unused) bool strict __always_unused)
{ {
......
...@@ -9,22 +9,6 @@ config NF_DEFRAG_IPV4 ...@@ -9,22 +9,6 @@ config NF_DEFRAG_IPV4
tristate tristate
default n default n
config NF_CONNTRACK_IPV4
tristate "IPv4 connection tracking support (required for NAT)"
depends on NF_CONNTRACK
default m if NETFILTER_ADVANCED=n
select NF_DEFRAG_IPV4
---help---
Connection tracking keeps a record of what packets have passed
through your machine, in order to figure out how they are related
into connections.
This is IPv4 support on Layer 3 independent connection tracking.
Layer 3 independent connection tracking is experimental scheme
which generalize ip_conntrack to support other layer 3 protocols.
To compile it as a module, choose M here. If unsure, say N.
config NF_SOCKET_IPV4 config NF_SOCKET_IPV4
tristate "IPv4 socket lookup support" tristate "IPv4 socket lookup support"
help help
...@@ -112,7 +96,7 @@ config NF_REJECT_IPV4 ...@@ -112,7 +96,7 @@ config NF_REJECT_IPV4
config NF_NAT_IPV4 config NF_NAT_IPV4
tristate "IPv4 NAT" tristate "IPv4 NAT"
depends on NF_CONNTRACK_IPV4 depends on NF_CONNTRACK
default m if NETFILTER_ADVANCED=n default m if NETFILTER_ADVANCED=n
select NF_NAT select NF_NAT
help help
...@@ -279,7 +263,7 @@ config IP_NF_TARGET_SYNPROXY ...@@ -279,7 +263,7 @@ config IP_NF_TARGET_SYNPROXY
# NAT + specific targets: nf_conntrack # NAT + specific targets: nf_conntrack
config IP_NF_NAT config IP_NF_NAT
tristate "iptables NAT support" tristate "iptables NAT support"
depends on NF_CONNTRACK_IPV4 depends on NF_CONNTRACK
default m if NETFILTER_ADVANCED=n default m if NETFILTER_ADVANCED=n
select NF_NAT select NF_NAT
select NF_NAT_IPV4 select NF_NAT_IPV4
...@@ -340,7 +324,7 @@ config IP_NF_MANGLE ...@@ -340,7 +324,7 @@ config IP_NF_MANGLE
config IP_NF_TARGET_CLUSTERIP config IP_NF_TARGET_CLUSTERIP
tristate "CLUSTERIP target support" tristate "CLUSTERIP target support"
depends on IP_NF_MANGLE depends on IP_NF_MANGLE
depends on NF_CONNTRACK_IPV4 depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED depends on NETFILTER_ADVANCED
select NF_CONNTRACK_MARK select NF_CONNTRACK_MARK
select NETFILTER_FAMILY_ARP select NETFILTER_FAMILY_ARP
......
...@@ -3,12 +3,6 @@ ...@@ -3,12 +3,6 @@
# Makefile for the netfilter modules on top of IPv4. # Makefile for the netfilter modules on top of IPv4.
# #
# objects for l3 independent conntrack
nf_conntrack_ipv4-y := nf_conntrack_l3proto_ipv4.o nf_conntrack_proto_icmp.o
# connection tracking
obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o
nf_nat_ipv4-y := nf_nat_l3proto_ipv4.o nf_nat_proto_icmp.o nf_nat_ipv4-y := nf_nat_l3proto_ipv4.o nf_nat_proto_icmp.o
nf_nat_ipv4-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o nf_nat_ipv4-$(CONFIG_NF_NAT_MASQUERADE_IPV4) += nf_nat_masquerade_ipv4.o
obj-$(CONFIG_NF_NAT_IPV4) += nf_nat_ipv4.o obj-$(CONFIG_NF_NAT_IPV4) += nf_nat_ipv4.o
......
This diff is collapsed.
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include <net/ipv6.h> #include <net/ipv6.h>
#include <net/ip6_route.h> #include <net/ip6_route.h>
#include <net/xfrm.h> #include <net/xfrm.h>
#include <net/ip6_checksum.h>
#include <net/netfilter/nf_queue.h> #include <net/netfilter/nf_queue.h>
int ip6_route_me_harder(struct net *net, struct sk_buff *skb) int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
...@@ -106,71 +105,10 @@ static int nf_ip6_route(struct net *net, struct dst_entry **dst, ...@@ -106,71 +105,10 @@ static int nf_ip6_route(struct net *net, struct dst_entry **dst,
return err; return err;
} }
__sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, u_int8_t protocol)
{
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
__sum16 csum = 0;
switch (skb->ip_summed) {
case CHECKSUM_COMPLETE:
if (hook != NF_INET_PRE_ROUTING && hook != NF_INET_LOCAL_IN)
break;
if (!csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
skb->len - dataoff, protocol,
csum_sub(skb->csum,
skb_checksum(skb, 0,
dataoff, 0)))) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
break;
}
/* fall through */
case CHECKSUM_NONE:
skb->csum = ~csum_unfold(
csum_ipv6_magic(&ip6h->saddr, &ip6h->daddr,
skb->len - dataoff,
protocol,
csum_sub(0,
skb_checksum(skb, 0,
dataoff, 0))));
csum = __skb_checksum_complete(skb);
}
return csum;
}
EXPORT_SYMBOL(nf_ip6_checksum);
static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook,
unsigned int dataoff, unsigned int len,
u_int8_t protocol)
{
const struct ipv6hdr *ip6h = ipv6_hdr(skb);
__wsum hsum;
__sum16 csum = 0;
switch (skb->ip_summed) {
case CHECKSUM_COMPLETE:
if (len == skb->len - dataoff)
return nf_ip6_checksum(skb, hook, dataoff, protocol);
/* fall through */
case CHECKSUM_NONE:
hsum = skb_checksum(skb, 0, dataoff, 0);
skb->csum = ~csum_unfold(csum_ipv6_magic(&ip6h->saddr,
&ip6h->daddr,
skb->len - dataoff,
protocol,
csum_sub(0, hsum)));
skb->ip_summed = CHECKSUM_NONE;
return __skb_checksum_complete_head(skb, dataoff + len);
}
return csum;
};
static const struct nf_ipv6_ops ipv6ops = { static const struct nf_ipv6_ops ipv6ops = {
.chk_addr = ipv6_chk_addr, .chk_addr = ipv6_chk_addr,
.route_input = ip6_route_input, .route_input = ip6_route_input,
.fragment = ip6_fragment, .fragment = ip6_fragment,
.checksum = nf_ip6_checksum,
.checksum_partial = nf_ip6_checksum_partial,
.route = nf_ip6_route, .route = nf_ip6_route,
.reroute = nf_ip6_reroute, .reroute = nf_ip6_reroute,
}; };
......
...@@ -5,26 +5,6 @@ ...@@ -5,26 +5,6 @@
menu "IPv6: Netfilter Configuration" menu "IPv6: Netfilter Configuration"
depends on INET && IPV6 && NETFILTER depends on INET && IPV6 && NETFILTER
config NF_DEFRAG_IPV6
tristate
default n
config NF_CONNTRACK_IPV6
tristate "IPv6 connection tracking support"
depends on INET && IPV6 && NF_CONNTRACK
default m if NETFILTER_ADVANCED=n
select NF_DEFRAG_IPV6
---help---
Connection tracking keeps a record of what packets have passed
through your machine, in order to figure out how they are related
into connections.
This is IPv6 support on Layer 3 independent connection tracking.
Layer 3 independent connection tracking is experimental scheme
which generalize ip_conntrack to support other layer 3 protocols.
To compile it as a module, choose M here. If unsure, say N.
config NF_SOCKET_IPV6 config NF_SOCKET_IPV6
tristate "IPv6 socket lookup support" tristate "IPv6 socket lookup support"
help help
...@@ -128,7 +108,7 @@ config NF_LOG_IPV6 ...@@ -128,7 +108,7 @@ config NF_LOG_IPV6
config NF_NAT_IPV6 config NF_NAT_IPV6
tristate "IPv6 NAT" tristate "IPv6 NAT"
depends on NF_CONNTRACK_IPV6 depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED depends on NETFILTER_ADVANCED
select NF_NAT select NF_NAT
help help
...@@ -328,7 +308,7 @@ config IP6_NF_SECURITY ...@@ -328,7 +308,7 @@ config IP6_NF_SECURITY
config IP6_NF_NAT config IP6_NF_NAT
tristate "ip6tables NAT support" tristate "ip6tables NAT support"
depends on NF_CONNTRACK_IPV6 depends on NF_CONNTRACK
depends on NETFILTER_ADVANCED depends on NETFILTER_ADVANCED
select NF_NAT select NF_NAT
select NF_NAT_IPV6 select NF_NAT_IPV6
...@@ -365,6 +345,7 @@ config IP6_NF_TARGET_NPT ...@@ -365,6 +345,7 @@ config IP6_NF_TARGET_NPT
endif # IP6_NF_NAT endif # IP6_NF_NAT
endif # IP6_NF_IPTABLES endif # IP6_NF_IPTABLES
endmenu endmenu
config NF_DEFRAG_IPV6
tristate
...@@ -11,12 +11,6 @@ obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o ...@@ -11,12 +11,6 @@ obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o
obj-$(CONFIG_IP6_NF_NAT) += ip6table_nat.o obj-$(CONFIG_IP6_NF_NAT) += ip6table_nat.o
# objects for l3 independent conntrack
nf_conntrack_ipv6-y := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o
# l3 independent conntrack
obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o
nf_nat_ipv6-y := nf_nat_l3proto_ipv6.o nf_nat_proto_icmpv6.o nf_nat_ipv6-y := nf_nat_l3proto_ipv6.o nf_nat_proto_icmpv6.o
nf_nat_ipv6-$(CONFIG_NF_NAT_MASQUERADE_IPV6) += nf_nat_masquerade_ipv6.o nf_nat_ipv6-$(CONFIG_NF_NAT_MASQUERADE_IPV6) += nf_nat_masquerade_ipv6.o
obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o
......
This diff is collapsed.
...@@ -33,9 +33,8 @@ ...@@ -33,9 +33,8 @@
#include <net/sock.h> #include <net/sock.h>
#include <net/snmp.h> #include <net/snmp.h>
#include <net/inet_frag.h> #include <net/ipv6_frag.h>
#include <net/ipv6.h>
#include <net/protocol.h> #include <net/protocol.h>
#include <net/transp_v6.h> #include <net/transp_v6.h>
#include <net/rawv6.h> #include <net/rawv6.h>
...@@ -151,7 +150,7 @@ static void nf_ct_frag6_expire(struct timer_list *t) ...@@ -151,7 +150,7 @@ static void nf_ct_frag6_expire(struct timer_list *t)
fq = container_of(frag, struct frag_queue, q); fq = container_of(frag, struct frag_queue, q);
net = container_of(fq->q.net, struct net, nf_frag.frags); net = container_of(fq->q.net, struct net, nf_frag.frags);
ip6_expire_frag_queue(net, fq); ip6frag_expire_frag_queue(net, fq);
} }
/* Creation primitives. */ /* Creation primitives. */
...@@ -624,16 +623,24 @@ static struct pernet_operations nf_ct_net_ops = { ...@@ -624,16 +623,24 @@ static struct pernet_operations nf_ct_net_ops = {
.exit = nf_ct_net_exit, .exit = nf_ct_net_exit,
}; };
static const struct rhashtable_params nfct_rhash_params = {
.head_offset = offsetof(struct inet_frag_queue, node),
.hashfn = ip6frag_key_hashfn,
.obj_hashfn = ip6frag_obj_hashfn,
.obj_cmpfn = ip6frag_obj_cmpfn,
.automatic_shrinking = true,
};
int nf_ct_frag6_init(void) int nf_ct_frag6_init(void)
{ {
int ret = 0; int ret = 0;
nf_frags.constructor = ip6_frag_init; nf_frags.constructor = ip6frag_init;
nf_frags.destructor = NULL; nf_frags.destructor = NULL;
nf_frags.qsize = sizeof(struct frag_queue); nf_frags.qsize = sizeof(struct frag_queue);
nf_frags.frag_expire = nf_ct_frag6_expire; nf_frags.frag_expire = nf_ct_frag6_expire;
nf_frags.frags_cache_name = nf_frags_cache_name; nf_frags.frags_cache_name = nf_frags_cache_name;
nf_frags.rhash_params = ip6_rhash_params; nf_frags.rhash_params = nfct_rhash_params;
ret = inet_frags_init(&nf_frags); ret = inet_frags_init(&nf_frags);
if (ret) if (ret)
goto out; goto out;
......
...@@ -14,8 +14,7 @@ ...@@ -14,8 +14,7 @@
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <linux/icmp.h> #include <linux/icmp.h>
#include <linux/sysctl.h> #include <linux/sysctl.h>
#include <net/ipv6.h> #include <net/ipv6_frag.h>
#include <net/inet_frag.h>
#include <linux/netfilter_ipv6.h> #include <linux/netfilter_ipv6.h>
#include <linux/netfilter_bridge.h> #include <linux/netfilter_bridge.h>
...@@ -23,7 +22,6 @@ ...@@ -23,7 +22,6 @@
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h> #include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
#endif #endif
......
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
#include <net/rawv6.h> #include <net/rawv6.h>
#include <net/ndisc.h> #include <net/ndisc.h>
#include <net/addrconf.h> #include <net/addrconf.h>
#include <net/inet_frag.h> #include <net/ipv6_frag.h>
#include <net/inet_ecn.h> #include <net/inet_ecn.h>
static const char ip6_frag_cache_name[] = "ip6-frags"; static const char ip6_frag_cache_name[] = "ip6-frags";
...@@ -72,61 +72,6 @@ static struct inet_frags ip6_frags; ...@@ -72,61 +72,6 @@ static struct inet_frags ip6_frags;
static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev,
struct net_device *dev); struct net_device *dev);
void ip6_frag_init(struct inet_frag_queue *q, const void *a)
{
struct frag_queue *fq = container_of(q, struct frag_queue, q);
const struct frag_v6_compare_key *key = a;
q->key.v6 = *key;
fq->ecn = 0;
}
EXPORT_SYMBOL(ip6_frag_init);
void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq)
{
struct net_device *dev = NULL;
struct sk_buff *head;
rcu_read_lock();
spin_lock(&fq->q.lock);
if (fq->q.flags & INET_FRAG_COMPLETE)
goto out;
inet_frag_kill(&fq->q);
dev = dev_get_by_index_rcu(net, fq->iif);
if (!dev)
goto out;
__IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS);
__IP6_INC_STATS(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT);
/* Don't send error if the first segment did not arrive. */
head = fq->q.fragments;
if (!(fq->q.flags & INET_FRAG_FIRST_IN) || !head)
goto out;
/* But use as source device on which LAST ARRIVED
* segment was received. And do not use fq->dev
* pointer directly, device might already disappeared.
*/
head->dev = dev;
skb_get(head);
spin_unlock(&fq->q.lock);
icmpv6_send(head, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0);
kfree_skb(head);
goto out_rcu_unlock;
out:
spin_unlock(&fq->q.lock);
out_rcu_unlock:
rcu_read_unlock();
inet_frag_put(&fq->q);
}
EXPORT_SYMBOL(ip6_expire_frag_queue);
static void ip6_frag_expire(struct timer_list *t) static void ip6_frag_expire(struct timer_list *t)
{ {
struct inet_frag_queue *frag = from_timer(frag, t, timer); struct inet_frag_queue *frag = from_timer(frag, t, timer);
...@@ -136,7 +81,7 @@ static void ip6_frag_expire(struct timer_list *t) ...@@ -136,7 +81,7 @@ static void ip6_frag_expire(struct timer_list *t)
fq = container_of(frag, struct frag_queue, q); fq = container_of(frag, struct frag_queue, q);
net = container_of(fq->q.net, struct net, ipv6.frags); net = container_of(fq->q.net, struct net, ipv6.frags);
ip6_expire_frag_queue(net, fq); ip6frag_expire_frag_queue(net, fq);
} }
static struct frag_queue * static struct frag_queue *
...@@ -696,42 +641,19 @@ static struct pernet_operations ip6_frags_ops = { ...@@ -696,42 +641,19 @@ static struct pernet_operations ip6_frags_ops = {
.exit = ipv6_frags_exit_net, .exit = ipv6_frags_exit_net,
}; };
static u32 ip6_key_hashfn(const void *data, u32 len, u32 seed) static const struct rhashtable_params ip6_rhash_params = {
{
return jhash2(data,
sizeof(struct frag_v6_compare_key) / sizeof(u32), seed);
}
static u32 ip6_obj_hashfn(const void *data, u32 len, u32 seed)
{
const struct inet_frag_queue *fq = data;
return jhash2((const u32 *)&fq->key.v6,
sizeof(struct frag_v6_compare_key) / sizeof(u32), seed);
}
static int ip6_obj_cmpfn(struct rhashtable_compare_arg *arg, const void *ptr)
{
const struct frag_v6_compare_key *key = arg->key;
const struct inet_frag_queue *fq = ptr;
return !!memcmp(&fq->key, key, sizeof(*key));
}
const struct rhashtable_params ip6_rhash_params = {
.head_offset = offsetof(struct inet_frag_queue, node), .head_offset = offsetof(struct inet_frag_queue, node),
.hashfn = ip6_key_hashfn, .hashfn = ip6frag_key_hashfn,
.obj_hashfn = ip6_obj_hashfn, .obj_hashfn = ip6frag_obj_hashfn,
.obj_cmpfn = ip6_obj_cmpfn, .obj_cmpfn = ip6frag_obj_cmpfn,
.automatic_shrinking = true, .automatic_shrinking = true,
}; };
EXPORT_SYMBOL(ip6_rhash_params);
int __init ipv6_frag_init(void) int __init ipv6_frag_init(void)
{ {
int ret; int ret;
ip6_frags.constructor = ip6_frag_init; ip6_frags.constructor = ip6frag_init;
ip6_frags.destructor = NULL; ip6_frags.destructor = NULL;
ip6_frags.qsize = sizeof(struct frag_queue); ip6_frags.qsize = sizeof(struct frag_queue);
ip6_frags.frag_expire = ip6_frag_expire; ip6_frags.frag_expire = ip6_frag_expire;
......
...@@ -49,6 +49,8 @@ config NETFILTER_NETLINK_LOG ...@@ -49,6 +49,8 @@ config NETFILTER_NETLINK_LOG
config NF_CONNTRACK config NF_CONNTRACK
tristate "Netfilter connection tracking support" tristate "Netfilter connection tracking support"
default m if NETFILTER_ADVANCED=n default m if NETFILTER_ADVANCED=n
select NF_DEFRAG_IPV4
select NF_DEFRAG_IPV6 if IPV6 != n
help help
Connection tracking keeps a record of what packets have passed Connection tracking keeps a record of what packets have passed
through your machine, in order to figure out how they are related through your machine, in order to figure out how they are related
...@@ -615,7 +617,7 @@ config NFT_SOCKET ...@@ -615,7 +617,7 @@ config NFT_SOCKET
tristate "Netfilter nf_tables socket match support" tristate "Netfilter nf_tables socket match support"
depends on IPV6 || IPV6=n depends on IPV6 || IPV6=n
select NF_SOCKET_IPV4 select NF_SOCKET_IPV4
select NF_SOCKET_IPV6 if IPV6 select NF_SOCKET_IPV6 if NF_TABLES_IPV6
help help
This option allows matching for the presence or absence of a This option allows matching for the presence or absence of a
corresponding socket and its attributes. corresponding socket and its attributes.
...@@ -881,7 +883,7 @@ config NETFILTER_XT_TARGET_LOG ...@@ -881,7 +883,7 @@ config NETFILTER_XT_TARGET_LOG
tristate "LOG target support" tristate "LOG target support"
select NF_LOG_COMMON select NF_LOG_COMMON
select NF_LOG_IPV4 select NF_LOG_IPV4
select NF_LOG_IPV6 if IPV6 select NF_LOG_IPV6 if IP6_NF_IPTABLES
default m if NETFILTER_ADVANCED=n default m if NETFILTER_ADVANCED=n
help help
This option adds a `LOG' target, which allows you to create rules in This option adds a `LOG' target, which allows you to create rules in
...@@ -973,7 +975,7 @@ config NETFILTER_XT_TARGET_TEE ...@@ -973,7 +975,7 @@ config NETFILTER_XT_TARGET_TEE
depends on IPV6 || IPV6=n depends on IPV6 || IPV6=n
depends on !NF_CONNTRACK || NF_CONNTRACK depends on !NF_CONNTRACK || NF_CONNTRACK
select NF_DUP_IPV4 select NF_DUP_IPV4
select NF_DUP_IPV6 if IPV6 select NF_DUP_IPV6 if IP6_NF_IPTABLES
---help--- ---help---
This option adds a "TEE" target with which a packet can be cloned and This option adds a "TEE" target with which a packet can be cloned and
this clone be rerouted to another nexthop. this clone be rerouted to another nexthop.
...@@ -1481,8 +1483,8 @@ config NETFILTER_XT_MATCH_SOCKET ...@@ -1481,8 +1483,8 @@ config NETFILTER_XT_MATCH_SOCKET
depends on NETFILTER_ADVANCED depends on NETFILTER_ADVANCED
depends on IPV6 || IPV6=n depends on IPV6 || IPV6=n
depends on IP6_NF_IPTABLES || IP6_NF_IPTABLES=n depends on IP6_NF_IPTABLES || IP6_NF_IPTABLES=n
depends on NF_SOCKET_IPV4 select NF_SOCKET_IPV4
depends on NF_SOCKET_IPV6 select NF_SOCKET_IPV6 if IP6_NF_IPTABLES
select NF_DEFRAG_IPV4 select NF_DEFRAG_IPV4
select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES != n select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES != n
help help
......
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o utils.o netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o utils.o
nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o \
nf_conntrack_proto.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o \
nf_conntrack_proto_icmp.o \
nf_conntrack_extend.o nf_conntrack_acct.o nf_conntrack_seqadj.o
nf_conntrack-$(subst m,y,$(CONFIG_IPV6)) += nf_conntrack_proto_icmpv6.o
nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMEOUT) += nf_conntrack_timeout.o
nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMESTAMP) += nf_conntrack_timestamp.o nf_conntrack-$(CONFIG_NF_CONNTRACK_TIMESTAMP) += nf_conntrack_timestamp.o
nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
......
...@@ -825,12 +825,23 @@ static void ip_vs_conn_expire(struct timer_list *t) ...@@ -825,12 +825,23 @@ static void ip_vs_conn_expire(struct timer_list *t)
/* Unlink conn if not referenced anymore */ /* Unlink conn if not referenced anymore */
if (likely(ip_vs_conn_unlink(cp))) { if (likely(ip_vs_conn_unlink(cp))) {
struct ip_vs_conn *ct = cp->control;
/* delete the timer if it is activated by other users */ /* delete the timer if it is activated by other users */
del_timer(&cp->timer); del_timer(&cp->timer);
/* does anybody control me? */ /* does anybody control me? */
if (cp->control) if (ct) {
ip_vs_control_del(cp); ip_vs_control_del(cp);
/* Drop CTL or non-assured TPL if not used anymore */
if (!cp->timeout && !atomic_read(&ct->n_control) &&
(!(ct->flags & IP_VS_CONN_F_TEMPLATE) ||
!(ct->state & IP_VS_CTPL_S_ASSURED))) {
IP_VS_DBG(4, "drop controlling connection\n");
ct->timeout = 0;
ip_vs_conn_expire_now(ct);
}
}
if ((cp->flags & IP_VS_CONN_F_NFCT) && if ((cp->flags & IP_VS_CONN_F_NFCT) &&
!(cp->flags & IP_VS_CONN_F_ONE_PACKET)) { !(cp->flags & IP_VS_CONN_F_ONE_PACKET)) {
...@@ -872,6 +883,10 @@ static void ip_vs_conn_expire(struct timer_list *t) ...@@ -872,6 +883,10 @@ static void ip_vs_conn_expire(struct timer_list *t)
/* Modify timer, so that it expires as soon as possible. /* Modify timer, so that it expires as soon as possible.
* Can be called without reference only if under RCU lock. * Can be called without reference only if under RCU lock.
* We can have such chain of conns linked with ->control: DATA->CTL->TPL
* - DATA (eg. FTP) and TPL (persistence) can be present depending on setup
* - cp->timeout=0 indicates all conns from chain should be dropped but
* TPL is not dropped if in assured state
*/ */
void ip_vs_conn_expire_now(struct ip_vs_conn *cp) void ip_vs_conn_expire_now(struct ip_vs_conn *cp)
{ {
...@@ -1107,7 +1122,7 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v) ...@@ -1107,7 +1122,7 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v)
&cp->caddr.in6, ntohs(cp->cport), &cp->caddr.in6, ntohs(cp->cport),
&cp->vaddr.in6, ntohs(cp->vport), &cp->vaddr.in6, ntohs(cp->vport),
dbuf, ntohs(cp->dport), dbuf, ntohs(cp->dport),
ip_vs_state_name(cp->protocol, cp->state), ip_vs_state_name(cp),
(cp->timer.expires-jiffies)/HZ, pe_data); (cp->timer.expires-jiffies)/HZ, pe_data);
else else
#endif #endif
...@@ -1118,7 +1133,7 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v) ...@@ -1118,7 +1133,7 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v)
ntohl(cp->caddr.ip), ntohs(cp->cport), ntohl(cp->caddr.ip), ntohs(cp->cport),
ntohl(cp->vaddr.ip), ntohs(cp->vport), ntohl(cp->vaddr.ip), ntohs(cp->vport),
dbuf, ntohs(cp->dport), dbuf, ntohs(cp->dport),
ip_vs_state_name(cp->protocol, cp->state), ip_vs_state_name(cp),
(cp->timer.expires-jiffies)/HZ, pe_data); (cp->timer.expires-jiffies)/HZ, pe_data);
} }
return 0; return 0;
...@@ -1169,7 +1184,7 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v) ...@@ -1169,7 +1184,7 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v)
&cp->caddr.in6, ntohs(cp->cport), &cp->caddr.in6, ntohs(cp->cport),
&cp->vaddr.in6, ntohs(cp->vport), &cp->vaddr.in6, ntohs(cp->vport),
dbuf, ntohs(cp->dport), dbuf, ntohs(cp->dport),
ip_vs_state_name(cp->protocol, cp->state), ip_vs_state_name(cp),
ip_vs_origin_name(cp->flags), ip_vs_origin_name(cp->flags),
(cp->timer.expires-jiffies)/HZ); (cp->timer.expires-jiffies)/HZ);
else else
...@@ -1181,7 +1196,7 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v) ...@@ -1181,7 +1196,7 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v)
ntohl(cp->caddr.ip), ntohs(cp->cport), ntohl(cp->caddr.ip), ntohs(cp->cport),
ntohl(cp->vaddr.ip), ntohs(cp->vport), ntohl(cp->vaddr.ip), ntohs(cp->vport),
dbuf, ntohs(cp->dport), dbuf, ntohs(cp->dport),
ip_vs_state_name(cp->protocol, cp->state), ip_vs_state_name(cp),
ip_vs_origin_name(cp->flags), ip_vs_origin_name(cp->flags),
(cp->timer.expires-jiffies)/HZ); (cp->timer.expires-jiffies)/HZ);
} }
...@@ -1197,8 +1212,11 @@ static const struct seq_operations ip_vs_conn_sync_seq_ops = { ...@@ -1197,8 +1212,11 @@ static const struct seq_operations ip_vs_conn_sync_seq_ops = {
#endif #endif
/* /* Randomly drop connection entries before running out of memory
* Randomly drop connection entries before running out of memory * Can be used for DATA and CTL conns. For TPL conns there are exceptions:
* - traffic for services in OPS mode increases ct->in_pkts, so it is supported
* - traffic for services not in OPS mode does not increase ct->in_pkts in
* all cases, so it is not supported
*/ */
static inline int todrop_entry(struct ip_vs_conn *cp) static inline int todrop_entry(struct ip_vs_conn *cp)
{ {
...@@ -1242,7 +1260,7 @@ static inline bool ip_vs_conn_ops_mode(struct ip_vs_conn *cp) ...@@ -1242,7 +1260,7 @@ static inline bool ip_vs_conn_ops_mode(struct ip_vs_conn *cp)
void ip_vs_random_dropentry(struct netns_ipvs *ipvs) void ip_vs_random_dropentry(struct netns_ipvs *ipvs)
{ {
int idx; int idx;
struct ip_vs_conn *cp, *cp_c; struct ip_vs_conn *cp;
rcu_read_lock(); rcu_read_lock();
/* /*
...@@ -1254,13 +1272,15 @@ void ip_vs_random_dropentry(struct netns_ipvs *ipvs) ...@@ -1254,13 +1272,15 @@ void ip_vs_random_dropentry(struct netns_ipvs *ipvs)
hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[hash], c_list) { hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[hash], c_list) {
if (cp->ipvs != ipvs) if (cp->ipvs != ipvs)
continue; continue;
if (atomic_read(&cp->n_control))
continue;
if (cp->flags & IP_VS_CONN_F_TEMPLATE) { if (cp->flags & IP_VS_CONN_F_TEMPLATE) {
if (atomic_read(&cp->n_control) || /* connection template of OPS */
!ip_vs_conn_ops_mode(cp)) if (ip_vs_conn_ops_mode(cp))
continue;
else
/* connection template of OPS */
goto try_drop; goto try_drop;
if (!(cp->state & IP_VS_CTPL_S_ASSURED))
goto drop;
continue;
} }
if (cp->protocol == IPPROTO_TCP) { if (cp->protocol == IPPROTO_TCP) {
switch(cp->state) { switch(cp->state) {
...@@ -1294,15 +1314,10 @@ void ip_vs_random_dropentry(struct netns_ipvs *ipvs) ...@@ -1294,15 +1314,10 @@ void ip_vs_random_dropentry(struct netns_ipvs *ipvs)
continue; continue;
} }
IP_VS_DBG(4, "del connection\n"); drop:
IP_VS_DBG(4, "drop connection\n");
cp->timeout = 0;
ip_vs_conn_expire_now(cp); ip_vs_conn_expire_now(cp);
cp_c = cp->control;
/* cp->control is valid only with reference to cp */
if (cp_c && __ip_vs_conn_get(cp)) {
IP_VS_DBG(4, "del conn template\n");
ip_vs_conn_expire_now(cp_c);
__ip_vs_conn_put(cp);
}
} }
cond_resched_rcu(); cond_resched_rcu();
} }
...@@ -1325,15 +1340,19 @@ static void ip_vs_conn_flush(struct netns_ipvs *ipvs) ...@@ -1325,15 +1340,19 @@ static void ip_vs_conn_flush(struct netns_ipvs *ipvs)
hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[idx], c_list) { hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[idx], c_list) {
if (cp->ipvs != ipvs) if (cp->ipvs != ipvs)
continue; continue;
IP_VS_DBG(4, "del connection\n"); /* As timers are expired in LIFO order, restart
ip_vs_conn_expire_now(cp); * the timer of controlling connection first, so
* that it is expired after us.
*/
cp_c = cp->control; cp_c = cp->control;
/* cp->control is valid only with reference to cp */ /* cp->control is valid only with reference to cp */
if (cp_c && __ip_vs_conn_get(cp)) { if (cp_c && __ip_vs_conn_get(cp)) {
IP_VS_DBG(4, "del conn template\n"); IP_VS_DBG(4, "del controlling connection\n");
ip_vs_conn_expire_now(cp_c); ip_vs_conn_expire_now(cp_c);
__ip_vs_conn_put(cp); __ip_vs_conn_put(cp);
} }
IP_VS_DBG(4, "del connection\n");
ip_vs_conn_expire_now(cp);
} }
cond_resched_rcu(); cond_resched_rcu();
} }
......
...@@ -42,6 +42,11 @@ ...@@ -42,6 +42,11 @@
static struct ip_vs_protocol *ip_vs_proto_table[IP_VS_PROTO_TAB_SIZE]; static struct ip_vs_protocol *ip_vs_proto_table[IP_VS_PROTO_TAB_SIZE];
/* States for conn templates: NONE or words separated with ",", max 15 chars */
static const char *ip_vs_ctpl_state_name_table[IP_VS_CTPL_S_LAST] = {
[IP_VS_CTPL_S_NONE] = "NONE",
[IP_VS_CTPL_S_ASSURED] = "ASSURED",
};
/* /*
* register an ipvs protocol * register an ipvs protocol
...@@ -193,12 +198,20 @@ ip_vs_create_timeout_table(int *table, int size) ...@@ -193,12 +198,20 @@ ip_vs_create_timeout_table(int *table, int size)
} }
const char * ip_vs_state_name(__u16 proto, int state) const char *ip_vs_state_name(const struct ip_vs_conn *cp)
{ {
struct ip_vs_protocol *pp = ip_vs_proto_get(proto); unsigned int state = cp->state;
struct ip_vs_protocol *pp;
if (cp->flags & IP_VS_CONN_F_TEMPLATE) {
if (state >= IP_VS_CTPL_S_LAST)
return "ERR!";
return ip_vs_ctpl_state_name_table[state] ? : "?";
}
pp = ip_vs_proto_get(cp->protocol);
if (pp == NULL || pp->state_name == NULL) if (pp == NULL || pp->state_name == NULL)
return (IPPROTO_IP == proto) ? "NONE" : "ERR!"; return (cp->protocol == IPPROTO_IP) ? "NONE" : "ERR!";
return pp->state_name(state); return pp->state_name(state);
} }
......
...@@ -461,6 +461,8 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp, ...@@ -461,6 +461,8 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
cp->flags &= ~IP_VS_CONN_F_INACTIVE; cp->flags &= ~IP_VS_CONN_F_INACTIVE;
} }
} }
if (next_state == IP_VS_SCTP_S_ESTABLISHED)
ip_vs_control_assure_ct(cp);
} }
if (likely(pd)) if (likely(pd))
cp->timeout = pd->timeout_table[cp->state = next_state]; cp->timeout = pd->timeout_table[cp->state = next_state];
......
...@@ -569,6 +569,8 @@ set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp, ...@@ -569,6 +569,8 @@ set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
cp->flags &= ~IP_VS_CONN_F_INACTIVE; cp->flags &= ~IP_VS_CONN_F_INACTIVE;
} }
} }
if (new_state == IP_VS_TCP_S_ESTABLISHED)
ip_vs_control_assure_ct(cp);
} }
if (likely(pd)) if (likely(pd))
......
...@@ -460,6 +460,8 @@ udp_state_transition(struct ip_vs_conn *cp, int direction, ...@@ -460,6 +460,8 @@ udp_state_transition(struct ip_vs_conn *cp, int direction,
} }
cp->timeout = pd->timeout_table[IP_VS_UDP_S_NORMAL]; cp->timeout = pd->timeout_table[IP_VS_UDP_S_NORMAL];
if (direction == IP_VS_DIR_OUTPUT)
ip_vs_control_assure_ct(cp);
} }
static int __udp_init(struct netns_ipvs *ipvs, struct ip_vs_proto_data *pd) static int __udp_init(struct netns_ipvs *ipvs, struct ip_vs_proto_data *pd)
......
...@@ -1003,12 +1003,9 @@ static void ip_vs_process_message_v0(struct netns_ipvs *ipvs, const char *buffer ...@@ -1003,12 +1003,9 @@ static void ip_vs_process_message_v0(struct netns_ipvs *ipvs, const char *buffer
continue; continue;
} }
} else { } else {
/* protocol in templates is not used for state/timeout */ if (state >= IP_VS_CTPL_S_LAST)
if (state > 0) { IP_VS_DBG(7, "BACKUP v0, Invalid tpl state %u\n",
IP_VS_DBG(2, "BACKUP v0, Invalid template state %u\n", state);
state);
state = 0;
}
} }
ip_vs_conn_fill_param(ipvs, AF_INET, s->protocol, ip_vs_conn_fill_param(ipvs, AF_INET, s->protocol,
...@@ -1166,12 +1163,9 @@ static inline int ip_vs_proc_sync_conn(struct netns_ipvs *ipvs, __u8 *p, __u8 *m ...@@ -1166,12 +1163,9 @@ static inline int ip_vs_proc_sync_conn(struct netns_ipvs *ipvs, __u8 *p, __u8 *m
goto out; goto out;
} }
} else { } else {
/* protocol in templates is not used for state/timeout */ if (state >= IP_VS_CTPL_S_LAST)
if (state > 0) { IP_VS_DBG(7, "BACKUP, Invalid tpl state %u\n",
IP_VS_DBG(3, "BACKUP, Invalid template state %u\n", state);
state);
state = 0;
}
} }
if (ip_vs_conn_fill_param_sync(ipvs, af, s, &param, pe_data, if (ip_vs_conn_fill_param_sync(ipvs, af, s, &param, pe_data,
pe_data_len, pe_name, pe_name_len)) { pe_data_len, pe_name, pe_name_len)) {
......
This diff is collapsed.
This diff is collapsed.
...@@ -610,7 +610,6 @@ static int exp_seq_show(struct seq_file *s, void *v) ...@@ -610,7 +610,6 @@ static int exp_seq_show(struct seq_file *s, void *v)
expect->tuple.src.l3num, expect->tuple.src.l3num,
expect->tuple.dst.protonum); expect->tuple.dst.protonum);
print_tuple(s, &expect->tuple, print_tuple(s, &expect->tuple,
__nf_ct_l3proto_find(expect->tuple.src.l3num),
__nf_ct_l4proto_find(expect->tuple.src.l3num, __nf_ct_l4proto_find(expect->tuple.src.l3num,
expect->tuple.dst.protonum)); expect->tuple.dst.protonum));
......
...@@ -24,7 +24,6 @@ ...@@ -24,7 +24,6 @@
#include <linux/rtnetlink.h> #include <linux/rtnetlink.h>
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
...@@ -193,8 +192,7 @@ void nf_conntrack_helper_put(struct nf_conntrack_helper *helper) ...@@ -193,8 +192,7 @@ void nf_conntrack_helper_put(struct nf_conntrack_helper *helper)
EXPORT_SYMBOL_GPL(nf_conntrack_helper_put); EXPORT_SYMBOL_GPL(nf_conntrack_helper_put);
struct nf_conn_help * struct nf_conn_help *
nf_ct_helper_ext_add(struct nf_conn *ct, nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp)
struct nf_conntrack_helper *helper, gfp_t gfp)
{ {
struct nf_conn_help *help; struct nf_conn_help *help;
...@@ -263,7 +261,7 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, ...@@ -263,7 +261,7 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
} }
if (help == NULL) { if (help == NULL) {
help = nf_ct_helper_ext_add(ct, helper, flags); help = nf_ct_helper_ext_add(ct, flags);
if (help == NULL) if (help == NULL)
return -ENOMEM; return -ENOMEM;
} else { } else {
......
/*
* (C) 2003,2004 USAGI/WIDE Project <http://www.linux-ipv6.org>
*
* Based largely upon the original ip_conntrack code which
* had the following copyright information:
*
* (C) 1999-2001 Paul `Rusty' Russell
* (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Author:
* Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
*/
#include <linux/types.h>
#include <linux/ip.h>
#include <linux/netfilter.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/icmp.h>
#include <linux/sysctl.h>
#include <net/ip.h>
#include <linux/netfilter_ipv4.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
static bool generic_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
struct nf_conntrack_tuple *tuple)
{
memset(&tuple->src.u3, 0, sizeof(tuple->src.u3));
memset(&tuple->dst.u3, 0, sizeof(tuple->dst.u3));
return true;
}
static bool generic_invert_tuple(struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *orig)
{
memset(&tuple->src.u3, 0, sizeof(tuple->src.u3));
memset(&tuple->dst.u3, 0, sizeof(tuple->dst.u3));
return true;
}
static int generic_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
unsigned int *dataoff, u_int8_t *protonum)
{
/* Never track !!! */
return -NF_ACCEPT;
}
struct nf_conntrack_l3proto nf_conntrack_l3proto_generic __read_mostly = {
.l3proto = PF_UNSPEC,
.pkt_to_tuple = generic_pkt_to_tuple,
.invert_tuple = generic_invert_tuple,
.get_l4proto = generic_get_l4proto,
};
EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_generic);
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
#include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_seqadj.h> #include <net/netfilter/nf_conntrack_seqadj.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_tuple.h> #include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_acct.h> #include <net/netfilter/nf_conntrack_acct.h>
...@@ -81,9 +80,26 @@ static int ctnetlink_dump_tuples_proto(struct sk_buff *skb, ...@@ -81,9 +80,26 @@ static int ctnetlink_dump_tuples_proto(struct sk_buff *skb,
return -1; return -1;
} }
static int ipv4_tuple_to_nlattr(struct sk_buff *skb,
const struct nf_conntrack_tuple *tuple)
{
if (nla_put_in_addr(skb, CTA_IP_V4_SRC, tuple->src.u3.ip) ||
nla_put_in_addr(skb, CTA_IP_V4_DST, tuple->dst.u3.ip))
return -EMSGSIZE;
return 0;
}
static int ipv6_tuple_to_nlattr(struct sk_buff *skb,
const struct nf_conntrack_tuple *tuple)
{
if (nla_put_in6_addr(skb, CTA_IP_V6_SRC, &tuple->src.u3.in6) ||
nla_put_in6_addr(skb, CTA_IP_V6_DST, &tuple->dst.u3.in6))
return -EMSGSIZE;
return 0;
}
static int ctnetlink_dump_tuples_ip(struct sk_buff *skb, static int ctnetlink_dump_tuples_ip(struct sk_buff *skb,
const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_tuple *tuple)
const struct nf_conntrack_l3proto *l3proto)
{ {
int ret = 0; int ret = 0;
struct nlattr *nest_parms; struct nlattr *nest_parms;
...@@ -92,8 +108,14 @@ static int ctnetlink_dump_tuples_ip(struct sk_buff *skb, ...@@ -92,8 +108,14 @@ static int ctnetlink_dump_tuples_ip(struct sk_buff *skb,
if (!nest_parms) if (!nest_parms)
goto nla_put_failure; goto nla_put_failure;
if (likely(l3proto->tuple_to_nlattr)) switch (tuple->src.l3num) {
ret = l3proto->tuple_to_nlattr(skb, tuple); case NFPROTO_IPV4:
ret = ipv4_tuple_to_nlattr(skb, tuple);
break;
case NFPROTO_IPV6:
ret = ipv6_tuple_to_nlattr(skb, tuple);
break;
}
nla_nest_end(skb, nest_parms); nla_nest_end(skb, nest_parms);
...@@ -106,13 +128,11 @@ static int ctnetlink_dump_tuples_ip(struct sk_buff *skb, ...@@ -106,13 +128,11 @@ static int ctnetlink_dump_tuples_ip(struct sk_buff *skb,
static int ctnetlink_dump_tuples(struct sk_buff *skb, static int ctnetlink_dump_tuples(struct sk_buff *skb,
const struct nf_conntrack_tuple *tuple) const struct nf_conntrack_tuple *tuple)
{ {
const struct nf_conntrack_l3proto *l3proto;
const struct nf_conntrack_l4proto *l4proto; const struct nf_conntrack_l4proto *l4proto;
int ret; int ret;
rcu_read_lock(); rcu_read_lock();
l3proto = __nf_ct_l3proto_find(tuple->src.l3num); ret = ctnetlink_dump_tuples_ip(skb, tuple);
ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto);
if (ret >= 0) { if (ret >= 0) {
l4proto = __nf_ct_l4proto_find(tuple->src.l3num, l4proto = __nf_ct_l4proto_find(tuple->src.l3num,
...@@ -556,15 +576,20 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, ...@@ -556,15 +576,20 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
return -1; return -1;
} }
static const struct nla_policy cta_ip_nla_policy[CTA_IP_MAX + 1] = {
[CTA_IP_V4_SRC] = { .type = NLA_U32 },
[CTA_IP_V4_DST] = { .type = NLA_U32 },
[CTA_IP_V6_SRC] = { .len = sizeof(__be32) * 4 },
[CTA_IP_V6_DST] = { .len = sizeof(__be32) * 4 },
};
#if defined(CONFIG_NETFILTER_NETLINK_GLUE_CT) || defined(CONFIG_NF_CONNTRACK_EVENTS) #if defined(CONFIG_NETFILTER_NETLINK_GLUE_CT) || defined(CONFIG_NF_CONNTRACK_EVENTS)
static size_t ctnetlink_proto_size(const struct nf_conn *ct) static size_t ctnetlink_proto_size(const struct nf_conn *ct)
{ {
const struct nf_conntrack_l3proto *l3proto;
const struct nf_conntrack_l4proto *l4proto; const struct nf_conntrack_l4proto *l4proto;
size_t len, len4 = 0; size_t len, len4 = 0;
l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct)); len = nla_policy_len(cta_ip_nla_policy, CTA_IP_MAX + 1);
len = l3proto->nla_size;
len *= 3u; /* ORIG, REPLY, MASTER */ len *= 3u; /* ORIG, REPLY, MASTER */
l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
...@@ -936,29 +961,54 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -936,29 +961,54 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
return skb->len; return skb->len;
} }
static int ipv4_nlattr_to_tuple(struct nlattr *tb[],
struct nf_conntrack_tuple *t)
{
if (!tb[CTA_IP_V4_SRC] || !tb[CTA_IP_V4_DST])
return -EINVAL;
t->src.u3.ip = nla_get_in_addr(tb[CTA_IP_V4_SRC]);
t->dst.u3.ip = nla_get_in_addr(tb[CTA_IP_V4_DST]);
return 0;
}
static int ipv6_nlattr_to_tuple(struct nlattr *tb[],
struct nf_conntrack_tuple *t)
{
if (!tb[CTA_IP_V6_SRC] || !tb[CTA_IP_V6_DST])
return -EINVAL;
t->src.u3.in6 = nla_get_in6_addr(tb[CTA_IP_V6_SRC]);
t->dst.u3.in6 = nla_get_in6_addr(tb[CTA_IP_V6_DST]);
return 0;
}
static int ctnetlink_parse_tuple_ip(struct nlattr *attr, static int ctnetlink_parse_tuple_ip(struct nlattr *attr,
struct nf_conntrack_tuple *tuple) struct nf_conntrack_tuple *tuple)
{ {
struct nlattr *tb[CTA_IP_MAX+1]; struct nlattr *tb[CTA_IP_MAX+1];
struct nf_conntrack_l3proto *l3proto;
int ret = 0; int ret = 0;
ret = nla_parse_nested(tb, CTA_IP_MAX, attr, NULL, NULL); ret = nla_parse_nested(tb, CTA_IP_MAX, attr, NULL, NULL);
if (ret < 0) if (ret < 0)
return ret; return ret;
rcu_read_lock(); ret = nla_validate_nested(attr, CTA_IP_MAX,
l3proto = __nf_ct_l3proto_find(tuple->src.l3num); cta_ip_nla_policy, NULL);
if (ret)
return ret;
if (likely(l3proto->nlattr_to_tuple)) { switch (tuple->src.l3num) {
ret = nla_validate_nested(attr, CTA_IP_MAX, case NFPROTO_IPV4:
l3proto->nla_policy, NULL); ret = ipv4_nlattr_to_tuple(tb, tuple);
if (ret == 0) break;
ret = l3proto->nlattr_to_tuple(tb, tuple); case NFPROTO_IPV6:
ret = ipv6_nlattr_to_tuple(tb, tuple);
break;
} }
rcu_read_unlock();
return ret; return ret;
} }
...@@ -1897,7 +1947,7 @@ ctnetlink_create_conntrack(struct net *net, ...@@ -1897,7 +1947,7 @@ ctnetlink_create_conntrack(struct net *net,
} else { } else {
struct nf_conn_help *help; struct nf_conn_help *help;
help = nf_ct_helper_ext_add(ct, helper, GFP_ATOMIC); help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
if (help == NULL) { if (help == NULL) {
err = -ENOMEM; err = -ENOMEM;
goto err2; goto err2;
...@@ -2581,7 +2631,6 @@ static int ctnetlink_exp_dump_mask(struct sk_buff *skb, ...@@ -2581,7 +2631,6 @@ static int ctnetlink_exp_dump_mask(struct sk_buff *skb,
const struct nf_conntrack_tuple *tuple, const struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple_mask *mask) const struct nf_conntrack_tuple_mask *mask)
{ {
const struct nf_conntrack_l3proto *l3proto;
const struct nf_conntrack_l4proto *l4proto; const struct nf_conntrack_l4proto *l4proto;
struct nf_conntrack_tuple m; struct nf_conntrack_tuple m;
struct nlattr *nest_parms; struct nlattr *nest_parms;
...@@ -2597,8 +2646,7 @@ static int ctnetlink_exp_dump_mask(struct sk_buff *skb, ...@@ -2597,8 +2646,7 @@ static int ctnetlink_exp_dump_mask(struct sk_buff *skb,
goto nla_put_failure; goto nla_put_failure;
rcu_read_lock(); rcu_read_lock();
l3proto = __nf_ct_l3proto_find(tuple->src.l3num); ret = ctnetlink_dump_tuples_ip(skb, &m);
ret = ctnetlink_dump_tuples_ip(skb, &m, l3proto);
if (ret >= 0) { if (ret >= 0) {
l4proto = __nf_ct_l4proto_find(tuple->src.l3num, l4proto = __nf_ct_l4proto_find(tuple->src.l3num,
tuple->dst.protonum); tuple->dst.protonum);
......
This diff is collapsed.
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_ecache.h> #include <net/netfilter/nf_conntrack_ecache.h>
#include <net/netfilter/nf_conntrack_timeout.h>
#include <net/netfilter/nf_log.h> #include <net/netfilter/nf_log.h>
/* Timeouts are based on values from RFC4340: /* Timeouts are based on values from RFC4340:
...@@ -388,31 +389,8 @@ static inline struct nf_dccp_net *dccp_pernet(struct net *net) ...@@ -388,31 +389,8 @@ static inline struct nf_dccp_net *dccp_pernet(struct net *net)
return &net->ct.nf_ct_proto.dccp; return &net->ct.nf_ct_proto.dccp;
} }
static bool dccp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
struct net *net, struct nf_conntrack_tuple *tuple)
{
struct dccp_hdr _hdr, *dh;
/* Actually only need first 4 bytes to get ports. */
dh = skb_header_pointer(skb, dataoff, 4, &_hdr);
if (dh == NULL)
return false;
tuple->src.u.dccp.port = dh->dccph_sport;
tuple->dst.u.dccp.port = dh->dccph_dport;
return true;
}
static bool dccp_invert_tuple(struct nf_conntrack_tuple *inv,
const struct nf_conntrack_tuple *tuple)
{
inv->src.u.dccp.port = tuple->dst.u.dccp.port;
inv->dst.u.dccp.port = tuple->src.u.dccp.port;
return true;
}
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 *timeouts) unsigned int dataoff)
{ {
struct net *net = nf_ct_net(ct); struct net *net = nf_ct_net(ct);
struct nf_dccp_net *dn; struct nf_dccp_net *dn;
...@@ -460,19 +438,14 @@ static u64 dccp_ack_seq(const struct dccp_hdr *dh) ...@@ -460,19 +438,14 @@ 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)
unsigned int *timeouts)
{ {
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;
enum ct_dccp_roles role; enum ct_dccp_roles role;
unsigned int *timeouts;
dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh); dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
BUG_ON(dh == NULL); BUG_ON(dh == NULL);
...@@ -546,6 +519,9 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb, ...@@ -546,6 +519,9 @@ 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);
timeouts = nf_ct_timeout_lookup(ct);
if (!timeouts)
timeouts = dccp_pernet(nf_ct_net(ct))->dccp_timeout;
nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]); nf_ct_refresh_acct(ct, ctinfo, skb, timeouts[new_state]);
return NF_ACCEPT; return NF_ACCEPT;
...@@ -864,11 +840,8 @@ static struct nf_proto_net *dccp_get_net_proto(struct net *net) ...@@ -864,11 +840,8 @@ static struct nf_proto_net *dccp_get_net_proto(struct net *net)
const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 = { const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4 = {
.l3proto = AF_INET, .l3proto = AF_INET,
.l4proto = IPPROTO_DCCP, .l4proto = IPPROTO_DCCP,
.pkt_to_tuple = dccp_pkt_to_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,
.can_early_drop = dccp_can_early_drop, .can_early_drop = dccp_can_early_drop,
#ifdef CONFIG_NF_CONNTRACK_PROCFS #ifdef CONFIG_NF_CONNTRACK_PROCFS
...@@ -900,11 +873,8 @@ EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_dccp4); ...@@ -900,11 +873,8 @@ EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_dccp4);
const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 = { const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6 = {
.l3proto = AF_INET6, .l3proto = AF_INET6,
.l4proto = IPPROTO_DCCP, .l4proto = IPPROTO_DCCP,
.pkt_to_tuple = dccp_pkt_to_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,
.can_early_drop = dccp_can_early_drop, .can_early_drop = dccp_can_early_drop,
#ifdef CONFIG_NF_CONNTRACK_PROCFS #ifdef CONFIG_NF_CONNTRACK_PROCFS
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/timer.h> #include <linux/timer.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_timeout.h>
static const unsigned int nf_ct_generic_timeout = 600*HZ; static const unsigned int nf_ct_generic_timeout = 600*HZ;
...@@ -41,34 +42,24 @@ static bool generic_pkt_to_tuple(const struct sk_buff *skb, ...@@ -41,34 +42,24 @@ static bool generic_pkt_to_tuple(const struct sk_buff *skb,
return true; return true;
} }
static bool generic_invert_tuple(struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *orig)
{
tuple->src.u.all = 0;
tuple->dst.u.all = 0;
return true;
}
static unsigned int *generic_get_timeouts(struct net *net)
{
return &(generic_pernet(net)->timeout);
}
/* Returns verdict for packet, or -1 for invalid. */ /* Returns verdict for packet, or -1 for invalid. */
static int generic_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)
unsigned int *timeout)
{ {
const unsigned int *timeout = nf_ct_timeout_lookup(ct);
if (!timeout)
timeout = &generic_pernet(nf_ct_net(ct))->timeout;
nf_ct_refresh_acct(ct, ctinfo, skb, *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 generic_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 *timeouts) unsigned int dataoff)
{ {
bool ret; bool ret;
...@@ -87,8 +78,11 @@ static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb, ...@@ -87,8 +78,11 @@ static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb,
static int generic_timeout_nlattr_to_obj(struct nlattr *tb[], static int generic_timeout_nlattr_to_obj(struct nlattr *tb[],
struct net *net, void *data) struct net *net, void *data)
{ {
unsigned int *timeout = data;
struct nf_generic_net *gn = generic_pernet(net); struct nf_generic_net *gn = generic_pernet(net);
unsigned int *timeout = data;
if (!timeout)
timeout = &gn->timeout;
if (tb[CTA_TIMEOUT_GENERIC_TIMEOUT]) if (tb[CTA_TIMEOUT_GENERIC_TIMEOUT])
*timeout = *timeout =
...@@ -168,9 +162,7 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = ...@@ -168,9 +162,7 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic =
.l3proto = PF_UNSPEC, .l3proto = PF_UNSPEC,
.l4proto = 255, .l4proto = 255,
.pkt_to_tuple = generic_pkt_to_tuple, .pkt_to_tuple = generic_pkt_to_tuple,
.invert_tuple = generic_invert_tuple,
.packet = generic_packet, .packet = generic_packet,
.get_timeouts = generic_get_timeouts,
.new = generic_new, .new = generic_new,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) #if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
.ctnl_timeout = { .ctnl_timeout = {
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_timeout.h>
#include <linux/netfilter/nf_conntrack_proto_gre.h> #include <linux/netfilter/nf_conntrack_proto_gre.h>
#include <linux/netfilter/nf_conntrack_pptp.h> #include <linux/netfilter/nf_conntrack_pptp.h>
...@@ -179,15 +180,6 @@ EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_destroy); ...@@ -179,15 +180,6 @@ EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_destroy);
/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */ /* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
/* invert gre part of tuple */
static bool gre_invert_tuple(struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *orig)
{
tuple->dst.u.gre.key = orig->src.u.gre.key;
tuple->src.u.gre.key = orig->dst.u.gre.key;
return true;
}
/* gre hdr info to tuple */ /* gre hdr info to tuple */
static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
struct net *net, struct nf_conntrack_tuple *tuple) struct net *net, struct nf_conntrack_tuple *tuple)
...@@ -243,8 +235,7 @@ static unsigned int *gre_get_timeouts(struct net *net) ...@@ -243,8 +235,7 @@ static unsigned int *gre_get_timeouts(struct net *net)
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)
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. */
...@@ -263,8 +254,13 @@ static int gre_packet(struct nf_conn *ct, ...@@ -263,8 +254,13 @@ 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 *timeouts) unsigned int dataoff)
{ {
unsigned int *timeouts = nf_ct_timeout_lookup(ct);
if (!timeouts)
timeouts = gre_get_timeouts(nf_ct_net(ct));
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);
...@@ -300,6 +296,8 @@ static int gre_timeout_nlattr_to_obj(struct nlattr *tb[], ...@@ -300,6 +296,8 @@ static int gre_timeout_nlattr_to_obj(struct nlattr *tb[],
unsigned int *timeouts = data; unsigned int *timeouts = data;
struct netns_proto_gre *net_gre = gre_pernet(net); struct netns_proto_gre *net_gre = gre_pernet(net);
if (!timeouts)
timeouts = gre_get_timeouts(net);
/* set default timeouts for GRE. */ /* set default timeouts for GRE. */
timeouts[GRE_CT_UNREPLIED] = net_gre->gre_timeouts[GRE_CT_UNREPLIED]; timeouts[GRE_CT_UNREPLIED] = net_gre->gre_timeouts[GRE_CT_UNREPLIED];
timeouts[GRE_CT_REPLIED] = net_gre->gre_timeouts[GRE_CT_REPLIED]; timeouts[GRE_CT_REPLIED] = net_gre->gre_timeouts[GRE_CT_REPLIED];
...@@ -356,11 +354,9 @@ static const struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = { ...@@ -356,11 +354,9 @@ static const struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = {
.l3proto = AF_INET, .l3proto = AF_INET,
.l4proto = IPPROTO_GRE, .l4proto = IPPROTO_GRE,
.pkt_to_tuple = gre_pkt_to_tuple, .pkt_to_tuple = gre_pkt_to_tuple,
.invert_tuple = gre_invert_tuple,
#ifdef CONFIG_NF_CONNTRACK_PROCFS #ifdef CONFIG_NF_CONNTRACK_PROCFS
.print_conntrack = gre_print_conntrack, .print_conntrack = gre_print_conntrack,
#endif #endif
.get_timeouts = gre_get_timeouts,
.packet = gre_packet, .packet = gre_packet,
.new = gre_new, .new = gre_new,
.destroy = gre_destroy, .destroy = gre_destroy,
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <net/netfilter/nf_conntrack_tuple.h> #include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_timeout.h>
#include <net/netfilter/nf_conntrack_zones.h> #include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/nf_log.h> #include <net/netfilter/nf_log.h>
...@@ -80,12 +81,16 @@ static unsigned int *icmp_get_timeouts(struct net *net) ...@@ -80,12 +81,16 @@ static unsigned int *icmp_get_timeouts(struct net *net)
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)
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. */
unsigned int *timeout = nf_ct_timeout_lookup(ct);
if (!timeout)
timeout = icmp_get_timeouts(nf_ct_net(ct));
nf_ct_refresh_acct(ct, ctinfo, skb, *timeout); nf_ct_refresh_acct(ct, ctinfo, skb, *timeout);
return NF_ACCEPT; return NF_ACCEPT;
...@@ -93,7 +98,7 @@ static int icmp_packet(struct nf_conn *ct, ...@@ -93,7 +98,7 @@ static int icmp_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 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 *timeouts) unsigned int dataoff)
{ {
static const u_int8_t valid_new[] = { static const u_int8_t valid_new[] = {
[ICMP_ECHO] = 1, [ICMP_ECHO] = 1,
...@@ -142,8 +147,7 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb, ...@@ -142,8 +147,7 @@ icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
/* Ordinarily, we'd expect the inverted tupleproto, but it's /* Ordinarily, we'd expect the inverted tupleproto, but it's
been preserved inside the ICMP. */ been preserved inside the ICMP. */
if (!nf_ct_invert_tuple(&innertuple, &origtuple, if (!nf_ct_invert_tuple(&innertuple, &origtuple, innerproto)) {
&nf_conntrack_l3proto_ipv4, innerproto)) {
pr_debug("icmp_error_message: no match\n"); pr_debug("icmp_error_message: no match\n");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
...@@ -281,9 +285,11 @@ static int icmp_timeout_nlattr_to_obj(struct nlattr *tb[], ...@@ -281,9 +285,11 @@ static int icmp_timeout_nlattr_to_obj(struct nlattr *tb[],
struct nf_icmp_net *in = icmp_pernet(net); struct nf_icmp_net *in = icmp_pernet(net);
if (tb[CTA_TIMEOUT_ICMP_TIMEOUT]) { if (tb[CTA_TIMEOUT_ICMP_TIMEOUT]) {
if (!timeout)
timeout = &in->timeout;
*timeout = *timeout =
ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMP_TIMEOUT])) * HZ; ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMP_TIMEOUT])) * HZ;
} else { } else if (timeout) {
/* Set default ICMP timeout. */ /* Set default ICMP timeout. */
*timeout = in->timeout; *timeout = in->timeout;
} }
...@@ -358,7 +364,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = ...@@ -358,7 +364,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp =
.pkt_to_tuple = icmp_pkt_to_tuple, .pkt_to_tuple = icmp_pkt_to_tuple,
.invert_tuple = icmp_invert_tuple, .invert_tuple = icmp_invert_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,
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include <net/netfilter/nf_conntrack_tuple.h> #include <net/netfilter/nf_conntrack_tuple.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_timeout.h>
#include <net/netfilter/nf_conntrack_zones.h> #include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/ipv6/nf_conntrack_icmpv6.h> #include <net/netfilter/ipv6/nf_conntrack_icmpv6.h>
#include <net/netfilter/nf_log.h> #include <net/netfilter/nf_log.h>
...@@ -93,9 +94,13 @@ static unsigned int *icmpv6_get_timeouts(struct net *net) ...@@ -93,9 +94,13 @@ static unsigned int *icmpv6_get_timeouts(struct net *net)
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)
unsigned int *timeout)
{ {
unsigned int *timeout = nf_ct_timeout_lookup(ct);
if (!timeout)
timeout = icmpv6_get_timeouts(nf_ct_net(ct));
/* 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. */
...@@ -106,7 +111,7 @@ static int icmpv6_packet(struct nf_conn *ct, ...@@ -106,7 +111,7 @@ static int icmpv6_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 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 *timeouts) unsigned int dataoff)
{ {
static const u_int8_t valid_new[] = { static const u_int8_t valid_new[] = {
[ICMPV6_ECHO_REQUEST - 128] = 1, [ICMPV6_ECHO_REQUEST - 128] = 1,
...@@ -152,8 +157,7 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl, ...@@ -152,8 +157,7 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl,
/* Ordinarily, we'd expect the inverted tupleproto, but it's /* Ordinarily, we'd expect the inverted tupleproto, but it's
been preserved inside the ICMP. */ been preserved inside the ICMP. */
if (!nf_ct_invert_tuple(&intuple, &origtuple, if (!nf_ct_invert_tuple(&intuple, &origtuple, inproto)) {
&nf_conntrack_l3proto_ipv6, inproto)) {
pr_debug("icmpv6_error: Can't invert tuple\n"); pr_debug("icmpv6_error: Can't invert tuple\n");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
...@@ -281,6 +285,8 @@ static int icmpv6_timeout_nlattr_to_obj(struct nlattr *tb[], ...@@ -281,6 +285,8 @@ static int icmpv6_timeout_nlattr_to_obj(struct nlattr *tb[],
unsigned int *timeout = data; unsigned int *timeout = data;
struct nf_icmp_net *in = icmpv6_pernet(net); struct nf_icmp_net *in = icmpv6_pernet(net);
if (!timeout)
timeout = icmpv6_get_timeouts(net);
if (tb[CTA_TIMEOUT_ICMPV6_TIMEOUT]) { if (tb[CTA_TIMEOUT_ICMPV6_TIMEOUT]) {
*timeout = *timeout =
ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMPV6_TIMEOUT])) * HZ; ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMPV6_TIMEOUT])) * HZ;
...@@ -359,7 +365,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = ...@@ -359,7 +365,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 =
.pkt_to_tuple = icmpv6_pkt_to_tuple, .pkt_to_tuple = icmpv6_pkt_to_tuple,
.invert_tuple = icmpv6_invert_tuple, .invert_tuple = icmpv6_invert_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 IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_ecache.h> #include <net/netfilter/nf_conntrack_ecache.h>
#include <net/netfilter/nf_conntrack_timeout.h>
/* FIXME: Examine ipfilter's timeouts and conntrack transitions more /* FIXME: Examine ipfilter's timeouts and conntrack transitions more
closely. They're more complex. --RR closely. They're more complex. --RR
...@@ -150,30 +151,6 @@ static inline struct nf_sctp_net *sctp_pernet(struct net *net) ...@@ -150,30 +151,6 @@ static inline struct nf_sctp_net *sctp_pernet(struct net *net)
return &net->ct.nf_ct_proto.sctp; return &net->ct.nf_ct_proto.sctp;
} }
static bool sctp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
struct net *net, struct nf_conntrack_tuple *tuple)
{
const struct sctphdr *hp;
struct sctphdr _hdr;
/* Actually only need first 4 bytes to get ports. */
hp = skb_header_pointer(skb, dataoff, 4, &_hdr);
if (hp == NULL)
return false;
tuple->src.u.sctp.port = hp->source;
tuple->dst.u.sctp.port = hp->dest;
return true;
}
static bool sctp_invert_tuple(struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *orig)
{
tuple->src.u.sctp.port = orig->dst.u.sctp.port;
tuple->dst.u.sctp.port = orig->src.u.sctp.port;
return true;
}
#ifdef CONFIG_NF_CONNTRACK_PROCFS #ifdef CONFIG_NF_CONNTRACK_PROCFS
/* Print out the private part of the conntrack. */ /* Print out the private part of the conntrack. */
static void sctp_print_conntrack(struct seq_file *s, struct nf_conn *ct) static void sctp_print_conntrack(struct seq_file *s, struct nf_conn *ct)
...@@ -296,17 +273,11 @@ static int sctp_new_state(enum ip_conntrack_dir dir, ...@@ -296,17 +273,11 @@ 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_pernet(net)->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)
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);
...@@ -315,6 +286,7 @@ static int sctp_packet(struct nf_conn *ct, ...@@ -315,6 +286,7 @@ static int sctp_packet(struct nf_conn *ct,
const struct sctp_chunkhdr *sch; const struct sctp_chunkhdr *sch;
struct sctp_chunkhdr _sch; struct sctp_chunkhdr _sch;
u_int32_t offset, count; u_int32_t offset, count;
unsigned int *timeouts;
unsigned long map[256 / sizeof(unsigned long)] = { 0 }; unsigned long map[256 / sizeof(unsigned long)] = { 0 };
sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph); sh = skb_header_pointer(skb, dataoff, sizeof(_sctph), &_sctph);
...@@ -403,6 +375,10 @@ static int sctp_packet(struct nf_conn *ct, ...@@ -403,6 +375,10 @@ static int sctp_packet(struct nf_conn *ct,
} }
spin_unlock_bh(&ct->lock); spin_unlock_bh(&ct->lock);
timeouts = nf_ct_timeout_lookup(ct);
if (!timeouts)
timeouts = sctp_pernet(nf_ct_net(ct))->timeouts;
nf_ct_refresh_acct(ct, ctinfo, skb, 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 &&
...@@ -423,7 +399,7 @@ static int sctp_packet(struct nf_conn *ct, ...@@ -423,7 +399,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 *timeouts) unsigned int dataoff)
{ {
enum sctp_conntrack new_state; enum sctp_conntrack new_state;
const struct sctphdr *sh; const struct sctphdr *sh;
...@@ -780,13 +756,10 @@ static struct nf_proto_net *sctp_get_net_proto(struct net *net) ...@@ -780,13 +756,10 @@ static struct nf_proto_net *sctp_get_net_proto(struct net *net)
const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = { const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4 = {
.l3proto = PF_INET, .l3proto = PF_INET,
.l4proto = IPPROTO_SCTP, .l4proto = IPPROTO_SCTP,
.pkt_to_tuple = sctp_pkt_to_tuple,
.invert_tuple = sctp_invert_tuple,
#ifdef CONFIG_NF_CONNTRACK_PROCFS #ifdef CONFIG_NF_CONNTRACK_PROCFS
.print_conntrack = sctp_print_conntrack, .print_conntrack = sctp_print_conntrack,
#endif #endif
.packet = sctp_packet, .packet = sctp_packet,
.get_timeouts = sctp_get_timeouts,
.new = sctp_new, .new = sctp_new,
.error = sctp_error, .error = sctp_error,
.can_early_drop = sctp_can_early_drop, .can_early_drop = sctp_can_early_drop,
...@@ -817,13 +790,10 @@ EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_sctp4); ...@@ -817,13 +790,10 @@ EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_sctp4);
const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = { const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6 = {
.l3proto = PF_INET6, .l3proto = PF_INET6,
.l4proto = IPPROTO_SCTP, .l4proto = IPPROTO_SCTP,
.pkt_to_tuple = sctp_pkt_to_tuple,
.invert_tuple = sctp_invert_tuple,
#ifdef CONFIG_NF_CONNTRACK_PROCFS #ifdef CONFIG_NF_CONNTRACK_PROCFS
.print_conntrack = sctp_print_conntrack, .print_conntrack = sctp_print_conntrack,
#endif #endif
.packet = sctp_packet, .packet = sctp_packet,
.get_timeouts = sctp_get_timeouts,
.new = sctp_new, .new = sctp_new,
.error = sctp_error, .error = sctp_error,
.can_early_drop = sctp_can_early_drop, .can_early_drop = sctp_can_early_drop,
......
This diff is collapsed.
This diff is collapsed.
/* (C) 1999-2001 Paul `Rusty' Russell // SPDX-License-Identifier: GPL-2.0
* (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
* (C) 2005-2012 Patrick McHardy <kaber@trash.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/types.h> #include <linux/types.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -24,7 +16,6 @@ ...@@ -24,7 +16,6 @@
#include <net/netfilter/nf_conntrack.h> #include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_core.h> #include <net/netfilter/nf_conntrack_core.h>
#include <net/netfilter/nf_conntrack_l3proto.h>
#include <net/netfilter/nf_conntrack_l4proto.h> #include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_expect.h> #include <net/netfilter/nf_conntrack_expect.h>
#include <net/netfilter/nf_conntrack_helper.h> #include <net/netfilter/nf_conntrack_helper.h>
...@@ -33,15 +24,14 @@ ...@@ -33,15 +24,14 @@
#include <net/netfilter/nf_conntrack_timestamp.h> #include <net/netfilter/nf_conntrack_timestamp.h>
#include <linux/rculist_nulls.h> #include <linux/rculist_nulls.h>
MODULE_LICENSE("GPL"); unsigned int nf_conntrack_net_id __read_mostly;
#ifdef CONFIG_NF_CONNTRACK_PROCFS #ifdef CONFIG_NF_CONNTRACK_PROCFS
void void
print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple, print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_l3proto *l3proto,
const struct nf_conntrack_l4proto *l4proto) const struct nf_conntrack_l4proto *l4proto)
{ {
switch (l3proto->l3proto) { switch (tuple->src.l3num) {
case NFPROTO_IPV4: case NFPROTO_IPV4:
seq_printf(s, "src=%pI4 dst=%pI4 ", seq_printf(s, "src=%pI4 dst=%pI4 ",
&tuple->src.u3.ip, &tuple->dst.u3.ip); &tuple->src.u3.ip, &tuple->dst.u3.ip);
...@@ -282,7 +272,6 @@ static int ct_seq_show(struct seq_file *s, void *v) ...@@ -282,7 +272,6 @@ static int ct_seq_show(struct seq_file *s, void *v)
{ {
struct nf_conntrack_tuple_hash *hash = v; struct nf_conntrack_tuple_hash *hash = v;
struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash); struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(hash);
const struct nf_conntrack_l3proto *l3proto;
const struct nf_conntrack_l4proto *l4proto; const struct nf_conntrack_l4proto *l4proto;
struct net *net = seq_file_net(s); struct net *net = seq_file_net(s);
int ret = 0; int ret = 0;
...@@ -303,14 +292,12 @@ static int ct_seq_show(struct seq_file *s, void *v) ...@@ -303,14 +292,12 @@ static int ct_seq_show(struct seq_file *s, void *v)
if (!net_eq(nf_ct_net(ct), net)) if (!net_eq(nf_ct_net(ct), net))
goto release; goto release;
l3proto = __nf_ct_l3proto_find(nf_ct_l3num(ct));
WARN_ON(!l3proto);
l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
WARN_ON(!l4proto); WARN_ON(!l4proto);
ret = -ENOSPC; ret = -ENOSPC;
seq_printf(s, "%-8s %u %-8s %u ", seq_printf(s, "%-8s %u %-8s %u ",
l3proto_name(l3proto->l3proto), nf_ct_l3num(ct), l3proto_name(nf_ct_l3num(ct)), nf_ct_l3num(ct),
l4proto_name(l4proto->l4proto), nf_ct_protonum(ct)); l4proto_name(l4proto->l4proto), nf_ct_protonum(ct));
if (!test_bit(IPS_OFFLOAD_BIT, &ct->status)) if (!test_bit(IPS_OFFLOAD_BIT, &ct->status))
...@@ -320,7 +307,7 @@ static int ct_seq_show(struct seq_file *s, void *v) ...@@ -320,7 +307,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
l4proto->print_conntrack(s, ct); l4proto->print_conntrack(s, ct);
print_tuple(s, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, print_tuple(s, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
l3proto, l4proto); l4proto);
ct_show_zone(s, ct, NF_CT_ZONE_DIR_ORIG); ct_show_zone(s, ct, NF_CT_ZONE_DIR_ORIG);
...@@ -333,8 +320,7 @@ static int ct_seq_show(struct seq_file *s, void *v) ...@@ -333,8 +320,7 @@ static int ct_seq_show(struct seq_file *s, void *v)
if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status))) if (!(test_bit(IPS_SEEN_REPLY_BIT, &ct->status)))
seq_puts(s, "[UNREPLIED] "); seq_puts(s, "[UNREPLIED] ");
print_tuple(s, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, print_tuple(s, &ct->tuplehash[IP_CT_DIR_REPLY].tuple, l4proto);
l3proto, l4proto);
ct_show_zone(s, ct, NF_CT_ZONE_DIR_REPL); ct_show_zone(s, ct, NF_CT_ZONE_DIR_REPL);
...@@ -680,6 +666,8 @@ static void nf_conntrack_pernet_exit(struct list_head *net_exit_list) ...@@ -680,6 +666,8 @@ static void nf_conntrack_pernet_exit(struct list_head *net_exit_list)
static struct pernet_operations nf_conntrack_net_ops = { static struct pernet_operations nf_conntrack_net_ops = {
.init = nf_conntrack_pernet_init, .init = nf_conntrack_pernet_init,
.exit_batch = nf_conntrack_pernet_exit, .exit_batch = nf_conntrack_pernet_exit,
.id = &nf_conntrack_net_id,
.size = sizeof(struct nf_conntrack_net),
}; };
static int __init nf_conntrack_standalone_init(void) static int __init nf_conntrack_standalone_init(void)
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -870,7 +870,7 @@ static void nft_ct_helper_obj_eval(struct nft_object *obj, ...@@ -870,7 +870,7 @@ static void nft_ct_helper_obj_eval(struct nft_object *obj,
if (test_bit(IPS_HELPER_BIT, &ct->status)) if (test_bit(IPS_HELPER_BIT, &ct->status))
return; return;
help = nf_ct_helper_ext_add(ct, to_assign, GFP_ATOMIC); help = nf_ct_helper_ext_add(ct, GFP_ATOMIC);
if (help) { if (help) {
rcu_assign_pointer(help->helper, to_assign); rcu_assign_pointer(help->helper, to_assign);
set_bit(IPS_HELPER_BIT, &ct->status); set_bit(IPS_HELPER_BIT, &ct->status);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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