31#define WHO "tcpserver"
44static stralloc tcpremoteinfo;
50static stralloc localhostsa;
58static stralloc remotehostsa;
61static char strnum[FMT_ULONG];
62static char strnum2[FMT_ULONG];
63static char strnum3[FMT_ULONG];
67static stralloc addresses;
79 logmsg(
WHO,111,FATAL,
"out of memory");
90GEN_ALLOC_readyplus(child_alloc,
struct child,c,len,a,i,n,x,24,child_readyplus)
91GEN_ALLOC_append(child_alloc,
struct child,c,len,a,i,n,x,24,child_readyplus,child_append)
93child_alloc children = {0};
97 struct child *ipchild = 0;
99 for (
unsigned long i = 0; i <= n; ++i) {
100 ipchild = &children.c[i];
101 if (byte_equal(ipchild->
ipaddr,16,ip)) {
105 byte_copy(ipchild->
ipaddr,16,ip);
114 struct child *ipchild = 0;
116 for (
unsigned long i = 0; i <= children.len; ++i) {
117 ipchild = &children.c[i];
118 if (byte_equal(ipchild->
ipaddr,16,ip)) {
119 if (ipchild->
num) --ipchild->
num;
128 for (
unsigned long i = 0; i <= n; ++i)
129 if (byte_equal(children.c[i].ipaddr,16,ip))
130 return children.c[i].
num;
156 for (i = 0; i < 100; ++i) {
159 if (ch < 33) ch =
'?';
160 if (ch > 126) ch =
'?';
161 if (ch ==
'%') ch =
'?';
166void env(
const char *s,
const char *t)
172 logmsg(
WHO,110,DROP,B(
"unable to read: ",fnbase));
182 while ((next0 = byte_chr(
data,datalen,0)) < datalen) {
189 split = str_chr(
data + 1,
'=');
190 if (
data[1 + split] ==
'=') {
193 if (!str_diff(
data + 1,
"MAXCONIP")) {
202 data += next0; datalen -= next0;
211 logmsg(
WHO,111,FATAL,
"unable to get local address");
213 socket_ipoptionskill(t);
215 socket_tcpnodelay(t);
226 strnum[fmt_ulong(strnum,getpid())] = 0;
232 if (buffer_putsflush(&
bo,
banner) == -1)
233 logmsg(
WHO,111,FATAL,
"unable to print banner");
237 if (dns_name(&localhostsa,
localip) >= 0)
238 if (localhostsa.len) {
264 if (dns_name(&remotehostsa,
remoteip) >= 0)
265 if (remotehostsa.len) {
267 if (dns_ip6(&tmp,&remotehostsa) >= 0)
268 for (j = 0; j + 16 <= tmp.len; j += 16)
269 if (byte_equal(
remoteip,16,tmp.s + j)) {
273 if (dns_ip4(&tmp,&remotehostsa) >= 0)
274 for (j = 0; j + 4 <= tmp.len; j += 4)
275 if (byte_equal(
remoteip + 12,4,tmp.s + j)) {
289 if (!stralloc_0(&tcpremoteinfo))
drop_nomem();
307 strnum[fmt_ulong(strnum,getpid())] = 0;
308 strnum2[fmt_ulong(strnum2,
maxconip)] = 0;
309 if (!stralloc_copys(&tmp,
"tcpserver: "))
drop_nomem();
321 buffer_putflush(buffer_2,tmp.s,tmp.len);
328 env(
"PROTO",ip6_isv4mapped(
remoteip)?
"TCP":
"TCP6");
353 logmsg(
WHO,100,USAGE,
"tcpserver \
354[ -46UxXpPhHrRoOdDqQv ] \
376 strnum2[fmt_ulong(strnum2,
limit)] = 0;
377 strnum3[fmt_ulong(strnum3,
maxconip)] = 0;
378 log_who(
WHO,B(
"status: ",strnum,
"/",strnum2,
"/",strnum3));
381static void sigterm(
int dummy)
386static void sigchld(
int dummy)
391 while ((
pid = wait_nohang(&wstat)) > 0) {
393 strnum[fmt_ulong(strnum,
pid)] = 0;
394 strnum2[fmt_ulong(strnum2,wstat)] = 0;
395 log_who(
WHO,B(
"end ",strnum,
" status ",strnum2));
403int main(
int argc,
char *
const *argv)
415 while ((opt = getoptb(argc,argv,
"146dDvqQhHrRUXx:y:t:u:g:l:b:B:c:I:pPoO")) != opteof) {
417 case '1':
flag1 = 1;
break;
418 case '4': ipflag = 1;
break;
419 case '6': ipflag = 2;
break;
429 case 'U': x = env_get(
"UID");
if (x) scan_ulong(x,&
uid);
430 x = env_get(
"GID");
if (x) scan_ulong(x,&
gid);
break;
431 case 'x':
fnrules = optarg;
break;
434 case 't': scan_ulong(optarg,&
timeout);
break;
435 case 'u': scan_ulong(optarg,&
uid);
break;
436 case 'g': scan_ulong(optarg,&
gid);
break;
438 case 'b': scan_ulong(optarg,&
backlog);
break;
439 case 'B':
banner = optarg;
break;
441 case 'I':
netif = socket_getifidx(optarg);
break;
458 else if (str_equal((
char *)
hostname,
":0")) {
466 if (!x[scan_ulong(x,&u)])
469 se = getservbyname(x,
"tcp");
471 logmsg(
WHO,111,FATAL,B(
"unable to figure out port number for: ",x));
472 uint16_unpack_big((
char*)&se->s_port,&
localport);
477 if ((x = env_get(
"MAXCONIP"))) { scan_ulong(x,&u);
maxconip = u; }
480 sig_block(sig_child);
481 sig_catch(sig_child,sigchld);
482 sig_catch(sig_term,sigterm);
483 sig_ignore(sig_pipe);
488 if (!stralloc_copyb(&addresses,(
char *)V4mappedprefix,12))
drop_nomem();
490 byte_copy(
localip,16,addresses.s);
493 byte_copy(
localip,16,addresses.s);
498 if (!addresses.len) {
500 if (dns_ip_qualify(&addresses,&fqdn,&tmp) < 0)
501 logmsg(
WHO,111,FATAL,B(
"temporarily unable to figure out IP address for: ",(
char *)
hostname));
503 byte_copy(
localip,16,addresses.s);
505 for (j = 0; j < addresses.len; j += 16) {
506 if (ipflag == 1 && !ip6_isv4mapped(addresses.s + j))
continue;
507 if (ipflag == 2 && ip6_isv4mapped(addresses.s + j))
continue;
508 byte_copy(
localip,16,addresses.s + j);
512 if (addresses.len < 16)
513 logmsg(
WHO,111,FATAL,B(
"no IP address for: ",(
char *)
hostname));
520 logmsg(
WHO,111,FATAL,
"unable to create socket");
524 logmsg(
WHO,111,FATAL,
"unable to bind");
526 logmsg(
WHO,111,FATAL,
"unable to get local address");
527 if (socket_listen(s,
backlog) == -1)
528 logmsg(
WHO,111,FATAL,
"unable to listen");
533 if (
gid)
if (prot_gid(
gid) == -1)
534 logmsg(
WHO,111,FATAL,
"unable to set gid");
535 if (
uid)
if (prot_uid(
uid) == -1)
536 logmsg(
WHO,111,FATAL,
"unable to set uid");
549 buffer_puts(&
bo,
" : ");
551 buffer_puts(&
bo,
" [");
552 strnum[fmt_ulong(strnum,
limit)] = 0;
553 buffer_puts(&
bo,strnum);
554 buffer_puts(&
bo,
"/");
555 strnum[fmt_ulong(strnum,
maxconip)] = 0;
556 buffer_puts(&
bo,strnum);
557 buffer_puts(&
bo,
"]");
558 buffer_puts(&
bo,
"\n");
570 sig_unblock(sig_child);
572 sig_block(sig_child);
573 if (t == -1)
continue;
583 strnum[fmt_ulong(strnum,
maxconip)] = 0;
584 logmsg(
WHO,100,WARN,B(
"ip connection limit of ",strnum,
" exceeded for: ",
remoteipstr));
597 if ((fd_move(0,t) == -1) || (fd_copy(1,0) == -1))
598 logmsg(
WHO,111,FATAL,
"unable to set up descriptors");
599 sig_uncatch(sig_child);
600 sig_unblock(sig_child);
601 sig_uncatch(sig_term);
602 sig_uncatch(sig_pipe);
604 logmsg(
WHO,111,FATAL,B(
"unable to run: ",*argv));
607 logmsg(
WHO,111,FATAL,
"unable to fork");
char bspace[BUFFER_SMALL]
void ipchild_append(char ip[16], unsigned long n)
void found(char *data, unsigned int datalen)
char remoteportstr[FMT_ULONG]
char localportstr[FMT_ULONG]
char remoteipstr[IP6_FMT]
void env(const char *s, const char *t)
unsigned long numchildren
GEN_ALLOC_typedef(GEN_ALLOC_readyplus(child_alloc, GEN_ALLOC_readyplus(struct child, GEN_ALLOC_readyplus(c, GEN_ALLOC_readyplus(len, GEN_ALLOC_readyplus(a)
void drop_rules(const char *fnbase)
void ipchild_clear(char ip[16])
int ipchild_limit(char ip[16], unsigned long n)
int rules(void(*callback)(char *, unsigned int), int fd, char *ip, char *host, char *info)
void found(char *data, unsigned int datalen)
int remoteinfo(stralloc *out, char ipremote[16], uint16 portremote, char iplocal[16], uint16 portlocal, unsigned int timeout, uint32 netif)