1237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu/* 2237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu * link_gre.c gre driver module 3237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu * 4237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu * This program is free software; you can redistribute it and/or 5237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu * modify it under the terms of the GNU General Public License 6237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu * as published by the Free Software Foundation; either version 7237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu * 2 of the License, or (at your option) any later version. 8237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu * 9237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu * Authors: Herbert Xu <herbert@gondor.apana.org.au> 10237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu * 11237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu */ 12237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 13237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu#include <string.h> 14237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu#include <net/if.h> 15237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu#include <sys/types.h> 16237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu#include <sys/socket.h> 17237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu#include <arpa/inet.h> 18237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 191957a322c9932e1a1d2ca1fd37ce4b335ceb7113Stephen Hemminger#include <linux/ip.h> 201957a322c9932e1a1d2ca1fd37ce4b335ceb7113Stephen Hemminger#include <linux/if_tunnel.h> 21237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu#include "rt_names.h" 22237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu#include "utils.h" 23237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu#include "ip_common.h" 24237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu#include "tunnel.h" 25237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 26237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xustatic void usage(void) __attribute__((noreturn)); 27237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xustatic void usage(void) 28237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu{ 29237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(stderr, "Usage: ip link { add | set | change | replace | del } NAME\n"); 30237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(stderr, " type { gre | gretap } [ remote ADDR ] [ local ADDR ]\n"); 31237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(stderr, " [ [i|o]seq ] [ [i|o]key KEY ] [ [i|o]csum ]\n"); 32237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(stderr, " [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n"); 33237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(stderr, "\n"); 34237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(stderr, "Where: NAME := STRING\n"); 35237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(stderr, " ADDR := { IP_ADDRESS | any }\n"); 36237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(stderr, " TOS := { NUMBER | inherit }\n"); 37237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(stderr, " TTL := { 1..255 | inherit }\n"); 38237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(stderr, " KEY := { DOTTED_QUAD | NUMBER }\n"); 39237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu exit(-1); 40237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu} 41237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 42237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xustatic int gre_parse_opt(struct link_util *lu, int argc, char **argv, 43237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu struct nlmsghdr *n) 44237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu{ 4572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu struct { 4672c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu struct nlmsghdr n; 4772c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu struct ifinfomsg i; 4872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu char buf[1024]; 4972c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu } req; 5072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); 5172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu struct rtattr *tb[IFLA_MAX + 1]; 5272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu struct rtattr *linkinfo[IFLA_INFO_MAX+1]; 5372c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu struct rtattr *greinfo[IFLA_GRE_MAX + 1]; 54237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu __u16 iflags = 0; 55237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu __u16 oflags = 0; 56237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu unsigned ikey = 0; 57237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu unsigned okey = 0; 58237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu unsigned saddr = 0; 59237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu unsigned daddr = 0; 6072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu unsigned link = 0; 6172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu __u8 pmtudisc = 1; 6272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu __u8 ttl = 0; 6372c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu __u8 tos = 0; 6472c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu int len; 6572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 6672c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (!(n->nlmsg_flags & NLM_F_CREATE)) { 6772c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu memset(&req, 0, sizeof(req)); 6872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 6972c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)); 7072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu req.n.nlmsg_flags = NLM_F_REQUEST; 7172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu req.n.nlmsg_type = RTM_GETLINK; 7272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu req.i.ifi_family = preferred_family; 7372c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu req.i.ifi_index = ifi->ifi_index; 7472c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 75cd70f3f522e04b4d2fa80ae10292379bf223a53bStephen Hemminger if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { 7672c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xuget_failed: 7772c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu fprintf(stderr, 7872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu "Failed to get existing tunnel info.\n"); 7972c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu return -1; 8072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu } 8172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 8272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu len = req.n.nlmsg_len; 8372c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu len -= NLMSG_LENGTH(sizeof(*ifi)); 8472c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (len < 0) 8572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu goto get_failed; 8672c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 8772c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len); 8872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 8972c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (!tb[IFLA_LINKINFO]) 9072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu goto get_failed; 9172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 9272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); 9372c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 9472c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (!linkinfo[IFLA_INFO_DATA]) 9572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu goto get_failed; 9672c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 9772c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu parse_rtattr_nested(greinfo, IFLA_GRE_MAX, 9872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu linkinfo[IFLA_INFO_DATA]); 9972c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 10072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (greinfo[IFLA_GRE_IKEY]) 101ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger ikey = rta_getattr_u32(greinfo[IFLA_GRE_IKEY]); 10272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 10372c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (greinfo[IFLA_GRE_OKEY]) 104ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger okey = rta_getattr_u32(greinfo[IFLA_GRE_OKEY]); 10572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 10672c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (greinfo[IFLA_GRE_IFLAGS]) 107ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger iflags = rta_getattr_u16(greinfo[IFLA_GRE_IFLAGS]); 10872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 10972c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (greinfo[IFLA_GRE_OFLAGS]) 110ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger oflags = rta_getattr_u16(greinfo[IFLA_GRE_OFLAGS]); 11172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 11272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (greinfo[IFLA_GRE_LOCAL]) 113ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger saddr = rta_getattr_u32(greinfo[IFLA_GRE_LOCAL]); 11472c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 11572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (greinfo[IFLA_GRE_REMOTE]) 116ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger daddr = rta_getattr_u32(greinfo[IFLA_GRE_REMOTE]); 11772c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 11872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (greinfo[IFLA_GRE_PMTUDISC]) 119ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger pmtudisc = rta_getattr_u8( 12072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu greinfo[IFLA_GRE_PMTUDISC]); 12172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 12272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (greinfo[IFLA_GRE_TTL]) 123ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger ttl = rta_getattr_u8(greinfo[IFLA_GRE_TTL]); 12472c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 12572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (greinfo[IFLA_GRE_TOS]) 126ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger tos = rta_getattr_u8(greinfo[IFLA_GRE_TOS]); 12772c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu 12872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (greinfo[IFLA_GRE_LINK]) 129ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger link = rta_getattr_u8(greinfo[IFLA_GRE_LINK]); 13072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu } 131237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 132237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu while (argc > 0) { 133237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (!matches(*argv, "key")) { 134237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu unsigned uval; 135237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 136237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu NEXT_ARG(); 137237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu iflags |= GRE_KEY; 138237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu oflags |= GRE_KEY; 139237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (strchr(*argv, '.')) 140237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu uval = get_addr32(*argv); 141237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu else { 142237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (get_unsigned(&uval, *argv, 0) < 0) { 143237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(stderr, 144237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu "Invalid value for \"key\"\n"); 145237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu exit(-1); 146237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 147237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu uval = htonl(uval); 148237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 149237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 150237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu ikey = okey = uval; 151237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "ikey")) { 152237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu unsigned uval; 153237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 154237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu NEXT_ARG(); 155237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu iflags |= GRE_KEY; 156237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (strchr(*argv, '.')) 157237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu uval = get_addr32(*argv); 158237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu else { 159237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (get_unsigned(&uval, *argv, 0)<0) { 160237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(stderr, "invalid value of \"ikey\"\n"); 161237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu exit(-1); 162237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 163237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu uval = htonl(uval); 164237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 165237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu ikey = uval; 166237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "okey")) { 167237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu unsigned uval; 168237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 169237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu NEXT_ARG(); 170237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu oflags |= GRE_KEY; 171237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (strchr(*argv, '.')) 172237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu uval = get_addr32(*argv); 173237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu else { 174237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (get_unsigned(&uval, *argv, 0)<0) { 175237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(stderr, "invalid value of \"okey\"\n"); 176237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu exit(-1); 177237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 178237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu uval = htonl(uval); 179237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 180237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu okey = uval; 181237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "seq")) { 182237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu iflags |= GRE_SEQ; 183237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu oflags |= GRE_SEQ; 184237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "iseq")) { 185237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu iflags |= GRE_SEQ; 186237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "oseq")) { 187237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu oflags |= GRE_SEQ; 188237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "csum")) { 189237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu iflags |= GRE_CSUM; 190237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu oflags |= GRE_CSUM; 191237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "icsum")) { 192237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu iflags |= GRE_CSUM; 193237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "ocsum")) { 194237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu oflags |= GRE_CSUM; 195237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "nopmtudisc")) { 19672c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu pmtudisc = 0; 197237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "pmtudisc")) { 19872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu pmtudisc = 1; 199237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "remote")) { 200237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu NEXT_ARG(); 201237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (strcmp(*argv, "any")) 202237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu daddr = get_addr32(*argv); 203237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "local")) { 204237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu NEXT_ARG(); 205237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (strcmp(*argv, "any")) 206237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu saddr = get_addr32(*argv); 207237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "dev")) { 208237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu NEXT_ARG(); 209ea71beacacb9ebf756bbc250c71df59ec2f46243Stephen Hemminger link = if_nametoindex(*argv); 210237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (link == 0) 211237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu exit(-1); 212237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "ttl") || 213237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu !matches(*argv, "hoplimit")) { 214237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu unsigned uval; 215237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 216237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu NEXT_ARG(); 217237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (strcmp(*argv, "inherit") != 0) { 218237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (get_unsigned(&uval, *argv, 0)) 219237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu invarg("invalid TTL\n", *argv); 220237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (uval > 255) 221237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu invarg("TTL must be <= 255\n", *argv); 222237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu ttl = uval; 223237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 224237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else if (!matches(*argv, "tos") || 225237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu !matches(*argv, "tclass") || 226237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu !matches(*argv, "dsfield")) { 227237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu __u32 uval; 228237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 229237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu NEXT_ARG(); 230237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (strcmp(*argv, "inherit") != 0) { 231237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (rtnl_dsfield_a2n(&uval, *argv)) 232237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu invarg("bad TOS value", *argv); 233237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu tos = uval; 234237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else 235237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu tos = 1; 236237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } else 237237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu usage(); 238237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu argc--; argv++; 239237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 240237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 241237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (!ikey && IN_MULTICAST(ntohl(daddr))) { 242237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu ikey = daddr; 243237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu iflags |= GRE_KEY; 244237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 245237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (!okey && IN_MULTICAST(ntohl(daddr))) { 246237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu okey = daddr; 247237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu oflags |= GRE_KEY; 248237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 249237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (IN_MULTICAST(ntohl(daddr)) && !saddr) { 250237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(stderr, "Broadcast tunnel requires a source address.\n"); 251237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu return -1; 252237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 253237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 254237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu addattr32(n, 1024, IFLA_GRE_IKEY, ikey); 255237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu addattr32(n, 1024, IFLA_GRE_OKEY, okey); 256237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2); 257237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2); 258237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu addattr_l(n, 1024, IFLA_GRE_LOCAL, &saddr, 4); 259237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu addattr_l(n, 1024, IFLA_GRE_REMOTE, &daddr, 4); 26072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &pmtudisc, 1); 26172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu if (link) 26272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu addattr32(n, 1024, IFLA_GRE_LINK, link); 26372c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1); 26472c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1); 265237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 266237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu return 0; 267237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu} 268237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 269237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xustatic void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) 270237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu{ 271237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu char s1[1024]; 272237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu char s2[64]; 273237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu const char *local = "any"; 274237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu const char *remote = "any"; 275237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu unsigned iflags = 0; 276237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu unsigned oflags = 0; 277237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 278237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (!tb) 279237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu return; 280237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 281237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (tb[IFLA_GRE_REMOTE]) { 282ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger unsigned addr = rta_getattr_u32(tb[IFLA_GRE_REMOTE]); 283237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 284237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (addr) 285237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1)); 286237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 287237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 288237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(f, "remote %s ", remote); 289237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 290237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (tb[IFLA_GRE_LOCAL]) { 291ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger unsigned addr = rta_getattr_u32(tb[IFLA_GRE_LOCAL]); 292237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 293237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (addr) 294237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu local = format_host(AF_INET, 4, &addr, s1, sizeof(s1)); 295237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 296237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 297237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(f, "local %s ", local); 298237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 299ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger if (tb[IFLA_GRE_LINK] && rta_getattr_u32(tb[IFLA_GRE_LINK])) { 300ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger unsigned link = rta_getattr_u32(tb[IFLA_GRE_LINK]); 301ea71beacacb9ebf756bbc250c71df59ec2f46243Stephen Hemminger const char *n = if_indextoname(link, s2); 302237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 303237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (n) 304237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(f, "dev %s ", n); 305237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu else 306237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(f, "dev %u ", link); 307237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 308237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 309ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger if (tb[IFLA_GRE_TTL] && rta_getattr_u8(tb[IFLA_GRE_TTL])) 310ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_GRE_TTL])); 311237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu else 312237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(f, "ttl inherit "); 313237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 314ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger if (tb[IFLA_GRE_TOS] && rta_getattr_u8(tb[IFLA_GRE_TOS])) { 315ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger int tos = rta_getattr_u8(tb[IFLA_GRE_TOS]); 316237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 317237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fputs("tos ", f); 318237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (tos == 1) 319237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fputs("inherit ", f); 320237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu else 321237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(f, "0x%x ", tos); 322237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 323237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 324237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (tb[IFLA_GRE_PMTUDISC] && 325ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger !rta_getattr_u8(tb[IFLA_GRE_PMTUDISC])) 326237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fputs("nopmtudisc ", f); 327237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 328237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (tb[IFLA_GRE_IFLAGS]) 329ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger iflags = rta_getattr_u16(tb[IFLA_GRE_IFLAGS]); 330237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 331237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (tb[IFLA_GRE_OFLAGS]) 332ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger oflags = rta_getattr_u16(tb[IFLA_GRE_OFLAGS]); 333237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 334718165534d0c57ea23c536f57affe7f04a33199aStephen Hemminger if ((iflags & GRE_KEY) && tb[IFLA_GRE_IKEY]) { 335237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_IKEY]), s2, sizeof(s2)); 336237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fprintf(f, "ikey %s ", s2); 337237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 338237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 339718165534d0c57ea23c536f57affe7f04a33199aStephen Hemminger if ((oflags & GRE_KEY) && tb[IFLA_GRE_OKEY]) { 340237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2)); 341718165534d0c57ea23c536f57affe7f04a33199aStephen Hemminger fprintf(f, "okey %s ", s2); 342237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu } 343237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 344237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (iflags & GRE_SEQ) 345237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fputs("iseq ", f); 346237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (oflags & GRE_SEQ) 347237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fputs("oseq ", f); 348237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (iflags & GRE_CSUM) 349237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fputs("icsum ", f); 350237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu if (oflags & GRE_CSUM) 351237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu fputs("ocsum ", f); 352237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu} 353237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 354237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xustruct link_util gre_link_util = { 355237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu .id = "gre", 356237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu .maxattr = IFLA_GRE_MAX, 357237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu .parse_opt = gre_parse_opt, 358237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu .print_opt = gre_print_opt, 359237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu}; 360237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu 361237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xustruct link_util gretap_link_util = { 362237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu .id = "gretap", 363237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu .maxattr = IFLA_GRE_MAX, 364237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu .parse_opt = gre_parse_opt, 365237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu .print_opt = gre_print_opt, 366237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu}; 367