summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2018-11-08 18:21:23 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2018-11-08 18:21:23 +0900
commitea69c7126ff25d7d44950bf4a70467d577989a34 (patch)
treedf4df1e6940b6d16ef1232abebf4e3c0a1d16a95
parent50ed4f7d5b68e94464df7c0646c3424cee2f47de (diff)
downloadlibassuan-ea69c7126ff25d7d44950bf4a70467d577989a34.tar.gz
socket: Use union for sockaddr access.
* src/assuan-socket.c (socks5_connect, use_socks): Use union to access, instead of using cast to the pointer. -- In some machine like 32-bit ARM, alignment requirement of struct sockaddr and struct sockaddr_in (or struct sockaddr_in6) is different. Although it is completely valid to use the value of the address by cast here, because the object should be allocated by struct sockaddr_in or struct sockaddr_in6 to be referred by struct sockaddr *. But compiler doesn't assume such a usage, thus, emits warnings. The API with struct sockaddr * is a bit difficult thing. I examined GNU C library for the implementation of the connect function, it uses transparent union, the GCC feature. It would be too much, if we do same thing here. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
-rw-r--r--src/assuan-socket.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/src/assuan-socket.c b/src/assuan-socket.c
index 7fb2201..7644ada 100644
--- a/src/assuan-socket.c
+++ b/src/assuan-socket.c
@@ -703,14 +703,19 @@ socks5_connect (assuan_context_t ctx, assuan_fd_t sock,
struct sockaddr_in proxyaddr_in;
struct sockaddr *proxyaddr;
size_t proxyaddrlen;
- struct sockaddr_in6 *addr_in6;
- struct sockaddr_in *addr_in;
+ union {
+ struct sockaddr *addr;
+ struct sockaddr_in *addr_in;
+ struct sockaddr_in6 *addr_in6;
+ } addru;
unsigned char buffer[22+512]; /* The extra 512 gives enough space
for username/password or the
hostname. */
size_t buflen, hostnamelen;
int method;
+ addru.addr = addr;
+
/* memset (&proxyaddr_in6, 0, sizeof proxyaddr_in6); */
memset (&proxyaddr_in, 0, sizeof proxyaddr_in);
@@ -848,20 +853,16 @@ socks5_connect (assuan_context_t ctx, assuan_fd_t sock,
}
else if (addr->sa_family == AF_INET6)
{
- addr_in6 = (struct sockaddr_in6 *)addr;
-
buffer[3] = 4; /* ATYP = IPv6 */
- memcpy (buffer+ 4, &addr_in6->sin6_addr.s6_addr, 16); /* DST.ADDR */
- memcpy (buffer+20, &addr_in6->sin6_port, 2); /* DST.PORT */
+ memcpy (buffer+ 4, &addru.addr_in6->sin6_addr.s6_addr, 16); /* DST.ADDR */
+ memcpy (buffer+20, &addru.addr_in6->sin6_port, 2); /* DST.PORT */
buflen = 22;
}
else
{
- addr_in = (struct sockaddr_in *)addr;
-
buffer[3] = 1; /* ATYP = IPv4 */
- memcpy (buffer+4, &addr_in->sin_addr.s_addr, 4); /* DST.ADDR */
- memcpy (buffer+8, &addr_in->sin_port, 2); /* DST.PORT */
+ memcpy (buffer+4, &addru.addr_in->sin_addr.s_addr, 4); /* DST.ADDR */
+ memcpy (buffer+8, &addru.addr_in->sin_port, 2); /* DST.PORT */
buflen = 10;
}
ret = do_writen (ctx, sock, buffer, buflen);
@@ -931,15 +932,22 @@ socks5_connect (assuan_context_t ctx, assuan_fd_t sock,
static int
use_socks (struct sockaddr *addr)
{
+ union {
+ struct sockaddr *addr;
+ struct sockaddr_in *addr_in;
+ struct sockaddr_in6 *addr_in6;
+ } addru;
+
+ addru.addr = addr;
+
if (!tor_mode)
return 0;
else if (addr->sa_family == AF_INET6)
{
- struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr;
const unsigned char *s;
int i;
- s = (unsigned char *)&addr_in6->sin6_addr.s6_addr;
+ s = (unsigned char *)&addru.addr_in6->sin6_addr.s6_addr;
if (s[15] != 1)
return 1; /* Last octet is not 1 - not the loopback address. */
for (i=0; i < 15; i++, s++)
@@ -950,9 +958,7 @@ use_socks (struct sockaddr *addr)
}
else if (addr->sa_family == AF_INET)
{
- struct sockaddr_in *addr_in = (struct sockaddr_in *)addr;
-
- if (*(unsigned char*)&addr_in->sin_addr.s_addr == 127)
+ if (*(unsigned char*)&addru.addr_in->sin_addr.s_addr == 127)
return 0; /* Loopback (127.0.0.0/8) */
return 1;