diff options
author | NIIBE Yutaka <gniibe@fsij.org> | 2018-11-08 18:21:23 +0900 |
---|---|---|
committer | NIIBE Yutaka <gniibe@fsij.org> | 2018-11-08 18:21:23 +0900 |
commit | ea69c7126ff25d7d44950bf4a70467d577989a34 (patch) | |
tree | df4df1e6940b6d16ef1232abebf4e3c0a1d16a95 | |
parent | 50ed4f7d5b68e94464df7c0646c3424cee2f47de (diff) | |
download | libassuan-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.c | 36 |
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; |