From 5afda2d2f256ee0980eda1c9c991037f957d63c5 Mon Sep 17 00:00:00 2001 From: Yangys Date: Fri, 18 Nov 2022 10:10:23 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90quota2log=E3=80=91=E4=BD=BF=E8=83=BD?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Yangys --- net/netfilter/Kconfig | 11 +++++ net/netfilter/xt_quota2.c | 93 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index 74c257b91de9..cb69a1088124 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -1489,6 +1489,17 @@ config NETFILTER_XT_MATCH_QUOTA2 If you want to compile it as a module, say M here and read . If unsure, say `N'. +config NETFILTER_XT_MATCH_QUOTA2_LOG + bool '"quota2" Netfilter LOG support' + depends on NETFILTER_XT_MATCH_QUOTA2 + default n + help + This option allows `quota2' to log ONCE when a quota limit + is passed. It logs via NETLINK using the NETLINK_NFLOG family. + It logs similarly to how ipt_ULOG would without data. + + If unsure, say `N'. + config NETFILTER_XT_MATCH_RATEEST tristate '"rateest" match support' depends on NETFILTER_ADVANCED diff --git a/net/netfilter/xt_quota2.c b/net/netfilter/xt_quota2.c index 6a641005adc7..14b51ee8e1f4 100644 --- a/net/netfilter/xt_quota2.c +++ b/net/netfilter/xt_quota2.c @@ -29,6 +29,35 @@ #include #include +#ifdef CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG +/* For compatibility, these definitions are copied from the + * deprecated header file */ +#define MAC_LEN 80 +#define PREFIX_LEN 32 + +/* Format of the ULOG packets passed through netlink */ +typedef struct ulog_packet_msg { + unsigned long mark; + long timestamp_sec; + long timestamp_usec; + unsigned int hook; + char indev_name[IFNAMSIZ]; + char outdev_name[IFNAMSIZ]; + size_t data_len; + char prefix[PREFIX_LEN]; + unsigned char mac_len; + unsigned char mac[MAC_LEN]; + unsigned char payload[0]; +} ulog_packet_msg_t; + +static int qlog_netlink_event = 112; +module_param_named(event_num, qlog_netlink_event, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(event_num, + "Event number for NETLINK_NFLOG message. 0 disables log." + "111 is what ipt_ULOG uses."); +static struct sock *quota2_log_netlink; +#endif + /** * @lock: lock to protect quota writers from each other */ @@ -61,6 +90,61 @@ module_param_named(perms, quota_list_perms, uint, S_IRUGO | S_IWUSR); module_param_named(uid, quota_list_uid, uint, S_IRUGO | S_IWUSR); module_param_named(gid, quota_list_gid, uint, S_IRUGO | S_IWUSR); +#ifdef CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG +static void quota2_log(unsigned int hookindex, const char *prefix, const struct sk_buff *skb, + const struct net_device *in, const struct net_device *out) +{ + if (!qlog_netlink_event) + return; + + ulog_packet_msg_t *log_packet; + struct sk_buff *log_skb; + size_t size; + struct nlmsghdr *msg_header; + + size = NLMSG_SPACE(sizeof(*log_packet)); + size = max(size, (size_t)NLMSG_GOODSIZE); + log_skb = alloc_skb(size, GFP_ATOMIC); + if (!log_skb) { + pr_err("xt_quota2: cannot alloc skb for log\n"); + return; + } + + msg_header = nlmsg_put(log_skb, 0, 0, qlog_netlink_event, sizeof(*log_packet), 0); + if (!msg_header) { + pr_err("xt_quota2: nlmsg_put failed\n"); + kfree_skb(log_skb); + return; + } + log_packet = nlmsg_data(msg_header); + if (skb->tstamp == 0) + __net_timestamp((struct sk_buff *)skb); + log_packet->data_len = 0; + log_packet->hook = hookindex; + if (prefix != NULL) + strlcpy(log_packet->prefix, prefix, sizeof(log_packet->prefix)); + else + *(log_packet->prefix) = '\0'; + if (in) + strlcpy(log_packet->indev_name, in->name, sizeof(log_packet->indev_name)); + else + log_packet->indev_name[0] = '\0'; + + if (out) + strlcpy(log_packet->outdev_name, out->name, sizeof(log_packet->outdev_name)); + else + log_packet->outdev_name[0] = '\0'; + + NETLINK_CB(log_skb).dst_group = 1; + pr_debug("packing 1 packet to netlink group 1\n"); + netlink_broadcast(quota2_log_netlink, log_skb, 0, 1, GFP_ATOMIC); +} +#else +static void quota2_log(unsigned int hookindex, const char *prefix, const struct sk_buff *skb, + const struct net_device *in, const struct net_device *out) +{ +} +#endif static int quota_proc_show(struct seq_file *m, void *data) { @@ -262,6 +346,9 @@ quota_mt2(const struct sk_buff *skb, struct xt_action_param *par) e->quota -= (q->flags & XT_QUOTA_PACKET) ? 1 : skb->len; ret = !ret; } else { + if (e->quota) { + quota2_log(xt_hooknum(par), q->name, skb, xt_in(par), xt_out(par)); + } /* we do not allow even small packets from now on */ if (!(q->flags & XT_QUOTA_NO_CHANGE)) e->quota = 0; @@ -300,6 +387,12 @@ static int __net_init quota2_net_init(struct net *net) struct quota2_net *quota2_net = quota2_pernet(net); INIT_LIST_HEAD("a2_net->counter_list); +#ifdef CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG + quota2_log_netlink = netlink_kernel_create(&init_net, NETLINK_NFLOG, NULL); + if (!quota2_log_netlink) { + return -ENOMEM; + } +#endif quota2_net->proc_xt_quota = proc_mkdir("xt_quota", net->proc_net); if (quota2_net->proc_xt_quota == NULL) return -EACCES; -- Gitee