]> git.proxmox.com Git - mirror_iproute2.git/blame - ip/link_iptnl.c
ip: Consolidate ip, xdp and lwtunnel parse/dump prototypes in ip_common.h
[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 };
08ede25f 86 struct nlmsghdr *answer;
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");
115 return -1;
116 }
117
86bf43c7 118 len = answer->nlmsg_len;
1ce2de97
ND
119 len -= NLMSG_LENGTH(sizeof(*ifi));
120 if (len < 0)
121 goto get_failed;
122
86bf43c7 123 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)), len);
1ce2de97
ND
124
125 if (!tb[IFLA_LINKINFO])
126 goto get_failed;
127
128 parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
129
130 if (!linkinfo[IFLA_INFO_DATA])
131 goto get_failed;
132
133 parse_rtattr_nested(iptuninfo, IFLA_IPTUN_MAX,
134 linkinfo[IFLA_INFO_DATA]);
135
136 if (iptuninfo[IFLA_IPTUN_LOCAL])
137 laddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LOCAL]);
138
139 if (iptuninfo[IFLA_IPTUN_REMOTE])
140 raddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_REMOTE]);
141
142 if (iptuninfo[IFLA_IPTUN_TTL])
143 ttl = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]);
144
145 if (iptuninfo[IFLA_IPTUN_TOS])
146 tos = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TOS]);
147
148 if (iptuninfo[IFLA_IPTUN_PMTUDISC])
149 pmtudisc =
150 rta_getattr_u8(iptuninfo[IFLA_IPTUN_PMTUDISC]);
151
152 if (iptuninfo[IFLA_IPTUN_FLAGS])
153 iflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_FLAGS]);
154
155 if (iptuninfo[IFLA_IPTUN_LINK])
156 link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]);
157
77620be8
ND
158 if (iptuninfo[IFLA_IPTUN_PROTO])
159 proto = rta_getattr_u8(iptuninfo[IFLA_IPTUN_PROTO]);
160
c1159152
TH
161 if (iptuninfo[IFLA_IPTUN_ENCAP_TYPE])
162 encaptype = rta_getattr_u16(iptuninfo[IFLA_IPTUN_ENCAP_TYPE]);
163 if (iptuninfo[IFLA_IPTUN_ENCAP_FLAGS])
164 encapflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_ENCAP_FLAGS]);
165 if (iptuninfo[IFLA_IPTUN_ENCAP_SPORT])
166 encapsport = rta_getattr_u16(iptuninfo[IFLA_IPTUN_ENCAP_SPORT]);
167 if (iptuninfo[IFLA_IPTUN_ENCAP_DPORT])
168 encapdport = rta_getattr_u16(iptuninfo[IFLA_IPTUN_ENCAP_DPORT]);
1ce2de97
ND
169 if (iptuninfo[IFLA_IPTUN_6RD_PREFIX])
170 memcpy(&ip6rdprefix,
171 RTA_DATA(iptuninfo[IFLA_IPTUN_6RD_PREFIX]),
172 sizeof(laddr));
173
174 if (iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN])
175 ip6rdprefixlen =
176 rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]);
177
178 if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX])
179 ip6rdrelayprefix =
180 rta_getattr_u32(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]);
181
182 if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN])
183 ip6rdrelayprefixlen =
184 rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
4bfe6825
AS
185 if (iptuninfo[IFLA_IPTUN_COLLECT_METADATA])
186 metadata = 1;
ad4b1425
CG
187
188 if (iptuninfo[IFLA_IPTUN_FWMARK])
189 fwmark = rta_getattr_u32(iptuninfo[IFLA_IPTUN_FWMARK]);
190
86bf43c7 191 free(answer);
1ce2de97
ND
192 }
193
194 while (argc > 0) {
195 if (strcmp(*argv, "remote") == 0) {
196 NEXT_ARG();
57daab1e 197 raddr = get_addr32(*argv);
1ce2de97
ND
198 } else if (strcmp(*argv, "local") == 0) {
199 NEXT_ARG();
57daab1e 200 laddr = get_addr32(*argv);
1ce2de97
ND
201 } else if (matches(*argv, "dev") == 0) {
202 NEXT_ARG();
7a14358b 203 link = ll_name_to_index(*argv);
1ce2de97
ND
204 if (link == 0)
205 invarg("\"dev\" is invalid", *argv);
206 } else if (strcmp(*argv, "ttl") == 0 ||
c4743c4d
SP
207 strcmp(*argv, "hoplimit") == 0 ||
208 strcmp(*argv, "hlim") == 0) {
1ce2de97
ND
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;
68a7f5ed 234 } else if (strcmp(*argv, "mode") == 0) {
77620be8 235 NEXT_ARG();
68a7f5ed
SP
236 if (strcmp(lu->id, "sit") == 0 &&
237 (strcmp(*argv, "ipv6/ipv4") == 0 ||
238 strcmp(*argv, "ip6ip") == 0))
77620be8
ND
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);
c1159152
TH
252 } else if (strcmp(*argv, "noencap") == 0) {
253 encaptype = TUNNEL_ENCAP_NONE;
254 } else if (strcmp(*argv, "encap") == 0) {
255 NEXT_ARG();
256 if (strcmp(*argv, "fou") == 0)
257 encaptype = TUNNEL_ENCAP_FOU;
258 else if (strcmp(*argv, "gue") == 0)
259 encaptype = TUNNEL_ENCAP_GUE;
260 else if (strcmp(*argv, "none") == 0)
261 encaptype = TUNNEL_ENCAP_NONE;
262 else
263 invarg("Invalid encap type.", *argv);
264 } else if (strcmp(*argv, "encap-sport") == 0) {
265 NEXT_ARG();
266 if (strcmp(*argv, "auto") == 0)
267 encapsport = 0;
268 else if (get_u16(&encapsport, *argv, 0))
269 invarg("Invalid source port.", *argv);
270 } else if (strcmp(*argv, "encap-dport") == 0) {
271 NEXT_ARG();
272 if (get_u16(&encapdport, *argv, 0))
273 invarg("Invalid destination port.", *argv);
274 } else if (strcmp(*argv, "encap-csum") == 0) {
275 encapflags |= TUNNEL_ENCAP_FLAG_CSUM;
276 } else if (strcmp(*argv, "noencap-csum") == 0) {
277 encapflags &= ~TUNNEL_ENCAP_FLAG_CSUM;
278 } else if (strcmp(*argv, "encap-udp6-csum") == 0) {
279 encapflags |= TUNNEL_ENCAP_FLAG_CSUM6;
280 } else if (strcmp(*argv, "noencap-udp6-csum") == 0) {
281 encapflags &= ~TUNNEL_ENCAP_FLAG_CSUM6;
858dbb20
TH
282 } else if (strcmp(*argv, "encap-remcsum") == 0) {
283 encapflags |= TUNNEL_ENCAP_FLAG_REMCSUM;
284 } else if (strcmp(*argv, "noencap-remcsum") == 0) {
285 encapflags &= ~TUNNEL_ENCAP_FLAG_REMCSUM;
4bfe6825
AS
286 } else if (strcmp(*argv, "external") == 0) {
287 metadata = 1;
1ce2de97
ND
288 } else if (strcmp(*argv, "6rd-prefix") == 0) {
289 inet_prefix prefix;
56f5daac 290
1ce2de97
ND
291 NEXT_ARG();
292 if (get_prefix(&prefix, *argv, AF_INET6))
293 invarg("invalid 6rd_prefix\n", *argv);
294 memcpy(&ip6rdprefix, prefix.data, 16);
295 ip6rdprefixlen = prefix.bitlen;
296 } else if (strcmp(*argv, "6rd-relay_prefix") == 0) {
297 inet_prefix prefix;
56f5daac 298
1ce2de97
ND
299 NEXT_ARG();
300 if (get_prefix(&prefix, *argv, AF_INET))
301 invarg("invalid 6rd-relay_prefix\n", *argv);
302 memcpy(&ip6rdrelayprefix, prefix.data, 4);
303 ip6rdrelayprefixlen = prefix.bitlen;
304 } else if (strcmp(*argv, "6rd-reset") == 0) {
305 inet_prefix prefix;
56f5daac 306
1ce2de97
ND
307 get_prefix(&prefix, "2002::", AF_INET6);
308 memcpy(&ip6rdprefix, prefix.data, 16);
309 ip6rdprefixlen = 16;
310 ip6rdrelayprefix = 0;
311 ip6rdrelayprefixlen = 0;
ad4b1425
CG
312 } else if (strcmp(*argv, "fwmark") == 0) {
313 NEXT_ARG();
314 if (get_u32(&fwmark, *argv, 0))
315 invarg("invalid fwmark\n", *argv);
1ce2de97
ND
316 } else
317 usage(strcmp(lu->id, "sit") == 0);
318 argc--, argv++;
319 }
320
321 if (ttl && pmtudisc == 0) {
30d07e9e 322 fprintf(stderr, "ttl != 0 and nopmtudisc are incompatible\n");
1ce2de97
ND
323 exit(-1);
324 }
325
68a7f5ed 326 addattr8(n, 1024, IFLA_IPTUN_PROTO, proto);
4bfe6825
AS
327 if (metadata) {
328 addattr_l(n, 1024, IFLA_IPTUN_COLLECT_METADATA, NULL, 0);
329 return 0;
330 }
331
1ce2de97
ND
332 addattr32(n, 1024, IFLA_IPTUN_LINK, link);
333 addattr32(n, 1024, IFLA_IPTUN_LOCAL, laddr);
334 addattr32(n, 1024, IFLA_IPTUN_REMOTE, raddr);
335 addattr8(n, 1024, IFLA_IPTUN_TTL, ttl);
336 addattr8(n, 1024, IFLA_IPTUN_TOS, tos);
337 addattr8(n, 1024, IFLA_IPTUN_PMTUDISC, pmtudisc);
ad4b1425 338 addattr32(n, 1024, IFLA_IPTUN_FWMARK, fwmark);
c1159152
TH
339
340 addattr16(n, 1024, IFLA_IPTUN_ENCAP_TYPE, encaptype);
341 addattr16(n, 1024, IFLA_IPTUN_ENCAP_FLAGS, encapflags);
342 addattr16(n, 1024, IFLA_IPTUN_ENCAP_SPORT, htons(encapsport));
343 addattr16(n, 1024, IFLA_IPTUN_ENCAP_DPORT, htons(encapdport));
344
1ce2de97
ND
345 if (strcmp(lu->id, "sit") == 0) {
346 addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags);
347 if (ip6rdprefixlen) {
348 addattr_l(n, 1024, IFLA_IPTUN_6RD_PREFIX,
349 &ip6rdprefix, sizeof(ip6rdprefix));
350 addattr16(n, 1024, IFLA_IPTUN_6RD_PREFIXLEN,
351 ip6rdprefixlen);
352 addattr32(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIX,
353 ip6rdrelayprefix);
354 addattr16(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIXLEN,
355 ip6rdrelayprefixlen);
356 }
357 }
358
359 return 0;
360}
361
362static void iptunnel_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
363{
1ce2de97 364 char s2[64];
bad76e6b 365 __u16 prefixlen;
375560c4 366 __u8 ttl = 0;
3caa526c 367 __u8 tos = 0;
1ce2de97
ND
368
369 if (!tb)
370 return;
371
00ff4b8e
SP
372 if (tb[IFLA_IPTUN_COLLECT_METADATA]) {
373 print_bool(PRINT_ANY, "external", "external", true);
374 return;
375 }
7b178324 376
d9aefbc0
SP
377 if (tb[IFLA_IPTUN_PROTO]) {
378 switch (rta_getattr_u8(tb[IFLA_IPTUN_PROTO])) {
379 case IPPROTO_IPIP:
380 print_string(PRINT_ANY, "proto", "%s ", "ipip");
381 break;
382 case IPPROTO_IPV6:
383 print_string(PRINT_ANY, "proto", "%s ", "ip6ip");
384 break;
385 case IPPROTO_MPLS:
386 print_string(PRINT_ANY, "proto", "%s ", "mplsip");
387 break;
388 case 0:
389 print_string(PRINT_ANY, "proto", "%s ", "any");
390 break;
391 }
392 }
393
b761fc41
SP
394 tnl_print_endpoint("remote", tb[IFLA_IPTUN_REMOTE], AF_INET);
395 tnl_print_endpoint("local", tb[IFLA_IPTUN_LOCAL], AF_INET);
1ce2de97 396
45d3a6ef 397 if (tb[IFLA_IPTUN_LINK]) {
56f5daac 398 unsigned int link = rta_getattr_u32(tb[IFLA_IPTUN_LINK]);
1ce2de97 399
45d3a6ef
SP
400 if (link) {
401 print_string(PRINT_ANY, "link", "dev %s ",
402 ll_index_to_name(link));
403 }
1ce2de97
ND
404 }
405
375560c4
SP
406 if (tb[IFLA_IPTUN_TTL])
407 ttl = rta_getattr_u8(tb[IFLA_IPTUN_TTL]);
408 if (is_json_context() || ttl)
409 print_uint(PRINT_ANY, "ttl", "ttl %u ", ttl);
410 else
2539a407 411 print_string(PRINT_FP, NULL, "ttl %s ", "inherit");
1ce2de97 412
3caa526c
SP
413 if (tb[IFLA_IPTUN_TOS])
414 tos = rta_getattr_u8(tb[IFLA_IPTUN_TOS]);
415 if (tos) {
416 if (is_json_context() || tos != 1)
417 print_0xhex(PRINT_ANY, "tos", "tos 0x%x ", tos);
418 else
419 print_string(PRINT_FP, NULL, "tos %s ", "inherit");
1ce2de97
ND
420 }
421
422 if (tb[IFLA_IPTUN_PMTUDISC] && rta_getattr_u8(tb[IFLA_IPTUN_PMTUDISC]))
2539a407 423 print_bool(PRINT_ANY, "pmtudisc", "pmtudisc ", true);
1ce2de97 424 else
2539a407 425 print_bool(PRINT_ANY, "pmtudisc", "nopmtudisc ", false);
1ce2de97
ND
426
427 if (tb[IFLA_IPTUN_FLAGS]) {
195f0f62 428 __u16 iflags = rta_getattr_u16(tb[IFLA_IPTUN_FLAGS]);
1ce2de97 429
195f0f62 430 if (iflags & SIT_ISATAP)
2539a407 431 print_bool(PRINT_ANY, "isatap", "isatap ", true);
1ce2de97
ND
432 }
433
434 if (tb[IFLA_IPTUN_6RD_PREFIXLEN] &&
9f1370c0 435 (prefixlen = rta_getattr_u16(tb[IFLA_IPTUN_6RD_PREFIXLEN]))) {
1ce2de97
ND
436 __u16 relayprefixlen =
437 rta_getattr_u16(tb[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]);
438 __u32 relayprefix =
439 rta_getattr_u32(tb[IFLA_IPTUN_6RD_RELAY_PREFIX]);
440
2539a407
JF
441 const char *prefix = inet_ntop(AF_INET6,
442 RTA_DATA(tb[IFLA_IPTUN_6RD_PREFIX]),
e97ad3d2 443 s2, sizeof(s2));
2539a407
JF
444
445 if (is_json_context()) {
446 print_string(PRINT_JSON, "prefix", NULL, prefix);
447 print_int(PRINT_JSON, "prefixlen", NULL, prefixlen);
448 if (relayprefix) {
449 print_string(PRINT_JSON,
450 "relay_prefix",
451 NULL,
452 format_host(AF_INET,
453 4,
454 &relayprefix));
455 print_int(PRINT_JSON,
456 "relay_prefixlen",
457 NULL,
458 relayprefixlen);
459 }
460 } else {
461 printf("6rd-prefix %s/%u ", prefix, prefixlen);
462 if (relayprefix) {
463 printf("6rd-relay_prefix %s/%u ",
464 format_host(AF_INET, 4, &relayprefix),
465 relayprefixlen);
466 }
1ce2de97
ND
467 }
468 }
c1159152 469
e97ad3d2
SP
470 if (tb[IFLA_IPTUN_FWMARK]) {
471 __u32 fwmark = rta_getattr_u32(tb[IFLA_IPTUN_FWMARK]);
472
473 if (fwmark) {
474 print_0xhex(PRINT_ANY,
475 "fwmark", "fwmark 0x%x ", fwmark);
476 }
477 }
478
bad76e6b
SP
479 tnl_print_encap(tb,
480 IFLA_IPTUN_ENCAP_TYPE,
481 IFLA_IPTUN_ENCAP_FLAGS,
482 IFLA_IPTUN_ENCAP_SPORT,
483 IFLA_IPTUN_ENCAP_DPORT);
1ce2de97
ND
484}
485
561e650e 486static void iptunnel_print_help(struct link_util *lu, int argc, char **argv,
487 FILE *f)
488{
489 print_usage(f, strcmp(lu->id, "sit") == 0);
490}
491
1ce2de97
ND
492struct link_util ipip_link_util = {
493 .id = "ipip",
494 .maxattr = IFLA_IPTUN_MAX,
495 .parse_opt = iptunnel_parse_opt,
496 .print_opt = iptunnel_print_opt,
561e650e 497 .print_help = iptunnel_print_help,
1ce2de97
ND
498};
499
500struct link_util sit_link_util = {
501 .id = "sit",
502 .maxattr = IFLA_IPTUN_MAX,
503 .parse_opt = iptunnel_parse_opt,
504 .print_opt = iptunnel_print_opt,
561e650e 505 .print_help = iptunnel_print_help,
1ce2de97 506};