libnl  3.6.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 
56 static 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 
69 static 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 
86 static 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 
157 errout:
158  return err;
159 }
160 
161 static 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 
205 nla_put_failure:
206  return 0;
207 }
208 
209 static 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 
217 static 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 
222 static 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 
245  if(inet_ntop(AF_INET6, &ip6_tnl->local, addr, INET6_ADDRSTRLEN))
246  nl_dump_line(p, "%s\n", addr);
247  else
248  nl_dump_line(p, "%#x\n", ip6_tnl->local);
249  }
250 
251  if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_REMOTE) {
252  nl_dump(p, " remote ");
253 
254  if(inet_ntop(AF_INET6, &ip6_tnl->remote, addr, INET6_ADDRSTRLEN))
255  nl_dump_line(p, "%s\n", addr);
256  else
257  nl_dump_line(p, "%#x\n", ip6_tnl->remote);
258  }
259 
260  if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_TTL) {
261  nl_dump(p, " ttl ");
262  nl_dump_line(p, "%d\n", ip6_tnl->ttl);
263  }
264 
265  if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_TOS) {
266  nl_dump(p, " tos ");
267  nl_dump_line(p, "%d\n", ip6_tnl->tos);
268  }
269 
270  if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_ENCAPLIMIT) {
271  nl_dump(p, " encaplimit ");
272  nl_dump_line(p, "%d\n", ip6_tnl->encap_limit);
273  }
274 
275  if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FLAGS) {
276  nl_dump(p, " flags ");
277  nl_dump_line(p, " (%x)\n", ip6_tnl->flags);
278  }
279 
280  if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FLOWINFO) {
281  nl_dump(p, " flowinfo ");
282  nl_dump_line(p, " (%x)\n", ip6_tnl->flowinfo);
283  }
284 
285  if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_PROTO) {
286  nl_dump(p, " proto ");
287  nl_dump_line(p, " (%x)\n", ip6_tnl->proto);
288  }
289 
290  if (ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FWMARK) {
291  nl_dump(p, " fwmark ");
292  nl_dump_line(p, "%x\n", ip6_tnl->fwmark);
293  }
294 }
295 
296 static int ip6_tnl_clone(struct rtnl_link *dst, struct rtnl_link *src)
297 {
298  struct ip6_tnl_info *ip6_tnl_dst, *ip6_tnl_src = src->l_info;
299  int err;
300 
301  dst->l_info = NULL;
302 
303  err = rtnl_link_set_type(dst, "ip6tnl");
304  if (err < 0)
305  return err;
306 
307  ip6_tnl_dst = dst->l_info;
308 
309  if (!ip6_tnl_dst || !ip6_tnl_src)
310  BUG();
311 
312  memcpy(ip6_tnl_dst, ip6_tnl_src, sizeof(struct ip6_tnl_info));
313 
314  return 0;
315 }
316 
317 static struct rtnl_link_info_ops ip6_tnl_info_ops = {
318  .io_name = "ip6tnl",
319  .io_alloc = ip6_tnl_alloc,
320  .io_parse = ip6_tnl_parse,
321  .io_dump = {
322  [NL_DUMP_LINE] = ip6_tnl_dump_line,
323  [NL_DUMP_DETAILS] = ip6_tnl_dump_details,
324  },
325  .io_clone = ip6_tnl_clone,
326  .io_put_attrs = ip6_tnl_put_attrs,
327  .io_free = ip6_tnl_free,
328 };
329 
330 #define IS_IP6_TNL_LINK_ASSERT(link)\
331  if ((link)->l_info_ops != &ip6_tnl_info_ops) {\
332  APPBUG("Link is not a ip6_tnl link. set type \"ip6tnl\" first.");\
333  return -NLE_OPNOTSUPP;\
334  }
335 
336 struct rtnl_link *rtnl_link_ip6_tnl_alloc(void)
337 {
338  struct rtnl_link *link;
339  int err;
340 
341  link = rtnl_link_alloc();
342  if (!link)
343  return NULL;
344 
345  err = rtnl_link_set_type(link, "ip6tnl");
346  if (err < 0) {
347  rtnl_link_put(link);
348  return NULL;
349  }
350 
351  return link;
352 }
353 
354 /**
355  * Check if link is a IP6_TNL link
356  * @arg link Link object
357  *
358  * @return True if link is a IP6_TNL link, otherwise false is returned.
359  */
361 {
362  return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "ip6tnl");
363 }
364 
365 /**
366  * Create a new ip6_tnl tunnel device
367  * @arg sock netlink socket
368  * @arg name name of the tunnel device
369  *
370  * Creates a new ip6_tnl tunnel device in the kernel
371  * @return 0 on success or a negative error code
372  */
373 int rtnl_link_ip6_tnl_add(struct nl_sock *sk, const char *name)
374 {
375  struct rtnl_link *link;
376  int err;
377 
378  link = rtnl_link_ip6_tnl_alloc();
379  if (!link)
380  return -NLE_NOMEM;
381 
382  if(name)
383  rtnl_link_set_name(link, name);
384 
385  err = rtnl_link_add(sk, link, NLM_F_CREATE);
386  rtnl_link_put(link);
387 
388  return err;
389 }
390 
391 /**
392  * Set IP6_TNL tunnel interface index
393  * @arg link Link object
394  * @arg index interface index
395  *
396  * @return 0 on success or a negative error code
397  */
398 int rtnl_link_ip6_tnl_set_link(struct rtnl_link *link, uint32_t index)
399 {
400  struct ip6_tnl_info *ip6_tnl = link->l_info;
401 
402  IS_IP6_TNL_LINK_ASSERT(link);
403 
404  ip6_tnl->link = index;
405  ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_LINK;
406 
407  return 0;
408 }
409 
410 /**
411  * Get IP6_TNL tunnel interface index
412  * @arg link Link object
413  *
414  * @return interface index value
415  */
416 uint32_t rtnl_link_ip6_tnl_get_link(struct rtnl_link *link)
417 {
418  struct ip6_tnl_info *ip6_tnl = link->l_info;
419 
420  IS_IP6_TNL_LINK_ASSERT(link);
421 
422  return ip6_tnl->link;
423 }
424 
425 /**
426  * Set IP6_TNL 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  */
432 int rtnl_link_ip6_tnl_set_local(struct rtnl_link *link, struct in6_addr *addr)
433 {
434  struct ip6_tnl_info *ip6_tnl = link->l_info;
435 
436  IS_IP6_TNL_LINK_ASSERT(link);
437 
438  memcpy(&ip6_tnl->local, addr, sizeof(struct in6_addr));
439  ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_LOCAL;
440 
441  return 0;
442 }
443 
444 /**
445  * Get IP6_TNL tunnel local address
446  * @arg link Link object
447  *
448  * @return 0 on success or a negative error code
449  */
450 int rtnl_link_ip6_tnl_get_local(struct rtnl_link *link, struct in6_addr *addr)
451 {
452  struct ip6_tnl_info *ip6_tnl = link->l_info;
453 
454  IS_IP6_TNL_LINK_ASSERT(link);
455 
456  memcpy(addr, &ip6_tnl->local, sizeof(struct in6_addr));
457 
458  return 0;
459 }
460 
461 /**
462  * Set IP6_TNL tunnel remote address
463  * @arg link Link object
464  * @arg remote remote address
465  *
466  * @return 0 on success or a negative error code
467  */
468 int rtnl_link_ip6_tnl_set_remote(struct rtnl_link *link, struct in6_addr *addr)
469 {
470  struct ip6_tnl_info *ip6_tnl = link->l_info;
471 
472  IS_IP6_TNL_LINK_ASSERT(link);
473 
474  memcpy(&ip6_tnl->remote, addr, sizeof(struct in6_addr));
475  ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_REMOTE;
476 
477  return 0;
478 }
479 
480 /**
481  * Get IP6_TNL tunnel remote address
482  * @arg link Link object
483  *
484  * @return 0 on success or a negative error code
485  */
486 int rtnl_link_ip6_tnl_get_remote(struct rtnl_link *link, struct in6_addr *addr)
487 {
488  struct ip6_tnl_info *ip6_tnl = link->l_info;
489 
490  IS_IP6_TNL_LINK_ASSERT(link);
491 
492  memcpy(addr, &ip6_tnl->remote, sizeof(struct in6_addr));
493 
494  return 0;
495 }
496 
497 /**
498  * Set IP6_TNL tunnel ttl
499  * @arg link Link object
500  * @arg ttl tunnel ttl
501  *
502  * @return 0 on success or a negative error code
503  */
504 int rtnl_link_ip6_tnl_set_ttl(struct rtnl_link *link, uint8_t ttl)
505 {
506  struct ip6_tnl_info *ip6_tnl = link->l_info;
507 
508  IS_IP6_TNL_LINK_ASSERT(link);
509 
510  ip6_tnl->ttl = ttl;
511  ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_TTL;
512 
513  return 0;
514 }
515 
516 /**
517  * Get IP6_TNL tunnel ttl
518  * @arg link Link object
519  *
520  * @return ttl value
521  */
523 {
524  struct ip6_tnl_info *ip6_tnl = link->l_info;
525 
526  IS_IP6_TNL_LINK_ASSERT(link);
527 
528  return ip6_tnl->ttl;
529 }
530 
531 /**
532  * Set IP6_TNL tunnel tos
533  * @arg link Link object
534  * @arg tos tunnel tos
535  *
536  * @return 0 on success or a negative error code
537  */
538 int rtnl_link_ip6_tnl_set_tos(struct rtnl_link *link, uint8_t tos)
539 {
540  struct ip6_tnl_info *ip6_tnl = link->l_info;
541 
542  IS_IP6_TNL_LINK_ASSERT(link);
543 
544  ip6_tnl->tos = tos;
545  ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_TOS;
546 
547  return 0;
548 }
549 
550 /**
551  * Get IP6_TNL tunnel tos
552  * @arg link Link object
553  *
554  * @return tos value
555  */
557 {
558  struct ip6_tnl_info *ip6_tnl = link->l_info;
559 
560  IS_IP6_TNL_LINK_ASSERT(link);
561 
562  return ip6_tnl->tos;
563 }
564 
565 /**
566  * Set IP6_TNL tunnel encap limit
567  * @arg link Link object
568  * @arg encap_limit encaplimit value
569  *
570  * @return 0 on success or a negative error code
571  */
572 int rtnl_link_ip6_tnl_set_encaplimit(struct rtnl_link *link, uint8_t encap_limit)
573 {
574  struct ip6_tnl_info *ip6_tnl = link->l_info;
575 
576  IS_IP6_TNL_LINK_ASSERT(link);
577 
578  ip6_tnl->encap_limit = encap_limit;
579  ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_ENCAPLIMIT;
580 
581  return 0;
582 }
583 
584 /**
585  * Get IP6_TNL encaplimit
586  * @arg link Link object
587  *
588  * @return encaplimit value
589  */
591 {
592  struct ip6_tnl_info *ip6_tnl = link->l_info;
593 
594  IS_IP6_TNL_LINK_ASSERT(link);
595 
596  return ip6_tnl->encap_limit;
597 }
598 
599 /**
600  * Set IP6_TNL tunnel flowinfo
601  * @arg link Link object
602  * @arg flowinfo flowinfo value
603  *
604  * @return 0 on success or a negative error code
605  */
606 int rtnl_link_ip6_tnl_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo)
607 {
608  struct ip6_tnl_info *ip6_tnl = link->l_info;
609 
610  IS_IP6_TNL_LINK_ASSERT(link);
611 
612  ip6_tnl->flowinfo = flowinfo;
613  ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FLOWINFO;
614 
615  return 0;
616 }
617 
618 /**
619  * Get IP6_TNL flowinfo
620  * @arg link Link object
621  *
622  * @return flowinfo value
623  */
625 {
626  struct ip6_tnl_info *ip6_tnl = link->l_info;
627 
628  IS_IP6_TNL_LINK_ASSERT(link);
629 
630  return ip6_tnl->flowinfo;
631 }
632 
633 /**
634  * Set IP6_TNL tunnel flags
635  * @arg link Link object
636  * @arg flags tunnel flags
637  *
638  * @return 0 on success or a negative error code
639  */
640 int rtnl_link_ip6_tnl_set_flags(struct rtnl_link *link, uint32_t flags)
641 {
642  struct ip6_tnl_info *ip6_tnl = link->l_info;
643 
644  IS_IP6_TNL_LINK_ASSERT(link);
645 
646  ip6_tnl->flags = flags;
647  ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FLAGS;
648 
649  return 0;
650 }
651 
652 /**
653  * Get IP6_TNL path flags
654  * @arg link Link object
655  *
656  * @return flags value
657  */
659 {
660  struct ip6_tnl_info *ip6_tnl = link->l_info;
661 
662  IS_IP6_TNL_LINK_ASSERT(link);
663 
664  return ip6_tnl->flags;
665 }
666 
667 /**
668  * Set IP6_TNL tunnel proto
669  * @arg link Link object
670  * @arg proto tunnel proto
671  *
672  * @return 0 on success or a negative error code
673  */
674 int rtnl_link_ip6_tnl_set_proto(struct rtnl_link *link, uint8_t proto)
675 {
676  struct ip6_tnl_info *ip6_tnl = link->l_info;
677 
678  IS_IP6_TNL_LINK_ASSERT(link);
679 
680  ip6_tnl->proto = proto;
681  ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_PROTO;
682 
683  return 0;
684 }
685 
686 /**
687  * Get IP6_TNL proto
688  * @arg link Link object
689  *
690  * @return proto value
691  */
693 {
694  struct ip6_tnl_info *ip6_tnl = link->l_info;
695 
696  IS_IP6_TNL_LINK_ASSERT(link);
697 
698  return ip6_tnl->proto;
699 }
700 
701 /**
702  * Set IP6_TNL tunnel fwmark
703  * @arg link Link object
704  * @arg fwmark fwmark
705  *
706  * @return 0 on success or a negative error code
707  */
708 int rtnl_link_ip6_tnl_set_fwmark(struct rtnl_link *link, uint32_t fwmark)
709 {
710  struct ip6_tnl_info *ip6_tnl = link->l_info;
711 
712  IS_IP6_TNL_LINK_ASSERT(link);
713 
714  ip6_tnl->fwmark = fwmark;
715  ip6_tnl->ip6_tnl_mask |= IP6_TNL_ATTR_FWMARK;
716 
717  return 0;
718 }
719 
720 /**
721  * Get IP6_TNL tunnel fwmark
722  * @arg link Link object
723  * @arg fwmark addr to fill in with the fwmark
724  *
725  * @return 0 on success or a negative error code
726  */
727 int rtnl_link_ip6_tnl_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
728 {
729  struct ip6_tnl_info *ip6_tnl = link->l_info;
730 
731  IS_IP6_TNL_LINK_ASSERT(link);
732 
733  if (!(ip6_tnl->ip6_tnl_mask & IP6_TNL_ATTR_FWMARK))
734  return -NLE_NOATTR;
735 
736  *fwmark = ip6_tnl->fwmark;
737 
738  return 0;
739 }
740 
741 static void __init ip6_tnl_init(void)
742 {
743  rtnl_link_register_info(&ip6_tnl_info_ops);
744 }
745 
746 static void __exit ip6_tnl_exit(void)
747 {
748  rtnl_link_unregister_info(&ip6_tnl_info_ops);
749 }
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:699
#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:599
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:895
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:1013
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:958
@ 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:468
uint8_t rtnl_link_ip6_tnl_get_proto(struct rtnl_link *link)
Get IP6_TNL proto.
Definition: ip6tnl.c:692
uint32_t rtnl_link_ip6_tnl_get_flowinfo(struct rtnl_link *link)
Get IP6_TNL flowinfo.
Definition: ip6tnl.c:624
int rtnl_link_is_ip6_tnl(struct rtnl_link *link)
Check if link is a IP6_TNL link.
Definition: ip6tnl.c:360
int rtnl_link_ip6_tnl_set_link(struct rtnl_link *link, uint32_t index)
Set IP6_TNL tunnel interface index.
Definition: ip6tnl.c:398
int rtnl_link_ip6_tnl_add(struct nl_sock *sk, const char *name)
Create a new ip6_tnl tunnel device.
Definition: ip6tnl.c:373
uint8_t rtnl_link_ip6_tnl_get_ttl(struct rtnl_link *link)
Get IP6_TNL tunnel ttl.
Definition: ip6tnl.c:522
int rtnl_link_ip6_tnl_get_remote(struct rtnl_link *link, struct in6_addr *addr)
Get IP6_TNL tunnel remote address.
Definition: ip6tnl.c:486
uint32_t rtnl_link_ip6_tnl_get_flags(struct rtnl_link *link)
Get IP6_TNL path flags.
Definition: ip6tnl.c:658
int rtnl_link_ip6_tnl_set_fwmark(struct rtnl_link *link, uint32_t fwmark)
Set IP6_TNL tunnel fwmark.
Definition: ip6tnl.c:708
uint8_t rtnl_link_ip6_tnl_get_encaplimit(struct rtnl_link *link)
Get IP6_TNL encaplimit.
Definition: ip6tnl.c:590
int rtnl_link_ip6_tnl_set_flags(struct rtnl_link *link, uint32_t flags)
Set IP6_TNL tunnel flags.
Definition: ip6tnl.c:640
int rtnl_link_ip6_tnl_set_local(struct rtnl_link *link, struct in6_addr *addr)
Set IP6_TNL tunnel local address.
Definition: ip6tnl.c:432
int rtnl_link_ip6_tnl_set_ttl(struct rtnl_link *link, uint8_t ttl)
Set IP6_TNL tunnel ttl.
Definition: ip6tnl.c:504
int rtnl_link_ip6_tnl_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo)
Set IP6_TNL tunnel flowinfo.
Definition: ip6tnl.c:606
int rtnl_link_ip6_tnl_get_local(struct rtnl_link *link, struct in6_addr *addr)
Get IP6_TNL tunnel local address.
Definition: ip6tnl.c:450
int rtnl_link_ip6_tnl_set_tos(struct rtnl_link *link, uint8_t tos)
Set IP6_TNL tunnel tos.
Definition: ip6tnl.c:538
int rtnl_link_ip6_tnl_set_proto(struct rtnl_link *link, uint8_t proto)
Set IP6_TNL tunnel proto.
Definition: ip6tnl.c:674
int rtnl_link_ip6_tnl_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
Get IP6_TNL tunnel fwmark.
Definition: ip6tnl.c:727
int rtnl_link_ip6_tnl_set_encaplimit(struct rtnl_link *link, uint8_t encap_limit)
Set IP6_TNL tunnel encap limit.
Definition: ip6tnl.c:572
uint32_t rtnl_link_ip6_tnl_get_link(struct rtnl_link *link)
Get IP6_TNL tunnel interface index.
Definition: ip6tnl.c:416
uint8_t rtnl_link_ip6_tnl_get_tos(struct rtnl_link *link)
Get IP6_TNL tunnel tos.
Definition: ip6tnl.c:556
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