Blame view

net/netfilter/nft_byteorder.c 4.46 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
96518518c   Patrick McHardy   netfilter: add nf...
2
  /*
ef1f7df91   Patrick McHardy   netfilter: nf_tab...
3
   * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net>
96518518c   Patrick McHardy   netfilter: add nf...
4
   *
96518518c   Patrick McHardy   netfilter: add nf...
5
6
   * Development of this code funded by Astaro AG (http://www.astaro.com/)
   */
ce1e7989d   Florian Westphal   netfilter: nft_by...
7
  #include <asm/unaligned.h>
96518518c   Patrick McHardy   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   Florian Westphal   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   Patrick McHardy   netfilter: add nf...
27
28
  {
  	const struct nft_byteorder *priv = nft_expr_priv(expr);
49499c3e6   Patrick McHardy   netfilter: nf_tab...
29
30
  	u32 *src = &regs->data[priv->sreg];
  	u32 *dst = &regs->data[priv->dreg];
96518518c   Patrick McHardy   netfilter: add nf...
31
32
  	union { u32 u32; u16 u16; } *s, *d;
  	unsigned int i;
fad136ea0   Patrick McHardy   netfilter: nf_tab...
33
34
  	s = (void *)src;
  	d = (void *)dst;
96518518c   Patrick McHardy   netfilter: add nf...
35
36
  
  	switch (priv->size) {
ce1e7989d   Florian Westphal   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   Ander Juaristi   netfilter: nf_tab...
43
44
  				src64 = nft_reg_load64(&src[i]);
  				nft_reg_store64(&dst[i], be64_to_cpu(src64));
ce1e7989d   Florian Westphal   netfilter: nft_by...
45
46
47
48
  			}
  			break;
  		case NFT_BYTEORDER_HTON:
  			for (i = 0; i < priv->len / 8; i++) {
a1b840ada   Ander Juaristi   netfilter: nf_tab...
49
50
51
  				src64 = (__force __u64)
  					cpu_to_be64(nft_reg_load64(&src[i]));
  				nft_reg_store64(&dst[i], src64);
ce1e7989d   Florian Westphal   netfilter: nft_by...
52
53
54
55
56
  			}
  			break;
  		}
  		break;
  	}
96518518c   Patrick McHardy   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   Laura Garcia Liebana   netfilter: nf_tab...
97
  	u32 size, len;
96518518c   Patrick McHardy   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   Patrick McHardy   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   Laura Garcia Liebana   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   Patrick McHardy   netfilter: add nf...
119
120
121
  	switch (priv->size) {
  	case 2:
  	case 4:
ce1e7989d   Florian Westphal   netfilter: nft_by...
122
  	case 8:
96518518c   Patrick McHardy   netfilter: add nf...
123
124
125
126
  		break;
  	default:
  		return -EINVAL;
  	}
b1c96ed37   Patrick McHardy   netfilter: nf_tab...
127
  	priv->sreg = nft_parse_register(tb[NFTA_BYTEORDER_SREG]);
36b701fae   Laura Garcia Liebana   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   Patrick McHardy   netfilter: nf_tab...
133
  	err = nft_validate_register_load(priv->sreg, priv->len);
45d9bcda2   Patrick McHardy   netfilter: nf_tab...
134
135
  	if (err < 0)
  		return err;
b1c96ed37   Patrick McHardy   netfilter: nf_tab...
136
  	priv->dreg = nft_parse_register(tb[NFTA_BYTEORDER_DREG]);
27e6d2017   Patrick McHardy   netfilter: nf_tab...
137
138
  	return nft_validate_register_store(ctx, priv->dreg, NULL,
  					   NFT_DATA_VALUE, priv->len);
96518518c   Patrick McHardy   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   Patrick McHardy   netfilter: nf_tab...
144
  	if (nft_dump_register(skb, NFTA_BYTEORDER_SREG, priv->sreg))
96518518c   Patrick McHardy   netfilter: add nf...
145
  		goto nla_put_failure;
b1c96ed37   Patrick McHardy   netfilter: nf_tab...
146
  	if (nft_dump_register(skb, NFTA_BYTEORDER_DREG, priv->dreg))
96518518c   Patrick McHardy   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   Patrick McHardy   netfilter: nf_tab...
159
160
  static const struct nft_expr_ops nft_byteorder_ops = {
  	.type		= &nft_byteorder_type,
96518518c   Patrick McHardy   netfilter: add nf...
161
  	.size		= NFT_EXPR_SIZE(sizeof(struct nft_byteorder)),
96518518c   Patrick McHardy   netfilter: add nf...
162
163
164
  	.eval		= nft_byteorder_eval,
  	.init		= nft_byteorder_init,
  	.dump		= nft_byteorder_dump,
ef1f7df91   Patrick McHardy   netfilter: nf_tab...
165
  };
4e24877e6   Liping Zhang   netfilter: nf_tab...
166
  struct nft_expr_type nft_byteorder_type __read_mostly = {
ef1f7df91   Patrick McHardy   netfilter: nf_tab...
167
168
  	.name		= "byteorder",
  	.ops		= &nft_byteorder_ops,
96518518c   Patrick McHardy   netfilter: add nf...
169
170
  	.policy		= nft_byteorder_policy,
  	.maxattr	= NFTA_BYTEORDER_MAX,
ef1f7df91   Patrick McHardy   netfilter: nf_tab...
171
  	.owner		= THIS_MODULE,
96518518c   Patrick McHardy   netfilter: add nf...
172
  };