1 /*
2  * Copyright (c) 2009 NLNet Labs. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
27 /**
28  * Zone transfer handler.
29  *
30  */
31 
32 #include "config.h"
33 #include "daemon/engine.h"
34 #include "daemon/xfrhandler.h"
35 #include "duration.h"
36 #include "status.h"
37 
38 #include <errno.h>
39 #include <string.h>
40 
41 static const char* xfrh_str = "xfrhandler";
42 
43 static void xfrhandler_handle_dns(netio_type* netio,
44     netio_handler_type* handler, netio_events_type event_types);
45 
46 
47 /**
48  * Create zone transfer handler.
49  *
50  */
51 xfrhandler_type*
xfrhandler_create()52 xfrhandler_create()
53 {
54     xfrhandler_type* xfrh = NULL;
55     CHECKALLOC(xfrh = (xfrhandler_type*) malloc(sizeof(xfrhandler_type)));
56     xfrh->engine = NULL;
57     xfrh->packet = NULL;
58     xfrh->netio = NULL;
59     xfrh->tcp_set = NULL;
60     xfrh->tcp_waiting_first = NULL;
61     xfrh->udp_waiting_first = NULL;
62     xfrh->udp_waiting_last = NULL;
63     xfrh->udp_use_num = 0;
64     xfrh->start_time = 0;
65     xfrh->current_time = 0;
66     xfrh->got_time = 0;
67     xfrh->need_to_exit = 0;
68     xfrh->started = 0;
69     /* notify */
70     xfrh->notify_waiting_first = NULL;
71     xfrh->notify_waiting_last = NULL;
72     xfrh->notify_udp_num = 0;
73     /* setup */
74     xfrh->netio = netio_create();
75     if (!xfrh->netio) {
76         ods_log_error("[%s] unable to create xfrhandler: "
77             "netio_create() failed", xfrh_str);
78         xfrhandler_cleanup(xfrh);
79         return NULL;
80     }
81     xfrh->packet = buffer_create(PACKET_BUFFER_SIZE);
82     if (!xfrh->packet) {
83         ods_log_error("[%s] unable to create xfrhandler: "
84             "buffer_create() failed", xfrh_str);
85         xfrhandler_cleanup(xfrh);
86         return NULL;
87     }
88     xfrh->tcp_set = tcp_set_create();
89     if (!xfrh->tcp_set) {
90         ods_log_error("[%s] unable to create xfrhandler: "
91             "tcp_set_create() failed", xfrh_str);
92         xfrhandler_cleanup(xfrh);
93         return NULL;
94     }
95     xfrh->dnshandler.fd = -1;
96     xfrh->dnshandler.user_data = (void*) xfrh;
97     xfrh->dnshandler.timeout = 0;
98     xfrh->dnshandler.event_types = NETIO_EVENT_READ;
99     xfrh->dnshandler.event_handler = xfrhandler_handle_dns;
100     xfrh->dnshandler.free_handler = 0;
101     return xfrh;
102 }
103 
104 
105 /**
106  * Start zone transfer handler.
107  *
108  */
109 void
xfrhandler_start(xfrhandler_type * xfrhandler)110 xfrhandler_start(xfrhandler_type* xfrhandler)
111 {
112     ods_log_assert(xfrhandler);
113     ods_log_assert(xfrhandler->engine);
114     ods_log_debug("[%s] start", xfrh_str);
115     /* setup */
116     xfrhandler->start_time = time_now();
117     /* handlers */
118     netio_add_handler(xfrhandler->netio, &xfrhandler->dnshandler);
119     /* service */
120     while (xfrhandler->need_to_exit == 0) {
121         /* dispatch may block for a longer period, so current is gone */
122         xfrhandler->got_time = 0;
123         ods_log_deeebug("[%s] netio dispatch", xfrh_str);
124         if (netio_dispatch(xfrhandler->netio, NULL, NULL) == -1) {
125             if (errno != EINTR) {
126                 ods_log_error("[%s] unable to dispatch netio: %s", xfrh_str,
127                     strerror(errno));
128             }
129         }
130     }
131     /* shutdown */
132     ods_log_debug("[%s] shutdown", xfrh_str);
133 }
134 
135 
136 /**
137  * Get current time from zone transfer handler.
138  *
139  */
140 time_t
xfrhandler_time(xfrhandler_type * xfrhandler)141 xfrhandler_time(xfrhandler_type* xfrhandler)
142 {
143     if (!xfrhandler) {
144         return 0;
145     }
146     if (!xfrhandler->got_time) {
147         xfrhandler->current_time = time_now();
148         xfrhandler->got_time = 1;
149     }
150     return xfrhandler->current_time;
151 }
152 
153 
154 /**
155  * Signal zone transfer handler.
156  *
157  */
158 void
xfrhandler_signal(xfrhandler_type * xfrhandler)159 xfrhandler_signal(xfrhandler_type* xfrhandler)
160 {
161     if (xfrhandler && xfrhandler->started) {
162         janitor_thread_signal(xfrhandler->thread_id);
163     }
164 }
165 
166 
167 /**
168  * Handle forwarded dns packets.
169  *
170  */
171 static void
xfrhandler_handle_dns(netio_type * ATTR_UNUSED (netio),netio_handler_type * handler,netio_events_type event_types)172 xfrhandler_handle_dns(netio_type* ATTR_UNUSED(netio),
173     netio_handler_type* handler, netio_events_type event_types)
174 {
175     xfrhandler_type* xfrhandler = NULL;
176     uint8_t buf[MAX_PACKET_SIZE];
177     ssize_t received = 0;
178     if (!handler) {
179         return;
180     }
181     xfrhandler = (xfrhandler_type*) handler->user_data;
182     ods_log_assert(event_types & NETIO_EVENT_READ);
183     received = read(xfrhandler->dnshandler.fd, &buf, MAX_PACKET_SIZE);
184     ods_log_debug("[%s] read forwarded dns packet: %d bytes received",
185         xfrh_str, (int) received);
186     if (received == -1) {
187         ods_log_error("[%s] unable to forward dns packet: %s", xfrh_str,
188             strerror(errno));
189     }
190 }
191 
192 
193 /**
194  * Cleanup zone transfer handler.
195  *
196  */
197 void
xfrhandler_cleanup(xfrhandler_type * xfrhandler)198 xfrhandler_cleanup(xfrhandler_type* xfrhandler)
199 {
200     if (!xfrhandler) {
201         return;
202     }
203     netio_cleanup_shallow(xfrhandler->netio);
204     buffer_cleanup(xfrhandler->packet);
205     tcp_set_cleanup(xfrhandler->tcp_set);
206     free(xfrhandler);
207 }
208