==== Patch level 1 Source: [No source] Target: 53eccb64-3fed-0310-a953-aee945e670f6:/quagga/working-copy:832 [local] Log: Patch updated to the Quagga version 0.98.0. --- bgpd/bgp_network.c (revision 832) +++ bgpd/bgp_network.c (patch ht-20050110-0.98.0-bgp-md5 level 1) @@ -38,6 +38,56 @@ Software Foundation, Inc., 59 Temple Pla extern struct zebra_privs_t bgpd_privs; +#if defined(HAVE_TCP_MD5) && defined(GNU_LINUX) +/* Set MD5 key to the socket. */ +int +bgp_md5_set (int sock, struct peer *peer, char *password) +{ + int ret; + struct tcp_rfc2385_cmd cmd; + struct in_addr *addr = &peer->su.sin.sin_addr; + + cmd.command = TCP_MD5_AUTH_ADD; + cmd.address = addr->s_addr; + cmd.keylen = strlen (password); + cmd.key = password; + + if ( bgpd_privs.change (ZPRIVS_RAISE) ) + zlog_err ("bgp_md5_set: could not raise privs"); + + ret = setsockopt (sock, IPPROTO_TCP, TCP_MD5_AUTH, &cmd, sizeof cmd); + + if (bgpd_privs.change (ZPRIVS_LOWER) ) + zlog_err ("bgp_md5_set: could not lower privs"); + + return ret; +} + +/* Unset MD5 key from the socket. */ +int +bgp_md5_unset (int sock, struct peer *peer, char *password) +{ + int ret; + struct tcp_rfc2385_cmd cmd; + struct in_addr *addr = &peer->su.sin.sin_addr; + + cmd.command = TCP_MD5_AUTH_DEL; + cmd.address = addr->s_addr; + cmd.keylen = strlen (password); + cmd.key = password; + + if ( bgpd_privs.change (ZPRIVS_RAISE) ) + zlog_err ("bgp_md5_unset: could not raise privs"); + + ret = setsockopt (sock, IPPROTO_TCP, TCP_MD5_AUTH, &cmd, sizeof cmd); + + if (bgpd_privs.change (ZPRIVS_LOWER) ) + zlog_err ("bgp_md5_unset: could not lower privs"); + + return ret; +} +#endif /* defined(HAVE_TCP_MD5) && defined(GNU_LINUX) */ + /* Accept bgp connection. */ static int bgp_accept (struct thread *thread) @@ -240,6 +290,12 @@ bgp_connect (struct peer *peer) sockopt_reuseaddr (peer->fd); sockopt_reuseport (peer->fd); +#ifdef HAVE_TCP_MD5 + if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSWORD)) + if (sockunion_family (&peer->su) == AF_INET) + bgp_md5_set (peer->fd, peer, peer->password); +#endif /* HAVE_TCP_MD5 */ + /* Bind socket. */ bgp_bind (peer); @@ -287,6 +343,9 @@ int bgp_socket (struct bgp *bgp, unsigned short port) { int ret, en; +#ifdef IPV6_V6ONLY + int v6only = 1; +#endif /* IPV6_V6ONLY */ struct addrinfo req; struct addrinfo *ainfo; struct addrinfo *ainfo_save; @@ -321,6 +380,11 @@ bgp_socket (struct bgp *bgp, unsigned sh zlog_err ("socket: %s", safe_strerror (errno)); continue; } +#ifdef IPV6_V6ONLY + ret = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&v6only, sizeof(v6only)); + if (ret < 0) + zlog_err ("setsockopt IPV6_V6ONLY: i%s", strerror (errno)); +#endif /* IPV6_V6ONLY */ sockopt_reuseaddr (sock); sockopt_reuseport (sock); @@ -348,6 +412,11 @@ bgp_socket (struct bgp *bgp, unsigned sh continue; } +#ifdef HAVE_TCP_MD5 + if (ainfo->ai_family == AF_INET) + bm->sock = sock; +#endif /* HAVE_TCP_MD5 */ + thread_add_read (master, bgp_accept, bgp, sock); } while ((ainfo = ainfo->ai_next) != NULL); @@ -408,6 +477,9 @@ bgp_socket (struct bgp *bgp, unsigned sh close (sock); return ret; } +#ifdef HAVE_TCP_MD5 + bm->sock = sock; +#endif /* HAVE_TCP_MD5 */ thread_add_read (bm->master, bgp_accept, bgp, sock); --- bgpd/bgp_network.h (revision 832) +++ bgpd/bgp_network.h (patch ht-20050110-0.98.0-bgp-md5 level 1) @@ -18,6 +18,27 @@ along with GNU Zebra; see the file COPYI Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#if defined(HAVE_TCP_MD5) && defined(GNU_LINUX) +/* setsockopt Number */ +#define TCP_MD5_AUTH 13 + +/* Commands (used in the structure passed from userland) */ +#define TCP_MD5_AUTH_ADD 1 +#define TCP_MD5_AUTH_DEL 2 + +struct tcp_rfc2385_cmd { + u_int8_t command; /* Command - Add/Delete */ + u_int32_t address; /* IPV4 address associated */ + u_int8_t keylen; /* MD5 Key len (do NOT assume 0 terminated ascii) */ + void *key; /* MD5 Key */ +}; +#endif /* defined(HAVE_TCP_MD5) && defined(GNU_LINUX) */ + +#ifdef HAVE_TCP_MD5 +int bgp_md5_set (int sock, struct peer *, char *); +int bgp_md5_unset (int sock, struct peer *, char *); +#endif /* HAVE_TCP_MD5 */ + int bgp_socket (struct bgp *, unsigned short); int bgp_connect (struct peer *); void bgp_getsockname (struct peer *); --- bgpd/bgp_vty.c (revision 832) +++ bgpd/bgp_vty.c (patch ht-20050110-0.98.0-bgp-md5 level 1) @@ -1386,6 +1386,46 @@ ALIAS (no_neighbor_local_as, "AS number used as local AS\n" "Do not prepend local-as to updates from ebgp peers\n") +#ifdef HAVE_TCP_MD5 +DEFUN (neighbor_password, + neighbor_password_cmd, + NEIGHBOR_CMD2 "password LINE", + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Set a password\n" + "The password\n") +{ + struct peer *peer; + int ret; + + peer = peer_and_group_lookup_vty (vty, argv[0]); + if (! peer) + return CMD_WARNING; + + ret = peer_password_set (peer, argv[1]); + return bgp_vty_return (vty, ret); +} + +DEFUN (no_neighbor_password, + no_neighbor_password_cmd, + NO_NEIGHBOR_CMD2 "password", + NO_STR + NEIGHBOR_STR + NEIGHBOR_ADDR_STR2 + "Set a password\n") +{ + struct peer *peer; + int ret; + + peer = peer_and_group_lookup_vty (vty, argv[0]); + if (! peer) + return CMD_WARNING; + + ret = peer_password_unset (peer); + return bgp_vty_return (vty, ret); +} +#endif /* HAVE_TCP_MD5 */ + DEFUN (neighbor_activate, neighbor_activate_cmd, NEIGHBOR_CMD2 "activate", @@ -8531,6 +8571,12 @@ bgp_vty_init () install_element (BGP_NODE, &no_neighbor_local_as_val_cmd); install_element (BGP_NODE, &no_neighbor_local_as_val2_cmd); +#ifdef HAVE_TCP_MD5 + /* "neighbor password" commands. */ + install_element (BGP_NODE, &neighbor_password_cmd); + install_element (BGP_NODE, &no_neighbor_password_cmd); +#endif /* HAVE_TCP_MD5 */ + /* "neighbor activate" commands. */ install_element (BGP_NODE, &neighbor_activate_cmd); install_element (BGP_IPV4_NODE, &neighbor_activate_cmd); --- bgpd/bgpd.c (revision 832) +++ bgpd/bgpd.c (patch ht-20050110-0.98.0-bgp-md5 level 1) @@ -707,6 +707,7 @@ peer_new () peer->ostatus = Idle; peer->version = BGP_VERSION_4; peer->weight = 0; + peer->password = NULL; /* Set default flags. */ for (afi = AFI_IP; afi < AFI_MAX; afi++) @@ -1068,6 +1069,17 @@ peer_delete (struct peer *peer) bgp_stop (peer); bgp_fsm_change_status (peer, Idle); +#ifdef HAVE_TCP_MD5 + /* Password configuration */ + if (peer->password) + { + if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP) + && sockunion_family (&peer->su) == AF_INET) + bgp_md5_unset (bm->sock, peer, peer->password); + free (peer->password); + } +#endif /* HAVE_TCP_MD5 */ + /* Stop all timers. */ BGP_TIMER_OFF (peer->t_start); BGP_TIMER_OFF (peer->t_connect); @@ -1293,6 +1305,26 @@ peer_group2peer_config_copy (struct peer else peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV; +#ifdef HAVE_TCP_MD5 + /* password apply */ + if (CHECK_FLAG (conf->flags, PEER_FLAG_PASSWORD)) + { + if (peer->password) + free (peer->password); + peer->password = strdup (conf->password); + + if (sockunion_family (&peer->su) == AF_INET) + bgp_md5_set (bm->sock, peer, peer->password); + } + else if (peer->password) + { + if (sockunion_family (&peer->su) == AF_INET) + bgp_md5_unset (bm->sock, peer, peer->password); + free (peer->password); + peer->password = NULL; + } +#endif /* HAVE_TCP_MD5 */ + /* maximum-prefix */ peer->pmax[afi][safi] = conf->pmax[afi][safi]; peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi]; @@ -3270,6 +3302,119 @@ peer_local_as_unset (struct peer *peer) return 0; } +#ifdef HAVE_TCP_MD5 +/* Set password for authenticating with the peer. */ +int +peer_password_set (struct peer *peer, const char *password) +{ + struct peer_group *group; + struct listnode *nn; + + if (peer->password && strcmp (peer->password, password) == 0 + && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) + return 0; + + SET_FLAG (peer->flags, PEER_FLAG_PASSWORD); + if (peer->password) + free (peer->password); + peer->password = strdup (password); + + if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) + { + if (peer->status == Established) + bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + BGP_EVENT_ADD (peer, BGP_Stop); + + if (sockunion_family (&peer->su) == AF_INET) + bgp_md5_set (bm->sock, peer, peer->password); + return 0; + } + + group = peer->group; + LIST_LOOP (group->peer, peer, nn) + { + if (peer->password && strcmp (peer->password, password) == 0) + continue; + + SET_FLAG (peer->flags, PEER_FLAG_PASSWORD); + if (peer->password) + free (peer->password); + peer->password = strdup (password); + + if (peer->status == Established) + bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + BGP_EVENT_ADD (peer, BGP_Stop); + + if (sockunion_family (&peer->su) == AF_INET) + bgp_md5_set (bm->sock, peer, peer->password); + } + + return 0; +} + +int +peer_password_unset (struct peer *peer) +{ + struct peer_group *group; + struct listnode *nn; + + if (! CHECK_FLAG (peer->flags, PEER_FLAG_PASSWORD) + && ! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) + return 0; + + if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)) + { + if (peer_group_active (peer) + && CHECK_FLAG (peer->group->conf->flags, PEER_FLAG_PASSWORD)) + return BGP_ERR_PEER_GROUP_HAS_THE_FLAG; + + if (peer->status == Established) + bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + BGP_EVENT_ADD (peer, BGP_Stop); + + if (sockunion_family (&peer->su) == AF_INET) + bgp_md5_unset (bm->sock, peer, peer->password); + + UNSET_FLAG (peer->flags, PEER_FLAG_PASSWORD); + if (peer->password) + free (peer->password); + peer->password = NULL; + + return 0; + } + + UNSET_FLAG (peer->flags, PEER_FLAG_PASSWORD); + if (peer->password) + free (peer->password); + peer->password = NULL; + + group = peer->group; + LIST_LOOP (group->peer, peer, nn) + { + if (! CHECK_FLAG (peer->flags, PEER_FLAG_PASSWORD)) + continue; + + if (peer->status == Established) + bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_CONFIG_CHANGE); + else + BGP_EVENT_ADD (peer, BGP_Stop); + + if (sockunion_family (&peer->su) == AF_INET) + bgp_md5_unset (bm->sock, peer, peer->password); + + UNSET_FLAG (peer->flags, PEER_FLAG_PASSWORD); + if (peer->password) + free (peer->password); + peer->password = NULL; + } + + return 0; +} +#endif /* HAVE_TCP_MD5 */ + /* Set distribute list to the peer. */ int peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct, @@ -4286,6 +4431,16 @@ bgp_config_write_peer (struct vty *vty, ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN)) vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE); +#ifdef HAVE_TCP_MD5 + /* Password. */ + if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSWORD)) + if (! peer_group_active (peer) + || ! CHECK_FLAG (g_peer->flags, PEER_FLAG_PASSWORD) + || strcmp (peer->password, g_peer->password) != 0) + vty_out (vty, " neighbor %s password %s%s", addr, peer->password, + VTY_NEWLINE); +#endif /* HAVE_TCP_MD5 */ + /* BGP port. */ if (peer->port != BGP_PORT_DEFAULT) vty_out (vty, " neighbor %s port %d%s", addr, peer->port, @@ -4817,6 +4972,9 @@ bgp_master_init () bm->port = BGP_PORT_DEFAULT; bm->master = thread_master_create (); bm->start_time = time (NULL); +#ifdef HAVE_TCP_MD5 + bm->sock = -1; +#endif /* HAVE_TCP_MD5 */ } void --- bgpd/bgpd.h (revision 832) +++ bgpd/bgpd.h (patch ht-20050110-0.98.0-bgp-md5 level 1) @@ -45,6 +45,11 @@ struct bgp_master #define BGP_OPT_NO_FIB (1 << 0) #define BGP_OPT_MULTIPLE_INSTANCE (1 << 1) #define BGP_OPT_CONFIG_CISCO (1 << 2) + +#ifdef HAVE_TCP_MD5 + /* bgp receive socket */ + int sock; +#endif /* HAVE_TCP_MD5 */ }; /* BGP instance structure. */ @@ -335,6 +340,7 @@ struct peer #define PEER_FLAG_DYNAMIC_CAPABILITY (1 << 6) /* dynamic capability */ #define PEER_FLAG_ENFORCE_MULTIHOP (1 << 7) /* enforce-multihop */ #define PEER_FLAG_LOCAL_AS_NO_PREPEND (1 << 8) /* local-as no-prepend */ +#define PEER_FLAG_PASSWORD (1 << 9) /* password */ /* Per AF configuration flags. */ u_int32_t af_flags[AFI_MAX][SAFI_MAX]; @@ -356,6 +362,9 @@ struct peer #define PEER_FLAG_MAX_PREFIX_WARNING (1 << 15) /* maximum prefix warning-only */ #define PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED (1 << 16) /* leave link-local nexthop unchanged */ + /* MD5 password */ + char *password; + /* default-originate route-map. */ struct { @@ -895,5 +904,10 @@ int peer_unsuppress_map_unset (struct pe int peer_maximum_prefix_set (struct peer *, afi_t, safi_t, u_int32_t, u_char, int); int peer_maximum_prefix_unset (struct peer *, afi_t, safi_t); +#ifdef HAVE_TCP_MD5 +int peer_password_set (struct peer *, const char *); +int peer_password_unset (struct peer *); +#endif /* HAVE_TCP_MD5 */ + int peer_clear (struct peer *); int peer_clear_soft (struct peer *, afi_t, safi_t, enum bgp_clear_type); --- configure.ac (revision 832) +++ configure.ac (patch ht-20050110-0.98.0-bgp-md5 level 1) @@ -153,6 +153,8 @@ AC_ARG_ENABLE(irdp, [ --enable-irdp enable IRDP server support in zebra]) AC_ARG_ENABLE(capabilities, [ --disable-capabilities disable using POSIX capabilities]) +AC_ARG_ENABLE(tcp-md5, +[ --enable-tcp-md5 enable TCP MD5 Signature Option (RFC2385)]) AC_ARG_ENABLE(gcc_ultra_verbose, [ --enable-gcc-ultra-verbose enable ultra verbose GCC warnings]) AC_ARG_ENABLE(gcc-rdynamic, @@ -192,6 +194,11 @@ if test "${enable_ospf_te}" = "yes"; the AC_DEFINE(HAVE_OSPF_TE,,OSPF TE) fi +if test "${enable_tcp_md5}" = "yes"; then + AC_DEFINE(HAVE_TCP_MD5,,Linux TCP MD5 Signature Option) +fi + + AC_MSG_CHECKING(if zebra should be configurable to send Route Advertisements) if test "${enable_rtadv}" != "no"; then AC_MSG_RESULT(yes)