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
39 struct ip6gre_info
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
ip6gre_alloc(struct rtnl_link * link)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
ip6gre_parse(struct rtnl_link * link,struct nlattr * data,struct nlattr * xstats)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
ip6gre_put_attrs(struct nl_msg * msg,struct rtnl_link * link)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
ip6gre_free(struct rtnl_link * link)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
ip6gre_dump_line(struct rtnl_link * link,struct nl_dump_params * p)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
ip6gre_dump_details(struct rtnl_link * link,struct nl_dump_params * p)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
ip6gre_clone(struct rtnl_link * dst,struct rtnl_link * src)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
rtnl_link_ip6gre_alloc(void)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 */
rtnl_link_is_ip6gre(struct rtnl_link * link)379 int rtnl_link_is_ip6gre(struct rtnl_link *link)
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 */
rtnl_link_ip6gre_add(struct nl_sock * sk,const char * name)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 */
rtnl_link_ip6gre_set_link(struct rtnl_link * link,uint32_t index)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 */
rtnl_link_ip6gre_get_link(struct rtnl_link * link,uint32_t * index)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 */
rtnl_link_ip6gre_set_iflags(struct rtnl_link * link,uint16_t iflags)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 */
rtnl_link_ip6gre_get_iflags(struct rtnl_link * link,uint16_t * iflags)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 */
rtnl_link_ip6gre_set_oflags(struct rtnl_link * link,uint16_t oflags)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 */
rtnl_link_ip6gre_get_oflags(struct rtnl_link * link,uint16_t * oflags)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 */
rtnl_link_ip6gre_set_ikey(struct rtnl_link * link,uint32_t ikey)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 */
rtnl_link_ip6gre_get_ikey(struct rtnl_link * link,uint32_t * ikey)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 */
rtnl_link_ip6gre_set_okey(struct rtnl_link * link,uint32_t okey)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 */
rtnl_link_ip6gre_get_okey(struct rtnl_link * link,uint32_t * okey)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 */
rtnl_link_ip6gre_set_local(struct rtnl_link * link,struct in6_addr * local)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 */
rtnl_link_ip6gre_get_local(struct rtnl_link * link,struct in6_addr * local)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 */
rtnl_link_ip6gre_set_remote(struct rtnl_link * link,struct in6_addr * remote)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 */
rtnl_link_ip6gre_get_remote(struct rtnl_link * link,struct in6_addr * remote)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 */
rtnl_link_ip6gre_set_ttl(struct rtnl_link * link,uint8_t ttl)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 */
rtnl_link_ip6gre_get_ttl(struct rtnl_link * link,uint8_t * ttl)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 */
rtnl_link_ip6gre_set_encaplimit(struct rtnl_link * link,uint8_t encaplimit)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 */
rtnl_link_ip6gre_get_encaplimit(struct rtnl_link * link,uint8_t * encaplimit)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 */
rtnl_link_ip6gre_set_flowinfo(struct rtnl_link * link,uint32_t flowinfo)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 */
rtnl_link_ip6gre_get_flowinfo(struct rtnl_link * link,uint32_t * flowinfo)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 */
rtnl_link_ip6gre_set_flags(struct rtnl_link * link,uint32_t flags)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 */
rtnl_link_ip6gre_get_flags(struct rtnl_link * link,uint32_t * flags)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 */
rtnl_link_ip6gre_set_fwmark(struct rtnl_link * link,uint32_t fwmark)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 */
rtnl_link_ip6gre_get_fwmark(struct rtnl_link * link,uint32_t * fwmark)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
ip6gre_init(void)878 static void __init ip6gre_init(void)
879 {
880 rtnl_link_register_info(&ip6gre_info_ops);
881 }
882
ip6gre_exit(void)883 static void __exit ip6gre_exit(void)
884 {
885 rtnl_link_unregister_info(&ip6gre_info_ops);
886 }
887