Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : NBT server task
5 :
6 : Copyright (C) Andrew Tridgell 2005
7 :
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.
12 :
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.
17 :
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/>.
20 : */
21 :
22 : #include "includes.h"
23 : #include "samba/service_task.h"
24 : #include "samba/service.h"
25 : #include "nbt_server/nbt_server.h"
26 : #include "nbt_server/wins/winsserver.h"
27 : #include "system/network.h"
28 : #include "lib/socket/netif.h"
29 : #include "auth/auth.h"
30 : #include "dsdb/samdb/samdb.h"
31 : #include "param/param.h"
32 : #include "dynconfig/dynconfig.h"
33 : #include "lib/util/pidfile.h"
34 : #include "lib/util/util_net.h"
35 : #include "lib/socket/socket.h"
36 : #include "../source3/include/fstring.h"
37 : #include "../source3/libsmb/nmblib.h"
38 : #include "../source3/libsmb/unexpected.h"
39 : #include "../source3/lib/util_procid.h"
40 :
41 : NTSTATUS server_service_nbtd_init(TALLOC_CTX *);
42 :
43 15 : static void nbtd_server_msg_send_packet(struct imessaging_context *msg,
44 : void *private_data,
45 : uint32_t msg_type,
46 : struct server_id src,
47 : size_t num_fds,
48 : int *fds,
49 : DATA_BLOB *data)
50 : {
51 15 : TALLOC_CTX *frame = talloc_stackframe();
52 0 : struct nbtd_server *nbtsrv =
53 15 : talloc_get_type_abort(private_data,
54 : struct nbtd_server);
55 15 : struct packet_struct *p = (struct packet_struct *)data->data;
56 0 : struct sockaddr_storage ss;
57 15 : struct socket_address *dst = NULL;
58 15 : struct nbtd_interface *iface = NULL;
59 15 : char buf[1024] = { 0, };
60 15 : DATA_BLOB blob = { .length = 0, };
61 :
62 15 : DBG_DEBUG("Received send_packet from %u\n", (unsigned int)procid_to_pid(&src));
63 :
64 15 : if (data->length != sizeof(struct packet_struct)) {
65 0 : DBG_WARNING("Discarding invalid packet length from %u\n",
66 : (unsigned int)procid_to_pid(&src));
67 0 : TALLOC_FREE(frame);
68 0 : return;
69 : }
70 :
71 15 : if ((p->packet_type != NMB_PACKET) &&
72 15 : (p->packet_type != DGRAM_PACKET)) {
73 0 : DBG_WARNING("Discarding invalid packet type from %u: %d\n",
74 : (unsigned int)procid_to_pid(&src), p->packet_type);
75 0 : TALLOC_FREE(frame);
76 0 : return;
77 : }
78 :
79 15 : if (p->packet_type == DGRAM_PACKET) {
80 15 : p->port = 138;
81 : }
82 :
83 15 : in_addr_to_sockaddr_storage(&ss, p->ip);
84 15 : dst = socket_address_from_sockaddr_storage(frame, &ss, p->port);
85 15 : if (dst == NULL) {
86 0 : TALLOC_FREE(frame);
87 0 : return;
88 : }
89 15 : if (p->port == 0) {
90 0 : DBG_WARNING("Discarding packet with missing port for addr[%s] "
91 : "from %u\n",
92 : dst->addr, (unsigned int)procid_to_pid(&src));
93 0 : TALLOC_FREE(frame);
94 0 : return;
95 : }
96 :
97 15 : iface = nbtd_find_request_iface(nbtsrv, dst->addr, true);
98 15 : if (iface == NULL) {
99 0 : DBG_WARNING("Could not find iface for packet to addr[%s] "
100 : "from %u\n",
101 : dst->addr, (unsigned int)procid_to_pid(&src));
102 0 : TALLOC_FREE(frame);
103 0 : return;
104 : }
105 :
106 15 : p->recv_fd = -1;
107 15 : p->send_fd = -1;
108 :
109 15 : if (p->packet_type == DGRAM_PACKET) {
110 15 : p->packet.dgram.header.source_ip.s_addr = interpret_addr(iface->ip_address);
111 15 : p->packet.dgram.header.source_port = 138;
112 : }
113 :
114 15 : blob.length = build_packet(buf, sizeof(buf), p);
115 15 : if (blob.length == 0) {
116 0 : TALLOC_FREE(frame);
117 0 : return;
118 : }
119 15 : blob.data = (uint8_t *)buf;
120 :
121 15 : if (p->packet_type == DGRAM_PACKET) {
122 15 : nbt_dgram_send_raw(iface->dgmsock, dst, blob);
123 : } else {
124 0 : nbt_name_send_raw(iface->nbtsock, dst, blob);
125 : }
126 :
127 15 : TALLOC_FREE(frame);
128 : }
129 :
130 65 : static int nbtd_server_destructor(struct nbtd_server *nbtsrv)
131 : {
132 65 : struct task_server *task = nbtsrv->task;
133 :
134 65 : pidfile_unlink(lpcfg_pid_directory(task->lp_ctx), "nmbd");
135 :
136 65 : return 0;
137 : }
138 :
139 : /*
140 : startup the nbtd task
141 : */
142 65 : static NTSTATUS nbtd_task_init(struct task_server *task)
143 : {
144 2 : struct nbtd_server *nbtsrv;
145 2 : NTSTATUS status;
146 2 : struct interface *ifaces;
147 65 : const char *nmbd_socket_dir = NULL;
148 2 : int unexpected_clients;
149 :
150 65 : load_interface_list(task, task->lp_ctx, &ifaces);
151 :
152 65 : if (iface_list_count(ifaces) == 0) {
153 0 : task_server_terminate(task, "nbtd: no network interfaces configured", false);
154 0 : return NT_STATUS_UNSUCCESSFUL;
155 : }
156 :
157 65 : if (lpcfg_disable_netbios(task->lp_ctx)) {
158 0 : task_server_terminate(task, "nbtd: 'disable netbios = yes' set in smb.conf, shutting down nbt server", false);
159 0 : return NT_STATUS_UNSUCCESSFUL;
160 : }
161 :
162 65 : task_server_set_title(task, "task[nbtd]");
163 :
164 65 : nbtsrv = talloc(task, struct nbtd_server);
165 65 : if (nbtsrv == NULL) {
166 0 : task_server_terminate(task, "nbtd: out of memory", true);
167 0 : return NT_STATUS_NO_MEMORY;
168 : }
169 :
170 65 : nbtsrv->task = task;
171 65 : nbtsrv->interfaces = NULL;
172 65 : nbtsrv->bcast_interface = NULL;
173 65 : nbtsrv->wins_interface = NULL;
174 :
175 65 : talloc_set_destructor(nbtsrv, nbtd_server_destructor);
176 :
177 : /* start listening on the configured network interfaces */
178 65 : status = nbtd_startup_interfaces(nbtsrv, task->lp_ctx, ifaces);
179 65 : if (!NT_STATUS_IS_OK(status)) {
180 0 : task_server_terminate(task, "nbtd failed to setup interfaces", true);
181 0 : return status;
182 : }
183 :
184 65 : nmbd_socket_dir = lpcfg_parm_string(task->lp_ctx,
185 : NULL,
186 : "nmbd",
187 : "socket dir");
188 65 : if (nmbd_socket_dir == NULL) {
189 0 : nmbd_socket_dir = get_dyn_NMBDSOCKETDIR();
190 : }
191 :
192 65 : unexpected_clients = lpcfg_parm_int(task->lp_ctx,
193 : NULL,
194 : "nmbd",
195 : "unexpected_clients",
196 : 200);
197 :
198 67 : status = nb_packet_server_create(nbtsrv,
199 65 : nbtsrv->task->event_ctx,
200 : nmbd_socket_dir,
201 : unexpected_clients,
202 : &nbtsrv->unexpected_server);
203 65 : if (!NT_STATUS_IS_OK(status)) {
204 0 : task_server_terminate(task, "nbtd failed to start unexpected_server", true);
205 0 : return status;
206 : }
207 :
208 65 : nbtsrv->sam_ctx = samdb_connect(nbtsrv,
209 : task->event_ctx,
210 : task->lp_ctx,
211 : system_session(task->lp_ctx),
212 : NULL,
213 : 0);
214 65 : if (nbtsrv->sam_ctx == NULL) {
215 0 : task_server_terminate(task, "nbtd failed to open samdb", true);
216 0 : return NT_STATUS_UNSUCCESSFUL;
217 : }
218 :
219 : /* start the WINS server, if appropriate */
220 65 : status = nbtd_winsserver_init(nbtsrv);
221 65 : if (!NT_STATUS_IS_OK(status)) {
222 0 : task_server_terminate(task, "nbtd failed to start WINS server", true);
223 0 : return status;
224 : }
225 :
226 65 : nbtd_register_irpc(nbtsrv);
227 :
228 65 : status = imessaging_register(task->msg_ctx,
229 : nbtsrv,
230 : MSG_SEND_PACKET,
231 : nbtd_server_msg_send_packet);
232 65 : if (!NT_STATUS_IS_OK(status)) {
233 0 : task_server_terminate(task, "nbtd failed imessaging_register(MSG_SEND_PACKET)", true);
234 0 : return status;
235 : }
236 :
237 : /* start the process of registering our names on all interfaces */
238 65 : nbtd_register_names(nbtsrv);
239 :
240 65 : irpc_add_name(task->msg_ctx, "nbt_server");
241 :
242 65 : pidfile_create(lpcfg_pid_directory(task->lp_ctx), "nmbd");
243 :
244 65 : return NT_STATUS_OK;
245 : }
246 :
247 :
248 : /*
249 : register ourselves as a available server
250 : */
251 66 : NTSTATUS server_service_nbtd_init(TALLOC_CTX *ctx)
252 : {
253 3 : static const struct service_details details = {
254 : .inhibit_fork_on_accept = true,
255 : .inhibit_pre_fork = true,
256 : .task_init = nbtd_task_init,
257 : .post_fork = NULL
258 : };
259 66 : return register_server_service(ctx, "nbt", &details);
260 : }
|