1 /* 2 * link_gre.c gre 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: Herbert Xu <herbert (at) gondor.apana.org.au> 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 26 static void usage(void) __attribute__((noreturn)); 27 static void usage(void) 28 { 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"); 39 exit(-1); 40 } 41 42 static int gre_parse_opt(struct link_util *lu, int argc, char **argv, 43 struct nlmsghdr *n) 44 { 45 struct { 46 struct nlmsghdr n; 47 struct ifinfomsg i; 48 char buf[1024]; 49 } req; 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]; 54 __u16 iflags = 0; 55 __u16 oflags = 0; 56 unsigned ikey = 0; 57 unsigned okey = 0; 58 unsigned saddr = 0; 59 unsigned daddr = 0; 60 unsigned link = 0; 61 __u8 pmtudisc = 1; 62 __u8 ttl = 0; 63 __u8 tos = 0; 64 int len; 65 66 if (!(n->nlmsg_flags & NLM_F_CREATE)) { 67 memset(&req, 0, sizeof(req)); 68 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; 74 75 if (rtnl_talk(&rth, &req.n, 0, 0, &req.n, NULL, NULL) < 0) { 76 get_failed: 77 fprintf(stderr, 78 "Failed to get existing tunnel info.\n"); 79 return -1; 80 } 81 82 len = req.n.nlmsg_len; 83 len -= NLMSG_LENGTH(sizeof(*ifi)); 84 if (len < 0) 85 goto get_failed; 86 87 parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len); 88 89 if (!tb[IFLA_LINKINFO]) 90 goto get_failed; 91 92 parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); 93 94 if (!linkinfo[IFLA_INFO_DATA]) 95 goto get_failed; 96 97 parse_rtattr_nested(greinfo, IFLA_GRE_MAX, 98 linkinfo[IFLA_INFO_DATA]); 99 100 if (greinfo[IFLA_GRE_IKEY]) 101 ikey = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_IKEY]); 102 103 if (greinfo[IFLA_GRE_OKEY]) 104 okey = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_OKEY]); 105 106 if (greinfo[IFLA_GRE_IFLAGS]) 107 iflags = *(__u16 *)RTA_DATA(greinfo[IFLA_GRE_IFLAGS]); 108 109 if (greinfo[IFLA_GRE_OFLAGS]) 110 oflags = *(__u16 *)RTA_DATA(greinfo[IFLA_GRE_OFLAGS]); 111 112 if (greinfo[IFLA_GRE_LOCAL]) 113 saddr = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_LOCAL]); 114 115 if (greinfo[IFLA_GRE_REMOTE]) 116 daddr = *(__u32 *)RTA_DATA(greinfo[IFLA_GRE_REMOTE]); 117 118 if (greinfo[IFLA_GRE_PMTUDISC]) 119 pmtudisc = *(__u8 *)RTA_DATA( 120 greinfo[IFLA_GRE_PMTUDISC]); 121 122 if (greinfo[IFLA_GRE_TTL]) 123 ttl = *(__u8 *)RTA_DATA(greinfo[IFLA_GRE_TTL]); 124 125 if (greinfo[IFLA_GRE_TOS]) 126 tos = *(__u8 *)RTA_DATA(greinfo[IFLA_GRE_TOS]); 127 128 if (greinfo[IFLA_GRE_LINK]) 129 link = *(__u8 *)RTA_DATA(greinfo[IFLA_GRE_LINK]); 130 } 131 132 while (argc > 0) { 133 if (!matches(*argv, "key")) { 134 unsigned uval; 135 136 NEXT_ARG(); 137 iflags |= GRE_KEY; 138 oflags |= GRE_KEY; 139 if (strchr(*argv, '.')) 140 uval = get_addr32(*argv); 141 else { 142 if (get_unsigned(&uval, *argv, 0) < 0) { 143 fprintf(stderr, 144 "Invalid value for \"key\"\n"); 145 exit(-1); 146 } 147 uval = htonl(uval); 148 } 149 150 ikey = okey = uval; 151 } else if (!matches(*argv, "ikey")) { 152 unsigned uval; 153 154 NEXT_ARG(); 155 iflags |= GRE_KEY; 156 if (strchr(*argv, '.')) 157 uval = get_addr32(*argv); 158 else { 159 if (get_unsigned(&uval, *argv, 0)<0) { 160 fprintf(stderr, "invalid value of \"ikey\"\n"); 161 exit(-1); 162 } 163 uval = htonl(uval); 164 } 165 ikey = uval; 166 } else if (!matches(*argv, "okey")) { 167 unsigned uval; 168 169 NEXT_ARG(); 170 oflags |= GRE_KEY; 171 if (strchr(*argv, '.')) 172 uval = get_addr32(*argv); 173 else { 174 if (get_unsigned(&uval, *argv, 0)<0) { 175 fprintf(stderr, "invalid value of \"okey\"\n"); 176 exit(-1); 177 } 178 uval = htonl(uval); 179 } 180 okey = uval; 181 } else if (!matches(*argv, "seq")) { 182 iflags |= GRE_SEQ; 183 oflags |= GRE_SEQ; 184 } else if (!matches(*argv, "iseq")) { 185 iflags |= GRE_SEQ; 186 } else if (!matches(*argv, "oseq")) { 187 oflags |= GRE_SEQ; 188 } else if (!matches(*argv, "csum")) { 189 iflags |= GRE_CSUM; 190 oflags |= GRE_CSUM; 191 } else if (!matches(*argv, "icsum")) { 192 iflags |= GRE_CSUM; 193 } else if (!matches(*argv, "ocsum")) { 194 oflags |= GRE_CSUM; 195 } else if (!matches(*argv, "nopmtudisc")) { 196 pmtudisc = 0; 197 } else if (!matches(*argv, "pmtudisc")) { 198 pmtudisc = 1; 199 } else if (!matches(*argv, "remote")) { 200 NEXT_ARG(); 201 if (strcmp(*argv, "any")) 202 daddr = get_addr32(*argv); 203 } else if (!matches(*argv, "local")) { 204 NEXT_ARG(); 205 if (strcmp(*argv, "any")) 206 saddr = get_addr32(*argv); 207 } else if (!matches(*argv, "dev")) { 208 NEXT_ARG(); 209 link = tnl_ioctl_get_ifindex(*argv); 210 if (link == 0) 211 exit(-1); 212 } else if (!matches(*argv, "ttl") || 213 !matches(*argv, "hoplimit")) { 214 unsigned uval; 215 216 NEXT_ARG(); 217 if (strcmp(*argv, "inherit") != 0) { 218 if (get_unsigned(&uval, *argv, 0)) 219 invarg("invalid TTL\n", *argv); 220 if (uval > 255) 221 invarg("TTL must be <= 255\n", *argv); 222 ttl = uval; 223 } 224 } else if (!matches(*argv, "tos") || 225 !matches(*argv, "tclass") || 226 !matches(*argv, "dsfield")) { 227 __u32 uval; 228 229 NEXT_ARG(); 230 if (strcmp(*argv, "inherit") != 0) { 231 if (rtnl_dsfield_a2n(&uval, *argv)) 232 invarg("bad TOS value", *argv); 233 tos = uval; 234 } else 235 tos = 1; 236 } else 237 usage(); 238 argc--; argv++; 239 } 240 241 if (!ikey && IN_MULTICAST(ntohl(daddr))) { 242 ikey = daddr; 243 iflags |= GRE_KEY; 244 } 245 if (!okey && IN_MULTICAST(ntohl(daddr))) { 246 okey = daddr; 247 oflags |= GRE_KEY; 248 } 249 if (IN_MULTICAST(ntohl(daddr)) && !saddr) { 250 fprintf(stderr, "Broadcast tunnel requires a source address.\n"); 251 return -1; 252 } 253 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); 261 if (link) 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); 265 266 return 0; 267 } 268 269 static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) 270 { 271 char s1[1024]; 272 char s2[64]; 273 const char *local = "any"; 274 const char *remote = "any"; 275 unsigned iflags = 0; 276 unsigned oflags = 0; 277 278 if (!tb) 279 return; 280 281 if (tb[IFLA_GRE_REMOTE]) { 282 unsigned addr = *(__u32 *)RTA_DATA(tb[IFLA_GRE_REMOTE]); 283 284 if (addr) 285 remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1)); 286 } 287 288 fprintf(f, "remote %s ", remote); 289 290 if (tb[IFLA_GRE_LOCAL]) { 291 unsigned addr = *(__u32 *)RTA_DATA(tb[IFLA_GRE_LOCAL]); 292 293 if (addr) 294 local = format_host(AF_INET, 4, &addr, s1, sizeof(s1)); 295 } 296 297 fprintf(f, "local %s ", local); 298 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); 302 303 if (n) 304 fprintf(f, "dev %s ", n); 305 else 306 fprintf(f, "dev %u ", link); 307 } 308 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])); 311 else 312 fprintf(f, "ttl inherit "); 313 314 if (tb[IFLA_GRE_TOS] && *(__u8 *)RTA_DATA(tb[IFLA_GRE_TOS])) { 315 int tos = *(__u8 *)RTA_DATA(tb[IFLA_GRE_TOS]); 316 317 fputs("tos ", f); 318 if (tos == 1) 319 fputs("inherit ", f); 320 else 321 fprintf(f, "0x%x ", tos); 322 } 323 324 if (tb[IFLA_GRE_PMTUDISC] && 325 !*(__u8 *)RTA_DATA(tb[IFLA_GRE_PMTUDISC])) 326 fputs("nopmtudisc ", f); 327 328 if (tb[IFLA_GRE_IFLAGS]) 329 iflags = *(__u16 *)RTA_DATA(tb[IFLA_GRE_IFLAGS]); 330 331 if (tb[IFLA_GRE_OFLAGS]) 332 oflags = *(__u16 *)RTA_DATA(tb[IFLA_GRE_OFLAGS]); 333 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); 338 } 339 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); 344 } 345 346 if (iflags & GRE_SEQ) 347 fputs("iseq ", f); 348 if (oflags & GRE_SEQ) 349 fputs("oseq ", f); 350 if (iflags & GRE_CSUM) 351 fputs("icsum ", f); 352 if (oflags & GRE_CSUM) 353 fputs("ocsum ", f); 354 } 355 356 struct link_util gre_link_util = { 357 .id = "gre", 358 .maxattr = IFLA_GRE_MAX, 359 .parse_opt = gre_parse_opt, 360 .print_opt = gre_print_opt, 361 }; 362 363 struct link_util gretap_link_util = { 364 .id = "gretap", 365 .maxattr = IFLA_GRE_MAX, 366 .parse_opt = gre_parse_opt, 367 .print_opt = gre_print_opt, 368 }; 369