2 Unix SMB/Netbios implementation.
4 NBT netbios routines and daemon - version 2
5 Copyright (C) Andrew Tridgell 1994-1997
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.
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.
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.
21 Module name: nameserv.c
25 14 jan 96: lkcl@pires.co.uk
26 added multiple workgroup domain master support
28 04 jul 96: lkcl@pires.co.uk
29 module nameserv contains name server management functions
36 extern int DEBUGLEVEL
;
39 extern pstring myname
;
40 extern fstring myworkgroup
;
41 extern char **my_netbios_names
;
42 extern struct in_addr ipzero
;
43 extern struct in_addr wins_ip
;
45 extern struct subnet_record
*subnetlist
;
47 extern uint16 nb_type
; /* samba's NetBIOS type */
49 /****************************************************************************
50 remove an entry from the name list
52 note: the name will _always_ be removed
53 XXXX at present, the name is removed _even_ if a WINS server says keep it.
55 ****************************************************************************/
56 void remove_name_entry(struct subnet_record
*d
, char *name
,int type
)
58 /* XXXX BUG: if samba is offering WINS support, it should still broadcast
59 a de-registration packet to the local subnet before removing the
60 name from its local-subnet name database. */
62 int search
= FIND_SELF
;
64 struct name_record
*n2
=NULL
;
66 make_nmb_name(&n
.name
,name
,type
,scope
);
73 if ((n2
= find_name_search(&d
, &n
.name
, search
, ipzero
)))
75 /* check name isn't already being de-registered */
76 if (NAME_DEREG(n2
->ip_flgs
[0].nb_flags
))
79 /* mark the name as in the process of deletion. */
80 n2
->ip_flgs
[0].nb_flags
&= NB_DEREG
;
85 /* Only remove names with non-zero death times. */
86 if(n2
->death_time
== 0)
88 DEBUG(5,("remove_name_entry: Name %s(%d) has zero ttl - not removing.\n",
93 /* remove the name immediately. even if the spec says we should
94 first try to release them, this is too dangerous with our current
95 name structures as otherwise we will end up replying to names we
97 remove_netbios_name(d
,name
,type
,SELF
,n2
->ip_flgs
[0].ip
);
99 if (ip_equal(d
->bcast_ip
, wins_ip
))
101 if (!lp_wins_support())
103 /* not a WINS server: we have to release them on the network */
104 queue_netbios_pkt_wins(ClientNMB
,NMB_REL
,NAME_RELEASE
,
105 name
, type
, 0, 0,0,NULL
,NULL
,
106 False
, True
, ipzero
, ipzero
);
111 /* local interface: release them on the network */
112 queue_netbios_packet(d
,ClientNMB
,NMB_REL
,NAME_RELEASE
,
113 name
, type
, 0, 0,0,NULL
,NULL
,
114 True
, False
, d
->bcast_ip
, d
->bcast_ip
);
119 /****************************************************************************
120 add an entry to the name list
122 big note: our name will _always_ be added (if there are no objections).
123 it's just a matter of when this will be done (e.g after a time-out).
125 ****************************************************************************/
126 void add_my_name_entry(struct subnet_record
*d
,char *name
,int type
,int nb_flags
)
133 /* not that it particularly matters, but if the SELF name already exists,
134 it must be re-registered, rather than just registered */
136 make_nmb_name(&n
, name
, type
, scope
);
137 if (find_name(d
->namelist
, &n
, SELF
))
140 /* XXXX BUG: if samba is offering WINS support, it should still add the
141 name entry to a local-subnet name database. see rfc1001.txt 15.1.1 p28
142 regarding the point about M-nodes. */
144 if (ip_equal(d
->bcast_ip
, wins_ip
))
146 if (lp_wins_support())
148 /* we are a WINS server. */
149 if(lp_wins_support())
151 DEBUG(4,("add_my_name_entry: samba as WINS server adding: "));
154 /* this will call add_netbios_entry() */
155 name_register_work(d
, name
, type
, nb_flags
,0, ipzero
, False
);
159 DEBUG(4,("add_my_name_entry registering name %s with WINS server.\n",
162 /* a time-to-live allows us to refresh this name with the WINS server. */
163 queue_netbios_pkt_wins(ClientNMB
,
164 re_reg
? NMB_REG_REFRESH
: NMB_REG
, NAME_REGISTER
,
165 name
, type
, nb_flags
, GET_TTL(0),0,NULL
,NULL
,
166 False
, True
, ipzero
, ipzero
);
171 /* broadcast the packet, but it comes from ipzero */
172 queue_netbios_packet(d
,ClientNMB
,
173 re_reg
? NMB_REG_REFRESH
: NMB_REG
, NAME_REGISTER
,
174 name
, type
, nb_flags
, GET_TTL(0),0,NULL
,NULL
,
175 True
, False
, d
->bcast_ip
, ipzero
);
180 /****************************************************************************
181 add the internet group <1c> domain logon names by wins unicast and broadcast.
182 ****************************************************************************/
183 void add_domain_logon_names(void)
185 struct subnet_record
*d
;
187 if (!lp_domain_logons()) return;
189 for (d
= FIRST_SUBNET
; d
; d
= NEXT_SUBNET_INCLUDING_WINS(d
))
191 struct work_record
*work
= find_workgroupstruct(d
, myworkgroup
, True
);
193 if (work
&& work
->log_state
== LOGON_NONE
)
196 make_nmb_name(&n
,myworkgroup
,0x1c,scope
);
198 if (!find_name(d
->namelist
, &n
, FIND_SELF
))
200 /* logon servers are group names. don't expect failure */
202 DEBUG(0,("%s attempting to become logon server for %s %s\n",
203 timestring(), myworkgroup
, inet_ntoa(d
->bcast_ip
)));
205 become_logon_server(d
, work
);
212 /****************************************************************************
213 add the <1b> domain master names by broadcast.
214 ****************************************************************************/
215 void add_domain_master_bcast(void)
217 struct subnet_record
*d
;
219 if (!lp_domain_master()) return;
221 for (d
= FIRST_SUBNET
; d
; d
= NEXT_SUBNET_EXCLUDING_WINS(d
))
223 struct work_record
*work
= find_workgroupstruct(d
, myworkgroup
, True
);
225 if (work
&& work
->dom_state
== DOMAIN_NONE
)
228 make_nmb_name(&n
,myworkgroup
,0x1b,scope
);
230 if (!find_name(d
->namelist
, &n
, FIND_SELF
))
232 DEBUG(0,("%s add_domain_names: attempting to become domain \
233 master browser on workgroup %s %s\n",
234 timestring(), myworkgroup
, inet_ntoa(d
->bcast_ip
)));
236 /* send out a query to establish whether there's a
237 domain controller on the local subnet. if not,
238 we can become a domain controller. it's only
239 polite that we check, before claiming the
243 DEBUG(0,("add_domain_names:querying subnet %s \
244 for domain master on workgroup %s\n",
245 inet_ntoa(d
->bcast_ip
), myworkgroup
));
247 queue_netbios_packet(d
,ClientNMB
,NMB_QUERY
,
252 d
->bcast_ip
, d
->bcast_ip
);
259 /****************************************************************************
260 add the <1b> domain master name by wins unicast.
261 ****************************************************************************/
262 void add_domain_master_wins(void)
264 struct work_record
*work
;
266 if (!lp_domain_master() || wins_subnet
== NULL
) return;
268 work
= find_workgroupstruct(wins_subnet
, myworkgroup
, True
);
270 if (work
&& work
->dom_state
== DOMAIN_NONE
)
273 make_nmb_name(&n
,myworkgroup
,0x1b,scope
);
275 if (!find_name(wins_subnet
->namelist
, &n
, FIND_SELF
))
277 DEBUG(0,("%s add_domain_names: attempting to become domain \
278 master browser on workgroup %s %s\n",
279 timestring(), myworkgroup
, inet_ntoa(wins_subnet
->bcast_ip
)));
281 if (lp_wins_support())
283 /* use the wins server's capabilities (indirectly). if
284 someone has already registered the domain<1b>
285 name with the WINS server, then the WINS
286 server's job is to _check_ that the owner still
287 wants it, before giving it away.
290 DEBUG(1,("%s initiate become domain master for %s\n",
291 timestring(), myworkgroup
));
293 become_domain_master(wins_subnet
, work
);
297 /* send out a query to establish whether there's a
298 domain controller on the WINS subnet. if not,
299 we can become a domain controller. it's only
300 polite that we check, before claiming the
304 DEBUG(0,("add_domain_names:querying WINS \
305 for domain master on workgroup %s\n", myworkgroup
));
307 queue_netbios_pkt_wins(ClientNMB
,NMB_QUERY
,
311 False
, True
, ipzero
, ipzero
);
318 /****************************************************************************
319 add the domain logon server and domain master browser names
321 this code was written so that several samba servers can co-operate in
322 sharing the task of (one server) being a domain master, and of being
323 domain logon servers.
325 **************************************************************************/
326 void add_domain_names(time_t t
)
328 static time_t lastrun
= 0;
330 if (lastrun
!= 0 && t
< lastrun
+ CHECK_TIME_ADD_DOM_NAMES
* 60) return;
333 /* do the "internet group" - <1c> names */
334 add_domain_logon_names();
336 /* do the domain master names */
337 if (wins_subnet
!= NULL
)
339 /* if the registration of the <1b> name is successful, then
340 add_domain_master_bcast() will be called. this will
341 result in domain logon services being gracefully provided,
342 as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
344 which, due to a bug in namelogon.c from 1.9.16p2 to 1.9.16p11
345 cannot _provide_ domain master / domain logon services!!!
348 add_domain_master_wins();
352 add_domain_master_bcast();
356 /****************************************************************************
357 add the magic samba names, useful for finding samba servers
358 **************************************************************************/
359 void add_my_names(void)
361 struct subnet_record
*d
;
362 /* each subnet entry, including WINS pseudo-subnet, has SELF names */
364 /* XXXX if there was a transport layer added to samba (ipx/spx etc) then
365 there would be yet _another_ for-loop, this time on the transport type
368 for (d
= FIRST_SUBNET
; d
; d
= NEXT_SUBNET_INCLUDING_WINS(d
))
371 BOOL wins
= (lp_wins_support() && (d
== wins_subnet
));
373 /* Add all our names including aliases. */
374 for (n
=0; my_netbios_names
[n
]; n
++)
376 add_my_name_entry(d
, my_netbios_names
[n
],0x20,nb_type
|NB_ACTIVE
);
377 add_my_name_entry(d
, my_netbios_names
[n
],0x03,nb_type
|NB_ACTIVE
);
378 add_my_name_entry(d
, my_netbios_names
[n
],0x00,nb_type
|NB_ACTIVE
);
381 /* these names are added permanently (ttl of zero) and will NOT be
382 refreshed with the WINS server */
383 add_netbios_entry(d
,"*",0x0,nb_type
|NB_ACTIVE
,0,SELF
,d
->myip
,False
,wins
);
384 add_netbios_entry(d
,"*",0x20,nb_type
|NB_ACTIVE
,0,SELF
,d
->myip
,False
,wins
);
385 add_netbios_entry(d
,"__SAMBA__",0x20,nb_type
|NB_ACTIVE
,0,SELF
,d
->myip
,False
,wins
);
386 add_netbios_entry(d
,"__SAMBA__",0x00,nb_type
|NB_ACTIVE
,0,SELF
,d
->myip
,False
,wins
);
391 /****************************************************************************
392 remove all the samba names... from a WINS server if necessary.
393 **************************************************************************/
394 void remove_my_names()
396 struct subnet_record
*d
;
398 for (d
= FIRST_SUBNET
; d
; d
= NEXT_SUBNET_INCLUDING_WINS(d
))
400 struct name_record
*n
, *next
;
402 for (n
= d
->namelist
; n
; n
= next
)
405 if (n
->source
== SELF
)
407 /* get all SELF names removed from the WINS server's database */
408 /* XXXX note: problem occurs if this removes the wrong one! */
410 remove_name_entry(d
,n
->name
.name
, n
->name
.name_type
);
417 /*******************************************************************
419 ******************************************************************/
420 void refresh_my_names(time_t t
)
422 struct subnet_record
*d
;
424 for (d
= FIRST_SUBNET
; d
; d
= NEXT_SUBNET_INCLUDING_WINS(d
))
426 struct name_record
*n
;
428 for (n
= d
->namelist
; n
; n
= n
->next
)
430 /* each SELF name has an individual time to be refreshed */
431 if (n
->source
== SELF
&& n
->refresh_time
< t
&&
434 add_my_name_entry(d
,n
->name
.name
,n
->name
.name_type
,
435 n
->ip_flgs
[0].nb_flags
);
436 /* they get a new lease on life :-) */
437 n
->death_time
+= GET_TTL(0);
438 n
->refresh_time
+= GET_TTL(0);
445 /*******************************************************************
446 queries names occasionally. an over-cautious, non-trusting WINS server!
448 this function has been added because nmbd could be restarted. it
449 is generally a good idea to check all the names that have been
452 XXXX which names to poll and which not can be refined at a later date.
453 ******************************************************************/
454 void query_refresh_names(time_t t
)
456 struct name_record
*n
;
457 struct subnet_record
*d
= wins_subnet
;
459 static time_t lasttime
= 0;
462 int name_refresh_time
= NAME_POLL_REFRESH_TIME
;
463 int max_count
= name_refresh_time
* 2 / NAME_POLL_INTERVAL
;
464 if (max_count
> 10) max_count
= 10;
466 name_refresh_time
= NAME_POLL_INTERVAL
* max_count
/ 2;
468 /* if (!lp_poll_wins()) return; polling of registered names allowed */
472 if (!lasttime
) lasttime
= t
;
473 if (t
- lasttime
< NAME_POLL_INTERVAL
) return;
475 lasttime
= time(NULL
);
477 for (n
= d
->namelist
; n
; n
= n
->next
)
479 /* only do unique, registered names */
481 if (n
->source
!= REGISTER
) continue;
482 if (!NAME_GROUP(n
->ip_flgs
[0].nb_flags
)) continue;
484 if (n
->refresh_time
< t
)
486 DEBUG(3,("Polling name %s\n", namestr(&n
->name
)));
488 queue_netbios_packet(d
,ClientNMB
,NMB_QUERY
,NAME_QUERY_CONFIRM
,
489 n
->name
.name
, n
->name
.name_type
,
491 False
,False
,n
->ip_flgs
[0].ip
,n
->ip_flgs
[0].ip
);
495 if (count
>= max_count
)
497 /* don't do too many of these at once, but do enough to
498 cover everyone in the list */
502 /* this name will be checked on again, if it's not removed */
503 n
->refresh_time
+= name_refresh_time
;