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