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