2 Unix SMB/Netbios implementation.
4 NBT netbios routines and daemon - version 2
5 Copyright (C) Andrew Tridgell 1994-1998
6 Copyright (C) Luke Kenneth Casson Leighton 1994-1998
7 Copyright (C) Jeremy Allison 1994-1998
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.
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.
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.
27 extern char **my_netbios_names
;
29 uint16 samba_nb_type
= 0; /* samba's NetBIOS name type */
32 /* ************************************************************************** **
33 * Set Samba's NetBIOS name type.
34 * ************************************************************************** **
36 void set_samba_nb_type(void)
38 if( lp_wins_support() || (*lp_wins_server()) )
39 samba_nb_type
= NB_MFLAG
; /* samba is a 'hybrid' node type. */
41 samba_nb_type
= NB_BFLAG
; /* samba is broadcast-only node type. */
42 } /* set_samba_nb_type */
44 /* ************************************************************************** **
45 * Convert a NetBIOS name to upper case.
46 * ************************************************************************** **
48 static void upcase_name( struct nmb_name
*target
, struct nmb_name
*source
)
53 (void)memcpy( target
, source
, sizeof( struct nmb_name
) );
55 strupper( target
->name
);
56 strupper( target
->scope
);
58 /* fudge... We're using a byte-by-byte compare, so we must be sure that
59 * unused space doesn't have garbage in it.
61 for( i
= strlen( target
->name
); i
< sizeof( target
->name
); i
++ )
62 target
->name
[i
] = '\0';
63 for( i
= strlen( target
->scope
); i
< sizeof( target
->scope
); i
++ )
64 target
->scope
[i
] = '\0';
67 /* ************************************************************************** **
68 * Add a new or overwrite an existing namelist entry.
69 * ************************************************************************** **
71 static void update_name_in_namelist( struct subnet_record
*subrec
,
72 struct name_record
*namerec
)
74 struct name_record
*oldrec
= NULL
;
76 (void)ubi_trInsert( subrec
->namelist
, namerec
, &(namerec
->name
), &oldrec
);
79 SAFE_FREE( oldrec
->data
.ip
);
82 } /* update_name_in_namelist */
84 /* ************************************************************************** **
85 * Remove a name from the namelist.
86 * ************************************************************************** **
88 void remove_name_from_namelist( struct subnet_record
*subrec
,
89 struct name_record
*namerec
)
91 (void)ubi_trRemove( subrec
->namelist
, namerec
);
93 SAFE_FREE(namerec
->data
.ip
);
95 ZERO_STRUCTP(namerec
);
98 subrec
->namelist_changed
= True
;
99 } /* remove_name_from_namelist */
101 /* ************************************************************************** **
102 * Find a name in a subnet.
103 * ************************************************************************** **
105 struct name_record
*find_name_on_subnet( struct subnet_record
*subrec
,
106 struct nmb_name
*nmbname
,
109 struct nmb_name uc_name
[1];
110 struct name_record
*name_ret
;
112 upcase_name( uc_name
, nmbname
);
113 name_ret
= (struct name_record
*)ubi_trFind( subrec
->namelist
, uc_name
);
116 /* Self names only - these include permanent names. */
118 && (name_ret
->data
.source
!= SELF_NAME
)
119 && (name_ret
->data
.source
!= PERMANENT_NAME
) )
122 ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n",
123 subrec
->subnet_name
, nmb_namestr(nmbname
) ) );
126 DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n",
127 subrec
->subnet_name
, nmb_namestr(nmbname
), name_ret
->data
.source
) );
131 ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n",
132 subrec
->subnet_name
, nmb_namestr(nmbname
) ) );
134 } /* find_name_on_subnet */
136 /* ************************************************************************** **
137 * Find a name over all known broadcast subnets.
138 * ************************************************************************** **
140 struct name_record
*find_name_for_remote_broadcast_subnet(
141 struct nmb_name
*nmbname
,
144 struct subnet_record
*subrec
;
145 struct name_record
*namerec
= NULL
;
147 for( subrec
= FIRST_SUBNET
;
149 subrec
= NEXT_SUBNET_EXCLUDING_UNICAST(subrec
) )
151 if( NULL
!= (namerec
= find_name_on_subnet(subrec
, nmbname
, self_only
)) )
156 } /* find_name_for_remote_broadcast_subnet */
158 /* ************************************************************************** **
159 * Update the ttl of an entry in a subnet name list.
160 * ************************************************************************** **
162 void update_name_ttl( struct name_record
*namerec
, int ttl
)
164 time_t time_now
= time(NULL
);
166 if( namerec
->data
.death_time
!= PERMANENT_TTL
)
167 namerec
->data
.death_time
= time_now
+ ttl
;
169 namerec
->data
.refresh_time
= time_now
+ MIN((ttl
/2), MAX_REFRESH_TIME
);
171 namerec
->subnet
->namelist_changed
= True
;
172 } /* update_name_ttl */
174 /* ************************************************************************** **
175 * Add an entry to a subnet name list.
176 * ************************************************************************** **
178 struct name_record
*add_name_to_subnet( struct subnet_record
*subrec
,
183 enum name_source source
,
185 struct in_addr
*iplist
)
187 struct name_record
*namerec
;
188 time_t time_now
= time(NULL
);
190 namerec
= (struct name_record
*)malloc( sizeof(*namerec
) );
191 if( NULL
== namerec
)
193 DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) );
197 memset( (char *)namerec
, '\0', sizeof(*namerec
) );
198 namerec
->data
.ip
= (struct in_addr
*)malloc( sizeof(struct in_addr
)
200 if( NULL
== namerec
->data
.ip
)
202 DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) );
204 ZERO_STRUCTP(namerec
);
205 SAFE_FREE( namerec
);
209 namerec
->subnet
= subrec
;
211 make_nmb_name(&namerec
->name
, name
, type
);
212 upcase_name(&namerec
->name
, NULL
);
214 /* Enter the name as active. */
215 namerec
->data
.nb_flags
= nb_flags
| NB_ACTIVE
;
217 /* If it's our primary name, flag it as so. */
218 if( strequal( my_netbios_names
[0], name
) )
219 namerec
->data
.nb_flags
|= NB_PERM
;
222 namerec
->data
.num_ips
= num_ips
;
223 memcpy( (namerec
->data
.ip
), iplist
, num_ips
* sizeof(struct in_addr
) );
226 namerec
->data
.source
= source
;
228 /* Setup the death_time and refresh_time. */
229 if( ttl
== PERMANENT_TTL
)
230 namerec
->data
.death_time
= PERMANENT_TTL
;
232 namerec
->data
.death_time
= time_now
+ ttl
;
234 namerec
->data
.refresh_time
= time_now
+ MIN((ttl
/2), MAX_REFRESH_TIME
);
236 /* Now add the record to the name list. */
237 update_name_in_namelist( subrec
, namerec
);
239 DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \
240 ttl=%d nb_flags=%2x to subnet %s\n",
241 nmb_namestr( &namerec
->name
),
242 inet_ntoa( *iplist
),
244 (unsigned int)nb_flags
,
245 subrec
->subnet_name
) );
247 subrec
->namelist_changed
= True
;
252 /*******************************************************************
253 Utility function automatically called when a name refresh or register
254 succeeds. By definition this is a SELF_NAME (or we wouldn't be registering
256 ******************************************************************/
258 void standard_success_register(struct subnet_record
*subrec
,
259 struct userdata_struct
*userdata
,
260 struct nmb_name
*nmbname
, uint16 nb_flags
, int ttl
,
261 struct in_addr registered_ip
)
263 struct name_record
*namerec
;
265 namerec
= find_name_on_subnet( subrec
, nmbname
, FIND_SELF_NAME
);
266 if( NULL
== namerec
)
267 (void)add_name_to_subnet( subrec
, nmbname
->name
, nmbname
->name_type
,
268 nb_flags
, ttl
, SELF_NAME
, 1, ®istered_ip
);
270 update_name_ttl( namerec
, ttl
);
273 /*******************************************************************
274 Utility function automatically called when a name refresh or register
275 fails. Note that this is only ever called on a broadcast subnet with
276 one IP address per name. This is why it can just delete the name
277 without enumerating the IP adresses. JRA.
278 ******************************************************************/
280 void standard_fail_register( struct subnet_record
*subrec
,
281 struct response_record
*rrec
,
282 struct nmb_name
*nmbname
)
284 struct name_record
*namerec
;
286 namerec
= find_name_on_subnet( subrec
, nmbname
, FIND_SELF_NAME
);
288 DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \
290 nmb_namestr(nmbname
), subrec
->subnet_name
) );
292 /* Remove the name from the subnet. */
294 remove_name_from_namelist(subrec
, namerec
);
297 /*******************************************************************
298 Utility function to remove an IP address from a name record.
299 ******************************************************************/
301 static void remove_nth_ip_in_record( struct name_record
*namerec
, int ind
)
303 if( ind
!= namerec
->data
.num_ips
)
304 memmove( (char *)(&namerec
->data
.ip
[ind
]),
305 (char *)(&namerec
->data
.ip
[ind
+1]),
306 ( namerec
->data
.num_ips
- ind
- 1) * sizeof(struct in_addr
) );
308 namerec
->data
.num_ips
--;
309 namerec
->subnet
->namelist_changed
= True
;
312 /*******************************************************************
313 Utility function to check if an IP address exists in a name record.
314 ******************************************************************/
316 BOOL
find_ip_in_name_record( struct name_record
*namerec
, struct in_addr ip
)
320 for(i
= 0; i
< namerec
->data
.num_ips
; i
++)
321 if(ip_equal( namerec
->data
.ip
[i
], ip
))
327 /*******************************************************************
328 Utility function to add an IP address to a name record.
329 ******************************************************************/
331 void add_ip_to_name_record( struct name_record
*namerec
, struct in_addr new_ip
)
333 struct in_addr
*new_list
;
335 /* Don't add one we already have. */
336 if( find_ip_in_name_record( namerec
, new_ip
) )
339 new_list
= (struct in_addr
*)malloc( (namerec
->data
.num_ips
+ 1)
340 * sizeof(struct in_addr
) );
341 if( NULL
== new_list
)
343 DEBUG(0,("add_ip_to_name_record: Malloc fail !\n"));
347 memcpy( (char *)new_list
,
348 (char *)namerec
->data
.ip
,
349 namerec
->data
.num_ips
* sizeof(struct in_addr
) );
350 new_list
[namerec
->data
.num_ips
] = new_ip
;
352 SAFE_FREE(namerec
->data
.ip
);
353 namerec
->data
.ip
= new_list
;
354 namerec
->data
.num_ips
+= 1;
356 namerec
->subnet
->namelist_changed
= True
;
359 /*******************************************************************
360 Utility function to remove an IP address from a name record.
361 ******************************************************************/
363 void remove_ip_from_name_record( struct name_record
*namerec
,
364 struct in_addr remove_ip
)
366 /* Try and find the requested ip address - remove it. */
368 int orig_num
= namerec
->data
.num_ips
;
370 for(i
= 0; i
< orig_num
; i
++)
371 if( ip_equal( remove_ip
, namerec
->data
.ip
[i
]) )
373 remove_nth_ip_in_record( namerec
, i
);
378 /*******************************************************************
379 Utility function that release_name callers can plug into as the
380 success function when a name release is successful. Used to save
381 duplication of success_function code.
382 ******************************************************************/
384 void standard_success_release( struct subnet_record
*subrec
,
385 struct userdata_struct
*userdata
,
386 struct nmb_name
*nmbname
,
387 struct in_addr released_ip
)
389 struct name_record
*namerec
;
391 namerec
= find_name_on_subnet( subrec
, nmbname
, FIND_ANY_NAME
);
393 if( namerec
== NULL
)
395 DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
396 on subnet %s. Name was not found on subnet.\n",
397 nmb_namestr(nmbname
),
398 inet_ntoa(released_ip
),
399 subrec
->subnet_name
) );
404 int orig_num
= namerec
->data
.num_ips
;
406 remove_ip_from_name_record( namerec
, released_ip
);
408 if( namerec
->data
.num_ips
== orig_num
)
409 DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
410 on subnet %s. This ip is not known for this name.\n",
411 nmb_namestr(nmbname
),
412 inet_ntoa(released_ip
),
413 subrec
->subnet_name
) );
416 if( namerec
->data
.num_ips
== 0 )
417 remove_name_from_namelist( subrec
, namerec
);
420 /*******************************************************************
421 Expires old names in a subnet namelist.
422 ******************************************************************/
424 void expire_names_on_subnet(struct subnet_record
*subrec
, time_t t
)
426 struct name_record
*namerec
;
427 struct name_record
*next_namerec
;
429 for( namerec
= (struct name_record
*)ubi_trFirst( subrec
->namelist
);
431 namerec
= next_namerec
)
433 next_namerec
= (struct name_record
*)ubi_trNext( namerec
);
434 if( (namerec
->data
.death_time
!= PERMANENT_TTL
)
435 && (namerec
->data
.death_time
< t
) )
437 if( namerec
->data
.source
== SELF_NAME
)
439 DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \
441 subrec
->subnet_name
, nmb_namestr(&namerec
->name
) ) );
442 namerec
->data
.death_time
+= 300;
443 namerec
->subnet
->namelist_changed
= True
;
446 DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n",
447 subrec
->subnet_name
, nmb_namestr(&namerec
->name
)));
449 remove_name_from_namelist( subrec
, namerec
);
454 /*******************************************************************
455 Expires old names in all subnet namelists.
456 ******************************************************************/
458 void expire_names(time_t t
)
460 struct subnet_record
*subrec
;
462 for( subrec
= FIRST_SUBNET
;
464 subrec
= NEXT_SUBNET_INCLUDING_UNICAST(subrec
) )
466 expire_names_on_subnet( subrec
, t
);
470 /****************************************************************************
471 Add the magic samba names, useful for finding samba servers.
472 These go directly into the name list for a particular subnet,
473 without going through the normal registration process.
474 When adding them to the unicast subnet, add them as a list of
475 all broadcast subnet IP addresses.
476 **************************************************************************/
478 void add_samba_names_to_subnet( struct subnet_record
*subrec
)
480 struct in_addr
*iplist
= &subrec
->myip
;
483 /* These names are added permanently (ttl of zero) and will NOT be
486 if( (subrec
== unicast_subnet
)
487 || (subrec
== wins_server_subnet
)
488 || (subrec
== remote_broadcast_subnet
) )
490 struct subnet_record
*bcast_subrecs
;
492 /* Create an IP list containing all our known subnets. */
494 num_ips
= iface_count();
495 iplist
= (struct in_addr
*)malloc( num_ips
* sizeof(struct in_addr
) );
498 DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n"));
502 for( bcast_subrecs
= FIRST_SUBNET
, i
= 0;
504 bcast_subrecs
= NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs
), i
++ )
505 iplist
[i
] = bcast_subrecs
->myip
;
509 (void)add_name_to_subnet(subrec
,"*",0x0,samba_nb_type
, PERMANENT_TTL
,
510 PERMANENT_NAME
, num_ips
, iplist
);
511 (void)add_name_to_subnet(subrec
,"*",0x20,samba_nb_type
,PERMANENT_TTL
,
512 PERMANENT_NAME
, num_ips
, iplist
);
513 (void)add_name_to_subnet(subrec
,"__SAMBA__",0x20,samba_nb_type
,PERMANENT_TTL
,
514 PERMANENT_NAME
, num_ips
, iplist
);
515 (void)add_name_to_subnet(subrec
,"__SAMBA__",0x00,samba_nb_type
,PERMANENT_TTL
,
516 PERMANENT_NAME
, num_ips
, iplist
);
518 if(iplist
!= &subrec
->myip
)
522 /****************************************************************************
523 Dump the contents of the namelists on all the subnets (including unicast)
524 into a file. Initiated by SIGHUP - used to debug the state of the namelists.
525 **************************************************************************/
527 static void dump_subnet_namelist( struct subnet_record
*subrec
, FILE *fp
)
529 struct name_record
*namerec
;
534 fprintf(fp
, "Subnet %s\n----------------------\n", subrec
->subnet_name
);
535 for( namerec
= (struct name_record
*)ubi_trFirst( subrec
->namelist
);
537 namerec
= (struct name_record
*)ubi_trNext( namerec
) )
539 fprintf(fp
,"\tName = %s\t", nmb_namestr(&namerec
->name
));
540 switch(namerec
->data
.source
)
543 src_type
= "LMHOSTS_NAME";
545 case WINS_PROXY_NAME
:
546 src_type
= "WINS_PROXY_NAME";
549 src_type
= "REGISTER_NAME";
552 src_type
= "SELF_NAME";
555 src_type
= "DNS_NAME";
558 src_type
= "DNSFAIL_NAME";
561 src_type
= "PERMANENT_NAME";
564 src_type
= "unknown!";
567 fprintf(fp
,"Source = %s\nb_flags = %x\t", src_type
, namerec
->data
.nb_flags
);
569 if(namerec
->data
.death_time
!= PERMANENT_TTL
)
571 tm
= LocalTime(&namerec
->data
.death_time
);
572 fprintf(fp
, "death_time = %s\t", asctime(tm
));
575 fprintf(fp
, "death_time = PERMANENT\t");
577 if(namerec
->data
.refresh_time
!= PERMANENT_TTL
)
579 tm
= LocalTime(&namerec
->data
.refresh_time
);
580 fprintf(fp
, "refresh_time = %s\n", asctime(tm
));
583 fprintf(fp
, "refresh_time = PERMANENT\n");
585 fprintf(fp
, "\t\tnumber of IPS = %d", namerec
->data
.num_ips
);
586 for(i
= 0; i
< namerec
->data
.num_ips
; i
++)
587 fprintf(fp
, "\t%s", inet_ntoa(namerec
->data
.ip
[i
]));
593 /****************************************************************************
594 Dump the contents of the namelists on all the subnets (including unicast)
595 into a file. Initiated by SIGHUP - used to debug the state of the namelists.
596 **************************************************************************/
598 void dump_all_namelists(void)
601 struct subnet_record
*subrec
;
603 fp
= sys_fopen(lock_path("namelist.debug"),"w");
607 DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n",
608 "namelist.debug",strerror(errno
)));
612 for( subrec
= FIRST_SUBNET
;
614 subrec
= NEXT_SUBNET_INCLUDING_UNICAST(subrec
) )
615 dump_subnet_namelist( subrec
, fp
);
617 if( !we_are_a_wins_client() )
618 dump_subnet_namelist( unicast_subnet
, fp
);
620 if( remote_broadcast_subnet
->namelist
!= NULL
)
621 dump_subnet_namelist( remote_broadcast_subnet
, fp
);
623 if( wins_server_subnet
!= NULL
)
624 dump_subnet_namelist( wins_server_subnet
, fp
);