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