version 1.4, 2002/02/19 22:42:04 |
version 1.5, 2002/02/28 18:05:36 |
|
|
#include <unistd.h> |
#include <unistd.h> |
|
|
#define SOCKS_PORT "1080" |
#define SOCKS_PORT "1080" |
#define SOCKS_VERSION 5 |
#define SOCKS_V5 5 |
|
#define SOCKS_V4 4 |
#define SOCKS_NOAUTH 0 |
#define SOCKS_NOAUTH 0 |
#define SOCKS_NOMETHOD 0xff |
#define SOCKS_NOMETHOD 0xff |
#define SOCKS_CONNECT 1 |
#define SOCKS_CONNECT 1 |
|
|
|
|
int |
int |
socks_connect (char *host, char *port, struct addrinfo hints, |
socks_connect (char *host, char *port, struct addrinfo hints, |
char *proxyhost, char *proxyport, struct addrinfo proxyhints) |
char *proxyhost, char *proxyport, struct addrinfo proxyhints, |
|
int socksv) |
{ |
{ |
int proxyfd; |
int proxyfd; |
unsigned char buf[SOCKS_MAXCMDSZ]; |
unsigned char buf[SOCKS_MAXCMDSZ]; |
|
|
serveraddr = decode_addr (host); |
serveraddr = decode_addr (host); |
serverport = decode_port (port); |
serverport = decode_port (port); |
|
|
/* Version 5, one method: no authentication */ |
if (socksv == 5) { |
buf[0] = SOCKS_VERSION; |
/* Version 5, one method: no authentication */ |
buf[1] = 1; |
buf[0] = SOCKS_V5; |
buf[2] = SOCKS_NOAUTH; |
buf[1] = 1; |
cnt = write (proxyfd, buf, 3); |
buf[2] = SOCKS_NOAUTH; |
if (cnt == -1) |
cnt = write (proxyfd, buf, 3); |
err (1, "write failed"); |
if (cnt == -1) |
if (cnt != 3) |
err (1, "write failed"); |
errx (1, "short write, %d (expected 3)", cnt); |
if (cnt != 3) |
|
errx (1, "short write, %d (expected 3)", cnt); |
|
|
read (proxyfd, buf, 2); |
read (proxyfd, buf, 2); |
if (buf[1] == SOCKS_NOMETHOD) |
if (buf[1] == SOCKS_NOMETHOD) |
errx (1, "authentication method negotiation failed"); |
errx (1, "authentication method negotiation failed"); |
|
|
/* Version 5, connect: IPv4 address */ |
/* Version 5, connect: IPv4 address */ |
buf[0] = SOCKS_VERSION; |
buf[0] = SOCKS_V5; |
buf[1] = SOCKS_CONNECT; |
buf[1] = SOCKS_CONNECT; |
buf[2] = 0; |
buf[2] = 0; |
buf[3] = SOCKS_IPV4; |
buf[3] = SOCKS_IPV4; |
memcpy (buf + 4, &serveraddr, sizeof serveraddr); |
memcpy (buf + 4, &serveraddr, sizeof serveraddr); |
memcpy (buf + 8, &serverport, sizeof serverport); |
memcpy (buf + 8, &serverport, sizeof serverport); |
|
|
/* XXX Handle short writes better */ |
/* XXX Handle short writes better */ |
cnt = write (proxyfd, buf, 10); |
cnt = write (proxyfd, buf, 10); |
if (cnt == -1) |
if (cnt == -1) |
err (1, "write failed"); |
err (1, "write failed"); |
if (cnt != 10) |
if (cnt != 10) |
errx (1, "short write, %d (expected 10)", cnt); |
errx (1, "short write, %d (expected 10)", cnt); |
|
|
/* XXX Handle short reads better */ |
/* XXX Handle short reads better */ |
cnt = read (proxyfd, buf, sizeof buf); |
cnt = read (proxyfd, buf, sizeof buf); |
if (cnt == -1) |
if (cnt == -1) |
err (1, "read failed"); |
err (1, "read failed"); |
if (cnt != 10) |
if (cnt != 10) |
errx (1, "unexpected reply size %d (expected 10)", cnt); |
errx (1, "unexpected reply size %d (expected 10)", cnt); |
if (buf[1] != 0) |
if (buf[1] != 0) |
errx (1, "connection failed, SOCKS error %d", buf[1]); |
errx (1, "connection failed, SOCKS error %d", buf[1]); |
|
} else { |
|
/* Version 4 */ |
|
buf[0] = SOCKS_V4; |
|
buf[1] = SOCKS_CONNECT; /* connect */ |
|
memcpy (buf + 2, &serverport, sizeof serverport); |
|
memcpy (buf + 4, &serveraddr, sizeof serveraddr); |
|
buf[8] = 0; /* empty username */ |
|
|
|
cnt = write (proxyfd, buf, 9); |
|
if (cnt == -1) |
|
err (1, "write failed"); |
|
if (cnt != 9) |
|
errx (1, "short write, %d (expected 9)", cnt); |
|
|
|
/* XXX Handle short reads better */ |
|
cnt = read (proxyfd, buf, 8); |
|
if (cnt == -1) |
|
err (1, "read failed"); |
|
if (cnt != 8) |
|
errx (1, "unexpected reply size %d (expected 8)", cnt); |
|
if (buf[1] != 90) |
|
errx (1, "connection failed, SOCKS error %d", buf[1]); |
|
} |
|
|
return proxyfd; |
return proxyfd; |
} |
} |