summaryrefslogtreecommitdiff
path: root/source4/nmbd
diff options
context:
space:
mode:
Diffstat (limited to 'source4/nmbd')
-rw-r--r--source4/nmbd/asyncdns.c349
-rw-r--r--source4/nmbd/nmbd.c778
-rw-r--r--source4/nmbd/nmbd_become_dmb.c396
-rw-r--r--source4/nmbd/nmbd_become_lmb.c605
-rw-r--r--source4/nmbd/nmbd_browserdb.c182
-rw-r--r--source4/nmbd/nmbd_browsesync.c699
-rw-r--r--source4/nmbd/nmbd_elections.c403
-rw-r--r--source4/nmbd/nmbd_incomingdgrams.c858
-rw-r--r--source4/nmbd/nmbd_incomingrequests.c596
-rw-r--r--source4/nmbd/nmbd_lmhosts.c104
-rw-r--r--source4/nmbd/nmbd_logonnames.c172
-rw-r--r--source4/nmbd/nmbd_mynames.c228
-rw-r--r--source4/nmbd/nmbd_namelistdb.c624
-rw-r--r--source4/nmbd/nmbd_namequery.c304
-rw-r--r--source4/nmbd/nmbd_nameregister.c522
-rw-r--r--source4/nmbd/nmbd_namerelease.c222
-rw-r--r--source4/nmbd/nmbd_nodestatus.c94
-rw-r--r--source4/nmbd/nmbd_packets.c2013
-rw-r--r--source4/nmbd/nmbd_processlogon.c480
-rw-r--r--source4/nmbd/nmbd_responserecordsdb.c264
-rw-r--r--source4/nmbd/nmbd_sendannounce.c607
-rw-r--r--source4/nmbd/nmbd_serverlistdb.c448
-rw-r--r--source4/nmbd/nmbd_subnetdb.c361
-rw-r--r--source4/nmbd/nmbd_synclists.c300
-rw-r--r--source4/nmbd/nmbd_winsproxy.c221
-rw-r--r--source4/nmbd/nmbd_winsserver.c2032
-rw-r--r--source4/nmbd/nmbd_workgroupdb.c342
27 files changed, 0 insertions, 14204 deletions
diff --git a/source4/nmbd/asyncdns.c b/source4/nmbd/asyncdns.c
deleted file mode 100644
index c86ee69a09..0000000000
--- a/source4/nmbd/asyncdns.c
+++ /dev/null
@@ -1,349 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- a async DNS handler
- Copyright (C) Andrew Tridgell 1997-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include "includes.h"
-
-/***************************************************************************
- Add a DNS result to the name cache.
-****************************************************************************/
-
-static struct name_record *add_dns_result(struct nmb_name *question, struct in_addr addr)
-{
- int name_type = question->name_type;
- char *qname = question->name;
-
-
- if (!addr.s_addr) {
- /* add the fail to WINS cache of names. give it 1 hour in the cache */
- DEBUG(3,("add_dns_result: Negative DNS answer for %s\n", qname));
- (void)add_name_to_subnet( wins_server_subnet, qname, name_type,
- NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr );
- return( NULL );
- }
-
- /* add it to our WINS cache of names. give it 2 hours in the cache */
- DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr)));
-
- return( add_name_to_subnet( wins_server_subnet, qname, name_type,
- NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr ) );
-}
-
-
-
-#ifndef SYNC_DNS
-
-static int fd_in = -1, fd_out = -1;
-static pid_t child_pid = -1;
-static int in_dns;
-
-/* this is the structure that is passed between the parent and child */
-struct query_record {
- struct nmb_name name;
- struct in_addr result;
-};
-
-/* a queue of pending requests waiting to be sent to the DNS child */
-static struct packet_struct *dns_queue;
-
-/* the packet currently being processed by the dns child */
-static struct packet_struct *dns_current;
-
-
-/***************************************************************************
- return the fd used to gather async dns replies. This is added to the select
- loop
- ****************************************************************************/
-int asyncdns_fd(void)
-{
- return fd_in;
-}
-
-/***************************************************************************
- handle DNS queries arriving from the parent
- ****************************************************************************/
-static void asyncdns_process(void)
-{
- struct query_record r;
- fstring qname;
-
- DEBUGLEVEL = -1;
-
- while (1) {
- if (read_data(fd_in, (char *)&r, sizeof(r)) != sizeof(r))
- break;
-
- fstrcpy(qname, r.name.name);
-
- r.result.s_addr = interpret_addr(qname);
-
- if (write_data(fd_out, (char *)&r, sizeof(r)) != sizeof(r))
- break;
- }
-
- _exit(0);
-}
-
-/**************************************************************************** **
- catch a sigterm (in the child process - the parent has a different handler
- see nmbd.c for details).
- We need a separate term handler here so we don't release any
- names that our parent is going to release, or overwrite a
- WINS db that our parent is going to write.
- **************************************************************************** */
-
-static void sig_term(int sig)
-{
- _exit(0);
-}
-
-/***************************************************************************
- Called by the parent process when it receives a SIGTERM - also kills the
- child so we don't get child async dns processes lying around, causing trouble.
- ****************************************************************************/
-
-void kill_async_dns_child(void)
-{
- if (child_pid > 0) {
- kill(child_pid, SIGTERM);
- child_pid = -1;
- }
-}
-
-/***************************************************************************
- create a child process to handle DNS lookups
- ****************************************************************************/
-void start_async_dns(void)
-{
- int fd1[2], fd2[2];
-
- CatchChild();
-
- if (pipe(fd1) || pipe(fd2)) {
- DEBUG(0,("can't create asyncdns pipes\n"));
- return;
- }
-
- child_pid = sys_fork();
-
- if (child_pid) {
- fd_in = fd1[0];
- fd_out = fd2[1];
- close(fd1[1]);
- close(fd2[0]);
- DEBUG(0,("started asyncdns process %d\n", (int)child_pid));
- return;
- }
-
- fd_in = fd2[0];
- fd_out = fd1[1];
-
- CatchSignal(SIGUSR2, SIG_IGN);
- CatchSignal(SIGUSR1, SIG_IGN);
- CatchSignal(SIGHUP, SIG_IGN);
- CatchSignal(SIGTERM, SIGNAL_CAST sig_term );
-
- asyncdns_process();
-}
-
-
-/***************************************************************************
-check if a particular name is already being queried
- ****************************************************************************/
-static BOOL query_current(struct query_record *r)
-{
- return dns_current &&
- nmb_name_equal(&r->name,
- &dns_current->packet.nmb.question.question_name);
-}
-
-
-/***************************************************************************
- write a query to the child process
- ****************************************************************************/
-static BOOL write_child(struct packet_struct *p)
-{
- struct query_record r;
-
- r.name = p->packet.nmb.question.question_name;
-
- return write_data(fd_out, (char *)&r, sizeof(r)) == sizeof(r);
-}
-
-/***************************************************************************
- check the DNS queue
- ****************************************************************************/
-void run_dns_queue(void)
-{
- struct query_record r;
- struct packet_struct *p, *p2;
- struct name_record *namerec;
- int size;
-
- if (fd_in == -1)
- return;
-
- /* Allow SIGTERM to kill us. */
- BlockSignals(False, SIGTERM);
-
- if (!process_exists(child_pid)) {
- close(fd_in);
- start_async_dns();
- }
-
- if ((size=read_data(fd_in, (char *)&r, sizeof(r))) != sizeof(r)) {
- if (size) {
- DEBUG(0,("Incomplete DNS answer from child!\n"));
- fd_in = -1;
- }
- BlockSignals(True, SIGTERM);
- return;
- }
-
- BlockSignals(True, SIGTERM);
-
- namerec = add_dns_result(&r.name, r.result);
-
- if (dns_current) {
- if (query_current(&r)) {
- DEBUG(3,("DNS calling send_wins_name_query_response\n"));
- in_dns = 1;
- if(namerec == NULL)
- send_wins_name_query_response(NAM_ERR, dns_current, NULL);
- else
- send_wins_name_query_response(0,dns_current,namerec);
- in_dns = 0;
- }
-
- dns_current->locked = False;
- free_packet(dns_current);
- dns_current = NULL;
- }
-
- /* loop over the whole dns queue looking for entries that
- match the result we just got */
- for (p = dns_queue; p;) {
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
-
- if (nmb_name_equal(question, &r.name)) {
- DEBUG(3,("DNS calling send_wins_name_query_response\n"));
- in_dns = 1;
- if(namerec == NULL)
- send_wins_name_query_response(NAM_ERR, p, NULL);
- else
- send_wins_name_query_response(0,p,namerec);
- in_dns = 0;
- p->locked = False;
-
- if (p->prev)
- p->prev->next = p->next;
- else
- dns_queue = p->next;
- if (p->next)
- p->next->prev = p->prev;
- p2 = p->next;
- free_packet(p);
- p = p2;
- } else {
- p = p->next;
- }
- }
-
- if (dns_queue) {
- dns_current = dns_queue;
- dns_queue = dns_queue->next;
- if (dns_queue) dns_queue->prev = NULL;
- dns_current->next = NULL;
-
- if (!write_child(dns_current)) {
- DEBUG(3,("failed to send DNS query to child!\n"));
- return;
- }
- }
-
-}
-
-/***************************************************************************
-queue a DNS query
- ****************************************************************************/
-BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
- struct name_record **n)
-{
- if (in_dns || fd_in == -1)
- return False;
-
- if (!dns_current) {
- if (!write_child(p)) {
- DEBUG(3,("failed to send DNS query to child!\n"));
- return False;
- }
- dns_current = p;
- p->locked = True;
- } else {
- p->locked = True;
- p->next = dns_queue;
- p->prev = NULL;
- if (p->next)
- p->next->prev = p;
- dns_queue = p;
- }
-
- DEBUG(3,("added DNS query for %s\n", nmb_namestr(question)));
- return True;
-}
-
-#else
-
-
-/***************************************************************************
- we use this when we can't do async DNS lookups
- ****************************************************************************/
-BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
- struct name_record **n)
-{
- char *qname = question->name;
- struct in_addr dns_ip;
-
- DEBUG(3,("DNS search for %s - ", nmb_namestr(question)));
-
- /* Unblock TERM signal so we can be killed in DNS lookup. */
- BlockSignals(False, SIGTERM);
-
- dns_ip.s_addr = interpret_addr(qname);
-
- /* Re-block TERM signal. */
- BlockSignals(True, SIGTERM);
-
- *n = add_dns_result(question, dns_ip);
- if(*n == NULL)
- send_wins_name_query_response(NAM_ERR, p, NULL);
- else
- send_wins_name_query_response(0, p, *n);
- return False;
-}
-
-/***************************************************************************
- With sync dns there is no child to kill on SIGTERM.
- ****************************************************************************/
-void kill_async_dns_child(void)
-{
- return;
-}
-#endif
diff --git a/source4/nmbd/nmbd.c b/source4/nmbd/nmbd.c
deleted file mode 100644
index 0fa3525666..0000000000
--- a/source4/nmbd/nmbd.c
+++ /dev/null
@@ -1,778 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Jeremy Allison 1997-2002
- Copyright (C) Jelmer Vernooij 2002 (Conversion to popt)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-int ClientNMB = -1;
-int ClientDGRAM = -1;
-int global_nmb_port = -1;
-
-extern BOOL global_in_nmbd;
-
-/* are we running as a daemon ? */
-static BOOL is_daemon = False;
-
-/* fork or run in foreground ? */
-static BOOL Fork = True;
-
-/* log to standard output ? */
-static BOOL log_stdout = False;
-
-/* have we found LanMan clients yet? */
-BOOL found_lm_clients = False;
-
-/* what server type are we currently */
-
-time_t StartupTime = 0;
-
-/**************************************************************************** **
- Handle a SIGTERM in band.
- **************************************************************************** */
-
-static void terminate(void)
-{
- DEBUG(0,("Got SIGTERM: going down...\n"));
-
- /* Write out wins.dat file if samba is a WINS server */
- wins_write_database(False);
-
- /* Remove all SELF registered names from WINS */
- release_wins_names();
-
- /* Announce all server entries as 0 time-to-live, 0 type. */
- announce_my_servers_removed();
-
- /* If there was an async dns child - kill it. */
- kill_async_dns_child();
-
- exit(0);
-}
-
-/**************************************************************************** **
- Handle a SHUTDOWN message from smbcontrol.
- **************************************************************************** */
-
-static void nmbd_terminate(int msg_type, pid_t src, void *buf, size_t len)
-{
- terminate();
-}
-
-/**************************************************************************** **
- Catch a SIGTERM signal.
- **************************************************************************** */
-
-static sig_atomic_t got_sig_term;
-
-static void sig_term(int sig)
-{
- got_sig_term = 1;
- sys_select_signal();
-}
-
-/**************************************************************************** **
- Catch a SIGHUP signal.
- **************************************************************************** */
-
-static sig_atomic_t reload_after_sighup;
-
-static void sig_hup(int sig)
-{
- reload_after_sighup = 1;
- sys_select_signal();
-}
-
-/*******************************************************************
- Print out all talloc memory info.
-********************************************************************/
-
-void return_all_talloc_info(int msg_type, pid_t src_pid, void *buf, size_t len)
-{
- TALLOC_CTX *ctx = talloc_init("info context");
- char *info = NULL;
-
- if (!ctx)
- return;
-
- info = talloc_describe_all(ctx);
- if (info)
- DEBUG(10,(info));
- message_send_pid(src_pid, MSG_TALLOC_USAGE, info, info ? strlen(info) + 1 : 0, True);
- talloc_destroy(ctx);
-}
-
-#if DUMP_CORE
-/**************************************************************************** **
- Prepare to dump a core file - carefully!
- **************************************************************************** */
-
-static BOOL dump_core(void)
-{
- char *p;
- pstring dname;
- pstrcpy( dname, lp_logfile() );
- if ((p=strrchr_m(dname,'/')))
- *p=0;
- pstrcat( dname, "/corefiles" );
- mkdir( dname, 0700 );
- sys_chown( dname, getuid(), getgid() );
- chmod( dname, 0700 );
- if ( chdir(dname) )
- return( False );
- umask( ~(0700) );
-
-#ifdef HAVE_GETRLIMIT
-#ifdef RLIMIT_CORE
- {
- struct rlimit rlp;
- getrlimit( RLIMIT_CORE, &rlp );
- rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );
- setrlimit( RLIMIT_CORE, &rlp );
- getrlimit( RLIMIT_CORE, &rlp );
- DEBUG( 3, ( "Core limits now %d %d\n", (int)rlp.rlim_cur, (int)rlp.rlim_max ) );
- }
-#endif
-#endif
-
-
- DEBUG(0,("Dumping core in %s\n",dname));
- abort();
- return( True );
-}
-#endif
-
-/**************************************************************************** **
- Possibly continue after a fault.
- **************************************************************************** */
-
-static void fault_continue(void)
-{
-#if DUMP_CORE
- dump_core();
-#endif
-}
-
-/**************************************************************************** **
- Expire old names from the namelist and server list.
- **************************************************************************** */
-
-static void expire_names_and_servers(time_t t)
-{
- static time_t lastrun = 0;
-
- if ( !lastrun )
- lastrun = t;
- if ( t < (lastrun + 5) )
- return;
- lastrun = t;
-
- /*
- * Expire any timed out names on all the broadcast
- * subnets and those registered with the WINS server.
- * (nmbd_namelistdb.c)
- */
-
- expire_names(t);
-
- /*
- * Go through all the broadcast subnets and for each
- * workgroup known on that subnet remove any expired
- * server names. If a workgroup has an empty serverlist
- * and has itself timed out then remove the workgroup.
- * (nmbd_workgroupdb.c)
- */
-
- expire_workgroups_and_servers(t);
-}
-
-/************************************************************************** **
- Reload the list of network interfaces.
- ************************************************************************** */
-
-static BOOL reload_interfaces(time_t t)
-{
- static time_t lastt;
- int n;
- struct subnet_record *subrec;
- extern BOOL rescan_listen_set;
- extern struct in_addr loopback_ip;
-
- if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) return False;
- lastt = t;
-
- if (!interfaces_changed()) return False;
-
- /* the list of probed interfaces has changed, we may need to add/remove
- some subnets */
- load_interfaces();
-
- /* find any interfaces that need adding */
- for (n=iface_count() - 1; n >= 0; n--) {
- struct interface *iface = get_interface(n);
-
- /*
- * We don't want to add a loopback interface, in case
- * someone has added 127.0.0.1 for smbd, nmbd needs to
- * ignore it here. JRA.
- */
-
- if (ip_equal(iface->ip, loopback_ip)) {
- DEBUG(2,("reload_interfaces: Ignoring loopback interface %s\n", inet_ntoa(iface->ip)));
- continue;
- }
-
- for (subrec=subnetlist; subrec; subrec=subrec->next) {
- if (ip_equal(iface->ip, subrec->myip) &&
- ip_equal(iface->nmask, subrec->mask_ip)) break;
- }
-
- if (!subrec) {
- /* it wasn't found! add it */
- DEBUG(2,("Found new interface %s\n",
- inet_ntoa(iface->ip)));
- subrec = make_normal_subnet(iface);
- if (subrec) register_my_workgroup_one_subnet(subrec);
- }
- }
-
- /* find any interfaces that need deleting */
- for (subrec=subnetlist; subrec; subrec=subrec->next) {
- for (n=iface_count() - 1; n >= 0; n--) {
- struct interface *iface = get_interface(n);
- if (ip_equal(iface->ip, subrec->myip) &&
- ip_equal(iface->nmask, subrec->mask_ip)) break;
- }
- if (n == -1) {
- /* oops, an interface has disapeared. This is
- tricky, we don't dare actually free the
- interface as it could be being used, so
- instead we just wear the memory leak and
- remove it from the list of interfaces without
- freeing it */
- DEBUG(2,("Deleting dead interface %s\n",
- inet_ntoa(subrec->myip)));
- close_subnet(subrec);
- }
- }
-
- rescan_listen_set = True;
-
- /* We need to shutdown if there are no subnets... */
- if (FIRST_SUBNET == NULL) {
- DEBUG(0,("reload_interfaces: No subnets to listen to. Shutting down...\n"));
- return True;
- }
- return False;
-}
-
-/**************************************************************************** **
- Reload the services file.
- **************************************************************************** */
-
-static BOOL reload_nmbd_services(BOOL test)
-{
- BOOL ret;
-
- set_remote_machine_name("nmbd");
-
- if ( lp_loaded() ) {
- pstring fname;
- pstrcpy( fname,lp_configfile());
- if (file_exist(fname,NULL) && !strcsequal(fname,dyn_CONFIGFILE)) {
- pstrcpy(dyn_CONFIGFILE,fname);
- test = False;
- }
- }
-
- if ( test && !lp_file_list_changed() )
- return(True);
-
- ret = lp_load( dyn_CONFIGFILE, True , False, False);
-
- /* perhaps the config filename is now set */
- if ( !test ) {
- DEBUG( 3, ( "services not loaded\n" ) );
- reload_nmbd_services( True );
- }
-
- return(ret);
-}
-
-/**************************************************************************** **
- The main select loop.
- **************************************************************************** */
-
-static void process(void)
-{
- BOOL run_election;
-
- while( True ) {
- time_t t = time(NULL);
-
- /* Check for internal messages */
-
- message_dispatch();
-
- /*
- * Check all broadcast subnets to see if
- * we need to run an election on any of them.
- * (nmbd_elections.c)
- */
-
- run_election = check_elections();
-
- /*
- * Read incoming UDP packets.
- * (nmbd_packets.c)
- */
-
- if(listen_for_packets(run_election))
- return;
-
- /*
- * Handle termination inband.
- */
-
- if (got_sig_term) {
- got_sig_term = 0;
- terminate();
- }
-
- /*
- * Process all incoming packets
- * read above. This calls the success and
- * failure functions registered when response
- * packets arrrive, and also deals with request
- * packets from other sources.
- * (nmbd_packets.c)
- */
-
- run_packet_queue();
-
- /*
- * Run any elections - initiate becoming
- * a local master browser if we have won.
- * (nmbd_elections.c)
- */
-
- run_elections(t);
-
- /*
- * Send out any broadcast announcements
- * of our server names. This also announces
- * the workgroup name if we are a local
- * master browser.
- * (nmbd_sendannounce.c)
- */
-
- announce_my_server_names(t);
-
- /*
- * Send out any LanMan broadcast announcements
- * of our server names.
- * (nmbd_sendannounce.c)
- */
-
- announce_my_lm_server_names(t);
-
- /*
- * If we are a local master browser, periodically
- * announce ourselves to the domain master browser.
- * This also deals with syncronising the domain master
- * browser server lists with ourselves as a local
- * master browser.
- * (nmbd_sendannounce.c)
- */
-
- announce_myself_to_domain_master_browser(t);
-
- /*
- * Fullfill any remote announce requests.
- * (nmbd_sendannounce.c)
- */
-
- announce_remote(t);
-
- /*
- * Fullfill any remote browse sync announce requests.
- * (nmbd_sendannounce.c)
- */
-
- browse_sync_remote(t);
-
- /*
- * Scan the broadcast subnets, and WINS client
- * namelists and refresh any that need refreshing.
- * (nmbd_mynames.c)
- */
-
- refresh_my_names(t);
-
- /*
- * Scan the subnet namelists and server lists and
- * expire thos that have timed out.
- * (nmbd.c)
- */
-
- expire_names_and_servers(t);
-
- /*
- * Write out a snapshot of our current browse list into
- * the browse.dat file. This is used by smbd to service
- * incoming NetServerEnum calls - used to synchronise
- * browse lists over subnets.
- * (nmbd_serverlistdb.c)
- */
-
- write_browse_list(t, False);
-
- /*
- * If we are a domain master browser, we have a list of
- * local master browsers we should synchronise browse
- * lists with (these are added by an incoming local
- * master browser announcement packet). Expire any of
- * these that are no longer current, and pull the server
- * lists from each of these known local master browsers.
- * (nmbd_browsesync.c)
- */
-
- dmb_expire_and_sync_browser_lists(t);
-
- /*
- * Check that there is a local master browser for our
- * workgroup for all our broadcast subnets. If one
- * is not found, start an election (which we ourselves
- * may or may not participate in, depending on the
- * setting of the 'local master' parameter.
- * (nmbd_elections.c)
- */
-
- check_master_browser_exists(t);
-
- /*
- * If we are configured as a logon server, attempt to
- * register the special NetBIOS names to become such
- * (WORKGROUP<1c> name) on all broadcast subnets and
- * with the WINS server (if used). If we are configured
- * to become a domain master browser, attempt to register
- * the special NetBIOS name (WORKGROUP<1b> name) to
- * become such.
- * (nmbd_become_dmb.c)
- */
-
- add_domain_names(t);
-
- /*
- * If we are a WINS server, do any timer dependent
- * processing required.
- * (nmbd_winsserver.c)
- */
-
- initiate_wins_processing(t);
-
- /*
- * If we are a domain master browser, attempt to contact the
- * WINS server to get a list of all known WORKGROUPS/DOMAINS.
- * This will only work to a Samba WINS server.
- * (nmbd_browsesync.c)
- */
-
- if (lp_enhanced_browsing())
- collect_all_workgroup_names_from_wins_server(t);
-
- /*
- * Go through the response record queue and time out or re-transmit
- * and expired entries.
- * (nmbd_packets.c)
- */
-
- retransmit_or_expire_response_records(t);
-
- /*
- * check to see if any remote browse sync child processes have completed
- */
-
- sync_check_completion();
-
- /*
- * regularly sync with any other DMBs we know about
- */
-
- if (lp_enhanced_browsing())
- sync_all_dmbs(t);
-
- /*
- * clear the unexpected packet queue
- */
-
- clear_unexpected(t);
-
- /*
- * Reload the services file if we got a sighup.
- */
-
- if(reload_after_sighup) {
- DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) );
- write_browse_list( 0, True );
- dump_all_namelists();
- reload_nmbd_services( True );
- reopen_logs();
- if(reload_interfaces(0))
- return;
- reload_after_sighup = 0;
- }
-
- /* check for new network interfaces */
-
- if(reload_interfaces(t))
- return;
-
- /* free up temp memory */
- lp_talloc_free();
- }
-}
-
-/**************************************************************************** **
- Open the socket communication.
- **************************************************************************** */
-
-static BOOL open_sockets(BOOL isdaemon, int port)
-{
- /*
- * The sockets opened here will be used to receive broadcast
- * packets *only*. Interface specific sockets are opened in
- * make_subnet() in namedbsubnet.c. Thus we bind to the
- * address "0.0.0.0". The parameter 'socket address' is
- * now deprecated.
- */
-
- if ( isdaemon )
- ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0,True);
- else
- ClientNMB = 0;
-
- ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0,True);
-
- if ( ClientNMB == -1 )
- return( False );
-
- /* we are never interested in SIGPIPE */
- BlockSignals(True,SIGPIPE);
-
- set_socket_options( ClientNMB, "SO_BROADCAST" );
- set_socket_options( ClientDGRAM, "SO_BROADCAST" );
-
- DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
- return( True );
-}
-
-/**************************************************************************** **
- main program
- **************************************************************************** */
- int main(int argc, const char *argv[])
-{
- static BOOL opt_interactive = False;
- poptContext pc;
- struct poptOption long_options[] = {
- POPT_AUTOHELP
- {"daemon", 'D', POPT_ARG_VAL, &is_daemon, True, "Become a daemon(default)" },
- {"interactive", 'i', POPT_ARG_VAL, &opt_interactive, True, "Run interactive (not a daemon)" },
- {"foreground", 'F', POPT_ARG_VAL, &Fork, False, "Run daemon in foreground (for daemontools & etc)" },
- {"log-stdout", 'S', POPT_ARG_VAL, &log_stdout, True, "Log to stdout" },
- {"hosts", 'H', POPT_ARG_STRING, dyn_LMHOSTSFILE, 'H', "Load a netbios hosts file"},
- {"port", 'p', POPT_ARG_INT, &global_nmb_port, NMB_PORT, "Listen on the specified port" },
- {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_debug },
- {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_configfile },
- {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_socket_options },
- {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_version },
- {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_netbios_name },
- {NULL, 0, POPT_ARG_INCLUDE_TABLE, popt_common_log_base },
- { NULL }
- };
- int opt;
- pstring logfile;
-
- global_nmb_port = NMB_PORT;
- global_in_nmbd = True;
-
- StartupTime = time(NULL);
-
- sys_srandom(time(NULL) ^ sys_getpid());
-
- slprintf(logfile, sizeof(logfile)-1, "%s/log.nmbd", dyn_LOGFILEBASE);
- lp_set_logfile(logfile);
-
- fault_setup((void (*)(void *))fault_continue );
-
- /* POSIX demands that signals are inherited. If the invoking process has
- * these signals masked, we will have problems, as we won't recieve them. */
- BlockSignals(False, SIGHUP);
- BlockSignals(False, SIGUSR1);
- BlockSignals(False, SIGTERM);
-
- CatchSignal( SIGHUP, SIGNAL_CAST sig_hup );
- CatchSignal( SIGTERM, SIGNAL_CAST sig_term );
-
-#if defined(SIGFPE)
- /* we are never interested in SIGFPE */
- BlockSignals(True,SIGFPE);
-#endif
-
- /* We no longer use USR2... */
-#if defined(SIGUSR2)
- BlockSignals(True, SIGUSR2);
-#endif
- pc = poptGetContext("nmbd", argc, argv, long_options, 0);
-
- while((opt = poptGetNextOpt(pc)) != -1)
- { }
-
- poptFreeContext(pc);
-
- if ( opt_interactive ) {
- Fork = False;
- log_stdout = True;
- }
-
- if ( log_stdout && Fork ) {
- DEBUG(0,("ERROR: Can't log to stdout (-S) unless daemon is in foreground (-F) or interactive (-i)\n"));
- exit(1);
- }
-
- setup_logging( argv[0], log_stdout?DEBUG_STDOUT : DEBUG_FILE );
-
- reopen_logs();
-
- DEBUG( 0, ( "Netbios nameserver version %s started.\n", VERSION ) );
- DEBUGADD( 0, ( "Copyright Andrew Tridgell and the Samba Team 1994-2002\n" ) );
-
- if ( !reload_nmbd_services(False) )
- return(-1);
-
- if(!init_names())
- return -1;
-
- reload_nmbd_services( True );
-
- if (strequal(lp_workgroup(),"*"))
- {
- DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
- exit(1);
- }
-
- set_samba_nb_type();
-
- if (!is_daemon && !is_a_socket(0))
- {
- DEBUG(0,("standard input is not a socket, assuming -D option\n"));
- is_daemon = True;
- }
-
- if (is_daemon && !opt_interactive)
- {
- DEBUG( 2, ( "Becoming a daemon.\n" ) );
- become_daemon(Fork);
- }
-
-#if HAVE_SETPGID
- /*
- * If we're interactive we want to set our own process group for
- * signal management.
- */
- if (opt_interactive)
- setpgid( (pid_t)0, (pid_t)0 );
-#endif
-
-#ifndef SYNC_DNS
- /* Setup the async dns. We do it here so it doesn't have all the other
- stuff initialised and thus chewing memory and sockets */
- if(lp_we_are_a_wins_server() && lp_dns_proxy()) {
- start_async_dns();
- }
-#endif
-
- if (!directory_exist(lp_lockdir(), NULL)) {
- mkdir(lp_lockdir(), 0755);
- }
-
- pidfile_create("nmbd");
- message_init();
- message_register(MSG_FORCE_ELECTION, nmbd_message_election);
- message_register(MSG_WINS_NEW_ENTRY, nmbd_wins_new_entry);
- message_register(MSG_SHUTDOWN, nmbd_terminate);
- message_register(MSG_REQ_TALLOC_USAGE, return_all_talloc_info);
-
- DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
-
- if ( !open_sockets( is_daemon, global_nmb_port ) ) {
- kill_async_dns_child();
- return 1;
- }
-
- /* Determine all the IP addresses we have. */
- load_interfaces();
-
- /* Create an nmbd subnet record for each of the above. */
- if( False == create_subnets() )
- {
- DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
- kill_async_dns_child();
- exit(1);
- }
-
- /* Load in any static local names. */
- load_lmhosts_file(dyn_LMHOSTSFILE);
- DEBUG(3,("Loaded hosts file %s\n", dyn_LMHOSTSFILE));
-
- /* If we are acting as a WINS server, initialise data structures. */
- if( !initialise_wins() )
- {
- DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
- kill_async_dns_child();
- exit(1);
- }
-
- /*
- * Register nmbd primary workgroup and nmbd names on all
- * the broadcast subnets, and on the WINS server (if specified).
- * Also initiate the startup of our primary workgroup (start
- * elections if we are setup as being able to be a local
- * master browser.
- */
-
- if( False == register_my_workgroup_and_names() )
- {
- DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
- kill_async_dns_child();
- exit(1);
- }
-
- /* We can only take signals in the select. */
- BlockSignals( True, SIGTERM );
-
- process();
-
- if (dbf)
- x_fclose(dbf);
- kill_async_dns_child();
- return(0);
-}
diff --git a/source4/nmbd/nmbd_become_dmb.c b/source4/nmbd/nmbd_become_dmb.c
deleted file mode 100644
index d8122777fe..0000000000
--- a/source4/nmbd/nmbd_become_dmb.c
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-extern struct in_addr allones_ip;
-
-extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
-
-static void become_domain_master_browser_bcast(const char *);
-
-/****************************************************************************
- Fail to become a Domain Master Browser on a subnet.
- ****************************************************************************/
-
-static void become_domain_master_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *fail_name)
-{
- struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
- struct server_record *servrec;
-
- if(!work)
- {
- DEBUG(0,("become_domain_master_fail: Error - cannot find \
-workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
- return;
- }
-
- /* Set the state back to DOMAIN_NONE. */
- work->dom_state = DOMAIN_NONE;
-
- if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL)
- {
- DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- lp_netbios_name(), work->work_group, subrec->subnet_name));
- return;
- }
-
- /* Update our server status. */
- servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
-
- /* Tell the namelist writer to write out a change. */
- subrec->work_changed = True;
-
- DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
-workgroup %s on subnet %s. Couldn't register name %s.\n",
- work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
-}
-
-/****************************************************************************
- Become a Domain Master Browser on a subnet.
- ****************************************************************************/
-
-static void become_domain_master_stage2(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *registered_name,
- uint16 nb_flags,
- int ttl, struct in_addr registered_ip)
-{
- struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
- struct server_record *servrec;
-
- if(!work)
- {
- DEBUG(0,("become_domain_master_stage2: Error - cannot find \
-workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
- return;
- }
-
- if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL)
- {
- DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- lp_netbios_name(), registered_name->name, subrec->subnet_name));
- work->dom_state = DOMAIN_NONE;
- return;
- }
-
- /* Set the state in the workgroup structure. */
- work->dom_state = DOMAIN_MST; /* Become domain master. */
-
- /* Update our server status. */
- servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
-
- /* Tell the namelist writer to write out a change. */
- subrec->work_changed = True;
-
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "*****\n\nSamba server %s ", lp_netbios_name() );
- dbgtext( "is now a domain master browser for " );
- dbgtext( "workgroup %s ", work->work_group );
- dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
- }
-
- if( subrec == unicast_subnet )
- {
- struct nmb_name nmbname;
- struct in_addr my_first_ip;
-
- /* Put our name and first IP address into the
- workgroup struct as domain master browser. This
- will stop us syncing with ourself if we are also
- a local master browser. */
-
- make_nmb_name(&nmbname, lp_netbios_name(), 0x20);
-
- work->dmb_name = nmbname;
- /* Pick the first interface ip address as the domain master browser ip. */
- my_first_ip = *iface_n_ip(0);
-
- putip((char *)&work->dmb_addr, &my_first_ip);
-
- /* We successfully registered by unicast with the
- WINS server. We now expect to become the domain
- master on the local subnets. If this fails, it's
- probably a 1.9.16p2 to 1.9.16p11 server's fault.
-
- This is a configuration issue that should be addressed
- by the network administrator - you shouldn't have
- several machines configured as a domain master browser
- for the same WINS scope (except if they are 1.9.17 or
- greater, and you know what you're doing.
-
- see docs/DOMAIN.txt.
-
- */
- become_domain_master_browser_bcast(work->work_group);
- }
- else
- {
- /*
- * Now we are a domain master on a broadcast subnet, we need to add
- * the WORKGROUP<1b> name to the unicast subnet so that we can answer
- * unicast requests sent to this name. This bug wasn't found for a while
- * as it is strange to have a DMB without using WINS. JRA.
- */
- insert_permanent_name_into_unicast(subrec, registered_name, nb_flags);
- }
-}
-
-/****************************************************************************
- Start the name registration process when becoming a Domain Master Browser
- on a subnet.
- ****************************************************************************/
-
-static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name)
-{
- struct work_record *work;
-
- DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
-workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
-
- /* First, find the workgroup on the subnet. */
- if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL)
- {
- DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
- wg_name, subrec->subnet_name));
- return;
- }
-
- DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
- work->dom_state = DOMAIN_WAIT;
-
- /* WORKGROUP<1b> is the domain master browser name. */
- register_name(subrec, work->work_group,0x1b,samba_nb_type,
- become_domain_master_stage2,
- become_domain_master_fail, NULL);
-}
-
-/****************************************************************************
- Function called when a query for a WORKGROUP<1b> name succeeds.
- This is normally a fail condition as it means there is already
- a domain master browser for a workgroup and we were trying to
- become one.
-****************************************************************************/
-
-static void become_domain_master_query_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname, struct in_addr ip,
- struct res_rec *rrec)
-{
- /* If the given ip is not ours, then we can't become a domain
- controler as the name is already registered.
- */
-
- /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
- address or zero ip for this query. Pretend this is ok. */
-
- if(ismyip(ip) || ip_equal(allones_ip, ip) || is_zero_ip(ip))
- {
- if( DEBUGLVL( 3 ) )
- {
- dbgtext( "become_domain_master_query_success():\n" );
- dbgtext( "Our address (%s) ", inet_ntoa(ip) );
- dbgtext( "returned in query for name %s ", nmb_namestr(nmbname) );
- dbgtext( "(domain master browser name) " );
- dbgtext( "on subnet %s.\n", subrec->subnet_name );
- dbgtext( "Continuing with domain master code.\n" );
- }
-
- become_domain_master_stage1(subrec, nmbname->name);
- }
- else
- {
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "become_domain_master_query_success:\n" );
- dbgtext( "There is already a domain master browser at " );
- dbgtext( "IP %s for workgroup %s ", inet_ntoa(ip), nmbname->name );
- dbgtext( "registered on subnet %s.\n", subrec->subnet_name );
- }
- }
-}
-
-/****************************************************************************
- Function called when a query for a WORKGROUP<1b> name fails.
- This is normally a success condition as it then allows us to register
- our own Domain Master Browser name.
- ****************************************************************************/
-
-static void become_domain_master_query_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *question_name, int fail_code)
-{
- /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
- then this is a failure. Otherwise, not finding the name is what we want. */
- if((subrec == unicast_subnet) && (fail_code != NAM_ERR))
- {
- DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
-querying WINS server for name %s.\n",
- fail_code, nmb_namestr(question_name)));
- return;
- }
-
- /* Otherwise - not having the name allows us to register it. */
- become_domain_master_stage1(subrec, question_name->name);
-}
-
-/****************************************************************************
- Attempt to become a domain master browser on all broadcast subnets.
- ****************************************************************************/
-
-static void become_domain_master_browser_bcast(const char *workgroup_name)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
-
- if (work && (work->dom_state == DOMAIN_NONE))
- {
- struct nmb_name nmbname;
- make_nmb_name(&nmbname,workgroup_name,0x1b);
-
- /*
- * Check for our name on the given broadcast subnet first, only initiate
- * further processing if we cannot find it.
- */
-
- if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
- {
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "become_domain_master_browser_bcast:\n" );
- dbgtext( "Attempting to become domain master browser on " );
- dbgtext( "workgroup %s on subnet %s\n",
- workgroup_name, subrec->subnet_name );
- }
-
- /* Send out a query to establish whether there's a
- domain controller on the local subnet. If not,
- we can become a domain controller.
- */
-
- DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
-for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
-
- query_name(subrec, nmbname.name, nmbname.name_type,
- become_domain_master_query_success,
- become_domain_master_query_fail,
- NULL);
- }
- }
- }
-}
-
-/****************************************************************************
- Attempt to become a domain master browser by registering with WINS.
- ****************************************************************************/
-
-static void become_domain_master_browser_wins(const char *workgroup_name)
-{
- struct work_record *work;
-
- work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
-
- if (work && (work->dom_state == DOMAIN_NONE))
- {
- struct nmb_name nmbname;
-
- make_nmb_name(&nmbname,workgroup_name,0x1b);
-
- /*
- * Check for our name on the unicast subnet first, only initiate
- * further processing if we cannot find it.
- */
-
- if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL)
- {
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "become_domain_master_browser_wins:\n" );
- dbgtext( "Attempting to become domain master browser " );
- dbgtext( "on workgroup %s, subnet %s.\n",
- workgroup_name, unicast_subnet->subnet_name );
- }
-
- /* Send out a query to establish whether there's a
- domain master broswer registered with WINS. If not,
- we can become a domain master browser.
- */
-
- DEBUG(0,("become_domain_master_browser_wins: querying WINS server from IP %s \
-for domain master browser name %s on workgroup %s\n",
- inet_ntoa(unicast_subnet->myip), nmb_namestr(&nmbname), workgroup_name));
-
- query_name(unicast_subnet, nmbname.name, nmbname.name_type,
- become_domain_master_query_success,
- become_domain_master_query_fail,
- NULL);
- }
- }
-}
-
-/****************************************************************************
- Add the domain logon server and domain master browser names
- if we are set up to do so.
- **************************************************************************/
-
-void add_domain_names(time_t t)
-{
- static time_t lastrun = 0;
-
- if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
- return;
-
- lastrun = t;
-
- /* Do the "internet group" - <1c> names. */
- if (lp_domain_logons())
- add_logon_names();
-
- /* Do the domain master names. */
- if(lp_server_role() == ROLE_DOMAIN_PDC)
- {
- if(we_are_a_wins_client())
- {
- /* We register the WORKGROUP<1b> name with the WINS
- server first, and call add_domain_master_bcast()
- only if this is successful.
-
- This results in domain logon services being gracefully provided,
- as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
- 1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
- cannot provide domain master / domain logon services.
- */
- become_domain_master_browser_wins(lp_workgroup());
- }
- else
- become_domain_master_browser_bcast(lp_workgroup());
- }
-}
diff --git a/source4/nmbd/nmbd_become_lmb.c b/source4/nmbd/nmbd_become_lmb.c
deleted file mode 100644
index 8b87ca7444..0000000000
--- a/source4/nmbd/nmbd_become_lmb.c
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
-
-/*******************************************************************
- Utility function to add a name to the unicast subnet, or add in
- our IP address if it already exists.
-******************************************************************/
-
-void insert_permanent_name_into_unicast( struct subnet_record *subrec,
- struct nmb_name *nmbname, uint16 nb_type )
-{
- struct name_record *namerec;
-
- if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL)
- {
- /* The name needs to be created on the unicast subnet. */
- (void)add_name_to_subnet( unicast_subnet, nmbname->name,
- nmbname->name_type, nb_type,
- PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
- }
- else
- {
- /* The name already exists on the unicast subnet. Add our local
- IP for the given broadcast subnet to the name. */
- add_ip_to_name_record( namerec, subrec->myip);
- }
-}
-
-/*******************************************************************
- Utility function to remove a name from the unicast subnet.
-******************************************************************/
-
-static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
- struct nmb_name *nmbname )
-{
- struct name_record *namerec;
-
- if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL)
- {
- /* Remove this broadcast subnet IP address from the name. */
- remove_ip_from_name_record( namerec, subrec->myip);
- if(namerec->data.num_ips == 0)
- remove_name_from_namelist( unicast_subnet, namerec);
- }
-}
-
-/*******************************************************************
- Utility function always called to set our workgroup and server
- state back to potential browser, or none.
-******************************************************************/
-
-static void reset_workgroup_state( struct subnet_record *subrec, char *workgroup_name,
- BOOL force_new_election )
-{
- struct work_record *work;
- struct server_record *servrec;
- struct nmb_name nmbname;
-
- if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL)
- {
- DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
-subnet %s.\n", workgroup_name, subrec->subnet_name ));
- return;
- }
-
- if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL)
- {
- DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- lp_netbios_name(), work->work_group, subrec->subnet_name));
- work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
- return;
- }
-
- /* Update our server status - remove any master flag and replace
- it with the potential browser flag. */
- servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
- servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
-
- /* Tell the namelist writer to write out a change. */
- subrec->work_changed = True;
-
- /* Reset our election flags. */
- work->ElectionCriterion &= ~0x4;
-
- work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
-
- /* Forget who the local master browser was for
- this workgroup. */
-
- set_workgroup_local_master_browser_name( work, "");
-
- /*
- * Ensure the IP address of this subnet is not registered as one
- * of the IP addresses of the WORKGROUP<1d> name on the unicast
- * subnet. This undoes what we did below when we became a local
- * master browser.
- */
-
- make_nmb_name(&nmbname, work->work_group, 0x1d);
-
- remove_permanent_name_from_unicast( subrec, &nmbname);
-
- if(force_new_election)
- work->needelection = True;
-}
-
-/*******************************************************************
- Unbecome the local master browser name release success function.
-******************************************************************/
-
-static void unbecome_local_master_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *released_name,
- struct in_addr released_ip)
-{
- BOOL force_new_election = False;
-
- memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
-
- DEBUG(3,("unbecome_local_master_success: released name %s.\n",
- nmb_namestr(released_name)));
-
- /* Now reset the workgroup and server state. */
- reset_workgroup_state( subrec, released_name->name, force_new_election );
-
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "*****\n\n" );
- dbgtext( "Samba name server %s ", lp_netbios_name() );
- dbgtext( "has stopped being a local master browser " );
- dbgtext( "for workgroup %s ", released_name->name );
- dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
- }
-
-}
-
-/*******************************************************************
- Unbecome the local master browser name release fail function.
-******************************************************************/
-
-static void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
- struct nmb_name *fail_name)
-{
- struct name_record *namerec;
- struct userdata_struct *userdata = rrec->userdata;
- BOOL force_new_election = False;
-
- memcpy((char *)&force_new_election, userdata->data, sizeof(BOOL));
-
- DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
-Removing from namelist anyway.\n", nmb_namestr(fail_name)));
-
- /* Do it anyway. */
- namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
- if(namerec)
- remove_name_from_namelist(subrec, namerec);
-
- /* Now reset the workgroup and server state. */
- reset_workgroup_state( subrec, fail_name->name, force_new_election );
-
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "*****\n\n" );
- dbgtext( "Samba name server %s ", lp_netbios_name() );
- dbgtext( "has stopped being a local master browser " );
- dbgtext( "for workgroup %s ", fail_name->name );
- dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
- }
-}
-
-/*******************************************************************
- Utility function to remove the WORKGROUP<1d> name.
-******************************************************************/
-
-static void release_1d_name( struct subnet_record *subrec, char *workgroup_name,
- BOOL force_new_election)
-{
- struct nmb_name nmbname;
- struct name_record *namerec;
-
- make_nmb_name(&nmbname, workgroup_name, 0x1d);
- if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
- {
- struct userdata_struct *userdata;
- int size = sizeof(struct userdata_struct) + sizeof(BOOL);
-
- if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
- {
- DEBUG(0,("release_1d_name: malloc fail.\n"));
- return;
- }
-
- userdata->copy_fn = NULL;
- userdata->free_fn = NULL;
- userdata->userdata_len = sizeof(BOOL);
- memcpy((char *)userdata->data, &force_new_election, sizeof(BOOL));
-
- release_name(subrec, namerec,
- unbecome_local_master_success,
- unbecome_local_master_fail,
- userdata);
-
- zero_free(userdata, size);
- }
-}
-
-/*******************************************************************
- Unbecome the local master browser MSBROWSE name release success function.
-******************************************************************/
-
-static void release_msbrowse_name_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *released_name,
- struct in_addr released_ip)
-{
- DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
- nmb_namestr(released_name), subrec->subnet_name ));
-
- /* Remove the permanent MSBROWSE name added into the unicast subnet. */
- remove_permanent_name_from_unicast( subrec, released_name);
-}
-
-/*******************************************************************
- Unbecome the local master browser MSBROWSE name release fail function.
-******************************************************************/
-
-static void release_msbrowse_name_fail( struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *fail_name)
-{
- struct name_record *namerec;
-
- DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
- nmb_namestr(fail_name), subrec->subnet_name ));
-
- /* Release the name anyway. */
- namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
- if(namerec)
- remove_name_from_namelist(subrec, namerec);
-
- /* Remove the permanent MSBROWSE name added into the unicast subnet. */
- remove_permanent_name_from_unicast( subrec, fail_name);
-}
-
-/*******************************************************************
- Unbecome the local master browser. If force_new_election is true, restart
- the election process after we've unbecome the local master.
-******************************************************************/
-
-void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work,
- BOOL force_new_election)
-{
- struct name_record *namerec;
- struct nmb_name nmbname;
-
- /* Sanity check. */
-
- DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \
-on subnet %s\n",work->work_group, subrec->subnet_name));
-
- if(find_server_in_workgroup( work, lp_netbios_name()) == NULL)
- {
- DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- lp_netbios_name(), work->work_group, subrec->subnet_name));
- work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
- return;
- }
-
- /* Set the state to unbecoming. */
- work->mst_state = MST_UNBECOMING_MASTER;
-
- /*
- * Release the WORKGROUP<1d> name asap to allow another machine to
- * claim it.
- */
-
- release_1d_name( subrec, work->work_group, force_new_election);
-
- /* Deregister any browser names we may have. */
- make_nmb_name(&nmbname, MSBROWSE, 0x1);
- if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
- {
- release_name(subrec, namerec,
- release_msbrowse_name_success,
- release_msbrowse_name_fail,
- NULL);
- }
-
- /*
- * Ensure we have sent and processed these release packets
- * before returning - we don't want to process any election
- * packets before dealing with the 1d release.
- */
-
- retransmit_or_expire_response_records(time(NULL));
-}
-
-/****************************************************************************
- Success in registering the WORKGROUP<1d> name.
- We are now *really* a local master browser.
- ****************************************************************************/
-
-static void become_local_master_stage2(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *registered_name,
- uint16 nb_flags,
- int ttl, struct in_addr registered_ip)
-{
- int i = 0;
- struct server_record *sl;
- struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
- struct server_record *servrec;
-
- if(!work)
- {
- DEBUG(0,("become_local_master_stage2: Error - cannot find \
-workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
- return;
- }
-
- if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL)
- {
- DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- lp_netbios_name(), registered_name->name, subrec->subnet_name));
- work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
- return;
- }
-
- DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \
-on subnet %s\n", work->work_group, subrec->subnet_name));
-
- work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
-
- /* update our server status */
- servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
- servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
-
- /* Tell the namelist writer to write out a change. */
- subrec->work_changed = True;
-
- /* Add this name to the workgroup as local master browser. */
- set_workgroup_local_master_browser_name( work, lp_netbios_name());
-
- /* Count the number of servers we have on our list. If it's
- less than 10 (just a heuristic) request the servers
- to announce themselves.
- */
- for( sl = work->serverlist; sl != NULL; sl = sl->next)
- i++;
-
- if (i < 10)
- {
- /* Ask all servers on our local net to announce to us. */
- broadcast_announce_request(subrec, work);
- }
-
- /*
- * Now we are a local master on a broadcast subnet, we need to add
- * the WORKGROUP<1d> name to the unicast subnet so that we can answer
- * unicast requests sent to this name. We can create this name directly on
- * the unicast subnet as a WINS server always returns true when registering
- * this name, and discards the registration. We use the number of IP
- * addresses registered to this name as a reference count, as we
- * remove this broadcast subnet IP address from it when we stop becoming a local
- * master browser for this broadcast subnet.
- */
-
- insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
-
- /* Reset the announce master browser timer so that we try and tell a domain
- master browser as soon as possible that we are a local master browser. */
- reset_announce_timer();
-
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "*****\n\n" );
- dbgtext( "Samba name server %s ", lp_netbios_name() );
- dbgtext( "is now a local master browser " );
- dbgtext( "for workgroup %s ", work->work_group );
- dbgtext( "on subnet %s\n\n*****\n", subrec->subnet_name );
- }
-
-}
-
-/****************************************************************************
- Failed to register the WORKGROUP<1d> name.
- ****************************************************************************/
-static void become_local_master_fail2(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *fail_name)
-{
- struct work_record *work = find_workgroup_on_subnet( subrec, fail_name->name);
-
- DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \
-Failed to become a local master browser.\n", nmb_namestr(fail_name), subrec->subnet_name));
-
- if(!work)
- {
- DEBUG(0,("become_local_master_fail2: Error - cannot find \
-workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
- return;
- }
-
- /* Roll back all the way by calling unbecome_local_master_browser(). */
- unbecome_local_master_browser(subrec, work, False);
-}
-
-/****************************************************************************
- Success in registering the MSBROWSE name.
- ****************************************************************************/
-
-static void become_local_master_stage1(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *registered_name,
- uint16 nb_flags,
- int ttl, struct in_addr registered_ip)
-{
- char *work_name = userdata->data;
- struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
-
- if(!work)
- {
- DEBUG(0,("become_local_master_stage1: Error - cannot find \
-workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
- return;
- }
-
- DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
- work->work_group));
-
- work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */
-
- /*
- * We registered the MSBROWSE name on a broadcast subnet, now need to add
- * the MSBROWSE name to the unicast subnet so that we can answer
- * unicast requests sent to this name. We create this name directly on
- * the unicast subnet.
- */
-
- insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
-
- /* Attempt to register the WORKGROUP<1d> name. */
- register_name(subrec, work->work_group,0x1d,samba_nb_type,
- become_local_master_stage2,
- become_local_master_fail2,
- NULL);
-}
-
-/****************************************************************************
- Failed to register the MSBROWSE name.
- ****************************************************************************/
-
-static void become_local_master_fail1(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *fail_name)
-{
- char *work_name = rrec->userdata->data;
- struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
-
- if(!work)
- {
- DEBUG(0,("become_local_master_fail1: Error - cannot find \
-workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
- return;
- }
-
- if(find_server_in_workgroup(work, lp_netbios_name()) == NULL)
- {
- DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- lp_netbios_name(), work->work_group, subrec->subnet_name));
- return;
- }
-
- reset_workgroup_state( subrec, work->work_group, False );
-
- DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \
-workgroup %s on subnet %s. Couldn't register name %s.\n",
- work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
-}
-
-/******************************************************************
- Become the local master browser on a subnet.
- This gets called if we win an election on this subnet.
-
- Stage 1: mst_state was MST_POTENTIAL - go to MST_BACK register ^1^2__MSBROWSE__^2^1.
- Stage 2: mst_state was MST_BACKUP - go to MST_MSB and register WORKGROUP<1d>.
- Stage 3: mst_state was MST_MSB - go to MST_BROWSER.
-******************************************************************/
-
-void become_local_master_browser(struct subnet_record *subrec, struct work_record *work)
-{
- struct userdata_struct *userdata;
- int size = sizeof(struct userdata_struct) + sizeof(fstring) + 1;
-
- /* Sanity check. */
- if (!lp_local_master())
- {
- DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
- return;
- }
-
- if(!AM_POTENTIAL_MASTER_BROWSER(work))
- {
- DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
- work->mst_state ));
- return;
- }
-
- if(find_server_in_workgroup( work, lp_netbios_name()) == NULL)
- {
- DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- lp_netbios_name(), work->work_group, subrec->subnet_name));
- return;
- }
-
- DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \
-%s on subnet %s\n", work->work_group, subrec->subnet_name));
-
- DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n"));
- work->mst_state = MST_BACKUP; /* an election win was successful */
-
- work->ElectionCriterion |= 0x5;
-
- /* Tell the namelist writer to write out a change. */
- subrec->work_changed = True;
-
- /* Setup the userdata_struct. */
- if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
- {
- DEBUG(0,("become_local_master_browser: malloc fail.\n"));
- return;
- }
-
- userdata->copy_fn = NULL;
- userdata->free_fn = NULL;
- userdata->userdata_len = strlen(work->work_group)+1;
- fstrcpy(userdata->data, work->work_group);
-
- /* Register the special browser group name. */
- register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
- become_local_master_stage1,
- become_local_master_fail1,
- userdata);
-
- zero_free(userdata, size);
-}
-
-/***************************************************************
- Utility function to set the local master browser name. Does
- some sanity checking as old versions of Samba seem to sometimes
- say that the master browser name for a workgroup is the same
- as the workgroup name.
-****************************************************************/
-
-void set_workgroup_local_master_browser_name( struct work_record *work, const char *newname)
-{
- DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \
-for workgroup %s.\n", newname, work->work_group ));
-
-#if 0
- /*
- * Apparently some sites use the workgroup name as the local
- * master browser name. Arrrrggghhhhh ! (JRA).
- */
- if(strequal( work->work_group, newname))
- {
- DEBUG(5, ("set_workgroup_local_master_browser_name: Refusing to set \
-local_master_browser_name for workgroup %s to workgroup name.\n",
- work->work_group ));
- return;
- }
-#endif
-
- StrnCpy(work->local_master_browser_name, newname,
- sizeof(work->local_master_browser_name)-1);
-}
diff --git a/source4/nmbd/nmbd_browserdb.c b/source4/nmbd/nmbd_browserdb.c
deleted file mode 100644
index a4ef98e265..0000000000
--- a/source4/nmbd/nmbd_browserdb.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
- Copyright (C) Christopher R. Hertel 1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-/* -------------------------------------------------------------------------- **
- * Modified July 1998 by CRH.
- * I converted this module to use the canned doubly-linked lists. I also
- * added comments above the functions where possible.
- */
-
-#include "includes.h"
-
-/* -------------------------------------------------------------------------- **
- * Variables...
- *
- * lmb_browserlist - This is our local master browser list.
- */
-
-ubi_dlNewList( lmb_browserlist );
-
-
-/* -------------------------------------------------------------------------- **
- * Functions...
- */
-
-/* ************************************************************************** **
- * Remove and free a browser list entry.
- *
- * Input: browc - A pointer to the entry to be removed from the list and
- * freed.
- * Output: none.
- *
- * ************************************************************************** **
- */
-static void remove_lmb_browser_entry( struct browse_cache_record *browc )
- {
- safe_free( ubi_dlRemThis( lmb_browserlist, browc ) );
- } /* remove_lmb_browser_entry */
-
-/* ************************************************************************** **
- * Update a browser death time.
- *
- * Input: browc - Pointer to the entry to be updated.
- * Output: none.
- *
- * ************************************************************************** **
- */
-void update_browser_death_time( struct browse_cache_record *browc )
- {
- /* Allow the new lmb to miss an announce period before we remove it. */
- browc->death_time = time(NULL) + ( (CHECK_TIME_MST_ANNOUNCE + 2) * 60 );
- } /* update_browser_death_time */
-
-/* ************************************************************************** **
- * Create a browser entry and add it to the local master browser list.
- *
- * Input: work_name
- * browser_name
- * ip
- *
- * Output: Pointer to the new entry, or NULL if malloc() failed.
- *
- * ************************************************************************** **
- */
-struct browse_cache_record *create_browser_in_lmb_cache( char *work_name,
- char *browser_name,
- struct in_addr ip )
- {
- struct browse_cache_record *browc;
- time_t now = time( NULL );
-
- browc = (struct browse_cache_record *)malloc( sizeof( *browc ) );
-
- if( NULL == browc )
- {
- DEBUG( 0, ("create_browser_in_lmb_cache: malloc fail !\n") );
- return( NULL );
- }
-
- memset( (char *)browc, '\0', sizeof( *browc ) );
-
- /* For a new lmb entry we want to sync with it after one minute. This
- will allow it time to send out a local announce and build its
- browse list.
- */
- browc->sync_time = now + 60;
-
- /* Allow the new lmb to miss an announce period before we remove it. */
- browc->death_time = now + ( (CHECK_TIME_MST_ANNOUNCE + 2) * 60 );
-
- StrnCpy( browc->lmb_name, browser_name, sizeof(browc->lmb_name)-1 );
- StrnCpy( browc->work_group, work_name, sizeof(browc->work_group)-1 );
- strupper( browc->lmb_name );
- strupper( browc->work_group );
-
- browc->ip = ip;
-
- (void)ubi_dlAddTail( lmb_browserlist, browc );
-
- if( DEBUGLVL( 3 ) )
- {
- Debug1( "nmbd_browserdb:create_browser_in_lmb_cache()\n" );
- Debug1( " Added lmb cache entry for workgroup %s ", browc->work_group );
- Debug1( "name %s IP %s ", browc->lmb_name, inet_ntoa(ip) );
- Debug1( "ttl %d\n", (int)browc->death_time );
- }
-
- return( browc );
- } /* create_browser_in_lmb_cache */
-
-/* ************************************************************************** **
- * Find a browser entry in the local master browser list.
- *
- * Input: browser_name - The name for which to search.
- *
- * Output: A pointer to the matching entry, or NULL if no match was found.
- *
- * ************************************************************************** **
- */
-struct browse_cache_record *find_browser_in_lmb_cache( char *browser_name )
- {
- struct browse_cache_record *browc;
-
- for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
- browc;
- browc = (struct browse_cache_record *)ubi_dlNext( browc ) )
- if( strequal( browser_name, browc->lmb_name ) )
- break;
-
- return( browc );
- } /* find_browser_in_lmb_cache */
-
-/* ************************************************************************** **
- * Expire timed out browsers in the browserlist.
- *
- * Input: t - Expiration time. Entries with death times less than this
- * value will be removed from the list.
- * Output: none.
- *
- * ************************************************************************** **
- */
-void expire_lmb_browsers( time_t t )
- {
- struct browse_cache_record *browc;
- struct browse_cache_record *nextbrowc;
-
- for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
- browc;
- browc = nextbrowc )
- {
- nextbrowc = (struct browse_cache_record *)ubi_dlNext( browc );
-
- if( browc->death_time < t )
- {
- if( DEBUGLVL( 3 ) )
- {
- Debug1( "nmbd_browserdb:expire_lmb_browsers()\n" );
- Debug1( " Removing timed out lmb entry %s\n", browc->lmb_name );
- }
- remove_lmb_browser_entry( browc );
- }
- }
- } /* expire_lmb_browsers */
diff --git a/source4/nmbd/nmbd_browsesync.c b/source4/nmbd/nmbd_browsesync.c
deleted file mode 100644
index ff022a7bb1..0000000000
--- a/source4/nmbd/nmbd_browsesync.c
+++ /dev/null
@@ -1,699 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-/* This is our local master browser list database. */
-extern ubi_dlList lmb_browserlist[];
-
-/****************************************************************************
-As a domain master browser, do a sync with a local master browser.
-**************************************************************************/
-static void sync_with_lmb(struct browse_cache_record *browc)
-{
- struct work_record *work;
-
- if( !(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group)) )
- {
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "sync_with_lmb:\n" );
- dbgtext( "Failed to get a workgroup for a local master browser " );
- dbgtext( "cache entry workgroup " );
- dbgtext( "%s, server %s\n", browc->work_group, browc->lmb_name );
- }
- return;
- }
-
- /* We should only be doing this if we are a domain master browser for
- the given workgroup. Ensure this is so. */
-
- if(!AM_DOMAIN_MASTER_BROWSER(work))
- {
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "sync_with_lmb:\n" );
- dbgtext( "We are trying to sync with a local master browser " );
- dbgtext( "%s for workgroup %s\n", browc->lmb_name, browc->work_group );
- dbgtext( "and we are not a domain master browser on this workgroup.\n" );
- dbgtext( "Error!\n" );
- }
- return;
- }
-
- if( DEBUGLVL( 2 ) )
- {
- dbgtext( "sync_with_lmb:\n" );
- dbgtext( "Initiating sync with local master browser " );
- dbgtext( "%s<0x20> at IP %s ", browc->lmb_name, inet_ntoa(browc->ip) );
- dbgtext( "for workgroup %s\n", browc->work_group );
- }
-
- sync_browse_lists(work, browc->lmb_name, 0x20, browc->ip, True, True);
-
- browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60);
-}
-
-/****************************************************************************
-Sync or expire any local master browsers.
-**************************************************************************/
-void dmb_expire_and_sync_browser_lists(time_t t)
-{
- static time_t last_run = 0;
- struct browse_cache_record *browc;
-
- /* Only do this every 20 seconds. */
- if (t - last_run < 20)
- return;
-
- last_run = t;
-
- expire_lmb_browsers(t);
-
- for( browc = (struct browse_cache_record *)ubi_dlFirst( lmb_browserlist );
- browc;
- browc = (struct browse_cache_record *)ubi_dlNext( browc ) )
- {
- if (browc->sync_time < t)
- sync_with_lmb(browc);
- }
-}
-
-/****************************************************************************
-As a local master browser, send an announce packet to the domain master browser.
-**************************************************************************/
-
-static void announce_local_master_browser_to_domain_master_browser( struct work_record *work)
-{
- pstring outbuf;
- char *p;
-
- if(ismyip(work->dmb_addr))
- {
- if( DEBUGLVL( 2 ) )
- {
- dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
- dbgtext( "We are both a domain and a local master browser for " );
- dbgtext( "workgroup %s. ", work->work_group );
- dbgtext( "Do not announce to ourselves.\n" );
- }
- return;
- }
-
- memset(outbuf,'\0',sizeof(outbuf));
- p = outbuf;
- SCVAL(p,0,ANN_MasterAnnouncement);
- p++;
-
- StrnCpy(p,lp_netbios_name(),15);
- strupper(p);
- p = skip_string(p,1);
-
- if( DEBUGLVL( 4 ) )
- {
- dbgtext( "announce_local_master_browser_to_domain_master_browser:\n" );
- dbgtext( "Sending local master announce to " );
- dbgtext( "%s for workgroup %s.\n", nmb_namestr(&work->dmb_name),
- work->work_group );
- }
-
- send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
- lp_netbios_name(), 0x0, work->dmb_name.name, 0x0,
- work->dmb_addr, FIRST_SUBNET->myip, DGRAM_PORT);
-
-}
-
-/****************************************************************************
-As a local master browser, do a sync with a domain master browser.
-**************************************************************************/
-
-static void sync_with_dmb(struct work_record *work)
-{
- if( DEBUGLVL( 2 ) )
- {
- dbgtext( "sync_with_dmb:\n" );
- dbgtext( "Initiating sync with domain master browser " );
- dbgtext( "%s ", nmb_namestr(&work->dmb_name) );
- dbgtext( "at IP %s ", inet_ntoa(work->dmb_addr) );
- dbgtext( "for workgroup %s\n", work->work_group );
- }
-
- sync_browse_lists(work, work->dmb_name.name, work->dmb_name.name_type,
- work->dmb_addr, False, True);
-}
-
-/****************************************************************************
- Function called when a node status query to a domain master browser IP succeeds.
-****************************************************************************/
-
-static void domain_master_node_status_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct res_rec *answers,
- struct in_addr from_ip)
-{
- struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data);
-
- if( work == NULL )
- {
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "domain_master_node_status_success:\n" );
- dbgtext( "Unable to find workgroup " );
- dbgtext( "%s on subnet %s.\n", userdata->data, subrec->subnet_name );
- }
- return;
- }
-
- if( DEBUGLVL( 3 ) )
- {
- dbgtext( "domain_master_node_status_success:\n" );
- dbgtext( "Success in node status for workgroup " );
- dbgtext( "%s from ip %s\n", work->work_group, inet_ntoa(from_ip) );
- }
-
- /* Go through the list of names found at answers->rdata and look for
- the first SERVER<0x20> name. */
-
- if(answers->rdata != NULL)
- {
- char *p = answers->rdata;
- int numnames = CVAL(p, 0);
-
- p += 1;
-
- while (numnames--)
- {
- char qname[17];
- uint16 nb_flags;
- int name_type;
-
- StrnCpy(qname,p,15);
- name_type = CVAL(p,15);
- nb_flags = get_nb_flags(&p[16]);
- trim_string(qname,NULL," ");
-
- p += 18;
-
- if(!(nb_flags & NB_GROUP) && (name_type == 0x20))
- {
- struct nmb_name nmbname;
-
- make_nmb_name(&nmbname, qname, name_type);
-
- /* Copy the dmb name and IP address
- into the workgroup struct. */
-
- work->dmb_name = nmbname;
- putip((char *)&work->dmb_addr, &from_ip);
-
- /* Do the local master browser announcement to the domain
- master browser name and IP. */
- announce_local_master_browser_to_domain_master_browser( work );
-
- /* Now synchronise lists with the domain master browser. */
- sync_with_dmb(work);
- break;
- }
- }
- }
- else
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "domain_master_node_status_success:\n" );
- dbgtext( "Failed to find a SERVER<0x20> name in reply from IP " );
- dbgtext( "%s.\n", inet_ntoa(from_ip) );
- }
-}
-
-/****************************************************************************
- Function called when a node status query to a domain master browser IP fails.
-****************************************************************************/
-
-static void domain_master_node_status_fail(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- struct userdata_struct *userdata = rrec->userdata;
-
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "domain_master_node_status_fail:\n" );
- dbgtext( "Doing a node status request to the domain master browser\n" );
- dbgtext( "for workgroup %s ", userdata->data );
- dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
- dbgtext( "Cannot sync browser lists.\n" );
- }
-}
-
-/****************************************************************************
- Function called when a query for a WORKGROUP<1b> name succeeds.
-****************************************************************************/
-
-static void find_domain_master_name_query_success(struct subnet_record *subrec,
- struct userdata_struct *userdata_in,
- struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
-{
- /*
- * Unfortunately, finding the IP address of the Domain Master Browser,
- * as we have here, is not enough. We need to now do a sync to the
- * SERVERNAME<0x20> NetBIOS name, as only recent NT servers will
- * respond to the SMBSERVER name. To get this name from IP
- * address we do a Node status request, and look for the first
- * NAME<0x20> in the response, and take that as the server name.
- * We also keep a cache of the Domain Master Browser name for this
- * workgroup in the Workgroup struct, so that if the same IP addess
- * is returned every time, we don't need to do the node status
- * request.
- */
-
- struct work_record *work;
- struct nmb_name nmbname;
- struct userdata_struct *userdata;
- int size = sizeof(struct userdata_struct) + sizeof(fstring)+1;
-
- if( !(work = find_workgroup_on_subnet(subrec, q_name->name)) )
- {
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "find_domain_master_name_query_success:\n" );
- dbgtext( "Failed to find workgroup %s\n", q_name->name );
- }
- return;
- }
-
- /* First check if we already have a dmb for this workgroup. */
-
- if(!is_zero_ip(work->dmb_addr) && ip_equal(work->dmb_addr, answer_ip))
- {
- /* Do the local master browser announcement to the domain
- master browser name and IP. */
- announce_local_master_browser_to_domain_master_browser( work );
-
- /* Now synchronise lists with the domain master browser. */
- sync_with_dmb(work);
- return;
- }
- else
- zero_ip(&work->dmb_addr);
-
- /* Now initiate the node status request. */
- make_nmb_name(&nmbname,"*",0x0);
-
- /* Put the workgroup name into the userdata so we know
- what workgroup we're talking to when the reply comes
- back. */
-
- /* Setup the userdata_struct - this is copied so we can use
- a stack variable for this. */
- if((userdata = (struct userdata_struct *)malloc(size)) == NULL)
- {
- DEBUG(0, ("find_domain_master_name_query_success: malloc fail.\n"));
- return;
- }
-
- userdata->copy_fn = NULL;
- userdata->free_fn = NULL;
- userdata->userdata_len = strlen(work->work_group)+1;
- fstrcpy(userdata->data, work->work_group);
-
- node_status( subrec, &nmbname, answer_ip,
- domain_master_node_status_success,
- domain_master_node_status_fail,
- userdata);
-
- zero_free(userdata, size);
-}
-
-/****************************************************************************
- Function called when a query for a WORKGROUP<1b> name fails.
- ****************************************************************************/
-static void find_domain_master_name_query_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *question_name, int fail_code)
-{
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "find_domain_master_name_query_fail:\n" );
- dbgtext( "Unable to find the Domain Master Browser name " );
- dbgtext( "%s for the workgroup %s.\n",
- nmb_namestr(question_name), question_name->name );
- dbgtext( "Unable to sync browse lists in this workgroup.\n" );
- }
-}
-
-/****************************************************************************
-As a local master browser for a workgroup find the domain master browser
-name, announce ourselves as local master browser to it and then pull the
-full domain browse lists from it onto the given subnet.
-**************************************************************************/
-
-void announce_and_sync_with_domain_master_browser( struct subnet_record *subrec,
- struct work_record *work)
-{
- struct nmb_name nmbname;
-
- /* Only do this if we are using a WINS server. */
- if(we_are_a_wins_client() == False)
- {
- if( DEBUGLVL( 10 ) )
- {
- dbgtext( "announce_and_sync_with_domain_master_browser:\n" );
- dbgtext( "Ignoring, as we are not a WINS client.\n" );
- }
- return;
- }
-
- make_nmb_name(&nmbname,work->work_group,0x1b);
-
- /* First, query for the WORKGROUP<1b> name from the WINS server. */
- query_name(unicast_subnet, nmbname.name, nmbname.name_type,
- find_domain_master_name_query_success,
- find_domain_master_name_query_fail,
- NULL);
-
-}
-
-/****************************************************************************
- Function called when a node status query to a domain master browser IP succeeds.
- This function is only called on query to a Samba 1.9.18 or above WINS server.
-
- Note that adding the workgroup name is enough for this workgroup to be
- browsable by clients, as clients query the WINS server or broadcast
- nets for the WORKGROUP<1b> name when they want to browse a workgroup
- they are not in. We do not need to do a sync with this Domain Master
- Browser in order for our browse clients to see machines in this workgroup.
- JRA.
-****************************************************************************/
-
-static void get_domain_master_name_node_status_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct res_rec *answers,
- struct in_addr from_ip)
-{
- struct work_record *work;
- fstring server_name;
-
- server_name[0] = 0;
-
- if( DEBUGLVL( 3 ) )
- {
- dbgtext( "get_domain_master_name_node_status_success:\n" );
- dbgtext( "Success in node status from ip %s\n", inet_ntoa(from_ip) );
- }
-
- /*
- * Go through the list of names found at answers->rdata and look for
- * the first WORKGROUP<0x1b> name.
- */
-
- if(answers->rdata != NULL)
- {
- char *p = answers->rdata;
- int numnames = CVAL(p, 0);
-
- p += 1;
-
- while (numnames--)
- {
- char qname[17];
- uint16 nb_flags;
- int name_type;
-
- StrnCpy(qname,p,15);
- name_type = CVAL(p,15);
- nb_flags = get_nb_flags(&p[16]);
- trim_string(qname,NULL," ");
-
- p += 18;
-
- if(!(nb_flags & NB_GROUP) && (name_type == 0x00) &&
- server_name[0] == 0) {
- /* this is almost certainly the server netbios name */
- fstrcpy(server_name, qname);
- continue;
- }
-
- if(!(nb_flags & NB_GROUP) && (name_type == 0x1b))
- {
- if( DEBUGLVL( 5 ) )
- {
- dbgtext( "get_domain_master_name_node_status_success:\n" );
- dbgtext( "%s(%s) ", server_name, inet_ntoa(from_ip) );
- dbgtext( "is a domain master browser for workgroup " );
- dbgtext( "%s. Adding this name.\n", qname );
- }
-
- /*
- * If we don't already know about this workgroup, add it
- * to the workgroup list on the unicast_subnet.
- */
- if((work = find_workgroup_on_subnet( subrec, qname)) == NULL)
- {
- struct nmb_name nmbname;
- /*
- * Add it - with an hour in the cache.
- */
- if(!(work= create_workgroup_on_subnet(subrec, qname, 60*60)))
- return;
-
- /* remember who the master is */
- fstrcpy(work->local_master_browser_name, server_name);
- make_nmb_name(&nmbname, server_name, 0x20);
- work->dmb_name = nmbname;
- work->dmb_addr = from_ip;
- }
- break;
- }
- }
- }
- else
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "get_domain_master_name_node_status_success:\n" );
- dbgtext( "Failed to find a WORKGROUP<0x1b> name in reply from IP " );
- dbgtext( "%s.\n", inet_ntoa(from_ip) );
- }
-}
-
-/****************************************************************************
- Function called when a node status query to a domain master browser IP fails.
-****************************************************************************/
-
-static void get_domain_master_name_node_status_fail(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "get_domain_master_name_node_status_fail:\n" );
- dbgtext( "Doing a node status request to the domain master browser " );
- dbgtext( "at IP %s failed.\n", inet_ntoa(rrec->packet->ip) );
- dbgtext( "Cannot get workgroup name.\n" );
- }
-}
-
-/****************************************************************************
- Function called when a query for *<1b> name succeeds.
-****************************************************************************/
-
-static void find_all_domain_master_names_query_success(struct subnet_record *subrec,
- struct userdata_struct *userdata_in,
- struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
-{
- /*
- * We now have a list of all the domain master browsers for all workgroups
- * that have registered with the WINS server. Now do a node status request
- * to each one and look for the first 1b name in the reply. This will be
- * the workgroup name that we will add to the unicast subnet as a 'non-local'
- * workgroup.
- */
-
- struct nmb_name nmbname;
- struct in_addr send_ip;
- int i;
-
- if( DEBUGLVL( 5 ) )
- {
- dbgtext( "find_all_domain_master_names_query_succes:\n" );
- dbgtext( "Got answer from WINS server of %d ", (rrec->rdlength / 6) );
- dbgtext( "IP addresses for Domain Master Browsers.\n" );
- }
-
- for(i = 0; i < rrec->rdlength / 6; i++)
- {
- /* Initiate the node status requests. */
- make_nmb_name(&nmbname, "*", 0);
-
- putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]);
-
- /*
- * Don't send node status requests to ourself.
- */
-
- if(ismyip( send_ip ))
- {
- if( DEBUGLVL( 5 ) )
- {
- dbgtext( "find_all_domain_master_names_query_succes:\n" );
- dbgtext( "Not sending node status to our own IP " );
- dbgtext( "%s.\n", inet_ntoa(send_ip) );
- }
- continue;
- }
-
- if( DEBUGLVL( 5 ) )
- {
- dbgtext( "find_all_domain_master_names_query_success:\n" );
- dbgtext( "Sending node status request to IP %s.\n", inet_ntoa(send_ip) );
- }
-
- node_status( subrec, &nmbname, send_ip,
- get_domain_master_name_node_status_success,
- get_domain_master_name_node_status_fail,
- NULL);
- }
-}
-
-/****************************************************************************
- Function called when a query for *<1b> name fails.
- ****************************************************************************/
-static void find_all_domain_master_names_query_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *question_name, int fail_code)
-{
- if( DEBUGLVL( 10 ) )
- {
- dbgtext( "find_domain_master_name_query_fail:\n" );
- dbgtext( "WINS server did not reply to a query for name " );
- dbgtext( "%s.\nThis means it ", nmb_namestr(question_name) );
- dbgtext( "is probably not a Samba 1.9.18 or above WINS server.\n" );
- }
-}
-
-/****************************************************************************
- If we are a domain master browser on the unicast subnet, do a query to the
- WINS server for the *<1b> name. This will only work to a Samba WINS server,
- so ignore it if we fail. If we succeed, contact each of the IP addresses in
- turn and do a node status request to them. If this succeeds then look for a
- <1b> name in the reply - this is the workgroup name. Add this to the unicast
- subnet. This is expensive, so we only do this every 15 minutes.
-**************************************************************************/
-void collect_all_workgroup_names_from_wins_server(time_t t)
-{
- static time_t lastrun = 0;
- struct work_record *work;
- struct nmb_name nmbname;
-
- /* Only do this if we are using a WINS server. */
- if(we_are_a_wins_client() == False)
- return;
-
- /* Check to see if we are a domain master browser on the unicast subnet. */
- if((work = find_workgroup_on_subnet( unicast_subnet, lp_workgroup())) == NULL)
- {
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "collect_all_workgroup_names_from_wins_server:\n" );
- dbgtext( "Cannot find my workgroup %s ", lp_workgroup() );
- dbgtext( "on subnet %s.\n", unicast_subnet->subnet_name );
- }
- return;
- }
-
- if(!AM_DOMAIN_MASTER_BROWSER(work))
- return;
-
- if ((lastrun != 0) && (t < lastrun + (15 * 60)))
- return;
-
- lastrun = t;
-
- make_nmb_name(&nmbname,"*",0x1b);
-
- /* First, query for the *<1b> name from the WINS server. */
- query_name(unicast_subnet, nmbname.name, nmbname.name_type,
- find_all_domain_master_names_query_success,
- find_all_domain_master_names_query_fail,
- NULL);
-}
-
-
-/****************************************************************************
- If we are a domain master browser on the unicast subnet, do a regular sync
- with all other DMBs that we know of on that subnet.
-
-To prevent exponential network traffic with large numbers of workgroups
-we use a randomised system where sync probability is inversely proportional
-to the number of known workgroups
-**************************************************************************/
-void sync_all_dmbs(time_t t)
-{
- static time_t lastrun = 0;
- struct work_record *work;
- int count=0;
-
- /* Only do this if we are using a WINS server. */
- if(we_are_a_wins_client() == False)
- return;
-
- /* Check to see if we are a domain master browser on the
- unicast subnet. */
- work = find_workgroup_on_subnet(unicast_subnet, lp_workgroup());
- if (!work) return;
-
- if (!AM_DOMAIN_MASTER_BROWSER(work))
- return;
-
- if ((lastrun != 0) && (t < lastrun + (5 * 60)))
- return;
-
- /* count how many syncs we might need to do */
- for (work=unicast_subnet->workgrouplist; work; work = work->next) {
- if (strcmp(lp_workgroup(), work->work_group)) {
- count++;
- }
- }
-
- /* sync with a probability of 1/count */
- for (work=unicast_subnet->workgrouplist; work; work = work->next) {
- if (strcmp(lp_workgroup(), work->work_group)) {
- if (((unsigned)sys_random()) % count != 0) continue;
-
- lastrun = t;
-
- if (!work->dmb_name.name[0]) {
- /* we don't know the DMB - assume it is
- the same as the unicast local master */
- make_nmb_name(&work->dmb_name,
- work->local_master_browser_name,
- 0x20);
- }
-
- DEBUG(3,("Initiating DMB<->DMB sync with %s(%s)\n",
- work->dmb_name.name,
- inet_ntoa(work->dmb_addr)));
- sync_browse_lists(work,
- work->dmb_name.name,
- work->dmb_name.name_type,
- work->dmb_addr, False, False);
- }
- }
-}
diff --git a/source4/nmbd/nmbd_elections.c b/source4/nmbd/nmbd_elections.c
deleted file mode 100644
index 759379cc84..0000000000
--- a/source4/nmbd/nmbd_elections.c
+++ /dev/null
@@ -1,403 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-/* Election parameters. */
-extern time_t StartupTime;
-
-/****************************************************************************
- Send an election datagram packet.
-**************************************************************************/
-static void send_election_dgram(struct subnet_record *subrec, const char *workgroup_name,
- uint32 criterion, int timeup,const char *server_name)
-{
- pstring outbuf;
- char *p;
-
- DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n",
- workgroup_name, subrec->subnet_name ));
-
- memset(outbuf,'\0',sizeof(outbuf));
- p = outbuf;
- SCVAL(p,0,ANN_Election); /* Election opcode. */
- p++;
-
- SCVAL(p,0,((criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION));
- SIVAL(p,1,criterion);
- SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */
- p += 13;
- pstrcpy(p,server_name);
- strupper(p);
- p = skip_string(p,1);
-
- send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
- lp_netbios_name(), 0,
- workgroup_name, 0x1e,
- subrec->bcast_ip, subrec->myip, DGRAM_PORT);
-}
-
-/*******************************************************************
- We found a current master browser on one of our broadcast interfaces.
-******************************************************************/
-
-static void check_for_master_browser_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *answer_name,
- struct in_addr answer_ip, struct res_rec *rrec)
-{
- DEBUG(3,("check_for_master_browser_success: Local master browser for workgroup %s exists at \
-IP %s (just checking).\n", answer_name->name, inet_ntoa(answer_ip) ));
-}
-
-/*******************************************************************
- We failed to find a current master browser on one of our broadcast interfaces.
-******************************************************************/
-
-static void check_for_master_browser_fail( struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *question_name,
- int fail_code)
-{
- char *workgroup_name = question_name->name;
- struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
-
- if(work == NULL)
- {
- DEBUG(0,("check_for_master_browser_fail: Unable to find workgroup %s on subnet %s.=\n",
- workgroup_name, subrec->subnet_name ));
- return;
- }
-
- if (strequal(work->work_group, lp_workgroup()))
- {
-
- if (lp_local_master())
- {
- /* We have discovered that there is no local master
- browser, and we are configured to initiate
- an election that we will participate in.
- */
- DEBUG(2,("check_for_master_browser_fail: Forcing election on workgroup %s subnet %s\n",
- work->work_group, subrec->subnet_name ));
-
- /* Setting this means we will participate when the
- election is run in run_elections(). */
- work->needelection = True;
- }
- else
- {
- /* We need to force an election, because we are configured
- not to become the local master, but we still need one,
- having detected that one doesn't exist.
- */
- send_election_dgram(subrec, work->work_group, 0, 0, "");
- }
- }
-}
-
-/*******************************************************************
- Ensure there is a local master browser for a workgroup on our
- broadcast interfaces.
-******************************************************************/
-
-void check_master_browser_exists(time_t t)
-{
- static time_t lastrun=0;
- struct subnet_record *subrec;
- const char *workgroup_name = lp_workgroup();
-
- if (!lastrun)
- lastrun = t;
-
- if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60)))
- return;
-
- lastrun = t;
-
- dump_workgroups(False);
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work;
-
- for (work = subrec->workgrouplist; work; work = work->next)
- {
- if (strequal(work->work_group, workgroup_name) && !AM_LOCAL_MASTER_BROWSER(work))
- {
- /* Do a name query for the local master browser on this net. */
- query_name( subrec, work->work_group, 0x1d,
- check_for_master_browser_success,
- check_for_master_browser_fail,
- NULL);
- }
- }
- }
-}
-
-/*******************************************************************
- Run an election.
-******************************************************************/
-
-void run_elections(time_t t)
-{
- static time_t lastime = 0;
-
- struct subnet_record *subrec;
-
- /* Send election packets once every 2 seconds - note */
- if (lastime && (t - lastime < 2))
- return;
-
- lastime = t;
-
- START_PROFILE(run_elections);
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work;
-
- for (work = subrec->workgrouplist; work; work = work->next)
- {
- if (work->RunningElection)
- {
- /*
- * We can only run an election for a workgroup if we have
- * registered the WORKGROUP<1e> name, as that's the name
- * we must listen to.
- */
- struct nmb_name nmbname;
-
- make_nmb_name(&nmbname, work->work_group, 0x1e);
- if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
- DEBUG(8,("run_elections: Cannot send election packet yet as name %s not \
-yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name ));
- continue;
- }
-
- send_election_dgram(subrec, work->work_group, work->ElectionCriterion,
- t - StartupTime, lp_netbios_name());
-
- if (work->ElectionCount++ >= 4)
- {
- /* Won election (4 packets were sent out uncontested. */
- DEBUG(2,("run_elections: >>> Won election for workgroup %s on subnet %s <<<\n",
- work->work_group, subrec->subnet_name ));
-
- work->RunningElection = False;
-
- become_local_master_browser(subrec, work);
- }
- }
- }
- }
- END_PROFILE(run_elections);
-}
-
-/*******************************************************************
- Determine if I win an election.
-******************************************************************/
-
-static BOOL win_election(struct work_record *work, int version,
- uint32 criterion, int timeup, char *server_name)
-{
- int mytimeup = time(NULL) - StartupTime;
- uint32 mycriterion = work->ElectionCriterion;
-
- /* If local master is false then never win
- in election broadcasts. */
- if(!lp_local_master())
- {
- DEBUG(3,("win_election: Losing election as local master == False\n"));
- return False;
- }
-
- DEBUG(4,("win_election: election comparison: %x:%x %x:%x %d:%d %s:%s\n",
- version, ELECTION_VERSION,
- criterion, mycriterion,
- timeup, mytimeup,
- server_name, lp_netbios_name()));
-
- if (version > ELECTION_VERSION)
- return(False);
- if (version < ELECTION_VERSION)
- return(True);
-
- if (criterion > mycriterion)
- return(False);
- if (criterion < mycriterion)
- return(True);
-
- if (timeup > mytimeup)
- return(False);
- if (timeup < mytimeup)
- return(True);
-
- if (strcasecmp(lp_netbios_name(), server_name) > 0)
- return(False);
-
- return(True);
-}
-
-/*******************************************************************
- Process an incoming election datagram packet.
-******************************************************************/
-
-void process_election(struct subnet_record *subrec, struct packet_struct *p, char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int version = CVAL(buf,0);
- uint32 criterion = IVAL(buf,1);
- int timeup = IVAL(buf,5)/1000;
- char *server_name = buf+13;
- struct work_record *work;
- char *workgroup_name = dgram->dest_name.name;
-
- START_PROFILE(election);
- server_name[15] = 0;
-
- DEBUG(3,("process_election: Election request from %s at IP %s on subnet %s for workgroup %s.\n",
- server_name,inet_ntoa(p->ip), subrec->subnet_name, workgroup_name ));
-
- DEBUG(5,("process_election: vers=%d criterion=%08x timeup=%d\n", version,criterion,timeup));
-
- if(( work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL)
- {
- DEBUG(0,("process_election: Cannot find workgroup %s on subnet %s.\n",
- workgroup_name, subrec->subnet_name ));
- goto done;
- }
-
- if (!strequal(work->work_group, lp_workgroup()))
- {
- DEBUG(3,("process_election: ignoring election request for workgroup %s on subnet %s as this \
-is not my workgroup.\n", work->work_group, subrec->subnet_name ));
- goto done;
- }
-
- if (win_election(work, version,criterion,timeup,server_name))
- {
- /* We take precedence over the requesting server. */
- if (!work->RunningElection)
- {
- /* We weren't running an election - start running one. */
-
- work->needelection = True;
- work->ElectionCount=0;
- }
-
- /* Note that if we were running an election for this workgroup on this
- subnet already, we just ignore the server we take precedence over. */
- }
- else
- {
- /* We lost. Stop participating. */
- work->needelection = False;
-
- if (work->RunningElection || AM_LOCAL_MASTER_BROWSER(work))
- {
- work->RunningElection = False;
- DEBUG(3,("process_election: >>> Lost election for workgroup %s on subnet %s <<<\n",
- work->work_group, subrec->subnet_name ));
- if (AM_LOCAL_MASTER_BROWSER(work))
- unbecome_local_master_browser(subrec, work, False);
- }
- }
-done:
- END_PROFILE(election);
-}
-
-/****************************************************************************
- This function looks over all the workgroups known on all the broadcast
- subnets and decides if a browser election is to be run on that workgroup.
- It returns True if any election packets need to be sent (this will then
- be done by run_elections().
-***************************************************************************/
-
-BOOL check_elections(void)
-{
- struct subnet_record *subrec;
- BOOL run_any_election = False;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work;
- for (work = subrec->workgrouplist; work; work = work->next)
- {
- run_any_election |= work->RunningElection;
-
- /*
- * Start an election if we have any chance of winning.
- * Note this is a change to the previous code, that would
- * only run an election if nmbd was in the potential browser
- * state. We need to run elections in any state if we're told
- * to. JRA.
- */
-
- if (work->needelection && !work->RunningElection && lp_local_master())
- {
- /*
- * We can only run an election for a workgroup if we have
- * registered the WORKGROUP<1e> name, as that's the name
- * we must listen to.
- */
- struct nmb_name nmbname;
-
- make_nmb_name(&nmbname, work->work_group, 0x1e);
- if(find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME)==NULL) {
- DEBUG(8,("check_elections: Cannot send election packet yet as name %s not \
-yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name ));
- continue;
- }
-
- DEBUG(3,("check_elections: >>> Starting election for workgroup %s on subnet %s <<<\n",
- work->work_group, subrec->subnet_name ));
-
- work->ElectionCount = 0;
- work->RunningElection = True;
- work->needelection = False;
- }
- }
- }
- return run_any_election;
-}
-
-
-
-/****************************************************************************
-process a internal Samba message forcing an election
-***************************************************************************/
-void nmbd_message_election(int msg_type, pid_t src, void *buf, size_t len)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
- struct work_record *work;
- for (work = subrec->workgrouplist; work; work = work->next) {
- if (strequal(work->work_group, lp_workgroup())) {
- work->needelection = True;
- work->ElectionCount=0;
- work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
- }
- }
- }
-}
diff --git a/source4/nmbd/nmbd_incomingdgrams.c b/source4/nmbd/nmbd_incomingdgrams.c
deleted file mode 100644
index 3000c347d8..0000000000
--- a/source4/nmbd/nmbd_incomingdgrams.c
+++ /dev/null
@@ -1,858 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-extern BOOL found_lm_clients;
-
-#if 0
-
-/* XXXX note: This function is currently unsuitable for use, as it
- does not properly check that a server is in a fit state to become
- a backup browser before asking it to be one.
- The code is left here to be worked on at a later date.
-*/
-
-/****************************************************************************
-Tell a server to become a backup browser
-**************************************************************************/
-
-void tell_become_backup(void)
-{
- struct subnet_record *subrec;
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work;
- for (work = subrec->workgrouplist; work; work = work->next)
- {
- struct server_record *servrec;
- int num_servers = 0;
- int num_backups = 0;
-
- for (servrec = work->serverlist; servrec; servrec = servrec->next)
- {
- num_servers++;
-
- if (is_myname(servrec->serv.name))
- continue;
-
- if (servrec->serv.type & SV_TYPE_BACKUP_BROWSER)
- {
- num_backups++;
- continue;
- }
-
- if (servrec->serv.type & SV_TYPE_MASTER_BROWSER)
- continue;
-
- if (!(servrec->serv.type & SV_TYPE_POTENTIAL_BROWSER))
- continue;
-
- DEBUG(3,("num servers: %d num backups: %d\n",
- num_servers, num_backups));
-
- /* make first server a backup server. thereafter make every
- tenth server a backup server */
- if (num_backups != 0 && (num_servers+9) / num_backups > 10)
- continue;
-
- DEBUG(2,("sending become backup to %s %s for %s\n",
- servrec->serv.name, inet_ntoa(subrec->bcast_ip),
- work->work_group));
-
- /* type 11 request from MYNAME(20) to WG(1e) for SERVER */
- do_announce_request(servrec->serv.name, work->work_group,
- ANN_BecomeBackup, 0x20, 0x1e, subrec->bcast_ip);
- }
- }
- }
-}
-#endif
-
-/*******************************************************************
- Process an incoming host announcement packet.
-*******************************************************************/
-
-void process_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int ttl = IVAL(buf,1)/1000;
- char *announce_name = buf+5;
- uint32 servertype = IVAL(buf,23);
- char *comment = buf+31;
- struct work_record *work;
- struct server_record *servrec;
- const char *work_name;
- char *source_name = dgram->source_name.name;
-
- START_PROFILE(host_announce);
- comment[43] = 0;
-
- DEBUG(3,("process_host_announce: from %s<%02x> IP %s to \
-%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
- nmb_namestr(&dgram->dest_name),announce_name));
-
- DEBUG(5,("process_host_announce: ttl=%d server type=%08x comment=%s\n",
- ttl, servertype,comment));
-
- /* Filter servertype to remove impossible bits. */
- servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
-
- /* A host announcement must be sent to the name WORKGROUP<1d>. */
- if(dgram->dest_name.name_type != 0x1d)
- {
- DEBUG(2,("process_host_announce: incorrect name type for destination from IP %s \
-(was %02x) should be 0x1d. Allowing packet anyway.\n",
- inet_ntoa(p->ip), dgram->dest_name.name_type));
- /* Change it so it was. */
- dgram->dest_name.name_type = 0x1d;
- }
-
- /* For a host announce the workgroup name is the destination name. */
- work_name = dgram->dest_name.name;
-
- /*
- * Syntax servers version 5.1 send HostAnnounce packets to
- * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>
- * instead of WORKGROUP<1d> name. So to fix this we check if
- * the workgroup name is our own name, and if so change it
- * to be our primary workgroup name.
- */
-
- if(strequal(work_name, lp_netbios_name()))
- work_name = lp_workgroup();
-
- /*
- * We are being very agressive here in adding a workgroup
- * name on the basis of a host announcing itself as being
- * in that workgroup. Maybe we should wait for the workgroup
- * announce instead ? JRA.
- */
-
- work = find_workgroup_on_subnet(subrec, work_name);
-
- if(servertype != 0)
- {
- if (work ==NULL )
- {
- /* We have no record of this workgroup. Add it. */
- if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
- goto done;
- }
-
- if((servrec = find_server_in_workgroup( work, announce_name))==NULL)
- {
- /* If this server is not already in the workgroup, add it. */
- create_server_on_workgroup(work, announce_name,
- servertype|SV_TYPE_LOCAL_LIST_ONLY,
- ttl, comment);
- }
- else
- {
- /* Update the record. */
- servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
- update_server_ttl( servrec, ttl);
- StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1);
- }
- }
- else
- {
- /*
- * This server is announcing it is going down. Remove it from the
- * workgroup.
- */
- if(!is_myname(announce_name) && (work != NULL) &&
- ((servrec = find_server_in_workgroup( work, announce_name))!=NULL)
- )
- {
- remove_server_from_workgroup( work, servrec);
- }
- }
- subrec->work_changed = True;
-done:
- END_PROFILE(host_announce);
-}
-
-/*******************************************************************
- Process an incoming WORKGROUP announcement packet.
-*******************************************************************/
-
-void process_workgroup_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int ttl = IVAL(buf,1)/1000;
- char *workgroup_announce_name = buf+5;
- uint32 servertype = IVAL(buf,23);
- char *master_name = buf+31;
- struct work_record *work;
- char *source_name = dgram->source_name.name;
-
- START_PROFILE(workgroup_announce);
- master_name[43] = 0;
-
- DEBUG(3,("process_workgroup_announce: from %s<%02x> IP %s to \
-%s for workgroup %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
- nmb_namestr(&dgram->dest_name),workgroup_announce_name));
-
- DEBUG(5,("process_workgroup_announce: ttl=%d server type=%08x master browser=%s\n",
- ttl, servertype, master_name));
-
- /* Workgroup announcements must only go to the MSBROWSE name. */
- if (!strequal(dgram->dest_name.name, MSBROWSE) || (dgram->dest_name.name_type != 0x1))
- {
- DEBUG(0,("process_workgroup_announce: from IP %s should be to __MSBROWSE__<0x01> not %s\n",
- inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));
- goto done;
- }
-
- if ((work = find_workgroup_on_subnet(subrec, workgroup_announce_name))==NULL)
- {
- /* We have no record of this workgroup. Add it. */
- if((work = create_workgroup_on_subnet(subrec, workgroup_announce_name, ttl))==NULL)
- goto done;
- }
- else
- {
- /* Update the workgroup death_time. */
- update_workgroup_ttl(work, ttl);
- }
-
- if(*work->local_master_browser_name == '\0')
- {
- /* Set the master browser name. */
- set_workgroup_local_master_browser_name( work, master_name );
- }
-
- subrec->work_changed = True;
-done:
- END_PROFILE(workgroup_announce);
-}
-
-/*******************************************************************
- Process an incoming local master browser announcement packet.
-*******************************************************************/
-
-void process_local_master_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int ttl = IVAL(buf,1)/1000;
- char *server_name = buf+5;
- uint32 servertype = IVAL(buf,23);
- char *comment = buf+31;
- char *work_name;
- struct work_record *work;
- struct server_record *servrec;
- char *source_name = dgram->source_name.name;
-
- START_PROFILE(local_master_announce);
- comment[43] = 0;
-
- DEBUG(3,("process_local_master_announce: from %s<%02x> IP %s to \
-%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
- nmb_namestr(&dgram->dest_name),server_name));
-
- DEBUG(5,("process_local_master_announce: ttl=%d server type=%08x comment=%s\n",
- ttl, servertype, comment));
-
- /* A local master announcement must be sent to the name WORKGROUP<1e>. */
- if(dgram->dest_name.name_type != 0x1e)
- {
- DEBUG(0,("process_local_master_announce: incorrect name type for destination from IP %s \
-(was %02x) should be 0x1e. Ignoring packet.\n",
- inet_ntoa(p->ip), dgram->dest_name.name_type));
- goto done;
- }
-
- /* Filter servertype to remove impossible bits. */
- servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
-
- /* For a local master announce the workgroup name is the destination name. */
- work_name = dgram->dest_name.name;
-
- if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL)
- {
- /* Don't bother adding if it's a local master release announce. */
- if(servertype == 0)
- goto done;
-
- /* We have no record of this workgroup. Add it. */
- if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
- goto done;
- }
-
- /* If we think we're the local master browser for this workgroup,
- we should never have got this packet. We don't see our own
- packets.
- */
- if(AM_LOCAL_MASTER_BROWSER(work))
- {
- DEBUG(0,("process_local_master_announce: Server %s at IP %s is announcing itself as \
-a local master browser for workgroup %s and we think we are master. Forcing election.\n",
- server_name, inet_ntoa(p->ip), work_name));
-
- /* Samba nmbd versions 1.9.17 to 1.9.17p4 have a bug in that when
- they have become a local master browser once, they will never
- stop sending local master announcements. To fix this we send
- them a reset browser packet, with level 0x2 on the __SAMBA__
- name that only they should be listening to. */
-
- send_browser_reset( 0x2, "__SAMBA__" , 0x20, p->ip);
-
- /* We should demote ourself and force an election. */
-
- unbecome_local_master_browser( subrec, work, True);
-
- /* The actual election requests are handled in
- nmbd_election.c */
- goto done;
- }
-
- /* Find the server record on this workgroup. If it doesn't exist, add it. */
-
- if(servertype != 0)
- {
- if((servrec = find_server_in_workgroup( work, server_name))==NULL)
- {
- /* If this server is not already in the workgroup, add it. */
- create_server_on_workgroup(work, server_name,
- servertype|SV_TYPE_LOCAL_LIST_ONLY,
- ttl, comment);
- }
- else
- {
- /* Update the record. */
- servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
- update_server_ttl(servrec, ttl);
- StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1);
- }
-
- set_workgroup_local_master_browser_name( work, server_name );
- }
- else
- {
- /*
- * This server is announcing it is going down. Remove it from the
- * workgroup.
- */
- if(!is_myname(server_name) && (work != NULL) &&
- ((servrec = find_server_in_workgroup( work, server_name))!=NULL)
- )
- {
- remove_server_from_workgroup( work, servrec);
- }
- }
-
- subrec->work_changed = True;
-done:
- END_PROFILE(local_master_announce);
-}
-
-/*******************************************************************
- Process a domain master announcement frame.
- Domain master browsers receive these from local masters. The Domain
- master should then issue a sync with the local master, asking for
- that machines local server list.
-******************************************************************/
-
-void process_master_browser_announce(struct subnet_record *subrec,
- struct packet_struct *p,char *buf)
-{
- char *local_master_name = buf;
- struct work_record *work;
- struct browse_cache_record *browrec;
-
- START_PROFILE(master_browser_announce);
- local_master_name[15] = 0;
-
- DEBUG(3,("process_master_browser_announce: Local master announce from %s IP %s.\n",
- local_master_name, inet_ntoa(p->ip)));
-
- if (!lp_domain_master())
- {
- DEBUG(0,("process_master_browser_announce: Not configured as domain \
-master - ignoring master announce.\n"));
- goto done;
- }
-
- if((work = find_workgroup_on_subnet(subrec, lp_workgroup())) == NULL)
- {
- DEBUG(0,("process_master_browser_announce: Cannot find workgroup %s on subnet %s\n",
- lp_workgroup(), subrec->subnet_name));
- goto done;
- }
-
- if(!AM_DOMAIN_MASTER_BROWSER(work))
- {
- DEBUG(0,("process_master_browser_announce: Local master announce made to us from \
-%s IP %s and we are not a domain master browser.\n", local_master_name, inet_ntoa(p->ip)));
- goto done;
- }
-
- /* Add this host as a local master browser entry on the browse lists.
- This causes a sync request to be made to it at a later date.
- */
-
- if((browrec = find_browser_in_lmb_cache( local_master_name )) == NULL)
- {
- /* Add it. */
- create_browser_in_lmb_cache( work->work_group, local_master_name, p->ip);
- }
- else
- update_browser_death_time(browrec);
-done:
- END_PROFILE(master_browser_announce);
-}
-
-/*******************************************************************
- Process an incoming LanMan host announcement packet.
-*******************************************************************/
-
-void process_lm_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- uint32 servertype = IVAL(buf,1);
- int osmajor=CVAL(buf,5); /* major version of node software */
- int osminor=CVAL(buf,6); /* minor version of node software */
- int ttl = SVAL(buf,7);
- char *announce_name = buf+9;
- struct work_record *work;
- struct server_record *servrec;
- const char *work_name;
- char *source_name = dgram->source_name.name;
- pstring comment;
- char *s = buf+9;
-
- START_PROFILE(lm_host_announce);
- s = skip_string(s,1);
- StrnCpy(comment, s, 43);
-
- DEBUG(3,("process_lm_host_announce: LM Announcement from %s<%02x> IP %s to \
-%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
- nmb_namestr(&dgram->dest_name),announce_name));
-
- DEBUG(5,("process_lm_host_announce: os=(%d,%d) ttl=%d server type=%08x comment=%s\n",
- osmajor, osminor, ttl, servertype,comment));
-
- if ((osmajor < 36) || (osmajor > 38) || (osminor !=0))
- {
- DEBUG(5,("process_lm_host_announce: LM Announcement packet does not \
-originate from OS/2 Warp client. Ignoring packet.\n"));
- /* Could have been from a Windows machine (with its LM Announce enabled),
- or a Samba server. Then don't disrupt the current browse list. */
- goto done;
- }
-
- /* Filter servertype to remove impossible bits. */
- servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
-
- /* A LanMan host announcement must be sent to the name WORKGROUP<00>. */
- if(dgram->dest_name.name_type != 0x00)
- {
- DEBUG(2,("process_lm_host_announce: incorrect name type for destination from IP %s \
-(was %02x) should be 0x00. Allowing packet anyway.\n",
- inet_ntoa(p->ip), dgram->dest_name.name_type));
- /* Change it so it was. */
- dgram->dest_name.name_type = 0x00;
- }
-
- /* For a LanMan host announce the workgroup name is the destination name. */
- work_name = dgram->dest_name.name;
-
- /*
- * Syntax servers version 5.1 send HostAnnounce packets to
- * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>
- * instead of WORKGROUP<1d> name. So to fix this we check if
- * the workgroup name is our own name, and if so change it
- * to be our primary workgroup name. This code is probably
- * not needed in the LanMan announce code, but it won't hurt.
- */
-
- if(strequal(work_name, lp_netbios_name()))
- work_name = lp_workgroup();
-
- /*
- * We are being very agressive here in adding a workgroup
- * name on the basis of a host announcing itself as being
- * in that workgroup. Maybe we should wait for the workgroup
- * announce instead ? JRA.
- */
-
- work = find_workgroup_on_subnet(subrec, work_name);
-
- if(servertype != 0)
- {
- if (work == NULL)
- {
- /* We have no record of this workgroup. Add it. */
- if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
- goto done;
- }
-
- if((servrec = find_server_in_workgroup( work, announce_name))==NULL)
- {
- /* If this server is not already in the workgroup, add it. */
- create_server_on_workgroup(work, announce_name,
- servertype|SV_TYPE_LOCAL_LIST_ONLY,
- ttl, comment);
- }
- else
- {
- /* Update the record. */
- servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
- update_server_ttl( servrec, ttl);
- StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1);
- }
- }
- else
- {
- /*
- * This server is announcing it is going down. Remove it from the
- * workgroup.
- */
- if(!is_myname(announce_name) && (work != NULL) &&
- ((servrec = find_server_in_workgroup( work, announce_name))!=NULL)
- )
- {
- remove_server_from_workgroup( work, servrec);
- }
- }
-
- subrec->work_changed = True;
- found_lm_clients = True;
-done:
- END_PROFILE(lm_host_announce);
-}
-
-/****************************************************************************
- Send a backup list response.
-*****************************************************************************/
-static void send_backup_list_response(struct subnet_record *subrec,
- struct work_record *work,
- struct nmb_name *send_to_name,
- unsigned char max_number_requested,
- uint32 token, struct in_addr sendto_ip,
- int port)
-{
- char outbuf[1024];
- char *p, *countptr;
- unsigned int count = 0;
-#if 0
- struct server_record *servrec;
-#endif
-
- memset(outbuf,'\0',sizeof(outbuf));
-
- DEBUG(3,("send_backup_list_response: sending backup list for workgroup %s to %s IP %s\n",
- work->work_group, nmb_namestr(send_to_name), inet_ntoa(sendto_ip)));
-
- p = outbuf;
-
- SCVAL(p,0,ANN_GetBackupListResp); /* Backup list response opcode. */
- p++;
-
- countptr = p;
- p++;
-
- SIVAL(p,0,token); /* The sender's unique info. */
- p += 4;
-
- /* We always return at least one name - our own. */
- count = 1;
- StrnCpy(p,lp_netbios_name(),15);
- strupper(p);
- p = skip_string(p,1);
-
- /* Look for backup browsers in this workgroup. */
-
-#if 0
- /* we don't currently send become_backup requests so we should never
- send any other servers names out as backups for our
- workgroup. That's why this is commented out (tridge) */
-
- /*
- * NB. Note that the struct work_record here is not neccessarily
- * attached to the subnet *subrec.
- */
-
- for (servrec = work->serverlist; servrec; servrec = servrec->next)
- {
- int len = PTR_DIFF(p, outbuf);
- if((sizeof(outbuf) - len) < 16)
- break;
-
- if(count >= (unsigned int)max_number_requested)
- break;
-
- if(strnequal(servrec->serv.name, lp_netbios_name(),15))
- continue;
-
- if(!(servrec->serv.type & SV_TYPE_BACKUP_BROWSER))
- continue;
-
- StrnCpy(p, servrec->serv.name, 15);
- strupper(p);
- count++;
-
- DEBUG(5,("send_backup_list_response: Adding server %s number %d\n",
- p, count));
-
- p = skip_string(p,1);
- }
-#endif
-
- SCVAL(countptr, 0, count);
-
- DEBUG(4,("send_backup_list_response: sending response to %s<00> IP %s with %d servers.\n",
- send_to_name->name, inet_ntoa(sendto_ip), count));
-
- send_mailslot(True, BROWSE_MAILSLOT,
- outbuf,PTR_DIFF(p,outbuf),
- lp_netbios_name(), 0,
- send_to_name->name,0,
- sendto_ip, subrec->myip, port);
-}
-
-/*******************************************************************
- Process a send backup list request packet.
-
- A client sends a backup list request to ask for a list of servers on
- the net that maintain server lists for a domain. A server is then
- chosen from this list to send NetServerEnum commands to to list
- available servers.
-
-********************************************************************/
-
-void process_get_backup_list_request(struct subnet_record *subrec,
- struct packet_struct *p,char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- struct work_record *work;
- unsigned char max_number_requested = CVAL(buf,0);
- uint32 token = IVAL(buf,1); /* Sender's key index for the workgroup. */
- int name_type = dgram->dest_name.name_type;
- char *workgroup_name = dgram->dest_name.name;
- struct subnet_record *search_subrec = subrec;
-
- START_PROFILE(get_backup_list);
- DEBUG(3,("process_get_backup_list_request: request from %s IP %s to %s.\n",
- nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
- nmb_namestr(&dgram->dest_name)));
-
- /* We have to be a master browser, or a domain master browser
- for the requested workgroup. That means it must be our
- workgroup. */
-
- if(strequal(workgroup_name, lp_workgroup()) == False)
- {
- DEBUG(7,("process_get_backup_list_request: Ignoring announce request for workgroup %s.\n",
- workgroup_name));
- goto done;
- }
-
- if((work = find_workgroup_on_subnet(search_subrec, workgroup_name)) == NULL)
- {
- DEBUG(0,("process_get_backup_list_request: Cannot find workgroup %s on \
-subnet %s.\n", workgroup_name, search_subrec->subnet_name));
- goto done;
- }
-
- /*
- * If the packet was sent to WORKGROUP<1b> instead
- * of WORKGROUP<1d> then it was unicast to us a domain master
- * browser. Change search subrec to unicast.
- */
-
- if(name_type == 0x1b)
- {
- /* We must be a domain master browser in order to
- process this packet. */
-
- if(!AM_DOMAIN_MASTER_BROWSER(work))
- {
- DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \
-and I am not a domain master browser.\n", workgroup_name));
- goto done;
- }
-
- search_subrec = unicast_subnet;
- }
- else if (name_type == 0x1d)
- {
- /* We must be a local master browser in order to
- process this packet. */
-
- if(!AM_LOCAL_MASTER_BROWSER(work))
- {
- DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \
-and I am not a local master browser.\n", workgroup_name));
- goto done;
- }
- }
- else
- {
- DEBUG(0,("process_get_backup_list_request: Invalid name type %x - should be 0x1b or 0x1d.\n",
- name_type));
- goto done;
- }
-
- send_backup_list_response(subrec, work, &dgram->source_name,
- max_number_requested, token, p->ip, p->port);
-done:
- END_PROFILE(get_backup_list);
-}
-
-/*******************************************************************
- Process a reset browser state packet.
-
- Diagnostic packet:
- 0x1 - Stop being a master browser and become a backup browser.
- 0x2 - Discard browse lists, stop being a master browser, try again.
- 0x4 - Stop being a master browser forever.
-
-******************************************************************/
-
-void process_reset_browser(struct subnet_record *subrec,
- struct packet_struct *p,char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int state = CVAL(buf,0);
- struct subnet_record *sr;
-
- START_PROFILE(reset_browser);
- DEBUG(1,("process_reset_browser: received diagnostic browser reset \
-request from %s IP %s state=0x%X\n",
- nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), state));
-
- /* Stop being a local master browser on all our broadcast subnets. */
- if (state & 0x1)
- {
- for (sr = FIRST_SUBNET; sr; sr = NEXT_SUBNET_EXCLUDING_UNICAST(sr))
- {
- struct work_record *work;
- for (work = sr->workgrouplist; work; work = work->next)
- {
- if (AM_LOCAL_MASTER_BROWSER(work))
- unbecome_local_master_browser(sr, work, True);
- }
- }
- }
-
- /* Discard our browse lists. */
- if (state & 0x2)
- {
- /*
- * Calling expire_workgroups_and_servers with a -1
- * time causes all servers not marked with a PERMANENT_TTL
- * on the workgroup lists to be discarded, and all
- * workgroups with empty server lists to be discarded.
- * This means we keep our own server names and workgroup
- * as these have a PERMANENT_TTL.
- */
-
- expire_workgroups_and_servers(-1);
- }
-
- /* Request to stop browsing altogether. */
- if (state & 0x4)
- DEBUG(1,("process_reset_browser: ignoring request to stop being a browser.\n"));
-
- END_PROFILE(reset_browser);
-}
-
-/*******************************************************************
- Process an announcement request packet.
- We don't respond immediately, we just check it's a request for
- our workgroup and then set the flag telling the announce code
- in nmbd_sendannounce.c:announce_my_server_names that an
- announcement is needed soon.
-******************************************************************/
-
-void process_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- struct work_record *work;
- char *workgroup_name = dgram->dest_name.name;
-
- START_PROFILE(announce_request);
- DEBUG(3,("process_announce_request: Announce request from %s IP %s to %s.\n",
- nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
- nmb_namestr(&dgram->dest_name)));
-
- /* We only send announcement requests on our workgroup. */
- if(strequal(workgroup_name, lp_workgroup()) == False)
- {
- DEBUG(7,("process_announce_request: Ignoring announce request for workgroup %s.\n",
- workgroup_name));
- goto done;
- }
-
- if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL)
- {
- DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",
- workgroup_name));
- goto done;
- }
-
- work->needannounce = True;
-done:
- END_PROFILE(lm_host_announce);
-}
-
-/*******************************************************************
- Process a LanMan announcement request packet.
- We don't respond immediately, we just check it's a request for
- our workgroup and then set the flag telling that we have found
- a LanMan client (DOS or OS/2) and that we will have to start
- sending LanMan announcements (unless specifically disabled
- through the "lm announce" parameter in smb.conf)
-******************************************************************/
-
-void process_lm_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- char *workgroup_name = dgram->dest_name.name;
-
- START_PROFILE(lm_announce_request);
- DEBUG(3,("process_lm_announce_request: Announce request from %s IP %s to %s.\n",
- nmb_namestr(&dgram->source_name), inet_ntoa(p->ip),
- nmb_namestr(&dgram->dest_name)));
-
- /* We only send announcement requests on our workgroup. */
- if(strequal(workgroup_name, lp_workgroup()) == False)
- {
- DEBUG(7,("process_lm_announce_request: Ignoring announce request for workgroup %s.\n",
- workgroup_name));
- goto done;
- }
-
- if(find_workgroup_on_subnet(subrec, workgroup_name) == NULL)
- {
- DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",
- workgroup_name));
- goto done;
- }
-
- found_lm_clients = True;
-done:
- END_PROFILE(lm_host_announce);
-}
diff --git a/source4/nmbd/nmbd_incomingrequests.c b/source4/nmbd/nmbd_incomingrequests.c
deleted file mode 100644
index 916f7763f2..0000000000
--- a/source4/nmbd/nmbd_incomingrequests.c
+++ /dev/null
@@ -1,596 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- This file contains all the code to process NetBIOS requests coming
- in on port 137. It does not deal with the code needed to service
- WINS server requests, but only broadcast and unicast requests.
-
-*/
-
-#include "includes.h"
-
-/****************************************************************************
-Send a name release response.
-**************************************************************************/
-
-static void send_name_release_response(int rcode, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- char rdata[6];
-
- memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- NMB_REL, /* nmbd type code. */
- NMB_NAME_RELEASE_OPCODE, /* opcode. */
- 0, /* ttl. */
- rdata, /* data to send. */
- 6); /* data length. */
-}
-
-/****************************************************************************
-Process a name release packet on a broadcast subnet.
-Ignore it if it's not one of our names.
-****************************************************************************/
-
-void process_name_release_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct in_addr owner_ip;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- BOOL group = (nb_flags & NB_GROUP) ? True : False;
- struct name_record *namerec;
- int rcode = 0;
-
- putip((char *)&owner_ip,&nmb->additional->rdata[2]);
-
- if(!bcast)
- {
- /* We should only get broadcast name release packets here.
- Anyone trying to release unicast should be going to a WINS
- server. If the code gets here, then either we are not a wins
- server and they sent it anyway, or we are a WINS server and
- the request was malformed. Either way, log an error here.
- and send an error reply back.
- */
- DEBUG(0,("process_name_release_request: unicast name release request \
-received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
- nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name));
-
- send_name_release_response(FMT_ERR, p);
- return;
- }
-
- DEBUG(3,("process_name_release_request: Name release on name %s, \
-subnet %s from owner IP %s\n",
- nmb_namestr(&nmb->question.question_name),
- subrec->subnet_name, inet_ntoa(owner_ip)));
-
- /* If someone is releasing a broadcast group name, just ignore it. */
- if( group && !ismyip(owner_ip) )
- return;
-
- /*
- * Code to work around a bug in FTP OnNet software NBT implementation.
- * They do a broadcast name release for WORKGROUP<0> and WORKGROUP<1e>
- * names and *don't set the group bit* !!!!!
- */
-
- if( !group && !ismyip(owner_ip) && strequal(question->name, lp_workgroup()) &&
- ((question->name_type == 0x0) || (question->name_type == 0x1e)))
- {
- DEBUG(6,("process_name_release_request: FTP OnNet bug workaround. Ignoring \
-group release name %s from IP %s on subnet %s with no group bit set.\n",
- nmb_namestr(question), inet_ntoa(owner_ip), subrec->subnet_name ));
- return;
- }
-
- namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_ANY_NAME);
-
- /* We only care about someone trying to release one of our names. */
- if( namerec
- && ( (namerec->data.source == SELF_NAME)
- || (namerec->data.source == PERMANENT_NAME) ) )
- {
- rcode = ACT_ERR;
- DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \
-on subnet %s being rejected as it is one of our names.\n",
- nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name));
- }
-
- if(rcode == 0)
- return;
-
- /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
- send_name_release_response(rcode, p);
-}
-
-/****************************************************************************
-Send a name registration response.
-**************************************************************************/
-
-static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- char rdata[6];
-
- memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- NMB_REG, /* nmbd type code. */
- NMB_NAME_REG_OPCODE, /* opcode. */
- ttl, /* ttl. */
- rdata, /* data to send. */
- 6); /* data length. */
-}
-
-/****************************************************************************
-Process a name refresh request on a broadcast subnet.
-**************************************************************************/
-
-void process_name_refresh_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
-
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- struct in_addr from_ip;
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
-
- if(!bcast)
- {
- /* We should only get broadcast name refresh packets here.
- Anyone trying to refresh unicast should be going to a WINS
- server. If the code gets here, then either we are not a wins
- server and they sent it anyway, or we are a WINS server and
- the request was malformed. Either way, log an error here.
- and send an error reply back.
- */
- DEBUG(0,("process_name_refresh_request: unicast name registration request \
-received for name %s from IP %s on subnet %s.\n",
- nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
- DEBUG(0,("Error - should be sent to WINS server\n"));
-
- send_name_registration_response(FMT_ERR, 0, p);
- return;
- }
-
- /* Just log a message. We really don't care about broadcast name
- refreshes. */
-
- DEBUG(3,("process_name_refresh_request: Name refresh for name %s \
-IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
-
-}
-
-/****************************************************************************
-Process a name registration request on a broadcast subnet.
-**************************************************************************/
-
-void process_name_registration_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- BOOL group = (nb_flags & NB_GROUP) ? True : False;
- struct name_record *namerec = NULL;
- int ttl = nmb->additional->ttl;
- struct in_addr from_ip;
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
-
- if(!bcast)
- {
- /* We should only get broadcast name registration packets here.
- Anyone trying to register unicast should be going to a WINS
- server. If the code gets here, then either we are not a wins
- server and they sent it anyway, or we are a WINS server and
- the request was malformed. Either way, log an error here.
- and send an error reply back.
- */
- DEBUG(0,("process_name_registration_request: unicast name registration request \
-received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
- nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
-
- send_name_registration_response(FMT_ERR, 0, p);
- return;
- }
-
- DEBUG(3,("process_name_registration_request: Name registration for name %s \
-IP %s on subnet %s\n", nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
-
- /* See if the name already exists. */
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- /*
- * If the name being registered exists and is a WINS_PROXY_NAME
- * then delete the WINS proxy name entry so we don't reply erroneously
- * later to queries.
- */
-
- if((namerec != NULL) && (namerec->data.source == WINS_PROXY_NAME))
- {
- remove_name_from_namelist( subrec, namerec );
- namerec = NULL;
- }
-
- if (!group)
- {
- /* Unique name. */
-
- if( (namerec != NULL)
- && ( (namerec->data.source == SELF_NAME)
- || (namerec->data.source == PERMANENT_NAME)
- || NAME_GROUP(namerec) ) )
- {
- /* No-one can register one of Samba's names, nor can they
- register a name that's a group name as a unique name */
-
- send_name_registration_response(ACT_ERR, 0, p);
- return;
- }
- else if(namerec != NULL)
- {
- /* Update the namelist record with the new information. */
- namerec->data.ip[0] = from_ip;
- update_name_ttl(namerec, ttl);
-
- DEBUG(3,("process_name_registration_request: Updated name record %s \
-with IP %s on subnet %s\n",nmb_namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name));
- return;
- }
- }
- else
- {
- /* Group name. */
-
- if( (namerec != NULL)
- && !NAME_GROUP(namerec)
- && ( (namerec->data.source == SELF_NAME)
- || (namerec->data.source == PERMANENT_NAME) ) )
- {
- /* Disallow group names when we have a unique name. */
- send_name_registration_response(ACT_ERR, 0, p);
- return;
- }
- }
-}
-
-/****************************************************************************
-This is used to sort names for a name status into a sensible order.
-We put our own names first, then in alphabetical order.
-**************************************************************************/
-
-static int status_compare(char *n1,char *n2)
-{
- int l1,l2,l3;
-
- /* It's a bit tricky because the names are space padded */
- for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ;
- for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ;
- l3 = strlen(lp_netbios_name());
-
- if ((l1==l3) && strncmp(n1,lp_netbios_name(),l3) == 0 &&
- (l2!=l3 || strncmp(n2,lp_netbios_name(),l3) != 0))
- return -1;
-
- if ((l2==l3) && strncmp(n2,lp_netbios_name(),l3) == 0 &&
- (l1!=l3 || strncmp(n1,lp_netbios_name(),l3) != 0))
- return 1;
-
- return memcmp(n1,n2,18);
-}
-
-
-/****************************************************************************
- Process a node status query
- ****************************************************************************/
-
-void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- char *qname = nmb->question.question_name.name;
- int ques_type = nmb->question.question_name.name_type;
- char rdata[MAX_DGRAM_SIZE];
- char *countptr, *buf, *bufend, *buf0;
- int names_added,i;
- struct name_record *namerec;
-
- DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \
-subnet %s.\n", nmb_namestr(&nmb->question.question_name), inet_ntoa(p->ip),
- subrec->subnet_name));
-
- if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name,
- FIND_SELF_NAME)) == 0)
- {
- DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \
-subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
- inet_ntoa(p->ip), subrec->subnet_name));
-
- return;
- }
-
- /* this is not an exact calculation. the 46 is for the stats buffer
- and the 60 is to leave room for the header etc */
- bufend = &rdata[MAX_DGRAM_SIZE] - (18 + 46 + 60);
- countptr = buf = rdata;
- buf += 1;
- buf0 = buf;
-
- names_added = 0;
-
- namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
-
- while (buf < bufend)
- {
- if( (namerec->data.source == SELF_NAME)
- || (namerec->data.source == PERMANENT_NAME) )
- {
- int name_type = namerec->name.name_type;
-
- if (!strequal(namerec->name.name,"*") &&
- !strequal(namerec->name.name,"__SAMBA__") &&
- (name_type < 0x1b || name_type >= 0x20 ||
- ques_type < 0x1b || ques_type >= 0x20 ||
- strequal(qname, namerec->name.name)))
- {
- /* Start with the name. */
- memset(buf,'\0',18);
- slprintf(buf, 17, "%-15.15s",namerec->name.name);
- strupper(buf);
-
- /* Put the name type and netbios flags in the buffer. */
- buf[15] = name_type;
- set_nb_flags( &buf[16],namerec->data.nb_flags );
- buf[16] |= NB_ACTIVE; /* all our names are active */
-
- buf += 18;
-
- names_added++;
- }
- }
-
- /* Remove duplicate names. */
- if (names_added > 1) {
- qsort( buf0, names_added, 18, QSORT_CAST status_compare );
- }
-
- for( i=1; i < names_added ; i++ )
- {
- if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0)
- {
- names_added--;
- if (names_added == i)
- break;
- memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
- i--;
- }
- }
-
- buf = buf0 + 18*names_added;
-
- namerec = (struct name_record *)ubi_trNext( namerec );
-
- if (!namerec)
- {
- /* End of the subnet specific name list. Now
- add the names on the unicast subnet . */
- struct subnet_record *uni_subrec = unicast_subnet;
-
- if (uni_subrec != subrec)
- {
- subrec = uni_subrec;
- namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
- }
- }
- if (!namerec)
- break;
-
- }
-
- SCVAL(countptr,0,names_added);
-
- /* We don't send any stats as they could be used to attack
- the protocol. */
- memset(buf,'\0',46);
-
- buf += 46;
-
- /* Send a NODE STATUS RESPONSE */
- reply_netbios_packet(p, /* Packet to reply to. */
- 0, /* Result code. */
- NMB_STATUS, /* nmbd type code. */
- NMB_NAME_QUERY_OPCODE, /* opcode. */
- 0, /* ttl. */
- rdata, /* data to send. */
- PTR_DIFF(buf,rdata)); /* data length. */
-}
-
-
-/***************************************************************************
-Process a name query.
-
-For broadcast name queries:
-
- - Only reply if the query is for one of YOUR names.
- - NEVER send a negative response to a broadcast query.
-
-****************************************************************************/
-
-void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- int name_type = question->name_type;
- BOOL bcast = nmb->header.nm_flags.bcast;
- int ttl=0;
- int rcode = 0;
- char *prdata = NULL;
- char rdata[6];
- BOOL success = False;
- struct name_record *namerec = NULL;
- int reply_data_len = 0;
- int i;
-
- DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n",
- inet_ntoa(p->ip), subrec->subnet_name, nmb_namestr(question)));
-
- /* Look up the name in the cache - if the request is a broadcast request that
- came from a subnet we don't know about then search all the broadcast subnets
- for a match (as we don't know what interface the request came in on). */
-
- if(subrec == remote_broadcast_subnet)
- namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME);
- else
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- /* Check if it is a name that expired */
- if (namerec &&
- ((namerec->data.death_time != PERMANENT_TTL) &&
- (namerec->data.death_time < p->timestamp))) {
- DEBUG(5,("process_name_query_request: expired name %s\n", nmb_namestr(&namerec->name)));
- namerec = NULL;
- }
-
- if (namerec) {
- /*
- * Always respond to unicast queries.
- * Don't respond to broadcast queries unless the query is for
- * a name we own, a Primary Domain Controller name, or a WINS_PROXY
- * name with type 0 or 0x20. WINS_PROXY names are only ever added
- * into the namelist if we were configured as a WINS proxy.
- */
-
- if (!bcast ||
- (bcast && ((name_type == 0x1b) ||
- (namerec->data.source == SELF_NAME) ||
- (namerec->data.source == PERMANENT_NAME) ||
- ((namerec->data.source == WINS_PROXY_NAME) &&
- ((name_type == 0) || (name_type == 0x20)))))) {
- /* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY,
- or it's a Domain Master type. */
-
- /*
- * If this is a WINS_PROXY_NAME, then ceck that none of the IP
- * addresses we are returning is on the same broadcast subnet
- * as the requesting packet. If it is then don't reply as the
- * actual machine will be replying also and we don't want two
- * replies to a broadcast query.
- */
-
- if (namerec->data.source == WINS_PROXY_NAME) {
- for( i = 0; i < namerec->data.num_ips; i++) {
- if (same_net(namerec->data.ip[i], subrec->myip, subrec->mask_ip)) {
- DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also on the same subnet (%s) as the requestor. Not replying.\n",
- nmb_namestr(&namerec->name), subrec->subnet_name ));
- return;
- }
- }
- }
-
- ttl = (namerec->data.death_time != PERMANENT_TTL) ?
- namerec->data.death_time - p->timestamp : lp_max_ttl();
-
- /* Copy all known ip addresses into the return data. */
- /* Optimise for the common case of one IP address so
- we don't need a malloc. */
-
- if (namerec->data.num_ips == 1) {
- prdata = rdata;
- } else {
- if ((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL) {
- DEBUG(0,("process_name_query_request: malloc fail !\n"));
- return;
- }
- }
-
- for (i = 0; i < namerec->data.num_ips; i++) {
- set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
- putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
- }
-
- sort_query_replies(prdata, i, p->ip);
-
- reply_data_len = namerec->data.num_ips * 6;
- success = True;
- }
- }
-
- /*
- * If a machine is broadcasting a name lookup request and we have lp_wins_proxy()
- * set we should initiate a WINS query here. On success we add the resolved name
- * into our namelist with a type of WINS_PROXY_NAME and then reply to the query.
- */
-
- if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() &&
- bcast && (subrec != remote_broadcast_subnet)) {
- make_wins_proxy_name_query_request( subrec, p, question );
- return;
- }
-
- if (!success && bcast) {
- if(prdata != rdata)
- SAFE_FREE(prdata);
- return; /* Never reply with a negative response to broadcasts. */
- }
-
- /*
- * Final check. From observation, if a unicast packet is sent
- * to a non-WINS server with the recursion desired bit set
- * then never send a negative response.
- */
-
- if(!success && !bcast && nmb->header.nm_flags.recursion_desired) {
- if(prdata != rdata)
- SAFE_FREE(prdata);
- return;
- }
-
- if (success) {
- rcode = 0;
- DEBUG(3,("OK\n"));
- } else {
- rcode = NAM_ERR;
- DEBUG(3,("UNKNOWN\n"));
- }
-
- /* See rfc1002.txt 4.2.13. */
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- NMB_QUERY, /* nmbd type code. */
- NMB_NAME_QUERY_OPCODE, /* opcode. */
- ttl, /* ttl. */
- prdata, /* data to send. */
- reply_data_len); /* data length. */
-
- if(prdata != rdata)
- SAFE_FREE(prdata);
-}
diff --git a/source4/nmbd/nmbd_lmhosts.c b/source4/nmbd/nmbd_lmhosts.c
deleted file mode 100644
index c47384c819..0000000000
--- a/source4/nmbd/nmbd_lmhosts.c
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Revision History:
-
- Handle lmhosts file reading.
-
-*/
-
-#include "includes.h"
-
-/****************************************************************************
-Load a lmhosts file.
-****************************************************************************/
-void load_lmhosts_file(char *fname)
-{
- char *name;
- int name_type;
- struct in_addr ipaddr;
- XFILE *fp = startlmhosts( fname );
- TALLOC_CTX *mem_ctx;
-
- if (!fp) {
- DEBUG(2,("load_lmhosts_file: Can't open lmhosts file %s. Error was %s\n",
- fname, strerror(errno)));
- return;
- }
- mem_ctx = talloc_init("load_lmhosts_files");
- if (!mem_ctx) {
- DEBUG(2,("load_lmhosts_file: No memory to open lmhosts file %s. Error was %s\n",
- fname, strerror(errno)));
- return;
- }
- while (getlmhostsent(mem_ctx, fp, name, &name_type, &ipaddr) )
- {
- struct subnet_record *subrec = NULL;
- enum name_source source = LMHOSTS_NAME;
-
- /* We find a relevent subnet to put this entry on, then add it. */
- /* Go through all the broadcast subnets and see if the mask matches. */
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- if(same_net(ipaddr, subrec->bcast_ip, subrec->mask_ip))
- break;
- }
-
- /* If none match add the name to the remote_broadcast_subnet. */
- if(subrec == NULL)
- subrec = remote_broadcast_subnet;
-
- if(name_type == -1)
- {
- /* Add the (0) and (0x20) names directly into the namelist for this subnet. */
- (void)add_name_to_subnet(subrec,name,0x00,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
- (void)add_name_to_subnet(subrec,name,0x20,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
- }
- else
- {
- /* Add the given name type to the subnet namelist. */
- (void)add_name_to_subnet(subrec,name,name_type,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
- }
- }
-
- endlmhosts(fp);
-}
-
-/****************************************************************************
- Find a name read from the lmhosts file. We secretly check the names on
- the remote_broadcast_subnet as if the name was added to a regular broadcast
- subnet it will be found by normal name query processing.
-****************************************************************************/
-
-BOOL find_name_in_lmhosts(struct nmb_name *nmbname, struct name_record **namerecp)
-{
- struct name_record *namerec;
-
- *namerecp = NULL;
-
- if((namerec = find_name_on_subnet(remote_broadcast_subnet, nmbname,
- FIND_ANY_NAME))==NULL)
- return False;
-
- if(!NAME_IS_ACTIVE(namerec) || (namerec->data.source != LMHOSTS_NAME))
- return False;
-
- *namerecp = namerec;
- return True;
-}
diff --git a/source4/nmbd/nmbd_logonnames.c b/source4/nmbd/nmbd_logonnames.c
deleted file mode 100644
index 40edc68800..0000000000
--- a/source4/nmbd/nmbd_logonnames.c
+++ /dev/null
@@ -1,172 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-extern struct in_addr allones_ip;
-
-extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
-
-/****************************************************************************
- Fail to become a Logon server on a subnet.
- ****************************************************************************/
-static void become_logon_server_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *fail_name)
-{
- struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
- struct server_record *servrec;
-
- if(!work)
- {
- DEBUG(0,("become_logon_server_fail: Error - cannot find \
-workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
- return;
- }
-
- if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL)
- {
- DEBUG(0,("become_logon_server_fail: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- lp_netbios_name(), fail_name->name, subrec->subnet_name));
- work->log_state = LOGON_NONE;
- return;
- }
-
- /* Set the state back to LOGON_NONE. */
- work->log_state = LOGON_NONE;
-
- servrec->serv.type &= ~SV_TYPE_DOMAIN_CTRL;
-
- DEBUG(0,("become_logon_server_fail: Failed to become a domain master for \
-workgroup %s on subnet %s. Couldn't register name %s.\n",
- work->work_group, subrec->subnet_name, nmb_namestr(fail_name)));
-
-}
-
-/****************************************************************************
- Become a Logon server on a subnet.
- ****************************************************************************/
-
-static void become_logon_server_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *registered_name,
- uint16 nb_flags,
- int ttl, struct in_addr registered_ip)
-{
- struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
- struct server_record *servrec;
-
- if(!work)
- {
- DEBUG(0,("become_logon_server_success: Error - cannot find \
-workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
- return;
- }
-
- if((servrec = find_server_in_workgroup( work, lp_netbios_name())) == NULL)
- {
- DEBUG(0,("become_logon_server_success: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- lp_netbios_name(), registered_name->name, subrec->subnet_name));
- work->log_state = LOGON_NONE;
- return;
- }
-
- /* Set the state in the workgroup structure. */
- work->log_state = LOGON_SRV; /* Become domain master. */
-
- /* Update our server status. */
- servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER);
- /* To allow Win95 policies to load we need to set type domain
- controller.
- */
- servrec->serv.type |= SV_TYPE_DOMAIN_CTRL;
-
- /* Tell the namelist writer to write out a change. */
- subrec->work_changed = True;
-
- /*
- * Add the WORKGROUP<1C> name to the UNICAST subnet with the IP address
- * for this subnet so we will respond to queries on this name.
- */
- {
- struct nmb_name nmbname;
- make_nmb_name(&nmbname,lp_workgroup(),0x1c);
- insert_permanent_name_into_unicast(subrec, &nmbname, 0x1c);
- }
-
- DEBUG(0,("become_logon_server_success: Samba is now a logon server \
-for workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name));
-}
-
-/*******************************************************************
- Become a logon server by attempting to register the WORKGROUP<1c>
- group name.
-******************************************************************/
-
-static void become_logon_server(struct subnet_record *subrec,
- struct work_record *work)
-{
- DEBUG(2,("become_logon_server: Atempting to become logon server for workgroup %s \
-on subnet %s\n", work->work_group,subrec->subnet_name));
-
- DEBUG(3,("become_logon_server: go to first stage: register %s<1c> name\n",
- work->work_group));
- work->log_state = LOGON_WAIT;
-
- register_name(subrec, work->work_group,0x1c,samba_nb_type|NB_GROUP,
- become_logon_server_success,
- become_logon_server_fail, NULL);
-}
-
-/*****************************************************************************
- Add the internet group <1c> logon names by unicast and broadcast.
- ****************************************************************************/
-void add_logon_names(void)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup());
-
- if (work && (work->log_state == LOGON_NONE))
- {
- struct nmb_name nmbname;
- make_nmb_name(&nmbname,lp_workgroup(),0x1c);
-
- if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
- {
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "add_domain_logon_names:\n" );
- dbgtext( "Attempting to become logon server " );
- dbgtext( "for workgroup %s ", lp_workgroup() );
- dbgtext( "on subnet %s\n", subrec->subnet_name );
- }
- become_logon_server(subrec, work);
- }
- }
- }
-}
diff --git a/source4/nmbd/nmbd_mynames.c b/source4/nmbd/nmbd_mynames.c
deleted file mode 100644
index dd66821839..0000000000
--- a/source4/nmbd/nmbd_mynames.c
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
-
-/****************************************************************************
- Fail funtion when registering my netbios names.
- **************************************************************************/
-
-static void my_name_register_failed(struct subnet_record *subrec,
- struct response_record *rrec, struct nmb_name *nmbname)
-{
- DEBUG(0,("my_name_register_failed: Failed to register my name %s on subnet %s.\n",
- nmb_namestr(nmbname), subrec->subnet_name));
-}
-
-
-/****************************************************************************
- Add my workgroup and my given names to one subnet
- Also add the magic Samba names.
- **************************************************************************/
-void register_my_workgroup_one_subnet(struct subnet_record *subrec)
-{
- int i;
-
- struct work_record *work;
-
- /* Create the workgroup on the subnet. */
- if((work = create_workgroup_on_subnet(subrec, lp_workgroup(),
- PERMANENT_TTL)) == NULL) {
- DEBUG(0,("register_my_workgroup_and_names: Failed to create my workgroup %s on subnet %s. \
-Exiting.\n", lp_workgroup(), subrec->subnet_name));
- return;
- }
-
- /* Each subnet entry, except for the wins_server_subnet has
- the magic Samba names. */
- add_samba_names_to_subnet(subrec);
-
- /* Register all our names including aliases. */
- for (i=0; my_netbios_names(i); i++) {
- register_name(subrec, my_netbios_names(i),0x20,samba_nb_type,
- NULL,
- my_name_register_failed, NULL);
- register_name(subrec, my_netbios_names(i),0x03,samba_nb_type,
- NULL,
- my_name_register_failed, NULL);
- register_name(subrec, my_netbios_names(i),0x00,samba_nb_type,
- NULL,
- my_name_register_failed, NULL);
- }
-
- /* Initiate election processing, register the workgroup names etc. */
- initiate_myworkgroup_startup(subrec, work);
-}
-
-/*******************************************************************
- Utility function to add a name to the unicast subnet, or add in
- our IP address if it already exists.
-******************************************************************/
-
-static void insert_refresh_name_into_unicast( struct subnet_record *subrec,
- struct nmb_name *nmbname, uint16 nb_type )
-{
- struct name_record *namerec;
-
- if (!we_are_a_wins_client()) {
- insert_permanent_name_into_unicast(subrec, nmbname, nb_type);
- return;
- }
-
- if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL)
- {
- /* The name needs to be created on the unicast subnet. */
- (void)add_name_to_subnet( unicast_subnet, nmbname->name,
- nmbname->name_type, nb_type,
- MIN(lp_max_ttl(), MAX_REFRESH_TIME), SELF_NAME, 1, &subrec->myip);
- }
- else
- {
- /* The name already exists on the unicast subnet. Add our local
- IP for the given broadcast subnet to the name. */
- add_ip_to_name_record( namerec, subrec->myip);
- }
-}
-
-/****************************************************************************
- Add my workgroup and my given names to the subnet lists.
- Also add the magic Samba names.
- **************************************************************************/
-
-BOOL register_my_workgroup_and_names(void)
-{
- struct subnet_record *subrec;
- int i;
-
- for(subrec = FIRST_SUBNET;
- subrec;
- subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- register_my_workgroup_one_subnet(subrec);
- }
-
- /* We still need to add the magic Samba
- names and the netbios names to the unicast subnet directly. This is
- to allow unicast node status requests and queries to still work
- in a broadcast only environment. */
-
- add_samba_names_to_subnet(unicast_subnet);
-
- for (i=0; my_netbios_names(i); i++)
- {
- for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- /*
- * Ensure all the IP addresses are added if we are multihomed.
- */
- struct nmb_name nmbname;
-
- make_nmb_name(&nmbname, my_netbios_names(i),0x20);
- insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type);
-
- make_nmb_name(&nmbname, my_netbios_names(i),0x3);
- insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type);
-
- make_nmb_name(&nmbname, my_netbios_names(i),0x0);
- insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type);
- }
- }
-
- /*
- * Add the WORKGROUP<0> and WORKGROUP<1e> group names to the unicast subnet
- * also for the same reasons.
- */
-
- for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- /*
- * Ensure all the IP addresses are added if we are multihomed.
- */
- struct nmb_name nmbname;
-
- make_nmb_name(&nmbname, lp_workgroup(), 0x0);
- insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP);
-
- make_nmb_name(&nmbname, lp_workgroup(), 0x1e);
- insert_refresh_name_into_unicast(subrec, &nmbname, samba_nb_type|NB_GROUP);
- }
-
- /*
- * We need to add the Samba names to the remote broadcast subnet,
- * as NT 4.x does directed broadcast requests to the *<0x0> name.
- */
- add_samba_names_to_subnet(remote_broadcast_subnet);
-
- return True;
-}
-
-/****************************************************************************
- Remove all the names we registered.
-**************************************************************************/
-void release_wins_names(void)
-{
- struct subnet_record *subrec = unicast_subnet;
- struct name_record *namerec, *nextnamerec;
-
- for (namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
- namerec;
- namerec = nextnamerec) {
- nextnamerec = (struct name_record *)ubi_trNext( namerec );
- if( (namerec->data.source == SELF_NAME)
- && !NAME_IS_DEREGISTERING(namerec) )
- release_name( subrec, namerec, standard_success_release,
- NULL, NULL);
- }
-}
-
-/*******************************************************************
- Refresh our registered names with WINS
- ******************************************************************/
-void refresh_my_names(time_t t)
-{
- struct name_record *namerec;
-
- if (wins_srv_count() < 1) return;
-
- for (namerec = (struct name_record *)ubi_trFirst(unicast_subnet->namelist);
- namerec;
- namerec = (struct name_record *)ubi_trNext(namerec)) {
- /* Each SELF name has an individual time to be refreshed. */
- if ((namerec->data.source == SELF_NAME) &&
- (namerec->data.refresh_time < t) &&
- (namerec->data.death_time != PERMANENT_TTL)) {
- /* We cheat here and pretend the refresh is going to be
- successful & update the refresh times. This stops
- multiple refresh calls being done. We actually
- deal with refresh failure in the fail_fn.
- */
- if (!is_refresh_already_queued(unicast_subnet, namerec)) {
- wins_refresh_name(namerec);
- }
- namerec->data.death_time = t + lp_max_ttl();
- namerec->data.refresh_time = t + MIN(lp_max_ttl()/2, MAX_REFRESH_TIME);
- }
- }
-}
diff --git a/source4/nmbd/nmbd_namelistdb.c b/source4/nmbd/nmbd_namelistdb.c
deleted file mode 100644
index 6653cdd24b..0000000000
--- a/source4/nmbd/nmbd_namelistdb.c
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-uint16 samba_nb_type = 0; /* samba's NetBIOS name type */
-
-
-/* ************************************************************************** **
- * Set Samba's NetBIOS name type.
- * ************************************************************************** **
- */
-void set_samba_nb_type(void)
- {
- if( lp_wins_support() || wins_srv_count() )
- samba_nb_type = NB_HFLAG; /* samba is a 'hybrid' node type. */
- else
- samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type. */
- } /* set_samba_nb_type */
-
-/* ************************************************************************** **
- * Convert a NetBIOS name to upper case.
- * ************************************************************************** **
- */
-static void upcase_name( struct nmb_name *target, struct nmb_name *source )
- {
- int i;
-
- if( NULL != source )
- (void)memcpy( target, source, sizeof( struct nmb_name ) );
-
- strupper( target->name );
- strupper( target->scope );
-
- /* fudge... We're using a byte-by-byte compare, so we must be sure that
- * unused space doesn't have garbage in it.
- */
- for( i = strlen( target->name ); i < sizeof( target->name ); i++ )
- target->name[i] = '\0';
- for( i = strlen( target->scope ); i < sizeof( target->scope ); i++ )
- target->scope[i] = '\0';
- } /* upcase_name */
-
-/* ************************************************************************** **
- * Add a new or overwrite an existing namelist entry.
- * ************************************************************************** **
- */
-static void update_name_in_namelist( struct subnet_record *subrec,
- struct name_record *namerec )
- {
- struct name_record *oldrec = NULL;
-
- (void)ubi_trInsert( subrec->namelist, namerec, &(namerec->name), &oldrec );
- if( oldrec )
- {
- SAFE_FREE( oldrec->data.ip );
- SAFE_FREE( oldrec );
- }
- } /* update_name_in_namelist */
-
-/* ************************************************************************** **
- * Remove a name from the namelist.
- * ************************************************************************** **
- */
-void remove_name_from_namelist( struct subnet_record *subrec,
- struct name_record *namerec )
- {
- (void)ubi_trRemove( subrec->namelist, namerec );
-
- SAFE_FREE(namerec->data.ip);
-
- ZERO_STRUCTP(namerec);
- SAFE_FREE(namerec);
-
- subrec->namelist_changed = True;
- } /* remove_name_from_namelist */
-
-/* ************************************************************************** **
- * Find a name in a subnet.
- * ************************************************************************** **
- */
-struct name_record *find_name_on_subnet( struct subnet_record *subrec,
- struct nmb_name *nmbname,
- BOOL self_only )
- {
- struct nmb_name uc_name[1];
- struct name_record *name_ret;
-
- upcase_name( uc_name, nmbname );
- name_ret = (struct name_record *)ubi_trFind( subrec->namelist, uc_name );
- if( name_ret )
- {
- /* Self names only - these include permanent names. */
- if( self_only
- && (name_ret->data.source != SELF_NAME)
- && (name_ret->data.source != PERMANENT_NAME) )
- {
- DEBUG( 9,
- ( "find_name_on_subnet: on subnet %s - self name %s NOT FOUND\n",
- subrec->subnet_name, nmb_namestr(nmbname) ) );
- return( NULL );
- }
- DEBUG( 9, ("find_name_on_subnet: on subnet %s - found name %s source=%d\n",
- subrec->subnet_name, nmb_namestr(nmbname), name_ret->data.source) );
- return( name_ret );
- }
- DEBUG( 9,
- ( "find_name_on_subnet: on subnet %s - name %s NOT FOUND\n",
- subrec->subnet_name, nmb_namestr(nmbname) ) );
- return( NULL );
- } /* find_name_on_subnet */
-
-/* ************************************************************************** **
- * Find a name over all known broadcast subnets.
- * ************************************************************************** **
- */
-struct name_record *find_name_for_remote_broadcast_subnet(
- struct nmb_name *nmbname,
- BOOL self_only )
- {
- struct subnet_record *subrec;
- struct name_record *namerec = NULL;
-
- for( subrec = FIRST_SUBNET;
- subrec;
- subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
- {
- if( NULL != (namerec = find_name_on_subnet(subrec, nmbname, self_only)) )
- break;
- }
-
- return( namerec );
- } /* find_name_for_remote_broadcast_subnet */
-
-/* ************************************************************************** **
- * Update the ttl of an entry in a subnet name list.
- * ************************************************************************** **
- */
-void update_name_ttl( struct name_record *namerec, int ttl )
-{
- time_t time_now = time(NULL);
-
- if( namerec->data.death_time != PERMANENT_TTL )
- namerec->data.death_time = time_now + ttl;
-
- namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
-
- namerec->subnet->namelist_changed = True;
-} /* update_name_ttl */
-
-/* ************************************************************************** **
- * Add an entry to a subnet name list.
- * ************************************************************************** **
- */
-struct name_record *add_name_to_subnet( struct subnet_record *subrec,
- const char *name,
- int type,
- uint16 nb_flags,
- int ttl,
- enum name_source source,
- int num_ips,
- struct in_addr *iplist)
-{
- struct name_record *namerec;
- time_t time_now = time(NULL);
-
- namerec = (struct name_record *)malloc( sizeof(*namerec) );
- if( NULL == namerec )
- {
- DEBUG( 0, ( "add_name_to_subnet: malloc fail.\n" ) );
- return( NULL );
- }
-
- memset( (char *)namerec, '\0', sizeof(*namerec) );
- namerec->data.ip = (struct in_addr *)malloc( sizeof(struct in_addr)
- * num_ips );
- if( NULL == namerec->data.ip )
- {
- DEBUG( 0, ( "add_name_to_subnet: malloc fail when creating ip_flgs.\n" ) );
-
- ZERO_STRUCTP(namerec);
- SAFE_FREE(namerec);
- return NULL;
- }
-
- namerec->subnet = subrec;
-
- make_nmb_name(&namerec->name, name, type);
- upcase_name(&namerec->name, NULL );
-
- /* Enter the name as active. */
- namerec->data.nb_flags = nb_flags | NB_ACTIVE;
- namerec->data.wins_flags = WINS_ACTIVE;
-
- /* If it's our primary name, flag it as so. */
- if( strequal( my_netbios_names(0), name ) )
- namerec->data.nb_flags |= NB_PERM;
-
- /* Copy the IPs. */
- namerec->data.num_ips = num_ips;
- memcpy( (namerec->data.ip), iplist, num_ips * sizeof(struct in_addr) );
-
- /* Data source. */
- namerec->data.source = source;
-
- /* Setup the death_time and refresh_time. */
- if( ttl == PERMANENT_TTL )
- namerec->data.death_time = PERMANENT_TTL;
- else
- namerec->data.death_time = time_now + ttl;
-
- namerec->data.refresh_time = time_now + MIN((ttl/2), MAX_REFRESH_TIME);
-
- /* Now add the record to the name list. */
- update_name_in_namelist( subrec, namerec );
-
- DEBUG( 3, ( "add_name_to_subnet: Added netbios name %s with first IP %s \
-ttl=%d nb_flags=%2x to subnet %s\n",
- nmb_namestr( &namerec->name ),
- inet_ntoa( *iplist ),
- ttl,
- (unsigned int)nb_flags,
- subrec->subnet_name ) );
-
- subrec->namelist_changed = True;
-
- return(namerec);
-}
-
-/*******************************************************************
- Utility function automatically called when a name refresh or register
- succeeds. By definition this is a SELF_NAME (or we wouldn't be registering
- it).
- ******************************************************************/
-
-void standard_success_register(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname, uint16 nb_flags, int ttl,
- struct in_addr registered_ip)
-{
- struct name_record *namerec;
-
- namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME );
- if( NULL == namerec )
- (void)add_name_to_subnet( subrec, nmbname->name, nmbname->name_type,
- nb_flags, ttl, SELF_NAME, 1, &registered_ip );
- else
- update_name_ttl( namerec, ttl );
-}
-
-/*******************************************************************
- Utility function automatically called when a name refresh or register
- fails. Note that this is only ever called on a broadcast subnet with
- one IP address per name. This is why it can just delete the name
- without enumerating the IP adresses. JRA.
- ******************************************************************/
-
-void standard_fail_register( struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *nmbname )
-{
- struct name_record *namerec;
-
- namerec = find_name_on_subnet( subrec, nmbname, FIND_SELF_NAME );
-
- DEBUG( 0, ( "standard_fail_register: Failed to register/refresh name %s \
-on subnet %s\n",
- nmb_namestr(nmbname), subrec->subnet_name) );
-
- /* Remove the name from the subnet. */
- if( namerec )
- remove_name_from_namelist(subrec, namerec);
-}
-
-/*******************************************************************
- Utility function to remove an IP address from a name record.
- ******************************************************************/
-
-static void remove_nth_ip_in_record( struct name_record *namerec, int ind)
-{
- if( ind != namerec->data.num_ips )
- memmove( (char *)(&namerec->data.ip[ind]),
- (char *)(&namerec->data.ip[ind+1]),
- ( namerec->data.num_ips - ind - 1) * sizeof(struct in_addr) );
-
- namerec->data.num_ips--;
- namerec->subnet->namelist_changed = True;
-}
-
-/*******************************************************************
- Utility function to check if an IP address exists in a name record.
- ******************************************************************/
-
-BOOL find_ip_in_name_record( struct name_record *namerec, struct in_addr ip )
-{
- int i;
-
- for(i = 0; i < namerec->data.num_ips; i++)
- if(ip_equal( namerec->data.ip[i], ip))
- return True;
-
- return False;
-}
-
-/*******************************************************************
- Utility function to add an IP address to a name record.
- ******************************************************************/
-
-void add_ip_to_name_record( struct name_record *namerec, struct in_addr new_ip )
-{
- struct in_addr *new_list;
-
- /* Don't add one we already have. */
- if( find_ip_in_name_record( namerec, new_ip ) )
- return;
-
- new_list = (struct in_addr *)malloc( (namerec->data.num_ips + 1)
- * sizeof(struct in_addr) );
- if( NULL == new_list )
- {
- DEBUG(0,("add_ip_to_name_record: Malloc fail !\n"));
- return;
- }
-
- memcpy( (char *)new_list,
- (char *)namerec->data.ip,
- namerec->data.num_ips * sizeof(struct in_addr) );
- new_list[namerec->data.num_ips] = new_ip;
-
- SAFE_FREE(namerec->data.ip);
- namerec->data.ip = new_list;
- namerec->data.num_ips += 1;
-
- namerec->subnet->namelist_changed = True;
-}
-
-/*******************************************************************
- Utility function to remove an IP address from a name record.
- ******************************************************************/
-
-void remove_ip_from_name_record( struct name_record *namerec,
- struct in_addr remove_ip )
-{
- /* Try and find the requested ip address - remove it. */
- int i;
- int orig_num = namerec->data.num_ips;
-
- for(i = 0; i < orig_num; i++)
- if( ip_equal( remove_ip, namerec->data.ip[i]) )
- {
- remove_nth_ip_in_record( namerec, i);
- break;
- }
-}
-
-/*******************************************************************
- Utility function that release_name callers can plug into as the
- success function when a name release is successful. Used to save
- duplication of success_function code.
- ******************************************************************/
-
-void standard_success_release( struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname,
- struct in_addr released_ip )
-{
- struct name_record *namerec;
-
- namerec = find_name_on_subnet( subrec, nmbname, FIND_ANY_NAME );
-
- if( namerec == NULL )
- {
- DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
-on subnet %s. Name was not found on subnet.\n",
- nmb_namestr(nmbname),
- inet_ntoa(released_ip),
- subrec->subnet_name) );
- return;
- }
- else
- {
- int orig_num = namerec->data.num_ips;
-
- remove_ip_from_name_record( namerec, released_ip );
-
- if( namerec->data.num_ips == orig_num )
- DEBUG( 0, ( "standard_success_release: Name release for name %s IP %s \
-on subnet %s. This ip is not known for this name.\n",
- nmb_namestr(nmbname),
- inet_ntoa(released_ip),
- subrec->subnet_name ) );
- }
-
- if( namerec->data.num_ips == 0 )
- remove_name_from_namelist( subrec, namerec );
-}
-
-/*******************************************************************
- Expires old names in a subnet namelist.
- ******************************************************************/
-
-void expire_names_on_subnet(struct subnet_record *subrec, time_t t)
-{
- struct name_record *namerec;
- struct name_record *next_namerec;
-
- for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
- namerec;
- namerec = next_namerec )
- {
- next_namerec = (struct name_record *)ubi_trNext( namerec );
- if( (namerec->data.death_time != PERMANENT_TTL)
- && (namerec->data.death_time < t) )
- {
- if( namerec->data.source == SELF_NAME )
- {
- DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF \
-name %s\n",
- subrec->subnet_name, nmb_namestr(&namerec->name) ) );
- namerec->data.death_time += 300;
- namerec->subnet->namelist_changed = True;
- continue;
- }
- DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n",
- subrec->subnet_name, nmb_namestr(&namerec->name)));
-
- remove_name_from_namelist( subrec, namerec );
- }
- }
-}
-
-/*******************************************************************
- Expires old names in all subnet namelists.
- ******************************************************************/
-
-void expire_names(time_t t)
-{
- struct subnet_record *subrec;
-
- for( subrec = FIRST_SUBNET;
- subrec;
- subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) )
- {
- expire_names_on_subnet( subrec, t );
- }
-}
-
-/****************************************************************************
- Add the magic samba names, useful for finding samba servers.
- These go directly into the name list for a particular subnet,
- without going through the normal registration process.
- When adding them to the unicast subnet, add them as a list of
- all broadcast subnet IP addresses.
-**************************************************************************/
-
-void add_samba_names_to_subnet( struct subnet_record *subrec )
-{
- struct in_addr *iplist = &subrec->myip;
- int num_ips = 1;
-
- /* These names are added permanently (ttl of zero) and will NOT be
- refreshed. */
-
- if( (subrec == unicast_subnet)
- || (subrec == wins_server_subnet)
- || (subrec == remote_broadcast_subnet) )
- {
- struct subnet_record *bcast_subrecs;
- int i;
- /* Create an IP list containing all our known subnets. */
-
- num_ips = iface_count();
- iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) );
- if( NULL == iplist )
- {
- DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n"));
- return;
- }
-
- for( bcast_subrecs = FIRST_SUBNET, i = 0;
- bcast_subrecs;
- bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++ )
- iplist[i] = bcast_subrecs->myip;
-
- }
-
- (void)add_name_to_subnet(subrec,"*",0x0,samba_nb_type, PERMANENT_TTL,
- PERMANENT_NAME, num_ips, iplist);
- (void)add_name_to_subnet(subrec,"*",0x20,samba_nb_type,PERMANENT_TTL,
- PERMANENT_NAME, num_ips, iplist);
- (void)add_name_to_subnet(subrec,"__SAMBA__",0x20,samba_nb_type,PERMANENT_TTL,
- PERMANENT_NAME, num_ips, iplist);
- (void)add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL,
- PERMANENT_NAME, num_ips, iplist);
-
- if(iplist != &subrec->myip)
- SAFE_FREE(iplist);
-}
-
-/****************************************************************************
- Dump the contents of the namelists on all the subnets (including unicast)
- into a file. Initiated by SIGHUP - used to debug the state of the namelists.
-**************************************************************************/
-
-static void dump_subnet_namelist( struct subnet_record *subrec, XFILE *fp)
-{
- struct name_record *namerec;
- const char *src_type;
- struct tm *tm;
- int i;
-
- x_fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name);
- for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
- namerec;
- namerec = (struct name_record *)ubi_trNext( namerec ) )
- {
- x_fprintf(fp,"\tName = %s\t", nmb_namestr(&namerec->name));
- switch(namerec->data.source)
- {
- case LMHOSTS_NAME:
- src_type = "LMHOSTS_NAME";
- break;
- case WINS_PROXY_NAME:
- src_type = "WINS_PROXY_NAME";
- break;
- case REGISTER_NAME:
- src_type = "REGISTER_NAME";
- break;
- case SELF_NAME:
- src_type = "SELF_NAME";
- break;
- case DNS_NAME:
- src_type = "DNS_NAME";
- break;
- case DNSFAIL_NAME:
- src_type = "DNSFAIL_NAME";
- break;
- case PERMANENT_NAME:
- src_type = "PERMANENT_NAME";
- break;
- default:
- src_type = "unknown!";
- break;
- }
- x_fprintf(fp,"Source = %s\nb_flags = %x\t", src_type, namerec->data.nb_flags);
-
- if(namerec->data.death_time != PERMANENT_TTL)
- {
- tm = localtime(&namerec->data.death_time);
- x_fprintf(fp, "death_time = %s\t", asctime(tm));
- }
- else
- x_fprintf(fp, "death_time = PERMANENT\t");
-
- if(namerec->data.refresh_time != PERMANENT_TTL)
- {
- tm = localtime(&namerec->data.refresh_time);
- x_fprintf(fp, "refresh_time = %s\n", asctime(tm));
- }
- else
- x_fprintf(fp, "refresh_time = PERMANENT\n");
-
- x_fprintf(fp, "\t\tnumber of IPS = %d", namerec->data.num_ips);
- for(i = 0; i < namerec->data.num_ips; i++)
- x_fprintf(fp, "\t%s", inet_ntoa(namerec->data.ip[i]));
-
- x_fprintf(fp, "\n\n");
- }
-}
-
-/****************************************************************************
- Dump the contents of the namelists on all the subnets (including unicast)
- into a file. Initiated by SIGHUP - used to debug the state of the namelists.
-**************************************************************************/
-
-void dump_all_namelists(void)
-{
- XFILE *fp;
- struct subnet_record *subrec;
-
- fp = x_fopen(lock_path("namelist.debug"),O_WRONLY|O_CREAT|O_TRUNC, 0644);
-
- if (!fp)
- {
- DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n",
- "namelist.debug",strerror(errno)));
- return;
- }
-
- for( subrec = FIRST_SUBNET;
- subrec;
- subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec) )
- dump_subnet_namelist( subrec, fp );
-
- if( !we_are_a_wins_client() )
- dump_subnet_namelist( unicast_subnet, fp );
-
- if( remote_broadcast_subnet->namelist != NULL )
- dump_subnet_namelist( remote_broadcast_subnet, fp );
-
- if( wins_server_subnet != NULL )
- dump_subnet_namelist( wins_server_subnet, fp );
- x_fclose( fp );
-}
diff --git a/source4/nmbd/nmbd_namequery.c b/source4/nmbd/nmbd_namequery.c
deleted file mode 100644
index 8995e9ac52..0000000000
--- a/source4/nmbd/nmbd_namequery.c
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-/****************************************************************************
- Deal with a response packet when querying a name.
-****************************************************************************/
-
-static void query_name_response( struct subnet_record *subrec,
- struct response_record *rrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- BOOL success = False;
- struct nmb_name *question_name =
- &rrec->packet->packet.nmb.question.question_name;
- struct in_addr answer_ip;
-
- zero_ip(&answer_ip);
-
- /* Ensure we don't retry the query but leave the response record cleanup
- to the timeout code. We may get more answer responses in which case
- we should mark the name in conflict.. */
- rrec->repeat_count = 0;
-
- if(rrec->num_msgs == 1)
- {
- /* This is the first response. */
-
- if(nmb->header.opcode == NMB_WACK_OPCODE)
- {
- /* WINS server is telling us to wait. Pretend we didn't get
- the response but don't send out any more query requests. */
-
- if( DEBUGLVL( 5 ) )
- {
- dbgtext( "query_name_response: " );
- dbgtext( "WACK from WINS server %s ", inet_ntoa(p->ip) );
- dbgtext( "in querying name %s ", nmb_namestr(question_name) );
- dbgtext( "on subnet %s.\n", subrec->subnet_name );
- }
-
- rrec->repeat_count = 0;
- /* How long we should wait for. */
- rrec->repeat_time = p->timestamp + nmb->answers->ttl;
- rrec->num_msgs--;
- return;
- }
- else if(nmb->header.rcode != 0)
- {
- success = False;
-
- if( DEBUGLVL( 5 ) )
- {
- dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
- dbgtext( "- negative response from IP %s ", inet_ntoa(p->ip) );
- dbgtext( "for name %s. ", nmb_namestr(question_name) );
- dbgtext( "Error code was %d.\n", nmb->header.rcode );
- }
- }
- else
- {
- if (!nmb->answers)
- {
- dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
- dbgtext( "IP %s ", inet_ntoa(p->ip) );
- dbgtext( "returned a success response with no answer\n" );
- return;
- }
-
- success = True;
-
- putip((char *)&answer_ip,&nmb->answers->rdata[2]);
- if( DEBUGLVL( 5 ) )
- {
- dbgtext( "query_name_response: On subnet %s ", subrec->subnet_name );
- dbgtext( "- positive response from IP %s ", inet_ntoa(p->ip) );
- dbgtext( "for name %s. ", nmb_namestr(question_name) );
- dbgtext( "IP of that name is %s\n", inet_ntoa(answer_ip) );
- }
-
- /* Interestingly, we could add these names to our namelists, and
- change nmbd to a model that checked its own name cache first,
- before sending out a query. This is a task for another day, though.
- */
- }
- }
- else if( rrec->num_msgs > 1)
- {
- if( DEBUGLVL( 0 ) )
- {
- if (nmb->answers)
- putip( (char *)&answer_ip, &nmb->answers->rdata[2] );
- dbgtext( "query_name_response: " );
- dbgtext( "Multiple (%d) responses ", rrec->num_msgs );
- dbgtext( "received for a query on subnet %s ", subrec->subnet_name );
- dbgtext( "for name %s.\nThis response ", nmb_namestr(question_name) );
- dbgtext( "was from IP %s, reporting ", inet_ntoa(p->ip) );
- dbgtext( "an IP address of %s.\n", inet_ntoa(answer_ip) );
- }
-
- /* We have already called the success or fail function, so we
- don't call again here. Leave the response record around in
- case we get more responses. */
-
- return;
- }
-
- if(success && rrec->success_fn)
- (*(query_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers);
- else if( rrec->fail_fn)
- (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode);
-
-}
-
-/****************************************************************************
- Deal with a timeout when querying a name.
-****************************************************************************/
-
-static void query_name_timeout_response(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- /* We can only fail here, never succeed. */
- BOOL failed = True;
- struct nmb_name *question_name = &sent_nmb->question.question_name;
-
- if(rrec->num_msgs != 0)
- {
- /* We got at least one response, and have called the success/fail
- function already. */
-
- failed = False;
- }
-
- if(failed)
- {
- if( DEBUGLVL( 5 ) )
- {
- dbgtext( "query_name_timeout_response: No response to " );
- dbgtext( "query for name %s ", nmb_namestr(question_name) );
- dbgtext( "on subnet %s.\n", subrec->subnet_name );
- }
- if(rrec->fail_fn)
- (*(query_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name, 0);
- }
-
- remove_response_record(subrec, rrec);
-}
-
-/****************************************************************************
- Lookup a name on our local namelists. We check the lmhosts file first. If the
- name is not there we look for the name on the given subnet.
-****************************************************************************/
-
-static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name *nmbname,
- struct name_record **namerecp)
-{
- struct name_record *namerec;
-
- *namerecp = NULL;
-
- if(find_name_in_lmhosts(nmbname, namerecp))
- return True;
-
- if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL)
- return False;
-
- if( NAME_IS_ACTIVE(namerec)
- && ( (namerec->data.source == SELF_NAME)
- || (namerec->data.source == LMHOSTS_NAME) ) )
- {
- *namerecp = namerec;
- return True;
- }
- return False;
-}
-
-/****************************************************************************
- Try and query for a name.
-****************************************************************************/
-
-BOOL query_name(struct subnet_record *subrec, char *name, int type,
- query_name_success_function success_fn,
- query_name_fail_function fail_fn,
- struct userdata_struct *userdata)
-{
- struct nmb_name nmbname;
- struct name_record *namerec;
-
- make_nmb_name(&nmbname, name, type);
-
- /*
- * We need to check our local namelists first.
- * It may be an magic name, lmhosts name or just
- * a name we have registered.
- */
-
- if(query_local_namelists(subrec, &nmbname, &namerec) == True)
- {
- struct res_rec rrec;
- int i;
-
- memset((char *)&rrec, '\0', sizeof(struct res_rec));
-
- /* Fake up the needed res_rec just in case it's used. */
- rrec.rr_name = nmbname;
- rrec.rr_type = RR_TYPE_NB;
- rrec.rr_class = RR_CLASS_IN;
- rrec.ttl = PERMANENT_TTL;
- rrec.rdlength = namerec->data.num_ips * 6;
- if(rrec.rdlength > MAX_DGRAM_SIZE)
- {
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "query_name: nmbd internal error - " );
- dbgtext( "there are %d ip addresses ", namerec->data.num_ips );
- dbgtext( "for name %s.\n", nmb_namestr(&nmbname) );
- }
- return False;
- }
-
- for( i = 0; i < namerec->data.num_ips; i++)
- {
- set_nb_flags( &rrec.rdata[i*6], namerec->data.nb_flags );
- putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->data.ip[i]);
- }
-
- /* Call the success function directly. */
- if(success_fn)
- (*(query_name_success_function)success_fn)(subrec, userdata, &nmbname, namerec->data.ip[0], &rrec);
- return False;
- }
-
- if(queue_query_name( subrec,
- query_name_response,
- query_name_timeout_response,
- success_fn,
- fail_fn,
- userdata,
- &nmbname) == NULL)
- {
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "query_name: Failed to send packet " );
- dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
- }
- return True;
- }
- return False;
-}
-
-/****************************************************************************
- Try and query for a name from nmbd acting as a WINS server.
-****************************************************************************/
-
-BOOL query_name_from_wins_server(struct in_addr ip_to,
- char *name, int type,
- query_name_success_function success_fn,
- query_name_fail_function fail_fn,
- struct userdata_struct *userdata)
-{
- struct nmb_name nmbname;
-
- make_nmb_name(&nmbname, name, type);
-
- if(queue_query_name_from_wins_server( ip_to,
- query_name_response,
- query_name_timeout_response,
- success_fn,
- fail_fn,
- userdata,
- &nmbname) == NULL)
- {
- if( DEBUGLVL( 0 ) )
- {
- dbgtext( "query_name_from_wins_server: Failed to send packet " );
- dbgtext( "trying to query name %s\n", nmb_namestr(&nmbname) );
- }
- return True;
- }
- return False;
-}
diff --git a/source4/nmbd/nmbd_nameregister.c b/source4/nmbd/nmbd_nameregister.c
deleted file mode 100644
index 7bf2584053..0000000000
--- a/source4/nmbd/nmbd_nameregister.c
+++ /dev/null
@@ -1,522 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-/* forward declarations */
-static void wins_next_registration(struct response_record *rrec);
-
-
-/****************************************************************************
- Deal with a response packet when registering one of our names.
-****************************************************************************/
-
-static void register_name_response(struct subnet_record *subrec,
- struct response_record *rrec, struct packet_struct *p)
-{
- /*
- * If we are registering broadcast, then getting a response is an
- * error - we do not have the name. If we are registering unicast,
- * then we expect to get a response.
- */
-
- struct nmb_packet *nmb = &p->packet.nmb;
- BOOL bcast = nmb->header.nm_flags.bcast;
- BOOL success = True;
- struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
- struct nmb_name *answer_name = &nmb->answers->rr_name;
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- int ttl = 0;
- uint16 nb_flags = 0;
- struct in_addr register_ip;
- fstring reg_name;
-
- putip(&register_ip,&sent_nmb->additional->rdata[2]);
- fstrcpy(reg_name, inet_ntoa(register_ip));
-
- if (subrec == unicast_subnet) {
- /* we know that this wins server is definately alive - for the moment! */
- wins_srv_alive(rrec->packet->ip, register_ip);
- }
-
- /* Sanity check. Ensure that the answer name in the incoming packet is the
- same as the requested name in the outgoing packet. */
-
- if(!question_name || !answer_name) {
- DEBUG(0,("register_name_response: malformed response (%s is NULL).\n",
- question_name ? "question_name" : "answer_name" ));
- return;
- }
-
- if(!nmb_name_equal(question_name, answer_name)) {
- DEBUG(0,("register_name_response: Answer name %s differs from question name %s.\n",
- nmb_namestr(answer_name), nmb_namestr(question_name)));
- return;
- }
-
- if(bcast) {
- /*
- * Special hack to cope with old Samba nmbd's.
- * Earlier versions of Samba (up to 1.9.16p11) respond
- * to a broadcast name registration of WORKGROUP<1b> when
- * they should not. Hence, until these versions are gone,
- * we should treat such errors as success for this particular
- * case only. jallison@whistle.com.
- */
-
-#if 1 /* OLD_SAMBA_SERVER_HACK */
- if((nmb->header.rcode == ACT_ERR) && strequal(lp_workgroup(), answer_name->name) &&
- (answer_name->name_type == 0x1b)) {
- /* Pretend we did not get this. */
- rrec->num_msgs--;
-
- DEBUG(5,("register_name_response: Ignoring broadcast response to registration of name %s due to old Samba server bug.\n",
- nmb_namestr(answer_name)));
- return;
- }
-#endif /* OLD_SAMBA_SERVER_HACK */
-
- /* Someone else has the name. Log the problem. */
- DEBUG(1,("register_name_response: Failed to register name %s IP %s on subnet %s via broadcast. Error code was %d. Reject came from IP %s\n",
- nmb_namestr(answer_name),
- reg_name,
- subrec->subnet_name, nmb->header.rcode, inet_ntoa(p->ip)));
- success = False;
- } else {
- /* Unicast - check to see if the response allows us to have the name. */
- if (nmb->header.opcode == NMB_WACK_OPCODE) {
- /* WINS server is telling us to wait. Pretend we didn't get
- the response but don't send out any more register requests. */
-
- DEBUG(5,("register_name_response: WACK from WINS server %s in registering name %s IP %s\n",
- inet_ntoa(p->ip), nmb_namestr(answer_name), reg_name));
-
- rrec->repeat_count = 0;
- /* How long we should wait for. */
- rrec->repeat_time = p->timestamp + nmb->answers->ttl;
- rrec->num_msgs--;
- return;
- } else if (nmb->header.rcode != 0) {
- /* Error code - we didn't get the name. */
- success = False;
-
- DEBUG(0,("register_name_response: %sserver at IP %s rejected our name registration of %s IP %s with error code %d.\n",
- subrec==unicast_subnet?"WINS ":"",
- inet_ntoa(p->ip),
- nmb_namestr(answer_name),
- reg_name,
- nmb->header.rcode));
- } else {
- success = True;
- /* Get the data we need to pass to the success function. */
- nb_flags = get_nb_flags(nmb->answers->rdata);
- ttl = nmb->answers->ttl;
-
- /* send off a registration for the next IP, if any */
- wins_next_registration(rrec);
- }
- }
-
- DEBUG(5,("register_name_response: %s in registering %sname %s IP %s with %s.\n",
- success ? "success" : "failure",
- subrec==unicast_subnet?"WINS ":"",
- nmb_namestr(answer_name),
- reg_name,
- inet_ntoa(rrec->packet->ip)));
-
- if(success) {
- /* Enter the registered name into the subnet name database before calling
- the success function. */
- standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
- if( rrec->success_fn)
- (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, register_ip);
- } else {
- if( rrec->fail_fn)
- (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
- /* Remove the name. */
- standard_fail_register( subrec, rrec, question_name);
- }
-
- /* Ensure we don't retry. */
- remove_response_record(subrec, rrec);
-}
-
-
-/****************************************************************************
- Deal with a timeout of a WINS registration request
-****************************************************************************/
-static void wins_registration_timeout(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- struct userdata_struct *userdata = rrec->userdata;
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- struct nmb_name *nmbname = &sent_nmb->question.question_name;
- struct in_addr register_ip;
- fstring src_addr;
-
- putip(&register_ip,&sent_nmb->additional->rdata[2]);
-
- fstrcpy(src_addr, inet_ntoa(register_ip));
-
- DEBUG(2,("wins_registration_timeout: WINS server %s timed out registering IP %s\n",
- inet_ntoa(rrec->packet->ip), src_addr));
-
- /* mark it temporarily dead for this source address */
- wins_srv_died(rrec->packet->ip, register_ip);
-
- /* if we have some userdata then use that to work out what
- wins server to try next */
- if (userdata) {
- const char *tag = (const char *)userdata->data;
-
- /* try the next wins server in our failover list for
- this tag */
- rrec->packet->ip = wins_srv_ip_tag(tag, register_ip);
- }
-
- /* if we have run out of wins servers for this tag then they
- must all have timed out. We treat this as *success*, not
- failure, and go into our standard name refresh mode. This
- copes with all the wins servers being down */
- if (wins_srv_is_dead(rrec->packet->ip, register_ip)) {
- uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
- int ttl = sent_nmb->additional->ttl;
-
- standard_success_register(subrec, userdata, nmbname, nb_flags, ttl, register_ip);
- if(rrec->success_fn) {
- (*(register_name_success_function)rrec->success_fn)(subrec,
- rrec->userdata,
- nmbname,
- nb_flags,
- ttl,
- register_ip);
- }
-
- /* send off a registration for the next IP, if any */
- wins_next_registration(rrec);
-
- /* don't need to send this packet any more */
- remove_response_record(subrec, rrec);
- return;
- }
-
- /* we will be moving to the next WINS server for this group,
- send it immediately */
- rrec->repeat_count = 2;
- rrec->repeat_time = time(NULL) + 1;
- rrec->in_expiration_processing = False;
-
- DEBUG(6,("Retrying register of name %s IP %s with WINS server %s\n",
- nmb_namestr(nmbname), src_addr, inet_ntoa(rrec->packet->ip)));
-
- /* notice that we don't remove the response record. This keeps
- us trying to register with each of our failover wins servers */
-}
-
-
-/****************************************************************************
- Deal with a timeout when registering one of our names.
-****************************************************************************/
-
-static void register_name_timeout_response(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- /*
- * If we are registering unicast, then NOT getting a response is an
- * error - we do not have the name. If we are registering broadcast,
- * then we don't expect to get a response.
- */
-
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- BOOL bcast = sent_nmb->header.nm_flags.bcast;
- BOOL success = False;
- struct nmb_name *question_name = &sent_nmb->question.question_name;
- uint16 nb_flags = 0;
- int ttl = 0;
- struct in_addr registered_ip;
-
- if (bcast) {
- if(rrec->num_msgs == 0) {
- /* Not receiving a message is success for broadcast registration. */
- success = True;
-
- /* Pull the success values from the original request packet. */
- nb_flags = get_nb_flags(sent_nmb->additional->rdata);
- ttl = sent_nmb->additional->ttl;
- putip(&registered_ip,&sent_nmb->additional->rdata[2]);
- }
- } else {
- /* wins timeouts are special */
- wins_registration_timeout(subrec, rrec);
- return;
- }
-
- DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n",
- success ? "success" : "failure", nmb_namestr(question_name), subrec->subnet_name));
- if(success) {
- /* Enter the registered name into the subnet name database before calling
- the success function. */
- standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
- if( rrec->success_fn)
- (*(register_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
- } else {
- if( rrec->fail_fn)
- (*(register_name_fail_function)rrec->fail_fn)(subrec, rrec, question_name);
- /* Remove the name. */
- standard_fail_register( subrec, rrec, question_name);
- }
-
- /* Ensure we don't retry. */
- remove_response_record(subrec, rrec);
-}
-
-
-/****************************************************************************
-initiate one multi-homed name registration packet
-****************************************************************************/
-static void multihomed_register_one(struct nmb_name *nmbname,
- uint16 nb_flags,
- register_name_success_function success_fn,
- register_name_fail_function fail_fn,
- struct in_addr ip,
- const char *tag)
-{
- struct userdata_struct *userdata;
- struct in_addr wins_ip = wins_srv_ip_tag(tag, ip);
- fstring ip_str;
-
- userdata = (struct userdata_struct *)malloc(sizeof(*userdata) + strlen(tag) + 1);
- if (!userdata) {
- DEBUG(0,("Failed to allocate userdata structure!\n"));
- return;
- }
- ZERO_STRUCTP(userdata);
- userdata->userdata_len = strlen(tag) + 1;
- strlcpy(userdata->data, tag, userdata->userdata_len);
-
- fstrcpy(ip_str, inet_ntoa(ip));
-
- DEBUG(6,("Registering name %s IP %s with WINS server %s using tag '%s'\n",
- nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag));
-
- if (queue_register_multihomed_name(unicast_subnet,
- register_name_response,
- register_name_timeout_response,
- success_fn,
- fail_fn,
- userdata,
- nmbname,
- nb_flags,
- ip,
- wins_ip) == NULL) {
- DEBUG(0,("multihomed_register_one: Failed to send packet trying to register name %s IP %s\n",
- nmb_namestr(nmbname), inet_ntoa(ip)));
- }
-
- free(userdata);
-}
-
-
-/****************************************************************************
-we have finished the registration of one IP and need to see if we have
-any more IPs left to register with this group of wins server for this name
-****************************************************************************/
-static void wins_next_registration(struct response_record *rrec)
-{
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- struct nmb_name *nmbname = &sent_nmb->question.question_name;
- uint16 nb_flags = get_nb_flags(sent_nmb->additional->rdata);
- struct userdata_struct *userdata = rrec->userdata;
- const char *tag;
- struct in_addr last_ip;
- struct subnet_record *subrec;
-
- putip(&last_ip,&sent_nmb->additional->rdata[2]);
-
- if (!userdata) {
- /* it wasn't multi-homed */
- return;
- }
-
- tag = (const char *)userdata->data;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec)) {
- if (ip_equal(last_ip, subrec->myip)) {
- subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec);
- break;
- }
- }
-
- if (!subrec) {
- /* no more to do! */
- return;
- }
-
- switch (sent_nmb->header.opcode) {
- case NMB_NAME_MULTIHOMED_REG_OPCODE:
- multihomed_register_one(nmbname, nb_flags, NULL, NULL, subrec->myip, tag);
- break;
- case NMB_NAME_REFRESH_OPCODE_8:
- queue_wins_refresh(nmbname,
- register_name_response,
- register_name_timeout_response,
- nb_flags, subrec->myip, tag);
- break;
- }
-}
-
-/****************************************************************************
- Try and register one of our names on the unicast subnet - multihomed.
-****************************************************************************/
-static void multihomed_register_name(struct nmb_name *nmbname, uint16 nb_flags,
- register_name_success_function success_fn,
- register_name_fail_function fail_fn)
-{
- /*
- If we are adding a group name, we just send multiple
- register name packets to the WINS server (this is an
- internet group name.
-
- If we are adding a unique name, We need first to add
- our names to the unicast subnet namelist. This is
- because when a WINS server receives a multihomed
- registration request, the first thing it does is to
- send a name query to the registering machine, to see
- if it has put the name in it's local namelist.
- We need the name there so the query response code in
- nmbd_incomingrequests.c will find it.
-
- We are adding this name prematurely (we don't really
- have it yet), but as this is on the unicast subnet
- only we will get away with this (only the WINS server
- will ever query names from us on this subnet).
- */
- int num_ips=0;
- int i, t;
- struct subnet_record *subrec;
- char **wins_tags;
- struct in_addr *ip_list;
-
- for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
- num_ips++;
-
- if((ip_list = (struct in_addr *)malloc(num_ips * sizeof(struct in_addr)))==NULL) {
- DEBUG(0,("multihomed_register_name: malloc fail !\n"));
- return;
- }
-
- for (subrec = FIRST_SUBNET, i = 0;
- subrec;
- subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ ) {
- ip_list[i] = subrec->myip;
- }
-
- add_name_to_subnet(unicast_subnet, nmbname->name, nmbname->name_type,
- nb_flags, lp_max_ttl(), SELF_NAME,
- num_ips, ip_list);
-
- /* get the list of wins tags - we try to register for each of them */
- wins_tags = wins_srv_tags();
-
- /* Now try and register the name for each wins tag. Note that
- at this point we only register our first IP with each wins
- group. We will register the rest from
- wins_next_registration() when we get the reply for this
- one. That follows the way W2K does things (tridge)
- */
- for (t=0; wins_tags && wins_tags[t]; t++) {
- multihomed_register_one(nmbname, nb_flags,
- success_fn, fail_fn,
- ip_list[0],
- wins_tags[t]);
- }
-
- wins_srv_tags_free(wins_tags);
-
- SAFE_FREE(ip_list);
-}
-
-
-/****************************************************************************
- Try and register one of our names.
-****************************************************************************/
-void register_name(struct subnet_record *subrec,
- const char *name, int type, uint16 nb_flags,
- register_name_success_function success_fn,
- register_name_fail_function fail_fn,
- struct userdata_struct *userdata)
-{
- struct nmb_name nmbname;
-
- make_nmb_name(&nmbname, name, type);
-
- /* Always set the NB_ACTIVE flag on the name we are
- registering. Doesn't make sense without it.
- */
-
- nb_flags |= NB_ACTIVE;
-
- if (subrec == unicast_subnet) {
- /* we now always do multi-homed registration if we are
- registering to a WINS server. This copes much
- better with complex WINS setups */
- multihomed_register_name(&nmbname, nb_flags,
- success_fn, fail_fn);
- return;
- }
-
- if (queue_register_name(subrec,
- register_name_response,
- register_name_timeout_response,
- success_fn,
- fail_fn,
- userdata,
- &nmbname,
- nb_flags) == NULL) {
- DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
- nmb_namestr(&nmbname)));
- }
-}
-
-
-/****************************************************************************
- Try and refresh one of our names. This is *only* called for WINS refresh
-****************************************************************************/
-void wins_refresh_name(struct name_record *namerec)
-{
- int t;
- char **wins_tags;
-
- /* get the list of wins tags - we try to refresh for each of them */
- wins_tags = wins_srv_tags();
-
- for (t=0; wins_tags && wins_tags[t]; t++) {
- queue_wins_refresh(&namerec->name,
- register_name_response,
- register_name_timeout_response,
- namerec->data.nb_flags,
- namerec->data.ip[0], wins_tags[t]);
- }
-
- wins_srv_tags_free(wins_tags);
-}
diff --git a/source4/nmbd/nmbd_namerelease.c b/source4/nmbd/nmbd_namerelease.c
deleted file mode 100644
index 0611ca9323..0000000000
--- a/source4/nmbd/nmbd_namerelease.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-/****************************************************************************
- Deal with a response packet when releasing one of our names.
-****************************************************************************/
-
-static void release_name_response(struct subnet_record *subrec,
- struct response_record *rrec, struct packet_struct *p)
-{
- /*
- * If we are releasing broadcast, then getting a response is an
- * error. If we are releasing unicast, then we expect to get a response.
- */
- struct nmb_packet *nmb = &p->packet.nmb;
- BOOL bcast = nmb->header.nm_flags.bcast;
- BOOL success = True;
- struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
- struct nmb_name *answer_name = &nmb->answers->rr_name;
- struct in_addr released_ip;
-
- /* Sanity check. Ensure that the answer name in the incoming packet is the
- same as the requested name in the outgoing packet. */
- if (!nmb_name_equal(question_name, answer_name)) {
- DEBUG(0,("release_name_response: Answer name %s differs from question name %s.\n",
- nmb_namestr(answer_name), nmb_namestr(question_name)));
- return;
- }
-
- if (bcast) {
- /* Someone sent a response to a bcast release? ignore it. */
- return;
- }
-
- /* Unicast - check to see if the response allows us to release the name. */
- if (nmb->header.rcode != 0) {
- /* Error code - we were told not to release the name ! What now ! */
- success = False;
-
- DEBUG(0,("release_name_response: WINS server at IP %s rejected our \
-name release of name %s with error code %d.\n",
- inet_ntoa(p->ip),
- nmb_namestr(answer_name), nmb->header.rcode));
- } else if (nmb->header.opcode == NMB_WACK_OPCODE) {
- /* WINS server is telling us to wait. Pretend we didn't get
- the response but don't send out any more release requests. */
-
- DEBUG(5,("release_name_response: WACK from WINS server %s in releasing \
-name %s on subnet %s.\n",
- inet_ntoa(p->ip), nmb_namestr(answer_name), subrec->subnet_name));
-
- rrec->repeat_count = 0;
- /* How long we should wait for. */
- rrec->repeat_time = p->timestamp + nmb->answers->ttl;
- rrec->num_msgs--;
- return;
- }
-
- DEBUG(5,("release_name_response: %s in releasing name %s on subnet %s.\n",
- success ? "success" : "failure", nmb_namestr(answer_name), subrec->subnet_name));
- if (success) {
- putip((char*)&released_ip ,&nmb->answers->rdata[2]);
-
- if(rrec->success_fn)
- (*(release_name_success_function)rrec->success_fn)(subrec, rrec->userdata, answer_name, released_ip);
- standard_success_release( subrec, rrec->userdata, answer_name, released_ip);
- } else {
- /* We have no standard_fail_release - maybe we should add one ? */
- if (rrec->fail_fn) {
- (*(release_name_fail_function)rrec->fail_fn)(subrec, rrec, answer_name);
- }
- }
-
- remove_response_record(subrec, rrec);
-}
-
-/****************************************************************************
- Deal with a timeout when releasing one of our names.
-****************************************************************************/
-
-static void release_name_timeout_response(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- /* a release is *always* considered to be successful when it
- times out. This doesn't cause problems as if a WINS server
- doesn't respond and someone else wants the name then the
- normal WACK/name query from the WINS server will cope */
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- BOOL bcast = sent_nmb->header.nm_flags.bcast;
- struct nmb_name *question_name = &sent_nmb->question.question_name;
- struct in_addr released_ip;
-
- /* Get the ip address we were trying to release. */
- putip((char*)&released_ip ,&sent_nmb->additional->rdata[2]);
-
- if (!bcast) {
- /* mark the WINS server temporarily dead */
- wins_srv_died(rrec->packet->ip, released_ip);
- }
-
- DEBUG(5,("release_name_timeout_response: success in releasing name %s on subnet %s.\n",
- nmb_namestr(question_name), subrec->subnet_name));
-
- if (rrec->success_fn) {
- (*(release_name_success_function)rrec->success_fn)(subrec, rrec->userdata, question_name, released_ip);
- }
-
- standard_success_release( subrec, rrec->userdata, question_name, released_ip);
- remove_response_record(subrec, rrec);
-}
-
-
-/*
- when releasing a name with WINS we need to send the release to each of
- the WINS groups
-*/
-static void wins_release_name(struct name_record *namerec,
- release_name_success_function success_fn,
- release_name_fail_function fail_fn,
- struct userdata_struct *userdata)
-{
- int t, i;
- char **wins_tags;
-
- /* get the list of wins tags - we try to release for each of them */
- wins_tags = wins_srv_tags();
-
- for (t=0;wins_tags && wins_tags[t]; t++) {
- for (i = 0; i < namerec->data.num_ips; i++) {
- struct in_addr wins_ip = wins_srv_ip_tag(wins_tags[t], namerec->data.ip[i]);
-
- BOOL last_one = ((i==namerec->data.num_ips - 1) && !wins_tags[t+1]);
- if (queue_release_name(unicast_subnet,
- release_name_response,
- release_name_timeout_response,
- last_one?success_fn : NULL,
- last_one? fail_fn : NULL,
- last_one? userdata : NULL,
- &namerec->name,
- namerec->data.nb_flags,
- namerec->data.ip[i],
- wins_ip) == NULL) {
- DEBUG(0,("release_name: Failed to send packet trying to release name %s IP %s\n",
- nmb_namestr(&namerec->name), inet_ntoa(namerec->data.ip[i]) ));
- }
- }
- }
-
- wins_srv_tags_free(wins_tags);
-}
-
-
-/****************************************************************************
- Try and release one of our names.
-****************************************************************************/
-
-void release_name(struct subnet_record *subrec, struct name_record *namerec,
- release_name_success_function success_fn,
- release_name_fail_function fail_fn,
- struct userdata_struct *userdata)
-{
- int i;
-
- /* Ensure it's a SELF name, and in the ACTIVE state. */
- if ((namerec->data.source != SELF_NAME) || !NAME_IS_ACTIVE(namerec)) {
- DEBUG(0,("release_name: Cannot release name %s from subnet %s. Source was %d \n",
- nmb_namestr(&namerec->name), subrec->subnet_name, namerec->data.source));
- return;
- }
-
- /* Set the name into the deregistering state. */
- namerec->data.nb_flags |= NB_DEREG;
-
- /* wins releases are a bit different */
- if (subrec == unicast_subnet) {
- wins_release_name(namerec, success_fn, fail_fn, userdata);
- return;
- }
-
- /*
- * Go through and release the name for all known ip addresses.
- * Only call the success/fail function on the last one (it should
- * only be done once).
- */
- for (i = 0; i < namerec->data.num_ips; i++) {
- if (queue_release_name(subrec,
- release_name_response,
- release_name_timeout_response,
- (i == (namerec->data.num_ips - 1)) ? success_fn : NULL,
- (i == (namerec->data.num_ips - 1)) ? fail_fn : NULL,
- (i == (namerec->data.num_ips - 1)) ? userdata : NULL,
- &namerec->name,
- namerec->data.nb_flags,
- namerec->data.ip[i],
- subrec->bcast_ip) == NULL) {
- DEBUG(0,("release_name: Failed to send packet trying to release name %s IP %s\n",
- nmb_namestr(&namerec->name), inet_ntoa(namerec->data.ip[i]) ));
- }
- }
-}
diff --git a/source4/nmbd/nmbd_nodestatus.c b/source4/nmbd/nmbd_nodestatus.c
deleted file mode 100644
index 993e4d9d17..0000000000
--- a/source4/nmbd/nmbd_nodestatus.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-/****************************************************************************
- Deal with a successful node status response.
-****************************************************************************/
-static void node_status_response(struct subnet_record *subrec,
- struct response_record *rrec, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
- struct nmb_name *answer_name = &nmb->answers->rr_name;
-
- /* Sanity check. Ensure that the answer name in the incoming packet is the
- same as the requested name in the outgoing packet. */
-
- if(!nmb_name_equal(question_name, answer_name))
- {
- DEBUG(0,("node_status_response: Answer name %s differs from question \
-name %s.\n", nmb_namestr(answer_name), nmb_namestr(question_name)));
- return;
- }
-
- DEBUG(5,("node_status_response: response from name %s on subnet %s.\n",
- nmb_namestr(answer_name), subrec->subnet_name));
-
- /* Just send the whole answer resource record for the success function
- to parse. */
- if(rrec->success_fn)
- (*(node_status_success_function)rrec->success_fn)(subrec, rrec->userdata, nmb->answers, p->ip);
-
- /* Ensure we don't retry. */
- remove_response_record(subrec, rrec);
-}
-
-/****************************************************************************
- Deal with a timeout when requesting a node status.
-****************************************************************************/
-static void node_status_timeout_response(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- struct nmb_name *question_name = &sent_nmb->question.question_name;
-
- DEBUG(5,("node_status_timeout_response: failed to get node status from name %s on subnet %s\n",
- nmb_namestr(question_name), subrec->subnet_name));
-
- if( rrec->fail_fn)
- (*rrec->fail_fn)(subrec, rrec);
-
- /* Ensure we don't retry. */
- remove_response_record(subrec, rrec);
-}
-
-/****************************************************************************
- Try and do a node status to a name - given the name & IP address.
-****************************************************************************/
-
-BOOL node_status(struct subnet_record *subrec, struct nmb_name *nmbname,
- struct in_addr send_ip, node_status_success_function success_fn,
- node_status_fail_function fail_fn, struct userdata_struct *userdata)
-{
- if(queue_node_status( subrec,
- node_status_response, node_status_timeout_response,
- success_fn, fail_fn, userdata, nmbname, send_ip)==NULL)
- {
- DEBUG(0,("node_status: Failed to send packet trying to get node status for \
-name %s, IP address %s\n", nmb_namestr(nmbname), inet_ntoa(send_ip)));
- return True;
- }
- return False;
-}
diff --git a/source4/nmbd/nmbd_packets.c b/source4/nmbd/nmbd_packets.c
deleted file mode 100644
index 6ee13812dc..0000000000
--- a/source4/nmbd/nmbd_packets.c
+++ /dev/null
@@ -1,2013 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-extern int ClientNMB;
-extern int ClientDGRAM;
-extern int global_nmb_port;
-
-extern int num_response_packets;
-
-extern struct in_addr loopback_ip;
-
-static void queue_packet(struct packet_struct *packet);
-
-BOOL rescan_listen_set = False;
-
-
-/*******************************************************************
- The global packet linked-list. Incoming entries are
- added to the end of this list. It is supposed to remain fairly
- short so we won't bother with an end pointer.
-******************************************************************/
-
-static struct packet_struct *packet_queue = NULL;
-
-/***************************************************************************
-Utility function to find the specific fd to send a packet out on.
-**************************************************************************/
-
-static int find_subnet_fd_for_address( struct in_addr local_ip )
-{
- struct subnet_record *subrec;
-
- for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- if(ip_equal(local_ip, subrec->myip))
- return subrec->nmb_sock;
-
- return ClientNMB;
-}
-
-/***************************************************************************
-Utility function to find the specific fd to send a mailslot packet out on.
-**************************************************************************/
-
-static int find_subnet_mailslot_fd_for_address( struct in_addr local_ip )
-{
- struct subnet_record *subrec;
-
- for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- if(ip_equal(local_ip, subrec->myip))
- return subrec->dgram_sock;
-
- return ClientDGRAM;
-}
-
-/***************************************************************************
-Get/Set problematic nb_flags as network byte order 16 bit int.
-**************************************************************************/
-
-uint16 get_nb_flags(char *buf)
-{
- return ((((uint16)*buf)&0xFFFF) & NB_FLGMSK);
-}
-
-void set_nb_flags(char *buf, uint16 nb_flags)
-{
- *buf++ = ((nb_flags & NB_FLGMSK) & 0xFF);
- *buf = '\0';
-}
-
-/***************************************************************************
-Dumps out the browse packet data.
-**************************************************************************/
-
-static void debug_browse_data(char *outbuf, int len)
-{
- int i,j;
-
- DEBUG( 4, ( "debug_browse_data():\n" ) );
- for (i = 0; i < len; i+= 16)
- {
- DEBUGADD( 4, ( "%3x char ", i ) );
-
- for (j = 0; j < 16; j++)
- {
- unsigned char x;
- if (i+j >= len)
- break;
-
- x = outbuf[i+j];
- if (x < 32 || x > 127)
- x = '.';
-
- DEBUGADD( 4, ( "%c", x ) );
- }
-
- DEBUGADD( 4, ( "%*s hex", 16-j, "" ) );
-
- for (j = 0; j < 16; j++)
- {
- if (i+j >= len)
- break;
- DEBUGADD( 4, ( " %02x", (unsigned char)outbuf[i+j] ) );
- }
-
- DEBUGADD( 4, ("\n") );
- }
-}
-
-/***************************************************************************
- Generates the unique transaction identifier
-**************************************************************************/
-
-static uint16 name_trn_id=0;
-
-static uint16 generate_name_trn_id(void)
-{
-
- if (!name_trn_id)
- {
- name_trn_id = ((unsigned)time(NULL)%(unsigned)0x7FFF) + ((unsigned)sys_getpid()%(unsigned)100);
- }
- name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
- return name_trn_id;
-}
-
-/***************************************************************************
- Either loops back or sends out a completed NetBIOS packet.
-**************************************************************************/
-
-static BOOL send_netbios_packet(struct packet_struct *p)
-{
- BOOL loopback_this_packet = False;
-
- /* Check if we are sending to or from ourselves as a WINS server. */
- if(ismyip(p->ip) && (p->port == global_nmb_port))
- loopback_this_packet = True;
-
- if(loopback_this_packet)
- {
- struct packet_struct *lo_packet = NULL;
- DEBUG(5,("send_netbios_packet: sending packet to ourselves.\n"));
- if((lo_packet = copy_packet(p)) == NULL)
- return False;
- queue_packet(lo_packet);
- }
- else if (!send_packet(p))
- {
- DEBUG(0,("send_netbios_packet: send_packet() to IP %s port %d failed\n",
- inet_ntoa(p->ip),p->port));
- return False;
- }
-
- return True;
-}
-
-/***************************************************************************
- Sets up the common elements of an outgoing NetBIOS packet.
-
- Note: do not attempt to rationalise whether rec_des should be set or not
- in a particular situation. Just follow rfc_1002 or look at examples from WinXX.
- It does NOT follow the rule that requests to the wins server always have
- rec_des true. See for example name releases and refreshes
-**************************************************************************/
-
-static struct packet_struct *create_and_init_netbios_packet(struct nmb_name *nmbname,
- BOOL bcast, BOOL rec_des,
- struct in_addr to_ip)
-{
- struct packet_struct *packet = NULL;
- struct nmb_packet *nmb = NULL;
-
- /* Allocate the packet_struct we will return. */
- if((packet = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)
- {
- DEBUG(0,("create_and_init_netbios_packet: malloc fail (1) for packet struct.\n"));
- return NULL;
- }
-
- memset((char *)packet,'\0',sizeof(*packet));
-
- nmb = &packet->packet.nmb;
-
- nmb->header.name_trn_id = generate_name_trn_id();
- nmb->header.response = False;
- nmb->header.nm_flags.recursion_desired = rec_des;
- nmb->header.nm_flags.recursion_available = False;
- nmb->header.nm_flags.trunc = False;
- nmb->header.nm_flags.authoritative = False;
- nmb->header.nm_flags.bcast = bcast;
-
- nmb->header.rcode = 0;
- nmb->header.qdcount = 1;
- nmb->header.ancount = 0;
- nmb->header.nscount = 0;
-
- nmb->question.question_name = *nmbname;
- nmb->question.question_type = QUESTION_TYPE_NB_QUERY;
- nmb->question.question_class = QUESTION_CLASS_IN;
-
- packet->ip = to_ip;
- packet->port = NMB_PORT;
- packet->fd = ClientNMB;
- packet->timestamp = time(NULL);
- packet->packet_type = NMB_PACKET;
- packet->locked = False;
-
- return packet; /* Caller must free. */
-}
-
-/***************************************************************************
- Sets up the common elements of register, refresh or release packet.
-**************************************************************************/
-
-static BOOL create_and_init_additional_record(struct packet_struct *packet,
- uint16 nb_flags,
- struct in_addr *register_ip)
-{
- struct nmb_packet *nmb = &packet->packet.nmb;
-
- if((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL) {
- DEBUG(0,("initiate_name_register_packet: malloc fail for additional record.\n"));
- return False;
- }
-
- memset((char *)nmb->additional,'\0',sizeof(struct res_rec));
-
- nmb->additional->rr_name = nmb->question.question_name;
- nmb->additional->rr_type = RR_TYPE_NB;
- nmb->additional->rr_class = RR_CLASS_IN;
-
- /* See RFC 1002, sections 5.1.1.1, 5.1.1.2 and 5.1.1.3 */
- if (nmb->header.nm_flags.bcast)
- nmb->additional->ttl = PERMANENT_TTL;
- else
- nmb->additional->ttl = lp_max_ttl();
-
- nmb->additional->rdlength = 6;
-
- set_nb_flags(nmb->additional->rdata,nb_flags);
-
- /* Set the address for the name we are registering. */
- putip(&nmb->additional->rdata[2], register_ip);
-
- /*
- it turns out that Jeremys code was correct, we are supposed
- to send registrations from the IP we are registering. The
- trick is what to do on timeouts! When we send on a
- non-routable IP then the reply will timeout, and we should
- treat this as success, not failure. That means we go into
- our standard refresh cycle for that name which copes nicely
- with disconnected networks.
- */
- packet->fd = find_subnet_fd_for_address(*register_ip);
-
- return True;
-}
-
-/***************************************************************************
- Sends out a name query.
-**************************************************************************/
-
-static BOOL initiate_name_query_packet( struct packet_struct *packet)
-{
- struct nmb_packet *nmb = NULL;
-
- nmb = &packet->packet.nmb;
-
- nmb->header.opcode = NMB_NAME_QUERY_OPCODE;
- nmb->header.arcount = 0;
-
- nmb->header.nm_flags.recursion_desired = True;
-
- DEBUG(4,("initiate_name_query_packet: sending query for name %s (bcast=%s) to IP %s\n",
- nmb_namestr(&nmb->question.question_name),
- BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip)));
-
- return send_netbios_packet( packet );
-}
-
-/***************************************************************************
- Sends out a name query - from a WINS server.
-**************************************************************************/
-
-static BOOL initiate_name_query_packet_from_wins_server( struct packet_struct *packet)
-{
- struct nmb_packet *nmb = NULL;
-
- nmb = &packet->packet.nmb;
-
- nmb->header.opcode = NMB_NAME_QUERY_OPCODE;
- nmb->header.arcount = 0;
-
- nmb->header.nm_flags.recursion_desired = False;
-
- DEBUG(4,("initiate_name_query_packet_from_wins_server: sending query for name %s (bcast=%s) to IP %s\n",
- nmb_namestr(&nmb->question.question_name),
- BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip)));
-
- return send_netbios_packet( packet );
-}
-
-/***************************************************************************
- Sends out a name register.
-**************************************************************************/
-
-static BOOL initiate_name_register_packet( struct packet_struct *packet,
- uint16 nb_flags, struct in_addr *register_ip)
-{
- struct nmb_packet *nmb = &packet->packet.nmb;
-
- nmb->header.opcode = NMB_NAME_REG_OPCODE;
- nmb->header.arcount = 1;
-
- nmb->header.nm_flags.recursion_desired = True;
-
- if(create_and_init_additional_record(packet, nb_flags, register_ip) == False)
- return False;
-
- DEBUG(4,("initiate_name_register_packet: sending registration for name %s (bcast=%s) to IP %s\n",
- nmb_namestr(&nmb->additional->rr_name),
- BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip)));
-
- return send_netbios_packet( packet );
-}
-
-/***************************************************************************
- Sends out a multihomed name register.
-**************************************************************************/
-
-static BOOL initiate_multihomed_name_register_packet(struct packet_struct *packet,
- uint16 nb_flags, struct in_addr *register_ip)
-{
- struct nmb_packet *nmb = &packet->packet.nmb;
- fstring second_ip_buf;
-
- fstrcpy(second_ip_buf, inet_ntoa(packet->ip));
-
- nmb->header.opcode = NMB_NAME_MULTIHOMED_REG_OPCODE;
- nmb->header.arcount = 1;
-
- nmb->header.nm_flags.recursion_desired = True;
-
- if(create_and_init_additional_record(packet, nb_flags, register_ip) == False)
- return False;
-
- DEBUG(4,("initiate_multihomed_name_register_packet: sending registration \
-for name %s IP %s (bcast=%s) to IP %s\n",
- nmb_namestr(&nmb->additional->rr_name), inet_ntoa(*register_ip),
- BOOLSTR(nmb->header.nm_flags.bcast), second_ip_buf ));
-
- return send_netbios_packet( packet );
-}
-
-/***************************************************************************
- Sends out a name refresh.
-**************************************************************************/
-
-static BOOL initiate_name_refresh_packet( struct packet_struct *packet,
- uint16 nb_flags, struct in_addr *refresh_ip)
-{
- struct nmb_packet *nmb = &packet->packet.nmb;
-
- nmb->header.opcode = NMB_NAME_REFRESH_OPCODE_8;
- nmb->header.arcount = 1;
-
- nmb->header.nm_flags.recursion_desired = False;
-
- if(create_and_init_additional_record(packet, nb_flags, refresh_ip) == False)
- return False;
-
- DEBUG(4,("initiate_name_refresh_packet: sending refresh for name %s (bcast=%s) to IP %s\n",
- nmb_namestr(&nmb->additional->rr_name),
- BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip)));
-
- return send_netbios_packet( packet );
-}
-
-/***************************************************************************
- Sends out a name release.
-**************************************************************************/
-
-static BOOL initiate_name_release_packet( struct packet_struct *packet,
- uint16 nb_flags, struct in_addr *release_ip)
-{
- struct nmb_packet *nmb = &packet->packet.nmb;
-
- nmb->header.opcode = NMB_NAME_RELEASE_OPCODE;
- nmb->header.arcount = 1;
-
- nmb->header.nm_flags.recursion_desired = False;
-
- if(create_and_init_additional_record(packet, nb_flags, release_ip) == False)
- return False;
-
- DEBUG(4,("initiate_name_release_packet: sending release for name %s (bcast=%s) to IP %s\n",
- nmb_namestr(&nmb->additional->rr_name),
- BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip)));
-
- return send_netbios_packet( packet );
-}
-
-/***************************************************************************
- Sends out a node status.
-**************************************************************************/
-
-static BOOL initiate_node_status_packet( struct packet_struct *packet )
-{
- struct nmb_packet *nmb = &packet->packet.nmb;
-
- nmb->header.opcode = NMB_NAME_QUERY_OPCODE;
- nmb->header.arcount = 0;
-
- nmb->header.nm_flags.recursion_desired = False;
-
- nmb->question.question_type = QUESTION_TYPE_NB_STATUS;
-
- DEBUG(4,("initiate_node_status_packet: sending node status request for name %s to IP %s\n",
- nmb_namestr(&nmb->question.question_name),
- inet_ntoa(packet->ip)));
-
- return send_netbios_packet( packet );
-}
-
-/****************************************************************************
- Simplification functions for queuing standard packets.
- These should be the only publicly callable functions for sending
- out packets.
-****************************************************************************/
-
-/****************************************************************************
- Assertion - we should never be sending nmbd packets on the remote
- broadcast subnet.
-****************************************************************************/
-
-static BOOL assert_check_subnet(struct subnet_record *subrec)
-{
- if( subrec == remote_broadcast_subnet)
- {
- DEBUG(0,("assert_check_subnet: Attempt to send packet on remote broadcast subnet. \
-This is a bug.\n"));
- return True;
- }
- return False;
-}
-
-/****************************************************************************
- Queue a register name packet to the broadcast address of a subnet.
-****************************************************************************/
-
-struct response_record *queue_register_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- register_name_success_function success_fn,
- register_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname,
- uint16 nb_flags)
-{
- struct packet_struct *p;
- struct response_record *rrec;
-
- if(assert_check_subnet(subrec))
- return NULL;
-
- /* note that all name registration requests have RD set (rfc1002 -
- section 4.2.2 */
- if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), True,
- subrec->bcast_ip)) == NULL)
- return NULL;
-
- if(initiate_name_register_packet( p, nb_flags,
- iface_ip(subrec->bcast_ip)) == False)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- if((rrec = make_response_record(subrec, /* subnet record. */
- p, /* packet we sent. */
- resp_fn, /* function to call on response. */
- timeout_fn, /* function to call on timeout. */
- (success_function)success_fn, /* function to call on operation success. */
- (fail_function)fail_fn, /* function to call on operation fail. */
- userdata)) == NULL)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- return rrec;
-}
-
-
-/****************************************************************************
- Queue a refresh name packet to the broadcast address of a subnet.
-****************************************************************************/
-void queue_wins_refresh(struct nmb_name *nmbname,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- uint16 nb_flags,
- struct in_addr refresh_ip,
- const char *tag)
-{
- struct packet_struct *p;
- struct response_record *rrec;
- struct in_addr wins_ip;
- struct userdata_struct *userdata;
- fstring ip_str;
-
- wins_ip = wins_srv_ip_tag(tag, refresh_ip);
-
- if ((p = create_and_init_netbios_packet(nmbname, False, False, wins_ip)) == NULL) {
- return;
- }
-
- if (!initiate_name_refresh_packet(p, nb_flags, &refresh_ip)) {
- p->locked = False;
- free_packet(p);
- return;
- }
-
- fstrcpy(ip_str, inet_ntoa(refresh_ip));
-
- DEBUG(6,("Refreshing name %s IP %s with WINS server %s using tag '%s'\n",
- nmb_namestr(nmbname), ip_str, inet_ntoa(wins_ip), tag));
-
- userdata = (struct userdata_struct *)malloc(sizeof(*userdata) + strlen(tag) + 1);
- if (!userdata) {
- DEBUG(0,("Failed to allocate userdata structure!\n"));
- return;
- }
- ZERO_STRUCTP(userdata);
- userdata->userdata_len = strlen(tag) + 1;
- strlcpy(userdata->data, tag, userdata->userdata_len);
-
- if ((rrec = make_response_record(unicast_subnet,
- p,
- resp_fn, timeout_fn,
- NULL,
- NULL,
- userdata)) == NULL) {
- p->locked = False;
- free_packet(p);
- return;
- }
-
- free(userdata);
-
- /* we don't want to repeat refresh packets */
- rrec->repeat_count = 0;
-}
-
-
-/****************************************************************************
- Queue a multihomed register name packet to a given WINS server IP
-****************************************************************************/
-
-struct response_record *queue_register_multihomed_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- register_name_success_function success_fn,
- register_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname,
- uint16 nb_flags,
- struct in_addr register_ip,
- struct in_addr wins_ip)
-{
- struct packet_struct *p;
- struct response_record *rrec;
- BOOL ret;
-
- /* Sanity check. */
- if(subrec != unicast_subnet) {
- DEBUG(0,("queue_register_multihomed_name: should only be done on \
-unicast subnet. subnet is %s\n.", subrec->subnet_name ));
- return NULL;
- }
-
- if(assert_check_subnet(subrec))
- return NULL;
-
- if ((p = create_and_init_netbios_packet(nmbname, False, True, wins_ip)) == NULL)
- return NULL;
-
- if (nb_flags & NB_GROUP)
- ret = initiate_name_register_packet( p, nb_flags, &register_ip);
- else
- ret = initiate_multihomed_name_register_packet(p, nb_flags, &register_ip);
-
- if (ret == False) {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- if ((rrec = make_response_record(subrec, /* subnet record. */
- p, /* packet we sent. */
- resp_fn, /* function to call on response. */
- timeout_fn, /* function to call on timeout. */
- (success_function)success_fn, /* function to call on operation success. */
- (fail_function)fail_fn, /* function to call on operation fail. */
- userdata)) == NULL) {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- return rrec;
-}
-
-/****************************************************************************
- Queue a release name packet to the broadcast address of a subnet.
-****************************************************************************/
-
-struct response_record *queue_release_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- release_name_success_function success_fn,
- release_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname,
- uint16 nb_flags,
- struct in_addr release_ip,
- struct in_addr dest_ip)
-{
- struct packet_struct *p;
- struct response_record *rrec;
-
- if(assert_check_subnet(subrec))
- return NULL;
-
- if ((p = create_and_init_netbios_packet(nmbname, (subrec != unicast_subnet), False,
- dest_ip)) == NULL)
- return NULL;
-
- if(initiate_name_release_packet( p, nb_flags, &release_ip) == False)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- if((rrec = make_response_record(subrec, /* subnet record. */
- p, /* packet we sent. */
- resp_fn, /* function to call on response. */
- timeout_fn, /* function to call on timeout. */
- (success_function)success_fn, /* function to call on operation success. */
- (fail_function)fail_fn, /* function to call on operation fail. */
- userdata)) == NULL)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- /*
- * For a broadcast release packet, only send once.
- * This will cause us to remove the name asap. JRA.
- */
-
- if (subrec != unicast_subnet) {
- rrec->repeat_count = 0;
- rrec->repeat_time = 0;
- }
-
- return rrec;
-}
-
-/****************************************************************************
- Queue a query name packet to the broadcast address of a subnet.
-****************************************************************************/
-
-struct response_record *queue_query_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- query_name_success_function success_fn,
- query_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname)
-{
- struct packet_struct *p;
- struct response_record *rrec;
- struct in_addr to_ip;
-
- if(assert_check_subnet(subrec))
- return NULL;
-
- to_ip = subrec->bcast_ip;
-
- /* queries to the WINS server turn up here as queries to IP 0.0.0.0
- These need to be handled a bit differently */
- if (subrec->type == UNICAST_SUBNET && is_zero_ip(to_ip)) {
- /* what we really need to do is loop over each of our wins
- * servers and wins server tags here, but that just doesn't
- * fit our architecture at the moment (userdata may already
- * be used when we get here). For now we just query the first
- * active wins server on the first tag. */
- char **tags = wins_srv_tags();
- if (!tags) {
- return NULL;
- }
- to_ip = wins_srv_ip_tag(tags[0], to_ip);
- wins_srv_tags_free(tags);
- }
-
- if(( p = create_and_init_netbios_packet(nmbname,
- (subrec != unicast_subnet),
- (subrec == unicast_subnet),
- to_ip)) == NULL)
- return NULL;
-
- if(lp_bind_interfaces_only()) {
- int i;
-
- DEBUG(10,("queue_query_name: bind_interfaces_only is set, looking for suitable source IP\n"));
- for(i = 0; i < iface_count(); i++) {
- struct in_addr *ifip = iface_n_ip(i);
-
- if(ifip == NULL) {
- DEBUG(0,("queue_query_name: interface %d has NULL IP address !\n", i));
- continue;
- }
-
- if (ip_equal(*ifip,loopback_ip)) {
- DEBUG(5,("queue_query_name: ignoring loopback interface (%d)\n", i));
- continue;
- }
-
- DEBUG(10,("queue_query_name: using source IP %s\n",inet_ntoa(*ifip)));
- p->fd = find_subnet_fd_for_address( *ifip );
- break;
- }
- }
-
- if(initiate_name_query_packet( p ) == False) {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- if((rrec = make_response_record(subrec, /* subnet record. */
- p, /* packet we sent. */
- resp_fn, /* function to call on response. */
- timeout_fn, /* function to call on timeout. */
- (success_function)success_fn, /* function to call on operation success. */
- (fail_function)fail_fn, /* function to call on operation fail. */
- userdata)) == NULL)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- return rrec;
-}
-
-/****************************************************************************
- Queue a query name packet to a given address from the WINS subnet.
-****************************************************************************/
-
-struct response_record *queue_query_name_from_wins_server( struct in_addr to_ip,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- query_name_success_function success_fn,
- query_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname)
-{
- struct packet_struct *p;
- struct response_record *rrec;
-
- if ((p = create_and_init_netbios_packet(nmbname, False, False, to_ip)) == NULL)
- return NULL;
-
- if(initiate_name_query_packet_from_wins_server( p ) == False)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- if((rrec = make_response_record(wins_server_subnet, /* subnet record. */
- p, /* packet we sent. */
- resp_fn, /* function to call on response. */
- timeout_fn, /* function to call on timeout. */
- (success_function)success_fn, /* function to call on operation success. */
- (fail_function)fail_fn, /* function to call on operation fail. */
- userdata)) == NULL)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- return rrec;
-}
-
-/****************************************************************************
- Queue a node status packet to a given name and address.
-****************************************************************************/
-
-struct response_record *queue_node_status( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- node_status_success_function success_fn,
- node_status_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname,
- struct in_addr send_ip)
-{
- struct packet_struct *p;
- struct response_record *rrec;
-
- /* Sanity check. */
- if(subrec != unicast_subnet)
- {
- DEBUG(0,("queue_register_multihomed_name: should only be done on \
-unicast subnet. subnet is %s\n.", subrec->subnet_name ));
- return NULL;
- }
-
- if(assert_check_subnet(subrec))
- return NULL;
-
- if(( p = create_and_init_netbios_packet(nmbname, False, False,
- send_ip)) == NULL)
- return NULL;
-
- if(initiate_node_status_packet(p) == False)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- if((rrec = make_response_record(subrec, /* subnet record. */
- p, /* packet we sent. */
- resp_fn, /* function to call on response. */
- timeout_fn, /* function to call on timeout. */
- (success_function)success_fn, /* function to call on operation success. */
- (fail_function)fail_fn, /* function to call on operation fail. */
- userdata)) == NULL)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- return rrec;
-}
-
-/****************************************************************************
- Reply to a netbios name packet. see rfc1002.txt
-****************************************************************************/
-
-void reply_netbios_packet(struct packet_struct *orig_packet,
- int rcode, enum netbios_reply_type_code rcv_code, int opcode,
- int ttl, char *data,int len)
-{
- struct packet_struct packet;
- struct nmb_packet *nmb = NULL;
- struct res_rec answers;
- struct nmb_packet *orig_nmb = &orig_packet->packet.nmb;
- BOOL loopback_this_packet = False;
- const char *packet_type = "unknown";
-
- /* Check if we are sending to or from ourselves. */
- if(ismyip(orig_packet->ip) && (orig_packet->port == global_nmb_port))
- loopback_this_packet = True;
-
- nmb = &packet.packet.nmb;
-
- /* Do a partial copy of the packet. We clear the locked flag and
- the resource record pointers. */
- packet = *orig_packet; /* Full structure copy. */
- packet.locked = False;
- nmb->answers = NULL;
- nmb->nsrecs = NULL;
- nmb->additional = NULL;
-
- switch (rcv_code)
- {
- case NMB_STATUS:
- {
- packet_type = "nmb_status";
- nmb->header.nm_flags.recursion_desired = False;
- nmb->header.nm_flags.recursion_available = False;
- break;
- }
- case NMB_QUERY:
- {
- packet_type = "nmb_query";
- nmb->header.nm_flags.recursion_desired = True;
- nmb->header.nm_flags.recursion_available = True;
- break;
- }
- case NMB_REG:
- case NMB_REG_REFRESH:
- {
- packet_type = "nmb_reg";
- nmb->header.nm_flags.recursion_desired = True;
- nmb->header.nm_flags.recursion_available = True;
- break;
- }
- case NMB_REL:
- {
- packet_type = "nmb_rel";
- nmb->header.nm_flags.recursion_desired = False;
- nmb->header.nm_flags.recursion_available = False;
- break;
- }
- case NMB_WAIT_ACK:
- {
- packet_type = "nmb_wack";
- nmb->header.nm_flags.recursion_desired = False;
- nmb->header.nm_flags.recursion_available = False;
- break;
- }
- case WINS_REG:
- {
- packet_type = "wins_reg";
- nmb->header.nm_flags.recursion_desired = True;
- nmb->header.nm_flags.recursion_available = True;
- break;
- }
- case WINS_QUERY:
- {
- packet_type = "wins_query";
- nmb->header.nm_flags.recursion_desired = True;
- nmb->header.nm_flags.recursion_available = True;
- break;
- }
-
- default:
- {
- DEBUG(0,("reply_netbios_packet: Unknown packet type: %s %s to ip %s\n",
- packet_type, nmb_namestr(&orig_nmb->question.question_name),
- inet_ntoa(packet.ip)));
-
- return;
- }
- }
-
- DEBUG(4,("reply_netbios_packet: sending a reply of packet type: %s %s to ip %s \
-for id %hu\n",
- packet_type, nmb_namestr(&orig_nmb->question.question_name),
- inet_ntoa(packet.ip), orig_nmb->header.name_trn_id));
-
- nmb->header.name_trn_id = orig_nmb->header.name_trn_id;
- nmb->header.opcode = opcode;
- nmb->header.response = True;
- nmb->header.nm_flags.bcast = False;
- nmb->header.nm_flags.trunc = False;
- nmb->header.nm_flags.authoritative = True;
-
- nmb->header.rcode = rcode;
- nmb->header.qdcount = 0;
- nmb->header.ancount = 1;
- nmb->header.nscount = 0;
- nmb->header.arcount = 0;
-
- memset((char*)&nmb->question,'\0',sizeof(nmb->question));
-
- nmb->answers = &answers;
- memset((char*)nmb->answers,'\0',sizeof(*nmb->answers));
-
- nmb->answers->rr_name = orig_nmb->question.question_name;
- nmb->answers->rr_type = orig_nmb->question.question_type;
- nmb->answers->rr_class = orig_nmb->question.question_class;
- nmb->answers->ttl = ttl;
-
- if (data && len)
- {
- nmb->answers->rdlength = len;
- memcpy(nmb->answers->rdata, data, len);
- }
-
- packet.packet_type = NMB_PACKET;
- /* Ensure we send out on the same fd that the original
- packet came in on to give the correct source IP address. */
- packet.fd = orig_packet->fd;
- packet.timestamp = time(NULL);
-
- debug_nmb_packet(&packet);
-
- if(loopback_this_packet)
- {
- struct packet_struct *lo_packet;
- DEBUG(5,("reply_netbios_packet: sending packet to ourselves.\n"));
- if((lo_packet = copy_packet(&packet)) == NULL)
- return;
- queue_packet(lo_packet);
- }
- else if (!send_packet(&packet))
- {
- DEBUG(0,("reply_netbios_packet: send_packet to IP %s port %d failed\n",
- inet_ntoa(packet.ip),packet.port));
- }
-}
-
-/*******************************************************************
- Queue a packet into a packet queue
-******************************************************************/
-static void queue_packet(struct packet_struct *packet)
-{
- struct packet_struct *p;
-
- if (!packet_queue)
- {
- packet->prev = NULL;
- packet->next = NULL;
- packet_queue = packet;
- return;
- }
-
- /* find the bottom */
- for (p=packet_queue;p->next;p=p->next)
- ;
-
- p->next = packet;
- packet->next = NULL;
- packet->prev = p;
-}
-
-/****************************************************************************
- Try and find a matching subnet record for a datagram port 138 packet.
-****************************************************************************/
-
-static struct subnet_record *find_subnet_for_dgram_browse_packet(struct packet_struct *p)
-{
- struct subnet_record *subrec;
-
- /* Go through all the broadcast subnets and see if the mask matches. */
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip))
- return subrec;
- }
-
- /* If the subnet record is the remote announce broadcast subnet,
- hack it here to be the first subnet. This is really gross and
- is needed due to people turning on port 137/138 broadcast
- forwarding on their routers. May fire and brimstone rain
- down upon them...
- */
-
- return FIRST_SUBNET;
-}
-
-/****************************************************************************
-Dispatch a browse frame from port 138 to the correct processing function.
-****************************************************************************/
-static void process_browse_packet(struct packet_struct *p, char *buf,int len)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int command = CVAL(buf,0);
- struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p);
-
- /* Drop the packet if it's a different NetBIOS scope, or
- the source is from one of our names. */
-
- if (!strequal(dgram->dest_name.scope, lp_netbios_scope()))
- {
- DEBUG(7,("process_browse_packet: Discarding datagram from IP %s. Scope (%s) \
-mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, lp_netbios_scope()));
- return;
- }
-
- if (is_myname(dgram->source_name.name))
- {
- DEBUG(0,("process_browse_packet: Discarding datagram from IP %s. Source name \
-%s is one of our names !\n", inet_ntoa(p->ip), nmb_namestr(&dgram->source_name)));
- return;
- }
-
- switch (command)
- {
- case ANN_HostAnnouncement:
- {
- debug_browse_data(buf, len);
- process_host_announce(subrec, p, buf+1);
- break;
- }
- case ANN_DomainAnnouncement:
- {
- debug_browse_data(buf, len);
- process_workgroup_announce(subrec, p, buf+1);
- break;
- }
- case ANN_LocalMasterAnnouncement:
- {
- debug_browse_data(buf, len);
- process_local_master_announce(subrec, p, buf+1);
- break;
- }
- case ANN_AnnouncementRequest:
- {
- debug_browse_data(buf, len);
- process_announce_request(subrec, p, buf+1);
- break;
- }
- case ANN_Election:
- {
- debug_browse_data(buf, len);
- process_election(subrec, p, buf+1);
- break;
- }
- case ANN_GetBackupListReq:
- {
- debug_browse_data(buf, len);
- process_get_backup_list_request(subrec, p, buf+1);
- break;
- }
- case ANN_GetBackupListResp:
- {
- debug_browse_data(buf, len);
- /* We never send ANN_GetBackupListReq so we
- should never get these. */
- DEBUG(0,("process_browse_packet: Discarding GetBackupListResponse \
-packet from %s IP %s\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip)));
- break;
- }
- case ANN_ResetBrowserState:
- {
- debug_browse_data(buf, len);
- process_reset_browser(subrec, p, buf+1);
- break;
- }
- case ANN_MasterAnnouncement:
- {
- /* Master browser datagrams must be processed
- on the unicast subnet. */
- subrec = unicast_subnet;
-
- debug_browse_data(buf, len);
- process_master_browser_announce(subrec, p, buf+1);
- break;
- }
- case ANN_BecomeBackup:
- {
- /*
- * We don't currently implement this. Log it just in case.
- */
- debug_browse_data(buf, len);
- DEBUG(10,("process_browse_packet: On subnet %s ignoring browse packet \
-command ANN_BecomeBackup from %s IP %s to %s\n",
- subrec->subnet_name, nmb_namestr(&dgram->source_name),
- inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));
- break;
- }
- default:
- {
- debug_browse_data(buf, len);
- DEBUG(0,("process_browse_packet: On subnet %s ignoring browse packet \
-command code %d from %s IP %s to %s\n",
- subrec->subnet_name, command, nmb_namestr(&dgram->source_name),
- inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));
- }
- }
-}
-
-/****************************************************************************
- Dispatch a LanMan browse frame from port 138 to the correct processing function.
-****************************************************************************/
-static void process_lanman_packet(struct packet_struct *p, char *buf,int len)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int command = SVAL(buf,0);
- struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p);
-
- /* Drop the packet if it's a different NetBIOS scope, or
- the source is from one of our names. */
-
- if (!strequal(dgram->dest_name.scope, lp_netbios_scope()))
- {
- DEBUG(7,("process_lanman_packet: Discarding datagram from IP %s. Scope (%s) \
-mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, lp_netbios_scope()));
- return;
- }
-
- if (is_myname(dgram->source_name.name))
- {
- DEBUG(0,("process_lanman_packet: Discarding datagram from IP %s. Source name \
-%s is one of our names !\n", inet_ntoa(p->ip), nmb_namestr(&dgram->source_name)));
- return;
- }
-
- switch (command)
- {
- case ANN_HostAnnouncement:
- {
- debug_browse_data(buf, len);
- process_lm_host_announce(subrec, p, buf+1);
- break;
- }
- case ANN_AnnouncementRequest:
- {
- process_lm_announce_request(subrec, p, buf+1);
- break;
- }
- default:
- {
- DEBUG(0,("process_lanman_packet: On subnet %s ignoring browse packet \
-command code %d from %s IP %s to %s\n",
- subrec->subnet_name, command, nmb_namestr(&dgram->source_name),
- inet_ntoa(p->ip), nmb_namestr(&dgram->dest_name)));
- }
- }
-}
-
-/****************************************************************************
- Determine if a packet is for us on port 138. Note that to have any chance of
- being efficient we need to drop as many packets as possible at this
- stage as subsequent processing is expensive.
-****************************************************************************/
-
-static BOOL listening(struct packet_struct *p,struct nmb_name *nbname)
-{
- struct subnet_record *subrec = NULL;
-
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip))
- break;
- }
-
- if(subrec == NULL)
- subrec = unicast_subnet;
-
- return (find_name_on_subnet(subrec, nbname, FIND_SELF_NAME) != NULL);
-}
-
-/****************************************************************************
- Process udp 138 datagrams
-****************************************************************************/
-static void process_dgram(struct packet_struct *p)
-{
- char *buf;
- char *buf2;
- int len;
- struct dgram_packet *dgram = &p->packet.dgram;
-
- /* If we aren't listening to the destination name then ignore the packet */
- if (!listening(p,&dgram->dest_name))
- {
- unexpected_packet(p);
- DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from %s\n",
- nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip)));
- return;
- }
-
- if (dgram->header.msg_type != 0x10 &&
- dgram->header.msg_type != 0x11 &&
- dgram->header.msg_type != 0x12)
- {
- unexpected_packet(p);
- /* Don't process error packets etc yet */
- DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from IP %s as it is \
-an error packet of type %x\n",
- nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip), dgram->header.msg_type));
- return;
- }
-
- buf = &dgram->data[0];
- buf -= 4; /* XXXX for the pseudo tcp length -
- someday I need to get rid of this */
-
- if (CVAL(buf,smb_com) != SMBtrans)
- return;
-
- len = SVAL(buf,smb_vwv11);
- buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
-
- if (len <= 0)
- return;
-
- if (buf2 + len > buf + sizeof(dgram->data)) {
- DEBUG(2,("process_dgram: datagram from %s to %s IP %s for %s len=%d too long.\n",
- nmb_namestr(&dgram->source_name),nmb_namestr(&dgram->dest_name),
- inet_ntoa(p->ip), smb_buf(buf),len));
- len = (buf + sizeof(dgram->data)) - buf;
- }
-
- DEBUG(4,("process_dgram: datagram from %s to %s IP %s for %s of type %d len=%d\n",
- nmb_namestr(&dgram->source_name),nmb_namestr(&dgram->dest_name),
- inet_ntoa(p->ip), smb_buf(buf),CVAL(buf2,0),len));
-
-
- /* Datagram packet received for the browser mailslot */
- if (strequal(smb_buf(buf),BROWSE_MAILSLOT))
- {
- process_browse_packet(p,buf2,len);
- return;
- }
-
- /* Datagram packet received for the LAN Manager mailslot */
- if (strequal(smb_buf(buf),LANMAN_MAILSLOT)) {
- process_lanman_packet(p,buf2,len);
- return;
- }
-
- /* Datagram packet received for the domain logon mailslot */
- if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT))
- {
- process_logon_packet(p,buf2,len,NET_LOGON_MAILSLOT);
- return;
- }
-
- /* Datagram packet received for the NT domain logon mailslot */
- if (strequal(smb_buf(buf),NT_LOGON_MAILSLOT))
- {
- process_logon_packet(p,buf2,len,NT_LOGON_MAILSLOT);
- return;
- }
-
- unexpected_packet(p);
-}
-
-/****************************************************************************
- Validate a response nmb packet.
-****************************************************************************/
-
-static BOOL validate_nmb_response_packet( struct nmb_packet *nmb )
-{
- BOOL ignore = False;
-
- switch (nmb->header.opcode)
- {
- case NMB_NAME_REG_OPCODE:
- case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
- case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
- if (nmb->header.ancount == 0)
- {
- DEBUG(0,("validate_nmb_response_packet: Bad REG/REFRESH Packet. "));
- ignore = True;
- }
- break;
-
- case NMB_NAME_QUERY_OPCODE:
- if ((nmb->header.ancount != 0) && (nmb->header.ancount != 1))
- {
- DEBUG(0,("validate_nmb_response_packet: Bad QUERY Packet. "));
- ignore = True;
- }
- break;
- case NMB_NAME_RELEASE_OPCODE:
- if (nmb->header.ancount == 0)
- {
- DEBUG(0,("validate_nmb_response_packet: Bad RELEASE Packet. "));
- ignore = True;
- }
- break;
- case NMB_WACK_OPCODE:
- /* Check WACK response here. */
- if (nmb->header.ancount != 1)
- {
- DEBUG(0,("validate_nmb_response_packet: Bad WACK Packet. "));
- ignore = True;
- }
- break;
- default:
- DEBUG(0,("validate_nmb_response_packet: Ignoring packet with unknown opcode %d.\n",
- nmb->header.opcode));
- return True;
- }
-
- if(ignore)
- DEBUG(0,("Ignoring response packet with opcode %d.\n", nmb->header.opcode));
-
- return ignore;
-}
-
-/****************************************************************************
- Validate a request nmb packet.
-****************************************************************************/
-
-static BOOL validate_nmb_packet( struct nmb_packet *nmb )
-{
- BOOL ignore = False;
-
- switch (nmb->header.opcode)
- {
- case NMB_NAME_REG_OPCODE:
- case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
- case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
- case NMB_NAME_MULTIHOMED_REG_OPCODE:
- if (nmb->header.qdcount==0 || nmb->header.arcount==0)
- {
- DEBUG(0,("validate_nmb_packet: Bad REG/REFRESH Packet. "));
- ignore = True;
- }
- break;
-
- case NMB_NAME_QUERY_OPCODE:
- if ((nmb->header.qdcount == 0) ||
- ((nmb->question.question_type != QUESTION_TYPE_NB_QUERY) &&
- (nmb->question.question_type != QUESTION_TYPE_NB_STATUS)))
- {
- DEBUG(0,("validate_nmb_packet: Bad QUERY Packet. "));
- ignore = True;
- }
- break;
-
- case NMB_NAME_RELEASE_OPCODE:
- if (nmb->header.qdcount==0 || nmb->header.arcount==0)
- {
- DEBUG(0,("validate_nmb_packet: Bad RELEASE Packet. "));
- ignore = True;
- }
- break;
- default:
- DEBUG(0,("validate_nmb_packet: Ignoring packet with unknown opcode %d.\n",
- nmb->header.opcode));
- return True;
- }
-
- if(ignore)
- DEBUG(0,("validate_nmb_packet: Ignoring request packet with opcode %d.\n", nmb->header.opcode));
-
- return ignore;
-}
-
-/****************************************************************************
- Find a subnet (and potentially a response record) for a packet.
-****************************************************************************/
-
-static struct subnet_record *find_subnet_for_nmb_packet( struct packet_struct *p,
- struct response_record **pprrec)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct response_record *rrec = NULL;
- struct subnet_record *subrec = NULL;
-
- if(pprrec != NULL)
- *pprrec = NULL;
-
- if(nmb->header.response)
- {
- /* It's a response packet. Find a record for it or it's an error. */
-
- rrec = find_response_record( &subrec, nmb->header.name_trn_id);
- if(rrec == NULL)
- {
- DEBUG(3,("find_subnet_for_nmb_packet: response record not found for response id %hu\n",
- nmb->header.name_trn_id));
- unexpected_packet(p);
- return NULL;
- }
-
- if(subrec == NULL)
- {
- DEBUG(0,("find_subnet_for_nmb_packet: subnet record not found for response id %hu\n",
- nmb->header.name_trn_id));
- return NULL;
- }
-
- if(pprrec != NULL)
- *pprrec = rrec;
- return subrec;
- }
-
- /* Try and see what subnet this packet belongs to. */
-
- /* WINS server ? */
- if(packet_is_for_wins_server(p))
- return wins_server_subnet;
-
- /* If it wasn't a broadcast packet then send to the UNICAST subnet. */
- if(nmb->header.nm_flags.bcast == False)
- return unicast_subnet;
-
- /* Go through all the broadcast subnets and see if the mask matches. */
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip))
- return subrec;
- }
-
- /* If none match it must have been a directed broadcast - assign
- the remote_broadcast_subnet. */
- return remote_broadcast_subnet;
-}
-
-/****************************************************************************
- Process a nmb request packet - validate the packet and route it.
-****************************************************************************/
-
-static void process_nmb_request(struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct subnet_record *subrec = NULL;
-
- debug_nmb_packet(p);
-
- /* Ensure we have a good packet. */
- if(validate_nmb_packet(nmb))
- return;
-
- /* Allocate a subnet to this packet - if we cannot - fail. */
- if((subrec = find_subnet_for_nmb_packet(p, NULL))==NULL)
- return;
-
- switch (nmb->header.opcode)
- {
- case NMB_NAME_REG_OPCODE:
- if(subrec == wins_server_subnet)
- wins_process_name_registration_request(subrec, p);
- else
- process_name_registration_request(subrec, p);
- break;
-
- case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
- case NMB_NAME_REFRESH_OPCODE_9:
- if(subrec == wins_server_subnet)
- wins_process_name_refresh_request(subrec, p);
- else
- process_name_refresh_request(subrec, p);
- break;
-
- case NMB_NAME_MULTIHOMED_REG_OPCODE:
- if(subrec == wins_server_subnet)
- wins_process_multihomed_name_registration_request(subrec, p);
- else
- {
- DEBUG(0,("process_nmb_request: Multihomed registration request must be \
-directed at a WINS server.\n"));
- }
- break;
-
- case NMB_NAME_QUERY_OPCODE:
- switch (nmb->question.question_type)
- {
- case QUESTION_TYPE_NB_QUERY:
- {
- if(subrec == wins_server_subnet)
- wins_process_name_query_request(subrec, p);
- else
- process_name_query_request(subrec, p);
- break;
- }
- case QUESTION_TYPE_NB_STATUS:
- {
- if(subrec == wins_server_subnet)
- {
- DEBUG(0,("process_nmb_request: NB_STATUS request directed at WINS server is \
-not allowed.\n"));
- break;
- }
- else
- process_node_status_request(subrec, p);
- break;
- }
- }
- break;
-
- case NMB_NAME_RELEASE_OPCODE:
- if(subrec == wins_server_subnet)
- wins_process_name_release_request(subrec, p);
- else
- process_name_release_request(subrec, p);
- break;
- }
-}
-
-/****************************************************************************
- Process a nmb response packet - validate the packet and route it.
- to either the WINS server or a normal response.
-****************************************************************************/
-
-static void process_nmb_response(struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct subnet_record *subrec = NULL;
- struct response_record *rrec = NULL;
-
- debug_nmb_packet(p);
-
- if(validate_nmb_response_packet(nmb))
- return;
-
- if((subrec = find_subnet_for_nmb_packet(p, &rrec))==NULL)
- return;
-
- if(rrec == NULL)
- {
- DEBUG(0,("process_nmb_response: response packet received but no response record \
-found for id = %hu. Ignoring packet.\n", nmb->header.name_trn_id));
- return;
- }
-
- /* Increment the number of responses received for this record. */
- rrec->num_msgs++;
- /* Ensure we don't re-send the request. */
- rrec->repeat_count = 0;
-
- /* Call the response received function for this packet. */
- (*rrec->resp_fn)(subrec, rrec, p);
-}
-
-
-/*******************************************************************
- Run elements off the packet queue till its empty
-******************************************************************/
-
-void run_packet_queue(void)
-{
- struct packet_struct *p;
-
- while ((p = packet_queue))
- {
- packet_queue = p->next;
- if (packet_queue)
- packet_queue->prev = NULL;
- p->next = p->prev = NULL;
-
- switch (p->packet_type)
- {
- case NMB_PACKET:
- if(p->packet.nmb.header.response)
- process_nmb_response(p);
- else
- process_nmb_request(p);
- break;
-
- case DGRAM_PACKET:
- process_dgram(p);
- break;
- }
- free_packet(p);
- }
-}
-
-/*******************************************************************
- Retransmit or timeout elements from all the outgoing subnet response
- record queues. NOTE that this code must also check the WINS server
- subnet for response records to timeout as the WINS server code
- can send requests to check if a client still owns a name.
- (Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>).
-******************************************************************/
-
-void retransmit_or_expire_response_records(time_t t)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec;
- subrec = get_next_subnet_maybe_unicast_or_wins_server(subrec))
- {
- struct response_record *rrec, *nextrrec;
-
- for (rrec = subrec->responselist; rrec; rrec = nextrrec)
- {
- nextrrec = rrec->next;
-
- if (rrec->repeat_time <= t)
- {
- if (rrec->repeat_count > 0)
- {
- /* Resend while we have a non-zero repeat_count. */
- if(!send_packet(rrec->packet))
- {
- DEBUG(0,("retransmit_or_expire_response_records: Failed to resend packet id %hu \
-to IP %s on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip),
- subrec->subnet_name));
- }
- rrec->repeat_time = t + rrec->repeat_interval;
- rrec->repeat_count--;
- }
- else
- {
- DEBUG(4,("retransmit_or_expire_response_records: timeout for packet id %hu to IP %s \
-on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip),
- subrec->subnet_name));
-
- /*
- * Check the flag in this record to prevent recursion if we end
- * up in this function again via the timeout function call.
- */
-
- if(!rrec->in_expiration_processing)
- {
-
- /*
- * Set the recursion protection flag in this record.
- */
-
- rrec->in_expiration_processing = True;
-
- /* Call the timeout function. This will deal with removing the
- timed out packet. */
- if(rrec->timeout_fn)
- (*rrec->timeout_fn)(subrec, rrec);
- else
- {
- /* We must remove the record ourself if there is
- no timeout function. */
- remove_response_record(subrec, rrec);
- }
- } /* !rrec->in_expitation_processing */
- } /* rrec->repeat_count > 0 */
- } /* rrec->repeat_time <= t */
- } /* end for rrec */
- } /* end for subnet */
-}
-
-/****************************************************************************
- Create an fd_set containing all the sockets in the subnet structures,
- plus the broadcast sockets.
-***************************************************************************/
-
-static BOOL create_listen_fdset(fd_set **ppset, int **psock_array, int *listen_number)
-{
- int *sock_array = NULL;
- struct subnet_record *subrec = NULL;
- int count = 0;
- int num = 0;
- fd_set *pset = (fd_set *)malloc(sizeof(fd_set));
-
- if(pset == NULL)
- {
- DEBUG(0,("create_listen_fdset: malloc fail !\n"));
- return True;
- }
-
- /* Check that we can add all the fd's we need. */
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- count++;
-
- if((count*2) + 2 > FD_SETSIZE)
- {
- DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \
-only use %d.\n", (count*2) + 2, FD_SETSIZE));
- return True;
- }
-
- if((sock_array = (int *)malloc(((count*2) + 2)*sizeof(int))) == NULL)
- {
- DEBUG(0,("create_listen_fdset: malloc fail for socket array.\n"));
- return True;
- }
-
- FD_ZERO(pset);
-
- /* Add in the broadcast socket on 137. */
- FD_SET(ClientNMB,pset);
- sock_array[num++] = ClientNMB;
-
- /* Add in the 137 sockets on all the interfaces. */
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- FD_SET(subrec->nmb_sock,pset);
- sock_array[num++] = subrec->nmb_sock;
- }
-
- /* Add in the broadcast socket on 138. */
- FD_SET(ClientDGRAM,pset);
- sock_array[num++] = ClientDGRAM;
-
- /* Add in the 138 sockets on all the interfaces. */
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- FD_SET(subrec->dgram_sock,pset);
- sock_array[num++] = subrec->dgram_sock;
- }
-
- *listen_number = (count*2) + 2;
-
- SAFE_FREE(*ppset);
- SAFE_FREE(*psock_array);
-
- *ppset = pset;
- *psock_array = sock_array;
-
- return False;
-}
-
-/****************************************************************************
- Listens for NMB or DGRAM packets, and queues them.
- return True if the socket is dead
-***************************************************************************/
-
-BOOL listen_for_packets(BOOL run_election)
-{
- static fd_set *listen_set = NULL;
- static int listen_number = 0;
- static int *sock_array = NULL;
- int i;
-
- fd_set fds;
- int selrtn;
- struct timeval timeout;
-#ifndef SYNC_DNS
- int dns_fd;
-#endif
-
- if(listen_set == NULL || rescan_listen_set)
- {
- if(create_listen_fdset(&listen_set, &sock_array, &listen_number))
- {
- DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n"));
- return True;
- }
- rescan_listen_set = False;
- }
-
- memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set));
-
-#ifndef SYNC_DNS
- dns_fd = asyncdns_fd();
- if (dns_fd != -1) {
- FD_SET(dns_fd, &fds);
- }
-#endif
-
-
- /*
- * During elections and when expecting a netbios response packet we
- * need to send election packets at tighter intervals.
- * Ideally it needs to be the interval (in ms) between time now and
- * the time we are expecting the next netbios packet.
- */
-
- timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP;
- timeout.tv_usec = 0;
-
- /* Prepare for the select - allow certain signals. */
-
- BlockSignals(False, SIGTERM);
-
- selrtn = sys_select(FD_SETSIZE,&fds,NULL,NULL,&timeout);
-
- /* We can only take signals when we are in the select - block them again here. */
-
- BlockSignals(True, SIGTERM);
-
- if(selrtn == -1) {
- return False;
- }
-
-#ifndef SYNC_DNS
- if (dns_fd != -1 && FD_ISSET(dns_fd,&fds)) {
- run_dns_queue();
- }
-#endif
-
- for(i = 0; i < listen_number; i++) {
- if (i < (listen_number/2)) {
- /* Processing a 137 socket. */
- if (FD_ISSET(sock_array[i],&fds)) {
- struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET);
- if (packet) {
- /*
- * If we got a packet on the broadcast socket and interfaces
- * only is set then check it came from one of our local nets.
- */
- if(lp_bind_interfaces_only() && (sock_array[i] == ClientNMB) &&
- (!is_local_net(packet->ip))) {
- DEBUG(7,("discarding nmb packet sent to broadcast socket from %s:%d\n",
- inet_ntoa(packet->ip),packet->port));
- free_packet(packet);
- } else if ((ip_equal(loopback_ip, packet->ip) ||
- ismyip(packet->ip)) && packet->port == global_nmb_port &&
- packet->packet.nmb.header.nm_flags.bcast) {
- DEBUG(7,("discarding own bcast packet from %s:%d\n",
- inet_ntoa(packet->ip),packet->port));
- free_packet(packet);
- } else {
- /* Save the file descriptor this packet came in on. */
- packet->fd = sock_array[i];
- queue_packet(packet);
- }
- }
- }
- } else {
- /* Processing a 138 socket. */
- if (FD_ISSET(sock_array[i],&fds)) {
- struct packet_struct *packet = read_packet(sock_array[i], DGRAM_PACKET);
- if (packet) {
- /*
- * If we got a packet on the broadcast socket and interfaces
- * only is set then check it came from one of our local nets.
- */
- if(lp_bind_interfaces_only() && (sock_array[i] == ClientDGRAM) &&
- (!is_local_net(packet->ip))) {
- DEBUG(7,("discarding dgram packet sent to broadcast socket from %s:%d\n",
- inet_ntoa(packet->ip),packet->port));
- free_packet(packet);
- } else if ((ip_equal(loopback_ip, packet->ip) ||
- ismyip(packet->ip)) && packet->port == DGRAM_PORT) {
- DEBUG(7,("discarding own dgram packet from %s:%d\n",
- inet_ntoa(packet->ip),packet->port));
- free_packet(packet);
- } else {
- /* Save the file descriptor this packet came in on. */
- packet->fd = sock_array[i];
- queue_packet(packet);
- }
- }
- }
- } /* end processing 138 socket. */
- } /* end for */
- return False;
-}
-
-/****************************************************************************
- Construct and send a netbios DGRAM.
-**************************************************************************/
-BOOL send_mailslot(BOOL unique, const char *mailslot,char *buf,int len,
- const char *srcname, int src_type,
- const char *dstname, int dest_type,
- struct in_addr dest_ip,struct in_addr src_ip,
- int dest_port)
-{
- BOOL loopback_this_packet = False;
- struct packet_struct p;
- struct dgram_packet *dgram = &p.packet.dgram;
- char *ptr,*p2;
- char tmp[4];
-
- memset((char *)&p,'\0',sizeof(p));
-
- if(ismyip(dest_ip) && (dest_port == DGRAM_PORT)) /* Only if to DGRAM_PORT */
- loopback_this_packet = True;
-
- /* generate_name_trn_id(); */ /* Not used, so gone, RJS */
-
- /* DIRECT GROUP or UNIQUE datagram. */
- dgram->header.msg_type = unique ? 0x10 : 0x11;
- dgram->header.flags.node_type = M_NODE;
- dgram->header.flags.first = True;
- dgram->header.flags.more = False;
- dgram->header.dgm_id = generate_name_trn_id();
- dgram->header.source_ip = src_ip;
- dgram->header.source_port = DGRAM_PORT;
- dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
- dgram->header.packet_offset = 0;
-
- make_nmb_name(&dgram->source_name,srcname,src_type);
- make_nmb_name(&dgram->dest_name,dstname,dest_type);
-
- ptr = &dgram->data[0];
-
- /* Setup the smb part. */
- ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
- memcpy(tmp,ptr,4);
- set_message(ptr,17,23 + len,True);
- memcpy(ptr,tmp,4);
-
- SCVAL(ptr,smb_com,SMBtrans);
- SSVAL(ptr,smb_vwv1,len);
- SSVAL(ptr,smb_vwv11,len);
- SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
- SSVAL(ptr,smb_vwv13,3);
- SSVAL(ptr,smb_vwv14,1);
- SSVAL(ptr,smb_vwv15,1);
- SSVAL(ptr,smb_vwv16,2);
- p2 = smb_buf(ptr);
- pstrcpy(p2,mailslot);
- p2 = skip_string(p2,1);
-
- memcpy(p2,buf,len);
- p2 += len;
-
- dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
-
- p.ip = dest_ip;
- p.port = dest_port;
- p.fd = find_subnet_mailslot_fd_for_address( src_ip );
- p.timestamp = time(NULL);
- p.packet_type = DGRAM_PACKET;
-
- DEBUG(4,("send_mailslot: Sending to mailslot %s from %s IP %s ", mailslot,
- nmb_namestr(&dgram->source_name), inet_ntoa(src_ip)));
- DEBUG(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), inet_ntoa(dest_ip)));
-
- debug_browse_data(buf, len);
-
- if(loopback_this_packet)
- {
- struct packet_struct *lo_packet = NULL;
- DEBUG(5,("send_mailslot: sending packet to ourselves.\n"));
- if((lo_packet = copy_packet(&p)) == NULL)
- return False;
- queue_packet(lo_packet);
- return True;
- }
- else
- return(send_packet(&p));
-}
diff --git a/source4/nmbd/nmbd_processlogon.c b/source4/nmbd/nmbd_processlogon.c
deleted file mode 100644
index 1fcfd11a3e..0000000000
--- a/source4/nmbd/nmbd_processlogon.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
- Copyright (C) Jim McDonough 2002
- Copyright (C) Anthony Liguori 2002
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Revision History:
-
-*/
-
-#include "includes.h"
-
-struct sam_database_info {
- uint32 index;
- uint32 serial_lo, serial_hi;
- uint32 date_lo, date_hi;
-};
-
-/****************************************************************************
-Send a message to smbd to do a sam delta sync
-**************************************************************************/
-static void send_repl_message(uint32 low_serial)
-{
- TDB_CONTEXT *tdb;
-
- tdb = tdb_open_log(lock_path("connections.tdb"), 0,
- TDB_DEFAULT, O_RDONLY, 0);
-
- if (!tdb) {
- DEBUG(3, ("send_repl_message(): failed to open connections "
- "database\n"));
- return;
- }
-
- DEBUG(3, ("sending replication message, serial = 0x%04x\n",
- low_serial));
-
- message_send_all(tdb, MSG_SMB_SAM_REPL, &low_serial,
- sizeof(low_serial), False, NULL);
-
- tdb_close(tdb);
-}
-
-/****************************************************************************
-Process a domain logon packet
-**************************************************************************/
-
-void process_logon_packet(struct packet_struct *p, char *buf,int len,
- const char *mailslot)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- pstring my_name;
- fstring reply_name;
- pstring outbuf;
- int code;
- uint16 token = 0;
- uint32 ntversion = 0;
- uint16 lmnttoken = 0;
- uint16 lm20token = 0;
- uint32 domainsidsize;
- BOOL short_request = False;
- char *getdc;
- char *uniuser; /* Unicode user name. */
- pstring ascuser;
- char *unicomp; /* Unicode computer name. */
-
- memset(outbuf, 0, sizeof(outbuf));
-
- if (!lp_domain_logons())
- {
- DEBUG(3,("process_logon_packet: Logon packet received from IP %s and domain \
-logons are not enabled.\n", inet_ntoa(p->ip) ));
- return;
- }
-
- pstrcpy(my_name, lp_netbios_name());
-
- code = SVAL(buf,0);
- DEBUG(1,("process_logon_packet: Logon from %s: code = 0x%x\n", inet_ntoa(p->ip), code));
-
- switch (code)
- {
- case 0:
- {
- char *q = buf + 2;
- char *machine = q;
- char *user = skip_string(machine,1);
-
- getdc = skip_string(user,1);
- q = skip_string(getdc,1);
- token = SVAL(q,3);
-
- fstrcpy(reply_name,my_name);
-
- DEBUG(3,("process_logon_packet: Domain login request from %s at IP %s user=%s token=%x\n",
- machine,inet_ntoa(p->ip),user,token));
-
- q = outbuf;
- SSVAL(q, 0, 6);
- q += 2;
-
- fstrcpy(reply_name, "\\\\");
- fstrcat(reply_name, my_name);
- fstrcpy(q, reply_name); q = skip_string(q, 1); /* PDC name */
-
- SSVAL(q, 0, token);
- q += 2;
-
- dump_data(4, outbuf, PTR_DIFF(q, outbuf));
-
- send_mailslot(True, getdc,
- outbuf,PTR_DIFF(q,outbuf),
- lp_netbios_name(), 0x0,
- machine,
- dgram->source_name.name_type,
- p->ip, *iface_ip(p->ip), p->port);
- break;
- }
-
- case QUERYFORPDC:
- {
- char *q = buf + 2;
- char *machine = q;
-
- if (!lp_domain_master())
- {
- /* We're not Primary Domain Controller -- ignore this */
- return;
- }
-
- getdc = skip_string(machine,1);
- q = skip_string(getdc,1);
- q = ALIGN2(q, buf);
-
- /* at this point we can work out if this is a W9X or NT style
- request. Experiments show that the difference is wether the
- packet ends here. For a W9X request we now end with a pair of
- bytes (usually 0xFE 0xFF) whereas with NT we have two further
- strings - the following is a simple way of detecting this */
- if (len - PTR_DIFF(q, buf) <= 3) {
- short_request = True;
- } else {
- unicomp = q;
-
- /* A full length (NT style) request */
- q = skip_unibuf(unicomp, PTR_DIFF(buf + len, unicomp));
-
- if (len - PTR_DIFF(q, buf) > 8) {
- /* with NT5 clients we can sometimes
- get additional data - a length specificed string
- containing the domain name, then 16 bytes of
- data (no idea what it is) */
- int dom_len = CVAL(q, 0);
- q++;
- if (dom_len != 0) {
- q += dom_len + 1;
- }
- q += 16;
- }
- ntversion = IVAL(q, 0);
- lmnttoken = SVAL(q, 4);
- lm20token = SVAL(q, 6);
- }
-
- /* Construct reply. */
- q = outbuf;
- SSVAL(q, 0, QUERYFORPDC_R);
- q += 2;
-
- fstrcpy(reply_name,my_name);
- fstrcpy(q, reply_name);
- q = skip_string(q, 1); /* PDC name */
-
- /* PDC and domain name */
- if (!short_request) /* Make a full reply */
- {
- q = ALIGN2(q, outbuf);
-
- q += dos_PutUniCode(q, my_name, sizeof(pstring), True); /* PDC name */
- q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True); /* Domain name*/
- SIVAL(q, 0, 1); /* our nt version */
- SSVAL(q, 4, 0xffff); /* our lmnttoken */
- SSVAL(q, 6, 0xffff); /* our lm20token */
- q += 8;
- }
-
- /* RJS, 21-Feb-2000, we send a short reply if the request was short */
-
- DEBUG(3,("process_logon_packet: GETDC request from %s at IP %s, \
-reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
- machine,inet_ntoa(p->ip), reply_name, lp_workgroup(),
- QUERYFORPDC_R, (uint32)ntversion, (uint32)lmnttoken,
- (uint32)lm20token ));
-
- dump_data(4, outbuf, PTR_DIFF(q, outbuf));
-
- send_mailslot(True, getdc,
- outbuf,PTR_DIFF(q,outbuf),
- lp_netbios_name(), 0x0,
- dgram->source_name.name,
- dgram->source_name.name_type,
- p->ip, *iface_ip(p->ip), p->port);
- return;
- }
-
- case SAMLOGON:
- {
- char *q = buf + 2;
- fstring asccomp;
-
- q += 2;
- unicomp = q;
- uniuser = skip_unibuf(unicomp, PTR_DIFF(buf+len, unicomp));
- getdc = skip_unibuf(uniuser,PTR_DIFF(buf+len, uniuser));
- q = skip_string(getdc,1);
- q += 4; /* Account Control Bits - indicating username type */
- domainsidsize = IVAL(q, 0);
- q += 4;
-
- DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d, len = %d\n", domainsidsize, len));
-
- if (domainsidsize < (len - PTR_DIFF(q, buf)) && (domainsidsize != 0)) {
- q += domainsidsize;
- q = ALIGN4(q, buf);
- }
-
- DEBUG(3,("process_logon_packet: len = %d PTR_DIFF(q, buf) = %d\n", len, PTR_DIFF(q, buf) ));
-
- if (len - PTR_DIFF(q, buf) > 8) {
- /* with NT5 clients we can sometimes
- get additional data - a length specificed string
- containing the domain name, then 16 bytes of
- data (no idea what it is) */
- int dom_len = CVAL(q, 0);
- q++;
- if (dom_len < (len - PTR_DIFF(q, buf)) && (dom_len != 0)) {
- q += dom_len + 1;
- }
- q += 16;
- }
-
- ntversion = IVAL(q, 0);
- lmnttoken = SVAL(q, 4);
- lm20token = SVAL(q, 6);
- q += 8;
-
- DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d ntv %d\n", domainsidsize, ntversion));
-
- /*
- * we respond regadless of whether the machine is in our password
- * database. If it isn't then we let smbd send an appropriate error.
- * Let's ignore the SID.
- */
- pull_ucs2_pstring(ascuser, uniuser);
- pull_ucs2_fstring(asccomp, unicomp);
- DEBUG(3,("process_logon_packet: SAMLOGON user %s\n", ascuser));
-
- fstrcpy(reply_name, "\\\\"); /* Here it wants \\LOGONSERVER. */
- fstrcat(reply_name, my_name);
-
- DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n",
- asccomp,inet_ntoa(p->ip), ascuser, reply_name, lp_workgroup(),
- SAMLOGON_R ,lmnttoken));
-
- /* Construct reply. */
-
- q = outbuf;
- /* we want the simple version unless we are an ADS PDC..which means */
- /* never, at least for now */
- if ((ntversion < 11) || (SEC_ADS != lp_security()) || (ROLE_DOMAIN_PDC != lp_server_role())) {
- if (SVAL(uniuser, 0) == 0) {
- SSVAL(q, 0, SAMLOGON_UNK_R); /* user unknown */
- } else {
- SSVAL(q, 0, SAMLOGON_R);
- }
-
- q += 2;
-
- q += dos_PutUniCode(q, reply_name,sizeof(pstring), True);
- q += dos_PutUniCode(q, ascuser, sizeof(pstring), True);
- q += dos_PutUniCode(q, lp_workgroup(),sizeof(pstring), True);
- }
-#ifdef HAVE_ADS
- else {
- GUID domain_guid;
- pstring domain;
- char *hostname = NULL;
- char *component, *dc, *q1;
- uint8 size;
-
- get_mydomname(domain);
- hostname = get_myname();
-
- if (SVAL(uniuser, 0) == 0) {
- SSVAL(q, 0, SAMLOGON_AD_UNK_R); /* user unknown */
- } else {
- SSVAL(q, 0, SAMLOGON_AD_R);
- }
- q += 2;
-
- SSVAL(q, 0, 0);
- q += 2;
- SIVAL(q, 0, ADS_PDC|ADS_GC|ADS_LDAP|ADS_DS|
- ADS_KDC|ADS_TIMESERV|ADS_CLOSEST|ADS_WRITABLE);
- q += 4;
-
- /* Push Domain GUID */
- if (False == secrets_fetch_domain_guid(domain, &domain_guid)) {
- DEBUG(2, ("Could not fetch DomainGUID for %s\n", domain));
- return;
- }
- memcpy(q, &domain_guid, sizeof(domain_guid));
- q += sizeof(domain_guid);
-
- /* Push domain components */
- dc = domain;
- q1 = q;
- while ((component = strtok(dc, "."))) {
- dc = NULL;
- size = push_ascii(&q[1], component, -1, 0);
- SCVAL(q, 0, size);
- q += (size + 1);
- }
- SCVAL(q, 0, 0); q++;
- SSVAL(q, 0, 0x18c0); /* not sure what this is for, but */
- q += 2; /* it must follow the domain name. */
-
- /* Push dns host name */
- size = push_ascii(&q[1], hostname, -1, 0);
- SCVAL(q, 0, size);
- q += (size + 1);
- SSVAL(q, 0, 0x18c0); /* not sure what this is for, but */
- q += 2; /* it must follow the domain name. */
-
- /* Push NETBIOS of domain */
- size = push_ascii(&q[1], lp_workgroup(), -1, STR_UPPER);
- SCVAL(q, 0, size);
- q += (size + 1);
- SCVAL(q, 0, 0); q++; /* is this a null terminator or empty field */
- /* null terminator would not be needed because size is included */
-
- /* Push NETBIOS of hostname */
- size = push_ascii(&q[1], my_name, -1, 0);
- SCVAL(q, 0, size);
- q += (size + 1);
- SCVAL(q, 0, 0); q++; /* null terminator or empty field? */
-
- /* Push user account */
- size = push_ascii(&q[1], ascuser, -1, 0);
- SCVAL(q, 0, size);
- q += (size + 1);
-
- /* Push 'Default-First-Site-Name' */
- size = push_ascii(&q[1], "Default-First-Site-Name", -1, 0);
- SCVAL(q, 0, size);
- q += (size + 1);
-
- SSVAL(q, 0, 0xc000); /* unknown */
- SCVAL(q, 2, PTR_DIFF(q,q1));
- SCVAL(q, 3, 0x10); /* unknown */
- q += 4;
-
- SIVAL(q, 0, 0x00000002); q += 4; /* unknown */
- SIVAL(q, 0, (iface_ip(p->ip))->s_addr); q += 4;
- SIVAL(q, 0, 0x00000000); q += 4; /* unknown */
- SIVAL(q, 0, 0x00000000); q += 4; /* unknown */
- if (hostname) free(hostname);
- }
-#endif
-
- /* tell the client what version we are */
- SIVAL(q, 0, ((ntversion < 11) || (SEC_ADS != lp_security())) ? 1 : 13);
- /* our ntversion */
- SSVAL(q, 4, 0xffff); /* our lmnttoken */
- SSVAL(q, 6, 0xffff); /* our lm20token */
- q += 8;
-
- dump_data(4, outbuf, PTR_DIFF(q, outbuf));
-
- send_mailslot(True, getdc,
- outbuf,PTR_DIFF(q,outbuf),
- lp_netbios_name(), 0x0,
- dgram->source_name.name,
- dgram->source_name.name_type,
- p->ip, *iface_ip(p->ip), p->port);
- break;
- }
-
- /* Announce change to UAS or SAM. Send by the domain controller when a
- replication event is required. */
-
- case SAM_UAS_CHANGE: {
- struct sam_database_info *db_info;
- char *q = buf + 2;
- int i, db_count;
- uint32 low_serial;
-
- /* Header */
-
- low_serial = IVAL(q, 0); q += 4; /* Low serial number */
-
- q += 4; /* Date/time */
- q += 4; /* Pulse */
- q += 4; /* Random */
-
- /* Domain info */
-
- q = skip_string(q, 1); /* PDC name */
- q = skip_string(q, 1); /* Domain name */
- q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode PDC name */
- q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode domain name */
-
- /* Database info */
-
- db_count = SVAL(q, 0); q += 2;
-
- db_info = (struct sam_database_info *)
- malloc(sizeof(struct sam_database_info) * db_count);
-
- if (db_info == NULL) {
- DEBUG(3, ("out of memory allocating info for %d databases\n",
- db_count));
- return;
- }
-
- for (i = 0; i < db_count; i++) {
- db_info[i].index = IVAL(q, 0);
- db_info[i].serial_lo = IVAL(q, 4);
- db_info[i].serial_hi = IVAL(q, 8);
- db_info[i].date_lo = IVAL(q, 12);
- db_info[i].date_hi = IVAL(q, 16);
- q += 20;
- }
-
- /* Domain SID */
-
- q += IVAL(q, 0) + 4; /* 4 byte length plus data */
-
- q += 2; /* Alignment? */
-
- /* Misc other info */
-
- q += 4; /* NT version (0x1) */
- q += 2; /* LMNT token (0xff) */
- q += 2; /* LM20 token (0xff) */
-
- SAFE_FREE(db_info); /* Not sure whether we need to do anything
- useful with these */
-
- /* Send message to smbd */
-
- send_repl_message(low_serial);
-
- break;
- }
-
- default:
- {
- DEBUG(3,("process_logon_packet: Unknown domain request %d\n",code));
- return;
- }
- }
-}
diff --git a/source4/nmbd/nmbd_responserecordsdb.c b/source4/nmbd/nmbd_responserecordsdb.c
deleted file mode 100644
index 7e8c8025ae..0000000000
--- a/source4/nmbd/nmbd_responserecordsdb.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios library routines
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-extern int ClientNMB;
-
-int num_response_packets = 0;
-
-/***************************************************************************
- Add an expected response record into the list
- **************************************************************************/
-
-static void add_response_record(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- struct response_record *rrec2;
-
- num_response_packets++; /* count of total number of packets still around */
-
- DEBUG(4,("add_response_record: adding response record id:%hu to subnet %s. num_records:%d\n",
- rrec->response_id, subrec->subnet_name, num_response_packets));
-
- if (!subrec->responselist)
- {
- subrec->responselist = rrec;
- rrec->prev = NULL;
- rrec->next = NULL;
- return;
- }
-
- for (rrec2 = subrec->responselist; rrec2->next; rrec2 = rrec2->next)
- ;
-
- rrec2->next = rrec;
- rrec->next = NULL;
- rrec->prev = rrec2;
-}
-
-/***************************************************************************
- Remove an expected response record from the list
- **************************************************************************/
-
-void remove_response_record(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- if (rrec->prev)
- rrec->prev->next = rrec->next;
- if (rrec->next)
- rrec->next->prev = rrec->prev;
-
- if (subrec->responselist == rrec)
- subrec->responselist = rrec->next;
-
- if(rrec->userdata)
- {
- if(rrec->userdata->free_fn) {
- (*rrec->userdata->free_fn)(rrec->userdata);
- } else {
- ZERO_STRUCTP(rrec->userdata);
- SAFE_FREE(rrec->userdata);
- }
- }
-
- /* Ensure we can delete. */
- rrec->packet->locked = False;
- free_packet(rrec->packet);
-
- ZERO_STRUCTP(rrec);
- SAFE_FREE(rrec);
-
- num_response_packets--; /* count of total number of packets still around */
-}
-
-/****************************************************************************
- Create a response record for an outgoing packet.
- **************************************************************************/
-
-struct response_record *make_response_record( struct subnet_record *subrec,
- struct packet_struct *p,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- success_function success_fn,
- fail_function fail_fn,
- struct userdata_struct *userdata)
-{
- struct response_record *rrec;
- struct nmb_packet *nmb = &p->packet.nmb;
-
- if (!(rrec = (struct response_record *)malloc(sizeof(*rrec))))
- {
- DEBUG(0,("make_response_queue_record: malloc fail for response_record.\n"));
- return NULL;
- }
-
- memset((char *)rrec, '\0', sizeof(*rrec));
-
- rrec->response_id = nmb->header.name_trn_id;
-
- rrec->resp_fn = resp_fn;
- rrec->timeout_fn = timeout_fn;
- rrec->success_fn = success_fn;
- rrec->fail_fn = fail_fn;
-
- rrec->packet = p;
-
- if(userdata)
- {
- /* Intelligent userdata. */
- if(userdata->copy_fn)
- {
- if((rrec->userdata = (*userdata->copy_fn)(userdata)) == NULL)
- {
- DEBUG(0,("make_response_queue_record: copy fail for userdata.\n"));
- ZERO_STRUCTP(rrec);
- SAFE_FREE(rrec);
- return NULL;
- }
- }
- else
- {
- /* Primitive userdata, do a memcpy. */
- if((rrec->userdata = (struct userdata_struct *)
- malloc(sizeof(struct userdata_struct)+userdata->userdata_len)) == NULL)
- {
- DEBUG(0,("make_response_queue_record: malloc fail for userdata.\n"));
- ZERO_STRUCTP(rrec);
- SAFE_FREE(rrec);
- return NULL;
- }
- rrec->userdata->copy_fn = userdata->copy_fn;
- rrec->userdata->free_fn = userdata->free_fn;
- rrec->userdata->userdata_len = userdata->userdata_len;
- memcpy(rrec->userdata->data, userdata->data, userdata->userdata_len);
- }
- }
- else
- rrec->userdata = NULL;
-
- rrec->num_msgs = 0;
-
- if(!nmb->header.nm_flags.bcast)
- rrec->repeat_interval = 5; /* 5 seconds for unicast packets. */
- else
- rrec->repeat_interval = 1; /* XXXX should be in ms */
- rrec->repeat_count = 3; /* 3 retries */
- rrec->repeat_time = time(NULL) + rrec->repeat_interval; /* initial retry time */
-
- /* This packet is not being processed. */
- rrec->in_expiration_processing = False;
-
- /* Lock the packet so we won't lose it while it's on the list. */
- p->locked = True;
-
- add_response_record(subrec, rrec);
-
- return rrec;
-}
-
-/****************************************************************************
- Find a response in a subnet's name query response list.
- **************************************************************************/
-
-static struct response_record *find_response_record_on_subnet(
- struct subnet_record *subrec, uint16 id)
-{
- struct response_record *rrec = NULL;
-
- for (rrec = subrec->responselist; rrec; rrec = rrec->next)
- {
- if (rrec->response_id == id)
- {
- DEBUG(4, ("find_response_record: found response record id = %hu on subnet %s\n",
- id, subrec->subnet_name));
- break;
- }
- }
- return rrec;
-}
-
-/****************************************************************************
- Find a response in any subnet's name query response list.
- **************************************************************************/
-
-struct response_record *find_response_record(struct subnet_record **ppsubrec,
- uint16 id)
-{
- struct response_record *rrec = NULL;
-
- for ((*ppsubrec) = FIRST_SUBNET; (*ppsubrec);
- (*ppsubrec) = NEXT_SUBNET_INCLUDING_UNICAST(*ppsubrec))
- {
- if((rrec = find_response_record_on_subnet(*ppsubrec, id)) != NULL)
- return rrec;
- }
-
- /* There should never be response records on the remote_broadcast subnet.
- Sanity check to ensure this is so. */
- if(remote_broadcast_subnet->responselist != NULL)
- {
- DEBUG(0,("find_response_record: response record found on subnet %s. This should \
-never happen !\n", remote_broadcast_subnet->subnet_name));
- }
-
- /* Now check the WINS server subnet if it exists. */
- if(wins_server_subnet != NULL)
- {
- *ppsubrec = wins_server_subnet;
- if((rrec = find_response_record_on_subnet(*ppsubrec, id))!= NULL)
- return rrec;
- }
-
- DEBUG(0,("find_response_record: response packet id %hu received with no \
-matching record.\n", id));
-
- *ppsubrec = NULL;
-
- return NULL;
-}
-
-/****************************************************************************
- Check if a refresh is queued for a particular name on a particular subnet.
- **************************************************************************/
-
-BOOL is_refresh_already_queued(struct subnet_record *subrec, struct name_record *namerec)
-{
- struct response_record *rrec = NULL;
-
- for (rrec = subrec->responselist; rrec; rrec = rrec->next)
- {
- struct packet_struct *p = rrec->packet;
- struct nmb_packet *nmb = &p->packet.nmb;
-
- if((nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_8) ||
- (nmb->header.opcode == NMB_NAME_REFRESH_OPCODE_9))
- {
- /* Yes it's a queued refresh - check if the name is correct. */
- if(nmb_name_equal(&nmb->question.question_name, &namerec->name))
- return True;
- }
- }
-
- return False;
-}
diff --git a/source4/nmbd/nmbd_sendannounce.c b/source4/nmbd/nmbd_sendannounce.c
deleted file mode 100644
index 191a3b7c7b..0000000000
--- a/source4/nmbd/nmbd_sendannounce.c
+++ /dev/null
@@ -1,607 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- SMB Version handling
- Copyright (C) John H Terpstra 1995-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-extern int updatecount;
-extern BOOL found_lm_clients;
-
-/****************************************************************************
- Send a browser reset packet.
-**************************************************************************/
-
-void send_browser_reset(int reset_type, const char *to_name, int to_type, struct in_addr to_ip)
-{
- pstring outbuf;
- char *p;
-
- DEBUG(3,("send_browser_reset: sending reset request type %d to %s<%02x> IP %s.\n",
- reset_type, to_name, to_type, inet_ntoa(to_ip) ));
-
- memset(outbuf,'\0',sizeof(outbuf));
- p = outbuf;
- SCVAL(p,0,ANN_ResetBrowserState);
- p++;
- SCVAL(p,0,reset_type);
- p++;
-
- send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
- lp_netbios_name(), 0x0, to_name, to_type, to_ip,
- FIRST_SUBNET->myip, DGRAM_PORT);
-}
-
-/****************************************************************************
- Broadcast a packet to the local net requesting that all servers in this
- workgroup announce themselves to us.
- **************************************************************************/
-
-void broadcast_announce_request(struct subnet_record *subrec, struct work_record *work)
-{
- pstring outbuf;
- char *p;
-
- work->needannounce = True;
-
- DEBUG(3,("broadcast_announce_request: sending announce request for workgroup %s \
-to subnet %s\n", work->work_group, subrec->subnet_name));
-
- memset(outbuf,'\0',sizeof(outbuf));
- p = outbuf;
- SCVAL(p,0,ANN_AnnouncementRequest);
- p++;
-
- SCVAL(p,0,work->token); /* (local) Unique workgroup token id. */
- p++;
- p += push_string(NULL, p+1, lp_netbios_name(), 15, STR_ASCII|STR_UPPER|STR_TERMINATE);
-
- send_mailslot(False, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
- lp_netbios_name(), 0x0, work->work_group,0x1e, subrec->bcast_ip,
- subrec->myip, DGRAM_PORT);
-}
-
-/****************************************************************************
- Broadcast an announcement.
- **************************************************************************/
-
-static void send_announcement(struct subnet_record *subrec, int announce_type,
- const char *from_name, const char *to_name, int to_type, struct in_addr to_ip,
- time_t announce_interval,
- const char *server_name, int server_type, const char *server_comment)
-{
- pstring outbuf;
- char *p;
-
- memset(outbuf,'\0',sizeof(outbuf));
- p = outbuf+1;
-
- SCVAL(outbuf,0,announce_type);
-
- /* Announcement parameters. */
- SCVAL(p,0,updatecount);
- SIVAL(p,1,announce_interval*1000); /* Milliseconds - despite the spec. */
-
- push_string(NULL, p+5, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE);
-
- SCVAL(p,21,lp_major_announce_version()); /* Major version. */
- SCVAL(p,22,lp_minor_announce_version()); /* Minor version. */
-
- SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
- /* Browse version: got from NT/AS 4.00 - Value defined in smb.h (JHT). */
- SSVAL(p,27,BROWSER_ELECTION_VERSION);
- SSVAL(p,29,BROWSER_CONSTANT); /* Browse signature. */
-
- p += 31 + push_string(NULL, p+31, server_comment, -1, STR_ASCII|STR_TERMINATE);
-
- send_mailslot(False,BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
- from_name, 0x0, to_name, to_type, to_ip, subrec->myip,
- DGRAM_PORT);
-}
-
-/****************************************************************************
- Broadcast a LanMan announcement.
-**************************************************************************/
-
-static void send_lm_announcement(struct subnet_record *subrec, int announce_type,
- char *from_name, char *to_name, int to_type, struct in_addr to_ip,
- time_t announce_interval,
- char *server_name, int server_type, char *server_comment)
-{
- pstring outbuf;
- char *p=outbuf;
-
- memset(outbuf,'\0',sizeof(outbuf));
-
- SSVAL(p,0,announce_type);
- SIVAL(p,2,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
- SCVAL(p,6,lp_major_announce_version()); /* Major version. */
- SCVAL(p,7,lp_minor_announce_version()); /* Minor version. */
- SSVAL(p,8,announce_interval); /* In seconds - according to spec. */
-
- p += 10;
- /*StrnCpy(p,server_name,15);
- strupper(p);
- p = skip_string(p,1);
- pstrcpy(p,server_comment);
- p = skip_string(p,1);*/
- p += push_string(NULL, p, server_name, 15, STR_ASCII|STR_UPPER|STR_TERMINATE);
- p += push_string(NULL, p, server_comment, sizeof(pstring)-15, STR_ASCII|STR_UPPER|STR_TERMINATE);
-
- send_mailslot(False,LANMAN_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
- from_name, 0x0, to_name, to_type, to_ip, subrec->myip,
- DGRAM_PORT);
-}
-
-/****************************************************************************
- We are a local master browser. Announce this to WORKGROUP<1e>.
-****************************************************************************/
-
-static void send_local_master_announcement(struct subnet_record *subrec, struct work_record *work,
- struct server_record *servrec)
-{
- /* Ensure we don't have the prohibited bit set. */
- uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
-
- DEBUG(3,("send_local_master_announcement: type %x for name %s on subnet %s for workgroup %s\n",
- type, lp_netbios_name(), subrec->subnet_name, work->work_group));
-
- send_announcement(subrec, ANN_LocalMasterAnnouncement,
- lp_netbios_name(), /* From nbt name. */
- work->work_group, 0x1e, /* To nbt name. */
- subrec->bcast_ip, /* To ip. */
- work->announce_interval, /* Time until next announce. */
- lp_netbios_name(), /* Name to announce. */
- type, /* Type field. */
- servrec->serv.comment);
-}
-
-/****************************************************************************
- Announce the workgroup WORKGROUP to MSBROWSE<01>.
-****************************************************************************/
-
-static void send_workgroup_announcement(struct subnet_record *subrec, struct work_record *work)
-{
- DEBUG(3,("send_workgroup_announcement: on subnet %s for workgroup %s\n",
- subrec->subnet_name, work->work_group));
-
- send_announcement(subrec, ANN_DomainAnnouncement,
- lp_netbios_name(), /* From nbt name. */
- MSBROWSE, 0x1, /* To nbt name. */
- subrec->bcast_ip, /* To ip. */
- work->announce_interval, /* Time until next announce. */
- work->work_group, /* Name to announce. */
- SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT, /* workgroup announce flags. */
- lp_netbios_name()); /* From name as comment. */
-}
-
-/****************************************************************************
- Announce the given host to WORKGROUP<1d>.
-****************************************************************************/
-
-static void send_host_announcement(struct subnet_record *subrec, struct work_record *work,
- struct server_record *servrec)
-{
- /* Ensure we don't have the prohibited bits set. */
- uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
-
- DEBUG(3,("send_host_announcement: type %x for host %s on subnet %s for workgroup %s\n",
- type, servrec->serv.name, subrec->subnet_name, work->work_group));
-
- send_announcement(subrec, ANN_HostAnnouncement,
- servrec->serv.name, /* From nbt name. */
- work->work_group, 0x1d, /* To nbt name. */
- subrec->bcast_ip, /* To ip. */
- work->announce_interval, /* Time until next announce. */
- servrec->serv.name, /* Name to announce. */
- type, /* Type field. */
- servrec->serv.comment);
-}
-
-/****************************************************************************
- Announce the given LanMan host
-****************************************************************************/
-
-static void send_lm_host_announcement(struct subnet_record *subrec, struct work_record *work,
- struct server_record *servrec, int lm_interval)
-{
- /* Ensure we don't have the prohibited bits set. */
- uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
-
- DEBUG(3,("send_lm_host_announcement: type %x for host %s on subnet %s for workgroup %s, ttl: %d\n",
- type, servrec->serv.name, subrec->subnet_name, work->work_group, lm_interval));
-
- send_lm_announcement(subrec, ANN_HostAnnouncement,
- servrec->serv.name, /* From nbt name. */
- work->work_group, 0x00, /* To nbt name. */
- subrec->bcast_ip, /* To ip. */
- lm_interval, /* Time until next announce. */
- servrec->serv.name, /* Name to announce. */
- type, /* Type field. */
- servrec->serv.comment);
-}
-
-/****************************************************************************
- Announce a server record.
- ****************************************************************************/
-
-static void announce_server(struct subnet_record *subrec, struct work_record *work,
- struct server_record *servrec)
-{
- /* Only do domain announcements if we are a master and it's
- our primary name we're being asked to announce. */
-
- if (AM_LOCAL_MASTER_BROWSER(work) && strequal(lp_netbios_name(),servrec->serv.name))
- {
- send_local_master_announcement(subrec, work, servrec);
- send_workgroup_announcement(subrec, work);
- }
- else
- {
- send_host_announcement(subrec, work, servrec);
- }
-}
-
-/****************************************************************************
- Go through all my registered names on all broadcast subnets and announce
- them if the timeout requires it.
- **************************************************************************/
-
-void announce_my_server_names(time_t t)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup());
-
- if(work)
- {
- struct server_record *servrec;
-
- if (work->needannounce)
- {
- /* Drop back to a max 3 minute announce. This is to prevent a
- single lost packet from breaking things for too long. */
-
- work->announce_interval = MIN(work->announce_interval,
- CHECK_TIME_MIN_HOST_ANNCE*60);
- work->lastannounce_time = t - (work->announce_interval+1);
- work->needannounce = False;
- }
-
- /* Announce every minute at first then progress to every 12 mins */
- if ((t - work->lastannounce_time) < work->announce_interval)
- continue;
-
- if (work->announce_interval < (CHECK_TIME_MAX_HOST_ANNCE * 60))
- work->announce_interval += 60;
-
- work->lastannounce_time = t;
-
- for (servrec = work->serverlist; servrec; servrec = servrec->next)
- {
- if (is_myname(servrec->serv.name))
- announce_server(subrec, work, servrec);
- }
- } /* if work */
- } /* for subrec */
-}
-
-/****************************************************************************
- Go through all my registered names on all broadcast subnets and announce
- them as a LanMan server if the timeout requires it.
-**************************************************************************/
-
-void announce_my_lm_server_names(time_t t)
-{
- struct subnet_record *subrec;
- static time_t last_lm_announce_time=0;
- int announce_interval = lp_lm_interval();
- int lm_announce = lp_lm_announce();
-
- if ((announce_interval <= 0) || (lm_announce <= 0))
- {
- /* user absolutely does not want LM announcements to be sent. */
- return;
- }
-
- if ((lm_announce >= 2) && (!found_lm_clients))
- {
- /* has been set to 2 (Auto) but no LM clients detected (yet). */
- return;
- }
-
- /* Otherwise: must have been set to 1 (Yes), or LM clients *have*
- been detected. */
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work = find_workgroup_on_subnet(subrec, lp_workgroup());
-
- if(work)
- {
- struct server_record *servrec;
-
- if (last_lm_announce_time && ((t - last_lm_announce_time) < announce_interval ))
- continue;
-
- last_lm_announce_time = t;
-
- for (servrec = work->serverlist; servrec; servrec = servrec->next)
- {
- if (is_myname(servrec->serv.name))
- /* skipping equivalent of announce_server() */
- send_lm_host_announcement(subrec, work, servrec, announce_interval);
- }
- } /* if work */
- } /* for subrec */
-}
-
-/* Announce timer. Moved into global static so it can be reset
- when a machine becomes a local master browser. */
-static time_t announce_timer_last=0;
-
-/****************************************************************************
- Reset the announce_timer so that a local master browser announce will be done
- immediately.
- ****************************************************************************/
-
-void reset_announce_timer(void)
-{
- announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60);
-}
-
-/****************************************************************************
- Announce myself as a local master browser to a domain master browser.
- **************************************************************************/
-
-void announce_myself_to_domain_master_browser(time_t t)
-{
- struct subnet_record *subrec;
- struct work_record *work;
-
- if(!we_are_a_wins_client())
- {
- DEBUG(10,("announce_myself_to_domain_master_browser: no unicast subnet, ignoring.\n"));
- return;
- }
-
- if (!announce_timer_last)
- announce_timer_last = t;
-
- if ((t-announce_timer_last) < (CHECK_TIME_MST_ANNOUNCE * 60))
- {
- DEBUG(10,("announce_myself_to_domain_master_browser: t (%d) - last(%d) < %d\n",
- (int)t, (int)announce_timer_last,
- CHECK_TIME_MST_ANNOUNCE * 60 ));
- return;
- }
-
- announce_timer_last = t;
-
- /* Look over all our broadcast subnets to see if any of them
- has the state set as local master browser. */
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- for (work = subrec->workgrouplist; work; work = work->next)
- {
- if (AM_LOCAL_MASTER_BROWSER(work))
- {
- DEBUG(4,( "announce_myself_to_domain_master_browser: I am a local master browser for \
-workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name));
-
- /* Look in nmbd_browsersync.c for the rest of this code. */
- announce_and_sync_with_domain_master_browser(subrec, work);
- }
- }
- }
-}
-
-/****************************************************************************
-Announce all samba's server entries as 'gone'.
-This must *only* be called on shutdown.
-****************************************************************************/
-
-void announce_my_servers_removed(void)
-{
- int announce_interval = lp_lm_interval();
- int lm_announce = lp_lm_announce();
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work;
- for (work = subrec->workgrouplist; work; work = work->next)
- {
- struct server_record *servrec;
-
- work->announce_interval = 0;
- for (servrec = work->serverlist; servrec; servrec = servrec->next)
- {
- if (!is_myname(servrec->serv.name))
- continue;
- servrec->serv.type = 0;
- if(AM_LOCAL_MASTER_BROWSER(work))
- send_local_master_announcement(subrec, work, servrec);
- send_host_announcement(subrec, work, servrec);
-
-
- if ((announce_interval <= 0) || (lm_announce <= 0))
- {
- /* user absolutely does not want LM announcements to be sent. */
- continue;
- }
-
- if ((lm_announce >= 2) && (!found_lm_clients))
- {
- /* has been set to 2 (Auto) but no LM clients detected (yet). */
- continue;
- }
-
- /*
- * lm announce was set or we have seen lm announcements, so do
- * a lm announcement of host removed.
- */
-
- send_lm_host_announcement(subrec, work, servrec, 0);
- }
- }
- }
-}
-
-/****************************************************************************
- Do all the "remote" announcements. These are used to put ourselves
- on a remote browse list. They are done blind, no checking is done to
- see if there is actually a local master browser at the other end.
- **************************************************************************/
-
-void announce_remote(time_t t)
-{
- char *s;
- const char *ptr;
- static time_t last_time = 0;
- pstring s2;
- struct in_addr addr;
- char *comment;
- int stype = lp_default_server_announce();
-
- if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL)))
- return;
-
- last_time = t;
-
- s = lp_remote_announce();
- if (!*s)
- return;
-
- comment = string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH);
-
- for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); )
- {
- /* The entries are of the form a.b.c.d/WORKGROUP with
- WORKGROUP being optional */
- const char *wgroup;
- char *pwgroup;
- int i;
-
- pwgroup = strchr_m(s2,'/');
- if (pwgroup)
- *pwgroup++ = 0;
- if (!pwgroup || !*pwgroup)
- wgroup = lp_workgroup();
- else
- wgroup = pwgroup;
-
- addr = *interpret_addr2(s2);
-
- /* Announce all our names including aliases */
- /* Give the ip address as the address of our first
- broadcast subnet. */
-
- for(i=0; my_netbios_names(i); i++)
- {
- const char *name = my_netbios_names(i);
-
- DEBUG(5,("announce_remote: Doing remote announce for server %s to IP %s.\n",
- name, inet_ntoa(addr) ));
-
- send_announcement(FIRST_SUBNET, ANN_HostAnnouncement,
- name, /* From nbt name. */
- wgroup, 0x1d, /* To nbt name. */
- addr, /* To ip. */
- REMOTE_ANNOUNCE_INTERVAL, /* Time until next announce. */
- name, /* Name to announce. */
- stype, /* Type field. */
- comment);
- }
- }
-}
-
-/****************************************************************************
- Implement the 'remote browse sync' feature Andrew added.
- These are used to put our browse lists into remote browse lists.
- **************************************************************************/
-
-void browse_sync_remote(time_t t)
-{
- char *s;
- const char *ptr;
- static time_t last_time = 0;
- pstring s2;
- struct in_addr addr;
- struct work_record *work;
- pstring outbuf;
- char *p;
-
- if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL)))
- return;
-
- last_time = t;
-
- s = lp_remote_browse_sync();
- if (!*s)
- return;
-
- /*
- * We only do this if we are the local master browser
- * for our workgroup on the firsst subnet.
- */
-
- if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL)
- {
- DEBUG(0,("browse_sync_remote: Cannot find workgroup %s on subnet %s\n",
- lp_workgroup(), FIRST_SUBNET->subnet_name ));
- return;
- }
-
- if(!AM_LOCAL_MASTER_BROWSER(work))
- {
- DEBUG(5,("browse_sync_remote: We can only do this if we are a local master browser \
-for workgroup %s on subnet %s.\n", lp_workgroup(), FIRST_SUBNET->subnet_name ));
- return;
- }
-
- memset(outbuf,'\0',sizeof(outbuf));
- p = outbuf;
- SCVAL(p,0,ANN_MasterAnnouncement);
- p++;
-
- StrnCpy(p,lp_netbios_name(),15);
- strupper(p);
- p = skip_string(p,1);
-
- for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); )
- {
- /* The entries are of the form a.b.c.d */
- addr = *interpret_addr2(s2);
-
- DEBUG(5,("announce_remote: Doing remote browse sync announce for server %s to IP %s.\n",
- lp_netbios_name(), inet_ntoa(addr) ));
-
- send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
- lp_netbios_name(), 0x0, "*", 0x0, addr, FIRST_SUBNET->myip, DGRAM_PORT);
- }
-}
diff --git a/source4/nmbd/nmbd_serverlistdb.c b/source4/nmbd/nmbd_serverlistdb.c
deleted file mode 100644
index ee0c021d5d..0000000000
--- a/source4/nmbd/nmbd_serverlistdb.c
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-extern int ClientNMB;
-
-int updatecount = 0;
-
-/*******************************************************************
- Remove all the servers in a work group.
- ******************************************************************/
-
-void remove_all_servers(struct work_record *work)
-{
- struct server_record *servrec;
- struct server_record *nexts;
-
- for (servrec = work->serverlist; servrec; servrec = nexts)
- {
- DEBUG(7,("remove_all_servers: Removing server %s\n",servrec->serv.name));
- nexts = servrec->next;
-
- if (servrec->prev)
- servrec->prev->next = servrec->next;
- if (servrec->next)
- servrec->next->prev = servrec->prev;
-
- if (work->serverlist == servrec)
- work->serverlist = servrec->next;
-
- ZERO_STRUCTP(servrec);
- SAFE_FREE(servrec);
-
- }
-
- work->subnet->work_changed = True;
-}
-
-/***************************************************************************
- Add a server into the a workgroup serverlist.
- **************************************************************************/
-
-static void add_server_to_workgroup(struct work_record *work,
- struct server_record *servrec)
-{
- struct server_record *servrec2;
-
- if (!work->serverlist)
- {
- work->serverlist = servrec;
- servrec->prev = NULL;
- servrec->next = NULL;
- return;
- }
-
- for (servrec2 = work->serverlist; servrec2->next; servrec2 = servrec2->next)
- ;
-
- servrec2->next = servrec;
- servrec->next = NULL;
- servrec->prev = servrec2;
- work->subnet->work_changed = True;
-}
-
-/****************************************************************************
- Find a server in a server list.
- **************************************************************************/
-
-struct server_record *find_server_in_workgroup(struct work_record *work, const char *name)
-{
- struct server_record *ret;
-
- for (ret = work->serverlist; ret; ret = ret->next)
- {
- if (strequal(ret->serv.name,name))
- return ret;
- }
- return NULL;
-}
-
-
-/****************************************************************************
- Remove a server entry from this workgroup.
- ****************************************************************************/
-
-void remove_server_from_workgroup(struct work_record *work, struct server_record *servrec)
-{
- if (servrec->prev)
- servrec->prev->next = servrec->next;
- if (servrec->next)
- servrec->next->prev = servrec->prev;
-
- if (work->serverlist == servrec)
- work->serverlist = servrec->next;
-
- ZERO_STRUCTP(servrec);
- SAFE_FREE(servrec);
- work->subnet->work_changed = True;
-}
-
-/****************************************************************************
- Create a server entry on this workgroup.
- ****************************************************************************/
-
-struct server_record *create_server_on_workgroup(struct work_record *work,
- const char *name,int servertype,
- int ttl, const char *comment)
-{
- struct server_record *servrec;
-
- if (name[0] == '*')
- {
- DEBUG(7,("create_server_on_workgroup: not adding name starting with '*' (%s)\n",
- name));
- return (NULL);
- }
-
- if((servrec = find_server_in_workgroup(work, name)) != NULL)
- {
- DEBUG(0,("create_server_on_workgroup: Server %s already exists on \
-workgroup %s. This is a bug.\n", name, work->work_group));
- return NULL;
- }
-
- if((servrec = (struct server_record *)malloc(sizeof(*servrec))) == NULL)
- {
- DEBUG(0,("create_server_entry_on_workgroup: malloc fail !\n"));
- return NULL;
- }
-
- memset((char *)servrec,'\0',sizeof(*servrec));
-
- servrec->subnet = work->subnet;
-
- StrnCpy(servrec->serv.name,name,sizeof(servrec->serv.name)-1);
- StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1);
- strupper(servrec->serv.name);
- servrec->serv.type = servertype;
-
- update_server_ttl(servrec, ttl);
-
- add_server_to_workgroup(work, servrec);
-
- DEBUG(3,("create_server_on_workgroup: Created server entry %s of type %x (%s) on \
-workgroup %s.\n", name,servertype,comment, work->work_group));
-
- work->subnet->work_changed = True;
-
- return(servrec);
-}
-
-/*******************************************************************
- Update the ttl field of a server record.
-*******************************************************************/
-
-void update_server_ttl(struct server_record *servrec, int ttl)
-{
- if(ttl > lp_max_ttl())
- ttl = lp_max_ttl();
-
- if(is_myname(servrec->serv.name))
- servrec->death_time = PERMANENT_TTL;
- else
- servrec->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL;
-
- servrec->subnet->work_changed = True;
-}
-
-/*******************************************************************
- Expire old servers in the serverlist. A time of -1 indicates
- everybody dies except those with a death_time of PERMANENT_TTL (which is 0).
- This should only be called from expire_workgroups_and_servers().
- ******************************************************************/
-
-void expire_servers(struct work_record *work, time_t t)
-{
- struct server_record *servrec;
- struct server_record *nexts;
-
- for (servrec = work->serverlist; servrec; servrec = nexts)
- {
- nexts = servrec->next;
-
- if ((servrec->death_time != PERMANENT_TTL) && ((t == -1) || (servrec->death_time < t)))
- {
- DEBUG(3,("expire_old_servers: Removing timed out server %s\n",servrec->serv.name));
- remove_server_from_workgroup(work, servrec);
- work->subnet->work_changed = True;
- }
- }
-}
-
-/*******************************************************************
- Decide if we should write out a server record for this server.
- We return zero if we should not. Check if we've already written
- out this server record from an earlier subnet.
-******************************************************************/
-
-static uint32 write_this_server_name( struct subnet_record *subrec,
- struct work_record *work,
- struct server_record *servrec)
-{
- struct subnet_record *ssub;
- struct work_record *iwork;
-
- /* Go through all the subnets we have already seen. */
- for (ssub = FIRST_SUBNET; ssub != subrec; ssub = NEXT_SUBNET_INCLUDING_UNICAST(ssub))
- {
- for(iwork = ssub->workgrouplist; iwork; iwork = iwork->next)
- {
- if(find_server_in_workgroup( iwork, servrec->serv.name) != NULL)
- {
- /*
- * We have already written out this server record, don't
- * do it again. This gives precedence to servers we have seen
- * on the broadcast subnets over servers that may have been
- * added via a sync on the unicast_subet.
- *
- * The correct way to do this is to have a serverlist file
- * per subnet - this means changes to smbd as well. I may
- * add this at a later date (JRA).
- */
-
- return 0;
- }
- }
- }
-
- return servrec->serv.type;
-}
-
-/*******************************************************************
- Decide if we should write out a workgroup record for this workgroup.
- We return zero if we should not. Don't write out lp_workgroup() (we've
- already done it) and also don't write out a second workgroup record
- on the unicast subnet that we've already written out on one of the
- broadcast subnets.
-******************************************************************/
-
-static uint32 write_this_workgroup_name( struct subnet_record *subrec,
- struct work_record *work)
-{
- struct subnet_record *ssub;
-
- if(strequal(lp_workgroup(), work->work_group))
- return 0;
-
- /* This is a workgroup we have seen on a broadcast subnet. All
- these have the same type. */
-
- if(subrec != unicast_subnet)
- return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY);
-
- for(ssub = FIRST_SUBNET; ssub; ssub = NEXT_SUBNET_EXCLUDING_UNICAST(ssub))
- {
- /* This is the unicast subnet so check if we've already written out
- this subnet when we passed over the broadcast subnets. */
-
- if(find_workgroup_on_subnet( ssub, work->work_group) != NULL)
- return 0;
- }
-
- /* All workgroups on the unicast subnet (except our own, which we
- have already written out) cannot be local. */
-
- return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT);
-}
-
-/*******************************************************************
- Write out the browse.dat file.
- ******************************************************************/
-
-void write_browse_list_entry(XFILE *fp, const char *name, uint32 rec_type,
- const char *local_master_browser_name, const char *description)
-{
- fstring tmp;
-
- slprintf(tmp,sizeof(tmp)-1, "\"%s\"", name);
- x_fprintf(fp, "%-25s ", tmp);
- x_fprintf(fp, "%08x ", rec_type);
- slprintf(tmp, sizeof(tmp)-1, "\"%s\" ", local_master_browser_name);
- x_fprintf(fp, "%-30s", tmp);
- x_fprintf(fp, "\"%s\"\n", description);
-}
-
-void write_browse_list(time_t t, BOOL force_write)
-{
- struct subnet_record *subrec;
- struct work_record *work;
- struct server_record *servrec;
- pstring fname,fnamenew;
- uint32 stype;
- int i;
- XFILE *fp;
- BOOL list_changed = force_write;
- static time_t lasttime = 0;
-
- /* Always dump if we're being told to by a signal. */
- if(force_write == False)
- {
- if (!lasttime)
- lasttime = t;
- if (t - lasttime < 5)
- return;
- }
-
- lasttime = t;
-
- dump_workgroups(force_write);
-
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- if(subrec->work_changed)
- {
- list_changed = True;
- break;
- }
- }
-
- if(!list_changed)
- return;
-
- updatecount++;
-
- pstrcpy(fname,lp_lockdir());
- trim_string(fname,NULL,"/");
- pstrcat(fname,"/");
- pstrcat(fname,SERVER_LIST);
- pstrcpy(fnamenew,fname);
- pstrcat(fnamenew,".");
-
- fp = x_fopen(fnamenew,O_WRONLY|O_CREAT|O_TRUNC, 0644);
-
- if (!fp)
- {
- DEBUG(0,("write_browse_list: Can't open file %s. Error was %s\n",
- fnamenew,strerror(errno)));
- return;
- }
-
- /*
- * Write out a record for our workgroup. Use the record from the first
- * subnet.
- */
-
- if((work = find_workgroup_on_subnet(FIRST_SUBNET, lp_workgroup())) == NULL)
- {
- DEBUG(0,("write_browse_list: Fatal error - cannot find my workgroup %s\n",
- lp_workgroup()));
- x_fclose(fp);
- return;
- }
-
- write_browse_list_entry(fp, work->work_group,
- SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY,
- work->local_master_browser_name, work->work_group);
-
- /*
- * We need to do something special for our own names.
- * This is due to the fact that we may be a local master browser on
- * one of our broadcast subnets, and a domain master on the unicast
- * subnet. We iterate over the subnets and only write out the name
- * once.
- */
-
- for (i=0; my_netbios_names(i); i++)
- {
- stype = 0;
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- if((work = find_workgroup_on_subnet( subrec, lp_workgroup() )) == NULL)
- continue;
- if((servrec = find_server_in_workgroup( work, my_netbios_names(i))) == NULL)
- continue;
-
- stype |= servrec->serv.type;
- }
-
- /* Output server details, plus what workgroup they're in. */
- write_browse_list_entry(fp, my_netbios_names(i), stype,
- string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH), lp_workgroup());
- }
-
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- subrec->work_changed = False;
-
- for (work = subrec->workgrouplist; work ; work = work->next)
- {
- /* Write out a workgroup record for a workgroup. */
- uint32 wg_type = write_this_workgroup_name( subrec, work);
-
- if(wg_type)
- {
- write_browse_list_entry(fp, work->work_group, wg_type,
- work->local_master_browser_name,
- work->work_group);
- }
-
- /* Now write out any server records a workgroup may have. */
-
- for (servrec = work->serverlist; servrec ; servrec = servrec->next)
- {
- uint32 serv_type;
-
- /* We have already written our names here. */
- if(is_myname(servrec->serv.name))
- continue;
-
- serv_type = write_this_server_name(subrec, work, servrec);
-
- if(serv_type)
- {
- /* Output server details, plus what workgroup they're in. */
- write_browse_list_entry(fp, servrec->serv.name, serv_type,
- servrec->serv.comment, work->work_group);
- }
- }
- }
- }
-
- x_fclose(fp);
- unlink(fname);
- chmod(fnamenew,0644);
- rename(fnamenew,fname);
- DEBUG(3,("write_browse_list: Wrote browse list into file %s\n",fname));
-}
diff --git a/source4/nmbd/nmbd_subnetdb.c b/source4/nmbd/nmbd_subnetdb.c
deleted file mode 100644
index 6296826425..0000000000
--- a/source4/nmbd/nmbd_subnetdb.c
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Revision History:
-
-*/
-
-#include "includes.h"
-
-extern int ClientNMB;
-extern int ClientDGRAM;
-extern int global_nmb_port;
-
-/* This is the broadcast subnets database. */
-struct subnet_record *subnetlist = NULL;
-
-/* Extra subnets - keep these separate so enumeration code doesn't
- run onto it by mistake. */
-
-struct subnet_record *unicast_subnet = NULL;
-struct subnet_record *remote_broadcast_subnet = NULL;
-struct subnet_record *wins_server_subnet = NULL;
-
-extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
-
-/****************************************************************************
- Add a subnet into the list.
- **************************************************************************/
-
-static void add_subnet(struct subnet_record *subrec)
-{
- DLIST_ADD(subnetlist, subrec);
-}
-
-/* ************************************************************************** **
- * Comparison routine for ordering the splay-tree based namelists assoicated
- * with each subnet record.
- *
- * Input: Item - Pointer to the comparison key.
- * Node - Pointer to a node the splay tree.
- *
- * Output: The return value will be <0 , ==0, or >0 depending upon the
- * ordinal relationship of the two keys.
- *
- * ************************************************************************** **
- */
-static int namelist_entry_compare( ubi_trItemPtr Item, ubi_trNodePtr Node )
- {
- struct name_record *NR = (struct name_record *)Node;
-
- if( DEBUGLVL( 10 ) )
- {
- struct nmb_name *Iname = (struct nmb_name *)Item;
-
- Debug1( "nmbd_subnetdb:namelist_entry_compare()\n" );
- Debug1( "%d == memcmp( \"%s\", \"%s\", %d )\n",
- memcmp( Item, &(NR->name), sizeof(struct nmb_name) ),
- nmb_namestr(Iname), nmb_namestr(&NR->name), (int)sizeof(struct nmb_name) );
- }
-
- return( memcmp( Item, &(NR->name), sizeof(struct nmb_name) ) );
- } /* namelist_entry_compare */
-
-
-/****************************************************************************
-stop listening on a subnet
-we don't free the record as we don't have proper reference counting for it
-yet and it may be in use by a response record
- ****************************************************************************/
-void close_subnet(struct subnet_record *subrec)
-{
- DLIST_REMOVE(subnetlist, subrec);
-
- if (subrec->dgram_sock != -1) {
- close(subrec->dgram_sock);
- subrec->dgram_sock = -1;
- }
- if (subrec->nmb_sock != -1) {
- close(subrec->nmb_sock);
- subrec->nmb_sock = -1;
- }
-}
-
-
-
-/****************************************************************************
- Create a subnet entry.
- ****************************************************************************/
-
-static struct subnet_record *make_subnet(const char *name, enum subnet_type type,
- struct in_addr myip, struct in_addr bcast_ip,
- struct in_addr mask_ip)
-{
- struct subnet_record *subrec = NULL;
- int nmb_sock, dgram_sock;
-
- /* Check if we are creating a non broadcast subnet - if so don't create
- sockets.
- */
-
- if(type != NORMAL_SUBNET)
- {
- nmb_sock = -1;
- dgram_sock = -1;
- }
- else
- {
- /*
- * Attempt to open the sockets on port 137/138 for this interface
- * and bind them.
- * Fail the subnet creation if this fails.
- */
-
- if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1)
- {
- if( DEBUGLVL( 0 ) )
- {
- Debug1( "nmbd_subnetdb:make_subnet()\n" );
- Debug1( " Failed to open nmb socket on interface %s ", inet_ntoa(myip) );
- Debug1( "for port %d. ", global_nmb_port );
- Debug1( "Error was %s\n", strerror(errno) );
- }
- return NULL;
- }
-
- if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1)
- {
- if( DEBUGLVL( 0 ) )
- {
- Debug1( "nmbd_subnetdb:make_subnet()\n" );
- Debug1( " Failed to open dgram socket on interface %s ", inet_ntoa(myip) );
- Debug1( "for port %d. ", DGRAM_PORT );
- Debug1( "Error was %s\n", strerror(errno) );
- }
- return NULL;
- }
-
- /* Make sure we can broadcast from these sockets. */
- set_socket_options(nmb_sock,"SO_BROADCAST");
- set_socket_options(dgram_sock,"SO_BROADCAST");
-
- }
-
- subrec = (struct subnet_record *)malloc(sizeof(*subrec));
-
- if (!subrec)
- {
- DEBUG(0,("make_subnet: malloc fail !\n"));
- close(nmb_sock);
- close(dgram_sock);
- return(NULL);
- }
-
- memset( (char *)subrec, '\0', sizeof(*subrec) );
- (void)ubi_trInitTree( subrec->namelist,
- namelist_entry_compare,
- ubi_trOVERWRITE );
-
- if((subrec->subnet_name = strdup(name)) == NULL)
- {
- DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
- close(nmb_sock);
- close(dgram_sock);
- ZERO_STRUCTP(subrec);
- SAFE_FREE(subrec);
- return(NULL);
- }
-
- DEBUG(2, ("making subnet name:%s ", name ));
- DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip)));
- DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip)));
-
- subrec->namelist_changed = False;
- subrec->work_changed = False;
-
- subrec->bcast_ip = bcast_ip;
- subrec->mask_ip = mask_ip;
- subrec->myip = myip;
- subrec->type = type;
- subrec->nmb_sock = nmb_sock;
- subrec->dgram_sock = dgram_sock;
-
- return subrec;
-}
-
-
-/****************************************************************************
- Create a normal subnet
-**************************************************************************/
-struct subnet_record *make_normal_subnet(struct interface *iface)
-{
- struct subnet_record *subrec;
-
- subrec = make_subnet(inet_ntoa(iface->ip), NORMAL_SUBNET,
- iface->ip, iface->bcast, iface->nmask);
- if (subrec) {
- add_subnet(subrec);
- }
- return subrec;
-}
-
-
-/****************************************************************************
- Create subnet entries.
-**************************************************************************/
-
-BOOL create_subnets(void)
-{
- int num_interfaces = iface_count();
- int i;
- struct in_addr unicast_ip, ipzero;
- extern struct in_addr loopback_ip;
-
- if(num_interfaces == 0) {
- DEBUG(0,("create_subnets: No local interfaces !\n"));
- DEBUG(0,("create_subnets: Waiting for an interface to appear ...\n"));
- while (iface_count() == 0) {
- sleep(5);
- load_interfaces();
- }
- }
-
- num_interfaces = iface_count();
-
- /*
- * Create subnets from all the local interfaces and thread them onto
- * the linked list.
- */
-
- for (i = 0 ; i < num_interfaces; i++)
- {
- struct interface *iface = get_interface(i);
-
- /*
- * We don't want to add a loopback interface, in case
- * someone has added 127.0.0.1 for smbd, nmbd needs to
- * ignore it here. JRA.
- */
-
- if (ip_equal(iface->ip, loopback_ip)) {
- DEBUG(2,("create_subnets: Ignoring loopback interface.\n" ));
- continue;
- }
-
- if (!make_normal_subnet(iface)) return False;
- }
-
- if (lp_we_are_a_wins_server()) {
- /* Pick the first interface ip address as the WINS server ip. */
- unicast_ip = *iface_n_ip(0);
- } else {
- /* note that we do not set the wins server IP here. We just
- set it at zero and let the wins registration code cope
- with getting the IPs right for each packet */
- zero_ip(&unicast_ip);
- }
-
- /*
- * Create the unicast and remote broadcast subnets.
- * Don't put these onto the linked list.
- * The ip address of the unicast subnet is set to be
- * the WINS server address, if it exists, or ipzero if not.
- */
-
- unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET,
- unicast_ip, unicast_ip, unicast_ip);
-
- zero_ip(&ipzero);
-
- remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
- REMOTE_BROADCAST_SUBNET,
- ipzero, ipzero, ipzero);
-
- if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
- return False;
-
- /*
- * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
- * the linked list.
- */
-
- if (lp_we_are_a_wins_server())
- {
- if( (wins_server_subnet = make_subnet( "WINS_SERVER_SUBNET",
- WINS_SERVER_SUBNET,
- ipzero, ipzero, ipzero )) == NULL )
- return False;
- }
-
- return True;
-}
-
-/*******************************************************************
-Function to tell us if we can use the unicast subnet.
-******************************************************************/
-BOOL we_are_a_wins_client(void)
-{
- if (wins_srv_count() > 0) {
- return True;
- }
-
- return False;
-}
-
-/*******************************************************************
-Access function used by NEXT_SUBNET_INCLUDING_UNICAST
-******************************************************************/
-
-struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec)
-{
- if(subrec == unicast_subnet)
- return NULL;
- else if((subrec->next == NULL) && we_are_a_wins_client())
- return unicast_subnet;
- else
- return subrec->next;
-}
-
-/*******************************************************************
- Access function used by retransmit_or_expire_response_records() in
- nmbd_packets.c. Patch from Andrey Alekseyev <fetch@muffin.arcadia.spb.ru>
- Needed when we need to enumerate all the broadcast, unicast and
- WINS subnets.
-******************************************************************/
-
-struct subnet_record *get_next_subnet_maybe_unicast_or_wins_server(struct subnet_record *subrec)
-{
- if(subrec == unicast_subnet)
- {
- if(wins_server_subnet)
- return wins_server_subnet;
- else
- return NULL;
- }
-
- if(wins_server_subnet && subrec == wins_server_subnet)
- return NULL;
-
- if((subrec->next == NULL) && we_are_a_wins_client())
- return unicast_subnet;
- else
- return subrec->next;
-}
diff --git a/source4/nmbd/nmbd_synclists.c b/source4/nmbd/nmbd_synclists.c
deleted file mode 100644
index b9952fb446..0000000000
--- a/source4/nmbd/nmbd_synclists.c
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-/* this file handles asynchronous browse synchronisation requests. The
- requests are done by forking and putting the result in a file in the
- locks directory. We do it this way because we don't want nmbd to be
- blocked waiting for some server to respond on a TCP connection. This
- also allows us to have more than 1 sync going at once (tridge) */
-
-#include "includes.h"
-
-struct sync_record {
- struct sync_record *next, *prev;
- fstring workgroup;
- fstring server;
- pstring fname;
- struct in_addr ip;
- pid_t pid;
-};
-
-/* a linked list of current sync connections */
-static struct sync_record *syncs;
-
-static XFILE *fp;
-
-/*******************************************************************
- This is the NetServerEnum callback.
- Note sname and comment are in UNIX codepage format.
- ******************************************************************/
-static void callback(const char *sname, uint32 stype,
- const char *comment, void *state)
-{
- x_fprintf(fp,"\"%s\" %08X \"%s\"\n", sname, stype, comment);
-}
-
-/*******************************************************************
- Synchronise browse lists with another browse server.
- Log in on the remote server's SMB port to their IPC$ service,
- do a NetServerEnum and record the results in fname
-******************************************************************/
-static void sync_child(char *name, int nm_type,
- char *workgroup,
- struct in_addr ip, BOOL local, BOOL servers,
- char *fname)
-{
- extern fstring local_machine;
- fstring unix_workgroup;
- static struct cli_state cli;
- uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0;
- struct nmb_name called, calling;
-
- /* W2K DMB's return empty browse lists on port 445. Use 139.
- * Patch from Andy Levine andyl@epicrealm.com.
- */
-
- if (!cli_initialise(&cli) || !cli_set_port(&cli, 139) || !cli_connect(&cli, name, &ip)) {
- return;
- }
-
- make_nmb_name(&calling, local_machine, 0x0);
- make_nmb_name(&called , name , nm_type);
-
- if (!cli_session_request(&cli, &calling, &called))
- {
- cli_shutdown(&cli);
- return;
- }
-
- if (!cli_negprot(&cli)) {
- cli_shutdown(&cli);
- return;
- }
-
- if (!cli_session_setup(&cli, "", "", 1, "", 0, workgroup)) {
- cli_shutdown(&cli);
- return;
- }
-
- if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
- cli_shutdown(&cli);
- return;
- }
-
- /* All the cli_XX functions take UNIX character set. */
- fstrcpy(unix_workgroup, cli.server_domain?cli.server_domain:workgroup);
-
- /* Fetch a workgroup list. */
- cli_NetServerEnum(&cli, unix_workgroup,
- local_type|SV_TYPE_DOMAIN_ENUM,
- callback, NULL);
-
- /* Now fetch a server list. */
- if (servers) {
- fstrcpy(unix_workgroup, workgroup);
- cli_NetServerEnum(&cli, unix_workgroup,
- local?SV_TYPE_LOCAL_LIST_ONLY:SV_TYPE_ALL,
- callback, NULL);
- }
-
- cli_shutdown(&cli);
-}
-
-
-/*******************************************************************
- initialise a browse sync with another browse server. Log in on the
- remote server's SMB port to their IPC$ service, do a NetServerEnum
- and record the results
-******************************************************************/
-void sync_browse_lists(struct work_record *work,
- char *name, int nm_type,
- struct in_addr ip, BOOL local, BOOL servers)
-{
- struct sync_record *s;
- static int counter;
-
- START_PROFILE(sync_browse_lists);
- /* Check we're not trying to sync with ourselves. This can
- happen if we are a domain *and* a local master browser. */
- if (ismyip(ip)) {
-done:
- END_PROFILE(sync_browse_lists);
- return;
- }
-
- s = (struct sync_record *)malloc(sizeof(*s));
- if (!s) goto done;
-
- ZERO_STRUCTP(s);
-
- fstrcpy(s->workgroup, work->work_group);
- fstrcpy(s->server, name);
- s->ip = ip;
-
- slprintf(s->fname, sizeof(pstring)-1,
- "%s/sync.%d", lp_lockdir(), counter++);
- all_string_sub(s->fname,"//", "/", 0);
-
- DLIST_ADD(syncs, s);
-
- /* the parent forks and returns, leaving the child to do the
- actual sync and call END_PROFILE*/
- CatchChild();
- if ((s->pid = sys_fork())) return;
-
- BlockSignals( False, SIGTERM );
-
- DEBUG(2,("Initiating browse sync for %s to %s(%s)\n",
- work->work_group, name, inet_ntoa(ip)));
-
- fp = x_fopen(s->fname,O_WRONLY|O_CREAT|O_TRUNC, 0644);
- if (!fp) {
- END_PROFILE(sync_browse_lists);
- _exit(1);
- }
-
- sync_child(name, nm_type, work->work_group, ip, local, servers,
- s->fname);
-
- x_fclose(fp);
- END_PROFILE(sync_browse_lists);
- _exit(0);
-}
-
-/**********************************************************************
-handle one line from a completed sync file
- **********************************************************************/
-static void complete_one(struct sync_record *s,
- char *sname, uint32 stype, char *comment)
-{
- struct work_record *work;
- struct server_record *servrec;
-
- stype &= ~SV_TYPE_LOCAL_LIST_ONLY;
-
- if (stype & SV_TYPE_DOMAIN_ENUM) {
- /* See if we can find the workgroup on this subnet. */
- if((work=find_workgroup_on_subnet(unicast_subnet, sname))) {
- /* We already know about this workgroup -
- update the ttl. */
- update_workgroup_ttl(work,lp_max_ttl());
- } else {
- /* Create the workgroup on the subnet. */
- work = create_workgroup_on_subnet(unicast_subnet,
- sname, lp_max_ttl());
- if (work) {
- /* remember who the master is */
- fstrcpy(work->local_master_browser_name,
- comment);
- }
- }
- return;
- }
-
- work = find_workgroup_on_subnet(unicast_subnet, s->workgroup);
- if (!work) {
- DEBUG(3,("workgroup %s doesn't exist on unicast subnet?\n",
- s->workgroup));
- return;
- }
-
- if ((servrec = find_server_in_workgroup( work, sname))) {
- /* Check that this is not a locally known
- server - if so ignore the entry. */
- if(!(servrec->serv.type & SV_TYPE_LOCAL_LIST_ONLY)) {
- /* We already know about this server - update
- the ttl. */
- update_server_ttl(servrec, lp_max_ttl());
- /* Update the type. */
- servrec->serv.type = stype;
- }
- return;
- }
-
- /* Create the server in the workgroup. */
- create_server_on_workgroup(work, sname,stype, lp_max_ttl(), comment);
-}
-
-
-/**********************************************************************
-read the completed sync info
- **********************************************************************/
-static void complete_sync(struct sync_record *s)
-{
- XFILE *f;
- fstring server, type_str;
- unsigned type;
- pstring comment;
- pstring line;
- const char *ptr;
- int count=0;
-
- f = x_fopen(s->fname,O_RDONLY, 0);
-
- if (!f) return;
-
- while (!x_feof(f)) {
-
- if (!fgets_slash(line,sizeof(pstring),f)) continue;
-
- ptr = line;
-
- if (!next_token(&ptr,server,NULL,sizeof(server)) ||
- !next_token(&ptr,type_str,NULL, sizeof(type_str)) ||
- !next_token(&ptr,comment,NULL, sizeof(comment))) {
- continue;
- }
-
- sscanf(type_str, "%X", &type);
-
- complete_one(s, server, type, comment);
-
- count++;
- }
-
- x_fclose(f);
-
- unlink(s->fname);
-
- DEBUG(2,("sync with %s(%s) for workgroup %s completed (%d records)\n",
- s->server, inet_ntoa(s->ip), s->workgroup, count));
-}
-
-/**********************************************************************
-check for completion of any of the child processes
- **********************************************************************/
-void sync_check_completion(void)
-{
- struct sync_record *s, *next;
-
- for (s=syncs;s;s=next) {
- next = s->next;
- if (!process_exists(s->pid)) {
- /* it has completed - grab the info */
- complete_sync(s);
- DLIST_REMOVE(syncs, s);
- ZERO_STRUCTP(s);
- SAFE_FREE(s);
- }
- }
-}
diff --git a/source4/nmbd/nmbd_winsproxy.c b/source4/nmbd/nmbd_winsproxy.c
deleted file mode 100644
index 2e65ebb612..0000000000
--- a/source4/nmbd/nmbd_winsproxy.c
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
-
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-/****************************************************************************
-Function called when the name lookup succeeded.
-****************************************************************************/
-
-static void wins_proxy_name_query_request_success( struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname, struct in_addr ip, struct res_rec *rrec)
-{
- struct packet_struct *original_packet;
- struct subnet_record *orig_broadcast_subnet;
- struct name_record *namerec;
- uint16 nb_flags;
- int num_ips;
- int i;
- int ttl = 3600; /* By default one hour in the cache. */
- struct in_addr *iplist;
-
- /* Extract the original packet and the original broadcast subnet from
- the userdata. */
-
- memcpy( (char *)&orig_broadcast_subnet, userdata->data, sizeof(struct subnet_record *) );
- memcpy( (char *)&original_packet, &userdata->data[sizeof(struct subnet_record *)],
- sizeof(struct packet_struct *) );
-
- nb_flags = get_nb_flags( rrec->rdata );
-
- num_ips = rrec->rdlength / 6;
- if(num_ips == 0)
- {
- DEBUG(0,("wins_proxy_name_query_request_success: Invalid number of IP records (0) \
-returned for name %s.\n", nmb_namestr(nmbname) ));
- return;
- }
-
- if(num_ips == 1)
- iplist = &ip;
- else
- {
- if((iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) )) == NULL)
- {
- DEBUG(0,("wins_proxy_name_query_request_success: malloc fail !\n"));
- return;
- }
-
- for(i = 0; i < num_ips; i++)
- putip( (char *)&iplist[i], (char *)&rrec->rdata[ (i*6) + 2]);
- }
-
- /* Add the queried name to the original subnet as a WINS_PROXY_NAME. */
-
- if(rrec == PERMANENT_TTL)
- ttl = lp_max_ttl();
-
- namerec = add_name_to_subnet( orig_broadcast_subnet, nmbname->name,
- nmbname->name_type, nb_flags, ttl,
- WINS_PROXY_NAME, num_ips, iplist );
-
- if(iplist != &ip)
- SAFE_FREE(iplist);
-
- /*
- * Check that none of the IP addresses we are returning is on the
- * same broadcast subnet as the original requesting packet. If it
- * is then don't reply (although we still need to add the name
- * to the cache) as the actual machine will be replying also
- * and we don't want two replies to a broadcast query.
- */
-
- if(namerec && original_packet->packet.nmb.header.nm_flags.bcast)
- {
- for( i = 0; i < namerec->data.num_ips; i++)
- {
- if( same_net( namerec->data.ip[i],
- orig_broadcast_subnet->myip,
- orig_broadcast_subnet->mask_ip ) )
- {
- DEBUG( 5, ( "wins_proxy_name_query_request_success: name %s is a WINS \
-proxy name and is also on the same subnet (%s) as the requestor. \
-Not replying.\n",
- nmb_namestr(&namerec->name),
- orig_broadcast_subnet->subnet_name ) );
- return;
- }
- }
- }
-
- /* Finally reply to the original name query. */
- reply_netbios_packet(original_packet, /* Packet to reply to. */
- 0, /* Result code. */
- NMB_QUERY, /* nmbd type code. */
- NMB_NAME_QUERY_OPCODE, /* opcode. */
- ttl, /* ttl. */
- rrec->rdata, /* data to send. */
- rrec->rdlength); /* data length. */
-}
-
-/****************************************************************************
-Function called when the name lookup failed.
-****************************************************************************/
-
-static void wins_proxy_name_query_request_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *question_name, int fail_code)
-{
- DEBUG(4,("wins_proxy_name_query_request_fail: WINS server returned error code %d for lookup \
-of name %s.\n", fail_code, nmb_namestr(question_name) ));
-}
-
-/****************************************************************************
-Function to make a deep copy of the userdata we will need when the WINS
-proxy query returns.
-****************************************************************************/
-
-static struct userdata_struct *wins_proxy_userdata_copy_fn(struct userdata_struct *userdata)
-{
- struct packet_struct *p, *copy_of_p;
- struct userdata_struct *new_userdata =
- (struct userdata_struct *)malloc( userdata->userdata_len );
-
- if(new_userdata == NULL)
- return NULL;
-
- new_userdata->copy_fn = userdata->copy_fn;
- new_userdata->free_fn = userdata->free_fn;
- new_userdata->userdata_len = userdata->userdata_len;
-
- /* Copy the subnet_record pointer. */
- memcpy( new_userdata->data, userdata->data, sizeof(struct subnet_record *) );
-
- /* Extract the pointer to the packet struct */
- memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)],
- sizeof(struct packet_struct *) );
-
- /* Do a deep copy of the packet. */
- if((copy_of_p = copy_packet(p)) == NULL)
- {
- SAFE_FREE(new_userdata);
- return NULL;
- }
-
- /* Lock the copy. */
- copy_of_p->locked = True;
-
- memcpy( &new_userdata->data[sizeof(struct subnet_record *)], (char *)&copy_of_p,
- sizeof(struct packet_struct *) );
-
- return new_userdata;
-}
-
-/****************************************************************************
-Function to free the deep copy of the userdata we used when the WINS
-proxy query returned.
-****************************************************************************/
-
-static void wins_proxy_userdata_free_fn(struct userdata_struct *userdata)
-{
- struct packet_struct *p;
-
- /* Extract the pointer to the packet struct */
- memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)],
- sizeof(struct packet_struct *));
-
- /* Unlock the packet. */
- p->locked = False;
-
- free_packet(p);
- ZERO_STRUCTP(userdata);
- SAFE_FREE(userdata);
-}
-
-/****************************************************************************
- Make a WINS query on behalf of a broadcast client name query request.
-****************************************************************************/
-
-void make_wins_proxy_name_query_request( struct subnet_record *subrec,
- struct packet_struct *incoming_packet,
- struct nmb_name *question_name)
-{
- long *ud[(sizeof(struct userdata_struct) + sizeof(struct subrec *) +
- sizeof(struct packet_struct *))/sizeof(long *) + 1];
- struct userdata_struct *userdata = (struct userdata_struct *)ud;
-
- memset(ud, '\0', sizeof(ud));
-
- userdata->copy_fn = wins_proxy_userdata_copy_fn;
- userdata->free_fn = wins_proxy_userdata_free_fn;
- userdata->userdata_len = sizeof(ud);
- memcpy( userdata->data, (char *)&subrec, sizeof(struct subnet_record *));
- memcpy( &userdata->data[sizeof(struct subnet_record *)], (char *)&incoming_packet,
- sizeof(struct packet_struct *));
-
- /* Now use the unicast subnet to query the name with the WINS server. */
- query_name( unicast_subnet, question_name->name, question_name->name_type,
- wins_proxy_name_query_request_success,
- wins_proxy_name_query_request_fail,
- userdata);
-}
diff --git a/source4/nmbd/nmbd_winsserver.c b/source4/nmbd/nmbd_winsserver.c
deleted file mode 100644
index 6d1f654e84..0000000000
--- a/source4/nmbd/nmbd_winsserver.c
+++ /dev/null
@@ -1,2032 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
-
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-#define WINS_LIST "wins.tdb"
-#define WINS_VERSION 1
-
-/****************************************************************************
-change the wins owner address in the record.
-*****************************************************************************/
-static void update_wins_owner(struct name_record *namerec, struct in_addr wins_ip)
-{
- if (namerec==NULL)
- return;
- namerec->data.wins_ip=wins_ip;
-}
-
-/****************************************************************************
-create the wins flags based on the nb flags and the input value.
-*****************************************************************************/
-static void update_wins_flag(struct name_record *namerec, int flags)
-{
- if (namerec==NULL)
- return;
-
- namerec->data.wins_flags=0x0;
-
- /* if it's a group, it can be a normal or a special one */
- if (namerec->data.nb_flags & NB_GROUP) {
- if (namerec->name.name_type==0x1C)
- namerec->data.wins_flags|=WINS_SGROUP;
- else
- if (namerec->data.num_ips>1)
- namerec->data.wins_flags|=WINS_SGROUP;
- else
- namerec->data.wins_flags|=WINS_NGROUP;
- } else {
- /* can be unique or multi-homed */
- if (namerec->data.num_ips>1)
- namerec->data.wins_flags|=WINS_MHOMED;
- else
- namerec->data.wins_flags|=WINS_UNIQUE;
- }
-
- /* the node type are the same bits */
- namerec->data.wins_flags|=namerec->data.nb_flags&NB_NODETYPEMASK;
-
- /* the static bit is elsewhere */
- if (namerec->data.death_time == PERMANENT_TTL)
- namerec->data.wins_flags|=WINS_STATIC;
-
- /* and add the given bits */
- namerec->data.wins_flags|=flags;
-
- DEBUG(8,("update_wins_flag: nbflags: 0x%x, ttl: 0x%d, flags: 0x%x, winsflags: 0x%x\n",
- namerec->data.nb_flags, (int)namerec->data.death_time, flags, namerec->data.wins_flags));
-
-}
-
-/****************************************************************************
-return the general ID value and increase it if requested
-*****************************************************************************/
-static void get_global_id_and_update(SMB_BIG_UINT *current_id, BOOL update)
-{
- /*
- * it's kept as a static here, to prevent people from messing
- * with the value directly
- */
-
- static SMB_BIG_UINT general_id = 1;
-
- DEBUG(5,("get_global_id_and_update: updating version ID: %d\n", (int)general_id));
-
- *current_id = general_id;
-
- if (update)
- general_id++;
-}
-
-/****************************************************************************
-possibly call the WINS hook external program when a WINS change is made
-*****************************************************************************/
-static void wins_hook(const char *operation, struct name_record *namerec, int ttl)
-{
- pstring command;
- char *cmd = lp_wins_hook();
- char *p;
- int i;
-
- if (!cmd || !*cmd) return;
-
- for (p=namerec->name.name; *p; p++) {
- if (!(isalnum((int)*p) || strchr_m("._-",*p))) {
- DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name)));
- return;
- }
- }
-
- p = command;
- p += slprintf(p, sizeof(command)-1, "%s %s %s %02x %d",
- cmd,
- operation,
- namerec->name.name,
- namerec->name.name_type,
- ttl);
-
- for (i=0;i<namerec->data.num_ips;i++) {
- p += slprintf(p, sizeof(command) - (p-command) -1, " %s", inet_ntoa(namerec->data.ip[i]));
- }
-
- DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name)));
- smbrun(command, NULL);
-}
-
-
-/****************************************************************************
-Determine if this packet should be allocated to the WINS server.
-*****************************************************************************/
-
-BOOL packet_is_for_wins_server(struct packet_struct *packet)
-{
- struct nmb_packet *nmb = &packet->packet.nmb;
-
- /* Only unicast packets go to a WINS server. */
- if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True))
- {
- DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
- return False;
- }
-
- /* Check for node status requests. */
- if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
- return False;
-
- switch(nmb->header.opcode)
- {
- /*
- * A WINS server issues WACKS, not receives them.
- */
- case NMB_WACK_OPCODE:
- DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
- return False;
- /*
- * A WINS server only processes registration and
- * release requests, not responses.
- */
- case NMB_NAME_REG_OPCODE:
- case NMB_NAME_MULTIHOMED_REG_OPCODE:
- case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
- case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
- if(nmb->header.response)
- {
- DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
- return False;
- }
- break;
-
- case NMB_NAME_RELEASE_OPCODE:
- if(nmb->header.response)
- {
- DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
- return False;
- }
- break;
-
- /*
- * Only process unicast name queries with rd = 1.
- */
- case NMB_NAME_QUERY_OPCODE:
- if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired)
- {
- DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
- return False;
- }
- break;
- }
-
- return True;
-}
-
-/****************************************************************************
-Utility function to decide what ttl to give a register/refresh request.
-*****************************************************************************/
-
-static int get_ttl_from_packet(struct nmb_packet *nmb)
-{
- int ttl = nmb->additional->ttl;
-
- if(ttl < lp_min_wins_ttl() )
- ttl = lp_min_wins_ttl();
-
- if(ttl > lp_max_wins_ttl() )
- ttl = lp_max_wins_ttl();
-
- return ttl;
-}
-
-/****************************************************************************
-Load or create the WINS database.
-*****************************************************************************/
-
-BOOL initialise_wins(void)
-{
- time_t time_now = time(NULL);
- TDB_CONTEXT *tdb;
- TDB_DATA kbuf, dbuf, newkey;
- struct name_record *namerec = NULL;
- struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
-
- DEBUG(2,("initialise_wins: started\n"));
-
- if(!lp_we_are_a_wins_server())
- return True;
-
- add_samba_names_to_subnet(wins_server_subnet);
-
- tdb = tdb_open_log(lock_path(WINS_LIST), 0, TDB_DEFAULT, O_RDONLY, 0600);
- if (!tdb) {
- DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n", WINS_LIST, strerror(errno) ));
- return True;
- }
-
- if (tdb_fetch_int32(tdb, INFO_VERSION) != WINS_VERSION) {
- DEBUG(0,("Discarding invalid wins.dat file\n"));
- tdb_close(tdb);
- return True;
- }
-
- for (kbuf = tdb_firstkey(tdb);
- kbuf.dptr;
- newkey = tdb_nextkey(tdb, kbuf), safe_free(kbuf.dptr), kbuf=newkey) {
-
- fstring name_type;
- pstring name, ip_str;
- char *p;
- int type = 0;
- int nb_flags;
- int ttl;
- unsigned int num_ips;
- int high, low;
- struct in_addr wins_ip;
- struct in_addr *ip_list;
- int wins_flags;
- int len,i;
-
- if (strncmp(kbuf.dptr, ENTRY_PREFIX, strlen(ENTRY_PREFIX)) != 0)
- continue;
-
- dbuf = tdb_fetch(tdb, kbuf);
- if (!dbuf.dptr)
- continue;
-
- fstrcpy(name_type, kbuf.dptr+strlen(ENTRY_PREFIX));
-
- pstrcpy(name, name_type);
-
- if((p = strchr(name,'#')) != NULL) {
- *p = 0;
- sscanf(p+1,"%x",&type);
- }
-
- len = tdb_unpack(dbuf.dptr, dbuf.dsize, "dddfddd",
- &nb_flags, &high, &low,
- ip_str, &ttl, &num_ips, &wins_flags);
-
- wins_ip=*interpret_addr2(ip_str);
-
- /* Don't reload replica records */
- if (!ip_equal(wins_ip, our_fake_ip)) {
- SAFE_FREE(dbuf.dptr);
- continue;
- }
-
- /* Don't reload released or tombstoned records */
- if ((wins_flags&WINS_STATE_MASK) != WINS_ACTIVE) {
- SAFE_FREE(dbuf.dptr);
- continue;
- }
-
- /* Allocate the space for the ip_list. */
- if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL) {
- SAFE_FREE(dbuf.dptr);
- DEBUG(0,("initialise_wins: Malloc fail !\n"));
- return False;
- }
-
- for (i = 0; i < num_ips; i++) {
- len += tdb_unpack(dbuf.dptr+len, dbuf.dsize-len, "f", ip_str);
- ip_list[i] = *interpret_addr2(ip_str);
- }
-
- /* add all entries that have 60 seconds or more to live */
- if ((ttl - 60) > time_now || ttl == PERMANENT_TTL) {
- if(ttl != PERMANENT_TTL)
- ttl -= time_now;
-
- DEBUG( 4, ("initialise_wins: add name: %s#%02x ttl = %d first IP %s flags = %2x\n",
- name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
-
- namerec=add_name_to_subnet( wins_server_subnet, name, type, nb_flags,
- ttl, REGISTER_NAME, num_ips, ip_list);
- if (namerec!=NULL) {
- update_wins_owner(namerec, wins_ip);
- update_wins_flag(namerec, wins_flags);
- /* we don't reload the ID, on startup we restart at 1 */
- get_global_id_and_update(&namerec->data.id, True);
- }
-
- } else {
- DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %d first IP %s flags = %2x\n",
- name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
- }
-
- SAFE_FREE(dbuf.dptr);
- SAFE_FREE(ip_list);
- }
-
- tdb_close(tdb);
- DEBUG(2,("initialise_wins: done\n"));
- return True;
-}
-
-/****************************************************************************
-Send a WINS WACK (Wait ACKnowledgement) response.
-**************************************************************************/
-
-static void send_wins_wack_response(int ttl, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- unsigned char rdata[2];
-
- rdata[0] = rdata[1] = 0;
-
- /* Taken from nmblib.c - we need to send back almost
- identical bytes from the requesting packet header. */
-
- rdata[0] = (nmb->header.opcode & 0xF) << 3;
- if (nmb->header.nm_flags.authoritative &&
- nmb->header.response) rdata[0] |= 0x4;
- if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2;
- if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1;
- if (nmb->header.nm_flags.recursion_available &&
- nmb->header.response) rdata[1] |= 0x80;
- if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10;
-
- reply_netbios_packet(p, /* Packet to reply to. */
- 0, /* Result code. */
- NMB_WAIT_ACK, /* nmbd type code. */
- NMB_WACK_OPCODE, /* opcode. */
- ttl, /* ttl. */
- (char *)rdata, /* data to send. */
- 2); /* data length. */
-}
-
-/****************************************************************************
-Send a WINS name registration response.
-**************************************************************************/
-
-static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- char rdata[6];
-
- memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- WINS_REG, /* nmbd type code. */
- NMB_NAME_REG_OPCODE, /* opcode. */
- ttl, /* ttl. */
- rdata, /* data to send. */
- 6); /* data length. */
-}
-
-/***********************************************************************
- Deal with a name refresh request to a WINS server.
-************************************************************************/
-
-void wins_process_name_refresh_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- BOOL group = (nb_flags & NB_GROUP) ? True : False;
- struct name_record *namerec = NULL;
- int ttl = get_ttl_from_packet(nmb);
- struct in_addr from_ip;
- struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
-
- if(bcast)
- {
- /*
- * We should only get unicast name refresh packets here.
- * Anyone trying to refresh broadcast should not be going to a WINS
- * server. Log an error here.
- */
-
- DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
-received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
- nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
- return;
- }
-
- DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
-IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
-
- /*
- * See if the name already exists.
- */
-
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- /*
- * If this is a refresh request and the name doesn't exist then
- * treat it like a registration request. This allows us to recover
- * from errors (tridge)
- */
-
- if(namerec == NULL)
- {
- DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
-the name does not exist. Treating as registration.\n", nmb_namestr(question) ));
- wins_process_name_registration_request(subrec,p);
- return;
- }
-
- /*
- * if the name is present but not active,
- * simply remove it and treat the request
- * as a registration
- */
- if (namerec != NULL && !WINS_STATE_ACTIVE(namerec))
- {
- DEBUG(5,("wins_process_name_refresh_request: Name (%s) in WINS was \
-not active - removing it.\n", nmb_namestr(question) ));
- remove_name_from_namelist( subrec, namerec );
- namerec = NULL;
- wins_process_name_registration_request(subrec,p);
- return;
- }
-
- /*
- * Check that the group bits for the refreshing name and the
- * name in our database match.
- */
-
- if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) )
- {
- DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
-does not match group bit in WINS for this name.\n", nmb_namestr(question), group ? "True" : "False" ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
-
- /*
- * For a unique name check that the person refreshing the name is one of the registered IP
- * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
- * Just return success for unique 0x1d refreshes. For normal group names update the ttl
- * and return success.
- */
-
- if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip ))
- {
- /*
- * Update the ttl.
- */
- update_name_ttl(namerec, ttl);
-
- /*
- * if the record is a replica:
- * we take ownership and update the version ID.
- */
- if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
- update_wins_owner(namerec, our_fake_ip);
- get_global_id_and_update(&namerec->data.id, True);
- }
-
- send_wins_name_registration_response(0, ttl, p);
- wins_hook("refresh", namerec, ttl);
- return;
- }
- else if(group)
- {
- /*
- * Normal groups are all registered with an IP address of 255.255.255.255
- * so we can't search for the IP address.
- */
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
- else if(!group && (question->name_type == 0x1d))
- {
- /*
- * Special name type - just pretend the refresh succeeded.
- */
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
- else
- {
- /*
- * Fail the refresh.
- */
-
- DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
-is IP is not known to the name.\n", nmb_namestr(question), inet_ntoa(from_ip) ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
-}
-
-/***********************************************************************
- Deal with a name registration request query success to a client that
- owned the name.
-
- We have a locked pointer to the original packet stashed away in the
- userdata pointer. The success here is actually a failure as it means
- the client we queried wants to keep the name, so we must return
- a registration failure to the original requestor.
-************************************************************************/
-
-static void wins_register_query_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *question_name,
- struct in_addr ip,
- struct res_rec *answers)
-{
- struct packet_struct *orig_reg_packet;
-
- memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
-
- DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
-name %s. Rejecting registration request.\n", inet_ntoa(ip), nmb_namestr(question_name) ));
-
- send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
-
- orig_reg_packet->locked = False;
- free_packet(orig_reg_packet);
-}
-
-/***********************************************************************
- Deal with a name registration request query failure to a client that
- owned the name.
-
- We have a locked pointer to the original packet stashed away in the
- userdata pointer. The failure here is actually a success as it means
- the client we queried didn't want to keep the name, so we can remove
- the old name record and then successfully add the new name.
-************************************************************************/
-
-static void wins_register_query_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *question_name,
- int rcode)
-{
- struct userdata_struct *userdata = rrec->userdata;
- struct packet_struct *orig_reg_packet;
- struct name_record *namerec = NULL;
-
- memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
-
- /*
- * We want to just add the name, as we now know the original owner
- * didn't want it. But we can't just do that as an arbitary
- * amount of time may have taken place between the name query
- * request and this timeout/error response. So we check that
- * the name still exists and is in the same state - if so
- * we remove it and call wins_process_name_registration_request()
- * as we know it will do the right thing now.
- */
-
- namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
-
- if( (namerec != NULL)
- && (namerec->data.source == REGISTER_NAME)
- && ip_equal(rrec->packet->ip, *namerec->data.ip) )
- {
- remove_name_from_namelist( subrec, namerec);
- namerec = NULL;
- }
-
- if(namerec == NULL)
- wins_process_name_registration_request(subrec, orig_reg_packet);
- else
- DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
-querying for name %s in order to replace it and this reply.\n", nmb_namestr(question_name) ));
-
- orig_reg_packet->locked = False;
- free_packet(orig_reg_packet);
-}
-
-/***********************************************************************
- Deal with a name registration request to a WINS server.
-
- Use the following pseudocode :
-
- registering_group
- |
- |
- +--------name exists
- | |
- | |
- | +--- existing name is group
- | | |
- | | |
- | | +--- add name (return).
- | |
- | |
- | +--- exiting name is unique
- | |
- | |
- | +--- query existing owner (return).
- |
- |
- +--------name doesn't exist
- |
- |
- +--- add name (return).
-
- registering_unique
- |
- |
- +--------name exists
- | |
- | |
- | +--- existing name is group
- | | |
- | | |
- | | +--- fail add (return).
- | |
- | |
- | +--- exiting name is unique
- | |
- | |
- | +--- query existing owner (return).
- |
- |
- +--------name doesn't exist
- |
- |
- +--- add name (return).
-
- As can be seen from the above, the two cases may be collapsed onto each
- other with the exception of the case where the name already exists and
- is a group name. This case we handle with an if statement.
-
-************************************************************************/
-
-void wins_process_name_registration_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- int ttl = get_ttl_from_packet(nmb);
- struct name_record *namerec = NULL;
- struct in_addr from_ip;
- BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;
- struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
-
- if(bcast)
- {
- /*
- * We should only get unicast name registration packets here.
- * Anyone trying to register broadcast should not be going to a WINS
- * server. Log an error here.
- */
-
- DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
-received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
- nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
- return;
- }
-
- DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
-IP %s\n", registering_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
-
- /*
- * See if the name already exists.
- */
-
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- /*
- * if the record exists but NOT in active state,
- * consider it dead.
- */
- if ( (namerec != NULL) && !WINS_STATE_ACTIVE(namerec))
- {
- DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
-not active - removing it.\n", nmb_namestr(question) ));
- remove_name_from_namelist( subrec, namerec );
- namerec = NULL;
- }
-
- /*
- * Deal with the case where the name found was a dns entry.
- * Remove it as we now have a NetBIOS client registering the
- * name.
- */
-
- if( (namerec != NULL)
- && ( (namerec->data.source == DNS_NAME)
- || (namerec->data.source == DNSFAIL_NAME) ) )
- {
- DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was \
-a dns lookup - removing it.\n", nmb_namestr(question) ));
- remove_name_from_namelist( subrec, namerec );
- namerec = NULL;
- }
-
- /*
- * Reject if the name exists and is not a REGISTER_NAME.
- * (ie. Don't allow any static names to be overwritten.
- */
-
- if((namerec != NULL) && (namerec->data.source != REGISTER_NAME))
- {
- DEBUG( 3, ( "wins_process_name_registration_request: Attempt \
-to register name %s. Name already exists in WINS with source type %d.\n",
- nmb_namestr(question), namerec->data.source ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
-
- /*
- * Special policy decisions based on MS documentation.
- * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
- * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
- */
-
- /*
- * A group name is always added as the local broadcast address, except
- * for group names ending in 0x1c.
- * Group names with type 0x1c are registered with individual IP addresses.
- */
-
- if(registering_group_name && (question->name_type != 0x1c))
- from_ip = *interpret_addr2("255.255.255.255");
-
- /*
- * Ignore all attempts to register a unique 0x1d name, although return success.
- */
-
- if(!registering_group_name && (question->name_type == 0x1d))
- {
- DEBUG(3,("wins_process_name_registration_request: Ignoring request \
-to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) ));
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
-
- /*
- * Next two cases are the 'if statement' mentioned above.
- */
-
- if((namerec != NULL) && NAME_GROUP(namerec))
- {
- if(registering_group_name)
- {
- /*
- * If we are adding a group name, the name exists and is also a group entry just add this
- * IP address to it and update the ttl.
- */
-
- DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
- inet_ntoa(from_ip), nmb_namestr(question) ));
- /*
- * Check the ip address is not already in the group.
- */
- if(!find_ip_in_name_record(namerec, from_ip)) {
- add_ip_to_name_record(namerec, from_ip);
- /* we need to update the record for replication */
- get_global_id_and_update(&namerec->data.id, True);
-
- /*
- * if the record is a replica, we must change
- * the wins owner to us to make the replication updates
- * it on the other wins servers.
- * And when the partner will receive this record,
- * it will update its own record.
- */
-
- update_wins_owner(namerec, our_fake_ip);
-
- }
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
- else
- {
- /*
- * If we are adding a unique name, the name exists in the WINS db
- * and is a group name then reject the registration.
- *
- * explanation: groups have a higher priority than unique names.
- */
-
- DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
-already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
- }
-
- /*
- * From here on down we know that if the name exists in the WINS db it is
- * a unique name, not a group name.
- */
-
- /*
- * If the name exists and is one of our names then check the
- * registering IP address. If it's not one of ours then automatically
- * reject without doing the query - we know we will reject it.
- */
-
- if((namerec != NULL) && (is_myname(namerec->name.name)) )
- {
- if(!ismyip(from_ip))
- {
- DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
-is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
- else
- {
- /*
- * It's one of our names and one of our IP's - update the ttl.
- */
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
- wins_hook("refresh", namerec, ttl);
- return;
- }
- }
-
- /*
- * If the name exists and it is a unique registration and the registering IP
- * is the same as the (single) already registered IP then just update the ttl.
- *
- * But not if the record is an active replica. IF it's a replica, it means it can be
- * the same client which has moved and not yet expired. So we don't update
- * the ttl in this case and go beyond to do a WACK and query the old client
- */
-
- if( !registering_group_name
- && (namerec != NULL)
- && (namerec->data.num_ips == 1)
- && ip_equal( namerec->data.ip[0], from_ip )
- && ip_equal(namerec->data.wins_ip, our_fake_ip) )
- {
- update_name_ttl( namerec, ttl );
- send_wins_name_registration_response( 0, ttl, p );
- wins_hook("refresh", namerec, ttl);
- return;
- }
-
- /*
- * Finally if the name exists do a query to the registering machine
- * to see if they still claim to have the name.
- */
-
- if( namerec != NULL )
- {
- long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
- struct userdata_struct *userdata = (struct userdata_struct *)ud;
-
- /*
- * First send a WACK to the registering machine.
- */
-
- send_wins_wack_response(60, p);
-
- /*
- * When the reply comes back we need the original packet.
- * Lock this so it won't be freed and then put it into
- * the userdata structure.
- */
-
- p->locked = True;
-
- userdata = (struct userdata_struct *)ud;
-
- userdata->copy_fn = NULL;
- userdata->free_fn = NULL;
- userdata->userdata_len = sizeof(struct packet_struct *);
- memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
-
- /*
- * Use the new call to send a query directly to an IP address.
- * This sends the query directly to the IP address, and ensures
- * the recursion desired flag is not set (you were right Luke :-).
- * This function should *only* be called from the WINS server
- * code. JRA.
- */
-
- query_name_from_wins_server( *namerec->data.ip,
- question->name,
- question->name_type,
- wins_register_query_success,
- wins_register_query_fail,
- userdata );
- return;
- }
-
- /*
- * Name did not exist - add it.
- */
-
- (void)add_name_to_subnet( subrec, question->name, question->name_type,
- nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
- if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
- get_global_id_and_update(&namerec->data.id, True);
- update_wins_owner(namerec, our_fake_ip);
- update_wins_flag(namerec, WINS_ACTIVE);
- wins_hook("add", namerec, ttl);
- }
-
- send_wins_name_registration_response(0, ttl, p);
-}
-
-/***********************************************************************
- Deal with a mutihomed name query success to the machine that
- requested the multihomed name registration.
-
- We have a locked pointer to the original packet stashed away in the
- userdata pointer.
-************************************************************************/
-
-static void wins_multihomed_register_query_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *question_name,
- struct in_addr ip,
- struct res_rec *answers)
-{
- struct packet_struct *orig_reg_packet;
- struct nmb_packet *nmb;
- struct name_record *namerec = NULL;
- struct in_addr from_ip;
- int ttl;
- struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
-
- memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
-
- nmb = &orig_reg_packet->packet.nmb;
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
- ttl = get_ttl_from_packet(nmb);
-
- /*
- * We want to just add the new IP, as we now know the requesting
- * machine claims to own it. But we can't just do that as an arbitary
- * amount of time may have taken place between the name query
- * request and this response. So we check that
- * the name still exists and is in the same state - if so
- * we just add the extra IP and update the ttl.
- */
-
- namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
-
- if( (namerec == NULL) || (namerec->data.source != REGISTER_NAME) || !WINS_STATE_ACTIVE(namerec) )
- {
- DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
-a subsequent IP address.\n", nmb_namestr(question_name) ));
- send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
-
- orig_reg_packet->locked = False;
- free_packet(orig_reg_packet);
-
- return;
- }
-
- if(!find_ip_in_name_record(namerec, from_ip))
- add_ip_to_name_record(namerec, from_ip);
-
- get_global_id_and_update(&namerec->data.id, True);
- update_wins_owner(namerec, our_fake_ip);
- update_wins_flag(namerec, WINS_ACTIVE);
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, orig_reg_packet);
- wins_hook("add", namerec, ttl);
-
- orig_reg_packet->locked = False;
- free_packet(orig_reg_packet);
-}
-
-/***********************************************************************
- Deal with a name registration request query failure to a client that
- owned the name.
-
- We have a locked pointer to the original packet stashed away in the
- userdata pointer.
-************************************************************************/
-
-static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *question_name,
- int rcode)
-{
- struct userdata_struct *userdata = rrec->userdata;
- struct packet_struct *orig_reg_packet;
-
- memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
-
- DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
-query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), nmb_namestr(question_name) ));
- send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
-
- orig_reg_packet->locked = False;
- free_packet(orig_reg_packet);
- return;
-}
-
-/***********************************************************************
- Deal with a multihomed name registration request to a WINS server.
- These cannot be group name registrations.
-***********************************************************************/
-
-void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- int ttl = get_ttl_from_packet(nmb);
- struct name_record *namerec = NULL;
- struct in_addr from_ip;
- BOOL group = (nb_flags & NB_GROUP) ? True : False;
- struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
-
- if(bcast)
- {
- /*
- * We should only get unicast name registration packets here.
- * Anyone trying to register broadcast should not be going to a WINS
- * server. Log an error here.
- */
-
- DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
-received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
- nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
- return;
- }
-
- /*
- * Only unique names should be registered multihomed.
- */
-
- if(group)
- {
- DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
-received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
- nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
- return;
- }
-
- DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
-IP %s\n", nmb_namestr(question), inet_ntoa(from_ip) ));
-
- /*
- * Deal with policy regarding 0x1d names.
- */
-
- if(question->name_type == 0x1d)
- {
- DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
-to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
-
- /*
- * See if the name already exists.
- */
-
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- /*
- * if the record exists but NOT in active state,
- * consider it dead.
- */
- if ((namerec != NULL) && !WINS_STATE_ACTIVE(namerec)) {
- DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was not active - removing it.\n", nmb_namestr(question)));
- remove_name_from_namelist(subrec, namerec);
- namerec = NULL;
- }
-
- /*
- * Deal with the case where the name found was a dns entry.
- * Remove it as we now have a NetBIOS client registering the
- * name.
- */
-
- if( (namerec != NULL)
- && ( (namerec->data.source == DNS_NAME)
- || (namerec->data.source == DNSFAIL_NAME) ) )
- {
- DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
-- removing it.\n", nmb_namestr(question) ));
- remove_name_from_namelist( subrec, namerec);
- namerec = NULL;
- }
-
- /*
- * Reject if the name exists and is not a REGISTER_NAME.
- * (ie. Don't allow any static names to be overwritten.
- */
-
- if( (namerec != NULL) && (namerec->data.source != REGISTER_NAME) )
- {
- DEBUG( 3, ( "wins_process_multihomed_name_registration_request: Attempt \
-to register name %s. Name already exists in WINS with source type %d.\n",
- nmb_namestr(question), namerec->data.source ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
-
- /*
- * Reject if the name exists and is a GROUP name and is active.
- */
-
- if((namerec != NULL) && NAME_GROUP(namerec) && WINS_STATE_ACTIVE(namerec))
- {
- DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
-already exists in WINS as a GROUP name.\n", nmb_namestr(question) ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
-
- /*
- * From here on down we know that if the name exists in the WINS db it is
- * a unique name, not a group name.
- */
-
- /*
- * If the name exists and is one of our names then check the
- * registering IP address. If it's not one of ours then automatically
- * reject without doing the query - we know we will reject it.
- */
-
- if((namerec != NULL) && (is_myname(namerec->name.name)) )
- {
- if(!ismyip(from_ip))
- {
- DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
-is one of our (WINS server) names. Denying registration.\n", nmb_namestr(question) ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
- else
- {
- /*
- * It's one of our names and one of our IP's. Ensure the IP is in the record and
- * update the ttl. Update the version ID to force replication.
- */
- if(!find_ip_in_name_record(namerec, from_ip)) {
- get_global_id_and_update(&namerec->data.id, True);
- update_wins_owner(namerec, our_fake_ip);
- update_wins_flag(namerec, WINS_ACTIVE);
-
- add_ip_to_name_record(namerec, from_ip);
- wins_hook("add", namerec, ttl);
- } else {
- wins_hook("refresh", namerec, ttl);
- }
-
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
- }
-
- /*
- * If the name exists and is active, check if the IP address is already registered
- * to that name. If so then update the ttl and reply success.
- */
-
- if((namerec != NULL) && find_ip_in_name_record(namerec, from_ip) && WINS_STATE_ACTIVE(namerec))
- {
- update_name_ttl(namerec, ttl);
- /*
- * If it's a replica, we need to become the wins owner
- * to force the replication
- */
- if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
- get_global_id_and_update(&namerec->data.id, True);
- update_wins_owner(namerec, our_fake_ip);
- update_wins_flag(namerec, WINS_ACTIVE);
- }
-
- send_wins_name_registration_response(0, ttl, p);
- wins_hook("refresh", namerec, ttl);
- return;
- }
-
- /*
- * If the name exists do a query to the owner
- * to see if they still want the name.
- */
-
- if(namerec != NULL)
- {
- long *ud[(sizeof(struct userdata_struct) + sizeof(struct packet_struct *))/sizeof(long *) + 1];
- struct userdata_struct *userdata = (struct userdata_struct *)ud;
-
- /*
- * First send a WACK to the registering machine.
- */
-
- send_wins_wack_response(60, p);
-
- /*
- * When the reply comes back we need the original packet.
- * Lock this so it won't be freed and then put it into
- * the userdata structure.
- */
-
- p->locked = True;
-
- userdata = (struct userdata_struct *)ud;
-
- userdata->copy_fn = NULL;
- userdata->free_fn = NULL;
- userdata->userdata_len = sizeof(struct packet_struct *);
- memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
-
- /*
- * Use the new call to send a query directly to an IP address.
- * This sends the query directly to the IP address, and ensures
- * the recursion desired flag is not set (you were right Luke :-).
- * This function should *only* be called from the WINS server
- * code. JRA.
- *
- * Note that this packet is sent to the current owner of the name,
- * not the person who sent the packet
- */
-
- query_name_from_wins_server( namerec->data.ip[0],
- question->name,
- question->name_type,
- wins_multihomed_register_query_success,
- wins_multihomed_register_query_fail,
- userdata );
-
- return;
- }
-
- /*
- * Name did not exist - add it.
- */
-
- (void)add_name_to_subnet( subrec, question->name, question->name_type,
- nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
-
- if ((namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME))) {
- get_global_id_and_update(&namerec->data.id, True);
- update_wins_owner(namerec, our_fake_ip);
- update_wins_flag(namerec, WINS_ACTIVE);
- wins_hook("add", namerec, ttl);
- }
-
- send_wins_name_registration_response(0, ttl, p);
-}
-
-/***********************************************************************
- Deal with the special name query for *<1b>.
-***********************************************************************/
-
-static void process_wins_dmb_query_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct name_record *namerec = NULL;
- char *prdata;
- int num_ips;
-
- /*
- * Go through all the ACTIVE names in the WINS db looking for those
- * ending in <1b>. Use this to calculate the number of IP
- * addresses we need to return.
- */
-
- num_ips = 0;
- for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
- namerec;
- namerec = (struct name_record *)ubi_trNext( namerec ) )
- {
- if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b )
- num_ips += namerec->data.num_ips;
- }
-
- if(num_ips == 0)
- {
- /*
- * There are no 0x1b names registered. Return name query fail.
- */
- send_wins_name_query_response(NAM_ERR, p, NULL);
- return;
- }
-
- if((prdata = (char *)malloc( num_ips * 6 )) == NULL)
- {
- DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
- return;
- }
-
- /*
- * Go through all the names again in the WINS db looking for those
- * ending in <1b>. Add their IP addresses into the list we will
- * return.
- */
-
- num_ips = 0;
- for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist );
- namerec;
- namerec = (struct name_record *)ubi_trNext( namerec ) )
- {
- if(WINS_STATE_ACTIVE(namerec) && namerec->name.name_type == 0x1b)
- {
- int i;
- for(i = 0; i < namerec->data.num_ips; i++)
- {
- set_nb_flags(&prdata[num_ips * 6],namerec->data.nb_flags);
- putip((char *)&prdata[(num_ips * 6) + 2], &namerec->data.ip[i]);
- num_ips++;
- }
- }
- }
-
- /*
- * Send back the reply containing the IP list.
- */
-
- reply_netbios_packet(p, /* Packet to reply to. */
- 0, /* Result code. */
- WINS_QUERY, /* nmbd type code. */
- NMB_NAME_QUERY_OPCODE, /* opcode. */
- lp_min_wins_ttl(), /* ttl. */
- prdata, /* data to send. */
- num_ips*6); /* data length. */
-
- SAFE_FREE(prdata);
-}
-
-/****************************************************************************
-Send a WINS name query response.
-**************************************************************************/
-
-void send_wins_name_query_response(int rcode, struct packet_struct *p,
- struct name_record *namerec)
-{
- char rdata[6];
- char *prdata = rdata;
- int reply_data_len = 0;
- int ttl = 0;
- int i;
-
- memset(rdata,'\0',6);
-
- if(rcode == 0)
- {
- ttl = (namerec->data.death_time != PERMANENT_TTL) ?
- namerec->data.death_time - p->timestamp : lp_max_wins_ttl();
-
- /* Copy all known ip addresses into the return data. */
- /* Optimise for the common case of one IP address so
- we don't need a malloc. */
-
- if( namerec->data.num_ips == 1 )
- prdata = rdata;
- else
- {
- if((prdata = (char *)malloc( namerec->data.num_ips * 6 )) == NULL)
- {
- DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
- return;
- }
- }
-
- for(i = 0; i < namerec->data.num_ips; i++)
- {
- set_nb_flags(&prdata[i*6],namerec->data.nb_flags);
- putip((char *)&prdata[2+(i*6)], &namerec->data.ip[i]);
- }
-
- sort_query_replies(prdata, i, p->ip);
-
- reply_data_len = namerec->data.num_ips * 6;
- }
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- WINS_QUERY, /* nmbd type code. */
- NMB_NAME_QUERY_OPCODE, /* opcode. */
- ttl, /* ttl. */
- prdata, /* data to send. */
- reply_data_len); /* data length. */
-
- if(prdata != rdata)
- SAFE_FREE(prdata);
-}
-
-/***********************************************************************
- Deal with a name query.
-***********************************************************************/
-
-void wins_process_name_query_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- struct name_record *namerec = NULL;
-
- DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
- nmb_namestr(question), inet_ntoa(p->ip) ));
-
- /*
- * Special name code. If the queried name is *<1b> then search
- * the entire WINS database and return a list of all the IP addresses
- * registered to any <1b> name. This is to allow domain master browsers
- * to discover other domains that may not have a presence on their subnet.
- */
-
- if(strequal( question->name, "*") && (question->name_type == 0x1b))
- {
- process_wins_dmb_query_request( subrec, p);
- return;
- }
-
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- if(namerec != NULL)
- {
- /*
- * If the name is not anymore in active state then reply not found.
- * it's fair even if we keep it in the cache for days.
- */
- if (!WINS_STATE_ACTIVE(namerec))
- {
- DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
- nmb_namestr(question) ));
- send_wins_name_query_response(NAM_ERR, p, namerec);
- return;
- }
- /*
- * If it's a DNSFAIL_NAME then reply name not found.
- */
-
- if( namerec->data.source == DNSFAIL_NAME )
- {
- DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
- nmb_namestr(question) ));
- send_wins_name_query_response(NAM_ERR, p, namerec);
- return;
- }
-
- /*
- * If the name has expired then reply name not found.
- */
-
- if( (namerec->data.death_time != PERMANENT_TTL)
- && (namerec->data.death_time < p->timestamp) )
- {
- DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
- nmb_namestr(question) ));
- send_wins_name_query_response(NAM_ERR, p, namerec);
- return;
- }
-
- DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
- nmb_namestr(question), inet_ntoa(namerec->data.ip[0]) ));
-
- send_wins_name_query_response(0, p, namerec);
- return;
- }
-
- /*
- * Name not found in WINS - try a dns query if it's a 0x20 name.
- */
-
- if(lp_dns_proxy() &&
- ((question->name_type == 0x20) || question->name_type == 0))
- {
-
- DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
- nmb_namestr(question) ));
-
- queue_dns_query(p, question, &namerec);
- return;
- }
-
- /*
- * Name not found - return error.
- */
-
- send_wins_name_query_response(NAM_ERR, p, NULL);
-}
-
-/****************************************************************************
-Send a WINS name release response.
-**************************************************************************/
-
-static void send_wins_name_release_response(int rcode, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- char rdata[6];
-
- memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- NMB_REL, /* nmbd type code. */
- NMB_NAME_RELEASE_OPCODE, /* opcode. */
- 0, /* ttl. */
- rdata, /* data to send. */
- 6); /* data length. */
-}
-
-/***********************************************************************
- Deal with a name release.
-***********************************************************************/
-
-void wins_process_name_release_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- struct name_record *namerec = NULL;
- struct in_addr from_ip;
- BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
-
- if(bcast)
- {
- /*
- * We should only get unicast name registration packets here.
- * Anyone trying to register broadcast should not be going to a WINS
- * server. Log an error here.
- */
-
- DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
-received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
- nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
- return;
- }
-
- DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
-IP %s\n", releasing_group_name ? "Group" : "Unique", nmb_namestr(question), inet_ntoa(from_ip) ));
-
- /*
- * Deal with policy regarding 0x1d names.
- */
-
- if(!releasing_group_name && (question->name_type == 0x1d))
- {
- DEBUG(3,("wins_process_name_release_request: Ignoring request \
-to release name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) ));
- send_wins_name_release_response(0, p);
- return;
- }
-
- /*
- * See if the name already exists.
- */
-
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- if( (namerec == NULL)
- || ((namerec != NULL) && (namerec->data.source != REGISTER_NAME)) )
- {
- send_wins_name_release_response(NAM_ERR, p);
- return;
- }
-
- /*
- * Check that the sending machine has permission to release this name.
- * If it's a group name not ending in 0x1c then just say yes and let
- * the group time out.
- */
-
- if(releasing_group_name && (question->name_type != 0x1c))
- {
- send_wins_name_release_response(0, p);
- return;
- }
-
- /*
- * Check that the releasing node is on the list of IP addresses
- * for this name. Disallow the release if not.
- */
-
- if(!find_ip_in_name_record(namerec, from_ip))
- {
- DEBUG(3,("wins_process_name_release_request: Refusing request to \
-release name %s as IP %s is not one of the known IP's for this name.\n",
- nmb_namestr(question), inet_ntoa(from_ip) ));
- send_wins_name_release_response(NAM_ERR, p);
- return;
- }
-
- /*
- * Check if the record is active. IF it's already released
- * or tombstoned, refuse the release.
- */
- if (!WINS_STATE_ACTIVE(namerec)) {
- DEBUG(3,("wins_process_name_release_request: Refusing request to \
-release name %s as this record is not anymore active.\n",
- nmb_namestr(question) ));
- send_wins_name_release_response(NAM_ERR, p);
- return;
- }
-
- /*
- * Check if the record is a 0x1c group
- * and has more then one ip
- * remove only this address.
- */
-
- if(releasing_group_name &&
- (question->name_type == 0x1c) &&
- (namerec->data.num_ips > 1)) {
- remove_ip_from_name_record(namerec, from_ip);
- DEBUG(3,("wins_process_name_release_request: Remove IP %s from NAME: %s\n",
- inet_ntoa(from_ip),nmb_namestr(question)));
- send_wins_name_release_response(0, p);
- return;
- }
-
- /*
- * Send a release response.
- * Flag the name as released and update the ttl
- */
-
- send_wins_name_release_response(0, p);
-
- namerec->data.wins_flags |= WINS_RELEASED;
- update_name_ttl(namerec, EXTINCTION_INTERVAL);
-
- wins_hook("delete", namerec, 0);
-}
-
-/*******************************************************************
- WINS time dependent processing.
-******************************************************************/
-
-void initiate_wins_processing(time_t t)
-{
- static time_t lasttime = 0;
- struct name_record *namerec;
- struct name_record *next_namerec;
- struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
-
- if (!lasttime)
- lasttime = t;
- if (t - lasttime < 20)
- return;
-
- lasttime = t;
-
- if(!lp_we_are_a_wins_server())
- return;
-
- for( namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
- namerec;
- namerec = next_namerec ) {
- next_namerec = (struct name_record *)ubi_trNext( namerec );
-
- if( (namerec->data.death_time != PERMANENT_TTL)
- && (namerec->data.death_time < t) ) {
-
- if( namerec->data.source == SELF_NAME ) {
- DEBUG( 3, ( "expire_names_on_subnet: Subnet %s not expiring SELF name %s\n",
- wins_server_subnet->subnet_name, nmb_namestr(&namerec->name) ) );
- namerec->data.death_time += 300;
- namerec->subnet->namelist_changed = True;
- continue;
- }
-
- /* handle records, samba is the wins owner */
- if (ip_equal(namerec->data.wins_ip, our_fake_ip)) {
- switch (namerec->data.wins_flags | WINS_STATE_MASK) {
- case WINS_ACTIVE:
- namerec->data.wins_flags&=~WINS_STATE_MASK;
- namerec->data.wins_flags|=WINS_RELEASED;
- namerec->data.death_time = t + EXTINCTION_INTERVAL;
- DEBUG(3,("initiate_wins_processing: expiring %s\n", nmb_namestr(&namerec->name)));
- break;
- case WINS_RELEASED:
- namerec->data.wins_flags&=~WINS_STATE_MASK;
- namerec->data.wins_flags|=WINS_TOMBSTONED;
- namerec->data.death_time = t + EXTINCTION_TIMEOUT;
- get_global_id_and_update(&namerec->data.id, True);
- DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
- break;
- case WINS_TOMBSTONED:
- DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
- remove_name_from_namelist( wins_server_subnet, namerec );
- break;
- }
- } else {
- switch (namerec->data.wins_flags | WINS_STATE_MASK) {
- case WINS_ACTIVE:
- /* that's not as MS says it should be */
- namerec->data.wins_flags&=~WINS_STATE_MASK;
- namerec->data.wins_flags|=WINS_TOMBSTONED;
- namerec->data.death_time = t + EXTINCTION_TIMEOUT;
- DEBUG(3,("initiate_wins_processing: tombstoning %s\n", nmb_namestr(&namerec->name)));
- case WINS_TOMBSTONED:
- DEBUG(3,("initiate_wins_processing: deleting %s\n", nmb_namestr(&namerec->name)));
- remove_name_from_namelist( wins_server_subnet, namerec );
- break;
- case WINS_RELEASED:
- DEBUG(0,("initiate_wins_processing: %s is in released state and\
-we are not the wins owner !\n", nmb_namestr(&namerec->name)));
- break;
- }
- }
-
- }
- }
-
- if(wins_server_subnet->namelist_changed)
- wins_write_database(True);
-
- wins_server_subnet->namelist_changed = False;
-}
-
-/*******************************************************************
- Write out the current WINS database.
-******************************************************************/
-void wins_write_database(BOOL background)
-{
- struct name_record *namerec;
- pstring fname, fnamenew;
- TDB_CONTEXT *tdb;
- TDB_DATA kbuf, dbuf;
- pstring key, buf;
- int len;
- int num_record=0;
- SMB_BIG_UINT id;
-
- if(!lp_we_are_a_wins_server())
- return;
-
- /* we will do the writing in a child process to ensure that the parent
- doesn't block while this is done */
- if (background) {
- CatchChild();
- if (sys_fork()) {
- return;
- }
- }
-
- slprintf(fname,sizeof(fname)-1,"%s/%s", lp_lockdir(), WINS_LIST);
- all_string_sub(fname,"//", "/", 0);
- slprintf(fnamenew,sizeof(fnamenew)-1,"%s.%u", fname, (unsigned int)sys_getpid());
-
- tdb = tdb_open_log(fnamenew, 0, TDB_DEFAULT, O_RDWR|O_CREAT|O_TRUNC, 0644);
- if (!tdb) {
- DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
- if (background)
- _exit(0);
- return;
- }
-
- DEBUG(3,("wins_write_database: Dump of WINS name list.\n"));
-
- tdb_store_int32(tdb, INFO_VERSION, WINS_VERSION);
-
- for (namerec = (struct name_record *)ubi_trFirst( wins_server_subnet->namelist );
- namerec;
- namerec = (struct name_record *)ubi_trNext( namerec ) ) {
-
- int i;
- struct tm *tm;
-
- DEBUGADD(3,("%-19s ", nmb_namestr(&namerec->name) ));
-
- if( namerec->data.death_time != PERMANENT_TTL ) {
- char *ts, *nl;
-
- tm = localtime(&namerec->data.death_time);
- ts = asctime(tm);
- nl = strrchr_m( ts, '\n' );
- if( NULL != nl )
- *nl = '\0';
-
- DEBUGADD(3,("TTL = %s ", ts ));
- } else
- DEBUGADD(3,("TTL = PERMANENT "));
-
- for (i = 0; i < namerec->data.num_ips; i++)
- DEBUGADD(0,("%15s ", inet_ntoa(namerec->data.ip[i]) ));
-
- DEBUGADD(3,("0x%2x 0x%2x %15s\n", namerec->data.nb_flags, namerec->data.wins_flags, inet_ntoa(namerec->data.wins_ip)));
-
- if( namerec->data.source == REGISTER_NAME ) {
-
- /* store the type in the key to make the name unique */
- slprintf(key, sizeof(key), "%s%s#%02x", ENTRY_PREFIX, namerec->name.name, namerec->name.name_type);
-
- len = tdb_pack(buf, sizeof(buf), "dddfddd",
- (int)namerec->data.nb_flags,
- (int)(namerec->data.id>>32),
- (int)(namerec->data.id&0xffffffff),
- inet_ntoa(namerec->data.wins_ip),
- (int)namerec->data.death_time,
- namerec->data.num_ips,
- namerec->data.wins_flags);
-
- for (i = 0; i < namerec->data.num_ips; i++)
- len += tdb_pack(buf+len, sizeof(buf)-len, "f", inet_ntoa(namerec->data.ip[i]));
-
- kbuf.dsize = strlen(key)+1;
- kbuf.dptr = key;
- dbuf.dsize = len;
- dbuf.dptr = buf;
- if (tdb_store(tdb, kbuf, dbuf, TDB_INSERT) != 0) return;
-
- num_record++;
- }
- }
-
- /* store the number of records */
- tdb_store_int32(tdb, INFO_COUNT, num_record);
-
- /* get and store the last used ID */
- get_global_id_and_update(&id, False);
- tdb_store_int32(tdb, INFO_ID_HIGH, id>>32);
- tdb_store_int32(tdb, INFO_ID_LOW, id&0xffffffff);
-
- tdb_close(tdb);
-
- chmod(fnamenew,0644);
- unlink(fname);
- rename(fnamenew,fname);
-
- if (background)
- _exit(0);
-}
-
-/****************************************************************************
-process a internal Samba message receiving a wins record
-***************************************************************************/
-void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len)
-{
- WINS_RECORD *record;
- struct name_record *namerec = NULL;
- struct name_record *new_namerec = NULL;
- struct nmb_name question;
- BOOL overwrite=False;
- struct in_addr our_fake_ip = *interpret_addr2("0.0.0.0");
- int i;
-
- if (buf==NULL)
- return;
-
- record=(WINS_RECORD *)buf;
-
- ZERO_STRUCT(question);
- memcpy(question.name, record->name, 16);
- question.name_type=record->type;
-
- namerec = find_name_on_subnet(wins_server_subnet, &question, FIND_ANY_NAME);
-
- /* record doesn't exist, add it */
- if (namerec == NULL) {
- DEBUG(3,("nmbd_wins_new_entry: adding new replicated record: %s<%02x> for wins server: %s\n",
- record->name, record->type, inet_ntoa(record->wins_ip)));
-
- new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
- EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
- if (new_namerec!=NULL) {
- update_wins_owner(new_namerec, record->wins_ip);
- update_wins_flag(new_namerec, record->wins_flags);
- new_namerec->data.id=record->id;
-
- wins_server_subnet->namelist_changed = True;
- }
- }
-
- /* check if we have a conflict */
- if (namerec != NULL) {
- /* both records are UNIQUE */
- if (namerec->data.wins_flags&WINS_UNIQUE && record->wins_flags&WINS_UNIQUE) {
-
- /* the database record is a replica */
- if (!ip_equal(namerec->data.wins_ip, our_fake_ip)) {
- if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED) {
- if (ip_equal(namerec->data.wins_ip, record->wins_ip))
- overwrite=True;
- } else
- overwrite=True;
- } else {
- /* we are the wins owner of the database record */
- /* the 2 records have the same IP address */
- if (ip_equal(namerec->data.ip[0], record->ip[0])) {
- if (namerec->data.wins_flags&WINS_ACTIVE && record->wins_flags&WINS_TOMBSTONED)
- get_global_id_and_update(&namerec->data.id, True);
- else
- overwrite=True;
-
- } else {
- /* the 2 records have different IP address */
- if (namerec->data.wins_flags&WINS_ACTIVE) {
- if (record->wins_flags&WINS_TOMBSTONED)
- get_global_id_and_update(&namerec->data.id, True);
- if (record->wins_flags&WINS_ACTIVE)
- /* send conflict challenge to the replica node */
- ;
- } else
- overwrite=True;
- }
-
- }
- }
-
- /* the replica is a standard group */
- if (record->wins_flags&WINS_NGROUP || record->wins_flags&WINS_SGROUP) {
- /* if the database record is unique and active force a name release */
- if (namerec->data.wins_flags&WINS_UNIQUE)
- /* send a release name to the unique node */
- ;
- overwrite=True;
-
- }
-
- /* the replica is a special group */
- if (record->wins_flags&WINS_SGROUP && namerec->data.wins_flags&WINS_SGROUP) {
- if (namerec->data.wins_flags&WINS_ACTIVE) {
- for (i=0; i<record->num_ips; i++)
- if(!find_ip_in_name_record(namerec, record->ip[i]))
- add_ip_to_name_record(namerec, record->ip[i]);
- }
- else
- overwrite=True;
- }
-
- /* the replica is a multihomed host */
-
- /* I'm giving up on multi homed. Too much complex to understand */
-
- if (record->wins_flags&WINS_MHOMED) {
- if (! (namerec->data.wins_flags&WINS_ACTIVE)) {
- if ( !(namerec->data.wins_flags&WINS_RELEASED) && !(namerec->data.wins_flags&WINS_NGROUP))
- overwrite=True;
- }
- else {
- if (ip_equal(record->wins_ip, namerec->data.wins_ip))
- overwrite=True;
-
- if (ip_equal(namerec->data.wins_ip, our_fake_ip))
- if (namerec->data.wins_flags&WINS_UNIQUE)
- get_global_id_and_update(&namerec->data.id, True);
-
- }
-
- if (record->wins_flags&WINS_ACTIVE && namerec->data.wins_flags&WINS_ACTIVE)
- if (namerec->data.wins_flags&WINS_UNIQUE ||
- namerec->data.wins_flags&WINS_MHOMED)
- if (ip_equal(record->wins_ip, namerec->data.wins_ip))
- overwrite=True;
-
- }
-
- if (overwrite == False)
- DEBUG(3, ("nmbd_wins_new_entry: conflict in adding record: %s<%02x> from wins server: %s\n",
- record->name, record->type, inet_ntoa(record->wins_ip)));
- else {
- DEBUG(3, ("nmbd_wins_new_entry: replacing record: %s<%02x> from wins server: %s\n",
- record->name, record->type, inet_ntoa(record->wins_ip)));
-
- /* remove the old record and add a new one */
- remove_name_from_namelist( wins_server_subnet, namerec );
- new_namerec=add_name_to_subnet( wins_server_subnet, record->name, record->type, record->nb_flags,
- EXTINCTION_INTERVAL, REGISTER_NAME, record->num_ips, record->ip);
- if (new_namerec!=NULL) {
- update_wins_owner(new_namerec, record->wins_ip);
- update_wins_flag(new_namerec, record->wins_flags);
- new_namerec->data.id=record->id;
-
- wins_server_subnet->namelist_changed = True;
- }
-
- wins_server_subnet->namelist_changed = True;
- }
-
- }
-}
-
-
-
-
-
-
-
-
diff --git a/source4/nmbd/nmbd_workgroupdb.c b/source4/nmbd/nmbd_workgroupdb.c
deleted file mode 100644
index 3e177bceb4..0000000000
--- a/source4/nmbd/nmbd_workgroupdb.c
+++ /dev/null
@@ -1,342 +0,0 @@
-/*
- Unix SMB/CIFS implementation.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1998
- Copyright (C) Luke Kenneth Casson Leighton 1994-1998
- Copyright (C) Jeremy Allison 1994-1998
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "includes.h"
-
-extern int ClientNMB;
-
-extern uint16 samba_nb_type;
-
-int workgroup_count = 0; /* unique index key: one for each workgroup */
-
-/****************************************************************************
- Add a workgroup into the list.
- **************************************************************************/
-
-static void add_workgroup(struct subnet_record *subrec, struct work_record *work)
-{
- work->subnet = subrec;
- DLIST_ADD(subrec->workgrouplist, work);
- subrec->work_changed = True;
-}
-
-/****************************************************************************
- Create an empty workgroup.
- **************************************************************************/
-
-static struct work_record *create_workgroup(const char *name, int ttl)
-{
- struct work_record *work;
- struct subnet_record *subrec;
- int t = -1;
-
- if((work = (struct work_record *)malloc(sizeof(*work))) == NULL)
- {
- DEBUG(0,("create_workgroup: malloc fail !\n"));
- return NULL;
- }
- memset((char *)work, '\0', sizeof(*work));
-
- StrnCpy(work->work_group,name,sizeof(work->work_group)-1);
- work->serverlist = NULL;
-
- work->RunningElection = False;
- work->ElectionCount = 0;
- work->announce_interval = 0;
- work->needelection = False;
- work->needannounce = True;
- work->lastannounce_time = time(NULL);
- work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
- work->dom_state = DOMAIN_NONE;
- work->log_state = LOGON_NONE;
-
- work->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL;
-
- /* Make sure all token representations of workgroups are unique. */
-
- for (subrec = FIRST_SUBNET; subrec && (t == -1);
- subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- struct work_record *w;
- for (w = subrec->workgrouplist; w && t == -1; w = w->next)
- {
- if (strequal(w->work_group, work->work_group))
- t = w->token;
- }
- }
-
- if (t == -1)
- work->token = ++workgroup_count;
- else
- work->token = t;
-
- /* No known local master browser as yet. */
- *work->local_master_browser_name = '\0';
-
- /* No known domain master browser as yet. */
- *work->dmb_name.name = '\0';
- zero_ip(&work->dmb_addr);
-
- /* WfWg uses 01040b01 */
- /* Win95 uses 01041501 */
- /* NTAS uses ???????? */
- work->ElectionCriterion = (MAINTAIN_LIST)|(BROWSER_ELECTION_VERSION<<8);
- work->ElectionCriterion |= (lp_os_level() << 24);
- if (lp_domain_master())
- work->ElectionCriterion |= 0x80;
-
- return work;
-}
-
-/*******************************************************************
- Remove a workgroup.
- ******************************************************************/
-
-static struct work_record *remove_workgroup_from_subnet(struct subnet_record *subrec,
- struct work_record *work)
-{
- struct work_record *ret_work = NULL;
-
- DEBUG(3,("remove_workgroup: Removing workgroup %s\n", work->work_group));
-
- ret_work = work->next;
-
- remove_all_servers(work);
-
- if (!work->serverlist)
- {
- if (work->prev)
- work->prev->next = work->next;
- if (work->next)
- work->next->prev = work->prev;
-
- if (subrec->workgrouplist == work)
- subrec->workgrouplist = work->next;
-
- ZERO_STRUCTP(work);
- SAFE_FREE(work);
- }
-
- subrec->work_changed = True;
-
- return ret_work;
-}
-
-
-/****************************************************************************
- Find a workgroup in the workgroup list of a subnet.
- **************************************************************************/
-
-struct work_record *find_workgroup_on_subnet(struct subnet_record *subrec,
- const char *name)
-{
- struct work_record *ret;
-
- DEBUG(4, ("find_workgroup_on_subnet: workgroup search for %s on subnet %s: ",
- name, subrec->subnet_name));
-
- for (ret = subrec->workgrouplist; ret; ret = ret->next)
- {
- if (!strcmp(ret->work_group,name))
- {
- DEBUGADD(4, ("found.\n"));
- return(ret);
- }
- }
- DEBUGADD(4, ("not found.\n"));
- return NULL;
-}
-
-/****************************************************************************
- Create a workgroup in the workgroup list of the subnet.
- **************************************************************************/
-
-struct work_record *create_workgroup_on_subnet(struct subnet_record *subrec,
- const char *name, int ttl)
-{
- struct work_record *work = NULL;
-
- DEBUG(4,("create_workgroup_on_subnet: creating group %s on subnet %s\n",
- name, subrec->subnet_name));
-
- if ((work = create_workgroup(name, ttl)))
- {
- add_workgroup(subrec, work);
-
- subrec->work_changed = True;
-
- return(work);
- }
-
- return NULL;
-}
-
-/****************************************************************************
- Update a workgroup ttl.
- **************************************************************************/
-
-void update_workgroup_ttl(struct work_record *work, int ttl)
-{
- if(work->death_time != PERMANENT_TTL)
- work->death_time = time(NULL)+(ttl*3);
- work->subnet->work_changed = True;
-}
-
-/****************************************************************************
- Fail function called if we cannot register the WORKGROUP<0> and
- WORKGROUP<1e> names on the net.
-**************************************************************************/
-
-static void fail_register(struct subnet_record *subrec, struct response_record *rrec,
- struct nmb_name *nmbname)
-{
- DEBUG(0,("fail_register: Failed to register name %s on subnet %s.\n",
- nmb_namestr(nmbname), subrec->subnet_name));
-}
-
-/****************************************************************************
- If the workgroup is our primary workgroup, add the required names to it.
-**************************************************************************/
-
-void initiate_myworkgroup_startup(struct subnet_record *subrec, struct work_record *work)
-{
- int i;
-
- if(!strequal(lp_workgroup(), work->work_group))
- return;
-
- /* If this is a broadcast subnet then start elections on it
- if we are so configured. */
-
- if ((subrec != unicast_subnet) && (subrec != remote_broadcast_subnet) &&
- (subrec != wins_server_subnet) && lp_preferred_master() &&
- lp_local_master())
- {
- DEBUG(3, ("initiate_myworkgroup_startup: preferred master startup for \
-workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name));
- work->needelection = True;
- work->ElectionCriterion |= (1<<3);
- }
-
- /* Register the WORKGROUP<0> and WORKGROUP<1e> names on the network. */
-
- register_name(subrec,lp_workgroup(),0x0,samba_nb_type|NB_GROUP,
- NULL,
- fail_register,NULL);
-
- register_name(subrec,lp_workgroup(),0x1e,samba_nb_type|NB_GROUP,
- NULL,
- fail_register,NULL);
-
- for( i = 0; my_netbios_names(i); i++)
- {
- const char *name = my_netbios_names(i);
- int stype = lp_default_server_announce() | (lp_local_master() ?
- SV_TYPE_POTENTIAL_BROWSER : 0 );
-
- if(!strequal(lp_netbios_name(), name))
- stype &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_POTENTIAL_BROWSER|
- SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER);
-
- create_server_on_workgroup(work,name,stype|SV_TYPE_LOCAL_LIST_ONLY,
- PERMANENT_TTL,
- string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
- DEBUG(3,("initiate_myworkgroup_startup: Added server name entry %s \
-on subnet %s\n", name, subrec->subnet_name));
- }
-}
-
-/****************************************************************************
- Dump a copy of the workgroup database into the log file.
- **************************************************************************/
-
-void dump_workgroups(BOOL force_write)
-{
- struct subnet_record *subrec;
- int debuglevel = force_write ? 0 : 4;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- if (subrec->workgrouplist)
- {
- struct work_record *work;
-
- if( DEBUGLVL( debuglevel ) )
- {
- dbgtext( "dump_workgroups()\n " );
- dbgtext( "dump workgroup on subnet %15s: ", subrec->subnet_name );
- dbgtext( "netmask=%15s:\n", inet_ntoa(subrec->mask_ip) );
- }
-
- for (work = subrec->workgrouplist; work; work = work->next)
- {
- DEBUGADD( debuglevel, ( "\t%s(%d) current master browser = %s\n",
- work->work_group,
- work->token,
- *work->local_master_browser_name
- ? work->local_master_browser_name : "UNKNOWN" ) );
- if (work->serverlist)
- {
- struct server_record *servrec;
- for (servrec = work->serverlist; servrec; servrec = servrec->next)
- {
- DEBUGADD( debuglevel, ( "\t\t%s %8x (%s)\n",
- servrec->serv.name,
- servrec->serv.type,
- servrec->serv.comment ) );
- }
- }
- }
- }
- }
-}
-
-/****************************************************************************
- Expire any dead servers on all workgroups. If the workgroup has expired
- remove it.
- **************************************************************************/
-
-void expire_workgroups_and_servers(time_t t)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- struct work_record *work;
- struct work_record *nextwork;
-
- for (work = subrec->workgrouplist; work; work = nextwork)
- {
- nextwork = work->next;
- expire_servers(work, t);
-
- if ((work->serverlist == NULL) && (work->death_time != PERMANENT_TTL) &&
- ((t == -1) || (work->death_time < t)))
- {
- DEBUG(3,("expire_workgroups_and_servers: Removing timed out workgroup %s\n",
- work->work_group));
- remove_workgroup_from_subnet(subrec, work);
- }
- }
- }
-}