]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_pbr.c
bgpd: Validate large-community-list against UINT_MAX
[mirror_frr.git] / bgpd / bgp_pbr.c
1 /*
2 * BGP pbr
3 * Copyright (C) 6WIND
4 *
5 * FRR is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2, or (at your option) any
8 * later version.
9 *
10 * FRR is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include "zebra.h"
21 #include "prefix.h"
22 #include "zclient.h"
23 #include "jhash.h"
24 #include "pbr.h"
25
26 #include "bgpd/bgpd.h"
27 #include "bgpd/bgp_pbr.h"
28 #include "bgpd/bgp_debug.h"
29 #include "bgpd/bgp_flowspec_util.h"
30 #include "bgpd/bgp_ecommunity.h"
31 #include "bgpd/bgp_route.h"
32 #include "bgpd/bgp_attr.h"
33 #include "bgpd/bgp_zebra.h"
34 #include "bgpd/bgp_mplsvpn.h"
35 #include "bgpd/bgp_flowspec_private.h"
36 #include "bgpd/bgp_errors.h"
37
38 DEFINE_MTYPE_STATIC(BGPD, PBR_MATCH_ENTRY, "PBR match entry")
39 DEFINE_MTYPE_STATIC(BGPD, PBR_MATCH, "PBR match")
40 DEFINE_MTYPE_STATIC(BGPD, PBR_ACTION, "PBR action")
41 DEFINE_MTYPE_STATIC(BGPD, PBR_RULE, "PBR rule")
42 DEFINE_MTYPE_STATIC(BGPD, PBR, "BGP PBR Context")
43 DEFINE_MTYPE_STATIC(BGPD, PBR_VALMASK, "BGP PBR Val Mask Value")
44
45 RB_GENERATE(bgp_pbr_interface_head, bgp_pbr_interface,
46 id_entry, bgp_pbr_interface_compare);
47 struct bgp_pbr_interface_head ifaces_by_name_ipv4 =
48 RB_INITIALIZER(&ifaces_by_name_ipv4);
49
50 static int bgp_pbr_match_counter_unique;
51 static int bgp_pbr_match_entry_counter_unique;
52 static int bgp_pbr_action_counter_unique;
53 static int bgp_pbr_match_iptable_counter_unique;
54
55 struct bgp_pbr_match_iptable_unique {
56 uint32_t unique;
57 struct bgp_pbr_match *bpm_found;
58 };
59
60 struct bgp_pbr_match_entry_unique {
61 uint32_t unique;
62 struct bgp_pbr_match_entry *bpme_found;
63 };
64
65 struct bgp_pbr_action_unique {
66 uint32_t unique;
67 struct bgp_pbr_action *bpa_found;
68 };
69
70 struct bgp_pbr_rule_unique {
71 uint32_t unique;
72 struct bgp_pbr_rule *bpr_found;
73 };
74
75 static int bgp_pbr_rule_walkcb(struct hash_bucket *bucket, void *arg)
76 {
77 struct bgp_pbr_rule *bpr = (struct bgp_pbr_rule *)bucket->data;
78 struct bgp_pbr_rule_unique *bpru = (struct bgp_pbr_rule_unique *)
79 arg;
80 uint32_t unique = bpru->unique;
81
82 if (bpr->unique == unique) {
83 bpru->bpr_found = bpr;
84 return HASHWALK_ABORT;
85 }
86 return HASHWALK_CONTINUE;
87 }
88
89 static int bgp_pbr_action_walkcb(struct hash_bucket *bucket, void *arg)
90 {
91 struct bgp_pbr_action *bpa = (struct bgp_pbr_action *)bucket->data;
92 struct bgp_pbr_action_unique *bpau = (struct bgp_pbr_action_unique *)
93 arg;
94 uint32_t unique = bpau->unique;
95
96 if (bpa->unique == unique) {
97 bpau->bpa_found = bpa;
98 return HASHWALK_ABORT;
99 }
100 return HASHWALK_CONTINUE;
101 }
102
103 static int bgp_pbr_match_entry_walkcb(struct hash_bucket *bucket, void *arg)
104 {
105 struct bgp_pbr_match_entry *bpme =
106 (struct bgp_pbr_match_entry *)bucket->data;
107 struct bgp_pbr_match_entry_unique *bpmeu =
108 (struct bgp_pbr_match_entry_unique *)arg;
109 uint32_t unique = bpmeu->unique;
110
111 if (bpme->unique == unique) {
112 bpmeu->bpme_found = bpme;
113 return HASHWALK_ABORT;
114 }
115 return HASHWALK_CONTINUE;
116 }
117
118 struct bgp_pbr_match_ipsetname {
119 char *ipsetname;
120 struct bgp_pbr_match *bpm_found;
121 };
122
123 static int bgp_pbr_match_pername_walkcb(struct hash_bucket *bucket, void *arg)
124 {
125 struct bgp_pbr_match *bpm = (struct bgp_pbr_match *)bucket->data;
126 struct bgp_pbr_match_ipsetname *bpmi =
127 (struct bgp_pbr_match_ipsetname *)arg;
128 char *ipset_name = bpmi->ipsetname;
129
130 if (!strncmp(ipset_name, bpm->ipset_name,
131 ZEBRA_IPSET_NAME_SIZE)) {
132 bpmi->bpm_found = bpm;
133 return HASHWALK_ABORT;
134 }
135 return HASHWALK_CONTINUE;
136 }
137
138 static int bgp_pbr_match_iptable_walkcb(struct hash_bucket *bucket, void *arg)
139 {
140 struct bgp_pbr_match *bpm = (struct bgp_pbr_match *)bucket->data;
141 struct bgp_pbr_match_iptable_unique *bpmiu =
142 (struct bgp_pbr_match_iptable_unique *)arg;
143 uint32_t unique = bpmiu->unique;
144
145 if (bpm->unique2 == unique) {
146 bpmiu->bpm_found = bpm;
147 return HASHWALK_ABORT;
148 }
149 return HASHWALK_CONTINUE;
150 }
151
152 struct bgp_pbr_match_unique {
153 uint32_t unique;
154 struct bgp_pbr_match *bpm_found;
155 };
156
157 static int bgp_pbr_match_walkcb(struct hash_bucket *bucket, void *arg)
158 {
159 struct bgp_pbr_match *bpm = (struct bgp_pbr_match *)bucket->data;
160 struct bgp_pbr_match_unique *bpmu = (struct bgp_pbr_match_unique *)
161 arg;
162 uint32_t unique = bpmu->unique;
163
164 if (bpm->unique == unique) {
165 bpmu->bpm_found = bpm;
166 return HASHWALK_ABORT;
167 }
168 return HASHWALK_CONTINUE;
169 }
170
171 static int sprintf_bgp_pbr_match_val(char *str, struct bgp_pbr_match_val *mval,
172 const char *prepend)
173 {
174 char *ptr = str;
175
176 if (prepend)
177 ptr += sprintf(ptr, "%s", prepend);
178 else {
179 if (mval->unary_operator & OPERATOR_UNARY_OR)
180 ptr += sprintf(ptr, ", or ");
181 if (mval->unary_operator & OPERATOR_UNARY_AND)
182 ptr += sprintf(ptr, ", and ");
183 }
184 if (mval->compare_operator & OPERATOR_COMPARE_LESS_THAN)
185 ptr += sprintf(ptr, "<");
186 if (mval->compare_operator & OPERATOR_COMPARE_GREATER_THAN)
187 ptr += sprintf(ptr, ">");
188 if (mval->compare_operator & OPERATOR_COMPARE_EQUAL_TO)
189 ptr += sprintf(ptr, "=");
190 if (mval->compare_operator & OPERATOR_COMPARE_EXACT_MATCH)
191 ptr += sprintf(ptr, "match");
192 ptr += sprintf(ptr, " %u", mval->value);
193 return (int)(ptr - str);
194 }
195
196 #define INCREMENT_DISPLAY(_ptr, _cnt) do { \
197 if (_cnt) \
198 (_ptr) += sprintf((_ptr), "; "); \
199 _cnt++; \
200 } while (0)
201
202 /* this structure can be used for port range,
203 * but also for other values range like packet length range
204 */
205 struct bgp_pbr_range_port {
206 uint16_t min_port;
207 uint16_t max_port;
208 };
209
210 /* this structure can be used to filter with a mask
211 * for instance it supports not instructions like for
212 * tcpflags
213 */
214 struct bgp_pbr_val_mask {
215 uint16_t val;
216 uint16_t mask;
217 };
218
219 /* this structure is used to pass instructs
220 * so that BGP can create pbr instructions to ZEBRA
221 */
222 struct bgp_pbr_filter {
223 uint8_t type;
224 vrf_id_t vrf_id;
225 struct prefix *src;
226 struct prefix *dst;
227 uint8_t bitmask_iprule;
228 uint8_t protocol;
229 struct bgp_pbr_range_port *pkt_len;
230 struct bgp_pbr_range_port *src_port;
231 struct bgp_pbr_range_port *dst_port;
232 struct bgp_pbr_val_mask *tcp_flags;
233 struct bgp_pbr_val_mask *dscp;
234 struct bgp_pbr_val_mask *pkt_len_val;
235 struct bgp_pbr_val_mask *fragment;
236 };
237
238 /* this structure is used to contain OR instructions
239 * so that BGP can create multiple pbr instructions
240 * to ZEBRA
241 */
242 struct bgp_pbr_or_filter {
243 struct list *tcpflags;
244 struct list *dscp;
245 struct list *pkt_len;
246 struct list *fragment;
247 struct list *icmp_type;
248 struct list *icmp_code;
249 };
250
251 static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
252 struct bgp_path_info *path,
253 struct bgp_pbr_filter *bpf,
254 struct nexthop *nh,
255 float *rate);
256
257 static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add);
258
259 static bool bgp_pbr_extract_enumerate_unary_opposite(
260 uint8_t unary_operator,
261 struct bgp_pbr_val_mask *and_valmask,
262 struct list *or_valmask, uint32_t value,
263 uint8_t type_entry)
264 {
265 if (unary_operator == OPERATOR_UNARY_AND && and_valmask) {
266 if (type_entry == FLOWSPEC_TCP_FLAGS) {
267 and_valmask->mask |=
268 TCP_HEADER_ALL_FLAGS &
269 ~(value);
270 } else if (type_entry == FLOWSPEC_DSCP ||
271 type_entry == FLOWSPEC_PKT_LEN ||
272 type_entry == FLOWSPEC_FRAGMENT) {
273 and_valmask->val = value;
274 and_valmask->mask = 1; /* inverse */
275 }
276 } else if (unary_operator == OPERATOR_UNARY_OR && or_valmask) {
277 and_valmask = XCALLOC(MTYPE_PBR_VALMASK,
278 sizeof(struct bgp_pbr_val_mask));
279 if (type_entry == FLOWSPEC_TCP_FLAGS) {
280 and_valmask->val = TCP_HEADER_ALL_FLAGS;
281 and_valmask->mask |=
282 TCP_HEADER_ALL_FLAGS &
283 ~(value);
284 } else if (type_entry == FLOWSPEC_DSCP ||
285 type_entry == FLOWSPEC_FRAGMENT ||
286 type_entry == FLOWSPEC_PKT_LEN) {
287 and_valmask->val = value;
288 and_valmask->mask = 1; /* inverse */
289 }
290 listnode_add(or_valmask, and_valmask);
291 } else if (type_entry == FLOWSPEC_ICMP_CODE ||
292 type_entry == FLOWSPEC_ICMP_TYPE)
293 return false;
294 return true;
295 }
296
297 /* TCP : FIN and SYN -> val = ALL; mask = 3
298 * TCP : not (FIN and SYN) -> val = ALL; mask = ALL & ~(FIN|RST)
299 * other variables type: dscp, pkt len, fragment
300 * - value is copied in bgp_pbr_val_mask->val value
301 * - if negate form is identifierd, bgp_pbr_val_mask->mask set to 1
302 */
303 static bool bgp_pbr_extract_enumerate_unary(struct bgp_pbr_match_val list[],
304 int num, uint8_t unary_operator,
305 void *valmask, uint8_t type_entry)
306 {
307 int i = 0;
308 struct bgp_pbr_val_mask *and_valmask = NULL;
309 struct list *or_valmask = NULL;
310 bool ret;
311
312 if (valmask) {
313 if (unary_operator == OPERATOR_UNARY_AND) {
314 and_valmask = (struct bgp_pbr_val_mask *)valmask;
315 memset(and_valmask, 0, sizeof(struct bgp_pbr_val_mask));
316 } else if (unary_operator == OPERATOR_UNARY_OR) {
317 or_valmask = (struct list *)valmask;
318 }
319 }
320 for (i = 0; i < num; i++) {
321 if (i != 0 && list[i].unary_operator !=
322 unary_operator)
323 return false;
324 if (!(list[i].compare_operator &
325 OPERATOR_COMPARE_EQUAL_TO) &&
326 !(list[i].compare_operator &
327 OPERATOR_COMPARE_EXACT_MATCH)) {
328 if ((list[i].compare_operator &
329 OPERATOR_COMPARE_LESS_THAN) &&
330 (list[i].compare_operator &
331 OPERATOR_COMPARE_GREATER_THAN)) {
332 ret = bgp_pbr_extract_enumerate_unary_opposite(
333 unary_operator, and_valmask,
334 or_valmask, list[i].value,
335 type_entry);
336 if (!ret)
337 return ret;
338 continue;
339 }
340 return false;
341 }
342 if (unary_operator == OPERATOR_UNARY_AND && and_valmask) {
343 if (type_entry == FLOWSPEC_TCP_FLAGS)
344 and_valmask->mask |=
345 TCP_HEADER_ALL_FLAGS & list[i].value;
346 } else if (unary_operator == OPERATOR_UNARY_OR && or_valmask) {
347 and_valmask = XCALLOC(MTYPE_PBR_VALMASK,
348 sizeof(struct bgp_pbr_val_mask));
349 if (type_entry == FLOWSPEC_TCP_FLAGS) {
350 and_valmask->val = TCP_HEADER_ALL_FLAGS;
351 and_valmask->mask |=
352 TCP_HEADER_ALL_FLAGS & list[i].value;
353 } else if (type_entry == FLOWSPEC_DSCP ||
354 type_entry == FLOWSPEC_ICMP_TYPE ||
355 type_entry == FLOWSPEC_ICMP_CODE ||
356 type_entry == FLOWSPEC_FRAGMENT ||
357 type_entry == FLOWSPEC_PKT_LEN)
358 and_valmask->val = list[i].value;
359 listnode_add(or_valmask, and_valmask);
360 }
361 }
362 if (unary_operator == OPERATOR_UNARY_AND && and_valmask
363 && type_entry == FLOWSPEC_TCP_FLAGS)
364 and_valmask->val = TCP_HEADER_ALL_FLAGS;
365 return true;
366 }
367
368 /* if unary operator can either be UNARY_OR/AND/OR-AND.
369 * in the latter case, combinationf of both is not handled
370 */
371 static bool bgp_pbr_extract_enumerate(struct bgp_pbr_match_val list[],
372 int num, uint8_t unary_operator,
373 void *valmask, uint8_t type_entry)
374 {
375 bool ret;
376 uint8_t unary_operator_val;
377 bool double_check = false;
378
379 if ((unary_operator & OPERATOR_UNARY_OR) &&
380 (unary_operator & OPERATOR_UNARY_AND)) {
381 unary_operator_val = OPERATOR_UNARY_AND;
382 double_check = true;
383 } else
384 unary_operator_val = unary_operator;
385 ret = bgp_pbr_extract_enumerate_unary(list, num, unary_operator_val,
386 valmask, type_entry);
387 if (!ret && double_check)
388 ret = bgp_pbr_extract_enumerate_unary(list, num,
389 OPERATOR_UNARY_OR,
390 valmask,
391 type_entry);
392 return ret;
393 }
394
395 /* returns the unary operator that is in the list
396 * return 0 if both operators are used
397 */
398 static uint8_t bgp_pbr_match_val_get_operator(struct bgp_pbr_match_val list[],
399 int num)
400
401 {
402 int i;
403 uint8_t unary_operator = OPERATOR_UNARY_AND;
404
405 for (i = 0; i < num; i++) {
406 if (i == 0)
407 continue;
408 if (list[i].unary_operator & OPERATOR_UNARY_OR)
409 unary_operator = OPERATOR_UNARY_OR;
410 if ((list[i].unary_operator & OPERATOR_UNARY_AND
411 && unary_operator == OPERATOR_UNARY_OR) ||
412 (list[i].unary_operator & OPERATOR_UNARY_OR
413 && unary_operator == OPERATOR_UNARY_AND))
414 return 0;
415 }
416 return unary_operator;
417 }
418
419
420 /* return true if extraction ok
421 */
422 static bool bgp_pbr_extract(struct bgp_pbr_match_val list[],
423 int num,
424 struct bgp_pbr_range_port *range)
425 {
426 int i = 0;
427 bool exact_match = false;
428
429 if (range)
430 memset(range, 0, sizeof(struct bgp_pbr_range_port));
431
432 if (num > 2)
433 return false;
434 for (i = 0; i < num; i++) {
435 if (i != 0 && (list[i].compare_operator ==
436 OPERATOR_COMPARE_EQUAL_TO))
437 return false;
438 if (i == 0 && (list[i].compare_operator ==
439 OPERATOR_COMPARE_EQUAL_TO)) {
440 if (range)
441 range->min_port = list[i].value;
442 exact_match = true;
443 }
444 if (exact_match && i > 0)
445 return false;
446 if (list[i].compare_operator ==
447 (OPERATOR_COMPARE_GREATER_THAN +
448 OPERATOR_COMPARE_EQUAL_TO)) {
449 if (range)
450 range->min_port = list[i].value;
451 } else if (list[i].compare_operator ==
452 (OPERATOR_COMPARE_LESS_THAN +
453 OPERATOR_COMPARE_EQUAL_TO)) {
454 if (range)
455 range->max_port = list[i].value;
456 } else if (list[i].compare_operator ==
457 OPERATOR_COMPARE_LESS_THAN) {
458 if (range)
459 range->max_port = list[i].value - 1;
460 } else if (list[i].compare_operator ==
461 OPERATOR_COMPARE_GREATER_THAN) {
462 if (range)
463 range->min_port = list[i].value + 1;
464 }
465 }
466 return true;
467 }
468
469 static int bgp_pbr_validate_policy_route(struct bgp_pbr_entry_main *api)
470 {
471 bool enumerate_icmp = false;
472
473 if (api->type == BGP_PBR_UNDEFINED) {
474 if (BGP_DEBUG(pbr, PBR))
475 zlog_debug("BGP: pbr entry undefined. cancel.");
476 return 0;
477 }
478 /* because bgp pbr entry may contain unsupported
479 * combinations, a message will be displayed here if
480 * not supported.
481 * for now, only match/set supported is
482 * - combination src/dst => redirect nexthop [ + rate]
483 * - combination src/dst => redirect VRF [ + rate]
484 * - combination src/dst => drop
485 * - combination srcport + @IP
486 */
487 if (api->match_protocol_num > 1) {
488 if (BGP_DEBUG(pbr, PBR))
489 zlog_debug("BGP: match protocol operations:"
490 "multiple protocols ( %d). ignoring.",
491 api->match_protocol_num);
492 return 0;
493 }
494 if (api->match_protocol_num == 1 &&
495 api->protocol[0].value != PROTOCOL_UDP &&
496 api->protocol[0].value != PROTOCOL_ICMP &&
497 api->protocol[0].value != PROTOCOL_TCP) {
498 if (BGP_DEBUG(pbr, PBR))
499 zlog_debug("BGP: match protocol operations:"
500 "protocol (%d) not supported. ignoring",
501 api->match_protocol_num);
502 return 0;
503 }
504 if (!bgp_pbr_extract(api->src_port, api->match_src_port_num, NULL)) {
505 if (BGP_DEBUG(pbr, PBR))
506 zlog_debug("BGP: match src port operations:"
507 "too complex. ignoring.");
508 return 0;
509 }
510 if (!bgp_pbr_extract(api->dst_port, api->match_dst_port_num, NULL)) {
511 if (BGP_DEBUG(pbr, PBR))
512 zlog_debug("BGP: match dst port operations:"
513 "too complex. ignoring.");
514 return 0;
515 }
516 if (!bgp_pbr_extract_enumerate(api->tcpflags,
517 api->match_tcpflags_num,
518 OPERATOR_UNARY_AND |
519 OPERATOR_UNARY_OR, NULL,
520 FLOWSPEC_TCP_FLAGS)) {
521 if (BGP_DEBUG(pbr, PBR))
522 zlog_debug("BGP: match tcp flags:"
523 "too complex. ignoring.");
524 return 0;
525 }
526 if (!bgp_pbr_extract(api->icmp_type, api->match_icmp_type_num, NULL)) {
527 if (!bgp_pbr_extract_enumerate(api->icmp_type,
528 api->match_icmp_type_num,
529 OPERATOR_UNARY_OR, NULL,
530 FLOWSPEC_ICMP_TYPE)) {
531 if (BGP_DEBUG(pbr, PBR))
532 zlog_debug("BGP: match icmp type operations:"
533 "too complex. ignoring.");
534 return 0;
535 }
536 enumerate_icmp = true;
537 }
538 if (!bgp_pbr_extract(api->icmp_code, api->match_icmp_code_num, NULL)) {
539 if (!bgp_pbr_extract_enumerate(api->icmp_code,
540 api->match_icmp_code_num,
541 OPERATOR_UNARY_OR, NULL,
542 FLOWSPEC_ICMP_CODE)) {
543 if (BGP_DEBUG(pbr, PBR))
544 zlog_debug("BGP: match icmp code operations:"
545 "too complex. ignoring.");
546 return 0;
547 } else if (api->match_icmp_type_num > 1 &&
548 !enumerate_icmp) {
549 if (BGP_DEBUG(pbr, PBR))
550 zlog_debug("BGP: match icmp code is enumerate"
551 ", and icmp type is not."
552 " too complex. ignoring.");
553 return 0;
554 }
555 }
556 if (!bgp_pbr_extract(api->port, api->match_port_num, NULL)) {
557 if (BGP_DEBUG(pbr, PBR))
558 zlog_debug("BGP: match port operations:"
559 "too complex. ignoring.");
560 return 0;
561 }
562 if (api->match_packet_length_num) {
563 bool ret;
564
565 ret = bgp_pbr_extract(api->packet_length,
566 api->match_packet_length_num, NULL);
567 if (!ret)
568 ret = bgp_pbr_extract_enumerate(api->packet_length,
569 api->match_packet_length_num,
570 OPERATOR_UNARY_OR
571 | OPERATOR_UNARY_AND,
572 NULL, FLOWSPEC_PKT_LEN);
573 if (!ret) {
574 if (BGP_DEBUG(pbr, PBR))
575 zlog_debug("BGP: match packet length operations:"
576 "too complex. ignoring.");
577 return 0;
578 }
579 }
580 if (api->match_dscp_num) {
581 if (!bgp_pbr_extract_enumerate(api->dscp, api->match_dscp_num,
582 OPERATOR_UNARY_OR | OPERATOR_UNARY_AND,
583 NULL, FLOWSPEC_DSCP)) {
584 if (BGP_DEBUG(pbr, PBR))
585 zlog_debug("BGP: match DSCP operations:"
586 "too complex. ignoring.");
587 return 0;
588 }
589 }
590 if (api->match_fragment_num) {
591 char fail_str[64];
592 bool success;
593
594 success = bgp_pbr_extract_enumerate(api->fragment,
595 api->match_fragment_num,
596 OPERATOR_UNARY_OR
597 | OPERATOR_UNARY_AND,
598 NULL, FLOWSPEC_FRAGMENT);
599 if (success) {
600 int i;
601
602 for (i = 0; i < api->match_fragment_num; i++) {
603 if (api->fragment[i].value != 1 &&
604 api->fragment[i].value != 2 &&
605 api->fragment[i].value != 4 &&
606 api->fragment[i].value != 8) {
607 success = false;
608 sprintf(fail_str,
609 "Value not valid (%d) for this implementation",
610 api->fragment[i].value);
611 }
612 }
613 } else
614 sprintf(fail_str, "too complex. ignoring");
615 if (!success) {
616 if (BGP_DEBUG(pbr, PBR))
617 zlog_debug("BGP: match fragment operation (%d) %s",
618 api->match_fragment_num,
619 fail_str);
620 return 0;
621 }
622 }
623
624 /* no combinations with both src_port and dst_port
625 * or port with src_port and dst_port
626 */
627 if (api->match_src_port_num + api->match_dst_port_num +
628 api->match_port_num > 3) {
629 if (BGP_DEBUG(pbr, PBR))
630 zlog_debug("BGP: match multiple port operations:"
631 " too complex. ignoring.");
632 return 0;
633 }
634 if ((api->match_src_port_num || api->match_dst_port_num
635 || api->match_port_num) && (api->match_icmp_type_num
636 || api->match_icmp_code_num)) {
637 if (BGP_DEBUG(pbr, PBR))
638 zlog_debug("BGP: match multiple port/imcp operations:"
639 " too complex. ignoring.");
640 return 0;
641 }
642 /* iprule only supports redirect IP */
643 if (api->type == BGP_PBR_IPRULE) {
644 int i;
645
646 for (i = 0; i < api->action_num; i++) {
647 if (api->actions[i].action == ACTION_TRAFFICRATE &&
648 api->actions[i].u.r.rate == 0) {
649 if (BGP_DEBUG(pbr, PBR)) {
650 bgp_pbr_print_policy_route(api);
651 zlog_debug("BGP: iprule match actions"
652 " drop not supported");
653 }
654 return 0;
655 }
656 if (api->actions[i].action == ACTION_MARKING) {
657 if (BGP_DEBUG(pbr, PBR)) {
658 bgp_pbr_print_policy_route(api);
659 zlog_warn("PBR: iprule set DSCP %u"
660 " not supported",
661 api->actions[i].u.marking_dscp);
662 }
663 }
664 if (api->actions[i].action == ACTION_REDIRECT) {
665 if (BGP_DEBUG(pbr, PBR)) {
666 bgp_pbr_print_policy_route(api);
667 zlog_warn("PBR: iprule redirect VRF %u"
668 " not supported",
669 api->actions[i].u.redirect_vrf);
670 }
671 }
672 }
673
674 } else if (!(api->match_bitmask & PREFIX_SRC_PRESENT) &&
675 !(api->match_bitmask & PREFIX_DST_PRESENT)) {
676 if (BGP_DEBUG(pbr, PBR)) {
677 bgp_pbr_print_policy_route(api);
678 zlog_debug("BGP: match actions without src"
679 " or dst address can not operate."
680 " ignoring.");
681 }
682 return 0;
683 }
684 return 1;
685 }
686
687 /* return -1 if build or validation failed */
688 int bgp_pbr_build_and_validate_entry(struct prefix *p,
689 struct bgp_path_info *path,
690 struct bgp_pbr_entry_main *api)
691 {
692 int ret;
693 int i, action_count = 0;
694 struct ecommunity *ecom;
695 struct ecommunity_val *ecom_eval;
696 struct bgp_pbr_entry_action *api_action;
697 struct prefix *src = NULL, *dst = NULL;
698 int valid_prefix = 0;
699 afi_t afi = AFI_IP;
700 struct bgp_pbr_entry_action *api_action_redirect_ip = NULL;
701
702 /* extract match from flowspec entries */
703 ret = bgp_flowspec_match_rules_fill((uint8_t *)p->u.prefix_flowspec.ptr,
704 p->u.prefix_flowspec.prefixlen, api);
705 if (ret < 0)
706 return -1;
707 /* extract actiosn from flowspec ecom list */
708 if (path && path->attr && path->attr->ecommunity) {
709 ecom = path->attr->ecommunity;
710 for (i = 0; i < ecom->size; i++) {
711 ecom_eval = (struct ecommunity_val *)
712 (ecom->val + (i * ECOMMUNITY_SIZE));
713 action_count++;
714 if (action_count > ACTIONS_MAX_NUM) {
715 if (BGP_DEBUG(pbr, PBR_ERROR))
716 flog_err(
717 EC_BGP_FLOWSPEC_PACKET,
718 "%s: flowspec actions exceeds limit (max %u)",
719 __func__, action_count);
720 break;
721 }
722 api_action = &api->actions[action_count - 1];
723
724 if ((ecom_eval->val[1] ==
725 (char)ECOMMUNITY_REDIRECT_VRF) &&
726 (ecom_eval->val[0] ==
727 (char)ECOMMUNITY_ENCODE_TRANS_EXP ||
728 ecom_eval->val[0] ==
729 (char)ECOMMUNITY_EXTENDED_COMMUNITY_PART_2 ||
730 ecom_eval->val[0] ==
731 (char)ECOMMUNITY_EXTENDED_COMMUNITY_PART_3)) {
732 struct ecommunity *eckey = ecommunity_new();
733 struct ecommunity_val ecom_copy;
734
735 memcpy(&ecom_copy, ecom_eval,
736 sizeof(struct ecommunity_val));
737 ecom_copy.val[0] &=
738 ~ECOMMUNITY_ENCODE_TRANS_EXP;
739 ecom_copy.val[1] = ECOMMUNITY_ROUTE_TARGET;
740 ecommunity_add_val(eckey, &ecom_copy);
741
742 api_action->action = ACTION_REDIRECT;
743 api_action->u.redirect_vrf =
744 get_first_vrf_for_redirect_with_rt(
745 eckey);
746 ecommunity_free(&eckey);
747 } else if ((ecom_eval->val[0] ==
748 (char)ECOMMUNITY_ENCODE_REDIRECT_IP_NH) &&
749 (ecom_eval->val[1] ==
750 (char)ECOMMUNITY_REDIRECT_IP_NH)) {
751 /* in case the 2 ecom present,
752 * do not overwrite
753 * draft-ietf-idr-flowspec-redirect
754 */
755 if (api_action_redirect_ip) {
756 if (api_action_redirect_ip->u
757 .zr.redirect_ip_v4.s_addr)
758 continue;
759 if (!path->attr->nexthop.s_addr)
760 continue;
761 api_action_redirect_ip->u
762 .zr.redirect_ip_v4.s_addr =
763 path->attr->nexthop.s_addr;
764 api_action_redirect_ip->u.zr.duplicate
765 = ecom_eval->val[7];
766 continue;
767 } else {
768 api_action->action = ACTION_REDIRECT_IP;
769 api_action->u.zr.redirect_ip_v4.s_addr =
770 path->attr->nexthop.s_addr;
771 api_action->u.zr.duplicate =
772 ecom_eval->val[7];
773 api_action_redirect_ip = api_action;
774 }
775 } else if ((ecom_eval->val[0] ==
776 (char)ECOMMUNITY_ENCODE_IP) &&
777 (ecom_eval->val[1] ==
778 (char)ECOMMUNITY_FLOWSPEC_REDIRECT_IPV4)) {
779 /* in case the 2 ecom present,
780 * overwrite simpson draft
781 * update redirect ip fields
782 */
783 if (api_action_redirect_ip) {
784 memcpy(&(api_action_redirect_ip->u
785 .zr.redirect_ip_v4.s_addr),
786 (ecom_eval->val+2), 4);
787 api_action_redirect_ip->u
788 .zr.duplicate =
789 ecom_eval->val[7];
790 continue;
791 } else {
792 api_action->action = ACTION_REDIRECT_IP;
793 memcpy(&(api_action->u
794 .zr.redirect_ip_v4.s_addr),
795 (ecom_eval->val+2), 4);
796 api_action->u.zr.duplicate =
797 ecom_eval->val[7];
798 api_action_redirect_ip = api_action;
799 }
800 } else {
801 if (ecom_eval->val[0] !=
802 (char)ECOMMUNITY_ENCODE_TRANS_EXP)
803 continue;
804 ret = ecommunity_fill_pbr_action(ecom_eval,
805 api_action);
806 if (ret != 0)
807 continue;
808 }
809 api->action_num++;
810 }
811 }
812
813 /* validate if incoming matc/action is compatible
814 * with our policy routing engine
815 */
816 if (!bgp_pbr_validate_policy_route(api))
817 return -1;
818
819 /* check inconsistency in the match rule */
820 if (api->match_bitmask & PREFIX_SRC_PRESENT) {
821 src = &api->src_prefix;
822 afi = family2afi(src->family);
823 valid_prefix = 1;
824 }
825 if (api->match_bitmask & PREFIX_DST_PRESENT) {
826 dst = &api->dst_prefix;
827 if (valid_prefix && afi != family2afi(dst->family)) {
828 if (BGP_DEBUG(pbr, PBR)) {
829 bgp_pbr_print_policy_route(api);
830 zlog_debug("%s: inconsistency:"
831 " no match for afi src and dst (%u/%u)",
832 __func__, afi, family2afi(dst->family));
833 }
834 return -1;
835 }
836 }
837 return 0;
838 }
839
840 static void bgp_pbr_match_entry_free(void *arg)
841 {
842 struct bgp_pbr_match_entry *bpme;
843
844 bpme = (struct bgp_pbr_match_entry *)arg;
845
846 if (bpme->installed) {
847 bgp_send_pbr_ipset_entry_match(bpme, false);
848 bpme->installed = false;
849 bpme->backpointer = NULL;
850 }
851 XFREE(MTYPE_PBR_MATCH_ENTRY, bpme);
852 }
853
854 static void bgp_pbr_match_free(void *arg)
855 {
856 struct bgp_pbr_match *bpm;
857
858 bpm = (struct bgp_pbr_match *)arg;
859
860 hash_clean(bpm->entry_hash, bgp_pbr_match_entry_free);
861
862 if (hashcount(bpm->entry_hash) == 0) {
863 /* delete iptable entry first */
864 /* then delete ipset match */
865 if (bpm->installed) {
866 if (bpm->installed_in_iptable) {
867 bgp_send_pbr_iptable(bpm->action,
868 bpm, false);
869 bpm->installed_in_iptable = false;
870 bpm->action->refcnt--;
871 }
872 bgp_send_pbr_ipset_match(bpm, false);
873 bpm->installed = false;
874 bpm->action = NULL;
875 }
876 }
877 hash_free(bpm->entry_hash);
878
879 XFREE(MTYPE_PBR_MATCH, bpm);
880 }
881
882 static void *bgp_pbr_match_alloc_intern(void *arg)
883 {
884 struct bgp_pbr_match *bpm, *new;
885
886 bpm = (struct bgp_pbr_match *)arg;
887
888 new = XCALLOC(MTYPE_PBR_MATCH, sizeof(*new));
889 memcpy(new, bpm, sizeof(*bpm));
890
891 return new;
892 }
893
894 static void bgp_pbr_rule_free(void *arg)
895 {
896 struct bgp_pbr_rule *bpr;
897
898 bpr = (struct bgp_pbr_rule *)arg;
899
900 /* delete iprule */
901 if (bpr->installed) {
902 bgp_send_pbr_rule_action(bpr->action, bpr, false);
903 bpr->installed = false;
904 bpr->action->refcnt--;
905 bpr->action = NULL;
906 }
907 XFREE(MTYPE_PBR_RULE, bpr);
908 }
909
910 static void *bgp_pbr_rule_alloc_intern(void *arg)
911 {
912 struct bgp_pbr_rule *bpr, *new;
913
914 bpr = (struct bgp_pbr_rule *)arg;
915
916 new = XCALLOC(MTYPE_PBR_RULE, sizeof(*new));
917 memcpy(new, bpr, sizeof(*bpr));
918
919 return new;
920 }
921
922 static void bgp_pbr_action_free(void *arg)
923 {
924 struct bgp_pbr_action *bpa;
925
926 bpa = (struct bgp_pbr_action *)arg;
927
928 if (bpa->refcnt == 0) {
929 if (bpa->installed && bpa->table_id != 0) {
930 bgp_send_pbr_rule_action(bpa, NULL, false);
931 bgp_zebra_announce_default(bpa->bgp, &(bpa->nh),
932 AFI_IP,
933 bpa->table_id,
934 false);
935 bpa->installed = false;
936 }
937 }
938 XFREE(MTYPE_PBR_ACTION, bpa);
939 }
940
941 static void *bgp_pbr_action_alloc_intern(void *arg)
942 {
943 struct bgp_pbr_action *bpa, *new;
944
945 bpa = (struct bgp_pbr_action *)arg;
946
947 new = XCALLOC(MTYPE_PBR_ACTION, sizeof(*new));
948
949 memcpy(new, bpa, sizeof(*bpa));
950
951 return new;
952 }
953
954 static void *bgp_pbr_match_entry_alloc_intern(void *arg)
955 {
956 struct bgp_pbr_match_entry *bpme, *new;
957
958 bpme = (struct bgp_pbr_match_entry *)arg;
959
960 new = XCALLOC(MTYPE_PBR_MATCH_ENTRY, sizeof(*new));
961
962 memcpy(new, bpme, sizeof(*bpme));
963
964 return new;
965 }
966
967 uint32_t bgp_pbr_match_hash_key(void *arg)
968 {
969 struct bgp_pbr_match *pbm = (struct bgp_pbr_match *)arg;
970 uint32_t key;
971
972 key = jhash_1word(pbm->vrf_id, 0x4312abde);
973 key = jhash_1word(pbm->flags, key);
974 key = jhash(&pbm->pkt_len_min, 2, key);
975 key = jhash(&pbm->pkt_len_max, 2, key);
976 key = jhash(&pbm->tcp_flags, 2, key);
977 key = jhash(&pbm->tcp_mask_flags, 2, key);
978 key = jhash(&pbm->dscp_value, 1, key);
979 key = jhash(&pbm->fragment, 1, key);
980 return jhash_1word(pbm->type, key);
981 }
982
983 bool bgp_pbr_match_hash_equal(const void *arg1, const void *arg2)
984 {
985 const struct bgp_pbr_match *r1, *r2;
986
987 r1 = (const struct bgp_pbr_match *)arg1;
988 r2 = (const struct bgp_pbr_match *)arg2;
989
990 if (r1->vrf_id != r2->vrf_id)
991 return false;
992
993 if (r1->type != r2->type)
994 return false;
995
996 if (r1->flags != r2->flags)
997 return false;
998
999 if (r1->action != r2->action)
1000 return false;
1001
1002 if (r1->pkt_len_min != r2->pkt_len_min)
1003 return false;
1004
1005 if (r1->pkt_len_max != r2->pkt_len_max)
1006 return false;
1007
1008 if (r1->tcp_flags != r2->tcp_flags)
1009 return false;
1010
1011 if (r1->tcp_mask_flags != r2->tcp_mask_flags)
1012 return false;
1013
1014 if (r1->dscp_value != r2->dscp_value)
1015 return false;
1016
1017 if (r1->fragment != r2->fragment)
1018 return false;
1019 return true;
1020 }
1021
1022 uint32_t bgp_pbr_rule_hash_key(void *arg)
1023 {
1024 struct bgp_pbr_rule *pbr = (struct bgp_pbr_rule *)arg;
1025 uint32_t key;
1026
1027 key = prefix_hash_key(&pbr->src);
1028 key = jhash_1word(pbr->vrf_id, key);
1029 key = jhash_1word(pbr->flags, key);
1030 return jhash_1word(prefix_hash_key(&pbr->dst), key);
1031 }
1032
1033 bool bgp_pbr_rule_hash_equal(const void *arg1, const void *arg2)
1034 {
1035 const struct bgp_pbr_rule *r1, *r2;
1036
1037 r1 = (const struct bgp_pbr_rule *)arg1;
1038 r2 = (const struct bgp_pbr_rule *)arg2;
1039
1040 if (r1->vrf_id != r2->vrf_id)
1041 return false;
1042
1043 if (r1->flags != r2->flags)
1044 return false;
1045
1046 if (r1->action != r2->action)
1047 return false;
1048
1049 if ((r1->flags & MATCH_IP_SRC_SET) &&
1050 !prefix_same(&r1->src, &r2->src))
1051 return false;
1052
1053 if ((r1->flags & MATCH_IP_DST_SET) &&
1054 !prefix_same(&r1->dst, &r2->dst))
1055 return false;
1056
1057 return true;
1058 }
1059
1060 uint32_t bgp_pbr_match_entry_hash_key(void *arg)
1061 {
1062 struct bgp_pbr_match_entry *pbme;
1063 uint32_t key;
1064
1065 pbme = (struct bgp_pbr_match_entry *)arg;
1066 key = prefix_hash_key(&pbme->src);
1067 key = jhash_1word(prefix_hash_key(&pbme->dst), key);
1068 key = jhash(&pbme->dst_port_min, 2, key);
1069 key = jhash(&pbme->src_port_min, 2, key);
1070 key = jhash(&pbme->dst_port_max, 2, key);
1071 key = jhash(&pbme->src_port_max, 2, key);
1072 key = jhash(&pbme->proto, 1, key);
1073
1074 return key;
1075 }
1076
1077 bool bgp_pbr_match_entry_hash_equal(const void *arg1, const void *arg2)
1078 {
1079 const struct bgp_pbr_match_entry *r1, *r2;
1080
1081 r1 = (const struct bgp_pbr_match_entry *)arg1;
1082 r2 = (const struct bgp_pbr_match_entry *)arg2;
1083
1084 /*
1085 * on updates, comparing backpointer is not necessary
1086 * unique value is self calculated
1087 * rate is ignored for now
1088 */
1089
1090 if (!prefix_same(&r1->src, &r2->src))
1091 return false;
1092
1093 if (!prefix_same(&r1->dst, &r2->dst))
1094 return false;
1095
1096 if (r1->src_port_min != r2->src_port_min)
1097 return false;
1098
1099 if (r1->dst_port_min != r2->dst_port_min)
1100 return false;
1101
1102 if (r1->src_port_max != r2->src_port_max)
1103 return false;
1104
1105 if (r1->dst_port_max != r2->dst_port_max)
1106 return false;
1107
1108 if (r1->proto != r2->proto)
1109 return false;
1110
1111 return true;
1112 }
1113
1114 uint32_t bgp_pbr_action_hash_key(void *arg)
1115 {
1116 struct bgp_pbr_action *pbra;
1117 uint32_t key;
1118
1119 pbra = (struct bgp_pbr_action *)arg;
1120 key = jhash_1word(pbra->table_id, 0x4312abde);
1121 key = jhash_1word(pbra->fwmark, key);
1122 return key;
1123 }
1124
1125 bool bgp_pbr_action_hash_equal(const void *arg1, const void *arg2)
1126 {
1127 const struct bgp_pbr_action *r1, *r2;
1128
1129 r1 = (const struct bgp_pbr_action *)arg1;
1130 r2 = (const struct bgp_pbr_action *)arg2;
1131
1132 /* unique value is self calculated
1133 * table and fwmark is self calculated
1134 * rate is ignored
1135 */
1136 if (r1->vrf_id != r2->vrf_id)
1137 return false;
1138
1139 if (memcmp(&r1->nh, &r2->nh, sizeof(struct nexthop)))
1140 return false;
1141
1142 return true;
1143 }
1144
1145 struct bgp_pbr_rule *bgp_pbr_rule_lookup(vrf_id_t vrf_id,
1146 uint32_t unique)
1147 {
1148 struct bgp *bgp = bgp_lookup_by_vrf_id(vrf_id);
1149 struct bgp_pbr_rule_unique bpru;
1150
1151 if (!bgp || unique == 0)
1152 return NULL;
1153 bpru.unique = unique;
1154 bpru.bpr_found = NULL;
1155 hash_walk(bgp->pbr_rule_hash, bgp_pbr_rule_walkcb, &bpru);
1156 return bpru.bpr_found;
1157 }
1158
1159 struct bgp_pbr_action *bgp_pbr_action_rule_lookup(vrf_id_t vrf_id,
1160 uint32_t unique)
1161 {
1162 struct bgp *bgp = bgp_lookup_by_vrf_id(vrf_id);
1163 struct bgp_pbr_action_unique bpau;
1164
1165 if (!bgp || unique == 0)
1166 return NULL;
1167 bpau.unique = unique;
1168 bpau.bpa_found = NULL;
1169 hash_walk(bgp->pbr_action_hash, bgp_pbr_action_walkcb, &bpau);
1170 return bpau.bpa_found;
1171 }
1172
1173 struct bgp_pbr_match *bgp_pbr_match_ipset_lookup(vrf_id_t vrf_id,
1174 uint32_t unique)
1175 {
1176 struct bgp *bgp = bgp_lookup_by_vrf_id(vrf_id);
1177 struct bgp_pbr_match_unique bpmu;
1178
1179 if (!bgp || unique == 0)
1180 return NULL;
1181 bpmu.unique = unique;
1182 bpmu.bpm_found = NULL;
1183 hash_walk(bgp->pbr_match_hash, bgp_pbr_match_walkcb, &bpmu);
1184 return bpmu.bpm_found;
1185 }
1186
1187 struct bgp_pbr_match_entry *bgp_pbr_match_ipset_entry_lookup(vrf_id_t vrf_id,
1188 char *ipset_name,
1189 uint32_t unique)
1190 {
1191 struct bgp *bgp = bgp_lookup_by_vrf_id(vrf_id);
1192 struct bgp_pbr_match_entry_unique bpmeu;
1193 struct bgp_pbr_match_ipsetname bpmi;
1194
1195 if (!bgp || unique == 0)
1196 return NULL;
1197 bpmi.ipsetname = XCALLOC(MTYPE_TMP, ZEBRA_IPSET_NAME_SIZE);
1198 snprintf(bpmi.ipsetname, ZEBRA_IPSET_NAME_SIZE, "%s", ipset_name);
1199 bpmi.bpm_found = NULL;
1200 hash_walk(bgp->pbr_match_hash, bgp_pbr_match_pername_walkcb, &bpmi);
1201 XFREE(MTYPE_TMP, bpmi.ipsetname);
1202 if (!bpmi.bpm_found)
1203 return NULL;
1204 bpmeu.bpme_found = NULL;
1205 bpmeu.unique = unique;
1206 hash_walk(bpmi.bpm_found->entry_hash,
1207 bgp_pbr_match_entry_walkcb, &bpmeu);
1208 return bpmeu.bpme_found;
1209 }
1210
1211 struct bgp_pbr_match *bgp_pbr_match_iptable_lookup(vrf_id_t vrf_id,
1212 uint32_t unique)
1213 {
1214 struct bgp *bgp = bgp_lookup_by_vrf_id(vrf_id);
1215 struct bgp_pbr_match_iptable_unique bpmiu;
1216
1217 if (!bgp || unique == 0)
1218 return NULL;
1219 bpmiu.unique = unique;
1220 bpmiu.bpm_found = NULL;
1221 hash_walk(bgp->pbr_match_hash, bgp_pbr_match_iptable_walkcb, &bpmiu);
1222 return bpmiu.bpm_found;
1223 }
1224
1225 void bgp_pbr_cleanup(struct bgp *bgp)
1226 {
1227 if (bgp->pbr_match_hash) {
1228 hash_clean(bgp->pbr_match_hash, bgp_pbr_match_free);
1229 hash_free(bgp->pbr_match_hash);
1230 bgp->pbr_match_hash = NULL;
1231 }
1232 if (bgp->pbr_rule_hash) {
1233 hash_clean(bgp->pbr_rule_hash, bgp_pbr_rule_free);
1234 hash_free(bgp->pbr_rule_hash);
1235 bgp->pbr_rule_hash = NULL;
1236 }
1237 if (bgp->pbr_action_hash) {
1238 hash_clean(bgp->pbr_action_hash, bgp_pbr_action_free);
1239 hash_free(bgp->pbr_action_hash);
1240 bgp->pbr_action_hash = NULL;
1241 }
1242 if (bgp->bgp_pbr_cfg == NULL)
1243 return;
1244 bgp_pbr_reset(bgp, AFI_IP);
1245 XFREE(MTYPE_PBR, bgp->bgp_pbr_cfg);
1246 bgp->bgp_pbr_cfg = NULL;
1247 }
1248
1249 void bgp_pbr_init(struct bgp *bgp)
1250 {
1251 bgp->pbr_match_hash =
1252 hash_create_size(8, bgp_pbr_match_hash_key,
1253 bgp_pbr_match_hash_equal,
1254 "Match Hash");
1255 bgp->pbr_action_hash =
1256 hash_create_size(8, bgp_pbr_action_hash_key,
1257 bgp_pbr_action_hash_equal,
1258 "Match Hash Entry");
1259
1260 bgp->pbr_rule_hash =
1261 hash_create_size(8, bgp_pbr_rule_hash_key,
1262 bgp_pbr_rule_hash_equal,
1263 "Match Rule");
1264
1265 bgp->bgp_pbr_cfg = XCALLOC(MTYPE_PBR, sizeof(struct bgp_pbr_config));
1266 bgp->bgp_pbr_cfg->pbr_interface_any_ipv4 = true;
1267 }
1268
1269 void bgp_pbr_print_policy_route(struct bgp_pbr_entry_main *api)
1270 {
1271 int i = 0;
1272 char return_string[512];
1273 char *ptr = return_string;
1274 char buff[64];
1275 int nb_items = 0;
1276
1277 ptr += sprintf(ptr, "MATCH : ");
1278 if (api->match_bitmask & PREFIX_SRC_PRESENT) {
1279 struct prefix *p = &(api->src_prefix);
1280
1281 ptr += sprintf(ptr, "@src %s", prefix2str(p, buff, 64));
1282 INCREMENT_DISPLAY(ptr, nb_items);
1283 }
1284 if (api->match_bitmask & PREFIX_DST_PRESENT) {
1285 struct prefix *p = &(api->dst_prefix);
1286
1287 INCREMENT_DISPLAY(ptr, nb_items);
1288 ptr += sprintf(ptr, "@dst %s", prefix2str(p, buff, 64));
1289 }
1290
1291 if (api->match_protocol_num)
1292 INCREMENT_DISPLAY(ptr, nb_items);
1293 for (i = 0; i < api->match_protocol_num; i++)
1294 ptr += sprintf_bgp_pbr_match_val(ptr, &api->protocol[i],
1295 i > 0 ? NULL : "@proto ");
1296
1297 if (api->match_src_port_num)
1298 INCREMENT_DISPLAY(ptr, nb_items);
1299 for (i = 0; i < api->match_src_port_num; i++)
1300 ptr += sprintf_bgp_pbr_match_val(ptr, &api->src_port[i],
1301 i > 0 ? NULL : "@srcport ");
1302
1303 if (api->match_dst_port_num)
1304 INCREMENT_DISPLAY(ptr, nb_items);
1305 for (i = 0; i < api->match_dst_port_num; i++)
1306 ptr += sprintf_bgp_pbr_match_val(ptr, &api->dst_port[i],
1307 i > 0 ? NULL : "@dstport ");
1308
1309 if (api->match_port_num)
1310 INCREMENT_DISPLAY(ptr, nb_items);
1311 for (i = 0; i < api->match_port_num; i++)
1312 ptr += sprintf_bgp_pbr_match_val(ptr, &api->port[i],
1313 i > 0 ? NULL : "@port ");
1314
1315 if (api->match_icmp_type_num)
1316 INCREMENT_DISPLAY(ptr, nb_items);
1317 for (i = 0; i < api->match_icmp_type_num; i++)
1318 ptr += sprintf_bgp_pbr_match_val(ptr, &api->icmp_type[i],
1319 i > 0 ? NULL : "@icmptype ");
1320
1321 if (api->match_icmp_code_num)
1322 INCREMENT_DISPLAY(ptr, nb_items);
1323 for (i = 0; i < api->match_icmp_code_num; i++)
1324 ptr += sprintf_bgp_pbr_match_val(ptr, &api->icmp_code[i],
1325 i > 0 ? NULL : "@icmpcode ");
1326
1327 if (api->match_packet_length_num)
1328 INCREMENT_DISPLAY(ptr, nb_items);
1329 for (i = 0; i < api->match_packet_length_num; i++)
1330 ptr += sprintf_bgp_pbr_match_val(ptr, &api->packet_length[i],
1331 i > 0 ? NULL : "@plen ");
1332
1333 if (api->match_dscp_num)
1334 INCREMENT_DISPLAY(ptr, nb_items);
1335 for (i = 0; i < api->match_dscp_num; i++)
1336 ptr += sprintf_bgp_pbr_match_val(ptr, &api->dscp[i],
1337 i > 0 ? NULL : "@dscp ");
1338
1339 if (api->match_tcpflags_num)
1340 INCREMENT_DISPLAY(ptr, nb_items);
1341 for (i = 0; i < api->match_tcpflags_num; i++)
1342 ptr += sprintf_bgp_pbr_match_val(ptr, &api->tcpflags[i],
1343 i > 0 ? NULL : "@tcpflags ");
1344
1345 if (api->match_fragment_num)
1346 INCREMENT_DISPLAY(ptr, nb_items);
1347 for (i = 0; i < api->match_fragment_num; i++)
1348 ptr += sprintf_bgp_pbr_match_val(ptr, &api->fragment[i],
1349 i > 0 ? NULL : "@fragment ");
1350 if (!nb_items)
1351 ptr = return_string;
1352 else
1353 ptr += sprintf(ptr, "; ");
1354 if (api->action_num)
1355 ptr += sprintf(ptr, "SET : ");
1356 nb_items = 0;
1357 for (i = 0; i < api->action_num; i++) {
1358 switch (api->actions[i].action) {
1359 case ACTION_TRAFFICRATE:
1360 INCREMENT_DISPLAY(ptr, nb_items);
1361 ptr += sprintf(ptr, "@set rate %f",
1362 api->actions[i].u.r.rate);
1363 break;
1364 case ACTION_TRAFFIC_ACTION:
1365 INCREMENT_DISPLAY(ptr, nb_items);
1366 ptr += sprintf(ptr, "@action ");
1367 if (api->actions[i].u.za.filter
1368 & TRAFFIC_ACTION_TERMINATE)
1369 ptr += sprintf(ptr,
1370 " terminate (apply filter(s))");
1371 if (api->actions[i].u.za.filter
1372 & TRAFFIC_ACTION_DISTRIBUTE)
1373 ptr += sprintf(ptr, " distribute");
1374 if (api->actions[i].u.za.filter
1375 & TRAFFIC_ACTION_SAMPLE)
1376 ptr += sprintf(ptr, " sample");
1377 break;
1378 case ACTION_REDIRECT_IP:
1379 INCREMENT_DISPLAY(ptr, nb_items);
1380 char local_buff[INET_ADDRSTRLEN];
1381
1382 if (inet_ntop(AF_INET,
1383 &api->actions[i].u.zr.redirect_ip_v4,
1384 local_buff, INET_ADDRSTRLEN) != NULL)
1385 ptr += sprintf(ptr,
1386 "@redirect ip nh %s", local_buff);
1387 break;
1388 case ACTION_REDIRECT:
1389 INCREMENT_DISPLAY(ptr, nb_items);
1390 ptr += sprintf(ptr, "@redirect vrf %u",
1391 api->actions[i].u.redirect_vrf);
1392 break;
1393 case ACTION_MARKING:
1394 INCREMENT_DISPLAY(ptr, nb_items);
1395 ptr += sprintf(ptr, "@set dscp %u",
1396 api->actions[i].u.marking_dscp);
1397 break;
1398 default:
1399 break;
1400 }
1401 }
1402 zlog_info("%s", return_string);
1403 }
1404
1405 static void bgp_pbr_flush_iprule(struct bgp *bgp, struct bgp_pbr_action *bpa,
1406 struct bgp_pbr_rule *bpr)
1407 {
1408 /* if bpr is null, do nothing
1409 */
1410 if (bpr == NULL)
1411 return;
1412 if (bpr->installed) {
1413 bgp_send_pbr_rule_action(bpa, bpr, false);
1414 bpr->installed = false;
1415 bpr->action->refcnt--;
1416 bpr->action = NULL;
1417 if (bpr->path) {
1418 struct bgp_path_info *path;
1419 struct bgp_path_info_extra *extra;
1420
1421 /* unlink path to bpme */
1422 path = (struct bgp_path_info *)bpr->path;
1423 extra = bgp_path_info_extra_get(path);
1424 if (extra->bgp_fs_iprule)
1425 listnode_delete(extra->bgp_fs_iprule, bpr);
1426 bpr->path = NULL;
1427 }
1428 }
1429 hash_release(bgp->pbr_rule_hash, bpr);
1430 if (bpa->refcnt == 0) {
1431 if (bpa->installed && bpa->table_id != 0) {
1432 bgp_send_pbr_rule_action(bpa, NULL, false);
1433 bgp_zebra_announce_default(bpa->bgp, &(bpa->nh),
1434 AFI_IP,
1435 bpa->table_id,
1436 false);
1437 bpa->installed = false;
1438 }
1439 }
1440 }
1441
1442 static void bgp_pbr_flush_entry(struct bgp *bgp, struct bgp_pbr_action *bpa,
1443 struct bgp_pbr_match *bpm,
1444 struct bgp_pbr_match_entry *bpme)
1445 {
1446 /* if bpme is null, bpm is also null
1447 */
1448 if (bpme == NULL)
1449 return;
1450 /* ipset del entry */
1451 if (bpme->installed) {
1452 bgp_send_pbr_ipset_entry_match(bpme, false);
1453 bpme->installed = false;
1454 bpme->backpointer = NULL;
1455 if (bpme->path) {
1456 struct bgp_path_info *path;
1457 struct bgp_path_info_extra *extra;
1458
1459 /* unlink path to bpme */
1460 path = (struct bgp_path_info *)bpme->path;
1461 extra = bgp_path_info_extra_get(path);
1462 if (extra->bgp_fs_pbr)
1463 listnode_delete(extra->bgp_fs_pbr, bpme);
1464 bpme->path = NULL;
1465 }
1466 }
1467 hash_release(bpm->entry_hash, bpme);
1468 if (hashcount(bpm->entry_hash) == 0) {
1469 /* delete iptable entry first */
1470 /* then delete ipset match */
1471 if (bpm->installed) {
1472 if (bpm->installed_in_iptable) {
1473 bgp_send_pbr_iptable(bpm->action,
1474 bpm, false);
1475 bpm->installed_in_iptable = false;
1476 bpm->action->refcnt--;
1477 }
1478 bgp_send_pbr_ipset_match(bpm, false);
1479 bpm->installed = false;
1480 bpm->action = NULL;
1481 }
1482 hash_release(bgp->pbr_match_hash, bpm);
1483 /* XXX release pbr_match_action if not used
1484 * note that drop does not need to call send_pbr_action
1485 */
1486 }
1487 if (bpa->refcnt == 0) {
1488 if (bpa->installed && bpa->table_id != 0) {
1489 bgp_send_pbr_rule_action(bpa, NULL, false);
1490 bgp_zebra_announce_default(bpa->bgp, &(bpa->nh),
1491 AFI_IP,
1492 bpa->table_id,
1493 false);
1494 bpa->installed = false;
1495 }
1496 }
1497 }
1498
1499 struct bgp_pbr_match_entry_remain {
1500 struct bgp_pbr_match_entry *bpme_to_match;
1501 struct bgp_pbr_match_entry *bpme_found;
1502 };
1503
1504 struct bgp_pbr_rule_remain {
1505 struct bgp_pbr_rule *bpr_to_match;
1506 struct bgp_pbr_rule *bpr_found;
1507 };
1508
1509 static int bgp_pbr_get_same_rule(struct hash_bucket *bucket, void *arg)
1510 {
1511 struct bgp_pbr_rule *r1 = (struct bgp_pbr_rule *)bucket->data;
1512 struct bgp_pbr_rule_remain *ctxt =
1513 (struct bgp_pbr_rule_remain *)arg;
1514 struct bgp_pbr_rule *r2;
1515
1516 r2 = ctxt->bpr_to_match;
1517
1518 if (r1->vrf_id != r2->vrf_id)
1519 return HASHWALK_CONTINUE;
1520
1521 if (r1->flags != r2->flags)
1522 return HASHWALK_CONTINUE;
1523
1524 if ((r1->flags & MATCH_IP_SRC_SET) &&
1525 !prefix_same(&r1->src, &r2->src))
1526 return HASHWALK_CONTINUE;
1527
1528 if ((r1->flags & MATCH_IP_DST_SET) &&
1529 !prefix_same(&r1->dst, &r2->dst))
1530 return HASHWALK_CONTINUE;
1531
1532 /* this function is used for two cases:
1533 * - remove an entry upon withdraw request
1534 * (case r2->action is null)
1535 * - replace an old iprule with different action
1536 * (case r2->action is != null)
1537 * the old one is removed after the new one
1538 * this is to avoid disruption in traffic
1539 */
1540 if (r2->action == NULL ||
1541 r1->action != r2->action) {
1542 ctxt->bpr_found = r1;
1543 return HASHWALK_ABORT;
1544 }
1545 return HASHWALK_CONTINUE;
1546 }
1547
1548 static int bgp_pbr_get_remaining_entry(struct hash_bucket *bucket, void *arg)
1549 {
1550 struct bgp_pbr_match *bpm = (struct bgp_pbr_match *)bucket->data;
1551 struct bgp_pbr_match_entry_remain *bpmer =
1552 (struct bgp_pbr_match_entry_remain *)arg;
1553 struct bgp_pbr_match *bpm_temp;
1554 struct bgp_pbr_match_entry *bpme = bpmer->bpme_to_match;
1555
1556 if (!bpme->backpointer ||
1557 bpm == bpme->backpointer ||
1558 bpme->backpointer->action == bpm->action)
1559 return HASHWALK_CONTINUE;
1560 /* ensure bpm other characteristics are equal */
1561 bpm_temp = bpme->backpointer;
1562 if (bpm_temp->vrf_id != bpm->vrf_id ||
1563 bpm_temp->type != bpm->type ||
1564 bpm_temp->flags != bpm->flags ||
1565 bpm_temp->tcp_flags != bpm->tcp_flags ||
1566 bpm_temp->tcp_mask_flags != bpm->tcp_mask_flags ||
1567 bpm_temp->pkt_len_min != bpm->pkt_len_min ||
1568 bpm_temp->pkt_len_max != bpm->pkt_len_max ||
1569 bpm_temp->dscp_value != bpm->dscp_value ||
1570 bpm_temp->fragment != bpm->fragment)
1571 return HASHWALK_CONTINUE;
1572
1573 /* look for remaining bpme */
1574 bpmer->bpme_found = hash_lookup(bpm->entry_hash, bpme);
1575 if (!bpmer->bpme_found)
1576 return HASHWALK_CONTINUE;
1577 return HASHWALK_ABORT;
1578 }
1579
1580 static void bgp_pbr_policyroute_remove_from_zebra_unit(
1581 struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf)
1582 {
1583 struct bgp_pbr_match temp;
1584 struct bgp_pbr_match_entry temp2;
1585 struct bgp_pbr_rule pbr_rule;
1586 struct bgp_pbr_rule *bpr;
1587 struct bgp_pbr_match *bpm;
1588 struct bgp_pbr_match_entry *bpme;
1589 struct bgp_pbr_match_entry_remain bpmer;
1590 struct bgp_pbr_range_port *src_port;
1591 struct bgp_pbr_range_port *dst_port;
1592 struct bgp_pbr_range_port *pkt_len;
1593 struct bgp_pbr_rule_remain bprr;
1594
1595 if (!bpf)
1596 return;
1597 src_port = bpf->src_port;
1598 dst_port = bpf->dst_port;
1599 pkt_len = bpf->pkt_len;
1600
1601 if (BGP_DEBUG(zebra, ZEBRA))
1602 bgp_pbr_dump_entry(bpf, false);
1603
1604 /* as we don't know information from EC
1605 * look for bpm that have the bpm
1606 * with vrf_id characteristics
1607 */
1608 memset(&temp2, 0, sizeof(temp2));
1609 memset(&temp, 0, sizeof(temp));
1610
1611 if (bpf->type == BGP_PBR_IPRULE) {
1612 memset(&pbr_rule, 0, sizeof(pbr_rule));
1613 pbr_rule.vrf_id = bpf->vrf_id;
1614 if (bpf->src) {
1615 prefix_copy(&pbr_rule.src, bpf->src);
1616 pbr_rule.flags |= MATCH_IP_SRC_SET;
1617 }
1618 if (bpf->dst) {
1619 prefix_copy(&pbr_rule.dst, bpf->dst);
1620 pbr_rule.flags |= MATCH_IP_DST_SET;
1621 }
1622 bpr = &pbr_rule;
1623 /* A previous entry may already exist
1624 * flush previous entry if necessary
1625 */
1626 bprr.bpr_to_match = bpr;
1627 bprr.bpr_found = NULL;
1628 hash_walk(bgp->pbr_rule_hash, bgp_pbr_get_same_rule, &bprr);
1629 if (bprr.bpr_found) {
1630 static struct bgp_pbr_rule *local_bpr;
1631 static struct bgp_pbr_action *local_bpa;
1632
1633 local_bpr = bprr.bpr_found;
1634 local_bpa = local_bpr->action;
1635 bgp_pbr_flush_iprule(bgp, local_bpa,
1636 local_bpr);
1637 }
1638 return;
1639 }
1640
1641 if (bpf->src) {
1642 temp.flags |= MATCH_IP_SRC_SET;
1643 prefix_copy(&temp2.src, bpf->src);
1644 } else
1645 temp2.src.family = AF_INET;
1646 if (bpf->dst) {
1647 temp.flags |= MATCH_IP_DST_SET;
1648 prefix_copy(&temp2.dst, bpf->dst);
1649 } else
1650 temp2.dst.family = AF_INET;
1651 if (src_port && (src_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
1652 if (bpf->protocol == IPPROTO_ICMP)
1653 temp.flags |= MATCH_ICMP_SET;
1654 temp.flags |= MATCH_PORT_SRC_SET;
1655 temp2.src_port_min = src_port->min_port;
1656 if (src_port->max_port) {
1657 temp.flags |= MATCH_PORT_SRC_RANGE_SET;
1658 temp2.src_port_max = src_port->max_port;
1659 }
1660 }
1661 if (dst_port && (dst_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
1662 if (bpf->protocol == IPPROTO_ICMP)
1663 temp.flags |= MATCH_ICMP_SET;
1664 temp.flags |= MATCH_PORT_DST_SET;
1665 temp2.dst_port_min = dst_port->min_port;
1666 if (dst_port->max_port) {
1667 temp.flags |= MATCH_PORT_DST_RANGE_SET;
1668 temp2.dst_port_max = dst_port->max_port;
1669 }
1670 }
1671 temp2.proto = bpf->protocol;
1672
1673 if (pkt_len) {
1674 temp.pkt_len_min = pkt_len->min_port;
1675 if (pkt_len->max_port)
1676 temp.pkt_len_max = pkt_len->max_port;
1677 } else if (bpf->pkt_len_val) {
1678 if (bpf->pkt_len_val->mask)
1679 temp.flags |= MATCH_PKT_LEN_INVERSE_SET;
1680 temp.pkt_len_min = bpf->pkt_len_val->val;
1681 }
1682 if (bpf->tcp_flags) {
1683 temp.tcp_flags = bpf->tcp_flags->val;
1684 temp.tcp_mask_flags = bpf->tcp_flags->mask;
1685 }
1686 if (bpf->dscp) {
1687 if (bpf->dscp->mask)
1688 temp.flags |= MATCH_DSCP_INVERSE_SET;
1689 else
1690 temp.flags |= MATCH_DSCP_SET;
1691 temp.dscp_value = bpf->dscp->val;
1692 }
1693 if (bpf->fragment) {
1694 if (bpf->fragment->mask)
1695 temp.flags |= MATCH_FRAGMENT_INVERSE_SET;
1696 temp.fragment = bpf->fragment->val;
1697 }
1698
1699 if (bpf->src == NULL || bpf->dst == NULL) {
1700 if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
1701 temp.type = IPSET_NET_PORT;
1702 else
1703 temp.type = IPSET_NET;
1704 } else {
1705 if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
1706 temp.type = IPSET_NET_PORT_NET;
1707 else
1708 temp.type = IPSET_NET_NET;
1709 }
1710 if (bpf->vrf_id == VRF_UNKNOWN) /* XXX case BGP destroy */
1711 temp.vrf_id = 0;
1712 else
1713 temp.vrf_id = bpf->vrf_id;
1714 bpme = &temp2;
1715 bpm = &temp;
1716 bpme->backpointer = bpm;
1717 /* right now, a previous entry may already exist
1718 * flush previous entry if necessary
1719 */
1720 bpmer.bpme_to_match = bpme;
1721 bpmer.bpme_found = NULL;
1722 hash_walk(bgp->pbr_match_hash, bgp_pbr_get_remaining_entry, &bpmer);
1723 if (bpmer.bpme_found) {
1724 static struct bgp_pbr_match *local_bpm;
1725 static struct bgp_pbr_action *local_bpa;
1726
1727 local_bpm = bpmer.bpme_found->backpointer;
1728 local_bpa = local_bpm->action;
1729 bgp_pbr_flush_entry(bgp, local_bpa,
1730 local_bpm, bpmer.bpme_found);
1731 }
1732 }
1733
1734 static uint8_t bgp_pbr_next_type_entry(uint8_t type_entry)
1735 {
1736 if (type_entry == FLOWSPEC_TCP_FLAGS)
1737 return FLOWSPEC_DSCP;
1738 if (type_entry == FLOWSPEC_DSCP)
1739 return FLOWSPEC_PKT_LEN;
1740 if (type_entry == FLOWSPEC_PKT_LEN)
1741 return FLOWSPEC_FRAGMENT;
1742 if (type_entry == FLOWSPEC_FRAGMENT)
1743 return FLOWSPEC_ICMP_TYPE;
1744 return 0;
1745 }
1746
1747 static void bgp_pbr_icmp_action(struct bgp *bgp, struct bgp_path_info *path,
1748 struct bgp_pbr_filter *bpf,
1749 struct bgp_pbr_or_filter *bpof, bool add,
1750 struct nexthop *nh, float *rate)
1751 {
1752 struct bgp_pbr_range_port srcp, dstp;
1753 struct bgp_pbr_val_mask *icmp_type, *icmp_code;
1754 struct listnode *tnode, *cnode;
1755
1756 if (!bpf)
1757 return;
1758 if (bpf->protocol != IPPROTO_ICMP)
1759 return;
1760 bpf->src_port = &srcp;
1761 bpf->dst_port = &dstp;
1762 /* parse icmp type and lookup appropriate icmp code
1763 * if no icmp code found, create as many entryes as
1764 * there are listed icmp codes for that icmp type
1765 */
1766 if (!bpof->icmp_type) {
1767 srcp.min_port = 0;
1768 srcp.max_port = 255;
1769 for (ALL_LIST_ELEMENTS_RO(bpof->icmp_code, cnode, icmp_code)) {
1770 dstp.min_port = icmp_code->val;
1771 if (add)
1772 bgp_pbr_policyroute_add_to_zebra_unit(
1773 bgp, path, bpf, nh, rate);
1774 else
1775 bgp_pbr_policyroute_remove_from_zebra_unit(
1776 bgp, path, bpf);
1777 }
1778 return;
1779 }
1780 for (ALL_LIST_ELEMENTS_RO(bpof->icmp_type, tnode, icmp_type)) {
1781 srcp.min_port = icmp_type->val;
1782 srcp.max_port = 0;
1783 dstp.max_port = 0;
1784 /* only icmp type. create an entry only with icmp type */
1785 if (!bpof->icmp_code) {
1786 /* icmp type is not one of the above
1787 * forge an entry only based on the icmp type
1788 */
1789 dstp.min_port = 0;
1790 dstp.max_port = 255;
1791 if (add)
1792 bgp_pbr_policyroute_add_to_zebra_unit(
1793 bgp, path, bpf, nh, rate);
1794 else
1795 bgp_pbr_policyroute_remove_from_zebra_unit(
1796 bgp, path, bpf);
1797 continue;
1798 }
1799 for (ALL_LIST_ELEMENTS_RO(bpof->icmp_code, cnode, icmp_code)) {
1800 dstp.min_port = icmp_code->val;
1801 if (add)
1802 bgp_pbr_policyroute_add_to_zebra_unit(
1803 bgp, path, bpf, nh, rate);
1804 else
1805 bgp_pbr_policyroute_remove_from_zebra_unit(
1806 bgp, path, bpf);
1807 }
1808 }
1809 }
1810
1811 static void bgp_pbr_policyroute_remove_from_zebra_recursive(
1812 struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf,
1813 struct bgp_pbr_or_filter *bpof, uint8_t type_entry)
1814 {
1815 struct listnode *node, *nnode;
1816 struct bgp_pbr_val_mask *valmask;
1817 uint8_t next_type_entry;
1818 struct list *orig_list;
1819 struct bgp_pbr_val_mask **target_val;
1820
1821 if (type_entry == 0) {
1822 bgp_pbr_policyroute_remove_from_zebra_unit(bgp, path, bpf);
1823 return;
1824 }
1825 next_type_entry = bgp_pbr_next_type_entry(type_entry);
1826 if (type_entry == FLOWSPEC_TCP_FLAGS && bpof->tcpflags) {
1827 orig_list = bpof->tcpflags;
1828 target_val = &bpf->tcp_flags;
1829 } else if (type_entry == FLOWSPEC_DSCP && bpof->dscp) {
1830 orig_list = bpof->dscp;
1831 target_val = &bpf->dscp;
1832 } else if (type_entry == FLOWSPEC_PKT_LEN && bpof->pkt_len) {
1833 orig_list = bpof->pkt_len;
1834 target_val = &bpf->pkt_len_val;
1835 } else if (type_entry == FLOWSPEC_FRAGMENT && bpof->fragment) {
1836 orig_list = bpof->fragment;
1837 target_val = &bpf->fragment;
1838 } else if (type_entry == FLOWSPEC_ICMP_TYPE &&
1839 (bpof->icmp_type || bpof->icmp_code)) {
1840 /* enumerate list for icmp - must be last one */
1841 bgp_pbr_icmp_action(bgp, path, bpf, bpof, false, NULL, NULL);
1842 return;
1843 } else {
1844 bgp_pbr_policyroute_remove_from_zebra_recursive(
1845 bgp, path, bpf, bpof, next_type_entry);
1846 return;
1847 }
1848 for (ALL_LIST_ELEMENTS(orig_list, node, nnode, valmask)) {
1849 *target_val = valmask;
1850 bgp_pbr_policyroute_remove_from_zebra_recursive(
1851 bgp, path, bpf, bpof, next_type_entry);
1852 }
1853 }
1854
1855 static void bgp_pbr_policyroute_remove_from_zebra(
1856 struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf,
1857 struct bgp_pbr_or_filter *bpof)
1858 {
1859 if (!bpof) {
1860 bgp_pbr_policyroute_remove_from_zebra_unit(bgp, path, bpf);
1861 return;
1862 }
1863 if (bpof->tcpflags)
1864 bgp_pbr_policyroute_remove_from_zebra_recursive(
1865 bgp, path, bpf, bpof, FLOWSPEC_TCP_FLAGS);
1866 else if (bpof->dscp)
1867 bgp_pbr_policyroute_remove_from_zebra_recursive(
1868 bgp, path, bpf, bpof, FLOWSPEC_DSCP);
1869 else if (bpof->pkt_len)
1870 bgp_pbr_policyroute_remove_from_zebra_recursive(
1871 bgp, path, bpf, bpof, FLOWSPEC_PKT_LEN);
1872 else if (bpof->fragment)
1873 bgp_pbr_policyroute_remove_from_zebra_recursive(
1874 bgp, path, bpf, bpof, FLOWSPEC_FRAGMENT);
1875 else if (bpof->icmp_type || bpof->icmp_code)
1876 bgp_pbr_policyroute_remove_from_zebra_recursive(
1877 bgp, path, bpf, bpof, FLOWSPEC_ICMP_TYPE);
1878 else
1879 bgp_pbr_policyroute_remove_from_zebra_unit(bgp, path, bpf);
1880 /* flush bpof */
1881 if (bpof->tcpflags)
1882 list_delete_all_node(bpof->tcpflags);
1883 if (bpof->dscp)
1884 list_delete_all_node(bpof->dscp);
1885 if (bpof->pkt_len)
1886 list_delete_all_node(bpof->pkt_len);
1887 if (bpof->fragment)
1888 list_delete_all_node(bpof->fragment);
1889 }
1890
1891 static void bgp_pbr_dump_entry(struct bgp_pbr_filter *bpf, bool add)
1892 {
1893 struct bgp_pbr_range_port *src_port;
1894 struct bgp_pbr_range_port *dst_port;
1895 struct bgp_pbr_range_port *pkt_len;
1896 char bufsrc[64], bufdst[64];
1897 char buffer[64];
1898 int remaining_len = 0;
1899 char protocol_str[16];
1900
1901 if (!bpf)
1902 return;
1903 src_port = bpf->src_port;
1904 dst_port = bpf->dst_port;
1905 pkt_len = bpf->pkt_len;
1906
1907 protocol_str[0] = '\0';
1908 if (bpf->tcp_flags && bpf->tcp_flags->mask)
1909 bpf->protocol = IPPROTO_TCP;
1910 if (bpf->protocol)
1911 snprintf(protocol_str, sizeof(protocol_str),
1912 "proto %d", bpf->protocol);
1913 buffer[0] = '\0';
1914 if (bpf->protocol == IPPROTO_ICMP && src_port && dst_port)
1915 remaining_len += snprintf(buffer, sizeof(buffer),
1916 "type %d, code %d",
1917 src_port->min_port,
1918 dst_port->min_port);
1919 else if (bpf->protocol == IPPROTO_UDP ||
1920 bpf->protocol == IPPROTO_TCP) {
1921
1922 if (src_port && src_port->min_port)
1923 remaining_len += snprintf(buffer,
1924 sizeof(buffer),
1925 "from [%u:%u]",
1926 src_port->min_port,
1927 src_port->max_port ?
1928 src_port->max_port :
1929 src_port->min_port);
1930 if (dst_port && dst_port->min_port)
1931 remaining_len += snprintf(buffer +
1932 remaining_len,
1933 sizeof(buffer)
1934 - remaining_len,
1935 "to [%u:%u]",
1936 dst_port->min_port,
1937 dst_port->max_port ?
1938 dst_port->max_port :
1939 dst_port->min_port);
1940 }
1941 if (pkt_len && (pkt_len->min_port || pkt_len->max_port)) {
1942 remaining_len += snprintf(buffer + remaining_len,
1943 sizeof(buffer)
1944 - remaining_len,
1945 " len [%u:%u]",
1946 pkt_len->min_port,
1947 pkt_len->max_port ?
1948 pkt_len->max_port :
1949 pkt_len->min_port);
1950 } else if (bpf->pkt_len_val) {
1951 remaining_len += snprintf(buffer + remaining_len,
1952 sizeof(buffer)
1953 - remaining_len,
1954 " %s len %u",
1955 bpf->pkt_len_val->mask
1956 ? "!" : "",
1957 bpf->pkt_len_val->val);
1958 }
1959 if (bpf->tcp_flags) {
1960 remaining_len += snprintf(buffer + remaining_len,
1961 sizeof(buffer)
1962 - remaining_len,
1963 "tcpflags %x/%x",
1964 bpf->tcp_flags->val,
1965 bpf->tcp_flags->mask);
1966 }
1967 if (bpf->dscp) {
1968 snprintf(buffer + remaining_len,
1969 sizeof(buffer)
1970 - remaining_len,
1971 "%s dscp %d",
1972 bpf->dscp->mask
1973 ? "!" : "",
1974 bpf->dscp->val);
1975 }
1976 zlog_debug("BGP: %s FS PBR from %s to %s, %s %s",
1977 add ? "adding" : "removing",
1978 bpf->src == NULL ? "<all>" :
1979 prefix2str(bpf->src, bufsrc, sizeof(bufsrc)),
1980 bpf->dst == NULL ? "<all>" :
1981 prefix2str(bpf->dst, bufdst, sizeof(bufdst)),
1982 protocol_str, buffer);
1983
1984 }
1985
1986 static void bgp_pbr_policyroute_add_to_zebra_unit(struct bgp *bgp,
1987 struct bgp_path_info *path,
1988 struct bgp_pbr_filter *bpf,
1989 struct nexthop *nh,
1990 float *rate)
1991 {
1992 struct bgp_pbr_match temp;
1993 struct bgp_pbr_match_entry temp2;
1994 struct bgp_pbr_match *bpm;
1995 struct bgp_pbr_match_entry *bpme = NULL;
1996 struct bgp_pbr_action temp3;
1997 struct bgp_pbr_action *bpa = NULL;
1998 struct bgp_pbr_match_entry_remain bpmer;
1999 struct bgp_pbr_rule_remain bprr;
2000 struct bgp_pbr_range_port *src_port;
2001 struct bgp_pbr_range_port *dst_port;
2002 struct bgp_pbr_range_port *pkt_len;
2003 struct bgp_pbr_rule pbr_rule;
2004 struct bgp_pbr_rule *bpr;
2005 bool bpr_found = false;
2006 bool bpme_found = false;
2007
2008 if (!bpf)
2009 return;
2010 src_port = bpf->src_port;
2011 dst_port = bpf->dst_port;
2012 pkt_len = bpf->pkt_len;
2013
2014 if (BGP_DEBUG(zebra, ZEBRA))
2015 bgp_pbr_dump_entry(bpf, true);
2016
2017 /* look for bpa first */
2018 memset(&temp3, 0, sizeof(temp3));
2019 if (rate)
2020 temp3.rate = *rate;
2021 if (nh)
2022 memcpy(&temp3.nh, nh, sizeof(struct nexthop));
2023 temp3.vrf_id = bpf->vrf_id;
2024 bpa = hash_get(bgp->pbr_action_hash, &temp3,
2025 bgp_pbr_action_alloc_intern);
2026
2027 if (bpa->fwmark == 0) {
2028 /* drop is handled by iptable */
2029 if (nh && nh->type == NEXTHOP_TYPE_BLACKHOLE) {
2030 bpa->table_id = 0;
2031 bpa->installed = true;
2032 } else {
2033 bpa->fwmark = bgp_zebra_tm_get_id();
2034 bpa->table_id = bpa->fwmark;
2035 bpa->installed = false;
2036 }
2037 bpa->bgp = bgp;
2038 bpa->unique = ++bgp_pbr_action_counter_unique;
2039 /* 0 value is forbidden */
2040 bpa->install_in_progress = false;
2041 }
2042 if (bpf->type == BGP_PBR_IPRULE) {
2043 memset(&pbr_rule, 0, sizeof(pbr_rule));
2044 pbr_rule.vrf_id = bpf->vrf_id;
2045 pbr_rule.priority = 20;
2046 if (bpf->src) {
2047 pbr_rule.flags |= MATCH_IP_SRC_SET;
2048 prefix_copy(&pbr_rule.src, bpf->src);
2049 }
2050 if (bpf->dst) {
2051 pbr_rule.flags |= MATCH_IP_DST_SET;
2052 prefix_copy(&pbr_rule.dst, bpf->dst);
2053 }
2054 pbr_rule.action = bpa;
2055 bpr = hash_get(bgp->pbr_rule_hash, &pbr_rule,
2056 bgp_pbr_rule_alloc_intern);
2057 if (bpr && bpr->unique == 0) {
2058 bpr->unique = ++bgp_pbr_action_counter_unique;
2059 bpr->installed = false;
2060 bpr->install_in_progress = false;
2061 /* link bgp info to bpr */
2062 bpr->path = (void *)path;
2063 } else
2064 bpr_found = true;
2065 /* already installed */
2066 if (bpr_found && bpr) {
2067 struct bgp_path_info_extra *extra =
2068 bgp_path_info_extra_get(path);
2069
2070 if (extra &&
2071 listnode_lookup_nocheck(extra->bgp_fs_iprule,
2072 bpr)) {
2073 if (BGP_DEBUG(pbr, PBR_ERROR))
2074 zlog_err("%s: entry %p/%p already "
2075 "installed in bgp pbr iprule",
2076 __func__, path, bpr);
2077 return;
2078 }
2079 }
2080 if (!bpa->installed && !bpa->install_in_progress) {
2081 bgp_send_pbr_rule_action(bpa, NULL, true);
2082 bgp_zebra_announce_default(bgp, nh,
2083 AFI_IP, bpa->table_id, true);
2084 }
2085 /* ip rule add */
2086 if (bpr && !bpr->installed)
2087 bgp_send_pbr_rule_action(bpa, bpr, true);
2088
2089 /* A previous entry may already exist
2090 * flush previous entry if necessary
2091 */
2092 bprr.bpr_to_match = bpr;
2093 bprr.bpr_found = NULL;
2094 hash_walk(bgp->pbr_rule_hash, bgp_pbr_get_same_rule, &bprr);
2095 if (bprr.bpr_found) {
2096 static struct bgp_pbr_rule *local_bpr;
2097 static struct bgp_pbr_action *local_bpa;
2098
2099 local_bpr = bprr.bpr_found;
2100 local_bpa = local_bpr->action;
2101 bgp_pbr_flush_iprule(bgp, local_bpa,
2102 local_bpr);
2103 }
2104 return;
2105 }
2106 /* then look for bpm */
2107 memset(&temp, 0, sizeof(temp));
2108 temp.vrf_id = bpf->vrf_id;
2109 if (bpf->src)
2110 temp.flags |= MATCH_IP_SRC_SET;
2111 if (bpf->dst)
2112 temp.flags |= MATCH_IP_DST_SET;
2113
2114 if (src_port && (src_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
2115 if (bpf->protocol == IPPROTO_ICMP)
2116 temp.flags |= MATCH_ICMP_SET;
2117 temp.flags |= MATCH_PORT_SRC_SET;
2118 }
2119 if (dst_port && (dst_port->min_port || bpf->protocol == IPPROTO_ICMP)) {
2120 if (bpf->protocol == IPPROTO_ICMP)
2121 temp.flags |= MATCH_ICMP_SET;
2122 temp.flags |= MATCH_PORT_DST_SET;
2123 }
2124 if (src_port && src_port->max_port)
2125 temp.flags |= MATCH_PORT_SRC_RANGE_SET;
2126 if (dst_port && dst_port->max_port)
2127 temp.flags |= MATCH_PORT_DST_RANGE_SET;
2128
2129 if (bpf->src == NULL || bpf->dst == NULL) {
2130 if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
2131 temp.type = IPSET_NET_PORT;
2132 else
2133 temp.type = IPSET_NET;
2134 } else {
2135 if (temp.flags & (MATCH_PORT_DST_SET | MATCH_PORT_SRC_SET))
2136 temp.type = IPSET_NET_PORT_NET;
2137 else
2138 temp.type = IPSET_NET_NET;
2139 }
2140 if (pkt_len) {
2141 temp.pkt_len_min = pkt_len->min_port;
2142 if (pkt_len->max_port)
2143 temp.pkt_len_max = pkt_len->max_port;
2144 } else if (bpf->pkt_len_val) {
2145 if (bpf->pkt_len_val->mask)
2146 temp.flags |= MATCH_PKT_LEN_INVERSE_SET;
2147 temp.pkt_len_min = bpf->pkt_len_val->val;
2148 }
2149 if (bpf->tcp_flags) {
2150 temp.tcp_flags = bpf->tcp_flags->val;
2151 temp.tcp_mask_flags = bpf->tcp_flags->mask;
2152 }
2153 if (bpf->dscp) {
2154 if (bpf->dscp->mask)
2155 temp.flags |= MATCH_DSCP_INVERSE_SET;
2156 else
2157 temp.flags |= MATCH_DSCP_SET;
2158 temp.dscp_value = bpf->dscp->val;
2159 }
2160 if (bpf->fragment) {
2161 if (bpf->fragment->mask)
2162 temp.flags |= MATCH_FRAGMENT_INVERSE_SET;
2163 temp.fragment = bpf->fragment->val;
2164 }
2165 temp.action = bpa;
2166 bpm = hash_get(bgp->pbr_match_hash, &temp,
2167 bgp_pbr_match_alloc_intern);
2168
2169 /* new, then self allocate ipset_name and unique */
2170 if (bpm->unique == 0) {
2171 bpm->unique = ++bgp_pbr_match_counter_unique;
2172 /* 0 value is forbidden */
2173 sprintf(bpm->ipset_name, "match%p", bpm);
2174 bpm->entry_hash = hash_create_size(8,
2175 bgp_pbr_match_entry_hash_key,
2176 bgp_pbr_match_entry_hash_equal,
2177 "Match Entry Hash");
2178 bpm->installed = false;
2179
2180 /* unique2 should be updated too */
2181 bpm->unique2 = ++bgp_pbr_match_iptable_counter_unique;
2182 bpm->installed_in_iptable = false;
2183 bpm->install_in_progress = false;
2184 bpm->install_iptable_in_progress = false;
2185 }
2186
2187 memset(&temp2, 0, sizeof(temp2));
2188 if (bpf->src)
2189 prefix_copy(&temp2.src, bpf->src);
2190 else
2191 temp2.src.family = AF_INET;
2192 if (bpf->dst)
2193 prefix_copy(&temp2.dst, bpf->dst);
2194 else
2195 temp2.dst.family = AF_INET;
2196 temp2.src_port_min = src_port ? src_port->min_port : 0;
2197 temp2.dst_port_min = dst_port ? dst_port->min_port : 0;
2198 temp2.src_port_max = src_port ? src_port->max_port : 0;
2199 temp2.dst_port_max = dst_port ? dst_port->max_port : 0;
2200 temp2.proto = bpf->protocol;
2201 bpme = hash_get(bpm->entry_hash, &temp2,
2202 bgp_pbr_match_entry_alloc_intern);
2203 if (bpme->unique == 0) {
2204 bpme->unique = ++bgp_pbr_match_entry_counter_unique;
2205 /* 0 value is forbidden */
2206 bpme->backpointer = bpm;
2207 bpme->installed = false;
2208 bpme->install_in_progress = false;
2209 /* link bgp info to bpme */
2210 bpme->path = (void *)path;
2211 } else
2212 bpme_found = true;
2213
2214 /* already installed */
2215 if (bpme_found) {
2216 struct bgp_path_info_extra *extra =
2217 bgp_path_info_extra_get(path);
2218
2219 if (extra &&
2220 listnode_lookup_nocheck(extra->bgp_fs_pbr, bpme)) {
2221 if (BGP_DEBUG(pbr, PBR_ERROR))
2222 zlog_err(
2223 "%s: entry %p/%p already installed in bgp pbr",
2224 __func__, path, bpme);
2225 return;
2226 }
2227 }
2228 /* BGP FS: append entry to zebra
2229 * - policies are not routing entries and as such
2230 * route replace semantics don't necessarily follow
2231 * through to policy entries
2232 * - because of that, not all policing information will be stored
2233 * into zebra. and non selected policies will be suppressed from zebra
2234 * - as consequence, in order to bring consistency
2235 * a policy will be added, then ifan ecmp policy exists,
2236 * it will be suppressed subsequently
2237 */
2238 /* ip rule add */
2239 if (!bpa->installed && !bpa->install_in_progress) {
2240 bgp_send_pbr_rule_action(bpa, NULL, true);
2241 bgp_zebra_announce_default(bgp, nh,
2242 AFI_IP, bpa->table_id, true);
2243 }
2244
2245 /* ipset create */
2246 if (!bpm->installed)
2247 bgp_send_pbr_ipset_match(bpm, true);
2248 /* ipset add */
2249 if (!bpme->installed)
2250 bgp_send_pbr_ipset_entry_match(bpme, true);
2251
2252 /* iptables */
2253 if (!bpm->installed_in_iptable)
2254 bgp_send_pbr_iptable(bpa, bpm, true);
2255
2256 /* A previous entry may already exist
2257 * flush previous entry if necessary
2258 */
2259 bpmer.bpme_to_match = bpme;
2260 bpmer.bpme_found = NULL;
2261 hash_walk(bgp->pbr_match_hash, bgp_pbr_get_remaining_entry, &bpmer);
2262 if (bpmer.bpme_found) {
2263 static struct bgp_pbr_match *local_bpm;
2264 static struct bgp_pbr_action *local_bpa;
2265
2266 local_bpm = bpmer.bpme_found->backpointer;
2267 local_bpa = local_bpm->action;
2268 bgp_pbr_flush_entry(bgp, local_bpa,
2269 local_bpm, bpmer.bpme_found);
2270 }
2271
2272
2273 }
2274
2275 static void bgp_pbr_policyroute_add_to_zebra_recursive(
2276 struct bgp *bgp, struct bgp_path_info *path, struct bgp_pbr_filter *bpf,
2277 struct bgp_pbr_or_filter *bpof, struct nexthop *nh, float *rate,
2278 uint8_t type_entry)
2279 {
2280 struct listnode *node, *nnode;
2281 struct bgp_pbr_val_mask *valmask;
2282 uint8_t next_type_entry;
2283 struct list *orig_list;
2284 struct bgp_pbr_val_mask **target_val;
2285
2286 if (type_entry == 0) {
2287 bgp_pbr_policyroute_add_to_zebra_unit(bgp, path, bpf, nh, rate);
2288 return;
2289 }
2290 next_type_entry = bgp_pbr_next_type_entry(type_entry);
2291 if (type_entry == FLOWSPEC_TCP_FLAGS && bpof->tcpflags) {
2292 orig_list = bpof->tcpflags;
2293 target_val = &bpf->tcp_flags;
2294 } else if (type_entry == FLOWSPEC_DSCP && bpof->dscp) {
2295 orig_list = bpof->dscp;
2296 target_val = &bpf->dscp;
2297 } else if (type_entry == FLOWSPEC_PKT_LEN && bpof->pkt_len) {
2298 orig_list = bpof->pkt_len;
2299 target_val = &bpf->pkt_len_val;
2300 } else if (type_entry == FLOWSPEC_FRAGMENT && bpof->fragment) {
2301 orig_list = bpof->fragment;
2302 target_val = &bpf->fragment;
2303 } else if (type_entry == FLOWSPEC_ICMP_TYPE &&
2304 (bpof->icmp_type || bpof->icmp_code)) {
2305 /* enumerate list for icmp - must be last one */
2306 bgp_pbr_icmp_action(bgp, path, bpf, bpof, true, nh, rate);
2307 return;
2308 } else {
2309 bgp_pbr_policyroute_add_to_zebra_recursive(
2310 bgp, path, bpf, bpof, nh, rate, next_type_entry);
2311 return;
2312 }
2313 for (ALL_LIST_ELEMENTS(orig_list, node, nnode, valmask)) {
2314 *target_val = valmask;
2315 bgp_pbr_policyroute_add_to_zebra_recursive(
2316 bgp, path, bpf, bpof, nh, rate, next_type_entry);
2317 }
2318 }
2319
2320 static void bgp_pbr_policyroute_add_to_zebra(struct bgp *bgp,
2321 struct bgp_path_info *path,
2322 struct bgp_pbr_filter *bpf,
2323 struct bgp_pbr_or_filter *bpof,
2324 struct nexthop *nh, float *rate)
2325 {
2326 if (!bpof) {
2327 bgp_pbr_policyroute_add_to_zebra_unit(bgp, path, bpf, nh, rate);
2328 return;
2329 }
2330 if (bpof->tcpflags)
2331 bgp_pbr_policyroute_add_to_zebra_recursive(
2332 bgp, path, bpf, bpof, nh, rate, FLOWSPEC_TCP_FLAGS);
2333 else if (bpof->dscp)
2334 bgp_pbr_policyroute_add_to_zebra_recursive(
2335 bgp, path, bpf, bpof, nh, rate, FLOWSPEC_DSCP);
2336 else if (bpof->pkt_len)
2337 bgp_pbr_policyroute_add_to_zebra_recursive(
2338 bgp, path, bpf, bpof, nh, rate, FLOWSPEC_PKT_LEN);
2339 else if (bpof->fragment)
2340 bgp_pbr_policyroute_add_to_zebra_recursive(
2341 bgp, path, bpf, bpof, nh, rate, FLOWSPEC_FRAGMENT);
2342 else if (bpof->icmp_type || bpof->icmp_code)
2343 bgp_pbr_policyroute_add_to_zebra_recursive(
2344 bgp, path, bpf, bpof, nh, rate, FLOWSPEC_ICMP_TYPE);
2345 else
2346 bgp_pbr_policyroute_add_to_zebra_unit(bgp, path, bpf, nh, rate);
2347 /* flush bpof */
2348 if (bpof->tcpflags)
2349 list_delete_all_node(bpof->tcpflags);
2350 if (bpof->dscp)
2351 list_delete_all_node(bpof->dscp);
2352 if (bpof->pkt_len)
2353 list_delete_all_node(bpof->pkt_len);
2354 if (bpof->fragment)
2355 list_delete_all_node(bpof->fragment);
2356 if (bpof->icmp_type)
2357 list_delete_all_node(bpof->icmp_type);
2358 if (bpof->icmp_code)
2359 list_delete_all_node(bpof->icmp_code);
2360 }
2361
2362 static void bgp_pbr_handle_entry(struct bgp *bgp, struct bgp_path_info *path,
2363 struct bgp_pbr_entry_main *api, bool add)
2364 {
2365 struct nexthop nh;
2366 int i = 0;
2367 int continue_loop = 1;
2368 float rate = 0;
2369 struct prefix *src = NULL, *dst = NULL;
2370 uint8_t proto = 0;
2371 struct bgp_pbr_range_port *srcp = NULL, *dstp = NULL;
2372 struct bgp_pbr_range_port range, range_icmp_code;
2373 struct bgp_pbr_range_port pkt_len;
2374 struct bgp_pbr_filter bpf;
2375 uint8_t kind_enum;
2376 struct bgp_pbr_or_filter bpof;
2377 struct bgp_pbr_val_mask bpvm;
2378
2379 memset(&nh, 0, sizeof(struct nexthop));
2380 memset(&bpf, 0, sizeof(struct bgp_pbr_filter));
2381 memset(&bpof, 0, sizeof(struct bgp_pbr_or_filter));
2382 if (api->match_bitmask & PREFIX_SRC_PRESENT ||
2383 (api->type == BGP_PBR_IPRULE &&
2384 api->match_bitmask_iprule & PREFIX_SRC_PRESENT))
2385 src = &api->src_prefix;
2386 if (api->match_bitmask & PREFIX_DST_PRESENT ||
2387 (api->type == BGP_PBR_IPRULE &&
2388 api->match_bitmask_iprule & PREFIX_DST_PRESENT))
2389 dst = &api->dst_prefix;
2390 if (api->type == BGP_PBR_IPRULE)
2391 bpf.type = api->type;
2392 memset(&nh, 0, sizeof(struct nexthop));
2393 nh.vrf_id = VRF_UNKNOWN;
2394 if (api->match_protocol_num)
2395 proto = (uint8_t)api->protocol[0].value;
2396 /* if match_port is selected, then either src or dst port will be parsed
2397 * but not both at the same time
2398 */
2399 if (api->match_port_num >= 1) {
2400 bgp_pbr_extract(api->port,
2401 api->match_port_num,
2402 &range);
2403 srcp = dstp = &range;
2404 } else if (api->match_src_port_num >= 1) {
2405 bgp_pbr_extract(api->src_port,
2406 api->match_src_port_num,
2407 &range);
2408 srcp = &range;
2409 dstp = NULL;
2410 } else if (api->match_dst_port_num >= 1) {
2411 bgp_pbr_extract(api->dst_port,
2412 api->match_dst_port_num,
2413 &range);
2414 dstp = &range;
2415 srcp = NULL;
2416 }
2417 if (api->match_icmp_type_num >= 1) {
2418 proto = IPPROTO_ICMP;
2419 if (bgp_pbr_extract(api->icmp_type,
2420 api->match_icmp_type_num,
2421 &range))
2422 srcp = &range;
2423 else {
2424 bpof.icmp_type = list_new();
2425 bgp_pbr_extract_enumerate(api->icmp_type,
2426 api->match_icmp_type_num,
2427 OPERATOR_UNARY_OR,
2428 bpof.icmp_type,
2429 FLOWSPEC_ICMP_TYPE);
2430 }
2431 }
2432 if (api->match_icmp_code_num >= 1) {
2433 proto = IPPROTO_ICMP;
2434 if (bgp_pbr_extract(api->icmp_code,
2435 api->match_icmp_code_num,
2436 &range_icmp_code))
2437 dstp = &range_icmp_code;
2438 else {
2439 bpof.icmp_code = list_new();
2440 bgp_pbr_extract_enumerate(api->icmp_code,
2441 api->match_icmp_code_num,
2442 OPERATOR_UNARY_OR,
2443 bpof.icmp_code,
2444 FLOWSPEC_ICMP_CODE);
2445 }
2446 }
2447
2448 if (api->match_tcpflags_num) {
2449 kind_enum = bgp_pbr_match_val_get_operator(api->tcpflags,
2450 api->match_tcpflags_num);
2451 if (kind_enum == OPERATOR_UNARY_AND) {
2452 bpf.tcp_flags = &bpvm;
2453 bgp_pbr_extract_enumerate(api->tcpflags,
2454 api->match_tcpflags_num,
2455 OPERATOR_UNARY_AND,
2456 bpf.tcp_flags,
2457 FLOWSPEC_TCP_FLAGS);
2458 } else if (kind_enum == OPERATOR_UNARY_OR) {
2459 bpof.tcpflags = list_new();
2460 bgp_pbr_extract_enumerate(api->tcpflags,
2461 api->match_tcpflags_num,
2462 OPERATOR_UNARY_OR,
2463 bpof.tcpflags,
2464 FLOWSPEC_TCP_FLAGS);
2465 }
2466 }
2467 if (api->match_packet_length_num) {
2468 bool ret;
2469
2470 ret = bgp_pbr_extract(api->packet_length,
2471 api->match_packet_length_num,
2472 &pkt_len);
2473 if (ret)
2474 bpf.pkt_len = &pkt_len;
2475 else {
2476 bpof.pkt_len = list_new();
2477 bgp_pbr_extract_enumerate(api->packet_length,
2478 api->match_packet_length_num,
2479 OPERATOR_UNARY_OR,
2480 bpof.pkt_len,
2481 FLOWSPEC_PKT_LEN);
2482 }
2483 }
2484 if (api->match_dscp_num >= 1) {
2485 bpof.dscp = list_new();
2486 bgp_pbr_extract_enumerate(api->dscp, api->match_dscp_num,
2487 OPERATOR_UNARY_OR,
2488 bpof.dscp, FLOWSPEC_DSCP);
2489 }
2490 if (api->match_fragment_num) {
2491 bpof.fragment = list_new();
2492 bgp_pbr_extract_enumerate(api->fragment,
2493 api->match_fragment_num,
2494 OPERATOR_UNARY_OR,
2495 bpof.fragment,
2496 FLOWSPEC_FRAGMENT);
2497 }
2498 bpf.vrf_id = api->vrf_id;
2499 bpf.src = src;
2500 bpf.dst = dst;
2501 bpf.protocol = proto;
2502 bpf.src_port = srcp;
2503 bpf.dst_port = dstp;
2504 if (!add) {
2505 bgp_pbr_policyroute_remove_from_zebra(bgp, path, &bpf, &bpof);
2506 return;
2507 }
2508 /* no action for add = true */
2509 for (i = 0; i < api->action_num; i++) {
2510 switch (api->actions[i].action) {
2511 case ACTION_TRAFFICRATE:
2512 /* drop packet */
2513 if (api->actions[i].u.r.rate == 0) {
2514 nh.vrf_id = api->vrf_id;
2515 nh.type = NEXTHOP_TYPE_BLACKHOLE;
2516 bgp_pbr_policyroute_add_to_zebra(
2517 bgp, path, &bpf, &bpof, &nh, &rate);
2518 } else {
2519 /* update rate. can be reentrant */
2520 rate = api->actions[i].u.r.rate;
2521 if (BGP_DEBUG(pbr, PBR)) {
2522 bgp_pbr_print_policy_route(api);
2523 zlog_warn("PBR: ignoring Set action rate %f",
2524 api->actions[i].u.r.rate);
2525 }
2526 }
2527 break;
2528 case ACTION_TRAFFIC_ACTION:
2529 if (api->actions[i].u.za.filter
2530 & TRAFFIC_ACTION_SAMPLE) {
2531 if (BGP_DEBUG(pbr, PBR)) {
2532 bgp_pbr_print_policy_route(api);
2533 zlog_warn("PBR: Sample action Ignored");
2534 }
2535 }
2536 #if 0
2537 if (api->actions[i].u.za.filter
2538 & TRAFFIC_ACTION_DISTRIBUTE) {
2539 if (BGP_DEBUG(pbr, PBR)) {
2540 bgp_pbr_print_policy_route(api);
2541 zlog_warn("PBR: Distribute action Applies");
2542 }
2543 continue_loop = 0;
2544 /* continue forwarding entry as before
2545 * no action
2546 */
2547 }
2548 #endif /* XXX to confirm behaviour of traffic action. for now , ignore */
2549 /* terminate action: run other filters
2550 */
2551 break;
2552 case ACTION_REDIRECT_IP:
2553 nh.type = NEXTHOP_TYPE_IPV4;
2554 nh.gate.ipv4.s_addr =
2555 api->actions[i].u.zr.redirect_ip_v4.s_addr;
2556 nh.vrf_id = api->vrf_id;
2557 bgp_pbr_policyroute_add_to_zebra(bgp, path, &bpf, &bpof,
2558 &nh, &rate);
2559 /* XXX combination with REDIRECT_VRF
2560 * + REDIRECT_NH_IP not done
2561 */
2562 continue_loop = 0;
2563 break;
2564 case ACTION_REDIRECT:
2565 nh.vrf_id = api->actions[i].u.redirect_vrf;
2566 nh.type = NEXTHOP_TYPE_IPV4;
2567 bgp_pbr_policyroute_add_to_zebra(bgp, path, &bpf, &bpof,
2568 &nh, &rate);
2569 continue_loop = 0;
2570 break;
2571 case ACTION_MARKING:
2572 if (BGP_DEBUG(pbr, PBR)) {
2573 bgp_pbr_print_policy_route(api);
2574 zlog_warn("PBR: Set DSCP %u Ignored",
2575 api->actions[i].u.marking_dscp);
2576 }
2577 break;
2578 default:
2579 break;
2580 }
2581 if (continue_loop == 0)
2582 break;
2583 }
2584 }
2585
2586 void bgp_pbr_update_entry(struct bgp *bgp, struct prefix *p,
2587 struct bgp_path_info *info, afi_t afi, safi_t safi,
2588 bool nlri_update)
2589 {
2590 struct bgp_pbr_entry_main api;
2591
2592 if (afi == AFI_IP6)
2593 return; /* IPv6 not supported */
2594 if (safi != SAFI_FLOWSPEC)
2595 return; /* not supported */
2596 /* Make Zebra API structure. */
2597 memset(&api, 0, sizeof(api));
2598 api.vrf_id = bgp->vrf_id;
2599 api.afi = afi;
2600
2601 if (!bgp_zebra_tm_chunk_obtained()) {
2602 if (BGP_DEBUG(pbr, PBR_ERROR))
2603 flog_err(EC_BGP_TABLE_CHUNK,
2604 "%s: table chunk not obtained yet", __func__);
2605 return;
2606 }
2607
2608 if (bgp_pbr_build_and_validate_entry(p, info, &api) < 0) {
2609 if (BGP_DEBUG(pbr, PBR_ERROR))
2610 flog_err(EC_BGP_FLOWSPEC_INSTALLATION,
2611 "%s: cancel updating entry %p in bgp pbr",
2612 __func__, info);
2613 return;
2614 }
2615 bgp_pbr_handle_entry(bgp, info, &api, nlri_update);
2616 }
2617
2618 int bgp_pbr_interface_compare(const struct bgp_pbr_interface *a,
2619 const struct bgp_pbr_interface *b)
2620 {
2621 return strcmp(a->name, b->name);
2622 }
2623
2624 struct bgp_pbr_interface *bgp_pbr_interface_lookup(const char *name,
2625 struct bgp_pbr_interface_head *head)
2626 {
2627 struct bgp_pbr_interface pbr_if;
2628
2629 strlcpy(pbr_if.name, name, sizeof(pbr_if.name));
2630 return (RB_FIND(bgp_pbr_interface_head,
2631 head, &pbr_if));
2632 }
2633
2634 /* this function resets to the default policy routing
2635 * go back to default status
2636 */
2637 void bgp_pbr_reset(struct bgp *bgp, afi_t afi)
2638 {
2639 struct bgp_pbr_config *bgp_pbr_cfg = bgp->bgp_pbr_cfg;
2640 struct bgp_pbr_interface_head *head;
2641 struct bgp_pbr_interface *pbr_if;
2642
2643 if (!bgp_pbr_cfg || afi != AFI_IP)
2644 return;
2645 head = &(bgp_pbr_cfg->ifaces_by_name_ipv4);
2646
2647 while (!RB_EMPTY(bgp_pbr_interface_head, head)) {
2648 pbr_if = RB_ROOT(bgp_pbr_interface_head, head);
2649 RB_REMOVE(bgp_pbr_interface_head, head, pbr_if);
2650 XFREE(MTYPE_TMP, pbr_if);
2651 }
2652 }