libnl 3.12.0
ipvti.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2014 Susant Sahani <susant@redhat.com>
4 */
5
6/**
7 * @ingroup link
8 * @defgroup ipvti IPVTI
9 * ipvti link module
10 *
11 * @details
12 * \b Link Type Name: "ipvti"
13 *
14 * @route_doc{link_ipvti, IPVTI Documentation}
15 *
16 * @{
17 */
18
19#include "nl-default.h"
20
21#include <linux/if_tunnel.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/ipvti.h>
29
30#include "nl-route.h"
31#include "link-api.h"
32#include "nl-aux-route/nl-route.h"
33
34#define IPVTI_ATTR_LINK (1 << 0)
35#define IPVTI_ATTR_IKEY (1 << 1)
36#define IPVTI_ATTR_OKEY (1 << 2)
37#define IPVTI_ATTR_LOCAL (1 << 3)
38#define IPVTI_ATTR_REMOTE (1 << 4)
39#define IPVTI_ATTR_FWMARK (1 << 5)
40
42{
43 uint32_t link;
44 uint32_t ikey;
45 uint32_t okey;
46 uint32_t local;
47 uint32_t remote;
48 uint32_t fwmark;
49 uint32_t ipvti_mask;
50};
51
52static struct nla_policy ipvti_policy[IFLA_VTI_MAX + 1] = {
53 [IFLA_VTI_LINK] = { .type = NLA_U32 },
54 [IFLA_VTI_IKEY] = { .type = NLA_U32 },
55 [IFLA_VTI_OKEY] = { .type = NLA_U32 },
56 [IFLA_VTI_LOCAL] = { .type = NLA_U32 },
57 [IFLA_VTI_REMOTE] = { .type = NLA_U32 },
58 [IFLA_VTI_FWMARK] = { .type = NLA_U32 },
59};
60
61static int ipvti_alloc(struct rtnl_link *link)
62{
63 struct ipvti_info *ipvti;
64
65 if (link->l_info)
66 memset(link->l_info, 0, sizeof(*ipvti));
67 else {
68 ipvti = calloc(1, sizeof(*ipvti));
69 if (!ipvti)
70 return -NLE_NOMEM;
71
72 link->l_info = ipvti;
73 }
74
75 return 0;
76}
77
78static int ipvti_parse(struct rtnl_link *link, struct nlattr *data,
79 struct nlattr *xstats)
80{
81 struct nlattr *tb[IFLA_VTI_MAX + 1];
82 struct ipvti_info *ipvti;
83 int err;
84
85 NL_DBG(3, "Parsing IPVTI link info\n");
86
87 err = nla_parse_nested(tb, IFLA_VTI_MAX, data, ipvti_policy);
88 if (err < 0)
89 goto errout;
90
91 err = ipvti_alloc(link);
92 if (err < 0)
93 goto errout;
94
95 ipvti = link->l_info;
96
97 if (tb[IFLA_VTI_LINK]) {
98 ipvti->link = nla_get_u32(tb[IFLA_VTI_LINK]);
99 ipvti->ipvti_mask |= IPVTI_ATTR_LINK;
100 }
101
102 if (tb[IFLA_VTI_IKEY]) {
103 ipvti->ikey = nla_get_u32(tb[IFLA_VTI_IKEY]);
104 ipvti->ipvti_mask |= IPVTI_ATTR_IKEY;
105 }
106
107 if (tb[IFLA_VTI_OKEY]) {
108 ipvti->okey = nla_get_u32(tb[IFLA_VTI_OKEY]);
109 ipvti->ipvti_mask |= IPVTI_ATTR_OKEY;
110 }
111
112 if (tb[IFLA_VTI_LOCAL]) {
113 ipvti->local = nla_get_u32(tb[IFLA_VTI_LOCAL]);
114 ipvti->ipvti_mask |= IPVTI_ATTR_LOCAL;
115 }
116
117 if (tb[IFLA_VTI_REMOTE]) {
118 ipvti->remote = nla_get_u32(tb[IFLA_VTI_REMOTE]);
119 ipvti->ipvti_mask |= IPVTI_ATTR_REMOTE;
120 }
121
122 if (tb[IFLA_VTI_FWMARK]) {
123 ipvti->fwmark = nla_get_u32(tb[IFLA_VTI_FWMARK]);
124 ipvti->ipvti_mask |= IPVTI_ATTR_FWMARK;
125 }
126
127 err = 0;
128
129errout:
130 return err;
131}
132
133static int ipvti_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
134{
135 struct ipvti_info *ipvti = link->l_info;
136 struct nlattr *data;
137
138 data = nla_nest_start(msg, IFLA_INFO_DATA);
139 if (!data)
140 return -NLE_MSGSIZE;
141
142 if (ipvti->ipvti_mask & IPVTI_ATTR_LINK)
143 NLA_PUT_U32(msg, IFLA_VTI_LINK, ipvti->link);
144
145 if (ipvti->ipvti_mask & IPVTI_ATTR_IKEY)
146 NLA_PUT_U32(msg, IFLA_VTI_IKEY, ipvti->ikey);
147
148 if (ipvti->ipvti_mask & IPVTI_ATTR_OKEY)
149 NLA_PUT_U32(msg, IFLA_VTI_OKEY, ipvti->okey);
150
151 if (ipvti->ipvti_mask & IPVTI_ATTR_LOCAL)
152 NLA_PUT_U32(msg, IFLA_VTI_LOCAL, ipvti->local);
153
154 if (ipvti->ipvti_mask & IPVTI_ATTR_REMOTE)
155 NLA_PUT_U32(msg, IFLA_VTI_REMOTE, ipvti->remote);
156
157 if (ipvti->ipvti_mask & IPVTI_ATTR_FWMARK)
158 NLA_PUT_U32(msg, IFLA_VTI_FWMARK, ipvti->fwmark);
159
160 nla_nest_end(msg, data);
161
162nla_put_failure:
163
164 return 0;
165}
166
167static void ipvti_free(struct rtnl_link *link)
168{
169 struct ipvti_info *ipvti = link->l_info;
170
171 free(ipvti);
172 link->l_info = NULL;
173}
174
175static void ipvti_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
176{
177 nl_dump(p, "ipvti : %s", link->l_name);
178}
179
180static void ipvti_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
181{
182 struct ipvti_info *ipvti = link->l_info;
183 char addr[INET_ADDRSTRLEN];
184
185 if (ipvti->ipvti_mask & IPVTI_ATTR_LINK) {
186 _nl_auto_rtnl_link struct rtnl_link *parent = NULL;
187 char *name;
188
189 nl_dump(p, " link ");
190
191 name = NULL;
192 parent = link_lookup(link->ce_cache, ipvti->link);
193 if (parent)
194 name = rtnl_link_get_name(parent);
195
196 if (name)
197 nl_dump_line(p, "%s\n", name);
198 else
199 nl_dump_line(p, "%u\n", ipvti->link);
200 }
201
202 if (ipvti->ipvti_mask & IPVTI_ATTR_IKEY) {
203 nl_dump(p, " ikey ");
204 nl_dump_line(p, "%x\n",ipvti->ikey);
205 }
206
207 if (ipvti->ipvti_mask & IPVTI_ATTR_OKEY) {
208 nl_dump(p, " okey ");
209 nl_dump_line(p, "%x\n", ipvti->okey);
210 }
211
212 if (ipvti->ipvti_mask & IPVTI_ATTR_LOCAL) {
213 nl_dump(p, " local ");
214 _nl_inet_ntop4(ipvti->local, addr);
215 nl_dump_line(p, "%s\n", addr);
216 }
217
218 if (ipvti->ipvti_mask & IPVTI_ATTR_REMOTE) {
219 nl_dump(p, " remote ");
220 _nl_inet_ntop4(ipvti->remote, addr);
221 nl_dump_line(p, "%s\n", addr);
222 }
223
224 if (ipvti->ipvti_mask & IPVTI_ATTR_FWMARK) {
225 nl_dump(p, " fwmark ");
226 nl_dump_line(p, "%x\n", ipvti->fwmark);
227 }
228}
229
230static int ipvti_clone(struct rtnl_link *dst, struct rtnl_link *src)
231{
232 struct ipvti_info *ipvti_dst, *ipvti_src = src->l_info;
233 int err;
234
235 dst->l_info = NULL;
236
237 err = rtnl_link_set_type(dst, "vti");
238 if (err < 0)
239 return err;
240
241 ipvti_dst = dst->l_info;
242
243 if (!ipvti_dst || !ipvti_src)
244 BUG();
245
246 memcpy(ipvti_dst, ipvti_src, sizeof(struct ipvti_info));
247
248 return 0;
249}
250
251static struct rtnl_link_info_ops ipvti_info_ops = {
252 .io_name = "vti",
253 .io_alloc = ipvti_alloc,
254 .io_parse = ipvti_parse,
255 .io_dump = {
256 [NL_DUMP_LINE] = ipvti_dump_line,
257 [NL_DUMP_DETAILS] = ipvti_dump_details,
258 },
259 .io_clone = ipvti_clone,
260 .io_put_attrs = ipvti_put_attrs,
261 .io_free = ipvti_free,
262};
263
264#define IS_IPVTI_LINK_ASSERT(link) \
265 if ((link)->l_info_ops != &ipvti_info_ops) { \
266 APPBUG("Link is not a ipvti link. set type \"vti\" first.");\
267 return -NLE_OPNOTSUPP; \
268 }
269
270struct rtnl_link *rtnl_link_ipvti_alloc(void)
271{
272 struct rtnl_link *link;
273 int err;
274
275 link = rtnl_link_alloc();
276 if (!link)
277 return NULL;
278
279 err = rtnl_link_set_type(link, "vti");
280 if (err < 0) {
281 rtnl_link_put(link);
282 return NULL;
283 }
284
285 return link;
286}
287
288/**
289 * Check if link is a IPVTI link
290 * @arg link Link object
291 *
292 * @return True if link is a IPVTI link, otherwise 0 is returned.
293 */
295{
296 return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "vti");
297}
298/**
299 * Create a new ipvti tunnel device
300 * @arg sock netlink socket
301 * @arg name name of the tunnel deviceL
302 *
303 * Creates a new ipvti tunnel device in the kernel
304 * @return 0 on success or a negative error code
305 */
306int rtnl_link_ipvti_add(struct nl_sock *sk, const char *name)
307{
308 struct rtnl_link *link;
309 int err;
310
311 link = rtnl_link_ipvti_alloc();
312 if (!link)
313 return -NLE_NOMEM;
314
315 if(name)
316 rtnl_link_set_name(link, name);
317
318 err = rtnl_link_add(sk, link, NLM_F_CREATE);
319 rtnl_link_put(link);
320
321 return err;
322}
323/**
324 * Set IPVTI tunnel interface index
325 * @arg link Link object
326 * @arg index interface index
327 *
328 * @return 0 on success or a negative error code
329 */
330int rtnl_link_ipvti_set_link(struct rtnl_link *link, uint32_t index)
331{
332 struct ipvti_info *ipvti = link->l_info;
333
334 IS_IPVTI_LINK_ASSERT(link);
335
336 ipvti->link = index;
337 ipvti->ipvti_mask |= IPVTI_ATTR_LINK;
338
339 return 0;
340}
341
342/**
343 * Get IPVTI tunnel interface index
344 * @arg link Link object
345 *
346 * @return interface index
347 */
349{
350 struct ipvti_info *ipvti = link->l_info;
351
352 IS_IPVTI_LINK_ASSERT(link);
353
354 return ipvti->link;
355}
356
357/**
358 * Set IPVTI tunnel set ikey
359 * @arg link Link object
360 * @arg ikey gre ikey
361 *
362 * @return 0 on success or a negative error code
363 */
364int rtnl_link_ipvti_set_ikey(struct rtnl_link *link, uint32_t ikey)
365{
366 struct ipvti_info *ipvti = link->l_info;
367
368 IS_IPVTI_LINK_ASSERT(link);
369
370 ipvti->ikey = ikey;
371 ipvti->ipvti_mask |= IPVTI_ATTR_IKEY;
372
373 return 0;
374}
375
376/**
377 * Get IPVTI tunnel ikey
378 * @arg link Link object
379 *
380 * @return ikey
381 */
383{
384 struct ipvti_info *ipvti = link->l_info;
385
386 IS_IPVTI_LINK_ASSERT(link);
387
388 return ipvti->ikey;
389}
390
391/**
392 * Set IPVTI tunnel set okey
393 * @arg link Link object
394 * @arg okey gre okey
395 *
396 * @return 0 on success or a negative error code
397 */
398int rtnl_link_ipvti_set_okey(struct rtnl_link *link, uint32_t okey)
399{
400 struct ipvti_info *ipvti = link->l_info;
401
402 IS_IPVTI_LINK_ASSERT(link);
403
404 ipvti->okey = okey;
405 ipvti->ipvti_mask |= IPVTI_ATTR_OKEY;
406
407 return 0;
408}
409
410/**
411 * Get IPVTI tunnel okey
412 * @arg link Link object
413 *
414 * @return okey value
415 */
417{
418 struct ipvti_info *ipvti = link->l_info;
419
420 IS_IPVTI_LINK_ASSERT(link);
421
422 return ipvti->okey;
423}
424
425/**
426 * Set IPVTI tunnel local address
427 * @arg link Link object
428 * @arg addr local address
429 *
430 * @return 0 on success or a negative error code
431 */
432int rtnl_link_ipvti_set_local(struct rtnl_link *link, uint32_t addr)
433{
434 struct ipvti_info *ipvti = link->l_info;
435
436 IS_IPVTI_LINK_ASSERT(link);
437
438 ipvti->local = addr;
439 ipvti->ipvti_mask |= IPVTI_ATTR_LOCAL;
440
441 return 0;
442}
443
444/**
445 * Get IPVTI tunnel local address
446 * @arg link Link object
447 *
448 * @return local address
449 */
451{
452 struct ipvti_info *ipvti = link->l_info;
453
454 IS_IPVTI_LINK_ASSERT(link);
455
456 return ipvti->local;
457}
458
459/**
460 * Set IPVTI tunnel remote address
461 * @arg link Link object
462 * @arg remote remote address
463 *
464 * @return 0 on success or a negative error code
465 */
466int rtnl_link_ipvti_set_remote(struct rtnl_link *link, uint32_t remote)
467{
468 struct ipvti_info *ipvti = link->l_info;
469
470 IS_IPVTI_LINK_ASSERT(link);
471
472 ipvti->remote = remote;
473 ipvti->ipvti_mask |= IPVTI_ATTR_REMOTE;
474
475 return 0;
476}
477
478/**
479 * Get IPVTI tunnel remote address
480 * @arg link Link object
481 *
482 * @return remote address on success or a negative error code
483 */
485{
486 struct ipvti_info *ipvti = link->l_info;
487
488 IS_IPVTI_LINK_ASSERT(link);
489
490 return ipvti->remote;
491}
492
493/**
494 * Set IPVTI tunnel fwmark
495 * @arg link Link object
496 * @arg fwmark fwmark
497 *
498 * @return 0 on success or a negative error code
499 */
500int rtnl_link_ipvti_set_fwmark(struct rtnl_link *link, uint32_t fwmark)
501{
502 struct ipvti_info *ipvti = link->l_info;
503
504 IS_IPVTI_LINK_ASSERT(link);
505
506 ipvti->fwmark = fwmark;
507 ipvti->ipvti_mask |= IPVTI_ATTR_FWMARK;
508
509 return 0;
510}
511
512/**
513 * Get IPVTI tunnel fwmark
514 * @arg link Link object
515 * @arg fwmark addr to fill in with the fwmark
516 *
517 * @return 0 on success or a negative error code
518 */
519int rtnl_link_ipvti_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
520{
521 struct ipvti_info *ipvti = link->l_info;
522
523 IS_IPVTI_LINK_ASSERT(link);
524
525 if (!(ipvti->ipvti_mask & IPVTI_ATTR_FWMARK))
526 return -NLE_NOATTR;
527
528 *fwmark = ipvti->fwmark;
529
530 return 0;
531}
532
533static void _nl_init ipvti_init(void)
534{
535 rtnl_link_register_info(&ipvti_info_ops);
536}
537
538static void _nl_exit ipvti_exit(void)
539{
540 rtnl_link_unregister_info(&ipvti_info_ops);
541}
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
int rtnl_link_ipvti_set_ikey(struct rtnl_link *link, uint32_t ikey)
Set IPVTI tunnel set ikey.
Definition ipvti.c:364
uint32_t rtnl_link_ipvti_get_ikey(struct rtnl_link *link)
Get IPVTI tunnel ikey.
Definition ipvti.c:382
int rtnl_link_ipvti_set_local(struct rtnl_link *link, uint32_t addr)
Set IPVTI tunnel local address.
Definition ipvti.c:432
int rtnl_link_ipvti_set_remote(struct rtnl_link *link, uint32_t remote)
Set IPVTI tunnel remote address.
Definition ipvti.c:466
int rtnl_link_ipvti_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
Get IPVTI tunnel fwmark.
Definition ipvti.c:519
uint32_t rtnl_link_ipvti_get_local(struct rtnl_link *link)
Get IPVTI tunnel local address.
Definition ipvti.c:450
int rtnl_link_ipvti_set_fwmark(struct rtnl_link *link, uint32_t fwmark)
Set IPVTI tunnel fwmark.
Definition ipvti.c:500
int rtnl_link_ipvti_set_okey(struct rtnl_link *link, uint32_t okey)
Set IPVTI tunnel set okey.
Definition ipvti.c:398
int rtnl_link_is_ipvti(struct rtnl_link *link)
Check if link is a IPVTI link.
Definition ipvti.c:294
uint32_t rtnl_link_ipvti_get_link(struct rtnl_link *link)
Get IPVTI tunnel interface index.
Definition ipvti.c:348
uint32_t rtnl_link_ipvti_get_remote(struct rtnl_link *link)
Get IPVTI tunnel remote address.
Definition ipvti.c:484
int rtnl_link_ipvti_set_link(struct rtnl_link *link, uint32_t index)
Set IPVTI tunnel interface index.
Definition ipvti.c:330
uint32_t rtnl_link_ipvti_get_okey(struct rtnl_link *link)
Get IPVTI tunnel okey.
Definition ipvti.c:416
int rtnl_link_ipvti_add(struct nl_sock *sk, const char *name)
Create a new ipvti tunnel device.
Definition ipvti.c:306
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
Dumping parameters.
Definition types.h:32
Attribute validation policy.
Definition attr.h:66