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