• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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