linux/net/netfilter/nf_conntrack_labels.c
<<
>>
Prefs
   1/*
   2 * test/set flag bits stored in conntrack extension area.
   3 *
   4 * (C) 2013 Astaro GmbH & Co KG
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 */
  10
  11#include <linux/ctype.h>
  12#include <linux/export.h>
  13#include <linux/jhash.h>
  14#include <linux/spinlock.h>
  15#include <linux/types.h>
  16#include <linux/slab.h>
  17
  18#include <net/netfilter/nf_conntrack_ecache.h>
  19#include <net/netfilter/nf_conntrack_labels.h>
  20
  21static unsigned int label_bits(const struct nf_conn_labels *l)
  22{
  23        unsigned int longs = l->words;
  24        return longs * BITS_PER_LONG;
  25}
  26
  27bool nf_connlabel_match(const struct nf_conn *ct, u16 bit)
  28{
  29        struct nf_conn_labels *labels = nf_ct_labels_find(ct);
  30
  31        if (!labels)
  32                return false;
  33
  34        return bit < label_bits(labels) && test_bit(bit, labels->bits);
  35}
  36EXPORT_SYMBOL_GPL(nf_connlabel_match);
  37
  38int nf_connlabel_set(struct nf_conn *ct, u16 bit)
  39{
  40        struct nf_conn_labels *labels = nf_ct_labels_find(ct);
  41
  42        if (!labels || bit >= label_bits(labels))
  43                return -ENOSPC;
  44
  45        if (test_bit(bit, labels->bits))
  46                return 0;
  47
  48        if (!test_and_set_bit(bit, labels->bits))
  49                nf_conntrack_event_cache(IPCT_LABEL, ct);
  50
  51        return 0;
  52}
  53EXPORT_SYMBOL_GPL(nf_connlabel_set);
  54
  55#if IS_ENABLED(CONFIG_NF_CT_NETLINK)
  56static void replace_u32(u32 *address, u32 mask, u32 new)
  57{
  58        u32 old, tmp;
  59
  60        do {
  61                old = *address;
  62                tmp = (old & mask) ^ new;
  63        } while (cmpxchg(address, old, tmp) != old);
  64}
  65
  66int nf_connlabels_replace(struct nf_conn *ct,
  67                          const u32 *data,
  68                          const u32 *mask, unsigned int words32)
  69{
  70        struct nf_conn_labels *labels;
  71        unsigned int size, i;
  72        u32 *dst;
  73
  74        labels = nf_ct_labels_find(ct);
  75        if (!labels)
  76                return -ENOSPC;
  77
  78        size = labels->words * sizeof(long);
  79        if (size < (words32 * sizeof(u32)))
  80                words32 = size / sizeof(u32);
  81
  82        dst = (u32 *) labels->bits;
  83        if (words32) {
  84                for (i = 0; i < words32; i++)
  85                        replace_u32(&dst[i], mask ? ~mask[i] : 0, data[i]);
  86        }
  87
  88        size /= sizeof(u32);
  89        for (i = words32; i < size; i++) /* pad */
  90                replace_u32(&dst[i], 0, 0);
  91
  92        nf_conntrack_event_cache(IPCT_LABEL, ct);
  93        return 0;
  94}
  95EXPORT_SYMBOL_GPL(nf_connlabels_replace);
  96#endif
  97
  98static struct nf_ct_ext_type labels_extend __read_mostly = {
  99        .len    = sizeof(struct nf_conn_labels),
 100        .align  = __alignof__(struct nf_conn_labels),
 101        .id     = NF_CT_EXT_LABELS,
 102};
 103
 104int nf_conntrack_labels_init(void)
 105{
 106        return nf_ct_extend_register(&labels_extend);
 107}
 108
 109void nf_conntrack_labels_fini(void)
 110{
 111        nf_ct_extend_unregister(&labels_extend);
 112}
 113
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.