summaryrefslogtreecommitdiff
path: root/lib-src/pop.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib-src/pop.c')
-rw-r--r--lib-src/pop.c66
1 files changed, 60 insertions, 6 deletions
diff --git a/lib-src/pop.c b/lib-src/pop.c
index 9fcbe4b370c..5e6623aaf8d 100644
--- a/lib-src/pop.c
+++ b/lib-src/pop.c
@@ -1010,12 +1010,19 @@ socket_connection (host, flags)
char *host;
int flags;
{
+#ifdef HAVE_GETADDRINFO
+ struct addrinfo *res, *it;
+ struct addrinfo hints;
+ int ret;
+#else /* !HAVE_GETADDRINFO */
struct hostent *hostent;
+#endif
struct servent *servent;
struct sockaddr_in addr;
char found_port = 0;
char *service;
int sock;
+ char *realhost;
#ifdef KERBEROS
#ifdef KERBEROS5
krb5_error_code rem;
@@ -1031,11 +1038,11 @@ socket_connection (host, flags)
CREDENTIALS cred;
Key_schedule schedule;
int rem;
- char *realhost;
#endif /* KERBEROS5 */
#endif /* KERBEROS */
int try_count = 0;
+ int connect_ok;
#ifdef WINDOWSNT
{
@@ -1097,6 +1104,46 @@ socket_connection (host, flags)
}
+#ifdef HAVE_GETADDRINFO
+ memset (&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = AF_INET;
+ do
+ {
+ ret = getaddrinfo (host, service, &hints, &res);
+ try_count++;
+ if (ret != 0 && (ret != EAI_AGAIN || try_count == 5))
+ {
+ strcpy (pop_error, "Could not determine POP server's address");
+ return (-1);
+ }
+ } while (ret != 0);
+
+ if (ret == 0)
+ {
+ it = res;
+ while (it)
+ {
+ if (it->ai_addrlen == sizeof (addr))
+ {
+ struct sockaddr_in *in_a = (struct sockaddr_in *) it->ai_addr;
+ bcopy (&in_a->sin_addr, (char *) &addr.sin_addr,
+ sizeof (addr.sin_addr));
+ if (! connect (sock, (struct sockaddr *) &addr, sizeof (addr)))
+ break;
+ }
+ it = it->ai_next;
+ }
+ connect_ok = it != NULL;
+ if (connect_ok)
+ {
+ realhost = alloca (strlen (it->ai_canonname) + 1);
+ strcpy (realhost, it->ai_canonname);
+ }
+ freeaddrinfo (res);
+ }
+#else /* !HAVE_GETADDRINFO */
do
{
hostent = gethostbyname (host);
@@ -1116,10 +1163,18 @@ socket_connection (host, flags)
break;
hostent->h_addr_list++;
}
+ connect_ok = *hostent->h_addr_list != NULL;
+ if (! connect_ok)
+ {
+ realhost = alloca (strlen (hostent->h_name) + 1);
+ strcpy (realhost, hostent->h_name);
+ }
+
+#endif /* !HAVE_GETADDRINFO */
#define CONNECT_ERROR "Could not connect to POP server: "
- if (! *hostent->h_addr_list)
+ if (! connect_ok)
{
CLOSESOCKET (sock);
strcpy (pop_error, CONNECT_ERROR);
@@ -1130,6 +1185,7 @@ socket_connection (host, flags)
}
#ifdef KERBEROS
+
#define KRB_ERROR "Kerberos error connecting to POP server: "
if (! (flags & POP_NO_KERBEROS))
{
@@ -1157,7 +1213,7 @@ socket_connection (host, flags)
if (rem = krb5_cc_get_principal (kcontext, ccdef, &client))
goto krb5error;
- for (cp = hostent->h_name; *cp; cp++)
+ for (cp = realhost; *cp; cp++)
{
if (isupper (*cp))
{
@@ -1165,7 +1221,7 @@ socket_connection (host, flags)
}
}
- if (rem = krb5_sname_to_principal (kcontext, hostent->h_name,
+ if (rem = krb5_sname_to_principal (kcontext, realhost,
POP_SERVICE, FALSE, &server))
goto krb5error;
@@ -1210,7 +1266,6 @@ socket_connection (host, flags)
}
#else /* ! KERBEROS5 */
ticket = (KTEXT) malloc (sizeof (KTEXT_ST));
- realhost = strdup (hostent->h_name);
rem = krb_sendauth (0L, sock, ticket, "pop", realhost,
(char *) krb_realmofhost (realhost),
(unsigned long) 0, &msg_data, &cred, schedule,
@@ -1218,7 +1273,6 @@ socket_connection (host, flags)
(struct sockaddr_in *) 0,
"KPOPV0.1");
free ((char *) ticket);
- free (realhost);
if (rem != KSUCCESS)
{
strcpy (pop_error, KRB_ERROR);