libnl: /data/src/libnl/lib/route/link/xfrmi.c Source File

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