Commit 63e74d8e authored by Philip Withnall's avatar Philip Withnall Committed by Olivier Crête

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
parent 71fa5bb8
......@@ -226,20 +226,25 @@ nice_address_set_from_sockaddr (NiceAddress *addr,
NICEAPI_EXPORT void
nice_address_copy_to_sockaddr (const NiceAddress *addr,
struct sockaddr *sa)
struct sockaddr *_sa)
{
struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
union {
struct sockaddr *addr;
struct sockaddr_in *in;
struct sockaddr_in6 *in6;
} sa;
g_assert (sa);
sa.addr = _sa;
g_assert (_sa);
switch (addr->s.addr.sa_family)
{
case AF_INET:
memcpy (sin4, &addr->s.ip4, sizeof (*sin4));
memcpy (sa.in, &addr->s.ip4, sizeof (*sa.in));
break;
case AF_INET6:
memcpy (sin6, &addr->s.ip6, sizeof (*sin6));
memcpy (sa.in6, &addr->s.ip6, sizeof (*sa.in6));
break;
default:
g_return_if_reached ();
......
......@@ -2096,7 +2096,10 @@ static CandidateCheckPair *priv_process_response_check_for_peer_reflexive(NiceAg
*/
static gboolean priv_map_reply_to_conn_check_request (NiceAgent *agent, Stream *stream, Component *component, NiceSocket *sockptr, const NiceAddress *from, NiceCandidate *local_candidate, NiceCandidate *remote_candidate, StunMessage *resp)
{
struct sockaddr_storage sockaddr;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} sockaddr;
socklen_t socklen = sizeof (sockaddr);
GSList *i;
StunUsageIceReturn res;
......@@ -2113,7 +2116,7 @@ static gboolean priv_map_reply_to_conn_check_request (NiceAgent *agent, Stream *
if (memcmp (discovery_id, response_id, sizeof(StunTransactionId)) == 0) {
res = stun_usage_ice_conncheck_process (resp,
(struct sockaddr *) &sockaddr, &socklen,
&sockaddr.addr, &socklen,
agent_to_ice_compatibility (agent));
nice_debug ("Agent %p : stun_bind_process/conncheck for %p res %d "
"(controlling=%d).", agent, p, (int)res, agent->controlling_mode);
......@@ -2164,7 +2167,7 @@ static gboolean priv_map_reply_to_conn_check_request (NiceAgent *agent, Stream *
priv_conn_check_unfreeze_related (agent, stream, p);
} else {
ok_pair = priv_process_response_check_for_peer_reflexive(agent,
stream, component, p, sockptr, (struct sockaddr *) &sockaddr,
stream, component, p, sockptr, &sockaddr.addr,
local_candidate, remote_candidate);
}
......@@ -2226,10 +2229,18 @@ static gboolean priv_map_reply_to_conn_check_request (NiceAgent *agent, Stream *
*/
static gboolean priv_map_reply_to_discovery_request (NiceAgent *agent, StunMessage *resp)
{
struct sockaddr_storage sockaddr;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} sockaddr;
socklen_t socklen = sizeof (sockaddr);
struct sockaddr_storage alternate;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} alternate;
socklen_t alternatelen = sizeof (sockaddr);
GSList *i;
StunUsageBindReturn res;
gboolean trans_found = FALSE;
......@@ -2245,24 +2256,22 @@ static gboolean priv_map_reply_to_discovery_request (NiceAgent *agent, StunMessa
stun_message_id (&d->stun_message, discovery_id);
if (memcmp (discovery_id, response_id, sizeof(StunTransactionId)) == 0) {
res = stun_usage_bind_process (resp, (struct sockaddr *) &sockaddr,
&socklen, (struct sockaddr *) &alternate, &alternatelen);
res = stun_usage_bind_process (resp, &sockaddr.addr,
&socklen, &alternate.addr, &alternatelen);
nice_debug ("Agent %p : stun_bind_process/disc for %p res %d.",
agent, d, (int)res);
if (res == STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER) {
/* handle alternate server */
NiceAddress niceaddr;
nice_address_set_from_sockaddr (&niceaddr,
(struct sockaddr *) &alternate);
nice_address_set_from_sockaddr (&niceaddr, &alternate.addr);
d->server = niceaddr;
d->pending = FALSE;
} else if (res == STUN_USAGE_BIND_RETURN_SUCCESS) {
/* case: successful binding discovery, create a new local candidate */
NiceAddress niceaddr;
nice_address_set_from_sockaddr (&niceaddr,
(struct sockaddr *) &sockaddr);
nice_address_set_from_sockaddr (&niceaddr, &sockaddr.addr);
discovery_add_server_reflexive_candidate (
d->agent,
......@@ -2341,12 +2350,24 @@ priv_add_new_turn_refresh (CandidateDiscovery *cdisco, NiceCandidate *relay_cand
*/
static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage *resp)
{
struct sockaddr_storage sockaddr;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} sockaddr;
socklen_t socklen = sizeof (sockaddr);
struct sockaddr_storage alternate;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} alternate;
socklen_t alternatelen = sizeof (alternate);
struct sockaddr_storage relayaddr;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} relayaddr;
socklen_t relayaddrlen = sizeof (relayaddr);
uint32_t lifetime;
uint32_t bandwidth;
GSList *i;
......@@ -2365,19 +2386,17 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage *
if (memcmp (discovery_id, response_id, sizeof(StunTransactionId)) == 0) {
res = stun_usage_turn_process (resp,
(struct sockaddr *) &relayaddr, &relayaddrlen,
(struct sockaddr *) &sockaddr, &socklen,
(struct sockaddr *) &alternate, &alternatelen,
&relayaddr.addr, &relayaddrlen,
&sockaddr.addr, &socklen,
&alternate.addr, &alternatelen,
&bandwidth, &lifetime, agent_to_turn_compatibility (agent));
nice_debug ("Agent %p : stun_turn_process/disc for %p res %d.",
agent, d, (int)res);
if (res == STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER) {
/* handle alternate server */
nice_address_set_from_sockaddr (&d->server,
(struct sockaddr *) &alternate);
nice_address_set_from_sockaddr (&d->turn->server,
(struct sockaddr *) &alternate);
nice_address_set_from_sockaddr (&d->server, &alternate.addr);
nice_address_set_from_sockaddr (&d->turn->server, &alternate.addr);
d->pending = FALSE;
} else if (res == STUN_USAGE_TURN_RETURN_RELAY_SUCCESS ||
......@@ -2390,8 +2409,7 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage *
if (res == STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS &&
!nice_socket_is_reliable (d->nicesock)) {
/* We also received our mapped address */
nice_address_set_from_sockaddr (&niceaddr,
(struct sockaddr *) &sockaddr);
nice_address_set_from_sockaddr (&niceaddr, &sockaddr.addr);
discovery_add_server_reflexive_candidate (
d->agent,
......@@ -2401,8 +2419,7 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage *
d->nicesock);
}
nice_address_set_from_sockaddr (&niceaddr,
(struct sockaddr *) &relayaddr);
nice_address_set_from_sockaddr (&niceaddr, &relayaddr.addr);
relay_cand = discovery_add_relay_candidate (
d->agent,
d->stream->id,
......@@ -2696,7 +2713,10 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream,
Component *component, NiceSocket *socket, const NiceAddress *from,
gchar *buf, guint len)
{
struct sockaddr_storage sockaddr;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} sockaddr;
uint8_t rbuf[MAX_STUN_DATAGRAM_PAYLOAD];
ssize_t res;
size_t rbuf_len = sizeof (rbuf);
......@@ -2715,7 +2735,7 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream,
NiceCandidate *local_candidate = NULL;
gboolean discovery_msg = FALSE;
nice_address_copy_to_sockaddr (from, (struct sockaddr *) &sockaddr);
nice_address_copy_to_sockaddr (from, &sockaddr.addr);
/* note: contents of 'buf' already validated, so it is
* a valid and fully received STUN message */
......@@ -2921,7 +2941,7 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream,
rbuf_len = sizeof (rbuf);
res = stun_usage_ice_conncheck_create_reply (&agent->stun_agent, &req,
&msg, rbuf, &rbuf_len, (struct sockaddr *) &sockaddr, sizeof (sockaddr),
&msg, rbuf, &rbuf_len, &sockaddr.addr, sizeof (sockaddr),
&control, agent->tie_breaker,
agent_to_ice_compatibility (agent));
......
......@@ -143,25 +143,30 @@ nice_interfaces_get_local_interfaces (void)
static gboolean
nice_interfaces_is_private_ip (const struct sockaddr *sa)
nice_interfaces_is_private_ip (const struct sockaddr *_sa)
{
if (sa->sa_family == AF_INET) {
struct sockaddr_in *sa4 = (struct sockaddr_in *) sa;
union {
const struct sockaddr *addr;
const struct sockaddr_in *in;
} sa;
sa.addr = _sa;
if (sa.addr->sa_family == AF_INET) {
/* 10.x.x.x/8 */
if (sa4->sin_addr.s_addr >> 24 == 0x0A)
if (sa.in->sin_addr.s_addr >> 24 == 0x0A)
return TRUE;
/* 172.16.0.0 - 172.31.255.255 = 172.16.0.0/10 */
if (sa4->sin_addr.s_addr >> 20 == 0xAC1)
if (sa.in->sin_addr.s_addr >> 20 == 0xAC1)
return TRUE;
/* 192.168.x.x/16 */
if (sa4->sin_addr.s_addr >> 16 == 0xC0A8)
if (sa.in->sin_addr.s_addr >> 16 == 0xC0A8)
return TRUE;
/* 169.254.x.x/16 (for APIPA) */
if (sa4->sin_addr.s_addr >> 16 == 0xA9FE)
if (sa.in->sin_addr.s_addr >> 16 == 0xA9FE)
return TRUE;
}
......@@ -185,6 +190,14 @@ nice_interfaces_get_local_ips (gboolean include_loopback)
for (ifa = results; ifa; ifa = ifa->ifa_next) {
char addr_as_string[INET6_ADDRSTRLEN+1];
union {
struct sockaddr *addr;
struct sockaddr_in *in;
struct sockaddr_in6 *in6;
} sa;
sa.addr = ifa->ifa_addr;
/* no ip address from interface that is down */
if ((ifa->ifa_flags & IFF_UP) == 0)
continue;
......@@ -192,19 +205,15 @@ nice_interfaces_get_local_ips (gboolean include_loopback)
if (ifa->ifa_addr == NULL) {
continue;
} else if (ifa->ifa_addr->sa_family == AF_INET) {
struct sockaddr_in *sa4 = (struct sockaddr_in *) ifa->ifa_addr;
if (inet_ntop (AF_INET, &sa4->sin_addr, addr_as_string,
if (inet_ntop (AF_INET, &sa.in->sin_addr, addr_as_string,
INET6_ADDRSTRLEN) == NULL)
continue;
} else if (ifa->ifa_addr->sa_family == AF_INET6) {
struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)ifa->ifa_addr;
/* Skip link-local addresses, they require a scope */
if (IN6_IS_ADDR_LINKLOCAL (&sa6->sin6_addr))
if (IN6_IS_ADDR_LINKLOCAL (&sa.in6->sin6_addr))
continue;
if (inet_ntop (AF_INET6, &sa6->sin6_addr, addr_as_string,
if (inet_ntop (AF_INET6, &sa.in6->sin6_addr, addr_as_string,
INET6_ADDRSTRLEN) == NULL)
continue;
} else
......@@ -318,7 +327,10 @@ gchar *
nice_interfaces_get_ip_for_interface (gchar *interface_name)
{
struct ifreq ifr;
struct sockaddr_in *sa;
union {
struct sockaddr *addr;
struct sockaddr_in *in;
} sa;
gint sockfd;
......@@ -339,9 +351,9 @@ nice_interfaces_get_ip_for_interface (gchar *interface_name)
}
close (sockfd);
sa = (struct sockaddr_in *) &ifr.ifr_addr;
nice_debug ("Address for %s: %s", interface_name, inet_ntoa (sa->sin_addr));
return g_strdup (inet_ntoa (sa->sin_addr));
sa.addr = &ifr.ifr_addr;
nice_debug ("Address for %s: %s", interface_name, inet_ntoa (sa.in->sin_addr));
return g_strdup (inet_ntoa (sa.in->sin_addr));
}
#else /* G_OS_UNIX */
......
......@@ -794,32 +794,36 @@ packet(PseudoTcpSocket *self, guint32 seq, guint8 flags,
{
PseudoTcpSocketPrivate *priv = self->priv;
guint32 now = get_current_time();
guint8 buffer[MAX_PACKET];
union {
guint8 u8[MAX_PACKET];
guint16 u16[MAX_PACKET / 2];
guint32 u32[MAX_PACKET / 4];
} buffer;
PseudoTcpWriteResult wres = WR_SUCCESS;
g_assert(HEADER_SIZE + len <= MAX_PACKET);
*((guint32 *) buffer) = htonl(priv->conv);
*((guint32 *) (buffer + 4)) = htonl(seq);
*((guint32 *) (buffer + 8)) = htonl(priv->rcv_nxt);
buffer[12] = 0;
buffer[13] = flags;
*((guint16 *) (buffer + 14)) = htons((guint16)priv->rcv_wnd);
*buffer.u32 = htonl(priv->conv);
*(buffer.u32 + 1) = htonl(seq);
*(buffer.u32 + 2) = htonl(priv->rcv_nxt);
buffer.u8[12] = 0;
buffer.u8[13] = flags;
*(buffer.u16 + 7) = htons((guint16)priv->rcv_wnd);
// Timestamp computations
*((guint32 *) (buffer + 16)) = htonl(now);
*((guint32 *) (buffer + 20)) = htonl(priv->ts_recent);
*(buffer.u32 + 4) = htonl(now);
*(buffer.u32 + 5) = htonl(priv->ts_recent);
priv->ts_lastack = priv->rcv_nxt;
if (data != NULL)
memcpy(buffer + HEADER_SIZE, data, len);
memcpy(buffer.u8 + HEADER_SIZE, data, len);
DEBUG (PSEUDO_TCP_DEBUG_VERBOSE, "<-- <CONV=%d><FLG=%d><SEQ=%d:%d><ACK=%d>"
"<WND=%d><TS=%d><TSR=%d><LEN=%d>",
priv->conv, (unsigned)flags, seq, seq + len, priv->rcv_nxt, priv->rcv_wnd,
now % 10000, priv->ts_recent % 10000, len);
wres = priv->callbacks.WritePacket(self, (gchar *) buffer, len + HEADER_SIZE,
wres = priv->callbacks.WritePacket(self, (gchar *) buffer.u8, len + HEADER_SIZE,
priv->callbacks.user_data);
/* Note: When data is NULL, this is an ACK packet. We don't read the
return value for those, and thus we won't retry. So go ahead and treat
......@@ -839,23 +843,31 @@ packet(PseudoTcpSocket *self, guint32 seq, guint8 flags,
}
static gboolean
parse(PseudoTcpSocket *self, const guint8 * buffer, guint32 size)
parse(PseudoTcpSocket *self, const guint8 * _buffer, guint32 size)
{
Segment seg;
union {
const guint8 *u8;
const guint16 *u16;
const guint32 *u32;
} buffer;
buffer.u8 = _buffer;
if (size < 12)
return FALSE;
seg.conv = ntohl(*(guint32 *)buffer);
seg.seq = ntohl(*(guint32 *)(buffer + 4));
seg.ack = ntohl(*(guint32 *)(buffer + 8));
seg.flags = buffer[13];
seg.wnd = ntohs(*(guint16 *)(buffer + 14));
seg.conv = ntohl(*buffer.u32);
seg.seq = ntohl(*(buffer.u32 + 1));
seg.ack = ntohl(*(buffer.u32 + 2));
seg.flags = buffer.u8[13];
seg.wnd = ntohs(*(buffer.u16 + 7));
seg.tsval = ntohl(*(guint32 *)(buffer + 16));
seg.tsecr = ntohl(*(guint32 *)(buffer + 20));
seg.tsval = ntohl(*(buffer.u32 + 4));
seg.tsecr = ntohl(*(buffer.u32 + 5));
seg.data = ((gchar *)buffer) + HEADER_SIZE;
seg.data = ((gchar *)buffer.u8) + HEADER_SIZE;
seg.len = size - HEADER_SIZE;
DEBUG (PSEUDO_TCP_DEBUG_VERBOSE, "--> <CONV=%d><FLG=%d><SEQ=%d:%d><ACK=%d>"
......
......@@ -343,27 +343,32 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint buf_len, gchar *buf)
{
gchar msg[22];
gint len = 0;
struct sockaddr_storage name;
nice_address_copy_to_sockaddr(&priv->addr, (struct sockaddr *)&name);
union {
struct sockaddr_storage storage;
struct sockaddr addr;
struct sockaddr_in in;
struct sockaddr_in6 in6;
} name;
nice_address_copy_to_sockaddr(&priv->addr, &name.addr);
msg[len++] = 0x05; /* SOCKS version */
msg[len++] = 0x01; /* connect command */
msg[len++] = 0x00; /* reserved */
if (name.ss_family == AF_INET) {
if (name.storage.ss_family == AF_INET) {
msg[len++] = 0x01; /* IPV4 address type */
/* Address */
memcpy (msg + len, &((struct sockaddr_in *) &name)->sin_addr, 4);
memcpy (msg + len, &(&name.in)->sin_addr, 4);
len += 4;
/* Port */
memcpy (msg + len, &((struct sockaddr_in *) &name)->sin_port, 2);
memcpy (msg + len, &(&name.in)->sin_port, 2);
len += 2;
} else if (name.ss_family == AF_INET6) {
} else if (name.storage.ss_family == AF_INET6) {
msg[len++] = 0x04; /* IPV6 address type */
/* Address */
memcpy (msg + len, &((struct sockaddr_in6 *) &name)->sin6_addr, 16);
memcpy (msg + len, &(&name.in6)->sin6_addr, 16);
len += 16;
/* Port */
memcpy (msg + len, &((struct sockaddr_in6 *) &name)->sin6_port, 2);
memcpy (msg + len, &(&name.in6)->sin6_port, 2);
len += 2;
}
......
......@@ -86,7 +86,10 @@ static gboolean socket_send_more (GSocket *gsocket, GIOCondition condition,
NiceSocket *
nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr)
{
struct sockaddr_storage name;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} name;
NiceSocket *sock;
TcpPriv *priv;
GSocket *gsock = NULL;
......@@ -101,23 +104,23 @@ nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr)
sock = g_slice_new0 (NiceSocket);
nice_address_copy_to_sockaddr (addr, (struct sockaddr *)&name);
nice_address_copy_to_sockaddr (addr, &name.addr);
if (gsock == NULL) {
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_STREAM,
G_SOCKET_PROTOCOL_TCP, 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_STREAM,
G_SOCKET_PROTOCOL_TCP, 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
}
}
......@@ -130,7 +133,7 @@ nice_tcp_bsd_socket_new (GMainContext *ctx, 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_connect (gsock, gaddr, NULL, &gerr);
......@@ -149,7 +152,7 @@ nice_tcp_bsd_socket_new (GMainContext *ctx, 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);
......@@ -157,7 +160,7 @@ nice_tcp_bsd_socket_new (GMainContext *ctx, 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);
sock->priv = priv = g_slice_new0 (TcpPriv);
......
......@@ -54,8 +54,11 @@
typedef struct {
NiceTurnSocketCompatibility compatibility;
gchar recv_buf[65536];
guint recv_buf_len;
union {
guint8 u8[65536];
guint16 u16[32768];
} recv_buf;
gsize recv_buf_len; /* in bytes */
guint expecting_len;
NiceSocket *base_socket;
} TurnTcpPriv;
......@@ -122,7 +125,8 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
return -1;
ret = nice_socket_recv (priv->base_socket, from,
headerlen - priv->recv_buf_len, priv->recv_buf + priv->recv_buf_len);
headerlen - priv->recv_buf_len,
(gchar *) priv->recv_buf.u8 + priv->recv_buf_len);
if (ret < 0)
return ret;
......@@ -133,8 +137,8 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
guint16 magic = ntohs (*(guint16*)priv->recv_buf);
guint16 packetlen = ntohs (*(guint16*)(priv->recv_buf + 2));
guint16 magic = ntohs (*priv->recv_buf.u16);
guint16 packetlen = ntohs (*(priv->recv_buf.u16 + 1));
if (magic < 0x4000) {
/* Its STUN */
......@@ -145,8 +149,8 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
}
}
else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
guint len = ntohs (*(guint16*)priv->recv_buf);
priv->expecting_len = len;
guint compat_len = ntohs (*priv->recv_buf.u16);
priv->expecting_len = compat_len;
priv->recv_buf_len = 0;
}
}
......@@ -159,7 +163,7 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
ret = nice_socket_recv (priv->base_socket, from,
priv->expecting_len + padlen - priv->recv_buf_len,
priv->recv_buf + priv->recv_buf_len);
(gchar *) priv->recv_buf.u8 + priv->recv_buf_len);
if (ret < 0)
return ret;
......@@ -168,7 +172,7 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
if (priv->recv_buf_len == priv->expecting_len + padlen) {
guint copy_len = MIN (len, priv->recv_buf_len);
memcpy (buf, priv->recv_buf, copy_len);
memcpy (buf, priv->recv_buf.u8, copy_len);
priv->expecting_len = 0;
priv->recv_buf_len = 0;
......
......@@ -491,7 +491,10 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
StunMessage msg;
uint8_t buffer[STUN_MAX_MESSAGE_SIZE];
size_t msg_len;
struct sockaddr_storage sa;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} sa;
GList *i = priv->channels;
ChannelBinding *binding = NULL;
......@@ -503,7 +506,7 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
}
}
nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa);
nice_address_copy_to_sockaddr (to, &sa.addr);
if (binding) {
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
......@@ -528,7 +531,7 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
buffer, sizeof(buffer), STUN_IND_SEND))
goto send;
if (stun_message_append_xor_addr (&msg, STUN_ATTRIBUTE_PEER_ADDRESS,
(struct sockaddr *)&sa, sizeof(sa)) !=
&sa.addr, sizeof(sa)) !=
STUN_MESSAGE_RETURN_SUCCESS)
goto send;
} else {
......@@ -546,7 +549,7 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
goto send;
}
if (stun_message_append_addr (&msg, STUN_ATTRIBUTE_DESTINATION_ADDRESS,
(struct sockaddr *)&sa, sizeof(sa)) !=
&sa.addr, sizeof(sa)) !=
STUN_MESSAGE_RETURN_SUCCESS)
goto send;
......@@ -682,16 +685,18 @@ priv_binding_expired_timeout (gpointer data)
priv->channels = g_list_remove (priv->channels, b);
/* Make sure we don't free a currently being-refreshed binding */
if (priv->current_binding_msg && !priv->current_binding) {
struct sockaddr_storage sa;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} sa;
socklen_t sa_len = sizeof(sa);
NiceAddress to;
/* look up binding associated with peer */
stun_message_find_xor_addr (
&priv->current_binding_msg->message,
STUN_ATTRIBUTE_XOR_PEER_ADDRESS, (struct sockaddr *) &sa,
&sa_len);
nice_address_set_from_sockaddr (&to, (struct sockaddr *) &sa);
STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &sa.addr, &sa_len);
nice_address_set_from_sockaddr (&to, &sa.addr);
/* If the binding is being refreshed, then move it to
priv->current_binding so it counts as a 'new' binding and
......@@ -756,7 +761,7 @@ priv_binding_timeout (gpointer data)
gint
nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
NiceAddress *from, guint len, gchar *buf,
NiceAddress *recv_from, gchar *recv_buf, guint recv_len)
NiceAddress *recv_from, gchar *_recv_buf, guint recv_len)
{
TurnPriv *priv = (TurnPriv *) sock->priv;
......@@ -765,9 +770,16 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
GList *l;
ChannelBinding *binding = NULL;
union {
guint8 *u8;
guint16 *u16;
} recv_buf;
recv_buf.u8 = (guint8 *) _recv_buf;
if (nice_address_equal (&priv->server_addr, recv_from)) {
valid = stun_agent_validate (&priv->agent, &msg,
(uint8_t *) recv_buf, (size_t) recv_len, NULL, NULL);
recv_buf.u8, (size_t) recv_len, NULL, NULL);
if (valid == STUN_VALIDATION_SUCCESS) {
if (priv->compatibility != NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 &&
......@@ -854,16 +866,18 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
} else {
/* Existing binding refresh */
GList *i;
struct sockaddr_storage sa;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} sa;
socklen_t sa_len = sizeof(sa);
NiceAddress to;
/* look up binding associated with peer */
stun_message_find_xor_addr (
&priv->current_binding_msg->message,
STUN_ATTRIBUTE_XOR_PEER_ADDRESS, (struct sockaddr *) &sa,
&sa_len);
nice_address_set_from_sockaddr (&to, (struct sockaddr *) &sa);
STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &sa.addr, &sa_len);
nice_address_set_from_sockaddr (&to, &sa.addr);
for (i = priv->channels; i; i = i->next) {
ChannelBinding *b = i->data;
......@@ -953,16 +967,18 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
if (memcmp (request_id, response_id,
sizeof(StunTransactionId)) == 0) {
struct sockaddr_storage peer;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} peer;
socklen_t peer_len = sizeof(peer);
NiceAddress to;
nice_debug ("got response for CreatePermission");
stun_message_find_xor_addr (
&current_create_permission_msg->message,
STUN_ATTRIBUTE_XOR_PEER_ADDRESS, (struct sockaddr *) &peer,
&peer_len);
nice_address_set_from_sockaddr (&to, (struct sockaddr *) &peer);
STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &peer.addr, &peer_len);
nice_address_set_from_sockaddr (&to, &peer.addr);
/* unathorized => resend with realm and nonce */
if (stun_message_get_class (&msg) == STUN_ERROR) {
......@@ -1033,18 +1049,21 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
stun_message_get_method (&msg) == STUN_IND_DATA) {
uint16_t data_len;
uint8_t *data;
struct sockaddr_storage sa;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} sa;
socklen_t from_len = sizeof (sa);
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
if (stun_message_find_xor_addr (&msg, STUN_ATTRIBUTE_REMOTE_ADDRESS,
(struct sockaddr *)&sa, &from_len) !=
&sa.addr, &from_len) !=
STUN_MESSAGE_RETURN_SUCCESS)
goto recv;
} else {
if (stun_message_find_addr (&msg, STUN_ATTRIBUTE_REMOTE_ADDRESS,
(struct sockaddr *)&sa, &from_len) !=
&sa.addr, &from_len) !=
STUN_MESSAGE_RETURN_SUCCESS)
goto recv;
}
......@@ -1055,7 +1074,7 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
if (data == NULL)
goto recv;
nice_address_set_from_sockaddr (from, (struct sockaddr *) &sa);
nice_address_set_from_sockaddr (from, &sa.addr);
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766 &&
!priv_has_permission_for_peer (priv, from)) {
......@@ -1078,9 +1097,9 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
ChannelBinding *b = l->data;
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
if (b->channel == ntohs(((uint16_t *)recv_buf)[0])) {
recv_len = ntohs (((uint16_t *)recv_buf)[1]);
recv_buf += sizeof(uint32_t);
if (b->channel == ntohs(recv_buf.u16[0])) {
recv_len = ntohs (recv_buf.u16[1]);
recv_buf.u8 += sizeof(uint32_t);
binding = b;
break;
}
......@@ -1097,7 +1116,7 @@ nice_turn_socket_parse_recv (NiceSocket *sock, NiceSocket **from_sock,
*from = *recv_from;
}
memmove (buf, recv_buf, len > recv_len ? recv_len : len);
memmove (buf, recv_buf.u8, len > recv_len ? recv_len : len);
return len > recv_len ? recv_len : len;
msn_google_lock:
......@@ -1214,16 +1233,18 @@ priv_retransmissions_create_permission_tick_unlocked (TurnPriv *priv, GList *lis
/* Time out */
StunTransactionId id;
NiceAddress to;
struct sockaddr_storage addr;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} addr;
socklen_t addr_len = sizeof(addr);
stun_message_id (&current_create_permission_msg->message, id);
stun_agent_forget_transaction (&priv->agent, id);
stun_message_find_xor_addr (
&current_create_permission_msg->message,
STUN_ATTRIBUTE_XOR_PEER_ADDRESS, (struct sockaddr *) &addr,
&addr_len);
nice_address_set_from_sockaddr (&to, (struct sockaddr *) &addr);
STUN_ATTRIBUTE_XOR_PEER_ADDRESS, &addr.addr, &addr_len);
nice_address_set_from_sockaddr (&to, &addr.addr);
priv_remove_sent_permission_for_peer (priv, &to);
priv->pending_permissions = g_list_delete_link (
......@@ -1392,7 +1413,10 @@ priv_send_create_permission(TurnPriv *priv, StunMessage *resp,
guint msg_buf_len;
gboolean res = FALSE;
TURNMessage *msg = g_new0 (TURNMessage, 1);
struct sockaddr_storage addr;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} addr;
uint8_t *realm = NULL;
uint16_t realm_len = 0;
uint8_t *nonce = NULL;
......@@ -1410,7 +1434,7 @@ priv_send_create_permission(TurnPriv *priv, StunMessage *resp,
priv_add_sent_permission_for_peer (priv, peer);
}
nice_address_copy_to_sockaddr (peer, (struct sockaddr *) &addr);
nice_address_copy_to_sockaddr (peer, &addr.addr);
/* send CreatePermission */
msg_buf_len = stun_usage_turn_create_permission(&priv->agent, &msg->message,
......@@ -1422,7 +1446,7 @@ priv_send_create_permission(TurnPriv *priv, StunMessage *resp,
priv->password_len,
realm, realm_len,
nonce, nonce_len,
(struct sockaddr *) &addr,
&addr.addr,
STUN_USAGE_TURN_COMPATIBILITY_RFC5766);
if (msg_buf_len > 0) {
......@@ -1452,10 +1476,13 @@ priv_send_channel_bind (TurnPriv *priv, StunMessage *resp,
{
uint32_t channel_attr = channel << 16;
size_t stun_len;
struct sockaddr_storage sa;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} sa;
TURNMessage *msg = g_new0 (TURNMessage, 1);
nice_address_copy_to_sockaddr (peer, (struct sockaddr *)&sa);
nice_address_copy_to_sockaddr (peer, &sa.addr);
if (!stun_agent_init_request (&priv->agent, &msg->message,
msg->buffer, sizeof(msg->buffer),
......@@ -1471,7 +1498,7 @@ priv_send_channel_bind (TurnPriv *priv, StunMessage *resp,
}
if (stun_message_append_xor_addr (&msg->message, STUN_ATTRIBUTE_PEER_ADDRESS,
(struct sockaddr *)&sa,
&sa.addr,
sizeof(sa))
!= STUN_MESSAGE_RETURN_SUCCESS) {
g_free (msg);
......@@ -1528,9 +1555,12 @@ static gboolean
priv_add_channel_binding (TurnPriv *priv, const NiceAddress *peer)
{
size_t stun_len;
struct sockaddr_storage sa;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} sa;
nice_address_copy_to_sockaddr (peer, (struct sockaddr *)&sa);
nice_address_copy_to_sockaddr (peer, &sa.addr);
if (priv->current_binding) {
NiceAddress * pending= nice_address_new ();
......@@ -1598,7 +1628,7 @@ priv_add_channel_binding (TurnPriv *priv, const NiceAddress *peer)
if (stun_message_append_addr (&msg->message,
STUN_ATTRIBUTE_DESTINATION_ADDRESS,
(struct sockaddr *)&sa, sizeof(sa))
&sa.addr, sizeof(sa))
!= STUN_MESSAGE_RETURN_SUCCESS) {
g_free (msg);
return FALSE;
......
......@@ -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;
......
......@@ -475,19 +475,21 @@ stun_message_append_xor_addr (StunMessage *msg, StunAttribute type,
{
StunMessageReturn val;
/* Must be big enough to hold any supported address: */
struct sockaddr_storage xor;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} xor;
if ((size_t) addrlen > sizeof (xor))
addrlen = sizeof (xor);
memcpy (&xor, addr, addrlen);
memcpy (&xor.storage, addr, addrlen);
val = stun_xor_address (msg, (struct sockaddr *)&xor, addrlen,
val = stun_xor_address (msg, &xor.addr, addrlen,
STUN_MAGIC_COOKIE);
if (val)
return val;
return stun_message_append_addr (msg, type, (struct sockaddr *)&xor,
addrlen);
return stun_message_append_addr (msg, type, &xor.addr, addrlen);
}
StunMessageReturn
......@@ -497,18 +499,20 @@ stun_message_append_xor_addr_full (StunMessage *msg, StunAttribute type,
{
StunMessageReturn val;
/* Must be big enough to hold any supported address: */
struct sockaddr_storage xor;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} xor;
if ((size_t) addrlen > sizeof (xor))
addrlen = sizeof (xor);
memcpy (&xor, addr, addrlen);
memcpy (&xor.storage, addr, addrlen);
val = stun_xor_address (msg, (struct sockaddr *)&xor, addrlen, magic_cookie);
val = stun_xor_address (msg, &xor.addr, addrlen, magic_cookie);
if (val)
return val;
return stun_message_append_addr (msg, type, (struct sockaddr *)&xor,
addrlen);
return stun_message_append_addr (msg, type, &xor.addr, addrlen);
}
......
......@@ -99,19 +99,22 @@ static int run (int family, const char *hostname, const char *service)
for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
{
struct sockaddr_storage addr;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} addr;
socklen_t addrlen = sizeof (addr);
StunUsageBindReturn val;
printaddr ("Server address", ptr->ai_addr, ptr->ai_addrlen);
val = stun_usage_bind_run (ptr->ai_addr, ptr->ai_addrlen,
(struct sockaddr *)&addr, &addrlen);
&addr.addr, &addrlen);
if (val)
fprintf (stderr, "%d\n", val);
else
{
printaddr ("Mapped address", (struct sockaddr *)&addr, addrlen);
printaddr ("Mapped address", &addr.addr, addrlen);
ret = 0;
}
}
......
......@@ -131,7 +131,7 @@ int listen_socket (int fam, int type, int proto, unsigned int port)
assert (0); /* should never be reached */
}
if (bind (fd, (struct sockaddr *)&addr, sizeof (struct sockaddr)))
if (bind (fd, &addr.addr, sizeof (struct sockaddr)))
{
perror ("Error opening IP port");
goto error;
......@@ -175,7 +175,10 @@ error:
static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
{
struct sockaddr_storage addr;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} addr;
socklen_t addr_len;
uint8_t buf[STUN_MAX_MESSAGE_SIZE];
size_t buf_len = 0;
......@@ -186,8 +189,7 @@ static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
StunAgent *agent = NULL;
addr_len = sizeof (struct sockaddr_in);
len = recvfrom (sock, buf, sizeof(buf), 0,
(struct sockaddr *)&addr, &addr_len);
len = recvfrom (sock, buf, sizeof(buf), 0, &addr.addr, &addr_len);
if (len == (size_t)-1)
return -1;
......@@ -221,11 +223,10 @@ static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
stun_agent_init_response (agent, &response, buf, sizeof (buf), &request);
if (stun_message_has_cookie (&request))
stun_message_append_xor_addr (&response,
STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
(struct sockaddr *)&addr, addr_len);
STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &addr.addr, addr_len);
else
stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS,
(struct sockaddr *)&addr, addr_len);
&addr.addr, addr_len);
break;
default:
......@@ -236,8 +237,7 @@ static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
buf_len = stun_agent_finish_message (agent, &response, NULL, 0);
send_buf:
len = sendto (sock, buf, buf_len, 0,
(struct sockaddr *)&addr, addr_len);
len = sendto (sock, buf, buf_len, 0, &addr.addr, addr_len);
return (len < buf_len) ? -1 : 0;
}
......
......@@ -396,8 +396,14 @@ stun_trans_recvfrom (StunTransport *tr, uint8_t *buf, size_t maxlen,
static ssize_t
stun_trans_send (StunTransport *tr, const uint8_t *buf, size_t len)
{
return stun_trans_sendto (tr, buf, len,
(struct sockaddr *)&tr->dst, tr->dstlen);
union {
struct sockaddr_storage *storage;
struct sockaddr *addr;
} conv;
conv.storage = &tr->dst;
return stun_trans_sendto (tr, buf, len, conv.addr, tr->dstlen);
}
static ssize_t
......@@ -461,7 +467,10 @@ StunUsageBindReturn stun_usage_bind_run (const struct sockaddr *srv,
size_t len;
StunUsageTransReturn ret;
int val;
struct sockaddr_storage alternate_server;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} alternate_server;
socklen_t alternate_server_len = sizeof (alternate_server);
StunUsageBindReturn bind_ret;
......@@ -526,12 +535,12 @@ StunUsageBindReturn stun_usage_bind_run (const struct sockaddr *srv,
ret = STUN_USAGE_TRANS_RETURN_RETRY;
} else {
bind_ret = stun_usage_bind_process (&msg, addr, addrlen,
(struct sockaddr *) &alternate_server, &alternate_server_len);
&alternate_server.addr, &alternate_server_len);
if (bind_ret == STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER) {
stun_trans_deinit (&trans);
ret = stun_trans_create (&trans, SOCK_DGRAM, 0,
(struct sockaddr *) &alternate_server, alternate_server_len);
&alternate_server.addr, alternate_server_len);
if (ret != STUN_USAGE_TRANS_RETURN_SUCCESS) {
return STUN_USAGE_BIND_RETURN_ERROR;
......
......@@ -168,10 +168,13 @@ StunUsageIceReturn stun_usage_ice_conncheck_process (StunMessage *msg,
stun_debug ("Received %u-bytes STUN message\n", stun_message_length (msg));
if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSN) {
StunTransactionId transid;
union {
StunTransactionId u8;
uint32_t u32[STUN_MESSAGE_TRANS_ID_LEN / 4];
} transid;
uint32_t magic_cookie;
stun_message_id (msg, transid);
magic_cookie = *((uint32_t *) transid);
stun_message_id (msg, transid.u8);
magic_cookie = *(transid.u32);
val = stun_message_find_xor_addr_full (msg,
STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, addr, addrlen, htonl (magic_cookie));
......@@ -287,13 +290,15 @@ stun_usage_ice_conncheck_create_reply (StunAgent *agent, StunMessage *req,
goto failure;
}
if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSN) {
union {
StunTransactionId transid;
uint32_t magic_cookie;
stun_message_id (msg, transid);
magic_cookie = *((uint32_t *) transid);
} conv;
stun_message_id (msg, conv.transid);
val = stun_message_append_xor_addr_full (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
src, srclen, htonl (magic_cookie));
src, srclen, htonl (conv.magic_cookie));
} else if (stun_message_has_cookie (msg) &&
compatibility != STUN_USAGE_ICE_COMPATIBILITY_GOOGLE) {
val = stun_message_append_xor_addr (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
......
......@@ -91,11 +91,19 @@ StunMessageReturn stun_xor_address (const StunMessage *msg,
struct sockaddr *addr, socklen_t addrlen,
uint32_t magic_cookie)
{
union {
struct sockaddr *addr;
struct sockaddr_in *in;
struct sockaddr_in6 *in6;
} addr_ptr;
addr_ptr.addr = addr;
switch (addr->sa_family)
{
case AF_INET:
{
struct sockaddr_in *ip4 = (struct sockaddr_in *)addr;
struct sockaddr_in *ip4 = addr_ptr.in;
if ((size_t) addrlen < sizeof (*ip4))
return STUN_MESSAGE_RETURN_INVALID;
......@@ -106,7 +114,7 @@ StunMessageReturn stun_xor_address (const StunMessage *msg,
case AF_INET6:
{
struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)addr;
struct sockaddr_in6 *ip6 = addr_ptr.in6;
unsigned short i;
if ((size_t) addrlen < sizeof (*ip6))
......
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