]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/link_iptnl.c
lib/libnetlink: update rtnl_talk to support malloc buff at run time
[mirror_iproute2.git] / ip / link_iptnl.c
CommitLineData
1ce2de97
ND
1/*
2 * link_iptnl.c ipip and sit driver module
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Nicolas Dichtel <nicolas.dichtel@6wind.com>
10 *
11 */
12
13#include <string.h>
14#include <net/if.h>
15#include <sys/types.h>
16#include <sys/socket.h>
17#include <arpa/inet.h>
18
f005b700 19#include <linux/in.h>
1ce2de97
ND
20#include <linux/ip.h>
21#include <linux/if_tunnel.h>
22#include "rt_names.h"
23#include "utils.h"
24#include "ip_common.h"
25#include "tunnel.h"
26
561e650e 27static void print_usage(FILE *f, int sit)
1ce2de97 28{
8b471354
PS
29 const char *type = sit ? "sit " : "ipip";
30
31 fprintf(f,
32 "Usage: ... %s [ remote ADDR ]\n"
33 " [ local ADDR ]\n"
34 " [ ttl TTL ]\n"
35 " [ tos TOS ]\n"
36 " [ [no]pmtudisc ]\n"
37 " [ dev PHYS_DEV ]\n"
38 " [ 6rd-prefix ADDR ]\n"
39 " [ 6rd-relay_prefix ADDR ]\n"
40 " [ 6rd-reset ]\n"
41 " [ noencap ]\n"
42 " [ encap { fou | gue | none } ]\n"
43 " [ encap-sport PORT ]\n"
44 " [ encap-dport PORT ]\n"
45 " [ [no]encap-csum ]\n"
46 " [ [no]encap-csum6 ]\n"
47 " [ [no]encap-remcsum ]\n",
48 type
49 );
77620be8 50 if (sit) {
f005b700
KJ
51 fprintf(f, " [ mode { ip6ip | ipip | mplsip | any } ]\n");
52 fprintf(f, " [ isatap ]\n");
288c28bc
KJ
53 } else {
54 fprintf(f, " [ mode { ipip | mplsip | any } ]\n");
77620be8 55 }
8b471354 56 fprintf(f, " [ external ]\n");
ad4b1425 57 fprintf(f, " [ fwmark MARK ]\n");
561e650e 58 fprintf(f, "\n");
8b471354 59 fprintf(f, "Where: ADDR := { IP_ADDRESS | any }\n");
561e650e 60 fprintf(f, " TOS := { NUMBER | inherit }\n");
61 fprintf(f, " TTL := { 1..255 | inherit }\n");
ad4b1425 62 fprintf(f, " MARK := { 0x0..0xffffffff }\n");
561e650e 63}
64
65static void usage(int sit) __attribute__((noreturn));
66static void usage(int sit)
67{
68 print_usage(stderr, sit);
1ce2de97
ND
69 exit(-1);
70}
71
72static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv,
73 struct nlmsghdr *n)
74{
d17b136f 75 struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
1ce2de97
ND
76 struct {
77 struct nlmsghdr n;
78 struct ifinfomsg i;
d17b136f
PS
79 } req = {
80 .n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)),
81 .n.nlmsg_flags = NLM_F_REQUEST,
82 .n.nlmsg_type = RTM_GETLINK,
83 .i.ifi_family = preferred_family,
84 .i.ifi_index = ifi->ifi_index,
85 };
86bf43c7 86 struct nlmsghdr *answer = NULL;
1ce2de97
ND
87 struct rtattr *tb[IFLA_MAX + 1];
88 struct rtattr *linkinfo[IFLA_INFO_MAX+1];
89 struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1];
90 int len;
91 __u32 link = 0;
92 __u32 laddr = 0;
93 __u32 raddr = 0;
94 __u8 ttl = 0;
95 __u8 tos = 0;
96 __u8 pmtudisc = 1;
97 __u16 iflags = 0;
77620be8 98 __u8 proto = 0;
d17b136f 99 struct in6_addr ip6rdprefix = {};
1ce2de97
ND
100 __u16 ip6rdprefixlen = 0;
101 __u32 ip6rdrelayprefix = 0;
102 __u16 ip6rdrelayprefixlen = 0;
c1159152
TH
103 __u16 encaptype = 0;
104 __u16 encapflags = 0;
105 __u16 encapsport = 0;
106 __u16 encapdport = 0;
4bfe6825 107 __u8 metadata = 0;
ad4b1425 108 __u32 fwmark = 0;
1ce2de97 109
1ce2de97 110 if (!(n->nlmsg_flags & NLM_F_CREATE)) {
86bf43c7 111 if (rtnl_talk(&rth, &req.n, &answer) < 0) {
1ce2de97
ND
112get_failed:
113 fprintf(stderr,
114 "Failed to get existing tunnel info.\n");
86bf43c7 115 free(answer);
1ce2de97
ND
116 return -1;
117 }
118
86bf43c7 119 len = answer->nlmsg_len;
1ce2de97
ND
120 len -= NLMSG_LENGTH(sizeof(*ifi));
121 if (len < 0)
122 goto get_failed;
123
86bf43c7 124 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)), len);
1ce2de97
ND
125
126 if (!tb[IFLA_LINKINFO])
127 goto get_failed;
128
129 parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
130
131 if (!linkinfo[IFLA_INFO_DATA])
132 goto get_failed;
133
134 parse_rtattr_nested(iptuninfo, IFLA_IPTUN_MAX,
135 linkinfo[IFLA_INFO_DATA]);
136
137 if (iptuninfo[IFLA_IPTUN_LOCAL])
138 laddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LOCAL]);
139
140 if (iptuninfo[IFLA_IPTUN_REMOTE])
141 raddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_REMOTE]);
142
143 if (iptuninfo[IFLA_IPTUN_TTL])
144 ttl = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]);
145
146 if (iptuninfo[IFLA_IPTUN_TOS])
147 tos = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TOS]);
148
149 if (iptuninfo[IFLA_IPTUN_PMTUDISC])
150 pmtudisc =
151 rta_getattr_u8(iptuninfo[IFLA_IPTUN_PMTUDISC]);
152
153 if (iptuninfo[IFLA_IPTUN_FLAGS])
154 iflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_FLAGS]);
155
156 if (iptuninfo[IFLA_IPTUN_LINK])
157 link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]);
158
77620be8
ND
159 if (iptuninfo[IFLA_IPTUN_PROTO])
160 proto = rta_getattr_u8(iptuninfo[IFLA_IPTUN_PROTO]);
161
c1159152
TH
162 if (iptuninfo[IFLA_IPTUN_ENCAP_TYPE])
163 encaptype = rta_getattr_u16(iptuninfo[IFLA_IPTUN_ENCAP_TYPE]);
164 if (iptuninfo[IFLA_IPTUN_ENCAP_FLAGS])
165 encapflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_ENCAP_FLAGS]);
166 if (iptuninfo[IFLA_IPTUN_ENCAP_SPORT])
167 encapsport = rta_getattr_u16(iptuninfo[IFLA_IPTUN_ENCAP_SPORT]);
168 if (iptuninfo[IFLA_IPTUN_ENCAP_DPORT])
169 encapdport = rta_getattr_u16(iptuninfo[IFLA_IPTUN_ENCAP_DPORT]);
1ce2de97
ND
170 if (iptuninfo[IFLA_IPTUN_6RD_PREFIX])
171 memcpy(&ip6rdprefix,
172 RTA_DATA(iptuninfo[IFLA_IPTUN_6RD_PREFIX]),
173 sizeof(laddr));
174
175 if (iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN])
176 ip6rdprefixlen =
177 rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]);
178
179 if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX])
180 ip6rdrelayprefix =
181 rta_getattr_u32(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]);
182
183 if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN])
184 ip6rdrelayprefixlen =
185 rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
4bfe6825
AS
186 if (iptuninfo[IFLA_IPTUN_COLLECT_METADATA])
187 metadata = 1;
ad4b1425
CG
188
189 if (iptuninfo[IFLA_IPTUN_FWMARK])
190 fwmark = rta_getattr_u32(iptuninfo[IFLA_IPTUN_FWMARK]);
191
86bf43c7 192 free(answer);
1ce2de97
ND
193 }
194
195 while (argc > 0) {
196 if (strcmp(*argv, "remote") == 0) {
197 NEXT_ARG();
198 if (strcmp(*argv, "any"))
199 raddr = get_addr32(*argv);
200 else
201 raddr = 0;
202 } else if (strcmp(*argv, "local") == 0) {
203 NEXT_ARG();
204 if (strcmp(*argv, "any"))
205 laddr = get_addr32(*argv);
206 else
207 laddr = 0;
208 } else if (matches(*argv, "dev") == 0) {
209 NEXT_ARG();
210 link = if_nametoindex(*argv);
211 if (link == 0)
212 invarg("\"dev\" is invalid", *argv);
213 } else if (strcmp(*argv, "ttl") == 0 ||
214 strcmp(*argv, "hoplimit") == 0) {
215 NEXT_ARG();
216 if (strcmp(*argv, "inherit") != 0) {
217 if (get_u8(&ttl, *argv, 0))
218 invarg("invalid TTL\n", *argv);
219 } else
220 ttl = 0;
221 } else if (strcmp(*argv, "tos") == 0 ||
222 strcmp(*argv, "tclass") == 0 ||
223 matches(*argv, "dsfield") == 0) {
224 __u32 uval;
56f5daac 225
1ce2de97
ND
226 NEXT_ARG();
227 if (strcmp(*argv, "inherit") != 0) {
228 if (rtnl_dsfield_a2n(&uval, *argv))
229 invarg("bad TOS value", *argv);
230 tos = uval;
231 } else
232 tos = 1;
233 } else if (strcmp(*argv, "nopmtudisc") == 0) {
234 pmtudisc = 0;
235 } else if (strcmp(*argv, "pmtudisc") == 0) {
236 pmtudisc = 1;
237 } else if (strcmp(lu->id, "sit") == 0 &&
238 strcmp(*argv, "isatap") == 0) {
239 iflags |= SIT_ISATAP;
77620be8
ND
240 } else if (strcmp(lu->id, "sit") == 0 &&
241 strcmp(*argv, "mode") == 0) {
242 NEXT_ARG();
243 if (strcmp(*argv, "ipv6/ipv4") == 0 ||
244 strcmp(*argv, "ip6ip") == 0)
245 proto = IPPROTO_IPV6;
246 else if (strcmp(*argv, "ipv4/ipv4") == 0 ||
247 strcmp(*argv, "ipip") == 0 ||
248 strcmp(*argv, "ip4ip4") == 0)
249 proto = IPPROTO_IPIP;
f005b700
KJ
250 else if (strcmp(*argv, "mpls/ipv4") == 0 ||
251 strcmp(*argv, "mplsip") == 0)
252 proto = IPPROTO_MPLS;
77620be8
ND
253 else if (strcmp(*argv, "any/ipv4") == 0 ||
254 strcmp(*argv, "any") == 0)
255 proto = 0;
256 else
257 invarg("Cannot guess tunnel mode.", *argv);
288c28bc
KJ
258 } else if (strcmp(lu->id, "ipip") == 0 &&
259 strcmp(*argv, "mode") == 0) {
260 NEXT_ARG();
261 if (strcmp(*argv, "ipv4/ipv4") == 0 ||
262 strcmp(*argv, "ipip") == 0 ||
263 strcmp(*argv, "ip4ip4") == 0)
264 proto = IPPROTO_IPIP;
265 else if (strcmp(*argv, "mpls/ipv4") == 0 ||
266 strcmp(*argv, "mplsip") == 0)
267 proto = IPPROTO_MPLS;
268 else if (strcmp(*argv, "any/ipv4") == 0 ||
269 strcmp(*argv, "any") == 0)
270 proto = 0;
271 else
272 invarg("Cannot guess tunnel mode.", *argv);
c1159152
TH
273 } else if (strcmp(*argv, "noencap") == 0) {
274 encaptype = TUNNEL_ENCAP_NONE;
275 } else if (strcmp(*argv, "encap") == 0) {
276 NEXT_ARG();
277 if (strcmp(*argv, "fou") == 0)
278 encaptype = TUNNEL_ENCAP_FOU;
279 else if (strcmp(*argv, "gue") == 0)
280 encaptype = TUNNEL_ENCAP_GUE;
281 else if (strcmp(*argv, "none") == 0)
282 encaptype = TUNNEL_ENCAP_NONE;
283 else
284 invarg("Invalid encap type.", *argv);
285 } else if (strcmp(*argv, "encap-sport") == 0) {
286 NEXT_ARG();
287 if (strcmp(*argv, "auto") == 0)
288 encapsport = 0;
289 else if (get_u16(&encapsport, *argv, 0))
290 invarg("Invalid source port.", *argv);
291 } else if (strcmp(*argv, "encap-dport") == 0) {
292 NEXT_ARG();
293 if (get_u16(&encapdport, *argv, 0))
294 invarg("Invalid destination port.", *argv);
295 } else if (strcmp(*argv, "encap-csum") == 0) {
296 encapflags |= TUNNEL_ENCAP_FLAG_CSUM;
297 } else if (strcmp(*argv, "noencap-csum") == 0) {
298 encapflags &= ~TUNNEL_ENCAP_FLAG_CSUM;
299 } else if (strcmp(*argv, "encap-udp6-csum") == 0) {
300 encapflags |= TUNNEL_ENCAP_FLAG_CSUM6;
301 } else if (strcmp(*argv, "noencap-udp6-csum") == 0) {
302 encapflags &= ~TUNNEL_ENCAP_FLAG_CSUM6;
858dbb20
TH
303 } else if (strcmp(*argv, "encap-remcsum") == 0) {
304 encapflags |= TUNNEL_ENCAP_FLAG_REMCSUM;
305 } else if (strcmp(*argv, "noencap-remcsum") == 0) {
306 encapflags &= ~TUNNEL_ENCAP_FLAG_REMCSUM;
4bfe6825
AS
307 } else if (strcmp(*argv, "external") == 0) {
308 metadata = 1;
1ce2de97
ND
309 } else if (strcmp(*argv, "6rd-prefix") == 0) {
310 inet_prefix prefix;
56f5daac 311
1ce2de97
ND
312 NEXT_ARG();
313 if (get_prefix(&prefix, *argv, AF_INET6))
314 invarg("invalid 6rd_prefix\n", *argv);
315 memcpy(&ip6rdprefix, prefix.data, 16);
316 ip6rdprefixlen = prefix.bitlen;
317 } else if (strcmp(*argv, "6rd-relay_prefix") == 0) {
318 inet_prefix prefix;
56f5daac 319
1ce2de97
ND
320 NEXT_ARG();
321 if (get_prefix(&prefix, *argv, AF_INET))
322 invarg("invalid 6rd-relay_prefix\n", *argv);
323 memcpy(&ip6rdrelayprefix, prefix.data, 4);
324 ip6rdrelayprefixlen = prefix.bitlen;
325 } else if (strcmp(*argv, "6rd-reset") == 0) {
326 inet_prefix prefix;
56f5daac 327
1ce2de97
ND
328 get_prefix(&prefix, "2002::", AF_INET6);
329 memcpy(&ip6rdprefix, prefix.data, 16);
330 ip6rdprefixlen = 16;
331 ip6rdrelayprefix = 0;
332 ip6rdrelayprefixlen = 0;
ad4b1425
CG
333 } else if (strcmp(*argv, "fwmark") == 0) {
334 NEXT_ARG();
335 if (get_u32(&fwmark, *argv, 0))
336 invarg("invalid fwmark\n", *argv);
1ce2de97
ND
337 } else
338 usage(strcmp(lu->id, "sit") == 0);
339 argc--, argv++;
340 }
341
342 if (ttl && pmtudisc == 0) {
30d07e9e 343 fprintf(stderr, "ttl != 0 and nopmtudisc are incompatible\n");
1ce2de97
ND
344 exit(-1);
345 }
346
4bfe6825
AS
347 if (metadata) {
348 addattr_l(n, 1024, IFLA_IPTUN_COLLECT_METADATA, NULL, 0);
349 return 0;
350 }
351
1ce2de97
ND
352 addattr32(n, 1024, IFLA_IPTUN_LINK, link);
353 addattr32(n, 1024, IFLA_IPTUN_LOCAL, laddr);
354 addattr32(n, 1024, IFLA_IPTUN_REMOTE, raddr);
355 addattr8(n, 1024, IFLA_IPTUN_TTL, ttl);
356 addattr8(n, 1024, IFLA_IPTUN_TOS, tos);
357 addattr8(n, 1024, IFLA_IPTUN_PMTUDISC, pmtudisc);
ad4b1425 358 addattr32(n, 1024, IFLA_IPTUN_FWMARK, fwmark);
c1159152
TH
359
360 addattr16(n, 1024, IFLA_IPTUN_ENCAP_TYPE, encaptype);
361 addattr16(n, 1024, IFLA_IPTUN_ENCAP_FLAGS, encapflags);
362 addattr16(n, 1024, IFLA_IPTUN_ENCAP_SPORT, htons(encapsport));
363 addattr16(n, 1024, IFLA_IPTUN_ENCAP_DPORT, htons(encapdport));
364
288c28bc
KJ
365 if (strcmp(lu->id, "ipip") == 0 || strcmp(lu->id, "sit") == 0)
366 addattr8(n, 1024, IFLA_IPTUN_PROTO, proto);
367
1ce2de97
ND
368 if (strcmp(lu->id, "sit") == 0) {
369 addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags);
370 if (ip6rdprefixlen) {
371 addattr_l(n, 1024, IFLA_IPTUN_6RD_PREFIX,
372 &ip6rdprefix, sizeof(ip6rdprefix));
373 addattr16(n, 1024, IFLA_IPTUN_6RD_PREFIXLEN,
374 ip6rdprefixlen);
375 addattr32(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIX,
376 ip6rdrelayprefix);
377 addattr16(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
378 ip6rdrelayprefixlen);
379 }
380 }
381
382 return 0;
383}
384
385static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
386{
387 char s1[1024];
388 char s2[64];
389 const char *local = "any";
390 const char *remote = "any";
9f1370c0 391 __u16 prefixlen, type;
1ce2de97
ND
392
393 if (!tb)
394 return;
395
396 if (tb[IFLA_IPTUN_REMOTE]) {
56f5daac 397 unsigned int addr = rta_getattr_u32(tb[IFLA_IPTUN_REMOTE]);
1ce2de97
ND
398
399 if (addr)
a418e451 400 remote = format_host(AF_INET, 4, &addr);
1ce2de97
ND
401 }
402
2539a407 403 print_string(PRINT_ANY, "remote", "remote %s ", remote);
1ce2de97
ND
404
405 if (tb[IFLA_IPTUN_LOCAL]) {
56f5daac 406 unsigned int addr = rta_getattr_u32(tb[IFLA_IPTUN_LOCAL]);
1ce2de97
ND
407
408 if (addr)
a418e451 409 local = format_host(AF_INET, 4, &addr);
1ce2de97
ND
410 }
411
2539a407 412 print_string(PRINT_ANY, "local", "local %s ", local);
1ce2de97
ND
413
414 if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
56f5daac 415 unsigned int link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);
1ce2de97
ND
416 const char *n = if_indextoname(link, s2);
417
418 if (n)
2539a407 419 print_string(PRINT_ANY, "link", "dev %s ", n);
1ce2de97 420 else
2539a407 421 print_int(PRINT_ANY, "link_index", "dev %u ", link);
1ce2de97
ND
422 }
423
2539a407
JF
424 if (tb[IFLA_IPTUN_TTL]) {
425 __u8 ttl = rta_getattr_u8(tb[IFLA_IPTUN_TTL]);
426
427 if (ttl)
428 print_int(PRINT_ANY, "ttl", "ttl %d ", ttl);
429 else
430 print_int(PRINT_JSON, "ttl", NULL, ttl);
431 } else {
432 print_string(PRINT_FP, NULL, "ttl %s ", "inherit");
433 }
1ce2de97 434
2539a407 435 if (tb[IFLA_IPTUN_TOS]) {
1ce2de97
ND
436 int tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]);
437
2539a407
JF
438 if (tos) {
439 if (is_json_context()) {
440 print_0xhex(PRINT_JSON, "tos", "%#x", tos);
441 } else {
442 fputs("tos ", f);
443 if (tos == 1)
444 fputs("inherit ", f);
445 else
446 fprintf(f, "0x%x ", tos);
447 }
448 }
1ce2de97
ND
449 }
450
451 if (tb[IFLA_IPTUN_PMTUDISC] && rta_getattr_u8(tb[IFLA_IPTUN_PMTUDISC]))
2539a407 452 print_bool(PRINT_ANY, "pmtudisc", "pmtudisc ", true);
1ce2de97 453 else
2539a407 454 print_bool(PRINT_ANY, "pmtudisc", "nopmtudisc ", false);
1ce2de97
ND
455
456 if (tb[IFLA_IPTUN_FLAGS]) {
195f0f62 457 __u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]);
1ce2de97 458
195f0f62 459 if (iflags & SIT_ISATAP)
2539a407 460 print_bool(PRINT_ANY, "isatap", "isatap ", true);
1ce2de97
ND
461 }
462
463 if (tb[IFLA_IPTUN_6RD_PREFIXLEN] &&
9f1370c0 464 (prefixlen = rta_getattr_u16(tb[IFLA_IPTUN_6RD_PREFIXLEN]))) {
1ce2de97
ND
465 __u16 relayprefixlen =
466 rta_getattr_u16(tb[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
467 __u32 relayprefix =
468 rta_getattr_u32(tb[IFLA_IPTUN_6RD_RELAY_PREFIX]);
469
2539a407
JF
470 const char *prefix = inet_ntop(AF_INET6,
471 RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]),
472 s1, sizeof(s1));
473
474 if (is_json_context()) {
475 print_string(PRINT_JSON, "prefix", NULL, prefix);
476 print_int(PRINT_JSON, "prefixlen", NULL, prefixlen);
477 if (relayprefix) {
478 print_string(PRINT_JSON,
479 "relay_prefix",
480 NULL,
481 format_host(AF_INET,
482 4,
483 &relayprefix));
484 print_int(PRINT_JSON,
485 "relay_prefixlen",
486 NULL,
487 relayprefixlen);
488 }
489 } else {
490 printf("6rd-prefix %s/%u ", prefix, prefixlen);
491 if (relayprefix) {
492 printf("6rd-relay_prefix %s/%u ",
493 format_host(AF_INET, 4, &relayprefix),
494 relayprefixlen);
495 }
1ce2de97
ND
496 }
497 }
c1159152
TH
498
499 if (tb[IFLA_IPTUN_ENCAP_TYPE] &&
9f1370c0 500 (type = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_TYPE])) != TUNNEL_ENCAP_NONE) {
c1159152
TH
501 __u16 flags = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_FLAGS]);
502 __u16 sport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_SPORT]);
503 __u16 dport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_DPORT]);
504
2539a407 505 print_string(PRINT_FP, NULL, "encap ", NULL);
c1159152
TH
506 switch (type) {
507 case TUNNEL_ENCAP_FOU:
2539a407 508 print_string(PRINT_ANY, "type", "%s ", "fou");
c1159152
TH
509 break;
510 case TUNNEL_ENCAP_GUE:
2539a407 511 print_string(PRINT_ANY, "type", "%s ", "gue");
c1159152
TH
512 break;
513 default:
2539a407 514 print_null(PRINT_ANY, "type", "unknown ", NULL);
c1159152
TH
515 break;
516 }
517
2539a407
JF
518 if (is_json_context()) {
519 print_uint(PRINT_JSON,
520 "sport",
521 NULL,
522 sport ? ntohs(sport) : 0);
523 print_uint(PRINT_JSON, "dport", NULL, ntohs(dport));
524 print_bool(PRINT_JSON,
525 "csum",
526 NULL,
527 flags & TUNNEL_ENCAP_FLAG_CSUM);
528 print_bool(PRINT_JSON,
529 "csum6",
530 NULL,
531 flags & TUNNEL_ENCAP_FLAG_CSUM6);
532 print_bool(PRINT_JSON,
533 "remcsum",
534 NULL,
535 flags & TUNNEL_ENCAP_FLAG_REMCSUM);
536 close_json_object();
537 } else {
538 if (sport == 0)
539 fputs("encap-sport auto ", f);
540 else
541 fprintf(f, "encap-sport %u", ntohs(sport));
c1159152 542
2539a407 543 fprintf(f, "encap-dport %u ", ntohs(dport));
c1159152 544
2539a407
JF
545 if (flags & TUNNEL_ENCAP_FLAG_CSUM)
546 fputs("encap-csum ", f);
547 else
548 fputs("noencap-csum ", f);
c1159152 549
2539a407
JF
550 if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
551 fputs("encap-csum6 ", f);
552 else
553 fputs("noencap-csum6 ", f);
858dbb20 554
2539a407
JF
555 if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
556 fputs("encap-remcsum ", f);
557 else
558 fputs("noencap-remcsum ", f);
559 }
c1159152 560 }
ad4b1425 561
2539a407
JF
562 if (tb[IFLA_IPTUN_FWMARK]) {
563 __u32 fwmark = rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]);
564
565 if (fwmark) {
566 snprintf(s2, sizeof(s2), "0x%x", fwmark);
567
568 print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2);
569 }
570 }
1ce2de97
ND
571}
572
561e650e 573static void iptunnel_print_help(struct link_util *lu, int argc, char **argv,
574 FILE *f)
575{
576 print_usage(f, strcmp(lu->id, "sit") == 0);
577}
578
1ce2de97
ND
579struct link_util ipip_link_util = {
580 .id = "ipip",
581 .maxattr = IFLA_IPTUN_MAX,
582 .parse_opt = iptunnel_parse_opt,
583 .print_opt = iptunnel_print_opt,
561e650e 584 .print_help = iptunnel_print_help,
1ce2de97
ND
585};
586
587struct link_util sit_link_util = {
588 .id = "sit",
589 .maxattr = IFLA_IPTUN_MAX,
590 .parse_opt = iptunnel_parse_opt,
591 .print_opt = iptunnel_print_opt,
561e650e 592 .print_help = iptunnel_print_help,
1ce2de97 593};