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