summaryrefslogtreecommitdiffstats
path: root/bgpd/bgp_network.c
diff options
context:
space:
mode:
Diffstat (limited to 'bgpd/bgp_network.c')
-rw-r--r--bgpd/bgp_network.c158
1 files changed, 61 insertions, 97 deletions
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index e981e718..87f7f7b6 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -29,6 +29,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
#include "prefix.h"
#include "command.h"
#include "privs.h"
+#include "linklist.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_fsm.h"
@@ -39,33 +40,70 @@ 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)
+static int
+bgp_md5_set_socket (int socket, union sockunion *su, 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);
+ int ret = -1;
+ int en = ENOSYS;
+
+ assert (socket >= 0);
+
+#if HAVE_DECL_TCP_MD5SIG
+ ret = sockopt_tcp_signature (socket, su, password);
en = errno;
-
- if (bgpd_privs.change (ZPRIVS_LOWER) )
- zlog_err ("bgp_md5_set: could not lower privs");
-
+#endif /* HAVE_TCP_MD5SIG */
+
if (ret < 0)
zlog (NULL, LOG_WARNING, "can't set TCP_MD5SIG option on socket %d: %s",
- sock, safe_strerror (en));
+ 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;
+
+ /* 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;
+ }
+ return fret;
+}
/* Accept bgp connection. */
static int
@@ -266,17 +304,14 @@ bgp_connect (struct peer *peer)
sockopt_reuseaddr (peer->fd);
sockopt_reuseport (peer->fd);
-
+
#ifdef IPTOS_PREC_INTERNETCONTROL
if (sockunion_family (&peer->su) == AF_INET)
setsockopt_ipv4_tos (peer->fd, IPTOS_PREC_INTERNETCONTROL);
#endif
-#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 */
+ if (peer->password)
+ bgp_md5_set_connect (peer->fd, &peer->su, peer->password);
/* Bind socket. */
bgp_bind (peer);
@@ -328,10 +363,6 @@ 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];
@@ -372,18 +403,12 @@ bgp_socket (struct bgp *bgp, unsigned short port, char *address)
setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
#endif
-#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*/
-
+#ifdef IPV6_V6ONLY
+ /* Want only IPV6 on ipv6 socket (not mapped addresses) */
if (ainfo->ai_family == AF_INET6) {
-/* Mark this one for IPv6 only */
- ret = setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ int on = 1;
+ setsockopt (sock, IPPROTO_IPV6, IPV6_V6ONLY,
(void *) &on, sizeof (on));
- if( ret < 0 ) {
- en = errno;
- zlog_err ("setsockopt V6ONLY: %s", safe_strerror (en));
- }
}
#endif
@@ -409,67 +434,9 @@ bgp_socket (struct bgp *bgp, unsigned short port, char *address)
close (sock);
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);
- setsockopt_ipv4_tos (sock, IPTOS_PREC_INTERNETCONTROL);
-
- 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 */
-
+
+ listnode_add (bm->listen_sockets, (void *)sock);
thread_add_read (master, bgp_accept, bgp, sock);
-
}
while ((ainfo = ainfo->ai_next) != NULL);
@@ -540,9 +507,6 @@ 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);