r5502: announce us as a print server by default
[samba.git] / source / 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 2 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, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "lib/events/events.h"
25 #include "dlinklist.h"
26 #include "nbt_server/nbt_server.h"
27 #include "smbd/service_task.h"
28 #include "libcli/raw/libcliraw.h"
29 #include "libcli/composite/composite.h"
30
31
32 static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname);
33
34 /*
35   a name refresh request has completed
36 */
37 static void refresh_completion_handler(struct nbt_name_request *req)
38 {
39         struct nbtd_iface_name *iname = talloc_get_type(req->async.private, 
40                                                         struct nbtd_iface_name);
41         NTSTATUS status;
42         struct nbt_name_refresh io;
43         TALLOC_CTX *tmp_ctx = talloc_new(iname);
44
45         status = nbt_name_refresh_recv(req, tmp_ctx, &io);
46         if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
47                 DEBUG(4,("Refreshed name %s on %s\n", 
48                          nbt_name_string(tmp_ctx, &iname->name), 
49                          iname->iface->ip_address));
50                 iname->registration_time = timeval_current();
51                 nbtd_start_refresh_timer(iname);
52                 talloc_free(tmp_ctx);
53                 return;
54         }
55
56         iname->nb_flags |= NBT_NM_CONFLICT;
57         iname->nb_flags &= ~NBT_NM_ACTIVE;
58
59         if (NT_STATUS_IS_OK(status)) {
60                 DEBUG(1,("Name conflict from %s refreshing name %s on %s - %s\n", 
61                          io.out.reply_addr, nbt_name_string(tmp_ctx, &iname->name),
62                          iname->iface->ip_address, 
63                          nt_errstr(nbt_rcode_to_ntstatus(io.out.rcode))));
64         } else {
65                 DEBUG(1,("Error refreshing name %s on %s - %s\n", 
66                          nbt_name_string(tmp_ctx, &iname->name), 
67                          iname->iface->ip_address,
68                          nt_errstr(status)));
69         }
70
71         talloc_free(tmp_ctx);
72 }
73
74
75 /*
76   handle name refresh timer events
77 */
78 static void name_refresh_handler(struct event_context *ev, struct timed_event *te, 
79                                  struct timeval t, void *private)
80 {
81         struct nbtd_iface_name *iname = talloc_get_type(private, struct nbtd_iface_name);
82         struct nbtd_interface *iface = iname->iface;
83         struct nbt_name_register io;
84         struct nbt_name_request *req;
85
86         /* setup a single name register request. Notice that we don't
87            use a name refresh request, as Windows and Samba3 do not
88            defend against broadcast name refresh packets. So for this
89            to be of any use at all, we need to refresh using name
90            registration packets */
91         io.in.name            = iname->name;
92         io.in.dest_addr       = iface->bcast_address;
93         io.in.address         = iface->ip_address;
94         io.in.nb_flags        = iname->nb_flags;
95         io.in.ttl             = iname->ttl;
96         io.in.register_demand = False;
97         io.in.broadcast       = True;
98         io.in.multi_homed     = False;
99         io.in.timeout         = 3;
100         io.in.retries         = 0;
101
102         req = nbt_name_register_send(iface->nbtsock, &io);
103         if (req == NULL) return;
104
105         req->async.fn = refresh_completion_handler;
106         req->async.private = iname;
107 }
108
109
110 /*
111   start a timer to refresh this name
112 */
113 static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname)
114 {
115         uint32_t refresh_time;
116         uint32_t max_refresh_time = lp_parm_int(-1, "nbtd", "max_refresh_time", 7200);
117
118         refresh_time = MIN(max_refresh_time, iname->ttl/2);
119         
120         event_add_timed(iname->iface->nbtsrv->task->event_ctx, 
121                         iname, 
122                         timeval_add(&iname->registration_time, refresh_time, 0),
123                         name_refresh_handler, iname);
124 }
125
126
127 /*
128   a name registration has completed
129 */
130 static void nbtd_register_handler(struct composite_context *req)
131 {
132         struct nbtd_iface_name *iname = talloc_get_type(req->async.private, 
133                                                         struct nbtd_iface_name);
134         NTSTATUS status;
135         TALLOC_CTX *tmp_ctx = talloc_new(iname);
136
137         status = nbt_name_register_bcast_recv(req);
138         if (NT_STATUS_IS_OK(status)) {
139                 /* good - nobody complained about our registration */
140                 iname->nb_flags |= NBT_NM_ACTIVE;
141                 DEBUG(3,("Registered %s on interface %s\n",
142                          nbt_name_string(tmp_ctx, &iname->name), 
143                          iname->iface->bcast_address));
144                 iname->registration_time = timeval_current();
145                 talloc_free(tmp_ctx);
146                 nbtd_start_refresh_timer(iname);
147                 return;
148         }
149
150         /* someone must have replied with an objection! */
151         iname->nb_flags |= NBT_NM_CONFLICT;
152
153         DEBUG(1,("Error registering %s on interface %s - %s\n",
154                  nbt_name_string(tmp_ctx, &iname->name), iname->iface->bcast_address,
155                  nt_errstr(status)));
156         talloc_free(tmp_ctx);
157 }
158
159
160 /*
161   register a name on a network interface
162 */
163 static void nbtd_register_name_iface(struct nbtd_interface *iface,
164                                      const char *name, enum nbt_name_type type,
165                                      uint16_t nb_flags)
166 {
167         struct nbtd_iface_name *iname;
168         const char *scope = lp_netbios_scope();
169         struct nbt_name_register_bcast io;
170         struct composite_context *req;
171
172         iname = talloc(iface, struct nbtd_iface_name);
173         if (!iname) return;
174
175         iname->iface     = iface;
176         iname->name.name = strupper_talloc(iname, name);
177         iname->name.type = type;
178         if (scope && *scope) {
179                 iname->name.scope = strupper_talloc(iname, scope);
180         } else {
181                 iname->name.scope = NULL;
182         }
183         iname->nb_flags          = nb_flags;
184         iname->ttl               = lp_parm_int(-1, "nbtd", "bcast_ttl", 300000);
185         iname->registration_time = timeval_zero();
186         iname->wins_server       = NULL;
187
188         DLIST_ADD_END(iface->names, iname, struct nbtd_iface_name *);
189
190         if (nb_flags & NBT_NM_PERMANENT) {
191                 /* permanent names are not announced and are immediately active */
192                 iname->nb_flags |= NBT_NM_ACTIVE;
193                 iname->ttl       = 0;
194                 return;
195         }
196
197         /* if this is the wins interface, then we need to do a special
198            wins name registration */
199         if (iface == iface->nbtsrv->wins_interface) {
200                 nbtd_winsclient_register(iname);
201                 return;
202         }
203
204         /* setup a broadcast name registration request */
205         io.in.name            = iname->name;
206         io.in.dest_addr       = iface->bcast_address;
207         io.in.address         = iface->ip_address;
208         io.in.nb_flags        = nb_flags;
209         io.in.ttl             = iname->ttl;
210
211         req = nbt_name_register_bcast_send(iface->nbtsock, &io);
212         if (req == NULL) return;
213
214         req->async.fn = nbtd_register_handler;
215         req->async.private = iname;
216 }
217
218
219 /*
220   register one name on all our interfaces
221 */
222 static void nbtd_register_name(struct nbtd_server *nbtsrv, 
223                                const char *name, enum nbt_name_type type,
224                                uint16_t nb_flags)
225 {
226         struct nbtd_interface *iface;
227         
228         /* register with all the local interfaces */
229         for (iface=nbtsrv->interfaces;iface;iface=iface->next) {
230                 nbtd_register_name_iface(iface, name, type, nb_flags);
231         }
232
233         /* register on our general broadcast interface as a permanent name */
234         if (nbtsrv->bcast_interface) {
235                 nbtd_register_name_iface(nbtsrv->bcast_interface, name, type, 
236                                          nb_flags | NBT_NM_PERMANENT);
237         }
238
239         /* register with our WINS servers */
240         if (nbtsrv->wins_interface) {
241                 nbtd_register_name_iface(nbtsrv->wins_interface, name, type, nb_flags);
242         }
243 }
244
245
246 /*
247   register our names on all interfaces
248 */
249 void nbtd_register_names(struct nbtd_server *nbtsrv)
250 {
251         uint16_t nb_flags = NBT_NODE_M;
252         const char **aliases;
253
254         /* note that we don't initially mark the names "ACTIVE". They are 
255            marked active once registration is successful */
256         nbtd_register_name(nbtsrv, lp_netbios_name(), NBT_NAME_CLIENT, nb_flags);
257         nbtd_register_name(nbtsrv, lp_netbios_name(), NBT_NAME_USER,   nb_flags);
258         nbtd_register_name(nbtsrv, lp_netbios_name(), NBT_NAME_SERVER, nb_flags);
259
260         aliases = lp_netbios_aliases();
261         while (aliases && aliases[0]) {
262                 nbtd_register_name(nbtsrv, aliases[0], NBT_NAME_CLIENT, nb_flags);
263                 nbtd_register_name(nbtsrv, aliases[0], NBT_NAME_SERVER, nb_flags);
264                 aliases++;
265         }
266
267         nb_flags |= NBT_NM_GROUP;
268         nbtd_register_name(nbtsrv, lp_workgroup(),    NBT_NAME_CLIENT, nb_flags);
269
270         nb_flags |= NBT_NM_PERMANENT;
271         nbtd_register_name(nbtsrv, "__SAMBA__",       NBT_NAME_CLIENT, nb_flags);
272         nbtd_register_name(nbtsrv, "__SAMBA__",       NBT_NAME_SERVER, nb_flags);
273         nbtd_register_name(nbtsrv, "*",               NBT_NAME_CLIENT, nb_flags);
274 }