Permalink
Browse files

Add support for proxying through an external command.

Proxy type "exec" can be used to have an external script or binary set
up an outgoing connection. Standard input and output will be used to
exchange data with the external command. The variables REMOTEADDRESS and
REMOTEPORT are set to the intended destination address and port.
  • Loading branch information...
1 parent fb55888 commit 5ae19cb0bb8dd6be1e9bcd560bb051f496a373ec @gsliepen committed Apr 19, 2012
Showing with 68 additions and 12 deletions.
  1. +62 −10 src/net_socket.c
  2. +4 −2 src/netutl.c
  3. +2 −0 src/protocol_auth.c
View
@@ -294,13 +294,62 @@ void retry_outgoing(outgoing_t *outgoing) {
void finish_connecting(connection_t *c) {
ifdebug(CONNECTIONS) logger(LOG_INFO, "Connected to %s (%s)", c->name, c->hostname);
- configure_tcp(c);
+ if(proxytype != PROXY_EXEC)
+ configure_tcp(c);
c->last_ping_time = now;
send_id(c);
}
+static void do_outgoing_pipe(connection_t *c, char *command) {
+#ifndef HAVE_MINGW
+ int fd[2];
+
+ if(socketpair(AF_UNIX, SOCK_STREAM, 0, fd)) {
+ logger(LOG_ERR, "Could not create socketpair: %s\n", strerror(errno));
+ return;
+ }
+
+ if(fork()) {
+ c->socket = fd[0];
+ close(fd[1]);
+ logger(LOG_DEBUG, "Using proxy %s", command);
+ return;
+ }
+
+ close(0);
+ close(1);
+ close(fd[0]);
+ dup2(fd[1], 0);
+ dup2(fd[1], 1);
+ close(fd[1]);
+
+ // Other filedescriptors should be closed automatically by CLOEXEC
+
+ char *host = NULL;
+ char *port = NULL;
+
+ sockaddr2str(&c->address, &host, &port);
+ setenv("REMOTEADDRESS", host, true);
+ setenv("REMOTEPORT", port, true);
+ setenv("NODE", c->name, true);
+ setenv("NAME", myself->name, true);
+ if(netname)
+ setenv("NETNAME", netname, true);
+
+ int result = system(command);
+ if(result < 0)
+ logger(LOG_ERR, "Could not execute %s: %s\n", command, strerror(errno));
+ else if(result)
+ logger(LOG_ERR, "%s exited with non-zero status %d", command, result);
+ exit(result);
+#else
+ logger(LOG_ERR, "Proxy type exec not supported on this platform!");
+ return false;
+#endif
+}
+
void do_outgoing_connection(connection_t *c) {
char *address, *port, *space;
struct addrinfo *proxyai;
@@ -361,7 +410,10 @@ void do_outgoing_connection(connection_t *c) {
if(!proxytype) {
c->socket = socket(c->address.sa.sa_family, SOCK_STREAM, IPPROTO_TCP);
- } else {
+ configure_tcp(c);
+ } if(proxytype == PROXY_EXEC) {
+ do_outgoing_pipe(c, proxyhost);
+ } else {
proxyai = str2addrinfo(proxyhost, proxyport, SOCK_STREAM);
if(!proxyai)
goto begin;
@@ -378,22 +430,22 @@ void do_outgoing_connection(connection_t *c) {
fcntl(c->socket, F_SETFD, FD_CLOEXEC);
#endif
+ if(proxytype != PROXY_EXEC) {
#if defined(SOL_IPV6) && defined(IPV6_V6ONLY)
- int option = 1;
- if(c->address.sa.sa_family == AF_INET6)
- setsockopt(c->socket, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
+ int option = 1;
+ if(c->address.sa.sa_family == AF_INET6)
+ setsockopt(c->socket, SOL_IPV6, IPV6_V6ONLY, (void *)&option, sizeof option);
#endif
- bind_to_interface(c->socket);
-
- /* Optimize TCP settings */
-
-// configure_tcp(c);
+ bind_to_interface(c->socket);
+ }
/* Connect */
if(!proxytype) {
result = connect(c->socket, &c->address.sa, SALEN(c->address.sa));
+ } else if(proxytype == PROXY_EXEC) {
+ result = 0;
} else {
result = connect(c->socket, proxyai->ai_addr, proxyai->ai_addrlen);
freeaddrinfo(proxyai);
View
@@ -83,8 +83,10 @@ void sockaddr2str(const sockaddr_t *sa, char **addrstr, char **portstr) {
int err;
if(sa->sa.sa_family == AF_UNKNOWN) {
- *addrstr = xstrdup(sa->unknown.address);
- *portstr = xstrdup(sa->unknown.port);
+ if(addrstr)
+ *addrstr = xstrdup(sa->unknown.address);
+ if(portstr)
+ *portstr = xstrdup(sa->unknown.port);
return;
}
View
@@ -117,6 +117,8 @@ static bool send_proxyrequest(connection_t *c) {
case PROXY_SOCKS4A:
logger(LOG_ERR, "Proxy type not implemented yet");
return false;
+ case PROXY_EXEC:
+ return true;
default:
logger(LOG_ERR, "Unknown proxy type");
return false;

0 comments on commit 5ae19cb

Please sign in to comment.