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