root/net/netfilter/xt_connmark.c

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

DEFINITIONS

This source file includes following definitions.
  1. connmark_tg_shift
  2. connmark_tg
  3. connmark_tg_v2
  4. connmark_tg_check
  5. connmark_tg_destroy
  6. connmark_mt
  7. connmark_mt_check
  8. connmark_mt_destroy
  9. connmark_mt_init
  10. connmark_mt_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  *      xt_connmark - Netfilter module to operate on connection marks
   4  *
   5  *      Copyright (C) 2002,2004 MARA Systems AB <http://www.marasystems.com>
   6  *      by Henrik Nordstrom <hno@marasystems.com>
   7  *      Copyright © CC Computer Consultants GmbH, 2007 - 2008
   8  *      Jan Engelhardt <jengelh@medozas.de>
   9  */
  10 
  11 #include <linux/module.h>
  12 #include <linux/skbuff.h>
  13 #include <net/netfilter/nf_conntrack.h>
  14 #include <net/netfilter/nf_conntrack_ecache.h>
  15 #include <linux/netfilter/x_tables.h>
  16 #include <linux/netfilter/xt_connmark.h>
  17 
  18 MODULE_AUTHOR("Henrik Nordstrom <hno@marasystems.com>");
  19 MODULE_DESCRIPTION("Xtables: connection mark operations");
  20 MODULE_LICENSE("GPL");
  21 MODULE_ALIAS("ipt_CONNMARK");
  22 MODULE_ALIAS("ip6t_CONNMARK");
  23 MODULE_ALIAS("ipt_connmark");
  24 MODULE_ALIAS("ip6t_connmark");
  25 
  26 static unsigned int
  27 connmark_tg_shift(struct sk_buff *skb, const struct xt_connmark_tginfo2 *info)
  28 {
  29         enum ip_conntrack_info ctinfo;
  30         u_int32_t new_targetmark;
  31         struct nf_conn *ct;
  32         u_int32_t newmark;
  33 
  34         ct = nf_ct_get(skb, &ctinfo);
  35         if (ct == NULL)
  36                 return XT_CONTINUE;
  37 
  38         switch (info->mode) {
  39         case XT_CONNMARK_SET:
  40                 newmark = (ct->mark & ~info->ctmask) ^ info->ctmark;
  41                 if (info->shift_dir == D_SHIFT_RIGHT)
  42                         newmark >>= info->shift_bits;
  43                 else
  44                         newmark <<= info->shift_bits;
  45 
  46                 if (ct->mark != newmark) {
  47                         ct->mark = newmark;
  48                         nf_conntrack_event_cache(IPCT_MARK, ct);
  49                 }
  50                 break;
  51         case XT_CONNMARK_SAVE:
  52                 new_targetmark = (skb->mark & info->nfmask);
  53                 if (info->shift_dir == D_SHIFT_RIGHT)
  54                         new_targetmark >>= info->shift_bits;
  55                 else
  56                         new_targetmark <<= info->shift_bits;
  57 
  58                 newmark = (ct->mark & ~info->ctmask) ^
  59                           new_targetmark;
  60                 if (ct->mark != newmark) {
  61                         ct->mark = newmark;
  62                         nf_conntrack_event_cache(IPCT_MARK, ct);
  63                 }
  64                 break;
  65         case XT_CONNMARK_RESTORE:
  66                 new_targetmark = (ct->mark & info->ctmask);
  67                 if (info->shift_dir == D_SHIFT_RIGHT)
  68                         new_targetmark >>= info->shift_bits;
  69                 else
  70                         new_targetmark <<= info->shift_bits;
  71 
  72                 newmark = (skb->mark & ~info->nfmask) ^
  73                           new_targetmark;
  74                 skb->mark = newmark;
  75                 break;
  76         }
  77         return XT_CONTINUE;
  78 }
  79 
  80 static unsigned int
  81 connmark_tg(struct sk_buff *skb, const struct xt_action_param *par)
  82 {
  83         const struct xt_connmark_tginfo1 *info = par->targinfo;
  84         const struct xt_connmark_tginfo2 info2 = {
  85                 .ctmark = info->ctmark,
  86                 .ctmask = info->ctmask,
  87                 .nfmask = info->nfmask,
  88                 .mode   = info->mode,
  89         };
  90 
  91         return connmark_tg_shift(skb, &info2);
  92 }
  93 
  94 static unsigned int
  95 connmark_tg_v2(struct sk_buff *skb, const struct xt_action_param *par)
  96 {
  97         const struct xt_connmark_tginfo2 *info = par->targinfo;
  98 
  99         return connmark_tg_shift(skb, info);
 100 }
 101 
 102 static int connmark_tg_check(const struct xt_tgchk_param *par)
 103 {
 104         int ret;
 105 
 106         ret = nf_ct_netns_get(par->net, par->family);
 107         if (ret < 0)
 108                 pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
 109                                     par->family);
 110         return ret;
 111 }
 112 
 113 static void connmark_tg_destroy(const struct xt_tgdtor_param *par)
 114 {
 115         nf_ct_netns_put(par->net, par->family);
 116 }
 117 
 118 static bool
 119 connmark_mt(const struct sk_buff *skb, struct xt_action_param *par)
 120 {
 121         const struct xt_connmark_mtinfo1 *info = par->matchinfo;
 122         enum ip_conntrack_info ctinfo;
 123         const struct nf_conn *ct;
 124 
 125         ct = nf_ct_get(skb, &ctinfo);
 126         if (ct == NULL)
 127                 return false;
 128 
 129         return ((ct->mark & info->mask) == info->mark) ^ info->invert;
 130 }
 131 
 132 static int connmark_mt_check(const struct xt_mtchk_param *par)
 133 {
 134         int ret;
 135 
 136         ret = nf_ct_netns_get(par->net, par->family);
 137         if (ret < 0)
 138                 pr_info_ratelimited("cannot load conntrack support for proto=%u\n",
 139                                     par->family);
 140         return ret;
 141 }
 142 
 143 static void connmark_mt_destroy(const struct xt_mtdtor_param *par)
 144 {
 145         nf_ct_netns_put(par->net, par->family);
 146 }
 147 
 148 static struct xt_target connmark_tg_reg[] __read_mostly = {
 149         {
 150                 .name           = "CONNMARK",
 151                 .revision       = 1,
 152                 .family         = NFPROTO_UNSPEC,
 153                 .checkentry     = connmark_tg_check,
 154                 .target         = connmark_tg,
 155                 .targetsize     = sizeof(struct xt_connmark_tginfo1),
 156                 .destroy        = connmark_tg_destroy,
 157                 .me             = THIS_MODULE,
 158         },
 159         {
 160                 .name           = "CONNMARK",
 161                 .revision       = 2,
 162                 .family         = NFPROTO_UNSPEC,
 163                 .checkentry     = connmark_tg_check,
 164                 .target         = connmark_tg_v2,
 165                 .targetsize     = sizeof(struct xt_connmark_tginfo2),
 166                 .destroy        = connmark_tg_destroy,
 167                 .me             = THIS_MODULE,
 168         }
 169 };
 170 
 171 static struct xt_match connmark_mt_reg __read_mostly = {
 172         .name           = "connmark",
 173         .revision       = 1,
 174         .family         = NFPROTO_UNSPEC,
 175         .checkentry     = connmark_mt_check,
 176         .match          = connmark_mt,
 177         .matchsize      = sizeof(struct xt_connmark_mtinfo1),
 178         .destroy        = connmark_mt_destroy,
 179         .me             = THIS_MODULE,
 180 };
 181 
 182 static int __init connmark_mt_init(void)
 183 {
 184         int ret;
 185 
 186         ret = xt_register_targets(connmark_tg_reg,
 187                                   ARRAY_SIZE(connmark_tg_reg));
 188         if (ret < 0)
 189                 return ret;
 190         ret = xt_register_match(&connmark_mt_reg);
 191         if (ret < 0) {
 192                 xt_unregister_targets(connmark_tg_reg,
 193                                       ARRAY_SIZE(connmark_tg_reg));
 194                 return ret;
 195         }
 196         return 0;
 197 }
 198 
 199 static void __exit connmark_mt_exit(void)
 200 {
 201         xt_unregister_match(&connmark_mt_reg);
 202         xt_unregister_targets(connmark_tg_reg, ARRAY_SIZE(connmark_tg_reg));
 203 }
 204 
 205 module_init(connmark_mt_init);
 206 module_exit(connmark_mt_exit);

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