[bgpd] TCP-MD5: password vty configuration and initial Linux support
2008-07-21 Paul Jakma <paul.jakma@sun.com>
* bgp_packet.c: (bgp_open_receive) fix warning in a zlog call
* bgp_vty.c: (bgp_vty_return) add return code
* bgpd.c: (bgp_master_init) setup the socket list.
* bgp_network.c: Remove the dual IPv4/6 socket thing for now, which
was implemented by Michael, until such time as its clear its
required for Linux (see sockopt comments). IPv6 support, including
IPv4 sessions on AF_INET6 sockets, therefore is broken, and the
'-l 0.0.0.0' arguments would need to be given to bgpd to make
things work here.
2008-07-21 Michael H. Warfield <mhw@wittsend.com>
YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Tomohiko Kusuda <kusuda@inetcore.com>
Leigh Brown <leigh@solinno.co.uk>
* bgp_network.c: (bgp_md5_set_one) shim between libzebra tcp-md5
sockopt and bgpd.
(bgp_md5_set_socket) Helper for bgp_connect
(bgp_md5_set) setup TCP-MD5SIG for the given peer.
(bgp_connect) call out to bgp_md5_set_socket for the outgoing
connect socket.
(bgp_socket) save references to the listen sockets, needed if
TCP-MD5SIG is applied later or changed.
* bgp_vty.c: (*neighbor_password_cmd) New 'neighbor ... password'
commands.
* bgpd.c: (peer_{new,delete) manage TCP-MD5 password
(peer_group2peer_config_copy) inherit TCP-MD5 password
(peer_password_{un,}set) orchestrate the whole add/remove of TCP-MD5
passwords: applying checks, stopping peers, and trying to return
errors to UI, etc.
(bgp_config_write_peer) save password.
Fix missing newline in writeout of neighbor ... port.
2008-07-21 Paul Jakma <paul.jakma@sun.com>
* sockunion.c: ifdef out various places that converted
v4mapped sockets to pure v4. Doesn't seem necessary at all,
presumably a workaround for now historical inet_ntop bugs (?)
2008-07-21 Michael H. Warfield <mhw@wittsend.com>
YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
* sockopt.{c,h}: (sockopt_tcp_signature) Add TCP-MD5SIG support.
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index 8452545..71f3ec7 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -22,12 +22,14 @@
#include "thread.h"
#include "sockunion.h"
+#include "sockopt.h"
#include "memory.h"
#include "log.h"
#include "if.h"
#include "prefix.h"
#include "command.h"
#include "privs.h"
+#include "linklist.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_fsm.h"
@@ -38,6 +40,80 @@
extern struct zebra_privs_t bgpd_privs;
+/*
+ * 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.
+ */
+static int
+bgp_md5_set_socket (int socket, union sockunion *su, const char *password)
+{
+ int ret = -1;
+ int en = ENOSYS;
+
+ assert (socket >= 0);
+
+#if HAVE_DECL_TCP_MD5SIG
+ ret = sockopt_tcp_signature (socket, su, password);
+ en = errno;
+#endif /* HAVE_TCP_MD5SIG */
+
+ if (ret < 0)
+ zlog (NULL, LOG_WARNING, "can't set TCP_MD5SIG option on socket %d: %s",
+ socket, safe_strerror (en));
+
+ return ret;
+}
+
+/* Helper for bgp_connect */
+static int
+bgp_md5_set_connect (int socket, union sockunion *su, const char *password)
+{
+ int ret = -1;
+
+#if HAVE_DECL_TCP_MD5SIG
+ if ( bgpd_privs.change (ZPRIVS_RAISE) )
+ {
+ zlog_err ("%s: could not raise privs", __func__);
+ return ret;
+ }
+
+ ret = bgp_md5_set_socket (socket, su, password);
+
+ if (bgpd_privs.change (ZPRIVS_LOWER) )
+ zlog_err ("%s: could not lower privs", __func__);
+#endif /* HAVE_TCP_MD5SIG */
+
+ return ret;
+}
+
+int
+bgp_md5_set (struct peer *peer)
+{
+ struct listnode *node;
+ int fret = 0, ret;
+ int *socket;
+
+ if ( bgpd_privs.change (ZPRIVS_RAISE) )
+ {
+ zlog_err ("%s: could not raise privs", __func__);
+ return -1;
+ }
+
+ /* Just set the password on the listen socket(s). Outbound connections
+ * are taken care of in bgp_connect() below.
+ */
+ for (ALL_LIST_ELEMENTS_RO(bm->listen_sockets, node, socket))
+ {
+ ret = bgp_md5_set_socket ((int )socket, &peer->su, peer->password);
+ if (ret < 0)
+ fret = ret;
+ }
+ if (bgpd_privs.change (ZPRIVS_LOWER) )
+ zlog_err ("%s: could not lower privs", __func__);
+
+ return fret;
+}
+
/* Accept bgp connection. */
static int
bgp_accept (struct thread *thread)
@@ -237,6 +313,9 @@
sockopt_reuseaddr (peer->fd);
sockopt_reuseport (peer->fd);
+
+ if (peer->password)
+ bgp_md5_set_connect (peer->fd, &peer->su, peer->password);
/* Bind socket. */
bgp_bind (peer);
@@ -345,7 +424,8 @@
close (sock);
continue;
}
-
+
+ listnode_add (bm->listen_sockets, (void *)sock);
thread_add_read (master, bgp_accept, bgp, sock);
}
while ((ainfo = ainfo->ai_next) != NULL);