93cc59741534e4fe51ca1f90c6929e9dc2151cae
[kai/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-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 pstring ServerComment;
41 extern struct in_addr ipzero;
42 extern struct in_addr ipgrp;
43
44 extern struct subnet_record *subnetlist;
45
46
47 /****************************************************************************
48   remove an entry from the name list
49
50   note: the name will _always_ be removed: it's just a matter of when.
51   XXXX at present, the name is removed _even_ if a WINS server says keep it.
52
53   ****************************************************************************/
54 void remove_name_entry(struct subnet_record *d, char *name,int type)
55 {
56   /* XXXX BUG: if samba is offering WINS support, it should still broadcast
57       a de-registration packet to the local subnet before removing the
58       name from its local-subnet name database. */
59
60   struct name_record n;
61   struct name_record *n2=NULL;
62       
63   make_nmb_name(&n.name,name,type,scope);
64
65   if ((n2 = find_name_search(&d, &n.name, FIND_SELF, ipzero)))
66   {
67     /* check name isn't already being de-registered */
68     if (NAME_DEREG(n2->nb_flags))
69       return;
70
71     /* mark the name as in the process of deletion. */
72     n2->nb_flags &= NB_DEREG;
73   }
74
75   if (ip_equal(d->bcast_ip, ipgrp))
76   {
77     if (lp_wins_support())
78     {
79         /* we are a WINS server. */
80         /* XXXX assume that if we are a WINS server that we are therefore
81            not pointing to another WINS server as well. this may later NOT
82            actually be true
83          */
84         remove_netbios_name(d,name,type,SELF,ipzero);
85     }
86     else
87     {
88       /* not a WINS server: cannot just remove our own names: we have to
89          release them on the network first. ask permission from the WINS
90          server, or if no reply is received, then we can remove the name */
91
92         queue_netbios_pkt_wins(d,ClientNMB,NMB_REL,NAME_RELEASE,
93                  name, type, 0, 0,
94                  False, True, ipzero, ipzero);
95     }
96   }
97   else
98   {
99      /* local interface: cannot just remove our own names: we have to
100         release them on the network first. once no reply is received,
101         then we can remove the name. */
102
103      queue_netbios_packet(d,ClientNMB,NMB_REL,NAME_RELEASE,
104                              name, type, 0, 0,
105                              True, True, d->bcast_ip, d->bcast_ip);
106   }
107 }
108
109
110 /****************************************************************************
111   add an entry to the name list
112   
113   big note: our name will _always_ be added (if there are no objections).
114   it's just a matter of when this will be done (e.g after a time-out).
115
116   ****************************************************************************/
117 void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
118 {
119   BOOL re_reg = False;
120   struct nmb_name n;
121
122   if (!d) return;
123
124   /* not that it particularly matters, but if the SELF name already exists,
125      it must be re-registered, rather than just registered */
126
127   make_nmb_name(&n, name, type, scope);
128   if (find_name(d->namelist, &n, SELF))
129         re_reg = True;
130
131   /* XXXX BUG: if samba is offering WINS support, it should still add the
132      name entry to a local-subnet name database. see rfc1001.txt 15.1.1 p28
133      regarding the point about M-nodes. */
134
135   if (ip_equal(d->bcast_ip, ipgrp))
136   {
137     if (lp_wins_support())
138     {
139       /* we are a WINS server. */
140       /* XXXX assume that if we are a WINS server that we are therefore
141          not pointing to another WINS server as well. this may later NOT
142          actually be true
143        */
144
145       DEBUG(4,("samba as WINS server adding: "));
146       /* this will call add_netbios_entry() */
147       name_register_work(d, name, type, nb_flags,0, ipzero, False);
148     }
149     else
150     {
151       /* a time-to-live allows us to refresh this name with the WINS server. */
152           queue_netbios_pkt_wins(d,ClientNMB,
153                                  re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
154                              name, type, nb_flags, GET_TTL(0),
155                              False, True, ipzero, ipzero);
156     }
157   }
158   else
159   {
160     /* broadcast the packet, but it comes from ipzero */
161         queue_netbios_packet(d,ClientNMB,
162                                  re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
163                              name, type, nb_flags, GET_TTL(0),
164                              True, True, d->bcast_ip, ipzero);
165   }
166 }
167
168
169 /****************************************************************************
170   add the magic samba names, useful for finding samba servers
171   **************************************************************************/
172 void add_my_names(void)
173 {
174   BOOL wins = lp_wins_support();
175   struct subnet_record *d;
176
177   struct in_addr ip = ipzero;
178
179   /* each subnet entry, including WINS pseudo-subnet, has SELF names */
180
181   /* XXXX if there was a transport layer added to samba (ipx/spx etc) then
182      there would be yet _another_ for-loop, this time on the transport type
183    */
184
185   for (d = subnetlist; d; d = d->next)
186   {
187     BOOL wins_iface = ip_equal(d->bcast_ip, ipgrp);
188
189         add_my_name_entry(d, myname,0x20,NB_ACTIVE);
190         add_my_name_entry(d, myname,0x03,NB_ACTIVE);
191         add_my_name_entry(d, myname,0x00,NB_ACTIVE);
192         add_my_name_entry(d, myname,0x1f,NB_ACTIVE);
193
194     /* these names are added permanently (ttl of zero) and will NOT be
195        refreshed with the WINS server  */
196         add_netbios_entry(d,"*",0x0,NB_ACTIVE,0,SELF,ip,False,wins);
197         add_netbios_entry(d,"__SAMBA__",0x20,NB_ACTIVE,0,SELF,ip,False,wins);
198         add_netbios_entry(d,"__SAMBA__",0x00,NB_ACTIVE,0,SELF,ip,False,wins);
199
200     if (!wins_iface && lp_domain_logons() && lp_domain_master()) {
201         /* XXXX the 0x1c is apparently something to do with domain logons */
202           add_my_name_entry(d, my_workgroup(),0x1c,NB_ACTIVE|NB_GROUP);
203     }
204   }
205   if (lp_domain_master() && (d = find_subnet(ipgrp)))
206   {
207     struct work_record *work = find_workgroupstruct(d, lp_workgroup(), True);
208     if (work && work->state == MST_NONE)
209     {
210       work->state = MST_DOMAIN_NONE;
211       become_master(d, work);
212     }
213   }
214 }
215
216
217 /****************************************************************************
218   remove all the samba names... from a WINS server if necessary.
219   **************************************************************************/
220 void remove_my_names()
221 {
222         struct subnet_record *d;
223
224         for (d = subnetlist; d; d = d->next)
225         {
226                 struct name_record *n, *next;
227
228                 for (n = d->namelist; n; n = next)
229                 {
230                         next = n->next;
231                         if (n->source == SELF)
232                         {
233                                 /* get all SELF names removed from the WINS server's database */
234                                 /* XXXX note: problem occurs if this removes the wrong one! */
235
236                                 remove_name_entry(d,n->name.name, n->name.name_type);
237                         }
238                 }
239         }
240 }
241
242
243 /*******************************************************************
244   refresh my own names
245   ******************************************************************/
246 void refresh_my_names(time_t t)
247 {
248   struct subnet_record *d;
249
250   for (d = subnetlist; d; d = d->next)
251   {
252     struct name_record *n;
253           
254         for (n = d->namelist; n; n = n->next)
255     {
256       /* each SELF name has an individual time to be refreshed */
257       if (n->source == SELF && n->refresh_time < time(NULL) && 
258           n->death_time != 0)
259       {
260         add_my_name_entry(d,n->name.name,n->name.name_type,n->nb_flags);
261       }
262     }
263   }
264 }
265
266
267 /*******************************************************************
268   queries names occasionally. an over-cautious, non-trusting WINS server!
269
270   this function has been added because nmbd could be restarted. it
271   is generally a good idea to check all the names that have been
272   reloaded from file.
273
274   XXXX which names to poll and which not can be refined at a later date.
275   ******************************************************************/
276 void query_refresh_names(void)
277 {
278         struct name_record *n;
279         struct subnet_record *d = find_subnet(ipgrp);
280
281         static time_t lasttime = 0;
282         time_t t = time(NULL);
283
284         int count = 0;
285         int name_refresh_time = NAME_POLL_REFRESH_TIME;
286         int max_count = name_refresh_time * 2 / NAME_POLL_INTERVAL;
287         if (max_count > 10) max_count = 10;
288
289         name_refresh_time = NAME_POLL_INTERVAL * max_count / 2;
290
291         /* if (!lp_poll_wins()) return; polling of registered names allowed */
292
293         if (!d) return;
294
295     if (!lasttime) lasttime = t;
296         if (t - lasttime < NAME_POLL_INTERVAL) return;
297
298     lasttime = time(NULL);
299
300         for (n = d->namelist; n; n = n->next)
301         {
302                 /* only do unique, registered names */
303
304                 if (n->source != REGISTER) continue;
305                 if (!NAME_GROUP(n->nb_flags)) continue;
306
307                 if (n->refresh_time < t)
308                 {
309                   DEBUG(3,("Polling name %s\n", namestr(&n->name)));
310                   
311           queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM,
312                                 n->name.name, n->name.name_type,
313                                 0,0,
314                                 False,False,n->ip,n->ip);
315                   count++;
316                 }
317
318                 if (count >= max_count)
319                 {
320                         /* don't do too many of these at once, but do enough to
321                            cover everyone in the list */
322                         return;
323                 }
324
325                 /* this name will be checked on again, if it's not removed */
326                 n->refresh_time += name_refresh_time;
327         }
328 }
329