summaryrefslogtreecommitdiff
path: root/ucspi-tcp-0.88/tcpclient.c
diff options
context:
space:
mode:
Diffstat (limited to 'ucspi-tcp-0.88/tcpclient.c')
-rw-r--r--ucspi-tcp-0.88/tcpclient.c224
1 files changed, 224 insertions, 0 deletions
diff --git a/ucspi-tcp-0.88/tcpclient.c b/ucspi-tcp-0.88/tcpclient.c
new file mode 100644
index 0000000..9f6d7f2
--- /dev/null
+++ b/ucspi-tcp-0.88/tcpclient.c
@@ -0,0 +1,224 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netdb.h>
+#include "sig.h"
+#include "exit.h"
+#include "sgetopt.h"
+#include "uint16.h"
+#include "fmt.h"
+#include "scan.h"
+#include "str.h"
+#include "ip4.h"
+#include "uint16.h"
+#include "socket.h"
+#include "fd.h"
+#include "stralloc.h"
+#include "buffer.h"
+#include "error.h"
+#include "strerr.h"
+#include "pathexec.h"
+#include "timeoutconn.h"
+#include "remoteinfo.h"
+#include "dns.h"
+
+#define FATAL "tcpclient: fatal: "
+#define CONNECT "tcpclient: unable to connect to "
+
+void nomem(void)
+{
+ strerr_die2x(111,FATAL,"out of memory");
+}
+void usage(void)
+{
+ strerr_die1x(100,"tcpclient: usage: tcpclient \
+[ -hHrRdDqQv ] \
+[ -i localip ] \
+[ -p localport ] \
+[ -T timeoutconn ] \
+[ -l localname ] \
+[ -t timeoutinfo ] \
+host port program");
+}
+
+int verbosity = 1;
+int flagdelay = 1;
+int flagremoteinfo = 1;
+int flagremotehost = 1;
+unsigned long itimeout = 26;
+unsigned long ctimeout[2] = { 2, 58 };
+
+char iplocal[4] = { 0,0,0,0 };
+uint16 portlocal = 0;
+char *forcelocal = 0;
+
+char ipremote[4];
+uint16 portremote;
+
+char *hostname;
+static stralloc addresses;
+static stralloc moreaddresses;
+
+static stralloc tmp;
+static stralloc fqdn;
+char strnum[FMT_ULONG];
+char ipstr[IP4_FMT];
+
+char seed[128];
+
+main(int argc,char **argv)
+{
+ unsigned long u;
+ int opt;
+ char *x;
+ int j;
+ int s;
+ int cloop;
+
+ dns_random_init(seed);
+
+ close(6);
+ close(7);
+ sig_ignore(sig_pipe);
+
+ while ((opt = getopt(argc,argv,"dDvqQhHrRi:p:t:T:l:")) != opteof)
+ switch(opt) {
+ case 'd': flagdelay = 1; break;
+ case 'D': flagdelay = 0; break;
+ case 'v': verbosity = 2; break;
+ case 'q': verbosity = 0; break;
+ case 'Q': verbosity = 1; break;
+ case 'l': forcelocal = optarg; break;
+ case 'H': flagremotehost = 0; break;
+ case 'h': flagremotehost = 1; break;
+ case 'R': flagremoteinfo = 0; break;
+ case 'r': flagremoteinfo = 1; break;
+ case 't': scan_ulong(optarg,&itimeout); break;
+ case 'T': j = scan_ulong(optarg,&ctimeout[0]);
+ if (optarg[j] == '+') ++j;
+ scan_ulong(optarg + j,&ctimeout[1]);
+ break;
+ case 'i': if (!ip4_scan(optarg,iplocal)) usage(); break;
+ case 'p': scan_ulong(optarg,&u); portlocal = u; break;
+ default: usage();
+ }
+ argv += optind;
+
+ if (!verbosity)
+ buffer_2->fd = -1;
+
+ hostname = *argv;
+ if (!hostname) usage();
+ if (str_equal(hostname,"")) hostname = "127.0.0.1";
+ if (str_equal(hostname,"0")) hostname = "127.0.0.1";
+
+ x = *++argv;
+ if (!x) usage();
+ if (!x[scan_ulong(x,&u)])
+ portremote = u;
+ else {
+ struct servent *se;
+ se = getservbyname(x,"tcp");
+ if (!se)
+ strerr_die3x(111,FATAL,"unable to figure out port number for ",x);
+ portremote = ntohs(se->s_port);
+ /* i continue to be amazed at the stupidity of the s_port interface */
+ }
+
+ if (!*++argv) usage();
+
+ if (!stralloc_copys(&tmp,hostname)) nomem();
+ if (dns_ip4_qualify(&addresses,&fqdn,&tmp) == -1)
+ strerr_die4sys(111,FATAL,"temporarily unable to figure out IP address for ",hostname,": ");
+ if (addresses.len < 4)
+ strerr_die3x(111,FATAL,"no IP address for ",hostname);
+
+ if (addresses.len == 4) {
+ ctimeout[0] += ctimeout[1];
+ ctimeout[1] = 0;
+ }
+
+ for (cloop = 0;cloop < 2;++cloop) {
+ if (!stralloc_copys(&moreaddresses,"")) nomem();
+ for (j = 0;j + 4 <= addresses.len;j += 4) {
+ s = socket_tcp();
+ if (s == -1)
+ strerr_die2sys(111,FATAL,"unable to create socket: ");
+ if (socket_bind4(s,iplocal,portlocal) == -1)
+ strerr_die2sys(111,FATAL,"unable to bind socket: ");
+ if (timeoutconn(s,addresses.s + j,portremote,ctimeout[cloop]) == 0)
+ goto CONNECTED;
+ close(s);
+ if (!cloop && ctimeout[1] && (errno == error_timeout)) {
+ if (!stralloc_catb(&moreaddresses,addresses.s + j,4)) nomem();
+ }
+ else {
+ strnum[fmt_ulong(strnum,portremote)] = 0;
+ ipstr[ip4_fmt(ipstr,addresses.s + j)] = 0;
+ strerr_warn5(CONNECT,ipstr," port ",strnum,": ",&strerr_sys);
+ }
+ }
+ if (!stralloc_copy(&addresses,&moreaddresses)) nomem();
+ }
+
+ _exit(111);
+
+
+
+ CONNECTED:
+
+ if (!flagdelay)
+ socket_tcpnodelay(s); /* if it fails, bummer */
+
+ if (!pathexec_env("PROTO","TCP")) nomem();
+
+ if (socket_local4(s,iplocal,&portlocal) == -1)
+ strerr_die2sys(111,FATAL,"unable to get local address: ");
+
+ strnum[fmt_ulong(strnum,portlocal)] = 0;
+ if (!pathexec_env("TCPLOCALPORT",strnum)) nomem();
+ ipstr[ip4_fmt(ipstr,iplocal)] = 0;
+ if (!pathexec_env("TCPLOCALIP",ipstr)) nomem();
+
+ x = forcelocal;
+ if (!x)
+ if (dns_name4(&tmp,iplocal) == 0) {
+ if (!stralloc_0(&tmp)) nomem();
+ x = tmp.s;
+ }
+ if (!pathexec_env("TCPLOCALHOST",x)) nomem();
+
+ if (socket_remote4(s,ipremote,&portremote) == -1)
+ strerr_die2sys(111,FATAL,"unable to get remote address: ");
+
+ strnum[fmt_ulong(strnum,portremote)] = 0;
+ if (!pathexec_env("TCPREMOTEPORT",strnum)) nomem();
+ ipstr[ip4_fmt(ipstr,ipremote)] = 0;
+ if (!pathexec_env("TCPREMOTEIP",ipstr)) nomem();
+ if (verbosity >= 2)
+ strerr_warn4("tcpclient: connected to ",ipstr," port ",strnum,0);
+
+ x = 0;
+ if (flagremotehost)
+ if (dns_name4(&tmp,ipremote) == 0) {
+ if (!stralloc_0(&tmp)) nomem();
+ x = tmp.s;
+ }
+ if (!pathexec_env("TCPREMOTEHOST",x)) nomem();
+
+ x = 0;
+ if (flagremoteinfo)
+ if (remoteinfo(&tmp,ipremote,portremote,iplocal,portlocal,itimeout) == 0) {
+ if (!stralloc_0(&tmp)) nomem();
+ x = tmp.s;
+ }
+ if (!pathexec_env("TCPREMOTEINFO",x)) nomem();
+
+ if (fd_move(6,s) == -1)
+ strerr_die2sys(111,FATAL,"unable to set up descriptor 6: ");
+ if (fd_copy(7,6) == -1)
+ strerr_die2sys(111,FATAL,"unable to set up descriptor 7: ");
+ sig_uncatch(sig_pipe);
+
+ pathexec(argv);
+ strerr_die4sys(111,FATAL,"unable to run ",*argv,": ");
+}