Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  "TEE" target extension for Xtables
0004  *  Copyright © Sebastian Claßen, 2007
0005  *  Jan Engelhardt, 2007-2010
0006  *
0007  *  based on ipt_ROUTE.c from Cédric de Launois
0008  *  <delaunois@info.ucl.be>
0009  */
0010 #include <linux/module.h>
0011 #include <linux/skbuff.h>
0012 #include <linux/route.h>
0013 #include <linux/netfilter/x_tables.h>
0014 #include <net/net_namespace.h>
0015 #include <net/netns/generic.h>
0016 #include <net/route.h>
0017 #include <net/netfilter/ipv4/nf_dup_ipv4.h>
0018 #include <net/netfilter/ipv6/nf_dup_ipv6.h>
0019 #include <linux/netfilter/xt_TEE.h>
0020 
0021 struct xt_tee_priv {
0022     struct list_head    list;
0023     struct xt_tee_tginfo    *tginfo;
0024     int         oif;
0025 };
0026 
0027 static unsigned int tee_net_id __read_mostly;
0028 static const union nf_inet_addr tee_zero_address;
0029 
0030 struct tee_net {
0031     struct list_head priv_list;
0032     /* lock protects the priv_list */
0033     struct mutex lock;
0034 };
0035 
0036 static unsigned int
0037 tee_tg4(struct sk_buff *skb, const struct xt_action_param *par)
0038 {
0039     const struct xt_tee_tginfo *info = par->targinfo;
0040     int oif = info->priv ? info->priv->oif : 0;
0041 
0042     nf_dup_ipv4(xt_net(par), skb, xt_hooknum(par), &info->gw.in, oif);
0043 
0044     return XT_CONTINUE;
0045 }
0046 
0047 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
0048 static unsigned int
0049 tee_tg6(struct sk_buff *skb, const struct xt_action_param *par)
0050 {
0051     const struct xt_tee_tginfo *info = par->targinfo;
0052     int oif = info->priv ? info->priv->oif : 0;
0053 
0054     nf_dup_ipv6(xt_net(par), skb, xt_hooknum(par), &info->gw.in6, oif);
0055 
0056     return XT_CONTINUE;
0057 }
0058 #endif
0059 
0060 static int tee_netdev_event(struct notifier_block *this, unsigned long event,
0061                 void *ptr)
0062 {
0063     struct net_device *dev = netdev_notifier_info_to_dev(ptr);
0064     struct net *net = dev_net(dev);
0065     struct tee_net *tn = net_generic(net, tee_net_id);
0066     struct xt_tee_priv *priv;
0067 
0068     mutex_lock(&tn->lock);
0069     list_for_each_entry(priv, &tn->priv_list, list) {
0070         switch (event) {
0071         case NETDEV_REGISTER:
0072             if (!strcmp(dev->name, priv->tginfo->oif))
0073                 priv->oif = dev->ifindex;
0074             break;
0075         case NETDEV_UNREGISTER:
0076             if (dev->ifindex == priv->oif)
0077                 priv->oif = -1;
0078             break;
0079         case NETDEV_CHANGENAME:
0080             if (!strcmp(dev->name, priv->tginfo->oif))
0081                 priv->oif = dev->ifindex;
0082             else if (dev->ifindex == priv->oif)
0083                 priv->oif = -1;
0084             break;
0085         }
0086     }
0087     mutex_unlock(&tn->lock);
0088 
0089     return NOTIFY_DONE;
0090 }
0091 
0092 static int tee_tg_check(const struct xt_tgchk_param *par)
0093 {
0094     struct tee_net *tn = net_generic(par->net, tee_net_id);
0095     struct xt_tee_tginfo *info = par->targinfo;
0096     struct xt_tee_priv *priv;
0097 
0098     /* 0.0.0.0 and :: not allowed */
0099     if (memcmp(&info->gw, &tee_zero_address,
0100            sizeof(tee_zero_address)) == 0)
0101         return -EINVAL;
0102 
0103     if (info->oif[0]) {
0104         struct net_device *dev;
0105 
0106         if (info->oif[sizeof(info->oif)-1] != '\0')
0107             return -EINVAL;
0108 
0109         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
0110         if (priv == NULL)
0111             return -ENOMEM;
0112 
0113         priv->tginfo  = info;
0114         priv->oif     = -1;
0115         info->priv    = priv;
0116 
0117         dev = dev_get_by_name(par->net, info->oif);
0118         if (dev) {
0119             priv->oif = dev->ifindex;
0120             dev_put(dev);
0121         }
0122         mutex_lock(&tn->lock);
0123         list_add(&priv->list, &tn->priv_list);
0124         mutex_unlock(&tn->lock);
0125     } else
0126         info->priv = NULL;
0127 
0128     static_key_slow_inc(&xt_tee_enabled);
0129     return 0;
0130 }
0131 
0132 static void tee_tg_destroy(const struct xt_tgdtor_param *par)
0133 {
0134     struct tee_net *tn = net_generic(par->net, tee_net_id);
0135     struct xt_tee_tginfo *info = par->targinfo;
0136 
0137     if (info->priv) {
0138         mutex_lock(&tn->lock);
0139         list_del(&info->priv->list);
0140         mutex_unlock(&tn->lock);
0141         kfree(info->priv);
0142     }
0143     static_key_slow_dec(&xt_tee_enabled);
0144 }
0145 
0146 static struct xt_target tee_tg_reg[] __read_mostly = {
0147     {
0148         .name       = "TEE",
0149         .revision   = 1,
0150         .family     = NFPROTO_IPV4,
0151         .target     = tee_tg4,
0152         .targetsize = sizeof(struct xt_tee_tginfo),
0153         .usersize   = offsetof(struct xt_tee_tginfo, priv),
0154         .checkentry = tee_tg_check,
0155         .destroy    = tee_tg_destroy,
0156         .me         = THIS_MODULE,
0157     },
0158 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
0159     {
0160         .name       = "TEE",
0161         .revision   = 1,
0162         .family     = NFPROTO_IPV6,
0163         .target     = tee_tg6,
0164         .targetsize = sizeof(struct xt_tee_tginfo),
0165         .usersize   = offsetof(struct xt_tee_tginfo, priv),
0166         .checkentry = tee_tg_check,
0167         .destroy    = tee_tg_destroy,
0168         .me         = THIS_MODULE,
0169     },
0170 #endif
0171 };
0172 
0173 static int __net_init tee_net_init(struct net *net)
0174 {
0175     struct tee_net *tn = net_generic(net, tee_net_id);
0176 
0177     INIT_LIST_HEAD(&tn->priv_list);
0178     mutex_init(&tn->lock);
0179     return 0;
0180 }
0181 
0182 static struct pernet_operations tee_net_ops = {
0183     .init = tee_net_init,
0184     .id   = &tee_net_id,
0185     .size = sizeof(struct tee_net),
0186 };
0187 
0188 static struct notifier_block tee_netdev_notifier = {
0189     .notifier_call = tee_netdev_event,
0190 };
0191 
0192 static int __init tee_tg_init(void)
0193 {
0194     int ret;
0195 
0196     ret = register_pernet_subsys(&tee_net_ops);
0197     if (ret < 0)
0198         return ret;
0199 
0200     ret = xt_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg));
0201     if (ret < 0)
0202         goto cleanup_subsys;
0203 
0204     ret = register_netdevice_notifier(&tee_netdev_notifier);
0205     if (ret < 0)
0206         goto unregister_targets;
0207 
0208     return 0;
0209 
0210 unregister_targets:
0211     xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg));
0212 cleanup_subsys:
0213     unregister_pernet_subsys(&tee_net_ops);
0214     return ret;
0215 }
0216 
0217 static void __exit tee_tg_exit(void)
0218 {
0219     unregister_netdevice_notifier(&tee_netdev_notifier);
0220     xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg));
0221     unregister_pernet_subsys(&tee_net_ops);
0222 }
0223 
0224 module_init(tee_tg_init);
0225 module_exit(tee_tg_exit);
0226 MODULE_AUTHOR("Sebastian Claßen <sebastian.classen@freenet.ag>");
0227 MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
0228 MODULE_DESCRIPTION("Xtables: Reroute packet copy");
0229 MODULE_LICENSE("GPL");
0230 MODULE_ALIAS("ipt_TEE");
0231 MODULE_ALIAS("ip6t_TEE");