libnftnl  1.2.3
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, sizeof(helper->l3proto));
36  break;
37  case NFTNL_OBJ_CT_HELPER_L4PROTO:
38  memcpy(&helper->l4proto, data, sizeof(helper->l4proto));
39  break;
40  default:
41  return -1;
42  }
43  return 0;
44 }
45 
46 static const void *nftnl_obj_ct_helper_get(const struct nftnl_obj *e,
47  uint16_t type, uint32_t *data_len)
48 {
49  struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
50 
51  switch (type) {
52  case NFTNL_OBJ_CT_HELPER_NAME:
53  *data_len = strlen(helper->name);
54  return helper->name;
55  case NFTNL_OBJ_CT_HELPER_L3PROTO:
56  *data_len = sizeof(helper->l3proto);
57  return &helper->l3proto;
58  case NFTNL_OBJ_CT_HELPER_L4PROTO:
59  *data_len = sizeof(helper->l4proto);
60  return &helper->l4proto;
61  }
62  return NULL;
63 }
64 
65 static int nftnl_obj_ct_helper_cb(const struct nlattr *attr, void *data)
66 {
67  const struct nftnl_obj_ct_helper *helper = NULL;
68  int type = mnl_attr_get_type(attr);
69  const struct nlattr **tb = data;
70 
71  if (mnl_attr_type_valid(attr, NFTA_CT_HELPER_MAX) < 0)
72  return MNL_CB_OK;
73 
74  switch (type) {
75  case NFTA_CT_HELPER_NAME:
76  if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
77  abi_breakage();
78  if (mnl_attr_get_payload_len(attr) >= sizeof(helper->name))
79  abi_breakage();
80  break;
81  case NFTA_CT_HELPER_L3PROTO:
82  if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
83  abi_breakage();
84  break;
85  case NFTA_CT_HELPER_L4PROTO:
86  if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
87  abi_breakage();
88  break;
89  }
90 
91  tb[type] = attr;
92  return MNL_CB_OK;
93 }
94 
95 static void
96 nftnl_obj_ct_helper_build(struct nlmsghdr *nlh, const struct nftnl_obj *e)
97 {
98  struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
99 
100  if (e->flags & (1 << NFTNL_OBJ_CT_HELPER_NAME))
101  mnl_attr_put_str(nlh, NFTA_CT_HELPER_NAME, helper->name);
102  if (e->flags & (1 << NFTNL_OBJ_CT_HELPER_L3PROTO))
103  mnl_attr_put_u16(nlh, NFTA_CT_HELPER_L3PROTO, htons(helper->l3proto));
104  if (e->flags & (1 << NFTNL_OBJ_CT_HELPER_L4PROTO))
105  mnl_attr_put_u8(nlh, NFTA_CT_HELPER_L4PROTO, helper->l4proto);
106 }
107 
108 static int
109 nftnl_obj_ct_helper_parse(struct nftnl_obj *e, struct nlattr *attr)
110 {
111  struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
112  struct nlattr *tb[NFTA_CT_HELPER_MAX + 1] = {};
113 
114  if (mnl_attr_parse_nested(attr, nftnl_obj_ct_helper_cb, tb) < 0)
115  return -1;
116 
117  if (tb[NFTA_CT_HELPER_NAME]) {
118  snprintf(helper->name, sizeof(helper->name), "%s",
119  mnl_attr_get_str(tb[NFTA_CT_HELPER_NAME]));
120  e->flags |= (1 << NFTNL_OBJ_CT_HELPER_NAME);
121  }
122  if (tb[NFTA_CT_HELPER_L3PROTO]) {
123  helper->l3proto = ntohs(mnl_attr_get_u16(tb[NFTA_CT_HELPER_L3PROTO]));
124  e->flags |= (1 << NFTNL_OBJ_CT_HELPER_L3PROTO);
125  }
126  if (tb[NFTA_CT_HELPER_L4PROTO]) {
127  helper->l4proto = mnl_attr_get_u8(tb[NFTA_CT_HELPER_L4PROTO]);
128  e->flags |= (1 << NFTNL_OBJ_CT_HELPER_L4PROTO);
129  }
130 
131  return 0;
132 }
133 
134 static int nftnl_obj_ct_helper_snprintf(char *buf, size_t len,
135  uint32_t flags,
136  const struct nftnl_obj *e)
137 {
138  struct nftnl_obj_ct_helper *helper = nftnl_obj_data(e);
139 
140  return snprintf(buf, len, "name %s family %d protocol %d ",
141  helper->name, helper->l3proto, helper->l4proto);
142 }
143 
144 struct obj_ops obj_ops_ct_helper = {
145  .name = "ct_helper",
146  .type = NFT_OBJECT_CT_HELPER,
147  .alloc_len = sizeof(struct nftnl_obj_ct_helper),
148  .max_attr = NFTA_CT_HELPER_MAX,
149  .set = nftnl_obj_ct_helper_set,
150  .get = nftnl_obj_ct_helper_get,
151  .parse = nftnl_obj_ct_helper_parse,
152  .build = nftnl_obj_ct_helper_build,
153  .output = nftnl_obj_ct_helper_snprintf,
154 };