libnftnl  1.2.9
byteorder.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
4  *
5  * This code has been sponsored by Sophos Astaro <http://www.sophos.com>
6  */
7 
8 #include "internal.h"
9 
10 #include <stdio.h>
11 #include <stdint.h>
12 #include <string.h> /* for memcpy */
13 #include <arpa/inet.h>
14 #include <errno.h>
15 #include <libmnl/libmnl.h>
16 #include <linux/netfilter/nf_tables.h>
17 #include <libnftnl/expr.h>
18 #include <libnftnl/rule.h>
19 
21  enum nft_registers sreg;
22  enum nft_registers dreg;
23  enum nft_byteorder_ops op;
24  unsigned int len;
25  unsigned int size;
26 };
27 
28 static int
29 nftnl_expr_byteorder_set(struct nftnl_expr *e, uint16_t type,
30  const void *data, uint32_t data_len)
31 {
32  struct nftnl_expr_byteorder *byteorder = nftnl_expr_data(e);
33 
34  switch(type) {
35  case NFTNL_EXPR_BYTEORDER_SREG:
36  memcpy(&byteorder->sreg, data, data_len);
37  break;
38  case NFTNL_EXPR_BYTEORDER_DREG:
39  memcpy(&byteorder->dreg, data, data_len);
40  break;
41  case NFTNL_EXPR_BYTEORDER_OP:
42  memcpy(&byteorder->op, data, data_len);
43  break;
44  case NFTNL_EXPR_BYTEORDER_LEN:
45  memcpy(&byteorder->len, data, data_len);
46  break;
47  case NFTNL_EXPR_BYTEORDER_SIZE:
48  memcpy(&byteorder->size, data, data_len);
49  break;
50  }
51  return 0;
52 }
53 
54 static const void *
55 nftnl_expr_byteorder_get(const struct nftnl_expr *e, uint16_t type,
56  uint32_t *data_len)
57 {
58  struct nftnl_expr_byteorder *byteorder = nftnl_expr_data(e);
59 
60  switch(type) {
61  case NFTNL_EXPR_BYTEORDER_SREG:
62  *data_len = sizeof(byteorder->sreg);
63  return &byteorder->sreg;
64  case NFTNL_EXPR_BYTEORDER_DREG:
65  *data_len = sizeof(byteorder->dreg);
66  return &byteorder->dreg;
67  case NFTNL_EXPR_BYTEORDER_OP:
68  *data_len = sizeof(byteorder->op);
69  return &byteorder->op;
70  case NFTNL_EXPR_BYTEORDER_LEN:
71  *data_len = sizeof(byteorder->len);
72  return &byteorder->len;
73  case NFTNL_EXPR_BYTEORDER_SIZE:
74  *data_len = sizeof(byteorder->size);
75  return &byteorder->size;
76  }
77  return NULL;
78 }
79 
80 static int nftnl_expr_byteorder_cb(const struct nlattr *attr, void *data)
81 {
82  const struct nlattr **tb = data;
83  int type = mnl_attr_get_type(attr);
84 
85  if (mnl_attr_type_valid(attr, NFTA_BYTEORDER_MAX) < 0)
86  return MNL_CB_OK;
87 
88  switch(type) {
89  case NFTA_BYTEORDER_SREG:
90  case NFTA_BYTEORDER_DREG:
91  case NFTA_BYTEORDER_OP:
92  case NFTA_BYTEORDER_LEN:
93  case NFTA_BYTEORDER_SIZE:
94  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
95  abi_breakage();
96  break;
97  }
98 
99  tb[type] = attr;
100  return MNL_CB_OK;
101 }
102 
103 static void
104 nftnl_expr_byteorder_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
105 {
106  struct nftnl_expr_byteorder *byteorder = nftnl_expr_data(e);
107 
108  if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_SREG)) {
109  mnl_attr_put_u32(nlh, NFTA_BYTEORDER_SREG,
110  htonl(byteorder->sreg));
111  }
112  if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_DREG)) {
113  mnl_attr_put_u32(nlh, NFTA_BYTEORDER_DREG,
114  htonl(byteorder->dreg));
115  }
116  if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_OP)) {
117  mnl_attr_put_u32(nlh, NFTA_BYTEORDER_OP,
118  htonl(byteorder->op));
119  }
120  if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_LEN)) {
121  mnl_attr_put_u32(nlh, NFTA_BYTEORDER_LEN,
122  htonl(byteorder->len));
123  }
124  if (e->flags & (1 << NFTNL_EXPR_BYTEORDER_SIZE)) {
125  mnl_attr_put_u32(nlh, NFTA_BYTEORDER_SIZE,
126  htonl(byteorder->size));
127  }
128 }
129 
130 static int
131 nftnl_expr_byteorder_parse(struct nftnl_expr *e, struct nlattr *attr)
132 {
133  struct nftnl_expr_byteorder *byteorder = nftnl_expr_data(e);
134  struct nlattr *tb[NFTA_BYTEORDER_MAX+1] = {};
135  int ret = 0;
136 
137  if (mnl_attr_parse_nested(attr, nftnl_expr_byteorder_cb, tb) < 0)
138  return -1;
139 
140  if (tb[NFTA_BYTEORDER_SREG]) {
141  byteorder->sreg =
142  ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_SREG]));
143  e->flags |= (1 << NFTNL_EXPR_BYTEORDER_SREG);
144  }
145  if (tb[NFTA_BYTEORDER_DREG]) {
146  byteorder->dreg =
147  ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_DREG]));
148  e->flags |= (1 << NFTNL_EXPR_BYTEORDER_DREG);
149  }
150  if (tb[NFTA_BYTEORDER_OP]) {
151  byteorder->op =
152  ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_OP]));
153  e->flags |= (1 << NFTNL_EXPR_BYTEORDER_OP);
154  }
155  if (tb[NFTA_BYTEORDER_LEN]) {
156  byteorder->len =
157  ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_LEN]));
158  e->flags |= (1 << NFTNL_EXPR_BYTEORDER_LEN);
159  }
160  if (tb[NFTA_BYTEORDER_SIZE]) {
161  byteorder->size =
162  ntohl(mnl_attr_get_u32(tb[NFTA_BYTEORDER_SIZE]));
163  e->flags |= (1 << NFTNL_EXPR_BYTEORDER_SIZE);
164  }
165 
166  return ret;
167 }
168 
169 static const char *expr_byteorder_str[] = {
170  [NFT_BYTEORDER_HTON] = "hton",
171  [NFT_BYTEORDER_NTOH] = "ntoh",
172 };
173 
174 static const char *bo2str(uint32_t type)
175 {
176  if (type > NFT_BYTEORDER_HTON)
177  return "unknown";
178 
179  return expr_byteorder_str[type];
180 }
181 
182 static int
183 nftnl_expr_byteorder_snprintf(char *buf, size_t remain,
184  uint32_t flags, const struct nftnl_expr *e)
185 {
186  struct nftnl_expr_byteorder *byteorder = nftnl_expr_data(e);
187  int offset = 0, ret;
188 
189  ret = snprintf(buf, remain, "reg %u = %s(reg %u, %u, %u) ",
190  byteorder->dreg, bo2str(byteorder->op),
191  byteorder->sreg, byteorder->size, byteorder->len);
192  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
193 
194  return offset;
195 }
196 
197 static struct attr_policy byteorder_attr_policy[__NFTNL_EXPR_BYTEORDER_MAX] = {
198  [NFTNL_EXPR_BYTEORDER_DREG] = { .maxlen = sizeof(uint32_t) },
199  [NFTNL_EXPR_BYTEORDER_SREG] = { .maxlen = sizeof(uint32_t) },
200  [NFTNL_EXPR_BYTEORDER_OP] = { .maxlen = sizeof(uint32_t) },
201  [NFTNL_EXPR_BYTEORDER_LEN] = { .maxlen = sizeof(uint32_t) },
202  [NFTNL_EXPR_BYTEORDER_SIZE] = { .maxlen = sizeof(uint32_t) },
203 };
204 
205 struct expr_ops expr_ops_byteorder = {
206  .name = "byteorder",
207  .alloc_len = sizeof(struct nftnl_expr_byteorder),
208  .nftnl_max_attr = __NFTNL_EXPR_BYTEORDER_MAX - 1,
209  .attr_policy = byteorder_attr_policy,
210  .set = nftnl_expr_byteorder_set,
211  .get = nftnl_expr_byteorder_get,
212  .parse = nftnl_expr_byteorder_parse,
213  .build = nftnl_expr_byteorder_build,
214  .output = nftnl_expr_byteorder_snprintf,
215 };