diff --git a/tpws/helpers.c b/tpws/helpers.c index 6e6705f..5e5393e 100644 --- a/tpws/helpers.c +++ b/tpws/helpers.c @@ -183,6 +183,10 @@ void sacopy(struct sockaddr_storage *sa_dest, const struct sockaddr *sa) sa_dest->ss_family = 0; } } +void sa46copy(sockaddr_in46 *sa_dest, const struct sockaddr *sa) +{ + sacopy((struct sockaddr_storage*)sa_dest, sa); +} bool is_localnet(const struct sockaddr *a) { diff --git a/tpws/helpers.h b/tpws/helpers.h index edcfcfa..0447809 100644 --- a/tpws/helpers.h +++ b/tpws/helpers.h @@ -8,6 +8,14 @@ #include #include +// this saves memory. sockaddr_storage is larger than required. it can be 128 bytes. sockaddr_in6 is 28 bytes. +typedef union +{ + struct sockaddr_in sa4; // size 16 + struct sockaddr_in6 sa6; // size 28 + char _align[32]; // force 16-byte alignment for ip6_and int128 ops +} sockaddr_in46; + void rtrim(char *s); char *strncasestr(const char *s,const char *find, size_t slen); @@ -27,6 +35,7 @@ uint16_t saport(const struct sockaddr *sa); bool saconvmapped(struct sockaddr_storage *a); void sacopy(struct sockaddr_storage *sa_dest, const struct sockaddr *sa); +void sa46copy(sockaddr_in46 *sa_dest, const struct sockaddr *sa); bool is_localnet(const struct sockaddr *a); bool is_linklocal(const struct sockaddr_in6* a); diff --git a/tpws/resolver.c b/tpws/resolver.c index b9c204f..6fb25bb 100644 --- a/tpws/resolver.c +++ b/tpws/resolver.c @@ -103,7 +103,13 @@ static void *resolver_thread(void *arg) ri->ga_res = getaddrinfo(ri->dom,sport,&hints,&ai); if (!ri->ga_res) { - memcpy(&ri->ss, ai->ai_addr, ai->ai_addrlen); + if (ai->ai_addrlen>sizeof(ri->ss)) + { + DLOG_ERR("getaddrinfo returned too large address\n"); + ri->ga_res = EAI_FAIL; + } + else + memcpy(&ri->ss, ai->ai_addr, ai->ai_addrlen); freeaddrinfo(ai); } //printf("THREAD %d END JOB %s FIRST=%p\n", syscall(SYS_gettid), ri->dom, TAILQ_FIRST(&resolver.resolve_list)); diff --git a/tpws/resolver.h b/tpws/resolver.h index 3151717..d27c578 100644 --- a/tpws/resolver.h +++ b/tpws/resolver.h @@ -6,10 +6,12 @@ #include #include +#include "helpers.h" + struct resolve_item { char dom[256]; // request dom - struct sockaddr_storage ss; // resolve result + sockaddr_in46 ss; // resolve result int ga_res; // getaddrinfo result code uint16_t port; // request port void *ptr; diff --git a/tpws/tpws_conn.c b/tpws/tpws_conn.c index 3597ae8..296d03b 100644 --- a/tpws/tpws_conn.c +++ b/tpws/tpws_conn.c @@ -619,7 +619,7 @@ static tproxy_conn_t* add_tcp_connection(int efd, struct tailhead *conn_list,int if (proxy_type==CONN_TYPE_TRANSPARENT) { - sacopy(&conn->dest, (struct sockaddr *)&orig_dst); + sa46copy(&conn->dest, (struct sockaddr *)&orig_dst); if(!(conn->partner = new_conn(remote_fd, true))) { @@ -662,7 +662,7 @@ static tproxy_conn_t* add_tcp_connection(int efd, struct tailhead *conn_list,int TAILQ_INSERT_HEAD(conn_list, conn->partner, conn_ptrs); legs_remote++; } - + if (proxy_type==CONN_TYPE_TRANSPARENT) apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest); @@ -693,7 +693,7 @@ static bool check_connection_attempt(tproxy_conn_t *conn, int efd) { if (params.debug>=1) { - struct sockaddr_storage sa; + sockaddr_in46 sa; socklen_t salen=sizeof(sa); char ip_port[48]; @@ -920,7 +920,7 @@ static bool handle_proxy_mode(tproxy_conn_t *conn, struct tailhead *conn_list) socks4_send_rep(conn->fd, S4_REP_FAILED); return false; } - conn->dest.ss_family = AF_INET; + ((struct sockaddr_in*)&conn->dest)->sin_family = AF_INET; ((struct sockaddr_in*)&conn->dest)->sin_port = m->port; ((struct sockaddr_in*)&conn->dest)->sin_addr.s_addr = m->ip; return proxy_mode_connect_remote(conn, conn_list); @@ -952,12 +952,12 @@ static bool handle_proxy_mode(tproxy_conn_t *conn, struct tailhead *conn_list) switch(m->atyp) { case S5_ATYP_IP4: - conn->dest.ss_family = AF_INET; + ((struct sockaddr_in*)&conn->dest)->sin_family = AF_INET; ((struct sockaddr_in*)&conn->dest)->sin_port = m->d4.port; ((struct sockaddr_in*)&conn->dest)->sin_addr = m->d4.addr; break; case S5_ATYP_IP6: - conn->dest.ss_family = AF_INET6; + ((struct sockaddr_in6*)&conn->dest)->sin6_family = AF_INET6; ((struct sockaddr_in6*)&conn->dest)->sin6_port = m->d6.port; ((struct sockaddr_in6*)&conn->dest)->sin6_addr = m->d6.addr; ((struct sockaddr_in6*)&conn->dest)->sin6_flowinfo = 0; @@ -1037,7 +1037,7 @@ static bool resolve_complete(struct resolve_item *ri, struct tailhead *conn_list DBGPRINT("resolve_complete put hostname : %s\n", ri->dom); conn->track.hostname = strdup(ri->dom); } - sacopy(&conn->dest, (struct sockaddr *)&ri->ss); + sa46copy(&conn->dest, (struct sockaddr *)&ri->ss); return proxy_mode_connect_remote(conn,conn_list); } } diff --git a/tpws/tpws_conn.h b/tpws/tpws_conn.h index c52cbc8..f165bf0 100644 --- a/tpws/tpws_conn.h +++ b/tpws/tpws_conn.h @@ -54,7 +54,7 @@ struct tproxy_conn int splice_pipe[2]; conn_state_t state; conn_type_t conn_type; - struct sockaddr_storage dest; + sockaddr_in46 src, dest; struct tproxy_conn *partner; // other leg time_t orphan_since;