libnl  3.6.0
ip6gre.c
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 
3 /**
4  * @ingroup link
5  * @defgroup ip6gre IP6GRE
6  * ip6gre link module
7  *
8  * @details
9  * \b Link Type Name: "ip6gre"
10  *
11  * @route_doc{link_ip6gre, IP6GRE Documentation}
12  *
13  * @{
14  */
15 
16 #include <netlink-private/netlink.h>
17 #include <netlink/netlink.h>
18 #include <netlink/attr.h>
19 #include <netlink/utils.h>
20 #include <netlink/object.h>
21 #include <netlink/route/rtnl.h>
22 #include <netlink/route/link/ip6gre.h>
23 #include <netlink-private/route/link/api.h>
24 #include <linux/if_tunnel.h>
25 
26 #define IP6GRE_ATTR_LINK (1 << 0)
27 #define IP6GRE_ATTR_IFLAGS (1 << 1)
28 #define IP6GRE_ATTR_OFLAGS (1 << 2)
29 #define IP6GRE_ATTR_IKEY (1 << 3)
30 #define IP6GRE_ATTR_OKEY (1 << 4)
31 #define IP6GRE_ATTR_LOCAL (1 << 5)
32 #define IP6GRE_ATTR_REMOTE (1 << 6)
33 #define IP6GRE_ATTR_TTL (1 << 7)
34 #define IP6GRE_ATTR_ENCAPLIMIT (1 << 8)
35 #define IP6GRE_ATTR_FLOWINFO (1 << 9)
36 #define IP6GRE_ATTR_FLAGS (1 << 10)
37 #define IP6GRE_ATTR_FWMARK (1 << 11)
38 
40 {
41  uint8_t ttl;
42  uint8_t encaplimit;
43  uint16_t iflags;
44  uint16_t oflags;
45  uint32_t ikey;
46  uint32_t okey;
47  uint32_t link;
48  uint32_t flowinfo;
49  uint32_t flags;
50  struct in6_addr local;
51  struct in6_addr remote;
52  uint32_t fwmark;
53  uint32_t ip6gre_mask;
54 };
55 
56 static struct nla_policy ip6gre_policy[IFLA_GRE_MAX + 1] = {
57  [IFLA_GRE_LINK] = { .type = NLA_U32 },
58  [IFLA_GRE_IFLAGS] = { .type = NLA_U16 },
59  [IFLA_GRE_OFLAGS] = { .type = NLA_U16 },
60  [IFLA_GRE_IKEY] = { .type = NLA_U32 },
61  [IFLA_GRE_OKEY] = { .type = NLA_U32 },
62  [IFLA_GRE_LOCAL] = { .minlen = sizeof(struct in6_addr) },
63  [IFLA_GRE_REMOTE] = { .minlen = sizeof(struct in6_addr) },
64  [IFLA_GRE_TTL] = { .type = NLA_U8 },
65  [IFLA_GRE_ENCAP_LIMIT] = { .type = NLA_U8 },
66  [IFLA_GRE_FLOWINFO] = { .type = NLA_U32 },
67  [IFLA_GRE_FLAGS] = { .type = NLA_U32 },
68  [IFLA_GRE_FWMARK] = { .type = NLA_U32 },
69 };
70 
71 static int ip6gre_alloc(struct rtnl_link *link)
72 {
73  struct ip6gre_info *ip6gre;
74 
75  if (link->l_info)
76  memset(link->l_info, 0, sizeof(*ip6gre));
77  else {
78  ip6gre = calloc(1, sizeof(*ip6gre));
79  if (!ip6gre)
80  return -NLE_NOMEM;
81 
82  link->l_info = ip6gre;
83  }
84 
85  return 0;
86 }
87 
88 static int ip6gre_parse(struct rtnl_link *link, struct nlattr *data,
89  struct nlattr *xstats)
90 {
91  struct nlattr *tb[IFLA_GRE_MAX + 1];
92  struct ip6gre_info *ip6gre;
93  int err;
94 
95  NL_DBG(3, "Parsing IP6GRE link info\n");
96 
97  err = nla_parse_nested(tb, IFLA_GRE_MAX, data, ip6gre_policy);
98  if (err < 0)
99  goto errout;
100 
101  err = ip6gre_alloc(link);
102  if (err < 0)
103  goto errout;
104 
105  ip6gre = link->l_info;
106 
107  if (tb[IFLA_GRE_LINK]) {
108  ip6gre->link = nla_get_u32(tb[IFLA_GRE_LINK]);
109  ip6gre->ip6gre_mask |= IP6GRE_ATTR_LINK;
110  }
111 
112  if (tb[IFLA_GRE_IFLAGS]) {
113  ip6gre->iflags = nla_get_u16(tb[IFLA_GRE_IFLAGS]);
114  ip6gre->ip6gre_mask |= IP6GRE_ATTR_IFLAGS;
115  }
116 
117  if (tb[IFLA_GRE_OFLAGS]) {
118  ip6gre->oflags = nla_get_u16(tb[IFLA_GRE_OFLAGS]);
119  ip6gre->ip6gre_mask |= IP6GRE_ATTR_OFLAGS;
120  }
121 
122  if (tb[IFLA_GRE_IKEY]) {
123  ip6gre->ikey = nla_get_u32(tb[IFLA_GRE_IKEY]);
124  ip6gre->ip6gre_mask |= IP6GRE_ATTR_IKEY;
125  }
126 
127  if (tb[IFLA_GRE_OKEY]) {
128  ip6gre->okey = nla_get_u32(tb[IFLA_GRE_OKEY]);
129  ip6gre->ip6gre_mask |= IP6GRE_ATTR_OKEY;
130  }
131 
132  if (tb[IFLA_GRE_LOCAL]) {
133  nla_memcpy(&ip6gre->local, tb[IFLA_GRE_LOCAL], sizeof(struct in6_addr));
134  ip6gre->ip6gre_mask |= IP6GRE_ATTR_LOCAL;
135  }
136 
137  if (tb[IFLA_GRE_REMOTE]) {
138  nla_memcpy(&ip6gre->remote, tb[IFLA_GRE_REMOTE], sizeof(struct in6_addr));
139  ip6gre->ip6gre_mask |= IP6GRE_ATTR_REMOTE;
140  }
141 
142  if (tb[IFLA_GRE_TTL]) {
143  ip6gre->ttl = nla_get_u8(tb[IFLA_GRE_TTL]);
144  ip6gre->ip6gre_mask |= IP6GRE_ATTR_TTL;
145  }
146 
147  if (tb[IFLA_GRE_ENCAP_LIMIT]) {
148  ip6gre->encaplimit = nla_get_u8(tb[IFLA_GRE_ENCAP_LIMIT]);
149  ip6gre->ip6gre_mask |= IP6GRE_ATTR_ENCAPLIMIT;
150  }
151 
152  if (tb[IFLA_GRE_FLOWINFO]) {
153  ip6gre->flowinfo = nla_get_u32(tb[IFLA_GRE_FLOWINFO]);
154  ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLOWINFO;
155  }
156 
157  if (tb[IFLA_GRE_FLAGS]) {
158  ip6gre->flags = nla_get_u32(tb[IFLA_GRE_FLAGS]);
159  ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLAGS;
160  }
161 
162  if (tb[IFLA_GRE_FWMARK]) {
163  ip6gre->fwmark = nla_get_u32(tb[IFLA_GRE_FWMARK]);
164  ip6gre->ip6gre_mask |= IP6GRE_ATTR_FWMARK;
165  }
166 
167  err = 0;
168 
169  errout:
170  return err;
171 }
172 
173 static int ip6gre_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
174 {
175  struct ip6gre_info *ip6gre = link->l_info;
176  struct nlattr *data;
177 
178  data = nla_nest_start(msg, IFLA_INFO_DATA);
179  if (!data)
180  return -NLE_MSGSIZE;
181 
182  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LINK)
183  NLA_PUT_U32(msg, IFLA_GRE_LINK, ip6gre->link);
184 
185  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IFLAGS)
186  NLA_PUT_U16(msg, IFLA_GRE_IFLAGS, ip6gre->iflags);
187 
188  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OFLAGS)
189  NLA_PUT_U16(msg, IFLA_GRE_OFLAGS, ip6gre->oflags);
190 
191  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IKEY)
192  NLA_PUT_U32(msg, IFLA_GRE_IKEY, ip6gre->ikey);
193 
194  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OKEY)
195  NLA_PUT_U32(msg, IFLA_GRE_OKEY, ip6gre->okey);
196 
197  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LOCAL)
198  NLA_PUT(msg, IFLA_GRE_LOCAL, sizeof(struct in6_addr), &ip6gre->local);
199 
200  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_REMOTE)
201  NLA_PUT(msg, IFLA_GRE_REMOTE, sizeof(struct in6_addr), &ip6gre->remote);
202 
203  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_TTL)
204  NLA_PUT_U8(msg, IFLA_GRE_TTL, ip6gre->ttl);
205 
206  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_ENCAPLIMIT)
207  NLA_PUT_U8(msg, IFLA_GRE_ENCAP_LIMIT, ip6gre->encaplimit);
208 
209  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLOWINFO)
210  NLA_PUT_U32(msg, IFLA_GRE_FLOWINFO, ip6gre->flowinfo);
211 
212  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLAGS)
213  NLA_PUT_U32(msg, IFLA_GRE_FLAGS, ip6gre->flags);
214 
215  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FWMARK)
216  NLA_PUT_U32(msg, IFLA_GRE_FWMARK, ip6gre->fwmark);
217 
218  nla_nest_end(msg, data);
219 
220  nla_put_failure:
221 
222  return 0;
223 }
224 
225 static void ip6gre_free(struct rtnl_link *link)
226 {
227  struct ip6gre_info *ip6gre = link->l_info;
228 
229  free(ip6gre);
230  link->l_info = NULL;
231 }
232 
233 static void ip6gre_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
234 {
235  nl_dump(p, "ip6gre : %s", link->l_name);
236 }
237 
238 static void ip6gre_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
239 {
240  struct ip6gre_info *ip6gre = link->l_info;
241  char *name, addr[INET6_ADDRSTRLEN];
242 
243  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LINK) {
244  nl_dump(p, " link ");
245  name = rtnl_link_get_name(link);
246  if (name)
247  nl_dump_line(p, "%s\n", name);
248  else
249  nl_dump_line(p, "%u\n", ip6gre->link);
250  }
251 
252  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IFLAGS) {
253  nl_dump(p, " iflags ");
254  nl_dump_line(p, "%x\n", ip6gre->iflags);
255  }
256 
257  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OFLAGS) {
258  nl_dump(p, " oflags ");
259  nl_dump_line(p, "%x\n", ip6gre->oflags);
260  }
261 
262  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IKEY) {
263  nl_dump(p, " ikey ");
264  nl_dump_line(p, "%x\n",ip6gre->ikey);
265  }
266 
267  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OKEY) {
268  nl_dump(p, " okey ");
269  nl_dump_line(p, "%x\n", ip6gre->okey);
270  }
271 
272  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LOCAL) {
273  nl_dump(p, " local ");
274  if(inet_ntop(AF_INET6, &ip6gre->local, addr, sizeof(addr)))
275  nl_dump_line(p, "%s\n", addr);
276  else
277  nl_dump_line(p, "%#x\n", ip6gre->local);
278  }
279 
280  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_REMOTE) {
281  nl_dump(p, " remote ");
282  if(inet_ntop(AF_INET6, &ip6gre->remote, addr, sizeof(addr)))
283  nl_dump_line(p, "%s\n", addr);
284  else
285  nl_dump_line(p, "%#x\n", ip6gre->remote);
286  }
287 
288  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_TTL) {
289  nl_dump(p, " ttl ");
290  nl_dump_line(p, "%u\n", ip6gre->ttl);
291  }
292 
293  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_ENCAPLIMIT) {
294  nl_dump(p, " encaplimit ");
295  nl_dump_line(p, "%u\n", ip6gre->encaplimit);
296  }
297 
298  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLOWINFO) {
299  nl_dump(p, " flowinfo ");
300  nl_dump_line(p, "%x\n", ip6gre->flowinfo);
301  }
302 
303  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLAGS) {
304  nl_dump(p, " flags ");
305  nl_dump_line(p, "%x\n", ip6gre->flags);
306  }
307 
308  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FWMARK) {
309  nl_dump(p, " fwmark ");
310  nl_dump_line(p, "%x\n", ip6gre->fwmark);
311  }
312 }
313 
314 static int ip6gre_clone(struct rtnl_link *dst, struct rtnl_link *src)
315 {
316  struct ip6gre_info *ip6gre_dst, *ip6gre_src = src->l_info;
317  int err;
318 
319  dst->l_info = NULL;
320 
321  err = rtnl_link_set_type(dst, "ip6gre");
322  if (err < 0)
323  return err;
324 
325  ip6gre_dst = dst->l_info;
326 
327  if (!ip6gre_dst || !ip6gre_src)
328  BUG();
329 
330  memcpy(ip6gre_dst, ip6gre_src, sizeof(struct ip6gre_info));
331 
332  return 0;
333 }
334 
335 static struct rtnl_link_info_ops ip6gre_info_ops = {
336  .io_name = "ip6gre",
337  .io_alloc = ip6gre_alloc,
338  .io_parse = ip6gre_parse,
339  .io_dump = {
340  [NL_DUMP_LINE] = ip6gre_dump_line,
341  [NL_DUMP_DETAILS] = ip6gre_dump_details,
342  },
343  .io_clone = ip6gre_clone,
344  .io_put_attrs = ip6gre_put_attrs,
345  .io_free = ip6gre_free,
346 };
347 
348 #define IS_IP6GRE_LINK_ASSERT(link) \
349  if ((link)->l_info_ops != &ip6gre_info_ops) { \
350  APPBUG("Link is not a ip6gre link. set type \"ip6gre\" first.");\
351  return -NLE_OPNOTSUPP; \
352  }
353 
354 #define HAS_IP6GRE_ATTR_ASSERT(link,attr) \
355  if (!((link)->ip6gre_mask & (attr))) \
356  return -NLE_NOATTR;
357 
358 struct rtnl_link *rtnl_link_ip6gre_alloc(void)
359 {
360  struct rtnl_link *link;
361  int err;
362 
363  link = rtnl_link_alloc();
364  if (!link)
365  return NULL;
366 
367  err = rtnl_link_set_type(link, "ip6gre");
368  if (err < 0) {
369  rtnl_link_put(link);
370  return NULL;
371  }
372 
373  return link;
374 }
375 
376 /**
377  * Check if link is a IP6GRE link
378  * @arg link Link object
379  *
380  * @return True if link is a IP6GRE link, otherwise 0 is returned.
381  */
383 {
384  return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "ip6gre");
385 }
386 
387 /**
388  * Create a new IP6GRE tunnel device
389  * @arg sock netlink socket
390  * @arg name name of the tunnel deviceL
391  *
392  * Creates a new ip6gre tunnel device in the kernel
393  * @return 0 on success or a negative error code
394  */
395 int rtnl_link_ip6gre_add(struct nl_sock *sk, const char *name)
396 {
397  struct rtnl_link *link;
398  int err;
399 
400  link = rtnl_link_ip6gre_alloc();
401  if (!link)
402  return -NLE_NOMEM;
403 
404  if(name)
405  rtnl_link_set_name(link, name);
406 
407  err = rtnl_link_add(sk, link, NLM_F_CREATE);
408  rtnl_link_put(link);
409 
410  return err;
411 }
412 
413 /**
414  * Set IP6GRE tunnel interface index
415  * @arg link Link object
416  * @arg index interface index
417  *
418  * @return 0 on success or a negative error code
419  */
420 int rtnl_link_ip6gre_set_link(struct rtnl_link *link, uint32_t index)
421 {
422  struct ip6gre_info *ip6gre = link->l_info;
423 
424  IS_IP6GRE_LINK_ASSERT(link);
425 
426  ip6gre->link = index;
427  ip6gre->ip6gre_mask |= IP6GRE_ATTR_LINK;
428 
429  return 0;
430 }
431 
432 /**
433  * Get IP6GRE tunnel interface index
434  * @arg link Link object
435  * @arg index addr to fill in with the interface index
436  *
437  * @return 0 on success or a negative error code
438  */
439 int rtnl_link_ip6gre_get_link(struct rtnl_link *link, uint32_t *index)
440 {
441  struct ip6gre_info *ip6gre = link->l_info;
442 
443  IS_IP6GRE_LINK_ASSERT(link);
444 
445  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_LINK);
446 
447  *index = ip6gre->link;
448 
449  return 0;
450 }
451 
452 /**
453  * Set IP6GRE tunnel set iflags
454  * @arg link Link object
455  * @arg iflags ip6gre iflags
456  *
457  * @return 0 on success or a negative error code
458  */
459 int rtnl_link_ip6gre_set_iflags(struct rtnl_link *link, uint16_t iflags)
460 {
461  struct ip6gre_info *ip6gre = link->l_info;
462 
463  IS_IP6GRE_LINK_ASSERT(link);
464 
465  ip6gre->iflags = iflags;
466  ip6gre->ip6gre_mask |= IP6GRE_ATTR_IFLAGS;
467 
468  return 0;
469 }
470 
471 /**
472  * Get IP6GRE tunnel iflags
473  * @arg link Link object
474  * @arg iflags addr to fill in with the iflags
475  *
476  * @return 0 on success or a negative error code
477  */
478 int rtnl_link_ip6gre_get_iflags(struct rtnl_link *link, uint16_t *iflags)
479 {
480  struct ip6gre_info *ip6gre = link->l_info;
481 
482  IS_IP6GRE_LINK_ASSERT(link);
483 
484  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_IFLAGS);
485 
486  *iflags = ip6gre->iflags;
487 
488  return 0;
489 }
490 
491 /**
492  * Set IP6GRE tunnel set oflags
493  * @arg link Link object
494  * @arg oflags ip6gre oflags
495  *
496  * @return 0 on success or a negative error code
497  */
498 int rtnl_link_ip6gre_set_oflags(struct rtnl_link *link, uint16_t oflags)
499 {
500  struct ip6gre_info *ip6gre = link->l_info;
501 
502  IS_IP6GRE_LINK_ASSERT(link);
503 
504  ip6gre->oflags = oflags;
505  ip6gre->ip6gre_mask |= IP6GRE_ATTR_OFLAGS;
506 
507  return 0;
508 }
509 
510 /**
511  * Get IP6GRE tunnel oflags
512  * @arg link Link object
513  * @arg oflags addr to fill in with the oflags
514  *
515  * @return 0 on success or a negative error code
516  */
517 int rtnl_link_ip6gre_get_oflags(struct rtnl_link *link, uint16_t *oflags)
518 {
519  struct ip6gre_info *ip6gre = link->l_info;
520 
521  IS_IP6GRE_LINK_ASSERT(link);
522 
523  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_OFLAGS);
524 
525  *oflags = ip6gre->oflags;
526 
527  return 0;
528 }
529 
530 /**
531  * Set IP6GRE tunnel set ikey
532  * @arg link Link object
533  * @arg ikey ip6gre ikey
534  *
535  * @return 0 on success or a negative error code
536  */
537 int rtnl_link_ip6gre_set_ikey(struct rtnl_link *link, uint32_t ikey)
538 {
539  struct ip6gre_info *ip6gre = link->l_info;
540 
541  IS_IP6GRE_LINK_ASSERT(link);
542 
543  ip6gre->ikey = ikey;
544  ip6gre->ip6gre_mask |= IP6GRE_ATTR_IKEY;
545 
546  return 0;
547 }
548 
549 /**
550  * Get IP6GRE tunnel ikey
551  * @arg link Link object
552  * @arg ikey addr to fill in with the ikey
553  *
554  * @return 0 on success or a negative error code
555  */
556 int rtnl_link_ip6gre_get_ikey(struct rtnl_link *link, uint32_t *ikey)
557 {
558  struct ip6gre_info *ip6gre = link->l_info;
559 
560  IS_IP6GRE_LINK_ASSERT(link);
561 
562  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_IKEY);
563 
564  *ikey = ip6gre->ikey;
565 
566  return 0;
567 }
568 
569 /**
570  * Set IP6GRE tunnel set okey
571  * @arg link Link object
572  * @arg okey ip6gre okey
573  *
574  * @return 0 on success or a negative error code
575  */
576 int rtnl_link_ip6gre_set_okey(struct rtnl_link *link, uint32_t okey)
577 {
578  struct ip6gre_info *ip6gre = link->l_info;
579 
580  IS_IP6GRE_LINK_ASSERT(link);
581 
582  ip6gre->okey = okey;
583  ip6gre->ip6gre_mask |= IP6GRE_ATTR_OKEY;
584 
585  return 0;
586 }
587 
588 /**
589  * Get IP6GRE tunnel okey
590  * @arg link Link object
591  * @arg okey addr to fill in with the okey
592  *
593  * @return okey value
594  */
595 int rtnl_link_ip6gre_get_okey(struct rtnl_link *link, uint32_t *okey)
596 {
597  struct ip6gre_info *ip6gre = link->l_info;
598 
599  IS_IP6GRE_LINK_ASSERT(link);
600 
601  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_OKEY);
602 
603  *okey = ip6gre->okey;
604 
605  return 0;
606 }
607 
608 /**
609  * Set IP6GRE tunnel local address
610  * @arg link Link object
611  * @arg local local address
612  *
613  * @return 0 on success or a negative error code
614  */
615 int rtnl_link_ip6gre_set_local(struct rtnl_link *link, struct in6_addr *local)
616 {
617  struct ip6gre_info *ip6gre = link->l_info;
618 
619  IS_IP6GRE_LINK_ASSERT(link);
620 
621  memcpy(&ip6gre->local, local, sizeof(struct in6_addr));
622  ip6gre->ip6gre_mask |= IP6GRE_ATTR_LOCAL;
623 
624  return 0;
625 }
626 
627 /**
628  * Get IP6GRE tunnel local address
629  * @arg link Link object
630  * @arg local addr to fill in with local address
631  *
632  * @return 0 on success or a negative error code
633  */
634 int rtnl_link_ip6gre_get_local(struct rtnl_link *link, struct in6_addr *local)
635 {
636  struct ip6gre_info *ip6gre = link->l_info;
637 
638  IS_IP6GRE_LINK_ASSERT(link);
639 
640  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_LOCAL);
641 
642  memcpy(local, &ip6gre->local, sizeof(struct in6_addr));
643 
644  return 0;
645 }
646 
647 /**
648  * Set IP6GRE tunnel remote address
649  * @arg link Link object
650  * @arg remote remote address
651  *
652  * @return 0 on success or a negative error code
653  */
654 int rtnl_link_ip6gre_set_remote(struct rtnl_link *link, struct in6_addr *remote)
655 {
656  struct ip6gre_info *ip6gre = link->l_info;
657 
658  IS_IP6GRE_LINK_ASSERT(link);
659 
660  memcpy(&ip6gre->remote, remote, sizeof(struct in6_addr));
661  ip6gre->ip6gre_mask |= IP6GRE_ATTR_REMOTE;
662 
663  return 0;
664 }
665 
666 /**
667  * Get IP6GRE tunnel remote address
668  * @arg link Link object
669  * @arg remote addr to fill in with remote address
670  *
671  * @return 0 on success or a negative error code
672  */
673 int rtnl_link_ip6gre_get_remote(struct rtnl_link *link, struct in6_addr *remote)
674 {
675  struct ip6gre_info *ip6gre = link->l_info;
676 
677  IS_IP6GRE_LINK_ASSERT(link);
678 
679  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_REMOTE);
680 
681  memcpy(remote, &ip6gre->remote, sizeof(struct in6_addr));
682 
683  return 0;
684 }
685 
686 /**
687  * Set IP6GRE tunnel ttl
688  * @arg link Link object
689  * @arg ttl tunnel ttl
690  *
691  * @return 0 on success or a negative error code
692  */
693 int rtnl_link_ip6gre_set_ttl(struct rtnl_link *link, uint8_t ttl)
694 {
695  struct ip6gre_info *ip6gre = link->l_info;
696 
697  IS_IP6GRE_LINK_ASSERT(link);
698 
699  ip6gre->ttl = ttl;
700  ip6gre->ip6gre_mask |= IP6GRE_ATTR_TTL;
701 
702  return 0;
703 }
704 
705 /**
706  * Set IP6GRE tunnel ttl
707  * @arg link Link object
708  * @arg ttl addr to fill in with the ttl
709  *
710  * @return 0 on success or a negative error code
711  */
712 int rtnl_link_ip6gre_get_ttl(struct rtnl_link *link, uint8_t *ttl)
713 {
714  struct ip6gre_info *ip6gre = link->l_info;
715 
716  IS_IP6GRE_LINK_ASSERT(link);
717 
718  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_TTL);
719 
720  *ttl = ip6gre->ttl;
721 
722  return 0;
723 }
724 
725 /**
726  * Set IP6GRE tunnel encap limit
727  * @arg link Link object
728  * @arg encaplimit tunnel encap limit value
729  *
730  * @return 0 on success or a negative error code
731  */
732 int rtnl_link_ip6gre_set_encaplimit(struct rtnl_link *link, uint8_t encaplimit)
733 {
734  struct ip6gre_info *ip6gre = link->l_info;
735 
736  IS_IP6GRE_LINK_ASSERT(link);
737 
738  ip6gre->encaplimit = encaplimit;
739  ip6gre->ip6gre_mask |= IP6GRE_ATTR_ENCAPLIMIT;
740 
741  return 0;
742 }
743 
744 /**
745  * Get IP6GRE tunnel encap limit
746  * @arg link Link object
747  * @arg encaplimit addr to fill in with the encaplimit
748  *
749  * @return 0 on success or a negative error code
750  */
751 int rtnl_link_ip6gre_get_encaplimit(struct rtnl_link *link, uint8_t *encaplimit)
752 {
753  struct ip6gre_info *ip6gre = link->l_info;
754 
755  IS_IP6GRE_LINK_ASSERT(link);
756 
757  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_ENCAPLIMIT);
758 
759  *encaplimit = ip6gre->encaplimit;
760 
761  return 0;
762 }
763 
764 /**
765  * Set IP6GRE tunnel flowinfo
766  * @arg link Link object
767  * @arg flowinfo flowinfo value
768  *
769  * @return 0 on success or a negative error code
770  */
771 int rtnl_link_ip6gre_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo)
772 {
773  struct ip6gre_info *ip6gre = link->l_info;
774 
775  IS_IP6GRE_LINK_ASSERT(link);
776 
777  ip6gre->flowinfo = flowinfo;
778  ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLOWINFO;
779 
780  return 0;
781 }
782 
783 /**
784  * Get IP6GRE flowinfo
785  * @arg link Link object
786  * @arg flowinfo addr to fill in with the flowinfo
787  *
788  * @return 0 on success or a negative error code
789  */
790 int rtnl_link_ip6gre_get_flowinfo(struct rtnl_link *link, uint32_t *flowinfo)
791 {
792  struct ip6gre_info *ip6gre = link->l_info;
793 
794  IS_IP6GRE_LINK_ASSERT(link);
795 
796  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FLOWINFO);
797 
798  *flowinfo = ip6gre->flowinfo;
799 
800  return 0;
801 }
802 
803 /**
804  * Set IP6GRE tunnel flags
805  * @arg link Link object
806  * @arg flags tunnel flags
807  *
808  * @return 0 on success or a negative error code
809  */
810 int rtnl_link_ip6gre_set_flags(struct rtnl_link *link, uint32_t flags)
811 {
812  struct ip6gre_info *ip6gre = link->l_info;
813 
814  IS_IP6GRE_LINK_ASSERT(link);
815 
816  ip6gre->flags = flags;
817  ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLAGS;
818 
819  return 0;
820 }
821 
822 /**
823  * Get IP6GRE flags
824  * @arg link Link object
825  * @arg flags addr to fill in with the tunnel flags
826  *
827  * @return 0 on success or a negative error code
828  */
829 int rtnl_link_ip6gre_get_flags(struct rtnl_link *link, uint32_t *flags)
830 {
831  struct ip6gre_info *ip6gre = link->l_info;
832 
833  IS_IP6GRE_LINK_ASSERT(link);
834 
835  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FLAGS);
836 
837  *flags = ip6gre->flags;
838 
839  return 0;
840 }
841 
842 /**
843  * Set IP6GRE tunnel fwmark
844  * @arg link Link object
845  * @arg fwmark fwmark
846  *
847  * @return 0 on success or a negative error code
848  */
849 int rtnl_link_ip6gre_set_fwmark(struct rtnl_link *link, uint32_t fwmark)
850 {
851  struct ip6gre_info *ip6gre = link->l_info;
852 
853  IS_IP6GRE_LINK_ASSERT(link);
854 
855  ip6gre->fwmark = fwmark;
856  ip6gre->ip6gre_mask |= IP6GRE_ATTR_FWMARK;
857 
858  return 0;
859 }
860 
861 /**
862  * Get IP6GRE tunnel fwmark
863  * @arg link Link object
864  * @arg fwmark addr to fill in with the fwmark
865  *
866  * @return 0 on success or a negative error code
867  */
868 int rtnl_link_ip6gre_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
869 {
870  struct ip6gre_info *ip6gre = link->l_info;
871 
872  IS_IP6GRE_LINK_ASSERT(link);
873 
874  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FWMARK);
875 
876  *fwmark = ip6gre->fwmark;
877 
878  return 0;
879 }
880 
881 static void __init ip6gre_init(void)
882 {
883  rtnl_link_register_info(&ip6gre_info_ops);
884 }
885 
886 static void __exit ip6gre_exit(void)
887 {
888  rtnl_link_unregister_info(&ip6gre_info_ops);
889 }
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:699
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:649
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition: attr.h:212
#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_U16
16 bit integer
Definition: attr.h:36
@ NLA_U32
32 bit integer
Definition: attr.h:37
int rtnl_link_ip6gre_set_fwmark(struct rtnl_link *link, uint32_t fwmark)
Set IP6GRE tunnel fwmark.
Definition: ip6gre.c:849
int rtnl_link_ip6gre_set_flags(struct rtnl_link *link, uint32_t flags)
Set IP6GRE tunnel flags.
Definition: ip6gre.c:810
int rtnl_link_ip6gre_set_remote(struct rtnl_link *link, struct in6_addr *remote)
Set IP6GRE tunnel remote address.
Definition: ip6gre.c:654
int rtnl_link_ip6gre_set_ttl(struct rtnl_link *link, uint8_t ttl)
Set IP6GRE tunnel ttl.
Definition: ip6gre.c:693
int rtnl_link_ip6gre_get_oflags(struct rtnl_link *link, uint16_t *oflags)
Get IP6GRE tunnel oflags.
Definition: ip6gre.c:517
int rtnl_link_ip6gre_set_okey(struct rtnl_link *link, uint32_t okey)
Set IP6GRE tunnel set okey.
Definition: ip6gre.c:576
int rtnl_link_ip6gre_get_ttl(struct rtnl_link *link, uint8_t *ttl)
Set IP6GRE tunnel ttl.
Definition: ip6gre.c:712
int rtnl_link_ip6gre_set_iflags(struct rtnl_link *link, uint16_t iflags)
Set IP6GRE tunnel set iflags.
Definition: ip6gre.c:459
int rtnl_link_ip6gre_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
Get IP6GRE tunnel fwmark.
Definition: ip6gre.c:868
int rtnl_link_ip6gre_set_link(struct rtnl_link *link, uint32_t index)
Set IP6GRE tunnel interface index.
Definition: ip6gre.c:420
int rtnl_link_ip6gre_get_ikey(struct rtnl_link *link, uint32_t *ikey)
Get IP6GRE tunnel ikey.
Definition: ip6gre.c:556
int rtnl_link_ip6gre_get_iflags(struct rtnl_link *link, uint16_t *iflags)
Get IP6GRE tunnel iflags.
Definition: ip6gre.c:478
int rtnl_link_ip6gre_get_flowinfo(struct rtnl_link *link, uint32_t *flowinfo)
Get IP6GRE flowinfo.
Definition: ip6gre.c:790
int rtnl_link_ip6gre_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo)
Set IP6GRE tunnel flowinfo.
Definition: ip6gre.c:771
int rtnl_link_ip6gre_set_encaplimit(struct rtnl_link *link, uint8_t encaplimit)
Set IP6GRE tunnel encap limit.
Definition: ip6gre.c:732
int rtnl_link_ip6gre_get_flags(struct rtnl_link *link, uint32_t *flags)
Get IP6GRE flags.
Definition: ip6gre.c:829
int rtnl_link_ip6gre_set_ikey(struct rtnl_link *link, uint32_t ikey)
Set IP6GRE tunnel set ikey.
Definition: ip6gre.c:537
int rtnl_link_ip6gre_set_local(struct rtnl_link *link, struct in6_addr *local)
Set IP6GRE tunnel local address.
Definition: ip6gre.c:615
int rtnl_link_ip6gre_get_link(struct rtnl_link *link, uint32_t *index)
Get IP6GRE tunnel interface index.
Definition: ip6gre.c:439
int rtnl_link_ip6gre_add(struct nl_sock *sk, const char *name)
Create a new IP6GRE tunnel device.
Definition: ip6gre.c:395
int rtnl_link_ip6gre_get_local(struct rtnl_link *link, struct in6_addr *local)
Get IP6GRE tunnel local address.
Definition: ip6gre.c:634
int rtnl_link_ip6gre_get_okey(struct rtnl_link *link, uint32_t *okey)
Get IP6GRE tunnel okey.
Definition: ip6gre.c:595
int rtnl_link_ip6gre_set_oflags(struct rtnl_link *link, uint16_t oflags)
Set IP6GRE tunnel set oflags.
Definition: ip6gre.c:498
int rtnl_link_ip6gre_get_encaplimit(struct rtnl_link *link, uint8_t *encaplimit)
Get IP6GRE tunnel encap limit.
Definition: ip6gre.c:751
int rtnl_link_is_ip6gre(struct rtnl_link *link)
Check if link is a IP6GRE link.
Definition: ip6gre.c:382
int rtnl_link_ip6gre_get_remote(struct rtnl_link *link, struct in6_addr *remote)
Get IP6GRE tunnel remote address.
Definition: ip6gre.c:673
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