diff options
author | Stefan Metzmacher <metze@samba.org> | 2004-05-24 17:41:47 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:56:12 -0500 |
commit | 7fb1be73734915e027f86aca9ba62b86c56ca787 (patch) | |
tree | b66be4fc8eedb1ed5c20bbc29493e3a6353bcfff /source4/nmbd | |
parent | f1a8a690fcd9e8824dade9278e83902a6229b092 (diff) | |
download | samba-7fb1be73734915e027f86aca9ba62b86c56ca787.tar.gz samba-7fb1be73734915e027f86aca9ba62b86c56ca787.tar.bz2 samba-7fb1be73734915e027f86aca9ba62b86c56ca787.zip |
r853: remove a real big bunch of unused code
I really think that this is needed to get a better overview of what is currently used
Also this stuff is really out of date
so if we really ever need some of this stuff back,
a 'svn copy' from the SAMBA_3_0 branch should be no big problem...
metze
(This used to be commit 972598d511c64f29bdc849fe58c9c82fbcf6a4a2)
Diffstat (limited to 'source4/nmbd')
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, ®istered_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(®ister_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(®ister_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(®istered_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, ®ister_ip); - else - ret = initiate_multihomed_name_register_packet(p, nb_flags, ®ister_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 *)©_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); - } - } - } -} |