260f8f3475e0072a5cdaa3a01f6be95c321cf399
[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-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    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 extern int ClientDGRAM;
36
37 extern int DEBUGLEVEL;
38
39 extern pstring myname;
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       if (remove_all || (s->death_time && (t == -1 || s->death_time < t)))
62     {
63       DEBUG(3,("Removing dead server %s\n",s->serv.name));
64       updatedlists = True;
65       nexts = s->next;
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       else
76     {
77       nexts = s->next;
78     }
79     }
80 }
81
82
83 /***************************************************************************
84   add a server into the list
85   **************************************************************************/
86 static void add_server(struct work_record *work,struct server_record *s)
87 {
88   struct server_record *s2;
89
90   if (!work->serverlist) {
91     work->serverlist = s;
92     s->prev = NULL;
93     s->next = NULL;
94     return;
95   }
96
97   for (s2 = work->serverlist; s2->next; s2 = s2->next) ;
98
99   s2->next = s;
100   s->next = NULL;
101   s->prev = s2;
102 }
103
104
105 /****************************************************************************
106   find a server in a server list.
107   **************************************************************************/
108 struct server_record *find_server(struct work_record *work, char *name)
109 {
110     struct server_record *ret;
111   
112     if (!work) return NULL;
113
114     for (ret = work->serverlist; ret; ret = ret->next)
115     {
116         if (strequal(ret->serv.name,name))
117         {
118             return ret;
119         }
120     }
121     return NULL;
122 }
123
124
125 /****************************************************************************
126   add a server entry
127   ****************************************************************************/
128 struct server_record *add_server_entry(struct subnet_record *d, 
129                        struct work_record *work,
130                        char *name,int servertype, 
131                        int ttl,char *comment,
132                        BOOL replace)
133 {
134   BOOL newentry=False;
135   struct server_record *s;
136   int token = conf_workgroup_name_to_token(work->work_group, myname);
137
138   if (name[0] == '*')
139   {
140       return (NULL);
141   }
142   
143   s = find_server(work, name);
144
145   if (s && !replace)
146   {
147     DEBUG(4,("Not replacing %s\n",name));
148     return(s);
149   }
150   
151   if (!s || s->serv.type != servertype || !strequal(s->serv.comment, comment))
152     updatedlists=True;
153
154   if (!s)
155   {
156     newentry = True;
157     s = (struct server_record *)malloc(sizeof(*s));
158       
159     if (!s) return(NULL);
160       
161     bzero((char *)s,sizeof(*s));
162   }
163   
164   if (conf_should_workgroup_member(token))
165   {
166     if (servertype) servertype |= SV_TYPE_LOCAL_LIST_ONLY;
167   }
168   else
169   {
170       servertype &= ~SV_TYPE_LOCAL_LIST_ONLY;
171   }
172   
173   /* update the entry */
174   StrnCpy(s->serv.name,name,sizeof(s->serv.name)-1);
175   StrnCpy(s->serv.comment,comment,sizeof(s->serv.comment)-1);
176   strupper(s->serv.name);
177   s->serv.type  = servertype;
178   s->death_time = servertype ? (ttl?time(NULL)+ttl*3:0) : (time(NULL)-1);
179   
180   /* for a domain entry, the comment field refers to the server name */
181   
182   if (s->serv.type & SV_TYPE_DOMAIN_ENUM) strupper(s->serv.comment);
183   
184   if (newentry)
185     {
186       add_server(work, s);
187       
188       DEBUG(3,("Added "));
189     }
190   else
191     {
192       DEBUG(3,("Updated "));
193     }
194   
195   DEBUG(3,("server entry %s of type %x (%s) to %s %s\n",
196        name,servertype,comment,
197        work->work_group,inet_ntoa(d->bcast_ip)));
198   
199   return(s);
200 }
201
202
203 /*******************************************************************
204   expire old servers in the serverlist
205   ******************************************************************/
206 void expire_servers(time_t t)
207 {
208   struct subnet_record *d;
209   
210   for (d = subnetlist ; d ; d = d->next)
211     {
212       struct work_record *work;
213       
214       for (work = d->workgrouplist; work; work = work->next)
215     {
216       remove_old_servers(work, t, False);
217     }
218     }
219 }
220