summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/ChangeLog11
-rw-r--r--lib/memtypes.c1
-rw-r--r--lib/sockopt.c68
-rw-r--r--lib/sockopt.h4
-rw-r--r--lib/sockunion.c8
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 */