74c7a96baa9b56fa82cd0f8aed02959a6cd3a59c
[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
50   ******************************************************************/
51 void remove_old_servers(struct work_record *work, time_t t)
52 {
53   struct server_record *s;
54   struct server_record *nexts;
55   
56   /* expire old entries in the serverlist */
57   for (s = work->serverlist; s; s = nexts)
58     {
59       if (t == -1 || (s->death_time && s->death_time < t))
60         {
61           DEBUG(3,("Removing dead server %s\n",s->serv.name));
62           updatedlists = True;
63           nexts = s->next;
64           
65           if (s->prev) s->prev->next = s->next;
66           if (s->next) s->next->prev = s->prev;
67           
68           if (work->serverlist == s) 
69             work->serverlist = s->next; 
70
71           free(s);
72         }
73       else
74         {
75           nexts = s->next;
76         }
77     }
78 }
79
80
81 /***************************************************************************
82   add a server into the list
83   **************************************************************************/
84 static void add_server(struct work_record *work,struct server_record *s)
85 {
86   struct server_record *s2;
87
88   if (!work->serverlist) {
89     work->serverlist = s;
90     s->prev = NULL;
91     s->next = NULL;
92     return;
93   }
94
95   for (s2 = work->serverlist; s2->next; s2 = s2->next) ;
96
97   s2->next = s;
98   s->next = NULL;
99   s->prev = s2;
100 }
101
102
103 /****************************************************************************
104   add a server entry
105   ****************************************************************************/
106 struct server_record *add_server_entry(struct subnet_record *d, 
107                                        struct work_record *work,
108                                        char *name,int servertype, 
109                                        int ttl,char *comment,
110                                        BOOL replace)
111 {
112   BOOL newentry=False;
113   struct server_record *s;
114   
115   if (name[0] == '*')
116     {
117       return (NULL);
118     }
119   
120   for (s = work->serverlist; s; s = s->next)
121     {
122       if (strequal(name,s->serv.name)) break;
123     }
124   
125   if (s && !replace)
126     {
127       DEBUG(4,("Not replacing %s\n",name));
128       return(s);
129     }
130   
131   if (!s || s->serv.type != servertype || !strequal(s->serv.comment, comment))
132     updatedlists=True;
133
134   if (!s)
135     {
136       newentry = True;
137       s = (struct server_record *)malloc(sizeof(*s));
138       
139       if (!s) return(NULL);
140       
141       bzero((char *)s,sizeof(*s));
142     }
143   
144   
145   if (d->my_interface && strequal(lp_workgroup(),work->work_group))
146     {
147           if (servertype)
148         servertype |= SV_TYPE_LOCAL_LIST_ONLY;
149     }
150   else
151     {
152       servertype &= ~SV_TYPE_LOCAL_LIST_ONLY;
153     }
154   
155   /* update the entry */
156   StrnCpy(s->serv.name,name,sizeof(s->serv.name)-1);
157   StrnCpy(s->serv.comment,comment,sizeof(s->serv.comment)-1);
158   strupper(s->serv.name);
159   s->serv.type  = servertype;
160   s->death_time = servertype ? (ttl?time(NULL)+ttl*3:0) : (time(NULL)-1);
161   
162   /* for a domain entry, the comment field refers to the server name */
163   
164   if (s->serv.type & SV_TYPE_DOMAIN_ENUM) strupper(s->serv.comment);
165   
166   if (newentry)
167     {
168       add_server(work, s);
169       
170       DEBUG(3,("Added "));
171     }
172   else
173     {
174       DEBUG(3,("Updated "));
175     }
176   
177   DEBUG(3,("server entry %s of type %x (%s) to %s %s\n",
178            name,servertype,comment,
179            work->work_group,inet_ntoa(d->bcast_ip)));
180   
181   return(s);
182 }
183
184
185 /*******************************************************************
186   expire old servers in the serverlist
187   ******************************************************************/
188 void expire_servers(time_t t)
189 {
190   struct subnet_record *d;
191   
192   for (d = subnetlist ; d ; d = d->next)
193     {
194       struct work_record *work;
195       
196       for (work = d->workgrouplist; work; work = work->next)
197         {
198           remove_old_servers(work, t);
199         }
200     }
201 }
202