updated the NetBIOS code due to some bugs found by writing the first draft
authorSamba Release Account <samba-bugs@samba.org>
Mon, 1 Jul 1996 18:29:21 +0000 (18:29 +0000)
committerSamba Release Account <samba-bugs@samba.org>
Mon, 1 Jul 1996 18:29:21 +0000 (18:29 +0000)
of the low level design docs.

source/include/proto.h
source/nameresp.c
source/nameserv.c

index ce02be129fe4393dda618e703e9eb51dfbf0a78a..8dc3df0183478a516f6cf42ce93fa78d5d13f300 100644 (file)
@@ -1,20 +1,39 @@
 /* This file is automatically generated with "make proto". DO NOT EDIT */
+
+
+/*The following definitions come from  access.c  */
+
 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);
@@ -29,6 +48,9 @@ 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);
@@ -37,6 +59,9 @@ 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);
@@ -62,10 +87,18 @@ 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 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);
@@ -74,8 +107,17 @@ 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);
@@ -208,6 +250,9 @@ void lp_dump(void);
 int lp_servicenumber(char *pszServiceName);
 char *my_workgroup(void);
 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);
@@ -220,6 +265,9 @@ 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);
+
+/*The following definitions come from  mangle.c  */
+
 int str_checksum(char *s);
 BOOL is_8_3(char *fname);
 void create_mangled_stack(int size);
@@ -227,30 +275,50 @@ 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 announce_backup(void);
+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);
+void announce_server(struct subnet_record *d, struct work_record *work,
+                                       char *name, char *comment, time_t ttl, int server_type);
 void announce_host(void);
 void announce_master(void);
+
+/*The following definitions come from  namedb.c  */
+
 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);
+struct subnet_record *find_subnet(struct in_addr bcast_ip);
 void dump_workgroups(void);
-struct subnet_record *add_subnet_entry(struct in_addr source_ip, 
-                                      struct in_addr source_mask,
+void add_subnet_interfaces(void);
+struct subnet_record *add_subnet_entry(struct in_addr bcast_ip, 
+                                      struct in_addr mask_ip,
                                       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);
+void remove_my_servers(void);
 struct server_record *add_server_entry(struct subnet_record *d, 
                                       struct work_record *work,
                                       char *name,int servertype, 
@@ -258,36 +326,44 @@ struct server_record *add_server_entry(struct subnet_record *d,
                                       BOOL replace);
 void write_browse_list(void);
 void expire_servers(time_t t);
-void query_refresh_names(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);
 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  namequery.c  */
+
 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);
+
+/*The following definitions come from  nameresp.c  */
+
+void expire_netbios_response_entries();
 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);
+                               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,
+                           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,
+                       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();
@@ -298,38 +374,39 @@ BOOL interpret_node_status(struct subnet_record *d,
 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  nameserv.c  */
+
 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,
+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);
-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);
+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_name_entry(struct subnet_record *d,char *name,int type,int nb_flags);
 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 remove_my_names();
 void refresh_my_names(time_t t);
+void query_refresh_names(void);
 void expire_names(time_t t);
-void response_name_release(struct subnet_record *d,struct packet_struct *p);
+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 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);
+struct name_record *search_for_name(struct subnet_record **d,
+                                       struct nmb_name *question,
+                                   struct in_addr ip, int Time, int search);
 void reply_name_query(struct packet_struct *p);
 void process_nmb(struct packet_struct *p);
+
+/*The following definitions come from  namework.c  */
+
 void reset_server(char *name, int state, struct in_addr ip);
 void tell_become_backup(void);
 void do_browser_lists(void);
@@ -343,7 +420,13 @@ 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);
+
+/*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);
@@ -352,11 +435,23 @@ 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);
+               char *name, int nm_type, struct in_addr ip);
+
+/*The following definitions come from  params.c  */
+
 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);
@@ -376,18 +471,36 @@ 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  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);
@@ -395,6 +508,9 @@ 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);
@@ -445,6 +561,9 @@ 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);
@@ -486,6 +605,9 @@ 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);
+
+/*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);
@@ -494,10 +616,25 @@ 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  */
+
+
+/*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);
@@ -512,7 +649,16 @@ 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);
+
+/*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);
@@ -527,20 +673,35 @@ 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  */
+
 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);
@@ -647,6 +808,9 @@ char *gidtoname(int gid);
 void BlockSignals(BOOL block);
 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);
index 31df799691389b96ebd7caeef54371393121f4cb..14b995618630d33c26519f9de192588d736de4ad 100644 (file)
@@ -38,6 +38,19 @@ extern struct in_addr ipgrp;
 
 int num_response_packets = 0;
 
+/***************************************************************************
+  updates the unique transaction identifier
+  **************************************************************************/
+static void update_name_trn_id(void)
+{
+  if (!name_trn_id)
+  {
+    name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100);
+  }
+  name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
+}
+
+
 /***************************************************************************
   add an initated name query  into the list
   **************************************************************************/
@@ -74,20 +87,20 @@ static void dead_netbios_entry(struct subnet_record *d,
           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)
+               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)
                                {
@@ -97,24 +110,24 @@ static void dead_netbios_entry(struct subnet_record *d,
                                         */
                                        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
@@ -122,7 +135,7 @@ static void dead_netbios_entry(struct subnet_record *d,
                 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);
@@ -133,7 +146,7 @@ static void dead_netbios_entry(struct subnet_record *d,
          }
          break;
        }
-  
+
        case NAME_REGISTER:
        {
          /* if no response received, and we are using a broadcast registration
@@ -145,14 +158,14 @@ static void dead_netbios_entry(struct subnet_record *d,
          {
                /* 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
@@ -160,12 +173,12 @@ static void dead_netbios_entry(struct subnet_record *d,
                   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 */
@@ -181,8 +194,8 @@ static void dead_netbios_entry(struct subnet_record *d,
   ****************************************************************************/
 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)
+                           int nb_flags,BOOL bcast,BOOL recurse,
+                           struct in_addr to_ip)
 {
   struct packet_struct p;
   struct nmb_packet *nmb = &p.packet.nmb;
@@ -204,9 +217,7 @@ static void initiate_netbios_packet(uint16 *id,
 
   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;
+  update_name_trn_id();
 
   if (*id == 0xffff) *id = name_trn_id; /* allow resending with same id */
 
@@ -409,7 +420,7 @@ void queue_netbios_pkt_wins(struct subnet_record *d,
 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)
+                               BOOL bcast,BOOL recurse, struct in_addr ip)
 {
   struct response_record *n;
        
@@ -476,19 +487,24 @@ void queue_netbios_packet(struct subnet_record *d,
 /****************************************************************************
   find a response in a subnet's name query response list. 
   **************************************************************************/
-struct response_record *find_response_record(struct subnet_record *d,
+struct response_record *find_response_record(struct subnet_record **d,
                                uint16 id)
-{   
+{  
   struct response_record *n;
 
   if (!d) return NULL;
 
-  for (n = d->responselist; n; n = n->next)
+  for ((*d) = subnetlist; (*d); (*d) = (*d)->next)
+  {
+    for (n = (*d)->responselist; n; n = n->next)
     {
-      if (n->response_id == id)        {
-       return n;
+      if (n->response_id == id) {
+         return n;
       }
     }
+  }
+
+  *d = NULL;
 
   return NULL;
 }
@@ -724,11 +740,13 @@ BOOL send_mailslot_reply(char *mailslot,int fd,char *buf,int len,char *srcname,
 
   bzero((char *)&p,sizeof(p));
 
+  update_name_trn_id();
+
   dgram->header.msg_type = 0x11; /* DIRECT GROUP DATAGRAM */
   dgram->header.flags.node_type = M_NODE;
   dgram->header.flags.first = True;
   dgram->header.flags.more = False;
-  dgram->header.dgm_id = name_trn_id++;
+  dgram->header.dgm_id = name_trn_id;
   dgram->header.source_ip = src_ip;
   dgram->header.source_port = DGRAM_PORT;
   dgram->header.dgm_length = 0; /* let build_dgram() handle this */
index 7b72f93952a079e369107b41c5ef51f9f55b3dff..557bad73c3cc900d9d1aacef6a7c50b16daf4e26 100644 (file)
@@ -121,26 +121,28 @@ void remove_name(struct subnet_record *d, struct name_record *n)
 
 
 /****************************************************************************
-  find a name in a namelist 
+  find a name in a namelist.
   **************************************************************************/
 static struct name_record *find_name(struct name_record *n,
                        struct nmb_name *name,
                        int search, struct in_addr ip)
 {
-  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;
-      
+         
+                       /* zero ip is either samba's ip or a way of finding a
+                          name without needing to know the ip address */
                        if (zero_ip(ip) || ip_equal(ip, ret->ip))
                        {
-      return ret;
-    }
+                               return ret;
+                       }
                }
        }
     return NULL;
@@ -159,7 +161,7 @@ static struct name_record *find_name_search(struct subnet_record **d,
                        int search, struct in_addr ip)
 {
        if (d == NULL) return NULL; /* bad error! */
-  
+       
     if ((search & FIND_LOCAL) == FIND_LOCAL)
        {
                if (*d != NULL)
@@ -169,8 +171,8 @@ static struct name_record *find_name_search(struct subnet_record **d,
         else
         {
                        DEBUG(4,("local find_name_search with a NULL subnet pointer\n"));
-  return NULL;
-}
+            return NULL;
+               }
        }
 
        if ((search & FIND_WINS) != FIND_WINS) return NULL;
@@ -223,7 +225,7 @@ void dump_names(void)
         fstring data;
 
       /* XXXX i have little imagination as to how to output nb_flags as
-         anything other than a hexadecimal number :-) */
+         anything other than as a hexadecimal number :-) */
 
         sprintf(data, "%s#%02x %s %ld %2x",
               n->name.name,n->name.name_type, /* XXXX ignore the scope for now */
@@ -238,7 +240,7 @@ void dump_names(void)
       DEBUG(3,("%s %15s TTL=%15d NBFLAGS=%2x\n",
               namestr(&n->name),
               inet_ntoa(n->ip),
-              n->death_time?n->death_time-t:0,
+           n->death_time?n->death_time-t:0,
               n->nb_flags));
     }
 
@@ -366,7 +368,7 @@ void remove_netbios_name(struct subnet_record *d,
   /* if it's not a special browser name, search the WINS database */
   if (type != 0x01 && type != 0x1d && type != 0x1e)
     search |= FIND_WINS;
-  
+
   make_nmb_name(&nn, name, type, scope);
   n = find_name_search(&d, &nn, search, ip);
   
@@ -434,7 +436,10 @@ struct name_record *add_netbios_entry(struct subnet_record *d,
     n = n2;
   }
 
-  if (ttl) n->death_time = time(NULL)+ttl*3;
+  if (ttl)
+     n->death_time = time(NULL)+ttl*3;
+  n->refresh_time = time(NULL)+GET_TTL(ttl);
+
   n->ip = ip;
   n->nb_flags = nb_flags;
   n->source = source;
@@ -453,6 +458,10 @@ struct name_record *add_netbios_entry(struct subnet_record *d,
   ****************************************************************************/
 void remove_name_entry(struct subnet_record *d, 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
+      name from its local-subnet name database. */
+
   if (lp_wins_support())
     {
       /* we are a WINS server. */
@@ -466,7 +475,7 @@ void remove_name_entry(struct subnet_record *d, char *name,int type)
       /* not a WINS server: cannot just remove our own names: we have to
          ask permission from the WINS server, or if no reply is received,
                 _then_ we can remove the name */
-      
+
          struct name_record n;
          struct name_record *n2=NULL;
       
@@ -508,16 +517,23 @@ void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
   /* always add our own entries */
   add_netbios_entry(d,name,type,nb_flags,0,SELF,ipzero,False,lp_wins_support());
 
+  /* 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
+     regarding the point about M-nodes. */
+
   if (!lp_wins_support())
-    {
-      /* we aren't supporting WINS: register name using broadcast or
-         contact WINS server */
+  {
+    /* samba isn't supporting WINS itself: register the name using broadcast
+       or with another WINS server.
+       XXXX note: we may support WINS and also know about other WINS servers
+       in the future.
+     */
       
-      queue_netbios_pkt_wins(d,ClientNMB,
+    queue_netbios_pkt_wins(d,ClientNMB,
                                 re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
                             name, type, nb_flags, GET_TTL(0),
                             False, True, ipzero);
-    }
+  }
 }
 
 
@@ -530,12 +546,13 @@ void add_my_names(void)
   struct subnet_record *d;
 
   struct in_addr ip = ipzero;
-  
-  /* each subnet entry, including the WINS one, must have its own
-     netbios name. */
-  /* XXXX if there was a transport layer added to samba (ipx/spx, netbeui
-     etc) then there would be yet _another_ for-loop, this time on the
-     transport type */
+
+  /* each subnet entry, including WINS pseudo-subnet, has SELF names */
+
+  /* XXXX if there was a transport layer added to samba (ipx/spx etc) then
+     there would be yet _another_ for-loop, this time on the transport type
+   */
+
   for (d = subnetlist; d; d = d->next)
   {
        add_my_name_entry(d, myname,0x20,NB_ACTIVE);
@@ -548,11 +565,11 @@ void add_my_names(void)
        add_netbios_entry(d,"__SAMBA__",0x00,NB_ACTIVE,0,SELF,ip,False,wins);
 
     if (wins) {
-    /* the 0x1c name gets added by any WINS server it seems */
+       /* the 0x1c name gets added by any WINS server it seems */
          add_my_name_entry(d, my_workgroup(),0x1c,NB_ACTIVE|NB_GROUP);
+    }
   }
 }
-}
 
 
 /****************************************************************************
@@ -560,21 +577,24 @@ void add_my_names(void)
   **************************************************************************/
 void remove_my_names()
 {
-  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)
-    {
-      if (n->source == SELF)
+       for (d = subnetlist; d; d = d->next)
        {
-         /* get all SELF names removed from the WINS server's database */
-                 remove_name_entry(d,n->name.name, n->name.name_type);
+               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);
+                       }
                }
        }
-    }
 }
 
 
@@ -583,17 +603,31 @@ void remove_my_names()
   ******************************************************************/
 void refresh_my_names(time_t t)
 {
-  static time_t lasttime = 0;
-
-  if (t - lasttime < REFRESH_TIME) 
-    return;
-  lasttime = t;
+  struct subnet_record *d;
 
-  add_my_names();
+  for (d = subnetlist; d; d = d->next)
+  {
+    struct name_record *n;
+         
+       for (n = d->namelist; n; n = n->next)
+    {
+      /* each SELF name has an individual time to be refreshed */
+      if (n->source == SELF && n->refresh_time < time(NULL))
+      {
+        add_my_name_entry(d,n->name.name,n->name.name_type,n->nb_flags);
+      }
+    }
+  }
 }
 
 /*******************************************************************
   queries names occasionally. an over-cautious, non-trusting WINS server!
+
+  this function has been added because nmbd could be restarted. it
+  is generally a good idea to check all the names that have been
+  reloaded from file.
+
+  XXXX which names to poll and which not can be refined at a later date.
   ******************************************************************/
 void query_refresh_names(void)
 {
@@ -652,34 +686,34 @@ void query_refresh_names(void)
   ******************************************************************/
 void expire_names(time_t t)
 {
-  struct name_record *n;
-  struct name_record *next;
+       struct name_record *n;
+       struct name_record *next;
        struct subnet_record *d;
-  
-  /* expire old names */
+
+       /* 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)
-       {
-         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 (n->death_time && n->death_time < t)
+               {
+                 DEBUG(3,("Removing dead name %s\n", namestr(&n->name)));
+                 
+                 next = n->next;
+                 
+                 if (n->prev) n->prev->next = n->next;
+                 if (n->next) n->next->prev = n->prev;
+                 
                  if (d->namelist == n) d->namelist = n->next; 
-         
-         free(n);
-       }
-      else
-       {
-         next = n->next;
+                 
+                 free(n);
+               }
+                 else
+               {
+                 next = n->next;
+               }
+               }
        }
-    }
-}
 }
 
 
@@ -703,9 +737,9 @@ void response_name_release(struct subnet_record *d, struct packet_struct *p)
       putip((char*)&found_ip,&nmb->answers->rdata[2]);
       
       if (ismyip(found_ip))
-       {
+      {
            remove_netbios_name(d,name,type,SELF,found_ip);
-       }
+         }
     }
   else
     {
@@ -720,8 +754,8 @@ void response_name_release(struct subnet_record *d, struct packet_struct *p)
 
 
 /****************************************************************************
-  reply to a name release
-  ****************************************************************************/
+reply to a name release
+****************************************************************************/
 void reply_name_release(struct packet_struct *p)
 {
   struct nmb_packet *nmb = &p->packet.nmb;
@@ -738,7 +772,7 @@ void reply_name_release(struct packet_struct *p)
   putip((char *)&ip,&nmb->additional->rdata[2]);  
   
   DEBUG(3,("Name release on name %s rcode=%d\n",
-          namestr(&nmb->question.question_name),rcode));
+          namestr(&nmb->question.question_name),rcode));
   
   if (!(d = find_req_subnet(p->ip, bcast)))
   {
@@ -773,7 +807,7 @@ void reply_name_release(struct packet_struct *p)
   
   /* Send a NAME RELEASE RESPONSE */
   reply_netbios_packet(p,nmb->header.name_trn_id,
-                      rcode,opcode,True,
+                          rcode,opcode,True,
                       &nmb->question.question_name,
                       nmb->question.question_type,
                       nmb->question.question_class,
@@ -783,8 +817,8 @@ void reply_name_release(struct packet_struct *p)
 
 
 /****************************************************************************
-  response for a reg request received
-  **************************************************************************/
+response for a reg request received
+**************************************************************************/
 void response_name_reg(struct subnet_record *d, struct packet_struct *p)
 {
   struct nmb_packet *nmb = &p->packet.nmb;
@@ -820,9 +854,9 @@ void response_name_reg(struct subnet_record *d, struct packet_struct *p)
          been rejected: e.g if it was our GROUP(1d) name, we must unbecome
          a master browser. */
        
-               if (!(work = find_workgroupstruct(d, name, False))) return;
+        remove_netbios_name(d,name,type,SELF,ipzero);
 
-        /* remove_netbios_name(d,name,type,SELF,ipzero); */
+               if (!(work = find_workgroupstruct(d, name, False))) return;
 
                if (AM_MASTER(work) && (type == 0x1d || type == 0x1b))
                {
@@ -837,8 +871,8 @@ void response_name_reg(struct subnet_record *d, struct packet_struct *p)
 
 
 /****************************************************************************
-  reply to a reg request
-  **************************************************************************/
+reply to a reg request
+**************************************************************************/
 void reply_name_reg(struct packet_struct *p)
 {
   struct nmb_packet *nmb = &p->packet.nmb;
@@ -848,7 +882,7 @@ void reply_name_reg(struct packet_struct *p)
   char *qname = question->name;
   int name_type  = question->name_type;
   int name_class = nmb->question.question_class;
-  
   BOOL bcast = nmb->header.nm_flags.bcast;
   
   int ttl = GET_TTL(nmb->additional->ttl);
@@ -856,7 +890,7 @@ void reply_name_reg(struct packet_struct *p)
   BOOL group = NAME_GROUP(nb_flags);
   int rcode = 0;  
   int opcode = nmb->header.opcode;  
-  
+
   struct subnet_record *d = NULL;
   struct name_record *n = NULL;
   BOOL success = True;
@@ -895,19 +929,19 @@ void reply_name_reg(struct packet_struct *p)
   n = find_name_search(&d, question, search, from_ip);
   
   if (n)
-    {
-      if (!group) /* unique names */
+  {
+    if (!group) /* unique names */
        {
          if (n->source == SELF || NAME_GROUP(n->nb_flags))
-           {
+         {
              /* no-one can register one of samba's names, nor can they
                 register a name that's a group name as a unique name */
              
              rcode = 6;
              success = False;
-           }
+         }
          else if(!ip_equal(ip, n->ip))
-           {
+         {
              /* hm. this unique name doesn't belong to them. */
              
              /* XXXX rfc1001.txt says:
@@ -931,6 +965,11 @@ void reply_name_reg(struct packet_struct *p)
                 for checking with current owner of name, then getting back
                 to us... IF current owner no longer owns the unique name */
              
+           /* XXXX please note also that samba cannot cope with 
+              _receiving_ such redirecting, non-secured registration
+              packets. code to do this needs to be added.
+            */
+
              rcode = 0;
              success = False;
              recurse = False;
@@ -944,21 +983,21 @@ void reply_name_reg(struct packet_struct *p)
                 name_class = ?;
                 XXXX sorry, guys: i really can't see what name_type
                 and name_class should be set to according to rfc1001 */
-           }
+         }
          else
-           {
+         {
              n->ip = ip;
              n->death_time = ttl?p->timestamp+ttl*3:0;
              DEBUG(3,("%s owner: %s\n",namestr(&n->name),inet_ntoa(n->ip)));
-           }
+         }
        }
-      else
+    else
        {
          /* refresh the name */
          if (n->source != SELF)
-           {
+         {
              n->death_time = ttl?p->timestamp + ttl*3:0;
-           }
+         }
        }
 
     /* XXXX bug reported by terryt@ren.pc.athabascau.ca */
@@ -968,15 +1007,21 @@ void reply_name_reg(struct packet_struct *p)
     if (n->source == DNSFAIL)
       n->source = REGISTER;
 
-    }
+  }
   else
-    {
+  {
       /* add the name to our name/subnet, or WINS, database */
       n = add_netbios_entry(d,qname,name_type,nb_flags,ttl,REGISTER,ip,
                                True,!bcast);
-    }
+  }
   
-  if (bcast) return;
+  /* if samba owns a unique name on a subnet, then it must respond and
+     disallow the attempted registration. if the registration is
+     successful by broadcast, only then is there no need to respond
+     (implicit registration: see rfc1001.txt 15.2.1).
+   */
+
+  if (bcast || !success) return;
   
   rdata[0] = nb_flags;
   rdata[1] = 0;
@@ -993,8 +1038,8 @@ void reply_name_reg(struct packet_struct *p)
 
 
 /****************************************************************************
-  reply to a name status query
-  ****************************************************************************/
+reply to a name status query
+****************************************************************************/
 void reply_name_status(struct packet_struct *p)
 {
   struct nmb_packet *nmb = &p->packet.nmb;
@@ -1014,16 +1059,16 @@ void reply_name_status(struct packet_struct *p)
                        inet_ntoa(p->ip)));
     return;
   }
-  
+
   DEBUG(3,("Name status for name %s %s\n",
-          namestr(&nmb->question.question_name), inet_ntoa(p->ip)));
+          namestr(&nmb->question.question_name), inet_ntoa(p->ip)));
   
   n = find_name_search(&d, &nmb->question.question_name,
                                FIND_SELF|FIND_LOCAL,
                                p->ip);
   
   if (!n) return;
-    
+  
   /* XXXX hack, we should calculate exactly how many will fit */
   bufend = &rdata[MAX_DGRAM_SIZE] - 18;
   countptr = buf = rdata;
@@ -1040,7 +1085,7 @@ void reply_name_status(struct packet_struct *p)
       /* start with first bit of putting info in buffer: the name */
       
       bzero(buf,18);
-      sprintf(buf,"%-15.15s",n->name.name);
+         sprintf(buf,"%-15.15s",n->name.name);
       strupper(buf);
       
       /* now check if we want to exclude other workgroup names
@@ -1062,7 +1107,7 @@ void reply_name_status(struct packet_struct *p)
       
       names_added++;
     }
-    
+  
   SCVAL(countptr,0,names_added);
   
   /* XXXXXXX we should fill in more fields of the statistics structure */
@@ -1079,7 +1124,7 @@ void reply_name_status(struct packet_struct *p)
   
   /* Send a POSITIVE NAME STATUS RESPONSE */
   reply_netbios_packet(p,nmb->header.name_trn_id,
-                      0,0,True,
+                          0,0,True,
                       &nmb->question.question_name,
                       nmb->question.question_type,
                       nmb->question.question_class,
@@ -1107,7 +1152,7 @@ struct name_record *search_for_name(struct subnet_record **d,
   n = find_name_search(d,question,search,ip);
   
   if (*d == NULL) return NULL;
-  
+
   /* now try DNS lookup. */
   if (!n)
     {
@@ -1186,7 +1231,7 @@ with directed name queries:
       a negative response, a positive response, or a wait-for-acknowledgement
       packet, and then later on a pos/neg response.
 
-  ****************************************************************************/
+****************************************************************************/
 void reply_name_query(struct packet_struct *p)
 {
   struct nmb_packet *nmb = &p->packet.nmb;
@@ -1253,55 +1298,59 @@ void reply_name_query(struct packet_struct *p)
   }
 
   if (success && (n = search_for_name(&d,question,p->ip,p->timestamp, search)))
-    {
+  {
       /* don't respond to broadcast queries unless the query is for
-        a name we own or it is for a Primary Domain Controller name */
+         a name we own or it is for a Primary Domain Controller name */
 
       if (bcast && n->source != SELF && name_type != 0x1b) {
-         if (!lp_wins_proxy() || same_net(p->ip,n->ip,*iface_nmask(p->ip))) {
-           /* never reply with a negative response to broadcast queries */
-           return;
+           if (!lp_wins_proxy() || same_net(p->ip,n->ip,*iface_nmask(p->ip))) {
+             /* never reply with a negative response to broadcast queries */
+             return;
+           }
          }
-       }
-
+      
       /* name is directed query, or it's self, or it's a PDC type name, or
             we're replying on behalf of a caller because they are on a different
          subnet and cannot hear the broadcast. XXXX lp_wins_proxy should be
                 switched off in environments where broadcasts are forwarded */
 
+      /* XXXX note: for proxy servers, we should forward the query on to
+         another WINS server if the name is not in our database, or we are
+         not a WINS server ourselves
+       */
       ttl = n->death_time - p->timestamp;
       retip = n->ip;
       nb_flags = n->nb_flags;
-    }
+  }
   else
-    {
+  {
       if (bcast) return; /* never reply negative response to bcasts */
       success = False;
-    }
-
+  }
+  
   /* if the IP is 0 then substitute my IP */
   if (zero_ip(retip)) retip = *iface_ip(p->ip);
-  
+
   if (success)
-    {
+  {
       rcode = 0;
       DEBUG(3,("OK %s\n",inet_ntoa(retip)));      
-    }
+  }
   else
-    {
+  {
       rcode = 3;
       DEBUG(3,("UNKNOWN\n"));      
-    }
+  }
   
   if (success)
-    {
+  {
       rdata[0] = nb_flags;
       rdata[1] = 0;
       putip(&rdata[2],(char *)&retip);
-    }
+  }
   
   reply_netbios_packet(p,nmb->header.name_trn_id,
-                      rcode,0,True,
+                          rcode,0,True,
                       &nmb->question.question_name,
                       nmb->question.question_type,
                       nmb->question.question_class,
@@ -1332,7 +1381,7 @@ static void response_server_check(struct nmb_name *ans_name,
 /****************************************************************************
   response from a name status check. commands of type NAME_STATUS_MASTER_CHECK
   and NAME_STATUS_CHECK 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)
@@ -1345,18 +1394,18 @@ static void response_name_status_check(struct in_addr ip,
 
        if (interpret_node_status(d,nmb->answers->rdata,
                                  &name,0x1d,serv_name,ip,bcast))
-    {
+       {
                if (*serv_name)
                {
                        sync_server(n->cmd_type,serv_name,
                                    name.name,name.name_type, n->to_ip);
-    }
-  }
+               }
+       }
        else
        {
                DEBUG(1,("No 0x1d name type in interpret_node_status()\n"));
-  }
-  }
+       }
+}
 
 
 /****************************************************************************
@@ -1369,7 +1418,14 @@ static void response_name_query_sync(struct nmb_packet *nmb,
 {
        DEBUG(4, ("Name query at %s ip %s - ",
                  namestr(&n->name), inet_ntoa(n->to_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];
@@ -1377,6 +1433,14 @@ static void response_name_query_sync(struct nmb_packet *nmb,
 
                putip((char*)&found_ip,&nmb->answers->rdata[2]);
 
+               if (!ip_equal(n->ip, found_ip))
+               {
+                       /* someone gave us the wrong ip as a reply. oops. */
+                       DEBUG(4,("expected ip: %s\n", inet_ntoa(n->ip)));
+                       DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip)));
+                       return;
+               }
+
                DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
 
                if (n->cmd_type == NAME_QUERY_SYNC)
@@ -1388,12 +1452,12 @@ static void response_name_query_sync(struct nmb_packet *nmb,
                                sync_browse_lists(d, work, ans_name->name, ans_name->name_type,
                                                        found_ip);
                        }
-  }
+               }
                else
                {
-                       /* update our netbios name list */
+                       /* 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),STATUS_QUERY,
+                                                               nb_flags,GET_TTL(0),REGISTER,
                                                                found_ip,False,!bcast);
                }
        }
@@ -1408,6 +1472,8 @@ static void response_name_query_sync(struct nmb_packet *nmb,
                           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->ip);
                }
        }
 }
@@ -1416,7 +1482,7 @@ static void response_name_query_sync(struct nmb_packet *nmb,
   report the response record type
   ****************************************************************************/
 static void debug_rr_type(int rr_type)
-    {
+{
   switch (rr_type)
   {
       case NMB_STATUS: DEBUG(3,("Name status ")); break;
@@ -1446,7 +1512,7 @@ static void debug_cmd_type(int cmd_type)
     case NAME_QUERY_CONFIRM      : DEBUG(4,("NAME_QUERY_CONFIRM\n")); break;
     case NAME_QUERY_SYNC         : DEBUG(4,("NAME_QUERY_SYNC\n")); break;
     default: break;
-    }
+  }
 }
 
 /****************************************************************************
@@ -1456,39 +1522,39 @@ static void debug_cmd_type(int cmd_type)
   ****************************************************************************/
 static BOOL response_problem_check(struct response_record *n,
                        struct nmb_packet *nmb, char *qname)
-    {
+{
   switch (nmb->answers->rr_type)
-             {
+  {
     case NMB_REL:
     {
         if (n->num_msgs > 1)
         {
             DEBUG(1,("more than one release name response received!\n"));
             return True;
-             }
+        }
         break;
-         }
+    }
 
     case NMB_REG:
-         {
+    {
         if (n->num_msgs > 1)
         {
             DEBUG(1,("more than one register name response received!\n"));
             return True;
-         }
-       break;
-      }
-      
+        }
+        break;
+    }
+
     case NMB_QUERY:
-      {
+    { 
       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 */
@@ -1501,7 +1567,7 @@ static BOOL response_problem_check(struct response_record *n,
                /* this may cause problems for some early versions of nmbd */
 
                switch (n->cmd_type)
-                 {
+               {
                        case NAME_QUERY_MST_SRV_CHK:
                 case NAME_QUERY_SRV_CHK:
                 case NAME_QUERY_MST_CHK:
@@ -1521,17 +1587,17 @@ static BOOL response_problem_check(struct response_record *n,
                }
                DEBUG(3,("Unique Name conflict detected!\n"));
                           return True;
+                       }
                  }
-             }
-           else
-             {
+                 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;
-             }
-         }
+                 }
+       }
     }
   }
   return False;
@@ -1542,7 +1608,7 @@ static BOOL response_problem_check(struct response_record *n,
   ****************************************************************************/
 static BOOL response_compatible(struct response_record *n,
                        struct nmb_packet *nmb)
-         {
+{
   switch (n->cmd_type)
   {
     case NAME_RELEASE:
@@ -1551,19 +1617,19 @@ static BOOL response_compatible(struct response_record *n,
                {
                        DEBUG(1,("Name release reply has wrong answer rr_type\n"));
                        return False;
-         }
-       break;
-      }
-      
+               }
+        break;
+    }
+
     case NAME_REGISTER:
-      {
+    {
                if (nmb->answers->rr_type != NMB_REG)
-         {
+               {
                        DEBUG(1,("Name register reply has wrong answer rr_type\n"));
                        return False;
                }
         break;
-         }
+    }
 
     case NAME_QUERY_CONFIRM:
     case NAME_QUERY_SYNC:
@@ -1572,30 +1638,30 @@ 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"));
+               if (nmb->answers->rr_type != NMB_QUERY)
+               {
+                       DEBUG(1,("Name query reply has wrong answer rr_type\n"));
                        return False;
-         }
-       break;
-      }
+               }
+               break;
+    }
       
     case NAME_STATUS_MASTER_CHECK:
     case NAME_STATUS_CHECK:
-      {
+    {
                if (nmb->answers->rr_type != NMB_STATUS)
-         {
+               {
                        DEBUG(1,("Name status reply has wrong answer rr_type\n"));
                        return False;
                }
                break;
     }
-           
+      
     default:
     {
                DEBUG(0,("unknown command received in response_netbios_packet\n"));
                break;
-         }
+    }
   }
   return True;
 }
@@ -1609,7 +1675,7 @@ static void response_process(struct subnet_record *d, struct packet_struct *p,
                                BOOL bcast, struct nmb_name *ans_name)
 {
   switch (n->cmd_type)
-         {
+  {
     case NAME_RELEASE:
     {
         response_name_release(d, p);
@@ -1620,15 +1686,15 @@ static void response_process(struct subnet_record *d, struct packet_struct *p,
     {
                response_name_reg(d, p);
         break;
-         }
-       
+    }
+
     case NAME_QUERY_MST_SRV_CHK:
     case NAME_QUERY_SRV_CHK:
     case NAME_QUERY_FIND_MST:
     {
                response_server_check(ans_name, n, d);
-       break;
-      }
+               break;
+    }
       
     case NAME_STATUS_MASTER_CHECK:
     case NAME_STATUS_CHECK:
@@ -1654,11 +1720,11 @@ static void response_process(struct subnet_record *d, struct packet_struct *p,
     }
 
     default:
-      {
-       DEBUG(0,("unknown command received in response_netbios_packet\n"));
-       break;
-      }
+    {
+               DEBUG(0,("unknown command received in response_netbios_packet\n"));
+               break;
     }
+  }
 }
 
 
@@ -1675,9 +1741,21 @@ static void response_netbios_packet(struct packet_struct *p)
   struct response_record *n;
   struct subnet_record *d = NULL;
 
-  if (!(d = find_req_subnet(p->ip, bcast)))
+  if (!(n = find_response_record(&d,nmb->header.name_trn_id))) {
+    DEBUG(2,("unknown netbios response (received late or from nmblookup?)\n"));
+    return;
+  }
+
+  if (!d)
+  {
+    DEBUG(2,("response packet: subnet %s not known\n", inet_ntoa(p->ip)));
+    return;
+  }
+
+  if (!same_net(d->bcast_ip, d->mask_ip, p->ip)) /* copes with WINS 'subnet' */
   {
-    DEBUG(3,("response packet: bcast %s not known\n", inet_ntoa(p->ip)));
+    DEBUG(2,("response from %s. ", inet_ntoa(p->ip)));
+    DEBUG(2,("expected on subnet %s. hmm.\n", inet_ntoa(d->bcast_ip)));
     return;
   }
 
@@ -1693,11 +1771,6 @@ static void response_netbios_packet(struct packet_struct *p)
   DEBUG(3,("response for %s from %s (bcast=%s)\n",
           namestr(ans_name), inet_ntoa(p->ip), BOOLSTR(bcast)));
   
-  if (!(n = find_response_record(d,nmb->header.name_trn_id))) {
-    DEBUG(2,("unknown netbios response (received late or from nmblookup?)\n"));
-    return;
-  }
-
   debug_rr_type(nmb->answers->rr_type);
 
   n->num_msgs++; /* count number of responses received */
@@ -1728,22 +1801,22 @@ void process_nmb(struct packet_struct *p)
   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)
+    {
+         if (nmb->header.response)
          {
            switch (nmb->question.question_type)
              {
@@ -1755,7 +1828,7 @@ void process_nmb(struct packet_struct *p)
              }
            return;
          }
-       else if (nmb->header.qdcount>0) 
+      else if (nmb->header.qdcount>0) 
          {
            switch (nmb->question.question_type)
              {
@@ -1776,8 +1849,8 @@ void process_nmb(struct packet_struct *p)
       }
       
     case NMB_REL:
-      {
-       if (nmb->header.qdcount==0 || nmb->header.arcount==0)
+    {
+      if (nmb->header.qdcount==0 || nmb->header.arcount==0)
          {
            DEBUG(2,("netbios release packet rejected\n"));
            break;
@@ -1787,8 +1860,8 @@ void process_nmb(struct packet_struct *p)
          response_netbios_packet(p); /* response to reply dealt with in here */
        else
          reply_name_release(p);
-       break;
-      }
+      break;
     }
+  }
 }