summaryrefslogtreecommitdiff
path: root/tcpserver.c
diff options
context:
space:
mode:
authorDmitry Bogatov <KAction@debian.org>2018-11-29 05:18:28 +0000
committerDmitry Bogatov <KAction@debian.org>2018-11-29 05:18:28 +0000
commitb19ff825af9758fa905bf0ba29bbff66fa66cd50 (patch)
tree4a6fc0b53bb646a038a422b7ef90d65968fde149 /tcpserver.c
parent35c0ccd3b0eedd2d14e26a109f5812a5c30c38aa (diff)
Import Upstream version 0.88
Diffstat (limited to 'tcpserver.c')
-rw-r--r--tcpserver.c694
1 files changed, 307 insertions, 387 deletions
diff --git a/tcpserver.c b/tcpserver.c
index 012dc36..979a0be 100644
--- a/tcpserver.c
+++ b/tcpserver.c
@@ -1,66 +1,91 @@
#include <sys/types.h>
#include <sys/param.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
#include <netdb.h>
-
-#include "strerr.h"
-#include "substdio.h"
-#include "stralloc.h"
-#include "alloc.h"
-#include "readwrite.h"
-#include "fd.h"
-#include "sig.h"
-#include "wait.h"
-#include "ip.h"
-#include "ipalloc.h"
-#include "dns.h"
+#include "uint16.h"
#include "str.h"
-#include "case.h"
#include "byte.h"
-#include "sgetopt.h"
-#include "remoteinfo.h"
-#include "exit.h"
-#include "open.h"
-#include "scan.h"
#include "fmt.h"
+#include "scan.h"
+#include "ip4.h"
+#include "fd.h"
+#include "exit.h"
#include "env.h"
-#include "cdb.h"
+#include "prot.h"
+#include "open.h"
+#include "wait.h"
+#include "readwrite.h"
+#include "stralloc.h"
+#include "alloc.h"
+#include "buffer.h"
+#include "error.h"
+#include "strerr.h"
+#include "sgetopt.h"
+#include "pathexec.h"
+#include "socket.h"
+#include "ndelay.h"
+#include "remoteinfo.h"
+#include "rules.h"
+#include "sig.h"
+#include "dns.h"
-#define FATAL "tcpserver: fatal: "
-#define DROP "tcpserver: warning: dropping connection, "
int verbosity = 1;
+int flagkillopts = 1;
+int flagdelay = 1;
+char *banner = "";
+int flagremoteinfo = 1;
+int flagremotehost = 1;
+int flagparanoid = 0;
+unsigned long timeout = 26;
+
+static stralloc tcpremoteinfo;
+
+uint16 localport;
+char localportstr[FMT_ULONG];
+char localip[4];
+char localipstr[IP4_FMT];
+static stralloc localhostsa;
+char *localhost = 0;
-void die_nomem()
+uint16 remoteport;
+char remoteportstr[FMT_ULONG];
+char remoteip[4];
+char remoteipstr[IP4_FMT];
+static stralloc remotehostsa;
+char *remotehost = 0;
+
+char strnum[FMT_ULONG];
+char strnum2[FMT_ULONG];
+
+static stralloc tmp;
+static stralloc fqdn;
+static stralloc addresses;
+
+char bspace[16];
+buffer b;
+
+
+
+/* ---------------------------- child */
+
+#define DROP "tcpserver: warning: dropping connection, "
+
+int flagdeny = 0;
+int flagallownorules = 0;
+char *fnrules = 0;
+
+void drop_nomem(void)
{
- if (verbosity) strerr_warn2(FATAL,"out of memory",0);
- _exit(111);
+ strerr_die2sys(111,DROP,"out of memory");
}
-void drop_nomem()
+void cats(char *s)
{
- if (verbosity) strerr_warn2(DROP,"out of memory",0);
- _exit(111);
+ if (!stralloc_cats(&tmp,s)) drop_nomem();
}
-void usage()
+void append(char *ch)
{
- strerr_warn1("\
-tcpserver: usage: tcpserver \
-[ -1pPhHrRoOdDqQv ] \
-[ -c limit ] \
-[ -x rules.cdb ] \
-[ -B banner ] \
-[ -g gid ] \
-[ -u uid ] \
-[ -b backlog ] \
-[ -l localname ] \
-[ -t timeout ] \
-host port program",0);
- _exit(100);
+ if (!stralloc_append(&tmp,ch)) drop_nomem();
}
-
-void safeappend(sa,s)
-stralloc *sa;
-char *s;
+void safecats(char *s)
{
char ch;
int i;
@@ -72,204 +97,214 @@ char *s;
if (ch > 126) ch = '?';
if (ch == '%') ch = '?'; /* logger stupidity */
if (ch == ':') ch = '?';
- if (!stralloc_append(sa,&ch)) drop_nomem();
+ append(&ch);
}
- if (!stralloc_cats(sa,"...")) drop_nomem();
-}
-
-char strnum[FMT_ULONG];
-char strnum2[FMT_ULONG];
-stralloc tmp = {0};
-ipalloc ia = {0};
-
-unsigned long limit = 40;
-unsigned long numchildren = 0;
-
-char tcpremoteip[IPFMT];
-char tcpremoteport[IPFMT];
-char *tcpremoteinfo;
-struct sockaddr_in saremote;
-struct ip_address ipremote;
-unsigned long portremote;
-
-char tcplocalip[IPFMT];
-char tcplocalport[IPFMT];
-struct sockaddr_in salocal;
-struct ip_address iplocal;
-unsigned long portlocal;
-
-int fdrules;
-char *fnrules = 0;
-int flagdeny = 0;
-
-void printenv()
-{
- char *tcplocalhost;
- char *tcpremotehost;
-
- if (verbosity < 2) return;
-
- tcplocalhost = env_get("TCPLOCALHOST");
- tcpremotehost = env_get("TCPREMOTEHOST");
-
- if (!tcplocalhost) tcplocalhost = "";
- if (!tcpremotehost) tcpremotehost = "";
-
- if (!stralloc_copys(&tmp,"tcpserver: ")) drop_nomem();
- if (!stralloc_cats(&tmp,flagdeny ? "deny " : "ok ")) drop_nomem();
- if (!stralloc_catb(&tmp,strnum,fmt_ulong(strnum,getpid()))) drop_nomem();
- if (!stralloc_cats(&tmp," ")) drop_nomem();
- safeappend(&tmp,tcplocalhost);
- if (!stralloc_cats(&tmp,":")) drop_nomem();
- safeappend(&tmp,tcplocalip);
- if (!stralloc_cats(&tmp,":")) drop_nomem();
- safeappend(&tmp,tcplocalport);
- if (!stralloc_cats(&tmp," ")) drop_nomem();
- safeappend(&tmp,tcpremotehost);
- if (!stralloc_cats(&tmp,":")) drop_nomem();
- safeappend(&tmp,tcpremoteip);
- if (!stralloc_cats(&tmp,":")) drop_nomem();
- safeappend(&tmp,tcpremoteinfo ? tcpremoteinfo : "");
- if (!stralloc_cats(&tmp,":")) drop_nomem();
- safeappend(&tmp,tcpremoteport);
- if (!stralloc_0(&tmp)) drop_nomem();
-
- strerr_warn1(tmp.s,0);
+ cats("...");
}
-
-void printstatus()
+void env(char *s,char *t)
{
- if (verbosity < 2) return;
- strnum[fmt_ulong(strnum,numchildren)] = 0;
- strnum2[fmt_ulong(strnum2,limit)] = 0;
- strerr_warn4("tcpserver: status: ",strnum,"/",strnum2,0);
+ if (!pathexec_env(s,t)) drop_nomem();
}
-
-void printpid()
+void drop_rules(void)
{
- if (verbosity < 2) return;
- strnum[fmt_ulong(strnum,(unsigned long) getpid())] = 0;
- strerr_warn4("tcpserver: pid ",strnum," from ",tcpremoteip,0);
+ strerr_die4sys(111,DROP,"unable to read ",fnrules,": ");
}
-char printbuf[16];
-struct substdio print = SUBSTDIO_FDBUF(write,1,printbuf,sizeof(printbuf));
-void printlocalport()
+void found(char *data,unsigned int datalen)
{
- substdio_puts(&print,tcplocalport);
- substdio_puts(&print,"\n");
- substdio_flush(&print);
-}
-
-void sigterm() { _exit(0); }
+ unsigned int next0;
+ unsigned int split;
-void sigchld()
-{
- int wstat;
- int pid;
-
- while ((pid = wait_nohang(&wstat)) > 0) {
- if (verbosity >= 2) {
- strnum[fmt_ulong(strnum,(unsigned long) pid)] = 0;
- strnum2[fmt_ulong(strnum2,(unsigned long) wstat)] = 0;
- strerr_warn4("tcpserver: end ",strnum," status ",strnum2,0);
+ while ((next0 = byte_chr(data,datalen,0)) < datalen) {
+ switch(data[0]) {
+ case 'D':
+ flagdeny = 1;
+ break;
+ case '+':
+ split = str_chr(data + 1,'=');
+ if (data[1 + split] == '=') {
+ data[1 + split] = 0;
+ env(data + 1,data + 1 + split + 1);
+ }
+ break;
}
- if (numchildren) --numchildren; printstatus();
+ ++next0;
+ data += next0; datalen -= next0;
}
}
-void drop_rules()
+void doit(int t)
{
- if (verbosity) strerr_warn4(DROP,"unable to read ",fnrules,": ",&strerr_sys);
- _exit(111);
-}
+ int j;
-int dorule()
-{
- char *data;
- uint32 dlen32;
- unsigned int datalen;
- unsigned int next0;
+ remoteipstr[ip4_fmt(remoteipstr,remoteip)] = 0;
- switch(cdb_seek(fdrules,tmp.s,tmp.len,&dlen32)) {
- case -1: drop_rules();
- case 0: return 0;
+ if (verbosity >= 2) {
+ strnum[fmt_ulong(strnum,getpid())] = 0;
+ strerr_warn4("tcpserver: pid ",strnum," from ",remoteipstr,0);
}
- datalen = dlen32;
- data = alloc(datalen);
- if (!data) drop_nomem();
- if (cdb_bread(fdrules,data,datalen) != 0) drop_rules();
+ if (flagkillopts)
+ socket_ipoptionskill(t);
+ if (!flagdelay)
+ socket_tcpnodelay(t);
- while ((next0 = byte_chr(data,datalen,0)) < datalen) {
- switch(data[0]) {
- case 'D': flagdeny = 1; break;
- case '+': if (!env_put(data + 1)) drop_nomem(); break;
+ if (*banner) {
+ buffer_init(&b,write,t,bspace,sizeof bspace);
+ if (buffer_putsflush(&b,banner) == -1)
+ strerr_die2sys(111,DROP,"unable to print banner: ");
+ }
+
+ if (socket_local4(t,localip,&localport) == -1)
+ strerr_die2sys(111,DROP,"unable to get local address: ");
+
+ localipstr[ip4_fmt(localipstr,localip)] = 0;
+ remoteportstr[fmt_ulong(remoteportstr,remoteport)] = 0;
+
+ if (!localhost)
+ if (dns_name4(&localhostsa,localip) == 0)
+ if (localhostsa.len) {
+ if (!stralloc_0(&localhostsa)) drop_nomem();
+ localhost = localhostsa.s;
+ }
+ env("PROTO","TCP");
+ env("TCPLOCALIP",localipstr);
+ env("TCPLOCALPORT",localportstr);
+ env("TCPLOCALHOST",localhost);
+
+ if (flagremotehost)
+ if (dns_name4(&remotehostsa,remoteip) == 0)
+ if (remotehostsa.len) {
+ if (flagparanoid)
+ if (dns_ip4(&tmp,&remotehostsa) == 0)
+ for (j = 0;j + 4 <= tmp.len;j += 4)
+ if (byte_equal(remoteip,4,tmp.s + j)) {
+ flagparanoid = 0;
+ break;
+ }
+ if (!flagparanoid) {
+ if (!stralloc_0(&remotehostsa)) drop_nomem();
+ remotehost = remotehostsa.s;
+ }
+ }
+ env("TCPREMOTEIP",remoteipstr);
+ env("TCPREMOTEPORT",remoteportstr);
+ env("TCPREMOTEHOST",remotehost);
+
+ if (flagremoteinfo) {
+ if (remoteinfo(&tcpremoteinfo,remoteip,remoteport,localip,localport,timeout) == -1)
+ flagremoteinfo = 0;
+ if (!stralloc_0(&tcpremoteinfo)) drop_nomem();
+ }
+ env("TCPREMOTEINFO",flagremoteinfo ? tcpremoteinfo.s : 0);
+
+ if (fnrules) {
+ int fdrules;
+ fdrules = open_read(fnrules);
+ if (fdrules == -1) {
+ if (errno != error_noent) drop_rules();
+ if (!flagallownorules) drop_rules();
+ }
+ else {
+ if (rules(found,fdrules,remoteipstr,remotehost,flagremoteinfo ? tcpremoteinfo.s : 0) == -1) drop_rules();
+ close(fdrules);
}
- data += next0 + 1; datalen -= next0 + 1;
}
- return 1;
-}
-void rules()
-{
- if (!fnrules) return;
+ if (verbosity >= 2) {
+ strnum[fmt_ulong(strnum,getpid())] = 0;
+ if (!stralloc_copys(&tmp,"tcpserver: ")) drop_nomem();
+ safecats(flagdeny ? "deny" : "ok");
+ cats(" "); safecats(strnum);
+ cats(" "); if (localhost) safecats(localhost);
+ cats(":"); safecats(localipstr);
+ cats(":"); safecats(localportstr);
+ cats(" "); if (remotehost) safecats(remotehost);
+ cats(":"); safecats(remoteipstr);
+ cats(":"); if (flagremoteinfo) safecats(tcpremoteinfo.s);
+ cats(":"); safecats(remoteportstr);
+ cats("\n");
+ buffer_putflush(buffer_2,tmp.s,tmp.len);
+ }
- fdrules = open_read(fnrules);
- if (fdrules == -1) drop_rules();
+ if (flagdeny) _exit(100);
+}
- if (tcpremoteinfo) {
- if (!stralloc_copys(&tmp,tcpremoteinfo)) drop_nomem();
- if (!stralloc_cats(&tmp,"@")) drop_nomem();
- if (!stralloc_cats(&tmp,tcpremoteip)) drop_nomem();
- if (dorule()) goto done;
- }
- if (!stralloc_copys(&tmp,tcpremoteip)) drop_nomem();
- if (dorule()) goto done;
- while (tmp.len > 0) {
- if (tcpremoteip[tmp.len - 1] == '.')
- if (dorule()) goto done;
- --tmp.len;
- }
- dorule();
+/* ---------------------------- parent */
- done:
- close(fdrules);
+#define FATAL "tcpserver: fatal: "
+
+void usage(void)
+{
+ strerr_warn1("\
+tcpserver: usage: tcpserver \
+[ -1UXpPhHrRoOdDqQv ] \
+[ -c limit ] \
+[ -x rules.cdb ] \
+[ -B banner ] \
+[ -g gid ] \
+[ -u uid ] \
+[ -b backlog ] \
+[ -l localname ] \
+[ -t timeout ] \
+host port program",0);
+ _exit(100);
}
-int flagkillopts = 1;
-int flagdelay = 1;
-int flagremoteinfo = 1;
-int flagremotehost = 1;
-int flagparanoid = 0;
+unsigned long limit = 40;
+unsigned long numchildren = 0;
+
int flag1 = 0;
unsigned long backlog = 20;
-unsigned long timeout = 26;
unsigned long uid = 0;
unsigned long gid = 0;
-char *forcelocal = 0;
-char *banner = "";
+void printstatus(void)
+{
+ if (verbosity < 2) return;
+ strnum[fmt_ulong(strnum,numchildren)] = 0;
+ strnum2[fmt_ulong(strnum2,limit)] = 0;
+ strerr_warn4("tcpserver: status: ",strnum,"/",strnum2,0);
+}
-void main(argc,argv)
-int argc;
-char **argv;
+void sigterm()
+{
+ _exit(0);
+}
+
+void sigchld()
+{
+ int wstat;
+ int pid;
+
+ while ((pid = wait_nohang(&wstat)) > 0) {
+ if (verbosity >= 2) {
+ strnum[fmt_ulong(strnum,pid)] = 0;
+ strnum2[fmt_ulong(strnum2,wstat)] = 0;
+ strerr_warn4("tcpserver: end ",strnum," status ",strnum2,0);
+ }
+ if (numchildren) --numchildren; printstatus();
+ }
+}
+
+main(int argc,char **argv)
{
- int s;
- int t;
- int dummy;
- int opt;
char *hostname;
char *portname;
+ int opt;
struct servent *se;
- int j;
+ char *x;
+ unsigned long u;
+ int s;
+ int t;
- while ((opt = getopt(argc,argv,"dDvqQhHrR1x:t:u:g:l:b:B:c:pPoO")) != opteof)
+ while ((opt = getopt(argc,argv,"dDvqQhHrR1UXx:t:u:g:l:b:B:c:pPoO")) != opteof)
switch(opt) {
case 'b': scan_ulong(optarg,&backlog); break;
case 'c': scan_ulong(optarg,&limit); break;
+ case 'X': flagallownorules = 1; break;
case 'x': fnrules = optarg; break;
case 'B': banner = optarg; break;
case 'd': flagdelay = 1; break;
@@ -286,220 +321,105 @@ char **argv;
case 'R': flagremoteinfo = 0; break;
case 'r': flagremoteinfo = 1; break;
case 't': scan_ulong(optarg,&timeout); break;
- case 'g': scan_ulong(optarg,&gid); break;
+ case 'U': x = env_get("UID"); if (x) scan_ulong(x,&uid);
+ x = env_get("GID"); if (x) scan_ulong(x,&gid); break;
case 'u': scan_ulong(optarg,&uid); break;
+ case 'g': scan_ulong(optarg,&gid); break;
case '1': flag1 = 1; break;
- case 'l': forcelocal = optarg; break;
+ case 'l': localhost = optarg; break;
default: usage();
}
argc -= optind;
argv += optind;
+
+ if (!verbosity)
+ buffer_2->fd = -1;
hostname = *argv++;
if (!hostname) usage();
- portname = *argv++;
- if (!portname) usage();
- if (!*argv) usage();
-
- sig_pipeignore();
- sig_termcatch(sigterm);
- sig_childcatch(sigchld);
-
- dns_init(1);
-
- byte_zero(&salocal,sizeof(salocal));
- salocal.sin_family = AF_INET;
-
- if (!portname[scan_ulong(portname,&portlocal)])
- salocal.sin_port = htons((unsigned short) portlocal);
- else {
- se = getservbyname(portname,"tcp");
- if (!se) {
- if (verbosity) strerr_warn3(FATAL,"unable to figure out port number for ",portname,0);
- _exit(111);
- }
- salocal.sin_port = se->s_port;
- }
-
if (str_equal(hostname,"")) hostname = "0.0.0.0";
if (str_equal(hostname,"0")) hostname = "0.0.0.0";
-
- if (hostname[ip_scan(hostname,&iplocal)]) {
- if (!stralloc_copys(&tmp,hostname)) die_nomem();
- switch(dns_ip(&ia,&tmp)) {
- case DNS_MEM:
- die_nomem();
- case DNS_HARD:
- if (verbosity) strerr_warn3(FATAL,"unable to figure out IP address for ",hostname,0);
- _exit(111);
- case DNS_SOFT:
- if (verbosity) strerr_warn3(FATAL,"temporarily unable to figure out IP address for ",hostname,0);
- _exit(111);
- }
- if (!ia.len) {
- if (verbosity) strerr_warn3(FATAL,"no IP addresses for host ",hostname,0);
- _exit(111);
- }
- byte_copy(&iplocal,4,&ia.ix[0].ip);
+
+ x = *argv++;
+ if (!x) usage();
+ if (!x[scan_ulong(x,&u)])
+ localport = u;
+ else {
+ se = getservbyname(x,"tcp");
+ if (!se)
+ strerr_die3x(111,FATAL,"unable to figure out port number for ",x);
+ localport = ntohs(se->s_port);
}
+
+ if (!*argv) usage();
- byte_copy(&salocal.sin_addr,4,&iplocal);
- s = socket(AF_INET,SOCK_STREAM,0);
- if (s == -1) {
- if (verbosity) strerr_warn2(FATAL,"unable to create socket: ",&strerr_sys);
- _exit(111);
- }
+ sig_block(sig_child);
+ sig_catch(sig_child,sigchld);
+ sig_catch(sig_term,sigterm);
+ sig_ignore(sig_pipe);
- {
- int opt = 1;
- setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
- }
+ if (!stralloc_copys(&tmp,hostname))
+ strerr_die2x(111,FATAL,"out of memory");
+ 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);
+ byte_copy(localip,4,addresses.s);
+
+ s = socket_tcp();
+ if (s == -1)
+ strerr_die2sys(111,FATAL,"unable to create socket: ");
+ if (socket_bind4_reuse(s,localip,localport) == -1)
+ strerr_die2sys(111,FATAL,"unable to bind: ");
+ if (socket_local4(s,localip,&localport) == -1)
+ strerr_die2sys(111,FATAL,"unable to get local address: ");
+ if (socket_listen(s,backlog) == -1)
+ strerr_die2sys(111,FATAL,"unable to listen: ");
+ ndelay_off(s);
+
+ if (gid) if (prot_gid(gid) == -1)
+ strerr_die2sys(111,FATAL,"unable to set gid: ");
+ if (uid) if (prot_uid(uid) == -1)
+ strerr_die2sys(111,FATAL,"unable to set uid: ");
- if (bind(s,(struct sockaddr *) &salocal,sizeof(salocal)) == -1) {
- if (verbosity) strerr_warn2(FATAL,"unable to bind: ",&strerr_sys);
- _exit(111);
- }
- dummy = sizeof(salocal);
- if (getsockname(s,(struct sockaddr *) &salocal,&dummy) == -1) {
- if (verbosity) strerr_warn2(FATAL,"unable to get local address: ",&strerr_sys);
- _exit(111);
- }
- if (listen(s,backlog) == -1) {
- if (verbosity) strerr_warn2(FATAL,"unable to listen: ",&strerr_sys);
- _exit(111);
- }
- if (gid) if (setgid(gid) == -1) {
- if (verbosity) strerr_warn2(FATAL,"unable to set gid: ",&strerr_sys);
- _exit(100);
+ localportstr[fmt_ulong(localportstr,localport)] = 0;
+ if (flag1) {
+ buffer_init(&b,write,1,bspace,sizeof bspace);
+ buffer_puts(&b,localportstr);
+ buffer_puts(&b,"\n");
+ buffer_flush(&b);
}
- if (uid) if (setuid(uid) == -1) {
- if (verbosity) strerr_warn2(FATAL,"unable to set uid: ",&strerr_sys);
- _exit(100);
- }
-
- if (!env_init()) die_nomem();
- if (!env_put("PROTO=TCP")) die_nomem();
- if (!env_unset("TCPLOCALHOST")) die_nomem();
- if (!env_unset("TCPREMOTEHOST")) die_nomem();
- if (!env_unset("TCPREMOTEINFO")) die_nomem();
-
- if (forcelocal)
- if (!env_put2("TCPLOCALHOST",forcelocal)) die_nomem();
-
- portlocal = ntohs(salocal.sin_port);
- tcplocalport[fmt_ulong(tcplocalport,portlocal)] = 0;
- if (!env_put2("TCPLOCALPORT",tcplocalport)) die_nomem();
- if (flag1) printlocalport();
close(0);
close(1);
- sig_childblock();
+ printstatus();
for (;;) {
while (numchildren >= limit) sig_pause();
- sig_childunblock();
-
- dummy = sizeof(saremote);
- t = accept(s,(struct sockaddr *) &saremote,&dummy);
- if (t == -1) continue;
- portremote = ntohs(saremote.sin_port);
- byte_copy(&ipremote,4,&saremote.sin_addr);
-
- sig_childblock();
+ sig_unblock(sig_child);
+ t = socket_accept4(s,remoteip,&remoteport);
+ sig_block(sig_child);
+
+ if (t == -1) continue;
++numchildren; printstatus();
switch(fork()) {
- case -1:
- if (verbosity) strerr_warn2(DROP,"unable to fork: ",&strerr_sys);
- --numchildren; printstatus();
- break;
case 0:
- tcpremoteip[ip_fmt(tcpremoteip,&ipremote)] = 0;
- printpid();
-
close(s);
- if (flagkillopts) {
- setsockopt(t,IPPROTO_IP,1,(char *) 0,0); /* 1 == IP_OPTIONS */
- /* if it fails, bummer */
- }
- if (!flagdelay) {
- int opt = 1;
- setsockopt(t,IPPROTO_TCP,1,&opt,sizeof(opt)); /* 1 == TCP_NODELAY */
- /* if it fails, bummer */
- }
-
- if (*banner) {
- substdio ss;
- char ssbuf[1];
- substdio_fdbuf(&ss,write,t,ssbuf,sizeof ssbuf);
- if (substdio_putsflush(&ss,banner) == -1) {
- if (verbosity) strerr_warn2(DROP,"unable to print banner: ",&strerr_sys);
- _exit(111);
- }
- }
-
- dummy = sizeof(salocal);
- if (getsockname(t,(struct sockaddr *) &salocal,&dummy) == -1) {
- if (verbosity) strerr_warn2(DROP,"unable to get local address: ",&strerr_sys);
- _exit(111);
- }
- byte_copy(&iplocal,4,&salocal.sin_addr);
-
- tcplocalip[ip_fmt(tcplocalip,&iplocal)] = 0;
- tcpremoteport[fmt_ulong(tcpremoteport,portremote)] = 0;
-
- if (!env_put2("TCPREMOTEIP",tcpremoteip)) drop_nomem();
- if (!env_put2("TCPLOCALIP",tcplocalip)) drop_nomem();
- if (!env_put2("TCPREMOTEPORT",tcpremoteport)) drop_nomem();
-
- if (!forcelocal)
- switch(dns_ptr(&tmp,&iplocal)) {
- case DNS_MEM: drop_nomem();
- case 0:
- if (!stralloc_0(&tmp)) drop_nomem();
- case_lowers(tmp.s);
- if (!env_put2("TCPLOCALHOST",tmp.s)) drop_nomem();
- }
-
- if (flagremotehost)
- switch(dns_ptr(&tmp,&ipremote)) {
- case DNS_MEM: drop_nomem();
- case 0:
- if (flagparanoid) {
- if (dns_ip(&ia,&tmp) != 0) break;
- for (j = 0;j < ia.len;++j)
- if (!byte_diff(&ipremote,4,&ia.ix[j].ip))
- break;
- if (j == ia.len)
- break;
- }
- if (!stralloc_0(&tmp)) drop_nomem();
- case_lowers(tmp.s);
- if (!env_put2("TCPREMOTEHOST",tmp.s)) drop_nomem();
- }
- if (flagremoteinfo) {
- tcpremoteinfo = remoteinfo_get(&ipremote,portremote,&iplocal,portlocal,(int) timeout);
- if (tcpremoteinfo)
- if (!env_put2("TCPREMOTEINFO",tcpremoteinfo)) drop_nomem();
- }
-
- rules();
- printenv();
- if (flagdeny) _exit(100);
-
- if ((fd_move(0,t) == -1) || (fd_copy(1,0) == -1)) {
- if (verbosity) strerr_warn2(DROP,"unable to set up descriptors: ",&strerr_sys);
- _exit(111);
- }
- sig_childdefault();
- sig_childunblock();
- sig_termdefault();
- sig_pipedefault();
- execvp(*argv,argv);
- if (verbosity) strerr_warn4(DROP,"unable to run ",*argv,": ",&strerr_sys);
- _exit(111);
+ doit(t);
+ if ((fd_move(0,t) == -1) || (fd_copy(1,0) == -1))
+ strerr_die2sys(111,DROP,"unable to set up descriptors: ");
+ sig_uncatch(sig_child);
+ sig_unblock(sig_child);
+ sig_uncatch(sig_term);
+ sig_uncatch(sig_pipe);
+ pathexec(argv);
+ strerr_die4sys(111,DROP,"unable to run ",*argv,": ");
+ case -1:
+ strerr_warn2(DROP,"unable to fork: ",&strerr_sys);
+ --numchildren; printstatus();
}
close(t);
}