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, ...@@ -226,20 +226,25 @@ nice_address_set_from_sockaddr (NiceAddress *addr,
NICEAPI_EXPORT void NICEAPI_EXPORT void
nice_address_copy_to_sockaddr (const NiceAddress *addr, nice_address_copy_to_sockaddr (const NiceAddress *addr,
struct sockaddr *sa) struct sockaddr *_sa)
{ {
struct sockaddr_in *sin4 = (struct sockaddr_in *)sa; union {
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa; 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) switch (addr->s.addr.sa_family)
{ {
case AF_INET: case AF_INET:
memcpy (sin4, &addr->s.ip4, sizeof (*sin4)); memcpy (sa.in, &addr->s.ip4, sizeof (*sa.in));
break; break;
case AF_INET6: case AF_INET6:
memcpy (sin6, &addr->s.ip6, sizeof (*sin6)); memcpy (sa.in6, &addr->s.ip6, sizeof (*sa.in6));
break; break;
default: default:
g_return_if_reached (); g_return_if_reached ();
......
...@@ -2096,7 +2096,10 @@ static CandidateCheckPair *priv_process_response_check_for_peer_reflexive(NiceAg ...@@ -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) 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); socklen_t socklen = sizeof (sockaddr);
GSList *i; GSList *i;
StunUsageIceReturn res; StunUsageIceReturn res;
...@@ -2113,7 +2116,7 @@ static gboolean priv_map_reply_to_conn_check_request (NiceAgent *agent, Stream * ...@@ -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) { if (memcmp (discovery_id, response_id, sizeof(StunTransactionId)) == 0) {
res = stun_usage_ice_conncheck_process (resp, res = stun_usage_ice_conncheck_process (resp,
(struct sockaddr *) &sockaddr, &socklen, &sockaddr.addr, &socklen,
agent_to_ice_compatibility (agent)); agent_to_ice_compatibility (agent));
nice_debug ("Agent %p : stun_bind_process/conncheck for %p res %d " nice_debug ("Agent %p : stun_bind_process/conncheck for %p res %d "
"(controlling=%d).", agent, p, (int)res, agent->controlling_mode); "(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 * ...@@ -2164,7 +2167,7 @@ static gboolean priv_map_reply_to_conn_check_request (NiceAgent *agent, Stream *
priv_conn_check_unfreeze_related (agent, stream, p); priv_conn_check_unfreeze_related (agent, stream, p);
} else { } else {
ok_pair = priv_process_response_check_for_peer_reflexive(agent, 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); local_candidate, remote_candidate);
} }
...@@ -2226,10 +2229,18 @@ static gboolean priv_map_reply_to_conn_check_request (NiceAgent *agent, Stream * ...@@ -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) 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); socklen_t socklen = sizeof (sockaddr);
struct sockaddr_storage alternate;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} alternate;
socklen_t alternatelen = sizeof (sockaddr); socklen_t alternatelen = sizeof (sockaddr);
GSList *i; GSList *i;
StunUsageBindReturn res; StunUsageBindReturn res;
gboolean trans_found = FALSE; gboolean trans_found = FALSE;
...@@ -2245,24 +2256,22 @@ static gboolean priv_map_reply_to_discovery_request (NiceAgent *agent, StunMessa ...@@ -2245,24 +2256,22 @@ static gboolean priv_map_reply_to_discovery_request (NiceAgent *agent, StunMessa
stun_message_id (&d->stun_message, discovery_id); stun_message_id (&d->stun_message, discovery_id);
if (memcmp (discovery_id, response_id, sizeof(StunTransactionId)) == 0) { if (memcmp (discovery_id, response_id, sizeof(StunTransactionId)) == 0) {
res = stun_usage_bind_process (resp, (struct sockaddr *) &sockaddr, res = stun_usage_bind_process (resp, &sockaddr.addr,
&socklen, (struct sockaddr *) &alternate, &alternatelen); &socklen, &alternate.addr, &alternatelen);
nice_debug ("Agent %p : stun_bind_process/disc for %p res %d.", nice_debug ("Agent %p : stun_bind_process/disc for %p res %d.",
agent, d, (int)res); agent, d, (int)res);
if (res == STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER) { if (res == STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER) {
/* handle alternate server */ /* handle alternate server */
NiceAddress niceaddr; NiceAddress niceaddr;
nice_address_set_from_sockaddr (&niceaddr, nice_address_set_from_sockaddr (&niceaddr, &alternate.addr);
(struct sockaddr *) &alternate);
d->server = niceaddr; d->server = niceaddr;
d->pending = FALSE; d->pending = FALSE;
} else if (res == STUN_USAGE_BIND_RETURN_SUCCESS) { } else if (res == STUN_USAGE_BIND_RETURN_SUCCESS) {
/* case: successful binding discovery, create a new local candidate */ /* case: successful binding discovery, create a new local candidate */
NiceAddress niceaddr; NiceAddress niceaddr;
nice_address_set_from_sockaddr (&niceaddr, nice_address_set_from_sockaddr (&niceaddr, &sockaddr.addr);
(struct sockaddr *) &sockaddr);
discovery_add_server_reflexive_candidate ( discovery_add_server_reflexive_candidate (
d->agent, d->agent,
...@@ -2341,12 +2350,24 @@ priv_add_new_turn_refresh (CandidateDiscovery *cdisco, NiceCandidate *relay_cand ...@@ -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) 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); socklen_t socklen = sizeof (sockaddr);
struct sockaddr_storage alternate;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} alternate;
socklen_t alternatelen = sizeof (alternate); socklen_t alternatelen = sizeof (alternate);
struct sockaddr_storage relayaddr;
union {
struct sockaddr_storage storage;
struct sockaddr addr;
} relayaddr;
socklen_t relayaddrlen = sizeof (relayaddr); socklen_t relayaddrlen = sizeof (relayaddr);
uint32_t lifetime; uint32_t lifetime;
uint32_t bandwidth; uint32_t bandwidth;
GSList *i; GSList *i;
...@@ -2365,19 +2386,17 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage * ...@@ -2365,19 +2386,17 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage *
if (memcmp (discovery_id, response_id, sizeof(StunTransactionId)) == 0) { if (memcmp (discovery_id, response_id, sizeof(StunTransactionId)) == 0) {
res = stun_usage_turn_process (resp, res = stun_usage_turn_process (resp,
(struct sockaddr *) &relayaddr, &relayaddrlen, &relayaddr.addr, &relayaddrlen,
(struct sockaddr *) &sockaddr, &socklen, &sockaddr.addr, &socklen,
(struct sockaddr *) &alternate, &alternatelen, &alternate.addr, &alternatelen,
&bandwidth, &lifetime, agent_to_turn_compatibility (agent)); &bandwidth, &lifetime, agent_to_turn_compatibility (agent));
nice_debug ("Agent %p : stun_turn_process/disc for %p res %d.", nice_debug ("Agent %p : stun_turn_process/disc for %p res %d.",
agent, d, (int)res); agent, d, (int)res);
if (res == STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER) { if (res == STUN_USAGE_TURN_RETURN_ALTERNATE_SERVER) {
/* handle alternate server */ /* handle alternate server */
nice_address_set_from_sockaddr (&d->server, nice_address_set_from_sockaddr (&d->server, &alternate.addr);
(struct sockaddr *) &alternate); nice_address_set_from_sockaddr (&d->turn->server, &alternate.addr);
nice_address_set_from_sockaddr (&d->turn->server,
(struct sockaddr *) &alternate);
d->pending = FALSE; d->pending = FALSE;
} else if (res == STUN_USAGE_TURN_RETURN_RELAY_SUCCESS || } else if (res == STUN_USAGE_TURN_RETURN_RELAY_SUCCESS ||
...@@ -2390,8 +2409,7 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage * ...@@ -2390,8 +2409,7 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage *
if (res == STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS && if (res == STUN_USAGE_TURN_RETURN_MAPPED_SUCCESS &&
!nice_socket_is_reliable (d->nicesock)) { !nice_socket_is_reliable (d->nicesock)) {
/* We also received our mapped address */ /* We also received our mapped address */
nice_address_set_from_sockaddr (&niceaddr, nice_address_set_from_sockaddr (&niceaddr, &sockaddr.addr);
(struct sockaddr *) &sockaddr);
discovery_add_server_reflexive_candidate ( discovery_add_server_reflexive_candidate (
d->agent, d->agent,
...@@ -2401,8 +2419,7 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage * ...@@ -2401,8 +2419,7 @@ static gboolean priv_map_reply_to_relay_request (NiceAgent *agent, StunMessage *
d->nicesock); d->nicesock);
} }
nice_address_set_from_sockaddr (&niceaddr, nice_address_set_from_sockaddr (&niceaddr, &relayaddr.addr);
(struct sockaddr *) &relayaddr);
relay_cand = discovery_add_relay_candidate ( relay_cand = discovery_add_relay_candidate (
d->agent, d->agent,
d->stream->id, d->stream->id,
...@@ -2696,7 +2713,10 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream, ...@@ -2696,7 +2713,10 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream,
Component *component, NiceSocket *socket, const NiceAddress *from, Component *component, NiceSocket *socket, const NiceAddress *from,
gchar *buf, guint len) gchar *buf, guint len)
{ {
struct sockaddr_storage sockaddr; union {
struct sockaddr_storage storage;
struct sockaddr addr;
} sockaddr;
uint8_t rbuf[MAX_STUN_DATAGRAM_PAYLOAD]; uint8_t rbuf[MAX_STUN_DATAGRAM_PAYLOAD];
ssize_t res; ssize_t res;
size_t rbuf_len = sizeof (rbuf); size_t rbuf_len = sizeof (rbuf);
...@@ -2715,7 +2735,7 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream, ...@@ -2715,7 +2735,7 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream,
NiceCandidate *local_candidate = NULL; NiceCandidate *local_candidate = NULL;
gboolean discovery_msg = FALSE; 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 /* note: contents of 'buf' already validated, so it is
* a valid and fully received STUN message */ * a valid and fully received STUN message */
...@@ -2921,7 +2941,7 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream, ...@@ -2921,7 +2941,7 @@ gboolean conn_check_handle_inbound_stun (NiceAgent *agent, Stream *stream,
rbuf_len = sizeof (rbuf); rbuf_len = sizeof (rbuf);
res = stun_usage_ice_conncheck_create_reply (&agent->stun_agent, &req, 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, &control, agent->tie_breaker,
agent_to_ice_compatibility (agent)); agent_to_ice_compatibility (agent));
......
...@@ -143,25 +143,30 @@ nice_interfaces_get_local_interfaces (void) ...@@ -143,25 +143,30 @@ nice_interfaces_get_local_interfaces (void)
static gboolean 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) { union {
struct sockaddr_in *sa4 = (struct sockaddr_in *) sa; 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 */ /* 10.x.x.x/8 */
if (sa4->sin_addr.s_addr >> 24 == 0x0A) if (sa.in->sin_addr.s_addr >> 24 == 0x0A)
return TRUE; return TRUE;
/* 172.16.0.0 - 172.31.255.255 = 172.16.0.0/10 */ /* 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; return TRUE;
/* 192.168.x.x/16 */ /* 192.168.x.x/16 */
if (sa4->sin_addr.s_addr >> 16 == 0xC0A8) if (sa.in->sin_addr.s_addr >> 16 == 0xC0A8)
return TRUE; return TRUE;
/* 169.254.x.x/16 (for APIPA) */ /* 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; return TRUE;
} }
...@@ -185,6 +190,14 @@ nice_interfaces_get_local_ips (gboolean include_loopback) ...@@ -185,6 +190,14 @@ nice_interfaces_get_local_ips (gboolean include_loopback)
for (ifa = results; ifa; ifa = ifa->ifa_next) { for (ifa = results; ifa; ifa = ifa->ifa_next) {
char addr_as_string[INET6_ADDRSTRLEN+1]; 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 */ /* no ip address from interface that is down */
if ((ifa->ifa_flags & IFF_UP) == 0) if ((ifa->ifa_flags & IFF_UP) == 0)
continue; continue;
...@@ -192,19 +205,15 @@ nice_interfaces_get_local_ips (gboolean include_loopback) ...@@ -192,19 +205,15 @@ nice_interfaces_get_local_ips (gboolean include_loopback)
if (ifa->ifa_addr == NULL) { if (ifa->ifa_addr == NULL) {
continue; continue;
} else if (ifa->ifa_addr->sa_family == AF_INET) { } else if (ifa->ifa_addr->sa_family == AF_INET) {
struct sockaddr_in *sa4 = (struct sockaddr_in *) ifa->ifa_addr; if (inet_ntop (AF_INET, &sa.in->sin_addr, addr_as_string,
if (inet_ntop (AF_INET, &sa4->sin_addr, addr_as_string,
INET6_ADDRSTRLEN) == NULL) INET6_ADDRSTRLEN) == NULL)
continue; continue;
} else if (ifa->ifa_addr->sa_family == AF_INET6) { } 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 */ /* 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; 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) INET6_ADDRSTRLEN) == NULL)
continue; continue;
} else } else
...@@ -318,7 +327,10 @@ gchar * ...@@ -318,7 +327,10 @@ gchar *
nice_interfaces_get_ip_for_interface (gchar *interface_name) nice_interfaces_get_ip_for_interface (gchar *interface_name)
{ {
struct ifreq ifr; struct ifreq ifr;
struct sockaddr_in *sa; union {
struct sockaddr *addr;
struct sockaddr_in *in;
} sa;
gint sockfd; gint sockfd;
...@@ -339,9 +351,9 @@ nice_interfaces_get_ip_for_interface (gchar *interface_name) ...@@ -339,9 +351,9 @@ nice_interfaces_get_ip_for_interface (gchar *interface_name)
} }
close (sockfd); close (sockfd);
sa = (struct sockaddr_in *) &ifr.ifr_addr; sa.addr = &ifr.ifr_addr;
nice_debug ("Address for %s: %s", interface_name, inet_ntoa (sa->sin_addr)); nice_debug ("Address for %s: %s", interface_name, inet_ntoa (sa.in->sin_addr));
return g_strdup (inet_ntoa (sa->sin_addr)); return g_strdup (inet_ntoa (sa.in->sin_addr));
} }
#else /* G_OS_UNIX */ #else /* G_OS_UNIX */
......
...@@ -794,32 +794,36 @@ packet(PseudoTcpSocket *self, guint32 seq, guint8 flags, ...@@ -794,32 +794,36 @@ packet(PseudoTcpSocket *self, guint32 seq, guint8 flags,
{ {
PseudoTcpSocketPrivate *priv = self->priv; PseudoTcpSocketPrivate *priv = self->priv;
guint32 now = get_current_time(); 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; PseudoTcpWriteResult wres = WR_SUCCESS;
g_assert(HEADER_SIZE + len <= MAX_PACKET); g_assert(HEADER_SIZE + len <= MAX_PACKET);
*((guint32 *) buffer) = htonl(priv->conv); *buffer.u32 = htonl(priv->conv);
*((guint32 *) (buffer + 4)) = htonl(seq); *(buffer.u32 + 1) = htonl(seq);
*((guint32 *) (buffer + 8)) = htonl(priv->rcv_nxt); *(buffer.u32 + 2) = htonl(priv->rcv_nxt);
buffer[12] = 0; buffer.u8[12] = 0;
buffer[13] = flags; buffer.u8[13] = flags;
*((guint16 *) (buffer + 14)) = htons((guint16)priv->rcv_wnd); *(buffer.u16 + 7) = htons((guint16)priv->rcv_wnd);
// Timestamp computations // Timestamp computations
*((guint32 *) (buffer + 16)) = htonl(now); *(buffer.u32 + 4) = htonl(now);
*((guint32 *) (buffer + 20)) = htonl(priv->ts_recent); *(buffer.u32 + 5) = htonl(priv->ts_recent);
priv->ts_lastack = priv->rcv_nxt; priv->ts_lastack = priv->rcv_nxt;
if (data != NULL) 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>" DEBUG (PSEUDO_TCP_DEBUG_VERBOSE, "<-- <CONV=%d><FLG=%d><SEQ=%d:%d><ACK=%d>"
"<WND=%d><TS=%d><TSR=%d><LEN=%d>", "<WND=%d><TS=%d><TSR=%d><LEN=%d>",
priv->conv, (unsigned)flags, seq, seq + len, priv->rcv_nxt, priv->rcv_wnd, priv->conv, (unsigned)flags, seq, seq + len, priv->rcv_nxt, priv->rcv_wnd,
now % 10000, priv->ts_recent % 10000, len); 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); priv->callbacks.user_data);
/* Note: When data is NULL, this is an ACK packet. We don't read the /* 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 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, ...@@ -839,23 +843,31 @@ packet(PseudoTcpSocket *self, guint32 seq, guint8 flags,
} }
static gboolean static gboolean
parse(PseudoTcpSocket *self, const guint8 * buffer, guint32 size) parse(PseudoTcpSocket *self, const guint8 * _buffer, guint32 size)
{ {
Segment seg; Segment seg;
union {
const guint8 *u8;
const guint16 *u16;
const guint32 *u32;
} buffer;
buffer.u8 = _buffer;
if (size < 12) if (size < 12)
return FALSE; return FALSE;
seg.conv = ntohl(*(guint32 *)buffer); seg.conv = ntohl(*buffer.u32);
seg.seq = ntohl(*(guint32 *)(buffer + 4)); seg.seq = ntohl(*(buffer.u32 + 1));
seg.ack = ntohl(*(guint32 *)(buffer + 8)); seg.ack = ntohl(*(buffer.u32 + 2));
seg.flags = buffer[13]; seg.flags = buffer.u8[13];
seg.wnd = ntohs(*(guint16 *)(buffer + 14)); seg.wnd = ntohs(*(buffer.u16 + 7));
seg.tsval = ntohl(*(guint32 *)(buffer + 16)); seg.tsval = ntohl(*(buffer.u32 + 4));
seg.tsecr = ntohl(*(guint32 *)(buffer + 20)); seg.tsecr = ntohl(*(buffer.u32 + 5));
seg.data = ((gchar *)buffer) + HEADER_SIZE; seg.data = ((gchar *)buffer.u8) + HEADER_SIZE;
seg.len = size - HEADER_SIZE; seg.len = size - HEADER_SIZE;
DEBUG (PSEUDO_TCP_DEBUG_VERBOSE, "--> <CONV=%d><FLG=%d><SEQ=%d:%d><ACK=%d>" 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) ...@@ -343,27 +343,32 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint buf_len, gchar *buf)
{ {
gchar msg[22]; gchar msg[22];
gint len = 0; gint len = 0;
struct sockaddr_storage name; union {
nice_address_copy_to_sockaddr(&priv->addr, (struct sockaddr *)&name); 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++] = 0x05; /* SOCKS version */
msg[len++] = 0x01; /* connect command */ msg[len++] = 0x01; /* connect command */
msg[len++] = 0x00; /* reserved */ msg[len++] = 0x00; /* reserved */
if (name.ss_family == AF_INET) { if (name.storage.ss_family == AF_INET) {
msg[len++] = 0x01; /* IPV4 address type */ msg[len++] = 0x01; /* IPV4 address type */
/* Address */ /* Address */
memcpy (msg + len, &((struct sockaddr_in *) &name)->sin_addr, 4); memcpy (msg + len, &(&name.in)->sin_addr, 4);
len += 4; len += 4;
/* Port */ /* Port */
memcpy (msg + len, &((struct sockaddr_in *) &name)->sin_port, 2); memcpy (msg + len, &(&name.in)->sin_port, 2);
len += 2; len += 2;
} else if (name.ss_family == AF_INET6) { } else if (name.storage.ss_family == AF_INET6) {
msg[len++] = 0x04; /* IPV6 address type */ msg[len++] = 0x04; /* IPV6 address type */
/* Address */ /* Address */
memcpy (msg + len, &((struct sockaddr_in6 *) &name)->sin6_addr, 16); memcpy (msg + len, &(&name.in6)->sin6_addr, 16);
len += 16; len += 16;
/* Port */ /* Port */
memcpy (msg + len, &((struct sockaddr_in6 *) &name)->sin6_port, 2); memcpy (msg + len, &(&name.in6)->sin6_port, 2);
len += 2; len += 2;
} }
......
...@@ -86,7 +86,10 @@ static gboolean socket_send_more (GSocket *gsocket, GIOCondition condition, ...@@ -86,7 +86,10 @@ static gboolean socket_send_more (GSocket *gsocket, GIOCondition condition,
NiceSocket * NiceSocket *
nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr) nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr)
{ {
struct sockaddr_storage name; union {
struct sockaddr_storage storage;
struct sockaddr addr;
} name;
NiceSocket *sock; NiceSocket *sock;
TcpPriv *priv; TcpPriv *priv;
GSocket *gsock = NULL; GSocket *gsock = NULL;
...@@ -101,23 +104,23 @@ nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr) ...@@ -101,23 +104,23 @@ nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr)
sock = g_slice_new0 (NiceSocket); 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 (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, gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_TCP, NULL); G_SOCKET_PROTOCOL_TCP, NULL);
name.ss_family = AF_INET; name.storage.ss_family = AF_INET;
#ifdef HAVE_SA_LEN #ifdef HAVE_SA_LEN
name.ss_len = sizeof (struct sockaddr_in); name.storage.ss_len = sizeof (struct sockaddr_in);
#endif #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, gsock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_STREAM,
G_SOCKET_PROTOCOL_TCP, NULL); G_SOCKET_PROTOCOL_TCP, NULL);
name.ss_family = AF_INET6; name.storage.ss_family = AF_INET6;
#ifdef HAVE_SA_LEN #ifdef HAVE_SA_LEN
name.ss_len = sizeof (struct sockaddr_in6); name.storage.ss_len = sizeof (struct sockaddr_in6);
#endif #endif
} }
} }
...@@ -130,7 +133,7 @@ nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr) ...@@ -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. */ /* GSocket: All socket file descriptors are set to be close-on-exec. */
g_socket_set_blocking (gsock, false); 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) { if (gaddr != NULL) {
gret = g_socket_connect (gsock, gaddr, NULL, &gerr); gret = g_socket_connect (gsock, gaddr, NULL, &gerr);
...@@ -149,7 +152,7 @@ nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr) ...@@ -149,7 +152,7 @@ nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr)
gaddr = g_socket_get_local_address (gsock, NULL); gaddr = g_socket_get_local_address (gsock, NULL);
if (gaddr == 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_slice_free (NiceSocket, sock);
g_socket_close (gsock, NULL); g_socket_close (gsock, NULL);
g_object_unref (gsock); g_object_unref (gsock);
...@@ -157,7 +160,7 @@ nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr) ...@@ -157,7 +160,7 @@ nice_tcp_bsd_socket_new (GMainContext *ctx, NiceAddress *addr)
} }
g_object_unref (gaddr); 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); sock->priv = priv = g_slice_new0 (TcpPriv);
......
...@@ -54,8 +54,11 @@ ...@@ -54,8 +54,11 @@
typedef struct { typedef struct {
NiceTurnSocketCompatibility compatibility; NiceTurnSocketCompatibility compatibility;
gchar recv_buf[65536]; union {
guint recv_buf_len; guint8 u8[65536];
guint16 u16[32768];
} recv_buf;
gsize recv_buf_len; /* in bytes */
guint expecting_len; guint expecting_len;
NiceSocket *base_socket; NiceSocket *base_socket;
} TurnTcpPriv; } TurnTcpPriv;
...@@ -122,7 +125,8 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) ...@@ -122,7 +125,8 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
return -1; return -1;
ret = nice_socket_recv (priv->base_socket, from, 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) if (ret < 0)
return ret; return ret;
...@@ -133,8 +137,8 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) ...@@ -133,8 +137,8 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 || if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_DRAFT9 ||
priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) { priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_RFC5766) {
guint16 magic = ntohs (*(guint16*)priv->recv_buf); guint16 magic = ntohs (*priv->recv_buf.u16);
guint16 packetlen = ntohs (*(guint16*)(priv->recv_buf + 2)); guint16 packetlen = ntohs (*(priv->recv_buf.u16 + 1));
if (magic < 0x4000) { if (magic < 0x4000) {
/* Its STUN */ /* Its STUN */
...@@ -145,8 +149,8 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) ...@@ -145,8 +149,8 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
} }
} }
else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) { else if (priv->compatibility == NICE_TURN_SOCKET_COMPATIBILITY_GOOGLE) {
guint len = ntohs (*(guint16*)priv->recv_buf); guint compat_len = ntohs (*priv->recv_buf.u16);
priv->expecting_len = len; priv->expecting_len = compat_len;
priv->recv_buf_len = 0; priv->recv_buf_len = 0;
} }
} }
...@@ -159,7 +163,7 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) ...@@ -159,7 +163,7 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
ret = nice_socket_recv (priv->base_socket, from, ret = nice_socket_recv (priv->base_socket, from,
priv->expecting_len + padlen - priv->recv_buf_len, 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) if (ret < 0)
return ret; return ret;
...@@ -168,7 +172,7 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) ...@@ -168,7 +172,7 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
if (priv->recv_buf_len == priv->expecting_len + padlen) { if (priv->recv_buf_len == priv->expecting_len + padlen) {
guint copy_len = MIN (len, priv->recv_buf_len); 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->expecting_len = 0;
priv->recv_buf_len = 0; priv->recv_buf_len = 0;
......
This diff is collapsed.
...@@ -72,7 +72,10 @@ struct UdpBsdSocketPrivate ...@@ -72,7 +72,10 @@ struct UdpBsdSocketPrivate
NiceSocket * NiceSocket *
nice_udp_bsd_socket_new (NiceAddress *addr) 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); NiceSocket *sock = g_slice_new0 (NiceSocket);
GSocket *gsock = NULL; GSocket *gsock = NULL;
gboolean gret = FALSE; gboolean gret = FALSE;
...@@ -80,25 +83,25 @@ nice_udp_bsd_socket_new (NiceAddress *addr) ...@@ -80,25 +83,25 @@ nice_udp_bsd_socket_new (NiceAddress *addr)
struct UdpBsdSocketPrivate *priv; struct UdpBsdSocketPrivate *priv;
if (addr != NULL) { if (addr != NULL) {
nice_address_copy_to_sockaddr(addr, (struct sockaddr *)&name); nice_address_copy_to_sockaddr(addr, &name.addr);
} else { } else {
memset (&name, 0, sizeof (name)); 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, gsock = g_socket_new (G_SOCKET_FAMILY_IPV4, G_SOCKET_TYPE_DATAGRAM,
G_SOCKET_PROTOCOL_UDP, NULL); G_SOCKET_PROTOCOL_UDP, NULL);
name.ss_family = AF_INET; name.storage.ss_family = AF_INET;
#ifdef HAVE_SA_LEN #ifdef HAVE_SA_LEN
name.ss_len = sizeof (struct sockaddr_in); name.storage.ss_len = sizeof (struct sockaddr_in);
#endif #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, gsock = g_socket_new (G_SOCKET_FAMILY_IPV6, G_SOCKET_TYPE_DATAGRAM,
G_SOCKET_PROTOCOL_UDP, NULL); G_SOCKET_PROTOCOL_UDP, NULL);
name.ss_family = AF_INET6; name.storage.ss_family = AF_INET6;
#ifdef HAVE_SA_LEN #ifdef HAVE_SA_LEN
name.ss_len = sizeof (struct sockaddr_in6); name.storage.ss_len = sizeof (struct sockaddr_in6);
#endif #endif
} }
...@@ -109,7 +112,7 @@ nice_udp_bsd_socket_new (NiceAddress *addr) ...@@ -109,7 +112,7 @@ nice_udp_bsd_socket_new (NiceAddress *addr)
/* GSocket: All socket file descriptors are set to be close-on-exec. */ /* GSocket: All socket file descriptors are set to be close-on-exec. */
g_socket_set_blocking (gsock, false); 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) { if (gaddr != NULL) {
gret = g_socket_bind (gsock, gaddr, FALSE, NULL); gret = g_socket_bind (gsock, gaddr, FALSE, NULL);
g_object_unref (gaddr); g_object_unref (gaddr);
...@@ -124,7 +127,7 @@ nice_udp_bsd_socket_new (NiceAddress *addr) ...@@ -124,7 +127,7 @@ nice_udp_bsd_socket_new (NiceAddress *addr)
gaddr = g_socket_get_local_address (gsock, NULL); gaddr = g_socket_get_local_address (gsock, NULL);
if (gaddr == 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_slice_free (NiceSocket, sock);
g_socket_close (gsock, NULL); g_socket_close (gsock, NULL);
g_object_unref (gsock); g_object_unref (gsock);
...@@ -133,7 +136,7 @@ nice_udp_bsd_socket_new (NiceAddress *addr) ...@@ -133,7 +136,7 @@ nice_udp_bsd_socket_new (NiceAddress *addr)
g_object_unref (gaddr); 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); priv = sock->priv = g_slice_new0 (struct UdpBsdSocketPrivate);
nice_address_init (&priv->niceaddr); nice_address_init (&priv->niceaddr);
...@@ -181,10 +184,13 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf) ...@@ -181,10 +184,13 @@ socket_recv (NiceSocket *sock, NiceAddress *from, guint len, gchar *buf)
} }
if (recvd > 0 && from != NULL && gaddr != NULL) { 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); g_socket_address_to_native (gaddr, &sa.addr, sizeof (sa), NULL);
nice_address_set_from_sockaddr (from, (struct sockaddr *)&sa); nice_address_set_from_sockaddr (from, &sa.addr);
} }
if (gaddr != NULL) if (gaddr != NULL)
...@@ -202,13 +208,16 @@ socket_send (NiceSocket *sock, const NiceAddress *to, ...@@ -202,13 +208,16 @@ socket_send (NiceSocket *sock, const NiceAddress *to,
if (!nice_address_is_valid (&priv->niceaddr) || if (!nice_address_is_valid (&priv->niceaddr) ||
!nice_address_equal (&priv->niceaddr, to)) { !nice_address_equal (&priv->niceaddr, to)) {
struct sockaddr_storage sa; union {
struct sockaddr_storage storage;
struct sockaddr addr;
} sa;
GSocketAddress *gaddr; GSocketAddress *gaddr;
if (priv->gaddr) if (priv->gaddr)
g_object_unref (priv->gaddr); g_object_unref (priv->gaddr);
nice_address_copy_to_sockaddr (to, (struct sockaddr *)&sa); nice_address_copy_to_sockaddr (to, &sa.addr);
gaddr = g_socket_address_new_from_native (&sa, sizeof(sa)); gaddr = g_socket_address_new_from_native (&sa.addr, sizeof(sa));
if (gaddr == NULL) if (gaddr == NULL)
return -1; return -1;
priv->gaddr = gaddr; priv->gaddr = gaddr;
......
...@@ -475,19 +475,21 @@ stun_message_append_xor_addr (StunMessage *msg, StunAttribute type, ...@@ -475,19 +475,21 @@ stun_message_append_xor_addr (StunMessage *msg, StunAttribute type,
{ {
StunMessageReturn val; StunMessageReturn val;
/* Must be big enough to hold any supported address: */ /* 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)) if ((size_t) addrlen > sizeof (xor))
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); STUN_MAGIC_COOKIE);
if (val) if (val)
return val; return val;
return stun_message_append_addr (msg, type, (struct sockaddr *)&xor, return stun_message_append_addr (msg, type, &xor.addr, addrlen);
addrlen);
} }
StunMessageReturn StunMessageReturn
...@@ -497,18 +499,20 @@ stun_message_append_xor_addr_full (StunMessage *msg, StunAttribute type, ...@@ -497,18 +499,20 @@ stun_message_append_xor_addr_full (StunMessage *msg, StunAttribute type,
{ {
StunMessageReturn val; StunMessageReturn val;
/* Must be big enough to hold any supported address: */ /* 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)) if ((size_t) addrlen > sizeof (xor))
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) if (val)
return val; return val;
return stun_message_append_addr (msg, type, (struct sockaddr *)&xor, return stun_message_append_addr (msg, type, &xor.addr, addrlen);
addrlen);
} }
......
...@@ -99,19 +99,22 @@ static int run (int family, const char *hostname, const char *service) ...@@ -99,19 +99,22 @@ static int run (int family, const char *hostname, const char *service)
for (ptr = res; ptr != NULL; ptr = ptr->ai_next) 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); socklen_t addrlen = sizeof (addr);
StunUsageBindReturn val; StunUsageBindReturn val;
printaddr ("Server address", ptr->ai_addr, ptr->ai_addrlen); printaddr ("Server address", ptr->ai_addr, ptr->ai_addrlen);
val = stun_usage_bind_run (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) if (val)
fprintf (stderr, "%d\n", val); fprintf (stderr, "%d\n", val);
else else
{ {
printaddr ("Mapped address", (struct sockaddr *)&addr, addrlen); printaddr ("Mapped address", &addr.addr, addrlen);
ret = 0; ret = 0;
} }
} }
......
...@@ -131,7 +131,7 @@ int listen_socket (int fam, int type, int proto, unsigned int port) ...@@ -131,7 +131,7 @@ int listen_socket (int fam, int type, int proto, unsigned int port)
assert (0); /* should never be reached */ 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"); perror ("Error opening IP port");
goto error; goto error;
...@@ -175,7 +175,10 @@ error: ...@@ -175,7 +175,10 @@ error:
static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent) 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; socklen_t addr_len;
uint8_t buf[STUN_MAX_MESSAGE_SIZE]; uint8_t buf[STUN_MAX_MESSAGE_SIZE];
size_t buf_len = 0; size_t buf_len = 0;
...@@ -186,8 +189,7 @@ static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent) ...@@ -186,8 +189,7 @@ static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
StunAgent *agent = NULL; StunAgent *agent = NULL;
addr_len = sizeof (struct sockaddr_in); addr_len = sizeof (struct sockaddr_in);
len = recvfrom (sock, buf, sizeof(buf), 0, len = recvfrom (sock, buf, sizeof(buf), 0, &addr.addr, &addr_len);
(struct sockaddr *)&addr, &addr_len);
if (len == (size_t)-1) if (len == (size_t)-1)
return -1; return -1;
...@@ -221,11 +223,10 @@ static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent) ...@@ -221,11 +223,10 @@ static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
stun_agent_init_response (agent, &response, buf, sizeof (buf), &request); stun_agent_init_response (agent, &response, buf, sizeof (buf), &request);
if (stun_message_has_cookie (&request)) if (stun_message_has_cookie (&request))
stun_message_append_xor_addr (&response, stun_message_append_xor_addr (&response,
STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, &addr.addr, addr_len);
(struct sockaddr *)&addr, addr_len);
else else
stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS, stun_message_append_addr (&response, STUN_ATTRIBUTE_MAPPED_ADDRESS,
(struct sockaddr *)&addr, addr_len); &addr.addr, addr_len);
break; break;
default: default:
...@@ -236,8 +237,7 @@ static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent) ...@@ -236,8 +237,7 @@ static int dgram_process (int sock, StunAgent *oldagent, StunAgent *newagent)
buf_len = stun_agent_finish_message (agent, &response, NULL, 0); buf_len = stun_agent_finish_message (agent, &response, NULL, 0);
send_buf: send_buf:
len = sendto (sock, buf, buf_len, 0, len = sendto (sock, buf, buf_len, 0, &addr.addr, addr_len);
(struct sockaddr *)&addr, addr_len);
return (len < buf_len) ? -1 : 0; return (len < buf_len) ? -1 : 0;
} }
......
...@@ -396,8 +396,14 @@ stun_trans_recvfrom (StunTransport *tr, uint8_t *buf, size_t maxlen, ...@@ -396,8 +396,14 @@ stun_trans_recvfrom (StunTransport *tr, uint8_t *buf, size_t maxlen,
static ssize_t static ssize_t
stun_trans_send (StunTransport *tr, const uint8_t *buf, size_t len) stun_trans_send (StunTransport *tr, const uint8_t *buf, size_t len)
{ {
return stun_trans_sendto (tr, buf, len, union {
(struct sockaddr *)&tr->dst, tr->dstlen); 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 static ssize_t
...@@ -461,7 +467,10 @@ StunUsageBindReturn stun_usage_bind_run (const struct sockaddr *srv, ...@@ -461,7 +467,10 @@ StunUsageBindReturn stun_usage_bind_run (const struct sockaddr *srv,
size_t len; size_t len;
StunUsageTransReturn ret; StunUsageTransReturn ret;
int val; 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); socklen_t alternate_server_len = sizeof (alternate_server);
StunUsageBindReturn bind_ret; StunUsageBindReturn bind_ret;
...@@ -526,12 +535,12 @@ StunUsageBindReturn stun_usage_bind_run (const struct sockaddr *srv, ...@@ -526,12 +535,12 @@ StunUsageBindReturn stun_usage_bind_run (const struct sockaddr *srv,
ret = STUN_USAGE_TRANS_RETURN_RETRY; ret = STUN_USAGE_TRANS_RETURN_RETRY;
} else { } else {
bind_ret = stun_usage_bind_process (&msg, addr, addrlen, 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) { if (bind_ret == STUN_USAGE_BIND_RETURN_ALTERNATE_SERVER) {
stun_trans_deinit (&trans); stun_trans_deinit (&trans);
ret = stun_trans_create (&trans, SOCK_DGRAM, 0, 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) { if (ret != STUN_USAGE_TRANS_RETURN_SUCCESS) {
return STUN_USAGE_BIND_RETURN_ERROR; return STUN_USAGE_BIND_RETURN_ERROR;
......
...@@ -168,10 +168,13 @@ StunUsageIceReturn stun_usage_ice_conncheck_process (StunMessage *msg, ...@@ -168,10 +168,13 @@ StunUsageIceReturn stun_usage_ice_conncheck_process (StunMessage *msg,
stun_debug ("Received %u-bytes STUN message\n", stun_message_length (msg)); stun_debug ("Received %u-bytes STUN message\n", stun_message_length (msg));
if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSN) { 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; uint32_t magic_cookie;
stun_message_id (msg, transid); stun_message_id (msg, transid.u8);
magic_cookie = *((uint32_t *) transid); magic_cookie = *(transid.u32);
val = stun_message_find_xor_addr_full (msg, val = stun_message_find_xor_addr_full (msg,
STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, addr, addrlen, htonl (magic_cookie)); STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, addr, addrlen, htonl (magic_cookie));
...@@ -287,13 +290,15 @@ stun_usage_ice_conncheck_create_reply (StunAgent *agent, StunMessage *req, ...@@ -287,13 +290,15 @@ stun_usage_ice_conncheck_create_reply (StunAgent *agent, StunMessage *req,
goto failure; goto failure;
} }
if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSN) { if (compatibility == STUN_USAGE_ICE_COMPATIBILITY_MSN) {
union {
StunTransactionId transid; StunTransactionId transid;
uint32_t magic_cookie; uint32_t magic_cookie;
stun_message_id (msg, transid); } conv;
magic_cookie = *((uint32_t *) transid);
stun_message_id (msg, conv.transid);
val = stun_message_append_xor_addr_full (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, 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) && } else if (stun_message_has_cookie (msg) &&
compatibility != STUN_USAGE_ICE_COMPATIBILITY_GOOGLE) { compatibility != STUN_USAGE_ICE_COMPATIBILITY_GOOGLE) {
val = stun_message_append_xor_addr (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS, val = stun_message_append_xor_addr (msg, STUN_ATTRIBUTE_XOR_MAPPED_ADDRESS,
......
...@@ -91,11 +91,19 @@ StunMessageReturn stun_xor_address (const StunMessage *msg, ...@@ -91,11 +91,19 @@ StunMessageReturn stun_xor_address (const StunMessage *msg,
struct sockaddr *addr, socklen_t addrlen, struct sockaddr *addr, socklen_t addrlen,
uint32_t magic_cookie) 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) switch (addr->sa_family)
{ {
case AF_INET: case AF_INET:
{ {
struct sockaddr_in *ip4 = (struct sockaddr_in *)addr; struct sockaddr_in *ip4 = addr_ptr.in;
if ((size_t) addrlen < sizeof (*ip4)) if ((size_t) addrlen < sizeof (*ip4))
return STUN_MESSAGE_RETURN_INVALID; return STUN_MESSAGE_RETURN_INVALID;
...@@ -106,7 +114,7 @@ StunMessageReturn stun_xor_address (const StunMessage *msg, ...@@ -106,7 +114,7 @@ StunMessageReturn stun_xor_address (const StunMessage *msg,
case AF_INET6: case AF_INET6:
{ {
struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)addr; struct sockaddr_in6 *ip6 = addr_ptr.in6;
unsigned short i; unsigned short i;
if ((size_t) addrlen < sizeof (*ip6)) 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