From 0eaaeb664b7f66e389f1c626befa28d777fe8e65 Mon Sep 17 00:00:00 2001 From: paul Date: Mon, 21 Jul 2008 21:02:49 +0000 Subject: [bgpd] TCP-MD5: password vty configuration and initial Linux support 2008-07-21 Paul Jakma * 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 YOSHIFUJI Hideaki Tomohiko Kusuda Leigh Brown * 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 * 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 YOSHIFUJI Hideaki * sockopt.{c,h}: (sockopt_tcp_signature) Add TCP-MD5SIG support. --- lib/sockopt.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'lib/sockopt.c') 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 #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 */ +} -- cgit v1.2.3