torture: smbtorture test case to verify Compound related handling
[Samba.git] / source4 / nbt_server / register.c
blob4d10e9b16a23046bb4eb8a3885296c754ad6297f
1 /*
2 Unix SMB/CIFS implementation.
4 register our names
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/>.
22 #include "includes.h"
23 #include "lib/events/events.h"
24 #include "../lib/util/dlinklist.h"
25 #include "nbt_server/nbt_server.h"
26 #include "samba/service_task.h"
27 #include "libcli/composite/composite.h"
28 #include "librpc/gen_ndr/ndr_samr.h"
29 #include "nbt_server/wins/winsserver.h"
30 #include "librpc/gen_ndr/ndr_nbt.h"
31 #include "dsdb/samdb/samdb.h"
32 #include "param/param.h"
33 #include "libds/common/roles.h"
35 static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname);
38 a name refresh request has completed
40 static void refresh_completion_handler(struct nbt_name_request *req)
42 struct nbtd_iface_name *iname = talloc_get_type(req->async.private_data,
43 struct nbtd_iface_name);
44 NTSTATUS status;
45 struct nbt_name_refresh io;
46 TALLOC_CTX *tmp_ctx = talloc_new(iname);
48 status = nbt_name_refresh_recv(req, tmp_ctx, &io);
49 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
50 DEBUG(4,("Refreshed name %s with %s on interface %s\n",
51 nbt_name_string(tmp_ctx, &iname->name),
52 iname->iface->ip_address, iname->iface->bcast_address));
53 iname->registration_time = timeval_current();
54 nbtd_start_refresh_timer(iname);
55 talloc_free(tmp_ctx);
56 return;
59 iname->nb_flags |= NBT_NM_CONFLICT;
60 iname->nb_flags &= ~NBT_NM_ACTIVE;
62 if (NT_STATUS_IS_OK(status)) {
63 DEBUG(1,("Name conflict from %s refreshing name %s with %s on interface %s - %s\n",
64 io.out.reply_addr, nbt_name_string(tmp_ctx, &iname->name),
65 iname->iface->ip_address, iname->iface->bcast_address,
66 nt_errstr(nbt_rcode_to_ntstatus(io.out.rcode))));
67 } else {
68 DEBUG(1,("Error refreshing name %s with %s on interface %s - %s\n",
69 nbt_name_string(tmp_ctx, &iname->name),
70 iname->iface->ip_address, iname->iface->bcast_address,
71 nt_errstr(status)));
74 talloc_free(tmp_ctx);
79 handle name refresh timer events
81 static void name_refresh_handler(struct tevent_context *ev, struct tevent_timer *te,
82 struct timeval t, void *private_data)
84 struct nbtd_iface_name *iname = talloc_get_type(private_data, struct nbtd_iface_name);
85 struct nbtd_interface *iface = iname->iface;
86 struct nbt_name_register io;
87 struct nbt_name_request *req;
88 struct nbtd_server *nbtsrv = iface->nbtsrv;
90 /* setup a single name register request. Notice that we don't
91 use a name refresh request, as Windows and Samba3 do not
92 defend against broadcast name refresh packets. So for this
93 to be of any use at all, we need to refresh using name
94 registration packets */
95 io.in.name = iname->name;
96 io.in.dest_addr = iface->bcast_address;
97 io.in.dest_port = lpcfg_nbt_port(iface->nbtsrv->task->lp_ctx);
98 io.in.address = iface->ip_address;
99 io.in.nb_flags = iname->nb_flags;
100 io.in.ttl = iname->ttl;
101 io.in.register_demand = false;
102 io.in.broadcast = true;
103 io.in.multi_homed = false;
104 io.in.timeout = 3;
105 io.in.retries = 0;
107 nbtsrv->stats.total_sent++;
108 req = nbt_name_register_send(iface->nbtsock, &io);
109 if (req == NULL) return;
111 req->async.fn = refresh_completion_handler;
112 req->async.private_data = iname;
117 start a timer to refresh this name
119 static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname)
121 uint32_t refresh_time;
122 uint32_t max_refresh_time = lpcfg_parm_int(iname->iface->nbtsrv->task->lp_ctx, NULL, "nbtd", "max_refresh_time", 7200);
124 refresh_time = MIN(max_refresh_time, iname->ttl/2);
126 tevent_add_timer(iname->iface->nbtsrv->task->event_ctx,
127 iname,
128 timeval_add(&iname->registration_time, refresh_time, 0),
129 name_refresh_handler, iname);
132 struct nbtd_register_name_state {
133 struct nbtd_iface_name *iname;
134 struct nbt_name_register_bcast io;
138 a name registration has completed
140 static void nbtd_register_name_handler(struct tevent_req *subreq)
142 struct nbtd_register_name_state *state =
143 tevent_req_callback_data(subreq,
144 struct nbtd_register_name_state);
145 struct nbtd_iface_name *iname = state->iname;
146 NTSTATUS status;
148 status = nbt_name_register_bcast_recv(subreq);
149 TALLOC_FREE(subreq);
150 if (NT_STATUS_IS_OK(status)) {
151 /* good - nobody complained about our registration */
152 iname->nb_flags |= NBT_NM_ACTIVE;
153 DEBUG(3,("Registered %s with %s on interface %s\n",
154 nbt_name_string(state, &iname->name),
155 iname->iface->ip_address, iname->iface->bcast_address));
156 iname->registration_time = timeval_current();
157 talloc_free(state);
158 nbtd_start_refresh_timer(iname);
159 return;
162 /* someone must have replied with an objection! */
163 iname->nb_flags |= NBT_NM_CONFLICT;
165 DEBUG(1,("Error registering %s with %s on interface %s - %s\n",
166 nbt_name_string(state, &iname->name),
167 iname->iface->ip_address, iname->iface->bcast_address,
168 nt_errstr(status)));
169 talloc_free(state);
174 register a name on a network interface
176 static void nbtd_register_name_iface(struct nbtd_interface *iface,
177 const char *name, enum nbt_name_type type,
178 uint16_t nb_flags)
180 struct nbtd_iface_name *iname;
181 const char *scope = lpcfg_netbios_scope(iface->nbtsrv->task->lp_ctx);
182 struct nbtd_register_name_state *state;
183 struct tevent_req *subreq;
184 struct nbtd_server *nbtsrv = iface->nbtsrv;
186 iname = talloc(iface, struct nbtd_iface_name);
187 if (!iname) return;
189 iname->iface = iface;
190 iname->name.name = strupper_talloc(iname, name);
191 iname->name.type = type;
192 if (scope && *scope) {
193 iname->name.scope = strupper_talloc(iname, scope);
194 } else {
195 iname->name.scope = NULL;
197 iname->nb_flags = nb_flags;
198 iname->ttl = lpcfg_parm_int(iface->nbtsrv->task->lp_ctx, NULL, "nbtd", "bcast_ttl", 300000);
199 iname->registration_time = timeval_zero();
200 iname->wins_server = NULL;
202 DLIST_ADD_END(iface->names, iname);
204 if (nb_flags & NBT_NM_PERMANENT) {
205 /* permanent names are not announced and are immediately active */
206 iname->nb_flags |= NBT_NM_ACTIVE;
207 iname->ttl = 0;
208 return;
211 /* if this is the wins interface, then we need to do a special
212 wins name registration */
213 if (iface == iface->nbtsrv->wins_interface) {
214 nbtd_winsclient_register(iname);
215 return;
218 state = talloc_zero(iname, struct nbtd_register_name_state);
219 if (state == NULL) {
220 return;
223 state->iname = iname;
225 /* setup a broadcast name registration request */
226 state->io.in.name = iname->name;
227 state->io.in.dest_addr = iface->bcast_address;
228 state->io.in.dest_port = lpcfg_nbt_port(iface->nbtsrv->task->lp_ctx);
229 state->io.in.address = iface->ip_address;
230 state->io.in.nb_flags = nb_flags;
231 state->io.in.ttl = iname->ttl;
233 nbtsrv->stats.total_sent++;
235 subreq = nbt_name_register_bcast_send(state, nbtsrv->task->event_ctx,
236 iface->nbtsock, &state->io);
237 if (subreq == NULL) {
238 return;
241 tevent_req_set_callback(subreq, nbtd_register_name_handler, state);
246 register one name on all our interfaces
248 void nbtd_register_name(struct nbtd_server *nbtsrv,
249 const char *name, enum nbt_name_type type,
250 uint16_t nb_flags)
252 struct nbtd_interface *iface;
254 /* register with all the local interfaces */
255 for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
256 nbtd_register_name_iface(iface, name, type, nb_flags);
259 /* register on our general broadcast interface as a permanent name */
260 if (nbtsrv->bcast_interface) {
261 nbtd_register_name_iface(nbtsrv->bcast_interface, name, type,
262 nb_flags | NBT_NM_PERMANENT);
265 /* register with our WINS servers */
266 if (nbtsrv->wins_interface) {
267 nbtd_register_name_iface(nbtsrv->wins_interface, name, type, nb_flags);
273 register our names on all interfaces
275 void nbtd_register_names(struct nbtd_server *nbtsrv)
277 uint16_t nb_flags = NBT_NODE_M;
278 const char **aliases;
280 /* note that we don't initially mark the names "ACTIVE". They are
281 marked active once registration is successful */
282 nbtd_register_name(nbtsrv, lpcfg_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_CLIENT, nb_flags);
283 nbtd_register_name(nbtsrv, lpcfg_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_USER, nb_flags);
284 nbtd_register_name(nbtsrv, lpcfg_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_SERVER, nb_flags);
286 aliases = lpcfg_netbios_aliases(nbtsrv->task->lp_ctx);
287 while (aliases && aliases[0]) {
288 nbtd_register_name(nbtsrv, aliases[0], NBT_NAME_CLIENT, nb_flags);
289 nbtd_register_name(nbtsrv, aliases[0], NBT_NAME_SERVER, nb_flags);
290 aliases++;
293 if (lpcfg_server_role(nbtsrv->task->lp_ctx) == ROLE_ACTIVE_DIRECTORY_DC) {
294 bool is_pdc = samdb_is_pdc(nbtsrv->sam_ctx);
295 if (is_pdc) {
296 nbtd_register_name(nbtsrv, lpcfg_workgroup(nbtsrv->task->lp_ctx),
297 NBT_NAME_PDC, nb_flags);
299 nbtd_register_name(nbtsrv, lpcfg_workgroup(nbtsrv->task->lp_ctx),
300 NBT_NAME_LOGON, nb_flags | NBT_NM_GROUP);
303 nb_flags |= NBT_NM_GROUP;
304 nbtd_register_name(nbtsrv, lpcfg_workgroup(nbtsrv->task->lp_ctx), NBT_NAME_CLIENT, nb_flags);
306 nb_flags |= NBT_NM_PERMANENT;
307 nbtd_register_name(nbtsrv, "__SAMBA__", NBT_NAME_CLIENT, nb_flags);
308 nbtd_register_name(nbtsrv, "__SAMBA__", NBT_NAME_SERVER, nb_flags);
309 nbtd_register_name(nbtsrv, "*", NBT_NAME_CLIENT, nb_flags);