93111eb2689fa23aad303138d0d36a06ea1441db
[samba.git] / source3 / 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-1997
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 fstring myworkgroup;
41 extern struct in_addr ipzero;
42 extern struct in_addr wins_ip;
43
44 extern struct subnet_record *subnetlist;
45
46 extern uint16 nb_type; /* samba's NetBIOS type */
47
48 /****************************************************************************
49   remove an entry from the name list
50
51   note: the name will _always_ be removed
52   XXXX at present, the name is removed _even_ if a WINS server says keep it.
53
54   If direct is True then the name being removed must have been a direct name
55   add. This is done for special names such as DOMAIN<1b>. Just delete it
56   without any network release traffic.
57
58   ****************************************************************************/
59 void remove_name_entry(struct subnet_record *d, char *name,int type, BOOL direct)
60 {
61   /* XXXX BUG: if samba is offering WINS support, it should still broadcast
62       a de-registration packet to the local subnet before removing the
63       name from its local-subnet name database. */
64
65   struct name_record n;
66   struct name_record *n2=NULL;
67       
68   make_nmb_name(&n.name,name,type,scope);
69
70   if ((n2 = find_name_search(&d, &n.name, FIND_SELF, ipzero)))
71   {
72     /* check name isn't already being de-registered */
73     if (NAME_DEREG(n2->ip_flgs[0].nb_flags))
74       return;
75
76     /* mark the name as in the process of deletion. */
77     n2->ip_flgs[0].nb_flags &= NB_DEREG;
78   }
79
80   if (!n2) return;
81
82   /* remove the name immediately. even if the spec says we should
83      first try to release them, this is too dangerous with our current
84      name structures as otherwise we will end up replying to names we
85      don't really own */  
86   remove_netbios_name(d,name,type,SELF,n2->ip_flgs[0].ip);
87
88   if (ip_equal(d->bcast_ip, wins_ip))
89   {
90     if (!lp_wins_support() && !direct)
91     {
92       /* not a WINS server: we have to release them on the network */
93       queue_netbios_pkt_wins(ClientNMB,NMB_REL,NAME_RELEASE,
94                              name, type, 0, 0,0,NULL,NULL,
95                              False, True, ipzero, ipzero);
96     }
97   }
98   else
99   {
100     if(!direct)
101       /* local interface: release them on the network */
102       queue_netbios_packet(d,ClientNMB,NMB_REL,NAME_RELEASE,
103                          name, type, 0, 0,0,NULL,NULL,
104                          True, True, d->bcast_ip, d->bcast_ip);
105   }
106 }
107
108
109 /****************************************************************************
110   add an entry to the name list
111   If the direct BOOL is set then no network traffic is done for the add - it
112   is just blasted into the subnet entry with a zero TTL - it will not
113   expire and has not been legitimately claimed. This is *only* done if
114   we are a WINS server or for a special name such as DOMAIN<1b>.
115  
116   big note: our name will _always_ be added (if there are no objections).
117   it's just a matter of when this will be done (e.g after a time-out).
118
119   ****************************************************************************/
120 void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags, BOOL direct)
121 {
122   BOOL re_reg = False;
123   struct nmb_name n;
124
125   if (!d) return;
126
127   /* not that it particularly matters, but if the SELF name already exists,
128      it must be re-registered, rather than just registered */
129
130   make_nmb_name(&n, name, type, scope);
131   if (find_name(d->namelist, &n, SELF))
132         re_reg = True;
133
134   /* XXXX BUG: if samba is offering WINS support, it should still add the
135      name entry to a local-subnet name database. see rfc1001.txt 15.1.1 p28
136      regarding the point about M-nodes. */
137
138   if (ip_equal(d->bcast_ip, wins_ip))
139   {
140     if (lp_wins_support() || direct)
141     {
142       /* we are a WINS server. */
143       if(lp_wins_support())
144         DEBUG(4,("add_my_name_entry: samba as WINS server adding: "));
145       else
146         DEBUG(4,("add_my_name_entry: direct name entry : adding: "));
147         
148       /* this will call add_netbios_entry() */
149       name_register_work(d, name, type, nb_flags,0, ipzero, False);
150     }
151     else
152     {
153       DEBUG(4,("add_my_name_entry registering name %s with WINS server.\n",
154                 name));
155       
156       /* a time-to-live allows us to refresh this name with the WINS server. */
157           queue_netbios_pkt_wins(ClientNMB,
158                                  re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
159                              name, type, nb_flags, GET_TTL(0),0,NULL,NULL,
160                              False, True, ipzero, ipzero);
161     }
162   }
163   else
164   {
165     if(direct)
166     {
167       /* Just enter the name to be the ip address of the subnet
168          via name_register_work to ensure all side effects are done.
169        */
170       DEBUG(4,("add_my_name_entry: direct name entry : adding: "));
171       /* this will call add_netbios_entry() */
172       name_register_work(d, name, type, nb_flags,0, d->myip, False);
173     }
174     else
175     {
176       /* broadcast the packet, but it comes from ipzero */
177       queue_netbios_packet(d,ClientNMB,
178          re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
179          name, type, nb_flags, GET_TTL(0),0,NULL,NULL,
180          True, True, d->bcast_ip, ipzero);
181     }
182   }
183 }
184
185
186 /****************************************************************************
187   add the domain logon server and domain master browser names 
188
189   this code was written so that several samba servers can co-operate in
190   sharing the task of (one server) being a domain master, and of being
191   domain logon servers.
192
193   **************************************************************************/
194 void add_domain_names(time_t t)
195 {
196   static time_t lastrun = 0;
197   struct subnet_record *d;
198   struct work_record *work;
199   struct nmb_name n;
200
201   if (lastrun != 0 && t < lastrun + CHECK_TIME_ADD_DOM_NAMES * 60) return;
202   lastrun = t;
203
204   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
205   {
206     work = find_workgroupstruct(d, myworkgroup, False);
207     if (lp_domain_logons() && work && work->log_state == LOGON_NONE)
208     {
209       make_nmb_name(&n,myworkgroup,0x1c,scope);
210       if (!find_name(d->namelist, &n, FIND_SELF))
211       {
212         /* logon servers are group names - we don't expect this to fail. */
213         DEBUG(0,("%s attempting to become logon server for %s %s\n",
214              timestring(), myworkgroup, inet_ntoa(d->bcast_ip)));
215         become_logon_server(d, work);
216       }
217     }
218   }
219
220  for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
221  { 
222    work = find_workgroupstruct(d, myworkgroup, True);
223
224    if (lp_domain_master() && work && work->dom_state == DOMAIN_NONE)
225      {
226       make_nmb_name(&n,myworkgroup,0x1b,scope);
227       if (!find_name(d->namelist, &n, FIND_SELF))
228       {
229         DEBUG(0,("%s add_domain_names: attempting to become domain master \
230 browser on workgroup %s %s\n",
231                   timestring(), myworkgroup, inet_ntoa(d->bcast_ip)));
232
233         if(d == wins_subnet)
234         {
235           if (lp_wins_support())
236           {
237             /* use the wins server's capabilities (indirectly).  if
238                someone has already registered the domain<1b> name with 
239                the WINS server, then the WINS server's job is to _check_
240                that the owner still wants it, before giving it away.
241              */
242                
243             DEBUG(1,("%s initiating becoming domain master for %s\n",
244                         timestring(), myworkgroup));
245             become_domain_master(d, work);
246           }
247           else
248           {
249             /* send out a query to establish whether there's a 
250                domain controller on the WINS subnet.  if not,
251                we can become a domain controller.
252                it's only polite that we check, before claiming the
253                NetBIOS name 0x1b.
254              */
255
256             DEBUG(0,("add_domain_names:querying WINS for domain master \
257 on workgroup %s\n", myworkgroup));
258
259             queue_netbios_pkt_wins(ClientNMB,NMB_QUERY,NAME_QUERY_DOMAIN,
260                                 myworkgroup, 0x1b,
261                                 0, 0,0,NULL,NULL,
262                                 False, False, ipzero, ipzero);
263           }
264         }
265         else
266         {
267           DEBUG(0,("add_domain_names:querying subnet %s for domain master \
268 on workgroup %s\n", inet_ntoa(d->bcast_ip), myworkgroup));
269           queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_DOMAIN,
270                               myworkgroup, 0x1b,
271                               0, 0,0,NULL,NULL,
272                               True, False,
273                               d->bcast_ip, d->bcast_ip);
274         }
275       }
276     }
277   }
278 }
279
280
281 /****************************************************************************
282   add the magic samba names, useful for finding samba servers
283   **************************************************************************/
284 void add_my_names(void)
285 {
286   struct subnet_record *d;
287   /* each subnet entry, including WINS pseudo-subnet, has SELF names */
288
289   /* XXXX if there was a transport layer added to samba (ipx/spx etc) then
290      there would be yet _another_ for-loop, this time on the transport type
291    */
292
293   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
294   {
295     BOOL wins = (lp_wins_support() && (d == wins_subnet));
296
297     add_my_name_entry(d, myname,0x20,nb_type|NB_ACTIVE,False);
298     add_my_name_entry(d, myname,0x03,nb_type|NB_ACTIVE,False);
299     add_my_name_entry(d, myname,0x00,nb_type|NB_ACTIVE,False);
300     
301     /* these names are added permanently (ttl of zero) and will NOT be
302        refreshed with the WINS server  */
303     add_netbios_entry(d,"*",0x0,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
304     add_netbios_entry(d,"*",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
305     add_netbios_entry(d,"__SAMBA__",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
306     add_netbios_entry(d,"__SAMBA__",0x00,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
307   }
308 }
309
310
311 /****************************************************************************
312   remove all the samba names... from a WINS server if necessary.
313   **************************************************************************/
314 void remove_my_names()
315 {
316         struct subnet_record *d;
317
318         for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
319         {
320                 struct name_record *n, *next;
321
322                 for (n = d->namelist; n; n = next)
323                 {
324                         next = n->next;
325                         if (n->source == SELF)
326                         {
327                                 /* get all SELF names removed from the WINS server's database */
328                                 /* XXXX note: problem occurs if this removes the wrong one! */
329
330                                 remove_name_entry(d,n->name.name, n->name.name_type,False);
331                         }
332                 }
333         }
334 }
335
336
337 /*******************************************************************
338   refresh my own names
339   ******************************************************************/
340 void refresh_my_names(time_t t)
341 {
342   struct subnet_record *d;
343
344   for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
345   {
346     struct name_record *n;
347           
348     for (n = d->namelist; n; n = n->next)
349     {
350       /* each SELF name has an individual time to be refreshed */
351       if (n->source == SELF && n->refresh_time < t && 
352           n->death_time != 0)
353       {
354         add_my_name_entry(d,n->name.name,n->name.name_type,
355                           n->ip_flgs[0].nb_flags,False);
356         /* they get a new lease on life :-) */
357         n->death_time += GET_TTL(0);
358         n->refresh_time += GET_TTL(0);
359       }
360     }
361   }
362 }
363
364
365 /*******************************************************************
366   queries names occasionally. an over-cautious, non-trusting WINS server!
367
368   this function has been added because nmbd could be restarted. it
369   is generally a good idea to check all the names that have been
370   reloaded from file.
371
372   XXXX which names to poll and which not can be refined at a later date.
373   ******************************************************************/
374 void query_refresh_names(time_t t)
375 {
376         struct name_record *n;
377         struct subnet_record *d = wins_subnet;
378
379         static time_t lasttime = 0;
380
381         int count = 0;
382         int name_refresh_time = NAME_POLL_REFRESH_TIME;
383         int max_count = name_refresh_time * 2 / NAME_POLL_INTERVAL;
384         if (max_count > 10) max_count = 10;
385
386         name_refresh_time = NAME_POLL_INTERVAL * max_count / 2;
387
388         /* if (!lp_poll_wins()) return; polling of registered names allowed */
389
390         if (!d) return;
391
392     if (!lasttime) lasttime = t;
393         if (t - lasttime < NAME_POLL_INTERVAL) return;
394
395     lasttime = time(NULL);
396
397         for (n = d->namelist; n; n = n->next)
398         {
399                 /* only do unique, registered names */
400
401                 if (n->source != REGISTER) continue;
402                 if (!NAME_GROUP(n->ip_flgs[0].nb_flags)) continue;
403
404                 if (n->refresh_time < t)
405                 {
406                   DEBUG(3,("Polling name %s\n", namestr(&n->name)));
407                   
408           queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM,
409                                 n->name.name, n->name.name_type,
410                                 0,0,0,NULL,NULL,
411                                 False,False,n->ip_flgs[0].ip,n->ip_flgs[0].ip);
412                   count++;
413                 }
414
415                 if (count >= max_count)
416                 {
417                         /* don't do too many of these at once, but do enough to
418                            cover everyone in the list */
419                         return;
420                 }
421
422                 /* this name will be checked on again, if it's not removed */
423                 n->refresh_time += name_refresh_time;
424         }
425 }
426