libnl: /data/src/libnl3/lib/route/link/ipvti.c Source File

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
36 struct ipvti_info
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
47 static 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
56 static 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
73 static 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
124 errout:
125 return err;
126 }
127
128 static 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
157 nla_put_failure:
158
159 return 0;
160 }
161
162 static 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
170 static 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
175 static 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
227 static 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
248 static 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
267 struct 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 */
291 int rtnl_link_is_ipvti(struct rtnl_link *link)
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 */
303 int 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 */
327 int 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 */
345 uint32_t rtnl_link_ipvti_get_link(struct rtnl_link *link)
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 */
361 int 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 */
379 uint32_t rtnl_link_ipvti_get_ikey(struct rtnl_link *link)
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 */
395 int 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 */
413 uint32_t rtnl_link_ipvti_get_okey(struct rtnl_link *link)
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 */
429 int 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 */
447 uint32_t rtnl_link_ipvti_get_local(struct rtnl_link *link)
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 */
463 int 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 */
481 uint32_t rtnl_link_ipvti_get_remote(struct rtnl_link *link)
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 */
497 int 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 */
516 int 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
530 static void __init ipvti_init(void)
531 {
532 rtnl_link_register_info(&ipvti_info_ops);
533 }
534
535 static void __exit ipvti_exit(void)
536 {
537 rtnl_link_unregister_info(&ipvti_info_ops);
538 }
nla_get_u32
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:699
NLA_PUT_U32
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:230
nla_nest_start
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:895
nla_parse_nested
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:1013
nla_nest_end
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:958
NLA_U32
@ NLA_U32
32 bit integer
Definition: attr.h:37
rtnl_link_ipvti_set_ikey
int rtnl_link_ipvti_set_ikey(struct rtnl_link *link, uint32_t ikey)
Set IPVTI tunnel set ikey.
Definition: ipvti.c:361
rtnl_link_ipvti_get_ikey
uint32_t rtnl_link_ipvti_get_ikey(struct rtnl_link *link)
Get IPVTI tunnel ikey.
Definition: ipvti.c:379
rtnl_link_ipvti_set_local
int rtnl_link_ipvti_set_local(struct rtnl_link *link, uint32_t addr)
Set IPVTI tunnel local address.
Definition: ipvti.c:429
rtnl_link_ipvti_set_remote
int rtnl_link_ipvti_set_remote(struct rtnl_link *link, uint32_t remote)
Set IPVTI tunnel remote address.
Definition: ipvti.c:463
rtnl_link_ipvti_get_fwmark
int rtnl_link_ipvti_get_fwmark(struct rtnl_link *link, uint32_t *fwmark)
Get IPVTI tunnel fwmark.
Definition: ipvti.c:516
rtnl_link_ipvti_get_local
uint32_t rtnl_link_ipvti_get_local(struct rtnl_link *link)
Get IPVTI tunnel local address.
Definition: ipvti.c:447
rtnl_link_ipvti_set_fwmark
int rtnl_link_ipvti_set_fwmark(struct rtnl_link *link, uint32_t fwmark)
Set IPVTI tunnel fwmark.
Definition: ipvti.c:497
rtnl_link_ipvti_set_okey
int rtnl_link_ipvti_set_okey(struct rtnl_link *link, uint32_t okey)
Set IPVTI tunnel set okey.
Definition: ipvti.c:395
rtnl_link_is_ipvti
int rtnl_link_is_ipvti(struct rtnl_link *link)
Check if link is a IPVTI link.
Definition: ipvti.c:291
rtnl_link_ipvti_get_link
uint32_t rtnl_link_ipvti_get_link(struct rtnl_link *link)
Get IPVTI tunnel interface index.
Definition: ipvti.c:345
rtnl_link_ipvti_get_remote
uint32_t rtnl_link_ipvti_get_remote(struct rtnl_link *link)
Get IPVTI tunnel remote address.
Definition: ipvti.c:481
rtnl_link_ipvti_set_link
int rtnl_link_ipvti_set_link(struct rtnl_link *link, uint32_t index)
Set IPVTI tunnel interface index.
Definition: ipvti.c:327
rtnl_link_ipvti_get_okey
uint32_t rtnl_link_ipvti_get_okey(struct rtnl_link *link)
Get IPVTI tunnel okey.
Definition: ipvti.c:413
rtnl_link_ipvti_add
int rtnl_link_ipvti_add(struct nl_sock *sk, const char *name)
Create a new ipvti tunnel device.
Definition: ipvti.c:303
rtnl_link_register_info
int rtnl_link_register_info(struct rtnl_link_info_ops *ops)
Register operations for a link info type.
Definition: api.c:124
rtnl_link_unregister_info
int rtnl_link_unregister_info(struct rtnl_link_info_ops *ops)
Unregister operations for a link info type.
Definition: api.c:159
rtnl_link_add
int rtnl_link_add(struct nl_sock *sk, struct rtnl_link *link, int flags)
Add virtual link.
Definition: link.c:1684
rtnl_link_get_name
char * rtnl_link_get_name(struct rtnl_link *link)
Return name of link object.
Definition: link.c:1952
rtnl_link_set_name
void rtnl_link_set_name(struct rtnl_link *link, const char *name)
Set name of link object.
Definition: link.c:1938
rtnl_link_put
void rtnl_link_put(struct rtnl_link *link)
Return a link object reference.
Definition: link.c:1919
rtnl_link_set_type
int rtnl_link_set_type(struct rtnl_link *link, const char *type)
Set type of link object.
Definition: link.c:2548
rtnl_link_alloc
struct rtnl_link * rtnl_link_alloc(void)
Allocate link object.
Definition: link.c:1910
nl_dump
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:955
NL_DUMP_LINE
@ NL_DUMP_LINE
Dump object briefly on one line.
Definition: types.h:16
NL_DUMP_DETAILS
@ NL_DUMP_DETAILS
Dump all attributes but no statistics.
Definition: types.h:17
ipvti_info
Definition: ipvti.c:37
nl_dump_params
Dumping parameters.
Definition: types.h:28
nla_policy
Attribute validation policy.
Definition: attr.h:63
nla_policy::type
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:65
rtnl_link
Link object.