libnl  3.2.28
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  struct rtnl_link *parent;
184 
185  if (ipip->ipip_mask & IPIP_ATTR_LINK) {
186  nl_dump(p, " link ");
187 
188  name = NULL;
189  parent = link_lookup(link->ce_cache, ipip->link);
190  if (parent)
191  name = rtnl_link_get_name(parent);
192 
193  if (name)
194  nl_dump_line(p, "%s\n", name);
195  else
196  nl_dump_line(p, "%u\n", ipip->link);
197  }
198 
199  if (ipip->ipip_mask & IPIP_ATTR_LOCAL) {
200  nl_dump(p, " local ");
201  if(inet_ntop(AF_INET, &ipip->local, addr, sizeof(addr)))
202  nl_dump_line(p, "%s\n", addr);
203  else
204  nl_dump_line(p, "%#x\n", ntohs(ipip->local));
205  }
206 
207  if (ipip->ipip_mask & IPIP_ATTR_REMOTE) {
208  nl_dump(p, " remote ");
209  if(inet_ntop(AF_INET, &ipip->remote, addr, sizeof(addr)))
210  nl_dump_line(p, "%s\n", addr);
211  else
212  nl_dump_line(p, "%#x\n", ntohs(ipip->remote));
213  }
214 
215  if (ipip->ipip_mask & IPIP_ATTR_TTL) {
216  nl_dump(p, " ttl ");
217  nl_dump_line(p, "%u\n", ipip->ttl);
218  }
219 
220  if (ipip->ipip_mask & IPIP_ATTR_TOS) {
221  nl_dump(p, " tos ");
222  nl_dump_line(p, "%u\n", ipip->tos);
223  }
224 
225  if (ipip->ipip_mask & IPIP_ATTR_PMTUDISC) {
226  nl_dump(p, " pmtudisc ");
227  nl_dump_line(p, "enabled (%#x)\n", ipip->pmtudisc);
228  }
229 }
230 
231 static int ipip_clone(struct rtnl_link *dst, struct rtnl_link *src)
232 {
233  struct ipip_info *ipip_dst, *ipip_src = src->l_info;
234  int err;
235 
236  dst->l_info = NULL;
237 
238  err = rtnl_link_set_type(dst, "ipip");
239  if (err < 0)
240  return err;
241 
242  ipip_dst = dst->l_info;
243 
244  if (!ipip_dst || !ipip_src)
245  BUG();
246 
247  memcpy(ipip_dst, ipip_src, sizeof(struct ipip_info));
248 
249  return 0;
250 }
251 
252 static struct rtnl_link_info_ops ipip_info_ops = {
253  .io_name = "ipip",
254  .io_alloc = ipip_alloc,
255  .io_parse = ipip_parse,
256  .io_dump = {
257  [NL_DUMP_LINE] = ipip_dump_line,
258  [NL_DUMP_DETAILS] = ipip_dump_details,
259  },
260  .io_clone = ipip_clone,
261  .io_put_attrs = ipip_put_attrs,
262  .io_free = ipip_free,
263 };
264 
265 #define IS_IPIP_LINK_ASSERT(link) \
266  if ((link)->l_info_ops != &ipip_info_ops) { \
267  APPBUG("Link is not a ipip link. set type \"ipip\" first."); \
268  return -NLE_OPNOTSUPP; \
269  }
270 
271 struct rtnl_link *rtnl_link_ipip_alloc(void)
272 {
273  struct rtnl_link *link;
274  int err;
275 
276  link = rtnl_link_alloc();
277  if (!link)
278  return NULL;
279 
280  err = rtnl_link_set_type(link, "ipip");
281  if (err < 0) {
282  rtnl_link_put(link);
283  return NULL;
284  }
285 
286  return link;
287 }
288 
289 /**
290  * Check if link is a IPIP link
291  * @arg link Link object
292  *
293  * @return True if link is a IPIP link, otherwise false is returned.
294  */
295 int rtnl_link_is_ipip(struct rtnl_link *link)
296 {
297  return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "ipip");
298 }
299 
300 /**
301  * Create a new ipip tunnel device
302  * @arg sock netlink socket
303  * @arg name name of the tunnel deviceL
304  *
305  * Creates a new ipip tunnel device in the kernel
306  * @return 0 on success or a negative error code
307  */
308 int rtnl_link_ipip_add(struct nl_sock *sk, const char *name)
309 {
310  struct rtnl_link *link;
311  int err;
312 
313  link = rtnl_link_ipip_alloc();
314  if (!link)
315  return -NLE_NOMEM;
316 
317  if(name)
318  rtnl_link_set_name(link, name);
319 
320  err = rtnl_link_add(sk, link, NLM_F_CREATE);
321  rtnl_link_put(link);
322 
323  return err;
324 }
325 
326 /**
327  * Set IPIP tunnel interface index
328  * @arg link Link object
329  * @arg index interface index
330  *
331  * @return 0 on success or a negative error code
332  */
333 int rtnl_link_ipip_set_link(struct rtnl_link *link, uint32_t index)
334 {
335  struct ipip_info *ipip = link->l_info;
336 
337  IS_IPIP_LINK_ASSERT(link);
338 
339  ipip->link = index;
340  ipip->ipip_mask |= IPIP_ATTR_LINK;
341 
342  return 0;
343 }
344 
345 /**
346  * Get IPIP tunnel interface index
347  * @arg link Link object
348  *
349  * @return interface index value
350  */
351 uint32_t rtnl_link_ipip_get_link(struct rtnl_link *link)
352 {
353  struct ipip_info *ipip = link->l_info;
354 
355  IS_IPIP_LINK_ASSERT(link);
356 
357  return ipip->link;
358 }
359 
360 /**
361  * Set IPIP tunnel local address
362  * @arg link Link object
363  * @arg addr local address
364  *
365  * @return 0 on success or a negative error code
366  */
367 int rtnl_link_ipip_set_local(struct rtnl_link *link, uint32_t addr)
368 {
369  struct ipip_info *ipip = link->l_info;
370 
371  IS_IPIP_LINK_ASSERT(link);
372 
373  ipip->local = addr;
374  ipip->ipip_mask |= IPIP_ATTR_LOCAL;
375 
376  return 0;
377 }
378 
379 /**
380  * Get IPIP tunnel local address
381  * @arg link Link object
382  *
383  * @return local address value
384  */
385 uint32_t rtnl_link_ipip_get_local(struct rtnl_link *link)
386 {
387  struct ipip_info *ipip = link->l_info;
388 
389  IS_IPIP_LINK_ASSERT(link);
390 
391  return ipip->local;
392 }
393 
394 /**
395  * Set IPIP tunnel remote address
396  * @arg link Link object
397  * @arg remote remote address
398  *
399  * @return 0 on success or a negative error code
400  */
401 int rtnl_link_ipip_set_remote(struct rtnl_link *link, uint32_t addr)
402 {
403  struct ipip_info *ipip = link->l_info;
404 
405  IS_IPIP_LINK_ASSERT(link);
406 
407  ipip->remote = addr;
408  ipip->ipip_mask |= IPIP_ATTR_REMOTE;
409 
410  return 0;
411 }
412 
413 /**
414  * Get IPIP tunnel remote address
415  * @arg link Link object
416  *
417  * @return remote address
418  */
419 uint32_t rtnl_link_ipip_get_remote(struct rtnl_link *link)
420 {
421  struct ipip_info *ipip = link->l_info;
422 
423  IS_IPIP_LINK_ASSERT(link);
424 
425  return ipip->remote;
426 }
427 
428 /**
429  * Set IPIP tunnel ttl
430  * @arg link Link object
431  * @arg ttl tunnel ttl
432  *
433  * @return 0 on success or a negative error code
434  */
435 int rtnl_link_ipip_set_ttl(struct rtnl_link *link, uint8_t ttl)
436 {
437  struct ipip_info *ipip = link->l_info;
438 
439  IS_IPIP_LINK_ASSERT(link);
440 
441  ipip->ttl = ttl;
442  ipip->ipip_mask |= IPIP_ATTR_TTL;
443 
444  return 0;
445 }
446 
447 /**
448  * Get IPIP tunnel ttl
449  * @arg link Link object
450  *
451  * @return ttl value
452  */
453 uint8_t rtnl_link_ipip_get_ttl(struct rtnl_link *link)
454 {
455  struct ipip_info *ipip = link->l_info;
456 
457  IS_IPIP_LINK_ASSERT(link);
458 
459  return ipip->ttl;
460 }
461 
462 /**
463  * Set IPIP tunnel tos
464  * @arg link Link object
465  * @arg tos tunnel tos
466  *
467  * @return 0 on success or a negative error code
468  */
469 int rtnl_link_ipip_set_tos(struct rtnl_link *link, uint8_t tos)
470 {
471  struct ipip_info *ipip = link->l_info;
472 
473  IS_IPIP_LINK_ASSERT(link);
474 
475  ipip->tos = tos;
476  ipip->ipip_mask |= IPIP_ATTR_TOS;
477 
478  return 0;
479 }
480 
481 /**
482  * Get IPIP tunnel tos
483  * @arg link Link object
484  *
485  * @return tos value
486  */
487 uint8_t rtnl_link_ipip_get_tos(struct rtnl_link *link)
488 {
489  struct ipip_info *ipip = link->l_info;
490 
491  IS_IPIP_LINK_ASSERT(link);
492 
493  return ipip->tos;
494 }
495 
496 /**
497  * Set IPIP tunnel path MTU discovery
498  * @arg link Link object
499  * @arg pmtudisc path MTU discovery
500  *
501  * @return 0 on success or a negative error code
502  */
503 int rtnl_link_ipip_set_pmtudisc(struct rtnl_link *link, uint8_t pmtudisc)
504 {
505  struct ipip_info *ipip = link->l_info;
506 
507  IS_IPIP_LINK_ASSERT(link);
508 
509  ipip->pmtudisc = pmtudisc;
510  ipip->ipip_mask |= IPIP_ATTR_PMTUDISC;
511 
512  return 0;
513 }
514 
515 /**
516  * Get IPIP path MTU discovery
517  * @arg link Link object
518  *
519  * @return pmtudisc value
520  */
522 {
523  struct ipip_info *ipip = link->l_info;
524 
525  IS_IPIP_LINK_ASSERT(link);
526 
527  return ipip->pmtudisc;
528 }
529 
530 static void __init ipip_init(void)
531 {
532  rtnl_link_register_info(&ipip_info_ops);
533 }
534 
535 static void __exit ipip_exit(void)
536 {
537  rtnl_link_unregister_info(&ipip_info_ops);
538 }
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:503
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:295
int rtnl_link_ipip_set_remote(struct rtnl_link *link, uint32_t addr)
Set IPIP tunnel remote address.
Definition: ipip.c:401
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:308
int rtnl_link_ipip_set_ttl(struct rtnl_link *link, uint8_t ttl)
Set IPIP tunnel ttl.
Definition: ipip.c:435
#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:367
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:385
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:992
uint8_t rtnl_link_ipip_get_pmtudisc(struct rtnl_link *link)
Get IPIP path MTU discovery.
Definition: ipip.c:521
#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:333
uint32_t rtnl_link_ipip_get_remote(struct rtnl_link *link)
Get IPIP tunnel remote address.
Definition: ipip.c:419
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:469
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:351
uint8_t rtnl_link_ipip_get_tos(struct rtnl_link *link)
Get IPIP tunnel tos.
Definition: ipip.c:487
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:453