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
26561e650eff679296d3f4c12657721ae769cbc187vadimkstatic void print_usage(FILE *f)
27561e650eff679296d3f4c12657721ae769cbc187vadimk{
28561e650eff679296d3f4c12657721ae769cbc187vadimk	fprintf(f, "Usage: ip link { add | set | change | replace | del } NAME\n");
29561e650eff679296d3f4c12657721ae769cbc187vadimk	fprintf(f, "          type { gre | gretap } [ remote ADDR ] [ local ADDR ]\n");
30561e650eff679296d3f4c12657721ae769cbc187vadimk	fprintf(f, "          [ [i|o]seq ] [ [i|o]key KEY ] [ [i|o]csum ]\n");
31561e650eff679296d3f4c12657721ae769cbc187vadimk	fprintf(f, "          [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]\n");
3280c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert	fprintf(f, "          [ noencap ] [ encap { fou | gue | none } ]\n");
3380c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert	fprintf(f, "          [ encap-sport PORT ] [ encap-dport PORT ]\n");
34858dbb208e3934525674252a6b6cf7d36a9de191Tom Herbert	fprintf(f, "          [ [no]encap-csum ] [ [no]encap-csum6 ] [ [no]encap-remcsum ]\n");
35561e650eff679296d3f4c12657721ae769cbc187vadimk	fprintf(f, "\n");
36561e650eff679296d3f4c12657721ae769cbc187vadimk	fprintf(f, "Where: NAME := STRING\n");
37561e650eff679296d3f4c12657721ae769cbc187vadimk	fprintf(f, "       ADDR := { IP_ADDRESS | any }\n");
38561e650eff679296d3f4c12657721ae769cbc187vadimk	fprintf(f, "       TOS  := { NUMBER | inherit }\n");
39561e650eff679296d3f4c12657721ae769cbc187vadimk	fprintf(f, "       TTL  := { 1..255 | inherit }\n");
40561e650eff679296d3f4c12657721ae769cbc187vadimk	fprintf(f, "       KEY  := { DOTTED_QUAD | NUMBER }\n");
41561e650eff679296d3f4c12657721ae769cbc187vadimk}
42561e650eff679296d3f4c12657721ae769cbc187vadimk
43237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xustatic void usage(void) __attribute__((noreturn));
44237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xustatic void usage(void)
45237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu{
46561e650eff679296d3f4c12657721ae769cbc187vadimk	print_usage(stderr);
47237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	exit(-1);
48237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu}
49237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
50237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xustatic int gre_parse_opt(struct link_util *lu, int argc, char **argv,
51237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			 struct nlmsghdr *n)
52237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu{
5372c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	struct {
5472c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		struct nlmsghdr n;
5572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		struct ifinfomsg i;
56bde5baa5476cd8d7d33afc42170dc984f3717e14Jetchko Jekov		char buf[16384];
5772c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	} req;
5872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1);
5972c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	struct rtattr *tb[IFLA_MAX + 1];
6072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	struct rtattr *linkinfo[IFLA_INFO_MAX+1];
6172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	struct rtattr *greinfo[IFLA_GRE_MAX + 1];
62237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	__u16 iflags = 0;
63237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	__u16 oflags = 0;
64237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	unsigned ikey = 0;
65237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	unsigned okey = 0;
66237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	unsigned saddr = 0;
67237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	unsigned daddr = 0;
6872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	unsigned link = 0;
6972c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	__u8 pmtudisc = 1;
7072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	__u8 ttl = 0;
7172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	__u8 tos = 0;
7272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	int len;
7380c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert	__u16 encaptype = 0;
7480c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert	__u16 encapflags = 0;
7580c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert	__u16 encapsport = 0;
7680c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert	__u16 encapdport = 0;
77926b39e1feffdacff52fe8b7eafe0ba3b8c9ff59Paolo Abeni	__u8 metadata = 0;
7872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
7972c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	if (!(n->nlmsg_flags & NLM_F_CREATE)) {
8072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		memset(&req, 0, sizeof(req));
8172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
8272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi));
8372c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		req.n.nlmsg_flags = NLM_F_REQUEST;
8472c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		req.n.nlmsg_type = RTM_GETLINK;
8572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		req.i.ifi_family = preferred_family;
8672c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		req.i.ifi_index = ifi->ifi_index;
8772c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
88c079e121a73af5eb49e003b13607e8a690331df6Stephen Hemminger		if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) {
8972c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xuget_failed:
9072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu			fprintf(stderr,
9172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu				"Failed to get existing tunnel info.\n");
9272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu			return -1;
9372c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		}
9472c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
9572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		len = req.n.nlmsg_len;
9672c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		len -= NLMSG_LENGTH(sizeof(*ifi));
9772c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		if (len < 0)
9872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu			goto get_failed;
9972c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
10072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len);
10172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
10272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		if (!tb[IFLA_LINKINFO])
10372c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu			goto get_failed;
10472c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
10572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]);
10672c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
10772c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		if (!linkinfo[IFLA_INFO_DATA])
10872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu			goto get_failed;
10972c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
11072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		parse_rtattr_nested(greinfo, IFLA_GRE_MAX,
11172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu				    linkinfo[IFLA_INFO_DATA]);
11272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
11372c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		if (greinfo[IFLA_GRE_IKEY])
114ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger			ikey = rta_getattr_u32(greinfo[IFLA_GRE_IKEY]);
11572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
11672c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		if (greinfo[IFLA_GRE_OKEY])
117ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger			okey = rta_getattr_u32(greinfo[IFLA_GRE_OKEY]);
11872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
11972c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		if (greinfo[IFLA_GRE_IFLAGS])
120ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger			iflags = rta_getattr_u16(greinfo[IFLA_GRE_IFLAGS]);
12172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
12272c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		if (greinfo[IFLA_GRE_OFLAGS])
123ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger			oflags = rta_getattr_u16(greinfo[IFLA_GRE_OFLAGS]);
12472c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
12572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		if (greinfo[IFLA_GRE_LOCAL])
126ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger			saddr = rta_getattr_u32(greinfo[IFLA_GRE_LOCAL]);
12772c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
12872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		if (greinfo[IFLA_GRE_REMOTE])
129ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger			daddr = rta_getattr_u32(greinfo[IFLA_GRE_REMOTE]);
13072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
13172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		if (greinfo[IFLA_GRE_PMTUDISC])
132ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger			pmtudisc = rta_getattr_u8(
13372c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu				greinfo[IFLA_GRE_PMTUDISC]);
13472c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
13572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		if (greinfo[IFLA_GRE_TTL])
136ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger			ttl = rta_getattr_u8(greinfo[IFLA_GRE_TTL]);
13772c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
13872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		if (greinfo[IFLA_GRE_TOS])
139ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger			tos = rta_getattr_u8(greinfo[IFLA_GRE_TOS]);
14072c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu
14172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		if (greinfo[IFLA_GRE_LINK])
142ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger			link = rta_getattr_u8(greinfo[IFLA_GRE_LINK]);
14380c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert
14480c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		if (greinfo[IFLA_GRE_ENCAP_TYPE])
14580c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			encaptype = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_TYPE]);
14680c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		if (greinfo[IFLA_GRE_ENCAP_FLAGS])
14780c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			encapflags = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_FLAGS]);
14880c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		if (greinfo[IFLA_GRE_ENCAP_SPORT])
14980c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			encapsport = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_SPORT]);
15080c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		if (greinfo[IFLA_GRE_ENCAP_DPORT])
15180c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			encapdport = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_DPORT]);
152926b39e1feffdacff52fe8b7eafe0ba3b8c9ff59Paolo Abeni
153926b39e1feffdacff52fe8b7eafe0ba3b8c9ff59Paolo Abeni		if (greinfo[IFLA_GRE_COLLECT_METADATA])
154926b39e1feffdacff52fe8b7eafe0ba3b8c9ff59Paolo Abeni			metadata = 1;
15572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	}
156237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
157237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	while (argc > 0) {
158237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		if (!matches(*argv, "key")) {
159237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			unsigned uval;
160237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
161237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			NEXT_ARG();
162237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			iflags |= GRE_KEY;
163237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			oflags |= GRE_KEY;
164237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			if (strchr(*argv, '.'))
165237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				uval = get_addr32(*argv);
166237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			else {
167237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				if (get_unsigned(&uval, *argv, 0) < 0) {
168237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu					fprintf(stderr,
16914645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk						"Invalid value for \"key\": \"%s\"; it should be an unsigned integer\n", *argv);
170237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu					exit(-1);
171237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				}
172237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				uval = htonl(uval);
173237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			}
174237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
175237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			ikey = okey = uval;
176237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "ikey")) {
177237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			unsigned uval;
178237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
179237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			NEXT_ARG();
180237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			iflags |= GRE_KEY;
181237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			if (strchr(*argv, '.'))
182237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				uval = get_addr32(*argv);
183237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			else {
184237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				if (get_unsigned(&uval, *argv, 0)<0) {
18514645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk					fprintf(stderr, "invalid value for \"ikey\": \"%s\"; it should be an unsigned integer\n", *argv);
186237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu					exit(-1);
187237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				}
188237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				uval = htonl(uval);
189237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			}
190237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			ikey = uval;
191237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "okey")) {
192237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			unsigned uval;
193237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
194237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			NEXT_ARG();
195237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			oflags |= GRE_KEY;
196237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			if (strchr(*argv, '.'))
197237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				uval = get_addr32(*argv);
198237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			else {
199237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				if (get_unsigned(&uval, *argv, 0)<0) {
20014645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk					fprintf(stderr, "invalid value for \"okey\": \"%s\"; it should be an unsigned integer\n", *argv);
201237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu					exit(-1);
202237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				}
203237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				uval = htonl(uval);
204237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			}
205237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			okey = uval;
206237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "seq")) {
207237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			iflags |= GRE_SEQ;
208237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			oflags |= GRE_SEQ;
209237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "iseq")) {
210237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			iflags |= GRE_SEQ;
211237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "oseq")) {
212237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			oflags |= GRE_SEQ;
213237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "csum")) {
214237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			iflags |= GRE_CSUM;
215237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			oflags |= GRE_CSUM;
216237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "icsum")) {
217237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			iflags |= GRE_CSUM;
218237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "ocsum")) {
219237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			oflags |= GRE_CSUM;
220237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "nopmtudisc")) {
22172c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu			pmtudisc = 0;
222237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "pmtudisc")) {
22372c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu			pmtudisc = 1;
224237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "remote")) {
225237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			NEXT_ARG();
226237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			if (strcmp(*argv, "any"))
227237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				daddr = get_addr32(*argv);
228237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "local")) {
229237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			NEXT_ARG();
230237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			if (strcmp(*argv, "any"))
231237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				saddr = get_addr32(*argv);
232237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "dev")) {
233237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			NEXT_ARG();
234ea71beacacb9ebf756bbc250c71df59ec2f46243Stephen Hemminger			link = if_nametoindex(*argv);
2350cb6bb51b4eb9bd08e152342b95dcae13287dafdCong Wang			if (link == 0) {
2360cb6bb51b4eb9bd08e152342b95dcae13287dafdCong Wang				fprintf(stderr, "Cannot find device \"%s\"\n",
2370cb6bb51b4eb9bd08e152342b95dcae13287dafdCong Wang					*argv);
238237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				exit(-1);
2390cb6bb51b4eb9bd08e152342b95dcae13287dafdCong Wang			}
240237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "ttl") ||
241237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			   !matches(*argv, "hoplimit")) {
242237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			unsigned uval;
243237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
244237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			NEXT_ARG();
245237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			if (strcmp(*argv, "inherit") != 0) {
246237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				if (get_unsigned(&uval, *argv, 0))
247237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu					invarg("invalid TTL\n", *argv);
248237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				if (uval > 255)
249237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu					invarg("TTL must be <= 255\n", *argv);
250237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				ttl = uval;
251237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			}
252237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		} else if (!matches(*argv, "tos") ||
253237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			   !matches(*argv, "tclass") ||
254237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			   !matches(*argv, "dsfield")) {
255237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			__u32 uval;
256237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
257237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			NEXT_ARG();
258237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			if (strcmp(*argv, "inherit") != 0) {
259237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				if (rtnl_dsfield_a2n(&uval, *argv))
260237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu					invarg("bad TOS value", *argv);
261237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				tos = uval;
262237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			} else
263237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu				tos = 1;
26480c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		} else if (strcmp(*argv, "noencap") == 0) {
26580c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			encaptype = TUNNEL_ENCAP_NONE;
26680c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		} else if (strcmp(*argv, "encap") == 0) {
26780c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			NEXT_ARG();
26880c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			if (strcmp(*argv, "fou") == 0)
26980c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert				encaptype = TUNNEL_ENCAP_FOU;
27080c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			else if (strcmp(*argv, "gue") == 0)
27180c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert				encaptype = TUNNEL_ENCAP_GUE;
27280c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			else if (strcmp(*argv, "none") == 0)
27380c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert				encaptype = TUNNEL_ENCAP_NONE;
27480c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			else
27580c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert				invarg("Invalid encap type.", *argv);
27680c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		} else if (strcmp(*argv, "encap-sport") == 0) {
27780c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			NEXT_ARG();
27880c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			if (strcmp(*argv, "auto") == 0)
27980c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert				encapsport = 0;
28080c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			else if (get_u16(&encapsport, *argv, 0))
28180c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert				invarg("Invalid source port.", *argv);
28280c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		} else if (strcmp(*argv, "encap-dport") == 0) {
28380c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			NEXT_ARG();
28480c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			if (get_u16(&encapdport, *argv, 0))
28580c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert				invarg("Invalid destination port.", *argv);
28680c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		} else if (strcmp(*argv, "encap-csum") == 0) {
28780c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			encapflags |= TUNNEL_ENCAP_FLAG_CSUM;
28880c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		} else if (strcmp(*argv, "noencap-csum") == 0) {
28980c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			encapflags &= ~TUNNEL_ENCAP_FLAG_CSUM;
29080c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		} else if (strcmp(*argv, "encap-udp6-csum") == 0) {
29180c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			encapflags |= TUNNEL_ENCAP_FLAG_CSUM6;
29280c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		} else if (strcmp(*argv, "noencap-udp6-csum") == 0) {
29380c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			encapflags |= ~TUNNEL_ENCAP_FLAG_CSUM6;
294858dbb208e3934525674252a6b6cf7d36a9de191Tom Herbert		} else if (strcmp(*argv, "encap-remcsum") == 0) {
295858dbb208e3934525674252a6b6cf7d36a9de191Tom Herbert			encapflags |= TUNNEL_ENCAP_FLAG_REMCSUM;
296858dbb208e3934525674252a6b6cf7d36a9de191Tom Herbert		} else if (strcmp(*argv, "noencap-remcsum") == 0) {
297858dbb208e3934525674252a6b6cf7d36a9de191Tom Herbert			encapflags |= ~TUNNEL_ENCAP_FLAG_REMCSUM;
298926b39e1feffdacff52fe8b7eafe0ba3b8c9ff59Paolo Abeni		} else if (strcmp(*argv, "external") == 0) {
299926b39e1feffdacff52fe8b7eafe0ba3b8c9ff59Paolo Abeni			metadata = 1;
3000612519e011812276ade512d4a7f8113497f64edStephen Hemminger		} else
301237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			usage();
302237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		argc--; argv++;
303237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	}
304237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
305237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	if (!ikey && IN_MULTICAST(ntohl(daddr))) {
306237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		ikey = daddr;
307237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		iflags |= GRE_KEY;
308237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	}
309237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	if (!okey && IN_MULTICAST(ntohl(daddr))) {
310237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		okey = daddr;
311237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		oflags |= GRE_KEY;
312237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	}
313237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	if (IN_MULTICAST(ntohl(daddr)) && !saddr) {
31414645ec2310ee7cf6d2f3d5035ac37ec09674e2cKees van Reeuwijk		fprintf(stderr, "A broadcast tunnel requires a source address.\n");
315237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		return -1;
316237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	}
317237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
318237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	addattr32(n, 1024, IFLA_GRE_IKEY, ikey);
319237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	addattr32(n, 1024, IFLA_GRE_OKEY, okey);
320237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2);
321237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2);
322237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	addattr_l(n, 1024, IFLA_GRE_LOCAL, &saddr, 4);
323237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	addattr_l(n, 1024, IFLA_GRE_REMOTE, &daddr, 4);
32472c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &pmtudisc, 1);
32572c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	if (link)
32672c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu		addattr32(n, 1024, IFLA_GRE_LINK, link);
32772c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1);
32872c771b20e38eaabb7699625fcdc144a51771f9cHerbert Xu	addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1);
329237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
33080c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert	addattr16(n, 1024, IFLA_GRE_ENCAP_TYPE, encaptype);
33180c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert	addattr16(n, 1024, IFLA_GRE_ENCAP_FLAGS, encapflags);
33280c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert	addattr16(n, 1024, IFLA_GRE_ENCAP_SPORT, htons(encapsport));
33380c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert	addattr16(n, 1024, IFLA_GRE_ENCAP_DPORT, htons(encapdport));
334926b39e1feffdacff52fe8b7eafe0ba3b8c9ff59Paolo Abeni	if (metadata)
335926b39e1feffdacff52fe8b7eafe0ba3b8c9ff59Paolo Abeni		addattr_l(n, 1024, IFLA_GRE_COLLECT_METADATA, NULL, 0);
33680c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert
337237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	return 0;
338237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu}
339237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
340237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xustatic void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[])
341237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu{
342237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	char s1[1024];
343237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	char s2[64];
344237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	const char *local = "any";
345237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	const char *remote = "any";
346237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	unsigned iflags = 0;
347237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	unsigned oflags = 0;
348237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
349237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	if (!tb)
350237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		return;
351237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
352237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	if (tb[IFLA_GRE_REMOTE]) {
353ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger		unsigned addr = rta_getattr_u32(tb[IFLA_GRE_REMOTE]);
354237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
355237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		if (addr)
356237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			remote = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
357237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	}
358237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
359237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	fprintf(f, "remote %s ", remote);
360237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
361237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	if (tb[IFLA_GRE_LOCAL]) {
362ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger		unsigned addr = rta_getattr_u32(tb[IFLA_GRE_LOCAL]);
363237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
364237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		if (addr)
365237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			local = format_host(AF_INET, 4, &addr, s1, sizeof(s1));
366237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	}
367237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
368237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	fprintf(f, "local %s ", local);
369237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
370ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger	if (tb[IFLA_GRE_LINK] && rta_getattr_u32(tb[IFLA_GRE_LINK])) {
371ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger		unsigned link = rta_getattr_u32(tb[IFLA_GRE_LINK]);
372ea71beacacb9ebf756bbc250c71df59ec2f46243Stephen Hemminger		const char *n = if_indextoname(link, s2);
373237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
374237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		if (n)
375237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			fprintf(f, "dev %s ", n);
376237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		else
377237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			fprintf(f, "dev %u ", link);
378237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	}
379237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
380ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger	if (tb[IFLA_GRE_TTL] && rta_getattr_u8(tb[IFLA_GRE_TTL]))
381ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger		fprintf(f, "ttl %d ", rta_getattr_u8(tb[IFLA_GRE_TTL]));
382237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	else
383237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		fprintf(f, "ttl inherit ");
384237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
385ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger	if (tb[IFLA_GRE_TOS] && rta_getattr_u8(tb[IFLA_GRE_TOS])) {
386ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger		int tos = rta_getattr_u8(tb[IFLA_GRE_TOS]);
387237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
388237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		fputs("tos ", f);
389237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		if (tos == 1)
390237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			fputs("inherit ", f);
391237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		else
392237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu			fprintf(f, "0x%x ", tos);
393237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	}
394237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
395237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	if (tb[IFLA_GRE_PMTUDISC] &&
396ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger	    !rta_getattr_u8(tb[IFLA_GRE_PMTUDISC]))
397237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		fputs("nopmtudisc ", f);
398237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
399237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	if (tb[IFLA_GRE_IFLAGS])
400ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger		iflags = rta_getattr_u16(tb[IFLA_GRE_IFLAGS]);
401237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
402237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	if (tb[IFLA_GRE_OFLAGS])
403ff24746cca1ef0c92d46614158e6672acd6b63d3Stephen Hemminger		oflags = rta_getattr_u16(tb[IFLA_GRE_OFLAGS]);
404237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
405718165534d0c57ea23c536f57affe7f04a33199aStephen Hemminger	if ((iflags & GRE_KEY) && tb[IFLA_GRE_IKEY]) {
406237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_IKEY]), s2, sizeof(s2));
407237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		fprintf(f, "ikey %s ", s2);
408237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	}
409237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
410718165534d0c57ea23c536f57affe7f04a33199aStephen Hemminger	if ((oflags & GRE_KEY) && tb[IFLA_GRE_OKEY]) {
411237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2));
412718165534d0c57ea23c536f57affe7f04a33199aStephen Hemminger		fprintf(f, "okey %s ", s2);
413237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	}
414237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
415237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	if (iflags & GRE_SEQ)
416237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		fputs("iseq ", f);
417237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	if (oflags & GRE_SEQ)
418237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		fputs("oseq ", f);
419237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	if (iflags & GRE_CSUM)
420237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		fputs("icsum ", f);
421237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	if (oflags & GRE_CSUM)
422237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu		fputs("ocsum ", f);
42380c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert
424926b39e1feffdacff52fe8b7eafe0ba3b8c9ff59Paolo Abeni	if (tb[IFLA_GRE_COLLECT_METADATA])
425926b39e1feffdacff52fe8b7eafe0ba3b8c9ff59Paolo Abeni		fputs("external ", f);
426926b39e1feffdacff52fe8b7eafe0ba3b8c9ff59Paolo Abeni
42780c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert	if (tb[IFLA_GRE_ENCAP_TYPE] &&
42880c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert	    *(__u16 *)RTA_DATA(tb[IFLA_GRE_ENCAP_TYPE]) != TUNNEL_ENCAP_NONE) {
42980c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		__u16 type = rta_getattr_u16(tb[IFLA_GRE_ENCAP_TYPE]);
43080c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		__u16 flags = rta_getattr_u16(tb[IFLA_GRE_ENCAP_FLAGS]);
43180c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		__u16 sport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_SPORT]);
43280c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		__u16 dport = rta_getattr_u16(tb[IFLA_GRE_ENCAP_DPORT]);
43380c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert
43480c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		fputs("encap ", f);
43580c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		switch (type) {
43680c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		case TUNNEL_ENCAP_FOU:
43780c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			fputs("fou ", f);
43880c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			break;
43980c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		case TUNNEL_ENCAP_GUE:
44080c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			fputs("gue ", f);
44180c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			break;
44280c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		default:
44380c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			fputs("unknown ", f);
44480c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			break;
44580c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		}
44680c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert
44780c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		if (sport == 0)
44880c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			fputs("encap-sport auto ", f);
44980c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		else
45080c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			fprintf(f, "encap-sport %u", ntohs(sport));
45180c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert
45280c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		fprintf(f, "encap-dport %u ", ntohs(dport));
45380c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert
45480c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		if (flags & TUNNEL_ENCAP_FLAG_CSUM)
45580c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			fputs("encap-csum ", f);
45680c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		else
45780c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			fputs("noencap-csum ", f);
45880c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert
45980c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		if (flags & TUNNEL_ENCAP_FLAG_CSUM6)
46080c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			fputs("encap-csum6 ", f);
46180c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert		else
46280c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert			fputs("noencap-csum6 ", f);
463858dbb208e3934525674252a6b6cf7d36a9de191Tom Herbert
464858dbb208e3934525674252a6b6cf7d36a9de191Tom Herbert		if (flags & TUNNEL_ENCAP_FLAG_REMCSUM)
465858dbb208e3934525674252a6b6cf7d36a9de191Tom Herbert			fputs("encap-remcsum ", f);
466858dbb208e3934525674252a6b6cf7d36a9de191Tom Herbert		else
467858dbb208e3934525674252a6b6cf7d36a9de191Tom Herbert			fputs("noencap-remcsum ", f);
46880c24b097e2f943676b20c0b72a5c95da2d0285fTom Herbert	}
469237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu}
470237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
471561e650eff679296d3f4c12657721ae769cbc187vadimkstatic void gre_print_help(struct link_util *lu, int argc, char **argv,
472561e650eff679296d3f4c12657721ae769cbc187vadimk	FILE *f)
473561e650eff679296d3f4c12657721ae769cbc187vadimk{
474561e650eff679296d3f4c12657721ae769cbc187vadimk	print_usage(f);
475561e650eff679296d3f4c12657721ae769cbc187vadimk}
476561e650eff679296d3f4c12657721ae769cbc187vadimk
477237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xustruct link_util gre_link_util = {
478237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	.id = "gre",
479237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	.maxattr = IFLA_GRE_MAX,
480237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	.parse_opt = gre_parse_opt,
481237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	.print_opt = gre_print_opt,
482561e650eff679296d3f4c12657721ae769cbc187vadimk	.print_help = gre_print_help,
483237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu};
484237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu
485237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xustruct link_util gretap_link_util = {
486237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	.id = "gretap",
487237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	.maxattr = IFLA_GRE_MAX,
488237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	.parse_opt = gre_parse_opt,
489237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu	.print_opt = gre_print_opt,
490561e650eff679296d3f4c12657721ae769cbc187vadimk	.print_help = gre_print_help,
491237d9e82c56918a1c972e6f30dd3cf1cfb957412Herbert Xu};
492