2 Unix SMB/CIFS implementation.
6 Copyright (C) 2010 Kai Blin <kai@samba.org>
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "smbd/service_task.h"
24 #include "smbd/service.h"
25 #include "smbd/service_stream.h"
26 #include "smbd/process_model.h"
27 #include "lib/events/events.h"
28 #include "lib/socket/socket.h"
29 #include "lib/tsocket/tsocket.h"
30 #include "libcli/util/tstream.h"
31 #include "system/network.h"
32 #include "lib/stream/packet.h"
33 #include "lib/socket/netif.h"
34 #include "dns_server/dns_server.h"
35 #include "param/param.h"
36 #include "librpc/ndr/libndr.h"
37 #include "librpc/gen_ndr/ndr_dns.h"
39 /* hold information about one dns socket */
41 struct dns_server *dns;
42 struct tsocket_address *local_address;
45 struct dns_udp_socket {
46 struct dns_socket *dns_socket;
47 struct tdgram_context *dgram;
48 struct tevent_queue *send_queue;
52 state of an open tcp connection
54 struct dns_tcp_connection {
55 /* stream connection we belong to */
56 struct stream_connection *conn;
58 /* the dns_server the connection belongs to */
59 struct dns_socket *dns_socket;
61 struct tstream_context *tstream;
63 struct tevent_queue *send_queue;
66 static void dns_tcp_terminate_connection(struct dns_tcp_connection *dnsconn, const char *reason)
68 stream_terminate_connection(dnsconn->conn, reason);
71 static void dns_tcp_recv(struct stream_connection *conn, uint16_t flags)
73 struct dns_tcp_connection *dnsconn = talloc_get_type(conn->private_data,
74 struct dns_tcp_connection);
75 /* this should never be triggered! */
76 dns_tcp_terminate_connection(dnsconn, "dns_tcp_recv: called");
79 static void dns_tcp_send(struct stream_connection *conn, uint16_t flags)
81 struct dns_tcp_connection *dnsconn = talloc_get_type(conn->private_data,
82 struct dns_tcp_connection);
83 /* this should never be triggered! */
84 dns_tcp_terminate_connection(dnsconn, "dns_tcp_send: called");
87 bool dns_process(struct dns_server *dns,
92 enum ndr_err_code ndr_err;
93 struct dns_name_packet *packet = talloc(mem_ctx, struct dns_name_packet);
94 if (packet == NULL) return false;
96 dump_data(0, in->data, in->length);
98 ndr_err = ndr_pull_struct_blob(in, packet, packet,
99 (ndr_pull_flags_fn_t)ndr_pull_dns_name_packet);
100 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
102 DEBUG(0, ("Failed to parse packet %d!\n", ndr_err));
106 NDR_PRINT_DEBUG(dns_name_packet, packet);
110 struct dns_tcp_call {
111 struct dns_tcp_connection *dns_conn;
115 struct iovec out_iov[2];
118 static void dns_tcp_call_writev_done(struct tevent_req *subreq);
120 static void dns_tcp_call_loop(struct tevent_req *subreq)
122 struct dns_tcp_connection *dns_conn = tevent_req_callback_data(subreq,
123 struct dns_tcp_connection);
124 struct dns_tcp_call *call;
128 call = talloc(dns_conn, struct dns_tcp_call);
130 dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: "
131 "no memory for dns_tcp_call");
134 call->dns_conn = dns_conn;
136 status = tstream_read_pdu_blob_recv(subreq,
140 if (!NT_STATUS_IS_OK(status)) {
143 reason = talloc_asprintf(call, "dns_tcp_call_loop: "
144 "tstream_read_pdu_blob_recv() - %s",
147 reason = nt_errstr(status);
150 dns_tcp_terminate_connection(dns_conn, reason);
154 DEBUG(10,("Received krb5 TCP packet of length %lu from %s\n",
155 (long) call->in.length,
156 tsocket_address_string(dns_conn->conn->remote_address, call)));
158 /* skip length header */
160 call->in.length -= 4;
163 ok = dns_process(dns_conn->dns_socket->dns, call, &call->in, &call->out);
165 dns_tcp_terminate_connection(dns_conn,
166 "dns_tcp_call_loop: process function failed");
170 /* First add the length of the out buffer */
171 RSIVAL(call->out_hdr, 0, call->out.length);
172 call->out_iov[0].iov_base = (char *) call->out_hdr;
173 call->out_iov[0].iov_len = 4;
175 call->out_iov[1].iov_base = (char *) call->out.data;
176 call->out_iov[1].iov_len = call->out.length;
178 subreq = tstream_writev_queue_send(call,
179 dns_conn->conn->event.ctx,
181 dns_conn->send_queue,
183 if (subreq == NULL) {
184 dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: "
185 "no memory for tstream_writev_queue_send");
188 tevent_req_set_callback(subreq, dns_tcp_call_writev_done, call);
191 * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
192 * packet_full_request_u32 provides the pdu length then.
194 subreq = tstream_read_pdu_blob_send(dns_conn,
195 dns_conn->conn->event.ctx,
197 4, /* initial_read_size */
198 packet_full_request_u32,
200 if (subreq == NULL) {
201 dns_tcp_terminate_connection(dns_conn, "dns_tcp_call_loop: "
202 "no memory for tstream_read_pdu_blob_send");
205 tevent_req_set_callback(subreq, dns_tcp_call_loop, dns_conn);
208 static void dns_tcp_call_writev_done(struct tevent_req *subreq)
210 struct dns_tcp_call *call = tevent_req_callback_data(subreq,
211 struct dns_tcp_call);
215 rc = tstream_writev_queue_recv(subreq, &sys_errno);
220 reason = talloc_asprintf(call, "dns_tcp_call_writev_done: "
221 "tstream_writev_queue_recv() - %d:%s",
222 sys_errno, strerror(sys_errno));
224 reason = "dns_tcp_call_writev_done: tstream_writev_queue_recv() failed";
227 dns_tcp_terminate_connection(call->dns_conn, reason);
231 /* We don't care about errors */
237 called when we get a new connection
239 static void dns_tcp_accept(struct stream_connection *conn)
241 struct dns_socket *dns_socket;
242 struct dns_tcp_connection *dns_conn;
243 struct tevent_req *subreq;
246 dns_conn = talloc_zero(conn, struct dns_tcp_connection);
247 if (dns_conn == NULL) {
248 stream_terminate_connection(conn,
249 "dns_tcp_accept: out of memory");
253 dns_conn->send_queue = tevent_queue_create(conn, "dns_tcp_accept");
254 if (dns_conn->send_queue == NULL) {
255 stream_terminate_connection(conn,
256 "dns_tcp_accept: out of memory");
260 dns_socket = talloc_get_type(conn->private_data, struct dns_socket);
262 TALLOC_FREE(conn->event.fde);
264 rc = tstream_bsd_existing_socket(dns_conn,
265 socket_get_fd(conn->socket),
268 stream_terminate_connection(conn,
269 "dns_tcp_accept: out of memory");
273 dns_conn->conn = conn;
274 dns_conn->dns_socket = dns_socket;
275 conn->private_data = dns_conn;
278 * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
279 * packet_full_request_u32 provides the pdu length then.
281 subreq = tstream_read_pdu_blob_send(dns_conn,
282 dns_conn->conn->event.ctx,
284 4, /* initial_read_size */
285 packet_full_request_u32,
287 if (subreq == NULL) {
288 dns_tcp_terminate_connection(dns_conn, "dns_tcp_accept: "
289 "no memory for tstream_read_pdu_blob_send");
292 tevent_req_set_callback(subreq, dns_tcp_call_loop, dns_conn);
295 static const struct stream_server_ops dns_tcp_stream_ops = {
297 .accept_connection = dns_tcp_accept,
298 .recv_handler = dns_tcp_recv,
299 .send_handler = dns_tcp_send
302 struct dns_udp_call {
303 struct tsocket_address *src;
308 static void dns_udp_call_sendto_done(struct tevent_req *subreq);
310 static void dns_udp_call_loop(struct tevent_req *subreq)
312 struct dns_udp_socket *sock = tevent_req_callback_data(subreq,
313 struct dns_udp_socket);
314 struct dns_udp_call *call;
320 call = talloc(sock, struct dns_udp_call);
326 len = tdgram_recvfrom_recv(subreq, &sys_errno,
327 call, &buf, &call->src);
335 call->in.length = len;
337 DEBUG(10,("Received krb5 UDP packet of length %lu from %s\n",
338 (long)call->in.length,
339 tsocket_address_string(call->src, call)));
342 ok = dns_process(sock->dns_socket->dns, call, &call->in, &call->out);
348 subreq = tdgram_sendto_queue_send(call,
349 sock->dns_socket->dns->task->event_ctx,
355 if (subreq == NULL) {
359 tevent_req_set_callback(subreq, dns_udp_call_sendto_done, call);
362 subreq = tdgram_recvfrom_send(sock,
363 sock->dns_socket->dns->task->event_ctx,
365 if (subreq == NULL) {
366 task_server_terminate(sock->dns_socket->dns->task,
367 "no memory for tdgram_recvfrom_send",
371 tevent_req_set_callback(subreq, dns_udp_call_loop, sock);
374 static void dns_udp_call_sendto_done(struct tevent_req *subreq)
376 struct dns_udp_call *call = tevent_req_callback_data(subreq,
377 struct dns_udp_call);
381 ret = tdgram_sendto_queue_recv(subreq, &sys_errno);
383 /* We don't care about errors */
389 start listening on the given address
391 static NTSTATUS dns_add_socket(struct dns_server *dns,
392 const struct model_ops *model_ops,
397 struct dns_socket *dns_socket;
398 struct dns_udp_socket *dns_udp_socket;
399 struct tevent_req *udpsubreq;
403 dns_socket = talloc(dns, struct dns_socket);
404 NT_STATUS_HAVE_NO_MEMORY(dns_socket);
406 dns_socket->dns = dns;
408 ret = tsocket_address_inet_from_strings(dns_socket, "ip",
410 &dns_socket->local_address);
412 status = map_nt_error_from_unix(errno);
416 status = stream_setup_socket(dns->task->event_ctx,
420 "ip", address, &port,
421 lpcfg_socket_options(dns->task->lp_ctx),
423 if (!NT_STATUS_IS_OK(status)) {
424 DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
425 address, port, nt_errstr(status)));
426 talloc_free(dns_socket);
430 dns_udp_socket = talloc(dns_socket, struct dns_udp_socket);
431 NT_STATUS_HAVE_NO_MEMORY(dns_udp_socket);
433 dns_udp_socket->dns_socket = dns_socket;
435 ret = tdgram_inet_udp_socket(dns_socket->local_address,
438 &dns_udp_socket->dgram);
440 status = map_nt_error_from_unix(errno);
441 DEBUG(0,("Failed to bind to %s:%u UDP - %s\n",
442 address, port, nt_errstr(status)));
446 dns_udp_socket->send_queue = tevent_queue_create(dns_udp_socket,
447 "dns_udp_send_queue");
448 NT_STATUS_HAVE_NO_MEMORY(dns_udp_socket->send_queue);
450 udpsubreq = tdgram_recvfrom_send(dns_udp_socket,
451 dns->task->event_ctx,
452 dns_udp_socket->dgram);
453 NT_STATUS_HAVE_NO_MEMORY(udpsubreq);
454 tevent_req_set_callback(udpsubreq, dns_udp_call_loop, dns_udp_socket);
460 setup our listening sockets on the configured network interfaces
462 static NTSTATUS dns_startup_interfaces(struct dns_server *dns, struct loadparm_context *lp_ctx,
463 struct interface *ifaces)
465 const struct model_ops *model_ops;
467 TALLOC_CTX *tmp_ctx = talloc_new(dns);
471 /* within the dns task we want to be a single process, so
472 ask for the single process model ops and pass these to the
473 stream_setup_socket() call. */
474 model_ops = process_model_startup(dns->task->event_ctx, "single");
476 DEBUG(0,("Can't find 'single' process model_ops\n"));
477 return NT_STATUS_INTERNAL_ERROR;
480 num_interfaces = iface_count(ifaces);
482 for (i=0; i<num_interfaces; i++) {
483 const char *address = talloc_strdup(tmp_ctx, iface_n_ip(ifaces, i));
485 status = dns_add_socket(dns, model_ops, "dns", address, DNS_SERVICE_PORT);
486 NT_STATUS_NOT_OK_RETURN(status);
489 talloc_free(tmp_ctx);
493 static void dns_task_init(struct task_server *task)
495 struct dns_server *dns;
497 struct interface *ifaces;
499 switch (lpcfg_server_role(task->lp_ctx)) {
500 case ROLE_STANDALONE:
501 task_server_terminate(task, "dns: no DNS required in standalone configuration", false);
503 case ROLE_DOMAIN_MEMBER:
504 task_server_terminate(task, "dns: no DNS required in member server configuration", false);
506 case ROLE_DOMAIN_CONTROLLER:
507 /* Yes, we want a DNS */
511 load_interfaces(task, lpcfg_interfaces(task->lp_ctx), &ifaces);
513 if (iface_count(ifaces) == 0) {
514 task_server_terminate(task, "dns: no network interfaces configured", false);
518 task_server_set_title(task, "task[dns]");
520 dns = talloc(task, struct dns_server);
522 task_server_terminate(task, "dns: out of memory", true);
528 status = dns_startup_interfaces(dns, task->lp_ctx, ifaces);
529 if (!NT_STATUS_IS_OK(status)) {
530 task_server_terminate(task, "dns failed to setup interfaces", true);
535 NTSTATUS server_service_dns_init(void)
537 return register_server_service("dns", dns_task_init);