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