OpenDNSSEC-signer  1.4.8.2
dnshandler.c
Go to the documentation of this file.
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 
32 #include "config.h"
33 #include "daemon/dnshandler.h"
34 #include "daemon/engine.h"
35 #include "shared/status.h"
36 #include "wire/buffer.h"
37 
38 #include <errno.h>
39 #include <string.h>
40 
41 static const char* dnsh_str = "dnshandler";
42 
43 static void dnshandler_handle_xfr(netio_type* netio,
44  netio_handler_type* handler, netio_events_type event_types);
45 
52 {
53  dnshandler_type* dnsh = NULL;
54  if (!allocator || !interfaces || interfaces->count <= 0) {
55  return NULL;
56  }
57  dnsh = (dnshandler_type*) allocator_alloc(allocator,
58  sizeof(dnshandler_type));
59  if (!dnsh) {
60  ods_log_error("[%s] unable to create dnshandler: "
61  "allocator_alloc() failed", dnsh_str);
62  return NULL;
63  }
64  dnsh->allocator = allocator;
65  dnsh->need_to_exit = 0;
66  dnsh->engine = NULL;
67  dnsh->interfaces = interfaces;
68  dnsh->socklist = NULL;
69  dnsh->netio = NULL;
70  dnsh->query = NULL;
71  /* setup */
72  dnsh->socklist = (socklist_type*) allocator_alloc(allocator,
73  sizeof(socklist_type));
74  if (!dnsh->socklist) {
75  ods_log_error("[%s] unable to create socklist: "
76  "allocator_alloc() failed", dnsh_str);
77  dnshandler_cleanup(dnsh);
78  return NULL;
79  }
80  dnsh->netio = netio_create(allocator);
81  if (!dnsh->netio) {
82  ods_log_error("[%s] unable to create dnshandler: "
83  "netio_create() failed", dnsh_str);
84  dnshandler_cleanup(dnsh);
85  return NULL;
86  }
87  dnsh->query = query_create();
88  if (!dnsh->query) {
89  ods_log_error("[%s] unable to create dnshandler: "
90  "query_create() failed", dnsh_str);
91  dnshandler_cleanup(dnsh);
92  return NULL;
93  }
94  dnsh->xfrhandler.fd = -1;
95  dnsh->xfrhandler.user_data = (void*) dnsh;
96  dnsh->xfrhandler.timeout = 0;
98  dnsh->xfrhandler.event_handler = dnshandler_handle_xfr;
99  return dnsh;
100 }
101 
102 
109 {
110  ods_status status = ODS_STATUS_OK;
111  ods_log_assert(dnshandler);
112  status = sock_listen(dnshandler->socklist, dnshandler->interfaces);
113  if (status != ODS_STATUS_OK) {
114  ods_log_error("[%s] unable to start: sock_listen() "
115  "failed (%s)", dnsh_str, ods_status2str(status));
116  dnshandler->thread_id = 0;
117  }
118  return status;
119 }
120 
121 
126 void
128 {
129  size_t i = 0;
130  engine_type* engine = NULL;
131  netio_handler_type* tcp_accept_handlers = NULL;
132 
133  ods_log_assert(dnshandler);
134  ods_log_assert(dnshandler->engine);
135  ods_log_debug("[%s] start", dnsh_str);
136  /* udp */
137  for (i=0; i < dnshandler->interfaces->count; i++) {
138  struct udp_data* data = NULL;
139  netio_handler_type* handler = NULL;
140  data = (struct udp_data*) allocator_alloc(dnshandler->allocator,
141  sizeof(struct udp_data));
142  if (!data) {
143  ods_log_error("[%s] unable to start: allocator_alloc() "
144  "failed", dnsh_str);
145  dnshandler->thread_id = 0;
146  engine->need_to_exit = 1;
147  break;
148  }
149  data->query = dnshandler->query;
150  data->engine = dnshandler->engine;
151  data->socket = &dnshandler->socklist->udp[i];
152  handler = (netio_handler_type*) allocator_alloc(
153  dnshandler->allocator, sizeof(netio_handler_type));
154  if (!handler) {
155  ods_log_error("[%s] unable to start: allocator_alloc() "
156  "failed", dnsh_str);
157  allocator_deallocate(dnshandler->allocator, (void*)data);
158  dnshandler->thread_id = 0;
159  engine->need_to_exit = 1;
160  break;
161  }
162  handler->fd = dnshandler->socklist->udp[i].s;
163  handler->timeout = NULL;
164  handler->user_data = data;
165  handler->event_types = NETIO_EVENT_READ;
166  handler->event_handler = sock_handle_udp;
167  ods_log_debug("[%s] add udp network handler fd %u", dnsh_str,
168  (unsigned) handler->fd);
169  netio_add_handler(dnshandler->netio, handler);
170  }
171  /* tcp */
172  tcp_accept_handlers = (netio_handler_type*) allocator_alloc(
173  dnshandler->allocator,
174  dnshandler->interfaces->count * sizeof(netio_handler_type));
175  for (i=0; i < dnshandler->interfaces->count; i++) {
176  struct tcp_accept_data* data = NULL;
177  netio_handler_type* handler = NULL;
178  data = (struct tcp_accept_data*) allocator_alloc(
179  dnshandler->allocator, sizeof(struct tcp_accept_data));
180  if (!data) {
181  ods_log_error("[%s] unable to start: allocator_alloc() "
182  "failed", dnsh_str);
183  dnshandler->thread_id = 0;
184  engine->need_to_exit = 1;
185  return;
186  }
187  data->engine = dnshandler->engine;
188  data->socket = &dnshandler->socklist->udp[i];
189  data->tcp_accept_handler_count = dnshandler->interfaces->count;
191  handler = &tcp_accept_handlers[i];
192  handler->fd = dnshandler->socklist->tcp[i].s;
193  handler->timeout = NULL;
194  handler->user_data = data;
195  handler->event_types = NETIO_EVENT_READ;
197  ods_log_debug("[%s] add tcp network handler fd %u", dnsh_str,
198  (unsigned) handler->fd);
199  netio_add_handler(dnshandler->netio, handler);
200  }
201  /* service */
202  while (dnshandler->need_to_exit == 0) {
203  ods_log_deeebug("[%s] netio dispatch", dnsh_str);
204  if (netio_dispatch(dnshandler->netio, NULL, NULL) == -1) {
205  if (errno != EINTR) {
206  ods_log_error("[%s] unable to dispatch netio: %s", dnsh_str,
207  strerror(errno));
208  break;
209  }
210  }
211  }
212  /* shutdown */
213  ods_log_debug("[%s] shutdown", dnsh_str);
214  for (i=0; i < dnshandler->interfaces->count; i++) {
215  if (dnshandler->socklist->udp[i].s != -1) {
216  close(dnshandler->socklist->udp[i].s);
217  freeaddrinfo((void*)dnshandler->socklist->udp[i].addr);
218  }
219  if (dnshandler->socklist->tcp[i].s != -1) {
220  close(dnshandler->socklist->tcp[i].s);
221  freeaddrinfo((void*)dnshandler->socklist->tcp[i].addr);
222  }
223  }
224  return;
225 }
226 
227 
232 void
234 {
235  if (dnshandler && dnshandler->thread_id) {
236  ods_thread_kill(dnshandler->thread_id, SIGHUP);
237  }
238  return;
239 }
240 
241 
246 void
247 dnshandler_fwd_notify(dnshandler_type* dnshandler, uint8_t* pkt, size_t len)
248 {
249  ssize_t nb = 0;
250  ods_log_assert(dnshandler);
251  ods_log_assert(pkt);
252  nb = send(dnshandler->xfrhandler.fd, (const void*) pkt, len, 0);
253  if (nb < 0) {
254  ods_log_error("[%s] unable to forward notify: send() failed (%s)",
255  dnsh_str, strerror(errno));
256  } else {
257  ods_log_debug("[%s] forwarded notify: %u bytes sent", dnsh_str, nb);
258  }
259  return;
260 }
261 
262 
267 static void
268 dnshandler_handle_xfr(netio_type* ATTR_UNUSED(netio),
269  netio_handler_type* handler, netio_events_type event_types)
270 {
271  dnshandler_type* dnshandler = NULL;
272  uint8_t buf[MAX_PACKET_SIZE];
273  ssize_t received = 0;
274  if (!handler) {
275  return;
276  }
277  dnshandler = (dnshandler_type*) handler->user_data;
278  ods_log_assert(event_types & NETIO_EVENT_READ);
279  received = read(dnshandler->xfrhandler.fd, &buf, MAX_PACKET_SIZE);
280  ods_log_debug("[%s] read forwarded xfr packet: %d bytes received",
281  dnsh_str, (int) received);
282  if (received == -1) {
283  ods_log_error("[%s] unable to forward xfr packet: %s", dnsh_str,
284  strerror(errno));
285  }
286  return;
287 }
288 
289 
294 void
296 {
297  allocator_type* allocator = NULL;
298  if (!dnshandler) {
299  return;
300  }
301  allocator = dnshandler->allocator;
302  netio_cleanup(dnshandler->netio);
303  query_cleanup(dnshandler->query);
304  allocator_deallocate(allocator, (void*) dnshandler->socklist);
305  allocator_deallocate(allocator, (void*) dnshandler);
306  return;
307 }
int s
Definition: sock.h:49
query_type * query_create(void)
Definition: query.c:48
socklist_type * socklist
Definition: dnshandler.h:55
query_type * query
Definition: dnshandler.h:57
void query_cleanup(query_type *q)
Definition: query.c:1098
allocator_type * allocator
Definition: dnshandler.h:51
void ods_log_debug(const char *format,...)
Definition: log.c:270
ods_status dnshandler_listen(dnshandler_type *dnshandler)
Definition: dnshandler.c:108
void * allocator_alloc(allocator_type *allocator, size_t size)
Definition: allocator.c:66
listener_type * interfaces
Definition: dnshandler.h:54
query_type * query
Definition: sock.h:69
enum ods_enum_status ods_status
Definition: status.h:90
enum netio_events_enum netio_events_type
Definition: netio.h:76
void sock_handle_udp(netio_type *ATTR_UNUSED(netio), netio_handler_type *handler, netio_events_type event_types)
Definition: sock.c:390
void ods_log_error(const char *format,...)
Definition: log.c:334
const char * ods_status2str(ods_status status)
Definition: status.c:111
void sock_handle_tcp_accept(netio_type *netio, netio_handler_type *handler, netio_events_type event_types)
Definition: sock.c:451
sock_type udp[MAX_INTERFACES]
Definition: sock.h:59
void * user_data
Definition: netio.h:119
void netio_add_handler(netio_type *netio, netio_handler_type *handler)
Definition: netio.c:58
sock_type tcp[MAX_INTERFACES]
Definition: sock.h:58
netio_type * netio_create(allocator_type *allocator)
Definition: netio.c:39
void dnshandler_signal(dnshandler_type *dnshandler)
Definition: dnshandler.c:233
netio_handler_type * tcp_accept_handlers
Definition: sock.h:80
size_t count
Definition: listener.h:84
size_t tcp_accept_handler_count
Definition: sock.h:79
unsigned need_to_exit
Definition: dnshandler.h:59
netio_event_handler_type event_handler
Definition: netio.h:131
ods_status sock_listen(socklist_type *sockets, listener_type *listener)
Definition: sock.c:293
#define MAX_PACKET_SIZE
Definition: buffer.h:49
sock_type * socket
Definition: sock.h:68
struct addrinfo * addr
Definition: sock.h:48
Definition: sock.h:66
netio_handler_type xfrhandler
Definition: dnshandler.h:58
sock_type * socket
Definition: sock.h:78
dnshandler_type * dnshandler_create(allocator_type *allocator, listener_type *interfaces)
Definition: dnshandler.c:51
netio_events_type event_types
Definition: netio.h:124
void ods_log_deeebug(const char *format,...)
Definition: log.c:254
netio_type * netio
Definition: dnshandler.h:56
void * engine
Definition: sock.h:77
void allocator_deallocate(allocator_type *allocator, void *data)
Definition: allocator.c:135
int need_to_exit
Definition: engine.h:74
ods_thread_type thread_id
Definition: dnshandler.h:52
void dnshandler_start(dnshandler_type *dnshandler)
Definition: dnshandler.c:127
struct timespec * timeout
Definition: netio.h:115
#define ods_log_assert(x)
Definition: log.h:154
void dnshandler_fwd_notify(dnshandler_type *dnshandler, uint8_t *pkt, size_t len)
Definition: dnshandler.c:247
int netio_dispatch(netio_type *netio, const struct timespec *timeout, const sigset_t *sigmask)
Definition: netio.c:203
void netio_cleanup(netio_type *netio)
Definition: netio.c:352
void * engine
Definition: sock.h:67
void dnshandler_cleanup(dnshandler_type *dnshandler)
Definition: dnshandler.c:295