Initial commit: Linux kernel 4.19 for Unplugged OS

This commit is contained in:
ziv committed 2025-10-06 13:52:42 +00:00
commit d30235b04c
80519 files changed
+35800681

No files matched your search

+72
View File
@@ -0,0 +1,72 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _BR_NETFILTER_H_
#define _BR_NETFILTER_H_
#include "../../../net/bridge/br_private.h"
static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
{
skb->nf_bridge = kzalloc(sizeof(struct nf_bridge_info), GFP_ATOMIC);
if (likely(skb->nf_bridge))
refcount_set(&(skb->nf_bridge->use), 1);
return skb->nf_bridge;
}
void nf_bridge_update_protocol(struct sk_buff *skb);
int br_nf_hook_thresh(unsigned int hook, struct net *net, struct sock *sk,
struct sk_buff *skb, struct net_device *indev,
struct net_device *outdev,
int (*okfn)(struct net *, struct sock *,
struct sk_buff *));
static inline struct nf_bridge_info *
nf_bridge_info_get(const struct sk_buff *skb)
{
return skb->nf_bridge;
}
unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb);
static inline void nf_bridge_push_encap_header(struct sk_buff *skb)
{
unsigned int len = nf_bridge_encap_header_len(skb);
skb_push(skb, len);
skb->network_header -= len;
}
int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_buff *skb);
static inline struct rtable *bridge_parent_rtable(const struct net_device *dev)
{
struct net_bridge_port *port;
port = br_port_get_rcu(dev);
return port ? &port->br->fake_rtable : NULL;
}
struct net_device *setup_pre_routing(struct sk_buff *skb);
#if IS_ENABLED(CONFIG_IPV6)
int br_validate_ipv6(struct net *net, struct sk_buff *skb);
unsigned int br_nf_pre_routing_ipv6(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state);
#else
static inline int br_validate_ipv6(struct net *net, struct sk_buff *skb)
{
return -1;
}
static inline unsigned int
br_nf_pre_routing_ipv6(const struct nf_hook_ops *ops, struct sk_buff *skb,
const struct nf_hook_state *state)
{
return NF_ACCEPT;
}
#endif
#endif /* _BR_NETFILTER_H_ */
@@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* IPv4 support for nf_conntrack.
*
* 23 Mar 2004: Yasuyuki Kozakai @ USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - move L3 protocol dependent part from include/linux/netfilter_ipv4/
* ip_conntarck.h
*/
#ifndef _NF_CONNTRACK_IPV4_H
#define _NF_CONNTRACK_IPV4_H
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
#ifdef CONFIG_NF_CT_PROTO_DCCP
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4;
#endif
#ifdef CONFIG_NF_CT_PROTO_SCTP
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp4;
#endif
#ifdef CONFIG_NF_CT_PROTO_UDPLITE
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4;
#endif
int nf_conntrack_ipv4_compat_init(void);
void nf_conntrack_ipv4_compat_fini(void);
#endif /*_NF_CONNTRACK_IPV4_H*/
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_DEFRAG_IPV4_H
#define _NF_DEFRAG_IPV4_H
struct net;
int nf_defrag_ipv4_enable(struct net *);
#endif /* _NF_DEFRAG_IPV4_H */
+8
View File
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_DUP_IPV4_H_
#define _NF_DUP_IPV4_H_
void nf_dup_ipv4(struct net *net, struct sk_buff *skb, unsigned int hooknum,
const struct in_addr *gw, int oif);
#endif /* _NF_DUP_IPV4_H_ */
@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_NAT_MASQUERADE_IPV4_H_
#define _NF_NAT_MASQUERADE_IPV4_H_
#include <net/netfilter/nf_nat.h>
unsigned int
nf_nat_masquerade_ipv4(struct sk_buff *skb, unsigned int hooknum,
const struct nf_nat_range2 *range,
const struct net_device *out);
int nf_nat_masquerade_ipv4_register_notifier(void);
void nf_nat_masquerade_ipv4_unregister_notifier(void);
#endif /*_NF_NAT_MASQUERADE_IPV4_H_ */
+20
View File
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _IPV4_NF_REJECT_H
#define _IPV4_NF_REJECT_H
#include <linux/skbuff.h>
#include <net/ip.h>
#include <net/icmp.h>
void nf_send_unreach(struct sk_buff *skb_in, int code, int hook);
void nf_send_reset(struct net *net, struct sk_buff *oldskb, int hook);
const struct tcphdr *nf_reject_ip_tcphdr_get(struct sk_buff *oldskb,
struct tcphdr *_oth, int hook);
struct iphdr *nf_reject_iphdr_put(struct sk_buff *nskb,
const struct sk_buff *oldskb,
__u8 protocol, int ttl);
void nf_reject_ip_tcphdr_put(struct sk_buff *nskb, const struct sk_buff *oldskb,
const struct tcphdr *oth);
#endif /* _IPV4_NF_REJECT_H */
@@ -0,0 +1,21 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* ICMPv6 tracking.
*
* 21 Apl 2004: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - separated from nf_conntrack_icmp.h
*
* Derived from include/linux/netfiter_ipv4/ip_conntrack_icmp.h
*/
#ifndef _NF_CONNTRACK_ICMPV6_H
#define _NF_CONNTRACK_ICMPV6_H
#ifndef ICMPV6_NI_QUERY
#define ICMPV6_NI_QUERY 139
#endif
#ifndef ICMPV6_NI_REPLY
#define ICMPV6_NI_REPLY 140
#endif
#endif /* _NF_CONNTRACK_ICMPV6_H */
@@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_CONNTRACK_IPV6_H
#define _NF_CONNTRACK_IPV6_H
extern const struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp6;
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udp6;
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmpv6;
#ifdef CONFIG_NF_CT_PROTO_DCCP
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp6;
#endif
#ifdef CONFIG_NF_CT_PROTO_SCTP
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_sctp6;
#endif
#ifdef CONFIG_NF_CT_PROTO_UDPLITE
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite6;
#endif
#include <linux/sysctl.h>
extern struct ctl_table nf_ct_ipv6_sysctl_table[];
#endif /* _NF_CONNTRACK_IPV6_H*/
@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_DEFRAG_IPV6_H
#define _NF_DEFRAG_IPV6_H
struct net;
int nf_defrag_ipv6_enable(struct net *);
int nf_ct_frag6_init(void);
void nf_ct_frag6_cleanup(void);
int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user);
struct inet_frags_ctl;
#endif /* _NF_DEFRAG_IPV6_H */
+8
View File
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_DUP_IPV6_H_
#define _NF_DUP_IPV6_H_
void nf_dup_ipv6(struct net *net, struct sk_buff *skb, unsigned int hooknum,
const struct in6_addr *gw, int oif);
#endif /* _NF_DUP_IPV6_H_ */
@@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_NAT_MASQUERADE_IPV6_H_
#define _NF_NAT_MASQUERADE_IPV6_H_
unsigned int
nf_nat_masquerade_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
const struct net_device *out);
int nf_nat_masquerade_ipv6_register_notifier(void);
void nf_nat_masquerade_ipv6_unregister_notifier(void);
#endif /* _NF_NAT_MASQUERADE_IPV6_H_ */
+22
View File
@@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _IPV6_NF_REJECT_H
#define _IPV6_NF_REJECT_H
#include <linux/icmpv6.h>
void nf_send_unreach6(struct net *net, struct sk_buff *skb_in, unsigned char code,
unsigned int hooknum);
void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook);
const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb,
struct tcphdr *otcph,
unsigned int *otcplen, int hook);
struct ipv6hdr *nf_reject_ip6hdr_put(struct sk_buff *nskb,
const struct sk_buff *oldskb,
__u8 protocol, int hoplimit);
void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb,
const struct sk_buff *oldskb,
const struct tcphdr *oth, unsigned int otcplen);
#endif /* _IPV6_NF_REJECT_H */
+331
View File
@@ -0,0 +1,331 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Connection state tracking for netfilter. This is separated from,
* but required by, the (future) NAT layer; it can also be used by an iptables
* extension.
*
* 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - generalize L3 protocol dependent part.
*
* Derived from include/linux/netfiter_ipv4/ip_conntrack.h
*/
#ifndef _NF_CONNTRACK_H
#define _NF_CONNTRACK_H
#include <linux/netfilter/nf_conntrack_common.h>
#include <linux/bitops.h>
#include <linux/compiler.h>
#include <linux/atomic.h>
#include <linux/netfilter/nf_conntrack_tcp.h>
#include <linux/netfilter/nf_conntrack_dccp.h>
#include <linux/netfilter/nf_conntrack_sctp.h>
#include <linux/netfilter/nf_conntrack_proto_gre.h>
#include <net/netfilter/ipv6/nf_conntrack_icmpv6.h>
#include <net/netfilter/nf_conntrack_tuple.h>
/* per conntrack: protocol private data */
union nf_conntrack_proto {
/* insert conntrack proto private data here */
struct nf_ct_dccp dccp;
struct ip_ct_sctp sctp;
struct ip_ct_tcp tcp;
struct nf_ct_gre gre;
unsigned int tmpl_padto;
};
union nf_conntrack_expect_proto {
/* insert expect proto private data here */
};
struct nf_conntrack_net {
unsigned int users4;
unsigned int users6;
};
#include <linux/types.h>
#include <linux/skbuff.h>
#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
struct nf_conn {
/* Usage count in here is 1 for hash table, 1 per skb,
* plus 1 for any connection(s) we are `master' for
*
* Hint, SKB address this struct and refcnt via skb->_nfct and
* helpers nf_conntrack_get() and nf_conntrack_put().
* Helper nf_ct_put() equals nf_conntrack_put() by dec refcnt,
* beware nf_ct_get() is different and don't inc refcnt.
*/
struct nf_conntrack ct_general;
spinlock_t lock;
u16 cpu;
#ifdef CONFIG_NF_CONNTRACK_ZONES
struct nf_conntrack_zone zone;
#endif
/* XXX should I move this to the tail ? - Y.K */
/* These are my tuples; original and reply */
struct nf_conntrack_tuple_hash tuplehash[IP_CT_DIR_MAX];
/* Have we seen traffic both ways yet? (bitset) */
unsigned long status;
/* jiffies32 when this ct is considered dead */
u32 timeout;
possible_net_t ct_net;
#if IS_ENABLED(CONFIG_NF_NAT)
struct hlist_node nat_bysource;
#endif
/* all members below initialized via memset */
struct { } __nfct_init_offset;
/* If we were expected by an expectation, this will be it */
struct nf_conn *master;
#if defined(CONFIG_NF_CONNTRACK_MARK)
u_int32_t mark;
#endif
#ifdef CONFIG_NF_CONNTRACK_SECMARK
u_int32_t secmark;
#endif
/* Extensions */
struct nf_ct_ext *ext;
/* Storage reserved for other modules, must be the last member */
union nf_conntrack_proto proto;
};
static inline struct nf_conn *
nf_ct_tuplehash_to_ctrack(const struct nf_conntrack_tuple_hash *hash)
{
return container_of(hash, struct nf_conn,
tuplehash[hash->tuple.dst.dir]);
}
static inline u_int16_t nf_ct_l3num(const struct nf_conn *ct)
{
return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num;
}
static inline u_int8_t nf_ct_protonum(const struct nf_conn *ct)
{
return ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum;
}
#define nf_ct_tuple(ct, dir) (&(ct)->tuplehash[dir].tuple)
/* get master conntrack via master expectation */
#define master_ct(conntr) (conntr->master)
extern struct net init_net;
static inline struct net *nf_ct_net(const struct nf_conn *ct)
{
return read_pnet(&ct->ct_net);
}
/* Alter reply tuple (maybe alter helper). */
void nf_conntrack_alter_reply(struct nf_conn *ct,
const struct nf_conntrack_tuple *newreply);
/* Is this tuple taken? (ignoring any belonging to the given
conntrack). */
int nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
const struct nf_conn *ignored_conntrack);
#define NFCT_INFOMASK 7UL
#define NFCT_PTRMASK ~(NFCT_INFOMASK)
/* Return conntrack_info and tuple hash for given skb. */
static inline struct nf_conn *
nf_ct_get(const struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
{
*ctinfo = skb->_nfct & NFCT_INFOMASK;
return (struct nf_conn *)(skb->_nfct & NFCT_PTRMASK);
}
/* decrement reference count on a conntrack */
static inline void nf_ct_put(struct nf_conn *ct)
{
WARN_ON(!ct);
nf_conntrack_put(&ct->ct_general);
}
/* Protocol module loading */
int nf_ct_l3proto_try_module_get(unsigned short l3proto);
void nf_ct_l3proto_module_put(unsigned short l3proto);
/* load module; enable/disable conntrack in this namespace */
int nf_ct_netns_get(struct net *net, u8 nfproto);
void nf_ct_netns_put(struct net *net, u8 nfproto);
/*
* Allocate a hashtable of hlist_head (if nulls == 0),
* or hlist_nulls_head (if nulls == 1)
*/
void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls);
int nf_conntrack_hash_check_insert(struct nf_conn *ct);
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,
u_int16_t l3num, struct net *net,
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,
const struct sk_buff *skb,
unsigned long extra_jiffies, int do_acct);
/* Refresh conntrack for this many jiffies and do accounting */
static inline void nf_ct_refresh_acct(struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
const struct sk_buff *skb,
unsigned long extra_jiffies)
{
__nf_ct_refresh_acct(ct, ctinfo, skb, extra_jiffies, 1);
}
/* Refresh conntrack for this many jiffies */
static inline void nf_ct_refresh(struct nf_conn *ct,
const struct sk_buff *skb,
unsigned long extra_jiffies)
{
__nf_ct_refresh_acct(ct, 0, skb, extra_jiffies, 0);
}
/* kill conntrack and do accounting */
bool nf_ct_kill_acct(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
const struct sk_buff *skb);
/* kill conntrack without accounting */
static inline bool nf_ct_kill(struct nf_conn *ct)
{
return nf_ct_delete(ct, 0, 0);
}
/* Set all unconfirmed conntrack as dying */
void nf_ct_unconfirmed_destroy(struct net *);
/* Iterate over all conntracks: if iter returns true, it's deleted. */
void nf_ct_iterate_cleanup_net(struct net *net,
int (*iter)(struct nf_conn *i, void *data),
void *data, u32 portid, int report);
/* also set unconfirmed conntracks as dying. Only use in module exit path. */
void nf_ct_iterate_destroy(int (*iter)(struct nf_conn *i, void *data),
void *data);
struct nf_conntrack_zone;
void nf_conntrack_free(struct nf_conn *ct);
struct nf_conn *nf_conntrack_alloc(struct net *net,
const struct nf_conntrack_zone *zone,
const struct nf_conntrack_tuple *orig,
const struct nf_conntrack_tuple *repl,
gfp_t gfp);
static inline int nf_ct_is_template(const struct nf_conn *ct)
{
return test_bit(IPS_TEMPLATE_BIT, &ct->status);
}
/* It's confirmed if it is, or has been in the hash table. */
static inline int nf_ct_is_confirmed(const struct nf_conn *ct)
{
return test_bit(IPS_CONFIRMED_BIT, &ct->status);
}
static inline int nf_ct_is_dying(const struct nf_conn *ct)
{
return test_bit(IPS_DYING_BIT, &ct->status);
}
/* Packet is received from loopback */
static inline bool nf_is_loopback_packet(const struct sk_buff *skb)
{
return skb->dev && skb->skb_iif && skb->dev->flags & IFF_LOOPBACK;
}
#define nfct_time_stamp ((u32)(jiffies))
/* jiffies until ct expires, 0 if already expired */
static inline unsigned long nf_ct_expires(const struct nf_conn *ct)
{
s32 timeout = ct->timeout - nfct_time_stamp;
return timeout > 0 ? timeout : 0;
}
static inline bool nf_ct_is_expired(const struct nf_conn *ct)
{
return (__s32)(ct->timeout - nfct_time_stamp) <= 0;
}
/* use after obtaining a reference count */
static inline bool nf_ct_should_gc(const struct nf_conn *ct)
{
return nf_ct_is_expired(ct) && nf_ct_is_confirmed(ct) &&
!nf_ct_is_dying(ct);
}
struct kernel_param;
int nf_conntrack_set_hashsize(const char *val, const struct kernel_param *kp);
int nf_conntrack_hash_resize(unsigned int hashsize);
extern struct hlist_nulls_head *nf_conntrack_hash;
extern unsigned int nf_conntrack_htable_size;
extern seqcount_t nf_conntrack_generation;
extern unsigned int nf_conntrack_max;
/* must be called with rcu read lock held */
static inline void
nf_conntrack_get_ht(struct hlist_nulls_head **hash, unsigned int *hsize)
{
struct hlist_nulls_head *hptr;
unsigned int sequence, hsz;
do {
sequence = read_seqcount_begin(&nf_conntrack_generation);
hsz = nf_conntrack_htable_size;
hptr = nf_conntrack_hash;
} while (read_seqcount_retry(&nf_conntrack_generation, sequence));
*hash = hptr;
*hsize = hsz;
}
struct nf_conn *nf_ct_tmpl_alloc(struct net *net,
const struct nf_conntrack_zone *zone,
gfp_t flags);
void nf_ct_tmpl_free(struct nf_conn *tmpl);
u32 nf_ct_get_id(const struct nf_conn *ct);
static inline void
nf_ct_set(struct sk_buff *skb, struct nf_conn *ct, enum ip_conntrack_info info)
{
skb->_nfct = (unsigned long)ct | info;
}
#define NF_CT_STAT_INC(net, count) __this_cpu_inc((net)->ct.stat->count)
#define NF_CT_STAT_INC_ATOMIC(net, count) this_cpu_inc((net)->ct.stat->count)
#define NF_CT_STAT_ADD_ATOMIC(net, count, v) this_cpu_add((net)->ct.stat->count, (v))
#define MODULE_ALIAS_NFCT_HELPER(helper) \
MODULE_ALIAS("nfct-helper-" helper)
#endif /* _NF_CONNTRACK_H */
+69
View File
@@ -0,0 +1,69 @@
/*
* (C) 2008 Krzysztof Piotr Oledzki <ole@ans.pl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _NF_CONNTRACK_ACCT_H
#define _NF_CONNTRACK_ACCT_H
#include <net/net_namespace.h>
#include <linux/netfilter/nf_conntrack_common.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_extend.h>
struct nf_conn_counter {
atomic64_t packets;
atomic64_t bytes;
};
struct nf_conn_acct {
struct nf_conn_counter counter[IP_CT_DIR_MAX];
};
static inline
struct nf_conn_acct *nf_conn_acct_find(const struct nf_conn *ct)
{
return nf_ct_ext_find(ct, NF_CT_EXT_ACCT);
}
static inline
struct nf_conn_acct *nf_ct_acct_ext_add(struct nf_conn *ct, gfp_t gfp)
{
struct net *net = nf_ct_net(ct);
struct nf_conn_acct *acct;
if (!net->ct.sysctl_acct)
return NULL;
acct = nf_ct_ext_add(ct, NF_CT_EXT_ACCT, gfp);
if (!acct)
pr_debug("failed to add accounting extension area");
return acct;
};
unsigned int seq_print_acct(struct seq_file *s, const struct nf_conn *ct,
int dir);
/* Check if connection tracking accounting is enabled */
static inline bool nf_ct_acct_enabled(struct net *net)
{
return net->ct.sysctl_acct != 0;
}
/* Enable/disable connection tracking accounting */
static inline void nf_ct_set_acct(struct net *net, bool enable)
{
net->ct.sysctl_acct = enable;
}
int nf_conntrack_acct_pernet_init(struct net *net);
void nf_conntrack_acct_pernet_fini(struct net *net);
int nf_conntrack_acct_init(void);
void nf_conntrack_acct_fini(void);
#endif /* _NF_CONNTRACK_ACCT_H */
+79
View File
@@ -0,0 +1,79 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This header is used to share core functionality between the
* standalone connection tracking module, and the compatibility layer's use
* of connection tracking.
*
* 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - generalize L3 protocol dependent part.
*
* Derived from include/linux/netfiter_ipv4/ip_conntrack_core.h
*/
#ifndef _NF_CONNTRACK_CORE_H
#define _NF_CONNTRACK_CORE_H
#include <linux/netfilter.h>
#include <net/netfilter/nf_conntrack_l4proto.h>
#include <net/netfilter/nf_conntrack_ecache.h>
/* This header is used to share core functionality between the
standalone connection tracking module, and the compatibility layer's use
of connection tracking. */
unsigned int nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
struct sk_buff *skb);
int nf_conntrack_init_net(struct net *net);
void nf_conntrack_cleanup_net(struct net *net);
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_fini(struct net *net);
int nf_conntrack_proto_init(void);
void nf_conntrack_proto_fini(void);
int nf_conntrack_init_start(void);
void nf_conntrack_cleanup_start(void);
void nf_conntrack_init_end(void);
void nf_conntrack_cleanup_end(void);
bool nf_ct_invert_tuple(struct nf_conntrack_tuple *inverse,
const struct nf_conntrack_tuple *orig,
const struct nf_conntrack_l4proto *l4proto);
/* Find a connection corresponding to a tuple. */
struct nf_conntrack_tuple_hash *
nf_conntrack_find_get(struct net *net,
const struct nf_conntrack_zone *zone,
const struct nf_conntrack_tuple *tuple);
int __nf_conntrack_confirm(struct sk_buff *skb);
/* Confirm a connection: returns NF_DROP if packet must be dropped. */
static inline int nf_conntrack_confirm(struct sk_buff *skb)
{
struct nf_conn *ct = (struct nf_conn *)skb_nfct(skb);
int ret = NF_ACCEPT;
if (ct) {
if (!nf_ct_is_confirmed(ct))
ret = __nf_conntrack_confirm(skb);
if (likely(ret == NF_ACCEPT))
nf_ct_deliver_cached_events(ct);
}
return ret;
}
void print_tuple(struct seq_file *s, const struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_l4proto *proto);
#define CONNTRACK_LOCKS 1024
extern spinlock_t nf_conntrack_locks[CONNTRACK_LOCKS];
void nf_conntrack_lock(spinlock_t *lock);
extern spinlock_t nf_conntrack_expect_lock;
#endif /* _NF_CONNTRACK_CORE_H */
@@ -0,0 +1,36 @@
#ifndef _NF_CONNTRACK_COUNT_H
#define _NF_CONNTRACK_COUNT_H
#include <linux/list.h>
struct nf_conncount_data;
struct nf_conncount_list {
spinlock_t list_lock;
struct list_head head; /* connections with the same filtering key */
unsigned int count; /* length of list */
};
struct nf_conncount_data *nf_conncount_init(struct net *net, unsigned int family,
unsigned int keylen);
void nf_conncount_destroy(struct net *net, unsigned int family,
struct nf_conncount_data *data);
unsigned int nf_conncount_count(struct net *net,
struct nf_conncount_data *data,
const u32 *key,
const struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_zone *zone);
int nf_conncount_add(struct net *net, struct nf_conncount_list *list,
const struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_zone *zone);
void nf_conncount_list_init(struct nf_conncount_list *list);
bool nf_conncount_gc_list(struct net *net,
struct nf_conncount_list *list);
void nf_conncount_cache_free(struct nf_conncount_list *list);
#endif
+213
View File
@@ -0,0 +1,213 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* connection tracking event cache.
*/
#ifndef _NF_CONNTRACK_ECACHE_H
#define _NF_CONNTRACK_ECACHE_H
#include <net/netfilter/nf_conntrack.h>
#include <net/net_namespace.h>
#include <net/netfilter/nf_conntrack_expect.h>
#include <linux/netfilter/nf_conntrack_common.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
#include <net/netfilter/nf_conntrack_extend.h>
enum nf_ct_ecache_state {
NFCT_ECACHE_UNKNOWN, /* destroy event not sent */
NFCT_ECACHE_DESTROY_FAIL, /* tried but failed to send destroy event */
NFCT_ECACHE_DESTROY_SENT, /* sent destroy event after failure */
};
struct nf_conntrack_ecache {
unsigned long cache; /* bitops want long */
u16 missed; /* missed events */
u16 ctmask; /* bitmask of ct events to be delivered */
u16 expmask; /* bitmask of expect events to be delivered */
enum nf_ct_ecache_state state:8;/* ecache state */
u32 portid; /* netlink portid of destroyer */
};
static inline struct nf_conntrack_ecache *
nf_ct_ecache_find(const struct nf_conn *ct)
{
#ifdef CONFIG_NF_CONNTRACK_EVENTS
return nf_ct_ext_find(ct, NF_CT_EXT_ECACHE);
#else
return NULL;
#endif
}
static inline struct nf_conntrack_ecache *
nf_ct_ecache_ext_add(struct nf_conn *ct, u16 ctmask, u16 expmask, gfp_t gfp)
{
#ifdef CONFIG_NF_CONNTRACK_EVENTS
struct net *net = nf_ct_net(ct);
struct nf_conntrack_ecache *e;
if (!ctmask && !expmask && net->ct.sysctl_events) {
ctmask = ~0;
expmask = ~0;
}
if (!ctmask && !expmask)
return NULL;
e = nf_ct_ext_add(ct, NF_CT_EXT_ECACHE, gfp);
if (e) {
e->ctmask = ctmask;
e->expmask = expmask;
}
return e;
#else
return NULL;
#endif
};
#ifdef CONFIG_NF_CONNTRACK_EVENTS
/* This structure is passed to event handler */
struct nf_ct_event {
struct nf_conn *ct;
u32 portid;
int report;
};
struct nf_ct_event_notifier {
int (*fcn)(unsigned int events, struct nf_ct_event *item);
};
int nf_conntrack_register_notifier(struct net *net,
struct nf_ct_event_notifier *nb);
void nf_conntrack_unregister_notifier(struct net *net,
struct nf_ct_event_notifier *nb);
void nf_ct_deliver_cached_events(struct nf_conn *ct);
int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
u32 portid, int report);
static inline void
nf_conntrack_event_cache(enum ip_conntrack_events event, struct nf_conn *ct)
{
struct net *net = nf_ct_net(ct);
struct nf_conntrack_ecache *e;
if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
return;
e = nf_ct_ecache_find(ct);
if (e == NULL)
return;
set_bit(event, &e->cache);
}
static inline int
nf_conntrack_event_report(enum ip_conntrack_events event, struct nf_conn *ct,
u32 portid, int report)
{
const struct net *net = nf_ct_net(ct);
if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
return 0;
return nf_conntrack_eventmask_report(1 << event, ct, portid, report);
}
static inline int
nf_conntrack_event(enum ip_conntrack_events event, struct nf_conn *ct)
{
const struct net *net = nf_ct_net(ct);
if (!rcu_access_pointer(net->ct.nf_conntrack_event_cb))
return 0;
return nf_conntrack_eventmask_report(1 << event, ct, 0, 0);
}
struct nf_exp_event {
struct nf_conntrack_expect *exp;
u32 portid;
int report;
};
struct nf_exp_event_notifier {
int (*fcn)(unsigned int events, struct nf_exp_event *item);
};
int nf_ct_expect_register_notifier(struct net *net,
struct nf_exp_event_notifier *nb);
void nf_ct_expect_unregister_notifier(struct net *net,
struct nf_exp_event_notifier *nb);
void nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
struct nf_conntrack_expect *exp,
u32 portid, int report);
int nf_conntrack_ecache_pernet_init(struct net *net);
void nf_conntrack_ecache_pernet_fini(struct net *net);
int nf_conntrack_ecache_init(void);
void nf_conntrack_ecache_fini(void);
static inline void nf_conntrack_ecache_delayed_work(struct net *net)
{
if (!delayed_work_pending(&net->ct.ecache_dwork)) {
schedule_delayed_work(&net->ct.ecache_dwork, HZ);
net->ct.ecache_dwork_pending = true;
}
}
static inline void nf_conntrack_ecache_work(struct net *net)
{
if (net->ct.ecache_dwork_pending) {
net->ct.ecache_dwork_pending = false;
mod_delayed_work(system_wq, &net->ct.ecache_dwork, 0);
}
}
#else /* CONFIG_NF_CONNTRACK_EVENTS */
static inline void nf_conntrack_event_cache(enum ip_conntrack_events event,
struct nf_conn *ct) {}
static inline int nf_conntrack_eventmask_report(unsigned int eventmask,
struct nf_conn *ct,
u32 portid,
int report) { return 0; }
static inline int nf_conntrack_event(enum ip_conntrack_events event,
struct nf_conn *ct) { return 0; }
static inline int nf_conntrack_event_report(enum ip_conntrack_events event,
struct nf_conn *ct,
u32 portid,
int report) { return 0; }
static inline void nf_ct_deliver_cached_events(const struct nf_conn *ct) {}
static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
struct nf_conntrack_expect *exp,
u32 portid,
int report) {}
static inline int nf_conntrack_ecache_pernet_init(struct net *net)
{
return 0;
}
static inline void nf_conntrack_ecache_pernet_fini(struct net *net)
{
}
static inline int nf_conntrack_ecache_init(void)
{
return 0;
}
static inline void nf_conntrack_ecache_fini(void)
{
}
static inline void nf_conntrack_ecache_delayed_work(struct net *net)
{
}
static inline void nf_conntrack_ecache_work(struct net *net)
{
}
#endif /* CONFIG_NF_CONNTRACK_EVENTS */
#endif /*_NF_CONNTRACK_ECACHE_H*/
+132
View File
@@ -0,0 +1,132 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* connection tracking expectations.
*/
#ifndef _NF_CONNTRACK_EXPECT_H
#define _NF_CONNTRACK_EXPECT_H
#include <linux/refcount.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_zones.h>
extern unsigned int nf_ct_expect_hsize;
extern unsigned int nf_ct_expect_max;
extern struct hlist_head *nf_ct_expect_hash;
struct nf_conntrack_expect {
/* Conntrack expectation list member */
struct hlist_node lnode;
/* Hash member */
struct hlist_node hnode;
/* We expect this tuple, with the following mask */
struct nf_conntrack_tuple tuple;
struct nf_conntrack_tuple_mask mask;
/* Function to call after setup and insertion */
void (*expectfn)(struct nf_conn *new,
struct nf_conntrack_expect *this);
/* Helper to assign to new connection */
struct nf_conntrack_helper *helper;
/* The conntrack of the master connection */
struct nf_conn *master;
/* Timer function; deletes the expectation. */
struct timer_list timeout;
/* Usage count. */
refcount_t use;
/* Flags */
unsigned int flags;
/* Expectation class */
unsigned int class;
#ifdef CONFIG_NF_NAT_NEEDED
union nf_inet_addr saved_addr;
/* This is the original per-proto part, used to map the
* expected connection the way the recipient expects. */
union nf_conntrack_man_proto saved_proto;
/* Direction relative to the master connection. */
enum ip_conntrack_dir dir;
#endif
struct rcu_head rcu;
};
static inline struct net *nf_ct_exp_net(struct nf_conntrack_expect *exp)
{
return nf_ct_net(exp->master);
}
#define NF_CT_EXP_POLICY_NAME_LEN 16
struct nf_conntrack_expect_policy {
unsigned int max_expected;
unsigned int timeout;
char name[NF_CT_EXP_POLICY_NAME_LEN];
};
#define NF_CT_EXPECT_CLASS_DEFAULT 0
#define NF_CT_EXPECT_MAX_CNT 255
int nf_conntrack_expect_pernet_init(struct net *net);
void nf_conntrack_expect_pernet_fini(struct net *net);
int nf_conntrack_expect_init(void);
void nf_conntrack_expect_fini(void);
struct nf_conntrack_expect *
__nf_ct_expect_find(struct net *net,
const struct nf_conntrack_zone *zone,
const struct nf_conntrack_tuple *tuple);
struct nf_conntrack_expect *
nf_ct_expect_find_get(struct net *net,
const struct nf_conntrack_zone *zone,
const struct nf_conntrack_tuple *tuple);
struct nf_conntrack_expect *
nf_ct_find_expectation(struct net *net,
const struct nf_conntrack_zone *zone,
const struct nf_conntrack_tuple *tuple);
void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp,
u32 portid, int report);
static inline void nf_ct_unlink_expect(struct nf_conntrack_expect *exp)
{
nf_ct_unlink_expect_report(exp, 0, 0);
}
void nf_ct_remove_expectations(struct nf_conn *ct);
void nf_ct_unexpect_related(struct nf_conntrack_expect *exp);
bool nf_ct_remove_expect(struct nf_conntrack_expect *exp);
void nf_ct_expect_iterate_destroy(bool (*iter)(struct nf_conntrack_expect *e, void *data), void *data);
void nf_ct_expect_iterate_net(struct net *net,
bool (*iter)(struct nf_conntrack_expect *e, void *data),
void *data, u32 portid, int report);
/* Allocate space for an expectation: this is mandatory before calling
nf_ct_expect_related. You will have to call put afterwards. */
struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me);
void nf_ct_expect_init(struct nf_conntrack_expect *, unsigned int, u_int8_t,
const union nf_inet_addr *,
const union nf_inet_addr *,
u_int8_t, const __be16 *, const __be16 *);
void nf_ct_expect_put(struct nf_conntrack_expect *exp);
int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
u32 portid, int report);
static inline int nf_ct_expect_related(struct nf_conntrack_expect *expect)
{
return nf_ct_expect_related_report(expect, 0, 0);
}
#endif /*_NF_CONNTRACK_EXPECT_H*/
+100
View File
@@ -0,0 +1,100 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_CONNTRACK_EXTEND_H
#define _NF_CONNTRACK_EXTEND_H
#include <linux/slab.h>
#include <net/netfilter/nf_conntrack.h>
enum nf_ct_ext_id {
NF_CT_EXT_HELPER,
#if defined(CONFIG_NF_NAT) || defined(CONFIG_NF_NAT_MODULE)
NF_CT_EXT_NAT,
#endif
NF_CT_EXT_SEQADJ,
NF_CT_EXT_ACCT,
#ifdef CONFIG_NF_CONNTRACK_EVENTS
NF_CT_EXT_ECACHE,
#endif
#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
NF_CT_EXT_TSTAMP,
#endif
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
NF_CT_EXT_TIMEOUT,
#endif
#ifdef CONFIG_NF_CONNTRACK_LABELS
NF_CT_EXT_LABELS,
#endif
#if IS_ENABLED(CONFIG_NETFILTER_SYNPROXY)
NF_CT_EXT_SYNPROXY,
#endif
NF_CT_EXT_NUM,
};
#define NF_CT_EXT_HELPER_TYPE struct nf_conn_help
#define NF_CT_EXT_NAT_TYPE struct nf_conn_nat
#define NF_CT_EXT_SEQADJ_TYPE struct nf_conn_seqadj
#define NF_CT_EXT_ACCT_TYPE struct nf_conn_acct
#define NF_CT_EXT_ECACHE_TYPE struct nf_conntrack_ecache
#define NF_CT_EXT_TSTAMP_TYPE struct nf_conn_tstamp
#define NF_CT_EXT_TIMEOUT_TYPE struct nf_conn_timeout
#define NF_CT_EXT_LABELS_TYPE struct nf_conn_labels
#define NF_CT_EXT_SYNPROXY_TYPE struct nf_conn_synproxy
/* Extensions: optional stuff which isn't permanently in struct. */
struct nf_ct_ext {
struct rcu_head rcu;
u8 offset[NF_CT_EXT_NUM];
u8 len;
char data[0];
};
static inline bool __nf_ct_ext_exist(const struct nf_ct_ext *ext, u8 id)
{
return !!ext->offset[id];
}
static inline bool nf_ct_ext_exist(const struct nf_conn *ct, u8 id)
{
return (ct->ext && __nf_ct_ext_exist(ct->ext, id));
}
static inline void *__nf_ct_ext_find(const struct nf_conn *ct, u8 id)
{
if (!nf_ct_ext_exist(ct, id))
return NULL;
return (void *)ct->ext + ct->ext->offset[id];
}
#define nf_ct_ext_find(ext, id) \
((id##_TYPE *)__nf_ct_ext_find((ext), (id)))
/* Destroy all relationships */
void nf_ct_ext_destroy(struct nf_conn *ct);
/* Free operation. If you want to free a object referred from private area,
* please implement __nf_ct_ext_free() and call it.
*/
static inline void nf_ct_ext_free(struct nf_conn *ct)
{
if (ct->ext)
kfree_rcu(ct->ext, rcu);
}
/* Add this type, returns pointer to data or NULL. */
void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp);
struct nf_ct_ext_type {
/* Destroys relationships (can be NULL). */
void (*destroy)(struct nf_conn *ct);
enum nf_ct_ext_id id;
/* Length and min alignment. */
u8 len;
u8 align;
};
int nf_ct_extend_register(const struct nf_ct_ext_type *type);
void nf_ct_extend_unregister(const struct nf_ct_ext_type *type);
#endif /* _NF_CONNTRACK_EXTEND_H */
+157
View File
@@ -0,0 +1,157 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* connection tracking helpers.
*
* 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - generalize L3 protocol dependent part.
*
* Derived from include/linux/netfiter_ipv4/ip_conntrack_helper.h
*/
#ifndef _NF_CONNTRACK_HELPER_H
#define _NF_CONNTRACK_HELPER_H
#include <linux/refcount.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_extend.h>
#include <net/netfilter/nf_conntrack_expect.h>
struct module;
enum nf_ct_helper_flags {
NF_CT_HELPER_F_USERSPACE = (1 << 0),
NF_CT_HELPER_F_CONFIGURED = (1 << 1),
};
#define NF_CT_HELPER_NAME_LEN 16
struct nf_conntrack_helper {
struct hlist_node hnode; /* Internal use. */
char name[NF_CT_HELPER_NAME_LEN]; /* name of the module */
refcount_t refcnt;
struct module *me; /* pointer to self */
const struct nf_conntrack_expect_policy *expect_policy;
/* Tuple of things we will help (compared against server response) */
struct nf_conntrack_tuple tuple;
/* Function to call when data passes; return verdict, or -1 to
invalidate. */
int (*help)(struct sk_buff *skb,
unsigned int protoff,
struct nf_conn *ct,
enum ip_conntrack_info conntrackinfo);
void (*destroy)(struct nf_conn *ct);
int (*from_nlattr)(struct nlattr *attr, struct nf_conn *ct);
int (*to_nlattr)(struct sk_buff *skb, const struct nf_conn *ct);
unsigned int expect_class_max;
unsigned int flags;
/* For user-space helpers: */
unsigned int queue_num;
/* length of userspace private data stored in nf_conn_help->data */
u16 data_len;
};
/* Must be kept in sync with the classes defined by helpers */
#define NF_CT_MAX_EXPECT_CLASSES 4
/* nf_conn feature for connections that have a helper */
struct nf_conn_help {
/* Helper. if any */
struct nf_conntrack_helper __rcu *helper;
struct hlist_head expectations;
/* Current number of expected connections */
u8 expecting[NF_CT_MAX_EXPECT_CLASSES];
/* private helper information. */
char data[32] __aligned(8);
};
#define NF_CT_HELPER_BUILD_BUG_ON(structsize) \
BUILD_BUG_ON((structsize) > FIELD_SIZEOF(struct nf_conn_help, data))
struct nf_conntrack_helper *__nf_conntrack_helper_find(const char *name,
u16 l3num, u8 protonum);
struct nf_conntrack_helper *nf_conntrack_helper_try_module_get(const char *name,
u16 l3num,
u8 protonum);
void nf_conntrack_helper_put(struct nf_conntrack_helper *helper);
void nf_ct_helper_init(struct nf_conntrack_helper *helper,
u16 l3num, u16 protonum, const char *name,
u16 default_port, u16 spec_port, u32 id,
const struct nf_conntrack_expect_policy *exp_pol,
u32 expect_class_max,
int (*help)(struct sk_buff *skb, unsigned int protoff,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo),
int (*from_nlattr)(struct nlattr *attr,
struct nf_conn *ct),
struct module *module);
int nf_conntrack_helper_register(struct nf_conntrack_helper *);
void nf_conntrack_helper_unregister(struct nf_conntrack_helper *);
int nf_conntrack_helpers_register(struct nf_conntrack_helper *, unsigned int);
void nf_conntrack_helpers_unregister(struct nf_conntrack_helper *,
unsigned int);
struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp);
int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
gfp_t flags);
void nf_ct_helper_destroy(struct nf_conn *ct);
static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
{
return nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
}
static inline void *nfct_help_data(const struct nf_conn *ct)
{
struct nf_conn_help *help;
help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
return (void *)help->data;
}
int nf_conntrack_helper_pernet_init(struct net *net);
void nf_conntrack_helper_pernet_fini(struct net *net);
int nf_conntrack_helper_init(void);
void nf_conntrack_helper_fini(void);
int nf_conntrack_broadcast_help(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int timeout);
struct nf_ct_helper_expectfn {
struct list_head head;
const char *name;
void (*expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
};
__printf(3,4)
void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,
const char *fmt, ...);
void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n);
void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n);
struct nf_ct_helper_expectfn *
nf_ct_helper_expectfn_find_by_name(const char *name);
struct nf_ct_helper_expectfn *
nf_ct_helper_expectfn_find_by_symbol(const void *symbol);
extern struct hlist_head *nf_ct_helper_hash;
extern unsigned int nf_ct_helper_hsize;
#endif /*_NF_CONNTRACK_HELPER_H*/
@@ -0,0 +1,160 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Header for use in defining a given L4 protocol for connection tracking.
*
* 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - generalized L3 protocol dependent part.
*
* Derived from include/linux/netfiter_ipv4/ip_conntrack_protcol.h
*/
#ifndef _NF_CONNTRACK_L4PROTO_H
#define _NF_CONNTRACK_L4PROTO_H
#include <linux/netlink.h>
#include <net/netlink.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netns/generic.h>
struct seq_file;
struct nf_conntrack_l4proto {
/* L3 Protocol number. */
u_int16_t l3proto;
/* L4 Protocol number. */
u_int8_t l4proto;
/* Resolve clashes on insertion races. */
bool allow_clash;
/* protoinfo nlattr size, closes a hole */
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,
const struct sk_buff *skb,
unsigned int dataoff,
enum ip_conntrack_info ctinfo);
/* Called when a new connection for this protocol found;
* returns TRUE if it's OK. If so, packet() called next. */
bool (*new)(struct nf_conn *ct, const struct sk_buff *skb,
unsigned int dataoff);
/* Called when a conntrack entry is destroyed */
void (*destroy)(struct nf_conn *ct);
int (*error)(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
unsigned int dataoff,
u_int8_t pf, unsigned int hooknum);
/* called by gc worker if table is full */
bool (*can_early_drop)(const struct nf_conn *ct);
/* convert protoinfo to nfnetink attributes */
int (*to_nlattr)(struct sk_buff *skb, struct nlattr *nla,
struct nf_conn *ct);
/* convert nfnetlink attributes to protoinfo */
int (*from_nlattr)(struct nlattr *tb[], struct nf_conn *ct);
int (*tuple_to_nlattr)(struct sk_buff *skb,
const struct nf_conntrack_tuple *t);
/* Calculate tuple nlattr size */
unsigned int (*nlattr_tuple_size)(void);
int (*nlattr_to_tuple)(struct nlattr *tb[],
struct nf_conntrack_tuple *t);
const struct nla_policy *nla_policy;
struct {
int (*nlattr_to_obj)(struct nlattr *tb[],
struct net *net, void *data);
int (*obj_to_nlattr)(struct sk_buff *skb, const void *data);
u16 obj_size;
u16 nlattr_max;
const struct nla_policy *nla_policy;
} ctnl_timeout;
#ifdef CONFIG_NF_CONNTRACK_PROCFS
/* Print out the private part of the conntrack. */
void (*print_conntrack)(struct seq_file *s, struct nf_conn *);
#endif
unsigned int *net_id;
/* Init l4proto pernet data */
int (*init_net)(struct net *net, u_int16_t proto);
/* Return the per-net protocol part. */
struct nf_proto_net *(*get_net_proto)(struct net *net);
/* Module (if any) which this is connected to. */
struct module *me;
};
/* Existing built-in generic protocol */
extern const struct nf_conntrack_l4proto nf_conntrack_l4proto_generic;
#define MAX_NF_CT_PROTO 256
const struct nf_conntrack_l4proto *__nf_ct_l4proto_find(u_int16_t l3proto,
u_int8_t l4proto);
const struct nf_conntrack_l4proto *nf_ct_l4proto_find_get(u_int16_t l3proto,
u_int8_t l4proto);
void nf_ct_l4proto_put(const struct nf_conntrack_l4proto *p);
/* Protocol pernet registration. */
int nf_ct_l4proto_pernet_register_one(struct net *net,
const struct nf_conntrack_l4proto *proto);
void nf_ct_l4proto_pernet_unregister_one(struct net *net,
const struct nf_conntrack_l4proto *proto);
int nf_ct_l4proto_pernet_register(struct net *net,
const struct nf_conntrack_l4proto *const proto[],
unsigned int num_proto);
void nf_ct_l4proto_pernet_unregister(struct net *net,
const struct nf_conntrack_l4proto *const proto[],
unsigned int num_proto);
/* Protocol global registration. */
int nf_ct_l4proto_register_one(const struct nf_conntrack_l4proto *proto);
void nf_ct_l4proto_unregister_one(const struct nf_conntrack_l4proto *proto);
/* Generic netlink helpers */
int nf_ct_port_tuple_to_nlattr(struct sk_buff *skb,
const struct nf_conntrack_tuple *tuple);
int nf_ct_port_nlattr_to_tuple(struct nlattr *tb[],
struct nf_conntrack_tuple *t);
unsigned int nf_ct_port_nlattr_tuple_size(void);
extern const struct nla_policy nf_ct_port_nla_policy[];
#ifdef CONFIG_SYSCTL
__printf(3, 4) __cold
void nf_ct_l4proto_log_invalid(const struct sk_buff *skb,
const struct nf_conn *ct,
const char *fmt, ...);
__printf(5, 6) __cold
void nf_l4proto_log_invalid(const struct sk_buff *skb,
struct net *net,
u16 pf, u8 protonum,
const char *fmt, ...);
#else
static inline __printf(5, 6) __cold
void nf_l4proto_log_invalid(const struct sk_buff *skb, struct net *net,
u16 pf, u8 protonum, const char *fmt, ...) {}
static inline __printf(3, 4) __cold
void nf_ct_l4proto_log_invalid(const struct sk_buff *skb,
const struct nf_conn *ct,
const char *fmt, ...) { }
#endif /* CONFIG_SYSCTL */
#endif /*_NF_CONNTRACK_PROTOCOL_H*/
@@ -0,0 +1,53 @@
/* SPDX-License-Identifier: GPL-2.0 */
#include <linux/types.h>
#include <net/net_namespace.h>
#include <linux/netfilter/nf_conntrack_common.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_extend.h>
#include <uapi/linux/netfilter/xt_connlabel.h>
#define NF_CT_LABELS_MAX_SIZE ((XT_CONNLABEL_MAXBIT + 1) / BITS_PER_BYTE)
struct nf_conn_labels {
unsigned long bits[NF_CT_LABELS_MAX_SIZE / sizeof(long)];
};
static inline struct nf_conn_labels *nf_ct_labels_find(const struct nf_conn *ct)
{
#ifdef CONFIG_NF_CONNTRACK_LABELS
return nf_ct_ext_find(ct, NF_CT_EXT_LABELS);
#else
return NULL;
#endif
}
static inline struct nf_conn_labels *nf_ct_labels_ext_add(struct nf_conn *ct)
{
#ifdef CONFIG_NF_CONNTRACK_LABELS
struct net *net = nf_ct_net(ct);
if (net->ct.labels_used == 0)
return NULL;
return nf_ct_ext_add(ct, NF_CT_EXT_LABELS, GFP_ATOMIC);
#else
return NULL;
#endif
}
int nf_connlabels_replace(struct nf_conn *ct,
const u32 *data, const u32 *mask, unsigned int words);
#ifdef CONFIG_NF_CONNTRACK_LABELS
int nf_conntrack_labels_init(void);
void nf_conntrack_labels_fini(void);
int nf_connlabels_get(struct net *net, unsigned int bit);
void nf_connlabels_put(struct net *net);
#else
static inline int nf_conntrack_labels_init(void) { return 0; }
static inline void nf_conntrack_labels_fini(void) {}
static inline int nf_connlabels_get(struct net *net, unsigned int bit) { return 0; }
static inline void nf_connlabels_put(struct net *net) {}
#endif
@@ -0,0 +1,48 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_CONNTRACK_SEQADJ_H
#define _NF_CONNTRACK_SEQADJ_H
#include <net/netfilter/nf_conntrack_extend.h>
/**
* struct nf_ct_seqadj - sequence number adjustment information
*
* @correction_pos: position of the last TCP sequence number modification
* @offset_before: sequence number offset before last modification
* @offset_after: sequence number offset after last modification
*/
struct nf_ct_seqadj {
u32 correction_pos;
s32 offset_before;
s32 offset_after;
};
struct nf_conn_seqadj {
struct nf_ct_seqadj seq[IP_CT_DIR_MAX];
};
static inline struct nf_conn_seqadj *nfct_seqadj(const struct nf_conn *ct)
{
return nf_ct_ext_find(ct, NF_CT_EXT_SEQADJ);
}
static inline struct nf_conn_seqadj *nfct_seqadj_ext_add(struct nf_conn *ct)
{
return nf_ct_ext_add(ct, NF_CT_EXT_SEQADJ, GFP_ATOMIC);
}
int nf_ct_seqadj_init(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
s32 off);
int nf_ct_seqadj_set(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
__be32 seq, s32 off);
void nf_ct_tcp_seqadj_set(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo, s32 off);
int nf_ct_seq_adjust(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo, unsigned int protoff);
s32 nf_ct_seq_offset(const struct nf_conn *ct, enum ip_conntrack_dir, u32 seq);
int nf_conntrack_seqadj_init(void);
void nf_conntrack_seqadj_fini(void);
#endif /* _NF_CONNTRACK_SEQADJ_H */
@@ -0,0 +1,92 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_CONNTRACK_SYNPROXY_H
#define _NF_CONNTRACK_SYNPROXY_H
#include <net/netns/generic.h>
struct nf_conn_synproxy {
u32 isn;
u32 its;
u32 tsoff;
};
static inline struct nf_conn_synproxy *nfct_synproxy(const struct nf_conn *ct)
{
#if IS_ENABLED(CONFIG_NETFILTER_SYNPROXY)
return nf_ct_ext_find(ct, NF_CT_EXT_SYNPROXY);
#else
return NULL;
#endif
}
static inline struct nf_conn_synproxy *nfct_synproxy_ext_add(struct nf_conn *ct)
{
#if IS_ENABLED(CONFIG_NETFILTER_SYNPROXY)
return nf_ct_ext_add(ct, NF_CT_EXT_SYNPROXY, GFP_ATOMIC);
#else
return NULL;
#endif
}
static inline bool nf_ct_add_synproxy(struct nf_conn *ct,
const struct nf_conn *tmpl)
{
if (tmpl && nfct_synproxy(tmpl)) {
if (!nfct_seqadj_ext_add(ct))
return false;
if (!nfct_synproxy_ext_add(ct))
return false;
}
return true;
}
struct synproxy_stats {
unsigned int syn_received;
unsigned int cookie_invalid;
unsigned int cookie_valid;
unsigned int cookie_retrans;
unsigned int conn_reopened;
};
struct synproxy_net {
struct nf_conn *tmpl;
struct synproxy_stats __percpu *stats;
unsigned int hook_ref4;
unsigned int hook_ref6;
};
extern unsigned int synproxy_net_id;
static inline struct synproxy_net *synproxy_pernet(struct net *net)
{
return net_generic(net, synproxy_net_id);
}
struct synproxy_options {
u8 options;
u8 wscale;
u16 mss;
u32 tsval;
u32 tsecr;
};
struct tcphdr;
struct xt_synproxy_info;
bool synproxy_parse_options(const struct sk_buff *skb, unsigned int doff,
const struct tcphdr *th,
struct synproxy_options *opts);
unsigned int synproxy_options_size(const struct synproxy_options *opts);
void synproxy_build_options(struct tcphdr *th,
const struct synproxy_options *opts);
void synproxy_init_timestamp_cookie(const struct xt_synproxy_info *info,
struct synproxy_options *opts);
void synproxy_check_timestamp_cookie(struct synproxy_options *opts);
unsigned int synproxy_tstamp_adjust(struct sk_buff *skb, unsigned int protoff,
struct tcphdr *th, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
const struct nf_conn_synproxy *synproxy);
#endif /* _NF_CONNTRACK_SYNPROXY_H */
@@ -0,0 +1,108 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_CONNTRACK_TIMEOUT_H
#define _NF_CONNTRACK_TIMEOUT_H
#include <net/net_namespace.h>
#include <linux/netfilter/nf_conntrack_common.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
#include <linux/refcount.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_extend.h>
#define CTNL_TIMEOUT_NAME_MAX 32
struct nf_ct_timeout {
__u16 l3num;
const struct nf_conntrack_l4proto *l4proto;
char data[0];
};
struct ctnl_timeout {
struct list_head head;
struct rcu_head rcu_head;
refcount_t refcnt;
char name[CTNL_TIMEOUT_NAME_MAX];
struct nf_ct_timeout timeout;
};
struct nf_conn_timeout {
struct nf_ct_timeout __rcu *timeout;
};
static inline unsigned int *
nf_ct_timeout_data(const struct nf_conn_timeout *t)
{
struct nf_ct_timeout *timeout;
timeout = rcu_dereference(t->timeout);
if (timeout == NULL)
return NULL;
return (unsigned int *)timeout->data;
}
static inline
struct nf_conn_timeout *nf_ct_timeout_find(const struct nf_conn *ct)
{
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
return nf_ct_ext_find(ct, NF_CT_EXT_TIMEOUT);
#else
return NULL;
#endif
}
static inline
struct nf_conn_timeout *nf_ct_timeout_ext_add(struct nf_conn *ct,
struct nf_ct_timeout *timeout,
gfp_t gfp)
{
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
struct nf_conn_timeout *timeout_ext;
timeout_ext = nf_ct_ext_add(ct, NF_CT_EXT_TIMEOUT, gfp);
if (timeout_ext == NULL)
return NULL;
rcu_assign_pointer(timeout_ext->timeout, timeout);
return timeout_ext;
#else
return NULL;
#endif
};
static inline unsigned int *nf_ct_timeout_lookup(const struct nf_conn *ct)
{
unsigned int *timeouts = NULL;
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
struct nf_conn_timeout *timeout_ext;
timeout_ext = nf_ct_timeout_find(ct);
if (timeout_ext)
timeouts = nf_ct_timeout_data(timeout_ext);
#endif
return timeouts;
}
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
int nf_conntrack_timeout_init(void);
void nf_conntrack_timeout_fini(void);
void nf_ct_untimeout(struct net *net, struct nf_ct_timeout *timeout);
#else
static inline int nf_conntrack_timeout_init(void)
{
return 0;
}
static inline void nf_conntrack_timeout_fini(void)
{
return;
}
#endif /* CONFIG_NF_CONNTRACK_TIMEOUT */
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
extern struct nf_ct_timeout *(*nf_ct_timeout_find_get_hook)(struct net *net, const char *name);
extern void (*nf_ct_timeout_put_hook)(struct nf_ct_timeout *timeout);
#endif
#endif /* _NF_CONNTRACK_TIMEOUT_H */
@@ -0,0 +1,79 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_CONNTRACK_TSTAMP_H
#define _NF_CONNTRACK_TSTAMP_H
#include <net/net_namespace.h>
#include <linux/netfilter/nf_conntrack_common.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_conntrack_extend.h>
struct nf_conn_tstamp {
u_int64_t start;
u_int64_t stop;
};
static inline
struct nf_conn_tstamp *nf_conn_tstamp_find(const struct nf_conn *ct)
{
#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
return nf_ct_ext_find(ct, NF_CT_EXT_TSTAMP);
#else
return NULL;
#endif
}
static inline
struct nf_conn_tstamp *nf_ct_tstamp_ext_add(struct nf_conn *ct, gfp_t gfp)
{
#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
struct net *net = nf_ct_net(ct);
if (!net->ct.sysctl_tstamp)
return NULL;
return nf_ct_ext_add(ct, NF_CT_EXT_TSTAMP, gfp);
#else
return NULL;
#endif
};
static inline bool nf_ct_tstamp_enabled(struct net *net)
{
return net->ct.sysctl_tstamp != 0;
}
static inline void nf_ct_set_tstamp(struct net *net, bool enable)
{
net->ct.sysctl_tstamp = enable;
}
#ifdef CONFIG_NF_CONNTRACK_TIMESTAMP
int nf_conntrack_tstamp_pernet_init(struct net *net);
void nf_conntrack_tstamp_pernet_fini(struct net *net);
int nf_conntrack_tstamp_init(void);
void nf_conntrack_tstamp_fini(void);
#else
static inline int nf_conntrack_tstamp_pernet_init(struct net *net)
{
return 0;
}
static inline void nf_conntrack_tstamp_pernet_fini(struct net *net)
{
return;
}
static inline int nf_conntrack_tstamp_init(void)
{
return 0;
}
static inline void nf_conntrack_tstamp_fini(void)
{
return;
}
#endif /* CONFIG_NF_CONNTRACK_TIMESTAMP */
#endif /* _NF_CONNTRACK_TSTAMP_H */
+187
View File
@@ -0,0 +1,187 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Definitions and Declarations for tuple.
*
* 16 Dec 2003: Yasuyuki Kozakai @USAGI <yasuyuki.kozakai@toshiba.co.jp>
* - generalize L3 protocol dependent part.
*
* Derived from include/linux/netfiter_ipv4/ip_conntrack_tuple.h
*/
#ifndef _NF_CONNTRACK_TUPLE_H
#define _NF_CONNTRACK_TUPLE_H
#include <linux/netfilter/x_tables.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
#include <linux/list_nulls.h>
/* A `tuple' is a structure containing the information to uniquely
identify a connection. ie. if two packets have the same tuple, they
are in the same connection; if not, they are not.
We divide the structure along "manipulatable" and
"non-manipulatable" lines, for the benefit of the NAT code.
*/
#define NF_CT_TUPLE_L3SIZE ARRAY_SIZE(((union nf_inet_addr *)NULL)->all)
/* The manipulable part of the tuple. */
struct nf_conntrack_man {
union nf_inet_addr u3;
union nf_conntrack_man_proto u;
/* Layer 3 protocol */
u_int16_t l3num;
};
/* This contains the information to distinguish a connection. */
struct nf_conntrack_tuple {
struct nf_conntrack_man src;
/* These are the parts of the tuple which are fixed. */
struct {
union nf_inet_addr u3;
union {
/* Add other protocols here. */
__be16 all;
struct {
__be16 port;
} tcp;
struct {
__be16 port;
} udp;
struct {
u_int8_t type, code;
} icmp;
struct {
__be16 port;
} dccp;
struct {
__be16 port;
} sctp;
struct {
__be16 key;
} gre;
} u;
/* The protocol. */
u_int8_t protonum;
/* The direction (for tuplehash) */
u_int8_t dir;
} dst;
};
struct nf_conntrack_tuple_mask {
struct {
union nf_inet_addr u3;
union nf_conntrack_man_proto u;
} src;
};
static inline void nf_ct_dump_tuple_ip(const struct nf_conntrack_tuple *t)
{
#ifdef DEBUG
printk("tuple %p: %u %pI4:%hu -> %pI4:%hu\n",
t, t->dst.protonum,
&t->src.u3.ip, ntohs(t->src.u.all),
&t->dst.u3.ip, ntohs(t->dst.u.all));
#endif
}
static inline void nf_ct_dump_tuple_ipv6(const struct nf_conntrack_tuple *t)
{
#ifdef DEBUG
printk("tuple %p: %u %pI6 %hu -> %pI6 %hu\n",
t, t->dst.protonum,
t->src.u3.all, ntohs(t->src.u.all),
t->dst.u3.all, ntohs(t->dst.u.all));
#endif
}
static inline void nf_ct_dump_tuple(const struct nf_conntrack_tuple *t)
{
switch (t->src.l3num) {
case AF_INET:
nf_ct_dump_tuple_ip(t);
break;
case AF_INET6:
nf_ct_dump_tuple_ipv6(t);
break;
}
}
/* If we're the first tuple, it's the original dir. */
#define NF_CT_DIRECTION(h) \
((enum ip_conntrack_dir)(h)->tuple.dst.dir)
/* Connections have two entries in the hash table: one for each way */
struct nf_conntrack_tuple_hash {
struct hlist_nulls_node hnnode;
struct nf_conntrack_tuple tuple;
};
static inline bool __nf_ct_tuple_src_equal(const struct nf_conntrack_tuple *t1,
const struct nf_conntrack_tuple *t2)
{
return (nf_inet_addr_cmp(&t1->src.u3, &t2->src.u3) &&
t1->src.u.all == t2->src.u.all &&
t1->src.l3num == t2->src.l3num);
}
static inline bool __nf_ct_tuple_dst_equal(const struct nf_conntrack_tuple *t1,
const struct nf_conntrack_tuple *t2)
{
return (nf_inet_addr_cmp(&t1->dst.u3, &t2->dst.u3) &&
t1->dst.u.all == t2->dst.u.all &&
t1->dst.protonum == t2->dst.protonum);
}
static inline bool nf_ct_tuple_equal(const struct nf_conntrack_tuple *t1,
const struct nf_conntrack_tuple *t2)
{
return __nf_ct_tuple_src_equal(t1, t2) &&
__nf_ct_tuple_dst_equal(t1, t2);
}
static inline bool
nf_ct_tuple_mask_equal(const struct nf_conntrack_tuple_mask *m1,
const struct nf_conntrack_tuple_mask *m2)
{
return (nf_inet_addr_cmp(&m1->src.u3, &m2->src.u3) &&
m1->src.u.all == m2->src.u.all);
}
static inline bool
nf_ct_tuple_src_mask_cmp(const struct nf_conntrack_tuple *t1,
const struct nf_conntrack_tuple *t2,
const struct nf_conntrack_tuple_mask *mask)
{
int count;
for (count = 0; count < NF_CT_TUPLE_L3SIZE; count++) {
if ((t1->src.u3.all[count] ^ t2->src.u3.all[count]) &
mask->src.u3.all[count])
return false;
}
if ((t1->src.u.all ^ t2->src.u.all) & mask->src.u.all)
return false;
if (t1->src.l3num != t2->src.l3num ||
t1->dst.protonum != t2->dst.protonum)
return false;
return true;
}
static inline bool
nf_ct_tuple_mask_cmp(const struct nf_conntrack_tuple *t,
const struct nf_conntrack_tuple *tuple,
const struct nf_conntrack_tuple_mask *mask)
{
return nf_ct_tuple_src_mask_cmp(t, tuple, mask) &&
__nf_ct_tuple_dst_equal(t, tuple);
}
#endif /* _NF_CONNTRACK_TUPLE_H */
@@ -0,0 +1,91 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_CONNTRACK_ZONES_H
#define _NF_CONNTRACK_ZONES_H
#include <linux/netfilter/nf_conntrack_zones_common.h>
#if IS_ENABLED(CONFIG_NF_CONNTRACK)
#include <net/netfilter/nf_conntrack_extend.h>
static inline const struct nf_conntrack_zone *
nf_ct_zone(const struct nf_conn *ct)
{
#ifdef CONFIG_NF_CONNTRACK_ZONES
return &ct->zone;
#else
return &nf_ct_zone_dflt;
#endif
}
static inline const struct nf_conntrack_zone *
nf_ct_zone_init(struct nf_conntrack_zone *zone, u16 id, u8 dir, u8 flags)
{
zone->id = id;
zone->flags = flags;
zone->dir = dir;
return zone;
}
static inline const struct nf_conntrack_zone *
nf_ct_zone_tmpl(const struct nf_conn *tmpl, const struct sk_buff *skb,
struct nf_conntrack_zone *tmp)
{
#ifdef CONFIG_NF_CONNTRACK_ZONES
if (!tmpl)
return &nf_ct_zone_dflt;
if (tmpl->zone.flags & NF_CT_FLAG_MARK)
return nf_ct_zone_init(tmp, skb->mark, tmpl->zone.dir, 0);
#endif
return nf_ct_zone(tmpl);
}
static inline void nf_ct_zone_add(struct nf_conn *ct,
const struct nf_conntrack_zone *zone)
{
#ifdef CONFIG_NF_CONNTRACK_ZONES
ct->zone = *zone;
#endif
}
static inline bool nf_ct_zone_matches_dir(const struct nf_conntrack_zone *zone,
enum ip_conntrack_dir dir)
{
return zone->dir & (1 << dir);
}
static inline u16 nf_ct_zone_id(const struct nf_conntrack_zone *zone,
enum ip_conntrack_dir dir)
{
#ifdef CONFIG_NF_CONNTRACK_ZONES
return nf_ct_zone_matches_dir(zone, dir) ?
zone->id : NF_CT_DEFAULT_ZONE_ID;
#else
return NF_CT_DEFAULT_ZONE_ID;
#endif
}
static inline bool nf_ct_zone_equal(const struct nf_conn *a,
const struct nf_conntrack_zone *b,
enum ip_conntrack_dir dir)
{
#ifdef CONFIG_NF_CONNTRACK_ZONES
return nf_ct_zone_id(nf_ct_zone(a), dir) ==
nf_ct_zone_id(b, dir);
#else
return true;
#endif
}
static inline bool nf_ct_zone_equal_any(const struct nf_conn *a,
const struct nf_conntrack_zone *b)
{
#ifdef CONFIG_NF_CONNTRACK_ZONES
return nf_ct_zone(a)->id == b->id;
#else
return true;
#endif
}
#endif /* IS_ENABLED(CONFIG_NF_CONNTRACK) */
#endif /* _NF_CONNTRACK_ZONES_H */
+8
View File
@@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_DUP_NETDEV_H_
#define _NF_DUP_NETDEV_H_
void nf_dup_netdev_egress(const struct nft_pktinfo *pkt, int oif);
void nf_fwd_netdev_egress(const struct nft_pktinfo *pkt, int oif);
#endif
+131
View File
@@ -0,0 +1,131 @@
#ifndef _NF_FLOW_TABLE_H
#define _NF_FLOW_TABLE_H
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/netdevice.h>
#include <linux/rhashtable-types.h>
#include <linux/rcupdate.h>
#include <linux/netfilter/nf_conntrack_tuple_common.h>
#include <net/dst.h>
struct nf_flowtable;
struct nf_flowtable_type {
struct list_head list;
int family;
int (*init)(struct nf_flowtable *ft);
void (*free)(struct nf_flowtable *ft);
nf_hookfn *hook;
struct module *owner;
};
struct nf_flowtable {
struct list_head list;
struct rhashtable rhashtable;
const struct nf_flowtable_type *type;
struct delayed_work gc_work;
};
enum flow_offload_tuple_dir {
FLOW_OFFLOAD_DIR_ORIGINAL = IP_CT_DIR_ORIGINAL,
FLOW_OFFLOAD_DIR_REPLY = IP_CT_DIR_REPLY,
FLOW_OFFLOAD_DIR_MAX = IP_CT_DIR_MAX
};
struct flow_offload_tuple {
union {
struct in_addr src_v4;
struct in6_addr src_v6;
};
union {
struct in_addr dst_v4;
struct in6_addr dst_v6;
};
struct {
__be16 src_port;
__be16 dst_port;
};
int iifidx;
u8 l3proto;
u8 l4proto;
u8 dir;
int oifidx;
u16 mtu;
struct dst_entry *dst_cache;
};
struct flow_offload_tuple_rhash {
struct rhash_head node;
struct flow_offload_tuple tuple;
};
#define FLOW_OFFLOAD_SNAT 0x1
#define FLOW_OFFLOAD_DNAT 0x2
#define FLOW_OFFLOAD_DYING 0x4
#define FLOW_OFFLOAD_TEARDOWN 0x8
struct flow_offload {
struct flow_offload_tuple_rhash tuplehash[FLOW_OFFLOAD_DIR_MAX];
u32 flags;
union {
/* Your private driver data here. */
u32 timeout;
};
};
#define NF_FLOW_TIMEOUT (30 * HZ)
struct nf_flow_route {
struct {
struct dst_entry *dst;
} tuple[FLOW_OFFLOAD_DIR_MAX];
};
struct flow_offload *flow_offload_alloc(struct nf_conn *ct,
struct nf_flow_route *route);
void flow_offload_free(struct flow_offload *flow);
int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow);
struct flow_offload_tuple_rhash *flow_offload_lookup(struct nf_flowtable *flow_table,
struct flow_offload_tuple *tuple);
int nf_flow_table_iterate(struct nf_flowtable *flow_table,
void (*iter)(struct flow_offload *flow, void *data),
void *data);
void nf_flow_table_cleanup(struct net *net, struct net_device *dev);
int nf_flow_table_init(struct nf_flowtable *flow_table);
void nf_flow_table_free(struct nf_flowtable *flow_table);
void flow_offload_teardown(struct flow_offload *flow);
static inline void flow_offload_dead(struct flow_offload *flow)
{
flow->flags |= FLOW_OFFLOAD_DYING;
}
int nf_flow_snat_port(const struct flow_offload *flow,
struct sk_buff *skb, unsigned int thoff,
u8 protocol, enum flow_offload_tuple_dir dir);
int nf_flow_dnat_port(const struct flow_offload *flow,
struct sk_buff *skb, unsigned int thoff,
u8 protocol, enum flow_offload_tuple_dir dir);
struct flow_ports {
__be16 source, dest;
};
unsigned int nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state);
unsigned int nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state);
#define MODULE_ALIAS_NF_FLOWTABLE(family) \
MODULE_ALIAS("nf-flowtable-" __stringify(family))
#endif /* _FLOW_OFFLOAD_H */
+126
View File
@@ -0,0 +1,126 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_LOG_H
#define _NF_LOG_H
#include <linux/netfilter.h>
#include <linux/netfilter/nf_log.h>
/* Log tcp sequence, tcp options, ip options and uid owning local socket */
#define NF_LOG_DEFAULT_MASK 0x0f
/* This flag indicates that copy_len field in nf_loginfo is set */
#define NF_LOG_F_COPY_LEN 0x1
enum nf_log_type {
NF_LOG_TYPE_LOG = 0,
NF_LOG_TYPE_ULOG,
NF_LOG_TYPE_MAX
};
struct nf_loginfo {
u_int8_t type;
union {
struct {
/* copy_len will be used iff you set
* NF_LOG_F_COPY_LEN in flags
*/
u_int32_t copy_len;
u_int16_t group;
u_int16_t qthreshold;
u_int16_t flags;
} ulog;
struct {
u_int8_t level;
u_int8_t logflags;
} log;
} u;
};
typedef void nf_logfn(struct net *net,
u_int8_t pf,
unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct nf_loginfo *li,
const char *prefix);
struct nf_logger {
char *name;
enum nf_log_type type;
nf_logfn *logfn;
struct module *me;
};
/* sysctl_nf_log_all_netns - allow LOG target in all network namespaces */
extern int sysctl_nf_log_all_netns;
/* Function to register/unregister log function. */
int nf_log_register(u_int8_t pf, struct nf_logger *logger);
void nf_log_unregister(struct nf_logger *logger);
int nf_log_set(struct net *net, u_int8_t pf, const struct nf_logger *logger);
void nf_log_unset(struct net *net, const struct nf_logger *logger);
int nf_log_bind_pf(struct net *net, u_int8_t pf,
const struct nf_logger *logger);
void nf_log_unbind_pf(struct net *net, u_int8_t pf);
int nf_logger_find_get(int pf, enum nf_log_type type);
void nf_logger_put(int pf, enum nf_log_type type);
void nf_logger_request_module(int pf, enum nf_log_type type);
#define MODULE_ALIAS_NF_LOGGER(family, type) \
MODULE_ALIAS("nf-logger-" __stringify(family) "-" __stringify(type))
/* Calls the registered backend logging function */
__printf(8, 9)
void nf_log_packet(struct net *net,
u_int8_t pf,
unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct nf_loginfo *li,
const char *fmt, ...);
__printf(8, 9)
void nf_log_trace(struct net *net,
u_int8_t pf,
unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct nf_loginfo *li,
const char *fmt, ...);
struct nf_log_buf;
struct nf_log_buf *nf_log_buf_open(void);
__printf(2, 3) int nf_log_buf_add(struct nf_log_buf *m, const char *f, ...);
void nf_log_buf_close(struct nf_log_buf *m);
/* common logging functions */
int nf_log_dump_udp_header(struct nf_log_buf *m, const struct sk_buff *skb,
u8 proto, int fragment, unsigned int offset);
int nf_log_dump_tcp_header(struct nf_log_buf *m, const struct sk_buff *skb,
u8 proto, int fragment, unsigned int offset,
unsigned int logflags);
void nf_log_dump_sk_uid_gid(struct net *net, struct nf_log_buf *m,
struct sock *sk);
void nf_log_dump_vlan(struct nf_log_buf *m, const struct sk_buff *skb);
void nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf,
unsigned int hooknum, const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct nf_loginfo *loginfo,
const char *prefix);
void nf_log_l2packet(struct net *net, u_int8_t pf,
__be16 protocol,
unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const struct nf_loginfo *loginfo, const char *prefix);
#endif /* _NF_LOG_H */
+82
View File
@@ -0,0 +1,82 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_NAT_H
#define _NF_NAT_H
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter/nf_nat.h>
#include <net/netfilter/nf_conntrack_tuple.h>
enum nf_nat_manip_type {
NF_NAT_MANIP_SRC,
NF_NAT_MANIP_DST
};
/* SRC manip occurs POST_ROUTING or LOCAL_IN */
#define HOOK2MANIP(hooknum) ((hooknum) != NF_INET_POST_ROUTING && \
(hooknum) != NF_INET_LOCAL_IN)
#include <linux/list.h>
#include <linux/netfilter/nf_conntrack_pptp.h>
#include <net/netfilter/nf_conntrack_extend.h>
/* per conntrack: nat application helper private data */
union nf_conntrack_nat_help {
/* insert nat helper private data here */
#if defined(CONFIG_NF_NAT_PPTP) || defined(CONFIG_NF_NAT_PPTP_MODULE)
struct nf_nat_pptp nat_pptp_info;
#endif
};
struct nf_conn;
/* The structure embedded in the conntrack structure. */
struct nf_conn_nat {
union nf_conntrack_nat_help help;
#if IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV4) || \
IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV6)
int masq_index;
#endif
};
/* Set up the info structure to map into this range. */
unsigned int nf_nat_setup_info(struct nf_conn *ct,
const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype);
extern unsigned int nf_nat_alloc_null_binding(struct nf_conn *ct,
unsigned int hooknum);
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)
{
#if defined(CONFIG_NF_NAT) || defined(CONFIG_NF_NAT_MODULE)
return nf_ct_ext_find(ct, NF_CT_EXT_NAT);
#else
return NULL;
#endif
}
static inline bool nf_nat_oif_changed(unsigned int hooknum,
enum ip_conntrack_info ctinfo,
struct nf_conn_nat *nat,
const struct net_device *out)
{
#if IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV4) || \
IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV6)
return nat && nat->masq_index && hooknum == NF_INET_POST_ROUTING &&
CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL &&
nat->masq_index != out->ifindex;
#else
return false;
#endif
}
int nf_nat_register_fn(struct net *net, const struct nf_hook_ops *ops,
const struct nf_hook_ops *nat_ops, unsigned int ops_count);
void nf_nat_unregister_fn(struct net *net, const struct nf_hook_ops *ops,
unsigned int ops_count);
#endif
+29
View File
@@ -0,0 +1,29 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_NAT_CORE_H
#define _NF_NAT_CORE_H
#include <linux/list.h>
#include <net/netfilter/nf_conntrack.h>
#include <net/netfilter/nf_nat.h>
/* This header used to share core functionality between the standalone
NAT module, and the compatibility layer's use of NAT for masquerading. */
unsigned int nf_nat_packet(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
unsigned int hooknum, struct sk_buff *skb);
unsigned int
nf_nat_inet_fn(void *priv, struct sk_buff *skb,
const struct nf_hook_state *state);
int nf_xfrm_me_harder(struct net *net, struct sk_buff *skb, unsigned int family);
static inline int nf_nat_initialized(struct nf_conn *ct,
enum nf_nat_manip_type manip)
{
if (manip == NF_NAT_MANIP_SRC)
return ct->status & IPS_SRC_NAT_DONE;
else
return ct->status & IPS_DST_NAT_DONE;
}
#endif /* _NF_NAT_CORE_H */
+41
View File
@@ -0,0 +1,41 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_NAT_HELPER_H
#define _NF_NAT_HELPER_H
/* NAT protocol helper routines. */
#include <net/netfilter/nf_conntrack.h>
struct sk_buff;
/* These return true or false. */
bool __nf_nat_mangle_tcp_packet(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int protoff, unsigned int match_offset,
unsigned int match_len, const char *rep_buffer,
unsigned int rep_len, bool adjust);
static inline bool nf_nat_mangle_tcp_packet(struct sk_buff *skb,
struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int protoff,
unsigned int match_offset,
unsigned int match_len,
const char *rep_buffer,
unsigned int rep_len)
{
return __nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff,
match_offset, match_len,
rep_buffer, rep_len, true);
}
bool nf_nat_mangle_udp_packet(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int protoff, unsigned int match_offset,
unsigned int match_len, const char *rep_buffer,
unsigned int rep_len);
/* Setup NAT on this expected conntrack so it follows master, but goes
* to port ct->master->saved_proto. */
void nf_nat_follow_master(struct nf_conn *ct, struct nf_conntrack_expect *this);
#endif
+57
View File
@@ -0,0 +1,57 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_NAT_L3PROTO_H
#define _NF_NAT_L3PROTO_H
struct nf_nat_l4proto;
struct nf_nat_l3proto {
u8 l3proto;
bool (*in_range)(const struct nf_conntrack_tuple *t,
const struct nf_nat_range2 *range);
u32 (*secure_port)(const struct nf_conntrack_tuple *t, __be16);
bool (*manip_pkt)(struct sk_buff *skb,
unsigned int iphdroff,
const struct nf_nat_l4proto *l4proto,
const struct nf_conntrack_tuple *target,
enum nf_nat_manip_type maniptype);
void (*csum_update)(struct sk_buff *skb, unsigned int iphdroff,
__sum16 *check,
const struct nf_conntrack_tuple *t,
enum nf_nat_manip_type maniptype);
void (*csum_recalc)(struct sk_buff *skb, u8 proto,
void *data, __sum16 *check,
int datalen, int oldlen);
void (*decode_session)(struct sk_buff *skb,
const struct nf_conn *ct,
enum ip_conntrack_dir dir,
unsigned long statusbit,
struct flowi *fl);
int (*nlattr_to_range)(struct nlattr *tb[],
struct nf_nat_range2 *range);
};
int nf_nat_l3proto_register(const struct nf_nat_l3proto *);
void nf_nat_l3proto_unregister(const struct nf_nat_l3proto *);
const struct nf_nat_l3proto *__nf_nat_l3proto_find(u8 l3proto);
int nf_nat_icmp_reply_translation(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int hooknum);
int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, struct nf_conn *ct,
enum ip_conntrack_info ctinfo,
unsigned int hooknum, unsigned int hdrlen);
int nf_nat_l3proto_ipv4_register_fn(struct net *net, const struct nf_hook_ops *ops);
void nf_nat_l3proto_ipv4_unregister_fn(struct net *net, const struct nf_hook_ops *ops);
int nf_nat_l3proto_ipv6_register_fn(struct net *net, const struct nf_hook_ops *ops);
void nf_nat_l3proto_ipv6_unregister_fn(struct net *net, const struct nf_hook_ops *ops);
#endif /* _NF_NAT_L3PROTO_H */
+82
View File
@@ -0,0 +1,82 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Header for use in defining a given protocol. */
#ifndef _NF_NAT_L4PROTO_H
#define _NF_NAT_L4PROTO_H
#include <net/netfilter/nf_nat.h>
#include <linux/netfilter/nfnetlink_conntrack.h>
struct nf_nat_range;
struct nf_nat_l3proto;
struct nf_nat_l4proto {
/* Protocol number. */
u8 l4proto;
/* Translate a packet to the target according to manip type.
* Return true if succeeded.
*/
bool (*manip_pkt)(struct sk_buff *skb,
const struct nf_nat_l3proto *l3proto,
unsigned int iphdroff, unsigned int hdroff,
const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype);
/* Is the manipable part of the tuple between min and max incl? */
bool (*in_range)(const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype,
const union nf_conntrack_man_proto *min,
const union nf_conntrack_man_proto *max);
/* Alter the per-proto part of the tuple (depending on
* maniptype), to give a unique tuple in the given range if
* possible. Per-protocol part of tuple is initialized to the
* incoming packet.
*/
void (*unique_tuple)(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple,
const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype,
const struct nf_conn *ct);
int (*nlattr_to_range)(struct nlattr *tb[],
struct nf_nat_range2 *range);
};
/* Protocol registration. */
int nf_nat_l4proto_register(u8 l3proto, const struct nf_nat_l4proto *l4proto);
void nf_nat_l4proto_unregister(u8 l3proto,
const struct nf_nat_l4proto *l4proto);
const struct nf_nat_l4proto *__nf_nat_l4proto_find(u8 l3proto, u8 l4proto);
/* Built-in protocols. */
extern const struct nf_nat_l4proto nf_nat_l4proto_tcp;
extern const struct nf_nat_l4proto nf_nat_l4proto_udp;
extern const struct nf_nat_l4proto nf_nat_l4proto_icmp;
extern const struct nf_nat_l4proto nf_nat_l4proto_icmpv6;
extern const struct nf_nat_l4proto nf_nat_l4proto_unknown;
#ifdef CONFIG_NF_NAT_PROTO_DCCP
extern const struct nf_nat_l4proto nf_nat_l4proto_dccp;
#endif
#ifdef CONFIG_NF_NAT_PROTO_SCTP
extern const struct nf_nat_l4proto nf_nat_l4proto_sctp;
#endif
#ifdef CONFIG_NF_NAT_PROTO_UDPLITE
extern const struct nf_nat_l4proto nf_nat_l4proto_udplite;
#endif
bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple,
enum nf_nat_manip_type maniptype,
const union nf_conntrack_man_proto *min,
const union nf_conntrack_man_proto *max);
void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
struct nf_conntrack_tuple *tuple,
const struct nf_nat_range2 *range,
enum nf_nat_manip_type maniptype,
const struct nf_conn *ct, u16 *rover);
int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[],
struct nf_nat_range2 *range);
#endif /*_NF_NAT_L4PROTO_H*/
+13
View File
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_NAT_REDIRECT_H_
#define _NF_NAT_REDIRECT_H_
unsigned int
nf_nat_redirect_ipv4(struct sk_buff *skb,
const struct nf_nat_ipv4_multi_range_compat *mr,
unsigned int hooknum);
unsigned int
nf_nat_redirect_ipv6(struct sk_buff *skb, const struct nf_nat_range2 *range,
unsigned int hooknum);
#endif /* _NF_NAT_REDIRECT_H_ */
+122
View File
@@ -0,0 +1,122 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_QUEUE_H
#define _NF_QUEUE_H
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/jhash.h>
/* Each queued (to userspace) skbuff has one of these. */
struct nf_queue_entry {
struct list_head list;
struct sk_buff *skb;
unsigned int id;
unsigned int hook_index; /* index in hook_entries->hook[] */
struct nf_hook_state state;
u16 size; /* sizeof(entry) + saved route keys */
/* extra space to store route keys */
};
#define nf_queue_entry_reroute(x) ((void *)x + sizeof(struct nf_queue_entry))
/* Packet queuing */
struct nf_queue_handler {
int (*outfn)(struct nf_queue_entry *entry,
unsigned int queuenum);
void (*nf_hook_drop)(struct net *net);
};
void nf_register_queue_handler(struct net *net, const struct nf_queue_handler *qh);
void nf_unregister_queue_handler(struct net *net);
void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict);
void nf_queue_entry_get_refs(struct nf_queue_entry *entry);
void nf_queue_entry_release_refs(struct nf_queue_entry *entry);
static inline void init_hashrandom(u32 *jhash_initval)
{
while (*jhash_initval == 0)
*jhash_initval = prandom_u32();
}
static inline u32 hash_v4(const struct iphdr *iph, u32 initval)
{
/* packets in either direction go into same queue */
if ((__force u32)iph->saddr < (__force u32)iph->daddr)
return jhash_3words((__force u32)iph->saddr,
(__force u32)iph->daddr, iph->protocol, initval);
return jhash_3words((__force u32)iph->daddr,
(__force u32)iph->saddr, iph->protocol, initval);
}
static inline u32 hash_v6(const struct ipv6hdr *ip6h, u32 initval)
{
u32 a, b, c;
if ((__force u32)ip6h->saddr.s6_addr32[3] <
(__force u32)ip6h->daddr.s6_addr32[3]) {
a = (__force u32) ip6h->saddr.s6_addr32[3];
b = (__force u32) ip6h->daddr.s6_addr32[3];
} else {
b = (__force u32) ip6h->saddr.s6_addr32[3];
a = (__force u32) ip6h->daddr.s6_addr32[3];
}
if ((__force u32)ip6h->saddr.s6_addr32[1] <
(__force u32)ip6h->daddr.s6_addr32[1])
c = (__force u32) ip6h->saddr.s6_addr32[1];
else
c = (__force u32) ip6h->daddr.s6_addr32[1];
return jhash_3words(a, b, c, initval);
}
static inline u32 hash_bridge(const struct sk_buff *skb, u32 initval)
{
struct ipv6hdr *ip6h, _ip6h;
struct iphdr *iph, _iph;
switch (eth_hdr(skb)->h_proto) {
case htons(ETH_P_IP):
iph = skb_header_pointer(skb, skb_network_offset(skb),
sizeof(*iph), &_iph);
if (iph)
return hash_v4(iph, initval);
break;
case htons(ETH_P_IPV6):
ip6h = skb_header_pointer(skb, skb_network_offset(skb),
sizeof(*ip6h), &_ip6h);
if (ip6h)
return hash_v6(ip6h, initval);
break;
}
return 0;
}
static inline u32
nfqueue_hash(const struct sk_buff *skb, u16 queue, u16 queues_total, u8 family,
u32 initval)
{
switch (family) {
case NFPROTO_IPV4:
queue += reciprocal_scale(hash_v4(ip_hdr(skb), initval),
queues_total);
break;
case NFPROTO_IPV6:
queue += reciprocal_scale(hash_v6(ipv6_hdr(skb), initval),
queues_total);
break;
case NFPROTO_BRIDGE:
queue += reciprocal_scale(hash_bridge(skb, initval),
queues_total);
break;
}
return queue;
}
#endif /* _NF_QUEUE_H */
+13
View File
@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_SOCK_H_
#define _NF_SOCK_H_
#include <net/sock.h>
struct sock *nf_sk_lookup_slow_v4(struct net *net, const struct sk_buff *skb,
const struct net_device *indev);
struct sock *nf_sk_lookup_slow_v6(struct net *net, const struct sk_buff *skb,
const struct net_device *indev);
#endif
File diff suppressed because it is too large. Load diff
+81
View File
@@ -0,0 +1,81 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NET_NF_TABLES_CORE_H
#define _NET_NF_TABLES_CORE_H
#include <net/netfilter/nf_tables.h>
extern struct nft_expr_type nft_imm_type;
extern struct nft_expr_type nft_cmp_type;
extern struct nft_expr_type nft_lookup_type;
extern struct nft_expr_type nft_bitwise_type;
extern struct nft_expr_type nft_byteorder_type;
extern struct nft_expr_type nft_payload_type;
extern struct nft_expr_type nft_dynset_type;
extern struct nft_expr_type nft_range_type;
extern struct nft_expr_type nft_meta_type;
extern struct nft_expr_type nft_rt_type;
extern struct nft_expr_type nft_exthdr_type;
int nf_tables_core_module_init(void);
void nf_tables_core_module_exit(void);
struct nft_cmp_fast_expr {
u32 data;
enum nft_registers sreg:8;
u8 len;
};
struct nft_immediate_expr {
struct nft_data data;
enum nft_registers dreg:8;
u8 dlen;
};
/* Calculate the mask for the nft_cmp_fast expression. On big endian the
* mask needs to include the *upper* bytes when interpreting that data as
* something smaller than the full u32, therefore a cpu_to_le32 is done.
*/
static inline u32 nft_cmp_fast_mask(unsigned int len)
{
return cpu_to_le32(~0U >> (FIELD_SIZEOF(struct nft_cmp_fast_expr,
data) * BITS_PER_BYTE - len));
}
extern const struct nft_expr_ops nft_cmp_fast_ops;
struct nft_payload {
enum nft_payload_bases base:8;
u8 offset;
u8 len;
enum nft_registers dreg:8;
};
struct nft_payload_set {
enum nft_payload_bases base:8;
u8 offset;
u8 len;
enum nft_registers sreg:8;
u8 csum_type;
u8 csum_offset;
u8 csum_flags;
};
extern const struct nft_expr_ops nft_payload_fast_ops;
extern struct static_key_false nft_counters_enabled;
extern struct static_key_false nft_trace_enabled;
extern struct nft_set_type nft_set_rhash_type;
extern struct nft_set_type nft_set_hash_type;
extern struct nft_set_type nft_set_hash_fast_type;
extern struct nft_set_type nft_set_rbtree_type;
extern struct nft_set_type nft_set_bitmap_type;
struct nft_expr;
struct nft_regs;
struct nft_pktinfo;
void nft_meta_get_eval(const struct nft_expr *expr,
struct nft_regs *regs, const struct nft_pktinfo *pkt);
void nft_lookup_eval(const struct nft_expr *expr,
struct nft_regs *regs, const struct nft_pktinfo *pkt);
#endif /* _NET_NF_TABLES_CORE_H */
+56
View File
@@ -0,0 +1,56 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_TABLES_IPV4_H_
#define _NF_TABLES_IPV4_H_
#include <net/netfilter/nf_tables.h>
#include <net/ip.h>
static inline void nft_set_pktinfo_ipv4(struct nft_pktinfo *pkt,
struct sk_buff *skb)
{
struct iphdr *ip;
ip = ip_hdr(pkt->skb);
pkt->tprot_set = true;
pkt->tprot = ip->protocol;
pkt->xt.thoff = ip_hdrlen(pkt->skb);
pkt->xt.fragoff = ntohs(ip->frag_off) & IP_OFFSET;
}
static inline int __nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt,
struct sk_buff *skb)
{
struct iphdr *iph, _iph;
u32 len, thoff;
iph = skb_header_pointer(skb, skb_network_offset(skb), sizeof(*iph),
&_iph);
if (!iph)
return -1;
if (iph->ihl < 5 || iph->version != 4)
return -1;
len = ntohs(iph->tot_len);
thoff = iph->ihl * 4;
if (skb->len < len)
return -1;
else if (len < thoff)
return -1;
pkt->tprot_set = true;
pkt->tprot = iph->protocol;
pkt->xt.thoff = thoff;
pkt->xt.fragoff = ntohs(iph->frag_off) & IP_OFFSET;
return 0;
}
static inline void nft_set_pktinfo_ipv4_validate(struct nft_pktinfo *pkt,
struct sk_buff *skb)
{
if (__nft_set_pktinfo_ipv4_validate(pkt, skb) < 0)
nft_set_pktinfo_unspec(pkt, skb);
}
#endif
+72
View File
@@ -0,0 +1,72 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NF_TABLES_IPV6_H_
#define _NF_TABLES_IPV6_H_
#include <linux/netfilter_ipv6/ip6_tables.h>
#include <net/ipv6.h>
static inline void nft_set_pktinfo_ipv6(struct nft_pktinfo *pkt,
struct sk_buff *skb)
{
unsigned int flags = IP6_FH_F_AUTH;
int protohdr, thoff = 0;
unsigned short frag_off;
protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
if (protohdr < 0) {
nft_set_pktinfo_unspec(pkt, skb);
return;
}
pkt->tprot_set = true;
pkt->tprot = protohdr;
pkt->xt.thoff = thoff;
pkt->xt.fragoff = frag_off;
}
static inline int __nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
struct sk_buff *skb)
{
#if IS_ENABLED(CONFIG_IPV6)
unsigned int flags = IP6_FH_F_AUTH;
struct ipv6hdr *ip6h, _ip6h;
unsigned int thoff = 0;
unsigned short frag_off;
int protohdr;
u32 pkt_len;
ip6h = skb_header_pointer(skb, skb_network_offset(skb), sizeof(*ip6h),
&_ip6h);
if (!ip6h)
return -1;
if (ip6h->version != 6)
return -1;
pkt_len = ntohs(ip6h->payload_len);
if (pkt_len + sizeof(*ip6h) > skb->len)
return -1;
protohdr = ipv6_find_hdr(pkt->skb, &thoff, -1, &frag_off, &flags);
if (protohdr < 0)
return -1;
pkt->tprot_set = true;
pkt->tprot = protohdr;
pkt->xt.thoff = thoff;
pkt->xt.fragoff = frag_off;
return 0;
#else
return -1;
#endif
}
static inline void nft_set_pktinfo_ipv6_validate(struct nft_pktinfo *pkt,
struct sk_buff *skb)
{
if (__nft_set_pktinfo_ipv6_validate(pkt, skb) < 0)
nft_set_pktinfo_unspec(pkt, skb);
}
#endif
+121
View File
@@ -0,0 +1,121 @@
#ifndef _NF_TPROXY_H_
#define _NF_TPROXY_H_
#include <net/tcp.h>
enum nf_tproxy_lookup_t {
NF_TPROXY_LOOKUP_LISTENER,
NF_TPROXY_LOOKUP_ESTABLISHED,
};
static inline bool nf_tproxy_sk_is_transparent(struct sock *sk)
{
if (inet_sk_transparent(sk))
return true;
sock_gen_put(sk);
return false;
}
/* assign a socket to the skb -- consumes sk */
static inline void nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk)
{
skb_orphan(skb);
skb->sk = sk;
skb->destructor = sock_edemux;
}
__be32 nf_tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr);
/**
* nf_tproxy_handle_time_wait4 - handle IPv4 TCP TIME_WAIT reopen redirections
* @skb: The skb being processed.
* @laddr: IPv4 address to redirect to or zero.
* @lport: TCP port to redirect to or zero.
* @sk: The TIME_WAIT TCP socket found by the lookup.
*
* We have to handle SYN packets arriving to TIME_WAIT sockets
* differently: instead of reopening the connection we should rather
* redirect the new connection to the proxy if there's a listener
* socket present.
*
* nf_tproxy_handle_time_wait4() consumes the socket reference passed in.
*
* Returns the listener socket if there's one, the TIME_WAIT socket if
* no such listener is found, or NULL if the TCP header is incomplete.
*/
struct sock *
nf_tproxy_handle_time_wait4(struct net *net, struct sk_buff *skb,
__be32 laddr, __be16 lport, struct sock *sk);
/*
* This is used when the user wants to intercept a connection matching
* an explicit iptables rule. In this case the sockets are assumed
* matching in preference order:
*
* - match: if there's a fully established connection matching the
* _packet_ tuple, it is returned, assuming the redirection
* already took place and we process a packet belonging to an
* established connection
*
* - match: if there's a listening socket matching the redirection
* (e.g. on-port & on-ip of the connection), it is returned,
* regardless if it was bound to 0.0.0.0 or an explicit
* address. The reasoning is that if there's an explicit rule, it
* does not really matter if the listener is bound to an interface
* or to 0. The user already stated that he wants redirection
* (since he added the rule).
*
* Please note that there's an overlap between what a TPROXY target
* and a socket match will match. Normally if you have both rules the
* "socket" match will be the first one, effectively all packets
* belonging to established connections going through that one.
*/
struct sock *
nf_tproxy_get_sock_v4(struct net *net, struct sk_buff *skb,
const u8 protocol,
const __be32 saddr, const __be32 daddr,
const __be16 sport, const __be16 dport,
const struct net_device *in,
const enum nf_tproxy_lookup_t lookup_type);
const struct in6_addr *
nf_tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr,
const struct in6_addr *daddr);
/**
* nf_tproxy_handle_time_wait6 - handle IPv6 TCP TIME_WAIT reopen redirections
* @skb: The skb being processed.
* @tproto: Transport protocol.
* @thoff: Transport protocol header offset.
* @net: Network namespace.
* @laddr: IPv6 address to redirect to.
* @lport: TCP port to redirect to or zero.
* @sk: The TIME_WAIT TCP socket found by the lookup.
*
* We have to handle SYN packets arriving to TIME_WAIT sockets
* differently: instead of reopening the connection we should rather
* redirect the new connection to the proxy if there's a listener
* socket present.
*
* nf_tproxy_handle_time_wait6() consumes the socket reference passed in.
*
* Returns the listener socket if there's one, the TIME_WAIT socket if
* no such listener is found, or NULL if the TCP header is incomplete.
*/
struct sock *
nf_tproxy_handle_time_wait6(struct sk_buff *skb, int tproto, int thoff,
struct net *net,
const struct in6_addr *laddr,
const __be16 lport,
struct sock *sk);
struct sock *
nf_tproxy_get_sock_v6(struct net *net, struct sk_buff *skb, int thoff,
const u8 protocol,
const struct in6_addr *saddr, const struct in6_addr *daddr,
const __be16 sport, const __be16 dport,
const struct net_device *in,
const enum nf_tproxy_lookup_t lookup_type);
#endif /* _NF_TPROXY_H_ */
+1
View File
@@ -0,0 +1 @@
/* SPDX-License-Identifier: GPL-2.0 */
+38
View File
@@ -0,0 +1,38 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NFT_FIB_H_
#define _NFT_FIB_H_
struct nft_fib {
enum nft_registers dreg:8;
u8 result;
u32 flags;
};
extern const struct nla_policy nft_fib_policy[];
static inline bool
nft_fib_is_loopback(const struct sk_buff *skb, const struct net_device *in)
{
return skb->pkt_type == PACKET_LOOPBACK || in->flags & IFF_LOOPBACK;
}
int nft_fib_dump(struct sk_buff *skb, const struct nft_expr *expr);
int nft_fib_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
const struct nlattr * const tb[]);
int nft_fib_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
const struct nft_data **data);
void nft_fib4_eval_type(const struct nft_expr *expr, struct nft_regs *regs,
const struct nft_pktinfo *pkt);
void nft_fib4_eval(const struct nft_expr *expr, struct nft_regs *regs,
const struct nft_pktinfo *pkt);
void nft_fib6_eval_type(const struct nft_expr *expr, struct nft_regs *regs,
const struct nft_pktinfo *pkt);
void nft_fib6_eval(const struct nft_expr *expr, struct nft_regs *regs,
const struct nft_pktinfo *pkt);
void nft_fib_store_result(void *reg, const struct nft_fib *priv,
const struct nft_pktinfo *pkt, int index);
#endif
+22
View File
@@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NFT_MASQ_H_
#define _NFT_MASQ_H_
struct nft_masq {
u32 flags;
enum nft_registers sreg_proto_min:8;
enum nft_registers sreg_proto_max:8;
};
extern const struct nla_policy nft_masq_policy[];
int nft_masq_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[]);
int nft_masq_dump(struct sk_buff *skb, const struct nft_expr *expr);
int nft_masq_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
const struct nft_data **data);
#endif /* _NFT_MASQ_H_ */
+22
View File
@@ -0,0 +1,22 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NFT_REDIR_H_
#define _NFT_REDIR_H_
struct nft_redir {
enum nft_registers sreg_proto_min:8;
enum nft_registers sreg_proto_max:8;
u16 flags;
};
extern const struct nla_policy nft_redir_policy[];
int nft_redir_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[]);
int nft_redir_dump(struct sk_buff *skb, const struct nft_expr *expr);
int nft_redir_validate(const struct nft_ctx *ctx, const struct nft_expr *expr,
const struct nft_data **data);
#endif /* _NFT_REDIR_H_ */
+25
View File
@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _NFT_REJECT_H_
#define _NFT_REJECT_H_
struct nft_reject {
enum nft_reject_types type:8;
u8 icmp_code;
};
extern const struct nla_policy nft_reject_policy[];
int nft_reject_validate(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nft_data **data);
int nft_reject_init(const struct nft_ctx *ctx,
const struct nft_expr *expr,
const struct nlattr * const tb[]);
int nft_reject_dump(struct sk_buff *skb, const struct nft_expr *expr);
int nft_reject_icmp_code(u8 code);
int nft_reject_icmpv6_code(u8 code);
#endif
+27
View File
@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _XT_RATEEST_H
#define _XT_RATEEST_H
#include <net/gen_stats.h>
struct xt_rateest {
/* keep lock and bstats on same cache line to speedup xt_rateest_tg() */
struct gnet_stats_basic_packed bstats;
spinlock_t lock;
/* following fields not accessed in hot path */
unsigned int refcnt;
struct hlist_node list;
char name[IFNAMSIZ];
struct gnet_estimator params;
struct rcu_head rcu;
/* keep this field far away to speedup xt_rateest_mt() */
struct net_rate_estimator __rcu *rate_est;
};
struct xt_rateest *xt_rateest_lookup(struct net *net, const char *name);
void xt_rateest_put(struct net *net, struct xt_rateest *est);
#endif /* _XT_RATEEST_H */