xref: /aosp_15_r20/external/libnl/lib/route/link/ip6gre.c (revision 4dc78e53d49367fa8e61b07018507c90983a077d)
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