libnftnl  1.1.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, 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 
44 static 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 
69 static 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 
104 static void
105 nftnl_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 
121 static int
122 nftnl_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 
154 static int nftnl_obj_ct_expect_snprintf_default(char *buf, size_t len,
155  const struct nftnl_obj *e)
156 {
157  int ret = 0;
158  int offset = 0, remain = len;
159  struct nftnl_obj_ct_expect *exp = nftnl_obj_data(e);
160 
161  if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L3PROTO)) {
162  ret = snprintf(buf + offset, len, "family %d ", exp->l3proto);
163  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
164  }
165  if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_L4PROTO)) {
166  ret = snprintf(buf + offset, len, "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, len, "dport %d ", exp->dport);
171  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
172  }
173  if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_TIMEOUT)) {
174  ret = snprintf(buf + offset, len, "timeout %d ", exp->timeout);
175  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
176  }
177  if (e->flags & (1 << NFTNL_OBJ_CT_EXPECT_SIZE)) {
178  ret = snprintf(buf + offset, len, "size %d ", exp->size);
179  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
180  }
181 
182  buf[offset] = '\0';
183  return offset;
184 }
185 
186 static int nftnl_obj_ct_expect_snprintf(char *buf, size_t len, uint32_t type,
187  uint32_t flags,
188  const struct nftnl_obj *e)
189 {
190  if (len)
191  buf[0] = '\0';
192 
193  switch (type) {
194  case NFTNL_OUTPUT_DEFAULT:
195  return nftnl_obj_ct_expect_snprintf_default(buf, len, e);
196  case NFTNL_OUTPUT_JSON:
197  default:
198  break;
199  }
200  return -1;
201 }
202 
203 struct obj_ops obj_ops_ct_expect = {
204  .name = "ct_expect",
205  .type = NFT_OBJECT_CT_EXPECT,
206  .alloc_len = sizeof(struct nftnl_obj_ct_expect),
207  .max_attr = NFTA_CT_EXPECT_MAX,
208  .set = nftnl_obj_ct_expect_set,
209  .get = nftnl_obj_ct_expect_get,
210  .parse = nftnl_obj_ct_expect_parse,
211  .build = nftnl_obj_ct_expect_build,
212  .snprintf = nftnl_obj_ct_expect_snprintf,
213 };