libnftnl  1.2.9
ct_helper.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * (C) 2017 Red Hat GmbH
4  * Author: Florian Westphal <fw@strlen.de>
5  */
6 
7 #include <stdio.h>
8 #include <stdint.h>
9 #include <arpa/inet.h>
10 #include <errno.h>
11 #include <inttypes.h>
12 
13 #include <linux/netfilter/nf_tables.h>
14 
15 #include "internal.h"
16 #include <libmnl/libmnl.h>
17 #include <libnftnl/object.h>
18 
19 #include "obj.h"
20 
21 static int nftnl_obj_ct_helper_set(struct nftnl_obj *e, uint16_t type,
22  const void *data, uint32_t data_len)
23 {
24  struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
25 
26  switch (type) {
27  case NFTNL_OBJ_CT_HELPER_NAME:
28  snprintf(helper->name, sizeof(helper->name), "%s", (const char *)data);
29  break;
30  case NFTNL_OBJ_CT_HELPER_L3PROTO:
31  memcpy(&helper->l3proto, data, data_len);
32  break;
33  case NFTNL_OBJ_CT_HELPER_L4PROTO:
34  memcpy(&helper->l4proto, data, data_len);
35  break;
36  }
37  return 0;
38 }
39 
40 static const void *nftnl_obj_ct_helper_get(const struct nftnl_obj *e,
41  uint16_t type, uint32_t *data_len)
42 {
43  struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
44 
45  switch (type) {
46  case NFTNL_OBJ_CT_HELPER_NAME:
47  *data_len = strlen(helper->name);
48  return helper->name;
49  case NFTNL_OBJ_CT_HELPER_L3PROTO:
50  *data_len = sizeof(helper->l3proto);
51  return &helper->l3proto;
52  case NFTNL_OBJ_CT_HELPER_L4PROTO:
53  *data_len = sizeof(helper->l4proto);
54  return &helper->l4proto;
55  }
56  return NULL;
57 }
58 
59 static int nftnl_obj_ct_helper_cb(const struct nlattr *attr, void *data)
60 {
61  const struct nftnl_obj_ct_helper *helper = NULL;
62  int type = mnl_attr_get_type(attr);
63  const struct nlattr **tb = data;
64 
65  if (mnl_attr_type_valid(attr, NFTA_CT_HELPER_MAX) < 0)
66  return MNL_CB_OK;
67 
68  switch (type) {
69  case NFTA_CT_HELPER_NAME:
70  if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
71  abi_breakage();
72  if (mnl_attr_get_payload_len(attr) >= sizeof(helper->name))
73  abi_breakage();
74  break;
75  case NFTA_CT_HELPER_L3PROTO:
76  if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
77  abi_breakage();
78  break;
79  case NFTA_CT_HELPER_L4PROTO:
80  if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
81  abi_breakage();
82  break;
83  }
84 
85  tb[type] = attr;
86  return MNL_CB_OK;
87 }
88 
89 static void
90 nftnl_obj_ct_helper_build(struct nlmsghdr *nlh, const struct nftnl_obj *e)
91 {
92  struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
93 
94  if (e->flags & (1 << NFTNL_OBJ_CT_HELPER_NAME))
95  mnl_attr_put_str(nlh, NFTA_CT_HELPER_NAME, helper->name);
96  if (e->flags & (1 << NFTNL_OBJ_CT_HELPER_L3PROTO))
97  mnl_attr_put_u16(nlh, NFTA_CT_HELPER_L3PROTO, htons(helper->l3proto));
98  if (e->flags & (1 << NFTNL_OBJ_CT_HELPER_L4PROTO))
99  mnl_attr_put_u8(nlh, NFTA_CT_HELPER_L4PROTO, helper->l4proto);
100 }
101 
102 static int
103 nftnl_obj_ct_helper_parse(struct nftnl_obj *e, struct nlattr *attr)
104 {
105  struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
106  struct nlattr *tb[NFTA_CT_HELPER_MAX + 1] = {};
107 
108  if (mnl_attr_parse_nested(attr, nftnl_obj_ct_helper_cb, tb) < 0)
109  return -1;
110 
111  if (tb[NFTA_CT_HELPER_NAME]) {
112  snprintf(helper->name, sizeof(helper->name), "%s",
113  mnl_attr_get_str(tb[NFTA_CT_HELPER_NAME]));
114  e->flags |= (1 << NFTNL_OBJ_CT_HELPER_NAME);
115  }
116  if (tb[NFTA_CT_HELPER_L3PROTO]) {
117  helper->l3proto = ntohs(mnl_attr_get_u16(tb[NFTA_CT_HELPER_L3PROTO]));
118  e->flags |= (1 << NFTNL_OBJ_CT_HELPER_L3PROTO);
119  }
120  if (tb[NFTA_CT_HELPER_L4PROTO]) {
121  helper->l4proto = mnl_attr_get_u8(tb[NFTA_CT_HELPER_L4PROTO]);
122  e->flags |= (1 << NFTNL_OBJ_CT_HELPER_L4PROTO);
123  }
124 
125  return 0;
126 }
127 
128 static int nftnl_obj_ct_helper_snprintf(char *buf, size_t len,
129  uint32_t flags,
130  const struct nftnl_obj *e)
131 {
132  struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
133 
134  return snprintf(buf, len, "name %s family %d protocol %d ",
135  helper->name, helper->l3proto, helper->l4proto);
136 }
137 
138 /* from kernel's include/net/netfilter/nf_conntrack_helper.h */
139 #define NF_CT_HELPER_NAME_LEN 16
140 
141 static struct attr_policy
142 obj_ct_helper_attr_policy[__NFTNL_OBJ_CT_HELPER_MAX] = {
143  [NFTNL_OBJ_CT_HELPER_NAME] = { .maxlen = NF_CT_HELPER_NAME_LEN },
144  [NFTNL_OBJ_CT_HELPER_L3PROTO] = { .maxlen = sizeof(uint16_t) },
145  [NFTNL_OBJ_CT_HELPER_L4PROTO] = { .maxlen = sizeof(uint8_t) },
146 };
147 
148 struct obj_ops obj_ops_ct_helper = {
149  .name = "ct_helper",
150  .type = NFT_OBJECT_CT_HELPER,
151  .alloc_len = sizeof(struct nftnl_obj_ct_helper),
152  .nftnl_max_attr = __NFTNL_OBJ_CT_HELPER_MAX - 1,
153  .attr_policy = obj_ct_helper_attr_policy,
154  .set = nftnl_obj_ct_helper_set,
155  .get = nftnl_obj_ct_helper_get,
156  .parse = nftnl_obj_ct_helper_parse,
157  .build = nftnl_obj_ct_helper_build,
158  .output = nftnl_obj_ct_helper_snprintf,
159 };