2 * testcode/delayer.c - debug program that delays queries to a server.
4 * Copyright (c) 2008, NLnet Labs. All rights reserved.
6 * This software is open source.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
19 * Neither the name of the NLNET LABS nor the names of its contributors may
20 * be used to endorse or promote products derived from this software without
21 * specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
29 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 * This program delays queries made. It performs as a proxy to another
40 * server and delays queries to it.
51 #include "util/net_help.h"
52 #include "util/config_file.h"
53 #include "sldns/sbuffer.h"
56 /** number of reads per select for delayer */
57 #define TRIES_PER_SELECT 100
67 /** low mark, items start here */
69 /** high mark, items end here */
74 * List of proxy fds that return replies from the server to our clients.
77 /** the fd to listen for replies from server */
79 /** last time this was used */
80 struct timeval lastuse;
82 struct sockaddr_storage addr;
85 /** number of queries waiting (in total) */
87 /** number of queries sent to server (in total) */
89 /** numberof answers returned to client (in total) */
91 /** how many times repurposed */
93 /** next in proxylist */
98 * An item that has to be TCP relayed
100 struct tcp_send_list {
105 /** time when the item can be transmitted on */
107 /** how much of the item has already been transmitted */
110 struct tcp_send_list* next;
114 * List of TCP proxy fd pairs to TCP connect client to server
117 /** the fd to listen for client query */
119 /** the fd to listen for server answer */
122 /** remote client address */
123 struct sockaddr_storage addr;
124 /** length of address */
126 /** timeout on this entry */
127 struct timeval timeout;
129 /** list of query items to send to server */
130 struct tcp_send_list* querylist;
131 /** last in query list */
132 struct tcp_send_list* querylast;
133 /** list of answer items to send to client */
134 struct tcp_send_list* answerlist;
135 /** last in answerlist */
136 struct tcp_send_list* answerlast;
139 struct tcp_proxy* next;
142 /** usage information for delayer */
143 static void usage(char* argv[])
145 printf("usage: %s [options]\n", argv[0]);
146 printf(" -f addr : use addr, forward to that server, @port.\n");
147 printf(" -b addr : bind to this address to listen.\n");
148 printf(" -p port : bind to this port (use 0 for random).\n");
149 printf(" -m mem : use this much memory for waiting queries.\n");
150 printf(" -d delay: UDP queries are delayed n milliseconds.\n");
151 printf(" TCP is delayed twice (on send, on recv).\n");
152 printf(" -h : this help message\n");
156 /** timeval compare, t1 < t2 */
158 dl_tv_smaller(struct timeval* t1, const struct timeval* t2)
161 if(t1->tv_sec < t2->tv_sec)
163 if(t1->tv_sec == t2->tv_sec &&
164 t1->tv_usec < t2->tv_usec)
170 /** timeval add, t1 += t2 */
172 dl_tv_add(struct timeval* t1, const struct timeval* t2)
175 t1->tv_sec += t2->tv_sec;
176 t1->tv_usec += t2->tv_usec;
177 while(t1->tv_usec > 1000000) {
178 t1->tv_usec -= 1000000;
184 /** timeval subtract, t1 -= t2 */
186 dl_tv_subtract(struct timeval* t1, const struct timeval* t2)
189 t1->tv_sec -= t2->tv_sec;
190 if(t1->tv_usec >= t2->tv_usec) {
191 t1->tv_usec -= t2->tv_usec;
194 t1->tv_usec = 1000000-(t2->tv_usec-t1->tv_usec);
200 /** create new ring buffer */
201 static struct ringbuf*
202 ring_create(size_t sz)
204 struct ringbuf* r = (struct ringbuf*)calloc(1, sizeof(*r));
205 if(!r) fatal_exit("out of memory");
206 r->buf = (uint8_t*)malloc(sz);
207 if(!r->buf) fatal_exit("out of memory");
214 /** delete ring buffer */
216 ring_delete(struct ringbuf* r)
223 /** add entry to ringbuffer */
225 ring_add(struct ringbuf* r, sldns_buffer* pkt, struct timeval* now,
226 struct timeval* delay, struct proxy* p)
228 /* time -- proxy* -- 16bitlen -- message */
229 uint16_t len = (uint16_t)sldns_buffer_limit(pkt);
232 uint8_t* where = NULL;
233 log_assert(sldns_buffer_limit(pkt) <= 65535);
234 needed = sizeof(when) + sizeof(p) + sizeof(len) + len;
235 /* put item into ringbuffer */
236 if(r->low < r->high) {
237 /* used part is in the middle */
238 if(r->size - r->high >= needed) {
239 where = r->buf + r->high;
241 } else if(r->low > needed) {
242 /* wrap around ringbuffer */
243 /* make sure r->low == r->high means empty */
244 /* so r->low == r->high cannot be used to signify
245 * a completely full ringbuf */
246 if(r->size - r->high > sizeof(when)+sizeof(p)) {
247 /* zero entry at end of buffer */
248 memset(r->buf+r->high, 0,
249 sizeof(when)+sizeof(p));
255 log_warn("warning: mem full, dropped message");
260 if(r->high == r->low) {
264 /* unused part is in the middle */
265 /* so ringbuffer has wrapped around */
266 } else if(r->low - r->high > needed) {
267 where = r->buf + r->high;
270 log_warn("warning: mem full, dropped message");
275 dl_tv_add(&when, delay);
276 /* copy it at where part */
277 log_assert(where != NULL);
278 memmove(where, &when, sizeof(when));
279 memmove(where+sizeof(when), &p, sizeof(p));
280 memmove(where+sizeof(when)+sizeof(p), &len, sizeof(len));
281 memmove(where+sizeof(when)+sizeof(p)+sizeof(len),
282 sldns_buffer_begin(pkt), len);
285 /** see if the ringbuffer is empty */
287 ring_empty(struct ringbuf* r)
289 return (r->low == r->high);
292 /** peek at timevalue for next item in ring */
293 static struct timeval*
294 ring_peek_time(struct ringbuf* r)
298 return (struct timeval*)&r->buf[r->low];
301 /** get entry from ringbuffer */
303 ring_pop(struct ringbuf* r, sldns_buffer* pkt, struct timeval* tv,
306 /* time -- proxy* -- 16bitlen -- message */
308 uint8_t* where = NULL;
310 if(r->low == r->high)
312 where = r->buf + r->low;
313 memmove(tv, where, sizeof(*tv));
314 memmove(p, where+sizeof(*tv), sizeof(*p));
315 memmove(&len, where+sizeof(*tv)+sizeof(*p), sizeof(len));
316 memmove(sldns_buffer_begin(pkt),
317 where+sizeof(*tv)+sizeof(*p)+sizeof(len), len);
318 sldns_buffer_set_limit(pkt, (size_t)len);
319 done = sizeof(*tv)+sizeof(*p)+sizeof(len)+len;
321 if(r->low < r->high) {
322 /* used part in middle */
323 log_assert(r->high - r->low >= done);
326 /* unused part in middle */
327 log_assert(r->size - r->low >= done);
329 if(r->size - r->low > sizeof(*tv)+sizeof(*p)) {
330 /* see if it is zeroed; means end of buffer */
332 memmove(&pz, r->buf+r->low+sizeof(*tv), sizeof(pz));
337 if(r->low == r->high) {
338 r->low = 0; /* reset if empty */
344 /** signal handler global info */
345 static volatile int do_quit = 0;
347 /** signal handler for user quit */
348 static RETSIGTYPE delayer_sigh(int sig)
350 printf("exit on signal %d\n", sig);
354 /** send out waiting packets */
356 service_send(struct ringbuf* ring, struct timeval* now, sldns_buffer* pkt,
357 struct sockaddr_storage* srv_addr, socklen_t srv_len)
362 while(!ring_empty(ring) &&
363 dl_tv_smaller(ring_peek_time(ring), now)) {
364 /* this items needs to be sent out */
365 if(!ring_pop(ring, pkt, &tv, &p))
366 fatal_exit("ringbuf error: pop failed");
367 verbose(1, "send out query %d.%6.6d",
368 (unsigned)tv.tv_sec, (unsigned)tv.tv_usec);
369 log_addr(1, "from client", &p->addr, p->addr_len);
371 sent = sendto(p->s, (void*)sldns_buffer_begin(pkt),
372 sldns_buffer_limit(pkt), 0,
373 (struct sockaddr*)srv_addr, srv_len);
376 log_err("sendto: %s", strerror(errno));
378 log_err("sendto: %s", wsa_strerror(WSAGetLastError()));
380 } else if(sent != (ssize_t)sldns_buffer_limit(pkt)) {
381 log_err("sendto: partial send");
388 /** do proxy for one readable client */
390 do_proxy(struct proxy* p, int retsock, sldns_buffer* pkt)
394 for(i=0; i<TRIES_PER_SELECT; i++) {
395 r = recv(p->s, (void*)sldns_buffer_begin(pkt),
396 sldns_buffer_capacity(pkt), 0);
399 if(errno == EAGAIN || errno == EINTR)
401 log_err("recv: %s", strerror(errno));
403 if(WSAGetLastError() == WSAEINPROGRESS ||
404 WSAGetLastError() == WSAEWOULDBLOCK)
406 log_err("recv: %s", wsa_strerror(WSAGetLastError()));
410 sldns_buffer_set_limit(pkt, (size_t)r);
411 log_addr(1, "return reply to client", &p->addr, p->addr_len);
412 /* send reply back to the real client */
414 r = sendto(retsock, (void*)sldns_buffer_begin(pkt), (size_t)r,
415 0, (struct sockaddr*)&p->addr, p->addr_len);
418 log_err("sendto: %s", strerror(errno));
420 log_err("sendto: %s", wsa_strerror(WSAGetLastError()));
426 /** proxy return replies to clients */
428 service_proxy(fd_set* rset, int retsock, struct proxy* proxies,
429 sldns_buffer* pkt, struct timeval* now)
432 for(p = proxies; p; p = p->next) {
433 if(FD_ISSET(p->s, rset)) {
435 do_proxy(p, retsock, pkt);
440 /** find or else create proxy for this remote client */
442 find_create_proxy(struct sockaddr_storage* from, socklen_t from_len,
443 fd_set* rorig, int* max, struct proxy** proxies, int serv_ip6,
444 struct timeval* now, struct timeval* reuse_timeout)
448 for(p = *proxies; p; p = p->next) {
449 if(sockaddr_cmp(from, from_len, &p->addr, p->addr_len)==0)
452 /* possibly: reuse lapsed entries */
453 for(p = *proxies; p; p = p->next) {
454 if(p->numwait > p->numsent || p->numsent > p->numreturn)
457 dl_tv_subtract(&t, &p->lastuse);
458 if(dl_tv_smaller(&t, reuse_timeout))
461 verbose(1, "reuse existing entry");
462 memmove(&p->addr, from, from_len);
463 p->addr_len = from_len;
468 p = (struct proxy*)calloc(1, sizeof(*p));
469 if(!p) fatal_exit("out of memory");
470 p->s = socket(serv_ip6?AF_INET6:AF_INET, SOCK_DGRAM, 0);
473 fatal_exit("socket: %s", strerror(errno));
475 fatal_exit("socket: %s", wsa_strerror(WSAGetLastError()));
478 fd_set_nonblock(p->s);
479 memmove(&p->addr, from, from_len);
480 p->addr_len = from_len;
483 FD_SET(FD_SET_T p->s, rorig);
489 /** recv new waiting packets */
491 service_recv(int s, struct ringbuf* ring, sldns_buffer* pkt,
492 fd_set* rorig, int* max, struct proxy** proxies,
493 struct sockaddr_storage* srv_addr, socklen_t srv_len,
494 struct timeval* now, struct timeval* delay, struct timeval* reuse)
497 struct sockaddr_storage from;
501 for(i=0; i<TRIES_PER_SELECT; i++) {
502 from_len = (socklen_t)sizeof(from);
503 len = recvfrom(s, (void*)sldns_buffer_begin(pkt),
504 sldns_buffer_capacity(pkt), 0,
505 (struct sockaddr*)&from, &from_len);
508 if(errno == EAGAIN || errno == EINTR)
510 fatal_exit("recvfrom: %s", strerror(errno));
512 if(WSAGetLastError() == WSAEWOULDBLOCK ||
513 WSAGetLastError() == WSAEINPROGRESS)
515 fatal_exit("recvfrom: %s",
516 wsa_strerror(WSAGetLastError()));
519 sldns_buffer_set_limit(pkt, (size_t)len);
520 /* find its proxy element */
521 p = find_create_proxy(&from, from_len, rorig, max, proxies,
522 addr_is_ip6(srv_addr, srv_len), now, reuse);
523 if(!p) fatal_exit("error: cannot find or create proxy");
525 ring_add(ring, pkt, now, delay, p);
527 log_addr(1, "recv from client", &p->addr, p->addr_len);
531 /** delete tcp proxy */
533 tcp_proxy_delete(struct tcp_proxy* p)
535 struct tcp_send_list* s, *sn;
538 log_addr(1, "delete tcp proxy", &p->addr, p->addr_len);
555 if(p->server_s != -1)
558 closesocket(p->client_s);
559 if(p->server_s != -1)
560 closesocket(p->server_s);
565 /** accept new TCP connections, and set them up */
567 service_tcp_listen(int s, fd_set* rorig, int* max, struct tcp_proxy** proxies,
568 struct sockaddr_storage* srv_addr, socklen_t srv_len,
569 struct timeval* now, struct timeval* tcp_timeout)
572 struct sockaddr_storage addr;
575 newfd = accept(s, (struct sockaddr*)&addr, &addr_len);
578 if(errno == EAGAIN || errno == EINTR)
580 fatal_exit("accept: %s", strerror(errno));
582 if(WSAGetLastError() == WSAEWOULDBLOCK ||
583 WSAGetLastError() == WSAEINPROGRESS ||
584 WSAGetLastError() == WSAECONNRESET)
586 fatal_exit("accept: %s", wsa_strerror(WSAGetLastError()));
589 p = (struct tcp_proxy*)calloc(1, sizeof(*p));
590 if(!p) fatal_exit("out of memory");
591 memmove(&p->addr, &addr, addr_len);
592 p->addr_len = addr_len;
593 log_addr(1, "new tcp proxy", &p->addr, p->addr_len);
595 p->server_s = socket(addr_is_ip6(srv_addr, srv_len)?AF_INET6:AF_INET,
597 if(p->server_s == -1) {
599 fatal_exit("tcp socket: %s", strerror(errno));
601 fatal_exit("tcp socket: %s", wsa_strerror(WSAGetLastError()));
604 fd_set_nonblock(p->client_s);
605 fd_set_nonblock(p->server_s);
606 if(connect(p->server_s, (struct sockaddr*)srv_addr, srv_len) == -1) {
608 if(errno != EINPROGRESS) {
609 log_err("tcp connect: %s", strerror(errno));
613 if(WSAGetLastError() != WSAEWOULDBLOCK &&
614 WSAGetLastError() != WSAEINPROGRESS) {
615 log_err("tcp connect: %s",
616 wsa_strerror(WSAGetLastError()));
617 closesocket(p->server_s);
618 closesocket(p->client_s);
625 dl_tv_add(&p->timeout, tcp_timeout);
627 /* listen to client and server */
628 FD_SET(FD_SET_T p->client_s, rorig);
629 FD_SET(FD_SET_T p->server_s, rorig);
630 if(p->client_s+1 > *max)
631 *max = p->client_s+1;
632 if(p->server_s+1 > *max)
633 *max = p->server_s+1;
635 /* add into proxy list */
640 /** relay TCP, read a part */
642 tcp_relay_read(int s, struct tcp_send_list** first,
643 struct tcp_send_list** last, struct timeval* now,
644 struct timeval* delay, sldns_buffer* pkt)
646 struct tcp_send_list* item;
647 ssize_t r = recv(s, (void*)sldns_buffer_begin(pkt),
648 sldns_buffer_capacity(pkt), 0);
651 if(errno == EINTR || errno == EAGAIN)
653 log_err("tcp read: %s", strerror(errno));
655 if(WSAGetLastError() == WSAEINPROGRESS ||
656 WSAGetLastError() == WSAEWOULDBLOCK)
658 log_err("tcp read: %s", wsa_strerror(WSAGetLastError()));
662 /* connection closed */
665 item = (struct tcp_send_list*)malloc(sizeof(*item));
667 log_err("out of memory");
670 verbose(1, "read item len %d", (int)r);
671 item->len = (size_t)r;
672 item->item = memdup(sldns_buffer_begin(pkt), item->len);
675 log_err("out of memory");
680 dl_tv_add(&item->wait, delay);
685 (*last)->next = item;
693 /** relay TCP, write a part */
695 tcp_relay_write(int s, struct tcp_send_list** first,
696 struct tcp_send_list** last, struct timeval* now)
699 struct tcp_send_list* p;
702 /* is the item ready? */
703 if(!dl_tv_smaller(&p->wait, now))
706 r = send(s, (void*)(p->item + p->done), p->len - p->done, 0);
709 if(errno == EAGAIN || errno == EINTR)
711 log_err("tcp write: %s", strerror(errno));
713 if(WSAGetLastError() == WSAEWOULDBLOCK ||
714 WSAGetLastError() == WSAEINPROGRESS)
716 log_err("tcp write: %s",
717 wsa_strerror(WSAGetLastError()));
725 p->done += (size_t)r;
726 verbose(1, "write item %d of %d", (int)p->done, (int)p->len);
727 if(p->done >= p->len) {
741 /** perform TCP relaying */
743 service_tcp_relay(struct tcp_proxy** tcp_proxies, struct timeval* now,
744 struct timeval* delay, struct timeval* tcp_timeout, sldns_buffer* pkt,
745 fd_set* rset, fd_set* rorig, fd_set* worig)
747 struct tcp_proxy* p, **prev;
753 dl_tv_add(&tout, tcp_timeout);
757 /* can we receive further queries? */
758 if(!delete_it && FD_ISSET(p->client_s, rset)) {
760 log_addr(1, "read tcp query", &p->addr, p->addr_len);
761 if(!tcp_relay_read(p->client_s, &p->querylist,
762 &p->querylast, now, delay, pkt))
765 /* can we receive further answers? */
766 if(!delete_it && p->server_s != -1 &&
767 FD_ISSET(p->server_s, rset)) {
769 log_addr(1, "read tcp answer", &p->addr, p->addr_len);
770 if(!tcp_relay_read(p->server_s, &p->answerlist,
771 &p->answerlast, now, delay, pkt)) {
775 closesocket(p->server_s);
777 FD_CLR(FD_SET_T p->server_s, worig);
778 FD_CLR(FD_SET_T p->server_s, rorig);
782 /* can we send on further queries */
783 if(!delete_it && p->querylist && p->server_s != -1) {
785 if(dl_tv_smaller(&p->querylist->wait, now))
786 log_addr(1, "write tcp query",
787 &p->addr, p->addr_len);
788 if(!tcp_relay_write(p->server_s, &p->querylist,
792 dl_tv_smaller(&p->querylist->wait, now))
793 FD_SET(FD_SET_T p->server_s, worig);
794 else FD_CLR(FD_SET_T p->server_s, worig);
797 /* can we send on further answers */
798 if(!delete_it && p->answerlist) {
800 if(dl_tv_smaller(&p->answerlist->wait, now))
801 log_addr(1, "write tcp answer",
802 &p->addr, p->addr_len);
803 if(!tcp_relay_write(p->client_s, &p->answerlist,
804 &p->answerlast, now))
806 if(p->answerlist && dl_tv_smaller(&p->answerlist->wait,
808 FD_SET(FD_SET_T p->client_s, worig);
809 else FD_CLR(FD_SET_T p->client_s, worig);
810 if(!p->answerlist && p->server_s == -1)
814 /* does this entry timeout? (unused too long) */
815 if(dl_tv_smaller(&p->timeout, now)) {
819 struct tcp_proxy* np = p->next;
821 FD_CLR(FD_SET_T p->client_s, rorig);
822 FD_CLR(FD_SET_T p->client_s, worig);
823 if(p->server_s != -1) {
824 FD_CLR(FD_SET_T p->server_s, rorig);
825 FD_CLR(FD_SET_T p->server_s, worig);
837 /** find waiting time */
839 service_findwait(struct timeval* now, struct timeval* wait,
840 struct ringbuf* ring, struct tcp_proxy* tcplist)
842 /* first item is the time to wait */
843 struct timeval* peek = ring_peek_time(ring);
848 /* also for TCP list the first in sendlists is the time to wait */
849 for(p=tcplist; p; p=p->next) {
853 if(dl_tv_smaller(&p->timeout, &tcv))
855 if(p->querylist && dl_tv_smaller(&p->querylist->wait, &tcv))
856 tcv = p->querylist->wait;
857 if(p->answerlist && dl_tv_smaller(&p->answerlist->wait, &tcv))
858 tcv = p->answerlist->wait;
861 /* peek can be unaligned */
862 /* use wait as a temp variable */
863 memmove(wait, peek, sizeof(*wait));
866 else if(dl_tv_smaller(wait, &tcv))
872 dl_tv_subtract(wait, now);
879 /** clear proxy list */
881 proxy_list_clear(struct proxy* p)
888 port = (int)ntohs(((struct sockaddr_in*)&p->addr)->sin_port);
889 if(addr_is_ip6(&p->addr, p->addr_len)) {
890 if(inet_ntop(AF_INET6,
891 &((struct sockaddr_in6*)&p->addr)->sin6_addr,
892 from, (socklen_t)sizeof(from)) == 0)
893 (void)strlcpy(from, "err", sizeof(from));
895 if(inet_ntop(AF_INET,
896 &((struct sockaddr_in*)&p->addr)->sin_addr,
897 from, (socklen_t)sizeof(from)) == 0)
898 (void)strlcpy(from, "err", sizeof(from));
900 printf("client[%d]: last %s@%d of %d : %u in, %u out, "
901 "%u returned\n", i++, from, port, (int)p->numreuse+1,
902 (unsigned)p->numwait, (unsigned)p->numsent,
903 (unsigned)p->numreturn);
914 /** clear TCP proxy list */
916 tcp_proxy_list_clear(struct tcp_proxy* p)
918 struct tcp_proxy* np;
926 /** delayer service loop */
928 service_loop(int udp_s, int listen_s, struct ringbuf* ring,
929 struct timeval* delay, struct timeval* reuse,
930 struct sockaddr_storage* srv_addr, socklen_t srv_len,
935 struct timeval now, wait;
936 int max, have_wait = 0;
937 struct proxy* proxies = NULL;
938 struct tcp_proxy* tcp_proxies = NULL;
939 struct timeval tcp_timeout;
940 tcp_timeout.tv_sec = 120;
941 tcp_timeout.tv_usec = 0;
945 FD_SET(FD_SET_T udp_s, &rorig);
946 FD_SET(FD_SET_T listen_s, &rorig);
949 if(listen_s + 1 > max) max = listen_s + 1;
951 /* wait for events */
955 verbose(1, "wait for %d.%6.6d",
956 (unsigned)wait.tv_sec, (unsigned)wait.tv_usec);
957 else verbose(1, "wait");
958 if(select(max, &rset, &wset, NULL, have_wait?&wait:NULL) < 0) {
959 if(errno == EAGAIN || errno == EINTR)
961 fatal_exit("select: %s", strerror(errno));
963 /* get current time */
964 if(gettimeofday(&now, NULL) < 0) {
965 if(errno == EAGAIN || errno == EINTR)
967 fatal_exit("gettimeofday: %s", strerror(errno));
969 verbose(1, "process at %u.%6.6u\n",
970 (unsigned)now.tv_sec, (unsigned)now.tv_usec);
971 /* sendout delayed queries to master server (frees up buffer)*/
972 service_send(ring, &now, pkt, srv_addr, srv_len);
973 /* proxy return replies */
974 service_proxy(&rset, udp_s, proxies, pkt, &now);
975 /* see what can be received to start waiting */
976 service_recv(udp_s, ring, pkt, &rorig, &max, &proxies,
977 srv_addr, srv_len, &now, delay, reuse);
978 /* see if there are new tcp connections */
979 service_tcp_listen(listen_s, &rorig, &max, &tcp_proxies,
980 srv_addr, srv_len, &now, &tcp_timeout);
981 /* service tcp connections */
982 service_tcp_relay(&tcp_proxies, &now, delay, &tcp_timeout,
983 pkt, &rset, &rorig, &worig);
984 /* see what next timeout is (if any) */
985 have_wait = service_findwait(&now, &wait, ring, tcp_proxies);
987 proxy_list_clear(proxies);
988 tcp_proxy_list_clear(tcp_proxies);
991 /** delayer main service routine */
993 service(const char* bind_str, int bindport, const char* serv_str,
994 size_t memsize, int delay_msec)
996 struct sockaddr_storage bind_addr, srv_addr;
997 socklen_t bind_len, srv_len;
998 struct ringbuf* ring = ring_create(memsize);
999 struct timeval delay, reuse;
1003 delay.tv_sec = delay_msec / 1000;
1004 delay.tv_usec = (delay_msec % 1000)*1000;
1006 reuse = delay; /* reuse is max(4*delay, 1 second) */
1007 dl_tv_add(&reuse, &delay);
1008 dl_tv_add(&reuse, &delay);
1009 dl_tv_add(&reuse, &delay);
1010 if(reuse.tv_sec == 0)
1012 if(!extstrtoaddr(serv_str, &srv_addr, &srv_len)) {
1013 printf("cannot parse forward address: %s\n", serv_str);
1016 pkt = sldns_buffer_new(65535);
1018 fatal_exit("out of memory");
1019 if( signal(SIGINT, delayer_sigh) == SIG_ERR ||
1021 signal(SIGHUP, delayer_sigh) == SIG_ERR ||
1024 signal(SIGQUIT, delayer_sigh) == SIG_ERR ||
1027 signal(SIGBREAK, delayer_sigh) == SIG_ERR ||
1030 signal(SIGALRM, delayer_sigh) == SIG_ERR ||
1032 signal(SIGTERM, delayer_sigh) == SIG_ERR)
1033 fatal_exit("could not bind to signal");
1035 if((s = socket(str_is_ip6(bind_str)?AF_INET6:AF_INET,
1036 SOCK_DGRAM, 0)) == -1) {
1038 fatal_exit("socket: %s", strerror(errno));
1040 fatal_exit("socket: %s", wsa_strerror(WSAGetLastError()));
1045 bindport = 1024 + arc4random()%64000;
1049 if(!ipstrtoaddr(bind_str, bindport, &bind_addr, &bind_len)) {
1050 printf("cannot parse listen address: %s\n", bind_str);
1053 if(bind(s, (struct sockaddr*)&bind_addr, bind_len) == -1) {
1055 log_err("bind: %s", strerror(errno));
1057 log_err("bind: %s", wsa_strerror(WSAGetLastError()));
1060 fatal_exit("cannot bind any port");
1061 bindport = 1024 + arc4random()%64000;
1066 if((listen_s = socket(str_is_ip6(bind_str)?AF_INET6:AF_INET,
1067 SOCK_STREAM, 0)) == -1) {
1069 fatal_exit("tcp socket: %s", strerror(errno));
1071 fatal_exit("tcp socket: %s", wsa_strerror(WSAGetLastError()));
1077 if(setsockopt(listen_s, SOL_SOCKET, SO_REUSEADDR, (void*)&on,
1078 (socklen_t)sizeof(on)) < 0)
1080 fatal_exit("setsockopt(.. SO_REUSEADDR ..) failed: %s",
1083 fatal_exit("setsockopt(.. SO_REUSEADDR ..) failed: %s",
1084 wsa_strerror(WSAGetLastError()));
1088 if(bind(listen_s, (struct sockaddr*)&bind_addr, bind_len) == -1) {
1090 fatal_exit("tcp bind: %s", strerror(errno));
1092 fatal_exit("tcp bind: %s", wsa_strerror(WSAGetLastError()));
1095 if(listen(listen_s, 5) == -1) {
1097 fatal_exit("tcp listen: %s", strerror(errno));
1099 fatal_exit("tcp listen: %s", wsa_strerror(WSAGetLastError()));
1102 fd_set_nonblock(listen_s);
1103 printf("listening on port: %d\n", bindport);
1107 service_loop(s, listen_s, ring, &delay, &reuse, &srv_addr, srv_len,
1111 verbose(1, "cleanup");
1117 closesocket(listen_s);
1119 sldns_buffer_free(pkt);
1123 /** getopt global, in case header files fail to declare it. */
1125 /** getopt global, in case header files fail to declare it. */
1126 extern char* optarg;
1128 /** main program for delayer */
1129 int main(int argc, char** argv)
1131 int c; /* defaults */
1132 const char* server = "127.0.0.1@53";
1133 const char* bindto = "0.0.0.0";
1135 size_t memsize = 10*1024*1024;
1140 log_ident_set("delayer");
1141 if(argc == 1) usage(argv);
1142 while( (c=getopt(argc, argv, "b:d:f:hm:p:")) != -1) {
1148 if(atoi(optarg)==0 && strcmp(optarg,"0")!=0) {
1149 printf("bad delay: %s\n", optarg);
1152 delay = atoi(optarg);
1158 if(!cfg_parse_memsize(optarg, &memsize)) {
1159 printf("bad memsize: %s\n", optarg);
1164 if(atoi(optarg)==0 && strcmp(optarg,"0")!=0) {
1165 printf("bad port nr: %s\n", optarg);
1168 bindport = atoi(optarg);
1181 printf("bind to %s @ %d and forward to %s after %d msec\n",
1182 bindto, bindport, server, delay);
1183 service(bindto, bindport, server, memsize, delay);