]> git.proxmox.com Git - mirror_iproute2.git/blame - tc/m_tunnel_key.c
tc: m_action: check cookie hex string len
[mirror_iproute2.git] / tc / m_tunnel_key.c
CommitLineData
d57639a4
AV
1/*
2 * m_tunnel_key.c ip tunnel manipulation 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: Amir Vadai <amir@vadai.me>
10 */
11
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
15#include <string.h>
16#include <linux/if_ether.h>
17#include "utils.h"
18#include "rt_names.h"
19#include "tc_util.h"
20#include <linux/tc_act/tc_tunnel_key.h>
21
22static void explain(void)
23{
50907a82 24 fprintf(stderr,
8589eb4e
MC
25 "Usage: tunnel_key unset\n"
26 " tunnel_key set <TUNNEL_KEY>\n"
50907a82 27 "Where TUNNEL_KEY is a combination of:\n"
dc0332b1 28 "id <TUNNELID>\n"
50907a82
JB
29 "src_ip <IP> (mandatory)\n"
30 "dst_ip <IP> (mandatory)\n"
59eb271d 31 "dst_port <UDP_PORT>\n"
6217917a 32 "geneve_opts <OPTIONS>\n"
59eb271d 33 "csum | nocsum (default is \"csum\")\n");
d57639a4
AV
34}
35
36static void usage(void)
37{
38 explain();
39 exit(-1);
40}
41
42static int tunnel_key_parse_ip_addr(const char *str, int addr4_type,
43 int addr6_type, struct nlmsghdr *n)
44{
45 inet_prefix addr;
46 int ret;
47
48 ret = get_addr(&addr, str, AF_UNSPEC);
49 if (ret)
50 return ret;
51
52 addattr_l(n, MAX_MSG, addr.family == AF_INET ? addr4_type : addr6_type,
53 addr.data, addr.bytelen);
54
55 return 0;
56}
57
58static int tunnel_key_parse_key_id(const char *str, int type,
59 struct nlmsghdr *n)
60{
61 __be32 key_id;
62 int ret;
63
64 ret = get_be32(&key_id, str, 10);
65 if (!ret)
66 addattr32(n, MAX_MSG, type, key_id);
67
68 return ret;
69}
70
449c709c
HHZ
71static int tunnel_key_parse_dst_port(char *str, int type, struct nlmsghdr *n)
72{
73 int ret;
74 __be16 dst_port;
75
76 ret = get_be16(&dst_port, str, 10);
77 if (ret)
78 return -1;
79
80 addattr16(n, MAX_MSG, type, dst_port);
81
82 return 0;
83}
84
6217917a
SH
85static int tunnel_key_parse_be16(char *str, int base, int type,
86 struct nlmsghdr *n)
87{
88 int ret;
89 __be16 value;
90
91 ret = get_be16(&value, str, base);
92 if (ret)
93 return ret;
94
95 addattr16(n, MAX_MSG, type, value);
96
97 return 0;
98}
99
100static int tunnel_key_parse_u8(char *str, int base, int type,
101 struct nlmsghdr *n)
102{
103 int ret;
104 __u8 value;
105
106 ret = get_u8(&value, str, base);
107 if (ret)
108 return ret;
109
110 addattr8(n, MAX_MSG, type, value);
111
112 return 0;
113}
114
115static int tunnel_key_parse_geneve_opt(char *str, struct nlmsghdr *n)
116{
117 char *token, *saveptr = NULL;
118 struct rtattr *nest;
119 int i, ret;
120
121 nest = addattr_nest(n, MAX_MSG, TCA_TUNNEL_KEY_ENC_OPTS_GENEVE);
122
123 token = strtok_r(str, ":", &saveptr);
124 i = 1;
125 while (token) {
126 switch (i) {
127 case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS:
128 {
129 ret = tunnel_key_parse_be16(token, 16, i, n);
130 if (ret)
131 return ret;
132 break;
133 }
134 case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE:
135 {
136 ret = tunnel_key_parse_u8(token, 16, i, n);
137 if (ret)
138 return ret;
139 break;
140 }
141 case TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA:
142 {
143 size_t token_len = strlen(token);
144 uint8_t *opts;
145
146 opts = malloc(token_len / 2);
147 if (!opts)
148 return -1;
149 if (hex2mem(token, opts, token_len / 2) < 0) {
150 free(opts);
151 return -1;
152 }
153 addattr_l(n, MAX_MSG, i, opts, token_len / 2);
154 free(opts);
155
156 break;
157 }
158 default:
159 return -1;
160 }
161
162 token = strtok_r(NULL, ":", &saveptr);
163 i++;
164 }
165
166 addattr_nest_end(n, nest);
167
168 return 0;
169}
170
171static int tunnel_key_parse_geneve_opts(char *str, struct nlmsghdr *n)
172{
173 char *token, *saveptr = NULL;
174 struct rtattr *nest;
175 int ret;
176
177 nest = addattr_nest(n, MAX_MSG, TCA_TUNNEL_KEY_ENC_OPTS);
178
179 token = strtok_r(str, ",", &saveptr);
180 while (token) {
181 ret = tunnel_key_parse_geneve_opt(token, n);
182 if (ret)
183 return ret;
184
185 token = strtok_r(NULL, ",", &saveptr);
186 }
187
188 addattr_nest_end(n, nest);
189
190 return 0;
191}
192
9f89b0cc
OG
193static int tunnel_key_parse_tos_ttl(char *str, int type, struct nlmsghdr *n)
194{
195 int ret;
196 __u8 val;
197
198 ret = get_u8(&val, str, 10);
199 if (ret)
200 ret = get_u8(&val, str, 16);
201 if (ret)
202 return -1;
203
204 addattr8(n, MAX_MSG, type, val);
205
206 return 0;
207}
208
d57639a4
AV
209static int parse_tunnel_key(struct action_util *a, int *argc_p, char ***argv_p,
210 int tca_id, struct nlmsghdr *n)
211{
e67aba55 212 struct tc_tunnel_key parm = {};
d57639a4
AV
213 char **argv = *argv_p;
214 int argc = *argc_p;
215 struct rtattr *tail;
216 int action = 0;
217 int ret;
218 int has_src_ip = 0;
219 int has_dst_ip = 0;
59eb271d 220 int csum = 1;
d57639a4
AV
221
222 if (matches(*argv, "tunnel_key") != 0)
223 return -1;
224
c14f9d92 225 tail = addattr_nest(n, MAX_MSG, tca_id);
d57639a4
AV
226
227 NEXT_ARG();
228
229 while (argc > 0) {
230 if (matches(*argv, "unset") == 0) {
231 if (action) {
232 fprintf(stderr, "unexpected \"%s\" - action already specified\n",
233 *argv);
234 explain();
235 return -1;
236 }
237 action = TCA_TUNNEL_KEY_ACT_RELEASE;
238 } else if (matches(*argv, "set") == 0) {
239 if (action) {
240 fprintf(stderr, "unexpected \"%s\" - action already specified\n",
241 *argv);
242 explain();
243 return -1;
244 }
245 action = TCA_TUNNEL_KEY_ACT_SET;
246 } else if (matches(*argv, "src_ip") == 0) {
247 NEXT_ARG();
248 ret = tunnel_key_parse_ip_addr(*argv,
249 TCA_TUNNEL_KEY_ENC_IPV4_SRC,
250 TCA_TUNNEL_KEY_ENC_IPV6_SRC,
251 n);
252 if (ret < 0) {
253 fprintf(stderr, "Illegal \"src_ip\"\n");
254 return -1;
255 }
256 has_src_ip = 1;
257 } else if (matches(*argv, "dst_ip") == 0) {
258 NEXT_ARG();
259 ret = tunnel_key_parse_ip_addr(*argv,
260 TCA_TUNNEL_KEY_ENC_IPV4_DST,
261 TCA_TUNNEL_KEY_ENC_IPV6_DST,
262 n);
263 if (ret < 0) {
264 fprintf(stderr, "Illegal \"dst_ip\"\n");
265 return -1;
266 }
267 has_dst_ip = 1;
268 } else if (matches(*argv, "id") == 0) {
269 NEXT_ARG();
270 ret = tunnel_key_parse_key_id(*argv, TCA_TUNNEL_KEY_ENC_KEY_ID, n);
271 if (ret < 0) {
272 fprintf(stderr, "Illegal \"id\"\n");
273 return -1;
274 }
449c709c
HHZ
275 } else if (matches(*argv, "dst_port") == 0) {
276 NEXT_ARG();
277 ret = tunnel_key_parse_dst_port(*argv,
278 TCA_TUNNEL_KEY_ENC_DST_PORT, n);
279 if (ret < 0) {
280 fprintf(stderr, "Illegal \"dst port\"\n");
281 return -1;
282 }
6217917a
SH
283 } else if (matches(*argv, "geneve_opts") == 0) {
284 NEXT_ARG();
285
286 if (tunnel_key_parse_geneve_opts(*argv, n)) {
287 fprintf(stderr, "Illegal \"geneve_opts\"\n");
288 return -1;
289 }
9f89b0cc
OG
290 } else if (matches(*argv, "tos") == 0) {
291 NEXT_ARG();
292 ret = tunnel_key_parse_tos_ttl(*argv,
293 TCA_TUNNEL_KEY_ENC_TOS, n);
294 if (ret < 0) {
295 fprintf(stderr, "Illegal \"tos\"\n");
296 return -1;
297 }
298 } else if (matches(*argv, "ttl") == 0) {
299 NEXT_ARG();
300 ret = tunnel_key_parse_tos_ttl(*argv,
301 TCA_TUNNEL_KEY_ENC_TTL, n);
302 if (ret < 0) {
303 fprintf(stderr, "Illegal \"ttl\"\n");
304 return -1;
305 }
59eb271d
JB
306 } else if (matches(*argv, "csum") == 0) {
307 csum = 1;
308 } else if (matches(*argv, "nocsum") == 0) {
309 csum = 0;
d57639a4
AV
310 } else if (matches(*argv, "help") == 0) {
311 usage();
312 } else {
313 break;
314 }
315 NEXT_ARG_FWD();
316 }
317
59eb271d
JB
318 addattr8(n, MAX_MSG, TCA_TUNNEL_KEY_NO_CSUM, !csum);
319
e67aba55
JP
320 parse_action_control_dflt(&argc, &argv, &parm.action,
321 false, TC_ACT_PIPE);
d57639a4
AV
322
323 if (argc) {
324 if (matches(*argv, "index") == 0) {
325 NEXT_ARG();
326 if (get_u32(&parm.index, *argv, 10)) {
327 fprintf(stderr, "tunnel_key: Illegal \"index\"\n");
328 return -1;
329 }
330
331 NEXT_ARG_FWD();
332 }
333 }
334
335 if (action == TCA_TUNNEL_KEY_ACT_SET &&
dc0332b1 336 (!has_src_ip || !has_dst_ip)) {
d57639a4
AV
337 fprintf(stderr, "set needs tunnel_key parameters\n");
338 explain();
339 return -1;
340 }
341
342 parm.t_action = action;
343 addattr_l(n, MAX_MSG, TCA_TUNNEL_KEY_PARMS, &parm, sizeof(parm));
c14f9d92 344 addattr_nest_end(n, tail);
d57639a4
AV
345
346 *argc_p = argc;
347 *argv_p = argv;
348
349 return 0;
350}
351
352static void tunnel_key_print_ip_addr(FILE *f, const char *name,
353 struct rtattr *attr)
354{
355 int family;
356 size_t len;
357
358 if (!attr)
359 return;
360
361 len = RTA_PAYLOAD(attr);
362
363 if (len == 4)
364 family = AF_INET;
365 else if (len == 16)
366 family = AF_INET6;
367 else
368 return;
369
8feb516b
RM
370 print_string(PRINT_FP, NULL, "%s", _SL_);
371 if (matches(name, "src_ip") == 0)
372 print_string(PRINT_ANY, "src_ip", "\tsrc_ip %s",
373 rt_addr_n2a_rta(family, attr));
374 else if (matches(name, "dst_ip") == 0)
375 print_string(PRINT_ANY, "dst_ip", "\tdst_ip %s",
376 rt_addr_n2a_rta(family, attr));
d57639a4
AV
377}
378
379static void tunnel_key_print_key_id(FILE *f, const char *name,
380 struct rtattr *attr)
381{
382 if (!attr)
383 return;
8feb516b
RM
384 print_string(PRINT_FP, NULL, "%s", _SL_);
385 print_uint(PRINT_ANY, "key_id", "\tkey_id %u", rta_getattr_be32(attr));
d57639a4
AV
386}
387
449c709c
HHZ
388static void tunnel_key_print_dst_port(FILE *f, char *name,
389 struct rtattr *attr)
390{
391 if (!attr)
392 return;
8feb516b
RM
393 print_string(PRINT_FP, NULL, "%s", _SL_);
394 print_uint(PRINT_ANY, "dst_port", "\tdst_port %u",
395 rta_getattr_be16(attr));
449c709c
HHZ
396}
397
59eb271d
JB
398static void tunnel_key_print_flag(FILE *f, const char *name_on,
399 const char *name_off,
400 struct rtattr *attr)
401{
402 if (!attr)
403 return;
8feb516b
RM
404 print_string(PRINT_FP, NULL, "%s", _SL_);
405 print_string(PRINT_ANY, "flag", "\t%s",
406 rta_getattr_u8(attr) ? name_on : name_off);
59eb271d
JB
407}
408
6217917a
SH
409static void tunnel_key_print_geneve_options(const char *name,
410 struct rtattr *attr)
411{
412 struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX + 1];
413 struct rtattr *i = RTA_DATA(attr);
414 int ii, data_len = 0, offset = 0;
415 int rem = RTA_PAYLOAD(attr);
416 char strbuf[rem * 2 + 1];
417 char data[rem * 2 + 1];
418 uint8_t data_r[rem];
419 uint16_t clss;
420 uint8_t type;
421
422 open_json_array(PRINT_JSON, name);
7b0d424a
SH
423 print_nl();
424 print_string(PRINT_FP, name, "\t%s ", "geneve_opt");
6217917a
SH
425
426 while (rem) {
427 parse_rtattr(tb, TCA_TUNNEL_KEY_ENC_OPT_GENEVE_MAX, i, rem);
428 clss = rta_getattr_be16(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_CLASS]);
429 type = rta_getattr_u8(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_TYPE]);
430 data_len = RTA_PAYLOAD(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]);
431 hexstring_n2a(RTA_DATA(tb[TCA_TUNNEL_KEY_ENC_OPT_GENEVE_DATA]),
432 data_len, data, sizeof(data));
433 hex2mem(data, data_r, data_len);
434 offset += data_len + 20;
435 rem -= data_len + 20;
436 i = RTA_DATA(attr) + offset;
437
438 open_json_object(NULL);
439 print_uint(PRINT_JSON, "class", NULL, clss);
440 print_uint(PRINT_JSON, "type", NULL, type);
441 open_json_array(PRINT_JSON, "data");
442 for (ii = 0; ii < data_len; ii++)
443 print_uint(PRINT_JSON, NULL, NULL, data_r[ii]);
444 close_json_array(PRINT_JSON, "data");
445 close_json_object();
446
447 sprintf(strbuf, "%04x:%02x:%s", clss, type, data);
448 if (rem)
449 print_string(PRINT_FP, NULL, "%s,", strbuf);
450 else
451 print_string(PRINT_FP, NULL, "%s", strbuf);
452 }
453
454 close_json_array(PRINT_JSON, name);
455}
456
457static void tunnel_key_print_key_opt(const char *name, struct rtattr *attr)
458{
459 struct rtattr *tb[TCA_TUNNEL_KEY_ENC_OPTS_MAX + 1];
460
461 if (!attr)
462 return;
463
464 parse_rtattr_nested(tb, TCA_TUNNEL_KEY_ENC_OPTS_MAX, attr);
465 tunnel_key_print_geneve_options(name,
466 tb[TCA_TUNNEL_KEY_ENC_OPTS_GENEVE]);
467}
468
9f89b0cc
OG
469static void tunnel_key_print_tos_ttl(FILE *f, char *name,
470 struct rtattr *attr)
471{
472 if (!attr)
473 return;
474
475 if (matches(name, "tos") == 0 && rta_getattr_u8(attr) != 0) {
476 print_string(PRINT_FP, NULL, "%s", _SL_);
477 print_uint(PRINT_ANY, "tos", "\ttos 0x%x",
478 rta_getattr_u8(attr));
479 } else if (matches(name, "ttl") == 0 && rta_getattr_u8(attr) != 0) {
480 print_string(PRINT_FP, NULL, "%s", _SL_);
481 print_uint(PRINT_ANY, "ttl", "\tttl %u",
482 rta_getattr_u8(attr));
483 }
484}
485
d57639a4
AV
486static int print_tunnel_key(struct action_util *au, FILE *f, struct rtattr *arg)
487{
488 struct rtattr *tb[TCA_TUNNEL_KEY_MAX + 1];
489 struct tc_tunnel_key *parm;
490
491 if (!arg)
492 return -1;
493
494 parse_rtattr_nested(tb, TCA_TUNNEL_KEY_MAX, arg);
495
496 if (!tb[TCA_TUNNEL_KEY_PARMS]) {
d5ddb441 497 fprintf(stderr, "Missing tunnel_key parameters\n");
d57639a4
AV
498 return -1;
499 }
500 parm = RTA_DATA(tb[TCA_TUNNEL_KEY_PARMS]);
501
8feb516b 502 print_string(PRINT_ANY, "kind", "%s ", "tunnel_key");
d57639a4
AV
503
504 switch (parm->t_action) {
505 case TCA_TUNNEL_KEY_ACT_RELEASE:
8feb516b 506 print_string(PRINT_ANY, "mode", " %s", "unset");
d57639a4
AV
507 break;
508 case TCA_TUNNEL_KEY_ACT_SET:
8feb516b 509 print_string(PRINT_ANY, "mode", " %s", "set");
d57639a4
AV
510 tunnel_key_print_ip_addr(f, "src_ip",
511 tb[TCA_TUNNEL_KEY_ENC_IPV4_SRC]);
512 tunnel_key_print_ip_addr(f, "dst_ip",
513 tb[TCA_TUNNEL_KEY_ENC_IPV4_DST]);
514 tunnel_key_print_ip_addr(f, "src_ip",
515 tb[TCA_TUNNEL_KEY_ENC_IPV6_SRC]);
516 tunnel_key_print_ip_addr(f, "dst_ip",
517 tb[TCA_TUNNEL_KEY_ENC_IPV6_DST]);
518 tunnel_key_print_key_id(f, "key_id",
519 tb[TCA_TUNNEL_KEY_ENC_KEY_ID]);
449c709c
HHZ
520 tunnel_key_print_dst_port(f, "dst_port",
521 tb[TCA_TUNNEL_KEY_ENC_DST_PORT]);
6217917a
SH
522 tunnel_key_print_key_opt("geneve_opts",
523 tb[TCA_TUNNEL_KEY_ENC_OPTS]);
59eb271d
JB
524 tunnel_key_print_flag(f, "nocsum", "csum",
525 tb[TCA_TUNNEL_KEY_NO_CSUM]);
9f89b0cc
OG
526 tunnel_key_print_tos_ttl(f, "tos",
527 tb[TCA_TUNNEL_KEY_ENC_TOS]);
528 tunnel_key_print_tos_ttl(f, "ttl",
529 tb[TCA_TUNNEL_KEY_ENC_TTL]);
d57639a4
AV
530 break;
531 }
e67aba55 532 print_action_control(f, " ", parm->action, "");
d57639a4 533
8feb516b
RM
534 print_string(PRINT_FP, NULL, "%s", _SL_);
535 print_uint(PRINT_ANY, "index", "\t index %u", parm->index);
536 print_int(PRINT_ANY, "ref", " ref %d", parm->refcnt);
537 print_int(PRINT_ANY, "bind", " bind %d", parm->bindcnt);
d57639a4
AV
538
539 if (show_stats) {
540 if (tb[TCA_TUNNEL_KEY_TM]) {
541 struct tcf_t *tm = RTA_DATA(tb[TCA_TUNNEL_KEY_TM]);
542
543 print_tm(f, tm);
544 }
545 }
546
8feb516b 547 print_string(PRINT_FP, NULL, "%s", _SL_);
d57639a4
AV
548
549 return 0;
550}
551
552struct action_util tunnel_key_action_util = {
553 .id = "tunnel_key",
554 .parse_aopt = parse_tunnel_key,
555 .print_aopt = print_tunnel_key,
556};