libnftnl 1.2.7
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
17static 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
42static 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
67static 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
102static void
103nftnl_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
119static int
120nftnl_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
152static 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
188static struct attr_policy
189obj_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
197struct 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};