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