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