From a82476eee2c521e5eed092bc367da0a7cef23de1 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Wed, 9 Apr 1997 01:19:25 +0000 Subject: [PATCH] Large changes from jra@cygnus.com. Mainly browser updates. access.c: Fixed crash if yp domain unavailable. includes.h: Moved ifdefs for minor platform. interface.c: Changed name of ipgrp to wins_ip to make it clearer. loadparm.c: Changed default of wins support to 'no'. nameannounce.c: Many changes to fix cross subnet browsing. namebrowse.c: Many changes to fix cross subnet browsing. namedbname.c: Many changes to fix cross subnet browsing. namedbresp.c: Many changes to fix cross subnet browsing. namedbsubnet.c: Many changes to fix cross subnet browsing. namedbwork.c: Many changes to fix cross subnet browsing. nameelect.c: Many changes to fix cross subnet browsing. namelogon.c: Many changes to fix cross subnet browsing. namepacket.c: Many changes to fix cross subnet browsing. nameresp.c: Many changes to fix cross subnet browsing. nameserv.c: Many changes to fix cross subnet browsing. nameserv.h: Many changes to fix cross subnet browsing. nameservreply.c: Many changes to fix cross subnet browsing. nameservresp.c: Many changes to fix cross subnet browsing. namework.c: Many changes to fix cross subnet browsing. nmbd.c: Change to search wins subnet. nmbsync.c: Change to check if we are any master before proceeding. proto.h: Added find_subnet_all() and check_work_servertype(). util.c: Moved 'done' settings on name resolution. --- source/include/includes.h | 2 + source/include/nameserv.h | 7 +- source/include/proto.h | 5 +- source/lib/access.c | 4 + source/lib/interface.c | 4 +- source/lib/util.c | 6 +- source/nameannounce.c | 167 +++++++++--------- source/namebrowse.c | 66 ++++++-- source/namedbname.c | 50 +++--- source/namedbresp.c | 12 +- source/namedbsubnet.c | 76 +++++---- source/namedbwork.c | 43 ++++- source/nameelect.c | 21 ++- source/namelogon.c | 164 +++++++++--------- source/namepacket.c | 13 +- source/nameresp.c | 257 ++++++++++++++-------------- source/nameserv.c | 20 ++- source/nameservreply.c | 36 ++-- source/nameservresp.c | 420 ++++++++++++++++++++++++---------------------- source/namework.c | 39 +++-- source/nmbd/nmbd.c | 2 +- source/nmbsync.c | 2 +- source/param/loadparm.c | 2 +- 23 files changed, 790 insertions(+), 628 deletions(-) diff --git a/source/include/includes.h b/source/include/includes.h index a8653d09788..249e4940a91 100644 --- a/source/include/includes.h +++ b/source/include/includes.h @@ -344,6 +344,7 @@ char *getwd(char *); #endif #ifdef SGI5 +#include #include #include #include @@ -427,6 +428,7 @@ char *mktemp(char *); /* No standard include */ #define SIGNAL_CAST ( void (*) (int) ) #define STATFS3 #define USE_F_FSIZE +#define USE_SETSID #include #ifdef OSF1_ENH_SEC #include diff --git a/source/include/nameserv.h b/source/include/nameserv.h index 027931f9e63..17ae085bc62 100644 --- a/source/include/nameserv.h +++ b/source/include/nameserv.h @@ -75,6 +75,8 @@ #define AM_BACKUP(work) (work->ServerType & SV_TYPE_BACKUP_BROWSER) #define AM_DOMMST(work) (work->ServerType & SV_TYPE_DOMAIN_MASTER) #define AM_DOMMEM(work) (work->ServerType & SV_TYPE_DOMAIN_MEMBER) +#define AM_ANY_MASTER(work) (check_work_servertype(work->work_group, \ +SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER)) /* microsoft browser NetBIOS name */ #define MSBROWSE "\001\002__MSBROWSE__\002" @@ -124,7 +126,7 @@ enum state_type NAME_QUERY_SRV_CHK, NAME_QUERY_FIND_MST, NAME_QUERY_MST_CHK, - NAME_QUERY_DOMAIN, + NAME_QUERY_DOMAIN }; /* a netbios name structure */ @@ -401,7 +403,8 @@ struct packet_struct #define CHECK_TIME_MAX_HOST_ANNCE 12 /* announce as master to WINS server and any Primary Domain Controllers */ -#define CHECK_TIME_MST_ANNOUNCE 15 +/* ORIGINAL - changed for test by JRA #define CHECK_TIME_MST_ANNOUNCE 15 */ +#define CHECK_TIME_MST_ANNOUNCE 1 /* do all remote announcements this often */ #define REMOTE_ANNOUNCE_INTERVAL 180 diff --git a/source/include/proto.h b/source/include/proto.h index bbfcad78f94..cfc05c1c6b4 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -386,11 +386,9 @@ void expire_servers(time_t t); struct subnet_record *find_subnet(struct in_addr bcast_ip); struct subnet_record *find_req_subnet(struct in_addr ip, BOOL bcast); +struct subnet_record *find_subnet_all(struct in_addr bcast_ip); void add_subnet_interfaces(void); void add_my_subnets(char *group); -struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, - struct in_addr mask_ip, - char *name, BOOL add, BOOL lmhosts); void write_browse_list(time_t t); /*The following definitions come from namedbwork.c */ @@ -401,6 +399,7 @@ struct work_record *remove_workgroup(struct subnet_record *d, struct work_record *find_workgroupstruct(struct subnet_record *d, fstring name, BOOL add); void dump_workgroups(void); +int check_work_servertype(const char *work_name, int type_mask); /*The following definitions come from nameelect.c */ diff --git a/source/lib/access.c b/source/lib/access.c index 31a48d09d3c..599cb5ca7e3 100644 --- a/source/lib/access.c +++ b/source/lib/access.c @@ -209,6 +209,10 @@ static int string_match(char *tok,char *s) if (!mydomain) yp_get_default_domain(&mydomain); + if (!mydomain) { + DEBUG(0,("Unable to get default yp domain.\n")); + return NO; + } if (!(hostname = strdup(s))) { DEBUG(1,("out of memory for strdup!\n")); return NO; diff --git a/source/lib/interface.c b/source/lib/interface.c index 1c41293cf77..0e2a13e7b93 100644 --- a/source/lib/interface.c +++ b/source/lib/interface.c @@ -24,7 +24,7 @@ extern int DEBUGLEVEL; struct in_addr ipzero; -struct in_addr ipgrp; +struct in_addr wins_ip; static struct in_addr default_ip; static struct in_addr default_bcast; static struct in_addr default_nmask; @@ -261,7 +261,7 @@ static void interpret_interfaces(char *s, struct interface **interfaces, struct in_addr ip; ipzero = *interpret_addr2("0.0.0.0"); - ipgrp = *interpret_addr2("255.255.255.255"); + wins_ip = *interpret_addr2("255.255.255.255"); while (next_token(&ptr,token,NULL)) { /* parse it into an IP address/netmasklength pair */ diff --git a/source/lib/util.c b/source/lib/util.c index 643c2fb7a50..53b24173d51 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -3090,12 +3090,10 @@ char *client_name(void) if (done) return name_buf; - done = True; strcpy(name_buf,"UNKNOWN"); if (getpeername(Client, &sa, &length) < 0) { DEBUG(0,("getpeername failed\n")); - done = False; return name_buf; } @@ -3105,7 +3103,6 @@ char *client_name(void) AF_INET)) == 0) { DEBUG(1,("Gethostbyaddr failed for %s\n",client_addr())); StrnCpy(name_buf,client_addr(),sizeof(name_buf) - 1); - done = False; } else { StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1); if (!matchname(name_buf, sockin->sin_addr)) { @@ -3113,6 +3110,7 @@ char *client_name(void) strcpy(name_buf,"UNKNOWN"); } } + done = True; return name_buf; } @@ -3129,7 +3127,6 @@ char *client_addr(void) if (done) return addr_buf; - done = True; strcpy(addr_buf,"0.0.0.0"); if (getpeername(Client, &sa, &length) < 0) { @@ -3139,6 +3136,7 @@ char *client_addr(void) strcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr)); + done = True; return addr_buf; } diff --git a/source/nameannounce.c b/source/nameannounce.c index 8dc0668f4ed..a1eae127a2a 100644 --- a/source/nameannounce.c +++ b/source/nameannounce.c @@ -45,7 +45,7 @@ extern struct subnet_record *subnetlist; extern int updatecount; extern int workgroup_count; -extern struct in_addr ipgrp; +extern struct in_addr wins_ip; @@ -216,7 +216,7 @@ void announce_server(struct subnet_record *d, struct work_record *work, (SV_TYPE_SERVER_UNIX, for example) */ uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT; - BOOL wins_iface = ip_equal(d->bcast_ip, ipgrp); + BOOL wins_iface = ip_equal(d->bcast_ip, wins_ip); if (wins_iface && server_type != 0) { @@ -261,7 +261,7 @@ void announce_server(struct subnet_record *d, struct work_record *work, do_announce_host(ANN_LocalMasterAnnouncement, name , 0x00, d->myip, work->work_group, 0x1e, d->bcast_ip, - ttl*1000, + ttl, name, server_type, comment); DEBUG(3,("sending domain announce to %s for %s\n", @@ -273,7 +273,7 @@ void announce_server(struct subnet_record *d, struct work_record *work, do_announce_host(ANN_DomainAnnouncement, name , 0x00, d->myip, MSBROWSE, 0x01, d->bcast_ip, - ttl*1000, + ttl, work->work_group, server_type ? domain_type : 0, name); } @@ -286,7 +286,7 @@ void announce_server(struct subnet_record *d, struct work_record *work, do_announce_host(ANN_HostAnnouncement, name , 0x00, d->myip, work->work_group, 0x1d, d->bcast_ip, - ttl*1000, + ttl, name, server_type, comment); } } @@ -309,24 +309,24 @@ void announce_host(time_t t) { struct work_record *work; - if (ip_equal(d->bcast_ip, ipgrp)) continue; - + if (ip_equal(d->bcast_ip, wins_ip)) continue; + for (work = d->workgrouplist; work; work = work->next) { uint32 stype = work->ServerType; struct server_record *s; BOOL announce = False; - /* must work on the code that does announcements at up to - 30 seconds later if a master browser sends us a request - announce. - */ + /* must work on the code that does announcements at up to + 30 seconds later if a master browser sends us a request + announce. + */ if (work->needannounce) { /* drop back to a max 3 minute announce - this is to prevent a single lost packet from stuffing things up for too long */ work->announce_interval = MIN(work->announce_interval, - CHECK_TIME_MIN_HOST_ANNCE*60); + CHECK_TIME_MIN_HOST_ANNCE*60); work->lastannounce_time = t - (work->announce_interval+1); } @@ -339,7 +339,7 @@ void announce_host(time_t t) work->announce_interval += 60; work->lastannounce_time = t; - + for (s = work->serverlist; s; s = s->next) { if (strequal(myname, s->serv.name)) { announce = True; @@ -353,18 +353,18 @@ void announce_host(time_t t) } if (work->needannounce) - { + { work->needannounce = False; break; /* sorry: can't do too many announces. do some more later */ - } + } } - } + } } /**************************************************************************** - announce myself as a master to all other primary domain conrollers. + announce myself as a master to all other domain master browsers. this actually gets done in search_and_sync_workgroups() via the NAME_QUERY_DOM_SRV_CHK command, if there is a response from the @@ -393,86 +393,77 @@ void announce_master(time_t t) } } } - + + DEBUG(4,( "announce_master: am_master = %d for workgroup %s\n", am_master, lp_workgroup())); + if (!am_master) return; /* only proceed if we are a master browser */ + /* Note that we don't do this if we are domain master browser. */ + for (d = subnetlist; d; d = d->next) { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - struct server_record *s; - for (s = work->serverlist; s; s = s->next) - { - if (strequal(s->serv.name, myname)) continue; - - /* all DOMs (which should also be master browsers) */ - if (s->serv.type & SV_TYPE_DOMAIN_CTRL) - { - /* check the existence of a pdc for this workgroup, and if - one exists at the specified ip, sync with it and announce - ourselves as a master browser to it */ - - if (!*lp_domain_controller() || - !strequal(lp_domain_controller(), s->serv.name)) - { - if (!lp_wins_support() && *lp_wins_server()) - { - queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY, - NAME_QUERY_DOM_SRV_CHK, - work->work_group,0x1b,0,0,0,NULL,NULL, - False, False, ipzero, ipzero); - } - else - { - struct subnet_record *d2; - for (d2 = subnetlist; d2; d2 = d2->next) - { - queue_netbios_packet(d,ClientNMB,NMB_QUERY, - NAME_QUERY_DOM_SRV_CHK, - work->work_group,0x1b,0,0,0,NULL,NULL, - True, False, d2->bcast_ip, d2->bcast_ip); - } - } - } - } - } - - /* now do primary domain controller - the one that's not - necessarily in our browse lists, although it ought to be - this pdc is the one that we get TOLD about through smb.conf. - basically, if it's on a subnet that we know about, it may end - up in our browse lists (which is why it's explicitly excluded - in the code above) */ - - if (*lp_domain_controller()) - { - struct in_addr ip; - BOOL bcast = False; - - ip = *interpret_addr2(lp_domain_controller()); - - if (zero_ip(ip)) { - ip = d->bcast_ip; - bcast = True; - } - - DEBUG(2, ("Searching for DOM %s at %s\n", - lp_domain_controller(), inet_ntoa(ip))); - - /* check the existence of a pdc for this workgroup, and if - one exists at the specified ip, sync with it and announce - ourselves as a master browser to it */ - queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,NAME_QUERY_DOM_SRV_CHK, - work->work_group,0x1b,0,0,0,NULL,NULL, - bcast, False, ip, ip); + /* Try and find our workgroup on this subnet */ + struct work_record *work = find_workgroupstruct(d, lp_workgroup(), True); + + if (work) + { + char *name; + int type; + + if (*lp_domain_controller()) + { + /* the domain controller option is used to manually specify + the domain master browser to sync with + */ + + /* XXXX i'm not sure we should be using the domain controller + option for this purpose. + */ + + name = lp_domain_controller(); + type = 0x20; + } + else + { + /* assume that the domain master browser we want to sync + with is our own domain. + */ + name = work->work_group; + type = 0x1b; + } + + /* check the existence of a dmb for this workgroup, and if + one exists at the specified ip, sync with it and announce + ourselves as a master browser to it + */ + + if (!lp_wins_support() && *lp_wins_server() && + ip_equal(d->bcast_ip, wins_ip)) + { + DEBUG(4, ("Local Announce: find %s<%02x> from WINS server %s\n", + name, type, lp_wins_server())); + + queue_netbios_pkt_wins(d,ClientNMB, + NMB_QUERY,NAME_QUERY_DOM_SRV_CHK, + name, type, 0,0,0, + work->work_group,NULL, + False, False, ipzero, ipzero); + } + else + { + DEBUG(4, ("Local Announce: find %s<%02x> on %s\n", + name, type, inet_ntoa(d->bcast_ip))); + + queue_netbios_packet(d,ClientNMB, + NMB_QUERY,NAME_QUERY_DOM_SRV_CHK, + name, type, 0,0,0, + work->work_group,NULL, + True, False, d->bcast_ip, d->bcast_ip); } } } } - - /**************************************************************************** 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 diff --git a/source/namebrowse.c b/source/namebrowse.c index 3bc4f9f82aa..b87ea9fec34 100644 --- a/source/namebrowse.c +++ b/source/namebrowse.c @@ -32,6 +32,8 @@ extern int ClientNMB; extern int DEBUGLEVEL; +extern struct in_addr wins_ip; + /* this is our browse master/backup cache database */ static struct browse_cache_record *browserlist = NULL; @@ -89,7 +91,6 @@ void expire_browse_cache(time_t t) } } - /**************************************************************************** add a browser entry ****************************************************************************/ @@ -166,21 +167,48 @@ static void start_sync_browse_entry(struct browse_cache_record *b) struct subnet_record *d; struct work_record *work; - if (!(d = find_subnet(b->ip))) return; + /* Look for the workgroup first on the local subnet. If this + fails try WINS - we may need to sync with the domain master, + or we may be the domain master and need to sync with subnet + masters. + */ + + if (!(d = find_subnet_all(b->ip))) { + DEBUG(0, ("start_sync_browse_entry: failed to get a \ +subnet for a browse cache entry workgroup %s, server %s\n", + b->group, b->name)); + return; + } - if (!(work = find_workgroupstruct(d, b->group, False))) return; + if (!(work = find_workgroupstruct(d, b->group, False))) { + DEBUG(0, ("start_sync_browse_entry: failed to get a \ +workgroup for a browse cache entry workgroup %s, server %s\n", + b->group, b->name)); + return; + } - /* only sync if we are the master */ - if (AM_MASTER(work)) { + /* only sync if we are a subnet master or domain master - but + we sync if we are a master for this workgroup on *any* + of our interfaces. */ + if (AM_MASTER(work) || AM_DOMMST(work) || AM_ANY_MASTER(work)) { - /* first check whether the group we intend to sync with exists. if it - doesn't, the server must have died. o dear. */ + DEBUG(4, ("start_sync_browse_entry: Initiating %s sync with %s<0x20>, \ +workgroup %s\n", + b->local ? "local" : "remote", b->name, b->group)); - /* see response_netbios_packet() or expire_netbios_response_entries() */ - queue_netbios_packet(d,ClientNMB,NMB_QUERY, - b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE, - b->group,0x20,0,0,0,NULL,NULL, - False,False,b->ip,b->ip); + /* first check whether the server we intend to sync with exists. if it + doesn't, the server must have died. o dear. */ + + /* see response_netbios_packet() or expire_netbios_response_entries() */ + /* We cheat here by using the my_comment field of the response_record + struct as the workgroup name we are going to do the sync for. + This is because the reply packet doesn't include the workgroup, but + we need it when the reply comes back. + */ + queue_netbios_packet(d,ClientNMB,NMB_QUERY, + b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE, + b->name,0x20,0,0,0,NULL,b->group, + False,False,b->ip,b->ip); } b->synced = True; @@ -195,10 +223,14 @@ void do_browser_lists(time_t t) struct browse_cache_record *b; static time_t last = 0; - if (t-last < 20) return; /* don't do too many of these at once! */ + if (t-last < 20) + { + DEBUG(9,("do_browser_lists: returning due to t(%d) - last(%d) < 20\n", + t, last)); + return; /* don't do too many of these at once! */ /* XXXX equally this period should not be too long the server may die in the intervening gap */ - + } last = t; /* pick any entry in the list, preferably one whose time is up */ @@ -210,9 +242,15 @@ void do_browser_lists(time_t t) if (b && !b->synced) { /* sync with the selected entry then remove some dead entries */ + DEBUG(4,("do_browser_lists: Initiating sync with %s, workgroup %s\n", + b->name, b->group)); start_sync_browse_entry(b); expire_browse_cache(t - 60); } + else + { + DEBUG(9, ("do_browser_lists: no entries to sync.\n")); + } } diff --git a/source/namedbname.c b/source/namedbname.c index 2e8c8d589ae..d27bcf81586 100644 --- a/source/namedbname.c +++ b/source/namedbname.c @@ -35,7 +35,7 @@ extern int DEBUGLEVEL; extern pstring scope; extern struct in_addr ipzero; -extern struct in_addr ipgrp; +extern struct in_addr wins_ip; extern struct subnet_record *subnetlist; @@ -153,10 +153,11 @@ struct name_record *find_name(struct name_record *n, { continue; } - + DEBUG(9,("find_name: found name %s\n", name->name)); return ret; } } + DEBUG(9,("find_name: name %s NOT FOUND\n", name->name)); return NULL; } @@ -172,27 +173,27 @@ struct name_record *find_name_search(struct subnet_record **d, struct nmb_name *name, int search, struct in_addr ip) { - if (d == NULL) return NULL; /* bad error! */ + if (d == NULL) return NULL; /* bad error! */ - if (search & FIND_LOCAL) { - if (*d != NULL) { - struct name_record *n = find_name((*d)->namelist, name, search); - DEBUG(4,("find_name on local: %s %s search %x\n", - namestr(name),inet_ntoa(ip), search)); - if (n) return n; - } + if (search & FIND_LOCAL) { + if (*d != NULL) { + struct name_record *n = find_name((*d)->namelist, name, search); + DEBUG(4,("find_name on local: %s %s search %x\n", + namestr(name),inet_ntoa(ip), search)); + if (n) return n; } + } - if (!(search & FIND_WINS)) return NULL; + if (!(search & FIND_WINS)) return NULL; - /* find WINS subnet record. */ - *d = find_subnet(ipgrp); - - if (*d == NULL) return NULL; - - DEBUG(4,("find_name on WINS: %s %s search %x\n", - namestr(name),inet_ntoa(ip), search)); - return find_name((*d)->namelist, name, search); + /* find WINS subnet record. */ + *d = find_subnet(wins_ip); + + if (*d == NULL) return NULL; + + DEBUG(4,("find_name on WINS: %s %s search %x\n", + namestr(name),inet_ntoa(ip), search)); + return find_name((*d)->namelist, name, search); } @@ -245,7 +246,7 @@ void dump_names(void) } DEBUG(4,("\n")); - if (f && ip_equal(d->bcast_ip, ipgrp) && n->source == REGISTER) + if (f && ip_equal(d->bcast_ip, wins_ip) && n->source == REGISTER) { /* XXXX i have little imagination as to how to output nb_flags as anything other than as a hexadecimal number :-) */ @@ -281,7 +282,7 @@ void dump_names(void) ****************************************************************************/ void load_netbios_names(void) { - struct subnet_record *d = find_subnet(ipgrp); + struct subnet_record *d = find_subnet(wins_ip); fstring fname; FILE *f; @@ -466,8 +467,9 @@ struct name_record *add_netbios_entry(struct subnet_record *d, if (!n2) add_name(d,n); - DEBUG(3,("Added netbios name %s at %s ttl=%d nb_flags=%2x\n", - namestr(&n->name),inet_ntoa(ip),ttl,nb_flags)); + DEBUG(3,("Added netbios name %s at %s ttl=%d nb_flags=%2x to interface %s\n", + namestr(&n->name),inet_ntoa(ip),ttl,nb_flags, + ip_equal(d->bcast_ip, wins_ip) ? "WINS" : inet_ntoa(d->bcast_ip))); return(n); } @@ -520,7 +522,7 @@ struct name_record *dns_name_search(struct nmb_name *question, int Time) char *r; BOOL dns_type = (name_type == 0x20 || name_type == 0); struct in_addr dns_ip; - struct subnet_record *d = find_subnet(ipgrp); + struct subnet_record *d = find_subnet(wins_ip); if (d == NULL) return NULL; diff --git a/source/namedbresp.c b/source/namedbresp.c index d89bfe8ae84..6755de6534b 100644 --- a/source/namedbresp.c +++ b/source/namedbresp.c @@ -34,7 +34,6 @@ extern int DEBUGLEVEL; extern pstring scope; extern pstring myname; extern struct in_addr ipzero; -extern struct in_addr ipgrp; int num_response_packets = 0; @@ -117,9 +116,14 @@ struct response_record *make_response_queue_record(enum state_type state, n->recurse = recurse; n->send_ip = send_ip; n->reply_to_ip = reply_to_ip; - StrnCpy(my_name , n->my_name , sizeof(n->my_name )-1); - StrnCpy(my_comment, n->my_comment, sizeof(n->my_comment)-1); - + if(my_name) + StrnCpy(n->my_name, my_name, sizeof(n->my_name)-1); + else + *n->my_name = 0; + if(my_comment) + StrnCpy(n->my_comment, my_comment, sizeof(n->my_comment)-1); + else + *n->my_comment = 0; n->repeat_interval = 1; /* XXXX should be in ms */ n->repeat_count = 3; /* 3 retries */ n->repeat_time = time(NULL) + n->repeat_interval; /* initial retry time */ diff --git a/source/namedbsubnet.c b/source/namedbsubnet.c index 367179b6c61..144729e1e17 100644 --- a/source/namedbsubnet.c +++ b/source/namedbsubnet.c @@ -36,7 +36,7 @@ extern int ClientDGRAM; extern int DEBUGLEVEL; -extern struct in_addr ipgrp; +extern struct in_addr wins_ip; extern struct in_addr ipzero; extern pstring myname; @@ -52,6 +52,11 @@ struct subnet_record *subnetlist = NULL; extern uint16 nb_type; /* samba's NetBIOS name type */ +/* Forward references. */ +static struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, + struct in_addr mask_ip, + char *name, BOOL add, BOOL lmhosts); + /**************************************************************************** add a domain into the list **************************************************************************/ @@ -81,31 +86,30 @@ static void add_subnet(struct subnet_record *d) struct subnet_record *find_subnet(struct in_addr bcast_ip) { struct subnet_record *d; - struct in_addr wins_ip = ipgrp; /* search through subnet list for broadcast/netmask that matches the source ip address. a subnet 255.255.255.255 represents the WINS list. */ - for (d = subnetlist; d; d = d->next) + for (d = subnetlist; d; d = d->next) { - if (ip_equal(bcast_ip, wins_ip)) + if (ip_equal(bcast_ip, wins_ip)) + { + if (ip_equal(bcast_ip, d->bcast_ip)) { - if (ip_equal(bcast_ip, d->bcast_ip)) - { - return d; - } + return d; + } } - else if (same_net(bcast_ip, d->bcast_ip, d->mask_ip)) + else if (same_net(bcast_ip, d->bcast_ip, d->mask_ip)) + { + if (!ip_equal(d->bcast_ip, wins_ip)) { - if (!ip_equal(d->bcast_ip, wins_ip)) - { - return d; - } + return d; } + } } - return (NULL); + return (NULL); } @@ -122,9 +126,19 @@ struct subnet_record *find_req_subnet(struct in_addr ip, BOOL bcast) return find_subnet(*iface_bcast(ip)); } /* find the subnet under the pseudo-ip of 255.255.255.255 */ - return find_subnet(ipgrp); + return find_subnet(wins_ip); } +/**************************************************************************** + find a subnet in the subnetlist - if the subnet is not found + then return the WINS subnet. + **************************************************************************/ +struct subnet_record *find_subnet_all(struct in_addr bcast_ip) +{ + struct subnet_record *d = find_subnet(bcast_ip); + if(!d) + return find_subnet( wins_ip); +} /**************************************************************************** create a domain entry @@ -157,24 +171,24 @@ static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr ****************************************************************************/ void add_subnet_interfaces(void) { - struct interface *i; + struct interface *i; - /* loop on all local interfaces */ - for (i = local_interfaces; i; i = i->next) + /* loop on all local interfaces */ + for (i = local_interfaces; i; i = i->next) + { + /* add the interface into our subnet database */ + if (!find_subnet(i->bcast)) { - /* add the interface into our subnet database */ - if (!find_subnet(i->bcast)) - { - make_subnet(i->bcast,i->nmask); - } + make_subnet(i->bcast,i->nmask); } + } - /* add the pseudo-ip interface for WINS: 255.255.255.255 */ - if (lp_wins_support() || (*lp_wins_server())) + /* add the pseudo-ip interface for WINS: 255.255.255.255 */ + if (lp_wins_support() || (*lp_wins_server())) { - struct in_addr wins_bcast = ipgrp; - struct in_addr wins_nmask = ipzero; - make_subnet(wins_bcast, wins_nmask); + struct in_addr wins_bcast = wins_ip; + struct in_addr wins_nmask = ipzero; + make_subnet(wins_bcast, wins_nmask); } } @@ -205,7 +219,7 @@ void add_my_subnets(char *group) add a domain entry. creates a workgroup, if necessary, and adds the domain to the named a workgroup. ****************************************************************************/ -struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, +static struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, struct in_addr mask_ip, char *name, BOOL add, BOOL lmhosts) { @@ -215,7 +229,7 @@ struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, in the DEBUG comment. i assume that the DEBUG comment below actually intends to refer to bcast_ip? i don't know. - struct in_addr ip = ipgrp; + struct in_addr ip = wins_ip; */ @@ -223,6 +237,8 @@ struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, bcast_ip = *iface_bcast(bcast_ip); /* add the domain into our domain database */ + /* Note that we never add into the WINS subnet as add_subnet_entry + is only called to add our local interfaces. */ if ((d = find_subnet(bcast_ip)) || (d = make_subnet(bcast_ip, mask_ip))) { diff --git a/source/namedbwork.c b/source/namedbwork.c index 0cfc47c41a8..80a670fea84 100644 --- a/source/namedbwork.c +++ b/source/namedbwork.c @@ -38,7 +38,7 @@ extern int DEBUGLEVEL; /* this is our domain/workgroup/server database */ extern struct subnet_record *subnetlist; -extern struct in_addr ipgrp; +extern struct in_addr wins_ip; int workgroup_count = 0; /* unique index key: one for each workgroup */ @@ -201,7 +201,7 @@ struct work_record *find_workgroupstruct(struct subnet_record *d, if ((work = make_workgroup(name))) { - if (!ip_equal(d->bcast_ip, ipgrp) && + if (!ip_equal(d->bcast_ip, wins_ip) && lp_preferred_master() && strequal(lp_workgroup(), name)) { @@ -248,3 +248,42 @@ void dump_workgroups(void) } } } + +/**************************************************************************** + check to see if a ServerType bit is set in any workgroup on any interface + except WINS. Used to determine if a nmbd is a master browser or domain + master browser in a particular workgroup on any subnet. + **************************************************************************/ +int check_work_servertype(const char *work_name, int type_mask) +{ + struct subnet_record *d; + + for (d = subnetlist; d; d = d->next) + { + if(ip_equal(d->bcast_ip, wins_ip)) + { + /* WINS ip */ + DEBUG(10,("check_work_servertype: ignoring WINS subnet\n")); + continue; + } + if (d->workgrouplist) + { + struct work_record *work; + + for (work = d->workgrouplist; work; work = work->next) + { + if(strequal(work->work_group, (char *)work_name) && + (type_mask & work->ServerType) != 0) + { + DEBUG(10, ("check_work_servertype: Workgroup %s has \ +ServerType %x - match for type_mask %x\n", work_name, work->ServerType, + type_mask)); + return 1; + } + } + } + } + DEBUG(10, ("check_work_servertype: Workgroup %s has no match for \ +type mask %x\n", work_name, type_mask)); + return 0; +} diff --git a/source/nameelect.c b/source/nameelect.c index c33206083ec..a11d0fb7867 100644 --- a/source/nameelect.c +++ b/source/nameelect.c @@ -41,7 +41,7 @@ extern pstring scope; extern pstring myname; extern struct in_addr ipzero; -extern struct in_addr ipgrp; +extern struct in_addr wins_ip; /* here are my election parameters */ @@ -71,6 +71,10 @@ void check_master_browser(time_t t) { struct work_record *work; + /* don't do election stuff on the WINS subnet */ + if (ip_equal(d->bcast_ip,wins_ip)) + continue; + for (work = d->workgrouplist; work; work = work->next) { if (!AM_MASTER(work)) @@ -116,7 +120,7 @@ void browser_gone(char *work_name, struct in_addr ip) if (!work || !d) return; /* don't do election stuff on the WINS subnet */ - if (ip_equal(d->bcast_ip,ipgrp)) + if (ip_equal(d->bcast_ip,wins_ip)) return; if (strequal(work->work_group, lp_workgroup())) @@ -350,6 +354,9 @@ void become_local_master(struct subnet_record *d, struct work_record *work) /* update our server status */ work->ServerType |= SV_TYPE_MASTER_BROWSER; + + DEBUG(3,("become_local_master: updating our server %s to type %x\n", myname, work->ServerType)); + add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True); if (work->serverlist == NULL) /* no servers! */ @@ -638,6 +645,14 @@ void run_elections(time_t t) for (d = subnetlist; d; d = d->next) { struct work_record *work; + + if(ip_equal(d->bcast_ip, wins_ip)) + { + /* WINS ip */ + DEBUG(10,("run_elections: ignoring WINS subnet\n")); + continue; + } + for (work = d->workgrouplist; work; work = work->next) { if (work->RunningElection) @@ -710,7 +725,7 @@ void process_election(struct packet_struct *p,char *buf) if (!d) return; - if (ip_equal(d->bcast_ip,ipgrp)) { + if (ip_equal(d->bcast_ip,wins_ip)) { DEBUG(3,("Unexpected election request from %s %s on WINS net\n", name, inet_ntoa(p->ip))); return; diff --git a/source/namelogon.c b/source/namelogon.c index 3fab49cedd6..1ea09ee2bb6 100644 --- a/source/namelogon.c +++ b/source/namelogon.c @@ -47,104 +47,114 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len) { struct dgram_packet *dgram = &p->packet.dgram; struct in_addr ip = dgram->header.source_ip; - struct subnet_record *d = find_subnet(ip); + struct subnet_record *d = find_subnet_all(ip); char *logname,*q; fstring reply_name; BOOL add_slashes = False; pstring outbuf; int code,reply_code; struct work_record *work; - char unknown_byte = 0; - uint16 request_count = 0; - uint16 token = 0; + char unknown_byte = 0; + uint16 request_count = 0; + uint16 token = 0; - if (!d) return; - - if (!(work = find_workgroupstruct(d,dgram->dest_name.name, False))) return; + if (!lp_domain_logons()) + { + DEBUG(3,("No domain logons\n")); + return; + } - if (!lp_domain_logons()) - { - DEBUG(3,("No domain logons\n")); - return; - } + if (!d) + { + DEBUG(0,("process_logon_packet: Cannot find subnet for logon request from %s\n", + inet_ntoa(p->ip) )); + return; + } - code = SVAL(buf,0); - switch (code) - { - case 0: + if (!(work = find_workgroupstruct(d,dgram->dest_name.name, False))) { - char *machine = buf+2; - char *user = skip_string(machine,1); - char *tmp; - logname = skip_string(user,1); - tmp = skip_string(logname,1); - unknown_byte = CVAL(tmp,0); - request_count = SVAL(tmp,1); - token = SVAL(tmp,3); - - reply_code = 0x6; - strcpy(reply_name,myname); - strupper(reply_name); - add_slashes = True; - DEBUG(3,("Domain login request from %s(%s) user=%s token=%x\n", - machine,inet_ntoa(p->ip),user,token)); - break; - } - case 7: + DEBUG(0,("process_logon_packet: Cannot find WORKGROUP %s for logon request fomr %s\n", + dgram->dest_name.name, inet_ntoa(p->ip) )); + return; + } + + code = SVAL(buf,0); + switch (code) { - char *machine = buf+2; - logname = skip_string(machine,1); - token = SVAL(skip_string(logname,1),0); - - strcpy(reply_name,lp_domain_controller()); - if (!*reply_name) - { - /* oo! no domain controller. must be us, then */ + case 0: + { + char *machine = buf+2; + char *user = skip_string(machine,1); + char *tmp; + logname = skip_string(user,1); + tmp = skip_string(logname,1); + unknown_byte = CVAL(tmp,0); + request_count = SVAL(tmp,1); + token = SVAL(tmp,3); + + reply_code = 0x6; strcpy(reply_name,myname); - reply_code = 0xC; + strupper(reply_name); + add_slashes = True; + DEBUG(3,("Domain login request from %s(%s) user=%s token=%x\n", + machine,inet_ntoa(p->ip),user,token)); + break; + } + case 7: + { + char *machine = buf+2; + logname = skip_string(machine,1); + token = SVAL(skip_string(logname,1),0); + + strcpy(reply_name,lp_domain_controller()); + if (!*reply_name) + { + /* oo! no domain controller. must be us, then */ + strcpy(reply_name,myname); + reply_code = 0xC; + } + else + { + /* refer logon request to the domain controller */ + reply_code = 0x7; + } + + strupper(reply_name); + DEBUG(3,("GETDC request from %s(%s), reporting %s 0x%x token=%x\n", + machine,inet_ntoa(p->ip), reply_name, reply_code,token)); + break; + } + default: + { + DEBUG(3,("Unknown domain request %d\n",code)); + return; } - else - { - /* refer logon request to the domain controller */ - reply_code = 0x7; } - - strupper(reply_name); - DEBUG(3,("GETDC request from %s(%s), reporting %s 0x%x token=%x\n", - machine,inet_ntoa(p->ip), reply_name, reply_code,token)); - break; - } - default: - { - DEBUG(3,("Unknown domain request %d\n",code)); - return; - } - } bzero(outbuf,sizeof(outbuf)); q = outbuf; SSVAL(q,0,reply_code); q += 2; - - if (token == 0xffff || /* LM 2.0 or later */ - token == 0xfffe) /* WfWg networking */ + + if (token == 0xffff || /* LM 2.0 or later */ + token == 0xfffe) /* WfWg networking */ + { + if (add_slashes) { - if (add_slashes) - { - strcpy(q,"\\\\"); - q += 2; - } - strcpy(q, reply_name); - strupper(q); - q = skip_string(q,1); - - if (token == 0xffff) /* LM 2.0 or later */ - { - SSVAL(q,0,token); - q += 2; - } + strcpy(q,"\\\\"); + q += 2; } - + strcpy(q, reply_name); + strupper(q); + q = skip_string(q,1); + + if (token == 0xffff) /* LM 2.0 or later */ + { + SSVAL(q,0,token); + q += 2; + } + } + SSVAL(q,0,0xFFFF); q += 2; diff --git a/source/namepacket.c b/source/namepacket.c index 043e2c02f0f..09ee5dd79e2 100644 --- a/source/namepacket.c +++ b/source/namepacket.c @@ -36,7 +36,7 @@ extern int num_response_packets; BOOL CanRecurse = True; extern pstring scope; -extern struct in_addr ipgrp; +extern struct in_addr wins_ip; static uint16 name_trn_id=0; @@ -91,9 +91,9 @@ static void update_name_trn_id(void) initiate a netbios packet ****************************************************************************/ void initiate_netbios_packet(uint16 *id, - int fd,int quest_type,char *name,int name_type, - int nb_flags,BOOL bcast,BOOL recurse, - struct in_addr to_ip) + int fd,int quest_type,char *name,int name_type, + int nb_flags,BOOL bcast,BOOL recurse, + struct in_addr to_ip) { struct packet_struct p; struct nmb_packet *nmb = &p.packet.nmb; @@ -323,8 +323,10 @@ static BOOL listening(struct packet_struct *p,struct nmb_name *n) struct subnet_record *d; struct name_record *n1; + /* We explicitly don't search WINS here - this will be done + in find_name_search is it was a packet from a non-local subnet. */ d = find_subnet(p->ip); - + n1 = find_name_search(&d,n,FIND_LOCAL|FIND_WINS|FIND_SELF,p->ip); return (n1 != NULL); @@ -565,7 +567,6 @@ BOOL send_mailslot_reply(BOOL unique, char *mailslot,int fd,char *buf,int len,ch { struct packet_struct p; struct dgram_packet *dgram = &p.packet.dgram; - struct in_addr wins_ip = ipgrp; char *ptr,*p2; char tmp[4]; diff --git a/source/nameresp.c b/source/nameresp.c index b920742c765..fab16038ce0 100644 --- a/source/nameresp.c +++ b/source/nameresp.c @@ -33,7 +33,7 @@ extern int DEBUGLEVEL; extern pstring scope; extern struct in_addr ipzero; -extern struct in_addr ipgrp; +extern struct in_addr wins_ip; /*************************************************************************** @@ -51,146 +51,146 @@ static void dead_netbios_entry(struct subnet_record *d, { case NAME_QUERY_CONFIRM: { - if (!lp_wins_support()) return; /* only if we're a WINS server */ - - if (n->num_msgs == 0) + if (!lp_wins_support()) return; /* only if we're a WINS server */ + + if (n->num_msgs == 0) { - /* oops. name query had no response. check that the name is - unique and then remove it from our WINS database */ - - /* IMPORTANT: see query_refresh_names() */ - - if ((!NAME_GROUP(n->nb_flags))) - { - struct subnet_record *d1 = find_subnet(ipgrp); - if (d1) - { - /* remove the name that had been registered with us, - and we're now getting no response when challenging. - see rfc1001.txt 15.5.2 - */ - remove_netbios_name(d1, n->name.name, n->name.name_type, - REGISTER, n->send_ip); - } - } + /* oops. name query had no response. check that the name is + unique and then remove it from our WINS database */ + + /* IMPORTANT: see query_refresh_names() */ + + if ((!NAME_GROUP(n->nb_flags))) + { + struct subnet_record *d1 = find_subnet(wins_ip); + if (d1) + { + /* remove the name that had been registered with us, + and we're now getting no response when challenging. + see rfc1001.txt 15.5.2 + */ + remove_netbios_name(d1, n->name.name, n->name.name_type, + REGISTER, n->send_ip); } - break; + } + } + break; } - - case NAME_QUERY_MST_CHK: + + case NAME_QUERY_MST_CHK: + { + /* if no response received, the master browser must have gone + down on that subnet, without telling anyone. */ + + /* IMPORTANT: see response_netbios_packet() */ + + if (n->num_msgs == 0) + browser_gone(n->name.name, n->send_ip); + break; + } + + case NAME_RELEASE: + { + /* if no response received, it must be OK for us to release the + name. nobody objected (including a potentially dead or deaf + WINS server) */ + + /* IMPORTANT: see response_name_release() */ + + if (ismyip(n->send_ip)) { - /* if no response received, the master browser must have gone - down on that subnet, without telling anyone. */ - - /* IMPORTANT: see response_netbios_packet() */ - - if (n->num_msgs == 0) - browser_gone(n->name.name, n->send_ip); - break; + name_unregister_work(d,n->name.name,n->name.name_type); } - - case NAME_RELEASE: + if (!n->bcast && n->num_msgs == 0) { - /* if no response received, it must be OK for us to release the - name. nobody objected (including a potentially dead or deaf - WINS server) */ - - /* IMPORTANT: see response_name_release() */ - - if (ismyip(n->send_ip)) - { - name_unregister_work(d,n->name.name,n->name.name_type); - } - if (!n->bcast && n->num_msgs == 0) - { - DEBUG(0,("WINS server did not respond to name release!\n")); - /* XXXX whoops. we have problems. must deal with this */ - } - break; + DEBUG(0,("WINS server did not respond to name release!\n")); + /* XXXX whoops. we have problems. must deal with this */ } - - case NAME_REGISTER_CHALLENGE: - { - /* name challenge: no reply. we can reply to the person that - wanted the unique name and tell them that they can have it - */ - - add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name, - n->nb_flags, GET_TTL(0), - n->reply_to_ip, False, n->reply_to_ip); - - if (!n->bcast && n->num_msgs == 0) - { - DEBUG(1,("WINS server did not respond to name registration!\n")); - /* XXXX whoops. we have problems. must deal with this */ - } break; + } + + case NAME_REGISTER_CHALLENGE: + { + /* name challenge: no reply. we can reply to the person that + wanted the unique name and tell them that they can have it + */ + + add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name, + n->nb_flags, GET_TTL(0), + n->reply_to_ip, False, n->reply_to_ip); + + if (!n->bcast && n->num_msgs == 0) + { + DEBUG(1,("WINS server did not respond to name registration!\n")); + /* XXXX whoops. we have problems. must deal with this */ } - - case NAME_REGISTER: + break; + } + + case NAME_REGISTER: + { + /* if no response received, and we are using a broadcast registration + method, it must be OK for us to register the name: nobody objected + on that subnet. if we are using a WINS server, then the WINS + server must be dead or deaf. + */ + if (n->num_msgs == 0) { - /* if no response received, and we are using a broadcast registration - method, it must be OK for us to register the name: nobody objected - on that subnet. if we are using a WINS server, then the WINS - server must be dead or deaf. - */ - if (n->num_msgs == 0) - { - if (n->bcast) + if (n->bcast) { - /* broadcast method: implicit acceptance of the name registration - by not receiving any objections. */ - - /* IMPORTANT: see response_name_reg() */ - - name_register_work(d,n->name.name,n->name.name_type, - n->nb_flags, n->ttl, n->reply_to_ip, n->bcast); + /* broadcast method: implicit acceptance of the name registration + by not receiving any objections. */ + + /* IMPORTANT: see response_name_reg() */ + + name_register_work(d,n->name.name,n->name.name_type, + n->nb_flags, n->ttl, n->reply_to_ip, n->bcast); + } + else + { + /* received no response. rfc1001.txt states that after retrying, + we should assume the WINS server is dead, and fall back to + broadcasting (see bits about M nodes: can't find any right + now) */ + + DEBUG(1,("WINS server did not respond to name registration!\n")); + /* XXXX whoops. we have problems. must deal with this */ } - else - { - /* received no response. rfc1001.txt states that after retrying, - we should assume the WINS server is dead, and fall back to - broadcasting (see bits about M nodes: can't find any right - now) */ - - DEBUG(1,("WINS server did not respond to name registration!\n")); - /* XXXX whoops. we have problems. must deal with this */ - } - } - break; } - - case NAME_QUERY_DOMAIN: - { - /* if no response received, there is no domain controller on + break; + } + + case NAME_QUERY_DOMAIN: + { + /* if no response received, there is no domain controller on this local subnet. it's ok for us to register - */ - - if (!n->bcast) - { - DEBUG(0,("NAME_QUERY_DOMAIN incorrectly used - contact samba-bugs!\n")); - /* XXXX whoops. someone's using this to unicast a packet. this state - should only be used for broadcast checks - */ - break; - } - if (n->num_msgs == 0) - { - struct work_record *work = find_workgroupstruct(d,n->name.name,False); - if (work && d) - { - become_domain_master(d,work); - } - } + */ + + if (!n->bcast) + { + DEBUG(0,("NAME_QUERY_DOMAIN incorrectly used - contact samba-bugs!\n")); + /* XXXX whoops. someone's using this to unicast a packet. this state + should only be used for broadcast checks + */ break; } - - default: + if (n->num_msgs == 0) { - /* nothing to do but delete the dead expected-response structure */ - /* this is normal. */ - break; + struct work_record *work = find_workgroupstruct(d,n->name.name,False); + if (work && d) + { + become_domain_master(d,work); + } } + break; + } + + default: + { + /* nothing to do but delete the dead expected-response structure */ + /* this is normal. */ + break; + } } } @@ -300,10 +300,9 @@ struct response_record *queue_netbios_packet(struct subnet_record *d, int fd,int quest_type,enum state_type state,char *name, int name_type,int nb_flags, time_t ttl, int server_type, char *my_name, char *my_comment, - BOOL bcast,BOOL recurse, + BOOL bcast,BOOL recurse, struct in_addr send_ip, struct in_addr reply_to_ip) { - struct in_addr wins_ip = ipgrp; struct response_record *n; uint16 id = 0xffff; @@ -311,7 +310,7 @@ struct response_record *queue_netbios_packet(struct subnet_record *d, if (ip_equal(wins_ip, send_ip)) return NULL; initiate_netbios_packet(&id, fd, quest_type, name, name_type, - nb_flags, bcast, recurse, send_ip); + nb_flags, bcast, recurse, send_ip); if (id == 0xffff) { DEBUG(4,("did not initiate netbios packet: %s\n", inet_ntoa(send_ip))); @@ -319,9 +318,9 @@ struct response_record *queue_netbios_packet(struct subnet_record *d, } if ((n = make_response_queue_record(state,id,fd, - quest_type,name,name_type,nb_flags,ttl, - server_type,my_name, my_comment, - bcast,recurse,send_ip,reply_to_ip))) + quest_type,name,name_type,nb_flags,ttl, + server_type,my_name, my_comment, + bcast,recurse,send_ip,reply_to_ip))) { add_response_record(d,n); return n; diff --git a/source/nameserv.c b/source/nameserv.c index 77c39062422..ac2dac1683c 100644 --- a/source/nameserv.c +++ b/source/nameserv.c @@ -38,7 +38,7 @@ extern int DEBUGLEVEL; extern pstring scope; extern pstring myname; extern struct in_addr ipzero; -extern struct in_addr ipgrp; +extern struct in_addr wins_ip; extern struct subnet_record *subnetlist; @@ -80,7 +80,7 @@ void remove_name_entry(struct subnet_record *d, char *name,int type) don't really own */ remove_netbios_name(d,name,type,SELF,n2->ip_flgs[0].ip); - if (ip_equal(d->bcast_ip, ipgrp)) + if (ip_equal(d->bcast_ip, wins_ip)) { if (!lp_wins_support()) { @@ -125,7 +125,7 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags) name entry to a local-subnet name database. see rfc1001.txt 15.1.1 p28 regarding the point about M-nodes. */ - if (ip_equal(d->bcast_ip, ipgrp)) + if (ip_equal(d->bcast_ip, wins_ip)) { if (lp_wins_support()) { @@ -194,10 +194,16 @@ void add_domain_names(time_t t) if (lp_domain_master() && work && work->dom_state == DOMAIN_NONE) { + + DEBUG(0,("add_domain_names:Checking for domain master on workgroup %s\n", lp_workgroup())); + make_nmb_name(&n,lp_workgroup(),0x1b,scope); if (!find_name(d->namelist, &n, FIND_SELF)) { - if (ip_equal(d->bcast_ip,ipgrp)) + DEBUG(0,("add_domain_names: attempting to become domain master browser on workgroup %s, bcast %s\n", + lp_workgroup(), inet_ntoa(d->bcast_ip))); + + if (ip_equal(d->bcast_ip,wins_ip)) { if (lp_wins_support()) { @@ -221,6 +227,8 @@ void add_domain_names(time_t t) NetBIOS name 0x1b. */ + DEBUG(0,("add_domain_names:querying for domain master on workgroup %s\n", lp_workgroup())); + queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_DOMAIN, lp_workgroup(), 0x1b, 0, 0,0,NULL,NULL, @@ -246,7 +254,7 @@ void add_my_names(void) for (d = subnetlist; d; d = d->next) { - BOOL wins = lp_wins_support() && ip_equal(d->bcast_ip,ipgrp); + BOOL wins = lp_wins_support() && ip_equal(d->bcast_ip,wins_ip); struct work_record *work = find_workgroupstruct(d, lp_workgroup(), False); add_my_name_entry(d, myname,0x20,nb_type|NB_ACTIVE); @@ -339,7 +347,7 @@ void refresh_my_names(time_t t) void query_refresh_names(time_t t) { struct name_record *n; - struct subnet_record *d = find_subnet(ipgrp); + struct subnet_record *d = find_subnet(wins_ip); static time_t lasttime = 0; diff --git a/source/nameservreply.c b/source/nameservreply.c index 544cbc62b44..001695b3fbd 100644 --- a/source/nameservreply.c +++ b/source/nameservreply.c @@ -36,7 +36,7 @@ extern int ClientNMB; extern int DEBUGLEVEL; -extern struct in_addr ipgrp; +extern struct in_addr wins_ip; /**************************************************************************** @@ -120,35 +120,35 @@ void reply_name_release(struct packet_struct *p) namestr(&nmb->question.question_name))); if (!(d = find_req_subnet(p->ip, bcast))) - { - DEBUG(3,("response packet: bcast %s not known\n", - inet_ntoa(p->ip))); - return; - } + { + DEBUG(3,("response packet: bcast %s not known\n", + inet_ntoa(p->ip))); + return; + } if (bcast) - search |= FIND_LOCAL; + search |= FIND_LOCAL; else - search |= FIND_WINS; + search |= FIND_WINS; n = find_name_search(&d, &nmb->question.question_name, - search, ip); + search, ip); /* XXXX under what conditions should we reject the removal?? */ if (n && n->ip_flgs[0].nb_flags == nb_flags) - { + { success = True; remove_name(d,n); n = NULL; - } + } if (bcast) return; /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */ send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REL, - success, False, - &nmb->question.question_name, nb_flags, 0, ip); + success, False, + &nmb->question.question_name, nb_flags, 0, ip); } @@ -190,7 +190,7 @@ void reply_name_reg(struct packet_struct *p) { /* apparently we should return 255.255.255.255 for group queries (email from MS) */ - ip = ipgrp; + ip = wins_ip; } if (!(d = find_req_subnet(p->ip, bcast))) @@ -393,8 +393,8 @@ void reply_name_status(struct packet_struct *p) if (!strequal(n->name.name,"*") && !strequal(n->name.name,"__SAMBA__") && - (name_type < 0x1b || name_type > 0x20 || - ques_type < 0x1b || ques_type > 0x20 || + (name_type < 0x1b || name_type >= 0x20 || + ques_type < 0x1b || ques_type >= 0x20 || strequal(qname, n->name.name))) { /* start with first bit of putting info in buffer: the name */ @@ -433,7 +433,7 @@ void reply_name_status(struct packet_struct *p) /* end of this name list: add wins names too? */ struct subnet_record *w_d; - if (!(w_d = find_subnet(ipgrp))) break; + if (!(w_d = find_subnet(wins_ip))) break; if (w_d != d) { @@ -520,7 +520,7 @@ void reply_name_query(struct packet_struct *p) } else { - if (!(d = find_subnet(ipgrp))) + if (!(d = find_subnet(wins_ip))) { DEBUG(3,("name query: wins search %s not known\n", inet_ntoa(p->ip))); diff --git a/source/nameservresp.c b/source/nameservresp.c index ce626976444..30541034b81 100644 --- a/source/nameservresp.c +++ b/source/nameservresp.c @@ -192,10 +192,13 @@ static void response_server_check(struct nmb_name *ans_name, enum state_type cmd = (n->state == NAME_QUERY_DOM_SRV_CHK) ? NAME_STATUS_DOM_SRV_CHK : NAME_STATUS_SRV_CHK; - /* initiate a name status check on the server that replied */ + /* initiate a name status check on the server that replied + in addition, the workgroup being checked has been stored + in the response_record->my_name (see announce_master) we + also propagate this into the same field. */ queue_netbios_packet(d,ClientNMB,NMB_STATUS, cmd, ans_name->name, ans_name->name_type, - 0,0,0,NULL,NULL, + 0,0,0,n->my_name,NULL, False,False,n->send_ip,n->reply_to_ip); } @@ -243,10 +246,12 @@ static BOOL interpret_node_status(struct subnet_record *d, if (NAME_MFLAG (nb_flags)) { strcat(flags,"M "); } if (NAME_HFLAG (nb_flags)) { strcat(flags,"H "); } if (NAME_DEREG (nb_flags)) { strcat(flags," "); } - if (NAME_CONFLICT (nb_flags)) { strcat(flags," "); add=True;} + if (NAME_CONFLICT (nb_flags)) { strcat(flags," "); } if (NAME_ACTIVE (nb_flags)) { strcat(flags," "); add=True; } if (NAME_PERMANENT(nb_flags)) { strcat(flags," "); add=True;} - + +/* I don't think we should be messing with our namelist here... JRA */ +#if 0 /* might as well update our namelist while we're at it */ if (add) { @@ -262,9 +267,10 @@ static BOOL interpret_node_status(struct subnet_record *d, } add_netbios_entry(d,qname,type,nb_flags,2*60*60,src,nameip,True,bcast); } +#endif /* JRA */ /* we want the server name */ - if (serv_name && !*serv_name && !group && t == 0) + if (serv_name && !*serv_name && !group && type == 0x20) { StrnCpy(serv_name,qname,15); serv_name[15] = 0; @@ -275,8 +281,8 @@ static BOOL interpret_node_status(struct subnet_record *d, { /* take a guess at some of the name types we're going to ask for. evaluate whether they are group names or no... */ - if (((t == 0x1b || t == 0x1d ) && !group) || - ((t == 0x20 || t == 0x1c || t == 0x1e) && group)) + if (((t == 0x1b || t == 0x1d || t == 0x20 ) && !group) || + ((t == 0x1c || t == 0x1e ) && group)) { found = True; make_nmb_name(name,qname,type,scope); @@ -306,17 +312,20 @@ static void response_name_status_check(struct in_addr ip, fstring serv_name; if (interpret_node_status(d,nmb->answers->rdata, - &name,name.name_type,serv_name,ip,bcast)) + &name,0x20,serv_name,ip,bcast)) { if (*serv_name) { + /* response_record->my_name contains the + workgroup name to sync with. See + response_server_check() */ sync_server(n->state,serv_name, - name.name,name.name_type, n->send_ip); + n->my_name,name.name_type, n->send_ip); } } else { - DEBUG(1,("No 0x1d name type in interpret_node_status()\n")); + DEBUG(1,("No 0x20 name type in interpret_node_status()\n")); } } @@ -409,69 +418,74 @@ static void response_name_query_sync(struct nmb_packet *nmb, struct nmb_name *ans_name, BOOL bcast, struct response_record *n, struct subnet_record *d) { - DEBUG(4, ("Name query at %s ip %s - ", - namestr(&n->name), inet_ntoa(n->send_ip))); - - if (!name_equal(&n->name, ans_name)) - { - /* someone gave us the wrong name as a reply. oops. */ - DEBUG(4,("unexpected name received: %s\n", namestr(ans_name))); - return; - } + DEBUG(4, ("Name query at %s ip %s - ", + namestr(&n->name), inet_ntoa(n->send_ip))); - if (nmb->header.rcode == 0 && nmb->answers->rdata) + if (!name_equal(&n->name, ans_name)) { - int nb_flags = nmb->answers->rdata[0]; - struct in_addr found_ip; - - putip((char*)&found_ip,&nmb->answers->rdata[2]); - - if (!ip_equal(n->send_ip, found_ip)) - { - /* someone gave us the wrong ip as a reply. oops. */ - DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip))); - DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip))); - return; - } - - DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip))); + /* someone gave us the wrong name as a reply. oops. */ + DEBUG(4,("unexpected name received: %s\n", namestr(ans_name))); + return; + } - if (n->state == NAME_QUERY_SYNC_LOCAL || - n->state == NAME_QUERY_SYNC_REMOTE) - { - struct work_record *work = NULL; - if ((work = find_workgroupstruct(d, ans_name->name, False))) - { - BOOL local_list_only = n->state == NAME_QUERY_SYNC_LOCAL; + if (nmb->header.rcode == 0 && nmb->answers->rdata) + { + int nb_flags = nmb->answers->rdata[0]; + struct in_addr found_ip; + + putip((char*)&found_ip,&nmb->answers->rdata[2]); + + if (!ip_equal(n->send_ip, found_ip)) + { + /* someone gave us the wrong ip as a reply. oops. */ + DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip))); + DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip))); + return; + } - /* the server is there: sync quick before it (possibly) dies! */ - sync_browse_lists(d, work, ans_name->name, ans_name->name_type, - found_ip, local_list_only); - } - } - else - { - /* update our netbios name list (re-register it if necessary) */ - add_netbios_entry(d, ans_name->name, ans_name->name_type, - nb_flags,GET_TTL(0),REGISTER, - found_ip,False,!bcast); - } + DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip))); + + if (n->state == NAME_QUERY_SYNC_LOCAL || + n->state == NAME_QUERY_SYNC_REMOTE) + { + struct work_record *work = NULL; + /* We cheat here as we know that the workgroup name has + been placed in the my_comment field of the + response_record struct by the code in + start_sync_browse_entry(). + */ + if ((work = find_workgroupstruct(d, n->my_comment, False))) + { + BOOL local_list_only = n->state == NAME_QUERY_SYNC_LOCAL; + + /* the server is there: sync quick before it (possibly) dies! */ + sync_browse_lists(d, work, ans_name->name, ans_name->name_type, + found_ip, local_list_only); + } } - else + else { - DEBUG(4, (" NEGATIVE RESPONSE!\n")); - - if (n->state == NAME_QUERY_CONFIRM) - { - /* XXXX remove_netbios_entry()? */ - /* lots of things we ought to do, here. if we get here, - then we're in a mess: our name database doesn't match - reality. sort it out + /* update our netbios name list (re-register it if necessary) */ + add_netbios_entry(d, ans_name->name, ans_name->name_type, + nb_flags,GET_TTL(0),REGISTER, + found_ip,False,!bcast); + } + } + else + { + DEBUG(4, (" NEGATIVE RESPONSE!\n")); + + if (n->state == NAME_QUERY_CONFIRM) + { + /* XXXX remove_netbios_entry()? */ + /* lots of things we ought to do, here. if we get here, + then we're in a mess: our name database doesn't match + reality. sort it out */ - remove_netbios_name(d,n->name.name, n->name.name_type, - REGISTER,n->send_ip); - } + remove_netbios_name(d,n->name.name, n->name.name_type, + REGISTER,n->send_ip); } + } } @@ -481,13 +495,13 @@ static void response_name_query_sync(struct nmb_packet *nmb, static void debug_rr_type(int rr_type) { switch (rr_type) - { - case NMB_STATUS: DEBUG(3,("Name status ")); break; - case NMB_QUERY : DEBUG(3,("Name query ")); break; - case NMB_REG : DEBUG(3,("Name registration ")); break; - case NMB_REL : DEBUG(3,("Name release ")); break; - default : DEBUG(1,("wrong response packet type received")); break; - } + { + case NMB_STATUS: DEBUG(3,("Name status ")); break; + case NMB_QUERY : DEBUG(3,("Name query ")); break; + case NMB_REG : DEBUG(3,("Name registration ")); break; + case NMB_REL : DEBUG(3,("Name release ")); break; + default : DEBUG(1,("wrong response packet type received")); break; + } } /**************************************************************************** @@ -497,8 +511,8 @@ void debug_state_type(int state) { /* report the state type to help debugging */ switch (state) - { - case NAME_QUERY_DOM_SRV_CHK : DEBUG(4,("MASTER_SVR_CHECK\n")); break; + { + case NAME_QUERY_DOM_SRV_CHK : DEBUG(4,("NAME_QUERY_DOM_SRV_CHK\n")); break; case NAME_QUERY_SRV_CHK : DEBUG(4,("NAME_QUERY_SRV_CHK\n")); break; case NAME_QUERY_FIND_MST : DEBUG(4,("NAME_QUERY_FIND_MST\n")); break; case NAME_QUERY_MST_CHK : DEBUG(4,("NAME_QUERY_MST_CHK\n")); break; @@ -506,17 +520,17 @@ void debug_state_type(int state) case NAME_QUERY_SYNC_LOCAL : DEBUG(4,("NAME_QUERY_SYNC_LOCAL\n")); break; case NAME_QUERY_SYNC_REMOTE : DEBUG(4,("NAME_QUERY_SYNC_REMOTE\n")); break; case NAME_QUERY_ANNOUNCE_HOST: DEBUG(4,("NAME_QUERY_ANNCE_HOST\n"));break; - + case NAME_REGISTER : DEBUG(4,("NAME_REGISTER\n")); break; case NAME_REGISTER_CHALLENGE : DEBUG(4,("NAME_REGISTER_CHALLENGE\n"));break; - + case NAME_RELEASE : DEBUG(4,("NAME_RELEASE\n")); break; - - case NAME_STATUS_DOM_SRV_CHK : DEBUG(4,("NAME_STAT_MST_CHK\n")); break; + + case NAME_STATUS_DOM_SRV_CHK : DEBUG(4,("NAME_STATUS_DOM_SRV_CHK\n")); break; case NAME_STATUS_SRV_CHK : DEBUG(4,("NAME_STATUS_SRV_CHK\n")); break; - + default: break; - } + } } /**************************************************************************** @@ -528,87 +542,95 @@ static BOOL response_problem_check(struct response_record *n, struct nmb_packet *nmb, char *ans_name) { switch (nmb->answers->rr_type) - { - case NMB_REL: { + case NMB_REL: + { if (n->num_msgs > 1) - { + { DEBUG(1,("more than one release name response received!\n")); return True; - } + } break; - } + } case NMB_REG: - { + { if (n->num_msgs > 1) - { + { DEBUG(1,("more than one register name response received!\n")); return True; - } + } break; - } - + } + case NMB_QUERY: - { - if (n->num_msgs > 1) - { - if (nmb->header.rcode == 0 && nmb->answers->rdata) + { + if (n->num_msgs > 1) + { + if (nmb->header.rcode == 0 && nmb->answers->rdata) + { + int nb_flags = nmb->answers->rdata[0]; + + if ((!NAME_GROUP(nb_flags))) { - int nb_flags = nmb->answers->rdata[0]; - - if ((!NAME_GROUP(nb_flags))) + /* oh dear. more than one person responded to a + unique name. + there is either a network problem, a + configuration problem + or a server is mis-behaving */ + + /* XXXX mark the name as in conflict, and then let the + person who just responded know that they + must also mark it + as in conflict, and therefore must NOT use it. + see rfc1001.txt 15.1.3.5 */ + + /* this may cause problems for some + early versions of nmbd */ + + switch (n->state) + { + case NAME_QUERY_FIND_MST: { - /* oh dear. more than one person responded to a unique name. - there is either a network problem, a configuration problem - or a server is mis-behaving */ - - /* XXXX mark the name as in conflict, and then let the - person who just responded know that they must also mark it - as in conflict, and therefore must NOT use it. - see rfc1001.txt 15.1.3.5 */ - - /* this may cause problems for some early versions of nmbd */ - - switch (n->state) - { - case NAME_QUERY_FIND_MST: - { - /* query for ^1^2__MSBROWSE__^2^1 expect lots of responses */ - return False; - } - case NAME_QUERY_ANNOUNCE_HOST: - case NAME_QUERY_DOM_SRV_CHK: - case NAME_QUERY_SRV_CHK: - case NAME_QUERY_MST_CHK: - { - if (!strequal(ans_name,n->name.name)) - { - /* one subnet, one master browser per workgroup */ - /* XXXX force an election? */ - - DEBUG(3,("more than one master browser replied!\n")); - return True; - } - break; - } - default: break; - } - DEBUG(3,("Unique Name conflict detected!\n")); - return True; + /* query for ^1^2__MSBROWSE__^2^1 expect + lots of responses */ + return False; } + case NAME_QUERY_ANNOUNCE_HOST: + case NAME_QUERY_DOM_SRV_CHK: + case NAME_QUERY_SRV_CHK: + case NAME_QUERY_MST_CHK: + { + if (!strequal(ans_name,n->name.name)) + { + /* one subnet, one master browser + per workgroup */ + /* XXXX force an election? */ + + DEBUG(3,("more than one master browser replied!\n")); + return True; + } + break; + } + default: break; + } + DEBUG(3,("Unique Name conflict detected!\n")); + return True; } - else - { - /* we have received a negative reply, having already received - at least one response (pos/neg). something's really wrong! */ - - DEBUG(3,("wierd name query problem detected!\n")); - return True; - } - } + } + else + { + /* we have received a negative reply, + having already received + at least one response (pos/neg). + something's really wrong! */ + + DEBUG(3,("wierd name query problem detected!\n")); + return True; + } + } + } } - } return False; } @@ -685,73 +707,73 @@ static BOOL response_compatible(struct response_record *n, process the response packet received ****************************************************************************/ static void response_process(struct subnet_record *d, struct packet_struct *p, - struct response_record *n, struct nmb_packet *nmb, - BOOL bcast, struct nmb_name *ans_name) + struct response_record *n, struct nmb_packet *nmb, + BOOL bcast, struct nmb_name *ans_name) { switch (n->state) - { - case NAME_RELEASE: { + case NAME_RELEASE: + { response_name_release(ans_name, d, p); break; - } + } case NAME_REGISTER: - { + { response_name_reg(ans_name, d, p); break; - } + } case NAME_REGISTER_CHALLENGE: - { + { response_name_query_register(nmb, ans_name, n, d); break; - } + } case NAME_QUERY_DOM_SRV_CHK: case NAME_QUERY_SRV_CHK: case NAME_QUERY_FIND_MST: - { - response_server_check(ans_name, n, d); - break; - } - + { + response_server_check(ans_name, n, d); + break; + } + case NAME_STATUS_DOM_SRV_CHK: case NAME_STATUS_SRV_CHK: - { - response_name_status_check(p->ip, nmb, bcast, n, d); - break; - } - + { + response_name_status_check(p->ip, nmb, bcast, n, d); + break; + } + case NAME_QUERY_ANNOUNCE_HOST: - { - response_announce_host(ans_name, nmb, n, d); - break; - } + { + response_announce_host(ans_name, nmb, n, d); + break; + } case NAME_QUERY_CONFIRM: case NAME_QUERY_SYNC_LOCAL: case NAME_QUERY_SYNC_REMOTE: - { - response_name_query_sync(nmb, ans_name, bcast, n, d); - break; - } + { + response_name_query_sync(nmb, ans_name, bcast, n, d); + break; + } case NAME_QUERY_MST_CHK: - { - /* no action required here. it's when NO responses are received - that we need to do something. see expire_name_query_entries() */ + { + /* no action required here. it's when NO responses are received + that we need to do something. see expire_name_query_entries() */ - DEBUG(4, ("Master browser exists for %s at %s (just checking!)\n", - namestr(&n->name), inet_ntoa(n->send_ip))); - break; - } - + DEBUG(4, ("Master browser exists for %s at %s (just checking!)\n", + namestr(&n->name), inet_ntoa(n->send_ip))); + break; + } + default: - { - DEBUG(1,("unknown state type received in response_netbios_packet\n")); - break; + { + DEBUG(1,("unknown state type received in response_netbios_packet\n")); + break; + } } - } } @@ -772,43 +794,41 @@ void response_netbios_packet(struct packet_struct *p) } if (!d) - { - DEBUG(2,("response packet: subnet %s not known\n", inet_ntoa(p->ip))); - return; - } + { + DEBUG(2,("response packet: subnet %s not known\n", inet_ntoa(p->ip))); + return; + } /* args wrong way round: spotted by ccm@shentel.net */ if (!same_net(d->bcast_ip, p->ip, d->mask_ip)) /* copes with WINS 'subnet' */ - { - DEBUG(2,("response from %s. ", inet_ntoa(p->ip))); - DEBUG(2,("expected on subnet %s. hmm.\n", inet_ntoa(d->bcast_ip))); - } - + { + DEBUG(2,("response from %s. ", inet_ntoa(p->ip))); + DEBUG(2,("expected on subnet %s. hmm.\n", inet_ntoa(d->bcast_ip))); + } + if (nmb->answers == NULL) - { + { /* hm. the packet received was a response, but with no answer. wierd! */ DEBUG(2,("NMB packet response from %s (bcast=%s) - UNKNOWN\n", inet_ntoa(p->ip), BOOLSTR(bcast))); return; - } + } ans_name = &nmb->answers->rr_name; DEBUG(3,("response for %s from %s (bcast=%s)\n", namestr(ans_name), inet_ntoa(p->ip), BOOLSTR(bcast))); debug_rr_type(nmb->answers->rr_type); - + n->num_msgs++; /* count number of responses received */ n->repeat_count = 0; /* don't resend: see expire_netbios_packets() */ - + debug_state_type(n->state); - + /* problem checking: multiple responses etc */ if (response_problem_check(n, nmb, ans_name->name)) return; - + /* now deal with the current state */ response_process(d, p, n, nmb, bcast, ans_name); } - - diff --git a/source/namework.c b/source/namework.c index 20c1050597e..1d3ff9e0ee3 100644 --- a/source/namework.c +++ b/source/namework.c @@ -173,10 +173,10 @@ BOOL same_context(struct dgram_packet *dgram) resources. We just have to pass it to smbd (via browser.dat) and let the client choose using bit masks. ******************************************************************/ -static void process_announce(struct packet_struct *p,uint16 command,char *buf) +static void process_localnet_announce(struct packet_struct *p,uint16 command,char *buf) { struct dgram_packet *dgram = &p->packet.dgram; - struct subnet_record *d = find_subnet(p->ip); + struct subnet_record *d = find_subnet(p->ip); /* Explicitly exclude WINS - local nets only */ int update_count = CVAL(buf,0); int ttl = IVAL(buf,1)/1000; @@ -278,25 +278,33 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf) static void process_master_announce(struct packet_struct *p,char *buf) { struct dgram_packet *dgram = &p->packet.dgram; - struct subnet_record *d = find_subnet(p->ip); + struct subnet_record *d = find_subnet_all(p->ip); /* Explicitly include WINS */ char *name = buf; struct work_record *work; name[15] = 0; - DEBUG(3,("Master Announce from %s (%s)\n",name,inet_ntoa(p->ip))); + DEBUG(3,("process_master_announce: Master Announce from %s (%s)\n",name,inet_ntoa(p->ip))); if (same_context(dgram)) return; - if (!d) return; + if (!d) + { + DEBUG(3,("process_master_announce: Cannot find interface\n")); + return; + } - if (!lp_domain_master()) return; + if (!lp_domain_master()) + { + DEBUG(3,("process_master_announce: Not configured as domain master - ignoring master announce.\n")); + return; + } for (work = d->workgrouplist; work; work = work->next) { - if (AM_MASTER(work)) + if (AM_MASTER(work) || AM_DOMMST(work) || AM_ANY_MASTER(work)) { /* merge browse lists with them */ - add_browser_entry(name,0x1b, work->work_group,30,p->ip,True); + add_browser_entry(name,0x1d, work->work_group,30,p->ip,True); } } } @@ -612,13 +620,13 @@ static void process_announce_request(struct packet_struct *p,char *buf) struct dgram_packet *dgram = &p->packet.dgram; struct work_record *work; struct in_addr ip = dgram->header.source_ip; - struct subnet_record *d = find_subnet(ip); + struct subnet_record *d = find_subnet(ip); /* Explicitly NO WINS */ int token = CVAL(buf,0); char *name = buf+1; name[15] = 0; - DEBUG(3,("Announce request from %s to %s token=0x%X\n", + DEBUG(3,("process_announce_request: Announce request from %s to %s token=0x%X\n", name,namestr(&dgram->dest_name), token)); if (strequal(dgram->source_name.name,myname)) return; @@ -630,8 +638,13 @@ static void process_announce_request(struct packet_struct *p,char *buf) if (strequal(dgram->dest_name, lp_workgroup()) return; ??? */ - if (!d) return; - + if (!d) + { + DEBUG(3,("process_announce_request: No local interface to announce to %s\n", + name)); + return; + } + for (work = d->workgrouplist; work; work = work->next) { /* XXXX BUG: the destination name type should also be checked, @@ -660,7 +673,7 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len) case ANN_LocalMasterAnnouncement: { debug_browse_data(buf, len); - process_announce(p,command,buf+1); + process_localnet_announce(p,command,buf+1); break; } diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c index e45facdc2e3..eefb4162f79 100644 --- a/source/nmbd/nmbd.c +++ b/source/nmbd/nmbd.c @@ -272,7 +272,7 @@ static void load_hosts_file(char *fname) } ipaddr = *interpret_addr2(ip); - d = find_subnet(ipaddr); + d = find_subnet_all(ipaddr); if (d) { add_netbios_entry(d,name,0x00,NB_ACTIVE,0,source,ipaddr,True,True); add_netbios_entry(d,name,0x20,NB_ACTIVE,0,source,ipaddr,True,True); diff --git a/source/nmbsync.c b/source/nmbsync.c index 2efb364bcae..fa60b3ac35a 100644 --- a/source/nmbsync.c +++ b/source/nmbsync.c @@ -140,7 +140,7 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work, { uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0; - if (!d || !work || !AM_MASTER(work)) return; + if (!d || !work || !AM_ANY_MASTER(work)) return; pid = getpid(); uid = getuid(); diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 672f1fe5483..64dd01eeafa 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -600,7 +600,7 @@ static void init_globals(void) Globals.bDomainMaster = False; Globals.bDomainLogons = False; Globals.bBrowseList = True; - Globals.bWINSsupport = True; + Globals.bWINSsupport = False; Globals.bWINSproxy = False; Globals.ReadSize = 16*1024; -- 2.11.4.GIT