]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_flowspec_util.c
Merge pull request #13649 from donaldsharp/unlock_the_node_or_else
[mirror_frr.git] / bgpd / bgp_flowspec_util.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* BGP FlowSpec Utilities
3 * Portions:
4 * Copyright (C) 2017 ChinaTelecom SDN Group
5 * Copyright (C) 2018 6WIND
6 */
7
8 #include "zebra.h"
9
10 #include "lib/printfrr.h"
11
12 #include "prefix.h"
13 #include "lib_errors.h"
14
15 #include "bgp_route.h"
16 #include "bgp_table.h"
17 #include "bgp_flowspec_util.h"
18 #include "bgp_flowspec_private.h"
19 #include "bgp_pbr.h"
20 #include "bgp_errors.h"
21
22 static void hex2bin(uint8_t *hex, int *bin)
23 {
24 int remainder = *hex;
25 int i = 0;
26
27 while (remainder >= 1 && i < 8) {
28 bin[7-i] = remainder % 2;
29 remainder = remainder / 2;
30 i++;
31 }
32 for (; i < 8; i++)
33 bin[7-i] = 0;
34 }
35
36 static int hexstr2num(uint8_t *hexstr, int len)
37 {
38 int i = 0;
39 int num = 0;
40
41 for (i = 0; i < len; i++)
42 num = hexstr[i] + 16*16*num;
43 return num;
44 }
45
46 /* call bgp_flowspec_op_decode
47 * returns offset
48 */
49 static int bgp_flowspec_call_non_opaque_decode(uint8_t *nlri_content, int len,
50 struct bgp_pbr_match_val *mval,
51 uint8_t *match_num, int *error)
52 {
53 int ret;
54
55 ret = bgp_flowspec_op_decode(
56 BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
57 nlri_content,
58 len,
59 mval, error);
60 if (*error < 0)
61 flog_err(EC_BGP_FLOWSPEC_PACKET,
62 "%s: flowspec_op_decode error %d", __func__, *error);
63 else
64 *match_num = *error;
65 return ret;
66 }
67
68
69 bool bgp_flowspec_contains_prefix(const struct prefix *pfs,
70 struct prefix *input, int prefix_check)
71 {
72 uint32_t offset = 0;
73 int type;
74 int ret = 0, error = 0;
75 uint8_t *nlri_content = (uint8_t *)pfs->u.prefix_flowspec.ptr;
76 size_t len = pfs->u.prefix_flowspec.prefixlen;
77 afi_t afi = family2afi(pfs->u.prefix_flowspec.family);
78 struct prefix compare;
79
80 error = 0;
81 while (offset < len-1 && error >= 0) {
82 type = nlri_content[offset];
83 offset++;
84 switch (type) {
85 case FLOWSPEC_DEST_PREFIX:
86 case FLOWSPEC_SRC_PREFIX:
87 memset(&compare, 0, sizeof(compare));
88 ret = bgp_flowspec_ip_address(
89 BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
90 nlri_content+offset,
91 len - offset,
92 &compare, &error,
93 afi, NULL);
94 if (ret <= 0)
95 break;
96 if (prefix_check &&
97 compare.prefixlen != input->prefixlen)
98 break;
99 if (compare.family != input->family)
100 break;
101 if ((input->family == AF_INET) &&
102 IPV4_ADDR_SAME(&input->u.prefix4,
103 &compare.u.prefix4))
104 return true;
105 if ((input->family == AF_INET6) &&
106 IPV6_ADDR_SAME(&input->u.prefix6.s6_addr,
107 &compare.u.prefix6.s6_addr))
108 return true;
109 break;
110 case FLOWSPEC_FLOW_LABEL:
111 if (afi == AFI_IP) {
112 error = -1;
113 continue;
114 }
115 ret = bgp_flowspec_op_decode(BGP_FLOWSPEC_VALIDATE_ONLY,
116 nlri_content+offset,
117 len - offset,
118 NULL, &error);
119 break;
120 case FLOWSPEC_IP_PROTOCOL:
121 case FLOWSPEC_PORT:
122 case FLOWSPEC_DEST_PORT:
123 case FLOWSPEC_SRC_PORT:
124 case FLOWSPEC_ICMP_TYPE:
125 case FLOWSPEC_ICMP_CODE:
126 ret = bgp_flowspec_op_decode(BGP_FLOWSPEC_VALIDATE_ONLY,
127 nlri_content+offset,
128 len - offset,
129 NULL, &error);
130 break;
131 case FLOWSPEC_FRAGMENT:
132 case FLOWSPEC_TCP_FLAGS:
133 ret = bgp_flowspec_bitmask_decode(
134 BGP_FLOWSPEC_VALIDATE_ONLY,
135 nlri_content+offset,
136 len - offset,
137 NULL, &error);
138 break;
139 case FLOWSPEC_PKT_LEN:
140 case FLOWSPEC_DSCP:
141 ret = bgp_flowspec_op_decode(
142 BGP_FLOWSPEC_VALIDATE_ONLY,
143 nlri_content + offset,
144 len - offset, NULL,
145 &error);
146 break;
147 default:
148 error = -1;
149 break;
150 }
151 offset += ret;
152 }
153 return false;
154 }
155
156 /*
157 * handle the flowspec address src/dst or generic address NLRI
158 * return number of bytes analysed ( >= 0).
159 */
160 int bgp_flowspec_ip_address(enum bgp_flowspec_util_nlri_t type,
161 uint8_t *nlri_ptr,
162 uint32_t max_len,
163 void *result, int *error,
164 afi_t afi,
165 uint8_t *ipv6_offset)
166 {
167 char *display = (char *)result; /* for return_string */
168 struct prefix *prefix = (struct prefix *)result;
169 uint32_t offset = 0;
170 struct prefix prefix_local;
171 int psize;
172 uint8_t prefix_offset = 0;
173
174 *error = 0;
175 memset(&prefix_local, 0, sizeof(prefix_local));
176 /* read the prefix length */
177 prefix_local.prefixlen = nlri_ptr[offset];
178 psize = PSIZE(prefix_local.prefixlen);
179 offset++;
180 prefix_local.family = afi2family(afi);
181 if (prefix_local.family == AF_INET6) {
182 prefix_offset = nlri_ptr[offset];
183 if (ipv6_offset)
184 *ipv6_offset = prefix_offset;
185 offset++;
186 }
187 /* Prefix length check. */
188 if (prefix_local.prefixlen > prefix_blen(&prefix_local) * 8) {
189 *error = -1;
190 return offset;
191 }
192 /* When packet overflow occur return immediately. */
193 if (psize + offset > max_len) {
194 *error = -1;
195 return offset;
196 }
197 /* Defensive coding, double-check
198 * the psize fits in a struct prefix
199 */
200 if (psize > (ssize_t)sizeof(prefix_local.u)) {
201 *error = -1;
202 return offset;
203 }
204
205 memcpy(&prefix_local.u.prefix, &nlri_ptr[offset], psize);
206 offset += psize;
207 switch (type) {
208 case BGP_FLOWSPEC_RETURN_STRING:
209 if (prefix_local.family == AF_INET6) {
210 int ret;
211
212 ret = snprintfrr(
213 display, BGP_FLOWSPEC_STRING_DISPLAY_MAX,
214 "%pFX/off %u", &prefix_local, prefix_offset);
215 if (ret < 0) {
216 *error = -1;
217 break;
218 }
219 } else
220 prefix2str(&prefix_local, display,
221 BGP_FLOWSPEC_STRING_DISPLAY_MAX);
222 break;
223 case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE:
224 if (prefix)
225 prefix_copy(prefix, &prefix_local);
226 break;
227 case BGP_FLOWSPEC_VALIDATE_ONLY:
228 case BGP_FLOWSPEC_RETURN_JSON:
229 break;
230 }
231 return offset;
232 }
233
234 /*
235 * handle the flowspec operator NLRI
236 * return number of bytes analysed
237 * if there is an error, the passed error param is used to give error:
238 * -1 if decoding error,
239 * if result is a string, its assumed length
240 * is BGP_FLOWSPEC_STRING_DISPLAY_MAX
241 */
242 int bgp_flowspec_op_decode(enum bgp_flowspec_util_nlri_t type,
243 uint8_t *nlri_ptr,
244 uint32_t max_len,
245 void *result, int *error)
246 {
247 int op[8];
248 int len, value, value_size;
249 int loop = 0;
250 char *ptr = (char *)result; /* for return_string */
251 uint32_t offset = 0;
252 int len_string = BGP_FLOWSPEC_STRING_DISPLAY_MAX;
253 int len_written;
254 struct bgp_pbr_match_val *mval = (struct bgp_pbr_match_val *)result;
255
256 *error = 0;
257 do {
258 if (loop > BGP_PBR_MATCH_VAL_MAX)
259 *error = -2;
260 hex2bin(&nlri_ptr[offset], op);
261 offset++;
262 len = 2*op[2]+op[3];
263 value_size = 1 << len;
264 value = hexstr2num(&nlri_ptr[offset], value_size);
265 /* can not be < and > at the same time */
266 if (op[5] == 1 && op[6] == 1)
267 *error = -1;
268 /* if first element, AND bit can not be set */
269 if (op[1] == 1 && loop == 0)
270 *error = -1;
271 switch (type) {
272 case BGP_FLOWSPEC_RETURN_STRING:
273 if (loop) {
274 len_written = snprintf(ptr, len_string,
275 ", ");
276 len_string -= len_written;
277 ptr += len_written;
278 }
279 if (op[5] == 1) {
280 len_written = snprintf(ptr, len_string,
281 "<");
282 len_string -= len_written;
283 ptr += len_written;
284 }
285 if (op[6] == 1) {
286 len_written = snprintf(ptr, len_string,
287 ">");
288 len_string -= len_written;
289 ptr += len_written;
290 }
291 if (op[7] == 1) {
292 len_written = snprintf(ptr, len_string,
293 "=");
294 len_string -= len_written;
295 ptr += len_written;
296 }
297 len_written = snprintf(ptr, len_string,
298 " %d ", value);
299 len_string -= len_written;
300 ptr += len_written;
301 break;
302 case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE:
303 /* limitation: stop converting */
304 if (*error == -2)
305 break;
306 mval->value = value;
307 if (op[5] == 1)
308 mval->compare_operator |=
309 OPERATOR_COMPARE_LESS_THAN;
310 if (op[6] == 1)
311 mval->compare_operator |=
312 OPERATOR_COMPARE_GREATER_THAN;
313 if (op[7] == 1)
314 mval->compare_operator |=
315 OPERATOR_COMPARE_EQUAL_TO;
316 if (op[1] == 1)
317 mval->unary_operator = OPERATOR_UNARY_AND;
318 else
319 mval->unary_operator = OPERATOR_UNARY_OR;
320 mval++;
321 break;
322 case BGP_FLOWSPEC_VALIDATE_ONLY:
323 case BGP_FLOWSPEC_RETURN_JSON:
324 /* no action */
325 break;
326 }
327 offset += value_size;
328 loop++;
329 } while (op[0] == 0 && offset < max_len - 1);
330 if (offset > max_len)
331 *error = -1;
332 /* use error parameter to count the number of entries */
333 if (*error == 0)
334 *error = loop;
335 return offset;
336 }
337
338
339 /*
340 * handle the flowspec tcpflags or fragment field
341 * return number of bytes analysed
342 * if there is an error, the passed error param is used to give error:
343 * -1 if decoding error,
344 * if result is a string, its assumed length
345 * is BGP_FLOWSPEC_STRING_DISPLAY_MAX
346 */
347 int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type,
348 uint8_t *nlri_ptr,
349 uint32_t max_len,
350 void *result, int *error)
351 {
352 int op[8];
353 int len, value_size, loop = 0, value;
354 char *ptr = (char *)result; /* for return_string */
355 struct bgp_pbr_match_val *mval = (struct bgp_pbr_match_val *)result;
356 uint32_t offset = 0;
357 int len_string = BGP_FLOWSPEC_STRING_DISPLAY_MAX;
358 int len_written;
359
360 *error = 0;
361 do {
362 if (loop > BGP_PBR_MATCH_VAL_MAX) {
363 *error = -2;
364 return offset;
365 }
366 hex2bin(&nlri_ptr[offset], op);
367 /* if first element, AND bit can not be set */
368 if (op[1] == 1 && loop == 0)
369 *error = -1;
370 offset++;
371 len = 2 * op[2] + op[3];
372 value_size = 1 << len;
373 value = hexstr2num(&nlri_ptr[offset], value_size);
374 switch (type) {
375 case BGP_FLOWSPEC_RETURN_STRING:
376 if (op[1] == 1 && loop != 0) {
377 len_written = snprintf(ptr, len_string,
378 ",&");
379 len_string -= len_written;
380 ptr += len_written;
381 } else if (op[1] == 0 && loop != 0) {
382 len_written = snprintf(ptr, len_string,
383 ",|");
384 len_string -= len_written;
385 ptr += len_written;
386 }
387 if (op[7] == 1) {
388 len_written = snprintf(ptr, len_string,
389 "= ");
390 len_string -= len_written;
391 ptr += len_written;
392 } else {
393 len_written = snprintf(ptr, len_string,
394 "∋ ");
395 len_string -= len_written;
396 ptr += len_written;
397 }
398 if (op[6] == 1) {
399 len_written = snprintf(ptr, len_string,
400 "! ");
401 len_string -= len_written;
402 ptr += len_written;
403 }
404 len_written = snprintf(ptr, len_string,
405 "%d", value);
406 len_string -= len_written;
407 ptr += len_written;
408 break;
409 case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE:
410 /* limitation: stop converting */
411 if (*error == -2)
412 break;
413 mval->value = value;
414 if (op[6] == 1) {
415 /* different from */
416 mval->compare_operator |=
417 OPERATOR_COMPARE_LESS_THAN;
418 mval->compare_operator |=
419 OPERATOR_COMPARE_GREATER_THAN;
420 } else
421 mval->compare_operator |=
422 OPERATOR_COMPARE_EQUAL_TO;
423 if (op[7] == 1)
424 mval->compare_operator |=
425 OPERATOR_COMPARE_EXACT_MATCH;
426 if (op[1] == 1)
427 mval->unary_operator =
428 OPERATOR_UNARY_AND;
429 else
430 mval->unary_operator =
431 OPERATOR_UNARY_OR;
432 mval++;
433 break;
434 case BGP_FLOWSPEC_VALIDATE_ONLY:
435 case BGP_FLOWSPEC_RETURN_JSON:
436 /* no action */
437 break;
438 }
439 offset += value_size;
440 loop++;
441 } while (op[0] == 0 && offset < max_len - 1);
442 if (offset > max_len)
443 *error = -1;
444 /* use error parameter to count the number of entries */
445 if (*error == 0)
446 *error = loop;
447 return offset;
448 }
449
450 int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
451 struct bgp_pbr_entry_main *bpem,
452 afi_t afi)
453 {
454 int offset = 0, error = 0;
455 struct prefix *prefix;
456 struct bgp_pbr_match_val *mval;
457 uint8_t *match_num;
458 uint8_t bitmask = 0;
459 int ret = 0, type;
460 uint8_t *prefix_offset;
461
462 while (offset < len - 1 && error >= 0) {
463 type = nlri_content[offset];
464 offset++;
465 switch (type) {
466 case FLOWSPEC_DEST_PREFIX:
467 case FLOWSPEC_SRC_PREFIX:
468 bitmask = 0;
469 if (type == FLOWSPEC_DEST_PREFIX) {
470 bitmask |= PREFIX_DST_PRESENT;
471 prefix = &bpem->dst_prefix;
472 prefix_offset = &bpem->dst_prefix_offset;
473 } else {
474 bitmask |= PREFIX_SRC_PRESENT;
475 prefix = &bpem->src_prefix;
476 prefix_offset = &bpem->src_prefix_offset;
477 }
478 ret = bgp_flowspec_ip_address(
479 BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
480 nlri_content + offset,
481 len - offset,
482 prefix, &error,
483 afi, prefix_offset);
484 if (error < 0)
485 flog_err(EC_BGP_FLOWSPEC_PACKET,
486 "%s: flowspec_ip_address error %d",
487 __func__, error);
488 else {
489 /* if src or dst address is 0.0.0.0,
490 * ignore that rule
491 */
492 if (prefix->family == AF_INET
493 && prefix->u.prefix4.s_addr == INADDR_ANY)
494 bpem->match_bitmask_iprule |= bitmask;
495 else if (prefix->family == AF_INET6
496 && !memcmp(&prefix->u.prefix6,
497 &in6addr_any,
498 sizeof(struct in6_addr)))
499 bpem->match_bitmask_iprule |= bitmask;
500 else
501 bpem->match_bitmask |= bitmask;
502 }
503 offset += ret;
504 break;
505 case FLOWSPEC_FLOW_LABEL:
506 if (afi == AFI_IP) {
507 error = -1;
508 continue;
509 }
510 match_num = &(bpem->match_flowlabel_num);
511 mval = (struct bgp_pbr_match_val *)
512 &(bpem->flow_label);
513 offset += bgp_flowspec_call_non_opaque_decode(
514 nlri_content + offset,
515 len - offset,
516 mval, match_num,
517 &error);
518 break;
519 case FLOWSPEC_IP_PROTOCOL:
520 match_num = &(bpem->match_protocol_num);
521 mval = (struct bgp_pbr_match_val *)
522 &(bpem->protocol);
523 offset += bgp_flowspec_call_non_opaque_decode(
524 nlri_content + offset,
525 len - offset,
526 mval, match_num,
527 &error);
528 break;
529 case FLOWSPEC_PORT:
530 match_num = &(bpem->match_port_num);
531 mval = (struct bgp_pbr_match_val *)
532 &(bpem->port);
533 offset += bgp_flowspec_call_non_opaque_decode(
534 nlri_content + offset,
535 len - offset,
536 mval, match_num,
537 &error);
538 break;
539 case FLOWSPEC_DEST_PORT:
540 match_num = &(bpem->match_dst_port_num);
541 mval = (struct bgp_pbr_match_val *)
542 &(bpem->dst_port);
543 offset += bgp_flowspec_call_non_opaque_decode(
544 nlri_content + offset,
545 len - offset,
546 mval, match_num,
547 &error);
548 break;
549 case FLOWSPEC_SRC_PORT:
550 match_num = &(bpem->match_src_port_num);
551 mval = (struct bgp_pbr_match_val *)
552 &(bpem->src_port);
553 offset += bgp_flowspec_call_non_opaque_decode(
554 nlri_content + offset,
555 len - offset,
556 mval, match_num,
557 &error);
558 break;
559 case FLOWSPEC_ICMP_TYPE:
560 match_num = &(bpem->match_icmp_type_num);
561 mval = (struct bgp_pbr_match_val *)
562 &(bpem->icmp_type);
563 offset += bgp_flowspec_call_non_opaque_decode(
564 nlri_content + offset,
565 len - offset,
566 mval, match_num,
567 &error);
568 break;
569 case FLOWSPEC_ICMP_CODE:
570 match_num = &(bpem->match_icmp_code_num);
571 mval = (struct bgp_pbr_match_val *)
572 &(bpem->icmp_code);
573 offset += bgp_flowspec_call_non_opaque_decode(
574 nlri_content + offset,
575 len - offset,
576 mval, match_num,
577 &error);
578 break;
579 case FLOWSPEC_PKT_LEN:
580 match_num =
581 &(bpem->match_packet_length_num);
582 mval = (struct bgp_pbr_match_val *)
583 &(bpem->packet_length);
584 offset += bgp_flowspec_call_non_opaque_decode(
585 nlri_content + offset,
586 len - offset,
587 mval, match_num,
588 &error);
589 break;
590 case FLOWSPEC_DSCP:
591 match_num = &(bpem->match_dscp_num);
592 mval = (struct bgp_pbr_match_val *)
593 &(bpem->dscp);
594 offset += bgp_flowspec_call_non_opaque_decode(
595 nlri_content + offset,
596 len - offset,
597 mval, match_num,
598 &error);
599 break;
600 case FLOWSPEC_TCP_FLAGS:
601 ret = bgp_flowspec_bitmask_decode(
602 BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
603 nlri_content + offset,
604 len - offset,
605 &bpem->tcpflags, &error);
606 if (error < 0)
607 flog_err(
608 EC_BGP_FLOWSPEC_PACKET,
609 "%s: flowspec_tcpflags_decode error %d",
610 __func__, error);
611 else
612 bpem->match_tcpflags_num = error;
613 /* contains the number of slots used */
614 offset += ret;
615 break;
616 case FLOWSPEC_FRAGMENT:
617 ret = bgp_flowspec_bitmask_decode(
618 BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
619 nlri_content + offset,
620 len - offset, &bpem->fragment,
621 &error);
622 if (error < 0)
623 flog_err(
624 EC_BGP_FLOWSPEC_PACKET,
625 "%s: flowspec_fragment_type_decode error %d",
626 __func__, error);
627 else
628 bpem->match_fragment_num = error;
629 offset += ret;
630 break;
631 default:
632 flog_err(EC_LIB_DEVELOPMENT, "%s: unknown type %d",
633 __func__, type);
634 }
635 }
636 if (bpem->match_packet_length_num || bpem->match_fragment_num
637 || bpem->match_tcpflags_num || bpem->match_dscp_num
638 || bpem->match_icmp_code_num || bpem->match_icmp_type_num
639 || bpem->match_port_num || bpem->match_src_port_num
640 || bpem->match_dst_port_num || bpem->match_protocol_num
641 || bpem->match_bitmask || bpem->match_flowlabel_num)
642 bpem->type = BGP_PBR_IPSET;
643 else if ((bpem->match_bitmask_iprule & PREFIX_SRC_PRESENT) ||
644 (bpem->match_bitmask_iprule & PREFIX_DST_PRESENT))
645 /* the extracted policy rule may not need an
646 * iptables/ipset filtering. check this may not be
647 * a standard ip rule : permit any to any ( eg)
648 */
649 bpem->type = BGP_PBR_IPRULE;
650 else
651 bpem->type = BGP_PBR_UNDEFINED;
652 return error;
653 }
654
655 /* return 1 if FS entry invalid or no NH IP */
656 bool bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
657 struct prefix *p, afi_t afi)
658 {
659 struct bgp_pbr_entry_main api;
660 int i;
661 struct bgp_dest *dest = pi->net;
662 struct bgp_pbr_entry_action *api_action;
663
664 memset(&api, 0, sizeof(api));
665 if (bgp_pbr_build_and_validate_entry(bgp_dest_get_prefix(dest), pi,
666 &api)
667 < 0)
668 return true;
669 for (i = 0; i < api.action_num; i++) {
670 api_action = &api.actions[i];
671 if (api_action->action != ACTION_REDIRECT_IP)
672 continue;
673 p->family = afi2family(afi);
674 if (afi == AFI_IP) {
675 p->prefixlen = IPV4_MAX_BITLEN;
676 p->u.prefix4 = api_action->u.zr.redirect_ip_v4;
677 } else {
678 p->prefixlen = IPV6_MAX_BITLEN;
679 memcpy(&p->u.prefix6, &api_action->u.zr.redirect_ip_v6,
680 sizeof(struct in6_addr));
681 }
682 return false;
683 }
684 return true;
685 }