dfd8a80baa11578f3c1ec67eb3820c0b119ac72a
[samba.git] / source / nmbd / nmbd_namelistdb.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    Copyright (C) Luke Kenneth Casson Leighton 1994-1997 
7    Copyright (C) Jeremy Allison 1994-1997
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22    
23 */
24
25 #include "includes.h"
26
27 extern int DEBUGLEVEL;
28
29 extern pstring scope;
30 extern char **my_netbios_names;
31
32 uint16 samba_nb_type = 0; /* samba's NetBIOS name type */
33
34
35 /****************************************************************************
36   Set Samba's NetBIOS name type.
37   ****************************************************************************/
38
39 void set_samba_nb_type(void)
40 {
41   if (lp_wins_support() || (*lp_wins_server()))
42     samba_nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */
43   else
44     samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type */
45 }
46
47 /****************************************************************************
48   Returns True if the netbios name is ^1^2__MSBROWSE__^2^1.
49
50   Note: This name is registered if as a master browser or backup browser
51   you are responsible for a workgroup (when you announce a domain by
52   broadcasting on your local subnet, you announce it as coming from this
53   name: see announce_host()).
54
55   **************************************************************************/
56
57 BOOL ms_browser_name(char *name, int type)
58 {
59   return (strequal(name,MSBROWSE) && (type == 0x01));
60 }
61
62 /****************************************************************************
63   Add a netbios name into a namelist.
64   **************************************************************************/
65
66 static void add_name_to_namelist(struct subnet_record *subrec, 
67                                  struct name_record *namerec)
68 {
69   struct name_record *namerec2;
70
71   if (!subrec->namelist)
72   {
73     subrec->namelist = namerec;
74     namerec->prev = NULL;
75     namerec->next = NULL;
76     return;
77   }
78
79   for (namerec2 = subrec->namelist; namerec2->next; namerec2 = namerec2->next) 
80     ;
81
82   namerec2->next = namerec;
83   namerec->next = NULL;
84   namerec->prev = namerec2;
85   namerec->subnet = subrec;
86
87   subrec->namelist_changed = True;
88 }
89
90 /****************************************************************************
91   Remove a name from the namelist.
92   **************************************************************************/
93
94 void remove_name_from_namelist(struct subnet_record *subrec, 
95                                struct name_record *namerec)
96 {
97   if (namerec->next)
98     namerec->next->prev = namerec->prev;
99   if (namerec->prev)
100     namerec->prev->next = namerec->next;
101
102   if(namerec == subrec->namelist)
103     subrec->namelist = namerec->next;
104
105   if(namerec->ip != NULL)
106     free((char *)namerec->ip);
107   free((char *)namerec);
108
109   subrec->namelist_changed = True;
110 }
111
112
113 /****************************************************************************
114   Find a name in a subnet.
115   **************************************************************************/
116
117 struct name_record *find_name_on_subnet(struct subnet_record *subrec,
118                                       struct nmb_name *nmbname, BOOL self_only)
119 {
120   struct name_record *namerec = subrec->namelist;
121   struct name_record *name_ret;
122   
123   for (name_ret = namerec; name_ret; name_ret = name_ret->next)
124   {
125     if (nmb_name_equal(&name_ret->name, nmbname))
126     {
127       /* Self names only - these include permanent names. */
128       if (self_only && (name_ret->source != SELF_NAME) && 
129               (name_ret->source != PERMANENT_NAME) )
130       {
131         continue;
132       }
133       DEBUG(9,("find_name_on_subnet: on subnet %s - found name %s source=%d\n", 
134                 subrec->subnet_name, namestr(nmbname), name_ret->source));
135       return name_ret;
136     }
137   }
138   DEBUG(9,("find_name_on_subnet: on subnet %s - name %s NOT FOUND\n", 
139             subrec->subnet_name, namestr(nmbname)));
140   return NULL;
141 }
142
143 /****************************************************************************
144   Find a name over all known broadcast subnets.
145 **************************************************************************/
146
147 struct name_record *find_name_for_remote_broadcast_subnet( struct nmb_name *nmbname, 
148                                                            BOOL self_only)
149 {
150   struct subnet_record *subrec;
151   struct name_record *namerec = NULL;
152
153   for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
154   {
155     if((namerec = find_name_on_subnet(subrec, nmbname, self_only))!= NULL)
156       break;
157   }
158
159   return namerec;
160 }    
161   
162 /****************************************************************************
163   Update the ttl of an entry in a subnet name list.
164   ****************************************************************************/
165
166 void update_name_ttl(struct name_record *namerec, int ttl)
167 {
168   time_t time_now = time(NULL);
169
170   if(namerec->death_time != PERMANENT_TTL)
171     namerec->death_time = time_now + ttl;
172
173   namerec->refresh_time = time_now + (ttl/2);
174
175   namerec->subnet->namelist_changed = True;
176
177
178 /****************************************************************************
179   Add an entry to a subnet name list.
180   ****************************************************************************/
181
182 struct name_record *add_name_to_subnet(struct subnet_record *subrec,
183                 char *name, int type, uint16 nb_flags, int ttl, 
184                 enum name_source source, int num_ips, struct in_addr *iplist)
185 {
186   struct name_record *namerec;
187   time_t time_now = time(NULL);
188
189   if((namerec = (struct name_record *)malloc(sizeof(*namerec))) == NULL)
190   {
191     DEBUG(0,("add_name_to_subnet: malloc fail.\n"));
192     return NULL;
193   }
194
195   bzero((char *)namerec,sizeof(*namerec));
196
197   namerec->subnet = subrec;
198
199   namerec->num_ips = num_ips;
200   namerec->ip = (struct in_addr *)malloc(sizeof(struct in_addr) * namerec->num_ips);
201   if (!namerec->ip)
202   {
203      DEBUG(0,("add_name_to_subnet: malloc fail when creating ip_flgs.\n"));
204      free((char *)namerec);
205      return NULL;
206   }
207
208   bzero((char *)namerec->ip, sizeof(struct in_addr) * namerec->num_ips);
209
210   memcpy(&namerec->ip[0], iplist, num_ips * sizeof(struct in_addr));
211
212   make_nmb_name(&namerec->name,name,type,scope);
213
214   /* Setup the death_time and refresh_time. */
215   if(ttl == PERMANENT_TTL)
216     namerec->death_time = PERMANENT_TTL;
217   else
218     namerec->death_time = time_now + ttl;
219
220   namerec->refresh_time = time_now + (ttl/2);
221
222   /* Enter the name as active. */
223   namerec->nb_flags = nb_flags | NB_ACTIVE;
224
225   /* If it's our primary name, flag it as so. */
226   if(strequal(my_netbios_names[0],name))
227     namerec->nb_flags |= NB_PERM;
228
229   namerec->source = source;
230   
231   add_name_to_namelist(subrec,namerec);
232
233   DEBUG(3,("add_name_to_subnet: Added netbios name %s with first IP %s ttl=%d nb_flags=%2x to subnet %s\n",
234            namestr(&namerec->name),inet_ntoa(*iplist),ttl,(unsigned int)nb_flags,
235            subrec->subnet_name));
236
237   subrec->namelist_changed = True;
238
239   return(namerec);
240 }
241
242 /*******************************************************************
243  Utility function automatically called when a name refresh or register 
244  succeeds. By definition this is a SELF_NAME (or we wouldn't be registering
245  it).
246  ******************************************************************/
247
248 void standard_success_register(struct subnet_record *subrec, 
249                              struct userdata_struct *userdata,
250                              struct nmb_name *nmbname, uint16 nb_flags, int ttl,
251                              struct in_addr registered_ip)
252 {
253   struct name_record *namerec = find_name_on_subnet(subrec, nmbname, FIND_SELF_NAME);
254
255   if(namerec == NULL)
256     add_name_to_subnet(subrec, nmbname->name, nmbname->name_type,
257                      nb_flags, ttl, SELF_NAME, 1, &registered_ip);
258   else
259     update_name_ttl(namerec, ttl);
260 }
261
262 /*******************************************************************
263  Utility function automatically called when a name refresh or register 
264  fails.
265  ******************************************************************/
266
267 void standard_fail_register(struct subnet_record *subrec, 
268                              struct response_record *rrec, struct nmb_name *nmbname)
269 {
270   struct name_record *namerec = find_name_on_subnet(subrec, nmbname, FIND_SELF_NAME);
271
272   DEBUG(0,("standard_fail_register: Failed to register/refresh name %s on subnet %s\n",
273            namestr(nmbname), subrec->subnet_name));
274
275   /* Remove the name from the subnet. */
276   if(namerec)
277     remove_name_from_namelist(subrec, namerec);
278 }
279
280 /*******************************************************************
281  Utility function to remove an IP address from a name record.
282  ******************************************************************/
283
284 static void remove_nth_ip_in_record( struct name_record *namerec, int ind)
285 {
286   if(ind != namerec->num_ips)
287     memmove( (char *)(&namerec->ip[ind]), (char *)(&namerec->ip[ind+1]), 
288               ( namerec->num_ips - ind - 1) * sizeof(struct in_addr));
289
290   namerec->num_ips--;
291   namerec->subnet->namelist_changed = True;
292 }
293
294 /*******************************************************************
295  Utility function to check if an IP address exists in a name record.
296  ******************************************************************/
297
298 BOOL find_ip_in_name_record(struct name_record *namerec, struct in_addr ip)
299 {
300   int i;
301
302   for(i = 0; i < namerec->num_ips; i++)
303     if(ip_equal( namerec->ip[i], ip))
304       return True;
305
306   return False;
307 }
308
309 /*******************************************************************
310  Utility function to add an IP address to a name record.
311  ******************************************************************/
312
313 void add_ip_to_name_record(struct name_record *namerec, struct in_addr new_ip)
314 {
315   struct in_addr *new_list;
316
317   /* Don't add one we already have. */
318   if(find_ip_in_name_record( namerec, new_ip))
319     return;
320   
321   if((new_list = (struct in_addr *)malloc( (namerec->num_ips + 1)*sizeof(struct in_addr)) )== NULL)
322   {
323     DEBUG(0,("add_ip_to_name_record: Malloc fail !\n"));
324     return;
325   }
326
327   memcpy((char *)new_list, (char *)namerec->ip, namerec->num_ips *sizeof(struct in_addr));
328   new_list[namerec->num_ips] = new_ip;
329
330   free((char *)namerec->ip);
331   namerec->ip = new_list;
332   namerec->num_ips += 1;
333
334   namerec->subnet->namelist_changed = True;
335 }
336
337 /*******************************************************************
338  Utility function to remove an IP address from a name record.
339  ******************************************************************/
340
341 void remove_ip_from_name_record( struct name_record *namerec, struct in_addr remove_ip)
342 {
343   /* Try and find the requested ip address - remove it. */
344   int i;
345   int orig_num = namerec->num_ips;
346
347   for(i = 0; i < orig_num; i++)
348     if( ip_equal( remove_ip, namerec->ip[i]) )
349     {
350       remove_nth_ip_in_record( namerec, i);
351       break;
352     }
353 }
354
355 /*******************************************************************
356  Utility function that release_name callers can plug into as the
357  success function when a name release is successful. Used to save
358  duplication of success_function code.
359  ******************************************************************/
360
361 void standard_success_release(struct subnet_record *subrec, 
362                              struct userdata_struct *userdata,
363                              struct nmb_name *nmbname, struct in_addr released_ip)
364 {
365   struct name_record *namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME);
366
367   if(namerec == NULL)
368   {
369     DEBUG(0,("standard_success_release: Name release for name %s IP %s on subnet %s. Name \
370 was not found on subnet.\n", namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name));
371     return;
372   }
373   else
374   {
375     int orig_num = namerec->num_ips;
376
377     remove_ip_from_name_record( namerec, released_ip);
378
379     if(namerec->num_ips == orig_num)
380       DEBUG(0,("standard_success_release: Name release for name %s IP %s on subnet %s. This ip \
381 is not known for this name.\n", namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name ));
382   }
383
384   if (namerec->num_ips == 0)
385     remove_name_from_namelist(subrec, namerec);
386 }
387
388 /*******************************************************************
389   Expires old names in a subnet namelist.
390   ******************************************************************/
391
392 void expire_names_on_subnet(struct subnet_record *subrec, time_t t)
393 {
394   struct name_record *namerec;
395   struct name_record *next_namerec;
396
397   for (namerec = subrec->namelist; namerec; namerec = next_namerec)
398   {
399     next_namerec = namerec->next;
400     if ((namerec->death_time != PERMANENT_TTL) && (namerec->death_time < t))
401     {
402       if (namerec->source == SELF_NAME)
403       {
404         DEBUG(3,("expire_names_on_subnet: Subnet %s not expiring SELF name %s\n", 
405              subrec->subnet_name, namestr(&namerec->name)));
406         namerec->death_time += 300;
407         namerec->subnet->namelist_changed = True;
408         continue;
409       }
410       DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n", 
411                  subrec->subnet_name, namestr(&namerec->name)));
412   
413       remove_name_from_namelist(subrec, namerec);
414     }
415   }
416 }
417
418 /*******************************************************************
419   Expires old names in all subnet namelists.
420   ******************************************************************/
421
422 void expire_names(time_t t)
423 {
424   struct subnet_record *subrec;
425
426   for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
427   {
428     expire_names_on_subnet(subrec, t);
429   }
430 }
431
432 /****************************************************************************
433   Add the magic samba names, useful for finding samba servers.
434   These go directly into the name list for a particular subnet,
435   without going through the normal registration process.
436   When adding them to the unicast subnet, add them as a list of
437   all broadcast subnet IP addresses.
438 **************************************************************************/
439
440 void add_samba_names_to_subnet(struct subnet_record *subrec)
441 {
442   struct in_addr *iplist = &subrec->myip;
443   int num_ips = 1;
444
445   /* These names are added permanently (ttl of zero) and will NOT be
446      refreshed.  */
447
448   if((subrec == unicast_subnet) || (subrec == wins_server_subnet))
449   {
450     struct subnet_record *bcast_subrecs;
451     int i;
452     /* Create an IP list containing all our known subnets. */
453
454     num_ips = iface_count();
455     if((iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) )) == NULL)
456     {
457       DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n"));
458       return;
459     }
460
461     for(bcast_subrecs = FIRST_SUBNET, i = 0; bcast_subrecs; 
462                  bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++)
463       iplist[i] = bcast_subrecs->myip;
464
465   }
466
467   add_name_to_subnet(subrec,"*",0x0,samba_nb_type, PERMANENT_TTL,
468                      PERMANENT_NAME, num_ips, iplist);
469   add_name_to_subnet(subrec,"*",0x20,samba_nb_type,PERMANENT_TTL,
470                      PERMANENT_NAME, num_ips, iplist);
471   add_name_to_subnet(subrec,"__SAMBA__",0x20,samba_nb_type,PERMANENT_TTL,
472                    PERMANENT_NAME, num_ips, iplist);
473   add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL,
474                    PERMANENT_NAME, num_ips, iplist);
475
476   if(iplist != &subrec->myip)
477     free((char *)iplist);
478 }
479
480 /****************************************************************************
481  Dump the contents of the namelists on all the subnets (including unicast)
482  into a file. Initiated by SIGHUP - used to debug the state of the namelists.
483 **************************************************************************/
484
485 static void dump_subnet_namelist( struct subnet_record *subrec, FILE *fp)
486 {
487   struct name_record *namerec;
488   char *src_type;
489   struct tm *tm;
490   int i;
491
492   fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name);
493   for (namerec = subrec->namelist; namerec; namerec = namerec->next)
494   {
495     fprintf(fp,"\tName = %s\t", namestr(&namerec->name));
496     switch(namerec->source)
497     {
498       case LMHOSTS_NAME:
499         src_type = "LMHOSTS_NAME";
500         break;
501       case WINS_PROXY_NAME:
502         src_type = "WINS_PROXY_NAME";
503         break;
504       case REGISTER_NAME:
505         src_type = "REGISTER_NAME";
506         break;
507       case SELF_NAME:
508         src_type = "SELF_NAME";
509         break;
510       case DNS_NAME:
511         src_type = "DNS_NAME";
512         break;
513       case DNSFAIL_NAME:
514         src_type = "DNSFAIL_NAME";
515         break;
516       case PERMANENT_NAME:
517         src_type = "PERMANENT_NAME";
518         break;
519       default:
520         src_type = "unknown!";
521         break;
522     }
523     fprintf(fp, "Source = %s\nb_flags = %x\t", src_type, namerec->nb_flags);
524
525     if(namerec->death_time != PERMANENT_TTL)
526     {
527       tm = LocalTime(&namerec->death_time);
528       fprintf(fp, "death_time = %s\t", asctime(tm));
529     }
530     else
531       fprintf(fp, "death_time = PERMANENT\t");
532
533     if(namerec->refresh_time != PERMANENT_TTL)
534     {
535       tm = LocalTime(&namerec->refresh_time);
536       fprintf(fp, "refresh_time = %s\n", asctime(tm));
537     }
538     else
539       fprintf(fp, "refresh_time = PERMANENT\n");
540
541     fprintf(fp, "\t\tnumber of IPS = %d", namerec->num_ips);
542     for(i = 0; i < namerec->num_ips; i++)
543       fprintf(fp, "\t%s", inet_ntoa(namerec->ip[i]));
544
545     fprintf(fp, "\n\n");
546   }
547 }
548
549 /****************************************************************************
550  Dump the contents of the namelists on all the subnets (including unicast)
551  into a file. Initiated by SIGHUP - used to debug the state of the namelists.
552 **************************************************************************/
553
554 void dump_all_namelists()
555 {
556   fstring fname;
557   FILE *fp; 
558   struct subnet_record *subrec;
559
560   pstrcpy(fname,lp_lockdir());
561   trim_string(fname,NULL,"/");
562   strcat(fname,"/"); 
563   strcat(fname,"namelist.debug");
564
565   fp = fopen(fname,"w");
566      
567   if (!fp)
568   { 
569     DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n",
570               fname,strerror(errno)));
571     return;
572   }
573       
574   for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
575     dump_subnet_namelist( subrec, fp);
576
577   if(!we_are_a_wins_client())
578     dump_subnet_namelist(unicast_subnet, fp);
579
580   if(remote_broadcast_subnet->namelist != NULL)
581     dump_subnet_namelist(remote_broadcast_subnet, fp);
582
583   if(wins_server_subnet != NULL)
584     dump_subnet_namelist( wins_server_subnet, fp);
585   fclose(fp);
586 }