Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* iptables module for using new netfilter netlink queue
0003  *
0004  * (C) 2005 by Harald Welte <laforge@netfilter.org>
0005  */
0006 
0007 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0008 
0009 #include <linux/module.h>
0010 #include <linux/skbuff.h>
0011 
0012 #include <linux/netfilter.h>
0013 #include <linux/netfilter_arp.h>
0014 #include <linux/netfilter/x_tables.h>
0015 #include <linux/netfilter/xt_NFQUEUE.h>
0016 
0017 #include <net/netfilter/nf_queue.h>
0018 
0019 MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
0020 MODULE_DESCRIPTION("Xtables: packet forwarding to netlink");
0021 MODULE_LICENSE("GPL");
0022 MODULE_ALIAS("ipt_NFQUEUE");
0023 MODULE_ALIAS("ip6t_NFQUEUE");
0024 MODULE_ALIAS("arpt_NFQUEUE");
0025 
0026 static u32 jhash_initval __read_mostly;
0027 
0028 static unsigned int
0029 nfqueue_tg(struct sk_buff *skb, const struct xt_action_param *par)
0030 {
0031     const struct xt_NFQ_info *tinfo = par->targinfo;
0032 
0033     return NF_QUEUE_NR(tinfo->queuenum);
0034 }
0035 
0036 static unsigned int
0037 nfqueue_tg_v1(struct sk_buff *skb, const struct xt_action_param *par)
0038 {
0039     const struct xt_NFQ_info_v1 *info = par->targinfo;
0040     u32 queue = info->queuenum;
0041 
0042     if (info->queues_total > 1) {
0043         queue = nfqueue_hash(skb, queue, info->queues_total,
0044                      xt_family(par), jhash_initval);
0045     }
0046     return NF_QUEUE_NR(queue);
0047 }
0048 
0049 static unsigned int
0050 nfqueue_tg_v2(struct sk_buff *skb, const struct xt_action_param *par)
0051 {
0052     const struct xt_NFQ_info_v2 *info = par->targinfo;
0053     unsigned int ret = nfqueue_tg_v1(skb, par);
0054 
0055     if (info->bypass)
0056         ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
0057     return ret;
0058 }
0059 
0060 static int nfqueue_tg_check(const struct xt_tgchk_param *par)
0061 {
0062     const struct xt_NFQ_info_v3 *info = par->targinfo;
0063     u32 maxid;
0064 
0065     init_hashrandom(&jhash_initval);
0066 
0067     if (info->queues_total == 0) {
0068         pr_info_ratelimited("number of total queues is 0\n");
0069         return -EINVAL;
0070     }
0071     maxid = info->queues_total - 1 + info->queuenum;
0072     if (maxid > 0xffff) {
0073         pr_info_ratelimited("number of queues (%u) out of range (got %u)\n",
0074                     info->queues_total, maxid);
0075         return -ERANGE;
0076     }
0077     if (par->target->revision == 2 && info->flags > 1)
0078         return -EINVAL;
0079     if (par->target->revision == 3 && info->flags & ~NFQ_FLAG_MASK)
0080         return -EINVAL;
0081 
0082     return 0;
0083 }
0084 
0085 static unsigned int
0086 nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)
0087 {
0088     const struct xt_NFQ_info_v3 *info = par->targinfo;
0089     u32 queue = info->queuenum;
0090     int ret;
0091 
0092     if (info->queues_total > 1) {
0093         if (info->flags & NFQ_FLAG_CPU_FANOUT) {
0094             int cpu = smp_processor_id();
0095 
0096             queue = info->queuenum + cpu % info->queues_total;
0097         } else {
0098             queue = nfqueue_hash(skb, queue, info->queues_total,
0099                          xt_family(par), jhash_initval);
0100         }
0101     }
0102 
0103     ret = NF_QUEUE_NR(queue);
0104     if (info->flags & NFQ_FLAG_BYPASS)
0105         ret |= NF_VERDICT_FLAG_QUEUE_BYPASS;
0106 
0107     return ret;
0108 }
0109 
0110 static struct xt_target nfqueue_tg_reg[] __read_mostly = {
0111     {
0112         .name       = "NFQUEUE",
0113         .family     = NFPROTO_UNSPEC,
0114         .target     = nfqueue_tg,
0115         .targetsize = sizeof(struct xt_NFQ_info),
0116         .me     = THIS_MODULE,
0117     },
0118     {
0119         .name       = "NFQUEUE",
0120         .revision   = 1,
0121         .family     = NFPROTO_UNSPEC,
0122         .checkentry = nfqueue_tg_check,
0123         .target     = nfqueue_tg_v1,
0124         .targetsize = sizeof(struct xt_NFQ_info_v1),
0125         .me     = THIS_MODULE,
0126     },
0127     {
0128         .name       = "NFQUEUE",
0129         .revision   = 2,
0130         .family     = NFPROTO_UNSPEC,
0131         .checkentry = nfqueue_tg_check,
0132         .target     = nfqueue_tg_v2,
0133         .targetsize = sizeof(struct xt_NFQ_info_v2),
0134         .me     = THIS_MODULE,
0135     },
0136     {
0137         .name       = "NFQUEUE",
0138         .revision   = 3,
0139         .family     = NFPROTO_UNSPEC,
0140         .checkentry = nfqueue_tg_check,
0141         .target     = nfqueue_tg_v3,
0142         .targetsize = sizeof(struct xt_NFQ_info_v3),
0143         .me     = THIS_MODULE,
0144     },
0145 };
0146 
0147 static int __init nfqueue_tg_init(void)
0148 {
0149     return xt_register_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg));
0150 }
0151 
0152 static void __exit nfqueue_tg_exit(void)
0153 {
0154     xt_unregister_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg));
0155 }
0156 
0157 module_init(nfqueue_tg_init);
0158 module_exit(nfqueue_tg_exit);