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