aboutsummaryrefslogtreecommitdiffstats
path: root/camel/camel-tcp-stream-openssl.c
diff options
context:
space:
mode:
Diffstat (limited to 'camel/camel-tcp-stream-openssl.c')
-rw-r--r--camel/camel-tcp-stream-openssl.c103
1 files changed, 81 insertions, 22 deletions
diff --git a/camel/camel-tcp-stream-openssl.c b/camel/camel-tcp-stream-openssl.c
index 06d1a93c5a..324e58dd08 100644
--- a/camel/camel-tcp-stream-openssl.c
+++ b/camel/camel-tcp-stream-openssl.c
@@ -455,12 +455,15 @@ stream_close (CamelStream *stream)
static int
socket_connect (struct hostent *h, int port)
{
+#ifdef ENABLE_IPv6
+ struct sockaddr_in6 sin6;
+#endif
struct sockaddr_in sin;
- int fd;
- int ret;
- socklen_t len;
+ struct sockaddr *saddr;
struct timeval tv;
+ socklen_t len;
int cancel_fd;
+ int ret, fd;
/* see if we're cancelled yet */
if (camel_operation_cancel_check (NULL)) {
@@ -469,15 +472,29 @@ socket_connect (struct hostent *h, int port)
}
/* setup connect, we do it using a nonblocking socket so we can poll it */
- sin.sin_port = htons (port);
- sin.sin_family = h->h_addrtype;
- memcpy (&sin.sin_addr, h->h_addr, sizeof (sin.sin_addr));
+#ifdef ENABLE_IPv6
+ if (h->h_addrtype == AF_INET6) {
+ sin6.sin6_port = htons (port);
+ sin6.sin6_family = h->h_addrtype;
+ memcpy (&sin6.sin6_addr, h->h_addr, sizeof (sin6.sin6_addr));
+ saddr = (struct sockaddr *) &sin6;
+ len = sizeof (sin6);
+ } else {
+#endif
+ sin.sin_port = htons (port);
+ sin.sin_family = h->h_addrtype;
+ memcpy (&sin.sin_addr, h->h_addr, sizeof (sin.sin_addr));
+ saddr = (struct sockaddr *) &sin;
+ len = sizeof (sin);
+#ifdef ENABLE_IPv6
+ }
+#endif
fd = socket (h->h_addrtype, SOCK_STREAM, 0);
cancel_fd = camel_operation_cancel_fd (NULL);
if (cancel_fd == -1) {
- ret = connect (fd, (struct sockaddr *)&sin, sizeof (sin));
+ ret = connect (fd, saddr, len);
if (ret == -1) {
close (fd);
return -1;
@@ -491,7 +508,7 @@ socket_connect (struct hostent *h, int port)
flags = fcntl (fd, F_GETFL);
fcntl (fd, F_SETFL, flags | O_NONBLOCK);
- ret = connect (fd, (struct sockaddr *)&sin, sizeof (sin));
+ ret = connect (fd, saddr, len);
if (ret == 0) {
fcntl (fd, F_SETFL, flags);
return fd;
@@ -862,32 +879,74 @@ stream_setsockopt (CamelTcpStream *stream, const CamelSockOptData *data)
sizeof (data->value));
}
+#ifdef ENABLE_IPv6
+#define MIN_SOCKADDR_BUFLEN (sizeof (struct sockaddr_in6))
+#else
+#define MIN_SOCKADDR_BUFLEN (sizeof (struct sockaddr_in))
+#endif
+
static CamelTcpAddress *
stream_get_local_address (CamelTcpStream *stream)
{
- struct sockaddr_in sin;
+ unsigned char buf[MIN_SOCKADDR_BUFLEN];
+#ifdef ENABLE_IPv6
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) buf;
+#endif
+ struct sockaddr_in *sin = (struct sockaddr_in *) buf;
+ struct sockaddr *saddr = (struct sockaddr *) buf;
+ gpointer address;
socklen_t len;
-
- if (getsockname (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd,
- (struct sockaddr *)&sin, &len) == -1)
+ int family;
+
+ len = MIN_SOCKADDR_BUFLEN;
+
+ if (getsockname (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd, saddr, &len) == -1)
return NULL;
-
- return camel_tcp_address_new (CAMEL_TCP_ADDRESS_IPV4, sin.sin_port,
- 4, &sin.sin_addr);
+
+ if (saddr->sa_family == AF_INET) {
+ family = CAMEL_TCP_ADDRESS_IPv4;
+ address = &sin->sin_addr;
+#ifdef ENABLE_IPv6
+ } else if (saddr->sa_family == AF_INET6) {
+ family = CAMEL_TCP_ADDRESS_IPv6;
+ address = &sin6->sin6_addr;
+#endif
+ } else
+ return NULL;
+
+ return camel_tcp_address_new (family, sin->sin_port, len, address);
}
static CamelTcpAddress *
stream_get_remote_address (CamelTcpStream *stream)
{
- struct sockaddr_in sin;
+ unsigned char buf[MIN_SOCKADDR_BUFLEN];
+#ifdef ENABLE_IPv6
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) buf;
+#endif
+ struct sockaddr_in *sin = (struct sockaddr_in *) buf;
+ struct sockaddr *saddr = (struct sockaddr *) buf;
+ gpointer address;
socklen_t len;
-
- if (getpeername (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd,
- (struct sockaddr *)&sin, &len) == -1)
+ int family;
+
+ len = MIN_SOCKADDR_BUFLEN;
+
+ if (getpeername (CAMEL_TCP_STREAM_SSL (stream)->priv->sockfd, saddr, &len) == -1)
return NULL;
-
- return camel_tcp_address_new (CAMEL_TCP_ADDRESS_IPV4, sin.sin_port,
- 4, &sin.sin_addr);
+
+ if (saddr->sa_family == AF_INET) {
+ family = CAMEL_TCP_ADDRESS_IPv4;
+ address = &sin->sin_addr;
+#ifdef ENABLE_IPv6
+ } else if (saddr->sa_family == AF_INET6) {
+ family = CAMEL_TCP_ADDRESS_IPv6;
+ address = &sin6->sin6_addr;
+#endif
+ } else
+ return NULL;
+
+ return camel_tcp_address_new (family, sin->sin_port, len, address);
}
#endif /* HAVE_OPENSSL */