summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_network.c
diff options
context:
space:
mode:
authorMichael H. Warfield <mhw@WittsEnd.com>2008-04-15 21:49:45 +0000
committerTom Grennan <tgrennan@vyatta.com>2008-04-15 21:59:57 +0000
commit4c9782da0f5484e52a00bb769813b5988e857c38 (patch)
tree4cea02479b67f00728724727a6c001e05f25a4a3 /bgpd/bgp_network.c
parentc1bdabf8dd2f22a33fdc35b70b93e871f179445d (diff)
downloadquagga-4c9782da0f5484e52a00bb769813b5988e857c38.tar.bz2
quagga-4c9782da0f5484e52a00bb769813b5988e857c38.tar.xz
TCP MD5SIG patch
from http://www.gossamer-threads.com/lists/quagga/dev/15611 [clear_shim] Re: [quagga-users 9315] New md5 signature patch for bgp... quagga_md5_bsd_linux_v9.diff Remove Highlighting [In reply to] mhw at wittsend ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Jan 28, 2008, 12:55 PM And, of course, the moment I send off a patch against 0.99.9 and claim it should patch the CVS, I find out it does not. Post #2 of 3 (192 views) On Mon, 2008-01-28 at 14:50 -0500, Michael H. Warfield wrote: Permalink > Hello all! > Building on the efforts of Leigh Brown and the earlier works on an MD5 > signature patch for bgpd, I've incorporated the autoconf efforts by > Sargun Dhillon on top of my own changes for IPv6 along with filling in a > few missing spots in the autoconf stuff myself. Leigh had released a v7 > and I subsequently released a v8 patch for md5 signatures for Linux and > BSD to deal with conflicts with IPv6. This is now a v9 patch > incorporating some of the changes from Sargun and adding a few of my own > to complete the autoconf changes. > This patch is still against 0.99.9 but should patch cleanly against > CVS. Attached is the patch against CVS. It does NOT have a patch for config.h.in (that was a mistake on my part, it's not in CVS, it's generated but it's not regenerated if you are working from the releases and don't rerun autoheader) and fixes a problem with a header file and some alignments. [cl] > This adds a configure option, --enable-tcp-md5, to enable tcp md5 [cl] > signatures. This is not qualified against the operating system on which > it is being built. The patch should work on BSD and Linux. Other > operation systems are a crap shoot. I don't know. I presume some other > errors will occur on other operating systems which do not support MD5 > signatures in this manner. Since they're not supported now, this is no > great loss. Someone might want to test this in other environments, > though, and enhance it for those other environments. > > Attached... > > quagga_md5_bsd_linux_v9.diff > > http://www.wittsend.com/mhw/md5sig/quagga_md5_bsd_linux_v9.diff > > Is there anything left that needs to be done before this can be > committed to CVS? Can someone with commit privs please do the honors? Mike -- Michael H. Warfield (AI4NB) | (770) 985-6132 | mhw[at]WittsEnd.com /\/\|=mhw=|\/\/ | (678) 463-0932 | http://www.wittsend.com/mhw/ NIC whois: MHW9 | An optimist believes we live in the best of all PGP Key: 0xDF1DD471 | possible worlds. A pessimist is sure of it! Attachments: [unknown] quagga_cvs_md5_bsd_linux_v9.diff (18.4 KB) <http://www.gossamer-threads.com/lists/engine?do=post_attachment;postatt_id=1184;list=quagga> [unknown] signature.asc (0.30 KB) <http://www.gossamer-threads.com/lists/engine?do=post_attachment;postatt_id=1185;list=quagga> Signed-off-by: Tom Grennan <tgrennan@vyatta.com>
Diffstat (limited to 'bgpd/bgp_network.c')
-rw-r--r--bgpd/bgp_network.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 8452545d..4289ce20 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -22,6 +22,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "thread.h"
#include "sockunion.h"
+#include "sockopt.h"
#include "memory.h"
#include "log.h"
#include "if.h"
@@ -38,6 +39,34 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
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 @@ bgp_connect (struct peer *peer)
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 @@ bgp_socket (struct bgp *bgp, unsigned short port, char *address)
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 @@ bgp_socket (struct bgp *bgp, unsigned short port, char *address)
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 @@ bgp_socket (struct bgp *bgp, unsigned short port, char *address)
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);
@@ -413,6 +525,9 @@ bgp_socket (struct bgp *bgp, unsigned short port, char *address)
close (sock);
return ret;
}
+#ifdef HAVE_TCP_MD5SIG
+ bm->sock = sock;
+#endif /* HAVE_TCP_MD5SIG */
thread_add_read (bm->master, bgp_accept, bgp, sock);