libnftnl 1.2.6
xfrm.c
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published
4 * by the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 */
7
8#include <stdio.h>
9#include <string.h>
10#include <stdint.h>
11#include <arpa/inet.h>
12#include <errno.h>
13#include <linux/netfilter/nf_tables.h>
14#include <linux/xfrm.h>
15
16#include "internal.h"
17#include <libmnl/libmnl.h>
18#include <libnftnl/expr.h>
19#include <libnftnl/rule.h>
20
22 enum nft_registers dreg;
23 enum nft_xfrm_keys key;
24 uint32_t spnum;
25 uint8_t dir;
26};
27
28static int
29nftnl_expr_xfrm_set(struct nftnl_expr *e, uint16_t type,
30 const void *data, uint32_t data_len)
31{
32 struct nftnl_expr_xfrm *x = nftnl_expr_data(e);
33
34 switch(type) {
35 case NFTNL_EXPR_XFRM_KEY:
36 memcpy(&x->key, data, sizeof(x->key));
37 break;
38 case NFTNL_EXPR_XFRM_DIR:
39 memcpy(&x->dir, data, sizeof(x->dir));
40 break;
41 case NFTNL_EXPR_XFRM_SPNUM:
42 memcpy(&x->spnum, data, sizeof(x->spnum));
43 break;
44 case NFTNL_EXPR_XFRM_DREG:
45 memcpy(&x->dreg, data, sizeof(x->dreg));
46 break;
47 default:
48 return -1;
49 }
50 return 0;
51}
52
53static const void *
54nftnl_expr_xfrm_get(const struct nftnl_expr *e, uint16_t type,
55 uint32_t *data_len)
56{
57 struct nftnl_expr_xfrm *x = nftnl_expr_data(e);
58
59 switch(type) {
60 case NFTNL_EXPR_XFRM_KEY:
61 *data_len = sizeof(x->key);
62 return &x->key;
63 case NFTNL_EXPR_XFRM_DIR:
64 *data_len = sizeof(x->dir);
65 return &x->dir;
66 case NFTNL_EXPR_XFRM_SPNUM:
67 *data_len = sizeof(x->spnum);
68 return &x->spnum;
69 case NFTNL_EXPR_XFRM_DREG:
70 *data_len = sizeof(x->dreg);
71 return &x->dreg;
72 }
73 return NULL;
74}
75
76static int nftnl_expr_xfrm_cb(const struct nlattr *attr, void *data)
77{
78 const struct nlattr **tb = data;
79 int type = mnl_attr_get_type(attr);
80
81 if (mnl_attr_type_valid(attr, NFTA_XFRM_MAX) < 0)
82 return MNL_CB_OK;
83
84 switch (type) {
85 case NFTA_XFRM_DREG:
86 case NFTA_XFRM_KEY:
87 case NFTA_XFRM_SPNUM:
88 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
89 abi_breakage();
90 break;
91 case NFTA_XFRM_DIR:
92 if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0)
93 abi_breakage();
94 break;
95 }
96
97 tb[type] = attr;
98 return MNL_CB_OK;
99}
100
101static void
102nftnl_expr_xfrm_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
103{
104 struct nftnl_expr_xfrm *x = nftnl_expr_data(e);
105
106 if (e->flags & (1 << NFTNL_EXPR_XFRM_KEY))
107 mnl_attr_put_u32(nlh, NFTA_XFRM_KEY, htonl(x->key));
108 if (e->flags & (1 << NFTNL_EXPR_XFRM_DIR))
109 mnl_attr_put_u8(nlh, NFTA_XFRM_DIR, x->dir);
110 if (e->flags & (1 << NFTNL_EXPR_XFRM_SPNUM))
111 mnl_attr_put_u32(nlh, NFTA_XFRM_SPNUM, htonl(x->spnum));
112 if (e->flags & (1 << NFTNL_EXPR_XFRM_DREG))
113 mnl_attr_put_u32(nlh, NFTA_XFRM_DREG, htonl(x->dreg));
114}
115
116static int
117nftnl_expr_xfrm_parse(struct nftnl_expr *e, struct nlattr *attr)
118{
119 struct nftnl_expr_xfrm *x = nftnl_expr_data(e);
120 struct nlattr *tb[NFTA_XFRM_MAX+1] = {};
121
122 if (mnl_attr_parse_nested(attr, nftnl_expr_xfrm_cb, tb) < 0)
123 return -1;
124
125 if (tb[NFTA_XFRM_KEY]) {
126 x->key = ntohl(mnl_attr_get_u32(tb[NFTA_XFRM_KEY]));
127 e->flags |= (1 << NFTNL_EXPR_XFRM_KEY);
128 }
129 if (tb[NFTA_XFRM_DIR]) {
130 x->dir = mnl_attr_get_u8(tb[NFTA_XFRM_DIR]);
131 e->flags |= (1 << NFTNL_EXPR_XFRM_DIR);
132 }
133 if (tb[NFTA_XFRM_SPNUM]) {
134 x->spnum = ntohl(mnl_attr_get_u32(tb[NFTA_XFRM_SPNUM]));
135 e->flags |= (1 << NFTNL_EXPR_XFRM_SPNUM);
136 }
137 if (tb[NFTA_XFRM_DREG]) {
138 x->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_XFRM_DREG]));
139 e->flags |= (1 << NFTNL_EXPR_XFRM_DREG);
140 }
141 return 0;
142}
143
144static const char *xfrmkey2str_array[] = {
145 [NFT_XFRM_KEY_DADDR_IP4] = "daddr4",
146 [NFT_XFRM_KEY_SADDR_IP4] = "saddr4",
147 [NFT_XFRM_KEY_DADDR_IP6] = "daddr6",
148 [NFT_XFRM_KEY_SADDR_IP6] = "saddr6",
149 [NFT_XFRM_KEY_REQID] = "reqid",
150 [NFT_XFRM_KEY_SPI] = "spi",
151};
152
153static const char *xfrmkey2str(uint32_t key)
154{
155 if (key >= sizeof(xfrmkey2str_array) / sizeof(xfrmkey2str_array[0]))
156 return "unknown";
157
158 return xfrmkey2str_array[key];
159}
160
161static const char *xfrmdir2str_array[] = {
162 [XFRM_POLICY_IN] = "in",
163 [XFRM_POLICY_OUT] = "out",
164};
165
166static const char *xfrmdir2str(uint8_t dir)
167{
168 if (dir >= sizeof(xfrmdir2str_array) / sizeof(xfrmdir2str_array[0]))
169 return "unknown";
170
171 return xfrmdir2str_array[dir];
172}
173
174static int
175nftnl_expr_xfrm_snprintf(char *buf, size_t remain,
176 uint32_t flags, const struct nftnl_expr *e)
177{
178 struct nftnl_expr_xfrm *x = nftnl_expr_data(e);
179 int ret, offset = 0;
180
181 if (e->flags & (1 << NFTNL_EXPR_XFRM_DREG)) {
182 ret = snprintf(buf, remain, "load %s %u %s => reg %u ",
183 xfrmdir2str(x->dir),
184 x->spnum,
185 xfrmkey2str(x->key), x->dreg);
186 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
187 }
188 return offset;
189}
190
191struct expr_ops expr_ops_xfrm = {
192 .name = "xfrm",
193 .alloc_len = sizeof(struct nftnl_expr_xfrm),
194 .max_attr = NFTA_XFRM_MAX,
195 .set = nftnl_expr_xfrm_set,
196 .get = nftnl_expr_xfrm_get,
197 .parse = nftnl_expr_xfrm_parse,
198 .build = nftnl_expr_xfrm_build,
199 .output = nftnl_expr_xfrm_snprintf,
200};