diff --git a/src/account/pop3.c b/src/account/pop3.c index 07ade44..3a83624 100644 --- a/src/account/pop3.c +++ b/src/account/pop3.c @@ -161,7 +161,7 @@ static int _pop3_refresh(POP3 * pop3, AccountFolder * folder, static POP3Command * _pop3_command(POP3 * pop3, POP3Context context, char const * command); static int _pop3_lookup(POP3 * pop3, char const * hostname, uint16_t port, - struct sockaddr_in * sa); + struct addrinfo ** ai); static int _pop3_parse(POP3 * pop3); /* events */ @@ -376,18 +376,19 @@ static POP3Command * _pop3_command(POP3 * pop3, POP3Context context, /* pop3_lookup */ static int _pop3_lookup(POP3 * pop3, char const * hostname, uint16_t port, - struct sockaddr_in * sa) + struct addrinfo ** ai) { - struct hostent * he; + struct addrinfo hints; + int res; if(hostname == NULL) return -error_set_code(1, "%s", strerror(errno)); - if((he = gethostbyname(hostname)) == NULL) - return -error_set_code(1, "%s", hstrerror(h_errno)); - memset(sa, 0, sizeof(*sa)); - sa->sin_family = AF_INET; - sa->sin_port = htons(port); - sa->sin_addr.s_addr = *((uint32_t*)he->h_addr_list[0]); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + if((res = getaddrinfo(hostname, NULL, &hints, ai)) != 0) + return -error_set_code(1, "%s", gai_strerror(res)); return 0; } @@ -661,7 +662,8 @@ static gboolean _on_connect(gpointer data) char const * hostname; char const * p; uint16_t port; - struct sockaddr_in sa; + struct addrinfo * ai; + struct sockaddr_in * sa; int res; char buf[128]; @@ -679,7 +681,7 @@ static gboolean _on_connect(gpointer data) return FALSE; port = (unsigned long)p; /* lookup the address */ - if(_pop3_lookup(pop3, hostname, port, &sa) != 0) + if(_pop3_lookup(pop3, hostname, port, &ai) != 0) { helper->error(helper->account, error_get(), 1); return FALSE; @@ -697,8 +699,14 @@ static gboolean _on_connect(gpointer data) /* FIXME report properly as a warning instead */ helper->error(NULL, strerror(errno), 1); /* report the current status */ - snprintf(buf, sizeof(buf), "Connecting to %s (%s:%u)", hostname, - inet_ntoa(sa.sin_addr), port); + if(ai->ai_family == AF_INET) + { + sa = (struct sockaddr_in *)ai->ai_addr; + snprintf(buf, sizeof(buf), "Connecting to %s (%s:%u)", hostname, + inet_ntoa(sa->sin_addr), port); + } + else + snprintf(buf, sizeof(buf), "Connecting to %s", hostname); _pop3_event_status(pop3, AS_CONNECTING, buf); /* connect to the remote host */ if((connect(pop3->fd, (struct sockaddr *)&sa, sizeof(sa)) != 0 @@ -709,10 +717,12 @@ static gboolean _on_connect(gpointer data) strerror(errno)); helper->error(helper->account, buf, 1); _pop3_stop(pop3); + freeaddrinfo(ai); return FALSE; } pop3->wr_source = g_io_add_watch(pop3->channel, G_IO_OUT, _on_watch_can_connect, pop3); + freeaddrinfo(ai); return FALSE; } @@ -761,7 +771,8 @@ static gboolean _on_watch_can_connect(GIOChannel * source, socklen_t s = sizeof(res); char const * hostname = pop3->config[P3CV_HOSTNAME].value; uint16_t port = (unsigned long)pop3->config[P3CV_PORT].value; - struct sockaddr_in sa; + struct addrinfo * ai; + struct sockaddr_in * sa; SSL_CTX * ssl_ctx; char buf[128]; @@ -780,11 +791,19 @@ static gboolean _on_watch_can_connect(GIOChannel * source, return FALSE; } /* XXX remember the address instead */ - if(_pop3_lookup(pop3, hostname, port, &sa) == 0) + if(_pop3_lookup(pop3, hostname, port, &ai) == 0) { - snprintf(buf, sizeof(buf), "Connected to %s (%s:%u)", - hostname, inet_ntoa(sa.sin_addr), port); + if(ai->ai_family == AF_INET) + { + sa = (struct sockaddr_in *)ai->ai_addr; + snprintf(buf, sizeof(buf), "Connected to %s (%s:%u)", + hostname, inet_ntoa(sa->sin_addr), + port); + } + else + snprintf(buf, sizeof(buf), "Connected to %s", hostname); _pop3_event_status(pop3, AS_CONNECTED, buf); + freeaddrinfo(ai); } pop3->wr_source = 0; /* setup SSL */