1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

luke's first attempt at using cvs

accidentally updated the Makefile

updated the name database structure (again!). this time, there is one
name database per local interface. there is also a pseudo-interface on
ip 255.255.255.255. its purpose is to store WINS name entries. all the
local interface name databases store SELF names only. the WINS name
database stores non-special browser names.

added wins.dat file: records WINS entries in ascii format. this is reloaded
when nmbd restarts.

added repeating code for response packets. timer is in seconds only at the
moment.

updated the response queue code to deal with samba registering with a
WINS server a bit better (added more cases when a response isn't received).
tidied up the response packet processing code and expire_response_queue()
code. added cross references between response received and await-response
expired code.

added over-zealous code that checks all machines that register with samba
as a WINS server (every 10 minutes i think): to see whether they are still
alive or not (see rfc1001.txt)

bug reported by terry@ren.pc.athabascau.ca: DNSFAILed names _stay_ as
DNSFAIL, even though the machine may come back up and REGISTER.

removed update_from_reg() function. it's not necessary, and it does too much.

added code that announces on each local interface samba's ttl as zero and
servertype as zero when nmbd is kill -TERMed

first attempt at putting the first functionality of samba browsing back in
(remote subnets should have samba appear in a workgroup specified through
the lmhosts file)

lots of other miscellaneous tidying up / chopping about.
This commit is contained in:
Samba Release Account 0001-01-01 00:00:00 +00:00
parent 6d81d56f92
commit 7e8c60cfe5
14 changed files with 2379 additions and 664 deletions

View File

@ -29,8 +29,12 @@
#define NMB_QUERY 0x20
#define NMB_STATUS 0x21
#define NMB_REG 0x05
#define NMB_REL 0x06
#define NMB_REG 0x05 /* see rfc1002.txt 4.2.2,3,5,6,7,8 */
#define NMB_REG_REFRESH 0x09 /* see rfc1002.txt 4.2.4 */
#define NMB_REL 0x06 /* see rfc1002.txt 4.2.9,10,11 */
#define NMB_WAIT_ACK 0x07 /* see rfc1002.txt 4.2.17 */
/* XXXX what about all the other types?? 0x1, 0x2, 0x3, 0x4, 0x8? */
#define NB_GROUP 0x80
#define NB_PERM 0x02
@ -44,6 +48,8 @@
#define NB_FLGMSK 0x60
#define REFRESH_TIME (15*60)
#define NAME_POLL_REFRESH_TIME (5*60)
#define NAME_POLL_INTERVAL 15
#define NAME_PERMANENT(p) ((p) & NB_PERM)
#define NAME_ACTIVE(p) ((p) & NB_ACTIVE)
@ -58,7 +64,6 @@
#define MSBROWSE "\001\002__MSBROWSE__\002"
enum name_search { FIND_SELF, FIND_GLOBAL };
enum name_source {STATUS_QUERY, LMHOSTS, REGISTER, SELF, DNS, DNSFAIL};
enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3};
enum packet_type {NMB_PACKET, DGRAM_PACKET};
@ -66,13 +71,14 @@ enum cmd_type
{
NAME_STATUS_MASTER_CHECK,
NAME_STATUS_CHECK,
MASTER_SERVER_CHECK,
SERVER_CHECK,
FIND_MASTER,
CHECK_MASTER,
NAME_REGISTER,
NAME_RELEASE,
NAME_CONFIRM_QUERY
NAME_QUERY_CONFIRM,
NAME_QUERY_SYNC,
NAME_QUERY_MST_SRV_CHK,
NAME_QUERY_SRV_CHK,
NAME_QUERY_FIND_MST,
NAME_QUERY_MST_CHK
};
/* a netbios name structure */
@ -87,11 +93,15 @@ struct name_record
{
struct name_record *next;
struct name_record *prev;
struct nmb_name name;
time_t death_time;
struct in_addr ip;
int nb_flags;
enum name_source source;
struct nmb_name name; /* the netbios name */
struct in_addr ip; /* ip address of host that owns this name */
int nb_flags; /* netbios flags */
enum name_source source; /* where the name came from */
time_t death_time; /* time record must be removed (do not remove if 0) */
time_t refresh_time; /* time record should be refreshed */
};
/* browse and backup server cache for synchronising browse list */
@ -144,13 +154,63 @@ struct work_record
uint32 ElectionCriterion;
};
/* a subnet structure. it contains a list of workgroups */
/* initiated name queries recorded in this list to track any responses... */
struct response_record
{
struct response_record *next;
struct response_record *prev;
uint16 response_id;
enum cmd_type cmd_type;
int fd;
int quest_type;
struct nmb_name name;
int nb_flags;
time_t ttl;
BOOL bcast;
BOOL recurse;
struct in_addr to_ip;
int num_msgs;
time_t repeat_time;
time_t repeat_interval;
int repeat_count;
};
/* a subnet structure. it contains a list of workgroups and netbios names*/
/* note that a subnet of 255.255.255.255 contains all the WINS netbios names.
all communication from such nodes are on a non-broadcast basis: they
are point-to-point (P nodes) or mixed point-to-point and broadcast
(M nodes). M nodes use point-to-point as a preference, and will use
broadcasting for certain activities, or will resort to broadcasting as a
last resort, if the WINS server fails (users of wfwg will notice that their
machine often freezes for 30 seconds at a time intermittently, if the WINS
server is down).
B nodes will have their own, totally separate subnet record, with their
own netbios name set. these do NOT interact with other subnet records'
netbios names, INCLUDING the WINS one (with an ip "address", so called,
of 255.255.255.255)
there is a separate response list for each subnet record. in the case of
the 255.255.255.255 subnet record (WINS), the WINS server will be able to
use this to poll (infrequently!) each of its entries, to ensure that the
names are still in use.
XXXX this polling is a planned feature for a really over-cautious WINS server
*/
struct subnet_record
{
struct subnet_record *next;
struct subnet_record *prev;
struct work_record *workgrouplist;
struct work_record *workgrouplist; /* list of workgroups */
struct name_record *namelist; /* list of netbios names */
struct response_record *responselist; /* list of responses expected */
struct in_addr bcast_ip;
struct in_addr mask_ip;
@ -202,25 +262,6 @@ struct nmb_packet
};
/* initiated name queries recorded in this list to track any responses... */
struct name_response_record
{
struct name_response_record *next;
struct name_response_record *prev;
uint16 response_id;
enum cmd_type cmd_type;
int fd;
struct nmb_name name;
BOOL bcast;
BOOL recurse;
struct in_addr to_ip;
time_t start_time;
int num_msgs;
};
/* a datagram - this normally contains SMB data in the data[] array */
struct dgram_packet {
struct {

View File

@ -0,0 +1,659 @@
/* This file is automatically generated with "make proto". DO NOT EDIT */
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);
char *unix2dos_format(char *str,BOOL overwrite);
char *dos2unix_format(char *str, BOOL overwrite);
int interpret_character_set(char *str, int def);
void charset_initialise(void);
void add_char_string(char *s);
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);
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);
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);
BOOL cli_send_session_request(char *inbuf, char *outbuf);
BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setup);
void cli_send_logout(void);
BOOL cli_call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt,int *rprcnt,
int *rdrcnt, char *param,char *data, char **rparam,char **rdata);
BOOL cli_send_trans_request(char *outbuf, int trans, char *name, int fid, int flags,
char *data,char *param,uint16 *setup, int ldata,int lparam,
int lsetup,int mdata,int mparam,int msetup);
BOOL cli_open_sockets(int port);
BOOL cli_reopen_connection(char *inbuf,char *outbuf);
char *smb_errstr(char *inbuf);
int strslashcmp(const char *s1, const char *s2);
void cmd_block(void);
void cmd_tarmode(void);
void cmd_setmode(void);
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);
void init_dptrs(void);
char *dptr_path(int key);
char *dptr_wcard(int key);
BOOL dptr_set_wcard(int key, char *wcard);
BOOL dptr_set_attr(int key, uint16 attr);
uint16 dptr_attr(int key);
void dptr_close(int key);
void dptr_closecnum(int cnum);
void dptr_idlecnum(int cnum);
void dptr_closepath(char *path,int pid);
int dptr_create(int cnum,char *path, BOOL expect_close,int pid);
BOOL dptr_fill(char *buf1,unsigned int key);
BOOL dptr_zero(char *buf);
void *dptr_fetch(char *buf,int *num);
void *dptr_fetch_lanman2(char *params,int dptr_num);
BOOL dir_check_ftype(int cnum,int mode,struct stat *st,int dirtype);
BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mode,time_t *date,BOOL check_descend);
void *OpenDir(char *name);
void CloseDir(void *p);
char *ReadDirName(void *p);
BOOL SeekDir(void *p,int pos);
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);
void fault_setup(void (*fn)());
char *getsmbpass(char *prompt) ;
void load_interfaces(void);
void add_subnet_interfaces(void);
void iface_set_default(char *ip,char *bcast,char *nmask);
BOOL ismyip(struct in_addr ip);
BOOL ismybcast(struct in_addr bcast);
int iface_count(void);
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);
int reply_trans(char *inbuf,char *outbuf);
int interpret_coding_system(char *str, int def);
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_printcapname(void);
char *lp_lockdir(void);
char *lp_rootdir(void);
char *lp_defaultservice(void);
char *lp_msg_command(void);
char *lp_dfree_command(void);
char *lp_hosts_equiv(void);
char *lp_auto_services(void);
char *lp_passwd_program(void);
char *lp_passwd_chat(void);
char *lp_passwordserver(void);
char *lp_workgroup(void);
char *lp_domain_controller(void);
char *lp_username_map(void);
char *lp_character_set(void);
char *lp_logon_script(void);
char *lp_wins_server(void);
char *lp_interfaces(void);
char *lp_remote_interfaces(void);
BOOL lp_wins_support(void);
BOOL lp_wins_proxy(void);
BOOL lp_domain_master(void);
BOOL lp_domain_logons(void);
BOOL lp_preferred_master(void);
BOOL lp_load_printers(void);
BOOL lp_use_rhosts(void);
BOOL lp_getwdcache(void);
BOOL lp_readprediction(void);
BOOL lp_readbmpx(void);
BOOL lp_readraw(void);
BOOL lp_writeraw(void);
BOOL lp_null_passwords(void);
BOOL lp_strip_dot(void);
BOOL lp_encrypted_passwords(void);
BOOL lp_syslog_only(void);
BOOL lp_browse_list(void);
int lp_os_level(void);
int lp_max_ttl(void);
int lp_max_log_size(void);
int lp_mangledstack(void);
int lp_maxxmit(void);
int lp_maxmux(void);
int lp_maxpacket(void);
int lp_keepalive(void);
int lp_passwordlevel(void);
int lp_readsize(void);
int lp_deadtime(void);
int lp_maxprotocol(void);
int lp_security(void);
int lp_printing(void);
int lp_maxdisksize(void);
int lp_lpqcachetime(void);
int lp_syslog(void);
char *lp_preexec(int );
char *lp_postexec(int );
char *lp_rootpreexec(int );
char *lp_rootpostexec(int );
char *lp_servicename(int );
char *lp_pathname(int );
char *lp_dontdescend(int );
char *lp_username(int );
char *lp_guestaccount(int );
char *lp_invalid_users(int );
char *lp_valid_users(int );
char *lp_admin_users(int );
char *lp_printcommand(int );
char *lp_lpqcommand(int );
char *lp_lprmcommand(int );
char *lp_lppausecommand(int );
char *lp_lpresumecommand(int );
char *lp_printername(int );
char *lp_hostsallow(int );
char *lp_hostsdeny(int );
char *lp_magicscript(int );
char *lp_magicoutput(int );
char *lp_comment(int );
char *lp_force_user(int );
char *lp_force_group(int );
char *lp_readlist(int );
char *lp_writelist(int );
char *lp_volume(int );
char *lp_mangled_map(int );
BOOL lp_alternate_permissions(int );
BOOL lp_revalidate(int );
BOOL lp_casesensitive(int );
BOOL lp_preservecase(int );
BOOL lp_shortpreservecase(int );
BOOL lp_casemangle(int );
BOOL lp_status(int );
BOOL lp_hide_dot_files(int );
BOOL lp_browseable(int );
BOOL lp_readonly(int );
BOOL lp_no_set_dir(int );
BOOL lp_guest_ok(int );
BOOL lp_guest_only(int );
BOOL lp_print_ok(int );
BOOL lp_postscript(int );
BOOL lp_map_hidden(int );
BOOL lp_map_archive(int );
BOOL lp_locking(int );
BOOL lp_strict_locking(int );
BOOL lp_share_modes(int );
BOOL lp_onlyuser(int );
BOOL lp_manglednames(int );
BOOL lp_widelinks(int );
BOOL lp_syncalways(int );
BOOL lp_map_system(int );
BOOL lp_delete_readonly(int );
int lp_create_mode(int );
int lp_max_connections(int );
int lp_defaultcase(int );
int lp_minprintspace(int );
char lp_magicchar(int );
BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir);
int lp_add_service(char *pszService, int iDefaultService);
BOOL lp_add_printer(char *pszPrintername, int iDefaultService);
BOOL lp_file_list_changed(void);
BOOL lp_snum_ok(int iService);
BOOL lp_loaded(void);
void lp_killunused(BOOL (*snumused)(int ));
BOOL lp_load(char *pszFname,BOOL global_only);
int lp_numservices(void);
void lp_dump(void);
int lp_servicenumber(char *pszServiceName);
char *my_workgroup(void);
char *volume_label(int snum);
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);
BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset);
BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode);
BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode);
int get_share_mode_by_fnum(int cnum,int fnum,int *pid);
int get_share_mode_byname(int cnum,char *fname,int *pid);
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_files(void);
int str_checksum(char *s);
BOOL is_8_3(char *fname);
void create_mangled_stack(int size);
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);
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);
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 announce_backup(void);
void announce_host(void);
void announce_master(void);
struct work_record *remove_workgroup(struct subnet_record *d,
struct work_record *work);
void expire_browse_cache(time_t t);
struct work_record *find_workgroupstruct(struct subnet_record *d,
fstring name, BOOL add);
struct subnet_record *find_subnet(struct in_addr source_ip);
void dump_workgroups(void);
struct subnet_record *add_subnet_entry(struct in_addr source_ip,
struct in_addr source_mask,
char *name, BOOL add, BOOL lmhosts);
struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
time_t ttl, struct in_addr ip);
void remove_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);
void write_browse_list(void);
void expire_servers(time_t t);
void query_refresh_names(void);
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);
void become_nonmaster(struct subnet_record *d, struct work_record *work,
int remove_type);
void run_elections(void);
void process_election(struct packet_struct *p,char *buf);
BOOL check_elections(void);
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)());
void expire_netbios_response_entries(void);
void reply_netbios_packet(struct packet_struct *p1,int trn_id,
int rcode,int opcode,BOOL recurse,
struct nmb_name *rr_name,int rr_type,int rr_class,int ttl,
char *data,int len);
void queue_netbios_pkt_wins(struct subnet_record *d,
int fd,int quest_type,enum cmd_type cmd,
char *name,int name_type, int nb_flags, time_t ttl,
BOOL bcast,BOOL recurse,struct in_addr to_ip);
void queue_netbios_packet(struct subnet_record *d,
int fd,int quest_type,enum cmd_type cmd,char *name,
int name_type,int nb_flags,time_t ttl,
BOOL bcast,BOOL recurse, struct in_addr to_ip);
struct response_record *find_response_record(struct subnet_record *d,
uint16 id);
void queue_packet(struct packet_struct *packet);
void run_packet_queue();
void listen_for_packets(BOOL run_election);
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);
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);
void remove_name(struct subnet_record *d, struct name_record *n);
void dump_names(void);
void remove_netbios_name(struct subnet_record *d, 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 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 do_announce_host(int command,
char *from, int from_type, struct in_addr from_ip,
char *to , int to_type , struct in_addr to_ip,
int update_count, time_t announce_interval,
char *server_name, int server_type, char *server_comment);
void load_netbios_names(void);
void add_my_names(void);
void remove_my_names(void);
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);
void refresh_my_names(time_t t);
void expire_names(time_t t);
void response_name_release(struct subnet_record *d,struct packet_struct *p);
void reply_name_release(struct packet_struct *p);
void response_name_reg(struct subnet_record *d,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);
void process_nmb(struct packet_struct *p);
void reset_server(char *name, int state, struct in_addr ip);
void tell_become_backup(void);
void do_browser_lists(void);
void sync_server(enum cmd_type cmd, char *serv_name, char *work_name,
int name_type,
struct in_addr ip);
void add_my_subnets(char *group);
BOOL same_context(struct dgram_packet *dgram);
BOOL listening_name(struct work_record *work, struct nmb_name *n);
void process_logon_packet(struct packet_struct *p,char *buf,int len);
BOOL listening_type(struct packet_struct *p, int command);
void process_browse_packet(struct packet_struct *p,char *buf,int len);
void process_dgram(struct packet_struct *p);
BOOL reload_services(BOOL test);
void debug_nmb_packet(struct packet_struct *p);
char *namestr(struct nmb_name *n);
void free_nmb_packet(struct nmb_packet *nmb);
void free_packet(struct packet_struct *packet);
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);
int main(int argc,char *argv[]);
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 pm_process(char *pszFileName,BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *));
void generate_next_challenge(char *challenge);
BOOL set_challenge(char *challenge);
BOOL last_challenge(char *challenge);
int valid_uid(int uid);
user_struct *get_valid_user_struct(int uid);
void invalidate_uid(int uid);
char *validated_username(int vuid);
void register_uid(int uid,int gid, char *name,BOOL guest);
void add_session_user(char *user);
void dfs_unlogin(void);
BOOL password_check(char *password);
BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned char *c8);
BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd, BOOL is_nt_password);
BOOL user_ok(char *user,int snum);
BOOL authorise_login(int snum,char *user,char *password, int pwlen,
BOOL *guest,BOOL *force,int vuid);
BOOL check_hosts_equiv(char *user);
BOOL server_cryptkey(char *buf);
BOOL server_validate(char *buf);
BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname);
void pcap_printer_fn(void (*fn)());
int read_predict(int fd,int offset,char *buf,char **ptr,int num);
void do_read_prediction();
void invalidate_read_prediction(int fd);
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);
BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize);
char *Strstr(char *s, char *p);
time_t Mktime(struct tm *t);
int InNetGr(char *group,char *host,char *user,char *dom);
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);
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);
int reply_unknown(char *inbuf,char *outbuf);
int reply_ioctl(char *inbuf,char *outbuf);
int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize);
int reply_chkpth(char *inbuf,char *outbuf);
int reply_getatr(char *inbuf,char *outbuf);
int reply_setatr(char *inbuf,char *outbuf);
int reply_dskattr(char *inbuf,char *outbuf);
int reply_search(char *inbuf,char *outbuf);
int reply_fclose(char *inbuf,char *outbuf);
int reply_open(char *inbuf,char *outbuf);
int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize);
int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize);
int reply_mknew(char *inbuf,char *outbuf);
int reply_ctemp(char *inbuf,char *outbuf);
int reply_unlink(char *inbuf,char *outbuf);
int reply_readbraw(char *inbuf, char *outbuf);
int reply_lockread(char *inbuf,char *outbuf);
int reply_read(char *inbuf,char *outbuf);
int reply_read_and_X(char *inbuf,char *outbuf,int length,int bufsize);
int reply_writebraw(char *inbuf,char *outbuf);
int reply_writeunlock(char *inbuf,char *outbuf);
int reply_write(char *inbuf,char *outbuf,int dum1,int dum2);
int reply_write_and_X(char *inbuf,char *outbuf,int length,int bufsize);
int reply_lseek(char *inbuf,char *outbuf);
int reply_flush(char *inbuf,char *outbuf);
int reply_exit(char *inbuf,char *outbuf);
int reply_close(char *inbuf,char *outbuf);
int reply_writeclose(char *inbuf,char *outbuf);
int reply_lock(char *inbuf,char *outbuf);
int reply_unlock(char *inbuf,char *outbuf);
int reply_tdis(char *inbuf,char *outbuf);
int reply_echo(char *inbuf,char *outbuf);
int reply_printopen(char *inbuf,char *outbuf);
int reply_printclose(char *inbuf,char *outbuf);
int reply_printqueue(char *inbuf,char *outbuf);
int reply_printwrite(char *inbuf,char *outbuf);
int reply_mkdir(char *inbuf,char *outbuf);
int reply_rmdir(char *inbuf,char *outbuf);
int reply_mv(char *inbuf,char *outbuf);
int reply_copy(char *inbuf,char *outbuf);
int reply_setdir(char *inbuf,char *outbuf);
int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize);
int reply_readbmpx(char *inbuf,char *outbuf,int length,int bufsize);
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);
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);
BOOL unix_convert(char *name,int cnum);
int disk_free(char *path,int *bsize,int *dfree,int *dsize);
int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize);
BOOL check_name(char *name,int cnum);
void open_file(int fnum,int cnum,char *fname1,int flags,int mode);
void sync_file(int fnum);
void close_file(int fnum);
BOOL check_file_sharing(int cnum,char *fname);
void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
int mode,int *Access,int *action);
int seek_file(int fnum,int pos);
int read_file(int fnum,char *data,int pos,int mincnt,int maxcnt,int timeout,BOOL exact);
int write_file(int fnum,char *data,int n);
BOOL become_service(int cnum,BOOL do_chdir);
int find_service(char *service);
int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line);
int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line);
int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line);
BOOL snum_used(int snum);
BOOL reload_services(BOOL test);
int setup_groups(char *user, int uid, int gid, int *p_ngroups,
int **p_igroups, gid_t **p_groups);
int make_connection(char *service,char *user,char *password, int pwlen, char *dev,int vuid);
int find_free_file(void );
int reply_corep(char *outbuf);
int reply_coreplus(char *outbuf);
int reply_lanman1(char *outbuf);
int reply_lanman2(char *outbuf);
int reply_nt1(char *outbuf);
void parse_connect(char *buf,char *service,char *user,char *password,int *pwlen,char *dev);
void close_cnum(int cnum, int uid);
BOOL yield_connection(int cnum,char *name,int max_connections);
BOOL claim_connection(int cnum,char *name,int max_connections,BOOL Clear);
void exit_server(char *reason);
void standard_sub(int cnum,char *s);
char *smb_fn_name(int type);
int chain_reply(int type,char *inbuf,char *inbuf2,char *outbuf,char *outbuf2,int size,int bufsize);
int construct_reply(char *inbuf,char *outbuf,int size,int bufsize);
void str_to_key(uchar *str,uchar *key);
void D1(uchar *k, uchar *d, uchar *out);
void E1(uchar *k, uchar *d, uchar *out);
void E_P16(uchar *p14,uchar *p16);
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);
void Ucrit_addUsername(pstring username);
unsigned int Ucrit_checkUsername(pstring username);
void Ucrit_addPid(int pid);
unsigned int Ucrit_checkPid(int pid);
int sys_select(fd_set *fds,struct timeval *tval);
int sys_select(fd_set *fds,struct timeval *tval);
int sys_unlink(char *fname);
int sys_open(char *fname,int flags,int mode);
DIR *sys_opendir(char *dname);
int sys_stat(char *fname,struct stat *sbuf);
int sys_lstat(char *fname,struct stat *sbuf);
int sys_mkdir(char *dname,int mode);
int sys_rmdir(char *dname);
int sys_chdir(char *dname);
int sys_utime(char *fname,struct utimbuf *times);
int sys_rename(char *from, char *to);
int sys_chown(char *fname,int uid,int gid);
int sys_chroot(char *dname);
int main(int argc, char *argv[]);
void GetTimeOfDay(struct timeval *tval);
void TimeInit(void);
int TimeDiff(time_t t);
struct tm *LocalTime(time_t *t);
time_t interpret_long_date(char *p);
void put_long_date(char *p,time_t t);
void put_dos_date(char *buf,int offset,time_t unixdate);
void put_dos_date2(char *buf,int offset,time_t unixdate);
void put_dos_date3(char *buf,int offset,time_t unixdate);
time_t make_unix_date(void *date_ptr);
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 );
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);
char *ufc_crypt(char *key,char *salt);
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);
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);
void setup_logging(char *pname,BOOL interactive);
void reopen_logs(void);
BOOL is_a_socket(int fd);
BOOL next_token(char **ptr,char *buff,char *sep);
char **toktocliplist(int *ctok, char *sep);
void *MemMove(void *dest,void *src,int size);
void array_promote(char *array,int elsize,int element);
void set_socket_options(int fd, char *options);
void close_sockets(void );
BOOL in_group(gid_t group, int current_gid, int ngroups, int *groups);
char *StrCpy(char *dest,char *src);
char *StrnCpy(char *dest,const char *src,int n);
void putip(void *dest,void *src);
int name_mangle(char *In,char *Out,char name_type);
BOOL file_exist(char *fname,struct stat *sbuf);
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);
BOOL strnequal(char *s1,char *s2,int n);
BOOL strcsequal(char *s1,char *s2);
void strlower(char *s);
void strupper(char *s);
void strnorm(char *s);
BOOL strisnormal(char *s);
void string_replace(char *s,char oldc,char newc);
void unix_format(char *fname);
void dos_format(char *fname);
void show_msg(char *buf);
int smb_len(char *buf);
void _smb_setlen(char *buf,int len);
void smb_setlen(char *buf,int len);
int set_message(char *buf,int num_words,int num_bytes,BOOL zero);
int smb_numwords(char *buf);
int smb_buflen(char *buf);
int smb_buf_ofs(char *buf);
char *smb_buf(char *buf);
int smb_offset(char *p,char *buf);
char *skip_string(char *buf,int n);
BOOL trim_string(char *s,char *front,char *back);
void dos_clean_name(char *s);
void unix_clean_name(char *s);
int ChDir(char *path);
char *GetWd(char *str);
BOOL reduce_name(char *s,char *dir,BOOL widelinks);
void expand_mask(char *Mask,BOOL doext);
BOOL strhasupper(char *s);
BOOL strhaslower(char *s);
int count_chars(char *s,char c);
void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode,time_t date);
void close_low_fds(void);
int write_socket(int fd,char *buf,int len);
int read_udp_socket(int fd,char *buf,int len);
int set_blocking(int fd, BOOL set);
int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out,BOOL exact);
int read_max_udp(int fd,char *buffer,int bufsize,int maxtime);
int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew);
BOOL send_keepalive(int client);
int read_data(int fd,char *buffer,int N);
int write_data(int fd,char *buffer,int N);
int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align);
int read_smb_length(int fd,char *inbuf,int timeout);
BOOL receive_smb(int fd,char *buffer,int timeout);
BOOL send_smb(int fd,char *buffer);
char *name_ptr(char *buf,int ofs);
int name_extract(char *buf,int ofs,char *name);
int name_len(char *s);
BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type);
void msleep(int t);
BOOL in_list(char *s,char *list,BOOL casesensitive);
BOOL string_init(char **dest,char *src);
void string_free(char **s);
BOOL string_set(char **dest,char *src);
BOOL string_sub(char *s,char *pattern,char *insert);
BOOL do_match(char *str, char *regexp, int case_sig);
BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2);
void become_daemon(void);
BOOL yesno(char *p);
char *fgets_slash(char *s2,int maxlen,FILE *f);
int set_filelen(int fd, long len);
int byte_checksum(char *buf,int len);
char *dirname_dos(char *path,char *buf);
void *Realloc(void *p,int size);
void Abort(void );
BOOL get_myname(char *myname,struct in_addr *ip);
BOOL ip_equal(struct in_addr ip1,struct in_addr ip2);
int open_socket_in(int type, int port, int dlevel);
int open_socket_out(int type, struct in_addr *addr, int port );
int interpret_protocol(char *str,int def);
int interpret_security(char *str,int def);
unsigned long interpret_addr(char *str);
struct in_addr *interpret_addr2(char *str);
BOOL zero_ip(struct in_addr ip);
void standard_sub_basic(char *s);
BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask);
int PutUniCode(char *dst,char *src);
struct hostent *Get_Hostbyname(char *name);
BOOL process_exists(int pid);
char *uidtoname(int uid);
char *gidtoname(int gid);
void BlockSignals(BOOL block);
void ajt_panic(void);
char *readdirname(void *p);
int VT_Check(char *buffer);
int VT_Start_utmp(void);
int VT_Stop_utmp(void);
void VT_AtExit(void);
void VT_SigCLD(int sig);
void VT_SigEXIT(int sig);
int VT_Start(void);
int VT_Output(char *Buffer);
int VT_Input(char *Buffer,int Size);
void VT_Process(void);

View File

@ -381,6 +381,15 @@ struct server_info_struct
};
/* used for network interfaces */
struct interface
{
struct interface *next;
struct in_addr ip;
struct in_addr bcast;
struct in_addr nmask;
};
/* this is used for smbstatus */
struct connect_record
{

View File

@ -122,7 +122,8 @@ void announce_backup(void)
int tok;
if (!lastrun) lastrun = t;
if (t < lastrun + CHECK_TIME_ANNOUNCE_BACKUP * 60) return;
if (t < lastrun + CHECK_TIME_ANNOUNCE_BACKUP * 60)
return;
lastrun = t;
for (tok = 0; tok <= workgroup_count; tok++)
@ -178,20 +179,103 @@ void announce_backup(void)
}
/****************************************************************************
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,
int updatecount, time_t announce_interval,
char *server_name, int server_type, char *server_comment)
{
pstring outbuf;
char *p;
bzero(outbuf,sizeof(outbuf));
p = outbuf+1;
/* command type */
CVAL(outbuf,0) = command;
/* 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);
CVAL(p,21) = 2; /* major version */
CVAL(p,22) = 2; /* minor version */
SIVAL(p,23,server_type);
SSVAL(p,27,0xaa55); /* browse signature */
SSVAL(p,29,1); /* browse version */
strcpy(p+31,server_comment);
p += 31;
p = skip_string(p,1);
/* 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);
}
/****************************************************************************
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)
{
if (AM_MASTER(work))
{
DEBUG(3,("sending local master announce to %s for %s(1e)\n",
inet_ntoa(d->bcast_ip),work->work_group));
do_announce_host(ANN_LocalMasterAnnouncement,
name , 0x00, d->myip,
work->work_group, 0x1e, d->bcast_ip,
updatecount, ttl*1000,
name, server_type, comment);
DEBUG(3,("sending domain announce to %s for %s\n",
inet_ntoa(d->bcast_ip),work->work_group));
/* XXXX should we do a domain-announce-kill? */
if (server_type != 0)
{
do_announce_host(ANN_DomainAnnouncement,
work->work_group, 0x00, d->myip,
MSBROWSE , 0x01, d->bcast_ip,
updatecount, ttl*1000,
name, server_type ? SV_TYPE_DOMAIN_ENUM : 0, comment);
}
}
else
{
DEBUG(3,("sending host announce to %s for %s(1d)\n",
inet_ntoa(d->bcast_ip),work->work_group));
do_announce_host(ANN_HostAnnouncement,
name , 0x00, d->myip,
work->work_group, 0x1d, d->bcast_ip,
updatecount, ttl*1000,
name, server_type, comment);
}
}
/****************************************************************************
construct a host announcement unicast
**************************************************************************/
void announce_host(void)
{
time_t t = time(NULL);
pstring outbuf;
char *p;
char *namep;
char *stypep;
char *commentp;
struct subnet_record *d;
pstring comment;
char *my_name;
struct subnet_record *d;
StrnCpy(comment, *ServerComment ? ServerComment : "NoComment", 43);
@ -225,9 +309,6 @@ void announce_host(void)
work->lastannounce_time = t;
/* when announcing to remote networks we make sure we don't
claim to be any sort of special server, otherwise we may
stuff up their browsing */
if (!d->my_interface) {
stype &= ~(SV_TYPE_POTENTIAL_BROWSER | SV_TYPE_MASTER_BROWSER |
SV_TYPE_DOMAIN_MASTER | SV_TYPE_BACKUP_BROWSER |
@ -243,78 +324,15 @@ void announce_host(void)
if (announce)
{
bzero(outbuf,sizeof(outbuf));
p = outbuf+1;
CVAL(p,0) = updatecount;
/* ms - despite the spec */
SIVAL(p,1,work->announce_interval*1000);
namep = p+5;
StrnCpy(namep,my_name,16);
strupper(namep);
CVAL(p,21) = 2; /* major version */
CVAL(p,22) = 2; /* minor version */
stypep = p+23;
SIVAL(p,23,stype);
SSVAL(p,27,0xaa55); /* browse signature */
SSVAL(p,29,1); /* browse version */
commentp = p+31;
strcpy(commentp,comment);
p = p+31;
p = skip_string(p,1);
if (d->my_interface && AM_MASTER(work))
{
SIVAL(stypep,0,work->ServerType);
DEBUG(2,("sending local master announce to %s for %s\n",
inet_ntoa(d->bcast_ip),work->work_group));
CVAL(outbuf,0) = ANN_LocalMasterAnnouncement;
send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,
PTR_DIFF(p,outbuf),
my_name,work->work_group,0,
0x1e,d->bcast_ip,
*iface_ip(d->bcast_ip));
DEBUG(2,("sending domain announce to %s for %s\n",
inet_ntoa(d->bcast_ip),work->work_group));
CVAL(outbuf,0) = ANN_DomainAnnouncement;
StrnCpy(namep,work->work_group,15);
strupper(namep);
StrnCpy(commentp,myname,15);
strupper(commentp);
SIVAL(stypep,0,(unsigned)0x80000000);
p = commentp + strlen(commentp) + 1;
send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,
PTR_DIFF(p,outbuf),
my_name,MSBROWSE,0,0x01,d->bcast_ip,
*iface_ip(d->bcast_ip));
}
else
{
DEBUG(2,("sending host announce to %s for %s\n",
inet_ntoa(d->bcast_ip),work->work_group));
CVAL(outbuf,0) = ANN_HostAnnouncement;
send_mailslot_reply(BROWSE_MAILSLOT,ClientDGRAM,outbuf,
PTR_DIFF(p,outbuf),
my_name,work->work_group,0,0x1d,
d->bcast_ip,*iface_ip(d->bcast_ip));
}
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)
{
work->needannounce = False;
break;
/* sorry: can't do too many announces. do some more later */
}
}
}
}
@ -328,7 +346,7 @@ void announce_host(void)
least 15 minutes.
this actually gets done in search_and_sync_workgroups() via the
MASTER_SERVER_CHECK command, if there is a response from the
NAME_QUERY_MST_SRV_CHK command, if there is a response from the
name query initiated here. see response_name_query()
**************************************************************************/
void announce_master(void)
@ -382,9 +400,9 @@ void announce_master(void)
struct in_addr ip;
ip = ipzero;
queue_netbios_pkt_wins(ClientNMB,NMB_QUERY,
MASTER_SERVER_CHECK,
work->work_group,0x1b,0,
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY,
NAME_QUERY_MST_SRV_CHK,
work->work_group,0x1b,0,0,
False, False, ip);
}
else
@ -392,9 +410,9 @@ void announce_master(void)
struct subnet_record *d2;
for (d2 = subnetlist; d2; d2 = d2->next)
{
queue_netbios_packet(ClientNMB,NMB_QUERY,
MASTER_SERVER_CHECK,
work->work_group,0x1b,0,
queue_netbios_packet(d,ClientNMB,NMB_QUERY,
NAME_QUERY_MST_SRV_CHK,
work->work_group,0x1b,0,0,
True, False, d2->bcast_ip);
}
}
@ -427,8 +445,8 @@ void announce_master(void)
/* check the existence of a pdc for this workgroup, and if
one exists at the specified ip, sync with it and announce
ourselves as a master browser to it */
queue_netbios_pkt_wins(ClientNMB, NMB_QUERY,MASTER_SERVER_CHECK,
work->work_group,0x1b, 0,
queue_netbios_pkt_wins(d,ClientNMB, NMB_QUERY,NAME_QUERY_MST_SRV_CHK,
work->work_group,0x1b, 0, 0,
bcast, False, ip);
}
}

View File

@ -38,10 +38,17 @@ extern pstring myname;
extern pstring scope;
extern struct in_addr ipgrp;
extern struct in_addr ipzero;
/* this is our browse master/backup cache database */
struct browse_cache_record *browserlist = NULL;
/* local interfaces structure */
extern struct interface *local_interfaces;
/* remote interfaces structure */
extern struct interface *remote_interfaces;
/* this is our domain/workgroup/server database */
struct subnet_record *subnetlist = NULL;
@ -317,8 +324,8 @@ struct work_record *find_workgroupstruct(struct subnet_record *d,
{
DEBUG(2,("add any workgroups: initiating browser search on %s\n",
inet_ntoa(d->bcast_ip)));
queue_netbios_pkt_wins(ClientNMB,NMB_QUERY, FIND_MASTER,
MSBROWSE,0x1,0,
queue_netbios_pkt_wins(d,ClientNMB,NMB_QUERY, NAME_QUERY_FIND_MST,
MSBROWSE,0x1,0,0,
True,False, d->bcast_ip);
return NULL;
}
@ -339,8 +346,6 @@ struct work_record *find_workgroupstruct(struct subnet_record *d,
if ((work = make_workgroup(name)))
{
work->needelection = False;
if (lp_preferred_master() &&
strequal(lp_workgroup(), name) &&
d->my_interface)
@ -349,6 +354,10 @@ struct work_record *find_workgroupstruct(struct subnet_record *d,
work->needelection = True;
work->ElectionCriterion |= (1<<3);
}
if (!d->my_interface)
{
work->needelection = False;
}
add_workgroup(work, d);
return(work);
}
@ -356,20 +365,31 @@ struct work_record *find_workgroupstruct(struct subnet_record *d,
}
/****************************************************************************
find a domain in the subnetlist
find a subnet in the subnetlist
**************************************************************************/
struct subnet_record *find_domain(struct in_addr ip)
struct subnet_record *find_subnet(struct in_addr bcast_ip)
{
struct subnet_record *d;
struct in_addr wins_ip = ipgrp;
/* search through domain list for broadcast/netmask that matches
the source ip address */
/* search through subnet list for broadcast/netmask that matches
the source ip address. a subnet 255.255.255.255 represents the
WINS list. */
for (d = subnetlist; d; d = d->next)
{
if (same_net(ip, d->bcast_ip, d->mask_ip))
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 (NULL);
}
@ -411,8 +431,7 @@ void dump_workgroups(void)
/****************************************************************************
create a domain entry
****************************************************************************/
static struct subnet_record *make_subnet(struct in_addr bcast_ip,
struct in_addr mask)
static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr mask_ip)
{
struct subnet_record *d;
d = (struct subnet_record *)malloc(sizeof(*d));
@ -421,54 +440,107 @@ static struct subnet_record *make_subnet(struct in_addr bcast_ip,
bzero((char *)d,sizeof(*d));
DEBUG(4,("making subnet %s ", inet_ntoa(bcast_ip)));
DEBUG(4,("%s\n", inet_ntoa(mask)));
DEBUG(4, ("making domain %s ", inet_ntoa(bcast_ip)));
DEBUG(4, ("%s\n", inet_ntoa(mask_ip)));
d->bcast_ip = bcast_ip;
d->mask_ip = mask;
d->mask_ip = mask_ip;
d->workgrouplist = NULL;
d->my_interface = ismybcast(d->bcast_ip);
d->my_interface = False; /* True iff the interface is on the samba host */
add_subnet(d);
return d;
}
/****************************************************************************
add the remote interfaces from lp_remote_interfaces() and lp_interfaces()
to the netbios subnet database.
****************************************************************************/
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))
{
struct subnet_record *d = make_subnet(i->bcast,i->nmask);
if (d)
{
/* short-cut method to identifying local interfaces */
d->my_interface = True;
}
}
}
/* loop on all remote interfaces */
for (i = remote_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())
{
struct in_addr wins_bcast = ipgrp;
struct in_addr wins_nmask = ipzero;
make_subnet(wins_bcast, wins_nmask);
}
}
/****************************************************************************
add a domain entry. creates a workgroup, if necessary, and adds the domain
to the named a workgroup.
****************************************************************************/
struct subnet_record *add_subnet_entry(struct in_addr source_ip,
struct in_addr source_mask,
char *name, BOOL add)
struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
struct in_addr mask_ip,
char *name, BOOL add, BOOL lmhosts)
{
struct subnet_record *d;
struct in_addr ip;
ip = ipgrp;
/* XXXX andrew: struct in_addr ip appears not to be referenced at all except
in the DEBUG comment. i assume that the DEBUG comment below actually
intends to refer to bcast_ip? i don't know.
struct in_addr ip = ipgrp;
*/
if (zero_ip(source_ip))
source_ip = *iface_bcast(source_ip);
if (zero_ip(bcast_ip))
bcast_ip = *iface_bcast(bcast_ip);
/* add the domain into our domain database */
if ((d = find_domain(source_ip)) ||
(d = make_subnet(source_ip, source_mask)))
if ((d = find_subnet(bcast_ip)) ||
(d = make_subnet(bcast_ip, mask_ip)))
{
struct work_record *w = find_workgroupstruct(d, name, add);
extern pstring ServerComment;
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))
if (strequal(lp_workgroup(), name) && d->my_interface)
{
add_my_name_entry(d,name,0x1e,NB_ACTIVE|NB_GROUP);
add_my_name_entry(d,name,0x0 ,NB_ACTIVE|NB_GROUP);
}
/* add samba server name to workgroup list */
if ((strequal(lp_workgroup(), name) && d->my_interface) || lmhosts)
{
extern pstring ServerComment;
add_name_entry(name,0x1e,NB_ACTIVE|NB_GROUP);
add_name_entry(name,0x0 ,NB_ACTIVE|NB_GROUP);
add_server_entry(d,w,myname,w->ServerType,0,ServerComment,True);
}
DEBUG(3,("Added domain name entry %s at %s\n", name,inet_ntoa(ip)));
DEBUG(3,("Added domain name entry %s at %s\n", name,inet_ntoa(bcast_ip)));
return d;
}
return NULL;
@ -541,6 +613,28 @@ struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
}
/****************************************************************************
remove all samba's server entries
****************************************************************************/
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);
}
}
}
}
/****************************************************************************
add a server entry
****************************************************************************/
@ -569,6 +663,7 @@ struct server_record *add_server_entry(struct subnet_record *d,
return(s);
}
if (!s || s->serv.type != servertype || !strequal(s->serv.comment, comment))
updatedlists=True;
if (!s)
@ -581,8 +676,8 @@ struct server_record *add_server_entry(struct subnet_record *d,
bzero((char *)s,sizeof(*s));
}
if (d->my_interface &&
strequal(lp_workgroup(),work->work_group))
if (d->my_interface && strequal(lp_workgroup(),work->work_group))
{
if (servertype)
servertype |= SV_TYPE_LOCAL_LIST_ONLY;
@ -597,10 +692,7 @@ struct server_record *add_server_entry(struct subnet_record *d,
StrnCpy(s->serv.comment,comment,sizeof(s->serv.comment)-1);
strupper(s->serv.name);
s->serv.type = servertype;
s->death_time = ttl?time(NULL)+ttl*3:0;
if (servertype == 0)
s->death_time = time(NULL)-1;
s->death_time = servertype ? (ttl?time(NULL)+ttl*3:0) : (time(NULL)-1);
/* for a domain entry, the comment field refers to the server name */
@ -669,8 +761,7 @@ void write_browse_list(void)
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])
if ((s->serv.type & SV_TYPE_DOMAIN_ENUM) && !s->serv.comment[0])
{
continue;
}

View File

@ -42,8 +42,6 @@ extern pstring ServerComment;
extern time_t StartupTime;
#define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER)
#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
extern struct subnet_record *subnetlist;
@ -61,7 +59,6 @@ void check_master_browser(void)
if (!lastrun) lastrun = t;
if (t < lastrun + CHECK_TIME_MST_BROWSE * 60)
return;
lastrun = t;
dump_workgroups();
@ -77,8 +74,8 @@ void check_master_browser(void)
if (!AM_MASTER(work))
{
queue_netbios_packet(ClientNMB,NMB_QUERY,CHECK_MASTER,
work->work_group,0x1d,0,
queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK,
work->work_group,0x1d,0,0,
True,False,d->bcast_ip);
}
}
@ -91,13 +88,13 @@ void check_master_browser(void)
******************************************************************/
void browser_gone(char *work_name, struct in_addr ip)
{
struct subnet_record *d = find_domain(ip);
struct subnet_record *d = find_subnet(ip);
struct work_record *work = find_workgroupstruct(d, work_name, False);
if (!work || !d) return;
if (strequal(work->work_group, lp_workgroup()) &&
d->my_interface)
ismybcast(d->bcast_ip))
{
DEBUG(2,("Forcing election on %s %s\n",
@ -121,6 +118,7 @@ void browser_gone(char *work_name, struct in_addr ip)
}
}
/****************************************************************************
send an election packet
**************************************************************************/
@ -169,15 +167,16 @@ static void become_master(struct subnet_record *d, struct work_record *work)
work->ElectionCriterion |= 0x5;
/* add browse, master and general names to database or register with WINS */
add_name_entry(MSBROWSE ,0x01,NB_ACTIVE|NB_GROUP);
add_name_entry(work->work_group,0x1d,NB_ACTIVE );
add_my_name_entry(d,MSBROWSE ,0x01,NB_ACTIVE|NB_GROUP);
add_my_name_entry(d,work->work_group,0x1d,NB_ACTIVE );
if (lp_domain_master())
{
DEBUG(4,("Domain master: adding names...\n"));
/* add domain master and domain member names or register with WINS */
add_name_entry(work->work_group,0x1b,NB_ACTIVE);
add_my_name_entry(d,work->work_group,0x1b,NB_ACTIVE );
work->ServerType |= SV_TYPE_DOMAIN_MASTER;
if (lp_domain_logons())
@ -200,21 +199,44 @@ static void become_master(struct subnet_record *d, struct work_record *work)
/*******************************************************************
unbecome the master browser
unbecome the master browser. initates removal of necessary netbios
names, and tells the world that we are no longer a master browser.
******************************************************************/
void become_nonmaster(struct subnet_record *d, struct work_record *work)
void become_nonmaster(struct subnet_record *d, struct work_record *work,
int remove_type)
{
int new_server_type = work->ServerType;
DEBUG(2,("Becoming non-master for %s\n",work->work_group));
work->ServerType &= ~SV_TYPE_MASTER_BROWSER;
work->ServerType &= ~SV_TYPE_DOMAIN_MASTER;
work->ServerType |= SV_TYPE_POTENTIAL_BROWSER;
/* can only remove master or domain types with this function */
remove_type &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER);
/* unbecome a master browser; unbecome a domain master, too :-( */
if (remove_type & SV_TYPE_MASTER_BROWSER)
remove_type |= SV_TYPE_DOMAIN_MASTER;
new_server_type &= ~remove_type;
if (!(new_server_type & (SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER)))
{
/* no longer a master browser of any sort */
work->ServerType |= SV_TYPE_POTENTIAL_BROWSER;
work->ElectionCriterion &= ~0x4;
remove_name_entry(work->work_group,0x1b);
remove_name_entry(work->work_group,0x1d);
remove_name_entry(MSBROWSE ,0x01);
/* 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);
}
work->ServerType = new_server_type;
if (!(work->ServerType & SV_TYPE_DOMAIN_MASTER))
remove_name_entry(d,work->work_group,0x1b);
if (!(work->ServerType & SV_TYPE_DOMAIN_MASTER))
remove_name_entry(d,work->work_group,0x1d);
}
@ -292,7 +314,7 @@ void process_election(struct packet_struct *p,char *buf)
{
struct dgram_packet *dgram = &p->packet.dgram;
struct in_addr ip = dgram->header.source_ip;
struct subnet_record *d = find_domain(ip);
struct subnet_record *d = find_subnet(ip);
int version = CVAL(buf,0);
uint32 criterion = IVAL(buf,1);
int timeup = IVAL(buf,5)/1000;
@ -335,7 +357,8 @@ void process_election(struct packet_struct *p,char *buf)
/* if we are the master then remove our masterly names */
if (AM_MASTER(work))
{
become_nonmaster(d, work);
become_nonmaster(d, work,
SV_TYPE_MASTER_BROWSER|SV_TYPE_DOMAIN_MASTER);
}
}
}
@ -355,10 +378,6 @@ BOOL check_elections(void)
for (d = subnetlist; d; d = d->next)
{
struct work_record *work;
/* we only want to run elections on our own interfaces */
if (!d->my_interface) continue;
for (work = d->workgrouplist; work; work = work->next)
{
run_any_election |= work->RunningElection;

View File

@ -25,8 +25,7 @@
extern int ClientNMB;
extern int ClientDGRAM;
/* this is our initiated name query response database */
struct name_response_record *nameresponselist = NULL;
extern struct subnet_record *subnetlist;
extern int DEBUGLEVEL;
@ -35,24 +34,29 @@ BOOL CanRecurse = True;
extern pstring scope;
extern pstring myname;
extern struct in_addr ipzero;
extern struct in_addr ipgrp;
int num_response_packets = 0;
/***************************************************************************
add an initated name query into the list
**************************************************************************/
extern void add_response_record(struct name_response_record *n)
static void add_response_record(struct subnet_record *d,
struct response_record *n)
{
struct name_response_record *n2;
struct response_record *n2;
if (!nameresponselist)
if (!d) return;
if (!d->responselist)
{
nameresponselist = n;
d->responselist = n;
n->prev = NULL;
n->next = NULL;
return;
}
for (n2 = nameresponselist; n2->next; n2 = n2->next) ;
for (n2 = d->responselist; n2->next; n2 = n2->next) ;
n2->next = n;
n->next = NULL;
@ -60,41 +64,243 @@ extern void add_response_record(struct name_response_record *n)
}
/***************************************************************************
deals with an entry before it dies
**************************************************************************/
static void dead_netbios_entry(struct subnet_record *d,
struct response_record *n)
{
DEBUG(3,("Removing dead netbios entry for %s %s (num_msgs=%d)\n",
inet_ntoa(n->to_ip), namestr(&n->name), n->num_msgs));
switch (n->cmd_type)
{
case NAME_QUERY_CONFIRM:
{
if (!lp_wins_support()) return; /* only if we're a WINS server */
if (n->num_msgs == 0)
{
/* oops. name query had no response. check that the name is
unique and then remove it from our WINS database */
/* IMPORTANT: see query_refresh_names() */
if ((!NAME_GROUP(n->nb_flags)))
{
struct subnet_record *d = find_subnet(ipgrp);
if (d)
{
/* 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(d, n->name.name, n->name.name_type,
REGISTER, n->to_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->to_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->to_ip))
{
remove_netbios_name(d,n->name.name,n->name.name_type,SELF,n->to_ip);
}
if (!n->bcast)
{
DEBUG(1,("WINS server did not respond to name release!\n"));
}
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() */
enum name_source source = ismyip(n->to_ip) ? SELF : REGISTER;
add_netbios_entry(d,n->name.name,n->name.name_type,
n->nb_flags, n->ttl, source,n->to_ip, True,!n->bcast);
}
else
{
/* XXXX oops. this is where i wish this code could retry DGRAM
packets. we directed a name registration at a WINS server, and
received no response. rfc1001.txt states that after retrying,
we should assume the WINS server is dead, and fall back to
broadcasting. */
DEBUG(1,("WINS server did not respond to name registration!\n"));
}
break;
}
default:
{
/* nothing to do but delete the dead expected-response structure */
/* this is normal. */
break;
}
}
}
/****************************************************************************
initiate a netbios packet
****************************************************************************/
static 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)
{
struct packet_struct p;
struct nmb_packet *nmb = &p.packet.nmb;
struct res_rec additional_rec;
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; }
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)));
if (opcode == -1) return;
bzero((char *)&p,sizeof(p));
if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) +
(getpid()%(unsigned)100);
name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
if (*id == 0xffff) *id = name_trn_id; /* allow resending with same id */
nmb->header.name_trn_id = *id;
nmb->header.opcode = opcode;
nmb->header.response = False;
nmb->header.nm_flags.bcast = bcast;
nmb->header.nm_flags.recursion_available = CanRecurse;
nmb->header.nm_flags.recursion_desired = recurse;
nmb->header.nm_flags.trunc = False;
nmb->header.nm_flags.authoritative = False;
nmb->header.rcode = 0;
nmb->header.qdcount = 1;
nmb->header.ancount = 0;
nmb->header.nscount = 0;
nmb->header.arcount = (quest_type==NMB_REG || quest_type==NMB_REL) ? 1 : 0;
make_nmb_name(&nmb->question.question_name,name,name_type,scope);
nmb->question.question_type = quest_type;
nmb->question.question_class = 0x1;
if (quest_type == NMB_REG || quest_type == NMB_REL)
{
nmb->additional = &additional_rec;
bzero((char *)nmb->additional,sizeof(*nmb->additional));
nmb->additional->rr_name = nmb->question.question_name;
nmb->additional->rr_type = nmb->question.question_type;
nmb->additional->rr_class = nmb->question.question_class;
nmb->additional->ttl = quest_type == NMB_REG ? lp_max_ttl() : 0;
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;
p.fd = fd;
p.timestamp = time(NULL);
p.packet_type = NMB_PACKET;
if (!send_packet(&p)) *id = 0xffff;
return;
}
/*******************************************************************
remove old name response entries
XXXX retry code needs to be added, including a retry wait period and a count
see name_query() and name_status() for suggested implementation.
******************************************************************/
void expire_netbios_response_entries(time_t t)
void expire_netbios_response_entries()
{
struct name_response_record *n;
struct name_response_record *nextn;
struct response_record *n;
struct response_record *nextn;
struct subnet_record *d;
for (n = nameresponselist; n; n = nextn)
for (d = subnetlist; d; d = d->next)
for (n = d->responselist; n; n = nextn)
{
if (n->start_time < t)
{
DEBUG(3,("Removing dead name query for %s %s (num_msgs=%d)\n",
inet_ntoa(n->to_ip), namestr(&n->name), n->num_msgs));
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->to_ip);
if (n->cmd_type == CHECK_MASTER)
{
/* if no response received, the master browser must have gone */
if (n->num_msgs == 0)
browser_gone(n->name.name, n->to_ip);
}
n->repeat_time += n->repeat_interval; /* XXXX ms needed */
n->repeat_count--;
}
else
{
dead_netbios_entry(d,n);
nextn = n->next;
if (n->prev) n->prev->next = n->next;
if (n->next) n->next->prev = n->prev;
if (d->responselist == n) d->responselist = n->next;
free(n);
num_response_packets--;
continue;
}
}
nextn = n->next;
if (n->prev) n->prev->next = n->next;
if (n->next) n->next->prev = n->prev;
if (nameresponselist == n) nameresponselist = n->next;
free(n);
}
else
{
nextn = n->next;
}
}
}
@ -102,9 +308,10 @@ void expire_netbios_response_entries(time_t t)
/****************************************************************************
reply to a netbios name packet
****************************************************************************/
void reply_netbios_packet(struct packet_struct *p1,int trn_id,int rcode,
int opcode,BOOL recurse,struct nmb_name *rr_name,
int rr_type,int rr_class,int ttl,char *data,int len)
void reply_netbios_packet(struct packet_struct *p1,int trn_id,
int rcode,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;
@ -160,89 +367,14 @@ void reply_netbios_packet(struct packet_struct *p1,int trn_id,int rcode,
}
/****************************************************************************
initiate a netbios packet
****************************************************************************/
uint16 initiate_netbios_packet(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;
struct res_rec additional_rec;
char *packet_type = "unknown";
int opcode = -1;
if (quest_type == NMB_STATUS) { packet_type = "nmb_status"; opcode = 0; }
if (quest_type == NMB_QUERY ) { packet_type = "nmb_query"; opcode = 0; }
if (quest_type == NMB_REG ) { packet_type = "nmb_reg"; opcode = 5; }
if (quest_type == NMB_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)));
if (opcode == -1) return False;
bzero((char *)&p,sizeof(p));
if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) +
(getpid()%(unsigned)100);
name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
nmb->header.name_trn_id = name_trn_id;
nmb->header.opcode = opcode;
nmb->header.response = False;
nmb->header.nm_flags.bcast = bcast;
nmb->header.nm_flags.recursion_available = CanRecurse;
nmb->header.nm_flags.recursion_desired = recurse;
nmb->header.nm_flags.trunc = False;
nmb->header.nm_flags.authoritative = False;
nmb->header.rcode = 0;
nmb->header.qdcount = 1;
nmb->header.ancount = 0;
nmb->header.nscount = 0;
nmb->header.arcount = (quest_type==NMB_REG || quest_type==NMB_REL) ? 1 : 0;
make_nmb_name(&nmb->question.question_name,name,name_type,scope);
nmb->question.question_type = quest_type;
nmb->question.question_class = 0x1;
if (quest_type == NMB_REG || quest_type == NMB_REL)
{
nmb->additional = &additional_rec;
bzero((char *)nmb->additional,sizeof(*nmb->additional));
nmb->additional->rr_name = nmb->question.question_name;
nmb->additional->rr_type = nmb->question.question_type;
nmb->additional->rr_class = nmb->question.question_class;
nmb->additional->ttl = quest_type == NMB_REG ? lp_max_ttl() : 0;
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;
p.fd = fd;
p.timestamp = time(NULL);
p.packet_type = NMB_PACKET;
if (!send_packet(&p))
return(0);
return(name_trn_id);
}
/****************************************************************************
wrapper function to override a broadcast message and send it to the WINS
name server instead, if it exists. if wins is false, and there has been no
WINS server specified, the packet will NOT be sent.
****************************************************************************/
void queue_netbios_pkt_wins(int fd,int quest_type,enum cmd_type cmd,
char *name,int name_type,int nb_flags,
void queue_netbios_pkt_wins(struct subnet_record *d,
int fd,int quest_type,enum cmd_type cmd,
char *name,int name_type,int nb_flags, time_t ttl,
BOOL bcast,BOOL recurse,struct in_addr to_ip)
{
if ((!lp_wins_support()) && (*lp_wins_server()))
@ -266,35 +398,45 @@ void queue_netbios_pkt_wins(int fd,int quest_type,enum cmd_type cmd,
if (zero_ip(to_ip)) return;
queue_netbios_packet(fd, quest_type, cmd,
name, name_type, nb_flags,
queue_netbios_packet(d,fd, quest_type, cmd,
name, name_type, nb_flags, ttl,
bcast, recurse, to_ip);
}
/****************************************************************************
create a name query response record
**************************************************************************/
static struct name_response_record *
make_name_query_record(enum cmd_type cmd,int id,int fd,char *name,int type,
static struct response_record *
make_response_queue_record(enum cmd_type cmd,int id,int fd,
int quest_type, char *name,int type, int nb_flags, time_t ttl,
BOOL bcast,BOOL recurse,struct in_addr ip)
{
struct name_response_record *n;
struct response_record *n;
if (!name || !name[0]) return NULL;
if (!(n = (struct name_response_record *)malloc(sizeof(*n))))
if (!(n = (struct response_record *)malloc(sizeof(*n))))
return(NULL);
n->response_id = id;
n->cmd_type = cmd;
n->fd = fd;
n->quest_type = quest_type;
make_nmb_name(&n->name, name, type, scope);
n->nb_flags = nb_flags;
n->ttl = ttl;
n->bcast = bcast;
n->recurse = recurse;
n->to_ip = ip;
n->start_time = time(NULL);
n->repeat_interval = 1; /* XXXX should be in ms */
n->repeat_count = 4;
n->repeat_time = time(NULL) + n->repeat_interval;
n->num_msgs = 0;
num_response_packets++; /* count of total number of packets still around */
return n;
}
@ -305,32 +447,43 @@ make_name_query_record(enum cmd_type cmd,int id,int fd,char *name,int type,
master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
complete lists across a wide area network
****************************************************************************/
void queue_netbios_packet(int fd,int quest_type,enum cmd_type cmd,char *name,
int name_type,int nb_flags,BOOL bcast,BOOL recurse,
struct in_addr to_ip)
void queue_netbios_packet(struct subnet_record *d,
int fd,int quest_type,enum cmd_type cmd,char *name,
int name_type,int nb_flags, time_t ttl,
BOOL bcast,BOOL recurse, struct in_addr to_ip)
{
uint16 id = initiate_netbios_packet(fd, quest_type, name, name_type,
nb_flags, bcast, recurse, to_ip);
struct name_response_record *n;
struct in_addr wins_ip = ipgrp;
struct response_record *n;
uint16 id = 0xffff;
if (id == 0) return;
/* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */
if (ip_equal(wins_ip, to_ip)) return;
initiate_netbios_packet(&id, fd, quest_type, name, name_type,
nb_flags, bcast, recurse, to_ip);
if (id == 0xffff) return;
if ((n =
make_name_query_record(cmd,id,fd,name,name_type,bcast,recurse,to_ip)))
if ((n = make_response_queue_record(cmd,id,fd,
quest_type,name,name_type,nb_flags,ttl,
bcast,recurse,to_ip)))
{
add_response_record(n);
add_response_record(d,n);
}
}
/****************************************************************************
find a response in the name query response list
find a response in a subnet's name query response list.
**************************************************************************/
struct name_response_record *find_name_query(uint16 id)
struct response_record *find_response_record(struct subnet_record *d,
uint16 id)
{
struct name_response_record *n;
struct response_record *n;
for (n = nameresponselist; n; n = n->next)
if (!d) return NULL;
for (n = d->responselist; n; n = n->next)
{
if (n->response_id == id) {
return n;
@ -409,10 +562,12 @@ void listen_for_packets(BOOL run_election)
FD_SET(ClientNMB,&fds);
FD_SET(ClientDGRAM,&fds);
/* during elections we need to send election packets at one
second intervals */
/* during elections and when expecting a netbios response packet we need
to send election packets at one second intervals.
XXXX actually, it needs to be the interval (in ms) between time now and the
time we are expecting the next netbios packet */
timeout.tv_sec = run_election ? 1 : NMBD_SELECT_LOOP;
timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP;
timeout.tv_usec = 0;
selrtn = sys_select(&fds,&timeout);
@ -461,8 +616,9 @@ interpret a node status response. this is pretty hacked: we need two bits of
info. a) the name of the workgroup b) the name of the server. it will also
add all the names it finds into the namelist.
****************************************************************************/
BOOL interpret_node_status(char *p, struct nmb_name *name,int t,
char *serv_name, struct in_addr ip)
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)
{
int level = t==0x20 ? 4 : 0;
int numnames = CVAL(p,0);
@ -516,7 +672,7 @@ BOOL interpret_node_status(char *p, struct nmb_name *name,int t,
nameip = ip;
src = STATUS_QUERY;
}
add_netbios_entry(qname,type,nb_flags,2*60*60,src,nameip,True);
add_netbios_entry(d,qname,type,nb_flags,2*60*60,src,nameip,True,bcast);
}
/* we want the server name */
@ -559,9 +715,13 @@ BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
{
struct packet_struct p;
struct dgram_packet *dgram = &p.packet.dgram;
struct in_addr wins_ip = ipgrp;
char *ptr,*p2;
char tmp[4];
/* ha ha. no. do NOT send packets to 255.255.255.255: it's a pseudo address */
if (ip_equal(wins_ip, dest_ip)) return False;
bzero((char *)&p,sizeof(p));
dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */

File diff suppressed because it is too large Load Diff

View File

@ -48,6 +48,9 @@ extern int workgroup_count; /* total number of workgroups we know about */
/* this is our browse cache database */
extern struct browse_cache_record *browserlist;
/* this is our domain/workgroup/server database */
extern struct interface *local_interfaces;
/* this is our domain/workgroup/server database */
extern struct subnet_record *subnetlist;
@ -67,9 +70,6 @@ extern int updatecount;
extern time_t StartupTime;
#define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER)
#define AM_BACKUP(work) (work->ServerType & SV_TYPE_BACKUP_BROWSER)
#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
#define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
@ -158,28 +158,26 @@ void tell_become_backup(void)
/****************************************************************************
find a server responsible for a workgroup, and sync browse lists
**************************************************************************/
static BOOL sync_browse_entry(struct browse_cache_record *b)
static void start_sync_browse_entry(struct browse_cache_record *b)
{
struct subnet_record *d;
struct work_record *work;
/*
if (!strequal(serv_name, b->name))
{
DEBUG(0, ("browser's netbios name (%s) does not match %s (%s)",
b->name, inet_ntoa(b->ip), serv_name));
}
*/
if (!(d = find_domain(b->ip))) return False;
if (!(work = find_workgroupstruct(d, b->group, False))) return False;
if (!(d = find_subnet(b->ip))) return;
/* only sync if we are the master */
if (AM_MASTER(work)) {
/* only try to sync browse lists if we are the master, otherwise
the net could get a little bit too busy */
sync_browse_lists(work,b->name,0x20,b->ip);
/* 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,NAME_QUERY_SYNC,
b->group,0x20,0,0,
False,False,b->ip);
}
b->synced = True;
return True;
b->synced = True;
}
@ -193,6 +191,8 @@ void do_browser_lists(void)
time_t t = time(NULL);
if (t-last < 20) return; /* don't do too many of these at once! */
/* XXXX equally this period should not be too long
the server may die in the intervening gap */
last = t;
@ -202,12 +202,13 @@ void do_browser_lists(void)
if (b->sync_time < t && b->synced == False) break;
}
if (!b || b->synced || sync_browse_entry(b))
if (b && !b->synced)
{
/* leave entries (even ones already sync'd) for up to a minute.
this stops them getting re-sync'd too often */
/* sync with the selected entry then remove some dead entries */
start_sync_browse_entry(b);
expire_browse_cache(t - 60);
}
}
@ -221,7 +222,7 @@ void sync_server(enum cmd_type cmd, char *serv_name, char *work_name,
{
add_browser_entry(serv_name, name_type, work_name, 0, ip);
if (cmd == MASTER_SERVER_CHECK)
if (cmd == NAME_QUERY_MST_SRV_CHK)
{
/* announce ourselves as a master browser to serv_name */
do_announce_request(myname, serv_name, ANN_MasterAnnouncement,
@ -230,56 +231,23 @@ void sync_server(enum cmd_type cmd, char *serv_name, char *work_name,
}
/****************************************************************************
update workgroup database from a name registration
**************************************************************************/
void update_from_reg(char *name, int type, struct in_addr ip)
{
/* default server type: minimum guess at requirement XXXX */
DEBUG(3,("update from registration: host %s ip %s type %0x\n",
name, inet_ntoa(ip), type));
/* workgroup types, but not a chat type */
if (type >= 0x1b && type <= 0x1e)
{
struct work_record *work;
struct subnet_record *d;
if (!(d = find_domain(ip))) return;
if (!(work = find_workgroupstruct(d, name, False))) return;
/* request the server to announce if on our subnet */
if (d->my_interface) announce_request(work, ip);
/* domain master type or master browser type */
if (type == 0x1b || type == 0x1d)
{
struct hostent *hp = gethostbyaddr((char*)&ip, sizeof(ip), AF_INET);
if (hp) {
/* gethostbyaddr name may not match netbios name but who cares */
add_browser_entry(hp->h_name, type, work->work_group, 120, ip);
}
}
}
}
/****************************************************************************
add the default workgroup into my domain
**************************************************************************/
void add_my_domains(char *group)
void add_my_subnets(char *group)
{
int n,i;
struct in_addr *ip;
struct interface *i;
/* add or find domain on our local subnet, in the default workgroup */
if (*group == '*') return;
n = iface_count();
for (i=0;i<n;i++) {
ip = iface_n_ip(i);
if (!ip) return;
add_subnet_entry(*iface_bcast(*ip),*iface_nmask(*ip),lp_workgroup(),True);
/* the coding choice is up to you, andrew: i can see why you don't want
global access to the local_interfaces structure: so it can't get
messed up! */
for (i = local_interfaces; i; i = i->next)
{
add_subnet_entry(i->bcast,i->nmask,group, True, False);
}
}
@ -464,7 +432,7 @@ static void process_announce(struct packet_struct *p,int command,char *buf)
{
struct dgram_packet *dgram = &p->packet.dgram;
struct in_addr ip = dgram->header.source_ip;
struct subnet_record *d = find_domain(ip);
struct subnet_record *d = find_subnet(ip);
int update_count = CVAL(buf,0);
int ttl = IVAL(buf,1)/1000;
char *name = buf+5;
@ -545,8 +513,8 @@ static void process_master_announce(struct packet_struct *p,char *buf)
{
struct dgram_packet *dgram = &p->packet.dgram;
struct in_addr ip = dgram->header.source_ip;
struct subnet_record *d = find_domain(ip);
struct subnet_record *mydomain = find_domain(*iface_bcast(ip));
struct subnet_record *d = find_subnet(ip);
struct subnet_record *mydomain = find_subnet(*iface_bcast(ip));
char *name = buf;
struct work_record *work;
name[15] = 0;
@ -613,7 +581,7 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
DEBUG(4,("Found browser server at %s\n", inet_ntoa(back_ip)));
if ((d = find_domain(back_ip)))
if ((d = find_subnet(back_ip)))
{
struct subnet_record *d1;
for (d1 = subnetlist; d1; d1 = d1->next)
@ -623,8 +591,8 @@ static void process_rcv_backup_list(struct packet_struct *p,char *buf)
{
if (work->token == Index)
{
queue_netbios_packet(ClientNMB,NMB_QUERY,SERVER_CHECK,
work->work_group,0x1d,0,
queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK,
work->work_group,0x1d,0,0,
False,False,back_ip);
return;
}
@ -714,7 +682,7 @@ static void process_reset_browser(struct packet_struct *p,char *buf)
{
if (AM_MASTER(work))
{
become_nonmaster(d,work);
become_nonmaster(d,work,SV_TYPE_DOMAIN_MASTER|SV_TYPE_MASTER_BROWSER);
}
}
}
@ -729,7 +697,7 @@ static void process_reset_browser(struct packet_struct *p,char *buf)
struct work_record *work;
for (work=d->workgrouplist;work;work=remove_workgroup(d,work));
}
add_my_domains(lp_workgroup());
add_my_subnets(lp_workgroup());
}
/* stop browsing altogether. i don't think this is a good idea! */
@ -751,7 +719,7 @@ static void process_announce_request(struct packet_struct *p,char *buf)
struct dgram_packet *dgram = &p->packet.dgram;
struct work_record *work;
struct in_addr ip = dgram->header.source_ip;
struct subnet_record *d = find_domain(ip);
struct subnet_record *d = find_subnet(ip);
int token = CVAL(buf,0);
char *name = buf+1;
@ -783,7 +751,7 @@ void process_logon_packet(struct packet_struct *p,char *buf,int len)
{
struct dgram_packet *dgram = &p->packet.dgram;
struct in_addr ip = dgram->header.source_ip;
struct subnet_record *d = find_domain(ip);
struct subnet_record *d = find_subnet(ip);
char *logname,*q;
char *reply_name;
BOOL add_slashes = False;

View File

@ -69,6 +69,9 @@ static int sig_term()
/* remove all samba names, with wins server if necessary. */
remove_my_names();
/* announce all server entries as 0 time-to-live, 0 type */
remove_my_servers();
/* XXXX don't care if we never receive a response back... yet */
/* XXXX other things: if we are a master browser, force an election? */
@ -204,6 +207,7 @@ BOOL reload_services(BOOL test)
}
load_interfaces();
add_subnet_interfaces();
return(ret);
}
@ -286,9 +290,13 @@ static void load_hosts_file(char *fname)
ipmask = *iface_nmask(ipaddr);
if (group) {
add_subnet_entry(ipaddr, ipmask, name, True);
add_subnet_entry(ipaddr, ipmask, name, True, True);
} else {
add_netbios_entry(name,0x20,NB_ACTIVE,0,source,ipaddr,True);
struct subnet_record *d = find_subnet(ipaddr);
if (d)
{
add_netbios_entry(d,name,0x20,NB_ACTIVE,0,source,ipaddr,True,True);
}
}
}
}
@ -316,16 +324,19 @@ static void process(void)
announce_host();
#if 0
/* what was this stuff supposed to do? It sent
/* XXXX what was this stuff supposed to do? It sent
ANN_GetBackupListReq packets which I think should only be
sent when trying to find out who to browse with */
announce_backup();
#endif
announce_master();
query_refresh_names();
expire_names_and_servers();
expire_netbios_response_entries(t-10);
expire_netbios_response_entries();
refresh_my_names(t);
write_browse_list();
@ -514,7 +525,7 @@ static void usage(char *pname)
return(-1);
if (*group)
add_my_domains(group);
add_my_subnets(group);
if (!is_daemon && !is_a_socket(0)) {
DEBUG(0,("standard input is not a socket, assuming -D option\n"));
@ -535,16 +546,22 @@ static void usage(char *pname)
DEBUG(3,("Loaded hosts file\n"));
}
if (!*ServerComment)
strcpy(ServerComment,"Samba %v");
string_sub(ServerComment,"%v",VERSION);
string_sub(ServerComment,"%h",myhostname);
add_my_names();
add_my_domains(lp_workgroup());
add_my_subnets(lp_workgroup());
DEBUG(3,("Checked names\n"));
load_netbios_names();
DEBUG(3,("Loaded names\n"));
write_browse_list();
DEBUG(3,("Dumped names\n"));

View File

@ -102,6 +102,7 @@ static BOOL add_info(struct subnet_record *d, struct work_record *work, int serv
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));
@ -137,10 +138,11 @@ static BOOL add_info(struct subnet_record *d, struct work_record *work, int serv
log in on the remote server's SMB port to their IPC$ service,
do a NetServerEnum and update our server and workgroup databases.
******************************************************************/
void sync_browse_lists(struct work_record *work, char *name, int nm_type,
struct in_addr ip)
void sync_browse_lists(struct subnet_record *d, struct work_record *work,
char *name, int nm_type, struct in_addr ip)
{
struct subnet_record *d;
if (!d || !work || !AM_MASTER(work)) return;
pid = getpid();
uid = getuid();
gid = getgid();
@ -159,8 +161,6 @@ void sync_browse_lists(struct work_record *work, char *name, int nm_type,
if (zero_ip(dest_ip)) return;
have_ip = True;
if (!(d = find_domain(ip))) return;
connect_as_ipc = True;
/* connect as server and get domains, then servers */

View File

@ -129,6 +129,7 @@ typedef struct
char *szSmbrun;
char *szWINSserver;
char *szInterfaces;
char *szRemoteInterfaces;
int max_log_size;
int mangled_stack;
int max_xmit;
@ -366,6 +367,7 @@ struct parm_struct
{"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL},
{"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL},
{"interfaces", P_STRING, P_GLOBAL, &Globals.szInterfaces, NULL},
{"remote interfaces",P_STRING, P_GLOBAL, &Globals.szRemoteInterfaces,NULL},
{"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL},
{"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL},
{"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL},
@ -704,6 +706,7 @@ FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet)
FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript)
FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver)
FN_GLOBAL_STRING(lp_interfaces,&Globals.szInterfaces)
FN_GLOBAL_STRING(lp_remote_interfaces,&Globals.szRemoteInterfaces)
FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)

View File

@ -1,8 +1,3 @@
# generate prototypes for Samba C code
# tridge, June 1996
# added comment for each source file for use as crude index
# dan, 17 June 1996
BEGIN {
inheader=0;
current_file="";

View File

@ -93,7 +93,7 @@ static void usage(void)
int main(int argc,char *argv[])
{
int opt;
unsigned int lookup_type = 0;
unsigned int lookup_type = 0x0;
pstring lookup;
extern int optind;
extern char *optarg;