libnl  3.2.25
sit.c
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-private/route/link/api.h>
32 #include <linux/if_tunnel.h>
33 
34 #define SIT_ATTR_LINK (1 << 0)
35 #define SIT_ATTR_LOCAL (1 << 1)
36 #define SIT_ATTR_REMOTE (1 << 2)
37 #define SIT_ATTR_TTL (1 << 3)
38 #define SIT_ATTR_TOS (1 << 4)
39 #define SIT_ATTR_PMTUDISC (1 << 5)
40 #define SIT_ATTR_FLAGS (1 << 6)
41 #define SIT_ATTR_PROTO (1 << 7)
42 
43 struct sit_info
44 {
45  uint8_t ttl;
46  uint8_t tos;
47  uint8_t pmtudisc;
48  uint8_t proto;
49  uint16_t flags;
50  uint32_t link;
51  uint32_t local;
52  uint32_t remote;
53  uint32_t sit_mask;
54 };
55 
56 static struct nla_policy sit_policy[IFLA_IPTUN_MAX + 1] = {
57  [IFLA_IPTUN_LINK] = { .type = NLA_U32 },
58  [IFLA_IPTUN_LOCAL] = { .type = NLA_U32 },
59  [IFLA_IPTUN_REMOTE] = { .type = NLA_U32 },
60  [IFLA_IPTUN_TTL] = { .type = NLA_U8 },
61  [IFLA_IPTUN_TOS] = { .type = NLA_U8 },
62  [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 },
63  [IFLA_IPTUN_FLAGS] = { .type = NLA_U16 },
64  [IFLA_IPTUN_PROTO] = { .type = NLA_U8 },
65 };
66 
67 static int sit_alloc(struct rtnl_link *link)
68 {
69  struct sit_info *sit;
70 
71  sit = calloc(1, sizeof(*sit));
72  if (!sit)
73  return -NLE_NOMEM;
74 
75  link->l_info = sit;
76 
77  return 0;
78 }
79 
80 static int sit_parse(struct rtnl_link *link, struct nlattr *data,
81  struct nlattr *xstats)
82 {
83  struct nlattr *tb[IFLA_IPTUN_MAX + 1];
84  struct sit_info *sit;
85  int err;
86 
87  NL_DBG(3, "Parsing SIT link info");
88 
89  err = nla_parse_nested(tb, IFLA_IPTUN_MAX, data, sit_policy);
90  if (err < 0)
91  goto errout;
92 
93  err = sit_alloc(link);
94  if (err < 0)
95  goto errout;
96 
97  sit = link->l_info;
98 
99  if (tb[IFLA_IPTUN_LINK]) {
100  sit->link = nla_get_u32(tb[IFLA_IPTUN_LINK]);
101  sit->sit_mask |= SIT_ATTR_LINK;
102  }
103 
104  if (tb[IFLA_IPTUN_LOCAL]) {
105  sit->local = nla_get_u32(tb[IFLA_IPTUN_LOCAL]);
106  sit->sit_mask |= SIT_ATTR_LOCAL;
107  }
108 
109  if (tb[IFLA_IPTUN_REMOTE]) {
110  sit->remote = nla_get_u32(tb[IFLA_IPTUN_REMOTE]);
111  sit->sit_mask |= SIT_ATTR_REMOTE;
112  }
113 
114  if (tb[IFLA_IPTUN_TTL]) {
115  sit->ttl = nla_get_u8(tb[IFLA_IPTUN_TTL]);
116  sit->sit_mask |= SIT_ATTR_TTL;
117  }
118 
119  if (tb[IFLA_IPTUN_TOS]) {
120  sit->tos = nla_get_u8(tb[IFLA_IPTUN_TOS]);
121  sit->sit_mask |= SIT_ATTR_TOS;
122  }
123 
124  if (tb[IFLA_IPTUN_PMTUDISC]) {
125  sit->pmtudisc = nla_get_u8(tb[IFLA_IPTUN_PMTUDISC]);
126  sit->sit_mask |= SIT_ATTR_PMTUDISC;
127  }
128 
129  if (tb[IFLA_IPTUN_FLAGS]) {
130  sit->flags = nla_get_u16(tb[IFLA_IPTUN_FLAGS]);
131  sit->sit_mask |= SIT_ATTR_FLAGS;
132  }
133 
134  if (tb[IFLA_IPTUN_PROTO]) {
135  sit->proto = nla_get_u8(tb[IFLA_IPTUN_PROTO]);
136  sit->sit_mask |= SIT_ATTR_PROTO;
137  }
138 
139  err = 0;
140 
141  errout:
142  return err;
143 }
144 
145 static int sit_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
146 {
147  struct sit_info *sit = link->l_info;
148  struct nlattr *data;
149 
150  data = nla_nest_start(msg, IFLA_INFO_DATA);
151  if (!data)
152  return -NLE_MSGSIZE;
153 
154  if (sit->sit_mask & SIT_ATTR_LINK)
155  NLA_PUT_U32(msg, IFLA_IPTUN_LINK, sit->link);
156 
157  if (sit->sit_mask & SIT_ATTR_LOCAL)
158  NLA_PUT_U32(msg, IFLA_IPTUN_LOCAL, sit->local);
159 
160  if (sit->sit_mask & SIT_ATTR_REMOTE)
161  NLA_PUT_U32(msg, IFLA_IPTUN_REMOTE, sit->remote);
162 
163  if (sit->sit_mask & SIT_ATTR_TTL)
164  NLA_PUT_U8(msg, IFLA_IPTUN_TTL, sit->ttl);
165 
166  if (sit->sit_mask & SIT_ATTR_TOS)
167  NLA_PUT_U8(msg, IFLA_IPTUN_TOS, sit->tos);
168 
169  if (sit->sit_mask & SIT_ATTR_PMTUDISC)
170  NLA_PUT_U8(msg, IFLA_IPTUN_PMTUDISC, sit->pmtudisc);
171 
172  if (sit->sit_mask & SIT_ATTR_FLAGS)
173  NLA_PUT_U16(msg, IFLA_IPTUN_FLAGS, sit->flags);
174 
175  if (sit->sit_mask & SIT_ATTR_PROTO)
176  NLA_PUT_U8(msg, IFLA_IPTUN_PROTO, sit->proto);
177 
178  nla_nest_end(msg, data);
179 
180 nla_put_failure:
181 
182  return 0;
183 }
184 
185 static void sit_free(struct rtnl_link *link)
186 {
187  struct sit_info *sit = link->l_info;
188 
189  free(sit);
190  link->l_info = NULL;
191 }
192 
193 static void sit_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
194 {
195  nl_dump(p, "sit : %s", link->l_name);
196 }
197 
198 static void sit_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
199 {
200  struct sit_info *sit = link->l_info;
201  char *name, addr[INET_ADDRSTRLEN];
202 
203  if (sit->sit_mask & SIT_ATTR_LINK) {
204  nl_dump(p, " link ");
205  name = rtnl_link_get_name(link);
206  if (name)
207  nl_dump_line(p, "%s\n", name);
208  else
209  nl_dump_line(p, "%u\n", sit->link);
210  }
211 
212  if (sit->sit_mask & SIT_ATTR_LOCAL) {
213  nl_dump(p, " local ");
214  if(inet_ntop(AF_INET, &sit->local, addr, sizeof(addr)))
215  nl_dump_line(p, "%s\n", addr);
216  else
217  nl_dump_line(p, "%#x\n", ntohs(sit->local));
218  }
219 
220  if (sit->sit_mask & SIT_ATTR_REMOTE) {
221  nl_dump(p, " remote ");
222  if(inet_ntop(AF_INET, &sit->remote, addr, sizeof(addr)))
223  nl_dump_line(p, "%s\n", addr);
224  else
225  nl_dump_line(p, "%#x\n", ntohs(sit->remote));
226  }
227 
228  if (sit->sit_mask & SIT_ATTR_TTL) {
229  nl_dump(p, " ttl ");
230  nl_dump_line(p, "%u\n", sit->ttl);
231  }
232 
233  if (sit->sit_mask & SIT_ATTR_TOS) {
234  nl_dump(p, " tos ");
235  nl_dump_line(p, "%u\n", sit->tos);
236  }
237 
238  if (sit->sit_mask & SIT_ATTR_FLAGS) {
239  nl_dump(p, " flags ");
240  nl_dump_line(p, " (%x)\n", sit->flags);
241  }
242 
243  if (sit->sit_mask & SIT_ATTR_PROTO) {
244  nl_dump(p, " proto ");
245  nl_dump_line(p, " (%x)\n", sit->proto);
246  }
247 }
248 
249 static int sit_clone(struct rtnl_link *dst, struct rtnl_link *src)
250 {
251  struct sit_info *sit_dst, *sit_src = src->l_info;
252  int err;
253 
254  dst->l_info = NULL;
255 
256  err = rtnl_link_set_type(dst, "sit");
257  if (err < 0)
258  return err;
259 
260  sit_dst = dst->l_info;
261 
262  if (!sit_dst || !sit_src)
263  return -NLE_NOMEM;
264 
265  memcpy(sit_dst, sit_src, sizeof(struct sit_info));
266 
267  return 0;
268 }
269 
270 static struct rtnl_link_info_ops sit_info_ops = {
271  .io_name = "sit",
272  .io_alloc = sit_alloc,
273  .io_parse = sit_parse,
274  .io_dump = {
275  [NL_DUMP_LINE] = sit_dump_line,
276  [NL_DUMP_DETAILS] = sit_dump_details,
277  },
278  .io_clone = sit_clone,
279  .io_put_attrs = sit_put_attrs,
280  .io_free = sit_free,
281 };
282 
283 #define IS_SIT_LINK_ASSERT(link) \
284  if ((link)->l_info_ops != &sit_info_ops) { \
285  APPBUG("Link is not a sit link. set type \"sit\" first."); \
286  return -NLE_OPNOTSUPP; \
287  }
288 
289 struct rtnl_link *rtnl_link_sit_alloc(void)
290 {
291  struct rtnl_link *link;
292  int err;
293 
294  link = rtnl_link_alloc();
295  if (!link)
296  return NULL;
297 
298  err = rtnl_link_set_type(link, "sit");
299  if (err < 0) {
300  rtnl_link_put(link);
301  return NULL;
302  }
303 
304  return link;
305 }
306 
307 /**
308  * Check if link is a SIT link
309  * @arg link Link object
310  *
311  * @return True if link is a SIT link, otherwise false is returned.
312  */
313 int rtnl_link_is_sit(struct rtnl_link *link)
314 {
315  return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "sit");
316 }
317 
318 /**
319  * Create a new sit tunnel device
320  * @arg sock netlink socket
321  * @arg name name of the tunnel device
322  *
323  * Creates a new sit tunnel device in the kernel
324  * @return 0 on success or a negative error code
325  */
326 int rtnl_link_sit_add(struct nl_sock *sk, const char *name)
327 {
328  struct rtnl_link *link;
329  int err;
330 
331  link = rtnl_link_sit_alloc();
332  if (!link)
333  return -NLE_NOMEM;
334 
335  if(name)
336  rtnl_link_set_name(link, name);
337 
338  err = rtnl_link_add(sk, link, NLM_F_CREATE);
339  rtnl_link_put(link);
340 
341  return err;
342 }
343 
344 /**
345  * Set SIT tunnel interface index
346  * @arg link Link object
347  * @arg index interface index
348  *
349  * @return 0 on success or a negative error code
350  */
351 int rtnl_link_sit_set_link(struct rtnl_link *link, uint32_t index)
352 {
353  struct sit_info *sit = link->l_info;
354 
355  IS_SIT_LINK_ASSERT(link);
356 
357  sit->link = index;
358  sit->sit_mask |= SIT_ATTR_LINK;
359 
360  return 0;
361 }
362 
363 /**
364  * Get SIT tunnel interface index
365  * @arg link Link object
366  *
367  * @return interface index value
368  */
369 uint32_t rtnl_link_sit_get_link(struct rtnl_link *link)
370 {
371  struct sit_info *sit = link->l_info;
372 
373  IS_SIT_LINK_ASSERT(link);
374 
375  return sit->link;
376 }
377 
378 /**
379  * Set SIT tunnel local address
380  * @arg link Link object
381  * @arg addr local address
382  *
383  * @return 0 on success or a negative error code
384  */
385 int rtnl_link_sit_set_local(struct rtnl_link *link, uint32_t addr)
386 {
387  struct sit_info *sit = link->l_info;
388 
389  IS_SIT_LINK_ASSERT(link);
390 
391  sit->local = addr;
392  sit->sit_mask |= SIT_ATTR_LOCAL;
393 
394  return 0;
395 }
396 
397 /**
398  * Get SIT tunnel local address
399  * @arg link Link object
400  *
401  * @return local address value
402  */
403 uint32_t rtnl_link_sit_get_local(struct rtnl_link *link)
404 {
405  struct sit_info *sit = link->l_info;
406 
407  IS_SIT_LINK_ASSERT(link);
408 
409  return sit->local;
410 }
411 
412 /**
413  * Set SIT tunnel remote address
414  * @arg link Link object
415  * @arg remote remote address
416  *
417  * @return 0 on success or a negative error code
418  */
419 int rtnl_link_sit_set_remote(struct rtnl_link *link, uint32_t addr)
420 {
421  struct sit_info *sit = link->l_info;
422 
423  IS_SIT_LINK_ASSERT(link);
424 
425  sit->remote = addr;
426  sit->sit_mask |= SIT_ATTR_REMOTE;
427 
428  return 0;
429 }
430 
431 /**
432  * Get SIT tunnel remote address
433  * @arg link Link object
434  *
435  * @return remote address
436  */
437 uint32_t rtnl_link_sit_get_remote(struct rtnl_link *link)
438 {
439  struct sit_info *sit = link->l_info;
440 
441  IS_SIT_LINK_ASSERT(link);
442 
443  return sit->remote;
444 }
445 
446 /**
447  * Set SIT tunnel ttl
448  * @arg link Link object
449  * @arg ttl tunnel ttl
450  *
451  * @return 0 on success or a negative error code
452  */
453 int rtnl_link_sit_set_ttl(struct rtnl_link *link, uint8_t ttl)
454 {
455  struct sit_info *sit = link->l_info;
456 
457  IS_SIT_LINK_ASSERT(link);
458 
459  sit->ttl = ttl;
460  sit->sit_mask |= SIT_ATTR_TTL;
461 
462  return 0;
463 }
464 
465 /**
466  * Get SIT tunnel ttl
467  * @arg link Link object
468  *
469  * @return ttl value
470  */
471 uint8_t rtnl_link_sit_get_ttl(struct rtnl_link *link)
472 {
473  struct sit_info *sit = link->l_info;
474 
475  IS_SIT_LINK_ASSERT(link);
476 
477  return sit->ttl;
478 }
479 
480 /**
481  * Set SIT tunnel tos
482  * @arg link Link object
483  * @arg tos tunnel tos
484  *
485  * @return 0 on success or a negative error code
486  */
487 int rtnl_link_sit_set_tos(struct rtnl_link *link, uint8_t tos)
488 {
489  struct sit_info *sit = link->l_info;
490 
491  IS_SIT_LINK_ASSERT(link);
492 
493  sit->tos = tos;
494  sit->sit_mask |= SIT_ATTR_TOS;
495 
496  return 0;
497 }
498 
499 /**
500  * Get SIT tunnel tos
501  * @arg link Link object
502  *
503  * @return tos value
504  */
505 uint8_t rtnl_link_sit_get_tos(struct rtnl_link *link)
506 {
507  struct sit_info *sit = link->l_info;
508 
509  IS_SIT_LINK_ASSERT(link);
510 
511  return sit->tos;
512 }
513 
514 /**
515  * Set SIT tunnel path MTU discovery
516  * @arg link Link object
517  * @arg pmtudisc path MTU discovery
518  *
519  * @return 0 on success or a negative error code
520  */
521 int rtnl_link_sit_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc)
522 {
523  struct sit_info *sit = link->l_info;
524 
525  IS_SIT_LINK_ASSERT(link);
526 
527  sit->pmtudisc = pmtudisc;
528  sit->sit_mask |= SIT_ATTR_PMTUDISC;
529 
530  return 0;
531 }
532 
533 /**
534  * Get SIT path MTU discovery
535  * @arg link Link object
536  *
537  * @return pmtudisc value
538  */
540 {
541  struct sit_info *sit = link->l_info;
542 
543  IS_SIT_LINK_ASSERT(link);
544 
545  return sit->pmtudisc;
546 }
547 
548 /**
549  * Set SIT tunnel flags
550  * @arg link Link object
551  * @arg flags tunnel flags
552  *
553  * @return 0 on success or a negative error code
554  */
555 int rtnl_link_sit_set_flags(struct rtnl_link *link, uint16_t flags)
556 {
557  struct sit_info *sit = link->l_info;
558 
559  IS_SIT_LINK_ASSERT(link);
560 
561  sit->flags = flags;
562  sit->sit_mask |= SIT_ATTR_FLAGS;
563 
564  return 0;
565 }
566 
567 /**
568  * Get SIT path flags
569  * @arg link Link object
570  *
571  * @return flags value
572  */
573 uint16_t rtnl_link_sit_get_flags(struct rtnl_link *link)
574 {
575  struct sit_info *sit = link->l_info;
576 
577  IS_SIT_LINK_ASSERT(link);
578 
579  return sit->flags;
580 }
581 
582 /**
583  * Set SIT tunnel proto
584  * @arg link Link object
585  * @arg proto tunnel proto
586  *
587  * @return 0 on success or a negative error code
588  */
589 int rtnl_link_sit_set_proto(struct rtnl_link *link, uint8_t proto)
590 {
591  struct sit_info *sit = link->l_info;
592 
593  IS_SIT_LINK_ASSERT(link);
594 
595  sit->proto = proto;
596  sit->sit_mask |= SIT_ATTR_PROTO;
597 
598  return 0;
599 }
600 
601 /**
602  * Get SIT proto
603  * @arg link Link object
604  *
605  * @return proto value
606  */
607 uint8_t rtnl_link_sit_get_proto(struct rtnl_link *link)
608 {
609  struct sit_info *sit = link->l_info;
610 
611  IS_SIT_LINK_ASSERT(link);
612 
613  return sit->proto;
614 }
615 
616 static void __init sit_init(void)
617 {
618  rtnl_link_register_info(&sit_info_ops);
619 }
620 
621 static void __exit sit_exit(void)
622 {
623  rtnl_link_unregister_info(&sit_info_ops);
624 }
Definition: sit.c:43
Dump object briefly on one line.
Definition: types.h:22
uint16_t nla_get_u16(struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:599
8 bit integer
Definition: attr.h:39
int rtnl_link_sit_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc)
Set SIT tunnel path MTU discovery.
Definition: sit.c:521
Attribute validation policy.
Definition: attr.h:60
uint16_t rtnl_link_sit_get_flags(struct rtnl_link *link)
Get SIT path flags.
Definition: sit.c:573
int rtnl_link_sit_set_proto(struct rtnl_link *link, uint8_t proto)
Set SIT tunnel proto.
Definition: sit.c:589
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition: attr.h:171
Dump all attributes but no statistics.
Definition: types.h:23
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:811
int rtnl_link_sit_set_remote(struct rtnl_link *link, uint32_t addr)
Set SIT tunnel remote address.
Definition: sit.c:419
uint32_t rtnl_link_sit_get_remote(struct rtnl_link *link)
Get SIT tunnel remote address.
Definition: sit.c:437
int rtnl_link_sit_set_ttl(struct rtnl_link *link, uint8_t ttl)
Set SIT tunnel ttl.
Definition: sit.c:453
uint8_t rtnl_link_sit_get_ttl(struct rtnl_link *link)
Get SIT tunnel ttl.
Definition: sit.c:471
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, struct nla_policy *policy)
Create attribute index based on nested attribute.
Definition: attr.c:885
uint8_t nla_get_u8(struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition: attr.c:574
16 bit integer
Definition: attr.h:40
uint8_t rtnl_link_sit_get_proto(struct rtnl_link *link)
Get SIT proto.
Definition: sit.c:607
int rtnl_link_sit_add(struct nl_sock *sk, const char *name)
Create a new sit tunnel device.
Definition: sit.c:326
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:189
uint32_t rtnl_link_sit_get_local(struct rtnl_link *link)
Get SIT tunnel local address.
Definition: sit.c:403
int rtnl_link_sit_set_link(struct rtnl_link *link, uint32_t index)
Set SIT tunnel interface index.
Definition: sit.c:351
uint8_t rtnl_link_sit_get_pmtudisc(struct rtnl_link *link)
Get SIT path MTU discovery.
Definition: sit.c:539
uint8_t rtnl_link_sit_get_tos(struct rtnl_link *link)
Get SIT tunnel tos.
Definition: sit.c:505
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:62
32 bit integer
Definition: attr.h:41
Dumping parameters.
Definition: types.h:33
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition: attr.h:180
int rtnl_link_sit_set_tos(struct rtnl_link *link, uint8_t tos)
Set SIT tunnel tos.
Definition: sit.c:487
uint32_t rtnl_link_sit_get_link(struct rtnl_link *link)
Get SIT tunnel interface index.
Definition: sit.c:369
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:915
uint32_t nla_get_u32(struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:624
int rtnl_link_sit_set_local(struct rtnl_link *link, uint32_t addr)
Set SIT tunnel local address.
Definition: sit.c:385
int rtnl_link_is_sit(struct rtnl_link *link)
Check if link is a SIT link.
Definition: sit.c:313
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:789
int rtnl_link_sit_set_flags(struct rtnl_link *link, uint16_t flags)
Set SIT tunnel flags.
Definition: sit.c:555