libnl  3.7.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;
242  char addr[INET6_ADDRSTRLEN];
243 
244  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LINK) {
245  nl_dump(p, " link ");
246  name = rtnl_link_get_name(link);
247  if (name)
248  nl_dump_line(p, "%s\n", name);
249  else
250  nl_dump_line(p, "%u\n", ip6gre->link);
251  }
252 
253  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IFLAGS) {
254  nl_dump(p, " iflags ");
255  nl_dump_line(p, "%x\n", ip6gre->iflags);
256  }
257 
258  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OFLAGS) {
259  nl_dump(p, " oflags ");
260  nl_dump_line(p, "%x\n", ip6gre->oflags);
261  }
262 
263  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_IKEY) {
264  nl_dump(p, " ikey ");
265  nl_dump_line(p, "%x\n",ip6gre->ikey);
266  }
267 
268  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_OKEY) {
269  nl_dump(p, " okey ");
270  nl_dump_line(p, "%x\n", ip6gre->okey);
271  }
272 
273  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_LOCAL) {
274  nl_dump(p, " local ");
275  nl_dump_line(p, "%s\n",
276  _nl_inet_ntop(AF_INET6, &ip6gre->local, addr));
277  }
278 
279  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_REMOTE) {
280  nl_dump(p, " remote ");
281  nl_dump_line(p, "%s\n",
282  _nl_inet_ntop(AF_INET6, &ip6gre->remote, addr));
283  }
284 
285  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_TTL) {
286  nl_dump(p, " ttl ");
287  nl_dump_line(p, "%u\n", ip6gre->ttl);
288  }
289 
290  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_ENCAPLIMIT) {
291  nl_dump(p, " encaplimit ");
292  nl_dump_line(p, "%u\n", ip6gre->encaplimit);
293  }
294 
295  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLOWINFO) {
296  nl_dump(p, " flowinfo ");
297  nl_dump_line(p, "%x\n", ip6gre->flowinfo);
298  }
299 
300  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FLAGS) {
301  nl_dump(p, " flags ");
302  nl_dump_line(p, "%x\n", ip6gre->flags);
303  }
304 
305  if (ip6gre->ip6gre_mask & IP6GRE_ATTR_FWMARK) {
306  nl_dump(p, " fwmark ");
307  nl_dump_line(p, "%x\n", ip6gre->fwmark);
308  }
309 }
310 
311 static int ip6gre_clone(struct rtnl_link *dst, struct rtnl_link *src)
312 {
313  struct ip6gre_info *ip6gre_dst, *ip6gre_src = src->l_info;
314  int err;
315 
316  dst->l_info = NULL;
317 
318  err = rtnl_link_set_type(dst, "ip6gre");
319  if (err < 0)
320  return err;
321 
322  ip6gre_dst = dst->l_info;
323 
324  if (!ip6gre_dst || !ip6gre_src)
325  BUG();
326 
327  memcpy(ip6gre_dst, ip6gre_src, sizeof(struct ip6gre_info));
328 
329  return 0;
330 }
331 
332 static struct rtnl_link_info_ops ip6gre_info_ops = {
333  .io_name = "ip6gre",
334  .io_alloc = ip6gre_alloc,
335  .io_parse = ip6gre_parse,
336  .io_dump = {
337  [NL_DUMP_LINE] = ip6gre_dump_line,
338  [NL_DUMP_DETAILS] = ip6gre_dump_details,
339  },
340  .io_clone = ip6gre_clone,
341  .io_put_attrs = ip6gre_put_attrs,
342  .io_free = ip6gre_free,
343 };
344 
345 #define IS_IP6GRE_LINK_ASSERT(link) \
346  if ((link)->l_info_ops != &ip6gre_info_ops) { \
347  APPBUG("Link is not a ip6gre link. set type \"ip6gre\" first.");\
348  return -NLE_OPNOTSUPP; \
349  }
350 
351 #define HAS_IP6GRE_ATTR_ASSERT(link,attr) \
352  if (!((link)->ip6gre_mask & (attr))) \
353  return -NLE_NOATTR;
354 
355 struct rtnl_link *rtnl_link_ip6gre_alloc(void)
356 {
357  struct rtnl_link *link;
358  int err;
359 
360  link = rtnl_link_alloc();
361  if (!link)
362  return NULL;
363 
364  err = rtnl_link_set_type(link, "ip6gre");
365  if (err < 0) {
366  rtnl_link_put(link);
367  return NULL;
368  }
369 
370  return link;
371 }
372 
373 /**
374  * Check if link is a IP6GRE link
375  * @arg link Link object
376  *
377  * @return True if link is a IP6GRE link, otherwise 0 is returned.
378  */
380 {
381  return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "ip6gre");
382 }
383 
384 /**
385  * Create a new IP6GRE tunnel device
386  * @arg sock netlink socket
387  * @arg name name of the tunnel deviceL
388  *
389  * Creates a new ip6gre tunnel device in the kernel
390  * @return 0 on success or a negative error code
391  */
392 int rtnl_link_ip6gre_add(struct nl_sock *sk, const char *name)
393 {
394  struct rtnl_link *link;
395  int err;
396 
397  link = rtnl_link_ip6gre_alloc();
398  if (!link)
399  return -NLE_NOMEM;
400 
401  if(name)
402  rtnl_link_set_name(link, name);
403 
404  err = rtnl_link_add(sk, link, NLM_F_CREATE);
405  rtnl_link_put(link);
406 
407  return err;
408 }
409 
410 /**
411  * Set IP6GRE tunnel interface index
412  * @arg link Link object
413  * @arg index interface index
414  *
415  * @return 0 on success or a negative error code
416  */
417 int rtnl_link_ip6gre_set_link(struct rtnl_link *link, uint32_t index)
418 {
419  struct ip6gre_info *ip6gre = link->l_info;
420 
421  IS_IP6GRE_LINK_ASSERT(link);
422 
423  ip6gre->link = index;
424  ip6gre->ip6gre_mask |= IP6GRE_ATTR_LINK;
425 
426  return 0;
427 }
428 
429 /**
430  * Get IP6GRE tunnel interface index
431  * @arg link Link object
432  * @arg index addr to fill in with the interface index
433  *
434  * @return 0 on success or a negative error code
435  */
436 int rtnl_link_ip6gre_get_link(struct rtnl_link *link, uint32_t *index)
437 {
438  struct ip6gre_info *ip6gre = link->l_info;
439 
440  IS_IP6GRE_LINK_ASSERT(link);
441 
442  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_LINK);
443 
444  *index = ip6gre->link;
445 
446  return 0;
447 }
448 
449 /**
450  * Set IP6GRE tunnel set iflags
451  * @arg link Link object
452  * @arg iflags ip6gre iflags
453  *
454  * @return 0 on success or a negative error code
455  */
456 int rtnl_link_ip6gre_set_iflags(struct rtnl_link *link, uint16_t iflags)
457 {
458  struct ip6gre_info *ip6gre = link->l_info;
459 
460  IS_IP6GRE_LINK_ASSERT(link);
461 
462  ip6gre->iflags = iflags;
463  ip6gre->ip6gre_mask |= IP6GRE_ATTR_IFLAGS;
464 
465  return 0;
466 }
467 
468 /**
469  * Get IP6GRE tunnel iflags
470  * @arg link Link object
471  * @arg iflags addr to fill in with the iflags
472  *
473  * @return 0 on success or a negative error code
474  */
475 int rtnl_link_ip6gre_get_iflags(struct rtnl_link *link, uint16_t *iflags)
476 {
477  struct ip6gre_info *ip6gre = link->l_info;
478 
479  IS_IP6GRE_LINK_ASSERT(link);
480 
481  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_IFLAGS);
482 
483  *iflags = ip6gre->iflags;
484 
485  return 0;
486 }
487 
488 /**
489  * Set IP6GRE tunnel set oflags
490  * @arg link Link object
491  * @arg oflags ip6gre oflags
492  *
493  * @return 0 on success or a negative error code
494  */
495 int rtnl_link_ip6gre_set_oflags(struct rtnl_link *link, uint16_t oflags)
496 {
497  struct ip6gre_info *ip6gre = link->l_info;
498 
499  IS_IP6GRE_LINK_ASSERT(link);
500 
501  ip6gre->oflags = oflags;
502  ip6gre->ip6gre_mask |= IP6GRE_ATTR_OFLAGS;
503 
504  return 0;
505 }
506 
507 /**
508  * Get IP6GRE tunnel oflags
509  * @arg link Link object
510  * @arg oflags addr to fill in with the oflags
511  *
512  * @return 0 on success or a negative error code
513  */
514 int rtnl_link_ip6gre_get_oflags(struct rtnl_link *link, uint16_t *oflags)
515 {
516  struct ip6gre_info *ip6gre = link->l_info;
517 
518  IS_IP6GRE_LINK_ASSERT(link);
519 
520  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_OFLAGS);
521 
522  *oflags = ip6gre->oflags;
523 
524  return 0;
525 }
526 
527 /**
528  * Set IP6GRE tunnel set ikey
529  * @arg link Link object
530  * @arg ikey ip6gre ikey
531  *
532  * @return 0 on success or a negative error code
533  */
534 int rtnl_link_ip6gre_set_ikey(struct rtnl_link *link, uint32_t ikey)
535 {
536  struct ip6gre_info *ip6gre = link->l_info;
537 
538  IS_IP6GRE_LINK_ASSERT(link);
539 
540  ip6gre->ikey = ikey;
541  ip6gre->ip6gre_mask |= IP6GRE_ATTR_IKEY;
542 
543  return 0;
544 }
545 
546 /**
547  * Get IP6GRE tunnel ikey
548  * @arg link Link object
549  * @arg ikey addr to fill in with the ikey
550  *
551  * @return 0 on success or a negative error code
552  */
553 int rtnl_link_ip6gre_get_ikey(struct rtnl_link *link, uint32_t *ikey)
554 {
555  struct ip6gre_info *ip6gre = link->l_info;
556 
557  IS_IP6GRE_LINK_ASSERT(link);
558 
559  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_IKEY);
560 
561  *ikey = ip6gre->ikey;
562 
563  return 0;
564 }
565 
566 /**
567  * Set IP6GRE tunnel set okey
568  * @arg link Link object
569  * @arg okey ip6gre okey
570  *
571  * @return 0 on success or a negative error code
572  */
573 int rtnl_link_ip6gre_set_okey(struct rtnl_link *link, uint32_t okey)
574 {
575  struct ip6gre_info *ip6gre = link->l_info;
576 
577  IS_IP6GRE_LINK_ASSERT(link);
578 
579  ip6gre->okey = okey;
580  ip6gre->ip6gre_mask |= IP6GRE_ATTR_OKEY;
581 
582  return 0;
583 }
584 
585 /**
586  * Get IP6GRE tunnel okey
587  * @arg link Link object
588  * @arg okey addr to fill in with the okey
589  *
590  * @return okey value
591  */
592 int rtnl_link_ip6gre_get_okey(struct rtnl_link *link, uint32_t *okey)
593 {
594  struct ip6gre_info *ip6gre = link->l_info;
595 
596  IS_IP6GRE_LINK_ASSERT(link);
597 
598  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_OKEY);
599 
600  *okey = ip6gre->okey;
601 
602  return 0;
603 }
604 
605 /**
606  * Set IP6GRE tunnel local address
607  * @arg link Link object
608  * @arg local local address
609  *
610  * @return 0 on success or a negative error code
611  */
612 int rtnl_link_ip6gre_set_local(struct rtnl_link *link, struct in6_addr *local)
613 {
614  struct ip6gre_info *ip6gre = link->l_info;
615 
616  IS_IP6GRE_LINK_ASSERT(link);
617 
618  memcpy(&ip6gre->local, local, sizeof(struct in6_addr));
619  ip6gre->ip6gre_mask |= IP6GRE_ATTR_LOCAL;
620 
621  return 0;
622 }
623 
624 /**
625  * Get IP6GRE tunnel local address
626  * @arg link Link object
627  * @arg local addr to fill in with local address
628  *
629  * @return 0 on success or a negative error code
630  */
631 int rtnl_link_ip6gre_get_local(struct rtnl_link *link, struct in6_addr *local)
632 {
633  struct ip6gre_info *ip6gre = link->l_info;
634 
635  IS_IP6GRE_LINK_ASSERT(link);
636 
637  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_LOCAL);
638 
639  memcpy(local, &ip6gre->local, sizeof(struct in6_addr));
640 
641  return 0;
642 }
643 
644 /**
645  * Set IP6GRE tunnel remote address
646  * @arg link Link object
647  * @arg remote remote address
648  *
649  * @return 0 on success or a negative error code
650  */
651 int rtnl_link_ip6gre_set_remote(struct rtnl_link *link, struct in6_addr *remote)
652 {
653  struct ip6gre_info *ip6gre = link->l_info;
654 
655  IS_IP6GRE_LINK_ASSERT(link);
656 
657  memcpy(&ip6gre->remote, remote, sizeof(struct in6_addr));
658  ip6gre->ip6gre_mask |= IP6GRE_ATTR_REMOTE;
659 
660  return 0;
661 }
662 
663 /**
664  * Get IP6GRE tunnel remote address
665  * @arg link Link object
666  * @arg remote addr to fill in with remote address
667  *
668  * @return 0 on success or a negative error code
669  */
670 int rtnl_link_ip6gre_get_remote(struct rtnl_link *link, struct in6_addr *remote)
671 {
672  struct ip6gre_info *ip6gre = link->l_info;
673 
674  IS_IP6GRE_LINK_ASSERT(link);
675 
676  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_REMOTE);
677 
678  memcpy(remote, &ip6gre->remote, sizeof(struct in6_addr));
679 
680  return 0;
681 }
682 
683 /**
684  * Set IP6GRE tunnel ttl
685  * @arg link Link object
686  * @arg ttl tunnel ttl
687  *
688  * @return 0 on success or a negative error code
689  */
690 int rtnl_link_ip6gre_set_ttl(struct rtnl_link *link, uint8_t ttl)
691 {
692  struct ip6gre_info *ip6gre = link->l_info;
693 
694  IS_IP6GRE_LINK_ASSERT(link);
695 
696  ip6gre->ttl = ttl;
697  ip6gre->ip6gre_mask |= IP6GRE_ATTR_TTL;
698 
699  return 0;
700 }
701 
702 /**
703  * Set IP6GRE tunnel ttl
704  * @arg link Link object
705  * @arg ttl addr to fill in with the ttl
706  *
707  * @return 0 on success or a negative error code
708  */
709 int rtnl_link_ip6gre_get_ttl(struct rtnl_link *link, uint8_t *ttl)
710 {
711  struct ip6gre_info *ip6gre = link->l_info;
712 
713  IS_IP6GRE_LINK_ASSERT(link);
714 
715  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_TTL);
716 
717  *ttl = ip6gre->ttl;
718 
719  return 0;
720 }
721 
722 /**
723  * Set IP6GRE tunnel encap limit
724  * @arg link Link object
725  * @arg encaplimit tunnel encap limit value
726  *
727  * @return 0 on success or a negative error code
728  */
729 int rtnl_link_ip6gre_set_encaplimit(struct rtnl_link *link, uint8_t encaplimit)
730 {
731  struct ip6gre_info *ip6gre = link->l_info;
732 
733  IS_IP6GRE_LINK_ASSERT(link);
734 
735  ip6gre->encaplimit = encaplimit;
736  ip6gre->ip6gre_mask |= IP6GRE_ATTR_ENCAPLIMIT;
737 
738  return 0;
739 }
740 
741 /**
742  * Get IP6GRE tunnel encap limit
743  * @arg link Link object
744  * @arg encaplimit addr to fill in with the encaplimit
745  *
746  * @return 0 on success or a negative error code
747  */
748 int rtnl_link_ip6gre_get_encaplimit(struct rtnl_link *link, uint8_t *encaplimit)
749 {
750  struct ip6gre_info *ip6gre = link->l_info;
751 
752  IS_IP6GRE_LINK_ASSERT(link);
753 
754  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_ENCAPLIMIT);
755 
756  *encaplimit = ip6gre->encaplimit;
757 
758  return 0;
759 }
760 
761 /**
762  * Set IP6GRE tunnel flowinfo
763  * @arg link Link object
764  * @arg flowinfo flowinfo value
765  *
766  * @return 0 on success or a negative error code
767  */
768 int rtnl_link_ip6gre_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo)
769 {
770  struct ip6gre_info *ip6gre = link->l_info;
771 
772  IS_IP6GRE_LINK_ASSERT(link);
773 
774  ip6gre->flowinfo = flowinfo;
775  ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLOWINFO;
776 
777  return 0;
778 }
779 
780 /**
781  * Get IP6GRE flowinfo
782  * @arg link Link object
783  * @arg flowinfo addr to fill in with the flowinfo
784  *
785  * @return 0 on success or a negative error code
786  */
787 int rtnl_link_ip6gre_get_flowinfo(struct rtnl_link *link, uint32_t *flowinfo)
788 {
789  struct ip6gre_info *ip6gre = link->l_info;
790 
791  IS_IP6GRE_LINK_ASSERT(link);
792 
793  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FLOWINFO);
794 
795  *flowinfo = ip6gre->flowinfo;
796 
797  return 0;
798 }
799 
800 /**
801  * Set IP6GRE tunnel flags
802  * @arg link Link object
803  * @arg flags tunnel flags
804  *
805  * @return 0 on success or a negative error code
806  */
807 int rtnl_link_ip6gre_set_flags(struct rtnl_link *link, uint32_t flags)
808 {
809  struct ip6gre_info *ip6gre = link->l_info;
810 
811  IS_IP6GRE_LINK_ASSERT(link);
812 
813  ip6gre->flags = flags;
814  ip6gre->ip6gre_mask |= IP6GRE_ATTR_FLAGS;
815 
816  return 0;
817 }
818 
819 /**
820  * Get IP6GRE flags
821  * @arg link Link object
822  * @arg flags addr to fill in with the tunnel flags
823  *
824  * @return 0 on success or a negative error code
825  */
826 int rtnl_link_ip6gre_get_flags(struct rtnl_link *link, uint32_t *flags)
827 {
828  struct ip6gre_info *ip6gre = link->l_info;
829 
830  IS_IP6GRE_LINK_ASSERT(link);
831 
832  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FLAGS);
833 
834  *flags = ip6gre->flags;
835 
836  return 0;
837 }
838 
839 /**
840  * Set IP6GRE tunnel fwmark
841  * @arg link Link object
842  * @arg fwmark fwmark
843  *
844  * @return 0 on success or a negative error code
845  */
846 int rtnl_link_ip6gre_set_fwmark(struct rtnl_link *link, uint32_t fwmark)
847 {
848  struct ip6gre_info *ip6gre = link->l_info;
849 
850  IS_IP6GRE_LINK_ASSERT(link);
851 
852  ip6gre->fwmark = fwmark;
853  ip6gre->ip6gre_mask |= IP6GRE_ATTR_FWMARK;
854 
855  return 0;
856 }
857 
858 /**
859  * Get IP6GRE tunnel fwmark
860  * @arg link Link object
861  * @arg fwmark addr to fill in with the fwmark
862  *
863  * @return 0 on success or a negative error code
864  */
865 int rtnl_link_ip6gre_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
866 {
867  struct ip6gre_info *ip6gre = link->l_info;
868 
869  IS_IP6GRE_LINK_ASSERT(link);
870 
871  HAS_IP6GRE_ATTR_ASSERT(ip6gre, IP6GRE_ATTR_FWMARK);
872 
873  *fwmark = ip6gre->fwmark;
874 
875  return 0;
876 }
877 
878 static void __init ip6gre_init(void)
879 {
880  rtnl_link_register_info(&ip6gre_info_ops);
881 }
882 
883 static void __exit ip6gre_exit(void)
884 {
885  rtnl_link_unregister_info(&ip6gre_info_ops);
886 }
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:846
int rtnl_link_ip6gre_set_flags(struct rtnl_link *link, uint32_t flags)
Set IP6GRE tunnel flags.
Definition: ip6gre.c:807
int rtnl_link_ip6gre_set_remote(struct rtnl_link *link, struct in6_addr *remote)
Set IP6GRE tunnel remote address.
Definition: ip6gre.c:651
int rtnl_link_ip6gre_set_ttl(struct rtnl_link *link, uint8_t ttl)
Set IP6GRE tunnel ttl.
Definition: ip6gre.c:690
int rtnl_link_ip6gre_get_oflags(struct rtnl_link *link, uint16_t *oflags)
Get IP6GRE tunnel oflags.
Definition: ip6gre.c:514
int rtnl_link_ip6gre_set_okey(struct rtnl_link *link, uint32_t okey)
Set IP6GRE tunnel set okey.
Definition: ip6gre.c:573
int rtnl_link_ip6gre_get_ttl(struct rtnl_link *link, uint8_t *ttl)
Set IP6GRE tunnel ttl.
Definition: ip6gre.c:709
int rtnl_link_ip6gre_set_iflags(struct rtnl_link *link, uint16_t iflags)
Set IP6GRE tunnel set iflags.
Definition: ip6gre.c:456
int rtnl_link_ip6gre_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
Get IP6GRE tunnel fwmark.
Definition: ip6gre.c:865
int rtnl_link_ip6gre_set_link(struct rtnl_link *link, uint32_t index)
Set IP6GRE tunnel interface index.
Definition: ip6gre.c:417
int rtnl_link_ip6gre_get_ikey(struct rtnl_link *link, uint32_t *ikey)
Get IP6GRE tunnel ikey.
Definition: ip6gre.c:553
int rtnl_link_ip6gre_get_iflags(struct rtnl_link *link, uint16_t *iflags)
Get IP6GRE tunnel iflags.
Definition: ip6gre.c:475
int rtnl_link_ip6gre_get_flowinfo(struct rtnl_link *link, uint32_t *flowinfo)
Get IP6GRE flowinfo.
Definition: ip6gre.c:787
int rtnl_link_ip6gre_set_flowinfo(struct rtnl_link *link, uint32_t flowinfo)
Set IP6GRE tunnel flowinfo.
Definition: ip6gre.c:768
int rtnl_link_ip6gre_set_encaplimit(struct rtnl_link *link, uint8_t encaplimit)
Set IP6GRE tunnel encap limit.
Definition: ip6gre.c:729
int rtnl_link_ip6gre_get_flags(struct rtnl_link *link, uint32_t *flags)
Get IP6GRE flags.
Definition: ip6gre.c:826
int rtnl_link_ip6gre_set_ikey(struct rtnl_link *link, uint32_t ikey)
Set IP6GRE tunnel set ikey.
Definition: ip6gre.c:534
int rtnl_link_ip6gre_set_local(struct rtnl_link *link, struct in6_addr *local)
Set IP6GRE tunnel local address.
Definition: ip6gre.c:612
int rtnl_link_ip6gre_get_link(struct rtnl_link *link, uint32_t *index)
Get IP6GRE tunnel interface index.
Definition: ip6gre.c:436
int rtnl_link_ip6gre_add(struct nl_sock *sk, const char *name)
Create a new IP6GRE tunnel device.
Definition: ip6gre.c:392
int rtnl_link_ip6gre_get_local(struct rtnl_link *link, struct in6_addr *local)
Get IP6GRE tunnel local address.
Definition: ip6gre.c:631
int rtnl_link_ip6gre_get_okey(struct rtnl_link *link, uint32_t *okey)
Get IP6GRE tunnel okey.
Definition: ip6gre.c:592
int rtnl_link_ip6gre_set_oflags(struct rtnl_link *link, uint16_t oflags)
Set IP6GRE tunnel set oflags.
Definition: ip6gre.c:495
int rtnl_link_ip6gre_get_encaplimit(struct rtnl_link *link, uint8_t *encaplimit)
Get IP6GRE tunnel encap limit.
Definition: ip6gre.c:748
int rtnl_link_is_ip6gre(struct rtnl_link *link)
Check if link is a IP6GRE link.
Definition: ip6gre.c:379
int rtnl_link_ip6gre_get_remote(struct rtnl_link *link, struct in6_addr *remote)
Get IP6GRE tunnel remote address.
Definition: ip6gre.c:670
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