libnftnl  1.2.8
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 
25 static 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 
44 static 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 
63 static 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 
93 static void
94 nftnl_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 
106 static int
107 nftnl_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 
132 static 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 
145 static struct attr_policy
146 obj_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 
152 struct 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 };