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