s4-nbt: use private_data instead of private.
[idra/samba.git] / source4 / nbt_server / register.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    register our names
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 "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"
33
34 static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname);
35
36 /*
37   a name refresh request has completed
38 */
39 static void refresh_completion_handler(struct nbt_name_request *req)
40 {
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);
46
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;
56         }
57
58         iname->nb_flags |= NBT_NM_CONFLICT;
59         iname->nb_flags &= ~NBT_NM_ACTIVE;
60
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)));
71         }
72
73         talloc_free(tmp_ctx);
74 }
75
76
77 /*
78   handle name refresh timer events
79 */
80 static void name_refresh_handler(struct event_context *ev, struct timed_event *te, 
81                                  struct timeval t, void *private_data)
82 {
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;
88
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       = lp_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;
105
106         nbtsrv->stats.total_sent++;
107         req = nbt_name_register_send(iface->nbtsock, &io);
108         if (req == NULL) return;
109
110         req->async.fn = refresh_completion_handler;
111         req->async.private_data = iname;
112 }
113
114
115 /*
116   start a timer to refresh this name
117 */
118 static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname)
119 {
120         uint32_t refresh_time;
121         uint32_t max_refresh_time = lp_parm_int(iname->iface->nbtsrv->task->lp_ctx, NULL, "nbtd", "max_refresh_time", 7200);
122
123         refresh_time = MIN(max_refresh_time, iname->ttl/2);
124         
125         event_add_timed(iname->iface->nbtsrv->task->event_ctx, 
126                         iname, 
127                         timeval_add(&iname->registration_time, refresh_time, 0),
128                         name_refresh_handler, iname);
129 }
130
131
132 /*
133   a name registration has completed
134 */
135 static void nbtd_register_handler(struct composite_context *creq)
136 {
137         struct nbtd_iface_name *iname = talloc_get_type(creq->async.private_data, 
138                                                         struct nbtd_iface_name);
139         NTSTATUS status;
140         TALLOC_CTX *tmp_ctx = talloc_new(iname);
141
142         status = nbt_name_register_bcast_recv(creq);
143         if (NT_STATUS_IS_OK(status)) {
144                 /* good - nobody complained about our registration */
145                 iname->nb_flags |= NBT_NM_ACTIVE;
146                 DEBUG(3,("Registered %s with %s on interface %s\n",
147                          nbt_name_string(tmp_ctx, &iname->name), 
148                          iname->iface->ip_address, iname->iface->bcast_address));
149                 iname->registration_time = timeval_current();
150                 talloc_free(tmp_ctx);
151                 nbtd_start_refresh_timer(iname);
152                 return;
153         }
154
155         /* someone must have replied with an objection! */
156         iname->nb_flags |= NBT_NM_CONFLICT;
157
158         DEBUG(1,("Error registering %s with %s on interface %s - %s\n",
159                  nbt_name_string(tmp_ctx, &iname->name),
160                  iname->iface->ip_address, iname->iface->bcast_address,
161                  nt_errstr(status)));
162         talloc_free(tmp_ctx);
163 }
164
165
166 /*
167   register a name on a network interface
168 */
169 static void nbtd_register_name_iface(struct nbtd_interface *iface,
170                                      const char *name, enum nbt_name_type type,
171                                      uint16_t nb_flags)
172 {
173         struct nbtd_iface_name *iname;
174         const char *scope = lp_netbios_scope(iface->nbtsrv->task->lp_ctx);
175         struct nbt_name_register_bcast io;
176         struct composite_context *creq;
177         struct nbtd_server *nbtsrv = iface->nbtsrv;
178
179         iname = talloc(iface, struct nbtd_iface_name);
180         if (!iname) return;
181
182         iname->iface     = iface;
183         iname->name.name = strupper_talloc(iname, name);
184         iname->name.type = type;
185         if (scope && *scope) {
186                 iname->name.scope = strupper_talloc(iname, scope);
187         } else {
188                 iname->name.scope = NULL;
189         }
190         iname->nb_flags          = nb_flags;
191         iname->ttl               = lp_parm_int(iface->nbtsrv->task->lp_ctx, NULL, "nbtd", "bcast_ttl", 300000);
192         iname->registration_time = timeval_zero();
193         iname->wins_server       = NULL;
194
195         DLIST_ADD_END(iface->names, iname, struct nbtd_iface_name *);
196
197         if (nb_flags & NBT_NM_PERMANENT) {
198                 /* permanent names are not announced and are immediately active */
199                 iname->nb_flags |= NBT_NM_ACTIVE;
200                 iname->ttl       = 0;
201                 return;
202         }
203
204         /* if this is the wins interface, then we need to do a special
205            wins name registration */
206         if (iface == iface->nbtsrv->wins_interface) {
207                 nbtd_winsclient_register(iname);
208                 return;
209         }
210
211         /* setup a broadcast name registration request */
212         io.in.name            = iname->name;
213         io.in.dest_addr       = iface->bcast_address;
214         io.in.dest_port       = lp_nbt_port(iface->nbtsrv->task->lp_ctx);
215         io.in.address         = iface->ip_address;
216         io.in.nb_flags        = nb_flags;
217         io.in.ttl             = iname->ttl;
218
219         nbtsrv->stats.total_sent++;
220         creq = nbt_name_register_bcast_send(iface->nbtsock, &io);
221         if (creq == NULL) return;
222
223         creq->async.fn = nbtd_register_handler;
224         creq->async.private_data = iname;
225 }
226
227
228 /*
229   register one name on all our interfaces
230 */
231 void nbtd_register_name(struct nbtd_server *nbtsrv, 
232                         const char *name, enum nbt_name_type type,
233                         uint16_t nb_flags)
234 {
235         struct nbtd_interface *iface;
236         
237         /* register with all the local interfaces */
238         for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
239                 nbtd_register_name_iface(iface, name, type, nb_flags);
240         }
241
242         /* register on our general broadcast interface as a permanent name */
243         if (nbtsrv->bcast_interface) {
244                 nbtd_register_name_iface(nbtsrv->bcast_interface, name, type, 
245                                          nb_flags | NBT_NM_PERMANENT);
246         }
247
248         /* register with our WINS servers */
249         if (nbtsrv->wins_interface) {
250                 nbtd_register_name_iface(nbtsrv->wins_interface, name, type, nb_flags);
251         }
252 }
253
254
255 /*
256   register our names on all interfaces
257 */
258 void nbtd_register_names(struct nbtd_server *nbtsrv)
259 {
260         uint16_t nb_flags = NBT_NODE_M;
261         const char **aliases;
262
263         /* note that we don't initially mark the names "ACTIVE". They are 
264            marked active once registration is successful */
265         nbtd_register_name(nbtsrv, lp_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_CLIENT, nb_flags);
266         nbtd_register_name(nbtsrv, lp_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_USER,   nb_flags);
267         nbtd_register_name(nbtsrv, lp_netbios_name(nbtsrv->task->lp_ctx), NBT_NAME_SERVER, nb_flags);
268
269         aliases = lp_netbios_aliases(nbtsrv->task->lp_ctx);
270         while (aliases && aliases[0]) {
271                 nbtd_register_name(nbtsrv, aliases[0], NBT_NAME_CLIENT, nb_flags);
272                 nbtd_register_name(nbtsrv, aliases[0], NBT_NAME_SERVER, nb_flags);
273                 aliases++;
274         }
275
276         if (lp_server_role(nbtsrv->task->lp_ctx) == ROLE_DOMAIN_CONTROLLER)     {
277                 bool is_pdc = samdb_is_pdc(nbtsrv->sam_ctx);
278                 if (is_pdc) {
279                         nbtd_register_name(nbtsrv, lp_workgroup(nbtsrv->task->lp_ctx),
280                                            NBT_NAME_PDC, nb_flags);
281                 }
282                 nbtd_register_name(nbtsrv, lp_workgroup(nbtsrv->task->lp_ctx),
283                                    NBT_NAME_LOGON, nb_flags | NBT_NM_GROUP);
284         }
285
286         nb_flags |= NBT_NM_GROUP;
287         nbtd_register_name(nbtsrv, lp_workgroup(nbtsrv->task->lp_ctx), NBT_NAME_CLIENT, nb_flags);
288
289         nb_flags |= NBT_NM_PERMANENT;
290         nbtd_register_name(nbtsrv, "__SAMBA__",       NBT_NAME_CLIENT, nb_flags);
291         nbtd_register_name(nbtsrv, "__SAMBA__",       NBT_NAME_SERVER, nb_flags);
292         nbtd_register_name(nbtsrv, "*",               NBT_NAME_CLIENT, nb_flags);
293 }