libnftnl  1.2.8
objref.c
1 /*
2  * (C) 2016 by Pablo Neira Ayuso <pablo@netfilter.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published
6  * by the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  */
9 
10 #include <stdio.h>
11 #include <stdint.h>
12 #include <arpa/inet.h>
13 #include <errno.h>
14 #include <inttypes.h>
15 
16 #include <linux/netfilter/nf_tables.h>
17 
18 #include "internal.h"
19 #include <libmnl/libmnl.h>
20 #include <libnftnl/expr.h>
21 #include <libnftnl/rule.h>
22 
24  struct {
25  uint32_t type;
26  const char *name;
27  } imm;
28  struct {
29  uint32_t sreg;
30  const char *name;
31  uint32_t id;
32  } set;
33 };
34 
35 static int nftnl_expr_objref_set(struct nftnl_expr *e, uint16_t type,
36  const void *data, uint32_t data_len)
37 {
38  struct nftnl_expr_objref *objref = nftnl_expr_data(e);
39 
40  switch(type) {
41  case NFTNL_EXPR_OBJREF_IMM_TYPE:
42  memcpy(&objref->imm.type, data, data_len);
43  break;
44  case NFTNL_EXPR_OBJREF_IMM_NAME:
45  objref->imm.name = strdup(data);
46  if (!objref->imm.name)
47  return -1;
48  break;
49  case NFTNL_EXPR_OBJREF_SET_SREG:
50  memcpy(&objref->set.sreg, data, data_len);
51  break;
52  case NFTNL_EXPR_OBJREF_SET_NAME:
53  objref->set.name = strdup(data);
54  if (!objref->set.name)
55  return -1;
56  break;
57  case NFTNL_EXPR_OBJREF_SET_ID:
58  memcpy(&objref->set.id, data, data_len);
59  break;
60  }
61  return 0;
62 }
63 
64 static const void *nftnl_expr_objref_get(const struct nftnl_expr *e,
65  uint16_t type, uint32_t *data_len)
66 {
67  struct nftnl_expr_objref *objref = nftnl_expr_data(e);
68 
69  switch(type) {
70  case NFTNL_EXPR_OBJREF_IMM_TYPE:
71  *data_len = sizeof(objref->imm.type);
72  return &objref->imm.type;
73  case NFTNL_EXPR_OBJREF_IMM_NAME:
74  *data_len = strlen(objref->imm.name) + 1;
75  return objref->imm.name;
76  case NFTNL_EXPR_OBJREF_SET_SREG:
77  *data_len = sizeof(objref->set.sreg);
78  return &objref->set.sreg;
79  case NFTNL_EXPR_OBJREF_SET_NAME:
80  *data_len = strlen(objref->set.name) + 1;
81  return objref->set.name;
82  case NFTNL_EXPR_OBJREF_SET_ID:
83  *data_len = sizeof(objref->set.id);
84  return &objref->set.id;
85  }
86  return NULL;
87 }
88 
89 static int nftnl_expr_objref_cb(const struct nlattr *attr, void *data)
90 {
91  int type = mnl_attr_get_type(attr);
92  const struct nlattr **tb = data;
93 
94  if (mnl_attr_type_valid(attr, NFTA_OBJREF_MAX) < 0)
95  return MNL_CB_OK;
96 
97  switch(type) {
98  case NFTA_OBJREF_IMM_TYPE:
99  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
100  abi_breakage();
101  break;
102  case NFTA_OBJREF_IMM_NAME:
103  case NFTA_OBJREF_SET_NAME:
104  if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
105  abi_breakage();
106  break;
107  case NFTA_OBJREF_SET_SREG:
108  case NFTA_OBJREF_SET_ID:
109  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
110  abi_breakage();
111  break;
112  }
113 
114  tb[type] = attr;
115  return MNL_CB_OK;
116 }
117 
118 static void nftnl_expr_objref_build(struct nlmsghdr *nlh,
119  const struct nftnl_expr *e)
120 {
121  struct nftnl_expr_objref *objref = nftnl_expr_data(e);
122 
123  if (e->flags & (1 << NFTNL_EXPR_OBJREF_IMM_TYPE))
124  mnl_attr_put_u32(nlh, NFTA_OBJREF_IMM_TYPE,
125  htonl(objref->imm.type));
126  if (e->flags & (1 << NFTNL_EXPR_OBJREF_IMM_NAME))
127  mnl_attr_put_str(nlh, NFTA_OBJREF_IMM_NAME, objref->imm.name);
128  if (e->flags & (1 << NFTNL_EXPR_OBJREF_SET_SREG))
129  mnl_attr_put_u32(nlh, NFTA_OBJREF_SET_SREG,
130  htonl(objref->set.sreg));
131  if (e->flags & (1 << NFTNL_EXPR_OBJREF_SET_NAME))
132  mnl_attr_put_str(nlh, NFTA_OBJREF_SET_NAME, objref->set.name);
133  if (e->flags & (1 << NFTNL_EXPR_OBJREF_SET_ID))
134  mnl_attr_put_u32(nlh, NFTA_OBJREF_SET_ID,
135  htonl(objref->set.id));
136 }
137 
138 static int nftnl_expr_objref_parse(struct nftnl_expr *e, struct nlattr *attr)
139 {
140  struct nftnl_expr_objref *objref = nftnl_expr_data(e);
141  struct nlattr *tb[NFTA_OBJREF_MAX + 1] = {};
142 
143  if (mnl_attr_parse_nested(attr, nftnl_expr_objref_cb, tb) < 0)
144  return -1;
145 
146  if (tb[NFTA_OBJREF_IMM_TYPE]) {
147  objref->imm.type =
148  ntohl(mnl_attr_get_u32(tb[NFTA_OBJREF_IMM_TYPE]));
149  e->flags |= (1 << NFTNL_EXPR_OBJREF_IMM_TYPE);
150  }
151  if (tb[NFTA_OBJREF_IMM_NAME]) {
152  objref->imm.name =
153  strdup(mnl_attr_get_str(tb[NFTA_OBJREF_IMM_NAME]));
154  e->flags |= (1 << NFTNL_EXPR_OBJREF_IMM_NAME);
155  }
156  if (tb[NFTA_OBJREF_SET_SREG]) {
157  objref->set.sreg =
158  ntohl(mnl_attr_get_u32(tb[NFTA_OBJREF_SET_SREG]));
159  e->flags |= (1 << NFTNL_EXPR_OBJREF_SET_SREG);
160  }
161  if (tb[NFTA_OBJREF_SET_NAME]) {
162  objref->set.name =
163  strdup(mnl_attr_get_str(tb[NFTA_OBJREF_SET_NAME]));
164  e->flags |= (1 << NFTNL_EXPR_OBJREF_SET_NAME);
165  }
166  if (tb[NFTA_OBJREF_SET_ID]) {
167  objref->set.id =
168  ntohl(mnl_attr_get_u32(tb[NFTA_OBJREF_SET_ID]));
169  e->flags |= (1 << NFTNL_EXPR_OBJREF_SET_ID);
170  }
171 
172  return 0;
173 }
174 
175 static int nftnl_expr_objref_snprintf(char *buf, size_t len,
176  uint32_t flags,
177  const struct nftnl_expr *e)
178 {
179  struct nftnl_expr_objref *objref = nftnl_expr_data(e);
180 
181  if (e->flags & (1 << NFTNL_EXPR_OBJREF_SET_SREG))
182  return snprintf(buf, len, "sreg %u set %s ",
183  objref->set.sreg, objref->set.name);
184  else
185  return snprintf(buf, len, "type %u name %s ",
186  objref->imm.type, objref->imm.name);
187 }
188 
189 static void nftnl_expr_objref_free(const struct nftnl_expr *e)
190 {
191  struct nftnl_expr_objref *objref = nftnl_expr_data(e);
192 
193  xfree(objref->imm.name);
194  xfree(objref->set.name);
195 }
196 
197 static struct attr_policy objref_attr_policy[__NFTNL_EXPR_OBJREF_MAX] = {
198  [NFTNL_EXPR_OBJREF_IMM_TYPE] = { .maxlen = sizeof(uint32_t) },
199  [NFTNL_EXPR_OBJREF_IMM_NAME] = { .maxlen = NFT_NAME_MAXLEN },
200  [NFTNL_EXPR_OBJREF_SET_SREG] = { .maxlen = sizeof(uint32_t) },
201  [NFTNL_EXPR_OBJREF_SET_NAME] = { .maxlen = NFT_NAME_MAXLEN },
202  [NFTNL_EXPR_OBJREF_SET_ID] = { .maxlen = sizeof(uint32_t) },
203 };
204 
205 struct expr_ops expr_ops_objref = {
206  .name = "objref",
207  .alloc_len = sizeof(struct nftnl_expr_objref),
208  .nftnl_max_attr = __NFTNL_EXPR_OBJREF_MAX - 1,
209  .attr_policy = objref_attr_policy,
210  .free = nftnl_expr_objref_free,
211  .set = nftnl_expr_objref_set,
212  .get = nftnl_expr_objref_get,
213  .parse = nftnl_expr_objref_parse,
214  .build = nftnl_expr_objref_build,
215  .output = nftnl_expr_objref_snprintf,
216 };