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 */

Reply via email to