]>
Commit | Line | Data |
---|---|---|
237d9e82 HX |
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@gondor.apana.org.au> | |
10 | * | |
11 | */ | |
12 | ||
13 | #include <string.h> | |
14 | #include <net/if.h> | |
237d9e82 HX |
15 | #include <sys/types.h> |
16 | #include <sys/socket.h> | |
17 | #include <arpa/inet.h> | |
18 | ||
1957a322 SH |
19 | #include <linux/ip.h> |
20 | #include <linux/if_tunnel.h> | |
237d9e82 HX |
21 | #include "rt_names.h" |
22 | #include "utils.h" | |
23 | #include "ip_common.h" | |
24 | #include "tunnel.h" | |
25 | ||
561e650e | 26 | static void print_usage(FILE *f) |
27 | { | |
8b471354 | 28 | fprintf(f, |
9a1381d5 | 29 | "Usage: ... { gre | gretap | erspan } [ remote ADDR ]\n" |
8b471354 PS |
30 | " [ local ADDR ]\n" |
31 | " [ [i|o]seq ]\n" | |
32 | " [ [i|o]key KEY ]\n" | |
33 | " [ [i|o]csum ]\n" | |
34 | " [ ttl TTL ]\n" | |
35 | " [ tos TOS ]\n" | |
36 | " [ [no]pmtudisc ]\n" | |
adbb2965 | 37 | " [ [no]ignore-df ]\n" |
8b471354 PS |
38 | " [ dev PHYS_DEV ]\n" |
39 | " [ noencap ]\n" | |
40 | " [ encap { fou | gue | none } ]\n" | |
41 | " [ encap-sport PORT ]\n" | |
42 | " [ encap-dport PORT ]\n" | |
43 | " [ [no]encap-csum ]\n" | |
44 | " [ [no]encap-csum6 ]\n" | |
45 | " [ [no]encap-remcsum ]\n" | |
b760a882 | 46 | " [ external ]\n" |
ad4b1425 | 47 | " [ fwmark MARK ]\n" |
1e4be52b | 48 | " [ erspan_ver version ]\n" |
9a1381d5 | 49 | " [ erspan IDX ]\n" |
1e4be52b WT |
50 | " [ erspan_dir { ingress | egress } ]\n" |
51 | " [ erspan_hwid hwid ]\n" | |
52 | " [ external ]\n" | |
8b471354 PS |
53 | "\n" |
54 | "Where: ADDR := { IP_ADDRESS | any }\n" | |
55 | " TOS := { NUMBER | inherit }\n" | |
56 | " TTL := { 1..255 | inherit }\n" | |
57 | " KEY := { DOTTED_QUAD | NUMBER }\n" | |
ad4b1425 | 58 | " MARK := { 0x0..0xffffffff }\n" |
8b471354 | 59 | ); |
561e650e | 60 | } |
61 | ||
237d9e82 HX |
62 | static void usage(void) __attribute__((noreturn)); |
63 | static void usage(void) | |
64 | { | |
561e650e | 65 | print_usage(stderr); |
237d9e82 HX |
66 | exit(-1); |
67 | } | |
68 | ||
69 | static int gre_parse_opt(struct link_util *lu, int argc, char **argv, | |
70 | struct nlmsghdr *n) | |
71 | { | |
d17b136f | 72 | struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); |
72c771b2 HX |
73 | struct { |
74 | struct nlmsghdr n; | |
75 | struct ifinfomsg i; | |
d17b136f PS |
76 | } req = { |
77 | .n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)), | |
78 | .n.nlmsg_flags = NLM_F_REQUEST, | |
79 | .n.nlmsg_type = RTM_GETLINK, | |
80 | .i.ifi_family = preferred_family, | |
81 | .i.ifi_index = ifi->ifi_index, | |
82 | }; | |
08ede25f | 83 | struct nlmsghdr *answer; |
72c771b2 HX |
84 | struct rtattr *tb[IFLA_MAX + 1]; |
85 | struct rtattr *linkinfo[IFLA_INFO_MAX+1]; | |
86 | struct rtattr *greinfo[IFLA_GRE_MAX + 1]; | |
237d9e82 HX |
87 | __u16 iflags = 0; |
88 | __u16 oflags = 0; | |
1f44b937 SP |
89 | __be32 ikey = 0; |
90 | __be32 okey = 0; | |
56f5daac SH |
91 | unsigned int saddr = 0; |
92 | unsigned int daddr = 0; | |
93 | unsigned int link = 0; | |
72c771b2 HX |
94 | __u8 pmtudisc = 1; |
95 | __u8 ttl = 0; | |
96 | __u8 tos = 0; | |
97 | int len; | |
80c24b09 TH |
98 | __u16 encaptype = 0; |
99 | __u16 encapflags = 0; | |
100 | __u16 encapsport = 0; | |
101 | __u16 encapdport = 0; | |
926b39e1 | 102 | __u8 metadata = 0; |
adbb2965 | 103 | __u8 ignore_df = 0; |
ad4b1425 | 104 | __u32 fwmark = 0; |
9a1381d5 | 105 | __u32 erspan_idx = 0; |
28976362 WT |
106 | __u8 erspan_ver = 0; |
107 | __u8 erspan_dir = 0; | |
108 | __u16 erspan_hwid = 0; | |
72c771b2 HX |
109 | |
110 | if (!(n->nlmsg_flags & NLM_F_CREATE)) { | |
86bf43c7 | 111 | if (rtnl_talk(&rth, &req.n, &answer) < 0) { |
72c771b2 HX |
112 | get_failed: |
113 | fprintf(stderr, | |
114 | "Failed to get existing tunnel info.\n"); | |
115 | return -1; | |
116 | } | |
117 | ||
86bf43c7 | 118 | len = answer->nlmsg_len; |
72c771b2 HX |
119 | len -= NLMSG_LENGTH(sizeof(*ifi)); |
120 | if (len < 0) | |
121 | goto get_failed; | |
122 | ||
86bf43c7 | 123 | parse_rtattr(tb, IFLA_MAX, IFLA_RTA(NLMSG_DATA(answer)), len); |
72c771b2 HX |
124 | |
125 | if (!tb[IFLA_LINKINFO]) | |
126 | goto get_failed; | |
127 | ||
128 | parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); | |
129 | ||
130 | if (!linkinfo[IFLA_INFO_DATA]) | |
131 | goto get_failed; | |
132 | ||
133 | parse_rtattr_nested(greinfo, IFLA_GRE_MAX, | |
134 | linkinfo[IFLA_INFO_DATA]); | |
135 | ||
136 | if (greinfo[IFLA_GRE_IKEY]) | |
ff24746c | 137 | ikey = rta_getattr_u32(greinfo[IFLA_GRE_IKEY]); |
72c771b2 HX |
138 | |
139 | if (greinfo[IFLA_GRE_OKEY]) | |
ff24746c | 140 | okey = rta_getattr_u32(greinfo[IFLA_GRE_OKEY]); |
72c771b2 HX |
141 | |
142 | if (greinfo[IFLA_GRE_IFLAGS]) | |
ff24746c | 143 | iflags = rta_getattr_u16(greinfo[IFLA_GRE_IFLAGS]); |
72c771b2 HX |
144 | |
145 | if (greinfo[IFLA_GRE_OFLAGS]) | |
ff24746c | 146 | oflags = rta_getattr_u16(greinfo[IFLA_GRE_OFLAGS]); |
72c771b2 HX |
147 | |
148 | if (greinfo[IFLA_GRE_LOCAL]) | |
ff24746c | 149 | saddr = rta_getattr_u32(greinfo[IFLA_GRE_LOCAL]); |
72c771b2 HX |
150 | |
151 | if (greinfo[IFLA_GRE_REMOTE]) | |
ff24746c | 152 | daddr = rta_getattr_u32(greinfo[IFLA_GRE_REMOTE]); |
72c771b2 HX |
153 | |
154 | if (greinfo[IFLA_GRE_PMTUDISC]) | |
ff24746c | 155 | pmtudisc = rta_getattr_u8( |
72c771b2 HX |
156 | greinfo[IFLA_GRE_PMTUDISC]); |
157 | ||
158 | if (greinfo[IFLA_GRE_TTL]) | |
ff24746c | 159 | ttl = rta_getattr_u8(greinfo[IFLA_GRE_TTL]); |
72c771b2 HX |
160 | |
161 | if (greinfo[IFLA_GRE_TOS]) | |
ff24746c | 162 | tos = rta_getattr_u8(greinfo[IFLA_GRE_TOS]); |
72c771b2 HX |
163 | |
164 | if (greinfo[IFLA_GRE_LINK]) | |
a6addd5c | 165 | link = rta_getattr_u32(greinfo[IFLA_GRE_LINK]); |
80c24b09 TH |
166 | |
167 | if (greinfo[IFLA_GRE_ENCAP_TYPE]) | |
168 | encaptype = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_TYPE]); | |
169 | if (greinfo[IFLA_GRE_ENCAP_FLAGS]) | |
170 | encapflags = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_FLAGS]); | |
171 | if (greinfo[IFLA_GRE_ENCAP_SPORT]) | |
172 | encapsport = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_SPORT]); | |
173 | if (greinfo[IFLA_GRE_ENCAP_DPORT]) | |
174 | encapdport = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_DPORT]); | |
926b39e1 PA |
175 | |
176 | if (greinfo[IFLA_GRE_COLLECT_METADATA]) | |
177 | metadata = 1; | |
ad4b1425 | 178 | |
adbb2965 PP |
179 | if (greinfo[IFLA_GRE_IGNORE_DF]) |
180 | ignore_df = | |
181 | !!rta_getattr_u8(greinfo[IFLA_GRE_IGNORE_DF]); | |
182 | ||
ad4b1425 CG |
183 | if (greinfo[IFLA_GRE_FWMARK]) |
184 | fwmark = rta_getattr_u32(greinfo[IFLA_GRE_FWMARK]); | |
9a1381d5 WT |
185 | |
186 | if (greinfo[IFLA_GRE_ERSPAN_INDEX]) | |
187 | erspan_idx = rta_getattr_u32(greinfo[IFLA_GRE_ERSPAN_INDEX]); | |
86bf43c7 | 188 | |
28976362 WT |
189 | if (greinfo[IFLA_GRE_ERSPAN_VER]) |
190 | erspan_ver = rta_getattr_u8(greinfo[IFLA_GRE_ERSPAN_VER]); | |
191 | ||
192 | if (greinfo[IFLA_GRE_ERSPAN_DIR]) | |
193 | erspan_dir = rta_getattr_u8(greinfo[IFLA_GRE_ERSPAN_DIR]); | |
194 | ||
195 | if (greinfo[IFLA_GRE_ERSPAN_HWID]) | |
196 | erspan_hwid = rta_getattr_u16(greinfo[IFLA_GRE_ERSPAN_HWID]); | |
197 | ||
86bf43c7 | 198 | free(answer); |
72c771b2 | 199 | } |
237d9e82 HX |
200 | |
201 | while (argc > 0) { | |
202 | if (!matches(*argv, "key")) { | |
237d9e82 HX |
203 | NEXT_ARG(); |
204 | iflags |= GRE_KEY; | |
205 | oflags |= GRE_KEY; | |
1f44b937 | 206 | ikey = okey = tnl_parse_key("key", *argv); |
237d9e82 | 207 | } else if (!matches(*argv, "ikey")) { |
237d9e82 HX |
208 | NEXT_ARG(); |
209 | iflags |= GRE_KEY; | |
1f44b937 | 210 | ikey = tnl_parse_key("ikey", *argv); |
237d9e82 | 211 | } else if (!matches(*argv, "okey")) { |
237d9e82 HX |
212 | NEXT_ARG(); |
213 | oflags |= GRE_KEY; | |
1f44b937 | 214 | okey = tnl_parse_key("okey", *argv); |
237d9e82 HX |
215 | } else if (!matches(*argv, "seq")) { |
216 | iflags |= GRE_SEQ; | |
217 | oflags |= GRE_SEQ; | |
218 | } else if (!matches(*argv, "iseq")) { | |
219 | iflags |= GRE_SEQ; | |
220 | } else if (!matches(*argv, "oseq")) { | |
221 | oflags |= GRE_SEQ; | |
222 | } else if (!matches(*argv, "csum")) { | |
223 | iflags |= GRE_CSUM; | |
224 | oflags |= GRE_CSUM; | |
225 | } else if (!matches(*argv, "icsum")) { | |
226 | iflags |= GRE_CSUM; | |
227 | } else if (!matches(*argv, "ocsum")) { | |
228 | oflags |= GRE_CSUM; | |
229 | } else if (!matches(*argv, "nopmtudisc")) { | |
72c771b2 | 230 | pmtudisc = 0; |
237d9e82 | 231 | } else if (!matches(*argv, "pmtudisc")) { |
72c771b2 | 232 | pmtudisc = 1; |
237d9e82 HX |
233 | } else if (!matches(*argv, "remote")) { |
234 | NEXT_ARG(); | |
57daab1e | 235 | daddr = get_addr32(*argv); |
237d9e82 HX |
236 | } else if (!matches(*argv, "local")) { |
237 | NEXT_ARG(); | |
57daab1e | 238 | saddr = get_addr32(*argv); |
237d9e82 | 239 | } else if (!matches(*argv, "dev")) { |
237d9e82 | 240 | NEXT_ARG(); |
7a14358b | 241 | link = ll_name_to_index(*argv); |
0cb6bb51 CW |
242 | if (link == 0) { |
243 | fprintf(stderr, "Cannot find device \"%s\"\n", | |
244 | *argv); | |
237d9e82 | 245 | exit(-1); |
0cb6bb51 | 246 | } |
237d9e82 | 247 | } else if (!matches(*argv, "ttl") || |
c4743c4d SP |
248 | !matches(*argv, "hoplimit") || |
249 | !matches(*argv, "hlim")) { | |
237d9e82 HX |
250 | NEXT_ARG(); |
251 | if (strcmp(*argv, "inherit") != 0) { | |
c4743c4d | 252 | if (get_u8(&ttl, *argv, 0)) |
237d9e82 | 253 | invarg("invalid TTL\n", *argv); |
079e6781 RS |
254 | } else |
255 | ttl = 0; | |
237d9e82 HX |
256 | } else if (!matches(*argv, "tos") || |
257 | !matches(*argv, "tclass") || | |
258 | !matches(*argv, "dsfield")) { | |
259 | __u32 uval; | |
237d9e82 HX |
260 | |
261 | NEXT_ARG(); | |
262 | if (strcmp(*argv, "inherit") != 0) { | |
263 | if (rtnl_dsfield_a2n(&uval, *argv)) | |
264 | invarg("bad TOS value", *argv); | |
265 | tos = uval; | |
266 | } else | |
267 | tos = 1; | |
80c24b09 TH |
268 | } else if (strcmp(*argv, "noencap") == 0) { |
269 | encaptype = TUNNEL_ENCAP_NONE; | |
270 | } else if (strcmp(*argv, "encap") == 0) { | |
271 | NEXT_ARG(); | |
272 | if (strcmp(*argv, "fou") == 0) | |
273 | encaptype = TUNNEL_ENCAP_FOU; | |
274 | else if (strcmp(*argv, "gue") == 0) | |
275 | encaptype = TUNNEL_ENCAP_GUE; | |
276 | else if (strcmp(*argv, "none") == 0) | |
277 | encaptype = TUNNEL_ENCAP_NONE; | |
278 | else | |
279 | invarg("Invalid encap type.", *argv); | |
280 | } else if (strcmp(*argv, "encap-sport") == 0) { | |
281 | NEXT_ARG(); | |
282 | if (strcmp(*argv, "auto") == 0) | |
283 | encapsport = 0; | |
284 | else if (get_u16(&encapsport, *argv, 0)) | |
285 | invarg("Invalid source port.", *argv); | |
286 | } else if (strcmp(*argv, "encap-dport") == 0) { | |
287 | NEXT_ARG(); | |
288 | if (get_u16(&encapdport, *argv, 0)) | |
289 | invarg("Invalid destination port.", *argv); | |
290 | } else if (strcmp(*argv, "encap-csum") == 0) { | |
291 | encapflags |= TUNNEL_ENCAP_FLAG_CSUM; | |
292 | } else if (strcmp(*argv, "noencap-csum") == 0) { | |
293 | encapflags &= ~TUNNEL_ENCAP_FLAG_CSUM; | |
294 | } else if (strcmp(*argv, "encap-udp6-csum") == 0) { | |
295 | encapflags |= TUNNEL_ENCAP_FLAG_CSUM6; | |
296 | } else if (strcmp(*argv, "noencap-udp6-csum") == 0) { | |
147ade01 | 297 | encapflags &= ~TUNNEL_ENCAP_FLAG_CSUM6; |
858dbb20 TH |
298 | } else if (strcmp(*argv, "encap-remcsum") == 0) { |
299 | encapflags |= TUNNEL_ENCAP_FLAG_REMCSUM; | |
300 | } else if (strcmp(*argv, "noencap-remcsum") == 0) { | |
147ade01 | 301 | encapflags &= ~TUNNEL_ENCAP_FLAG_REMCSUM; |
926b39e1 PA |
302 | } else if (strcmp(*argv, "external") == 0) { |
303 | metadata = 1; | |
adbb2965 PP |
304 | } else if (strcmp(*argv, "ignore-df") == 0) { |
305 | ignore_df = 1; | |
306 | } else if (strcmp(*argv, "noignore-df") == 0) { | |
307 | /* | |
308 | *only the lsb is significant, use 2 for presence | |
309 | */ | |
310 | ignore_df = 2; | |
ad4b1425 CG |
311 | } else if (strcmp(*argv, "fwmark") == 0) { |
312 | NEXT_ARG(); | |
313 | if (get_u32(&fwmark, *argv, 0)) | |
314 | invarg("invalid fwmark\n", *argv); | |
9a1381d5 WT |
315 | } else if (strcmp(*argv, "erspan") == 0) { |
316 | NEXT_ARG(); | |
317 | if (get_u32(&erspan_idx, *argv, 0)) | |
318 | invarg("invalid erspan index\n", *argv); | |
319 | if (erspan_idx & ~((1<<20) - 1) || erspan_idx == 0) | |
320 | invarg("erspan index must be > 0 and <= 20-bit\n", *argv); | |
28976362 WT |
321 | } else if (strcmp(*argv, "erspan_ver") == 0) { |
322 | NEXT_ARG(); | |
323 | if (get_u8(&erspan_ver, *argv, 0)) | |
324 | invarg("invalid erspan version\n", *argv); | |
325 | if (erspan_ver != 1 && erspan_ver != 2) | |
326 | invarg("erspan version must be 1 or 2\n", *argv); | |
327 | } else if (strcmp(*argv, "erspan_dir") == 0) { | |
328 | NEXT_ARG(); | |
329 | if (matches(*argv, "ingress") == 0) | |
330 | erspan_dir = 0; | |
331 | else if (matches(*argv, "egress") == 0) | |
332 | erspan_dir = 1; | |
333 | else | |
334 | invarg("Invalid erspan direction.", *argv); | |
335 | } else if (strcmp(*argv, "erspan_hwid") == 0) { | |
336 | NEXT_ARG(); | |
337 | if (get_u16(&erspan_hwid, *argv, 0)) | |
338 | invarg("invalid erspan hwid\n", *argv); | |
0612519e | 339 | } else |
237d9e82 HX |
340 | usage(); |
341 | argc--; argv++; | |
342 | } | |
343 | ||
344 | if (!ikey && IN_MULTICAST(ntohl(daddr))) { | |
345 | ikey = daddr; | |
346 | iflags |= GRE_KEY; | |
347 | } | |
348 | if (!okey && IN_MULTICAST(ntohl(daddr))) { | |
349 | okey = daddr; | |
350 | oflags |= GRE_KEY; | |
351 | } | |
352 | if (IN_MULTICAST(ntohl(daddr)) && !saddr) { | |
14645ec2 | 353 | fprintf(stderr, "A broadcast tunnel requires a source address.\n"); |
237d9e82 HX |
354 | return -1; |
355 | } | |
356 | ||
df217d5d JB |
357 | if (!metadata) { |
358 | addattr32(n, 1024, IFLA_GRE_IKEY, ikey); | |
359 | addattr32(n, 1024, IFLA_GRE_OKEY, okey); | |
360 | addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2); | |
361 | addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2); | |
362 | addattr_l(n, 1024, IFLA_GRE_LOCAL, &saddr, 4); | |
363 | addattr_l(n, 1024, IFLA_GRE_REMOTE, &daddr, 4); | |
364 | addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &pmtudisc, 1); | |
de54cdd3 SP |
365 | if (ignore_df) |
366 | addattr8(n, 1024, IFLA_GRE_IGNORE_DF, ignore_df & 1); | |
df217d5d JB |
367 | if (link) |
368 | addattr32(n, 1024, IFLA_GRE_LINK, link); | |
369 | addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1); | |
370 | addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1); | |
ad4b1425 | 371 | addattr32(n, 1024, IFLA_GRE_FWMARK, fwmark); |
28976362 WT |
372 | if (erspan_ver) { |
373 | addattr8(n, 1024, IFLA_GRE_ERSPAN_VER, erspan_ver); | |
374 | if (erspan_ver == 1 && erspan_idx != 0) { | |
de54cdd3 SP |
375 | addattr32(n, 1024, |
376 | IFLA_GRE_ERSPAN_INDEX, erspan_idx); | |
28976362 | 377 | } else if (erspan_ver == 2) { |
de54cdd3 SP |
378 | addattr8(n, 1024, |
379 | IFLA_GRE_ERSPAN_DIR, erspan_dir); | |
380 | addattr16(n, 1024, | |
381 | IFLA_GRE_ERSPAN_HWID, erspan_hwid); | |
28976362 WT |
382 | } |
383 | } | |
de54cdd3 SP |
384 | addattr16(n, 1024, IFLA_GRE_ENCAP_TYPE, encaptype); |
385 | addattr16(n, 1024, IFLA_GRE_ENCAP_FLAGS, encapflags); | |
386 | addattr16(n, 1024, IFLA_GRE_ENCAP_SPORT, htons(encapsport)); | |
387 | addattr16(n, 1024, IFLA_GRE_ENCAP_DPORT, htons(encapdport)); | |
df217d5d JB |
388 | } else { |
389 | addattr_l(n, 1024, IFLA_GRE_COLLECT_METADATA, NULL, 0); | |
390 | } | |
237d9e82 HX |
391 | |
392 | return 0; | |
393 | } | |
394 | ||
00ff4b8e | 395 | static void gre_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) |
237d9e82 | 396 | { |
237d9e82 | 397 | char s2[64]; |
56f5daac SH |
398 | unsigned int iflags = 0; |
399 | unsigned int oflags = 0; | |
375560c4 | 400 | __u8 ttl = 0; |
3caa526c | 401 | __u8 tos = 0; |
237d9e82 | 402 | |
00ff4b8e SP |
403 | if (!tb) |
404 | return; | |
405 | ||
406 | if (tb[IFLA_GRE_COLLECT_METADATA]) { | |
407 | print_bool(PRINT_ANY, "external", "external", true); | |
408 | return; | |
409 | } | |
410 | ||
b761fc41 SP |
411 | tnl_print_endpoint("remote", tb[IFLA_GRE_REMOTE], AF_INET); |
412 | tnl_print_endpoint("local", tb[IFLA_GRE_LOCAL], AF_INET); | |
237d9e82 | 413 | |
45d3a6ef | 414 | if (tb[IFLA_GRE_LINK]) { |
56f5daac | 415 | unsigned int link = rta_getattr_u32(tb[IFLA_GRE_LINK]); |
237d9e82 | 416 | |
45d3a6ef SP |
417 | if (link) { |
418 | print_string(PRINT_ANY, "link", "dev %s ", | |
419 | ll_index_to_name(link)); | |
420 | } | |
237d9e82 HX |
421 | } |
422 | ||
375560c4 SP |
423 | if (tb[IFLA_GRE_TTL]) |
424 | ttl = rta_getattr_u8(tb[IFLA_GRE_TTL]); | |
425 | if (is_json_context() || ttl) | |
426 | print_uint(PRINT_ANY, "ttl", "ttl %u ", ttl); | |
427 | else | |
e2d45883 | 428 | print_string(PRINT_FP, NULL, "ttl %s ", "inherit"); |
e2d45883 | 429 | |
3caa526c SP |
430 | if (tb[IFLA_GRE_TOS]) |
431 | tos = rta_getattr_u8(tb[IFLA_GRE_TOS]); | |
432 | if (tos) { | |
433 | if (is_json_context() || tos != 1) | |
434 | print_0xhex(PRINT_ANY, "tos", "tos 0x%x ", tos); | |
435 | else | |
436 | print_string(PRINT_FP, NULL, "tos %s ", "inherit"); | |
237d9e82 HX |
437 | } |
438 | ||
e2d45883 JF |
439 | if (tb[IFLA_GRE_PMTUDISC]) { |
440 | if (!rta_getattr_u8(tb[IFLA_GRE_PMTUDISC])) | |
441 | print_bool(PRINT_ANY, "pmtudisc", "nopmtudisc ", false); | |
442 | else | |
443 | print_bool(PRINT_JSON, "pmtudisc", NULL, true); | |
444 | } | |
237d9e82 | 445 | |
00ff4b8e SP |
446 | if (tb[IFLA_GRE_IGNORE_DF] && rta_getattr_u8(tb[IFLA_GRE_IGNORE_DF])) |
447 | print_bool(PRINT_ANY, "ignore_df", "ignore-df ", true); | |
448 | ||
237d9e82 | 449 | if (tb[IFLA_GRE_IFLAGS]) |
ff24746c | 450 | iflags = rta_getattr_u16(tb[IFLA_GRE_IFLAGS]); |
237d9e82 HX |
451 | |
452 | if (tb[IFLA_GRE_OFLAGS]) | |
ff24746c | 453 | oflags = rta_getattr_u16(tb[IFLA_GRE_OFLAGS]); |
237d9e82 | 454 | |
71816553 | 455 | if ((iflags & GRE_KEY) && tb[IFLA_GRE_IKEY]) { |
237d9e82 | 456 | inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_IKEY]), s2, sizeof(s2)); |
e2d45883 | 457 | print_string(PRINT_ANY, "ikey", "ikey %s ", s2); |
237d9e82 HX |
458 | } |
459 | ||
71816553 | 460 | if ((oflags & GRE_KEY) && tb[IFLA_GRE_OKEY]) { |
237d9e82 | 461 | inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2)); |
e2d45883 | 462 | print_string(PRINT_ANY, "okey", "okey %s ", s2); |
237d9e82 HX |
463 | } |
464 | ||
465 | if (iflags & GRE_SEQ) | |
e2d45883 | 466 | print_bool(PRINT_ANY, "iseq", "iseq ", true); |
237d9e82 | 467 | if (oflags & GRE_SEQ) |
e2d45883 | 468 | print_bool(PRINT_ANY, "oseq", "oseq ", true); |
237d9e82 | 469 | if (iflags & GRE_CSUM) |
e2d45883 | 470 | print_bool(PRINT_ANY, "icsum", "icsum ", true); |
237d9e82 | 471 | if (oflags & GRE_CSUM) |
e2d45883 JF |
472 | print_bool(PRINT_ANY, "ocsum", "ocsum ", true); |
473 | ||
474 | if (tb[IFLA_GRE_FWMARK]) { | |
475 | __u32 fwmark = rta_getattr_u32(tb[IFLA_GRE_FWMARK]); | |
476 | ||
477 | if (fwmark) { | |
e97ad3d2 SP |
478 | print_0xhex(PRINT_ANY, |
479 | "fwmark", "fwmark 0x%x ", fwmark); | |
e2d45883 | 480 | } |
ad4b1425 | 481 | } |
adbb2965 | 482 | |
9a1381d5 WT |
483 | if (tb[IFLA_GRE_ERSPAN_INDEX]) { |
484 | __u32 erspan_idx = rta_getattr_u32(tb[IFLA_GRE_ERSPAN_INDEX]); | |
485 | ||
3cb92eb9 SP |
486 | print_uint(PRINT_ANY, |
487 | "erspan_index", "erspan_index %u ", erspan_idx); | |
28976362 WT |
488 | } |
489 | ||
490 | if (tb[IFLA_GRE_ERSPAN_VER]) { | |
491 | __u8 erspan_ver = rta_getattr_u8(tb[IFLA_GRE_ERSPAN_VER]); | |
492 | ||
493 | print_uint(PRINT_ANY, "erspan_ver", "erspan_ver %u ", erspan_ver); | |
494 | } | |
495 | ||
496 | if (tb[IFLA_GRE_ERSPAN_DIR]) { | |
497 | __u8 erspan_dir = rta_getattr_u8(tb[IFLA_GRE_ERSPAN_DIR]); | |
498 | ||
499 | if (erspan_dir == 0) | |
500 | print_string(PRINT_ANY, "erspan_dir", | |
501 | "erspan_dir ingress ", NULL); | |
502 | else | |
503 | print_string(PRINT_ANY, "erspan_dir", | |
504 | "erspan_dir egress ", NULL); | |
505 | } | |
506 | ||
507 | if (tb[IFLA_GRE_ERSPAN_HWID]) { | |
508 | __u16 erspan_hwid = rta_getattr_u16(tb[IFLA_GRE_ERSPAN_HWID]); | |
509 | ||
510 | print_hex(PRINT_ANY, "erspan_hwid", "erspan_hwid 0x%x ", erspan_hwid); | |
9a1381d5 WT |
511 | } |
512 | ||
bad76e6b SP |
513 | tnl_print_encap(tb, |
514 | IFLA_GRE_ENCAP_TYPE, | |
515 | IFLA_GRE_ENCAP_FLAGS, | |
516 | IFLA_GRE_ENCAP_SPORT, | |
517 | IFLA_GRE_ENCAP_DPORT); | |
237d9e82 HX |
518 | } |
519 | ||
561e650e | 520 | static void gre_print_help(struct link_util *lu, int argc, char **argv, |
e2d45883 | 521 | FILE *f) |
561e650e | 522 | { |
523 | print_usage(f); | |
524 | } | |
525 | ||
237d9e82 HX |
526 | struct link_util gre_link_util = { |
527 | .id = "gre", | |
528 | .maxattr = IFLA_GRE_MAX, | |
529 | .parse_opt = gre_parse_opt, | |
530 | .print_opt = gre_print_opt, | |
561e650e | 531 | .print_help = gre_print_help, |
237d9e82 HX |
532 | }; |
533 | ||
534 | struct link_util gretap_link_util = { | |
535 | .id = "gretap", | |
536 | .maxattr = IFLA_GRE_MAX, | |
537 | .parse_opt = gre_parse_opt, | |
538 | .print_opt = gre_print_opt, | |
561e650e | 539 | .print_help = gre_print_help, |
237d9e82 | 540 | }; |
9a1381d5 WT |
541 | |
542 | struct link_util erspan_link_util = { | |
543 | .id = "erspan", | |
544 | .maxattr = IFLA_GRE_MAX, | |
545 | .parse_opt = gre_parse_opt, | |
546 | .print_opt = gre_print_opt, | |
547 | .print_help = gre_print_help, | |
548 | }; |