IPv6 support
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@3479 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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,
|
||||||
|
Reference in New Issue
Block a user