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