libnl 3.12.0
ip6tnl.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 ip6tnl IP6TNL
9 * ip6tnl link module
10 *
11 * @details
12 * \b Link Type Name: "ip6tnl"
13 *
14 * @route_doc{link_ip6tnl, IP6TNL 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/ip6tnl.h>
29
30#include "nl-route.h"
31#include "link-api.h"
32#include "nl-aux-route/nl-route.h"
33
34#define IP6_TNL_ATTR_LINK (1 << 0)
35#define IP6_TNL_ATTR_LOCAL (1 << 1)
36#define IP6_TNL_ATTR_REMOTE (1 << 2)
37#define IP6_TNL_ATTR_TTL (1 << 3)
38#define IP6_TNL_ATTR_TOS (1 << 4)
39#define IP6_TNL_ATTR_ENCAPLIMIT (1 << 5)
40#define IP6_TNL_ATTR_FLAGS (1 << 6)
41#define IP6_TNL_ATTR_PROTO (1 << 7)
42#define IP6_TNL_ATTR_FLOWINFO (1 << 8)
43#define IP6_TNL_ATTR_FWMARK (1 << 9)
44#define IP6_TNL_ATTR_CMTD (1 << 10)
45
47 uint8_t ttl;
48 uint8_t tos;
49 uint8_t encap_limit;
50 uint8_t proto;
51 uint32_t flags;
52 uint32_t link;
53 uint32_t flowinfo;
54 struct in6_addr local;
55 struct in6_addr remote;
56 uint32_t fwmark;
57 uint32_t ip6_tnl_mask;
58};
59
60static struct nla_policy ip6_tnl_policy[IFLA_IPTUN_MAX + 1] = {
61 [IFLA_IPTUN_LINK] = { .type = NLA_U32 },
62 [IFLA_IPTUN_LOCAL] = { .minlen = sizeof(struct in6_addr) },
63 [IFLA_IPTUN_REMOTE] = { .minlen = sizeof(struct in6_addr) },
64 [IFLA_IPTUN_TTL] = { .type = NLA_U8 },
65 [IFLA_IPTUN_TOS] = { .type = NLA_U8 },
66 [IFLA_IPTUN_ENCAP_LIMIT] = { .type = NLA_U8 },
67 [IFLA_IPTUN_FLOWINFO] = { .type = NLA_U32 },
68 [IFLA_IPTUN_FLAGS] = { .type = NLA_U32 },
69 [IFLA_IPTUN_PROTO] = { .type = NLA_U8 },
70 [IFLA_IPTUN_FWMARK] = { .type = NLA_U32 },
71 [IFLA_IPTUN_COLLECT_METADATA] = { .type = NLA_FLAG },
72};
73
74static int ip6_tnl_alloc(struct rtnl_link *link)
75{
76 struct ip6_tnl_info *ip6_tnl;
77
78 if (link->l_info)
79 memset(link->l_info, 0, sizeof(*ip6_tnl));
80 else {
81 ip6_tnl = calloc(1, sizeof(*ip6_tnl));
82 if (!ip6_tnl)
83 return -NLE_NOMEM;
84
85 link->l_info = ip6_tnl;
86 }
87
88 return 0;
89}
90
91static int ip6_tnl_parse(struct rtnl_link *link, struct nlattr *data,
92 struct nlattr *xstats)
93{
94 struct nlattr *tb[IFLA_IPTUN_MAX + 1];
95 struct ip6_tnl_info *ip6_tnl;
96 int err;
97
98 NL_DBG(3, "Parsing IP6_TNL link info\n");
99
100 err = nla_parse_nested(tb, IFLA_IPTUN_MAX, data, ip6_tnl_policy);
101 if (err < 0)
102 goto errout;
103
104 err = ip6_tnl_alloc(link);
105 if (err < 0)
106 goto errout;
107
108 ip6_tnl = link->l_info;
109
110 if (tb[IFLA_IPTUN_LINK]) {
111 ip6_tnl->link = nla_get_u32(tb[IFLA_IPTUN_LINK]);
112 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_LINK;
113 }
114
115 if (tb[IFLA_IPTUN_LOCAL]) {
116 nla_memcpy(&ip6_tnl->local, tb[IFLA_IPTUN_LOCAL],
117 sizeof(struct in6_addr));
118 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_LOCAL;
119 }
120
121 if (tb[IFLA_IPTUN_REMOTE]) {
122 nla_memcpy(&ip6_tnl->remote, tb[IFLA_IPTUN_REMOTE],
123 sizeof(struct in6_addr));
124 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_REMOTE;
125 }
126
127 if (tb[IFLA_IPTUN_TTL]) {
128 ip6_tnl->ttl = nla_get_u8(tb[IFLA_IPTUN_TTL]);
129 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_TTL;
130 }
131
132 if (tb[IFLA_IPTUN_TOS]) {
133 ip6_tnl->tos = nla_get_u8(tb[IFLA_IPTUN_TOS]);
134 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_TOS;
135 }
136
137 if (tb[IFLA_IPTUN_ENCAP_LIMIT]) {
138 ip6_tnl->encap_limit = nla_get_u8(tb[IFLA_IPTUN_ENCAP_LIMIT]);
139 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_ENCAPLIMIT;
140 }
141
142 if (tb[IFLA_IPTUN_FLAGS]) {
143 ip6_tnl->flags = nla_get_u32(tb[IFLA_IPTUN_FLAGS]);
144 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FLAGS;
145 }
146
147 if (tb[IFLA_IPTUN_FLOWINFO]) {
148 ip6_tnl->flowinfo = nla_get_u32(tb[IFLA_IPTUN_FLOWINFO]);
149 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FLOWINFO;
150 }
151
152 if (tb[IFLA_IPTUN_PROTO]) {
153 ip6_tnl->proto = nla_get_u8(tb[IFLA_IPTUN_PROTO]);
154 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_PROTO;
155 }
156
157 if (tb[IFLA_IPTUN_FWMARK]) {
158 ip6_tnl->fwmark = nla_get_u32(tb[IFLA_IPTUN_FWMARK]);
159 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FWMARK;
160 }
161
162 if (tb[IFLA_IPTUN_COLLECT_METADATA])
163 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_CMTD;
164
165 err = 0;
166
167errout:
168 return err;
169}
170
171static int ip6_tnl_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
172{
173 struct ip6_tnl_info *ip6_tnl = link->l_info;
174 struct nlattr *data;
175
176 data = nla_nest_start(msg, IFLA_INFO_DATA);
177 if (!data)
178 return -NLE_MSGSIZE;
179
180 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_LINK)
181 NLA_PUT_U32(msg, IFLA_IPTUN_LINK, ip6_tnl->link);
182
183 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_LOCAL)
184 NLA_PUT(msg, IFLA_IPTUN_LOCAL, sizeof(struct in6_addr),
185 &ip6_tnl->local);
186
187 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_REMOTE)
188 NLA_PUT(msg, IFLA_IPTUN_REMOTE, sizeof(struct in6_addr),
189 &ip6_tnl->remote);
190
191 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_TTL)
192 NLA_PUT_U8(msg, IFLA_IPTUN_TTL, ip6_tnl->ttl);
193
194 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_TOS)
195 NLA_PUT_U8(msg, IFLA_IPTUN_TOS, ip6_tnl->tos);
196
197 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_ENCAPLIMIT)
198 NLA_PUT_U8(msg, IFLA_IPTUN_ENCAP_LIMIT, ip6_tnl->encap_limit);
199
200 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FLAGS)
201 NLA_PUT_U32(msg, IFLA_IPTUN_FLAGS, ip6_tnl->flags);
202
203 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FLOWINFO)
204 NLA_PUT_U32(msg, IFLA_IPTUN_FLOWINFO, ip6_tnl->flowinfo);
205
206 /* kernel crashes if this attribure is missing temporary fix */
207 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_PROTO)
208 NLA_PUT_U8(msg, IFLA_IPTUN_PROTO, ip6_tnl->proto);
209 else
210 NLA_PUT_U8(msg, IFLA_IPTUN_PROTO, 0);
211
212 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FWMARK)
213 NLA_PUT_U32(msg, IFLA_IPTUN_FWMARK, ip6_tnl->fwmark);
214
215 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_CMTD)
216 NLA_PUT_FLAG(msg, IFLA_IPTUN_COLLECT_METADATA);
217
218 nla_nest_end(msg, data);
219
220nla_put_failure:
221 return 0;
222}
223
224static void ip6_tnl_free(struct rtnl_link *link)
225{
226 struct ip6_tnl_info *ip6_tnl = link->l_info;
227
228 free(ip6_tnl);
229 link->l_info = NULL;
230}
231
232static void ip6_tnl_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
233{
234 nl_dump(p, "ip6_tnl : %s", link->l_name);
235}
236
237static void ip6_tnl_dump_details(struct rtnl_link *link,
238 struct nl_dump_params *p)
239{
240 struct ip6_tnl_info *ip6_tnl = link->l_info;
241 char addr[INET6_ADDRSTRLEN];
242
243 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_LINK) {
244 _nl_auto_rtnl_link struct rtnl_link *parent = NULL;
245 char *name;
246
247 nl_dump(p, " link ");
248
249 name = NULL;
250 parent = link_lookup(link->ce_cache, ip6_tnl->link);
251 if (parent)
252 name = rtnl_link_get_name(parent);
253
254 if (name)
255 nl_dump_line(p, "%s\n", name);
256 else
257 nl_dump_line(p, "%u\n", ip6_tnl->link);
258 }
259
260 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_LOCAL) {
261 nl_dump(p, " local ");
262 nl_dump_line(p, "%s\n",
263 _nl_inet_ntop(AF_INET6, &ip6_tnl->local, addr));
264 }
265
266 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_REMOTE) {
267 nl_dump(p, " remote ");
268 nl_dump_line(p, "%s\n",
269 _nl_inet_ntop(AF_INET6, &ip6_tnl->remote, addr));
270 }
271
272 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_TTL) {
273 nl_dump(p, " ttl ");
274 nl_dump_line(p, "%d\n", ip6_tnl->ttl);
275 }
276
277 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_TOS) {
278 nl_dump(p, " tos ");
279 nl_dump_line(p, "%d\n", ip6_tnl->tos);
280 }
281
282 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_ENCAPLIMIT) {
283 nl_dump(p, " encaplimit ");
284 nl_dump_line(p, "%d\n", ip6_tnl->encap_limit);
285 }
286
287 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FLAGS) {
288 nl_dump(p, " flags ");
289 nl_dump_line(p, " (%x)\n", ip6_tnl->flags);
290 }
291
292 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FLOWINFO) {
293 nl_dump(p, " flowinfo ");
294 nl_dump_line(p, " (%x)\n", ip6_tnl->flowinfo);
295 }
296
297 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_PROTO) {
298 nl_dump(p, " proto ");
299 nl_dump_line(p, " (%x)\n", ip6_tnl->proto);
300 }
301
302 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FWMARK) {
303 nl_dump(p, " fwmark ");
304 nl_dump_line(p, "%x\n", ip6_tnl->fwmark);
305 }
306
307 if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_CMTD) {
308 nl_dump(p, " collect-metadata\n");
309 }
310}
311
312static int ip6_tnl_clone(struct rtnl_link *dst, struct rtnl_link *src)
313{
314 struct ip6_tnl_info *ip6_tnl_dst, *ip6_tnl_src = src->l_info;
315 int err;
316
317 dst->l_info = NULL;
318
319 err = rtnl_link_set_type(dst, "ip6tnl");
320 if (err < 0)
321 return err;
322
323 ip6_tnl_dst = dst->l_info;
324
325 if (!ip6_tnl_dst || !ip6_tnl_src)
326 BUG();
327
328 memcpy(ip6_tnl_dst, ip6_tnl_src, sizeof(struct ip6_tnl_info));
329
330 return 0;
331}
332
333static struct rtnl_link_info_ops ip6_tnl_info_ops = {
334 .io_name = "ip6tnl",
335 .io_alloc = ip6_tnl_alloc,
336 .io_parse = ip6_tnl_parse,
337 .io_dump = {
338 [NL_DUMP_LINE] = ip6_tnl_dump_line,
339 [NL_DUMP_DETAILS] = ip6_tnl_dump_details,
340 },
341 .io_clone = ip6_tnl_clone,
342 .io_put_attrs = ip6_tnl_put_attrs,
343 .io_free = ip6_tnl_free,
344};
345
346#define IS_IP6_TNL_LINK_ASSERT(link) \
347 if ((link)->l_info_ops != &ip6_tnl_info_ops) { \
348 APPBUG("Link is not a ip6_tnl link. set type \"ip6tnl\" first."); \
349 return -NLE_OPNOTSUPP; \
350 }
351
352struct rtnl_link *rtnl_link_ip6_tnl_alloc(void)
353{
354 struct rtnl_link *link;
355 int err;
356
357 link = rtnl_link_alloc();
358 if (!link)
359 return NULL;
360
361 err = rtnl_link_set_type(link, "ip6tnl");
362 if (err < 0) {
363 rtnl_link_put(link);
364 return NULL;
365 }
366
367 return link;
368}
369
370/**
371 * Check if link is a IP6_TNL link
372 * @arg link Link object
373 *
374 * @return True if link is a IP6_TNL link, otherwise false is returned.
375 */
377{
378 return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "ip6tnl");
379}
380
381/**
382 * Create a new ip6_tnl tunnel device
383 * @arg sock netlink socket
384 * @arg name name of the tunnel device
385 *
386 * Creates a new ip6_tnl tunnel device in the kernel
387 * @return 0 on success or a negative error code
388 */
389int rtnl_link_ip6_tnl_add(struct nl_sock *sk, const char *name)
390{
391 struct rtnl_link *link;
392 int err;
393
394 link = rtnl_link_ip6_tnl_alloc();
395 if (!link)
396 return -NLE_NOMEM;
397
398 if (name)
399 rtnl_link_set_name(link, name);
400
401 err = rtnl_link_add(sk, link, NLM_F_CREATE);
402 rtnl_link_put(link);
403
404 return err;
405}
406
407/**
408 * Set IP6_TNL tunnel interface index
409 * @arg link Link object
410 * @arg index interface index
411 *
412 * @return 0 on success or a negative error code
413 */
414int rtnl_link_ip6_tnl_set_link(struct rtnl_link *link, uint32_t index)
415{
416 struct ip6_tnl_info *ip6_tnl = link->l_info;
417
418 IS_IP6_TNL_LINK_ASSERT(link);
419
420 ip6_tnl->link = index;
421 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_LINK;
422
423 return 0;
424}
425
426/**
427 * Get IP6_TNL tunnel interface index
428 * @arg link Link object
429 *
430 * @return interface index value
431 */
433{
434 struct ip6_tnl_info *ip6_tnl = link->l_info;
435
436 IS_IP6_TNL_LINK_ASSERT(link);
437
438 return ip6_tnl->link;
439}
440
441/**
442 * Set IP6_TNL tunnel local address
443 * @arg link Link object
444 * @arg addr local address
445 *
446 * @return 0 on success or a negative error code
447 */
448int rtnl_link_ip6_tnl_set_local(struct rtnl_link *link, struct in6_addr *addr)
449{
450 struct ip6_tnl_info *ip6_tnl = link->l_info;
451
452 IS_IP6_TNL_LINK_ASSERT(link);
453
454 memcpy(&ip6_tnl->local, addr, sizeof(struct in6_addr));
455 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_LOCAL;
456
457 return 0;
458}
459
460/**
461 * Get IP6_TNL tunnel local address
462 * @arg link Link object
463 *
464 * @return 0 on success or a negative error code
465 */
466int rtnl_link_ip6_tnl_get_local(struct rtnl_link *link, struct in6_addr *addr)
467{
468 struct ip6_tnl_info *ip6_tnl = link->l_info;
469
470 IS_IP6_TNL_LINK_ASSERT(link);
471
472 memcpy(addr, &ip6_tnl->local, sizeof(struct in6_addr));
473
474 return 0;
475}
476
477/**
478 * Set IP6_TNL tunnel remote address
479 * @arg link Link object
480 * @arg remote remote address
481 *
482 * @return 0 on success or a negative error code
483 */
484int rtnl_link_ip6_tnl_set_remote(struct rtnl_link *link, struct in6_addr *addr)
485{
486 struct ip6_tnl_info *ip6_tnl = link->l_info;
487
488 IS_IP6_TNL_LINK_ASSERT(link);
489
490 memcpy(&ip6_tnl->remote, addr, sizeof(struct in6_addr));
491 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_REMOTE;
492
493 return 0;
494}
495
496/**
497 * Get IP6_TNL tunnel remote address
498 * @arg link Link object
499 *
500 * @return 0 on success or a negative error code
501 */
502int rtnl_link_ip6_tnl_get_remote(struct rtnl_link *link, struct in6_addr *addr)
503{
504 struct ip6_tnl_info *ip6_tnl = link->l_info;
505
506 IS_IP6_TNL_LINK_ASSERT(link);
507
508 memcpy(addr, &ip6_tnl->remote, sizeof(struct in6_addr));
509
510 return 0;
511}
512
513/**
514 * Set IP6_TNL tunnel ttl
515 * @arg link Link object
516 * @arg ttl tunnel ttl
517 *
518 * @return 0 on success or a negative error code
519 */
520int rtnl_link_ip6_tnl_set_ttl(struct rtnl_link *link, uint8_t ttl)
521{
522 struct ip6_tnl_info *ip6_tnl = link->l_info;
523
524 IS_IP6_TNL_LINK_ASSERT(link);
525
526 ip6_tnl->ttl = ttl;
527 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_TTL;
528
529 return 0;
530}
531
532/**
533 * Get IP6_TNL tunnel ttl
534 * @arg link Link object
535 *
536 * @return ttl value
537 */
539{
540 struct ip6_tnl_info *ip6_tnl = link->l_info;
541
542 IS_IP6_TNL_LINK_ASSERT(link);
543
544 return ip6_tnl->ttl;
545}
546
547/**
548 * Set IP6_TNL tunnel tos
549 * @arg link Link object
550 * @arg tos tunnel tos
551 *
552 * @return 0 on success or a negative error code
553 */
554int rtnl_link_ip6_tnl_set_tos(struct rtnl_link *link, uint8_t tos)
555{
556 struct ip6_tnl_info *ip6_tnl = link->l_info;
557
558 IS_IP6_TNL_LINK_ASSERT(link);
559
560 ip6_tnl->tos = tos;
561 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_TOS;
562
563 return 0;
564}
565
566/**
567 * Get IP6_TNL tunnel tos
568 * @arg link Link object
569 *
570 * @return tos value
571 */
573{
574 struct ip6_tnl_info *ip6_tnl = link->l_info;
575
576 IS_IP6_TNL_LINK_ASSERT(link);
577
578 return ip6_tnl->tos;
579}
580
581/**
582 * Set IP6_TNL tunnel encap limit
583 * @arg link Link object
584 * @arg encap_limit encaplimit value
585 *
586 * @return 0 on success or a negative error code
587 */
589 uint8_t encap_limit)
590{
591 struct ip6_tnl_info *ip6_tnl = link->l_info;
592
593 IS_IP6_TNL_LINK_ASSERT(link);
594
595 ip6_tnl->encap_limit = encap_limit;
596 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_ENCAPLIMIT;
597
598 return 0;
599}
600
601/**
602 * Get IP6_TNL encaplimit
603 * @arg link Link object
604 *
605 * @return encaplimit value
606 */
608{
609 struct ip6_tnl_info *ip6_tnl = link->l_info;
610
611 IS_IP6_TNL_LINK_ASSERT(link);
612
613 return ip6_tnl->encap_limit;
614}
615
616/**
617 * Set IP6_TNL tunnel flowinfo
618 * @arg link Link object
619 * @arg flowinfo flowinfo value
620 *
621 * @return 0 on success or a negative error code
622 */
623int rtnl_link_ip6_tnl_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo)
624{
625 struct ip6_tnl_info *ip6_tnl = link->l_info;
626
627 IS_IP6_TNL_LINK_ASSERT(link);
628
629 ip6_tnl->flowinfo = flowinfo;
630 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FLOWINFO;
631
632 return 0;
633}
634
635/**
636 * Get IP6_TNL flowinfo
637 * @arg link Link object
638 *
639 * @return flowinfo value
640 */
642{
643 struct ip6_tnl_info *ip6_tnl = link->l_info;
644
645 IS_IP6_TNL_LINK_ASSERT(link);
646
647 return ip6_tnl->flowinfo;
648}
649
650/**
651 * Set IP6_TNL tunnel flags
652 * @arg link Link object
653 * @arg flags tunnel flags
654 *
655 * @return 0 on success or a negative error code
656 */
657int rtnl_link_ip6_tnl_set_flags(struct rtnl_link *link, uint32_t flags)
658{
659 struct ip6_tnl_info *ip6_tnl = link->l_info;
660
661 IS_IP6_TNL_LINK_ASSERT(link);
662
663 ip6_tnl->flags = flags;
664 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FLAGS;
665
666 return 0;
667}
668
669/**
670 * Get IP6_TNL path flags
671 * @arg link Link object
672 *
673 * @return flags value
674 */
676{
677 struct ip6_tnl_info *ip6_tnl = link->l_info;
678
679 IS_IP6_TNL_LINK_ASSERT(link);
680
681 return ip6_tnl->flags;
682}
683
684/**
685 * Set IP6_TNL collect-metadata flag
686 * @arg link Link object
687 * @arg enable 0 to disable, non-zero to enable
688 *
689 * Enable or disable the collect-metadata mode on the ip6tnl link.
690 *
691 * @return 0 on success or a negative error code
692 */
694{
695 struct ip6_tnl_info *ip6_tnl = link->l_info;
696
697 IS_IP6_TNL_LINK_ASSERT(link);
698
699 if (enable)
700 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_CMTD;
701 else
702 ip6_tnl->ip6_tnl_mask &= ~IP6_TNL_ATTR_CMTD;
703
704 return 0;
705}
706
707/**
708 * Get IP6_TNL collect-metadata flag
709 * @arg link Link object
710 * @arg enable Pointer to int which will be set to the current state
711 * (0 if disabled, non-zero if enabled)
712 *
713 * @return 0 on success or a negative error code
714 */
716{
717 struct ip6_tnl_info *ip6_tnl = link->l_info;
718
719 IS_IP6_TNL_LINK_ASSERT(link);
720
721 if (!enable)
722 return -NLE_INVAL;
723
724 *enable = !!(ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_CMTD);
725
726 return 0;
727}
728
729/**
730 * Set IP6_TNL tunnel proto
731 * @arg link Link object
732 * @arg proto tunnel proto
733 *
734 * @return 0 on success or a negative error code
735 */
736int rtnl_link_ip6_tnl_set_proto(struct rtnl_link *link, uint8_t proto)
737{
738 struct ip6_tnl_info *ip6_tnl = link->l_info;
739
740 IS_IP6_TNL_LINK_ASSERT(link);
741
742 ip6_tnl->proto = proto;
743 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_PROTO;
744
745 return 0;
746}
747
748/**
749 * Get IP6_TNL proto
750 * @arg link Link object
751 *
752 * @return proto value
753 */
755{
756 struct ip6_tnl_info *ip6_tnl = link->l_info;
757
758 IS_IP6_TNL_LINK_ASSERT(link);
759
760 return ip6_tnl->proto;
761}
762
763/**
764 * Set IP6_TNL tunnel fwmark
765 * @arg link Link object
766 * @arg fwmark fwmark
767 *
768 * @return 0 on success or a negative error code
769 */
770int rtnl_link_ip6_tnl_set_fwmark(struct rtnl_link *link, uint32_t fwmark)
771{
772 struct ip6_tnl_info *ip6_tnl = link->l_info;
773
774 IS_IP6_TNL_LINK_ASSERT(link);
775
776 ip6_tnl->fwmark = fwmark;
777 ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FWMARK;
778
779 return 0;
780}
781
782/**
783 * Get IP6_TNL tunnel fwmark
784 * @arg link Link object
785 * @arg fwmark addr to fill in with the fwmark
786 *
787 * @return 0 on success or a negative error code
788 */
789int rtnl_link_ip6_tnl_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
790{
791 struct ip6_tnl_info *ip6_tnl = link->l_info;
792
793 IS_IP6_TNL_LINK_ASSERT(link);
794
795 if (!(ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FWMARK))
796 return -NLE_NOATTR;
797
798 *fwmark = ip6_tnl->fwmark;
799
800 return 0;
801}
802
803static void _nl_init ip6_tnl_init(void)
804{
805 rtnl_link_register_info(&ip6_tnl_info_ops);
806}
807
808static void _nl_exit ip6_tnl_exit(void)
809{
810 rtnl_link_unregister_info(&ip6_tnl_info_ops);
811}
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition attr.c:714
#define NLA_PUT_FLAG(msg, attrtype)
Add flag attribute to netlink message.
Definition attr.h:272
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition attr.h:201
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition attr.h:166
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition attr.h:237
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition attr.c:614
int nla_memcpy(void *dest, const struct nlattr *src, int count)
Copy attribute payload to another memory area.
Definition attr.c:355
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_U8
8 bit integer
Definition attr.h:35
@ NLA_FLAG
Flag.
Definition attr.h:40
@ NLA_U32
32 bit integer
Definition attr.h:37
int rtnl_link_ip6_tnl_set_remote(struct rtnl_link *link, struct in6_addr *addr)
Set IP6_TNL tunnel remote address.
Definition ip6tnl.c:484
uint8_t rtnl_link_ip6_tnl_get_proto(struct rtnl_link *link)
Get IP6_TNL proto.
Definition ip6tnl.c:754
uint32_t rtnl_link_ip6_tnl_get_flowinfo(struct rtnl_link *link)
Get IP6_TNL flowinfo.
Definition ip6tnl.c:641
int rtnl_link_is_ip6_tnl(struct rtnl_link *link)
Check if link is a IP6_TNL link.
Definition ip6tnl.c:376
int rtnl_link_ip6_tnl_set_link(struct rtnl_link *link, uint32_t index)
Set IP6_TNL tunnel interface index.
Definition ip6tnl.c:414
int rtnl_link_ip6_tnl_add(struct nl_sock *sk, const char *name)
Create a new ip6_tnl tunnel device.
Definition ip6tnl.c:389
uint8_t rtnl_link_ip6_tnl_get_ttl(struct rtnl_link *link)
Get IP6_TNL tunnel ttl.
Definition ip6tnl.c:538
int rtnl_link_ip6_tnl_get_remote(struct rtnl_link *link, struct in6_addr *addr)
Get IP6_TNL tunnel remote address.
Definition ip6tnl.c:502
uint32_t rtnl_link_ip6_tnl_get_flags(struct rtnl_link *link)
Get IP6_TNL path flags.
Definition ip6tnl.c:675
int rtnl_link_ip6_tnl_get_collect_metadata(struct rtnl_link *link, int *enable)
Get IP6_TNL collect-metadata flag.
Definition ip6tnl.c:715
int rtnl_link_ip6_tnl_set_fwmark(struct rtnl_link *link, uint32_t fwmark)
Set IP6_TNL tunnel fwmark.
Definition ip6tnl.c:770
uint8_t rtnl_link_ip6_tnl_get_encaplimit(struct rtnl_link *link)
Get IP6_TNL encaplimit.
Definition ip6tnl.c:607
int rtnl_link_ip6_tnl_set_flags(struct rtnl_link *link, uint32_t flags)
Set IP6_TNL tunnel flags.
Definition ip6tnl.c:657
int rtnl_link_ip6_tnl_set_local(struct rtnl_link *link, struct in6_addr *addr)
Set IP6_TNL tunnel local address.
Definition ip6tnl.c:448
int rtnl_link_ip6_tnl_set_ttl(struct rtnl_link *link, uint8_t ttl)
Set IP6_TNL tunnel ttl.
Definition ip6tnl.c:520
int rtnl_link_ip6_tnl_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo)
Set IP6_TNL tunnel flowinfo.
Definition ip6tnl.c:623
int rtnl_link_ip6_tnl_get_local(struct rtnl_link *link, struct in6_addr *addr)
Get IP6_TNL tunnel local address.
Definition ip6tnl.c:466
int rtnl_link_ip6_tnl_set_tos(struct rtnl_link *link, uint8_t tos)
Set IP6_TNL tunnel tos.
Definition ip6tnl.c:554
int rtnl_link_ip6_tnl_set_proto(struct rtnl_link *link, uint8_t proto)
Set IP6_TNL tunnel proto.
Definition ip6tnl.c:736
int rtnl_link_ip6_tnl_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
Get IP6_TNL tunnel fwmark.
Definition ip6tnl.c:789
int rtnl_link_ip6_tnl_set_encaplimit(struct rtnl_link *link, uint8_t encap_limit)
Set IP6_TNL tunnel encap limit.
Definition ip6tnl.c:588
uint32_t rtnl_link_ip6_tnl_get_link(struct rtnl_link *link)
Get IP6_TNL tunnel interface index.
Definition ip6tnl.c:432
uint8_t rtnl_link_ip6_tnl_get_tos(struct rtnl_link *link)
Get IP6_TNL tunnel tos.
Definition ip6tnl.c:572
int rtnl_link_ip6_tnl_set_collect_metadata(struct rtnl_link *link, int enable)
Set IP6_TNL collect-metadata flag.
Definition ip6tnl.c:693
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