Commit 343917b4 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) Introduce a hashtable to speed up object lookups, from Florian Westphal.

2) Make direct calls to built-in extension, also from Florian.

3) Call helper before confirming the conntrack as it used to be originally,
   from Florian.

4) Call request_module() to autoload br_netfilter when physdev is used
   to relax the dependency, also from Florian.

5) Allow to insert rules at a given position ID that is internal to the
   batch, from Phil Sutter.

6) Several patches to replace conntrack indirections by direct calls,
   and to reduce modularization, from Florian. This also includes
   several follow up patches to deal with minor fallout from this
   rework.

7) Use RCU from conntrack gre helper, from Florian.

8) GRE conntrack module becomes built-in into nf_conntrack, from Florian.

9) Replace nf_ct_invert_tuplepr() by calls to nf_ct_invert_tuple(),
   from Florian.

10) Unify sysctl handling at the core of nf_conntrack, from Florian.

11) Provide modparam to register conntrack hooks.

12) Allow to match on the interface kind string, from wenxu.

13) Remove several exported symbols, not required anymore now after
    a bit of de-modulatization work has been done, from Florian.

14) Remove built-in map support in the hash extension, this can be
    done with the existing userspace infrastructure, from laura.

15) Remove indirection to calculate checksums in IPVS, from Matteo Croce.

16) Use call wrappers for indirection in IPVS, also from Matteo.

17) Remove superfluous __percpu parameter in nft_counter, patch from
    Luc Van Oostenryck.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents bb7c778b 83f52928
...@@ -19,27 +19,18 @@ struct nf_conn; ...@@ -19,27 +19,18 @@ struct nf_conn;
struct nf_ct_gre_keymap { struct nf_ct_gre_keymap {
struct list_head list; struct list_head list;
struct nf_conntrack_tuple tuple; struct nf_conntrack_tuple tuple;
}; struct rcu_head rcu;
enum grep_conntrack {
GRE_CT_UNREPLIED,
GRE_CT_REPLIED,
GRE_CT_MAX
};
struct netns_proto_gre {
struct nf_proto_net nf;
rwlock_t keymap_lock;
struct list_head keymap_list;
unsigned int gre_timeouts[GRE_CT_MAX];
}; };
/* add new tuple->key_reply pair to keymap */ /* add new tuple->key_reply pair to keymap */
int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
struct nf_conntrack_tuple *t); struct nf_conntrack_tuple *t);
void nf_ct_gre_keymap_flush(struct net *net);
/* delete keymap entries */ /* delete keymap entries */
void nf_ct_gre_keymap_destroy(struct nf_conn *ct); void nf_ct_gre_keymap_destroy(struct nf_conn *ct);
bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff,
struct net *net, struct nf_conntrack_tuple *tuple);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _CONNTRACK_PROTO_GRE_H */ #endif /* _CONNTRACK_PROTO_GRE_H */
...@@ -25,7 +25,6 @@ __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, ...@@ -25,7 +25,6 @@ __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);
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);
#else #else
static inline __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook, static inline __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)
...@@ -37,11 +36,6 @@ static inline int nf_ip_route(struct net *net, struct dst_entry **dst, ...@@ -37,11 +36,6 @@ static inline int nf_ip_route(struct net *net, struct dst_entry **dst,
{ {
return -EOPNOTSUPP; return -EOPNOTSUPP;
} }
static inline int nf_ip_reroute(struct sk_buff *skb,
const struct nf_queue_entry *entry)
{
return -EOPNOTSUPP;
}
#endif /* CONFIG_INET */ #endif /* CONFIG_INET */
#endif /*__LINUX_IP_NETFILTER_H*/ #endif /*__LINUX_IP_NETFILTER_H*/
...@@ -453,9 +453,6 @@ struct ip_vs_protocol { ...@@ -453,9 +453,6 @@ struct ip_vs_protocol {
int (*dnat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp, int (*dnat_handler)(struct sk_buff *skb, struct ip_vs_protocol *pp,
struct ip_vs_conn *cp, struct ip_vs_iphdr *iph); struct ip_vs_conn *cp, struct ip_vs_iphdr *iph);
int (*csum_check)(int af, struct sk_buff *skb,
struct ip_vs_protocol *pp);
const char *(*state_name)(int state); const char *(*state_name)(int state);
void (*state_transition)(struct ip_vs_conn *cp, int direction, void (*state_transition)(struct ip_vs_conn *cp, int direction,
......
...@@ -43,7 +43,6 @@ static inline struct rtable *bridge_parent_rtable(const struct net_device *dev) ...@@ -43,7 +43,6 @@ static inline struct rtable *bridge_parent_rtable(const struct net_device *dev)
} }
struct net_device *setup_pre_routing(struct sk_buff *skb); struct net_device *setup_pre_routing(struct sk_buff *skb);
void br_netfilter_enable(void);
#if IS_ENABLED(CONFIG_IPV6) #if IS_ENABLED(CONFIG_IPV6)
int br_validate_ipv6(struct net *net, struct sk_buff *skb); int br_validate_ipv6(struct net *net, struct sk_buff *skb);
......
...@@ -22,5 +22,8 @@ extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp; ...@@ -22,5 +22,8 @@ extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp;
#ifdef CONFIG_NF_CT_PROTO_UDPLITE #ifdef CONFIG_NF_CT_PROTO_UDPLITE
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite; extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite;
#endif #endif
#ifdef CONFIG_NF_CT_PROTO_GRE
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_gre;
#endif
#endif /*_NF_CONNTRACK_IPV4_H*/ #endif /*_NF_CONNTRACK_IPV4_H*/
...@@ -187,8 +187,6 @@ bool nf_ct_delete(struct nf_conn *ct, u32 pid, int report); ...@@ -187,8 +187,6 @@ bool nf_ct_delete(struct nf_conn *ct, u32 pid, int report);
bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff, bool nf_ct_get_tuplepr(const struct sk_buff *skb, unsigned int nhoff,
u_int16_t l3num, struct net *net, u_int16_t l3num, struct net *net,
struct nf_conntrack_tuple *tuple); struct nf_conntrack_tuple *tuple);
bool nf_ct_invert_tuplepr(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig);
void __nf_ct_refresh_acct(struct nf_conn *ct, enum ip_conntrack_info ctinfo, void __nf_ct_refresh_acct(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
const struct sk_buff *skb, const struct sk_buff *skb,
......
...@@ -26,7 +26,7 @@ int nf_conntrack_init_net(struct net *net); ...@@ -26,7 +26,7 @@ int nf_conntrack_init_net(struct net *net);
void nf_conntrack_cleanup_net(struct net *net); void nf_conntrack_cleanup_net(struct net *net);
void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list); void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list);
int nf_conntrack_proto_pernet_init(struct net *net); void nf_conntrack_proto_pernet_init(struct net *net);
void nf_conntrack_proto_pernet_fini(struct net *net); void nf_conntrack_proto_pernet_fini(struct net *net);
int nf_conntrack_proto_init(void); int nf_conntrack_proto_init(void);
...@@ -39,8 +39,7 @@ void nf_conntrack_init_end(void); ...@@ -39,8 +39,7 @@ void nf_conntrack_init_end(void);
void nf_conntrack_cleanup_end(void); void nf_conntrack_cleanup_end(void);
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_l4proto *l4proto);
/* Find a connection corresponding to a tuple. */ /* Find a connection corresponding to a tuple. */
struct nf_conntrack_tuple_hash * struct nf_conntrack_tuple_hash *
......
...@@ -27,27 +27,6 @@ struct nf_conntrack_l4proto { ...@@ -27,27 +27,6 @@ struct nf_conntrack_l4proto {
/* protoinfo nlattr size, closes a hole */ /* protoinfo nlattr size, closes a hole */
u16 nlattr_size; u16 nlattr_size;
/* Try to fill in the third arg: dataoff is offset past network protocol
hdr. Return true if possible. */
bool (*pkt_to_tuple)(const struct sk_buff *skb, unsigned int dataoff,
struct net *net, struct nf_conntrack_tuple *tuple);
/* Invert the per-proto part of the tuple: ie. turn xmit into reply.
* Only used by icmp, most protocols use a generic version.
*/
bool (*invert_tuple)(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig);
/* Returns verdict for packet, or -1 for invalid. */
int (*packet)(struct nf_conn *ct,
struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
const struct nf_hook_state *state);
/* Called when a conntrack entry is destroyed */
void (*destroy)(struct nf_conn *ct);
/* 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);
...@@ -79,16 +58,22 @@ struct nf_conntrack_l4proto { ...@@ -79,16 +58,22 @@ struct nf_conntrack_l4proto {
/* Print out the private part of the conntrack. */ /* Print out the private part of the conntrack. */
void (*print_conntrack)(struct seq_file *s, struct nf_conn *); void (*print_conntrack)(struct seq_file *s, struct nf_conn *);
#endif #endif
unsigned int *net_id; };
/* Init l4proto pernet data */
int (*init_net)(struct net *net);
/* Return the per-net protocol part. */ bool icmp_pkt_to_tuple(const struct sk_buff *skb,
struct nf_proto_net *(*get_net_proto)(struct net *net); unsigned int dataoff,
struct net *net,
struct nf_conntrack_tuple *tuple);
/* Module (if any) which this is connected to. */ bool icmpv6_pkt_to_tuple(const struct sk_buff *skb,
struct module *me; unsigned int dataoff,
}; struct net *net,
struct nf_conntrack_tuple *tuple);
bool nf_conntrack_invert_icmp_tuple(struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *orig);
bool nf_conntrack_invert_icmpv6_tuple(struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *orig);
int nf_conntrack_icmpv4_error(struct nf_conn *tmpl, int nf_conntrack_icmpv4_error(struct nf_conn *tmpl,
struct sk_buff *skb, struct sk_buff *skb,
...@@ -99,31 +84,63 @@ int nf_conntrack_icmpv6_error(struct nf_conn *tmpl, ...@@ -99,31 +84,63 @@ int nf_conntrack_icmpv6_error(struct nf_conn *tmpl,
struct sk_buff *skb, struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
const struct nf_hook_state *state); const struct nf_hook_state *state);
/* Existing built-in generic protocol */
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic;
#define MAX_NF_CT_PROTO IPPROTO_UDPLITE int nf_conntrack_icmp_packet(struct nf_conn *ct,
struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
const struct nf_hook_state *state);
const struct nf_conntrack_l4proto *__nf_ct_l4proto_find(u8 l4proto); int nf_conntrack_icmpv6_packet(struct nf_conn *ct,
struct sk_buff *skb,
enum ip_conntrack_info ctinfo,
const struct nf_hook_state *state);
const struct nf_conntrack_l4proto *nf_ct_l4proto_find_get(u8 l4proto); int nf_conntrack_udp_packet(struct nf_conn *ct,
void nf_ct_l4proto_put(const struct nf_conntrack_l4proto *p); struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
const struct nf_hook_state *state);
int nf_conntrack_udplite_packet(struct nf_conn *ct,
struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
const struct nf_hook_state *state);
int nf_conntrack_tcp_packet(struct nf_conn *ct,
struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
const struct nf_hook_state *state);
int nf_conntrack_dccp_packet(struct nf_conn *ct,
struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
const struct nf_hook_state *state);
int nf_conntrack_sctp_packet(struct nf_conn *ct,
struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
const struct nf_hook_state *state);
int nf_conntrack_gre_packet(struct nf_conn *ct,
struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
const struct nf_hook_state *state);
/* Protocol pernet registration. */ void nf_conntrack_generic_init_net(struct net *net);
int nf_ct_l4proto_pernet_register_one(struct net *net, void nf_conntrack_tcp_init_net(struct net *net);
const struct nf_conntrack_l4proto *proto); void nf_conntrack_udp_init_net(struct net *net);
void nf_ct_l4proto_pernet_unregister_one(struct net *net, void nf_conntrack_gre_init_net(struct net *net);
const struct nf_conntrack_l4proto *proto); void nf_conntrack_dccp_init_net(struct net *net);
int nf_ct_l4proto_pernet_register(struct net *net, void nf_conntrack_sctp_init_net(struct net *net);
const struct nf_conntrack_l4proto *const proto[], void nf_conntrack_icmp_init_net(struct net *net);
unsigned int num_proto); void nf_conntrack_icmpv6_init_net(struct net *net);
void nf_ct_l4proto_pernet_unregister(struct net *net,
const struct nf_conntrack_l4proto *const proto[],
unsigned int num_proto);
/* Protocol global registration. */ /* Existing built-in generic protocol */
int nf_ct_l4proto_register_one(const struct nf_conntrack_l4proto *proto); extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic;
void nf_ct_l4proto_unregister_one(const struct nf_conntrack_l4proto *proto);
#define MAX_NF_CT_PROTO IPPROTO_UDPLITE
const struct nf_conntrack_l4proto *nf_ct_l4proto_find(u8 l4proto);
/* 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,
...@@ -192,4 +209,11 @@ static inline struct nf_sctp_net *nf_sctp_pernet(struct net *net) ...@@ -192,4 +209,11 @@ static inline struct nf_sctp_net *nf_sctp_pernet(struct net *net)
} }
#endif #endif
#ifdef CONFIG_NF_CT_PROTO_GRE
static inline struct nf_gre_net *nf_gre_pernet(struct net *net)
{
return &net->ct.nf_ct_proto.gre;
}
#endif
#endif /*_NF_CONNTRACK_PROTOCOL_H*/ #endif /*_NF_CONNTRACK_PROTOCOL_H*/
...@@ -47,10 +47,6 @@ extern unsigned int nf_nat_alloc_null_binding(struct nf_conn *ct, ...@@ -47,10 +47,6 @@ extern unsigned int nf_nat_alloc_null_binding(struct nf_conn *ct,
struct nf_conn_nat *nf_ct_nat_ext_add(struct nf_conn *ct); struct nf_conn_nat *nf_ct_nat_ext_add(struct nf_conn *ct);
/* Is this tuple already taken? (not by us)*/
int nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack);
static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct) static inline struct nf_conn_nat *nfct_nat(const struct nf_conn *ct)
{ {
#if defined(CONFIG_NF_NAT) || defined(CONFIG_NF_NAT_MODULE) #if defined(CONFIG_NF_NAT) || defined(CONFIG_NF_NAT_MODULE)
......
...@@ -1011,12 +1011,23 @@ void nft_unregister_expr(struct nft_expr_type *); ...@@ -1011,12 +1011,23 @@ void nft_unregister_expr(struct nft_expr_type *);
int nft_verdict_dump(struct sk_buff *skb, int type, int nft_verdict_dump(struct sk_buff *skb, int type,
const struct nft_verdict *v); const struct nft_verdict *v);
/**
* struct nft_object_hash_key - key to lookup nft_object
*
* @name: name of the stateful object to look up
* @table: table the object belongs to
*/
struct nft_object_hash_key {
const char *name;
const struct nft_table *table;
};
/** /**
* struct nft_object - nf_tables stateful object * struct nft_object - nf_tables stateful object
* *
* @list: table stateful object list node * @list: table stateful object list node
* @table: table this object belongs to * @key: keys that identify this object
* @name: name of this stateful object * @rhlhead: nft_objname_ht node
* @genmask: generation mask * @genmask: generation mask
* @use: number of references to this stateful object * @use: number of references to this stateful object
* @handle: unique object handle * @handle: unique object handle
...@@ -1025,8 +1036,8 @@ int nft_verdict_dump(struct sk_buff *skb, int type, ...@@ -1025,8 +1036,8 @@ int nft_verdict_dump(struct sk_buff *skb, int type,
*/ */
struct nft_object { struct nft_object {
struct list_head list; struct list_head list;
char *name; struct rhlist_head rhlhead;
struct nft_table *table; struct nft_object_hash_key key;
u32 genmask:2, u32 genmask:2,
use:30; use:30;
u64 handle; u64 handle;
...@@ -1043,11 +1054,12 @@ static inline void *nft_obj_data(const struct nft_object *obj) ...@@ -1043,11 +1054,12 @@ static inline void *nft_obj_data(const struct nft_object *obj)
#define nft_expr_obj(expr) *((struct nft_object **)nft_expr_priv(expr)) #define nft_expr_obj(expr) *((struct nft_object **)nft_expr_priv(expr))
struct nft_object *nft_obj_lookup(const struct nft_table *table, struct nft_object *nft_obj_lookup(const struct net *net,
const struct nft_table *table,
const struct nlattr *nla, u32 objtype, const struct nlattr *nla, u32 objtype,
u8 genmask); u8 genmask);
void nft_obj_notify(struct net *net, struct nft_table *table, void nft_obj_notify(struct net *net, const struct nft_table *table,
struct nft_object *obj, u32 portid, u32 seq, struct nft_object *obj, u32 portid, u32 seq,
int event, int family, int report, gfp_t gfp); int event, int family, int report, gfp_t gfp);
......
...@@ -80,6 +80,22 @@ struct nft_regs; ...@@ -80,6 +80,22 @@ struct nft_regs;
struct nft_pktinfo; struct nft_pktinfo;
void nft_meta_get_eval(const struct nft_expr *expr, void nft_meta_get_eval(const struct nft_expr *expr,
struct nft_regs *regs, const struct nft_pktinfo *pkt); struct nft_regs *regs, const struct nft_pktinfo *pkt);
void nft_cmp_eval(const struct nft_expr *expr,
struct nft_regs *regs, const struct nft_pktinfo *pkt);
void nft_lookup_eval(const struct nft_expr *expr, void nft_lookup_eval(const struct nft_expr *expr,
struct nft_regs *regs, const struct nft_pktinfo *pkt); struct nft_regs *regs, const struct nft_pktinfo *pkt);
void nft_payload_eval(const struct nft_expr *expr,
struct nft_regs *regs, const struct nft_pktinfo *pkt);
void nft_immediate_eval(const struct nft_expr *expr,
struct nft_regs *regs, const struct nft_pktinfo *pkt);
void nft_bitwise_eval(const struct nft_expr *expr,
struct nft_regs *regs, const struct nft_pktinfo *pkt);
void nft_range_eval(const struct nft_expr *expr,
struct nft_regs *regs, const struct nft_pktinfo *pkt);
void nft_byteorder_eval(const struct nft_expr *expr,
struct nft_regs *regs, const struct nft_pktinfo *pkt);
void nft_dynset_eval(const struct nft_expr *expr,
struct nft_regs *regs, const struct nft_pktinfo *pkt);
void nft_rt_get_eval(const struct nft_expr *expr,
struct nft_regs *regs, const struct nft_pktinfo *pkt);
#endif /* _NET_NF_TABLES_CORE_H */ #endif /* _NET_NF_TABLES_CORE_H */
...@@ -18,21 +18,11 @@ ...@@ -18,21 +18,11 @@
struct ctl_table_header; struct ctl_table_header;
struct nf_conntrack_ecache; struct nf_conntrack_ecache;
struct nf_proto_net {
#ifdef CONFIG_SYSCTL
struct ctl_table_header *ctl_table_header;
struct ctl_table *ctl_table;
#endif
unsigned int users;
};
struct nf_generic_net { struct nf_generic_net {
struct nf_proto_net pn;
unsigned int timeout; unsigned int timeout;
}; };
struct nf_tcp_net { struct nf_tcp_net {
struct nf_proto_net pn;
unsigned int timeouts[TCP_CONNTRACK_TIMEOUT_MAX]; unsigned int timeouts[TCP_CONNTRACK_TIMEOUT_MAX];
unsigned int tcp_loose; unsigned int tcp_loose;
unsigned int tcp_be_liberal; unsigned int tcp_be_liberal;
...@@ -46,18 +36,15 @@ enum udp_conntrack { ...@@ -46,18 +36,15 @@ enum udp_conntrack {
}; };
struct nf_udp_net { struct nf_udp_net {
struct nf_proto_net pn;
unsigned int timeouts[UDP_CT_MAX]; unsigned int timeouts[UDP_CT_MAX];
}; };
struct nf_icmp_net { struct nf_icmp_net {
struct nf_proto_net pn;
unsigned int timeout; unsigned int timeout;
}; };
#ifdef CONFIG_NF_CT_PROTO_DCCP #ifdef CONFIG_NF_CT_PROTO_DCCP
struct nf_dccp_net { struct nf_dccp_net {
struct nf_proto_net pn;
int dccp_loose; int dccp_loose;
unsigned int dccp_timeout[CT_DCCP_MAX + 1]; unsigned int dccp_timeout[CT_DCCP_MAX + 1];
}; };
...@@ -65,11 +52,23 @@ struct nf_dccp_net { ...@@ -65,11 +52,23 @@ struct nf_dccp_net {
#ifdef CONFIG_NF_CT_PROTO_SCTP #ifdef CONFIG_NF_CT_PROTO_SCTP
struct nf_sctp_net { struct nf_sctp_net {
struct nf_proto_net pn;
unsigned int timeouts[SCTP_CONNTRACK_MAX]; unsigned int timeouts[SCTP_CONNTRACK_MAX];
}; };
#endif #endif
#ifdef CONFIG_NF_CT_PROTO_GRE
enum gre_conntrack {
GRE_CT_UNREPLIED,
GRE_CT_REPLIED,
GRE_CT_MAX
};
struct nf_gre_net {
struct list_head keymap_list;
unsigned int timeouts[GRE_CT_MAX];
};
#endif
struct nf_ip_net { struct nf_ip_net {
struct nf_generic_net generic; struct nf_generic_net generic;
struct nf_tcp_net tcp; struct nf_tcp_net tcp;
...@@ -82,6 +81,9 @@ struct nf_ip_net { ...@@ -82,6 +81,9 @@ struct nf_ip_net {
#ifdef CONFIG_NF_CT_PROTO_SCTP #ifdef CONFIG_NF_CT_PROTO_SCTP
struct nf_sctp_net sctp; struct nf_sctp_net sctp;
#endif #endif
#ifdef CONFIG_NF_CT_PROTO_GRE
struct nf_gre_net gre;
#endif
}; };
struct ct_pcpu { struct ct_pcpu {
......
...@@ -219,6 +219,7 @@ enum nft_chain_attributes { ...@@ -219,6 +219,7 @@ enum nft_chain_attributes {
* @NFTA_RULE_POSITION: numeric handle of the previous rule (NLA_U64) * @NFTA_RULE_POSITION: numeric handle of the previous rule (NLA_U64)
* @NFTA_RULE_USERDATA: user data (NLA_BINARY, NFT_USERDATA_MAXLEN) * @NFTA_RULE_USERDATA: user data (NLA_BINARY, NFT_USERDATA_MAXLEN)
* @NFTA_RULE_ID: uniquely identifies a rule in a transaction (NLA_U32) * @NFTA_RULE_ID: uniquely identifies a rule in a transaction (NLA_U32)
* @NFTA_RULE_POSITION_ID: transaction unique identifier of the previous rule (NLA_U32)
*/ */
enum nft_rule_attributes { enum nft_rule_attributes {
NFTA_RULE_UNSPEC, NFTA_RULE_UNSPEC,
...@@ -231,6 +232,7 @@ enum nft_rule_attributes { ...@@ -231,6 +232,7 @@ enum nft_rule_attributes {
NFTA_RULE_USERDATA, NFTA_RULE_USERDATA,
NFTA_RULE_PAD, NFTA_RULE_PAD,
NFTA_RULE_ID, NFTA_RULE_ID,
NFTA_RULE_POSITION_ID,
__NFTA_RULE_MAX __NFTA_RULE_MAX
}; };
#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1) #define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
...@@ -789,6 +791,8 @@ enum nft_exthdr_attributes { ...@@ -789,6 +791,8 @@ enum nft_exthdr_attributes {
* @NFT_META_CGROUP: socket control group (skb->sk->sk_classid) * @NFT_META_CGROUP: socket control group (skb->sk->sk_classid)
* @NFT_META_PRANDOM: a 32bit pseudo-random number * @NFT_META_PRANDOM: a 32bit pseudo-random number
* @NFT_META_SECPATH: boolean, secpath_exists (!!skb->sp) * @NFT_META_SECPATH: boolean, secpath_exists (!!skb->sp)
* @NFT_META_IIFKIND: packet input interface kind name (dev->rtnl_link_ops->kind)
* @NFT_META_OIFKIND: packet output interface kind name (dev->rtnl_link_ops->kind)
*/ */
enum nft_meta_keys { enum nft_meta_keys {
NFT_META_LEN, NFT_META_LEN,
...@@ -817,6 +821,8 @@ enum nft_meta_keys { ...@@ -817,6 +821,8 @@ enum nft_meta_keys {
NFT_META_CGROUP, NFT_META_CGROUP,
NFT_META_PRANDOM, NFT_META_PRANDOM,
NFT_META_SECPATH, NFT_META_SECPATH,
NFT_META_IIFKIND,
NFT_META_OIFKIND,
}; };
/** /**
...@@ -871,8 +877,8 @@ enum nft_hash_attributes { ...@@ -871,8 +877,8 @@ enum nft_hash_attributes {
NFTA_HASH_SEED, NFTA_HASH_SEED,
NFTA_HASH_OFFSET, NFTA_HASH_OFFSET,
NFTA_HASH_TYPE, NFTA_HASH_TYPE,
NFTA_HASH_SET_NAME, NFTA_HASH_SET_NAME, /* deprecated */
NFTA_HASH_SET_ID, NFTA_HASH_SET_ID, /* deprecated */
__NFTA_HASH_MAX, __NFTA_HASH_MAX,
}; };
#define NFTA_HASH_MAX (__NFTA_HASH_MAX - 1) #define NFTA_HASH_MAX (__NFTA_HASH_MAX - 1)
......
...@@ -881,11 +881,6 @@ static const struct nf_br_ops br_ops = { ...@@ -881,11 +881,6 @@ static const struct nf_br_ops br_ops = {
.br_dev_xmit_hook = br_nf_dev_xmit, .br_dev_xmit_hook = br_nf_dev_xmit,
}; };
void br_netfilter_enable(void)
{
}
EXPORT_SYMBOL_GPL(br_netfilter_enable);
/* For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because /* For br_nf_post_routing, we need (prio = NF_BR_PRI_LAST), because
* br_dev_queue_push_xmit is called afterwards */ * br_dev_queue_push_xmit is called afterwards */
static const struct nf_hook_ops br_nf_ops[] = { static const struct nf_hook_ops br_nf_ops[] = {
......
...@@ -80,24 +80,6 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t ...@@ -80,24 +80,6 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t
} }
EXPORT_SYMBOL(ip_route_me_harder); EXPORT_SYMBOL(ip_route_me_harder);
int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry)
{
const struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry);
if (entry->state.hook == NF_INET_LOCAL_OUT) {
const struct iphdr *iph = ip_hdr(skb);
if (!(iph->tos == rt_info->tos &&
skb->mark == rt_info->mark &&
iph->daddr == rt_info->daddr &&
iph->saddr == rt_info->saddr))
return ip_route_me_harder(entry->state.net, skb,
RTN_UNSPEC);
}
return 0;
}
EXPORT_SYMBOL_GPL(nf_ip_reroute);
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)
{ {
......
...@@ -214,7 +214,7 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb, ...@@ -214,7 +214,7 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb,
} }
/* Change outer to look like the reply to an incoming packet */ /* Change outer to look like the reply to an incoming packet */
nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple);
if (!nf_nat_ipv4_manip_pkt(skb, 0, &target, manip)) if (!nf_nat_ipv4_manip_pkt(skb, 0, &target, manip))
return 0; return 0;
......
...@@ -225,7 +225,7 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, ...@@ -225,7 +225,7 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
skb->len - hdrlen, 0)); skb->len - hdrlen, 0));
} }
nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple);
if (!nf_nat_ipv6_manip_pkt(skb, 0, &target, manip)) if (!nf_nat_ipv6_manip_pkt(skb, 0, &target, manip))
return 0; return 0;
......
...@@ -174,7 +174,7 @@ config NF_CT_PROTO_DCCP ...@@ -174,7 +174,7 @@ config NF_CT_PROTO_DCCP
If unsure, say Y. If unsure, say Y.
config NF_CT_PROTO_GRE config NF_CT_PROTO_GRE
tristate bool
config NF_CT_PROTO_SCTP config NF_CT_PROTO_SCTP
bool 'SCTP protocol connection tracking support' bool 'SCTP protocol connection tracking support'
......
...@@ -13,6 +13,7 @@ nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o ...@@ -13,6 +13,7 @@ nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o
nf_conntrack-$(CONFIG_NF_CONNTRACK_LABELS) += nf_conntrack_labels.o nf_conntrack-$(CONFIG_NF_CONNTRACK_LABELS) += nf_conntrack_labels.o
nf_conntrack-$(CONFIG_NF_CT_PROTO_DCCP) += nf_conntrack_proto_dccp.o nf_conntrack-$(CONFIG_NF_CT_PROTO_DCCP) += nf_conntrack_proto_dccp.o
nf_conntrack-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o nf_conntrack-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
nf_conntrack-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o
obj-$(CONFIG_NETFILTER) = netfilter.o obj-$(CONFIG_NETFILTER) = netfilter.o
...@@ -25,8 +26,6 @@ obj-$(CONFIG_NETFILTER_NETLINK_OSF) += nfnetlink_osf.o ...@@ -25,8 +26,6 @@ obj-$(CONFIG_NETFILTER_NETLINK_OSF) += nfnetlink_osf.o
# connection tracking # connection tracking
obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o obj-$(CONFIG_NF_CONNTRACK) += nf_conntrack.o
obj-$(CONFIG_NF_CT_PROTO_GRE) += nf_conntrack_proto_gre.o
# netlink interface for nf_conntrack # netlink interface for nf_conntrack
obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
obj-$(CONFIG_NF_CT_NETLINK_TIMEOUT) += nfnetlink_cttimeout.o obj-$(CONFIG_NF_CT_NETLINK_TIMEOUT) += nfnetlink_cttimeout.o
......
...@@ -53,6 +53,7 @@ ...@@ -53,6 +53,7 @@
#endif #endif
#include <net/ip_vs.h> #include <net/ip_vs.h>
#include <linux/indirect_call_wrapper.h>
EXPORT_SYMBOL(register_ip_vs_scheduler); EXPORT_SYMBOL(register_ip_vs_scheduler);
...@@ -70,6 +71,29 @@ EXPORT_SYMBOL(ip_vs_get_debug_level); ...@@ -70,6 +71,29 @@ EXPORT_SYMBOL(ip_vs_get_debug_level);
#endif #endif
EXPORT_SYMBOL(ip_vs_new_conn_out); EXPORT_SYMBOL(ip_vs_new_conn_out);
#ifdef CONFIG_IP_VS_PROTO_TCP
INDIRECT_CALLABLE_DECLARE(int
tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
struct ip_vs_conn *cp, struct ip_vs_iphdr *iph));
#endif
#ifdef CONFIG_IP_VS_PROTO_UDP
INDIRECT_CALLABLE_DECLARE(int
udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
struct ip_vs_conn *cp, struct ip_vs_iphdr *iph));
#endif
#if defined(CONFIG_IP_VS_PROTO_TCP) && defined(CONFIG_IP_VS_PROTO_UDP)
#define SNAT_CALL(f, ...) \
INDIRECT_CALL_2(f, tcp_snat_handler, udp_snat_handler, __VA_ARGS__)
#elif defined(CONFIG_IP_VS_PROTO_TCP)
#define SNAT_CALL(f, ...) INDIRECT_CALL_1(f, tcp_snat_handler, __VA_ARGS__)
#elif defined(CONFIG_IP_VS_PROTO_UDP)
#define SNAT_CALL(f, ...) INDIRECT_CALL_1(f, udp_snat_handler, __VA_ARGS__)
#else
#define SNAT_CALL(f, ...) f(__VA_ARGS__)
#endif
static unsigned int ip_vs_net_id __read_mostly; static unsigned int ip_vs_net_id __read_mostly;
/* netns cnt used for uniqueness */ /* netns cnt used for uniqueness */
static atomic_t ipvs_netns_cnt = ATOMIC_INIT(0); static atomic_t ipvs_netns_cnt = ATOMIC_INIT(0);
...@@ -478,7 +502,9 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb, ...@@ -478,7 +502,9 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
*/ */
if ((!skb->dev || skb->dev->flags & IFF_LOOPBACK)) { if ((!skb->dev || skb->dev->flags & IFF_LOOPBACK)) {
iph->hdr_flags ^= IP_VS_HDR_INVERSE; iph->hdr_flags ^= IP_VS_HDR_INVERSE;
cp = pp->conn_in_get(svc->ipvs, svc->af, skb, iph); cp = INDIRECT_CALL_1(pp->conn_in_get,
ip_vs_conn_in_get_proto, svc->ipvs,
svc->af, skb, iph);
iph->hdr_flags ^= IP_VS_HDR_INVERSE; iph->hdr_flags ^= IP_VS_HDR_INVERSE;
if (cp) { if (cp) {
...@@ -972,7 +998,8 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, ...@@ -972,7 +998,8 @@ static int ip_vs_out_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb,
ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph); ip_vs_fill_iph_skb_icmp(AF_INET, skb, offset, true, &ciph);
/* The embedded headers contain source and dest in reverse order */ /* The embedded headers contain source and dest in reverse order */
cp = pp->conn_out_get(ipvs, AF_INET, skb, &ciph); cp = INDIRECT_CALL_1(pp->conn_out_get, ip_vs_conn_out_get_proto,
ipvs, AF_INET, skb, &ciph);
if (!cp) if (!cp)
return NF_ACCEPT; return NF_ACCEPT;
...@@ -1028,7 +1055,8 @@ static int ip_vs_out_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb, ...@@ -1028,7 +1055,8 @@ static int ip_vs_out_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb,
return NF_ACCEPT; return NF_ACCEPT;
/* The embedded headers contain source and dest in reverse order */ /* The embedded headers contain source and dest in reverse order */
cp = pp->conn_out_get(ipvs, AF_INET6, skb, &ciph); cp = INDIRECT_CALL_1(pp->conn_out_get, ip_vs_conn_out_get_proto,
ipvs, AF_INET6, skb, &ciph);
if (!cp) if (!cp)
return NF_ACCEPT; return NF_ACCEPT;
...@@ -1263,7 +1291,8 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, ...@@ -1263,7 +1291,8 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd,
goto drop; goto drop;
/* mangle the packet */ /* mangle the packet */
if (pp->snat_handler && !pp->snat_handler(skb, pp, cp, iph)) if (pp->snat_handler &&
!SNAT_CALL(pp->snat_handler, skb, pp, cp, iph))
goto drop; goto drop;
#ifdef CONFIG_IP_VS_IPV6 #ifdef CONFIG_IP_VS_IPV6
...@@ -1389,7 +1418,8 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in ...@@ -1389,7 +1418,8 @@ ip_vs_out(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, in
/* /*
* Check if the packet belongs to an existing entry * Check if the packet belongs to an existing entry
*/ */
cp = pp->conn_out_get(ipvs, af, skb, &iph); cp = INDIRECT_CALL_1(pp->conn_out_get, ip_vs_conn_out_get_proto,
ipvs, af, skb, &iph);
if (likely(cp)) { if (likely(cp)) {
if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ) if (IP_VS_FWD_METHOD(cp) != IP_VS_CONN_F_MASQ)
...@@ -1644,7 +1674,8 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related, ...@@ -1644,7 +1674,8 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,
/* The embedded headers contain source and dest in reverse order. /* The embedded headers contain source and dest in reverse order.
* For IPIP this is error for request, not for reply. * For IPIP this is error for request, not for reply.
*/ */
cp = pp->conn_in_get(ipvs, AF_INET, skb, &ciph); cp = INDIRECT_CALL_1(pp->conn_in_get, ip_vs_conn_in_get_proto,
ipvs, AF_INET, skb, &ciph);
if (!cp) { if (!cp) {
int v; int v;
...@@ -1796,7 +1827,8 @@ static int ip_vs_in_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb, ...@@ -1796,7 +1827,8 @@ static int ip_vs_in_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb,
/* The embedded headers contain source and dest in reverse order /* The embedded headers contain source and dest in reverse order
* if not from localhost * if not from localhost
*/ */
cp = pp->conn_in_get(ipvs, AF_INET6, skb, &ciph); cp = INDIRECT_CALL_1(pp->conn_in_get, ip_vs_conn_in_get_proto,
ipvs, AF_INET6, skb, &ciph);
if (!cp) { if (!cp) {
int v; int v;
...@@ -1925,7 +1957,8 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int ...@@ -1925,7 +1957,8 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int
/* /*
* Check if the packet belongs to an existing connection entry * Check if the packet belongs to an existing connection entry
*/ */
cp = pp->conn_in_get(ipvs, af, skb, &iph); cp = INDIRECT_CALL_1(pp->conn_in_get, ip_vs_conn_in_get_proto,
ipvs, af, skb, &iph);
conn_reuse_mode = sysctl_conn_reuse_mode(ipvs); conn_reuse_mode = sysctl_conn_reuse_mode(ipvs);
if (conn_reuse_mode && !iph.fragoffs && is_new_conn(skb, &iph) && cp) { if (conn_reuse_mode && !iph.fragoffs && is_new_conn(skb, &iph) && cp) {
......
...@@ -129,7 +129,6 @@ struct ip_vs_protocol ip_vs_protocol_ah = { ...@@ -129,7 +129,6 @@ struct ip_vs_protocol ip_vs_protocol_ah = {
.conn_out_get = ah_esp_conn_out_get, .conn_out_get = ah_esp_conn_out_get,
.snat_handler = NULL, .snat_handler = NULL,
.dnat_handler = NULL, .dnat_handler = NULL,
.csum_check = NULL,
.state_transition = NULL, .state_transition = NULL,
.register_app = NULL, .register_app = NULL,
.unregister_app = NULL, .unregister_app = NULL,
...@@ -152,7 +151,6 @@ struct ip_vs_protocol ip_vs_protocol_esp = { ...@@ -152,7 +151,6 @@ struct ip_vs_protocol ip_vs_protocol_esp = {
.conn_out_get = ah_esp_conn_out_get, .conn_out_get = ah_esp_conn_out_get,
.snat_handler = NULL, .snat_handler = NULL,
.dnat_handler = NULL, .dnat_handler = NULL,
.csum_check = NULL,
.state_transition = NULL, .state_transition = NULL,
.register_app = NULL, .register_app = NULL,
.unregister_app = NULL, .unregister_app = NULL,
......
...@@ -9,6 +9,9 @@ ...@@ -9,6 +9,9 @@
#include <net/sctp/checksum.h> #include <net/sctp/checksum.h>
#include <net/ip_vs.h> #include <net/ip_vs.h>
static int
sctp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
static int static int
sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
struct ip_vs_proto_data *pd, struct ip_vs_proto_data *pd,
...@@ -105,7 +108,7 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -105,7 +108,7 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret; int ret;
/* Some checks before mangling */ /* Some checks before mangling */
if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) if (!sctp_csum_check(cp->af, skb, pp))
return 0; return 0;
/* Call application helper if needed */ /* Call application helper if needed */
...@@ -152,7 +155,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -152,7 +155,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret; int ret;
/* Some checks before mangling */ /* Some checks before mangling */
if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) if (!sctp_csum_check(cp->af, skb, pp))
return 0; return 0;
/* Call application helper if needed */ /* Call application helper if needed */
...@@ -587,7 +590,6 @@ struct ip_vs_protocol ip_vs_protocol_sctp = { ...@@ -587,7 +590,6 @@ struct ip_vs_protocol ip_vs_protocol_sctp = {
.conn_out_get = ip_vs_conn_out_get_proto, .conn_out_get = ip_vs_conn_out_get_proto,
.snat_handler = sctp_snat_handler, .snat_handler = sctp_snat_handler,
.dnat_handler = sctp_dnat_handler, .dnat_handler = sctp_dnat_handler,
.csum_check = sctp_csum_check,
.state_name = sctp_state_name, .state_name = sctp_state_name,
.state_transition = sctp_state_transition, .state_transition = sctp_state_transition,
.app_conn_bind = sctp_app_conn_bind, .app_conn_bind = sctp_app_conn_bind,
......
...@@ -28,9 +28,13 @@ ...@@ -28,9 +28,13 @@
#include <net/ip6_checksum.h> #include <net/ip6_checksum.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv4.h>
#include <linux/indirect_call_wrapper.h>
#include <net/ip_vs.h> #include <net/ip_vs.h>
static int
tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
static int static int
tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
struct ip_vs_proto_data *pd, struct ip_vs_proto_data *pd,
...@@ -143,7 +147,7 @@ tcp_partial_csum_update(int af, struct tcphdr *tcph, ...@@ -143,7 +147,7 @@ tcp_partial_csum_update(int af, struct tcphdr *tcph,
} }
static int INDIRECT_CALLABLE_SCOPE int
tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
struct ip_vs_conn *cp, struct ip_vs_iphdr *iph) struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
{ {
...@@ -166,7 +170,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -166,7 +170,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret; int ret;
/* Some checks before mangling */ /* Some checks before mangling */
if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) if (!tcp_csum_check(cp->af, skb, pp))
return 0; return 0;
/* Call application helper if needed */ /* Call application helper if needed */
...@@ -192,7 +196,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -192,7 +196,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
tcp_fast_csum_update(cp->af, tcph, &cp->daddr, &cp->vaddr, tcp_fast_csum_update(cp->af, tcph, &cp->daddr, &cp->vaddr,
cp->dport, cp->vport); cp->dport, cp->vport);
if (skb->ip_summed == CHECKSUM_COMPLETE) if (skb->ip_summed == CHECKSUM_COMPLETE)
skb->ip_summed = (cp->app && pp->csum_check) ? skb->ip_summed = cp->app ?
CHECKSUM_UNNECESSARY : CHECKSUM_NONE; CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
} else { } else {
/* full checksum calculation */ /* full checksum calculation */
...@@ -244,7 +248,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -244,7 +248,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret; int ret;
/* Some checks before mangling */ /* Some checks before mangling */
if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) if (!tcp_csum_check(cp->af, skb, pp))
return 0; return 0;
/* /*
...@@ -275,7 +279,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -275,7 +279,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
tcp_fast_csum_update(cp->af, tcph, &cp->vaddr, &cp->daddr, tcp_fast_csum_update(cp->af, tcph, &cp->vaddr, &cp->daddr,
cp->vport, cp->dport); cp->vport, cp->dport);
if (skb->ip_summed == CHECKSUM_COMPLETE) if (skb->ip_summed == CHECKSUM_COMPLETE)
skb->ip_summed = (cp->app && pp->csum_check) ? skb->ip_summed = cp->app ?
CHECKSUM_UNNECESSARY : CHECKSUM_NONE; CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
} else { } else {
/* full checksum calculation */ /* full checksum calculation */
...@@ -736,7 +740,6 @@ struct ip_vs_protocol ip_vs_protocol_tcp = { ...@@ -736,7 +740,6 @@ struct ip_vs_protocol ip_vs_protocol_tcp = {
.conn_out_get = ip_vs_conn_out_get_proto, .conn_out_get = ip_vs_conn_out_get_proto,
.snat_handler = tcp_snat_handler, .snat_handler = tcp_snat_handler,
.dnat_handler = tcp_dnat_handler, .dnat_handler = tcp_dnat_handler,
.csum_check = tcp_csum_check,
.state_name = tcp_state_name, .state_name = tcp_state_name,
.state_transition = tcp_state_transition, .state_transition = tcp_state_transition,
.app_conn_bind = tcp_app_conn_bind, .app_conn_bind = tcp_app_conn_bind,
......
...@@ -23,11 +23,15 @@ ...@@ -23,11 +23,15 @@
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h> #include <linux/netfilter_ipv4.h>
#include <linux/udp.h> #include <linux/udp.h>
#include <linux/indirect_call_wrapper.h>
#include <net/ip_vs.h> #include <net/ip_vs.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/ip6_checksum.h> #include <net/ip6_checksum.h>
static int
udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp);
static int static int
udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
struct ip_vs_proto_data *pd, struct ip_vs_proto_data *pd,
...@@ -133,7 +137,7 @@ udp_partial_csum_update(int af, struct udphdr *uhdr, ...@@ -133,7 +137,7 @@ udp_partial_csum_update(int af, struct udphdr *uhdr,
} }
static int INDIRECT_CALLABLE_SCOPE int
udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
struct ip_vs_conn *cp, struct ip_vs_iphdr *iph) struct ip_vs_conn *cp, struct ip_vs_iphdr *iph)
{ {
...@@ -156,7 +160,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -156,7 +160,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret; int ret;
/* Some checks before mangling */ /* Some checks before mangling */
if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) if (!udp_csum_check(cp->af, skb, pp))
return 0; return 0;
/* /*
...@@ -186,7 +190,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -186,7 +190,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
udp_fast_csum_update(cp->af, udph, &cp->daddr, &cp->vaddr, udp_fast_csum_update(cp->af, udph, &cp->daddr, &cp->vaddr,
cp->dport, cp->vport); cp->dport, cp->vport);
if (skb->ip_summed == CHECKSUM_COMPLETE) if (skb->ip_summed == CHECKSUM_COMPLETE)
skb->ip_summed = (cp->app && pp->csum_check) ? skb->ip_summed = cp->app ?
CHECKSUM_UNNECESSARY : CHECKSUM_NONE; CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
} else { } else {
/* full checksum calculation */ /* full checksum calculation */
...@@ -239,7 +243,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -239,7 +243,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
int ret; int ret;
/* Some checks before mangling */ /* Some checks before mangling */
if (pp->csum_check && !pp->csum_check(cp->af, skb, pp)) if (!udp_csum_check(cp->af, skb, pp))
return 0; return 0;
/* /*
...@@ -270,7 +274,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, ...@@ -270,7 +274,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,
udp_fast_csum_update(cp->af, udph, &cp->vaddr, &cp->daddr, udp_fast_csum_update(cp->af, udph, &cp->vaddr, &cp->daddr,
cp->vport, cp->dport); cp->vport, cp->dport);
if (skb->ip_summed == CHECKSUM_COMPLETE) if (skb->ip_summed == CHECKSUM_COMPLETE)
skb->ip_summed = (cp->app && pp->csum_check) ? skb->ip_summed = cp->app ?
CHECKSUM_UNNECESSARY : CHECKSUM_NONE; CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
} else { } else {
/* full checksum calculation */ /* full checksum calculation */
...@@ -494,7 +498,6 @@ struct ip_vs_protocol ip_vs_protocol_udp = { ...@@ -494,7 +498,6 @@ struct ip_vs_protocol ip_vs_protocol_udp = {
.conn_out_get = ip_vs_conn_out_get_proto, .conn_out_get = ip_vs_conn_out_get_proto,
.snat_handler = udp_snat_handler, .snat_handler = udp_snat_handler,
.dnat_handler = udp_dnat_handler, .dnat_handler = udp_dnat_handler,
.csum_check = udp_csum_check,
.state_transition = udp_state_transition, .state_transition = udp_state_transition,
.state_name = udp_state_name, .state_name = udp_state_name,
.register_app = udp_register_app, .register_app = udp_register_app,
......
This diff is collapsed.
...@@ -610,7 +610,7 @@ static int exp_seq_show(struct seq_file *s, void *v) ...@@ -610,7 +610,7 @@ 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_l4proto_find(expect->tuple.dst.protonum)); nf_ct_l4proto_find(expect->tuple.dst.protonum));
if (expect->flags & NF_CT_EXPECT_PERMANENT) { if (expect->flags & NF_CT_EXPECT_PERMANENT) {
seq_puts(s, "PERMANENT"); seq_puts(s, "PERMANENT");
......
...@@ -134,7 +134,7 @@ static int ctnetlink_dump_tuples(struct sk_buff *skb, ...@@ -134,7 +134,7 @@ static int ctnetlink_dump_tuples(struct sk_buff *skb,
ret = ctnetlink_dump_tuples_ip(skb, tuple); ret = ctnetlink_dump_tuples_ip(skb, tuple);
if (ret >= 0) { if (ret >= 0) {
l4proto = __nf_ct_l4proto_find(tuple->dst.protonum); l4proto = nf_ct_l4proto_find(tuple->dst.protonum);
ret = ctnetlink_dump_tuples_proto(skb, tuple, l4proto); ret = ctnetlink_dump_tuples_proto(skb, tuple, l4proto);
} }
rcu_read_unlock(); rcu_read_unlock();
...@@ -182,7 +182,7 @@ static int ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct) ...@@ -182,7 +182,7 @@ static int ctnetlink_dump_protoinfo(struct sk_buff *skb, struct nf_conn *ct)
struct nlattr *nest_proto; struct nlattr *nest_proto;
int ret; int ret;
l4proto = __nf_ct_l4proto_find(nf_ct_protonum(ct)); l4proto = nf_ct_l4proto_find(nf_ct_protonum(ct));
if (!l4proto->to_nlattr) if (!l4proto->to_nlattr)
return 0; return 0;
...@@ -590,7 +590,7 @@ static size_t ctnetlink_proto_size(const struct nf_conn *ct) ...@@ -590,7 +590,7 @@ static size_t ctnetlink_proto_size(const struct nf_conn *ct)
len = nla_policy_len(cta_ip_nla_policy, CTA_IP_MAX + 1); len = nla_policy_len(cta_ip_nla_policy, CTA_IP_MAX + 1);
len *= 3u; /* ORIG, REPLY, MASTER */ len *= 3u; /* ORIG, REPLY, MASTER */
l4proto = __nf_ct_l4proto_find(nf_ct_protonum(ct)); l4proto = nf_ct_l4proto_find(nf_ct_protonum(ct));
len += l4proto->nlattr_size; len += l4proto->nlattr_size;
if (l4proto->nlattr_tuple_size) { if (l4proto->nlattr_tuple_size) {
len4 = l4proto->nlattr_tuple_size(); len4 = l4proto->nlattr_tuple_size();
...@@ -1059,7 +1059,7 @@ static int ctnetlink_parse_tuple_proto(struct nlattr *attr, ...@@ -1059,7 +1059,7 @@ static int ctnetlink_parse_tuple_proto(struct nlattr *attr,
tuple->dst.protonum = nla_get_u8(tb[CTA_PROTO_NUM]); tuple->dst.protonum = nla_get_u8(tb[CTA_PROTO_NUM]);
rcu_read_lock(); rcu_read_lock();
l4proto = __nf_ct_l4proto_find(tuple->dst.protonum); l4proto = nf_ct_l4proto_find(tuple->dst.protonum);
if (likely(l4proto->nlattr_to_tuple)) { if (likely(l4proto->nlattr_to_tuple)) {
ret = nla_validate_nested(attr, CTA_PROTO_MAX, ret = nla_validate_nested(attr, CTA_PROTO_MAX,
...@@ -1722,11 +1722,9 @@ static int ctnetlink_change_protoinfo(struct nf_conn *ct, ...@@ -1722,11 +1722,9 @@ static int ctnetlink_change_protoinfo(struct nf_conn *ct,
if (err < 0) if (err < 0)
return err; return err;
rcu_read_lock(); l4proto = nf_ct_l4proto_find(nf_ct_protonum(ct));
l4proto = __nf_ct_l4proto_find(nf_ct_protonum(ct));
if (l4proto->from_nlattr) if (l4proto->from_nlattr)
err = l4proto->from_nlattr(tb, ct); err = l4proto->from_nlattr(tb, ct);
rcu_read_unlock();
return err; return err;
} }
...@@ -2676,7 +2674,7 @@ static int ctnetlink_exp_dump_mask(struct sk_buff *skb, ...@@ -2676,7 +2674,7 @@ static int ctnetlink_exp_dump_mask(struct sk_buff *skb,
rcu_read_lock(); rcu_read_lock();
ret = ctnetlink_dump_tuples_ip(skb, &m); ret = ctnetlink_dump_tuples_ip(skb, &m);
if (ret >= 0) { if (ret >= 0) {
l4proto = __nf_ct_l4proto_find(tuple->dst.protonum); l4proto = nf_ct_l4proto_find(tuple->dst.protonum);
ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto); ret = ctnetlink_dump_tuples_proto(skb, &m, l4proto);
} }
rcu_read_unlock(); rcu_read_unlock();
......
...@@ -121,7 +121,7 @@ static void pptp_expectfn(struct nf_conn *ct, ...@@ -121,7 +121,7 @@ static void pptp_expectfn(struct nf_conn *ct,
struct nf_conntrack_expect *exp_other; struct nf_conntrack_expect *exp_other;
/* obviously this tuple inversion only works until you do NAT */ /* obviously this tuple inversion only works until you do NAT */
nf_ct_invert_tuplepr(&inv_t, &exp->tuple); nf_ct_invert_tuple(&inv_t, &exp->tuple);
pr_debug("trying to unexpect other dir: "); pr_debug("trying to unexpect other dir: ");
nf_ct_dump_tuple(&inv_t); nf_ct_dump_tuple(&inv_t);
......
This diff is collapsed.
...@@ -472,8 +472,9 @@ static bool dccp_error(const struct dccp_hdr *dh, ...@@ -472,8 +472,9 @@ static bool dccp_error(const struct dccp_hdr *dh,
return true; return true;
} }
static int dccp_packet(struct nf_conn *ct, struct sk_buff *skb, int nf_conntrack_dccp_packet(struct nf_conn *ct, struct sk_buff *skb,
unsigned int dataoff, enum ip_conntrack_info ctinfo, unsigned int dataoff,
enum ip_conntrack_info ctinfo,
const struct nf_hook_state *state) const struct nf_hook_state *state)
{ {
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
...@@ -723,96 +724,10 @@ dccp_timeout_nla_policy[CTA_TIMEOUT_DCCP_MAX+1] = { ...@@ -723,96 +724,10 @@ dccp_timeout_nla_policy[CTA_TIMEOUT_DCCP_MAX+1] = {
}; };
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
#ifdef CONFIG_SYSCTL void nf_conntrack_dccp_init_net(struct net *net)
/* template, data assigned later */
static struct ctl_table dccp_sysctl_table[] = {
{
.procname = "nf_conntrack_dccp_timeout_request",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_dccp_timeout_respond",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_dccp_timeout_partopen",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_dccp_timeout_open",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_dccp_timeout_closereq",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_dccp_timeout_closing",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_dccp_timeout_timewait",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_dccp_loose",
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{ }
};
#endif /* CONFIG_SYSCTL */
static int dccp_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *pn,
struct nf_dccp_net *dn)
{
#ifdef CONFIG_SYSCTL
if (pn->ctl_table)
return 0;
pn->ctl_table = kmemdup(dccp_sysctl_table,
sizeof(dccp_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_table)
return -ENOMEM;
pn->ctl_table[0].data = &dn->dccp_timeout[CT_DCCP_REQUEST];
pn->ctl_table[1].data = &dn->dccp_timeout[CT_DCCP_RESPOND];
pn->ctl_table[2].data = &dn->dccp_timeout[CT_DCCP_PARTOPEN];
pn->ctl_table[3].data = &dn->dccp_timeout[CT_DCCP_OPEN];
pn->ctl_table[4].data = &dn->dccp_timeout[CT_DCCP_CLOSEREQ];
pn->ctl_table[5].data = &dn->dccp_timeout[CT_DCCP_CLOSING];
pn->ctl_table[6].data = &dn->dccp_timeout[CT_DCCP_TIMEWAIT];
pn->ctl_table[7].data = &dn->dccp_loose;
/* Don't export sysctls to unprivileged users */
if (net->user_ns != &init_user_ns)
pn->ctl_table[0].procname = NULL;
#endif
return 0;
}
static int dccp_init_net(struct net *net)
{ {
struct nf_dccp_net *dn = nf_dccp_pernet(net); struct nf_dccp_net *dn = nf_dccp_pernet(net);
struct nf_proto_net *pn = &dn->pn;
if (!pn->users) {
/* default values */ /* default values */
dn->dccp_loose = 1; dn->dccp_loose = 1;
dn->dccp_timeout[CT_DCCP_REQUEST] = 2 * DCCP_MSL; dn->dccp_timeout[CT_DCCP_REQUEST] = 2 * DCCP_MSL;
...@@ -827,19 +742,10 @@ static int dccp_init_net(struct net *net) ...@@ -827,19 +742,10 @@ static int dccp_init_net(struct net *net)
* ->timeouts[0] contains 'new' timeout, like udp or icmp. * ->timeouts[0] contains 'new' timeout, like udp or icmp.
*/ */
dn->dccp_timeout[CT_DCCP_NONE] = dn->dccp_timeout[CT_DCCP_REQUEST]; dn->dccp_timeout[CT_DCCP_NONE] = dn->dccp_timeout[CT_DCCP_REQUEST];
}
return dccp_kmemdup_sysctl_table(net, pn, dn);
}
static struct nf_proto_net *dccp_get_net_proto(struct net *net)
{
return &net->ct.nf_ct_proto.dccp.pn;
} }
const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp = { const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp = {
.l4proto = IPPROTO_DCCP, .l4proto = IPPROTO_DCCP,
.packet = dccp_packet,
.can_early_drop = dccp_can_early_drop, .can_early_drop = dccp_can_early_drop,
#ifdef CONFIG_NF_CONNTRACK_PROCFS #ifdef CONFIG_NF_CONNTRACK_PROCFS
.print_conntrack = dccp_print_conntrack, .print_conntrack = dccp_print_conntrack,
...@@ -862,6 +768,4 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp = { ...@@ -862,6 +768,4 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp = {
.nla_policy = dccp_timeout_nla_policy, .nla_policy = dccp_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
.init_net = dccp_init_net,
.get_net_proto = dccp_get_net_proto,
}; };
...@@ -15,50 +15,6 @@ ...@@ -15,50 +15,6 @@
static const unsigned int nf_ct_generic_timeout = 600*HZ; static const unsigned int nf_ct_generic_timeout = 600*HZ;
static bool nf_generic_should_process(u8 proto)
{
switch (proto) {
#ifdef CONFIG_NF_CT_PROTO_GRE_MODULE
case IPPROTO_GRE:
return false;
#endif
default:
return true;
}
}
static bool generic_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff,
struct net *net, struct nf_conntrack_tuple *tuple)
{
tuple->src.u.all = 0;
tuple->dst.u.all = 0;
return true;
}
/* Returns verdict for packet, or -1 for invalid. */
static int generic_packet(struct nf_conn *ct,
struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo,
const struct nf_hook_state *state)
{
const unsigned int *timeout = nf_ct_timeout_lookup(ct);
if (!nf_generic_should_process(nf_ct_protonum(ct))) {
pr_warn_once("conntrack: generic helper won't handle protocol %d. Please consider loading the specific helper module.\n",
nf_ct_protonum(ct));
return -NF_ACCEPT;
}
if (!timeout)
timeout = &nf_generic_pernet(nf_ct_net(ct))->timeout;
nf_ct_refresh_acct(ct, ctinfo, skb, *timeout);
return NF_ACCEPT;
}
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink.h>
...@@ -104,53 +60,16 @@ generic_timeout_nla_policy[CTA_TIMEOUT_GENERIC_MAX+1] = { ...@@ -104,53 +60,16 @@ generic_timeout_nla_policy[CTA_TIMEOUT_GENERIC_MAX+1] = {
}; };
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
#ifdef CONFIG_SYSCTL void nf_conntrack_generic_init_net(struct net *net)
static struct ctl_table generic_sysctl_table[] = {
{
.procname = "nf_conntrack_generic_timeout",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{ }
};
#endif /* CONFIG_SYSCTL */
static int generic_kmemdup_sysctl_table(struct nf_proto_net *pn,
struct nf_generic_net *gn)
{
#ifdef CONFIG_SYSCTL
pn->ctl_table = kmemdup(generic_sysctl_table,
sizeof(generic_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_table)
return -ENOMEM;
pn->ctl_table[0].data = &gn->timeout;
#endif
return 0;
}
static int generic_init_net(struct net *net)
{ {
struct nf_generic_net *gn = nf_generic_pernet(net); struct nf_generic_net *gn = nf_generic_pernet(net);
struct nf_proto_net *pn = &gn->pn;
gn->timeout = nf_ct_generic_timeout; gn->timeout = nf_ct_generic_timeout;
return generic_kmemdup_sysctl_table(pn, gn);
}
static struct nf_proto_net *generic_get_net_proto(struct net *net)
{
return &net->ct.nf_ct_proto.generic.pn;
} }
const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic =
{ {
.l4proto = 255, .l4proto = 255,
.pkt_to_tuple = generic_pkt_to_tuple,
.packet = generic_packet,
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
.ctnl_timeout = { .ctnl_timeout = {
.nlattr_to_obj = generic_timeout_nlattr_to_obj, .nlattr_to_obj = generic_timeout_nlattr_to_obj,
...@@ -160,6 +79,4 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic = ...@@ -160,6 +79,4 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic =
.nla_policy = generic_timeout_nla_policy, .nla_policy = generic_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
.init_net = generic_init_net,
.get_net_proto = generic_get_net_proto,
}; };
...@@ -48,24 +48,25 @@ static const unsigned int gre_timeouts[GRE_CT_MAX] = { ...@@ -48,24 +48,25 @@ static const unsigned int gre_timeouts[GRE_CT_MAX] = {
[GRE_CT_REPLIED] = 180*HZ, [GRE_CT_REPLIED] = 180*HZ,
}; };
static unsigned int proto_gre_net_id __read_mostly; /* used when expectation is added */
static DEFINE_SPINLOCK(keymap_lock);
static inline struct netns_proto_gre *gre_pernet(struct net *net) static inline struct nf_gre_net *gre_pernet(struct net *net)
{ {
return net_generic(net, proto_gre_net_id); return &net->ct.nf_ct_proto.gre;
} }
static void nf_ct_gre_keymap_flush(struct net *net) void nf_ct_gre_keymap_flush(struct net *net)
{ {
struct netns_proto_gre *net_gre = gre_pernet(net); struct nf_gre_net *net_gre = gre_pernet(net);
struct nf_ct_gre_keymap *km, *tmp; struct nf_ct_gre_keymap *km, *tmp;
write_lock_bh(&net_gre->keymap_lock); spin_lock_bh(&keymap_lock);
list_for_each_entry_safe(km, tmp, &net_gre->keymap_list, list) { list_for_each_entry_safe(km, tmp, &net_gre->keymap_list, list) {
list_del(&km->list); list_del_rcu(&km->list);
kfree(km); kfree_rcu(km, rcu);
} }
write_unlock_bh(&net_gre->keymap_lock); spin_unlock_bh(&keymap_lock);
} }
static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km, static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km,
...@@ -81,18 +82,16 @@ static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km, ...@@ -81,18 +82,16 @@ static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km,
/* look up the source key for a given tuple */ /* look up the source key for a given tuple */
static __be16 gre_keymap_lookup(struct net *net, struct nf_conntrack_tuple *t) static __be16 gre_keymap_lookup(struct net *net, struct nf_conntrack_tuple *t)
{ {
struct netns_proto_gre *net_gre = gre_pernet(net); struct nf_gre_net *net_gre = gre_pernet(net);
struct nf_ct_gre_keymap *km; struct nf_ct_gre_keymap *km;
__be16 key = 0; __be16 key = 0;
read_lock_bh(&net_gre->keymap_lock); list_for_each_entry_rcu(km, &net_gre->keymap_list, list) {
list_for_each_entry(km, &net_gre->keymap_list, list) {
if (gre_key_cmpfn(km, t)) { if (gre_key_cmpfn(km, t)) {
key = km->tuple.src.u.gre.key; key = km->tuple.src.u.gre.key;
break; break;
} }
} }
read_unlock_bh(&net_gre->keymap_lock);
pr_debug("lookup src key 0x%x for ", key); pr_debug("lookup src key 0x%x for ", key);
nf_ct_dump_tuple(t); nf_ct_dump_tuple(t);
...@@ -105,21 +104,17 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, ...@@ -105,21 +104,17 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
struct nf_conntrack_tuple *t) struct nf_conntrack_tuple *t)
{ {
struct net *net = nf_ct_net(ct); struct net *net = nf_ct_net(ct);
struct netns_proto_gre *net_gre = gre_pernet(net); struct nf_gre_net *net_gre = gre_pernet(net);
struct nf_ct_pptp_master *ct_pptp_info = nfct_help_data(ct); struct nf_ct_pptp_master *ct_pptp_info = nfct_help_data(ct);
struct nf_ct_gre_keymap **kmp, *km; struct nf_ct_gre_keymap **kmp, *km;
kmp = &ct_pptp_info->keymap[dir]; kmp = &ct_pptp_info->keymap[dir];
if (*kmp) { if (*kmp) {
/* check whether it's a retransmission */ /* check whether it's a retransmission */
read_lock_bh(&net_gre->keymap_lock); list_for_each_entry_rcu(km, &net_gre->keymap_list, list) {
list_for_each_entry(km, &net_gre->keymap_list, list) { if (gre_key_cmpfn(km, t) && km == *kmp)
if (gre_key_cmpfn(km, t) && km == *kmp) {
read_unlock_bh(&net_gre->keymap_lock);
return 0; return 0;
} }
}
read_unlock_bh(&net_gre->keymap_lock);
pr_debug("trying to override keymap_%s for ct %p\n", pr_debug("trying to override keymap_%s for ct %p\n",
dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct); dir == IP_CT_DIR_REPLY ? "reply" : "orig", ct);
return -EEXIST; return -EEXIST;
...@@ -134,9 +129,9 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, ...@@ -134,9 +129,9 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
pr_debug("adding new entry %p: ", km); pr_debug("adding new entry %p: ", km);
nf_ct_dump_tuple(&km->tuple); nf_ct_dump_tuple(&km->tuple);
write_lock_bh(&net_gre->keymap_lock); spin_lock_bh(&keymap_lock);
list_add_tail(&km->list, &net_gre->keymap_list); list_add_tail(&km->list, &net_gre->keymap_list);
write_unlock_bh(&net_gre->keymap_lock); spin_unlock_bh(&keymap_lock);
return 0; return 0;
} }
...@@ -145,31 +140,29 @@ EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_add); ...@@ -145,31 +140,29 @@ EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_add);
/* destroy the keymap entries associated with specified master ct */ /* destroy the keymap entries associated with specified master ct */
void nf_ct_gre_keymap_destroy(struct nf_conn *ct) void nf_ct_gre_keymap_destroy(struct nf_conn *ct)
{ {
struct net *net = nf_ct_net(ct);
struct netns_proto_gre *net_gre = gre_pernet(net);
struct nf_ct_pptp_master *ct_pptp_info = nfct_help_data(ct); struct nf_ct_pptp_master *ct_pptp_info = nfct_help_data(ct);
enum ip_conntrack_dir dir; enum ip_conntrack_dir dir;
pr_debug("entering for ct %p\n", ct); pr_debug("entering for ct %p\n", ct);
write_lock_bh(&net_gre->keymap_lock); spin_lock_bh(&keymap_lock);
for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) { for (dir = IP_CT_DIR_ORIGINAL; dir < IP_CT_DIR_MAX; dir++) {
if (ct_pptp_info->keymap[dir]) { if (ct_pptp_info->keymap[dir]) {
pr_debug("removing %p from list\n", pr_debug("removing %p from list\n",
ct_pptp_info->keymap[dir]); ct_pptp_info->keymap[dir]);
list_del(&ct_pptp_info->keymap[dir]->list); list_del_rcu(&ct_pptp_info->keymap[dir]->list);
kfree(ct_pptp_info->keymap[dir]); kfree_rcu(ct_pptp_info->keymap[dir], rcu);
ct_pptp_info->keymap[dir] = NULL; ct_pptp_info->keymap[dir] = NULL;
} }
} }
write_unlock_bh(&net_gre->keymap_lock); spin_unlock_bh(&keymap_lock);
} }
EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_destroy); EXPORT_SYMBOL_GPL(nf_ct_gre_keymap_destroy);
/* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */ /* PUBLIC CONNTRACK PROTO HELPER FUNCTIONS */
/* gre hdr info to tuple */ /* gre hdr info to tuple */
static bool gre_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, 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)
{ {
const struct pptp_gre_header *pgrehdr; const struct pptp_gre_header *pgrehdr;
...@@ -216,11 +209,11 @@ static void gre_print_conntrack(struct seq_file *s, struct nf_conn *ct) ...@@ -216,11 +209,11 @@ static void gre_print_conntrack(struct seq_file *s, struct nf_conn *ct)
static unsigned int *gre_get_timeouts(struct net *net) static unsigned int *gre_get_timeouts(struct net *net)
{ {
return gre_pernet(net)->gre_timeouts; return gre_pernet(net)->timeouts;
} }
/* Returns verdict for packet, and may modify conntrack */ /* Returns verdict for packet, and may modify conntrack */
static int gre_packet(struct nf_conn *ct, int nf_conntrack_gre_packet(struct nf_conn *ct,
struct sk_buff *skb, struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
...@@ -256,19 +249,6 @@ static int gre_packet(struct nf_conn *ct, ...@@ -256,19 +249,6 @@ static int gre_packet(struct nf_conn *ct,
return NF_ACCEPT; return NF_ACCEPT;
} }
/* Called when a conntrack entry has already been removed from the hashes
* and is about to be deleted from memory */
static void gre_destroy(struct nf_conn *ct)
{
struct nf_conn *master = ct->master;
pr_debug(" entering\n");
if (!master)
pr_debug("no master !?!\n");
else
nf_ct_gre_keymap_destroy(master);
}
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT #ifdef CONFIG_NF_CONNTRACK_TIMEOUT
#include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nfnetlink.h>
...@@ -278,13 +258,13 @@ static int gre_timeout_nlattr_to_obj(struct nlattr *tb[], ...@@ -278,13 +258,13 @@ static int gre_timeout_nlattr_to_obj(struct nlattr *tb[],
struct net *net, void *data) struct net *net, void *data)
{ {
unsigned int *timeouts = data; unsigned int *timeouts = data;
struct netns_proto_gre *net_gre = gre_pernet(net); struct nf_gre_net *net_gre = gre_pernet(net);
if (!timeouts) if (!timeouts)
timeouts = gre_get_timeouts(net); 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->timeouts[GRE_CT_UNREPLIED];
timeouts[GRE_CT_REPLIED] = net_gre->gre_timeouts[GRE_CT_REPLIED]; timeouts[GRE_CT_REPLIED] = net_gre->timeouts[GRE_CT_REPLIED];
if (tb[CTA_TIMEOUT_GRE_UNREPLIED]) { if (tb[CTA_TIMEOUT_GRE_UNREPLIED]) {
timeouts[GRE_CT_UNREPLIED] = timeouts[GRE_CT_UNREPLIED] =
...@@ -320,69 +300,22 @@ gre_timeout_nla_policy[CTA_TIMEOUT_GRE_MAX+1] = { ...@@ -320,69 +300,22 @@ gre_timeout_nla_policy[CTA_TIMEOUT_GRE_MAX+1] = {
}; };
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
#ifdef CONFIG_SYSCTL void nf_conntrack_gre_init_net(struct net *net)
static struct ctl_table gre_sysctl_table[] = {
{
.procname = "nf_conntrack_gre_timeout",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_gre_timeout_stream",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{}
};
#endif
static int gre_kmemdup_sysctl_table(struct net *net, struct nf_proto_net *nf,
struct netns_proto_gre *net_gre)
{
#ifdef CONFIG_SYSCTL
int i;
if (nf->ctl_table)
return 0;
nf->ctl_table = kmemdup(gre_sysctl_table,
sizeof(gre_sysctl_table),
GFP_KERNEL);
if (!nf->ctl_table)
return -ENOMEM;
for (i = 0; i < GRE_CT_MAX; i++)
nf->ctl_table[i].data = &net_gre->gre_timeouts[i];
#endif
return 0;
}
static int gre_init_net(struct net *net)
{ {
struct netns_proto_gre *net_gre = gre_pernet(net); struct nf_gre_net *net_gre = gre_pernet(net);
struct nf_proto_net *nf = &net_gre->nf;
int i; int i;
rwlock_init(&net_gre->keymap_lock);
INIT_LIST_HEAD(&net_gre->keymap_list); INIT_LIST_HEAD(&net_gre->keymap_list);
for (i = 0; i < GRE_CT_MAX; i++) for (i = 0; i < GRE_CT_MAX; i++)
net_gre->gre_timeouts[i] = gre_timeouts[i]; net_gre->timeouts[i] = gre_timeouts[i];
return gre_kmemdup_sysctl_table(net, nf, net_gre);
} }
/* protocol helper struct */ /* protocol helper struct */
static const struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = { const struct nf_conntrack_l4proto nf_conntrack_l4proto_gre = {
.l4proto = IPPROTO_GRE, .l4proto = IPPROTO_GRE,
.pkt_to_tuple = gre_pkt_to_tuple,
#ifdef CONFIG_NF_CONNTRACK_PROCFS #ifdef CONFIG_NF_CONNTRACK_PROCFS
.print_conntrack = gre_print_conntrack, .print_conntrack = gre_print_conntrack,
#endif #endif
.packet = gre_packet,
.destroy = gre_destroy,
.me = THIS_MODULE,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
.tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
.nlattr_tuple_size = nf_ct_port_nlattr_tuple_size, .nlattr_tuple_size = nf_ct_port_nlattr_tuple_size,
...@@ -398,61 +331,4 @@ static const struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = { ...@@ -398,61 +331,4 @@ static const struct nf_conntrack_l4proto nf_conntrack_l4proto_gre4 = {
.nla_policy = gre_timeout_nla_policy, .nla_policy = gre_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
.net_id = &proto_gre_net_id,
.init_net = gre_init_net,
}; };
static int proto_gre_net_init(struct net *net)
{
int ret = 0;
ret = nf_ct_l4proto_pernet_register_one(net,
&nf_conntrack_l4proto_gre4);
if (ret < 0)
pr_err("nf_conntrack_gre4: pernet registration failed.\n");
return ret;
}
static void proto_gre_net_exit(struct net *net)
{
nf_ct_l4proto_pernet_unregister_one(net, &nf_conntrack_l4proto_gre4);
nf_ct_gre_keymap_flush(net);
}
static struct pernet_operations proto_gre_net_ops = {
.init = proto_gre_net_init,
.exit = proto_gre_net_exit,
.id = &proto_gre_net_id,
.size = sizeof(struct netns_proto_gre),
};
static int __init nf_ct_proto_gre_init(void)
{
int ret;
BUILD_BUG_ON(offsetof(struct netns_proto_gre, nf) != 0);
ret = register_pernet_subsys(&proto_gre_net_ops);
if (ret < 0)
goto out_pernet;
ret = nf_ct_l4proto_register_one(&nf_conntrack_l4proto_gre4);
if (ret < 0)
goto out_gre4;
return 0;
out_gre4:
unregister_pernet_subsys(&proto_gre_net_ops);
out_pernet:
return ret;
}
static void __exit nf_ct_proto_gre_fini(void)
{
nf_ct_l4proto_unregister_one(&nf_conntrack_l4proto_gre4);
unregister_pernet_subsys(&proto_gre_net_ops);
}
module_init(nf_ct_proto_gre_init);
module_exit(nf_ct_proto_gre_fini);
MODULE_LICENSE("GPL");
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
static const unsigned int nf_ct_icmp_timeout = 30*HZ; static const unsigned int nf_ct_icmp_timeout = 30*HZ;
static bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, bool icmp_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)
{ {
const struct icmphdr *hp; const struct icmphdr *hp;
...@@ -54,7 +54,7 @@ static const u_int8_t invmap[] = { ...@@ -54,7 +54,7 @@ static const u_int8_t invmap[] = {
[ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1 [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1
}; };
static bool icmp_invert_tuple(struct nf_conntrack_tuple *tuple, bool nf_conntrack_invert_icmp_tuple(struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *orig) const struct nf_conntrack_tuple *orig)
{ {
if (orig->dst.u.icmp.type >= sizeof(invmap) || if (orig->dst.u.icmp.type >= sizeof(invmap) ||
...@@ -68,9 +68,8 @@ static bool icmp_invert_tuple(struct nf_conntrack_tuple *tuple, ...@@ -68,9 +68,8 @@ static bool icmp_invert_tuple(struct nf_conntrack_tuple *tuple,
} }
/* Returns verdict for packet, or -1 for invalid. */ /* Returns verdict for packet, or -1 for invalid. */
static int icmp_packet(struct nf_conn *ct, int nf_conntrack_icmp_packet(struct nf_conn *ct,
struct sk_buff *skb, struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
const struct nf_hook_state *state) const struct nf_hook_state *state)
{ {
...@@ -110,7 +109,6 @@ icmp_error_message(struct nf_conn *tmpl, struct sk_buff *skb, ...@@ -110,7 +109,6 @@ icmp_error_message(struct nf_conn *tmpl, struct sk_buff *skb,
const struct nf_hook_state *state) const struct nf_hook_state *state)
{ {
struct nf_conntrack_tuple innertuple, origtuple; struct nf_conntrack_tuple innertuple, origtuple;
const struct nf_conntrack_l4proto *innerproto;
const struct nf_conntrack_tuple_hash *h; const struct nf_conntrack_tuple_hash *h;
const struct nf_conntrack_zone *zone; const struct nf_conntrack_zone *zone;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
...@@ -128,12 +126,9 @@ icmp_error_message(struct nf_conn *tmpl, struct sk_buff *skb, ...@@ -128,12 +126,9 @@ icmp_error_message(struct nf_conn *tmpl, struct sk_buff *skb,
return -NF_ACCEPT; return -NF_ACCEPT;
} }
/* rcu_read_lock()ed by nf_hook_thresh */
innerproto = __nf_ct_l4proto_find(origtuple.dst.protonum);
/* 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, innerproto)) { if (!nf_ct_invert_tuple(&innertuple, &origtuple)) {
pr_debug("icmp_error_message: no match\n"); pr_debug("icmp_error_message: no match\n");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
...@@ -303,56 +298,16 @@ icmp_timeout_nla_policy[CTA_TIMEOUT_ICMP_MAX+1] = { ...@@ -303,56 +298,16 @@ icmp_timeout_nla_policy[CTA_TIMEOUT_ICMP_MAX+1] = {
}; };
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
#ifdef CONFIG_SYSCTL void nf_conntrack_icmp_init_net(struct net *net)
static struct ctl_table icmp_sysctl_table[] = {
{
.procname = "nf_conntrack_icmp_timeout",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{ }
};
#endif /* CONFIG_SYSCTL */
static int icmp_kmemdup_sysctl_table(struct nf_proto_net *pn,
struct nf_icmp_net *in)
{
#ifdef CONFIG_SYSCTL
pn->ctl_table = kmemdup(icmp_sysctl_table,
sizeof(icmp_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_table)
return -ENOMEM;
pn->ctl_table[0].data = &in->timeout;
#endif
return 0;
}
static int icmp_init_net(struct net *net)
{ {
struct nf_icmp_net *in = nf_icmp_pernet(net); struct nf_icmp_net *in = nf_icmp_pernet(net);
struct nf_proto_net *pn = &in->pn;
in->timeout = nf_ct_icmp_timeout; in->timeout = nf_ct_icmp_timeout;
return icmp_kmemdup_sysctl_table(pn, in);
}
static struct nf_proto_net *icmp_get_net_proto(struct net *net)
{
return &net->ct.nf_ct_proto.icmp.pn;
} }
const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp =
{ {
.l4proto = IPPROTO_ICMP, .l4proto = IPPROTO_ICMP,
.pkt_to_tuple = icmp_pkt_to_tuple,
.invert_tuple = icmp_invert_tuple,
.packet = icmp_packet,
.destroy = NULL,
.me = NULL,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
.tuple_to_nlattr = icmp_tuple_to_nlattr, .tuple_to_nlattr = icmp_tuple_to_nlattr,
.nlattr_tuple_size = icmp_nlattr_tuple_size, .nlattr_tuple_size = icmp_nlattr_tuple_size,
...@@ -368,6 +323,4 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = ...@@ -368,6 +323,4 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp =
.nla_policy = icmp_timeout_nla_policy, .nla_policy = icmp_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
.init_net = icmp_init_net,
.get_net_proto = icmp_get_net_proto,
}; };
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
static const unsigned int nf_ct_icmpv6_timeout = 30*HZ; static const unsigned int nf_ct_icmpv6_timeout = 30*HZ;
static bool icmpv6_pkt_to_tuple(const struct sk_buff *skb, bool icmpv6_pkt_to_tuple(const struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
struct net *net, struct net *net,
struct nf_conntrack_tuple *tuple) struct nf_conntrack_tuple *tuple)
...@@ -67,7 +67,7 @@ static const u_int8_t noct_valid_new[] = { ...@@ -67,7 +67,7 @@ static const u_int8_t noct_valid_new[] = {
[ICMPV6_MLD2_REPORT - 130] = 1 [ICMPV6_MLD2_REPORT - 130] = 1
}; };
static bool icmpv6_invert_tuple(struct nf_conntrack_tuple *tuple, bool nf_conntrack_invert_icmpv6_tuple(struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple *orig) const struct nf_conntrack_tuple *orig)
{ {
int type = orig->dst.u.icmp.type - 128; int type = orig->dst.u.icmp.type - 128;
...@@ -86,9 +86,8 @@ static unsigned int *icmpv6_get_timeouts(struct net *net) ...@@ -86,9 +86,8 @@ static unsigned int *icmpv6_get_timeouts(struct net *net)
} }
/* Returns verdict for packet, or -1 for invalid. */ /* Returns verdict for packet, or -1 for invalid. */
static int icmpv6_packet(struct nf_conn *ct, int nf_conntrack_icmpv6_packet(struct nf_conn *ct,
struct sk_buff *skb, struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
const struct nf_hook_state *state) const struct nf_hook_state *state)
{ {
...@@ -131,7 +130,6 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl, ...@@ -131,7 +130,6 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl,
{ {
struct nf_conntrack_tuple intuple, origtuple; struct nf_conntrack_tuple intuple, origtuple;
const struct nf_conntrack_tuple_hash *h; const struct nf_conntrack_tuple_hash *h;
const struct nf_conntrack_l4proto *inproto;
enum ip_conntrack_info ctinfo; enum ip_conntrack_info ctinfo;
struct nf_conntrack_zone tmp; struct nf_conntrack_zone tmp;
...@@ -147,12 +145,9 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl, ...@@ -147,12 +145,9 @@ icmpv6_error_message(struct net *net, struct nf_conn *tmpl,
return -NF_ACCEPT; return -NF_ACCEPT;
} }
/* rcu_read_lock()ed by nf_hook_thresh */
inproto = __nf_ct_l4proto_find(origtuple.dst.protonum);
/* 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, inproto)) { if (!nf_ct_invert_tuple(&intuple, &origtuple)) {
pr_debug("icmpv6_error: Can't invert tuple\n"); pr_debug("icmpv6_error: Can't invert tuple\n");
return -NF_ACCEPT; return -NF_ACCEPT;
} }
...@@ -314,54 +309,16 @@ icmpv6_timeout_nla_policy[CTA_TIMEOUT_ICMPV6_MAX+1] = { ...@@ -314,54 +309,16 @@ icmpv6_timeout_nla_policy[CTA_TIMEOUT_ICMPV6_MAX+1] = {
}; };
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
#ifdef CONFIG_SYSCTL void nf_conntrack_icmpv6_init_net(struct net *net)
static struct ctl_table icmpv6_sysctl_table[] = {
{
.procname = "nf_conntrack_icmpv6_timeout",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{ }
};
#endif /* CONFIG_SYSCTL */
static int icmpv6_kmemdup_sysctl_table(struct nf_proto_net *pn,
struct nf_icmp_net *in)
{
#ifdef CONFIG_SYSCTL
pn->ctl_table = kmemdup(icmpv6_sysctl_table,
sizeof(icmpv6_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_table)
return -ENOMEM;
pn->ctl_table[0].data = &in->timeout;
#endif
return 0;
}
static int icmpv6_init_net(struct net *net)
{ {
struct nf_icmp_net *in = nf_icmpv6_pernet(net); struct nf_icmp_net *in = nf_icmpv6_pernet(net);
struct nf_proto_net *pn = &in->pn;
in->timeout = nf_ct_icmpv6_timeout; in->timeout = nf_ct_icmpv6_timeout;
return icmpv6_kmemdup_sysctl_table(pn, in);
}
static struct nf_proto_net *icmpv6_get_net_proto(struct net *net)
{
return &net->ct.nf_ct_proto.icmpv6.pn;
} }
const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 =
{ {
.l4proto = IPPROTO_ICMPV6, .l4proto = IPPROTO_ICMPV6,
.pkt_to_tuple = icmpv6_pkt_to_tuple,
.invert_tuple = icmpv6_invert_tuple,
.packet = icmpv6_packet,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
.tuple_to_nlattr = icmpv6_tuple_to_nlattr, .tuple_to_nlattr = icmpv6_tuple_to_nlattr,
.nlattr_tuple_size = icmpv6_nlattr_tuple_size, .nlattr_tuple_size = icmpv6_nlattr_tuple_size,
...@@ -377,6 +334,4 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 = ...@@ -377,6 +334,4 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6 =
.nla_policy = icmpv6_timeout_nla_policy, .nla_policy = icmpv6_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
.init_net = icmpv6_init_net,
.get_net_proto = icmpv6_get_net_proto,
}; };
...@@ -357,7 +357,7 @@ static bool sctp_error(struct sk_buff *skb, ...@@ -357,7 +357,7 @@ static bool sctp_error(struct sk_buff *skb,
} }
/* 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, int nf_conntrack_sctp_packet(struct nf_conn *ct,
struct sk_buff *skb, struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
...@@ -642,99 +642,9 @@ sctp_timeout_nla_policy[CTA_TIMEOUT_SCTP_MAX+1] = { ...@@ -642,99 +642,9 @@ sctp_timeout_nla_policy[CTA_TIMEOUT_SCTP_MAX+1] = {
}; };
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
void nf_conntrack_sctp_init_net(struct net *net)
#ifdef CONFIG_SYSCTL
static struct ctl_table sctp_sysctl_table[] = {
{
.procname = "nf_conntrack_sctp_timeout_closed",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_cookie_wait",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_cookie_echoed",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_established",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_shutdown_sent",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_shutdown_recd",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_shutdown_ack_sent",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_heartbeat_sent",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_sctp_timeout_heartbeat_acked",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{ }
};
#endif
static int sctp_kmemdup_sysctl_table(struct nf_proto_net *pn,
struct nf_sctp_net *sn)
{
#ifdef CONFIG_SYSCTL
if (pn->ctl_table)
return 0;
pn->ctl_table = kmemdup(sctp_sysctl_table,
sizeof(sctp_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_table)
return -ENOMEM;
pn->ctl_table[0].data = &sn->timeouts[SCTP_CONNTRACK_CLOSED];
pn->ctl_table[1].data = &sn->timeouts[SCTP_CONNTRACK_COOKIE_WAIT];
pn->ctl_table[2].data = &sn->timeouts[SCTP_CONNTRACK_COOKIE_ECHOED];
pn->ctl_table[3].data = &sn->timeouts[SCTP_CONNTRACK_ESTABLISHED];
pn->ctl_table[4].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_SENT];
pn->ctl_table[5].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_RECD];
pn->ctl_table[6].data = &sn->timeouts[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT];
pn->ctl_table[7].data = &sn->timeouts[SCTP_CONNTRACK_HEARTBEAT_SENT];
pn->ctl_table[8].data = &sn->timeouts[SCTP_CONNTRACK_HEARTBEAT_ACKED];
#endif
return 0;
}
static int sctp_init_net(struct net *net)
{ {
struct nf_sctp_net *sn = nf_sctp_pernet(net); struct nf_sctp_net *sn = nf_sctp_pernet(net);
struct nf_proto_net *pn = &sn->pn;
if (!pn->users) {
int i; int i;
for (i = 0; i < SCTP_CONNTRACK_MAX; i++) for (i = 0; i < SCTP_CONNTRACK_MAX; i++)
...@@ -744,14 +654,6 @@ static int sctp_init_net(struct net *net) ...@@ -744,14 +654,6 @@ static int sctp_init_net(struct net *net)
* 'new' timeout, like udp or icmp. * 'new' timeout, like udp or icmp.
*/ */
sn->timeouts[0] = sctp_timeouts[SCTP_CONNTRACK_CLOSED]; sn->timeouts[0] = sctp_timeouts[SCTP_CONNTRACK_CLOSED];
}
return sctp_kmemdup_sysctl_table(pn, sn);
}
static struct nf_proto_net *sctp_get_net_proto(struct net *net)
{
return &net->ct.nf_ct_proto.sctp.pn;
} }
const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp = { const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp = {
...@@ -759,9 +661,7 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp = { ...@@ -759,9 +661,7 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp = {
#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,
.can_early_drop = sctp_can_early_drop, .can_early_drop = sctp_can_early_drop,
.me = THIS_MODULE,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
.nlattr_size = SCTP_NLATTR_SIZE, .nlattr_size = SCTP_NLATTR_SIZE,
.to_nlattr = sctp_to_nlattr, .to_nlattr = sctp_to_nlattr,
...@@ -780,6 +680,4 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp = { ...@@ -780,6 +680,4 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp = {
.nla_policy = sctp_timeout_nla_policy, .nla_policy = sctp_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
.init_net = sctp_init_net,
.get_net_proto = sctp_get_net_proto,
}; };
...@@ -829,7 +829,7 @@ static noinline bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb, ...@@ -829,7 +829,7 @@ static noinline bool tcp_new(struct nf_conn *ct, const struct sk_buff *skb,
} }
/* Returns verdict for packet, or -1 for invalid. */ /* Returns verdict for packet, or -1 for invalid. */
static int tcp_packet(struct nf_conn *ct, int nf_conntrack_tcp_packet(struct nf_conn *ct,
struct sk_buff *skb, struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
...@@ -1387,126 +1387,9 @@ static const struct nla_policy tcp_timeout_nla_policy[CTA_TIMEOUT_TCP_MAX+1] = { ...@@ -1387,126 +1387,9 @@ static const struct nla_policy tcp_timeout_nla_policy[CTA_TIMEOUT_TCP_MAX+1] = {
}; };
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
#ifdef CONFIG_SYSCTL void nf_conntrack_tcp_init_net(struct net *net)
static struct ctl_table tcp_sysctl_table[] = {
{
.procname = "nf_conntrack_tcp_timeout_syn_sent",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_syn_recv",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_established",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_fin_wait",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_close_wait",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_last_ack",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_time_wait",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_close",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_max_retrans",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_timeout_unacknowledged",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_tcp_loose",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "nf_conntrack_tcp_be_liberal",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{
.procname = "nf_conntrack_tcp_max_retrans",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec,
},
{ }
};
#endif /* CONFIG_SYSCTL */
static int tcp_kmemdup_sysctl_table(struct nf_proto_net *pn,
struct nf_tcp_net *tn)
{
#ifdef CONFIG_SYSCTL
if (pn->ctl_table)
return 0;
pn->ctl_table = kmemdup(tcp_sysctl_table,
sizeof(tcp_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_table)
return -ENOMEM;
pn->ctl_table[0].data = &tn->timeouts[TCP_CONNTRACK_SYN_SENT];
pn->ctl_table[1].data = &tn->timeouts[TCP_CONNTRACK_SYN_RECV];
pn->ctl_table[2].data = &tn->timeouts[TCP_CONNTRACK_ESTABLISHED];
pn->ctl_table[3].data = &tn->timeouts[TCP_CONNTRACK_FIN_WAIT];
pn->ctl_table[4].data = &tn->timeouts[TCP_CONNTRACK_CLOSE_WAIT];
pn->ctl_table[5].data = &tn->timeouts[TCP_CONNTRACK_LAST_ACK];
pn->ctl_table[6].data = &tn->timeouts[TCP_CONNTRACK_TIME_WAIT];
pn->ctl_table[7].data = &tn->timeouts[TCP_CONNTRACK_CLOSE];
pn->ctl_table[8].data = &tn->timeouts[TCP_CONNTRACK_RETRANS];
pn->ctl_table[9].data = &tn->timeouts[TCP_CONNTRACK_UNACK];
pn->ctl_table[10].data = &tn->tcp_loose;
pn->ctl_table[11].data = &tn->tcp_be_liberal;
pn->ctl_table[12].data = &tn->tcp_max_retrans;
#endif
return 0;
}
static int tcp_init_net(struct net *net)
{ {
struct nf_tcp_net *tn = nf_tcp_pernet(net); struct nf_tcp_net *tn = nf_tcp_pernet(net);
struct nf_proto_net *pn = &tn->pn;
if (!pn->users) {
int i; int i;
for (i = 0; i < TCP_CONNTRACK_TIMEOUT_MAX; i++) for (i = 0; i < TCP_CONNTRACK_TIMEOUT_MAX; i++)
...@@ -1519,14 +1402,6 @@ static int tcp_init_net(struct net *net) ...@@ -1519,14 +1402,6 @@ static int tcp_init_net(struct net *net)
tn->tcp_loose = nf_ct_tcp_loose; tn->tcp_loose = nf_ct_tcp_loose;
tn->tcp_be_liberal = nf_ct_tcp_be_liberal; tn->tcp_be_liberal = nf_ct_tcp_be_liberal;
tn->tcp_max_retrans = nf_ct_tcp_max_retrans; tn->tcp_max_retrans = nf_ct_tcp_max_retrans;
}
return tcp_kmemdup_sysctl_table(pn, tn);
}
static struct nf_proto_net *tcp_get_net_proto(struct net *net)
{
return &net->ct.nf_ct_proto.tcp.pn;
} }
const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp = const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp =
...@@ -1535,7 +1410,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp = ...@@ -1535,7 +1410,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp =
#ifdef CONFIG_NF_CONNTRACK_PROCFS #ifdef CONFIG_NF_CONNTRACK_PROCFS
.print_conntrack = tcp_print_conntrack, .print_conntrack = tcp_print_conntrack,
#endif #endif
.packet = tcp_packet,
.can_early_drop = tcp_can_early_drop, .can_early_drop = tcp_can_early_drop,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
.to_nlattr = tcp_to_nlattr, .to_nlattr = tcp_to_nlattr,
...@@ -1556,6 +1430,4 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp = ...@@ -1556,6 +1430,4 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp =
.nla_policy = tcp_timeout_nla_policy, .nla_policy = tcp_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
.init_net = tcp_init_net,
.get_net_proto = tcp_get_net_proto,
}; };
...@@ -85,7 +85,7 @@ static bool udp_error(struct sk_buff *skb, ...@@ -85,7 +85,7 @@ static bool udp_error(struct sk_buff *skb,
} }
/* Returns verdict for packet, and may modify conntracktype */ /* Returns verdict for packet, and may modify conntracktype */
static int udp_packet(struct nf_conn *ct, int nf_conntrack_udp_packet(struct nf_conn *ct,
struct sk_buff *skb, struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
...@@ -177,7 +177,7 @@ static bool udplite_error(struct sk_buff *skb, ...@@ -177,7 +177,7 @@ static bool udplite_error(struct sk_buff *skb,
} }
/* Returns verdict for packet, and may modify conntracktype */ /* Returns verdict for packet, and may modify conntracktype */
static int udplite_packet(struct nf_conn *ct, int nf_conntrack_udplite_packet(struct nf_conn *ct,
struct sk_buff *skb, struct sk_buff *skb,
unsigned int dataoff, unsigned int dataoff,
enum ip_conntrack_info ctinfo, enum ip_conntrack_info ctinfo,
...@@ -260,66 +260,19 @@ udp_timeout_nla_policy[CTA_TIMEOUT_UDP_MAX+1] = { ...@@ -260,66 +260,19 @@ udp_timeout_nla_policy[CTA_TIMEOUT_UDP_MAX+1] = {
}; };
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
#ifdef CONFIG_SYSCTL void nf_conntrack_udp_init_net(struct net *net)
static struct ctl_table udp_sysctl_table[] = {
{
.procname = "nf_conntrack_udp_timeout",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{
.procname = "nf_conntrack_udp_timeout_stream",
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_jiffies,
},
{ }
};
#endif /* CONFIG_SYSCTL */
static int udp_kmemdup_sysctl_table(struct nf_proto_net *pn,
struct nf_udp_net *un)
{
#ifdef CONFIG_SYSCTL
if (pn->ctl_table)
return 0;
pn->ctl_table = kmemdup(udp_sysctl_table,
sizeof(udp_sysctl_table),
GFP_KERNEL);
if (!pn->ctl_table)
return -ENOMEM;
pn->ctl_table[0].data = &un->timeouts[UDP_CT_UNREPLIED];
pn->ctl_table[1].data = &un->timeouts[UDP_CT_REPLIED];
#endif
return 0;
}
static int udp_init_net(struct net *net)
{ {
struct nf_udp_net *un = nf_udp_pernet(net); struct nf_udp_net *un = nf_udp_pernet(net);
struct nf_proto_net *pn = &un->pn;
if (!pn->users) {
int i; int i;
for (i = 0; i < UDP_CT_MAX; i++) for (i = 0; i < UDP_CT_MAX; i++)
un->timeouts[i] = udp_timeouts[i]; un->timeouts[i] = udp_timeouts[i];
}
return udp_kmemdup_sysctl_table(pn, un);
}
static struct nf_proto_net *udp_get_net_proto(struct net *net)
{
return &net->ct.nf_ct_proto.udp.pn;
} }
const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp = const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp =
{ {
.l4proto = IPPROTO_UDP, .l4proto = IPPROTO_UDP,
.allow_clash = true, .allow_clash = true,
.packet = udp_packet,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
.tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
.nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
...@@ -335,8 +288,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp = ...@@ -335,8 +288,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp =
.nla_policy = udp_timeout_nla_policy, .nla_policy = udp_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
.init_net = udp_init_net,
.get_net_proto = udp_get_net_proto,
}; };
#ifdef CONFIG_NF_CT_PROTO_UDPLITE #ifdef CONFIG_NF_CT_PROTO_UDPLITE
...@@ -344,7 +295,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite = ...@@ -344,7 +295,6 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite =
{ {
.l4proto = IPPROTO_UDPLITE, .l4proto = IPPROTO_UDPLITE,
.allow_clash = true, .allow_clash = true,
.packet = udplite_packet,
#if IS_ENABLED(CONFIG_NF_CT_NETLINK) #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
.tuple_to_nlattr = nf_ct_port_tuple_to_nlattr, .tuple_to_nlattr = nf_ct_port_tuple_to_nlattr,
.nlattr_to_tuple = nf_ct_port_nlattr_to_tuple, .nlattr_to_tuple = nf_ct_port_nlattr_to_tuple,
...@@ -360,7 +310,5 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite = ...@@ -360,7 +310,5 @@ const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite =
.nla_policy = udp_timeout_nla_policy, .nla_policy = udp_timeout_nla_policy,
}, },
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
.init_net = udp_init_net,
.get_net_proto = udp_get_net_proto,
}; };
#endif #endif
This diff is collapsed.
...@@ -121,7 +121,7 @@ static void flow_offload_fixup_ct_state(struct nf_conn *ct) ...@@ -121,7 +121,7 @@ static void flow_offload_fixup_ct_state(struct nf_conn *ct)
if (l4num == IPPROTO_TCP) if (l4num == IPPROTO_TCP)
flow_offload_fixup_tcp(&ct->proto.tcp); flow_offload_fixup_tcp(&ct->proto.tcp);
l4proto = __nf_ct_l4proto_find(l4num); l4proto = nf_ct_l4proto_find(l4num);
if (!l4proto) if (!l4proto)
return; return;
......
...@@ -146,7 +146,7 @@ hash_by_src(const struct net *n, const struct nf_conntrack_tuple *tuple) ...@@ -146,7 +146,7 @@ hash_by_src(const struct net *n, const struct nf_conntrack_tuple *tuple)
} }
/* Is this tuple already taken? (not by us) */ /* Is this tuple already taken? (not by us) */
int static int
nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple, nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack) const struct nf_conn *ignored_conntrack)
{ {
...@@ -158,10 +158,9 @@ nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple, ...@@ -158,10 +158,9 @@ nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple,
*/ */
struct nf_conntrack_tuple reply; struct nf_conntrack_tuple reply;
nf_ct_invert_tuplepr(&reply, tuple); nf_ct_invert_tuple(&reply, tuple);
return nf_conntrack_tuple_taken(&reply, ignored_conntrack); return nf_conntrack_tuple_taken(&reply, ignored_conntrack);
} }
EXPORT_SYMBOL(nf_nat_used_tuple);
static bool nf_nat_inet_in_range(const struct nf_conntrack_tuple *t, static bool nf_nat_inet_in_range(const struct nf_conntrack_tuple *t,
const struct nf_nat_range2 *range) const struct nf_nat_range2 *range)
...@@ -253,7 +252,7 @@ find_appropriate_src(struct net *net, ...@@ -253,7 +252,7 @@ find_appropriate_src(struct net *net,
net_eq(net, nf_ct_net(ct)) && net_eq(net, nf_ct_net(ct)) &&
nf_ct_zone_equal(ct, zone, IP_CT_DIR_ORIGINAL)) { nf_ct_zone_equal(ct, zone, IP_CT_DIR_ORIGINAL)) {
/* Copy source part from reply tuple. */ /* Copy source part from reply tuple. */
nf_ct_invert_tuplepr(result, nf_ct_invert_tuple(result,
&ct->tuplehash[IP_CT_DIR_REPLY].tuple); &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
result->dst = tuple->dst; result->dst = tuple->dst;
...@@ -560,7 +559,7 @@ nf_nat_setup_info(struct nf_conn *ct, ...@@ -560,7 +559,7 @@ nf_nat_setup_info(struct nf_conn *ct,
* manipulations (future optimization: if num_manips == 0, * manipulations (future optimization: if num_manips == 0,
* orig_tp = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple) * orig_tp = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple)
*/ */
nf_ct_invert_tuplepr(&curr_tuple, nf_ct_invert_tuple(&curr_tuple,
&ct->tuplehash[IP_CT_DIR_REPLY].tuple); &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
get_unique_tuple(&new_tuple, &curr_tuple, range, ct, maniptype); get_unique_tuple(&new_tuple, &curr_tuple, range, ct, maniptype);
...@@ -569,7 +568,7 @@ nf_nat_setup_info(struct nf_conn *ct, ...@@ -569,7 +568,7 @@ nf_nat_setup_info(struct nf_conn *ct,
struct nf_conntrack_tuple reply; struct nf_conntrack_tuple reply;
/* Alter conntrack table so will recognize replies. */ /* Alter conntrack table so will recognize replies. */
nf_ct_invert_tuplepr(&reply, &new_tuple); nf_ct_invert_tuple(&reply, &new_tuple);
nf_conntrack_alter_reply(ct, &reply); nf_conntrack_alter_reply(ct, &reply);
/* Non-atomic: we own this at the moment. */ /* Non-atomic: we own this at the moment. */
...@@ -640,7 +639,7 @@ static unsigned int nf_nat_manip_pkt(struct sk_buff *skb, struct nf_conn *ct, ...@@ -640,7 +639,7 @@ static unsigned int nf_nat_manip_pkt(struct sk_buff *skb, struct nf_conn *ct,
struct nf_conntrack_tuple target; struct nf_conntrack_tuple target;
/* We are aiming to look like inverse of other direction. */ /* We are aiming to look like inverse of other direction. */
nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); nf_ct_invert_tuple(&target, &ct->tuplehash[!dir].tuple);
l3proto = __nf_nat_l3proto_find(target.src.l3num); l3proto = __nf_nat_l3proto_find(target.src.l3num);
if (!l3proto->manip_pkt(skb, 0, &target, mtype)) if (!l3proto->manip_pkt(skb, 0, &target, mtype))
......
This diff is collapsed.
...@@ -124,13 +124,24 @@ static void expr_call_ops_eval(const struct nft_expr *expr, ...@@ -124,13 +124,24 @@ static void expr_call_ops_eval(const struct nft_expr *expr,
struct nft_regs *regs, struct nft_regs *regs,
struct nft_pktinfo *pkt) struct nft_pktinfo *pkt)
{ {
#ifdef CONFIG_RETPOLINE
unsigned long e = (unsigned long)expr->ops->eval; unsigned long e = (unsigned long)expr->ops->eval;
#define X(e, fun) \
if (e == (unsigned long)nft_meta_get_eval) do { if ((e) == (unsigned long)(fun)) \
nft_meta_get_eval(expr, regs, pkt); return fun(expr, regs, pkt); } while (0)
else if (e == (unsigned long)nft_lookup_eval)
nft_lookup_eval(expr, regs, pkt); X(e, nft_payload_eval);
else X(e, nft_cmp_eval);
X(e, nft_meta_get_eval);
X(e, nft_lookup_eval);
X(e, nft_range_eval);
X(e, nft_immediate_eval);
X(e, nft_byteorder_eval);
X(e, nft_dynset_eval);
X(e, nft_rt_get_eval);
X(e, nft_bitwise_eval);
#undef X
#endif /* CONFIG_RETPOLINE */
expr->ops->eval(expr, regs, pkt); expr->ops->eval(expr, regs, pkt);
} }
......
...@@ -122,7 +122,7 @@ static int cttimeout_new_timeout(struct net *net, struct sock *ctnl, ...@@ -122,7 +122,7 @@ static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
return -EBUSY; return -EBUSY;
} }
l4proto = nf_ct_l4proto_find_get(l4num); l4proto = nf_ct_l4proto_find(l4num);
/* This protocol is not supportted, skip. */ /* This protocol is not supportted, skip. */
if (l4proto->l4proto != l4num) { if (l4proto->l4proto != l4num) {
...@@ -152,7 +152,6 @@ static int cttimeout_new_timeout(struct net *net, struct sock *ctnl, ...@@ -152,7 +152,6 @@ static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
err: err:
kfree(timeout); kfree(timeout);
err_proto_put: err_proto_put:
nf_ct_l4proto_put(l4proto);
return ret; return ret;
} }
...@@ -302,7 +301,6 @@ static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout) ...@@ -302,7 +301,6 @@ static int ctnl_timeout_try_del(struct net *net, struct ctnl_timeout *timeout)
if (refcount_dec_if_one(&timeout->refcnt)) { if (refcount_dec_if_one(&timeout->refcnt)) {
/* We are protected by nfnl mutex. */ /* We are protected by nfnl mutex. */
list_del_rcu(&timeout->head); list_del_rcu(&timeout->head);
nf_ct_l4proto_put(timeout->timeout.l4proto);
nf_ct_untimeout(net, &timeout->timeout); nf_ct_untimeout(net, &timeout->timeout);
kfree_rcu(timeout, rcu_head); kfree_rcu(timeout, rcu_head);
} else { } else {
...@@ -359,7 +357,7 @@ static int cttimeout_default_set(struct net *net, struct sock *ctnl, ...@@ -359,7 +357,7 @@ static int cttimeout_default_set(struct net *net, struct sock *ctnl,
return -EINVAL; return -EINVAL;
l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
l4proto = nf_ct_l4proto_find_get(l4num); l4proto = nf_ct_l4proto_find(l4num);
/* This protocol is not supported, skip. */ /* This protocol is not supported, skip. */
if (l4proto->l4proto != l4num) { if (l4proto->l4proto != l4num) {
...@@ -372,10 +370,8 @@ static int cttimeout_default_set(struct net *net, struct sock *ctnl, ...@@ -372,10 +370,8 @@ static int cttimeout_default_set(struct net *net, struct sock *ctnl,
if (ret < 0) if (ret < 0)
goto err; goto err;
nf_ct_l4proto_put(l4proto);
return 0; return 0;
err: err:
nf_ct_l4proto_put(l4proto);
return ret; return ret;
} }
...@@ -442,7 +438,7 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, ...@@ -442,7 +438,7 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl,
l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO])); l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]); l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
l4proto = nf_ct_l4proto_find_get(l4num); l4proto = nf_ct_l4proto_find(l4num);
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
if (l4proto->l4proto != l4num) if (l4proto->l4proto != l4num)
...@@ -474,12 +470,7 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, ...@@ -474,12 +470,7 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl,
break; break;
case IPPROTO_GRE: case IPPROTO_GRE:
#ifdef CONFIG_NF_CT_PROTO_GRE #ifdef CONFIG_NF_CT_PROTO_GRE
if (l4proto->net_id) { timeouts = nf_gre_pernet(net)->timeouts;
struct netns_proto_gre *net_gre;
net_gre = net_generic(net, *l4proto->net_id);
timeouts = net_gre->gre_timeouts;
}
#endif #endif
break; break;
case 255: case 255:
...@@ -516,7 +507,6 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, ...@@ -516,7 +507,6 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl,
/* this avoids a loop in nfnetlink. */ /* this avoids a loop in nfnetlink. */
return ret == -EAGAIN ? -ENOBUFS : ret; return ret == -EAGAIN ? -ENOBUFS : ret;
err: err:
nf_ct_l4proto_put(l4proto);
return err; return err;
} }
...@@ -597,7 +587,6 @@ static void __net_exit cttimeout_net_exit(struct net *net) ...@@ -597,7 +587,6 @@ static void __net_exit cttimeout_net_exit(struct net *net)
list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list, head) { list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list, head) {
list_del_rcu(&cur->head); list_del_rcu(&cur->head);
nf_ct_l4proto_put(cur->timeout.l4proto);
if (refcount_dec_and_test(&cur->refcnt)) if (refcount_dec_and_test(&cur->refcnt))
kfree_rcu(cur, rcu_head); kfree_rcu(cur, rcu_head);
......
...@@ -25,9 +25,8 @@ struct nft_bitwise { ...@@ -25,9 +25,8 @@ struct nft_bitwise {
struct nft_data xor; struct nft_data xor;
}; };
static void nft_bitwise_eval(const struct nft_expr *expr, void nft_bitwise_eval(const struct nft_expr *expr,
struct nft_regs *regs, struct nft_regs *regs, const struct nft_pktinfo *pkt)
const struct nft_pktinfo *pkt)
{ {
const struct nft_bitwise *priv = nft_expr_priv(expr); const struct nft_bitwise *priv = nft_expr_priv(expr);
const u32 *src = &regs->data[priv->sreg]; const u32 *src = &regs->data[priv->sreg];
......
...@@ -26,7 +26,7 @@ struct nft_byteorder { ...@@ -26,7 +26,7 @@ struct nft_byteorder {
u8 size; u8 size;
}; };
static void nft_byteorder_eval(const struct nft_expr *expr, void nft_byteorder_eval(const struct nft_expr *expr,
struct nft_regs *regs, struct nft_regs *regs,
const struct nft_pktinfo *pkt) const struct nft_pktinfo *pkt)
{ {
......
...@@ -24,7 +24,7 @@ struct nft_cmp_expr { ...@@ -24,7 +24,7 @@ struct nft_cmp_expr {
enum nft_cmp_ops op:8; enum nft_cmp_ops op:8;
}; };
static void nft_cmp_eval(const struct nft_expr *expr, void nft_cmp_eval(const struct nft_expr *expr,
struct nft_regs *regs, struct nft_regs *regs,
const struct nft_pktinfo *pkt) const struct nft_pktinfo *pkt)
{ {
......
...@@ -104,7 +104,7 @@ static void nft_counter_obj_destroy(const struct nft_ctx *ctx, ...@@ -104,7 +104,7 @@ static void nft_counter_obj_destroy(const struct nft_ctx *ctx,
nft_counter_do_destroy(priv); nft_counter_do_destroy(priv);
} }
static void nft_counter_reset(struct nft_counter_percpu_priv __percpu *priv, static void nft_counter_reset(struct nft_counter_percpu_priv *priv,
struct nft_counter *total) struct nft_counter *total)
{ {
struct nft_counter *this_cpu; struct nft_counter *this_cpu;
......
...@@ -870,7 +870,7 @@ static int nft_ct_timeout_obj_init(const struct nft_ctx *ctx, ...@@ -870,7 +870,7 @@ static int nft_ct_timeout_obj_init(const struct nft_ctx *ctx,
l4num = nla_get_u8(tb[NFTA_CT_TIMEOUT_L4PROTO]); l4num = nla_get_u8(tb[NFTA_CT_TIMEOUT_L4PROTO]);
priv->l4proto = l4num; priv->l4proto = l4num;
l4proto = nf_ct_l4proto_find_get(l4num); l4proto = nf_ct_l4proto_find(l4num);
if (l4proto->l4proto != l4num) { if (l4proto->l4proto != l4num) {
ret = -EOPNOTSUPP; ret = -EOPNOTSUPP;
...@@ -902,7 +902,6 @@ static int nft_ct_timeout_obj_init(const struct nft_ctx *ctx, ...@@ -902,7 +902,6 @@ static int nft_ct_timeout_obj_init(const struct nft_ctx *ctx,
err_free_timeout: err_free_timeout:
kfree(timeout); kfree(timeout);
err_proto_put: err_proto_put:
nf_ct_l4proto_put(l4proto);
return ret; return ret;
} }
...@@ -913,7 +912,6 @@ static void nft_ct_timeout_obj_destroy(const struct nft_ctx *ctx, ...@@ -913,7 +912,6 @@ static void nft_ct_timeout_obj_destroy(const struct nft_ctx *ctx,
struct nf_ct_timeout *timeout = priv->timeout; struct nf_ct_timeout *timeout = priv->timeout;
nf_ct_untimeout(ctx->net, timeout); nf_ct_untimeout(ctx->net, timeout);
nf_ct_l4proto_put(timeout->l4proto);
nf_ct_netns_put(ctx->net, ctx->family); nf_ct_netns_put(ctx->net, ctx->family);
kfree(priv->timeout); kfree(priv->timeout);
} }
......
...@@ -62,9 +62,8 @@ static void *nft_dynset_new(struct nft_set *set, const struct nft_expr *expr, ...@@ -62,9 +62,8 @@ static void *nft_dynset_new(struct nft_set *set, const struct nft_expr *expr,
return NULL; return NULL;
} }
static void nft_dynset_eval(const struct nft_expr *expr, void nft_dynset_eval(const struct nft_expr *expr,
struct nft_regs *regs, struct nft_regs *regs, const struct nft_pktinfo *pkt)
const struct nft_pktinfo *pkt)
{ {
const struct nft_dynset *priv = nft_expr_priv(expr); const struct nft_dynset *priv = nft_expr_priv(expr);
struct nft_set *set = priv->set; struct nft_set *set = priv->set;
......
...@@ -25,7 +25,6 @@ struct nft_jhash { ...@@ -25,7 +25,6 @@ struct nft_jhash {
u32 modulus; u32 modulus;
u32 seed; u32 seed;
u32 offset; u32 offset;
struct nft_set *map;
}; };
static void nft_jhash_eval(const struct nft_expr *expr, static void nft_jhash_eval(const struct nft_expr *expr,
...@@ -42,33 +41,10 @@ static void nft_jhash_eval(const struct nft_expr *expr, ...@@ -42,33 +41,10 @@ static void nft_jhash_eval(const struct nft_expr *expr,
regs->data[priv->dreg] = h + priv->offset; regs->data[priv->dreg] = h + priv->offset;
} }
static void nft_jhash_map_eval(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
{
struct nft_jhash *priv = nft_expr_priv(expr);
const void *data = &regs->data[priv->sreg];
const struct nft_set *map = priv->map;
const struct nft_set_ext *ext;
u32 result;
bool found;
result = reciprocal_scale(jhash(data, priv->len, priv->seed),
priv->modulus) + priv->offset;
found = map->ops->lookup(nft_net(pkt), map, &result, &ext);
if (!found)
return;
nft_data_copy(&regs->data[priv->dreg],
nft_set_ext_data(ext), map->dlen);
}
struct nft_symhash { struct nft_symhash {
enum nft_registers dreg:8; enum nft_registers dreg:8;
u32 modulus; u32 modulus;
u32 offset; u32 offset;
struct nft_set *map;
}; };
static void nft_symhash_eval(const struct nft_expr *expr, static void nft_symhash_eval(const struct nft_expr *expr,
...@@ -84,28 +60,6 @@ static void nft_symhash_eval(const struct nft_expr *expr, ...@@ -84,28 +60,6 @@ static void nft_symhash_eval(const struct nft_expr *expr,
regs->data[priv->dreg] = h + priv->offset; regs->data[priv->dreg] = h + priv->offset;
} }
static void nft_symhash_map_eval(const struct nft_expr *expr,
struct nft_regs *regs,
const struct nft_pktinfo *pkt)
{
struct nft_symhash *priv = nft_expr_priv(expr);
struct sk_buff *skb = pkt->skb;
const struct nft_set *map = priv->map;
const struct nft_set_ext *ext;
u32 result;
bool found;
result = reciprocal_scale(__skb_get_hash_symmetric(skb),
priv->modulus) + priv->offset;
found = map->ops->lookup(nft_net(pkt), map, &result, &ext);
if (!found)
return;
nft_data_copy(&regs->data[priv->dreg],
nft_set_ext_data(ext), map->dlen);
}
static const struct nla_policy nft_hash_policy[NFTA_HASH_MAX + 1] = { static const struct nla_policy nft_hash_policy[NFTA_HASH_MAX + 1] = {
[NFTA_HASH_SREG] = { .type = NLA_U32 }, [NFTA_HASH_SREG] = { .type = NLA_U32 },
[NFTA_HASH_DREG] = { .type = NLA_U32 }, [NFTA_HASH_DREG] = { .type = NLA_U32 },
...@@ -114,9 +68,6 @@ static const struct nla_policy nft_hash_policy[NFTA_HASH_MAX + 1] = { ...@@ -114,9 +68,6 @@ static const struct nla_policy nft_hash_policy[NFTA_HASH_MAX + 1] = {
[NFTA_HASH_SEED] = { .type = NLA_U32 }, [NFTA_HASH_SEED] = { .type = NLA_U32 },
[NFTA_HASH_OFFSET] = { .type = NLA_U32 }, [NFTA_HASH_OFFSET] = { .type = NLA_U32 },
[NFTA_HASH_TYPE] = { .type = NLA_U32 }, [NFTA_HASH_TYPE] = { .type = NLA_U32 },
[NFTA_HASH_SET_NAME] = { .type = NLA_STRING,
.len = NFT_SET_MAXNAMELEN - 1 },
[NFTA_HASH_SET_ID] = { .type = NLA_U32 },
}; };
static int nft_jhash_init(const struct nft_ctx *ctx, static int nft_jhash_init(const struct nft_ctx *ctx,
...@@ -166,20 +117,6 @@ static int nft_jhash_init(const struct nft_ctx *ctx, ...@@ -166,20 +117,6 @@ static int nft_jhash_init(const struct nft_ctx *ctx,
NFT_DATA_VALUE, sizeof(u32)); NFT_DATA_VALUE, sizeof(u32));
} }
static int nft_jhash_map_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[])
{
struct nft_jhash *priv = nft_expr_priv(expr);
u8 genmask = nft_genmask_next(ctx->net);
nft_jhash_init(ctx, expr, tb);
priv->map = nft_set_lookup_global(ctx->net, ctx->table,
tb[NFTA_HASH_SET_NAME],
tb[NFTA_HASH_SET_ID], genmask);
return PTR_ERR_OR_ZERO(priv->map);
}
static int nft_symhash_init(const struct nft_ctx *ctx, static int nft_symhash_init(const struct nft_ctx *ctx,
const struct nft_expr *expr, const struct nft_expr *expr,
const struct nlattr * const tb[]) const struct nlattr * const tb[])
...@@ -206,20 +143,6 @@ static int nft_symhash_init(const struct nft_ctx *ctx, ...@@ -206,20 +143,6 @@ static int nft_symhash_init(const struct nft_ctx *ctx,
NFT_DATA_VALUE, sizeof(u32)); NFT_DATA_VALUE, sizeof(u32));
} }
static int nft_symhash_map_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[])
{
struct nft_jhash *priv = nft_expr_priv(expr);
u8 genmask = nft_genmask_next(ctx->net);
nft_symhash_init(ctx, expr, tb);
priv->map = nft_set_lookup_global(ctx->net, ctx->table,
tb[NFTA_HASH_SET_NAME],
tb[NFTA_HASH_SET_ID], genmask);
return PTR_ERR_OR_ZERO(priv->map);
}
static int nft_jhash_dump(struct sk_buff *skb, static int nft_jhash_dump(struct sk_buff *skb,
const struct nft_expr *expr) const struct nft_expr *expr)
{ {
...@@ -247,18 +170,6 @@ static int nft_jhash_dump(struct sk_buff *skb, ...@@ -247,18 +170,6 @@ static int nft_jhash_dump(struct sk_buff *skb,
return -1; return -1;
} }
static int nft_jhash_map_dump(struct sk_buff *skb,
const struct nft_expr *expr)
{
const struct nft_jhash *priv = nft_expr_priv(expr);
if (nft_jhash_dump(skb, expr) ||
nla_put_string(skb, NFTA_HASH_SET_NAME, priv->map->name))
return -1;
return 0;
}
static int nft_symhash_dump(struct sk_buff *skb, static int nft_symhash_dump(struct sk_buff *skb,
const struct nft_expr *expr) const struct nft_expr *expr)
{ {
...@@ -279,18 +190,6 @@ static int nft_symhash_dump(struct sk_buff *skb, ...@@ -279,18 +190,6 @@ static int nft_symhash_dump(struct sk_buff *skb,
return -1; return -1;
} }
static int nft_symhash_map_dump(struct sk_buff *skb,
const struct nft_expr *expr)
{
const struct nft_symhash *priv = nft_expr_priv(expr);
if (nft_symhash_dump(skb, expr) ||
nla_put_string(skb, NFTA_HASH_SET_NAME, priv->map->name))
return -1;
return 0;
}
static struct nft_expr_type nft_hash_type; static struct nft_expr_type nft_hash_type;
static const struct nft_expr_ops nft_jhash_ops = { static const struct nft_expr_ops nft_jhash_ops = {
.type = &nft_hash_type, .type = &nft_hash_type,
...@@ -300,14 +199,6 @@ static const struct nft_expr_ops nft_jhash_ops = { ...@@ -300,14 +199,6 @@ static const struct nft_expr_ops nft_jhash_ops = {
.dump = nft_jhash_dump, .dump = nft_jhash_dump,
}; };
static const struct nft_expr_ops nft_jhash_map_ops = {
.type = &nft_hash_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_jhash)),
.eval = nft_jhash_map_eval,
.init = nft_jhash_map_init,
.dump = nft_jhash_map_dump,
};
static const struct nft_expr_ops nft_symhash_ops = { static const struct nft_expr_ops nft_symhash_ops = {
.type = &nft_hash_type, .type = &nft_hash_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_symhash)), .size = NFT_EXPR_SIZE(sizeof(struct nft_symhash)),
...@@ -316,14 +207,6 @@ static const struct nft_expr_ops nft_symhash_ops = { ...@@ -316,14 +207,6 @@ static const struct nft_expr_ops nft_symhash_ops = {
.dump = nft_symhash_dump, .dump = nft_symhash_dump,
}; };
static const struct nft_expr_ops nft_symhash_map_ops = {
.type = &nft_hash_type,
.size = NFT_EXPR_SIZE(sizeof(struct nft_symhash)),
.eval = nft_symhash_map_eval,
.init = nft_symhash_map_init,
.dump = nft_symhash_map_dump,
};
static const struct nft_expr_ops * static const struct nft_expr_ops *
nft_hash_select_ops(const struct nft_ctx *ctx, nft_hash_select_ops(const struct nft_ctx *ctx,
const struct nlattr * const tb[]) const struct nlattr * const tb[])
...@@ -336,12 +219,8 @@ nft_hash_select_ops(const struct nft_ctx *ctx, ...@@ -336,12 +219,8 @@ nft_hash_select_ops(const struct nft_ctx *ctx,
type = ntohl(nla_get_be32(tb[NFTA_HASH_TYPE])); type = ntohl(nla_get_be32(tb[NFTA_HASH_TYPE]));
switch (type) { switch (type) {
case NFT_HASH_SYM: case NFT_HASH_SYM:
if (tb[NFTA_HASH_SET_NAME])
return &nft_symhash_map_ops;
return &nft_symhash_ops; return &nft_symhash_ops;
case NFT_HASH_JENKINS: case NFT_HASH_JENKINS:
if (tb[NFTA_HASH_SET_NAME])
return &nft_jhash_map_ops;
return &nft_jhash_ops; return &nft_jhash_ops;
default: default:
break; break;
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <net/netfilter/nf_tables_core.h> #include <net/netfilter/nf_tables_core.h>
#include <net/netfilter/nf_tables.h> #include <net/netfilter/nf_tables.h>
static void nft_immediate_eval(const struct nft_expr *expr, void nft_immediate_eval(const struct nft_expr *expr,
struct nft_regs *regs, struct nft_regs *regs,
const struct nft_pktinfo *pkt) const struct nft_pktinfo *pkt)
{ {
......
...@@ -244,6 +244,16 @@ void nft_meta_get_eval(const struct nft_expr *expr, ...@@ -244,6 +244,16 @@ void nft_meta_get_eval(const struct nft_expr *expr,
strncpy((char *)dest, p->br->dev->name, IFNAMSIZ); strncpy((char *)dest, p->br->dev->name, IFNAMSIZ);
return; return;
#endif #endif
case NFT_META_IIFKIND:
if (in == NULL || in->rtnl_link_ops == NULL)
goto err;
strncpy((char *)dest, in->rtnl_link_ops->kind, IFNAMSIZ);
break;
case NFT_META_OIFKIND:
if (out == NULL || out->rtnl_link_ops == NULL)
goto err;
strncpy((char *)dest, out->rtnl_link_ops->kind, IFNAMSIZ);
break;
default: default:
WARN_ON(1); WARN_ON(1);
goto err; goto err;
...@@ -340,6 +350,8 @@ static int nft_meta_get_init(const struct nft_ctx *ctx, ...@@ -340,6 +350,8 @@ static int nft_meta_get_init(const struct nft_ctx *ctx,
break; break;
case NFT_META_IIFNAME: case NFT_META_IIFNAME:
case NFT_META_OIFNAME: case NFT_META_OIFNAME:
case NFT_META_IIFKIND:
case NFT_META_OIFKIND:
len = IFNAMSIZ; len = IFNAMSIZ;
break; break;
case NFT_META_PRANDOM: case NFT_META_PRANDOM:
......
...@@ -38,7 +38,8 @@ static int nft_objref_init(const struct nft_ctx *ctx, ...@@ -38,7 +38,8 @@ static int nft_objref_init(const struct nft_ctx *ctx,
return -EINVAL; return -EINVAL;
objtype = ntohl(nla_get_be32(tb[NFTA_OBJREF_IMM_TYPE])); objtype = ntohl(nla_get_be32(tb[NFTA_OBJREF_IMM_TYPE]));
obj = nft_obj_lookup(ctx->table, tb[NFTA_OBJREF_IMM_NAME], objtype, obj = nft_obj_lookup(ctx->net, ctx->table,
tb[NFTA_OBJREF_IMM_NAME], objtype,
genmask); genmask);
if (IS_ERR(obj)) if (IS_ERR(obj))
return -ENOENT; return -ENOENT;
...@@ -53,7 +54,7 @@ static int nft_objref_dump(struct sk_buff *skb, const struct nft_expr *expr) ...@@ -53,7 +54,7 @@ static int nft_objref_dump(struct sk_buff *skb, const struct nft_expr *expr)
{ {
const struct nft_object *obj = nft_objref_priv(expr); const struct nft_object *obj = nft_objref_priv(expr);
if (nla_put_string(skb, NFTA_OBJREF_IMM_NAME, obj->name) || if (nla_put_string(skb, NFTA_OBJREF_IMM_NAME, obj->key.name) ||
nla_put_be32(skb, NFTA_OBJREF_IMM_TYPE, nla_put_be32(skb, NFTA_OBJREF_IMM_TYPE,
htonl(obj->ops->type->type))) htonl(obj->ops->type->type)))
goto nla_put_failure; goto nla_put_failure;
......
...@@ -70,7 +70,7 @@ nft_payload_copy_vlan(u32 *d, const struct sk_buff *skb, u8 offset, u8 len) ...@@ -70,7 +70,7 @@ nft_payload_copy_vlan(u32 *d, const struct sk_buff *skb, u8 offset, u8 len)
return skb_copy_bits(skb, offset + mac_off, dst_u8, len) == 0; return skb_copy_bits(skb, offset + mac_off, dst_u8, len) == 0;
} }
static void nft_payload_eval(const struct nft_expr *expr, void nft_payload_eval(const struct nft_expr *expr,
struct nft_regs *regs, struct nft_regs *regs,
const struct nft_pktinfo *pkt) const struct nft_pktinfo *pkt)
{ {
......
...@@ -61,7 +61,7 @@ static void nft_quota_obj_eval(struct nft_object *obj, ...@@ -61,7 +61,7 @@ static void nft_quota_obj_eval(struct nft_object *obj,
if (overquota && if (overquota &&
!test_and_set_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags)) !test_and_set_bit(NFT_QUOTA_DEPLETED_BIT, &priv->flags))
nft_obj_notify(nft_net(pkt), obj->table, obj, 0, 0, nft_obj_notify(nft_net(pkt), obj->key.table, obj, 0, 0,
NFT_MSG_NEWOBJ, nft_pf(pkt), 0, GFP_ATOMIC); NFT_MSG_NEWOBJ, nft_pf(pkt), 0, GFP_ATOMIC);
} }
......
...@@ -23,9 +23,8 @@ struct nft_range_expr { ...@@ -23,9 +23,8 @@ struct nft_range_expr {
enum nft_range_ops op:8; enum nft_range_ops op:8;
}; };
static void nft_range_eval(const struct nft_expr *expr, void nft_range_eval(const struct nft_expr *expr,
struct nft_regs *regs, struct nft_regs *regs, const struct nft_pktinfo *pkt)
const struct nft_pktinfo *pkt)
{ {
const struct nft_range_expr *priv = nft_expr_priv(expr); const struct nft_range_expr *priv = nft_expr_priv(expr);
int d1, d2; int d1, d2;
......
...@@ -53,7 +53,7 @@ static u16 get_tcpmss(const struct nft_pktinfo *pkt, const struct dst_entry *skb ...@@ -53,7 +53,7 @@ static u16 get_tcpmss(const struct nft_pktinfo *pkt, const struct dst_entry *skb
return mtu - minlen; return mtu - minlen;
} }
static void nft_rt_get_eval(const struct nft_expr *expr, void nft_rt_get_eval(const struct nft_expr *expr,
struct nft_regs *regs, struct nft_regs *regs,
const struct nft_pktinfo *pkt) const struct nft_pktinfo *pkt)
{ {
......
...@@ -180,6 +180,25 @@ int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl, ...@@ -180,6 +180,25 @@ int nf_route(struct net *net, struct dst_entry **dst, struct flowi *fl,
} }
EXPORT_SYMBOL_GPL(nf_route); EXPORT_SYMBOL_GPL(nf_route);
static int nf_ip_reroute(struct sk_buff *skb, const struct nf_queue_entry *entry)
{
#ifdef CONFIG_INET
const struct ip_rt_info *rt_info = nf_queue_entry_reroute(entry);
if (entry->state.hook == NF_INET_LOCAL_OUT) {
const struct iphdr *iph = ip_hdr(skb);
if (!(iph->tos == rt_info->tos &&
skb->mark == rt_info->mark &&
iph->daddr == rt_info->daddr &&
iph->saddr == rt_info->saddr))
return ip_route_me_harder(entry->state.net, skb,
RTN_UNSPEC);
}
#endif
return 0;
}
int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry) int nf_reroute(struct sk_buff *skb, struct nf_queue_entry *entry)
{ {
const struct nf_ipv6_ops *v6ops; const struct nf_ipv6_ops *v6ops;
......
...@@ -159,7 +159,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, ...@@ -159,7 +159,7 @@ xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par,
/* Make sure the timeout policy matches any existing protocol tracker, /* Make sure the timeout policy matches any existing protocol tracker,
* otherwise default to generic. * otherwise default to generic.
*/ */
l4proto = __nf_ct_l4proto_find(proto); l4proto = nf_ct_l4proto_find(proto);
if (timeout->l4proto->l4proto != l4proto->l4proto) { if (timeout->l4proto->l4proto != l4proto->l4proto) {
ret = -EINVAL; ret = -EINVAL;
pr_info_ratelimited("Timeout policy `%s' can only be used by L%d protocol number %d\n", pr_info_ratelimited("Timeout policy `%s' can only be used by L%d protocol number %d\n",
......
...@@ -96,8 +96,7 @@ physdev_mt(const struct sk_buff *skb, struct xt_action_param *par) ...@@ -96,8 +96,7 @@ physdev_mt(const struct sk_buff *skb, struct xt_action_param *par)
static int physdev_mt_check(const struct xt_mtchk_param *par) static int physdev_mt_check(const struct xt_mtchk_param *par)
{ {
const struct xt_physdev_info *info = par->matchinfo; const struct xt_physdev_info *info = par->matchinfo;
static bool brnf_probed __read_mostly;
br_netfilter_enable();
if (!(info->bitmask & XT_PHYSDEV_OP_MASK) || if (!(info->bitmask & XT_PHYSDEV_OP_MASK) ||
info->bitmask & ~XT_PHYSDEV_OP_MASK) info->bitmask & ~XT_PHYSDEV_OP_MASK)
...@@ -111,6 +110,12 @@ static int physdev_mt_check(const struct xt_mtchk_param *par) ...@@ -111,6 +110,12 @@ static int physdev_mt_check(const struct xt_mtchk_param *par)
if (par->hook_mask & (1 << NF_INET_LOCAL_OUT)) if (par->hook_mask & (1 << NF_INET_LOCAL_OUT))
return -EINVAL; return -EINVAL;
} }
if (!brnf_probed) {
brnf_probed = true;
request_module("br_netfilter");
}
return 0; return 0;
} }
......
...@@ -622,7 +622,7 @@ ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone, ...@@ -622,7 +622,7 @@ ovs_ct_find_existing(struct net *net, const struct nf_conntrack_zone *zone,
if (natted) { if (natted) {
struct nf_conntrack_tuple inverse; struct nf_conntrack_tuple inverse;
if (!nf_ct_invert_tuplepr(&inverse, &tuple)) { if (!nf_ct_invert_tuple(&inverse, &tuple)) {
pr_debug("ovs_ct_find_existing: Inversion failed!\n"); pr_debug("ovs_ct_find_existing: Inversion failed!\n");
return NULL; return NULL;
} }
......
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