From f24e341e7e4d8726b98d3a0f83b24f61817fe536 Mon Sep 17 00:00:00 2001 From: Samba Release Account Date: Fri, 23 Aug 1996 10:17:30 +0000 Subject: [PATCH] - fixed bugs in nmb response packet checking. - added multiple workgroup code - samba can register under different (unique) NetBIOS aliases, one per workgroup it joins. lkcl --- source/include/nameserv.h | 58 +-- source/include/proto.h | 349 +++++------------- source/lib/util.c | 666 ++++++++++++++++----------------- source/nameannounce.c | 421 +++++++++++---------- source/namebrowse.c | 57 +-- source/nameconf.c | 349 ++++++++++++++++++ source/namedbname.c | 268 +++++++------- source/namedbresp.c | 10 +- source/namedbserver.c | 89 +++-- source/namedbsubnet.c | 151 ++++---- source/namedbwork.c | 120 +++--- source/nameelect.c | 306 ++++++++------- source/namepacket.c | 327 ++++++++-------- source/nameresp.c | 381 ++++++++++--------- source/nameserv.c | 243 ++++++------ source/nameservreply.c | 2 +- source/nameservresp.c | 757 ++++++++++++++++++++------------------ source/namework.c | 412 +++++++++++---------- source/nmbd/nmbd.c | 142 +++---- source/nmbsync.c | 77 ++-- source/param/loadparm.c | 52 +-- source/smbd/ipc.c | 38 +- source/smbd/server.c | 2 + 23 files changed, 2863 insertions(+), 2414 deletions(-) create mode 100644 source/nameconf.c diff --git a/source/include/nameserv.h b/source/include/nameserv.h index e4876bac570..404c0531e52 100644 --- a/source/include/nameserv.h +++ b/source/include/nameserv.h @@ -99,19 +99,19 @@ enum master_state enum state_type { - NAME_STATUS_DOM_SRV_CHK, - NAME_STATUS_SRV_CHK, - NAME_REGISTER_CHALLENGE, - NAME_REGISTER, - NAME_RELEASE, - NAME_QUERY_CONFIRM, - NAME_QUERY_ANNOUNCE_HOST, - NAME_QUERY_SYNC_LOCAL, - NAME_QUERY_SYNC_REMOTE, - NAME_QUERY_DOM_SRV_CHK, - NAME_QUERY_SRV_CHK, - NAME_QUERY_FIND_MST, - NAME_QUERY_MST_CHK + NAME_STATUS_DOM_SRV_CHK, + NAME_STATUS_SRV_CHK, + NAME_REGISTER_CHALLENGE, + NAME_REGISTER, + NAME_RELEASE, + NAME_QUERY_CONFIRM, + NAME_QUERY_ANNOUNCE_HOST, + NAME_QUERY_SYNC_LOCAL, + NAME_QUERY_SYNC_REMOTE, + NAME_QUERY_DOM_SRV_CHK, + NAME_QUERY_SRV_CHK, + NAME_QUERY_FIND_MST, + NAME_QUERY_MST_CHK }; /* a netbios name structure */ @@ -121,6 +121,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 @@ -148,16 +156,16 @@ struct name_record /* browse and backup server cache for synchronising browse list */ struct browse_cache_record { - struct browse_cache_record *next; - struct browse_cache_record *prev; - - pstring name; - int type; - pstring group; - struct in_addr ip; - time_t sync_time; - BOOL synced; - BOOL local; + struct browse_cache_record *next; + struct browse_cache_record *prev; + + pstring name; + int type; + pstring group; + struct in_addr ip; + time_t sync_time; + BOOL synced; + BOOL local; }; /* this is used to hold the list of servers in my domain, and is */ @@ -214,9 +222,10 @@ struct response_record int fd; int quest_type; struct nmb_name name; - int nb_flags; + struct nmb_ip reply; time_t ttl; + int token; /* unique workgroup token id */ int server_type; fstring my_name; fstring my_comment; @@ -224,7 +233,6 @@ struct response_record BOOL bcast; BOOL recurse; struct in_addr send_ip; - struct in_addr reply_to_ip; int num_msgs; diff --git a/source/include/proto.h b/source/include/proto.h index e20238fee42..293179d4ab0 100644 --- a/source/include/proto.h +++ b/source/include/proto.h @@ -1,39 +1,24 @@ /* This file is automatically generated with "make proto". DO NOT EDIT */ -/*The following definitions come from access.c */ +/*The following definitions come from - */ BOOL check_access(int snum); BOOL allow_access(char *deny_list,char *allow_list,struct from_host *client); BOOL fromhost(int sock,struct from_host *f); - -/*The following definitions come from charcnv.c */ - char *unix2dos_format(char *str,BOOL overwrite); char *dos2unix_format(char *str, BOOL overwrite); int interpret_character_set(char *str, int def); - -/*The following definitions come from charset.c */ - void charset_initialise(void); void add_char_string(char *s); - -/*The following definitions come from chgpasswd.c */ - BOOL chat_with_program(char *passwordprogram,char *name,char *chatsequence); BOOL chgpasswd(char *name,char *oldpass,char *newpass); BOOL chgpasswd(char *name,char *oldpass,char *newpass); - -/*The following definitions come from client.c */ - void setup_pkt(char *outbuf); void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir); void cmd_help(void); BOOL reopen_connection(char *inbuf,char *outbuf); char *smb_errstr(char *inbuf); - -/*The following definitions come from clientutil.c */ - void cli_setup_pkt(char *outbuf); BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len, int *param_len, char **data,char **param); @@ -48,9 +33,6 @@ BOOL cli_send_trans_request(char *outbuf, int trans, char *name, int fid, int fl BOOL cli_open_sockets(int port); BOOL cli_reopen_connection(char *inbuf,char *outbuf); char *smb_errstr(char *inbuf); - -/*The following definitions come from clitar.c */ - int strslashcmp(const char *s1, const char *s2); void cmd_block(void); void cmd_tarmode(void); @@ -59,9 +41,6 @@ void cmd_tar(char *inbuf, char *outbuf); int process_tar(char *inbuf, char *outbuf); int clipfind(char **aret, int ret, char *tok); int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind); - -/*The following definitions come from dir.c */ - void init_dptrs(void); char *dptr_path(int key); char *dptr_wcard(int key); @@ -87,17 +66,8 @@ int TellDir(void *p); void DirCacheAdd(char *path,char *name,char *dname,int snum); char *DirCacheCheck(char *path,char *name,int snum); void DirCacheFlush(int snum); - -/*The following definitions come from fault.c */ - void fault_setup(void (*fn)()); - -/*The following definitions come from getsmbpass.c */ - char *getsmbpass(char *prompt) ; - -/*The following definitions come from interface.c */ - void load_interfaces(void); void iface_set_default(char *ip,char *bcast,char *nmask); BOOL ismyip(struct in_addr ip); @@ -107,23 +77,15 @@ struct in_addr *iface_n_ip(int n); struct in_addr *iface_bcast(struct in_addr ip); struct in_addr *iface_nmask(struct in_addr ip); struct in_addr *iface_ip(struct in_addr ip); - -/*The following definitions come from ipc.c */ - int reply_trans(char *inbuf,char *outbuf); - -/*The following definitions come from kanji.c */ - int interpret_coding_system(char *str, int def); - -/*The following definitions come from loadparm.c */ - char *lp_string(char *s); char *lp_logfile(void); 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 +108,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); @@ -251,9 +214,6 @@ int lp_numservices(void); void lp_dump(void); int lp_servicenumber(char *pszServiceName); char *volume_label(int snum); - -/*The following definitions come from locking.c */ - BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type); int file_lock(char *name,int timeout); void file_unlock(int fd); @@ -268,9 +228,6 @@ int get_share_mode(int cnum,struct stat *sbuf,int *pid); void del_share_mode(int fnum); BOOL set_share_mode(int fnum,int mode); void clean_share_modes(void); - -/*The following definitions come from mangle.c */ - int str_checksum(char *s); BOOL is_8_3(char *fname); void create_mangled_stack(int size); @@ -278,192 +235,157 @@ BOOL check_mangled_stack(char *s); BOOL is_mangled(char *s); void mangle_name_83(char *s); BOOL name_map_mangle(char *OutName,BOOL need83,int snum); - -/*The following definitions come from md4.c */ - - -/*The following definitions come from message.c */ - int reply_sends(char *inbuf,char *outbuf); int reply_sendstrt(char *inbuf,char *outbuf); int reply_sendtxt(char *inbuf,char *outbuf); 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); + int name_type, + struct in_addr ip); 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 *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); 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); + char *name, char *comment, time_t ttl, int server_type); void announce_host(void); void announce_master(void); void announce_remote(void); - -/*The following definitions come from namebrowse.c */ - void expire_browse_cache(time_t t); struct browse_cache_record *add_browser_entry(char *name, int type, char *wg, - time_t ttl, struct in_addr ip, BOOL local); + time_t ttl, struct in_addr ip, BOOL local); void do_browser_lists(void); - -/*The following definitions come from namedbname.c */ - +int get_num_workgroups(void); +int conf_workgroup_name_to_token(const char *workgroup_name, + const char *default_name); +char *conf_workgroup_name(int token); +int conf_should_workgroup_member(int token); +int conf_should_local_master(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(const char *alias); +int conf_alias_to_token(const char *alias); +void read_smbbrowse_conf(char *default_name); void set_samba_nb_type(void); BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2); BOOL ms_browser_name(char *name, int type); void remove_name(struct subnet_record *d, struct name_record *n); struct name_record *find_name(struct name_record *n, - struct nmb_name *name, - int search); + struct nmb_name *name, + int search); struct name_record *find_name_search(struct subnet_record **d, - struct nmb_name *name, - int search, struct in_addr ip); + struct nmb_name *name, + int search, struct in_addr ip); void dump_names(void); void load_netbios_names(void); void remove_netbios_name(struct subnet_record *d, - char *name,int type, enum name_source source, - struct in_addr ip); + char *name,int type, enum name_source source, + struct in_addr ip); 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); + char *name, int type, int nb_flags, + int ttl, enum name_source source, struct in_addr ip, + BOOL new_only,BOOL wins); +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); - -/*The following definitions come from namedbresp.c */ - + struct nmb_name *question, + struct in_addr ip, int Time, int search); void add_response_record(struct subnet_record *d, struct response_record *n); 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, 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 *find_response_record(struct subnet_record **d, uint16 id); - -/*The following definitions come from namedbserver.c */ - void remove_old_servers(struct work_record *work, time_t t, - BOOL remove_all); + BOOL remove_all); struct server_record *find_server(struct work_record *work, char *name); struct server_record *add_server_entry(struct subnet_record *d, - struct work_record *work, - char *name,int servertype, - int ttl,char *comment, - BOOL replace); + struct work_record *work, + char *name,int servertype, + int ttl,char *comment, + BOOL replace); void expire_servers(time_t t); - -/*The following definitions come from namedbsubnet.c */ - 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); struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, - struct in_addr mask_ip, - char *name, BOOL add, BOOL lmhosts); + struct in_addr mask_ip, + char *name, BOOL add, BOOL lmhosts); void write_browse_list(void); - -/*The following definitions come from namedbwork.c */ - struct work_record *remove_workgroup(struct subnet_record *d, - struct work_record *work, - BOOL remove_all_servers); + struct work_record *work, + BOOL remove_all_servers); struct work_record *find_workgroupstruct(struct subnet_record *d, - fstring name, BOOL add); + fstring name, BOOL add); void dump_workgroups(void); - -/*The following definitions come from nameelect.c */ - void check_master_browser(void); 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); + 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, + 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); + int remove_type); void run_elections(void); void process_election(struct packet_struct *p,char *buf); BOOL check_elections(void); - -/*The following definitions come from namelogon.c */ - 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, - int fd,int quest_type,char *name,int name_type, - int nb_flags,BOOL bcast,BOOL recurse, - struct in_addr to_ip); +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); void reply_netbios_packet(struct packet_struct *p1,int trn_id, - int rcode, int rcv_code, int opcode, BOOL recurse, - struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, - char *data,int len); + int rcode, int rcv_code, int opcode, BOOL recurse, + struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, + char *data,int len); void queue_packet(struct packet_struct *packet); void run_packet_queue(); void listen_for_packets(BOOL run_election); BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname, - char *dstname,int src_type,int dest_type, - struct in_addr dest_ip,struct in_addr src_ip); - -/*The following definitions come from namequery.c */ - + char *dstname,int src_type,int dest_type, + struct in_addr dest_ip,struct in_addr src_ip); BOOL name_status(int fd,char *name,int name_type,BOOL recurse, struct in_addr to_ip,char *master,char *rname, void (*fn)()); BOOL name_query(int fd,char *name,int name_type, BOOL bcast,BOOL recurse, struct in_addr to_ip, struct in_addr *ip,void (*fn)()); - -/*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, - 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 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); - -/*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 queue_netbios_pkt_wins(struct subnet_record *d, + int fd,int quest_type,enum state_type state, + int token, 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); +void queue_netbios_packet(struct subnet_record *d, + int fd,int quest_type,enum state_type state, + int token, 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); +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 */ - void add_name_respond(struct subnet_record *d, int fd, struct in_addr from_ip, uint16 response_id, struct nmb_name *name, @@ -477,25 +399,18 @@ void reply_name_release(struct packet_struct *p); void reply_name_reg(struct packet_struct *p); void reply_name_status(struct packet_struct *p); 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 */ - BOOL reload_services(BOOL test); - -/*The following definitions come from nmblib.c */ - void debug_nmb_packet(struct packet_struct *p); char *namestr(struct nmb_name *n); void free_nmb_packet(struct nmb_packet *nmb); @@ -504,23 +419,11 @@ struct packet_struct *read_packet(int fd,enum packet_type packet_type); void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope); BOOL send_packet(struct packet_struct *p); struct packet_struct *receive_packet(int fd,enum packet_type type,int t); - -/*The following definitions come from nmblookup.c */ - int main(int argc,char *argv[]); - -/*The following definitions come from nmbsync.c */ - char *getsmbpass(char *pass); void sync_browse_lists(struct subnet_record *d, struct work_record *work, - char *name, int nm_type, struct in_addr ip, BOOL local); - -/*The following definitions come from params.c */ - + char *name, int nm_type, struct in_addr ip, BOOL local); BOOL pm_process(char *pszFileName,BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *)); - -/*The following definitions come from password.c */ - void generate_next_challenge(char *challenge); BOOL set_challenge(char *challenge); BOOL last_challenge(char *challenge); @@ -540,14 +443,8 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen, BOOL check_hosts_equiv(char *user); BOOL server_cryptkey(char *buf); BOOL server_validate(char *buf); - -/*The following definitions come from pcap.c */ - BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname); void pcap_printer_fn(void (*fn)()); - -/*The following definitions come from pipes.c */ - int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize); BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, @@ -557,31 +454,19 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data, int mdrcnt,int mprcnt, char **rdata,char **rparam, int *rdata_len,int *rparam_len); - -/*The following definitions come from predict.c */ - int read_predict(int fd,int offset,char *buf,char **ptr,int num); void do_read_prediction(); void invalidate_read_prediction(int fd); - -/*The following definitions come from printing.c */ - void lpq_reset(int snum); void print_file(int fnum); int get_printqueue(int snum,int cnum,print_queue_struct **queue, print_status_struct *status); void del_printqueue(int cnum,int snum,int jobid); void status_printjob(int cnum,int snum,int jobid,int status); - -/*The following definitions come from quotas.c */ - BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize); - -/*The following definitions come from replace.c */ - char *Strstr(char *s, char *p); time_t Mktime(struct tm *t); int InNetGr(char *group,char *host,char *user,char *dom); @@ -589,9 +474,6 @@ void *malloc_wrapped(int size,char *file,int line); void *realloc_wrapped(void *ptr,int size,char *file,int line); void free_wrapped(void *ptr,char *file,int line); void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line); - -/*The following definitions come from reply.c */ - int reply_special(char *inbuf,char *outbuf); int reply_tcon(char *inbuf,char *outbuf); int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize); @@ -642,9 +524,6 @@ int reply_writebmpx(char *inbuf,char *outbuf); int reply_writebs(char *inbuf,char *outbuf); int reply_setattrE(char *inbuf,char *outbuf); int reply_getattrE(char *inbuf,char *outbuf); - -/*The following definitions come from server.c */ - mode_t unix_mode(int cnum,int dosmode); int dos_mode(int cnum,char *path,struct stat *sbuf); int dos_chmod(int cnum,char *fname,int dosmode,struct stat *st); @@ -685,9 +564,6 @@ void standard_sub(int cnum,char *s); char *smb_fn_name(int type); int chain_reply(char *inbuf,char *outbuf,int size,int bufsize); int construct_reply(char *inbuf,char *outbuf,int size,int bufsize); - -/*The following definitions come from shmem.c */ - BOOL shm_open( char *file_name, int size); BOOL shm_close( void ); shm_offset_t shm_alloc(int size); @@ -701,9 +577,6 @@ BOOL shm_unlock(void); BOOL shm_get_usage(int *bytes_free, int *bytes_used, int *bytes_overhead); - -/*The following definitions come from smbencrypt.c */ - void str_to_key(uchar *str,uchar *key); void D1(uchar *k, uchar *d, uchar *out); void E1(uchar *k, uchar *d, uchar *out); @@ -712,28 +585,13 @@ void E_P24(uchar *p21, uchar *c8, uchar *p24); void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24); void E_md4hash(uchar *passwd, uchar *p16); void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24); - -/*The following definitions come from smbpass.c */ - int pw_file_lock(char *name, int type, int secs); int pw_file_unlock(int fd); struct smb_passwd *get_smbpwnam(char *name); - -/*The following definitions come from smbpasswd.c */ - - -/*The following definitions come from smbrun.c */ - - -/*The following definitions come from status.c */ - void Ucrit_addUsername(pstring username); unsigned int Ucrit_checkUsername(pstring username); void Ucrit_addPid(int pid); unsigned int Ucrit_checkPid(int pid); - -/*The following definitions come from system.c */ - int sys_select(fd_set *fds,struct timeval *tval); int sys_select(fd_set *fds,struct timeval *tval); int sys_unlink(char *fname); @@ -749,16 +607,7 @@ int sys_rename(char *from, char *to); int sys_chmod(char *fname,int mode); int sys_chown(char *fname,int uid,int gid); int sys_chroot(char *dname); - -/*The following definitions come from testparm.c */ - - -/*The following definitions come from testprns.c */ - int main(int argc, char *argv[]); - -/*The following definitions come from time.c */ - void GetTimeOfDay(struct timeval *tval); void TimeInit(void); int TimeDiff(time_t t); @@ -773,35 +622,22 @@ time_t make_unix_date2(void *date_ptr); time_t make_unix_date3(void *date_ptr); BOOL set_filetime(char *fname,time_t mtime); char *timestring(void ); - -/*The following definitions come from trans2.c */ - int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize); int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize); int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize); int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize); - -/*The following definitions come from ufc.c */ - char *ufc_crypt(char *key,char *salt); - -/*The following definitions come from uid.c */ - void init_uid(void); BOOL become_guest(void); BOOL become_user(int cnum, int uid); BOOL unbecome_user(void ); int smbrun(char *cmd,char *outfile); - -/*The following definitions come from username.c */ - +void write_utmp(int dologin, int connection, int pid, + char *from_addr, char *username); char *get_home_dir(char *user); void map_username(char *user); struct passwd *Get_Pwnam(char *user,BOOL allow_change); BOOL user_in_list(char *user,char *list); - -/*The following definitions come from util.c */ - void setup_logging(char *pname,BOOL interactive); void reopen_logs(void); BOOL is_a_socket(int fd); @@ -821,9 +657,9 @@ time_t file_modtime(char *fname); BOOL directory_exist(char *dname,struct stat *st); uint32 file_size(char *file_name); char *attrib_string(int mode); -int StrCaseCmp(char *s, char *t); -int StrnCaseCmp(char *s, char *t, int n); -BOOL strequal(char *s1,char *s2); +int StrCaseCmp(const char *s, const char *t); +int StrnCaseCmp(const char *s, const char *t, int n); +BOOL strequal(const char *s1, const char *s2); BOOL strnequal(char *s1,char *s2,int n); BOOL strcsequal(char *s1,char *s2); void strlower(char *s); @@ -908,9 +744,6 @@ char *gidtoname(int gid); void BlockSignals(BOOL block,int signum); void ajt_panic(void); char *readdirname(void *p); - -/*The following definitions come from vt_mode.c */ - int VT_Check(char *buffer); int VT_Start_utmp(void); int VT_Stop_utmp(void); diff --git a/source/lib/util.c b/source/lib/util.c index 31ad3da31cb..45fdb045060 100644 --- a/source/lib/util.c +++ b/source/lib/util.c @@ -119,26 +119,26 @@ void reopen_logs(void) { strcpy(fname,debugf); if (lp_loaded() && (*lp_logfile())) - strcpy(fname,lp_logfile()); + strcpy(fname,lp_logfile()); if (!strcsequal(fname,debugf) || !dbf || !file_exist(debugf,NULL)) - { - strcpy(debugf,fname); - if (dbf) fclose(dbf); - if (append_log) - dbf = fopen(debugf,"a"); - else - dbf = fopen(debugf,"w"); - if (dbf) setbuf(dbf,NULL); - } + { + strcpy(debugf,fname); + if (dbf) fclose(dbf); + if (append_log) + dbf = fopen(debugf,"a"); + else + dbf = fopen(debugf,"w"); + if (dbf) setbuf(dbf,NULL); + } } else { if (dbf) - { - fclose(dbf); - dbf = NULL; - } + { + fclose(dbf); + dbf = NULL; + } } } @@ -204,13 +204,13 @@ va_dcl #endif { if (!dbf) - { - dbf = fopen(debugf,"w"); - if (dbf) - setbuf(dbf,NULL); - else - return(0); - } + { + dbf = fopen(debugf,"w"); + if (dbf) + setbuf(dbf,NULL); + else + return(0); + } } #ifdef SYSLOG @@ -222,19 +222,19 @@ va_dcl * necessarily errors */ static int priority_map[] = { - LOG_ERR, /* 0 */ - LOG_WARNING, /* 1 */ - LOG_NOTICE, /* 2 */ - LOG_INFO, /* 3 */ + LOG_ERR, /* 0 */ + LOG_WARNING, /* 1 */ + LOG_NOTICE, /* 2 */ + LOG_INFO, /* 3 */ }; int priority; pstring msgbuf; if (syslog_level >= sizeof(priority_map) / sizeof(priority_map[0]) || - syslog_level < 0) - priority = LOG_DEBUG; + syslog_level < 0) + priority = LOG_DEBUG; else - priority = priority_map[syslog_level]; + priority = priority_map[syslog_level]; #ifdef __STDC__ va_start(ap, format_str); @@ -312,9 +312,9 @@ BOOL next_token(char **ptr,char *buff,char *sep) for (quoted = False; *s && (quoted || !strchr(sep,*s)); s++) { if (*s == '\"') - quoted = !quoted; + quoted = !quoted; else - *buff++ = *s; + *buff++ = *s; } *ptr = (*s) ? s+1 : s; @@ -387,34 +387,34 @@ void *MemMove(void *dest,void *src,int size) { /* we can forward copy */ if (s-d >= sizeof(int) && - !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) { - /* do it all as words */ - int *idest = (int *)dest; - int *isrc = (int *)src; - size /= sizeof(int); - for (i=0;i= sizeof(int) && - !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) { - /* do it all as words */ - int *idest = (int *)dest; - int *isrc = (int *)src; - size /= sizeof(int); - for (i=size-1;i>=0;i--) idest[i] = isrc[i]; + !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) { + /* do it all as words */ + int *idest = (int *)dest; + int *isrc = (int *)src; + size /= sizeof(int); + for (i=size-1;i>=0;i--) idest[i] = isrc[i]; } else { - /* simplest */ - char *cdest = (char *)dest; - char *csrc = (char *)src; - for (i=size-1;i>=0;i--) cdest[i] = csrc[i]; + /* simplest */ + char *cdest = (char *)dest; + char *csrc = (char *)src; + for (i=size-1;i>=0;i--) cdest[i] = csrc[i]; } } return(dest); @@ -486,7 +486,7 @@ struct #endif {NULL,0,0,0,0}}; - + /**************************************************************************** set user socket options @@ -503,44 +503,44 @@ void set_socket_options(int fd, char *options) BOOL got_value = False; if ((p = strchr(tok,'='))) - { - *p = 0; - value = atoi(p+1); - got_value = True; - } + { + *p = 0; + value = atoi(p+1); + got_value = True; + } for (i=0;socket_options[i].name;i++) - if (strequal(socket_options[i].name,tok)) - break; + if (strequal(socket_options[i].name,tok)) + break; if (!socket_options[i].name) - { - DEBUG(0,("Unknown socket option %s\n",tok)); - continue; - } + { + DEBUG(0,("Unknown socket option %s\n",tok)); + continue; + } switch (socket_options[i].opttype) - { - case OPT_BOOL: - case OPT_INT: - ret = setsockopt(fd,socket_options[i].level, - socket_options[i].option,(char *)&value,sizeof(int)); - break; - - case OPT_ON: - if (got_value) - DEBUG(0,("syntax error - %s does not take a value\n",tok)); - - { - int on = socket_options[i].value; - ret = setsockopt(fd,socket_options[i].level, - socket_options[i].option,(char *)&on,sizeof(int)); - } - break; - } + { + case OPT_BOOL: + case OPT_INT: + ret = setsockopt(fd,socket_options[i].level, + socket_options[i].option,(char *)&value,sizeof(int)); + break; + + case OPT_ON: + if (got_value) + DEBUG(0,("syntax error - %s does not take a value\n",tok)); + + { + int on = socket_options[i].value; + ret = setsockopt(fd,socket_options[i].level, + socket_options[i].option,(char *)&on,sizeof(int)); + } + break; + } if (ret != 0) - DEBUG(0,("Failed to set socket option %s\n",tok)); + DEBUG(0,("Failed to set socket option %s\n",tok)); } } @@ -636,8 +636,8 @@ static int name_interpret(char *in,char *out) while (len--) { if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') { - *out = 0; - return(0); + *out = 0; + return(0); } *out = ((in[0]-'A')<<4) + (in[1]-'A'); in += 2; @@ -695,7 +695,7 @@ int name_mangle(char *In,char *Out,char name_type) { p = strchr(label, '.'); if (p == 0) - p = label + strlen(label); + p = label + strlen(label); *out++ = p - label; memcpy(out, label, p - label); out += p - label; @@ -772,7 +772,7 @@ char *attrib_string(int mode) if (mode & aARCH) strcat(attrstr,"A"); if (mode & aHIDDEN) strcat(attrstr,"H"); if (mode & aSYSTEM) strcat(attrstr,"S"); - if (mode & aRONLY) strcat(attrstr,"R"); + if (mode & aRONLY) strcat(attrstr,"R"); return(attrstr); } @@ -781,7 +781,7 @@ char *attrib_string(int mode) /******************************************************************* case insensitive string compararison ********************************************************************/ -int StrCaseCmp(char *s, char *t) +int StrCaseCmp(const char *s, const char *t) { for (; tolower(*s) == tolower(*t); ++s, ++t) if (!*s) return 0; @@ -792,7 +792,7 @@ int StrCaseCmp(char *s, char *t) /******************************************************************* case insensitive string compararison, length limited ********************************************************************/ -int StrnCaseCmp(char *s, char *t, int n) +int StrnCaseCmp(const char *s, const char *t, int n) { while (n-- && *s && *t) { if (tolower(*s) != tolower(*t)) return(tolower(*s) - tolower(*t)); @@ -806,7 +806,7 @@ int StrnCaseCmp(char *s, char *t, int n) /******************************************************************* compare 2 strings ********************************************************************/ -BOOL strequal(char *s1,char *s2) +BOOL strequal(const char *s1, const char *s2) { if (s1 == s2) return(True); if (!s1 || !s2) return(False); @@ -845,18 +845,18 @@ void strlower(char *s) while (*s) { #ifdef KANJI - if (is_shift_jis (*s)) { - s += 2; - } else if (is_kana (*s)) { - s++; - } else { - if (isupper(*s)) - *s = tolower(*s); - s++; - } + if (is_shift_jis (*s)) { + s += 2; + } else if (is_kana (*s)) { + s++; + } else { + if (isupper(*s)) + *s = tolower(*s); + s++; + } #else if (isupper(*s)) - *s = tolower(*s); + *s = tolower(*s); s++; #endif /* KANJI */ } @@ -870,18 +870,18 @@ void strupper(char *s) while (*s) { #ifdef KANJI - if (is_shift_jis (*s)) { - s += 2; - } else if (is_kana (*s)) { - s++; - } else { - if (islower(*s)) - *s = toupper(*s); - s++; - } + if (is_shift_jis (*s)) { + s += 2; + } else if (is_kana (*s)) { + s++; + } else { + if (islower(*s)) + *s = toupper(*s); + s++; + } #else if (islower(*s)) - *s = toupper(*s); + *s = toupper(*s); s++; #endif } @@ -918,18 +918,18 @@ void string_replace(char *s,char oldc,char newc) while (*s) { #ifdef KANJI - if (is_shift_jis (*s)) { - s += 2; - } else if (is_kana (*s)) { - s++; - } else { - if (oldc == *s) - *s = newc; - s++; - } + if (is_shift_jis (*s)) { + s += 2; + } else if (is_kana (*s)) { + s++; + } else { + if (oldc == *s) + *s = newc; + s++; + } #else if (oldc == *s) - *s = newc; + *s = newc; s++; #endif /* KANJI */ } @@ -977,22 +977,22 @@ void show_msg(char *buf) return; DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n", - smb_len(buf), - (int)CVAL(buf,smb_com), - (int)CVAL(buf,smb_rcls), - (int)CVAL(buf,smb_reh), - (int)SVAL(buf,smb_err), - (int)CVAL(buf,smb_flg), - (int)SVAL(buf,smb_flg2))); + smb_len(buf), + (int)CVAL(buf,smb_com), + (int)CVAL(buf,smb_rcls), + (int)CVAL(buf,smb_reh), + (int)SVAL(buf,smb_err), + (int)CVAL(buf,smb_flg), + (int)SVAL(buf,smb_flg2))); DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n", - (int)SVAL(buf,smb_tid), - (int)SVAL(buf,smb_pid), - (int)SVAL(buf,smb_uid), - (int)SVAL(buf,smb_mid), - (int)CVAL(buf,smb_wct))); + (int)SVAL(buf,smb_tid), + (int)SVAL(buf,smb_pid), + (int)SVAL(buf,smb_uid), + (int)SVAL(buf,smb_mid), + (int)CVAL(buf,smb_wct))); for (i=0;i<(int)CVAL(buf,smb_wct);i++) DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i, - SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i))); + SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i))); bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct))); DEBUG(5,("smb_bcc=%d\n",bcc)); if (DEBUGLEVEL < 10) @@ -1109,14 +1109,14 @@ BOOL trim_string(char *s,char *front,char *back) char *p = s; ret = True; while (1) - { - if (!(*p = p[strlen(front)])) - break; - p++; - } + { + if (!(*p = p[strlen(front)])) + break; + p++; + } } while (back && *back && strlen(s) >= strlen(back) && - (strncmp(s+strlen(s)-strlen(back),back,strlen(back))==0)) + (strncmp(s+strlen(s)-strlen(back),back,strlen(back))==0)) { ret = True; s[strlen(s)-strlen(back)] = 0; @@ -1145,9 +1145,9 @@ void dos_clean_name(char *s) strcpy(s1,p+3); if ((p=strrchr(s,'\\')) != NULL) - *p = 0; + *p = 0; else - *s = 0; + *s = 0; strcat(s,s1); } @@ -1176,9 +1176,9 @@ void unix_clean_name(char *s) strcpy(s1,p+3); if ((p=strrchr(s,'/')) != NULL) - *p = 0; + *p = 0; else - *s = 0; + *s = 0; strcat(s,s1); } @@ -1251,10 +1251,10 @@ char *GetWd(char *str) { getwd_cache_init = True; for (i=0;i 8) - { - strcpy(mext,mbeg + 8); - mbeg[8] = 0; - } + { + strcpy(mext,mbeg + 8); + mbeg[8] = 0; + } } if (*mbeg == 0) @@ -1545,14 +1545,14 @@ BOOL strhasupper(char *s) while (*s) { #ifdef KANJI - if (is_shift_jis (*s)) { - s += 2; - } else if (is_kana (*s)) { - s++; - } else { - if (isupper(*s)) return(True); - s++; - } + if (is_shift_jis (*s)) { + s += 2; + } else if (is_kana (*s)) { + s++; + } else { + if (isupper(*s)) return(True); + s++; + } #else if (isupper(*s)) return(True); s++; @@ -1569,14 +1569,14 @@ BOOL strhaslower(char *s) while (*s) { #ifdef KANJI - if (is_shift_jis (*s)) { - s += 2; - } else if (is_kana (*s)) { - s++; - } else { - if (islower(*s)) return(True); - s++; - } + if (is_shift_jis (*s)) { + s += 2; + } else if (is_kana (*s)) { + s++; + } else { + if (islower(*s)) return(True); + s++; + } #else if (islower(*s)) return(True); s++; @@ -1594,7 +1594,7 @@ int count_chars(char *s,char c) while (*s) { if (*s == c) - count++; + count++; s++; } return(count); @@ -1756,13 +1756,13 @@ int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out) while (nread < mincnt) { readret = read(fd, buf + nread, maxcnt - nread); if (readret == 0) { - smb_read_error = READ_EOF; - return -1; + smb_read_error = READ_EOF; + return -1; } if (readret == -1) { - smb_read_error = READ_ERROR; - return -1; + smb_read_error = READ_ERROR; + return -1; } nread += readret; } @@ -1771,9 +1771,9 @@ int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out) /* Most difficult - timeout read */ /* If this is ever called on a disk file and - mincnt is greater then the filesize then - system performance will suffer severely as - select always return true on disk files */ + mincnt is greater then the filesize then + system performance will suffer severely as + select always return true on disk files */ /* Set initial timeout */ timeout.tv_sec = time_out / 1000; @@ -1788,28 +1788,28 @@ int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out) /* Check if error */ if(selrtn == -1) { - /* something is wrong. Maybe the socket is dead? */ - smb_read_error = READ_ERROR; - return -1; + /* something is wrong. Maybe the socket is dead? */ + smb_read_error = READ_ERROR; + return -1; } /* Did we timeout ? */ if (selrtn == 0) { - smb_read_error = READ_TIMEOUT; - return -1; + smb_read_error = READ_TIMEOUT; + return -1; } readret = read(fd, buf+nread, maxcnt-nread); if (readret == 0) { - /* we got EOF on the file descriptor */ - smb_read_error = READ_EOF; - return -1; + /* we got EOF on the file descriptor */ + smb_read_error = READ_EOF; + return -1; } if (readret == -1) { - /* the descriptor is probably dead */ - smb_read_error = READ_ERROR; - return -1; + /* the descriptor is probably dead */ + smb_read_error = READ_ERROR; + return -1; } nread += readret; @@ -1853,7 +1853,7 @@ values int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew) { return((tvalnew->tv_sec - tvalold->tv_sec)*1000 + - ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000); + ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000); } /**************************************************************************** @@ -1885,12 +1885,12 @@ int read_data(int fd,char *buffer,int N) { ret = read(fd,buffer + total,N - total); if (ret == 0) { - smb_read_error = READ_EOF; - return 0; + smb_read_error = READ_EOF; + return 0; } if (ret == -1) { - smb_read_error = READ_ERROR; - return -1; + smb_read_error = READ_ERROR; + return -1; } total += ret; } @@ -1959,37 +1959,37 @@ int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align) ret = 0; if (header && (headlen >= MIN(s,1024))) { - buf1 = header; - s = headlen; - ret = headlen; - headlen = 0; - header = NULL; + buf1 = header; + s = headlen; + ret = headlen; + headlen = 0; + header = NULL; } else { - buf1 = abuf; + buf1 = abuf; } if (header && headlen > 0) - { - ret = MIN(headlen,size); - memcpy(buf1,header,ret); - headlen -= ret; - header += ret; - if (headlen <= 0) header = NULL; - } + { + ret = MIN(headlen,size); + memcpy(buf1,header,ret); + headlen -= ret; + header += ret; + if (headlen <= 0) header = NULL; + } if (s > ret) - ret += read(infd,buf1+ret,s-ret); + ret += read(infd,buf1+ret,s-ret); if (ret > 0) - { - ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret); - if (ret2 > 0) total += ret2; - /* if we can't write then dump excess data */ - if (ret2 != ret) - transfer_file(infd,-1,n-(ret+headlen),NULL,0,0); - } + { + ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret); + if (ret2 > 0) total += ret2; + /* if we can't write then dump excess data */ + if (ret2 != ret) + transfer_file(infd,-1,n-(ret+headlen),NULL,0,0); + } if (ret <= 0 || ret2 != ret) - return(total); + return(total); n -= ret; } return(total); @@ -2015,21 +2015,21 @@ int read_smb_length(int fd,char *inbuf,int timeout) while (!ok) { if (timeout > 0) - ok = (read_with_timeout(fd,buffer,4,4,timeout) == 4); + ok = (read_with_timeout(fd,buffer,4,4,timeout) == 4); else - ok = (read_data(fd,buffer,4) == 4); + ok = (read_data(fd,buffer,4) == 4); if (!ok) - return(-1); + return(-1); len = smb_len(buffer); msg_type = CVAL(buffer,0); if (msg_type == 0x85) - { - DEBUG(5,("Got keepalive packet\n")); - ok = False; - } + { + DEBUG(5,("Got keepalive packet\n")); + ok = False; + } } DEBUG(10,("got smb length of %d\n",len)); @@ -2084,11 +2084,11 @@ BOOL send_smb(int fd,char *buffer) { ret = write_socket(fd,buffer+nwritten,len - nwritten); if (ret <= 0) - { - DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret)); + { + DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret)); close_sockets(); - exit(1); - } + exit(1); + } nwritten += ret; } @@ -2172,14 +2172,14 @@ BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type) if (DEBUGLEVEL > 0) DEBUG(3,("sending a packet of len %d to (%s) on port %d of type %s\n", - len,inet_ntoa(ip),port,type==SOCK_DGRAM?"DGRAM":"STREAM")); - + len,inet_ntoa(ip),port,type==SOCK_DGRAM?"DGRAM":"STREAM")); + /* send it */ ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0); if (!ret) DEBUG(0,("Packet send to %s(%d) failed ERRNO=%d\n", - inet_ntoa(ip),port,errno)); + inet_ntoa(ip),port,errno)); close(out_fd); return(ret); @@ -2223,11 +2223,11 @@ BOOL in_list(char *s,char *list,BOOL casesensitive) while (next_token(&p,tok,LIST_SEP)) { if (casesensitive) { - if (strcmp(tok,s) == 0) - return(True); + if (strcmp(tok,s) == 0) + return(True); } else { - if (StrCaseCmp(tok,s) == 0) - return(True); + if (StrCaseCmp(tok,s) == 0) + return(True); } } return(False); @@ -2250,7 +2250,7 @@ BOOL string_init(char **dest,char *src) if (l == 0) { if (!null_string) - null_string = (char *)malloc(1); + null_string = (char *)malloc(1); *null_string = 0; *dest = null_string; @@ -2338,29 +2338,29 @@ BOOL do_match(char *str, char *regexp, int case_sig) case '*': /* Look for a character matching - the one after the '*' */ + the one after the '*' */ p++; if(!*p) - return True; /* Automatic match */ + return True; /* Automatic match */ while(*str) { - while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str)))) - str++; - if(do_match(str,p,case_sig)) - return True; - if(!*str) - return False; - else - str++; + while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str)))) + str++; + if(do_match(str,p,case_sig)) + return True; + if(!*str) + return False; + else + str++; } return False; default: if(case_sig) { - if(*str != *p) - return False; + if(*str != *p) + return False; } else { - if(toupper(*str) != toupper(*p)) - return False; + if(toupper(*str) != toupper(*p)) + return False; } str++, p++; break; @@ -2479,8 +2479,8 @@ void become_daemon(void) int i = open("/dev/tty", O_RDWR); if (i >= 0) { - ioctl(i, (int) TIOCNOTTY, (char *)0); - close(i); + ioctl(i, (int) TIOCNOTTY, (char *)0); + close(i); } } #endif @@ -2535,39 +2535,39 @@ char *fgets_slash(char *s2,int maxlen,FILE *f) { c = getc(f); switch (c) - { - case '\r': - break; - case '\n': - while (len > 0 && s[len-1] == ' ') - { - s[--len] = 0; - } - if (len > 0 && s[len-1] == '\\') - { - s[--len] = 0; - start_of_line = True; - break; - } - return(s); - case EOF: - if (len <= 0 && !s2) - free(s); - return(len>0?s:NULL); - case ' ': - if (start_of_line) - break; - default: - start_of_line = False; - s[len++] = c; - s[len] = 0; - } + { + case '\r': + break; + case '\n': + while (len > 0 && s[len-1] == ' ') + { + s[--len] = 0; + } + if (len > 0 && s[len-1] == '\\') + { + s[--len] = 0; + start_of_line = True; + break; + } + return(s); + case EOF: + if (len <= 0 && !s2) + free(s); + return(len>0?s:NULL); + case ' ': + if (start_of_line) + break; + default: + start_of_line = False; + s[len++] = c; + s[len] = 0; + } if (!s2 && len > maxlen-3) - { - maxlen *= 2; - s = (char *)Realloc(s,maxlen); - if (!s) return(NULL); - } + { + maxlen *= 2; + s = (char *)Realloc(s,maxlen); + if (!s) return(NULL); + } } return(s); } @@ -2825,16 +2825,16 @@ int open_socket_in(int type, int port, int dlevel,uint32 socket_addr) if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) { if (port) { - if (port == SMB_PORT || port == NMB_PORT) - DEBUG(dlevel,("bind failed on port %d socket_addr=%x (%s)\n", - port,socket_addr,strerror(errno))); - close(res); + if (port == SMB_PORT || port == NMB_PORT) + DEBUG(dlevel,("bind failed on port %d socket_addr=%x (%s)\n", + port,socket_addr,strerror(errno))); + close(res); - if (dlevel > 0 && port < 1000) - port = 7999; + if (dlevel > 0 && port < 1000) + port = 7999; - if (port >= 1000 && port < 9000) - return(open_socket_in(type,port+1,dlevel,socket_addr)); + if (port >= 1000 && port < 9000) + return(open_socket_in(type,port+1,dlevel,socket_addr)); } return(-1); @@ -3258,8 +3258,8 @@ char *readdirname(void *p) static BOOL broken_readdir = False; if (!broken_readdir && !(*(dname)) && strequal("..",dname-2)) { - DEBUG(0,("Your readdir() is broken. You have somehow mixed SYSV and BSD headers and libraries\n")); - broken_readdir = True; + DEBUG(0,("Your readdir() is broken. You have somehow mixed SYSV and BSD headers and libraries\n")); + broken_readdir = True; } if (broken_readdir) return(dname-2); diff --git a/source/nameannounce.c b/source/nameannounce.c index ff2c89df852..84a5f2627ec 100644 --- a/source/nameannounce.c +++ b/source/nameannounce.c @@ -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" @@ -34,8 +37,6 @@ extern BOOL CanRecurse; extern struct in_addr ipzero; -extern pstring myname; - extern int ClientDGRAM; extern int ClientNMB; @@ -43,14 +44,17 @@ extern int ClientNMB; extern struct subnet_record *subnetlist; extern int updatecount; -extern int workgroup_count; -extern struct in_addr ipgrp; +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) { @@ -62,7 +66,7 @@ void announce_request(struct work_record *work, struct in_addr ip) work->needannounce = True; DEBUG(2,("sending announce request to %s for workgroup %s\n", - inet_ntoa(ip),work->work_group)); + inet_ntoa(ip),work->work_group)); bzero(outbuf,sizeof(outbuf)); p = outbuf; @@ -71,8 +75,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 +83,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; @@ -100,14 +104,15 @@ void do_announce_request(char *info, char *to_name, int announce_type, p++; DEBUG(2,("sending announce type %d: info %s to %s - server %s(%x)\n", - announce_type, info, inet_ntoa(dest_ip),to_name,to)); + announce_type, info, inet_ntoa(dest_ip),to_name,to)); StrnCpy(p,info,16); strupper(p); p = skip_string(p,1); send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), - myname,to_name,from,to,dest_ip,*iface_ip(dest_ip)); + from_name,to_name,from,to, + dest_ip,*iface_ip(dest_ip)); } @@ -116,19 +121,23 @@ void do_announce_request(char *info, char *to_name, int announce_type, control ends up back here via response_name_query. **************************************************************************/ void sync_server(enum state_type state, char *serv_name, char *work_name, - int name_type, - struct in_addr ip) -{ + 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); } } @@ -137,46 +146,46 @@ void sync_server(enum state_type state, char *serv_name, char *work_name, send a host announcement packet **************************************************************************/ 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 *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) { - pstring outbuf; - char *p; + pstring outbuf; + char *p; - bzero(outbuf,sizeof(outbuf)); - p = outbuf+1; + bzero(outbuf,sizeof(outbuf)); + p = outbuf+1; - /* command type */ - CVAL(outbuf,0) = command; + /* command type */ + CVAL(outbuf,0) = command; - /* announcement parameters */ - CVAL(p,0) = updatecount; - SIVAL(p,1,announce_interval*1000); /* ms - despite the spec */ + /* announcement parameters */ + CVAL(p,0) = updatecount; + SIVAL(p,1,announce_interval*1000); /* ms - despite the spec */ - StrnCpy(p+5,server_name,16); - strupper(p+5); + StrnCpy(p+5,server_name,16); + strupper(p+5); - CVAL(p,21) = 0x02; /* major version */ - CVAL(p,22) = 0x02; /* minor version */ + CVAL(p,21) = 0x02; /* major version */ + CVAL(p,22) = 0x02; /* 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 */ + SIVAL(p,23,server_type); + SSVAL(p,27,0x010f); /* browse version: got from NT/AS 4.00 */ + SSVAL(p,29,0xaa55); /* browse signature */ - strcpy(p+31,server_comment); - p += 31; - p = skip_string(p,1); + strcpy(p+31,server_comment); + p += 31; + p = skip_string(p,1); debug_browse_data(outbuf, PTR_DIFF(p,outbuf)); - /* send the announcement */ - send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf, - PTR_DIFF(p,outbuf), - from_name, to_name, - from_type, to_type, - to_ip, from_ip); + /* send the announcement */ + send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf, + PTR_DIFF(p,outbuf), + from_name, to_name, + from_type, to_type, + to_ip, from_ip); } @@ -185,20 +194,23 @@ void do_announce_host(int command, ****************************************************************************/ void remove_my_servers(void) { - struct subnet_record *d; - for (d = subnetlist; d; d = d->next) - { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - struct server_record *s; - for (s = work->serverlist; s; s = s->next) - { - if (!strequal(myname,s->serv.name)) continue; - announce_server(d, work, s->serv.name, s->serv.comment, 0, 0); - } - } - } + struct subnet_record *d; + for (d = subnetlist; d; d = d->next) + { + struct work_record *work; + for (work = d->workgrouplist; work; work = work->next) + { + struct server_record *s; + for (s = work->serverlist; s; s = s->next) + { + if (!strequal(conf_browsing_alias(work->token),s->serv.name)) + { + continue; + } + announce_server(d, work, s->serv.name, s->serv.comment, 0, 0); + } + } + } } @@ -206,7 +218,7 @@ void remove_my_servers(void) announce a server entry ****************************************************************************/ void announce_server(struct subnet_record *d, struct work_record *work, - char *name, char *comment, time_t ttl, int server_type) + char *name, char *comment, time_t ttl, int server_type) { uint32 domain_type = SV_TYPE_DOMAIN_ENUM|DFLT_SERVER_TYPE; BOOL wins_iface = ip_equal(d->bcast_ip, ipgrp); @@ -223,7 +235,7 @@ void announce_server(struct subnet_record *d, struct work_record *work, /* 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,ttl*1000, server_type,name,comment, False, False, ipzero, d->bcast_ip); } @@ -293,11 +305,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) { @@ -306,53 +313,62 @@ void announce_host(void) if (ip_equal(d->bcast_ip, ipgrp)) continue; for (work = d->workgrouplist; work; work = work->next) - { - uint32 stype = work->ServerType; - struct server_record *s; - BOOL announce = False; - + { + 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); + + my_name = my_name ? my_name : myname; + my_comment = my_comment ? my_comment : lp_server_comment(); + + 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 announce. */ - if (work->needannounce) { - /* drop back to a max 3 minute announce - this is to prevent a - single lost packet from stuffing things up for too long */ - work->announce_interval = MIN(work->announce_interval, - CHECK_TIME_MIN_HOST_ANNCE*60); - work->lastannounce_time = t - (work->announce_interval+1); - } - - /* announce every minute at first then progress to every 12 mins */ - if (work->lastannounce_time && - (t - work->lastannounce_time) < work->announce_interval) - continue; - - if (work->announce_interval < CHECK_TIME_MAX_HOST_ANNCE * 60) - work->announce_interval += 60; - - work->lastannounce_time = t; - - for (s = work->serverlist; s; s = s->next) { - if (strequal(myname, s->serv.name)) { - announce = True; - break; - } - } - - if (announce) { - announce_server(d,work,my_name,comment, - work->announce_interval,stype); - } - - if (work->needannounce) - { - work->needannounce = False; - break; - /* sorry: can't do too many announces. do some more later */ - } - } + if (work->needannounce) { + /* drop back to a max 3 minute announce - this is to prevent a + single lost packet from stuffing things up for too long */ + work->announce_interval = MIN(work->announce_interval, + CHECK_TIME_MIN_HOST_ANNCE*60); + work->lastannounce_time = t - (work->announce_interval+1); + } + + /* announce every minute at first then progress to every 12 mins */ + if (work->lastannounce_time && + (t - work->lastannounce_time) < work->announce_interval) + continue; + + if (work->announce_interval < CHECK_TIME_MAX_HOST_ANNCE * 60) + work->announce_interval += 60; + + work->lastannounce_time = t; + + for (s = work->serverlist; s; s = s->next) { + if (strequal(my_name, s->serv.name)) + { + announce = True; + break; + } + } + + if (announce) { + announce_server(d,work,my_name,comment, + work->announce_interval,stype); + } + + if (work->needannounce) + { + work->needannounce = False; + break; + /* sorry: can't do too many announces. do some more later */ + } + } } } @@ -373,97 +389,96 @@ void announce_master(void) if (!last) last = t; if (t-last < CHECK_TIME_MST_ANNOUNCE * 60) - return; + return; last = t; for (d = subnetlist; d; d = d->next) + { + struct work_record *work; + for (work = d->workgrouplist; work; work = work->next) { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - if (AM_MASTER(work)) - { - am_master = True; - } - } + if (AM_MASTER(work)) + { + am_master = True; + } } + } if (!am_master) return; /* only proceed if we are a master browser */ for (d = subnetlist; d; d = d->next) + { + struct work_record *work; + for (work = d->workgrouplist; work; work = work->next) { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - struct server_record *s; - for (s = work->serverlist; s; s = s->next) - { - if (strequal(s->serv.name, myname)) continue; - - /* all DOMs (which should also be master browsers) */ - if (s->serv.type & SV_TYPE_DOMAIN_CTRL) - { - /* check the existence of a pdc for this workgroup, and if - one exists at the specified ip, sync with it and announce - ourselves as a master browser to it */ - - if (!*lp_domain_controller() || - !strequal(lp_domain_controller(), s->serv.name)) - { - if (!lp_wins_support() && *lp_wins_server()) - { - queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY, - NAME_QUERY_DOM_SRV_CHK, - work->work_group,0x1b,0,0,0,NULL,NULL, - False, False, ipzero, ipzero); - } - else - { - struct subnet_record *d2; - for (d2 = subnetlist; d2; d2 = d2->next) - { - queue_netbios_packet(d,ClientNMB,NMB_QUERY, - NAME_QUERY_DOM_SRV_CHK, - work->work_group,0x1b,0,0,0,NULL,NULL, - True, False, d2->bcast_ip, d2->bcast_ip); - } - } - } - } - } - - /* now do primary domain controller - the one that's not - necessarily in our browse lists, although it ought to be - this pdc is the one that we get TOLD about through smb.conf. - basically, if it's on a subnet that we know about, it may end - up in our browse lists (which is why it's explicitly excluded - in the code above) */ - - if (*lp_domain_controller()) - { - struct in_addr ip; - BOOL bcast = False; - - ip = *interpret_addr2(lp_domain_controller()); - - if (zero_ip(ip)) { - ip = d->bcast_ip; - bcast = True; - } - - DEBUG(2, ("Searching for DOM %s at %s\n", - lp_domain_controller(), inet_ntoa(ip))); - - /* check the existence of a pdc for this workgroup, and if - one exists at the specified ip, sync with it and announce - ourselves as a master browser to it */ - queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,NAME_QUERY_DOM_SRV_CHK, - work->work_group,0x1b,0,0,0,NULL,NULL, - bcast, False, ip, ip); - } - } + struct server_record *s; + for (s = work->serverlist; s; s = s->next) + { + 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) + { + /* check the existence of a pdc for this workgroup, and if + one exists at the specified ip, sync with it and announce + ourselves as a master browser to it */ + + if (!*lp_domain_controller() || + !strequal(lp_domain_controller(), s->serv.name)) + { + if (!lp_wins_support() && *lp_wins_server()) + { + queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY, + NAME_QUERY_DOM_SRV_CHK, + work->token, work->work_group,0x1b,0,0,0,NULL,NULL, + False, False, ipzero, ipzero); + } + else + { + struct subnet_record *d2; + for (d2 = subnetlist; d2; d2 = d2->next) + { + queue_netbios_packet(d,ClientNMB,NMB_QUERY, + NAME_QUERY_DOM_SRV_CHK, + work->token, work->work_group,0x1b,0,0,0,NULL,NULL, + True, False, d2->bcast_ip, d2->bcast_ip); + } + } + } + } + } + + /* now do primary domain controller - the one that's not + necessarily in our browse lists, although it ought to be + this pdc is the one that we get TOLD about through smb.conf. + basically, if it's on a subnet that we know about, it may end + up in our browse lists (which is why it's explicitly excluded + in the code above) */ + + if (*lp_domain_controller()) + { + struct in_addr ip; + + ip = *interpret_addr2(lp_domain_controller()); + + /* 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))); + + /* check the existence of a pdc for this workgroup, and if + one exists at the specified ip, sync with it and announce + ourselves as a master browser to it */ + queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,NAME_QUERY_DOM_SRV_CHK, + work->token, work->work_group,0x1b,0,0,0,NULL,NULL, + False, False, ip, ip); + } } + } } @@ -481,6 +496,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 +507,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 +525,14 @@ 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,comment); } - } diff --git a/source/namebrowse.c b/source/namebrowse.c index b426bc7a150..8ebf7b8c900 100644 --- a/source/namebrowse.c +++ b/source/namebrowse.c @@ -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" @@ -71,21 +74,21 @@ void expire_browse_cache(time_t t) for (b = browserlist; b; b = nextb) { if (b->synced && b->sync_time < t) - { - DEBUG(3,("Removing dead cached browser %s\n",b->name)); - nextb = b->next; - - if (b->prev) b->prev->next = b->next; - if (b->next) b->next->prev = b->prev; - - if (browserlist == b) browserlist = b->next; - - free(b); - } + { + DEBUG(3,("Removing dead cached browser %s\n",b->name)); + nextb = b->next; + + if (b->prev) b->prev->next = b->next; + if (b->next) b->next->prev = b->prev; + + if (browserlist == b) browserlist = b->next; + + free(b); + } else - { - nextb = b->next; - } + { + nextb = b->next; + } } } @@ -94,7 +97,7 @@ void expire_browse_cache(time_t t) add a browser entry ****************************************************************************/ struct browse_cache_record *add_browser_entry(char *name, int type, char *wg, - time_t ttl, struct in_addr ip, BOOL local) + time_t ttl, struct in_addr ip, BOOL local) { BOOL newentry=False; @@ -109,9 +112,9 @@ struct browse_cache_record *add_browser_entry(char *name, int type, char *wg, if (b && b->synced) { /* entries get left in the cache for a while. this stops sync'ing too - often if the network is large */ + often if the network is large */ DEBUG(4, ("browser %s %s %s already sync'd at time %d\n", - b->name, b->group, inet_ntoa(b->ip), b->sync_time)); + b->name, b->group, inet_ntoa(b->ip), b->sync_time)); return NULL; } @@ -146,12 +149,12 @@ struct browse_cache_record *add_browser_entry(char *name, int type, char *wg, add_browse_cache(b); DEBUG(3,("Added cache entry %s %s(%2x) %s ttl %d\n", - wg, name, type, inet_ntoa(ip),ttl)); + wg, name, type, inet_ntoa(ip),ttl)); } else { DEBUG(3,("Updated cache entry %s %s(%2x) %s ttl %d\n", - wg, name, type, inet_ntoa(ip),ttl)); + wg, name, type, inet_ntoa(ip),ttl)); } return(b); @@ -166,23 +169,23 @@ 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; - + /* only sync if we are the master */ if (AM_MASTER(work)) { - + /* first check whether the group we intend to sync with exists. if it doesn't, the server must have died. o dear. */ - + /* see response_netbios_packet() or expire_netbios_response_entries() */ queue_netbios_packet(d,ClientNMB,NMB_QUERY, b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE, - b->group,0x20,0,0,0,NULL,NULL, - False,False,b->ip,b->ip); + work->token,b->group,0x20,0,0,0,NULL,NULL, + False,False,b->ip,b->ip); } - + b->synced = True; } diff --git a/source/nameconf.c b/source/nameconf.c new file mode 100644 index 00000000000..79fa2abe431 --- /dev/null +++ b/source/nameconf.c @@ -0,0 +1,349 @@ +/* + Unix SMB/Netbios implementation. + Version 1.9. + NBT netbios routines and daemon - version 2 + Copyright (C) David Chappell 1996 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + Revision History: + + 30 July 96: David.Chappell@mail.trincoll.edu + Expanded multiple workgroup domain master browser support. + +*/ + +/* +** nameconf.c +** These functions dispense information from smbbrowse.conf. +** +** +*/ + +#include "includes.h" +extern int DEBUGLEVEL; + +#if 0 +struct smbbrowse_parms + { + char *name; + BOOL (*reader)(char *string, void *toset); + } smbbrowse_table[] = +{ + {"preferred master", NULL}, + {"local master", NULL}, + {"domain master", NULL} +} ; +#endif + +/* +** Structure for the list of workgroups from smbbrowse.conf. This +** structure should only be manipulated thru the functions in this file. +** That is why it is not defined in a header file. +*/ +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? */ +} ; + +/* The whole list */ +static struct smbbrowse *smbbrowse_workgroups = (struct smbbrowse*)NULL; + +/* The size of the list */ +static int array_size = 0; + +/* The next available space in the list */ +static int nexttoken = 0; + +int get_num_workgroups(void) +{ + return nexttoken; +} + +/* +** This makes a new workgroup structure, possibly taking an +** old one as a model. +*/ +static struct smbbrowse *new_workgroup(struct smbbrowse *model, + const char *workgroup_name, + const char *default_name) +{ + struct smbbrowse *new; + + if( ! (array_size > nexttoken) ) + { + array_size += 10; + smbbrowse_workgroups = (struct smbbrowse*)realloc(smbbrowse_workgroups, + array_size * sizeof(struct smbbrowse)); + } + + new = &smbbrowse_workgroups[nexttoken]; + + if(model != (struct smbbrowse *)NULL ) + memcpy(new, model, sizeof(struct smbbrowse)); + else + memset(new, 0, sizeof(struct smbbrowse)); + + StrnCpy(new->work_name, workgroup_name, 15); + strupper(new->work_name); + + if (strequal(lp_workgroup(), workgroup_name)) + StrnCpy(new->browsing_alias, default_name, 15); + else + sprintf(new->browsing_alias, "%.14s%x", default_name, nexttoken); + strupper(new->browsing_alias); + + DEBUG(4,("wg: %s alias: %s token: %x\n", + new->work_name, new->browsing_alias, nexttoken)); + + nexttoken++; + return new; +} + +/* +** If fed a workgroup name, this function returns its token number. +** 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 idx; + + /* Look for an existing instance. */ + for(idx=0; idx < nexttoken; idx++) + { + if(strequal(workgroup_name, smbbrowse_workgroups[idx].work_name)) + { + return idx; + } + } + + /* See if creating new ones in admissable. */ + for(idx=0; idx < nexttoken; idx++) + { + if(strequal("*", smbbrowse_workgroups[idx].work_name)) + { + struct smbbrowse *w = new_workgroup(&smbbrowse_workgroups[idx], + workgroup_name, default_name); + w->should_workgroup_member = False; + + return (nexttoken - 1); + } + } + + /* Not allowed */ + DEBUG(4, ("refusing to allow new workgroup\n")); + return -1; +} + +/* +** This is a workgroups array bounds checker. +*/ +static int range_check(int token) +{ + if(token < 0 || token >= nexttoken) + { + DEBUG(0, ("range_check(): failed\n")); + return True; + } + + return False; +} + +/* +** Given a token, return the name. +*/ +char *conf_workgroup_name(int 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_workgroup_member(int token) + { + + if(range_check(token)) + return False; + + return smbbrowse_workgroups[token].should_workgroup_member; + } + +/* +** Given a token, return True if we should try +** to become a master browser. +*/ +int conf_should_local_master(int token) + { + 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_master(int token) + { + if(range_check(token)) + return False; + + return smbbrowse_workgroups[token].should_domain_master; + } + +/* +** Given a token, return the name. +*/ +char *conf_browsing_alias(int token) + { + if(range_check(token)) + return (char*)NULL; + + return smbbrowse_workgroups[token].browsing_alias; + } + +/* +** Return the server comment which should be used with the +** browsing alias. +*/ +char *conf_browsing_alias_comment(int token) +{ + if(range_check(token)) + return (char*) NULL; + + return "Browser"; + } + +/* +** 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) +{ + int x; + + DEBUG(4,("alias_to_workgroup: %s", alias)); + + for(x=0; x < nexttoken; x++) + { + DEBUG(4,("%s ", smbbrowse_workgroups[x].browsing_alias)); + + if(strequal(alias, smbbrowse_workgroups[x].browsing_alias)) + { + DEBUG(4,("OK\n")); + return smbbrowse_workgroups[x].work_name; + } + } + DEBUG(4,("not found\n")); + return (char*)NULL; +} + +/* +** 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 x; + + for(x=0; x < nexttoken; x++) + { + if(strequal(alias, smbbrowse_workgroups[x].browsing_alias)) + { + return x; + } + } + return -1; +} + +/* +** 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) +{ + 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_domain_master = lp_domain_master(); + w->should_workgroup_member = True; + + /* default action: allow any new workgroup to be added */ + w = new_workgroup((struct smbbrowse *)NULL, "*", default_name); + w->should_local_master = False; + w->should_domain_master = False; + w->should_workgroup_member = False; +} + +/* +** This function is called from main(). +*/ +void read_smbbrowse_conf(char *default_name) +{ + FILE *f = fopen(BROWSEFILE,"r"); + if (f) + { + while (!feof(f)) + { + pstring line; + char *ptr; + int count = 0; + + pstring work_name; + struct smbbrowse *w; + + if (!fgets_slash(line,sizeof(pstring),f)) continue; + + if (*line == '#') continue; + + strcpy(work_name,""); + + ptr = line; + + if (next_token(&ptr, work_name, NULL)) ++count; + + if (count <= 0) continue; + + 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_workgroup_member = True; + } + + fclose(f); + } + else + { + DEBUG(2,("Can't open browse configuration file %s\n",BROWSEFILE)); + } + default_smbbrowse_conf(default_name); +} + + diff --git a/source/namedbname.c b/source/namedbname.c index 1f16553b0f4..74777a91456 100644 --- a/source/namedbname.c +++ b/source/namedbname.c @@ -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" @@ -52,14 +56,14 @@ uint16 nb_type = 0; /* samba's NetBIOS name type */ ****************************************************************************/ void set_samba_nb_type(void) { - if (lp_wins_support() || (*lp_wins_server())) - { - nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */ - } - else - { - nb_type = NB_BFLAG; /* samba is broadcast-only node type */ - } + if (lp_wins_support() || (*lp_wins_server())) + { + nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */ + } + else + { + nb_type = NB_BFLAG; /* samba is broadcast-only node type */ + } } @@ -69,7 +73,7 @@ void set_samba_nb_type(void) BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2) { return n1->name_type == n2->name_type && - strequal(n1->name ,n2->name ) && + strequal(n1->name ,n2->name ) && strequal(n1->scope,n2->scope); } @@ -140,22 +144,22 @@ void remove_name(struct subnet_record *d, struct name_record *n) find a name in a namelist. **************************************************************************/ struct name_record *find_name(struct name_record *n, - struct nmb_name *name, - int search) + struct nmb_name *name, + int search) { - struct name_record *ret; + struct name_record *ret; - for (ret = n; ret; ret = ret->next) - { - if (name_equal(&ret->name,name)) - { - /* self search: self names only */ - if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF) - continue; - - return ret; - } - } + for (ret = n; ret; ret = ret->next) + { + if (name_equal(&ret->name,name)) + { + /* self search: self names only */ + if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF) + continue; + + return ret; + } + } return NULL; } @@ -168,29 +172,31 @@ struct name_record *find_name(struct name_record *n, FIND_WINS - look for names in the WINS record **************************************************************************/ struct name_record *find_name_search(struct subnet_record **d, - struct nmb_name *name, - int search, struct in_addr ip) + struct nmb_name *name, + int search, struct in_addr ip) { - if (d == NULL) return NULL; /* bad error! */ - - if (search & FIND_LOCAL) { - if (*d != NULL) { - struct name_record *n = find_name((*d)->namelist, name, search); - DEBUG(4,("find_name on local: %s %s search %x\n", - namestr(name),inet_ntoa(ip), search)); - if (n) return n; - } + if (d == NULL) return NULL; /* bad error! */ + + if (search & FIND_LOCAL) + { + if (*d != NULL) + { + struct name_record *n = find_name((*d)->namelist, name, search); + DEBUG(4,("find_name on local: %s %s search %x\n", + namestr(name),inet_ntoa(ip), search)); + if (n) return n; + } } - if (!(search & FIND_WINS)) return NULL; + if ((search & FIND_WINS) != FIND_WINS) return NULL; /* find WINS subnet record. */ *d = find_subnet(ipgrp); - + if (*d == NULL) return NULL; - + DEBUG(4,("find_name on WINS: %s %s search %x\n", - namestr(name),inet_ntoa(ip), search)); + namestr(name),inet_ntoa(ip), search)); return find_name((*d)->namelist, name, search); } @@ -228,20 +234,19 @@ 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 ", - namestr(&n->name), - n->death_time?n->death_time-t:0)); + DEBUG(3,("%15s ", inet_ntoa(d->bcast_ip))); + DEBUG(3,("%15s ", inet_ntoa(d->mask_ip))); + DEBUG(3,("%-19s TTL=%ld source=%d", + namestr(&n->name), + n->death_time?n->death_time-t:0, n->source)); for (i = 0; i < n->num_ips; i++) { - DEBUG(3,("%15s NB=%2x source=%d", - inet_ntoa(n->ip_flgs[i].ip), - n->ip_flgs[i].nb_flags,n->source)); - + DEBUG(3,("%15s NB=%2x ", + inet_ntoa(n->ip_flgs[i].ip), + n->ip_flgs[i].nb_flags)); } - DEBUG(3,("\n")); + DEBUG(3,("\n")); if (f && ip_equal(d->bcast_ip, ipgrp) && n->source == REGISTER) { @@ -249,16 +254,16 @@ void dump_names(void) anything other than as a hexadecimal number :-) */ fprintf(f, "%s#%02x %ld ", - n->name.name,n->name.name_type, /* XXXX ignore scope for now */ - n->death_time); + n->name.name,n->name.name_type, /* XXXX ignore scope for now */ + n->death_time); for (i = 0; i < n->num_ips; i++) { fprintf(f, "%s %2x ", - inet_ntoa(n->ip_flgs[i].ip), - n->ip_flgs[i].nb_flags); + inet_ntoa(n->ip_flgs[i].ip), + n->ip_flgs[i].nb_flags); } - fprintf(f, "\n"); + fprintf(f, "\n"); } } @@ -307,12 +312,12 @@ void load_netbios_names(void) int type = 0; unsigned int nb_flags; time_t ttd; - struct in_addr ipaddr; + struct in_addr ipaddr; - enum name_source source; + enum name_source source; char *ptr; - int count = 0; + int count = 0; char *p; @@ -320,20 +325,20 @@ void load_netbios_names(void) if (*line == '#') continue; - ptr = line; + ptr = line; - if (next_token(&ptr,name_str ,NULL)) ++count; - if (next_token(&ptr,ttd_str ,NULL)) ++count; - if (next_token(&ptr,ip_str ,NULL)) ++count; - if (next_token(&ptr,nb_flags_str,NULL)) ++count; + if (next_token(&ptr,name_str ,NULL)) ++count; + if (next_token(&ptr,ttd_str ,NULL)) ++count; + if (next_token(&ptr,ip_str ,NULL)) ++count; + if (next_token(&ptr,nb_flags_str,NULL)) ++count; - if (count <= 0) continue; + if (count <= 0) continue; - if (count != 4) { - DEBUG(0,("Ill formed wins line")); - DEBUG(0,("[%s]: name#type abs_time ip nb_flags\n",line)); - continue; - } + if (count != 4) { + DEBUG(0,("Ill formed wins line")); + DEBUG(0,("[%s]: name#type abs_time ip nb_flags\n",line)); + continue; + } /* netbios name. # divides the name from the type (hex): netbios#xx */ strcpy(name,name_str); @@ -341,15 +346,15 @@ void load_netbios_names(void) p = strchr(name,'#'); if (p) { - *p = 0; - sscanf(p+1,"%x",&type); + *p = 0; + sscanf(p+1,"%x",&type); } /* decode the netbios flags (hex) and the time-to-die (seconds) */ - sscanf(nb_flags_str,"%x",&nb_flags); - sscanf(ttd_str,"%ld",&ttd); + sscanf(nb_flags_str,"%x",&nb_flags); + sscanf(ttd_str,"%ld",&ttd); - ipaddr = *interpret_addr2(ip_str); + ipaddr = *interpret_addr2(ip_str); if (ip_equal(ipaddr,ipzero)) { source = SELF; @@ -360,7 +365,7 @@ void load_netbios_names(void) } DEBUG(4, ("add WINS line: %s#%02x %ld %s %2x\n", - name,type, ttd, inet_ntoa(ipaddr), nb_flags)); + name,type, ttd, inet_ntoa(ipaddr), nb_flags)); /* add all entries that have 60 seconds or more to live */ if (ttd - 60 > time(NULL) || ttd == 0) @@ -380,8 +385,8 @@ void load_netbios_names(void) remove an entry from the name list ****************************************************************************/ void remove_netbios_name(struct subnet_record *d, - char *name,int type, enum name_source source, - struct in_addr ip) + char *name,int type, enum name_source source, + struct in_addr ip) { struct nmb_name nn; struct name_record *n; @@ -405,9 +410,9 @@ void remove_netbios_name(struct subnet_record *d, ****************************************************************************/ 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) + char *name, int type, int nb_flags, + int ttl, enum name_source source, struct in_addr ip, + BOOL new_only,BOOL wins) { struct name_record *n; struct name_record *n2=NULL; @@ -465,46 +470,61 @@ struct name_record *add_netbios_entry(struct subnet_record *d, if (!n2) add_name(d,n); DEBUG(3,("Added netbios name %s at %s ttl=%d nb_flags=%2x\n", - namestr(&n->name),inet_ntoa(ip),ttl,nb_flags)); + namestr(&n->name),inet_ntoa(ip),ttl,nb_flags)); return(n); } /******************************************************************* - 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; - struct subnet_record *d; - - /* expire old names */ - for (d = subnetlist; d; d = d->next) - { - 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; - continue; - } - DEBUG(3,("Removing dead name %s\n", namestr(&n->name))); - - if (n->prev) n->prev->next = n->next; - if (n->next) n->next->prev = n->prev; - - if (d->namelist == n) d->namelist = n->next; - - free(n->ip_flgs); - free(n); - } - } - } + struct name_record *n; + struct name_record *next; + struct subnet_record *d; + + /* expire old names */ + for (d = subnetlist; d; d = d->next) + { + for (n = d->namelist; n; n = next) + { + if (n->death_time && n->death_time < t) + { + 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))); + + next = n->next; + + if (n->prev) n->prev->next = n->next; + if (n->next) n->next->prev = n->prev; + + if (d->namelist == n) d->namelist = n->next; + + free(n->ip_flgs); + free(n); + } + else + { + next = n->next; + } + } + } } @@ -512,8 +532,8 @@ void expire_names(time_t t) reply to a name query ****************************************************************************/ struct name_record *search_for_name(struct subnet_record **d, - struct nmb_name *question, - struct in_addr ip, int Time, int search) + struct nmb_name *question, + struct in_addr ip, int Time, int search) { int name_type = question->name_type; char *qname = question->name; @@ -538,10 +558,10 @@ struct name_record *search_for_name(struct subnet_record **d, /* only do DNS lookups if the query is for type 0x20 or type 0x0 */ if (!dns_type && name_type != 0x1b) - { - DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n")); - return NULL; - } + { + DEBUG(3,("types 0x20 0x1b 0x0 only: name not found\n")); + return NULL; + } /* look it up with DNS */ a = interpret_addr(qname); @@ -549,18 +569,18 @@ struct name_record *search_for_name(struct subnet_record **d, putip((char *)&dns_ip,(char *)&a); if (!a) - { - /* no luck with DNS. We could possibly recurse here XXXX */ - DEBUG(3,("no recursion.\n")); + { + /* no luck with DNS. We could possibly recurse here XXXX */ + DEBUG(3,("no recursion.\n")); /* add the fail to our WINS cache of names. give it 1 hour in the cache */ - add_netbios_entry(*d,qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip, - True, True); - return NULL; - } + add_netbios_entry(*d,qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip, + True, True); + return NULL; + } /* add it to our WINS cache of names. give it 2 hours in the cache */ n = add_netbios_entry(*d,qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip, - True,True); + True,True); /* failed to add it? yikes! */ if (!n) return NULL; diff --git a/source/namedbresp.c b/source/namedbresp.c index d89bfe8ae84..10a9523b8da 100644 --- a/source/namedbresp.c +++ b/source/namedbresp.c @@ -92,8 +92,8 @@ 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, 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 +109,16 @@ 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->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); diff --git a/source/namedbserver.c b/source/namedbserver.c index afb1dc14315..260f8f3475e 100644 --- a/source/namedbserver.c +++ b/source/namedbserver.c @@ -50,7 +50,7 @@ extern BOOL updatedlists; remove_all_servers indicates everybody dies. ******************************************************************/ void remove_old_servers(struct work_record *work, time_t t, - BOOL remove_all) + BOOL remove_all) { struct server_record *s; struct server_record *nexts; @@ -59,23 +59,23 @@ void remove_old_servers(struct work_record *work, time_t t, for (s = work->serverlist; s; s = nexts) { if (remove_all || (s->death_time && (t == -1 || s->death_time < t))) - { - DEBUG(3,("Removing dead server %s\n",s->serv.name)); - updatedlists = True; - nexts = s->next; - - if (s->prev) s->prev->next = s->next; - if (s->next) s->next->prev = s->prev; - - if (work->serverlist == s) - work->serverlist = s->next; - - free(s); - } + { + DEBUG(3,("Removing dead server %s\n",s->serv.name)); + updatedlists = True; + nexts = s->next; + + if (s->prev) s->prev->next = s->next; + if (s->next) s->next->prev = s->prev; + + if (work->serverlist == s) + work->serverlist = s->next; + + free(s); + } else - { - nexts = s->next; - } + { + nexts = s->next; + } } } @@ -107,17 +107,17 @@ static void add_server(struct work_record *work,struct server_record *s) **************************************************************************/ struct server_record *find_server(struct work_record *work, char *name) { - struct server_record *ret; + struct server_record *ret; - if (!work) return NULL; - - for (ret = work->serverlist; ret; ret = ret->next) - { - if (strequal(ret->serv.name,name)) - { - return ret; - } - } + if (!work) return NULL; + + for (ret = work->serverlist; ret; ret = ret->next) + { + if (strequal(ret->serv.name,name)) + { + return ret; + } + } return NULL; } @@ -126,14 +126,15 @@ struct server_record *find_server(struct work_record *work, char *name) add a server entry ****************************************************************************/ struct server_record *add_server_entry(struct subnet_record *d, - struct work_record *work, - char *name,int servertype, - int ttl,char *comment, - BOOL replace) + struct work_record *work, + char *name,int servertype, + int ttl,char *comment, + BOOL replace) { BOOL newentry=False; struct server_record *s; - + int token = conf_workgroup_name_to_token(work->work_group, myname); + if (name[0] == '*') { return (NULL); @@ -160,16 +161,14 @@ struct server_record *add_server_entry(struct subnet_record *d, bzero((char *)s,sizeof(*s)); } - - if (strequal(lp_workgroup(),work->work_group)) - { - if (servertype) - servertype |= SV_TYPE_LOCAL_LIST_ONLY; - } + if (conf_should_workgroup_member(token)) + { + if (servertype) servertype |= SV_TYPE_LOCAL_LIST_ONLY; + } else - { + { servertype &= ~SV_TYPE_LOCAL_LIST_ONLY; - } + } /* update the entry */ StrnCpy(s->serv.name,name,sizeof(s->serv.name)-1); @@ -194,8 +193,8 @@ struct server_record *add_server_entry(struct subnet_record *d, } DEBUG(3,("server entry %s of type %x (%s) to %s %s\n", - name,servertype,comment, - work->work_group,inet_ntoa(d->bcast_ip))); + name,servertype,comment, + work->work_group,inet_ntoa(d->bcast_ip))); return(s); } @@ -213,9 +212,9 @@ void expire_servers(time_t t) struct work_record *work; for (work = d->workgrouplist; work; work = work->next) - { - remove_old_servers(work, t, False); - } + { + remove_old_servers(work, t, False); + } } } diff --git a/source/namedbsubnet.c b/source/namedbsubnet.c index 0bad79246ad..94decb7f0b7 100644 --- a/source/namedbsubnet.c +++ b/source/namedbsubnet.c @@ -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" @@ -90,16 +93,16 @@ struct subnet_record *find_subnet(struct in_addr bcast_ip) for (d = subnetlist; d; d = d->next) { if (ip_equal(bcast_ip, wins_ip)) - { + { if (ip_equal(bcast_ip, d->bcast_ip)) { return d; } } else if (same_net(bcast_ip, d->bcast_ip, d->mask_ip)) - { - return(d); - } + { + return(d); + } } return (NULL); @@ -154,24 +157,24 @@ static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr ****************************************************************************/ void add_subnet_interfaces(void) { - struct interface *i; - - /* loop on all local interfaces */ - for (i = local_interfaces; i; i = i->next) - { - /* add the interface into our subnet database */ - if (!find_subnet(i->bcast)) - { - make_subnet(i->bcast,i->nmask); - } - } - - /* add the pseudo-ip interface for WINS: 255.255.255.255 */ - if (lp_wins_support() || (*lp_wins_server())) + struct interface *i; + + /* loop on all local interfaces */ + for (i = local_interfaces; i; i = i->next) { - struct in_addr wins_bcast = ipgrp; - struct in_addr wins_nmask = ipzero; - make_subnet(wins_bcast, wins_nmask); + /* add the interface into our subnet database */ + if (!find_subnet(i->bcast)) + { + make_subnet(i->bcast,i->nmask); + } + } + + /* add the pseudo-ip interface for WINS: 255.255.255.255 */ + if (lp_wins_support() || (*lp_wins_server())) + { + struct in_addr wins_bcast = ipgrp; + struct in_addr wins_nmask = ipzero; + make_subnet(wins_bcast, wins_nmask); } } @@ -188,7 +191,7 @@ void add_my_subnets(char *group) if (*group == '*') return; - /* the coding choice is up to you, andrew: i can see why you don't want + /* 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) @@ -203,8 +206,8 @@ void add_my_subnets(char *group) to the named a workgroup. ****************************************************************************/ struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, - struct in_addr mask_ip, - char *name, BOOL add, BOOL lmhosts) + struct in_addr mask_ip, + char *name, BOOL add, BOOL lmhosts) { struct subnet_record *d; @@ -222,29 +225,41 @@ struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, /* add the domain into our domain database */ 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; - - /* 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); + 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); + + my_name = my_name ? my_name : myname; + my_comment = my_comment ? my_comment : lp_server_comment(); + + 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))); - } - - return d; + + /* add WORKGROUP(1e) and WORKGROUP(00) entries into name database + or register with WINS server, if it's our workgroup */ + 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; } @@ -290,31 +305,31 @@ void write_browse_list(void) { struct work_record *work; for (work = d->workgrouplist; work ; work = work->next) - { - struct server_record *s; - for (s = work->serverlist; s ; s = s->next) - { - fstring tmp; - - /* don't list domains I don't have a master for */ - if ((s->serv.type & SV_TYPE_DOMAIN_ENUM) && !s->serv.comment[0]) - { - continue; - } - - /* output server details, plus what workgroup/domain - they're in. without the domain information, the - combined list of all servers in all workgroups gets - sent to anyone asking about any workgroup! */ - - sprintf(tmp, "\"%s\"", s->serv.name); - fprintf(f, "%-25s ", tmp); - fprintf(f, "%08x ", s->serv.type); - sprintf(tmp, "\"%s\" ", s->serv.comment); - fprintf(f, "%-30s", tmp); - fprintf(f, "\"%s\"\n", work->work_group); - } - } + { + struct server_record *s; + for (s = work->serverlist; s ; s = s->next) + { + fstring tmp; + + /* don't list domains I don't have a master for */ + if ((s->serv.type & SV_TYPE_DOMAIN_ENUM) && !s->serv.comment[0]) + { + continue; + } + + /* output server details, plus what workgroup/domain + they're in. without the domain information, the + combined list of all servers in all workgroups gets + sent to anyone asking about any workgroup! */ + + sprintf(tmp, "\"%s\"", s->serv.name); + fprintf(f, "%-25s ", tmp); + fprintf(f, "%08x ", s->serv.type); + sprintf(tmp, "\"%s\" ", s->serv.comment); + fprintf(f, "%-30s", tmp); + fprintf(f, "\"%s\"\n", work->work_group); + } + } } fclose(f); diff --git a/source/namedbwork.c b/source/namedbwork.c index 04f2103254b..172a93860c2 100644 --- a/source/namedbwork.c +++ b/source/namedbwork.c @@ -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; - } - + 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; } @@ -131,8 +120,8 @@ static struct work_record *make_workgroup(char *name) remove workgroups ******************************************************************/ struct work_record *remove_workgroup(struct subnet_record *d, - struct work_record *work, - BOOL remove_all_servers) + struct work_record *work, + BOOL remove_all_servers) { struct work_record *ret_work = NULL; @@ -165,7 +154,7 @@ struct work_record *remove_workgroup(struct subnet_record *d, lmhosts file to be added. **************************************************************************/ struct work_record *find_workgroupstruct(struct subnet_record *d, - fstring name, BOOL add) + fstring name, BOOL add) { struct work_record *ret, *work; @@ -174,23 +163,26 @@ struct work_record *find_workgroupstruct(struct subnet_record *d, DEBUG(4, ("workgroup search for %s: ", name)); if (strequal(name, "*")) - { + { DEBUG(2,("add any workgroups: initiating browser search on %s\n", - inet_ntoa(d->bcast_ip))); + inet_ntoa(d->bcast_ip))); queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY, NAME_QUERY_FIND_MST, - MSBROWSE,0x1,0,0,0,NULL,NULL, - True,False, d->bcast_ip, d->bcast_ip); + -1,MSBROWSE,0x1,0,0,0,NULL,NULL, + True,False, d->bcast_ip, d->bcast_ip); 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; } @@ -200,13 +192,13 @@ struct work_record *find_workgroupstruct(struct subnet_record *d, if ((work = make_workgroup(name))) { if (!ip_equal(d->bcast_ip, ipgrp) && - lp_preferred_master() && - strequal(lp_workgroup(), name)) - { - DEBUG(3, ("preferred master startup for %s\n", work->work_group)); - work->needelection = True; - work->ElectionCriterion |= (1<<3); - } + lp_preferred_master() && + conf_should_local_master(work->token)) + { + DEBUG(3, ("preferred master startup for %s\n", work->work_group)); + work->needelection = True; + work->ElectionCriterion |= (1<<3); + } add_workgroup(work, d); return(work); } @@ -224,25 +216,25 @@ void dump_workgroups(void) for (d = subnetlist; d; d = d->next) { if (d->workgrouplist) - { - struct work_record *work; - - DEBUG(4,("dump domain bcast=%15s: ", inet_ntoa(d->bcast_ip))); - DEBUG(4,(" netmask=%15s:\n", inet_ntoa(d->mask_ip))); - - for (work = d->workgrouplist; work; work = work->next) - { - DEBUG(4,("\t%s(%d)\n", work->work_group, work->token)); - if (work->serverlist) - { - struct server_record *s; - for (s = work->serverlist; s; s = s->next) - { - DEBUG(4,("\t\t%s %8x (%s)\n", - s->serv.name, s->serv.type, s->serv.comment)); - } - } - } - } + { + struct work_record *work; + + DEBUG(4,("dump domain bcast=%15s: ", inet_ntoa(d->bcast_ip))); + DEBUG(4,(" netmask=%15s:\n", inet_ntoa(d->mask_ip))); + + for (work = d->workgrouplist; work; work = work->next) + { + DEBUG(4,("\t%s(%d)\n", work->work_group, work->token)); + if (work->serverlist) + { + struct server_record *s; + for (s = work->serverlist; s; s = s->next) + { + DEBUG(4,("\t\t%s %8x (%s)\n", + s->serv.name, s->serv.type, s->serv.comment)); + } + } + } + } } } diff --git a/source/nameelect.c b/source/nameelect.c index 07429013e0d..225b0bfaae0 100644 --- a/source/nameelect.c +++ b/source/nameelect.c @@ -28,10 +28,12 @@ 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. */ -#include "includes.h" +#include "includes.h" extern int ClientNMB; extern int ClientDGRAM; @@ -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 ******************************************************************/ @@ -68,22 +72,22 @@ void check_master_browser(void) dump_workgroups(); for (d = subnetlist; d; d = d->next) + { + struct work_record *work; + + for (work = d->workgrouplist; work; work = work->next) { - struct work_record *work; + /* if we are not the browse master of a workgroup, and we can't + find a browser on the subnet, do something about it. */ - for (work = d->workgrouplist; work; work = work->next) - { - /* if we are not the browse master of a workgroup, and we can't - find a browser on the subnet, do something about it. */ - - if (!AM_MASTER(work)) - { - queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK, - work->work_group,0x1d,0,0,0,NULL,NULL, - True,False,d->bcast_ip,d->bcast_ip); - } - } + if (!AM_MASTER(work)) + { + queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK, + work->token, work->work_group,0x1d,0,0,0,NULL,NULL, + True,False,d->bcast_ip,d->bcast_ip); + } } + } } @@ -102,11 +106,11 @@ 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))); + work->work_group,inet_ntoa(d->bcast_ip))); /* we can attempt to become master browser */ work->needelection = True; @@ -114,10 +118,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); } @@ -128,7 +132,7 @@ void browser_gone(char *work_name, struct in_addr ip) send an election packet **************************************************************************/ void send_election(struct subnet_record *d, char *group,uint32 criterion, - int timeup,char *name) + int timeup,char *name) { pstring outbuf; char *p; @@ -136,7 +140,7 @@ void send_election(struct subnet_record *d, char *group,uint32 criterion, if (!d) return; DEBUG(2,("Sending election to %s for workgroup %s\n", - inet_ntoa(d->bcast_ip),group)); + inet_ntoa(d->bcast_ip),group)); bzero(outbuf,sizeof(outbuf)); p = outbuf; @@ -152,7 +156,7 @@ void send_election(struct subnet_record *d, char *group,uint32 criterion, p = skip_string(p,1); send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,PTR_DIFF(p,outbuf), - name,group,0,0x1e,d->bcast_ip,*iface_ip(d->bcast_ip)); + name,group,0,0x1e,d->bcast_ip,*iface_ip(d->bcast_ip)); } @@ -173,7 +177,7 @@ void name_unregister_work(struct subnet_record *d, char *name, int name_type) if (!(work = find_workgroupstruct(d, name, False))) return; if (ms_browser_name(name, name_type) || - (AM_MASTER(work) && strequal(name, lp_workgroup()) == 0 && + (AM_MASTER(work) && conf_should_workgroup_member(work->token) && (name_type == 0x1d || name_type == 0x1b))) { int remove_type = 0; @@ -184,7 +188,7 @@ void name_unregister_work(struct subnet_record *d, char *name, int name_type) remove_type = SV_TYPE_MASTER_BROWSER; if (name_type == 0x1b) remove_type = SV_TYPE_DOMAIN_MASTER; - + become_nonmaster(d, work, remove_type); } } @@ -197,17 +201,20 @@ 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, + 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; + 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) { @@ -251,11 +258,23 @@ 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; + + char *my_name ; + char *my_comment; if (!work) return; + my_name = conf_browsing_alias(work->token); + my_comment = conf_browsing_alias_comment(work->token); + + my_name = my_name ? my_name : myname; + my_comment = my_comment ? my_comment : lp_server_comment(); + + StrnCpy(comment, my_comment, 43); + DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n", - work->work_group,inet_ntoa(d->bcast_ip),work->state)); + work->work_group,inet_ntoa(d->bcast_ip),work->state)); switch (work->state) { @@ -268,10 +287,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 +301,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 +317,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 +338,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 +360,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()) - { + { 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,10 +389,10 @@ 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; + uint32 update_type = 0; DEBUG(3,("domain third stage: samba is now a domain master.\n")); work->state = MST_DOMAIN; /* ... registering WORKGROUP(1b) succeeded */ @@ -377,30 +400,30 @@ void become_master(struct subnet_record *d, struct work_record *work) update_type |= DFLT_SERVER_TYPE | SV_TYPE_DOMAIN_MASTER | SV_TYPE_POTENTIAL_BROWSER; - work->ServerType |= update_type; - add_server_entry(d,work,myname,work->ServerType,0,lp_serverstring(),True); - - for (d1 = subnetlist; d1; d1 = d1->next) - { - struct work_record *w; - if (ip_equal(d1->bcast_ip, d->bcast_ip)) continue; - - for (w = d1->workgrouplist; w; w = w->next) - { - struct server_record *s = find_server(w, myname); - if (strequal(w->work_group, work->work_group)) - { - w->ServerType |= update_type; - } - if (s) - { - s->serv.type |= update_type; - DEBUG(4,("found server %s on %s: update to %8x\n", - s->serv.name, inet_ntoa(d1->bcast_ip), - s->serv.type)); - } - } - } + work->ServerType |= update_type; + add_server_entry(d,work,my_name,work->ServerType,0,comment,True); + + for (d1 = subnetlist; d1; d1 = d1->next) + { + struct work_record *w; + if (ip_equal(d1->bcast_ip, d->bcast_ip)) continue; + + for (w = d1->workgrouplist; w; w = w->next) + { + struct server_record *s = find_server(w, my_name); + if (strequal(w->work_group, work->work_group)) + { + w->ServerType |= update_type; + } + if (s) + { + s->serv.type |= update_type; + DEBUG(4,("found server %s on %s: update to %8x\n", + s->serv.name, inet_ntoa(d1->bcast_ip), + s->serv.type)); + } + } + } } break; @@ -421,10 +444,25 @@ void become_master(struct subnet_record *d, struct work_record *work) names, and tells the world that we are no longer a master browser. ******************************************************************/ void become_nonmaster(struct subnet_record *d, struct work_record *work, - int remove_type) + int remove_type) { int new_server_type = work->ServerType; + pstring comment; + + char *my_name ; + char *my_comment; + + if (!work) return; + + my_name = conf_browsing_alias (work->token); + my_comment = conf_browsing_alias_comment(work->token); + + my_name = my_name ? my_name : myname; + my_comment = my_comment ? my_comment : lp_server_comment(); + + StrnCpy(comment, my_comment, 43); + DEBUG(2,("Becoming non-master for %s\n",work->work_group)); /* can only remove master or domain types with this function */ @@ -444,9 +482,7 @@ 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; @@ -455,15 +491,21 @@ void become_nonmaster(struct subnet_record *d, struct work_record *work, { if (work->state == MST_DOMAIN) 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) work->state = MST_NONE; - remove_name_entry(d,work->work_group,0x1d); + remove_name_entry(d,work->token,work->work_group,0x1d); } + + /* announce ourselves as no longer active as a master browser. */ + announce_server(d,work,work->work_group,my_name,GET_TTL(0),work->ServerType); + + /* update our internal records with our new server state */ + add_server_entry(d, work, my_name, work->ServerType, 0, my_comment, True); } @@ -486,25 +528,25 @@ void run_elections(void) { struct work_record *work; for (work = d->workgrouplist; work; work = work->next) - { - if (work->RunningElection) - { - send_election(d,work->work_group, work->ElectionCriterion, - t-StartupTime,myname); - - if (work->ElectionCount++ >= 4) - { - /* I won! now what :-) */ - DEBUG(2,(">>> Won election on %s %s <<<\n", - work->work_group,inet_ntoa(d->bcast_ip))); - - work->RunningElection = False; - work->state = MST_NONE; - - become_master(d, work); - } - } - } + { + if (work->RunningElection) + { + send_election(d,work->work_group, work->ElectionCriterion, + t-StartupTime,conf_browsing_alias(work->token)); + + if (work->ElectionCount++ >= 4) + { + /* I won! now what :-) */ + DEBUG(2,(">>> Won election on %s %s <<<\n", + work->work_group,inet_ntoa(d->bcast_ip))); + + work->RunningElection = False; + work->state = MST_NONE; + + become_master(d, work); + } + } + } } } @@ -513,7 +555,7 @@ void run_elections(void) work out if I win an election ******************************************************************/ static BOOL win_election(struct work_record *work,int version,uint32 criterion, - int timeup,char *name) + int timeup,char *name) { int mytimeup = time(NULL) - StartupTime; uint32 mycriterion = work->ElectionCriterion; @@ -533,7 +575,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); } @@ -571,30 +613,38 @@ void process_election(struct packet_struct *p,char *buf) if (same_context(dgram)) return; for (work = d->workgrouplist; work; work = work->next) + { + if (!conf_should_local_master(work->token)) continue; + + if (win_election(work, version,criterion,timeup,name)) { - if (!strequal(work->work_group, lp_workgroup())) - continue; - - if (win_election(work, version,criterion,timeup,name)) { - if (!work->RunningElection) { - work->needelection = True; - work->ElectionCount=0; - work->state = MST_NONE; - } - } else { - work->needelection = False; - - 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 (AM_MASTER(work)) - become_nonmaster(d, work, - SV_TYPE_MASTER_BROWSER| - SV_TYPE_DOMAIN_MASTER); - } - } + if (!work->RunningElection) + { + work->needelection = True; + work->ElectionCount=0; + work->state = MST_NONE; + } + } + else + { + work->needelection = False; + + 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); + } + } } + } } @@ -615,18 +665,18 @@ BOOL check_elections(void) { struct work_record *work; for (work = d->workgrouplist; work; work = work->next) - { - run_any_election |= work->RunningElection; - - if (work->needelection && !work->RunningElection) - { - DEBUG(3,(">>> Starting election on %s %s <<<\n", - work->work_group,inet_ntoa(d->bcast_ip))); - work->ElectionCount = 0; - work->RunningElection = True; - work->needelection = False; - } - } + { + run_any_election |= work->RunningElection; + + if (work->needelection && !work->RunningElection) + { + DEBUG(3,(">>> Starting election on %s %s <<<\n", + work->work_group,inet_ntoa(d->bcast_ip))); + work->ElectionCount = 0; + work->RunningElection = True; + work->needelection = False; + } + } } return run_any_election; } diff --git a/source/namepacket.c b/source/namepacket.c index 5bfa55d4f16..1ebdf0a2bd6 100644 --- a/source/namepacket.c +++ b/source/namepacket.c @@ -38,62 +38,137 @@ BOOL CanRecurse = True; extern pstring scope; extern struct in_addr ipgrp; -static uint16 name_trn_id=0; +extern uint16 name_trn_id; -/*************************************************************************** - updates the unique transaction identifier - **************************************************************************/ -void debug_browse_data(char *outbuf, int len) +/**************************************************************************** + process a nmb packet + ****************************************************************************/ +static void process_nmb(struct packet_struct *p) { - int i,j; - for (i = 0; i < len; i+= 16) + 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) { - DEBUG(4, ("%3x char ", i)); - - for (j = 0; j < 16; j++) - { - unsigned char x = outbuf[i+j]; - if (x < 32 || x > 127) x = '.'; - - if (i+j >= len) break; - DEBUG(4, ("%c", x)); - } - - DEBUG(4, (" hex ", i)); - - for (j = 0; j < 16; j++) - { - if (i+j >= len) break; - DEBUG(4, (" %02x", outbuf[i+j])); - } - - DEBUG(4, ("\n")); + 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; + } + } } /*************************************************************************** updates the unique transaction identifier **************************************************************************/ -static void update_name_trn_id(void) +void debug_browse_data(char *outbuf, int len) { - if (!name_trn_id) - { - name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100); - } - name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF; + int i,j; + for (i = 0; i < len; i+= 16) + { + DEBUG(4, ("%3x char ", i)); + + for (j = 0; j < 16; j++) + { + unsigned char x = outbuf[i+j]; + if (x < 32 || x > 127) x = '.'; + + if (i+j >= len) break; + DEBUG(4, ("%c", x)); + } + + DEBUG(4, (" hex ", i)); + + for (j = 0; j < 16; j++) + { + if (i+j >= len) break; + DEBUG(4, (" %02x", outbuf[i+j])); + } + + DEBUG(4, ("\n")); + } + } /**************************************************************************** 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. ****************************************************************************/ -void initiate_netbios_packet(uint16 *id, - int fd,int quest_type,char *name,int name_type, - int nb_flags,BOOL bcast,BOOL recurse, - struct in_addr to_ip) +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) { struct packet_struct p; struct nmb_packet *nmb = &p.packet.nmb; @@ -101,8 +176,6 @@ void initiate_netbios_packet(uint16 *id, char *packet_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; } @@ -110,18 +183,13 @@ void initiate_netbios_packet(uint16 *id, if (quest_type == NMB_REL ) { packet_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))); + packet_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; @@ -162,7 +230,7 @@ void initiate_netbios_packet(uint16 *id, nmb->additional->rdlength = 6; nmb->additional->rdata[0] = nb_flags; putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip)); - } + } p.ip = to_ip; p.port = NMB_PORT; @@ -170,12 +238,21 @@ void initiate_netbios_packet(uint16 *id, p.timestamp = time(NULL); p.packet_type = NMB_PACKET; - if (!send_packet(&p)) { - DEBUG(3,("send_packet to %s %d failed\n",inet_ntoa(p.ip),p.port)); - *id = 0xffff; + if (zero_ip(to_ip)) /* samba's own ip */ + { + DEBUG(4,("process packet ourselves\n")); + /* respond internally to the packet. */ + process_nmb(&p); } - - return; + else + { + if (!send_packet(&p)) { + DEBUG(3,("send_packet to %s %d failed\n",inet_ntoa(p.ip),p.port)); + return False; + } + } + + return True; } @@ -183,9 +260,9 @@ void initiate_netbios_packet(uint16 *id, reply to a netbios name packet ****************************************************************************/ void reply_netbios_packet(struct packet_struct *p1,int trn_id, - int rcode, int rcv_code, int opcode, BOOL recurse, - struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, - char *data,int len) + int rcode, int rcv_code, int opcode, BOOL recurse, + struct nmb_name *rr_name,int rr_type,int rr_class,int ttl, + char *data,int len) { struct packet_struct p; struct nmb_packet *nmb = &p.packet.nmb; @@ -198,31 +275,31 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id, switch (rcv_code) { case NMB_STATUS: - { + { packet_type = "nmb_status"; recursion_desired = True; break; } case NMB_QUERY: - { + { packet_type = "nmb_query"; recursion_desired = True; break; } case NMB_REG: - { + { packet_type = "nmb_reg"; recursion_desired = True; break; } case NMB_REL: - { + { packet_type = "nmb_rel"; recursion_desired = False; break; } case NMB_WAIT_ACK: - { + { packet_type = "nmb_wack"; recursion_desired = False; break; @@ -230,14 +307,14 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id, default: { DEBUG(1,("replying netbios packet: %s %s\n", - packet_type, namestr(rr_name), inet_ntoa(p.ip))); + packet_type, namestr(rr_name), inet_ntoa(p.ip))); return; } } DEBUG(4,("replying netbios packet: %s %s\n", - packet_type, namestr(rr_name), inet_ntoa(p.ip))); + packet_type, namestr(rr_name), inet_ntoa(p.ip))); nmb->header.name_trn_id = trn_id; nmb->header.opcode = opcode; @@ -265,16 +342,25 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id, nmb->answers->ttl = ttl; if (data && len) - { - nmb->answers->rdlength = len; - memcpy(nmb->answers->rdata, data, len); - } + { + nmb->answers->rdlength = len; + memcpy(nmb->answers->rdata, data, len); + } p.packet_type = NMB_PACKET; debug_nmb_packet(&p); - send_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); + } } @@ -352,7 +438,7 @@ static void process_dgram(struct packet_struct *p) buf = &dgram->data[0]; buf -= 4; /* XXXX for the pseudo tcp length - - someday I need to get rid of this */ + someday I need to get rid of this */ if (CVAL(buf,smb_com) != SMBtrans) return; @@ -360,8 +446,8 @@ static void process_dgram(struct packet_struct *p) buf2 = smb_base(buf) + SVAL(buf,smb_vwv12); DEBUG(4,("datagram from %s to %s for %s of type %d len=%d\n", - namestr(&dgram->source_name),namestr(&dgram->dest_name), - smb_buf(buf),CVAL(buf2,0),len)); + namestr(&dgram->source_name),namestr(&dgram->dest_name), + smb_buf(buf),CVAL(buf2,0),len)); if (len <= 0) return; @@ -379,83 +465,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 ******************************************************************/ @@ -466,15 +475,15 @@ void run_packet_queue() while ((p=packet_queue)) { switch (p->packet_type) - { - case NMB_PACKET: - process_nmb(p); - break; - - case DGRAM_PACKET: - process_dgram(p); - break; - } + { + case NMB_PACKET: + process_nmb(p); + break; + + case DGRAM_PACKET: + process_dgram(p); + break; + } packet_queue = packet_queue->next; if (packet_queue) packet_queue->prev = NULL; @@ -550,8 +559,8 @@ try_again: wrong things to do! I should send to the requestors port. XXX **************************************************************************/ BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname, - char *dstname,int src_type,int dest_type, - struct in_addr dest_ip,struct in_addr src_ip) + char *dstname,int src_type,int dest_type, + struct in_addr dest_ip,struct in_addr src_ip) { struct packet_struct p; struct dgram_packet *dgram = &p.packet.dgram; diff --git a/source/nameresp.c b/source/nameresp.c index 7fcb41e79f0..a9422116fbc 100644 --- a/source/nameresp.c +++ b/source/nameresp.c @@ -35,15 +35,30 @@ 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 **************************************************************************/ static void dead_netbios_entry(struct subnet_record *d, - struct response_record *n) + struct response_record *n) { DEBUG(3,("Removing dead netbios entry for %s %s (num_msgs=%d)\n", - inet_ntoa(n->send_ip), namestr(&n->name), n->num_msgs)); + inet_ntoa(n->send_ip), namestr(&n->name), n->num_msgs)); debug_state_type(n->state); @@ -51,118 +66,118 @@ static void dead_netbios_entry(struct subnet_record *d, { case NAME_QUERY_CONFIRM: { - if (!lp_wins_support()) return; /* only if we're a WINS server */ + if (!lp_wins_support()) return; /* only if we're a WINS server */ - if (n->num_msgs == 0) + if (n->num_msgs == 0) { - /* oops. name query had no response. check that the name is - unique and then remove it from our WINS database */ - - /* IMPORTANT: see query_refresh_names() */ - - if ((!NAME_GROUP(n->nb_flags))) - { - struct subnet_record *d1 = find_subnet(ipgrp); - if (d1) - { - /* remove the name that had been registered with us, - and we're now getting no response when challenging. - see rfc1001.txt 15.5.2 - */ - remove_netbios_name(d1, n->name.name, n->name.name_type, - REGISTER, n->send_ip); - } - } - } - break; + /* oops. name query had no response. check that the name is + unique and then remove it from our WINS database */ + + /* IMPORTANT: see query_refresh_names() */ + + if ((!NAME_GROUP(n->reply.nb_flags))) + { + struct subnet_record *d1 = find_subnet(ipgrp); + if (d1) + { + /* remove the name that had been registered with us, + and we're now getting no response when challenging. + see rfc1001.txt 15.5.2 + */ + remove_netbios_name(d1, n->name.name, n->name.name_type, + REGISTER, n->send_ip); + } + } + } + break; + } + + case NAME_QUERY_MST_CHK: + { + /* if no response received, the master browser must have gone + down on that subnet, without telling anyone. */ + + /* IMPORTANT: see response_netbios_packet() */ + + if (n->num_msgs == 0) + browser_gone(n->name.name, n->send_ip); + break; } - case NAME_QUERY_MST_CHK: - { - /* if no response received, the master browser must have gone - down on that subnet, without telling anyone. */ - - /* IMPORTANT: see response_netbios_packet() */ - - if (n->num_msgs == 0) - browser_gone(n->name.name, n->send_ip); - break; - } - - case NAME_RELEASE: - { - /* if no response received, it must be OK for us to release the - name. nobody objected (including a potentially dead or deaf - WINS server) */ - - /* IMPORTANT: see response_name_release() */ - - if (ismyip(n->send_ip)) - { - name_unregister_work(d,n->name.name,n->name.name_type); - } - if (!n->bcast) - { - DEBUG(0,("WINS server did not respond to name release!\n")); + case NAME_RELEASE: + { + /* if no response received, it must be OK for us to release the + name. nobody objected (including a potentially dead or deaf + WINS server) */ + + /* IMPORTANT: see response_name_release() */ + + if (ismyip(n->send_ip)) + { + name_unregister_work(d,n->name.name,n->name.name_type); + } + if (!n->bcast) + { + DEBUG(0,("WINS server did not respond to name release!\n")); /* XXXX whoops. we have problems. must deal with this */ - } - break; - } - - case NAME_REGISTER_CHALLENGE: - { - /* name challenge: no reply. we can reply to the person that - wanted the unique name and tell them that they can have it - */ - - add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name, - n->nb_flags, GET_TTL(0), - n->reply_to_ip, False, n->reply_to_ip); - - if (!n->bcast) - { - DEBUG(1,("WINS server did not respond to name registration!\n")); + } + break; + } + + case NAME_REGISTER_CHALLENGE: + { + /* name challenge: no reply. we can reply to the person that + wanted the unique name and tell them that they can have it + */ + + add_name_respond(d,n->fd,d->myip, n->response_id ,&n->name, + n->reply.nb_flags, GET_TTL(0), + n->reply.ip, False, n->reply.ip); + + if (!n->bcast) + { + DEBUG(1,("WINS server did not respond to name registration!\n")); /* XXXX whoops. we have problems. must deal with this */ - } + } break; - } - - case NAME_REGISTER: - { - /* if no response received, and we are using a broadcast registration - method, it must be OK for us to register the name: nobody objected - on that subnet. if we are using a WINS server, then the WINS - server must be dead or deaf. - */ - if (n->bcast) - { - /* broadcast method: implicit acceptance of the name registration - by not receiving any objections. */ - - /* IMPORTANT: see response_name_reg() */ - - name_register_work(d,n->name.name,n->name.name_type, - n->nb_flags, n->ttl, n->reply_to_ip, n->bcast); - } - else - { - /* received no response. rfc1001.txt states that after retrying, - we should assume the WINS server is dead, and fall back to - broadcasting (see bits about M nodes: can't find any right + } + + case NAME_REGISTER: + { + /* if no response received, and we are using a broadcast registration + method, it must be OK for us to register the name: nobody objected + on that subnet. if we are using a WINS server, then the WINS + server must be dead or deaf. + */ + if (n->bcast) + { + /* broadcast method: implicit acceptance of the name registration + by not receiving any objections. */ + + /* IMPORTANT: see response_name_reg() */ + + name_register_work(d,n->token,n->name.name,n->name.name_type, + &n->reply, n->ttl, n->reply.ip, n->bcast); + } + else + { + /* received no response. rfc1001.txt states that after retrying, + we should assume the WINS server is dead, and fall back to + broadcasting (see bits about M nodes: can't find any right now) */ - - DEBUG(1,("WINS server did not respond to name registration!\n")); + + DEBUG(1,("WINS server did not respond to name registration!\n")); /* XXXX whoops. we have problems. must deal with this */ - } - break; - } - - default: - { - /* nothing to do but delete the dead expected-response structure */ - /* this is normal. */ - break; - } + } + break; + } + + default: + { + /* nothing to do but delete the dead expected-response structure */ + /* this is normal. */ + break; + } } } @@ -184,33 +199,33 @@ void expire_netbios_response_entries() for (n = d->responselist; n; n = nextn) { - nextn = n->next; + nextn = n->next; if (n->repeat_time <= time(NULL)) - { - if (n->repeat_count > 0) - { - /* resend the entry */ - 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); + { + if (n->repeat_count > 0) + { + /* resend the entry */ + initiate_netbios_packet(n->response_id, n->fd, n->quest_type, + n->name.name, n->name.name_type, + n->reply.nb_flags, n->bcast, n->recurse, n->send_ip); n->repeat_time += n->repeat_interval; /* XXXX ms needed */ n->repeat_count--; - } - else - { + } + else + { DEBUG(4,("timeout response %d for %s %s\n", - n->response_id, namestr(&n->name), + n->response_id, namestr(&n->name), inet_ntoa(n->send_ip))); - dead_netbios_entry (d,n); /* process the non-response */ + dead_netbios_entry (d,n); /* process the non-response */ remove_response_record(d,n); /* remove the non-response */ - continue; - } - } + continue; + } + } } } } @@ -221,44 +236,56 @@ void expire_netbios_response_entries() 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, - 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) +void queue_netbios_pkt_wins(struct subnet_record *d, + int fd,int quest_type,enum state_type state, + int token, 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) { - /* 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 - which one samba is supposed to be - */ + /* 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 + which one samba is supposed to be + */ - if ((!lp_wins_support()) && (*lp_wins_server())) + if ((!lp_wins_support()) && (*lp_wins_server())) { - /* samba is not a WINS server, and we are using a WINS server */ - struct in_addr wins_ip; - wins_ip = *interpret_addr2(lp_wins_server()); - - if (!zero_ip(wins_ip)) - { - bcast = False; - send_ip = wins_ip; - } + /* samba is not a WINS server, and we are using a WINS server */ + struct in_addr wins_ip; + wins_ip = *interpret_addr2(lp_wins_server()); + + if (!zero_ip(wins_ip)) + { + bcast = False; + send_ip = wins_ip; + } + else + { + /* oops. smb.conf's wins server parameter MUST be a host_name + or an ip_address. */ + DEBUG(0,("invalid smb.conf parameter 'wins server'\n")); + } + } + + if (zero_ip(send_ip)) + { + /* doing a netbios query to samba as a WINS server, internally */ + if (lp_wins_support()) + { + DEBUG(4,("queue netbios packet with ourselves...\n")); + bcast = False; + } else - { - /* oops. smb.conf's wins server parameter MUST be a host_name - or an ip_address. */ - DEBUG(0,("invalid smb.conf parameter 'wins server'\n")); - } + { + return; + } } - - if (zero_ip(send_ip)) return NULL; - - return queue_netbios_packet(d,fd, quest_type, state, - name, name_type, nb_flags, ttl, + + queue_netbios_packet(d,fd, quest_type, state, + token, name, name_type, nb_flags, ttl, server_type,my_name,my_comment, - bcast, recurse, send_ip, reply_to_ip); + bcast, recurse, send_ip, reply_to_ip); } @@ -268,35 +295,37 @@ struct response_record *queue_netbios_pkt_wins(struct subnet_record *d, 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) +void queue_netbios_packet(struct subnet_record *d, + int fd,int quest_type,enum state_type state, + int token, 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 (ip_equal(wins_ip, send_ip)) return; + + 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, nb_flags, ttl, + server_type, my_name, my_comment, + bcast, recurse, send_ip, reply_to_ip))) + { + add_response_record(d,n); + } - if (id == 0xffff) { + 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))); - return NULL; + remove_response_record(d, n); + 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))) - { - add_response_record(d,n); - return n; - } - return NULL; } diff --git a/source/nameserv.c b/source/nameserv.c index c8bbb528116..20b46d52242 100644 --- a/source/nameserv.c +++ b/source/nameserv.c @@ -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, 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, 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; @@ -115,7 +117,7 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags) make_nmb_name(&n, name, type, scope); if (find_name(d->namelist, &n, SELF)) - re_reg = True; + re_reg = True; /* XXXX BUG: if samba is offering WINS support, it should still add the name entry to a local-subnet name database. see rfc1001.txt 15.1.1 p28 @@ -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,26 +134,38 @@ 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, &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, - False, True, ipzero, ipzero); + queue_netbios_pkt_wins(d,ClientNMB, + re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, + token, name, type, 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, - True, True, d->bcast_ip, ipzero); + queue_netbios_packet(d,ClientNMB, + re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER, + token, name, type, 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 @@ -171,30 +188,54 @@ void add_my_names(void) { BOOL wins = lp_wins_support() && 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); + 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); + } + } + /* 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 only be a logon server for the DEFAULT samba workgroup. for now. */ + + 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); + token = conf_workgroup_name_to_token(lp_workgroup(),myname); + add_my_name_entry(d, token, 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); - if (work && work->state == MST_NONE) + for (token = 0; token < get_num_workgroups(); token++) { - work->state = MST_DOMAIN_NONE; - become_master(d, work); + 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); + } + } + } } } } @@ -205,52 +246,24 @@ void add_my_names(void) **************************************************************************/ void remove_my_names() { - struct subnet_record *d; - - for (d = subnetlist; d; d = d->next) - { - struct name_record *n, *next; - - for (n = d->namelist; n; n = next) - { - next = n->next; - if (n->source == SELF) - { - /* 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; + struct subnet_record *d; - for (d = subnetlist; d; d = d->next) - { - struct name_record *n; - - for (n = d->namelist; n; n = n->next) + for (d = subnetlist; d; d = d->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); - } + struct name_record *n, *next; + + for (n = d->namelist; n; n = next) + { + next = n->next; + if (n->source == SELF) + { + /* 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, -1, n->name.name, n->name.name_type); + } + } } - } } @@ -265,55 +278,55 @@ void refresh_my_names(time_t t) ******************************************************************/ void query_refresh_names(void) { - struct name_record *n; - struct subnet_record *d = find_subnet(ipgrp); + struct name_record *n; + struct subnet_record *d = find_subnet(ipgrp); - static time_t lasttime = 0; - time_t t = time(NULL); + static time_t lasttime = 0; + time_t t = time(NULL); - int count = 0; - int name_refresh_time = NAME_POLL_REFRESH_TIME; - int max_count = name_refresh_time * 2 / NAME_POLL_INTERVAL; - if (max_count > 10) max_count = 10; + int count = 0; + int name_refresh_time = NAME_POLL_REFRESH_TIME; + int max_count = name_refresh_time * 2 / NAME_POLL_INTERVAL; + if (max_count > 10) max_count = 10; - name_refresh_time = NAME_POLL_INTERVAL * max_count / 2; + name_refresh_time = NAME_POLL_INTERVAL * max_count / 2; - /* if (!lp_poll_wins()) return; polling of registered names allowed */ + /* if (!lp_poll_wins()) return; polling of registered names allowed */ - if (!d) return; + if (!d) return; if (!lasttime) lasttime = t; - if (t - lasttime < NAME_POLL_INTERVAL) return; + if (t - lasttime < NAME_POLL_INTERVAL) return; lasttime = time(NULL); - for (n = d->namelist; n; n = n->next) - { - /* only do unique, registered names */ - - if (n->source != REGISTER) continue; - if (!NAME_GROUP(n->ip_flgs[0].nb_flags)) continue; - - if (n->refresh_time < t) - { - 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, - False,False,n->ip_flgs[0].ip,n->ip_flgs[0].ip); - count++; - } - - if (count >= max_count) - { - /* don't do too many of these at once, but do enough to - cover everyone in the list */ - return; - } - - /* this name will be checked on again, if it's not removed */ - n->refresh_time += name_refresh_time; - } + for (n = d->namelist; n; n = n->next) + { + /* only do unique, registered names. */ + + if (n->source != REGISTER) continue; + if (!NAME_GROUP(n->ip_flgs[0].nb_flags)) continue; + + if (n->refresh_time < t) + { + DEBUG(3,("Polling name %s\n", namestr(&n->name))); + + queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM, + -1,n->name.name, n->name.name_type, + 0,0,0,NULL,NULL, + False,False,n->ip_flgs[0].ip,n->ip_flgs[0].ip); + count++; + } + + if (count >= max_count) + { + /* don't do too many of these at once, but do enough to + cover everyone in the list */ + return; + } + + /* this name will be checked on again, if it's not removed */ + n->refresh_time += name_refresh_time; + } } diff --git a/source/nameservreply.c b/source/nameservreply.c index b01c2c25b4c..ae568198ac8 100644 --- a/source/nameservreply.c +++ b/source/nameservreply.c @@ -294,7 +294,7 @@ 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, + -1,reply_name->name,reply_name->name_type, nb_flags,0,0,NULL,NULL, False, False, n->ip_flgs[0].ip, p->ip); } diff --git a/source/nameservresp.c b/source/nameservresp.c index a4cda7cdfb5..0b8e23bfae0 100644 --- a/source/nameservresp.c +++ b/source/nameservresp.c @@ -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, 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, + 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); + /* oh dear. we have problems. possibly unbecome a master browser. */ + name_unregister_work(d,name->name,name->name_type); } } @@ -127,58 +109,53 @@ 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, - struct response_record *n, struct subnet_record *d) +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 - ", - namestr(&n->name), inet_ntoa(n->send_ip))); - - if (!name_equal(&n->name, ans_name)) - { - /* someone gave us the wrong name as a reply. oops. */ - /* XXXX should say to them 'oi! release that name!' */ - - DEBUG(4,("unexpected name received: %s\n", namestr(ans_name))); - return; - } - - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - /* we had sent out a name query to the current owner - of a name because someone else wanted it. now they - have responded saying that they still want the name, - so the other host can't have it. - */ - - /* 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) - { - /* 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)); - return; - } - - /* do an announce host */ - do_announce_host(ANN_HostAnnouncement, - n->my_name , 0x00, d->myip, - n->name.name, 0x1d, found_ip, - n->ttl, - n->my_name, n->server_type, n->my_comment); - } - else - { - /* XXXX negative name query response. no master exists. oops */ - } + DEBUG(4, ("Name query at %s ip %s - ", + namestr(&n->name), inet_ntoa(n->send_ip))); + + if (!name_equal(&n->name, ans_name)) + { + /* someone gave us the wrong name as a reply. oops. */ + /* XXXX should say to them 'oi! release that name!' */ + + DEBUG(4,("unexpected name received: %s\n", namestr(ans_name))); + return; + } + + if (data) + { + /* we had sent out a name query to the current owner + of a name because someone else wanted it. now they + have responded saying that they still want the name, + so the other host can't have it. + */ + + /* first check all the details are correct */ + + 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->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, data->ip, + n->ttl, + n->my_name, n->server_type, n->my_comment); + } + else + { + /* XXXX negative name query response. no master exists. oops */ + } } @@ -187,18 +164,18 @@ static void response_announce_host(struct nmb_name *ans_name, NAME_QUERY_SRV_CHK, and NAME_QUERY_FIND_MST dealt with here. ****************************************************************************/ static void response_server_check(struct nmb_name *ans_name, - struct response_record *n, struct subnet_record *d) + struct response_record *n, struct subnet_record *d) { /* issue another state: this time to do a name status check */ enum state_type cmd = (n->state == NAME_QUERY_DOM_SRV_CHK) ? - NAME_STATUS_DOM_SRV_CHK : NAME_STATUS_SRV_CHK; + NAME_STATUS_DOM_SRV_CHK : NAME_STATUS_SRV_CHK; /* 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,NULL,NULL, + False,False,n->send_ip,n->reply.ip); } @@ -208,8 +185,8 @@ static void response_server_check(struct nmb_name *ans_name, add all the names it finds into the namelist. ****************************************************************************/ static BOOL interpret_node_status(struct subnet_record *d, - char *p, struct nmb_name *name,int t, - char *serv_name, struct in_addr ip, BOOL bcast) + char *p, struct nmb_name *name,int t, + char *serv_name, struct in_addr ip, BOOL bcast) { int level = t==0x20 ? 4 : 0; int numnames = CVAL(p,0); @@ -252,44 +229,44 @@ static BOOL interpret_node_status(struct subnet_record *d, /* might as well update our namelist while we're at it */ if (add) - { - struct in_addr nameip; - enum name_source src; - - if (ismyip(ip)) { - nameip = ipzero; - src = SELF; - } else { - nameip = ip; - src = STATUS_QUERY; - } - add_netbios_entry(d,qname,type,nb_flags,2*60*60,src,nameip,True,bcast); - } + { + struct in_addr nameip; + enum name_source src; + + if (ismyip(ip)) { + nameip = ipzero; + src = SELF; + } else { + nameip = ip; + src = STATUS_QUERY; + } + add_netbios_entry(d,qname,type,nb_flags,2*60*60,src,nameip,True,bcast); + } /* we want the server name */ if (serv_name && !*serv_name && !group && t == 0) - { - StrnCpy(serv_name,qname,15); - serv_name[15] = 0; - } + { + StrnCpy(serv_name,qname,15); + serv_name[15] = 0; + } /* looking for a name and type? */ if (name && !found && (t == type)) - { - /* take a guess at some of the name types we're going to ask for. - evaluate whether they are group names or no... */ - if (((t == 0x1b || t == 0x1d ) && !group) || - ((t == 0x20 || t == 0x1c || t == 0x1e) && group)) - { - found = True; - make_nmb_name(name,qname,type,scope); - } - } + { + /* take a guess at some of the name types we're going to ask for. + evaluate whether they are group names or no... */ + if (((t == 0x1b || t == 0x1d ) && !group) || + ((t == 0x20 || t == 0x1c || t == 0x1e) && group)) + { + found = True; + make_nmb_name(name,qname,type,scope); + } + } DEBUG(level,("\t%s(0x%x)\t%s\n",qname,type,flags)); } DEBUG(level,("num_good_sends=%d num_good_receives=%d\n", - IVAL(p,20),IVAL(p,24))); + IVAL(p,20),IVAL(p,24))); return found; } @@ -299,28 +276,26 @@ 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, - struct response_record *n, struct subnet_record *d) + char *data, BOOL bcast, + struct response_record *n, struct subnet_record *d) { - /* NMB_STATUS arrives: contains workgroup name and server name required. + /* NMB_STATUS arrives: contains workgroup name and server name required. amongst other things. */ - struct nmb_name name; - fstring serv_name; - - if (interpret_node_status(d,nmb->answers->rdata, - &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); - } - } - else - { - DEBUG(1,("No 0x1d name type in interpret_node_status()\n")); - } + struct nmb_name name; + fstring serv_name; + + 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); + } + } + else + { + DEBUG(1,("No 0x1d name type in interpret_node_status()\n")); + } } @@ -328,79 +303,74 @@ 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, - struct nmb_name *ans_name, - struct response_record *n, struct subnet_record *d) +static void response_name_query_register(struct nmb_ip *data, + struct nmb_name *ans_name, + struct response_record *n, struct subnet_record *d) { - struct in_addr register_ip; - BOOL new_owner; - - DEBUG(4, ("Name query at %s ip %s - ", - namestr(&n->name), inet_ntoa(n->send_ip))); - - if (!name_equal(&n->name, ans_name)) - { - /* someone gave us the wrong name as a reply. oops. */ - /* XXXX should say to them 'oi! release that name!' */ - - DEBUG(4,("unexpected name received: %s\n", namestr(ans_name))); - return; - } - - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - /* we had sent out a name query to the current owner - of a name because someone else wanted it. now they - have responded saying that they still want the name, - so the other host can't have it. - */ - - /* 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) - { - /* 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)); - return; - } - - if (!ip_equal(n->send_ip, found_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))); - return; - } - - DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip))); - - /* fine: now tell the other host they can't have the name */ - register_ip = n->send_ip; - new_owner = False; - } - else - { - DEBUG(4, (" NEGATIVE RESPONSE!\n")); - - /* the owner didn't want the name: the other host can have it */ - register_ip = n->reply_to_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); + struct in_addr register_ip; + BOOL new_owner; + + DEBUG(4, ("Name query at %s ip %s - ", + namestr(&n->name), inet_ntoa(n->send_ip))); + + if (!name_equal(&n->name, ans_name)) + { + /* someone gave us the wrong name as a reply. oops. */ + /* XXXX should say to them 'oi! release that name!' */ + + DEBUG(4,("unexpected name received: %s\n", namestr(ans_name))); + return; + } + + if (data) + { + /* we had sent out a name query to the current owner + of a name because someone else wanted it. now they + have responded saying that they still want the name, + so the other host can't have it. + */ + + /* first check all the details are correct */ + + 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->reply.nb_flags)); + DEBUG(4,("unexpected nb_flags: %d\n", data->nb_flags)); + return; + } + + 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(data->ip))); + return; + } + + 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; + new_owner = False; + } + else + { + DEBUG(4, (" NEGATIVE RESPONSE!\n")); + + /* the owner didn't want the name: the other host can have it */ + 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->reply.nb_flags, GET_TTL(0), register_ip, + new_owner, n->reply.ip); } @@ -408,73 +378,68 @@ 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, - struct nmb_name *ans_name, BOOL bcast, - struct response_record *n, struct subnet_record *d) +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) { - DEBUG(4, ("Name query at %s ip %s - ", - namestr(&n->name), inet_ntoa(n->send_ip))); - - if (!name_equal(&n->name, ans_name)) - { - /* someone gave us the wrong name as a reply. oops. */ - DEBUG(4,("unexpected name received: %s\n", namestr(ans_name))); - return; - } - - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - int nb_flags = nmb->answers->rdata[0]; - struct in_addr found_ip; - - putip((char*)&found_ip,&nmb->answers->rdata[2]); - - if (!ip_equal(n->send_ip, found_ip)) - { - /* someone gave us the wrong ip as a reply. oops. */ - DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip))); - DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip))); - return; - } - - DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip))); - - if (n->state == NAME_QUERY_SYNC_LOCAL || - n->state == NAME_QUERY_SYNC_REMOTE) - { - struct work_record *work = NULL; - if ((work = find_workgroupstruct(d, ans_name->name, False))) - { - BOOL local_list_only = n->state == NAME_QUERY_SYNC_LOCAL; - - /* the server is there: sync quick before it (possibly) dies! */ - sync_browse_lists(d, work, ans_name->name, ans_name->name_type, - found_ip, local_list_only); - } - } - else - { - /* update our netbios name list (re-register it if necessary) */ - add_netbios_entry(d, ans_name->name, ans_name->name_type, - nb_flags,GET_TTL(0),REGISTER, - found_ip,False,!bcast); - } - } - else - { - DEBUG(4, (" NEGATIVE RESPONSE!\n")); - - if (n->state == NAME_QUERY_CONFIRM) - { - /* XXXX remove_netbios_entry()? */ - /* lots of things we ought to do, here. if we get here, - then we're in a mess: our name database doesn't match - reality. sort it out + DEBUG(4, ("Name query at %s ip %s - ", + namestr(&n->name), inet_ntoa(n->send_ip))); + + if (!name_equal(&n->name, ans_name)) + { + /* someone gave us the wrong name as a reply. oops. */ + DEBUG(4,("unexpected name received: %s\n", namestr(ans_name))); + return; + } + + if (data) + { + 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(data->ip))); + return; + } + + DEBUG(4, (" OK: %s\n", inet_ntoa(data->ip))); + + if (n->state == NAME_QUERY_SYNC_LOCAL || + n->state == NAME_QUERY_SYNC_REMOTE) + { + struct work_record *work = NULL; + if ((work = find_workgroupstruct(d, ans_name->name, False))) + { + BOOL local_list_only = n->state == NAME_QUERY_SYNC_LOCAL; + + /* the server is there: sync quick before it (possibly) dies! */ + sync_browse_lists(d, work, ans_name->name, ans_name->name_type, + 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, + data->nb_flags,GET_TTL(0),REGISTER, + data->ip,False,!bcast); + } + } + else + { + DEBUG(4, (" NEGATIVE RESPONSE!\n")); + + if (n->state == NAME_QUERY_CONFIRM) + { + /* XXXX remove_netbios_entry()? */ + /* lots of things we ought to do, here. if we get here, + then we're in a mess: our name database doesn't match + reality. sort it out */ - remove_netbios_name(d,n->name.name, n->name.name_type, - REGISTER,n->send_ip); - } - } + remove_netbios_name(d,n->name.name, n->name.name_type, + REGISTER,n->send_ip); + } + } } @@ -486,9 +451,9 @@ static void debug_rr_type(int rr_type) switch (rr_type) { case NMB_STATUS: DEBUG(3,("Name status ")); break; - case NMB_QUERY : DEBUG(3,("Name query ")); break; - case NMB_REG : DEBUG(3,("Name registration ")); break; - case NMB_REL : DEBUG(3,("Name release ")); break; + case NMB_QUERY : DEBUG(3,("Name query ")); break; + case NMB_REG : DEBUG(3,("Name registration ")); break; + case NMB_REL : DEBUG(3,("Name release ")); break; default : DEBUG(1,("wrong response packet type received")); break; } } @@ -528,7 +493,7 @@ void debug_state_type(int state) (responses for certain types of operations are only expected from one host) ****************************************************************************/ static BOOL response_problem_check(struct response_record *n, - struct nmb_packet *nmb, char *qname) + struct nmb_packet *nmb, char *qname) { switch (nmb->answers->rr_type) { @@ -556,21 +521,21 @@ static BOOL response_problem_check(struct response_record *n, { if (n->num_msgs > 1) { - if (nmb->header.rcode == 0 && nmb->answers->rdata) - { - int nb_flags = nmb->answers->rdata[0]; - - if ((!NAME_GROUP(nb_flags))) - { - /* oh dear. more than one person responded to a unique name. - there is either a network problem, a configuration problem - or a server is mis-behaving */ - - /* XXXX mark the name as in conflict, and then let the - person who just responded know that they must also mark it - as in conflict, and therefore must NOT use it. + if (nmb->header.rcode == 0 && nmb->answers->rdata) + { + int nb_flags = nmb->answers->rdata[0]; + + if ((!NAME_GROUP(nb_flags))) + { + /* oh dear. more than one person responded to a unique name. + there is either a network problem, a configuration problem + or a server is mis-behaving */ + + /* XXXX mark the name as in conflict, and then let the + person who just responded know that they must also mark it + as in conflict, and therefore must NOT use it. see rfc1001.txt 15.1.3.5 */ - + /* this may cause problems for some early versions of nmbd */ switch (n->state) @@ -580,35 +545,35 @@ static BOOL response_problem_check(struct response_record *n, /* query for ^1^2__MSBROWSE__^2^1 expect lots of responses */ return False; } - case NAME_QUERY_ANNOUNCE_HOST: - case NAME_QUERY_DOM_SRV_CHK: + case NAME_QUERY_ANNOUNCE_HOST: + case NAME_QUERY_DOM_SRV_CHK: case NAME_QUERY_SRV_CHK: case NAME_QUERY_MST_CHK: { - if (!strequal(qname,n->name.name)) - { - /* one subnet, one master browser per workgroup */ - /* XXXX force an election? */ - - DEBUG(3,("more than one master browser replied!\n")); - return True; - } + if (!strequal(qname,n->name.name)) + { + /* one subnet, one master browser per workgroup */ + /* XXXX force an election? */ + + DEBUG(3,("more than one master browser replied!\n")); + return True; + } break; } default: break; } DEBUG(3,("Unique Name conflict detected!\n")); - return True; - } - } - else - { + return True; + } + } + else + { /* we have received a negative reply, having already received at least one response (pos/neg). something's really wrong! */ - DEBUG(3,("wierd name query problem detected!\n")); - return True; - } + DEBUG(3,("wierd name query problem detected!\n")); + return True; + } } } } @@ -619,27 +584,30 @@ static BOOL response_problem_check(struct response_record *n, check that the response received is compatible with the response record ****************************************************************************/ static BOOL response_compatible(struct response_record *n, - struct nmb_packet *nmb) + struct nmb_packet *nmb) { switch (n->state) { case NAME_RELEASE: { - if (nmb->answers->rr_type != NMB_REL) - { - DEBUG(1,("Name release reply has wrong answer rr_type\n")); - return False; - } + if (nmb->answers->rr_type != NMB_REL) + { + DEBUG(1,("Name release reply has wrong answer rr_type\n")); + return False; + } break; } case NAME_REGISTER: { - if (nmb->answers->rr_type != NMB_REG) - { - DEBUG(1,("Name register reply has wrong answer rr_type\n")); - return False; - } +/* 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; } @@ -653,29 +621,29 @@ static BOOL response_compatible(struct response_record *n, case NAME_QUERY_FIND_MST: case NAME_QUERY_MST_CHK: { - if (nmb->answers->rr_type != NMB_QUERY) - { - DEBUG(1,("Name query reply has wrong answer rr_type\n")); - return False; - } - break; + if (nmb->answers->rr_type != NMB_QUERY) + { + DEBUG(1,("Name query reply has wrong answer rr_type\n")); + return False; + } + break; } case NAME_STATUS_DOM_SRV_CHK: case NAME_STATUS_SRV_CHK: { - if (nmb->answers->rr_type != NMB_STATUS) - { - DEBUG(1,("Name status reply has wrong answer rr_type\n")); - return False; - } - break; + if (nmb->answers->rr_type != NMB_STATUS) + { + DEBUG(1,("Name status reply has wrong answer rr_type\n")); + return False; + } + break; } default: { - DEBUG(1,("unknown state type received in response_netbios_packet\n")); - return False; + DEBUG(1,("unknown state type received in response_netbios_packet\n")); + return False; } } return True; @@ -685,27 +653,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->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; } @@ -713,44 +716,66 @@ static void response_process(struct subnet_record *d, struct packet_struct *p, case NAME_QUERY_SRV_CHK: case NAME_QUERY_FIND_MST: { - response_server_check(ans_name, n, d); - break; + response_server_check(ans_name, n, d); + break; } case NAME_STATUS_DOM_SRV_CHK: case NAME_STATUS_SRV_CHK: { - response_name_status_check(p->ip, nmb, bcast, n, d); - break; + response_name_status_check(ip,nmb_data,bcast,n,d); + break; } case NAME_QUERY_ANNOUNCE_HOST: { - response_announce_host(ans_name, nmb, n, d); - break; + 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; } case NAME_QUERY_CONFIRM: case NAME_QUERY_SYNC_LOCAL: case NAME_QUERY_SYNC_REMOTE: { - response_name_query_sync(nmb, ans_name, bcast, n, d); - break; + 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: { - /* no action required here. it's when NO responses are received - that we need to do something. see expire_name_query_entries() */ - - DEBUG(4, ("Master browser exists for %s at %s (just checking!)\n", - namestr(&n->name), inet_ntoa(n->send_ip))); - break; + /* no action required here. it's when NO responses are received + that we need to do something. see expire_name_query_entries() */ + + DEBUG(4, ("Master browser exists for %s at %s (just checking!)\n", + namestr(&n->name), inet_ntoa(n->send_ip))); + break; } default: { - DEBUG(1,("unknown state type received in response_netbios_packet\n")); - break; + DEBUG(1,("unknown state type received in response_netbios_packet\n")); + break; } } } @@ -780,7 +805,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))); @@ -792,13 +819,13 @@ void response_netbios_packet(struct packet_struct *p) { /* hm. the packet received was a response, but with no answer. wierd! */ DEBUG(2,("NMB packet response from %s (bcast=%s) - UNKNOWN\n", - inet_ntoa(p->ip), BOOLSTR(bcast))); + inet_ntoa(p->ip), BOOLSTR(bcast))); return; } ans_name = &nmb->answers->rr_name; DEBUG(3,("response for %s from %s (bcast=%s)\n", - namestr(ans_name), inet_ntoa(p->ip), BOOLSTR(bcast))); + namestr(ans_name), inet_ntoa(p->ip), BOOLSTR(bcast))); debug_rr_type(nmb->answers->rr_type); @@ -816,7 +843,11 @@ 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); } diff --git a/source/namework.c b/source/namework.c index 0380c1460af..b341fcfdc86 100644 --- a/source/namework.c +++ b/source/namework.c @@ -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" @@ -36,15 +39,11 @@ 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; @@ -64,7 +63,7 @@ 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; @@ -77,10 +76,10 @@ void reset_server(char *name, int state, struct in_addr ip) p += 2; DEBUG(2,("sending reset to %s %s of state %d\n", - name,inet_ntoa(ip),state)); + 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)); } @@ -99,47 +98,47 @@ void tell_become_backup(void) { struct work_record *work; for (work = d->workgrouplist; work; work = work->next) - { - struct server_record *s; - int num_servers = 0; - int num_backups = 0; - - for (s = work->serverlist; s; s = s->next) - { - if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; - - num_servers++; - - if (strequal(myname, s->serv.name)) continue; - - if (s->serv.type & SV_TYPE_BACKUP_BROWSER) { - num_backups++; - continue; - } - - if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue; - - if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue; - - DEBUG(3,("num servers: %d num backups: %d\n", - num_servers, num_backups)); - - /* make first server a backup server. thereafter make every - tenth server a backup server */ - if (num_backups != 0 && (num_servers+9) / num_backups > 10) - { - continue; - } - - DEBUG(2,("sending become backup to %s %s for %s\n", - s->serv.name, inet_ntoa(d->bcast_ip), - work->work_group)); - - /* type 11 request from MYNAME(20) to WG(1e) for SERVER */ - do_announce_request(s->serv.name, work->work_group, - ANN_BecomeBackup, 0x20, 0x1e, d->bcast_ip); - } - } + { + struct server_record *s; + int num_servers = 0; + int num_backups = 0; + + for (s = work->serverlist; s; s = s->next) + { + if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; + + num_servers++; + + if (strequal(conf_browsing_alias(work->token), s->serv.name)) continue; + + if (s->serv.type & SV_TYPE_BACKUP_BROWSER) { + num_backups++; + continue; + } + + if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue; + + if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue; + + DEBUG(3,("num servers: %d num backups: %d\n", + num_servers, num_backups)); + + /* make first server a backup server. thereafter make every + tenth server a backup server */ + if (num_backups != 0 && (num_servers+9) / num_backups > 10) + { + continue; + } + + DEBUG(2,("sending become backup to %s %s for %s\n", + s->serv.name, inet_ntoa(d->bcast_ip), + work->work_group)); + + /* type 11 request from 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 +149,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); } @@ -197,8 +211,8 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf) DEBUG(4,("Announce(%d) %s(%x)",command,name,name[15])); DEBUG(4,("%s count=%d ttl=%d OS=(%d,%d) type=%08x sig=%4x %4x comment=%s\n", - namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor, - servertype,browse_type,browse_sig,comment)); + namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor, + servertype,browse_type,browse_sig,comment)); name[15] = 0; @@ -213,7 +227,7 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf) dgram->dest_name.name_type != 0x1)) { DEBUG(0,("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n", - command, inet_ntoa(ip), namestr(&dgram->dest_name))); + command, inet_ntoa(ip), namestr(&dgram->dest_name))); return; } @@ -265,7 +279,7 @@ static void process_announce(struct packet_struct *p,uint16 command,char *buf) if (command == ANN_LocalMasterAnnouncement) { add_browser_entry(serv_name,dgram->dest_name.name_type, - work->work_group,30,ip,True); + work->work_group,30,ip,True); } } @@ -278,26 +292,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; - - for (work = mydomain->workgrouplist; work; work = work->next) + token = conf_alias_to_token(to_name); + + if (token == -1) { - if (AM_MASTER(work)) - { - /* merge browse lists with them */ - add_browser_entry(name,0x1b, work->work_group,30,ip,True); - } + 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_name,30,ip,True); } /******************************************************************* @@ -322,8 +350,8 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf) char *buf1; DEBUG(3,("Receive Backup ack for %s from %s total=%d info=%d\n", - namestr(&dgram->dest_name), inet_ntoa(ip), - count, info)); + namestr(&dgram->dest_name), inet_ntoa(ip), + count, info)); if (same_context(dgram)) return; @@ -336,44 +364,44 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf) struct subnet_record *d; DEBUG(4,("Searching for backup browser %s at %s...\n", - buf1, inet_ntoa(ip))); + buf1, inet_ntoa(ip))); /* XXXX assume name is a DNS name NOT a netbios name. a more complete - approach is to use reply_name_query functionality to find the name */ + approach is to use reply_name_query functionality to find the name */ back_ip = *interpret_addr2(buf1); if (zero_ip(back_ip)) - { - DEBUG(4,("Failed to find backup browser server using DNS\n")); - continue; - } + { + DEBUG(4,("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; + continue; if ((d = find_subnet(back_ip))) - { - struct subnet_record *d1; - for (d1 = subnetlist; d1; d1 = d1->next) - { - struct work_record *work; - for (work = d1->workgrouplist; work; work = work->next) - { - if (work->token == 0 /* token */) - { - queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK, - work->work_group,0x1d, + { + struct subnet_record *d1; + for (d1 = subnetlist; d1; d1 = d1->next) + { + struct work_record *work; + for (work = d1->workgrouplist; work; work = work->next) + { + if (work->token == 0 /* token */) + { + queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK, + work->token,work->work_group,0x1d, 0,0,0,NULL,NULL, - False,False,back_ip,back_ip); - return; - } - } - } - } + False,False,back_ip,back_ip); + return; + } + } + } + } } } @@ -381,9 +409,9 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf) /**************************************************************************** send a backup list response. **************************************************************************/ -static void send_backup_list(char *work_name, struct nmb_name *src_name, - int token, uint32 info, - int name_type, struct in_addr ip) +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) { char outbuf[1024]; char *p, *countptr, *nameptr; @@ -391,8 +419,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,62 +452,51 @@ 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; + struct server_record *s; - for (work = d->workgrouplist; work; work = work->next) - { - struct server_record *s; - - if (!strequal(work->work_group, work_name)) continue; - - for (s = work->serverlist; s; s = s->next) - { - BOOL found = False; - char *n; - - if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; - - for (n = nameptr; n < p; n = skip_string(n, 1)) - { - if (strequal(n, s->serv.name)) found = True; - } - - if (found) continue; /* exclude names already added */ - - /* workgroup request: include all backup browsers in the list */ - /* domain request: include all domain members in the list */ - - if ((name_type == 0x1d && (s->serv.type & MASTER_TYPE)) || - (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE))) - { - DEBUG(4, ("%s ", s->serv.name)); - - count++; - strcpy(p,s->serv.name); - strupper(p); - p = skip_string(p,1); - } - } - } + for (s = work->serverlist; s; s = s->next) + { + BOOL found = False; + char *n; + + if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue; + + for (n = nameptr; n < p; n = skip_string(n, 1)) + { + if (strequal(n, s->serv.name)) found = True; + } + + if (found) continue; /* exclude names already added */ + + /* workgroup request: include all backup browsers in the list */ + /* domain request: include all domain members in the list */ + + if ((name_type == 0x1d && (s->serv.type & MASTER_TYPE)) || + (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE))) + { + DEBUG(4, ("%s ", s->serv.name)); + + count++; + strcpy(p,s->serv.name); + strupper(p); + p = skip_string(p,1); + } } - #endif - count++; - strcpy(p,myname); - strupper(p); - p = skip_string(p,1); + count++; + strcpy(p,conf_browsing_alias(work->token)); + strupper(p); + p = skip_string(p,1); if (count == 0) - { + { DEBUG(4, ("none\n")); - } + } else - { + { DEBUG(4, (" - count %d\n", count)); - } + } CVAL(countptr, 0) = count; @@ -488,7 +505,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)); } @@ -519,24 +536,24 @@ static void process_send_backup_list(struct packet_struct *p,char *buf) if (name_type != 0x1b && name_type != 0x1d) { DEBUG(0,("backup request to wrong type %d from %s\n", - name_type,inet_ntoa(ip))); + name_type,inet_ntoa(ip))); return; } for (d = subnetlist; d; d = d->next) { for (work = d->workgrouplist; work; work = work->next) - { - if (strequal(work->work_group, dgram->dest_name.name)) - { - DEBUG(2,("sending backup list to %s %s id=%x\n", - namestr(&dgram->dest_name),inet_ntoa(ip),info)); - - send_backup_list(work->work_group,&dgram->source_name, - token,info,name_type,ip); - return; - } - } + { + if (strequal(work->work_group, dgram->dest_name.name)) + { + DEBUG(2,("sending backup list to %s %s id=%x\n", + namestr(&dgram->dest_name),inet_ntoa(ip),info)); + + send_backup_list(work,&dgram->source_name, + token,info,name_type,ip); + return; + } + } } } @@ -556,23 +573,23 @@ static void process_reset_browser(struct packet_struct *p,char *buf) int state = CVAL(buf,0); DEBUG(1,("received diagnostic browser reset request to %s state=0x%X\n", - namestr(&dgram->dest_name), state)); + namestr(&dgram->dest_name), state)); /* stop being a master but still deal with being a backup browser */ if (state & 0x1) { struct subnet_record *d; for (d = subnetlist; d; d = d->next) - { - struct work_record *work; - for (work = d->workgrouplist; work; work = work->next) - { - if (AM_MASTER(work)) - { - become_nonmaster(d,work,SV_TYPE_DOMAIN_MASTER|SV_TYPE_MASTER_BROWSER); - } - } - } + { + struct work_record *work; + for (work = d->workgrouplist; work; work = work->next) + { + if (AM_MASTER(work)) + { + become_nonmaster(d,work,SV_TYPE_DOMAIN_MASTER|SV_TYPE_MASTER_BROWSER); + } + } + } } /* XXXX documentation inconsistency: the above description does not @@ -581,21 +598,21 @@ static void process_reset_browser(struct packet_struct *p,char *buf) /* totally delete all servers and start afresh */ if (state & 0x2) + { + struct subnet_record *d; + for (d = subnetlist; d; d = d->next) { - 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()); + struct work_record *work; + for (work=d->workgrouplist;work;work=remove_workgroup(d,work,True)); } + add_my_subnets(lp_workgroup()); + } /* stop browsing altogether. i don't think this is a good idea! */ if (state & 0x4) - { + { DEBUG(1,("ignoring request to stop being a browser. sorry!\n")); - } + } } /******************************************************************* @@ -616,9 +633,9 @@ static void process_announce_request(struct packet_struct *p,char *buf) name[15] = 0; DEBUG(3,("Announce request from %s to %s token=0x%X\n", - name,namestr(&dgram->dest_name), token)); + name,namestr(&dgram->dest_name), token)); - if (strequal(dgram->source_name.name,myname)) return; + if (strequal(dgram->source_name.name,conf_browsing_alias(work->token))) return; /* XXXX BUG or FEATURE?: need to ensure that we are a member of this workgroup before announcing, particularly as we only @@ -630,20 +647,19 @@ static void process_announce_request(struct packet_struct *p,char *buf) 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)) - { - work->needannounce = True; - } + { + work->needannounce = True; } + } } - /**************************************************************************** process a browse frame ****************************************************************************/ @@ -657,27 +673,27 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len) case ANN_LocalMasterAnnouncement: { debug_browse_data(buf, len); - process_announce(p,command,buf+1); - break; + process_announce(p,command,buf+1); + break; } case ANN_AnnouncementRequest: { - process_announce_request(p,buf+1); - break; + process_announce_request(p,buf+1); + break; } case ANN_Election: { - process_election(p,buf+1); - break; + process_election(p,buf+1); + break; } case ANN_GetBackupListReq: { debug_browse_data(buf, len); - process_send_backup_list(p,buf+1); - break; + process_send_backup_list(p,buf+1); + break; } case ANN_GetBackupListResp: @@ -689,22 +705,22 @@ void process_browse_packet(struct packet_struct *p,char *buf,int len) case ANN_ResetBrowserState: { - process_reset_browser(p, buf+1); - break; + process_reset_browser(p, buf+1); + break; } case ANN_MasterAnnouncement: { - process_master_announce(p,buf+1); - break; + process_master_announce(p,buf+1); + break; } default: { - struct dgram_packet *dgram = &p->packet.dgram; - DEBUG(4,("ignoring browse packet %d from %s %s to %s\n", - command, namestr(&dgram->source_name), - inet_ntoa(p->ip), namestr(&dgram->dest_name))); + struct dgram_packet *dgram = &p->packet.dgram; + DEBUG(4,("ignoring browse packet %d from %s %s to %s\n", + command, namestr(&dgram->source_name), + inet_ntoa(p->ip), namestr(&dgram->dest_name))); } } } diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c index 5b3fd19491d..4a3d139fdad 100644 --- a/source/nmbd/nmbd.c +++ b/source/nmbd/nmbd.c @@ -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); } @@ -187,10 +191,10 @@ BOOL reload_services(BOOL test) pstring fname; strcpy(fname,lp_configfile()); if (file_exist(fname,NULL) && !strcsequal(fname,servicesf)) - { - strcpy(servicesf,fname); - test = False; - } + { + strcpy(servicesf,fname); + test = False; + } } if (test && !lp_file_list_changed()) @@ -251,32 +255,32 @@ static void load_hosts_file(char *fname) if (count <= 0) continue; if (count > 0 && count < 2) { - DEBUG(0,("Ill formed hosts line [%s]\n",line)); - continue; + DEBUG(0,("Ill formed hosts line [%s]\n",line)); + continue; } if (count >= 4) { - DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname)); - continue; + DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname)); + continue; } DEBUG(4, ("lmhost entry: %s %s %s\n", ip, name, flags)); if (strchr(flags,'G') || strchr(flags,'S')) { - DEBUG(0,("group flag in %s ignored (obsolete)\n",fname)); - continue; + DEBUG(0,("group flag in %s ignored (obsolete)\n",fname)); + continue; } if (strchr(flags,'M')) { - source = SELF; - strcpy(myname,name); + source = SELF; + strcpy(myname,name); } ipaddr = *interpret_addr2(ip); d = find_subnet(ipaddr); if (d) { - add_netbios_entry(d,name,0x00,NB_ACTIVE,0,source,ipaddr,True,True); - add_netbios_entry(d,name,0x20,NB_ACTIVE,0,source,ipaddr,True,True); + add_netbios_entry(d,name,0x00,NB_ACTIVE,0,source,ipaddr,True,True); + add_netbios_entry(d,name,0x20,NB_ACTIVE,0,source,ipaddr,True,True); } } @@ -292,8 +296,7 @@ static void process(void) BOOL run_election; while (True) - { - time_t t = time(NULL); + { run_election = check_elections(); listen_for_packets(run_election); @@ -310,12 +313,11 @@ static void process(void) expire_names_and_servers(); expire_netbios_response_entries(); - refresh_my_names(t); write_browse_list(); do_browser_lists(); check_master_browser(); - } + } } @@ -435,50 +437,50 @@ static void usage(char *pname) while ((opt = getopt(argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:")) != EOF) { switch (opt) - { - case 's': - strcpy(servicesf,optarg); - break; - case 'N': - case 'B': - case 'I': - case 'C': - case 'G': - DEBUG(0,("Obsolete option '%c' used\n",opt)); - break; - case 'H': - strcpy(host_file,optarg); - break; - case 'n': - strcpy(myname,optarg); - strupper(myname); - break; - case 'l': - sprintf(debugf,"%s.nmb",optarg); - break; - case 'i': - strcpy(scope,optarg); - strupper(scope); - break; - case 'D': - is_daemon = True; - break; - case 'd': - DEBUGLEVEL = atoi(optarg); - break; - case 'p': - port = atoi(optarg); - break; - case 'h': - usage(argv[0]); - exit(0); - break; - default: - if (!is_a_socket(0)) { - usage(argv[0]); - } - break; - } + { + case 's': + strcpy(servicesf,optarg); + break; + case 'N': + case 'B': + case 'I': + case 'C': + case 'G': + DEBUG(0,("Obsolete option '%c' used\n",opt)); + break; + case 'H': + strcpy(host_file,optarg); + break; + case 'n': + strcpy(myname,optarg); + strupper(myname); + break; + case 'l': + sprintf(debugf,"%s.nmb",optarg); + break; + case 'i': + strcpy(scope,optarg); + strupper(scope); + break; + case 'D': + is_daemon = True; + break; + case 'd': + DEBUGLEVEL = atoi(optarg); + break; + case 'p': + port = atoi(optarg); + break; + case 'h': + usage(argv[0]); + exit(0); + break; + default: + if (!is_a_socket(0)) { + usage(argv[0]); + } + break; + } } DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION)); @@ -487,10 +489,18 @@ static void usage(char *pname) get_myname(myhostname,NULL); if (!reload_services(False)) - return(-1); - + return(-1); + 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(); diff --git a/source/nmbsync.c b/source/nmbsync.c index 2efb364bcae..5a4d93f1a00 100644 --- a/source/nmbsync.c +++ b/source/nmbsync.c @@ -48,7 +48,7 @@ fudge for getpass function ****************************************************************************/ char *getsmbpass(char *pass) { - return "dummy"; /* return anything: it should be ignored anyway */ + return "dummy"; /* return anything: it should be ignored anyway */ } /**************************************************************************** @@ -84,43 +84,46 @@ static BOOL add_info(struct subnet_record *d, struct work_record *work, int serv p = skip_string(p,1); if (cli_call_api(PTR_DIFF(p,param),0, 8,10000, - &rprcnt,&rdrcnt, param,NULL, - &rparam,&rdata)) + &rprcnt,&rdrcnt, param,NULL, + &rparam,&rdata)) { int res = SVAL(rparam,0); int converter=SVAL(rparam,2); int i; if (res == 0) - { - count=SVAL(rparam,4); - p = rdata; - - for (i = 0;i < count;i++, p += 26) - { - char *sname = p; - uint32 stype = IVAL(p,18); - int comment_offset = IVAL(p,22) & 0xFFFF; - char *cmnt = comment_offset?(rdata+comment_offset-converter):""; - - struct work_record *w = work; - - DEBUG(4, ("\t%-16.16s %08x %s\n", sname, stype, cmnt)); - - if (stype & SV_TYPE_DOMAIN_ENUM) - { - /* creates workgroup on remote subnet */ - if ((w = find_workgroupstruct(d,sname,True))) - { - announce_request(w, d->bcast_ip); - } - } - - if (w) - add_server_entry(d,w,sname,stype,lp_max_ttl(),cmnt,False); - } - } + { + count=SVAL(rparam,4); + p = rdata; + + for (i = 0;i < count;i++, p += 26) + { + char *sname = p; + uint32 stype = IVAL(p,18); + int comment_offset = IVAL(p,22) & 0xFFFF; + char *cmnt = comment_offset?(rdata+comment_offset-converter):""; + + struct work_record *w = work; + + DEBUG(4, ("\t%-16.16s %08x %s\n", sname, stype, cmnt)); + + if (stype & SV_TYPE_DOMAIN_ENUM) + { + /* creates workgroup on remote subnet */ + if ((w = find_workgroupstruct(d,sname,True))) + { + announce_request(w, d->bcast_ip); + } + } + + if (w) + { + add_server_entry(d,w,sname,stype & ~SV_TYPE_LOCAL_LIST_ONLY, + lp_max_ttl(),cmnt,False); + } + } } + } if (rparam) free(rparam); if (rdata) free(rdata); @@ -136,7 +139,7 @@ static BOOL add_info(struct subnet_record *d, struct work_record *work, int serv do a NetServerEnum and update our server and workgroup databases. ******************************************************************/ void sync_browse_lists(struct subnet_record *d, struct work_record *work, - char *name, int nm_type, struct in_addr ip, BOOL local) + char *name, int nm_type, struct in_addr ip, BOOL local) { uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0; @@ -151,7 +154,7 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work, got_pass = True; DEBUG(4,("sync browse lists with %s for %s %s\n", - work->work_group, name, inet_ntoa(ip))); + work->work_group, name, inet_ntoa(ip))); strcpy(workgroup,work->work_group); strcpy(desthost,name); @@ -170,11 +173,11 @@ void sync_browse_lists(struct subnet_record *d, struct work_record *work, if (cli_open_sockets(SMB_PORT)) { if (cli_send_login(NULL,NULL,True,True)) - { - add_info(d, work, local_type|SV_TYPE_DOMAIN_ENUM); - add_info(d, work, local_type|(SV_TYPE_ALL& + { + add_info(d, work, local_type|SV_TYPE_DOMAIN_ENUM); + add_info(d, work, local_type|(SV_TYPE_ALL& ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY))); - } + } close_sockets(); } diff --git a/source/param/loadparm.c b/source/param/loadparm.c index 87209d1bb7c..2a76ce70f77 100644 --- a/source/param/loadparm.c +++ b/source/param/loadparm.c @@ -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 *szDomainController; char *szHostsEquiv; - char *szServerString; - char *szAutoServices; - char *szPasswdProgram; - char *szPasswdChat; + char *szInterfaces; + char *szLockDir; char *szLogFile; - char *szConfigFile; - char *szSMBPasswdFile; + 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 *szValidChars; - char *szWorkGroup; - char *szDomainController; char *szUsernameMap; - char *szCharacterSet; - char *szLogonScript; - char *szSmbrun; + char *szValidChars; char *szWINSserver; - char *szInterfaces; - char *szRemoteAnnounce; - char *szSocketAddress; + 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) diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c index dd9b9661ae8..916d7e3cc49 100644 --- a/source/smbd/ipc.c +++ b/source/smbd/ipc.c @@ -983,8 +983,26 @@ 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; + char host_alias[16]; + + StrnCpy(host_alias, local_machine, 15); + work_alias = conf_alias_to_workgroup(host_alias); /* look-up */ + + DEBUG(4,("host alias: %s work_alias: %s\n", + host_alias, work_alias)); + if (work_alias) + StrnCpy(domain, work_alias, sizeof(fstring)-1); } if (lp_browse_list()) @@ -1668,9 +1686,23 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data, pstring comment; uint32 servertype=DFLT_SERVER_TYPE; + char *work_alias; + char host_alias[16]; + char domain[16]; + + StrnCpy(host_alias, local_machine, 15); + work_alias = conf_alias_to_workgroup(host_alias); /* look-up */ + + DEBUG(4,("host alias: %s work_alias: %s\n", + host_alias, work_alias)); + 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