]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_flowspec_util.c
Merge pull request #10399 from g-balaji1/pimv6-sock
[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:
b08dcc3f
IR
230 if (prefix)
231 prefix_copy(prefix, &prefix_local);
034cdee9
PG
232 break;
233 case BGP_FLOWSPEC_VALIDATE_ONLY:
234 default:
235 break;
236 }
237 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,
362a06e3
PG
245 * if result is a string, its assumed length
246 * is BGP_FLOWSPEC_STRING_DISPLAY_MAX
034cdee9
PG
247 */
248int 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 int op[8];
254 int len, value, value_size;
255 int loop = 0;
256 char *ptr = (char *)result; /* for return_string */
257 uint32_t offset = 0;
362a06e3
PG
258 int len_string = BGP_FLOWSPEC_STRING_DISPLAY_MAX;
259 int len_written;
47555ee9 260 struct bgp_pbr_match_val *mval = (struct bgp_pbr_match_val *)result;
034cdee9
PG
261
262 *error = 0;
263 do {
47555ee9
PG
264 if (loop > BGP_PBR_MATCH_VAL_MAX)
265 *error = -2;
034cdee9
PG
266 hex2bin(&nlri_ptr[offset], op);
267 offset++;
268 len = 2*op[2]+op[3];
269 value_size = 1 << len;
270 value = hexstr2num(&nlri_ptr[offset], value_size);
271 /* can not be < and > at the same time */
272 if (op[5] == 1 && op[6] == 1)
273 *error = -1;
274 /* if first element, AND bit can not be set */
275 if (op[1] == 1 && loop == 0)
276 *error = -1;
277 switch (type) {
278 case BGP_FLOWSPEC_RETURN_STRING:
362a06e3
PG
279 if (loop) {
280 len_written = snprintf(ptr, len_string,
281 ", ");
282 len_string -= len_written;
283 ptr += len_written;
284 }
285 if (op[5] == 1) {
286 len_written = snprintf(ptr, len_string,
287 "<");
288 len_string -= len_written;
289 ptr += len_written;
290 }
291 if (op[6] == 1) {
292 len_written = snprintf(ptr, len_string,
293 ">");
294 len_string -= len_written;
295 ptr += len_written;
296 }
297 if (op[7] == 1) {
298 len_written = snprintf(ptr, len_string,
299 "=");
300 len_string -= len_written;
301 ptr += len_written;
302 }
303 len_written = snprintf(ptr, len_string,
304 " %d ", value);
305 len_string -= len_written;
306 ptr += len_written;
034cdee9
PG
307 break;
308 case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE:
47555ee9
PG
309 /* limitation: stop converting */
310 if (*error == -2)
311 break;
312 mval->value = value;
313 if (op[5] == 1)
314 mval->compare_operator |=
315 OPERATOR_COMPARE_LESS_THAN;
316 if (op[6] == 1)
317 mval->compare_operator |=
318 OPERATOR_COMPARE_GREATER_THAN;
319 if (op[7] == 1)
320 mval->compare_operator |=
321 OPERATOR_COMPARE_EQUAL_TO;
322 if (op[1] == 1)
323 mval->unary_operator = OPERATOR_UNARY_AND;
324 else
325 mval->unary_operator = OPERATOR_UNARY_OR;
326 mval++;
034cdee9
PG
327 break;
328 case BGP_FLOWSPEC_VALIDATE_ONLY:
329 default:
330 /* no action */
331 break;
332 }
333 offset += value_size;
334 loop++;
335 } while (op[0] == 0 && offset < max_len - 1);
336 if (offset > max_len)
337 *error = -1;
338 /* use error parameter to count the number of entries */
339 if (*error == 0)
340 *error = loop;
341 return offset;
342}
343
344
345/*
588ec356 346 * handle the flowspec tcpflags or fragment field
034cdee9
PG
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,
362a06e3
PG
350 * if result is a string, its assumed length
351 * is BGP_FLOWSPEC_STRING_DISPLAY_MAX
034cdee9 352 */
588ec356 353int bgp_flowspec_bitmask_decode(enum bgp_flowspec_util_nlri_t type,
034cdee9
PG
354 uint8_t *nlri_ptr,
355 uint32_t max_len,
356 void *result, int *error)
357{
358 int op[8];
359 int len, value_size, loop = 0, value;
360 char *ptr = (char *)result; /* for return_string */
47555ee9 361 struct bgp_pbr_match_val *mval = (struct bgp_pbr_match_val *)result;
034cdee9 362 uint32_t offset = 0;
362a06e3
PG
363 int len_string = BGP_FLOWSPEC_STRING_DISPLAY_MAX;
364 int len_written;
034cdee9
PG
365
366 *error = 0;
367 do {
47555ee9
PG
368 if (loop > BGP_PBR_MATCH_VAL_MAX)
369 *error = -2;
034cdee9
PG
370 hex2bin(&nlri_ptr[offset], op);
371 /* if first element, AND bit can not be set */
372 if (op[1] == 1 && loop == 0)
373 *error = -1;
374 offset++;
375 len = 2 * op[2] + op[3];
376 value_size = 1 << len;
377 value = hexstr2num(&nlri_ptr[offset], value_size);
378 switch (type) {
379 case BGP_FLOWSPEC_RETURN_STRING:
362a06e3
PG
380 if (op[1] == 1 && loop != 0) {
381 len_written = snprintf(ptr, len_string,
01ffd28b 382 ",&");
362a06e3
PG
383 len_string -= len_written;
384 ptr += len_written;
385 } else if (op[1] == 0 && loop != 0) {
386 len_written = snprintf(ptr, len_string,
01ffd28b 387 ",|");
362a06e3
PG
388 len_string -= len_written;
389 ptr += len_written;
390 }
01ffd28b
PG
391 if (op[7] == 1) {
392 len_written = snprintf(ptr, len_string,
393 "= ");
394 len_string -= len_written;
395 ptr += len_written;
396 } else {
397 len_written = snprintf(ptr, len_string,
398 "∋ ");
362a06e3
PG
399 len_string -= len_written;
400 ptr += len_written;
401 }
01ffd28b
PG
402 if (op[6] == 1) {
403 len_written = snprintf(ptr, len_string,
404 "! ");
362a06e3
PG
405 len_string -= len_written;
406 ptr += len_written;
407 }
01ffd28b 408 len_written = snprintf(ptr, len_string,
362a06e3
PG
409 "%d", value);
410 len_string -= len_written;
411 ptr += len_written;
034cdee9
PG
412 break;
413 case BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE:
47555ee9
PG
414 /* limitation: stop converting */
415 if (*error == -2)
416 break;
417 mval->value = value;
418 if (op[6] == 1) {
419 /* different from */
420 mval->compare_operator |=
421 OPERATOR_COMPARE_LESS_THAN;
422 mval->compare_operator |=
423 OPERATOR_COMPARE_GREATER_THAN;
424 } else
425 mval->compare_operator |=
426 OPERATOR_COMPARE_EQUAL_TO;
427 if (op[7] == 1)
428 mval->compare_operator |=
429 OPERATOR_COMPARE_EXACT_MATCH;
430 if (op[1] == 1)
431 mval->unary_operator =
432 OPERATOR_UNARY_AND;
433 else
434 mval->unary_operator =
435 OPERATOR_UNARY_OR;
436 mval++;
034cdee9
PG
437 break;
438 case BGP_FLOWSPEC_VALIDATE_ONLY:
439 default:
440 /* no action */
441 break;
442 }
443 offset += value_size;
444 loop++;
445 } while (op[0] == 0 && offset < max_len - 1);
446 if (offset > max_len)
447 *error = -1;
448 /* use error parameter to count the number of entries */
449 if (*error == 0)
450 *error = loop;
451 return offset;
452}
453
47555ee9 454int bgp_flowspec_match_rules_fill(uint8_t *nlri_content, int len,
1840384b
PG
455 struct bgp_pbr_entry_main *bpem,
456 afi_t afi)
98a9dbc7 457{
47555ee9
PG
458 int offset = 0, error = 0;
459 struct prefix *prefix;
460 struct bgp_pbr_match_val *mval;
461 uint8_t *match_num;
462 uint8_t bitmask = 0;
463 int ret = 0, type;
9cec4121 464 uint8_t *prefix_offset;
98a9dbc7 465
47555ee9 466 while (offset < len - 1 && error >= 0) {
98a9dbc7
PG
467 type = nlri_content[offset];
468 offset++;
469 switch (type) {
470 case FLOWSPEC_DEST_PREFIX:
471 case FLOWSPEC_SRC_PREFIX:
47555ee9
PG
472 bitmask = 0;
473 if (type == FLOWSPEC_DEST_PREFIX) {
474 bitmask |= PREFIX_DST_PRESENT;
475 prefix = &bpem->dst_prefix;
9cec4121 476 prefix_offset = &bpem->dst_prefix_offset;
47555ee9
PG
477 } else {
478 bitmask |= PREFIX_SRC_PRESENT;
479 prefix = &bpem->src_prefix;
9cec4121 480 prefix_offset = &bpem->src_prefix_offset;
47555ee9 481 }
98a9dbc7
PG
482 ret = bgp_flowspec_ip_address(
483 BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
47555ee9 484 nlri_content + offset,
98a9dbc7 485 len - offset,
1840384b 486 prefix, &error,
9cec4121 487 afi, prefix_offset);
47555ee9 488 if (error < 0)
e50f7cfd 489 flog_err(EC_BGP_FLOWSPEC_PACKET,
1c50c1c0
QY
490 "%s: flowspec_ip_address error %d",
491 __func__, error);
4c2876fb
PG
492 else {
493 /* if src or dst address is 0.0.0.0,
494 * ignore that rule
495 */
496 if (prefix->family == AF_INET
975a328e 497 && prefix->u.prefix4.s_addr == INADDR_ANY)
5fa779c9 498 bpem->match_bitmask_iprule |= bitmask;
9cec4121
PG
499 else if (prefix->family == AF_INET6
500 && !memcmp(&prefix->u.prefix6,
501 &in6addr_any,
502 sizeof(struct in6_addr)))
503 bpem->match_bitmask_iprule |= bitmask;
4c2876fb
PG
504 else
505 bpem->match_bitmask |= bitmask;
506 }
47555ee9 507 offset += ret;
98a9dbc7 508 break;
40881800
PG
509 case FLOWSPEC_FLOW_LABEL:
510 if (afi == AFI_IP) {
511 error = -1;
512 continue;
513 }
514 match_num = &(bpem->match_flowlabel_num);
515 mval = (struct bgp_pbr_match_val *)
516 &(bpem->flow_label);
517 offset += bgp_flowspec_call_non_opaque_decode(
518 nlri_content + offset,
519 len - offset,
520 mval, match_num,
521 &error);
522 break;
98a9dbc7 523 case FLOWSPEC_IP_PROTOCOL:
47555ee9
PG
524 match_num = &(bpem->match_protocol_num);
525 mval = (struct bgp_pbr_match_val *)
526 &(bpem->protocol);
527 offset += bgp_flowspec_call_non_opaque_decode(
528 nlri_content + offset,
529 len - offset,
530 mval, match_num,
531 &error);
532 break;
98a9dbc7 533 case FLOWSPEC_PORT:
47555ee9
PG
534 match_num = &(bpem->match_port_num);
535 mval = (struct bgp_pbr_match_val *)
536 &(bpem->port);
537 offset += bgp_flowspec_call_non_opaque_decode(
538 nlri_content + offset,
539 len - offset,
540 mval, match_num,
541 &error);
542 break;
98a9dbc7 543 case FLOWSPEC_DEST_PORT:
47555ee9
PG
544 match_num = &(bpem->match_dst_port_num);
545 mval = (struct bgp_pbr_match_val *)
546 &(bpem->dst_port);
547 offset += bgp_flowspec_call_non_opaque_decode(
548 nlri_content + offset,
549 len - offset,
550 mval, match_num,
551 &error);
552 break;
98a9dbc7 553 case FLOWSPEC_SRC_PORT:
47555ee9
PG
554 match_num = &(bpem->match_src_port_num);
555 mval = (struct bgp_pbr_match_val *)
556 &(bpem->src_port);
557 offset += bgp_flowspec_call_non_opaque_decode(
558 nlri_content + offset,
559 len - offset,
560 mval, match_num,
561 &error);
562 break;
98a9dbc7 563 case FLOWSPEC_ICMP_TYPE:
47555ee9
PG
564 match_num = &(bpem->match_icmp_type_num);
565 mval = (struct bgp_pbr_match_val *)
566 &(bpem->icmp_type);
567 offset += bgp_flowspec_call_non_opaque_decode(
568 nlri_content + offset,
569 len - offset,
570 mval, match_num,
571 &error);
98a9dbc7 572 break;
47555ee9
PG
573 case FLOWSPEC_ICMP_CODE:
574 match_num = &(bpem->match_icmp_code_num);
575 mval = (struct bgp_pbr_match_val *)
576 &(bpem->icmp_code);
577 offset += bgp_flowspec_call_non_opaque_decode(
578 nlri_content + offset,
579 len - offset,
580 mval, match_num,
581 &error);
98a9dbc7
PG
582 break;
583 case FLOWSPEC_PKT_LEN:
47555ee9
PG
584 match_num =
585 &(bpem->match_packet_length_num);
586 mval = (struct bgp_pbr_match_val *)
587 &(bpem->packet_length);
588 offset += bgp_flowspec_call_non_opaque_decode(
589 nlri_content + offset,
590 len - offset,
591 mval, match_num,
592 &error);
593 break;
98a9dbc7 594 case FLOWSPEC_DSCP:
47555ee9
PG
595 match_num = &(bpem->match_dscp_num);
596 mval = (struct bgp_pbr_match_val *)
597 &(bpem->dscp);
598 offset += bgp_flowspec_call_non_opaque_decode(
599 nlri_content + offset,
600 len - offset,
601 mval, match_num,
602 &error);
603 break;
604 case FLOWSPEC_TCP_FLAGS:
588ec356 605 ret = bgp_flowspec_bitmask_decode(
47555ee9
PG
606 BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
607 nlri_content + offset,
608 len - offset,
609 &bpem->tcpflags, &error);
610 if (error < 0)
1c50c1c0
QY
611 flog_err(
612 EC_BGP_FLOWSPEC_PACKET,
613 "%s: flowspec_tcpflags_decode error %d",
614 __func__, error);
47555ee9
PG
615 else
616 bpem->match_tcpflags_num = error;
617 /* contains the number of slots used */
618 offset += ret;
98a9dbc7
PG
619 break;
620 case FLOWSPEC_FRAGMENT:
588ec356 621 ret = bgp_flowspec_bitmask_decode(
47555ee9
PG
622 BGP_FLOWSPEC_CONVERT_TO_NON_OPAQUE,
623 nlri_content + offset,
624 len - offset, &bpem->fragment,
625 &error);
626 if (error < 0)
1c50c1c0
QY
627 flog_err(
628 EC_BGP_FLOWSPEC_PACKET,
629 "%s: flowspec_fragment_type_decode error %d",
630 __func__, error);
47555ee9 631 else
588ec356 632 bpem->match_fragment_num = error;
47555ee9 633 offset += ret;
98a9dbc7
PG
634 break;
635 default:
1d5453d6 636 flog_err(EC_LIB_DEVELOPMENT, "%s: unknown type %d",
1c50c1c0 637 __func__, type);
98a9dbc7 638 }
98a9dbc7 639 }
734c6f09
DA
640 if (bpem->match_packet_length_num || bpem->match_fragment_num
641 || bpem->match_tcpflags_num || bpem->match_dscp_num
642 || bpem->match_icmp_code_num || bpem->match_icmp_type_num
643 || bpem->match_port_num || bpem->match_src_port_num
644 || bpem->match_dst_port_num || bpem->match_protocol_num
645 || bpem->match_bitmask || bpem->match_flowlabel_num)
5fa779c9
PG
646 bpem->type = BGP_PBR_IPSET;
647 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 bpem->type = BGP_PBR_IPRULE;
654 else
655 bpem->type = BGP_PBR_UNDEFINED;
47555ee9 656 return error;
98a9dbc7 657}
0378bcaa
PG
658
659/* return 1 if FS entry invalid or no NH IP */
3dc339cd 660bool bgp_flowspec_get_first_nh(struct bgp *bgp, struct bgp_path_info *pi,
1840384b 661 struct prefix *p, afi_t afi)
0378bcaa
PG
662{
663 struct bgp_pbr_entry_main api;
664 int i;
9bcb3eef 665 struct bgp_dest *dest = pi->net;
0378bcaa
PG
666 struct bgp_pbr_entry_action *api_action;
667
668 memset(&api, 0, sizeof(struct bgp_pbr_entry_main));
9bcb3eef
DS
669 if (bgp_pbr_build_and_validate_entry(bgp_dest_get_prefix(dest), pi,
670 &api)
b54892e0 671 < 0)
3dc339cd 672 return true;
0378bcaa
PG
673 for (i = 0; i < api.action_num; i++) {
674 api_action = &api.actions[i];
675 if (api_action->action != ACTION_REDIRECT_IP)
676 continue;
1840384b
PG
677 p->family = afi2family(afi);
678 if (afi == AFI_IP) {
679 p->prefixlen = IPV4_MAX_BITLEN;
680 p->u.prefix4 = api_action->u.zr.redirect_ip_v4;
681 } else {
682 p->prefixlen = IPV6_MAX_BITLEN;
683 memcpy(&p->u.prefix6, &api_action->u.zr.redirect_ip_v6,
684 sizeof(struct in6_addr));
685 }
3dc339cd 686 return false;
0378bcaa 687 }
3dc339cd 688 return true;
0378bcaa 689}