Blame view
net/netfilter/nft_byteorder.c
4.46 KB
d2912cb15 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
96518518c netfilter: add nf... |
2 |
/* |
ef1f7df91 netfilter: nf_tab... |
3 |
* Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> |
96518518c netfilter: add nf... |
4 |
* |
96518518c netfilter: add nf... |
5 6 |
* Development of this code funded by Astaro AG (http://www.astaro.com/) */ |
ce1e7989d netfilter: nft_by... |
7 |
#include <asm/unaligned.h> |
96518518c netfilter: add nf... |
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#include <linux/kernel.h> #include <linux/init.h> #include <linux/module.h> #include <linux/netlink.h> #include <linux/netfilter.h> #include <linux/netfilter/nf_tables.h> #include <net/netfilter/nf_tables_core.h> #include <net/netfilter/nf_tables.h> struct nft_byteorder { enum nft_registers sreg:8; enum nft_registers dreg:8; enum nft_byteorder_ops op:8; u8 len; u8 size; }; |
10870dd89 netfilter: nf_tab... |
24 25 26 |
void nft_byteorder_eval(const struct nft_expr *expr, struct nft_regs *regs, const struct nft_pktinfo *pkt) |
96518518c netfilter: add nf... |
27 28 |
{ const struct nft_byteorder *priv = nft_expr_priv(expr); |
49499c3e6 netfilter: nf_tab... |
29 30 |
u32 *src = ®s->data[priv->sreg]; u32 *dst = ®s->data[priv->dreg]; |
96518518c netfilter: add nf... |
31 32 |
union { u32 u32; u16 u16; } *s, *d; unsigned int i; |
fad136ea0 netfilter: nf_tab... |
33 34 |
s = (void *)src; d = (void *)dst; |
96518518c netfilter: add nf... |
35 36 |
switch (priv->size) { |
ce1e7989d netfilter: nft_by... |
37 38 39 40 41 42 |
case 8: { u64 src64; switch (priv->op) { case NFT_BYTEORDER_NTOH: for (i = 0; i < priv->len / 8; i++) { |
a1b840ada netfilter: nf_tab... |
43 44 |
src64 = nft_reg_load64(&src[i]); nft_reg_store64(&dst[i], be64_to_cpu(src64)); |
ce1e7989d netfilter: nft_by... |
45 46 47 48 |
} break; case NFT_BYTEORDER_HTON: for (i = 0; i < priv->len / 8; i++) { |
a1b840ada netfilter: nf_tab... |
49 50 51 |
src64 = (__force __u64) cpu_to_be64(nft_reg_load64(&src[i])); nft_reg_store64(&dst[i], src64); |
ce1e7989d netfilter: nft_by... |
52 53 54 55 56 |
} break; } break; } |
96518518c netfilter: add nf... |
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
case 4: switch (priv->op) { case NFT_BYTEORDER_NTOH: for (i = 0; i < priv->len / 4; i++) d[i].u32 = ntohl((__force __be32)s[i].u32); break; case NFT_BYTEORDER_HTON: for (i = 0; i < priv->len / 4; i++) d[i].u32 = (__force __u32)htonl(s[i].u32); break; } break; case 2: switch (priv->op) { case NFT_BYTEORDER_NTOH: for (i = 0; i < priv->len / 2; i++) d[i].u16 = ntohs((__force __be16)s[i].u16); break; case NFT_BYTEORDER_HTON: for (i = 0; i < priv->len / 2; i++) d[i].u16 = (__force __u16)htons(s[i].u16); break; } break; } } static const struct nla_policy nft_byteorder_policy[NFTA_BYTEORDER_MAX + 1] = { [NFTA_BYTEORDER_SREG] = { .type = NLA_U32 }, [NFTA_BYTEORDER_DREG] = { .type = NLA_U32 }, [NFTA_BYTEORDER_OP] = { .type = NLA_U32 }, [NFTA_BYTEORDER_LEN] = { .type = NLA_U32 }, [NFTA_BYTEORDER_SIZE] = { .type = NLA_U32 }, }; static int nft_byteorder_init(const struct nft_ctx *ctx, const struct nft_expr *expr, const struct nlattr * const tb[]) { struct nft_byteorder *priv = nft_expr_priv(expr); |
36b701fae netfilter: nf_tab... |
97 |
u32 size, len; |
96518518c netfilter: add nf... |
98 99 100 101 102 103 104 105 |
int err; if (tb[NFTA_BYTEORDER_SREG] == NULL || tb[NFTA_BYTEORDER_DREG] == NULL || tb[NFTA_BYTEORDER_LEN] == NULL || tb[NFTA_BYTEORDER_SIZE] == NULL || tb[NFTA_BYTEORDER_OP] == NULL) return -EINVAL; |
96518518c netfilter: add nf... |
106 107 108 109 110 111 112 113 |
priv->op = ntohl(nla_get_be32(tb[NFTA_BYTEORDER_OP])); switch (priv->op) { case NFT_BYTEORDER_NTOH: case NFT_BYTEORDER_HTON: break; default: return -EINVAL; } |
36b701fae netfilter: nf_tab... |
114 115 116 117 118 |
err = nft_parse_u32_check(tb[NFTA_BYTEORDER_SIZE], U8_MAX, &size); if (err < 0) return err; priv->size = size; |
96518518c netfilter: add nf... |
119 120 121 |
switch (priv->size) { case 2: case 4: |
ce1e7989d netfilter: nft_by... |
122 |
case 8: |
96518518c netfilter: add nf... |
123 124 125 126 |
break; default: return -EINVAL; } |
b1c96ed37 netfilter: nf_tab... |
127 |
priv->sreg = nft_parse_register(tb[NFTA_BYTEORDER_SREG]); |
36b701fae netfilter: nf_tab... |
128 129 130 131 132 |
err = nft_parse_u32_check(tb[NFTA_BYTEORDER_LEN], U8_MAX, &len); if (err < 0) return err; priv->len = len; |
d07db9884 netfilter: nf_tab... |
133 |
err = nft_validate_register_load(priv->sreg, priv->len); |
45d9bcda2 netfilter: nf_tab... |
134 135 |
if (err < 0) return err; |
b1c96ed37 netfilter: nf_tab... |
136 |
priv->dreg = nft_parse_register(tb[NFTA_BYTEORDER_DREG]); |
27e6d2017 netfilter: nf_tab... |
137 138 |
return nft_validate_register_store(ctx, priv->dreg, NULL, NFT_DATA_VALUE, priv->len); |
96518518c netfilter: add nf... |
139 140 141 142 143 |
} static int nft_byteorder_dump(struct sk_buff *skb, const struct nft_expr *expr) { const struct nft_byteorder *priv = nft_expr_priv(expr); |
b1c96ed37 netfilter: nf_tab... |
144 |
if (nft_dump_register(skb, NFTA_BYTEORDER_SREG, priv->sreg)) |
96518518c netfilter: add nf... |
145 |
goto nla_put_failure; |
b1c96ed37 netfilter: nf_tab... |
146 |
if (nft_dump_register(skb, NFTA_BYTEORDER_DREG, priv->dreg)) |
96518518c netfilter: add nf... |
147 148 149 150 151 152 153 154 155 156 157 158 |
goto nla_put_failure; if (nla_put_be32(skb, NFTA_BYTEORDER_OP, htonl(priv->op))) goto nla_put_failure; if (nla_put_be32(skb, NFTA_BYTEORDER_LEN, htonl(priv->len))) goto nla_put_failure; if (nla_put_be32(skb, NFTA_BYTEORDER_SIZE, htonl(priv->size))) goto nla_put_failure; return 0; nla_put_failure: return -1; } |
ef1f7df91 netfilter: nf_tab... |
159 160 |
static const struct nft_expr_ops nft_byteorder_ops = { .type = &nft_byteorder_type, |
96518518c netfilter: add nf... |
161 |
.size = NFT_EXPR_SIZE(sizeof(struct nft_byteorder)), |
96518518c netfilter: add nf... |
162 163 164 |
.eval = nft_byteorder_eval, .init = nft_byteorder_init, .dump = nft_byteorder_dump, |
ef1f7df91 netfilter: nf_tab... |
165 |
}; |
4e24877e6 netfilter: nf_tab... |
166 |
struct nft_expr_type nft_byteorder_type __read_mostly = { |
ef1f7df91 netfilter: nf_tab... |
167 168 |
.name = "byteorder", .ops = &nft_byteorder_ops, |
96518518c netfilter: add nf... |
169 170 |
.policy = nft_byteorder_policy, .maxattr = NFTA_BYTEORDER_MAX, |
ef1f7df91 netfilter: nf_tab... |
171 |
.owner = THIS_MODULE, |
96518518c netfilter: add nf... |
172 |
}; |