diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/ChangeLog | 11 | ||||
-rw-r--r-- | lib/memtypes.c | 1 | ||||
-rw-r--r-- | lib/sockopt.c | 68 | ||||
-rw-r--r-- | lib/sockopt.h | 4 | ||||
-rw-r--r-- | lib/sockunion.c | 8 |
5 files changed, 90 insertions, 2 deletions
diff --git a/lib/ChangeLog b/lib/ChangeLog index 681bdebc..688c44f7 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,14 @@ +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. + 2008-06-07 Paul Jakma <paul@jakma.org> * stream.{c,h}: (stream_{put,write}) add const qualifier to source diff --git a/lib/memtypes.c b/lib/memtypes.c index f1b10e71..dd365ddb 100644 --- a/lib/memtypes.c +++ b/lib/memtypes.c @@ -95,6 +95,7 @@ struct memory_list memory_list_bgp[] = { MTYPE_BGP_PEER_HOST, "BGP peer hostname" }, { MTYPE_PEER_GROUP, "Peer group" }, { MTYPE_PEER_DESC, "Peer description" }, + { MTYPE_PEER_PASSWORD, "Peer password string" }, { MTYPE_ATTR, "BGP attribute" }, { MTYPE_ATTR_EXTRA, "BGP extra attributes" }, { MTYPE_AS_PATH, "BGP aspath" }, 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 */ +} diff --git a/lib/sockopt.h b/lib/sockopt.h index ebb71430..95382792 100644 --- a/lib/sockopt.h +++ b/lib/sockopt.h @@ -22,6 +22,8 @@ #ifndef _ZEBRA_SOCKOPT_H #define _ZEBRA_SOCKOPT_H +#include "sockunion.h" + extern int setsockopt_so_recvbuf (int sock, int size); extern int setsockopt_so_sendbuf (const int sock, int size); extern int getsockopt_so_sendbuf (const int sock); @@ -98,4 +100,6 @@ extern int getsockopt_ifindex (int, struct msghdr *); extern void sockopt_iphdrincl_swab_htosys (struct ip *iph); extern void sockopt_iphdrincl_swab_systoh (struct ip *iph); +extern int sockopt_tcp_signature(int sock, union sockunion *su, + const char *password); #endif /*_ZEBRA_SOCKOPT_H */ diff --git a/lib/sockunion.c b/lib/sockunion.c index 7721666e..cfd3bf9a 100644 --- a/lib/sockunion.c +++ b/lib/sockunion.c @@ -254,6 +254,7 @@ sockunion_accept (int sock, union sockunion *su) client_sock = accept (sock, (struct sockaddr *) su, &len); /* Convert IPv4 compatible IPv6 address to IPv4 address. */ +#if 0 #ifdef HAVE_IPV6 if (su->sa.sa_family == AF_INET6) { @@ -268,7 +269,7 @@ sockunion_accept (int sock, union sockunion *su) } } #endif /* HAVE_IPV6 */ - +#endif return client_sock; } @@ -592,6 +593,7 @@ sockunion_getsockname (int fd) su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion)); memcpy (su, &name, sizeof (struct sockaddr_in6)); +#if 0 if (IN6_IS_ADDR_V4MAPPED (&su->sin6.sin6_addr)) { struct sockaddr_in sin; @@ -601,6 +603,7 @@ sockunion_getsockname (int fd) sin.sin_port = su->sin6.sin6_port; memcpy (su, &sin, sizeof (struct sockaddr_in)); } +#endif return su; } #endif /* HAVE_IPV6 */ @@ -645,7 +648,7 @@ sockunion_getpeername (int fd) { su = XCALLOC (MTYPE_SOCKUNION, sizeof (union sockunion)); memcpy (su, &name, sizeof (struct sockaddr_in6)); - +#if 0 if (IN6_IS_ADDR_V4MAPPED (&su->sin6.sin6_addr)) { struct sockaddr_in sin; @@ -655,6 +658,7 @@ sockunion_getpeername (int fd) sin.sin_port = su->sin6.sin6_port; memcpy (su, &sin, sizeof (struct sockaddr_in)); } +#endif return su; } #endif /* HAVE_IPV6 */ |