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
13static 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
38static 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
63static 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
98static void
99nftnl_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
115static int
116nftnl_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
148static 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
184static struct attr_policy
185obj_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
193struct 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};