libnftnl  1.2.9
ct_expect.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * (C) 2019 by Stéphane Veyret <sveyret@gmail.com>
4  */
5 
6 #include <arpa/inet.h>
7 #include <errno.h>
8 
9 #include <libmnl/libmnl.h>
10 
11 #include "obj.h"
12 
13 static int nftnl_obj_ct_expect_set(struct nftnl_obj *e, uint16_t type,
14  const void *data, uint32_t data_len)
15 {
16  struct nftnl_obj_ct_expect *exp = nftnl_obj_data(e);
17 
18  switch (type) {
19  case NFTNL_OBJ_CT_EXPECT_L3PROTO:
20  memcpy(&exp->l3proto, data, data_len);
21  break;
22  case NFTNL_OBJ_CT_EXPECT_L4PROTO:
23  memcpy(&exp->l4proto, data, data_len);
24  break;
25  case NFTNL_OBJ_CT_EXPECT_DPORT:
26  memcpy(&exp->dport, data, data_len);
27  break;
28  case NFTNL_OBJ_CT_EXPECT_TIMEOUT:
29  memcpy(&exp->timeout, data, data_len);
30  break;
31  case NFTNL_OBJ_CT_EXPECT_SIZE:
32  memcpy(&exp->size, data, data_len);
33  break;
34  }
35  return 0;
36 }
37 
38 static const void *nftnl_obj_ct_expect_get(const struct nftnl_obj *e,
39  uint16_t type, uint32_t *data_len)
40 {
41  struct nftnl_obj_ct_expect *exp = nftnl_obj_data(e);
42 
43  switch (type) {
44  case NFTNL_OBJ_CT_EXPECT_L3PROTO:
45  *data_len = sizeof(exp->l3proto);
46  return &exp->l3proto;
47  case NFTNL_OBJ_CT_EXPECT_L4PROTO:
48  *data_len = sizeof(exp->l4proto);
49  return &exp->l4proto;
50  case NFTNL_OBJ_CT_EXPECT_DPORT:
51  *data_len = sizeof(exp->dport);
52  return &exp->dport;
53  case NFTNL_OBJ_CT_EXPECT_TIMEOUT:
54  *data_len = sizeof(exp->timeout);
55  return &exp->timeout;
56  case NFTNL_OBJ_CT_EXPECT_SIZE:
57  *data_len = sizeof(exp->size);
58  return &exp->size;
59  }
60  return NULL;
61 }
62 
63 static int nftnl_obj_ct_expect_cb(const struct nlattr *attr, void *data)
64 {
65  int type = mnl_attr_get_type(attr);
66  const struct nlattr **tb = data;
67 
68  if (mnl_attr_type_valid(attr, NFTA_CT_EXPECT_MAX) < 0)
69  return MNL_CB_OK;
70 
71  switch (type) {
72  case NFTA_CT_EXPECT_L3PROTO:
73  if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
74  abi_breakage();
75  break;
76  case NFTA_CT_EXPECT_L4PROTO:
77  if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
78  abi_breakage();
79  break;
80  case NFTA_CT_EXPECT_DPORT:
81  if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
82  abi_breakage();
83  break;
84  case NFTA_CT_EXPECT_TIMEOUT:
85  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
86  abi_breakage();
87  break;
88  case NFTA_CT_EXPECT_SIZE:
89  if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
90  abi_breakage();
91  break;
92  }
93 
94  tb[type] = attr;
95  return MNL_CB_OK;
96 }
97 
98 static void
99 nftnl_obj_ct_expect_build(struct nlmsghdr *nlh, const struct nftnl_obj *e)
100 {
101  struct nftnl_obj_ct_expect *exp = nftnl_obj_data(e);
102 
103  if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L3PROTO))
104  mnl_attr_put_u16(nlh, NFTA_CT_EXPECT_L3PROTO, htons(exp->l3proto));
105  if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L4PROTO))
106  mnl_attr_put_u8(nlh, NFTA_CT_EXPECT_L4PROTO, exp->l4proto);
107  if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_DPORT))
108  mnl_attr_put_u16(nlh, NFTA_CT_EXPECT_DPORT, htons(exp->dport));
109  if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_TIMEOUT))
110  mnl_attr_put_u32(nlh, NFTA_CT_EXPECT_TIMEOUT, exp->timeout);
111  if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_SIZE))
112  mnl_attr_put_u8(nlh, NFTA_CT_EXPECT_SIZE, exp->size);
113 }
114 
115 static int
116 nftnl_obj_ct_expect_parse(struct nftnl_obj *e, struct nlattr *attr)
117 {
118  struct nftnl_obj_ct_expect *exp = nftnl_obj_data(e);
119  struct nlattr *tb[NFTA_CT_EXPECT_MAX + 1] = {};
120 
121  if (mnl_attr_parse_nested(attr, nftnl_obj_ct_expect_cb, tb) < 0)
122  return -1;
123 
124  if (tb[NFTA_CT_EXPECT_L3PROTO]) {
125  exp->l3proto = ntohs(mnl_attr_get_u16(tb[NFTA_CT_EXPECT_L3PROTO]));
126  e->flags |= (1 << NFTNL_OBJ_CT_EXPECT_L3PROTO);
127  }
128  if (tb[NFTA_CT_EXPECT_L4PROTO]) {
129  exp->l4proto = mnl_attr_get_u8(tb[NFTA_CT_EXPECT_L4PROTO]);
130  e->flags |= (1 << NFTNL_OBJ_CT_EXPECT_L4PROTO);
131  }
132  if (tb[NFTA_CT_EXPECT_DPORT]) {
133  exp->dport = ntohs(mnl_attr_get_u16(tb[NFTA_CT_EXPECT_DPORT]));
134  e->flags |= (1 << NFTNL_OBJ_CT_EXPECT_DPORT);
135  }
136  if (tb[NFTA_CT_EXPECT_TIMEOUT]) {
137  exp->timeout = mnl_attr_get_u32(tb[NFTA_CT_EXPECT_TIMEOUT]);
138  e->flags |= (1 << NFTNL_OBJ_CT_EXPECT_TIMEOUT);
139  }
140  if (tb[NFTA_CT_EXPECT_SIZE]) {
141  exp->size = mnl_attr_get_u8(tb[NFTA_CT_EXPECT_SIZE]);
142  e->flags |= (1 << NFTNL_OBJ_CT_EXPECT_SIZE);
143  }
144 
145  return 0;
146 }
147 
148 static int nftnl_obj_ct_expect_snprintf(char *buf, size_t remain,
149  uint32_t flags,
150  const struct nftnl_obj *e)
151 {
152  struct nftnl_obj_ct_expect *exp = nftnl_obj_data(e);
153  int ret = 0, offset = 0;
154 
155  if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L3PROTO)) {
156  ret = snprintf(buf + offset, remain,
157  "family %d ", exp->l3proto);
158  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
159  }
160  if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L4PROTO)) {
161  ret = snprintf(buf + offset, remain,
162  "protocol %d ", exp->l4proto);
163  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
164  }
165  if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_DPORT)) {
166  ret = snprintf(buf + offset, remain,
167  "dport %d ", exp->dport);
168  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
169  }
170  if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_TIMEOUT)) {
171  ret = snprintf(buf + offset, remain,
172  "timeout %d ", exp->timeout);
173  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
174  }
175  if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_SIZE)) {
176  ret = snprintf(buf + offset, remain, "size %d ", exp->size);
177  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
178  }
179 
180  buf[offset] = '\0';
181  return offset;
182 }
183 
184 static struct attr_policy
185 obj_ct_expect_attr_policy[__NFTNL_OBJ_CT_EXPECT_MAX] = {
186  [NFTNL_OBJ_CT_EXPECT_L3PROTO] = { .maxlen = sizeof(uint16_t) },
187  [NFTNL_OBJ_CT_EXPECT_L4PROTO] = { .maxlen = sizeof(uint8_t) },
188  [NFTNL_OBJ_CT_EXPECT_DPORT] = { .maxlen = sizeof(uint16_t) },
189  [NFTNL_OBJ_CT_EXPECT_TIMEOUT] = { .maxlen = sizeof(uint32_t) },
190  [NFTNL_OBJ_CT_EXPECT_SIZE] = { .maxlen = sizeof(uint8_t) },
191 };
192 
193 struct obj_ops obj_ops_ct_expect = {
194  .name = "ct_expect",
195  .type = NFT_OBJECT_CT_EXPECT,
196  .alloc_len = sizeof(struct nftnl_obj_ct_expect),
197  .nftnl_max_attr = __NFTNL_OBJ_CT_EXPECT_MAX - 1,
198  .attr_policy = obj_ct_expect_attr_policy,
199  .set = nftnl_obj_ct_expect_set,
200  .get = nftnl_obj_ct_expect_get,
201  .parse = nftnl_obj_ct_expect_parse,
202  .build = nftnl_obj_ct_expect_build,
203  .output = nftnl_obj_ct_expect_snprintf,
204 };