libnftnl  1.2.9
expr/tunnel.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * (C) 2018 by Pablo Neira Ayuso <pablo@netfilter.org>
4  */
5 
6 #include <stdio.h>
7 #include <stdint.h>
8 #include <string.h>
9 #include <arpa/inet.h>
10 #include <errno.h>
11 #include <linux/netfilter/nf_tables.h>
12 
13 #include "internal.h"
14 #include <libmnl/libmnl.h>
15 #include <libnftnl/expr.h>
16 #include <libnftnl/rule.h>
17 
19  enum nft_tunnel_keys key;
20  enum nft_registers dreg;
21 };
22 
23 static int nftnl_expr_tunnel_set(struct nftnl_expr *e, uint16_t type,
24  const void *data, uint32_t data_len)
25 {
26  struct nftnl_expr_tunnel *tunnel = nftnl_expr_data(e);
27 
28  switch(type) {
29  case NFTNL_EXPR_TUNNEL_KEY:
30  memcpy(&tunnel->key, data, data_len);
31  break;
32  case NFTNL_EXPR_TUNNEL_DREG:
33  memcpy(&tunnel->dreg, data, data_len);
34  break;
35  }
36  return 0;
37 }
38 
39 static const void *
40 nftnl_expr_tunnel_get(const struct nftnl_expr *e, uint16_t type,
41  uint32_t *data_len)
42 {
43  struct nftnl_expr_tunnel *tunnel = nftnl_expr_data(e);
44 
45  switch(type) {
46  case NFTNL_EXPR_TUNNEL_KEY:
47  *data_len = sizeof(tunnel->key);
48  return &tunnel->key;
49  case NFTNL_EXPR_TUNNEL_DREG:
50  *data_len = sizeof(tunnel->dreg);
51  return &tunnel->dreg;
52  }
53  return NULL;
54 }
55 
56 static int nftnl_expr_tunnel_cb(const struct nlattr *attr, void *data)
57 {
58  const struct nlattr **tb = data;
59  int type = mnl_attr_get_type(attr);
60 
61  if (mnl_attr_type_valid(attr, NFTA_TUNNEL_MAX) < 0)
62  return MNL_CB_OK;
63 
64  switch(type) {
65  case NFTA_TUNNEL_KEY:
66  case NFTA_TUNNEL_DREG:
67  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
68  abi_breakage();
69  break;
70  }
71 
72  tb[type] = attr;
73  return MNL_CB_OK;
74 }
75 
76 static void
77 nftnl_expr_tunnel_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
78 {
79  struct nftnl_expr_tunnel *tunnel = nftnl_expr_data(e);
80 
81  if (e->flags & (1 << NFTNL_EXPR_TUNNEL_KEY))
82  mnl_attr_put_u32(nlh, NFTA_TUNNEL_KEY, htonl(tunnel->key));
83  if (e->flags & (1 << NFTNL_EXPR_TUNNEL_DREG))
84  mnl_attr_put_u32(nlh, NFTA_TUNNEL_DREG, htonl(tunnel->dreg));
85 }
86 
87 static int
88 nftnl_expr_tunnel_parse(struct nftnl_expr *e, struct nlattr *attr)
89 {
90  struct nftnl_expr_tunnel *tunnel = nftnl_expr_data(e);
91  struct nlattr *tb[NFTA_TUNNEL_MAX + 1] = {};
92 
93  if (mnl_attr_parse_nested(attr, nftnl_expr_tunnel_cb, tb) < 0)
94  return -1;
95 
96  if (tb[NFTA_TUNNEL_KEY]) {
97  tunnel->key = ntohl(mnl_attr_get_u32(tb[NFTA_TUNNEL_KEY]));
98  e->flags |= (1 << NFTNL_EXPR_TUNNEL_KEY);
99  }
100  if (tb[NFTA_TUNNEL_DREG]) {
101  tunnel->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_TUNNEL_DREG]));
102  e->flags |= (1 << NFTNL_EXPR_TUNNEL_DREG);
103  }
104 
105  return 0;
106 }
107 
108 static const char *tunnel_key2str_array[NFT_TUNNEL_MAX + 1] = {
109  [NFT_TUNNEL_PATH] = "path",
110  [NFT_TUNNEL_ID] = "id",
111 };
112 
113 static const char *tunnel_key2str(uint8_t key)
114 {
115  if (key <= NFT_TUNNEL_MAX)
116  return tunnel_key2str_array[key];
117 
118  return "unknown";
119 }
120 
121 static int
122 nftnl_expr_tunnel_snprintf(char *buf, size_t len,
123  uint32_t flags, const struct nftnl_expr *e)
124 {
125  struct nftnl_expr_tunnel *tunnel = nftnl_expr_data(e);
126 
127  if (e->flags & (1 << NFTNL_EXPR_TUNNEL_DREG)) {
128  return snprintf(buf, len, "load %s => reg %u ",
129  tunnel_key2str(tunnel->key), tunnel->dreg);
130  }
131  return 0;
132 }
133 
134 static struct attr_policy tunnel_attr_policy[__NFTNL_EXPR_TUNNEL_MAX] = {
135  [NFTNL_EXPR_TUNNEL_KEY] = { .maxlen = sizeof(uint32_t) },
136  [NFTNL_EXPR_TUNNEL_DREG] = { .maxlen = sizeof(uint32_t) },
137 };
138 
139 struct expr_ops expr_ops_tunnel = {
140  .name = "tunnel",
141  .alloc_len = sizeof(struct nftnl_expr_tunnel),
142  .nftnl_max_attr = __NFTNL_EXPR_TUNNEL_MAX - 1,
143  .attr_policy = tunnel_attr_policy,
144  .set = nftnl_expr_tunnel_set,
145  .get = nftnl_expr_tunnel_get,
146  .parse = nftnl_expr_tunnel_parse,
147  .build = nftnl_expr_tunnel_build,
148  .output = nftnl_expr_tunnel_snprintf,
149 };