int dns_resolve (const char *q, const char qtype[2]) { int r = 0; char servers[64]; iopause_fd x[1]; struct taia stamp; struct taia deadline; if (dns_resolvconfip (servers) == -1) return -1; memset (&dns_resolve_tx, 0, sizeof (dns_resolve_tx)); r = dns_transmit_start (&dns_resolve_tx, servers, 1, q, qtype, "\0\0\0\0"); if (r == -1) return -1; for (;;) { taia_now (&stamp); taia_uint (&deadline, 120); taia_add (&deadline, &deadline, &stamp); dns_transmit_io (&dns_resolve_tx, x, &deadline); iopause (x, 1, &deadline, &stamp); r = dns_transmit_get (&dns_resolve_tx, x, &stamp); if (r == -1) return -1; if (r == 1) return 0; } }
int timeoutconn(int s,char ip[4],uint16 port,unsigned int timeout) { struct taia now; struct taia deadline; iopause_fd x; if (socket_connect4(s,ip,port) == -1) { if ((errno != error_wouldblock) && (errno != error_inprogress)) return -1; x.fd = s; x.events = IOPAUSE_WRITE; taia_now(&now); taia_uint(&deadline,timeout); taia_add(&deadline,&now,&deadline); for (;;) { taia_now(&now); iopause(&x,1,&deadline,&now); if (x.revents) break; if (taia_less(&deadline,&now)) { errno = error_timeout; /* note that connect attempt is continuing */ return -1; } } if (!socket_connected(s)) return -1; } if (ndelay_off(s) == -1) return -1; return 0; }
int timeoutconn6(int s,const char ip[16],uint16 port,unsigned int scope_id,unsigned int timeout) { struct taia now; struct taia deadline; iopause_fd x; if (socket_connect6(s,ip,port,scope_id) == -1) { if ((errno != EWOULDBLOCK) && (errno != EINPROGRESS)) return -1; x.fd = s; x.events = IOPAUSE_WRITE; taia_now(&now); taia_uint(&deadline,timeout); taia_add(&deadline,&now,&deadline); for (;;) { taia_now(&now); iopause(&x,1,&deadline,&now); if (x.revents) break; if (taia_less(&deadline,&now)) { errno = ETIMEDOUT; /* note that connect attempt is continuing */ return -1; } } if (!socket_connected(s)) return -1; } if (ndelay_off(s) == -1) return -1; return 0; }
void t_timeout(int j) { struct taia now; if (!t[j].active) return; taia_now(&now); taia_uint(&t[j].timeout,10); taia_add(&t[j].timeout,&t[j].timeout,&now); }
int main() { taia_t a = TAIA_INIT; taia_t b = TAIA_INIT; taia_t t = TAIA_INIT; taia_init(&a, 0, 0, 500000000UL); taia_init(&b, 0, 0, 500000001UL); taia_add(&t, &b, &a); if ((t.nano != 1) && (t.atto != 1)) return 1; taia_now(&a); b.sec = TAI_EPOCH; taia_add(&t, &a, &b); if (a.sec == (t.sec - TAI_EPOCH)) return 0; return 2; }
static int thistcp (struct dns_transmit *d) { struct taia now; const char *ip = NULL; socketfree (d); packetfree (d); for (; d->curserver < 16; ++d->curserver) { ip = d->servers + 4 * d->curserver; if (byte_diff (ip, 4, "\0\0\0\0")) { d->query[2] = dns_random (256); d->query[3] = dns_random (256); d->s1 = 1 + socket_tcp (); if (!d->s1) { dns_transmit_free (d); return -1; } if (randombind (d) == -1) { dns_transmit_free (d); return -1; } taia_now (&now); taia_uint (&d->deadline, 10); taia_add (&d->deadline, &d->deadline, &now); if (socket_connect4 (d->s1 - 1, ip, 53) == 0) { d->pos = 0; d->tcpstate = 2; return 0; } if (errno == error_inprogress || errno == error_wouldblock) { d->tcpstate = 1; return 0; } socketfree(d); } } dns_transmit_free(d); return -1; }
int remoteinfo6(stralloc *out,char ipremote[16],uint16 portremote,char iplocal[16],uint16 portlocal,unsigned int timeout,uint32 netif) { int s; int r; if (!stralloc_copys(out,"")) return -1; taia_now(&now); taia_uint(&deadline,timeout); taia_add(&deadline,&now,&deadline); s = socket_tcp6(); if (s == -1) return -1; r = doit(out,s,ipremote,portremote,iplocal,portlocal,timeout,netif); close(s); return r; }
int ssl_timeoutaccept(SSL *ssl,unsigned int timeout) { struct taia now; struct taia deadline; iopause_fd x; int r; int rfd; int wfd; taia_now(&now); taia_uint(&deadline,timeout); taia_add(&deadline,&now,&deadline); rfd = SSL_get_fd(ssl); /* XXX */ wfd = SSL_get_fd(ssl); /* XXX */ SSL_set_accept_state(ssl); for (;;) { r = SSL_accept(ssl); if (r == 1) return 0; ssl_errno = SSL_get_error(ssl,r); errno = error_proto; if ((ssl_errno != SSL_ERROR_WANT_READ) && (ssl_errno != SSL_ERROR_WANT_WRITE)) return -1; if (ssl_errno == SSL_ERROR_WANT_READ) { x.events = IOPAUSE_READ; x.fd = rfd; if (x.fd == -1) return -1; } else { x.events = IOPAUSE_WRITE; x.fd = wfd; if (x.fd == -1) return -1; } for (;;) { taia_now(&now); iopause(&x,1,&deadline,&now); if (x.revents) break; if (taia_less(&deadline,&now)) return -1; } } }
int dns_resolvconfip(char s[64]) { struct taia now; taia_now(&now); if (taia_less(&deadline,&now)) ok = 0; if (!uses) ok = 0; if (!ok) { if (init(ip) == -1) return -1; taia_uint(&deadline,600); taia_add(&deadline,&now,&deadline); uses = 10000; ok = 1; } --uses; byte_copy(s,64,ip); return 0; }
int dns_resolvconfrewrite(stralloc *out) { struct taia now; taia_now(&now); if (taia_less(&deadline,&now)) ok = 0; if (!uses) ok = 0; if (!ok) { if (init(&rules) == -1) return -1; taia_uint(&deadline,600); taia_add(&deadline,&now,&deadline); uses = 10000; ok = 1; } --uses; if (!stralloc_copy(out,&rules)) return -1; return 0; }
int dns_resolve(const char *q,const char qtype[2]) { struct taia stamp; struct taia deadline; char servers[256]; iopause_fd x[1]; int r; if (dns_resolvconfip(servers) == -1) return -1; if (dns_transmit_start(&dns_resolve_tx,servers,1,q,qtype,V6any) == -1) return -1; for (;;) { taia_now(&stamp); taia_uint(&deadline,120); taia_add(&deadline,&deadline,&stamp); dns_transmit_io(&dns_resolve_tx,x,&deadline); iopause(x,1,&deadline,&stamp); r = dns_transmit_get(&dns_resolve_tx,x,&stamp); if (r == -1) return -1; if (r == 1) return 0; } }
int resolve(char *q,char qtype[2],char servers[256]) { struct taia stamp; struct taia deadline; iopause_fd x[1]; int r; if (dns_transmit_start(&tx,servers,0,q,qtype,V6any) == -1) return -1; for (;;) { taia_now(&stamp); taia_uint(&deadline,120); taia_add(&deadline,&deadline,&stamp); dns_transmit_io(&tx,x,&deadline); iopause(x,1,&deadline,&stamp); r = dns_transmit_get(&tx,x,&stamp); if (r == -1) return -1; if (r == 1) break; } return 0; }
int timeoutwrite(int t,int fd,const char *buf,int len) { struct taia now; struct taia deadline; iopause_fd x; taia_now(&now); taia_uint(&deadline,t); taia_add(&deadline,&now,&deadline); x.fd = fd; x.events = IOPAUSE_WRITE; for (;;) { taia_now(&now); iopause(&x,1,&deadline,&now); if (x.revents) break; if (taia_less(&deadline,&now)) { errno = error_timeout; return -1; } } return write(fd,buf,len); }
int timeoutread(int t,int fd,char *buf,int len) { struct taia now; struct taia deadline; iopause_fd x; taia_now(&now); taia_uint(&deadline,t); taia_add(&deadline,&now,&deadline); x.fd = fd; x.events = IOPAUSE_READ; for (;;) { taia_now(&now); iopause(&x,1,&deadline,&now); if (x.revents) break; if (taia_less(&deadline,&now)) { errno = ETIMEDOUT; return -1; } } return read(fd,buf,len); }
int resolve(char *q,char qtype[2],char ip[16]) { struct taia start; struct taia stamp; struct taia deadline; char servers[256]; iopause_fd x[1]; int r; taia_now(&start); byte_zero(servers,256); byte_copy(servers,16,ip); if (dns_transmit_start(&tx,servers,0,q,qtype,"\0\0\0\0") == -1) return -1; for (;;) { taia_now(&stamp); taia_uint(&deadline,120); taia_add(&deadline,&deadline,&stamp); dns_transmit_io(&tx,x,&deadline); iopause(x,1,&deadline,&stamp); r = dns_transmit_get(&tx,x,&stamp); if (r == -1) return -1; if (r == 1) break; } taia_now(&stamp); taia_sub(&stamp,&stamp,&start); taia_uint(&deadline,1); if (taia_less(&deadline,&stamp)) { buffer_put(buffer_1,querystr.s,querystr.len); buffer_puts(buffer_1,"ALERT:took more than 1 second\n"); } return 0; }
static int thisudp(struct dns_transmit *d) { const char *ip; socketfree(d); while (d->udploop < 4) { for (;d->curserver < 16;++d->curserver) { ip = d->servers + 4 * d->curserver; if (byte_diff(ip,4,"\0\0\0\0")) { d->query[2] = dns_random(256); d->query[3] = dns_random(256); d->s1 = 1 + socket_udp(); if (!d->s1) { dns_transmit_free(d); return -1; } if (randombind(d) == -1) { dns_transmit_free(d); return -1; } if (socket_connect4(d->s1 - 1,ip,53) == 0) if (send(d->s1 - 1,d->query + 2,d->querylen - 2,0) == d->querylen - 2) { struct taia now; taia_now(&now); taia_uint(&d->deadline,timeouts[d->udploop]); taia_add(&d->deadline,&d->deadline,&now); d->tcpstate = 0; return 0; } socketfree(d); } } ++d->udploop; d->curserver = 0; } dns_transmit_free(d); return -1; }
static int thistcp(struct dns_transmit *d) { struct taia now; const char *ip; socketfree(d); packetfree(d); for (;d->curserver < 16;++d->curserver) { ip = d->servers + 16 * d->curserver; if (byte_diff(ip,16,V6any)) { d->query[2] = dns_random(256); d->query[3] = dns_random(256); d->s1 = 1 + socket_tcp6(); if (!d->s1) { dns_transmit_free(d); return -1; } if (randombind(d) == -1) { dns_transmit_free(d); return -1; } taia_now(&now); taia_uint(&d->deadline,10); taia_add(&d->deadline,&d->deadline,&now); if (socket_connect6(d->s1 - 1,ip,53,d->scope_id) == 0) { d->tcpstate = 2; return 0; } if ((errno == error_inprogress) || (errno == error_wouldblock)) { d->tcpstate = 1; return 0; } socketfree(d); } } dns_transmit_free(d); return -1; }
int timeoutaccept6(int s,char ip[16],uint16 *port,unsigned int timeout,uint32 *scope_id) { struct taia now; struct taia deadline; iopause_fd x; x.fd = s; x.events = IOPAUSE_READ; taia_now(&now); taia_uint(&deadline,timeout); taia_add(&deadline,&now,&deadline); for (;;) { taia_now(&now); iopause(&x,1,&deadline,&now); if (x.revents) break; if (taia_less(&deadline,&now)) { errno = ETIMEDOUT; /* note that connect attempt is continuing */ return -1; } } if (!socket_connected(s)) return -1; if (ndelay_off(s) == -1) return -1; return socket_accept6(s,ip,port,scope_id); }
void doit(void) { iopause_fd x[2]; struct taia deadline; struct taia stamp; int wstat; int r; char ch; announce(); for (;;) { if (flagexit && !pid) return; sig_unblock(sig_child); x[0].fd = selfpipe[0]; x[0].events = IOPAUSE_READ; x[1].fd = fdcontrol; x[1].events = IOPAUSE_READ; taia_now(&stamp); taia_uint(&deadline,3600); taia_add(&deadline,&stamp,&deadline); iopause(x,2,&deadline,&stamp); sig_block(sig_child); while (read(selfpipe[0],&ch,1) == 1) ; for (;;) { r = wait_nohang(&wstat); if (!r) break; if ((r == -1) && (errno != error_intr)) break; if (r == pid) { pid = 0; pidchange(); announce(); if (flagexit) return; if (flagwant && flagwantup) trystart(); break; } } if (read(fdcontrol,&ch,1) == 1) switch(ch) { case 'd': flagwant = 1; flagwantup = 0; if (pid) { kill(pid,SIGTERM); kill(pid,SIGCONT); flagpaused = 0; } announce(); break; case 'u': flagwant = 1; flagwantup = 1; announce(); if (!pid) trystart(); break; case 'o': flagwant = 0; announce(); if (!pid) trystart(); break; case 'a': if (pid) kill(pid,SIGALRM); break; case 'h': if (pid) kill(pid,SIGHUP); break; case 'k': if (pid) kill(pid,SIGKILL); break; case 't': if (pid) kill(pid,SIGTERM); break; case 'i': if (pid) kill(pid,SIGINT); break; case 'p': flagpaused = 1; announce(); if (pid) kill(pid,SIGSTOP); break; case 'c': flagpaused = 0; announce(); if (pid) kill(pid,SIGCONT); break; case 'x': flagexit = 1; announce(); break; } } }
Taia Taia::operator + (Taia &a) { taia_t t; taia_add(&t, &data, &a.data); return Taia(t.sec, t.nano, t.atto); }
static int thisudp (struct dns_transmit *d) { const char *ip = NULL; socketfree (d); mergefree (d); while (d->udploop < 4) { for (; d->curserver < 16; ++d->curserver) { ip = d->servers + 4 * d->curserver; if (byte_diff (ip, 4, "\0\0\0\0")) { if (merge_enable && try_merge (d)) { if (merge_logger) merge_logger (ip, d->qtype, d->query + 14); return 0; } d->query[2] = dns_random (256); d->query[3] = dns_random (256); d->s1 = 1 + socket_udp (); if (!d->s1) { dns_transmit_free (d); return -1; } if (randombind (d) == -1) { dns_transmit_free (d); return -1; } if (socket_connect4 (d->s1 - 1, ip, 53) == 0) { if (send (d->s1 - 1, d->query + 2, d->querylen - 2, 0) == d->querylen - 2) { struct taia now; taia_now (&now); taia_uint (&d->deadline, timeouts[d->udploop]); taia_add (&d->deadline, &d->deadline, &now); d->tcpstate = 0; if (merge_enable) register_inprogress (d); return 0; } } socketfree (d); } } ++d->udploop; d->curserver = 0; } dns_transmit_free (d); return -1; }
int main(int argc,char **argv) { struct taia stamp; struct taia deadline; int opt; unsigned long u; int i; int j; int r; while ((opt = getopt(argc,argv,"c:l:")) != opteof) switch(opt) { case 'c': scan_ulong(optarg,&u); if (u < 1) u = 1; if (u > 1000) u = 1000; maxactive = u; break; case 'l': scan_ulong(optarg,&u); if (u < 1) u = 1; if (u > 1000000) u = 1000000; xmax = u; break; default: strerr_die1x(111,"dnsfilter: usage: dnsfilter [ -c concurrency ] [ -l lines ]"); } x = (struct line *) alloc(xmax * sizeof(struct line)); if (!x) nomem(); byte_zero(x,xmax * sizeof(struct line)); io = (iopause_fd *) alloc((xmax + 1) * sizeof(iopause_fd)); if (!io) nomem(); if (!stralloc_copys(&partial,"")) nomem(); while (flag0 || inbuflen || partial.len || xnum) { taia_now(&stamp); taia_uint(&deadline,120); taia_add(&deadline,&deadline,&stamp); iolen = 0; if (flag0) if (inbuflen < sizeof inbuf) { inio = io + iolen++; inio->fd = 0; inio->events = IOPAUSE_READ; } for (i = 0;i < xnum;++i) if (x[i].flagactive) { x[i].io = io + iolen++; dns_transmit_io(&x[i].dt,x[i].io,&deadline); } iopause(io,iolen,&deadline,&stamp); if (flag0) if (inbuflen < sizeof inbuf) if (inio->revents) { r = read(0,inbuf + inbuflen,(sizeof inbuf) - inbuflen); if (r <= 0) flag0 = 0; else inbuflen += r; } for (i = 0;i < xnum;++i) if (x[i].flagactive) { r = dns_transmit_get(&x[i].dt,x[i].io,&stamp); if (r == -1) { errout(i); x[i].flagactive = 0; --numactive; } else if (r == 1) { if (dns_name_packet(&x[i].middle,x[i].dt.packet,x[i].dt.packetlen) == -1) errout(i); if (x[i].middle.len) if (!stralloc_cats(&x[i].left,"=")) nomem(); x[i].flagactive = 0; --numactive; } } for (;;) { if (xnum && !x[0].flagactive) { buffer_put(buffer_1,x[0].left.s,x[0].left.len); buffer_put(buffer_1,x[0].middle.s,x[0].middle.len); buffer_put(buffer_1,x[0].right.s,x[0].right.len); buffer_flush(buffer_1); --xnum; tmp = x[0]; for (i = 0;i < xnum;++i) x[i] = x[i + 1]; x[xnum] = tmp; continue; } if ((xnum < xmax) && (numactive < maxactive)) { i = byte_chr(inbuf,inbuflen,'\n'); if (inbuflen && (i == inbuflen)) { if (!stralloc_catb(&partial,inbuf,inbuflen)) nomem(); inbuflen = 0; continue; } if ((i < inbuflen) || (!flag0 && partial.len)) { if (i < inbuflen) ++i; if (!stralloc_catb(&partial,inbuf,i)) nomem(); inbuflen -= i; for (j = 0;j < inbuflen;++j) inbuf[j] = inbuf[j + i]; if (partial.len) { i = byte_chr(partial.s,partial.len,'\n'); i = byte_chr(partial.s,i,'\t'); i = byte_chr(partial.s,i,' '); if (!stralloc_copyb(&x[xnum].left,partial.s,i)) nomem(); if (!stralloc_copys(&x[xnum].middle,"")) nomem(); if (!stralloc_copyb(&x[xnum].right,partial.s + i,partial.len - i)) nomem(); x[xnum].flagactive = 0; partial.len = i; if (!stralloc_0(&partial)) nomem(); if (ip4_scan(partial.s,ip)) { dns_name4_domain(name,ip); if (dns_resolvconfip(servers) == -1) strerr_die2sys(111,FATAL,"unable to read /etc/resolv.conf: "); if (dns_transmit_start(&x[xnum].dt,servers,1,name,DNS_T_PTR,"\0\0\0\0") == -1) errout(xnum); else { x[xnum].flagactive = 1; ++numactive; } } ++xnum; } partial.len = 0; continue; } } break; } } _exit(0); }
int main(int argc, char **argv) { struct stat s; time_t mtime =0; int wstat; int curdir; int pid; struct taia deadline; struct taia now; struct taia stampcheck; char ch; int i; progname =*argv++; if (! argv || ! *argv) usage(); if (**argv == '-') { switch (*(*argv +1)) { case 'P': pgrp =1; case '-': ++argv; } if (! argv || ! *argv) usage(); } sig_catch(sig_term, s_term); sig_catch(sig_hangup, s_hangup); svdir =*argv++; if (argv && *argv) { rplog =*argv; if (setup_log() != 1) { rplog =0; warn3x("log service disabled.", 0, 0); } } if ((curdir =open_read(".")) == -1) fatal("unable to open current directory", 0); coe(curdir); taia_now(&stampcheck); for (;;) { /* collect children */ for (;;) { if ((pid =wait_nohang(&wstat)) <= 0) break; for (i =0; i < svnum; i++) { if (pid == sv[i].pid) { /* runsv has gone */ sv[i].pid =0; check =1; break; } } } taia_now(&now); if (now.sec.x < (stampcheck.sec.x -3)) { /* time warp */ warn3x("time warp: resetting time stamp.", 0, 0); taia_now(&stampcheck); taia_now(&now); if (rplog) taia_now(&stamplog); } if (taia_less(&now, &stampcheck) == 0) { /* wait at least a second */ taia_uint(&deadline, 1); taia_add(&stampcheck, &now, &deadline); if (stat(svdir, &s) != -1) { if (check || \ s.st_mtime != mtime || s.st_ino != ino || s.st_dev != dev) { /* svdir modified */ if (chdir(svdir) != -1) { mtime =s.st_mtime; dev =s.st_dev; ino =s.st_ino; check =0; if (now.sec.x <= (4611686018427387914ULL +(uint64)mtime)) sleep(1); runsvdir(); while (fchdir(curdir) == -1) { warn("unable to change directory, pausing", 0); sleep(5); } } else warn("unable to change directory to ", svdir); } } else warn("unable to stat ", svdir); } if (rplog) if (taia_less(&now, &stamplog) == 0) { write(logpipe[1], ".", 1); taia_uint(&deadline, 900); taia_add(&stamplog, &now, &deadline); } /* half a second */ deadline.sec.x =0; deadline.nano =500000000UL; deadline.atto =0; taia_add(&deadline, &now, &deadline); sig_block(sig_child); if (rplog) iopause(io, 1, &deadline, &now); else iopause(0, 0, &deadline, &now); sig_unblock(sig_child); if (rplog && (io[0].revents | IOPAUSE_READ)) while (read(logpipe[0], &ch, 1) > 0) if (ch) { for (i =6; i < rploglen; i++) rplog[i -1] =rplog[i]; rplog[rploglen -1] =ch; } switch(exitsoon) { case 1: _exit(0); case 2: for (i =0; i < svnum; i++) if (sv[i].pid) kill(sv[i].pid, SIGTERM); _exit(111); } } /* for (;;) */ /* not reached */ _exit(0); }
int main (int argc, char *argv[]) { time_t t = 0; char *x = NULL; struct sigaction sa; iopause_fd *iop = NULL; int i = 0, n = 0, *udp53 = NULL; prog = strdup ((x = strrchr (argv[0], '/')) != NULL ? x + 1 : argv[0]); sa.sa_handler = handle_term; sigaction (SIGINT, &sa, NULL); sigaction (SIGTERM, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, NULL); i = check_option (argc, argv); argc -= i; argv += i; if (mode & DAEMON) { i = fork (); if (i == -1) err (-1, "could not fork a daemon process"); if (i > 0) return 0; } time (&t); memset (buf, 0, sizeof (buf)); strftime (buf, sizeof (buf), "%b-%d %Y %T %Z", localtime (&t)); warnx ("version %s: starting: %s\n", VERSION, buf); set_timezone (); if (debug_level) warnx ("TIMEZONE: %s", env_get ("TZ")); initialize (); if (!debug_level) if ((x = env_get ("DEBUG_LEVEL"))) debug_level = atol (x); warnx ("DEBUG_LEVEL set to `%d'", debug_level); if ((x = env_get ("DATALIMIT"))) { struct rlimit r; unsigned long dlimit = atol (x); if (getrlimit (RLIMIT_DATA, &r) != 0) err (-1, "could not get resource RLIMIT_DATA"); r.rlim_cur = (dlimit <= r.rlim_max) ? dlimit : r.rlim_max; if (setrlimit (RLIMIT_DATA, &r) != 0) err (-1, "could not set resource RLIMIT_DATA"); if (debug_level) warnx ("DATALIMIT set to `%ld' bytes", r.rlim_cur); } if (!(x = env_get ("IP"))) err (-1, "$IP not set"); for (i = 0; (unsigned)i < strlen (x); i++) n = (x[i] == ',') ? n+1 : n; if (!(udp53 = calloc (n+1, sizeof (int)))) err (-1, "could not allocate enough memory for udp53"); if (!(iop = calloc (n+1, sizeof (iopause_fd)))) err (-1, "could not allocate enough memory for iop"); i = n = 0; while (x[i]) { unsigned int l = 0; if (!(l = ip4_scan(x+i, ip))) errx (-1, "could not parse IP address `%s'", x + i); udp53[n] = socket_udp(); if (udp53[n] == -1) errx (-1, "could not open UDP socket"); if (socket_bind4_reuse (udp53[n], ip, server_port) == -1) errx (-1, "could not bind UDP socket"); ndelay_off (udp53[n]); socket_tryreservein (udp53[n], 65536); iop[n].fd = udp53[n]; iop[n].events = IOPAUSE_READ; n++; i += (x[i + l] == ',') ? l + 1 : l; } droproot (); while (1) { struct taia stamp; struct in_addr odst; /* original destination IP */ struct taia deadline; taia_now (&stamp); taia_uint (&deadline, 300); taia_add (&deadline, &deadline, &stamp); iopause (iop, n, &deadline, &stamp); for (i = 0; i < n; i++) { if (!iop[i].revents) continue; len = socket_recv4 (udp53[i], buf, sizeof (buf), ip, &port, &odst); if (len < 0) continue; if (!doit ()) continue; if (response_len > 512) response_tc (); /* may block for buffer space; if it fails, too bad */ len = socket_send4 (udp53[i], response, response_len, ip, port, &odst); if (len < 0) continue; if (debug_level > 1) log_querydone(qnum, response, response_len); } } return 0; }
static void doit (void) { struct taia stamp; struct taia deadline; int j = 0, r = 0, iolen = 0; for (;;) { taia_now (&stamp); taia_uint (&deadline, 120); taia_add (&deadline, &deadline, &stamp); iolen = 0; udp53io = io + iolen++; udp53io->fd = udp53; udp53io->events = IOPAUSE_READ; tcp53io = io + iolen++; tcp53io->fd = tcp53; tcp53io->events = IOPAUSE_READ; for (j = 0; j < MAXUDP; ++j) { if (u[j].active) { u[j].io = io + iolen++; query_io (&u[j].q, u[j].io, &deadline); } } for (j = 0; j < MAXTCP; ++j) { if (t[j].active) { t[j].io = io + iolen++; if (t[j].state == 0) query_io (&t[j].q, t[j].io, &deadline); else { if (taia_less (&t[j].timeout, &deadline)) deadline = t[j].timeout; t[j].io->fd = t[j].tcp; t[j].io->events = (t[j].state > 0) ? IOPAUSE_READ : IOPAUSE_WRITE; } } } iopause (io, iolen, &deadline, &stamp); for (j = 0; j < MAXUDP; ++j) { if (u[j].active) { r = query_get (&u[j].q, u[j].io, &stamp); if (r == -1) u_drop (j); if (r == 1) u_respond (j); } } for (j = 0; j < MAXTCP; ++j) { if (t[j].active) { if (t[j].io->revents) t_timeout (j); if (t[j].state == 0) { r = query_get (&t[j].q, t[j].io, &stamp); if (r == -1) t_drop (j); if (r == 1) t_respond (j); } else if (t[j].io->revents || taia_less (&t[j].timeout, &stamp)) t_rw (j); } } if (udp53io && udp53io->revents) u_new(); if (tcp53io && tcp53io->revents) t_new(); } }
void doit(int fdleft,int fdright) /* copy 0 -> fdleft, copy fdright -> 1 */ { struct taia stamp; struct taia deadline; iopause_fd x[4]; int xlen; iopause_fd *io0; iopause_fd *ioleft; iopause_fd *io1; iopause_fd *ioright; int r; for (;;) { xlen = 0; io0 = 0; if (leftstatus == 0) { io0 = &x[xlen++]; io0->fd = 0; io0->events = IOPAUSE_READ; } ioleft = 0; if (leftstatus == 1) { ioleft = &x[xlen++]; ioleft->fd = fdleft; ioleft->events = IOPAUSE_WRITE; } ioright = 0; if (rightstatus == 0) { ioright = &x[xlen++]; ioright->fd = fdright; ioright->events = IOPAUSE_READ; } io1 = 0; if (rightstatus == 1) { io1 = &x[xlen++]; io1->fd = 1; io1->events = IOPAUSE_WRITE; } taia_now(&stamp); taia_uint(&deadline,3600); taia_add(&deadline,&stamp,&deadline); iopause(x,xlen,&deadline,&stamp); if (io0 && io0->revents) { r = read(0,leftbuf,sizeof leftbuf); if (r <= 0) { leftstatus = -1; close(fdleft); buffer_puts(&ssrecord,pid); buffer_puts(&ssrecord," < [EOF]\n"); buffer_flush(&ssrecord); } else { leftstatus = 1; leftpos = 0; leftlen = r; record(leftbuf,r," < "); } } if (ioleft && ioleft->revents) { r = write(fdleft,leftbuf + leftpos,leftlen - leftpos); if (r == -1) break; leftpos += r; if (leftpos == leftlen) leftstatus = 0; } if (ioright && ioright->revents) { r = read(fdright,rightbuf,sizeof rightbuf); if (r <= 0) { buffer_puts(&ssrecord,pid); buffer_puts(&ssrecord," > [EOF]\n"); buffer_flush(&ssrecord); break; } rightstatus = 1; rightpos = 0; rightlen = r; record(rightbuf,r," > "); } if (io1 && io1->revents) { r = write(1,rightbuf + rightpos,rightlen - rightpos); if (r == -1) break; rightpos += r; if (rightpos == rightlen) rightstatus = 0; } } _exit(0); }
int dns_transmit_get(struct dns_transmit *d,const iopause_fd *x,const struct taia *when) { char udpbuf[513]; unsigned char ch; int r; int fd; errno = error_io; fd = d->s1 - 1; if (!x->revents) { if (taia_less(when,&d->deadline)) return 0; errno = error_timeout; if (d->tcpstate == 0) return nextudp(d); return nexttcp(d); } if (d->tcpstate == 0) { /* have attempted to send UDP query to each server udploop times have sent query to curserver on UDP socket s */ r = recv(fd,udpbuf,sizeof udpbuf,0); if (r <= 0) { if (errno == error_connrefused) if (d->udploop == 2) return 0; return nextudp(d); } if (r + 1 > sizeof udpbuf) return 0; if (irrelevant(d,udpbuf,r)) return 0; if (serverwantstcp(udpbuf,r)) return firsttcp(d); if (serverfailed(udpbuf,r)) { if (d->udploop == 2) return 0; return nextudp(d); } socketfree(d); d->packetlen = r; d->packet = alloc(d->packetlen); if (!d->packet) { dns_transmit_free(d); return -1; } byte_copy(d->packet,d->packetlen,udpbuf); queryfree(d); return 1; } if (d->tcpstate == 1) { /* have sent connection attempt to curserver on TCP socket s pos not defined */ if (!socket_connected(fd)) return nexttcp(d); d->pos = 0; d->tcpstate = 2; return 0; } if (d->tcpstate == 2) { /* have connection to curserver on TCP socket s have sent pos bytes of query */ r = write(fd,d->query + d->pos,d->querylen - d->pos); if (r <= 0) return nexttcp(d); d->pos += r; if (d->pos == d->querylen) { struct taia now; taia_now(&now); taia_uint(&d->deadline,10); taia_add(&d->deadline,&d->deadline,&now); d->tcpstate = 3; } return 0; } if (d->tcpstate == 3) { /* have sent entire query to curserver on TCP socket s pos not defined */ r = read(fd,&ch,1); if (r <= 0) return nexttcp(d); d->packetlen = ch; d->tcpstate = 4; return 0; } if (d->tcpstate == 4) { /* have sent entire query to curserver on TCP socket s pos not defined have received one byte of packet length into packetlen */ r = read(fd,&ch,1); if (r <= 0) return nexttcp(d); d->packetlen <<= 8; d->packetlen += ch; d->tcpstate = 5; d->pos = 0; d->packet = alloc(d->packetlen); if (!d->packet) { dns_transmit_free(d); return -1; } return 0; } if (d->tcpstate == 5) { /* have sent entire query to curserver on TCP socket s have received entire packet length into packetlen packet is allocated have received pos bytes of packet */ r = read(fd,d->packet + d->pos,d->packetlen - d->pos); if (r <= 0) return nexttcp(d); d->pos += r; if (d->pos < d->packetlen) return 0; socketfree(d); if (irrelevant(d,d->packet,d->packetlen)) return nexttcp(d); if (serverwantstcp(d->packet,d->packetlen)) return nexttcp(d); if (serverfailed(d->packet,d->packetlen)) return nexttcp(d); queryfree(d); return 1; } return 0; }
void doio(void) { iopause_fd x[2]; struct taia deadline; struct taia now; struct taia timeout; if (! stralloc_ready(&encinbuf, bufsizein)) die_nomem(); encin.buf =encin.start =encin.end =encinbuf.s; encin.size =bufsizein; if (! stralloc_ready(&decinbuf, bufsizein)) die_nomem(); decin.buf =decin.start =decin.end =decinbuf.s; decin.size =bufsizein; if (! stralloc_ready(&encoubuf, bufsizeou)) die_nomem(); encou.buf =encou.start =encou.end =encoubuf.s; encou.size =bufsizeou; if (! stralloc_ready(&decoubuf, bufsizeou)) die_nomem(); decou.buf =decou.start =decou.end =decoubuf.s; decou.size =bufsizeou; if (client) { rc =matrixSslEncodeClientHello(ssl, &decou, 0); if (rc != 0) fatalx("unable to encode client hello"); if (write(fdstdou, decou.start, decou.end -decou.start) != (decou.end -decou.start)) fatal("unable to send client hello"); if (verbose > 2) info("sending client hello"); if (verbose > 2) infou("write bytes: ", decou.end -decou.start); bytesou +=decou.end -decou.start; decou.start =decou.end =decou.buf; } taia_now(&now); taia_uint(&timeout, handshake_timeout); taia_add(&timeout, &now, &timeout); for (;;) { iopause_fd *xx =x; int l =2; x[0].fd =encpipe[0]; x[0].events =IOPAUSE_READ; x[0].revents =0; x[1].fd =fdstdin; x[1].events =IOPAUSE_READ; x[1].revents =0; if ((x[0].fd == -1) || handshake) { --l; ++xx; } if (x[1].fd == -1) --l; if (! l) return; taia_now(&now); if (handshake) { if (taia_less(&timeout, &now)) { if (verbose) info("ssl handshake timeout, exit."); return; } deadline.sec =timeout.sec; deadline.nano =timeout.nano; deadline.atto =timeout.atto; } else { taia_uint(&deadline, 30); taia_add(&deadline, &now, &deadline); } iopause(xx, l, &deadline, &now); if (x[0].revents) encode(); if (x[1].revents) decode(); } }
void doit(int fdleft,int fdright) { struct taia stamp; struct taia deadline; iopause_fd x[4]; int xlen; iopause_fd *io0; iopause_fd *ioleft; iopause_fd *io1; iopause_fd *ioright; int r; int i; char ch; for (;;) { xlen = 0; io0 = 0; if (leftstatus == 0) { io0 = &x[xlen++]; io0->fd = 0; io0->events = IOPAUSE_READ; } ioleft = 0; if (leftstatus == 1) { ioleft = &x[xlen++]; ioleft->fd = fdleft; ioleft->events = IOPAUSE_WRITE; } ioright = 0; if (rightstatus == 0) { ioright = &x[xlen++]; ioright->fd = fdright; ioright->events = IOPAUSE_READ; } io1 = 0; if (rightstatus == 1) { io1 = &x[xlen++]; io1->fd = 1; io1->events = IOPAUSE_WRITE; } taia_now(&stamp); taia_uint(&deadline,3600); taia_add(&deadline,&stamp,&deadline); iopause(x,xlen,&deadline,&stamp); if (io0 && io0->revents) { r = read(0,prebuf,sizeof prebuf); if (r <= 0) { leftstatus = -1; close(fdleft); } else { leftstatus = 1; leftpos = 0; leftlen = 0; for (i = 0;i < r;++i) { ch = prebuf[i]; if (ch == '\n') if (!leftflagcr) leftbuf[leftlen++] = '\r'; leftbuf[leftlen++] = ch; leftflagcr = (ch == '\r'); } } } if (ioleft && ioleft->revents) { r = write(fdleft,leftbuf + leftpos,leftlen - leftpos); if (r == -1) break; leftpos += r; if (leftpos == leftlen) leftstatus = 0; } if (ioright && ioright->revents) { r = read(fdright,prebuf,sizeof prebuf); if (r <= 0) break; rightstatus = 1; rightpos = 0; rightlen = 0; for (i = 0;i < r;++i) { ch = prebuf[i]; if (ch == '\n') if (!rightflagcr) rightbuf[rightlen++] = '\r'; rightbuf[rightlen++] = ch; rightflagcr = (ch == '\r'); } } if (io1 && io1->revents) { r = write(1,rightbuf + rightpos,rightlen - rightpos); if (r == -1) break; rightpos += r; if (rightpos == rightlen) rightstatus = 0; } } _exit(0); }
static void doit() { iopause_fd x[2]; struct taia deadline; struct taia stamp; int wstat; long int time_cmp = 0; int r; char ch; char warn_message[2048]; int coredumped = 0; char restart_cmd[2048]; announce(); x[0].fd = selfpipe[0]; x[0].events = IOPAUSE_READ; x[1].fd = fdcontrol; x[1].events = IOPAUSE_READ; while (1) { if (flagexit && !pid) break; taia_now(&stamp); taia_uint(&deadline, 3600); taia_add(&deadline, &stamp, &deadline); sig_unblock(sig_child); iopause(x, 2, &deadline, &stamp); sig_block(sig_child); while (read(selfpipe[0], &ch, 1) == 1); while (1) { //waitpid(-1,&wstat,WNOHANG);WNOHANG : return immediately if no child has exited r = wait_nohang(&wstat); //r==0 if one or more child(ren) exit(s) but have not yet changed state if (!r) break; //r == -1 && errno == error_intr means waitpid is interrupted by a signal, we should call waitpid again. //here is not necessary cause we call waitpid with a WNOHANG argument. if (r == -1 && errno != error_intr) break; if (r == pid) { pid = 0; pidchange(); announce(); time_now = time((time_t *)0); if(time_old) { time_cmp = time_now - time_old; if(time_cmp >= time_alarm) //cmp { num = 0; } time_old = time_now; } else { time_cmp = 0; time_old = time_now; } if (0 != restart_sh[0]) { if (num == INT_MAX) num = 0; num++; if (snprintf(restart_cmd, sizeof(restart_cmd), "%s %d", restart_sh, num) > 1) { system(restart_cmd); write_log(fdlog, NOTICE, "restart_cmd: ", restart_cmd, " is called.\n"); } } else { if (WCOREDUMP(wstat)) { have_coredumped++; coredumped = 1; } bzero(warn_message, 2048); create_warn_message(warn_message, coredumped); write_log(fdlog, NOTICE, "service exited", coredumped ? " with coredump" : "", "!\n"); coredumped = 0; if (!closealarm && alarm_interval > 0 && have_tried++ == 0) { alarm(alarm_interval); do_alarm(warn_message); } if (flagexit || (alarm_interval > 0 && have_tried > max_tries && max_tries > 0) || (alarm_interval > 0 && have_coredumped > max_tries_if_coredumped && max_tries_if_coredumped > 0)) { write_log(fdlog, NOTICE, "supervise refused to restart ", service, " any more and exited itself!\n"); alarm(0); return; } } if (flagwant && flagwantup) { write_log(fdlog, NOTICE, "supervise is trying to restart ", service, "...\n"); trystart(); } break; } } if (read(fdcontrol, &ch, 1) != 1) continue; switch(ch) { // -s: Silent. Do not alarm any more. case 's': closealarm = 1; announce(); break; case 'n': closealarm = 0; announce(); break; case 'r': parse_conf(); break; // -d: Down. If the service is running, send it a TERM signal and then a CONT signal. // After it stops, do not restart it. case 'd': flagwant = 1; flagwantup = 0; if (pid) { kill(pid, SIGTERM); kill(pid, SIGCONT); flagpaused = 0; } announce(); break; // -u: Up. If the service is not running, start it. If the service stops, restart it. case 'u': flagwant = 1; flagwantup = 1; announce(); if (!pid) trystart(); break; // -o: Once. If the service is not running, start it. Do not restart it if it stops. case 'o': flagwant = 0; announce(); if (!pid) trystart(); break; // -a: Alarm. Send the service an ALRM signal. case 'a': if (pid) kill(pid, SIGALRM); break; // -h: Hangup. Send the service a HUP signal. case 'h': if (pid) kill(pid, SIGHUP); break; // -k: Kill. Send the service a KILL signal. case 'k': if (pid) kill(pid, SIGKILL); break; //* -t: Terminate. Send the service a TERM signal. case 't': if (pid) kill(pid, SIGTERM); break; // -i: Interrupt. Send the service an INT signal. case 'i': if (pid) kill(pid, SIGINT); break; // -p: Pause. Send the service a STOP signal. case 'p': flagpaused = 1; announce(); if (pid) kill(pid, SIGSTOP); break; // -c: Continue. Send the service a CONT signal. case 'c': flagpaused = 0; announce(); if (pid) kill(pid, SIGCONT); break; // -x: Exit. supervise will exit as soon as the service is down. If you use this option on a //stable system, you're doing something wrong; supervise is designed to run forever. case 'x': flagexit = 1; announce(); break; } //end switch } //end while }