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