IPv6 support
inspired by a patch by "Todd T. Fries" <todd@fries.net>.
This commit is contained in:
parent
4a39cae8c4
commit
3ceb553102
|
@ -35,6 +35,15 @@ AC_CHECK_LIB(socket, socket, [SOCK_LIBS="-lsocket"])
|
||||||
AC_CHECK_LIB(nsl, inet_ntoa, [SOCK_LIBS="$SOCK_LIBS -lnsl"])
|
AC_CHECK_LIB(nsl, inet_ntoa, [SOCK_LIBS="$SOCK_LIBS -lnsl"])
|
||||||
AC_SUBST(SOCK_LIBS)
|
AC_SUBST(SOCK_LIBS)
|
||||||
|
|
||||||
|
have_ipv6=true
|
||||||
|
sav_LDFLAGS=$LDFLAGS
|
||||||
|
LDFLAGS="$LDFLAGS $SOCK_LIBS"
|
||||||
|
AC_CHECK_FUNCS(getaddrinfo inet_ntop, , [have_ipv6=false])
|
||||||
|
LDFLAGS=$sav_LDFLAGS
|
||||||
|
if $have_ipv6; then
|
||||||
|
AC_DEFINE(HAVE_IPV6, 1, [if your libc has IPv6 support])
|
||||||
|
fi
|
||||||
|
|
||||||
have_ssl_paths=
|
have_ssl_paths=
|
||||||
AC_ARG_WITH(ssl,
|
AC_ARG_WITH(ssl,
|
||||||
AC_HELP_STRING([--with-ssl[=PATH]], [where to look for SSL [detect]]),
|
AC_HELP_STRING([--with-ssl[=PATH]], [where to look for SSL [detect]]),
|
||||||
|
|
|
@ -85,7 +85,11 @@ typedef struct {
|
||||||
int fd;
|
int fd;
|
||||||
int state;
|
int state;
|
||||||
const server_conf_t *conf; /* needed during connect */
|
const server_conf_t *conf; /* needed during connect */
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
struct addrinfo *addrs, *curr_addr; /* needed during connect */
|
||||||
|
#else
|
||||||
char **curr_addr; /* needed during connect */
|
char **curr_addr; /* needed during connect */
|
||||||
|
#endif
|
||||||
char *name;
|
char *name;
|
||||||
#ifdef HAVE_LIBSSL
|
#ifdef HAVE_LIBSSL
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
|
|
56
src/socket.c
56
src/socket.c
|
@ -346,6 +346,24 @@ socket_connect( conn_t *sock, void (*cb)( int ok, void *aux ) )
|
||||||
info( "\vok\n" );
|
info( "\vok\n" );
|
||||||
socket_connected( sock );
|
socket_connected( sock );
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
int gaierr;
|
||||||
|
struct addrinfo hints;
|
||||||
|
|
||||||
|
memset( &hints, 0, sizeof(hints) );
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG;
|
||||||
|
infon( "Resolving %s... ", conf->host );
|
||||||
|
if ((gaierr = getaddrinfo( conf->host, NULL, &hints, &sock->addrs ))) {
|
||||||
|
error( "IMAP error: Cannot resolve server '%s': %s\n", conf->host, gai_strerror( gaierr ) );
|
||||||
|
socket_connect_bail( sock );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
info( "\vok\n" );
|
||||||
|
|
||||||
|
sock->curr_addr = sock->addrs;
|
||||||
|
#else
|
||||||
struct hostent *he;
|
struct hostent *he;
|
||||||
|
|
||||||
infon( "Resolving %s... ", conf->host );
|
infon( "Resolving %s... ", conf->host );
|
||||||
|
@ -358,6 +376,7 @@ socket_connect( conn_t *sock, void (*cb)( int ok, void *aux ) )
|
||||||
info( "\vok\n" );
|
info( "\vok\n" );
|
||||||
|
|
||||||
sock->curr_addr = he->h_addr_list;
|
sock->curr_addr = he->h_addr_list;
|
||||||
|
#endif
|
||||||
socket_connect_one( sock );
|
socket_connect_one( sock );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -367,11 +386,19 @@ socket_connect_one( conn_t *sock )
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
ushort port;
|
ushort port;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
struct addrinfo *ai;
|
||||||
|
#else
|
||||||
struct {
|
struct {
|
||||||
struct sockaddr_in ai_addr[1];
|
struct sockaddr_in ai_addr[1];
|
||||||
} ai[1];
|
} ai[1];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (!(ai = sock->curr_addr)) {
|
||||||
|
#else
|
||||||
if (!*sock->curr_addr) {
|
if (!*sock->curr_addr) {
|
||||||
|
#endif
|
||||||
error( "No working address found for %s\n", sock->conf->host );
|
error( "No working address found for %s\n", sock->conf->host );
|
||||||
socket_connect_bail( sock );
|
socket_connect_bail( sock );
|
||||||
return;
|
return;
|
||||||
|
@ -382,17 +409,32 @@ socket_connect_one( conn_t *sock )
|
||||||
sock->conf->use_imaps ? 993 :
|
sock->conf->use_imaps ? 993 :
|
||||||
#endif
|
#endif
|
||||||
143;
|
143;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (ai->ai_family == AF_INET6) {
|
||||||
|
struct sockaddr_in6 *in6 = ((struct sockaddr_in6 *)ai->ai_addr);
|
||||||
|
char sockname[64];
|
||||||
|
in6->sin6_port = htons( port );
|
||||||
|
nfasprintf( &sock->name, "%s ([%s]:%hu)",
|
||||||
|
sock->conf->host, inet_ntop( AF_INET6, &in6->sin6_addr, sockname, sizeof(sockname) ), port );
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
struct sockaddr_in *in = ((struct sockaddr_in *)ai->ai_addr);
|
struct sockaddr_in *in = ((struct sockaddr_in *)ai->ai_addr);
|
||||||
|
#ifndef HAVE_IPV6
|
||||||
memset( in, 0, sizeof(*in) );
|
memset( in, 0, sizeof(*in) );
|
||||||
in->sin_family = AF_INET;
|
in->sin_family = AF_INET;
|
||||||
in->sin_addr.s_addr = *((int *)*sock->curr_addr);
|
in->sin_addr.s_addr = *((int *)*sock->curr_addr);
|
||||||
|
#endif
|
||||||
in->sin_port = htons( port );
|
in->sin_port = htons( port );
|
||||||
nfasprintf( &sock->name, "%s (%s:%hu)",
|
nfasprintf( &sock->name, "%s (%s:%hu)",
|
||||||
sock->conf->host, inet_ntoa( in->sin_addr ), port );
|
sock->conf->host, inet_ntoa( in->sin_addr ), port );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
s = socket( ai->ai_family, SOCK_STREAM, 0 );
|
||||||
|
#else
|
||||||
s = socket( PF_INET, SOCK_STREAM, 0 );
|
s = socket( PF_INET, SOCK_STREAM, 0 );
|
||||||
|
#endif
|
||||||
if (s < 0) {
|
if (s < 0) {
|
||||||
perror( "socket" );
|
perror( "socket" );
|
||||||
exit( 1 );
|
exit( 1 );
|
||||||
|
@ -402,7 +444,11 @@ socket_connect_one( conn_t *sock )
|
||||||
add_fd( s, socket_fd_cb, sock );
|
add_fd( s, socket_fd_cb, sock );
|
||||||
|
|
||||||
infon( "Connecting to %s... ", sock->name );
|
infon( "Connecting to %s... ", sock->name );
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
if (connect( s, ai->ai_addr, ai->ai_addrlen )) {
|
||||||
|
#else
|
||||||
if (connect( s, ai->ai_addr, sizeof(*ai->ai_addr) )) {
|
if (connect( s, ai->ai_addr, sizeof(*ai->ai_addr) )) {
|
||||||
|
#endif
|
||||||
if (errno != EINPROGRESS) {
|
if (errno != EINPROGRESS) {
|
||||||
socket_connect_failed( sock );
|
socket_connect_failed( sock );
|
||||||
return;
|
return;
|
||||||
|
@ -423,13 +469,20 @@ socket_connect_failed( conn_t *conn )
|
||||||
socket_close_internal( conn );
|
socket_close_internal( conn );
|
||||||
free( conn->name );
|
free( conn->name );
|
||||||
conn->name = 0;
|
conn->name = 0;
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
conn->curr_addr = conn->curr_addr->ai_next;
|
||||||
|
#else
|
||||||
conn->curr_addr++;
|
conn->curr_addr++;
|
||||||
|
#endif
|
||||||
socket_connect_one( conn );
|
socket_connect_one( conn );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
socket_connected( conn_t *conn )
|
socket_connected( conn_t *conn )
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
freeaddrinfo( conn->addrs );
|
||||||
|
#endif
|
||||||
conf_fd( conn->fd, 0, POLLIN );
|
conf_fd( conn->fd, 0, POLLIN );
|
||||||
conn->state = SCK_READY;
|
conn->state = SCK_READY;
|
||||||
conn->callbacks.connect( 1, conn->callback_aux );
|
conn->callbacks.connect( 1, conn->callback_aux );
|
||||||
|
@ -438,6 +491,9 @@ socket_connected( conn_t *conn )
|
||||||
static void
|
static void
|
||||||
socket_connect_bail( conn_t *conn )
|
socket_connect_bail( conn_t *conn )
|
||||||
{
|
{
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
freeaddrinfo( conn->addrs );
|
||||||
|
#endif
|
||||||
free( conn->name );
|
free( conn->name );
|
||||||
conn->name = 0;
|
conn->name = 0;
|
||||||
conn->callbacks.connect( 0, conn->callback_aux );
|
conn->callbacks.connect( 0, conn->callback_aux );
|
||||||
|
|
Loading…
Reference in New Issue
Block a user