s4:dsdb/repl: avoid reallocation of msg->elements
[Samba/gebeck_regimport.git] / source4 / nbt_server / register.c
blobf5517b249a543daee1b8a2babb64afd4529f1b88
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 "smbd/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"
34 static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname);
37 a name refresh request has completed
39 static void refresh_completion_handler(struct nbt_name_request *req)
41 struct nbtd_iface_name *iname = talloc_get_type(req->async.private_data,
42 struct nbtd_iface_name);
43 NTSTATUS status;
44 struct nbt_name_refresh io;
45 TALLOC_CTX *tmp_ctx = talloc_new(iname);
47 status = nbt_name_refresh_recv(req, tmp_ctx, &io);
48 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
49 DEBUG(4,("Refreshed name %s with %s on interface %s\n",
50 nbt_name_string(tmp_ctx, &iname->name),
51 iname->iface->ip_address, iname->iface->bcast_address));
52 iname->registration_time = timeval_current();
53 nbtd_start_refresh_timer(iname);
54 talloc_free(tmp_ctx);
55 return;
58 iname->nb_flags |= NBT_NM_CONFLICT;
59 iname->nb_flags &= ~NBT_NM_ACTIVE;
61 if (NT_STATUS_IS_OK(status)) {
62 DEBUG(1,("Name conflict from %s refreshing name %s with %s on interface %s - %s\n",
63 io.out.reply_addr, nbt_name_string(tmp_ctx, &iname->name),
64 iname->iface->ip_address, iname->iface->bcast_address,
65 nt_errstr(nbt_rcode_to_ntstatus(io.out.rcode))));
66 } else {
67 DEBUG(1,("Error refreshing name %s with %s on interface %s - %s\n",
68 nbt_name_string(tmp_ctx, &iname->name),
69 iname->iface->ip_address, iname->iface->bcast_address,
70 nt_errstr(status)));
73 talloc_free(tmp_ctx);
78 handle name refresh timer events
80 static void name_refresh_handler(struct tevent_context *ev, struct tevent_timer *te,
81 struct timeval t, void *private_data)
83 struct nbtd_iface_name *iname = talloc_get_type(private_data, struct nbtd_iface_name);
84 struct nbtd_interface *iface = iname->iface;
85 struct nbt_name_register io;
86 struct nbt_name_request *req;
87 struct nbtd_server *nbtsrv = iface->nbtsrv;
89 /* setup a single name register request. Notice that we don't
90 use a name refresh request, as Windows and Samba3 do not
91 defend against broadcast name refresh packets. So for this
92 to be of any use at all, we need to refresh using name
93 registration packets */
94 io.in.name = iname->name;
95 io.in.dest_addr = iface->bcast_address;
96 io.in.dest_port = lpcfg_nbt_port(iface->nbtsrv->task->lp_ctx);
97 io.in.address = iface->ip_address;
98 io.in.nb_flags = iname->nb_flags;
99 io.in.ttl = iname->ttl;
100 io.in.register_demand = false;
101 io.in.broadcast = true;
102 io.in.multi_homed = false;
103 io.in.timeout = 3;
104 io.in.retries = 0;
106 nbtsrv->stats.total_sent++;
107 req = nbt_name_register_send(iface->nbtsock, &io);
108 if (req == NULL) return;
110 req->async.fn = refresh_completion_handler;
111 req->async.private_data = iname;
116 start a timer to refresh this name
118 static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname)
120 uint32_t refresh_time;
121 uint32_t max_refresh_time = lpcfg_parm_int(iname->iface->nbtsrv->task->lp_ctx, NULL, "nbtd", "max_refresh_time", 7200);
123 refresh_time = MIN(max_refresh_time, iname->ttl/2);
125 tevent_add_timer(iname->iface->nbtsrv->task->event_ctx,
126 iname,
127 timeval_add(&iname->registration_time, refresh_time, 0),
128 name_refresh_handler, iname);
131 struct nbtd_register_name_state {
132 struct nbtd_iface_name *iname;
133 struct nbt_name_register_bcast io;
137 a name registration has completed
139 static void nbtd_register_name_handler(struct tevent_req *subreq)
141 struct nbtd_register_name_state *state =
142 tevent_req_callback_data(subreq,
143 struct nbtd_register_name_state);
144 struct nbtd_iface_name *iname = state->iname;
145 NTSTATUS status;
147 status = nbt_name_register_bcast_recv(subreq);
148 TALLOC_FREE(subreq);
149 if (NT_STATUS_IS_OK(status)) {
150 /* good - nobody complained about our registration */
151 iname->nb_flags |= NBT_NM_ACTIVE;
152 DEBUG(3,("Registered %s with %s on interface %s\n",
153 nbt_name_string(state, &iname->name),
154 iname->iface->ip_address, iname->iface->bcast_address));
155 iname->registration_time = timeval_current();
156 talloc_free(state);
157 nbtd_start_refresh_timer(iname);
158 return;
161 /* someone must have replied with an objection! */
162 iname->nb_flags |= NBT_NM_CONFLICT;
164 DEBUG(1,("Error registering %s with %s on interface %s - %s\n",
165 nbt_name_string(state, &iname->name),
166 iname->iface->ip_address, iname->iface->bcast_address,
167 nt_errstr(status)));
168 talloc_free(state);
173 register a name on a network interface
175 static void nbtd_register_name_iface(struct nbtd_interface *iface,
176 const char *name, enum nbt_name_type type,
177 uint16_t nb_flags)
179 struct nbtd_iface_name *iname;
180 const char *scope = lpcfg_netbios_scope(iface->nbtsrv->task->lp_ctx);
181 struct nbtd_register_name_state *state;
182 struct tevent_req *subreq;
183 struct nbtd_server *nbtsrv = iface->nbtsrv;
185 iname = talloc(iface, struct nbtd_iface_name);
186 if (!iname) return;
188 iname->iface = iface;
189 iname->name.name = strupper_talloc(iname, name);
190 iname->name.type = type;
191 if (scope && *scope) {
192 iname->name.scope = strupper_talloc(iname, scope);
193 } else {
194 iname->name.scope = NULL;
196 iname->nb_flags = nb_flags;
197 iname->ttl = lpcfg_parm_int(iface->nbtsrv->task->lp_ctx, NULL, "nbtd", "bcast_ttl", 300000);
198 iname->registration_time = timeval_zero();
199 iname->wins_server = NULL;
201 DLIST_ADD_END(iface->names, iname, struct nbtd_iface_name *);
203 if (nb_flags & NBT_NM_PERMANENT) {
204 /* permanent names are not announced and are immediately active */
205 iname->nb_flags |= NBT_NM_ACTIVE;
206 iname->ttl = 0;
207 return;
210 /* if this is the wins interface, then we need to do a special
211 wins name registration */
212 if (iface == iface->nbtsrv->wins_interface) {
213 nbtd_winsclient_register(iname);
214 return;
217 state = talloc_zero(iname, struct nbtd_register_name_state);
218 if (state == NULL) {
219 return;
222 state->iname = iname;
224 /* setup a broadcast name registration request */
225 state->io.in.name = iname->name;
226 state->io.in.dest_addr = iface->bcast_address;
227 state->io.in.dest_port = lpcfg_nbt_port(iface->nbtsrv->task->lp_ctx);
228 state->io.in.address = iface->ip_address;
229 state->io.in.nb_flags = nb_flags;
230 state->io.in.ttl = iname->ttl;
232 nbtsrv->stats.total_sent++;
234 subreq = nbt_name_register_bcast_send(state, nbtsrv->task->event_ctx,
235 iface->nbtsock, &state->io);
236 if (subreq == NULL) {
237 return;
240 tevent_req_set_callback(subreq, nbtd_register_name_handler, state);
245 register one name on all our interfaces
247 void nbtd_register_name(struct nbtd_server *nbtsrv,
248 const char *name, enum nbt_name_type type,
249 uint16_t nb_flags)
251 struct nbtd_interface *iface;
253 /* register with all the local interfaces */
254 for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
255 nbtd_register_name_iface(iface, name, type, nb_flags);
258 /* register on our general broadcast interface as a permanent name */
259 if (nbtsrv->bcast_interface) {
260 nbtd_register_name_iface(nbtsrv->bcast_interface, name, type,
261 nb_flags | NBT_NM_PERMANENT);
264 /* register with our WINS servers */
265 if (nbtsrv->wins_interface) {
266 nbtd_register_name_iface(nbtsrv->wins_interface, name, type, nb_flags);
272 register our names on all interfaces
274 void nbtd_register_names(struct nbtd_server *nbtsrv)
276 uint16_t nb_flags = NBT_NODE_M;
277 const char **aliases;
279 /* note that we don't initially mark the names "ACTIVE". They are
280 marked active once registration is successful */
281 nbtd_register_name(nbtsrv, lpcfg_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_CLIENT, nb_flags);
282 nbtd_register_name(nbtsrv, lpcfg_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_USER, nb_flags);
283 nbtd_register_name(nbtsrv, lpcfg_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_SERVER, nb_flags);
285 aliases = lpcfg_netbios_aliases(nbtsrv->task->lp_ctx);
286 while (aliases && aliases[0]) {
287 nbtd_register_name(nbtsrv, aliases[0], NBT_NAME_CLIENT, nb_flags);
288 nbtd_register_name(nbtsrv, aliases[0], NBT_NAME_SERVER, nb_flags);
289 aliases++;
292 if (lpcfg_server_role(nbtsrv->task->lp_ctx) == ROLE_ACTIVE_DIRECTORY_DC) {
293 bool is_pdc = samdb_is_pdc(nbtsrv->sam_ctx);
294 if (is_pdc) {
295 nbtd_register_name(nbtsrv, lpcfg_workgroup(nbtsrv->task->lp_ctx),
296 NBT_NAME_PDC, nb_flags);
298 nbtd_register_name(nbtsrv, lpcfg_workgroup(nbtsrv->task->lp_ctx),
299 NBT_NAME_LOGON, nb_flags | NBT_NM_GROUP);
302 nb_flags |= NBT_NM_GROUP;
303 nbtd_register_name(nbtsrv, lpcfg_workgroup(nbtsrv->task->lp_ctx), NBT_NAME_CLIENT, nb_flags);
305 nb_flags |= NBT_NM_PERMANENT;
306 nbtd_register_name(nbtsrv, "__SAMBA__", NBT_NAME_CLIENT, nb_flags);
307 nbtd_register_name(nbtsrv, "__SAMBA__", NBT_NAME_SERVER, nb_flags);
308 nbtd_register_name(nbtsrv, "*", NBT_NAME_CLIENT, nb_flags);