libnftnl  1.0.2
expr.c
1 /*
2  * (C) 2012 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  * This code has been sponsored by Sophos Astaro <http://www.sophos.com>
10  */
11 #include "internal.h"
12 #include "expr_ops.h"
13 
14 #include <time.h>
15 #include <endian.h>
16 #include <stdint.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <netinet/in.h>
20 
21 #include <libmnl/libmnl.h>
22 #include <linux/netfilter/nfnetlink.h>
23 #include <linux/netfilter/nf_tables.h>
24 
25 #include <libnftnl/expr.h>
26 
27 #include "linux_list.h"
28 
29 struct nft_rule_expr *nft_rule_expr_alloc(const char *name)
30 {
31  struct nft_rule_expr *expr;
32  struct expr_ops *ops;
33 
34  ops = nft_expr_ops_lookup(name);
35  if (ops == NULL)
36  return NULL;
37 
38  expr = calloc(1, sizeof(struct nft_rule_expr) + ops->alloc_len);
39  if (expr == NULL)
40  return NULL;
41 
42  /* Manually set expression name attribute */
43  expr->flags |= (1 << NFT_RULE_EXPR_ATTR_NAME);
44  expr->ops = ops;
45 
46  return expr;
47 }
48 EXPORT_SYMBOL(nft_rule_expr_alloc);
49 
50 void nft_rule_expr_free(struct nft_rule_expr *expr)
51 {
52  if (expr->ops->free)
53  expr->ops->free(expr);
54 
55  xfree(expr);
56 }
57 EXPORT_SYMBOL(nft_rule_expr_free);
58 
59 bool nft_rule_expr_is_set(const struct nft_rule_expr *expr, uint16_t type)
60 {
61  return expr->flags & (1 << type);
62 }
63 EXPORT_SYMBOL(nft_rule_expr_is_set);
64 
65 void
66 nft_rule_expr_set(struct nft_rule_expr *expr, uint16_t type,
67  const void *data, uint32_t data_len)
68 {
69  switch(type) {
70  case NFT_RULE_EXPR_ATTR_NAME: /* cannot be modified */
71  return;
72  default:
73  if (expr->ops->set(expr, type, data, data_len) < 0)
74  return;
75  }
76  expr->flags |= (1 << type);
77 }
78 EXPORT_SYMBOL(nft_rule_expr_set);
79 
80 void
81 nft_rule_expr_set_u8(struct nft_rule_expr *expr, uint16_t type, uint8_t data)
82 {
83  nft_rule_expr_set(expr, type, &data, sizeof(uint8_t));
84 }
85 EXPORT_SYMBOL(nft_rule_expr_set_u8);
86 
87 void
88 nft_rule_expr_set_u16(struct nft_rule_expr *expr, uint16_t type, uint16_t data)
89 {
90  nft_rule_expr_set(expr, type, &data, sizeof(uint16_t));
91 }
92 EXPORT_SYMBOL(nft_rule_expr_set_u16);
93 
94 void
95 nft_rule_expr_set_u32(struct nft_rule_expr *expr, uint16_t type, uint32_t data)
96 {
97  nft_rule_expr_set(expr, type, &data, sizeof(uint32_t));
98 }
99 EXPORT_SYMBOL(nft_rule_expr_set_u32);
100 
101 void
102 nft_rule_expr_set_u64(struct nft_rule_expr *expr, uint16_t type, uint64_t data)
103 {
104  nft_rule_expr_set(expr, type, &data, sizeof(uint64_t));
105 }
106 EXPORT_SYMBOL(nft_rule_expr_set_u64);
107 
108 void
109 nft_rule_expr_set_str(struct nft_rule_expr *expr, uint16_t type, const char *str)
110 {
111  nft_rule_expr_set(expr, type, str, strlen(str)+1);
112 }
113 EXPORT_SYMBOL(nft_rule_expr_set_str);
114 
115 const void *nft_rule_expr_get(const struct nft_rule_expr *expr,
116  uint16_t type, uint32_t *data_len)
117 {
118  const void *ret;
119 
120  if (!(expr->flags & (1 << type)))
121  return NULL;
122 
123  switch(type) {
124  case NFT_RULE_EXPR_ATTR_NAME:
125  ret = expr->ops->name;
126  break;
127  default:
128  ret = expr->ops->get(expr, type, data_len);
129  break;
130  }
131 
132  return ret;
133 }
134 EXPORT_SYMBOL(nft_rule_expr_get);
135 
136 uint8_t nft_rule_expr_get_u8(const struct nft_rule_expr *expr, uint16_t type)
137 {
138  const void *data;
139  uint32_t data_len;
140 
141  data = nft_rule_expr_get(expr, type, &data_len);
142  if (data == NULL)
143  return 0;
144 
145  if (data_len != sizeof(uint8_t))
146  return 0;
147 
148  return *((uint8_t *)data);
149 }
150 EXPORT_SYMBOL(nft_rule_expr_get_u8);
151 
152 uint16_t nft_rule_expr_get_u16(const struct nft_rule_expr *expr, uint16_t type)
153 {
154  const void *data;
155  uint32_t data_len;
156 
157  data = nft_rule_expr_get(expr, type, &data_len);
158  if (data == NULL)
159  return 0;
160 
161  if (data_len != sizeof(uint16_t))
162  return 0;
163 
164  return *((uint16_t *)data);
165 }
166 EXPORT_SYMBOL(nft_rule_expr_get_u16);
167 
168 uint32_t nft_rule_expr_get_u32(const struct nft_rule_expr *expr, uint16_t type)
169 {
170  const void *data;
171  uint32_t data_len;
172 
173  data = nft_rule_expr_get(expr, type, &data_len);
174  if (data == NULL)
175  return 0;
176 
177  if (data_len != sizeof(uint32_t))
178  return 0;
179 
180  return *((uint32_t *)data);
181 }
182 EXPORT_SYMBOL(nft_rule_expr_get_u32);
183 
184 uint64_t nft_rule_expr_get_u64(const struct nft_rule_expr *expr, uint16_t type)
185 {
186  const void *data;
187  uint32_t data_len;
188 
189  data = nft_rule_expr_get(expr, type, &data_len);
190  if (data == NULL)
191  return 0;
192 
193  if (data_len != sizeof(uint64_t))
194  return 0;
195 
196  return *((uint64_t *)data);
197 }
198 EXPORT_SYMBOL(nft_rule_expr_get_u64);
199 
200 const char *nft_rule_expr_get_str(const struct nft_rule_expr *expr, uint16_t type)
201 {
202  uint32_t data_len;
203 
204  return (const char *)nft_rule_expr_get(expr, type, &data_len);
205 }
206 EXPORT_SYMBOL(nft_rule_expr_get_str);
207 
208 void
209 nft_rule_expr_build_payload(struct nlmsghdr *nlh, struct nft_rule_expr *expr)
210 {
211  struct nlattr *nest1, *nest2;
212 
213  nest1 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
214  mnl_attr_put_strz(nlh, NFTA_EXPR_NAME, expr->ops->name);
215 
216  nest2 = mnl_attr_nest_start(nlh, NFTA_EXPR_DATA);
217  expr->ops->build(nlh, expr);
218  mnl_attr_nest_end(nlh, nest2);
219 
220  mnl_attr_nest_end(nlh, nest1);
221 }
222 EXPORT_SYMBOL(nft_rule_expr_build_payload);
223 
224 int nft_rule_expr_snprintf(char *buf, size_t size, struct nft_rule_expr *expr,
225  uint32_t type, uint32_t flags)
226 {
227  int ret;
228  unsigned int offset = 0, len = size;
229 
230  ret = expr->ops->snprintf(buf+offset, len, type, flags, expr);
231  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
232 
233  return offset;
234 }
235 EXPORT_SYMBOL(nft_rule_expr_snprintf);