2 Unix SMB/CIFS implementation.
3 NBT netbios routines and daemon - version 2
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Luke Kenneth Casson Leighton 1994-1998
6 Copyright (C) Jeremy Allison 1994-1998
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 uint16 samba_nb_type
= 0; /* samba's NetBIOS name type */
29 /* ************************************************************************** **
30 * Set Samba's NetBIOS name type.
31 * ************************************************************************** **
33 void set_samba_nb_type(void)
35 if( lp_wins_support() || wins_srv_count() )
36 samba_nb_type
= NB_HFLAG
; /* samba is a 'hybrid' node type. */
38 samba_nb_type
= NB_BFLAG
; /* samba is broadcast-only node type. */
39 } /* set_samba_nb_type */
41 /* ************************************************************************** **
42 * Convert a NetBIOS name to upper case.
43 * ************************************************************************** **
45 static void upcase_name( struct nmb_name
*target
, struct nmb_name
*source
)
50 (void)memcpy( target
, source
, sizeof( struct nmb_name
) );
52 strupper( target
->name
);
53 strupper( target
->scope
);
55 /* fudge... We're using a byte-by-byte compare, so we must be sure that
56 * unused space doesn't have garbage in it.
58 for( i
= strlen( target
->name
); i
< sizeof( target
->name
); i
++ )
59 target
->name
[i
] = '\0';
60 for( i
= strlen( target
->scope
); i
< sizeof( target
->scope
); i
++ )
61 target
->scope
[i
] = '\0';
64 /* ************************************************************************** **
65 * Add a new or overwrite an existing namelist entry.
66 * ************************************************************************** **
68 static void update_name_in_namelist( struct subnet_record
*subrec
,
69 struct name_record
*namerec
)
71 struct name_record
*oldrec
= NULL
;
73 (void)ubi_trInsert( subrec
->namelist
, namerec
, &(namerec
->name
), &oldrec
);
76 SAFE_FREE( oldrec
->data
.ip
);
79 } /* update_name_in_namelist */
81 /* ************************************************************************** **
82 * Remove a name from the namelist.
83 * ************************************************************************** **
85 void remove_name_from_namelist( struct subnet_record
*subrec
,
86 struct name_record
*namerec
)
88 (void)ubi_trRemove( subrec
->namelist
, namerec
);
90 SAFE_FREE(namerec
->data
.ip
);
92 ZERO_STRUCTP(namerec
);
95 subrec
->namelist_changed
= True
;
96 } /* remove_name_from_namelist */
98 /* ************************************************************************** **
99 * Find a name in a subnet.
100 * ************************************************************************** **
102 struct name_record
*find_name_on_subnet( struct subnet_record
*subrec
,
103 struct nmb_name
*nmbname
,
106 struct nmb_name uc_name
[1];
107 struct name_record
*name_ret
;
109 upcase_name( uc_name
, nmbname
);
110 name_ret
= (struct name_record
*)ubi_trFind( subrec
->namelist
, uc_name
);
113 /* Self names only - these include permanent names. */
115 && (name_ret
->data
.source
!= SELF_NAME
)
116 && (name_ret
->data
.source
!= PERMANENT_NAME
) )
119 ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n",
120 subrec
->subnet_name
, nmb_namestr(nmbname
) ) );
123 DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n",
124 subrec
->subnet_name
, nmb_namestr(nmbname
), name_ret
->data
.source
) );
128 ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n",
129 subrec
->subnet_name
, nmb_namestr(nmbname
) ) );
131 } /* find_name_on_subnet */
133 /* ************************************************************************** **
134 * Find a name over all known broadcast subnets.
135 * ************************************************************************** **
137 struct name_record
*find_name_for_remote_broadcast_subnet(
138 struct nmb_name
*nmbname
,
141 struct subnet_record
*subrec
;
142 struct name_record
*namerec
= NULL
;
144 for( subrec
= FIRST_SUBNET
;
146 subrec
= NEXT_SUBNET_EXCLUDING_UNICAST(subrec
) )
148 if( NULL
!= (namerec
= find_name_on_subnet(subrec
, nmbname
, self_only
)) )
153 } /* find_name_for_remote_broadcast_subnet */
155 /* ************************************************************************** **
156 * Update the ttl of an entry in a subnet name list.
157 * ************************************************************************** **
159 void update_name_ttl( struct name_record
*namerec
, int ttl
)
161 time_t time_now
= time(NULL
);
163 if( namerec
->data
.death_time
!= PERMANENT_TTL
)
164 namerec
->data
.death_time
= time_now
+ ttl
;
166 namerec
->data
.refresh_time
= time_now
+ MIN((ttl
/2), MAX_REFRESH_TIME
);
168 namerec
->subnet
->namelist_changed
= True
;
169 } /* update_name_ttl */
171 /* ************************************************************************** **
172 * Add an entry to a subnet name list.
173 * ************************************************************************** **
175 struct name_record
*add_name_to_subnet( struct subnet_record
*subrec
,
180 enum name_source source
,
182 struct in_addr
*iplist
)
184 struct name_record
*namerec
;
185 time_t time_now
= time(NULL
);
187 namerec
= (struct name_record
*)malloc( sizeof(*namerec
) );
188 if( NULL
== namerec
)
190 DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) );
194 memset( (char *)namerec
, '\0', sizeof(*namerec
) );
195 namerec
->data
.ip
= (struct in_addr
*)malloc( sizeof(struct in_addr
)
197 if( NULL
== namerec
->data
.ip
)
199 DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) );
201 ZERO_STRUCTP(namerec
);
206 namerec
->subnet
= subrec
;
208 make_nmb_name(&namerec
->name
, name
, type
);
209 upcase_name(&namerec
->name
, NULL
);
211 /* Enter the name as active. */
212 namerec
->data
.nb_flags
= nb_flags
| NB_ACTIVE
;
213 namerec
->data
.wins_flags
= WINS_ACTIVE
;
215 /* If it's our primary name, flag it as so. */
216 if( strequal( my_netbios_names(0), name
) )
217 namerec
->data
.nb_flags
|= NB_PERM
;
220 namerec
->data
.num_ips
= num_ips
;
221 memcpy( (namerec
->data
.ip
), iplist
, num_ips
* sizeof(struct in_addr
) );
224 namerec
->data
.source
= source
;
226 /* Setup the death_time and refresh_time. */
227 if( ttl
== PERMANENT_TTL
)
228 namerec
->data
.death_time
= PERMANENT_TTL
;
230 namerec
->data
.death_time
= time_now
+ ttl
;
232 namerec
->data
.refresh_time
= time_now
+ MIN((ttl
/2), MAX_REFRESH_TIME
);
234 /* Now add the record to the name list. */
235 update_name_in_namelist( subrec
, namerec
);
237 DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \
238 ttl=%d nb_flags=%2x to subnet %s\n",
239 nmb_namestr( &namerec
->name
),
240 inet_ntoa( *iplist
),
242 (unsigned int)nb_flags
,
243 subrec
->subnet_name
) );
245 subrec
->namelist_changed
= True
;
250 /*******************************************************************
251 Utility function automatically called when a name refresh or register
252 succeeds. By definition this is a SELF_NAME (or we wouldn't be registering
254 ******************************************************************/
256 void standard_success_register(struct subnet_record
*subrec
,
257 struct userdata_struct
*userdata
,
258 struct nmb_name
*nmbname
, uint16 nb_flags
, int ttl
,
259 struct in_addr registered_ip
)
261 struct name_record
*namerec
;
263 namerec
= find_name_on_subnet( subrec
, nmbname
, FIND_SELF_NAME
);
264 if( NULL
== namerec
)
265 (void)add_name_to_subnet( subrec
, nmbname
->name
, nmbname
->name_type
,
266 nb_flags
, ttl
, SELF_NAME
, 1, ®istered_ip
);
268 update_name_ttl( namerec
, ttl
);
271 /*******************************************************************
272 Utility function automatically called when a name refresh or register
273 fails. Note that this is only ever called on a broadcast subnet with
274 one IP address per name. This is why it can just delete the name
275 without enumerating the IP adresses. JRA.
276 ******************************************************************/
278 void standard_fail_register( struct subnet_record
*subrec
,
279 struct response_record
*rrec
,
280 struct nmb_name
*nmbname
)
282 struct name_record
*namerec
;
284 namerec
= find_name_on_subnet( subrec
, nmbname
, FIND_SELF_NAME
);
286 DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \
288 nmb_namestr(nmbname
), subrec
->subnet_name
) );
290 /* Remove the name from the subnet. */
292 remove_name_from_namelist(subrec
, namerec
);
295 /*******************************************************************
296 Utility function to remove an IP address from a name record.
297 ******************************************************************/
299 static void remove_nth_ip_in_record( struct name_record
*namerec
, int ind
)
301 if( ind
!= namerec
->data
.num_ips
)
302 memmove( (char *)(&namerec
->data
.ip
[ind
]),
303 (char *)(&namerec
->data
.ip
[ind
+1]),
304 ( namerec
->data
.num_ips
- ind
- 1) * sizeof(struct in_addr
) );
306 namerec
->data
.num_ips
--;
307 namerec
->subnet
->namelist_changed
= True
;
310 /*******************************************************************
311 Utility function to check if an IP address exists in a name record.
312 ******************************************************************/
314 BOOL
find_ip_in_name_record( struct name_record
*namerec
, struct in_addr ip
)
318 for(i
= 0; i
< namerec
->data
.num_ips
; i
++)
319 if(ip_equal( namerec
->data
.ip
[i
], ip
))
325 /*******************************************************************
326 Utility function to add an IP address to a name record.
327 ******************************************************************/
329 void add_ip_to_name_record( struct name_record
*namerec
, struct in_addr new_ip
)
331 struct in_addr
*new_list
;
333 /* Don't add one we already have. */
334 if( find_ip_in_name_record( namerec
, new_ip
) )
337 new_list
= (struct in_addr
*)malloc( (namerec
->data
.num_ips
+ 1)
338 * sizeof(struct in_addr
) );
339 if( NULL
== new_list
)
341 DEBUG(0,("add_ip_to_name_record: Malloc fail !\n"));
345 memcpy( (char *)new_list
,
346 (char *)namerec
->data
.ip
,
347 namerec
->data
.num_ips
* sizeof(struct in_addr
) );
348 new_list
[namerec
->data
.num_ips
] = new_ip
;
350 SAFE_FREE(namerec
->data
.ip
);
351 namerec
->data
.ip
= new_list
;
352 namerec
->data
.num_ips
+= 1;
354 namerec
->subnet
->namelist_changed
= True
;
357 /*******************************************************************
358 Utility function to remove an IP address from a name record.
359 ******************************************************************/
361 void remove_ip_from_name_record( struct name_record
*namerec
,
362 struct in_addr remove_ip
)
364 /* Try and find the requested ip address - remove it. */
366 int orig_num
= namerec
->data
.num_ips
;
368 for(i
= 0; i
< orig_num
; i
++)
369 if( ip_equal( remove_ip
, namerec
->data
.ip
[i
]) )
371 remove_nth_ip_in_record( namerec
, i
);
376 /*******************************************************************
377 Utility function that release_name callers can plug into as the
378 success function when a name release is successful. Used to save
379 duplication of success_function code.
380 ******************************************************************/
382 void standard_success_release( struct subnet_record
*subrec
,
383 struct userdata_struct
*userdata
,
384 struct nmb_name
*nmbname
,
385 struct in_addr released_ip
)
387 struct name_record
*namerec
;
389 namerec
= find_name_on_subnet( subrec
, nmbname
, FIND_ANY_NAME
);
391 if( namerec
== NULL
)
393 DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
394 on subnet %s. Name was not found on subnet.\n",
395 nmb_namestr(nmbname
),
396 inet_ntoa(released_ip
),
397 subrec
->subnet_name
) );
402 int orig_num
= namerec
->data
.num_ips
;
404 remove_ip_from_name_record( namerec
, released_ip
);
406 if( namerec
->data
.num_ips
== orig_num
)
407 DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
408 on subnet %s. This ip is not known for this name.\n",
409 nmb_namestr(nmbname
),
410 inet_ntoa(released_ip
),
411 subrec
->subnet_name
) );
414 if( namerec
->data
.num_ips
== 0 )
415 remove_name_from_namelist( subrec
, namerec
);
418 /*******************************************************************
419 Expires old names in a subnet namelist.
420 ******************************************************************/
422 void expire_names_on_subnet(struct subnet_record
*subrec
, time_t t
)
424 struct name_record
*namerec
;
425 struct name_record
*next_namerec
;
427 for( namerec
= (struct name_record
*)ubi_trFirst( subrec
->namelist
);
429 namerec
= next_namerec
)
431 next_namerec
= (struct name_record
*)ubi_trNext( namerec
);
432 if( (namerec
->data
.death_time
!= PERMANENT_TTL
)
433 && (namerec
->data
.death_time
< t
) )
435 if( namerec
->data
.source
== SELF_NAME
)
437 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \
439 subrec
->subnet_name
, nmb_namestr(&namerec
->name
) ) );
440 namerec
->data
.death_time
+= 300;
441 namerec
->subnet
->namelist_changed
= True
;
444 DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n",
445 subrec
->subnet_name
, nmb_namestr(&namerec
->name
)));
447 remove_name_from_namelist( subrec
, namerec
);
452 /*******************************************************************
453 Expires old names in all subnet namelists.
454 ******************************************************************/
456 void expire_names(time_t t
)
458 struct subnet_record
*subrec
;
460 for( subrec
= FIRST_SUBNET
;
462 subrec
= NEXT_SUBNET_INCLUDING_UNICAST(subrec
) )
464 expire_names_on_subnet( subrec
, t
);
468 /****************************************************************************
469 Add the magic samba names, useful for finding samba servers.
470 These go directly into the name list for a particular subnet,
471 without going through the normal registration process.
472 When adding them to the unicast subnet, add them as a list of
473 all broadcast subnet IP addresses.
474 **************************************************************************/
476 void add_samba_names_to_subnet( struct subnet_record
*subrec
)
478 struct in_addr
*iplist
= &subrec
->myip
;
481 /* These names are added permanently (ttl of zero) and will NOT be
484 if( (subrec
== unicast_subnet
)
485 || (subrec
== wins_server_subnet
)
486 || (subrec
== remote_broadcast_subnet
) )
488 struct subnet_record
*bcast_subrecs
;
490 /* Create an IP list containing all our known subnets. */
492 num_ips
= iface_count();
493 iplist
= (struct in_addr
*)malloc( num_ips
* sizeof(struct in_addr
) );
496 DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n"));
500 for( bcast_subrecs
= FIRST_SUBNET
, i
= 0;
502 bcast_subrecs
= NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs
), i
++ )
503 iplist
[i
] = bcast_subrecs
->myip
;
507 (void)add_name_to_subnet(subrec
,"*",0x0,samba_nb_type
, PERMANENT_TTL
,
508 PERMANENT_NAME
, num_ips
, iplist
);
509 (void)add_name_to_subnet(subrec
,"*",0x20,samba_nb_type
,PERMANENT_TTL
,
510 PERMANENT_NAME
, num_ips
, iplist
);
511 (void)add_name_to_subnet(subrec
,"__SAMBA__",0x20,samba_nb_type
,PERMANENT_TTL
,
512 PERMANENT_NAME
, num_ips
, iplist
);
513 (void)add_name_to_subnet(subrec
,"__SAMBA__",0x00,samba_nb_type
,PERMANENT_TTL
,
514 PERMANENT_NAME
, num_ips
, iplist
);
516 if(iplist
!= &subrec
->myip
)
520 /****************************************************************************
521 Dump the contents of the namelists on all the subnets (including unicast)
522 into a file. Initiated by SIGHUP - used to debug the state of the namelists.
523 **************************************************************************/
525 static void dump_subnet_namelist( struct subnet_record
*subrec
, XFILE
*fp
)
527 struct name_record
*namerec
;
528 const char *src_type
;
532 x_fprintf(fp
, "Subnet %s\n----------------------\n", subrec
->subnet_name
);
533 for( namerec
= (struct name_record
*)ubi_trFirst( subrec
->namelist
);
535 namerec
= (struct name_record
*)ubi_trNext( namerec
) )
537 x_fprintf(fp
,"\tName = %s\t", nmb_namestr(&namerec
->name
));
538 switch(namerec
->data
.source
)
541 src_type
= "LMHOSTS_NAME";
543 case WINS_PROXY_NAME
:
544 src_type
= "WINS_PROXY_NAME";
547 src_type
= "REGISTER_NAME";
550 src_type
= "SELF_NAME";
553 src_type
= "DNS_NAME";
556 src_type
= "DNSFAIL_NAME";
559 src_type
= "PERMANENT_NAME";
562 src_type
= "unknown!";
565 x_fprintf(fp
,"Source = %s\nb_flags = %x\t", src_type
, namerec
->data
.nb_flags
);
567 if(namerec
->data
.death_time
!= PERMANENT_TTL
)
569 tm
= LocalTime(&namerec
->data
.death_time
);
570 x_fprintf(fp
, "death_time = %s\t", asctime(tm
));
573 x_fprintf(fp
, "death_time = PERMANENT\t");
575 if(namerec
->data
.refresh_time
!= PERMANENT_TTL
)
577 tm
= LocalTime(&namerec
->data
.refresh_time
);
578 x_fprintf(fp
, "refresh_time = %s\n", asctime(tm
));
581 x_fprintf(fp
, "refresh_time = PERMANENT\n");
583 x_fprintf(fp
, "\t\tnumber of IPS = %d", namerec
->data
.num_ips
);
584 for(i
= 0; i
< namerec
->data
.num_ips
; i
++)
585 x_fprintf(fp
, "\t%s", inet_ntoa(namerec
->data
.ip
[i
]));
587 x_fprintf(fp
, "\n\n");
591 /****************************************************************************
592 Dump the contents of the namelists on all the subnets (including unicast)
593 into a file. Initiated by SIGHUP - used to debug the state of the namelists.
594 **************************************************************************/
596 void dump_all_namelists(void)
599 struct subnet_record
*subrec
;
601 fp
= x_fopen(lock_path("namelist.debug"),O_WRONLY
|O_CREAT
|O_TRUNC
, 0644);
605 DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n",
606 "namelist.debug",strerror(errno
)));
610 for( subrec
= FIRST_SUBNET
;
612 subrec
= NEXT_SUBNET_INCLUDING_UNICAST(subrec
) )
613 dump_subnet_namelist( subrec
, fp
);
615 if( !we_are_a_wins_client() )
616 dump_subnet_namelist( unicast_subnet
, fp
);
618 if( remote_broadcast_subnet
->namelist
!= NULL
)
619 dump_subnet_namelist( remote_broadcast_subnet
, fp
);
621 if( wins_server_subnet
!= NULL
)
622 dump_subnet_namelist( wins_server_subnet
, fp
);