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