From 877b3d84597fcfc3abf5aa332019d412f2717896 Mon Sep 17 00:00:00 2001 From: Richard Purdie Date: Wed, 20 Apr 2011 23:24:51 +0100 Subject: Rename the remaining poky-* scripts to oe-* or runqemu-* Signed-off-by: Richard Purdie --- scripts/oe-find-native-sysroot | 72 + scripts/oe-git-proxy-command | 10 + scripts/oe-git-proxy-socks-command | 2 + scripts/oe-git-proxy-socks.c | 2982 ++++++++++++++++++++++++++++++++++ scripts/oe-setup-rpmrepo | 89 + scripts/oe-trim-schemas | 49 + scripts/poky-addptable2image | 51 - scripts/poky-export-rootfs | 186 --- scripts/poky-extract-sdk | 100 -- scripts/poky-find-native-sysroot | 72 - scripts/poky-gen-tapdevs | 85 - scripts/poky-git-proxy-command | 10 - scripts/poky-git-proxy-socks-command | 2 - scripts/poky-git-proxy-socks.c | 2982 ---------------------------------- scripts/poky-setup-rpmrepo | 89 - scripts/poky-trim-schemas | 49 - scripts/runqemu-addptable2image | 51 + scripts/runqemu-export-rootfs | 186 +++ scripts/runqemu-extract-sdk | 100 ++ scripts/runqemu-gen-tapdevs | 85 + scripts/runqemu-ifup | 2 +- scripts/runqemu-internal | 12 +- 22 files changed, 3633 insertions(+), 3633 deletions(-) create mode 100755 scripts/oe-find-native-sysroot create mode 100755 scripts/oe-git-proxy-command create mode 100755 scripts/oe-git-proxy-socks-command create mode 100644 scripts/oe-git-proxy-socks.c create mode 100755 scripts/oe-setup-rpmrepo create mode 100755 scripts/oe-trim-schemas delete mode 100755 scripts/poky-addptable2image delete mode 100755 scripts/poky-export-rootfs delete mode 100755 scripts/poky-extract-sdk delete mode 100755 scripts/poky-find-native-sysroot delete mode 100755 scripts/poky-gen-tapdevs delete mode 100755 scripts/poky-git-proxy-command delete mode 100755 scripts/poky-git-proxy-socks-command delete mode 100644 scripts/poky-git-proxy-socks.c delete mode 100755 scripts/poky-setup-rpmrepo delete mode 100755 scripts/poky-trim-schemas create mode 100755 scripts/runqemu-addptable2image create mode 100755 scripts/runqemu-export-rootfs create mode 100755 scripts/runqemu-extract-sdk create mode 100755 scripts/runqemu-gen-tapdevs (limited to 'scripts') diff --git a/scripts/oe-find-native-sysroot b/scripts/oe-find-native-sysroot new file mode 100755 index 0000000000..da00a07850 --- /dev/null +++ b/scripts/oe-find-native-sysroot @@ -0,0 +1,72 @@ +#!/bin/bash +# +# Find a native sysroot to use - either from an in-tree Poky build or +# from a toolchain installation. It then ensures the variable +# $OECORE_NATIVE_SYSROOT is set to the sysroot's base directory, and sets +# $PSEUDO to the path of the pseudo binary. +# +# This script is intended to be run within other scripts by source'ing +# it, e.g: +# +# SYSROOT_SETUP_SCRIPT=`which oe-find-native-sysroot` +# . $SYSROOT_SETUP_SCRIPT +# +# This script will terminate execution of your calling program unless +# you set a variable $SKIP_STRICT_SYSROOT_CHECK to a non-empty string +# beforehand. +# +# Copyright (c) 2010 Intel Corp. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +if [ -z "$OECORE_NATIVE_SYSROOT" ]; then + BITBAKE=`which bitbake` + if [ "x$BITBAKE" != "x" ]; then + if [ "$UID" = "0" ]; then + # Root cannot run bitbake unless sanity checking is disabled + if [ ! -d "./conf" ]; then + echo "Error: root cannot run bitbake by default, and I cannot find a ./conf directory to be able to disable sanity checking" + exit 1 + fi + touch conf/sanity.conf + OECORE_NATIVE_SYSROOT=`bitbake -e | grep ^STAGING_DIR_NATIVE | cut -d '=' -f2 | cut -d '"' -f2` + rm -f conf/sanity.conf + else + OECORE_NATIVE_SYSROOT=`bitbake -e | grep ^STAGING_DIR_NATIVE | cut -d '=' -f2 | cut -d '"' -f2` + fi + else + echo "Error: Unable to locate your native sysroot." + echo "Did you forget to source the Poky environment script?" + + if [ -z "$SKIP_STRICT_SYSROOT_CHECK" ]; then + exit 1 + fi + fi +fi + +# Set up pseudo command +if [ ! -e "$OECORE_NATIVE_SYSROOT/usr/bin/pseudo" ]; then + echo "Error: Unable to find pseudo binary in $OECORE_NATIVE_SYSROOT/usr/bin/" + + if [ "x$POKY_DISTRO_VERSION" = "x" ]; then + echo "Have you run 'bitbake meta-ide-support'?" + else + echo "This shouldn't happen - something is wrong with your toolchain installation" + fi + + if [ -z "$SKIP_STRICT_SYSROOT_CHECK" ]; then + exit 1 + fi +fi +PSEUDO="$OECORE_NATIVE_SYSROOT/usr/bin/pseudo" diff --git a/scripts/oe-git-proxy-command b/scripts/oe-git-proxy-command new file mode 100755 index 0000000000..d31f85abd8 --- /dev/null +++ b/scripts/oe-git-proxy-command @@ -0,0 +1,10 @@ +#! /bin/bash + +(echo "CONNECT $1:$2 HTTP/1.0"; + echo; + cat ) | nc $GIT_PROXY_HOST $GIT_PROXY_PORT | + +(read a; + read a; + read a; + cat ) \ No newline at end of file diff --git a/scripts/oe-git-proxy-socks-command b/scripts/oe-git-proxy-socks-command new file mode 100755 index 0000000000..90fa14e1ed --- /dev/null +++ b/scripts/oe-git-proxy-socks-command @@ -0,0 +1,2 @@ +#! /bin/bash +oe-git-proxy-socks -S $GIT_PROXY_HOST:$GIT_PROXY_PORT $@ diff --git a/scripts/oe-git-proxy-socks.c b/scripts/oe-git-proxy-socks.c new file mode 100644 index 0000000000..f5747117ab --- /dev/null +++ b/scripts/oe-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 + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __CYGWIN32__ +#undef _WIN32 +#endif + +#ifdef _WIN32 +#include +#include +#include +#include +#include +#else /* !_WIN32 */ +#include +#include +#include +#include +#ifndef __hpux +#include +#endif /* __hpux */ +#include +#include +#include +#include +#if !defined(_WIN32) && !defined(__CYGWIN32__) +#define WITH_RESOLVER 1 +#include +#include +#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 ¶meter_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 || 32s_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 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 partial match. + Return true if exact or domain match. + Or continue checking. */ + if (tail1 == s1 || tail1[-1] == '.') + return 1; /* match! */ + return 0; /* not match */ +} + +/* Check given NAME is ends with one of + registered direct name entry. + Return 1 if matched, or 0. +*/ +int +is_direct_name (const char *name) +{ + int len, i; + const char *tail; + debug("checking %s is for direct?\n", name); + name = downcase(strdup(name)); + len = strlen(name); + if (len < 1) + return 0; /* false */ + tail = &name[len]; + for (i=0; is_port); + debug("service: %s => %d\n", service, port); + } + } + return (u_short)port; +} + +void +make_revstr(void) +{ + char *ptr; + size_t len; + ptr = strstr(rcs_revstr, ": "); + if (!ptr) { + revstr = strdup("unknown"); + return; + } + ptr += 2; + /* assume subversion's keyword expansion like "Revision: 96". */ + minor_version = atoi(ptr); + revstr = xmalloc(20); + snprintf(revstr, 20, "%d.%d", major_version, minor_version); +} + +int +getarg( int argc, char **argv ) +{ + int err = 0; + char *ptr, *server = (char*)NULL; + int method = METHOD_DIRECT; + + progname = *argv; + argc--, argv++; + + /* check optinos */ + while ( (0 < argc) && (**argv == '-') ) { + ptr = *argv + 1; + while ( *ptr ) { + switch ( *ptr ) { + case 's': /* use SOCKS */ + method = METHOD_SOCKS; + break; + + case 'n': /* no proxy */ + method = METHOD_DIRECT; + break; + + case 'h': /* use http-proxy */ + method = METHOD_HTTP; + break; + case 't': + method = METHOD_TELNET; + break; + + case 'S': /* specify SOCKS server */ + if ( 1 < argc ) { + argv++, argc--; + method = METHOD_SOCKS; + server = *argv; + } else { + error("option '-%c' needs argument.\n", *ptr); + err++; + } + break; + + case 'H': /* specify http-proxy server */ + if ( 1 < argc ) { + argv++, argc--; + method = METHOD_HTTP; + server = *argv; + } else { + error("option '-%c' needs argument.\n", *ptr); + err++; + } + break; + case 'T': /* specify telnet proxy server */ + if ( 1 < argc ) { + argv++, argc--; + method = METHOD_TELNET; + server = *argv; + } else { + error("option '-%c' needs argument.\n", *ptr); + err++; + } + break; + + case 'c': + if (1 < argc) { + argv++, argc--; + telnet_command = *argv; + } else { + error("option '%c' needs argument.\n", *ptr); + err++; + } + break; + + case 'P': + f_hold_session = 1; + /* without break */ + case 'p': /* specify port to forward */ + if ( 1 < argc ) { + argv++, argc--; + local_type = LOCAL_SOCKET; + local_port = resolve_port(*argv); + } else { + error("option '-%c' needs argument.\n", *ptr); + err++; + } + break; + +#ifndef _WIN32 + case 'w': + if ( 1 < argc ) { + argv++, argc--; + connect_timeout = atoi(*argv); + } else { + error("option '-%c' needs argument.\n", *ptr); + err++; + } + break; +#endif /* not _WIN32 */ + + case '4': + socks_version = 4; + break; + + case '5': + socks_version = 5; + break; + + case 'a': + if ( 1 < argc ) { + argv++, argc--; + socks5_auth = *argv; + } else { + error("option '-%c' needs argument.\n", *ptr); + err++; + } + break; + + case 'R': /* specify resolve method */ + if ( 1 < argc ) { + argv++, argc--; + socks_resolve = lookup_resolve( *argv ); + } else { + error("option '-%c' needs argument.\n", *ptr); + err++; + } + break; + + case 'V': /* print version */ + fprintf(stderr, "%s\nVersion %s\n", progdesc, revstr); + exit(0); + + case 'd': /* debug mode */ + f_debug++; + break; + + default: + error("unknown option '-%c'\n", *ptr); + err++; + } + ptr++; + } + argc--, argv++; + } + + /* check error */ + if ( 0 < err ) + goto quit; + + set_relay( method, server ); + + /* check destination HOST (MUST) */ + if ( argc == 0 ) { + fprintf(stderr, "%s\nVersion %s\n", progdesc, revstr); + fprintf(stderr, usage, progname); + exit(0); + } + dest_host = argv[0]; + /* decide port or service name from programname or argument */ + if ( ((ptr=strrchr( progname, '/' )) != NULL) || + ((ptr=strchr( progname, '\\')) != NULL) ) + ptr++; + else + ptr = progname; + if ( dest_port == 0 ) { + /* accept only if -P is not specified. */ + if ( 1 < argc ) { + /* get port number from argument (prior to progname) */ + /* NOTE: This way is for cvs ext method. */ + dest_port = resolve_port(argv[1]); + } else if ( strncmp( ptr, "connect-", 8) == 0 ) { + /* decide port number from program name */ + char *str = strdup( ptr+8 ); + str[strcspn( str, "." )] = '\0'; + dest_port = resolve_port(str); + free(str); + } + } + /* check port number */ + if ( dest_port <= 0 ) { + error( "You must specify the destination port correctly.\n"); + err++; + goto quit; + } + if ( (relay_method != METHOD_DIRECT) && (relay_port <= 0) ) { + error("Invalid relay port: %d\n", dest_port); + err++; + goto quit; + } + +quit: + /* report for debugging */ + debug("relay_method = %s (%d)\n", + method_names[relay_method], relay_method); + if ( relay_method != METHOD_DIRECT ) { + debug("relay_host=%s\n", relay_host); + debug("relay_port=%d\n", relay_port); + debug("relay_user=%s\n", relay_user); + } + if ( relay_method == METHOD_SOCKS ) { + debug("socks_version=%d\n", socks_version); + debug("socks_resolve=%s (%d)\n", + resolve_names[socks_resolve], socks_resolve); + } + debug("local_type=%s\n", local_type_names[local_type]); + if ( local_type == LOCAL_SOCKET ) { + debug("local_port=%d\n", local_port); + if (f_hold_session) + debug (" with holding remote session.\n"); + } + debug("dest_host=%s\n", dest_host); + debug("dest_port=%d\n", dest_port); + if ( 0 < err ) { + fprintf(stderr, usage, progname); + exit(1); + } + return 0; +} + +#ifndef _WIN32 +/* Time-out feature is not allowed for Win32 native compilers. */ +/* MSVC and Borland C cannot but Cygwin and UNIXes can. */ + +/* timeout signal hander */ +void +sig_timeout(void) +{ + signal( SIGALRM, SIG_IGN ); + alarm( 0 ); + error( "timed out\n" ); + exit(1); +} + +/* set timeout param = seconds, 0 clears */ +void +set_timeout(int timeout) +{ + /* This feature is allowed for UNIX or cygwin environments, currently */ + if ( timeout == 0 ) { + debug( "clearing timeout\n" ); + signal( SIGALRM, SIG_IGN ); + alarm( 0 ); + } else { + debug( "setting timeout: %d seconds\n", timeout ); + signal(SIGALRM, (void *)sig_timeout); + alarm( timeout ); + } +} +#endif + +#if !defined(_WIN32) && !defined(__CYGWIN32__) +void +switch_ns (struct sockaddr_in *ns) +{ + res_init(); + memcpy (&_res.nsaddr_list[0], ns, sizeof(*ns)); + _res.nscount = 1; + debug("Using nameserver at %s\n", inet_ntoa(ns->sin_addr)); +} +#endif /* !_WIN32 && !__CYGWIN32__ */ + +/* TODO: IPv6 + TODO: fallback if askpass execution failed. + */ + +int +local_resolve (const char *host, struct sockaddr_in *addr) +{ + struct hostent *ent; + if ( strspn(host, dotdigits) == strlen(host) ) { + /* given by IPv4 address */ + addr->sin_family = AF_INET; + addr->sin_addr.s_addr = inet_addr(host); + } else { + debug("resolving host by name: %s\n", host); + ent = gethostbyname (host); + if ( ent ) { + memcpy (&addr->sin_addr, ent->h_addr, ent->h_length); + addr->sin_family = ent->h_addrtype; + debug("resolved: %s (%s)\n", + host, inet_ntoa(addr->sin_addr)); + } else { + debug("failed to resolve locally.\n"); + return -1; /* failed */ + } + } + return 0; /* good */ +} + +int +open_connection( const char *host, u_short port ) +{ + SOCKET s; + struct sockaddr_in saddr; + + /* resolve address of proxy or direct target */ + if (local_resolve (host, &saddr) < 0) { + error("can't resolve hostname: %s\n", host); + return SOCKET_ERROR; + } + saddr.sin_port = htons(port); + + debug("connecting to %s:%u\n", inet_ntoa(saddr.sin_addr), port); + s = socket( AF_INET, SOCK_STREAM, 0 ); + if ( connect( s, (struct sockaddr *)&saddr, sizeof(saddr)) + == SOCKET_ERROR) { + debug( "connect() failed.\n"); + return SOCKET_ERROR; + } + return s; +} + +void +report_text( char *prefix, char *buf ) +{ + static char work[1024]; + char *tmp; + + if ( !f_debug ) + return; + if ( !f_report ) + return; /* don't report */ + debug("%s \"", prefix); + while ( *buf ) { + memset( work, 0, sizeof(work)); + tmp = work; + while ( *buf && ((tmp-work) < (int)sizeof(work)-5) ) { + switch ( *buf ) { + case '\t': *tmp++ = '\\'; *tmp++ = 't'; break; + case '\r': *tmp++ = '\\'; *tmp++ = 'r'; break; + case '\n': *tmp++ = '\\'; *tmp++ = 'n'; break; + case '\\': *tmp++ = '\\'; *tmp++ = '\\'; break; + default: + if ( isprint(*buf) ) { + *tmp++ = *buf; + } else { + int consumed = tmp - work; + snprintf( tmp, sizeof(work)-consumed, + "\\x%02X", (unsigned char)*buf); + tmp += strlen(tmp); + } + } + buf++; + *tmp = '\0'; + } + debug_("%s", work); + } + + debug_("\"\n"); +} + + +void +report_bytes( char *prefix, char *buf, int len ) +{ + if ( ! f_debug ) + return; + debug( "%s", prefix ); + while ( 0 < len ) { + fprintf( stderr, " %02x", *(unsigned char *)buf); + buf++; + len--; + } + fprintf(stderr, "\n"); + return; +} + +int +atomic_out( SOCKET s, char *buf, int size ) +{ + int ret, len; + + assert( buf != NULL ); + assert( 0<=size ); + /* do atomic out */ + ret = 0; + while ( 0 < size ) { + len = send( s, buf+ret, size, 0 ); + if ( len == -1 ) + fatal("atomic_out() failed to send(), %d\n", socket_errno()); + ret += len; + size -= len; + } + if (!f_report) { + debug("atomic_out() [some bytes]\n"); + debug(">>> xx xx xx xx ...\n"); + } else { + debug("atomic_out() [%d bytes]\n", ret); + report_bytes(">>>", buf, ret); + } + return ret; +} + +int +atomic_in( SOCKET s, char *buf, int size ) +{ + int ret, len; + + assert( buf != NULL ); + assert( 0<=size ); + + /* do atomic in */ + ret = 0; + while ( 0 < size ) { + len = recv( s, buf+ret, size, 0 ); + if ( len == -1 ) { + fatal("atomic_in() failed to recv(), %d\n", socket_errno()); + } else if ( len == 0 ) { + fatal( "Connection closed by peer.\n"); + } + ret += len; + size -= len; + } + if (!f_report) { + debug("atomic_in() [some bytes]\n"); + debug("<<< xx xx xx xx ...\n"); + } else { + debug("atomic_in() [%d bytes]\n", ret); + report_bytes("<<<", buf, ret); + } + return ret; +} + +int +line_input( SOCKET s, char *buf, int size ) +{ + char *dst = buf; + if ( size == 0 ) + return 0; /* no error */ + size--; + while ( 0 < size ) { + switch ( recv( s, dst, 1, 0) ) { /* recv one-by-one */ + case SOCKET_ERROR: + error("recv() error\n"); + return -1; /* error */ + case 0: + size = 0; /* end of stream */ + break; + default: + /* continue reading until last 1 char is EOL? */ + if ( *dst == '\n' ) { + /* finished */ + size = 0; + } else { + /* more... */ + size--; + } + dst++; + } + } + *dst = '\0'; + report_text( "<<<", buf); + return 0; +} + +/* cut_token() + Span token in given string STR until char in DELIM is appeared. + Then replace contiguous DELIMS with '\0' for string termination + and returns next pointer. + If no next token, return NULL. +*/ +char * +cut_token( char *str, char *delim) +{ + char *ptr = str + strcspn(str, delim); + char *end = ptr + strspn(ptr, delim); + if ( ptr == str ) + return NULL; + while ( ptr < end ) + *ptr++ = '\0'; + return ptr; +} + +const char * +lookup(int num, LOOKUP_ITEM *items) +{ + int i = 0; + while (0 <= items[i].num) { + if (items[i].num == num) + return items[i].str; + i++; + } + return "(unknown)"; +} + +/* readpass() + password input routine + Use ssh-askpass (same mechanism to OpenSSH) +*/ +char * +readpass( const char* prompt, ...) +{ + static char buf[1000]; /* XXX, don't be fix length */ + va_list args; + va_start(args, prompt); + vsnprintf(buf, sizeof(buf), prompt, args); + va_end(args); + + if ( getparam(ENV_SSH_ASKPASS) +#if !defined(_WIN32) && !defined(__CYGWIN32__) + && getenv("DISPLAY") +#endif /* not _WIN32 && not __CYGWIN32__ */ + ) { + /* use ssh-askpass to get password */ + FILE *fp; + char *askpass = getparam(ENV_SSH_ASKPASS), *cmd; + int cmd_size = strlen(askpass) +1 +1 +strlen(buf) +1 +1; + cmd = xmalloc(cmd_size); + snprintf(cmd, cmd_size, "%s \"%s\"", askpass, buf); + fp = popen(cmd, "r"); + free(cmd); + if ( fp == NULL ) + return NULL; /* fail */ + buf[0] = '\0'; + if (fgets(buf, sizeof(buf), fp) == NULL) + return NULL; /* fail */ + fclose(fp); + } else { + tty_readpass( buf, buf, sizeof(buf)); + } + buf[strcspn(buf, "\r\n")] = '\0'; + return buf; +} + +static int +socks5_do_auth_userpass( int s ) +{ + unsigned char buf[1024], *ptr; + char *pass = NULL; + int len; + + /* do User/Password authentication. */ + /* This feature requires username and password from + command line argument or environment variable, + or terminal. */ + if (relay_user == NULL) + fatal("cannot determine user name.\n"); + + /* get password from environment variable if exists. */ + if ((pass=determine_relay_password()) == NULL && + (pass=readpass("Enter SOCKS5 password for %s@%s: ", + relay_user, relay_host)) == NULL) + fatal("Cannot get password for user: %s\n", relay_user); + + /* make authentication packet */ + ptr = buf; + PUT_BYTE( ptr++, 1 ); /* subnegotiation ver.: 1 */ + len = strlen( relay_user ); /* ULEN and UNAME */ + PUT_BYTE( ptr++, len ); + strcpy( ptr, relay_user ); + ptr += len; + len = strlen( pass ); /* PLEN and PASSWD */ + PUT_BYTE( ptr++, strlen(pass)); + strcpy( ptr, pass ); + ptr += len; + memset (pass, 0, strlen(pass)); /* erase password */ + + /* send it and get answer */ + f_report = 0; + atomic_out( s, buf, ptr-buf ); + f_report = 1; + atomic_in( s, buf, 2 ); + + /* check status */ + if ( buf[1] == 0 ) + return 0; /* success */ + else + return -1; /* fail */ +} + +static const char * +socks5_getauthname( int auth ) +{ + switch ( auth ) { + case SOCKS5_AUTH_REJECT: return "REJECTED"; + case SOCKS5_AUTH_NOAUTH: return "NO-AUTH"; + case SOCKS5_AUTH_GSSAPI: return "GSSAPI"; + case SOCKS5_AUTH_USERPASS: return "USERPASS"; + case SOCKS5_AUTH_CHAP: return "CHAP"; + case SOCKS5_AUTH_EAP: return "EAP"; + case SOCKS5_AUTH_MAF: return "MAF"; + default: return "(unknown)"; + } +} + +typedef struct { + char* name; + unsigned char auth; +} AUTH_METHOD_ITEM; + +AUTH_METHOD_ITEM socks5_auth_table[] = { + { "none", SOCKS5_AUTH_NOAUTH }, + { "gssapi", SOCKS5_AUTH_GSSAPI }, + { "userpass", SOCKS5_AUTH_USERPASS }, + { "chap", SOCKS5_AUTH_CHAP }, + { NULL, -1 }, +}; + +int +socks5_auth_parse_1(char *start, char *end){ + int i, len; + for ( ; *start; start++ ) + if ( *start != ' ' && *start != '\t') break; + for ( end--; end >= start; end-- ) { + if ( *end != ' ' && *end != '\t'){ + end++; + break; + } + } + len = end - start; + for ( i = 0; socks5_auth_table[i].name != NULL; i++ ){ + if ( strncmp(start, socks5_auth_table[i].name, len) == 0) { + return socks5_auth_table[i].auth; + } + } + fatal("Unknown auth method: %s\n", start); + return -1; +} + +int +socks5_auth_parse(char *start, unsigned char *auth_list, int max_auth){ + char *end; + int i = 0; + while ( i < max_auth ) { + end = strchr(start, ','); + if (*start && end) { + auth_list[i++] = socks5_auth_parse_1(start, end); + start = ++end; + } else { + break; + } + } + if ( *start && ( i < max_auth ) ){ + for( end = start; *end; end++ ); + auth_list[i++] = socks5_auth_parse_1(start, end); + } else { + fatal("Too much auth method.\n"); + } + return i; +} + +/* begin SOCKS5 relaying + And no authentication is supported. + */ +int +begin_socks5_relay( SOCKET s ) +{ + unsigned char buf[256], *ptr, *env = socks5_auth; + unsigned char n_auth = 0; unsigned char auth_list[10], auth_method; + int len, auth_result, i; + + debug( "begin_socks_relay()\n"); + + /* request authentication */ + ptr = buf; + PUT_BYTE( ptr++, 5); /* SOCKS version (5) */ + + if ( env == NULL ) + env = getparam(ENV_SOCKS5_AUTH); + if ( env == NULL ) { + /* add no-auth authentication */ + auth_list[n_auth++] = SOCKS5_AUTH_NOAUTH; + /* add user/pass authentication */ + auth_list[n_auth++] = SOCKS5_AUTH_USERPASS; + } else { + n_auth = socks5_auth_parse(env, auth_list, 10); + } + PUT_BYTE( ptr++, n_auth); /* num auth */ + for (i=0; i>8); /* DST.PORT */ + PUT_BYTE( ptr++, dest_port&0xFF); + atomic_out( s, buf, ptr-buf); /* send request */ + atomic_in( s, buf, 4 ); /* recv response */ + if ( (buf[1] != SOCKS5_REP_SUCCEEDED) ) { /* check reply code */ + error("Got error response from SOCKS server: %d (%s).\n", + buf[1], lookup(buf[1], socks5_rep_names)); + return -1; + } + ptr = buf + 4; + switch ( buf[3] ) { /* case by ATYP */ + case 1: /* IP v4 ADDR*/ + atomic_in( s, ptr, 4+2 ); /* recv IPv4 addr and port */ + break; + case 3: /* DOMAINNAME */ + atomic_in( s, ptr, 1 ); /* recv name and port */ + atomic_in( s, ptr+1, *(unsigned char*)ptr + 2); + break; + case 4: /* IP v6 ADDR */ + atomic_in( s, ptr, 16+2 ); /* recv IPv6 addr and port */ + break; + } + + /* Conguraturation, connected via SOCKS5 server! */ + return 0; +} + +/* begin SOCKS protocol 4 relaying + And no authentication is supported. + + There's SOCKS protocol version 4 and 4a. Protocol version + 4a has capability to resolve hostname by SOCKS server, so + we don't need resolving IP address of destination host on + local machine. + + Environment variable SOCKS_RESOLVE directs how to resolve + IP addess. There's 3 keywords allowed; "local", "remote" + and "both" (case insensitive). Keyword "local" means taht + target host name is resolved by localhost resolver + (usualy with gethostbyname()), "remote" means by remote + SOCKS server, "both" means to try resolving by localhost + then remote. + + SOCKS4 protocol and authentication of SOCKS5 protocol + requires user name on connect request. + User name is determined by following method. + + 1. If server spec has user@hostname:port format then + user part is used for this SOCKS server. + + 2. Get user name from environment variable LOGNAME, USER + (in this order). + +*/ +int +begin_socks4_relay( SOCKET s ) +{ + unsigned char buf[256], *ptr; + + debug( "begin_socks_relay()\n"); + + /* make connect request packet + protocol v4: + VN:1, CD:1, PORT:2, ADDR:4, USER:n, NULL:1 + protocol v4a: + VN:1, CD:1, PORT:2, DUMMY:4, USER:n, NULL:1, HOSTNAME:n, NULL:1 + */ + ptr = buf; + PUT_BYTE( ptr++, 4); /* protocol version (4) */ + PUT_BYTE( ptr++, 1); /* CONNECT command */ + PUT_BYTE( ptr++, dest_port>>8); /* destination Port */ + PUT_BYTE( ptr++, dest_port&0xFF); + /* destination IP */ + memcpy(ptr, &dest_addr.sin_addr, sizeof(dest_addr.sin_addr)); + ptr += sizeof(dest_addr.sin_addr); + if ( dest_addr.sin_addr.s_addr == 0 ) + *(ptr-1) = 1; /* fake, protocol 4a */ + /* username */ + if (relay_user == NULL) + fatal( "Cannot determine user name.\n"); + strcpy( ptr, relay_user ); + ptr += strlen( relay_user ) +1; + /* destination host name (for protocol 4a) */ + if ( (socks_version == 4) && (dest_addr.sin_addr.s_addr == 0)) { + strcpy( ptr, dest_host ); + ptr += strlen( dest_host ) +1; + } + /* send command and get response + response is: VN:1, CD:1, PORT:2, ADDR:4 */ + atomic_out( s, buf, ptr-buf); /* send request */ + atomic_in( s, buf, 8 ); /* recv response */ + if ( (buf[1] != SOCKS4_REP_SUCCEEDED) ) { /* check reply code */ + error("Got error response: %d: '%s'.\n", + buf[1], lookup(buf[1], socks4_rep_names)); + return -1; /* failed */ + } + + /* Conguraturation, connected via SOCKS4 server! */ + return 0; +} + +int +sendf(SOCKET s, const char *fmt,...) +{ + static char buf[10240]; /* xxx, enough? */ + + va_list args; + va_start( args, fmt ); + vsnprintf( buf, sizeof(buf), fmt, args ); + va_end( args ); + + report_text(">>>", buf); + if ( send(s, buf, strlen(buf), 0) == SOCKET_ERROR ) { + debug("failed to send http request. errno=%d\n", socket_errno()); + return -1; + } + return 0; +} + +const char *base64_table = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +char * +make_base64_string(const char *str) +{ + static char *buf; + unsigned char *src; + char *dst; + int bits, data, src_len, dst_len; + /* make base64 string */ + src_len = strlen(str); + dst_len = (src_len+2)/3*4; + buf = xmalloc(dst_len+1); + bits = data = 0; + src = (unsigned char *)str; + dst = (unsigned char *)buf; + while ( dst_len-- ) { + if ( bits < 6 ) { + data = (data << 8) | *src; + bits += 8; + if ( *src != 0 ) + src++; + } + *dst++ = base64_table[0x3F & (data >> (bits-6))]; + bits -= 6; + } + *dst = '\0'; + /* fix-up tail padding */ + switch ( src_len%3 ) { + case 1: + *--dst = '='; + case 2: + *--dst = '='; + } + return buf; +} + + +int +basic_auth (SOCKET s) +{ + char *userpass; + char *cred; + const char *user = relay_user; + char *pass = NULL; + int len, ret; + + /* Get username/password for authentication */ + if (user == NULL) + fatal("Cannot decide username for proxy authentication."); + if ((pass = determine_relay_password ()) == NULL && + (pass = readpass("Enter proxy authentication password for %s@%s: ", + relay_user, relay_host)) == NULL) + fatal("Cannot decide password for proxy authentication."); + + len = strlen(user)+strlen(pass)+1; + userpass = xmalloc(len+1); + snprintf(userpass, len+1, "%s:%s", user, pass); + memset (pass, 0, strlen(pass)); + cred = make_base64_string(userpass); + memset (userpass, 0, len); + + f_report = 0; /* don't report for security */ + ret = sendf(s, "Proxy-Authorization: Basic %s\r\n", cred); + f_report = 1; + report_text(">>>", "Proxy-Authorization: Basic xxxxx\r\n"); + + memset(cred, 0, strlen(cred)); + free(cred); + + return ret; +} + +/* begin relaying via HTTP proxy + Directs CONNECT method to proxy server to connect to + destination host (and port). It may not be allowed on your + proxy server. + */ +int +begin_http_relay( SOCKET s ) +{ + char buf[1024]; + int result; + char *auth_what; + + debug("begin_http_relay()\n"); + + if (sendf(s,"CONNECT %s:%d HTTP/1.0\r\n", dest_host, dest_port) < 0) + return START_ERROR; + if (proxy_auth_type == PROXY_AUTH_BASIC && basic_auth (s) < 0) + return START_ERROR; + if (sendf(s,"\r\n") < 0) + return START_ERROR; + + /* get response */ + if ( line_input(s, buf, sizeof(buf)) < 0 ) { + debug("failed to read http response.\n"); + return START_ERROR; + } + + /* check status */ + if (!strchr(buf, ' ')) { + error ("Unexpected http response: '%s'.\n", buf); + return START_ERROR; + } + result = atoi(strchr(buf,' ')); + + switch ( result ) { + case 200: + /* Conguraturation, connected via http proxy server! */ + debug("connected, start user session.\n"); + break; + case 302: /* redirect */ + do { + if (line_input(s, buf, sizeof(buf))) + break; + downcase(buf); + if (expect(buf, "Location: ")) { + relay_host = cut_token(buf, "//"); + cut_token(buf, "/"); + relay_port = atoi(cut_token(buf, ":")); + } + } while (strcmp(buf,"\r\n") != 0); + return START_RETRY; + + /* We handle both 401 and 407 codes here: 401 is WWW-Authenticate, which + * not strictly the correct response, but some proxies do send this (e.g. + * Symantec's Raptor firewall) */ + case 401: /* WWW-Auth required */ + case 407: /* Proxy-Auth required */ + /** NOTE: As easy implementation, we support only BASIC scheme + and ignore realm. */ + /* If proxy_auth_type is PROXY_AUTH_BASIC and get + this result code, authentication was failed. */ + if (proxy_auth_type != PROXY_AUTH_NONE) { + error("Authentication failed.\n"); + return START_ERROR; + } + auth_what = (result == 401) ? "WWW-Authenticate:" : "Proxy-Authenticate:"; + do { + if ( line_input(s, buf, sizeof(buf)) ) { + break; + } + downcase(buf); + if (expect(buf, auth_what)) { + /* parse type and realm */ + char *scheme, *realm; + scheme = cut_token(buf, " "); + realm = cut_token(scheme, " "); + if ( scheme == NULL || realm == NULL ) { + debug("Invalid format of %s field.", auth_what); + return START_ERROR; /* fail */ + } + /* check supported auth type */ + if (expect(scheme, "basic")) { + proxy_auth_type = PROXY_AUTH_BASIC; + } else { + debug("Unsupported authentication type: %s", scheme); + } + } + } while (strcmp(buf,"\r\n") != 0); + if ( proxy_auth_type == PROXY_AUTH_NONE ) { + debug("Can't find %s in response header.", auth_what); + return START_ERROR; + } else { + return START_RETRY; + } + + default: + /* Not allowed */ + debug("http proxy is not allowed.\n"); + return START_ERROR; + } + /* skip to end of response header */ + do { + if ( line_input(s, buf, sizeof(buf) ) ) { + debug("Can't skip response headers\n"); + return START_ERROR; + } + } while ( strcmp(buf,"\r\n") != 0 ); + + return START_OK; +} + +/* begin relaying via TELNET proxy. + Sends string specified by telnet_command (-c option) with + replacing host name and port number to the socket. */ +int +begin_telnet_relay( SOCKET s ) +{ + char buf[1024]; + char *cmd; + char *good_phrase = "connected to"; + char *bad_phrase_list[] = { + " failed", " refused", " rejected", " closed" + }; + char sep = ' '; + int i; + + debug("begin_telnet_relay()\n"); + + /* report phrase */ + debug("good phrase: '%s'\n", good_phrase); + debug("bad phrases"); + sep = ':'; + for (i=0; i< (sizeof(bad_phrase_list) / sizeof(char*)); i++) { + debug_("%c '%s'", sep, bad_phrase_list[i]); + sep = ','; + } + debug_("\n"); + + /* make request string with replacing %h by destination hostname + and %p by port number, etc. */ + cmd = expand_host_and_port(telnet_command, dest_host, dest_port); + + /* Sorry, we send request string now without waiting a prompt. */ + if (sendf(s, "%s\r\n", cmd) < 0) { + free(cmd); + return START_ERROR; + } + free(cmd); + + /* Process answer from proxy until good or bad phrase is detected. We + assume that the good phrase should be appeared only in the final + line of proxy responses. Bad keywods in the line causes operation + fail. First checks a good phrase, then checks bad phrases. + If no match, continue reading line from proxy. */ + while (!line_input(s, buf, sizeof(buf)) && buf[0] != '\0') { + downcase(buf); + /* first, check good phrase */ + if (strstr(buf, good_phrase)) { + debug("good phrase is detected: '%s'\n", good_phrase); + return START_OK; + } + /* then, check bad phrase */ + for (i=0; i<(sizeof(bad_phrase_list)/sizeof(char*)); i++) { + if (strstr(buf, bad_phrase_list[i]) != NULL) { + debug("bad phrase is detected: '%s'\n", bad_phrase_list[i]); + return START_ERROR; + } + } + } + debug("error reading from telnet proxy\n"); + + return START_ERROR; +} + + +#ifdef _WIN32 +/* ddatalen() + Returns 1 if data is available, otherwise return 0 + */ +int +stdindatalen (void) +{ + DWORD len = 0; + struct stat st; + fstat( 0, &st ); + if ( st.st_mode & _S_IFIFO ) { + /* in case of PIPE */ + if ( !PeekNamedPipe( GetStdHandle(STD_INPUT_HANDLE), + NULL, 0, NULL, &len, NULL) ) { + if ( GetLastError() == ERROR_BROKEN_PIPE ) { + /* PIPE source is closed */ + /* read() will detects EOF */ + len = 1; + } else { + fatal("PeekNamedPipe() failed, errno=%d\n", + GetLastError()); + } + } + } else if ( st.st_mode & _S_IFREG ) { + /* in case of regular file (redirected) */ + len = 1; /* always data ready */ + } else if ( _kbhit() ) { + /* in case of console */ + len = 1; + } + return len; +} +#endif /* _WIN32 */ + +/* relay byte from stdin to socket and fro socket to stdout. + returns reason of termination */ +int +do_repeater( SOCKET local_in, SOCKET local_out, SOCKET remote ) +{ + /** vars for local input data **/ + char lbuf[1024]; /* local input buffer */ + int lbuf_len; /* available data in lbuf */ + int f_local; /* read local input more? */ + /** vars for remote input data **/ + char rbuf[1024]; /* remote input buffer */ + int rbuf_len; /* available data in rbuf */ + int f_remote; /* read remote input more? */ + int close_reason = REASON_UNK; /* reason of end repeating */ + /** other variables **/ + int nfds, len; + fd_set ifds, ofds; + struct timeval *tmo; +#ifdef _WIN32 + struct timeval win32_tmo; +#endif /* _WIN32 */ + + /* repeater between stdin/out and socket */ + nfds = ((local_in local */ + if ( FD_ISSET(remote, &ifds) && (rbuf_len < (int)sizeof(rbuf)) ) { + len = recv( remote, rbuf + rbuf_len, sizeof(rbuf)-rbuf_len, 0); + if ( len == 0 || (len == -1 && socket_errno() == ECONNRESET)) { + debug("connection %s by peer\n", + (len==0)? "closed": "reset"); + close_reason = REASON_CLOSED_BY_REMOTE; + f_remote = 0; /* no more read from socket */ + f_local = 0; + } else if ( len == -1 ) { + /* error */ + fatal("recv() failed, %d\n", socket_errno()); + } else { + debug("recv %d bytes\n", len); + if ( 1 < f_debug ) /* more verbose */ + report_bytes( "<<<", rbuf+rbuf_len, len); + rbuf_len += len; + } + } + + /* local => remote */ + if ( FD_ISSET(local_in, &ifds) && (lbuf_len < (int)sizeof(lbuf)) ) { + if (local_type == LOCAL_SOCKET) + len = recv(local_in, lbuf + lbuf_len, + sizeof(lbuf)-lbuf_len, 0); + else + len = read(local_in, lbuf + lbuf_len, sizeof(lbuf)-lbuf_len); + if ( len == 0 ) { + /* stdin is EOF */ + debug("local input is EOF\n"); + if (!f_hold_session) + shutdown(remote, 1); /* no-more writing */ + f_local = 0; + close_reason = REASON_CLOSED_BY_LOCAL; + } else if ( len == -1 ) { + /* error on reading from stdin */ + if (f_hold_session) { + debug ("failed to read from local\n"); + f_local = 0; + close_reason = REASON_CLOSED_BY_LOCAL; + } else + fatal("recv() failed, errno = %d\n", errno); + } else { + /* repeat */ + lbuf_len += len; + } + } + + /* flush data in buffer to socket */ + if ( 0 < lbuf_len ) { + len = send(remote, lbuf, lbuf_len, 0); + if ( len == -1 ) { + fatal("send() failed, %d\n", socket_errno()); + } else if ( 0 < len ) { + if ( 1 < f_debug ) /* more verbose */ + report_bytes( ">>>", lbuf, len); + /* move data on to top of buffer */ + debug("sent %d bytes\n", len); + lbuf_len -= len; + if ( 0 < lbuf_len ) + memcpy( lbuf, lbuf+len, lbuf_len ); + assert( 0 <= lbuf_len ); + } + } + + /* flush data in buffer to local output */ + if ( 0 < rbuf_len ) { + if (local_type == LOCAL_SOCKET) + len = send( local_out, rbuf, rbuf_len, 0); + else + len = write( local_out, rbuf, rbuf_len); + if ( len == -1 ) { + fatal("output (local) failed, errno=%d\n", errno); + } + rbuf_len -= len; + if ( len < rbuf_len ) + memcpy( rbuf, rbuf+len, rbuf_len ); + assert( 0 <= rbuf_len ); + } + if (f_local == 0 && f_hold_session) { + debug ("closing local port without disconnecting from remote\n"); + f_remote = 0; + shutdown (local_out, 2); + close (local_out); + break; + } + } + + return close_reason; +} + +int +accept_connection (u_short port) +{ + static int sock = -1; + int connection; + struct sockaddr_in name; + struct sockaddr client; + int socklen; + fd_set ifds; + int nfds; + int sockopt; + + /* Create the socket. */ + debug("Creating source port to forward.\n"); + sock = socket (PF_INET, SOCK_STREAM, 0); + if (sock < 0) + fatal("socket() failed, errno=%d\n", socket_errno()); + sockopt = 1; + setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, + (void*)&sockopt, sizeof(sockopt)); + + /* Give the socket a name. */ + name.sin_family = AF_INET; + name.sin_port = htons (port); + name.sin_addr.s_addr = htonl (INADDR_ANY); + if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) + fatal ("bind() failed, errno=%d\n", socket_errno()); + + if (listen( sock, 1) < 0) + fatal ("listen() failed, errno=%d\n", socket_errno()); + + /* wait for new connection with watching EOF of stdin. */ + debug ("waiting new connection at port %d (socket=%d)\n", port, sock); + nfds = sock + 1; + do { + int n; + struct timeval *ptmo = NULL; +#ifdef _WIN32 + struct timeval tmo; + tmo.tv_sec = 0; + tmo.tv_usec = 100*1000; /* On Windows, 100ms timeout */ + ptmo = &tmo; +#endif /* _WIN32 */ + FD_ZERO (&ifds); + FD_SET ((SOCKET)sock, &ifds); +#ifndef _WIN32 + FD_SET (0, &ifds); /* watch stdin */ +#endif + n = select (nfds, &ifds, NULL, NULL, ptmo); + if (n == -1) { + fatal ("select() failed, %d\n", socket_errno()); + exit (1); + } +#ifdef _WIN32 + if (0 < stdindatalen()) { + FD_SET (0, &ifds); /* fake */ + n++; + } +#endif + if (0 < n) { + if (FD_ISSET(0, &ifds) && (getchar() <= 0)) { + /* EOF */ + debug ("Give-up waiting port because stdin is closed."); + exit(0); + } + if (FD_ISSET(sock, &ifds)) + break; /* socket is stimulated */ + } + } while (1); + socklen = sizeof(client); + connection = accept( sock, &client, &socklen); + if ( connection < 0 ) + fatal ("accept() failed, errno=%d\n", socket_errno()); + return connection; +} + + + +/** Main of program **/ +int +main( int argc, char **argv ) +{ + int ret; + int remote; /* socket */ + int local_in; /* Local input */ + int local_out; /* Local output */ + int reason; +#ifdef _WIN32 + WSADATA wsadata; + WSAStartup( 0x101, &wsadata); +#endif /* _WIN32 */ + + /* initialization */ + make_revstr(); + getarg( argc, argv ); + debug("Program is $Revision: 100 $\n"); + + /* Open local_in and local_out if forwarding a port */ + if ( local_type == LOCAL_SOCKET ) { + /* Relay between local port and destination */ + local_in = local_out = accept_connection( local_port ); + } else { + /* Relay between stdin/stdout and desteination */ + local_in = 0; + local_out = 1; +#ifdef _WIN32 + _setmode(local_in, O_BINARY); + _setmode(local_out, O_BINARY); +#endif + } + +retry: +#ifndef _WIN32 + if (0 < connect_timeout) + set_timeout (connect_timeout); +#endif /* not _WIN32 */ + + if (check_direct(dest_host)) + relay_method = METHOD_DIRECT; + /* make connection */ + if ( relay_method == METHOD_DIRECT ) { + remote = open_connection (dest_host, dest_port); + if ( remote == SOCKET_ERROR ) + fatal( "Unable to connect to destination host, errno=%d\n", + socket_errno()); + } else { + remote = open_connection (relay_host, relay_port); + if ( remote == SOCKET_ERROR ) + fatal( "Unable to connect to relay host, errno=%d\n", + socket_errno()); + } + + /** resolve destination host (SOCKS) **/ +#if !defined(_WIN32) && !defined(__CYGWIN32__) + if (socks_ns.sin_addr.s_addr != 0) + switch_ns (&socks_ns); +#endif /* not _WIN32 && not __CYGWIN32__ */ + if (relay_method == METHOD_SOCKS && + socks_resolve == RESOLVE_LOCAL && + local_resolve (dest_host, &dest_addr) < 0) { + fatal("Unknown host: %s", dest_host); + } + + /** relay negociation **/ + switch ( relay_method ) { + case METHOD_SOCKS: + if ( ((socks_version == 5) && (begin_socks5_relay(remote) < 0)) || + ((socks_version == 4) && (begin_socks4_relay(remote) < 0)) ) + fatal( "failed to begin relaying via SOCKS.\n"); + break; + + case METHOD_HTTP: + ret = begin_http_relay(remote); + switch (ret) { + case START_ERROR: + close (remote); + fatal("failed to begin relaying via HTTP.\n"); + case START_OK: + break; + case START_RETRY: + /* retry with authentication */ + close (remote); + goto retry; + } + break; + case METHOD_TELNET: + if (begin_telnet_relay(remote) < 0) + fatal("failed to begin relaying via telnet.\n"); + break; + } + debug("connected\n"); + +#ifndef _WIN32 + if (0 < connect_timeout) + set_timeout (0); +#endif /* not _WIN32 */ + + /* main loop */ + debug ("start relaying.\n"); +do_repeater: + reason = do_repeater(local_in, local_out, remote); + debug ("relaying done.\n"); + if (local_type == LOCAL_SOCKET && + reason == REASON_CLOSED_BY_LOCAL && + f_hold_session) { + /* re-wait at local port without closing remote session */ + debug ("re-waiting at local port %d\n", local_port); + local_in = local_out = accept_connection( local_port ); + debug ("re-start relaying\n"); + goto do_repeater; + } + closesocket(remote); + if ( local_type == LOCAL_SOCKET) + closesocket(local_in); +#ifdef _WIN32 + WSACleanup(); +#endif /* _WIN32 */ + debug ("that's all, bye.\n"); + + return 0; +} + +/* ------------------------------------------------------------ + Local Variables: + compile-command: "cc connect.c -o connect" + tab-width: 8 + fill-column: 74 + comment-column: 48 + End: + ------------------------------------------------------------ */ + +/*** end of connect.c ***/ diff --git a/scripts/oe-setup-rpmrepo b/scripts/oe-setup-rpmrepo new file mode 100755 index 0000000000..03372b6199 --- /dev/null +++ b/scripts/oe-setup-rpmrepo @@ -0,0 +1,89 @@ +#!/bin/bash +# +# This utility setup the necessary metadata for an rpm repo +# +# Copyright (c) 2011 Intel Corp. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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 + +function usage() { + echo "Usage: $0 " + echo " : default is $TPMDIR/deploy/rpm" +} + +if [ $# -gt 1 ]; then + usage + exit 1 +fi + +setup_tmpdir() { + if [ -z "$TMPDIR" ]; then + if [ "x$BUILDDIR" = "x" -o ! -d "$BUILDDIR/tmp" ]; then + # BUILDDIR unset, try and get TMPDIR from bitbake + type -P bitbake &>/dev/null || { + echo "In order for this script to dynamically infer paths"; + echo "to kernels or filesystem images, you either need"; + echo "bitbake in your PATH or to source oe-init-build-env"; + echo "before running this script" >&2; + exit 1; } + + # We have bitbake in PATH, get TMPDIR from bitbake + TMPDIR=`bitbake -e | grep TMPDIR=\" | cut -d '=' -f2 | cut -d '"' -f2` + else + TMPDIR=$BUILDDIR/tmp + fi + fi +} + +setup_sysroot() { + # Toolchain installs set up $OECORE_NATIVE_SYSROOT in their + # environment script. If that variable isn't set, we're + # either in an in-tree poky scenario or the environment + # script wasn't source'd. + if [ -z "$OECORE_NATIVE_SYSROOT" ]; then + setup_tmpdir + BUILD_ARCH=`uname -m` + BUILD_OS=`uname | tr '[A-Z]' '[a-z]'` + BUILD_SYS="$BUILD_ARCH-$BUILD_OS" + + OECORE_NATIVE_SYSROOT=$TMPDIR/sysroots/$BUILD_SYS + fi +} + +setup_tmpdir +setup_sysroot + + +if [ -n "$1" ]; then + RPM_DIR="$1" +else + RPM_DIR="$TMPDIR/deploy/rpm" +fi + +if [ ! -d "$RPM_DIR" ]; then + echo "Error: rpm dir $RPM_DIR doesn't exist" + exit 1 +fi + +CREATEREPO=$OECORE_NATIVE_SYSROOT/usr/bin/createrepo +if [ ! -e "$CREATEREPO" ]; then + echo "Error: can't find createrepo binary" + echo "please run bitbake createrepo-native first" + exit 1 +fi + + +$CREATEREPO "$RPM_DIR" + +exit 0 diff --git a/scripts/oe-trim-schemas b/scripts/oe-trim-schemas new file mode 100755 index 0000000000..29fb3a1b67 --- /dev/null +++ b/scripts/oe-trim-schemas @@ -0,0 +1,49 @@ +#! /usr/bin/env python + +import sys +try: + import xml.etree.cElementTree as etree +except: + import xml.etree.ElementTree as etree + +def child (elem, name): + for e in elem.getchildren(): + if e.tag == name: + return e + return None + +def children (elem, name=None): + l = elem.getchildren() + if name: + l = [e for e in l if e.tag == name] + return l + +xml = etree.parse(sys.argv[1]) + +for schema in child(xml.getroot(), "schemalist").getchildren(): + e = child(schema, "short") + if e is not None: + schema.remove(e) + + e = child(schema, "long") + if e is not None: + schema.remove(e) + + for locale in children(schema, "locale"): + # One locale must exist so leave C locale... + a = locale.attrib.get("name") + if a == 'C': + continue + e = child(locale, "default") + if e is None: + schema.remove(locale) + else: + e = child(locale, "short") + if e is not None: + locale.remove(e) + e = child(locale, "long") + if e is not None: + locale.remove(e) + +xml.write(sys.stdout, "UTF-8") + diff --git a/scripts/poky-addptable2image b/scripts/poky-addptable2image deleted file mode 100755 index f0195ad8a3..0000000000 --- a/scripts/poky-addptable2image +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/sh - -# Add a partion table to an ext2 image file -# -# Copyright (C) 2006-2007 OpenedHand Ltd. -# -# 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 - - -IMAGE=$1 -IMAGEOUT=$2 - -echo $IMAGE -echo $IMAGEOUT - -size=`ls -l $IMAGE | awk '{ print $5}'` -size2=`expr $size / 512 / 16 / 63` - -echo $size -echo $size2 - -# MBR Size = 512 * 63 bytes -dd if=/dev/zero of=$IMAGEOUT count=63 - -echo "x" > /tmp/fdisk.cmds -echo "c" >> /tmp/fdisk.cmds -echo "1024" >> /tmp/fdisk.cmds -echo "h" >> /tmp/fdisk.cmds -echo "16" >> /tmp/fdisk.cmds -echo "r" >> /tmp/fdisk.cmds -echo "n" >> /tmp/fdisk.cmds -echo "p" >> /tmp/fdisk.cmds -echo "1" >> /tmp/fdisk.cmds -echo "1" >> /tmp/fdisk.cmds -echo "$size2" >> /tmp/fdisk.cmds -echo "w" >> /tmp/fdisk.cmds - -/sbin/fdisk $IMAGEOUT < /tmp/fdisk.cmds -cat $IMAGE >> $IMAGEOUT diff --git a/scripts/poky-export-rootfs b/scripts/poky-export-rootfs deleted file mode 100755 index 764d19a823..0000000000 --- a/scripts/poky-export-rootfs +++ /dev/null @@ -1,186 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2005-2009 Wind River Systems, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# 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 - -usage() { - echo "Usage: $0 {start|stop|restart} " -} - -if [ $# != 2 ]; then - usage - exit 1 -fi - -if [[ "$1" != "start" && "$1" != "stop" && "$1" != "restart" ]]; then - echo "Unknown command '$1'" - usage - exit 1 -fi - -if [ ! -d "$2" ]; then - echo "Error: '$2' does not exist" - usage - exit 1 -fi -# Ensure the nfs-export-dir is an absolute path -NFS_EXPORT_DIR=$(cd "$2" && pwd) - -SYSROOT_SETUP_SCRIPT=`which poky-find-native-sysroot` -if [ -z "$SYSROOT_SETUP_SCRIPT" ]; then - echo "Error: Unable to find the poky-find-native-sysroot script" - echo "Did you forget to source your Poky environment script?" - exit 1 -fi -. $SYSROOT_SETUP_SCRIPT - -if [ ! -e "$OECORE_NATIVE_SYSROOT/usr/sbin/rpc.mountd" ]; then - echo "Error: Unable to find rpc.mountd binary in $OECORE_NATIVE_SYSROOT/usr/sbin/" - - if [ "x$POKY_DISTRO_VERSION" = "x" ]; then - echo "Have you run 'bitbake meta-ide-support'?" - else - echo "This shouldn't happen - something is missing from your toolchain installation" - fi - exit 1 -fi - -if [ ! -d ~/.poky-sdk ]; then - mkdir -p ~/.poky-sdk -fi - -NFS_INSTANCE=${NFS_INSTANCE:=0} -EXPORTS=~/.poky-sdk/exports$NFS_INSTANCE -RMTAB=~/.poky-sdk/rmtab$NFS_INSTANCE -NFSPID=~/.poky-sdk/nfs$NFS_INSTANCE.pid -MOUNTPID=~/.poky-sdk/mount$NFS_INSTANCE.pid - -PSEUDO_OPTS="-P $OECORE_NATIVE_SYSROOT/usr" -PSEUDO_LOCALSTATEDIR="$NFS_EXPORT_DIR/var/pseudo" -export PSEUDO_LOCALSTATEDIR - -if [ ! -d "$PSEUDO_LOCALSTATEDIR" ]; then - echo "Error: $PSEUDO_LOCALSTATEDIR does not exist." - echo "Did you create the export directory using poky-extract-sdk?" - exit 1 -fi - -# rpc.mountd RPC port -NFS_MOUNTPROG=$[ 21111 + $NFS_INSTANCE ] -# rpc.nfsd RPC port -NFS_NFSPROG=$[ 11111 + $NFS_INSTANCE ] -# NFS port number -NFS_PORT=$[ 3049 + $NFS_INSTANCE ] - -## For debugging you would additionally add -## --debug all -MOUNTD_OPTS="--allow-non-root --mount-pid $MOUNTPID -f $EXPORTS --rmtab $RMTAB --prog $NFS_MOUNTPROG -r" -NFSD_OPTS="--allow-non-root --nfs-pid $NFSPID -f $EXPORTS --prog $NFS_NFSPROG -P $NFS_PORT -r" - -# Setup the exports file -if [ "$1" = "start" ]; then - echo "Creating exports file..." - echo "$NFS_EXPORT_DIR (rw,async,no_root_squash,no_all_squash,insecure)" > $EXPORTS -fi - -# See how we were called. -case "$1" in - start) - echo "Starting User Mode rpc.mountd" - echo " $PSEUDO $PSEUDO_OPTS $OECORE_NATIVE_SYSROOT/usr/sbin/rpc.mountd $MOUNTD_OPTS" - $PSEUDO $PSEUDO_OPTS $OECORE_NATIVE_SYSROOT/usr/sbin/rpc.mountd $MOUNTD_OPTS - if [ ! $? = 0 ]; then - echo "=====================" - echo "Error starting MOUNTD" - echo "=====================" - ps -ef | grep -v grep | grep rpcbind 2>&1 > /dev/null - if [ $? = 0 ] ; then - echo " If you see an error above that says:" - echo " RPC: Authentication error; why = Client credential too weak" - echo " You need to change the startup of rpcbind" - echo " on your host by doing the following as root:" - echo "===============================================" - echo " According to /etc/sysconfig/rpcbind, then " - echo " echo RPCBIND_ARGS=-i >> /etc/sysconfig/rpcbind" - echo " or" - echo " echo RPCBIND_OPTIONS=-i >> /etc/sysconfig/rpcbind" - echo " /etc/init.d/rpcbind restart" - echo "===============================================" - fi - exit 1 - fi - echo "Starting User Mode nfsd" - echo " $PSEUDO $PSEUDO_OPTS $OECORE_NATIVE_SYSROOT/usr/sbin/rpc.nfsd $NFSD_OPTS" - $PSEUDO $PSEUDO_OPTS $OECORE_NATIVE_SYSROOT/usr/sbin/rpc.nfsd $NFSD_OPTS - if [ ! $? = 0 ]; then - echo "Error starting nfsd" - exit 1 - fi - # Check to make sure everything started ok. - if [ ! -f $MOUNTPID ]; then - echo "rpc.mountd did not start correctly" - exit 1 - fi - if [ ! -f $NFSPID ]; then - echo "rpc.nfsd did not start correctly" - exit 1 - fi - ps -fp `cat $MOUNTPID` > /dev/null 2> /dev/null - if [ ! $? = 0 ]; then - echo "rpc.mountd did not start correctly" - exit 1 - fi - ps -fp `cat $NFSPID` > /dev/null 2> /dev/null - if [ ! $? = 0 ]; then - echo "rpc.nfsd did not start correctly" - exit 1 - fi - echo " " - echo "On your target please remember to add the following options for NFS" - echo "nfsroot=IP_ADDRESS:$NFS_EXPORT_DIR,nfsvers=2,mountprog=$NFS_MOUNTPROG,nfsprog=$NFS_NFSPROG,udp" - ;; - stop) - if [ -f "$MOUNTPID" ]; then - echo "Stopping rpc.mountd" - kill `cat $MOUNTPID` - rm -f $MOUNTPID - else - echo "No PID file, not stopping rpc.mountd" - fi - if [ -f "$NFSPID" ]; then - echo "Stopping rpc.nfsd" - kill `cat $NFSPID` - rm -f $NFSPID - else - echo "No PID file, not stopping rpc.nfsd" - fi - if [ -f "$EXPORTS" ]; then - echo "Removing exports file" - rm -f $EXPORTS - fi - ;; - restart) - $0 stop $NFS_EXPORT_DIR - $0 start $NFS_EXPORT_DIR - if [ ! $? = 0 ]; then - exit 1 - fi - ;; - *) - echo "$0 {start|stop|restart} " - ;; -esac - -exit 0 diff --git a/scripts/poky-extract-sdk b/scripts/poky-extract-sdk deleted file mode 100755 index ee2682e74a..0000000000 --- a/scripts/poky-extract-sdk +++ /dev/null @@ -1,100 +0,0 @@ -#!/bin/bash -# -# This utility extracts an SDK image tarball using pseudo, and stores -# the pseudo database in var/pseudo within the rootfs. If you want to -# boot QEMU using an nfsroot, you *must* use this script to create the -# rootfs to ensure it is done correctly with pseudo. -# -# Copyright (c) 2010 Intel Corp. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# 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 - -function usage() { - echo "Usage: $0 " -} - -if [ $# -ne 2 ]; then - usage - exit 1 -fi - -SYSROOT_SETUP_SCRIPT=`which poky-find-native-sysroot` -if [ -z "$SYSROOT_SETUP_SCRIPT" ]; then - echo "Error: Unable to find the poky-find-native-sysroot script" - echo "Did you forget to source your Poky environment script?" - exit 1 -fi -. $SYSROOT_SETUP_SCRIPT -PSEUDO_OPTS="-P $OECORE_NATIVE_SYSROOT/usr" - -ROOTFS_TARBALL=$1 -SDK_ROOTFS_DIR=$2 - -if [ ! -e "$ROOTFS_TARBALL" ]; then - echo "Error: sdk tarball '$ROOTFS_TARBALL' does not exist" - usage - exit 1 -fi - -# Convert SDK_ROOTFS_DIR to a full pathname -if [[ ${SDK_ROOTFS_DIR:0:1} != "/" ]]; then - SDK_ROOTFS_DIR=$(pwd)/$SDK_ROOTFS_DIR -fi - -TAR_OPTS="" -if [[ "$ROOTFS_TARBALL" =~ tar\.bz2$ ]]; then - TAR_OPTS="-xjf" -fi -if [[ "$ROOTFS_TARBALL" =~ tar\.gz$ ]]; then - TAR_OPTS="-xzf" -fi -if [[ "$ROOTFS_TARBALL" =~ \.tar$ ]]; then - TAR_OPTS="-xf" -fi -if [ -z "$TAR_OPTS" ]; then - echo "Error: Unable to determine sdk tarball format" - echo "Accepted types: .tar / .tar.gz / .tar.bz2" - exit 1 -fi - -if [ ! -d "$SDK_ROOTFS_DIR" ]; then - echo "Creating directory $SDK_ROOTFS_DIR" - mkdir -p "$SDK_ROOTFS_DIR" -fi - -if [ -e "$SDK_ROOTFS_DIR/var/pseudo" ]; then - echo "Error: $SDK_ROOTFS_DIR/var/pseudo already exists!" - echo "Please delete the entire rootfs tree manually if this is really what you want" - exit 1 -fi - -mkdir -p "$SDK_ROOTFS_DIR/var/pseudo" -touch "$SDK_ROOTFS_DIR/var/pseudo/pseudo.pid" -PSEUDO_LOCALSTATEDIR="$SDK_ROOTFS_DIR/var/pseudo" -export PSEUDO_LOCALSTATEDIR - -echo "Extracting rootfs tarball using pseudo..." -echo "$PSEUDO $PSEUDO_OPTS tar -C \"$SDK_ROOTFS_DIR\" $TAR_OPTS \"$ROOTFS_TARBALL\"" -$PSEUDO $PSEUDO_OPTS tar -C "$SDK_ROOTFS_DIR" $TAR_OPTS "$ROOTFS_TARBALL" - -DIRCHECK=`ls -l "$SDK_ROOTFS_DIR" | wc -l` -if [ "$DIRCHECK" -lt 5 ]; then - echo "Warning: I don't see many files in $SDK_ROOTFS_DIR" - echo "Please double-check the extraction worked as intended" - exit 0 -fi - -echo "SDK image successfully extracted to $SDK_ROOTFS_DIR" - -exit 0 diff --git a/scripts/poky-find-native-sysroot b/scripts/poky-find-native-sysroot deleted file mode 100755 index d44fd9536e..0000000000 --- a/scripts/poky-find-native-sysroot +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/bash -# -# Find a native sysroot to use - either from an in-tree Poky build or -# from a toolchain installation. It then ensures the variable -# $OECORE_NATIVE_SYSROOT is set to the sysroot's base directory, and sets -# $PSEUDO to the path of the pseudo binary. -# -# This script is intended to be run within other scripts by source'ing -# it, e.g: -# -# SYSROOT_SETUP_SCRIPT=`which poky-find-native-sysroot` -# . $SYSROOT_SETUP_SCRIPT -# -# This script will terminate execution of your calling program unless -# you set a variable $SKIP_STRICT_SYSROOT_CHECK to a non-empty string -# beforehand. -# -# Copyright (c) 2010 Intel Corp. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# 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., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -if [ -z "$OECORE_NATIVE_SYSROOT" ]; then - BITBAKE=`which bitbake` - if [ "x$BITBAKE" != "x" ]; then - if [ "$UID" = "0" ]; then - # Root cannot run bitbake unless sanity checking is disabled - if [ ! -d "./conf" ]; then - echo "Error: root cannot run bitbake by default, and I cannot find a ./conf directory to be able to disable sanity checking" - exit 1 - fi - touch conf/sanity.conf - OECORE_NATIVE_SYSROOT=`bitbake -e | grep ^STAGING_DIR_NATIVE | cut -d '=' -f2 | cut -d '"' -f2` - rm -f conf/sanity.conf - else - OECORE_NATIVE_SYSROOT=`bitbake -e | grep ^STAGING_DIR_NATIVE | cut -d '=' -f2 | cut -d '"' -f2` - fi - else - echo "Error: Unable to locate your native sysroot." - echo "Did you forget to source the Poky environment script?" - - if [ -z "$SKIP_STRICT_SYSROOT_CHECK" ]; then - exit 1 - fi - fi -fi - -# Set up pseudo command -if [ ! -e "$OECORE_NATIVE_SYSROOT/usr/bin/pseudo" ]; then - echo "Error: Unable to find pseudo binary in $OECORE_NATIVE_SYSROOT/usr/bin/" - - if [ "x$POKY_DISTRO_VERSION" = "x" ]; then - echo "Have you run 'bitbake meta-ide-support'?" - else - echo "This shouldn't happen - something is wrong with your toolchain installation" - fi - - if [ -z "$SKIP_STRICT_SYSROOT_CHECK" ]; then - exit 1 - fi -fi -PSEUDO="$OECORE_NATIVE_SYSROOT/usr/bin/pseudo" diff --git a/scripts/poky-gen-tapdevs b/scripts/poky-gen-tapdevs deleted file mode 100755 index 527c01e7b4..0000000000 --- a/scripts/poky-gen-tapdevs +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/bash -# -# Create a "bank" of tap network devices that can be used by the -# runqemu script. This script needs to be run as root, and will -# use the tunctl binary from a Poky sysroot. Note: many Linux distros -# these days still use an older version of tunctl which does not -# support the group permissions option, hence the need to use Poky's -# version. -# -# Copyright (C) 2010 Intel Corp. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# 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., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -usage() { - echo "Usage: sudo $0 " - echo "Where is the numeric group id the tap devices will be owned by" - echo " is the number of tap devices to create (0 to remove all)" - echo " is the path to Poky's native sysroot" - exit 1 -} - -if [ $EUID -ne 0 ]; then - echo "Error: This script must be run with root privileges" - exit -fi - -if [ $# -ne 3 ]; then - echo "Error: Incorrect number of arguments" - usage -fi - -GID=$1 -COUNT=$2 -SYSROOT=$3 - -TUNCTL=$SYSROOT/usr/bin/tunctl -if [[ ! -x "$TUNCTL" || -d "$TUNCTL" ]]; then - echo "Error: $TUNCTL is not an executable" - usage -fi - -SCRIPT_DIR=`dirname $0` -POKY_QEMU_IFUP="$SCRIPT_DIR/runqemu-ifup" -if [ ! -x "$POKY_QEMU_IFUP" ]; then - echo "Error: Unable to find the runqemu-ifup script in $SCRIPT_DIR" - exit 1 -fi - -IFCONFIG=`which ifconfig` -if [ -z "$IFCONFIG" ]; then - # Is it ever anywhere else? - IFCONFIG=/sbin/ifconfig -fi - -# Ensure we start with a clean slate -for tap in `$IFCONFIG | grep ^tap | awk '{ print \$1 }'`; do - echo "Note: Destroying pre-existing tap interface $tap..." - $TUNCTL -d $tap -done - -echo "Creating $COUNT tap devices for GID $GID..." -for ((index=0; index < $COUNT; index++)); do - echo "Creating tap$index" - ifup=`$POKY_QEMU_IFUP $GID $SYSROOT 2>&1` - if [ $? -ne 0 ]; then - echo "Error running tunctl: $ifup" - exit 1 - fi -done - -# The runqemu script will check for this file, and if it exists, -# will use the existing bank of tap devices without creating -# additional ones via sudo. -touch /etc/poky-nosudo diff --git a/scripts/poky-git-proxy-command b/scripts/poky-git-proxy-command deleted file mode 100755 index d31f85abd8..0000000000 --- a/scripts/poky-git-proxy-command +++ /dev/null @@ -1,10 +0,0 @@ -#! /bin/bash - -(echo "CONNECT $1:$2 HTTP/1.0"; - echo; - cat ) | nc $GIT_PROXY_HOST $GIT_PROXY_PORT | - -(read a; - read a; - read a; - cat ) \ No newline at end of file diff --git a/scripts/poky-git-proxy-socks-command b/scripts/poky-git-proxy-socks-command deleted file mode 100755 index a5af2d33fa..0000000000 --- a/scripts/poky-git-proxy-socks-command +++ /dev/null @@ -1,2 +0,0 @@ -#! /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 deleted file mode 100644 index f5747117ab..0000000000 --- a/scripts/poky-git-proxy-socks.c +++ /dev/null @@ -1,2982 +0,0 @@ -/*********************************************************************** - * 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 - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef __CYGWIN32__ -#undef _WIN32 -#endif - -#ifdef _WIN32 -#include -#include -#include -#include -#include -#else /* !_WIN32 */ -#include -#include -#include -#include -#ifndef __hpux -#include -#endif /* __hpux */ -#include -#include -#include -#include -#if !defined(_WIN32) && !defined(__CYGWIN32__) -#define WITH_RESOLVER 1 -#include -#include -#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 ¶meter_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 || 32s_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 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 partial match. - Return true if exact or domain match. - Or continue checking. */ - if (tail1 == s1 || tail1[-1] == '.') - return 1; /* match! */ - return 0; /* not match */ -} - -/* Check given NAME is ends with one of - registered direct name entry. - Return 1 if matched, or 0. -*/ -int -is_direct_name (const char *name) -{ - int len, i; - const char *tail; - debug("checking %s is for direct?\n", name); - name = downcase(strdup(name)); - len = strlen(name); - if (len < 1) - return 0; /* false */ - tail = &name[len]; - for (i=0; is_port); - debug("service: %s => %d\n", service, port); - } - } - return (u_short)port; -} - -void -make_revstr(void) -{ - char *ptr; - size_t len; - ptr = strstr(rcs_revstr, ": "); - if (!ptr) { - revstr = strdup("unknown"); - return; - } - ptr += 2; - /* assume subversion's keyword expansion like "Revision: 96". */ - minor_version = atoi(ptr); - revstr = xmalloc(20); - snprintf(revstr, 20, "%d.%d", major_version, minor_version); -} - -int -getarg( int argc, char **argv ) -{ - int err = 0; - char *ptr, *server = (char*)NULL; - int method = METHOD_DIRECT; - - progname = *argv; - argc--, argv++; - - /* check optinos */ - while ( (0 < argc) && (**argv == '-') ) { - ptr = *argv + 1; - while ( *ptr ) { - switch ( *ptr ) { - case 's': /* use SOCKS */ - method = METHOD_SOCKS; - break; - - case 'n': /* no proxy */ - method = METHOD_DIRECT; - break; - - case 'h': /* use http-proxy */ - method = METHOD_HTTP; - break; - case 't': - method = METHOD_TELNET; - break; - - case 'S': /* specify SOCKS server */ - if ( 1 < argc ) { - argv++, argc--; - method = METHOD_SOCKS; - server = *argv; - } else { - error("option '-%c' needs argument.\n", *ptr); - err++; - } - break; - - case 'H': /* specify http-proxy server */ - if ( 1 < argc ) { - argv++, argc--; - method = METHOD_HTTP; - server = *argv; - } else { - error("option '-%c' needs argument.\n", *ptr); - err++; - } - break; - case 'T': /* specify telnet proxy server */ - if ( 1 < argc ) { - argv++, argc--; - method = METHOD_TELNET; - server = *argv; - } else { - error("option '-%c' needs argument.\n", *ptr); - err++; - } - break; - - case 'c': - if (1 < argc) { - argv++, argc--; - telnet_command = *argv; - } else { - error("option '%c' needs argument.\n", *ptr); - err++; - } - break; - - case 'P': - f_hold_session = 1; - /* without break */ - case 'p': /* specify port to forward */ - if ( 1 < argc ) { - argv++, argc--; - local_type = LOCAL_SOCKET; - local_port = resolve_port(*argv); - } else { - error("option '-%c' needs argument.\n", *ptr); - err++; - } - break; - -#ifndef _WIN32 - case 'w': - if ( 1 < argc ) { - argv++, argc--; - connect_timeout = atoi(*argv); - } else { - error("option '-%c' needs argument.\n", *ptr); - err++; - } - break; -#endif /* not _WIN32 */ - - case '4': - socks_version = 4; - break; - - case '5': - socks_version = 5; - break; - - case 'a': - if ( 1 < argc ) { - argv++, argc--; - socks5_auth = *argv; - } else { - error("option '-%c' needs argument.\n", *ptr); - err++; - } - break; - - case 'R': /* specify resolve method */ - if ( 1 < argc ) { - argv++, argc--; - socks_resolve = lookup_resolve( *argv ); - } else { - error("option '-%c' needs argument.\n", *ptr); - err++; - } - break; - - case 'V': /* print version */ - fprintf(stderr, "%s\nVersion %s\n", progdesc, revstr); - exit(0); - - case 'd': /* debug mode */ - f_debug++; - break; - - default: - error("unknown option '-%c'\n", *ptr); - err++; - } - ptr++; - } - argc--, argv++; - } - - /* check error */ - if ( 0 < err ) - goto quit; - - set_relay( method, server ); - - /* check destination HOST (MUST) */ - if ( argc == 0 ) { - fprintf(stderr, "%s\nVersion %s\n", progdesc, revstr); - fprintf(stderr, usage, progname); - exit(0); - } - dest_host = argv[0]; - /* decide port or service name from programname or argument */ - if ( ((ptr=strrchr( progname, '/' )) != NULL) || - ((ptr=strchr( progname, '\\')) != NULL) ) - ptr++; - else - ptr = progname; - if ( dest_port == 0 ) { - /* accept only if -P is not specified. */ - if ( 1 < argc ) { - /* get port number from argument (prior to progname) */ - /* NOTE: This way is for cvs ext method. */ - dest_port = resolve_port(argv[1]); - } else if ( strncmp( ptr, "connect-", 8) == 0 ) { - /* decide port number from program name */ - char *str = strdup( ptr+8 ); - str[strcspn( str, "." )] = '\0'; - dest_port = resolve_port(str); - free(str); - } - } - /* check port number */ - if ( dest_port <= 0 ) { - error( "You must specify the destination port correctly.\n"); - err++; - goto quit; - } - if ( (relay_method != METHOD_DIRECT) && (relay_port <= 0) ) { - error("Invalid relay port: %d\n", dest_port); - err++; - goto quit; - } - -quit: - /* report for debugging */ - debug("relay_method = %s (%d)\n", - method_names[relay_method], relay_method); - if ( relay_method != METHOD_DIRECT ) { - debug("relay_host=%s\n", relay_host); - debug("relay_port=%d\n", relay_port); - debug("relay_user=%s\n", relay_user); - } - if ( relay_method == METHOD_SOCKS ) { - debug("socks_version=%d\n", socks_version); - debug("socks_resolve=%s (%d)\n", - resolve_names[socks_resolve], socks_resolve); - } - debug("local_type=%s\n", local_type_names[local_type]); - if ( local_type == LOCAL_SOCKET ) { - debug("local_port=%d\n", local_port); - if (f_hold_session) - debug (" with holding remote session.\n"); - } - debug("dest_host=%s\n", dest_host); - debug("dest_port=%d\n", dest_port); - if ( 0 < err ) { - fprintf(stderr, usage, progname); - exit(1); - } - return 0; -} - -#ifndef _WIN32 -/* Time-out feature is not allowed for Win32 native compilers. */ -/* MSVC and Borland C cannot but Cygwin and UNIXes can. */ - -/* timeout signal hander */ -void -sig_timeout(void) -{ - signal( SIGALRM, SIG_IGN ); - alarm( 0 ); - error( "timed out\n" ); - exit(1); -} - -/* set timeout param = seconds, 0 clears */ -void -set_timeout(int timeout) -{ - /* This feature is allowed for UNIX or cygwin environments, currently */ - if ( timeout == 0 ) { - debug( "clearing timeout\n" ); - signal( SIGALRM, SIG_IGN ); - alarm( 0 ); - } else { - debug( "setting timeout: %d seconds\n", timeout ); - signal(SIGALRM, (void *)sig_timeout); - alarm( timeout ); - } -} -#endif - -#if !defined(_WIN32) && !defined(__CYGWIN32__) -void -switch_ns (struct sockaddr_in *ns) -{ - res_init(); - memcpy (&_res.nsaddr_list[0], ns, sizeof(*ns)); - _res.nscount = 1; - debug("Using nameserver at %s\n", inet_ntoa(ns->sin_addr)); -} -#endif /* !_WIN32 && !__CYGWIN32__ */ - -/* TODO: IPv6 - TODO: fallback if askpass execution failed. - */ - -int -local_resolve (const char *host, struct sockaddr_in *addr) -{ - struct hostent *ent; - if ( strspn(host, dotdigits) == strlen(host) ) { - /* given by IPv4 address */ - addr->sin_family = AF_INET; - addr->sin_addr.s_addr = inet_addr(host); - } else { - debug("resolving host by name: %s\n", host); - ent = gethostbyname (host); - if ( ent ) { - memcpy (&addr->sin_addr, ent->h_addr, ent->h_length); - addr->sin_family = ent->h_addrtype; - debug("resolved: %s (%s)\n", - host, inet_ntoa(addr->sin_addr)); - } else { - debug("failed to resolve locally.\n"); - return -1; /* failed */ - } - } - return 0; /* good */ -} - -int -open_connection( const char *host, u_short port ) -{ - SOCKET s; - struct sockaddr_in saddr; - - /* resolve address of proxy or direct target */ - if (local_resolve (host, &saddr) < 0) { - error("can't resolve hostname: %s\n", host); - return SOCKET_ERROR; - } - saddr.sin_port = htons(port); - - debug("connecting to %s:%u\n", inet_ntoa(saddr.sin_addr), port); - s = socket( AF_INET, SOCK_STREAM, 0 ); - if ( connect( s, (struct sockaddr *)&saddr, sizeof(saddr)) - == SOCKET_ERROR) { - debug( "connect() failed.\n"); - return SOCKET_ERROR; - } - return s; -} - -void -report_text( char *prefix, char *buf ) -{ - static char work[1024]; - char *tmp; - - if ( !f_debug ) - return; - if ( !f_report ) - return; /* don't report */ - debug("%s \"", prefix); - while ( *buf ) { - memset( work, 0, sizeof(work)); - tmp = work; - while ( *buf && ((tmp-work) < (int)sizeof(work)-5) ) { - switch ( *buf ) { - case '\t': *tmp++ = '\\'; *tmp++ = 't'; break; - case '\r': *tmp++ = '\\'; *tmp++ = 'r'; break; - case '\n': *tmp++ = '\\'; *tmp++ = 'n'; break; - case '\\': *tmp++ = '\\'; *tmp++ = '\\'; break; - default: - if ( isprint(*buf) ) { - *tmp++ = *buf; - } else { - int consumed = tmp - work; - snprintf( tmp, sizeof(work)-consumed, - "\\x%02X", (unsigned char)*buf); - tmp += strlen(tmp); - } - } - buf++; - *tmp = '\0'; - } - debug_("%s", work); - } - - debug_("\"\n"); -} - - -void -report_bytes( char *prefix, char *buf, int len ) -{ - if ( ! f_debug ) - return; - debug( "%s", prefix ); - while ( 0 < len ) { - fprintf( stderr, " %02x", *(unsigned char *)buf); - buf++; - len--; - } - fprintf(stderr, "\n"); - return; -} - -int -atomic_out( SOCKET s, char *buf, int size ) -{ - int ret, len; - - assert( buf != NULL ); - assert( 0<=size ); - /* do atomic out */ - ret = 0; - while ( 0 < size ) { - len = send( s, buf+ret, size, 0 ); - if ( len == -1 ) - fatal("atomic_out() failed to send(), %d\n", socket_errno()); - ret += len; - size -= len; - } - if (!f_report) { - debug("atomic_out() [some bytes]\n"); - debug(">>> xx xx xx xx ...\n"); - } else { - debug("atomic_out() [%d bytes]\n", ret); - report_bytes(">>>", buf, ret); - } - return ret; -} - -int -atomic_in( SOCKET s, char *buf, int size ) -{ - int ret, len; - - assert( buf != NULL ); - assert( 0<=size ); - - /* do atomic in */ - ret = 0; - while ( 0 < size ) { - len = recv( s, buf+ret, size, 0 ); - if ( len == -1 ) { - fatal("atomic_in() failed to recv(), %d\n", socket_errno()); - } else if ( len == 0 ) { - fatal( "Connection closed by peer.\n"); - } - ret += len; - size -= len; - } - if (!f_report) { - debug("atomic_in() [some bytes]\n"); - debug("<<< xx xx xx xx ...\n"); - } else { - debug("atomic_in() [%d bytes]\n", ret); - report_bytes("<<<", buf, ret); - } - return ret; -} - -int -line_input( SOCKET s, char *buf, int size ) -{ - char *dst = buf; - if ( size == 0 ) - return 0; /* no error */ - size--; - while ( 0 < size ) { - switch ( recv( s, dst, 1, 0) ) { /* recv one-by-one */ - case SOCKET_ERROR: - error("recv() error\n"); - return -1; /* error */ - case 0: - size = 0; /* end of stream */ - break; - default: - /* continue reading until last 1 char is EOL? */ - if ( *dst == '\n' ) { - /* finished */ - size = 0; - } else { - /* more... */ - size--; - } - dst++; - } - } - *dst = '\0'; - report_text( "<<<", buf); - return 0; -} - -/* cut_token() - Span token in given string STR until char in DELIM is appeared. - Then replace contiguous DELIMS with '\0' for string termination - and returns next pointer. - If no next token, return NULL. -*/ -char * -cut_token( char *str, char *delim) -{ - char *ptr = str + strcspn(str, delim); - char *end = ptr + strspn(ptr, delim); - if ( ptr == str ) - return NULL; - while ( ptr < end ) - *ptr++ = '\0'; - return ptr; -} - -const char * -lookup(int num, LOOKUP_ITEM *items) -{ - int i = 0; - while (0 <= items[i].num) { - if (items[i].num == num) - return items[i].str; - i++; - } - return "(unknown)"; -} - -/* readpass() - password input routine - Use ssh-askpass (same mechanism to OpenSSH) -*/ -char * -readpass( const char* prompt, ...) -{ - static char buf[1000]; /* XXX, don't be fix length */ - va_list args; - va_start(args, prompt); - vsnprintf(buf, sizeof(buf), prompt, args); - va_end(args); - - if ( getparam(ENV_SSH_ASKPASS) -#if !defined(_WIN32) && !defined(__CYGWIN32__) - && getenv("DISPLAY") -#endif /* not _WIN32 && not __CYGWIN32__ */ - ) { - /* use ssh-askpass to get password */ - FILE *fp; - char *askpass = getparam(ENV_SSH_ASKPASS), *cmd; - int cmd_size = strlen(askpass) +1 +1 +strlen(buf) +1 +1; - cmd = xmalloc(cmd_size); - snprintf(cmd, cmd_size, "%s \"%s\"", askpass, buf); - fp = popen(cmd, "r"); - free(cmd); - if ( fp == NULL ) - return NULL; /* fail */ - buf[0] = '\0'; - if (fgets(buf, sizeof(buf), fp) == NULL) - return NULL; /* fail */ - fclose(fp); - } else { - tty_readpass( buf, buf, sizeof(buf)); - } - buf[strcspn(buf, "\r\n")] = '\0'; - return buf; -} - -static int -socks5_do_auth_userpass( int s ) -{ - unsigned char buf[1024], *ptr; - char *pass = NULL; - int len; - - /* do User/Password authentication. */ - /* This feature requires username and password from - command line argument or environment variable, - or terminal. */ - if (relay_user == NULL) - fatal("cannot determine user name.\n"); - - /* get password from environment variable if exists. */ - if ((pass=determine_relay_password()) == NULL && - (pass=readpass("Enter SOCKS5 password for %s@%s: ", - relay_user, relay_host)) == NULL) - fatal("Cannot get password for user: %s\n", relay_user); - - /* make authentication packet */ - ptr = buf; - PUT_BYTE( ptr++, 1 ); /* subnegotiation ver.: 1 */ - len = strlen( relay_user ); /* ULEN and UNAME */ - PUT_BYTE( ptr++, len ); - strcpy( ptr, relay_user ); - ptr += len; - len = strlen( pass ); /* PLEN and PASSWD */ - PUT_BYTE( ptr++, strlen(pass)); - strcpy( ptr, pass ); - ptr += len; - memset (pass, 0, strlen(pass)); /* erase password */ - - /* send it and get answer */ - f_report = 0; - atomic_out( s, buf, ptr-buf ); - f_report = 1; - atomic_in( s, buf, 2 ); - - /* check status */ - if ( buf[1] == 0 ) - return 0; /* success */ - else - return -1; /* fail */ -} - -static const char * -socks5_getauthname( int auth ) -{ - switch ( auth ) { - case SOCKS5_AUTH_REJECT: return "REJECTED"; - case SOCKS5_AUTH_NOAUTH: return "NO-AUTH"; - case SOCKS5_AUTH_GSSAPI: return "GSSAPI"; - case SOCKS5_AUTH_USERPASS: return "USERPASS"; - case SOCKS5_AUTH_CHAP: return "CHAP"; - case SOCKS5_AUTH_EAP: return "EAP"; - case SOCKS5_AUTH_MAF: return "MAF"; - default: return "(unknown)"; - } -} - -typedef struct { - char* name; - unsigned char auth; -} AUTH_METHOD_ITEM; - -AUTH_METHOD_ITEM socks5_auth_table[] = { - { "none", SOCKS5_AUTH_NOAUTH }, - { "gssapi", SOCKS5_AUTH_GSSAPI }, - { "userpass", SOCKS5_AUTH_USERPASS }, - { "chap", SOCKS5_AUTH_CHAP }, - { NULL, -1 }, -}; - -int -socks5_auth_parse_1(char *start, char *end){ - int i, len; - for ( ; *start; start++ ) - if ( *start != ' ' && *start != '\t') break; - for ( end--; end >= start; end-- ) { - if ( *end != ' ' && *end != '\t'){ - end++; - break; - } - } - len = end - start; - for ( i = 0; socks5_auth_table[i].name != NULL; i++ ){ - if ( strncmp(start, socks5_auth_table[i].name, len) == 0) { - return socks5_auth_table[i].auth; - } - } - fatal("Unknown auth method: %s\n", start); - return -1; -} - -int -socks5_auth_parse(char *start, unsigned char *auth_list, int max_auth){ - char *end; - int i = 0; - while ( i < max_auth ) { - end = strchr(start, ','); - if (*start && end) { - auth_list[i++] = socks5_auth_parse_1(start, end); - start = ++end; - } else { - break; - } - } - if ( *start && ( i < max_auth ) ){ - for( end = start; *end; end++ ); - auth_list[i++] = socks5_auth_parse_1(start, end); - } else { - fatal("Too much auth method.\n"); - } - return i; -} - -/* begin SOCKS5 relaying - And no authentication is supported. - */ -int -begin_socks5_relay( SOCKET s ) -{ - unsigned char buf[256], *ptr, *env = socks5_auth; - unsigned char n_auth = 0; unsigned char auth_list[10], auth_method; - int len, auth_result, i; - - debug( "begin_socks_relay()\n"); - - /* request authentication */ - ptr = buf; - PUT_BYTE( ptr++, 5); /* SOCKS version (5) */ - - if ( env == NULL ) - env = getparam(ENV_SOCKS5_AUTH); - if ( env == NULL ) { - /* add no-auth authentication */ - auth_list[n_auth++] = SOCKS5_AUTH_NOAUTH; - /* add user/pass authentication */ - auth_list[n_auth++] = SOCKS5_AUTH_USERPASS; - } else { - n_auth = socks5_auth_parse(env, auth_list, 10); - } - PUT_BYTE( ptr++, n_auth); /* num auth */ - for (i=0; i>8); /* DST.PORT */ - PUT_BYTE( ptr++, dest_port&0xFF); - atomic_out( s, buf, ptr-buf); /* send request */ - atomic_in( s, buf, 4 ); /* recv response */ - if ( (buf[1] != SOCKS5_REP_SUCCEEDED) ) { /* check reply code */ - error("Got error response from SOCKS server: %d (%s).\n", - buf[1], lookup(buf[1], socks5_rep_names)); - return -1; - } - ptr = buf + 4; - switch ( buf[3] ) { /* case by ATYP */ - case 1: /* IP v4 ADDR*/ - atomic_in( s, ptr, 4+2 ); /* recv IPv4 addr and port */ - break; - case 3: /* DOMAINNAME */ - atomic_in( s, ptr, 1 ); /* recv name and port */ - atomic_in( s, ptr+1, *(unsigned char*)ptr + 2); - break; - case 4: /* IP v6 ADDR */ - atomic_in( s, ptr, 16+2 ); /* recv IPv6 addr and port */ - break; - } - - /* Conguraturation, connected via SOCKS5 server! */ - return 0; -} - -/* begin SOCKS protocol 4 relaying - And no authentication is supported. - - There's SOCKS protocol version 4 and 4a. Protocol version - 4a has capability to resolve hostname by SOCKS server, so - we don't need resolving IP address of destination host on - local machine. - - Environment variable SOCKS_RESOLVE directs how to resolve - IP addess. There's 3 keywords allowed; "local", "remote" - and "both" (case insensitive). Keyword "local" means taht - target host name is resolved by localhost resolver - (usualy with gethostbyname()), "remote" means by remote - SOCKS server, "both" means to try resolving by localhost - then remote. - - SOCKS4 protocol and authentication of SOCKS5 protocol - requires user name on connect request. - User name is determined by following method. - - 1. If server spec has user@hostname:port format then - user part is used for this SOCKS server. - - 2. Get user name from environment variable LOGNAME, USER - (in this order). - -*/ -int -begin_socks4_relay( SOCKET s ) -{ - unsigned char buf[256], *ptr; - - debug( "begin_socks_relay()\n"); - - /* make connect request packet - protocol v4: - VN:1, CD:1, PORT:2, ADDR:4, USER:n, NULL:1 - protocol v4a: - VN:1, CD:1, PORT:2, DUMMY:4, USER:n, NULL:1, HOSTNAME:n, NULL:1 - */ - ptr = buf; - PUT_BYTE( ptr++, 4); /* protocol version (4) */ - PUT_BYTE( ptr++, 1); /* CONNECT command */ - PUT_BYTE( ptr++, dest_port>>8); /* destination Port */ - PUT_BYTE( ptr++, dest_port&0xFF); - /* destination IP */ - memcpy(ptr, &dest_addr.sin_addr, sizeof(dest_addr.sin_addr)); - ptr += sizeof(dest_addr.sin_addr); - if ( dest_addr.sin_addr.s_addr == 0 ) - *(ptr-1) = 1; /* fake, protocol 4a */ - /* username */ - if (relay_user == NULL) - fatal( "Cannot determine user name.\n"); - strcpy( ptr, relay_user ); - ptr += strlen( relay_user ) +1; - /* destination host name (for protocol 4a) */ - if ( (socks_version == 4) && (dest_addr.sin_addr.s_addr == 0)) { - strcpy( ptr, dest_host ); - ptr += strlen( dest_host ) +1; - } - /* send command and get response - response is: VN:1, CD:1, PORT:2, ADDR:4 */ - atomic_out( s, buf, ptr-buf); /* send request */ - atomic_in( s, buf, 8 ); /* recv response */ - if ( (buf[1] != SOCKS4_REP_SUCCEEDED) ) { /* check reply code */ - error("Got error response: %d: '%s'.\n", - buf[1], lookup(buf[1], socks4_rep_names)); - return -1; /* failed */ - } - - /* Conguraturation, connected via SOCKS4 server! */ - return 0; -} - -int -sendf(SOCKET s, const char *fmt,...) -{ - static char buf[10240]; /* xxx, enough? */ - - va_list args; - va_start( args, fmt ); - vsnprintf( buf, sizeof(buf), fmt, args ); - va_end( args ); - - report_text(">>>", buf); - if ( send(s, buf, strlen(buf), 0) == SOCKET_ERROR ) { - debug("failed to send http request. errno=%d\n", socket_errno()); - return -1; - } - return 0; -} - -const char *base64_table = -"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -char * -make_base64_string(const char *str) -{ - static char *buf; - unsigned char *src; - char *dst; - int bits, data, src_len, dst_len; - /* make base64 string */ - src_len = strlen(str); - dst_len = (src_len+2)/3*4; - buf = xmalloc(dst_len+1); - bits = data = 0; - src = (unsigned char *)str; - dst = (unsigned char *)buf; - while ( dst_len-- ) { - if ( bits < 6 ) { - data = (data << 8) | *src; - bits += 8; - if ( *src != 0 ) - src++; - } - *dst++ = base64_table[0x3F & (data >> (bits-6))]; - bits -= 6; - } - *dst = '\0'; - /* fix-up tail padding */ - switch ( src_len%3 ) { - case 1: - *--dst = '='; - case 2: - *--dst = '='; - } - return buf; -} - - -int -basic_auth (SOCKET s) -{ - char *userpass; - char *cred; - const char *user = relay_user; - char *pass = NULL; - int len, ret; - - /* Get username/password for authentication */ - if (user == NULL) - fatal("Cannot decide username for proxy authentication."); - if ((pass = determine_relay_password ()) == NULL && - (pass = readpass("Enter proxy authentication password for %s@%s: ", - relay_user, relay_host)) == NULL) - fatal("Cannot decide password for proxy authentication."); - - len = strlen(user)+strlen(pass)+1; - userpass = xmalloc(len+1); - snprintf(userpass, len+1, "%s:%s", user, pass); - memset (pass, 0, strlen(pass)); - cred = make_base64_string(userpass); - memset (userpass, 0, len); - - f_report = 0; /* don't report for security */ - ret = sendf(s, "Proxy-Authorization: Basic %s\r\n", cred); - f_report = 1; - report_text(">>>", "Proxy-Authorization: Basic xxxxx\r\n"); - - memset(cred, 0, strlen(cred)); - free(cred); - - return ret; -} - -/* begin relaying via HTTP proxy - Directs CONNECT method to proxy server to connect to - destination host (and port). It may not be allowed on your - proxy server. - */ -int -begin_http_relay( SOCKET s ) -{ - char buf[1024]; - int result; - char *auth_what; - - debug("begin_http_relay()\n"); - - if (sendf(s,"CONNECT %s:%d HTTP/1.0\r\n", dest_host, dest_port) < 0) - return START_ERROR; - if (proxy_auth_type == PROXY_AUTH_BASIC && basic_auth (s) < 0) - return START_ERROR; - if (sendf(s,"\r\n") < 0) - return START_ERROR; - - /* get response */ - if ( line_input(s, buf, sizeof(buf)) < 0 ) { - debug("failed to read http response.\n"); - return START_ERROR; - } - - /* check status */ - if (!strchr(buf, ' ')) { - error ("Unexpected http response: '%s'.\n", buf); - return START_ERROR; - } - result = atoi(strchr(buf,' ')); - - switch ( result ) { - case 200: - /* Conguraturation, connected via http proxy server! */ - debug("connected, start user session.\n"); - break; - case 302: /* redirect */ - do { - if (line_input(s, buf, sizeof(buf))) - break; - downcase(buf); - if (expect(buf, "Location: ")) { - relay_host = cut_token(buf, "//"); - cut_token(buf, "/"); - relay_port = atoi(cut_token(buf, ":")); - } - } while (strcmp(buf,"\r\n") != 0); - return START_RETRY; - - /* We handle both 401 and 407 codes here: 401 is WWW-Authenticate, which - * not strictly the correct response, but some proxies do send this (e.g. - * Symantec's Raptor firewall) */ - case 401: /* WWW-Auth required */ - case 407: /* Proxy-Auth required */ - /** NOTE: As easy implementation, we support only BASIC scheme - and ignore realm. */ - /* If proxy_auth_type is PROXY_AUTH_BASIC and get - this result code, authentication was failed. */ - if (proxy_auth_type != PROXY_AUTH_NONE) { - error("Authentication failed.\n"); - return START_ERROR; - } - auth_what = (result == 401) ? "WWW-Authenticate:" : "Proxy-Authenticate:"; - do { - if ( line_input(s, buf, sizeof(buf)) ) { - break; - } - downcase(buf); - if (expect(buf, auth_what)) { - /* parse type and realm */ - char *scheme, *realm; - scheme = cut_token(buf, " "); - realm = cut_token(scheme, " "); - if ( scheme == NULL || realm == NULL ) { - debug("Invalid format of %s field.", auth_what); - return START_ERROR; /* fail */ - } - /* check supported auth type */ - if (expect(scheme, "basic")) { - proxy_auth_type = PROXY_AUTH_BASIC; - } else { - debug("Unsupported authentication type: %s", scheme); - } - } - } while (strcmp(buf,"\r\n") != 0); - if ( proxy_auth_type == PROXY_AUTH_NONE ) { - debug("Can't find %s in response header.", auth_what); - return START_ERROR; - } else { - return START_RETRY; - } - - default: - /* Not allowed */ - debug("http proxy is not allowed.\n"); - return START_ERROR; - } - /* skip to end of response header */ - do { - if ( line_input(s, buf, sizeof(buf) ) ) { - debug("Can't skip response headers\n"); - return START_ERROR; - } - } while ( strcmp(buf,"\r\n") != 0 ); - - return START_OK; -} - -/* begin relaying via TELNET proxy. - Sends string specified by telnet_command (-c option) with - replacing host name and port number to the socket. */ -int -begin_telnet_relay( SOCKET s ) -{ - char buf[1024]; - char *cmd; - char *good_phrase = "connected to"; - char *bad_phrase_list[] = { - " failed", " refused", " rejected", " closed" - }; - char sep = ' '; - int i; - - debug("begin_telnet_relay()\n"); - - /* report phrase */ - debug("good phrase: '%s'\n", good_phrase); - debug("bad phrases"); - sep = ':'; - for (i=0; i< (sizeof(bad_phrase_list) / sizeof(char*)); i++) { - debug_("%c '%s'", sep, bad_phrase_list[i]); - sep = ','; - } - debug_("\n"); - - /* make request string with replacing %h by destination hostname - and %p by port number, etc. */ - cmd = expand_host_and_port(telnet_command, dest_host, dest_port); - - /* Sorry, we send request string now without waiting a prompt. */ - if (sendf(s, "%s\r\n", cmd) < 0) { - free(cmd); - return START_ERROR; - } - free(cmd); - - /* Process answer from proxy until good or bad phrase is detected. We - assume that the good phrase should be appeared only in the final - line of proxy responses. Bad keywods in the line causes operation - fail. First checks a good phrase, then checks bad phrases. - If no match, continue reading line from proxy. */ - while (!line_input(s, buf, sizeof(buf)) && buf[0] != '\0') { - downcase(buf); - /* first, check good phrase */ - if (strstr(buf, good_phrase)) { - debug("good phrase is detected: '%s'\n", good_phrase); - return START_OK; - } - /* then, check bad phrase */ - for (i=0; i<(sizeof(bad_phrase_list)/sizeof(char*)); i++) { - if (strstr(buf, bad_phrase_list[i]) != NULL) { - debug("bad phrase is detected: '%s'\n", bad_phrase_list[i]); - return START_ERROR; - } - } - } - debug("error reading from telnet proxy\n"); - - return START_ERROR; -} - - -#ifdef _WIN32 -/* ddatalen() - Returns 1 if data is available, otherwise return 0 - */ -int -stdindatalen (void) -{ - DWORD len = 0; - struct stat st; - fstat( 0, &st ); - if ( st.st_mode & _S_IFIFO ) { - /* in case of PIPE */ - if ( !PeekNamedPipe( GetStdHandle(STD_INPUT_HANDLE), - NULL, 0, NULL, &len, NULL) ) { - if ( GetLastError() == ERROR_BROKEN_PIPE ) { - /* PIPE source is closed */ - /* read() will detects EOF */ - len = 1; - } else { - fatal("PeekNamedPipe() failed, errno=%d\n", - GetLastError()); - } - } - } else if ( st.st_mode & _S_IFREG ) { - /* in case of regular file (redirected) */ - len = 1; /* always data ready */ - } else if ( _kbhit() ) { - /* in case of console */ - len = 1; - } - return len; -} -#endif /* _WIN32 */ - -/* relay byte from stdin to socket and fro socket to stdout. - returns reason of termination */ -int -do_repeater( SOCKET local_in, SOCKET local_out, SOCKET remote ) -{ - /** vars for local input data **/ - char lbuf[1024]; /* local input buffer */ - int lbuf_len; /* available data in lbuf */ - int f_local; /* read local input more? */ - /** vars for remote input data **/ - char rbuf[1024]; /* remote input buffer */ - int rbuf_len; /* available data in rbuf */ - int f_remote; /* read remote input more? */ - int close_reason = REASON_UNK; /* reason of end repeating */ - /** other variables **/ - int nfds, len; - fd_set ifds, ofds; - struct timeval *tmo; -#ifdef _WIN32 - struct timeval win32_tmo; -#endif /* _WIN32 */ - - /* repeater between stdin/out and socket */ - nfds = ((local_in local */ - if ( FD_ISSET(remote, &ifds) && (rbuf_len < (int)sizeof(rbuf)) ) { - len = recv( remote, rbuf + rbuf_len, sizeof(rbuf)-rbuf_len, 0); - if ( len == 0 || (len == -1 && socket_errno() == ECONNRESET)) { - debug("connection %s by peer\n", - (len==0)? "closed": "reset"); - close_reason = REASON_CLOSED_BY_REMOTE; - f_remote = 0; /* no more read from socket */ - f_local = 0; - } else if ( len == -1 ) { - /* error */ - fatal("recv() failed, %d\n", socket_errno()); - } else { - debug("recv %d bytes\n", len); - if ( 1 < f_debug ) /* more verbose */ - report_bytes( "<<<", rbuf+rbuf_len, len); - rbuf_len += len; - } - } - - /* local => remote */ - if ( FD_ISSET(local_in, &ifds) && (lbuf_len < (int)sizeof(lbuf)) ) { - if (local_type == LOCAL_SOCKET) - len = recv(local_in, lbuf + lbuf_len, - sizeof(lbuf)-lbuf_len, 0); - else - len = read(local_in, lbuf + lbuf_len, sizeof(lbuf)-lbuf_len); - if ( len == 0 ) { - /* stdin is EOF */ - debug("local input is EOF\n"); - if (!f_hold_session) - shutdown(remote, 1); /* no-more writing */ - f_local = 0; - close_reason = REASON_CLOSED_BY_LOCAL; - } else if ( len == -1 ) { - /* error on reading from stdin */ - if (f_hold_session) { - debug ("failed to read from local\n"); - f_local = 0; - close_reason = REASON_CLOSED_BY_LOCAL; - } else - fatal("recv() failed, errno = %d\n", errno); - } else { - /* repeat */ - lbuf_len += len; - } - } - - /* flush data in buffer to socket */ - if ( 0 < lbuf_len ) { - len = send(remote, lbuf, lbuf_len, 0); - if ( len == -1 ) { - fatal("send() failed, %d\n", socket_errno()); - } else if ( 0 < len ) { - if ( 1 < f_debug ) /* more verbose */ - report_bytes( ">>>", lbuf, len); - /* move data on to top of buffer */ - debug("sent %d bytes\n", len); - lbuf_len -= len; - if ( 0 < lbuf_len ) - memcpy( lbuf, lbuf+len, lbuf_len ); - assert( 0 <= lbuf_len ); - } - } - - /* flush data in buffer to local output */ - if ( 0 < rbuf_len ) { - if (local_type == LOCAL_SOCKET) - len = send( local_out, rbuf, rbuf_len, 0); - else - len = write( local_out, rbuf, rbuf_len); - if ( len == -1 ) { - fatal("output (local) failed, errno=%d\n", errno); - } - rbuf_len -= len; - if ( len < rbuf_len ) - memcpy( rbuf, rbuf+len, rbuf_len ); - assert( 0 <= rbuf_len ); - } - if (f_local == 0 && f_hold_session) { - debug ("closing local port without disconnecting from remote\n"); - f_remote = 0; - shutdown (local_out, 2); - close (local_out); - break; - } - } - - return close_reason; -} - -int -accept_connection (u_short port) -{ - static int sock = -1; - int connection; - struct sockaddr_in name; - struct sockaddr client; - int socklen; - fd_set ifds; - int nfds; - int sockopt; - - /* Create the socket. */ - debug("Creating source port to forward.\n"); - sock = socket (PF_INET, SOCK_STREAM, 0); - if (sock < 0) - fatal("socket() failed, errno=%d\n", socket_errno()); - sockopt = 1; - setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, - (void*)&sockopt, sizeof(sockopt)); - - /* Give the socket a name. */ - name.sin_family = AF_INET; - name.sin_port = htons (port); - name.sin_addr.s_addr = htonl (INADDR_ANY); - if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0) - fatal ("bind() failed, errno=%d\n", socket_errno()); - - if (listen( sock, 1) < 0) - fatal ("listen() failed, errno=%d\n", socket_errno()); - - /* wait for new connection with watching EOF of stdin. */ - debug ("waiting new connection at port %d (socket=%d)\n", port, sock); - nfds = sock + 1; - do { - int n; - struct timeval *ptmo = NULL; -#ifdef _WIN32 - struct timeval tmo; - tmo.tv_sec = 0; - tmo.tv_usec = 100*1000; /* On Windows, 100ms timeout */ - ptmo = &tmo; -#endif /* _WIN32 */ - FD_ZERO (&ifds); - FD_SET ((SOCKET)sock, &ifds); -#ifndef _WIN32 - FD_SET (0, &ifds); /* watch stdin */ -#endif - n = select (nfds, &ifds, NULL, NULL, ptmo); - if (n == -1) { - fatal ("select() failed, %d\n", socket_errno()); - exit (1); - } -#ifdef _WIN32 - if (0 < stdindatalen()) { - FD_SET (0, &ifds); /* fake */ - n++; - } -#endif - if (0 < n) { - if (FD_ISSET(0, &ifds) && (getchar() <= 0)) { - /* EOF */ - debug ("Give-up waiting port because stdin is closed."); - exit(0); - } - if (FD_ISSET(sock, &ifds)) - break; /* socket is stimulated */ - } - } while (1); - socklen = sizeof(client); - connection = accept( sock, &client, &socklen); - if ( connection < 0 ) - fatal ("accept() failed, errno=%d\n", socket_errno()); - return connection; -} - - - -/** Main of program **/ -int -main( int argc, char **argv ) -{ - int ret; - int remote; /* socket */ - int local_in; /* Local input */ - int local_out; /* Local output */ - int reason; -#ifdef _WIN32 - WSADATA wsadata; - WSAStartup( 0x101, &wsadata); -#endif /* _WIN32 */ - - /* initialization */ - make_revstr(); - getarg( argc, argv ); - debug("Program is $Revision: 100 $\n"); - - /* Open local_in and local_out if forwarding a port */ - if ( local_type == LOCAL_SOCKET ) { - /* Relay between local port and destination */ - local_in = local_out = accept_connection( local_port ); - } else { - /* Relay between stdin/stdout and desteination */ - local_in = 0; - local_out = 1; -#ifdef _WIN32 - _setmode(local_in, O_BINARY); - _setmode(local_out, O_BINARY); -#endif - } - -retry: -#ifndef _WIN32 - if (0 < connect_timeout) - set_timeout (connect_timeout); -#endif /* not _WIN32 */ - - if (check_direct(dest_host)) - relay_method = METHOD_DIRECT; - /* make connection */ - if ( relay_method == METHOD_DIRECT ) { - remote = open_connection (dest_host, dest_port); - if ( remote == SOCKET_ERROR ) - fatal( "Unable to connect to destination host, errno=%d\n", - socket_errno()); - } else { - remote = open_connection (relay_host, relay_port); - if ( remote == SOCKET_ERROR ) - fatal( "Unable to connect to relay host, errno=%d\n", - socket_errno()); - } - - /** resolve destination host (SOCKS) **/ -#if !defined(_WIN32) && !defined(__CYGWIN32__) - if (socks_ns.sin_addr.s_addr != 0) - switch_ns (&socks_ns); -#endif /* not _WIN32 && not __CYGWIN32__ */ - if (relay_method == METHOD_SOCKS && - socks_resolve == RESOLVE_LOCAL && - local_resolve (dest_host, &dest_addr) < 0) { - fatal("Unknown host: %s", dest_host); - } - - /** relay negociation **/ - switch ( relay_method ) { - case METHOD_SOCKS: - if ( ((socks_version == 5) && (begin_socks5_relay(remote) < 0)) || - ((socks_version == 4) && (begin_socks4_relay(remote) < 0)) ) - fatal( "failed to begin relaying via SOCKS.\n"); - break; - - case METHOD_HTTP: - ret = begin_http_relay(remote); - switch (ret) { - case START_ERROR: - close (remote); - fatal("failed to begin relaying via HTTP.\n"); - case START_OK: - break; - case START_RETRY: - /* retry with authentication */ - close (remote); - goto retry; - } - break; - case METHOD_TELNET: - if (begin_telnet_relay(remote) < 0) - fatal("failed to begin relaying via telnet.\n"); - break; - } - debug("connected\n"); - -#ifndef _WIN32 - if (0 < connect_timeout) - set_timeout (0); -#endif /* not _WIN32 */ - - /* main loop */ - debug ("start relaying.\n"); -do_repeater: - reason = do_repeater(local_in, local_out, remote); - debug ("relaying done.\n"); - if (local_type == LOCAL_SOCKET && - reason == REASON_CLOSED_BY_LOCAL && - f_hold_session) { - /* re-wait at local port without closing remote session */ - debug ("re-waiting at local port %d\n", local_port); - local_in = local_out = accept_connection( local_port ); - debug ("re-start relaying\n"); - goto do_repeater; - } - closesocket(remote); - if ( local_type == LOCAL_SOCKET) - closesocket(local_in); -#ifdef _WIN32 - WSACleanup(); -#endif /* _WIN32 */ - debug ("that's all, bye.\n"); - - return 0; -} - -/* ------------------------------------------------------------ - Local Variables: - compile-command: "cc connect.c -o connect" - tab-width: 8 - fill-column: 74 - comment-column: 48 - End: - ------------------------------------------------------------ */ - -/*** end of connect.c ***/ diff --git a/scripts/poky-setup-rpmrepo b/scripts/poky-setup-rpmrepo deleted file mode 100755 index 03372b6199..0000000000 --- a/scripts/poky-setup-rpmrepo +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/bash -# -# This utility setup the necessary metadata for an rpm repo -# -# Copyright (c) 2011 Intel Corp. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# 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 - -function usage() { - echo "Usage: $0 " - echo " : default is $TPMDIR/deploy/rpm" -} - -if [ $# -gt 1 ]; then - usage - exit 1 -fi - -setup_tmpdir() { - if [ -z "$TMPDIR" ]; then - if [ "x$BUILDDIR" = "x" -o ! -d "$BUILDDIR/tmp" ]; then - # BUILDDIR unset, try and get TMPDIR from bitbake - type -P bitbake &>/dev/null || { - echo "In order for this script to dynamically infer paths"; - echo "to kernels or filesystem images, you either need"; - echo "bitbake in your PATH or to source oe-init-build-env"; - echo "before running this script" >&2; - exit 1; } - - # We have bitbake in PATH, get TMPDIR from bitbake - TMPDIR=`bitbake -e | grep TMPDIR=\" | cut -d '=' -f2 | cut -d '"' -f2` - else - TMPDIR=$BUILDDIR/tmp - fi - fi -} - -setup_sysroot() { - # Toolchain installs set up $OECORE_NATIVE_SYSROOT in their - # environment script. If that variable isn't set, we're - # either in an in-tree poky scenario or the environment - # script wasn't source'd. - if [ -z "$OECORE_NATIVE_SYSROOT" ]; then - setup_tmpdir - BUILD_ARCH=`uname -m` - BUILD_OS=`uname | tr '[A-Z]' '[a-z]'` - BUILD_SYS="$BUILD_ARCH-$BUILD_OS" - - OECORE_NATIVE_SYSROOT=$TMPDIR/sysroots/$BUILD_SYS - fi -} - -setup_tmpdir -setup_sysroot - - -if [ -n "$1" ]; then - RPM_DIR="$1" -else - RPM_DIR="$TMPDIR/deploy/rpm" -fi - -if [ ! -d "$RPM_DIR" ]; then - echo "Error: rpm dir $RPM_DIR doesn't exist" - exit 1 -fi - -CREATEREPO=$OECORE_NATIVE_SYSROOT/usr/bin/createrepo -if [ ! -e "$CREATEREPO" ]; then - echo "Error: can't find createrepo binary" - echo "please run bitbake createrepo-native first" - exit 1 -fi - - -$CREATEREPO "$RPM_DIR" - -exit 0 diff --git a/scripts/poky-trim-schemas b/scripts/poky-trim-schemas deleted file mode 100755 index 29fb3a1b67..0000000000 --- a/scripts/poky-trim-schemas +++ /dev/null @@ -1,49 +0,0 @@ -#! /usr/bin/env python - -import sys -try: - import xml.etree.cElementTree as etree -except: - import xml.etree.ElementTree as etree - -def child (elem, name): - for e in elem.getchildren(): - if e.tag == name: - return e - return None - -def children (elem, name=None): - l = elem.getchildren() - if name: - l = [e for e in l if e.tag == name] - return l - -xml = etree.parse(sys.argv[1]) - -for schema in child(xml.getroot(), "schemalist").getchildren(): - e = child(schema, "short") - if e is not None: - schema.remove(e) - - e = child(schema, "long") - if e is not None: - schema.remove(e) - - for locale in children(schema, "locale"): - # One locale must exist so leave C locale... - a = locale.attrib.get("name") - if a == 'C': - continue - e = child(locale, "default") - if e is None: - schema.remove(locale) - else: - e = child(locale, "short") - if e is not None: - locale.remove(e) - e = child(locale, "long") - if e is not None: - locale.remove(e) - -xml.write(sys.stdout, "UTF-8") - diff --git a/scripts/runqemu-addptable2image b/scripts/runqemu-addptable2image new file mode 100755 index 0000000000..f0195ad8a3 --- /dev/null +++ b/scripts/runqemu-addptable2image @@ -0,0 +1,51 @@ +#!/bin/sh + +# Add a partion table to an ext2 image file +# +# Copyright (C) 2006-2007 OpenedHand Ltd. +# +# 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 + + +IMAGE=$1 +IMAGEOUT=$2 + +echo $IMAGE +echo $IMAGEOUT + +size=`ls -l $IMAGE | awk '{ print $5}'` +size2=`expr $size / 512 / 16 / 63` + +echo $size +echo $size2 + +# MBR Size = 512 * 63 bytes +dd if=/dev/zero of=$IMAGEOUT count=63 + +echo "x" > /tmp/fdisk.cmds +echo "c" >> /tmp/fdisk.cmds +echo "1024" >> /tmp/fdisk.cmds +echo "h" >> /tmp/fdisk.cmds +echo "16" >> /tmp/fdisk.cmds +echo "r" >> /tmp/fdisk.cmds +echo "n" >> /tmp/fdisk.cmds +echo "p" >> /tmp/fdisk.cmds +echo "1" >> /tmp/fdisk.cmds +echo "1" >> /tmp/fdisk.cmds +echo "$size2" >> /tmp/fdisk.cmds +echo "w" >> /tmp/fdisk.cmds + +/sbin/fdisk $IMAGEOUT < /tmp/fdisk.cmds +cat $IMAGE >> $IMAGEOUT diff --git a/scripts/runqemu-export-rootfs b/scripts/runqemu-export-rootfs new file mode 100755 index 0000000000..0076768d20 --- /dev/null +++ b/scripts/runqemu-export-rootfs @@ -0,0 +1,186 @@ +#!/bin/bash +# +# Copyright (c) 2005-2009 Wind River Systems, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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 + +usage() { + echo "Usage: $0 {start|stop|restart} " +} + +if [ $# != 2 ]; then + usage + exit 1 +fi + +if [[ "$1" != "start" && "$1" != "stop" && "$1" != "restart" ]]; then + echo "Unknown command '$1'" + usage + exit 1 +fi + +if [ ! -d "$2" ]; then + echo "Error: '$2' does not exist" + usage + exit 1 +fi +# Ensure the nfs-export-dir is an absolute path +NFS_EXPORT_DIR=$(cd "$2" && pwd) + +SYSROOT_SETUP_SCRIPT=`which oe-find-native-sysroot` +if [ -z "$SYSROOT_SETUP_SCRIPT" ]; then + echo "Error: Unable to find the oe-find-native-sysroot script" + echo "Did you forget to source your Poky environment script?" + exit 1 +fi +. $SYSROOT_SETUP_SCRIPT + +if [ ! -e "$OECORE_NATIVE_SYSROOT/usr/sbin/rpc.mountd" ]; then + echo "Error: Unable to find rpc.mountd binary in $OECORE_NATIVE_SYSROOT/usr/sbin/" + + if [ "x$POKY_DISTRO_VERSION" = "x" ]; then + echo "Have you run 'bitbake meta-ide-support'?" + else + echo "This shouldn't happen - something is missing from your toolchain installation" + fi + exit 1 +fi + +if [ ! -d ~/.poky-sdk ]; then + mkdir -p ~/.poky-sdk +fi + +NFS_INSTANCE=${NFS_INSTANCE:=0} +EXPORTS=~/.poky-sdk/exports$NFS_INSTANCE +RMTAB=~/.poky-sdk/rmtab$NFS_INSTANCE +NFSPID=~/.poky-sdk/nfs$NFS_INSTANCE.pid +MOUNTPID=~/.poky-sdk/mount$NFS_INSTANCE.pid + +PSEUDO_OPTS="-P $OECORE_NATIVE_SYSROOT/usr" +PSEUDO_LOCALSTATEDIR="$NFS_EXPORT_DIR/var/pseudo" +export PSEUDO_LOCALSTATEDIR + +if [ ! -d "$PSEUDO_LOCALSTATEDIR" ]; then + echo "Error: $PSEUDO_LOCALSTATEDIR does not exist." + echo "Did you create the export directory using runqemu-extract-sdk?" + exit 1 +fi + +# rpc.mountd RPC port +NFS_MOUNTPROG=$[ 21111 + $NFS_INSTANCE ] +# rpc.nfsd RPC port +NFS_NFSPROG=$[ 11111 + $NFS_INSTANCE ] +# NFS port number +NFS_PORT=$[ 3049 + $NFS_INSTANCE ] + +## For debugging you would additionally add +## --debug all +MOUNTD_OPTS="--allow-non-root --mount-pid $MOUNTPID -f $EXPORTS --rmtab $RMTAB --prog $NFS_MOUNTPROG -r" +NFSD_OPTS="--allow-non-root --nfs-pid $NFSPID -f $EXPORTS --prog $NFS_NFSPROG -P $NFS_PORT -r" + +# Setup the exports file +if [ "$1" = "start" ]; then + echo "Creating exports file..." + echo "$NFS_EXPORT_DIR (rw,async,no_root_squash,no_all_squash,insecure)" > $EXPORTS +fi + +# See how we were called. +case "$1" in + start) + echo "Starting User Mode rpc.mountd" + echo " $PSEUDO $PSEUDO_OPTS $OECORE_NATIVE_SYSROOT/usr/sbin/rpc.mountd $MOUNTD_OPTS" + $PSEUDO $PSEUDO_OPTS $OECORE_NATIVE_SYSROOT/usr/sbin/rpc.mountd $MOUNTD_OPTS + if [ ! $? = 0 ]; then + echo "=====================" + echo "Error starting MOUNTD" + echo "=====================" + ps -ef | grep -v grep | grep rpcbind 2>&1 > /dev/null + if [ $? = 0 ] ; then + echo " If you see an error above that says:" + echo " RPC: Authentication error; why = Client credential too weak" + echo " You need to change the startup of rpcbind" + echo " on your host by doing the following as root:" + echo "===============================================" + echo " According to /etc/sysconfig/rpcbind, then " + echo " echo RPCBIND_ARGS=-i >> /etc/sysconfig/rpcbind" + echo " or" + echo " echo RPCBIND_OPTIONS=-i >> /etc/sysconfig/rpcbind" + echo " /etc/init.d/rpcbind restart" + echo "===============================================" + fi + exit 1 + fi + echo "Starting User Mode nfsd" + echo " $PSEUDO $PSEUDO_OPTS $OECORE_NATIVE_SYSROOT/usr/sbin/rpc.nfsd $NFSD_OPTS" + $PSEUDO $PSEUDO_OPTS $OECORE_NATIVE_SYSROOT/usr/sbin/rpc.nfsd $NFSD_OPTS + if [ ! $? = 0 ]; then + echo "Error starting nfsd" + exit 1 + fi + # Check to make sure everything started ok. + if [ ! -f $MOUNTPID ]; then + echo "rpc.mountd did not start correctly" + exit 1 + fi + if [ ! -f $NFSPID ]; then + echo "rpc.nfsd did not start correctly" + exit 1 + fi + ps -fp `cat $MOUNTPID` > /dev/null 2> /dev/null + if [ ! $? = 0 ]; then + echo "rpc.mountd did not start correctly" + exit 1 + fi + ps -fp `cat $NFSPID` > /dev/null 2> /dev/null + if [ ! $? = 0 ]; then + echo "rpc.nfsd did not start correctly" + exit 1 + fi + echo " " + echo "On your target please remember to add the following options for NFS" + echo "nfsroot=IP_ADDRESS:$NFS_EXPORT_DIR,nfsvers=2,mountprog=$NFS_MOUNTPROG,nfsprog=$NFS_NFSPROG,udp" + ;; + stop) + if [ -f "$MOUNTPID" ]; then + echo "Stopping rpc.mountd" + kill `cat $MOUNTPID` + rm -f $MOUNTPID + else + echo "No PID file, not stopping rpc.mountd" + fi + if [ -f "$NFSPID" ]; then + echo "Stopping rpc.nfsd" + kill `cat $NFSPID` + rm -f $NFSPID + else + echo "No PID file, not stopping rpc.nfsd" + fi + if [ -f "$EXPORTS" ]; then + echo "Removing exports file" + rm -f $EXPORTS + fi + ;; + restart) + $0 stop $NFS_EXPORT_DIR + $0 start $NFS_EXPORT_DIR + if [ ! $? = 0 ]; then + exit 1 + fi + ;; + *) + echo "$0 {start|stop|restart} " + ;; +esac + +exit 0 diff --git a/scripts/runqemu-extract-sdk b/scripts/runqemu-extract-sdk new file mode 100755 index 0000000000..ed349dd306 --- /dev/null +++ b/scripts/runqemu-extract-sdk @@ -0,0 +1,100 @@ +#!/bin/bash +# +# This utility extracts an SDK image tarball using pseudo, and stores +# the pseudo database in var/pseudo within the rootfs. If you want to +# boot QEMU using an nfsroot, you *must* use this script to create the +# rootfs to ensure it is done correctly with pseudo. +# +# Copyright (c) 2010 Intel Corp. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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 + +function usage() { + echo "Usage: $0 " +} + +if [ $# -ne 2 ]; then + usage + exit 1 +fi + +SYSROOT_SETUP_SCRIPT=`which oe-find-native-sysroot` +if [ -z "$SYSROOT_SETUP_SCRIPT" ]; then + echo "Error: Unable to find the oe-find-native-sysroot script" + echo "Did you forget to source your Poky environment script?" + exit 1 +fi +. $SYSROOT_SETUP_SCRIPT +PSEUDO_OPTS="-P $OECORE_NATIVE_SYSROOT/usr" + +ROOTFS_TARBALL=$1 +SDK_ROOTFS_DIR=$2 + +if [ ! -e "$ROOTFS_TARBALL" ]; then + echo "Error: sdk tarball '$ROOTFS_TARBALL' does not exist" + usage + exit 1 +fi + +# Convert SDK_ROOTFS_DIR to a full pathname +if [[ ${SDK_ROOTFS_DIR:0:1} != "/" ]]; then + SDK_ROOTFS_DIR=$(pwd)/$SDK_ROOTFS_DIR +fi + +TAR_OPTS="" +if [[ "$ROOTFS_TARBALL" =~ tar\.bz2$ ]]; then + TAR_OPTS="-xjf" +fi +if [[ "$ROOTFS_TARBALL" =~ tar\.gz$ ]]; then + TAR_OPTS="-xzf" +fi +if [[ "$ROOTFS_TARBALL" =~ \.tar$ ]]; then + TAR_OPTS="-xf" +fi +if [ -z "$TAR_OPTS" ]; then + echo "Error: Unable to determine sdk tarball format" + echo "Accepted types: .tar / .tar.gz / .tar.bz2" + exit 1 +fi + +if [ ! -d "$SDK_ROOTFS_DIR" ]; then + echo "Creating directory $SDK_ROOTFS_DIR" + mkdir -p "$SDK_ROOTFS_DIR" +fi + +if [ -e "$SDK_ROOTFS_DIR/var/pseudo" ]; then + echo "Error: $SDK_ROOTFS_DIR/var/pseudo already exists!" + echo "Please delete the entire rootfs tree manually if this is really what you want" + exit 1 +fi + +mkdir -p "$SDK_ROOTFS_DIR/var/pseudo" +touch "$SDK_ROOTFS_DIR/var/pseudo/pseudo.pid" +PSEUDO_LOCALSTATEDIR="$SDK_ROOTFS_DIR/var/pseudo" +export PSEUDO_LOCALSTATEDIR + +echo "Extracting rootfs tarball using pseudo..." +echo "$PSEUDO $PSEUDO_OPTS tar -C \"$SDK_ROOTFS_DIR\" $TAR_OPTS \"$ROOTFS_TARBALL\"" +$PSEUDO $PSEUDO_OPTS tar -C "$SDK_ROOTFS_DIR" $TAR_OPTS "$ROOTFS_TARBALL" + +DIRCHECK=`ls -l "$SDK_ROOTFS_DIR" | wc -l` +if [ "$DIRCHECK" -lt 5 ]; then + echo "Warning: I don't see many files in $SDK_ROOTFS_DIR" + echo "Please double-check the extraction worked as intended" + exit 0 +fi + +echo "SDK image successfully extracted to $SDK_ROOTFS_DIR" + +exit 0 diff --git a/scripts/runqemu-gen-tapdevs b/scripts/runqemu-gen-tapdevs new file mode 100755 index 0000000000..527c01e7b4 --- /dev/null +++ b/scripts/runqemu-gen-tapdevs @@ -0,0 +1,85 @@ +#!/bin/bash +# +# Create a "bank" of tap network devices that can be used by the +# runqemu script. This script needs to be run as root, and will +# use the tunctl binary from a Poky sysroot. Note: many Linux distros +# these days still use an older version of tunctl which does not +# support the group permissions option, hence the need to use Poky's +# version. +# +# Copyright (C) 2010 Intel Corp. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# 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., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +usage() { + echo "Usage: sudo $0 " + echo "Where is the numeric group id the tap devices will be owned by" + echo " is the number of tap devices to create (0 to remove all)" + echo " is the path to Poky's native sysroot" + exit 1 +} + +if [ $EUID -ne 0 ]; then + echo "Error: This script must be run with root privileges" + exit +fi + +if [ $# -ne 3 ]; then + echo "Error: Incorrect number of arguments" + usage +fi + +GID=$1 +COUNT=$2 +SYSROOT=$3 + +TUNCTL=$SYSROOT/usr/bin/tunctl +if [[ ! -x "$TUNCTL" || -d "$TUNCTL" ]]; then + echo "Error: $TUNCTL is not an executable" + usage +fi + +SCRIPT_DIR=`dirname $0` +POKY_QEMU_IFUP="$SCRIPT_DIR/runqemu-ifup" +if [ ! -x "$POKY_QEMU_IFUP" ]; then + echo "Error: Unable to find the runqemu-ifup script in $SCRIPT_DIR" + exit 1 +fi + +IFCONFIG=`which ifconfig` +if [ -z "$IFCONFIG" ]; then + # Is it ever anywhere else? + IFCONFIG=/sbin/ifconfig +fi + +# Ensure we start with a clean slate +for tap in `$IFCONFIG | grep ^tap | awk '{ print \$1 }'`; do + echo "Note: Destroying pre-existing tap interface $tap..." + $TUNCTL -d $tap +done + +echo "Creating $COUNT tap devices for GID $GID..." +for ((index=0; index < $COUNT; index++)); do + echo "Creating tap$index" + ifup=`$POKY_QEMU_IFUP $GID $SYSROOT 2>&1` + if [ $? -ne 0 ]; then + echo "Error running tunctl: $ifup" + exit 1 + fi +done + +# The runqemu script will check for this file, and if it exists, +# will use the existing bank of tap devices without creating +# additional ones via sudo. +touch /etc/poky-nosudo diff --git a/scripts/runqemu-ifup b/scripts/runqemu-ifup index c963af5df9..a3914140a6 100755 --- a/scripts/runqemu-ifup +++ b/scripts/runqemu-ifup @@ -14,7 +14,7 @@ # ALL=NOPASSWD: /path/to/runqemu-ifdown # # If you'd like to create a bank of tap devices at once, you should use -# the poky-gen-tapdevs script instead. If tap devices are set up using +# the runqemu-gen-tapdevs script instead. If tap devices are set up using # that script, the runqemu script will never end up calling this # script. # diff --git a/scripts/runqemu-internal b/scripts/runqemu-internal index 64374f2076..adf2b47aae 100755 --- a/scripts/runqemu-internal +++ b/scripts/runqemu-internal @@ -83,7 +83,7 @@ fi if [ -z "$mem_set" ] ; then SCRIPT_QEMU_EXTRA_OPT="$SCRIPT_QEMU_EXTRA_OPT -m $mem_size" fi -# This file is created when poky-gen-tapdevs creates a bank of tap +# This file is created when runqemu-gen-tapdevs creates a bank of tap # devices, indicating that the user should not bring up new ones using # sudo. NOSUDO_FLAG="/etc/poky-nosudo" @@ -186,8 +186,8 @@ cleanup() { if [ "$NFSRUNNING" = "true" ]; then echo "Shutting down the userspace NFS server..." - echo "poky-export-rootfs stop $ROOTFS" - poky-export-rootfs stop $ROOTFS + echo "runqemu-export-rootfs stop $ROOTFS" + runqemu-export-rootfs stop $ROOTFS fi # If QEMU crashes or somehow tty properties are not restored # after qemu exits, we need to run stty sane @@ -258,8 +258,8 @@ if [ "$FSTYPE" = "nfs" ]; then fi # Start the userspace NFS server - echo "poky-export-rootfs restart $ROOTFS" - poky-export-rootfs restart $ROOTFS + echo "runqemu-export-rootfs restart $ROOTFS" + runqemu-export-rootfs restart $ROOTFS if [ $? != 0 ]; then cleanup return @@ -351,7 +351,7 @@ if [ "$MACHINE" = "spitz" ]; then echo $ROOTFS if [ ! -e "$ROOTFS.qemudisk" ]; then echo "Adding a partition table to the ext3 image for use by QEMU, please wait..." - poky-addptable2image $ROOTFS $ROOTFS.qemudisk + runqemu-addptable2image $ROOTFS $ROOTFS.qemudisk fi QEMUOPTIONS="$QEMU_NETWORK_CMD -M spitz -hda $ROOTFS.qemudisk -portrait" fi -- cgit 1.2.3-korg