libnftnl  1.2.9
fwd.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * (C) 2015 Pablo Neira Ayuso <pablo@netfilter.org>
4  */
5 
6 #include <stdio.h>
7 #include <stdint.h>
8 #include <string.h>
9 #include <arpa/inet.h>
10 #include <errno.h>
11 #include "internal.h"
12 #include <libmnl/libmnl.h>
13 #include <linux/netfilter/nf_tables.h>
14 #include <libnftnl/expr.h>
15 #include <libnftnl/rule.h>
16 #include "expr_ops.h"
17 #include "data_reg.h"
18 
20  enum nft_registers sreg_dev;
21  enum nft_registers sreg_addr;
22  uint32_t nfproto;
23 };
24 
25 static int nftnl_expr_fwd_set(struct nftnl_expr *e, uint16_t type,
26  const void *data, uint32_t data_len)
27 {
28  struct nftnl_expr_fwd *fwd = nftnl_expr_data(e);
29 
30  switch (type) {
31  case NFTNL_EXPR_FWD_SREG_DEV:
32  memcpy(&fwd->sreg_dev, data, data_len);
33  break;
34  case NFTNL_EXPR_FWD_SREG_ADDR:
35  memcpy(&fwd->sreg_addr, data, data_len);
36  break;
37  case NFTNL_EXPR_FWD_NFPROTO:
38  memcpy(&fwd->nfproto, data, data_len);
39  break;
40  }
41  return 0;
42 }
43 
44 static const void *nftnl_expr_fwd_get(const struct nftnl_expr *e,
45  uint16_t type, uint32_t *data_len)
46 {
47  struct nftnl_expr_fwd *fwd = nftnl_expr_data(e);
48 
49  switch (type) {
50  case NFTNL_EXPR_FWD_SREG_DEV:
51  *data_len = sizeof(fwd->sreg_dev);
52  return &fwd->sreg_dev;
53  case NFTNL_EXPR_FWD_SREG_ADDR:
54  *data_len = sizeof(fwd->sreg_addr);
55  return &fwd->sreg_addr;
56  case NFTNL_EXPR_FWD_NFPROTO:
57  *data_len = sizeof(fwd->nfproto);
58  return &fwd->nfproto;
59  }
60  return NULL;
61 }
62 
63 static int nftnl_expr_fwd_cb(const struct nlattr *attr, void *data)
64 {
65  const struct nlattr **tb = data;
66  int type = mnl_attr_get_type(attr);
67 
68  if (mnl_attr_type_valid(attr, NFTA_FWD_MAX) < 0)
69  return MNL_CB_OK;
70 
71  switch (type) {
72  case NFTA_FWD_SREG_DEV:
73  case NFTA_FWD_SREG_ADDR:
74  case NFTA_FWD_NFPROTO:
75  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
76  abi_breakage();
77  break;
78  }
79 
80  tb[type] = attr;
81  return MNL_CB_OK;
82 }
83 
84 static void nftnl_expr_fwd_build(struct nlmsghdr *nlh,
85  const struct nftnl_expr *e)
86 {
87  struct nftnl_expr_fwd *fwd = nftnl_expr_data(e);
88 
89  if (e->flags & (1 << NFTNL_EXPR_FWD_SREG_DEV))
90  mnl_attr_put_u32(nlh, NFTA_FWD_SREG_DEV, htonl(fwd->sreg_dev));
91  if (e->flags & (1 << NFTNL_EXPR_FWD_SREG_ADDR))
92  mnl_attr_put_u32(nlh, NFTA_FWD_SREG_ADDR, htonl(fwd->sreg_addr));
93  if (e->flags & (1 << NFTNL_EXPR_FWD_NFPROTO))
94  mnl_attr_put_u32(nlh, NFTA_FWD_NFPROTO, htonl(fwd->nfproto));
95 }
96 
97 static int nftnl_expr_fwd_parse(struct nftnl_expr *e, struct nlattr *attr)
98 {
99  struct nftnl_expr_fwd *fwd = nftnl_expr_data(e);
100  struct nlattr *tb[NFTA_FWD_MAX + 1] = {};
101  int ret = 0;
102 
103  if (mnl_attr_parse_nested(attr, nftnl_expr_fwd_cb, tb) < 0)
104  return -1;
105 
106  if (tb[NFTA_FWD_SREG_DEV]) {
107  fwd->sreg_dev = ntohl(mnl_attr_get_u32(tb[NFTA_FWD_SREG_DEV]));
108  e->flags |= (1 << NFTNL_EXPR_FWD_SREG_DEV);
109  }
110  if (tb[NFTA_FWD_SREG_ADDR]) {
111  fwd->sreg_addr = ntohl(mnl_attr_get_u32(tb[NFTA_FWD_SREG_ADDR]));
112  e->flags |= (1 << NFTNL_EXPR_FWD_SREG_ADDR);
113  }
114  if (tb[NFTA_FWD_NFPROTO]) {
115  fwd->nfproto = ntohl(mnl_attr_get_u32(tb[NFTA_FWD_NFPROTO]));
116  e->flags |= (1 << NFTNL_EXPR_FWD_NFPROTO);
117  }
118 
119  return ret;
120 }
121 
122 static int nftnl_expr_fwd_snprintf(char *buf, size_t remain,
123  uint32_t flags, const struct nftnl_expr *e)
124 {
125  struct nftnl_expr_fwd *fwd = nftnl_expr_data(e);
126  int offset = 0, ret;
127 
128  if (e->flags & (1 << NFTNL_EXPR_FWD_SREG_DEV)) {
129  ret = snprintf(buf + offset, remain, "sreg_dev %u ",
130  fwd->sreg_dev);
131  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
132  }
133  if (e->flags & (1 << NFTNL_EXPR_FWD_SREG_ADDR)) {
134  ret = snprintf(buf + offset, remain, "sreg_addr %u ",
135  fwd->sreg_addr);
136  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
137  }
138  if (e->flags & (1 << NFTNL_EXPR_FWD_NFPROTO)) {
139  ret = snprintf(buf + offset, remain, "nfproto %u ",
140  fwd->nfproto);
141  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
142  }
143 
144  return offset;
145 }
146 
147 static struct attr_policy fwd_attr_policy[__NFTNL_EXPR_FWD_MAX] = {
148  [NFTNL_EXPR_FWD_SREG_DEV] = { .maxlen = sizeof(uint32_t) },
149  [NFTNL_EXPR_FWD_SREG_ADDR] = { .maxlen = sizeof(uint32_t) },
150  [NFTNL_EXPR_FWD_NFPROTO] = { .maxlen = sizeof(uint32_t) },
151 };
152 
153 struct expr_ops expr_ops_fwd = {
154  .name = "fwd",
155  .alloc_len = sizeof(struct nftnl_expr_fwd),
156  .nftnl_max_attr = __NFTNL_EXPR_FWD_MAX - 1,
157  .attr_policy = fwd_attr_policy,
158  .set = nftnl_expr_fwd_set,
159  .get = nftnl_expr_fwd_get,
160  .parse = nftnl_expr_fwd_parse,
161  .build = nftnl_expr_fwd_build,
162  .output = nftnl_expr_fwd_snprintf,
163 };