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