Skip to content

Commit 2237749

Browse files
committed
preliminary ipv6 support
only basic testing was done (with 2 socks5 proxies listening on ::1) but seems to work as intended. ipv6 support for the hostsreader (/etc/hosts) is not implemented so far.
1 parent 9969dd3 commit 2237749

7 files changed

+100
-62
lines changed

src/allocator_thread.c

+17-17
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,16 @@ pthread_mutex_t internal_ips_lock;
3838
internal_ip_lookup_table *internal_ips = NULL;
3939
internal_ip_lookup_table internal_ips_buf;
4040

41-
uint32_t index_from_internal_ip(ip_type internalip) {
41+
uint32_t index_from_internal_ip(ip_type4 internalip) {
4242
PFUNC();
43-
ip_type tmp = internalip;
43+
ip_type4 tmp = internalip;
4444
uint32_t ret;
4545
ret = tmp.octet[3] + (tmp.octet[2] << 8) + (tmp.octet[1] << 16);
4646
ret -= 1;
4747
return ret;
4848
}
4949

50-
char *string_from_internal_ip(ip_type internalip) {
50+
char *string_from_internal_ip(ip_type4 internalip) {
5151
PFUNC();
5252
char *res = NULL;
5353
uint32_t index = index_from_internal_ip(internalip);
@@ -57,22 +57,22 @@ char *string_from_internal_ip(ip_type internalip) {
5757
}
5858

5959
extern unsigned int remote_dns_subnet;
60-
ip_type make_internal_ip(uint32_t index) {
61-
ip_type ret;
60+
ip_type4 make_internal_ip(uint32_t index) {
61+
ip_type4 ret;
6262
index++; // so we can start at .0.0.1
6363
if(index > 0xFFFFFF)
64-
return ip_type_invalid;
64+
return ip_type_invalid.addr.v4;
6565
ret.octet[0] = remote_dns_subnet & 0xFF;
6666
ret.octet[1] = (index & 0xFF0000) >> 16;
6767
ret.octet[2] = (index & 0xFF00) >> 8;
6868
ret.octet[3] = index & 0xFF;
6969
return ret;
7070
}
7171

72-
static ip_type ip_from_internal_list(char* name, size_t len) {
72+
static ip_type4 ip_from_internal_list(char* name, size_t len) {
7373
uint32_t hash = dalias_hash((char *) name);
7474
size_t i;
75-
ip_type res;
75+
ip_type4 res;
7676
void* new_mem;
7777
// see if we already have this dns entry saved.
7878
if(internal_ips->counter) {
@@ -99,7 +99,7 @@ static ip_type ip_from_internal_list(char* name, size_t len) {
9999
}
100100

101101
res = make_internal_ip(internal_ips->counter);
102-
if(res.as_int == ip_type_invalid.as_int)
102+
if(res.as_int == ip_type_invalid.addr.v4.as_int)
103103
goto err_plus_unlock;
104104

105105
string_hash_tuple tmp = { 0 };
@@ -128,7 +128,7 @@ static ip_type ip_from_internal_list(char* name, size_t len) {
128128
err_plus_unlock:
129129

130130
PDEBUG("return err\n");
131-
return ip_type_invalid;
131+
return ip_type_invalid.addr.v4;
132132
}
133133

134134
/* stuff for communication with the allocator thread */
@@ -205,15 +205,15 @@ static void* threadfunc(void* x) {
205205
struct at_msghdr msg;
206206
union {
207207
char host[MSG_LEN_MAX];
208-
ip_type ip;
208+
ip_type4 ip;
209209
} readbuf;
210210
while((ret = getmessage(ATD_SERVER, &msg, &readbuf))) {
211211
switch(msg.msgtype) {
212212
case ATM_GETIP:
213213
/* client wants an ip for a DNS name. iterate our list and check if we have an existing entry.
214214
* if not, create a new one. */
215215
readbuf.ip = ip_from_internal_list(readbuf.host, msg.datalen - 1);
216-
msg.datalen = sizeof(ip_type);
216+
msg.datalen = sizeof(ip_type4);
217217
break;
218218
case ATM_GETNAME: {
219219
char *host = string_from_internal_ip(readbuf.ip);
@@ -237,23 +237,23 @@ static void* threadfunc(void* x) {
237237

238238
/* API to access the internal ip mapping */
239239

240-
ip_type at_get_ip_for_host(char* host, size_t len) {
241-
ip_type readbuf;
240+
ip_type4 at_get_ip_for_host(char* host, size_t len) {
241+
ip_type4 readbuf;
242242
MUTEX_LOCK(&internal_ips_lock);
243243
if(len > MSG_LEN_MAX) goto inv;
244244
struct at_msghdr msg = {.msgtype = ATM_GETIP, .datalen = len + 1 };
245245
if(sendmessage(ATD_SERVER, &msg, host) &&
246246
getmessage(ATD_CLIENT, &msg, &readbuf));
247247
else {
248248
inv:
249-
readbuf = ip_type_invalid;
249+
readbuf = ip_type_invalid.addr.v4;
250250
}
251251
MUTEX_UNLOCK(&internal_ips_lock);
252252
return readbuf;
253253
}
254254

255-
size_t at_get_host_for_ip(ip_type ip, char* readbuf) {
256-
struct at_msghdr msg = {.msgtype = ATM_GETNAME, .datalen = sizeof(ip_type) };
255+
size_t at_get_host_for_ip(ip_type4 ip, char* readbuf) {
256+
struct at_msghdr msg = {.msgtype = ATM_GETNAME, .datalen = sizeof(ip_type4) };
257257
size_t res = 0;
258258
MUTEX_LOCK(&internal_ips_lock);
259259
if(sendmessage(ATD_SERVER, &msg, &ip) && getmessage(ATD_CLIENT, &msg, readbuf)) {

src/allocator_thread.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ extern int resp_pipefd[2];
1111

1212
void at_init(void);
1313
void at_close(void);
14-
size_t at_get_host_for_ip(ip_type ip, char* readbuf);
15-
ip_type at_get_ip_for_host(char* host, size_t len);
14+
size_t at_get_host_for_ip(ip_type4 ip, char* readbuf);
15+
ip_type4 at_get_ip_for_host(char* host, size_t len);
1616

1717
//RcB: DEP "allocator_thread.c"
1818
#endif

src/core.c

+49-26
Original file line numberDiff line numberDiff line change
@@ -198,8 +198,8 @@ static int tunnel_to(int sock, ip_type ip, unsigned short port, proxy_type pt, c
198198
// the range 224-255.* is reserved, and it won't go outside (unless the app does some other stuff with
199199
// the results returned from gethostbyname et al.)
200200
// the hardcoded number 224 can now be changed using the config option remote_dns_subnet to i.e. 127
201-
if(ip.octet[0] == remote_dns_subnet) {
202-
dns_len = at_get_host_for_ip(ip, hostnamebuf);
201+
if(!ip.is_v6 && ip.addr.v4.octet[0] == remote_dns_subnet) {
202+
dns_len = at_get_host_for_ip(ip.addr.v4, hostnamebuf);
203203
if(!dns_len) goto err;
204204
else dns_name = hostnamebuf;
205205
}
@@ -216,12 +216,16 @@ static int tunnel_to(int sock, ip_type ip, unsigned short port, proxy_type pt, c
216216

217217
int len;
218218
unsigned char buff[BUFF_SIZE];
219-
char ip_buf[16];
219+
char ip_buf[INET6_ADDRSTRLEN];
220+
int v6 = ip.is_v6;
220221

221222
switch (pt) {
222223
case HTTP_TYPE:{
223224
if(!dns_len) {
224-
pc_stringfromipv4(&ip.octet[0], ip_buf);
225+
if(!inet_ntop(v6?AF_INET6:AF_INET,ip.addr.v6,ip_buf,sizeof ip_buf)) {
226+
proxychains_write_log(LOG_PREFIX "error: ip address conversion failed\n");
227+
goto err;
228+
}
225229
dns_name = ip_buf;
226230
}
227231
#define HTTP_AUTH_MAX ((0xFF * 2) + 1 + 1) /* 2 * 0xff: username and pass, plus 1 for ':' and 1 for zero terminator. */
@@ -264,16 +268,20 @@ static int tunnel_to(int sock, ip_type ip, unsigned short port, proxy_type pt, c
264268
}
265269
break;
266270
case SOCKS4_TYPE:{
271+
if(v6) {
272+
proxychains_write_log(LOG_PREFIX "error: SOCKS4 doesnt support ipv6 addresses\n");
273+
goto err;
274+
}
267275
buff[0] = 4; // socks version
268276
buff[1] = 1; // connect command
269277
memcpy(&buff[2], &port, 2); // dest port
270278
if(dns_len) {
271-
ip.octet[0] = 0;
272-
ip.octet[1] = 0;
273-
ip.octet[2] = 0;
274-
ip.octet[3] = 1;
279+
ip.addr.v4.octet[0] = 0;
280+
ip.addr.v4.octet[1] = 0;
281+
ip.addr.v4.octet[2] = 0;
282+
ip.addr.v4.octet[3] = 1;
275283
}
276-
memcpy(&buff[4], &ip, 4); // dest host
284+
memcpy(&buff[4], &ip.addr.v4, 4); // dest host
277285
len = ulen + 1; // username
278286
if(len > 1)
279287
memcpy(&buff[8], user, len);
@@ -353,9 +361,9 @@ static int tunnel_to(int sock, ip_type ip, unsigned short port, proxy_type pt, c
353361
buff[buff_iter++] = 0; // reserved
354362

355363
if(!dns_len) {
356-
buff[buff_iter++] = 1; // ip v4
357-
memcpy(buff + buff_iter, &ip, 4); // dest host
358-
buff_iter += 4;
364+
buff[buff_iter++] = v6 ? 4 : 1; // ip v4/v6
365+
memcpy(buff + buff_iter, ip.addr.v6, v6?16:4); // dest host
366+
buff_iter += v6?16:4;
359367
} else {
360368
buff[buff_iter++] = 3; //dns
361369
buff[buff_iter++] = dns_len & 0xFF;
@@ -411,21 +419,30 @@ static int tunnel_to(int sock, ip_type ip, unsigned short port, proxy_type pt, c
411419
#define RRT "Round Robin chain"
412420

413421
static int start_chain(int *fd, proxy_data * pd, char *begin_mark) {
414-
*fd = socket(PF_INET, SOCK_STREAM, 0);
422+
int v6 = pd->ip.is_v6;
423+
424+
*fd = socket(v6?PF_INET6:PF_INET, SOCK_STREAM, 0);
415425
if(*fd == -1)
416426
goto error;
417427

418-
char ip_buf[16];
419-
pc_stringfromipv4(&pd->ip.octet[0], ip_buf);
428+
char ip_buf[INET6_ADDRSTRLEN];
429+
if(!inet_ntop(v6?AF_INET6:AF_INET,pd->ip.addr.v6,ip_buf,sizeof ip_buf))
430+
goto error;
431+
420432
proxychains_write_log(LOG_PREFIX "%s " TP " %s:%d ",
421433
begin_mark, ip_buf, htons(pd->port));
422434
pd->ps = PLAY_STATE;
423435
struct sockaddr_in addr = {
424436
.sin_family = AF_INET,
425437
.sin_port = pd->port,
426-
.sin_addr.s_addr = (in_addr_t) pd->ip.as_int
438+
.sin_addr.s_addr = (in_addr_t) pd->ip.addr.v4.as_int
439+
};
440+
struct sockaddr_in6 addr6 = {
441+
.sin6_family = AF_INET6,
442+
.sin6_port = pd->port,
427443
};
428-
if(timed_connect(*fd, (struct sockaddr *) &addr, sizeof(addr))) {
444+
if(v6) memcpy(&addr6.sin6_addr.s6_addr, pd->ip.addr.v6, 16);
445+
if(timed_connect(*fd, (struct sockaddr *) (v6?(void*)&addr6:(void*)&addr), v6?sizeof(addr6):sizeof(addr))) {
429446
pd->ps = DOWN_STATE;
430447
goto error1;
431448
}
@@ -496,16 +513,22 @@ static int chain_step(int ns, proxy_data * pfrom, proxy_data * pto) {
496513
int retcode = -1;
497514
char *hostname;
498515
char hostname_buf[MSG_LEN_MAX];
499-
char ip_buf[16];
516+
char ip_buf[INET6_ADDRSTRLEN];
517+
int v6 = pto->ip.is_v6;
500518

501519
PFUNC();
502520

503-
if(pto->ip.octet[0] == remote_dns_subnet) {
504-
if(!at_get_host_for_ip(pto->ip, hostname_buf)) goto usenumericip;
521+
if(!v6 && pto->ip.addr.v4.octet[0] == remote_dns_subnet) {
522+
if(!at_get_host_for_ip(pto->ip.addr.v4, hostname_buf)) goto usenumericip;
505523
else hostname = hostname_buf;
506524
} else {
507525
usenumericip:
508-
pc_stringfromipv4(&pto->ip.octet[0], ip_buf);
526+
if(!inet_ntop(v6?AF_INET6:AF_INET,pto->ip.addr.v6,ip_buf,sizeof ip_buf)) {
527+
pto->ps = DOWN_STATE;
528+
proxychains_write_log("<--ip conversion error!\n");
529+
close(ns);
530+
return SOCKET_ERROR;
531+
}
509532
hostname = ip_buf;
510533
}
511534

@@ -707,7 +730,7 @@ static void gethostbyname_data_setstring(struct gethostbyname_data* data, char*
707730
data->hostent_space.h_name = data->addr_name;
708731
}
709732

710-
extern ip_type hostsreader_get_numeric_ip_for_name(const char* name);
733+
extern ip_type4 hostsreader_get_numeric_ip_for_name(const char* name);
711734
struct hostent *proxy_gethostbyname(const char *name, struct gethostbyname_data* data) {
712735
PFUNC();
713736
char buff[256];
@@ -728,19 +751,19 @@ struct hostent *proxy_gethostbyname(const char *name, struct gethostbyname_data*
728751
if(!strcmp(buff, name)) {
729752
data->resolved_addr = inet_addr(buff);
730753
if(data->resolved_addr == (in_addr_t) (-1))
731-
data->resolved_addr = (in_addr_t) (ip_type_localhost.as_int);
754+
data->resolved_addr = (in_addr_t) (ip_type_localhost.addr.v4.as_int);
732755
goto retname;
733756
}
734757

735758
// this iterates over the "known hosts" db, usually /etc/hosts
736-
ip_type hdb_res = hostsreader_get_numeric_ip_for_name(name);
737-
if(hdb_res.as_int != ip_type_invalid.as_int) {
759+
ip_type4 hdb_res = hostsreader_get_numeric_ip_for_name(name);
760+
if(hdb_res.as_int != ip_type_invalid.addr.v4.as_int) {
738761
data->resolved_addr = hdb_res.as_int;
739762
goto retname;
740763
}
741764

742765
data->resolved_addr = at_get_ip_for_host((char*) name, strlen(name)).as_int;
743-
if(data->resolved_addr == (in_addr_t) ip_type_invalid.as_int) return NULL;
766+
if(data->resolved_addr == (in_addr_t) ip_type_invalid.addr.v4.as_int) return NULL;
744767

745768
retname:
746769

src/hostsreader.c

+3-3
Original file line numberDiff line numberDiff line change
@@ -73,16 +73,16 @@ char* hostsreader_get_ip_for_name(const char* name, char* buf, size_t bufsize) {
7373
#include <netinet/in.h>
7474
#include <sys/socket.h>
7575
#include <arpa/inet.h>
76-
ip_type hostsreader_get_numeric_ip_for_name(const char* name) {
76+
ip_type4 hostsreader_get_numeric_ip_for_name(const char* name) {
7777
char *hres;
7878
char buf[320];
7979
if((hres = hostsreader_get_ip_for_name(name, buf, sizeof buf))) {
8080
struct in_addr c;
8181
inet_aton(hres, &c);
82-
ip_type res;
82+
ip_type4 res;
8383
memcpy(res.octet, &c.s_addr, 4);
8484
return res;
85-
} else return ip_type_invalid;
85+
} else return ip_type_invalid.addr.v4;
8686
}
8787

8888
#ifdef HOSTSREADER_TEST

src/ip_type.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#include "ip_type.h"
22

3-
const ip_type ip_type_invalid = { .as_int = -1 };
4-
const ip_type ip_type_localhost = { {127, 0, 0, 1} };
3+
const ip_type ip_type_invalid = { .addr.v4.as_int = -1 };
4+
const ip_type ip_type_localhost = { .addr.v4 = {127, 0, 0, 1} };
55

src/ip_type.h

+8
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@
66
typedef union {
77
unsigned char octet[4];
88
uint32_t as_int;
9+
} ip_type4;
10+
11+
typedef struct {
12+
union {
13+
ip_type4 v4;
14+
unsigned char v6[16];
15+
} addr;
16+
char is_v6;
917
} ip_type;
1018

1119
extern const ip_type ip_type_invalid;

0 commit comments

Comments
 (0)