summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorRob Bradford <rob@linux.intel.com>2008-10-24 14:46:07 +0100
committerRob Bradford <rob@linux.intel.com>2008-10-24 14:46:07 +0100
commit08197d62efb5e7cbf92d3fbf94a6d192a311214c (patch)
tree4364d997e6a11abfbf43f9b3fba1317db48f799d /scripts
parentfbfc669583328a6df2415ecc6343bba509e44459 (diff)
parente84e951822687dd7a2e2c632ac9caa799ddfd593 (diff)
downloadopenembedded-core-08197d62efb5e7cbf92d3fbf94a6d192a311214c.tar.gz
openembedded-core-08197d62efb5e7cbf92d3fbf94a6d192a311214c.tar.bz2
openembedded-core-08197d62efb5e7cbf92d3fbf94a6d192a311214c.zip
Merge branch 'master' of ssh://git@git.moblin.org/poky
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/poky-git-proxy-socks-command2
-rw-r--r--scripts/poky-git-proxy-socks.c2982
2 files changed, 2984 insertions, 0 deletions
diff --git a/scripts/poky-git-proxy-socks-command b/scripts/poky-git-proxy-socks-command
new file mode 100755
index 0000000000..a5af2d33fa
--- /dev/null
+++ b/scripts/poky-git-proxy-socks-command
@@ -0,0 +1,2 @@
+#! /bin/bash
+poky-git-proxy-socks -S $GIT_PROXY_HOST:$GIT_PROXY_PORT $@
diff --git a/scripts/poky-git-proxy-socks.c b/scripts/poky-git-proxy-socks.c
new file mode 100644
index 0000000000..f5747117ab
--- /dev/null
+++ b/scripts/poky-git-proxy-socks.c
@@ -0,0 +1,2982 @@
+/***********************************************************************
+ * connect.c -- Make socket connection using SOCKS4/5 and HTTP tunnel.
+ *
+ * Copyright (c) 2000-2006 Shun-ichi Goto
+ * Copyright (c) 2002, J. Grant (English Corrections)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * ---------------------------------------------------------
+ * PROJECT: My Test Program
+ * AUTHOR: Shun-ichi GOTO <gotoh@taiyo.co.jp>
+ * CREATE: Wed Jun 21, 2000
+ * REVISION: $Revision: 100 $
+ * ---------------------------------------------------------
+ *
+ * Getting Source
+ * ==============
+ *
+ * Recent version of 'connect.c' is available from
+ * http://www.taiyo.co.jp/~gotoh/ssh/connect.c
+ *
+ * Related tool, ssh-askpass.exe (alternative ssh-askpass on UNIX)
+ * is available:
+ * http://www.taiyo.co.jp/~gotoh/ssh/ssh-askpass.exe.gz
+ *
+ * See more detail:
+ * http://www.taiyo.co.jp/~gotoh/ssh/connect.html
+ *
+ * How To Compile
+ * ==============
+ *
+ * On UNIX environment:
+ * $ gcc connect.c -o connect
+ *
+ * On SOLARIS:
+ * $ gcc -o connect -lresolv -lsocket -lnsl connect.c
+ *
+ * on Win32 environment:
+ * $ cl connect.c wsock32.lib advapi32.lib
+ * or
+ * $ bcc32 connect.c wsock32.lib advapi32.lib
+ * or
+ * $ gcc connect.c -o connect
+ *
+ * on Mac OS X environment:
+ * $ gcc connect.c -o connect -lresolv
+ * or
+ * $ gcc connect.c -o connect -DBIND_8_COMPAT=1
+ *
+ * How To Use
+ * ==========
+ *
+ * You can specify proxy method in an environment variable or in a
+ * command line option.
+ *
+ * usage: connect [-dnhst45] [-R resolve] [-p local-port] [-w sec]
+ * [-H [user@]proxy-server[:port]]
+ * [-S [user@]socks-server[:port]]
+ * [-T proxy-server[:port]]
+ * [-c telnet proxy command]
+ * host port
+ *
+ * "host" and "port" is for the target hostname and port-number to
+ * connect to.
+ *
+ * The -H option specifys a hostname and port number of the http proxy
+ * server to relay. If port is omitted, 80 is used. You can specify this
+ * value in the environment variable HTTP_PROXY and pass the -h option
+ * to use it.
+ *
+ * The -S option specifys the hostname and port number of the SOCKS
+ * server to relay. Like -H, port number can be omitted and the default
+ * is 1080. You can also specify this value pair in the environment
+ * variable SOCKS5_SERVER and give the -s option to use it.
+ *
+ * The '-4' and the '-5' options are for specifying SOCKS relaying and
+ * indicates protocol version to use. It is valid only when used with
+ * '-s' or '-S'. Default is '-5' (protocol version 5)
+ *
+ * The '-R' option is for specifying method to resolve the
+ * hostname. Three keywords ("local", "remote", "both") or dot-notation
+ * IP address are acceptable. The keyword "both" means, "Try local
+ * first, then remote". If a dot-notation IP address is specified, use
+ * this host as nameserver. The default is "remote" for SOCKS5 or
+ * "local" for others. On SOCKS4 protocol, remote resolving method
+ * ("remote" and "both") requires protocol 4a supported server.
+ *
+ * The '-p' option will forward a local TCP port instead of using the
+ * standard input and output.
+ *
+ * The '-P' option is same to '-p' except keep remote session. The
+ * program repeats waiting the port with holding remote session without
+ * disconnecting. To disconnect the remote session, send EOF to stdin or
+ * kill the program.
+ *
+ * The '-w' option specifys timeout seconds for making connection with
+ * TARGET host.
+ *
+ * The '-d' option is used for debug. If you fail to connect, use this
+ * and check request to and response from server.
+ *
+ * You can omit the "port" argument when program name is special format
+ * containing port number itself. For example,
+ * $ ln -s connect connect-25
+ * means this connect-25 command is spcifying port number 25 already
+ * so you need not 2nd argument (and ignored if specified).
+ *
+ * To use proxy, this example is for SOCKS5 connection to connect to
+ * 'host' at port 25 via SOCKS5 server on 'firewall' host.
+ * $ connect -S firewall host 25
+ * or
+ * $ SOCKS5_SERVER=firewall; export SOCKS5_SERVER
+ * $ connect -s host 25
+ *
+ * For a HTTP-PROXY connection:
+ * $ connect -H proxy-server:8080 host 25
+ * or
+ * $ HTTP_PROXY=proxy-server:8080; export HTTP_PROXY
+ * $ connect -h host 25
+ * To forward a local port, for example to use ssh:
+ * $ connect -p 5550 -H proxy-server:8080 host 22
+ * ($ ssh -l user -p 5550 localhost )
+ *
+ * TIPS
+ * ====
+ *
+ * Connect.c doesn't have any configuration to specify the SOCKS server.
+ * If you are a mobile user, this limitation might bother you. However,
+ * You can compile connect.c and link with other standard SOCKS library
+ * like the NEC SOCKS5 library or Dante. This means connect.c is
+ * socksified and uses a configration file like to other SOCKSified
+ * network commands and you can switch configuration file any time
+ * (ex. when ppp startup) that brings you switching of SOCKS server for
+ * connect.c in same way with other commands. For this case, you can
+ * write ~/.ssh/config like this:
+ *
+ * ProxyCommand connect -n %h %p
+ *
+ * SOCKS5 authentication
+ * =====================
+ *
+ * Only USER/PASS authentication is supported.
+ *
+ * Proxy authentication
+ * ====================
+ *
+ * Only BASIC scheme is supported.
+ *
+ * Authentication informations
+ * ===========================
+ *
+ * User name for authentication is specifed by an environment variable
+ * or system login name. And password is specified from environment
+ * variable or external program (specified in $SSH_ASKPASS) or tty.
+ *
+ * Following environment variable is used for specifying user name.
+ * SOCKS: $SOCKS5_USER, $LOGNAME, $USER
+ * HTTP Proxy: $HTTP_PROXY_USER, $LOGNAME, $USER
+ *
+ * ssh-askpass support
+ * ===================
+ *
+ * You can use ssh-askpass (came from OpenSSH or else) to specify
+ * password on graphical environment (X-Window or MS Windows). To use
+ * this, set program name to environment variable SSH_ASKPASS. On UNIX,
+ * X-Window must be required, so $DISPLAY environment variable is also
+ * needed. On Win32 environment, $DISPLAY is not mentioned.
+ *
+ * Related Informations
+ * ====================
+ *
+ * SOCKS5 -- RFC 1928, RFC 1929, RFC 1961
+ * NEC SOCKS Reference Implementation is available from:
+ * http://www.socks.nec.com
+ * DeleGate version 5 or earlier can be SOCKS4 server,
+ * and version 6 can be SOCKS5 and SOCKS4 server.
+ * and version 7.7.0 or later can be SOCKS5 and SOCKS4a server.
+ * http://www.delegate.org/delegate/
+ *
+ * HTTP-Proxy --
+ * Many http proxy servers supports this, but https should
+ * be allowed as configuration on your host.
+ * For example on DeleGate, you should add "https" to the
+ * "REMITTABLE" parameter to allow HTTP-Proxy like this:
+ * delegated -Pxxxx ...... REMITTABLE="+,https" ...
+ *
+ * Hypertext Transfer Protocol -- HTTP/1.1 -- RFC 2616
+ * HTTP Authentication: Basic and Digest Access Authentication -- RFC 2617
+ * For proxy authentication, refer these documents.
+ *
+ ***********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <memory.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <signal.h>
+
+#ifdef __CYGWIN32__
+#undef _WIN32
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#include <winsock.h>
+#include <sys/stat.h>
+#include <io.h>
+#include <conio.h>
+#else /* !_WIN32 */
+#include <unistd.h>
+#include <pwd.h>
+#include <termios.h>
+#include <sys/time.h>
+#ifndef __hpux
+#include <sys/select.h>
+#endif /* __hpux */
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#if !defined(_WIN32) && !defined(__CYGWIN32__)
+#define WITH_RESOLVER 1
+#include <arpa/nameser.h>
+#include <resolv.h>
+#else /* not ( not _WIN32 && not __CYGWIN32__) */
+#undef WITH_RESOLVER
+#endif /* not ( not _WIN32 && not __CYGWIN32__) */
+#endif /* !_WIN32 */
+
+#ifdef _WIN32
+#define ECONNRESET WSAECONNRESET
+#endif /* _WI32 */
+
+
+
+#ifndef LINT
+static char *vcid = "$Id: connect.c 100 2007-07-03 10:48:26Z gotoh $";
+#endif
+
+/* Microsoft Visual C/C++ has _snprintf() and _vsnprintf() */
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+#endif
+
+/* consider Borland C */
+#ifdef __BORLANDC__
+#define _kbhit kbhit
+#define _setmode setmode
+#endif
+
+/* help message.
+ Win32 environment does not support -R option (vc and cygwin)
+ Win32 native compilers does not support -w option, yet (vc)
+*/
+static char *usage = "usage: %s [-dnhst45] [-p local-port]"
+#ifdef _WIN32
+#ifdef __CYGWIN32__
+"[-w timeout] \n" /* cygwin cannot -R */
+#else /* not __CYGWIN32__ */
+" \n" /* VC cannot -w nor -R */
+#endif /* not __CYGWIN32__ */
+#else /* not _WIN32 */
+/* help message for UNIX */
+"[-R resolve] [-w timeout] \n"
+#endif /* not _WIN32 */
+" [-H proxy-server[:port]] [-S [user@]socks-server[:port]] \n"
+" [-T proxy-server[:port]]\n"
+" [-c telnet-proxy-command]\n"
+" host port\n";
+
+/* name of this program */
+char *progname = NULL;
+char *progdesc = "connect --- simple relaying command via proxy.";
+char *rcs_revstr = "$Revision: 100 $";
+char *revstr = NULL;
+int major_version = 1;
+int minor_version = 0;
+
+/* set of character for strspn() */
+const char *digits = "0123456789";
+const char *dotdigits = "0123456789.";
+
+/* options */
+int f_debug = 0;
+
+/* report flag to hide secure information */
+int f_report = 1;
+
+int connect_timeout = 0;
+
+/* local input type */
+#define LOCAL_STDIO 0
+#define LOCAL_SOCKET 1
+char *local_type_names[] = { "stdio", "socket" };
+int local_type = LOCAL_STDIO;
+u_short local_port = 0; /* option 'p' */
+int f_hold_session = 0; /* option 'P' */
+
+char *telnet_command = "telnet %h %p";
+
+/* utiity types, pair holder of number and string */
+typedef struct {
+ int num;
+ const char *str;
+} LOOKUP_ITEM;
+
+/* relay method, server and port */
+#define METHOD_UNDECIDED 0
+#define METHOD_DIRECT 1
+#define METHOD_SOCKS 2
+#define METHOD_HTTP 3
+#define METHOD_TELNET 4
+char *method_names[] = { "UNDECIDED", "DIRECT", "SOCKS", "HTTP", "TELNET" };
+
+int relay_method = METHOD_UNDECIDED; /* relaying method */
+char *relay_host = NULL; /* hostname of relay server */
+u_short relay_port = 0; /* port of relay server */
+char *relay_user = NULL; /* user name for auth */
+
+/* destination target host and port */
+char *dest_host = NULL;
+struct sockaddr_in dest_addr;
+u_short dest_port = 0;
+
+/* informations for SOCKS */
+#define SOCKS5_REP_SUCCEEDED 0x00 /* succeeded */
+#define SOCKS5_REP_FAIL 0x01 /* general SOCKS serer failure */
+#define SOCKS5_REP_NALLOWED 0x02 /* connection not allowed by ruleset */
+#define SOCKS5_REP_NUNREACH 0x03 /* Network unreachable */
+#define SOCKS5_REP_HUNREACH 0x04 /* Host unreachable */
+#define SOCKS5_REP_REFUSED 0x05 /* connection refused */
+#define SOCKS5_REP_EXPIRED 0x06 /* TTL expired */
+#define SOCKS5_REP_CNOTSUP 0x07 /* Command not supported */
+#define SOCKS5_REP_ANOTSUP 0x08 /* Address not supported */
+#define SOCKS5_REP_INVADDR 0x09 /* Inalid address */
+
+LOOKUP_ITEM socks5_rep_names[] = {
+ { SOCKS5_REP_SUCCEEDED, "succeeded"},
+ { SOCKS5_REP_FAIL, "general SOCKS server failure"},
+ { SOCKS5_REP_NALLOWED, "connection not allowed by ruleset"},
+ { SOCKS5_REP_NUNREACH, "Network unreachable"},
+ { SOCKS5_REP_HUNREACH, "Host unreachable"},
+ { SOCKS5_REP_REFUSED, "connection refused"},
+ { SOCKS5_REP_EXPIRED, "TTL expired"},
+ { SOCKS5_REP_CNOTSUP, "Command not supported"},
+ { SOCKS5_REP_ANOTSUP, "Address not supported"},
+ { SOCKS5_REP_INVADDR, "Invalid address"},
+ { -1, NULL }
+};
+
+/* SOCKS5 authentication methods */
+#define SOCKS5_AUTH_REJECT 0xFF /* No acceptable auth method */
+#define SOCKS5_AUTH_NOAUTH 0x00 /* without authentication */
+#define SOCKS5_AUTH_GSSAPI 0x01 /* GSSAPI */
+#define SOCKS5_AUTH_USERPASS 0x02 /* User/Password */
+#define SOCKS5_AUTH_CHAP 0x03 /* Challenge-Handshake Auth Proto. */
+#define SOCKS5_AUTH_EAP 0x05 /* Extensible Authentication Proto. */
+#define SOCKS5_AUTH_MAF 0x08 /* Multi-Authentication Framework */
+
+#define SOCKS4_REP_SUCCEEDED 90 /* rquest granted (succeeded) */
+#define SOCKS4_REP_REJECTED 91 /* request rejected or failed */
+#define SOCKS4_REP_IDENT_FAIL 92 /* cannot connect identd */
+#define SOCKS4_REP_USERID 93 /* user id not matched */
+
+LOOKUP_ITEM socks4_rep_names[] = {
+ { SOCKS4_REP_SUCCEEDED, "request granted (succeeded)"},
+ { SOCKS4_REP_REJECTED, "request rejected or failed"},
+ { SOCKS4_REP_IDENT_FAIL, "cannot connect identd"},
+ { SOCKS4_REP_USERID, "user id not matched"},
+ { -1, NULL }
+};
+
+#define RESOLVE_UNKNOWN 0
+#define RESOLVE_LOCAL 1
+#define RESOLVE_REMOTE 2
+#define RESOLVE_BOTH 3
+char *resolve_names[] = { "UNKNOWN", "LOCAL", "REMOTE", "BOTH" };
+
+int socks_version = 5; /* SOCKS protocol version */
+int socks_resolve = RESOLVE_UNKNOWN;
+struct sockaddr_in socks_ns;
+char *socks5_auth = NULL;
+
+/* Environment variable names */
+#define ENV_SOCKS_SERVER "SOCKS_SERVER" /* SOCKS server */
+#define ENV_SOCKS5_SERVER "SOCKS5_SERVER"
+#define ENV_SOCKS4_SERVER "SOCKS4_SERVER"
+
+#define ENV_SOCKS_RESOLVE "SOCKS_RESOLVE" /* resolve method */
+#define ENV_SOCKS5_RESOLVE "SOCKS5_RESOLVE"
+#define ENV_SOCKS4_RESOLVE "SOCKS4_RESOLVE"
+
+#define ENV_SOCKS5_USER "SOCKS5_USER" /* auth user for SOCKS5 */
+#define ENV_SOCKS4_USER "SOCKS4_USER" /* auth user for SOCKS4 */
+#define ENV_SOCKS_USER "SOCKS_USER" /* auth user for SOCKS */
+#define ENV_SOCKS5_PASSWD "SOCKS5_PASSWD" /* auth password for SOCKS5 */
+#define ENV_SOCKS5_PASSWORD "SOCKS5_PASSWORD" /* old style */
+
+#define ENV_HTTP_PROXY "HTTP_PROXY" /* common env var */
+#define ENV_HTTP_PROXY_USER "HTTP_PROXY_USER" /* auth user */
+#define ENV_HTTP_PROXY_PASSWORD "HTTP_PROXY_PASSWORD" /* auth password */
+
+#define ENV_TELNET_PROXY "TELNET_PROXY" /* common env var */
+
+#define ENV_CONNECT_USER "CONNECT_USER" /* default auth user name */
+#define ENV_CONNECT_PASSWORD "CONNECT_PASSWORD" /* default auth password */
+
+#define ENV_SOCKS_DIRECT "SOCKS_DIRECT" /* addr-list for non-proxy */
+#define ENV_SOCKS5_DIRECT "SOCKS5_DIRECT"
+#define ENV_SOCKS4_DIRECT "SOCKS4_DIRECT"
+#define ENV_HTTP_DIRECT "HTTP_DIRECT"
+#define ENV_CONNECT_DIRECT "CONNECT_DIRECT"
+
+#define ENV_SOCKS5_AUTH "SOCKS5_AUTH"
+#define ENV_SSH_ASKPASS "SSH_ASKPASS" /* askpass program */
+
+/* Prefix string of HTTP_PROXY */
+#define HTTP_PROXY_PREFIX "http://"
+#define PROXY_AUTH_NONE 0
+#define PROXY_AUTH_BASIC 1
+#define PROXY_AUTH_DIGEST 2
+int proxy_auth_type = PROXY_AUTH_NONE;
+
+/* reason of end repeating */
+#define REASON_UNK -2
+#define REASON_ERROR -1
+#define REASON_CLOSED_BY_LOCAL 0
+#define REASON_CLOSED_BY_REMOTE 1
+
+/* return value of relay start function. */
+#define START_ERROR -1
+#define START_OK 0
+#define START_RETRY 1
+
+/* socket related definitions */
+#ifndef _WIN32
+#define SOCKET int
+#endif
+#ifndef SOCKET_ERROR
+#define SOCKET_ERROR -1
+#endif
+
+#ifdef _WIN32
+#define socket_errno() WSAGetLastError()
+#else /* !_WIN32 */
+#define closesocket close
+#define socket_errno() (errno)
+#endif /* !_WIN32 */
+
+#ifdef _WIN32
+#define popen _popen
+#endif /* WIN32 */
+
+/* packet operation macro */
+#define PUT_BYTE(ptr,data) (*(unsigned char*)ptr = data)
+
+/* debug message output */
+void
+debug( const char *fmt, ... )
+{
+ va_list args;
+ if ( f_debug ) {
+ va_start( args, fmt );
+ fprintf(stderr, "DEBUG: ");
+ vfprintf( stderr, fmt, args );
+ va_end( args );
+ }
+}
+
+void
+debug_( const char *fmt, ... ) /* without prefix */
+{
+ va_list args;
+ if ( f_debug ) {
+ va_start( args, fmt );
+ vfprintf( stderr, fmt, args );
+ va_end( args );
+ }
+}
+
+/* error message output */
+void
+error( const char *fmt, ... )
+{
+ va_list args;
+ va_start( args, fmt );
+ fprintf(stderr, "ERROR: ");
+ vfprintf( stderr, fmt, args );
+ va_end( args );
+}
+
+void
+fatal( const char *fmt, ... )
+{
+ va_list args;
+ va_start( args, fmt );
+ fprintf(stderr, "FATAL: ");
+ vfprintf( stderr, fmt, args );
+ va_end( args );
+ exit (EXIT_FAILURE);
+}
+
+
+void *
+xmalloc (size_t size)
+{
+ void *ret = malloc(size);
+ if (ret == NULL)
+ fatal("Cannot allocate memory: %d bytes.\n", size);
+ return ret;
+}
+
+char *
+downcase( char *str )
+{
+ char *buf = str;
+ while ( *buf ) {
+ if ( isupper(*buf) )
+ *buf += 'a'-'A';
+ buf++;
+ }
+ return str; /* return converted arg */
+}
+
+char *
+expand_host_and_port (const char *fmt, const char *host, int port)
+{
+ const char *src;
+ char *buf, *dst, *ptr;
+ size_t len = strlen(fmt) + strlen(host) + 20;
+ buf = xmalloc (len);
+ dst = buf;
+ src = fmt;
+
+ while (*src) {
+ if (*src == '%') {
+ switch (src[1]) {
+ case 'h':
+ strcpy (dst, host);
+ src += 2;
+ break;
+ case 'p':
+ snprintf (dst, len, "%d", port);
+ src += 2;
+ break;
+ default:
+ src ++;
+ break;
+ }
+ dst = buf + strlen (buf);
+ } else if (*src == '\\') {
+ switch (src[1]) {
+ case 'r': /* CR */
+ *dst++ = '\r';
+ src += 2;
+ break;
+ case 'n': /* LF */
+ *dst++ = '\n';
+ src += 2;
+ break;
+ case 't': /* TAB */
+ *dst++ = '\t';
+ src += 2;
+ break;
+ default:
+ src ++;
+ break;
+ }
+ } else {
+ /* usual */
+ *dst++ = *src++;
+ }
+ *dst = '\0';
+ }
+ assert (strlen(buf) < len);
+ return buf;
+}
+
+
+int
+lookup_resolve( const char *str )
+{
+ char *buf = strdup( str );
+ int ret;
+
+ downcase( buf );
+ if ( strcmp( buf, "both" ) == 0 )
+ ret = RESOLVE_BOTH;
+ else if ( strcmp( buf, "remote" ) == 0 )
+ ret = RESOLVE_REMOTE;
+ else if ( strcmp( buf, "local" ) == 0 )
+ ret = RESOLVE_LOCAL;
+ else if ( strspn(buf, dotdigits) == strlen(buf) ) {
+#ifndef WITH_RESOLVER
+ fatal("Sorry, you can't specify to resolve the hostname with the -R option on Win32 environment.");
+#endif /* not WITH_RESOLVER */
+ ret = RESOLVE_LOCAL; /* this case is also 'local' */
+ socks_ns.sin_addr.s_addr = inet_addr(buf);
+ socks_ns.sin_family = AF_INET;
+ }
+ else
+ ret = RESOLVE_UNKNOWN;
+ free(buf);
+ return ret;
+}
+
+char *
+getusername(void)
+{
+#ifdef _WIN32
+ static char buf[1024];
+ DWORD size = sizeof(buf);
+ buf[0] = '\0';
+ GetUserName( buf, &size);
+ return buf;
+#else /* not _WIN32 */
+ struct passwd *pw = getpwuid(getuid());
+ if ( pw == NULL )
+ fatal("getpwuid() failed for uid: %d\n", getuid());
+ return pw->pw_name;
+#endif /* not _WIN32 */
+}
+
+/* expect
+ check STR is begin with substr with case-ignored comparison.
+ Return 1 if matched, otherwise 0.
+*/
+int
+expect( char *str, char *substr)
+{
+ int len = strlen(substr);
+ while ( 0 < len-- ) {
+ if ( toupper(*str) != toupper(*substr) )
+ return 0; /* not matched */
+ str++, substr++;
+ }
+ return 1; /* good, matched */
+}
+
+
+/** PARAMETER operation **/
+#define PARAMETER_FILE "/etc/connectrc"
+#define PARAMETER_DOTFILE ".connectrc"
+typedef struct {
+ char* name;
+ char* value;
+} PARAMETER_ITEM;
+PARAMETER_ITEM parameter_table[] = {
+ { ENV_SOCKS_SERVER, NULL },
+ { ENV_SOCKS5_SERVER, NULL },
+ { ENV_SOCKS4_SERVER, NULL },
+ { ENV_SOCKS_RESOLVE, NULL },
+ { ENV_SOCKS5_RESOLVE, NULL },
+ { ENV_SOCKS4_RESOLVE, NULL },
+ { ENV_SOCKS5_USER, NULL },
+ { ENV_SOCKS5_PASSWD, NULL },
+ { ENV_SOCKS5_PASSWORD, NULL },
+ { ENV_HTTP_PROXY, NULL },
+ { ENV_HTTP_PROXY_USER, NULL },
+ { ENV_HTTP_PROXY_PASSWORD, NULL },
+ { ENV_CONNECT_USER, NULL },
+ { ENV_CONNECT_PASSWORD, NULL },
+ { ENV_SSH_ASKPASS, NULL },
+ { ENV_SOCKS5_DIRECT, NULL },
+ { ENV_SOCKS4_DIRECT, NULL },
+ { ENV_SOCKS_DIRECT, NULL },
+ { ENV_HTTP_DIRECT, NULL },
+ { ENV_CONNECT_DIRECT, NULL },
+ { ENV_SOCKS5_AUTH, NULL },
+ { NULL, NULL }
+};
+
+PARAMETER_ITEM*
+find_parameter_item(const char* name)
+{
+ int i;
+ for( i = 0; parameter_table[i].name != NULL; i++ ){
+ if ( strcmp(name, parameter_table[i].name) == 0 )
+ return &parameter_table[i];
+ }
+ return NULL;
+}
+
+void
+read_parameter_file_1(const char* name)
+{
+ FILE* f;
+ int line;
+ char lbuf[1025];
+ f = fopen(name, "r");
+ if( f ){
+ debug("Reading parameter file(%s)\n", name);
+ for ( line = 1; fgets(lbuf, 1024, f); line++ ) {
+ char *p, *q, *param, *value;
+ p = strchr(lbuf, '\n');
+ if ( p == NULL )
+ fatal("%s:%d: buffer overflow\n", name, line);
+ *p = '\0';
+ p = strchr(lbuf, '#');
+ if ( p )
+ *p = '\0';
+ for ( p = lbuf; *p; p++ )
+ if( *p != ' ' && *p != '\t' ) break;
+ if ( *p == '\0' ) continue;
+ param = p;
+ p = strchr(p, '=');
+ if ( p == NULL ) {
+ error("%s:%d: missing equal sign\n", name, line);
+ continue;
+ }
+ for ( q = p - 1; q >= lbuf; q-- )
+ if ( *q != ' ' && *q != '\t' ) break;
+ *++q = '\0';
+ for ( ++p; *p; p++ )
+ if ( *p != ' ' && *p != '\t' ) break;
+ value = p;
+ for ( ; *p; p++ );
+ for ( p--; p >= lbuf; p-- )
+ if ( *p != ' ' && *p != '\t' ) break;
+ *++p = '\0';
+ if ( param && value ) {
+ PARAMETER_ITEM *item;
+ item = find_parameter_item(param);
+ if ( item == NULL ) {
+ error("%s:%d: unknown parameter `%s'\n", name, line, param);
+ continue;
+ }
+ item->value = strdup(value);
+ debug("Parameter `%s' is set to `%s'\n", param, value);
+ }
+ }
+ }
+}
+
+void
+read_parameter_file(void)
+{
+#if !defined(_WIN32) || defined(cygwin)
+ char *name;
+ struct passwd *pw;
+#endif
+
+ read_parameter_file_1(PARAMETER_FILE);
+#if !defined(_WIN32) || defined(cygwin)
+ pw = getpwuid(getuid());
+ if ( pw == NULL )
+ fatal("getpwuid() failed for uid: %d\n", getuid());
+ name = xmalloc(strlen(pw->pw_dir) + strlen(PARAMETER_DOTFILE) + 2);
+ strcpy(name, pw->pw_dir);
+ strcat(name, "/" PARAMETER_DOTFILE);
+ read_parameter_file_1(name);
+ free(name);
+#endif /* _WIN32 */
+}
+
+char*
+getparam(const char* name)
+{
+ char *value = getenv(name);
+ if ( value == NULL ){
+ PARAMETER_ITEM *item = find_parameter_item(name);
+ if ( item != NULL )
+ value = item->value;
+ }
+ return value;
+}
+
+
+/** DIRECT connection **/
+#define MAX_DIRECT_ADDR_LIST 256
+
+struct ADDRPAIR {
+ struct in_addr addr;
+ struct in_addr mask;
+ char *name;
+ int negative;
+};
+
+struct ADDRPAIR direct_addr_list[MAX_DIRECT_ADDR_LIST];
+int n_direct_addr_list = 0;
+
+void
+mask_addr (void *addr, void *mask, int addrlen)
+{
+ char *a, *m;
+ a = addr;
+ m = mask;
+ while ( 0 < addrlen-- )
+ *a++ &= *m++;
+}
+
+int
+add_direct_addr (struct in_addr *addr, struct in_addr *mask, int negative)
+{
+ struct in_addr iaddr;
+ char *s;
+ if ( MAX_DIRECT_ADDR_LIST <= n_direct_addr_list ) {
+ error("direct address table is full!\n");
+ return -1;
+ }
+ iaddr = *addr;
+ mask_addr(&iaddr, mask, sizeof(iaddr));
+ s = strdup(inet_ntoa(iaddr));
+ debug("adding direct addr entry: %s%s/%s\n",
+ negative? "!": "", s, inet_ntoa(*mask));
+ free(s);
+ memcpy( &direct_addr_list[n_direct_addr_list].addr,
+ &iaddr, sizeof(iaddr));
+ memcpy( &direct_addr_list[n_direct_addr_list].mask,
+ mask, sizeof(*mask));
+ direct_addr_list[n_direct_addr_list].name = NULL;
+ direct_addr_list[n_direct_addr_list].negative = negative;
+ n_direct_addr_list++;
+ return 0;
+}
+
+
+/* add domain/host name entry to direct name table */
+int
+add_direct_host( const char *name, int negative)
+{
+ if ( MAX_DIRECT_ADDR_LIST <= n_direct_addr_list ) {
+ error("direct address table is full!\n");
+ return -1;
+ }
+ if (*name == '*')
+ name++;
+ if (*name == '.')
+ name++;
+ debug("adding direct name entry: %s%s\n", negative? "!": "", name);
+ direct_addr_list[n_direct_addr_list].name = downcase(strdup(name));
+ direct_addr_list[n_direct_addr_list].negative = negative;
+ n_direct_addr_list++;
+ return 0;
+}
+
+
+int
+parse_addr_pair (const char *str, struct in_addr *addr, struct in_addr *mask)
+{
+ /* NOTE: */
+ /* Assume already be splitted by separator
+ and formatted as folowing:
+ 1) 12.34.56.789/255.255.255.0
+ 2) 12.34.56.789/24
+ 3) 12.34.56.
+ All above generates same addr/mask pair 12.34.56.0 and 255.255.255.0
+ */
+ const char *ptr;
+ u_char *dsta, *dstm;
+ int i, n;
+
+ assert( str != NULL );
+ addr->s_addr = 0;
+ mask->s_addr = 0;
+ ptr = str;
+ dsta = (u_char*)&addr->s_addr;
+ dstm = (u_char*)&mask->s_addr;
+ for (i=0; i<4; i++ ) {
+ if ( *ptr == '\0' )
+ break; /* case of format #3 */
+ if ( !isdigit(*ptr) )
+ return -1; /* format error: */
+ *dsta++ = atoi( ptr );
+ *dstm++ = 255; /* automatic mask for format #3 */
+ while ( isdigit(*ptr) ) /* skip digits */
+ ptr++;
+ if ( *ptr == '.' )
+ ptr++;
+ else
+ break;
+ }
+ /* At this point, *ptr points '/' or EOS ('\0') */
+ if ( *ptr == '\0' )
+ return 0; /* complete as format #3 */
+ if ( *ptr != '/' )
+ return -1; /* format error */
+ /* Now parse mask for format #1 or #2 */
+ ptr++;
+ mask->s_addr = 0; /* clear automatic mask */
+
+ if ( strchr( ptr, '.') ) {
+ /* case of format #1 */
+ dstm = (u_char*)&mask->s_addr;
+ for (i=0; i<4; i++) {
+ if ( !isdigit(*ptr) )
+ return -1; /* format error: */
+ *dstm++ = atoi(ptr);
+ while ( isdigit(*ptr) ) /* skip digits */
+ ptr++;
+ if ( *ptr == '.' )
+ ptr++;
+ else
+ break; /* from for loop */
+ }
+ /* complete as format #1 */
+ } else {
+ /* case of format #2 */
+ if ( !isdigit(*ptr) )
+ return -1; /* format error: */
+ n = atoi(ptr);
+ if ( n<0 || 32<n)
+ return -1; /* format error */
+ mask->s_addr = (n==0)? 0: htonl(((u_long)0xFFFFFFFF)<<(32-n));
+ /* complete as format #1 */
+ }
+ return 0;
+}
+
+void
+initialize_direct_addr (void)
+{
+ int negative;
+ int n_entries;
+ char *env = NULL, *beg, *next, *envkey = NULL;
+ struct in_addr addr, mask;
+
+ if ( relay_method == METHOD_SOCKS ){
+ if ( socks_version == 5 )
+ envkey = ENV_SOCKS5_DIRECT;
+ else
+ envkey = ENV_SOCKS4_DIRECT;
+ env = getparam(envkey);
+ if ( env == NULL )
+ env = getparam(ENV_SOCKS_DIRECT);
+ } else if ( relay_method == METHOD_HTTP ){
+ env = getparam(ENV_HTTP_DIRECT);
+ }
+
+ if ( env == NULL )
+ env = getparam(ENV_CONNECT_DIRECT);
+
+ if ( env == NULL )
+ return; /* no entry */
+ debug("making direct addr list from: '%s'\n", env);
+ env = strdup( env ); /* reallocate to modify */
+ beg = next = env;
+ n_entries = 0;
+ do {
+ if ( MAX_DIRECT_ADDR_LIST <= n_entries ) {
+ error("too many entries in %s", envkey);
+ break; /* from do loop */
+ }
+ next = strchr( beg, ',');
+ if ( next != NULL )
+ *next++ = '\0';
+ addr.s_addr = 0;
+ mask.s_addr = 0;
+ if (*beg == '!') {
+ negative = 1;
+ beg++;
+ } else
+ negative = 0;
+ if ( !parse_addr_pair( beg, &addr, &mask ) ) {
+ add_direct_addr( &addr, &mask, negative );
+ } else {
+ add_direct_host( beg, negative );
+ }
+ if ( next != NULL )
+ beg = next;
+ } while ( next != NULL );
+
+ free( env );
+ return;
+}
+
+int
+cmp_addr (void *addr1, void *addr2, int addrlen)
+{
+ return memcmp( addr1, addr2, addrlen );
+}
+
+int
+is_direct_address (const struct in_addr addr)
+{
+ int i, neg;
+ struct in_addr iaddr;
+
+ /* Note: assume IPV4 address !! */
+ for (i=0; i<n_direct_addr_list; i++ ) {
+ if (direct_addr_list[i].name != NULL)
+ continue; /* it's name entry */
+ neg = direct_addr_list[i].negative;
+ iaddr = addr;
+ mask_addr( &iaddr, &direct_addr_list[i].mask,
+ sizeof(struct in_addr));
+ if (cmp_addr(&iaddr, &direct_addr_list[i].addr,
+ sizeof(struct in_addr)) == 0) {
+ char *a, *m;
+ a = strdup(inet_ntoa(direct_addr_list[i].addr));
+ m = strdup(inet_ntoa(direct_addr_list[i].mask));
+ debug("match with: %s/%s%s\n", a, m, neg? " (negative)": "");
+ free(a);
+ free(m);
+ return !neg? 1: 0;
+ }
+ }
+ debug("not matched, addr to be relayed: %s\n", inet_ntoa(addr));
+ return 0; /* not direct */
+}
+
+
+/* check s1 is ends with s2.
+ return 1 if exact match or domain part match.
+ return 0 if s1 is shorter than s2 or partial match.
+ For example,
+ ends_with("bar.com", "bar.com") => 1 (exact match)
+ ends_with("foo.bar.com", "bar.com") => 1 (domain match)
+ ends_with("foo.beebar.com", "bar.com") => 0 (partial match)
+ ends_with("bar", "bar.com") => 0 (shorter)
+ */
+domain_match(const char *s1, const char *s2)
+{
+ int len1, len2;
+ const char *tail1, *tail2;
+ len1 = strlen(s1);
+ len2 = strlen(s2);
+ if (len1 < len2 || len1 == 0 || len2 == 0)
+ return 0; /* not match */
+ tail1 = s1 + len1;
+ tail2 = s2 + len2;
+ while (0 < len1 && 0 < len2) {
+ if (*--tail1 != *--tail2)
+ break; /* not match */
+ len1--, len2--;
+ }
+ if (len2 != 0)
+ return 0; /* not match */
+ /* Now exact match, domain match or