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;
100 for (i = 0; i <= n; ++i) {
101 ipchild = &children.c[i];
102 if (byte_equal(ipchild->
ipaddr,16,ip)) {
106 byte_copy(ipchild->
ipaddr,16,ip);
115 struct child *ipchild = 0;
118 for (i = 0; i <= children.len; ++i) {
119 ipchild = &children.c[i];
120 if (byte_equal(ipchild->
ipaddr,16,ip)) {
121 if (ipchild->
num) --ipchild->
num;
131 for (i = 0; i <= n; ++i)
132 if (byte_equal(children.c[i].ipaddr,16,ip))
133 return children.c[i].num;
159 for (i = 0; i < 100; ++i) {
162 if (ch < 33) ch =
'?';
163 if (ch > 126) ch =
'?';
164 if (ch ==
'%') ch =
'?';
169void env(
const char *s,
const char *t)
175 logmsg(
WHO,110,DROP,B(
"unable to read: ",fnbase));
185 while ((next0 = byte_chr(
data,datalen,0)) < datalen) {
192 split = str_chr(
data + 1,
'=');
193 if (
data[1 + split] ==
'=') {
196 if (!str_diff(
data + 1,
"MAXCONIP")) {
205 data += next0; datalen -= next0;
214 logmsg(
WHO,111,FATAL,
"unable to get local address");
216 socket_ipoptionskill(t);
218 socket_tcpnodelay(t);
229 strnum[fmt_ulong(strnum,getpid())] = 0;
235 if (buffer_putsflush(&
bo,
banner) == -1)
236 logmsg(
WHO,111,FATAL,
"unable to print banner");
240 if (dns_name(&localhostsa,
localip) >= 0)
241 if (localhostsa.len) {
267 if (dns_name(&remotehostsa,
remoteip) >= 0)
268 if (remotehostsa.len) {
270 if (dns_ip6(&tmp,&remotehostsa) >= 0)
271 for (j = 0; j + 16 <= tmp.len; j += 16)
272 if (byte_equal(
remoteip,16,tmp.s + j)) {
276 if (dns_ip4(&tmp,&remotehostsa) >= 0)
277 for (j = 0; j + 4 <= tmp.len; j += 4)
278 if (byte_equal(
remoteip + 12,4,tmp.s + j)) {
292 if (!stralloc_0(&tcpremoteinfo))
drop_nomem();
310 strnum[fmt_ulong(strnum,getpid())] = 0;
311 strnum2[fmt_ulong(strnum2,
maxconip)] = 0;
312 if (!stralloc_copys(&tmp,
"tcpserver: "))
drop_nomem();
324 buffer_putflush(buffer_2,tmp.s,tmp.len);
331 env(
"PROTO",ip6_isv4mapped(
remoteip)?
"TCP":
"TCP6");
356 logmsg(
WHO,100,USAGE,
"tcpserver \
357[ -46UxXpPhHrRoOdDqQv ] \
379 strnum2[fmt_ulong(strnum2,
limit)] = 0;
380 strnum3[fmt_ulong(strnum3,
maxconip)] = 0;
381 log_who(
WHO,B(
"status: ",strnum,
"/",strnum2,
"/",strnum3));
384static void sigterm(
int dummy)
389static void sigchld(
int dummy)
394 while ((
pid = wait_nohang(&wstat)) > 0) {
396 strnum[fmt_ulong(strnum,
pid)] = 0;
397 strnum2[fmt_ulong(strnum2,wstat)] = 0;
398 log_who(
WHO,B(
"end ",strnum,
" status ",strnum2));
406int main(
int argc,
char *
const *argv)
418 while ((opt = getoptb(argc,(
char **)argv,
"146dDvqQhHrRUXx:y:t:u:g:l:b:B:c:I:pPoO")) != opteof) {
420 case '1':
flag1 = 1;
break;
421 case '4': ipflag = 1;
break;
422 case '6': ipflag = 2;
break;
432 case 'U': x = env_get(
"UID");
if (x) scan_ulong(x,&
uid);
433 x = env_get(
"GID");
if (x) scan_ulong(x,&
gid);
break;
434 case 'x':
fnrules = optarg;
break;
437 case 't': scan_ulong(optarg,&
timeout);
break;
438 case 'u': scan_ulong(optarg,&
uid);
break;
439 case 'g': scan_ulong(optarg,&
gid);
break;
441 case 'b': scan_ulong(optarg,&
backlog);
break;
442 case 'B':
banner = optarg;
break;
443 case 'c': scan_ulong(optarg,&
limit);
break;
444 case 'I':
netif = socket_getifidx(optarg);
break;
461 else if (str_equal((
char *)
hostname,
":0")) {
469 if (!x[scan_ulong(x,&u)])
472 se = getservbyname(x,
"tcp");
474 logmsg(
WHO,111,FATAL,B(
"unable to figure out port number for: ",x));
475 uint16_unpack_big((
char*)&se->s_port,&
localport);
480 if ((x = env_get(
"MAXCONIP"))) { scan_ulong(x,&u);
maxconip = u; }
484 sig_block(sig_child);
485 sig_catch(sig_child,sigchld);
486 sig_catch(sig_term,sigterm);
487 sig_ignore(sig_pipe);
492 if (!stralloc_copyb(&addresses,(
char *)V4mappedprefix,12))
drop_nomem();
494 byte_copy(
localip,16,addresses.s);
497 byte_copy(
localip,16,addresses.s);
502 if (!addresses.len) {
504 if (dns_ip_qualify(&addresses,&fqdn,&tmp) < 0)
505 logmsg(
WHO,111,FATAL,B(
"temporarily unable to figure out IP address for: ",(
char *)
hostname));
507 byte_copy(
localip,16,addresses.s);
509 for (j = 0; j < addresses.len; j += 16) {
510 if (ipflag == 1 && !ip6_isv4mapped(addresses.s + j))
continue;
511 if (ipflag == 2 && ip6_isv4mapped(addresses.s + j))
continue;
512 byte_copy(
localip,16,addresses.s + j);
516 if (addresses.len < 16)
517 logmsg(
WHO,111,FATAL,B(
"no IP address for: ",(
char *)
hostname));
524 logmsg(
WHO,111,FATAL,
"unable to create socket");
528 logmsg(
WHO,111,FATAL,
"unable to bind");
530 logmsg(
WHO,111,FATAL,
"unable to get local address");
531 if (socket_listen(s,
backlog) == -1)
532 logmsg(
WHO,111,FATAL,
"unable to listen");
537 if (
gid)
if (prot_gid(
gid) == -1)
538 logmsg(
WHO,111,FATAL,
"unable to set gid");
539 if (
uid)
if (prot_uid(
uid) == -1)
540 logmsg(
WHO,111,FATAL,
"unable to set uid");
553 buffer_puts(&
bo,
" : ");
555 buffer_puts(&
bo,
"\n");
567 sig_unblock(sig_child);
569 sig_block(sig_child);
570 if (t == -1)
continue;
580 strnum[fmt_ulong(strnum,
maxconip)] = 0;
581 logmsg(
WHO,100,WARN,B(
"ip connection limit of ",strnum,
" exceeded for: ",
remoteipstr));
594 if ((fd_move(0,t) == -1) || (fd_copy(1,0) == -1))
595 logmsg(
WHO,111,FATAL,
"unable to set up descriptors");
596 sig_uncatch(sig_child);
597 sig_unblock(sig_child);
598 sig_uncatch(sig_term);
599 sig_uncatch(sig_pipe);
601 logmsg(
WHO,111,FATAL,B(
"unable to run: ",*argv));
604 logmsg(
WHO,111,FATAL,
"unable to fork");
int remoteinfo(stralloc *out, char ipremote[16], uint16 portremote, char iplocal[16], uint16 portlocal, unsigned int timeout, uint32 netif)
int rules(void(*callback)(char *, unsigned int), int fd, char *ip, char *host, char *info)
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)