From 0299c0042783463ee007a6dba0de70dcf6fc36ee Mon Sep 17 00:00:00 2001 From: Donald Sharp Date: Tue, 19 May 2015 18:04:25 -0700 Subject: [PATCH] bgpd: bgpd-no-as.patch bgp: Fixup of the remote-as command to allow user to not have to enter an actual as number Signed-off-by: Donald Sharp Reviewed-by: --- bgpd/bgp_fsm.c | 1 + bgpd/bgp_network.c | 2 +- bgpd/bgp_packet.c | 38 ++++++++++++++++++--- bgpd/bgp_vty.c | 40 ++++++++++++++++------ bgpd/bgpd.c | 85 ++++++++++++++++++++++++++++++++-------------- bgpd/bgpd.h | 23 ++++++++++--- 6 files changed, 143 insertions(+), 46 deletions(-) diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c index 388b85b051..6db94ff4f2 100644 --- a/bgpd/bgp_fsm.c +++ b/bgpd/bgp_fsm.c @@ -137,6 +137,7 @@ peer_xfer_conn(struct peer *from_peer) stream_fifo_clean(peer->obuf); stream_fifo_clean(from_peer->obuf); + peer->as = from_peer->as; peer->v_holdtime = from_peer->v_holdtime; peer->v_keepalive = from_peer->v_keepalive; peer->v_asorig = from_peer->v_asorig; diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c index 3cf1d3b84c..fc4983a563 100644 --- a/bgpd/bgp_network.c +++ b/bgpd/bgp_network.c @@ -310,7 +310,7 @@ bgp_accept (struct thread *thread) bgp_set_socket_ttl (peer1, bgp_sock); peer = peer_create (&su, peer1->conf_if, peer1->bgp, peer1->local_as, - peer1->as, 0, 0); + peer1->as, peer1->as_type, 0, 0); peer_xfer_config(peer, peer1); UNSET_FLAG (peer->flags, PEER_FLAG_CONFIG_NODE); diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c index 1a5e8855a1..af76f7d64c 100644 --- a/bgpd/bgp_packet.c +++ b/bgpd/bgp_packet.c @@ -1033,13 +1033,43 @@ bgp_open_receive (struct peer *peer, bgp_size_t size) } /* Check neighbor as number. */ - if (remote_as != peer->as) + if (peer->as_type == AS_INTERNAL) + { + if (remote_as != peer->bgp->as) + { + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s bad OPEN, remote AS is %u, internal specified", + peer->host, remote_as); + bgp_notify_send_with_data (peer, + BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_BAD_PEER_AS, + notify_data_remote_as, 2); + return -1; + } + peer->as = peer->local_as; + } + else if (peer->as_type == AS_EXTERNAL) + { + if (remote_as == peer->bgp->as) + { + if (bgp_debug_neighbor_events(peer)) + zlog_debug ("%s bad OPEN, remote AS is %u, external specified", + peer->host, remote_as); + bgp_notify_send_with_data (peer, + BGP_NOTIFY_OPEN_ERR, + BGP_NOTIFY_OPEN_BAD_PEER_AS, + notify_data_remote_as, 2); + return -1; + } + peer->as = remote_as; + } + else if ((peer->as_type == AS_SPECIFIED) && (remote_as != peer->as)) { if (bgp_debug_neighbor_events(peer)) zlog_debug ("%s bad OPEN, remote AS is %u, expected %u", - peer->host, remote_as, peer->as); - bgp_notify_send_with_data (peer, - BGP_NOTIFY_OPEN_ERR, + peer->host, remote_as, peer->as); + bgp_notify_send_with_data (peer, + BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_BAD_PEER_AS, notify_data_remote_as, 2); return -1; diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index 4152b8cd2e..abda0684d0 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -2507,22 +2507,36 @@ peer_remote_as_vty (struct vty *vty, const char *peer_str, int ret; struct bgp *bgp; as_t as; + int as_type = AS_SPECIFIED; union sockunion su; bgp = vty->index; - /* Get AS number. */ - VTY_GET_INTEGER_RANGE ("AS", as, as_str, 1, BGP_AS4_MAX); + if (strncmp(as_str, "internal", strlen("internal")) == 0) + { + as = 0; + as_type = AS_INTERNAL; + } + else if (strncmp(as_str, "external", strlen("external")) == 0) + { + as = 0; + as_type = AS_EXTERNAL; + } + else + { + /* Get AS number. */ + VTY_GET_INTEGER_RANGE ("AS", as, as_str, 1, BGP_AS4_MAX); + } /* If peer is peer group, call proper function. */ ret = str2sockunion (peer_str, &su); if (ret < 0) { /* Check for peer by interface */ - ret = peer_remote_as (bgp, NULL, peer_str, &as, afi, safi); + ret = peer_remote_as (bgp, NULL, peer_str, &as, as_type, afi, safi); if (ret < 0) { - ret = peer_group_remote_as (bgp, peer_str, &as); + ret = peer_group_remote_as (bgp, peer_str, &as, as_type); if (ret < 0) { vty_out (vty, "%% Create the peer-group or interface first%s", @@ -2540,7 +2554,7 @@ peer_remote_as_vty (struct vty *vty, const char *peer_str, VTY_NEWLINE); return CMD_WARNING; } - ret = peer_remote_as (bgp, &su, NULL, &as, afi, safi); + ret = peer_remote_as (bgp, &su, NULL, &as, as_type, afi, safi); } /* This peer belongs to peer group. */ @@ -2558,7 +2572,7 @@ peer_remote_as_vty (struct vty *vty, const char *peer_str, DEFUN (neighbor_remote_as, neighbor_remote_as_cmd, - NEIGHBOR_CMD2 "remote-as " CMD_AS_RANGE, + NEIGHBOR_CMD2 "remote-as (" CMD_AS_RANGE "|external|internal)", NEIGHBOR_STR NEIGHBOR_ADDR_STR2 "Specify a BGP neighbor\n" @@ -2677,7 +2691,7 @@ DEFUN (no_neighbor, ALIAS (no_neighbor, no_neighbor_remote_as_cmd, - NO_NEIGHBOR_CMD "remote-as " CMD_AS_RANGE, + NO_NEIGHBOR_CMD "remote-as (" CMD_AS_RANGE "|internal|external)", NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR @@ -2731,7 +2745,7 @@ DEFUN (no_neighbor_peer_group, DEFUN (no_neighbor_interface_peer_group_remote_as, no_neighbor_interface_peer_group_remote_as_cmd, - "no neighbor WORD remote-as " CMD_AS_RANGE, + "no neighbor WORD remote-as (" CMD_AS_RANGE "|internal|external)", NO_STR NEIGHBOR_STR "Interface name or neighbor tag\n" @@ -2745,7 +2759,7 @@ DEFUN (no_neighbor_interface_peer_group_remote_as, peer = peer_lookup_by_conf_if (vty->index, argv[0]); if (peer) { - peer_as_change (peer, 0); + peer_as_change (peer, 0, AS_SPECIFIED); return CMD_SUCCESS; } @@ -10668,10 +10682,16 @@ bgp_show_one_peer_group (struct vty *vty, struct peer_group *group) conf = group->conf; + if (conf->as_type == AS_SPECIFIED || + conf->as_type == AS_EXTERNAL) { vty_out (vty, "%sBGP peer-group %s, remote AS %d%s", VTY_NEWLINE, group->name, conf->as, VTY_NEWLINE); + } else if (conf->as_type == AS_INTERNAL) { + vty_out (vty, "%sBGP peer-group %s, remote AS %d%s", + VTY_NEWLINE, group->name, group->bgp->as, VTY_NEWLINE); + } - if (group->bgp->as == conf->as) + if ((group->bgp->as == conf->as) || (conf->as_type == AS_INTERNAL)) vty_out (vty, " Peer-group type is internal%s", VTY_NEWLINE); else vty_out (vty, " Peer-group type is external%s", VTY_NEWLINE); diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index a5794af789..c532e695b1 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -830,7 +830,9 @@ peer_calc_sort (struct peer *peer) /* Peer-group */ if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) { - if (peer->as) + if (peer->as_type != AS_SPECIFIED) + return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP : BGP_PEER_EBGP); + else if (peer->as) return (bgp->as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP); else { @@ -864,6 +866,9 @@ peer_calc_sort (struct peer *peer) } else { + if (peer->as_type != AS_SPECIFIED) + return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP : BGP_PEER_EBGP); + return (peer->local_as == 0 ? BGP_PEER_INTERNAL : peer->local_as == peer->as ? BGP_PEER_IBGP : BGP_PEER_EBGP); @@ -1170,7 +1175,7 @@ bgp_peer_conf_if_to_su_update (struct peer *peer) /* Create new BGP peer. */ struct peer * peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp, - as_t local_as, as_t remote_as, afi_t afi, safi_t safi) + as_t local_as, as_t remote_as, int as_type, afi_t afi, safi_t safi) { int active; struct peer *peer; @@ -1191,6 +1196,7 @@ peer_create (union sockunion *su, const char *conf_if, struct bgp *bgp, } peer->local_as = local_as; peer->as = remote_as; + peer->as_type = as_type; peer->local_id = bgp->router_id; peer->v_holdtime = bgp->default_holdtime; peer->v_keepalive = bgp->default_keepalive; @@ -1239,9 +1245,9 @@ peer_conf_interface_get(struct bgp *bgp, const char *conf_if, afi_t afi, { if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4) && afi == AFI_IP && safi == SAFI_UNICAST) - peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, 0, 0); + peer = peer_create (NULL, conf_if, bgp, bgp->as, AS_SPECIFIED, 0, 0, 0); else - peer = peer_create (NULL, conf_if, bgp, bgp->as, 0, afi, safi); + peer = peer_create (NULL, conf_if, bgp, bgp->as, AS_SPECIFIED, 0, afi, safi); } @@ -1264,7 +1270,7 @@ peer_create_accept (struct bgp *bgp) /* Change peer's AS number. */ void -peer_as_change (struct peer *peer, as_t as) +peer_as_change (struct peer *peer, as_t as, int as_specified) { bgp_peer_sort_t type; struct peer *conf; @@ -1283,6 +1289,7 @@ peer_as_change (struct peer *peer, as_t as) } type = peer_sort (peer); peer->as = as; + peer->as_type = as_specified; if (bgp_config_check (peer->bgp, BGP_CONFIG_CONFEDERATION) && ! bgp_confederation_peers_check (peer->bgp, as) @@ -1340,8 +1347,8 @@ peer_as_change (struct peer *peer, as_t as) /* If peer does not exist, create new one. If peer already exists, set AS number to the peer. */ int -peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, as_t *as, - afi_t afi, safi_t safi) +peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, + as_t *as, int as_type, afi_t afi, safi_t safi) { struct peer *peer; as_t local_as; @@ -1371,7 +1378,7 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, as_t } if (peer_sort (peer->group->conf) == BGP_PEER_IBGP) { - if (bgp->as != *as) + if ((as_type != AS_INTERNAL) && (bgp->as != *as)) { *as = peer->as; return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; @@ -1379,7 +1386,7 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, as_t } else { - if (bgp->as == *as) + if ((as_type != AS_EXTERNAL) && (bgp->as == *as)) { *as = peer->as; return BGP_ERR_PEER_GROUP_PEER_TYPE_DIFFERENT; @@ -1389,7 +1396,7 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, as_t /* Existing peer's AS number change. */ if (peer->as != *as) - peer_as_change (peer, *as); + peer_as_change (peer, *as, as_type); } else { @@ -1410,9 +1417,9 @@ peer_remote_as (struct bgp *bgp, union sockunion *su, const char *conf_if, as_t if (bgp_flag_check (bgp, BGP_FLAG_NO_DEFAULT_IPV4) && afi == AFI_IP && safi == SAFI_UNICAST) - peer = peer_create (su, conf_if, bgp, local_as, *as, 0, 0); + peer = peer_create (su, conf_if, bgp, local_as, *as, as_type, 0, 0); else - peer = peer_create (su, conf_if, bgp, local_as, *as, afi, safi); + peer = peer_create (su, conf_if, bgp, local_as, *as, as_type, afi, safi); } return 0; @@ -2065,7 +2072,8 @@ peer_group2peer_config_copy (struct peer_group *group, struct peer *peer, /* Peer group's remote AS configuration. */ int -peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as) +peer_group_remote_as (struct bgp *bgp, const char *group_name, + as_t *as, int as_type) { struct peer_group *group; struct peer *peer; @@ -2075,17 +2083,18 @@ peer_group_remote_as (struct bgp *bgp, const char *group_name, as_t *as) if (! group) return -1; - if (group->conf->as == *as) + if ((as_type == group->conf->as_type) && (group->conf->as == *as)) return 0; + /* When we setup peer-group AS number all peer group member's AS number must be updated to same number. */ - peer_as_change (group->conf, *as); + peer_as_change (group->conf, *as, as_type); for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) { if (peer->as != *as) - peer_as_change (peer, *as); + peer_as_change (peer, *as, as_type); } return 0; @@ -2145,7 +2154,8 @@ peer_group_remote_as_delete (struct peer_group *group) struct peer *peer, *other; struct listnode *node, *nnode; - if (! group->conf->as) + if ((group->conf->as_type == AS_UNSPECIFIED) || + ((! group->conf->as) && (group->conf->as_type == AS_SPECIFIED))) return 0; for (ALL_LIST_ELEMENTS (group->peer, node, nnode, peer)) @@ -2164,6 +2174,7 @@ peer_group_remote_as_delete (struct peer_group *group) list_delete_all_node (group->peer); group->conf->as = 0; + group->conf->as_type = AS_UNSPECIFIED; return 0; } @@ -2258,10 +2269,11 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer, /* Create a new peer. */ if (! peer) { - if (! group->conf->as) + if ((group->conf->as_type == AS_SPECIFIED) && (! group->conf->as)) { return BGP_ERR_PEER_GROUP_NO_REMOTE_AS; + } - peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, afi, safi); + peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, afi, safi); peer->group = group; peer->af_group[afi][safi] = 1; @@ -2287,6 +2299,12 @@ peer_group_bind (struct bgp *bgp, union sockunion *su, struct peer *peer, && strcmp (peer->group->name, group->name) != 0) return BGP_ERR_PEER_GROUP_MISMATCH; + if (peer->as_type == AS_UNSPECIFIED) + { + peer->as_type = group->conf->as_type; + peer->as = group->conf->as; + } + if (! group->conf->as) { if (peer_sort (group->conf) != BGP_PEER_INTERNAL @@ -2821,7 +2839,7 @@ peer_create_bind_dynamic_neighbor (struct bgp *bgp, union sockunion *su, as_t as; /* Create peer first; we've already checked group config is valid. */ - peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, 0, 0); + peer = peer_create (su, NULL, bgp, bgp->as, group->conf->as, group->conf->as_type, 0, 0); if (!peer) return NULL; @@ -2916,8 +2934,9 @@ peer_lookup_dynamic_neighbor (struct bgp *bgp, union sockunion *su) char buf1[SU_ADDRSTRLEN]; prefix = sockunion2hostprefix(su); - if (!prefix) + if (!prefix) { return NULL; + } /* See if incoming connection matches a configured listen range. */ group = peer_group_lookup_dynamic_neighbor (bgp, prefix, &listen_range); @@ -2925,6 +2944,7 @@ peer_lookup_dynamic_neighbor (struct bgp *bgp, union sockunion *su) if (! group) return NULL; + gbgp = group->bgp; if (! gbgp) @@ -5820,15 +5840,28 @@ bgp_config_write_peer (struct vty *vty, struct bgp *bgp, if (CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) vty_out (vty, " neighbor %s peer-group%s", addr, VTY_NEWLINE); - if (peer->as) - vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as, - VTY_NEWLINE); + if (peer->as_type == AS_SPECIFIED) + { + vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as, + VTY_NEWLINE); + } + else if (peer->as_type == AS_INTERNAL) + { + vty_out (vty, " neighbor %s remote-as internal%s", addr, VTY_NEWLINE); + } + else if (peer->as_type == AS_EXTERNAL) + { + vty_out (vty, " neighbor %s remote-as external%s", addr, VTY_NEWLINE); + } } else { if (! g_peer->as) - vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as, - VTY_NEWLINE); + { + if (g_peer->as_type == AS_SPECIFIED) + vty_out (vty, " neighbor %s remote-as %u%s", addr, peer->as, + VTY_NEWLINE); + } if (peer->af_group[AFI_IP][SAFI_UNICAST]) vty_out (vty, " neighbor %s peer-group %s%s", addr, peer->group->name, VTY_NEWLINE); diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 0cd72e0e64..7584faf700 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -29,6 +29,18 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA struct update_subgroup; struct bpacket; +/* + * Allow the neighbor XXXX remote-as to take internal or external + * AS_SPECIFIED is zero to auto-inherit original non-feature/enhancement behavior + * in the system. + */ +enum { + AS_UNSPECIFIED = 0, + AS_SPECIFIED, + AS_INTERNAL, + AS_EXTERNAL, +}; + /* Typedef BGP specific types. */ typedef u_int32_t as_t; typedef u_int16_t as16_t; /* we may still encounter 16 Bit asnums */ @@ -471,7 +483,8 @@ struct peer struct peer_af *peer_af_array[BGP_AF_MAX]; /* Peer's remote AS number. */ - as_t as; + int as_type; + as_t as; /* Peer's local AS number. */ as_t local_as; @@ -1109,7 +1122,7 @@ extern bgp_peer_sort_t peer_sort (struct peer *peer); extern int peer_active (struct peer *); extern int peer_active_nego (struct peer *); extern struct peer *peer_create(union sockunion *, const char *, struct bgp *, - as_t, as_t, afi_t, safi_t); + as_t, as_t, int, afi_t, safi_t); extern struct peer *peer_create_accept (struct bgp *); extern void peer_xfer_config (struct peer *dst, struct peer *src); extern char *peer_uptime (time_t, char *, size_t); @@ -1162,10 +1175,10 @@ extern int bgp_listen_limit_unset (struct bgp *); extern int bgp_update_delay_active (struct bgp *); extern int bgp_update_delay_configured (struct bgp *); extern int peer_rsclient_active (struct peer *); -extern void peer_as_change (struct peer *, as_t); +extern void peer_as_change (struct peer *, as_t, int); extern int peer_remote_as (struct bgp *, union sockunion *,const char *, as_t *, - afi_t, safi_t); -extern int peer_group_remote_as (struct bgp *, const char *, as_t *); + int, afi_t, safi_t); +extern int peer_group_remote_as (struct bgp *, const char *, as_t *, int); extern int peer_delete (struct peer *peer); extern int peer_group_delete (struct peer_group *); extern int peer_group_remote_as_delete (struct peer_group *); -- 2.39.5