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