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 +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 <&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 header file. */ #undef HAVE_LIMITS_H +/* Define if you have the header file. */ +#undef HAVE_LINUX_IP_FW_H + +/* Define if you have the header file. */ +#undef HAVE_LINUX_IP_MASQ_H + /* Define if you have the 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 +#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); +}