c3f6076f49bfd981a16c4a4cc51d4239bf396fc3
[kai/samba.git] / source3 / namedbserver.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    Revision History:
22
23    14 jan 96: lkcl@pires.co.uk
24    added multiple workgroup domain master support
25
26    04 jul 96: lkcl@pires.co.uk
27    created module namedbserver containing server database functions
28
29 */
30
31 #include "includes.h"
32 #include "smb.h"
33
34 extern int ClientNMB;
35
36 extern int DEBUGLEVEL;
37
38 extern pstring myname;
39 extern fstring myworkgroup;
40
41 /* this is our domain/workgroup/server database */
42 extern struct subnet_record *subnetlist;
43
44 extern BOOL updatedlists;
45
46
47 /*******************************************************************
48   expire old servers in the serverlist
49   time of -1 indicates everybody dies except those with time of 0
50   remove_all_servers indicates everybody dies.
51   ******************************************************************/
52 void remove_old_servers(struct work_record *work, time_t t,
53                                         BOOL remove_all)
54 {
55   struct server_record *s;
56   struct server_record *nexts;
57   
58   /* expire old entries in the serverlist */
59   for (s = work->serverlist; s; s = nexts)
60     {
61             nexts = s->next;
62             if (remove_all || 
63                 (s->death_time && (t == -1 || s->death_time < t))) {
64                     DEBUG(3,("Removing dead server %s\n",s->serv.name));
65                     updatedlists = True;
66           
67                     if (s->prev) s->prev->next = s->next;
68                     if (s->next) s->next->prev = s->prev;
69           
70                     if (work->serverlist == s) 
71                             work->serverlist = s->next; 
72
73                     free(s);
74             }
75     }
76 }
77
78
79 /***************************************************************************
80   add a server into the list
81   **************************************************************************/
82 static void add_server(struct work_record *work,struct server_record *s)
83 {
84   struct server_record *s2;
85
86   if (!work->serverlist) {
87     work->serverlist = s;
88     s->prev = NULL;
89     s->next = NULL;
90     return;
91   }
92
93   for (s2 = work->serverlist; s2->next; s2 = s2->next) ;
94
95   s2->next = s;
96   s->next = NULL;
97   s->prev = s2;
98 }
99
100
101 /****************************************************************************
102   find a server in a server list.
103   **************************************************************************/
104 struct server_record *find_server(struct work_record *work, char *name)
105 {
106         struct server_record *ret;
107   
108         if (!work) return NULL;
109
110         for (ret = work->serverlist; ret; ret = ret->next)
111         {
112                 if (strequal(ret->serv.name,name))
113                 {
114                         return ret;
115                 }
116         }
117     return NULL;
118 }
119
120
121 /****************************************************************************
122   add a server entry
123   ****************************************************************************/
124 struct server_record *add_server_entry(struct subnet_record *d, 
125                                        struct work_record *work,
126                                        char *name,int servertype, 
127                                        int ttl,char *comment,
128                                        BOOL replace)
129 {
130   BOOL newentry=False;
131   struct server_record *s;
132   
133   if (name[0] == '*')
134   {
135       return (NULL);
136   }
137   
138   s = find_server(work, name);
139
140   if (s && !replace)
141   {
142     DEBUG(4,("Not replacing %s\n",name));
143     return(s);
144   }
145   
146   if (!s || s->serv.type != servertype || !strequal(s->serv.comment, comment))
147     updatedlists=True;
148
149   if (!s)
150   {
151     newentry = True;
152     s = (struct server_record *)malloc(sizeof(*s));
153       
154     if (!s) return(NULL);
155       
156     bzero((char *)s,sizeof(*s));
157   }
158   
159   
160   /* update the entry */
161   StrnCpy(s->serv.name,name,sizeof(s->serv.name)-1);
162   StrnCpy(s->serv.comment,comment,sizeof(s->serv.comment)-1);
163   strupper(s->serv.name);
164   s->serv.type  = servertype;
165   s->death_time = servertype ? (ttl?time(NULL)+ttl*3:0) : (time(NULL)-1);
166   
167   /* for a domain entry, the comment field refers to the server name */
168   
169   if (s->serv.type & SV_TYPE_DOMAIN_ENUM) strupper(s->serv.comment);
170   
171   if (newentry)
172     {
173       add_server(work, s);
174       
175       DEBUG(3,("Added "));
176     }
177   else
178     {
179       DEBUG(3,("Updated "));
180     }
181   
182   DEBUG(3,("server entry %s of type %x (%s) to %s %s\n",
183            name,servertype,comment,
184            work->work_group,inet_ntoa(d->bcast_ip)));
185   
186   return(s);
187 }
188
189
190 /*******************************************************************
191   expire old servers in the serverlist
192   ******************************************************************/
193 void expire_servers(time_t t)
194 {
195   struct subnet_record *d;
196   
197   for (d = FIRST_SUBNET; d ; d = NEXT_SUBNET_INCLUDING_WINS(d))
198     {
199       struct work_record *work;
200       
201       for (work = d->workgrouplist; work; work = work->next)
202         {
203           remove_old_servers(work, t, False);
204         }
205     }
206 }
207