summaryrefslogtreecommitdiff
path: root/socket/udp-bsd.c
diff options
context:
space:
mode:
authorPhilip Withnall <philip.withnall@collabora.co.uk>2013-12-17 09:27:58 +0000
committerOlivier Crête <olivier.crete@collabora.com>2013-12-18 17:50:33 -0500
commit63e74d8efac70b92df008da8a27d72720216b937 (patch)
tree13301091104a90abce05445ee582f6419882d30d /socket/udp-bsd.c
parent71fa5bb8716ea311fc3a1d9cc845a123eb8cd4cc (diff)
downloadlibnice-63e74d8efac70b92df008da8a27d72720216b937.tar.gz
Fix strict aliasing of sockaddr structures
Casting from one struct sockaddr type to another breaks C’s strict aliasing rules (variables of different types cannot alias). Fix this cleanly by using unions of struct sockaddrs to convert between the types (i.e. type-punning). I wish sockaddr didn’t have to be this painful. See: http://gcc.gnu.org/onlinedocs/gcc-4.4.1/gcc/Optimize-Options.html#Type_002dpunning
Diffstat (limited to 'socket/udp-bsd.c')
-rw-r--r--socket/udp-bsd.c45
1 files changed, 27 insertions, 18 deletions
diff --git a/socket/udp-bsd.c b/socket/udp-bsd.c
index 553f0fe..721da00 100644
--- a/socket/udp-bsd.c
+++ b/socket/udp-bsd.c
@@ -72,7 +72,10 @@ struct UdpBsdSocketPrivate
NiceSocket *
nice_udp_bsd_socket_new (NiceAddress *addr)
{
- struct sockaddr_storage name;
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } name;
NiceSocket *sock = g_slice_new0 (NiceSocket);
GSocket *gsock = NULL;
gboolean gret = FALSE;
@@ -80,25 +83,25 @@ nice_udp_bsd_socket_new (NiceAddress *addr)
struct UdpBsdSocketPrivate *priv;
if (addr != NULL) {
- nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name);
+ nice_address_copy_to_sockaddr(addr, &name.addr);
} else {
memset (&name, 0, sizeof (name));
- name.ss_family = AF_UNSPEC;
+ name.storage.ss_family = AF_UNSPEC;
}
- if (name.ss_family == AF_UNSPEC || name.ss_family == AF_INET) {
+ if (name.storage.ss_family == AF_UNSPEC || name.storage.ss_family == AF_INET) {
gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
G_SOCKET_PROTOCOL_UDP, NULL);
- name.ss_family = AF_INET;
+ name.storage.ss_family = AF_INET;
#ifdef HAVE_SA_LEN
- name.ss_len = sizeof (struct sockaddr_in);
+ name.storage.ss_len = sizeof (struct sockaddr_in);
#endif
- } else if (name.ss_family == AF_INET6) {
+ } else if (name.storage.ss_family == AF_INET6) {
gsock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_DATAGRAM,
G_SOCKET_PROTOCOL_UDP, NULL);
- name.ss_family = AF_INET6;
+ name.storage.ss_family = AF_INET6;
#ifdef HAVE_SA_LEN
- name.ss_len = sizeof (struct sockaddr_in6);
+ name.storage.ss_len = sizeof (struct sockaddr_in6);
#endif
}
@@ -109,7 +112,7 @@ nice_udp_bsd_socket_new (NiceAddress *addr)
/* GSocket: All socket file descriptors are set to be close-on-exec. */
g_socket_set_blocking (gsock, false);
- gaddr = g_socket_address_new_from_native (&name, sizeof (name));
+ gaddr = g_socket_address_new_from_native (&name.addr, sizeof (name));
if (gaddr != NULL) {
gret = g_socket_bind (gsock, gaddr, FALSE, NULL);
g_object_unref (gaddr);
@@ -124,7 +127,7 @@ nice_udp_bsd_socket_new (NiceAddress *addr)
gaddr = g_socket_get_local_address (gsock, NULL);
if (gaddr == NULL ||
- !g_socket_address_to_native (gaddr, &name, sizeof(name), NULL)) {
+ !g_socket_address_to_native (gaddr, &name.addr, sizeof(name), NULL)) {
g_slice_free (NiceSocket, sock);
g_socket_close (gsock, NULL);
g_object_unref (gsock);
@@ -133,7 +136,7 @@ nice_udp_bsd_socket_new (NiceAddress *addr)
g_object_unref (gaddr);
- nice_address_set_from_sockaddr (&sock->addr, (struct sockaddr *)&name);
+ nice_address_set_from_sockaddr (&sock->addr, &name.addr);
priv = sock->priv = g_slice_new0 (struct UdpBsdSocketPrivate);
nice_address_init (&priv->niceaddr);
@@ -181,10 +184,13 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
}
if (recvd > 0 && from != NULL && gaddr != NULL) {
- struct sockaddr_storage sa;
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } sa;
- g_socket_address_to_native (gaddr, &sa, sizeof (sa), NULL);
- nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa);
+ g_socket_address_to_native (gaddr, &sa.addr, sizeof (sa), NULL);
+ nice_address_set_from_sockaddr (from, &sa.addr);
}
if (gaddr != NULL)
@@ -202,13 +208,16 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
if (!nice_address_is_valid (&priv->niceaddr) ||
!nice_address_equal (&priv->niceaddr, to)) {
- struct sockaddr_storage sa;
+ union {
+ struct sockaddr_storage storage;
+ struct sockaddr addr;
+ } sa;
GSocketAddress *gaddr;
if (priv->gaddr)
g_object_unref (priv->gaddr);
- nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa);
- gaddr = g_socket_address_new_from_native (&sa, sizeof(sa));
+ nice_address_copy_to_sockaddr (to, &sa.addr);
+ gaddr = g_socket_address_new_from_native (&sa.addr, sizeof(sa));
if (gaddr == NULL)
return -1;
priv->gaddr = gaddr;