Commits
paul authored 3bf1c917d10
627 627 | /* Execute event hook. */ |
628 628 | if (route_map_master.event_hook) |
629 629 | (*route_map_master.event_hook) (RMAP_EVENT_SET_DELETED, |
630 630 | index->map->name); |
631 631 | return 0; |
632 632 | } |
633 633 | /* Can't find matched rule. */ |
634 634 | return 1; |
635 635 | } |
636 636 | |
637 - | /* Apply route map's each index to the object. */ |
638 - | /* |
639 - | ** The matrix for a route-map looks like this: |
640 - | ** (note, this includes the description for the "NEXT" |
641 - | ** and "GOTO" frobs now |
642 - | ** |
643 - | ** Match | No Match |
644 - | ** | |
645 - | ** permit a | c |
646 - | ** | |
647 - | ** ------------------+--------------- |
648 - | ** | |
649 - | ** deny b | d |
650 - | ** | |
651 - | ** |
652 - | ** a) Apply Set statements, accept route |
653 - | ** If NEXT is specified, goto NEXT statement |
654 - | ** If GOTO is specified, goto the first clause where pref > nextpref |
655 - | ** If nothing is specified, do as Cisco and finish |
656 - | ** b) Finish route-map processing, and deny route |
657 - | ** c) & d) Goto Next index |
658 - | ** |
659 - | ** If we get no matches after we've processed all updates, then the route |
660 - | ** is dropped too. |
661 - | ** |
662 - | ** Some notes on the new "NEXT" and "GOTO" |
663 - | ** on-match next - If this clause is matched, then the set statements |
664 - | ** are executed and then we drop through to the next clause |
665 - | ** on-match goto n - If this clause is matched, then the set statments |
666 - | ** are executed and then we goto the nth clause, or the |
667 - | ** first clause greater than this. In order to ensure |
668 - | ** route-maps *always* exit, you cannot jump backwards. |
669 - | ** Sorry ;) |
670 - | ** |
671 - | ** We need to make sure our route-map processing matches the above |
637 + | /* Apply route map's each index to the object. |
638 + | |
639 + | The matrix for a route-map looks like this: |
640 + | (note, this includes the description for the "NEXT" |
641 + | and "GOTO" frobs now |
642 + | |
643 + | Match | No Match |
644 + | | |
645 + | permit action | cont |
646 + | | |
647 + | ------------------+--------------- |
648 + | | |
649 + | deny deny | cont |
650 + | | |
651 + | |
652 + | action) Apply Set statements, accept route |
653 + | If NEXT is specified, goto NEXT statement |
654 + | If GOTO is specified, goto the first clause where pref > nextpref |
655 + | If nothing is specified, do as Cisco and finish |
656 + | deny) If NEXT is specified, goto NEXT statement |
657 + | If nothing is specified, finally will be denied by route-map. |
658 + | cont) Goto Next index |
659 + | |
660 + | If we get no matches after we've processed all updates, then the route |
661 + | is dropped too. |
662 + | |
663 + | Some notes on the new "NEXT" and "GOTO" |
664 + | on-match next - If this clause is matched, then the set statements |
665 + | are executed and then we drop through to the next clause |
666 + | on-match goto n - If this clause is matched, then the set statments |
667 + | are executed and then we goto the nth clause, or the |
668 + | first clause greater than this. In order to ensure |
669 + | route-maps *always* exit, you cannot jump backwards. |
670 + | Sorry ;) |
671 + | |
672 + | We need to make sure our route-map processing matches the above |
672 673 | */ |
674 + | |
673 675 | route_map_result_t |
674 - | route_map_apply_index (struct route_map_index *index, struct prefix *prefix, |
675 - | route_map_object_t type, void *object) |
676 + | route_map_apply_match (struct route_map_rule_list *match_list, |
677 + | struct prefix *prefix, route_map_object_t type, |
678 + | void *object) |
676 679 | { |
677 - | int ret; |
680 + | route_map_result_t ret = RMAP_NOMATCH; |
678 681 | struct route_map_rule *match; |
679 - | struct route_map_rule *set; |
680 - | |
681 - | /* Check all match rule and if there is no match rule return 0. */ |
682 - | for (match = index->match_list.head; match; match = match->next) |
683 - | { |
684 - | /* Try each match statement in turn. If any return something |
685 - | other than RM_MATCH then we don't need to check anymore and can |
686 - | return */ |
687 - | ret = (*match->cmd->func_apply)(match->value, prefix, type, object); |
688 - | if (ret != RMAP_MATCH) |
689 - | return ret; |
690 - | } |
691 682 | |
692 - | /* We get here if all match statements matched From the matrix |
693 - | above, if this is PERMIT we go on and apply the SET functions. If |
694 - | we're deny, we return indicating we matched a deny */ |
695 683 | |
696 - | /* Apply set statement to the object. */ |
697 - | if (index->type == RMAP_PERMIT) |
698 - | { |
699 - | for (set = index->set_list.head; set; set = set->next) |
700 - | { |
701 - | ret = (*set->cmd->func_apply)(set->value, prefix, type, object); |
702 - | } |
703 - | return RMAP_MATCH; |
704 - | } |
705 - | else |
684 + | /* Check all match rule and if there is no match rule, go to the |
685 + | set statement. */ |
686 + | if (!match_list->head) |
687 + | ret = RMAP_MATCH; |
688 + | else |
706 689 | { |
707 - | return RMAP_DENYMATCH; |
690 + | for (match = match_list->head; match; match = match->next) |
691 + | { |
692 + | /* Try each match statement in turn, If any do not return |
693 + | RMAP_MATCH, return, otherwise continue on to next match |
694 + | statement. All match statements must match for end-result |
695 + | to be a match. */ |
696 + | ret = (*match->cmd->func_apply) (match->value, prefix, |
697 + | type, object); |
698 + | if (ret != RMAP_MATCH) |
699 + | return ret; |
700 + | } |
708 701 | } |
709 - | /* Should not get here! */ |
710 - | return RMAP_MATCH; |
702 + | return ret; |
711 703 | } |
712 704 | |
713 705 | /* Apply route map to the object. */ |
714 706 | route_map_result_t |
715 - | route_map_apply (struct route_map *map, struct prefix *prefix, |
716 - | route_map_object_t type, void *object) |
707 + | route_map_apply (struct route_map *map, struct prefix *prefix, |
708 + | route_map_object_t type, void *object) |
717 709 | { |
718 710 | int ret = 0; |
719 711 | struct route_map_index *index; |
712 + | struct route_map_rule *set; |
720 713 | |
721 714 | if (map == NULL) |
722 715 | return RMAP_DENYMATCH; |
723 716 | |
724 717 | for (index = map->head; index; index = index->next) |
725 718 | { |
726 - | /* Apply this index. End here if we get a RM_NOMATCH */ |
727 - | ret = route_map_apply_index (index, prefix, type, object); |
728 - | |
729 - | if (ret != RMAP_NOMATCH) |
730 - | { |
731 - | /* We now have to handle the NEXT and GOTO clauses */ |
732 - | if(index->exitpolicy == RMAP_EXIT) |
733 - | return ret; |
734 - | if(index->exitpolicy == RMAP_GOTO) |
735 - | { |
736 - | /* Find the next clause to jump to */ |
737 - | struct route_map_index *next; |
738 - | |
739 - | next = index->next; |
740 - | while (next && next->pref < index->nextpref) |
741 - | { |
742 - | index = next; |
743 - | next = next->next; |
744 - | } |
745 - | if (next == NULL) |
746 - | { |
747 - | /* No clauses match! */ |
748 - | return ret; |
749 - | } |
750 - | } |
751 - | /* Otherwise, we fall through as it was a NEXT */ |
752 - | } |
719 + | /* Apply this index. */ |
720 + | ret = route_map_apply_match (&index->match_list, prefix, type, object); |
721 + | |
722 + | /* Now we apply the matrix from above */ |
723 + | if (ret == RMAP_NOMATCH) |
724 + | /* 'cont' from matrix - continue to next route-map sequence */ |
725 + | continue; |
726 + | else if (ret == RMAP_MATCH) |
727 + | { |
728 + | if (index->type == RMAP_PERMIT) |
729 + | /* 'action' */ |
730 + | { |
731 + | /* permit+match must execute sets */ |
732 + | for (set = index->set_list.head; set; set = set->next) |
733 + | ret = (*set->cmd->func_apply) (set->value, prefix, |
734 + | type, object); |
735 + | switch (index->exitpolicy) |
736 + | { |
737 + | case RMAP_EXIT: |
738 + | return ret; |
739 + | case RMAP_NEXT: |
740 + | continue; |
741 + | case RMAP_GOTO: |
742 + | { |
743 + | /* Find the next clause to jump to */ |
744 + | struct route_map_index *next = index->next; |
745 + | |
746 + | while (next && next->pref < index->nextpref) |
747 + | { |
748 + | index = next; |
749 + | next = next->next; |
750 + | } |
751 + | if (next == NULL) |
752 + | { |
753 + | /* No clauses match! */ |
754 + | return ret; |
755 + | } |
756 + | } |
757 + | } |
758 + | } |
759 + | else if (index->type == RMAP_DENY) |
760 + | /* 'deny' */ |
761 + | { |
762 + | if (index->exitpolicy == RMAP_NEXT) |
763 + | continue; |
764 + | else |
765 + | return RMAP_DENYMATCH; |
766 + | } |
767 + | } |
753 768 | } |
754 769 | /* Finally route-map does not match at all. */ |
755 770 | return RMAP_DENYMATCH; |
756 771 | } |
757 772 | |
758 773 | void |
759 774 | route_map_add_hook (void (*func) (char *)) |
760 775 | { |
761 776 | route_map_master.add_hook = func; |
762 777 | } |