Avoid extensive casting of sockaddr types in socket-default by using a union

Additionally fixes a strict-aliasing rule compiler warning with older gcc.
This commit is contained in:
Martin Willi
2013-02-06 15:20:32 +01:00
parent 82c884c015
commit 6c37daaa3b
@@ -433,22 +433,24 @@ static int open_socket(private_socket_default_socket_t *this,
int family, u_int16_t *port) int family, u_int16_t *port)
{ {
int on = TRUE; int on = TRUE;
struct sockaddr_storage addr; union {
struct sockaddr sockaddr;
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
} addr;
socklen_t addrlen; socklen_t addrlen;
u_int sol, pktinfo = 0; u_int sol, pktinfo = 0;
int skt; int skt;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.ss_family = family; addr.sockaddr.sa_family = family;
/* precalculate constants depending on address family */ /* precalculate constants depending on address family */
switch (family) switch (family)
{ {
case AF_INET: case AF_INET:
{ addr.sin.sin_addr.s_addr = htonl(INADDR_ANY);
struct sockaddr_in *sin = (struct sockaddr_in *)&addr; addr.sin.sin_port = htons(*port);
htoun32(&sin->sin_addr.s_addr, INADDR_ANY); addrlen = sizeof(addr.sin);
htoun16(&sin->sin_port, *port);
addrlen = sizeof(struct sockaddr_in);
sol = SOL_IP; sol = SOL_IP;
#ifdef IP_PKTINFO #ifdef IP_PKTINFO
pktinfo = IP_PKTINFO; pktinfo = IP_PKTINFO;
@@ -456,17 +458,13 @@ static int open_socket(private_socket_default_socket_t *this,
pktinfo = IP_RECVDSTADDR; pktinfo = IP_RECVDSTADDR;
#endif #endif
break; break;
}
case AF_INET6: case AF_INET6:
{ memcpy(&addr.sin6.sin6_addr, &in6addr_any, sizeof(in6addr_any));
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr; addr.sin6.sin6_port = htons(*port);
memcpy(&sin6->sin6_addr, &in6addr_any, sizeof(in6addr_any)); addrlen = sizeof(addr.sin6);
htoun16(&sin6->sin6_port, *port);
addrlen = sizeof(struct sockaddr_in6);
sol = SOL_IPV6; sol = SOL_IPV6;
pktinfo = IPV6_RECVPKTINFO; pktinfo = IPV6_RECVPKTINFO;
break; break;
}
default: default:
return 0; return 0;
} }
@@ -485,7 +483,7 @@ static int open_socket(private_socket_default_socket_t *this,
} }
/* bind the socket */ /* bind the socket */
if (bind(skt, (struct sockaddr *)&addr, addrlen) < 0) if (bind(skt, &addr.sockaddr, addrlen) < 0)
{ {
DBG1(DBG_NET, "unable to bind socket: %s", strerror(errno)); DBG1(DBG_NET, "unable to bind socket: %s", strerror(errno));
close(skt); close(skt);
@@ -495,7 +493,7 @@ static int open_socket(private_socket_default_socket_t *this,
/* retrieve randomly allocated port if needed */ /* retrieve randomly allocated port if needed */
if (*port == 0) if (*port == 0)
{ {
if (getsockname(skt, (struct sockaddr *)&addr, &addrlen) < 0) if (getsockname(skt, &addr.sockaddr, &addrlen) < 0)
{ {
DBG1(DBG_NET, "unable to determine port: %s", strerror(errno)); DBG1(DBG_NET, "unable to determine port: %s", strerror(errno));
close(skt); close(skt);
@@ -504,17 +502,11 @@ static int open_socket(private_socket_default_socket_t *this,
switch (family) switch (family)
{ {
case AF_INET: case AF_INET:
{ *port = ntohs(addr.sin.sin_port);
struct sockaddr_in *sin = (struct sockaddr_in *)&addr;
*port = untoh16(&sin->sin_port);
break; break;
}
case AF_INET6: case AF_INET6:
{ *port = ntohs(addr.sin6.sin6_port);
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
*port = untoh16(&sin6->sin6_port);
break; break;
}
} }
} }