IPv6 support

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@3479 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Assar Westerlund
1997-09-12 23:06:36 +00:00
parent f62e4928b2
commit 4704b3c219
3 changed files with 152 additions and 56 deletions

View File

@@ -132,6 +132,40 @@ krb5_auth_con_setaddrs(krb5_context context,
return 0; return 0;
} }
static void
sockaddr2krb5_address (struct sockaddr *sa,
krb5_address *ka)
{
switch (sa->sa_family) {
case AF_INET: {
struct sockaddr_in *sin = (struct sockaddr_in *)sa;
ka->addr_type = AF_INET;
ka->address.length = sizeof(sin->sin_addr);
ka->address.data = &sin->sin_addr;
break;
}
#if defined(AF_INET6) && defined(HAVE_SOCKADDR_IN6)
case AF_INET6: {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
ka->addr_type = AF_INET;
ka->address.length = sizeof(struct in_addr);
ka->address.data = IN6_ADDR_V6_TO_V4(&sin6->sin6_addr);
} else {
ka->addr_type = AF_INET6;
ka->address.length = sizeof(sin6->sin6_addr);
ka->address.data = &sin6->sin6_addr;
}
break;
}
#endif
default:
break;
}
}
krb5_error_code krb5_error_code
krb5_auth_con_setaddrs_from_fd (krb5_context context, krb5_auth_con_setaddrs_from_fd (krb5_context context,
@@ -140,16 +174,19 @@ krb5_auth_con_setaddrs_from_fd (krb5_context context,
{ {
krb5_address *lptr = NULL, *rptr = NULL; krb5_address *lptr = NULL, *rptr = NULL;
krb5_address local_k_address, remote_k_address; krb5_address local_k_address, remote_k_address;
#if defined(AF_INET6) && defined(HAVE_SOCKADDR_IN6)
struct sockaddr_in6 local_addr, remote_addr;
#else
struct sockaddr_in local_addr, remote_addr; struct sockaddr_in local_addr, remote_addr;
#endif
int len; int len;
if (auth_context->local_address == NULL) { if (auth_context->local_address == NULL) {
len = sizeof (local_addr); len = sizeof (local_addr);
if (getsockname (fd, (struct sockaddr *)&local_addr, &len) < 0) if (getsockname (fd, (struct sockaddr *)&local_addr, &len) < 0)
return errno; return errno;
local_k_address.addr_type = AF_INET; sockaddr2krb5_address((struct sockaddr *)&local_addr,
local_k_address.address.length = sizeof(local_addr.sin_addr); &local_k_address);
local_k_address.address.data = &local_addr.sin_addr;
lptr = &local_k_address; lptr = &local_k_address;
} }
@@ -157,9 +194,8 @@ krb5_auth_con_setaddrs_from_fd (krb5_context context,
len = sizeof (remote_addr); len = sizeof (remote_addr);
if (getpeername (fd, (struct sockaddr *)&remote_addr, &len) < 0) if (getpeername (fd, (struct sockaddr *)&remote_addr, &len) < 0)
return errno; return errno;
remote_k_address.addr_type = AF_INET; sockaddr2krb5_address((struct sockaddr *)&remote_addr,
remote_k_address.address.length = sizeof(remote_addr.sin_addr); &remote_k_address);
remote_k_address.address.data = &remote_addr.sin_addr;
rptr = &remote_k_address; rptr = &remote_k_address;
} }

View File

@@ -120,6 +120,18 @@ send_and_recv_http(int fd,
return 0; return 0;
} }
static int
init_port(const char *s, int fallback)
{
if (s) {
int tmp;
sscanf (s, "%d", &tmp);
return htons(tmp);
} else
return fallback;
}
krb5_error_code krb5_error_code
krb5_sendto_kdc (krb5_context context, krb5_sendto_kdc (krb5_context context,
const krb5_data *send, const krb5_data *send,
@@ -141,61 +153,90 @@ krb5_sendto_kdc (krb5_context context,
return err; return err;
} }
for (i = 0; i < 3; ++i) for (i = 0; i < context->max_retries; ++i)
for (hp = hostlist; (p = *hp); ++hp) { for (hp = hostlist; (p = *hp); ++hp) {
char *addr; char *addr;
char *colon; char *colon;
int http_flag = 0; int http_flag = 0;
if(strncmp(p, "http://", 7) == 0){ if(strncmp(p, "http://", 7) == 0){
p += 7; p += 7;
http_flag = 1; http_flag = 1;
} }
colon = strchr (p, ':'); colon = strchr (p, ':');
if (colon) if (colon)
*colon = '\0'; *colon = '\0';
hostent = gethostbyname (p); #ifdef HAVE_GETHOSTBYNAME2
if(hostent == NULL) hostent = gethostbyname2 (p, AF_INET6);
continue; if (hostent == NULL)
if (colon) hostent = gethostbyname2 (p, AF_INET);
*colon++ = ':'; #else
while ((addr = *hostent->h_addr_list++)) { hostent = gethostbyname (p);
struct sockaddr_in a; #endif
int ret; if(hostent == NULL)
continue;
if(http_flag) if (colon)
fd = socket(AF_INET, SOCK_STREAM, 0); *colon++ = ':';
else while ((addr = *hostent->h_addr_list++)) {
fd = socket(AF_INET, SOCK_DGRAM, 0); int ret;
int family;
if(fd < 0){ struct sockaddr *sa;
return errno; int sa_len;
} struct sockaddr_in sin;
memset (&a, 0, sizeof(a)); #if defined(AF_INET6) && defined(HAVE_SOCKADDR_IN6)
a.sin_family = AF_INET; struct sockaddr_in6 sin6;
if (colon) { #endif
int tmp;
sscanf (colon, "%d", &tmp); family = hostent->h_addrtype;
a.sin_port = htons(tmp);
} else
a.sin_port = port;
a.sin_addr = *((struct in_addr *)addr);
connect(fd, (struct sockaddr*)&a, sizeof(a));
if(http_flag) if(http_flag)
ret = send_and_recv_http(fd, context->kdc_timeout, fd = socket(family, SOCK_STREAM, 0);
send, receive); else
else fd = socket(family, SOCK_DGRAM, 0);
if(fd < 0)
return errno;
switch (family) {
case AF_INET :
memset(&sin, 0, sizeof(sin));
sa_len = sizeof(sin);
sa = (struct sockaddr *)&sin;
sin.sin_family = family;
sin.sin_port = init_port(colon, port);
sin.sin_addr = *((struct in_addr *)addr);
break;
#if defined(AF_INET6) && defined(HAVE_SOCKADDR_IN6)
case AF_INET6:
memset(&sin6, 0, sizeof(sin6));
sa_len = sizeof(sin6);
sa = (struct sockaddr *)&sin6;
sin6.sin6_family = family;
sin6.sin6_port = init_port(colon, port);
sin6.sin6_addr = *((struct in6_addr *)addr);
break;
#endif
default:
continue;
}
if(connect(fd, sa, sa_len) < 0) {
close (fd);
continue;
}
if(http_flag)
ret = send_and_recv_http(fd, context->kdc_timeout,
send, receive);
else
ret = send_and_recv (fd, context->kdc_timeout, 1, ret = send_and_recv (fd, context->kdc_timeout, 1,
send, receive); send, receive);
close (fd); close (fd);
if(ret == 0){ if(ret == 0){
krb5_free_krbhst (context, hostlist); krb5_free_krbhst (context, hostlist);
return 0; return 0;
} }
} }
} }
krb5_free_krbhst (context, hostlist); krb5_free_krbhst (context, hostlist);
return KRB5_KDC_UNREACH; return KRB5_KDC_UNREACH;

View File

@@ -48,16 +48,35 @@ krb5_sock_to_principal (krb5_context context,
krb5_principal *ret_princ) krb5_principal *ret_princ)
{ {
krb5_error_code ret; krb5_error_code ret;
#if defined(AF_INET6) && defined(HAVE_SOCKADDR_IN6)
struct sockaddr_in6 addr;
#else
struct sockaddr_in addr; struct sockaddr_in addr;
#endif
int len = sizeof(addr); int len = sizeof(addr);
struct hostent *hostent; struct hostent *hostent;
if (getsockname (sock, (struct sockaddr *)&addr, &len) < 0) if (getsockname (sock, (struct sockaddr *)&addr, &len) < 0)
return errno; return errno;
#if defined(AF_INET6) && defined(HAVE_SOCKADDR_IN6)
if(len == sizeof(struct sockaddr_in6))
hostent = gethostbyaddr ((const char *)&addr.sin6_addr,
sizeof(addr.sin6_addr),
addr.sin6_family);
else {
struct sockaddr_in *foo = (struct sockaddr_in *)&addr;
hostent = gethostbyaddr ((const char *)&foo->sin_addr,
sizeof(foo->sin_addr),
foo->sin_family);
}
#else
hostent = gethostbyaddr ((const char *)&addr.sin_addr, hostent = gethostbyaddr ((const char *)&addr.sin_addr,
sizeof(addr.sin_addr), sizeof(addr.sin_addr),
addr.sin_family); addr.sin_family);
#endif
if (hostent == NULL) if (hostent == NULL)
return h_errno; return h_errno;
return krb5_sname_to_principal (context, return krb5_sname_to_principal (context,