libnl  3.3.0
ipvti.c
1 /*
2  * lib/route/link/ipvti.c IPVTI 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 ipvti IPVTI
15  * ipvti link module
16  *
17  * @details
18  * \b Link Type Name: "ipvti"
19  *
20  * @route_doc{link_ipvti, IPVTI 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/ipvti.h>
32 #include <netlink-private/route/link/api.h>
33 #include <linux/if_tunnel.h>
34 
35 #define IPVTI_ATTR_LINK (1 << 0)
36 #define IPVTI_ATTR_IKEY (1 << 1)
37 #define IPVTI_ATTR_OKEY (1 << 2)
38 #define IPVTI_ATTR_LOCAL (1 << 3)
39 #define IPVTI_ATTR_REMOTE (1 << 4)
40 
41 struct ipvti_info
42 {
43  uint32_t link;
44  uint32_t ikey;
45  uint32_t okey;
46  uint32_t local;
47  uint32_t remote;
48  uint32_t ipvti_mask;
49 };
50 
51 static struct nla_policy ipvti_policy[IFLA_GRE_MAX + 1] = {
52  [IFLA_VTI_LINK] = { .type = NLA_U32 },
53  [IFLA_VTI_IKEY] = { .type = NLA_U32 },
54  [IFLA_VTI_OKEY] = { .type = NLA_U32 },
55  [IFLA_VTI_LOCAL] = { .type = NLA_U32 },
56  [IFLA_VTI_REMOTE] = { .type = NLA_U32 },
57 };
58 
59 static int ipvti_alloc(struct rtnl_link *link)
60 {
61  struct ipvti_info *ipvti;
62 
63  if (link->l_info)
64  memset(link->l_info, 0, sizeof(*ipvti));
65  else {
66  ipvti = calloc(1, sizeof(*ipvti));
67  if (!ipvti)
68  return -NLE_NOMEM;
69 
70  link->l_info = ipvti;
71  }
72 
73  return 0;
74 }
75 
76 static int ipvti_parse(struct rtnl_link *link, struct nlattr *data,
77  struct nlattr *xstats)
78 {
79  struct nlattr *tb[IFLA_IPTUN_MAX + 1];
80  struct ipvti_info *ipvti;
81  int err;
82 
83  NL_DBG(3, "Parsing IPVTI link info\n");
84 
85  err = nla_parse_nested(tb, IFLA_GRE_MAX, data, ipvti_policy);
86  if (err < 0)
87  goto errout;
88 
89  err = ipvti_alloc(link);
90  if (err < 0)
91  goto errout;
92 
93  ipvti = link->l_info;
94 
95  if (tb[IFLA_VTI_LINK]) {
96  ipvti->link = nla_get_u32(tb[IFLA_VTI_LINK]);
97  ipvti->ipvti_mask |= IPVTI_ATTR_LINK;
98  }
99 
100  if (tb[IFLA_VTI_IKEY]) {
101  ipvti->ikey = nla_get_u32(tb[IFLA_VTI_IKEY]);
102  ipvti->ipvti_mask |= IPVTI_ATTR_IKEY;
103  }
104 
105  if (tb[IFLA_VTI_OKEY]) {
106  ipvti->okey = nla_get_u32(tb[IFLA_VTI_OKEY]);
107  ipvti->ipvti_mask |= IPVTI_ATTR_OKEY;
108  }
109 
110  if (tb[IFLA_VTI_LOCAL]) {
111  ipvti->local = nla_get_u32(tb[IFLA_VTI_LOCAL]);
112  ipvti->ipvti_mask |= IPVTI_ATTR_LOCAL;
113  }
114 
115  if (tb[IFLA_VTI_REMOTE]) {
116  ipvti->remote = nla_get_u32(tb[IFLA_VTI_REMOTE]);
117  ipvti->ipvti_mask |= IPVTI_ATTR_REMOTE;
118  }
119 
120  err = 0;
121 
122 errout:
123  return err;
124 }
125 
126 static int ipvti_put_attrs(struct nl_msg *msg, struct rtnl_link *link)
127 {
128  struct ipvti_info *ipvti = link->l_info;
129  struct nlattr *data;
130 
131  data = nla_nest_start(msg, IFLA_INFO_DATA);
132  if (!data)
133  return -NLE_MSGSIZE;
134 
135  if (ipvti->ipvti_mask & IPVTI_ATTR_LINK)
136  NLA_PUT_U32(msg, IFLA_VTI_LINK, ipvti->link);
137 
138  if (ipvti->ipvti_mask & IPVTI_ATTR_IKEY)
139  NLA_PUT_U32(msg, IFLA_VTI_IKEY, ipvti->ikey);
140 
141  if (ipvti->ipvti_mask & IFLA_VTI_IKEY)
142  NLA_PUT_U32(msg, IFLA_VTI_OKEY, ipvti->okey);
143 
144  if (ipvti->ipvti_mask & IPVTI_ATTR_LOCAL)
145  NLA_PUT_U32(msg, IFLA_VTI_LOCAL, ipvti->local);
146 
147  if (ipvti->ipvti_mask & IPVTI_ATTR_REMOTE)
148  NLA_PUT_U32(msg, IFLA_VTI_REMOTE, ipvti->remote);
149 
150  nla_nest_end(msg, data);
151 
152 nla_put_failure:
153 
154  return 0;
155 }
156 
157 static void ipvti_free(struct rtnl_link *link)
158 {
159  struct ipvti_info *ipvti = link->l_info;
160 
161  free(ipvti);
162  link->l_info = NULL;
163 }
164 
165 static void ipvti_dump_line(struct rtnl_link *link, struct nl_dump_params *p)
166 {
167  nl_dump(p, "ipvti : %s", link->l_name);
168 }
169 
170 static void ipvti_dump_details(struct rtnl_link *link, struct nl_dump_params *p)
171 {
172  struct ipvti_info *ipvti = link->l_info;
173  char *name, addr[INET_ADDRSTRLEN];
174  struct rtnl_link *parent;
175 
176  if (ipvti->ipvti_mask & IPVTI_ATTR_LINK) {
177  nl_dump(p, " link ");
178 
179  name = NULL;
180  parent = link_lookup(link->ce_cache, ipvti->link);
181  if (parent)
182  name = rtnl_link_get_name(parent);
183 
184  if (name)
185  nl_dump_line(p, "%s\n", name);
186  else
187  nl_dump_line(p, "%u\n", ipvti->link);
188  }
189 
190  if (ipvti->ipvti_mask & IPVTI_ATTR_IKEY) {
191  nl_dump(p, " ikey ");
192  nl_dump_line(p, "%x\n",ipvti->ikey);
193  }
194 
195  if (ipvti->ipvti_mask & IPVTI_ATTR_OKEY) {
196  nl_dump(p, " okey ");
197  nl_dump_line(p, "%x\n", ipvti->okey);
198  }
199 
200  if (ipvti->ipvti_mask & IPVTI_ATTR_LOCAL) {
201  nl_dump(p, " local ");
202  if(inet_ntop(AF_INET, &ipvti->local, addr, sizeof(addr)))
203  nl_dump_line(p, "%s\n", addr);
204  else
205  nl_dump_line(p, "%#x\n", ntohs(ipvti->local));
206  }
207 
208  if (ipvti->ipvti_mask & IPVTI_ATTR_REMOTE) {
209  nl_dump(p, " remote ");
210  if(inet_ntop(AF_INET, &ipvti->remote, addr, sizeof(addr)))
211  nl_dump_line(p, "%s\n", addr);
212  else
213  nl_dump_line(p, "%#x\n", ntohs(ipvti->remote));
214  }
215 }
216 
217 static int ipvti_clone(struct rtnl_link *dst, struct rtnl_link *src)
218 {
219  struct ipvti_info *ipvti_dst, *ipvti_src = src->l_info;
220  int err;
221 
222  dst->l_info = NULL;
223 
224  err = rtnl_link_set_type(dst, "vti");
225  if (err < 0)
226  return err;
227 
228  ipvti_dst = dst->l_info;
229 
230  if (!ipvti_dst || !ipvti_src)
231  BUG();
232 
233  memcpy(ipvti_dst, ipvti_src, sizeof(struct ipvti_info));
234 
235  return 0;
236 }
237 
238 static struct rtnl_link_info_ops ipvti_info_ops = {
239  .io_name = "vti",
240  .io_alloc = ipvti_alloc,
241  .io_parse = ipvti_parse,
242  .io_dump = {
243  [NL_DUMP_LINE] = ipvti_dump_line,
244  [NL_DUMP_DETAILS] = ipvti_dump_details,
245  },
246  .io_clone = ipvti_clone,
247  .io_put_attrs = ipvti_put_attrs,
248  .io_free = ipvti_free,
249 };
250 
251 #define IS_IPVTI_LINK_ASSERT(link) \
252  if ((link)->l_info_ops != &ipvti_info_ops) { \
253  APPBUG("Link is not a ipvti link. set type \vti\" first."); \
254  return -NLE_OPNOTSUPP; \
255  }
256 
257 struct rtnl_link *rtnl_link_ipvti_alloc(void)
258 {
259  struct rtnl_link *link;
260  int err;
261 
262  link = rtnl_link_alloc();
263  if (!link)
264  return NULL;
265 
266  err = rtnl_link_set_type(link, "vti");
267  if (err < 0) {
268  rtnl_link_put(link);
269  return NULL;
270  }
271 
272  return link;
273 }
274 
275 /**
276  * Check if link is a IPVTI link
277  * @arg link Link object
278  *
279  * @return True if link is a IPVTI link, otherwise 0 is returned.
280  */
281 int rtnl_link_is_ipvti(struct rtnl_link *link)
282 {
283  return link->l_info_ops && !strcmp(link->l_info_ops->io_name, "vti");
284 }
285 /**
286  * Create a new ipvti tunnel device
287  * @arg sock netlink socket
288  * @arg name name of the tunnel deviceL
289  *
290  * Creates a new ipvti tunnel device in the kernel
291  * @return 0 on success or a negative error code
292  */
293 int rtnl_link_ipvti_add(struct nl_sock *sk, const char *name)
294 {
295  struct rtnl_link *link;
296  int err;
297 
298  link = rtnl_link_ipvti_alloc();
299  if (!link)
300  return -NLE_NOMEM;
301 
302  if(name)
303  rtnl_link_set_name(link, name);
304 
305  err = rtnl_link_add(sk, link, NLM_F_CREATE);
306  rtnl_link_put(link);
307 
308  return err;
309 }
310 /**
311  * Set IPVTI tunnel interface index
312  * @arg link Link object
313  * @arg index interface index
314  *
315  * @return 0 on success or a negative error code
316  */
317 int rtnl_link_ipvti_set_link(struct rtnl_link *link, uint32_t index)
318 {
319  struct ipvti_info *ipvti = link->l_info;
320 
321  IS_IPVTI_LINK_ASSERT(link);
322 
323  ipvti->link = index;
324  ipvti->ipvti_mask |= IPVTI_ATTR_LINK;
325 
326  return 0;
327 }
328 
329 /**
330  * Get IPVTI tunnel interface index
331  * @arg link Link object
332  *
333  * @return interface index
334  */
335 uint32_t rtnl_link_ipvti_get_link(struct rtnl_link *link)
336 {
337  struct ipvti_info *ipvti = link->l_info;
338 
339  IS_IPVTI_LINK_ASSERT(link);
340 
341  return ipvti->link;
342 }
343 
344 /**
345  * Set IPVTI tunnel set ikey
346  * @arg link Link object
347  * @arg ikey gre ikey
348  *
349  * @return 0 on success or a negative error code
350  */
351 int rtnl_link_ipvti_set_ikey(struct rtnl_link *link, uint32_t ikey)
352 {
353  struct ipvti_info *ipvti = link->l_info;
354 
355  IS_IPVTI_LINK_ASSERT(link);
356 
357  ipvti->ikey = ikey;
358  ipvti->ipvti_mask |= IPVTI_ATTR_IKEY;
359 
360  return 0;
361 }
362 
363 /**
364  * Get IPVTI tunnel ikey
365  * @arg link Link object
366  *
367  * @return ikey
368  */
369 uint32_t rtnl_link_ipvti_get_ikey(struct rtnl_link *link)
370 {
371  struct ipvti_info *ipvti = link->l_info;
372 
373  IS_IPVTI_LINK_ASSERT(link);
374 
375  return ipvti->ikey;
376 }
377 
378 /**
379  * Set IPVTI tunnel set okey
380  * @arg link Link object
381  * @arg okey gre okey
382  *
383  * @return 0 on success or a negative error code
384  */
385 int rtnl_link_ipvti_set_okey(struct rtnl_link *link, uint32_t okey)
386 {
387  struct ipvti_info *ipvti = link->l_info;
388 
389  IS_IPVTI_LINK_ASSERT(link);
390 
391  ipvti->okey = okey;
392  ipvti->ipvti_mask |= IPVTI_ATTR_OKEY;
393 
394  return 0;
395 }
396 
397 /**
398  * Get IPVTI tunnel okey
399  * @arg link Link object
400  *
401  * @return okey value
402  */
403 uint32_t rtnl_link_ipvti_get_okey(struct rtnl_link *link)
404 {
405  struct ipvti_info *ipvti = link->l_info;
406 
407  IS_IPVTI_LINK_ASSERT(link);
408 
409  return ipvti->okey;
410 }
411 
412 /**
413  * Set IPVTI tunnel local address
414  * @arg link Link object
415  * @arg addr local address
416  *
417  * @return 0 on success or a negative error code
418  */
419 int rtnl_link_ipvti_set_local(struct rtnl_link *link, uint32_t addr)
420 {
421  struct ipvti_info *ipvti = link->l_info;
422 
423  IS_IPVTI_LINK_ASSERT(link);
424 
425  ipvti->local = addr;
426  ipvti->ipvti_mask |= IPVTI_ATTR_LOCAL;
427 
428  return 0;
429 }
430 
431 /**
432  * Get IPVTI tunnel local address
433  * @arg link Link object
434  *
435  * @return local address
436  */
437 uint32_t rtnl_link_ipvti_get_local(struct rtnl_link *link)
438 {
439  struct ipvti_info *ipvti = link->l_info;
440 
441  IS_IPVTI_LINK_ASSERT(link);
442 
443  return ipvti->local;
444 }
445 
446 /**
447  * Set IPVTI tunnel remote address
448  * @arg link Link object
449  * @arg remote remote address
450  *
451  * @return 0 on success or a negative error code
452  */
453 int rtnl_link_ipvti_set_remote(struct rtnl_link *link, uint32_t remote)
454 {
455  struct ipvti_info *ipvti = link->l_info;
456 
457  IS_IPVTI_LINK_ASSERT(link);
458 
459  ipvti->remote = remote;
460  ipvti->ipvti_mask |= IPVTI_ATTR_REMOTE;
461 
462  return 0;
463 }
464 
465 /**
466  * Get IPVTI tunnel remote address
467  * @arg link Link object
468  *
469  * @return remote address on success or a negative error code
470  */
471 uint32_t rtnl_link_ipvti_get_remote(struct rtnl_link *link)
472 {
473  struct ipvti_info *ipvti = link->l_info;
474 
475  IS_IPVTI_LINK_ASSERT(link);
476 
477  return ipvti->remote;
478 }
479 
480 static void __init ipvti_init(void)
481 {
482  rtnl_link_register_info(&ipvti_info_ops);
483 }
484 
485 static void __exit ipvti_exit(void)
486 {
487  rtnl_link_unregister_info(&ipvti_info_ops);
488 }
uint32_t rtnl_link_ipvti_get_ikey(struct rtnl_link *link)
Get IPVTI tunnel ikey.
Definition: ipvti.c:369
Dump object briefly on one line.
Definition: types.h:22
Attribute validation policy.
Definition: attr.h:69
uint32_t rtnl_link_ipvti_get_remote(struct rtnl_link *link)
Get IPVTI tunnel remote address.
Definition: ipvti.c:471
int rtnl_link_ipvti_set_okey(struct rtnl_link *link, uint32_t okey)
Set IPVTI tunnel set okey.
Definition: ipvti.c:385
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:706
int rtnl_link_is_ipvti(struct rtnl_link *link)
Check if link is a IPVTI link.
Definition: ipvti.c:281
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:924
int rtnl_link_ipvti_add(struct nl_sock *sk, const char *name)
Create a new ipvti tunnel device.
Definition: ipvti.c:293
int rtnl_link_ipvti_set_ikey(struct rtnl_link *link, uint32_t ikey)
Set IPVTI tunnel set ikey.
Definition: ipvti.c:351
uint32_t rtnl_link_ipvti_get_okey(struct rtnl_link *link)
Get IPVTI tunnel okey.
Definition: ipvti.c:403
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:999
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:235
uint32_t rtnl_link_ipvti_get_local(struct rtnl_link *link)
Get IPVTI tunnel local address.
Definition: ipvti.c:437
int rtnl_link_ipvti_set_link(struct rtnl_link *link, uint32_t index)
Set IPVTI tunnel interface index.
Definition: ipvti.c:317
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:71
32 bit integer
Definition: attr.h:43
Dumping parameters.
Definition: types.h:33
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:961
int rtnl_link_ipvti_set_local(struct rtnl_link *link, uint32_t addr)
Set IPVTI tunnel local address.
Definition: ipvti.c:419
uint32_t rtnl_link_ipvti_get_link(struct rtnl_link *link)
Get IPVTI tunnel interface index.
Definition: ipvti.c:335
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:902
int rtnl_link_ipvti_set_remote(struct rtnl_link *link, uint32_t remote)
Set IPVTI tunnel remote address.
Definition: ipvti.c:453