Coverage Report

Created: 2025-12-05 06:31

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