root/net/netfilter/xt_TEE.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tee_tg4
  2. tee_tg6
  3. tee_netdev_event
  4. tee_tg_check
  5. tee_tg_destroy
  6. tee_net_init
  7. tee_tg_init
  8. tee_tg_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *      "TEE" target extension for Xtables
   4  *      Copyright © Sebastian Claßen, 2007
   5  *      Jan Engelhardt, 2007-2010
   6  *
   7  *      based on ipt_ROUTE.c from Cédric de Launois
   8  *      <delaunois@info.ucl.be>
   9  */
  10 #include <linux/module.h>
  11 #include <linux/skbuff.h>
  12 #include <linux/route.h>
  13 #include <linux/netfilter/x_tables.h>
  14 #include <net/net_namespace.h>
  15 #include <net/netns/generic.h>
  16 #include <net/route.h>
  17 #include <net/netfilter/ipv4/nf_dup_ipv4.h>
  18 #include <net/netfilter/ipv6/nf_dup_ipv6.h>
  19 #include <linux/netfilter/xt_TEE.h>
  20 
  21 struct xt_tee_priv {
  22         struct list_head        list;
  23         struct xt_tee_tginfo    *tginfo;
  24         int                     oif;
  25 };
  26 
  27 static unsigned int tee_net_id __read_mostly;
  28 static const union nf_inet_addr tee_zero_address;
  29 
  30 struct tee_net {
  31         struct list_head priv_list;
  32         /* lock protects the priv_list */
  33         struct mutex lock;
  34 };
  35 
  36 static unsigned int
  37 tee_tg4(struct sk_buff *skb, const struct xt_action_param *par)
  38 {
  39         const struct xt_tee_tginfo *info = par->targinfo;
  40         int oif = info->priv ? info->priv->oif : 0;
  41 
  42         nf_dup_ipv4(xt_net(par), skb, xt_hooknum(par), &info->gw.in, oif);
  43 
  44         return XT_CONTINUE;
  45 }
  46 
  47 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
  48 static unsigned int
  49 tee_tg6(struct sk_buff *skb, const struct xt_action_param *par)
  50 {
  51         const struct xt_tee_tginfo *info = par->targinfo;
  52         int oif = info->priv ? info->priv->oif : 0;
  53 
  54         nf_dup_ipv6(xt_net(par), skb, xt_hooknum(par), &info->gw.in6, oif);
  55 
  56         return XT_CONTINUE;
  57 }
  58 #endif
  59 
  60 static int tee_netdev_event(struct notifier_block *this, unsigned long event,
  61                             void *ptr)
  62 {
  63         struct net_device *dev = netdev_notifier_info_to_dev(ptr);
  64         struct net *net = dev_net(dev);
  65         struct tee_net *tn = net_generic(net, tee_net_id);
  66         struct xt_tee_priv *priv;
  67 
  68         mutex_lock(&tn->lock);
  69         list_for_each_entry(priv, &tn->priv_list, list) {
  70                 switch (event) {
  71                 case NETDEV_REGISTER:
  72                         if (!strcmp(dev->name, priv->tginfo->oif))
  73                                 priv->oif = dev->ifindex;
  74                         break;
  75                 case NETDEV_UNREGISTER:
  76                         if (dev->ifindex == priv->oif)
  77                                 priv->oif = -1;
  78                         break;
  79                 case NETDEV_CHANGENAME:
  80                         if (!strcmp(dev->name, priv->tginfo->oif))
  81                                 priv->oif = dev->ifindex;
  82                         else if (dev->ifindex == priv->oif)
  83                                 priv->oif = -1;
  84                         break;
  85                 }
  86         }
  87         mutex_unlock(&tn->lock);
  88 
  89         return NOTIFY_DONE;
  90 }
  91 
  92 static int tee_tg_check(const struct xt_tgchk_param *par)
  93 {
  94         struct tee_net *tn = net_generic(par->net, tee_net_id);
  95         struct xt_tee_tginfo *info = par->targinfo;
  96         struct xt_tee_priv *priv;
  97 
  98         /* 0.0.0.0 and :: not allowed */
  99         if (memcmp(&info->gw, &tee_zero_address,
 100                    sizeof(tee_zero_address)) == 0)
 101                 return -EINVAL;
 102 
 103         if (info->oif[0]) {
 104                 struct net_device *dev;
 105 
 106                 if (info->oif[sizeof(info->oif)-1] != '\0')
 107                         return -EINVAL;
 108 
 109                 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 110                 if (priv == NULL)
 111                         return -ENOMEM;
 112 
 113                 priv->tginfo  = info;
 114                 priv->oif     = -1;
 115                 info->priv    = priv;
 116 
 117                 dev = dev_get_by_name(par->net, info->oif);
 118                 if (dev) {
 119                         priv->oif = dev->ifindex;
 120                         dev_put(dev);
 121                 }
 122                 mutex_lock(&tn->lock);
 123                 list_add(&priv->list, &tn->priv_list);
 124                 mutex_unlock(&tn->lock);
 125         } else
 126                 info->priv = NULL;
 127 
 128         static_key_slow_inc(&xt_tee_enabled);
 129         return 0;
 130 }
 131 
 132 static void tee_tg_destroy(const struct xt_tgdtor_param *par)
 133 {
 134         struct tee_net *tn = net_generic(par->net, tee_net_id);
 135         struct xt_tee_tginfo *info = par->targinfo;
 136 
 137         if (info->priv) {
 138                 mutex_lock(&tn->lock);
 139                 list_del(&info->priv->list);
 140                 mutex_unlock(&tn->lock);
 141                 kfree(info->priv);
 142         }
 143         static_key_slow_dec(&xt_tee_enabled);
 144 }
 145 
 146 static struct xt_target tee_tg_reg[] __read_mostly = {
 147         {
 148                 .name       = "TEE",
 149                 .revision   = 1,
 150                 .family     = NFPROTO_IPV4,
 151                 .target     = tee_tg4,
 152                 .targetsize = sizeof(struct xt_tee_tginfo),
 153                 .usersize   = offsetof(struct xt_tee_tginfo, priv),
 154                 .checkentry = tee_tg_check,
 155                 .destroy    = tee_tg_destroy,
 156                 .me         = THIS_MODULE,
 157         },
 158 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
 159         {
 160                 .name       = "TEE",
 161                 .revision   = 1,
 162                 .family     = NFPROTO_IPV6,
 163                 .target     = tee_tg6,
 164                 .targetsize = sizeof(struct xt_tee_tginfo),
 165                 .usersize   = offsetof(struct xt_tee_tginfo, priv),
 166                 .checkentry = tee_tg_check,
 167                 .destroy    = tee_tg_destroy,
 168                 .me         = THIS_MODULE,
 169         },
 170 #endif
 171 };
 172 
 173 static int __net_init tee_net_init(struct net *net)
 174 {
 175         struct tee_net *tn = net_generic(net, tee_net_id);
 176 
 177         INIT_LIST_HEAD(&tn->priv_list);
 178         mutex_init(&tn->lock);
 179         return 0;
 180 }
 181 
 182 static struct pernet_operations tee_net_ops = {
 183         .init = tee_net_init,
 184         .id   = &tee_net_id,
 185         .size = sizeof(struct tee_net),
 186 };
 187 
 188 static struct notifier_block tee_netdev_notifier = {
 189         .notifier_call = tee_netdev_event,
 190 };
 191 
 192 static int __init tee_tg_init(void)
 193 {
 194         int ret;
 195 
 196         ret = register_pernet_subsys(&tee_net_ops);
 197         if (ret < 0)
 198                 return ret;
 199 
 200         ret = xt_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg));
 201         if (ret < 0)
 202                 goto cleanup_subsys;
 203 
 204         ret = register_netdevice_notifier(&tee_netdev_notifier);
 205         if (ret < 0)
 206                 goto unregister_targets;
 207 
 208         return 0;
 209 
 210 unregister_targets:
 211         xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg));
 212 cleanup_subsys:
 213         unregister_pernet_subsys(&tee_net_ops);
 214         return ret;
 215 }
 216 
 217 static void __exit tee_tg_exit(void)
 218 {
 219         unregister_netdevice_notifier(&tee_netdev_notifier);
 220         xt_unregister_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg));
 221         unregister_pernet_subsys(&tee_net_ops);
 222 }
 223 
 224 module_init(tee_tg_init);
 225 module_exit(tee_tg_exit);
 226 MODULE_AUTHOR("Sebastian Claßen <sebastian.classen@freenet.ag>");
 227 MODULE_AUTHOR("Jan Engelhardt <jengelh@medozas.de>");
 228 MODULE_DESCRIPTION("Xtables: Reroute packet copy");
 229 MODULE_LICENSE("GPL");
 230 MODULE_ALIAS("ipt_TEE");
 231 MODULE_ALIAS("ip6t_TEE");

/* [<][>][^][v][top][bottom][index][help] */