root/net/bridge/netfilter/nft_meta_bridge.c

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

DEFINITIONS

This source file includes following definitions.
  1. nft_meta_get_bridge
  2. nft_meta_bridge_get_eval
  3. nft_meta_bridge_get_init
  4. nft_meta_bridge_select_ops
  5. nft_meta_bridge_module_init
  6. nft_meta_bridge_module_exit

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <linux/kernel.h>
   3 #include <linux/init.h>
   4 #include <linux/module.h>
   5 #include <linux/netlink.h>
   6 #include <linux/netfilter.h>
   7 #include <linux/netfilter/nf_tables.h>
   8 #include <net/netfilter/nf_tables.h>
   9 #include <net/netfilter/nft_meta.h>
  10 #include <linux/if_bridge.h>
  11 
  12 static const struct net_device *
  13 nft_meta_get_bridge(const struct net_device *dev)
  14 {
  15         if (dev && netif_is_bridge_port(dev))
  16                 return netdev_master_upper_dev_get_rcu((struct net_device *)dev);
  17 
  18         return NULL;
  19 }
  20 
  21 static void nft_meta_bridge_get_eval(const struct nft_expr *expr,
  22                                      struct nft_regs *regs,
  23                                      const struct nft_pktinfo *pkt)
  24 {
  25         const struct nft_meta *priv = nft_expr_priv(expr);
  26         const struct net_device *in = nft_in(pkt), *out = nft_out(pkt);
  27         u32 *dest = &regs->data[priv->dreg];
  28         const struct net_device *br_dev;
  29 
  30         switch (priv->key) {
  31         case NFT_META_BRI_IIFNAME:
  32                 br_dev = nft_meta_get_bridge(in);
  33                 break;
  34         case NFT_META_BRI_OIFNAME:
  35                 br_dev = nft_meta_get_bridge(out);
  36                 break;
  37         case NFT_META_BRI_IIFPVID: {
  38                 u16 p_pvid;
  39 
  40                 br_dev = nft_meta_get_bridge(in);
  41                 if (!br_dev || !br_vlan_enabled(br_dev))
  42                         goto err;
  43 
  44                 br_vlan_get_pvid_rcu(in, &p_pvid);
  45                 nft_reg_store16(dest, p_pvid);
  46                 return;
  47         }
  48         case NFT_META_BRI_IIFVPROTO: {
  49                 u16 p_proto;
  50 
  51                 br_dev = nft_meta_get_bridge(in);
  52                 if (!br_dev || !br_vlan_enabled(br_dev))
  53                         goto err;
  54 
  55                 br_vlan_get_proto(br_dev, &p_proto);
  56                 nft_reg_store16(dest, htons(p_proto));
  57                 return;
  58         }
  59         default:
  60                 return nft_meta_get_eval(expr, regs, pkt);
  61         }
  62 
  63         strncpy((char *)dest, br_dev ? br_dev->name : "", IFNAMSIZ);
  64         return;
  65 err:
  66         regs->verdict.code = NFT_BREAK;
  67 }
  68 
  69 static int nft_meta_bridge_get_init(const struct nft_ctx *ctx,
  70                                     const struct nft_expr *expr,
  71                                     const struct nlattr * const tb[])
  72 {
  73         struct nft_meta *priv = nft_expr_priv(expr);
  74         unsigned int len;
  75 
  76         priv->key = ntohl(nla_get_be32(tb[NFTA_META_KEY]));
  77         switch (priv->key) {
  78         case NFT_META_BRI_IIFNAME:
  79         case NFT_META_BRI_OIFNAME:
  80                 len = IFNAMSIZ;
  81                 break;
  82         case NFT_META_BRI_IIFPVID:
  83         case NFT_META_BRI_IIFVPROTO:
  84                 len = sizeof(u16);
  85                 break;
  86         default:
  87                 return nft_meta_get_init(ctx, expr, tb);
  88         }
  89 
  90         priv->dreg = nft_parse_register(tb[NFTA_META_DREG]);
  91         return nft_validate_register_store(ctx, priv->dreg, NULL,
  92                                            NFT_DATA_VALUE, len);
  93 }
  94 
  95 static struct nft_expr_type nft_meta_bridge_type;
  96 static const struct nft_expr_ops nft_meta_bridge_get_ops = {
  97         .type           = &nft_meta_bridge_type,
  98         .size           = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
  99         .eval           = nft_meta_bridge_get_eval,
 100         .init           = nft_meta_bridge_get_init,
 101         .dump           = nft_meta_get_dump,
 102 };
 103 
 104 static const struct nft_expr_ops nft_meta_bridge_set_ops = {
 105         .type           = &nft_meta_bridge_type,
 106         .size           = NFT_EXPR_SIZE(sizeof(struct nft_meta)),
 107         .eval           = nft_meta_set_eval,
 108         .init           = nft_meta_set_init,
 109         .destroy        = nft_meta_set_destroy,
 110         .dump           = nft_meta_set_dump,
 111         .validate       = nft_meta_set_validate,
 112 };
 113 
 114 static const struct nft_expr_ops *
 115 nft_meta_bridge_select_ops(const struct nft_ctx *ctx,
 116                            const struct nlattr * const tb[])
 117 {
 118         if (tb[NFTA_META_KEY] == NULL)
 119                 return ERR_PTR(-EINVAL);
 120 
 121         if (tb[NFTA_META_DREG] && tb[NFTA_META_SREG])
 122                 return ERR_PTR(-EINVAL);
 123 
 124         if (tb[NFTA_META_DREG])
 125                 return &nft_meta_bridge_get_ops;
 126 
 127         if (tb[NFTA_META_SREG])
 128                 return &nft_meta_bridge_set_ops;
 129 
 130         return ERR_PTR(-EINVAL);
 131 }
 132 
 133 static struct nft_expr_type nft_meta_bridge_type __read_mostly = {
 134         .family         = NFPROTO_BRIDGE,
 135         .name           = "meta",
 136         .select_ops     = nft_meta_bridge_select_ops,
 137         .policy         = nft_meta_policy,
 138         .maxattr        = NFTA_META_MAX,
 139         .owner          = THIS_MODULE,
 140 };
 141 
 142 static int __init nft_meta_bridge_module_init(void)
 143 {
 144         return nft_register_expr(&nft_meta_bridge_type);
 145 }
 146 
 147 static void __exit nft_meta_bridge_module_exit(void)
 148 {
 149         nft_unregister_expr(&nft_meta_bridge_type);
 150 }
 151 
 152 module_init(nft_meta_bridge_module_init);
 153 module_exit(nft_meta_bridge_module_exit);
 154 
 155 MODULE_LICENSE("GPL");
 156 MODULE_AUTHOR("wenxu <wenxu@ucloud.cn>");
 157 MODULE_ALIAS_NFT_AF_EXPR(AF_BRIDGE, "meta");

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