libnl 3.11.0
xfrmi.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2019 Eyal Birger <eyal.birger@gmail.com>
4 *
5 * Based on lib/route/link/ipvti.c
6 */
7
8/**
9 * @ingroup link
10 * @defgroup xfrmi XFRMI
11 * xfrmi link module
12 *
13 * @details
14 * \b Link Type Name: "xfrmi"
15 *
16 * @route_doc{link_xfrmi, XFRMI Documentation}
17 *
18 * @{
19 */
20
21#include "nl-default.h"
22
23#include <netlink/netlink.h>
24#include <netlink/attr.h>
25#include <netlink/utils.h>
26#include <netlink/object.h>
27#include <netlink/route/rtnl.h>
28#include <netlink/route/link/xfrmi.h>
29
30#include "nl-route.h"
31#include "link-api.h"
32
33#define XFRMI_ATTR_LINK (1 << 0)
34#define XFRMI_ATTR_IF_ID (1 << 1)
35
36#define XFRMI_LINK_TYPE_NAME "xfrm"
37
38struct xfrmi_info {
39 uint32_t link;
40 uint32_t if_id;
41 uint32_t xfrmi_mask;
42};
43
44static struct nla_policy xfrmi_policy[IFLA_XFRM_MAX + 1] = {
45 [IFLA_XFRM_LINK] = { .type = NLA_U32 },
46 [IFLA_XFRM_IF_ID] = { .type = NLA_U32 },
47};
48
49static int xfrmi_alloc(struct rtnl_link *link)
50{
51 struct xfrmi_info *xfrmi;
52
53 if (link->l_info)
54 memset(link->l_info, 0, sizeof(*xfrmi));
55 else {
56 xfrmi = calloc(1, sizeof(*xfrmi));
57 if (!xfrmi)
58 return -NLE_NOMEM;
59
60 link->l_info = xfrmi;
61 }
62
63 return 0;
64}
65
66static int xfrmi_parse(struct rtnl_link *link, struct nlattr *data,
67 struct nlattr *xstats)
68{
69 struct nlattr *tb[IFLA_XFRM_MAX + 1];
70 struct xfrmi_info *xfrmi;
71 int err;
72
73 NL_DBG(3, "Parsing XFRMI link info\n");
74
75 err = nla_parse_nested(tb, IFLA_XFRM_MAX, data, xfrmi_policy);
76 if (err < 0)
77 return err;
78
79 err = xfrmi_alloc(link);
80 if (err < 0)
81 return err;
82
83 xfrmi = link->l_info;
84
85 if (tb[IFLA_XFRM_LINK]) {
86 xfrmi->link = nla_get_u32(tb[IFLA_XFRM_LINK]);
87 xfrmi->xfrmi_mask |= XFRMI_ATTR_LINK;
88 }
89
90 if (tb[IFLA_XFRM_IF_ID]) {
91 xfrmi->if_id = nla_get_u32(tb[IFLA_XFRM_IF_ID]);
92 xfrmi->xfrmi_mask |= XFRMI_ATTR_IF_ID;
93 }
94
95 return 0;
96}
97
98static int xfrmi_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
99{
100 struct xfrmi_info *xfrmi = link->l_info;
101 struct nlattr *data;
102
103 data = nla_nest_start(msg, IFLA_INFO_DATA);
104 if (!data)
105 return -NLE_MSGSIZE;
106
107 if (xfrmi->xfrmi_mask & XFRMI_ATTR_LINK)
108 NLA_PUT_U32(msg, IFLA_XFRM_LINK, xfrmi->link);
109
110 if (xfrmi->xfrmi_mask & XFRMI_ATTR_IF_ID)
111 NLA_PUT_U32(msg, IFLA_XFRM_IF_ID, xfrmi->if_id);
112
113 nla_nest_end(msg, data);
114
115nla_put_failure:
116 return 0;
117}
118
119static void xfrmi_free(struct rtnl_link *link)
120{
121 struct xfrmi_info *xfrmi = link->l_info;
122
123 free(xfrmi);
124 link->l_info = NULL;
125}
126
127static void xfrmi_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
128{
129 nl_dump(p, "xfrmi : %s", link->l_name);
130}
131
132static void xfrmi_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
133{
134 struct xfrmi_info *xfrmi = link->l_info;
135
136 if (xfrmi->xfrmi_mask & XFRMI_ATTR_LINK) {
137 struct rtnl_link *parent;
138 char *name;
139
140 nl_dump(p, " link ");
141
142 name = NULL;
143 parent = link_lookup(link->ce_cache, xfrmi->link);
144 if (parent)
145 name = rtnl_link_get_name(parent);
146
147 if (name)
148 nl_dump_line(p, "%s\n", name);
149 else
150 nl_dump_line(p, "%u\n", xfrmi->link);
151 }
152
153 if (xfrmi->xfrmi_mask & XFRMI_ATTR_IF_ID) {
154 nl_dump(p, " if_id ");
155 nl_dump_line(p, "%x\n", xfrmi->if_id);
156 }
157}
158
159static int xfrmi_clone(struct rtnl_link *dst, struct rtnl_link *src)
160{
161 struct xfrmi_info *xfrmi_dst, *xfrmi_src = src->l_info;
162 int err;
163
164 dst->l_info = NULL;
165
166 err = rtnl_link_set_type(dst, XFRMI_LINK_TYPE_NAME);
167 if (err < 0)
168 return err;
169
170 xfrmi_dst = dst->l_info;
171
172 if (!xfrmi_dst || !xfrmi_src)
173 BUG();
174
175 memcpy(xfrmi_dst, xfrmi_src, sizeof(struct xfrmi_info));
176
177 return 0;
178}
179
180static struct rtnl_link_info_ops xfrmi_info_ops = {
181 .io_name = XFRMI_LINK_TYPE_NAME,
182 .io_alloc = xfrmi_alloc,
183 .io_parse = xfrmi_parse,
184 .io_dump = {
185 [NL_DUMP_LINE] = xfrmi_dump_line,
186 [NL_DUMP_DETAILS] = xfrmi_dump_details,
187 },
188 .io_clone = xfrmi_clone,
189 .io_put_attrs = xfrmi_put_attrs,
190 .io_free = xfrmi_free,
191};
192
193#define IS_XFRMI_LINK_ASSERT(link) do { \
194 if ((link)->l_info_ops != &xfrmi_info_ops) { \
195 APPBUG("Link is not a xfrmi link. set type \"xfrmi\" first."); \
196 return -NLE_OPNOTSUPP; \
197 } \
198 } while(0)
199
200struct rtnl_link *rtnl_link_xfrmi_alloc(void)
201{
202 struct rtnl_link *link;
203 int err;
204
205 link = rtnl_link_alloc();
206 if (!link)
207 return NULL;
208
209 err = rtnl_link_set_type(link, XFRMI_LINK_TYPE_NAME);
210 if (err < 0) {
211 rtnl_link_put(link);
212 return NULL;
213 }
214
215 return link;
216}
217
218/**
219 * Check if link is a XFRMI link
220 * @arg link Link object
221 *
222 * @return True if link is a IXFRMI link, otherwise 0 is returned.
223 */
225{
226 return link->l_info_ops && !strcmp(link->l_info_ops->io_name,
227 XFRMI_LINK_TYPE_NAME);
228}
229
230/**
231 * Set XFRMI link interface index
232 * @arg link Link object
233 * @arg index interface index
234 *
235 * @return 0 on success or a negative error code
236 */
237int rtnl_link_xfrmi_set_link(struct rtnl_link *link, uint32_t index)
238{
239 struct xfrmi_info *xfrmi = link->l_info;
240
241 IS_XFRMI_LINK_ASSERT(link);
242
243 xfrmi->link = index;
244 xfrmi->xfrmi_mask |= XFRMI_ATTR_LINK;
245
246 return 0;
247}
248
249/**
250 * Get XFRMI link interface index
251 * @arg link Link object
252 * @arg out_link The output value on success
253 *
254 * @return 0 on success or a negative error code
255 */
256int rtnl_link_xfrmi_get_link(struct rtnl_link *link, uint32_t *out_link)
257{
258 struct xfrmi_info *xfrmi = link->l_info;
259
260 IS_XFRMI_LINK_ASSERT(link);
261
262 if (!(xfrmi->xfrmi_mask & XFRMI_ATTR_LINK))
263 return -NLE_NOATTR;
264
265 *out_link = xfrmi->link;
266 return 0;
267}
268
269/**
270 * Set XFRMI if_id
271 * @arg link Link object
272 * @arg if_id xfrm if_id
273 *
274 * @return 0 on success or a negative error code
275 */
276int rtnl_link_xfrmi_set_if_id(struct rtnl_link *link, uint32_t if_id)
277{
278 struct xfrmi_info *xfrmi = link->l_info;
279
280 IS_XFRMI_LINK_ASSERT(link);
281
282 xfrmi->if_id = if_id;
283 xfrmi->xfrmi_mask |= XFRMI_ATTR_IF_ID;
284
285 return 0;
286}
287
288/**
289 * Get XFRMI if_id
290 * @arg link Link object
291 * @arg out_if_id The output value on success
292 *
293 * @return 0 on success or a negative error code
294 */
295int rtnl_link_xfrmi_get_if_id(struct rtnl_link *link, uint32_t *out_if_id)
296{
297 struct xfrmi_info *xfrmi = link->l_info;
298
299 IS_XFRMI_LINK_ASSERT(link);
300
301 if (!(xfrmi->xfrmi_mask & XFRMI_ATTR_IF_ID))
302 return -NLE_NOATTR;
303
304 *out_if_id = xfrmi->if_id;
305 return 0;
306}
307
308static void _nl_init xfrmi_init(void)
309{
310 rtnl_link_register_info(&xfrmi_info_ops);
311}
312
313static void _nl_exit xfrmi_exit(void)
314{
315 rtnl_link_unregister_info(&xfrmi_info_ops);
316}
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition attr.c:714
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition attr.h:237
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition attr.c:974
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition attr.c:1101
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition attr.c:1037
@ NLA_U32
32 bit integer
Definition attr.h:37
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1015
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition types.h:20
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition types.h:21
int rtnl_link_xfrmi_set_link(struct rtnl_link *link, uint32_t index)
Set XFRMI link interface index.
Definition xfrmi.c:237
int rtnl_link_is_xfrmi(struct rtnl_link *link)
Check if link is a XFRMI link.
Definition xfrmi.c:224
int rtnl_link_xfrmi_set_if_id(struct rtnl_link *link, uint32_t if_id)
Set XFRMI if_id.
Definition xfrmi.c:276
int rtnl_link_xfrmi_get_if_id(struct rtnl_link *link, uint32_t *out_if_id)
Get XFRMI if_id.
Definition xfrmi.c:295
int rtnl_link_xfrmi_get_link(struct rtnl_link *link, uint32_t *out_link)
Get XFRMI link interface index.
Definition xfrmi.c:256
Dumping parameters.
Definition types.h:32
Attribute validation policy.
Definition attr.h:66
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition attr.h:68