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