Commit d1278b06 authored by Per Cederqvist's avatar Per Cederqvist
Browse files

(isc_udp_read_fn): Handle IPv6.

(isc_udp_write_fn): Handle IPv6.
(isc_mkudpaddress): New argument: address_family.  All callers
	updated.  Handle IPv6.  Broadcast addresses are not supported.
(isc_createudp): Handle IPv6.  The first argument of socket()
	should be PF_INET for IPv4, not AF_INET.
(isc_bindudp): Handle IPv6.
(isc_connectudp): Handle IPv6.
parent 2de64c81
......@@ -68,7 +68,7 @@ isc_udp_read_fn(IscHandlerList *UNUSED(hl),
IscSession *scb)
{
IscMessage *msg;
struct sockaddr addr;
SOCKADDR_STORAGE addr;
socklen_t len;
int status;
......@@ -79,7 +79,7 @@ isc_udp_read_fn(IscHandlerList *UNUSED(hl),
status = recvfrom(scb->fd, msg->buffer, msg->size,
0,
&addr, &len);
(struct sockaddr *) &addr, &len);
if (status < 0)
{
isc_freemsg(msg);
......@@ -116,7 +116,7 @@ isc_udp_write_fn(IscHandlerList *hl,
return sendto(scb->fd, msg->buffer, msg->length,
0,
&msg->address->ip.saddr,
(struct sockaddr *) &msg->address->ip.saddr,
sizeof(msg->address->ip.saddr));
}
......@@ -146,9 +146,10 @@ isc_udp_destroy_fn(IscHandlerList *UNUSED(hl),
*/
static IscAddress *
isc_mkudpaddress(const char *address,
const char *service)
const char *service,
int address_family)
{
struct sockaddr_in addr;
union sockaddrs addr;
struct hostent *hp;
struct servent *sp;
......@@ -158,37 +159,82 @@ isc_mkudpaddress(const char *address,
/* Any local address? */
if (address == NULL)
{
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sa.sa_family = address_family;
STORE_ADDR(addr, htonl(INADDR_ANY), in6addr_any);
}
else if (strcmp(address, "*") == 0)
{
/* Broadcast address */
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_BROADCAST);
/* Broadcast address, no IPv6 support for now */
if (address_family == AF_INET6)
return NULL;
addr.sa.sa_family = AF_INET;
addr.sa_in.sin_addr.s_addr = htonl(INADDR_BROADCAST);
}
else if (isdigit((int)(unsigned char)address[0]))
else if (isdigit((int)(unsigned char)address[0])
|| (address[0] == ':'))
{
addr.sin_family = AF_INET;
if (!inet_aton(address, &addr.sin_addr))
return NULL;
#ifdef HAVE_INET_PTON
if (FOR_EACH_AF(addr.sa.sa_family,
(address_family != addr.sa.sa_family)
|| (inet_pton(address_family,
address,
CHOOSE_IP4OR6(addr,
(void *) &addr.sa_in.sin_addr,
(void *) &addr.sa_in6.sin6_addr)
) <= 0)))
return NULL;
#else
/* No inet_pton; we have to do with inet_aton which
only handles AF_INET addresses */
if (address_family != AF_INET)
return NULL;
addr.sa.sa_family = AF_INET;
if (!inet_aton(address, &addr.sa_in.sin_addr))
return NULL;
#endif
}
#ifdef HAVE_GETIPNODEBYNAME
else if ((hp = getipnodebyname(address,
address_family,
AI_ADDRCONFIG,
&error_num)) == NULL)
return NULL;
#elif defined(HAVE_GETHOSTBYNAME2)
else if ((hp = gethostbyname2(address, address_family)))
return NULL;
#else
else if ((hp = gethostbyname(address)) == NULL)
return NULL;
#endif
else
{
addr.sin_family = hp->h_addrtype;
memcpy(&addr.sin_addr, hp->h_addr, sizeof(addr.sin_addr));
addr.sa.sa_family = hp->h_addrtype;
memcpy(CHOOSE_IP4OR6(addr,
(void *) &addr.sa_in.sin_addr,
(void *) &addr.sa_in6.sin6_addr),
hp->h_addr,
hp->h_length);
}
#ifdef HAVE_GETIPNODEBYNAME
freehostent(hp);
#endif
if (addr.sa.sa_family != address_family)
return NULL;
if (isdigit((int)(unsigned char)service[0]))
addr.sin_port = htons(atoi(service));
CHOOSE_IP4OR6(addr,
addr.sa_in.sin_port = htons(atoi(service)),
addr.sa_in6.sin6_port = htons(atoi(service)));
else if ((sp = getservbyname(service, "udp")) == NULL)
return NULL;
else
addr.sin_port = sp->s_port;
return isc_mkipaddress((struct sockaddr *) &addr);
CHOOSE_IP4OR6(addr,
addr.sa_in.sin_port = sp->s_port,
addr.sa_in6.sin6_port = sp->s_port);
return isc_mkipaddress(&addr.ssa);
}
......@@ -216,8 +262,10 @@ isc_createudp(IscSessionConfig *cfg)
int fd, res;
int flag;
struct linger ling;
int protocol_family;
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
if (FOR_EACH_PF(protocol_family,
(fd = socket(protocol_family, SOCK_DGRAM, 0)) < 0))
return NULL;
fd = isc_relocate_fd(fd, cfg->fd_relocate);
......@@ -280,17 +328,17 @@ isc_bindudp(IscSession *scb,
const char *service)
{
IscAddress *ia;
int af;
if (scb->type != ISC_TYPE_UDP)
return -1;
ia = isc_mkudpaddress(address, service);
if (!ia)
return -1;
if (bind(scb->fd, &ia->ip.saddr, sizeof(ia->ip.saddr)) < 0)
if (FOR_EACH_AF(af,
! (ia = isc_mkudpaddress(address, service, af))
|| (bind(scb->fd,
(struct sockaddr *) &ia->ip.saddr,
sizeof(ia->ip.saddr)) < 0)))
return -1;
scb->state = ISC_STATE_RUNNING;
......@@ -310,6 +358,7 @@ isc_connectudp(IscSession *scb,
const char *service)
{
IscAddress *ia;
int af;
int res;
......@@ -319,13 +368,12 @@ isc_connectudp(IscSession *scb,
if (address == NULL)
address = "localhost";
ia = isc_mkudpaddress(address, service);
if (!ia)
return -1;
res = connect(scb->fd, &ia->ip.saddr, sizeof(ia->ip.saddr));
if (res < 0 && errno != EINPROGRESS)
if (FOR_EACH_AF(af,
! (ia = isc_mkudpaddress(address, service, af))
|| (((res = connect(scb->fd,
(struct sockaddr *) &ia->ip.saddr,
sizeof(ia->ip.saddr))
) < 0) && (errno != EINPROGRESS))))
return -1;
scb->state = (res < 0 ? ISC_STATE_CONNECTING : ISC_STATE_RUNNING);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment