diff options
Diffstat (limited to 'source/nmbd')
-rw-r--r-- | source/nmbd/asyncdns.c | 4 | ||||
-rw-r--r-- | source/nmbd/nmbd.c | 163 | ||||
-rw-r--r-- | source/nmbd/nmbd_become_dmb.c | 10 | ||||
-rw-r--r-- | source/nmbd/nmbd_browserdb.c | 2 | ||||
-rw-r--r-- | source/nmbd/nmbd_browsesync.c | 8 | ||||
-rw-r--r-- | source/nmbd/nmbd_elections.c | 5 | ||||
-rw-r--r-- | source/nmbd/nmbd_incomingdgrams.c | 34 | ||||
-rw-r--r-- | source/nmbd/nmbd_incomingrequests.c | 7 | ||||
-rw-r--r-- | source/nmbd/nmbd_mynames.c | 78 | ||||
-rw-r--r-- | source/nmbd/nmbd_namelistdb.c | 4 | ||||
-rw-r--r-- | source/nmbd/nmbd_namequery.c | 2 | ||||
-rw-r--r-- | source/nmbd/nmbd_nameregister.c | 7 | ||||
-rw-r--r-- | source/nmbd/nmbd_packets.c | 119 | ||||
-rw-r--r-- | source/nmbd/nmbd_processlogon.c | 91 | ||||
-rw-r--r-- | source/nmbd/nmbd_responserecordsdb.c | 2 | ||||
-rw-r--r-- | source/nmbd/nmbd_sendannounce.c | 12 | ||||
-rw-r--r-- | source/nmbd/nmbd_serverlistdb.c | 5 | ||||
-rw-r--r-- | source/nmbd/nmbd_subnetdb.c | 74 | ||||
-rw-r--r-- | source/nmbd/nmbd_synclists.c | 8 | ||||
-rw-r--r-- | source/nmbd/nmbd_winsproxy.c | 2 | ||||
-rw-r--r-- | source/nmbd/nmbd_winsserver.c | 77 | ||||
-rw-r--r-- | source/nmbd/nmbd_workgroupdb.c | 31 |
22 files changed, 484 insertions, 261 deletions
diff --git a/source/nmbd/asyncdns.c b/source/nmbd/asyncdns.c index 67e55ebd508..99e697b4705 100644 --- a/source/nmbd/asyncdns.c +++ b/source/nmbd/asyncdns.c @@ -52,7 +52,7 @@ static struct name_record *add_dns_result(struct nmb_name *question, struct in_a #ifndef SYNC_DNS static int fd_in = -1, fd_out = -1; -static int child_pid = -1; +static pid_t child_pid = -1; static int in_dns; /* this is the structure that is passed between the parent and child */ @@ -147,7 +147,7 @@ void start_async_dns(void) fd_out = fd2[1]; close(fd1[1]); close(fd2[0]); - DEBUG(0,("started asyncdns process %d\n", child_pid)); + DEBUG(0,("started asyncdns process %d\n", (int)child_pid)); return; } diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c index 1471254b4ea..533c06351f1 100644 --- a/source/nmbd/nmbd.c +++ b/source/nmbd/nmbd.c @@ -1,7 +1,7 @@ /* - Unix SMB/NetBIOS implementation. + Unix SMB/Netbios implementation. Version 1.9. - NBT NetBIOS routines and daemon - version 2 + NBT netbios routines and daemon - version 2 Copyright (C) Andrew Tridgell 1994-1998 This program is free software; you can redistribute it and/or modify @@ -38,7 +38,6 @@ int ClientNMB = -1; int ClientDGRAM = -1; int global_nmb_port = -1; -extern pstring myhostname; static pstring host_file; extern pstring global_myname; extern fstring global_myworkgroup; @@ -86,6 +85,8 @@ static void sig_term(int sig) /**************************************************************************** ** catch a sighup **************************************************************************** */ +static VOLATILE SIG_ATOMIC_T reload_after_sighup = False; + static void sig_hup(int sig) { BlockSignals( True, SIGHUP ); @@ -95,9 +96,8 @@ static void sig_hup(int sig) write_browse_list( 0, True ); dump_all_namelists(); - reload_services( True ); - set_samba_nb_type(); + reload_after_sighup = True; BlockSignals(False,SIGHUP); @@ -184,6 +184,67 @@ static void expire_names_and_servers(time_t t) expire_workgroups_and_servers(t); } /* expire_names_and_servers */ + +/************************************************************************** ** +reload the list of network interfaces + ************************************************************************** */ +static void reload_interfaces(time_t t) +{ + static time_t lastt; + int n; + struct subnet_record *subrec; + extern BOOL rescan_listen_set; + + if (t && ((t - lastt) < NMBD_INTERFACES_RELOAD)) return; + lastt = t; + + if (!interfaces_changed()) return; + + /* 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); + 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; +} + + + /**************************************************************************** ** reload the services file **************************************************************************** */ @@ -395,6 +456,20 @@ static void process(void) * regularly sync with any other DMBs we know about */ sync_all_dmbs(t); + + /* + * Reload the services file if we got a sighup. + */ + + if(reload_after_sighup) { + reload_services( True ); + reopen_logs(); + reload_interfaces(0); + reload_after_sighup = False; + } + + /* check for new network interfaces */ + reload_interfaces(t); } } /* process */ @@ -412,11 +487,11 @@ static BOOL open_sockets(BOOL isdaemon, int port) */ if ( isdaemon ) - ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0); + ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0,True); else ClientNMB = 0; - ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0); + ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0,True); if ( ClientNMB == -1 ) return( False ); @@ -446,7 +521,7 @@ static BOOL init_structs(void) if (! *global_myname) { - fstrcpy( global_myname, myhostname ); + fstrcpy( global_myname, myhostname() ); p = strchr( global_myname, '.' ); if (p) *p = 0; @@ -509,7 +584,7 @@ static BOOL init_structs(void) *p = 0; strlower( local_machine ); - DEBUG( 5, ("NetBIOS name list:-\n") ); + DEBUG( 5, ("Netbios name list:-\n") ); for( n=0; my_netbios_names[n]; n++ ) DEBUGADD( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n] ) ); @@ -521,20 +596,21 @@ static BOOL init_structs(void) **************************************************************************** */ static void usage(char *pname) { - DEBUG(0,("Incorrect program usage - is the command line correct?\n")); - - printf( "Usage: %s [-n name] [-D] [-p port] [-d debuglevel] ", pname ); - printf( "[-l log basename]\n" ); - printf( "Version %s\n", VERSION ); - printf( "\t-D become a daemon\n" ); - printf( "\t-p port listen on the specified port\n" ); - printf( "\t-d debuglevel set the debuglevel\n" ); + + printf( "Usage: %s [-DaohV] [-H lmhosts file] [-d debuglevel] [-l log basename]\n", pname ); + printf( " [-n name] [-p port] [-s configuration file] [-i scope]\n" ); + printf( "\t-D Become a daemon\n" ); + printf( "\t-a Append to log file (default)\n" ); + printf( "\t-o Overwrite log file, don't append\n" ); + printf( "\t-h Print usage\n" ); + printf( "\t-V Print version\n" ); + printf( "\t-H hosts file Load a netbios hosts file\n" ); + printf( "\t-d debuglevel Set the debuglevel\n" ); printf( "\t-l log basename. Basename for log/debug files\n" ); - printf( "\t-n netbiosname. " ); - printf( "the netbios name to advertise for this host\n"); - printf( "\t-H hosts file load a netbios hosts file\n" ); - printf( "\t-a append to log file (default)\n" ); - printf( "\t-o overwrite log file, don't append\n" ); + printf( "\t-n netbiosname. Primary netbios name\n" ); + printf( "\t-p port Listen on the specified port\n" ); + printf( "\t-s configuration file Configuration file name\n" ); + printf( "\t-i scope NetBIOS scope\n" ); printf( "\n"); } /* usage */ @@ -583,6 +659,11 @@ static void usage(char *pname) 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 + /* Setup the signals that allow the debug log level to by dynamically changed. */ @@ -590,16 +671,16 @@ static void usage(char *pname) SIGUSR1 and SIGUSR2 to do debug level changes. */ #ifndef MEM_MAN #if defined(SIGUSR1) - CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 ); + CatchSignal( SIGUSR1, SIGNAL_CAST sig_usr1 ); #endif /* SIGUSR1 */ #if defined(SIGUSR2) - CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 ); + CatchSignal( SIGUSR2, SIGNAL_CAST sig_usr2 ); #endif /* SIGUSR2 */ #endif /* MEM_MAN */ while( EOF != - (opt = getopt( argc, argv, "aos:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:" )) ) + (opt = getopt( argc, argv, "Vaos:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:" )) ) { switch (opt) { @@ -646,9 +727,14 @@ static void usage(char *pname) usage(argv[0]); exit(0); break; + case 'V': + printf( "Version %s\n", VERSION ); + exit(0); + break; default: if( !is_a_socket(0) ) { + DEBUG(0,("Incorrect program usage - is the command line correct?\n")); usage(argv[0]); exit(0); } @@ -658,15 +744,9 @@ static void usage(char *pname) reopen_logs(); - DEBUG( 1, ( "NetBIOS nameserver version %s started.\n", VERSION ) ); + DEBUG( 1, ( "Netbios nameserver version %s started.\n", VERSION ) ); DEBUGADD( 1, ( "Copyright Andrew Tridgell 1994-1998\n" ) ); - if( !get_myname( myhostname, NULL) ) - { - DEBUG( 0, ( "Unable to get my hostname - exiting.\n" ) ); - return -1; - } - if ( !reload_services(False) ) return(-1); @@ -677,10 +757,13 @@ static void usage(char *pname) reload_services( True ); - if (!init_myworkgroup()) - { - exit(1); - } + fstrcpy( global_myworkgroup, lp_workgroup() ); + + if (strequal(global_myworkgroup,"*")) + { + DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n")); + exit(1); + } set_samba_nb_type(); @@ -696,6 +779,14 @@ static void usage(char *pname) become_daemon(); } +#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()) { + start_async_dns(); + } +#endif + if (!directory_exist(lp_lockdir(), NULL)) { mkdir(lp_lockdir(), 0755); } diff --git a/source/nmbd/nmbd_become_dmb.c b/source/nmbd/nmbd_become_dmb.c index cbef1db4b7e..ae809607dc6 100644 --- a/source/nmbd/nmbd_become_dmb.c +++ b/source/nmbd/nmbd_become_dmb.c @@ -157,6 +157,16 @@ in workgroup %s on subnet %s\n", */ 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); + } } /**************************************************************************** diff --git a/source/nmbd/nmbd_browserdb.c b/source/nmbd/nmbd_browserdb.c index 12ce00df4f2..10d22431e91 100644 --- a/source/nmbd/nmbd_browserdb.c +++ b/source/nmbd/nmbd_browserdb.c @@ -99,7 +99,7 @@ struct browse_cache_record *create_browser_in_lmb_cache( char *work_name, return( NULL ); } - bzero( (char *)browc, sizeof( *browc ) ); + 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 diff --git a/source/nmbd/nmbd_browsesync.c b/source/nmbd/nmbd_browsesync.c index eafcc79c0aa..b177fb524e9 100644 --- a/source/nmbd/nmbd_browsesync.c +++ b/source/nmbd/nmbd_browsesync.c @@ -32,7 +32,7 @@ extern pstring global_myname; extern fstring global_myworkgroup; /* This is our local master browser list database. */ -extern struct ubi_dlList lmb_browserlist[]; +extern ubi_dlList lmb_browserlist[]; /**************************************************************************** As a domain master browser, do a sync with a local master browser. @@ -128,7 +128,7 @@ static void announce_local_master_browser_to_domain_master_browser( struct work_ return; } - bzero(outbuf,sizeof(outbuf)); + memset(outbuf,'\0',sizeof(outbuf)); p = outbuf; CVAL(p,0) = ANN_MasterAnnouncement; p++; @@ -324,7 +324,7 @@ static void find_domain_master_name_query_success(struct subnet_record *subrec, putip((char *)&work->dmb_addr, &ipzero); /* Now initiate the node status request. */ - bzero((char *)&nmbname, sizeof(nmbname)); + memset((char *)&nmbname, '\0',sizeof(nmbname)); nmbname.name[0] = '*'; /* Put the workgroup name into the userdata so we know @@ -549,7 +549,7 @@ static void find_all_domain_master_names_query_success(struct subnet_record *sub for(i = 0; i < rrec->rdlength / 6; i++) { /* Initiate the node status requests. */ - bzero((char *)&nmbname, sizeof(nmbname)); + memset((char *)&nmbname, '\0', sizeof(nmbname)); nmbname.name[0] = '*'; putip((char *)&send_ip, (char *)&rrec->rdata[(i*6) + 2]); diff --git a/source/nmbd/nmbd_elections.c b/source/nmbd/nmbd_elections.c index 8f876eab0c5..8e1605dbba9 100644 --- a/source/nmbd/nmbd_elections.c +++ b/source/nmbd/nmbd_elections.c @@ -46,7 +46,7 @@ static void send_election_dgram(struct subnet_record *subrec, char *workgroup_na DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n", workgroup_name, subrec->subnet_name )); - bzero(outbuf,sizeof(outbuf)); + memset(outbuf,'\0',sizeof(outbuf)); p = outbuf; CVAL(p,0) = ANN_Election; /* Election opcode. */ p++; @@ -135,6 +135,9 @@ void check_master_browser_exists(time_t t) struct subnet_record *subrec; char *workgroup_name = global_myworkgroup; + if (!lastrun) + lastrun = t; + if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60))) return; diff --git a/source/nmbd/nmbd_incomingdgrams.c b/source/nmbd/nmbd_incomingdgrams.c index 41aaebd9b1b..b8be579779f 100644 --- a/source/nmbd/nmbd_incomingdgrams.c +++ b/source/nmbd/nmbd_incomingdgrams.c @@ -546,10 +546,11 @@ static void send_backup_list_response(struct subnet_record *subrec, char outbuf[1024]; char *p, *countptr; unsigned int count = 0; - int len; +#if 0 struct server_record *servrec; +#endif - bzero(outbuf,sizeof(outbuf)); + 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))); @@ -572,9 +573,20 @@ static void send_backup_list_response(struct subnet_record *subrec, 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) { - len = PTR_DIFF(p, outbuf); + int len = PTR_DIFF(p, outbuf); if((sizeof(outbuf) - len) < 16) break; @@ -596,11 +608,10 @@ static void send_backup_list_response(struct subnet_record *subrec, p = skip_string(p,1); } +#endif SCVAL(countptr, 0, count); - len = PTR_DIFF(p, outbuf); - 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)); @@ -630,6 +641,7 @@ void process_get_backup_list_request(struct subnet_record *subrec, 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; DEBUG(3,("process_get_backup_list_request: request from %s IP %s to %s.\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip), @@ -646,13 +658,19 @@ void process_get_backup_list_request(struct subnet_record *subrec, return; } - if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL) + 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, subrec->subnet_name)); +subnet %s.\n", workgroup_name, search_subrec->subnet_name)); return; } + /* + * 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 @@ -664,6 +682,8 @@ subnet %s.\n", workgroup_name, subrec->subnet_name)); and I am not a domain master browser.\n", workgroup_name)); return; } + + search_subrec = unicast_subnet; } else if (name_type == 0x1d) { diff --git a/source/nmbd/nmbd_incomingrequests.c b/source/nmbd/nmbd_incomingrequests.c index dd5a23e0b0d..7c46204445c 100644 --- a/source/nmbd/nmbd_incomingrequests.c +++ b/source/nmbd/nmbd_incomingrequests.c @@ -176,8 +176,9 @@ void process_name_refresh_request(struct subnet_record *subrec, 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. Error - should be sent to WINS server\n", +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; @@ -366,7 +367,7 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name), strequal(qname, namerec->name.name))) { /* Start with the name. */ - bzero(buf,18); + memset(buf,'\0',18); slprintf(buf, 17, "%-15.15s",namerec->name.name); strupper(buf); @@ -421,7 +422,7 @@ subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name), /* We don't send any stats as they could be used to attack the protocol. */ - bzero(buf,46); + memset(buf,'\0',46); buf += 46; diff --git a/source/nmbd/nmbd_mynames.c b/source/nmbd/nmbd_mynames.c index 64cb8ea9e93..c36df21e7b0 100644 --- a/source/nmbd/nmbd_mynames.c +++ b/source/nmbd/nmbd_mynames.c @@ -43,6 +43,47 @@ static void my_name_register_failed(struct subnet_record *subrec, 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, global_myworkgroup, + PERMANENT_TTL)) == NULL) { + DEBUG(0,("register_my_workgroup_and_names: Failed to create my workgroup %s on subnet %s. \ +Exiting.\n", global_myworkgroup, 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); +} + + /**************************************************************************** Add my workgroup and my given names to the subnet lists. Also add the magic Samba names. @@ -51,38 +92,13 @@ static void my_name_register_failed(struct subnet_record *subrec, BOOL register_my_workgroup_and_names(void) { struct subnet_record *subrec; - struct work_record *work; int i; - for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) + for(subrec = FIRST_SUBNET; + subrec; + subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec)) { - /* Create the workgroup on the subnet. */ - if((work = create_workgroup_on_subnet(subrec, global_myworkgroup, PERMANENT_TTL)) == NULL) - { - DEBUG(0,("register_my_workgroup_and_names: Failed to create my workgroup %s on subnet %s. \ -Exiting.\n", global_myworkgroup, subrec->subnet_name)); - return False; - } - - /* 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); + register_my_workgroup_one_subnet(subrec); } /* If we are not a WINS client, we still need to add the magic Samba @@ -180,6 +196,10 @@ void refresh_my_names(time_t t) { struct name_record *namerec; + /* B nodes don't send out name refresh requests, see RFC 1001, 15.5.1 */ + if (subrec != unicast_subnet) + continue; + for( namerec = (struct name_record *)ubi_trFirst( subrec->namelist ); namerec; namerec = (struct name_record *)ubi_trNext( namerec ) ) diff --git a/source/nmbd/nmbd_namelistdb.c b/source/nmbd/nmbd_namelistdb.c index 0bc5fd875a7..dbb8be1f2d5 100644 --- a/source/nmbd/nmbd_namelistdb.c +++ b/source/nmbd/nmbd_namelistdb.c @@ -42,8 +42,6 @@ void set_samba_nb_type(void) samba_nb_type = NB_MFLAG; /* samba is a 'hybrid' node type. */ else samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type. */ - - DEBUG(10,("set_samba_nb_type: %x\n", samba_nb_type)); } /* set_samba_nb_type */ /* ************************************************************************** ** @@ -201,7 +199,7 @@ struct name_record *add_name_to_subnet( struct subnet_record *subrec, return( NULL ); } - bzero( (char *)namerec, sizeof(*namerec) ); + memset( (char *)namerec, '\0', sizeof(*namerec) ); namerec->data.ip = (struct in_addr *)malloc( sizeof(struct in_addr) * num_ips ); if( NULL == namerec->data.ip ) diff --git a/source/nmbd/nmbd_namequery.c b/source/nmbd/nmbd_namequery.c index fae045882f2..8c415548421 100644 --- a/source/nmbd/nmbd_namequery.c +++ b/source/nmbd/nmbd_namequery.c @@ -193,7 +193,7 @@ BOOL query_name(struct subnet_record *subrec, char *name, int type, struct res_rec rrec; int i; - bzero((char *)&rrec, sizeof(struct res_rec)); + memset((char *)&rrec, '\0', sizeof(struct res_rec)); /* Fake up the needed res_rec just in case it's used. */ rrec.rr_name = nmbname; diff --git a/source/nmbd/nmbd_nameregister.c b/source/nmbd/nmbd_nameregister.c index 069e262987e..1e819cc88f6 100644 --- a/source/nmbd/nmbd_nameregister.c +++ b/source/nmbd/nmbd_nameregister.c @@ -54,6 +54,13 @@ static void register_name_response(struct subnet_record *subrec, /* 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 \ diff --git a/source/nmbd/nmbd_packets.c b/source/nmbd/nmbd_packets.c index 66c774a6e98..0a7696a4663 100644 --- a/source/nmbd/nmbd_packets.c +++ b/source/nmbd/nmbd_packets.c @@ -37,6 +37,9 @@ 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 @@ -91,6 +94,43 @@ void set_nb_flags(char *buf, uint16 nb_flags) } /*************************************************************************** +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 = outbuf[i+j]; + if (x < 32 || x > 127) + x = '.'; + + if (i+j >= len) + break; + 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 **************************************************************************/ @@ -143,7 +183,6 @@ static BOOL send_netbios_packet(struct packet_struct *p) 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; @@ -156,13 +195,13 @@ static struct packet_struct *create_and_init_netbios_packet(struct nmb_name *nmb return NULL; } - bzero((char *)packet,sizeof(*packet)); + 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_desired = False; nmb->header.nm_flags.recursion_available = False; nmb->header.nm_flags.trunc = False; nmb->header.nm_flags.authoritative = False; @@ -203,13 +242,17 @@ static BOOL create_and_init_additional_record(struct packet_struct *packet, return False; } - bzero((char *)nmb->additional,sizeof(struct res_rec)); + 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; - nmb->additional->ttl = lp_max_ttl(); + /* 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; @@ -431,12 +474,11 @@ struct response_record *queue_register_name( struct subnet_record *subrec, struct packet_struct *p; struct response_record *rrec; BOOL bcast = (subrec == unicast_subnet) ? False : True; - BOOL rec_des = (subrec == wins_server_subnet) ? True : False; if(assert_check_subnet(subrec)) return NULL; - if(( p = create_and_init_netbios_packet(nmbname, bcast, rec_des, + if(( p = create_and_init_netbios_packet(nmbname, bcast, subrec->bcast_ip)) == NULL) return NULL; @@ -481,7 +523,6 @@ struct response_record *queue_register_multihomed_name( struct subnet_record *su struct packet_struct *p; struct response_record *rrec; BOOL bcast = False; - BOOL rec_des = (subrec == wins_server_subnet) ? True : False; BOOL ret; /* Sanity check. */ @@ -495,7 +536,7 @@ unicast subnet. subnet is %s\n.", subrec->subnet_name )); if(assert_check_subnet(subrec)) return NULL; - if(( p = create_and_init_netbios_packet(nmbname, bcast, rec_des, + if(( p = create_and_init_netbios_packet(nmbname, bcast, subrec->bcast_ip)) == NULL) return NULL; @@ -542,14 +583,13 @@ struct response_record *queue_release_name( struct subnet_record *subrec, struct in_addr release_ip) { BOOL bcast = (subrec == unicast_subnet) ? False : True; - BOOL rec_des = (subrec == wins_server_subnet) ? True : False; struct packet_struct *p; struct response_record *rrec; if(assert_check_subnet(subrec)) return NULL; - if(( p = create_and_init_netbios_packet(nmbname, bcast, rec_des, + if(( p = create_and_init_netbios_packet(nmbname, bcast, subrec->bcast_ip)) == NULL) return NULL; @@ -601,14 +641,13 @@ struct response_record *queue_refresh_name( struct subnet_record *subrec, struct in_addr refresh_ip) { BOOL bcast = (subrec == unicast_subnet) ? False : True; - BOOL rec_des = (subrec == wins_server_subnet) ? True : False; struct packet_struct *p; struct response_record *rrec; if(assert_check_subnet(subrec)) return NULL; - if(( p = create_and_init_netbios_packet(&namerec->name, bcast,rec_des, + if(( p = create_and_init_netbios_packet(&namerec->name, bcast, subrec->bcast_ip)) == NULL) return NULL; @@ -650,7 +689,6 @@ struct response_record *queue_query_name( struct subnet_record *subrec, struct packet_struct *p; struct response_record *rrec; BOOL bcast = True; - BOOL rec_des = (subrec == wins_server_subnet) ? True : False; if ((subrec == unicast_subnet) || (subrec == wins_server_subnet)) bcast = False; @@ -658,7 +696,7 @@ struct response_record *queue_query_name( struct subnet_record *subrec, if(assert_check_subnet(subrec)) return NULL; - if(( p = create_and_init_netbios_packet(nmbname, bcast,rec_des, + if(( p = create_and_init_netbios_packet(nmbname, bcast, subrec->bcast_ip)) == NULL) return NULL; @@ -700,10 +738,8 @@ struct response_record *queue_query_name_from_wins_server( struct in_addr to_ip, struct packet_struct *p; struct response_record *rrec; BOOL bcast = False; - BOOL rec_des = True; - if(( p = create_and_init_netbios_packet(nmbname, bcast, rec_des, - to_ip)) == NULL) + if(( p = create_and_init_netbios_packet(nmbname, bcast, to_ip)) == NULL) return NULL; if(initiate_name_query_packet_from_wins_server( p ) == False) @@ -745,7 +781,6 @@ struct response_record *queue_node_status( struct subnet_record *subrec, struct packet_struct *p; struct response_record *rrec; BOOL bcast = False; - BOOL rec_des = (subrec == wins_server_subnet) ? True : False; /* Sanity check. */ if(subrec != unicast_subnet) @@ -758,7 +793,7 @@ unicast subnet. subnet is %s\n.", subrec->subnet_name )); if(assert_check_subnet(subrec)) return NULL; - if(( p = create_and_init_netbios_packet(nmbname, bcast,rec_des, + if(( p = create_and_init_netbios_packet(nmbname, bcast, send_ip)) == NULL) return NULL; @@ -895,10 +930,10 @@ for id %hu\n", nmb->header.nscount = 0; nmb->header.arcount = 0; - bzero((char*)&nmb->question,sizeof(nmb->question)); + memset((char*)&nmb->question,'\0',sizeof(nmb->question)); nmb->answers = &answers; - bzero((char*)nmb->answers,sizeof(*nmb->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; @@ -1013,45 +1048,43 @@ mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, scop { 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: { - - /* This is one occasion where we change a subnet that is - given to us. If the packet was sent to WORKGROUP<1b> instead - of WORKGROUP<1d> then it was unicast to us a domain master - browser. Change subrec to unicast. - */ - if(dgram->dest_name.name_type == 0x1b) - subrec = unicast_subnet; - + 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 \ @@ -1060,6 +1093,7 @@ packet from %s IP %s\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip))); } case ANN_ResetBrowserState: { + debug_browse_data(buf, len); process_reset_browser(subrec, p, buf+1); break; } @@ -1069,6 +1103,7 @@ packet from %s IP %s\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip))); on the unicast subnet. */ subrec = unicast_subnet; + debug_browse_data(buf, len); process_master_browser_announce(subrec, p, buf+1); break; } @@ -1077,6 +1112,7 @@ packet from %s IP %s\n", nmb_namestr(&dgram->source_name), inet_ntoa(p->ip))); /* * 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), @@ -1085,6 +1121,7 @@ command ANN_BecomeBackup from %s IP %s to %s\n", } 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), @@ -1123,7 +1160,7 @@ mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, scop { case ANN_HostAnnouncement: { - dump_data(4, buf, len); + debug_browse_data(buf, len); process_lm_host_announce(subrec, p, buf+1); break; } @@ -1208,11 +1245,10 @@ static void process_dgram(struct packet_struct *p) nmb_namestr(&dgram->source_name),nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip), smb_buf(buf),CVAL(buf2,0),len)); + if (len <= 0) return; - dump_data(100, buf2, len); - /* Datagram packet received for the browser mailslot */ if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) { @@ -1687,6 +1723,10 @@ only use %d.\n", (count*2) + 2, FD_SETSIZE)); } *listen_number = (count*2) + 2; + + if (*ppset) free(*ppset); + if (*psock_array) free(*psock_array); + *ppset = pset; *psock_array = sock_array; @@ -1710,13 +1750,14 @@ BOOL listen_for_packets(BOOL run_election) int dns_fd; #endif - if(listen_set == NULL) + 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)); @@ -1749,7 +1790,7 @@ BOOL listen_for_packets(BOOL run_election) BlockSignals(False, SIGUSR2); #endif /* SIGUSR2 */ - selrtn = sys_select(256,&fds,NULL, &timeout); + selrtn = sys_select(FD_SETSIZE,&fds,&timeout); /* We can only take signals when we are in the select - block them again here. */ @@ -1864,7 +1905,7 @@ BOOL send_mailslot(BOOL unique, char *mailslot,char *buf,int len, char *ptr,*p2; char tmp[4]; - bzero((char *)&p,sizeof(p)); + memset((char *)&p,'\0',sizeof(p)); if(ismyip(dest_ip)) loopback_this_packet = True; @@ -1873,7 +1914,7 @@ BOOL send_mailslot(BOOL unique, char *mailslot,char *buf,int len, /* DIRECT GROUP or UNIQUE datagram. */ dgram->header.msg_type = unique ? 0x10 : 0x11; - dgram->header.flags.node_type = M_NODE | 0x40; + dgram->header.flags.node_type = M_NODE; dgram->header.flags.first = True; dgram->header.flags.more = False; dgram->header.dgm_id = name_trn_id; @@ -1920,7 +1961,7 @@ BOOL send_mailslot(BOOL unique, char *mailslot,char *buf,int len, 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))); - dump_data(4, buf, len); + debug_browse_data(buf, len); if(loopback_this_packet) { diff --git a/source/nmbd/nmbd_processlogon.c b/source/nmbd/nmbd_processlogon.c index a515c2706d4..279ab1c764f 100644 --- a/source/nmbd/nmbd_processlogon.c +++ b/source/nmbd/nmbd_processlogon.c @@ -50,6 +50,7 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len, uint32 domainsidsize; char *getdc; char *uniuser; /* Unicode user name. */ + pstring ascuser; char *unicomp; /* Unicode computer name. */ memset(outbuf, 0, sizeof(outbuf)); @@ -117,7 +118,7 @@ logons are not enabled.\n", inet_ntoa(p->ip) )); q = align2(unicomp, buf); - q = skip_unibuf(q, buf+len-q); + q = skip_unicode_string(q, 1); ntversion = IVAL(q, 0); q += 4; @@ -134,19 +135,17 @@ logons are not enabled.\n", inet_ntoa(p->ip) )); fstrcpy(reply_name,my_name); fstrcpy(q, reply_name); + q = skip_string(q, 1); /* PDC name */ - /* PDC and domain name */ -#if 0 - if (strcmp(mailslot, NT_LOGON_MAILSLOT)==0) -#endif - { + if (strcmp(mailslot, NT_LOGON_MAILSLOT)==0) { q = align2(q, buf); - q = ascii_to_unibuf(q, my_name, outbuf+sizeof(outbuf)-q-2); - q = ascii_to_unibuf(q, global_myworkgroup, outbuf+sizeof(outbuf)-q-2); + dos_PutUniCode(q, my_name, sizeof(pstring)); /* PDC name */ + q = skip_unicode_string(q, 1); - ntversion = 0x01; + dos_PutUniCode(q, global_myworkgroup,sizeof(pstring)); /* Domain name*/ + q = skip_unicode_string(q, 1); SIVAL(q, 0, ntversion); q += 4; @@ -166,10 +165,10 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", send_mailslot(True, getdc, outbuf,PTR_DIFF(q,outbuf), - my_name, - 0x0, - dgram->source_name.name, - dgram->source_name.name_type, + dgram->dest_name.name, + dgram->dest_name.name_type, + dgram->source_name.name, + dgram->source_name.name_type, p->ip, *iface_ip(p->ip), p->port); return; } @@ -180,20 +179,13 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", q += 2; unicomp = q; - uniuser = skip_unibuf(unicomp, buf+len-q); - getdc = skip_unibuf(uniuser, buf+len-q); + uniuser = skip_unicode_string(unicomp,1); + getdc = skip_unicode_string(uniuser,1); q = skip_string(getdc,1); - q += 4; /* skip Account Control Bits */ + q += 4; domainsidsize = IVAL(q, 0); q += 4; - - if (domainsidsize != 0) - { - q += domainsidsize; - q += 2; - q = align4(q, buf); - } - + q += domainsidsize + 3; ntversion = IVAL(q, 0); q += 4; lmnttoken = SVAL(q, 0); @@ -201,7 +193,7 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", lm20token = SVAL(q, 0); q += 2; - DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d ntv %x\n", domainsidsize, ntversion)); + DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d ntv %d\n", domainsidsize, ntversion)); /* * we respond regadless of whether the machine is in our password @@ -209,43 +201,28 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", * Let's ignore the SID. */ + pstrcpy(ascuser, dos_unistr(uniuser)); + DEBUG(3,("process_logon_packet: SAMLOGON user %s\n", ascuser)); + fstrcpy(reply_name,"\\\\"); /* Here it wants \\LOGONSERVER. */ fstrcpy(reply_name+2,my_name); - ntversion = 0x01; - lmnttoken = 0xffff; - lm20token = 0xffff; - - if (DEBUGLVL(3)) - { - fstring ascuser; - fstring asccomp; - - unibuf_to_ascii(ascuser, uniuser, sizeof(ascuser)-1); - unibuf_to_ascii(asccomp, unicomp, sizeof(asccomp)-1); - - DEBUGADD(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, - global_myworkgroup, SAMLOGON_R, lmnttoken)); - } + DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n", + dos_unistr(unicomp),inet_ntoa(p->ip), ascuser, reply_name, global_myworkgroup, + SAMLOGON_R ,lmnttoken)); /* Construct reply. */ q = outbuf; - if (uniuser[0] == 0) - { - SSVAL(q, 0, SAMLOGON_UNK_R); /* user unknown */ - } - else - { - SSVAL(q, 0, SAMLOGON_R); - } + SSVAL(q, 0, SAMLOGON_R); q += 2; - /* Logon server, trust account, domain */ - q = ascii_to_unibuf(q, reply_name, outbuf+sizeof(outbuf)-q-2); - q = uni_strncpy(q, uniuser, outbuf+sizeof(outbuf)-q-2); - q = ascii_to_unibuf(q, lp_workgroup(), outbuf+sizeof(outbuf)-q-2); + dos_PutUniCode(q, reply_name,sizeof(pstring)); + q = skip_unicode_string(q, 1); + unistrcpy(q, uniuser); + q = skip_unicode_string(q, 1); /* User name (workstation trust account) */ + dos_PutUniCode(q, lp_workgroup(),sizeof(pstring)); + q = skip_unicode_string(q, 1); /* Domain name. */ SIVAL(q, 0, ntversion); q += 4; @@ -258,10 +235,10 @@ reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n", send_mailslot(True, getdc, outbuf,PTR_DIFF(q,outbuf), - my_name, - 0x0, - dgram->source_name.name, - dgram->source_name.name_type, + dgram->dest_name.name, + dgram->dest_name.name_type, + dgram->source_name.name, + dgram->source_name.name_type, p->ip, *iface_ip(p->ip), p->port); break; } diff --git a/source/nmbd/nmbd_responserecordsdb.c b/source/nmbd/nmbd_responserecordsdb.c index 0c698760bb6..fe294647732 100644 --- a/source/nmbd/nmbd_responserecordsdb.c +++ b/source/nmbd/nmbd_responserecordsdb.c @@ -119,7 +119,7 @@ struct response_record *make_response_record( struct subnet_record *subrec, return NULL; } - bzero((char *)rrec, sizeof(*rrec)); + memset((char *)rrec, '\0', sizeof(*rrec)); rrec->response_id = nmb->header.name_trn_id; diff --git a/source/nmbd/nmbd_sendannounce.c b/source/nmbd/nmbd_sendannounce.c index 38c8deafe72..87115a1eb0d 100644 --- a/source/nmbd/nmbd_sendannounce.c +++ b/source/nmbd/nmbd_sendannounce.c @@ -46,7 +46,7 @@ void send_browser_reset(int reset_type, char *to_name, int to_type, struct in_ad 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) )); - bzero(outbuf,sizeof(outbuf)); + memset(outbuf,'\0',sizeof(outbuf)); p = outbuf; CVAL(p,0) = ANN_ResetBrowserState; p++; @@ -73,7 +73,7 @@ void broadcast_announce_request(struct subnet_record *subrec, struct work_record DEBUG(3,("broadcast_announce_request: sending announce request for workgroup %s \ to subnet %s\n", work->work_group, subrec->subnet_name)); - bzero(outbuf,sizeof(outbuf)); + memset(outbuf,'\0',sizeof(outbuf)); p = outbuf; CVAL(p,0) = ANN_AnnouncementRequest; p++; @@ -101,7 +101,7 @@ static void send_announcement(struct subnet_record *subrec, int announce_type, pstring outbuf; char *p; - bzero(outbuf,sizeof(outbuf)); + memset(outbuf,'\0',sizeof(outbuf)); p = outbuf+1; CVAL(outbuf,0) = announce_type; @@ -142,7 +142,7 @@ static void send_lm_announcement(struct subnet_record *subrec, int announce_type pstring outbuf; char *p=outbuf; - bzero(outbuf,sizeof(outbuf)); + memset(outbuf,'\0',sizeof(outbuf)); SSVAL(p,0,announce_type); SIVAL(p,2,server_type & ~SV_TYPE_LOCAL_LIST_ONLY); @@ -504,7 +504,7 @@ void announce_remote(time_t t) if (!*s) return; - comment = lp_serverstring(); + comment = string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH); for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) { @@ -587,7 +587,7 @@ for workgroup %s on subnet %s.\n", global_myworkgroup, FIRST_SUBNET->subnet_name return; } - bzero(outbuf,sizeof(outbuf)); + memset(outbuf,'\0',sizeof(outbuf)); p = outbuf; CVAL(p,0) = ANN_MasterAnnouncement; p++; diff --git a/source/nmbd/nmbd_serverlistdb.c b/source/nmbd/nmbd_serverlistdb.c index d30e8da64ce..41009bc68f0 100644 --- a/source/nmbd/nmbd_serverlistdb.c +++ b/source/nmbd/nmbd_serverlistdb.c @@ -156,7 +156,7 @@ workgroup %s. This is a bug.\n", name, work->work_group)); return NULL; } - bzero((char *)servrec,sizeof(*servrec)); + memset((char *)servrec,'\0',sizeof(*servrec)); servrec->subnet = work->subnet; @@ -399,7 +399,8 @@ void write_browse_list(time_t t, BOOL force_write) slprintf(tmp, sizeof(tmp)-1, "\"%s\"", my_netbios_names[i]); fprintf(fp, "%-25s ", tmp); fprintf(fp, "%08x ", stype); - slprintf(tmp, sizeof(tmp)-1, "\"%s\" ", lp_serverstring()); + slprintf(tmp, sizeof(tmp)-1, "\"%s\" ", + string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH)); fprintf(fp, "%-30s", tmp); fprintf(fp, "\"%s\"\n", global_myworkgroup); } diff --git a/source/nmbd/nmbd_subnetdb.c b/source/nmbd/nmbd_subnetdb.c index 527efa9dd83..37b50f85250 100644 --- a/source/nmbd/nmbd_subnetdb.c +++ b/source/nmbd/nmbd_subnetdb.c @@ -55,22 +55,7 @@ extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */ static void add_subnet(struct subnet_record *subrec) { - struct subnet_record *subrec2; - - if (!subnetlist) - { - subnetlist = subrec; - subrec->prev = NULL; - subrec->next = NULL; - return; - } - - for (subrec2 = subnetlist; subrec2->next; subrec2 = subrec2->next) - ; - - subrec2->next = subrec; - subrec->next = NULL; - subrec->prev = subrec2; + DLIST_ADD(subnetlist, subrec); } /* ************************************************************************** ** @@ -96,19 +81,41 @@ static int namelist_entry_compare( ubi_trItemPtr Item, ubi_trNodePtr Node ) 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), 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(char *name, enum subnet_type type, - struct in_addr myip, struct in_addr bcast_ip, - struct in_addr mask_ip) + struct in_addr myip, struct in_addr bcast_ip, + struct in_addr mask_ip) { struct subnet_record *subrec = NULL; int nmb_sock, dgram_sock; @@ -130,7 +137,7 @@ static struct subnet_record *make_subnet(char *name, enum subnet_type type, * Fail the subnet creation if this fails. */ - if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr)) == -1) + if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr,True)) == -1) { if( DEBUGLVL( 0 ) ) { @@ -142,7 +149,7 @@ static struct subnet_record *make_subnet(char *name, enum subnet_type type, return NULL; } - if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr)) == -1) + if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr,True)) == -1) { if( DEBUGLVL( 0 ) ) { @@ -170,7 +177,7 @@ static struct subnet_record *make_subnet(char *name, enum subnet_type type, return(NULL); } - bzero( (char *)subrec, sizeof(*subrec) ); + memset( (char *)subrec, '\0', sizeof(*subrec) ); (void)ubi_trInitTree( subrec->namelist, namelist_entry_compare, ubi_trOVERWRITE ); @@ -202,6 +209,23 @@ static struct subnet_record *make_subnet(char *name, enum subnet_type type, 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. **************************************************************************/ @@ -225,13 +249,9 @@ BOOL create_subnets(void) for (i = 0 ; i < num_interfaces; i++) { - struct subnet_record *subrec; struct interface *iface = get_interface(i); - if((subrec = make_subnet(inet_ntoa(iface->ip), NORMAL_SUBNET, - iface->ip, iface->bcast,iface->nmask)) == NULL) - return False; - add_subnet(subrec); + if (!make_normal_subnet(iface)) return False; } /* diff --git a/source/nmbd/nmbd_synclists.c b/source/nmbd/nmbd_synclists.c index aab1e4349ca..fb51be4d8f2 100644 --- a/source/nmbd/nmbd_synclists.c +++ b/source/nmbd/nmbd_synclists.c @@ -40,7 +40,7 @@ struct sync_record { fstring server; pstring fname; struct in_addr ip; - int pid; + pid_t pid; }; /* a linked list of current sync connections */ @@ -92,7 +92,7 @@ static void sync_child(char *name, int nm_type, return; } - if (!cli_session_setup(&cli, local_machine, "", "", 1, "", 0, workgroup)) { + if (!cli_session_setup(&cli, "", "", 1, "", 0, workgroup)) { cli_shutdown(&cli); return; } @@ -103,7 +103,7 @@ static void sync_child(char *name, int nm_type, } /* Fetch a workgroup list. */ - cli_NetServerEnum(&cli, workgroup, + cli_NetServerEnum(&cli, cli.server_domain?cli.server_domain:workgroup, local_type|SV_TYPE_DOMAIN_ENUM, callback); @@ -147,7 +147,7 @@ void sync_browse_lists(struct work_record *work, slprintf(s->fname, sizeof(pstring)-1, "%s/sync.%d", lp_lockdir(), counter++); - string_sub(s->fname,"//", "/"); + all_string_sub(s->fname,"//", "/", 0); DLIST_ADD(syncs, s); diff --git a/source/nmbd/nmbd_winsproxy.c b/source/nmbd/nmbd_winsproxy.c index 43beb9acd85..1398ebd299a 100644 --- a/source/nmbd/nmbd_winsproxy.c +++ b/source/nmbd/nmbd_winsproxy.c @@ -207,7 +207,7 @@ void make_wins_proxy_name_query_request( struct subnet_record *subrec, sizeof(struct packet_struct *)]; struct userdata_struct *userdata = (struct userdata_struct *)ud; - bzero(ud, sizeof(ud)); + memset(ud, '\0', sizeof(ud)); userdata->copy_fn = wins_proxy_userdata_copy_fn; userdata->free_fn = wins_proxy_userdata_free_fn; diff --git a/source/nmbd/nmbd_winsserver.c b/source/nmbd/nmbd_winsserver.c index 35ca5af62c4..45e93351674 100644 --- a/source/nmbd/nmbd_winsserver.c +++ b/source/nmbd/nmbd_winsserver.c @@ -30,6 +30,41 @@ extern int DEBUGLEVEL; extern struct in_addr ipzero; +/**************************************************************************** +possibly call the WINS hook external program when a WINS change is made +*****************************************************************************/ +static void wins_hook(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("._-",*p))) { + DEBUG(3,("not calling wins hook for invalid name %s\n", nmb_namestr(&namerec->name))); + return; + } + } + + p = command; + p += slprintf(p, sizeof(command), "%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), " %s", inet_ntoa(namerec->data.ip[i])); + } + + DEBUG(3,("calling wins hook for %s\n", nmb_namestr(&namerec->name))); + smbrun(command, NULL, False); +} + /**************************************************************************** hash our interfaces and netbios names settings @@ -147,11 +182,6 @@ BOOL initialise_wins(void) add_samba_names_to_subnet(wins_server_subnet); -#ifndef SYNC_DNS - /* Setup the async dns. */ - start_async_dns(); -#endif - pstrcpy(fname,lp_lockdir()); trim_string(fname,NULL,"/"); pstrcat(fname,"/"); @@ -456,6 +486,7 @@ does not match group bit in WINS for this name.\n", nmb_namestr(question), group */ update_name_ttl(namerec, ttl); send_wins_name_registration_response(0, ttl, p); + wins_hook("refresh", namerec, ttl); return; } else if(group) @@ -636,7 +667,7 @@ void wins_process_name_registration_request(struct subnet_record *subrec, 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;; + BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False; putip((char *)&from_ip,&nmb->additional->rdata[2]); @@ -715,7 +746,7 @@ to register name %s. Name already exists in WINS with source type %d.\n", if(!registering_group_name && (question->name_type == 0x1d)) { DEBUG(3,("wins_process_name_registration_request: Ignoring request \ -to register name %s from IP %s.", nmb_namestr(question), inet_ntoa(p->ip) )); +to register name %s from IP %s.\n", nmb_namestr(question), inet_ntoa(p->ip) )); send_wins_name_registration_response(0, ttl, p); return; } @@ -785,6 +816,7 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio */ update_name_ttl(namerec, ttl); send_wins_name_registration_response(0, ttl, p); + wins_hook("refresh", namerec, ttl); return; } } @@ -801,6 +833,7 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio { update_name_ttl( namerec, ttl ); send_wins_name_registration_response( 0, ttl, p ); + wins_hook("refresh", namerec, ttl); return; } @@ -858,6 +891,9 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio (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))) { + wins_hook("add", namerec, ttl); + } send_wins_name_registration_response(0, ttl, p); } @@ -916,6 +952,7 @@ a subsequent IP addess.\n", nmb_namestr(question_name) )); add_ip_to_name_record(namerec, from_ip); 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); @@ -1082,11 +1119,16 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio * It's one of our names and one of our IP's. Ensure the IP is in the record and * update the ttl. */ - if(!find_ip_in_name_record(namerec, from_ip)) - add_ip_to_name_record(namerec, from_ip); - update_name_ttl(namerec, ttl); - send_wins_name_registration_response(0, ttl, p); - return; + if(!find_ip_in_name_record(namerec, from_ip)) { + 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; } } @@ -1099,6 +1141,7 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio { update_name_ttl(namerec, ttl); send_wins_name_registration_response(0, ttl, p); + wins_hook("refresh", namerec, ttl); return; } @@ -1158,6 +1201,10 @@ is one of our (WINS server) names. Denying registration.\n", nmb_namestr(questio (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))) { + wins_hook("add", namerec, ttl); + } + send_wins_name_registration_response(0, ttl, p); } @@ -1253,7 +1300,7 @@ void send_wins_name_query_response(int rcode, struct packet_struct *p, int ttl = 0; int i; - bzero(rdata,6); + memset(rdata,'\0',6); if(rcode == 0) { @@ -1495,6 +1542,8 @@ release name %s as IP %s is not one of the known IP's for this name.\n", send_wins_name_release_response(0, p); remove_ip_from_name_record(namerec, from_ip); + wins_hook("delete", namerec, 0); + /* * Remove the name entirely if no IP addresses left. */ @@ -1552,7 +1601,7 @@ void wins_write_database(BOOL background) } slprintf(fname,sizeof(fname),"%s/%s", lp_lockdir(), WINS_LIST); - string_sub(fname,"//", "/"); + all_string_sub(fname,"//", "/", 0); slprintf(fnamenew,sizeof(fnamenew),"%s.%u", fname, (unsigned int)getpid()); if((fp = sys_fopen(fnamenew,"w")) == NULL) diff --git a/source/nmbd/nmbd_workgroupdb.c b/source/nmbd/nmbd_workgroupdb.c index 0f66b140a81..5514e78dc1c 100644 --- a/source/nmbd/nmbd_workgroupdb.c +++ b/source/nmbd/nmbd_workgroupdb.c @@ -43,26 +43,9 @@ int workgroup_count = 0; /* unique index key: one for each workgroup */ static void add_workgroup(struct subnet_record *subrec, struct work_record *work) { - struct work_record *w2; - - work->subnet = subrec; - - if (!subrec->workgrouplist) - { - subrec->workgrouplist = work; - work->prev = NULL; - work->next = NULL; - return; - } - - for (w2 = subrec->workgrouplist; w2->next; w2 = w2->next) - ; - - w2->next = work; - work->next = NULL; - work->prev = w2; - - subrec->work_changed = True; + work->subnet = subrec; + DLIST_ADD(subrec->workgrouplist, work); + subrec->work_changed = True; } /**************************************************************************** @@ -80,7 +63,7 @@ static struct work_record *create_workgroup(char *name, int ttl) DEBUG(0,("create_workgroup: malloc fail !\n")); return NULL; } - bzero((char *)work, sizeof(*work)); + memset((char *)work, '\0', sizeof(*work)); StrnCpy(work->work_group,name,sizeof(work->work_group)-1); work->serverlist = NULL; @@ -254,7 +237,8 @@ void initiate_myworkgroup_startup(struct subnet_record *subrec, struct work_reco if we are so configured. */ if ((subrec != unicast_subnet) && (subrec != remote_broadcast_subnet) && - (subrec != wins_server_subnet) && lp_preferred_master()) + (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)); @@ -283,7 +267,8 @@ workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name)); SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER); create_server_on_workgroup(work,name,stype|SV_TYPE_LOCAL_LIST_ONLY, - PERMANENT_TTL, lp_serverstring()); + 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)); } |