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));