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