Hi,
I've attached a debdiff to update the md5 patches.
It replaces the 15_ and 20_ patches with an updated md5 patch,
posted on quagga-dev at the end of october 2007:
http://marc.info/?l=quagga-dev&m=119356096204723&w=2.
--
Mathias
reverted:
--- quagga-0.99.9/debian/patches/20_ht-20050321-0.98.2-bgp-md5.dpatch
+++ quagga-0.99.9.orig/debian/patches/20_ht-20050321-0.98.2-bgp-md5.dpatch
@@ -1,450 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## 20_ht-20050110-0.98.0-bgp-md5.dpatch by <[EMAIL PROTECTED]>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: Based on latest MD5 patch from Hasso.
-## DP: Modified LIST_LOOP to new 0.99.1 macros. -ch-
-## DP: The configure.ac block has been removed so that no automatic autoreconf
-## DP: is done which overwrites patches to Makefile.in.
-
[EMAIL PROTECTED]@
-diff -Nur quagga-0.99.1.ORIG/bgpd/bgpd.c quagga-0.99.1/bgpd/bgpd.c
---- quagga-0.99.1.ORIG/bgpd/bgpd.c 2005-04-08 17:40:37.000000000 +0200
-+++ quagga-0.99.1/bgpd/bgpd.c 2005-05-07 06:23:28.969954946 +0200
-@@ -706,8 +706,9 @@
- peer->status = Idle;
- peer->ostatus = Idle;
- peer->weight = 0;
-+ peer->password = NULL;
- peer->bgp = bgp;
- peer = peer_lock (peer); /* initial reference */
-
- /* Set default flags. */
- for (afi = AFI_IP; afi < AFI_MAX; afi++)
-@@ -1202,4 +1202,16 @@
- peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
- bgp_stop (peer);
- bgp_fsm_change_status (peer, Deleted);
-+
-+#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 */
-+
- bgp_timer_set (peer); /* stops all timers for Deleted */
-@@ -1390,6 +1402,26 @@
- 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];
-@@ -3269,6 +3301,121 @@
- 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, *nnode;
-+
-+ 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;
-+ /* #42# LIST_LOOP (group->peer, peer, nn) */
-+ for (ALL_LIST_ELEMENTS (group->peer, nn, nnode, peer))
-+ {
-+ 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, *nnode;
-+
-+ 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;
-+ /* #42# LIST_LOOP (group->peer, peer, nn) */
-+ for (ALL_LIST_ELEMENTS (group->peer, nn, nnode, peer))
-+ {
-+ 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,
-@@ -4307,6 +4454,16 @@
- ! 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,
-@@ -4834,7 +4991,10 @@
- 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
-diff -Nur quagga-0.99.1.ORIG/bgpd/bgpd.h quagga-0.99.1/bgpd/bgpd.h
---- quagga-0.99.1.ORIG/bgpd/bgpd.h 2005-04-08 17:40:37.000000000 +0200
-+++ quagga-0.99.1/bgpd/bgpd.h 2005-05-07 06:15:52.840226893 +0200
-@@ -45,6 +45,11 @@
- #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 @@
-
- /* NSF mode (graceful restart) */
- u_char nsf[AFI_MAX][SAFI_MAX];
-+#define PEER_FLAG_PASSWORD (1 << 9) /* password */
-
- /* Per AF configuration flags. */
- u_int32_t af_flags[AFI_MAX][SAFI_MAX];
-@@ -356,6 +362,9 @@
- #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
- {
-@@ -916,6 +925,11 @@
- int peer_maximum_prefix_unset (struct peer *, afi_t, safi_t);
-
- extern int peer_unsuppress_map_set (struct peer *, afi_t, safi_t, const char
*);
-+#ifdef HAVE_TCP_MD5
-+int peer_password_set (struct peer *, const char *);
-+int peer_password_unset (struct peer *);
-+#endif /* HAVE_TCP_MD5 */
-+
- extern int peer_unsuppress_map_unset (struct peer *, afi_t, safi_t);
-
- extern int peer_maximum_prefix_set (struct peer *, afi_t, safi_t, u_int32_t,
u_char, int, u_int16_t);
-diff -Nur quagga-0.99.1.ORIG/bgpd/bgp_network.c
quagga-0.99.1/bgpd/bgp_network.c
---- quagga-0.99.1.ORIG/bgpd/bgp_network.c 2005-04-07 09:30:20.000000000
+0200
-+++ quagga-0.99.1/bgpd/bgp_network.c 2005-05-07 06:15:52.841226737 +0200
-@@ -38,6 +38,56 @@
- 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)
-@@ -238,6 +288,12 @@
- 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);
-
-@@ -346,6 +402,10 @@
- continue;
- }
-
-+#ifdef HAVE_TCP_MD5
-+ bm->sock = sock;
-+#endif /* HAVE_TCP_MD5 */
-+
- thread_add_read (master, bgp_accept, bgp, sock);
- }
- while ((ainfo = ainfo->ai_next) != NULL);
-@@ -406,6 +466,9 @@
- close (sock);
- return ret;
- }
-+#ifdef HAVE_TCP_MD5
-+ bm->sock = sock;
-+#endif /* HAVE_TCP_MD5 */
-
- thread_add_read (bm->master, bgp_accept, bgp, sock);
-
-diff -Nur quagga-0.99.1.ORIG/bgpd/bgp_network.h
quagga-0.99.1/bgpd/bgp_network.h
---- quagga-0.99.1.ORIG/bgpd/bgp_network.h 2002-12-13 21:15:29.000000000
+0100
-+++ quagga-0.99.1/bgpd/bgp_network.h 2005-05-07 06:15:52.841226737 +0200
-@@ -21,6 +21,27 @@
- #ifndef _QUAGGA_BGP_NETWORK_H
- #define _QUAGGA_BGP_NETWORK_H
-
-+#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 */
-+
- extern int bgp_socket (struct bgp *, unsigned short);
- extern int bgp_connect (struct peer *);
- extern void bgp_getsockname (struct peer *);
-diff -Nur quagga-0.99.1.ORIG/bgpd/bgp_vty.c quagga-0.99.1/bgpd/bgp_vty.c
---- quagga-0.99.1.ORIG/bgpd/bgp_vty.c 2005-04-09 15:07:47.000000000 +0200
-+++ quagga-0.99.1/bgpd/bgp_vty.c 2005-05-07 06:15:52.903217051 +0200
-@@ -1477,6 +1477,46 @@
- "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",
-@@ -8705,6 +8745,12 @@
- 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);
reverted:
--- quagga-0.99.9/debian/patches/15_ht-bgp-md5__configure.dpatch
+++ quagga-0.99.9.orig/debian/patches/15_ht-bgp-md5__configure.dpatch
@@ -1,39 +0,0 @@
-#! /bin/sh /usr/share/dpatch/dpatch-run
-## 15_ht-20050110-0.98.0-bgp-md5__configure.dpatch by <[EMAIL PROTECTED]>
-##
-## All lines beginning with `## DP:' are a description of the patch.
-## DP: ht-20050110-0.98.0-bgp-md5__configure
-
[EMAIL PROTECTED]@
-
-#
-# Addition to the patch that makes autoreconf unneccessary.
-#
-# FIXME: This is very ugly.
-#
---- old/configure.orig 2007-08-17 00:09:26.000000000 +0200
-+++ new/configure 2007-08-17 00:09:59.000000000 +0200
-@@ -20078,6 +20078,11 @@
-
- fi
-
-+cat >>confdefs.h <<\_ACEOF
-+#define HAVE_TCP_MD5
-+_ACEOF
-+
-+
- { echo "$as_me:$LINENO: checking if zebra should be configurable to send
Route Advertisements" >&5
- echo $ECHO_N "checking if zebra should be configurable to send Route
Advertisements... $ECHO_C" >&6; }
- if test "${enable_rtadv}" != "no"; then
---- old/config.h.in 2005-01-07 15:10:53.000000000 +0100
-+++ new/config.h.in 2005-01-13 03:03:44.000000000 +0100
-@@ -213,6 +213,9 @@
- /* OSPF TE */
- #undef HAVE_OSPF_TE
-
-+/* Linux TCP MD5 Signature Option */
-+#define HAVE_TCP_MD5 1
-+
- /* Have pam_misc.h */
- #undef HAVE_PAM_MISC_H
-
only in patch2:
unchanged:
--- quagga-0.99.9.orig/debian/patches/20_bgp-md5.dpatch
+++ quagga-0.99.9/debian/patches/20_bgp-md5.dpatch
@@ -0,0 +1,635 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 20_bgp-md5.dpatch by Mathias Gug <[EMAIL PROTECTED]>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: This is the patch posted on quagga-devel by Sargun Dhillon,
+## DP: based on previous patches by others.
+## DP: http://marc.info/?l=quagga-dev&m=119356096204723&w=2
+
[EMAIL PROTECTED]@
+diff -urNad quagga-0.99.9~/bgpd/bgp_network.c quagga-0.99.9/bgpd/bgp_network.c
+--- quagga-0.99.9~/bgpd/bgp_network.c 2007-05-09 16:59:33.000000000 -0400
++++ quagga-0.99.9/bgpd/bgp_network.c 2007-11-16 09:08:56.000000000 -0500
+@@ -22,6 +22,7 @@
+
+ #include "thread.h"
+ #include "sockunion.h"
++#include "sockopt.h"
+ #include "memory.h"
+ #include "log.h"
+ #include "if.h"
+@@ -38,6 +39,34 @@
+ extern struct zebra_privs_t bgpd_privs;
+
+
++#if defined(HAVE_TCP_MD5SIG)
++/*
++ * Set MD5 key for the socket, for the given IPv4 peer address.
++ * If the password is NULL or zero-length, the option will be disabled.
++ */
++int
++bgp_md5_set (int sock, struct sockaddr_in *sin, const char *password)
++{
++ int ret, en;
++
++ if ( bgpd_privs.change (ZPRIVS_RAISE) )
++ zlog_err ("bgp_md5_set: could not raise privs");
++
++ ret = sockopt_tcp_signature (sock, sin, password);
++ en = errno;
++
++ if (bgpd_privs.change (ZPRIVS_LOWER) )
++ zlog_err ("bgp_md5_set: could not lower privs");
++
++ if (ret < 0)
++ zlog (NULL, LOG_WARNING, "can't set TCP_MD5SIG option on socket %d: %s",
++ sock, safe_strerror (en));
++
++ return ret;
++}
++
++#endif /* HAVE_TCP_MD5SIG */
++
+ /* Accept bgp connection. */
+ static int
+ bgp_accept (struct thread *thread)
+@@ -238,6 +267,12 @@
+ sockopt_reuseaddr (peer->fd);
+ sockopt_reuseport (peer->fd);
+
++#ifdef HAVE_TCP_MD5SIG
++ if (CHECK_FLAG (peer->flags, PEER_FLAG_PASSWORD))
++ if (sockunion_family (&peer->su) == AF_INET)
++ bgp_md5_set (peer->fd, &peer->su.sin, peer->password);
++#endif /* HAVE_TCP_MD5SIG */
++
+ /* Bind socket. */
+ bgp_bind (peer);
+
+@@ -288,6 +323,10 @@
+ struct addrinfo req;
+ struct addrinfo *ainfo;
+ struct addrinfo *ainfo_save;
++#if defined(HAVE_TCP_MD5SIG) && defined(IPV6_V6ONLY)
++ struct sockaddr_in sin;
++ int socklen, on = 1;
++#endif
+ int sock = 0;
+ char port_str[BUFSIZ];
+
+@@ -323,6 +362,21 @@
+ sockopt_reuseaddr (sock);
+ sockopt_reuseport (sock);
+
++#if defined(HAVE_TCP_MD5SIG) && defined(IPV6_V6ONLY)
++/* We can not apply MD5SIG to an IPv6 socket. If this is an AF_INET6
++ socket, we'll have to create another socket for IPv4*/
++
++ if (ainfo->ai_family == AF_INET6) {
++/* Mark this one for IPv6 only */
++ ret = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
++ (void *) &on, sizeof (on));
++ if( ret < 0 ) {
++ en = errno;
++ zlog_err ("setsockopt V6ONLY: %s", safe_strerror (en));
++ }
++ }
++#endif
++
+ if (bgpd_privs.change (ZPRIVS_RAISE) )
+ zlog_err ("bgp_socket: could not raise privs");
+
+@@ -346,7 +400,65 @@
+ continue;
+ }
+
++#if defined(HAVE_TCP_MD5SIG) && defined(IPV6_V6ONLY)
+ thread_add_read (master, bgp_accept, bgp, sock);
++
++ if (ainfo->ai_family != AF_INET6)
++ continue;
++
++ /* If first socket was an IPv6 socket, we need to create an IPv4
++ socket for use by the TCP_MD5SIG logic. This code is blatently
++ copied and modified from the alternate IPv4 only code from below... */
++
++ sock = socket (AF_INET, SOCK_STREAM, 0);
++ if (sock < 0)
++ {
++ zlog_err ("socket: %s", safe_strerror (errno));
++ continue;
++ }
++
++ sockopt_reuseaddr (sock);
++ sockopt_reuseport (sock);
++
++ memset (&sin, 0, sizeof (struct sockaddr_in));
++
++ sin.sin_family = AF_INET;
++ sin.sin_port = htons (port);
++ socklen = sizeof (struct sockaddr_in);
++#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
++ sin.sin_len = socklen;
++#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
++
++ if ( bgpd_privs.change (ZPRIVS_RAISE) )
++ zlog_err ("bgp_socket: could not raise privs");
++
++ ret = bind (sock, (struct sockaddr *) &sin, socklen);
++ en = errno;
++ if (bgpd_privs.change (ZPRIVS_LOWER) )
++ zlog_err ("bgp_bind_address: could not lower privs");
++
++ if (ret < 0)
++ {
++ zlog_err ("bind: %s", safe_strerror (en));
++ close(sock);
++ continue;
++ }
++
++ ret = listen (sock, 3);
++ if (ret < 0)
++ {
++ zlog_err ("listen: %s", safe_strerror (errno));
++ close (sock);
++ continue;
++ }
++#endif
++
++#ifdef HAVE_TCP_MD5SIG
++ bm->sock = sock;
++#endif /* HAVE_TCP_MD5SIG */
++
++ thread_add_read (master, bgp_accept, bgp, sock);
++
+ }
+ while ((ainfo = ainfo->ai_next) != NULL);
+
+@@ -406,6 +518,9 @@
+ close (sock);
+ return ret;
+ }
++#ifdef HAVE_TCP_MD5SIG
++ bm->sock = sock;
++#endif /* HAVE_TCP_MD5SIG */
+
+ thread_add_read (bm->master, bgp_accept, bgp, sock);
+
+diff -urNad quagga-0.99.9~/bgpd/bgp_network.h quagga-0.99.9/bgpd/bgp_network.h
+--- quagga-0.99.9~/bgpd/bgp_network.h 2007-06-29 09:41:43.000000000 -0400
++++ quagga-0.99.9/bgpd/bgp_network.h 2007-11-16 09:08:56.000000000 -0500
+@@ -21,6 +21,10 @@
+ #ifndef _QUAGGA_BGP_NETWORK_H
+ #define _QUAGGA_BGP_NETWORK_H
+
++#if defined(HAVE_TCP_MD5SIG)
++extern int bgp_md5_set (int, struct sockaddr_in *, const char *);
++#endif /* HAVE_TCP_MD5SIG */
++
+ extern int bgp_socket (struct bgp *, unsigned short);
+ extern int bgp_connect (struct peer *);
+ extern void bgp_getsockname (struct peer *);
+diff -urNad quagga-0.99.9~/bgpd/bgp_vty.c quagga-0.99.9/bgpd/bgp_vty.c
+--- quagga-0.99.9~/bgpd/bgp_vty.c 2007-08-06 11:17:46.000000000 -0400
++++ quagga-0.99.9/bgpd/bgp_vty.c 2007-11-16 09:08:56.000000000 -0500
+@@ -1479,6 +1479,46 @@
+ "AS number used as local AS\n"
+ "Do not prepend local-as to updates from ebgp peers\n")
+
++#ifdef HAVE_TCP_MD5SIG
++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_MD5SIG */
++
+ DEFUN (neighbor_activate,
+ neighbor_activate_cmd,
+ NEIGHBOR_CMD2 "activate",
+@@ -8896,6 +8936,12 @@
+
+ /* "neighbor activate" commands. */
+ install_element (BGP_NODE, &neighbor_activate_cmd);
++
++#ifdef HAVE_TCP_MD5SIG
++ /* "neighbor password" commands. */
++ install_element (BGP_NODE, &neighbor_password_cmd);
++ install_element (BGP_NODE, &no_neighbor_password_cmd);
++#endif /* HAVE_TCP_MD5SIG */
+ install_element (BGP_IPV4_NODE, &neighbor_activate_cmd);
+ install_element (BGP_IPV4M_NODE, &neighbor_activate_cmd);
+ install_element (BGP_IPV6_NODE, &neighbor_activate_cmd);
+diff -urNad quagga-0.99.9~/bgpd/bgpd.c quagga-0.99.9/bgpd/bgpd.c
+--- quagga-0.99.9~/bgpd/bgpd.c 2007-07-25 12:49:06.000000000 -0400
++++ quagga-0.99.9/bgpd/bgpd.c 2007-11-16 09:08:56.000000000 -0500
+@@ -788,6 +788,7 @@
+ peer->status = Idle;
+ peer->ostatus = Idle;
+ peer->weight = 0;
++ peer->password = NULL;
+ peer->bgp = bgp;
+ peer = peer_lock (peer); /* initial reference */
+
+@@ -1202,6 +1203,20 @@
+ peer->last_reset = PEER_DOWN_NEIGHBOR_DELETE;
+ bgp_stop (peer);
+ bgp_fsm_change_status (peer, Deleted);
++
++#ifdef HAVE_TCP_MD5SIG
++ /* Password configuration */
++ if (peer->password)
++ {
++ free (peer->password);
++ peer->password = NULL;
++
++ if (! CHECK_FLAG (peer->sflags, PEER_STATUS_GROUP)
++ && sockunion_family (&peer->su) == AF_INET)
++ bgp_md5_set (bm->sock, &peer->su.sin, NULL);
++ }
++#endif /* HAVE_TCP_MD5SIG */
++
+ bgp_timer_set (peer); /* stops all timers for Deleted */
+
+ /* Delete from all peer list. */
+@@ -1417,6 +1432,27 @@
+ else
+ peer->v_routeadv = BGP_DEFAULT_EBGP_ROUTEADV;
+
++#ifdef HAVE_TCP_MD5SIG
++ /* 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->su.sin, peer->password);
++ }
++ else if (peer->password)
++ {
++ free (peer->password);
++ peer->password = NULL;
++
++ if (sockunion_family (&peer->su) == AF_INET)
++ bgp_md5_set (bm->sock, &peer->su.sin, NULL);
++ }
++#endif /* HAVE_TCP_MD5SIG */
++
+ /* maximum-prefix */
+ peer->pmax[afi][safi] = conf->pmax[afi][safi];
+ peer->pmax_threshold[afi][safi] = conf->pmax_threshold[afi][safi];
+@@ -3379,6 +3415,125 @@
+ return 0;
+ }
+
++#ifdef HAVE_TCP_MD5SIG
++/* Set password for authenticating with the peer. */
++int
++peer_password_set (struct peer *peer, const char *password)
++{
++ struct peer_group *group;
++ struct listnode *nn, *nnode;
++ int len = password ? strlen(password) : 0;
++
++ if ((len < PEER_PASSWORD_MINLEN) || (len > PEER_PASSWORD_MAXLEN))
++ return BGP_ERR_INVALID_VALUE;
++
++ 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->su.sin, peer->password);
++ return 0;
++ }
++
++ group = peer->group;
++ /* #42# LIST_LOOP (group->peer, peer, nn) */
++ for (ALL_LIST_ELEMENTS (group->peer, nn, nnode, peer))
++ {
++ 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->su.sin, peer->password);
++ }
++
++ return 0;
++}
++
++int
++peer_password_unset (struct peer *peer)
++{
++ struct peer_group *group;
++ struct listnode *nn, *nnode;
++
++ 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_set (bm->sock, &peer->su.sin, NULL);
++
++ 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;
++ /* #42# LIST_LOOP (group->peer, peer, nn) */
++ for (ALL_LIST_ELEMENTS (group->peer, nn, nnode, peer))
++ {
++ 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_set (bm->sock, &peer->su.sin, NULL);
++
++ UNSET_FLAG (peer->flags, PEER_FLAG_PASSWORD);
++ if (peer->password)
++ free (peer->password);
++ peer->password = NULL;
++ }
++
++ return 0;
++}
++#endif /* HAVE_TCP_MD5SIG */
++
+ /* Set distribute list to the peer. */
+ int
+ peer_distribute_set (struct peer *peer, afi_t afi, safi_t safi, int direct,
+@@ -4416,6 +4571,16 @@
+ ! CHECK_FLAG (g_peer->flags, PEER_FLAG_SHUTDOWN))
+ vty_out (vty, " neighbor %s shutdown%s", addr, VTY_NEWLINE);
+
++#ifdef HAVE_TCP_MD5SIG
++ /* 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_MD5SIG */
++
+ /* BGP port. */
+ if (peer->port != BGP_PORT_DEFAULT)
+ vty_out (vty, " neighbor %s port %d%s", addr, peer->port,
+@@ -4951,6 +5116,9 @@
+ bm->port = BGP_PORT_DEFAULT;
+ bm->master = thread_master_create ();
+ bm->start_time = time (NULL);
++#ifdef HAVE_TCP_MD5SIG
++ bm->sock = -1;
++#endif /* HAVE_TCP_MD5SIG */
+ }
+
+
+diff -urNad quagga-0.99.9~/bgpd/bgpd.h quagga-0.99.9/bgpd/bgpd.h
+--- quagga-0.99.9~/bgpd/bgpd.h 2007-08-06 11:22:43.000000000 -0400
++++ quagga-0.99.9/bgpd/bgpd.h 2007-11-16 09:08:56.000000000 -0500
+@@ -54,6 +54,11 @@
+ #define BGP_OPT_CONFIG_CISCO (1 << 2)
+ };
+
++#ifdef HAVE_TCP_MD5SIG
++ /* bgp receive socket */
++ int sock;
++#endif /* HAVE_TCP_MD5SIG */
++
+ /* BGP instance structure. */
+ struct bgp
+ {
+@@ -355,6 +360,7 @@
+ #define PEER_FLAG_SEND_COMMUNITY (1 << 0) /* send-community */
+ #define PEER_FLAG_SEND_EXT_COMMUNITY (1 << 1) /* send-community ext. */
+ #define PEER_FLAG_NEXTHOP_SELF (1 << 2) /* next-hop-self */
++#define PEER_FLAG_PASSWORD (1 << 9) /* password */
+ #define PEER_FLAG_REFLECTOR_CLIENT (1 << 3) /* reflector-client */
+ #define PEER_FLAG_RSERVER_CLIENT (1 << 4) /* route-server-client */
+ #define PEER_FLAG_SOFT_RECONFIG (1 << 5) /* soft-reconfiguration
*/
+@@ -376,6 +382,9 @@
+ char *name;
+ struct route_map *map;
+ } default_rmap[AFI_MAX][SAFI_MAX];
++ /* MD5 password */
++ char *password;
++
+
+ /* Peer status flags. */
+ u_int16_t sflags;
+@@ -531,6 +540,13 @@
+ {
+ /* AFI. */
+ afi_t afi;
++#if defined(HAVE_TCP_MD5SIG)
++
++#define PEER_PASSWORD_MINLEN (1)
++#define PEER_PASSWORD_MAXLEN (80)
++
++#endif /* HAVE_TCP_MD5SIG */
++
+
+ /* SAFI. */
+ safi_t safi;
+@@ -921,6 +937,11 @@
+ extern int peer_clear (struct peer *);
+ extern int peer_clear_soft (struct peer *, afi_t, safi_t, enum
bgp_clear_type);
+
++#ifdef HAVE_TCP_MD5SIG
++extern int peer_password_set (struct peer *, const char *);
++extern int peer_password_unset (struct peer *);
++#endif /* HAVE_TCP_MD5SIG */
++
+ extern void peer_nsf_stop (struct peer *);
+
+ #endif /* _QUAGGA_BGPD_H */
+diff -urNad quagga-0.99.9~/configure.ac quagga-0.99.9/configure.ac
+--- quagga-0.99.9~/configure.ac 2007-09-07 12:54:01.000000000 -0400
++++ quagga-0.99.9/configure.ac 2007-11-16 09:08:56.000000000 -0500
+@@ -211,6 +211,8 @@
+ [ --with-libpam use libpam for PAM support in vtysh])
+ AC_ARG_ENABLE(tcp-zebra,
+ [ --enable-tcp-zebra enable TCP/IP socket connection between zebra and
protocol daemon])
++AC_ARG_ENABLE(tcp-md5,
++[ --enable-tcp-md5 enable TCP/IP md5 in BGPd])
+ AC_ARG_ENABLE(opaque-lsa,
+ [ --enable-opaque-lsa enable OSPF Opaque-LSA with OSPFAPI support
(RFC2370)])
+ AC_ARG_ENABLE(ospfapi,
+@@ -281,6 +283,7 @@
+ AC_DEFINE(HAVE_TCP_ZEBRA,,Use TCP for zebra communication)
+ fi
+
++
+ if test "${enable_opaque_lsa}" = "yes"; then
+ AC_DEFINE(HAVE_OPAQUE_LSA,,OSPF Opaque LSA)
+ fi
+@@ -528,6 +531,12 @@
+ ;;
+ esac
+
++if test "${enable_tcp_md5}" = "yes"; then
++ if test x"$opsys" = x"gnu-linux"; then
++ AC_DEFINE(HAVE_TCP_MD5SIG,1,Enable TCP Signing)
++ fi
++fi
++
+ dnl ---------------------
+ dnl Integrated VTY option
+ dnl ---------------------
+diff -urNad quagga-0.99.9~/lib/sockopt.c quagga-0.99.9/lib/sockopt.c
+--- quagga-0.99.9~/lib/sockopt.c 2007-08-22 12:22:54.000000000 -0400
++++ quagga-0.99.9/lib/sockopt.c 2007-11-16 09:08:56.000000000 -0500
+@@ -480,3 +480,36 @@
+
+ iph->ip_id = ntohs(iph->ip_id);
+ }
++
++#if defined(HAVE_TCP_MD5SIG)
++int
++sockopt_tcp_signature (int sock, struct sockaddr_in *sin, const char
*password)
++{
++ int keylen = password ? strlen(password) : 0;
++
++#if defined(GNU_LINUX)
++
++ struct tcp_md5sig md5sig;
++
++ bzero ((char *)&md5sig, sizeof(md5sig));
++ memcpy (&md5sig.tcpm_addr, sin, sizeof(*sin));
++ md5sig.tcpm_keylen = keylen;
++ if (keylen)
++ memcpy (md5sig.tcpm_key, password, keylen);
++
++ return setsockopt (sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof md5sig);
++
++#else /* !GNU_LINUX */
++
++ int enable = keylen ? (TCP_SIG_SPI_BASE + sin->sin_port) : 0;
++
++ /*
++ * XXX Need to do PF_KEY operation here to add/remove an SA entry,
++ * and add/remove an SP entry for this peer's packet flows also.
++ */
++ return setsockopt (sock, IPPROTO_TCP, TCP_MD5SIG, &enable,
++ sizeof(enable));
++
++#endif /* !GNU_LINUX */
++}
++#endif /* HAVE_TCP_MD5SIG */
+diff -urNad quagga-0.99.9~/lib/sockopt.h quagga-0.99.9/lib/sockopt.h
+--- quagga-0.99.9~/lib/sockopt.h 2007-08-22 12:22:54.000000000 -0400
++++ quagga-0.99.9/lib/sockopt.h 2007-11-16 09:08:56.000000000 -0500
+@@ -98,4 +98,32 @@
+ extern void sockopt_iphdrincl_swab_htosys (struct ip *iph);
+ extern void sockopt_iphdrincl_swab_systoh (struct ip *iph);
+
++#if defined(HAVE_TCP_MD5SIG)
++
++#if defined(GNU_LINUX) && !defined(TCP_MD5SIG)
++
++/* XXX these will come from <linux/tcp.h> eventually */
++
++#define TCP_MD5SIG 14
++#define TCP_MD5SIG_MAXKEYLEN 80
++
++struct tcp_md5sig {
++ struct sockaddr_storage tcpm_addr; /* address associated */
++ __u16 __tcpm_pad1; /* zero */
++ __u16 tcpm_keylen; /* key length */
++ __u32 __tcpm_pad2; /* zero */
++ __u8 tcpm_key[TCP_MD5SIG_MAXKEYLEN]; /* key (binary) */
++};
++
++#endif /* defined(GNU_LINUX) && !defined(TCP_MD5SIG) */
++
++#if !defined(GNU_LINUX) && !defined(TCP_SIG_SPI_BASE)
++#define TCP_SIG_SPI_BASE 1000 /* XXX this will go away */
++#endif
++
++extern int sockopt_tcp_signature(int sock, struct sockaddr_in *sin,
++ const char *password);
++
++#endif /* HAVE_TCP_MD5SIG */
++
+ #endif /*_ZEBRA_SOCKOPT_H */