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