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 "ldns/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
,
791 if(p
->querylist
&& p
->server_s
!= -1 &&
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 + random()%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 + random()%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 srandom(time(NULL
) ^ getpid());
1142 if(argc
== 1) usage(argv
);
1143 while( (c
=getopt(argc
, argv
, "b:d:f:hm:p:")) != -1) {
1149 if(atoi(optarg
)==0 && strcmp(optarg
,"0")!=0) {
1150 printf("bad delay: %s\n", optarg
);
1153 delay
= atoi(optarg
);
1159 if(!cfg_parse_memsize(optarg
, &memsize
)) {
1160 printf("bad memsize: %s\n", optarg
);
1165 if(atoi(optarg
)==0 && strcmp(optarg
,"0")!=0) {
1166 printf("bad port nr: %s\n", optarg
);
1169 bindport
= atoi(optarg
);
1182 printf("bind to %s @ %d and forward to %s after %d msec\n",
1183 bindto
, bindport
, server
, delay
);
1184 service(bindto
, bindport
, server
, memsize
, delay
);