diff options
-rw-r--r-- | docs/manpages/smb.conf.5 | 35 | ||||
-rw-r--r-- | source3/client/client.c | 7 | ||||
-rw-r--r-- | source3/include/nameserv.h | 6 | ||||
-rw-r--r-- | source3/lib/util.c | 9 | ||||
-rw-r--r-- | source3/libsmb/nmblib.c | 2 | ||||
-rw-r--r-- | source3/loadparm.h | 2 | ||||
-rw-r--r-- | source3/nameannounce.c | 452 | ||||
-rw-r--r-- | source3/namedb.c | 910 | ||||
-rw-r--r-- | source3/nameelect.c | 286 | ||||
-rw-r--r-- | source3/nameresp.c | 60 | ||||
-rw-r--r-- | source3/nameserv.c | 1246 | ||||
-rw-r--r-- | source3/namework.c | 1116 | ||||
-rw-r--r-- | source3/nmbd/nmbd.c | 22 | ||||
-rw-r--r-- | source3/nmbsync.c | 132 | ||||
-rw-r--r-- | source3/param/loadparm.c | 8 |
15 files changed, 2166 insertions, 2127 deletions
diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5 index f29e7b6b02..7149be6a47 100644 --- a/docs/manpages/smb.conf.5 +++ b/docs/manpages/smb.conf.5 @@ -1962,14 +1962,6 @@ merits of each are discussed in the README file. .B Example: protocol = LANMAN1 -.SS proxy name resolution (G) - -This is a boolean that controls if nmbd will respond to broadcast name -queries on behalf of other hosts. You may need to set this to no for -some older clients. - -.B Default: - proxy name resolution = yes .SS public (S) A synonym for this parameter is 'guest ok'. @@ -2548,6 +2540,33 @@ only to areas that are outside the directory tree being exported. .B Example: wide links = no +.SS wins proxy (G) + +This is a boolean that controls if nmbd will respond to broadcast name +queries on behalf of other hosts. You may need to set this to no for +some older clients. + +.B Default: + wins proxy = no +.SS wins support (G) + +This boolean controls if Samba will act as a WINS server. You should +normally set this to true unless you already have another WINS server +on the network. + +.B Default: + wins support = yes +.SS wins server (G) + +This specifies the DNS name of the WINS server that Samba should +register with. If you have a WINS server on your network then you +should set this to the WINS servers name. + +This option only takes effect if Samba is not acting as a WINS server +itself. + +.B Default: + wins server = .SS workgroup (G) This controls what workgroup your server will appear to be in when diff --git a/source3/client/client.c b/source3/client/client.c index 3cefbc2284..5e464ea111 100644 --- a/source3/client/client.c +++ b/source3/client/client.c @@ -3599,6 +3599,7 @@ static BOOL list_servers() pstring param; int uLevel = 1; int count = 0; + BOOL ok = False; /* now send a SMBtrans command with api ServerEnum? */ p = param; @@ -3645,7 +3646,8 @@ static BOOL list_servers() printf("\t%-16.16s %s\n", sname, comment_offset?rdata+comment_offset-converter:""); - + + ok=True; p2 += 26; } } @@ -3683,6 +3685,7 @@ static BOOL list_servers() sname, comment_offset?rdata+comment_offset-converter:""); + ok=True; p2 += 26; } } @@ -3691,7 +3694,7 @@ static BOOL list_servers() if (rparam) free(rparam); if (rdata) free(rdata); - return(count>0); + return(ok); } diff --git a/source3/include/nameserv.h b/source3/include/nameserv.h index 81079fabe0..51f5ec8479 100644 --- a/source3/include/nameserv.h +++ b/source3/include/nameserv.h @@ -20,6 +20,10 @@ */ +/* NTAS uses 2, NT uses 1, WfWg uses 0 */ +#define MAINTAIN_LIST 2 +#define ELECTION_VERSION 2 + #define MAX_DGRAM_SIZE (80*18+64) #define MIN_DGRAM_SIZE 12 @@ -39,6 +43,8 @@ #define NB__FLAG 0x60 #define NB_FLGMSK 0x60 +#define REFRESH_TIME (15*60) + #define NAME_PERMANENT(p) ((p) & NB_PERM) #define NAME_ACTIVE(p) ((p) & NB_ACTIVE) #define NAME_CONFLICT(p) ((p) & NB_CONFL) diff --git a/source3/lib/util.c b/source3/lib/util.c index 57f2e9240c..427d15cdcf 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -1820,11 +1820,10 @@ int read_udp_socket(int fd,char *buf,int len) bzero((char *)&sock,socklen); bzero((char *)&lastip,sizeof(lastip)); ret = recvfrom(fd,buf,len,0,&sock,&socklen); - if (ret <= 0) - { - DEBUG(2,("read socket failed. ERRNO=%d\n",errno)); - return(0); - } + if (ret <= 0) { + DEBUG(2,("read socket failed. ERRNO=%d\n",errno)); + return(0); + } lastip = *(struct in_addr *) &sock.sa_data[2]; lastport = ntohs(((struct sockaddr_in *)&sock)->sin_port); diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c index d8d6eb0ee4..87fe5fee78 100644 --- a/source3/libsmb/nmblib.c +++ b/source3/libsmb/nmblib.c @@ -472,7 +472,7 @@ struct packet_struct *read_packet(int fd,enum packet_type packet_type) length = read_udp_socket(fd,buf,sizeof(buf)); if (length < MIN_DGRAM_SIZE) return(NULL); - + packet = (struct packet_struct *)malloc(sizeof(*packet)); if (!packet) return(NULL); diff --git a/source3/loadparm.h b/source3/loadparm.h index 5600d66922..92c8274767 100644 --- a/source3/loadparm.h +++ b/source3/loadparm.h @@ -68,6 +68,7 @@ extern int lp_maxxmit(void); extern int lp_maxmux(void); extern int lp_mangledstack(void); extern BOOL lp_wins_support(void); +extern BOOL lp_wins_proxy(void); extern BOOL lp_preferred_master(void); extern BOOL lp_domain_master(void); extern BOOL lp_domain_logons(void); @@ -82,7 +83,6 @@ extern BOOL lp_strip_dot(void); extern BOOL lp_encrypted_passwords(void); extern BOOL lp_syslog_only(void); extern BOOL lp_browse_list(void); -extern BOOL lp_proxy_name_resolution(void); extern int lp_numservices(void); extern int lp_keepalive(void); extern int lp_passwordlevel(void); diff --git a/source3/nameannounce.c b/source3/nameannounce.c index f0de4d0a27..083512990b 100644 --- a/source3/nameannounce.c +++ b/source3/nameannounce.c @@ -98,23 +98,23 @@ void announce_request(struct work_record *work, struct in_addr ip) void do_announce_request(char *info, char *to_name, int announce_type, int from, int to, struct in_addr dest_ip) { - pstring outbuf; - char *p; - - bzero(outbuf,sizeof(outbuf)); - p = outbuf; - CVAL(p,0) = announce_type; /* announce request */ - p++; - - DEBUG(2,("Sending announce type %d: info %s to %s - server %s(%x)\n", - announce_type, info, inet_ntoa(dest_ip),to_name,to)); - - StrnCpy(p,info,16); - strupper(p); - p = skip_string(p,1); - - send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), - myname,to_name,from,to,dest_ip,myip); + pstring outbuf; + char *p; + + bzero(outbuf,sizeof(outbuf)); + p = outbuf; + CVAL(p,0) = announce_type; /* announce request */ + p++; + + DEBUG(2,("Sending announce type %d: info %s to %s - server %s(%x)\n", + announce_type, info, inet_ntoa(dest_ip),to_name,to)); + + StrnCpy(p,info,16); + strupper(p); + p = skip_string(p,1); + + send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), + myname,to_name,from,to,dest_ip,myip); } /**************************************************************************** @@ -192,135 +192,133 @@ void announce_backup(void) **************************************************************************/ void announce_host(void) { - time_t t = time(NULL); - pstring outbuf; - char *p; - char *namep; - char *stypep; - char *commentp; - pstring comment; - char *my_name; - struct domain_record *d; - - StrnCpy(comment, *ServerComment ? ServerComment : "NoComment", 43); + time_t t = time(NULL); + pstring outbuf; + char *p; + char *namep; + char *stypep; + char *commentp; + pstring comment; + char *my_name; + struct domain_record *d; - my_name = *myname ? myname : "NoName"; + StrnCpy(comment, *ServerComment ? ServerComment : "NoComment", 43); - for (d = domainlist; d; d = d->next) - { - struct work_record *work; + my_name = *myname ? myname : "NoName"; - if (!ip_equal(bcast_ip,d->bcast_ip)) - { - continue; - } + for (d = domainlist; d; d = d->next) + { + struct work_record *work; + + if (!ip_equal(bcast_ip,d->bcast_ip)) + continue; - for (work = d->workgrouplist; work; work = work->next) + for (work = d->workgrouplist; work; work = work->next) + { + uint32 stype = work->ServerType; + struct server_record *s; + BOOL announce = False; + + 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,3*60); + work->lastannounce_time = t - (work->announce_interval+1); + } + + /* announce every minute at first then progress to every 12 mins */ + if (work->lastannounce_time && + (t - work->lastannounce_time) < work->announce_interval) + continue; + + if (work->announce_interval < 12*60) + work->announce_interval += 60; + + work->lastannounce_time = t; + + DEBUG(2,("Sending announcement to subnet %s for workgroup %s\n", + inet_ntoa(d->bcast_ip),work->work_group)); + + if (!ip_equal(bcast_ip,d->bcast_ip)) { + stype &= ~(SV_TYPE_POTENTIAL_BROWSER | SV_TYPE_MASTER_BROWSER | + SV_TYPE_DOMAIN_MASTER | SV_TYPE_BACKUP_BROWSER | + SV_TYPE_DOMAIN_CTRL | SV_TYPE_DOMAIN_MEMBER); + } + + for (s = work->serverlist; s; s = s->next) { + if (strequal(myname, s->serv.name)) { + announce = True; + break; + } + } + + if (announce) + { + bzero(outbuf,sizeof(outbuf)); + p = outbuf+1; + + CVAL(p,0) = updatecount; + SIVAL(p,1,work->announce_interval*1000); /* ms - despite the spec */ + namep = p+5; + StrnCpy(namep,my_name,16); + strupper(namep); + CVAL(p,21) = 2; /* major version */ + CVAL(p,22) = 2; /* minor version */ + stypep = p+23; + SIVAL(p,23,stype); + SSVAL(p,27,0xaa55); /* browse signature */ + SSVAL(p,29,1); /* browse version */ + commentp = p+31; + strcpy(commentp,comment); + p = p+31; + p = skip_string(p,1); + + if (ip_equal(bcast_ip,d->bcast_ip)) { - uint32 stype = work->ServerType; - struct server_record *s; - BOOL announce = False; - - 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,3*60); - work->lastannounce_time = t - (work->announce_interval+1); - } - - /* announce every minute at first then progress to every 12 mins */ - if (work->lastannounce_time && - (t - work->lastannounce_time) < work->announce_interval) - { - continue; - } - - if (work->announce_interval < 12*60) work->announce_interval += 60; - - work->lastannounce_time = t; - - DEBUG(2,("Sending announcement to subnet %s for workgroup %s\n", - inet_ntoa(d->bcast_ip),work->work_group)); - - if (!ip_equal(bcast_ip,d->bcast_ip)) - { - stype &= ~(SV_TYPE_POTENTIAL_BROWSER | SV_TYPE_MASTER_BROWSER | - SV_TYPE_DOMAIN_MASTER | SV_TYPE_BACKUP_BROWSER | - SV_TYPE_DOMAIN_CTRL | SV_TYPE_DOMAIN_MEMBER); - } - - for (s = work->serverlist; s; s = s->next) - { - if (strequal(myname, s->serv.name)) { announce = True; break; } - } - - if (announce) - { - bzero(outbuf,sizeof(outbuf)); - p = outbuf+1; - - CVAL(p,0) = updatecount; - SIVAL(p,1,work->announce_interval*1000); /* ms - despite the spec */ - namep = p+5; - StrnCpy(namep,my_name,16); - strupper(namep); - CVAL(p,21) = 2; /* major version */ - CVAL(p,22) = 2; /* minor version */ - stypep = p+23; - SIVAL(p,23,stype); - SSVAL(p,27,0xaa55); /* browse signature */ - SSVAL(p,29,1); /* browse version */ - commentp = p+31; - strcpy(commentp,comment); - p = p+31; - p = skip_string(p,1); - - if (ip_equal(bcast_ip,d->bcast_ip)) - { - if (AM_MASTER(work)) - { - SIVAL(stypep,0,work->ServerType); - - CVAL(outbuf,0) = 15; /* local member announce */ - - send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf, - PTR_DIFF(p,outbuf), - my_name,work->work_group,0,0x1e,d->bcast_ip,myip); - - CVAL(outbuf,0) = 12; /* domain announce */ - - StrnCpy(namep,work->work_group,15); - strupper(namep); - StrnCpy(commentp,myname,15); - strupper(commentp); - - SIVAL(stypep,0,(unsigned)0x80000000); - p = commentp + strlen(commentp) + 1; - - send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf, - PTR_DIFF(p,outbuf), - my_name,MSBROWSE,0,0x01,d->bcast_ip,myip); - } - else - { - CVAL(outbuf,0) = 1; /* host announce */ - - send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf, - PTR_DIFF(p,outbuf), - my_name,work->work_group,0,0x1d,d->bcast_ip,myip); - } - } - } - - if (work->needannounce) - { - work->needannounce = False; - break; - /* sorry: can't do too many announces. do some more later */ - } + if (AM_MASTER(work)) + { + SIVAL(stypep,0,work->ServerType); + + CVAL(outbuf,0) = 15; /* local member announce */ + + send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf, + PTR_DIFF(p,outbuf), + my_name,work->work_group,0, + 0x1e,d->bcast_ip,myip); + + CVAL(outbuf,0) = 12; /* domain announce */ + + StrnCpy(namep,work->work_group,15); + strupper(namep); + StrnCpy(commentp,myname,15); + strupper(commentp); + + SIVAL(stypep,0,(unsigned)0x80000000); + p = commentp + strlen(commentp) + 1; + + send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf, + PTR_DIFF(p,outbuf), + my_name,MSBROWSE,0,0x01,d->bcast_ip,myip); + } + else + { + CVAL(outbuf,0) = 1; /* host announce */ + + send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf, + PTR_DIFF(p,outbuf), + my_name,work->work_group,0,0x1d,d->bcast_ip,myip); + } } + } + + if (work->needannounce) + { + work->needannounce = False; + break; + /* sorry: can't do too many announces. do some more later */ + } } + } } @@ -337,108 +335,108 @@ void announce_host(void) **************************************************************************/ void announce_master(void) { - struct domain_record *d; - static time_t last=0; - time_t t = time(NULL); - BOOL am_master = False; /* are we a master of some sort? :-) */ + struct domain_record *d; + static time_t last=0; + time_t t = time(NULL); + BOOL am_master = False; /* are we a master of some sort? :-) */ #ifdef TEST_CODE - if (last && (t-last < 2*60)) return; + if (last && (t-last < 2*60)) return; #else - if (last && (t-last < 15*60)) return; + if (last && (t-last < 15*60)) return; #endif - last = t; + last = t; - for (d = domainlist; d; d = d->next) + for (d = domainlist; d; d = d->next) + { + struct work_record *work; + for (work = d->workgrouplist; work; work = work->next) { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - if (AM_MASTER(work)) - { - am_master = True; - } - } + if (AM_MASTER(work)) + { + am_master = True; + } } - - if (!am_master) return; /* only proceed if we are a master browser */ - - for (d = domainlist; d; d = d->next) + } + + if (!am_master) return; /* only proceed if we are a master browser */ + + for (d = domainlist; d; d = d->next) + { + struct work_record *work; + for (work = d->workgrouplist; work; work = work->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 PDCs (which should also be master browsers) */ + if (s->serv.type & SV_TYPE_DOMAIN_CTRL) { - struct server_record *s; - for (s = work->serverlist; s; s = s->next) + /* 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()) { - if (strequal(s->serv.name, myname)) continue; - - /* all PDCs (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()) - { - struct in_addr ip; - ip = ipzero; - - queue_netbios_pkt_wins(ClientNMB,NMB_QUERY, - MASTER_SERVER_CHECK, - work->work_group,0x1b,0, - False, False, ip); - } - else - { - struct domain_record *d2; - for (d2 = domainlist; d2; d2 = d2->next) - { - queue_netbios_packet(ClientNMB,NMB_QUERY, - MASTER_SERVER_CHECK, - work->work_group,0x1b,0, - True, False, d2->bcast_ip); - } - } - } - } + struct in_addr ip; + ip = ipzero; + + queue_netbios_pkt_wins(ClientNMB,NMB_QUERY, + MASTER_SERVER_CHECK, + work->work_group,0x1b,0, + False, False, 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()) + else { - struct in_addr ip; - BOOL bcast = False; - - ip = *interpret_addr2(lp_domain_controller()); - - if (zero_ip(ip)) - { - ip = bcast_ip; - bcast = True; - } - - DEBUG(2, ("Searching for PDC %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(ClientNMB, NMB_QUERY,MASTER_SERVER_CHECK, - work->work_group,0x1b, 0, - bcast, False, ip); + struct domain_record *d2; + for (d2 = domainlist; d2; d2 = d2->next) + { + queue_netbios_packet(ClientNMB,NMB_QUERY, + MASTER_SERVER_CHECK, + work->work_group,0x1b,0, + True, False, 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 = bcast_ip; + bcast = True; + } + + DEBUG(2, ("Searching for PDC %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(ClientNMB, NMB_QUERY,MASTER_SERVER_CHECK, + work->work_group,0x1b, 0, + bcast, False, ip); + } } + } } diff --git a/source3/namedb.c b/source3/namedb.c index 9151789b9b..3e19f3fc8a 100644 --- a/source3/namedb.c +++ b/source3/namedb.c @@ -55,11 +55,6 @@ int workgroup_count = 0; /* unique index key: one for each workgroup */ SV_TYPE_PRINTQ_SERVER | SV_TYPE_POTENTIAL_BROWSER) /* here are my election parameters */ - -/* NTAS uses 2, NT uses 1, WfWg uses 0 */ -#define MAINTAIN_LIST 2 -#define ELECTION_VERSION 2 - #define MSBROWSE "\001\002__MSBROWSE__\002" @@ -68,23 +63,23 @@ int workgroup_count = 0; /* unique index key: one for each workgroup */ **************************************************************************/ static void add_workgroup(struct work_record *work, struct domain_record *d) { - struct work_record *w2; - - if (!work || !d) return; - - if (!d->workgrouplist) - { - d->workgrouplist = work; - work->prev = NULL; - work->next = NULL; - return; - } - - for (w2 = d->workgrouplist; w2->next; w2 = w2->next); - - w2->next = work; - work->next = NULL; - work->prev = w2; + struct work_record *w2; + + if (!work || !d) return; + + if (!d->workgrouplist) + { + d->workgrouplist = work; + work->prev = NULL; + work->next = NULL; + return; + } + + for (w2 = d->workgrouplist; w2->next; w2 = w2->next); + + w2->next = work; + work->next = NULL; + work->prev = w2; } @@ -93,56 +88,55 @@ static void add_workgroup(struct work_record *work, struct domain_record *d) **************************************************************************/ static struct work_record *make_workgroup(char *name) { - struct work_record *work; - struct domain_record *d; - int t = -1; - - if (!name || !name[0]) return NULL; - - work = (struct work_record *)malloc(sizeof(*work)); - if (!work) return(NULL); - - StrnCpy(work->work_group,name,sizeof(work->work_group)-1); - work->serverlist = NULL; - - work->ServerType = DFLT_SERVER_TYPE; - work->RunningElection = False; - work->ElectionCount = 0; - work->needelection = False; - work->needannounce = True; - - /* make sure all token representations of workgroups are unique */ - - for (d = domainlist; d && t == -1; d = d->next) - { - struct work_record *w; - for (w = d->workgrouplist; w && t == -1; w = w->next) - { - if (strequal(w->work_group, work->work_group)) t = w->token; - } - } - - if (t == -1) - { - work->token = ++workgroup_count; - } - else - { - work->token = t; - } - - - /* WfWg uses 01040b01 */ - /* Win95 uses 01041501 */ - /* NTAS uses ???????? */ - work->ElectionCriterion = (MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8); - work->ElectionCriterion |= (lp_os_level() << 24); - if (lp_domain_master()) + struct work_record *work; + struct domain_record *d; + int t = -1; + + if (!name || !name[0]) return NULL; + + work = (struct work_record *)malloc(sizeof(*work)); + if (!work) return(NULL); + + StrnCpy(work->work_group,name,sizeof(work->work_group)-1); + work->serverlist = NULL; + + work->ServerType = DFLT_SERVER_TYPE; + work->RunningElection = False; + work->ElectionCount = 0; + work->needelection = False; + work->needannounce = True; + + /* make sure all token representations of workgroups are unique */ + + for (d = domainlist; d && t == -1; d = d->next) + { + struct work_record *w; + for (w = d->workgrouplist; w && t == -1; w = w->next) { - work->ElectionCriterion |= 0x80; + if (strequal(w->work_group, work->work_group)) t = w->token; } - - return work; + } + + if (t == -1) + { + work->token = ++workgroup_count; + } + else + { + work->token = t; + } + + + /* WfWg uses 01040b01 */ + /* Win95 uses 01041501 */ + /* NTAS uses ???????? */ + work->ElectionCriterion = (MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8); + work->ElectionCriterion |= (lp_os_level() << 24); + if (lp_domain_master()) { + work->ElectionCriterion |= 0x80; + } + + return work; } @@ -152,30 +146,31 @@ static struct work_record *make_workgroup(char *name) ******************************************************************/ static void remove_old_servers(struct work_record *work, time_t t) { - struct server_record *s; - struct server_record *nexts; - - /* expire old entries in the serverlist */ - for (s = work->serverlist; s; s = nexts) + struct server_record *s; + struct server_record *nexts; + + /* expire old entries in the serverlist */ + for (s = work->serverlist; s; s = nexts) + { + if (t == -1 || (s->death_time && s->death_time < t)) { - if (t == -1 || (s->death_time && s->death_time < t)) - { - DEBUG(3,("Removing dead server %s\n",s->serv.name)); - updatedlists = True; - nexts = s->next; - - if (s->prev) s->prev->next = s->next; - if (s->next) s->next->prev = s->prev; - - if (work->serverlist == s) work->serverlist = s->next; + DEBUG(3,("Removing dead server %s\n",s->serv.name)); + updatedlists = True; + nexts = s->next; + + if (s->prev) s->prev->next = s->next; + if (s->next) s->next->prev = s->prev; + + if (work->serverlist == s) + work->serverlist = s->next; - free(s); - } - else - { - nexts = s->next; - } + free(s); } + else + { + nexts = s->next; + } + } } @@ -184,24 +179,24 @@ static void remove_old_servers(struct work_record *work, time_t t) ******************************************************************/ struct work_record *remove_workgroup(struct domain_record *d, struct work_record *work) { - struct work_record *ret_work = NULL; - - if (!d || !work) return NULL; - - DEBUG(3,("Removing old workgroup %s\n", work->work_group)); - - remove_old_servers(work, -1); - - ret_work = work->next; - - if (work->prev) work->prev->next = work->next; - if (work->next) work->next->prev = work->prev; - - if (d->workgrouplist == work) d->workgrouplist = work->next; - - free(work); - - return ret_work; + struct work_record *ret_work = NULL; + + if (!d || !work) return NULL; + + DEBUG(3,("Removing old workgroup %s\n", work->work_group)); + + remove_old_servers(work, -1); + + ret_work = work->next; + + if (work->prev) work->prev->next = work->next; + if (work->next) work->next->prev = work->prev; + + if (d->workgrouplist == work) d->workgrouplist = work->next; + + free(work); + + return ret_work; } @@ -232,21 +227,21 @@ static void add_domain(struct domain_record *d) **************************************************************************/ static void add_browse_cache(struct browse_cache_record *b) { -struct browse_cache_record *b2; - - if (!browserlist) - { - browserlist = b; - b->prev = NULL; - b->next = NULL; - return; - } - - for (b2 = browserlist; b2->next; b2 = b2->next) ; - - b2->next = b; - b->next = NULL; - b->prev = b2; + struct browse_cache_record *b2; + + if (!browserlist) + { + browserlist = b; + b->prev = NULL; + b->next = NULL; + return; + } + + for (b2 = browserlist; b2->next; b2 = b2->next) ; + + b2->next = b; + b->next = NULL; + b->prev = b2; } @@ -277,29 +272,29 @@ static void add_server(struct work_record *work,struct server_record *s) ******************************************************************/ void expire_browse_cache(time_t t) { - struct browse_cache_record *b; - struct browse_cache_record *nextb; - - /* expire old entries in the serverlist */ - for (b = browserlist; b; b = nextb) + struct browse_cache_record *b; + struct browse_cache_record *nextb; + + /* expire old entries in the serverlist */ + for (b = browserlist; b; b = nextb) + { + if (b->synced && b->sync_time < t) { - if (b->synced && b->sync_time < t) - { - DEBUG(3,("Removing dead cached browser %s\n",b->name)); - nextb = b->next; - - if (b->prev) b->prev->next = b->next; - if (b->next) b->next->prev = b->prev; - - if (browserlist == b) browserlist = b->next; - - free(b); - } - else - { - nextb = b->next; - } + DEBUG(3,("Removing dead cached browser %s\n",b->name)); + nextb = b->next; + + if (b->prev) b->prev->next = b->next; + if (b->next) b->next->prev = b->prev; + + if (browserlist == b) browserlist = b->next; + + free(b); } + else + { + nextb = b->next; + } + } } @@ -311,51 +306,51 @@ void expire_browse_cache(time_t t) **************************************************************************/ struct work_record *find_workgroupstruct(struct domain_record *d, fstring name, BOOL add) { - struct work_record *ret, *work; - - if (!d) return NULL; - - DEBUG(4, ("workgroup search for %s: ", name)); - - if (strequal(name, "*")) + struct work_record *ret, *work; + + if (!d) return NULL; + + DEBUG(4, ("workgroup search for %s: ", name)); + + if (strequal(name, "*")) + { + DEBUG(2,("add any workgroups: initiating browser search on %s\n", + inet_ntoa(d->bcast_ip))); + queue_netbios_pkt_wins(ClientNMB,NMB_QUERY, FIND_MASTER, + MSBROWSE,0x1,0, + True,False, d->bcast_ip); + return NULL; + } + + for (ret = d->workgrouplist; ret; ret = ret->next) + { + if (!strcmp(ret->work_group,name)) { - DEBUG(2,("add any workgroups: initiating browser search on %s\n", - inet_ntoa(d->bcast_ip))); - queue_netbios_pkt_wins(ClientNMB,NMB_QUERY, FIND_MASTER, - MSBROWSE,0x1,0, - True,False, d->bcast_ip); - return NULL; + DEBUG(4, ("found\n")); + return(ret); } - - for (ret = d->workgrouplist; ret; ret = ret->next) + } + + DEBUG(4, ("not found: creating\n")); + + if ((work = make_workgroup(name))) + { + if (lp_preferred_master() && + strequal(lp_workgroup(), name) && + ip_equal(d->bcast_ip, bcast_ip)) { - if (!strcmp(ret->work_group,name)) - { - DEBUG(4, ("found\n")); - return(ret); - } + DEBUG(3, ("preferred master startup for %s\n", work->work_group)); + work->needelection = True; + work->ElectionCriterion |= (1<<3); } - - DEBUG(4, ("not found: creating\n")); - - if ((work = make_workgroup(name))) + if (!ip_equal(bcast_ip, d->bcast_ip)) { - if (lp_preferred_master() && - strequal(lp_workgroup(), name) && - ip_equal(d->bcast_ip, bcast_ip)) - { - DEBUG(3, ("preferred master startup for %s\n", work->work_group)); - work->needelection = True; - work->ElectionCriterion |= (1<<3); - } - if (!ip_equal(bcast_ip, d->bcast_ip)) - { - work->needelection = False; - } - add_workgroup(work, d); - return(work); + work->needelection = False; } - return NULL; + add_workgroup(work, d); + return(work); + } + return NULL; } /**************************************************************************** @@ -363,20 +358,20 @@ struct work_record *find_workgroupstruct(struct domain_record *d, fstring name, **************************************************************************/ struct domain_record *find_domain(struct in_addr source_ip) { - struct domain_record *d; - - /* search through domain list for broadcast/netmask that matches - the source ip address */ - - for (d = domainlist; d; d = d->next) + struct domain_record *d; + + /* search through domain list for broadcast/netmask that matches + the source ip address */ + + for (d = domainlist; d; d = d->next) + { + if (same_net(source_ip, d->bcast_ip, d->mask_ip)) { - if (same_net(source_ip, d->bcast_ip, d->mask_ip)) - { - return(d); - } + return(d); } - - return (NULL); + } + + return (NULL); } @@ -385,33 +380,33 @@ struct domain_record *find_domain(struct in_addr source_ip) **************************************************************************/ static void dump_workgroups(void) { - struct domain_record *d; - - for (d = domainlist; d; d = d->next) + struct domain_record *d; + + for (d = domainlist; d; d = d->next) + { + if (d->workgrouplist) { - if (d->workgrouplist) + struct work_record *work; + + DEBUG(3,("dump domain %15s: ", inet_ntoa(d->bcast_ip))); + DEBUG(3,(" %15s:\n", inet_ntoa(d->bcast_ip))); + + for (work = d->workgrouplist; work; work = work->next) + { + if (work->serverlist) { - struct work_record *work; - - DEBUG(3,("dump domain %15s: ", inet_ntoa(d->bcast_ip))); - DEBUG(3,(" %15s:\n", inet_ntoa(d->bcast_ip))); - - for (work = d->workgrouplist; work; work = work->next) - { - if (work->serverlist) - { - struct server_record *s; - - DEBUG(3,("\t%s(%d)\n", work->work_group, work->token)); - for (s = work->serverlist; s; s = s->next) - { - DEBUG(3,("\t\t%s %8x (%s)\n", - s->serv.name, s->serv.type, s->serv.comment)); - } - } - } + struct server_record *s; + + DEBUG(3,("\t%s(%d)\n", work->work_group, work->token)); + for (s = work->serverlist; s; s = s->next) + { + DEBUG(3,("\t\t%s %8x (%s)\n", + s->serv.name, s->serv.type, s->serv.comment)); + } } + } } + } } /**************************************************************************** @@ -419,57 +414,60 @@ static void dump_workgroups(void) ****************************************************************************/ static struct domain_record *make_domain(struct in_addr ip, struct in_addr mask) { - struct domain_record *d; - d = (struct domain_record *)malloc(sizeof(*d)); - - if (!d) return(NULL); - - bzero((char *)d,sizeof(*d)); - - DEBUG(4, ("making domain %s ", inet_ntoa(ip))); - DEBUG(4, ("%s\n", inet_ntoa(mask))); - - d->bcast_ip = ip; - d->mask_ip = mask; - d->workgrouplist = NULL; - - add_domain(d); - - return d; + struct domain_record *d; + d = (struct domain_record *)malloc(sizeof(*d)); + + if (!d) return(NULL); + + bzero((char *)d,sizeof(*d)); + + DEBUG(4, ("making domain %s ", inet_ntoa(ip))); + DEBUG(4, ("%s\n", inet_ntoa(mask))); + + d->bcast_ip = ip; + d->mask_ip = mask; + d->workgrouplist = NULL; + + add_domain(d); + + return d; } /**************************************************************************** add a domain entry. creates a workgroup, if necessary, and adds the domain to the named a workgroup. ****************************************************************************/ -struct domain_record *add_domain_entry(struct in_addr source_ip, struct in_addr source_mask, +struct domain_record *add_domain_entry(struct in_addr source_ip, + struct in_addr source_mask, char *name, BOOL add) { struct domain_record *d; struct in_addr ip; - - ip = *interpret_addr2("255.255.255.255"); - - if (zero_ip(source_ip)) source_ip = bcast_ip; - - /* add the domain into our domain database */ - if ((d = find_domain(source_ip)) || - (d = make_domain(source_ip, source_mask))) + + ip = *interpret_addr2("255.255.255.255"); + + if (zero_ip(source_ip)) source_ip = bcast_ip; + + /* add the domain into our domain database */ + if ((d = find_domain(source_ip)) || + (d = make_domain(source_ip, source_mask))) + { + struct work_record *w = find_workgroupstruct(d, name, add); + + /* add WORKGROUP(1e) and WORKGROUP(00) entries into name database + or register with WINS server, if it's our workgroup */ + if (strequal(lp_workgroup(), name)) { - find_workgroupstruct(d, name, add); - - /* add WORKGROUP(1e) and WORKGROUP(00) entries into name database - or register with WINS server, if it's our workgroup */ - if (strequal(lp_workgroup(), name)) - { - add_name_entry(name,0x1e,NB_ACTIVE|NB_GROUP); - add_name_entry(name,0x0 ,NB_ACTIVE|NB_GROUP); - } - - DEBUG(3,("Added domain name entry %s at %s\n", name,inet_ntoa(ip))); - return d; + extern pstring ServerComment; + add_name_entry(name,0x1e,NB_ACTIVE|NB_GROUP); + add_name_entry(name,0x0 ,NB_ACTIVE|NB_GROUP); + add_server_entry(d,w,myname,w->ServerType,0,ServerComment,True); } - return NULL; + + DEBUG(3,("Added domain name entry %s at %s\n", name,inet_ntoa(ip))); + return d; + } + return NULL; } /**************************************************************************** @@ -478,141 +476,143 @@ struct domain_record *add_domain_entry(struct in_addr source_ip, struct in_addr struct browse_cache_record *add_browser_entry(char *name, int type, char *wg, time_t ttl, struct in_addr ip) { - BOOL newentry=False; - - struct browse_cache_record *b; - - /* search for the entry: if it's already in the cache, update that entry */ - for (b = browserlist; b; b = b->next) - { - if (ip_equal(ip,b->ip) && strequal(b->group, wg)) break; - } - - if (b && b->synced) - { - /* entries get left in the cache for a while. this stops sync'ing too - often if the network is large */ - DEBUG(4, ("browser %s %s %s already sync'd at time %d\n", - b->name, b->group, inet_ntoa(b->ip), b->sync_time)); - return NULL; - } - - if (!b) - { - newentry = True; - b = (struct browse_cache_record *)malloc(sizeof(*b)); - - if (!b) return(NULL); - - bzero((char *)b,sizeof(*b)); - } - - /* update the entry */ - ttl = time(NULL)+ttl; - - StrnCpy(b->name ,name,sizeof(b->name )-1); - StrnCpy(b->group,wg ,sizeof(b->group)-1); - strupper(b->name); - strupper(b->group); - - b->ip = ip; - b->type = type; - - if (newentry || ttl < b->sync_time) b->sync_time = ttl; - - if (newentry) - { - b->synced = False; - add_browse_cache(b); - - DEBUG(3,("Added cache entry %s %s(%2x) %s ttl %d\n", - wg, name, type, inet_ntoa(ip),ttl)); - } - else - { - DEBUG(3,("Updated cache entry %s %s(%2x) %s ttl %d\n", - wg, name, type, inet_ntoa(ip),ttl)); - } - - return(b); + BOOL newentry=False; + + struct browse_cache_record *b; + + /* search for the entry: if it's already in the cache, update that entry */ + for (b = browserlist; b; b = b->next) + { + if (ip_equal(ip,b->ip) && strequal(b->group, wg)) break; + } + + if (b && b->synced) + { + /* entries get left in the cache for a while. this stops sync'ing too + often if the network is large */ + DEBUG(4, ("browser %s %s %s already sync'd at time %d\n", + b->name, b->group, inet_ntoa(b->ip), b->sync_time)); + return NULL; + } + + if (!b) + { + newentry = True; + b = (struct browse_cache_record *)malloc(sizeof(*b)); + + if (!b) return(NULL); + + bzero((char *)b,sizeof(*b)); + } + + /* update the entry */ + ttl = time(NULL)+ttl; + + StrnCpy(b->name ,name,sizeof(b->name )-1); + StrnCpy(b->group,wg ,sizeof(b->group)-1); + strupper(b->name); + strupper(b->group); + + b->ip = ip; + b->type = type; + + if (newentry || ttl < b->sync_time) b->sync_time = ttl; + + if (newentry) + { + b->synced = False; + add_browse_cache(b); + + DEBUG(3,("Added cache entry %s %s(%2x) %s ttl %d\n", + wg, name, type, inet_ntoa(ip),ttl)); + } + else + { + DEBUG(3,("Updated cache entry %s %s(%2x) %s ttl %d\n", + wg, name, type, inet_ntoa(ip),ttl)); + } + + return(b); } /**************************************************************************** add a server entry ****************************************************************************/ -struct server_record *add_server_entry(struct domain_record *d, struct work_record *work, - char *name,int servertype, int ttl,char *comment, +struct server_record *add_server_entry(struct domain_record *d, + struct work_record *work, + char *name,int servertype, + int ttl,char *comment, BOOL replace) { - BOOL newentry=False; - struct server_record *s; - - if (name[0] == '*') - { - return (NULL); - } - - for (s = work->serverlist; s; s = s->next) - { - if (strequal(name,s->serv.name)) break; - } - - if (s && !replace) - { - DEBUG(4,("Not replacing %s\n",name)); - return(s); - } - - updatedlists=True; - - if (!s) - { - newentry = True; - s = (struct server_record *)malloc(sizeof(*s)); - - if (!s) return(NULL); - - bzero((char *)s,sizeof(*s)); - } - - if (ip_equal(bcast_ip, d->bcast_ip) && - strequal(lp_workgroup(),work->work_group)) - { - servertype |= SV_TYPE_LOCAL_LIST_ONLY; - } - else - { - servertype &= ~SV_TYPE_LOCAL_LIST_ONLY; - } - - /* update the entry */ - StrnCpy(s->serv.name,name,sizeof(s->serv.name)-1); - StrnCpy(s->serv.comment,comment,sizeof(s->serv.comment)-1); - strupper(s->serv.name); - s->serv.type = servertype; - s->death_time = ttl?time(NULL)+ttl*3:0; - - /* for a domain entry, the comment field refers to the server name */ - - if (s->serv.type & SV_TYPE_DOMAIN_ENUM) strupper(s->serv.comment); - - if (newentry) - { - add_server(work, s); - - DEBUG(3,("Added ")); - } - else - { - DEBUG(3,("Updated ")); - } - - DEBUG(3,("server entry %s of type %x (%s) to %s %s\n", - name,servertype,comment, - work->work_group,inet_ntoa(d->bcast_ip))); - - return(s); + BOOL newentry=False; + struct server_record *s; + + if (name[0] == '*') + { + return (NULL); + } + + for (s = work->serverlist; s; s = s->next) + { + if (strequal(name,s->serv.name)) break; + } + + if (s && !replace) + { + DEBUG(4,("Not replacing %s\n",name)); + return(s); + } + + updatedlists=True; + + if (!s) + { + newentry = True; + s = (struct server_record *)malloc(sizeof(*s)); + + if (!s) return(NULL); + + bzero((char *)s,sizeof(*s)); + } + + if (ip_equal(bcast_ip, d->bcast_ip) && + strequal(lp_workgroup(),work->work_group)) + { + servertype |= SV_TYPE_LOCAL_LIST_ONLY; + } + else + { + servertype &= ~SV_TYPE_LOCAL_LIST_ONLY; + } + + /* update the entry */ + StrnCpy(s->serv.name,name,sizeof(s->serv.name)-1); + StrnCpy(s->serv.comment,comment,sizeof(s->serv.comment)-1); + strupper(s->serv.name); + s->serv.type = servertype; + s->death_time = ttl?time(NULL)+ttl*3:0; + + /* for a domain entry, the comment field refers to the server name */ + + if (s->serv.type & SV_TYPE_DOMAIN_ENUM) strupper(s->serv.comment); + + if (newentry) + { + add_server(work, s); + + DEBUG(3,("Added ")); + } + else + { + DEBUG(3,("Updated ")); + } + + DEBUG(3,("server entry %s of type %x (%s) to %s %s\n", + name,servertype,comment, + work->work_group,inet_ntoa(d->bcast_ip))); + + return(s); } @@ -621,71 +621,71 @@ struct server_record *add_server_entry(struct domain_record *d, struct work_reco ******************************************************************/ void write_browse_list(void) { - struct domain_record *d; - - pstring fname,fnamenew; - FILE *f; - - if (!updatedlists) return; - - dump_names(); - dump_workgroups(); - - updatedlists = False; - updatecount++; - - strcpy(fname,lp_lockdir()); - trim_string(fname,NULL,"/"); - strcat(fname,"/"); - strcat(fname,SERVER_LIST); - strcpy(fnamenew,fname); - strcat(fnamenew,"."); - - f = fopen(fnamenew,"w"); - - if (!f) - { - DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno))); - return; - } - - for (d = domainlist; d ; d = d->next) + struct domain_record *d; + + pstring fname,fnamenew; + FILE *f; + + if (!updatedlists) return; + + dump_names(); + dump_workgroups(); + + updatedlists = False; + updatecount++; + + strcpy(fname,lp_lockdir()); + trim_string(fname,NULL,"/"); + strcat(fname,"/"); + strcat(fname,SERVER_LIST); + strcpy(fnamenew,fname); + strcat(fnamenew,"."); + + f = fopen(fnamenew,"w"); + + if (!f) + { + DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno))); + return; + } + + for (d = domainlist; d ; d = d->next) + { + struct work_record *work; + for (work = d->workgrouplist; work ; work = work->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) + { + fstring tmp; + + /* don't list domains I don't have a master for */ + if ((s->serv.type & SV_TYPE_DOMAIN_ENUM) && + !s->serv.comment[0]) { - struct server_record *s; - for (s = work->serverlist; s ; s = s->next) - { - fstring tmp; - - /* don't list domains I don't have a master for */ - if ((s->serv.type & SV_TYPE_DOMAIN_ENUM) && - !s->serv.comment[0]) - { - continue; - } - - /* output server details, plus what workgroup/domain - they're in. without the domain information, the - combined list of all servers in all workgroups gets - sent to anyone asking about any workgroup! */ - - sprintf(tmp, "\"%s\"", s->serv.name); - fprintf(f, "%-25s ", tmp); - fprintf(f, "%08x ", s->serv.type); - sprintf(tmp, "\"%s\"", s->serv.comment); - fprintf(f, "%-30s", tmp); - fprintf(f, "\"%s\"\n", work->work_group); - } + continue; } + + /* output server details, plus what workgroup/domain + they're in. without the domain information, the + combined list of all servers in all workgroups gets + sent to anyone asking about any workgroup! */ + + sprintf(tmp, "\"%s\"", s->serv.name); + fprintf(f, "%-25s ", tmp); + fprintf(f, "%08x ", s->serv.type); + sprintf(tmp, "\"%s\"", s->serv.comment); + fprintf(f, "%-30s", tmp); + fprintf(f, "\"%s\"\n", work->work_group); + } } - - fclose(f); - unlink(fname); - chmod(fnamenew,0644); - rename(fnamenew,fname); - DEBUG(3,("Wrote browse list %s\n",fname)); + } + + fclose(f); + unlink(fname); + chmod(fnamenew,0644); + rename(fnamenew,fname); + DEBUG(3,("Wrote browse list %s\n",fname)); } @@ -694,16 +694,16 @@ void write_browse_list(void) ******************************************************************/ void expire_servers(time_t t) { - struct domain_record *d; - - for (d = domainlist ; d ; d = d->next) + struct domain_record *d; + + for (d = domainlist ; d ; d = d->next) + { + struct work_record *work; + + for (work = d->workgrouplist; work; work = work->next) { - struct work_record *work; - - for (work = d->workgrouplist; work; work = work->next) - { - remove_old_servers(work, t); - } + remove_old_servers(work, t); } + } } diff --git a/source3/nameelect.c b/source3/nameelect.c index 30c3c3795e..34455b27f9 100644 --- a/source3/nameelect.c +++ b/source3/nameelect.c @@ -39,10 +39,6 @@ extern pstring ServerComment; /* here are my election parameters */ -/* NTAS uses 2, NT uses 1, WfWg uses 0 */ -#define MAINTAIN_LIST 2 -#define ELECTION_VERSION 2 - extern time_t StartupTime; #define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER) @@ -124,29 +120,29 @@ void browser_gone(char *work_name, struct in_addr ip) void send_election(struct domain_record *d, char *group,uint32 criterion, int timeup,char *name) { - pstring outbuf; - char *p; - - if (!d) return; + pstring outbuf; + char *p; - DEBUG(2,("Sending election to %s for workgroup %s\n", + if (!d) return; + + DEBUG(2,("Sending election to %s for workgroup %s\n", inet_ntoa(d->bcast_ip),group)); - bzero(outbuf,sizeof(outbuf)); - p = outbuf; - CVAL(p,0) = 8; /* election */ - p++; - - CVAL(p,0) = (criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION; - SIVAL(p,1,criterion); - SIVAL(p,5,timeup*1000); /* ms - despite the spec */ - p += 13; - strcpy(p,name); - strupper(p); - p = skip_string(p,1); - - send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), - name,group,0,0x1e,d->bcast_ip,myip); + bzero(outbuf,sizeof(outbuf)); + p = outbuf; + CVAL(p,0) = 8; /* election */ + p++; + + CVAL(p,0) = (criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION; + SIVAL(p,1,criterion); + SIVAL(p,5,timeup*1000); /* ms - despite the spec */ + p += 13; + strcpy(p,name); + strupper(p); + p = skip_string(p,1); + + send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), + name,group,0,0x1e,d->bcast_ip,myip); } @@ -155,46 +151,46 @@ void send_election(struct domain_record *d, char *group,uint32 criterion, ******************************************************************/ static void become_master(struct domain_record *d, struct work_record *work) { - uint32 domain_type = SV_TYPE_DOMAIN_ENUM | SV_TYPE_SERVER_UNIX | 0x00400000; - - if (!work) return; - - DEBUG(2,("Becoming master for %s\n",work->work_group)); - - work->ServerType |= SV_TYPE_MASTER_BROWSER; - work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER; - work->ElectionCriterion |= 0x5; - - /* add browse, master and general names to database or register with WINS */ - add_name_entry(MSBROWSE ,0x01,NB_ACTIVE|NB_GROUP); - add_name_entry(work->work_group,0x1d,NB_ACTIVE ); - - if (lp_domain_master()) - { - DEBUG(4,("Domain master: adding names...\n")); - - /* add domain master and domain member names or register with WINS */ - add_name_entry(work->work_group,0x1b,NB_ACTIVE ); - add_name_entry(work->work_group,0x1c,NB_ACTIVE|NB_GROUP); - - work->ServerType |= SV_TYPE_DOMAIN_MASTER; - - if (lp_domain_logons()) - { - work->ServerType |= SV_TYPE_DOMAIN_CTRL; - work->ServerType |= SV_TYPE_DOMAIN_MEMBER; - } - } + uint32 domain_type = SV_TYPE_DOMAIN_ENUM | SV_TYPE_SERVER_UNIX | 0x00400000; - /* update our server status */ - add_server_entry(d,work,work->work_group,domain_type,0,myname,True); - add_server_entry(d,work,myname,work->ServerType,0,ServerComment,True); - - if (ip_equal(bcast_ip, d->bcast_ip)) + if (!work) return; + + DEBUG(2,("Becoming master for %s\n",work->work_group)); + + work->ServerType |= SV_TYPE_MASTER_BROWSER; + work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER; + work->ElectionCriterion |= 0x5; + + /* add browse, master and general names to database or register with WINS */ + add_name_entry(MSBROWSE ,0x01,NB_ACTIVE|NB_GROUP); + add_name_entry(work->work_group,0x1d,NB_ACTIVE ); + + if (lp_domain_master()) + { + DEBUG(4,("Domain master: adding names...\n")); + + /* add domain master and domain member names or register with WINS */ + add_name_entry(work->work_group,0x1b,NB_ACTIVE ); + add_name_entry(work->work_group,0x1c,NB_ACTIVE|NB_GROUP); + + work->ServerType |= SV_TYPE_DOMAIN_MASTER; + + if (lp_domain_logons()) { - /* ask all servers on our local net to announce to us */ - announce_request(work, d->bcast_ip); + work->ServerType |= SV_TYPE_DOMAIN_CTRL; + work->ServerType |= SV_TYPE_DOMAIN_MEMBER; } + } + + /* update our server status */ + add_server_entry(d,work,work->work_group,domain_type,0,myname,True); + add_server_entry(d,work,myname,work->ServerType,0,ServerComment,True); + + if (ip_equal(bcast_ip, d->bcast_ip)) + { + /* ask all servers on our local net to announce to us */ + announce_request(work, d->bcast_ip); + } } @@ -203,18 +199,18 @@ static void become_master(struct domain_record *d, struct work_record *work) ******************************************************************/ void become_nonmaster(struct domain_record *d, struct work_record *work) { - DEBUG(2,("Becoming non-master for %s\n",work->work_group)); - - work->ServerType &= ~SV_TYPE_MASTER_BROWSER; - work->ServerType &= ~SV_TYPE_DOMAIN_MASTER; - work->ServerType |= SV_TYPE_POTENTIAL_BROWSER; - - work->ElectionCriterion &= ~0x4; - - remove_name_entry(work->work_group,0x1b); - remove_name_entry(work->work_group,0x1c); - remove_name_entry(work->work_group,0x1d); - remove_name_entry(MSBROWSE ,0x01); + DEBUG(2,("Becoming non-master for %s\n",work->work_group)); + + work->ServerType &= ~SV_TYPE_MASTER_BROWSER; + work->ServerType &= ~SV_TYPE_DOMAIN_MASTER; + work->ServerType |= SV_TYPE_POTENTIAL_BROWSER; + + work->ElectionCriterion &= ~0x4; + + remove_name_entry(work->work_group,0x1b); + remove_name_entry(work->work_group,0x1c); + remove_name_entry(work->work_group,0x1d); + remove_name_entry(MSBROWSE ,0x01); } @@ -223,37 +219,37 @@ void become_nonmaster(struct domain_record *d, struct work_record *work) ******************************************************************/ void run_elections(void) { - time_t t = time(NULL); - static time_t lastime = 0; - - struct domain_record *d; - - /* send election packets once a second */ - if (lastime && t-lastime <= 0) return; - - lastime = t; - - for (d = domainlist; d; d = d->next) + time_t t = time(NULL); + static time_t lastime = 0; + + struct domain_record *d; + + /* send election packets once a second */ + if (lastime && t-lastime <= 0) return; + + lastime = t; + + for (d = domainlist; d; d = d->next) + { + struct work_record *work; + for (work = d->workgrouplist; work; work = work->next) { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) + if (work->RunningElection) + { + send_election(d,work->work_group, work->ElectionCriterion, + t-StartupTime,myname); + + if (work->ElectionCount++ >= 4) { - if (work->RunningElection) - { - send_election(d,work->work_group, work->ElectionCriterion, - t-StartupTime,myname); - - if (work->ElectionCount++ >= 4) - { - /* I won! now what :-) */ - DEBUG(2,(">>> Won election on %s <<<\n",work->work_group)); - - work->RunningElection = False; - become_master(d, work); - } - } + /* I won! now what :-) */ + DEBUG(2,(">>> Won election on %s <<<\n",work->work_group)); + + work->RunningElection = False; + become_master(d, work); } + } } + } } @@ -289,56 +285,56 @@ static BOOL win_election(struct work_record *work,int version,uint32 criterion, ******************************************************************/ void process_election(struct packet_struct *p,char *buf) { - struct dgram_packet *dgram = &p->packet.dgram; - struct in_addr ip = dgram->header.source_ip; - struct domain_record *d = find_domain(ip); - int version = CVAL(buf,0); - uint32 criterion = IVAL(buf,1); - int timeup = IVAL(buf,5)/1000; - char *name = buf+13; - struct work_record *work; - - if (!d) return; - - name[15] = 0; - - DEBUG(3,("Election request from %s vers=%d criterion=%08x timeup=%d\n", - name,version,criterion,timeup)); - - if (same_context(dgram)) return; + struct dgram_packet *dgram = &p->packet.dgram; + struct in_addr ip = dgram->header.source_ip; + struct domain_record *d = find_domain(ip); + int version = CVAL(buf,0); + uint32 criterion = IVAL(buf,1); + int timeup = IVAL(buf,5)/1000; + char *name = buf+13; + struct work_record *work; + + if (!d) return; + + name[15] = 0; - for (work = d->workgrouplist; work; work = work->next) + DEBUG(3,("Election request from %s vers=%d criterion=%08x timeup=%d\n", + name,version,criterion,timeup)); + + if (same_context(dgram)) return; + + for (work = d->workgrouplist; work; work = work->next) + { + if (listening_name(work, &dgram->dest_name) && + strequal(work->work_group, lp_workgroup()) && + ip_equal(d->bcast_ip, bcast_ip)) { - if (listening_name(work, &dgram->dest_name) && - strequal(work->work_group, lp_workgroup()) && - ip_equal(d->bcast_ip, bcast_ip)) + if (win_election(work, version,criterion,timeup,name)) + { + if (!work->RunningElection) { - if (win_election(work, version,criterion,timeup,name)) - { - if (!work->RunningElection) - { - work->needelection = True; - work->ElectionCount=0; - } - } - else - { - work->needelection = False; - - if (work->RunningElection) - { - work->RunningElection = False; - DEBUG(3,(">>> Lost election on %s <<<\n",work->work_group)); - - /* if we are the master then remove our masterly names */ - if (AM_MASTER(work)) - { - become_nonmaster(d, work); - } - } - } + work->needelection = True; + work->ElectionCount=0; + } + } + else + { + work->needelection = False; + + if (work->RunningElection) + { + work->RunningElection = False; + DEBUG(3,(">>> Lost election on %s <<<\n",work->work_group)); + + /* if we are the master then remove our masterly names */ + if (AM_MASTER(work)) + { + become_nonmaster(d, work); + } } + } } + } } diff --git a/source3/nameresp.c b/source3/nameresp.c index a4a55c9f1b..8ed2ba92c4 100644 --- a/source3/nameresp.c +++ b/source3/nameresp.c @@ -245,29 +245,6 @@ uint16 initiate_netbios_packet(int fd,int quest_type,char *name,int name_type, } -void send_name_reg(void) -{ - struct packet_struct p; - struct nmb_packet *nmb = &p.packet.nmb; - int rcode = 0; - - nmb->header.opcode = 5; - nmb->header.response = True; - nmb->header.nm_flags.bcast = False; - nmb->header.nm_flags.recursion_available = CanRecurse; - nmb->header.nm_flags.recursion_desired = CanRecurse; - nmb->header.nm_flags.trunc = False; - nmb->header.nm_flags.authoritative = True; - nmb->header.qdcount = 0; - nmb->header.ancount = 1; - nmb->header.nscount = 0; - nmb->header.arcount = 0; - nmb->header.rcode = rcode; - - send_packet(&p); -} - - /**************************************************************************** wrapper function to override a broadcast message and send it to the WINS name server instead, if it exists. if wins is false, and there has been no @@ -349,7 +326,8 @@ void queue_netbios_packet(int fd,int quest_type,enum cmd_type cmd,char *name, if (id == 0) return; - if ((n = make_name_query_record(cmd,id,fd,name,name_type,bcast,recurse,to_ip))) + if ((n = + make_name_query_record(cmd,id,fd,name,name_type,bcast,recurse,to_ip))) { add_response_record(n); } @@ -453,13 +431,41 @@ void listen_for_packets(BOOL run_election) if (FD_ISSET(ClientNMB,&fds)) { struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET); - if (packet) queue_packet(packet); + if (packet) { +#if 0 + if (ip_equal(packet->ip,myip) && + (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) { + DEBUG(3,("discarding packet from %s:%d\n", + inet_ntoa(packet->ip),packet->port)); + DEBUG(3,("myip=%s eq=%d\n", + inet_ntoa(myip),ip_equal(packet->ip,myip))); + free_packet(packet); + } else +#endif + { + queue_packet(packet); + } + } } if (FD_ISSET(ClientDGRAM,&fds)) { struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET); - if (packet) queue_packet(packet); + if (packet) { +#if 0 + if (ip_equal(packet->ip,myip) && + (packet->port == NMB_PORT || packet->port == DGRAM_PORT)) { + DEBUG(3,("discarding packet from %s:%d\n", + inet_ntoa(packet->ip),packet->port)); + DEBUG(3,("myip=%s eq=%d\n", + inet_ntoa(myip),ip_equal(packet->ip,myip))); + free_packet(packet); + } else +#endif + { + queue_packet(packet); + } + } } } @@ -615,7 +621,7 @@ BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname, p.ip = dest_ip; p.port = DGRAM_PORT; - p.fd = fd; + p.fd = ClientDGRAM; p.timestamp = time(NULL); p.packet_type = DGRAM_PACKET; diff --git a/source3/nameserv.c b/source3/nameserv.c index 4cd9b099f0..176d955853 100644 --- a/source3/nameserv.c +++ b/source3/nameserv.c @@ -206,20 +206,20 @@ struct name_record *add_netbios_entry(char *name, int type, int nb_flags, int tt ****************************************************************************/ void remove_name_entry(char *name,int type) { - if (lp_wins_support()) - { - /* we are a WINS server. */ - remove_netbios_name(name,type,SELF,myip); - } - else - { - struct in_addr ip; - ip = ipzero; - - queue_netbios_pkt_wins(ClientNMB,NMB_REL,NAME_RELEASE, - name, type, 0, - False, True, ip); - } + if (lp_wins_support()) + { + /* we are a WINS server. */ + remove_netbios_name(name,type,SELF,myip); + } + else + { + struct in_addr ip; + ip = ipzero; + + queue_netbios_pkt_wins(ClientNMB,NMB_REL,NAME_RELEASE, + name, type, 0, + False, True, ip); + } } @@ -228,20 +228,18 @@ void remove_name_entry(char *name,int type) ****************************************************************************/ void add_name_entry(char *name,int type,int nb_flags) { - if (lp_wins_support()) - { - /* we are a WINS server. */ - add_netbios_entry(name,type,nb_flags,0,SELF,myip); - } - else - { - struct in_addr ip; - ip = ipzero; - - queue_netbios_pkt_wins(ClientNMB,NMB_REG,NAME_REGISTER, - name, type, nb_flags, - False, True, ip); - } + /* always add our own entries */ + add_netbios_entry(name,type,nb_flags,0,SELF,myip); + + if (!lp_wins_support()) + { + struct in_addr ip; + ip = ipzero; + + queue_netbios_pkt_wins(ClientNMB,NMB_REG,NAME_REGISTER, + name, type, nb_flags, + False, True, ip); + } } @@ -250,52 +248,67 @@ void add_name_entry(char *name,int type,int nb_flags) **************************************************************************/ void add_my_names(void) { - struct in_addr ip; + struct in_addr ip; - ip = ipzero; - - add_netbios_entry(myname,0x20,NB_ACTIVE,0,SELF,ip); - add_netbios_entry(myname,0x03,NB_ACTIVE,0,SELF,ip); - add_netbios_entry(myname,0x00,NB_ACTIVE,0,SELF,ip); - add_netbios_entry(myname,0x1f,NB_ACTIVE,0,SELF,ip); - add_netbios_entry("*",0x01,NB_ACTIVE,0,SELF,ip); - add_netbios_entry("__SAMBA__",0x20,NB_ACTIVE,0,SELF,ip); - add_netbios_entry("__SAMBA__",0x00,NB_ACTIVE,0,SELF,ip); - - if (lp_wins_support()) { - add_netbios_entry(inet_ntoa(myip),0x01,NB_ACTIVE,0,SELF,ip); /* nt as? */ - } + ip = ipzero; + + add_name_entry(myname,0x20,NB_ACTIVE); + add_name_entry(myname,0x03,NB_ACTIVE); + add_name_entry(myname,0x00,NB_ACTIVE); + add_name_entry(myname,0x1f,NB_ACTIVE); + + add_netbios_entry("*",0x0,NB_ACTIVE,0,SELF,ip); + add_netbios_entry("__SAMBA__",0x20,NB_ACTIVE,0,SELF,ip); + add_netbios_entry("__SAMBA__",0x00,NB_ACTIVE,0,SELF,ip); + + if (lp_wins_support()) { + add_netbios_entry(inet_ntoa(myip),0x01,NB_ACTIVE,0,SELF,ip); /* nt as? */ + } } /******************************************************************* - expires old names in the namelist + refresh my own names ******************************************************************/ -void expire_names(time_t t) +void refresh_my_names(time_t t) { - struct name_record *n; - struct name_record *next; - - /* expire old names */ - for (n = namelist; n; n = next) - { - if (n->death_time && n->death_time < t) - { - DEBUG(3,("Removing dead name %s\n", namestr(&n->name))); - - next = n->next; + static time_t lasttime = 0; - if (n->prev) n->prev->next = n->next; - if (n->next) n->next->prev = n->prev; + if (t - lasttime < REFRESH_TIME) + return; + lasttime = t; - if (namelist == n) namelist = n->next; + add_my_names(); +} - free(n); - } - else - { - next = n->next; - } +/******************************************************************* + expires old names in the namelist + ******************************************************************/ +void expire_names(time_t t) +{ + struct name_record *n; + struct name_record *next; + + /* expire old names */ + for (n = namelist; n; n = next) + { + if (n->death_time && n->death_time < t) + { + DEBUG(3,("Removing dead name %s\n", namestr(&n->name))); + + next = n->next; + + if (n->prev) n->prev->next = n->next; + if (n->next) n->next->prev = n->prev; + + if (namelist == n) namelist = n->next; + + free(n); } + else + { + next = n->next; + } + } } @@ -304,27 +317,27 @@ response for a reg release received **************************************************************************/ void response_name_release(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - char *name = nmb->question.question_name.name; - int type = nmb->question.question_name.name_type; - - DEBUG(4,("response name release received\n")); - - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - struct in_addr found_ip; - putip((char*)&found_ip,&nmb->answers->rdata[2]); - - if (ip_equal(found_ip, myip)) - { - remove_netbios_name(name,type,SELF,found_ip); - } - } - else + struct nmb_packet *nmb = &p->packet.nmb; + char *name = nmb->question.question_name.name; + int type = nmb->question.question_name.name_type; + + DEBUG(4,("response name release received\n")); + + if (nmb->header.rcode == 0 && nmb->answers->rdata) + { + struct in_addr found_ip; + putip((char*)&found_ip,&nmb->answers->rdata[2]); + + if (ip_equal(found_ip, myip)) { - DEBUG(1,("name registration for %s rejected!\n", - namestr(&nmb->question.question_name))); + remove_netbios_name(name,type,SELF,found_ip); } + } + else + { + DEBUG(1,("name registration for %s rejected!\n", + namestr(&nmb->question.question_name))); + } } @@ -333,49 +346,49 @@ reply to a name release ****************************************************************************/ void reply_name_release(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct in_addr ip; - int rcode=0; - int opcode = nmb->header.opcode; - int nb_flags = nmb->additional->rdata[0]; - BOOL bcast = nmb->header.nm_flags.bcast; - struct name_record *n; - char rdata[6]; - - putip((char *)&ip,&nmb->additional->rdata[2]); - - DEBUG(3,("Name release on name %s rcode=%d\n", + struct nmb_packet *nmb = &p->packet.nmb; + struct in_addr ip; + int rcode=0; + int opcode = nmb->header.opcode; + int nb_flags = nmb->additional->rdata[0]; + BOOL bcast = nmb->header.nm_flags.bcast; + struct name_record *n; + char rdata[6]; + + putip((char *)&ip,&nmb->additional->rdata[2]); + + DEBUG(3,("Name release on name %s rcode=%d\n", namestr(&nmb->question.question_name),rcode)); - - n = find_name_search(&nmb->question.question_name, FIND_GLOBAL, ip); - - /* XXXX under what conditions should we reject the removal?? */ - if (n && n->nb_flags == nb_flags && ip_equal(n->ip,ip)) - { - /* success = True; - rcode = 6; */ - - remove_name(n); - n = NULL; - } - - if (bcast) return; - - /*if (success)*/ - { - rdata[0] = nb_flags; - rdata[1] = 0; - putip(&rdata[2],(char *)&ip); - } - - /* Send a NAME RELEASE RESPONSE */ - reply_netbios_packet(p,nmb->header.name_trn_id,rcode,opcode, - &nmb->question.question_name, - nmb->question.question_type, - nmb->question.question_class, - 0, - rdata, 6 /*success ? 6 : 0*/); - /* XXXX reject packet never tested: cannot tell what to do */ + + n = find_name_search(&nmb->question.question_name, FIND_GLOBAL, ip); + + /* XXXX under what conditions should we reject the removal?? */ + if (n && n->nb_flags == nb_flags && ip_equal(n->ip,ip)) + { + /* success = True; + rcode = 6; */ + + remove_name(n); + n = NULL; + } + + if (bcast) return; + + /*if (success)*/ + { + rdata[0] = nb_flags; + rdata[1] = 0; + putip(&rdata[2],(char *)&ip); + } + + /* Send a NAME RELEASE RESPONSE */ + reply_netbios_packet(p,nmb->header.name_trn_id,rcode,opcode, + &nmb->question.question_name, + nmb->question.question_type, + nmb->question.question_class, + 0, + rdata, 6 /*success ? 6 : 0*/); + /* XXXX reject packet never tested: cannot tell what to do */ } @@ -384,30 +397,30 @@ response for a reg request received **************************************************************************/ void response_name_reg(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - char *name = nmb->question.question_name.name; - int type = nmb->question.question_name.name_type; - - DEBUG(4,("response name registration received!\n")); - - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - int nb_flags = nmb->answers->rdata[0]; - struct in_addr found_ip; - int ttl = nmb->answers->ttl; - enum name_source source = REGISTER; - - putip((char*)&found_ip,&nmb->answers->rdata[2]); - - if (ip_equal(found_ip, myip)) source = SELF; - - add_netbios_entry(name,type,nb_flags,ttl,source,found_ip); - } - else - { - DEBUG(1,("name registration for %s rejected!\n", - namestr(&nmb->question.question_name))); - } + struct nmb_packet *nmb = &p->packet.nmb; + char *name = nmb->question.question_name.name; + int type = nmb->question.question_name.name_type; + + DEBUG(4,("response name registration received!\n")); + + if (nmb->header.rcode == 0 && nmb->answers->rdata) + { + int nb_flags = nmb->answers->rdata[0]; + struct in_addr found_ip; + int ttl = nmb->answers->ttl; + enum name_source source = REGISTER; + + putip((char*)&found_ip,&nmb->answers->rdata[2]); + + if (ip_equal(found_ip, myip)) source = SELF; + + add_netbios_entry(name,type,nb_flags,ttl,source,found_ip); + } + else + { + DEBUG(1,("name registration for %s rejected!\n", + namestr(&nmb->question.question_name))); + } } @@ -416,92 +429,92 @@ reply to a reg request **************************************************************************/ void reply_name_reg(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - char *qname = nmb->question.question_name.name; - int name_type = nmb->question.question_name.name_type; - - BOOL bcast = nmb->header.nm_flags.bcast; - - int ttl = GET_TTL(nmb->additional->ttl); - int nb_flags = nmb->additional->rdata[0]; - BOOL group = (nb_flags&0x80); - int rcode = 0; - int opcode = nmb->header.opcode; - struct name_record *n = NULL; - int success = True; - char rdata[6]; - struct in_addr ip, from_ip; - - putip((char *)&from_ip,&nmb->additional->rdata[2]); - ip = from_ip; - - DEBUG(3,("Name registration for name %s at %s rcode=%d\n", - namestr(question),inet_ntoa(ip),rcode)); - - if (group) - { - /* apparently we should return 255.255.255.255 for group queries - (email from MS) */ - ip = *interpret_addr2("255.255.255.255"); - } - - /* see if the name already exists */ - n = find_name_search(question, FIND_GLOBAL, from_ip); - - if (n) - { - if (!group && !ip_equal(ip,n->ip) && question->name_type != 0x3) - { - if (n->source == SELF) - { - rcode = 6; - success = False; - } - else - { - n->ip = ip; - n->death_time = ttl?p->timestamp+ttl*3:0; - DEBUG(3,("%s changed owner to %s\n", - namestr(&n->name),inet_ntoa(n->ip))); - } - } - else - { - /* refresh the name */ - if (n->source != SELF) - { - n->death_time = ttl?p->timestamp + ttl*3:0; - } - } - } - else + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + char *qname = nmb->question.question_name.name; + int name_type = nmb->question.question_name.name_type; + + BOOL bcast = nmb->header.nm_flags.bcast; + + int ttl = GET_TTL(nmb->additional->ttl); + int nb_flags = nmb->additional->rdata[0]; + BOOL group = (nb_flags&0x80); + int rcode = 0; + int opcode = nmb->header.opcode; + struct name_record *n = NULL; + int success = True; + char rdata[6]; + struct in_addr ip, from_ip; + + putip((char *)&from_ip,&nmb->additional->rdata[2]); + ip = from_ip; + + DEBUG(3,("Name registration for name %s at %s rcode=%d\n", + namestr(question),inet_ntoa(ip),rcode)); + + if (group) + { + /* apparently we should return 255.255.255.255 for group queries + (email from MS) */ + ip = *interpret_addr2("255.255.255.255"); + } + + /* see if the name already exists */ + n = find_name_search(question, FIND_GLOBAL, from_ip); + + if (n) + { + if (!group && !ip_equal(ip,n->ip) && question->name_type != 0x3) { - /* add the name to our subnet/name database */ - n = add_netbios_entry(qname,name_type,nb_flags,ttl,REGISTER,ip); + if (n->source == SELF) + { + rcode = 6; + success = False; + } + else + { + n->ip = ip; + n->death_time = ttl?p->timestamp+ttl*3:0; + DEBUG(3,("%s changed owner to %s\n", + namestr(&n->name),inet_ntoa(n->ip))); + } } - - if (bcast) return; - - update_from_reg(nmb->question.question_name.name, - nmb->question.question_name.name_type, from_ip); - - /* XXXX don't know how to reject a name register: stick info in anyway - and guess that it doesn't matter if info is there! */ - /*if (success)*/ + else { - rdata[0] = nb_flags; - rdata[1] = 0; - putip(&rdata[2],(char *)&ip); + /* refresh the name */ + if (n->source != SELF) + { + n->death_time = ttl?p->timestamp + ttl*3:0; + } } - - /* Send a NAME REGISTRATION RESPONSE */ - reply_netbios_packet(p,nmb->header.name_trn_id,rcode,opcode, - &nmb->question.question_name, - nmb->question.question_type, - nmb->question.question_class, - ttl, - rdata, 6 /*success ? 6 : 0*/); + } + else + { + /* add the name to our subnet/name database */ + n = add_netbios_entry(qname,name_type,nb_flags,ttl,REGISTER,ip); + } + + if (bcast) return; + + update_from_reg(nmb->question.question_name.name, + nmb->question.question_name.name_type, from_ip); + + /* XXXX don't know how to reject a name register: stick info in anyway + and guess that it doesn't matter if info is there! */ + /*if (success)*/ + { + rdata[0] = nb_flags; + rdata[1] = 0; + putip(&rdata[2],(char *)&ip); + } + + /* Send a NAME REGISTRATION RESPONSE */ + reply_netbios_packet(p,nmb->header.name_trn_id,rcode,opcode, + &nmb->question.question_name, + nmb->question.question_type, + nmb->question.question_class, + ttl, + rdata, 6 /*success ? 6 : 0*/); } @@ -510,107 +523,107 @@ reply to a name status query ****************************************************************************/ void reply_name_status(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - char *qname = nmb->question.question_name.name; - int ques_type = nmb->question.question_name.name_type; - BOOL wildcard = (qname[0] == '*'); - char rdata[MAX_DGRAM_SIZE]; - char *countptr, *buf; - int count, names_added; - struct name_record *n; - - DEBUG(3,("Name status for name %s %s\n", + struct nmb_packet *nmb = &p->packet.nmb; + char *qname = nmb->question.question_name.name; + int ques_type = nmb->question.question_name.name_type; + BOOL wildcard = (qname[0] == '*'); + char rdata[MAX_DGRAM_SIZE]; + char *countptr, *buf; + int count, names_added; + struct name_record *n; + + DEBUG(3,("Name status for name %s %s\n", namestr(&nmb->question.question_name), inet_ntoa(p->ip))); - - /* find a name: if it's a wildcard, search the entire database. - if not, search for source SELF names only */ - n = find_name_search(&nmb->question.question_name, - wildcard ? FIND_GLOBAL : FIND_SELF, p->ip); - - if (!wildcard && (!n || n->source != SELF)) return; - - for (count=0, n = namelist ; n; n = n->next) - { - int name_type = n->name.name_type; - - if (n->source != SELF) continue; - - if (name_type >= 0x1b && name_type <= 0x20 && - ques_type >= 0x1b && ques_type <= 0x20) - { - if (!strequal(qname, n->name.name)) continue; - } - - count++; - } - - /* XXXX hack, we should calculate exactly how many will fit */ - count = MIN(count,(sizeof(rdata) - 64) / 18); - - countptr = buf = rdata; - buf += 1; - - names_added = 0; - - for (n = namelist ; n && count >= 0; n = n->next) - { - int name_type = n->name.name_type; - - if (n->source != SELF) continue; - - /* start with first bit of putting info in buffer: the name */ - - bzero(buf,18); - StrnCpy(buf,n->name.name,15); - strupper(buf); - - /* now check if we want to exclude other workgroup names - from the response. if we don't exclude them, windows clients - get confused and will respond with an error for NET VIEW */ - - if (name_type >= 0x1b && name_type <= 0x20 && - ques_type >= 0x1b && ques_type <= 0x20) - { - if (!strequal(qname, n->name.name)) continue; - } - - /* carry on putting name info in buffer */ - - buf[15] = name_type; - buf[16] = n->nb_flags; - - buf += 18; - - count--; - names_added++; - } - - if (count < 0) + + /* find a name: if it's a wildcard, search the entire database. + if not, search for source SELF names only */ + n = find_name_search(&nmb->question.question_name, + wildcard ? FIND_GLOBAL : FIND_SELF, p->ip); + + if (!wildcard && (!n || n->source != SELF)) return; + + for (count=0, n = namelist ; n; n = n->next) + { + int name_type = n->name.name_type; + + if (n->source != SELF) continue; + + if (name_type >= 0x1b && name_type <= 0x20 && + ques_type >= 0x1b && ques_type <= 0x20) { - DEBUG(3, (("too many names: missing a few!\n"))); + if (!strequal(qname, n->name.name)) continue; } - - SCVAL(countptr,0,names_added); - - /* XXXXXXX we should fill in more fields of the statistics structure */ - bzero(buf,64); + + count++; + } + + /* XXXX hack, we should calculate exactly how many will fit */ + count = MIN(count,(sizeof(rdata) - 64) / 18); + + countptr = buf = rdata; + buf += 1; + + names_added = 0; + + for (n = namelist ; n && count >= 0; n = n->next) + { + int name_type = n->name.name_type; + + if (n->source != SELF) continue; + + /* start with first bit of putting info in buffer: the name */ + + bzero(buf,18); + StrnCpy(buf,n->name.name,15); + strupper(buf); + + /* now check if we want to exclude other workgroup names + from the response. if we don't exclude them, windows clients + get confused and will respond with an error for NET VIEW */ + + if (name_type >= 0x1b && name_type <= 0x20 && + ques_type >= 0x1b && ques_type <= 0x20) { - extern int num_good_sends,num_good_receives; - SIVAL(buf,20,num_good_sends); - SIVAL(buf,24,num_good_receives); + if (!strequal(qname, n->name.name)) continue; } - - SIVAL(buf,46,0xFFB8E5); /* undocumented - used by NT */ - - buf += 64; - - /* Send a POSITIVE NAME STATUS RESPONSE */ - reply_netbios_packet(p,nmb->header.name_trn_id,0,0, - &nmb->question.question_name, - nmb->question.question_type, - nmb->question.question_class, - 0, - rdata,PTR_DIFF(buf,rdata)); + + /* carry on putting name info in buffer */ + + buf[15] = name_type; + buf[16] = n->nb_flags; + + buf += 18; + + count--; + names_added++; + } + + if (count < 0) + { + DEBUG(3, (("too many names: missing a few!\n"))); + } + + SCVAL(countptr,0,names_added); + + /* XXXXXXX we should fill in more fields of the statistics structure */ + bzero(buf,64); + { + extern int num_good_sends,num_good_receives; + SIVAL(buf,20,num_good_sends); + SIVAL(buf,24,num_good_receives); + } + + SIVAL(buf,46,0xFFB8E5); /* undocumented - used by NT */ + + buf += 64; + + /* Send a POSITIVE NAME STATUS RESPONSE */ + reply_netbios_packet(p,nmb->header.name_trn_id,0,0, + &nmb->question.question_name, + nmb->question.question_type, + nmb->question.question_class, + 0, + rdata,PTR_DIFF(buf,rdata)); } @@ -620,73 +633,73 @@ reply to a name query struct name_record *search_for_name(struct nmb_name *question, struct in_addr ip, int Time, int search) { - int name_type = question->name_type; - char *qname = question->name; - BOOL dns_type = name_type == 0x20 || name_type == 0; - - struct name_record *n; - - DEBUG(3,("Search for %s from %s - ", namestr(question), inet_ntoa(ip))); - - /* first look up name in cache */ - n = find_name_search(question,search,ip); - - /* now try DNS lookup. */ - if (!n) - { - struct in_addr dns_ip; - unsigned long a; - - /* only do DNS lookups if the query is for type 0x20 or type 0x0 */ - if (!dns_type) - { - DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n")); - return NULL; - } - - /* look it up with DNS */ - a = interpret_addr(qname); - - putip((char *)&dns_ip,(char *)&a); - - if (!a) - { - /* no luck with DNS. We could possibly recurse here XXXX */ - /* if this isn't a bcast then we should send a negative reply XXXX */ - DEBUG(3,("no recursion\n")); - add_netbios_entry(qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip); - return NULL; - } - - /* add it to our cache of names. give it 2 hours in the cache */ - n = add_netbios_entry(qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip); - - /* failed to add it? yikes! */ - if (!n) return NULL; - } - - /* is our entry already dead? */ - if (n->death_time) + int name_type = question->name_type; + char *qname = question->name; + BOOL dns_type = name_type == 0x20 || name_type == 0; + + struct name_record *n; + + DEBUG(3,("Search for %s from %s - ", namestr(question), inet_ntoa(ip))); + + /* first look up name in cache */ + n = find_name_search(question,search,ip); + + /* now try DNS lookup. */ + if (!n) + { + struct in_addr dns_ip; + unsigned long a; + + /* only do DNS lookups if the query is for type 0x20 or type 0x0 */ + if (!dns_type) { - if (n->death_time < Time) return False; + DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n")); + return NULL; } - - /* it may have been an earlier failure */ - if (n->source == DNSFAIL) + + /* look it up with DNS */ + a = interpret_addr(qname); + + putip((char *)&dns_ip,(char *)&a); + + if (!a) { - DEBUG(3,("DNSFAIL\n")); - return NULL; + /* no luck with DNS. We could possibly recurse here XXXX */ + /* if this isn't a bcast then we should send a negative reply XXXX */ + DEBUG(3,("no recursion\n")); + add_netbios_entry(qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip); + return NULL; } - - DEBUG(3,("OK %s\n",inet_ntoa(n->ip))); - - return n; + + /* add it to our cache of names. give it 2 hours in the cache */ + n = add_netbios_entry(qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip); + + /* failed to add it? yikes! */ + if (!n) return NULL; + } + + /* is our entry already dead? */ + if (n->death_time) + { + if (n->death_time < Time) return False; + } + + /* it may have been an earlier failure */ + if (n->source == DNSFAIL) + { + DEBUG(3,("DNSFAIL\n")); + return NULL; + } + + DEBUG(3,("OK %s\n",inet_ntoa(n->ip))); + + return n; } /* XXXX i think we should only do this if we are a WINS proxy if (!n && bcast) { - // now try look up the name at the primary domain controller + // now try look up the name at the primary domain controller if (*lp_domain_controller()) { struct in_addr dom_ip; @@ -729,78 +742,80 @@ with directed name queries: ****************************************************************************/ extern void reply_name_query(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - int name_type = question->name_type; - BOOL dns_type = name_type == 0x20 || name_type == 0; - BOOL bcast = nmb->header.nm_flags.bcast; - int ttl=0; - int rcode = 0; - int nb_flags = 0; - struct in_addr retip; - char rdata[6]; - - struct in_addr gp_ip = *interpret_addr2("255.255.255.255"); - BOOL success = True; - - struct name_record *n; - enum name_search search = dns_type || name_type == 0x1b ? - FIND_GLOBAL : FIND_SELF; - - DEBUG(3,("Name query ")); - - if ((n = search_for_name(question,p->ip,p->timestamp, search))) - { - /* don't respond to broadcast queries unless the query is for - a name we own or it is for a Primary Domain Controller name */ - if (bcast && n->source != SELF && name_type != 0x1b) - { - /* never reply with a negative response to broadcast queries */ - return; - } - - /* name is directed query, or it's self, or it's a PDC type name */ - ttl = n->death_time - p->timestamp; - retip = n->ip; - nb_flags = n->nb_flags; - } - else - { - if (bcast) return; /* never reply negative response to bcasts */ - success = False; - } - - /* if asking for a group name (type 0x1e) return 255.255.255.255 */ - if (ip_equal(retip, gp_ip) && name_type == 0x1e) retip = gp_ip; - - /* if the IP is 0 then substitute my IP - we should see which one is on the - right interface for the caller to do this right XXX */ - if (zero_ip(retip)) retip = myip; - - if (success) - { - rcode = 0; - DEBUG(3,("OK %s\n",inet_ntoa(retip))); - } - else - { - rcode = 3; - DEBUG(3,("UNKNOWN\n")); - } - - if (success) + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + int name_type = question->name_type; + BOOL dns_type = name_type == 0x20 || name_type == 0; + BOOL bcast = nmb->header.nm_flags.bcast; + int ttl=0; + int rcode = 0; + int nb_flags = 0; + struct in_addr retip; + char rdata[6]; + + struct in_addr gp_ip = *interpret_addr2("255.255.255.255"); + BOOL success = True; + + struct name_record *n; + enum name_search search = dns_type || name_type == 0x1b ? + FIND_GLOBAL : FIND_SELF; + + DEBUG(3,("Name query ")); + + if ((n = search_for_name(question,p->ip,p->timestamp, search))) + { + /* don't respond to broadcast queries unless the query is for + a name we own or it is for a Primary Domain Controller name */ + if (bcast && n->source != SELF && name_type != 0x1b) { - rdata[0] = nb_flags; - rdata[1] = 0; - putip(&rdata[2],(char *)&retip); + if (!lp_wins_proxy() || same_net(p->ip,n->ip,Netmask)) { + /* never reply with a negative response to broadcast queries */ + return; + } } - - reply_netbios_packet(p,nmb->header.name_trn_id,rcode,0, - &nmb->question.question_name, - nmb->question.question_type, - nmb->question.question_class, - ttl, - rdata, success ? 6 : 0); + + /* we will reply */ + ttl = n->death_time - p->timestamp; + retip = n->ip; + nb_flags = n->nb_flags; + } + else + { + if (bcast) return; /* never reply negative response to bcasts */ + success = False; + } + + /* if asking for a group name (type 0x1e) return 255.255.255.255 */ + if (ip_equal(retip, gp_ip) && name_type == 0x1e) retip = gp_ip; + + /* if the IP is 0 then substitute my IP - we should see which one is on the + right interface for the caller to do this right XXX */ + if (zero_ip(retip)) retip = myip; + + if (success) + { + rcode = 0; + DEBUG(3,("OK %s\n",inet_ntoa(retip))); + } + else + { + rcode = 3; + DEBUG(3,("UNKNOWN\n")); + } + + if (success) + { + rdata[0] = nb_flags; + rdata[1] = 0; + putip(&rdata[2],(char *)&retip); + } + + reply_netbios_packet(p,nmb->header.name_trn_id,rcode,0, + &nmb->question.question_name, + nmb->question.question_type, + nmb->question.question_class, + ttl, + rdata, success ? 6 : 0); } @@ -809,174 +824,169 @@ response from a name query ****************************************************************************/ static void response_netbios_packet(struct packet_struct *p) { - struct nmb_packet *nmb = &p->packet.nmb; - struct nmb_name *question = &nmb->question.question_name; - char *qname = question->name; - BOOL bcast = nmb->header.nm_flags.bcast; - struct name_response_record *n; - - if (nmb->answers == NULL) - { - DEBUG(3,("NMB packet response from %s (bcast=%s) - UNKNOWN\n", - inet_ntoa(p->ip), - BOOLSTR(bcast))); - return; - } - - if (nmb->answers->rr_type == NMB_STATUS) - { - DEBUG(3,("Name status ")); - } - - if (nmb->answers->rr_type == NMB_QUERY) - { - DEBUG(3,("Name query ")); - } - - if (nmb->answers->rr_type == NMB_REG) - { - DEBUG(3,("Name registration ")); - } - - if (nmb->answers->rr_type == NMB_REL) - { - DEBUG(3,("Name release ")); - } - - DEBUG(3,("response for %s from %s (bcast=%s)\n", - namestr(&nmb->answers->rr_name), - inet_ntoa(p->ip), - BOOLSTR(bcast))); - - if (!(n = find_name_query(nmb->header.name_trn_id))) - { - DEBUG(3,("unknown response (received too late or from nmblookup?)\n")); - return; - } - - n->num_msgs++; /* count number of responses received */ - - switch (n->cmd_type) - { - case MASTER_SERVER_CHECK : DEBUG(4,("MASTER_SVR_CHECK\n")); break; - case SERVER_CHECK : DEBUG(4,("SERVER_CHECK\n")); break; - case FIND_MASTER : DEBUG(4,("FIND_MASTER\n")); break; - case NAME_STATUS_MASTER_CHECK: DEBUG(4,("NAME_STAT_MST_CHK\n")); break; - case NAME_STATUS_CHECK : DEBUG(4,("NAME_STATUS_CHECK\n")); break; - case CHECK_MASTER : DEBUG(4,("CHECK_MASTER\n")); break; - case NAME_CONFIRM_QUERY : DEBUG(4,("NAME_CONFIRM_QUERY\n")); break; - default: break; - } - switch (n->cmd_type) - { - case MASTER_SERVER_CHECK: - case SERVER_CHECK: - case FIND_MASTER: - { - if (nmb->answers->rr_type == NMB_QUERY) - { - enum cmd_type cmd = (n->cmd_type == MASTER_SERVER_CHECK) ? - NAME_STATUS_MASTER_CHECK : - NAME_STATUS_CHECK; - if (n->num_msgs > 1 && !strequal(qname,n->name.name)) - { - /* one subnet, one master browser per workgroup */ - /* XXXX force an election? */ - DEBUG(1,("more than one master browser replied!\n")); - } - - /* initiate a name status check on the server that replied */ - queue_netbios_packet(ClientNMB,NMB_STATUS, cmd, - nmb->answers->rr_name.name, - nmb->answers->rr_name.name_type,0, - False,False,n->to_ip); - } - else - { - DEBUG(1,("Name query reply has wrong answer rr_type\n")); - } - break; - } + struct nmb_packet *nmb = &p->packet.nmb; + struct nmb_name *question = &nmb->question.question_name; + char *qname = question->name; + BOOL bcast = nmb->header.nm_flags.bcast; + struct name_response_record *n; + + if (nmb->answers == NULL) + { + DEBUG(3,("NMB packet response from %s (bcast=%s) - UNKNOWN\n", + inet_ntoa(p->ip), + BOOLSTR(bcast))); + return; + } + + if (nmb->answers->rr_type == NMB_STATUS) { + DEBUG(3,("Name status ")); + } - case NAME_STATUS_MASTER_CHECK: - case NAME_STATUS_CHECK: - { - if (nmb->answers->rr_type == NMB_STATUS) - { - /* NMB_STATUS arrives: contains the workgroup name - and server name we require */ - struct nmb_name name; - fstring serv_name; + if (nmb->answers->rr_type == NMB_QUERY) { + DEBUG(3,("Name query ")); + } - if (interpret_node_status(nmb->answers->rdata, - &name,0x1d,serv_name,n->to_ip)) - { - if (*serv_name) - { - sync_server(n->cmd_type,serv_name, - name.name,name.name_type, - n->to_ip); - } - } - else - { - DEBUG(1,("No 0x1d name type in interpret_node_status()\n")); - } - } - else - { - DEBUG(1,("Name status reply has wrong answer rr_type\n")); - } - break; - } + if (nmb->answers->rr_type == NMB_REG) { + DEBUG(3,("Name registration ")); + } - case CHECK_MASTER: - { - /* no action required here. it's when NO responses are received - that we need to do something (see expire_name_query_entries) */ + if (nmb->answers->rr_type == NMB_REL) { + DEBUG(3,("Name release ")); + } - DEBUG(4, ("Master browser exists for %s at %s\n", - namestr(&n->name), - inet_ntoa(n->to_ip))); - if (n->num_msgs > 1) - { - DEBUG(1,("more than one master browser!\n")); - } - if (nmb->answers->rr_type != NMB_QUERY) - { - DEBUG(1,("Name query reply has wrong answer rr_type\n")); - } - break; - } - case NAME_CONFIRM_QUERY: - { - DEBUG(4, ("Name query at WINS server: %s at %s - ", - namestr(&n->name), - inet_ntoa(n->to_ip))); - 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]); - - DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip))); - add_netbios_entry(nmb->answers->rr_name.name, - nmb->answers->rr_name.name_type, - nb_flags,GET_TTL(0),STATUS_QUERY,found_ip); - } - else - { - DEBUG(4, (" NEGATIVE RESPONSE\n")); - } + DEBUG(3,("response for %s from %s (bcast=%s)\n", + namestr(&nmb->answers->rr_name), + inet_ntoa(p->ip), + BOOLSTR(bcast))); + + if (!(n = find_name_query(nmb->header.name_trn_id))) { + DEBUG(3,("unknown response (received too late or from nmblookup?)\n")); + return; + } - break; - } - default: - { - DEBUG(0,("unknown command received in response_netbios_packet\n")); - break; - } - } + n->num_msgs++; /* count number of responses received */ + + switch (n->cmd_type) + { + case MASTER_SERVER_CHECK : DEBUG(4,("MASTER_SVR_CHECK\n")); break; + case SERVER_CHECK : DEBUG(4,("SERVER_CHECK\n")); break; + case FIND_MASTER : DEBUG(4,("FIND_MASTER\n")); break; + case NAME_STATUS_MASTER_CHECK: DEBUG(4,("NAME_STAT_MST_CHK\n")); break; + case NAME_STATUS_CHECK : DEBUG(4,("NAME_STATUS_CHECK\n")); break; + case CHECK_MASTER : DEBUG(4,("CHECK_MASTER\n")); break; + case NAME_CONFIRM_QUERY : DEBUG(4,("NAME_CONFIRM_QUERY\n")); break; + default: break; + } + switch (n->cmd_type) + { + case MASTER_SERVER_CHECK: + case SERVER_CHECK: + case FIND_MASTER: + { + if (nmb->answers->rr_type == NMB_QUERY) + { + enum cmd_type cmd = (n->cmd_type == MASTER_SERVER_CHECK) ? + NAME_STATUS_MASTER_CHECK : + NAME_STATUS_CHECK; + if (n->num_msgs > 1 && !strequal(qname,n->name.name)) + { + /* one subnet, one master browser per workgroup */ + /* XXXX force an election? */ + DEBUG(1,("more than one master browser replied!\n")); + } + + /* initiate a name status check on the server that replied */ + queue_netbios_packet(ClientNMB,NMB_STATUS, cmd, + nmb->answers->rr_name.name, + nmb->answers->rr_name.name_type,0, + False,False,n->to_ip); + } + else + { + DEBUG(1,("Name query reply has wrong answer rr_type\n")); + } + break; + } + + case NAME_STATUS_MASTER_CHECK: + case NAME_STATUS_CHECK: + { + if (nmb->answers->rr_type == NMB_STATUS) + { + /* NMB_STATUS arrives: contains the workgroup name + and server name we require */ + struct nmb_name name; + fstring serv_name; + + if (interpret_node_status(nmb->answers->rdata, + &name,0x1d,serv_name,n->to_ip)) + { + if (*serv_name) + { + sync_server(n->cmd_type,serv_name, + name.name,name.name_type, + n->to_ip); + } + } + else + { + DEBUG(1,("No 0x1d name type in interpret_node_status()\n")); + } + } + else + { + DEBUG(1,("Name status reply has wrong answer rr_type\n")); + } + break; + } + + case CHECK_MASTER: + { + /* 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\n", + namestr(&n->name), + inet_ntoa(n->to_ip))); + if (n->num_msgs > 1) + { + DEBUG(1,("more than one master browser!\n")); + } + if (nmb->answers->rr_type != NMB_QUERY) + { + DEBUG(1,("Name query reply has wrong answer rr_type\n")); + } + break; + } + case NAME_CONFIRM_QUERY: + { + DEBUG(4, ("Name query at WINS server: %s at %s - ", + namestr(&n->name), + inet_ntoa(n->to_ip))); + 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]); + + DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip))); + add_netbios_entry(nmb->answers->rr_name.name, + nmb->answers->rr_name.name_type, + nb_flags,GET_TTL(0),STATUS_QUERY,found_ip); + } + else + { + DEBUG(4, (" NEGATIVE RESPONSE\n")); + } + + break; + } + default: + { + DEBUG(0,("unknown command received in response_netbios_packet\n")); + break; + } + } } diff --git a/source3/namework.c b/source3/namework.c index 91215ec45d..ee60e9115f 100644 --- a/source3/namework.c +++ b/source3/namework.c @@ -263,12 +263,12 @@ void update_from_reg(char *name, int type, struct in_addr ip) **************************************************************************/ void add_my_domains(void) { - /* add or find domain on our local subnet, in the default workgroup */ - - if (*lp_workgroup() != '*') - { - add_domain_entry(bcast_ip,Netmask,lp_workgroup(), True); - } + /* add or find domain on our local subnet, in the default workgroup */ + + if (*lp_workgroup() != '*') + { + add_domain_entry(bcast_ip,Netmask,lp_workgroup(), True); + } } @@ -279,128 +279,128 @@ static void send_backup_list(char *work_name, struct nmb_name *src_name, int info_count, int token, int info, int name_type, struct in_addr ip) { - struct domain_record *d; - char outbuf[1024]; - char *p, *countptr, *nameptr; - int count = 0; - int i, j; - char *theirname = src_name->name; - - DEBUG(3,("Backup list of %s to %s: %s(%x) %s(%x)\n", - work_name, inet_ntoa(ip), - myname,0x20,theirname,0x0)); - - if (name_type == 0x1d) - { - DEBUG(4,("master browsers: ")); - } - else if (name_type == 0x1b) - { - DEBUG(4,("domain controllers: ")); - } - else - { - DEBUG(0,("backup request for unknown type %0x\n", name_type)); - return; - } - - bzero(outbuf,sizeof(outbuf)); - p = outbuf; - - CVAL(p,0) = 10; /* backup list response */ - p++; - - countptr = p; /* count pointer */ - - SSVAL(p,1,token); /* sender's workgroup index representation */ - SSVAL(p,3,info); /* XXXX clueless: info, usually zero */ - p += 5; - - nameptr = p; - - for (d = domainlist; d; d = d->next) + struct domain_record *d; + char outbuf[1024]; + char *p, *countptr, *nameptr; + int count = 0; + int i, j; + char *theirname = src_name->name; + + DEBUG(3,("Backup list of %s to %s: %s(%x) %s(%x)\n", + work_name, inet_ntoa(ip), + myname,0x20,theirname,0x0)); + + if (name_type == 0x1d) + { + DEBUG(4,("master browsers: ")); + } + else if (name_type == 0x1b) + { + DEBUG(4,("domain controllers: ")); + } + else + { + DEBUG(0,("backup request for unknown type %0x\n", name_type)); + return; + } + + bzero(outbuf,sizeof(outbuf)); + p = outbuf; + + CVAL(p,0) = 10; /* backup list response */ + p++; + + countptr = p; /* count pointer */ + + SSVAL(p,1,token); /* sender's workgroup index representation */ + SSVAL(p,3,info); /* XXXX clueless: info, usually zero */ + p += 5; + + nameptr = p; + + for (d = domainlist; d; d = d->next) + { + struct work_record *work; + + for (work = d->workgrouplist; work; work = work->next) { - struct work_record *work; - - for (work = d->workgrouplist; work; work = work->next) + struct server_record *s; + + if (!strequal(work->work_group, work_name)) continue; + + for (s = work->serverlist; s; s = s->next) + { + BOOL found = False; + char *n; + + if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; + + for (n = nameptr; n < p; n = skip_string(n, 1)) { - struct server_record *s; - - if (!strequal(work->work_group, work_name)) continue; - - for (s = work->serverlist; s; s = s->next) - { - BOOL found = False; - char *n; - - if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; - - for (n = nameptr; n < p; n = skip_string(n, 1)) - { - if (strequal(n, s->serv.name)) found = True; - } - - if (found) continue; /* exclude names already added */ - - /* workgroup request: include all backup browsers in the list */ - /* domain request: include all domain members in the list */ - - if ((name_type == 0x1d && (s->serv.type & MASTER_TYPE)) || - (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE))) - { - DEBUG(4, ("%s ", s->serv.name)); - - count++; - strcpy(p,s->serv.name); - strupper(p); - p = skip_string(p,1); - } - } + if (strequal(n, s->serv.name)) found = True; } - } - - if (count == 0) - { - DEBUG(4, ("none\n")); - return; - } - else - { - DEBUG(4, (" - count %d\n", count)); - } - - CVAL(countptr,0) = count; /* total number of backup browsers found */ - - { - int len = PTR_DIFF(p, outbuf); - - for (i = 0; i < len; i+= 16) - { - DEBUG(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; - DEBUG(4, ("%c", x)); - } - - DEBUG(4, (" hex ", i)); - - for (j = 0; j < 16; j++) - { - if (i+j >= len) break; - DEBUG(4, (" %02x", outbuf[i+j])); - } - - DEBUG(4, ("\n")); + + if (found) continue; /* exclude names already added */ + + /* workgroup request: include all backup browsers in the list */ + /* domain request: include all domain members in the list */ + + if ((name_type == 0x1d && (s->serv.type & MASTER_TYPE)) || + (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE))) + { + DEBUG(4, ("%s ", s->serv.name)); + + count++; + strcpy(p,s->serv.name); + strupper(p); + p = skip_string(p,1); } - + } } - send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), - myname,theirname,0x20,0,ip,myip); + } + + if (count == 0) + { + DEBUG(4, ("none\n")); + return; + } + else + { + DEBUG(4, (" - count %d\n", count)); + } + + CVAL(countptr,0) = count; /* total number of backup browsers found */ + + { + int len = PTR_DIFF(p, outbuf); + + for (i = 0; i < len; i+= 16) + { + DEBUG(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; + DEBUG(4, ("%c", x)); + } + + DEBUG(4, (" hex ", i)); + + for (j = 0; j < 16; j++) + { + if (i+j >= len) break; + DEBUG(4, (" %02x", outbuf[i+j])); + } + + DEBUG(4, ("\n")); + } + + } + send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), + myname,theirname,0x20,0,ip,myip); } @@ -410,10 +410,10 @@ static void send_backup_list(char *work_name, struct nmb_name *src_name, ******************************************************************/ BOOL same_context(struct dgram_packet *dgram) { - if (!strequal(dgram->dest_name .scope,scope )) return(True); - if ( strequal(dgram->source_name.name ,myname)) return(True); - - return(False); + if (!strequal(dgram->dest_name .scope,scope )) return(True); + if ( strequal(dgram->source_name.name ,myname)) return(True); + + return(False); } @@ -422,14 +422,14 @@ BOOL same_context(struct dgram_packet *dgram) ******************************************************************/ BOOL listening_name(struct work_record *work, struct nmb_name *n) { - if (strequal(n->name,myname) || - strequal(n->name,work->work_group) || - strequal(n->name,MSBROWSE)) - { - return(True); - } - - return(False); + if (strequal(n->name,myname) || + strequal(n->name,work->work_group) || + strequal(n->name,MSBROWSE)) + { + return(True); + } + + return(False); } @@ -450,69 +450,69 @@ BOOL listening_name(struct work_record *work, struct nmb_name *n) ******************************************************************/ static void process_announce(struct packet_struct *p,int command,char *buf) { - struct dgram_packet *dgram = &p->packet.dgram; - struct in_addr ip = dgram->header.source_ip; - struct domain_record *d = find_domain(ip); - - int update_count = CVAL(buf,0); - int ttl = IVAL(buf,1)/1000; - char *name = buf+5; - int osmajor=CVAL(buf,21); - int osminor=CVAL(buf,22); - uint32 servertype = IVAL(buf,23); - char *comment = buf+31; - struct work_record *work; - char *work_name; - char *serv_name = dgram->source_name.name; - - comment[43] = 0; - - DEBUG(3,("Announce(%d) %s(%x)",command,name,name[15])); - DEBUG(3,("%s count=%d ttl=%d OS=(%d,%d) type=%08x comment=%s\n", + struct dgram_packet *dgram = &p->packet.dgram; + struct in_addr ip = dgram->header.source_ip; + struct domain_record *d = find_domain(ip); + + int update_count = CVAL(buf,0); + int ttl = IVAL(buf,1)/1000; + char *name = buf+5; + int osmajor=CVAL(buf,21); + int osminor=CVAL(buf,22); + uint32 servertype = IVAL(buf,23); + char *comment = buf+31; + struct work_record *work; + char *work_name; + char *serv_name = dgram->source_name.name; + + comment[43] = 0; + + DEBUG(3,("Announce(%d) %s(%x)",command,name,name[15])); + DEBUG(3,("%s count=%d ttl=%d OS=(%d,%d) type=%08x comment=%s\n", namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor, servertype,comment)); - - name[15] = 0; - - if (dgram->dest_name.name_type == 0 && command == 1) - { - DEBUG(2,("Announce to nametype(0) not supported yet\n")); - return; - } - if (command == 12 && ((!strequal(dgram->dest_name.name, MSBROWSE)) || - dgram->dest_name.name_type != 0x1)) - { - DEBUG(0, ("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n", - command, inet_ntoa(ip), namestr(&dgram->dest_name))); - return; - } - - if (same_context(dgram)) return; - - if (command == 12) - { - work_name = name; - } - else - { - work_name = dgram->dest_name.name; - } - - if (!(work = find_workgroupstruct(d, work_name, False))) return; - - DEBUG(4, ("workgroup %s on %s\n", work->work_group, serv_name)); - - ttl = GET_TTL(ttl); - - /* add them to our browse list */ - add_server_entry(d,work,name,servertype,ttl,comment,True); - - /* make a selection of machines become backup browsers (1 in 10) */ - tell_become_backup(); - - /* get their browse list from them and add it to ours. */ - add_browser_entry(serv_name,dgram->dest_name.name_type, - work->work_group,30,ip); + + name[15] = 0; + + if (dgram->dest_name.name_type == 0 && command == 1) + { + DEBUG(2,("Announce to nametype(0) not supported yet\n")); + return; + } + if (command == 12 && ((!strequal(dgram->dest_name.name, MSBROWSE)) || + dgram->dest_name.name_type != 0x1)) + { + DEBUG(0, ("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n", + command, inet_ntoa(ip), namestr(&dgram->dest_name))); + return; + } + + if (same_context(dgram)) return; + + if (command == 12) + { + work_name = name; + } + else + { + work_name = dgram->dest_name.name; + } + + if (!(work = find_workgroupstruct(d, work_name, False))) return; + + DEBUG(4, ("workgroup %s on %s\n", work->work_group, serv_name)); + + ttl = GET_TTL(ttl); + + /* add them to our browse list */ + add_server_entry(d,work,name,servertype,ttl,comment,True); + + /* make a selection of machines become backup browsers (1 in 10) */ + tell_become_backup(); + + /* get their browse list from them and add it to ours. */ + add_browser_entry(serv_name,dgram->dest_name.name_type, + work->work_group,30,ip); } /******************************************************************* @@ -520,30 +520,30 @@ static void process_announce(struct packet_struct *p,int command,char *buf) ******************************************************************/ static void process_master_announce(struct packet_struct *p,char *buf) { - struct dgram_packet *dgram = &p->packet.dgram; - struct in_addr ip = dgram->header.source_ip; - struct domain_record *d = find_domain(ip); - struct domain_record *mydomain = find_domain(bcast_ip); - char *name = buf; - struct work_record *work; - name[15] = 0; - - DEBUG(3,("Master Announce from %s (%s)\n",name,inet_ntoa(ip))); - - if (same_context(dgram)) return; - - if (!d || !mydomain) return; - - if (!lp_domain_master()) return; - - for (work = mydomain->workgrouplist; work; work = work->next) + struct dgram_packet *dgram = &p->packet.dgram; + struct in_addr ip = dgram->header.source_ip; + struct domain_record *d = find_domain(ip); + struct domain_record *mydomain = find_domain(bcast_ip); + char *name = buf; + struct work_record *work; + name[15] = 0; + + DEBUG(3,("Master Announce from %s (%s)\n",name,inet_ntoa(ip))); + + if (same_context(dgram)) return; + + if (!d || !mydomain) return; + + if (!lp_domain_master()) return; + + for (work = mydomain->workgrouplist; work; work = work->next) + { + if (AM_MASTER(work)) { - if (AM_MASTER(work)) - { - /* merge browse lists with them */ - add_browser_entry(name,0x1b, work->work_group,30,ip); - } + /* merge browse lists with them */ + add_browser_entry(name,0x1b, work->work_group,30,ip); } + } } /******************************************************************* @@ -555,60 +555,60 @@ static void process_master_announce(struct packet_struct *p,char *buf) ******************************************************************/ static void process_rcv_backup_list(struct packet_struct *p,char *buf) { - struct dgram_packet *dgram = &p->packet.dgram; - struct in_addr ip = dgram->header.source_ip; - int count = CVAL(buf,0); - int Index = IVAL(buf,1); /* caller's index representing workgroup */ - char *buf1; - - DEBUG(3,("Receive Backup ack for %s from %s total=%d index=%d\n", - namestr(&dgram->dest_name), inet_ntoa(ip), - count, Index)); - - if (same_context(dgram)) return; - - if (count <= 0) return; - - /* go through the list of servers attempting to sync browse lists */ - for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count) + struct dgram_packet *dgram = &p->packet.dgram; + struct in_addr ip = dgram->header.source_ip; + int count = CVAL(buf,0); + int Index = IVAL(buf,1); /* caller's index representing workgroup */ + char *buf1; + + DEBUG(3,("Receive Backup ack for %s from %s total=%d index=%d\n", + namestr(&dgram->dest_name), inet_ntoa(ip), + count, Index)); + + if (same_context(dgram)) return; + + if (count <= 0) return; + + /* go through the list of servers attempting to sync browse lists */ + for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count) + { + struct in_addr back_ip; + struct domain_record *d; + + DEBUG(4, ("Searching for backup browser %s at %s...\n", + buf1, inet_ntoa(ip))); + + /* XXXX assume name is a DNS name NOT a netbios name. a more complete + approach is to use reply_name_query functionality to find the name */ + back_ip = *interpret_addr2(buf1); + + if (zero_ip(back_ip)) { - struct in_addr back_ip; - struct domain_record *d; - - DEBUG(4, ("Searching for backup browser %s at %s...\n", - buf1, inet_ntoa(ip))); - - /* XXXX assume name is a DNS name NOT a netbios name. a more complete - approach is to use reply_name_query functionality to find the name */ - back_ip = *interpret_addr2(buf1); - - if (zero_ip(back_ip)) - { - DEBUG(4,("Failed to find backup browser server using DNS\n")); - continue; - } - - DEBUG(4,("Found browser server at %s\n", inet_ntoa(back_ip))); - - if ((d = find_domain(back_ip))) + DEBUG(4,("Failed to find backup browser server using DNS\n")); + continue; + } + + DEBUG(4,("Found browser server at %s\n", inet_ntoa(back_ip))); + + if ((d = find_domain(back_ip))) + { + struct domain_record *d1; + for (d1 = domainlist; d1; d1 = d1->next) + { + struct work_record *work; + for (work = d1->workgrouplist; work; work = work->next) { - struct domain_record *d1; - for (d1 = domainlist; d1; d1 = d1->next) - { - struct work_record *work; - for (work = d1->workgrouplist; work; work = work->next) - { - if (work->token == Index) - { - queue_netbios_packet(ClientNMB,NMB_QUERY,SERVER_CHECK, - work->work_group,0x1d,0, - False,False,back_ip); - return; - } - } - } + if (work->token == Index) + { + queue_netbios_packet(ClientNMB,NMB_QUERY,SERVER_CHECK, + work->work_group,0x1d,0, + False,False,back_ip); + return; + } } + } } + } } /******************************************************************* @@ -676,46 +676,46 @@ static void process_send_backup_list(struct packet_struct *p,char *buf) ******************************************************************/ static void process_reset_browser(struct packet_struct *p,char *buf) { - struct dgram_packet *dgram = &p->packet.dgram; - int state = CVAL(buf,0); + struct dgram_packet *dgram = &p->packet.dgram; + int state = CVAL(buf,0); - DEBUG(1,("Diagnostic browser reset request to %s state=0x%X\n", - namestr(&dgram->dest_name), state)); + DEBUG(1,("Diagnostic browser reset request to %s state=0x%X\n", + namestr(&dgram->dest_name), state)); - /* stop being a master but still deal with being a backup browser */ - if (state & 0x1) - { - struct domain_record *d; - for (d = domainlist; d; d = d->next) - { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - if (AM_MASTER(work)) - { - become_nonmaster(d,work); - } - } - } - } - - /* totally delete all servers and start afresh */ - if (state & 0x2) + /* stop being a master but still deal with being a backup browser */ + if (state & 0x1) + { + struct domain_record *d; + for (d = domainlist; d; d = d->next) { - struct domain_record *d; - for (d = domainlist; d; d = d->next) + struct work_record *work; + for (work = d->workgrouplist; work; work = work->next) + { + if (AM_MASTER(work)) { - struct work_record *work; - for (work=d->workgrouplist;work;work=remove_workgroup(d,work)); + become_nonmaster(d,work); } - add_my_domains(); + } } - - /* stop browsing altogether. i don't think this is a good idea! */ - if (state & 0x4) + } + + /* totally delete all servers and start afresh */ + if (state & 0x2) + { + struct domain_record *d; + for (d = domainlist; d; d = d->next) { - DEBUG(1, ("ignoring request to stop being a browser. sorry!\n")); + struct work_record *work; + for (work=d->workgrouplist;work;work=remove_workgroup(d,work)); } + add_my_domains(); + } + + /* stop browsing altogether. i don't think this is a good idea! */ + if (state & 0x4) + { + DEBUG(1, ("ignoring request to stop being a browser. sorry!\n")); + } } @@ -727,31 +727,31 @@ static void process_reset_browser(struct packet_struct *p,char *buf) ******************************************************************/ 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 domain_record *d = find_domain(ip); - int token = CVAL(buf,0); - char *name = buf+1; - - name[15] = 0; - - DEBUG(3,("Announce request from %s to %s token=0x%X\n", - name,namestr(&dgram->dest_name), token)); - - if (strequal(dgram->source_name.name,myname)) return; - - if (!d) return; - - if (!ip_equal(bcast_ip, d->bcast_ip)) return; - - for (work = d->workgrouplist; work; work = work->next) + struct dgram_packet *dgram = &p->packet.dgram; + struct work_record *work; + struct in_addr ip = dgram->header.source_ip; + struct domain_record *d = find_domain(ip); + int token = CVAL(buf,0); + char *name = buf+1; + + name[15] = 0; + + DEBUG(3,("Announce request from %s to %s token=0x%X\n", + name,namestr(&dgram->dest_name), token)); + + if (strequal(dgram->source_name.name,myname)) return; + + if (!d) return; + + if (!ip_equal(bcast_ip, d->bcast_ip)) return; + + for (work = d->workgrouplist; work; work = work->next) + { + if (strequal(dgram->dest_name.name,work->work_group)) { - if (strequal(dgram->dest_name.name,work->work_group)) - { - work->needannounce = True; - } + work->needannounce = True; } + } } @@ -760,79 +760,79 @@ static void process_announce_request(struct packet_struct *p,char *buf) **************************************************************************/ 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 domain_record *d = find_domain(ip); - char *logname,*q; - char *reply_name; - BOOL add_slashes = False; - pstring outbuf; - int code,reply_code; - struct work_record *work; - - 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 (!listening_name(work, &dgram->dest_name)) - { - DEBUG(4,("Not listening to that domain\n")); - return; - } - - code = SVAL(buf,0); - switch (code) { - case 0: - { - char *machine = buf+2; - char *user = skip_string(machine,1); - logname = skip_string(user,1); - reply_code = 6; - reply_name = myname; - add_slashes = True; - DEBUG(3,("Domain login request from %s(%s) user=%s\n", + struct dgram_packet *dgram = &p->packet.dgram; + struct in_addr ip = dgram->header.source_ip; + struct domain_record *d = find_domain(ip); + char *logname,*q; + char *reply_name; + BOOL add_slashes = False; + pstring outbuf; + int code,reply_code; + struct work_record *work; + + 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 (!listening_name(work, &dgram->dest_name)) + { + DEBUG(4,("Not listening to that domain\n")); + return; + } + + code = SVAL(buf,0); + switch (code) { + case 0: + { + char *machine = buf+2; + char *user = skip_string(machine,1); + logname = skip_string(user,1); + reply_code = 6; + reply_name = myname; + add_slashes = True; + DEBUG(3,("Domain login request from %s(%s) user=%s\n", machine,inet_ntoa(p->ip),user)); - } - break; - case 7: - { - char *machine = buf+2; - logname = skip_string(machine,1); - reply_code = 7; - reply_name = lp_domain_controller(); - if (!*reply_name) { + } + break; + case 7: + { + char *machine = buf+2; + logname = skip_string(machine,1); + reply_code = 7; + reply_name = lp_domain_controller(); + if (!*reply_name) { DEBUG(3,("No domain controller configured\n")); return; - } - DEBUG(3,("GETDC request from %s(%s)\n", + } + DEBUG(3,("GETDC request from %s(%s)\n", machine,inet_ntoa(p->ip))); - } - 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 (add_slashes) { - strcpy(q,"\\\\"); - q += 2; - } - StrnCpy(q,reply_name,16); - strupper(q); - q = skip_string(q,1); - SSVAL(q,0,0xFFFF); - q += 2; - - send_mailslot_reply(logname,ClientDGRAM,outbuf,PTR_DIFF(q,outbuf), + } + 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 (add_slashes) { + strcpy(q,"\\\\"); + q += 2; + } + StrnCpy(q,reply_name,16); + strupper(q); + q = skip_string(q,1); + SSVAL(q,0,0xFFFF); + q += 2; + + send_mailslot_reply(logname,ClientDGRAM,outbuf,PTR_DIFF(q,outbuf), myname,&dgram->source_name.name[0],0x20,0,p->ip,myip); } @@ -845,60 +845,60 @@ check listening name type ****************************************************************************/ BOOL listening_type(struct packet_struct *p, int command) { - struct dgram_packet *dgram = &p->packet.dgram; - int type = dgram->dest_name.name_type; - - switch (command) - { - case 1: /* host announce */ - { - if (type != 0x0 || type != 0x20) return (False); - break; - } - - case 2: /* announce request */ - { - return (True); - break; - } - - case 8: /* election */ - { - return (True); - break; - } - - case 9: /* get backup list */ - { - return (True); - break; - } - - case 10: /* receive backup list */ - { - return (True); - break; - } - - case 12: /* domain announce */ - { - if (type != 0x1b || type != 0x1c) return (False); - break; - } - - case 13: /* master announcement */ - { - if (type != 0x1d) return (False); - break; - } + struct dgram_packet *dgram = &p->packet.dgram; + int type = dgram->dest_name.name_type; - case 15: /* local master announce */ - { - if (type != 0x1c || type != 0x1d) return (False); - break; - } - } - return (True); /* we're not dealing with unknown packet types */ + switch (command) + { + case 1: /* host announce */ + { + if (type != 0x0 || type != 0x20) return (False); + break; + } + + case 2: /* announce request */ + { + return (True); + break; + } + + case 8: /* election */ + { + return (True); + break; + } + + case 9: /* get backup list */ + { + return (True); + break; + } + + case 10: /* receive backup list */ + { + return (True); + break; + } + + case 12: /* domain announce */ + { + if (type != 0x1b || type != 0x1c) return (False); + break; + } + + case 13: /* master announcement */ + { + if (type != 0x1d) return (False); + break; + } + + case 15: /* local master announce */ + { + if (type != 0x1c || type != 0x1d) return (False); + break; + } + } + return (True); /* we're not dealing with unknown packet types */ } @@ -907,123 +907,123 @@ process a browse frame ****************************************************************************/ void process_browse_packet(struct packet_struct *p,char *buf,int len) { - int command = CVAL(buf,0); - switch (command) - { - case 1: /* host announce */ - case 12: /* domain announce */ - case 15: /* local master announce */ - { - process_announce(p,command,buf+1); - break; - } - - case 2: /* announce request */ - { - process_announce_request(p,buf+1); - break; - } - - case 8: /* election */ - { - process_election(p,buf+1); - break; - } - - case 9: /* get backup list */ - { - process_send_backup_list(p,buf+1); - break; - } - - case 10: /* receive backup list */ - { + int command = CVAL(buf,0); + switch (command) + { + case 1: /* host announce */ + case 12: /* domain announce */ + case 15: /* local master announce */ + { + process_announce(p,command,buf+1); + break; + } + + case 2: /* announce request */ + { + process_announce_request(p,buf+1); + break; + } + + case 8: /* election */ + { + process_election(p,buf+1); + break; + } + + case 9: /* get backup list */ + { + process_send_backup_list(p,buf+1); + break; + } + + case 10: /* receive backup list */ + { #ifdef TEST_CODE - struct dgram_packet *dgram = &p->packet.dgram; - int i, j; - - DEBUG(4, ("ignoring browse packet %d from %s %s to %s\n", - command, namestr(&dgram->source_name), - inet_ntoa(p->ip), namestr(&dgram->dest_name))); - - for (i = 0; i < len; i+= 16) - { - DEBUG(4, ("%3x char ", i)); - - for (j = 0; j < 16; j++) - { - unsigned char x = buf[i+j]; - if (x < 32 || x > 127) x = '.'; - - if (i+j >= len) break; - DEBUG(4, ("%c", x)); - } - - DEBUG(4, (" hex ", i)); - - for (j = 0; j < 16; j++) - { - if (i+j >= len) break; - DEBUG(4, (" %02x", buf[i+j])); - } - - DEBUG(4, ("\n")); - } - + struct dgram_packet *dgram = &p->packet.dgram; + int i, j; + + DEBUG(4, ("ignoring browse packet %d from %s %s to %s\n", + command, namestr(&dgram->source_name), + inet_ntoa(p->ip), namestr(&dgram->dest_name))); + + for (i = 0; i < len; i+= 16) + { + DEBUG(4, ("%3x char ", i)); + + for (j = 0; j < 16; j++) + { + unsigned char x = buf[i+j]; + if (x < 32 || x > 127) x = '.'; + + if (i+j >= len) break; + DEBUG(4, ("%c", x)); + } + + DEBUG(4, (" hex ", i)); + + for (j = 0; j < 16; j++) + { + if (i+j >= len) break; + DEBUG(4, (" %02x", buf[i+j])); + } + + DEBUG(4, ("\n")); + } + #endif /* TEST_CODE */ - process_rcv_backup_list(p, buf+1); - break; - } - - case 11: /* reset browser state */ - { - process_reset_browser(p, buf+1); - break; - } - - case 13: /* master announcement */ - { - process_master_announce(p,buf+1); - break; - } - + process_rcv_backup_list(p, buf+1); + break; + } + + case 11: /* reset browser state */ + { + process_reset_browser(p, buf+1); + break; + } + + case 13: /* master announcement */ + { + process_master_announce(p,buf+1); + break; + } + #ifdef TEST_CODE - default: - { - struct dgram_packet *dgram = &p->packet.dgram; - int i, j; - - DEBUG(4, ("ignoring browse packet %d from %s %s to %s\n", - command, namestr(&dgram->source_name), - inet_ntoa(p->ip), namestr(&dgram->dest_name))); - - for (i = 0; i < len; i+= 16) - { - DEBUG(4, ("%3x char ", i)); - - for (j = 0; j < 16; j++) - { - unsigned char x = buf[i+j]; - if (x < 32 || x > 127) x = '.'; - - if (i+j >= len) break; - DEBUG(4, ("%c", x)); - } - - DEBUG(4, (" hex ", i)); - - for (j = 0; j < 16; j++) - { - if (i+j >= len) break; - DEBUG(4, (" %02x", buf[i+j])); - } - - DEBUG(4, ("\n")); - } - - } + default: + { + struct dgram_packet *dgram = &p->packet.dgram; + int i, j; + + DEBUG(4, ("ignoring browse packet %d from %s %s to %s\n", + command, namestr(&dgram->source_name), + inet_ntoa(p->ip), namestr(&dgram->dest_name))); + + for (i = 0; i < len; i+= 16) + { + DEBUG(4, ("%3x char ", i)); + + for (j = 0; j < 16; j++) + { + unsigned char x = buf[i+j]; + if (x < 32 || x > 127) x = '.'; + + if (i+j >= len) break; + DEBUG(4, ("%c", x)); + } + + DEBUG(4, (" hex ", i)); + + for (j = 0; j < 16; j++) + { + if (i+j >= len) break; + DEBUG(4, (" %02x", buf[i+j])); + } + + DEBUG(4, ("\n")); + } + + } #endif /* TEST_CODE */ - } + } } diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index 222ab3f921..b6ef717cc0 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -144,15 +144,15 @@ static void fault_continue(void) ******************************************************************/ static void expire_names_and_servers(void) { - static time_t lastrun = 0; - time_t t = time(NULL); - - if (!lastrun) lastrun = t; - if (t < lastrun + 5) return; - lastrun = t; - - expire_names(t); - expire_servers(t); + static time_t lastrun = 0; + time_t t = time(NULL); + + if (!lastrun) lastrun = t; + if (t < lastrun + 5) return; + lastrun = t; + + expire_names(t); + expire_servers(t); } /***************************************************************************** @@ -285,6 +285,7 @@ static void process(void) while (True) { + time_t t = time(NULL); run_election = check_elections(); listen_for_packets(run_election); @@ -296,7 +297,8 @@ static void process(void) announce_master(); expire_names_and_servers(); - expire_netbios_response_entries(time(NULL)-10); + expire_netbios_response_entries(t-10); + refresh_my_names(t); write_browse_list(); do_browser_lists(); diff --git a/source3/nmbsync.c b/source3/nmbsync.c index 5a6c07086a..c3e3f43e51 100644 --- a/source3/nmbsync.c +++ b/source3/nmbsync.c @@ -58,78 +58,78 @@ adds information retrieved from a NetServerEnum call ****************************************************************************/ static BOOL add_info(struct domain_record *d, struct work_record *work, int servertype) { - char *rparam = NULL; - char *rdata = NULL; - int rdrcnt,rprcnt; - char *p; - pstring param; - int uLevel = 1; - int count = -1; - - /* now send a SMBtrans command with api ServerEnum? */ - p = param; - SSVAL(p,0,0x68); /* api number */ - p += 2; - strcpy(p,"WrLehDz"); - p = skip_string(p,1); - - strcpy(p,"B16BBDz"); - - p = skip_string(p,1); - SSVAL(p,0,uLevel); - SSVAL(p,2,0x2000); /* buf length */ - p += 4; - SIVAL(p,0,servertype); - p += 4; - - strcpy(p, work->work_group); - p = skip_string(p,1); - - if (cli_call_api(PTR_DIFF(p,param),0, 8,10000, - &rprcnt,&rdrcnt, param,NULL, - &rparam,&rdata)) + char *rparam = NULL; + char *rdata = NULL; + int rdrcnt,rprcnt; + char *p; + pstring param; + int uLevel = 1; + int count = -1; + + /* now send a SMBtrans command with api ServerEnum? */ + p = param; + SSVAL(p,0,0x68); /* api number */ + p += 2; + strcpy(p,"WrLehDz"); + p = skip_string(p,1); + + strcpy(p,"B16BBDz"); + + p = skip_string(p,1); + SSVAL(p,0,uLevel); + SSVAL(p,2,0x2000); /* buf length */ + p += 4; + SIVAL(p,0,servertype); + p += 4; + + strcpy(p, work->work_group); + p = skip_string(p,1); + + if (cli_call_api(PTR_DIFF(p,param),0, 8,10000, + &rprcnt,&rdrcnt, param,NULL, + &rparam,&rdata)) + { + int res = SVAL(rparam,0); + int converter=SVAL(rparam,2); + int i; + + if (res == 0) { - int res = SVAL(rparam,0); - int converter=SVAL(rparam,2); - int i; - - if (res == 0) + count=SVAL(rparam,4); + p = rdata; + + for (i = 0;i < count;i++, p += 26) + { + char *sname = p; + uint32 stype = IVAL(p,18); + int comment_offset = IVAL(p,22) & 0xFFFF; + char *cmnt = comment_offset?(rdata+comment_offset-converter):""; + + struct work_record *w = work; + + DEBUG(4, ("\t%-16.16s %08x %s\n", sname, stype, cmnt)); + + if (stype & SV_TYPE_DOMAIN_ENUM) { - count=SVAL(rparam,4); - p = rdata; - - for (i = 0;i < count;i++, p += 26) + /* creates workgroup on remote subnet */ + if ((w = find_workgroupstruct(d,sname, False))) + { + if (ip_equal(bcast_ip, d->bcast_ip)) { - char *sname = p; - uint32 stype = IVAL(p,18); - int comment_offset = IVAL(p,22) & 0xFFFF; - char *cmnt = comment_offset?(rdata+comment_offset-converter):""; - - struct work_record *w = work; - - DEBUG(4, ("\t%-16.16s %08x %s\n", sname, stype, cmnt)); - - if (stype & SV_TYPE_DOMAIN_ENUM) - { - /* creates workgroup on remote subnet */ - if ((w = find_workgroupstruct(d,sname, False))) - { - if (ip_equal(bcast_ip, d->bcast_ip)) - { - announce_request(w, d->bcast_ip); - } - } - } - - add_server_entry(d,w,sname,stype,lp_max_ttl(),cmnt,False); + announce_request(w, d->bcast_ip); } + } } + + add_server_entry(d,w,sname,stype,lp_max_ttl(),cmnt,False); + } } - - if (rparam) free(rparam); - if (rdata) free(rdata); - - return(True); + } + + if (rparam) free(rparam); + if (rdata) free(rdata); + + return(True); } diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 1e488ec90d..bbeb4801d5 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -149,6 +149,7 @@ typedef struct int os_level; int max_ttl; BOOL bWINSsupport; + BOOL bWINSproxy; BOOL bPreferredMaster; BOOL bDomainMaster; BOOL bDomainLogons; @@ -163,7 +164,6 @@ typedef struct BOOL bReadbmpx; BOOL bSyslogOnly; BOOL bBrowseList; - BOOL bProxyNameResolution; } global; static global Globals; @@ -414,13 +414,13 @@ struct parm_struct {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL}, {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL}, {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL}, + {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL}, {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL}, {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL}, {"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL}, {"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL}, {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL}, {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL}, - {"proxy name resolution",P_BOOL,P_GLOBAL,&Globals.bProxyNameResolution,NULL}, {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL}, {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL}, @@ -578,8 +578,8 @@ static void init_globals(void) Globals.bDomainMaster = False; Globals.bDomainLogons = False; Globals.bBrowseList = True; - Globals.bProxyNameResolution = True; Globals.bWINSsupport = True; + Globals.bWINSproxy = False; #ifdef KANJI coding_system = interpret_coding_system (KANJI, SJIS_CODE); @@ -706,6 +706,7 @@ FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript) FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver) FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport) +FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy) FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster) FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons) FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster) @@ -721,7 +722,6 @@ FN_GLOBAL_BOOL(lp_strip_dot,&Globals.bStripDot) FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords) FN_GLOBAL_BOOL(lp_syslog_only,&Globals.bSyslogOnly) FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList) -FN_GLOBAL_BOOL(lp_proxy_name_resolution,&Globals.bProxyNameResolution) FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level) FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl) |