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