summaryrefslogtreecommitdiff
path: root/lib/sockopt.c
diff options
context:
space:
mode:
authorPaul Jakma <paul.jakma@sun.com>2008-07-21 21:02:49 +0000
committerPaul Jakma <paul.jakma@sun.com>2008-07-21 21:02:49 +0000
commit0df7c91f048f2116610d6bdfce3ab6cad1981802 (patch)
tree18390aa845054b757fae86dde49b907ee7f14908 /lib/sockopt.c
parentf04b0e6bb8c1339243717b156880d7e24c84c951 (diff)
[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.
Diffstat (limited to 'lib/sockopt.c')
-rw-r--r--lib/sockopt.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/lib/sockopt.c b/lib/sockopt.c
index f8fa946e..a2038a5c 100644
--- a/lib/sockopt.c
+++ b/lib/sockopt.c
@@ -22,6 +22,7 @@
#include <zebra.h>
#include "log.h"
#include "sockopt.h"
+#include "sockunion.h"
int
setsockopt_so_recvbuf (int sock, int size)
@@ -480,3 +481,70 @@ sockopt_iphdrincl_swab_systoh (struct ip *iph)
iph->ip_id = ntohs(iph->ip_id);
}
+
+int
+sockopt_tcp_signature (int sock, union sockunion *su, const char *password)
+{
+#if HAVE_DECL_TCP_MD5SIG
+#ifndef GNU_LINUX
+ /*
+ * 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.
+ */
+ int md5sig = password && *password ? 1 : 0;
+#else
+ int keylen = password ? strlen (password) : 0;
+ struct tcp_md5sig md5sig;
+ union sockunion *su2, *susock;
+ int ret;
+
+ /* Figure out whether the socket and the sockunion are the same family..
+ * adding AF_INET to AF_INET6 needs to be v4 mapped, you'd think..
+ */
+ if (!(susock = sockunion_getsockname (sock)))
+ return -1;
+
+ if (susock->sa.sa_family == su->sa.sa_family)
+ su2 = su;
+ else
+ {
+ /* oops.. */
+ su2 = susock;
+
+ if (su2->sa.sa_family == AF_INET)
+ {
+ sockunion_free (susock);
+ return -1;
+ };
+
+ /* If this does not work, then all users of this sockopt will need to
+ * differentiate between IPv4 and IPv6, and keep seperate sockets for
+ * each.
+ *
+ * Sadly, it doesn't seem to work at present. It's unknown whether
+ * this is a bug or not.
+ */
+ if (su2->sa.sa_family == AF_INET6
+ && su->sa.sa_family == AF_INET)
+ {
+ su2->sin6.sin6_family = AF_INET6;
+ /* V4Map the address */
+ memset (&su2->sin6.sin6_addr, 0, sizeof (struct in6_addr));
+ su2->sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
+ memcpy (&su2->sin6.sin6_addr.s6_addr32[3], &su->sin.sin_addr, 4);
+ }
+ }
+
+ memset (&md5sig, 0, sizeof (md5sig));
+ memcpy (&md5sig.tcpm_addr, su2, sizeof (*su2));
+ md5sig.tcpm_keylen = keylen;
+ if (keylen)
+ memcpy (md5sig.tcpm_key, password, keylen);
+#endif /* GNU_LINUX */
+ ret = setsockopt (sock, IPPROTO_TCP, TCP_MD5SIG, &md5sig, sizeof md5sig);
+ sockunion_free (susock);
+ return ret;
+#else /* HAVE_TCP_MD5SIG */
+ return -2;
+#endif /* HAVE_TCP_MD5SIG */
+}