diff -ruN tsocks-1.8/parser.c tsocks-1.8-remote/parser.c --- tsocks-1.8/parser.c 2002-03-13 06:34:22.000000000 -0600 +++ tsocks-1.8-remote/parser.c 2005-09-13 23:23:20.000000000 -0500 @@ -29,9 +29,12 @@ static int handle_type(struct parsedfile *config, int, char *); static int handle_port(struct parsedfile *config, int, char *); static int handle_local(struct parsedfile *, int, char *); +static int handle_remote(struct parsedfile *, int, char *); +static int handle_net(struct parsedfile *, int, char *, struct netent **); static int handle_defuser(struct parsedfile *, int, char *); static int handle_defpass(struct parsedfile *, int, char *); static int make_netent(char *value, struct netent **ent); +static int is_localremote(struct parsedfile *, struct in_addr *, struct netent *); int read_config (char *filename, struct parsedfile *config) { FILE *conf; @@ -54,6 +57,9 @@ filename = line; } + /* By default we check for local nets first */ + config->useremote = 0; + /* Read the configuration file */ if ((conf = fopen(filename, "r")) == NULL) { show_msg(MSGERR, "Could not open socks configuration file " @@ -74,8 +80,10 @@ } fclose(conf); - /* Always add the 127.0.0.1/255.0.0.0 subnet to local */ - handle_local(config, 0, "127.0.0.0/255.0.0.0"); + /* Always add the 127.0.0.1/255.0.0.0 subnet to local if needed */ + if (!config->useremote) { + handle_local(config, 0, "127.0.0.0/255.0.0.0"); + } /* Check default server */ check_server(&(config->defaultserver)); @@ -152,6 +160,8 @@ handle_defpass(config, lineno, words[2]); } else if (!strcmp(words[0], "local")) { handle_local(config, lineno, words[2]); + } else if (!strcmp(words[0], "remote")) { + handle_remote(config, lineno, words[2]); } else { show_msg(MSGERR, "Invalid pair type (%s) specified " "on line %d in configuration file, " @@ -419,11 +429,20 @@ } static int handle_local(struct parsedfile *config, int lineno, char *value) { + return handle_net(config, lineno, value, &(config->localnets)); +} + +static int handle_remote(struct parsedfile *config, int lineno, char *value) { + config->useremote = 1; + return handle_net(config, lineno, value, &(config->remotenets)); +} + +static int handle_net(struct parsedfile *config, int lineno, char *value, struct netent **whichnets) { int rc; struct netent *ent; if (currentcontext != &(config->defaultserver)) { - show_msg(MSGERR, "Local networks cannot be specified in path " + show_msg(MSGERR, "Networks cannot be specified in path " "block at like %d in configuration file. " "(Path block started at line %d)\n", lineno, currentcontext->lineno); @@ -433,20 +452,20 @@ rc = make_netent(value, &ent); switch(rc) { case 1: - show_msg(MSGERR, "Local network specification (%s) is not validly " + show_msg(MSGERR, "Network specification (%s) is not validly " "constructed on line %d in configuration " "file\n", value, lineno); return(0); break; case 2: - show_msg(MSGERR, "IP for local " + show_msg(MSGERR, "IP for " "network specification (%s) is not valid on line " "%d in configuration file\n", value, lineno); return(0); break; case 3: show_msg(MSGERR, "SUBNET for " - "local network specification (%s) is not valid on " + "network specification (%s) is not valid on " "line %d in configuration file\n", value, lineno); return(0); @@ -461,7 +480,7 @@ case 6: case 7: show_msg(MSGERR, "Port specification is invalid and " - "not allowed in local network specification " + "not allowed in network specification " "(%s) on line %d in configuration file\n", value, lineno); return(0); @@ -470,15 +489,15 @@ if (ent->startport || ent->endport) { show_msg(MSGERR, "Port specification is " - "not allowed in local network specification " + "not allowed in network specification " "(%s) on line %d in configuration file\n", value, lineno); return(0); } /* The entry is valid so add it to linked list */ - ent -> next = config->localnets; - (config->localnets) = ent; + ent -> next = *whichnets; + *whichnets = ent; return(0); } @@ -578,9 +597,17 @@ } int is_local(struct parsedfile *config, struct in_addr *testip) { + return is_localremote(config, testip, config->localnets); +} + +int is_remote(struct parsedfile *config, struct in_addr *testip) { + return is_localremote(config, testip, config->remotenets); +} + +static int is_localremote(struct parsedfile *config, struct in_addr *testip, struct netent *whichnets) { struct netent *ent; - for (ent = (config->localnets); ent != NULL; ent = ent -> next) { + for (ent = (whichnets); ent != NULL; ent = ent -> next) { if ((testip->s_addr & ent->localnet.s_addr) == (ent->localip.s_addr & ent->localnet.s_addr)) { return(0); diff -ruN tsocks-1.8/parser.h tsocks-1.8-remote/parser.h --- tsocks-1.8/parser.h 2002-02-10 01:26:27.000000000 -0600 +++ tsocks-1.8-remote/parser.h 2005-09-13 23:22:47.000000000 -0500 @@ -31,13 +31,16 @@ /* Structure representing a complete parsed file */ struct parsedfile { struct netent *localnets; + struct netent *remotenets; struct serverent defaultserver; struct serverent *paths; + int useremote; }; /* Functions provided by parser module */ int read_config(char *, struct parsedfile *); int is_local(struct parsedfile *, struct in_addr *); +int is_remote(struct parsedfile *, struct in_addr *); int pick_server(struct parsedfile *, struct serverent **, struct in_addr *, unsigned int port); char *strsplit(char *separator, char **text, const char *search); diff -ruN tsocks-1.8/tsocks.c tsocks-1.8-remote/tsocks.c --- tsocks-1.8/tsocks.c 2002-07-15 17:50:52.000000000 -0500 +++ tsocks-1.8-remote/tsocks.c 2005-09-13 23:24:46.000000000 -0500 @@ -277,14 +277,33 @@ show_msg(MSGDEBUG, "Got connection request for socket %d to " "%s\n", __fd, inet_ntoa(connaddr->sin_addr)); - /* If the address is local call realconnect */ - if (!(is_local(config, &(connaddr->sin_addr)))) { - show_msg(MSGDEBUG, "Connection for socket %d is local\n", __fd); - return(realconnect(__fd, __addr, __len)); - } + /* Do we check paths first or second? */ + if (config->useremote) { + + /* Check paths first */ + pick_server(config, &path, &(connaddr->sin_addr), ntohs(connaddr->sin_port)); + + /* If we didn't find a path, check to see if it's a remote connection */ + if (path == &(config->defaultserver)) + { + if (is_remote(config, &(connaddr->sin_addr))) { + show_msg(MSGDEBUG, "Connection for socket %d defaulted to local\n", __fd); + return(realconnect(__fd, __addr, __len)); + } + } + + } else { - /* Ok, so its not local, we need a path to the net */ - pick_server(config, &path, &(connaddr->sin_addr), ntohs(connaddr->sin_port)); + /* If the address is local call realconnect */ + if (!(is_local(config, &(connaddr->sin_addr)))) { + show_msg(MSGDEBUG, "Connection for socket %d is local\n", __fd); + return(realconnect(__fd, __addr, __len)); + } + + /* Ok, so its not local, we need a path to the net */ + pick_server(config, &path, &(connaddr->sin_addr), ntohs(connaddr->sin_port)); + + } show_msg(MSGDEBUG, "Picked server %s for connection\n", (path->address ? path->address : "(Not Provided)")); @@ -313,11 +332,15 @@ bzero(&(server_address.sin_zero), 8); /* Complain if this server isn't on a localnet */ - if (is_local(config, &server_address.sin_addr)) { - show_msg(MSGERR, "SOCKS server %s (%s) is not on a local subnet!\n", - path->address, inet_ntoa(server_address.sin_addr)); - } else - gotvalidserver = 1; + if (config->useremote) { + gotvalidserver = 1; + } else { + if (is_local(config, &server_address.sin_addr)) { + show_msg(MSGERR, "SOCKS server %s (%s) is not on a local subnet!\n", + path->address, inet_ntoa(server_address.sin_addr)); + } else + gotvalidserver = 1; + } } /* If we haven't found a valid server we return connection refused */ diff -ruN tsocks-1.8/validateconf.c tsocks-1.8-remote/validateconf.c --- tsocks-1.8/validateconf.c 2002-02-07 04:49:59.000000000 -0600 +++ tsocks-1.8-remote/validateconf.c 2005-09-13 23:24:58.000000000 -0500 @@ -108,18 +108,34 @@ return; } else { printf("Finding path for %s...\n", inet_ntoa(hostaddr)); - if (!(is_local(config, &(hostaddr)))) { - printf("Path is local\n"); - } else { - pick_server(config, &path, &hostaddr, portno); - if (path == &(config->defaultserver)) { - printf("Path is via default server:\n"); - show_server(config, path, 1); - } else { - printf("Host is reached via this path:\n"); - show_server(config, path, 0); - } - } + if (config->useremote) { + pick_server(config, &path, &hostaddr, portno); + if (path == &(config->defaultserver)) { + if (is_remote(config, &(hostaddr))) { + printf("Path is local\n"); + } else { + printf("Path is via default server:\n"); + show_server(config, path, 1); + } + } else { + printf("Host is reached via this path:\n"); + show_server(config, path, 0); + } + } else { + if (!(is_local(config, &(hostaddr)))) { + printf("Path is local\n"); + } else { + pick_server(config, &path, &hostaddr, portno); + if (path == &(config->defaultserver)) { + printf("Path is via default server:\n"); + show_server(config, path, 1); + } else { + printf("Host is reached via this path:\n"); + show_server(config, path, 0); + } + } + + } } return; @@ -129,17 +145,31 @@ struct netent *net; struct serverent *server; - /* Show the local networks */ - printf("=== Local networks (no socks server needed) ===\n"); - net = (config->localnets); - while (net != NULL) { - printf("Network: %15s ", - inet_ntoa(net->localip)); - printf("NetMask: %15s\n", - inet_ntoa(net->localnet)); - net = net->next; + if (config->useremote) { + /* Show the remote networks */ + printf("=== Remote networks (using default socks server) ===\n"); + net = (config->remotenets); + while (net != NULL) { + printf("Network: %15s ", + inet_ntoa(net->localip)); + printf("NetMask: %15s\n", + inet_ntoa(net->localnet)); + net = net->next; + } + printf("\n"); + } else { + /* Show the local networks */ + printf("=== Local networks (no socks server needed) ===\n"); + net = (config->localnets); + while (net != NULL) { + printf("Network: %15s ", + inet_ntoa(net->localip)); + printf("NetMask: %15s\n", + inet_ntoa(net->localnet)); + net = net->next; + } + printf("\n"); } - printf("\n"); /* If we have a default server configuration show it */ printf("=== Default Server Configuration ===\n"); @@ -181,7 +211,7 @@ /* Check the server is on a local net */ if ((server->address != NULL) && (res.s_addr != -1) && - (is_local(config, &res))) + (is_local(config, &res)) && !config->useremote) fprintf(stderr, "Error: Server is not on a network " "specified as local\n");