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