4be2caa89a1a88933a289aeae7257c57dae58f97
[abartlet/samba.git/.git] / source4 / s3compat / s3_smbd.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    use s3compat to run s3 smbd within Samba4
5
6    based on smb_samba3 by Metze
7
8    Copyright (C) Andrew Tridgell        2010
9    Copyright (C) Stefan Metzmacher      2008
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "includes.h"
26 #include "smbd/service.h"
27 #include "libcli/smb2/smb2.h"
28 #include "system/network.h"
29 #include "lib/socket/netif.h"
30 #include "param/param.h"
31 #include "dynconfig/dynconfig.h"
32 #include "smbd/process_model.h"
33 #include "tevent/tevent.h"
34 #include "s3compat_wrapper.h"
35 #include "s3compat_proto.h"
36 #include "s3compat_globals.h"
37 static struct stream_connection *samba3_conn;
38
39 struct stream_connection *s3compat_get_conn(void) 
40 {
41         return samba3_conn;
42 }
43
44 /*
45   initialise a server_context from a open socket and register a event handler
46   for reading from that socket
47 */
48 static void s3compat_smb_accept(struct stream_connection *conn)
49 {
50         if (lp_parm_bool(conn->lp_ctx, NULL, "s3compat", "gdb", false)) {
51                 char *cmd = talloc_asprintf(conn, "gnome-terminal -e \"gdb --pid %u\"", getpid());
52                 system(cmd);
53                 sleep(2);
54         }
55         DEBUG(0,(__location__ ": new s3compat smbd connection\n"));
56         samba3_conn = conn;
57
58         s3compat_set_lp_ctx(conn->lp_ctx);
59
60         s3compat_set_tevent_ctx(conn->event.ctx);
61         s3compat_set_msg_ctx(conn->msg_ctx);
62         tevent_re_initialise(conn->event.ctx);
63         s3compat_smbd_process();
64         _exit(1);
65 }
66
67 static const struct stream_server_ops s3compat_smb_stream_ops = {
68         .name                   = "s3compat",
69         .accept_connection      = s3compat_smb_accept,
70 };
71
72 /*
73   setup a listening socket on all the SMB ports for a particular address
74 */
75 static NTSTATUS s3compat_add_socket(struct tevent_context *event_context,
76                                   struct loadparm_context *lp_ctx,
77                                   const struct model_ops *model_ops,
78                                   const char *address)
79 {
80         const char **ports = lp_smb_ports(lp_ctx);
81         int i;
82         NTSTATUS status;
83
84         for (i=0;ports[i];i++) {
85                 uint16_t port = atoi(ports[i]);
86                 if (port == 0) continue;
87                 status = stream_setup_socket(event_context, lp_ctx,
88                                              model_ops, &s3compat_smb_stream_ops,
89                                              "ip", address, &port,
90                                              lp_socket_options(lp_ctx),
91                                              NULL);
92                 NT_STATUS_NOT_OK_RETURN(status);
93         }
94
95         return NT_STATUS_OK;
96 }
97
98
99 /*
100   open the smb server sockets
101 */
102 _PUBLIC_ void s3_smbd_task_init(struct task_server *task)
103 {
104         NTSTATUS status;
105         const struct model_ops *model_ops;
106         
107         model_ops = process_model_startup(task->event_ctx, "standard");
108
109         if (model_ops == NULL) {
110                 goto failed;
111         }
112
113         task_server_set_title(task, "task[s3compat_smb]");
114
115         if (lp_interfaces(task->lp_ctx)
116             && lp_bind_interfaces_only(task->lp_ctx)) {
117                 int num_interfaces;
118                 int i;
119                 struct interface *ifaces;
120
121                 load_interfaces(task, lp_interfaces(task->lp_ctx), &ifaces);
122
123                 num_interfaces = iface_count(ifaces);
124
125                 /* We have been given an interfaces line, and been
126                    told to only bind to those interfaces. Create a
127                    socket per interface and bind to only these.
128                 */
129                 for(i = 0; i < num_interfaces; i++) {
130                         const char *address = iface_n_ip(ifaces, i);
131                         status = s3compat_add_socket(task->event_ctx,
132                                                    task->lp_ctx,
133                                                    model_ops, address);
134                         if (!NT_STATUS_IS_OK(status)) goto failed;
135                 }
136         } else {
137                 /* Just bind to lp_socket_address() (usually 0.0.0.0) */
138                 status = s3compat_add_socket(task->event_ctx, task->lp_ctx,
139                                            model_ops,
140                                            lp_socket_address(task->lp_ctx));
141                 if (!NT_STATUS_IS_OK(status)) goto failed;
142         }
143
144         return;
145 failed:
146         task_server_terminate(task, "Failed to startup s3compat smb task", true);
147 }
148