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
21static 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
40static 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
59static 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
89static void
90nftnl_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
102static int
103nftnl_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
128static 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
141static struct attr_policy
142obj_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
148struct 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};