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