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