summaryrefslogtreecommitdiffstats
path: root/source/namework.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/namework.c')
-rw-r--r--source/namework.c733
1 files changed, 0 insertions, 733 deletions
diff --git a/source/namework.c b/source/namework.c
deleted file mode 100644
index ff623e69dbf..00000000000
--- a/source/namework.c
+++ /dev/null
@@ -1,733 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Revision History:
-
- 14 jan 96: lkcl@pires.co.uk
- added multiple workgroup domain master support
-
-*/
-
-#include "includes.h"
-
-extern int ClientNMB;
-extern int ClientDGRAM;
-
-#define TEST_CODE /* want to debug unknown browse packets */
-
-extern int DEBUGLEVEL;
-extern pstring scope;
-extern BOOL CanRecurse;
-
-extern pstring myname;
-extern fstring myworkgroup;
-
-extern int ClientNMB;
-extern int ClientDGRAM;
-
-extern struct in_addr ipzero;
-
-extern int workgroup_count; /* total number of workgroups we know about */
-
-/* this is our domain/workgroup/server database */
-extern struct subnet_record *subnetlist;
-
-extern int updatecount;
-
-/* backup request types: which servers are to be included */
-#define MASTER_TYPE (SV_TYPE_MASTER_BROWSER)
-#define DOMCTL_TYPE (SV_TYPE_DOMAIN_CTRL )
-
-extern time_t StartupTime;
-
-extern BOOL updatedlists;
-
-/****************************************************************************
-tell a server to become a backup browser
-state - 0x01 become backup instead of master
- - 0x02 remove all entries in browse list and become non-master
- - 0x04 stop master browser service altogether. NT ignores this
-**************************************************************************/
-void reset_server(char *name, int state, struct in_addr ip)
-{
- char outbuf[20];
- char *p;
-
- bzero(outbuf,sizeof(outbuf));
- p = outbuf;
-
- CVAL(p,0) = ANN_ResetBrowserState;
- CVAL(p,2) = state;
- p += 2;
-
- DEBUG(2,("sending reset to %s %s of state %d\n",
- name,inet_ntoa(ip),state));
-
- send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
- outbuf,PTR_DIFF(p,outbuf),
- myname,name,0x20,0x1d,ip,*iface_ip(ip));
-}
-
-
-/****************************************************************************
-tell a server to become a backup browser
-**************************************************************************/
-void tell_become_backup(void)
-{
- /* XXXX note: this function is currently unsuitable for use, as it
- does not properly check that a server is in a fit state to become
- a backup browser before asking it to be one.
- */
-
- struct subnet_record *d;
- for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
- {
- struct work_record *work;
- for (work = d->workgrouplist; work; work = work->next)
- {
- struct server_record *s;
- int num_servers = 0;
- int num_backups = 0;
-
- for (s = work->serverlist; s; s = s->next)
- {
- if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
-
- num_servers++;
-
- if (strequal(myname, s->serv.name)) continue;
-
- if (s->serv.type & SV_TYPE_BACKUP_BROWSER) {
- num_backups++;
- continue;
- }
-
- if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue;
-
- if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue;
-
- DEBUG(3,("num servers: %d num backups: %d\n",
- num_servers, num_backups));
-
- /* make first server a backup server. thereafter make every
- tenth server a backup server */
- if (num_backups != 0 && (num_servers+9) / num_backups > 10)
- {
- continue;
- }
-
- DEBUG(2,("sending become backup to %s %s for %s\n",
- s->serv.name, inet_ntoa(d->bcast_ip),
- work->work_group));
-
- /* type 11 request from MYNAME(20) to WG(1e) for SERVER */
- do_announce_request(s->serv.name, work->work_group,
- ANN_BecomeBackup, 0x20, 0x1e, d->bcast_ip);
- }
- }
- }
-}
-
-
-/*******************************************************************
- same context: scope. should check name_type as well, and makes sure
- we don't process messages from ourselves
- ******************************************************************/
-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);
-}
-
-
-/*******************************************************************
- process a domain announcement frame
-
- Announce frames come in 3 types. Servers send host announcements
- (command=1) to let the master browswer know they are
- available. Master browsers send local master announcements
- (command=15) to let other masters and backups that they are the
- master. They also send domain announcements (command=12) to register
- the domain
-
- The comment field of domain announcements contains the master
- browser name. The servertype is used by NetServerEnum to select
- resources. We just have to pass it to smbd (via browser.dat) and let
- the client choose using bit masks.
- ******************************************************************/
-static void process_localnet_announce(struct packet_struct *p,uint16 command,char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- struct subnet_record *d = find_subnet(p->ip); /* Explicitly exclude WINS - local nets only */
- 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);
- uint32 browse_type= CVAL(buf,27);
- uint32 browse_sig = CVAL(buf,29);
- char *comment = buf+31;
-
- struct work_record *work;
- char *work_name;
- char *serv_name = dgram->source_name.name;
- BOOL add = False;
-
- comment[43] = 0;
-
- DEBUG(4,("Announce(%d) %s(%x)",command,name,name[15]));
- DEBUG(4,("%s count=%d ttl=%d OS=(%d,%d) type=%08x sig=%4x %4x comment=%s\n",
- namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor,
- servertype,browse_type,browse_sig,comment));
-
- name[15] = 0;
-
- if (dgram->dest_name.name_type == 0 && command == ANN_HostAnnouncement)
- {
- DEBUG(2,("Announce to nametype(0) not supported yet\n"));
- return;
- }
-
- if (command == ANN_DomainAnnouncement &&
- ((!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(p->ip), namestr(&dgram->dest_name)));
- return;
- }
-
- if (!strequal(dgram->dest_name.scope,scope )) return;
-
- if (command == ANN_DomainAnnouncement) {
- /* XXXX if we are a master browser for the workgroup work_name,
- then there is a local subnet configuration problem. only
- we should be sending out such domain announcements, because
- as the master browser, that is our job.
-
- stop being a master browser, and force an election. this will
- sort out the network problem. hopefully.
- */
-
- work_name = name;
- add = True;
- } else {
- work_name = dgram->dest_name.name;
- }
-
- /* we need some way of finding out about new workgroups
- that appear to be sending packets to us. The name_type checks make
- sure we don't add host names as workgroups */
- if (command == ANN_HostAnnouncement &&
- (dgram->dest_name.name_type == 0x1d ||
- dgram->dest_name.name_type == 0x1e))
- add = True;
-
- DEBUG(4,("search for workgroup: %s (add? %s)\n",
- work_name, BOOLSTR(add)));
-
- if (!(work = find_workgroupstruct(d, work_name,add)))
- return;
-
- DEBUG(4, ("workgroup %s on %s\n", work->work_group, serv_name));
-
- ttl = GET_TTL(ttl);
-
- /* add them to our browse list, and update the browse.dat file */
- add_server_entry(d,work,name,servertype|SV_TYPE_LOCAL_LIST_ONLY,ttl,comment,True);
- updatedlists = True;
-
-#if 0
- /* the tell become backup code is broken, no great harm is done by
- disabling it */
- tell_become_backup();
-#endif
-
-#if 0 /* JRA TEST - I Think this code should not be here */
- /* get the local_only browse list from the local master and add it
- to ours. */
- if (command == ANN_LocalMasterAnnouncement)
- {
- add_browser_entry(serv_name,dgram->dest_name.name_type,
- work->work_group,30,p->ip,True);
- }
-#endif /* END JRA TEST */
-}
-
-/*******************************************************************
- process a master announcement frame
- Domain master browsers recieve these from local masters. The Domain
- master should then issue a sync with the local master, asking for
- that machines local server list.
- ******************************************************************/
-static void process_master_announce(struct packet_struct *p,char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- char *name = buf;
- struct work_record *work;
- name[15] = 0;
-
- DEBUG(3,("process_master_announce: Master Announce from %s (%s)\n",name,inet_ntoa(p->ip)));
-
- if (same_context(dgram)) return;
-
- if (!wins_subnet)
- {
- DEBUG(3,("process_master_announce: No wins subnet !\n"));
- return;
- }
-
- if (!lp_domain_master())
- {
- DEBUG(3,("process_master_announce: Not configured as domain master - ignoring master announce.\n"));
- return;
- }
-
- for (work = wins_subnet->workgrouplist; work; work = work->next)
- {
- if (AM_MASTER(work) || AM_DOMMST(work))
- {
- /* merge browse lists with them */
- add_browser_entry(name,0x1d, work->work_group,30,wins_subnet,p->ip,True);
- }
- }
-}
-
-/*******************************************************************
- process a receive backup list request
-
- we receive a list of servers, and we attempt to locate them all on
- our local subnet, and sync browse lists with them on the workgroup
- they are said to be in.
-
- XXXX NOTE: this function is in overdrive. it should not really do
- half of what it actually does (it should pick _one_ name from the
- list received and sync with it at regular intervals, rather than
- sync with them all only once!)
-
- ******************************************************************/
-static void process_rcv_backup_list(struct packet_struct *p,char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int count = CVAL(buf,0);
- uint32 info = IVAL(buf,1); /* XXXX caller's incremental info */
- char *buf1;
-
- DEBUG(3,("Receive Backup ack for %s from %s total=%d info=%d\n",
- namestr(&dgram->dest_name), inet_ntoa(p->ip),
- count, info));
-
- 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 subnet_record *d; */
-
- DEBUG(4,("Searching for backup browser %s at %s...\n",
- buf1, inet_ntoa(p->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)));
- DEBUG(4,("END THIS LOOP: CODE NEEDS UPDATING\n"));
-
-#if 0
- /* XXXX function needs work */
- continue;
-
- if ((d = find_subnet(back_ip)))
- {
- struct subnet_record *d1;
- for (d1 = subnetlist; d1; d1 = d1->next)
- {
- struct work_record *work;
- for (work = d1->workgrouplist; work; work = work->next)
- {
- if (work->token == 0 /* token */)
- {
- queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK,
- work->work_group,0x1d,
- 0,0,0,NULL,NULL,
- False,False,back_ip,back_ip);
- return;
- }
- }
- }
- }
-#endif
- }
-}
-
-
-/****************************************************************************
- send a backup list response.
- **************************************************************************/
-static void send_backup_list(char *work_name, struct nmb_name *src_name,
- int token, uint32 info,
- int name_type, struct in_addr ip)
-{
- char outbuf[1024];
- char *p, *countptr, *nameptr;
- int count = 0;
- char *theirname = src_name->name;
-
- DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n",
- work_name, inet_ntoa(ip),
- myname,0x0,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) = ANN_GetBackupListResp; /* backup list response */
-
- p++;
- countptr = p;
-
- SIVAL(p,1,info); /* the sender's unique info */
-
- p += 5;
-
- nameptr = p;
-
-#if 0
-
- for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
- {
- 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))
- {
- 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);
- }
- }
- }
- }
-
-#endif
-
- count++;
- strcpy(p,myname);
- strupper(p);
- p = skip_string(p,1);
-
- if (count == 0)
- {
- DEBUG(4, ("none\n"));
- }
- else
- {
- DEBUG(4, (" - count %d\n", count));
- }
-
- CVAL(countptr, 0) = count;
-
- {
- int len = PTR_DIFF(p, outbuf);
- debug_browse_data(outbuf, len);
- }
- send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
- outbuf,PTR_DIFF(p,outbuf),
- myname,theirname,0x0,0x0,ip,*iface_ip(ip));
-}
-
-
-/*******************************************************************
- process a send backup list request
-
- A client sends a backup list request to ask for a list of servers on
- the net that maintain server lists for a domain. A server is then
- chosen from this list to send NetServerEnum commands to to list
- available servers.
-
- Currently samba only sends back one name in the backup list, its
- own. For larger nets we'll have to add backups and send "become
- backup" requests occasionally.
- ******************************************************************/
-static void process_send_backup_list(struct packet_struct *p,char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- struct in_addr ip = dgram->header.source_ip;
- struct subnet_record *d;
- struct work_record *work;
-
- int token = CVAL(buf,0); /* sender's key index for the workgroup */
- uint32 info = IVAL(buf,1); /* XXXX don't know: some sort of info */
- int name_type = dgram->dest_name.name_type;
-
- if (same_context(dgram)) return;
-
- if (name_type != 0x1b && name_type != 0x1d) {
- DEBUG(0,("backup request to wrong type %d from %s\n",
- name_type,inet_ntoa(ip)));
- return;
- }
-
- for (d = subnetlist; d; d = d->next)
- {
- for (work = d->workgrouplist; work; work = work->next)
- {
- if (strequal(work->work_group, dgram->dest_name.name))
- {
- DEBUG(2,("sending backup list to %s %s id=%x\n",
- namestr(&dgram->dest_name),inet_ntoa(ip),info));
-
- send_backup_list(work->work_group,&dgram->source_name,
- token,info,name_type,ip);
- return;
- }
- }
- }
-}
-
-
-/*******************************************************************
- process a reset browser state
-
- diagnostic packet:
- 0x1 - stop being a master browser and become a backup browser.
- 0x2 - discard browse lists, stop being a master browser, try again.
- 0x4 - stop being a master browser forever. no way. ain't gonna.
-
- ******************************************************************/
-static void process_reset_browser(struct packet_struct *p,char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int state = CVAL(buf,0);
-
- DEBUG(1,("received 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 subnet_record *d;
- for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
- {
- struct work_record *work;
- for (work = d->workgrouplist; work; work = work->next)
- {
- if (AM_MASTER(work))
- {
- unbecome_local_master(d,work,SV_TYPE_MASTER_BROWSER);
- }
- }
- }
- }
-
- /* XXXX documentation inconsistency: the above description does not
- exactly tally with what is implemented for state & 0x2
- */
-
- /* totally delete all servers and start afresh */
- if (state & 0x2)
- {
- struct subnet_record *d;
- for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
- {
- struct work_record *work;
- for (work=d->workgrouplist;work;work=remove_workgroup(d,work,True));
- }
- add_my_subnets(myworkgroup);
- }
-
- /* 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"));
- }
-}
-
-/*******************************************************************
- process a announcement request
-
- clients send these when they want everyone to send an announcement
- immediately. This can cause quite a storm of packets!
- ******************************************************************/
-static void process_announce_request(struct packet_struct *p,char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- struct work_record *work;
- struct in_addr ip = dgram->header.source_ip;
- struct subnet_record *d = find_subnet(ip); /* Explicitly NO WINS */
- int token = CVAL(buf,0);
- char *name = buf+1;
-
- name[15] = 0;
-
- DEBUG(3,("process_announce_request: Announce request from %s to %s token=0x%X\n",
- name,namestr(&dgram->dest_name), token));
-
- if (strequal(dgram->source_name.name,myname)) return;
-
- /* XXXX BUG or FEATURE?: need to ensure that we are a member of
- this workgroup before announcing, particularly as we only
- respond on local interfaces anyway.
-
- if (strequal(dgram->dest_name, myworkgroup) return; ???
- */
-
- if (!d)
- {
- DEBUG(3,("process_announce_request: No local interface to announce to %s\n",
- name));
- return;
- }
-
- for (work = d->workgrouplist; work; work = work->next)
- {
- /* XXXX BUG: the destination name type should also be checked,
- not just the name. e.g if the name is WORKGROUP(0x1d) then
- we should only respond if we own that name */
-
- if (strequal(dgram->dest_name.name,work->work_group))
- {
- work->needannounce = True;
- }
- }
-}
-
-
-
-/****************************************************************************
-process a browse frame
-****************************************************************************/
-void process_browse_packet(struct packet_struct *p,char *buf,int len)
-{
- int command = CVAL(buf,0);
- switch (command)
- {
- case ANN_HostAnnouncement:
- case ANN_DomainAnnouncement:
- case ANN_LocalMasterAnnouncement:
- {
- debug_browse_data(buf, len);
- process_localnet_announce(p,command,buf+1);
- break;
- }
-
- case ANN_AnnouncementRequest:
- {
- process_announce_request(p,buf+1);
- break;
- }
-
- case ANN_Election:
- {
- process_election(p,buf+1);
- break;
- }
-
- case ANN_GetBackupListReq:
- {
- debug_browse_data(buf, len);
- process_send_backup_list(p,buf+1);
- break;
- }
-
- case ANN_GetBackupListResp:
- {
- debug_browse_data(buf, len);
- process_rcv_backup_list(p, buf+1);
- break;
- }
-
- case ANN_ResetBrowserState:
- {
- process_reset_browser(p, buf+1);
- break;
- }
-
- case ANN_MasterAnnouncement:
- {
- process_master_announce(p,buf+1);
- break;
- }
-
- default:
- {
- struct dgram_packet *dgram = &p->packet.dgram;
- 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)));
- }
- }
-}
-
-