func modAction(name, op string, args []string) error { stmt := config.Statement{ Name: name, } usage := fmt.Sprintf("usage: gobgp policy statement %s %s action", name, op) if len(args) < 1 { return fmt.Errorf("%s { reject | accept | community | ext-community | large-community | med | local-pref | as-prepend | next-hop }", usage) } typ := args[0] args = args[1:] switch typ { case "reject": stmt.Actions.RouteDisposition = config.ROUTE_DISPOSITION_REJECT_ROUTE case "accept": stmt.Actions.RouteDisposition = config.ROUTE_DISPOSITION_ACCEPT_ROUTE case "community": if len(args) < 1 { return fmt.Errorf("%s community { add | remove | replace } <value>...", usage) } stmt.Actions.BgpActions.SetCommunity.SetCommunityMethod.CommunitiesList = args[1:] switch strings.ToLower(args[0]) { case "add": stmt.Actions.BgpActions.SetCommunity.Options = string(config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD) case "remove": stmt.Actions.BgpActions.SetCommunity.Options = string(config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE) case "replace": stmt.Actions.BgpActions.SetCommunity.Options = string(config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE) default: return fmt.Errorf("%s community { add | remove | replace } <value>...", usage) } case "ext-community": if len(args) < 1 { return fmt.Errorf("%s ext-community { add | remove | replace } <value>...", usage) } stmt.Actions.BgpActions.SetExtCommunity.SetExtCommunityMethod.CommunitiesList = args[1:] switch strings.ToLower(args[0]) { case "add": stmt.Actions.BgpActions.SetExtCommunity.Options = string(config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD) case "remove": stmt.Actions.BgpActions.SetExtCommunity.Options = string(config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE) case "replace": stmt.Actions.BgpActions.SetExtCommunity.Options = string(config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE) default: return fmt.Errorf("%s ext-community { add | remove | replace } <value>...", usage) } case "large-community": if len(args) < 1 { return fmt.Errorf("%s large-community { add | remove | replace } <value>...", usage) } stmt.Actions.BgpActions.SetLargeCommunity.SetLargeCommunityMethod.CommunitiesList = args[1:] switch strings.ToLower(args[0]) { case "add": stmt.Actions.BgpActions.SetLargeCommunity.Options = config.BGP_SET_COMMUNITY_OPTION_TYPE_ADD case "remove": stmt.Actions.BgpActions.SetLargeCommunity.Options = config.BGP_SET_COMMUNITY_OPTION_TYPE_REMOVE case "replace": stmt.Actions.BgpActions.SetLargeCommunity.Options = config.BGP_SET_COMMUNITY_OPTION_TYPE_REPLACE default: return fmt.Errorf("%s large-community { add | remove | replace } <value>...", usage) } case "med": if len(args) < 2 { return fmt.Errorf("%s med { add | sub | set } <value>", usage) } med, err := strconv.Atoi(args[1]) if err != nil { return err } switch strings.ToLower(args[0]) { case "add": stmt.Actions.BgpActions.SetMed = config.BgpSetMedType(fmt.Sprintf("+%d", med)) case "sub": stmt.Actions.BgpActions.SetMed = config.BgpSetMedType(fmt.Sprintf("-%d", med)) case "set": stmt.Actions.BgpActions.SetMed = config.BgpSetMedType(fmt.Sprintf("%d", med)) default: return fmt.Errorf("%s med { add | sub | set } <value>", usage) } case "local-pref": if len(args) < 1 { return fmt.Errorf("%s local-pref <value>", usage) } value, err := strconv.ParseUint(args[0], 10, 32) if err != nil { return err } stmt.Actions.BgpActions.SetLocalPref = uint32(value) case "as-prepend": if len(args) < 2 { return fmt.Errorf("%s as-prepend { <asn> | last-as } <repeat-value>", usage) } stmt.Actions.BgpActions.SetAsPathPrepend.As = args[0] repeat, err := strconv.Atoi(args[1]) if err != nil { return err } stmt.Actions.BgpActions.SetAsPathPrepend.RepeatN = uint8(repeat) case "next-hop": if len(args) != 1 { return fmt.Errorf("%s next-hop { <value> | self }", usage) } stmt.Actions.BgpActions.SetNextHop = config.BgpNextHopType(args[0]) } t, err := table.NewStatement(stmt) switch op { case CMD_ADD: err = client.AddStatement(t) case CMD_DEL: err = client.DeleteStatement(t, false) case CMD_SET: err = client.ReplaceStatement(t) default: return fmt.Errorf("invalid operation: %s", op) } return err }
func modCondition(name, op string, args []string) error { stmt := config.Statement{ Name: name, } usage := fmt.Sprintf("usage: gobgp policy statement %s %s condition", name, op) if len(args) < 1 { return fmt.Errorf("%s { prefix | neighbor | as-path | community | ext-community | large-community | as-path-length | rpki | route-type }", usage) } typ := args[0] args = args[1:] switch typ { case "prefix": if len(args) < 1 { return fmt.Errorf("%s prefix <set-name> [{ any | invert }]", usage) } stmt.Conditions.MatchPrefixSet.PrefixSet = args[0] if len(args) == 1 { break } switch strings.ToLower(args[1]) { case "any": stmt.Conditions.MatchPrefixSet.MatchSetOptions = config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY case "invert": stmt.Conditions.MatchPrefixSet.MatchSetOptions = config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT default: return fmt.Errorf("%s prefix <set-name> [{ any | invert }]", usage) } case "neighbor": if len(args) < 1 { return fmt.Errorf("%s neighbor <set-name> [{ any | invert }]", usage) } stmt.Conditions.MatchNeighborSet.NeighborSet = args[0] if len(args) == 1 { break } switch strings.ToLower(args[1]) { case "any": stmt.Conditions.MatchNeighborSet.MatchSetOptions = config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_ANY case "invert": stmt.Conditions.MatchNeighborSet.MatchSetOptions = config.MATCH_SET_OPTIONS_RESTRICTED_TYPE_INVERT default: return fmt.Errorf("%s neighbor <set-name> [{ any | invert }]", usage) } case "as-path": if len(args) < 1 { return fmt.Errorf("%s as-path <set-name> [{ any | all | invert }]", usage) } stmt.Conditions.BgpConditions.MatchAsPathSet.AsPathSet = args[0] if len(args) == 1 { break } switch strings.ToLower(args[1]) { case "any": stmt.Conditions.BgpConditions.MatchAsPathSet.MatchSetOptions = config.MATCH_SET_OPTIONS_TYPE_ANY case "all": stmt.Conditions.BgpConditions.MatchAsPathSet.MatchSetOptions = config.MATCH_SET_OPTIONS_TYPE_ALL case "invert": stmt.Conditions.BgpConditions.MatchAsPathSet.MatchSetOptions = config.MATCH_SET_OPTIONS_TYPE_INVERT default: return fmt.Errorf("%s as-path <set-name> [{ any | all | invert }]", usage) } case "community": if len(args) < 1 { return fmt.Errorf("%s community <set-name> [{ any | all | invert }]", usage) } stmt.Conditions.BgpConditions.MatchCommunitySet.CommunitySet = args[0] if len(args) == 1 { break } switch strings.ToLower(args[1]) { case "any": stmt.Conditions.BgpConditions.MatchCommunitySet.MatchSetOptions = config.MATCH_SET_OPTIONS_TYPE_ANY case "all": stmt.Conditions.BgpConditions.MatchCommunitySet.MatchSetOptions = config.MATCH_SET_OPTIONS_TYPE_ALL case "invert": stmt.Conditions.BgpConditions.MatchCommunitySet.MatchSetOptions = config.MATCH_SET_OPTIONS_TYPE_INVERT default: return fmt.Errorf("%s community <set-name> [{ any | all | invert }]", usage) } case "ext-community": if len(args) < 1 { return fmt.Errorf("%s ext-community <set-name> [{ any | all | invert }]", usage) } stmt.Conditions.BgpConditions.MatchExtCommunitySet.ExtCommunitySet = args[0] if len(args) == 1 { break } switch strings.ToLower(args[1]) { case "any": stmt.Conditions.BgpConditions.MatchExtCommunitySet.MatchSetOptions = config.MATCH_SET_OPTIONS_TYPE_ANY case "all": stmt.Conditions.BgpConditions.MatchExtCommunitySet.MatchSetOptions = config.MATCH_SET_OPTIONS_TYPE_ALL case "invert": stmt.Conditions.BgpConditions.MatchExtCommunitySet.MatchSetOptions = config.MATCH_SET_OPTIONS_TYPE_INVERT default: return fmt.Errorf("%s ext-community <set-name> [{ any | all | invert }]", usage) } case "large-community": if len(args) < 1 { return fmt.Errorf("%s large-community <set-name> [{ any | all | invert }]", usage) } stmt.Conditions.BgpConditions.MatchLargeCommunitySet.LargeCommunitySet = args[0] if len(args) == 1 { break } switch strings.ToLower(args[1]) { case "any": stmt.Conditions.BgpConditions.MatchLargeCommunitySet.MatchSetOptions = config.MATCH_SET_OPTIONS_TYPE_ANY case "all": stmt.Conditions.BgpConditions.MatchLargeCommunitySet.MatchSetOptions = config.MATCH_SET_OPTIONS_TYPE_ALL case "invert": stmt.Conditions.BgpConditions.MatchLargeCommunitySet.MatchSetOptions = config.MATCH_SET_OPTIONS_TYPE_INVERT default: return fmt.Errorf("%s large-community <set-name> [{ any | all | invert }]", usage) } case "as-path-length": if len(args) < 2 { return fmt.Errorf("%s as-path-length <length> { eq | ge | le }", usage) } length, err := strconv.Atoi(args[0]) if err != nil { return err } stmt.Conditions.BgpConditions.AsPathLength.Value = uint32(length) switch strings.ToLower(args[1]) { case "eq": stmt.Conditions.BgpConditions.AsPathLength.Operator = config.ATTRIBUTE_COMPARISON_EQ case "ge": stmt.Conditions.BgpConditions.AsPathLength.Operator = config.ATTRIBUTE_COMPARISON_GE case "le": stmt.Conditions.BgpConditions.AsPathLength.Operator = config.ATTRIBUTE_COMPARISON_LE default: return fmt.Errorf("%s as-path-length <length> { eq | ge | le }", usage) } case "rpki": if len(args) < 1 { return fmt.Errorf("%s rpki { valid | invalid | not-found }", usage) } switch strings.ToLower(args[0]) { case "valid": stmt.Conditions.BgpConditions.RpkiValidationResult = config.RPKI_VALIDATION_RESULT_TYPE_VALID case "invalid": stmt.Conditions.BgpConditions.RpkiValidationResult = config.RPKI_VALIDATION_RESULT_TYPE_INVALID case "not-found": stmt.Conditions.BgpConditions.RpkiValidationResult = config.RPKI_VALIDATION_RESULT_TYPE_NOT_FOUND default: return fmt.Errorf("%s rpki { valid | invalid | not-found }", usage) } case "route-type": err := fmt.Errorf("%s route-type { internal | external | local }", usage) if len(args) < 1 { return err } switch strings.ToLower(args[0]) { case "internal": stmt.Conditions.BgpConditions.RouteType = config.ROUTE_TYPE_INTERNAL case "external": stmt.Conditions.BgpConditions.RouteType = config.ROUTE_TYPE_EXTERNAL case "local": stmt.Conditions.BgpConditions.RouteType = config.ROUTE_TYPE_LOCAL default: return err } default: return fmt.Errorf("%s { prefix | neighbor | as-path | community | ext-community | large-community | as-path-length | rpki | route-type }", usage) } t, err := table.NewStatement(stmt) if err != nil { return err } switch op { case CMD_ADD: err = client.AddStatement(t) case CMD_DEL: err = client.DeleteStatement(t, false) case CMD_SET: err = client.ReplaceStatement(t) default: return fmt.Errorf("invalid operation: %s", op) } return err }