sorted out various timer delay bugs: nameannounce.c nameserv.c
[samba.git] / source / nameserv.c
1 /* 
2    Unix SMB/Netbios implementation.
3    Version 1.9.
4    NBT netbios routines and daemon - version 2
5    Copyright (C) Andrew Tridgell 1994-1996
6    
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11    
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16    
17    You should have received a copy of the GNU General Public License
18    along with this program; if not, write to the Free Software
19    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21    Module name: nameserv.c
22
23    Revision History:
24
25    14 jan 96: lkcl@pires.co.uk
26    added multiple workgroup domain master support
27
28    04 jul 96: lkcl@pires.co.uk
29    module nameserv contains name server management functions
30 */
31
32 #include "includes.h"
33
34 extern int ClientNMB;
35
36 extern int DEBUGLEVEL;
37
38 extern pstring scope;
39 extern pstring myname;
40 extern struct in_addr ipzero;
41 extern struct in_addr ipgrp;
42
43 extern struct subnet_record *subnetlist;
44
45
46 /****************************************************************************
47   remove an entry from the name list
48
49   note: the name will _always_ be removed: it's just a matter of when.
50   XXXX at present, the name is removed _even_ if a WINS server says keep it.
51
52   ****************************************************************************/
53 void remove_name_entry(struct subnet_record *d, char *name,int type)
54 {
55   /* XXXX BUG: if samba is offering WINS support, it should still broadcast
56       a de-registration packet to the local subnet before removing the
57       name from its local-subnet name database. */
58
59   struct name_record n;
60   struct name_record *n2=NULL;
61       
62   make_nmb_name(&n.name,name,type,scope);
63
64   if ((n2 = find_name_search(&d, &n.name, FIND_SELF, ipzero)))
65   {
66     /* check name isn't already being de-registered */
67     if (NAME_DEREG(n2->nb_flags))
68       return;
69
70     /* mark the name as in the process of deletion. */
71     n2->nb_flags &= NB_DEREG;
72   }
73
74   if (ip_equal(d->bcast_ip, ipgrp))
75   {
76     if (lp_wins_support())
77     {
78         /* we are a WINS server. */
79         /* XXXX assume that if we are a WINS server that we are therefore
80            not pointing to another WINS server as well. this may later NOT
81            actually be true
82          */
83         remove_netbios_name(d,name,type,SELF,ipzero);
84     }
85     else
86     {
87       /* not a WINS server: cannot just remove our own names: we have to
88          release them on the network first. ask permission from the WINS
89          server, or if no reply is received, then we can remove the name */
90
91         queue_netbios_pkt_wins(d,ClientNMB,NMB_REL,NAME_RELEASE,
92                  name, type, 0, 0,
93                  False, True, ipzero, ipzero);
94     }
95   }
96   else
97   {
98      /* local interface: cannot just remove our own names: we have to
99         release them on the network first. once no reply is received,
100         then we can remove the name. */
101
102      queue_netbios_packet(d,ClientNMB,NMB_REL,NAME_RELEASE,
103                              name, type, 0, 0,
104                              True, True, d->bcast_ip, d->bcast_ip);
105   }
106 }
107
108
109 /****************************************************************************
110   add an entry to the name list
111   
112   big note: our name will _always_ be added (if there are no objections).
113   it's just a matter of when this will be done (e.g after a time-out).
114
115   ****************************************************************************/
116 void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
117 {
118   BOOL re_reg = False;
119   struct nmb_name n;
120
121   if (!d) return;
122
123   /* not that it particularly matters, but if the SELF name already exists,
124      it must be re-registered, rather than just registered */
125
126   make_nmb_name(&n, name, type, scope);
127   if (find_name(d->namelist, &n, SELF, ipzero))
128         re_reg = True;
129
130   /* XXXX BUG: if samba is offering WINS support, it should still add the
131      name entry to a local-subnet name database. see rfc1001.txt 15.1.1 p28
132      regarding the point about M-nodes. */
133
134   if (ip_equal(d->bcast_ip, ipgrp))
135   {
136     if (lp_wins_support())
137     {
138       /* we are a WINS server. */
139       /* XXXX assume that if we are a WINS server that we are therefore
140          not pointing to another WINS server as well. this may later NOT
141          actually be true
142        */
143
144       add_netbios_entry(d,name,type,nb_flags,0,
145                                 SELF,ipzero,False,lp_wins_support());
146     }
147     else
148     {
149       /* a time-to-live allows us to refresh this name with the WINS server. */
150           queue_netbios_pkt_wins(d,ClientNMB,
151                                  re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
152                              name, type, nb_flags, GET_TTL(0),
153                              False, True, ipzero, ipzero);
154     }
155   }
156   else
157   {
158         queue_netbios_packet(d,ClientNMB,
159                                  re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
160                              name, type, nb_flags, GET_TTL(0),
161                              True, True, d->bcast_ip, d->bcast_ip);
162   }
163 }
164
165
166 /****************************************************************************
167   add the magic samba names, useful for finding samba servers
168   **************************************************************************/
169 void add_my_names(void)
170 {
171   BOOL wins = lp_wins_support();
172   struct subnet_record *d;
173
174   struct in_addr ip = ipzero;
175
176   /* each subnet entry, including WINS pseudo-subnet, has SELF names */
177
178   /* XXXX if there was a transport layer added to samba (ipx/spx etc) then
179      there would be yet _another_ for-loop, this time on the transport type
180    */
181
182   for (d = subnetlist; d; d = d->next)
183   {
184     if (!d->my_interface) continue;
185
186     /* these names need to be refreshed with the WINS server */
187         add_my_name_entry(d, myname,0x20,NB_ACTIVE);
188         add_my_name_entry(d, myname,0x03,NB_ACTIVE);
189         add_my_name_entry(d, myname,0x00,NB_ACTIVE);
190         add_my_name_entry(d, myname,0x1f,NB_ACTIVE);
191
192     /* these names are added permanently (ttl of zero) and will NOT be
193        refreshed with the WINS server  */
194         add_netbios_entry(d,"*",0x0,NB_ACTIVE,0,SELF,ip,False,wins);
195         add_netbios_entry(d,"__SAMBA__",0x20,NB_ACTIVE,0,SELF,ip,False,wins);
196         add_netbios_entry(d,"__SAMBA__",0x00,NB_ACTIVE,0,SELF,ip,False,wins);
197
198     if (lp_domain_logons() && lp_domain_master()) {
199         /* XXXX the 0x1c is apparently something to do with domain logons */
200           add_my_name_entry(d, my_workgroup(),0x1c,NB_ACTIVE|NB_GROUP);
201     }
202   }
203 }
204
205
206 /****************************************************************************
207   remove all the samba names... from a WINS server if necessary.
208   **************************************************************************/
209 void remove_my_names()
210 {
211         struct subnet_record *d;
212
213         for (d = subnetlist; d; d = d->next)
214         {
215                 struct name_record *n, *next;
216
217                 for (n = d->namelist; n; n = next)
218                 {
219                         next = n->next;
220                         if (n->source == SELF)
221                         {
222                                 /* get all SELF names removed from the WINS server's database */
223                                 /* XXXX note: problem occurs if this removes the wrong one! */
224
225                                 remove_name_entry(d,n->name.name, n->name.name_type);
226                         }
227                 }
228         }
229 }
230
231
232 /*******************************************************************
233   refresh my own names
234   ******************************************************************/
235 void refresh_my_names(time_t t)
236 {
237   struct subnet_record *d;
238
239   for (d = subnetlist; d; d = d->next)
240   {
241     struct name_record *n;
242           
243         for (n = d->namelist; n; n = n->next)
244     {
245       /* each SELF name has an individual time to be refreshed */
246       if (n->source == SELF && n->refresh_time < time(NULL) && 
247           n->death_time != 0)
248       {
249         add_my_name_entry(d,n->name.name,n->name.name_type,n->nb_flags);
250       }
251     }
252   }
253 }
254
255
256 /*******************************************************************
257   queries names occasionally. an over-cautious, non-trusting WINS server!
258
259   this function has been added because nmbd could be restarted. it
260   is generally a good idea to check all the names that have been
261   reloaded from file.
262
263   XXXX which names to poll and which not can be refined at a later date.
264   ******************************************************************/
265 void query_refresh_names(void)
266 {
267         struct name_record *n;
268         struct subnet_record *d = find_subnet(ipgrp);
269
270         static time_t lasttime = 0;
271         time_t t = time(NULL);
272
273         int count = 0;
274         int name_refresh_time = NAME_POLL_REFRESH_TIME;
275         int max_count = name_refresh_time * 2 / NAME_POLL_INTERVAL;
276         if (max_count > 10) max_count = 10;
277
278         name_refresh_time = NAME_POLL_INTERVAL * max_count / 2;
279
280         /* if (!lp_poll_wins()) return; polling of registered names allowed */
281
282         if (!d) return;
283
284     if (!lasttime) lasttime = t;
285         if (t - lasttime < NAME_POLL_INTERVAL) return;
286
287     lasttime = time(NULL);
288
289         for (n = d->namelist; n; n = n->next)
290         {
291                 /* only do unique, registered names */
292
293                 if (n->source != REGISTER) continue;
294                 if (!NAME_GROUP(n->nb_flags)) continue;
295
296                 if (n->refresh_time < t)
297                 {
298                   DEBUG(3,("Polling name %s\n", namestr(&n->name)));
299                   
300           queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM,
301                                 n->name.name, n->name.name_type,
302                                 0,0,
303                                 False,False,n->ip,n->ip);
304                   count++;
305                 }
306
307                 if (count >= max_count)
308                 {
309                         /* don't do too many of these at once, but do enough to
310                            cover everyone in the list */
311                         return;
312                 }
313
314                 /* this name will be checked on again, if it's not removed */
315                 n->refresh_time += name_refresh_time;
316         }
317 }
318