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