summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorrofl0r <rofl0r@users.noreply.github.com>2020-09-18 12:12:14 +0100
committerrofl0r <rofl0r@users.noreply.github.com>2020-09-18 12:12:14 +0100
commitc74fe5726259c508a541eb5b97ca1def7733a5c9 (patch)
treeefb57677b7ccd014fbcfd8e2f08c3f654adc02c9
parentd4ef2cfa625d4a9011d61dcc7537963906ff3105 (diff)
transparent: workaround old glibc bug on RHEL7
it's been reported[0] that RHEL7 fails to properly set the length parameter of the getsockname() call to the length of the required struct sockaddr type, and always returns the length passed if it is big enough. the SOCKADDR_UNION_* macros originate from my microsocks[1] project, and facilitate handling of the sockaddr mess without nasty casts. [0]: https://github.com/tinyproxy/tinyproxy/issues/45#issuecomment-694594990 [1]: https://github.com/rofl0r/microsocks
-rw-r--r--src/sock.h14
-rw-r--r--src/transparent-proxy.c8
2 files changed, 17 insertions, 5 deletions
diff --git a/src/sock.h b/src/sock.h
index 722371d..aee5bf5 100644
--- a/src/sock.h
+++ b/src/sock.h
@@ -31,6 +31,20 @@
#include "common.h"
#include "sblist.h"
+#define SOCKADDR_UNION_AF(PTR) (PTR)->v4.sin_family
+
+#define SOCKADDR_UNION_LENGTH(PTR) ( \
+ ( SOCKADDR_UNION_AF(PTR) == AF_INET ) ? sizeof((PTR)->v4) : ( \
+ ( SOCKADDR_UNION_AF(PTR) == AF_INET6 ) ? sizeof((PTR)->v6) : 0 ) )
+
+#define SOCKADDR_UNION_ADDRESS(PTR) ( \
+ ( SOCKADDR_UNION_AF(PTR) == AF_INET ) ? (void*) &(PTR)->v4.sin_addr : ( \
+ ( SOCKADDR_UNION_AF(PTR) == AF_INET6 ) ? (void*) &(PTR)->v6.sin6_addr : (void*) 0 ) )
+
+#define SOCKADDR_UNION_PORT(PTR) ( \
+ ( SOCKADDR_UNION_AF(PTR) == AF_INET ) ? (PTR)->v4.sin_port : ( \
+ ( SOCKADDR_UNION_AF(PTR) == AF_INET6 ) ? (PTR)->v6.sin6_port : 0 ) )
+
union sockaddr_union {
struct sockaddr_in v4;
struct sockaddr_in6 v6;
diff --git a/src/transparent-proxy.c b/src/transparent-proxy.c
index e3265f9..d090ae3 100644
--- a/src/transparent-proxy.c
+++ b/src/transparent-proxy.c
@@ -83,16 +83,14 @@ do_transparent_proxy (struct conn_s *connptr, orderedmap hashofheaders,
return 0;
}
- af = length == sizeof(dest_addr.v4) ? AF_INET : AF_INET6;
- if (af == AF_INET) dest_inaddr = &dest_addr.v4.sin_addr;
- else dest_inaddr = &dest_addr.v6.sin6_addr;
+ af = SOCKADDR_UNION_AF(&dest_addr);
+ dest_inaddr = SOCKADDR_UNION_ADDRESS(&dest_addr);
if (!inet_ntop(af, dest_inaddr, namebuf, sizeof namebuf))
goto addr_err;
request->host = safestrdup (namebuf);
- request->port = ntohs (af == AF_INET ? dest_addr.v4.sin_port
- : dest_addr.v6.sin6_port);
+ request->port = ntohs (SOCKADDR_UNION_PORT(&dest_addr));
request->path = (char *) safemalloc (ulen + 1);
strlcpy (request->path, *url, ulen + 1);