JHT => Modified for RedHat Linux for DEC Alpha platform includes.
[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   
137   if (name[0] == '*')
138   {
139       return (NULL);
140   }
141   
142   s = find_server(work, name);
143
144   if (s && !replace)
145   {
146     DEBUG(4,("Not replacing %s\n",name));
147     return(s);
148   }
149   
150   if (!s || s->serv.type != servertype || !strequal(s->serv.comment, comment))
151     updatedlists=True;
152
153   if (!s)
154   {
155     newentry = True;
156     s = (struct server_record *)malloc(sizeof(*s));
157       
158     if (!s) return(NULL);
159       
160     bzero((char *)s,sizeof(*s));
161   }
162   
163   
164   if (strequal(lp_workgroup(),work->work_group))
165     {
166           if (servertype)
167         servertype |= SV_TYPE_LOCAL_LIST_ONLY;
168     }
169   else
170     {
171       servertype &= ~SV_TYPE_LOCAL_LIST_ONLY;
172     }
173   
174   /* update the entry */
175   StrnCpy(s->serv.name,name,sizeof(s->serv.name)-1);
176   StrnCpy(s->serv.comment,comment,sizeof(s->serv.comment)-1);
177   strupper(s->serv.name);
178   s->serv.type  = servertype;
179   s->death_time = servertype ? (ttl?time(NULL)+ttl*3:0) : (time(NULL)-1);
180   
181   /* for a domain entry, the comment field refers to the server name */
182   
183   if (s->serv.type & SV_TYPE_DOMAIN_ENUM) strupper(s->serv.comment);
184   
185   if (newentry)
186     {
187       add_server(work, s);
188       
189       DEBUG(3,("Added "));
190     }
191   else
192     {
193       DEBUG(3,("Updated "));
194     }
195   
196   DEBUG(3,("server entry %s of type %x (%s) to %s %s\n",
197            name,servertype,comment,
198            work->work_group,inet_ntoa(d->bcast_ip)));
199   
200   return(s);
201 }
202
203
204 /*******************************************************************
205   expire old servers in the serverlist
206   ******************************************************************/
207 void expire_servers(time_t t)
208 {
209   struct subnet_record *d;
210   
211   for (d = subnetlist ; d ; d = d->next)
212     {
213       struct work_record *work;
214       
215       for (work = d->workgrouplist; work; work = work->next)
216         {
217           remove_old_servers(work, t, False);
218         }
219     }
220 }
221