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-2003
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 3 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, see <http://www.gnu.org/licenses/>.
24 #include "system/filesys.h"
25 #include "nmbd/nmbd.h"
27 uint16 samba_nb_type
= 0; /* samba's NetBIOS name type */
30 /**************************************************************************
31 Set Samba's NetBIOS name type.
32 ***************************************************************************/
34 void set_samba_nb_type(void)
36 if( lp_we_are_a_wins_server() || wins_srv_count() ) {
37 samba_nb_type
= NB_HFLAG
; /* samba is a 'hybrid' node type. */
39 samba_nb_type
= NB_BFLAG
; /* samba is broadcast-only node type. */
43 /***************************************************************************
44 Convert a NetBIOS name to upper case.
45 ***************************************************************************/
47 static bool upcase_name( struct nmb_name
*target
, const struct nmb_name
*source
)
53 if( NULL
!= source
) {
54 memcpy( target
, source
, sizeof( struct nmb_name
) );
57 pull_ascii_nstring(targ
, sizeof(targ
), target
->name
);
58 if (!strupper_m( targ
)) {
61 push_ascii_nstring( target
->name
, targ
);
63 pull_ascii(scope
, target
->scope
, 64, -1, STR_TERMINATE
);
64 if (!strupper_m( scope
)) {
67 push_ascii(target
->scope
, scope
, 64, STR_TERMINATE
);
69 /* fudge... We're using a byte-by-byte compare, so we must be sure that
70 * unused space doesn't have garbage in it.
73 for( i
= strlen( target
->name
); i
< sizeof( target
->name
); i
++ ) {
74 target
->name
[i
] = '\0';
76 for( i
= strlen( target
->scope
); i
< sizeof( target
->scope
); i
++ ) {
77 target
->scope
[i
] = '\0';
82 /**************************************************************************
83 Remove a name from the namelist.
84 ***************************************************************************/
86 void remove_name_from_namelist(struct subnet_record
*subrec
,
87 struct name_record
*namerec
)
89 if (subrec
== wins_server_subnet
)
90 remove_name_from_wins_namelist(namerec
);
92 subrec
->namelist_changed
= True
;
93 DLIST_REMOVE(subrec
->namelist
, namerec
);
96 SAFE_FREE(namerec
->data
.ip
);
97 ZERO_STRUCTP(namerec
);
101 /**************************************************************************
102 Find a name in a subnet.
103 **************************************************************************/
105 struct name_record
*find_name_on_subnet(struct subnet_record
*subrec
,
106 const struct nmb_name
*nmbname
,
109 struct nmb_name uc_name
;
110 struct name_record
*name_ret
;
112 if (!upcase_name( &uc_name
, nmbname
)) {
116 if (subrec
== wins_server_subnet
) {
117 return find_name_on_wins_subnet(&uc_name
, self_only
);
120 for( name_ret
= subrec
->namelist
; name_ret
; name_ret
= name_ret
->next
) {
121 if (memcmp(&uc_name
, &name_ret
->name
, sizeof(struct nmb_name
)) == 0) {
127 /* Self names only - these include permanent names. */
128 if( self_only
&& (name_ret
->data
.source
!= SELF_NAME
) && (name_ret
->data
.source
!= PERMANENT_NAME
) ) {
129 DEBUG( 9, ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n",
130 subrec
->subnet_name
, nmb_namestr(nmbname
) ) );
134 DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n",
135 subrec
->subnet_name
, nmb_namestr(nmbname
), name_ret
->data
.source
) );
140 DEBUG( 9, ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n",
141 subrec
->subnet_name
, nmb_namestr(nmbname
) ) );
146 /**************************************************************************
147 Find a name over all known broadcast subnets.
148 ************************************************************************/
150 struct name_record
*find_name_for_remote_broadcast_subnet(struct nmb_name
*nmbname
,
153 struct subnet_record
*subrec
;
154 struct name_record
*namerec
;
156 for( subrec
= FIRST_SUBNET
; subrec
; subrec
= NEXT_SUBNET_EXCLUDING_UNICAST(subrec
) ) {
157 namerec
= find_name_on_subnet(subrec
, nmbname
, self_only
);
166 /**************************************************************************
167 Update the ttl of an entry in a subnet name list.
168 ***************************************************************************/
170 void update_name_ttl( struct name_record
*namerec
, int ttl
)
172 time_t time_now
= time(NULL
);
174 if( namerec
->data
.death_time
!= PERMANENT_TTL
) {
175 namerec
->data
.death_time
= time_now
+ ttl
;
178 namerec
->data
.refresh_time
= time_now
+ MIN((ttl
/2), MAX_REFRESH_TIME
);
180 if (namerec
->subnet
== wins_server_subnet
) {
181 wins_store_changed_namerec(namerec
);
183 namerec
->subnet
->namelist_changed
= True
;
187 /**************************************************************************
188 Add an entry to a subnet name list.
189 ***********************************************************************/
191 bool add_name_to_subnet( struct subnet_record
*subrec
,
196 enum name_source source
,
198 struct in_addr
*iplist
)
201 struct name_record
*namerec
;
202 time_t time_now
= time(NULL
);
208 namerec
= SMB_MALLOC_P(struct name_record
);
209 if( NULL
== namerec
) {
210 DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) );
214 memset( (char *)namerec
, '\0', sizeof(*namerec
) );
215 namerec
->data
.ip
= SMB_MALLOC_ARRAY( struct in_addr
, num_ips
);
216 if( NULL
== namerec
->data
.ip
) {
217 DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) );
218 ZERO_STRUCTP(namerec
);
223 namerec
->subnet
= subrec
;
225 make_nmb_name(&namerec
->name
, name
, type
);
226 if (!upcase_name(&namerec
->name
, NULL
)) {
227 SAFE_FREE(namerec
->data
.ip
);
232 /* Enter the name as active. */
233 namerec
->data
.nb_flags
= nb_flags
| NB_ACTIVE
;
234 namerec
->data
.wins_flags
= WINS_ACTIVE
;
236 /* If it's our primary name, flag it as so. */
237 if (strequal( my_netbios_names(0), name
)) {
238 namerec
->data
.nb_flags
|= NB_PERM
;
242 namerec
->data
.num_ips
= num_ips
;
243 memcpy( (namerec
->data
.ip
), iplist
, num_ips
* sizeof(struct in_addr
) );
246 namerec
->data
.source
= source
;
248 /* Setup the death_time and refresh_time. */
249 if (ttl
== PERMANENT_TTL
) {
250 namerec
->data
.death_time
= PERMANENT_TTL
;
252 namerec
->data
.death_time
= time_now
+ ttl
;
255 namerec
->data
.refresh_time
= time_now
+ MIN((ttl
/2), MAX_REFRESH_TIME
);
257 DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \
258 ttl=%d nb_flags=%2x to subnet %s\n",
259 nmb_namestr( &namerec
->name
),
260 inet_ntoa( *iplist
),
262 (unsigned int)nb_flags
,
263 subrec
->subnet_name
) );
265 /* Now add the record to the name list. */
267 if (subrec
== wins_server_subnet
) {
268 ret
= add_name_to_wins_subnet(namerec
);
269 /* Free namerec - it's stored in the tdb. */
270 SAFE_FREE(namerec
->data
.ip
);
273 DLIST_ADD(subrec
->namelist
, namerec
);
274 subrec
->namelist_changed
= True
;
281 /*******************************************************************
282 Utility function automatically called when a name refresh or register
283 succeeds. By definition this is a SELF_NAME (or we wouldn't be registering
285 ******************************************************************/
287 void standard_success_register(struct subnet_record
*subrec
,
288 struct userdata_struct
*userdata
,
289 struct nmb_name
*nmbname
, uint16 nb_flags
, int ttl
,
290 struct in_addr registered_ip
)
292 struct name_record
*namerec
;
294 namerec
= find_name_on_subnet( subrec
, nmbname
, FIND_SELF_NAME
);
295 if (namerec
== NULL
) {
297 pull_ascii_nstring(name
, sizeof(name
), nmbname
->name
);
298 add_name_to_subnet( subrec
, name
, nmbname
->name_type
,
299 nb_flags
, ttl
, SELF_NAME
, 1, ®istered_ip
);
301 update_name_ttl( namerec
, ttl
);
305 /*******************************************************************
306 Utility function automatically called when a name refresh or register
307 fails. Note that this is only ever called on a broadcast subnet with
308 one IP address per name. This is why it can just delete the name
309 without enumerating the IP adresses. JRA.
310 ******************************************************************/
312 void standard_fail_register( struct subnet_record
*subrec
,
313 struct nmb_name
*nmbname
)
315 struct name_record
*namerec
;
317 namerec
= find_name_on_subnet( subrec
, nmbname
, FIND_SELF_NAME
);
319 DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \
320 on subnet %s\n", nmb_namestr(nmbname
), subrec
->subnet_name
) );
322 /* Remove the name from the subnet. */
324 remove_name_from_namelist(subrec
, namerec
);
328 /*******************************************************************
329 Utility function to remove an IP address from a name record.
330 ******************************************************************/
332 static void remove_nth_ip_in_record( struct name_record
*namerec
, int ind
)
334 if( ind
!= namerec
->data
.num_ips
) {
335 memmove( (char *)(&namerec
->data
.ip
[ind
]),
336 (char *)(&namerec
->data
.ip
[ind
+1]),
337 ( namerec
->data
.num_ips
- ind
- 1) * sizeof(struct in_addr
) );
340 namerec
->data
.num_ips
--;
341 if (namerec
->subnet
== wins_server_subnet
) {
342 wins_store_changed_namerec(namerec
);
344 namerec
->subnet
->namelist_changed
= True
;
348 /*******************************************************************
349 Utility function to check if an IP address exists in a name record.
350 ******************************************************************/
352 bool find_ip_in_name_record( struct name_record
*namerec
, struct in_addr ip
)
356 for(i
= 0; i
< namerec
->data
.num_ips
; i
++) {
357 if(ip_equal_v4( namerec
->data
.ip
[i
], ip
)) {
365 /*******************************************************************
366 Utility function to add an IP address to a name record.
367 ******************************************************************/
369 void add_ip_to_name_record( struct name_record
*namerec
, struct in_addr new_ip
)
371 struct in_addr
*new_list
;
373 /* Don't add one we already have. */
374 if( find_ip_in_name_record( namerec
, new_ip
)) {
378 new_list
= SMB_MALLOC_ARRAY( struct in_addr
, namerec
->data
.num_ips
+ 1);
379 if( NULL
== new_list
) {
380 DEBUG(0,("add_ip_to_name_record: Malloc fail !\n"));
384 memcpy( (char *)new_list
, (char *)namerec
->data
.ip
, namerec
->data
.num_ips
* sizeof(struct in_addr
) );
385 new_list
[namerec
->data
.num_ips
] = new_ip
;
387 SAFE_FREE(namerec
->data
.ip
);
388 namerec
->data
.ip
= new_list
;
389 namerec
->data
.num_ips
+= 1;
391 if (namerec
->subnet
== wins_server_subnet
) {
392 wins_store_changed_namerec(namerec
);
394 namerec
->subnet
->namelist_changed
= True
;
398 /*******************************************************************
399 Utility function to remove an IP address from a name record.
400 ******************************************************************/
402 void remove_ip_from_name_record( struct name_record
*namerec
,
403 struct in_addr remove_ip
)
405 /* Try and find the requested ip address - remove it. */
407 int orig_num
= namerec
->data
.num_ips
;
409 for(i
= 0; i
< orig_num
; i
++) {
410 if( ip_equal_v4( remove_ip
, namerec
->data
.ip
[i
]) ) {
411 remove_nth_ip_in_record( namerec
, i
);
417 /*******************************************************************
418 Utility function that release_name callers can plug into as the
419 success function when a name release is successful. Used to save
420 duplication of success_function code.
421 ******************************************************************/
423 void standard_success_release( struct subnet_record
*subrec
,
424 struct userdata_struct
*userdata
,
425 struct nmb_name
*nmbname
,
426 struct in_addr released_ip
)
428 struct name_record
*namerec
;
430 namerec
= find_name_on_subnet( subrec
, nmbname
, FIND_ANY_NAME
);
431 if( namerec
== NULL
) {
432 DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
433 on subnet %s. Name was not found on subnet.\n", nmb_namestr(nmbname
), inet_ntoa(released_ip
),
434 subrec
->subnet_name
) );
437 int orig_num
= namerec
->data
.num_ips
;
439 remove_ip_from_name_record( namerec
, released_ip
);
441 if( namerec
->data
.num_ips
== orig_num
) {
442 DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
443 on subnet %s. This ip is not known for this name.\n", nmb_namestr(nmbname
), inet_ntoa(released_ip
), subrec
->subnet_name
) );
447 if( namerec
->data
.num_ips
== 0 ) {
448 remove_name_from_namelist( subrec
, namerec
);
452 /*******************************************************************
453 Expires old names in a subnet namelist.
454 NB. Does not touch the wins_subnet - no wins specific processing here.
455 ******************************************************************/
457 static void expire_names_on_subnet(struct subnet_record
*subrec
, time_t t
)
459 struct name_record
*namerec
;
460 struct name_record
*next_namerec
;
462 for( namerec
= subrec
->namelist
; namerec
; namerec
= next_namerec
) {
463 next_namerec
= namerec
->next
;
464 if( (namerec
->data
.death_time
!= PERMANENT_TTL
) && (namerec
->data
.death_time
< t
) ) {
465 if( namerec
->data
.source
== SELF_NAME
) {
466 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \
467 name %s\n", subrec
->subnet_name
, nmb_namestr(&namerec
->name
) ) );
468 namerec
->data
.death_time
+= 300;
469 namerec
->subnet
->namelist_changed
= True
;
473 DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n",
474 subrec
->subnet_name
, nmb_namestr(&namerec
->name
)));
476 remove_name_from_namelist(subrec
, namerec
);
481 /*******************************************************************
482 Expires old names in all subnet namelists.
483 NB. Does not touch the wins_subnet.
484 ******************************************************************/
486 void expire_names(time_t t
)
488 struct subnet_record
*subrec
;
490 for( subrec
= FIRST_SUBNET
; subrec
; subrec
= NEXT_SUBNET_INCLUDING_UNICAST(subrec
) ) {
491 expire_names_on_subnet( subrec
, t
);
495 /****************************************************************************
496 Add the magic samba names, useful for finding samba servers.
497 These go directly into the name list for a particular subnet,
498 without going through the normal registration process.
499 When adding them to the unicast subnet, add them as a list of
500 all broadcast subnet IP addresses.
501 **************************************************************************/
503 void add_samba_names_to_subnet( struct subnet_record
*subrec
)
505 struct in_addr
*iplist
= &subrec
->myip
;
508 /* These names are added permanently (ttl of zero) and will NOT be refreshed. */
510 if( (subrec
== unicast_subnet
) || (subrec
== wins_server_subnet
) || (subrec
== remote_broadcast_subnet
) ) {
511 struct subnet_record
*bcast_subrecs
;
514 /* Create an IP list containing all our known subnets. */
516 num_ips
= iface_count();
517 iplist
= SMB_MALLOC_ARRAY( struct in_addr
, num_ips
);
518 if( NULL
== iplist
) {
519 DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n"));
523 for( bcast_subrecs
= FIRST_SUBNET
, i
= 0; bcast_subrecs
&&
525 bcast_subrecs
= NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs
), i
++ ) {
526 iplist
[i
] = bcast_subrecs
->myip
;
531 add_name_to_subnet(subrec
,"*",0x0,samba_nb_type
, PERMANENT_TTL
,
532 PERMANENT_NAME
, num_ips
, iplist
);
533 add_name_to_subnet(subrec
,"*",0x20,samba_nb_type
,PERMANENT_TTL
,
534 PERMANENT_NAME
, num_ips
, iplist
);
535 add_name_to_subnet(subrec
,"__SAMBA__",0x20,samba_nb_type
,PERMANENT_TTL
,
536 PERMANENT_NAME
, num_ips
, iplist
);
537 add_name_to_subnet(subrec
,"__SAMBA__",0x00,samba_nb_type
,PERMANENT_TTL
,
538 PERMANENT_NAME
, num_ips
, iplist
);
540 if(iplist
!= &subrec
->myip
) {
545 /****************************************************************************
546 Dump a name_record struct.
547 **************************************************************************/
549 void dump_name_record( struct name_record
*namerec
, XFILE
*fp
)
551 const char *src_type
;
555 x_fprintf(fp
,"\tName = %s\t", nmb_namestr(&namerec
->name
));
556 switch(namerec
->data
.source
) {
558 src_type
= "LMHOSTS_NAME";
560 case WINS_PROXY_NAME
:
561 src_type
= "WINS_PROXY_NAME";
564 src_type
= "REGISTER_NAME";
567 src_type
= "SELF_NAME";
570 src_type
= "DNS_NAME";
573 src_type
= "DNSFAIL_NAME";
576 src_type
= "PERMANENT_NAME";
579 src_type
= "unknown!";
583 x_fprintf(fp
,"Source = %s\nb_flags = %x\t", src_type
, namerec
->data
.nb_flags
);
585 if(namerec
->data
.death_time
!= PERMANENT_TTL
) {
587 tm
= localtime(&namerec
->data
.death_time
);
595 x_fprintf(fp
, "death_time = %s\t", asct
);
597 x_fprintf(fp
, "death_time = PERMANENT\t");
600 if(namerec
->data
.refresh_time
!= PERMANENT_TTL
) {
602 tm
= localtime(&namerec
->data
.refresh_time
);
610 x_fprintf(fp
, "refresh_time = %s\n", asct
);
612 x_fprintf(fp
, "refresh_time = PERMANENT\n");
615 x_fprintf(fp
, "\t\tnumber of IPS = %d", namerec
->data
.num_ips
);
616 for(i
= 0; i
< namerec
->data
.num_ips
; i
++) {
617 x_fprintf(fp
, "\t%s", inet_ntoa(namerec
->data
.ip
[i
]));
620 x_fprintf(fp
, "\n\n");
624 /****************************************************************************
625 Dump the contents of the namelists on all the subnets (including unicast)
626 into a file. Initiated by SIGHUP - used to debug the state of the namelists.
627 **************************************************************************/
629 static void dump_subnet_namelist( struct subnet_record
*subrec
, XFILE
*fp
)
631 struct name_record
*namerec
;
632 x_fprintf(fp
, "Subnet %s\n----------------------\n", subrec
->subnet_name
);
633 for( namerec
= subrec
->namelist
; namerec
; namerec
= namerec
->next
) {
634 dump_name_record(namerec
, fp
);
638 /****************************************************************************
639 Dump the contents of the namelists on all the subnets (including unicast)
640 into a file. Initiated by SIGHUP - used to debug the state of the namelists.
641 **************************************************************************/
643 void dump_all_namelists(void)
646 struct subnet_record
*subrec
;
648 fp
= x_fopen(lock_path("namelist.debug"),O_WRONLY
|O_CREAT
|O_TRUNC
, 0644);
651 DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n",
652 "namelist.debug",strerror(errno
)));
656 for (subrec
= FIRST_SUBNET
; subrec
; subrec
= NEXT_SUBNET_INCLUDING_UNICAST(subrec
)) {
657 dump_subnet_namelist( subrec
, fp
);
660 if (!we_are_a_wins_client()) {
661 dump_subnet_namelist( unicast_subnet
, fp
);
664 if (remote_broadcast_subnet
->namelist
!= NULL
) {
665 dump_subnet_namelist( remote_broadcast_subnet
, fp
);
668 if (wins_server_subnet
!= NULL
) {
669 dump_wins_subnet_namelist(fp
);