diff -urP ../../samba-tng-alpha.2.5.3/source/Makefile.in ./Makefile.in
--- ../../samba-tng-alpha.2.5.3/source/Makefile.in	Tue May  2 13:09:17 2000
+++ ./Makefile.in	Fri May 26 10:28:24 2000
@@ -80,6 +80,13 @@
 # The current codepage definition list.
 CODEPAGELIST= 437 737 775 850 852 861 932 866 949 950 936 1251 ISO8859-1 ISO8859-2 ISO8859-5 ISO8859-7 koi8-r
 
+# Set this option if you don't want smbdnbfw to accept connection
+# for every name, except for its own one.
+# Note: NetBIOS aliases are _NOT_ checked
+# Note: This option makes no difference in smbd
+#
+STRICT_NETBIOS_NAME_CHECKING = -DSTRICT_NETBIOS_NAME_CHECKING
+
 # where you are going to have the smbrun binary. This defaults to the 
 # install directory. This binary is needed for correct printing
 # and magic script execution. This should be an absolute path!
@@ -112,9 +119,9 @@
 FLAGS5 = $(FLAGS1) $(FLAGS2) $(FLAGS3) $(FLAGS4) -DHAVE_INCLUDES_H
 FLAGS  = $(FLAGS5) $(PASSWD_FLAGS)
 
-SPROGS = bin/smbd bin/lsarpcd bin/svcctld bin/spoolssd bin/samrd \
+SPROGS = bin/smbd bin/smbdnbfw bin/lsarpcd bin/svcctld bin/spoolssd bin/samrd \
          bin/srvsvcd bin/wkssvcd bin/browserd bin/netlogond bin/winregd \
-         bin/nmbd bin/swat
+         bin/nmbd bin/nmbdnbfw bin/swat
 PROGS1 = bin/smbclient bin/testparm bin/testprns bin/smbrun bin/smbstatus 
 PROGS2 = bin/rpcclient bin/smbpasswd bin/make_smbcodepage bin/make_unicodemap 
 PROGS3 = bin/regedit bin/samedit bin/net bin/svccontrol bin/cmdat bin/ntspool
@@ -131,9 +138,11 @@
 ######################################################################
 
 SAMBALIB = bin/libsamba.la
+SAMBALIBNBFW = bin/libsambanbfw.la
 UBIQXLIB = bin/libubiqx.la
 SMBLIB = bin/libsmb.la
 NMBLIB = bin/libnmb.la
+NMBLIBNBFW = bin/libnmbnbfw.la
 MSRPCLIB = bin/libmsrpc.la
 SMBPWLIB = bin/libsmbpw.la
 SAMRPASSLIB = bin/libsamrpass.la
@@ -145,8 +154,10 @@
 
 SAMBA_LIBS = $(MSRPCLIB) $(SMBLIB) $(NMBLIB) $(SAMBALIB)
 
+SAMBANBFW_LIBS = $(MSRPCLIB) $(SMBLIB) $(NMBLIB) $(SAMBALIBNBFW)
+
 SHARED_LIBS = $(SAMBA_LIBS) $(SMBPWLIB) $(UBIQXLIB) \
-		$(SAM_PWDB_LIB) $(LIBSURS)
+		$(SAM_PWDB_LIB) $(LIBSURS) $(SAMBALIBNBFW) $(NMBLIBNBFW)
 
 LIBSTATUS_OBJ = lib/util_status.o 
 
@@ -167,6 +178,23 @@
 		lib/interfaces.o \
 		tdb/tdb.o tdb/tdbutil.o
 
+LIBNBFW_OBJ =	lib/charcnv.o lib/charset.o lib/debug.o lib/fault.o \
+		lib/getsmbpass.o lib/interface-fw.o  lib/kanji.o lib/md4.o \
+		lib/pidfile.o lib/replace.o \
+		lib/signal.o lib/getopt.o lib/slprintf.o \
+		lib/fsusage.o lib/system.o lib/doscalls.o \
+		lib/time.o lib/ufc.o lib/util.o lib/substitute.o \
+		lib/genrand.o lib/username.o \
+		lib/access.o lib/smbrun.o \
+		lib/bitmap.o lib/util_sid.o lib/snprintf.o \
+		lib/util_str.o lib/util_unistr.o lib/util_wunistr.o \
+		lib/util_file.o \
+		lib/util_sock.o lib/util_sec.o lib/util_array.o \
+		lib/talloc.o \
+		lib/ms_fnmatch.o \
+		lib/interfaces.o \
+		tdb/tdb.o tdb/tdbutil.o
+
 STUB_UID_OBJ = lib/stub_uid.o
 
 UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
@@ -176,8 +204,11 @@
 
 LIBSAMBA_OBJ = $(PARAM_OBJ) $(LIB_OBJ)
 
+LIBSAMBANBFW_OBJ = $(PARAM_OBJ) $(LIBNBFW_OBJ)
+
 LIBNMB_OBJ = libsmb/namequery.o libsmb/nmblib.o libsmb/unexpected.o
 
+LIBNMBNBFW_OBJ = libsmb/namequery.o libsmb/nmblib-fw.o libsmb/unexpected.o
 
 LIBSMB_OBJ = libsmb/clientgen.o libsmb/clidomain.o \
 	libsmb/clifile.o libsmb/cliprint.o libsmb/clierror.o \
@@ -280,6 +311,19 @@
 		smbd/challenge.o  lib/util_pwdb.o smbd/afsticket.o \
 		printing/printfsp.o
 
+SMBDNBFW_OBJ1 = smbd/smbdnbfw.o smbd/smbd-fw.o smbd/files.o smbd/connection.o \
+		lib/set_uid.o smbd/dfree.o smbd/dir.o smbd/password.o \
+		smbd/conn.o smbd/fileio.o \
+		smbd/statcache.o \
+		smbd/ipc.o smbd/lanman.o smbd/mangle.o smbd/negprot.o \
+		smbd/message.o smbd/nttrans.o smbd/pipes.o \
+		smbd/$(QUOTAOBJS) smbd/reply.o smbd/ssl.o smbd/trans2.o \
+		smbd/uid.o smbd/dosmode.o smbd/filename.o smbd/open.o \
+		smbd/close.o smbd/blocking.o smbd/process-fw.o smbd/oplock.o \
+		smbd/service.o smbd/error.o smbd/vfs.o smbd/vfs-wrap.o \
+		smbd/challenge.o  lib/util_pwdb.o smbd/afsticket.o \
+		printing/printfsp.o
+
 
 PRINTING_OBJ =  printing/pcap.o printing/print_svid.o \
 		printing/print_cups.o printing/load.o
@@ -367,6 +411,16 @@
 
 SMBD_LIBS = $(SAMBA_LIBS) $(UBIQXLIB) $(LIBSURS)
 
+SMBDNBFW_OBJ = $(SMBDNBFW_OBJ1) $(MSDFS_OBJ) $(UNIXPASSDB_OBJ) \
+           $(RPC_SERVER_OBJ) \
+           lib/domain_namemap.o \
+           $(LOCKING_OBJ) \
+           $(SIDDB_OBJ) \
+		$(LIBSTATUS_OBJ) $(PRINTING_OBJ) $(PRINTBACKEND_OBJ) \
+		$(PROFILE_OBJ)
+
+SMBDNBFW_LIBS = $(SAMBANBFW_LIBS) $(UBIQXLIB) $(LIBSURS)
+
 SRVSVCD_OBJ = $(MSRPCD_OBJ) $(SRVSVCD_OBJ1) \
            $(RPC_SRVUTIL_OBJ) \
            $(PROFILE_OBJ)  \
@@ -461,6 +515,24 @@
 NMBD_OBJ = $(NMBD_OBJ1) 
 NMBD_LIBS = $(SMBLIB) $(NMBLIB) $(SAMBALIB) $(UBIQXLIB)
 
+
+NMBDNBFW_OBJ1 = nmbd/asyncdns.o nmbd/nmbdnbfw.o nmbd/nmbd-fw.o nmbd/nmbd_become_dmb.o \
+            nmbd/nmbd_become_lmb.o nmbd/nmbd_browserdb.o \
+            nmbd/nmbd_browsesync.o nmbd/nmbd_elections.o \
+            nmbd/nmbd_incomingdgrams.o nmbd/nmbd_incomingrequests.o \
+            nmbd/nmbd_lmhosts.o nmbd/nmbd_logonnames.o nmbd/nmbd_mynames.o \
+            nmbd/nmbd_namelistdb.o nmbd/nmbd_namequery.o \
+            nmbd/nmbd_nameregister.o nmbd/nmbd_namerelease.o \
+            nmbd/nmbd_nodestatus.o nmbd/nmbd_packets.o \
+            nmbd/nmbd_processlogon.o nmbd/nmbd_responserecordsdb.o \
+            nmbd/nmbd_sendannounce.o nmbd/nmbd_serverlistdb.o \
+            nmbd/nmbd_subnetdb.o nmbd/nmbd_winsproxy.o nmbd/nmbd_winsserver.o \
+            nmbd/nmbd_workgroupdb.o nmbd/nmbd_synclists.o
+
+NMBDNBFW_OBJ = $(NMBDNBFW_OBJ1)
+NMBDNBFW_LIBS = $(SMBLIB) $(NMBLIBNBFW) $(SAMBALIBNBFW) $(UBIQXLIB)
+
+
 SWAT_OBJ = web/cgi.o web/diagnose.o web/startstop.o web/statuspage.o \
            web/swat.o libsmb/passchange.o $(LOCKING_OBJ) \
            rpc_server/srv_lookup.o \
@@ -693,7 +765,7 @@
 		$(LIBSMB_OBJ) $(SMBWRAPPER_OBJ) \
 		$(GROUPDB_OBJ) $(PASSDB_OBJ) $(SAMPASSDB_OBJ) \
 		$(SMBPASSWD_OBJ) $(SIDDB_OBJ) \
-		$(RPC_SRVUTIL_OBJ)
+		$(RPC_SRVUTIL_OBJ) nmbd/nmbd-fw.o nmbd/smbd-fw.o
 
 SMBWRAPPERPICOBJS = $(SMBWRAPPER_OBJ:.o=.po)
 SMBWRAPPERPICOBJS32 = $(SMBWRAPPER_OBJ:.o=.po32)
@@ -713,8 +785,12 @@
 
 LIBSAMBA_LTOBJS = $(LIBSAMBA_OBJ:.o=.lo)
 
+LIBSAMBANBFW_LTOBJS = $(LIBSAMBANBFW_OBJ:.o=.lo)
+
 LIBNMB_LTOBJS = $(LIBNMB_OBJ:.o=.lo)
 
+LIBNMBNBFW_LTOBJS = $(LIBNMBNBFW_OBJ:.o=.lo)
+
 LIBSMB_LTOBJS = $(LIBSMB_OBJ:.o=.lo)
 
 LIBMSRPC_LTOBJS = $(RPC_CLIENT_OBJ:.o=.lo) $(RPC_PARSE_OBJ:.o=.lo)
@@ -761,6 +837,8 @@
 
 libsamba : CHECK $(SAMBALIB)
 
+libsambanbfw : CHECK $(SAMBANBFWLIB)
+
 libubiqx : CHECK $(UBIQXLIB)
 
 smbwrapper : CHECK bin/smbsh bin/smbwrapper.so @WRAP32@
@@ -852,6 +930,77 @@
 @MAINT@	  <.deps/$@ >.deps/$@d && \
 @MAINT@	rm -f .deps/$@ && : >.deps/.stamp
 	@mv $*.po32.o $@
+
+
+# Start netbiosfw rules
+#
+nmbd/nmbd-fw.o: nmbd/nmbd-fw.c
+	@echo Compiling nmbd-fw.c to nmbd-fw.o
+	@$(CC) -I. -I$(srcdir) $(FLAGS) -DNETBIOSFW -o nmbd/nmbd-fw.o -c nmbd/nmbd-fw.c
+
+nmbd/nmbdnbfw.o: nmbd/nmbd.c
+	@echo Compiling nmbd.c to nmbdnbfw.o
+	@$(CC) -I. -I$(srcdir) $(FLAGS) -DNETBIOSFW -c nmbd/nmbd.c -o nmbd/nmbdnbfw.o
+
+smbd/smbd-fw.o: smbd/smbd-fw.c
+	@echo Compiling smbd-fw.c to smbd-fw.o
+	@$(CC) -I. -I$(srcdir) $(FLAGS) -DNETBIOSFW -o smbd/smbd-fw.o -c smbd/smbd-fw.c
+
+smbd/process-nbfw.o: smbd/process.c
+	@echo Compiling process.c to process-nbfw.o
+	@$(CC) -I. -I$(srcdir) $(FLAGS) -DNETBIOSFW $(STRICT_NETBIOS_NAME_CHECKING) -c smbd/process.c -o smbd/process-nbfw.o
+
+smbd/process-fw.o: smbd/process.c
+	@echo Compiling process.c to process-fw.o
+	@$(CC) -I. -I$(srcdir) $(FLAGS) -DNETBIOSFW $(STRICT_NETBIOS_NAME_CHECKING) -c smbd/process.c -o smbd/process-fw.o
+
+smbd/smbdnbfw.o: smbd/server.c
+	@echo Compiling server.c to smbdnbfw.o
+	@$(CC) -I. -I$(srcdir) $(FLAGS) -DNETBIOSFW -c smbd/server.c -o smbd/smbdnbfw.o
+
+libsmb/nbfw-lib.o: libsmb/nmblib.c
+	@echo Compiling nmblib.c to nbfw-lib.o
+	@$(CC) -I. -I$(srcdir) $(FLAGS) -DNETBIOSFW -c libsmb/nmblib.c -o libsmb/nbfw-lib.o
+
+libsmb/nmblib-fw.lo: libsmb/nmblib.c
+	@echo Compiling libsmb/nmblib.c with libtool to libsmb/nmblib-fw.lo
+	@$(LIBTOOL) --mode=compile \
+	  $(CC) -I. -I$(srcdir) $(FLAGS) -DNETBIOSFW -c libsmb/nmblib.c \
+	  -o libsmb/nmblib-fw.lo
+
+lib/interface-fw.o: lib/interface.c
+	@echo Compiling interface.c to interface-fw.o
+	@$(CC) -I. -I$(srcdir) $(FLAGS) -DNETBIOSFW -c lib/interface.c -o lib/interface-fw.o
+
+lib/interface-fw.lo: lib/interface.c
+	@echo Compiling lib/interface.c with libtool to lib/interface-fw.lo
+	@$(LIBTOOL) --mode=compile \
+	  $(CC) -I. -I$(srcdir) $(FLAGS) -DNETBIOSFW -c lib/interface.c \
+	  -o lib/interface-fw.lo
+
+bin/nmbdnbfw: $(NMBDNBFW_LIBS) $(NMBDNBFW_OBJ) bin/.dummy
+	@echo Linking $@
+	@$(LINK) -o $@ $(NMBDNBFW_OBJ) $(NMBDNBFW_LIBS) $(LIBS)
+
+bin/smbdnbfw: $(SMBDNBFW_LIBS) $(SMBDNBFW_OBJ) bin/.dummy
+	@echo Linking $@
+	@$(LINK) -o $@ $(SMBDNBFW_OBJ) $(SMBDNBFW_LIBS) $(LIBS)
+
+bin/libsambanbfw.la: $(LIBSAMBANBFW_LTOBJS) bin/.dummy
+	@echo Linking shared library $@
+	@$(LINK) -o $@ -rpath $(LIBDIR) -version-info 0:1:0 \
+	  $(LIBSAMBANBFW_LTOBJS)
+
+bin/libnmbnbfw.la: $(LIBNMBNBFW_LTOBJS) bin/.dummy
+	@echo Linking shared library $@
+	@$(LINK) -o $@ -rpath $(LIBDIR) -version-info 0:1:0 \
+	  $(LIBNMBNBFW_LTOBJS)
+
+# End netbiosfw rules
+#
+
+
+
 
 bin/.dummy:
 	@if (: >> $@ || : > $@) >/dev/null 2>&1; then :; else \
diff -urP ../../samba-tng-alpha.2.5.3/source/configure ./configure
--- ../../samba-tng-alpha.2.5.3/source/configure	Mon May  1 02:41:22 2000
+++ ./configure	Wed May 24 14:55:52 2000
@@ -2945,6 +2945,56 @@
 fi
 done
 
+#
+# NBfW: check if header-files are available to automatically configure
+# port-forwarding. Supported linux kernels 2.0.3x and 2.2.x .
+#
+case "$host_os" in
+    *linux*)
+		for ac_hdr in linux/ip_fw.h linux/ip_masq.h
+do
+ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
+echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
+echo "configure:2357: checking for $ac_hdr" >&5
+if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
+  echo $ac_n "(cached) $ac_c" 1>&6
+else
+  cat > conftest.$ac_ext <<EOF
+#line 2362 "configure"
+#include "confdefs.h"
+#include <$ac_hdr>
+EOF
+ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
+{ (eval echo configure:2367: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
+ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
+if test -z "$ac_err"; then
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=yes"
+else
+  echo "$ac_err" >&5
+  echo "configure: failed program was:" >&5
+  cat conftest.$ac_ext >&5
+  rm -rf conftest*
+  eval "ac_cv_header_$ac_safe=no"
+fi
+rm -f conftest*
+fi
+if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
+  echo "$ac_t""yes" 1>&6
+    ac_tr_hdr=HAVE_`echo $ac_hdr | sed 'y%abcdefghijklmnopqrstuvwxyz./-%ABCDEFGHIJKLMNOPQRSTUVWXYZ___%'`
+  cat >> confdefs.h <<EOF
+#define $ac_tr_hdr 1
+EOF
+ 
+else
+  echo "$ac_t""no" 1>&6
+fi
+done
+
+    ;;
+esac
+#
+#
 
 echo $ac_n "checking size of int""... $ac_c" 1>&6
 echo "configure:2951: checking size of int" >&5
diff -urP ../../samba-tng-alpha.2.5.3/source/configure.in ./configure.in
--- ../../samba-tng-alpha.2.5.3/source/configure.in	Fri Apr 14 08:37:18 2000
+++ ./configure.in	Wed May 24 14:55:52 2000
@@ -218,6 +218,18 @@
 # For experimental utmp support
 AC_CHECK_HEADERS(utmp.h utmpx.h)
 
+#
+# NBfW: check if header-files are available to automatically configure
+# port-forwarding. Supported linux kernels 2.0.3x and 2.2.x .
+#
+case "$host_os" in
+    *linux*)
+		AC_CHECK_HEADERS(linux/ip_fw.h linux/ip_masq.h)
+    ;;
+esac
+#
+#
+
 AC_CHECK_SIZEOF(int,cross)
 AC_CHECK_SIZEOF(long,cross)
 AC_CHECK_SIZEOF(short,cross)
diff -urP ../../samba-tng-alpha.2.5.3/source/include/config.h.in ./include/config.h.in
--- ../../samba-tng-alpha.2.5.3/source/include/config.h.in	Fri Mar 31 05:14:52 2000
+++ ./include/config.h.in	Wed May 24 14:55:52 2000
@@ -719,6 +719,12 @@
 /* Define if you have the <limits.h> header file.  */
 #undef HAVE_LIMITS_H
 
+/* Define if you have the <linux/ip_fw.h> header file.  */
+#undef HAVE_LINUX_IP_FW_H
+
+/* Define if you have the <linux/ip_masq.h> header file.  */
+#undef HAVE_LINUX_IP_MASQ_H
+
 /* Define if you have the <memory.h> header file.  */
 #undef HAVE_MEMORY_H
 
diff -urP ../../samba-tng-alpha.2.5.3/source/include/nameserv.h ./include/nameserv.h
--- ../../samba-tng-alpha.2.5.3/source/include/nameserv.h	Thu Apr 20 06:48:21 2000
+++ ./include/nameserv.h	Wed May 24 14:55:52 2000
@@ -26,8 +26,12 @@
 
 /* NTAS uses 2, NT uses 1, WfWg uses 0 */
 #define MAINTAIN_LIST    2
-#define ELECTION_VERSION 1
 
+/* WinNT uses 0x010F, Win95 uses 0x0415 */
+/* Highest wins, but not Win95 ... */
+#define ELECTION_VERSION 0x010F
+#define ELECTION_VERSION_WIN95 0x0415
+ 
 #define MAX_DGRAM_SIZE (576) /* tcp/ip datagram limit is 576 bytes */
 #define MIN_DGRAM_SIZE 12
 
diff -urP ../../samba-tng-alpha.2.5.3/source/include/nbfw.h ./include/nbfw.h
--- ../../samba-tng-alpha.2.5.3/source/include/nbfw.h	Thu Jan  1 01:00:00 1970
+++ ./include/nbfw.h	Wed May 24 14:55:52 2000
@@ -0,0 +1,109 @@
+/*
+	 NetBIOS masquerading forwarding routines
+   Version 0.40
+      
+   include/nbfw.h
+      
+   Copyright (C) Jasper van der Neut 1998,1999,2000
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+            
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+                        
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+                                 
+            
+   See CHANGES for revision history.
+
+*/
+               
+               
+struct net_addr
+{
+	struct in_addr	ip;
+	struct in_addr	retarget_ip;
+	struct net_addr	*next;
+	int             retarget_port;
+};
+
+struct net_addr_group
+{
+	struct in_addr        ip;
+	struct in_addr        subnet;
+	struct in_addr	      nmask;
+	struct in_addr        bcast;
+	struct net_addr_group *next;
+	struct net_addr	      *addresses;
+	int                   masquerade;
+};
+
+struct deny_addr
+{
+	struct in_addr   ip;
+	struct deny_addr *next;
+};
+
+struct name_list
+{
+  struct name_list  *next;
+  char              name[17];
+};
+
+struct fwd_req_list
+{
+	struct in_addr sender_addr;
+	time_t         ttl;
+	int            tid;
+	int            sender_port;
+	
+	struct fwd_req_list *next;
+	struct nmb_name     sender_name;
+};
+	
+
+#if defined (PORTFW_LINUX_2_0) || defined (PORTFW_LINUX_2_2)
+
+#define IP_FW_PORTFW            6
+
+#define IP_FW_BASE_CTL          64      /* base for firewall socket options */
+
+#define IP_FW_COMMAND           0x00FF  /* mask for command without chain */
+#define IP_FW_TYPE              0x0300  /* mask for type (chain) */
+#define IP_FW_SHIFT             8       /* shift count for type (chain) */
+ 
+
+#define IP_FW_APPEND            (IP_FW_BASE_CTL+1)
+#define IP_FW_DELETE            (IP_FW_BASE_CTL+2)
+#define IP_FW_MASQ_CTL          (IP_FW_BASE_CTL+12)
+
+
+#define IP_PORTFW_ADD           (IP_FW_APPEND | (IP_FW_PORTFW << IP_FW_SHIFT))
+#define IP_PORTFW_DEL           (IP_FW_DELETE | (IP_FW_PORTFW << IP_FW_SHIFT))
+#define IP_PORTFW_FLUSH         (IP_FW_FLUSH  | (IP_FW_PORTFW << IP_FW_SHIFT))
+
+
+#define IP_PORTFW_PORT_MIN 1
+#define IP_PORTFW_PORT_MAX 60999
+
+struct ip_portfw {
+  struct ip_portfw *next;
+  u_int32_t           laddr, raddr;
+  u_int16_t           lport, rport;
+};
+                        
+struct ip_portfw_edits {
+  u_int16_t           protocol;       /* Which protocol are we talking? */
+  u_int32_t           laddr, raddr;   /* Remote address */
+  u_int16_t           lport, rport;   /* Local and remote port */
+  u_int16_t           dummy;          /* Make up to multiple of 4 */
+};
+
+#endif
diff -urP ../../samba-tng-alpha.2.5.3/source/include/proto.h ./include/proto.h
--- ../../samba-tng-alpha.2.5.3/source/include/proto.h	Tue May  2 13:09:26 2000
+++ ./include/proto.h	Wed May 24 14:55:52 2000
@@ -296,6 +296,9 @@
 
 /*The following definitions come from  lib/interface.c  */
 
+void load_nbfw_interface(void);
+void unload_nbfw_interface(void);
+void control_forwards(int state);
 void load_interfaces(void);
 BOOL interfaces_changed(void);
 BOOL ismyip(struct in_addr ip);
@@ -1466,6 +1469,12 @@
 		     struct name_record **n);
 void kill_async_dns_child(void);
 
+/*The following definitions come from  nmbd/nmbd-fw.c  */
+
+void expire_forwarded_requests(time_t t);
+int forward_nmb(struct packet_struct *p);
+int forward_dgram(struct packet_struct *p);
+
 /*The following definitions come from  nmbd/nmbd.c  */
 
 
@@ -1628,6 +1637,8 @@
 
 /*The following definitions come from  nmbd/nmbd_packets.c  */
 
+int find_subnet_fd_for_address( struct in_addr local_ip );
+int find_subnet_mailslot_fd_for_address( struct in_addr local_ip );
 uint16 get_nb_flags(char *buf);
 void set_nb_flags(char *buf, uint16 nb_flags);
 struct response_record *queue_register_name( struct subnet_record *subrec,
@@ -1796,6 +1807,10 @@
 
 /*The following definitions come from  param/loadparm.c  */
 
+char *lp_nbfw_netbios_names(void);
+char *lp_nbfw_backend_hosts(void);
+char *lp_nbfw_deny_hosts(void);
+
 void lp_talloc_free(void);
 char *lp_logfile(void);
 char *lp_smbrun(void);
@@ -4102,6 +4117,10 @@
 				char *password, int pwlen,
 				char *dev,uint16 vuid, int *ecode);
 void close_cnum(connection_struct *conn, uint16 vuid);
+
+/*The following definitions come from  smbd/smbd-fw.c  */
+
+BOOL find_ip_in_forward_list(struct in_addr *ip, unsigned int *port);
 
 /*The following definitions come from  smbd/ssl.c  */
 
diff -urP ../../samba-tng-alpha.2.5.3/source/include/smb.h ./include/smb.h
--- ../../samba-tng-alpha.2.5.3/source/include/smb.h	Tue May  2 13:09:28 2000
+++ ./include/smb.h	Wed May 24 14:55:52 2000
@@ -45,7 +45,9 @@
 #endif
 
 /* limiting size of ipc replies */
-#define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
+/* A larger size seems to improve smbd(nbfw)'s stability with
+   _large_ browselists (16kB or more). */
+#define REALLOC(ptr,size) Realloc(ptr,MAX((size),8*1024))
 
 #define SIZEOFWORD 2
 
@@ -1591,11 +1593,15 @@
 /* Version 4.20 - To indicate that nmbd and browsing now works better */
 
 #define DEFAULT_MAJOR_VERSION 0x04
-#define DEFAULT_MINOR_VERSION 0x00
+#define DEFAULT_MINOR_VERSION 0x03
 
 /* Browser Election Values */
-#define BROWSER_ELECTION_VERSION	0x010f
-#define BROWSER_CONSTANT	0xaa55
+#define BROWSER_ELECTION_VERSION_NT    0x010f
+#define BROWSER_ELECTION_VERSION_WIN95 0x0415
+#define BROWSER_CONSTANT               0xaa55
+#define BROWSER_ANNDOMAIN_CONSTANT 0x00000000
+#define BROWSER_ANNDOMAIN_TYPE     0x80402000
+ 
 
 /* NT Flags2 bits - cifs6.txt section 3.1.2 */
 
diff -urP ../../samba-tng-alpha.2.5.3/source/lib/interface.c ./lib/interface.c
--- ../../samba-tng-alpha.2.5.3/source/lib/interface.c	Mon May  1 02:41:32 2000
+++ ./lib/interface.c	Fri May 26 09:33:57 2000
@@ -28,6 +28,34 @@
 
 extern int DEBUGLEVEL;
 
+#ifdef NETBIOSFW
+
+#undef PORTFW
+#undef PORTFW_LINUX_2_0
+#undef PORTFW_LINUX_2_2
+
+#ifdef HAVE_LINUX_IP_FW_H
+#define PORTFW
+#define	PORTFW_LINUX_2_0
+#endif
+
+#ifdef HAVE_LINUX_IP_MASQ_H
+#include <linux/ip_masq.h>
+#define PORTFW
+#undef  PORTFW_LINUX_2_0
+#define PORTFW_LINUX_2_2
+#endif
+
+#include "nbfw.h"
+
+struct net_addr_group	*group_list = NULL;
+struct deny_addr	*deny_list = NULL;
+struct name_list	*nbfw_name_list = NULL;
+
+int forwarding_on = 0;
+
+#endif
+
 struct in_addr ipzero;
 struct in_addr allones_ip;
 struct in_addr loopback_ip;
@@ -223,6 +251,386 @@
 	}
 }
 
+#ifdef NETBIOSFW
+
+/****************************************************************************
+	Determine if a subnet is a backend subnet
+****************************************************************************/
+static int is_backend_interface(struct interface *interface)
+{
+	struct in_addr subnet;
+	
+	subnet.s_addr = htonl(interface->ip.s_addr) >> 16;
+	
+	if (subnet.s_addr == 0xC0A8) {
+		return (1);
+	} else {
+		subnet.s_addr = subnet.s_addr >> 4;
+		if (subnet.s_addr == 0xAC1) {
+			return (1);
+		} else {
+			subnet.s_addr = subnet.s_addr >> 4;
+			if (subnet.s_addr == 0x0A) {
+				return (1);
+			} else {
+				return (0);
+			}
+		}
+	}
+	return (0);
+}
+
+/****************************************************************************
+	Setup the NBfW interface structure
+****************************************************************************/
+static void make_firewalls(struct interface *interfaces, struct net_addr_group **addr_group)
+{
+	struct net_addr_group *group_new = NULL;
+	struct net_addr_group *group_last = NULL;
+	struct interface *iface = NULL;
+	
+	for (iface = interfaces; iface != NULL; iface = iface->next) {
+		if ((group_new = (struct net_addr_group *) malloc(sizeof(struct net_addr_group))) == NULL) {
+			DEBUG(0, ("Malloc failed\n"));
+			exit(1);
+		}
+		group_new->next = NULL;
+		group_new->addresses = NULL;
+		group_new->masquerade = is_backend_interface(iface);
+		group_new->ip = iface->ip;
+		group_new->subnet.s_addr = iface->ip.s_addr & iface->nmask.s_addr;
+		group_new->nmask = iface->nmask;
+		group_new->bcast = iface->bcast;
+		
+		if (!(*addr_group)) {
+			(*addr_group) = group_new;
+		} else {
+			group_last->next = group_new;
+		}
+		
+		group_last = group_new;
+		
+		DEBUG(2,("Added NBfW ip=%s ",inet_ntoa(group_new->ip)));
+		DEBUG(2,("subnet=%s ",inet_ntoa(group_new->subnet)));
+		DEBUG(2,("bcast=%s ",inet_ntoa(group_new->bcast)));
+		DEBUG(2,("nmask=%s ",inet_ntoa(group_new->nmask)));
+		DEBUG(2,("masquerade=%d\n", group_new->masquerade));
+	}
+}
+
+/****************************************************************************
+	Add backend hosts to the NBfW interface structure
+****************************************************************************/
+static void interpret_backend_hosts(char *s, struct net_addr_group *addr_group)
+{
+	char *ptr;
+	fstring token;
+	
+	struct in_addr ip;
+	struct in_addr subnet;
+	struct net_addr_group *firewall = NULL;
+	struct net_addr *addr = NULL;
+	
+	ptr = s;
+	
+	while (next_token(&ptr,token,NULL,sizeof(token))) {
+		ip = *interpret_addr2(token);
+		
+		for (firewall = addr_group; firewall; firewall = firewall->next) {
+			subnet.s_addr = ip.s_addr & firewall->nmask.s_addr;
+			
+			if (ip_equal(subnet, firewall->subnet)) {
+				if (!firewall->masquerade) {
+					DEBUG(0, ("Backend host not on masqueraded network\n"));
+					DEBUGADD(0, ("Exiting ..."));
+					exit(1);
+				} else {
+					forwarding_on = 1;
+				}
+				
+				if (ip_equal(ip, firewall->bcast)) {
+					continue;
+				}
+				
+				if (firewall->addresses == NULL) {
+					firewall->addresses = (struct net_addr *) malloc(sizeof(struct net_addr));
+					if (firewall->addresses == NULL) {
+						return;
+					}
+						
+					firewall->addresses->ip = ip;
+					firewall->addresses->next = NULL;
+					
+					DEBUG(2, ("Added %s to backend list\n", inet_ntoa(firewall->addresses->ip)));
+					continue;
+				} else {
+					for (addr = firewall->addresses; addr; addr = addr->next) {
+						if (ip_equal(ip, addr->ip)) {
+							break;
+						}
+					
+						if (addr->next == NULL)	{
+							addr->next = (struct net_addr *) malloc(sizeof(struct net_addr));
+							if (!addr->next) {
+								return;
+							}
+						
+							addr->next->ip = ip;
+							addr->next->next = NULL;
+
+							DEBUG(2, ("Added %s to backend list\n", inet_ntoa(addr->next->ip)));
+							break;
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
+/****************************************************************************
+	Add denied hosts to the NBfW structure
+****************************************************************************/
+static void interpret_deny_hosts(char *s, struct deny_addr **deny_list)
+{
+	char *ptr;
+	fstring token;
+	
+	struct in_addr ip;
+	struct deny_addr *last_deny = NULL;
+	
+	ptr = s;
+	
+	while (next_token(&ptr,token,NULL,sizeof(token))) {
+		ip = *interpret_addr2(token);
+		
+		if (!(*deny_list)) {
+			*deny_list = (struct deny_addr *) malloc(sizeof(struct deny_addr));
+			if ((*deny_list) == NULL) {
+				return;
+			}
+			
+			last_deny = *deny_list;
+		} else {
+			last_deny->next = (struct deny_addr *) malloc(sizeof(struct deny_addr));
+			if (last_deny->next == NULL) {
+				return;
+			}
+			last_deny = last_deny->next;
+		}
+		last_deny->ip = ip;
+		last_deny->next = NULL;
+	
+		DEBUG(2, ("Added %s to deny list\n", inet_ntoa(ip)));
+	}
+}
+
+
+/****************************************************************************
+	Add forwarded names to the NBfW structure
+****************************************************************************/
+static void read_nbfw_netbios_names(char *s, struct name_list **nbfw_name_list)
+{
+	char *ptr;
+	pstring nbname;
+	struct name_list *last_name = NULL;
+	
+	ptr = s;
+
+	while (next_token(&ptr, nbname, NULL, sizeof(nbname))) {
+		strupper(nbname);
+		
+		if (!(*nbfw_name_list)) {
+			*nbfw_name_list = (struct name_list *) malloc(sizeof(struct name_list));
+			if ((*nbfw_name_list) == NULL) {
+				return;
+			}
+			
+			last_name = *nbfw_name_list;
+			
+		} else {
+			last_name->next = (struct name_list *) malloc(sizeof(struct name_list));
+			if ((last_name->next) == NULL) {
+				return;
+			}
+    		    	last_name = last_name->next;
+		}
+	
+		safe_strcpy(last_name->name, nbname, sizeof(last_name->name));
+		last_name->next = NULL;
+    
+		DEBUG(2, ("Added %s to netbios forwarded list\n", nbname));
+	}
+}
+
+void load_nbfw_interface(void)
+{
+	make_firewalls(local_interfaces, &group_list);
+	interpret_backend_hosts(lp_nbfw_backend_hosts(), group_list);
+	interpret_deny_hosts(lp_nbfw_deny_hosts(), &deny_list);
+	read_nbfw_netbios_names(lp_nbfw_netbios_names(), &nbfw_name_list);
+}
+
+void unload_nbfw_interface(void)
+{
+	struct net_addr_group *firewall = NULL;
+	struct net_addr_group *firewall_next = NULL;
+	struct net_addr *addr = NULL;
+	struct net_addr *addr_next = NULL;
+	struct deny_addr *deny = NULL;
+	struct deny_addr *deny_next = NULL;
+	struct name_list *name = NULL;
+	struct name_list *name_next = NULL;
+
+	for (firewall = group_list; firewall; firewall = firewall_next) {
+		for (addr = firewall->addresses ; addr; addr = addr_next) {
+			addr_next = addr->next;
+			free(addr);	
+		}
+		firewall_next = firewall->next;
+		free(firewall);
+	}
+	group_list = NULL;
+	
+	for (deny = deny_list; deny; deny = deny_next) {
+		deny_next = deny->next;
+		free(deny);
+	}
+	deny_list = NULL;
+
+	for (name = nbfw_name_list; name; name = name_next) {
+		name_next = name->next;
+		free(name);
+	}
+	nbfw_name_list = NULL;
+}
+
+
+/****************************************************************************
+  This function sets the kernel forwarding rules.
+  It will add one entry for every non-masquerading subnet to
+  every masqueraded host. This can be a lot of entries ;)
+  Every masqueraded host will have its own port on the firewall which
+  we forward in the kernel. When remote clients try to connect to port 139
+  of the firewall, we check the called name and send a Session Retarget
+  Response telling these client to use another port.
+****************************************************************************/
+
+void control_forwards(int state)
+{
+
+#ifdef PORTFW
+
+#ifdef PORTFW_LINUX_2_0
+	struct ip_portfw_edits pfw;
+#endif
+
+#ifdef PORTFW_LINUX_2_2
+	struct ip_masq_ctl masq;
+#define pfw masq.u.portfw_user
+#endif
+
+	struct net_addr_group *firewall;
+	struct net_addr_group *firewall_2;
+	struct net_addr *addr;
+  
+	int sockportfw;
+
+#else
+	DEBUG(0, ("Smbdnbfw did not setup port forwarding, because it does not know how to do it.\n"));
+	DEBUGADD(0, ("If you have a Linux kernel greater than 2.0.30 this is probably not wat you want.\n"));
+#endif /* PORTFW */
+
+	int firewall_port = 60000;
+
+	/* Scan through all subnets */
+        
+	if (!(state)) {
+		DEBUG(3, ("Resetting forwards\n"));
+	}
+	
+	for (firewall = group_list; firewall; firewall = firewall->next) {
+		if (firewall->masquerade) {
+			/* For all masqueraded hosts */
+			
+			for (addr = firewall->addresses; addr; addr = addr->next) {
+				DEBUG(4, ("Forwarding rules: processing %s\n", inet_ntoa(addr->ip)));
+				
+				for (firewall_2 = group_list; firewall_2; firewall_2 = firewall_2->next) {
+					/* For every firewall address on a non-masqueraded subnet */
+					if (!(firewall_2->masquerade)) {
+						DEBUG(3, ("Forwarding rules: found %s\n", inet_ntoa(firewall_2->ip)));
+#ifdef PORTFW    
+#ifdef PORTFW_LINUX_2_0
+						pfw.protocol = IPPROTO_TCP;
+						pfw.laddr = htonl(firewall_2->ip.s_addr);
+						pfw.lport = firewall_port;
+						
+						if (state) {
+							/* Some host byte order and network byte order fun */
+							pfw.raddr = htonl(addr->ip.s_addr);
+							pfw.rport = 139;
+						} else {
+							pfw.raddr = 0;
+							pfw.rport = 0;
+						}
+#endif
+#ifdef PORTFW_LINUX_2_2
+						memset (&masq, 0, sizeof(masq));
+
+						masq.m_target = IP_MASQ_TARGET_MOD;
+						safe_strcpy(masq.m_tname, "portfw", sizeof(masq.m_tname));
+						masq.m_cmd = ( state ? IP_MASQ_CMD_ADD : IP_MASQ_CMD_DEL);
+
+						pfw.pref = 10;
+						pfw.protocol = IPPROTO_TCP;
+						pfw.laddr = firewall_2->ip.s_addr;
+						pfw.lport = htons(firewall_port);
+						
+						if (state) {
+							/* Even more host byte order and network byte order fun */
+							pfw.raddr = addr->ip.s_addr;
+							pfw.rport = htons(139);
+						} else {
+							pfw.raddr = 0;
+							pfw.rport = 0;
+						}
+#endif
+      
+						if ((sockportfw = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) { 
+							DEBUG(0, ("Socket: could not open RAW : %s\n", strerror(errno)));
+							exit(1);
+						}
+#ifdef PORTFW_LINUX_2_0
+						if (setsockopt(sockportfw, IPPROTO_IP, 
+							      (state ? IP_PORTFW_ADD : IP_PORTFW_DEL), 
+							      (char *) &pfw, sizeof(pfw))) {
+							DEBUG(0, ("Setsockopt ipportfw: could not set options : %s\n", strerror(errno)));
+						}
+#endif           
+#ifdef PORTFW_LINUX_2_2
+						if (setsockopt(sockportfw, IPPROTO_IP, IP_FW_MASQ_CTL, (char *) &masq, sizeof(masq))) {
+							DEBUG(0, ("Setsockopt ipchains: could not set options : %s\n", strerror(errno)));
+						}
+#endif
+						else {
+							DEBUG(2, ("Added retarget port %u from %s for %s\n", firewall_port,
+								inet_ntoa(firewall_2->ip), inet_ntoa(addr->ip)));
+
+							addr->retarget_port = firewall_port;
+							addr->retarget_ip = firewall_2->ip;
+						}
+						close(sockportfw);
+#endif /* PORTFW */
+					}
+				}
+				firewall_port--;
+			}
+		}
+	}
+}
+
+#endif /* NETBIOSFW */
 
 /****************************************************************************
 return True if the list of probed interfaces has changed
diff -urP ../../samba-tng-alpha.2.5.3/source/libsmb/nmblib.c ./libsmb/nmblib.c
--- ../../samba-tng-alpha.2.5.3/source/libsmb/nmblib.c	Thu Apr 20 06:48:33 2000
+++ ./libsmb/nmblib.c	Wed May 24 14:55:52 2000
@@ -23,6 +23,7 @@
 #include "includes.h"
 
 extern int DEBUGLEVEL;
+extern int forwarding_on;
 
 int num_good_sends = 0;
 int num_good_receives = 0;
@@ -747,6 +748,27 @@
 	packet->fd = fd;
 	
 	num_good_receives++;
+	
+#ifdef NETBIOSFW
+	/* packet validated ok, so we do some forwarding */
+	
+	if (forwarding_on) {
+		switch (packet_type) {
+			case NMB_PACKET:
+				if (forward_nmb(packet)) {
+					free_packet(packet);
+					return(NULL);
+				}
+				break;
+			case DGRAM_PACKET:
+				if (forward_dgram(packet)) {
+					free_packet(packet);
+					return(NULL);
+				}
+				break;
+		}
+	}
+#endif
 	
 	DEBUG(5,("Received a packet of len %d from (%s) port %d\n",
 		 length, inet_ntoa(packet->ip), packet->port ) );
diff -urP ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd-fw.c ./nmbd/nmbd-fw.c
--- ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd-fw.c	Thu Jan  1 01:00:00 1970
+++ ./nmbd/nmbd-fw.c	Wed May 24 14:55:52 2000
@@ -0,0 +1,727 @@
+/* 
+   NetBIOS masquerading forwarding
+   Version 0.40
+   
+   nmbd/nmbd-fw.c - NBfW for nmbd
+   
+   Copyright (C) Jasper van der Neut 1998,1999,2000
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+            
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+                       
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+                                 
+   
+   See CHANGES for revision history
+	 											
+*/
+
+#include "includes.h"
+
+#include "nbfw.h"
+
+extern int DEBUGLEVEL;
+
+extern struct net_addr_group *group_list;
+extern struct deny_addr *deny_list;
+extern struct name_list *nbfw_name_list;
+
+static struct fwd_req_list *fwd_reqs = NULL;
+
+extern int ClientDGRAM;
+extern int ClientNMB;
+
+
+/****************************************************************************
+  Update the forwarded request list.
+****************************************************************************/
+
+void expire_forwarded_requests(time_t t)
+{
+	struct fwd_req_list *fwd_req = NULL;
+	struct fwd_req_list *fwd_req_next = NULL;
+
+	for (fwd_req = fwd_reqs; fwd_req; fwd_req = fwd_req_next) {
+		fwd_req_next = fwd_req->next;
+
+		if (fwd_req->ttl <= t) {
+			DEBUG(4, ("Deleting: id %u\n", fwd_req->tid));
+
+			free(fwd_req);
+			fwd_reqs = fwd_req_next;
+		} else {
+			break;
+		}
+	}
+}
+
+/****************************************************************************
+  Add a new record to the forwarded requests list.
+****************************************************************************/
+
+static int add_forwarded_request(struct packet_struct *p, struct nmb_packet *nmb)
+{
+	struct fwd_req_list *fwd_req_new = NULL;
+	struct fwd_req_list *fwd_req = NULL;
+
+	if ((fwd_req_new = malloc(sizeof(struct fwd_req_list))) == NULL) {
+		DEBUG(0, ("Malloc failed\n"));
+		return (0);
+	}
+
+	fwd_req_new->next = NULL;
+	fwd_req_new->tid = nmb->header.name_trn_id;
+	fwd_req_new->sender_addr = p->ip;
+	fwd_req_new->sender_port = p->port;
+	fwd_req_new->ttl = time(NULL) + 10;
+
+	DEBUG(3, ("Added remember-record: id = %u, ip = %s\n", fwd_req_new->tid, inet_ntoa(p->ip)));
+
+	if (fwd_reqs == NULL) {
+		fwd_reqs = fwd_req_new;
+	} else {
+		for (fwd_req = fwd_reqs; fwd_req->next; fwd_req = fwd_req->next);
+		fwd_req->next = fwd_req_new;
+	}
+	return (1);
+}
+
+/****************************************************************************
+  Check if packet came from a good host or subnet. Also check if a packet
+  needs to be masqueraded.
+****************************************************************************/
+
+static int is_from_good_ip(struct in_addr source_addr, struct in_addr *masq_mask, int *masquerade)
+{
+	struct net_addr_group *firewall = NULL;
+	struct net_addr *addr = NULL;
+
+	masq_mask->s_addr = htonl(0xFFFFFFFF);
+	*masquerade = 0;
+
+	for (firewall = group_list; firewall; firewall = firewall->next) {
+		if (ip_equal(firewall->ip, source_addr)) {
+			DEBUG(5, ("Not forwarding our own datagram"));
+			return (0);
+		}
+
+		if (same_net(firewall->ip, source_addr, firewall->nmask)) {
+			/* We found the subnet the datagram came from.
+			   Now check if it came from a host we forward for */
+
+			if (!firewall->addresses) {
+				/* We forward for the whole subnet, check if subnet needs to be masqueraded */
+
+				if ((*masquerade = firewall->masquerade))
+					*masq_mask = firewall->nmask;
+				return (1);
+			} else {
+				/* Check with the address list if the datagram
+				   came from a host we forward for */
+
+				for (addr = firewall->addresses; addr; addr = addr->next) {
+					if (ip_equal(addr->ip, source_addr)) {
+						if ((*masquerade = firewall->masquerade))
+							*masq_mask = firewall->nmask;
+						return (1);
+					}
+				}
+			}
+		}
+	}
+	return (0);
+}
+
+/****************************************************************************
+  Check if packet came from a denied host. To avoid name conflict and
+  broadcast loops when using multiple gateways dump packets from the gateways
+****************************************************************************/
+
+static int is_from_denied_ip(struct in_addr source_addr)
+{
+	struct deny_addr *deny = NULL;
+
+	for (deny = deny_list; deny; deny = deny->next) {
+		if (ip_equal(deny->ip, source_addr))
+			return (1);
+	}
+	return (0);
+}
+
+
+/****************************************************************************
+  Check if name is in the namelist.
+****************************************************************************/
+
+static int is_known_name(struct nmb_name *name)
+{
+	struct name_list *nbfw_name = NULL;
+
+	for (nbfw_name = nbfw_name_list; nbfw_name; nbfw_name = nbfw_name->next) {
+		if (!(strcmp(nbfw_name->name, name->name)))
+			return (1);
+	}
+	return (0);
+}
+
+/****************************************************************************
+  Check if nmb packet came from a good host or subnet.
+****************************************************************************/
+
+static int is_from_good_nmbname(struct nmb_packet *nmb, int masquerade)
+{
+	struct in_addr resolved_addr;
+
+	if (nmb->header.qdcount && nbfw_name_list) {
+		if (!masquerade) {
+			return (is_known_name(&nmb->question.question_name));
+		} else {
+			if (nmb->header.arcount)
+				return (is_known_name(&nmb->question.question_name));
+			else
+				return (1);
+		}
+	} else {
+		if (nmb->header.arcount && masquerade) {
+			if (resolve_name(nmb->question.question_name.name, &resolved_addr, -1)) {
+				switch (nmb->additional->rr_type) {
+				case 0x0001:
+
+					if (!ip_equal(resolved_addr, *((struct in_addr *) &nmb->answers->rdata[0]))) {
+						DEBUG(0, ("Error: packet accepted for forwarding from backend to outside, 
+							   but source name does exist on outside. Please check config\n"));
+						return (0);
+					} else
+						return (1);
+					break;
+
+				case 0x0020:
+
+					if (!ip_equal(resolved_addr, *((struct in_addr *) &nmb->answers->rdata[2]))) {
+						DEBUG(0, ("Error: packet accepted for forwarding from backend to outside, 
+							   but source name does exist on outside. Please check config\n"));
+						return (0);
+					} else
+						return (1);
+					break;
+				}
+			} else {
+				DEBUG(0, ("Error: packet accepted for forwarding from backend to outside, 
+					   but source name does not exist on backend\n"));
+				DEBUGADD(0, ("Please check config: program halted.\n"));
+				exit(1);
+			}
+		}
+	}
+	return (1);
+}
+
+
+/****************************************************************************
+  Check if dgram packet came from a good host or subnet.
+****************************************************************************/
+
+static int is_from_good_dgramname(struct dgram_packet *dgram, int masquerade)
+{
+	struct in_addr resolved_addr;
+
+	if (nbfw_name_list) {
+		if (!masquerade) {
+			/* If we don't masquerade we're probably dealing with packets from
+			   the outside to our backend. There's no need to forward packets
+			   if our backend will just drop them */
+
+			return (is_known_name(&dgram->dest_name));
+		} else {
+			/* If we _do_ masquerade forward only the packets which came
+			   form a known netbios name */
+
+			if (is_known_name(&dgram->source_name))
+				return (1);
+			else {
+				DEBUG(0, ("Warning: packet accepted for forwarding from backend to outside, 
+					   but we don't forward for this netbios name. Please check config.\n"));
+				return (0);
+			}
+		}
+	} else {
+		if (masquerade) {
+			/* If we _do_ masquerade forward only the packets which came
+			   form a known netbios name */
+
+			if (resolve_name(dgram->source_name.name, &resolved_addr, -1)) {
+				if (!ip_equal(dgram->header.source_ip, resolved_addr)) {
+					DEBUG(0, ("Error: packet accepted for forwarding from backend to outside, 
+						   but source name does exist on outside.\n"));
+					DEBUGADD(0, ("Please check config, program halted\n"));
+					exit(1);
+				}
+			} else {
+				DEBUG(0, ("Error: packet accepted for forwarding from backend to outside, 
+					   but source name '%s' does not exist on backend\n",
+					   dgram->source_name.name));
+				DEBUGADD(0, ("Please check config, program halted\n"));
+				exit(1);
+			}
+		}
+	}
+	return (1);
+}
+
+
+
+/****************************************************************************
+  Forward nmb packets to/from backend, masquerade if needed.
+  Return 1 if packet is not needed by firewall nmbd anymore.
+****************************************************************************/
+
+int forward_nmb(struct packet_struct *p)
+{
+	struct in_addr masq_mask;
+	struct in_addr from_addr;
+	struct in_addr data_addr;
+
+	struct net_addr_group *firewall;
+	struct net_addr *addr;
+
+	struct fwd_req_list *fwd_req = NULL;
+
+	int masquerade = 0;
+	int offset = 0;
+	int i = 0;
+
+	struct packet_struct *forward_p = NULL;
+	struct nmb_packet *nmb;
+
+
+	if (!(forward_p = copy_packet(p)))
+		return 0;
+
+	forward_p->locked = False;
+	forward_p->fd = ClientNMB;
+
+	from_addr = forward_p->ip;
+	nmb = &(forward_p->packet.nmb);
+
+	if (!is_from_good_ip(from_addr, &masq_mask, &masquerade)) {
+		DEBUG(4, ("Wrong IP: %s\n", inet_ntoa(from_addr)));
+		free_packet(forward_p);
+		return 0;
+	}
+
+	if (is_from_denied_ip(from_addr)) {
+		DEBUG(3, ("Denied IP: %s\n", inet_ntoa(from_addr)));
+		free_packet(forward_p);
+		return 0;
+	}
+
+	if (!is_from_good_nmbname(nmb, masquerade)) {
+		DEBUG(5, ("Wrong name %s\n", nmb->question.question_name.name));
+		free_packet(forward_p);
+		return 0;
+	}
+
+
+	/* Process node status requests */
+
+	if (masquerade && nmb->header.qdcount && nmb->question.question_type == 0x0021) {
+		struct in_addr ToIp;
+
+		DEBUG(3, ("Node status request from %s to %s\n", inet_ntoa(p->ip),
+			   nmb->question.question_name.name));
+
+		if (resolve_name
+			(nmb->question.question_name.name, &ToIp, nmb->question.question_name.name_type)) {
+			DEBUG(4, ("Found destination %s for host request.\n", inet_ntoa(ToIp)));
+
+			if (!add_forwarded_request(forward_p, nmb)) {
+				free_packet(forward_p);
+				return 0;
+			}
+
+			forward_p->ip = ToIp;
+			forward_p->port = NMB_PORT;
+
+			if (!send_packet(forward_p)) {
+				DEBUG(0, ("forward_nmb: Node status request to IP %s port %d failed\n",
+					   inet_ntoa(forward_p->ip), forward_p->port));
+				free_packet(forward_p);
+				return 0;
+			}
+		}
+
+		free_packet(forward_p);
+		return 0;
+	}
+
+
+	/* For every subnet we forward for, except the one where our nmb
+	   came from, masquerade if needed and send. */
+
+	for (firewall = group_list; firewall; firewall = firewall->next) {
+		if (!same_net(firewall->ip, from_addr, firewall->nmask)) {
+			if (masquerade) {
+				/* Check every SECTION type which can have IP-addresses inside.
+				   See RFC1002 for exact details. */
+
+				/* Note: we assume only one section of every type in a packet. 
+				   This because the nmb_packet structure assumes this too. Otherwise
+				   use: for (count = 0; count < nmb->header.arcount; count++) */
+
+
+				/* QDcount section, contains no IP addresses */
+#ifdef NBFWDEBUG
+				if (nmb->header.qdcount) {
+					switch (nmb->question.question_type) {
+					case 0x0020:
+						break;
+
+					case 0x0021:
+						break;
+
+					default:
+
+						DEBUG(0, ("Unknown type %u in question section from %s.\n",
+							   nmb->question.question_type, inet_ntoa(from_addr)));
+					}
+				}
+#endif
+				/* ANcount section */
+
+				if (nmb->header.ancount) {
+					switch (nmb->answers->rr_type) {
+					case 0x000A:
+						break;	/* Assumed WACK opcode to be 0x000A as described
+							   in RFC 1002 (4.2.1.3) although in section 4.2.16
+							   it says 0x020 ... joy */
+
+					case 0x0020:
+
+						offset = 2;
+
+						if (nmb->header.rcode == 0x7 && nmb->header.opcode == 0x5) {
+							/* Name conflict demand, no ip-address in data */
+							SIVAL(nmb->answers->rdata, offset, 0x00000000);
+
+							break;
+						}
+
+						for (i = 0; i < (nmb->answers->rdlength / 6); i++);
+						{
+							data_addr.s_addr = IVAL(&p->packet.nmb.answers->rdata, offset);
+
+							if (same_net(data_addr, from_addr, masq_mask)) {
+								SIVAL(nmb->answers->rdata, offset, firewall->ip.s_addr);
+							} else {
+								DEBUG(1, ("Hmm, funny packets from %s\n", inet_ntoa(from_addr)));
+								free_packet(forward_p);
+								return 0;
+							}
+							offset += 6;
+						}
+
+						break;
+
+					case 0x0021:
+						break;	/* Some hosts may have ip-addresses in the 
+							   node status data. I've only see this on 
+							   one host: mine... Not Yet Implemented */
+
+					default:
+
+						DEBUG(0, ("Unknown packet type from %s\n", inet_ntoa(from_addr)));
+						free_packet(forward_p);
+						return 0;
+					}
+
+				}
+
+
+				/* NScount section, contains no IP-addresses */
+
+#ifdef NBFWDEBUG
+				if (nmb->header.nscount) {
+					switch (nmb->nsrecs->rr_type) {
+					case 0x0002:
+						break;
+
+					default:
+
+						DEBUG(0, ("Unknown type %u in name service section from %s\n",
+							   nmb->nsrecs->rr_type, inet_ntoa(from_addr)));
+						free_packet(forward_p);
+						return 0;
+					}
+				}
+#endif
+
+
+				/* ARcount section */
+
+				if (nmb->header.arcount) {
+					switch (nmb->additional->rr_type) {
+					case 0x0001:
+						offset = 0;
+						break;
+
+					case 0x0020:
+						offset = 2;
+						break;
+
+					default:
+
+						DEBUG(0, ("Unknown type %u in additional section from %s\n",
+							   nmb->additional->rr_type, inet_ntoa(from_addr)));
+						free_packet(forward_p);
+						return 0;
+					}
+
+					data_addr.s_addr = IVAL(&p->packet.nmb.additional->rdata, offset);
+
+					if (same_net(data_addr, from_addr, masq_mask)) {
+						SIVAL(nmb->additional->rdata, offset, firewall->ip.s_addr);
+					} else {
+						DEBUG(1, ("Hmm, funny packets from %s\n", inet_ntoa(from_addr)));
+						free_packet(forward_p);
+						return 0;
+					}
+				}
+			}
+
+
+			/* if (masquerade) */
+			/* Check if it's a request. If so remember the transaction ID and
+			   the senders name and its IP */
+			if (nmb->header.qdcount) {
+				if (!add_forwarded_request(forward_p, nmb)) {
+					free_packet(forward_p);
+					return 0;
+				}
+			}
+
+			/* Check if this packet if for a WINS server */
+			if (we_are_a_wins_client() && nmb->header.qdcount && !nmb->header.nm_flags.bcast) {
+				forward_p->port = NMB_PORT;
+				forward_p->ip = unicast_subnet->myip;
+				forward_p->fd = ClientNMB;
+
+				if (!send_packet(forward_p)) {
+					DEBUG(0, ("forward_nmb: Request to WINS server at IP %s port %d failed\n",
+						   inet_ntoa(forward_p->ip), forward_p->port));
+					free_packet(forward_p);
+					return 0;
+				}
+				break;
+			}
+
+
+			if (nmb->header.response) {
+				DEBUG(3, ("Response to forwarded packet found\n"));
+
+				for (fwd_req = fwd_reqs; fwd_req; fwd_req = fwd_req->next) {
+					if (fwd_req->tid == nmb->header.name_trn_id) {
+						/* Found a record, send response to correct ip */
+						forward_p->ip = fwd_req->sender_addr;
+						forward_p->port = fwd_req->sender_port;
+						forward_p->fd = ClientNMB;
+
+						if (!send_packet(forward_p)) {
+							DEBUG(0, ("forward_nmb: Response to IP %s port %d on socket %d failed\n",
+								   inet_ntoa(forward_p->ip), forward_p->port, forward_p->fd));
+							free_packet(forward_p);
+							return 1;
+						}
+
+						DEBUG(3, ("Forwarded response\n"));
+						free_packet(forward_p);
+						return 1;
+					}
+				}
+
+				/* It's a response, but we have no record for it, 
+				   maybe it's for the firewall itself */
+
+				DEBUG(3, ("Normal response\n"));
+				free_packet(forward_p);
+				return 0;
+			} else {
+				forward_p->port = NMB_PORT;
+				if (firewall->addresses == NULL) {
+					forward_p->ip = firewall->bcast;
+					forward_p->fd = ClientNMB;	/*find_subnet_fd_for_address(firewall->ip); */
+
+					if (!send_packet(forward_p)) {
+						DEBUG(0, ("forward_nmb: Request to IP %s port %d on socket %d failed\n",
+							   inet_ntoa(forward_p->ip), forward_p->port, forward_p->fd));
+						free_packet(forward_p);
+						return 0;
+					}
+				} else {
+					for (addr = firewall->addresses; addr; addr = addr->next) {
+						forward_p->ip = addr->ip;
+						forward_p->fd = ClientNMB;	/*find_subnet_fd_for_address(firewall->ip); */
+
+						if (!send_packet(forward_p)) {
+							DEBUG(0, ("forward_nmb: Request to IP %s port %d on socket %d failed\n",
+								   inet_ntoa(forward_p->ip), forward_p->port, forward_p->fd));
+							continue;
+						}
+					}
+				}
+			}
+		}
+	}
+	free_packet(forward_p);
+
+	if (p->packet.nmb.header.nm_flags.bcast)
+		return 0;
+	else
+		return 1;
+}
+
+
+/****************************************************************************
+  Forward datagram packets to/from backend, masquerade if needed.
+  Return 1 if packet is not needed by firewall nmbd anymore.
+****************************************************************************/
+
+int forward_dgram(struct packet_struct *p)
+{
+	struct in_addr masq_mask;
+	struct in_addr from_addr;
+
+	struct net_addr_group *firewall;
+	struct net_addr *addr;
+
+	struct packet_struct *forward_p = NULL;
+	struct dgram_packet *dgram;
+
+	int masquerade = 0;
+	char *buf;
+
+
+	if (!(forward_p = copy_packet(p)))
+		return;
+
+	forward_p->locked = False;
+	forward_p->fd = ClientDGRAM;
+
+	from_addr = forward_p->ip;
+	dgram = &(forward_p->packet.dgram);
+
+	/* Do some sanity checking */
+	buf = &dgram->data[0];
+	buf -= 4;
+
+	if (CVAL(buf, smb_com) != SMBtrans) {
+		free_packet(forward_p);
+		return 0;
+	}
+	DEBUG(3, ("Opcode = %d\n", CVAL((smb_base(buf) + SVAL(buf, smb_vwv12)), 0)));
+
+
+	if (!ip_equal(from_addr, dgram->header.source_ip)) {
+		/* Dump these silently, apparently old nmbds or nmbd M-nodes
+		   don't fill all the ip field of the datagram .... */
+		DEBUG(3, ("IP mismatch, spoofing !?\n"));
+		free_packet(forward_p);
+		return 0;
+	}
+
+	if (!is_from_good_ip(from_addr, &masq_mask, &masquerade)) {
+		DEBUG(4, ("Wrong IP: %s\n", inet_ntoa(from_addr)));
+		free_packet(forward_p);
+		return 0;
+	}
+
+	if (is_from_denied_ip(from_addr)) {
+		DEBUG(3, ("Denied IP: %s\n", inet_ntoa(from_addr)));
+		free_packet(forward_p);
+		return 0;
+	}
+
+	if (!is_from_good_dgramname(dgram, masquerade)) {
+		DEBUG(3, ("Dropping packet, not forwarding to/from this name\n"));
+		free_packet(forward_p);
+		return 0;
+	}
+
+	/* Browser Elections are _very_ tricky to deal with. Normally if you
+	   run NBfW you should be master browser to serve your backend and 
+	   normal network. But but when 2 people are running NBfW we cannot
+	   have 2 master browsers. To insure a backend host can never ever become
+	   master browser several this must be done:
+	   1. Election packets may never be forwarded / masqueraded _to_ the
+	   outside network
+	   2. Election packets must be forwarded _and_ masqueraded _from_ the
+	   outside to the backend network but ONLY when we are NOT master
+	   browser !
+	 */
+	if (CVAL((smb_base(buf) + SVAL(buf, smb_vwv12)), 0) == ANN_Election) {
+		if (masquerade) {
+			free_packet(forward_p);
+			return 0;
+		} else {
+			if (!lp_local_master)
+				masquerade = 1;
+		}
+	}
+
+	/* For every subnet we forward for, except the one where our datagram
+	   came from, masquerade if needed and send. */
+
+	for (firewall = group_list; firewall; firewall = firewall->next) {
+		if (!same_net(firewall->ip, from_addr, firewall->nmask)) {
+			if (masquerade)
+				dgram->header.source_ip = firewall->ip;
+
+			/* Check if this packet if for a WINS server */
+			if (we_are_a_wins_client() && dgram->header.msg_type == 0x14) {
+				/* The DATAGRAM QUERY TYPE is the only datagram which goes
+				   to a WINS server. The description of the packet and the
+				   return packets is quite vague. Luckily a WINS server may
+				   discard it, so just shuffle it under the carpet */
+
+				free_packet(forward_p);
+				return 0;
+			}
+
+			forward_p->port = DGRAM_PORT;
+			if (firewall->addresses == NULL) {
+				forward_p->ip = firewall->bcast;
+
+/*				forward_p->fd = find_subnet_mailslot_fd_for_address(firewall->ip);*/
+
+				if (!send_packet(forward_p)) {
+					DEBUG(0,  ("forward_dgram: Datagram request to IP %s port %d failed\n",
+						   inet_ntoa(forward_p->ip), forward_p->port));
+					free_packet(forward_p);
+					return 0;
+				}
+			} else {
+				for (addr = firewall->addresses; addr; addr = addr->next) {
+					forward_p->ip = addr->ip;
+
+/*					forward_p->fd = find_subnet_mailslot_fd_for_address(firewall->ip);*/
+
+					if (!send_packet(forward_p)) {
+						DEBUG(0, ("forward_dgram: Datagram request to IP %s port %d failed\n",
+							   inet_ntoa(forward_p->ip), forward_p->port));
+						continue;
+					}
+				}
+			}
+		}
+	}
+	free_packet(forward_p);
+	return 0;
+}
diff -urP ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd.c ./nmbd/nmbd.c
--- ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd.c	Tue May  2 13:09:40 2000
+++ ./nmbd/nmbd.c	Wed May 24 14:55:52 2000
@@ -395,6 +395,14 @@
      */
     expire_names_and_servers(t);
 
+#ifdef NETBIOSFW
+    /*
+     * Expire the entries in the forwardedRequestList if
+     * the ttl has expired
+     */
+     expire_forwarded_requests(t);
+#endif
+
     /*
      * Write out a snapshot of our current browse list into
      * the browse.dat file. This is used by smbd to service
@@ -423,7 +431,9 @@
      * setting of the 'local master' parameter.
      * (nmbd_elections.c)
      */
-    check_master_browser_exists(t);
+    /* Not needed. Clients will start an election when they can't
+       find a master browser */
+    /*  check_master_browser_exists(t);  */
 
     /*
      * If we are configured as a logon server, attempt to
@@ -757,8 +767,16 @@
 
   reopen_logs();
 
+#ifdef NETBIOSFW
+  DEBUG( 1, ( "nmbdnbfw version %s started.\n", VERSION ) );
+#else
   DEBUG( 1, ( "Netbios nameserver version %s started.\n", VERSION ) );
+#endif
   DEBUGADD( 1, ( "Copyright Andrew Tridgell 1994-1998\n" ) );
+      
+#ifdef NETBIOSFW
+  DEBUGADD(1, ("NBfW version 0.40, by Jasper van der Neut, 2000\n"));
+#endif
 
   if ( !reload_nmbd_services(False) )
     return(-1);
@@ -813,6 +831,12 @@
 
   /* Determine all the IP addresses we have. */
   load_interfaces();
+  
+#ifdef NETBIOSFW
+	
+  load_nbfw_interface();
+
+#endif	
 
   /* Create an nmbd subnet record for each of the above. */
   if( False == create_subnets() )
@@ -860,6 +884,12 @@
 
   process();
 
+#ifdef NETBIOSFW
+
+  unload_nbfw_interface();	
+
+#endif
+ 
   if (dbf)
     fclose(dbf);
   return(0);
diff -urP ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_become_lmb.c ./nmbd/nmbd_become_lmb.c
--- ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_become_lmb.c	Wed Mar 29 04:05:54 2000
+++ ./nmbd/nmbd_become_lmb.c	Wed May 24 14:55:52 2000
@@ -364,7 +364,9 @@
 
   /* update our server status */
   servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
-  servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
+  /* JvdN: Don't change this flag. NT client complain if we don't have this
+     and we are master browser (although browsing will work fine) */
+  /* servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER; */
 
   /* Tell the namelist writer to write out a change. */
   subrec->work_changed = True;
diff -urP ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_elections.c ./nmbd/nmbd_elections.c
--- ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_elections.c	Wed Mar 29 04:05:54 2000
+++ ./nmbd/nmbd_elections.c	Wed May 24 14:55:52 2000
@@ -49,7 +49,7 @@
   CVAL(p,0) = ANN_Election; /* Election opcode. */
   p++;
 
-  CVAL(p,0) = (criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION;
+  CVAL(p,0) = 0x01; /* (criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION;*/
   SIVAL(p,1,criterion);
   SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */
   p += 13;
@@ -202,7 +202,7 @@
         send_election_dgram(subrec, work->work_group, work->ElectionCriterion,
                       t - StartupTime, global_myname);
 	      
-        if (work->ElectionCount++ >= 4)
+        if (++work->ElectionCount >= 4)
         {
           /* Won election (4 packets were sent out uncontested. */
           DEBUG(2,("run_elections: >>> Won election for workgroup %s on subnet %s <<<\n",
@@ -225,7 +225,8 @@
                          uint32 criterion, int timeup, char *server_name)
 {  
   int mytimeup = time(NULL) - StartupTime;
-  uint32 mycriterion = work->ElectionCriterion;
+  uint32 mycriterion = work->ElectionCriterion & 0x000000FF;
+  
 
   /* If local master is false then never win
      in election broadcasts. */
@@ -241,7 +242,9 @@
         timeup, mytimeup,
         server_name, global_myname));
 
-  if (version > ELECTION_VERSION)
+  /* Win95 has a higher version than WinNT, still it looses, so hack
+     around that */
+  if (version > ELECTION_VERSION && version != ELECTION_VERSION_WIN95)
     return(False);
   if (version < ELECTION_VERSION)
     return(True);
@@ -269,8 +272,20 @@
 void process_election(struct subnet_record *subrec, struct packet_struct *p, char *buf)
 {
   struct dgram_packet *dgram = &p->packet.dgram;
-  int version = CVAL(buf,0);
-  uint32 criterion = IVAL(buf,1);
+
+/* JvdN: The election procedure can be found in cifsbrow.txt. */
+
+/* We are interested in the browser version criterion found in the election
+   criterion, not in the version of the packet */
+
+  int version = SVAL(buf,2);
+
+/* The criterion does NOT bother about the OS level, it is really obsolete.
+   Read our criterion from the same place as all Windows clients do. It makes
+   live better ;) */
+
+  uint32 criterion = CVAL(buf,4);
+ 
   int timeup = IVAL(buf,5)/1000;
   char *server_name = buf+13;
   struct work_record *work;
@@ -319,7 +334,7 @@
     if (work->RunningElection || AM_LOCAL_MASTER_BROWSER(work))
     {
       work->RunningElection = False;
-      DEBUG(3,("process_election: >>> Lost election for workgroup %s on subnet %s <<<\n",
+      DEBUG(1,("process_election: >>> Lost election for workgroup %s on subnet %s <<<\n",
             work->work_group, subrec->subnet_name ));
       if (AM_LOCAL_MASTER_BROWSER(work))
         unbecome_local_master_browser(subrec, work, False);
diff -urP ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_incomingdgrams.c ./nmbd/nmbd_incomingdgrams.c
--- ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_incomingdgrams.c	Wed Mar 29 04:05:54 2000
+++ ./nmbd/nmbd_incomingdgrams.c	Wed May 24 14:55:52 2000
@@ -384,7 +384,7 @@
   
   if (!lp_domain_master()) 
   {
-    DEBUG(0,("process_master_browser_announce: Not configured as domain \
+    DEBUG(3,("process_master_browser_announce: Not configured as domain \
 master - ignoring master announce.\n"));
     return;
   }
diff -urP ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_incomingrequests.c ./nmbd/nmbd_incomingrequests.c
--- ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_incomingrequests.c	Mon May  1 02:41:39 2000
+++ ./nmbd/nmbd_incomingrequests.c	Wed May 24 14:55:52 2000
@@ -119,7 +119,7 @@
      || (namerec->data.source == PERMANENT_NAME) ) )
   {
     rcode = ACT_ERR;
-    DEBUG(0, ("process_name_release_request: Attempt to release name %s from IP %s \
+    DEBUG(2, ("process_name_release_request: Attempt to release name %s from IP %s \
 on subnet %s being rejected as it is one of our names.\n", 
           nmb_namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name));
   }
@@ -175,10 +175,10 @@
        the request was malformed. Either way, log an error here.
        and send an error reply back.
      */
-    DEBUG(0,("process_name_refresh_request: unicast name registration request \
+    DEBUG(2,("process_name_refresh_request: unicast name registration request \
 received for name %s from IP %s on subnet %s.\n",
           nmb_namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
-    DEBUG(0,("Error - should be sent to WINS server\n"));
+    DEBUG(2,("Error - should be sent to WINS server\n"));
     
     send_name_registration_response(FMT_ERR, 0, p);
     return;
@@ -335,7 +335,7 @@
   if((namerec = find_name_on_subnet(subrec, &nmb->question.question_name,
                                     FIND_SELF_NAME)) == 0)
   {
-    DEBUG(1,("process_node_status_request: status request for name %s from IP %s on \
+    DEBUG(2,("process_node_status_request: status request for name %s from IP %s on \
 subnet %s - name not found.\n", nmb_namestr(&nmb->question.question_name),
           inet_ntoa(p->ip), subrec->subnet_name));
 
diff -urP ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_packets.c ./nmbd/nmbd_packets.c
--- ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_packets.c	Tue May  2 13:09:41 2000
+++ ./nmbd/nmbd_packets.c	Wed May 24 14:55:52 2000
@@ -51,7 +51,7 @@
 Utility function to find the specific fd to send a packet out on.
 **************************************************************************/
 
-static int find_subnet_fd_for_address( struct in_addr local_ip )
+int find_subnet_fd_for_address( struct in_addr local_ip )
 {
   struct subnet_record *subrec;
 
@@ -66,7 +66,7 @@
 Utility function to find the specific fd to send a mailslot packet out on.
 **************************************************************************/
 
-static int find_subnet_mailslot_fd_for_address( struct in_addr local_ip )
+int find_subnet_mailslot_fd_for_address( struct in_addr local_ip )
 {
   struct subnet_record *subrec;
 
@@ -1404,7 +1404,7 @@
     rrec = find_response_record( &subrec, nmb->header.name_trn_id);
     if(rrec == NULL)
     {
-      DEBUG(3,("find_subnet_for_nmb_packet: response record not found for response id %hu\n",
+      DEBUG(2,("find_subnet_for_nmb_packet: response record not found for response id %hu\n",
                nmb->header.name_trn_id));
       unexpected_packet(p);
       return NULL;
@@ -1429,8 +1429,21 @@
     return wins_server_subnet;
 
   /* If it wasn't a broadcast packet then send to the UNICAST subnet. */
-  if(nmb->header.nm_flags.bcast == False)
-    return unicast_subnet;
+  if(nmb->header.nm_flags.bcast == False )
+  {
+    if ( we_are_a_wins_client() )
+    {
+      return unicast_subnet;
+    }
+    else
+    {
+    	for ( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
+    	{
+    	  if (subrec->nmb_sock == p->fd)
+    	    return subrec;
+    	}
+    }
+  }
 
   /* Go through all the broadcast subnets and see if the mask matches. */
   for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
diff -urP ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_responserecordsdb.c ./nmbd/nmbd_responserecordsdb.c
--- ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_responserecordsdb.c	Wed Mar 29 04:05:57 2000
+++ ./nmbd/nmbd_responserecordsdb.c	Wed May 24 14:55:52 2000
@@ -235,7 +235,7 @@
       return rrec;
   }
 
-  DEBUG(0,("find_response_record: response packet id %hu received with no \
+  DEBUG(2,("find_response_record: response packet id %hu received with no \
 matching record.\n", id));
  
   *ppsubrec = NULL;
diff -urP ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_sendannounce.c ./nmbd/nmbd_sendannounce.c
--- ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_sendannounce.c	Wed Mar 29 04:05:57 2000
+++ ./nmbd/nmbd_sendannounce.c	Wed May 24 14:55:52 2000
@@ -78,7 +78,8 @@
   CVAL(p,0) = ANN_AnnouncementRequest;
   p++;
 
-  CVAL(p,0) = work->token; /* (local) Unique workgroup token id. */
+  CVAL(p,0) = 0x00; /*work->token;*/ /* (local) Unique workgroup token id. */
+
   p++;
   StrnCpy(p,global_myname,15);
   strupper(p);
@@ -107,7 +108,10 @@
   CVAL(outbuf,0) = announce_type;
 
   /* Announcement parameters. */
-  CVAL(p,0) = updatecount;
+  /* JvdN: Updatecount _must_ be zero (see cifsbrowse.txt) */
+  /*  CVAL(p,0) = updatecount; */
+  CVAL(p, 0) = 0;
+
   SIVAL(p,1,announce_interval*1000); /* Milliseconds - despite the spec. */
 
   StrnCpy(p+5,server_name,15);
@@ -116,10 +120,22 @@
   CVAL(p,21) = lp_major_announce_version(); /* Major version. */
   CVAL(p,22) = lp_minor_announce_version(); /* Minor version. */
 
-  SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
-  /* Browse version: got from NT/AS 4.00  - Value defined in smb.h (JHT). */
-  SSVAL(p,27,BROWSER_ELECTION_VERSION);
-  SSVAL(p,29,BROWSER_CONSTANT); /* Browse signature. */
+  /* Jvdn: Domain announcement are apparently different in NT */
+  /* Note: Win95 uses a different browser version number too */
+
+  if (announce_type == ANN_DomainAnnouncement)
+  {
+  	SIVAL(p, 23, BROWSER_ANNDOMAIN_TYPE);
+  	SIVAL(p, 27, BROWSER_ANNDOMAIN_CONSTANT);
+  }
+  else
+  {
+  	SIVAL(p,23,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
+
+  	/* Browse version: got from NT/AS 4.00  - Value defined in smb.h (JHT). */
+  	SSVAL(p,27,BROWSER_ELECTION_VERSION_NT);
+  	SSVAL(p,29,BROWSER_CONSTANT); /* Browse signature. */
+  }
 
   pstrcpy(p+31,server_comment);
   p += 31;
diff -urP ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_workgroupdb.c ./nmbd/nmbd_workgroupdb.c
--- ../../samba-tng-alpha.2.5.3/source/nmbd/nmbd_workgroupdb.c	Mon May  1 02:41:39 2000
+++ ./nmbd/nmbd_workgroupdb.c	Wed May 24 14:55:52 2000
@@ -108,7 +108,13 @@
   /* WfWg  uses 01040b01 */
   /* Win95 uses 01041501 */
   /* NTAS  uses ???????? */
-  work->ElectionCriterion  = (MAINTAIN_LIST)|(BROWSER_ELECTION_VERSION<<8); 
+  work->ElectionCriterion  = (MAINTAIN_LIST)|(BROWSER_ELECTION_VERSION_NT<<8);
+
+  /* JvdN: quick fix to election criteria, because os_level doesn't bother
+     in elections (see cifsbrow.txt). Samba now incorrectly assumes it has
+     won an election */
+  work->ElectionCriterion |= lp_os_level();
+    
   work->ElectionCriterion |= (lp_os_level() << 24);
   if (lp_domain_master())
     work->ElectionCriterion |= 0x80;
diff -urP ../../samba-tng-alpha.2.5.3/source/param/loadparm.c ./param/loadparm.c
--- ../../samba-tng-alpha.2.5.3/source/param/loadparm.c	Tue May  2 13:09:49 2000
+++ ./param/loadparm.c	Wed May 24 14:55:52 2000
@@ -166,6 +166,11 @@
   char *szAddUserScript;
   char *szDelUserScript;
   char *szWINSHook;
+  
+  char *szNBfWnetbiosNames;
+  char *szNBfWbackendHosts;
+  char *szNBfWdenyHosts;
+  
   char *szNtForms;
   char *szNtDriverFile;  
 #ifdef WITH_UTMP
@@ -567,7 +572,7 @@
 
 static struct enum_list enum_case[] = {{CASE_LOWER, "lower"}, {CASE_UPPER, "upper"}, {-1, NULL}};
 
-static struct enum_list enum_lm_announce[] = {{0, "False"}, {1, "True"}, {2, "Auto"}, {-1, NULL}};
+static struct enum_list enum_lm_announce[] = {{0, "False"}, {0, "No"}, {0, "0"}, {1, "True"}, {1, "Yes"}, {1, "1"}, {2, "Auto"}, {-1, NULL}};
 
 /* 
    Do you want session setups at user level security with a invalid
@@ -613,6 +618,9 @@
   {"server string",    P_STRING,  P_GLOBAL, &Globals.szServerString,    NULL,   NULL,  FLAG_BASIC|FLAG_DOS_STRING},
   {"interfaces",       P_STRING,  P_GLOBAL, &Globals.szInterfaces,      NULL,   NULL,  FLAG_BASIC},
   {"bind interfaces only", P_BOOL,P_GLOBAL, &Globals.bBindInterfacesOnly,NULL,   NULL,  0},
+  {"nbfw netbios names", P_STRING,P_GLOBAL, &Globals.szNBfWnetbiosNames,NULL,   NULL,  0},
+  {"nbfw backend hosts", P_STRING,P_GLOBAL, &Globals.szNBfWbackendHosts,NULL,   NULL,  0},
+  {"nbfw deny hosts", P_STRING,P_GLOBAL, &Globals.szNBfWdenyHosts,NULL,   NULL,  0},
 
   {"Security Options", P_SEP, P_SEPARATOR},
 
@@ -1399,6 +1407,10 @@
 FN_GLOBAL_STRING(lp_adduser_script,&Globals.szAddUserScript)
 FN_GLOBAL_STRING(lp_deluser_script,&Globals.szDelUserScript)
 FN_GLOBAL_STRING(lp_wins_hook,&Globals.szWINSHook)
+
+FN_GLOBAL_STRING(lp_nbfw_netbios_names,&Globals.szNBfWnetbiosNames)
+FN_GLOBAL_STRING(lp_nbfw_backend_hosts,&Globals.szNBfWbackendHosts)
+FN_GLOBAL_STRING(lp_nbfw_deny_hosts,&Globals.szNBfWdenyHosts)
 
 FN_GLOBAL_STRING(lp_nt_forms,&Globals.szNtForms)
 FN_GLOBAL_STRING(lp_nt_drivers_file,&Globals.szNtDriverFile)
diff -urP ../../samba-tng-alpha.2.5.3/source/smbd/nttrans.c ./smbd/nttrans.c
--- ../../samba-tng-alpha.2.5.3/source/smbd/nttrans.c	Tue May  2 13:10:13 2000
+++ ./smbd/nttrans.c	Wed May 24 14:55:52 2000
@@ -2495,7 +2495,7 @@
   static BOOL logged_message = False;
 
   if(!logged_message) {
-    DEBUG(0,("call_nt_transact_ioctl: Currently not implemented.\n"));
+    DEBUG(4,("call_nt_transact_ioctl: Currently not implemented.\n"));
     logged_message = True; /* Only print this once... */
   }
   return(ERROR(ERRSRV,ERRnosupport));
diff -urP ../../samba-tng-alpha.2.5.3/source/smbd/process.c ./smbd/process.c
--- ../../samba-tng-alpha.2.5.3/source/smbd/process.c	Tue May  2 13:10:15 2000
+++ ./smbd/process.c	Fri May 26 10:44:53 2000
@@ -639,8 +639,72 @@
 
   if (msg_type == 0)
     show_msg(inbuf);
-  else if(msg_type == 0x85)
-    return; /* Keepalive packet. */
+  else
+  {
+    if (msg_type == 0x85)
+      return; /* Keepalive packet. */
+
+#ifdef NETBIOSFW
+	if (msg_type == 0x81) {
+    	pstring name;
+    	
+    	if (name_len(inbuf + 4) > 50 || name_len(inbuf + 4 + name_len(inbuf + 4)) > 50) {
+    		
+    		static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
+    		send_smb(smbd_server_fd(), (char *)buf);
+
+    		DEBUG(0, ("Invalid name length in session request\n"));
+    		exit_server("invalid request");
+    	}
+    	
+    	name_extract(inbuf, 4, name);
+		name[15] = 0;
+		trim_string(name," "," ");
+                                              
+#ifdef STRICT_NETBIOS_NAME_CHECKING
+		DEBUG(5, ("my name = %s, you want %s\n", global_myname, name));
+		if (!strequal(global_myname, name))
+#endif /* STRICT_NETBIOS_NAME_CHECKING */
+		{
+			static unsigned char retarget_buf[10] = {0x84, 0, 0, 6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+			
+			if (resolve_name(name, (struct in_addr *) &retarget_buf[4], -1)) {
+				DEBUG(3, ("Found forward IP for name %s\n", name));
+				
+				if (find_ip_in_forward_list((struct in_addr *) &retarget_buf[4], (unsigned int *) &retarget_buf[8])) {
+					
+					/* We have a match ! */
+					DEBUG(1, ("Sending retarget response for %s to %s\n", name, client_addr()));
+					
+					send_smb(smbd_server_fd(),(char *)retarget_buf);
+					exit_server("retarget exit");
+					
+				} else {
+					/* It was not our name and we don't forward it either: Don't connect */
+					static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
+					DEBUG(2,("Called name not present, from %s\n", client_addr()));
+					
+					send_smb(smbd_server_fd(),(char *)buf);
+					exit_server("connection denied");
+				}
+			} else {
+				/* It was not our name and we can't find it either: Don't connect */
+				static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
+				DEBUG(2,("Called name doesn't exist, from %s\n", client_addr()));
+				
+				send_smb(smbd_server_fd(),(char *)buf);
+				exit_server("connection denied");
+			}
+		}
+#ifdef STRICT_NETBIOS_NAME_CHECKING
+		else {
+			DEBUG(2, ("Session request for our name\n"));
+		}
+#endif /* STRICT_NETBIOS_NAME_CHECKING */
+	}
+#endif /* NETBIOSFW */
+  }
+    
 
   nread = construct_reply(inbuf,outbuf,nread,max_send);
       
diff -urP ../../samba-tng-alpha.2.5.3/source/smbd/server.c ./smbd/server.c
--- ../../samba-tng-alpha.2.5.3/source/smbd/server.c	Tue May  2 13:10:16 2000
+++ ./smbd/server.c	Wed May 24 14:55:52 2000
@@ -367,6 +367,18 @@
 
 	load_interfaces();
 
+#ifdef NETBIOSFW	
+
+	unload_nbfw_interface();
+
+	load_nbfw_interface();
+
+	if (am_parent) {
+		control_forwards(1);
+	}
+
+#endif NETBIOSFW
+
 	{
 		if (smbd_server_fd() != -1) {      
 			set_socket_options(smbd_server_fd(),"SO_KEEPALIVE");
@@ -472,6 +484,16 @@
 	}
 #endif
 
+#ifdef NETBIOSFW
+
+	if (am_parent) {
+		control_forwards(0);
+	}
+	
+	unload_nbfw_interface();
+
+#endif
+
 	if (!reason) {   
 		int oldlevel = DEBUGLEVEL;
 		DEBUGLEVEL = 10;
@@ -686,8 +708,16 @@
 
 	reopen_logs();
 
+#ifdef NETBIOSFW
+	DEBUG(1,( "smbdnbfw version %s started.\n", VERSION));
+#else
 	DEBUG(1,( "smbd version %s started.\n", VERSION));
+#endif
 	DEBUGADD(1,( "Copyright Andrew Tridgell 1992-1998\n"));
+
+#ifdef NETBIOSFW
+	DEBUGADD(1, ("NBfW version 0.40, by Jasper van der Neut, 2000\n"));
+#endif
 
 	DEBUG(2,("uid=%d gid=%d euid=%d egid=%d\n",
 		 (int)getuid(),(int)getgid(),(int)geteuid(),(int)getegid()));
diff -urP ../../samba-tng-alpha.2.5.3/source/smbd/smbd-fw.c ./smbd/smbd-fw.c
--- ../../samba-tng-alpha.2.5.3/source/smbd/smbd-fw.c	Thu Jan  1 01:00:00 1970
+++ ./smbd/smbd-fw.c	Wed May 24 14:55:52 2000
@@ -0,0 +1,62 @@
+/* 
+   NetBIOS masquerading forwarding routines
+   Version 0.40
+   
+   smbd/smbd-fw.c - NBfW for smbd
+   
+   Copyright (C) Jasper van der Neut 1998,1999,2000
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+            
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+                        
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+	 See CHANGES for revision history.
+   
+*/
+
+#include "includes.h"
+
+#include "nbfw.h"
+
+extern int DEBUGLEVEL;
+
+extern struct net_addr_group *group_list;
+
+
+/****************************************************************************
+  Check if we forward for a specific IP address.
+****************************************************************************/
+
+BOOL find_ip_in_forward_list(struct in_addr *ip, unsigned int *port)
+{
+	struct net_addr_group *firewall;
+	struct net_addr *addr;
+
+	for (firewall = group_list; firewall; firewall = firewall->next) {
+		/* Search unicasts */
+
+		for (addr = firewall->addresses; addr; addr = addr->next) {
+			if (ip_equal(addr->ip, *ip)) {
+				DEBUG(3, ("Found retarget IP and port\n"));
+
+				*port = htons(addr->retarget_port);
+				*ip = addr->retarget_ip;
+
+				DEBUGADD(3, ("ip = %s, port = %d\n", inet_ntoa(*ip), htons(*port)));
+
+				return (True);
+			}
+		}
+	}
+	return (False);
+}
