Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
Pablo Neira Ayuso says: ==================== Netfilter updates for net-next The following batch contains Netfilter/IPVS updates for your net-next tree: 1) Simplify log infrastructure modularity: Merge ipv4, ipv6, bridge, netdev and ARP families to nf_log_syslog.c. Add module softdeps. This fixes a rare deadlock condition that might occur when log module autoload is required. From Florian Westphal. 2) Moves part of netfilter related pernet data from struct net to net_generic() infrastructure. All of these users can be modules, so if they are not loaded there is no need to waste space. Size reduction is 7 cachelines on x86_64, also from Florian. 2) Update nftables audit support to report events once per table, to get it aligned with iptables. From Richard Guy Briggs. 3) Check for stale routes from the flowtable garbage collector path. This is fixing IPv6 which breaks due missing check for the dst_cookie. 4) Add a nfnl_fill_hdr() function to simplify netlink + nfnetlink headers setup. 5) Remove documentation on several statified functions. 6) Remove printk on netns creation for the FTP IPVS tracker, from Florian Westphal. 7) Remove unnecessary nf_tables_destroy_list_lock spinlock initialization, from Yang Yingliang. 7) Remove a duplicated forward declaration in ipset, from Wan Jiabing. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
5106efe6ed
@ -124,8 +124,6 @@ struct ip_set_ext {
|
||||
bool target;
|
||||
};
|
||||
|
||||
struct ip_set;
|
||||
|
||||
#define ext_timeout(e, s) \
|
||||
((unsigned long *)(((void *)(e)) + (s)->offset[IPSET_EXT_ID_TIMEOUT]))
|
||||
#define ext_counter(e, s) \
|
||||
|
@ -51,12 +51,41 @@ int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 portid,
|
||||
unsigned int group, int echo, gfp_t flags);
|
||||
int nfnetlink_set_err(struct net *net, u32 portid, u32 group, int error);
|
||||
int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u32 portid);
|
||||
void nfnetlink_broadcast(struct net *net, struct sk_buff *skb, __u32 portid,
|
||||
__u32 group, gfp_t allocation);
|
||||
|
||||
static inline u16 nfnl_msg_type(u8 subsys, u8 msg_type)
|
||||
{
|
||||
return subsys << 8 | msg_type;
|
||||
}
|
||||
|
||||
static inline void nfnl_fill_hdr(struct nlmsghdr *nlh, u8 family, u8 version,
|
||||
__be16 res_id)
|
||||
{
|
||||
struct nfgenmsg *nfmsg;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = family;
|
||||
nfmsg->version = version;
|
||||
nfmsg->res_id = res_id;
|
||||
}
|
||||
|
||||
static inline struct nlmsghdr *nfnl_msg_put(struct sk_buff *skb, u32 portid,
|
||||
u32 seq, int type, int flags,
|
||||
u8 family, u8 version,
|
||||
__be16 res_id)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
|
||||
nlh = nlmsg_put(skb, portid, seq, type, sizeof(struct nfgenmsg), flags);
|
||||
if (!nlh)
|
||||
return NULL;
|
||||
|
||||
nfnl_fill_hdr(nlh, family, version, res_id);
|
||||
|
||||
return nlh;
|
||||
}
|
||||
|
||||
void nfnl_lock(__u8 subsys_id);
|
||||
void nfnl_unlock(__u8 subsys_id);
|
||||
#ifdef CONFIG_PROVE_LOCKING
|
||||
|
@ -142,15 +142,6 @@ struct net {
|
||||
#if defined(CONFIG_NF_TABLES) || defined(CONFIG_NF_TABLES_MODULE)
|
||||
struct netns_nftables nft;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
|
||||
struct netns_nf_frag nf_frag;
|
||||
struct ctl_table_header *nf_frag_frags_hdr;
|
||||
#endif
|
||||
struct sock *nfnl;
|
||||
struct sock *nfnl_stash;
|
||||
#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
|
||||
struct list_head nfct_timeout_list;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_WEXT_CORE
|
||||
struct sk_buff_head wext_nlevents;
|
||||
|
@ -13,4 +13,10 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user);
|
||||
|
||||
struct inet_frags_ctl;
|
||||
|
||||
struct nft_ct_frag6_pernet {
|
||||
struct ctl_table_header *nf_frag_frags_hdr;
|
||||
struct fqdir *fqdir;
|
||||
unsigned int users;
|
||||
};
|
||||
|
||||
#endif /* _NF_DEFRAG_IPV6_H */
|
||||
|
@ -47,6 +47,13 @@ struct nf_conntrack_net {
|
||||
unsigned int users4;
|
||||
unsigned int users6;
|
||||
unsigned int users_bridge;
|
||||
#ifdef CONFIG_SYSCTL
|
||||
struct ctl_table_header *sysctl_header;
|
||||
#endif
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
struct delayed_work ecache_dwork;
|
||||
struct netns_ct *ct_net;
|
||||
#endif
|
||||
};
|
||||
|
||||
#include <linux/types.h>
|
||||
|
@ -171,12 +171,18 @@ void nf_ct_expect_event_report(enum ip_conntrack_expect_events event,
|
||||
struct nf_conntrack_expect *exp,
|
||||
u32 portid, int report);
|
||||
|
||||
void nf_conntrack_ecache_work(struct net *net, enum nf_ct_ecache_state state);
|
||||
|
||||
void 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 bool nf_conntrack_ecache_dwork_pending(const struct net *net)
|
||||
{
|
||||
return net->ct.ecache_dwork_pending;
|
||||
}
|
||||
#else /* CONFIG_NF_CONNTRACK_EVENTS */
|
||||
|
||||
static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
|
||||
@ -186,6 +192,11 @@ static inline void nf_ct_expect_event_report(enum ip_conntrack_expect_events e,
|
||||
{
|
||||
}
|
||||
|
||||
static inline void nf_conntrack_ecache_work(struct net *net,
|
||||
enum nf_ct_ecache_state s)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void nf_conntrack_ecache_pernet_init(struct net *net)
|
||||
{
|
||||
}
|
||||
@ -203,26 +214,6 @@ static inline void nf_conntrack_ecache_fini(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline bool nf_conntrack_ecache_dwork_pending(const struct net *net) { return false; }
|
||||
#endif /* CONFIG_NF_CONNTRACK_EVENTS */
|
||||
|
||||
static inline void nf_conntrack_ecache_delayed_work(struct net *net)
|
||||
{
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
if (!delayed_work_pending(&net->ct.ecache_dwork)) {
|
||||
schedule_delayed_work(&net->ct.ecache_dwork, HZ);
|
||||
net->ct.ecache_dwork_pending = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void nf_conntrack_ecache_work(struct net *net)
|
||||
{
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
if (net->ct.ecache_dwork_pending) {
|
||||
net->ct.ecache_dwork_pending = false;
|
||||
mod_delayed_work(system_wq, &net->ct.ecache_dwork, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /*_NF_CONNTRACK_ECACHE_H*/
|
||||
|
@ -129,7 +129,10 @@ struct flow_offload_tuple {
|
||||
in_vlan_ingress:2;
|
||||
u16 mtu;
|
||||
union {
|
||||
struct {
|
||||
struct dst_entry *dst_cache;
|
||||
u32 dst_cookie;
|
||||
};
|
||||
struct {
|
||||
u32 ifidx;
|
||||
u32 hw_ifidx;
|
||||
|
@ -68,7 +68,6 @@ 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))
|
||||
@ -99,28 +98,4 @@ 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 */
|
||||
|
@ -1562,4 +1562,20 @@ void nf_tables_trans_destroy_flush_work(void);
|
||||
int nf_msecs_to_jiffies64(const struct nlattr *nla, u64 *result);
|
||||
__be64 nf_jiffies64_to_msecs(u64 input);
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
__printf(2, 3) int nft_request_module(struct net *net, const char *fmt, ...);
|
||||
#else
|
||||
static inline int nft_request_module(struct net *net, const char *fmt, ...) { return -ENOENT; }
|
||||
#endif
|
||||
|
||||
struct nftables_pernet {
|
||||
struct list_head tables;
|
||||
struct list_head commit_list;
|
||||
struct list_head module_list;
|
||||
struct list_head notify_list;
|
||||
struct mutex commit_mutex;
|
||||
unsigned int base_seq;
|
||||
u8 validate_state;
|
||||
};
|
||||
|
||||
#endif /* _NET_NF_TABLES_H */
|
||||
|
@ -96,13 +96,9 @@ struct netns_ct {
|
||||
atomic_t count;
|
||||
unsigned int expect_count;
|
||||
#ifdef CONFIG_NF_CONNTRACK_EVENTS
|
||||
struct delayed_work ecache_dwork;
|
||||
bool ecache_dwork_pending;
|
||||
#endif
|
||||
bool auto_assign_helper_warned;
|
||||
#ifdef CONFIG_SYSCTL
|
||||
struct ctl_table_header *sysctl_header;
|
||||
#endif
|
||||
unsigned int sysctl_log_invalid; /* Log invalid packets */
|
||||
int sysctl_events;
|
||||
int sysctl_acct;
|
||||
|
@ -28,11 +28,5 @@ struct netns_nf {
|
||||
#if IS_ENABLED(CONFIG_DECNET)
|
||||
struct nf_hook_entries __rcu *hooks_decnet[NF_DN_NUMHOOKS];
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV4)
|
||||
bool defrag_ipv4;
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6)
|
||||
bool defrag_ipv6;
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
|
@ -5,14 +5,7 @@
|
||||
#include <linux/list.h>
|
||||
|
||||
struct netns_nftables {
|
||||
struct list_head tables;
|
||||
struct list_head commit_list;
|
||||
struct list_head module_list;
|
||||
struct list_head notify_list;
|
||||
struct mutex commit_mutex;
|
||||
unsigned int base_seq;
|
||||
u8 gencursor;
|
||||
u8 validate_state;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -8,7 +8,6 @@
|
||||
struct ebt_table;
|
||||
|
||||
struct netns_xt {
|
||||
struct list_head tables[NFPROTO_NUMPROTO];
|
||||
bool notrack_deprecated_warning;
|
||||
bool clusterip_deprecated_warning;
|
||||
#if defined(CONFIG_BRIDGE_NF_EBTABLES) || \
|
||||
|
@ -23,10 +23,6 @@ config NFT_BRIDGE_REJECT
|
||||
help
|
||||
Add support to reject packets.
|
||||
|
||||
config NF_LOG_BRIDGE
|
||||
tristate "Bridge packet logging"
|
||||
select NF_LOG_COMMON
|
||||
|
||||
endif # NF_TABLES_BRIDGE
|
||||
|
||||
config NF_CONNTRACK_BRIDGE
|
||||
|
@ -9,9 +9,6 @@ obj-$(CONFIG_NFT_BRIDGE_REJECT) += nft_reject_bridge.o
|
||||
# connection tracking
|
||||
obj-$(CONFIG_NF_CONNTRACK_BRIDGE) += nf_conntrack_bridge.o
|
||||
|
||||
# packet logging
|
||||
obj-$(CONFIG_NF_LOG_BRIDGE) += nf_log_bridge.o
|
||||
|
||||
obj-$(CONFIG_BRIDGE_NF_EBTABLES) += ebtables.o
|
||||
|
||||
# tables
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/audit.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/netns/generic.h>
|
||||
/* needed for logical [in,out]-dev filtering */
|
||||
#include "../br_private.h"
|
||||
|
||||
@ -39,8 +40,11 @@
|
||||
#define COUNTER_BASE(c, n, cpu) ((struct ebt_counter *)(((char *)c) + \
|
||||
COUNTER_OFFSET(n) * cpu))
|
||||
|
||||
struct ebt_pernet {
|
||||
struct list_head tables;
|
||||
};
|
||||
|
||||
|
||||
static unsigned int ebt_pernet_id __read_mostly;
|
||||
static DEFINE_MUTEX(ebt_mutex);
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
@ -336,7 +340,9 @@ static inline struct ebt_table *
|
||||
find_table_lock(struct net *net, const char *name, int *error,
|
||||
struct mutex *mutex)
|
||||
{
|
||||
return find_inlist_lock(&net->xt.tables[NFPROTO_BRIDGE], name,
|
||||
struct ebt_pernet *ebt_net = net_generic(net, ebt_pernet_id);
|
||||
|
||||
return find_inlist_lock(&ebt_net->tables, name,
|
||||
"ebtable_", error, mutex);
|
||||
}
|
||||
|
||||
@ -1136,6 +1142,7 @@ static void __ebt_unregister_table(struct net *net, struct ebt_table *table)
|
||||
int ebt_register_table(struct net *net, const struct ebt_table *input_table,
|
||||
const struct nf_hook_ops *ops, struct ebt_table **res)
|
||||
{
|
||||
struct ebt_pernet *ebt_net = net_generic(net, ebt_pernet_id);
|
||||
struct ebt_table_info *newinfo;
|
||||
struct ebt_table *t, *table;
|
||||
struct ebt_replace_kernel *repl;
|
||||
@ -1194,7 +1201,7 @@ int ebt_register_table(struct net *net, const struct ebt_table *input_table,
|
||||
table->private = newinfo;
|
||||
rwlock_init(&table->lock);
|
||||
mutex_lock(&ebt_mutex);
|
||||
list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) {
|
||||
list_for_each_entry(t, &ebt_net->tables, list) {
|
||||
if (strcmp(t->name, table->name) == 0) {
|
||||
ret = -EEXIST;
|
||||
goto free_unlock;
|
||||
@ -1206,7 +1213,7 @@ int ebt_register_table(struct net *net, const struct ebt_table *input_table,
|
||||
ret = -ENOENT;
|
||||
goto free_unlock;
|
||||
}
|
||||
list_add(&table->list, &net->xt.tables[NFPROTO_BRIDGE]);
|
||||
list_add(&table->list, &ebt_net->tables);
|
||||
mutex_unlock(&ebt_mutex);
|
||||
|
||||
WRITE_ONCE(*res, table);
|
||||
@ -2412,6 +2419,20 @@ static struct nf_sockopt_ops ebt_sockopts = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __net_init ebt_pernet_init(struct net *net)
|
||||
{
|
||||
struct ebt_pernet *ebt_net = net_generic(net, ebt_pernet_id);
|
||||
|
||||
INIT_LIST_HEAD(&ebt_net->tables);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct pernet_operations ebt_net_ops = {
|
||||
.init = ebt_pernet_init,
|
||||
.id = &ebt_pernet_id,
|
||||
.size = sizeof(struct ebt_pernet),
|
||||
};
|
||||
|
||||
static int __init ebtables_init(void)
|
||||
{
|
||||
int ret;
|
||||
@ -2425,13 +2446,21 @@ static int __init ebtables_init(void)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = register_pernet_subsys(&ebt_net_ops);
|
||||
if (ret < 0) {
|
||||
nf_unregister_sockopt(&ebt_sockopts);
|
||||
xt_unregister_target(&ebt_standard_target);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit ebtables_fini(void)
|
||||
static void ebtables_fini(void)
|
||||
{
|
||||
nf_unregister_sockopt(&ebt_sockopts);
|
||||
xt_unregister_target(&ebt_standard_target);
|
||||
unregister_pernet_subsys(&ebt_net_ops);
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ebt_register_table);
|
||||
|
@ -1,79 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* (C) 2014 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/if_bridge.h>
|
||||
#include <linux/ip.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include <net/netfilter/nf_log.h>
|
||||
|
||||
static void nf_log_bridge_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 *loginfo,
|
||||
const char *prefix)
|
||||
{
|
||||
nf_log_l2packet(net, pf, eth_hdr(skb)->h_proto, hooknum, skb,
|
||||
in, out, loginfo, prefix);
|
||||
}
|
||||
|
||||
static struct nf_logger nf_bridge_logger __read_mostly = {
|
||||
.name = "nf_log_bridge",
|
||||
.type = NF_LOG_TYPE_LOG,
|
||||
.logfn = nf_log_bridge_packet,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __net_init nf_log_bridge_net_init(struct net *net)
|
||||
{
|
||||
return nf_log_set(net, NFPROTO_BRIDGE, &nf_bridge_logger);
|
||||
}
|
||||
|
||||
static void __net_exit nf_log_bridge_net_exit(struct net *net)
|
||||
{
|
||||
nf_log_unset(net, &nf_bridge_logger);
|
||||
}
|
||||
|
||||
static struct pernet_operations nf_log_bridge_net_ops = {
|
||||
.init = nf_log_bridge_net_init,
|
||||
.exit = nf_log_bridge_net_exit,
|
||||
};
|
||||
|
||||
static int __init nf_log_bridge_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Request to load the real packet loggers. */
|
||||
nf_logger_request_module(NFPROTO_IPV4, NF_LOG_TYPE_LOG);
|
||||
nf_logger_request_module(NFPROTO_IPV6, NF_LOG_TYPE_LOG);
|
||||
nf_logger_request_module(NFPROTO_ARP, NF_LOG_TYPE_LOG);
|
||||
|
||||
ret = register_pernet_subsys(&nf_log_bridge_net_ops);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
nf_log_register(NFPROTO_BRIDGE, &nf_bridge_logger);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit nf_log_bridge_exit(void)
|
||||
{
|
||||
unregister_pernet_subsys(&nf_log_bridge_net_ops);
|
||||
nf_log_unregister(&nf_bridge_logger);
|
||||
}
|
||||
|
||||
module_init(nf_log_bridge_init);
|
||||
module_exit(nf_log_bridge_exit);
|
||||
|
||||
MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
|
||||
MODULE_DESCRIPTION("Netfilter bridge packet logging");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_NF_LOGGER(AF_BRIDGE, 0);
|
@ -76,12 +76,18 @@ config NF_DUP_IPV4
|
||||
config NF_LOG_ARP
|
||||
tristate "ARP packet logging"
|
||||
default m if NETFILTER_ADVANCED=n
|
||||
select NF_LOG_COMMON
|
||||
select NF_LOG_SYSLOG
|
||||
help
|
||||
This is a backwards-compat option for the user's convenience
|
||||
(e.g. when running oldconfig). It selects CONFIG_NF_LOG_SYSLOG.
|
||||
|
||||
config NF_LOG_IPV4
|
||||
tristate "IPv4 packet logging"
|
||||
default m if NETFILTER_ADVANCED=n
|
||||
select NF_LOG_COMMON
|
||||
select NF_LOG_SYSLOG
|
||||
help
|
||||
This is a backwards-compat option for the user's convenience
|
||||
(e.g. when running oldconfig). It selects CONFIG_NF_LOG_SYSLOG.
|
||||
|
||||
config NF_REJECT_IPV4
|
||||
tristate "IPv4 packet rejection"
|
||||
|
@ -9,10 +9,6 @@ obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o
|
||||
obj-$(CONFIG_NF_SOCKET_IPV4) += nf_socket_ipv4.o
|
||||
obj-$(CONFIG_NF_TPROXY_IPV4) += nf_tproxy_ipv4.o
|
||||
|
||||
# logging
|
||||
obj-$(CONFIG_NF_LOG_ARP) += nf_log_arp.o
|
||||
obj-$(CONFIG_NF_LOG_IPV4) += nf_log_ipv4.o
|
||||
|
||||
# reject
|
||||
obj-$(CONFIG_NF_REJECT_IPV4) += nf_reject_ipv4.o
|
||||
|
||||
|
@ -20,8 +20,13 @@
|
||||
#endif
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
|
||||
static unsigned int defrag4_pernet_id __read_mostly;
|
||||
static DEFINE_MUTEX(defrag4_mutex);
|
||||
|
||||
struct defrag4_pernet {
|
||||
unsigned int users;
|
||||
};
|
||||
|
||||
static int nf_ct_ipv4_gather_frags(struct net *net, struct sk_buff *skb,
|
||||
u_int32_t user)
|
||||
{
|
||||
@ -106,15 +111,19 @@ static const struct nf_hook_ops ipv4_defrag_ops[] = {
|
||||
|
||||
static void __net_exit defrag4_net_exit(struct net *net)
|
||||
{
|
||||
if (net->nf.defrag_ipv4) {
|
||||
struct defrag4_pernet *nf_defrag = net_generic(net, defrag4_pernet_id);
|
||||
|
||||
if (nf_defrag->users) {
|
||||
nf_unregister_net_hooks(net, ipv4_defrag_ops,
|
||||
ARRAY_SIZE(ipv4_defrag_ops));
|
||||
net->nf.defrag_ipv4 = false;
|
||||
nf_defrag->users = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static struct pernet_operations defrag4_net_ops = {
|
||||
.exit = defrag4_net_exit,
|
||||
.id = &defrag4_pernet_id,
|
||||
.size = sizeof(struct defrag4_pernet),
|
||||
};
|
||||
|
||||
static int __init nf_defrag_init(void)
|
||||
@ -129,21 +138,22 @@ static void __exit nf_defrag_fini(void)
|
||||
|
||||
int nf_defrag_ipv4_enable(struct net *net)
|
||||
{
|
||||
struct defrag4_pernet *nf_defrag = net_generic(net, defrag4_pernet_id);
|
||||
int err = 0;
|
||||
|
||||
might_sleep();
|
||||
|
||||
if (net->nf.defrag_ipv4)
|
||||
if (nf_defrag->users)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&defrag4_mutex);
|
||||
if (net->nf.defrag_ipv4)
|
||||
if (nf_defrag->users)
|
||||
goto out_unlock;
|
||||
|
||||
err = nf_register_net_hooks(net, ipv4_defrag_ops,
|
||||
ARRAY_SIZE(ipv4_defrag_ops));
|
||||
if (err == 0)
|
||||
net->nf.defrag_ipv4 = true;
|
||||
nf_defrag->users = 1;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&defrag4_mutex);
|
||||
|
@ -1,172 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* (C) 2014 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
*
|
||||
* Based on code from ebt_log from:
|
||||
*
|
||||
* Bart De Schuymer <bdschuym@pandora.be>
|
||||
* Harald Welte <laforge@netfilter.org>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/ip.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/xt_LOG.h>
|
||||
#include <net/netfilter/nf_log.h>
|
||||
|
||||
static const struct nf_loginfo default_loginfo = {
|
||||
.type = NF_LOG_TYPE_LOG,
|
||||
.u = {
|
||||
.log = {
|
||||
.level = LOGLEVEL_NOTICE,
|
||||
.logflags = NF_LOG_DEFAULT_MASK,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
struct arppayload {
|
||||
unsigned char mac_src[ETH_ALEN];
|
||||
unsigned char ip_src[4];
|
||||
unsigned char mac_dst[ETH_ALEN];
|
||||
unsigned char ip_dst[4];
|
||||
};
|
||||
|
||||
static void dump_arp_packet(struct nf_log_buf *m,
|
||||
const struct nf_loginfo *info,
|
||||
const struct sk_buff *skb, unsigned int nhoff)
|
||||
{
|
||||
const struct arppayload *ap;
|
||||
struct arppayload _arpp;
|
||||
const struct arphdr *ah;
|
||||
unsigned int logflags;
|
||||
struct arphdr _arph;
|
||||
|
||||
ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph);
|
||||
if (ah == NULL) {
|
||||
nf_log_buf_add(m, "TRUNCATED");
|
||||
return;
|
||||
}
|
||||
|
||||
if (info->type == NF_LOG_TYPE_LOG)
|
||||
logflags = info->u.log.logflags;
|
||||
else
|
||||
logflags = NF_LOG_DEFAULT_MASK;
|
||||
|
||||
if (logflags & NF_LOG_MACDECODE) {
|
||||
nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ",
|
||||
eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest);
|
||||
nf_log_dump_vlan(m, skb);
|
||||
nf_log_buf_add(m, "MACPROTO=%04x ",
|
||||
ntohs(eth_hdr(skb)->h_proto));
|
||||
}
|
||||
|
||||
nf_log_buf_add(m, "ARP HTYPE=%d PTYPE=0x%04x OPCODE=%d",
|
||||
ntohs(ah->ar_hrd), ntohs(ah->ar_pro), ntohs(ah->ar_op));
|
||||
|
||||
/* If it's for Ethernet and the lengths are OK, then log the ARP
|
||||
* payload.
|
||||
*/
|
||||
if (ah->ar_hrd != htons(ARPHRD_ETHER) ||
|
||||
ah->ar_hln != ETH_ALEN ||
|
||||
ah->ar_pln != sizeof(__be32))
|
||||
return;
|
||||
|
||||
ap = skb_header_pointer(skb, sizeof(_arph), sizeof(_arpp), &_arpp);
|
||||
if (ap == NULL) {
|
||||
nf_log_buf_add(m, " INCOMPLETE [%zu bytes]",
|
||||
skb->len - sizeof(_arph));
|
||||
return;
|
||||
}
|
||||
nf_log_buf_add(m, " MACSRC=%pM IPSRC=%pI4 MACDST=%pM IPDST=%pI4",
|
||||
ap->mac_src, ap->ip_src, ap->mac_dst, ap->ip_dst);
|
||||
}
|
||||
|
||||
static void nf_log_arp_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 *loginfo,
|
||||
const char *prefix)
|
||||
{
|
||||
struct nf_log_buf *m;
|
||||
|
||||
/* FIXME: Disabled from containers until syslog ns is supported */
|
||||
if (!net_eq(net, &init_net) && !sysctl_nf_log_all_netns)
|
||||
return;
|
||||
|
||||
m = nf_log_buf_open();
|
||||
|
||||
if (!loginfo)
|
||||
loginfo = &default_loginfo;
|
||||
|
||||
nf_log_dump_packet_common(m, pf, hooknum, skb, in, out, loginfo,
|
||||
prefix);
|
||||
dump_arp_packet(m, loginfo, skb, 0);
|
||||
|
||||
nf_log_buf_close(m);
|
||||
}
|
||||
|
||||
static struct nf_logger nf_arp_logger __read_mostly = {
|
||||
.name = "nf_log_arp",
|
||||
.type = NF_LOG_TYPE_LOG,
|
||||
.logfn = nf_log_arp_packet,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __net_init nf_log_arp_net_init(struct net *net)
|
||||
{
|
||||
return nf_log_set(net, NFPROTO_ARP, &nf_arp_logger);
|
||||
}
|
||||
|
||||
static void __net_exit nf_log_arp_net_exit(struct net *net)
|
||||
{
|
||||
nf_log_unset(net, &nf_arp_logger);
|
||||
}
|
||||
|
||||
static struct pernet_operations nf_log_arp_net_ops = {
|
||||
.init = nf_log_arp_net_init,
|
||||
.exit = nf_log_arp_net_exit,
|
||||
};
|
||||
|
||||
static int __init nf_log_arp_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = register_pernet_subsys(&nf_log_arp_net_ops);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = nf_log_register(NFPROTO_ARP, &nf_arp_logger);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to register logger\n");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err1:
|
||||
unregister_pernet_subsys(&nf_log_arp_net_ops);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit nf_log_arp_exit(void)
|
||||
{
|
||||
unregister_pernet_subsys(&nf_log_arp_net_ops);
|
||||
nf_log_unregister(&nf_arp_logger);
|
||||
}
|
||||
|
||||
module_init(nf_log_arp_init);
|
||||
module_exit(nf_log_arp_exit);
|
||||
|
||||
MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
|
||||
MODULE_DESCRIPTION("Netfilter ARP packet logging");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_NF_LOGGER(3, 0);
|
@ -1,395 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* (C) 1999-2001 Paul `Rusty' Russell
|
||||
* (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/icmp.h>
|
||||
#include <net/udp.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter/xt_LOG.h>
|
||||
#include <net/netfilter/nf_log.h>
|
||||
|
||||
static const struct nf_loginfo default_loginfo = {
|
||||
.type = NF_LOG_TYPE_LOG,
|
||||
.u = {
|
||||
.log = {
|
||||
.level = LOGLEVEL_NOTICE,
|
||||
.logflags = NF_LOG_DEFAULT_MASK,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/* One level of recursion won't kill us */
|
||||
static void dump_ipv4_packet(struct net *net, struct nf_log_buf *m,
|
||||
const struct nf_loginfo *info,
|
||||
const struct sk_buff *skb, unsigned int iphoff)
|
||||
{
|
||||
struct iphdr _iph;
|
||||
const struct iphdr *ih;
|
||||
unsigned int logflags;
|
||||
|
||||
if (info->type == NF_LOG_TYPE_LOG)
|
||||
logflags = info->u.log.logflags;
|
||||
else
|
||||
logflags = NF_LOG_DEFAULT_MASK;
|
||||
|
||||
ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph);
|
||||
if (ih == NULL) {
|
||||
nf_log_buf_add(m, "TRUNCATED");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Important fields:
|
||||
* TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */
|
||||
/* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */
|
||||
nf_log_buf_add(m, "SRC=%pI4 DST=%pI4 ", &ih->saddr, &ih->daddr);
|
||||
|
||||
/* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */
|
||||
nf_log_buf_add(m, "LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ",
|
||||
ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK,
|
||||
ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id));
|
||||
|
||||
/* Max length: 6 "CE DF MF " */
|
||||
if (ntohs(ih->frag_off) & IP_CE)
|
||||
nf_log_buf_add(m, "CE ");
|
||||
if (ntohs(ih->frag_off) & IP_DF)
|
||||
nf_log_buf_add(m, "DF ");
|
||||
if (ntohs(ih->frag_off) & IP_MF)
|
||||
nf_log_buf_add(m, "MF ");
|
||||
|
||||
/* Max length: 11 "FRAG:65535 " */
|
||||
if (ntohs(ih->frag_off) & IP_OFFSET)
|
||||
nf_log_buf_add(m, "FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET);
|
||||
|
||||
if ((logflags & NF_LOG_IPOPT) &&
|
||||
ih->ihl * 4 > sizeof(struct iphdr)) {
|
||||
const unsigned char *op;
|
||||
unsigned char _opt[4 * 15 - sizeof(struct iphdr)];
|
||||
unsigned int i, optsize;
|
||||
|
||||
optsize = ih->ihl * 4 - sizeof(struct iphdr);
|
||||
op = skb_header_pointer(skb, iphoff+sizeof(_iph),
|
||||
optsize, _opt);
|
||||
if (op == NULL) {
|
||||
nf_log_buf_add(m, "TRUNCATED");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max length: 127 "OPT (" 15*4*2chars ") " */
|
||||
nf_log_buf_add(m, "OPT (");
|
||||
for (i = 0; i < optsize; i++)
|
||||
nf_log_buf_add(m, "%02X", op[i]);
|
||||
nf_log_buf_add(m, ") ");
|
||||
}
|
||||
|
||||
switch (ih->protocol) {
|
||||
case IPPROTO_TCP:
|
||||
if (nf_log_dump_tcp_header(m, skb, ih->protocol,
|
||||
ntohs(ih->frag_off) & IP_OFFSET,
|
||||
iphoff+ih->ihl*4, logflags))
|
||||
return;
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE:
|
||||
if (nf_log_dump_udp_header(m, skb, ih->protocol,
|
||||
ntohs(ih->frag_off) & IP_OFFSET,
|
||||
iphoff+ih->ihl*4))
|
||||
return;
|
||||
break;
|
||||
case IPPROTO_ICMP: {
|
||||
struct icmphdr _icmph;
|
||||
const struct icmphdr *ich;
|
||||
static const size_t required_len[NR_ICMP_TYPES+1]
|
||||
= { [ICMP_ECHOREPLY] = 4,
|
||||
[ICMP_DEST_UNREACH]
|
||||
= 8 + sizeof(struct iphdr),
|
||||
[ICMP_SOURCE_QUENCH]
|
||||
= 8 + sizeof(struct iphdr),
|
||||
[ICMP_REDIRECT]
|
||||
= 8 + sizeof(struct iphdr),
|
||||
[ICMP_ECHO] = 4,
|
||||
[ICMP_TIME_EXCEEDED]
|
||||
= 8 + sizeof(struct iphdr),
|
||||
[ICMP_PARAMETERPROB]
|
||||
= 8 + sizeof(struct iphdr),
|
||||
[ICMP_TIMESTAMP] = 20,
|
||||
[ICMP_TIMESTAMPREPLY] = 20,
|
||||
[ICMP_ADDRESS] = 12,
|
||||
[ICMP_ADDRESSREPLY] = 12 };
|
||||
|
||||
/* Max length: 11 "PROTO=ICMP " */
|
||||
nf_log_buf_add(m, "PROTO=ICMP ");
|
||||
|
||||
if (ntohs(ih->frag_off) & IP_OFFSET)
|
||||
break;
|
||||
|
||||
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
|
||||
ich = skb_header_pointer(skb, iphoff + ih->ihl * 4,
|
||||
sizeof(_icmph), &_icmph);
|
||||
if (ich == NULL) {
|
||||
nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
|
||||
skb->len - iphoff - ih->ihl*4);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Max length: 18 "TYPE=255 CODE=255 " */
|
||||
nf_log_buf_add(m, "TYPE=%u CODE=%u ", ich->type, ich->code);
|
||||
|
||||
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
|
||||
if (ich->type <= NR_ICMP_TYPES &&
|
||||
required_len[ich->type] &&
|
||||
skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) {
|
||||
nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
|
||||
skb->len - iphoff - ih->ihl*4);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ich->type) {
|
||||
case ICMP_ECHOREPLY:
|
||||
case ICMP_ECHO:
|
||||
/* Max length: 19 "ID=65535 SEQ=65535 " */
|
||||
nf_log_buf_add(m, "ID=%u SEQ=%u ",
|
||||
ntohs(ich->un.echo.id),
|
||||
ntohs(ich->un.echo.sequence));
|
||||
break;
|
||||
|
||||
case ICMP_PARAMETERPROB:
|
||||
/* Max length: 14 "PARAMETER=255 " */
|
||||
nf_log_buf_add(m, "PARAMETER=%u ",
|
||||
ntohl(ich->un.gateway) >> 24);
|
||||
break;
|
||||
case ICMP_REDIRECT:
|
||||
/* Max length: 24 "GATEWAY=255.255.255.255 " */
|
||||
nf_log_buf_add(m, "GATEWAY=%pI4 ", &ich->un.gateway);
|
||||
fallthrough;
|
||||
case ICMP_DEST_UNREACH:
|
||||
case ICMP_SOURCE_QUENCH:
|
||||
case ICMP_TIME_EXCEEDED:
|
||||
/* Max length: 3+maxlen */
|
||||
if (!iphoff) { /* Only recurse once. */
|
||||
nf_log_buf_add(m, "[");
|
||||
dump_ipv4_packet(net, m, info, skb,
|
||||
iphoff + ih->ihl*4+sizeof(_icmph));
|
||||
nf_log_buf_add(m, "] ");
|
||||
}
|
||||
|
||||
/* Max length: 10 "MTU=65535 " */
|
||||
if (ich->type == ICMP_DEST_UNREACH &&
|
||||
ich->code == ICMP_FRAG_NEEDED) {
|
||||
nf_log_buf_add(m, "MTU=%u ",
|
||||
ntohs(ich->un.frag.mtu));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Max Length */
|
||||
case IPPROTO_AH: {
|
||||
struct ip_auth_hdr _ahdr;
|
||||
const struct ip_auth_hdr *ah;
|
||||
|
||||
if (ntohs(ih->frag_off) & IP_OFFSET)
|
||||
break;
|
||||
|
||||
/* Max length: 9 "PROTO=AH " */
|
||||
nf_log_buf_add(m, "PROTO=AH ");
|
||||
|
||||
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
|
||||
ah = skb_header_pointer(skb, iphoff+ih->ihl*4,
|
||||
sizeof(_ahdr), &_ahdr);
|
||||
if (ah == NULL) {
|
||||
nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
|
||||
skb->len - iphoff - ih->ihl*4);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Length: 15 "SPI=0xF1234567 " */
|
||||
nf_log_buf_add(m, "SPI=0x%x ", ntohl(ah->spi));
|
||||
break;
|
||||
}
|
||||
case IPPROTO_ESP: {
|
||||
struct ip_esp_hdr _esph;
|
||||
const struct ip_esp_hdr *eh;
|
||||
|
||||
/* Max length: 10 "PROTO=ESP " */
|
||||
nf_log_buf_add(m, "PROTO=ESP ");
|
||||
|
||||
if (ntohs(ih->frag_off) & IP_OFFSET)
|
||||
break;
|
||||
|
||||
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
|
||||
eh = skb_header_pointer(skb, iphoff+ih->ihl*4,
|
||||
sizeof(_esph), &_esph);
|
||||
if (eh == NULL) {
|
||||
nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
|
||||
skb->len - iphoff - ih->ihl*4);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Length: 15 "SPI=0xF1234567 " */
|
||||
nf_log_buf_add(m, "SPI=0x%x ", ntohl(eh->spi));
|
||||
break;
|
||||
}
|
||||
/* Max length: 10 "PROTO 255 " */
|
||||
default:
|
||||
nf_log_buf_add(m, "PROTO=%u ", ih->protocol);
|
||||
}
|
||||
|
||||
/* Max length: 15 "UID=4294967295 " */
|
||||
if ((logflags & NF_LOG_UID) && !iphoff)
|
||||
nf_log_dump_sk_uid_gid(net, m, skb->sk);
|
||||
|
||||
/* Max length: 16 "MARK=0xFFFFFFFF " */
|
||||
if (!iphoff && skb->mark)
|
||||
nf_log_buf_add(m, "MARK=0x%x ", skb->mark);
|
||||
|
||||
/* Proto Max log string length */
|
||||
/* IP: 40+46+6+11+127 = 230 */
|
||||
/* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */
|
||||
/* UDP: 10+max(25,20) = 35 */
|
||||
/* UDPLITE: 14+max(25,20) = 39 */
|
||||
/* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */
|
||||
/* ESP: 10+max(25)+15 = 50 */
|
||||
/* AH: 9+max(25)+15 = 49 */
|
||||
/* unknown: 10 */
|
||||
|
||||
/* (ICMP allows recursion one level deep) */
|
||||
/* maxlen = IP + ICMP + IP + max(TCP,UDP,ICMP,unknown) */
|
||||
/* maxlen = 230+ 91 + 230 + 252 = 803 */
|
||||
}
|
||||
|
||||
static void dump_ipv4_mac_header(struct nf_log_buf *m,
|
||||
const struct nf_loginfo *info,
|
||||
const struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
unsigned int logflags = 0;
|
||||
|
||||
if (info->type == NF_LOG_TYPE_LOG)
|
||||
logflags = info->u.log.logflags;
|
||||
|
||||
if (!(logflags & NF_LOG_MACDECODE))
|
||||
goto fallback;
|
||||
|
||||
switch (dev->type) {
|
||||
case ARPHRD_ETHER:
|
||||
nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ",
|
||||
eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest);
|
||||
nf_log_dump_vlan(m, skb);
|
||||
nf_log_buf_add(m, "MACPROTO=%04x ",
|
||||
ntohs(eth_hdr(skb)->h_proto));
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fallback:
|
||||
nf_log_buf_add(m, "MAC=");
|
||||
if (dev->hard_header_len &&
|
||||
skb->mac_header != skb->network_header) {
|
||||
const unsigned char *p = skb_mac_header(skb);
|
||||
unsigned int i;
|
||||
|
||||
nf_log_buf_add(m, "%02x", *p++);
|
||||
for (i = 1; i < dev->hard_header_len; i++, p++)
|
||||
nf_log_buf_add(m, ":%02x", *p);
|
||||
}
|
||||
nf_log_buf_add(m, " ");
|
||||
}
|
||||
|
||||
static void nf_log_ip_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 *loginfo,
|
||||
const char *prefix)
|
||||
{
|
||||
struct nf_log_buf *m;
|
||||
|
||||
/* FIXME: Disabled from containers until syslog ns is supported */
|
||||
if (!net_eq(net, &init_net) && !sysctl_nf_log_all_netns)
|
||||
return;
|
||||
|
||||
m = nf_log_buf_open();
|
||||
|
||||
if (!loginfo)
|
||||
loginfo = &default_loginfo;
|
||||
|
||||
nf_log_dump_packet_common(m, pf, hooknum, skb, in,
|
||||
out, loginfo, prefix);
|
||||
|
||||
if (in != NULL)
|
||||
dump_ipv4_mac_header(m, loginfo, skb);
|
||||
|
||||
dump_ipv4_packet(net, m, loginfo, skb, 0);
|
||||
|
||||
nf_log_buf_close(m);
|
||||
}
|
||||
|
||||
static struct nf_logger nf_ip_logger __read_mostly = {
|
||||
.name = "nf_log_ipv4",
|
||||
.type = NF_LOG_TYPE_LOG,
|
||||
.logfn = nf_log_ip_packet,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __net_init nf_log_ipv4_net_init(struct net *net)
|
||||
{
|
||||
return nf_log_set(net, NFPROTO_IPV4, &nf_ip_logger);
|
||||
}
|
||||
|
||||
static void __net_exit nf_log_ipv4_net_exit(struct net *net)
|
||||
{
|
||||
nf_log_unset(net, &nf_ip_logger);
|
||||
}
|
||||
|
||||
static struct pernet_operations nf_log_ipv4_net_ops = {
|
||||
.init = nf_log_ipv4_net_init,
|
||||
.exit = nf_log_ipv4_net_exit,
|
||||
};
|
||||
|
||||
static int __init nf_log_ipv4_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = register_pernet_subsys(&nf_log_ipv4_net_ops);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = nf_log_register(NFPROTO_IPV4, &nf_ip_logger);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to register logger\n");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err1:
|
||||
unregister_pernet_subsys(&nf_log_ipv4_net_ops);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit nf_log_ipv4_exit(void)
|
||||
{
|
||||
unregister_pernet_subsys(&nf_log_ipv4_net_ops);
|
||||
nf_log_unregister(&nf_ip_logger);
|
||||
}
|
||||
|
||||
module_init(nf_log_ipv4_init);
|
||||
module_exit(nf_log_ipv4_exit);
|
||||
|
||||
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
|
||||
MODULE_DESCRIPTION("Netfilter IPv4 packet logging");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_NF_LOGGER(AF_INET, 0);
|
@ -69,7 +69,10 @@ config NF_REJECT_IPV6
|
||||
config NF_LOG_IPV6
|
||||
tristate "IPv6 packet logging"
|
||||
default m if NETFILTER_ADVANCED=n
|
||||
select NF_LOG_COMMON
|
||||
select NF_LOG_SYSLOG
|
||||
help
|
||||
This is a backwards-compat option for the user's convenience
|
||||
(e.g. when running oldconfig). It selects CONFIG_NF_LOG_SYSLOG.
|
||||
|
||||
config IP6_NF_IPTABLES
|
||||
tristate "IP6 tables support (required for filtering)"
|
||||
|
@ -18,9 +18,6 @@ obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o
|
||||
obj-$(CONFIG_NF_SOCKET_IPV6) += nf_socket_ipv6.o
|
||||
obj-$(CONFIG_NF_TPROXY_IPV6) += nf_tproxy_ipv6.o
|
||||
|
||||
# logging
|
||||
obj-$(CONFIG_NF_LOG_IPV6) += nf_log_ipv6.o
|
||||
|
||||
# reject
|
||||
obj-$(CONFIG_NF_REJECT_IPV6) += nf_reject_ipv6.o
|
||||
|
||||
|
@ -15,28 +15,13 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/socket.h>
|
||||
#include <linux/sockios.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/net.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/in6.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/icmpv6.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <net/sock.h>
|
||||
#include <net/snmp.h>
|
||||
#include <net/ipv6_frag.h>
|
||||
|
||||
#include <net/protocol.h>
|
||||
#include <net/transp_v6.h>
|
||||
#include <net/rawv6.h>
|
||||
#include <net/ndisc.h>
|
||||
#include <net/addrconf.h>
|
||||
#include <net/inet_ecn.h>
|
||||
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
|
||||
#include <linux/sysctl.h>
|
||||
#include <linux/netfilter.h>
|
||||
@ -44,11 +29,18 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
|
||||
#include <net/netns/generic.h>
|
||||
|
||||
static const char nf_frags_cache_name[] = "nf-frags";
|
||||
|
||||
unsigned int nf_frag_pernet_id __read_mostly;
|
||||
static struct inet_frags nf_frags;
|
||||
|
||||
static struct nft_ct_frag6_pernet *nf_frag_pernet(struct net *net)
|
||||
{
|
||||
return net_generic(net, nf_frag_pernet_id);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSCTL
|
||||
|
||||
static struct ctl_table nf_ct_frag6_sysctl_table[] = {
|
||||
@ -75,6 +67,7 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = {
|
||||
|
||||
static int nf_ct_frag6_sysctl_register(struct net *net)
|
||||
{
|
||||
struct nft_ct_frag6_pernet *nf_frag;
|
||||
struct ctl_table *table;
|
||||
struct ctl_table_header *hdr;
|
||||
|
||||
@ -86,18 +79,20 @@ static int nf_ct_frag6_sysctl_register(struct net *net)
|
||||
goto err_alloc;
|
||||
}
|
||||
|
||||
table[0].data = &net->nf_frag.fqdir->timeout;
|
||||
table[1].data = &net->nf_frag.fqdir->low_thresh;
|
||||
table[1].extra2 = &net->nf_frag.fqdir->high_thresh;
|
||||
table[2].data = &net->nf_frag.fqdir->high_thresh;
|
||||
table[2].extra1 = &net->nf_frag.fqdir->low_thresh;
|
||||
table[2].extra2 = &init_net.nf_frag.fqdir->high_thresh;
|
||||
nf_frag = nf_frag_pernet(net);
|
||||
|
||||
table[0].data = &nf_frag->fqdir->timeout;
|
||||
table[1].data = &nf_frag->fqdir->low_thresh;
|
||||
table[1].extra2 = &nf_frag->fqdir->high_thresh;
|
||||
table[2].data = &nf_frag->fqdir->high_thresh;
|
||||
table[2].extra1 = &nf_frag->fqdir->low_thresh;
|
||||
table[2].extra2 = &nf_frag->fqdir->high_thresh;
|
||||
|
||||
hdr = register_net_sysctl(net, "net/netfilter", table);
|
||||
if (hdr == NULL)
|
||||
goto err_reg;
|
||||
|
||||
net->nf_frag_frags_hdr = hdr;
|
||||
nf_frag->nf_frag_frags_hdr = hdr;
|
||||
return 0;
|
||||
|
||||
err_reg:
|
||||
@ -109,10 +104,11 @@ err_alloc:
|
||||
|
||||
static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net)
|
||||
{
|
||||
struct nft_ct_frag6_pernet *nf_frag = nf_frag_pernet(net);
|
||||
struct ctl_table *table;
|
||||
|
||||
table = net->nf_frag_frags_hdr->ctl_table_arg;
|
||||
unregister_net_sysctl_table(net->nf_frag_frags_hdr);
|
||||
table = nf_frag->nf_frag_frags_hdr->ctl_table_arg;
|
||||
unregister_net_sysctl_table(nf_frag->nf_frag_frags_hdr);
|
||||
if (!net_eq(net, &init_net))
|
||||
kfree(table);
|
||||
}
|
||||
@ -149,6 +145,7 @@ static void nf_ct_frag6_expire(struct timer_list *t)
|
||||
static struct frag_queue *fq_find(struct net *net, __be32 id, u32 user,
|
||||
const struct ipv6hdr *hdr, int iif)
|
||||
{
|
||||
struct nft_ct_frag6_pernet *nf_frag = nf_frag_pernet(net);
|
||||
struct frag_v6_compare_key key = {
|
||||
.id = id,
|
||||
.saddr = hdr->saddr,
|
||||
@ -158,7 +155,7 @@ static struct frag_queue *fq_find(struct net *net, __be32 id, u32 user,
|
||||
};
|
||||
struct inet_frag_queue *q;
|
||||
|
||||
q = inet_frag_find(net->nf_frag.fqdir, &key);
|
||||
q = inet_frag_find(nf_frag->fqdir, &key);
|
||||
if (!q)
|
||||
return NULL;
|
||||
|
||||
@ -495,37 +492,44 @@ EXPORT_SYMBOL_GPL(nf_ct_frag6_gather);
|
||||
|
||||
static int nf_ct_net_init(struct net *net)
|
||||
{
|
||||
struct nft_ct_frag6_pernet *nf_frag = nf_frag_pernet(net);
|
||||
int res;
|
||||
|
||||
res = fqdir_init(&net->nf_frag.fqdir, &nf_frags, net);
|
||||
res = fqdir_init(&nf_frag->fqdir, &nf_frags, net);
|
||||
if (res < 0)
|
||||
return res;
|
||||
|
||||
net->nf_frag.fqdir->high_thresh = IPV6_FRAG_HIGH_THRESH;
|
||||
net->nf_frag.fqdir->low_thresh = IPV6_FRAG_LOW_THRESH;
|
||||
net->nf_frag.fqdir->timeout = IPV6_FRAG_TIMEOUT;
|
||||
nf_frag->fqdir->high_thresh = IPV6_FRAG_HIGH_THRESH;
|
||||
nf_frag->fqdir->low_thresh = IPV6_FRAG_LOW_THRESH;
|
||||
nf_frag->fqdir->timeout = IPV6_FRAG_TIMEOUT;
|
||||
|
||||
res = nf_ct_frag6_sysctl_register(net);
|
||||
if (res < 0)
|
||||
fqdir_exit(net->nf_frag.fqdir);
|
||||
fqdir_exit(nf_frag->fqdir);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void nf_ct_net_pre_exit(struct net *net)
|
||||
{
|
||||
fqdir_pre_exit(net->nf_frag.fqdir);
|
||||
struct nft_ct_frag6_pernet *nf_frag = nf_frag_pernet(net);
|
||||
|
||||
fqdir_pre_exit(nf_frag->fqdir);
|
||||
}
|
||||
|
||||
static void nf_ct_net_exit(struct net *net)
|
||||
{
|
||||
struct nft_ct_frag6_pernet *nf_frag = nf_frag_pernet(net);
|
||||
|
||||
nf_ct_frags6_sysctl_unregister(net);
|
||||
fqdir_exit(net->nf_frag.fqdir);
|
||||
fqdir_exit(nf_frag->fqdir);
|
||||
}
|
||||
|
||||
static struct pernet_operations nf_ct_net_ops = {
|
||||
.init = nf_ct_net_init,
|
||||
.pre_exit = nf_ct_net_pre_exit,
|
||||
.exit = nf_ct_net_exit,
|
||||
.id = &nf_frag_pernet_id,
|
||||
.size = sizeof(struct nft_ct_frag6_pernet),
|
||||
};
|
||||
|
||||
static const struct rhashtable_params nfct_rhash_params = {
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
|
||||
|
||||
extern unsigned int nf_frag_pernet_id;
|
||||
|
||||
static DEFINE_MUTEX(defrag6_mutex);
|
||||
|
||||
static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
|
||||
@ -89,10 +91,12 @@ static const struct nf_hook_ops ipv6_defrag_ops[] = {
|
||||
|
||||
static void __net_exit defrag6_net_exit(struct net *net)
|
||||
{
|
||||
if (net->nf.defrag_ipv6) {
|
||||
struct nft_ct_frag6_pernet *nf_frag = net_generic(net, nf_frag_pernet_id);
|
||||
|
||||
if (nf_frag->users) {
|
||||
nf_unregister_net_hooks(net, ipv6_defrag_ops,
|
||||
ARRAY_SIZE(ipv6_defrag_ops));
|
||||
net->nf.defrag_ipv6 = false;
|
||||
nf_frag->users = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,21 +134,22 @@ static void __exit nf_defrag_fini(void)
|
||||
|
||||
int nf_defrag_ipv6_enable(struct net *net)
|
||||
{
|
||||
struct nft_ct_frag6_pernet *nf_frag = net_generic(net, nf_frag_pernet_id);
|
||||
int err = 0;
|
||||
|
||||
might_sleep();
|
||||
|
||||
if (net->nf.defrag_ipv6)
|
||||
if (nf_frag->users)
|
||||
return 0;
|
||||
|
||||
mutex_lock(&defrag6_mutex);
|
||||
if (net->nf.defrag_ipv6)
|
||||
if (nf_frag->users)
|
||||
goto out_unlock;
|
||||
|
||||
err = nf_register_net_hooks(net, ipv6_defrag_ops,
|
||||
ARRAY_SIZE(ipv6_defrag_ops));
|
||||
if (err == 0)
|
||||
net->nf.defrag_ipv6 = true;
|
||||
nf_frag->users = 1;
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&defrag6_mutex);
|
||||
|
@ -1,427 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* (C) 1999-2001 Paul `Rusty' Russell
|
||||
* (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/ip.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/icmp.h>
|
||||
#include <net/udp.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/netfilter/xt_LOG.h>
|
||||
#include <net/netfilter/nf_log.h>
|
||||
|
||||
static const struct nf_loginfo default_loginfo = {
|
||||
.type = NF_LOG_TYPE_LOG,
|
||||
.u = {
|
||||
.log = {
|
||||
.level = LOGLEVEL_NOTICE,
|
||||
.logflags = NF_LOG_DEFAULT_MASK,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/* One level of recursion won't kill us */
|
||||
static void dump_ipv6_packet(struct net *net, struct nf_log_buf *m,
|
||||
const struct nf_loginfo *info,
|
||||
const struct sk_buff *skb, unsigned int ip6hoff,
|
||||
int recurse)
|
||||
{
|
||||
u_int8_t currenthdr;
|
||||
int fragment;
|
||||
struct ipv6hdr _ip6h;
|
||||
const struct ipv6hdr *ih;
|
||||
unsigned int ptr;
|
||||
unsigned int hdrlen = 0;
|
||||
unsigned int logflags;
|
||||
|
||||
if (info->type == NF_LOG_TYPE_LOG)
|
||||
logflags = info->u.log.logflags;
|
||||
else
|
||||
logflags = NF_LOG_DEFAULT_MASK;
|
||||
|
||||
ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h);
|
||||
if (ih == NULL) {
|
||||
nf_log_buf_add(m, "TRUNCATED");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */
|
||||
nf_log_buf_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr);
|
||||
|
||||
/* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */
|
||||
nf_log_buf_add(m, "LEN=%zu TC=%u HOPLIMIT=%u FLOWLBL=%u ",
|
||||
ntohs(ih->payload_len) + sizeof(struct ipv6hdr),
|
||||
(ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20,
|
||||
ih->hop_limit,
|
||||
(ntohl(*(__be32 *)ih) & 0x000fffff));
|
||||
|
||||
fragment = 0;
|
||||
ptr = ip6hoff + sizeof(struct ipv6hdr);
|
||||
currenthdr = ih->nexthdr;
|
||||
while (currenthdr != NEXTHDR_NONE && nf_ip6_ext_hdr(currenthdr)) {
|
||||
struct ipv6_opt_hdr _hdr;
|
||||
const struct ipv6_opt_hdr *hp;
|
||||
|
||||
hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr);
|
||||
if (hp == NULL) {
|
||||
nf_log_buf_add(m, "TRUNCATED");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max length: 48 "OPT (...) " */
|
||||
if (logflags & NF_LOG_IPOPT)
|
||||
nf_log_buf_add(m, "OPT ( ");
|
||||
|
||||
switch (currenthdr) {
|
||||
case IPPROTO_FRAGMENT: {
|
||||
struct frag_hdr _fhdr;
|
||||
const struct frag_hdr *fh;
|
||||
|
||||
nf_log_buf_add(m, "FRAG:");
|
||||
fh = skb_header_pointer(skb, ptr, sizeof(_fhdr),
|
||||
&_fhdr);
|
||||
if (fh == NULL) {
|
||||
nf_log_buf_add(m, "TRUNCATED ");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max length: 6 "65535 " */
|
||||
nf_log_buf_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8);
|
||||
|
||||
/* Max length: 11 "INCOMPLETE " */
|
||||
if (fh->frag_off & htons(0x0001))
|
||||
nf_log_buf_add(m, "INCOMPLETE ");
|
||||
|
||||
nf_log_buf_add(m, "ID:%08x ",
|
||||
ntohl(fh->identification));
|
||||
|
||||
if (ntohs(fh->frag_off) & 0xFFF8)
|
||||
fragment = 1;
|
||||
|
||||
hdrlen = 8;
|
||||
|
||||
break;
|
||||
}
|
||||
case IPPROTO_DSTOPTS:
|
||||
case IPPROTO_ROUTING:
|
||||
case IPPROTO_HOPOPTS:
|
||||
if (fragment) {
|
||||
if (logflags & NF_LOG_IPOPT)
|
||||
nf_log_buf_add(m, ")");
|
||||
return;
|
||||
}
|
||||
hdrlen = ipv6_optlen(hp);
|
||||
break;
|
||||
/* Max Length */
|
||||
case IPPROTO_AH:
|
||||
if (logflags & NF_LOG_IPOPT) {
|
||||
struct ip_auth_hdr _ahdr;
|
||||
const struct ip_auth_hdr *ah;
|
||||
|
||||
/* Max length: 3 "AH " */
|
||||
nf_log_buf_add(m, "AH ");
|
||||
|
||||
if (fragment) {
|
||||
nf_log_buf_add(m, ")");
|
||||
return;
|
||||
}
|
||||
|
||||
ah = skb_header_pointer(skb, ptr, sizeof(_ahdr),
|
||||
&_ahdr);
|
||||
if (ah == NULL) {
|
||||
/*
|
||||
* Max length: 26 "INCOMPLETE [65535
|
||||
* bytes] )"
|
||||
*/
|
||||
nf_log_buf_add(m, "INCOMPLETE [%u bytes] )",
|
||||
skb->len - ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Length: 15 "SPI=0xF1234567 */
|
||||
nf_log_buf_add(m, "SPI=0x%x ", ntohl(ah->spi));
|
||||
|
||||
}
|
||||
|
||||
hdrlen = ipv6_authlen(hp);
|
||||
break;
|
||||
case IPPROTO_ESP:
|
||||
if (logflags & NF_LOG_IPOPT) {
|
||||
struct ip_esp_hdr _esph;
|
||||
const struct ip_esp_hdr *eh;
|
||||
|
||||
/* Max length: 4 "ESP " */
|
||||
nf_log_buf_add(m, "ESP ");
|
||||
|
||||
if (fragment) {
|
||||
nf_log_buf_add(m, ")");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Max length: 26 "INCOMPLETE [65535 bytes] )"
|
||||
*/
|
||||
eh = skb_header_pointer(skb, ptr, sizeof(_esph),
|
||||
&_esph);
|
||||
if (eh == NULL) {
|
||||
nf_log_buf_add(m, "INCOMPLETE [%u bytes] )",
|
||||
skb->len - ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Length: 16 "SPI=0xF1234567 )" */
|
||||
nf_log_buf_add(m, "SPI=0x%x )",
|
||||
ntohl(eh->spi));
|
||||
}
|
||||
return;
|
||||
default:
|
||||
/* Max length: 20 "Unknown Ext Hdr 255" */
|
||||
nf_log_buf_add(m, "Unknown Ext Hdr %u", currenthdr);
|
||||
return;
|
||||
}
|
||||
if (logflags & NF_LOG_IPOPT)
|
||||
nf_log_buf_add(m, ") ");
|
||||
|
||||
currenthdr = hp->nexthdr;
|
||||
ptr += hdrlen;
|
||||
}
|
||||
|
||||
switch (currenthdr) {
|
||||
case IPPROTO_TCP:
|
||||
if (nf_log_dump_tcp_header(m, skb, currenthdr, fragment,
|
||||
ptr, logflags))
|
||||
return;
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
case IPPROTO_UDPLITE:
|
||||
if (nf_log_dump_udp_header(m, skb, currenthdr, fragment, ptr))
|
||||
return;
|
||||
break;
|
||||
case IPPROTO_ICMPV6: {
|
||||
struct icmp6hdr _icmp6h;
|
||||
const struct icmp6hdr *ic;
|
||||
|
||||
/* Max length: 13 "PROTO=ICMPv6 " */
|
||||
nf_log_buf_add(m, "PROTO=ICMPv6 ");
|
||||
|
||||
if (fragment)
|
||||
break;
|
||||
|
||||
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
|
||||
ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h);
|
||||
if (ic == NULL) {
|
||||
nf_log_buf_add(m, "INCOMPLETE [%u bytes] ",
|
||||
skb->len - ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Max length: 18 "TYPE=255 CODE=255 " */
|
||||
nf_log_buf_add(m, "TYPE=%u CODE=%u ",
|
||||
ic->icmp6_type, ic->icmp6_code);
|
||||
|
||||
switch (ic->icmp6_type) {
|
||||
case ICMPV6_ECHO_REQUEST:
|
||||
case ICMPV6_ECHO_REPLY:
|
||||
/* Max length: 19 "ID=65535 SEQ=65535 " */
|
||||
nf_log_buf_add(m, "ID=%u SEQ=%u ",
|
||||
ntohs(ic->icmp6_identifier),
|
||||
ntohs(ic->icmp6_sequence));
|
||||
break;
|
||||
case ICMPV6_MGM_QUERY:
|
||||
case ICMPV6_MGM_REPORT:
|
||||
case ICMPV6_MGM_REDUCTION:
|
||||
break;
|
||||
|
||||
case ICMPV6_PARAMPROB:
|
||||
/* Max length: 17 "POINTER=ffffffff " */
|
||||
nf_log_buf_add(m, "POINTER=%08x ",
|
||||
ntohl(ic->icmp6_pointer));
|
||||
fallthrough;
|
||||
case ICMPV6_DEST_UNREACH:
|
||||
case ICMPV6_PKT_TOOBIG:
|
||||
case ICMPV6_TIME_EXCEED:
|
||||
/* Max length: 3+maxlen */
|
||||
if (recurse) {
|
||||
nf_log_buf_add(m, "[");
|
||||
dump_ipv6_packet(net, m, info, skb,
|
||||
ptr + sizeof(_icmp6h), 0);
|
||||
nf_log_buf_add(m, "] ");
|
||||
}
|
||||
|
||||
/* Max length: 10 "MTU=65535 " */
|
||||
if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) {
|
||||
nf_log_buf_add(m, "MTU=%u ",
|
||||
ntohl(ic->icmp6_mtu));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Max length: 10 "PROTO=255 " */
|
||||
default:
|
||||
nf_log_buf_add(m, "PROTO=%u ", currenthdr);
|
||||
}
|
||||
|
||||
/* Max length: 15 "UID=4294967295 " */
|
||||
if ((logflags & NF_LOG_UID) && recurse)
|
||||
nf_log_dump_sk_uid_gid(net, m, skb->sk);
|
||||
|
||||
/* Max length: 16 "MARK=0xFFFFFFFF " */
|
||||
if (recurse && skb->mark)
|
||||
nf_log_buf_add(m, "MARK=0x%x ", skb->mark);
|
||||
}
|
||||
|
||||
static void dump_ipv6_mac_header(struct nf_log_buf *m,
|
||||
const struct nf_loginfo *info,
|
||||
const struct sk_buff *skb)
|
||||
{
|
||||
struct net_device *dev = skb->dev;
|
||||
unsigned int logflags = 0;
|
||||
|
||||
if (info->type == NF_LOG_TYPE_LOG)
|
||||
logflags = info->u.log.logflags;
|
||||
|
||||
if (!(logflags & NF_LOG_MACDECODE))
|
||||
goto fallback;
|
||||
|
||||
switch (dev->type) {
|
||||
case ARPHRD_ETHER:
|
||||
nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ",
|
||||
eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest);
|
||||
nf_log_dump_vlan(m, skb);
|
||||
nf_log_buf_add(m, "MACPROTO=%04x ",
|
||||
ntohs(eth_hdr(skb)->h_proto));
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
fallback:
|
||||
nf_log_buf_add(m, "MAC=");
|
||||
if (dev->hard_header_len &&
|
||||
skb->mac_header != skb->network_header) {
|
||||
const unsigned char *p = skb_mac_header(skb);
|
||||
unsigned int len = dev->hard_header_len;
|
||||
unsigned int i;
|
||||
|
||||
if (dev->type == ARPHRD_SIT) {
|
||||
p -= ETH_HLEN;
|
||||
|
||||
if (p < skb->head)
|
||||
p = NULL;
|
||||
}
|
||||
|
||||
if (p != NULL) {
|
||||
nf_log_buf_add(m, "%02x", *p++);
|
||||
for (i = 1; i < len; i++)
|
||||
nf_log_buf_add(m, ":%02x", *p++);
|
||||
}
|
||||
nf_log_buf_add(m, " ");
|
||||
|
||||
if (dev->type == ARPHRD_SIT) {
|
||||
const struct iphdr *iph =
|
||||
(struct iphdr *)skb_mac_header(skb);
|
||||
nf_log_buf_add(m, "TUNNEL=%pI4->%pI4 ", &iph->saddr,
|
||||
&iph->daddr);
|
||||
}
|
||||
} else {
|
||||
nf_log_buf_add(m, " ");
|
||||
}
|
||||
}
|
||||
|
||||
static void nf_log_ip6_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 *loginfo,
|
||||
const char *prefix)
|
||||
{
|
||||
struct nf_log_buf *m;
|
||||
|
||||
/* FIXME: Disabled from containers until syslog ns is supported */
|
||||
if (!net_eq(net, &init_net) && !sysctl_nf_log_all_netns)
|
||||
return;
|
||||
|
||||
m = nf_log_buf_open();
|
||||
|
||||
if (!loginfo)
|
||||
loginfo = &default_loginfo;
|
||||
|
||||
nf_log_dump_packet_common(m, pf, hooknum, skb, in, out,
|
||||
loginfo, prefix);
|
||||
|
||||
if (in != NULL)
|
||||
dump_ipv6_mac_header(m, loginfo, skb);
|
||||
|
||||
dump_ipv6_packet(net, m, loginfo, skb, skb_network_offset(skb), 1);
|
||||
|
||||
nf_log_buf_close(m);
|
||||
}
|
||||
|
||||
static struct nf_logger nf_ip6_logger __read_mostly = {
|
||||
.name = "nf_log_ipv6",
|
||||
.type = NF_LOG_TYPE_LOG,
|
||||
.logfn = nf_log_ip6_packet,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __net_init nf_log_ipv6_net_init(struct net *net)
|
||||
{
|
||||
return nf_log_set(net, NFPROTO_IPV6, &nf_ip6_logger);
|
||||
}
|
||||
|
||||
static void __net_exit nf_log_ipv6_net_exit(struct net *net)
|
||||
{
|
||||
nf_log_unset(net, &nf_ip6_logger);
|
||||
}
|
||||
|
||||
static struct pernet_operations nf_log_ipv6_net_ops = {
|
||||
.init = nf_log_ipv6_net_init,
|
||||
.exit = nf_log_ipv6_net_exit,
|
||||
};
|
||||
|
||||
static int __init nf_log_ipv6_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = register_pernet_subsys(&nf_log_ipv6_net_ops);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = nf_log_register(NFPROTO_IPV6, &nf_ip6_logger);
|
||||
if (ret < 0) {
|
||||
pr_err("failed to register logger\n");
|
||||
goto err1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err1:
|
||||
unregister_pernet_subsys(&nf_log_ipv6_net_ops);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit nf_log_ipv6_exit(void)
|
||||
{
|
||||
unregister_pernet_subsys(&nf_log_ipv6_net_ops);
|
||||
nf_log_unregister(&nf_ip6_logger);
|
||||
}
|
||||
|
||||
module_init(nf_log_ipv6_init);
|
||||
module_exit(nf_log_ipv6_exit);
|
||||
|
||||
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
|
||||
MODULE_DESCRIPTION("Netfilter IPv6 packet logging");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_NF_LOGGER(AF_INET6, 0);
|
@ -71,12 +71,17 @@ config NF_CONNTRACK
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config NF_LOG_COMMON
|
||||
tristate
|
||||
|
||||
config NF_LOG_NETDEV
|
||||
tristate "Netdev packet logging"
|
||||
select NF_LOG_COMMON
|
||||
config NF_LOG_SYSLOG
|
||||
tristate "Syslog packet logging"
|
||||
default m if NETFILTER_ADVANCED=n
|
||||
help
|
||||
This option enable support for packet logging via syslog.
|
||||
It supports IPv4, IPV6, ARP and common transport protocols such
|
||||
as TCP and UDP.
|
||||
This is a simpler but less flexible logging method compared to
|
||||
CONFIG_NETFILTER_NETLINK_LOG.
|
||||
If both are enabled the backend to use can be configured at run-time
|
||||
by means of per-address-family sysctl tunables.
|
||||
|
||||
if NF_CONNTRACK
|
||||
config NETFILTER_CONNCOUNT
|
||||
@ -922,8 +927,7 @@ config NETFILTER_XT_TARGET_LED
|
||||
|
||||
config NETFILTER_XT_TARGET_LOG
|
||||
tristate "LOG target support"
|
||||
select NF_LOG_COMMON
|
||||
select NF_LOG_IPV4
|
||||
select NF_LOG_SYSLOG
|
||||
select NF_LOG_IPV6 if IP6_NF_IPTABLES
|
||||
default m if NETFILTER_ADVANCED=n
|
||||
help
|
||||
|
@ -48,11 +48,7 @@ obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o
|
||||
|
||||
nf_nat-y := nf_nat_core.o nf_nat_proto.o nf_nat_helper.o
|
||||
|
||||
# generic transport layer logging
|
||||
obj-$(CONFIG_NF_LOG_COMMON) += nf_log_common.o
|
||||
|
||||
# packet logging for netdev family
|
||||
obj-$(CONFIG_NF_LOG_NETDEV) += nf_log_netdev.o
|
||||
obj-$(CONFIG_NF_LOG_SYSLOG) += nf_log_syslog.o
|
||||
|
||||
obj-$(CONFIG_NF_NAT) += nf_nat.o
|
||||
nf_nat-$(CONFIG_NF_NAT_REDIRECT) += nf_nat_redirect.o
|
||||
|
@ -963,20 +963,9 @@ static struct nlmsghdr *
|
||||
start_msg(struct sk_buff *skb, u32 portid, u32 seq, unsigned int flags,
|
||||
enum ipset_cmd cmd)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
|
||||
nlh = nlmsg_put(skb, portid, seq, nfnl_msg_type(NFNL_SUBSYS_IPSET, cmd),
|
||||
sizeof(*nfmsg), flags);
|
||||
if (!nlh)
|
||||
return NULL;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = NFPROTO_IPV4;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = 0;
|
||||
|
||||
return nlh;
|
||||
return nfnl_msg_put(skb, portid, seq,
|
||||
nfnl_msg_type(NFNL_SUBSYS_IPSET, cmd), flags,
|
||||
NFPROTO_IPV4, NFNETLINK_V0, 0);
|
||||
}
|
||||
|
||||
/* Create a set */
|
||||
|
@ -591,8 +591,6 @@ static int __net_init __ip_vs_ftp_init(struct net *net)
|
||||
ret = register_ip_vs_app_inc(ipvs, app, app->protocol, ports[i]);
|
||||
if (ret)
|
||||
goto err_unreg;
|
||||
pr_info("%s: loaded support on port[%d] = %u\n",
|
||||
app->name, i, ports[i]);
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
@ -656,6 +656,7 @@ static void nf_ct_delete_from_lists(struct nf_conn *ct)
|
||||
bool nf_ct_delete(struct nf_conn *ct, u32 portid, int report)
|
||||
{
|
||||
struct nf_conn_tstamp *tstamp;
|
||||
struct net *net;
|
||||
|
||||
if (test_and_set_bit(IPS_DYING_BIT, &ct->status))
|
||||
return false;
|
||||
@ -670,11 +671,13 @@ bool nf_ct_delete(struct nf_conn *ct, u32 portid, int report)
|
||||
* be done by event cache worker on redelivery.
|
||||
*/
|
||||
nf_ct_delete_from_lists(ct);
|
||||
nf_conntrack_ecache_delayed_work(nf_ct_net(ct));
|
||||
nf_conntrack_ecache_work(nf_ct_net(ct), NFCT_ECACHE_DESTROY_FAIL);
|
||||
return false;
|
||||
}
|
||||
|
||||
nf_conntrack_ecache_work(nf_ct_net(ct));
|
||||
net = nf_ct_net(ct);
|
||||
if (nf_conntrack_ecache_dwork_pending(net))
|
||||
nf_conntrack_ecache_work(net, NFCT_ECACHE_DESTROY_SENT);
|
||||
nf_ct_delete_from_lists(ct);
|
||||
nf_ct_put(ct);
|
||||
return true;
|
||||
|
@ -27,6 +27,8 @@
|
||||
#include <net/netfilter/nf_conntrack_ecache.h>
|
||||
#include <net/netfilter/nf_conntrack_extend.h>
|
||||
|
||||
extern unsigned int nf_conntrack_net_id;
|
||||
|
||||
static DEFINE_MUTEX(nf_ct_ecache_mutex);
|
||||
|
||||
#define ECACHE_RETRY_WAIT (HZ/10)
|
||||
@ -96,8 +98,8 @@ static enum retry_state ecache_work_evict_list(struct ct_pcpu *pcpu)
|
||||
|
||||
static void ecache_work(struct work_struct *work)
|
||||
{
|
||||
struct netns_ct *ctnet =
|
||||
container_of(work, struct netns_ct, ecache_dwork.work);
|
||||
struct nf_conntrack_net *cnet = container_of(work, struct nf_conntrack_net, ecache_dwork.work);
|
||||
struct netns_ct *ctnet = cnet->ct_net;
|
||||
int cpu, delay = -1;
|
||||
struct ct_pcpu *pcpu;
|
||||
|
||||
@ -127,7 +129,7 @@ static void ecache_work(struct work_struct *work)
|
||||
|
||||
ctnet->ecache_dwork_pending = delay > 0;
|
||||
if (delay >= 0)
|
||||
schedule_delayed_work(&ctnet->ecache_dwork, delay);
|
||||
schedule_delayed_work(&cnet->ecache_dwork, delay);
|
||||
}
|
||||
|
||||
int nf_conntrack_eventmask_report(unsigned int eventmask, struct nf_conn *ct,
|
||||
@ -344,6 +346,20 @@ void nf_ct_expect_unregister_notifier(struct net *net,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier);
|
||||
|
||||
void nf_conntrack_ecache_work(struct net *net, enum nf_ct_ecache_state state)
|
||||
{
|
||||
struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
|
||||
|
||||
if (state == NFCT_ECACHE_DESTROY_FAIL &&
|
||||
!delayed_work_pending(&cnet->ecache_dwork)) {
|
||||
schedule_delayed_work(&cnet->ecache_dwork, HZ);
|
||||
net->ct.ecache_dwork_pending = true;
|
||||
} else if (state == NFCT_ECACHE_DESTROY_SENT) {
|
||||
net->ct.ecache_dwork_pending = false;
|
||||
mod_delayed_work(system_wq, &cnet->ecache_dwork, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#define NF_CT_EVENTS_DEFAULT 1
|
||||
static int nf_ct_events __read_mostly = NF_CT_EVENTS_DEFAULT;
|
||||
|
||||
@ -355,13 +371,18 @@ static const struct nf_ct_ext_type event_extend = {
|
||||
|
||||
void nf_conntrack_ecache_pernet_init(struct net *net)
|
||||
{
|
||||
struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
|
||||
|
||||
net->ct.sysctl_events = nf_ct_events;
|
||||
INIT_DELAYED_WORK(&net->ct.ecache_dwork, ecache_work);
|
||||
cnet->ct_net = &net->ct;
|
||||
INIT_DELAYED_WORK(&cnet->ecache_dwork, ecache_work);
|
||||
}
|
||||
|
||||
void nf_conntrack_ecache_pernet_fini(struct net *net)
|
||||
{
|
||||
cancel_delayed_work_sync(&net->ct.ecache_dwork);
|
||||
struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
|
||||
|
||||
cancel_delayed_work_sync(&cnet->ecache_dwork);
|
||||
}
|
||||
|
||||
int nf_conntrack_ecache_init(void)
|
||||
|
@ -555,22 +555,17 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
|
||||
{
|
||||
const struct nf_conntrack_zone *zone;
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
struct nlattr *nest_parms;
|
||||
unsigned int event;
|
||||
|
||||
if (portid)
|
||||
flags |= NLM_F_MULTI;
|
||||
event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_NEW);
|
||||
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
nlh = nfnl_msg_put(skb, portid, seq, event, flags, nf_ct_l3num(ct),
|
||||
NFNETLINK_V0, 0);
|
||||
if (!nlh)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = nf_ct_l3num(ct);
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = 0;
|
||||
|
||||
zone = nf_ct_zone(ct);
|
||||
|
||||
nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG);
|
||||
@ -713,7 +708,6 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
|
||||
const struct nf_conntrack_zone *zone;
|
||||
struct net *net;
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
struct nlattr *nest_parms;
|
||||
struct nf_conn *ct = item->ct;
|
||||
struct sk_buff *skb;
|
||||
@ -743,15 +737,11 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
|
||||
goto errout;
|
||||
|
||||
type = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, type);
|
||||
nlh = nlmsg_put(skb, item->portid, 0, type, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
nlh = nfnl_msg_put(skb, item->portid, 0, type, flags, nf_ct_l3num(ct),
|
||||
NFNETLINK_V0, 0);
|
||||
if (!nlh)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = nf_ct_l3num(ct);
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = 0;
|
||||
|
||||
zone = nf_ct_zone(ct);
|
||||
|
||||
nest_parms = nla_nest_start(skb, CTA_TUPLE_ORIG);
|
||||
@ -2490,20 +2480,15 @@ ctnetlink_ct_stat_cpu_fill_info(struct sk_buff *skb, u32 portid, u32 seq,
|
||||
__u16 cpu, const struct ip_conntrack_stat *st)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
unsigned int flags = portid ? NLM_F_MULTI : 0, event;
|
||||
|
||||
event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK,
|
||||
IPCTNL_MSG_CT_GET_STATS_CPU);
|
||||
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC,
|
||||
NFNETLINK_V0, htons(cpu));
|
||||
if (!nlh)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = AF_UNSPEC;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = htons(cpu);
|
||||
|
||||
if (nla_put_be32(skb, CTA_STATS_FOUND, htonl(st->found)) ||
|
||||
nla_put_be32(skb, CTA_STATS_INVALID, htonl(st->invalid)) ||
|
||||
nla_put_be32(skb, CTA_STATS_INSERT, htonl(st->insert)) ||
|
||||
@ -2575,20 +2560,15 @@ ctnetlink_stat_ct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
|
||||
struct net *net)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
unsigned int flags = portid ? NLM_F_MULTI : 0, event;
|
||||
unsigned int nr_conntracks = atomic_read(&net->ct.count);
|
||||
|
||||
event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_STATS);
|
||||
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC,
|
||||
NFNETLINK_V0, 0);
|
||||
if (!nlh)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = AF_UNSPEC;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = 0;
|
||||
|
||||
if (nla_put_be32(skb, CTA_STATS_GLOBAL_ENTRIES, htonl(nr_conntracks)))
|
||||
goto nla_put_failure;
|
||||
|
||||
@ -3085,19 +3065,14 @@ ctnetlink_exp_fill_info(struct sk_buff *skb, u32 portid, u32 seq,
|
||||
int event, const struct nf_conntrack_expect *exp)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
unsigned int flags = portid ? NLM_F_MULTI : 0;
|
||||
|
||||
event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_EXP, event);
|
||||
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
nlh = nfnl_msg_put(skb, portid, seq, event, flags,
|
||||
exp->tuple.src.l3num, NFNETLINK_V0, 0);
|
||||
if (!nlh)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = exp->tuple.src.l3num;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = 0;
|
||||
|
||||
if (ctnetlink_exp_dump_expect(skb, exp) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
@ -3117,7 +3092,6 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
|
||||
struct nf_conntrack_expect *exp = item->exp;
|
||||
struct net *net = nf_ct_exp_net(exp);
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
struct sk_buff *skb;
|
||||
unsigned int type, group;
|
||||
int flags = 0;
|
||||
@ -3140,15 +3114,11 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
|
||||
goto errout;
|
||||
|
||||
type = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_EXP, type);
|
||||
nlh = nlmsg_put(skb, item->portid, 0, type, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
nlh = nfnl_msg_put(skb, item->portid, 0, type, flags,
|
||||
exp->tuple.src.l3num, NFNETLINK_V0, 0);
|
||||
if (!nlh)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = exp->tuple.src.l3num;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = 0;
|
||||
|
||||
if (ctnetlink_exp_dump_expect(skb, exp) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
@ -3716,20 +3686,15 @@ ctnetlink_exp_stat_fill_info(struct sk_buff *skb, u32 portid, u32 seq, int cpu,
|
||||
const struct ip_conntrack_stat *st)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
unsigned int flags = portid ? NLM_F_MULTI : 0, event;
|
||||
|
||||
event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK,
|
||||
IPCTNL_MSG_EXP_GET_STATS_CPU);
|
||||
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC,
|
||||
NFNETLINK_V0, htons(cpu));
|
||||
if (!nlh)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = AF_UNSPEC;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = htons(cpu);
|
||||
|
||||
if (nla_put_be32(skb, CTA_STATS_EXP_NEW, htonl(st->expect_new)) ||
|
||||
nla_put_be32(skb, CTA_STATS_EXP_CREATE, htonl(st->expect_create)) ||
|
||||
nla_put_be32(skb, CTA_STATS_EXP_DELETE, htonl(st->expect_delete)))
|
||||
|
@ -1027,6 +1027,7 @@ static void nf_conntrack_standalone_init_gre_sysctl(struct net *net,
|
||||
|
||||
static int nf_conntrack_standalone_init_sysctl(struct net *net)
|
||||
{
|
||||
struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
|
||||
struct nf_udp_net *un = nf_udp_pernet(net);
|
||||
struct ctl_table *table;
|
||||
|
||||
@ -1072,8 +1073,8 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
|
||||
table[NF_SYSCTL_CT_BUCKETS].mode = 0444;
|
||||
}
|
||||
|
||||
net->ct.sysctl_header = register_net_sysctl(net, "net/netfilter", table);
|
||||
if (!net->ct.sysctl_header)
|
||||
cnet->sysctl_header = register_net_sysctl(net, "net/netfilter", table);
|
||||
if (!cnet->sysctl_header)
|
||||
goto out_unregister_netfilter;
|
||||
|
||||
return 0;
|
||||
@ -1085,10 +1086,11 @@ out_unregister_netfilter:
|
||||
|
||||
static void nf_conntrack_standalone_fini_sysctl(struct net *net)
|
||||
{
|
||||
struct nf_conntrack_net *cnet = net_generic(net, nf_conntrack_net_id);
|
||||
struct ctl_table *table;
|
||||
|
||||
table = net->ct.sysctl_header->ctl_table_arg;
|
||||
unregister_net_sysctl_table(net->ct.sysctl_header);
|
||||
table = cnet->sysctl_header->ctl_table_arg;
|
||||
unregister_net_sysctl_table(cnet->sysctl_header);
|
||||
kfree(table);
|
||||
}
|
||||
#else
|
||||
|
@ -74,6 +74,18 @@ err_ct_refcnt:
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(flow_offload_alloc);
|
||||
|
||||
static u32 flow_offload_dst_cookie(struct flow_offload_tuple *flow_tuple)
|
||||
{
|
||||
const struct rt6_info *rt;
|
||||
|
||||
if (flow_tuple->l3proto == NFPROTO_IPV6) {
|
||||
rt = (const struct rt6_info *)flow_tuple->dst_cache;
|
||||
return rt6_get_cookie(rt);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flow_offload_fill_route(struct flow_offload *flow,
|
||||
const struct nf_flow_route *route,
|
||||
enum flow_offload_tuple_dir dir)
|
||||
@ -116,6 +128,7 @@ static int flow_offload_fill_route(struct flow_offload *flow,
|
||||
return -1;
|
||||
|
||||
flow_tuple->dst_cache = dst;
|
||||
flow_tuple->dst_cookie = flow_offload_dst_cookie(flow_tuple);
|
||||
break;
|
||||
}
|
||||
flow_tuple->xmit_type = route->tuple[dir].xmit_type;
|
||||
@ -390,11 +403,33 @@ nf_flow_table_iterate(struct nf_flowtable *flow_table,
|
||||
return err;
|
||||
}
|
||||
|
||||
static bool flow_offload_stale_dst(struct flow_offload_tuple *tuple)
|
||||
{
|
||||
struct dst_entry *dst;
|
||||
|
||||
if (tuple->xmit_type == FLOW_OFFLOAD_XMIT_NEIGH ||
|
||||
tuple->xmit_type == FLOW_OFFLOAD_XMIT_XFRM) {
|
||||
dst = tuple->dst_cache;
|
||||
if (!dst_check(dst, tuple->dst_cookie))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool nf_flow_has_stale_dst(struct flow_offload *flow)
|
||||
{
|
||||
return flow_offload_stale_dst(&flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple) ||
|
||||
flow_offload_stale_dst(&flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple);
|
||||
}
|
||||
|
||||
static void nf_flow_offload_gc_step(struct flow_offload *flow, void *data)
|
||||
{
|
||||
struct nf_flowtable *flow_table = data;
|
||||
|
||||
if (nf_flow_has_expired(flow) || nf_ct_is_dying(flow->ct))
|
||||
if (nf_flow_has_expired(flow) ||
|
||||
nf_ct_is_dying(flow->ct) ||
|
||||
nf_flow_has_stale_dst(flow))
|
||||
set_bit(NF_FLOW_TEARDOWN, &flow->flags);
|
||||
|
||||
if (test_bit(NF_FLOW_TEARDOWN, &flow->flags)) {
|
||||
|
@ -364,15 +364,6 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
|
||||
if (nf_flow_state_check(flow, iph->protocol, skb, thoff))
|
||||
return NF_ACCEPT;
|
||||
|
||||
if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH ||
|
||||
tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM) {
|
||||
rt = (struct rtable *)tuplehash->tuple.dst_cache;
|
||||
if (!dst_check(&rt->dst, 0)) {
|
||||
flow_offload_teardown(flow);
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
}
|
||||
|
||||
if (skb_try_make_writable(skb, thoff + hdrsize))
|
||||
return NF_DROP;
|
||||
|
||||
@ -391,6 +382,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
|
||||
nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len);
|
||||
|
||||
if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
|
||||
rt = (struct rtable *)tuplehash->tuple.dst_cache;
|
||||
memset(skb->cb, 0, sizeof(struct inet_skb_parm));
|
||||
IPCB(skb)->iif = skb->dev->ifindex;
|
||||
IPCB(skb)->flags = IPSKB_FORWARDED;
|
||||
@ -399,6 +391,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
|
||||
|
||||
switch (tuplehash->tuple.xmit_type) {
|
||||
case FLOW_OFFLOAD_XMIT_NEIGH:
|
||||
rt = (struct rtable *)tuplehash->tuple.dst_cache;
|
||||
outdev = rt->dst.dev;
|
||||
skb->dev = outdev;
|
||||
nexthop = rt_nexthop(rt, flow->tuplehash[!dir].tuple.src_v4.s_addr);
|
||||
@ -607,15 +600,6 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
|
||||
if (nf_flow_state_check(flow, ip6h->nexthdr, skb, thoff))
|
||||
return NF_ACCEPT;
|
||||
|
||||
if (tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_NEIGH ||
|
||||
tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM) {
|
||||
rt = (struct rt6_info *)tuplehash->tuple.dst_cache;
|
||||
if (!dst_check(&rt->dst, 0)) {
|
||||
flow_offload_teardown(flow);
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
}
|
||||
|
||||
if (skb_try_make_writable(skb, thoff + hdrsize))
|
||||
return NF_DROP;
|
||||
|
||||
@ -633,6 +617,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
|
||||
nf_ct_acct_update(flow->ct, tuplehash->tuple.dir, skb->len);
|
||||
|
||||
if (unlikely(tuplehash->tuple.xmit_type == FLOW_OFFLOAD_XMIT_XFRM)) {
|
||||
rt = (struct rt6_info *)tuplehash->tuple.dst_cache;
|
||||
memset(skb->cb, 0, sizeof(struct inet6_skb_parm));
|
||||
IP6CB(skb)->iif = skb->dev->ifindex;
|
||||
IP6CB(skb)->flags = IP6SKB_FORWARDED;
|
||||
@ -641,6 +626,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
|
||||
|
||||
switch (tuplehash->tuple.xmit_type) {
|
||||
case FLOW_OFFLOAD_XMIT_NEIGH:
|
||||
rt = (struct rt6_info *)tuplehash->tuple.dst_cache;
|
||||
outdev = rt->dst.dev;
|
||||
skb->dev = outdev;
|
||||
nexthop = rt6_nexthop(rt, &flow->tuplehash[!dir].tuple.src_v6);
|
||||
|
@ -151,13 +151,6 @@ void nf_log_unbind_pf(struct net *net, u_int8_t pf)
|
||||
}
|
||||
EXPORT_SYMBOL(nf_log_unbind_pf);
|
||||
|
||||
void nf_logger_request_module(int pf, enum nf_log_type type)
|
||||
{
|
||||
if (loggers[pf][type] == NULL)
|
||||
request_module("nf-logger-%u-%u", pf, type);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_logger_request_module);
|
||||
|
||||
int nf_logger_find_get(int pf, enum nf_log_type type)
|
||||
{
|
||||
struct nf_logger *logger;
|
||||
@ -177,9 +170,6 @@ int nf_logger_find_get(int pf, enum nf_log_type type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (rcu_access_pointer(loggers[pf][type]) == NULL)
|
||||
request_module("nf-logger-%u-%u", pf, type);
|
||||
|
||||
rcu_read_lock();
|
||||
logger = rcu_dereference(loggers[pf][type]);
|
||||
if (logger == NULL)
|
||||
|
@ -1,224 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/* (C) 1999-2001 Paul `Rusty' Russell
|
||||
* (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/if_arp.h>
|
||||
#include <linux/ip.h>
|
||||
#include <net/icmp.h>
|
||||
#include <net/udp.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_bridge.h>
|
||||
#include <linux/netfilter/xt_LOG.h>
|
||||
#include <net/netfilter/nf_log.h>
|
||||
|
||||
int nf_log_dump_udp_header(struct nf_log_buf *m, const struct sk_buff *skb,
|
||||
u8 proto, int fragment, unsigned int offset)
|
||||
{
|
||||
struct udphdr _udph;
|
||||
const struct udphdr *uh;
|
||||
|
||||
if (proto == IPPROTO_UDP)
|
||||
/* Max length: 10 "PROTO=UDP " */
|
||||
nf_log_buf_add(m, "PROTO=UDP ");
|
||||
else /* Max length: 14 "PROTO=UDPLITE " */
|
||||
nf_log_buf_add(m, "PROTO=UDPLITE ");
|
||||
|
||||
if (fragment)
|
||||
goto out;
|
||||
|
||||
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
|
||||
uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph);
|
||||
if (uh == NULL) {
|
||||
nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Max length: 20 "SPT=65535 DPT=65535 " */
|
||||
nf_log_buf_add(m, "SPT=%u DPT=%u LEN=%u ",
|
||||
ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len));
|
||||
|
||||
out:
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_log_dump_udp_header);
|
||||
|
||||
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)
|
||||
{
|
||||
struct tcphdr _tcph;
|
||||
const struct tcphdr *th;
|
||||
|
||||
/* Max length: 10 "PROTO=TCP " */
|
||||
nf_log_buf_add(m, "PROTO=TCP ");
|
||||
|
||||
if (fragment)
|
||||
return 0;
|
||||
|
||||
/* Max length: 25 "INCOMPLETE [65535 bytes] " */
|
||||
th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph);
|
||||
if (th == NULL) {
|
||||
nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Max length: 20 "SPT=65535 DPT=65535 " */
|
||||
nf_log_buf_add(m, "SPT=%u DPT=%u ",
|
||||
ntohs(th->source), ntohs(th->dest));
|
||||
/* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */
|
||||
if (logflags & NF_LOG_TCPSEQ) {
|
||||
nf_log_buf_add(m, "SEQ=%u ACK=%u ",
|
||||
ntohl(th->seq), ntohl(th->ack_seq));
|
||||
}
|
||||
|
||||
/* Max length: 13 "WINDOW=65535 " */
|
||||
nf_log_buf_add(m, "WINDOW=%u ", ntohs(th->window));
|
||||
/* Max length: 9 "RES=0x3C " */
|
||||
nf_log_buf_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) &
|
||||
TCP_RESERVED_BITS) >> 22));
|
||||
/* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */
|
||||
if (th->cwr)
|
||||
nf_log_buf_add(m, "CWR ");
|
||||
if (th->ece)
|
||||
nf_log_buf_add(m, "ECE ");
|
||||
if (th->urg)
|
||||
nf_log_buf_add(m, "URG ");
|
||||
if (th->ack)
|
||||
nf_log_buf_add(m, "ACK ");
|
||||
if (th->psh)
|
||||
nf_log_buf_add(m, "PSH ");
|
||||
if (th->rst)
|
||||
nf_log_buf_add(m, "RST ");
|
||||
if (th->syn)
|
||||
nf_log_buf_add(m, "SYN ");
|
||||
if (th->fin)
|
||||
nf_log_buf_add(m, "FIN ");
|
||||
/* Max length: 11 "URGP=65535 " */
|
||||
nf_log_buf_add(m, "URGP=%u ", ntohs(th->urg_ptr));
|
||||
|
||||
if ((logflags & NF_LOG_TCPOPT) && th->doff*4 > sizeof(struct tcphdr)) {
|
||||
u_int8_t _opt[60 - sizeof(struct tcphdr)];
|
||||
const u_int8_t *op;
|
||||
unsigned int i;
|
||||
unsigned int optsize = th->doff*4 - sizeof(struct tcphdr);
|
||||
|
||||
op = skb_header_pointer(skb, offset + sizeof(struct tcphdr),
|
||||
optsize, _opt);
|
||||
if (op == NULL) {
|
||||
nf_log_buf_add(m, "OPT (TRUNCATED)");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Max length: 127 "OPT (" 15*4*2chars ") " */
|
||||
nf_log_buf_add(m, "OPT (");
|
||||
for (i = 0; i < optsize; i++)
|
||||
nf_log_buf_add(m, "%02X", op[i]);
|
||||
|
||||
nf_log_buf_add(m, ") ");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_log_dump_tcp_header);
|
||||
|
||||
void nf_log_dump_sk_uid_gid(struct net *net, struct nf_log_buf *m,
|
||||
struct sock *sk)
|
||||
{
|
||||
if (!sk || !sk_fullsock(sk) || !net_eq(net, sock_net(sk)))
|
||||
return;
|
||||
|
||||
read_lock_bh(&sk->sk_callback_lock);
|
||||
if (sk->sk_socket && sk->sk_socket->file) {
|
||||
const struct cred *cred = sk->sk_socket->file->f_cred;
|
||||
nf_log_buf_add(m, "UID=%u GID=%u ",
|
||||
from_kuid_munged(&init_user_ns, cred->fsuid),
|
||||
from_kgid_munged(&init_user_ns, cred->fsgid));
|
||||
}
|
||||
read_unlock_bh(&sk->sk_callback_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_log_dump_sk_uid_gid);
|
||||
|
||||
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)
|
||||
{
|
||||
const struct net_device *physoutdev __maybe_unused;
|
||||
const struct net_device *physindev __maybe_unused;
|
||||
|
||||
nf_log_buf_add(m, KERN_SOH "%c%sIN=%s OUT=%s ",
|
||||
'0' + loginfo->u.log.level, prefix,
|
||||
in ? in->name : "",
|
||||
out ? out->name : "");
|
||||
#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
|
||||
physindev = nf_bridge_get_physindev(skb);
|
||||
if (physindev && in != physindev)
|
||||
nf_log_buf_add(m, "PHYSIN=%s ", physindev->name);
|
||||
physoutdev = nf_bridge_get_physoutdev(skb);
|
||||
if (physoutdev && out != physoutdev)
|
||||
nf_log_buf_add(m, "PHYSOUT=%s ", physoutdev->name);
|
||||
#endif
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_log_dump_packet_common);
|
||||
|
||||
void nf_log_dump_vlan(struct nf_log_buf *m, const struct sk_buff *skb)
|
||||
{
|
||||
u16 vid;
|
||||
|
||||
if (!skb_vlan_tag_present(skb))
|
||||
return;
|
||||
|
||||
vid = skb_vlan_tag_get(skb);
|
||||
nf_log_buf_add(m, "VPROTO=%04x VID=%u ", ntohs(skb->vlan_proto), vid);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_log_dump_vlan);
|
||||
|
||||
/* bridge and netdev logging families share this code. */
|
||||
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)
|
||||
{
|
||||
switch (protocol) {
|
||||
case htons(ETH_P_IP):
|
||||
nf_log_packet(net, NFPROTO_IPV4, hooknum, skb, in, out,
|
||||
loginfo, "%s", prefix);
|
||||
break;
|
||||
case htons(ETH_P_IPV6):
|
||||
nf_log_packet(net, NFPROTO_IPV6, hooknum, skb, in, out,
|
||||
loginfo, "%s", prefix);
|
||||
break;
|
||||
case htons(ETH_P_ARP):
|
||||
case htons(ETH_P_RARP):
|
||||
nf_log_packet(net, NFPROTO_ARP, hooknum, skb, in, out,
|
||||
loginfo, "%s", prefix);
|
||||
break;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_log_l2packet);
|
||||
|
||||
static int __init nf_log_common_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit nf_log_common_exit(void) {}
|
||||
|
||||
module_init(nf_log_common_init);
|
||||
module_exit(nf_log_common_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
@ -1,78 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* (C) 2016 by Pablo Neira Ayuso <pablo@netfilter.org>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/ip.h>
|
||||
#include <net/route.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include <net/netfilter/nf_log.h>
|
||||
|
||||
static void nf_log_netdev_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 *loginfo,
|
||||
const char *prefix)
|
||||
{
|
||||
nf_log_l2packet(net, pf, skb->protocol, hooknum, skb, in, out,
|
||||
loginfo, prefix);
|
||||
}
|
||||
|
||||
static struct nf_logger nf_netdev_logger __read_mostly = {
|
||||
.name = "nf_log_netdev",
|
||||
.type = NF_LOG_TYPE_LOG,
|
||||
.logfn = nf_log_netdev_packet,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __net_init nf_log_netdev_net_init(struct net *net)
|
||||
{
|
||||
return nf_log_set(net, NFPROTO_NETDEV, &nf_netdev_logger);
|
||||
}
|
||||
|
||||
static void __net_exit nf_log_netdev_net_exit(struct net *net)
|
||||
{
|
||||
nf_log_unset(net, &nf_netdev_logger);
|
||||
}
|
||||
|
||||
static struct pernet_operations nf_log_netdev_net_ops = {
|
||||
.init = nf_log_netdev_net_init,
|
||||
.exit = nf_log_netdev_net_exit,
|
||||
};
|
||||
|
||||
static int __init nf_log_netdev_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Request to load the real packet loggers. */
|
||||
nf_logger_request_module(NFPROTO_IPV4, NF_LOG_TYPE_LOG);
|
||||
nf_logger_request_module(NFPROTO_IPV6, NF_LOG_TYPE_LOG);
|
||||
nf_logger_request_module(NFPROTO_ARP, NF_LOG_TYPE_LOG);
|
||||
|
||||
ret = register_pernet_subsys(&nf_log_netdev_net_ops);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
nf_log_register(NFPROTO_NETDEV, &nf_netdev_logger);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit nf_log_netdev_exit(void)
|
||||
{
|
||||
unregister_pernet_subsys(&nf_log_netdev_net_ops);
|
||||
nf_log_unregister(&nf_netdev_logger);
|
||||
}
|
||||
|
||||
module_init(nf_log_netdev_init);
|
||||
module_exit(nf_log_netdev_exit);
|
||||
|
||||
MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
|
||||
MODULE_DESCRIPTION("Netfilter netdev packet logging");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_NF_LOGGER(5, 0); /* NFPROTO_NETDEV */
|
1089
net/netfilter/nf_log_syslog.c
Normal file
1089
net/netfilter/nf_log_syslog.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -7,6 +7,8 @@
|
||||
#include <net/netfilter/nf_tables_offload.h>
|
||||
#include <net/pkt_cls.h>
|
||||
|
||||
extern unsigned int nf_tables_net_id;
|
||||
|
||||
static struct nft_flow_rule *nft_flow_rule_alloc(int num_actions)
|
||||
{
|
||||
struct nft_flow_rule *flow;
|
||||
@ -307,16 +309,18 @@ static void nft_indr_block_cleanup(struct flow_block_cb *block_cb)
|
||||
struct nft_base_chain *basechain = block_cb->indr.data;
|
||||
struct net_device *dev = block_cb->indr.dev;
|
||||
struct netlink_ext_ack extack = {};
|
||||
struct nftables_pernet *nft_net;
|
||||
struct net *net = dev_net(dev);
|
||||
struct flow_block_offload bo;
|
||||
|
||||
nft_flow_block_offload_init(&bo, dev_net(dev), FLOW_BLOCK_UNBIND,
|
||||
basechain, &extack);
|
||||
mutex_lock(&net->nft.commit_mutex);
|
||||
nft_net = net_generic(net, nf_tables_net_id);
|
||||
mutex_lock(&nft_net->commit_mutex);
|
||||
list_del(&block_cb->driver_list);
|
||||
list_move(&block_cb->list, &bo.cb_list);
|
||||
nft_flow_offload_unbind(&bo, basechain);
|
||||
mutex_unlock(&net->nft.commit_mutex);
|
||||
mutex_unlock(&nft_net->commit_mutex);
|
||||
}
|
||||
|
||||
static int nft_indr_block_offload_cmd(struct nft_base_chain *basechain,
|
||||
@ -412,9 +416,10 @@ static int nft_flow_offload_chain(struct nft_chain *chain, u8 *ppolicy,
|
||||
static void nft_flow_rule_offload_abort(struct net *net,
|
||||
struct nft_trans *trans)
|
||||
{
|
||||
struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
|
||||
int err = 0;
|
||||
|
||||
list_for_each_entry_continue_reverse(trans, &net->nft.commit_list, list) {
|
||||
list_for_each_entry_continue_reverse(trans, &nft_net->commit_list, list) {
|
||||
if (trans->ctx.family != NFPROTO_NETDEV)
|
||||
continue;
|
||||
|
||||
@ -460,11 +465,12 @@ static void nft_flow_rule_offload_abort(struct net *net,
|
||||
|
||||
int nft_flow_rule_offload_commit(struct net *net)
|
||||
{
|
||||
struct nftables_pernet *nft_net = net_generic(net, nf_tables_net_id);
|
||||
struct nft_trans *trans;
|
||||
int err = 0;
|
||||
u8 policy;
|
||||
|
||||
list_for_each_entry(trans, &net->nft.commit_list, list) {
|
||||
list_for_each_entry(trans, &nft_net->commit_list, list) {
|
||||
if (trans->ctx.family != NFPROTO_NETDEV)
|
||||
continue;
|
||||
|
||||
@ -516,7 +522,7 @@ int nft_flow_rule_offload_commit(struct net *net)
|
||||
}
|
||||
}
|
||||
|
||||
list_for_each_entry(trans, &net->nft.commit_list, list) {
|
||||
list_for_each_entry(trans, &nft_net->commit_list, list) {
|
||||
if (trans->ctx.family != NFPROTO_NETDEV)
|
||||
continue;
|
||||
|
||||
@ -536,15 +542,15 @@ int nft_flow_rule_offload_commit(struct net *net)
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct nft_chain *__nft_offload_get_chain(struct net_device *dev)
|
||||
static struct nft_chain *__nft_offload_get_chain(const struct nftables_pernet *nft_net,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct nft_base_chain *basechain;
|
||||
struct net *net = dev_net(dev);
|
||||
struct nft_hook *hook, *found;
|
||||
const struct nft_table *table;
|
||||
struct nft_chain *chain;
|
||||
|
||||
list_for_each_entry(table, &net->nft.tables, list) {
|
||||
list_for_each_entry(table, &nft_net->tables, list) {
|
||||
if (table->family != NFPROTO_NETDEV)
|
||||
continue;
|
||||
|
||||
@ -576,19 +582,21 @@ static int nft_offload_netdev_event(struct notifier_block *this,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
struct nftables_pernet *nft_net;
|
||||
struct net *net = dev_net(dev);
|
||||
struct nft_chain *chain;
|
||||
|
||||
if (event != NETDEV_UNREGISTER)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
mutex_lock(&net->nft.commit_mutex);
|
||||
chain = __nft_offload_get_chain(dev);
|
||||
nft_net = net_generic(net, nf_tables_net_id);
|
||||
mutex_lock(&nft_net->commit_mutex);
|
||||
chain = __nft_offload_get_chain(nft_net, dev);
|
||||
if (chain)
|
||||
nft_flow_block_chain(nft_base_chain(chain), dev,
|
||||
FLOW_BLOCK_UNBIND);
|
||||
|
||||
mutex_unlock(&net->nft.commit_mutex);
|
||||
mutex_unlock(&nft_net->commit_mutex);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
@ -183,7 +183,6 @@ static bool nft_trace_have_verdict_chain(struct nft_traceinfo *info)
|
||||
void nft_trace_notify(struct nft_traceinfo *info)
|
||||
{
|
||||
const struct nft_pktinfo *pkt = info->pkt;
|
||||
struct nfgenmsg *nfmsg;
|
||||
struct nlmsghdr *nlh;
|
||||
struct sk_buff *skb;
|
||||
unsigned int size;
|
||||
@ -219,15 +218,11 @@ void nft_trace_notify(struct nft_traceinfo *info)
|
||||
return;
|
||||
|
||||
event = nfnl_msg_type(NFNL_SUBSYS_NFTABLES, NFT_MSG_TRACE);
|
||||
nlh = nlmsg_put(skb, 0, 0, event, sizeof(struct nfgenmsg), 0);
|
||||
nlh = nfnl_msg_put(skb, 0, 0, event, 0, info->basechain->type->family,
|
||||
NFNETLINK_V0, 0);
|
||||
if (!nlh)
|
||||
goto nla_put_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = info->basechain->type->family;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = 0;
|
||||
|
||||
if (nla_put_be32(skb, NFTA_TRACE_NFPROTO, htonl(nft_pf(pkt))))
|
||||
goto nla_put_failure;
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <linux/sched/signal.h>
|
||||
|
||||
#include <net/netlink.h>
|
||||
#include <net/netns/generic.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
@ -41,6 +42,12 @@ MODULE_DESCRIPTION("Netfilter messages via netlink socket");
|
||||
|
||||
#define NFNL_MAX_ATTR_COUNT 32
|
||||
|
||||
static unsigned int nfnetlink_pernet_id __read_mostly;
|
||||
|
||||
struct nfnl_net {
|
||||
struct sock *nfnl;
|
||||
};
|
||||
|
||||
static struct {
|
||||
struct mutex mutex;
|
||||
const struct nfnetlink_subsystem __rcu *subsys;
|
||||
@ -75,6 +82,11 @@ static const int nfnl_group2type[NFNLGRP_MAX+1] = {
|
||||
[NFNLGRP_NFTRACE] = NFNL_SUBSYS_NFTABLES,
|
||||
};
|
||||
|
||||
static struct nfnl_net *nfnl_pernet(struct net *net)
|
||||
{
|
||||
return net_generic(net, nfnetlink_pernet_id);
|
||||
}
|
||||
|
||||
void nfnl_lock(__u8 subsys_id)
|
||||
{
|
||||
mutex_lock(&table[subsys_id].mutex);
|
||||
@ -149,28 +161,35 @@ nfnetlink_find_client(u16 type, const struct nfnetlink_subsystem *ss)
|
||||
|
||||
int nfnetlink_has_listeners(struct net *net, unsigned int group)
|
||||
{
|
||||
return netlink_has_listeners(net->nfnl, group);
|
||||
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
||||
|
||||
return netlink_has_listeners(nfnlnet->nfnl, group);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfnetlink_has_listeners);
|
||||
|
||||
int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 portid,
|
||||
unsigned int group, int echo, gfp_t flags)
|
||||
{
|
||||
return nlmsg_notify(net->nfnl, skb, portid, group, echo, flags);
|
||||
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
||||
|
||||
return nlmsg_notify(nfnlnet->nfnl, skb, portid, group, echo, flags);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfnetlink_send);
|
||||
|
||||
int nfnetlink_set_err(struct net *net, u32 portid, u32 group, int error)
|
||||
{
|
||||
return netlink_set_err(net->nfnl, portid, group, error);
|
||||
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
||||
|
||||
return netlink_set_err(nfnlnet->nfnl, portid, group, error);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfnetlink_set_err);
|
||||
|
||||
int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u32 portid)
|
||||
{
|
||||
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
||||
int err;
|
||||
|
||||
err = nlmsg_unicast(net->nfnl, skb, portid);
|
||||
err = nlmsg_unicast(nfnlnet->nfnl, skb, portid);
|
||||
if (err == -EAGAIN)
|
||||
err = -ENOBUFS;
|
||||
|
||||
@ -178,6 +197,15 @@ int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u32 portid)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfnetlink_unicast);
|
||||
|
||||
void nfnetlink_broadcast(struct net *net, struct sk_buff *skb, __u32 portid,
|
||||
__u32 group, gfp_t allocation)
|
||||
{
|
||||
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
||||
|
||||
netlink_broadcast(nfnlnet->nfnl, skb, portid, group, allocation);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nfnetlink_broadcast);
|
||||
|
||||
/* Process one complete nfnetlink message. */
|
||||
static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
struct netlink_ext_ack *extack)
|
||||
@ -194,6 +222,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
type = nlh->nlmsg_type;
|
||||
replay:
|
||||
rcu_read_lock();
|
||||
|
||||
ss = nfnetlink_get_subsys(type);
|
||||
if (!ss) {
|
||||
#ifdef CONFIG_MODULES
|
||||
@ -217,6 +246,7 @@ replay:
|
||||
|
||||
{
|
||||
int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
|
||||
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
||||
u8 cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
|
||||
struct nlattr *cda[NFNL_MAX_ATTR_COUNT + 1];
|
||||
struct nlattr *attr = (void *)nlh + min_len;
|
||||
@ -238,7 +268,7 @@ replay:
|
||||
}
|
||||
|
||||
if (nc->call_rcu) {
|
||||
err = nc->call_rcu(net, net->nfnl, skb, nlh,
|
||||
err = nc->call_rcu(net, nfnlnet->nfnl, skb, nlh,
|
||||
(const struct nlattr **)cda,
|
||||
extack);
|
||||
rcu_read_unlock();
|
||||
@ -249,7 +279,7 @@ replay:
|
||||
nfnetlink_find_client(type, ss) != nc)
|
||||
err = -EAGAIN;
|
||||
else if (nc->call)
|
||||
err = nc->call(net, net->nfnl, skb, nlh,
|
||||
err = nc->call(net, nfnlnet->nfnl, skb, nlh,
|
||||
(const struct nlattr **)cda,
|
||||
extack);
|
||||
else
|
||||
@ -453,7 +483,9 @@ replay_abort:
|
||||
goto ack;
|
||||
|
||||
if (nc->call_batch) {
|
||||
err = nc->call_batch(net, net->nfnl, skb, nlh,
|
||||
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
||||
|
||||
err = nc->call_batch(net, nfnlnet->nfnl, skb, nlh,
|
||||
(const struct nlattr **)cda,
|
||||
&extack);
|
||||
}
|
||||
@ -622,7 +654,7 @@ static int nfnetlink_bind(struct net *net, int group)
|
||||
|
||||
static int __net_init nfnetlink_net_init(struct net *net)
|
||||
{
|
||||
struct sock *nfnl;
|
||||
struct nfnl_net *nfnlnet = nfnl_pernet(net);
|
||||
struct netlink_kernel_cfg cfg = {
|
||||
.groups = NFNLGRP_MAX,
|
||||
.input = nfnetlink_rcv,
|
||||
@ -631,28 +663,29 @@ static int __net_init nfnetlink_net_init(struct net *net)
|
||||
#endif
|
||||
};
|
||||
|
||||
nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, &cfg);
|
||||
if (!nfnl)
|
||||
nfnlnet->nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, &cfg);
|
||||
if (!nfnlnet->nfnl)
|
||||
return -ENOMEM;
|
||||
net->nfnl_stash = nfnl;
|
||||
rcu_assign_pointer(net->nfnl, nfnl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __net_exit nfnetlink_net_exit_batch(struct list_head *net_exit_list)
|
||||
{
|
||||
struct nfnl_net *nfnlnet;
|
||||
struct net *net;
|
||||
|
||||
list_for_each_entry(net, net_exit_list, exit_list)
|
||||
RCU_INIT_POINTER(net->nfnl, NULL);
|
||||
synchronize_net();
|
||||
list_for_each_entry(net, net_exit_list, exit_list)
|
||||
netlink_kernel_release(net->nfnl_stash);
|
||||
list_for_each_entry(net, net_exit_list, exit_list) {
|
||||
nfnlnet = nfnl_pernet(net);
|
||||
|
||||
netlink_kernel_release(nfnlnet->nfnl);
|
||||
}
|
||||
}
|
||||
|
||||
static struct pernet_operations nfnetlink_net_ops = {
|
||||
.init = nfnetlink_net_init,
|
||||
.exit_batch = nfnetlink_net_exit_batch,
|
||||
.id = &nfnetlink_pernet_id,
|
||||
.size = sizeof(struct nfnl_net),
|
||||
};
|
||||
|
||||
static int __init nfnetlink_init(void)
|
||||
|
@ -145,21 +145,16 @@ nfnl_acct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
|
||||
int event, struct nf_acct *acct)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
unsigned int flags = portid ? NLM_F_MULTI : 0;
|
||||
u64 pkts, bytes;
|
||||
u32 old_flags;
|
||||
|
||||
event = nfnl_msg_type(NFNL_SUBSYS_ACCT, event);
|
||||
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC,
|
||||
NFNETLINK_V0, 0);
|
||||
if (!nlh)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = AF_UNSPEC;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = 0;
|
||||
|
||||
if (nla_put_string(skb, NFACCT_NAME, acct->name))
|
||||
goto nla_put_failure;
|
||||
|
||||
@ -474,8 +469,7 @@ static void nfnl_overquota_report(struct net *net, struct nf_acct *nfacct)
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
netlink_broadcast(net->nfnl, skb, 0, NFNLGRP_ACCT_QUOTA,
|
||||
GFP_ATOMIC);
|
||||
nfnetlink_broadcast(net, skb, 0, NFNLGRP_ACCT_QUOTA, GFP_ATOMIC);
|
||||
}
|
||||
|
||||
int nfnl_acct_overquota(struct net *net, struct nf_acct *nfacct)
|
||||
|
@ -526,20 +526,15 @@ nfnl_cthelper_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
|
||||
int event, struct nf_conntrack_helper *helper)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
unsigned int flags = portid ? NLM_F_MULTI : 0;
|
||||
int status;
|
||||
|
||||
event = nfnl_msg_type(NFNL_SUBSYS_CTHELPER, event);
|
||||
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC,
|
||||
NFNETLINK_V0, 0);
|
||||
if (!nlh)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = AF_UNSPEC;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = 0;
|
||||
|
||||
if (nla_put_string(skb, NFCTH_NAME, helper->name))
|
||||
goto nla_put_failure;
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include <net/netlink.h>
|
||||
#include <net/netns/generic.h>
|
||||
#include <net/sock.h>
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#include <net/netfilter/nf_conntrack_core.h>
|
||||
@ -30,6 +31,12 @@
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/netfilter/nfnetlink_cttimeout.h>
|
||||
|
||||
static unsigned int nfct_timeout_id __read_mostly;
|
||||
|
||||
struct nfct_timeout_pernet {
|
||||
struct list_head nfct_timeout_list;
|
||||
};
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>");
|
||||
MODULE_DESCRIPTION("cttimeout: Extended Netfilter Connection Tracking timeout tuning");
|
||||
@ -42,6 +49,11 @@ static const struct nla_policy cttimeout_nla_policy[CTA_TIMEOUT_MAX+1] = {
|
||||
[CTA_TIMEOUT_DATA] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static struct nfct_timeout_pernet *nfct_timeout_pernet(struct net *net)
|
||||
{
|
||||
return net_generic(net, nfct_timeout_id);
|
||||
}
|
||||
|
||||
static int
|
||||
ctnl_timeout_parse_policy(void *timeout,
|
||||
const struct nf_conntrack_l4proto *l4proto,
|
||||
@ -77,6 +89,7 @@ static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
|
||||
const struct nlattr * const cda[],
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
|
||||
__u16 l3num;
|
||||
__u8 l4num;
|
||||
const struct nf_conntrack_l4proto *l4proto;
|
||||
@ -94,7 +107,7 @@ static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
|
||||
l3num = ntohs(nla_get_be16(cda[CTA_TIMEOUT_L3PROTO]));
|
||||
l4num = nla_get_u8(cda[CTA_TIMEOUT_L4PROTO]);
|
||||
|
||||
list_for_each_entry(timeout, &net->nfct_timeout_list, head) {
|
||||
list_for_each_entry(timeout, &pernet->nfct_timeout_list, head) {
|
||||
if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
|
||||
continue;
|
||||
|
||||
@ -146,7 +159,7 @@ static int cttimeout_new_timeout(struct net *net, struct sock *ctnl,
|
||||
timeout->timeout.l3num = l3num;
|
||||
timeout->timeout.l4proto = l4proto;
|
||||
refcount_set(&timeout->refcnt, 1);
|
||||
list_add_tail_rcu(&timeout->head, &net->nfct_timeout_list);
|
||||
list_add_tail_rcu(&timeout->head, &pernet->nfct_timeout_list);
|
||||
|
||||
return 0;
|
||||
err:
|
||||
@ -160,22 +173,17 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
|
||||
int event, struct ctnl_timeout *timeout)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
unsigned int flags = portid ? NLM_F_MULTI : 0;
|
||||
const struct nf_conntrack_l4proto *l4proto = timeout->timeout.l4proto;
|
||||
struct nlattr *nest_parms;
|
||||
int ret;
|
||||
|
||||
event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event);
|
||||
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC,
|
||||
NFNETLINK_V0, 0);
|
||||
if (!nlh)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = AF_UNSPEC;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = 0;
|
||||
|
||||
if (nla_put_string(skb, CTA_TIMEOUT_NAME, timeout->name) ||
|
||||
nla_put_be16(skb, CTA_TIMEOUT_L3PROTO,
|
||||
htons(timeout->timeout.l3num)) ||
|
||||
@ -206,6 +214,7 @@ nla_put_failure:
|
||||
static int
|
||||
ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
{
|
||||
struct nfct_timeout_pernet *pernet;
|
||||
struct net *net = sock_net(skb->sk);
|
||||
struct ctnl_timeout *cur, *last;
|
||||
|
||||
@ -217,7 +226,8 @@ ctnl_timeout_dump(struct sk_buff *skb, struct netlink_callback *cb)
|
||||
cb->args[1] = 0;
|
||||
|
||||
rcu_read_lock();
|
||||
list_for_each_entry_rcu(cur, &net->nfct_timeout_list, head) {
|
||||
pernet = nfct_timeout_pernet(net);
|
||||
list_for_each_entry_rcu(cur, &pernet->nfct_timeout_list, head) {
|
||||
if (last) {
|
||||
if (cur != last)
|
||||
continue;
|
||||
@ -244,6 +254,7 @@ static int cttimeout_get_timeout(struct net *net, struct sock *ctnl,
|
||||
const struct nlattr * const cda[],
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
|
||||
int ret = -ENOENT;
|
||||
char *name;
|
||||
struct ctnl_timeout *cur;
|
||||
@ -259,7 +270,7 @@ static int cttimeout_get_timeout(struct net *net, struct sock *ctnl,
|
||||
return -EINVAL;
|
||||
name = nla_data(cda[CTA_TIMEOUT_NAME]);
|
||||
|
||||
list_for_each_entry(cur, &net->nfct_timeout_list, head) {
|
||||
list_for_each_entry(cur, &pernet->nfct_timeout_list, head) {
|
||||
struct sk_buff *skb2;
|
||||
|
||||
if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
|
||||
@ -315,12 +326,13 @@ static int cttimeout_del_timeout(struct net *net, struct sock *ctnl,
|
||||
const struct nlattr * const cda[],
|
||||
struct netlink_ext_ack *extack)
|
||||
{
|
||||
struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
|
||||
struct ctnl_timeout *cur, *tmp;
|
||||
int ret = -ENOENT;
|
||||
char *name;
|
||||
|
||||
if (!cda[CTA_TIMEOUT_NAME]) {
|
||||
list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list,
|
||||
list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_list,
|
||||
head)
|
||||
ctnl_timeout_try_del(net, cur);
|
||||
|
||||
@ -328,7 +340,7 @@ static int cttimeout_del_timeout(struct net *net, struct sock *ctnl,
|
||||
}
|
||||
name = nla_data(cda[CTA_TIMEOUT_NAME]);
|
||||
|
||||
list_for_each_entry(cur, &net->nfct_timeout_list, head) {
|
||||
list_for_each_entry(cur, &pernet->nfct_timeout_list, head) {
|
||||
if (strncmp(cur->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
|
||||
continue;
|
||||
|
||||
@ -382,21 +394,16 @@ cttimeout_default_fill_info(struct net *net, struct sk_buff *skb, u32 portid,
|
||||
const unsigned int *timeouts)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
unsigned int flags = portid ? NLM_F_MULTI : 0;
|
||||
struct nlattr *nest_parms;
|
||||
int ret;
|
||||
|
||||
event = nfnl_msg_type(NFNL_SUBSYS_CTNETLINK_TIMEOUT, event);
|
||||
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
nlh = nfnl_msg_put(skb, portid, seq, event, flags, AF_UNSPEC,
|
||||
NFNETLINK_V0, 0);
|
||||
if (!nlh)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = AF_UNSPEC;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = 0;
|
||||
|
||||
if (nla_put_be16(skb, CTA_TIMEOUT_L3PROTO, htons(l3num)) ||
|
||||
nla_put_u8(skb, CTA_TIMEOUT_L4PROTO, l4proto->l4proto))
|
||||
goto nla_put_failure;
|
||||
@ -513,9 +520,10 @@ err:
|
||||
static struct nf_ct_timeout *ctnl_timeout_find_get(struct net *net,
|
||||
const char *name)
|
||||
{
|
||||
struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
|
||||
struct ctnl_timeout *timeout, *matching = NULL;
|
||||
|
||||
list_for_each_entry_rcu(timeout, &net->nfct_timeout_list, head) {
|
||||
list_for_each_entry_rcu(timeout, &pernet->nfct_timeout_list, head) {
|
||||
if (strncmp(timeout->name, name, CTNL_TIMEOUT_NAME_MAX) != 0)
|
||||
continue;
|
||||
|
||||
@ -573,19 +581,22 @@ MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_CTNETLINK_TIMEOUT);
|
||||
|
||||
static int __net_init cttimeout_net_init(struct net *net)
|
||||
{
|
||||
INIT_LIST_HEAD(&net->nfct_timeout_list);
|
||||
struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
|
||||
|
||||
INIT_LIST_HEAD(&pernet->nfct_timeout_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __net_exit cttimeout_net_exit(struct net *net)
|
||||
{
|
||||
struct nfct_timeout_pernet *pernet = nfct_timeout_pernet(net);
|
||||
struct ctnl_timeout *cur, *tmp;
|
||||
|
||||
nf_ct_unconfirmed_destroy(net);
|
||||
nf_ct_untimeout(net, NULL);
|
||||
|
||||
list_for_each_entry_safe(cur, tmp, &net->nfct_timeout_list, head) {
|
||||
list_for_each_entry_safe(cur, tmp, &pernet->nfct_timeout_list, head) {
|
||||
list_del_rcu(&cur->head);
|
||||
|
||||
if (refcount_dec_and_test(&cur->refcnt))
|
||||
@ -596,6 +607,8 @@ static void __net_exit cttimeout_net_exit(struct net *net)
|
||||
static struct pernet_operations cttimeout_ops = {
|
||||
.init = cttimeout_net_init,
|
||||
.exit = cttimeout_net_exit,
|
||||
.id = &nfct_timeout_id,
|
||||
.size = sizeof(struct nfct_timeout_pernet),
|
||||
};
|
||||
|
||||
static int __init cttimeout_init(void)
|
||||
|
@ -456,20 +456,15 @@ __build_packet_message(struct nfnl_log_net *log,
|
||||
{
|
||||
struct nfulnl_msg_packet_hdr pmsg;
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
sk_buff_data_t old_tail = inst->skb->tail;
|
||||
struct sock *sk;
|
||||
const unsigned char *hwhdrp;
|
||||
|
||||
nlh = nlmsg_put(inst->skb, 0, 0,
|
||||
nlh = nfnl_msg_put(inst->skb, 0, 0,
|
||||
nfnl_msg_type(NFNL_SUBSYS_ULOG, NFULNL_MSG_PACKET),
|
||||
sizeof(struct nfgenmsg), 0);
|
||||
0, pf, NFNETLINK_V0, htons(inst->group_num));
|
||||
if (!nlh)
|
||||
return -1;
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = pf;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = htons(inst->group_num);
|
||||
|
||||
memset(&pmsg, 0, sizeof(pmsg));
|
||||
pmsg.hw_protocol = skb->protocol;
|
||||
|
@ -383,7 +383,6 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||
struct nlattr *nla;
|
||||
struct nfqnl_msg_packet_hdr *pmsg;
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
struct sk_buff *entskb = entry->skb;
|
||||
struct net_device *indev;
|
||||
struct net_device *outdev;
|
||||
@ -471,18 +470,15 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
|
||||
goto nlmsg_failure;
|
||||
}
|
||||
|
||||
nlh = nlmsg_put(skb, 0, 0,
|
||||
nlh = nfnl_msg_put(skb, 0, 0,
|
||||
nfnl_msg_type(NFNL_SUBSYS_QUEUE, NFQNL_MSG_PACKET),
|
||||
sizeof(struct nfgenmsg), 0);
|
||||
0, entry->state.pf, NFNETLINK_V0,
|
||||
htons(queue->queue_num));
|
||||
if (!nlh) {
|
||||
skb_tx_error(entskb);
|
||||
kfree_skb(skb);
|
||||
goto nlmsg_failure;
|
||||
}
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = entry->state.pf;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = htons(queue->queue_num);
|
||||
|
||||
nla = __nla_reserve(skb, NFQA_PACKET_HDR, sizeof(*pmsg));
|
||||
pmsg = nla_data(nla);
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/netns/generic.h>
|
||||
#include <net/netfilter/nf_tables.h>
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
@ -10,6 +11,8 @@
|
||||
#include <net/netfilter/nf_tables_ipv4.h>
|
||||
#include <net/netfilter/nf_tables_ipv6.h>
|
||||
|
||||
extern unsigned int nf_tables_net_id;
|
||||
|
||||
#ifdef CONFIG_NF_TABLES_IPV4
|
||||
static unsigned int nft_do_chain_ipv4(void *priv,
|
||||
struct sk_buff *skb,
|
||||
@ -355,6 +358,7 @@ static int nf_tables_netdev_event(struct notifier_block *this,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
|
||||
struct nftables_pernet *nft_net;
|
||||
struct nft_table *table;
|
||||
struct nft_chain *chain, *nr;
|
||||
struct nft_ctx ctx = {
|
||||
@ -365,8 +369,9 @@ static int nf_tables_netdev_event(struct notifier_block *this,
|
||||
event != NETDEV_CHANGENAME)
|
||||
return NOTIFY_DONE;
|
||||
|
||||
mutex_lock(&ctx.net->nft.commit_mutex);
|
||||
list_for_each_entry(table, &ctx.net->nft.tables, list) {
|
||||
nft_net = net_generic(ctx.net, nf_tables_net_id);
|
||||
mutex_lock(&nft_net->commit_mutex);
|
||||
list_for_each_entry(table, &nft_net->tables, list) {
|
||||
if (table->family != NFPROTO_NETDEV)
|
||||
continue;
|
||||
|
||||
@ -380,7 +385,7 @@ static int nf_tables_netdev_event(struct notifier_block *this,
|
||||
nft_netdev_event(event, dev, &ctx);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&ctx.net->nft.commit_mutex);
|
||||
mutex_unlock(&nft_net->commit_mutex);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
@ -591,19 +591,14 @@ nfnl_compat_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type,
|
||||
int rev, int target)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
struct nfgenmsg *nfmsg;
|
||||
unsigned int flags = portid ? NLM_F_MULTI : 0;
|
||||
|
||||
event = nfnl_msg_type(NFNL_SUBSYS_NFT_COMPAT, event);
|
||||
nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags);
|
||||
if (nlh == NULL)
|
||||
nlh = nfnl_msg_put(skb, portid, seq, event, flags, family,
|
||||
NFNETLINK_V0, 0);
|
||||
if (!nlh)
|
||||
goto nlmsg_failure;
|
||||
|
||||
nfmsg = nlmsg_data(nlh);
|
||||
nfmsg->nfgen_family = family;
|
||||
nfmsg->version = NFNETLINK_V0;
|
||||
nfmsg->res_id = 0;
|
||||
|
||||
if (nla_put_string(skb, NFTA_COMPAT_NAME, name) ||
|
||||
nla_put_be32(skb, NFTA_COMPAT_REV, htonl(rev)) ||
|
||||
nla_put_be32(skb, NFTA_COMPAT_TYPE, htonl(target)))
|
||||
|
@ -11,6 +11,9 @@
|
||||
#include <linux/netfilter/nf_tables.h>
|
||||
#include <net/netfilter/nf_tables.h>
|
||||
#include <net/netfilter/nf_tables_core.h>
|
||||
#include <net/netns/generic.h>
|
||||
|
||||
extern unsigned int nf_tables_net_id;
|
||||
|
||||
struct nft_dynset {
|
||||
struct nft_set *set;
|
||||
@ -161,13 +164,14 @@ static int nft_dynset_init(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr,
|
||||
const struct nlattr * const tb[])
|
||||
{
|
||||
struct nftables_pernet *nft_net = net_generic(ctx->net, nf_tables_net_id);
|
||||
struct nft_dynset *priv = nft_expr_priv(expr);
|
||||
u8 genmask = nft_genmask_next(ctx->net);
|
||||
struct nft_set *set;
|
||||
u64 timeout;
|
||||
int err, i;
|
||||
|
||||
lockdep_assert_held(&ctx->net->nft.commit_mutex);
|
||||
lockdep_assert_held(&nft_net->commit_mutex);
|
||||
|
||||
if (tb[NFTA_DYNSET_SET_NAME] == NULL ||
|
||||
tb[NFTA_DYNSET_OP] == NULL ||
|
||||
|
@ -128,6 +128,20 @@ static const struct nla_policy nft_log_policy[NFTA_LOG_MAX + 1] = {
|
||||
[NFTA_LOG_FLAGS] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int nft_log_modprobe(struct net *net, enum nf_log_type t)
|
||||
{
|
||||
switch (t) {
|
||||
case NF_LOG_TYPE_LOG:
|
||||
return nft_request_module(net, "%s", "nf_log_syslog");
|
||||
case NF_LOG_TYPE_ULOG:
|
||||
return nft_request_module(net, "%s", "nfnetlink_log");
|
||||
case NF_LOG_TYPE_MAX:
|
||||
break;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int nft_log_init(const struct nft_ctx *ctx,
|
||||
const struct nft_expr *expr,
|
||||
const struct nlattr * const tb[])
|
||||
@ -197,8 +211,12 @@ static int nft_log_init(const struct nft_ctx *ctx,
|
||||
return 0;
|
||||
|
||||
err = nf_logger_find_get(ctx->family, li->type);
|
||||
if (err < 0)
|
||||
if (err < 0) {
|
||||
if (nft_log_modprobe(ctx->net, li->type) == -EAGAIN)
|
||||
err = -EAGAIN;
|
||||
|
||||
goto err1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <linux/audit.h>
|
||||
#include <linux/user_namespace.h>
|
||||
#include <net/net_namespace.h>
|
||||
#include <net/netns/generic.h>
|
||||
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <linux/netfilter_arp.h>
|
||||
@ -38,6 +39,10 @@ MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module");
|
||||
#define XT_PCPU_BLOCK_SIZE 4096
|
||||
#define XT_MAX_TABLE_SIZE (512 * 1024 * 1024)
|
||||
|
||||
struct xt_pernet {
|
||||
struct list_head tables[NFPROTO_NUMPROTO];
|
||||
};
|
||||
|
||||
struct compat_delta {
|
||||
unsigned int offset; /* offset in kernel */
|
||||
int delta; /* delta in 32bit user land */
|
||||
@ -55,7 +60,8 @@ struct xt_af {
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct xt_af *xt;
|
||||
static unsigned int xt_pernet_id __read_mostly;
|
||||
static struct xt_af *xt __read_mostly;
|
||||
|
||||
static const char *const xt_prefix[NFPROTO_NUMPROTO] = {
|
||||
[NFPROTO_UNSPEC] = "x",
|
||||
@ -1203,10 +1209,11 @@ EXPORT_SYMBOL(xt_free_table_info);
|
||||
struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
|
||||
const char *name)
|
||||
{
|
||||
struct xt_pernet *xt_net = net_generic(net, xt_pernet_id);
|
||||
struct xt_table *t, *found = NULL;
|
||||
|
||||
mutex_lock(&xt[af].mutex);
|
||||
list_for_each_entry(t, &net->xt.tables[af], list)
|
||||
list_for_each_entry(t, &xt_net->tables[af], list)
|
||||
if (strcmp(t->name, name) == 0 && try_module_get(t->me))
|
||||
return t;
|
||||
|
||||
@ -1214,7 +1221,8 @@ struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
|
||||
goto out;
|
||||
|
||||
/* Table doesn't exist in this netns, re-try init */
|
||||
list_for_each_entry(t, &init_net.xt.tables[af], list) {
|
||||
xt_net = net_generic(&init_net, xt_pernet_id);
|
||||
list_for_each_entry(t, &xt_net->tables[af], list) {
|
||||
int err;
|
||||
|
||||
if (strcmp(t->name, name))
|
||||
@ -1237,8 +1245,9 @@ struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af,
|
||||
if (!found)
|
||||
goto out;
|
||||
|
||||
xt_net = net_generic(net, xt_pernet_id);
|
||||
/* and once again: */
|
||||
list_for_each_entry(t, &net->xt.tables[af], list)
|
||||
list_for_each_entry(t, &xt_net->tables[af], list)
|
||||
if (strcmp(t->name, name) == 0)
|
||||
return t;
|
||||
|
||||
@ -1423,9 +1432,10 @@ struct xt_table *xt_register_table(struct net *net,
|
||||
struct xt_table_info *bootstrap,
|
||||
struct xt_table_info *newinfo)
|
||||
{
|
||||
int ret;
|
||||
struct xt_pernet *xt_net = net_generic(net, xt_pernet_id);
|
||||
struct xt_table_info *private;
|
||||
struct xt_table *t, *table;
|
||||
int ret;
|
||||
|
||||
/* Don't add one object to multiple lists. */
|
||||
table = kmemdup(input_table, sizeof(struct xt_table), GFP_KERNEL);
|
||||
@ -1436,7 +1446,7 @@ struct xt_table *xt_register_table(struct net *net,
|
||||
|
||||
mutex_lock(&xt[table->af].mutex);
|
||||
/* Don't autoload: we'd eat our tail... */
|
||||
list_for_each_entry(t, &net->xt.tables[table->af], list) {
|
||||
list_for_each_entry(t, &xt_net->tables[table->af], list) {
|
||||
if (strcmp(t->name, table->name) == 0) {
|
||||
ret = -EEXIST;
|
||||
goto unlock;
|
||||
@ -1455,7 +1465,7 @@ struct xt_table *xt_register_table(struct net *net,
|
||||
/* save number of initial entries */
|
||||
private->initial_entries = private->number;
|
||||
|
||||
list_add(&table->list, &net->xt.tables[table->af]);
|
||||
list_add(&table->list, &xt_net->tables[table->af]);
|
||||
mutex_unlock(&xt[table->af].mutex);
|
||||
return table;
|
||||
|
||||
@ -1486,19 +1496,25 @@ EXPORT_SYMBOL_GPL(xt_unregister_table);
|
||||
#ifdef CONFIG_PROC_FS
|
||||
static void *xt_table_seq_start(struct seq_file *seq, loff_t *pos)
|
||||
{
|
||||
u8 af = (unsigned long)PDE_DATA(file_inode(seq->file));
|
||||
struct net *net = seq_file_net(seq);
|
||||
u_int8_t af = (unsigned long)PDE_DATA(file_inode(seq->file));
|
||||
struct xt_pernet *xt_net;
|
||||
|
||||
xt_net = net_generic(net, xt_pernet_id);
|
||||
|
||||
mutex_lock(&xt[af].mutex);
|
||||
return seq_list_start(&net->xt.tables[af], *pos);
|
||||
return seq_list_start(&xt_net->tables[af], *pos);
|
||||
}
|
||||
|
||||
static void *xt_table_seq_next(struct seq_file *seq, void *v, loff_t *pos)
|
||||
{
|
||||
u8 af = (unsigned long)PDE_DATA(file_inode(seq->file));
|
||||
struct net *net = seq_file_net(seq);
|
||||
u_int8_t af = (unsigned long)PDE_DATA(file_inode(seq->file));
|
||||
struct xt_pernet *xt_net;
|
||||
|
||||
return seq_list_next(v, &net->xt.tables[af], pos);
|
||||
xt_net = net_generic(net, xt_pernet_id);
|
||||
|
||||
return seq_list_next(v, &xt_net->tables[af], pos);
|
||||
}
|
||||
|
||||
static void xt_table_seq_stop(struct seq_file *seq, void *v)
|
||||
@ -1864,24 +1880,28 @@ EXPORT_SYMBOL_GPL(xt_percpu_counter_free);
|
||||
|
||||
static int __net_init xt_net_init(struct net *net)
|
||||
{
|
||||
struct xt_pernet *xt_net = net_generic(net, xt_pernet_id);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NFPROTO_NUMPROTO; i++)
|
||||
INIT_LIST_HEAD(&net->xt.tables[i]);
|
||||
INIT_LIST_HEAD(&xt_net->tables[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __net_exit xt_net_exit(struct net *net)
|
||||
{
|
||||
struct xt_pernet *xt_net = net_generic(net, xt_pernet_id);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NFPROTO_NUMPROTO; i++)
|
||||
WARN_ON_ONCE(!list_empty(&net->xt.tables[i]));
|
||||
WARN_ON_ONCE(!list_empty(&xt_net->tables[i]));
|
||||
}
|
||||
|
||||
static struct pernet_operations xt_net_ops = {
|
||||
.init = xt_net_init,
|
||||
.exit = xt_net_exit,
|
||||
.id = &xt_pernet_id,
|
||||
.size = sizeof(struct xt_pernet),
|
||||
};
|
||||
|
||||
static int __init xt_init(void)
|
||||
|
@ -108,3 +108,4 @@ MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
|
||||
MODULE_DESCRIPTION("Xtables: IPv4/IPv6 packet logging");
|
||||
MODULE_ALIAS("ipt_LOG");
|
||||
MODULE_ALIAS("ip6t_LOG");
|
||||
MODULE_SOFTDEP("pre: nf_log_syslog");
|
||||
|
@ -79,3 +79,4 @@ static void __exit nflog_tg_exit(void)
|
||||
|
||||
module_init(nflog_tg_init);
|
||||
module_exit(nflog_tg_exit);
|
||||
MODULE_SOFTDEP("pre: nfnetlink_log");
|
||||
|
@ -52,3 +52,4 @@ static void __exit trace_tg_exit(void)
|
||||
|
||||
module_init(trace_tg_init);
|
||||
module_exit(trace_tg_exit);
|
||||
MODULE_SOFTDEP("pre: nf_log_syslog");
|
||||
|
Loading…
Reference in New Issue
Block a user