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