1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-10 12:58:35 +03:00

- a huge pile of changes from Luke which implement the browse.conf

stuff and also fix a pile of nmbd bugs. Unfortunately I found it very
hard to disentangle the new features from the bug fixes so I am
putting in the new code. I hope this is the last big pile of changes
to the 1.9.16 series!
(This used to be commit 20b6203dac4bbb43e4e7bea0b214496d76d679d9)
This commit is contained in:
Andrew Tridgell 1996-10-02 14:09:22 +00:00
parent 11d9539d75
commit 5a2f52b79e
32 changed files with 2498 additions and 2036 deletions

@ -3787,10 +3787,12 @@ static BOOL list_servers(char *wk_grp)
for (i=0;i<count;i++) {
char *sname = p2;
uint32 stype = IVAL(p2,18);
int comment_offset = IVAL(p2,22) & 0xFFFF;
printf("\t%-16.16s %s\n",
printf("\t%-16.16s %s (%8x)\n",
sname,
comment_offset?rdata+comment_offset-converter:"");
comment_offset?rdata+comment_offset-converter:"",
stype);
ok=True;
p2 += 26;
@ -3826,10 +3828,12 @@ static BOOL list_servers(char *wk_grp)
for (i=0;i<count;i++) {
char *sname = p2;
uint32 stype = IVAL(p2,18);
int comment_offset = IVAL(p2,22) & 0xFFFF;
printf("\t%-16.16s %s\n",
printf("\t%-16.16s %s (%8x)\n",
sname,
comment_offset?rdata+comment_offset-converter:"");
comment_offset?rdata+comment_offset-converter:"",
stype);
ok=True;
p2 += 26;

@ -374,7 +374,7 @@ static long unoct(char *p, int ndgs)
/****************************************************************************
Compare two strings in a slash insensitive way
***************************************************************************/
int strslashcmp(const char *s1, const char *s2)
int strslashcmp(char *s1,char *s2)
{
while(*s1 && *s2 &&
(*s1 == *s2

@ -54,6 +54,19 @@
#define NB_HFLAG 0x60 /* microsoft 'hybrid' node type */
#define NB_FLGMSK 0x60
#define WG_BROWSE_SIGNATURE 0x017e
#define WG_BROWSE_VERSION 0xff08
#define HOST_BROWSE_SIGNATURE 0xaa55
#define HOST_BROWSE_VERSION 0x010f
#define WG_MAJOR_VERSION 0x03
#define WG_MINOR_VERSION 0x0a
#define HOST_MAJOR_VERSION 0x04 /* nt/as host version */
#define HOST_MINOR_VERSION 0x01 /* one better than current nt/as version */
#define REFRESH_TIME (15*60)
#define NAME_POLL_REFRESH_TIME (5*60)
#define NAME_POLL_INTERVAL 15
@ -73,7 +86,7 @@
/* server type identifiers */
#define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER)
#define AM_BACKUP(work) (work->ServerType & SV_TYPE_BACKUP_BROWSER)
#define AM_DOMCTL(work) (work->ServerType & SV_TYPE_DOMAIN_CTRL)
#define AM_DMBRSE(work) (work->ServerType & SV_TYPE_DOMAIN_MASTER)
/* microsoft browser NetBIOS name */
#define MSBROWSE "\001\002__MSBROWSE__\002"
@ -121,6 +134,14 @@ struct nmb_name {
int name_type;
};
/* A server name and comment. */
struct server_identity
{
char *name;
char *comment;
struct server_identity *next;
};
/* a netbios flags + ip address structure */
/* this is used for multi-homed systems and for internet group names */
struct nmb_ip
@ -151,9 +172,9 @@ struct browse_cache_record
struct browse_cache_record *next;
struct browse_cache_record *prev;
pstring name;
char name[17];
int type;
pstring group;
char group[17];
struct in_addr ip;
time_t sync_time;
BOOL synced;
@ -183,7 +204,7 @@ struct work_record
enum master_state state;
/* work group info */
fstring work_group;
char work_group[17];
int token; /* used when communicating with backup browsers */
int ServerType;
@ -214,17 +235,18 @@ struct response_record
int fd;
int quest_type;
struct nmb_name name;
int nb_flags;
struct nmb_ip reply;
time_t ttl;
enum name_source source;
int token; /* unique workgroup token id */
int server_type;
fstring my_name;
fstring my_comment;
char my_name[17];
char my_comment[50];
BOOL bcast;
BOOL recurse;
struct in_addr send_ip;
struct in_addr reply_to_ip;
int num_msgs;

@ -51,7 +51,7 @@ char *smb_errstr(char *inbuf);
/*The following definitions come from clitar.c */
int strslashcmp(const char *s1, const char *s2);
int strslashcmp(char *s1,char *s2);
void cmd_block(void);
void cmd_tarmode(void);
void cmd_setmode(void);
@ -124,6 +124,7 @@ char *lp_smbrun(void);
char *lp_configfile(void);
char *lp_smb_passwd_file(void);
char *lp_serverstring(void);
char *lp_server_comment(void);
char *lp_printcapname(void);
char *lp_lockdir(void);
char *lp_rootdir(void);
@ -146,6 +147,7 @@ char *lp_interfaces(void);
char *lp_socket_address(void);
BOOL lp_wins_support(void);
BOOL lp_wins_proxy(void);
BOOL lp_local_master(void);
BOOL lp_domain_master(void);
BOOL lp_domain_logons(void);
BOOL lp_preferred_master(void);
@ -292,9 +294,8 @@ int reply_sendend(char *inbuf,char *outbuf);
/*The following definitions come from nameannounce.c */
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);
void do_announce_request(char *info, char *from_name, char *to_name,
int announce_type, int from, int to, struct in_addr dest_ip);
void sync_server(enum state_type state, char *serv_name, char *work_name,
int name_type,
struct in_addr ip);
@ -302,7 +303,10 @@ void do_announce_host(int command,
char *from_name, int from_type, struct in_addr from_ip,
char *to_name , int to_type , struct in_addr to_ip,
time_t announce_interval,
char *server_name, int server_type, char *server_comment);
char *server_name, int server_type,
char major_version, char minor_version,
uint16 browse_version, uint16 browse_sig,
char *server_comment);
void remove_my_servers(void);
void announce_server(struct subnet_record *d, struct work_record *work,
char *name, char *comment, time_t ttl, int server_type);
@ -317,6 +321,22 @@ struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
time_t ttl, struct in_addr ip, BOOL local);
void do_browser_lists(void);
/*The following definitions come from nameconf.c */
int get_num_workgroups(void);
int conf_workgroup_name_to_token(char *workgroup_name,char *default_name);
char *conf_workgroup_name(int token);
int conf_should_preferred_master(int token);
int conf_should_workgroup_member(int token);
int conf_should_local_master(int token);
int conf_should_domain_logon(int token);
int conf_should_domain_master(int token);
char *conf_browsing_alias(int token);
char *conf_browsing_alias_comment(int token);
char *conf_alias_to_workgroup(char *alias);
int conf_alias_to_token(char *alias);
void read_smbbrowse_conf(char *default_name);
/*The following definitions come from namedbname.c */
void set_samba_nb_type(void);
@ -338,7 +358,7 @@ struct name_record *add_netbios_entry(struct subnet_record *d,
char *name, int type, int nb_flags,
int ttl, enum name_source source, struct in_addr ip,
BOOL new_only,BOOL wins);
void expire_names(time_t t);
void check_expire_names(time_t t);
struct name_record *search_for_name(struct subnet_record **d,
struct nmb_name *question,
struct in_addr ip, int Time, int search);
@ -350,8 +370,9 @@ void add_response_record(struct subnet_record *d,
void remove_response_record(struct subnet_record *d,
struct response_record *n);
struct response_record *make_response_queue_record(enum state_type state,
int id,uint16 fd,
int quest_type, char *name,int type, int nb_flags, time_t ttl,
int id,uint16 fd, int quest_type,
int token, char *name,int type,
enum name_source source, int nb_flags, time_t ttl,
int server_type, char *my_name, char *my_comment,
BOOL bcast,BOOL recurse,
struct in_addr send_ip, struct in_addr reply_to_ip);
@ -375,7 +396,9 @@ void expire_servers(time_t t);
struct subnet_record *find_subnet(struct in_addr bcast_ip);
struct subnet_record *find_req_subnet(struct in_addr ip, BOOL bcast);
void add_subnet_interfaces(void);
void add_my_subnets(char *group);
void add_workgroup_to_subnet(char *group, struct in_addr bcast_ip,
struct in_addr mask_ip);
void add_workgroups_to_subnets();
struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
struct in_addr mask_ip,
char *name, BOOL add, BOOL lmhosts);
@ -397,8 +420,9 @@ void browser_gone(char *work_name, struct in_addr ip);
void send_election(struct subnet_record *d, char *group,uint32 criterion,
int timeup,char *name);
void name_unregister_work(struct subnet_record *d, char *name, int name_type);
void name_register_work(struct subnet_record *d, char *name, int name_type,
int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast);
void name_register_work(struct subnet_record *d, int token,
char *name, int name_type, enum name_source source,
struct nmb_ip *data, time_t ttl, struct in_addr ip, BOOL bcast);
void become_master(struct subnet_record *d, struct work_record *work);
void become_nonmaster(struct subnet_record *d, struct work_record *work,
int remove_type);
@ -413,7 +437,7 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len);
/*The following definitions come from namepacket.c */
void debug_browse_data(char *outbuf, int len);
void initiate_netbios_packet(uint16 *id,
BOOL initiate_netbios_packet(uint16 id,
int fd,int quest_type,char *name,int name_type,
int nb_flags,BOOL bcast,BOOL recurse,
struct in_addr to_ip);
@ -439,27 +463,30 @@ BOOL name_query(int fd,char *name,int name_type,
/*The following definitions come from nameresp.c */
void update_name_trn_id(void);
void expire_netbios_response_entries();
struct response_record *queue_netbios_pkt_wins(struct subnet_record *d,
void queue_netbios_pkt_wins(struct subnet_record *d,
int fd,int quest_type,enum state_type state,
char *name,int name_type,int nb_flags, time_t ttl,
int token, char *name,int name_type,
enum name_source source, int nb_flags, time_t ttl,
int server_type, char *my_name, char *my_comment,
BOOL bcast,BOOL recurse,
struct in_addr send_ip, struct in_addr reply_to_ip);
struct response_record *queue_netbios_packet(struct subnet_record *d,
int fd,int quest_type,enum state_type state,char *name,
int name_type,int nb_flags, time_t ttl,
void queue_netbios_packet(struct subnet_record *d,
int fd,int quest_type,enum state_type state,
int token, char *name, int name_type,
enum name_source source, int nb_flags, time_t ttl,
int server_type, char *my_name, char *my_comment,
BOOL bcast,BOOL recurse,
struct in_addr send_ip, struct in_addr reply_to_ip);
/*The following definitions come from nameserv.c */
void remove_name_entry(struct subnet_record *d, char *name,int type);
void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags);
void remove_name_entry(struct subnet_record *d, int token, char *name,int type);
void add_my_name_entry(struct subnet_record *d, int token,
char *name,int type,int nb_flags);
void add_my_names(void);
void remove_my_names();
void refresh_my_names(time_t t);
void query_refresh_names(void);
/*The following definitions come from nameservreply.c */
@ -481,13 +508,18 @@ void reply_name_query(struct packet_struct *p);
/*The following definitions come from nameservresp.c */
void debug_state_type(int state);
void response_process(struct in_addr ip, struct subnet_record *d,
struct response_record *n,
int rcode, char *nmb_data, struct nmb_name *q_name,
time_t ttl, BOOL bcast, struct nmb_name *ans_name);
void response_netbios_packet(struct packet_struct *p);
/*The following definitions come from namework.c */
void reset_server(char *name, int state, struct in_addr ip);
void reset_server(struct work_record *work, char *name, int state, struct in_addr ip);
void tell_become_backup(void);
BOOL same_context(struct dgram_packet *dgram);
BOOL listening_name(struct work_record *work, struct nmb_name *n);
void process_browse_packet(struct packet_struct *p,char *buf,int len);
/*The following definitions come from nmbd.c */
@ -533,7 +565,7 @@ void add_session_user(char *user);
void dfs_unlogin(void);
BOOL password_check(char *password);
BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8);
BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL is_nt_password);
BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd);
BOOL user_ok(char *user,int snum);
BOOL authorise_login(int snum,char *user,char *password, int pwlen,
BOOL *guest,BOOL *force,int vuid);
@ -737,6 +769,7 @@ unsigned int Ucrit_checkPid(int pid);
int sys_select(fd_set *fds,struct timeval *tval);
int sys_select(fd_set *fds,struct timeval *tval);
int sys_unlink(char *fname);
unsigned int sys_random(int max_range);
int sys_open(char *fname,int flags,int mode);
DIR *sys_opendir(char *dname);
int sys_stat(char *fname,struct stat *sbuf);
@ -813,7 +846,7 @@ void set_socket_options(int fd, char *options);
void close_sockets(void );
BOOL in_group(gid_t group, int current_gid, int ngroups, int *groups);
char *StrCpy(char *dest,char *src);
char *StrnCpy(char *dest,const char *src,int n);
char *StrnCpy(char *dest,char *src,int n);
void putip(void *dest,void *src);
int name_mangle(char *In,char *Out,char name_type);
BOOL file_exist(char *fname,struct stat *sbuf);

@ -380,10 +380,10 @@ typedef struct
/* used for server information: client, nameserv and ipc */
struct server_info_struct
{
fstring name;
char name[17];
uint32 type;
fstring comment;
fstring domain; /* used ONLY in ipc.c NOT namework.c */
char comment[50];
char domain[17]; /* used ONLY in ipc.c NOT namework.c */
BOOL server_added; /* used ONLY in ipc.c NOT namework.c */
};

@ -115,6 +115,15 @@ int sys_unlink(char *fname)
}
/*******************************************************************
random number generator
********************************************************************/
unsigned int sys_random(int max_range)
{
return(((unsigned int)random()) % max_range);
}
/*******************************************************************
a simple open() wrapper
********************************************************************/

@ -598,7 +598,7 @@ char *StrCpy(char *dest,char *src)
/****************************************************************************
line strncpy but always null terminates. Make sure there is room!
****************************************************************************/
char *StrnCpy(char *dest,const char *src,int n)
char *StrnCpy(char *dest,char *src,int n)
{
char *d = dest;
if (!dest) return(NULL);

@ -65,7 +65,7 @@ static void debug_nmb_res_rec(struct res_rec *res, char *hdr)
for (j = 0; j < 16; j++)
{
if (i+j >= res->rdlength) break;
DEBUG(4, ("%02X", (unsigned char)res->rdata[i+j]));
DEBUG(4, ("%02x", (unsigned char)res->rdata[i+j]));
}
DEBUG(4, ("\n"));

@ -23,19 +23,18 @@
14 jan 96: lkcl@pires.co.uk
added multiple workgroup domain master support
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/
#include "includes.h"
#define TEST_CODE
extern int DEBUGLEVEL;
extern BOOL CanRecurse;
extern struct in_addr ipzero;
extern pstring myname;
extern int ClientDGRAM;
extern int ClientNMB;
@ -43,14 +42,17 @@ extern int ClientNMB;
extern struct subnet_record *subnetlist;
extern int updatecount;
extern int workgroup_count;
extern struct in_addr ipgrp;
extern pstring myname;
/****************************************************************************
send a announce request to the local net
Send a announce request to the local net.
This is called by become_master(). This purpose of this action is to
encourage servers to send us host announcements right away.
**************************************************************************/
void announce_request(struct work_record *work, struct in_addr ip)
{
@ -71,8 +73,7 @@ void announce_request(struct work_record *work, struct in_addr ip)
CVAL(p,0) = work->token; /* (local) unique workgroup token id */
p++;
StrnCpy(p,myname,16);
strupper(p);
StrnCpy(p,conf_browsing_alias(work->token),16);
p = skip_string(p,1);
/* XXXX note: if we sent the announcement request to 0x1d instead
@ -80,16 +81,17 @@ void announce_request(struct work_record *work, struct in_addr ip)
us instead of the members of the workgroup. wha-hey! */
send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
myname,work->work_group,0x20,0x1e,ip,*iface_ip(ip));
conf_browsing_alias(work->token),work->work_group,
0x20, 0x1e,
ip,*iface_ip(ip));
}
/****************************************************************************
request an announcement
**************************************************************************/
void do_announce_request(char *info, char *to_name, int announce_type,
int from,
int to, struct in_addr dest_ip)
void do_announce_request(char *info, char *from_name, char *to_name,
int announce_type, int from, int to, struct in_addr dest_ip)
{
pstring outbuf;
char *p;
@ -107,7 +109,8 @@ void do_announce_request(char *info, char *to_name, int announce_type,
p = skip_string(p,1);
send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
myname,to_name,from,to,dest_ip,*iface_ip(dest_ip));
from_name,to_name,from,to,
dest_ip,*iface_ip(dest_ip));
}
@ -119,16 +122,20 @@ void sync_server(enum state_type state, char *serv_name, char *work_name,
int name_type,
struct in_addr ip)
{
int token = conf_workgroup_name_to_token(work_name, myname);
/* with a domain master we can get the whole list (not local only list) */
BOOL local_only = (state != NAME_STATUS_DOM_SRV_CHK);
add_browser_entry(serv_name, name_type, work_name, 0, ip, local_only);
if (state == NAME_STATUS_DOM_SRV_CHK)
if (state == NAME_STATUS_DOM_SRV_CHK && conf_should_local_master(token))
{
/* announce ourselves as a master browser to serv_name */
do_announce_request(myname, serv_name, ANN_MasterAnnouncement,
0x20, 0, ip);
do_announce_request(conf_browsing_alias(token), /* info */
conf_browsing_alias(token), /* from */
serv_name, /* to */
ANN_MasterAnnouncement, 0x20, 0,ip);
}
}
@ -140,7 +147,10 @@ void do_announce_host(int command,
char *from_name, int from_type, struct in_addr from_ip,
char *to_name , int to_type , struct in_addr to_ip,
time_t announce_interval,
char *server_name, int server_type, char *server_comment)
char *server_name, int server_type,
char major_version, char minor_version,
uint16 browse_version, uint16 browse_sig,
char *server_comment)
{
pstring outbuf;
char *p;
@ -158,12 +168,13 @@ void do_announce_host(int command,
StrnCpy(p+5,server_name,16);
strupper(p+5);
CVAL(p,21) = 0x02; /* major version */
CVAL(p,22) = 0x02; /* minor version */
CVAL(p,21) = major_version;
CVAL(p,22) = minor_version;
SIVAL(p,23,server_type);
SSVAL(p,27,0x010f); /* browse version: got from NT/AS 4.00 */
SSVAL(p,29,0xaa55); /* browse signature */
SSVAL(p,27,browse_version);
SSVAL(p,29,browse_sig);
strcpy(p+31,server_comment);
p += 31;
@ -194,7 +205,10 @@ void remove_my_servers(void)
struct server_record *s;
for (s = work->serverlist; s; s = s->next)
{
if (!strequal(myname,s->serv.name)) continue;
if (!strequal(conf_browsing_alias(work->token),s->serv.name))
{
continue;
}
announce_server(d, work, s->serv.name, s->serv.comment, 0, 0);
}
}
@ -208,7 +222,12 @@ void remove_my_servers(void)
void announce_server(struct subnet_record *d, struct work_record *work,
char *name, char *comment, time_t ttl, int server_type)
{
uint32 domain_type = SV_TYPE_DOMAIN_ENUM|DFLT_SERVER_TYPE;
/* domain type cannot have anything in it that might confuse
a client into thinking that the domain is in fact a server.
(SV_TYPE_SERVER_UNIX, for example)
*/
uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
BOOL wins_iface = ip_equal(d->bcast_ip, ipgrp);
if (wins_iface && server_type != 0)
@ -216,14 +235,13 @@ void announce_server(struct subnet_record *d, struct work_record *work,
/* wins pseudo-ip interface */
if (!AM_MASTER(work))
{
/* non-master announce by unicast to the domain
master */
/* non-master announce by unicast to the domain master */
if (!lp_wins_support() && *lp_wins_server())
{
/* look up the domain master with the WINS server */
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,
NAME_QUERY_ANNOUNCE_HOST,
work->work_group,0x1b,0,ttl*1000,
work->token,work->work_group,0x1b,0,0,ttl*1000,
server_type,name,comment,
False, False, ipzero, d->bcast_ip);
}
@ -239,9 +257,7 @@ void announce_server(struct subnet_record *d, struct work_record *work,
/* XXXX any other kinds of announcements we need to consider here?
e.g local master browsers... no. local master browsers do
local master announcements to their domain master. they even
use WINS lookup of the domain master if another wins server
is being used!
local master announcements to their domain master.
*/
}
else
@ -255,7 +271,10 @@ void announce_server(struct subnet_record *d, struct work_record *work,
name , 0x00, d->myip,
work->work_group, 0x1e, d->bcast_ip,
ttl*1000,
name, server_type, comment);
name, server_type,
HOST_MAJOR_VERSION, HOST_MINOR_VERSION,
HOST_BROWSE_VERSION, HOST_BROWSE_SIGNATURE,
comment);
DEBUG(3,("sending domain announce to %s for %s\n",
inet_ntoa(d->bcast_ip),work->work_group));
@ -268,6 +287,8 @@ void announce_server(struct subnet_record *d, struct work_record *work,
MSBROWSE, 0x01, d->bcast_ip,
ttl*1000,
work->work_group, server_type ? domain_type : 0,
WG_MAJOR_VERSION, WG_MINOR_VERSION,
WG_BROWSE_VERSION, WG_BROWSE_SIGNATURE,
name);
}
}
@ -280,7 +301,10 @@ void announce_server(struct subnet_record *d, struct work_record *work,
name , 0x00, d->myip,
work->work_group, 0x1d, d->bcast_ip,
ttl*1000,
name, server_type, comment);
name, server_type,
HOST_MAJOR_VERSION, HOST_MINOR_VERSION,
HOST_BROWSE_VERSION, HOST_BROWSE_SIGNATURE,
comment);
}
}
}
@ -293,11 +317,6 @@ void announce_host(void)
time_t t = time(NULL);
struct subnet_record *d;
pstring comment;
char *my_name;
StrnCpy(comment, lp_serverstring(), 43);
my_name = *myname ? myname : "NoName";
for (d = subnetlist; d; d = d->next)
{
@ -309,7 +328,11 @@ void announce_host(void)
{
uint32 stype = work->ServerType;
struct server_record *s;
BOOL announce = False;
char *my_name = conf_browsing_alias(work->token);
char *my_comment = conf_browsing_alias_comment(work->token);
StrnCpy(comment, my_comment, 43);
/* must work on the code that does announcements at up to
30 seconds later if a master browser sends us a request
@ -335,15 +358,12 @@ void announce_host(void)
work->lastannounce_time = t;
for (s = work->serverlist; s; s = s->next) {
if (strequal(myname, s->serv.name)) {
announce = True;
break;
}
}
if (announce) {
if (strequal(my_name, s->serv.name))
{
announce_server(d,work,my_name,comment,
work->announce_interval,stype);
break;
}
}
if (work->needannounce)
@ -358,10 +378,10 @@ void announce_host(void)
/****************************************************************************
announce myself as a master to all other primary domain conrollers.
announce samba as a master to all other primary domain conrollers.
this actually gets done in search_and_sync_workgroups() via the
NAME_QUERY_DOM_SRV_CHK command, if there is a response from the
NAME_QUERY_DOM_SRV_CHK state, if there is a response from the
name query initiated here. see response_name_query()
**************************************************************************/
void announce_master(void)
@ -382,7 +402,7 @@ void announce_master(void)
struct work_record *work;
for (work = d->workgrouplist; work; work = work->next)
{
if (AM_MASTER(work))
if (AM_MASTER(work) || AM_DMBRSE(work))
{
am_master = True;
}
@ -399,23 +419,30 @@ void announce_master(void)
struct server_record *s;
for (s = work->serverlist; s; s = s->next)
{
if (strequal(s->serv.name, myname)) continue;
if (strequal(s->serv.name, conf_browsing_alias(work->token))) continue;
/* all DOMs (which should also be master browsers) */
if (s->serv.type & SV_TYPE_DOMAIN_CTRL)
/* all master browsers */
if (s->serv.type & SV_TYPE_DOMAIN_MASTER)
{
/* 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 */
/* check the existence of a domain master for this workgroup,
and if one exists at the specified ip, sync with it and
announce ourselves as a local master browser to it */
/* exclude lp_domain_controller() from this check if it's
in our browse lists, because it's dealt with separately
*/
if (!*lp_domain_controller() ||
!strequal(lp_domain_controller(), s->serv.name))
{
if (!lp_wins_support() && *lp_wins_server())
if (lp_wins_support() || *lp_wins_server())
{
/* query the WINS server (that may include samba itself)
to find the browse master
*/
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,
NAME_QUERY_DOM_SRV_CHK,
work->work_group,0x1b,0,0,0,NULL,NULL,
work->token,
work->work_group,0x1b,0,0,0,0,NULL,NULL,
False, False, ipzero, ipzero);
}
else
@ -423,9 +450,13 @@ void announce_master(void)
struct subnet_record *d2;
for (d2 = subnetlist; d2; d2 = d2->next)
{
/* query by broadcast on every local interface
to find the browse master
*/
queue_netbios_packet(d,ClientNMB,NMB_QUERY,
NAME_QUERY_DOM_SRV_CHK,
work->work_group,0x1b,0,0,0,NULL,NULL,
work->token, work->work_group,0x1b,
0,0,0,0,NULL,NULL,
True, False, d2->bcast_ip, d2->bcast_ip);
}
}
@ -443,14 +474,13 @@ void announce_master(void)
if (*lp_domain_controller())
{
struct in_addr ip;
BOOL bcast = False;
ip = *interpret_addr2(lp_domain_controller());
if (zero_ip(ip)) {
ip = d->bcast_ip;
bcast = True;
}
/* if the ip is zero, then make the query to samba as a WINS server */
/* XXXX later, if this also fails, we could also do a broadcast query on
samba's local subnets
*/
DEBUG(2, ("Searching for DOM %s at %s\n",
lp_domain_controller(), inet_ntoa(ip)));
@ -459,8 +489,9 @@ void announce_master(void)
one exists at the specified ip, sync with it and announce
ourselves as a master browser to it */
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,NAME_QUERY_DOM_SRV_CHK,
work->work_group,0x1b,0,0,0,NULL,NULL,
bcast, False, ip, ip);
work->token, work->work_group,0x1b,
0,0,0,0,NULL,NULL,
False, False, ip, ip);
}
}
}
@ -481,6 +512,7 @@ void announce_remote(void)
pstring s2;
struct in_addr addr;
char *comment,*workgroup;
int token;
int stype = DFLT_SERVER_TYPE;
if (last_time && t < last_time + REMOTE_ANNOUNCE_INTERVAL)
@ -491,13 +523,16 @@ void announce_remote(void)
s = lp_remote_announce();
if (!*s) return;
comment = lp_serverstring();
workgroup = lp_workgroup();
comment = lp_serverstring(); /* default comment */
workgroup = lp_workgroup(); /* default workgroup name */
for (ptr=s; next_token(&ptr,s2,NULL); ) {
for (ptr=s; next_token(&ptr,s2,NULL); )
{
/* the entries are of the form a.b.c.d/WORKGROUP with
WORKGROUP being optional */
char *wgroup;
char *my_name;
extern pstring myname; /* samba's default NetBIOS name */
wgroup = strchr(s2,'/');
if (wgroup) *wgroup++ = 0;
@ -506,10 +541,17 @@ void announce_remote(void)
addr = *interpret_addr2(s2);
do_announce_host(ANN_HostAnnouncement,myname,0x20,*iface_ip(addr),
wgroup,0x1e,addr,
REMOTE_ANNOUNCE_INTERVAL,
myname,stype,comment);
}
token = conf_workgroup_name_to_token(wgroup, myname);
my_name = conf_browsing_alias(token);
my_name = my_name ? my_name : myname;
do_announce_host(ANN_HostAnnouncement,
my_name, 0x20, *iface_ip(addr),
wgroup , 0x1e, addr,
REMOTE_ANNOUNCE_INTERVAL,
my_name,stype,
HOST_MAJOR_VERSION, HOST_MINOR_VERSION,
HOST_BROWSE_VERSION, HOST_BROWSE_SIGNATURE,
comment);
}
}

@ -23,6 +23,9 @@
14 jan 96: lkcl@pires.co.uk
added multiple workgroup domain master support
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/
#include "includes.h"
@ -166,7 +169,7 @@ static void start_sync_browse_entry(struct browse_cache_record *b)
struct subnet_record *d;
struct work_record *work;
if (!(d = find_subnet(b->ip))) return;
if( (d = find_subnet(b->ip)) == (struct subnet_record *)NULL ) return;
if (!(work = find_workgroupstruct(d, b->group, False))) return;
@ -179,7 +182,7 @@ static void start_sync_browse_entry(struct browse_cache_record *b)
/* see response_netbios_packet() or expire_netbios_response_entries() */
queue_netbios_packet(d,ClientNMB,NMB_QUERY,
b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE,
b->group,0x20,0,0,0,NULL,NULL,
work->token,b->group,0x20,0,0,0,0,NULL,NULL,
False,False,b->ip,b->ip);
}

@ -58,10 +58,12 @@ struct smbbrowse
char work_name[16]; /* workgroup name */
char browsing_alias[16]; /* alias for our role in this workgroup */
struct server_identity *my_names; /* a list of server name we should appear here as */
BOOL should_workgroup_member; /* should we try to become a member of this workgroup? */
BOOL should_local_master; /* should we try to become a master browser? */
BOOL should_domain_master; /* should we try to become the domain master browser? */
} ;
BOOL should_workgroup_member; /* should we be a member of this workgroup? */
BOOL should_local_master; /* should we be a master browser? */
BOOL should_preferred_master; /* should we initiate attempts to become a master browser? */
BOOL should_domain_master; /* should we be the domain master browser? */
BOOL should_domain_logon; /* should we be the domain logon? */
};
/* The whole list */
static struct smbbrowse *smbbrowse_workgroups = (struct smbbrowse*)NULL;
@ -82,12 +84,12 @@ int get_num_workgroups(void)
** old one as a model.
*/
static struct smbbrowse *new_workgroup(struct smbbrowse *model,
const char *workgroup_name,
const char *default_name)
char *workgroup_name,
char *default_name)
{
struct smbbrowse *new;
if( ! (array_size > nexttoken) )
if ( ! (array_size > nexttoken) )
{
array_size += 10;
smbbrowse_workgroups = (struct smbbrowse*)realloc(smbbrowse_workgroups,
@ -96,7 +98,7 @@ static struct smbbrowse *new_workgroup(struct smbbrowse *model,
new = &smbbrowse_workgroups[nexttoken];
if(model != (struct smbbrowse *)NULL )
if (model != (struct smbbrowse *)NULL )
memcpy(new, model, sizeof(struct smbbrowse));
else
memset(new, 0, sizeof(struct smbbrowse));
@ -122,28 +124,27 @@ static struct smbbrowse *new_workgroup(struct smbbrowse *model,
** If the workgroup does not exist a new token is assigned unless
** new workgroups are not allowed.
*/
int conf_workgroup_name_to_token(const char *workgroup_name,
const char *default_name)
int conf_workgroup_name_to_token(char *workgroup_name,char *default_name)
{
int idx;
/* Look for an existing instance. */
for(idx=0; idx < nexttoken; idx++)
for (idx=0; idx < nexttoken; idx++)
{
if(strequal(workgroup_name, smbbrowse_workgroups[idx].work_name))
if (strequal(workgroup_name, smbbrowse_workgroups[idx].work_name))
{
return idx;
}
}
/* See if creating new ones in admissable. */
for(idx=0; idx < nexttoken; idx++)
for (idx=0; idx < nexttoken; idx++)
{
if(strequal("*", smbbrowse_workgroups[idx].work_name))
if (strequal("*", smbbrowse_workgroups[idx].work_name))
{
struct smbbrowse *w = new_workgroup(&smbbrowse_workgroups[idx],
workgroup_name, default_name);
w->should_workgroup_member = False;
w->should_workgroup_member = True;
return (nexttoken - 1);
}
@ -159,7 +160,7 @@ int conf_workgroup_name_to_token(const char *workgroup_name,
*/
static int range_check(int token)
{
if(token < 0 || token >= nexttoken)
if (token < 0 || token >= nexttoken)
{
DEBUG(0, ("range_check(): failed\n"));
return True;
@ -173,12 +174,25 @@ static int range_check(int token)
*/
char *conf_workgroup_name(int token)
{
if(range_check(token))
if (range_check(token))
return (char*)NULL;
return smbbrowse_workgroups[token].work_name;
}
/*
** Given a token, return True if we should try
** to become a master browser.
*/
int conf_should_preferred_master(int token)
{
if (range_check(token))
return False;
return smbbrowse_workgroups[token].should_preferred_master;
}
/*
** Given a token, return True if we should try
** to become a master browser.
@ -186,7 +200,7 @@ char *conf_workgroup_name(int token)
int conf_should_workgroup_member(int token)
{
if(range_check(token))
if (range_check(token))
return False;
return smbbrowse_workgroups[token].should_workgroup_member;
@ -197,12 +211,22 @@ int conf_should_workgroup_member(int token)
** to become a master browser.
*/
int conf_should_local_master(int token)
{
if(range_check(token))
return False;
{
if (range_check(token)) return False;
return smbbrowse_workgroups[token].should_local_master;
}
}
/*
** Given a token, return True if we should try
** to become a domain master browser.
*/
int conf_should_domain_logon(int token)
{
if (range_check(token)) return False;
return smbbrowse_workgroups[token].should_domain_logon;
}
/*
** Given a token, return True if we should try
@ -210,7 +234,7 @@ int conf_should_local_master(int token)
*/
int conf_should_domain_master(int token)
{
if(range_check(token))
if (range_check(token))
return False;
return smbbrowse_workgroups[token].should_domain_master;
@ -220,12 +244,12 @@ int conf_should_domain_master(int token)
** Given a token, return the name.
*/
char *conf_browsing_alias(int token)
{
if(range_check(token))
{
if (range_check(token))
return (char*)NULL;
return smbbrowse_workgroups[token].browsing_alias;
}
}
/*
** Return the server comment which should be used with the
@ -233,27 +257,27 @@ char *conf_browsing_alias(int token)
*/
char *conf_browsing_alias_comment(int token)
{
if(range_check(token))
if (range_check(token))
return (char*) NULL;
return "Browser";
}
return lp_server_comment();
}
/*
** Given an alias name for this server, return the name of the workgroup
** for which it is the browsing alias.
*/
char *conf_alias_to_workgroup(const char *alias)
char *conf_alias_to_workgroup(char *alias)
{
int x;
DEBUG(4,("alias_to_workgroup: %s", alias));
for(x=0; x < nexttoken; x++)
for (x=0; x < nexttoken; x++)
{
DEBUG(4,("%s ", smbbrowse_workgroups[x].browsing_alias));
if(strequal(alias, smbbrowse_workgroups[x].browsing_alias))
if (strequal(alias, smbbrowse_workgroups[x].browsing_alias))
{
DEBUG(4,("OK\n"));
return smbbrowse_workgroups[x].work_name;
@ -267,13 +291,13 @@ char *conf_alias_to_workgroup(const char *alias)
** Given an alias name for this server, return the name of the workgroup
** for which it is the browsing alias.
*/
int conf_alias_to_token(const char *alias)
int conf_alias_to_token(char *alias)
{
int x;
for(x=0; x < nexttoken; x++)
for (x=0; x < nexttoken; x++)
{
if(strequal(alias, smbbrowse_workgroups[x].browsing_alias))
if (strequal(alias, smbbrowse_workgroups[x].browsing_alias))
{
return x;
}
@ -285,21 +309,25 @@ int conf_alias_to_token(const char *alias)
** Since there is no smbbrowse.conf file, we will fill in
** the structures with information from the smb.conf file.
*/
static void default_smbbrowse_conf(const char *default_name)
static void default_smbbrowse_conf(char *default_name)
{
struct smbbrowse *w;
/* The workgroup specified in smb.conf */
w = new_workgroup((struct smbbrowse *)NULL, lp_workgroup(), default_name);
w->should_local_master = lp_preferred_master();
w->should_local_master = lp_local_master();
w->should_domain_master = lp_domain_master();
w->should_domain_logon = lp_domain_logons();
w->should_workgroup_member = True;
/* default action: allow any new workgroup to be added */
/* default action: allow any new workgroup to be added. this is
_not_ the same as the old 1.9.14-1.9.15 definition of "*"
*/
w = new_workgroup((struct smbbrowse *)NULL, "*", default_name);
w->should_local_master = False;
w->should_domain_master = False;
w->should_workgroup_member = False;
w->should_domain_logon = False;
}
/*
@ -334,6 +362,8 @@ void read_smbbrowse_conf(char *default_name)
w = new_workgroup((struct smbbrowse *)NULL, work_name, default_name);
w->should_local_master = lp_local_master();
w->should_domain_master = lp_domain_master();
w->should_preferred_master = lp_preferred_master();
w->should_domain_logon = lp_domain_logons();
w->should_workgroup_member = True;
}

@ -27,6 +27,10 @@
04 jul 96: lkcl@pires.co.uk
created module namedbname containing name database functions
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/
#include "includes.h"
@ -43,6 +47,16 @@ extern struct subnet_record *subnetlist;
uint16 nb_type = 0; /* samba's NetBIOS name type */
static char *source_description[] =
{
"STATUS_QUERY",
"LMHOSTS",
"REG",
"SELF",
"DNS",
"DNSFAIL"
};
/****************************************************************************
samba's NetBIOS name type
@ -173,8 +187,10 @@ struct name_record *find_name_search(struct subnet_record **d,
{
if (d == NULL) return NULL; /* bad error! */
if (search & FIND_LOCAL) {
if (*d != NULL) {
if (search & FIND_LOCAL)
{
if (*d != NULL)
{
struct name_record *n = find_name((*d)->namelist, name, search);
DEBUG(4,("find_name on local: %s %s search %x\n",
namestr(name),inet_ntoa(ip), search));
@ -182,7 +198,7 @@ struct name_record *find_name_search(struct subnet_record **d,
}
}
if (!(search & FIND_WINS)) return NULL;
if ((search & FIND_WINS) != FIND_WINS) return NULL;
/* find WINS subnet record. */
*d = find_subnet(ipgrp);
@ -228,18 +244,16 @@ void dump_names(void)
{
int i;
DEBUG(3,("%15s ", inet_ntoa(d->bcast_ip)));
DEBUG(3,("%15s ", inet_ntoa(d->mask_ip)));
DEBUG(3,("%-19s TTL=%ld ",
DEBUG(3,("%-15s ", inet_ntoa(d->bcast_ip)));
DEBUG(3,("%-19s TTL=%7ld %s ",
namestr(&n->name),
n->death_time?n->death_time-t:0));
n->death_time?n->death_time-t:0, source_description[n->source]));
for (i = 0; i < n->num_ips; i++)
{
DEBUG(3,("%15s NB=%2x source=%d",
DEBUG(3,("%-15s NB=%2x ",
inet_ntoa(n->ip_flgs[i].ip),
n->ip_flgs[i].nb_flags,n->source));
(unsigned char)n->ip_flgs[i].nb_flags));
}
DEBUG(3,("\n"));
@ -256,7 +270,7 @@ void dump_names(void)
{
fprintf(f, "%s %2x ",
inet_ntoa(n->ip_flgs[i].ip),
n->ip_flgs[i].nb_flags);
(unsigned char)n->ip_flgs[i].nb_flags);
}
fprintf(f, "\n");
}
@ -412,7 +426,15 @@ struct name_record *add_netbios_entry(struct subnet_record *d,
struct name_record *n;
struct name_record *n2=NULL;
int search = 0;
BOOL self = source == SELF;
BOOL self;
if (iface_ip(ip))
{
source = SELF;
putip(&ip, &ipzero);
}
self = source == SELF;
/* add the name to the WINS list if the name comes from a directed query */
search |= wins ? FIND_WINS : FIND_LOCAL;
@ -472,9 +494,12 @@ struct name_record *add_netbios_entry(struct subnet_record *d,
/*******************************************************************
expires old names in the namelist
expires or refreshes old names in the namelist
if the name is a samba SELF name, it must be refreshed rather than
removed.
******************************************************************/
void expire_names(time_t t)
void check_expire_names(time_t t)
{
struct name_record *n;
struct name_record *next;
@ -486,13 +511,21 @@ void expire_names(time_t t)
for (n = d->namelist; n; n = next)
{
next = n->next;
if (n->death_time && n->death_time < t)
{
if (n->source == SELF) {
DEBUG(3,("not expiring SELF name %s\n", namestr(&n->name)));
n->death_time += 300;
if (n->source == SELF)
{
/* refresh the samba name. if this refresh fails
for any reason, it will be deleted.
*/
DEBUG(3,("Refreshing SELF name %s\n", namestr(&n->name)));
add_my_name_entry(d, -1,
n->name.name, n->name.name_type,
n->ip_flgs[0].nb_flags);
continue;
}
DEBUG(3,("Removing dead name %s\n", namestr(&n->name)));
if (n->prev) n->prev->next = n->next;

@ -92,8 +92,9 @@ void remove_response_record(struct subnet_record *d,
create a name query response record
**************************************************************************/
struct response_record *make_response_queue_record(enum state_type state,
int id,uint16 fd,
int quest_type, char *name,int type, int nb_flags, time_t ttl,
int id,uint16 fd, int quest_type,
int token, char *name,int type,
enum name_source source, int nb_flags, time_t ttl,
int server_type, char *my_name, char *my_comment,
BOOL bcast,BOOL recurse,
struct in_addr send_ip, struct in_addr reply_to_ip)
@ -109,14 +110,17 @@ struct response_record *make_response_queue_record(enum state_type state,
n->state = state;
n->fd = fd;
n->quest_type = quest_type;
n->token = token;
make_nmb_name(&n->name, name, type, scope);
n->nb_flags = nb_flags;
n->ttl = ttl;
n->source = source;
n->server_type = server_type;
n->bcast = bcast;
n->recurse = recurse;
n->reply.nb_flags = nb_flags;
n->reply.ip = reply_to_ip;
n->send_ip = send_ip;
n->reply_to_ip = reply_to_ip;
StrnCpy(my_name , n->my_name , sizeof(n->my_name )-1);
StrnCpy(my_comment, n->my_comment, sizeof(n->my_comment)-1);

@ -133,6 +133,7 @@ struct server_record *add_server_entry(struct subnet_record *d,
{
BOOL newentry=False;
struct server_record *s;
int token = conf_workgroup_name_to_token(work->work_group, myname);
if (name[0] == '*')
{
@ -160,11 +161,9 @@ struct server_record *add_server_entry(struct subnet_record *d,
bzero((char *)s,sizeof(*s));
}
if (strequal(lp_workgroup(),work->work_group))
if (conf_should_workgroup_member(token))
{
if (servertype)
servertype |= SV_TYPE_LOCAL_LIST_ONLY;
if (servertype) servertype |= SV_TYPE_LOCAL_LIST_ONLY;
}
else
{

@ -26,6 +26,9 @@
04 jul 96: lkcl@pires.co.uk
created module namedbsubnet containing subnet database functions
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/
#include "includes.h"
@ -177,23 +180,36 @@ void add_subnet_interfaces(void)
/****************************************************************************
add the default workgroups into my domain
**************************************************************************/
void add_workgroup_to_subnet(char *group, struct in_addr bcast_ip,
struct in_addr mask_ip)
{
if (group && *group != '*')
{
DEBUG(4,("add_wg_to_subnet: %s %s\n", group, inet_ntoa(bcast_ip)));
add_subnet_entry(bcast_ip,mask_ip,group, True, False);
}
}
/****************************************************************************
add the default workgroup into my domain
**************************************************************************/
void add_my_subnets(char *group)
void add_workgroups_to_subnets()
{
struct interface *i;
/* add or find domain on our local subnet, in the default workgroup */
if (*group == '*') return;
/* the coding choice is up to you, andrew: i can see why you don't want
global access to the local_interfaces structure: so it can't get
messed up! */
for (i = local_interfaces; i; i = i->next)
{
add_subnet_entry(i->bcast,i->nmask,group, True, False);
int token;
for (token = 0; token < get_num_workgroups(); token++)
{
add_workgroup_to_subnet(conf_workgroup_name(token),i->bcast,i->nmask);
}
}
}
@ -208,43 +224,44 @@ struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
{
struct subnet_record *d;
/* XXXX andrew: struct in_addr ip appears not to be referenced at all except
in the DEBUG comment. i assume that the DEBUG comment below actually
intends to refer to bcast_ip? i don't know.
DEBUG(4,("add_subnet_entry: %s %\n", name,inet_ntoa(bcast_ip)));
struct in_addr ip = ipgrp;
*/
if (zero_ip(bcast_ip))
bcast_ip = *iface_bcast(bcast_ip);
if (zero_ip(bcast_ip)) bcast_ip = *iface_bcast(bcast_ip);
/* add the domain into our domain database */
if ((d = find_subnet(bcast_ip)) ||
(d = make_subnet(bcast_ip, mask_ip)))
if ((d = find_subnet(bcast_ip)) || (d = make_subnet(bcast_ip, mask_ip)))
{
struct work_record *w = find_workgroupstruct(d, name, add);
struct work_record *work = find_workgroupstruct(d, name, add);
if (!w) return NULL;
if (!work) return NULL;
if (conf_should_workgroup_member(work->token))
{
/* add samba server name to workgroup list. don't add
lmhosts server entries to local interfaces */
pstring comment;
char *my_name = conf_browsing_alias (work->token);
char *my_comment = conf_browsing_alias_comment(work->token);
StrnCpy(comment, my_comment, 43);
add_server_entry(d,work,my_name,
work->ServerType | SV_TYPE_LOCAL_LIST_ONLY,
0,comment,True);
DEBUG(3,("Added server name entry %s at %s\n",
name,inet_ntoa(bcast_ip)));
/* 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_my_name_entry(d,name,0x1e,nb_type|NB_ACTIVE|NB_GROUP);
add_my_name_entry(d,name,0x0 ,nb_type|NB_ACTIVE|NB_GROUP);
}
/* add samba server name to workgroup list. don't add
lmhosts server entries to local interfaces */
if (strequal(lp_workgroup(), name))
{
add_server_entry(d,w,myname,w->ServerType,0,lp_serverstring(),True);
DEBUG(3,("Added server name entry %s at %s\n",
name,inet_ntoa(bcast_ip)));
add_my_name_entry(d,work->token,name,0x1e,nb_type|NB_ACTIVE|NB_GROUP);
add_my_name_entry(d,work->token,name,0x0 ,nb_type|NB_ACTIVE|NB_GROUP);
}
return d;
}
return NULL;
}

@ -26,6 +26,9 @@
04 jul 96: lkcl@pires.co.uk
created module namedbwork containing workgroup database functions
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/
#include "includes.h"
@ -40,9 +43,7 @@ extern struct subnet_record *subnetlist;
extern struct in_addr ipgrp;
int workgroup_count = 0; /* unique index key: one for each workgroup */
extern pstring myname;
/****************************************************************************
add a workgroup into the domain list
@ -75,11 +76,17 @@ static void add_workgroup(struct work_record *work, struct subnet_record *d)
static struct work_record *make_workgroup(char *name)
{
struct work_record *work;
struct subnet_record *d;
int t = -1;
if (!name || !name[0]) return NULL;
/* conf_workgroup_name_to_token() gets or creates a unique index for the workgroup name */
if ((t = conf_workgroup_name_to_token(name, myname)) == -1)
{
DEBUG(3, ("work_record(\"%s\"): conf_workgroup_name_to_token() refuses to allow workgroup\n", name));
return (struct work_record *)NULL;
}
work = (struct work_record *)malloc(sizeof(*work));
if (!work) return(NULL);
@ -92,34 +99,16 @@ static struct work_record *make_workgroup(char *name)
work->needelection = False;
work->needannounce = True;
work->state = MST_NONE;
/* make sure all token representations of workgroups are unique */
for (d = subnetlist; 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()) {
if (conf_should_domain_master(work->token))
{
work->ElectionCriterion |= 0x80;
}
@ -175,33 +164,45 @@ struct work_record *find_workgroupstruct(struct subnet_record *d,
if (strequal(name, "*"))
{
#if 0 /* XXXX this is being called too many times */
DEBUG(2,("add any workgroups: initiating browser search on %s\n",
inet_ntoa(d->bcast_ip)));
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY, NAME_QUERY_FIND_MST,
MSBROWSE,0x1,0,0,0,NULL,NULL,
-1,MSBROWSE,0x1,0,0,0,0,NULL,NULL,
True,False, d->bcast_ip, d->bcast_ip);
#endif
return NULL;
}
for (ret = d->workgrouplist; ret; ret = ret->next) {
if (!strcmp(ret->work_group,name)) {
for (ret = d->workgrouplist; ret; ret = ret->next)
{
if (!strcmp(ret->work_group,name))
{
DEBUG(4, ("found\n"));
return(ret);
}
}
if (!add) {
if (!add)
{
DEBUG(4, ("not found\n"));
return NULL;
}
DEBUG(4,("not found: creating\n"));
if ((work = make_workgroup(name)))
if ((work = make_workgroup(name)) != NULL)
{
DEBUG(4,("bcast_ip:%s preferred master=%s local_master=%s\n",
inet_ntoa(d->bcast_ip),
BOOLSTR(conf_should_preferred_master(work->token)),
BOOLSTR(conf_should_local_master(work->token)) ));
if (!ip_equal(d->bcast_ip, ipgrp) &&
lp_preferred_master() &&
strequal(lp_workgroup(), name))
conf_should_preferred_master(work->token) &&
conf_should_local_master (work->token))
{
DEBUG(3, ("preferred master startup for %s\n", work->work_group));
work->needelection = True;

@ -28,6 +28,8 @@
04 jul 96: lkcl@pires.co.uk
added system to become a master browser by stages.
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/
@ -39,7 +41,6 @@ extern int ClientDGRAM;
extern int DEBUGLEVEL;
extern pstring scope;
extern pstring myname;
extern struct in_addr ipzero;
extern struct in_addr ipgrp;
@ -51,6 +52,9 @@ extern struct subnet_record *subnetlist;
extern uint16 nb_type; /* samba's NetBIOS name type */
extern pstring myname;
/*******************************************************************
occasionally check to see if the master browser is around
******************************************************************/
@ -79,7 +83,7 @@ void check_master_browser(void)
if (!AM_MASTER(work))
{
queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK,
work->work_group,0x1d,0,0,0,NULL,NULL,
work->token, work->work_group,0x1d,REGISTER,0,0,0,NULL,NULL,
True,False,d->bcast_ip,d->bcast_ip);
}
}
@ -102,9 +106,8 @@ void browser_gone(char *work_name, struct in_addr ip)
if (ip_equal(d->bcast_ip,ipgrp))
return;
if (strequal(work->work_group, lp_workgroup()))
if (conf_should_local_master(work->token))
{
DEBUG(2,("Forcing election on %s %s\n",
work->work_group,inet_ntoa(d->bcast_ip)));
@ -114,10 +117,10 @@ void browser_gone(char *work_name, struct in_addr ip)
else
{
/* local interfaces: force an election */
send_election(d, work->work_group, 0, 0, myname);
send_election(d, work->work_group, 0, 0, conf_browsing_alias(work->token));
/* only removes workgroup completely on a local interface
persistent lmhosts entries on a local interface _will_ be removed).
persistent lmhosts entries on a local interface _will_ be removed.
*/
remove_workgroup(d, work,True);
}
@ -172,8 +175,10 @@ void name_unregister_work(struct subnet_record *d, char *name, int name_type)
if (!(work = find_workgroupstruct(d, name, False))) return;
if (!AM_MASTER(work) && !AM_DMBRSE(work)) return;
if (ms_browser_name(name, name_type) ||
(AM_MASTER(work) && strequal(name, lp_workgroup()) == 0 &&
(conf_should_workgroup_member(work->token) &&
(name_type == 0x1d || name_type == 0x1b)))
{
int remove_type = 0;
@ -197,17 +202,17 @@ void name_unregister_work(struct subnet_record *d, char *name, int name_type)
whether to proceed to the next stage in samba becoming a master browser.
**************************************************************************/
void name_register_work(struct subnet_record *d, char *name, int name_type,
int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast)
void name_register_work(struct subnet_record *d, int token,
char *name, int name_type, enum name_source source,
struct nmb_ip *data, time_t ttl, struct in_addr ip, BOOL bcast)
{
enum name_source source = (ismyip(ip) || ip_equal(ip, ipzero)) ?
SELF : REGISTER;
if (source == SELF)
{
struct work_record *work = find_workgroupstruct(d, lp_workgroup(), False);
char *work_name = conf_workgroup_name(token);
struct work_record *work = find_workgroupstruct(d, work_name, False);
add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast);
add_netbios_entry(d,name,name_type,data->nb_flags,
ttl,source,data->ip,True,!bcast);
if (work)
{
@ -249,11 +254,33 @@ void name_register_work(struct subnet_record *d, char *name, int name_type,
******************************************************************/
void become_master(struct subnet_record *d, struct work_record *work)
{
uint32 domain_type = SV_TYPE_DOMAIN_ENUM|DFLT_SERVER_TYPE|
SV_TYPE_POTENTIAL_BROWSER;
pstring comment;
/* domain type must be limited to domain enum + server type. it must
not have SV_TYPE_SERVER or anything else with SERVER in it, else
clients get confused and start thinking this entry is a server
not a workgroup
*/
uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
char *my_name ;
char *my_comment;
if (!work) return;
my_name = conf_browsing_alias(work->token);
my_comment = conf_browsing_alias_comment(work->token);
StrnCpy(comment, my_comment, 43);
if (!conf_should_local_master(work->token))
{
DEBUG(1,("Should not become master for %s %s\n",
work->work_group,inet_ntoa(d->bcast_ip)));
work->state = MST_NONE;
return;
}
DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n",
work->work_group,inet_ntoa(d->bcast_ip),work->state));
@ -268,10 +295,10 @@ void become_master(struct subnet_record *d, struct work_record *work)
/* update our server status */
work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER;
add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
add_server_entry(d,work,my_name,work->ServerType,0,comment,True);
/* add special browser name */
add_my_name_entry(d,MSBROWSE ,0x01,nb_type|NB_ACTIVE|NB_GROUP);
add_my_name_entry(d,work->token,MSBROWSE,0x01,nb_type|NB_ACTIVE|NB_GROUP);
/* DON'T do anything else after calling add_my_name_entry() */
return;
@ -282,10 +309,11 @@ void become_master(struct subnet_record *d, struct work_record *work)
work->state = MST_MSB; /* ... registering MSBROWSE was successful */
/* add server entry on successful registration of MSBROWSE */
add_server_entry(d,work,work->work_group,domain_type,0,myname,True);
add_server_entry(d,work,work->work_group,
domain_type,0,conf_browsing_alias(work->token),True);
/* add master name */
add_my_name_entry(d,work->work_group,0x1d,nb_type|NB_ACTIVE);
add_my_name_entry(d,work->token,work->work_group,0x1d,nb_type|NB_ACTIVE);
/* DON'T do anything else after calling add_my_name_entry() */
return;
@ -297,7 +325,8 @@ void become_master(struct subnet_record *d, struct work_record *work)
/* update our server status */
work->ServerType |= SV_TYPE_MASTER_BROWSER;
add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
add_server_entry(d,work,conf_browsing_alias(work->token),
work->ServerType,0,comment,True);
if (work->serverlist == NULL) /* no servers! */
{
@ -317,13 +346,14 @@ void become_master(struct subnet_record *d, struct work_record *work)
case MST_DOMAIN_NONE:
{
if (lp_domain_master())
if (conf_should_domain_master(work->token))
{
work->state = MST_DOMAIN_MEM; /* ... become domain member */
DEBUG(3,("domain first stage: register as domain member\n"));
/* add domain member name */
add_my_name_entry(d,work->work_group,0x1e,nb_type|NB_ACTIVE|NB_GROUP);
add_my_name_entry(d,work->token,work->work_group,0x1e,
nb_type|NB_ACTIVE|NB_GROUP);
/* DON'T do anything else after calling add_my_name_entry() */
return;
@ -338,19 +368,20 @@ void become_master(struct subnet_record *d, struct work_record *work)
case MST_DOMAIN_MEM:
{
if (lp_domain_master())
if (conf_should_domain_master(work->token))
{
work->state = MST_DOMAIN_TST; /* ... possibly become domain master */
DEBUG(3,("domain second stage: register as domain master\n"));
if (lp_domain_logons())
if (conf_should_domain_logon(work->token))
{
work->ServerType |= SV_TYPE_DOMAIN_MEMBER;
add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
add_server_entry(d,work,my_name,work->ServerType,0,comment,True);
}
/* add domain master name */
add_my_name_entry(d,work->work_group,0x1b,nb_type|NB_ACTIVE );
add_my_name_entry(d,work->token,work->work_group,0x1b,
nb_type|NB_ACTIVE );
/* DON'T do anything else after calling add_my_name_entry() */
return;
@ -366,7 +397,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
case MST_DOMAIN_TST: /* while we were still a master browser... */
{
/* update our server status */
if (lp_domain_master())
if (conf_should_domain_master(work->token))
{
struct subnet_record *d1;
uint32 update_type = 0;
@ -378,7 +409,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
SV_TYPE_POTENTIAL_BROWSER;
work->ServerType |= update_type;
add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True);
add_server_entry(d,work,my_name,work->ServerType,0,comment,True);
for (d1 = subnetlist; d1; d1 = d1->next)
{
@ -387,7 +418,7 @@ void become_master(struct subnet_record *d, struct work_record *work)
for (w = d1->workgrouplist; w; w = w->next)
{
struct server_record *s = find_server(w, myname);
struct server_record *s = find_server(w, my_name);
if (strequal(w->work_group, work->work_group))
{
w->ServerType |= update_type;
@ -425,7 +456,21 @@ void become_nonmaster(struct subnet_record *d, struct work_record *work,
{
int new_server_type = work->ServerType;
DEBUG(2,("Becoming non-master for %s\n",work->work_group));
pstring comment;
char *my_name ;
char *my_comment;
BOOL wins = ip_equal(d->bcast_ip, ipgrp);
enum master_state state;
if (!work) return;
my_name = conf_browsing_alias (work->token);
my_comment = conf_browsing_alias_comment(work->token);
StrnCpy(comment, my_comment, 43);
DEBUG(2,("Becoming non-master for %s alias %s\n",work->work_group, my_name));
/* can only remove master or domain types with this function */
remove_type &= SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER;
@ -435,6 +480,7 @@ void become_nonmaster(struct subnet_record *d, struct work_record *work,
remove_type |= SV_TYPE_DOMAIN_MASTER;
new_server_type &= ~remove_type;
state = work->state;
if (!(new_server_type & (SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER)))
{
@ -444,25 +490,40 @@ void become_nonmaster(struct subnet_record *d, struct work_record *work,
work->ElectionCriterion &= ~0x4;
work->state = MST_NONE;
/* announce ourselves as no longer active as a master browser. */
announce_server(d, work, work->work_group, myname, 0, 0);
remove_name_entry(d,MSBROWSE ,0x01);
remove_name_entry(d,work->token,MSBROWSE,0x01);
}
work->ServerType = new_server_type;
if (!(work->ServerType & SV_TYPE_DOMAIN_MASTER))
{
if (work->state == MST_DOMAIN)
if (state == MST_DOMAIN)
{
if (wins)
work->state = MST_NONE;
else
work->state = MST_BROWSER;
remove_name_entry(d,work->work_group,0x1b);
}
remove_name_entry(d,work->token,work->work_group,0x1b);
}
if (!(work->ServerType & SV_TYPE_MASTER_BROWSER))
{
if (work->state >= MST_BROWSER)
if (state >= MST_BROWSER)
work->state = MST_NONE;
remove_name_entry(d,work->work_group,0x1d);
remove_name_entry(d,work->token,work->work_group,0x1d);
}
/* update our internal records with our new server state */
add_server_entry(d, work, my_name, work->ServerType, 0, my_comment, True);
/* announce change in status on local interface */
if (!wins)
{
/* XXXX do we need also to do an announce with a time of zero
if we are no longer a local master browser?
*/
work->needannounce = True;
}
}
@ -489,14 +550,16 @@ void run_elections(void)
{
if (work->RunningElection)
{
char *alias = conf_browsing_alias(work->token);
send_election(d,work->work_group, work->ElectionCriterion,
t-StartupTime,myname);
t-StartupTime,alias);
if (work->ElectionCount++ >= 4)
{
/* I won! now what :-) */
DEBUG(2,(">>> Won election on %s %s <<<\n",
work->work_group,inet_ntoa(d->bcast_ip)));
DEBUG(2,(">>> Won election for %s as %s on %s <<<\n",
work->work_group,alias,inet_ntoa(d->bcast_ip)));
work->RunningElection = False;
work->state = MST_NONE;
@ -533,7 +596,7 @@ static BOOL win_election(struct work_record *work,int version,uint32 criterion,
if (timeup > mytimeup) return(False);
if (timeup < mytimeup) return(True);
if (strcasecmp(myname,name) > 0) return(False);
if (strcasecmp(conf_browsing_alias(work->token),name) > 0) return(False);
return(True);
}
@ -572,29 +635,37 @@ void process_election(struct packet_struct *p,char *buf)
for (work = d->workgrouplist; work; work = work->next)
{
if (!strequal(work->work_group, lp_workgroup()))
continue;
if (!conf_should_local_master(work->token)) continue;
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;
work->state = MST_NONE;
}
} else {
}
else
{
work->needelection = False;
if (work->RunningElection || AM_MASTER(work)) {
if (work->RunningElection || AM_MASTER(work))
{
work->RunningElection = False;
DEBUG(3,(">>> Lost election on %s %s <<<\n",
work->work_group,inet_ntoa(d->bcast_ip)));
/* if we are the master then remove our masterly names */
if (AM_MASTER(work))
{
become_nonmaster(d, work,
SV_TYPE_MASTER_BROWSER|
SV_TYPE_DOMAIN_MASTER);
}
}
}
}
}

@ -21,7 +21,11 @@
Revision History:
14 jan 96: lkcl@pires.co.uk
added multiple workgroup domain master support
added domain master browser support
30 aug 96: lkcl@pires.co.uk
added multiple domain logon support, using extensions to David Chappell's
multiple domain master browser code.
*/
@ -29,13 +33,8 @@
extern int ClientDGRAM;
#define TEST_CODE /* want to debug unknown browse packets */
extern int DEBUGLEVEL;
extern pstring myname;
/****************************************************************************
process a domain logon packet
@ -54,14 +53,18 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len)
pstring outbuf;
int code,reply_code;
struct work_record *work;
char *my_name;
if (!d) return;
if (!(work = find_workgroupstruct(d,dgram->dest_name.name, False)))
return;
if (!lp_domain_logons()) {
DEBUG(3,("No domain logons\n"));
if ((my_name = conf_browsing_alias(work->token)) == NULL) return;
if (!conf_should_domain_logon(work->token))
{
DEBUG(3,("No domain logons for %s (%s)\n", work->work_group, my_name));
return;
}
@ -73,7 +76,7 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len)
char *user = skip_string(machine,1);
logname = skip_string(user,1);
reply_code = 6;
strcpy(reply_name,myname);
strcpy(reply_name, my_name);
strupper(reply_name);
add_slashes = True;
DEBUG(3,("Domain login request from %s(%s) user=%s\n",
@ -87,7 +90,7 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len)
reply_code = 7;
strcpy(reply_name,lp_domain_controller());
if (!*reply_name) {
strcpy(reply_name,myname);
strcpy(reply_name,my_name);
reply_code = 0xC;
}
strupper(reply_name);
@ -121,8 +124,8 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len)
PutUniCode(q,reply_name);
q += 2*(strlen(reply_name) + 1);
PutUniCode(q,lp_workgroup());
q += 2*(strlen(lp_workgroup()) + 1);
PutUniCode(q,work->work_group);
q += 2*(strlen(work->work_group) + 1);
SIVAL(q,0,1);
q += 4;
@ -134,6 +137,6 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len)
q += 2;
send_mailslot_reply(logname,ClientDGRAM,outbuf,PTR_DIFF(q,outbuf),
myname,&dgram->source_name.name[0],0x20,0,p->ip,
my_name,&dgram->source_name.name[0],0x20,0,p->ip,
*iface_ip(p->ip));
}

@ -38,7 +38,92 @@ BOOL CanRecurse = True;
extern pstring scope;
extern struct in_addr ipgrp;
static uint16 name_trn_id=0;
extern uint16 name_trn_id;
/****************************************************************************
process a nmb packet
****************************************************************************/
static void process_nmb(struct packet_struct *p)
{
struct nmb_packet *nmb = &p->packet.nmb;
debug_nmb_packet(p);
switch (nmb->header.opcode)
{
case 8: /* what is this?? */
case NMB_REG:
case NMB_REG_REFRESH:
{
if (nmb->header.response)
{
if (nmb->header.ancount==0) break;
response_netbios_packet(p);
}
else
{
if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
reply_name_reg(p);
}
break;
}
case 0:
{
if (nmb->header.response)
{
switch (nmb->question.question_type)
{
case 0x0:
{
response_netbios_packet(p);
break;
}
}
return;
}
else if (nmb->header.qdcount>0)
{
switch (nmb->question.question_type)
{
case NMB_QUERY:
{
reply_name_query(p);
break;
}
case NMB_STATUS:
{
reply_name_status(p);
break;
}
}
return;
}
break;
}
case NMB_REL:
{
if (nmb->header.qdcount==0 || nmb->header.arcount==0)
{
DEBUG(2,("netbios release packet rejected\n"));
break;
}
if (nmb->header.response)
{
if (nmb->header.ancount==0) break;
response_netbios_packet(p);
}
else
{
reply_name_release(p);
}
break;
}
}
}
/***************************************************************************
@ -65,7 +150,7 @@ void debug_browse_data(char *outbuf, int len)
for (j = 0; j < 16; j++)
{
if (i+j >= len) break;
DEBUG(4, (" %02x", outbuf[i+j]));
DEBUG(4, (" %02x", (unsigned char)outbuf[i+j]));
}
DEBUG(4, ("\n"));
@ -74,23 +159,20 @@ void debug_browse_data(char *outbuf, int len)
}
/***************************************************************************
updates the unique transaction identifier
**************************************************************************/
static void update_name_trn_id(void)
{
if (!name_trn_id)
{
name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100);
}
name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
}
/****************************************************************************
initiate a netbios packet
if we are making queries to samba, then the ip must be zero. in this
instance, the packet is constructed and then dealt with immediately.
netbios packets sent to an ip of zero are dealt with immediately by calling
process_nmb(), in order to allow, for example, querying of samba's WINS
records. at first, this seems like a really dumb thing to do. but then
again, the packet_struct created contains _exactly_ the information
required. the alternative is to take packet_struct out of the loop,
which is a fairly messy operation.
****************************************************************************/
void initiate_netbios_packet(uint16 *id,
BOOL initiate_netbios_packet(uint16 id,
int fd,int quest_type,char *name,int name_type,
int nb_flags,BOOL bcast,BOOL recurse,
struct in_addr to_ip)
@ -98,30 +180,23 @@ void initiate_netbios_packet(uint16 *id,
struct packet_struct p;
struct nmb_packet *nmb = &p.packet.nmb;
struct res_rec additional_rec;
char *packet_type = "unknown";
char *pkt_type = "unknown";
int opcode = -1;
if (!id) return;
if (quest_type == NMB_STATUS) { packet_type = "nmb_status"; opcode = 0; }
if (quest_type == NMB_QUERY ) { packet_type = "nmb_query"; opcode = 0; }
if (quest_type == NMB_REG ) { packet_type = "nmb_reg"; opcode = 5; }
if (quest_type == NMB_REG_REFRESH ) { packet_type = "nmb_reg_refresh"; opcode = 9; }
if (quest_type == NMB_REL ) { packet_type = "nmb_rel"; opcode = 6; }
if (quest_type == NMB_STATUS) { pkt_type = "nmb_status"; opcode = 0; }
if (quest_type == NMB_QUERY ) { pkt_type = "nmb_query"; opcode = 0; }
if (quest_type == NMB_REG ) { pkt_type = "nmb_reg"; opcode = 5; }
if (quest_type == NMB_REG_REFRESH) { pkt_type="nmb_reg_refresh"; opcode=9; }
if (quest_type == NMB_REL ) { pkt_type = "nmb_rel"; opcode = 6; }
DEBUG(4,("initiating netbios packet: %s %s(%x) (bcast=%s) %s\n",
packet_type, name, name_type, BOOLSTR(bcast), inet_ntoa(to_ip)));
pkt_type, name, name_type, BOOLSTR(bcast), inet_ntoa(to_ip)));
if (opcode == -1) return;
if (opcode == -1) return False;
bzero((char *)&p,sizeof(p));
if (*id == 0xffff) {
update_name_trn_id();
*id = name_trn_id; /* allow resending with same id */
}
nmb->header.name_trn_id = *id;
nmb->header.name_trn_id = id;
nmb->header.opcode = opcode;
nmb->header.response = False;
@ -170,12 +245,21 @@ void initiate_netbios_packet(uint16 *id,
p.timestamp = time(NULL);
p.packet_type = NMB_PACKET;
if (zero_ip(to_ip)) /* samba's own ip */
{
DEBUG(4,("process packet ourselves\n"));
/* respond internally to the packet. */
process_nmb(&p);
}
else
{
if (!send_packet(&p)) {
DEBUG(3,("send_packet to %s %d failed\n",inet_ntoa(p.ip),p.port));
*id = 0xffff;
return False;
}
}
return;
return True;
}
@ -274,7 +358,16 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id,
debug_nmb_packet(&p);
if (zero_ip(p.ip)) /* samba's own ip */
{
DEBUG(4,("process response packet ourselves\n"));
/* respond internally to the packet. */
process_nmb(&p);
}
else
{
send_packet(&p);
}
}
@ -379,83 +472,6 @@ static void process_dgram(struct packet_struct *p)
}
}
/****************************************************************************
process a nmb packet
****************************************************************************/
static void process_nmb(struct packet_struct *p)
{
struct nmb_packet *nmb = &p->packet.nmb;
debug_nmb_packet(p);
switch (nmb->header.opcode)
{
case 8: /* what is this?? */
case NMB_REG:
case NMB_REG_REFRESH:
{
if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
if (nmb->header.response)
response_netbios_packet(p); /* response to registration dealt
with here */
else
reply_name_reg(p);
break;
}
case 0:
{
if (nmb->header.response)
{
switch (nmb->question.question_type)
{
case 0x0:
{
response_netbios_packet(p);
break;
}
}
return;
}
else if (nmb->header.qdcount>0)
{
switch (nmb->question.question_type)
{
case NMB_QUERY:
{
reply_name_query(p);
break;
}
case NMB_STATUS:
{
reply_name_status(p);
break;
}
}
return;
}
break;
}
case NMB_REL:
{
if (nmb->header.qdcount==0 || nmb->header.arcount==0)
{
DEBUG(2,("netbios release packet rejected\n"));
break;
}
if (nmb->header.response)
response_netbios_packet(p); /* response to reply dealt with
in here */
else
reply_name_release(p);
break;
}
}
}
/*******************************************************************
run elements off the packet queue till its empty
******************************************************************/

@ -35,6 +35,21 @@ extern pstring scope;
extern struct in_addr ipzero;
extern struct in_addr ipgrp;
uint16 name_trn_id=0;
/***************************************************************************
updates the unique transaction identifier
**************************************************************************/
void update_name_trn_id(void)
{
if (!name_trn_id)
{
name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100);
}
name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
}
/***************************************************************************
deals with an entry before it dies
@ -60,7 +75,7 @@ static void dead_netbios_entry(struct subnet_record *d,
/* IMPORTANT: see query_refresh_names() */
if ((!NAME_GROUP(n->nb_flags)))
if ((!NAME_GROUP(n->reply.nb_flags)))
{
struct subnet_record *d1 = find_subnet(ipgrp);
if (d1)
@ -116,8 +131,8 @@ static void dead_netbios_entry(struct subnet_record *d,
*/
add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name,
n->nb_flags, GET_TTL(0),
n->reply_to_ip, False, n->reply_to_ip);
n->reply.nb_flags, GET_TTL(0),
n->reply.ip, False, n->reply.ip);
if (!n->bcast)
{
@ -141,8 +156,8 @@ static void dead_netbios_entry(struct subnet_record *d,
/* IMPORTANT: see response_name_reg() */
name_register_work(d,n->name.name,n->name.name_type,
n->nb_flags, n->ttl, n->reply_to_ip, n->bcast);
name_register_work(d,n->token,n->name.name,n->name.name_type,
n->source, &n->reply, n->ttl, n->reply.ip, n->bcast);
}
else
{
@ -191,9 +206,9 @@ void expire_netbios_response_entries()
if (n->repeat_count > 0)
{
/* resend the entry */
initiate_netbios_packet(&n->response_id, n->fd, n->quest_type,
initiate_netbios_packet(n->response_id, n->fd, n->quest_type,
n->name.name, n->name.name_type,
n->nb_flags, n->bcast, n->recurse, n->send_ip);
n->reply.nb_flags, n->bcast, n->recurse, n->send_ip);
n->repeat_time += n->repeat_interval; /* XXXX ms needed */
n->repeat_count--;
@ -217,17 +232,47 @@ void expire_netbios_response_entries()
/****************************************************************************
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
WINS server specified, the packet will NOT be sent.
****************************************************************************/
struct response_record *queue_netbios_pkt_wins(struct subnet_record *d,
void queue_netbios_pkt_wins(struct subnet_record *d,
int fd,int quest_type,enum state_type state,
char *name,int name_type,int nb_flags, time_t ttl,
int token, char *name,int name_type,
enum name_source source, int nb_flags, time_t ttl,
int server_type, char *my_name, char *my_comment,
BOOL bcast,BOOL recurse,
struct in_addr send_ip, struct in_addr reply_to_ip)
{
queue_netbios_packet(d,fd, quest_type, state,
token, name, name_type, source, nb_flags, ttl,
server_type,my_name,my_comment,
bcast, recurse, send_ip, reply_to_ip);
}
/****************************************************************************
initiate a netbios name query to find someone's or someones' IP
this is intended to be used (not exclusively) for broadcasting to
master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
complete lists across a wide area network
a broadcast message will be over-ridden if the packet it sent to an
ip of zero, and the packet will be sent to the WINS name server instead,
if it exists. if samba is configured to be a WINS server, then the
packet will be dealt with _as if_ it had been sent on the network,
but in fact the function process_nmb() is called.
****************************************************************************/
void queue_netbios_packet(struct subnet_record *d,
int fd,int quest_type,enum state_type state,
int token, char *name, int name_type,
enum name_source source, int nb_flags, time_t ttl,
int server_type, char *my_name, char *my_comment,
BOOL bcast,BOOL recurse,
struct in_addr send_ip, struct in_addr reply_to_ip)
{
struct response_record *n;
/* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */
if (ip_equal(send_ip, ipgrp)) return;
/* XXXX note: please see rfc1001.txt section 10 for details on this
function: it is currently inappropriate to use this - it will do
for now - once there is a clarification of B, M and P nodes and
@ -253,50 +298,38 @@ struct response_record *queue_netbios_pkt_wins(struct subnet_record *d,
}
}
if (zero_ip(send_ip)) return NULL;
return queue_netbios_packet(d,fd, quest_type, state,
name, name_type, nb_flags, ttl,
server_type,my_name,my_comment,
bcast, recurse, send_ip, reply_to_ip);
}
/****************************************************************************
initiate a netbios name query to find someone's or someones' IP
this is intended to be used (not exclusively) for broadcasting to
master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
complete lists across a wide area network
****************************************************************************/
struct response_record *queue_netbios_packet(struct subnet_record *d,
int fd,int quest_type,enum state_type state,char *name,
int name_type,int nb_flags, time_t ttl,
int server_type, char *my_name, char *my_comment,
BOOL bcast,BOOL recurse,
struct in_addr send_ip, struct in_addr reply_to_ip)
{
struct in_addr wins_ip = ipgrp;
struct response_record *n;
uint16 id = 0xffff;
/* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */
if (ip_equal(wins_ip, send_ip)) return NULL;
initiate_netbios_packet(&id, fd, quest_type, name, name_type,
nb_flags, bcast, recurse, send_ip);
if (id == 0xffff) {
DEBUG(4,("did not initiate netbios packet: %s\n", inet_ntoa(send_ip)));
return NULL;
if (zero_ip(send_ip))
{
/* doing a netbios query to samba as a WINS server, internally */
if (lp_wins_support()) /* samba is a WINS server */
{
DEBUG(4,("queue netbios packet with ourselves...\n"));
bcast = False;
}
else
{
return;
}
}
if ((n = make_response_queue_record(state,id,fd,
quest_type,name,name_type,nb_flags,ttl,
server_type,my_name, my_comment,
bcast,recurse,send_ip,reply_to_ip)))
update_name_trn_id();
/* queue the response expected because if we do a query with an ip
of zero, we are expecting to hear from ourself immediately */
if ((n = make_response_queue_record(state, name_trn_id, fd, quest_type,
token, name, name_type, source, nb_flags, ttl,
server_type, my_name, my_comment,
bcast, recurse, send_ip, reply_to_ip)))
{
add_response_record(d,n);
return n;
}
return NULL;
if (!initiate_netbios_packet(name_trn_id, fd, quest_type, name, name_type,
nb_flags, bcast, recurse, send_ip))
{
/* packet wasn't sent - not expecting a response */
DEBUG(4,("did not initiate netbios packet: %s\n", inet_ntoa(send_ip)));
remove_response_record(d, n);
return;
}
}

@ -51,7 +51,7 @@ extern uint16 nb_type; /* samba's NetBIOS type */
XXXX at present, the name is removed _even_ if a WINS server says keep it.
****************************************************************************/
void remove_name_entry(struct subnet_record *d, char *name,int type)
void remove_name_entry(struct subnet_record *d, int token, char *name,int type)
{
/* XXXX BUG: if samba is offering WINS support, it should still broadcast
a de-registration packet to the local subnet before removing the
@ -80,17 +80,18 @@ void remove_name_entry(struct subnet_record *d, char *name,int type)
don't really own */
remove_netbios_name(d,name,type,SELF,n2->ip_flgs[0].ip);
if (ip_equal(d->bcast_ip, ipgrp)) {
if (!lp_wins_support()) {
/* not a WINS server: we have to release them on the network */
if (ip_equal(d->bcast_ip, ipgrp))
{
/* use WINS. this function can now be used to _either_
do the release on samba's own database _or_ release
the name with an arbitrary WINS server */
queue_netbios_pkt_wins(d,ClientNMB,NMB_REL,NAME_RELEASE,
name, type, 0, 0,0,NULL,NULL,
token, name, type, SELF, 0, 0,0,NULL,NULL,
False, True, ipzero, ipzero);
}
} else {
/* local interface: release them on the network */
queue_netbios_packet(d,ClientNMB,NMB_REL,NAME_RELEASE,
name, type, 0, 0,0,NULL,NULL,
token, name, type, SELF, 0, 0,0,NULL,NULL,
True, True, d->bcast_ip, d->bcast_ip);
}
}
@ -103,7 +104,8 @@ void remove_name_entry(struct subnet_record *d, char *name,int type)
it's just a matter of when this will be done (e.g after a time-out).
****************************************************************************/
void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
void add_my_name_entry(struct subnet_record *d, int token,
char *name,int type,int nb_flags)
{
BOOL re_reg = False;
struct nmb_name n;
@ -123,6 +125,7 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
if (ip_equal(d->bcast_ip, ipgrp))
{
#if 0
if (lp_wins_support())
{
/* we are a WINS server. */
@ -131,25 +134,37 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
actually be true
*/
struct nmb_ip data;
data.nb_flags = nb_flags;
putip(&data.ip, ipzero);
DEBUG(4,("samba as WINS server adding: "));
/* this will call add_netbios_entry() */
name_register_work(d, name, type, nb_flags,0, ipzero, False);
name_register_work(d,token,name,type,SELF,&data,GET_TTL(0),ipzero,False);
}
else
{
#endif
/* ipzero when not using an arbitrary wins server results in the
netbios packet being short-circuited to process_nmb()
*/
/* a time-to-live allows us to refresh this name with the WINS server. */
queue_netbios_pkt_wins(d,ClientNMB,
re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
name, type, nb_flags, GET_TTL(0),0,NULL,NULL,
token, name, type, SELF, nb_flags, GET_TTL(0),0,NULL,NULL,
False, True, ipzero, ipzero);
#if 0
}
#endif
}
else
{
/* broadcast the packet, but it comes from ipzero */
queue_netbios_packet(d,ClientNMB,
re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
name, type, nb_flags, GET_TTL(0),0,NULL,NULL,
token, name, type, SELF, nb_flags, GET_TTL(0),0,NULL,NULL,
True, True, d->bcast_ip, ipzero);
}
}
@ -161,6 +176,8 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
void add_my_names(void)
{
struct subnet_record *d;
int token;
/* each subnet entry, including WINS pseudo-subnet, has SELF names */
/* XXXX if there was a transport layer added to samba (ipx/spx etc) then
@ -169,34 +186,58 @@ void add_my_names(void)
for (d = subnetlist; d; d = d->next)
{
BOOL wins = lp_wins_support() && ip_equal(d->bcast_ip,ipgrp);
BOOL wins = ip_equal(d->bcast_ip,ipgrp);
add_my_name_entry(d, myname,0x20,nb_type|NB_ACTIVE);
add_my_name_entry(d, myname,0x03,nb_type|NB_ACTIVE);
add_my_name_entry(d, myname,0x00,nb_type|NB_ACTIVE);
add_my_name_entry(d, myname,0x1f,nb_type|NB_ACTIVE);
for (token = 0; token < get_num_workgroups(); token++)
{
char *my_name = conf_browsing_alias(token);
char *wg_name = conf_workgroup_name(token);
if (my_name)
{
add_my_name_entry(d, token, my_name,0x20,nb_type|NB_ACTIVE);
add_my_name_entry(d, token, my_name,0x03,nb_type|NB_ACTIVE);
add_my_name_entry(d, token, my_name,0x00,nb_type|NB_ACTIVE);
add_my_name_entry(d, token, my_name,0x1f,nb_type|NB_ACTIVE);
}
if (wg_name && conf_should_domain_logon(token))
{
/* the 0x1c is to do with domain logons */
add_my_name_entry(d, token, wg_name,0x1c,nb_type|NB_ACTIVE|NB_GROUP);
}
}
/* these names are added permanently (ttl of zero) and will NOT be
refreshed with the WINS server */
add_netbios_entry(d,"*",0x0,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
add_netbios_entry(d,"*",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
add_netbios_entry(d,"__SAMBA__",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
add_netbios_entry(d,"__SAMBA__",0x00,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
if (lp_domain_logons()) {
/* XXXX the 0x1c is apparently something to do with domain logons */
add_my_name_entry(d, lp_workgroup(),0x1c,nb_type|NB_ACTIVE|NB_GROUP);
}
}
if (lp_domain_master() && (d = find_subnet(ipgrp)))
/* check becoming a domain master under all browser aliases */
if ((d = find_subnet(ipgrp)))
{
struct work_record *work = find_workgroupstruct(d, lp_workgroup(), True);
for (token = 0; token < get_num_workgroups(); token++)
{
if (conf_should_domain_master(token))
{
char *work_name = conf_workgroup_name(token);
if (work_name)
{
struct work_record *work = find_workgroupstruct(d,work_name,True);
if (work && work->state == MST_NONE)
{
work->state = MST_DOMAIN_NONE;
become_master(d, work);
}
}
}
}
}
}
@ -219,35 +260,7 @@ void remove_my_names()
/* get all SELF names removed from the WINS server's database */
/* XXXX note: problem occurs if this removes the wrong one! */
remove_name_entry(d,n->name.name, n->name.name_type);
}
}
}
}
/*******************************************************************
refresh my own names
******************************************************************/
void refresh_my_names(time_t t)
{
struct subnet_record *d;
for (d = subnetlist; d; d = d->next)
{
struct name_record *n;
for (n = d->namelist; n; n = n->next)
{
/* each SELF name has an individual time to be refreshed */
if (n->source == SELF && n->refresh_time < time(NULL) &&
n->death_time != 0)
{
add_my_name_entry(d,n->name.name,n->name.name_type,
n->ip_flgs[0].nb_flags);
/* they get a new lease on life :-) */
n->death_time += GET_TTL(0);
n->refresh_time += GET_TTL(0);
remove_name_entry(d, -1, n->name.name, n->name.name_type);
}
}
}
@ -289,7 +302,7 @@ void query_refresh_names(void)
for (n = d->namelist; n; n = n->next)
{
/* only do unique, registered names */
/* only do unique, registered names. */
if (n->source != REGISTER) continue;
if (!NAME_GROUP(n->ip_flgs[0].nb_flags)) continue;
@ -299,8 +312,8 @@ void query_refresh_names(void)
DEBUG(3,("Polling name %s\n", namestr(&n->name)));
queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM,
n->name.name, n->name.name_type,
0,0,0,NULL,NULL,
-1,n->name.name, n->name.name_type,
n->source,0,0,0,NULL,NULL,
False,False,n->ip_flgs[0].ip,n->ip_flgs[0].ip);
count++;
}

@ -294,8 +294,8 @@ void reply_name_reg(struct packet_struct *p)
/* initiate some enquiries to the current owner. */
queue_netbios_packet(d,ClientNMB,NMB_QUERY,
NAME_REGISTER_CHALLENGE,
reply_name->name,reply_name->name_type,
nb_flags,0,0,NULL,NULL,
-1,reply_name->name,reply_name->name_type,
n->source, nb_flags,0,0,NULL,NULL,
False, False, n->ip_flgs[0].ip, p->ip);
}
else

@ -46,38 +46,29 @@ extern struct in_addr ipzero;
response for a reg release received. samba has asked a WINS server if it
could release a name.
**************************************************************************/
static void response_name_release(struct subnet_record *d,
struct packet_struct *p)
static void response_name_release(struct nmb_ip *data, struct nmb_name *name,
struct subnet_record *d)
{
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)
if (data)
{
/* IMPORTANT: see expire_netbios_response_entries() */
struct in_addr found_ip;
putip((char*)&found_ip,&nmb->answers->rdata[2]);
/* NOTE: we only release our own names at present */
if (ismyip(found_ip))
if (ismyip(data->ip))
{
name_unregister_work(d,name,type);
name_unregister_work(d, name->name, name->name_type);
}
else
{
DEBUG(2,("name release for different ip! %s %s\n",
inet_ntoa(found_ip),
namestr(&nmb->question.question_name)));
inet_ntoa(data->ip),namestr(name)));
}
}
else
{
DEBUG(2,("name release for %s rejected!\n",
namestr(&nmb->question.question_name)));
DEBUG(2,("name release for %s rejected!\n",namestr(name)));
/* XXXX PANIC! what to do if it's one of samba's own names? */
@ -91,34 +82,25 @@ static void response_name_release(struct subnet_record *d,
/****************************************************************************
response for a reg request received
**************************************************************************/
static void response_name_reg(struct subnet_record *d, struct packet_struct *p)
static void response_name_reg(struct nmb_ip *data, struct nmb_name *name,
time_t ttl, BOOL bcast, struct in_addr source_ip,
struct subnet_record *d, enum name_source source, int token)
{
struct nmb_packet *nmb = &p->packet.nmb;
char *name = nmb->question.question_name.name;
int type = nmb->question.question_name.name_type;
BOOL bcast = nmb->header.nm_flags.bcast;
DEBUG(4,("response name registration received!\n"));
if (nmb->header.rcode == 0 && nmb->answers->rdata)
if (data)
{
/* IMPORTANT: see expire_netbios_response_entries() */
int nb_flags = nmb->answers->rdata[0];
int ttl = nmb->answers->ttl;
struct in_addr found_ip;
putip((char*)&found_ip,&nmb->answers->rdata[2]);
name_register_work(d,name,type,nb_flags,ttl,found_ip,bcast);
name_register_work(d, token, name->name,name->name_type,
source, data, ttl, source_ip, bcast);
}
else
{
DEBUG(1,("name registration for %s rejected!\n",
namestr(&nmb->question.question_name)));
DEBUG(1,("name registration for %s rejected!\n", namestr(name)));
/* oh dear. we have problems. possibly unbecome a master browser. */
name_unregister_work(d,name,type);
name_unregister_work(d,name->name,name->name_type);
}
}
@ -127,8 +109,8 @@ static void response_name_reg(struct subnet_record *d, struct packet_struct *p)
response from a name query announce host
NAME_QUERY_ANNOUNCE_HOST is dealt with here
****************************************************************************/
static void response_announce_host(struct nmb_name *ans_name,
struct nmb_packet *nmb,
static void response_announce_host(struct nmb_ip *data,
struct nmb_name *ans_name,
struct response_record *n, struct subnet_record *d)
{
DEBUG(4, ("Name query at %s ip %s - ",
@ -143,7 +125,7 @@ static void response_announce_host(struct nmb_name *ans_name,
return;
}
if (nmb->header.rcode == 0 && nmb->answers->rdata)
if (data)
{
/* we had sent out a name query to the current owner
of a name because someone else wanted it. now they
@ -153,27 +135,25 @@ static void response_announce_host(struct nmb_name *ans_name,
/* first check all the details are correct */
int nb_flags = nmb->answers->rdata[0];
struct in_addr found_ip;
putip((char*)&found_ip,&nmb->answers->rdata[2]);
if (nb_flags != n->nb_flags)
if (data->nb_flags != n->reply.nb_flags)
{
/* someone gave us the wrong nb_flags as a reply. oops. */
/* XXXX should say to them 'oi! release that name!' */
DEBUG(4,("expected nb_flags: %d\n", n->nb_flags));
DEBUG(4,("unexpected nb_flags: %d\n", nb_flags));
DEBUG(4,("expected nb_flags: %d\n", n->reply.nb_flags));
DEBUG(4,("unexpected nb_flags: %d\n", data->nb_flags));
return;
}
/* do an announce host */
do_announce_host(ANN_HostAnnouncement,
n->my_name , 0x00, d->myip,
n->name.name, 0x1d, found_ip,
n->name.name, 0x1d, data->ip,
n->ttl,
n->my_name, n->server_type, n->my_comment);
n->my_name, n->server_type,
HOST_MAJOR_VERSION, HOST_MINOR_VERSION,
HOST_BROWSE_VERSION, HOST_BROWSE_SIGNATURE,
n->my_comment);
}
else
{
@ -196,9 +176,9 @@ static void response_server_check(struct nmb_name *ans_name,
/* initiate a name status check on the server that replied */
queue_netbios_packet(d,ClientNMB,NMB_STATUS, cmd,
ans_name->name, ans_name->name_type,
0,0,0,NULL,NULL,
False,False,n->send_ip,n->reply_to_ip);
-1,ans_name->name, ans_name->name_type,
0,0,0,0,NULL,NULL,
False,False,n->send_ip,n->reply.ip);
}
@ -299,7 +279,7 @@ static BOOL interpret_node_status(struct subnet_record *d,
and NAME_STATUS_SRV_CHK dealt with here.
****************************************************************************/
static void response_name_status_check(struct in_addr ip,
struct nmb_packet *nmb, BOOL bcast,
char *data, BOOL bcast,
struct response_record *n, struct subnet_record *d)
{
/* NMB_STATUS arrives: contains workgroup name and server name required.
@ -308,13 +288,11 @@ static void response_name_status_check(struct in_addr ip,
struct nmb_name name;
fstring serv_name;
if (interpret_node_status(d,nmb->answers->rdata,
&name,name.name_type,serv_name,ip,bcast))
if (interpret_node_status(d,data,&name,name.name_type,serv_name,ip,bcast))
{
if (*serv_name)
{
sync_server(n->state,serv_name,
name.name,name.name_type, n->send_ip);
sync_server(n->state,serv_name,name.name,name.name_type,n->send_ip);
}
}
else
@ -328,7 +306,7 @@ static void response_name_status_check(struct in_addr ip,
response from a name query for secured WINS registration. a state of
NAME_REGISTER_CHALLENGE is dealt with here.
****************************************************************************/
static void response_name_query_register(struct nmb_packet *nmb,
static void response_name_query_register(struct nmb_ip *data,
struct nmb_name *ans_name,
struct response_record *n, struct subnet_record *d)
{
@ -347,7 +325,7 @@ static void response_name_query_register(struct nmb_packet *nmb,
return;
}
if (nmb->header.rcode == 0 && nmb->answers->rdata)
if (data)
{
/* we had sent out a name query to the current owner
of a name because someone else wanted it. now they
@ -357,32 +335,27 @@ static void response_name_query_register(struct nmb_packet *nmb,
/* first check all the details are correct */
int nb_flags = nmb->answers->rdata[0];
struct in_addr found_ip;
putip((char*)&found_ip,&nmb->answers->rdata[2]);
if (nb_flags != n->nb_flags)
if (data->nb_flags != n->reply.nb_flags)
{
/* someone gave us the wrong nb_flags as a reply. oops. */
/* XXXX should say to them 'oi! release that name!' */
DEBUG(4,("expected nb_flags: %d\n", n->nb_flags));
DEBUG(4,("unexpected nb_flags: %d\n", nb_flags));
DEBUG(4,("expected nb_flags: %d\n", n->reply.nb_flags));
DEBUG(4,("unexpected nb_flags: %d\n", data->nb_flags));
return;
}
if (!ip_equal(n->send_ip, found_ip))
if (!ip_equal(n->send_ip, data->ip))
{
/* someone gave us the wrong ip as a reply. oops. */
/* XXXX should say to them 'oi! release that name!' */
DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip)));
DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip)));
DEBUG(4,("unexpected ip: %s\n", inet_ntoa(data->ip)));
return;
}
DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
DEBUG(4, (" OK: %s\n", inet_ntoa(data->ip)));
/* fine: now tell the other host they can't have the name */
register_ip = n->send_ip;
@ -393,14 +366,14 @@ static void response_name_query_register(struct nmb_packet *nmb,
DEBUG(4, (" NEGATIVE RESPONSE!\n"));
/* the owner didn't want the name: the other host can have it */
register_ip = n->reply_to_ip;
register_ip = n->reply.ip;
new_owner = True;
}
/* register the old or the new owners' ip */
add_name_respond(d, n->fd, d->myip, n->response_id,&n->name,n->nb_flags,
GET_TTL(0), register_ip,
new_owner, n->reply_to_ip);
add_name_respond(d, n->fd, d->myip, n->response_id,&n->name,
n->reply.nb_flags, GET_TTL(0), register_ip,
new_owner, n->reply.ip);
}
@ -408,7 +381,7 @@ static void response_name_query_register(struct nmb_packet *nmb,
response from a name query to sync browse lists or to update our netbios
entry. states of type NAME_QUERY_SYNC and NAME_QUERY_CONFIRM
****************************************************************************/
static void response_name_query_sync(struct nmb_packet *nmb,
static void response_name_query_sync(struct nmb_ip *data,
struct nmb_name *ans_name, BOOL bcast,
struct response_record *n, struct subnet_record *d)
{
@ -422,22 +395,17 @@ static void response_name_query_sync(struct nmb_packet *nmb,
return;
}
if (nmb->header.rcode == 0 && nmb->answers->rdata)
if (data)
{
int nb_flags = nmb->answers->rdata[0];
struct in_addr found_ip;
putip((char*)&found_ip,&nmb->answers->rdata[2]);
if (!ip_equal(n->send_ip, found_ip))
if (!ip_equal(n->send_ip, data->ip))
{
/* someone gave us the wrong ip as a reply. oops. */
DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip)));
DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip)));
DEBUG(4,("unexpected ip: %s\n", inet_ntoa(data->ip)));
return;
}
DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
DEBUG(4, (" OK: %s\n", inet_ntoa(data->ip)));
if (n->state == NAME_QUERY_SYNC_LOCAL ||
n->state == NAME_QUERY_SYNC_REMOTE)
@ -449,15 +417,15 @@ static void response_name_query_sync(struct nmb_packet *nmb,
/* the server is there: sync quick before it (possibly) dies! */
sync_browse_lists(d, work, ans_name->name, ans_name->name_type,
found_ip, local_list_only);
data->ip, local_list_only);
}
}
else
{
/* update our netbios name list (re-register it if necessary) */
add_netbios_entry(d, ans_name->name, ans_name->name_type,
nb_flags,GET_TTL(0),REGISTER,
found_ip,False,!bcast);
data->nb_flags,GET_TTL(0),REGISTER,
data->ip,False,!bcast);
}
}
else
@ -635,11 +603,14 @@ static BOOL response_compatible(struct response_record *n,
case NAME_REGISTER:
{
/* rfc1002.txt states that nmb->answers->rr_type must equal 0x20 */
#if 0
if (nmb->answers->rr_type != NMB_REG)
{
DEBUG(1,("Name register reply has wrong answer rr_type\n"));
return False;
}
#endif
break;
}
@ -685,27 +656,62 @@ static BOOL response_compatible(struct response_record *n,
/****************************************************************************
process the response packet received
****************************************************************************/
static void response_process(struct subnet_record *d, struct packet_struct *p,
struct response_record *n, struct nmb_packet *nmb,
BOOL bcast, struct nmb_name *ans_name)
void response_process(struct in_addr ip, struct subnet_record *d,
struct response_record *n,
int rcode, char *nmb_data, struct nmb_name *q_name,
time_t ttl, BOOL bcast, struct nmb_name *ans_name)
{
switch (n->state)
{
case NAME_RELEASE:
{
response_name_release(d, p);
struct nmb_ip found;
struct nmb_ip *data = NULL;
if (rcode == 0 && nmb_data)
{
/* copy the netbios flags and the ip address out of the reply data */
found.nb_flags = nmb_data[0];
putip((char*)&found.ip,&nmb_data[2]);
data = &found;
}
response_name_release(data, q_name, d);
break;
}
case NAME_REGISTER:
{
response_name_reg(d, p);
struct nmb_ip found;
struct nmb_ip *data = NULL;
if (rcode == 0 && nmb_data)
{
/* copy the netbios flags and the ip address out of the reply data */
found.nb_flags = nmb_data[0];
putip((char*)&found.ip,&nmb_data[2]);
data = &found;
}
response_name_reg(data,ans_name,ttl,bcast,ip,d,n->source,n->token);
break;
}
case NAME_REGISTER_CHALLENGE:
{
response_name_query_register(nmb, ans_name, n, d);
struct nmb_ip found;
struct nmb_ip *data = NULL;
if (rcode == 0 && nmb_data)
{
/* copy the netbios flags and the ip address out of the reply data */
found.nb_flags = nmb_data[0];
putip((char*)&found.ip,&nmb_data[2]);
data = &found;
}
response_name_query_register(data, ans_name, n, d);
break;
}
@ -720,13 +726,24 @@ static void response_process(struct subnet_record *d, struct packet_struct *p,
case NAME_STATUS_DOM_SRV_CHK:
case NAME_STATUS_SRV_CHK:
{
response_name_status_check(p->ip, nmb, bcast, n, d);
response_name_status_check(ip,nmb_data,bcast,n,d);
break;
}
case NAME_QUERY_ANNOUNCE_HOST:
{
response_announce_host(ans_name, nmb, n, d);
struct nmb_ip found;
struct nmb_ip *data = NULL;
if (rcode == 0 && nmb_data)
{
/* copy the netbios flags and the ip address out of the reply data */
found.nb_flags = nmb_data[0];
putip((char*)&found.ip,&nmb_data[2]);
data = &found;
}
response_announce_host(data, ans_name, n, d);
break;
}
@ -734,7 +751,18 @@ static void response_process(struct subnet_record *d, struct packet_struct *p,
case NAME_QUERY_SYNC_LOCAL:
case NAME_QUERY_SYNC_REMOTE:
{
response_name_query_sync(nmb, ans_name, bcast, n, d);
struct nmb_ip found;
struct nmb_ip *data = NULL;
if (rcode == 0 && nmb_data)
{
/* copy the netbios flags and the ip address out of the reply data */
found.nb_flags = nmb_data[0];
putip((char*)&found.ip,&nmb_data[2]);
data = &found;
}
response_name_query_sync(data,ans_name,bcast,n,d);
break;
}
case NAME_QUERY_MST_CHK:
@ -780,7 +808,9 @@ void response_netbios_packet(struct packet_struct *p)
return;
}
/* args wrong way round: spotted by ccm@shentel.net */
DEBUG(4,("response packet received: %s %d\n",
inet_ntoa(p->ip),n->response_id));
if (!same_net(d->bcast_ip, p->ip, d->mask_ip)) /* copes with WINS 'subnet' */
{
DEBUG(2,("response from %s. ", inet_ntoa(p->ip)));
@ -816,7 +846,13 @@ void response_netbios_packet(struct packet_struct *p)
return;
/* now deal with the current state */
response_process(d, p, n, nmb, bcast, ans_name);
response_process(p->ip, d, n,
nmb->header.rcode,
nmb->answers->rdata,
question,
nmb->answers->ttl, bcast, ans_name);
remove_response_record(d, n);
}

@ -23,6 +23,9 @@
14 jan 96: lkcl@pires.co.uk
added multiple workgroup domain master support
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/
#include "includes.h"
@ -30,41 +33,34 @@
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 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;
extern pstring myname;
/****************************************************************************
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)
void reset_server(struct work_record *work, char *name, int state, struct in_addr ip)
{
char outbuf[20];
char *p;
@ -80,7 +76,7 @@ void reset_server(char *name, int state, struct in_addr ip)
name,inet_ntoa(ip),state));
send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
myname,name,0x20,0x1d,ip,*iface_ip(ip));
conf_browsing_alias(work->token),name,0x20,0x1d,ip,*iface_ip(ip));
}
@ -110,7 +106,7 @@ void tell_become_backup(void)
num_servers++;
if (strequal(myname, s->serv.name)) continue;
if (strequal(conf_browsing_alias(work->token), s->serv.name)) continue;
if (s->serv.type & SV_TYPE_BACKUP_BROWSER) {
num_backups++;
@ -135,8 +131,8 @@ void tell_become_backup(void)
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,
/* type 11 request from conf_browsing_alias(work->token)(20) to WG(1e) for SERVER */
do_announce_request(s->serv.name, s->serv.name, work->work_group,
ANN_BecomeBackup, 0x20, 0x1e, d->bcast_ip);
}
}
@ -150,8 +146,23 @@ void tell_become_backup(void)
******************************************************************/
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);
if (!strequal(dgram->dest_name .scope,scope )) return True;
return False;
}
/*******************************************************************
am I listening on a name. XXXX check the type of name as well.
******************************************************************/
BOOL listening_name(struct work_record *work, struct nmb_name *n)
{
if (strequal(n->name,conf_browsing_alias(work->token)) ||
strequal(n->name,work->work_group) ||
strequal(n->name,MSBROWSE))
{
return(True);
}
return(False);
}
@ -278,26 +289,40 @@ static void process_master_announce(struct packet_struct *p,char *buf)
struct in_addr ip = dgram->header.source_ip;
struct subnet_record *d = find_subnet(ip);
struct subnet_record *mydomain = find_subnet(*iface_bcast(ip));
char *to_name = dgram->dest_name.name; /* our primary name or an alias */
char *name = buf;
struct work_record *work;
char *work_name;
int token;
name[15] = 0;
DEBUG(3,("Master Announce from %s (%s)\n",name,inet_ntoa(ip)));
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;
token = conf_alias_to_token(to_name);
for (work = mydomain->workgrouplist; work; work = work->next)
if (token == -1)
{
if (AM_MASTER(work))
DEBUG(4, ("alias %s not known\n", to_name));
return;
}
/* carry on only if we are a domain master under the server alias */
if (!conf_should_domain_master(token)) return;
/* Convert the server name by which the master browser
called this server to the workgroup name. */
if ((work_name = conf_workgroup_name(token)) == (char*)NULL)
{
DEBUG(4, ("process_master_announce(): no alias for \"%s\"\n", to_name));
return;
}
/* merge browse lists with them */
add_browser_entry(name,0x1b, work->work_group,30,ip,True);
}
}
add_browser_entry(name, 0x1b, work_name,30,ip,True);
}
/*******************************************************************
@ -318,6 +343,7 @@ 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);
unsigned int pick;
uint32 info = IVAL(buf,1); /* XXXX caller's incremental info */
char *buf1;
@ -329,59 +355,40 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
if (count <= 0) return;
pick = sys_random(count);
/* 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(ip)));
if (count != pick) continue;
/* 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 */
DEBUG(4,("Searching for backup browser %s...\n", buf1));
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"));
/* XXXX function needs work */
continue;
if ((d = find_subnet(back_ip)))
{
struct subnet_record *d1;
for (d1 = subnetlist; d1; d1 = d1->next)
if ((d = find_subnet(ip)) != NULL)
{
struct work_record *work;
for (work = d1->workgrouplist; work; work = work->next)
for (work = d->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);
queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK,
work->token,work->work_group,0x1d,
0,0,0,0,NULL,NULL,
False,False,ipzero,ipzero);
return;
}
}
}
}
}
}
/****************************************************************************
send a backup list response.
**************************************************************************/
static void send_backup_list(char *work_name, struct nmb_name *src_name,
static void send_backup_list(struct work_record *work, struct nmb_name *src_name,
int token, uint32 info,
int name_type, struct in_addr ip)
{
@ -391,8 +398,8 @@ static void send_backup_list(char *work_name, struct nmb_name *src_name,
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));
work->work_group, inet_ntoa(ip),
conf_browsing_alias(work->token),0x0,theirname,0x0));
if (name_type == 0x1d)
{
@ -424,16 +431,8 @@ static void send_backup_list(char *work_name, struct nmb_name *src_name,
#if 0
for (d = subnetlist; d; d = d->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;
@ -451,8 +450,8 @@ static void send_backup_list(char *work_name, struct nmb_name *src_name,
/* 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)))
if ((name_type == 0x1d && (s->serv.type & SV_TYPE_MASTER_BROWSER)) ||
(name_type == 0x1b && (s->serv.type & SV_TYPE_DOMAIN_BROWSER)))
{
DEBUG(4, ("%s ", s->serv.name));
@ -462,13 +461,10 @@ static void send_backup_list(char *work_name, struct nmb_name *src_name,
p = skip_string(p,1);
}
}
}
}
#endif
count++;
strcpy(p,myname);
strcpy(p,conf_browsing_alias(work->token));
strupper(p);
p = skip_string(p,1);
@ -488,7 +484,7 @@ static void send_backup_list(char *work_name, struct nmb_name *src_name,
debug_browse_data(outbuf, len);
}
send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
myname,theirname,0x0,0x0,ip,*iface_ip(ip));
conf_browsing_alias(work->token),theirname,0x0,0x0,ip,*iface_ip(ip));
}
@ -532,7 +528,7 @@ static void process_send_backup_list(struct packet_struct *p,char *buf)
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,
send_backup_list(work,&dgram->source_name,
token,info,name_type,ip);
return;
}
@ -582,13 +578,16 @@ static void process_reset_browser(struct packet_struct *p,char *buf)
/* totally delete all servers and start afresh */
if (state & 0x2)
{
/* remove all workgroups (and their servers) from database */
struct subnet_record *d;
for (d = subnetlist; d; d = d->next)
{
struct work_record *work;
for (work=d->workgrouplist;work;work=remove_workgroup(d,work,True));
}
add_my_subnets(lp_workgroup());
/* add all known workgroups back into database */
add_workgroups_to_subnets();
}
/* stop browsing altogether. i don't think this is a good idea! */
@ -611,39 +610,43 @@ static void process_announce_request(struct packet_struct *p,char *buf)
struct in_addr ip = dgram->header.source_ip;
struct subnet_record *d = find_subnet(ip);
int token = CVAL(buf,0);
int wg_token = 0;
char *name = buf+1;
char *samba_alias;
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;
/* look up the index for this workgroup */
wg_token = conf_workgroup_name_to_token(dgram->dest_name.name,myname);
if (wg_token == -1) 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.
/* check that samba is participating in this workgroup */
if (!conf_should_workgroup_member(wg_token)) return;
if (strequal(dgram->dest_name, lp_workgroup()) return; ???
*/
/* find samba's NetBIOS alias it operates under in this workgroup */
if ((samba_alias = conf_browsing_alias(wg_token)) == (char*)NULL) return;
/* ignore announce requests from samba under its own alias.
this should no longer happen because code has been added to
discard packets from ourself. */
if (strequal(dgram->source_name.name,samba_alias)) return;
if (!d) 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))
for (work = d->workgrouplist; work; work = work->next)
{
work->needannounce = True;
}
if (wg_token == work->token) work->needannounce = True;
}
}
/****************************************************************************
process a browse frame
****************************************************************************/

@ -23,6 +23,10 @@
14 jan 96: lkcl@pires.co.uk
added multiple workgroup domain master support
30 July 96: David.Chappell@mail.trincoll.edu
Expanded multiple workgroup domain master browser support.
*/
#include "includes.h"
@ -165,10 +169,10 @@ static void expire_names_and_servers(void)
time_t t = time(NULL);
if (!lastrun) lastrun = t;
if (t < lastrun + 5) return;
if (t < lastrun + 15) return; /* give samba time to check its names */
lastrun = t;
expire_names(t);
check_expire_names(t); /* this checks samba's NetBIOS names */
expire_servers(t);
}
@ -293,7 +297,6 @@ static void process(void)
while (True)
{
time_t t = time(NULL);
run_election = check_elections();
listen_for_packets(run_election);
@ -310,7 +313,6 @@ static void process(void)
expire_names_and_servers();
expire_netbios_response_entries();
refresh_my_names(t);
write_browse_list();
do_browser_lists();
@ -491,6 +493,14 @@ static void usage(char *pname)
init_structs();
/* reads the smbbrowse.conf file. this is an alias mapping between
workgroups and samba NetBIOS aliases. samba can therefore be
a member of multiple workgroups, a local master browser of
multiple workgroups, or a domain master browser of multiple
workgroups, via each NetBIOS name alias. the aliases MUST
be unique for this to work. */
read_smbbrowse_conf(myname);
reload_services(True);
set_samba_nb_type();
@ -520,7 +530,7 @@ static void usage(char *pname)
DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
}
add_my_subnets(lp_workgroup());
add_workgroups_to_subnets();
DEBUG(3,("Checked names\n"));

@ -117,7 +117,10 @@ static BOOL add_info(struct subnet_record *d, struct work_record *work, int serv
}
if (w)
add_server_entry(d,w,sname,stype,lp_max_ttl(),cmnt,False);
{
add_server_entry(d,w,sname,stype & ~SV_TYPE_LOCAL_LIST_ONLY,
lp_max_ttl(),cmnt,False);
}
}
}
}

@ -106,33 +106,34 @@ extern int coding_system;
*/
typedef struct
{
char *szPrintcapname;
char *szLockDir;
char *szRootdir;
char *szAutoServices;
char *szCharacterSet;
char *szConfigFile;
char *szDefaultService;
char *szDfree;
char *szMsgCommand;
char *szHostsEquiv;
char *szServerString;
char *szAutoServices;
char *szPasswdProgram;
char *szPasswdChat;
char *szLogFile;
char *szConfigFile;
char *szSMBPasswdFile;
char *szPasswordServer;
char *szSocketOptions;
char *szValidChars;
char *szWorkGroup;
char *szDomainController;
char *szUsernameMap;
char *szCharacterSet;
char *szLogonScript;
char *szSmbrun;
char *szWINSserver;
char *szHostsEquiv;
char *szInterfaces;
char *szLockDir;
char *szLogFile;
char *szLogonScript;
char *szMsgCommand;
char *szPasswdChat;
char *szPasswdProgram;
char *szPasswordServer;
char *szPrintcapname;
char *szRemoteAnnounce;
char *szRootdir;
char *szServerComment;
char *szServerString;
char *szSmbrun;
char *szSMBPasswdFile;
char *szSocketAddress;
char *szSocketOptions;
char *szUsernameMap;
char *szValidChars;
char *szWINSserver;
char *szWorkGroup;
int max_log_size;
int mangled_stack;
int max_xmit;
@ -152,6 +153,7 @@ typedef struct
BOOL bWINSsupport;
BOOL bWINSproxy;
BOOL bPreferredMaster;
BOOL bLocalMaster;
BOOL bDomainMaster;
BOOL bDomainLogons;
BOOL bEncryptPasswords;
@ -382,6 +384,7 @@ struct parm_struct
{"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL},
{"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
{"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
{"server comment", P_STRING, P_GLOBAL, &Globals.szServerComment, NULL},
{"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL},
{"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
{"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
@ -425,6 +428,7 @@ struct parm_struct
{"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},
{"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, 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},
@ -560,6 +564,9 @@ static void init_globals(void)
string_set(&Globals.szSocketAddress, "0.0.0.0");
sprintf(s,"Samba %s",VERSION);
string_set(&Globals.szServerString,s);
strcpy(s,"Samba %v"); /* samba comment */
string_sub(s,"%v",VERSION);
string_set(&Globals.szServerComment,s);
Globals.bLoadPrinters = True;
Globals.bUseRhosts = False;
Globals.max_packet = 65535;
@ -584,8 +591,9 @@ static void init_globals(void)
Globals.bSyslogOnly = False;
Globals.os_level = 0;
Globals.max_ttl = 60*60*4; /* 2 hours default */
Globals.bPreferredMaster = True;
Globals.bDomainMaster = False;
Globals.bPreferredMaster = True; /* force election on startup */
Globals.bLocalMaster = True; /* master browser on local subnet */
Globals.bDomainMaster = False; /* maintain wide area network browse list */
Globals.bDomainLogons = False;
Globals.bBrowseList = True;
Globals.bWINSsupport = True;
@ -724,6 +732,7 @@ FN_GLOBAL_STRING(lp_smbrun,&Globals.szSmbrun)
FN_GLOBAL_STRING(lp_configfile,&Globals.szConfigFile)
FN_GLOBAL_STRING(lp_smb_passwd_file,&Globals.szSMBPasswdFile)
FN_GLOBAL_STRING(lp_serverstring,&Globals.szServerString)
FN_GLOBAL_STRING(lp_server_comment,&Globals.szServerComment)
FN_GLOBAL_STRING(lp_printcapname,&Globals.szPrintcapname)
FN_GLOBAL_STRING(lp_lockdir,&Globals.szLockDir)
FN_GLOBAL_STRING(lp_rootdir,&Globals.szRootdir)
@ -747,6 +756,7 @@ FN_GLOBAL_STRING(lp_socket_address,&Globals.szSocketAddress)
FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)
FN_GLOBAL_BOOL(lp_local_master,&Globals.bLocalMaster)
FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)

@ -439,7 +439,7 @@ static void PackDriverData(struct pack_desc* desc)
}
static int check_printq_info(struct pack_desc* desc,
int uLevel, const char* id1, const char* id2)
int uLevel, char *id1, const char* id2)
{
desc->subformat = NULL;
switch( uLevel ) {
@ -812,10 +812,7 @@ static int get_server_info(uint32 servertype,
if (!next_token(&ptr,s->name , NULL)) continue;
if (!next_token(&ptr,stype , NULL)) continue;
if (!next_token(&ptr,s->comment, NULL)) continue;
if (!next_token(&ptr,s->domain , NULL)) {
/* this allows us to cope with an old nmbd */
strcpy(s->domain,lp_workgroup());
}
if (!next_token(&ptr,s->domain , NULL)) continue;
if (sscanf(stype,"%X",&s->type) != 1) {
DEBUG(4,("r:host file "));
@ -983,8 +980,22 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
if (strcmp(str1, "WrLehDz") == 0) {
StrnCpy(domain, p, sizeof(fstring)-1);
} else {
StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1);
}
else
{
/* a server will connect to us under one of samba's NetBIOS
name aliases, and by not giving us a domain name it
assumes we know which domain it's talking about.
do a look-up for the workgroup name against the name
the host connected to us as.
*/
char *work_alias;
work_alias = conf_alias_to_workgroup(local_machine); /* look-up */
if (work_alias)
StrnCpy(domain, work_alias, sizeof(fstring)-1);
}
if (lp_browse_list())
@ -1349,7 +1360,7 @@ static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
DEBUG(3,("Set password for <%s>\n",user));
if (password_ok(user,pass1,strlen(pass1),NULL,False) &&
if (password_ok(user,pass1,strlen(pass1),NULL) &&
chgpasswd(user,pass1,pass2))
{
SSVAL(*rparam,0,NERR_Success);
@ -1668,9 +1679,19 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
pstring comment;
uint32 servertype=DFLT_SERVER_TYPE;
char *work_alias;
char domain[16];
work_alias = conf_alias_to_workgroup(local_machine); /* look-up */
if (work_alias)
StrnCpy(domain, work_alias, sizeof(fstring)-1);
else
*domain = 0;
strcpy(comment,lp_serverstring());
if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
if ((count=get_server_info(SV_TYPE_ALL,&servers,domain))>0) {
for (i=0;i<count;i++)
if (strequal(servers[i].name,local_machine)) {
servertype = servers[i].type;
@ -1723,6 +1744,14 @@ static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
char *p2;
extern pstring sesssetup_user;
int level = SVAL(p,0);
char domain[17];
char *work_alias = conf_alias_to_workgroup(local_machine); /* look-up */
if (work_alias)
StrnCpy(domain, work_alias, 16);
else
StrnCpy(domain, lp_workgroup(), 16);
DEBUG(4,("NetWkstaGetInfo level %d\n",level));
@ -1753,7 +1782,7 @@ static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
p += 4;
SIVAL(p,0,PTR_DIFF(p2,*rdata));
strcpy(p2,lp_workgroup());
StrCpy(p2,domain);
p2 = skip_string(p2,1);
p += 4;
@ -1762,7 +1791,7 @@ static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
p += 2;
SIVAL(p,0,PTR_DIFF(p2,*rdata));
strcpy(p2,lp_workgroup()); /* login domain?? */
strcpy(p2,domain); /* login domain?? */
p2 = skip_string(p2,1);
p += 4;
@ -1985,6 +2014,14 @@ static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
int uLevel;
struct pack_desc desc;
char* name;
char domain[17];
char *work_alias = conf_alias_to_workgroup(local_machine); /* look-up */
if (work_alias)
StrnCpy(domain, work_alias, 16);
else
StrnCpy(domain, lp_workgroup(), 16);
uLevel = SVAL(p,0);
name = p + 2;
@ -2027,7 +2064,7 @@ static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
strupper(mypath);
PACKS(&desc,"z",mypath); /* computer */
}
PACKS(&desc,"z",lp_workgroup());/* domain */
PACKS(&desc,"z",domain);/* domain */
PACKS(&desc,"z",lp_logon_script()); /* script path */
PACKI(&desc,"D",0); /* reserved */
}

@ -44,6 +44,8 @@ extern BOOL case_sensitive;
extern pstring sesssetup_user;
extern int Client;
extern pstring local_machine;
/* this macro should always be used to extract an fnum (smb_fid) from
a packet to ensure chaining works correctly */
#define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
@ -251,9 +253,18 @@ static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
{
uint32 dword1;
uint16 word1;
char * workgroup = lp_workgroup();
int wglen = strlen(workgroup);
int wglen;
int i;
char domain[17];
char *work_alias = conf_alias_to_workgroup(local_machine); /* look-up */
if (work_alias)
StrnCpy(domain, work_alias, 16);
else
StrnCpy(domain, lp_workgroup(), 16);
wglen = strlen(domain);
/* All kinds of mysterious numbers here */
*rdata_len = 90 + 2 * wglen;
@ -279,7 +290,7 @@ static void LsarpcTNP3(char *data,char **rdata, int *rdata_len)
SIVAL(*rdata,0x2C,4);
SIVAL(*rdata,0x34,wglen);
for ( i = 0 ; i < wglen ; i++ )
(*rdata)[0x38 + i * 2] = workgroup[i];
(*rdata)[0x38 + i * 2] = domain[i];
/* Now fill in the rest */
i = 0x38 + wglen * 2;

@ -37,6 +37,7 @@ extern connection_struct Connections[];
extern files_struct Files[];
extern BOOL case_sensitive;
extern pstring sesssetup_user;
extern fstring local_machine;
extern int Client;
/* this macro should always be used to extract an fnum (smb_fid) from
@ -54,7 +55,6 @@ int reply_special(char *inbuf,char *outbuf)
int msg_flags = CVAL(inbuf,1);
pstring name1,name2;
extern fstring remote_machine;
extern fstring local_machine;
char *p;
*name1 = *name2 = 0;
@ -319,6 +319,14 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
BOOL guest=False;
BOOL computer_id=False;
char domain[17];
char *work_alias = conf_alias_to_workgroup(local_machine); /* look-up */
if (work_alias)
StrnCpy(domain, work_alias, 16);
else
StrnCpy(domain, lp_workgroup(), 16);
*smb_apasswd = 0;
sess_uid = SVAL(inbuf,smb_uid);
@ -404,12 +412,12 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
first. This is superior as the passwords are mixed case 128 length unicode */
if(smb_ntpasslen && !guest)
{
if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL,True))
if(!password_ok(user,smb_ntpasswd,smb_ntpasslen,NULL))
DEBUG(0,("NT Password did not match ! Defaulting to Lanman\n"));
else
valid_nt_password = True;
}
if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL,False))
if (!valid_nt_password && !guest && !password_ok(user,smb_apasswd,smb_apasslen,NULL))
{
if (!computer_id && lp_security() >= SEC_USER) {
#if (GUEST_SESSSETUP == 0)
@ -452,7 +460,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
p = smb_buf(outbuf);
strcpy(p,"Unix"); p = skip_string(p,1);
strcpy(p,"Samba "); strcat(p,VERSION); p = skip_string(p,1);
strcpy(p,lp_workgroup()); p = skip_string(p,1);
strcpy(p,domain); p = skip_string(p,1);
set_message(outbuf,3,PTR_DIFF(p,smb_buf(outbuf)),False);
/* perhaps grab OS version here?? */
}

@ -3746,6 +3746,8 @@ static void usage(char *pname)
DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
}
read_smbbrowse_conf(myhostname);
process();
close_sockets();

@ -100,6 +100,7 @@ int main(int argc,char *argv[])
BOOL find_master=False;
BOOL find_status=False;
int i;
static pstring servicesf = CONFIGFILE;
DEBUGLEVEL = 1;
*lookup = 0;
@ -110,7 +111,7 @@ int main(int argc,char *argv[])
charset_initialise();
while ((opt = getopt(argc, argv, "p:d:B:i:SMh")) != EOF)
while ((opt = getopt(argc, argv, "p:d:B:i:s:SMh")) != EOF)
switch (opt)
{
case 'B':
@ -129,6 +130,9 @@ int main(int argc,char *argv[])
case 'd':
DEBUGLEVEL = atoi(optarg);
break;
case 's':
strcpy(servicesf, optarg);
break;
case 'h':
usage();
exit(0);
@ -143,6 +147,11 @@ int main(int argc,char *argv[])
exit(1);
}
if (!lp_load(servicesf,True)) {
fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
return (-1);
}
load_interfaces();
init_structs();
if (!open_sockets()) return(1);