OpenDNSSEC-signer  1.4.1
dnshandler.c
Go to the documentation of this file.
1 /*
2  * $Id: dnshandler.c 4518 2011-02-24 15:39:09Z matthijs $
3  *
4  * Copyright (c) 2009 NLNet Labs. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
34 #include "config.h"
35 #include "daemon/dnshandler.h"
36 #include "daemon/engine.h"
37 #include "shared/status.h"
38 #include "wire/buffer.h"
39 
40 #include <errno.h>
41 #include <string.h>
42 
43 static const char* dnsh_str = "dnshandler";
44 
45 static void dnshandler_handle_xfr(netio_type* netio,
46  netio_handler_type* handler, netio_events_type event_types);
47 
54 {
55  dnshandler_type* dnsh = NULL;
56  if (!allocator || !interfaces || interfaces->count <= 0) {
57  return NULL;
58  }
59  dnsh = (dnshandler_type*) allocator_alloc(allocator,
60  sizeof(dnshandler_type));
61  if (!dnsh) {
62  ods_log_error("[%s] unable to create dnshandler: "
63  "allocator_alloc() failed", dnsh_str);
64  return NULL;
65  }
66  dnsh->allocator = allocator;
67  dnsh->need_to_exit = 0;
68  dnsh->engine = NULL;
69  dnsh->interfaces = interfaces;
70  dnsh->socklist = NULL;
71  dnsh->netio = NULL;
72  dnsh->query = NULL;
73  /* setup */
74  dnsh->socklist = (socklist_type*) allocator_alloc(allocator,
75  sizeof(socklist_type));
76  if (!dnsh->socklist) {
77  ods_log_error("[%s] unable to create socklist: "
78  "allocator_alloc() failed", dnsh_str);
79  dnshandler_cleanup(dnsh);
80  return NULL;
81  }
82  dnsh->netio = netio_create(allocator);
83  if (!dnsh->netio) {
84  ods_log_error("[%s] unable to create dnshandler: "
85  "netio_create() failed", dnsh_str);
86  dnshandler_cleanup(dnsh);
87  return NULL;
88  }
89  dnsh->query = query_create();
90  if (!dnsh->query) {
91  ods_log_error("[%s] unable to create dnshandler: "
92  "query_create() failed", dnsh_str);
93  dnshandler_cleanup(dnsh);
94  return NULL;
95  }
96  dnsh->xfrhandler.fd = -1;
97  dnsh->xfrhandler.user_data = (void*) dnsh;
98  dnsh->xfrhandler.timeout = 0;
100  dnsh->xfrhandler.event_handler = dnshandler_handle_xfr;
101  return dnsh;
102 }
103 
104 
111 {
112  ods_status status = ODS_STATUS_OK;
113  ods_log_assert(dnshandler);
114  status = sock_listen(dnshandler->socklist, dnshandler->interfaces);
115  if (status != ODS_STATUS_OK) {
116  ods_log_error("[%s] unable to start: sock_listen() "
117  "failed (%s)", dnsh_str, ods_status2str(status));
118  dnshandler->thread_id = 0;
119  }
120  return status;
121 }
122 
123 
128 void
130 {
131  size_t i = 0;
132  engine_type* engine = NULL;
133  netio_handler_type* tcp_accept_handlers = NULL;
134 
135  ods_log_assert(dnshandler);
136  ods_log_assert(dnshandler->engine);
137  ods_log_debug("[%s] start", dnsh_str);
138  /* udp */
139  for (i=0; i < dnshandler->interfaces->count; i++) {
140  struct udp_data* data = NULL;
141  netio_handler_type* handler = NULL;
142  data = (struct udp_data*) allocator_alloc(dnshandler->allocator,
143  sizeof(struct udp_data));
144  if (!data) {
145  ods_log_error("[%s] unable to start: allocator_alloc() "
146  "failed", dnsh_str);
147  dnshandler->thread_id = 0;
148  engine->need_to_exit = 1;
149  break;
150  }
151  data->query = dnshandler->query;
152  data->engine = dnshandler->engine;
153  data->socket = &dnshandler->socklist->udp[i];
154  handler = (netio_handler_type*) allocator_alloc(
155  dnshandler->allocator, sizeof(netio_handler_type));
156  if (!handler) {
157  ods_log_error("[%s] unable to start: allocator_alloc() "
158  "failed", dnsh_str);
159  allocator_deallocate(dnshandler->allocator, (void*)data);
160  dnshandler->thread_id = 0;
161  engine->need_to_exit = 1;
162  break;
163  }
164  handler->fd = dnshandler->socklist->udp[i].s;
165  handler->timeout = NULL;
166  handler->user_data = data;
167  handler->event_types = NETIO_EVENT_READ;
168  handler->event_handler = sock_handle_udp;
169  ods_log_debug("[%s] add udp network handler fd %u", dnsh_str,
170  (unsigned) handler->fd);
171  netio_add_handler(dnshandler->netio, handler);
172  }
173  /* tcp */
174  tcp_accept_handlers = (netio_handler_type*) allocator_alloc(
175  dnshandler->allocator,
176  dnshandler->interfaces->count * sizeof(netio_handler_type));
177  for (i=0; i < dnshandler->interfaces->count; i++) {
178  struct tcp_accept_data* data = NULL;
179  netio_handler_type* handler = NULL;
180  data = (struct tcp_accept_data*) allocator_alloc(
181  dnshandler->allocator, sizeof(struct tcp_accept_data));
182  if (!data) {
183  ods_log_error("[%s] unable to start: allocator_alloc() "
184  "failed", dnsh_str);
185  dnshandler->thread_id = 0;
186  engine->need_to_exit = 1;
187  return;
188  }
189  data->engine = dnshandler->engine;
190  data->socket = &dnshandler->socklist->udp[i];
191  data->tcp_accept_handler_count = dnshandler->interfaces->count;
193  handler = &tcp_accept_handlers[i];
194  handler->fd = dnshandler->socklist->tcp[i].s;
195  handler->timeout = NULL;
196  handler->user_data = data;
197  handler->event_types = NETIO_EVENT_READ;
199  ods_log_debug("[%s] add tcp network handler fd %u", dnsh_str,
200  (unsigned) handler->fd);
201  netio_add_handler(dnshandler->netio, handler);
202  }
203  /* service */
204  while (dnshandler->need_to_exit == 0) {
205  ods_log_deeebug("[%s] netio dispatch", dnsh_str);
206  if (netio_dispatch(dnshandler->netio, NULL, NULL) == -1) {
207  if (errno != EINTR) {
208  ods_log_error("[%s] unable to dispatch netio: %s", dnsh_str,
209  strerror(errno));
210  break;
211  }
212  }
213  }
214  /* shutdown */
215  ods_log_debug("[%s] shutdown", dnsh_str);
216  for (i=0; i < dnshandler->interfaces->count; i++) {
217  if (dnshandler->socklist->udp[i].s != -1) {
218  close(dnshandler->socklist->udp[i].s);
219  freeaddrinfo((void*)dnshandler->socklist->udp[i].addr);
220  }
221  if (dnshandler->socklist->tcp[i].s != -1) {
222  close(dnshandler->socklist->tcp[i].s);
223  freeaddrinfo((void*)dnshandler->socklist->tcp[i].addr);
224  }
225  }
226  return;
227 }
228 
229 
234 void
236 {
237  if (dnshandler && dnshandler->thread_id) {
238  ods_thread_kill(dnshandler->thread_id, SIGHUP);
239  }
240  return;
241 }
242 
243 
248 void
249 dnshandler_fwd_notify(dnshandler_type* dnshandler, uint8_t* pkt, size_t len)
250 {
251  ssize_t nb = 0;
252  ods_log_assert(dnshandler);
253  ods_log_assert(pkt);
254  nb = send(dnshandler->xfrhandler.fd, (const void*) pkt, len, 0);
255  if (nb < 0) {
256  ods_log_error("[%s] unable to forward notify: send() failed (%s)",
257  dnsh_str, strerror(errno));
258  } else {
259  ods_log_debug("[%s] forwarded notify: %u bytes sent", dnsh_str, nb);
260  }
261  return;
262 }
263 
264 
269 static void
270 dnshandler_handle_xfr(netio_type* ATTR_UNUSED(netio),
271  netio_handler_type* handler, netio_events_type event_types)
272 {
273  dnshandler_type* dnshandler = NULL;
274  uint8_t buf[MAX_PACKET_SIZE];
275  ssize_t received = 0;
276  if (!handler) {
277  return;
278  }
279  dnshandler = (dnshandler_type*) handler->user_data;
280  ods_log_assert(event_types & NETIO_EVENT_READ);
281  ods_log_debug("[%s] read forwarded xfr packet", dnsh_str);
282  received = read(dnshandler->xfrhandler.fd, &buf, MAX_PACKET_SIZE);
283  if (received == -1) {
284  ods_log_debug("[%s] unable to forward xfr packet: %s", dnsh_str,
285  strerror(errno));
286  }
287  return;
288 }
289 
290 
295 void
297 {
298  allocator_type* allocator = NULL;
299  if (!dnshandler) {
300  return;
301  }
302  allocator = dnshandler->allocator;
303  netio_cleanup(dnshandler->netio);
304  query_cleanup(dnshandler->query);
305  allocator_deallocate(allocator, (void*) dnshandler->socklist);
306  allocator_deallocate(allocator, (void*) dnshandler);
307  return;
308 }
int s
Definition: sock.h:51
query_type * query_create(void)
Definition: query.c:49
socklist_type * socklist
Definition: dnshandler.h:57
query_type * query
Definition: dnshandler.h:59
void query_cleanup(query_type *q)
Definition: query.c:1043
allocator_type * allocator
Definition: dnshandler.h:53
void ods_log_debug(const char *format,...)
Definition: log.c:272
ods_status dnshandler_listen(dnshandler_type *dnshandler)
Definition: dnshandler.c:110
void * allocator_alloc(allocator_type *allocator, size_t size)
Definition: allocator.c:68
listener_type * interfaces
Definition: dnshandler.h:56
query_type * query
Definition: sock.h:71
enum ods_enum_status ods_status
Definition: status.h:89
enum netio_events_enum netio_events_type
Definition: netio.h:78
void sock_handle_udp(netio_type *ATTR_UNUSED(netio), netio_handler_type *handler, netio_events_type event_types)
Definition: sock.c:392
void ods_log_error(const char *format,...)
Definition: log.c:336
const char * ods_status2str(ods_status status)
Definition: status.c:110
void sock_handle_tcp_accept(netio_type *netio, netio_handler_type *handler, netio_events_type event_types)
Definition: sock.c:453
sock_type udp[MAX_INTERFACES]
Definition: sock.h:61
void * user_data
Definition: netio.h:121
void netio_add_handler(netio_type *netio, netio_handler_type *handler)
Definition: netio.c:60
sock_type tcp[MAX_INTERFACES]
Definition: sock.h:60
netio_type * netio_create(allocator_type *allocator)
Definition: netio.c:41
void dnshandler_signal(dnshandler_type *dnshandler)
Definition: dnshandler.c:235
netio_handler_type * tcp_accept_handlers
Definition: sock.h:82
size_t count
Definition: listener.h:86
size_t tcp_accept_handler_count
Definition: sock.h:81
unsigned need_to_exit
Definition: dnshandler.h:61
netio_event_handler_type event_handler
Definition: netio.h:133
ods_status sock_listen(socklist_type *sockets, listener_type *listener)
Definition: sock.c:295
#define MAX_PACKET_SIZE
Definition: buffer.h:49
sock_type * socket
Definition: sock.h:70
struct addrinfo * addr
Definition: sock.h:50
Definition: sock.h:68
netio_handler_type xfrhandler
Definition: dnshandler.h:60
sock_type * socket
Definition: sock.h:80
dnshandler_type * dnshandler_create(allocator_type *allocator, listener_type *interfaces)
Definition: dnshandler.c:53
netio_events_type event_types
Definition: netio.h:126
void ods_log_deeebug(const char *format,...)
Definition: log.c:256
netio_type * netio
Definition: dnshandler.h:58
void * engine
Definition: sock.h:79
void allocator_deallocate(allocator_type *allocator, void *data)
Definition: allocator.c:137
int need_to_exit
Definition: engine.h:76
ods_thread_type thread_id
Definition: dnshandler.h:54
void dnshandler_start(dnshandler_type *dnshandler)
Definition: dnshandler.c:129
struct timespec * timeout
Definition: netio.h:117
#define ods_log_assert(x)
Definition: log.h:156
void dnshandler_fwd_notify(dnshandler_type *dnshandler, uint8_t *pkt, size_t len)
Definition: dnshandler.c:249
int netio_dispatch(netio_type *netio, const struct timespec *timeout, const sigset_t *sigmask)
Definition: netio.c:205
void netio_cleanup(netio_type *netio)
Definition: netio.c:354
void * engine
Definition: sock.h:69
void dnshandler_cleanup(dnshandler_type *dnshandler)
Definition: dnshandler.c:296