2 * link_gre.c gre driver module
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.
9 * Authors: Herbert Xu <herbert@gondor.apana.org.au>
15 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <arpa/inet.h>
20 #include <linux/if_tunnel.h>
23 #include "ip_common.h"
26 static void usage(void) __attribute__((noreturn
));
27 static void usage(void)
29 fprintf(stderr
, "Usage: ip link { add | set | change | replace | del } NAME\n");
30 fprintf(stderr
, " type { gre | gretap } [ remote ADDR ] [ local ADDR ]\n");
31 fprintf(stderr
, " [ [i|o]seq ] [ [i|o]key KEY ] [ [i|o]csum ]\n");
32 fprintf(stderr
, " [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n");
33 fprintf(stderr
, "\n");
34 fprintf(stderr
, "Where: NAME := STRING\n");
35 fprintf(stderr
, " ADDR := { IP_ADDRESS | any }\n");
36 fprintf(stderr
, " TOS := { NUMBER | inherit }\n");
37 fprintf(stderr
, " TTL := { 1..255 | inherit }\n");
38 fprintf(stderr
, " KEY := { DOTTED_QUAD | NUMBER }\n");
42 static int gre_parse_opt(struct link_util
*lu
, int argc
, char **argv
,
50 struct ifinfomsg
*ifi
= (struct ifinfomsg
*)(n
+ 1);
51 struct rtattr
*tb
[IFLA_MAX
+ 1];
52 struct rtattr
*linkinfo
[IFLA_INFO_MAX
+1];
53 struct rtattr
*greinfo
[IFLA_GRE_MAX
+ 1];
66 if (!(n
->nlmsg_flags
& NLM_F_CREATE
)) {
67 memset(&req
, 0, sizeof(req
));
69 req
.n
.nlmsg_len
= NLMSG_LENGTH(sizeof(*ifi
));
70 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
71 req
.n
.nlmsg_type
= RTM_GETLINK
;
72 req
.i
.ifi_family
= preferred_family
;
73 req
.i
.ifi_index
= ifi
->ifi_index
;
75 if (rtnl_talk(&rth
, &req
.n
, 0, 0, &req
.n
, NULL
, NULL
) < 0) {
78 "Failed to get existing tunnel info.\n");
82 len
= req
.n
.nlmsg_len
;
83 len
-= NLMSG_LENGTH(sizeof(*ifi
));
87 parse_rtattr(tb
, IFLA_MAX
, IFLA_RTA(&req
.i
), len
);
89 if (!tb
[IFLA_LINKINFO
])
92 parse_rtattr_nested(linkinfo
, IFLA_INFO_MAX
, tb
[IFLA_LINKINFO
]);
94 if (!linkinfo
[IFLA_INFO_DATA
])
97 parse_rtattr_nested(greinfo
, IFLA_GRE_MAX
,
98 linkinfo
[IFLA_INFO_DATA
]);
100 if (greinfo
[IFLA_GRE_IKEY
])
101 ikey
= *(__u32
*)RTA_DATA(greinfo
[IFLA_GRE_IKEY
]);
103 if (greinfo
[IFLA_GRE_OKEY
])
104 okey
= *(__u32
*)RTA_DATA(greinfo
[IFLA_GRE_OKEY
]);
106 if (greinfo
[IFLA_GRE_IFLAGS
])
107 iflags
= *(__u16
*)RTA_DATA(greinfo
[IFLA_GRE_IFLAGS
]);
109 if (greinfo
[IFLA_GRE_OFLAGS
])
110 oflags
= *(__u16
*)RTA_DATA(greinfo
[IFLA_GRE_OFLAGS
]);
112 if (greinfo
[IFLA_GRE_LOCAL
])
113 saddr
= *(__u32
*)RTA_DATA(greinfo
[IFLA_GRE_LOCAL
]);
115 if (greinfo
[IFLA_GRE_REMOTE
])
116 daddr
= *(__u32
*)RTA_DATA(greinfo
[IFLA_GRE_REMOTE
]);
118 if (greinfo
[IFLA_GRE_PMTUDISC
])
119 pmtudisc
= *(__u8
*)RTA_DATA(
120 greinfo
[IFLA_GRE_PMTUDISC
]);
122 if (greinfo
[IFLA_GRE_TTL
])
123 ttl
= *(__u8
*)RTA_DATA(greinfo
[IFLA_GRE_TTL
]);
125 if (greinfo
[IFLA_GRE_TOS
])
126 tos
= *(__u8
*)RTA_DATA(greinfo
[IFLA_GRE_TOS
]);
128 if (greinfo
[IFLA_GRE_LINK
])
129 link
= *(__u8
*)RTA_DATA(greinfo
[IFLA_GRE_LINK
]);
133 if (!matches(*argv
, "key")) {
139 if (strchr(*argv
, '.'))
140 uval
= get_addr32(*argv
);
142 if (get_unsigned(&uval
, *argv
, 0) < 0) {
144 "Invalid value for \"key\"\n");
151 } else if (!matches(*argv
, "ikey")) {
156 if (strchr(*argv
, '.'))
157 uval
= get_addr32(*argv
);
159 if (get_unsigned(&uval
, *argv
, 0)<0) {
160 fprintf(stderr
, "invalid value of \"ikey\"\n");
166 } else if (!matches(*argv
, "okey")) {
171 if (strchr(*argv
, '.'))
172 uval
= get_addr32(*argv
);
174 if (get_unsigned(&uval
, *argv
, 0)<0) {
175 fprintf(stderr
, "invalid value of \"okey\"\n");
181 } else if (!matches(*argv
, "seq")) {
184 } else if (!matches(*argv
, "iseq")) {
186 } else if (!matches(*argv
, "oseq")) {
188 } else if (!matches(*argv
, "csum")) {
191 } else if (!matches(*argv
, "icsum")) {
193 } else if (!matches(*argv
, "ocsum")) {
195 } else if (!matches(*argv
, "nopmtudisc")) {
197 } else if (!matches(*argv
, "pmtudisc")) {
199 } else if (!matches(*argv
, "remote")) {
201 if (strcmp(*argv
, "any"))
202 daddr
= get_addr32(*argv
);
203 } else if (!matches(*argv
, "local")) {
205 if (strcmp(*argv
, "any"))
206 saddr
= get_addr32(*argv
);
207 } else if (!matches(*argv
, "dev")) {
209 link
= tnl_ioctl_get_ifindex(*argv
);
212 } else if (!matches(*argv
, "ttl") ||
213 !matches(*argv
, "hoplimit")) {
217 if (strcmp(*argv
, "inherit") != 0) {
218 if (get_unsigned(&uval
, *argv
, 0))
219 invarg("invalid TTL\n", *argv
);
221 invarg("TTL must be <= 255\n", *argv
);
224 } else if (!matches(*argv
, "tos") ||
225 !matches(*argv
, "tclass") ||
226 !matches(*argv
, "dsfield")) {
230 if (strcmp(*argv
, "inherit") != 0) {
231 if (rtnl_dsfield_a2n(&uval
, *argv
))
232 invarg("bad TOS value", *argv
);
241 if (!ikey
&& IN_MULTICAST(ntohl(daddr
))) {
245 if (!okey
&& IN_MULTICAST(ntohl(daddr
))) {
249 if (IN_MULTICAST(ntohl(daddr
)) && !saddr
) {
250 fprintf(stderr
, "Broadcast tunnel requires a source address.\n");
254 addattr32(n
, 1024, IFLA_GRE_IKEY
, ikey
);
255 addattr32(n
, 1024, IFLA_GRE_OKEY
, okey
);
256 addattr_l(n
, 1024, IFLA_GRE_IFLAGS
, &iflags
, 2);
257 addattr_l(n
, 1024, IFLA_GRE_OFLAGS
, &oflags
, 2);
258 addattr_l(n
, 1024, IFLA_GRE_LOCAL
, &saddr
, 4);
259 addattr_l(n
, 1024, IFLA_GRE_REMOTE
, &daddr
, 4);
260 addattr_l(n
, 1024, IFLA_GRE_PMTUDISC
, &pmtudisc
, 1);
262 addattr32(n
, 1024, IFLA_GRE_LINK
, link
);
263 addattr_l(n
, 1024, IFLA_GRE_TTL
, &ttl
, 1);
264 addattr_l(n
, 1024, IFLA_GRE_TOS
, &tos
, 1);
269 static void gre_print_opt(struct link_util
*lu
, FILE *f
, struct rtattr
*tb
[])
273 const char *local
= "any";
274 const char *remote
= "any";
281 if (tb
[IFLA_GRE_REMOTE
]) {
282 unsigned addr
= *(__u32
*)RTA_DATA(tb
[IFLA_GRE_REMOTE
]);
285 remote
= format_host(AF_INET
, 4, &addr
, s1
, sizeof(s1
));
288 fprintf(f
, "remote %s ", remote
);
290 if (tb
[IFLA_GRE_LOCAL
]) {
291 unsigned addr
= *(__u32
*)RTA_DATA(tb
[IFLA_GRE_LOCAL
]);
294 local
= format_host(AF_INET
, 4, &addr
, s1
, sizeof(s1
));
297 fprintf(f
, "local %s ", local
);
299 if (tb
[IFLA_GRE_LINK
] && *(__u32
*)RTA_DATA(tb
[IFLA_GRE_LINK
])) {
300 unsigned link
= *(__u32
*)RTA_DATA(tb
[IFLA_GRE_LINK
]);
301 char *n
= tnl_ioctl_get_ifname(link
);
304 fprintf(f
, "dev %s ", n
);
306 fprintf(f
, "dev %u ", link
);
309 if (tb
[IFLA_GRE_TTL
] && *(__u8
*)RTA_DATA(tb
[IFLA_GRE_TTL
]))
310 fprintf(f
, "ttl %d ", *(__u8
*)RTA_DATA(tb
[IFLA_GRE_TTL
]));
312 fprintf(f
, "ttl inherit ");
314 if (tb
[IFLA_GRE_TOS
] && *(__u8
*)RTA_DATA(tb
[IFLA_GRE_TOS
])) {
315 int tos
= *(__u8
*)RTA_DATA(tb
[IFLA_GRE_TOS
]);
319 fputs("inherit ", f
);
321 fprintf(f
, "0x%x ", tos
);
324 if (tb
[IFLA_GRE_PMTUDISC
] &&
325 !*(__u8
*)RTA_DATA(tb
[IFLA_GRE_PMTUDISC
]))
326 fputs("nopmtudisc ", f
);
328 if (tb
[IFLA_GRE_IFLAGS
])
329 iflags
= *(__u16
*)RTA_DATA(tb
[IFLA_GRE_IFLAGS
]);
331 if (tb
[IFLA_GRE_OFLAGS
])
332 oflags
= *(__u16
*)RTA_DATA(tb
[IFLA_GRE_OFLAGS
]);
334 if (iflags
& GRE_KEY
&& tb
[IFLA_GRE_IKEY
] &&
335 *(__u32
*)RTA_DATA(tb
[IFLA_GRE_IKEY
])) {
336 inet_ntop(AF_INET
, RTA_DATA(tb
[IFLA_GRE_IKEY
]), s2
, sizeof(s2
));
337 fprintf(f
, "ikey %s ", s2
);
340 if (oflags
& GRE_KEY
&& tb
[IFLA_GRE_OKEY
] &&
341 *(__u32
*)RTA_DATA(tb
[IFLA_GRE_OKEY
])) {
342 inet_ntop(AF_INET
, RTA_DATA(tb
[IFLA_GRE_OKEY
]), s2
, sizeof(s2
));
343 fprintf(f
, "ikey %s ", s2
);
346 if (iflags
& GRE_SEQ
)
348 if (oflags
& GRE_SEQ
)
350 if (iflags
& GRE_CSUM
)
352 if (oflags
& GRE_CSUM
)
356 struct link_util gre_link_util
= {
358 .maxattr
= IFLA_GRE_MAX
,
359 .parse_opt
= gre_parse_opt
,
360 .print_opt
= gre_print_opt
,
363 struct link_util gretap_link_util
= {
365 .maxattr
= IFLA_GRE_MAX
,
366 .parse_opt
= gre_parse_opt
,
367 .print_opt
= gre_print_opt
,