root/net/netfilter/nf_conntrack_labels.c

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

DEFINITIONS

This source file includes following definitions.
  1. replace_u32
  2. nf_connlabels_replace
  3. nf_connlabels_get
  4. nf_connlabels_put
  5. nf_conntrack_labels_init
  6. nf_conntrack_labels_fini

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * test/set flag bits stored in conntrack extension area.
   4  *
   5  * (C) 2013 Astaro GmbH & Co KG
   6  */
   7 
   8 #include <linux/export.h>
   9 #include <linux/types.h>
  10 
  11 #include <net/netfilter/nf_conntrack_ecache.h>
  12 #include <net/netfilter/nf_conntrack_labels.h>
  13 
  14 static DEFINE_SPINLOCK(nf_connlabels_lock);
  15 
  16 static int replace_u32(u32 *address, u32 mask, u32 new)
  17 {
  18         u32 old, tmp;
  19 
  20         do {
  21                 old = *address;
  22                 tmp = (old & mask) ^ new;
  23                 if (old == tmp)
  24                         return 0;
  25         } while (cmpxchg(address, old, tmp) != old);
  26 
  27         return 1;
  28 }
  29 
  30 int nf_connlabels_replace(struct nf_conn *ct,
  31                           const u32 *data,
  32                           const u32 *mask, unsigned int words32)
  33 {
  34         struct nf_conn_labels *labels;
  35         unsigned int size, i;
  36         int changed = 0;
  37         u32 *dst;
  38 
  39         labels = nf_ct_labels_find(ct);
  40         if (!labels)
  41                 return -ENOSPC;
  42 
  43         size = sizeof(labels->bits);
  44         if (size < (words32 * sizeof(u32)))
  45                 words32 = size / sizeof(u32);
  46 
  47         dst = (u32 *) labels->bits;
  48         for (i = 0; i < words32; i++)
  49                 changed |= replace_u32(&dst[i], mask ? ~mask[i] : 0, data[i]);
  50 
  51         size /= sizeof(u32);
  52         for (i = words32; i < size; i++) /* pad */
  53                 replace_u32(&dst[i], 0, 0);
  54 
  55         if (changed)
  56                 nf_conntrack_event_cache(IPCT_LABEL, ct);
  57         return 0;
  58 }
  59 EXPORT_SYMBOL_GPL(nf_connlabels_replace);
  60 
  61 int nf_connlabels_get(struct net *net, unsigned int bits)
  62 {
  63         if (BIT_WORD(bits) >= NF_CT_LABELS_MAX_SIZE / sizeof(long))
  64                 return -ERANGE;
  65 
  66         spin_lock(&nf_connlabels_lock);
  67         net->ct.labels_used++;
  68         spin_unlock(&nf_connlabels_lock);
  69 
  70         return 0;
  71 }
  72 EXPORT_SYMBOL_GPL(nf_connlabels_get);
  73 
  74 void nf_connlabels_put(struct net *net)
  75 {
  76         spin_lock(&nf_connlabels_lock);
  77         net->ct.labels_used--;
  78         spin_unlock(&nf_connlabels_lock);
  79 }
  80 EXPORT_SYMBOL_GPL(nf_connlabels_put);
  81 
  82 static const struct nf_ct_ext_type labels_extend = {
  83         .len    = sizeof(struct nf_conn_labels),
  84         .align  = __alignof__(struct nf_conn_labels),
  85         .id     = NF_CT_EXT_LABELS,
  86 };
  87 
  88 int nf_conntrack_labels_init(void)
  89 {
  90         BUILD_BUG_ON(NF_CT_LABELS_MAX_SIZE / sizeof(long) >= U8_MAX);
  91 
  92         return nf_ct_extend_register(&labels_extend);
  93 }
  94 
  95 void nf_conntrack_labels_fini(void)
  96 {
  97         nf_ct_extend_unregister(&labels_extend);
  98 }

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