libnl  3.2.27
ipip.c
1 /*
2  * lib/route/link/ipip.c IPIP 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 ipip IPIP
15  * ipip link module
16  *
17  * @details
18  * \b Link Type Name: "ipip"
19  *
20  * @route_doc{link_ipip, IPIP 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 IPIP_ATTR_LINK (1 << 0)
35 #define IPIP_ATTR_LOCAL (1 << 1)
36 #define IPIP_ATTR_REMOTE (1 << 2)
37 #define IPIP_ATTR_TTL (1 << 3)
38 #define IPIP_ATTR_TOS (1 << 4)
39 #define IPIP_ATTR_PMTUDISC (1 << 5)
40 
41 struct ipip_info
42 {
43  uint8_t ttl;
44  uint8_t tos;
45  uint8_t pmtudisc;
46  uint32_t link;
47  uint32_t local;
48  uint32_t remote;
49  uint32_t ipip_mask;
50 };
51 
52 static struct nla_policy ipip_policy[IFLA_IPTUN_MAX + 1] = {
53  [IFLA_IPTUN_LINK] = { .type = NLA_U32 },
54  [IFLA_IPTUN_LOCAL] = { .type = NLA_U32 },
55  [IFLA_IPTUN_REMOTE] = { .type = NLA_U32 },
56  [IFLA_IPTUN_TTL] = { .type = NLA_U8 },
57  [IFLA_IPTUN_TOS] = { .type = NLA_U8 },
58  [IFLA_IPTUN_PMTUDISC] = { .type = NLA_U8 },
59 };
60 
61 static int ipip_alloc(struct rtnl_link *link)
62 {
63  struct ipip_info *ipip;
64 
65  if (link->l_info)
66  memset(link->l_info, 0, sizeof(*ipip));
67  else {
68  ipip = calloc(1, sizeof(*ipip));
69  if (!ipip)
70  return -NLE_NOMEM;
71 
72  link->l_info = ipip;
73  }
74 
75  return 0;
76 }
77 
78 static int ipip_parse(struct rtnl_link *link, struct nlattr *data,
79  struct nlattr *xstats)
80 {
81  struct nlattr *tb[IFLA_IPTUN_MAX + 1];
82  struct ipip_info *ipip;
83  int err;
84 
85  NL_DBG(3, "Parsing IPIP link info\n");
86 
87  err = nla_parse_nested(tb, IFLA_IPTUN_MAX, data, ipip_policy);
88  if (err < 0)
89  goto errout;
90 
91  err = ipip_alloc(link);
92  if (err < 0)
93  goto errout;
94 
95  ipip = link->l_info;
96 
97  if (tb[IFLA_IPTUN_LINK]) {
98  ipip->link = nla_get_u32(tb[IFLA_IPTUN_LINK]);
99  ipip->ipip_mask |= IPIP_ATTR_LINK;
100  }
101 
102  if (tb[IFLA_IPTUN_LOCAL]) {
103  ipip->local = nla_get_u32(tb[IFLA_IPTUN_LOCAL]);
104  ipip->ipip_mask |= IPIP_ATTR_LOCAL;
105  }
106 
107  if (tb[IFLA_IPTUN_REMOTE]) {
108  ipip->remote = nla_get_u32(tb[IFLA_IPTUN_REMOTE]);
109  ipip->ipip_mask |= IPIP_ATTR_REMOTE;
110  }
111 
112  if (tb[IFLA_IPTUN_TTL]) {
113  ipip->ttl = nla_get_u8(tb[IFLA_IPTUN_TTL]);
114  ipip->ipip_mask |= IPIP_ATTR_TTL;
115  }
116 
117  if (tb[IFLA_IPTUN_TOS]) {
118  ipip->tos = nla_get_u8(tb[IFLA_IPTUN_TOS]);
119  ipip->ipip_mask |= IPIP_ATTR_TOS;
120  }
121 
122  if (tb[IFLA_IPTUN_PMTUDISC]) {
123  ipip->pmtudisc = nla_get_u8(tb[IFLA_IPTUN_PMTUDISC]);
124  ipip->ipip_mask |= IPIP_ATTR_PMTUDISC;
125  }
126 
127  err = 0;
128 
129 errout:
130  return err;
131 }
132 
133 static int ipip_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
134 {
135  struct ipip_info *ipip = link->l_info;
136  struct nlattr *data;
137 
138  data = nla_nest_start(msg, IFLA_INFO_DATA);
139  if (!data)
140  return -NLE_MSGSIZE;
141 
142  if (ipip->ipip_mask & IPIP_ATTR_LINK)
143  NLA_PUT_U32(msg, IFLA_IPTUN_LINK, ipip->link);
144 
145  if (ipip->ipip_mask & IPIP_ATTR_LOCAL)
146  NLA_PUT_U32(msg, IFLA_IPTUN_LOCAL, ipip->local);
147 
148  if (ipip->ipip_mask & IPIP_ATTR_REMOTE)
149  NLA_PUT_U32(msg, IFLA_IPTUN_REMOTE, ipip->remote);
150 
151  if (ipip->ipip_mask & IPIP_ATTR_TTL)
152  NLA_PUT_U8(msg, IFLA_IPTUN_TTL, ipip->ttl);
153 
154  if (ipip->ipip_mask & IPIP_ATTR_TOS)
155  NLA_PUT_U8(msg, IFLA_IPTUN_TOS, ipip->tos);
156 
157  if (ipip->ipip_mask & IPIP_ATTR_PMTUDISC)
158  NLA_PUT_U8(msg, IFLA_IPTUN_PMTUDISC, ipip->pmtudisc);
159 
160  nla_nest_end(msg, data);
161 
162 nla_put_failure:
163  return 0;
164 }
165 
166 static void ipip_free(struct rtnl_link *link)
167 {
168  struct ipip_info *ipip = link->l_info;
169 
170  free(ipip);
171  link->l_info = NULL;
172 }
173 
174 static void ipip_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
175 {
176  nl_dump(p, "ipip : %s", link->l_name);
177 }
178 
179 static void ipip_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
180 {
181  struct ipip_info *ipip = link->l_info;
182  char *name, addr[INET_ADDRSTRLEN];
183 
184  if (ipip->ipip_mask & IPIP_ATTR_LINK) {
185  nl_dump(p, " link ");
186  name = rtnl_link_get_name(link);
187  if (name)
188  nl_dump_line(p, "%s\n", name);
189  else
190  nl_dump_line(p, "%u\n", ipip->link);
191  }
192 
193  if (ipip->ipip_mask & IPIP_ATTR_LOCAL) {
194  nl_dump(p, " local ");
195  if(inet_ntop(AF_INET, &ipip->local, addr, sizeof(addr)))
196  nl_dump_line(p, "%s\n", addr);
197  else
198  nl_dump_line(p, "%#x\n", ntohs(ipip->local));
199  }
200 
201  if (ipip->ipip_mask & IPIP_ATTR_REMOTE) {
202  nl_dump(p, " remote ");
203  if(inet_ntop(AF_INET, &ipip->remote, addr, sizeof(addr)))
204  nl_dump_line(p, "%s\n", addr);
205  else
206  nl_dump_line(p, "%#x\n", ntohs(ipip->remote));
207  }
208 
209  if (ipip->ipip_mask & IPIP_ATTR_TTL) {
210  nl_dump(p, " ttl ");
211  nl_dump_line(p, "%u\n", ipip->ttl);
212  }
213 
214  if (ipip->ipip_mask & IPIP_ATTR_TOS) {
215  nl_dump(p, " tos ");
216  nl_dump_line(p, "%u\n", ipip->tos);
217  }
218 
219  if (ipip->ipip_mask & IPIP_ATTR_PMTUDISC) {
220  nl_dump(p, " pmtudisc ");
221  nl_dump_line(p, "enabled (%#x)\n", ipip->pmtudisc);
222  }
223 }
224 
225 static int ipip_clone(struct rtnl_link *dst, struct rtnl_link *src)
226 {
227  struct ipip_info *ipip_dst, *ipip_src = src->l_info;
228  int err;
229 
230  dst->l_info = NULL;
231 
232  err = rtnl_link_set_type(dst, "ipip");
233  if (err < 0)
234  return err;
235 
236  ipip_dst = dst->l_info;
237 
238  if (!ipip_dst || !ipip_src)
239  BUG();
240 
241  memcpy(ipip_dst, ipip_src, sizeof(struct ipip_info));
242 
243  return 0;
244 }
245 
246 static struct rtnl_link_info_ops ipip_info_ops = {
247  .io_name = "ipip",
248  .io_alloc = ipip_alloc,
249  .io_parse = ipip_parse,
250  .io_dump = {
251  [NL_DUMP_LINE] = ipip_dump_line,
252  [NL_DUMP_DETAILS] = ipip_dump_details,
253  },
254  .io_clone = ipip_clone,
255  .io_put_attrs = ipip_put_attrs,
256  .io_free = ipip_free,
257 };
258 
259 #define IS_IPIP_LINK_ASSERT(link) \
260  if ((link)->l_info_ops != &ipip_info_ops) { \
261  APPBUG("Link is not a ipip link. set type \"ipip\" first."); \
262  return -NLE_OPNOTSUPP; \
263  }
264 
265 struct rtnl_link *rtnl_link_ipip_alloc(void)
266 {
267  struct rtnl_link *link;
268  int err;
269 
270  link = rtnl_link_alloc();
271  if (!link)
272  return NULL;
273 
274  err = rtnl_link_set_type(link, "ipip");
275  if (err < 0) {
276  rtnl_link_put(link);
277  return NULL;
278  }
279 
280  return link;
281 }
282 
283 /**
284  * Check if link is a IPIP link
285  * @arg link Link object
286  *
287  * @return True if link is a IPIP link, otherwise false is returned.
288  */
289 int rtnl_link_is_ipip(struct rtnl_link *link)
290 {
291  return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "ipip");
292 }
293 
294 /**
295  * Create a new ipip tunnel device
296  * @arg sock netlink socket
297  * @arg name name of the tunnel deviceL
298  *
299  * Creates a new ipip tunnel device in the kernel
300  * @return 0 on success or a negative error code
301  */
302 int rtnl_link_ipip_add(struct nl_sock *sk, const char *name)
303 {
304  struct rtnl_link *link;
305  int err;
306 
307  link = rtnl_link_ipip_alloc();
308  if (!link)
309  return -NLE_NOMEM;
310 
311  if(name)
312  rtnl_link_set_name(link, name);
313 
314  err = rtnl_link_add(sk, link, NLM_F_CREATE);
315  rtnl_link_put(link);
316 
317  return err;
318 }
319 
320 /**
321  * Set IPIP tunnel interface index
322  * @arg link Link object
323  * @arg index interface index
324  *
325  * @return 0 on success or a negative error code
326  */
327 int rtnl_link_ipip_set_link(struct rtnl_link *link, uint32_t index)
328 {
329  struct ipip_info *ipip = link->l_info;
330 
331  IS_IPIP_LINK_ASSERT(link);
332 
333  ipip->link = index;
334  ipip->ipip_mask |= IPIP_ATTR_LINK;
335 
336  return 0;
337 }
338 
339 /**
340  * Get IPIP tunnel interface index
341  * @arg link Link object
342  *
343  * @return interface index value
344  */
345 uint32_t rtnl_link_ipip_get_link(struct rtnl_link *link)
346 {
347  struct ipip_info *ipip = link->l_info;
348 
349  IS_IPIP_LINK_ASSERT(link);
350 
351  return ipip->link;
352 }
353 
354 /**
355  * Set IPIP tunnel local address
356  * @arg link Link object
357  * @arg addr local address
358  *
359  * @return 0 on success or a negative error code
360  */
361 int rtnl_link_ipip_set_local(struct rtnl_link *link, uint32_t addr)
362 {
363  struct ipip_info *ipip = link->l_info;
364 
365  IS_IPIP_LINK_ASSERT(link);
366 
367  ipip->local = addr;
368  ipip->ipip_mask |= IPIP_ATTR_LOCAL;
369 
370  return 0;
371 }
372 
373 /**
374  * Get IPIP tunnel local address
375  * @arg link Link object
376  *
377  * @return local address value
378  */
379 uint32_t rtnl_link_ipip_get_local(struct rtnl_link *link)
380 {
381  struct ipip_info *ipip = link->l_info;
382 
383  IS_IPIP_LINK_ASSERT(link);
384 
385  return ipip->local;
386 }
387 
388 /**
389  * Set IPIP tunnel remote address
390  * @arg link Link object
391  * @arg remote remote address
392  *
393  * @return 0 on success or a negative error code
394  */
395 int rtnl_link_ipip_set_remote(struct rtnl_link *link, uint32_t addr)
396 {
397  struct ipip_info *ipip = link->l_info;
398 
399  IS_IPIP_LINK_ASSERT(link);
400 
401  ipip->remote = addr;
402  ipip->ipip_mask |= IPIP_ATTR_REMOTE;
403 
404  return 0;
405 }
406 
407 /**
408  * Get IPIP tunnel remote address
409  * @arg link Link object
410  *
411  * @return remote address
412  */
413 uint32_t rtnl_link_ipip_get_remote(struct rtnl_link *link)
414 {
415  struct ipip_info *ipip = link->l_info;
416 
417  IS_IPIP_LINK_ASSERT(link);
418 
419  return ipip->remote;
420 }
421 
422 /**
423  * Set IPIP tunnel ttl
424  * @arg link Link object
425  * @arg ttl tunnel ttl
426  *
427  * @return 0 on success or a negative error code
428  */
429 int rtnl_link_ipip_set_ttl(struct rtnl_link *link, uint8_t ttl)
430 {
431  struct ipip_info *ipip = link->l_info;
432 
433  IS_IPIP_LINK_ASSERT(link);
434 
435  ipip->ttl = ttl;
436  ipip->ipip_mask |= IPIP_ATTR_TTL;
437 
438  return 0;
439 }
440 
441 /**
442  * Get IPIP tunnel ttl
443  * @arg link Link object
444  *
445  * @return ttl value
446  */
447 uint8_t rtnl_link_ipip_get_ttl(struct rtnl_link *link)
448 {
449  struct ipip_info *ipip = link->l_info;
450 
451  IS_IPIP_LINK_ASSERT(link);
452 
453  return ipip->ttl;
454 }
455 
456 /**
457  * Set IPIP tunnel tos
458  * @arg link Link object
459  * @arg tos tunnel tos
460  *
461  * @return 0 on success or a negative error code
462  */
463 int rtnl_link_ipip_set_tos(struct rtnl_link *link, uint8_t tos)
464 {
465  struct ipip_info *ipip = link->l_info;
466 
467  IS_IPIP_LINK_ASSERT(link);
468 
469  ipip->tos = tos;
470  ipip->ipip_mask |= IPIP_ATTR_TOS;
471 
472  return 0;
473 }
474 
475 /**
476  * Get IPIP tunnel tos
477  * @arg link Link object
478  *
479  * @return tos value
480  */
481 uint8_t rtnl_link_ipip_get_tos(struct rtnl_link *link)
482 {
483  struct ipip_info *ipip = link->l_info;
484 
485  IS_IPIP_LINK_ASSERT(link);
486 
487  return ipip->tos;
488 }
489 
490 /**
491  * Set IPIP tunnel path MTU discovery
492  * @arg link Link object
493  * @arg pmtudisc path MTU discovery
494  *
495  * @return 0 on success or a negative error code
496  */
497 int rtnl_link_ipip_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc)
498 {
499  struct ipip_info *ipip = link->l_info;
500 
501  IS_IPIP_LINK_ASSERT(link);
502 
503  ipip->pmtudisc = pmtudisc;
504  ipip->ipip_mask |= IPIP_ATTR_PMTUDISC;
505 
506  return 0;
507 }
508 
509 /**
510  * Get IPIP path MTU discovery
511  * @arg link Link object
512  *
513  * @return pmtudisc value
514  */
516 {
517  struct ipip_info *ipip = link->l_info;
518 
519  IS_IPIP_LINK_ASSERT(link);
520 
521  return ipip->pmtudisc;
522 }
523 
524 static void __init ipip_init(void)
525 {
526  rtnl_link_register_info(&ipip_info_ops);
527 }
528 
529 static void __exit ipip_exit(void)
530 {
531  rtnl_link_unregister_info(&ipip_info_ops);
532 }
Dump object briefly on one line.
Definition: types.h:22
8 bit integer
Definition: attr.h:39
int rtnl_link_ipip_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc)
Set IPIP tunnel path MTU discovery.
Definition: ipip.c:497
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
Definition: ipip.c:41
int rtnl_link_is_ipip(struct rtnl_link *link)
Check if link is a IPIP link.
Definition: ipip.c:289
int rtnl_link_ipip_set_remote(struct rtnl_link *link, uint32_t addr)
Set IPIP tunnel remote address.
Definition: ipip.c:395
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:699
int rtnl_link_ipip_add(struct nl_sock *sk, const char *name)
Create a new ipip tunnel device.
Definition: ipip.c:302
int rtnl_link_ipip_set_ttl(struct rtnl_link *link, uint8_t ttl)
Set IPIP tunnel ttl.
Definition: ipip.c:429
#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 rtnl_link_ipip_set_local(struct rtnl_link *link, uint32_t addr)
Set IPIP tunnel local address.
Definition: ipip.c:361
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:917
uint32_t rtnl_link_ipip_get_local(struct rtnl_link *link)
Get IPIP tunnel local address.
Definition: ipip.c:379
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
uint8_t rtnl_link_ipip_get_pmtudisc(struct rtnl_link *link)
Get IPIP path MTU discovery.
Definition: ipip.c:515
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:233
int rtnl_link_ipip_set_link(struct rtnl_link *link, uint32_t index)
Set IPIP tunnel interface index.
Definition: ipip.c:327
uint32_t rtnl_link_ipip_get_remote(struct rtnl_link *link)
Get IPIP tunnel remote address.
Definition: ipip.c:413
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:69
32 bit integer
Definition: attr.h:41
Dumping parameters.
Definition: types.h:33
int rtnl_link_ipip_set_tos(struct rtnl_link *link, uint8_t tos)
Set IPIP tunnel tos.
Definition: ipip.c:463
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:914
uint32_t rtnl_link_ipip_get_link(struct rtnl_link *link)
Get IPIP tunnel interface index.
Definition: ipip.c:345
uint8_t rtnl_link_ipip_get_tos(struct rtnl_link *link)
Get IPIP tunnel tos.
Definition: ipip.c:481
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:895
uint8_t rtnl_link_ipip_get_ttl(struct rtnl_link *link)
Get IPIP tunnel ttl.
Definition: ipip.c:447