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