2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2005
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 "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"
41 NTSTATUS
server_service_nbtd_init(TALLOC_CTX
*);
43 static void nbtd_server_msg_send_packet(struct imessaging_context
*msg
,
51 TALLOC_CTX
*frame
= talloc_stackframe();
52 struct nbtd_server
*nbtsrv
=
53 talloc_get_type_abort(private_data
,
55 struct packet_struct
*p
= (struct packet_struct
*)data
->data
;
56 struct sockaddr_storage ss
;
57 struct socket_address
*dst
= NULL
;
58 struct nbtd_interface
*iface
= NULL
;
59 char buf
[1024] = { 0, };
60 DATA_BLOB blob
= { .length
= 0, };
62 DBG_DEBUG("Received send_packet from %u\n", (unsigned int)procid_to_pid(&src
));
64 if (data
->length
!= sizeof(struct packet_struct
)) {
65 DBG_WARNING("Discarding invalid packet length from %u\n",
66 (unsigned int)procid_to_pid(&src
));
71 if ((p
->packet_type
!= NMB_PACKET
) &&
72 (p
->packet_type
!= DGRAM_PACKET
)) {
73 DBG_WARNING("Discarding invalid packet type from %u: %d\n",
74 (unsigned int)procid_to_pid(&src
), p
->packet_type
);
79 if (p
->packet_type
== DGRAM_PACKET
) {
83 in_addr_to_sockaddr_storage(&ss
, p
->ip
);
84 dst
= socket_address_from_sockaddr_storage(frame
, &ss
, p
->port
);
90 DBG_WARNING("Discarding packet with missing port for addr[%s] "
92 dst
->addr
, (unsigned int)procid_to_pid(&src
));
97 iface
= nbtd_find_request_iface(nbtsrv
, dst
->addr
, true);
99 DBG_WARNING("Could not find iface for packet to addr[%s] "
101 dst
->addr
, (unsigned int)procid_to_pid(&src
));
109 if (p
->packet_type
== DGRAM_PACKET
) {
110 p
->packet
.dgram
.header
.source_ip
.s_addr
= interpret_addr(iface
->ip_address
);
111 p
->packet
.dgram
.header
.source_port
= 138;
114 blob
.length
= build_packet(buf
, sizeof(buf
), p
);
115 if (blob
.length
== 0) {
119 blob
.data
= (uint8_t *)buf
;
121 if (p
->packet_type
== DGRAM_PACKET
) {
122 nbt_dgram_send_raw(iface
->dgmsock
, dst
, blob
);
124 nbt_name_send_raw(iface
->nbtsock
, dst
, blob
);
130 static int nbtd_server_destructor(struct nbtd_server
*nbtsrv
)
132 struct task_server
*task
= nbtsrv
->task
;
134 pidfile_unlink(lpcfg_pid_directory(task
->lp_ctx
), "nmbd");
140 startup the nbtd task
142 static NTSTATUS
nbtd_task_init(struct task_server
*task
)
144 struct nbtd_server
*nbtsrv
;
146 struct interface
*ifaces
;
147 const char *nmbd_socket_dir
= NULL
;
148 int unexpected_clients
;
150 load_interface_list(task
, task
->lp_ctx
, &ifaces
);
152 if (iface_list_count(ifaces
) == 0) {
153 task_server_terminate(task
, "nbtd: no network interfaces configured", false);
154 return NT_STATUS_UNSUCCESSFUL
;
157 if (lpcfg_disable_netbios(task
->lp_ctx
)) {
158 task_server_terminate(task
, "nbtd: 'disable netbios = yes' set in smb.conf, shutting down nbt server", false);
159 return NT_STATUS_UNSUCCESSFUL
;
162 task_server_set_title(task
, "task[nbtd]");
164 nbtsrv
= talloc(task
, struct nbtd_server
);
165 if (nbtsrv
== NULL
) {
166 task_server_terminate(task
, "nbtd: out of memory", true);
167 return NT_STATUS_NO_MEMORY
;
171 nbtsrv
->interfaces
= NULL
;
172 nbtsrv
->bcast_interface
= NULL
;
173 nbtsrv
->wins_interface
= NULL
;
175 talloc_set_destructor(nbtsrv
, nbtd_server_destructor
);
177 /* start listening on the configured network interfaces */
178 status
= nbtd_startup_interfaces(nbtsrv
, task
->lp_ctx
, ifaces
);
179 if (!NT_STATUS_IS_OK(status
)) {
180 task_server_terminate(task
, "nbtd failed to setup interfaces", true);
184 nmbd_socket_dir
= lpcfg_parm_string(task
->lp_ctx
,
188 if (nmbd_socket_dir
== NULL
) {
189 nmbd_socket_dir
= get_dyn_NMBDSOCKETDIR();
192 unexpected_clients
= lpcfg_parm_int(task
->lp_ctx
,
195 "unexpected_clients",
198 status
= nb_packet_server_create(nbtsrv
,
199 nbtsrv
->task
->event_ctx
,
202 &nbtsrv
->unexpected_server
);
203 if (!NT_STATUS_IS_OK(status
)) {
204 task_server_terminate(task
, "nbtd failed to start unexpected_server", true);
208 nbtsrv
->sam_ctx
= samdb_connect(nbtsrv
,
211 system_session(task
->lp_ctx
),
214 if (nbtsrv
->sam_ctx
== NULL
) {
215 task_server_terminate(task
, "nbtd failed to open samdb", true);
216 return NT_STATUS_UNSUCCESSFUL
;
219 /* start the WINS server, if appropriate */
220 status
= nbtd_winsserver_init(nbtsrv
);
221 if (!NT_STATUS_IS_OK(status
)) {
222 task_server_terminate(task
, "nbtd failed to start WINS server", true);
226 nbtd_register_irpc(nbtsrv
);
228 status
= imessaging_register(task
->msg_ctx
,
231 nbtd_server_msg_send_packet
);
232 if (!NT_STATUS_IS_OK(status
)) {
233 task_server_terminate(task
, "nbtd failed imessaging_register(MSG_SEND_PACKET)", true);
237 /* start the process of registering our names on all interfaces */
238 nbtd_register_names(nbtsrv
);
240 irpc_add_name(task
->msg_ctx
, "nbt_server");
242 pidfile_create(lpcfg_pid_directory(task
->lp_ctx
), "nmbd");
249 register ourselves as a available server
251 NTSTATUS
server_service_nbtd_init(TALLOC_CTX
*ctx
)
253 static const struct service_details details
= {
254 .inhibit_fork_on_accept
= true,
255 .inhibit_pre_fork
= true,
256 .task_init
= nbtd_task_init
,
259 return register_server_service(ctx
, "nbt", &details
);