libnftnl  1.2.4
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(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 
190 struct 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 };