Added _ADD and _REMOVE commands to nf_tables_api.c in order to use the nf_tables interface to add 'osf' signatures in nft. Signed-off-by: Fernando Fernandez Mancera <ffmancera@xxxxxxxxxx> --- include/net/netfilter/nf_tables_core.h | 2 + include/uapi/linux/netfilter/nf_osf.h | 8 ++ include/uapi/linux/netfilter/nf_tables.h | 14 +++ include/uapi/linux/netfilter/xt_osf.h | 7 +- net/netfilter/nf_tables_api.c | 110 +++++++++++++++++++++++ net/netfilter/nft_osf.c | 1 + 6 files changed, 136 insertions(+), 6 deletions(-) diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h index e0c0c2558ec4..ee7eabc8d3e1 100644 --- a/include/net/netfilter/nf_tables_core.h +++ b/include/net/netfilter/nf_tables_core.h @@ -65,4 +65,6 @@ extern const struct nft_expr_ops nft_payload_fast_ops; extern struct static_key_false nft_counters_enabled; extern struct static_key_false nft_trace_enabled; +extern struct list_head nft_osf_fingers[2]; + #endif /* _NET_NF_TABLES_CORE_H */ diff --git a/include/uapi/linux/netfilter/nf_osf.h b/include/uapi/linux/netfilter/nf_osf.h index 79882b2f7f8e..35352c1cd994 100644 --- a/include/uapi/linux/netfilter/nf_osf.h +++ b/include/uapi/linux/netfilter/nf_osf.h @@ -2,6 +2,8 @@ #define _NF_OSF_H #include <linux/types.h> +#include <linux/ip.h> +#include <linux/tcp.h> #define MAXGENRELEN 32 @@ -90,4 +92,10 @@ enum iana_options { OSFOPT_EMPTY = 255, }; +enum nf_osf_attr_type { + OSF_ATTR_UNSPEC, + OSF_ATTR_FINGER, + OSF_ATTR_MAX, +}; + #endif /* _NF_OSF_H */ diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index c9bf74b94f37..beffa2010b20 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -9,6 +9,8 @@ #define NFT_OBJ_MAXNAMELEN NFT_NAME_MAXLEN #define NFT_USERDATA_MAXLEN 256 +#define OSF_GENRE_SIZE 32 + /** * enum nft_registers - nf_tables registers * @@ -122,6 +124,8 @@ enum nf_tables_msg_types { NFT_MSG_NEWFLOWTABLE, NFT_MSG_GETFLOWTABLE, NFT_MSG_DELFLOWTABLE, + NFT_MSG_NEWOSF, + NFT_MSG_DELOSF, NFT_MSG_MAX, }; @@ -1461,6 +1465,16 @@ enum nft_flowtable_hook_attributes { }; #define NFTA_FLOWTABLE_HOOK_MAX (__NFTA_FLOWTABLE_HOOK_MAX - 1) +enum nft_osf_attributes { + NFTA_OSF_UNSPEC, + NFTA_OSF_GENRE, + NFTA_OSF_FLAGS, + NFTA_OSF_LOGLEVEL, + NFTA_OSF_TTL, + __NFTA_OSF_MAX, +}; +#define NFTA_OSF_MAX (__NFTA_OSF_MAX - 1) + /** * enum nft_device_attributes - nf_tables device netlink attributes * diff --git a/include/uapi/linux/netfilter/xt_osf.h b/include/uapi/linux/netfilter/xt_osf.h index 2f5d4e6d0434..b7c0f93fe9d4 100644 --- a/include/uapi/linux/netfilter/xt_osf.h +++ b/include/uapi/linux/netfilter/xt_osf.h @@ -51,6 +51,7 @@ #define xt_osf_finger nf_osf_finger #define xt_osf_nlmsg nf_osf_nlmsg +#define xt_osf_attr_type nf_osf_attr_type /* * Add/remove fingerprint from the kernel. */ @@ -60,10 +61,4 @@ enum xt_osf_msg_types { OSF_MSG_MAX, }; -enum xt_osf_attr_type { - OSF_ATTR_UNSPEC, - OSF_ATTR_FINGER, - OSF_ATTR_MAX, -}; - #endif /* _XT_OSF_H */ diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index ca4c4d994ddb..1783d8ef658c 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -17,6 +17,7 @@ #include <linux/netfilter.h> #include <linux/netfilter/nfnetlink.h> #include <linux/netfilter/nf_tables.h> +#include <linux/netfilter/nf_osf.h> #include <net/netfilter/nf_flow_table.h> #include <net/netfilter/nf_tables_core.h> #include <net/netfilter/nf_tables.h> @@ -26,6 +27,7 @@ static LIST_HEAD(nf_tables_expressions); static LIST_HEAD(nf_tables_objects); static LIST_HEAD(nf_tables_flowtables); + static u64 table_handle; enum { @@ -5851,6 +5853,8 @@ static int nf_tables_flowtable_event(struct notifier_block *this, return NOTIFY_DONE; } + + static struct notifier_block nf_tables_flowtable_notifier = { .notifier_call = nf_tables_flowtable_event, }; @@ -5908,6 +5912,102 @@ static int nf_tables_getgen(struct net *net, struct sock *nlsk, return err; } +struct list_head nft_osf_fingers[2]; +EXPORT_SYMBOL_GPL(nft_osf_fingers); + +static int nf_tables_newosf(struct net *net, struct sock *ctnl, + struct sk_buff *skb, const struct nlmsghdr *nlh, + const struct nlattr * const osf_attrs[], + struct netlink_ext_ack *extack) +{ + struct nf_osf_user_finger *f; + struct nf_osf_finger *kf = NULL, *sf; + int err = 0; + int i = 0; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (!osf_attrs[OSF_ATTR_FINGER]) + return -EINVAL; + + if (!(nlh->nlmsg_flags & NLM_F_CREATE)) + return -EINVAL; + + f = nla_data(osf_attrs[OSF_ATTR_FINGER]); + + kf = kmalloc(sizeof(struct nf_osf_finger), GFP_KERNEL); + if (!kf) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(nft_osf_fingers); ++i) + INIT_LIST_HEAD(&nft_osf_fingers[i]); + + memcpy(&kf->finger, f, sizeof(struct nf_osf_user_finger)); + + list_for_each_entry(sf, &nft_osf_fingers[!!f->df], finger_entry) { + if (memcmp(&sf->finger, f, sizeof(struct nf_osf_user_finger))) + continue; + + kfree(kf); + kf = NULL; + + if (nlh->nlmsg_flags & NLM_F_EXCL) + err = -EEXIST; + break; + } + + /* + * We are protected by nfnl mutex. + */ + if (kf) + list_add_tail_rcu(&kf->finger_entry, &nft_osf_fingers[!!f->df]); + + return err; +} + +static int nf_tables_delosf(struct net *net, struct sock *ctnl, + struct sk_buff *skb, + const struct nlmsghdr *nlh, + const struct nlattr * const osf_attrs[], + struct netlink_ext_ack *extack) +{ + struct nf_osf_user_finger *f; + struct nf_osf_finger *sf; + int err = -ENOENT; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (!osf_attrs[OSF_ATTR_FINGER]) + return -EINVAL; + + f = nla_data(osf_attrs[OSF_ATTR_FINGER]); + + list_for_each_entry(sf, &nft_osf_fingers[!!f->df], finger_entry) { + if (memcmp(&sf->finger, f, sizeof(struct nf_osf_user_finger))) + continue; + + /* + * We are protected by nfnl mutex. + */ + list_del_rcu(&sf->finger_entry); + kfree_rcu(sf, rcu_head); + + err = 0; + break; + } + + return err; +} + +static const struct nla_policy nft_osf_policy[NFTA_OSF_MAX + 1] = { + [NFTA_OSF_GENRE] = { .type = NLA_STRING, .len = OSF_GENRE_SIZE }, + [NFTA_OSF_FLAGS] = { .type = NLA_U32 }, + [NFTA_OSF_LOGLEVEL] = { .type = NLA_U32 }, + [NFTA_OSF_TTL] = { .type = NLA_U32 }, +}; + static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { [NFT_MSG_NEWTABLE] = { .call_batch = nf_tables_newtable, @@ -6022,6 +6122,16 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .attr_count = NFTA_FLOWTABLE_MAX, .policy = nft_flowtable_policy, }, + [NFT_MSG_NEWOSF] = { + .call_batch = nf_tables_newosf, + .attr_count = NFTA_OSF_MAX, + .policy = nft_osf_policy, + }, + [NFT_MSG_DELOSF] = { + .call_batch = nf_tables_delosf, + .attr_count = NFTA_OSF_MAX, + .policy = nft_osf_policy, + }, }; static int nf_tables_validate(struct net *net) diff --git a/net/netfilter/nft_osf.c b/net/netfilter/nft_osf.c index 30c503f2bf53..cf8a38b052ad 100644 --- a/net/netfilter/nft_osf.c +++ b/net/netfilter/nft_osf.c @@ -54,6 +54,7 @@ static int nft_osf_init(const struct nft_ctx *ctx, return -EINVAL; priv->ttl = ntohl(nla_get_be32(tb[NFTA_OSF_TTL])); priv->len = strlen(priv->genre); + return 0; } -- 2.18.0 -- To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html