]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/link_iptnl.c
utils: ll_addr: Handle ARPHRD_IP6GRE in ll_addr_n2a()
[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();
57daab1e 198 raddr = get_addr32(*argv);
1ce2de97
ND
199 } else if (strcmp(*argv, "local") == 0) {
200 NEXT_ARG();
57daab1e 201 laddr = get_addr32(*argv);
1ce2de97
ND
202 } else if (matches(*argv, "dev") == 0) {
203 NEXT_ARG();
204 link = if_nametoindex(*argv);
205 if (link == 0)
206 invarg("\"dev\" is invalid", *argv);
207 } else if (strcmp(*argv, "ttl") == 0 ||
208 strcmp(*argv, "hoplimit") == 0) {
209 NEXT_ARG();
210 if (strcmp(*argv, "inherit") != 0) {
211 if (get_u8(&ttl, *argv, 0))
212 invarg("invalid TTL\n", *argv);
213 } else
214 ttl = 0;
215 } else if (strcmp(*argv, "tos") == 0 ||
216 strcmp(*argv, "tclass") == 0 ||
217 matches(*argv, "dsfield") == 0) {
218 __u32 uval;
56f5daac 219
1ce2de97
ND
220 NEXT_ARG();
221 if (strcmp(*argv, "inherit") != 0) {
222 if (rtnl_dsfield_a2n(&uval, *argv))
223 invarg("bad TOS value", *argv);
224 tos = uval;
225 } else
226 tos = 1;
227 } else if (strcmp(*argv, "nopmtudisc") == 0) {
228 pmtudisc = 0;
229 } else if (strcmp(*argv, "pmtudisc") == 0) {
230 pmtudisc = 1;
231 } else if (strcmp(lu->id, "sit") == 0 &&
232 strcmp(*argv, "isatap") == 0) {
233 iflags |= SIT_ISATAP;
77620be8
ND
234 } else if (strcmp(lu->id, "sit") == 0 &&
235 strcmp(*argv, "mode") == 0) {
236 NEXT_ARG();
237 if (strcmp(*argv, "ipv6/ipv4") == 0 ||
238 strcmp(*argv, "ip6ip") == 0)
239 proto = IPPROTO_IPV6;
240 else if (strcmp(*argv, "ipv4/ipv4") == 0 ||
241 strcmp(*argv, "ipip") == 0 ||
242 strcmp(*argv, "ip4ip4") == 0)
243 proto = IPPROTO_IPIP;
f005b700
KJ
244 else if (strcmp(*argv, "mpls/ipv4") == 0 ||
245 strcmp(*argv, "mplsip") == 0)
246 proto = IPPROTO_MPLS;
77620be8
ND
247 else if (strcmp(*argv, "any/ipv4") == 0 ||
248 strcmp(*argv, "any") == 0)
249 proto = 0;
250 else
251 invarg("Cannot guess tunnel mode.", *argv);
288c28bc
KJ
252 } else if (strcmp(lu->id, "ipip") == 0 &&
253 strcmp(*argv, "mode") == 0) {
254 NEXT_ARG();
255 if (strcmp(*argv, "ipv4/ipv4") == 0 ||
256 strcmp(*argv, "ipip") == 0 ||
257 strcmp(*argv, "ip4ip4") == 0)
258 proto = IPPROTO_IPIP;
259 else if (strcmp(*argv, "mpls/ipv4") == 0 ||
260 strcmp(*argv, "mplsip") == 0)
261 proto = IPPROTO_MPLS;
262 else if (strcmp(*argv, "any/ipv4") == 0 ||
263 strcmp(*argv, "any") == 0)
264 proto = 0;
265 else
266 invarg("Cannot guess tunnel mode.", *argv);
c1159152
TH
267 } else if (strcmp(*argv, "noencap") == 0) {
268 encaptype = TUNNEL_ENCAP_NONE;
269 } else if (strcmp(*argv, "encap") == 0) {
270 NEXT_ARG();
271 if (strcmp(*argv, "fou") == 0)
272 encaptype = TUNNEL_ENCAP_FOU;
273 else if (strcmp(*argv, "gue") == 0)
274 encaptype = TUNNEL_ENCAP_GUE;
275 else if (strcmp(*argv, "none") == 0)
276 encaptype = TUNNEL_ENCAP_NONE;
277 else
278 invarg("Invalid encap type.", *argv);
279 } else if (strcmp(*argv, "encap-sport") == 0) {
280 NEXT_ARG();
281 if (strcmp(*argv, "auto") == 0)
282 encapsport = 0;
283 else if (get_u16(&encapsport, *argv, 0))
284 invarg("Invalid source port.", *argv);
285 } else if (strcmp(*argv, "encap-dport") == 0) {
286 NEXT_ARG();
287 if (get_u16(&encapdport, *argv, 0))
288 invarg("Invalid destination port.", *argv);
289 } else if (strcmp(*argv, "encap-csum") == 0) {
290 encapflags |= TUNNEL_ENCAP_FLAG_CSUM;
291 } else if (strcmp(*argv, "noencap-csum") == 0) {
292 encapflags &= ~TUNNEL_ENCAP_FLAG_CSUM;
293 } else if (strcmp(*argv, "encap-udp6-csum") == 0) {
294 encapflags |= TUNNEL_ENCAP_FLAG_CSUM6;
295 } else if (strcmp(*argv, "noencap-udp6-csum") == 0) {
296 encapflags &= ~TUNNEL_ENCAP_FLAG_CSUM6;
858dbb20
TH
297 } else if (strcmp(*argv, "encap-remcsum") == 0) {
298 encapflags |= TUNNEL_ENCAP_FLAG_REMCSUM;
299 } else if (strcmp(*argv, "noencap-remcsum") == 0) {
300 encapflags &= ~TUNNEL_ENCAP_FLAG_REMCSUM;
4bfe6825
AS
301 } else if (strcmp(*argv, "external") == 0) {
302 metadata = 1;
1ce2de97
ND
303 } else if (strcmp(*argv, "6rd-prefix") == 0) {
304 inet_prefix prefix;
56f5daac 305
1ce2de97
ND
306 NEXT_ARG();
307 if (get_prefix(&prefix, *argv, AF_INET6))
308 invarg("invalid 6rd_prefix\n", *argv);
309 memcpy(&ip6rdprefix, prefix.data, 16);
310 ip6rdprefixlen = prefix.bitlen;
311 } else if (strcmp(*argv, "6rd-relay_prefix") == 0) {
312 inet_prefix prefix;
56f5daac 313
1ce2de97
ND
314 NEXT_ARG();
315 if (get_prefix(&prefix, *argv, AF_INET))
316 invarg("invalid 6rd-relay_prefix\n", *argv);
317 memcpy(&ip6rdrelayprefix, prefix.data, 4);
318 ip6rdrelayprefixlen = prefix.bitlen;
319 } else if (strcmp(*argv, "6rd-reset") == 0) {
320 inet_prefix prefix;
56f5daac 321
1ce2de97
ND
322 get_prefix(&prefix, "2002::", AF_INET6);
323 memcpy(&ip6rdprefix, prefix.data, 16);
324 ip6rdprefixlen = 16;
325 ip6rdrelayprefix = 0;
326 ip6rdrelayprefixlen = 0;
ad4b1425
CG
327 } else if (strcmp(*argv, "fwmark") == 0) {
328 NEXT_ARG();
329 if (get_u32(&fwmark, *argv, 0))
330 invarg("invalid fwmark\n", *argv);
1ce2de97
ND
331 } else
332 usage(strcmp(lu->id, "sit") == 0);
333 argc--, argv++;
334 }
335
336 if (ttl && pmtudisc == 0) {
30d07e9e 337 fprintf(stderr, "ttl != 0 and nopmtudisc are incompatible\n");
1ce2de97
ND
338 exit(-1);
339 }
340
4bfe6825
AS
341 if (metadata) {
342 addattr_l(n, 1024, IFLA_IPTUN_COLLECT_METADATA, NULL, 0);
343 return 0;
344 }
345
1ce2de97
ND
346 addattr32(n, 1024, IFLA_IPTUN_LINK, link);
347 addattr32(n, 1024, IFLA_IPTUN_LOCAL, laddr);
348 addattr32(n, 1024, IFLA_IPTUN_REMOTE, raddr);
349 addattr8(n, 1024, IFLA_IPTUN_TTL, ttl);
350 addattr8(n, 1024, IFLA_IPTUN_TOS, tos);
351 addattr8(n, 1024, IFLA_IPTUN_PMTUDISC, pmtudisc);
ad4b1425 352 addattr32(n, 1024, IFLA_IPTUN_FWMARK, fwmark);
c1159152
TH
353
354 addattr16(n, 1024, IFLA_IPTUN_ENCAP_TYPE, encaptype);
355 addattr16(n, 1024, IFLA_IPTUN_ENCAP_FLAGS, encapflags);
356 addattr16(n, 1024, IFLA_IPTUN_ENCAP_SPORT, htons(encapsport));
357 addattr16(n, 1024, IFLA_IPTUN_ENCAP_DPORT, htons(encapdport));
358
288c28bc
KJ
359 if (strcmp(lu->id, "ipip") == 0 || strcmp(lu->id, "sit") == 0)
360 addattr8(n, 1024, IFLA_IPTUN_PROTO, proto);
361
1ce2de97
ND
362 if (strcmp(lu->id, "sit") == 0) {
363 addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags);
364 if (ip6rdprefixlen) {
365 addattr_l(n, 1024, IFLA_IPTUN_6RD_PREFIX,
366 &ip6rdprefix, sizeof(ip6rdprefix));
367 addattr16(n, 1024, IFLA_IPTUN_6RD_PREFIXLEN,
368 ip6rdprefixlen);
369 addattr32(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIX,
370 ip6rdrelayprefix);
371 addattr16(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
372 ip6rdrelayprefixlen);
373 }
374 }
375
376 return 0;
377}
378
379static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
380{
381 char s1[1024];
382 char s2[64];
383 const char *local = "any";
384 const char *remote = "any";
9f1370c0 385 __u16 prefixlen, type;
1ce2de97
ND
386
387 if (!tb)
388 return;
389
7b178324
PD
390 if (tb[IFLA_IPTUN_COLLECT_METADATA])
391 print_bool(PRINT_ANY, "external", "external ", true);
392
1ce2de97 393 if (tb[IFLA_IPTUN_REMOTE]) {
56f5daac 394 unsigned int addr = rta_getattr_u32(tb[IFLA_IPTUN_REMOTE]);
1ce2de97
ND
395
396 if (addr)
a418e451 397 remote = format_host(AF_INET, 4, &addr);
1ce2de97
ND
398 }
399
2539a407 400 print_string(PRINT_ANY, "remote", "remote %s ", remote);
1ce2de97
ND
401
402 if (tb[IFLA_IPTUN_LOCAL]) {
56f5daac 403 unsigned int addr = rta_getattr_u32(tb[IFLA_IPTUN_LOCAL]);
1ce2de97
ND
404
405 if (addr)
a418e451 406 local = format_host(AF_INET, 4, &addr);
1ce2de97
ND
407 }
408
2539a407 409 print_string(PRINT_ANY, "local", "local %s ", local);
1ce2de97
ND
410
411 if (tb[IFLA_IPTUN_LINK] && rta_getattr_u32(tb[IFLA_IPTUN_LINK])) {
56f5daac 412 unsigned int link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);
1ce2de97
ND
413 const char *n = if_indextoname(link, s2);
414
415 if (n)
2539a407 416 print_string(PRINT_ANY, "link", "dev %s ", n);
1ce2de97 417 else
2539a407 418 print_int(PRINT_ANY, "link_index", "dev %u ", link);
1ce2de97
ND
419 }
420
2539a407
JF
421 if (tb[IFLA_IPTUN_TTL]) {
422 __u8 ttl = rta_getattr_u8(tb[IFLA_IPTUN_TTL]);
423
424 if (ttl)
425 print_int(PRINT_ANY, "ttl", "ttl %d ", ttl);
426 else
427 print_int(PRINT_JSON, "ttl", NULL, ttl);
428 } else {
429 print_string(PRINT_FP, NULL, "ttl %s ", "inherit");
430 }
1ce2de97 431
2539a407 432 if (tb[IFLA_IPTUN_TOS]) {
1ce2de97
ND
433 int tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]);
434
2539a407
JF
435 if (tos) {
436 if (is_json_context()) {
437 print_0xhex(PRINT_JSON, "tos", "%#x", tos);
438 } else {
439 fputs("tos ", f);
440 if (tos == 1)
441 fputs("inherit ", f);
442 else
443 fprintf(f, "0x%x ", tos);
444 }
445 }
1ce2de97
ND
446 }
447
448 if (tb[IFLA_IPTUN_PMTUDISC] && rta_getattr_u8(tb[IFLA_IPTUN_PMTUDISC]))
2539a407 449 print_bool(PRINT_ANY, "pmtudisc", "pmtudisc ", true);
1ce2de97 450 else
2539a407 451 print_bool(PRINT_ANY, "pmtudisc", "nopmtudisc ", false);
1ce2de97
ND
452
453 if (tb[IFLA_IPTUN_FLAGS]) {
195f0f62 454 __u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]);
1ce2de97 455
195f0f62 456 if (iflags & SIT_ISATAP)
2539a407 457 print_bool(PRINT_ANY, "isatap", "isatap ", true);
1ce2de97
ND
458 }
459
460 if (tb[IFLA_IPTUN_6RD_PREFIXLEN] &&
9f1370c0 461 (prefixlen = rta_getattr_u16(tb[IFLA_IPTUN_6RD_PREFIXLEN]))) {
1ce2de97
ND
462 __u16 relayprefixlen =
463 rta_getattr_u16(tb[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
464 __u32 relayprefix =
465 rta_getattr_u32(tb[IFLA_IPTUN_6RD_RELAY_PREFIX]);
466
2539a407
JF
467 const char *prefix = inet_ntop(AF_INET6,
468 RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]),
469 s1, sizeof(s1));
470
471 if (is_json_context()) {
472 print_string(PRINT_JSON, "prefix", NULL, prefix);
473 print_int(PRINT_JSON, "prefixlen", NULL, prefixlen);
474 if (relayprefix) {
475 print_string(PRINT_JSON,
476 "relay_prefix",
477 NULL,
478 format_host(AF_INET,
479 4,
480 &relayprefix));
481 print_int(PRINT_JSON,
482 "relay_prefixlen",
483 NULL,
484 relayprefixlen);
485 }
486 } else {
487 printf("6rd-prefix %s/%u ", prefix, prefixlen);
488 if (relayprefix) {
489 printf("6rd-relay_prefix %s/%u ",
490 format_host(AF_INET, 4, &relayprefix),
491 relayprefixlen);
492 }
1ce2de97
ND
493 }
494 }
c1159152
TH
495
496 if (tb[IFLA_IPTUN_ENCAP_TYPE] &&
9f1370c0 497 (type = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_TYPE])) != TUNNEL_ENCAP_NONE) {
c1159152
TH
498 __u16 flags = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_FLAGS]);
499 __u16 sport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_SPORT]);
500 __u16 dport = rta_getattr_u16(tb[IFLA_IPTUN_ENCAP_DPORT]);
501
2539a407 502 print_string(PRINT_FP, NULL, "encap ", NULL);
c1159152
TH
503 switch (type) {
504 case TUNNEL_ENCAP_FOU:
2539a407 505 print_string(PRINT_ANY, "type", "%s ", "fou");
c1159152
TH
506 break;
507 case TUNNEL_ENCAP_GUE:
2539a407 508 print_string(PRINT_ANY, "type", "%s ", "gue");
c1159152
TH
509 break;
510 default:
2539a407 511 print_null(PRINT_ANY, "type", "unknown ", NULL);
c1159152
TH
512 break;
513 }
514
2539a407
JF
515 if (is_json_context()) {
516 print_uint(PRINT_JSON,
517 "sport",
518 NULL,
519 sport ? ntohs(sport) : 0);
520 print_uint(PRINT_JSON, "dport", NULL, ntohs(dport));
521 print_bool(PRINT_JSON,
522 "csum",
523 NULL,
524 flags & TUNNEL_ENCAP_FLAG_CSUM);
525 print_bool(PRINT_JSON,
526 "csum6",
527 NULL,
528 flags & TUNNEL_ENCAP_FLAG_CSUM6);
529 print_bool(PRINT_JSON,
530 "remcsum",
531 NULL,
532 flags & TUNNEL_ENCAP_FLAG_REMCSUM);
533 close_json_object();
534 } else {
535 if (sport == 0)
536 fputs("encap-sport auto ", f);
537 else
538 fprintf(f, "encap-sport %u", ntohs(sport));
c1159152 539
2539a407 540 fprintf(f, "encap-dport %u ", ntohs(dport));
c1159152 541
2539a407
JF
542 if (flags & TUNNEL_ENCAP_FLAG_CSUM)
543 fputs("encap-csum ", f);
544 else
545 fputs("noencap-csum ", f);
c1159152 546
2539a407
JF
547 if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
548 fputs("encap-csum6 ", f);
549 else
550 fputs("noencap-csum6 ", f);
858dbb20 551
2539a407
JF
552 if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
553 fputs("encap-remcsum ", f);
554 else
555 fputs("noencap-remcsum ", f);
556 }
c1159152 557 }
ad4b1425 558
2539a407
JF
559 if (tb[IFLA_IPTUN_FWMARK]) {
560 __u32 fwmark = rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]);
561
562 if (fwmark) {
563 snprintf(s2, sizeof(s2), "0x%x", fwmark);
564
565 print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2);
566 }
567 }
1ce2de97
ND
568}
569
561e650e 570static void iptunnel_print_help(struct link_util *lu, int argc, char **argv,
571 FILE *f)
572{
573 print_usage(f, strcmp(lu->id, "sit") == 0);
574}
575
1ce2de97
ND
576struct link_util ipip_link_util = {
577 .id = "ipip",
578 .maxattr = IFLA_IPTUN_MAX,
579 .parse_opt = iptunnel_parse_opt,
580 .print_opt = iptunnel_print_opt,
561e650e 581 .print_help = iptunnel_print_help,
1ce2de97
ND
582};
583
584struct link_util sit_link_util = {
585 .id = "sit",
586 .maxattr = IFLA_IPTUN_MAX,
587 .parse_opt = iptunnel_parse_opt,
588 .print_opt = iptunnel_print_opt,
561e650e 589 .print_help = iptunnel_print_help,
1ce2de97 590};