summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Announce38
-rw-r--r--README17
-rw-r--r--Roadmap12
-rw-r--r--WHATSNEW.txt347
-rw-r--r--docs/manpages/make_smbcodepage.1131
-rw-r--r--docs/manpages/nmbd.89
-rw-r--r--docs/manpages/samba.72
-rw-r--r--docs/manpages/smb.conf.5360
-rw-r--r--docs/manpages/smbclient.19
-rw-r--r--docs/manpages/smbd.830
-rw-r--r--docs/manpages/smbpasswd.82
-rw-r--r--docs/manpages/smbrun.12
-rw-r--r--docs/manpages/smbstatus.12
-rw-r--r--docs/manpages/smbtar.12
-rw-r--r--docs/manpages/testparm.12
-rw-r--r--docs/manpages/testprns.12
-rw-r--r--docs/textdocs/Application_Serving.txt2
-rw-r--r--docs/textdocs/BROWSING.txt13
-rw-r--r--docs/textdocs/BUGS.txt2
-rw-r--r--docs/textdocs/DIAGNOSIS.txt2
-rw-r--r--docs/textdocs/DNIX.txt2
-rw-r--r--docs/textdocs/DOMAIN.txt74
-rw-r--r--docs/textdocs/DOMAIN_CONTROL.txt11
-rw-r--r--docs/textdocs/ENCRYPTION.txt40
-rw-r--r--docs/textdocs/Faxing.txt2
-rw-r--r--docs/textdocs/GOTCHAS.txt2
-rw-r--r--docs/textdocs/HINTS.txt2
-rwxr-xr-xdocs/textdocs/MIRRORS.txt3
-rw-r--r--docs/textdocs/NTDOMAIN.txt155
-rw-r--r--docs/textdocs/NetBIOS.txt2
-rw-r--r--docs/textdocs/OS2-Client-HOWTO.txt2
-rw-r--r--docs/textdocs/PRINTER_DRIVER.txt77
-rw-r--r--docs/textdocs/Passwords.txt2
-rw-r--r--docs/textdocs/Printing.txt2
-rw-r--r--docs/textdocs/SCO.txt2
-rw-r--r--docs/textdocs/Speed.txt39
-rw-r--r--docs/textdocs/Support.txt41
-rw-r--r--docs/textdocs/Tracing.txt2
-rw-r--r--docs/textdocs/UNIX-SMB.txt2
-rw-r--r--docs/textdocs/UNIX_INSTALL.txt10
-rw-r--r--docs/textdocs/Win95.txt2
-rw-r--r--docs/textdocs/WinNT.txt4
-rw-r--r--docs/textdocs/cifsntdomain.txt1501
-rw-r--r--docs/textdocs/security_level.txt2
-rw-r--r--examples/misc/extra_smbstatus2
-rw-r--r--examples/smb.conf.default17
-rw-r--r--packaging/SGI/README14
-rwxr-xr-xpackaging/SGI/idb.pl8
-rw-r--r--packaging/SGI/smb.conf5
-rw-r--r--source/.cvsignore2
-rw-r--r--source/cgi.c621
-rw-r--r--source/client/client.c1400
-rw-r--r--source/client/clientutil.c693
-rw-r--r--source/client/clitar.c149
-rw-r--r--source/client/ntclient.c354
-rw-r--r--source/codepages/codepage_def.43770
-rw-r--r--source/codepages/codepage_def.85054
-rw-r--r--source/codepages/codepage_def.85263
-rw-r--r--source/codepages/codepage_def.93224
-rw-r--r--source/include/byteorder.h99
-rw-r--r--source/include/charset.h10
-rw-r--r--source/include/includes.h116
-rw-r--r--source/include/kanji.h40
-rw-r--r--source/include/local.h41
-rw-r--r--source/include/nameserv.h468
-rw-r--r--source/include/nterr.h505
-rw-r--r--source/include/proto.h1135
-rw-r--r--source/include/smb.h1385
-rw-r--r--source/include/trans2.h7
-rw-r--r--source/include/version.h2
-rw-r--r--source/lib/access.c4
-rw-r--r--source/lib/charcnv.c38
-rw-r--r--source/lib/charset.c256
-rw-r--r--source/lib/getsmbpass.c4
-rw-r--r--source/lib/interface.c69
-rw-r--r--source/lib/kanji.c133
-rw-r--r--source/lib/md4.c448
-rw-r--r--source/lib/replace.c67
-rw-r--r--source/lib/system.c25
-rw-r--r--source/lib/time.c16
-rw-r--r--source/lib/ufc.c2
-rw-r--r--source/lib/username.c83
-rw-r--r--source/lib/util.c1358
-rw-r--r--source/libsmb/clientgen.c821
-rw-r--r--source/libsmb/credentials.c222
-rw-r--r--source/libsmb/namequery.c38
-rw-r--r--source/libsmb/nmblib.c161
-rw-r--r--source/libsmb/nterr.c514
-rw-r--r--source/libsmb/smbdes.c337
-rw-r--r--source/libsmb/smbencrypt.c119
-rw-r--r--source/libsmb/smberr.c182
-rw-r--r--source/locking/locking.c1214
-rw-r--r--source/locking/locking_shm.c698
-rw-r--r--source/locking/locking_slow.c1052
-rw-r--r--source/locking/shmem.c648
-rw-r--r--source/locking/shmem_sysv.c706
-rw-r--r--source/md4.h58
-rw-r--r--source/nameannounce.c562
-rw-r--r--source/nameannounce.doc265
-rw-r--r--source/namebrowse.c246
-rw-r--r--source/namebrowse.doc149
-rw-r--r--source/namedbname.c601
-rw-r--r--source/namedbname.doc182
-rw-r--r--source/namedbresp.c168
-rw-r--r--source/namedbresp.doc100
-rw-r--r--source/namedbserver.c212
-rw-r--r--source/namedbsubnet.c363
-rw-r--r--source/namedbwork.c245
-rw-r--r--source/nameelect.c846
-rw-r--r--source/nameelect.doc256
-rw-r--r--source/namelogon.c145
-rw-r--r--source/namelogon.doc36
-rw-r--r--source/namepacket.c642
-rw-r--r--source/namepacket.doc133
-rw-r--r--source/namequery.doc83
-rw-r--r--source/nameresp.c326
-rw-r--r--source/nameresp.doc178
-rw-r--r--source/nameserv.c507
-rw-r--r--source/nameserv.doc159
-rw-r--r--source/nameservreply.c674
-rw-r--r--source/nameservreply.doc213
-rw-r--r--source/nameservresp.c851
-rw-r--r--source/nameservresp.doc191
-rw-r--r--source/namework.c724
-rw-r--r--source/namework.doc363
-rw-r--r--source/nmbd/asyncdns.c321
-rw-r--r--source/nmbd/nmbd.c829
-rw-r--r--source/nmbd/nmbd_become_dmb.c471
-rw-r--r--source/nmbd/nmbd_become_lmb.c563
-rw-r--r--source/nmbd/nmbd_browserdb.c184
-rw-r--r--source/nmbd/nmbd_browsesync.c458
-rw-r--r--source/nmbd/nmbd_elections.c348
-rw-r--r--source/nmbd/nmbd_incomingdgrams.c769
-rw-r--r--source/nmbd/nmbd_incomingrequests.c590
-rw-r--r--source/nmbd/nmbd_lmhosts.c168
-rw-r--r--source/nmbd/nmbd_logonnames.c166
-rw-r--r--source/nmbd/nmbd_mynames.c165
-rw-r--r--source/nmbd/nmbd_namelistdb.c586
-rw-r--r--source/nmbd/nmbd_namequery.c234
-rw-r--r--source/nmbd/nmbd_nameregister.c392
-rw-r--r--source/nmbd/nmbd_namerelease.c238
-rw-r--r--source/nmbd/nmbd_nodestatus.c99
-rw-r--r--source/nmbd/nmbd_packets.c1831
-rw-r--r--source/nmbd/nmbd_processlogon.c250
-rw-r--r--source/nmbd/nmbd_responserecordsdb.c238
-rw-r--r--source/nmbd/nmbd_sendannounce.c583
-rw-r--r--source/nmbd/nmbd_serverlistdb.c453
-rw-r--r--source/nmbd/nmbd_subnetdb.c291
-rw-r--r--source/nmbd/nmbd_winsproxy.c218
-rw-r--r--source/nmbd/nmbd_winsserver.c1566
-rw-r--r--source/nmbd/nmbd_workgroupdb.c356
-rw-r--r--source/nmbsync.c191
-rw-r--r--source/param/loadparm.c956
-rw-r--r--source/param/params.c851
-rw-r--r--source/passdb/smbpass.c635
-rw-r--r--source/printing/pcap.c21
-rw-r--r--source/printing/print_svid.c121
-rw-r--r--source/printing/printing.c5
-rwxr-xr-xsource/script/installcp.sh36
-rw-r--r--source/script/mkproto.awk2
-rw-r--r--source/script/smbtar2
-rwxr-xr-xsource/script/uninstallcp.sh33
-rwxr-xr-xsource/smbadduser73
-rw-r--r--source/smbd/chgpasswd.c6
-rw-r--r--source/smbd/dir.c210
-rw-r--r--source/smbd/ipc.c399
-rw-r--r--source/smbd/mangle.c644
-rw-r--r--source/smbd/password.c191
-rw-r--r--source/smbd/pipes.c129
-rw-r--r--source/smbd/quotas.c127
-rw-r--r--source/smbd/reply.c453
-rw-r--r--source/smbd/server.c1632
-rw-r--r--source/smbd/trans2.c82
-rw-r--r--source/smbd/uid.c71
-rw-r--r--source/utils/make_printerdef.c301
-rw-r--r--source/utils/make_smbcodepage.c472
-rw-r--r--source/utils/nmblookup.c93
-rw-r--r--source/utils/smbpasswd.c59
-rw-r--r--source/utils/status.c298
-rw-r--r--source/utils/testparm.c2
-rw-r--r--source/utils/torture.c919
-rw-r--r--source/web/cgi.c621
-rw-r--r--source/wsmbconf.c237
-rw-r--r--source/wsmbstatus.c87
184 files changed, 17616 insertions, 33654 deletions
diff --git a/Announce b/Announce
new file mode 100644
index 00000000000..45ead7d63a1
--- /dev/null
+++ b/Announce
@@ -0,0 +1,38 @@
+The Samba-Team is pleased to announce the final production release of
+Samba-1.9.17p5.
+
+Please note that this release is bein made purely for those who like
+the comfort of knowing that the code is stable and has been in use for
+a significant period. We ALL know that the next product is always
+__BETTER__, just like we know that it will without doubt have some
+not quite expected features too. The Samba-Team listens to it's users.
+You want stability, reliability and you want us to keep rolling out new
+features, improved ease of use, and so on.
+
+Samba-1.9.18 is now in final beta testing and unless any major bugs are
+reported within the next two weeks will ship early in 1998. We regret the
+delay but we also know that the new features were worth waiting for.
+
+This release of Samba-1.9.17p5 integrates all fixes that have been made to
+the Samba-1.9.17 source code tree and that have been included in Samba-1.9.18.
+This release is for use in mission critical sites that do NOT like to
+be early adopters.
+
+There are several key fixes in this update release:
+ - When Samba won the role of master browser it would NOT give it up
+ - Added feature of "remote browse sync" which helps those sites
+ that have multi-workgroup / multi-segmented networks.
+ - Some minor file-name handling fixes
+
+Should any problems be experienced with this release please mail your bug
+report to: samba-bugs@samba.anu.edu.au with the subject: BUGS17P5: XXXXXX
+
+As always, functionality afforded by Samba is for your pleasure, the bugs
+(we know there MUST be some) are our responsibility - so please report them
+to samba-bugs@samba.anu.edu.au
+
+Seasons Greetings.
+The Samba-Team
+
+---
+jht@samba.anu.edu.au Sat Dec 20 11:43:25 EST 1997
diff --git a/README b/README
index 30103241841..10d9d931e55 100644
--- a/README
+++ b/README
@@ -19,8 +19,10 @@ PC-related machines share files and printers and other informatiuon
such as lists of available files and printers. Operating systems that
support this natively include Windows NT, OS/2, and Linux and add on
packages that achieve the same thing are available for DOS, Windows,
-VMS, Unix of all kinds, MVS, and more. Apple Macs and some Web Browsers
-can speak this protocol as well. Alternatives to SMB include
+VMS, Unix of all kinds, MVS, and more. There is no reason why Apple
+Macs and indeed any Web browser should not be able to speak this
+protocol, and current development (in which the Samba team is heavily
+involved) is aimed at exactly that. Alternatives to SMB include
Netware, NFS, Appletalk, Banyan Vines, Decnet etc; many of these have
advantages but none are both public specifications and widely
implemented in desktop machines by default.
@@ -100,22 +102,19 @@ DOCUMENTATION
There is quite a bit of documentation included with the package,
including man pages, and lots of .txt files with hints and useful
-info. This is also available from the web page. There is a growing
-collection of information under docs/faq; by the next release expect
-this to be the default starting point.
+info. This is also available from the web page.
FTP SITE
--------
-Please use a mirror site! The list of mirrors is in docs/MIRRORS.txt.
-The master ftp site is samba.anu.edu.au in the directory pub/samba.
+The main anonymous ftp distribution site for this software is
+samba.anu.edu.au in the directory pub/samba/.
MAILING LIST
------------
There is a mailing list for discussion of Samba. To subscribe send
mail to listproc@samba.anu.edu.au with a body of "subscribe samba Your Name"
-Please do NOT send this request to the list alias instead.
To send mail to everyone on the list mail to samba@listproc.anu.edu.au
@@ -150,3 +149,5 @@ this package. Have you registered with the survey yet? :-)
It is maintained by Paul Blackman (thanks Paul!). You can contact him
at ictinus@samba.anu.edu.au.
+
+
diff --git a/Roadmap b/Roadmap
index 556e49d342f..6df5cf20d30 100644
--- a/Roadmap
+++ b/Roadmap
@@ -1,6 +1,6 @@
Copyright (C) 1997 - Samba-Team
-The Samba-Team are committed to an agressive program to deliver quality
+The Samba-Team are committed to an agressive program to deliver quailty
controlled software to a well defined roadmap.
The current Samba release 1.9.17 is called the "Browse Fix Release"
@@ -8,20 +8,22 @@ The following development objectives are in place:
Version / Codename Notes
------------------ ----------------------------------------------------
-1.9.18 This version will feature two main areas of improvement
+1.9.18 This version will feature three main areas of improvement
"Perf-Lock Release" - introduction of OpLock support
- introduction of new browse list and WINS methods
- - introduction of experimental NT Domain Authentication
- as a compile-time option only.
+ - full support for multi-homed servers
1.9.19 An authentication update release to offer improved
"Auth Code Release" security and password synchronisation capabilities
+ - watch out for new Windows NT interoperability
+ features.
1.9.20 Introduction of new managment tools
"GUI Config Release" Improved multi-language support.
+ - GUI Configuration Manager (Web based)
2.0 The next generation Directory Services update
-"DSA Release"
+"DSA Release" (We are still working on the features list)
While no release date or content promises are made we are hoping to release
the remainder of the 1.9 series relases within short time frame.
diff --git a/WHATSNEW.txt b/WHATSNEW.txt
index 322c646f7d7..06e3f687f72 100644
--- a/WHATSNEW.txt
+++ b/WHATSNEW.txt
@@ -1,193 +1,253 @@
- WHATS NEW IN 1.9.18alpha13 Dec 15th 1997
- ========================================
+ WHATS NEW IN 1.9.17p5 - December 19th. 1997
+ ===========================================
+
+Update release: Samba - version 1.9.17p5.
+-----------------------------------------
+
+This is the latest stable release of Samba. This is the
+version that all production Samba servers should be running
+for all current bug-fixes.
+
+Here are a list of the fixes in this release (the fixes
+introduced between 1.9.17p4 and 1.9.17p5) :
+
+1). Addition of 'remote browse sync' parameter.
+2). Fix for bug where nmbd would not stop announcing itself
+ as a local master browser once it had lost the election.
+3). No longer fill in status fields in node status reply for
+ security.
+4). Code added to seach the nmbd name cache for the results
+ of a previous dns search.
+5). Treat WORKGROUP<1c> names correctly when registering (don't
+ treat them as a normal group name).
+6). Fix bug in the handling of the 'character set' parameter.
+7). Disable read prediction code by default - conflicts with
+ locking fixes.
+8). Fix bug with name mangling with UNIX filenames containing ':'.
+
+Reporting bugs
+--------------
+
+The Samba Team believes that this is a stable
+production release, but all software has bugs.
+If you have problems, or think you have found a
+bug please email a report to :
-This is NOT a production release of Samba code.
-For production servers please run Samba 1.9.17p4
-or later releases in the 1.9.17 series.
+samba-bugs@samba.anu.edu.au
+
+Stating the version number of Samba that you
+are running, and *full details* of the steps
+we need to reproduce the problem.
+
+As always, all bugs are our responsibility.
+
+Regards,
-In this release (1.9.18alpha13) the Domain controller
-code should not be turned on. The Domain controller
-code stream is now being developed in a separate code
-development branch. To participate in this important
-work, send an email to :
+ The Samba Team.
+
+
+-------------Previous release notes-------------------------
+
+ WHATS NEW IN 1.9.17p4 - October 21st. 1997
+ ==========================================
+
+Update release: Samba - version 1.9.17p4.
+-----------------------------------------
+
+This will be the last officially released 1.9.17 version
+of Samba. Future official releases will be in the 1.9.18
+series (currently in beta).
+
+This is the latest stable release of Samba. This is the
+version that all production Samba servers should be running
+for all current bug-fixes.
+
+Here are a list of the fixes in this release (the fixes
+introduced between 1.9.17p3 and 1.9.17p4) :
+
+1). Fix in nmbd for Windows 95 machines hanging on logout !
+2). Fix for slow share mode code leaving zero length share
+ files.
+3). Fix for security = server, some broken NT4.x servers don't
+ set the guest bit on connections. New code to check logged
+ in user matches requested user.
+4). Fix for security = server. Problem with previous workaround
+ which caused machine logon restrictions on an NT server to fail.
+ This code has been completely re-written.
+5). New option 'dos filetimes' to fix UTIME_WORKAROUND problem.
+6). Fix so nmbd ignores loopback packets.
+7). Fix for nmbd ignoring WINS negative responses.
+8). New PAM support from RedHat for new PAM version.
+9). Memory leak fix when files included from an smb.conf
+ are changed.
+10). Client now logs when connecting as 'guest'.
+11). Updated documentation.
+
+Reporting bugs
+--------------
+
+The Samba Team believes that this is a stable
+production release, but all software has bugs.
+If you have problems, or think you have found a
+bug please email a report to :
samba-bugs@samba.anu.edu.au
-to get instructions on how to gain access to
-the latest Domain controller code.
+Stating the version number of Samba that you
+are running, and *full details* of the steps
+we need to reproduce the problem.
-This release contains three major changes to the
-1.9.17 series and much re-written code.
+As always, all bugs are our responsibility.
-The main changes are :
+Regards,
-1). Oplock support now operational.
------------------------------------
+ The Samba Team.
-Samba now supports 'exclusive' and 'batch' oplocks.
-These are an advanced networked file system feature
-that allows clients to obtain a exclusive use of a
-file. This allows a client to cache any changes it
-makes locally, and greatly improves performance.
-
-Windows NT has this feature and prior to this
-release this was one of the reasons Windows NT
-could be faster in some situations. Samba has
-now been benchmarked as out performing Windows
-NT on equivalently priced hardware.
-
-The oplock code in Samba has been extensively
-tested and is believed to be completely stable.
-
-Please report any problems to the samba-bugs alias.
-
-2). NetBIOS name daemon re-written.
------------------------------------
-
-The old nmbd that has caused some users problems
-has now been completely re-written and now is
-much easier to maintain and add changes to.
-
-Changes include support for multi-homed hosts
-in the same way as an NT Server with multiple
-IP interfaces behaves (registers with the WINS
-server as a multi-homed name type), and also
-support for multi-homed name registration in
-the Samba WINS server. Another added feature
-is robustness in the face of WINS server failure,
-nmbd will now keep trying to contact the WINS
-server until it is successful, in the same
-way as an NT Server.
+-------------Previous release notes-------------------------
-Also in this release is an implementation
-of the Lanman announce protocol used by
-OS/2 clients. Thanks to Jacco de Leeuw for
-this code.
+Update release: Samba - version 1.9.17p3.
+-----------------------------------------
-3). New Internationalization support.
--------------------------------------
+This is the latest stable release of Samba. This is the
+version that all production Samba servers should be running
+for all current bug-fixes.
-With this release Samba no longer needs to be
-separately compiled for Japanese (Kanji) support,
-the same binary will serve both Kanji and non-Kanji
-clients.
+Here are a list of the fixes in this release (the fixes
+introduced between 1.9.17p2 and 1.9.17p3) :
-A new method of dynamically loading client code pages
-has been added to allow the case insensitivity to
-be done dependent on the code page of the client.
+1). Removed truncation problem with long browse lists.
+2). Crash bug when dead share mode memory entries need removing.
+3). Race condition in slow share mode code.
+4). Potential buffer overflow from password server.
+5). Fix for read-prediction growing read-only files.
+6). Many quota code fixes.
+7). Fix for spelling mistake in attack warning :-).
+8). Removed 'ERRbaddirectory' error code - caused problem with
+ Visual Basic apps.
+9). Allow 'hosts allow/deny' to work before client packet parsed.
+10). Wrapping log file causes incorrect errors to be returned to
+ the clients.
+11). Crash fix for nmbd Get_Hostbyname bad return.
+12). 'become_root' 'unbecome_root' added to fix changing uid problems.
+13). No magic scripts or printing done on exceptional file close problems.
-Note that Samba still will only handle one client
-code page at a time. This will be fixed when
-Samba is fully UNICODE enabled.
-Please see the new man page for make_smbcodepage
-for details on adding additional client code page
-support.
+Security fix release: Samba - version 1.9.17p2.
+----------------------------------------------
+This new stable release fixes a very important security hole in all
+versions of Samba.
-Changed code.
--------------
+The security hole allows a remote user to obtain root access on the
+Samba server. A program which exploits this bug has been posted to the
+internet.
-Samba no longer needs the libdes library to support
-encrypted passwords. Samba now contains a restricted
-version of DES that can only be used for authentication
-purposes (to comply with the USA export encryption
-regulations and to allow USA Mirror sites to carry
-Samba source code). The 'encrypt passwords' parameter
-may now be used without recompiling.
+The security hole is only known to affect Samba servers running on
+Intel based hardware, and has only been demonstrated for Intel
+Linux. It is likley that exploits for other architectures would be
+very difficult but the possibility cannot be excluded completely.
-Much of the internals of Samba has been re-structured
-to support the oplock and Domain controller changes.
+This patch fixes the security hole for all platforms.
-An implementation of the Windows 95 automatic printer
-driver installation has been added to smbd. To use this
-new feature please read the document:
+This patch also adds a routine which will log a message when a user
+attempts to take advantage of the security hole.
-docs/PRINTER_DRIVER.txt
+A number of other minor bugs have also been fixed in this release.
-Thanks to Jean-Francois Micouleau for this new code.
+The Samba Team.
-Printer support on System V systems (notably Solaris)
-has been improved with the addition of code generously
-donated by Norm Jacobs of Sun Microsystems. Sun have
-also made a Solaris SPARC workstation available to the
-Samba Team to aid in their porting efforts.
-Samba now contains an implementation of share modes
-using System V shared memory as well as the mmap()
-based code. This was done to allow the 'FAST_SHARE_MODES'
-to be used on more systems (especially HPUX 9.x) that
-have System V shared memory, but not the mmap() call.
+-------------Previous release notes-------------------------
-The System V shared memory code is used by default on
-many systems as it has benchmarked as faster on many
-systems.
+New stable release of Samba - 1.9.17
+------------------------------------
-The Automount code has been slightly re-shuffled, such
-that the home directory (and profile location) can be
-specified by \\%N\homes and \\%N\homes\profiles
-respectively, which are the defaults for these values.
-If -DAUTOMOUNT is enabled, then %N is the server
-component of the user's NIS auto.home entry. Obviously,
-you will need to be running Samba on the user's home
-server as well as the one they just logged in on.
+This is the new stable release of Samba, superceeding
+the last stable release 1.9.16p11. All users are
+encouraged to upgrade to this new release as there have
+been many improvements to the code since that time.
-The RPC Domain code has been moved into a separate directory
-rpc_pipe/, and a LGPL License issued specifically for code
-in this directory. This is so that people can use this
-code in other projects.
+Changes since 1.9.16p11.
+------------------------
-Missing feature.
-----------------
+Improved browsing support.
+--------------------------
-One feature that we wanted to get into this release
-that was not possible due to the re-write of the nmbd
-code was the scalability features in the Samba WINS server.
-This feature is now tentatively scheduled for the next
-release (1.9.19). Apologies to anyone who was hoping
-for this feature to be included. The nmbd re-write
-will make it much easier to add such things in future.
+Samba now should support propagation of browse lists
+across subnets correctly. Look in the file docs/BROWSING.txt
+as it has been largely re-written to explain how to do this.
-New parameters in smb.conf.
----------------------------
+*IMPORTANT* All Samba servers acting as local/domain master
+browsers must be running 1.9.17 (or later).
-New Global parameters.
-----------------------
+Thanks to Silicon Graphics for allowing us to test the new
+code on their corporate network.
-Documented in the smb.conf man pages :
- "bind interfaces only"
+Improved share mode handling
+----------------------------
- "lm announce"
- "lm interval"
+The handling of share modes has been completely rewritten.
+Samba can now run agressive PC Benchmarks (Ziff-Davis
+NetBench) correctly with many hundreds of concurrent PC's.
+The confidence level on share mode handling in Samba
+is now much higher than it was previously. PC database
+packages should be safe when run against a Samba share.
+Thanks to Silicon Graphics for testing this code for us.
- "logon drive"
- "logon home"
+If at all possible compile Samba to use the new share
+mode handling with shared memory (set the flags
+FAST_SHARE_MODES in the Makefile). This will be *much* faster
+than old file-based share modes. FAST_SHARE_MODES have
+been turned on by default on the following platforms in
+the Makefile :
- "min wins ttl"
- "max wins ttl"
+ Linux
+ Solaris
+ BSDI
+ IRIX 5.x.x
+ FreeBSD
- "username level"
+Roving profile support.
+-----------------------
-New Share level parameters.
----------------------------
+Roving profiles are believed to work correctly
+with Windows NT 4.x and Windows 95. Domain logons
+are fully implemented *for Windows 95 machines only*.
-Documented in the smb.conf man pages :
- "delete veto files"
- "oplocks"
+Updated documentation
+---------------------
+All options are now documented in the smb.conf man page
+we believe. Much work has been done by Samba Team members
+to improve the quality and quantity of the Samba documentation.
+Many bugfixes and improvements
+------------------------------
+From around the 'net around the world. Many
+thanks to everyone who contributed.
-Reporting bugs.
----------------
+Commercial thanks.
+------------------
+Thanks to Cisco for the new netbios alias code support.
+Thanks to Silicon Graphics for the help with the cross
+subnet browsing and NetBench code.
+Thanks to Whistle for funding one of the Samba Team
+members.
+
+Reporting bugs
+--------------
+
+The Samba Team believes that this is a stable
+production release, but all software has bugs.
If you have problems, or think you have found a
bug please email a report to :
- samba-bugs@samba.anu.edu.au
+samba-bugs@samba.anu.edu.au
-Please state the version number of Samba that
-you are running, and *full details* of the steps
+Stating the version number of Samba that you
+are running, and *full details* of the steps
we need to reproduce the problem.
As always, all bugs are our responsibility.
@@ -195,4 +255,3 @@ As always, all bugs are our responsibility.
Regards,
The Samba Team.
-
diff --git a/docs/manpages/make_smbcodepage.1 b/docs/manpages/make_smbcodepage.1
deleted file mode 100644
index 51f572e8275..00000000000
--- a/docs/manpages/make_smbcodepage.1
+++ /dev/null
@@ -1,131 +0,0 @@
-.TH MAKE_SMBCODEPAGE 1 "16 Dec 1997" "make_smbcodepage 1.9.18alpha13"
-.SH NAME
-make_smbcodepage \- create a binary codepage definition file from an ascii codepage definition source file, or reverse the process.
-.SH SYNOPSIS
-.B make_smbcodepage
-.I c|d
-.I codepage
-.I inputfile
-.I outputfile
-.SH DESCRIPTION
-This program is part of the Samba suite.
-
-.B make_smbcodepage
-compiles or de-compiles codepage files for use with the internationalization
-features of Samba 1.9.18.
-
-An ascii Samba codepage definition file is a description that tells Samba
-how to map from upper to lower case for characters greater than ascii 127
-in the specified DOS code page. Note that for certain DOS codepages
-(437 for example) mapping from lower to upper case may be asynchronous.
-For example, in code page 437 lower case a acute maps to a plain upper
-case A when going from lower to upper case, but maps from plain upper
-case A to plain lower case a when lower casing a character.
-
-A binary Samba codepage definition file is a binary representation
-of the same information, including a value that specifies what codepage
-this file is describing.
-
-As Samba does not yet use UNICODE (current for Samba version 1.9.18)
-you must specify the client code page that your DOS and Windows clients
-are using if you wish to have case insensitivity done correctly for
-your particular language. The default codepage Samba uses is 850
-(Western European). Ascii codepage definition sample files are provided
-in the Samba distribution for codepages 437 (USA), 850 (Western European)
-852 (MS-DOS Latin 2) and 932 (Kanji SJIS). Users are encouraged to
-write ascii codepage definition files for their own code pages and
-donate them to samba-bugs@samba.anu.edu.au. All codepage files in the
-Samba source directory are compiled and installed when a 'make install'
-command is issued there.
-
-An ascii codepage definition file consists of multiple lines containing
-four fields. These fields are :
-.B lower
-which is the (hex) lower case character mapped on this line.
-.B upper
-which is the (hex) upper case character that the lower case character
-will map to.
-.B map upper to lower
-which is a boolean value (put either True or False here) which tells
-Samba if it is to map the given upper case character to the given
-lower case character when lower casing a filename.
-.B map lower to upper
-which is a boolean value (put either True or False here) which tells
-Samba if it is to map the given lower case character to the given
-upper case character when upper casing a filename.
-
-.SH OPTIONS
-.I c|d
-
-.RS 3
-This tells make_smbcodepage if it is compiling (c) an ascii code page file
-to binary, or de-compiling a binary codepage file to ascii.
-.RE
-
-.I codepage
-
-.RS 3
-This is the codepage we are processing (a number, eg. 850)
-.RE
-
-.I inputfile
-
-.RS 3
-This is the input file to process.
-.RE
-
-.I outputfile
-
-.RS 3
-This is the output file to produce.
-.RE
-
-.SH FILES
-.B codepage_def.<codepage>
-.RS 3
-These are the input (ascii) codepage files provided in the Samba
-source/ directory.
-.RE
-.SH FILES
-.B codepage.<codepage>
-.RS 3
-These are the output (binary) codepage files produced and placed in the Samba
-destination lib/codepage/ directory.
-.RE
-
-.SH ENVIRONMENT VARIABLES
-Not applicable.
-.SH INSTALLATION
-The location of the server and its support files is a matter for individual
-system administrators. The following are thus suggestions only.
-
-It is recommended that the
-.B make_smbcodepage
-program be installed under the /usr/local/samba hierarchy, in a directory readable
-by all, writeable only by root. The program itself should be executable by all.
-The program should NOT be setuid or setgid!
-.SH VERSION
-This man page is (mostly) correct for version 1.9.18 of the Samba suite, plus some
-of the recent patches to it. These notes will necessarily lag behind
-development of the software, so it is possible that your version of
-the program has extensions or parameter semantics that differ from or are not
-covered by this man page. Please notify these to the address below for
-rectification.
-.SH SEE ALSO
-.BR smb.conf (5),
-.BR smbd (8)
-
-.SH BUGS
-None known.
-.SH CREDITS
-The
-.B make_smbcodepage
-program was written by Jeremy Allison (jallison@whistle.com) as part of the
-Internationalization effort of the Samba software.
-
-Please send bug reports to samba-bugs@samba.anu.edu.au.
-
-See
-.BR samba (7)
-for a full list of contributors and details on how to
-submit bug reports, comments etc.
diff --git a/docs/manpages/nmbd.8 b/docs/manpages/nmbd.8
index ce530eb6209..a238a83a2aa 100644
--- a/docs/manpages/nmbd.8
+++ b/docs/manpages/nmbd.8
@@ -1,4 +1,4 @@
-.TH NMBD 8 "16 Dec 1997" "nmbd 1.9.18alpha13"
+.TH NMBD 8 "20 Dec 1997" "nmbd 1.9.17p5"
.SH NAME
nmbd \- provide netbios nameserver support to clients
.SH SYNOPSIS
@@ -186,13 +186,6 @@ The default log file is specified at compile time, typically as
This option allows you to override the Netbios name that Samba uses for itself.
.RE
-.B \-a
-
-.RS 3
-If this parameter is specified, the log files will be appended to with each
-new connection. By default, the log files will be overwritten.
-.RE
-
.B \-p
.I port number
.RS 3
diff --git a/docs/manpages/samba.7 b/docs/manpages/samba.7
index 0698f051e1a..61798f6b17f 100644
--- a/docs/manpages/samba.7
+++ b/docs/manpages/samba.7
@@ -1,4 +1,4 @@
-.TH SAMBA 7 "16 Dec 1997" "samba 1.9.18alpha13"
+.TH SAMBA 7 "20 Dec 1997" "samba 1.9.17p5"
.SH NAME
Samba \- a LanManager like fileserver for UNIX
.SH SYNOPSIS
diff --git a/docs/manpages/smb.conf.5 b/docs/manpages/smb.conf.5
index 77624737186..a3fe2371b26 100644
--- a/docs/manpages/smb.conf.5
+++ b/docs/manpages/smb.conf.5
@@ -1,4 +1,4 @@
-.TH SMB.CONF 5 "16 Dec 1997" "smb.conf 1.9.18alpha13"
+.TH SMB.CONF 5 "20 Dec 1997" "smb.conf 1.9.17p5"
.SH NAME
smb.conf \- configuration file for smbd
.SH SYNOPSIS
@@ -210,12 +210,6 @@ could be used simply to limit access to a subset of your local printers.
An alias, by the way, is defined as any component of the first entry of a
printcap record. Records are separated by newlines, components (if there are
more than one) are separated by vertical bar symbols ("|").
-
-NOTE: On SYSV systems which use lpstat to determine what printers are
-defined on the system you may be able to use "printcap name = lpstat"
-to automatically obtain a list of printers. See the "printcap name"
-option for more detils.
-
.RE
.SH PARAMETERS
Parameters define the specific attributes of services.
@@ -272,13 +266,6 @@ personality".
%M = the internet name of the client machine
-%N = the name of your NIS home directory server. This is obtained from
-your NIS auto.map entry. If you have not compiled Samba with -DAUTOMOUNT
-then this value will be the same as %L.
-
-%R = the selected protocol level after protocol negotiation. As of
-Samba 1.9.18 it can be one of CORE, COREPLUS, LANMAN1, LANMAN2 or NT1.
-
%d = The process id of the current server process
%a = the architecture of the remote machine. Only some are recognised,
@@ -295,9 +282,9 @@ substitutions and other smb.conf options.
.SS NAME MANGLING
-Samba supports "name mangling" so that DOS and Windows clients can use
-files that don't conform to the 8.3 format. It can also be set to adjust
-the case of 8.3 format filenames.
+Samba supports "name mangling" so that older DOS and Windows 3 clients
+can use files that don't conform to the 8.3 format. It can also be set
+to adjust the case of 8.3 format filenames.
There are several options that control the way mangling is performed,
and they are grouped here rather than listed separately. For the
@@ -340,8 +327,6 @@ announce version
auto services
-bind interfaces only
-
browse list
character set
@@ -382,14 +367,8 @@ hosts equiv
include
-interfaces
-
keepalive
-lm announce
-
-lm interval
-
lock dir
load printers
@@ -402,10 +381,6 @@ log file
log level
-logon drive
-
-logon home
-
logon path
logon script
@@ -424,12 +399,8 @@ max ttl
max xmit
-max wins ttl
-
message command
-min wins ttl
-
netbios aliases
netbios name
@@ -454,9 +425,9 @@ preferred master
preload
-printcap name
+printing
-printer driver file
+printcap name
protocol
@@ -508,8 +479,6 @@ time server
unix realname
-username level
-
username map
use rhosts
@@ -553,8 +522,6 @@ default case
delete readonly
-delete veto files
-
deny hosts
directory
@@ -629,8 +596,6 @@ only guest
only user
-oplocks
-
path
postexec
@@ -643,10 +608,6 @@ print command
printer driver
-printer driver location
-
-printing
-
print ok
printable
@@ -685,8 +646,6 @@ users
valid users
-veto oplock files
-
volume
wide links
@@ -841,40 +800,6 @@ ALL attempts to connect to the service will fail. Such failures are logged.
.B Example:
available = no
-
-.SS bind interfaces only (G)
-This global parameter (new for 1.9.18) allows the Samba admin to limit
-what interfaces on a machine will serve smb requests. If affects file service
-(smbd) and name service (nmbd) in slightly different ways.
-
-For name service it causes nmbd to bind to ports 137 and 138 on
-the interfaces listed in the 'interfaces' parameter. nmbd also binds
-to the 'all addresses' interface (0.0.0.0) on ports 137 and 138
-for the purposes of reading broadcast messages. If this option is
-not set then nmbd will service name requests on all of these
-sockets. If "bind interfaces only" is set then nmbd will check
-the source address of any packets coming in on the broadcast
-sockets and discard any that don't match the broadcast addresses
-of the interfaces in the 'interfaces' parameter list. As unicast
-packets are received on the other sockets it allows nmbd to
-refuse to serve names to machines that send packets that arrive
-through any interfaces not listed in the 'interfaces' list.
-IP Source address spoofing does defeat this simple check, however
-so it must not be used seriously as a security feature for nmbd.
-
-For file service it causes smbd to bind only to the interface
-list given in the 'interfaces' parameter. This restricts the
-networks that smbd will serve to packets coming in those interfaces.
-Note that you should not use this parameter for machines that
-are serving ppp or other intermittant or non-broadcast network
-interfaces as it will not cope with non-permanent interfaces.
-
-.B Default:
- bind interfaces only = False
-
-.B Example:
- bind interfaces only = True
-
.SS browseable (S)
This controls whether this share is seen in the list of available
shares in a net view and in the browse list.
@@ -1117,34 +1042,6 @@ override this one. Where the lists conflict, the 'allow' list takes precedence.
.B Example:
deny hosts = 150.203.4. badhost.mynet.edu.au
-
-.SS delete veto files (S)
-
-This option is used when Samba is attempting to delete a directory
-that contains one or more vetoed directories (see the 'veto files' option).
-If this option is set to False (the default) then if a vetoed directory
-contains any non-vetoed files or directories then the directory delete
-will fail. This is usually what you want.
-
-If this option is set to True, then Samba will attempt
-to recursively delete any files and directories within the vetoed
-directory. This can be useful for integration with file serving
-systems such as Netatalk, which create meta-files within directories
-you might normally veto DOS/Windows users from seeing (eg. .AppleDouble)
-
-Setting 'delete veto files = True' allows these directories to be
-transparently deleted when the parent directory is deleted (so long
-as the user has permissions to do so).
-
-.B Default:
- delete veto files = False
-
-.B Example:
- delete veto files = True
-
-See
-.B veto files
-
.SS dfree command (G)
The dfree command setting should only be used on systems where a
problem occurs with the internal disk space calculations. This has
@@ -1226,7 +1123,6 @@ files.
.B Example:
directory mask = 0775
-
.SS directory mode (S)
See
.B directory mask.
@@ -1330,8 +1226,11 @@ only one accessing the file and it will aggressively cache file
data. With some oplock types the client may even cache file open/close
operations. This can give enormous performance benefits.
-When you set "fake oplocks = yes" Samba will always grant oplock
-requests no matter how many clients are using the file.
+Samba does not support opportunistic locks in this release. Samba can
+fake them, however, by granting a oplock whenever a client asks for
+one. This is controlled using the smb.conf option "fake oplocks". If
+you set "fake oplocks = yes" then you are telling the client that it
+may aggressively cache the file data.
By enabling this option on all read-only shares or shares that you know
will only be accessed from one client at a time you will see a big
@@ -1340,9 +1239,6 @@ on shares where multiple clients may be accessing the files read-write
at the same time you can get data corruption. Use this option
carefully!
-It is generally much better to use the real oplock support except for
-physically read-only media such as CDROMs.
-
This option is disabled by default.
.SS follow symlinks (S)
@@ -1643,54 +1539,15 @@ difficulties.
.B Example:
keep alive = 60
-
-.SS lm announce (G)
-
-This parameter determines if Samba will produce Lanman announce
-broadcasts that are needed by OS/2 clients in order for them to
-see the Samba server in their browse list. This parameter can
-have three values, true, false, or auto. The default is auto.
-If set to False Samba will never produce these broadcasts. If
-set to true Samba will produce Lanman announce broadcasts at
-a frequency set by the parameter 'lm interval'. If set to auto
-Samba will not send Lanman announce broadcasts by default but
-will listen for them. If it hears such a broadcast on the wire
-it will then start sending them at a frequency set by the parameter
-'lm interval'.
-
-See also "lm interval".
-
-.B Default:
- lm announce = auto
-
-.B Example:
- lm announce = true
-
-.SS lm interval (G)
-
-If Samba is set to produce Lanman announce broadcasts needed
-by OS/2 clients (see the "lm announce" parameter) this parameter
-defines the frequency in seconds with which they will be made.
-If this is set to zero then no Lanman announcements will be
-made despite the setting of the "lm announce" parameter.
-
-See also "lm announce".
-
-.B Default:
- lm interval = 60
-
-.B Example:
- lm interval = 120
-
.SS load printers (G)
A boolean variable that controls whether all printers in the printcap
will be loaded for browsing by default.
.B Default:
- load printers = yes
+ load printers = no
.B Example:
- load printers = no
+ load printers = yes
.SS local master (G)
This option allows the nmbd to become a local master browser on a
@@ -1712,7 +1569,6 @@ The lock files are used to implement the "max connections" option.
.B Example:
lock directory = /usr/local/samba/var/locks
-
.SS locking (S)
This controls whether or not locking will be performed by the server in
response to lock requests from the client.
@@ -1748,30 +1604,6 @@ separate log files for each user or machine.
.SS log level (G)
see "debug level"
-.SS logon drive (G)
-
-This parameter specifies the local path to which the home directory
-will be connected (see "logon home") and is only used by NT Workstations.
-
-.B Example:
- logon drive = h:
-
-.SS logon home (G)
-
-This parameter specifies the home directory location when a Win95 or
-NT Workstation logs into a Samba PDC. It allows you to do "NET USE
-H: /HOME" from a command prompt, for example.
-
-.B
-This option takes the standard substitutions, allowing you to have
-separate logon scripts for each user or machine.
-
-.B Example:
- logon home = "\\\\remote_smb_server\\%U"
-
-.B Default:
- logon home = "\\\\%N\\%U"
-
.SS logon path (G)
This parameter specifies the home directory where roaming profiles
@@ -1796,14 +1628,10 @@ read-only - rename it to USER.MAN to achieve the desired effect
Windows clients can sometimes maintain a connection to the [homes]
share, even though there is no user logged in. Therefore, it is
vital that the logon path does not include a reference to the
-homes share (i.e \\\\%N\\HOMES\profile_path will cause problems).
-
-.B
-This option takes the standard substitutions, allowing you to have
-separate logon scripts for each user or machine.
+homes share (i.e \\\\%L\\HOMES\profile_path will cause problems).
.B Default:
- logon path = \\\\%N\\%U\\profile
+ logon path = \\\\%L\\%U\\profile
.B Example:
logon path = \\\\PROFILESERVER\\HOME_DIR\\%U\\PROFILE
@@ -2228,23 +2056,10 @@ A synonym for this parameter is 'packet size'.
.SS max ttl (G)
This option tells nmbd what the default 'time to live' of NetBIOS
-names should be (in seconds) when nmbd is requesting a name using
-either a broadcast or from a WINS server. You should never need to
-change this parameter.
+names should be (in seconds). You should never need to change this parameter.
.B Default:
max ttl = 14400
-
-.SS max wins ttl (G)
-
-This option tells nmbd when acting as a WINS server (wins support = true)
-what the maximum 'time to live' of NetBIOS names that nmbd will grant will
-be (in seconds). You should never need to change this parameter.
-The default is 3 days (259200 seconds).
-
-.B Default:
- max wins ttl = 259200
-
.SS max xmit (G)
This option controls the maximum packet size that will be negotiated
@@ -2332,17 +2147,6 @@ kilobytes. The default is 0, which means no limit.
.B Example:
min print space = 2000
-.SS min wins ttl (G)
-
-This option tells nmbd when acting as a WINS server (wins support = true)
-what the minimum 'time to live' of NetBIOS names that nmbd will grant will
-be (in seconds). You should never need to change this parameter.
-The default is 6 hours (21600 seconds).
-
-.B Default:
- min wins ttl = 21600
-
-
.SS netbios aliases (G)
This is a list of names that nmbd will advertise as additional
@@ -2421,25 +2225,6 @@ of the user.
.B Example:
only user = True
-.SS oplocks (S)
-This boolean option tells smbd whether to issue oplocks (opportunistic
-locks) to file open requests on this share. The oplock code was introduced in
-Samba 1.9.18 and can dramatically (approx 30% or more) improve the speed
-of access to files on Samba servers. It allows the clients to agressively
-cache files locally and you may want to disable this option for unreliable
-network environments (it is turned on by default in Windows NT Servers).
-For more information see the file Speed.txt in the Samba docs/ directory.
-
-Oplocks may be selectively turned off on certain files on a per share basis.
-See the 'veto oplock files' parameter.
-
-.B Default:
- oplocks = True
-
-.B Example:
- oplocks = False
-
-
.SS os level (G)
This integer value controls what level Samba advertises itself as for
browse elections. See BROWSING.txt for details.
@@ -2765,13 +2550,9 @@ This parameter may be used to override the compiled-in default printcap
name used by the server (usually /etc/printcap). See the discussion of the
[printers] section above for reasons why you might want to do this.
-On SystemV systems that use lpstat to list available printers you
-can use "printcap name = lpstat" to automatically obtain lists of
-available printers. This is the default for systems that define
-SYSV at compile time in Samba (this includes most SystemV based
-systems). If "printcap name" is set to lpstat on these systems then
-Samba will launch "lpstat -v" and attempt to parse the output to
-obtain a printer list.
+For those of you without a printcap (say on SysV) you can just create a
+minimal file that looks like a printcap and set "printcap name =" in
+[global] to point at it.
A minimal printcap file would look something like this:
@@ -2797,7 +2578,6 @@ will assume the file is in AIX "qconfig" format if the string
.B Example:
printcap name = /etc/myprintcap
-
.SS printer (S)
A synonym for this parameter is 'printer name'.
@@ -2833,51 +2613,7 @@ scrollbox after you have chosen the printer manufacturer.
See
.B printer.
-.SS printer driver file (G)
-This parameter tells Samba where the printer driver definition file,
-used when serving drivers to Windows 95 clients, is to be found. If
-this is not set, the default is :
-
-SAMBA_INSTALL_DIRECTORY/lib/printers.def
-
-This file is created from Windows 95 'msprint.def' files found on the
-Windows 95 client system. For more details on setting up serving of
-printer drivers to Windows 95 clients, see the documentation file
-docs/PRINTER_DRIVER.txt.
-
-.B Default:
- None (set in compile).
-
-.B Example:
- printer driver file = /usr/local/samba/printers/drivers.def
-
-Related parameters.
-.B printer driver location
-
-.SS printer driver location (S)
-This parameter tells clients of a particular printer share where
-to find the printer driver files for the automatic installation
-of drivers for Windows 95 machines. If Samba is set up to serve
-printer drivers to Windows 95 machines, this should be set to
-
-\e\eMACHINE\ePRINTER$
-
-Where MACHINE is the NetBIOS name of your Samba server, and PRINTER$
-is a share you set up for serving printer driver files. For more
-details on setting this up see the documentation file
-docs/PRINTER_DRIVER.txt.
-
-.B Default:
- None
-
-.B Example:
- printer driver location = \e\eMACHINE\ePRINTER$
-
-Related paramerers.
-.B printer driver file
-
-
-.SS printing (S)
+.SS printing (G)
This parameters controls how printer status information is interpreted
on your system, and also affects the default values for the "print
command", "lpq command" and "lprm command".
@@ -2889,7 +2625,6 @@ bsd", "printing = sysv", "printing = hpux", "printing = aix",
To see what the defaults are for the other print commands when using
these three options use the "testparm" program.
-As of version 1.9.18 of Samba this option can be set on a per printer basis
.SS protocol (G)
The value of the parameter (a string) is the highest protocol level that will
@@ -3490,26 +3225,6 @@ on how this parameter determines access to the services.
username = fred
username = fred, mary, jack, jane, @users, @pcgroup
-.SS username level (G)
-
-This option helps Samba to try and 'guess' at the real UNIX username,
-as many DOS clients send an all-uppercase username. By default Samba
-tries all lowercase, followed by the username with the first letter
-capitalized, and fails if the username is not found on the UNIX machine.
-
-If this parameter is set to non-zero the behaviour changes. This
-parameter is a number that specifies the number of uppercase combinations
-to try whilst trying to determine the UNIX user name. The higher the number
-the more combinations will be tried, but the slower the discovery
-of usernames will be. Use this parameter when you have strange
-usernames on your UNIX machine, such as 'AstrangeUser'.
-
-.B Default:
- username level = 0
-
-.B Example:
- username level = 5
-
.SS username map (G)
This option allows you to to specify a file containing a mapping of
@@ -3534,11 +3249,6 @@ then continues with the next line.
If any line begins with a '#' or a ';' then it is ignored
-If any line begins with an ! then the processing will stop after that
-line if a mapping was done by the line. Otherwise mapping continues
-with every line being processed. Using ! is most useful when you have
-a wildcard mapping line later in the file.
-
For example to map from the name "admin" or "administrator" to the UNIX
name "root" you would use
@@ -3559,14 +3269,6 @@ quotes around the name. For example:
would map the windows username "Andrew Tridgell" to the unix username
tridge.
-The following example would map mary and fred to the unix user sys,
-and map the rest to guest. Note the use of the ! to tell Samba to stop
-processing if it gets a match on that line.
-
- !sys = mary fred
- guest = *
-
-
Note that the remapping is applied to all occurrences of
usernames. Thus if you connect to "\e\eserver\efred" and "fred" is
remapped to "mary" then you will actually be connecting to
@@ -3698,25 +3400,6 @@ See also "hide files" and "case sensitive"
veto files = /.AppleDouble/.bin/.AppleDesktop/Network Trash Folder/
-.SS veto oplock files (S)
-This parameter is only valid when the 'oplocks' parameter is turned on
-for a share. It allows the Samba administrator to selectively turn off
-the granting of oplocks on selected files that match a wildcarded list,
-similar to the wildcarded list used in the 'veto files' parameter.
-
-.B Default
- No files are vetoed for oplock grants.
-
-.B Examples
-You might want to do this on files that you know will be heavily
-contended for by clients. A good example of this is in the NetBench
-SMB benchmark program, which causes heavy client contention for files
-ending in .SEM. To cause Samba not to grant oplocks on these files
-you would use the line (either in the [global] section or in the section
-for the particular NetBench share :
-
- veto oplock files = /*.SEM/
-
.SS volume (S)
This allows you to override the volume label returned for a
share. Useful for CDROMs with installation programs that insist on a
@@ -3765,7 +3448,6 @@ network.
.B Default:
wins support = no
-
.SS workgroup (G)
This controls what workgroup your server will appear to be in when
@@ -3879,7 +3561,7 @@ administrator easy, but the various combinations of default attributes can be
tricky. Take extreme care when designing these sections. In particular,
ensure that the permissions on spool directories are correct.
.SH VERSION
-This man page is (mostly) correct for version 1.9.18 of the Samba suite, plus some
+This man page is (mostly) correct for version 1.9.16 of the Samba suite, plus some
of the recent patches to it. These notes will necessarily lag behind
development of the software, so it is possible that your version of
the server has extensions or parameter semantics that differ from or are not
diff --git a/docs/manpages/smbclient.1 b/docs/manpages/smbclient.1
index a01d317bb7f..8ca91057693 100644
--- a/docs/manpages/smbclient.1
+++ b/docs/manpages/smbclient.1
@@ -1,4 +1,4 @@
-.TH SMBCLIENT 1 "16 Dec 1997" "smbclient 1.9.18alpha13"
+.TH SMBCLIENT 1 "20 Dec 1997" "smbclient 1.9.17p5"
.SH NAME
smbclient \- ftp-like Lan Manager client program
.SH SYNOPSIS
@@ -257,13 +257,6 @@ If no
is supplied and neither environment variable exists the user name will
be empty.
-If the USER environment variable containts a '%' character, everything
-after that will be treated as a password. This allows you to set the
-environment variable to be
-.B USER=username%password
-so that a password is not passed on the command line (where it may
-be seen by the ps command).
-
If the service you are connecting to requires a password, it can be supplied
using the
.B \-U
diff --git a/docs/manpages/smbd.8 b/docs/manpages/smbd.8
index f7ef71bd2ff..12f8ae3d696 100644
--- a/docs/manpages/smbd.8
+++ b/docs/manpages/smbd.8
@@ -1,4 +1,4 @@
-.TH SMBD 8 "16 Dec 1997" "smbd 1.9.18alpha13"
+.TH SMBD 8 "20 Dec 1997" "smbd 1.9.17p5"
.SH NAME
smbd \- provide SMB (aka LanManager) services to clients
.SH SYNOPSIS
@@ -27,11 +27,10 @@ smbd \- provide SMB (aka LanManager) services to clients
This program is part of the Samba suite.
.B smbd
-is a server that can provide most SMB services. The server provides
-filespace and printer services to clients using the SMB protocol. This
-is compatible with the LanManager protocol, and can service LanManager
-clients. These include MSCLIENT 3.0 for DOS, Windows for Workgroups,
-Windows 95, Windows NT, OS/2, DAVE for Macintosh, and smbfs for Linux.
+is a server that can provide most SMB services. The
+server provides filespace and printer services to clients using the SMB
+protocol. This is compatible with the LanManager protocol, and can
+service LanManager clients.
An extensive description of the services that the server can provide is given
in the man page for the configuration file controlling the attributes of those
@@ -51,11 +50,8 @@ of the server for each session. This copy then services all connections made
by the client during that session. When all connections from its client are
are closed, the copy of the server for that client terminates.
-The configuration file, and any files that it includes, are automatically
-reloaded every minute, if they change. You can force a reload by sending a
-SIGHUP to the server. Reloading the configuration file will not affect
-connections to any service that is already established. Either the user
-will have to disconnect from the service, or smbd killed and restarted.
+The configuration file is automatically reloaded if it changes. You
+can force a reload by sending a SIGHUP to the server.
.SH OPTIONS
.B \-D
@@ -78,7 +74,7 @@ new connection. By default, the log files will be appended to.
.I debuglevel
.RS 3
-debuglevel is an integer from 0 to 10.
+debuglevel is an integer from 0 to 5.
The default value if this parameter is not specified is zero.
@@ -142,10 +138,6 @@ user rather than as root, most systems will require you to use a port number
greater than 1024 - ask your system administrator for help if you are in this
situation.
-In order for the server to be useful by most clients, should you configure
-it on a port other than 139, you will require port redirection services
-on port 139, details of which are outlined in rfc1002.txt section 4.3.5.
-
This parameter is not normally specified except in the above situation.
.RE
@@ -382,8 +374,8 @@ To properly test and experiment with the server, we recommend using the
smbclient program (see
.BR smbclient (1)).
.SH VERSION
-This man page is (mostly) correct for version 1.9.00 of the Samba suite,
-plus some of the recent patches to it. These notes will necessarily lag behind
+This man page is (mostly) correct for version 1.9.00 of the Samba suite, plus some
+of the recent patches to it. These notes will necessarily lag behind
development of the software, so it is possible that your version of
the server has extensions or parameter semantics that differ from or are not
covered by this man page. Please notify these to the address below for
@@ -396,8 +388,6 @@ rectification.
.BR smbclient (1),
.BR testparm (1),
.BR testprns (1)
-.BR rfc1001.txt
-.BR rfc1002.txt
.SH DIAGNOSTICS
[This section under construction]
diff --git a/docs/manpages/smbpasswd.8 b/docs/manpages/smbpasswd.8
index a1039cbef26..da390c0261e 100644
--- a/docs/manpages/smbpasswd.8
+++ b/docs/manpages/smbpasswd.8
@@ -1,4 +1,4 @@
-.TH SMBPASSWD 8 "16 Dec 1997" "smbpasswd 1.9.18alpha13"
+.TH SMBPASSWD 8 "20 Dec 1997" "smbpasswd 1.9.17p5"
.SH NAME
smbpasswd \- change a users smb password in the smbpasswd file.
.SH SYNOPSIS
diff --git a/docs/manpages/smbrun.1 b/docs/manpages/smbrun.1
index f3fc7c46b3a..2dfab9d24e8 100644
--- a/docs/manpages/smbrun.1
+++ b/docs/manpages/smbrun.1
@@ -1,4 +1,4 @@
-.TH SMBRUN 1 "16 Dec 1997" "smbrun 1.9.18alpha13"
+.TH SMBRUN 1 "20 Dec 1997" "smbrun 1.9.17p5"
.SH NAME
smbrun \- interface program between smbd and external programs
.SH SYNOPSIS
diff --git a/docs/manpages/smbstatus.1 b/docs/manpages/smbstatus.1
index 17d6bc222ae..3df3bb7190c 100644
--- a/docs/manpages/smbstatus.1
+++ b/docs/manpages/smbstatus.1
@@ -1,4 +1,4 @@
-.TH SMBSTATUS 1 "16 Dec 1997" "smbstatus 1.9.18alpha13"
+.TH SMBSTATUS 1 "20 Dec 1997" "smbstatus 1.9.17p5"
.SH NAME
smbstatus \- report on current Samba connections
.SH SYNOPSIS
diff --git a/docs/manpages/smbtar.1 b/docs/manpages/smbtar.1
index cf1dc9d4aad..dd8805ffdd5 100644
--- a/docs/manpages/smbtar.1
+++ b/docs/manpages/smbtar.1
@@ -1,4 +1,4 @@
-.TH SMBTAR 1 "16 Dec 1997" "smbtar 1.9.18alpha13"
+.TH SMBTAR 1 "20 Dec 1997" "smbtar 1.9.17p5"
.SH NAME
smbtar \- shell script for backing up SMB shares directly to UNIX tape drive
.SH SYNOPSIS
diff --git a/docs/manpages/testparm.1 b/docs/manpages/testparm.1
index b39dcd7e723..9a640f90d29 100644
--- a/docs/manpages/testparm.1
+++ b/docs/manpages/testparm.1
@@ -1,4 +1,4 @@
-.TH TESTPARM 1 "16 Dec 1997" "testparm 1.9.18alpha13"
+.TH TESTPARM 1 "20 Dec 1997" "testparm 1.9.17p5"
.SH NAME
testparm \- check an smbd configuration file for internal correctness
.SH SYNOPSIS
diff --git a/docs/manpages/testprns.1 b/docs/manpages/testprns.1
index a0a1b02f2df..cc7bcc18c90 100644
--- a/docs/manpages/testprns.1
+++ b/docs/manpages/testprns.1
@@ -1,4 +1,4 @@
-.TH TESTPRNS 1 "16 Dec 1997" "testprns 1.9.18alpha13"
+.TH TESTPRNS 1 "20 Dec 1997" "testprns 1.9.17p5"
.SH NAME
testprns \- check printer name for validity with smbd
.SH SYNOPSIS
diff --git a/docs/textdocs/Application_Serving.txt b/docs/textdocs/Application_Serving.txt
index 82ee83e2072..788941f719f 100644
--- a/docs/textdocs/Application_Serving.txt
+++ b/docs/textdocs/Application_Serving.txt
@@ -1,5 +1,5 @@
!==
-!== Application_Serving.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== Application_Serving.txt for Samba release 1.9.17p5 20 Dec 1997
!==
January 7, 1997
Updated: June 27, 1997
diff --git a/docs/textdocs/BROWSING.txt b/docs/textdocs/BROWSING.txt
index 782ca1b0ef0..f7f45d7c7fe 100644
--- a/docs/textdocs/BROWSING.txt
+++ b/docs/textdocs/BROWSING.txt
@@ -1,8 +1,8 @@
!==
-!== BROWSING.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== BROWSING.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Author/s: Many (Thanks to Luke, Jeremy, Andrew, etc.)
-Updated: October 12, 1997
+Updated: June 29, 1997
Status: Current - For VERY Advanced Users ONLY
Summary: This describes how to configure Samba for improved browsing.
@@ -84,11 +84,10 @@ in smb.conf)
BROWSING ACROSS SUBNETS
=======================
-With the release of Samba 1.9.17(alpha1 and above) Samba has been
-updated to enable it to support the replication of browse lists
-across subnet boundaries. New code and options have been added to
-achieve this. This section describes how to set this feature up
-in different settings.
+With the release of Samba 1.9.17, Samba has been updated to enable
+it to support the replication of browse lists across subnet
+boundaries. New code and options have been added to achieve this.
+This section describes how to set this feature up in different settings.
To see browse lists that span TCP/IP subnets (ie. networks separated
by routers that don't pass broadcast traffic) you must set up at least
diff --git a/docs/textdocs/BUGS.txt b/docs/textdocs/BUGS.txt
index f5766a190d7..101154101cc 100644
--- a/docs/textdocs/BUGS.txt
+++ b/docs/textdocs/BUGS.txt
@@ -1,5 +1,5 @@
!==
-!== BUGS.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== BUGS.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: Samba Team
Updated: June 27, 1997
diff --git a/docs/textdocs/DIAGNOSIS.txt b/docs/textdocs/DIAGNOSIS.txt
index c321452b4b2..93b223fedd8 100644
--- a/docs/textdocs/DIAGNOSIS.txt
+++ b/docs/textdocs/DIAGNOSIS.txt
@@ -1,5 +1,5 @@
!==
-!== DIAGNOSIS.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== DIAGNOSIS.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: Andrew Tridgell
Updated: October 14, 1997
diff --git a/docs/textdocs/DNIX.txt b/docs/textdocs/DNIX.txt
index bfe51f41295..edd6ba9bf00 100644
--- a/docs/textdocs/DNIX.txt
+++ b/docs/textdocs/DNIX.txt
@@ -1,5 +1,5 @@
!==
-!== DNIX.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== DNIX.txt for Samba release 1.9.17p5 20 Dec 1997
!==
DNIX has a problem with seteuid() and setegid(). These routines are
needed for Samba to work correctly, but they were left out of the DNIX
diff --git a/docs/textdocs/DOMAIN.txt b/docs/textdocs/DOMAIN.txt
index 9b3888d64ea..61372cd46cd 100644
--- a/docs/textdocs/DOMAIN.txt
+++ b/docs/textdocs/DOMAIN.txt
@@ -1,5 +1,5 @@
!==
-!== DOMAIN.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== DOMAIN.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: Samba Team
Updated: June 27, 1997
@@ -44,29 +44,21 @@ cannot be implemented with an underlying username database which is
different from the Windows NT SAM. Support for the Remote Administration
Protocol is planned for a future release of Samba.
-The domain support works for WfWg, and Win95 clients and NT 4.0 and 3.51.
-Domain support is currently at an early experimental stage for NT 4.0 and
-NT 3.51. Support for Windows OS/2 clients is still being worked on and is
-still experimental.
+The domain support works for WfWg, and Win95 clients. Support for Windows
+NT and OS/2 clients is still being worked on and is still experimental.
+Support for profiles is confirmed as working for Win95, NT 4.0 and NT 3.51,
+although NT Workstation requires manual configuration of user accounts with
+NT's "User Manager for Domains", and no automatic profile location support
+is available using samba, although it has been confirmed as possible to use
+an NT server to specify that the location of profiles is on a samba server.
-Support for profiles is confirmed as working for Win95, NT 4.0 and NT 3.51.
-It is possible to specify: the profile location; script file to be loaded
-on login; the user's home directory; and for NT a kick-off time could also
-now easily be supported.
-
-With NT Workstations, all this does not require the use or intervention of
-an NT 4.0 or NT 3.51 server: Samba can now replace the logon services
-provided by an NT server, to a limited and experimental degree (for example,
-running "User Manager for Domains" will not provide you with access to
-a domain created by a Samba Server).
-
-With Win95, the help of an NT server can be enlisted, both for profile storage
-and for user authentication. For details on user authentication, see
+The help of an NT server can be enlisted, both for profile storage and
+for user authentication. For details on user authentication, see
security_level.txt. For details on profile storage, see below.
Using these features you can make your clients verify their logon via
-the Samba server; make clients run a batch file when they logon to
+the Samba server, make clients run a batch file when they logon to
the network and download their preferences, desktop and start menu.
@@ -81,7 +73,9 @@ To use domain logons and profiles you need to do the following:
for details.
2) Setup a WINS server (see NetBIOS.txt) and configure all your clients
- to use that WINS service.
+ to use that WINS service. [lkcl 12jul97 - problems occur where
+ clients do not pick up the profiles properly unless they are using a
+ WINS server. this is still under investigation].
3) Create a share called [netlogon] in your smb.conf. This share should
be readable by all users, and probably should not be writeable. This
@@ -145,8 +139,8 @@ In the [global] section of smb.conf set the following (for example):
logon path = \\profileserver\profileshare\profilepath\%U\moreprofilepath
-The default for this option is \\%N\%U\profile, namely
-\\sambaserver\username\profile. The \\N%\%U service is created
+The default for this option is \\%L\%U\profile, namely
+\\sambaserver\username\profile. The \\L%\%U services is created
automatically by the [homes] service.
If you are using a samba server for the profiles, you _must_ make the
@@ -279,18 +273,15 @@ Windows NT Workstation 4.0
--------------------------
When a user first logs in to a Windows NT Workstation, the profile
-NTuser.DAT is created. The profile location can be now specified
-through the "logon path" parameter, in exactly the same way as it
-can for Win95. [lkcl 10aug97 - i tried setting the path to
-\\samba-server\homes\profile, and discovered that this fails because
-a background process maintains the connection to the [homes] share
-which does _not_ close down in between user logins. you have to
-have \\samba-server\%L\profile, where user is the username created
-from the [homes] share].
-
-There is a parameter that is now available for use with NT Profiles:
-"logon drive". This should be set to "h:" or any other drive, and
-should be used in conjunction with the new "logon home" parameter.
+NTuser.MAN is created. The "User Manager for Domains" can be used
+to specify the location of the profile. Samba cannot be a domain
+logon server for NT, therefore you will need to manually configure
+each and every account. [lkcl 10aug97 - i tried setting the path
+in each account to \\samba-server\homes\profile, and discovered that
+this fails because a background process maintains the connection to
+the [homes] share which does _not_ close down in between user logins.
+you have to have \\samba-server\user\profile, where user is the
+username created from the [homes] share].
The entry for the NT 4.0 profile is a _directory_ not a file. The NT
help on profiles mentions that a directory is also created with a .PDS
@@ -323,7 +314,7 @@ matter to be resolved].
[lkcl 20aug97 - after samba digest correspondance, one user found, and
another confirmed, that profiles cannot be loaded from a samba server
-unless "security = user" and "encrypt passwords = yes" (see the file
+unless "security = user" and "encrypted passwords = yes" (see the file
ENCRYPTION.txt) or "security = server" and "password server = ip.address.
of.yourNTserver" are used. either of these options will allow the NT
workstation to access the samba server using LAN manager encrypted
@@ -338,17 +329,18 @@ a mandatory profile, NTuser.MAN].
Windows NT Server
-----------------
-There is nothing to stop you specifying any path that you like for the
-location of users' profiles. Therefore, you could specify that the
-profile be stored on a samba server, or any other SMB server, as long as
-that SMB server supports encrypted passwords.
+Following the instructions for NT Workstation, there is nothing to stop
+you specifying any path that you like for the location of users' profiles.
+Therefore, you could specify that the profile be stored on a samba server,
+or any other SMB server, as long as that SMB server supports encrypted
+passwords.
Sharing Profiles between W95 and NT Workstation 4.0
---------------------------------------------------
-The default logon path is \\%N\U%. NT Workstation will attempt to create
+The default logon path is \\%L\U%. NT Workstation will attempt to create
a directory "\\samba-server\username.PDS" if you specify the logon path
as "\\samba-server\username" with the NT User Manager. Therefore, you
will need to specify (for example) "\\samba-server\username\profile".
@@ -359,7 +351,7 @@ If you then want to share the same Start Menu / Desktop with W95, you will
need to specify "logon path = \\samba-server\username\profile" [lkcl 10aug97
this has its drawbacks: i created a shortcut to telnet.exe, which attempts
to run from the c:\winnt\system32 directory. this directory is obviously
-unlikely to exist on a Win95-only host].
+unlikely to exist on a W95 host].
If you have this set up correctly, you will find separate user.DAT and
NTuser.DAT files in the same profile directory.
diff --git a/docs/textdocs/DOMAIN_CONTROL.txt b/docs/textdocs/DOMAIN_CONTROL.txt
index 6448c8ade2f..5257a6508f6 100644
--- a/docs/textdocs/DOMAIN_CONTROL.txt
+++ b/docs/textdocs/DOMAIN_CONTROL.txt
@@ -1,5 +1,5 @@
!==
-!== DOMAIN_CONTROL.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== DOMAIN_CONTROL.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Initial Release: August 22, 1996
Contributor: John H Terpstra <samba-bugs@samba.anu.edu.au>
@@ -22,9 +22,12 @@ SMB domains based on shared authentication database schemes other than the
Windows NT SAM.
Microsoft Windows NT Domain Control is an extremely complex protocol.
-We have received countless requests to implement Domain Control in Samba.
-The 1.9.18 release of Samba contains experimental code to implement
-this. Please read the file docs/NTDOMAIN.txt for more information on this.
+We have received countless requests to implement Domain Control in Samba
+and have seriously investigated the potential to support this. The Samba
+Team have now concluded that since Domain Control is a completely
+undocumented protocol we ought NOT to implement our best guess of this
+technology. It is a Microsoft business policy NOT to release the information
+necessary to enable this to be implemented in a dependable manner.
============================================================================
Windows NT Server can be installed as either a plain file and print server
diff --git a/docs/textdocs/ENCRYPTION.txt b/docs/textdocs/ENCRYPTION.txt
index 7254ba9a899..511821481bb 100644
--- a/docs/textdocs/ENCRYPTION.txt
+++ b/docs/textdocs/ENCRYPTION.txt
@@ -1,5 +1,5 @@
!==
-!== ENCRYPTION.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== ENCRYPTION.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: Jeremy Allison <samba-bugs@samba.anu.edu.au>
Updated: June 27, 1997
@@ -272,15 +272,27 @@ This is a very brief description on how to setup samba to support
password encryption. More complete instructions will probably be added
later.
-1) compile and install samba as usual
+1) get and compile the libdes libraries. the source is available from
+ftp://samba.anu.edu.au/pub/libdes/
-2) if your system can't compile the module getsmbpass.c then remove the
+2) enable the encryption stuff in the Samba makefile, making sure you
+point it to the libdes library and include file (it needs des.h)
+The entries you need to uncomment are the four lines after the comment :-
+
+# This is for SMB encrypted (lanman) passwords.
+
+Note that you may have to change the variable DES_BASE to
+point at the place where you installed the DES library.
+
+3) compile and install samba as usual
+
+4) f your system can't compile the module getsmbpass.c then remove the
-DSMBGETPASS define from the Makefile.
-3) enable encrypted passwords in smb.conf by adding the line
+5) enable encrypted passwords in smb.conf by adding the line
"encrypt passwords = yes" in the [global] section
-4) create the initial smbpasswd password file in the place you
+6) create the initial smbpasswd password file in the place you
specified in the Makefile. A simple way to do this based on your
existing Makefile (assuming it is in a reasonably standard format) is
like this:
@@ -315,13 +327,27 @@ If you wish, install the smbpasswd program as suid root.
chown root /usr/local/samba/bin/smbpasswd
chmod 4555 /usr/local/samba/bin/smbpasswd
-5) set the passwords for users using the smbpasswd command. For
+7) set the passwords for users using the smbpasswd command. For
example, as root you could do "smbpasswd tridge"
-6) try it out!
+8) try it out!
Note that you can test things using smbclient, as it also now supports
encryption.
+NOTE TO USA Sites that Mirror Samba
+-----------------------------------
+
+The DES library is considered a munition in the USA. Under US Law it is
+illegal to export this software, or to put it in a freely available ftp
+site.
+
+Please do not mirror the libdes directory from the site on
+samba.anu.edu.au
+
+Thank you,
+
+Jeremy Allison.
+
==============================================================================
Footnote: Please refer to WinNT.txt also
diff --git a/docs/textdocs/Faxing.txt b/docs/textdocs/Faxing.txt
index f6ab2eb0cc6..be5590a5036 100644
--- a/docs/textdocs/Faxing.txt
+++ b/docs/textdocs/Faxing.txt
@@ -1,5 +1,5 @@
!==
-!== Faxing.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== Faxing.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: Gerhard Zuber <zuber@berlin.snafu.de>
Date: August 5th 1997.
diff --git a/docs/textdocs/GOTCHAS.txt b/docs/textdocs/GOTCHAS.txt
index 156c7f9ef16..03f9389e314 100644
--- a/docs/textdocs/GOTCHAS.txt
+++ b/docs/textdocs/GOTCHAS.txt
@@ -1,5 +1,5 @@
!==
-!== GOTCHAS.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== GOTCHAS.txt for Samba release 1.9.17p5 20 Dec 1997
!==
This file lists Gotchas to watch out for:
=========================================================================
diff --git a/docs/textdocs/HINTS.txt b/docs/textdocs/HINTS.txt
index 707f2bc8c39..0da5ff8de99 100644
--- a/docs/textdocs/HINTS.txt
+++ b/docs/textdocs/HINTS.txt
@@ -1,5 +1,5 @@
!==
-!== HINTS.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== HINTS.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: Many
Updated: Not for a long time!
diff --git a/docs/textdocs/MIRRORS.txt b/docs/textdocs/MIRRORS.txt
index 4e1a6960142..11f171766c3 100755
--- a/docs/textdocs/MIRRORS.txt
+++ b/docs/textdocs/MIRRORS.txt
@@ -1,5 +1,5 @@
!==
-!== MIRRORS.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== MIRRORS.txt for Samba release 1.9.17p5 20 Dec 1997
!==
The main Samba ftp site is samba.anu.edu.au in pub/samba/. Contact
samba-bugs@samba.anu.edu.au for help with this site.
@@ -26,6 +26,7 @@ Mirror sites include:
ftp://nic.funet.fi/pub/mirrors/samba.anu.edu.au/
--- Germany ---
ftp://ftp.uni-trier.de/pub/unix/network/samba/
+ ftp://ftp.gwdg.de/pub/server/samba/
--- Greece ---
ftp://ftp.ntua.gr/pub/net/samba/
--- Italy ---
diff --git a/docs/textdocs/NTDOMAIN.txt b/docs/textdocs/NTDOMAIN.txt
deleted file mode 100644
index a682643a456..00000000000
--- a/docs/textdocs/NTDOMAIN.txt
+++ /dev/null
@@ -1,155 +0,0 @@
-!==
-!== NTDOMAIN.txt for Samba release 1.9.18alpha13 16 Dec 1997
-!==
-Contributor: Luke Kenneth Casson Leighton (samba-bugs@samba.anu.edu.au)
- Copyright (C) 1997 Luke Kenneth Casson Leighton
-Created: October 20, 1997
-Updated: October 29, 1997
-
-Subject: NT Domain Logons
-===========================================================================
-
-As of 1.9.18alpha1, Samba supports logins for NT 3.51 and 4.0 Workstations,
-without the need, use or intervention of NT Server. This document describes
-how to set this up. Over the continued development of the 1.9.18alpha
-series, this process (and therefore this document) should become simpler.
-
-One useful thing to do is to get this version of Samba up and running
-with Win95 profiles, as you would for the current stable version of
-Samba (currently at 1.9.17p4), and is fully documented. You will need
-to set up encrypted passwords. Even if you don't have any Win95 machines,
-using your Samba Server to store the profile for one of your NT Workstation
-users is a good test that you have 1.9.18alpha1 correctly configured *prior*
-to attempting NT Domain Logons.
-
-The support is still experimental, so should be used at your own risk.
-
-NT is not as robust as you might have been led to believe: during the
-development of the Domain Logon Support, one person reported having to
-reinstall NT from scratch: their workstation had become totally unuseable.
-
-[further reports on ntsec@iss.net by independent administrators showing
- similar symptoms lead us to believe that the SAM database file may be
- corruptible. this _is_ recoverable (or, at least the machine is accessible),
- by deleting the SAM file, under which circumstances all user account details
- are lost, but at least the Administrator can log in with a blank password.
- this is *not* possible except if the NT system is installed in a FAT
- partition.]
-
-This *has* been reported to the NTBUGTRAQ@LISTSERV.NTBUGTRAQ.COM digest.
-
-
-Domain Logons using 1.9.18alpha1
-================================
-
-1) compile samba with -DNTDOMAIN
-
-2) set up samba with encrypted passwords: see ENCRYPTION.txt (probably out
- of date: you no longer need the DES libraries, but other than that,
- ENCRYPTION.txt is current).
-
- at this point, you ought to test that your samba server is accessible
- correctly with encrypted passwords, before progressing with any of the
- NT workstation-specific bits: it's up to you.
-
-3) [ for each workstation, add a line to smbpasswd with a username of MACHINE$
- and a password of "machine". this process will be automated in further
- releases. lkcl02nov97 - done, as of 1.9.18alpha11! added new options
- "domain hosts allow/deny" too :-) ]
-
-4) if using NT server to log in, run the User Manager for Domains, and
- add the capability to "Log in Locally" to the policies, which you would
- have to do even if you were logging in to another NT PDC instead of a
- Samba PDC.
-
-5) set up the following parameters in smb.conf
-
-; substitute your workgroup here
- workgroup = SAMBA
-
-; a description of domain sids can be found elsewhere.
-; you **MUST** begin the domain SID with S-1-5-21.
-; the rest is up to you.
- domain sid = S-1-5-21-123-456-789-123
-
-; tells workstations to use SAMBA as its Primary Domain Controller.
- domain logons = yes
-
-6) make sure samba is running before the next step is carried out. if
- this is your first time, just for fun you might like to switch the
- debug log level to about 10. the NT pipes produces some very pretty
- output when decoding requests and generating responses, which would
- be particularly useful to see in tcpdump at some point.
-
-7) In the NT Network Settings, change the domain to SAMBA. Do
- not attempt to create an account using the other part of the dialog:
- it will fail at present.
-
- You should get a wonderful message saying "Welcome to the SAMBA Domain."
-
- If you don't, then please first increase your debug log levels and also
- get a tcpdump (or preferably NetMonitor) trace and examine it carefully.
- You should see a NETLOGON, a SAMLOGON on UDP port 138. If you don't,
- then you probably don't have "domain logons = yes" or there is some other
- problem in resolving the NetBIOS name SAMBA<1c>.
-
- On port 139, you should see a LSA_OPEN_POLICY, two LSA_QUERY_INFOs (one
- for a domain SID of S-1-3... and another for S-1-5) and then an LSA_CLOSE
- or two.
-
- You may see a pipe connection to a wksta service being refused: this
- is acceptable, we have found. You may also see a "Net Server Get Info"
- being issued on the srvsvc pipe.
-
- Assuming you got the Welcome message, go through the obligatory reboot...
-
-8) When pressing Ctrl-Alt-Delete, the NT login box should have three entries.
- If there is a delay of about twenty seconds between pressing Ctrl-Alt-Delete
- and the appearance of this login dialog, then there might be a problem:
- at this stage the workstation is issuing an LSA_ENUMTRUSTEDDOMAIN request
-
- The domain box should have two entries: the hostname and the SAMBA domain.
- Any local accounts are under the hostname domain, from which you will be
- able to shut down the machine etc. At present, we do not specify that
- the NT user logging in is a member of any groups, so will have no
- priveleges, including the ability to shut down the machine [lkcl02nov97 -
- done, as of samba-1.9.18alpha3! see "domain admin/guest users" and
- "domain groups" parameters].
-
- Select the SAMBA domain, and type in a valid username and password for
- which there is a valid entry in the samba server's smbpasswd LM/NT OWF
- database. At present, the password is ignored, to allow access to the
- domain, but *not* ignored for accesses to Samba's SMB services: that's
- completely separate from the SAM Logon process. Even if you log in a
- user to a domain, your users will still need to connect to Samba SMB
- shares with valid username / passwords, for that share.
-
- You should see an LSA_REQ_CHAL, followed by LSA_AUTH2, LSA_NET_SRV_PWSET,
- and LSA_SAM_LOGON. The SAM Logon will be particularly large (the response
- can be approximately 600 bytes) as it contains user info.
-
- Also, there will probably be a "Net Server Get Info" and a "Net Share Enum"
- amongst this lot. If the SAM Logon is successful, the dialog should
- disappear, and a standard SMB connection established to download the
- profile specified in the SAM Logon (if it was).
-
- At this point, you _may_ encounter difficulties in creating a remote
- profile, and the login may terminate (generating an LSA_SAM_LOGOFF). If
- this occurs, then either find an existing profile on the samba server and
- copy it into the location specified by the "logon path" smb.conf parameter
- for the user logging in, or log in on the local machine, and use the
- System | Profiles control panel to make a copy of the _local_ profile onto
- the samba server. This process is described and documented in the NT
- Help Files.
-
-9) Play around. Look at the Samba Server: see if it can be found in the
- browse lists. Check that it is accessible; run some applications.
- Generally stress things. Laugh a lot. Logout of the NT machine
- (generating an LSA_SAM_LOGOFF) and log back in again. Try logging in
- two users simultaneously. Try logging the same user in twice.
- Make Samba fall over, and then send bug reports to us, with NTDOM: at
- the start of the subject line, as "samba-bugs@samba.anu.edu.au".
-
-Your reports, testing, patches, criticism and encouragement will help us
-get this right.
-
diff --git a/docs/textdocs/NetBIOS.txt b/docs/textdocs/NetBIOS.txt
index ded2a509435..8b27fcefd9c 100644
--- a/docs/textdocs/NetBIOS.txt
+++ b/docs/textdocs/NetBIOS.txt
@@ -1,5 +1,5 @@
!==
-!== NetBIOS.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== NetBIOS.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: lkcl - samba-bugs@arvidsjaur.anu.edu.au
Copyright 1997 Luke Kenneth Casson Leighton
diff --git a/docs/textdocs/OS2-Client-HOWTO.txt b/docs/textdocs/OS2-Client-HOWTO.txt
index 0077c84f3dd..4be30cb0955 100644
--- a/docs/textdocs/OS2-Client-HOWTO.txt
+++ b/docs/textdocs/OS2-Client-HOWTO.txt
@@ -1,5 +1,5 @@
!==
-!== OS2-Client-HOWTO.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== OS2-Client-HOWTO.txt for Samba release 1.9.17p5 20 Dec 1997
!==
diff --git a/docs/textdocs/PRINTER_DRIVER.txt b/docs/textdocs/PRINTER_DRIVER.txt
deleted file mode 100644
index 2ad2f570414..00000000000
--- a/docs/textdocs/PRINTER_DRIVER.txt
+++ /dev/null
@@ -1,77 +0,0 @@
-!==
-!== PRINTER_DRIVER.txt for Samba release 1.9.18alpha13 16 Dec 1997
-!==
-==========================================================================
- Supporting the famous PRINTER$ share
-
- Jean-Francois.Micouleau@utc.fr, 10/26/97
-
-===========================================================================
-
-Disclaimer:
-
- This ONLY works with Windows 95
- It does NOT work with Windows NT 4
-
-
-Goal:
-
- When you click on a samba shared printer, you can now install the driver
- automatically onto the Windows 95 machine, as you would from an NT server.
-
-How To:
-
- It's a three step config.
-
- First, create a new directory, where you will put the driver files, and
- make a share in smb.conf pointing to it.
-
- Example:
-
- [printer$]
- path=/usr/local/samba/printer
- public=yes
- writable=no
- browseable=yes
-
- Second, you have to build the list of the drivers required for a specific
- printer. This is the most complicated thing to do. Get the files
- 'msprint.inf' and 'msprint2.inf' from Windows 95, the easiest way is to
- grab them from a working Windows 95 computer. They are usually located
- in 'c:\windows\inf'. Look in them for the printer you have. Run the new
- program 'mkprinterdef' with the file name and the printer name as
- parameters.
- Example:
-
- mkprinterdef msprint.def "Apple LaserWriter" >>/usr/local/samba/lib/printers.def
-
- Copy also all the files into the directory you created in step 1
-
- Third, you need to add 2 new parameters in smb.conf. One is in the
- [global] section, called 'printer driver file' pointing to the file description,
- and the other in each printer share, called 'printer driver location' pointing
- to where the client will get the drivers. Don't forget to set correctly
- the printer driver parameter to the Windows printer name.
- Example:
-
- [global]
- printer driver file=/usr/local/samba/lib/printers.def
-
- [lp]
- comment = My old printer laser
- browseable = yes
- printable = yes
- public = yes
- writable = no
- create mode = 0700
- printer driver=Apple LaserWriter
- printer driver location=\\JOKER\PRINTER$
-
- JOKER is in my case my computer name, and PRINTER$ is the name of the
- share created in step one.
-
-
-If it doesn't work for you, don't send flame ! It worked for me. In case of
-trouble don't hesitate to send me a mail with your smb.conf file and
-printers.def
-
diff --git a/docs/textdocs/Passwords.txt b/docs/textdocs/Passwords.txt
index cf08024e64d..dd579fb00cf 100644
--- a/docs/textdocs/Passwords.txt
+++ b/docs/textdocs/Passwords.txt
@@ -1,5 +1,5 @@
!==
-!== Passwords.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== Passwords.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: Unknown
Date: Unknown
diff --git a/docs/textdocs/Printing.txt b/docs/textdocs/Printing.txt
index 2b9dbfbbeec..3359eab111a 100644
--- a/docs/textdocs/Printing.txt
+++ b/docs/textdocs/Printing.txt
@@ -1,5 +1,5 @@
!==
-!== Printing.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== Printing.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: Unknown <samba-bugs@samba.anu.edu.au>
Date: Unknown
diff --git a/docs/textdocs/SCO.txt b/docs/textdocs/SCO.txt
index fa641b24216..861bd482fb9 100644
--- a/docs/textdocs/SCO.txt
+++ b/docs/textdocs/SCO.txt
@@ -1,5 +1,5 @@
!==
-!== SCO.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== SCO.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: Geza Makay <makayg@math.u-szeged.hu>
Date: Unknown
diff --git a/docs/textdocs/Speed.txt b/docs/textdocs/Speed.txt
index 39d7d9aee5f..23a71d59682 100644
--- a/docs/textdocs/Speed.txt
+++ b/docs/textdocs/Speed.txt
@@ -1,5 +1,5 @@
!==
-!== Speed.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== Speed.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: Andrew Tridgell
Date: January 1995
@@ -46,36 +46,21 @@ only one accessing the file and it will agressively cache file
data. With some oplock types the client may even cache file open/close
operations. This can give enormous performance benefits.
-With the release of Samba 1.9.18 we now correctly support opportunistic
-locks. This is turned on by default, and can be turned off on a share-
-by-share basis by setting the parameter :
+Samba does not support opportunistic locks because they are very
+difficult to do under Unix. Samba can fake them, however, by granting
+a oplock whenever a client asks for one. This is controlled using the
+smb.conf option "fake oplocks". If you set "fake oplocks = yes" then
+you are telling the client that it may agressively cache the file
+data.
-oplocks = False
-
-We recommend that you leave oplocks on however, as current benchmark
-tests with NetBench seem to give approximately a 30% improvement in
-speed with them on. This is on average however, and the actual
-improvement seen can be orders of magnitude greater, depending on
-what the client redirector is doing.
-
-Previous to Samba 1.9.18 there was a 'fake oplocks' option. This
-option has been left in the code for backwards compatibility reasons
-but it's use is now deprecated. A short summary of what the old
-code did follows.
-
-Old 'fake oplocks' option - deprecated.
----------------------------------------
-
-Samba can also fake oplocks, by granting a oplock whenever a client
-asks for one. This is controlled using the smb.conf option "fake
-oplocks". If you set "fake oplocks = yes" then you are telling the
-client that it may agressively cache the file data for all opens.
-
-Enabling 'fake oplocks' on all read-only shares or shares that you know
+By enabling this option on all read-only shares or shares that you know
will only be accessed from one client at a time you will see a big
performance improvement on many operations. If you enable this option
on shares where multiple clients may be accessing the files read-write
-at the same time you can get data corruption.
+at the same time you can get data corruption. Use this option
+carefully!
+
+This option is disabled by default.
SOCKET OPTIONS
--------------
diff --git a/docs/textdocs/Support.txt b/docs/textdocs/Support.txt
index 2f43e040b27..b9129f02e89 100644
--- a/docs/textdocs/Support.txt
+++ b/docs/textdocs/Support.txt
@@ -1,5 +1,5 @@
!==
-!== Support.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== Support.txt for Samba release 1.9.17p5 20 Dec 1997
!==
The Samba Consultants List
==========================
@@ -32,10 +32,10 @@ Region Number of entries
----------------------------------------------------
AFRICA 2
AMERICA - CENTRAL & SOUTH 4
- AMERICA - USA 36
+ AMERICA - USA 35
ASIA 1
AUSTRALIA & NEW ZEALAND 18
- CANADA 9
+ CANADA 8
EUROPE 36
MIDDLE EAST 1
@@ -705,22 +705,6 @@ info@stelias.com.
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-USA - VIRGINIA
-
-Commonwealth Technical Services, Inc.
-13618 Hull Street Road
-Suite 300
-Midlothian, VA 23112
-bcaudle@ctsi.net
-www.ctsi.net
-804-639-5400
-
-Commonwealth Technical Services supports Samba systems on various UNIX platforms,
-as well as providing hardware, software, and consulting services for UNIX and Windows
-networks and the Internet.
-------------------------------------------------------------------------------
-
-------------------------------------------------------------------------------
WASHINGTON DC METRO - USA
Asset Software, Inc. has been running Samba since the 1.6 release on various
@@ -1166,21 +1150,6 @@ further information.
------------------------------------------------------------------------------
------------------------------------------------------------------------------
-ONTARIO - CANADA
-
-MIS Incorporated, London Ontario CANADA
-Tel: +1 (519) 673-3777 Fax: +1 (519) 673-4292
-Email: samba-support@netcontech.com
-
-MIS Incorporated is a Microsoft Certified Solution Provider,
-and system support group specializing in applying Windows
-front ends to high end relational database servers. Samba
-support available on any unix platform in conjunction with
-WFW, Windows-NT, Win95, OS/2. Dial-in support
-nation-wide, or on-site anywhere in Ontario.
-------------------------------------------------------------------------------
-
-------------------------------------------------------------------------------
OTTAWA - CANADA
Russell McOrmond
@@ -1292,8 +1261,8 @@ servers.
CAMBRIDGE - ENGLAND. Will travel / provide support world-wide.
Luke Kenneth Casson Leighton
-Phone: +44 1223 570 262 or 570 264 or Mobile +44 410 305 745
-lkcl@switchboard.net
+Phone: +44 1223 570 262 or 570 264
+lkcl@cb1.com
Configuration Experience:
diff --git a/docs/textdocs/Tracing.txt b/docs/textdocs/Tracing.txt
index 75bfea6de78..6a9aca80da8 100644
--- a/docs/textdocs/Tracing.txt
+++ b/docs/textdocs/Tracing.txt
@@ -1,5 +1,5 @@
!==
-!== Tracing.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== Tracing.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: Andrew Tridgell <samba-bugs@samba.anu.edu.au>
Date: Old
diff --git a/docs/textdocs/UNIX-SMB.txt b/docs/textdocs/UNIX-SMB.txt
index 6990d5acca8..9f7a692c52b 100644
--- a/docs/textdocs/UNIX-SMB.txt
+++ b/docs/textdocs/UNIX-SMB.txt
@@ -1,5 +1,5 @@
!==
-!== UNIX-SMB.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== UNIX-SMB.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: Andrew Tridgell <samba-bugs@samba.anu.edu.au>
Date: April 1995
diff --git a/docs/textdocs/UNIX_INSTALL.txt b/docs/textdocs/UNIX_INSTALL.txt
index 49a0c3a112a..cb18f0f9931 100644
--- a/docs/textdocs/UNIX_INSTALL.txt
+++ b/docs/textdocs/UNIX_INSTALL.txt
@@ -1,5 +1,5 @@
!==
-!== UNIX_INSTALL.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== UNIX_INSTALL.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: Andrew Tridgell <samba-bugs@samba.anu.edu.au>
Date: Unknown
@@ -18,7 +18,7 @@ try something like:
Unfortunately, having said this, the man pages are sadly out of date and
really need more effort to maintain them. Other sources of information
-are pointed to by the Samba web site, http://samba.anu.edu.au/samba.
+are pointed to by the Samba web site, http://samba.anu.edu.au/samba/.
STEP 1. Building the binaries
@@ -50,7 +50,7 @@ At this stage you must fetch yourself a coffee or other drink you find
stimulating. Getting the rest of the install right can sometimes be
tricky, so you will probably need it.
-If you have installed samba before then you can skip this step.
+If you have installed samba before then you can skip this step.
STEP 3. Create the smb configuration file.
@@ -94,9 +94,7 @@ You must choose to start smbd and nmbd either as daemons or from
inetd. Don't try to do both! Either you can put them in inetd.conf
and have them started on demand by inetd, or you can start them as
daemons either from the command line or in /etc/rc.local. See the man
-pages for details on the command line options. Take particular care
-to read the bit about what user you need to be in order to start Samba.
-In many cases you must be root.
+pages for details on the command line options.
The main advantage of starting smbd and nmbd as a daemon is that they
will respond slightly more quickly to an initial connection
diff --git a/docs/textdocs/Win95.txt b/docs/textdocs/Win95.txt
index af89c500691..26eb216b4df 100644
--- a/docs/textdocs/Win95.txt
+++ b/docs/textdocs/Win95.txt
@@ -1,5 +1,5 @@
!==
-!== Win95.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== Win95.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Copyright (C) 1997 - Samba-Team
Contributed Date: August 20, 1997
diff --git a/docs/textdocs/WinNT.txt b/docs/textdocs/WinNT.txt
index ed6cba56b47..8b14f66389c 100644
--- a/docs/textdocs/WinNT.txt
+++ b/docs/textdocs/WinNT.txt
@@ -1,5 +1,5 @@
!==
-!== WinNT.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== WinNT.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributors: Various
Password Section - Copyright (C) 1997 - John H Terpstra
@@ -32,7 +32,7 @@ The following registry entry change will re-enable clear text password
handling:
Run regedt32.exe and locate the hive key entry:
-HKEY_LOCAL_MACHINE\system\CurrentControlSet\Services\Rdr\Parameters\
+HKEY_LOCAL_MACHINE\system\CurrentControlSet\Services\rdr\parameters\
Add the following value:
EnablePlainTextPassword:REG_DWORD=1
diff --git a/docs/textdocs/cifsntdomain.txt b/docs/textdocs/cifsntdomain.txt
deleted file mode 100644
index 07a9efbca96..00000000000
--- a/docs/textdocs/cifsntdomain.txt
+++ /dev/null
@@ -1,1501 +0,0 @@
-!==
-!== cifsntdomain.txt for Samba release 1.9.18alpha13 16 Dec 1997
-!==
-NT Domain Authentication
-------------------------
-
-Authors: - Luke Kenneth Casson Leighton (lkcl@switchboard.net)
--------- - Paul Ashton (paul@argo.demon.co.uk)
- - Duncan Stansfield (duncans@sco.com)
-
- Copyright (C) 1997 Luke Kenneth Casson Leighton
- Copyright (C) 1997 Paul Ashton
- Copyright (C) 1997 Duncan Stansfield
-
-Version: 0.024 (01Nov97)
---------
-
-Distribution: Unlimited and encouraged, for the purposes of implementation
-------------- and comments. Feedback welcomed by the authors.
-
-Liability: Absolutely none accepted implicitly or explicitly, direct
----------- or consequentially, for use, abuse, misuse, lack of use,
- misunderstandings, mistakes, omissions, mis-information for
- anything in or not in, related to or not related to, or
- pertaining to this document, or anything else that a lawyer
- can think of or not think of.
-
-Warning: Please bear in mind that an incorrect implementation of this
--------- protocol can cause NT workstation to fail irrevocably, for
- which the authors accept no liability (see above). Please
- contact your vendor if you have any problems.
-
-Sources: - Packet Traces from Netmonitor (Service Pack 1 and above)
--------- - Paul Ashton and Luke Leighton's other "NT Domain" doc.
- - CIFS documentation - cifs6.txt
- - CIFS documentation - cifsrap2.txt
-
-Original: http://mailhost.cb1.com/~lkcl/cifsntdomain.txt.
---------- (Controlled copy maintained by lkcl@switchboard.net)
-
-Credits: - Paul Ashton: loads of work with Net Monitor;
--------- understanding the NT authentication system;
- reference implementation of the NT domain support on which
- this document is originally based.
- - Duncan Stansfield: low-level analysis of MSRPC Pipes.
- - Linus Nordberg: producing c-code from Paul's crypto spec.
- - Windows Sourcer development team
-
-
-Contents:
----------
-
- 1) Introduction
-
- 2) Structures and notes
-
- 2.1) Notes
- 2.3) Enumerations
- 2.3) Structures
-
- 3) Transact Named Pipe Header/Tail
-
- 3.1) MSRPC Pipes
- 3.2) Header
- 3.3) Tail
-
- 4) NTLSA Transact Named Pipe
-
- 4.1) LSA Open Policy
- 4.2) LSA Query Info Policy
- 4.3) LSA Enumerate Trusted Domains
- 4.4) LSA Open Secret
- 4.5) LSA Close
- 4.6) LSA Lookup SIDS
- 4.7) LSA Lookup Names
-
- 5) NETLOGON rpc Transact Named Pipe
-
- 5.1) LSA Request Challenge
- 5.2) LSA Authenticate 2
- 5.3) LSA Server Password Set
- 5.4) LSA SAM Logon
- 5.5) LSA SAM Logoff
-
- 6) \\MAILSLOT\NET\NTLOGON
-
- 6.1) Query for PDC
- 6.2) SAM Logon
-
- 7) SRVSVC Transact Named Pipe
-
- 7.1) Net Share Enum
- 7.2) Net Server Get Info
-
-
-Appendix:
----------
-
- A1) Cryptographic side of NT Domain Authentication
-
- A1.1) Definitions
- A1.2) Protocol
- A1.3) Comments
-
- A2) SIDs and RIDs
-
- A2.1) Well-known SIDs
-
- A2.1.1) Universal well-known SIDs
- A2.1.2) NT well-known SIDs
-
- A2.2) Well-known RIDS
-
- A2.2.1) Well-known RID users
- A2.2.2) Well-known RID groups
- A2.2.3) Well-known RID aliases
-
-
-
-1) Introduction
----------------
-
-
-This document contains information to provide an NT workstation with login
-services, without the need for an NT server.
-
-It should be possible to select a domain instead of a workgroup (in the NT
-workstation's TCP/IP settings) and after the obligatory reboot, type in a
-username, password, select a domain and successfully log in. I would
-appreciate any feedback on your experiences with this process, and any
-comments, corrections and additions to this document.
-
-
-The packets described here can be easily derived from (and are probably
-better understood using) Netmon.exe. You will need to use the version
-of Netmon that matches your system, in order to correctly decode the
-NETLOGON, lsarpc and srvsvc Transact pipes. This document is derived from
-NT Service Pack 1 and its corresponding version of Netmon. It is intended
-that an annotated packet trace be produced, which will likely be more
-instructive than this document.
-
-Also needed, to fully implement NT Domain Login Services, is the
-document describing the cryptographic part of the NT authentication.
-This document is available from comp.protocols.smb; from the ntsecurity.net
-digest and from the samba digest, amongst other sources.
-
-A copy is available from:
-
-http://ntbugtraq.rc.on.ca/SCRIPTS/WA.EXE?A2=ind9708&L=ntbugtraq&O=A&P=2935
-http://mailhost.cb1.com/~lkcl/crypt.html
-
-
-A c-code implementation, provided by Linus Nordberg <linus@incolumitas.se>
-of this protocol is available from:
-
-http://samba.anu.edu.au/cgi-bin/mfs/01/digest/1997/97aug/0391.html
-http://mailhost.cb1.com/~lkcl/crypt.txt
-
-
-Also used to provide debugging information is the Check Build version of
-NT workstation, and enabling full debugging in NETLOGON. This is
-achieved by setting the following REG_SZ registry key to 0x1ffffff:
-
-HKLM\SYSTEM\CurrentControlSet\Services\Netlogon\Parameters
-
-- Incorrect direct editing of the registry can cause your machine to fail.
- Then again, so can incorrect implementation of this protocol.
- See "Liability:" above.
-
-
-Bear in mind that each packet over-the-wire will have its origin in an
-API call. Therefore, there are likely to be structures, enumerations
-and defines that are usefully documented elsewhere.
-
-
-This document is by no means complete or authoritative. Missing sections
-include, but are not limited to:
-
-- the meaning (and use by NT) of SIDs and RIDs.
-
-- mappings of RIDs to usernames (and vice-versa).
-
-- what a User ID is and what a Group ID is.
-
-- the exact meaning/definition of various magic constants or enumerations.
-
-- the reply error code and use of that error code when a workstation
- becomes a member of a domain (to be described later). Failure to
- return this error code will make the workstation report that it is
- already a member of the domain.
-
-- the cryptographic side of the NetrServerPasswordSet command, which would
- allow the workstation to change its password. This password is used to
- generate the long-term session key. [It is possible to reject this
- command, and keep the default workstation password].
-
-
-2) Notes and Structures
------------------------
-
-
-2.1) Notes
-----------
-
-- In the SMB Transact pipes, some "Structures", described here, appear to be
- 4-byte aligned with the SMB header, at their start. Exactly which
- "Structures" need aligning is not precisely known or documented.
-
-- In the UDP NTLOGON Mailslots, some "Structures", described here, appear to be
- 2-byte aligned with the start of the mailslot, at their start.
-
-- Domain SID is of the format S-revision-version-auth1-auth2...authN.
- e.g S-1-5-123-456-789-123-456. the 5 could be a sub-revision.
-
-- any undocumented buffer pointers must be non-zero if the string buffer it
- refers to contains characters. exactly what value they should be is unknown.
- 0x0000 0002 seems to do the trick to indicate that the buffer exists. a
- NULL buffer pointer indicates that the string buffer is of zero length.
- If the buffer pointer is NULL, then it is suspected that the structure it
- refers to is NOT put into (or taken out of) the SMB data stream. This is
- empirically derived from, for example, the LSA SAM Logon response packet,
- where if the buffer pointer is NULL, the user information is not inserted
- into the data stream. Exactly what happens with an array of buffer pointers
- is not known, although an educated guess can be made.
-
-- an array of structures (a container) appears to have a count and a pointer.
- if the count is zero, the pointer is also zero. no further data is put
- into or taken out of the SMB data stream. if the count is non-zero, then
- the pointer is also non-zero. immediately following the pointer is the
- count again, followed by an array of container sub-structures. the count
- appears a third time after the last sub-structure.
-
-
-2.2) Enumerations
------------------
-
-- MSRPC Header type. command number in the msrpc packet header
-
- MSRPC_Request: 0x00
- MSRPC_Response: 0x02
- MSRPC_Bind: 0x0B
- MSRPC_BindAck: 0x0C
-
-- MSRPC Packet info. the meaning of these flags is undocumented
-
- FirstFrag: 0x01
- LastFrag: 0x02
- NotaFrag: 0x04
- RecRespond: 0x08
- NoMultiplex: 0x10
- NotForIdemp: 0x20
- NotforBcast: 0x40
- NoUuid: 0x80
-
-
-2.3) Structures
----------------
-
-- sizeof VOID* is 32 bits.
-
-- sizeof char is 8 bits.
-
-- UTIME is 32 bits, indicating time in seconds since 01jan1970. documented
- in cifs6.txt (section 3.5 page, page 30).
-
-- NTTIME is 64 bits. documented in cifs6.txt (section 3.5 page, page 30).
-
-- DOM_SID (domain SID structure) :
-
- UINT32 num of sub-authorities in domain SID
- UINT8 SID revision number
- UINT8 num of sub-authorities in domain SID
- UINT8[6] 6 bytes for domain SID - Identifier Authority.
- UINT16[n_subauths] domain SID sub-authorities
-
- Note: the domain SID is documented elsewhere.
-
-- STR (string) :
-
- char[] null-terminated string of ascii characters.
-
-- UNIHDR (unicode string header) :
-
- UINT16 length of unicode string
- UINT16 max length of unicode string
- UINT32 4 - undocumented.
-
-- UNIHDR2 (unicode string header plus buffer pointer) :
-
- UNIHDR unicode string header
- VOID* undocumented buffer pointer
-
-- UNISTR (unicode string) :
-
- UINT16[] null-terminated string of unicode characters.
-
-- NAME (length-indicated unicode string) :
-
- UINT32 length of unicode string
- UINT16[] null-terminated string of unicode characters.
-
-- UNISTR2 (aligned unicode string) :
-
- UINT8[] padding to get unicode string 4-byte aligned
- with the start of the SMB header.
- UINT32 max length of unicode string
- UINT32 0 - undocumented
- UINT32 length of unicode string
- UINT16[] string of uncode characters.
-
-- OBJ_ATTR (object attributes) :
-
- UINT32 0x18 - length (in bytes) including the length field.
- VOID* 0 - root directory (pointer)
- VOID* 0 - object name (pointer)
- UINT32 0 - attributes (undocumented)
- VOID* 0 - security descriptior (pointer)
- UINT32 0 - security quality of service
-
-- POL_HND (LSA policy handle) :
-
- char[20] policy handle
-
-- DOM_SID2 (domain SID structure, SIDS stored in unicode) :
-
- UINT32 5 - SID type
- UINT32 0 - undocumented
- UNIHDR2 domain SID unicode string header
- UNISTR domain SID unicode string
-
- Note: there is a conflict between the unicode string header and the
- unicode string itself as to which to use to indicate string
- length. this will need to be resolved.
-
- Note: the SID type indicates, for example, an alias; a well-known group etc.
- this is documented somewhere.
-
-- DOM_RID (domain RID structure) :
-
- UINT32 5 - well-known SID. 1 - user SID (see ShowACLs)
- UINT32 5 - undocumented
- UINT32 domain RID
- UINT32 0 - domain index out of above reference domains
-
-
-- LOG_INFO (server, account, client structure) :
-
- Note: logon server name starts with two '\' characters and is upper case.
-
- Note: account name is the logon client name from the LSA Request Challenge,
- with a $ on the end of it, in upper case.
-
- VOID* undocumented buffer pointer
- UNISTR2 logon server unicode string
- UNISTR2 account name unicode string
- UINT16 sec_chan - security channel type
- UNISTR2 logon client machine unicode string
-
-- CLNT_SRV (server, client names structure) :
-
- Note: logon server name starts with two '\' characters and is upper case.
-
- VOID* undocumented buffer pointer
- UNISTR2 logon server unicode string
- VOID* undocumented buffer pointer
- UNISTR2 logon client machine unicode string
-
-- CREDS (credentials + time stamp)
-
- char[8] credentials
- UTIME time stamp
-
-- CLNT_INFO2 (server, client structure, client credentials) :
-
- Note: whenever this structure appears in a request, you must take a copy
- of the client-calculated credentials received, because they will be
- used in subsequent credential checks. the presumed intention is to
- maintain an authenticated request/response trail.
-
- CLNT_SRV client and server names
- UINT8[] ???? padding, for 4-byte alignment with SMB header.
- VOID* pointer to client credentials.
- CREDS client-calculated credentials + client time
-
-- CLNT_INFO (server, account, client structure, client credentials) :
-
- Note: whenever this structure appears in a request, you must take a copy
- of the client-calculated credentials received, because they will be
- used in subsequent credential checks. the presumed intention is to
- maintain an authenticated request/response trail.
-
- LOG_INFO logon account info
- CREDS client-calculated credentials + client time
-
-- ID_INFO_1 (id info structure, auth level 1) :
-
- VOID* ptr_id_info_1
- UNIHDR domain name unicode header
- UINT32 param control
- UINT64 logon ID
- UNIHDR user name unicode header
- UNIHDR workgroup name unicode header
- char[16] rc4 LM OWF Password
- char[16] rc4 NT OWF Password
- UNISTR2 domain name unicode string
- UNISTR2 user name unicode string
- UNISTR2 workstation name unicode string
-
-- SAM_INFO (sam logon/logoff id info structure) :
-
- Note: presumably, the return credentials is supposedly for the server to
- verify that the credential chain hasn't been compromised.
-
- CLNT_INFO2 client identification/authentication info
- VOID* pointer to return credentials.
- CRED return credentials - ignored.
- UINT16 logon level
- UINT16 switch value
-
- switch (switch_value)
- case 1:
- {
- ID_INFO_1 id_info_1;
- }
-
-- GID (group id info) :
-
- UINT32 group id
- UINT32 user attributes (only used by NT 3.1 and 3.51)
-
-- DOM_REF (domain reference info) :
-
- VOID* undocumented buffer pointer.
- UINT32 num referenced domains?
- VOID* undocumented domain name buffer pointer.
- UINT32 32 - max number of entries
- UINT32 4 - num referenced domains?
-
- UNIHDR2 domain name unicode string header
- UNIHDR2[num_ref_doms-1] referenced domain unicode string headers
-
- UNISTR domain name unicode string
- DOM_SID[num_ref_doms] referenced domain SIDs
-
-- DOM_INFO (domain info, levels 3 and 5 are the same)) :
-
- UINT8[] ??? padding to get 4-byte alignment with start of SMB header
- UINT16 domain name string length * 2
- UINT16 domain name string length * 2
- VOID* undocumented domain name string buffer pointer
- VOID* undocumented domain SID string buffer pointer
- UNISTR2 domain name (unicode string)
- DOM_SID domain SID
-
-- USER_INFO (user logon info) :
-
- Note: it would be nice to know what the 16 byte user session key is for.
-
- NTTIME logon time
- NTTIME logoff time
- NTTIME kickoff time
- NTTIME password last set time
- NTTIME password can change time
- NTTIME password must change time
-
- UNIHDR username unicode string header
- UNIHDR user's full name unicode string header
- UNIHDR logon script unicode string header
- UNIHDR profile path unicode string header
- UNIHDR home directory unicode string header
- UNIHDR home directory drive unicode string header
-
- UINT16 logon count
- UINT16 bad password count
-
- UINT32 User ID
- UINT32 Group ID
- UINT32 num groups
- VOID* undocumented buffer pointer to groups.
-
- UINT32 user flags
- char[16] user session key
-
- UNIHDR logon server unicode string header
- UNIHDR logon domain unicode string header
- VOID* undocumented logon domain id pointer
- char[40] 40 undocumented padding bytes. future expansion?
-
- UINT32 0 - num_other_sids?
- VOID* NULL - undocumented pointer to other domain SIDs.
-
- UNISTR2 username unicode string
- UNISTR2 user's full name unicode string
- UNISTR2 logon script unicode string
- UNISTR2 profile path unicode string
- UNISTR2 home directory unicode string
- UNISTR2 home directory drive unicode string
-
- UINT32 num groups
- GID[num_groups] group info
-
- UNISTR2 logon server unicode string
- UNISTR2 logon domain unicode string
-
- DOM_SID domain SID
- DOM_SID[num_sids] other domain SIDs?
-
-- SH_INFO_1_PTR (pointers to level 1 share info strings):
-
-Note: see cifsrap2.txt section5, page 10.
-
- 0 for shi1_type indicates a Disk.
- 1 for shi1_type indicates a Print Queue.
- 2 for shi1_type indicates a Device.
- 3 for shi1_type indicates an IPC pipe.
- 0x8000 0000 (top bit set in shi1_type) indicates a hidden share.
-
- VOID* shi1_netname - pointer to net name
- UINT32 shi1_type - type of share. 0 - undocumented.
- VOID* shi1_remark - pointer to comment.
-
-- SH_INFO_1_STR (level 1 share info strings) :
-
- UNISTR2 shi1_netname - unicode string of net name
- UNISTR2 shi1_remark - unicode string of comment.
-
-- SHARE_INFO_1_CTR :
-
- share container with 0 entries:
-
- UINT32 0 - EntriesRead
- UINT32 0 - Buffer
-
- share container with > 0 entries:
-
- UINT32 EntriesRead
- UINT32 non-zero - Buffer
- UINT32 EntriesRead
-
- SH_INFO_1_PTR[EntriesRead] share entry pointers
- SH_INFO_1_STR[EntriesRead] share entry strings
-
- UINT8[] padding to get unicode string 4-byte
- aligned with start of the SMB header.
- UINT32 EntriesRead
- UINT32 0 - padding
-
-- SERVER_INFO_101 :
-
-Note: see cifs6.txt section 6.4 - the fields described therein will be
- of assistance here. for example, the type listed below is the
- same as fServerType, which is described in 6.4.1.
-
- SV_TYPE_WORKSTATION 0x00000001 All workstations
- SV_TYPE_SERVER 0x00000002 All servers
- SV_TYPE_SQLSERVER 0x00000004 Any server running with SQL
- server
- SV_TYPE_DOMAIN_CTRL 0x00000008 Primary domain controller
- SV_TYPE_DOMAIN_BAKCTRL 0x00000010 Backup domain controller
- SV_TYPE_TIME_SOURCE 0x00000020 Server running the timesource
- service
- SV_TYPE_AFP 0x00000040 Apple File Protocol servers
- SV_TYPE_NOVELL 0x00000080 Novell servers
- SV_TYPE_DOMAIN_MEMBER 0x00000100 Domain Member
- SV_TYPE_PRINTQ_SERVER 0x00000200 Server sharing print queue
- SV_TYPE_DIALIN_SERVER 0x00000400 Server running dialin service.
- SV_TYPE_XENIX_SERVER 0x00000800 Xenix server
- SV_TYPE_NT 0x00001000 NT server
- SV_TYPE_WFW 0x00002000 Server running Windows for
-
- SV_TYPE_SERVER_NT 0x00008000 Windows NT non DC server
- SV_TYPE_POTENTIAL_BROWSER 0x00010000 Server that can run the browser
- service
- SV_TYPE_BACKUP_BROWSER 0x00020000 Backup browser server
- SV_TYPE_MASTER_BROWSER 0x00040000 Master browser server
- SV_TYPE_DOMAIN_MASTER 0x00080000 Domain Master Browser server
- SV_TYPE_LOCAL_LIST_ONLY 0x40000000 Enumerate only entries marked
- "local"
- SV_TYPE_DOMAIN_ENUM 0x80000000 Enumerate Domains. The pszServer
- and pszDomain parameters must be
- NULL.
-
- UINT32 500 - platform_id
- VOID* pointer to name
- UINT32 5 - major version
- UINT32 4 - minor version
- UINT32 type (SV_TYPE_... bit field)
- VOID* pointer to comment
-
- UNISTR2 sv101_name - unicode string of server name
- UNISTR2 sv_101_comment - unicode string of server comment.
-
- UINT8[] padding to get unicode string 4-byte
- aligned with start of the SMB header.
-
-
-
-3) MSRPC over Transact Named Pipe
----------------------------------
-
-For details on the SMB Transact Named Pipe, see cifs6.txt
-
-
-3.1) MSRPC Pipes
-----------------
-
-The MSRPC is conducted over an SMB Transact Pipe with a name of "\PIPE\".
-You must first obtain a 16 bit file handle, by sending a SMBopenX with the
-pipe name "\PIPE\srvsvc" for example. You can then perform an SMB Trans,
-and must carry out an SMBclose on the file handle once you are finished.
-
-Trans Requests must be sent with two setup UINT16s, no UINT16 params (none
-known about), and UINT8 data parameters sufficient to contain the MSRPC
-header, and MSRPC data. The first UINT16 setup parameter must be either
-0x0026 to indicate an RPC, or 0x0001 to indicate Set Named Pipe Handle
-state. The second UINT16 parameter must be the file handle for the pipe,
-obtained above.
-
-The Data section for an API Command of 0x0026 (RPC pipe) in the Trans
-Request is the RPC Header, followed by the RPC Data. The Data section for
-an API Command of 0x0001 (Set Named Pipe Handle state) is two bytes. The
-only value seen for these two bytes is 0x00 0x43.
-
-
-MSRPC Responses are sent as response data inside standard SMB Trans
-responses, with the MSRPC Header, MSRPC Data and MSRPC tail.
-
-
-It is suspected that the Trans Requests will need to be at least 2-byte
-aligned (probably 4-byte). This is standard practice for SMBs. It is also
-independent of the observed 4-byte alignments with the start of the MSRPC
-header, including the 4-byte alignment between the MSRPC header and the
-MSRPC data.
-
-
-First, an SMBtconX connection is made to the IPC$ share. The connection
-must be made using encrypted passwords, not clear-text. Then, an SMBopenX
-is made on the pipe. Then, a Set Named Pipe Handle State must be sent,
-after which the pipe is ready to accept API commands. Lastly, and SMBclose
-is sent.
-
-
-To be resolved:
-
- lkcl/01nov97 there appear to be two additional bytes after the null-
- terminated \PIPE\ name for the RPC pipe. Values seen so far are
- listed below:
-
- initial SMBopenX request: RPC API command 0x26 params:
-
- "\\PIPE\\lsarpc" 0x65 0x63; 0x72 0x70; 0x44 0x65;
- "\\PIPE\\srvsvc" 0x73 0x76; 0x4E 0x00; 0x5C 0x43;
-
-
-3.2) Header
------------
-
-[section to be rewritten, following receipt of work by Duncan Stansfield]
-
-
-Interesting note: if you set packed data representation to 0x0100 0000
-then all 4-byte and 2-byte word ordering is turned around!
-
-The start of each of the NTLSA and NETLOGON named pipes begins with:
-
-00 UINT8 5 - RPC major version
-01 UINT8 0 - RPC minor version
-02 UINT8 2 - RPC response packet
-03 UINT8 3 - (FirstFrag bit-wise or with LastFrag)
-04 UINT32 0x1000 0000 - packed data representation
-08 UINT16 fragment length - data size (bytes) inc header and tail.
-0A UINT16 0 - authentication length
-0C UINT32 call identifier. matches 12th UINT32 of incoming RPC data.
-10 UINT32 allocation hint - data size (bytes) minus header and tail.
-14 UINT16 0 - presentation context identifier
-16 UINT8 0 - cancel count
-17 UINT8 in replies: 0 - reserved; in requests: opnum - see #defines.
-18 ...... start of data (goes on for allocation_hint bytes)
-
-
-RPC_Packet for request, response, bind and bind acknowledgement.
-{
-
- UINT8 versionmaj # reply same as request (0x05)
- UINT8 versionmin # reply same as request (0x00)
- UINT8 type # one of the MSRPC_Type enums
- UINT8 flags # reply same as request (0x00 for Bind, 0x03 for Request)
- UINT32 representation # reply same as request (0x00000010)
- UINT16 fraglength # the length of the data section of the SMB trans packet
- UINT16 authlength
- UINT32 callid # call identifier. (e.g. 0x00149594)
-
- * stub USE TvPacket # the remainder of the packet depending on the "type"
-}
-
-
-# the interfaces are numbered. as yet I haven't seen more than one interface
-# used on the same pipe name
-# srvsvc
-# abstract (0x4B324FC8, 0x01D31670, 0x475A7812, 0x88E16EBF, 0x00000003)
-# transfer (0x8A885D04, 0x11C91CEB, 0x0008E89F, 0x6048102B, 0x00000002)
-RPC_Iface RW
-{
- UINT8 byte[16] # 16 bytes of number
- UINT32 version # the interface number
-}
-
-
-# the remainder of the packet after the header if "type" was Bind
-# in the response header, "type" should be BindAck
-RPC_ReqBind RW
-{
- UINT16 maxtsize # maximum transmission fragment size (0x1630)
- UINT16 maxrsize # max receive fragment size (0x1630)
- UINT32 assocgid # associated group id (0x0)
- UINT32 numelements # the number of elements (0x1)
- UINT16 contextid # presentation context identifier (0x0)
- UINT8 numsyntaxes # the number of syntaxes (has always been 1?)(0x1)
- UINT8[] # 4-byte alignment padding, against SMB header
-
- * abstractint USE RPC_Iface # num and vers. of interface client is using
- * transferint USE RPC_Iface # num and vers. of interface to use for replies
-}
-
-
-RPC_Address RW
-{
- UINT16 length # length of the string including null terminator
- * port USE string # the string above in single byte, null terminated form
-}
-
-
-# the response to place after the header in the reply packet
-RPC_ResBind RW
-{
- UINT16 maxtsize # same as request
- UINT16 maxrsize # same as request
- UINT32 assocgid # zero
-
- * secondaddr USE RPC_Address # the address string, as described earlier
-
- UINT8[] # 4-byte alignment padding, against SMB header
-
- UINT8 numresults # the number of results (0x01)
-
- UINT8[] # 4-byte alignment padding, against SMB header
- UINT16 result # result (0x00 = accept)
- UINT16 reason # reason (0x00 = no reason specified)
-
- * transfersyntax USE RPC_Iface # the transfer syntax from the request
-}
-
-
-# the remainder of the packet after the header for every other other
-# request
-RPC_ReqNorm RW
-{
- UINT32 allochint # the size of the stub data in bytes
- UINT16 prescontext # presentation context identifier (0x0)
- UINT16 opnum # operation number (0x15)
-
- * stub USE TvPacket # a packet dependent on the pipe name
- # (probably the interface) and the op number)
-}
-
-
-# response to a request
-RPC_ResNorm RW
-{
- UINT32 allochint # size of the stub data in bytes
- UINT16 prescontext # presentation context identifier (same as request)
- UINT8 cancelcount # cancel count? (0x0)
- UINT8 reserved # 0 - one byte padding
-
- * stub USE TvPacket # the remainder of the reply
-}
-
-
-3.3) Tail
----------
-
-The end of each of the NTLSA and NETLOGON named pipes ends with:
-
- ...... end of data
- UINT32 return code
-
-
-
-3.4 RPC Bind / Bind Ack
------------------------
-
-RPC Binds are the process of associating an RPC pipe (e.g \PIPE\lsarpc)
-with a "transfer syntax" (see RPC_Iface structure). The purpose for doing
-this is unknown.
-
-Note: The RPC_ResBind SMB Transact request is sent with two uint16 setup
- parameters. The first is 0x0026; the second is the file handle
- returned by the SMBopenX Transact response.
-
-Note: The RPC_ResBind members maxtsize, maxrsize and assocgid are the
- same in the response as the same members in the RPC_ReqBind. The
- RPC_ResBind member transfersyntax is the same in the response as
- the
-
-Note: The RPC_ResBind response member secondaddr contains the name
- of what is presumed to be the service behind the RPC pipe. The
- mapping identified so far is:
-
- initial SMBopenX request: RPC_ResBind response:
-
- "\\PIPE\\srvsvc" "\\PIPE\\ntsvcs"
- "\\PIPE\\samr" "\\PIPE\\lsass"
- "\\PIPE\\lsarpc" "\\PIPE\\lsass"
- "\\PIPE\\wkssvc" "\\PIPE\\wksvcs"
- "\\PIPE\\NETLOGON" "\\PIPE\\NETLOGON"
-
-Note: The RPC_Packet fraglength member in both the Bind Request and Bind
- Acknowledgment must contain the length of the entire RPC data,
- including the RPC_Packet header.
-
-Request:
-
- RPC_Packet
- RPC_ReqBind
-
-Response:
-
- RPC_Packet
- RPC_ResBind
-
-
-
-4) NTLSA Transact Named Pipe
-----------------------------
-
-The sequence of actions taken on this pipe are:
-
-- Establish a connection to the IPC$ share (SMBtconX). use encrypted passwords.
-- Open an RPC Pipe with the name "\\PIPE\\lsarpc". Store the file handle.
-- Using the file handle, send a Set Named Pipe Handle state to 0x4300.
-- Send an LSA Open Policy request. Store the Policy Handle.
-- Using the Policy Handle, send LSA Query Info Policy requests, etc.
-- Using the Policy Handle, send an LSA Close.
-- Close the IPC$ share.
-
-
-Defines for this pipe, identifying the query are:
-
-- LSA Open Policy: 0x2c
-- LSA Query Info Policy: 0x07
-- LSA Enumerate Trusted Domains: 0x0d
-- LSA Open Secret: 0xff
-- LSA Lookup SIDs: 0xfe
-- LSA Lookup Names: 0xfd
-- LSA Close: 0x00
-
-
-4.1) LSA Open Policy
---------------------
-
-Note: The policy handle can be anything you like.
-
-Request:
-
- VOID* buffer pointer
- UNISTR2 server name - unicode string starting with two '\'s
- OBJ_ATTR object attributes
- UINT32 1 - desired access
-
-Response:
-
- POL_HND LSA policy handle
-
- return 0 - indicates success
-
-
-4.2) LSA Query Info Policy
---------------------------
-
-Note: The info class in response must be the same as that in the request.
-
-Request:
-
- POL_HND LSA policy handle
- UINT16 info class (also a policy handle?)
-
-Response:
-
- VOID* undocumented buffer pointer
- UINT16 info class (same as info class in request).
-
- switch (info class)
- case 3:
- case 5:
- {
- DOM_INFO domain info, levels 3 and 5 (are the same).
- }
-
- return 0 - indicates success
-
-
-4.3) LSA Enumerate Trusted Domains
-----------------------------------
-
-Request:
-
- no extra data
-
-Response:
-
- UINT32 0 - enumeration context
- UINT32 0 - entries read
- UINT32 0 - trust information
-
- return 0x8000 001a - "no trusted domains" success code
-
-
-4.4) LSA Open Secret
---------------------
-
-Request:
-
- no extra data
-
-Response:
-
- UINT32 0 - undocumented
- UINT32 0 - undocumented
- UINT32 0 - undocumented
- UINT32 0 - undocumented
- UINT32 0 - undocumented
-
- return 0x0C00 0034 - "no such secret" success code
-
-
-4.5) LSA Close
---------------
-
-Request:
-
- POL_HND policy handle to be closed
-
-Response:
-
- POL_HND 0s - closed policy handle (all zeros)
-
- return 0 - indicates success
-
-
-4.6) LSA Lookup SIDS
---------------------
-
-Note: num_entries in response must be same as num_entries in request.
-
-Request:
-
- POL_HND LSA policy handle
- UINT32 num_entries
- VOID* undocumented domain SID buffer pointer
- VOID* undocumented domain name buffer pointer
- VOID*[num_entries] undocumented domain SID pointers to be looked up.
- DOM_SID[num_entries] domain SIDs to be looked up.
- char[16] completely undocumented 16 bytes.
-
-Response:
-
- DOM_REF domain reference response
-
- UINT32 num_entries (listed above)
- VOID* undocumented buffer pointer
-
- UINT32 num_entries (listed above)
- DOM_SID2[num_entries] domain SIDs (from Request, listed above).
-
- UINT32 num_entries (listed above)
-
- return 0 - indicates success
-
-
-4.7) LSA Lookup Names
----------------------
-
-Note: num_entries in response must be same as num_entries in request.
-
-Request:
-
- POL_HND LSA policy handle
- UINT32 num_entries
- UINT32 num_entries
- VOID* undocumented domain SID buffer pointer
- VOID* undocumented domain name buffer pointer
- NAME[num_entries] names to be looked up.
- char[] undocumented bytes - falsely translated SID structure?
-
-Response:
-
- DOM_REF domain reference response
-
- UINT32 num_entries (listed above)
- VOID* undocumented buffer pointer
-
- UINT32 num_entries (listed above)
- DOM_RID[num_entries] domain SIDs (from Request, listed above).
-
- UINT32 num_entries (listed above)
-
- return 0 - indicates success
-
-
-
-5) NETLOGON rpc Transact Named Pipe
------------------------------------
-
-The sequence of actions taken on this pipe are:
-
-- Establish a connection to the IPC$ share (SMBtconX). use encrypted passwords.
-- Open an RPC Pipe with the name "\\PIPE\\NETLOGON". Store the file handle.
-- Using the file handle, send a Set Named Pipe Handle state to 0x4300.
-- Create Client Challenge. Send LSA Request Challenge. Store Server Challenge.
-- Calculate Session Key. Send an LSA Auth 2 Challenge. Store Auth2 Challenge.
-- Calc/Verify Client Creds. Send LSA Srv PW Set. Calc/Verify Server Creds.
-- Calc/Verify Client Creds. Send LSA SAM Logon . Calc/Verify Server Creds.
-- Calc/Verify Client Creds. Send LSA SAM Logoff. Calc/Verify Server Creds.
-- Close the IPC$ share.
-
-
-Defines for this pipe, identifying the query are:
-
-- LSA Request Challenge: 0x04
-- LSA Server Password Set: 0x06
-- LSA SAM Logon: 0x02
-- LSA SAM Logoff: 0x03
-- LSA Auth 2: 0x0f
-- LSA Logon Control: 0x0e
-
-
-5.1) LSA Request Challenge
---------------------------
-
-Note: logon server name starts with two '\' characters and is upper case.
-
-Note: logon client is the machine, not the user.
-
-Note: the initial LanManager password hash, against which the challenge
- is issued, is the machine name itself (lower case). there will be
- calls issued (LSA Server Password Set) which will change this, later.
- refusing these calls allows you to always deal with the same password
- (i.e the LM# of the machine name in lower case).
-
-Request:
-
- VOID* undocumented buffer pointer
- UNISTR2 logon server unicode string
- UNISTR2 logon client unicode string
- char[8] client challenge
-
-Response:
-
- char[8] server challenge
-
- return 0 - indicates success
-
-
-
-5.2) LSA Authenticate 2
------------------------
-
-Note: in between request and response, calculate the client credentials,
- and check them against the client-calculated credentials (this
- process uses the previously received client credentials).
-
-Note: neg_flags in the response is the same as that in the request.
-
-Note: you must take a copy of the client-calculated credentials received
- here, because they will be used in subsequent authentication packets.
-
-Request:
-
- LOG_INFO client identification info
-
- char[8] client-calculated credentials
- UINT8[] padding to 4-byte align with start of SMB header.
- UINT32 neg_flags - negotiated flags (usual value is 0x0000 01ff)
-
-Response:
-
- char[8] server credentials.
- UINT32 neg_flags - same as neg_flags in request.
-
- return 0 - indicates success. failure value unknown.
-
-
-5.3) LSA Server Password Set
-----------------------------
-
-Note: the new password is suspected to be a DES encryption using the old
- password to generate the key.
-
-Note: in between request and response, calculate the client credentials,
- and check them against the client-calculated credentials (this
- process uses the previously received client credentials).
-
-Note: the server credentials are constructed from the client-calculated
- credentials and the client time + 1 second.
-
-Note: you must take a copy of the client-calculated credentials received
- here, because they will be used in subsequent authentication packets.
-
-Request:
-
- CLNT_INFO client identification/authentication info
- char[] new password - undocumented.
-
-Response:
-
- CREDS server credentials. server time stamp appears to be ignored.
-
- return 0 - indicates success; 0xC000 006a indicates failure
-
-
-5.4) LSA SAM Logon
-------------------
-
-Note: valid_user is True iff the username and password hash are valid for
- the requested domain.
-
-Request:
-
- SAM_INFO sam_id structure
-
-Response:
-
- VOID* undocumented buffer pointer
- CREDS server credentials. server time stamp appears to be ignored.
-
- if (valid_user)
- {
- UINT16 3 - switch value indicating USER_INFO structure.
- VOID* non-zero - pointer to USER_INFO structure
- USER_INFO user logon information
-
- UINT32 1 - Authoritative response; 0 - Non-Auth?
-
- return 0 - indicates success
- }
- else
- {
- UINT16 0 - switch value. value to indicate no user presumed.
- VOID* 0x0000 0000 - indicates no USER_INFO structure.
-
- UINT32 1 - Authoritative response; 0 - Non-Auth?
-
- return 0xC000 0064 - NT_STATUS_NO_SUCH_USER.
- }
-
-
-5.5) LSA SAM Logoff
---------------------
-
-Note: presumably, the SAM_INFO structure is validated, and a (currently
- undocumented) error code returned if the Logoff is invalid.
-
-Request:
-
- SAM_INFO sam_id structure
-
-Response:
-
- VOID* undocumented buffer pointer
- CREDS server credentials. server time stamp appears to be ignored.
-
- return 0 - indicates success. undocumented failure indication.
-
-
-6) \\MAILSLOT\NET\NTLOGON
--------------------------
-
-Note: mailslots will contain a response mailslot, to which the response
- should be sent. the target NetBIOS name is REQUEST_NAME<20>, where
- REQUEST_NAME is the name of the machine that sent the request.
-
-
-6.1) Query for PDC
-------------------
-
-Note: NTversion, LMNTtoken, LM20token in response are the same as those
- given in the request.
-
-Request:
-
- UINT16 0x0007 - Query for PDC
- STR machine name
- STR response mailslot
- UINT8[] padding to 2-byte align with start of mailslot.
- UNISTR machine name
- UINT32 NTversion
- UINT16 LMNTtoken
- UINT16 LM20token
-
-Response:
-
- UINT16 0x000A - Respose to Query for PDC
- STR machine name (in uppercase)
- UINT8[] padding to 2-byte align with start of mailslot.
- UNISTR machine name
- UNISTR domain name
- UINT32 NTversion (same as received in request)
- UINT16 LMNTtoken (same as received in request)
- UINT16 LM20token (same as received in request)
-
-
-6.2) SAM Logon
---------------
-
-Note: machine name in response is preceded by two '\' characters.
-
-Note: NTversion, LMNTtoken, LM20token in response are the same as those
- given in the request.
-
-Note: user name in the response is presumably the same as that in the request.
-
-Request:
-
- UINT16 0x0012 - SAM Logon
- UINT16 request count
- UNISTR machine name
- UNISTR user name
- STR response mailslot
- UINT32 alloweable account
- UINT32 domain SID size
- char[sid_size] domain SID, of sid_size bytes.
- UINT8[] ???? padding to 4? 2? -byte align with start of mailslot.
- UINT32 NTversion
- UINT16 LMNTtoken
- UINT16 LM20token
-
-Response:
-
- UINT16 0x0013 - Response to SAM Logon
- UNISTR machine name
- UNISTR user name - workstation trust account
- UNISTR domain name
- UINT32 NTversion
- UINT16 LMNTtoken
- UINT16 LM20token
-
-
-
-7) SRVSVC Transact Named Pipe
------------------------------
-
-
-Defines for this pipe, identifying the query are:
-
-- Net Share Enum : 0x0f
-- Net Server Get Info : 0x15
-
-
-7.1) Net Share Enum
-------------------
-
-Note: share level and switch value in the response are presumably the
- same as those in the request.
-
-Note: cifsrap2.txt (section 5) may be of limited assistance here.
-
-Request:
-
- VOID* pointer (to server name?)
- UNISTR2 server name
-
- UINT8[] padding to get unicode string 4-byte aligned
- with the start of the SMB header.
-
- UINT32 share level
- UINT32 switch value
-
- VOID* pointer to SHARE_INFO_1_CTR
- SHARE_INFO_1_CTR share info with 0 entries
-
- UINT32 preferred maximum length (0xffff ffff)
-
-Response:
-
- UINT32 share level
- UINT32 switch value
-
- VOID* pointer to SHARE_INFO_1_CTR
- SHARE_INFO_1_CTR share info (only added if share info ptr is non-zero)
-
- return 0 - indicates success
-
-
-7.2) Net Server Get Info
-------------------
-
-Note: level is the same value as in the request.
-
-Request:
-
- UNISTR2 server name
- UINT32 switch level
-
-Response:
-
- UINT32 switch level
- VOID* pointer to SERVER_INFO_101
-
- SERVER_INFO_101 server info (only added if server info ptr is non-zero)
-
- return 0 - indicates success
-
-
-
-Appendix
---------
-
-A1) Cryptographic side of NT Domain Authentication
---------------------------------------------------
-
-
-A1.1) Definitions
------------------
-
-Add(A1,A2): Intel byte ordered addition of corresponding 4 byte words
-in arrays A1 and A2
-
-E(K,D): DES ECB encryption of 8 byte data D using 7 byte key K
-
-lmowf(): Lan man hash
-
-ntowf(): NT hash
-
-PW: md4(machine_password) == md4(lsadump $machine.acc) ==
-pwdump(machine$) (initially) == md4(lmowf(unicode(machine)))
-
-RC4(K,Lk,D,Ld): RC4 encryption of data D of length Ld with key K of
-length Lk
-
-v[m..n(,l)]: subset of v from bytes m to n, optionally padded with
-zeroes to length l
-
-Cred(K,D): E(K[7..7,7],E(K[0..6],D)) computes a credential
-
-Time(): 4 byte current time
-
-Cc,Cs: 8 byte client and server challenges Rc,Rs: 8 byte client and
-server credentials
-
-
-A1.2) Protocol
---------------
-
-C->S ReqChal,Cc S->C Cs
-
-C & S compute session key Ks = E(PW[9..15],E(PW[0..6],Add(Cc,Cs)))
-
-C: Rc = Cred(Ks,Cc) C->S Authenticate,Rc S: Rs = Cred(Ks,Cs),
-assert(Rc == Cred(Ks,Cc)) S->C Rs C: assert(Rs == Cred(Ks,Cs))
-
-On joining the domain the client will optionally attempt to change its
-password and the domain controller may refuse to update it depending
-on registry settings. This will also occur weekly afterwards.
-
-C: Tc = Time(), Rc' = Cred(Ks,Rc+Tc) C->S ServerPasswordSet,Rc',Tc,
-rc4(Ks[0..7,16],lmowf(randompassword()) C: Rc = Cred(Ks,Rc+Tc+1) S:
-assert(Rc' == Cred(Ks,Rc+Tc)), Ts = Time() S: Rs' = Cred(Ks,Rs+Tc+1)
-S->C Rs',Ts C: assert(Rs' == Cred(Ks,Rs+Tc+1)) S: Rs = Rs'
-
-User: U with password P wishes to login to the domain (incidental data
-such as workstation and domain omitted)
-
-C: Tc = Time(), Rc' = Cred(Ks,Rc+Tc) C->S NetLogonSamLogon,Rc',Tc,U,
-rc4(Ks[0..7,16],16,ntowf(P),16), rc4(Ks[0..7,16],16,lmowf(P),16) S:
-assert(Rc' == Cred(Ks,Rc+Tc)) assert(passwords match those in SAM) S:
-Ts = Time()
-
-S->C Cred(Ks,Cred(Ks,Rc+Tc+1)),userinfo(logon script,UID,SIDs,etc) C:
-assert(Rs == Cred(Ks,Cred(Rc+Tc+1)) C: Rc = Cred(Ks,Rc+Tc+1)
-
-
-A1.3) Comments
---------------
-
-On first joining the domain the session key could be computed by
-anyone listening in on the network as the machine password has a well
-known value. Until the machine is rebooted it will use this session
-key to encrypt NT and LM one way functions of passwords which are
-password equivalents. Any user who logs in before the machine has been
-rebooted a second time will have their password equivalent exposed. Of
-course the new machine password is exposed at this time anyway.
-
-None of the returned user info such as logon script, profile path and
-SIDs *appear* to be protected by anything other than the TCP checksum.
-
-The server time stamps appear to be ignored.
-
-The client sends a ReturnAuthenticator in the SamLogon request which I
-can't find a use for. However its time is used as the timestamp
-returned by the server.
-
-The password OWFs should NOT be sent over the network reversibly
-encrypted. They should be sent using RC4(Ks,md4(owf)) with the server
-computing the same function using the owf values in the SAM.
-
-
-A2) SIDs and RIDs
------------------
-
-SIDs and RIDs are well documented elsewhere.
-
-A SID is an NT Security ID (see DOM_SID structure). They are of the form:
-
- S-revision-NN-SubAuth1-SubAuth2-SubAuth3...
- S-revision-0xNNNNNNNNNNNN-SubAuth1-SubAuth2-SubAuth3...
-
-currently, the SID revision is 1.
-The Sub-Authorities are known as Relative IDs (RIDs).
-
-
-A2.1) Well-known SIDs
----------------------
-
-
-A2.1.1) Universal well-known SIDs
----------------------------------
-
- Null SID S-1-0-0
- World S-1-1-0
- Local S-1-2-0
- Creator Owner ID S-1-3-0
- Creator Group ID S-1-3-1
- Creator Owner Server ID S-1-3-2
- Creator Group Server ID S-1-3-3
-
- (Non-unique IDs) S-1-4
-
-
-A2.1.2) NT well-known SIDs
---------------------------
-
- NT Authority S-1-5
- Dialup S-1-5-1
-
- Network S-1-5-2
- Batch S-1-5-3
- Interactive S-1-5-4
- Service S-1-5-6
- AnonymousLogon S-1-5-7 (aka null logon session)
- Proxy S-1-5-8
- ServerLogon S-1-5-8 (aka domain controller account)
-
- (Logon IDs) S-1-5-5-X-Y
-
- (NT non-unique IDs) S-1-5-0x15-...
-
- (Built-in domain) s-1-5-0x20
-
-
-
-A2.2) Well-known RIDS
----------------------
-
-A RID is a sub-authority value, as part of either a SID, or in the case
-of Group RIDs, part of the DOM_GID structure, in the USER_INFO_1
-structure, in the LSA SAM Logon response.
-
-
-A2.2.1) Well-known RID users
-----------------------------
-
- DOMAIN_USER_RID_ADMIN 0x0000 01F4
- DOMAIN_USER_RID_GUEST 0x0000 01F5
-
-
-
-A2.2.2) Well-known RID groups
-----------------------------
-
- DOMAIN_GROUP_RID_ADMINS 0x0000 0200
- DOMAIN_GROUP_RID_USERS 0x0000 0201
- DOMAIN_GROUP_RID_GUESTS 0x0000 0202
-
-
-
-A2.2.3) Well-known RID aliases
-------------------------------
-
- DOMAIN_ALIAS_RID_ADMINS 0x0000 0220
- DOMAIN_ALIAS_RID_USERS 0x0000 0221
- DOMAIN_ALIAS_RID_GUESTS 0x0000 0222
- DOMAIN_ALIAS_RID_POWER_USERS 0x0000 0223
-
- DOMAIN_ALIAS_RID_ACCOUNT_OPS 0x0000 0224
- DOMAIN_ALIAS_RID_SYSTEM_OPS 0x0000 0225
- DOMAIN_ALIAS_RID_PRINT_OPS 0x0000 0226
- DOMAIN_ALIAS_RID_BACKUP_OPS 0x0000 0227
-
- DOMAIN_ALIAS_RID_REPLICATOR 0x0000 0228
-
-
diff --git a/docs/textdocs/security_level.txt b/docs/textdocs/security_level.txt
index a948d324bff..a231c62c1b2 100644
--- a/docs/textdocs/security_level.txt
+++ b/docs/textdocs/security_level.txt
@@ -1,5 +1,5 @@
!==
-!== security_level.txt for Samba release 1.9.18alpha13 16 Dec 1997
+!== security_level.txt for Samba release 1.9.17p5 20 Dec 1997
!==
Contributor: Andrew Tridgell
Updated: June 27, 1997
diff --git a/examples/misc/extra_smbstatus b/examples/misc/extra_smbstatus
index 584284feb34..363e7f67af5 100644
--- a/examples/misc/extra_smbstatus
+++ b/examples/misc/extra_smbstatus
@@ -46,5 +46,5 @@ Cheers,
| | "Spend a little love and get high"
_/ \_ | - Lenny Kravitz
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-~~~~~~~~~~~~~~ SAMBA Web Pages: http://samba.anu.edu.au/samba/ ~~~~~~~~~~~~~~
+~~~~ SAMBA Web Pages: http://samba.canberra.edu.au/pub/samba/samba.html ~~~~~
diff --git a/examples/smb.conf.default b/examples/smb.conf.default
index fba4ecca0ac..b8895bd4cf6 100644
--- a/examples/smb.conf.default
+++ b/examples/smb.conf.default
@@ -29,18 +29,11 @@
# If you want to automatically load your printer list rather
# than setting them up individually then you'll need this
+ printcap name = /etc/printcap
load printers = yes
-# you may wish to override the location of the printcap file
-; printcap name = /etc/printcap
-
-# on SystemV system setting printcap name to lpstat should allow
-# you to automatically obtain a printer list from the SystemV spool
-# system
-; printcap name = lpstat
-
-# It should not be necessary to specify the print system type unless
-# it is non-standard. Currently supported print systems include:
+# It should not be necessary to spell out the print system type unless
+# yours is non-standard. Currently supported print systems include:
# bsd, sysv, plp, lprng, aix, hpux, qnx
; printing = bsd
@@ -111,7 +104,7 @@
# run a specific logon batch file per workstation (machine)
; logon script = %m.bat
# run a specific logon batch file per username
-; logon script = %U.bat
+; logon script = %u.bat
# Where to store roving profiles (only for Win95 and WinNT)
# %L substitutes for this servers netbios name, %U is username
@@ -213,7 +206,7 @@
# a service which has a different directory for each machine that connects
# this allows you to tailor configurations to incoming machines. You could
-# also use the %U option to tailor it by user name.
+# also use the %u option to tailor it by user name.
# The %m gets replaced with the machine name that is connecting.
;[pchome]
; comment = PC Directories
diff --git a/packaging/SGI/README b/packaging/SGI/README
index 02855bb3a2c..0675deb51ee 100644
--- a/packaging/SGI/README
+++ b/packaging/SGI/README
@@ -31,12 +31,10 @@ inetd you can run the script /usr/samba/inetd.sh.
To create a Samba distribution you must have the Documenter's WorkBench
package installed to format the manual pages. In addition you need
to have the Software Packager software (inst_dev) installed to
-generate the inst images, and Perl to generate the spec and idb files.
-
-From /usr/samba/packaging/SGI directory run the mkrelease.sh script.
-There is one optional argument which is the major release number of the
-OS version (4, 5, or 6) you desire. If no number is specified it defaults
-to 6. This script uses Perl to generate the Makefile with the proper
-defines and the packaging files samba.spec and samba.idb. The binary
-package files will be placed in ./bins
+generate the inst images.
+
+From /usr/samba/packaging/SGI directory run the mkrelease.sh script.
+This script uses Perl to generate the Makefile with the proper defines
+and the packaging files samba.spec and samba.idb.
+The binary package files will be placed in ./bins
diff --git a/packaging/SGI/idb.pl b/packaging/SGI/idb.pl
index bad7bfb862e..47cf16a5bcf 100755
--- a/packaging/SGI/idb.pl
+++ b/packaging/SGI/idb.pl
@@ -54,7 +54,7 @@ if (@codepage) {
@codepage[0] =~ s/^.*\)//;
chdir '../../source';
# if we have codepages we need to create them for the package
- system("./installcp.sh . ../packaging/SGI/codepages . @codepage[0]");
+ system("./installcp.sh . ../packaging/SGI/codepage . @codepage[0]");
chdir $curdir;
@codepage = sort split(' ',@codepage[0]);
}
@@ -71,7 +71,7 @@ if (@codepage) {
# strip out all the generated directories and the "*.o" files from the source
# release
-@allfiles = grep(!/^.*\.o$/ & !/^packaging\/SGI\/bins/ & !/^packaging\/SGI\/catman/ & !/^packaging\/SGI\/html/ & !/^packaging\/SGI\/codepages/, @allfiles);
+@allfiles = grep(!/^.*\.o$/ & !/^packaging\/SGI\/bins/ & !/^packaging\/SGI\/catman/ & !/^packaging\/SGI\/html/ & !/^packaging\/SGI\/codepage/, @allfiles);
open(IDB,">samba.idb") || die "Unable to open samba.idb for output\n";
@@ -127,10 +127,10 @@ while (@docs) {
print IDB "f 0755 root sys usr/samba/inetd.sh packaging/SGI/inetd.sh samba.sw.base\n";
print IDB "d 0755 root sys usr/samba/lib packaging/SGI samba.sw.base\n";
if (@codepage) {
- print IDB "d 0755 root sys usr/samba/lib/codepages packaging/SGI samba.sw.base\n";
+ print IDB "d 0755 root sys usr/samba/lib/codepage packaging/SGI samba.sw.base\n";
while (@codepage) {
$nextpage = shift @codepage;
- print IDB "f 0644 root sys usr/samba/lib/codepages/codepage.$nextpage packaging/SGI/codepages/codepage.$nextpage samba.sw.base\n";
+ print IDB "f 0644 root sys usr/samba/lib/codepage/codepage.$nextpage packaging/SGI/codepage/codepage.$nextpage samba.sw.base\n";
}
}
print IDB "f 0644 root sys usr/samba/lib/smb.conf packaging/SGI/smb.conf samba.sw.base config(update)\n";
diff --git a/packaging/SGI/smb.conf b/packaging/SGI/smb.conf
index dce487b4e35..b484cc918b2 100644
--- a/packaging/SGI/smb.conf
+++ b/packaging/SGI/smb.conf
@@ -38,11 +38,8 @@
guest account = nobody
browseable = yes
-; this tells Samba to use a separate log file for each machine
-; that connects - default is single file named /usr/samba/var/log.smb
-; log file = /usr/samba/var/log.%m
-
; Set a max size for log files in Kb
+ log file = /usr/samba/var
max log size = 50
; You will need a world readable lock directory and "share modes=yes"
diff --git a/source/.cvsignore b/source/.cvsignore
index 1e48a541752..9b7ea034be9 100644
--- a/source/.cvsignore
+++ b/source/.cvsignore
@@ -1,8 +1,6 @@
Makefile.RPM
makefile
makefile.sunos5
-make_smbcodepage
-make_printerdef
nmbd
nmblookup
smbclient
diff --git a/source/cgi.c b/source/cgi.c
deleted file mode 100644
index f165c56110b..00000000000
--- a/source/cgi.c
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- some simple CGI helper routines
- Copyright (C) Andrew Tridgell 1997
-
- 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.
-*/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <pwd.h>
-
-#define MAX_VARIABLES 10000
-
-#ifdef DEBUG_COMMENTS
-extern void print_title(char *fmt, ...);
-#endif
-
-struct var {
- char *name;
- char *value;
-};
-
-static struct var variables[MAX_VARIABLES];
-static int num_variables;
-static int content_length;
-static int request_post;
-static int request_get;
-static char *query_string;
-
-static void unescape(char *buf)
-{
- char *p=buf;
-
- while ((p=strchr(p,'+')))
- *p = ' ';
-
- p = buf;
-
- while (p && *p && (p=strchr(p,'%'))) {
- int c1 = p[1];
- int c2 = p[2];
-
- if (c1 >= '0' && c1 <= '9')
- c1 = c1 - '0';
- else if (c1 >= 'A' && c1 <= 'F')
- c1 = 10 + c1 - 'A';
- else if (c1 >= 'a' && c1 <= 'f')
- c1 = 10 + c1 - 'a';
- else {p++; continue;}
-
- if (c2 >= '0' && c2 <= '9')
- c2 = c2 - '0';
- else if (c2 >= 'A' && c2 <= 'F')
- c2 = 10 + c2 - 'A';
- else if (c2 >= 'a' && c2 <= 'f')
- c2 = 10 + c2 - 'a';
- else {p++; continue;}
-
- *p = (c1<<4) | c2;
-
- memcpy(p+1, p+3, strlen(p+3)+1);
- p++;
- }
-}
-
-
-static char *grab_line(FILE *f, int *cl)
-{
- char *ret;
- int i = 0;
- int len = 1024;
-
- ret = (char *)malloc(len);
- if (!ret) return NULL;
-
-
- while ((*cl)) {
- int c = fgetc(f);
- (*cl)--;
-
- if (c == EOF) {
- (*cl) = 0;
- break;
- }
-
- if (c == '\r') continue;
-
- if (strchr("\n&", c)) break;
-
- ret[i++] = c;
-
- if (i == len-1) {
- char *ret2;
- ret2 = (char *)realloc(ret, len*2);
- if (!ret2) return ret;
- len *= 2;
- ret = ret2;
- }
- }
-
-
- ret[i] = 0;
- return ret;
-}
-
-/***************************************************************************
- load all the variables passed to the CGI program. May have multiple variables
- with the same name and the same or different values. Takes a file parameter
- for simulating CGI invocation eg loading saved preferences.
- ***************************************************************************/
-void cgi_load_variables(FILE *f1)
-{
- FILE *f = f1;
- static char *line;
- char *p, *s, *tok;
- int len;
-
-#ifdef DEBUG_COMMENTS
- char dummy[100]="";
- print_title(dummy);
- printf("<!== Start dump in cgi_load_variables() %s ==>\n",__FILE__);
-#endif
-
- if (!f1) {
- f = stdin;
- if (!content_length) {
- p = getenv("CONTENT_LENGTH");
- len = p?atoi(p):0;
- } else {
- len = content_length;
- }
- } else {
- fseek(f, 0, SEEK_END);
- len = ftell(f);
- fseek(f, 0, SEEK_SET);
- }
-
-
- if (len > 0 &&
- (f1 || request_post ||
- ((s=getenv("REQUEST_METHOD")) &&
- strcasecmp(s,"POST")==0))) {
- while (len && (line=grab_line(f, &len))) {
- p = strchr(line,'=');
- if (!p) continue;
-
- *p = 0;
-
- variables[num_variables].name = strdup(line);
- variables[num_variables].value = strdup(p+1);
-
- free(line);
-
- if (!variables[num_variables].name ||
- !variables[num_variables].value)
- continue;
-
- unescape(variables[num_variables].value);
- unescape(variables[num_variables].name);
-
-#ifdef DEBUG_COMMENTS
- printf("<!== POST var %s has value \"%s\" ==>\n",
- variables[num_variables].name,
- variables[num_variables].value);
-#endif
-
- num_variables++;
- if (num_variables == MAX_VARIABLES) break;
- }
- }
-
- if (f1) {
-#ifdef DEBUG_COMMENTS
- printf("<!== End dump in cgi_load_variables() ==>\n");
-#endif
- return;
- }
-
- fclose(stdin);
-
- if ((s=query_string) || (s=getenv("QUERY_STRING"))) {
- for (tok=strtok(s,"&;");tok;tok=strtok(NULL,"&;")) {
- p = strchr(tok,'=');
- if (!p) continue;
-
- *p = 0;
-
- variables[num_variables].name = strdup(tok);
- variables[num_variables].value = strdup(p+1);
-
- if (!variables[num_variables].name ||
- !variables[num_variables].value)
- continue;
-
- unescape(variables[num_variables].value);
- unescape(variables[num_variables].name);
-
-#ifdef DEBUG_COMMENTS
- printf("<!== Commandline var %s has value \"%s\" ==>\n",
- variables[num_variables].name,
- variables[num_variables].value);
-#endif
- num_variables++;
- if (num_variables == MAX_VARIABLES) break;
- }
-
- }
-#ifdef DEBUG_COMMENTS
- printf("<!== End dump in cgi_load_variables() ==>\n");
-#endif
-}
-
-
-/***************************************************************************
- find a variable passed via CGI
- Doesn't quite do what you think in the case of POST text variables, because
- if they exist they might have a value of "" or even " ", depending on the
- browser. Also doesn't allow for variables[] containing multiple variables
- with the same name and the same or different values.
- ***************************************************************************/
-char *cgi_variable(char *name)
-{
- int i;
-
- for (i=0;i<num_variables;i++)
- if (strcmp(variables[i].name, name) == 0)
- return variables[i].value;
- return NULL;
-}
-
-/***************************************************************************
-return a particular cgi variable
- ***************************************************************************/
-char *cgi_vnum(int i, char **name)
-{
- if (i < 0 || i >= num_variables) return NULL;
- *name = variables[i].name;
- return variables[i].value;
-}
-
-/***************************************************************************
- return the value of a CGI boolean variable.
- ***************************************************************************/
-int cgi_boolean(char *name, int def)
-{
- char *p = cgi_variable(name);
-
- if (!p) return def;
-
- return strcmp(p, "1") == 0;
-}
-
-/***************************************************************************
-like strdup() but quotes < > and &
- ***************************************************************************/
-char *quotedup(char *s)
-{
- int i, n=0;
- int len;
- char *ret;
- char *d;
-
- if (!s) return strdup("");
-
- len = strlen(s);
-
- for (i=0;i<len;i++)
- if (s[i] == '<' || s[i] == '>' || s[i] == '&')
- n++;
-
- ret = malloc(len + n*6 + 1);
-
- if (!ret) return NULL;
-
- d = ret;
-
- for (i=0;i<len;i++) {
- switch (s[i]) {
- case '<':
- strcpy(d, "&lt;");
- d += 4;
- break;
-
- case '>':
- strcpy(d, "&gt;");
- d += 4;
- break;
-
- case '&':
- strcpy(d, "&amp;");
- d += 5;
- break;
-
- default:
- *d++ = s[i];
- }
- }
-
- *d = 0;
-
- return ret;
-}
-
-
-/***************************************************************************
-like strdup() but quotes a wide range of characters
- ***************************************************************************/
-char *urlquote(char *s)
-{
- int i, n=0;
- int len;
- char *ret;
- char *d;
- char *qlist = "\"\n\r'&<> \t+;";
-
- if (!s) return strdup("");
-
- len = strlen(s);
-
- for (i=0;i<len;i++)
- if (strchr(qlist, s[i])) n++;
-
- ret = malloc(len + n*2 + 1);
-
- if (!ret) return NULL;
-
- d = ret;
-
- for (i=0;i<len;i++) {
- if (strchr(qlist,s[i])) {
- sprintf(d, "%%%02X", (int)s[i]);
- d += 3;
- } else {
- *d++ = s[i];
- }
- }
-
- *d = 0;
-
- return ret;
-}
-
-
-/***************************************************************************
-like strdup() but quotes " characters
- ***************************************************************************/
-char *quotequotes(char *s)
-{
- int i, n=0;
- int len;
- char *ret;
- char *d;
-
- if (!s) return strdup("");
-
- len = strlen(s);
-
- for (i=0;i<len;i++)
- if (s[i] == '"')
- n++;
-
- ret = malloc(len + n*6 + 1);
-
- if (!ret) return NULL;
-
- d = ret;
-
- for (i=0;i<len;i++) {
- switch (s[i]) {
- case '"':
- strcpy(d, "&quot;");
- d += 6;
- break;
-
- default:
- *d++ = s[i];
- }
- }
-
- *d = 0;
-
- return ret;
-}
-
-
-/***************************************************************************
-quote spaces in a buffer
- ***************************************************************************/
-void quote_spaces(char *buf)
-{
- while (*buf) {
- if (*buf == ' ') *buf = '+';
- buf++;
- }
-}
-
-
-
-/***************************************************************************
-tell a browser about a fatal error in the http processing
- ***************************************************************************/
-static void cgi_setup_error(char *err, char *header, char *info)
-{
- printf("HTTP/1.1 %s\r\n%sConnection: close\r\nContent-Type: text/html\r\n\r\n<HTML><HEAD><TITLE>%s</TITLE></HEAD><BODY><H1>%s</H1>%s<p></BODY></HTML>\r\n", err, header, err, err, info);
- exit(0);
-}
-
-
-/***************************************************************************
-decode a base64 string in-place - simple and slow algorithm
- ***************************************************************************/
-static void base64_decode(char *s)
-{
- char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- int bit_offset, byte_offset, idx, i;
- unsigned char *d = (unsigned char *)s;
- char *p;
-
- i=0;
-
- while (*s && (p=strchr(b64,*s))) {
- idx = (int)(p - b64);
- byte_offset = (i*6)/8;
- bit_offset = (i*6)%8;
- d[byte_offset] &= ~((1<<(8-bit_offset))-1);
- if (bit_offset < 3) {
- d[byte_offset] |= (idx << (2-bit_offset));
- } else {
- d[byte_offset] |= (idx >> (bit_offset-2));
- d[byte_offset+1] = 0;
- d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
- }
- s++; i++;
- }
-}
-
-
-/***************************************************************************
-handle a http authentication line
- ***************************************************************************/
-static int cgi_handle_authorization(char *line)
-{
- char *p, *user, *pass;
- struct passwd *pwd;
- int ret=0;
-
- if (strncasecmp(line,"Basic ", 6)) {
- cgi_setup_error("401 Bad Authorization", "",
- "Only basic authorization is understood");
- }
- line += 6;
- while (line[0] == ' ') line++;
- base64_decode(line);
- if (!(p=strchr(line,':'))) {
- cgi_setup_error("401 Bad Authorization", "",
- "username/password must be supplied");
- }
- *p = 0;
- user = line;
- pass = p+1;
-
- /* currently only allow connections as root */
- if (strcasecmp(user,"root")) {
- cgi_setup_error("401 Bad Authorization", "",
- "incorrect username/password");
- }
-
- pwd = getpwnam(user);
-
- if (!strcmp((char *)crypt(pass, pwd->pw_passwd),pwd->pw_passwd)) {
- ret = 1;
- }
-
- memset(pass, 0, strlen(pass));
-
- return ret;
-}
-
-
-/***************************************************************************
-handle a file download
- ***************************************************************************/
-static void cgi_download(char *file)
-{
- struct stat st;
- char buf[1024];
- int fd, l, i;
- char *p;
-
- /* sanitise the filename */
- for (i=0;file[i];i++) {
- if (!isalnum(file[i]) && !strchr("/.-_", file[i])) {
- cgi_setup_error("404 File Not Found","",
- "Illegal character in filename");
- }
- }
-
- if (strstr(file,"..")) {
- cgi_setup_error("404 File Not Found","",
- "Relative paths not allowed");
- }
-
- if (!file_exist(file, &st)) {
- cgi_setup_error("404 File Not Found","",
- "The requested file was not found");
- }
- fd = open(file,O_RDONLY);
- if (fd == -1) {
- cgi_setup_error("404 File Not Found","",
- "The requested file was not found");
- }
- printf("HTTP/1.1 200 OK\r\n");
- if ((p=strrchr(file,'.'))) {
- if (strcmp(p,".gif")==0 || strcmp(p,".jpg")==0) {
- printf("Content-Type: image/gif\r\n");
- } else {
- printf("Content-Type: text/html\r\n");
- }
- }
- printf("Content-Length: %d\r\n\r\n", (int)st.st_size);
- while ((l=read(fd,buf,sizeof(buf)))>0) {
- fwrite(buf, 1, l, stdout);
- }
- close(fd);
- exit(0);
-}
-
-
-/***************************************************************************
-setup the cgi framework, handling the possability that this program is either
-run as a true cgi program by a web browser or is itself a mini web server
- ***************************************************************************/
-void cgi_setup(char *rootdir)
-{
- int authenticated = 0;
- char line[1024];
- char *url=NULL;
- char *p;
-
- if (chdir(rootdir)) {
- cgi_setup_error("400 Server Error", "",
- "chdir failed - the server is not configured correctly");
- }
-
- if (getenv("CONTENT_LENGTH") || getenv("REQUEST_METHOD")) {
- /* assume we are running under a real web server */
- return;
- }
-
- /* we are a mini-web server. We need to read the request from stdin
- and handle authentication etc */
- while (fgets(line, sizeof(line)-1, stdin)) {
- if (line[0] == '\r' || line[0] == '\n') break;
- if (strncasecmp(line,"GET ", 4)==0) {
- request_get = 1;
- url = strdup(&line[4]);
- } else if (strncasecmp(line,"POST ", 5)==0) {
- request_post = 1;
- url = strdup(&line[5]);
- } else if (strncasecmp(line,"PUT ", 4)==0) {
- cgi_setup_error("400 Bad Request", "",
- "This server does not accept PUT requests");
- } else if (strncasecmp(line,"Authorization: ", 15)==0) {
- authenticated = cgi_handle_authorization(&line[15]);
- } else if (strncasecmp(line,"Content-Length: ", 16)==0) {
- content_length = atoi(&line[16]);
- }
- /* ignore all other requests! */
- }
-
- if (!authenticated) {
- cgi_setup_error("401 Authorization Required",
- "WWW-Authenticate: Basic realm=\"root\"\r\n",
- "You must be authenticated to use this service");
- }
-
- if (!url) {
- cgi_setup_error("400 Bad Request", "",
- "You must specify a GET or POST request");
- }
-
- /* trim the URL */
- if ((p = strchr(url,' ')) || (p=strchr(url,'\t'))) {
- *p = 0;
- }
- while (*url && strchr("\r\n",url[strlen(url)-1])) {
- url[strlen(url)-1] = 0;
- }
-
- /* anything following a ? in the URL is part of the query string */
- if ((p=strchr(url,'?'))) {
- query_string = p+1;
- *p = 0;
- }
-
- if (strcmp(url,"/")) {
- cgi_download(url+1);
- }
-
- printf("HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n");
-
-}
-
-
diff --git a/source/client/client.c b/source/client/client.c
index ee6155621cd..a48d1b4990b 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -31,20 +31,21 @@
pstring cur_dir = "\\";
pstring cd_path = "";
-extern pstring service;
-extern pstring desthost;
+pstring service="";
+pstring desthost="";
extern pstring myname;
extern pstring myhostname;
-extern pstring password;
-extern pstring username;
-extern pstring workgroup;
+pstring password = "";
+pstring username="";
+pstring workgroup="";
char *cmdstr="";
-extern BOOL got_pass;
-extern BOOL connect_as_printer;
-extern BOOL connect_as_ipc;
+BOOL got_pass = False;
+BOOL connect_as_printer = False;
+BOOL connect_as_ipc = False;
extern struct in_addr ipzero;
-extern BOOL doencrypt;
+char cryptkey[8];
+BOOL doencrypt=False;
extern pstring user_socket_options;
@@ -55,9 +56,9 @@ extern pstring user_socket_options;
/* value for unused fid field in trans2 secondary request */
#define FID_UNUSED (0xFFFF)
-extern int name_type;
+int name_type = 0x20;
-extern int max_protocol;
+int max_protocol = PROTOCOL_NT1;
time_t newer_than = 0;
@@ -68,19 +69,23 @@ extern int DEBUGLEVEL;
BOOL translation = False;
-extern int cnum;
-extern int mid;
-extern int pid;
-extern int tid;
-extern int gid;
-extern int uid;
-
-extern BOOL have_ip;
-extern int max_xmit;
+static BOOL send_trans_request(char *outbuf,int trans,
+ char *name,int fid,int flags,
+ char *data,char *param,uint16 *setup,
+ int ldata,int lparam,int lsetup,
+ int mdata,int mparam,int msetup);
+static BOOL receive_trans_response(char *inbuf,int trans,
+ int *data_len,int *param_len,
+ char **data,char **param);
static int interpret_long_filename(int level,char *p,file_info *finfo);
static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,BOOL recurse_dir,void (*fn)(),BOOL longdir);
static int interpret_short_filename(char *p,file_info *finfo);
+static BOOL call_api(int prcnt,int drcnt,
+ int mprcnt,int mdrcnt,
+ int *rprcnt,int *rdrcnt,
+ char *param,char *data,
+ char **rparam,char **rdata);
static BOOL do_this_one(file_info *finfo);
/* clitar bits insert */
@@ -90,8 +95,15 @@ extern BOOL tar_reset;
/* clitar bits end */
+int cnum = 0;
+int pid = 0;
+int gid = 0;
+int uid = 0;
+int mid = 0;
int myumask = 0755;
+int max_xmit = BUFFER_SIZE;
+
extern pstring scope;
BOOL prompt = True;
@@ -101,6 +113,8 @@ int printmode = 1;
BOOL recurse = False;
BOOL lowercase = False;
+BOOL have_ip = False;
+
struct in_addr dest_ip;
#define SEPARATORS " \t\n\r"
@@ -109,8 +123,8 @@ BOOL abort_mget = True;
extern int Protocol;
-extern BOOL readbraw_supported ;
-extern BOOL writebraw_supported;
+BOOL readbraw_supported = False;
+BOOL writebraw_supported = False;
pstring fileselection = "";
@@ -129,30 +143,39 @@ extern int Client;
#define USENMB
-static BOOL setup_term_code(char *code)
+#ifdef KANJI
+extern int coding_system;
+#define CNV_LANG(s) (coding_system == DOSV_CODE?s:dos_to_unix(s, False))
+#define CNV_INPUT(s) (coding_system == DOSV_CODE?s:unix_to_dos(s, True))
+static BOOL
+setup_term_code (char *code)
{
- interpret_coding_system(code);
+ int new;
+ new = interpret_coding_system (code, UNKNOWN_CODE);
+ if (new != UNKNOWN_CODE) {
+ coding_system = new;
return True;
+ }
+ return False;
}
+#else
#define CNV_LANG(s) dos2unix_format(s,False)
#define CNV_INPUT(s) unix2dos_format(s,True)
+#endif
/****************************************************************************
-send an SMBclose on an SMB file handle
+setup basics in a outgoing packet
****************************************************************************/
-void cli_smb_close(char *inbuf, char *outbuf, int clnt_fd, int c_num, int f_num)
+void setup_pkt(char *outbuf)
{
- bzero(outbuf,smb_size);
- set_message(outbuf,3,0,True);
-
- CVAL (outbuf,smb_com) = SMBclose;
- SSVAL(outbuf,smb_tid,c_num);
- cli_setup_pkt(outbuf);
- SSVAL (outbuf,smb_vwv0, f_num);
- SIVALS(outbuf,smb_vwv1, -1);
-
- send_smb(clnt_fd, outbuf);
- receive_smb(clnt_fd,inbuf,CLIENT_TIMEOUT);
+ SSVAL(outbuf,smb_pid,pid);
+ SSVAL(outbuf,smb_uid,uid);
+ SSVAL(outbuf,smb_mid,mid);
+ if (Protocol > PROTOCOL_COREPLUS)
+ {
+ SCVAL(outbuf,smb_flg,0x8);
+ SSVAL(outbuf,smb_flg2,0x1);
+ }
}
/****************************************************************************
@@ -252,24 +275,12 @@ static BOOL chkpath(char *path,BOOL report)
set_message(outbuf,0,4 + strlen(path2),True);
SCVAL(outbuf,smb_com,SMBchkpth);
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
p = smb_buf(outbuf);
*p++ = 4;
strcpy(p,path2);
-#if 0
- {
- /* this little bit of code can be used to extract NT error codes.
- Just feed a bunch of "cd foo" commands to smbclient then watch
- in netmon (tridge) */
- static int code=0;
- SIVAL(outbuf, smb_rcls, code | 0xC0000000);
- SSVAL(outbuf, smb_flg2, SVAL(outbuf, smb_flg2) | (1<<14));
- code++;
- }
-#endif
-
send_smb(Client,outbuf);
receive_smb(Client,inbuf,CLIENT_TIMEOUT);
@@ -392,7 +403,7 @@ static void do_dskattr(void)
set_message(outbuf,0,0,True);
CVAL(outbuf,smb_com) = SMBdskattr;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
send_smb(Client,outbuf);
receive_smb(Client,inbuf,CLIENT_TIMEOUT);
@@ -545,12 +556,12 @@ static int do_long_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*
}
/* ??? original code added 1 pad byte after param */
- cli_send_trans_request(outbuf,SMBtrans2,NULL,0,FID_UNUSED,0,
+ send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
NULL,param,&setup,
0,12+strlen(mask)+1,1,
BUFFER_SIZE,10,0);
- if (!cli_receive_trans_response(inbuf,SMBtrans2,
+ if (!receive_trans_response(inbuf,SMBtrans2,
&resp_data_len,&resp_param_len,
&resp_data,&resp_param))
{
@@ -689,7 +700,7 @@ static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (
CVAL(outbuf,smb_com) = SMBsearch;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,num_asked);
SSVAL(outbuf,smb_vwv1,attribute);
@@ -750,7 +761,7 @@ static int do_short_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (
CVAL(outbuf,smb_com) = SMBfclose;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
p = smb_buf(outbuf);
*p++ = 4;
@@ -825,7 +836,7 @@ static BOOL do_this_one(file_info *finfo)
/*****************************************************************************
- Convert a character pointer in a cli_call_api() response to a form we can use.
+ Convert a character pointer in a call_api() response to a form we can use.
This function contains code to prevent core dumps if the server returns
invalid data.
*****************************************************************************/
@@ -1017,6 +1028,80 @@ static void dir_action(char *inbuf,char *outbuf,int attribute,file_info *finfo,B
/****************************************************************************
+ receive a SMB trans or trans2 response allocating the necessary memory
+ ****************************************************************************/
+static BOOL receive_trans_response(char *inbuf,int trans,
+ int *data_len,int *param_len,
+ char **data,char **param)
+{
+ int total_data=0;
+ int total_param=0;
+ int this_data,this_param;
+
+ *data_len = *param_len = 0;
+
+ receive_smb(Client,inbuf,CLIENT_TIMEOUT);
+ show_msg(inbuf);
+
+ /* sanity check */
+ if (CVAL(inbuf,smb_com) != trans)
+ {
+ DEBUG(0,("Expected %s response, got command 0x%02x\n",
+ trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
+ return(False);
+ }
+ if (CVAL(inbuf,smb_rcls) != 0)
+ return(False);
+
+ /* parse out the lengths */
+ total_data = SVAL(inbuf,smb_tdrcnt);
+ total_param = SVAL(inbuf,smb_tprcnt);
+
+ /* allocate it */
+ *data = Realloc(*data,total_data);
+ *param = Realloc(*param,total_param);
+
+ while (1)
+ {
+ this_data = SVAL(inbuf,smb_drcnt);
+ this_param = SVAL(inbuf,smb_prcnt);
+ if (this_data)
+ memcpy(*data + SVAL(inbuf,smb_drdisp),
+ smb_base(inbuf) + SVAL(inbuf,smb_droff),
+ this_data);
+ if (this_param)
+ memcpy(*param + SVAL(inbuf,smb_prdisp),
+ smb_base(inbuf) + SVAL(inbuf,smb_proff),
+ this_param);
+ *data_len += this_data;
+ *param_len += this_param;
+
+ /* parse out the total lengths again - they can shrink! */
+ total_data = SVAL(inbuf,smb_tdrcnt);
+ total_param = SVAL(inbuf,smb_tprcnt);
+
+ if (total_data <= *data_len && total_param <= *param_len)
+ break;
+
+ receive_smb(Client,inbuf,CLIENT_TIMEOUT);
+ show_msg(inbuf);
+
+ /* sanity check */
+ if (CVAL(inbuf,smb_com) != trans)
+ {
+ DEBUG(0,("Expected %s response, got command 0x%02x\n",
+ trans==SMBtrans?"SMBtrans":"SMBtrans2", CVAL(inbuf,smb_com)));
+ return(False);
+ }
+ if (CVAL(inbuf,smb_rcls) != 0)
+ return(False);
+ }
+
+ return(True);
+}
+
+
+/****************************************************************************
get a directory listing
****************************************************************************/
static void cmd_dir(char *inbuf,char *outbuf)
@@ -1093,16 +1178,14 @@ static void do_get(char *rname,char *lname,file_info *finfo1)
CVAL(outbuf,smb_com) = SMBopenX;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,0xFF);
- SSVAL(outbuf,smb_vwv2,1); /* return additional info */
+ SSVAL(outbuf,smb_vwv2,1);
SSVAL(outbuf,smb_vwv3,(DENY_NONE<<4));
SSVAL(outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
SSVAL(outbuf,smb_vwv5,aSYSTEM | aHIDDEN);
SSVAL(outbuf,smb_vwv8,1);
- SSVAL(outbuf,smb_vwv11,0xffff);
- SSVAL(outbuf,smb_vwv12,0xffff);
p = smb_buf(outbuf);
strcpy(p,rname);
@@ -1146,7 +1229,7 @@ static void do_get(char *rname,char *lname,file_info *finfo1)
{
if (CVAL(inbuf,smb_rcls) == ERRSRV &&
SVAL(inbuf,smb_err) == ERRnoresource &&
- cli_reopen_connection(inbuf,outbuf))
+ reopen_connection(inbuf,outbuf))
{
do_get(rname,lname,finfo1);
return;
@@ -1236,7 +1319,7 @@ static void do_get(char *rname,char *lname,file_info *finfo1)
set_message(outbuf,10,0,True);
CVAL(outbuf,smb_com) = SMBreadX;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
if (close_done)
{
@@ -1300,7 +1383,7 @@ static void do_get(char *rname,char *lname,file_info *finfo1)
set_message(outbuf,8,0,True);
CVAL(outbuf,smb_com) = SMBreadbraw;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,fnum);
SIVAL(outbuf,smb_vwv1,nread);
SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
@@ -1352,7 +1435,7 @@ static void do_get(char *rname,char *lname,file_info *finfo1)
set_message(outbuf,5,0,True);
CVAL(outbuf,smb_com) = SMBread;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,fnum);
SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
@@ -1394,7 +1477,17 @@ static void do_get(char *rname,char *lname,file_info *finfo1)
if (!close_done)
{
- cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
+ bzero(outbuf,smb_size);
+ set_message(outbuf,3,0,True);
+ CVAL(outbuf,smb_com) = SMBclose;
+ SSVAL(outbuf,smb_tid,cnum);
+ setup_pkt(outbuf);
+
+ SSVAL(outbuf,smb_vwv0,fnum);
+ SIVALS(outbuf,smb_vwv1,-1);
+
+ send_smb(Client,outbuf);
+ receive_smb(Client,inbuf,CLIENT_TIMEOUT);
if (!ignore_close_error && CVAL(inbuf,smb_rcls) != 0)
{
@@ -1414,7 +1507,7 @@ static void do_get(char *rname,char *lname,file_info *finfo1)
set_message(outbuf,8,strlen(rname)+4,True);
CVAL(outbuf,smb_com) = SMBsetatr;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,finfo.mode & ~(aARCH));
SIVALS(outbuf,smb_vwv1,0);
p = smb_buf(outbuf);
@@ -1649,7 +1742,7 @@ static BOOL do_mkdir(char *name)
CVAL(outbuf,smb_com) = SMBmkdir;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
p = smb_buf(outbuf);
@@ -1731,7 +1824,7 @@ static int smb_writeraw(char *outbuf,int fnum,int pos,char *buf,int n)
CVAL(outbuf,smb_com) = SMBwritebraw;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,fnum);
SSVAL(outbuf,smb_vwv1,n);
@@ -1773,7 +1866,7 @@ static int smb_writefile(char *outbuf,int fnum,int pos,char *buf,int n)
CVAL(outbuf,smb_com) = SMBwrite;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,fnum);
SSVAL(outbuf,smb_vwv1,n);
@@ -1830,7 +1923,7 @@ static void do_put(char *rname,char *lname,file_info *finfo)
CVAL(outbuf,smb_com) = SMBcreate;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,finfo->mode);
put_dos_date3(outbuf,smb_vwv1,finfo->mtime);
@@ -1906,7 +1999,7 @@ static void do_put(char *rname,char *lname,file_info *finfo)
set_message(outbuf,3,0,True);
CVAL(outbuf,smb_com) = SMBclose;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,fnum);
put_dos_date3(outbuf,smb_vwv1,close_time);
@@ -2131,10 +2224,10 @@ static void do_cancel(int job)
SSVAL(p,0,job);
p += 2;
- if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
- 6, 1000,
+ if (call_api(PTR_DIFF(p,param),0,
+ 6,1000,
&rprcnt,&rdrcnt,
- param,NULL, NULL,
+ param,NULL,
&rparam,&rdata))
{
int res = SVAL(rparam,0);
@@ -2180,6 +2273,43 @@ static void cmd_cancel(char *inbuf,char *outbuf )
}
+/****************************************************************************
+ get info on a file
+ ****************************************************************************/
+static void cmd_stat(char *inbuf,char *outbuf)
+{
+ fstring buf;
+ pstring param;
+ char *resp_data=NULL;
+ char *resp_param=NULL;
+ int resp_data_len = 0;
+ int resp_param_len=0;
+ char *p;
+ uint16 setup = TRANSACT2_QPATHINFO;
+
+ if (!next_token(NULL,buf,NULL)) {
+ printf("stat <file>\n");
+ return;
+ }
+
+ bzero(param,6);
+ SSVAL(param,0,4); /* level */
+ p = param+6;
+ strcpy(p,cur_dir);
+ strcat(p,buf);
+
+ send_trans_request(outbuf,SMBtrans2,NULL,FID_UNUSED,0,
+ NULL,param,&setup,
+ 0,6 + strlen(p)+1,1,
+ BUFFER_SIZE,2,0);
+
+ receive_trans_response(inbuf,SMBtrans2,
+ &resp_data_len,&resp_param_len,
+ &resp_data,&resp_param);
+
+ if (resp_data) free(resp_data); resp_data = NULL;
+ if (resp_param) free(resp_param); resp_param = NULL;
+}
/****************************************************************************
@@ -2231,7 +2361,7 @@ static void cmd_print(char *inbuf,char *outbuf )
CVAL(outbuf,smb_com) = SMBsplopen;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,0);
SSVAL(outbuf,smb_vwv1,printmode);
@@ -2287,7 +2417,7 @@ static void cmd_print(char *inbuf,char *outbuf )
CVAL(outbuf,smb_com) = SMBsplwr;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,fnum);
SSVAL(outbuf,smb_vwv1,n+3);
@@ -2312,7 +2442,7 @@ static void cmd_print(char *inbuf,char *outbuf )
set_message(outbuf,1,0,True);
CVAL(outbuf,smb_com) = SMBsplclose;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,fnum);
@@ -2345,7 +2475,7 @@ static void cmd_queue(char *inbuf,char *outbuf )
CVAL(outbuf,smb_com) = SMBsplretq;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,32); /* a max of 20 entries is to be shown */
SSVAL(outbuf,smb_vwv1,0); /* the index into the queue */
@@ -2430,10 +2560,10 @@ static void cmd_p_queue_4(char *inbuf,char *outbuf )
p = skip_string(p,1);
DEBUG(1,("Calling DosPrintJobEnum()...\n"));
- if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0,
- 10, 0, 4096,
+ if( call_api(PTR_DIFF(p,param), 0,
+ 10, 4096,
&rprcnt, &rdrcnt,
- param, NULL, NULL,
+ param, NULL,
&rparam, &rdata) )
{
int converter;
@@ -2495,7 +2625,7 @@ static void cmd_p_queue_4(char *inbuf,char *outbuf )
}
}
}
- else /* cli_call_api() failed */
+ else /* call_api() failed */
{
printf("Failed, error = %d\n", result_code);
}
@@ -2537,10 +2667,10 @@ static void cmd_qinfo(char *inbuf,char *outbuf )
p = skip_string(p,1);
DEBUG(1,("Calling DosPrintQueueGetInfo()...\n"));
- if( cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param), 0, 0,
- 10, 4096,
+ if( call_api(PTR_DIFF(p,param), 0,
+ 10, 4096,
&rprcnt, &rdrcnt,
- param, NULL, NULL,
+ param, NULL,
&rparam, &rdata) )
{
int converter;
@@ -2598,7 +2728,7 @@ static void cmd_qinfo(char *inbuf,char *outbuf )
}
}
- else /* cli_call_api() failed */
+ else /* call_api() failed */
{
printf("Failed, error = %d\n", result_code);
}
@@ -2639,7 +2769,7 @@ static void do_del(file_info *finfo)
CVAL(outbuf,smb_com) = SMBunlink;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,0);
@@ -2705,7 +2835,7 @@ static void cmd_rmdir(char *inbuf,char *outbuf )
CVAL(outbuf,smb_com) = SMBrmdir;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
p = smb_buf(outbuf);
@@ -2749,7 +2879,7 @@ static void cmd_rename(char *inbuf,char *outbuf )
CVAL(outbuf,smb_com) = SMBmv;
SSVAL(outbuf,smb_tid,cnum);
SSVAL(outbuf,smb_vwv0,aHIDDEN | aDIR | aSYSTEM);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
p = smb_buf(outbuf);
*p++ = 4;
@@ -2900,6 +3030,679 @@ static void cmd_lcd(void)
/****************************************************************************
+send a session request
+****************************************************************************/
+static BOOL send_session_request(char *inbuf,char *outbuf)
+{
+ fstring dest;
+ char *p;
+ int len = 4;
+ /* send a session request (RFC 8002) */
+
+ strcpy(dest,desthost);
+ p = strchr(dest,'.');
+ if (p) *p = 0;
+
+ /* put in the destination name */
+ p = outbuf+len;
+ name_mangle(dest,p,name_type); /* 0x20 is the SMB server NetBIOS type. */
+ len += name_len(p);
+
+ /* and my name */
+ p = outbuf+len;
+ name_mangle(myname,p,0);
+ len += name_len(p);
+
+ /* setup the packet length */
+ _smb_setlen(outbuf,len);
+ CVAL(outbuf,0) = 0x81;
+
+ send_smb(Client,outbuf);
+ DEBUG(5,("Sent session request\n"));
+
+ receive_smb(Client,inbuf,CLIENT_TIMEOUT);
+
+ if (CVAL(inbuf,0) == 0x84) /* C. Hoch 9/14/95 Start */
+ {
+ /* For information, here is the response structure.
+ * We do the byte-twiddling to for portability.
+ struct RetargetResponse{
+ unsigned char type;
+ unsigned char flags;
+ int16 length;
+ int32 ip_addr;
+ int16 port;
+ };
+ */
+ extern int Client;
+ int port = (CVAL(inbuf,8)<<8)+CVAL(inbuf,9);
+ /* SESSION RETARGET */
+ putip((char *)&dest_ip,inbuf+4);
+
+ close_sockets();
+ Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
+ if (Client == -1)
+ return False;
+
+ DEBUG(3,("Retargeted\n"));
+
+ set_socket_options(Client,user_socket_options);
+
+ /* Try again */
+ return send_session_request(inbuf,outbuf);
+ } /* C. Hoch 9/14/95 End */
+
+
+ if (CVAL(inbuf,0) != 0x82)
+ {
+ int ecode = CVAL(inbuf,4);
+ DEBUG(0,("Session request failed (%d,%d) with myname=%s destname=%s\n",
+ CVAL(inbuf,0),ecode,myname,desthost));
+ switch (ecode)
+ {
+ case 0x80:
+ DEBUG(0,("Not listening on called name\n"));
+ DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
+ DEBUG(0,("You may find the -I option useful for this\n"));
+ break;
+ case 0x81:
+ DEBUG(0,("Not listening for calling name\n"));
+ DEBUG(0,("Try to connect as another name (instead of %s)\n",myname));
+ DEBUG(0,("You may find the -n option useful for this\n"));
+ break;
+ case 0x82:
+ DEBUG(0,("Called name not present\n"));
+ DEBUG(0,("Try to connect to another name (instead of %s)\n",desthost));
+ DEBUG(0,("You may find the -I option useful for this\n"));
+ break;
+ case 0x83:
+ DEBUG(0,("Called name present, but insufficient resources\n"));
+ DEBUG(0,("Perhaps you should try again later?\n"));
+ break;
+ default:
+ DEBUG(0,("Unspecified error 0x%X\n",ecode));
+ DEBUG(0,("Your server software is being unfriendly\n"));
+ break;
+ }
+ return(False);
+ }
+ return(True);
+}
+
+static struct {
+ int prot;
+ char *name;
+} prots[] = {
+ {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
+ {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
+ {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
+ {PROTOCOL_LANMAN1,"LANMAN1.0"},
+ {PROTOCOL_LANMAN2,"LM1.2X002"},
+ {PROTOCOL_LANMAN2,"Samba"},
+ {PROTOCOL_NT1,"NT LM 0.12"},
+ {PROTOCOL_NT1,"NT LANMAN 1.0"},
+ {-1,NULL}
+};
+
+
+/****************************************************************************
+send a login command
+****************************************************************************/
+static BOOL send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
+{
+ BOOL was_null = (!inbuf && !outbuf);
+ int sesskey=0;
+ time_t servertime = 0;
+ extern int serverzone;
+ int sec_mode=0;
+ int crypt_len;
+ int max_vcs=0;
+ char *pass = NULL;
+ pstring dev;
+ char *p;
+ int numprots;
+ int tries=0;
+
+ if (was_null)
+ {
+ inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
+ outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
+ }
+
+#if AJT
+ if (strstr(service,"IPC$")) connect_as_ipc = True;
+#endif
+
+ strcpy(dev,"A:");
+ if (connect_as_printer)
+ strcpy(dev,"LPT1:");
+ if (connect_as_ipc)
+ strcpy(dev,"IPC");
+
+
+ if (start_session && !send_session_request(inbuf,outbuf))
+ {
+ if (was_null)
+ {
+ free(inbuf);
+ free(outbuf);
+ }
+ return(False);
+ }
+
+ bzero(outbuf,smb_size);
+
+ /* setup the protocol strings */
+ {
+ int plength;
+
+ for (plength=0,numprots=0;
+ prots[numprots].name && prots[numprots].prot<=max_protocol;
+ numprots++)
+ plength += strlen(prots[numprots].name)+2;
+
+ set_message(outbuf,0,plength,True);
+
+ p = smb_buf(outbuf);
+ for (numprots=0;
+ prots[numprots].name && prots[numprots].prot<=max_protocol;
+ numprots++)
+ {
+ *p++ = 2;
+ strcpy(p,prots[numprots].name);
+ p += strlen(p) + 1;
+ }
+ }
+
+ CVAL(outbuf,smb_com) = SMBnegprot;
+ setup_pkt(outbuf);
+
+ CVAL(smb_buf(outbuf),0) = 2;
+
+ send_smb(Client,outbuf);
+ receive_smb(Client,inbuf,CLIENT_TIMEOUT);
+
+ show_msg(inbuf);
+
+ if (CVAL(inbuf,smb_rcls) != 0 || ((int)SVAL(inbuf,smb_vwv0) >= numprots))
+ {
+ DEBUG(0,("SMBnegprot failed. myname=%s destname=%s - %s \n",
+ myname,desthost,smb_errstr(inbuf)));
+ if (was_null)
+ {
+ free(inbuf);
+ free(outbuf);
+ }
+ return(False);
+ }
+
+ Protocol = prots[SVAL(inbuf,smb_vwv0)].prot;
+
+
+ if (Protocol < PROTOCOL_NT1) {
+ sec_mode = SVAL(inbuf,smb_vwv1);
+ max_xmit = SVAL(inbuf,smb_vwv2);
+ sesskey = IVAL(inbuf,smb_vwv6);
+ serverzone = SVALS(inbuf,smb_vwv10)*60;
+ /* this time is converted to GMT by make_unix_date */
+ servertime = make_unix_date(inbuf+smb_vwv8);
+ if (Protocol >= PROTOCOL_COREPLUS) {
+ readbraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x1) != 0);
+ writebraw_supported = ((SVAL(inbuf,smb_vwv5) & 0x2) != 0);
+ }
+ crypt_len = smb_buflen(inbuf);
+ memcpy(cryptkey,smb_buf(inbuf),8);
+ DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
+ max_vcs = SVAL(inbuf,smb_vwv4);
+ DEBUG(3,("max vcs %d\n",max_vcs));
+ DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
+ } else {
+ /* NT protocol */
+ sec_mode = CVAL(inbuf,smb_vwv1);
+ max_xmit = IVAL(inbuf,smb_vwv3+1);
+ sesskey = IVAL(inbuf,smb_vwv7+1);
+ serverzone = SVALS(inbuf,smb_vwv15+1)*60;
+ /* this time arrives in real GMT */
+ servertime = interpret_long_date(inbuf+smb_vwv11+1);
+ crypt_len = CVAL(inbuf,smb_vwv16+1);
+ memcpy(cryptkey,smb_buf(inbuf),8);
+ if (IVAL(inbuf,smb_vwv9+1) & 1)
+ readbraw_supported = writebraw_supported = True;
+ DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
+ max_vcs = SVAL(inbuf,smb_vwv2+1);
+ DEBUG(3,("max vcs %d\n",max_vcs));
+ DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
+ DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
+ }
+
+ DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
+ DEBUG(3,("max xmt %d\n",max_xmit));
+ DEBUG(3,("Got %d byte crypt key\n",crypt_len));
+ DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
+
+ doencrypt = ((sec_mode & 2) != 0);
+
+ if (servertime) {
+ static BOOL done_time = False;
+ if (!done_time) {
+ DEBUG(1,("Server time is %sTimezone is UTC%+02.1f\n",
+ asctime(LocalTime(&servertime)),
+ -(double)(serverzone/3600.0)));
+ done_time = True;
+ }
+ }
+
+ get_pass:
+
+ if (got_pass)
+ pass = password;
+ else
+ pass = (char *)getpass("Password: ");
+
+ /* use a blank username for the 2nd try with a blank password */
+ if (tries++ && !*pass)
+ *username = 0;
+
+ if (Protocol >= PROTOCOL_LANMAN1 && use_setup)
+ {
+ fstring pword;
+ int passlen = strlen(pass)+1;
+ strcpy(pword,pass);
+
+#ifdef SMB_PASSWD
+ if (doencrypt && *pass) {
+ DEBUG(3,("Using encrypted passwords\n"));
+ passlen = 24;
+ SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
+ }
+#else
+ doencrypt = False;
+#endif
+
+ /* if in share level security then don't send a password now */
+ if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;}
+
+ /* send a session setup command */
+ bzero(outbuf,smb_size);
+
+ if (Protocol < PROTOCOL_NT1) {
+ set_message(outbuf,10,1 + strlen(username) + passlen,True);
+ CVAL(outbuf,smb_com) = SMBsesssetupX;
+ setup_pkt(outbuf);
+
+ CVAL(outbuf,smb_vwv0) = 0xFF;
+ SSVAL(outbuf,smb_vwv2,max_xmit);
+ SSVAL(outbuf,smb_vwv3,2);
+ SSVAL(outbuf,smb_vwv4,max_vcs-1);
+ SIVAL(outbuf,smb_vwv5,sesskey);
+ SSVAL(outbuf,smb_vwv7,passlen);
+ p = smb_buf(outbuf);
+ memcpy(p,pword,passlen);
+ p += passlen;
+ strcpy(p,username);
+ } else {
+ if (!doencrypt) passlen--;
+ /* for Win95 */
+ set_message(outbuf,13,0,True);
+ CVAL(outbuf,smb_com) = SMBsesssetupX;
+ setup_pkt(outbuf);
+
+ CVAL(outbuf,smb_vwv0) = 0xFF;
+ SSVAL(outbuf,smb_vwv2,BUFFER_SIZE);
+ SSVAL(outbuf,smb_vwv3,2);
+ SSVAL(outbuf,smb_vwv4,getpid());
+ SIVAL(outbuf,smb_vwv5,sesskey);
+ SSVAL(outbuf,smb_vwv7,passlen);
+ SSVAL(outbuf,smb_vwv8,0);
+ p = smb_buf(outbuf);
+ memcpy(p,pword,passlen); p += SVAL(outbuf,smb_vwv7);
+ strcpy(p,username);p = skip_string(p,1);
+ strcpy(p,workgroup);p = skip_string(p,1);
+ strcpy(p,"Unix");p = skip_string(p,1);
+ strcpy(p,"Samba");p = skip_string(p,1);
+ set_message(outbuf,13,PTR_DIFF(p,smb_buf(outbuf)),False);
+ }
+
+ send_smb(Client,outbuf);
+ receive_smb(Client,inbuf,CLIENT_TIMEOUT);
+
+ show_msg(inbuf);
+
+ if (CVAL(inbuf,smb_rcls) != 0)
+ {
+ if (! *pass &&
+ ((CVAL(inbuf,smb_rcls) == ERRDOS &&
+ SVAL(inbuf,smb_err) == ERRnoaccess) ||
+ (CVAL(inbuf,smb_rcls) == ERRSRV &&
+ SVAL(inbuf,smb_err) == ERRbadpw)))
+ {
+ got_pass = False;
+ DEBUG(3,("resending login\n"));
+ goto get_pass;
+ }
+
+ DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s %s\n",
+ username,myname,desthost,smb_errstr(inbuf)));
+ DEBUG(0,("You might find the -U, -W or -n options useful\n"));
+ DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
+ DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
+ if (was_null)
+ {
+ free(inbuf);
+ free(outbuf);
+ }
+ return(False);
+ }
+
+ if (Protocol >= PROTOCOL_NT1) {
+ char *domain,*os,*lanman;
+ p = smb_buf(inbuf);
+ os = p;
+ lanman = skip_string(os,1);
+ domain = skip_string(lanman,1);
+ if (*domain || *os || *lanman)
+ DEBUG(1,("Domain=[%s] OS=[%s] Server=[%s]\n",domain,os,lanman));
+ }
+
+ /* use the returned uid from now on */
+ if (SVAL(inbuf,smb_uid) != uid)
+ DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
+ SVAL(inbuf,smb_uid),uid));
+ uid = SVAL(inbuf,smb_uid);
+ }
+
+ if (SVAL(inbuf, smb_vwv2) & 1)
+ DEBUG(1,("connected as guest "));
+ if (sec_mode & 1)
+ DEBUG(1,("security=user\n"));
+ else
+ DEBUG(1,("security=share\n"));
+
+ /* now we've got a connection - send a tcon message */
+ bzero(outbuf,smb_size);
+
+ if (strncmp(service,"\\\\",2) != 0)
+ {
+ DEBUG(0,("\nWarning: Your service name doesn't start with \\\\. This is probably incorrect.\n"));
+ DEBUG(0,("Perhaps try replacing each \\ with \\\\ on the command line?\n\n"));
+ }
+
+
+ again2:
+
+ {
+ int passlen = strlen(pass)+1;
+ fstring pword;
+ strcpy(pword,pass);
+
+#ifdef SMB_PASSWD
+ if (doencrypt && *pass) {
+ passlen=24;
+ SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
+ }
+#endif
+
+ /* if in user level security then don't send a password now */
+ if ((sec_mode & 1)) {
+ strcpy(pword, ""); passlen=1;
+ }
+
+ if (Protocol <= PROTOCOL_COREPLUS) {
+ set_message(outbuf,0,6 + strlen(service) + passlen + strlen(dev),True);
+ CVAL(outbuf,smb_com) = SMBtcon;
+ setup_pkt(outbuf);
+
+ p = smb_buf(outbuf);
+ *p++ = 0x04;
+ strcpy(p, service);
+ p = skip_string(p,1);
+ *p++ = 0x04;
+ memcpy(p,pword,passlen);
+ p += passlen;
+ *p++ = 0x04;
+ strcpy(p, dev);
+ }
+ else {
+ set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
+ CVAL(outbuf,smb_com) = SMBtconX;
+ setup_pkt(outbuf);
+
+ SSVAL(outbuf,smb_vwv0,0xFF);
+ SSVAL(outbuf,smb_vwv3,passlen);
+
+ p = smb_buf(outbuf);
+ memcpy(p,pword,passlen);
+ p += passlen;
+ strcpy(p,service);
+ p = skip_string(p,1);
+ strcpy(p,dev);
+ }
+ }
+
+ send_smb(Client,outbuf);
+ receive_smb(Client,inbuf,CLIENT_TIMEOUT);
+
+ /* trying again with a blank password */
+ if (CVAL(inbuf,smb_rcls) != 0 &&
+ (int)strlen(pass) > 0 &&
+ !doencrypt &&
+ Protocol >= PROTOCOL_LANMAN1)
+ {
+ DEBUG(2,("first SMBtconX failed, trying again. %s\n",smb_errstr(inbuf)));
+ strcpy(pass,"");
+ goto again2;
+ }
+
+ if (CVAL(inbuf,smb_rcls) != 0)
+ {
+ DEBUG(0,("SMBtconX failed. %s\n",smb_errstr(inbuf)));
+ DEBUG(0,("Perhaps you are using the wrong sharename, username or password?\n"));
+ DEBUG(0,("Some servers insist that these be in uppercase\n"));
+ if (was_null)
+ {
+ free(inbuf);
+ free(outbuf);
+ }
+ return(False);
+ }
+
+
+ if (Protocol <= PROTOCOL_COREPLUS) {
+ max_xmit = SVAL(inbuf,smb_vwv0);
+
+ cnum = SVAL(inbuf,smb_vwv1);
+ }
+ else {
+ max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
+ if (max_xmit <= 0)
+ max_xmit = BUFFER_SIZE - 4;
+
+ cnum = SVAL(inbuf,smb_tid);
+ }
+
+ DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
+
+ if (was_null)
+ {
+ free(inbuf);
+ free(outbuf);
+ }
+
+ return True;
+}
+
+
+/****************************************************************************
+send a logout command
+****************************************************************************/
+static void send_logout(void )
+{
+ pstring inbuf,outbuf;
+
+ bzero(outbuf,smb_size);
+ set_message(outbuf,0,0,True);
+ CVAL(outbuf,smb_com) = SMBtdis;
+ SSVAL(outbuf,smb_tid,cnum);
+ setup_pkt(outbuf);
+
+ send_smb(Client,outbuf);
+ receive_smb(Client,inbuf,SHORT_TIMEOUT);
+
+ if (CVAL(inbuf,smb_rcls) != 0)
+ {
+ DEBUG(0,("SMBtdis failed %s\n",smb_errstr(inbuf)));
+ }
+
+
+#ifdef STATS
+ stats_report();
+#endif
+ exit(0);
+}
+
+
+
+/****************************************************************************
+call a remote api
+****************************************************************************/
+static BOOL call_api(int prcnt,int drcnt,
+ int mprcnt,int mdrcnt,
+ int *rprcnt,int *rdrcnt,
+ char *param,char *data,
+ char **rparam,char **rdata)
+{
+ static char *inbuf=NULL;
+ static char *outbuf=NULL;
+
+ if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
+ if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
+
+ send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0,
+ data,param,NULL,
+ drcnt,prcnt,0,
+ mdrcnt,mprcnt,0);
+
+ return (receive_trans_response(inbuf,SMBtrans,
+ rdrcnt,rprcnt,
+ rdata,rparam));
+}
+
+/****************************************************************************
+ send a SMB trans or trans2 request
+ ****************************************************************************/
+static BOOL send_trans_request(char *outbuf,int trans,
+ char *name,int fid,int flags,
+ char *data,char *param,uint16 *setup,
+ int ldata,int lparam,int lsetup,
+ int mdata,int mparam,int msetup)
+{
+ int i;
+ int this_ldata,this_lparam;
+ int tot_data=0,tot_param=0;
+ char *outdata,*outparam;
+ pstring inbuf;
+ char *p;
+
+ this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
+ this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
+
+ bzero(outbuf,smb_size);
+ set_message(outbuf,14+lsetup,0,True);
+ CVAL(outbuf,smb_com) = trans;
+ SSVAL(outbuf,smb_tid,cnum);
+ setup_pkt(outbuf);
+
+ outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
+ outdata = outparam+this_lparam;
+
+ /* primary request */
+ SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
+ SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
+ SSVAL(outbuf,smb_mprcnt,mparam); /* mprcnt */
+ SSVAL(outbuf,smb_mdrcnt,mdata); /* mdrcnt */
+ SCVAL(outbuf,smb_msrcnt,msetup); /* msrcnt */
+ SSVAL(outbuf,smb_flags,flags); /* flags */
+ SIVAL(outbuf,smb_timeout,0); /* timeout */
+ SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */
+ SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
+ SSVAL(outbuf,smb_dscnt,this_ldata); /* dscnt */
+ SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
+ SCVAL(outbuf,smb_suwcnt,lsetup); /* suwcnt */
+ for (i=0;i<lsetup;i++) /* setup[] */
+ SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
+ p = smb_buf(outbuf);
+ if (trans==SMBtrans)
+ strcpy(p,name); /* name[] */
+ else
+ {
+ *p++ = 0; /* put in a null smb_name */
+ *p++ = 'D'; *p++ = ' '; /* this was added because OS/2 does it */
+ }
+ if (this_lparam) /* param[] */
+ memcpy(outparam,param,this_lparam);
+ if (this_ldata) /* data[] */
+ memcpy(outdata,data,this_ldata);
+ set_message(outbuf,14+lsetup, /* wcnt, bcc */
+ PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
+
+ show_msg(outbuf);
+ send_smb(Client,outbuf);
+
+ if (this_ldata < ldata || this_lparam < lparam)
+ {
+ /* receive interim response */
+ if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
+ {
+ DEBUG(0,("%s request failed (%s)\n",
+ trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf)));
+ return(False);
+ }
+
+ tot_data = this_ldata;
+ tot_param = this_lparam;
+
+ while (tot_data < ldata || tot_param < lparam)
+ {
+ this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
+ this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
+
+ set_message(outbuf,trans==SMBtrans?8:9,0,True);
+ CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
+
+ outparam = smb_buf(outbuf);
+ outdata = outparam+this_lparam;
+
+ /* secondary request */
+ SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
+ SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
+ SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */
+ SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
+ SSVAL(outbuf,smb_spsdisp,tot_param); /* psdisp */
+ SSVAL(outbuf,smb_sdscnt,this_ldata); /* dscnt */
+ SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
+ SSVAL(outbuf,smb_sdsdisp,tot_data); /* dsdisp */
+ if (trans==SMBtrans2)
+ SSVAL(outbuf,smb_sfid,fid); /* fid */
+ if (this_lparam) /* param[] */
+ memcpy(outparam,param,this_lparam);
+ if (this_ldata) /* data[] */
+ memcpy(outdata,data,this_ldata);
+ set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
+ PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
+
+ show_msg(outbuf);
+ send_smb(Client,outbuf);
+
+ tot_data += this_ldata;
+ tot_param += this_lparam;
+ }
+ }
+
+ return(True);
+}
+
+
+/****************************************************************************
try and browse available connections on a host
****************************************************************************/
static BOOL browse_host(BOOL sort)
@@ -2933,10 +3736,10 @@ static BOOL browse_host(BOOL sort)
SSVAL(p,2,BUFFER_SIZE);
p += 4;
- if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
- 1024, BUFFER_SIZE,
+ if (call_api(PTR_DIFF(p,param),0,
+ 1024,BUFFER_SIZE,
&rprcnt,&rdrcnt,
- param,NULL, NULL,
+ param,NULL,
&rparam,&rdata))
{
int res = SVAL(rparam,0);
@@ -3025,10 +3828,10 @@ static void server_info()
SSVAL(p,2,1000);
p += 6;
- if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p,param),0, 0,
- 6, 1000,
+ if (call_api(PTR_DIFF(p,param),0,
+ 6,1000,
&rprcnt,&rdrcnt,
- param,NULL, NULL,
+ param,NULL,
&rparam,&rdata))
{
int res = SVAL(rparam,0);
@@ -3100,10 +3903,10 @@ static BOOL list_servers(char *wk_grp)
/* first ask for a list of servers in this workgroup */
SIVAL(svtype_p,0,SV_TYPE_ALL);
- if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
- 8, BUFFER_SIZE - SAFETY_MARGIN,
+ if (call_api(PTR_DIFF(p+4,param),0,
+ 8,BUFFER_SIZE - SAFETY_MARGIN,
&rprcnt,&rdrcnt,
- param,NULL, NULL,
+ param,NULL,
&rparam,&rdata))
{
int res = SVAL(rparam,0);
@@ -3139,10 +3942,10 @@ static BOOL list_servers(char *wk_grp)
/* now ask for a list of workgroups */
SIVAL(svtype_p,0,SV_TYPE_DOMAIN_ENUM);
- if (cli_call_api(PIPE_LANMAN, 0,PTR_DIFF(p+4,param),0, 0,
- 8, BUFFER_SIZE - SAFETY_MARGIN,
+ if (call_api(PTR_DIFF(p+4,param),0,
+ 8,BUFFER_SIZE - SAFETY_MARGIN,
&rprcnt,&rdrcnt,
- param,NULL, NULL,
+ param,NULL,
&rparam,&rdata))
{
int res = SVAL(rparam,0);
@@ -3215,9 +4018,10 @@ struct
{"queue",cmd_queue,"show the print queue"},
{"qinfo",cmd_qinfo,"show print queue information"},
{"cancel",cmd_cancel,"<jobid> cancel a print queue entry"},
- {"quit",cli_send_logout,"logoff the server"},
- {"q",cli_send_logout,"logoff the server"},
- {"exit",cli_send_logout,"logoff the server"},
+ {"stat",cmd_stat,"<file> get info on a file (experimental!)"},
+ {"quit",send_logout,"logoff the server"},
+ {"q",send_logout,"logoff the server"},
+ {"exit",send_logout,"logoff the server"},
{"newer",cmd_newer,"<file> only mget files newer than the specified local file"},
{"archive",cmd_archive,"<level>\n0=ignore archive bit\n1=only get archive files\n2=only get archive files and reset archive bit\n3=get all files and reset archive bit"},
{"tar",cmd_tar,"tar <c|x>[IXbgNa] current directory to/from <file name>" },
@@ -3291,6 +4095,87 @@ void cmd_help(void)
}
/****************************************************************************
+open the client sockets
+****************************************************************************/
+static BOOL open_sockets(int port )
+{
+ static int last_port;
+ char *host;
+ pstring service2;
+ extern int Client;
+#ifdef USENMB
+ BOOL failed = True;
+#endif
+
+ if (port == 0) port=last_port;
+ last_port=port;
+
+ strupper(service);
+
+ if (*desthost)
+ {
+ host = desthost;
+ }
+ else
+ {
+ strcpy(service2,service);
+ host = strtok(service2,"\\/");
+ if (!host) {
+ DEBUG(0,("Badly formed host name\n"));
+ return(False);
+ }
+ strcpy(desthost,host);
+ }
+
+ if (!(*myname)) {
+ get_myname(myname,NULL);
+ }
+ strupper(myname);
+
+ DEBUG(3,("Opening sockets\n"));
+
+ if (!have_ip)
+ {
+ struct hostent *hp;
+
+ if ((hp = Get_Hostbyname(host))) {
+ putip((char *)&dest_ip,(char *)hp->h_addr);
+ failed = False;
+ } else {
+#ifdef USENMB
+ /* Try and resolve the name with the netbios server */
+ int bcast;
+
+ if ((bcast = open_socket_in(SOCK_DGRAM, 0, 3,
+ interpret_addr(lp_socket_address()))) != -1) {
+ set_socket_options(bcast, "SO_BROADCAST");
+
+ if (name_query(bcast, host, name_type, True, True, *iface_bcast(dest_ip),
+ &dest_ip,0)) {
+ failed = False;
+ }
+ close (bcast);
+ }
+#endif
+ if (failed) {
+ DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
+ return False;
+ }
+ }
+ }
+
+ Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
+ if (Client == -1)
+ return False;
+
+ DEBUG(3,("Connected\n"));
+
+ set_socket_options(Client,user_socket_options);
+
+ return True;
+}
+
+/****************************************************************************
wait for keyboard activity, swallowing network packets
****************************************************************************/
#ifdef CLIX
@@ -3366,6 +4251,33 @@ static void wait_keyboard(char *buffer)
/****************************************************************************
+close and open the connection again
+****************************************************************************/
+BOOL reopen_connection(char *inbuf,char *outbuf)
+{
+ static int open_count=0;
+
+ open_count++;
+
+ if (open_count>5) return(False);
+
+ DEBUG(1,("Trying to re-open connection\n"));
+
+ set_message(outbuf,0,0,True);
+ SCVAL(outbuf,smb_com,SMBtdis);
+ SSVAL(outbuf,smb_tid,cnum);
+ setup_pkt(outbuf);
+
+ send_smb(Client,outbuf);
+ receive_smb(Client,inbuf,SHORT_TIMEOUT);
+
+ close_sockets();
+ if (!open_sockets(0)) return(False);
+
+ return(send_login(inbuf,outbuf,True,True));
+}
+
+/****************************************************************************
process commands from the client
****************************************************************************/
static BOOL process(char *base_directory)
@@ -3382,7 +4294,7 @@ static BOOL process(char *base_directory)
bzero(OutBuffer,smb_size);
- if (!cli_send_login(InBuffer,OutBuffer,True,True))
+ if (!send_login(InBuffer,OutBuffer,True,True))
return(False);
if (*base_directory) do_cd(base_directory);
@@ -3476,10 +4388,11 @@ static BOOL process(char *base_directory)
DEBUG(0,("%s: command not found\n",CNV_LANG(tok)));
}
- cli_send_logout();
+ send_logout();
return(True);
}
+
/****************************************************************************
usage on the program
****************************************************************************/
@@ -3488,8 +4401,12 @@ static void usage(char *pname)
DEBUG(0,("Usage: %s service <password> [-p port] [-d debuglevel] [-l log] ",
pname));
+#ifdef KANJI
+ DEBUG(0,("[-t termcode] "));
+#endif /* KANJI */
+
DEBUG(0,("\nVersion %s\n",VERSION));
- DEBUG(0,("\t-p port connect to the specified port\n"));
+ DEBUG(0,("\t-p port listen on the specified port\n"));
DEBUG(0,("\t-d debuglevel set the debuglevel\n"));
DEBUG(0,("\t-l log basename. Basename for log/debug files\n"));
DEBUG(0,("\t-n netbios name. Use this name as my netbios name\n"));
@@ -3503,7 +4420,9 @@ static void usage(char *pname)
DEBUG(0,("\t-U username set the network username\n"));
DEBUG(0,("\t-W workgroup set the workgroup name\n"));
DEBUG(0,("\t-c command string execute semicolon separated commands\n"));
+#ifdef KANJI
DEBUG(0,("\t-t terminal code terminal i/o code {sjis|euc|jis7|jis8|junet|hex}\n"));
+#endif /* KANJI */
DEBUG(0,("\t-T<c|x>IXgbNa command line tar\n"));
DEBUG(0,("\t-D directory start from directory\n"));
DEBUG(0,("\n"));
@@ -3523,17 +4442,8 @@ static void usage(char *pname)
extern int optind;
pstring query_host;
BOOL message = False;
- BOOL nt_domain_logon = False;
extern char tar_type;
static pstring servicesf = CONFIGFILE;
- pstring term_code;
- char *p;
-
-#ifdef KANJI
- strcpy(term_code, KANJI);
-#else /* KANJI */
- *term_code = 0;
-#endif /* KANJI */
*query_host = 0;
*base_directory = 0;
@@ -3553,27 +4463,10 @@ static void usage(char *pname)
umask(myumask);
if (getenv("USER"))
- {
- strcpy(username,getenv("USER"));
-
- /* modification to support userid%passwd syntax in the USER var
- 25.Aug.97, jdblair@uab.edu */
-
- if ((p=strchr(username,'%')))
{
- *p = 0;
- strcpy(password,p+1);
- got_pass = True;
- memset(strchr(getenv("USER"),'%')+1,'X',strlen(password));
+ strcpy(username,getenv("USER"));
+ strupper(username);
}
- strupper(username);
- }
-
- /* modification to support PASSWD environmental var
- 25.Aug.97, jdblair@uab.edu */
-
- if (getenv("PASSWD"))
- strcpy(password,getenv("PASSWD"));
if (*username == 0 && getenv("LOGNAME"))
{
@@ -3622,8 +4515,11 @@ static void usage(char *pname)
}
}
+#ifdef KANJI
+ setup_term_code (KANJI);
+#endif
while ((opt =
- getopt(argc, argv,"s:B:O:M:S:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
+ getopt(argc, argv,"s:B:O:M:i:Nn:d:Pp:l:hI:EB:U:L:t:m:W:T:D:c:")) != EOF)
switch (opt)
{
case 'm':
@@ -3632,11 +4528,6 @@ static void usage(char *pname)
case 'O':
strcpy(user_socket_options,optarg);
break;
- case 'S':
- strcpy(desthost,optarg);
- strupper(desthost);
- nt_domain_logon = True;
- break;
case 'M':
name_type = 0x03; /* messages are sent to NetBIOS name type 0x3 */
strcpy(desthost,optarg);
@@ -3664,12 +4555,12 @@ static void usage(char *pname)
break;
case 'U':
{
- char *lp;
+ char *p;
strcpy(username,optarg);
- if ((lp=strchr(username,'%')))
+ if ((p=strchr(username,'%')))
{
- *lp = 0;
- strcpy(password,lp+1);
+ *p = 0;
+ strcpy(password,p+1);
got_pass = True;
memset(strchr(optarg,'%')+1,'X',strlen(password));
}
@@ -3722,7 +4613,13 @@ static void usage(char *pname)
strcpy(servicesf, optarg);
break;
case 't':
- strcpy(term_code, optarg);
+#ifdef KANJI
+ if (!setup_term_code (optarg)) {
+ DEBUG(0, ("%s: unknown terminal code name\n", optarg));
+ usage (pname);
+ exit (1);
+ }
+#endif
break;
default:
usage(pname);
@@ -3747,18 +4644,6 @@ static void usage(char *pname)
fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
}
- codepage_initialise(lp_client_code_page());
-
- if(lp_client_code_page() == KANJI_CODEPAGE)
- {
- if (!setup_term_code (term_code))
- {
- DEBUG(0, ("%s: unknown terminal code name\n", optarg));
- usage (pname);
- exit (1);
- }
- }
-
if (*workgroup == 0)
strcpy(workgroup,lp_workgroup());
@@ -3769,7 +4654,7 @@ static void usage(char *pname)
if (tar_type) {
recurse=True;
- if (cli_open_sockets(port)) {
+ if (open_sockets(port)) {
char *InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
char *OutBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
int ret;
@@ -3778,32 +4663,32 @@ static void usage(char *pname)
return(1);
bzero(OutBuffer,smb_size);
- if (!cli_send_login(InBuffer,OutBuffer,True,True))
+ if (!send_login(InBuffer,OutBuffer,True,True))
return(False);
if (*base_directory) do_cd(base_directory);
ret=process_tar(InBuffer, OutBuffer);
- cli_send_logout();
+ send_logout();
close_sockets();
return(ret);
} else
return(1);
}
- if (*query_host && !nt_domain_logon)
+ if (*query_host)
{
int ret = 0;
sprintf(service,"\\\\%s\\IPC$",query_host);
strupper(service);
connect_as_ipc = True;
- if (cli_open_sockets(port))
+ if (open_sockets(port))
{
#if 0
*username = 0;
#endif
- if (!cli_send_login(NULL,NULL,True,True))
+ if (!send_login(NULL,NULL,True,True))
return(1);
server_info();
@@ -3816,7 +4701,7 @@ static void usage(char *pname)
list_servers(workgroup);
}
- cli_send_logout();
+ send_logout();
close_sockets();
}
@@ -3826,11 +4711,11 @@ static void usage(char *pname)
if (message)
{
int ret = 0;
- if (cli_open_sockets(port))
+ if (open_sockets(port))
{
pstring inbuf,outbuf;
bzero(outbuf,smb_size);
- if (!cli_send_session_request(inbuf,outbuf))
+ if (!send_session_request(inbuf,outbuf))
return(1);
send_message(inbuf,outbuf);
@@ -3841,32 +4726,7 @@ static void usage(char *pname)
return(ret);
}
-#ifdef NTDOMAIN
-
- if (nt_domain_logon)
- {
- int ret = 0;
- sprintf(service,"\\\\%s\\IPC$",query_host);
- strupper(service);
- connect_as_ipc = True;
-
- DEBUG(5,("NT Domain Logon. Service: %s\n", service));
-
- if (cli_open_sockets(port))
- {
- if (!cli_send_login(NULL,NULL,True,True)) return(1);
-
- do_nt_login(desthost, myhostname, Client, cnum);
-
- cli_send_logout();
- close_sockets();
- }
-
- return(ret);
- }
-#endif
-
- if (cli_open_sockets(port))
+ if (open_sockets(port))
{
if (!process(base_directory))
{
@@ -3882,3 +4742,157 @@ static void usage(char *pname)
}
+/* error code stuff - put together by Merik Karman
+ merik@blackadder.dsh.oz.au */
+
+typedef struct
+{
+ char *name;
+ int code;
+ char *message;
+} err_code_struct;
+
+/* Dos Error Messages */
+err_code_struct dos_msgs[] = {
+ {"ERRbadfunc",1,"Invalid function."},
+ {"ERRbadfile",2,"File not found."},
+ {"ERRbadpath",3,"Directory invalid."},
+ {"ERRnofids",4,"No file descriptors available"},
+ {"ERRnoaccess",5,"Access denied."},
+ {"ERRbadfid",6,"Invalid file handle."},
+ {"ERRbadmcb",7,"Memory control blocks destroyed."},
+ {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
+ {"ERRbadmem",9,"Invalid memory block address."},
+ {"ERRbadenv",10,"Invalid environment."},
+ {"ERRbadformat",11,"Invalid format."},
+ {"ERRbadaccess",12,"Invalid open mode."},
+ {"ERRbaddata",13,"Invalid data."},
+ {"ERR",14,"reserved."},
+ {"ERRbaddrive",15,"Invalid drive specified."},
+ {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
+ {"ERRdiffdevice",17,"Not same device."},
+ {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
+ {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
+ {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
+ {"ERRnosuchshare", 67, "You specified an invalid share name"},
+ {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
+ {"ERRbadpipe",230,"Pipe invalid."},
+ {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
+ {"ERRpipeclosing",232,"Pipe close in progress."},
+ {"ERRnotconnected",233,"No process on other end of pipe."},
+ {"ERRmoredata",234,"There is more data to be returned."},
+ {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
+ {NULL,-1,NULL}};
+
+/* Server Error Messages */
+err_code_struct server_msgs[] = {
+ {"ERRerror",1,"Non-specific error code."},
+ {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
+ {"ERRbadtype",3,"reserved."},
+ {"ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."},
+ {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
+ {"ERRinvnetname",6,"Invalid network name in tree connect."},
+ {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
+ {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
+ {"ERRqtoobig",50,"Print queue full -- no space."},
+ {"ERRqeof",51,"EOF on print queue dump."},
+ {"ERRinvpfid",52,"Invalid print file FID."},
+ {"ERRsmbcmd",64,"The server did not recognize the command received."},
+ {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
+ {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
+ {"ERRreserved",68,"reserved."},
+ {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
+ {"ERRreserved",70,"reserved."},
+ {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
+ {"ERRpaused",81,"Server is paused."},
+ {"ERRmsgoff",82,"Not receiving messages."},
+ {"ERRnoroom",83,"No room to buffer message."},
+ {"ERRrmuns",87,"Too many remote user names."},
+ {"ERRtimeout",88,"Operation timed out."},
+ {"ERRnoresource",89,"No resources currently available for request."},
+ {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
+ {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
+ {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
+ {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
+ {"ERRcontmpx",252,"Continue in MPX mode."},
+ {"ERRreserved",253,"reserved."},
+ {"ERRreserved",254,"reserved."},
+ {"ERRnosupport",0xFFFF,"Function not supported."},
+ {NULL,-1,NULL}};
+
+/* Hard Error Messages */
+err_code_struct hard_msgs[] = {
+ {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
+ {"ERRbadunit",20,"Unknown unit."},
+ {"ERRnotready",21,"Drive not ready."},
+ {"ERRbadcmd",22,"Unknown command."},
+ {"ERRdata",23,"Data error (CRC)."},
+ {"ERRbadreq",24,"Bad request structure length."},
+ {"ERRseek",25 ,"Seek error."},
+ {"ERRbadmedia",26,"Unknown media type."},
+ {"ERRbadsector",27,"Sector not found."},
+ {"ERRnopaper",28,"Printer out of paper."},
+ {"ERRwrite",29,"Write fault."},
+ {"ERRread",30,"Read fault."},
+ {"ERRgeneral",31,"General failure."},
+ {"ERRbadshare",32,"An open conflicts with an existing open."},
+ {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
+ {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
+ {"ERRFCBUnavail",35,"No FCBs are available to process request."},
+ {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
+ {NULL,-1,NULL}};
+
+
+struct
+{
+ int code;
+ char *class;
+ err_code_struct *err_msgs;
+} err_classes[] = {
+ {0,"SUCCESS",NULL},
+ {0x01,"ERRDOS",dos_msgs},
+ {0x02,"ERRSRV",server_msgs},
+ {0x03,"ERRHRD",hard_msgs},
+ {0x04,"ERRXOS",NULL},
+ {0xE1,"ERRRMX1",NULL},
+ {0xE2,"ERRRMX2",NULL},
+ {0xE3,"ERRRMX3",NULL},
+ {0xFF,"ERRCMD",NULL},
+ {-1,NULL,NULL}};
+
+
+/****************************************************************************
+return a SMB error string from a SMB buffer
+****************************************************************************/
+char *smb_errstr(char *inbuf)
+{
+ static pstring ret;
+ int class = CVAL(inbuf,smb_rcls);
+ int num = SVAL(inbuf,smb_err);
+ int i,j;
+
+ for (i=0;err_classes[i].class;i++)
+ if (err_classes[i].code == class)
+ {
+ if (err_classes[i].err_msgs)
+ {
+ err_code_struct *err = err_classes[i].err_msgs;
+ for (j=0;err[j].name;j++)
+ if (num == err[j].code)
+ {
+ if (DEBUGLEVEL > 0)
+ sprintf(ret,"%s - %s (%s)",err_classes[i].class,
+ err[j].name,err[j].message);
+ else
+ sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
+ return ret;
+ }
+ }
+
+ sprintf(ret,"%s - %d",err_classes[i].class,num);
+ return ret;
+ }
+
+ sprintf(ret,"Error: Unknown error (%d,%d)",class,num);
+ return(ret);
+}
diff --git a/source/client/clientutil.c b/source/client/clientutil.c
index ca908457389..cb0a731480c 100644
--- a/source/client/clientutil.c
+++ b/source/client/clientutil.c
@@ -33,7 +33,6 @@ pstring service="";
pstring desthost="";
extern pstring myname;
pstring password = "";
-pstring smb_login_passwd = "";
pstring username="";
pstring workgroup=WORKGROUP;
BOOL got_pass = False;
@@ -68,7 +67,7 @@ int max_xmit = BUFFER_SIZE;
BOOL have_ip = False;
-extern struct in_addr dest_ip;
+struct in_addr dest_ip;
extern int Protocol;
@@ -78,53 +77,26 @@ extern int Client;
/****************************************************************************
setup basics in a outgoing packet
****************************************************************************/
-void cli_setup_pkt(char *outbuf)
+static void cli_setup_pkt(char *outbuf)
{
SSVAL(outbuf,smb_pid,pid);
SSVAL(outbuf,smb_uid,uid);
SSVAL(outbuf,smb_mid,mid);
- if (Protocol > PROTOCOL_COREPLUS)
+ if (Protocol > PROTOCOL_CORE)
{
SCVAL(outbuf,smb_flg,0x8);
SSVAL(outbuf,smb_flg2,0x1);
}
}
-/****************************************************************************
-call a remote api
-****************************************************************************/
-BOOL cli_call_api(char *pipe_name, int pipe_name_len,
- int prcnt,int drcnt, int srcnt,
- int mprcnt,int mdrcnt,
- int *rprcnt,int *rdrcnt,
- char *param,char *data, uint16 *setup,
- char **rparam,char **rdata)
-{
- static char *inbuf=NULL;
- static char *outbuf=NULL;
-
- if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
- if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
-
- if (pipe_name_len == 0) pipe_name_len = strlen(pipe_name);
-
- cli_send_trans_request(outbuf,SMBtrans,pipe_name, pipe_name_len, 0,0,
- data, param, setup,
- drcnt, prcnt, srcnt,
- mdrcnt, mprcnt, 0);
-
- return (cli_receive_trans_response(inbuf,SMBtrans,
- rdrcnt,rprcnt,
- rdata,rparam));
-}
/****************************************************************************
receive a SMB trans or trans2 response allocating the necessary memory
****************************************************************************/
-BOOL cli_receive_trans_response(char *inbuf,int trans,
- int *data_len,int *param_len,
- char **data,char **param)
+static BOOL cli_receive_trans_response(char *inbuf,int trans,int *data_len,
+ int *param_len, char **data,
+ char **param)
{
int total_data=0;
int total_param=0;
@@ -192,140 +164,24 @@ BOOL cli_receive_trans_response(char *inbuf,int trans,
return(True);
}
-
-
-/****************************************************************************
- send a SMB trans or trans2 request
- ****************************************************************************/
-BOOL cli_send_trans_request(char *outbuf,int trans,
- char *name,int namelen, int fid,int flags,
- char *data,char *param,uint16 *setup,
- int ldata,int lparam,int lsetup,
- int mdata,int mparam,int msetup)
-{
- int i;
- int this_ldata,this_lparam;
- int tot_data=0,tot_param=0;
- char *outdata,*outparam;
- pstring inbuf;
- char *p;
-
- this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
- this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
-
- bzero(outbuf,smb_size);
- set_message(outbuf,14+lsetup,0,True);
- CVAL(outbuf,smb_com) = trans;
- SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
-
- outparam = smb_buf(outbuf)+(trans==SMBtrans ? namelen+1 : 3);
- outdata = outparam+this_lparam;
-
- /* primary request */
- SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
- SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
- SSVAL(outbuf,smb_mprcnt,mparam); /* mprcnt */
- SSVAL(outbuf,smb_mdrcnt,mdata); /* mdrcnt */
- SCVAL(outbuf,smb_msrcnt,msetup); /* msrcnt */
- SSVAL(outbuf,smb_flags,flags); /* flags */
- SIVAL(outbuf,smb_timeout,0); /* timeout */
- SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */
- SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
- SSVAL(outbuf,smb_dscnt,this_ldata); /* dscnt */
- SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
- SCVAL(outbuf,smb_suwcnt,lsetup); /* suwcnt */
- for (i=0;i<lsetup;i++) /* setup[] */
- SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
- p = smb_buf(outbuf);
- if (trans==SMBtrans)
- memcpy(p,name, namelen+1); /* name[] */
- else
- {
- *p++ = 0; /* put in a null smb_name */
- *p++ = 'D'; *p++ = ' '; /* this was added because OS/2 does it */
- }
- if (this_lparam) /* param[] */
- memcpy(outparam,param,this_lparam);
- if (this_ldata) /* data[] */
- memcpy(outdata,data,this_ldata);
- set_message(outbuf,14+lsetup, /* wcnt, bcc */
- PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
-
- show_msg(outbuf);
- send_smb(Client,outbuf);
-
- if (this_ldata < ldata || this_lparam < lparam)
- {
- /* receive interim response */
- if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
- {
- DEBUG(0,("%s request failed (%s)\n",
- trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf)));
- return(False);
- }
-
- tot_data = this_ldata;
- tot_param = this_lparam;
-
- while (tot_data < ldata || tot_param < lparam)
- {
- this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
- this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
-
- set_message(outbuf,trans==SMBtrans?8:9,0,True);
- CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
-
- outparam = smb_buf(outbuf);
- outdata = outparam+this_lparam;
-
- /* secondary request */
- SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
- SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
- SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */
- SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
- SSVAL(outbuf,smb_spsdisp,tot_param); /* psdisp */
- SSVAL(outbuf,smb_sdscnt,this_ldata); /* dscnt */
- SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
- SSVAL(outbuf,smb_sdsdisp,tot_data); /* dsdisp */
- if (trans==SMBtrans2)
- SSVAL(outbuf,smb_sfid,fid); /* fid */
- if (this_lparam) /* param[] */
- memcpy(outparam,param,this_lparam);
- if (this_ldata) /* data[] */
- memcpy(outdata,data,this_ldata);
- set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
- PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
-
- show_msg(outbuf);
- send_smb(Client,outbuf);
-
- tot_data += this_ldata;
- tot_param += this_lparam;
- }
- }
-
- return(True);
-}
-
-
/****************************************************************************
send a session request
****************************************************************************/
-BOOL cli_send_session_request(char *inbuf,char *outbuf)
+static BOOL cli_send_session_request(char *inbuf, char *outbuf)
{
fstring dest;
char *p;
int len = 4;
/* send a session request (RFC 8002) */
- strcpy(dest,desthost);
+ fstrcpy(dest,desthost);
+
p = strchr(dest,'.');
if (p) *p = 0;
/* put in the destination name */
p = outbuf+len;
- name_mangle(dest,p,name_type); /* 0x20 is the SMB server NetBIOS type. */
+ name_mangle(dest,p,name_type);
len += name_len(p);
/* and my name */
@@ -360,11 +216,11 @@ BOOL cli_send_session_request(char *inbuf,char *outbuf)
putip((char *)&dest_ip,inbuf+4);
close_sockets();
- Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
+ Client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT);
if (Client == -1)
return False;
- DEBUG(3,("Retargeted\n"));
+ DEBUG(5,("Retargeted\n"));
set_socket_options(Client,user_socket_options);
@@ -409,26 +265,28 @@ BOOL cli_send_session_request(char *inbuf,char *outbuf)
return(True);
}
-static struct {
- int prot;
- char *name;
-} prots[] = {
- {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
- {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
- {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
- {PROTOCOL_LANMAN1,"LANMAN1.0"},
- {PROTOCOL_LANMAN2,"LM1.2X002"},
- {PROTOCOL_LANMAN2,"Samba"},
- {PROTOCOL_NT1,"NT LM 0.12"},
- {PROTOCOL_NT1,"NT LANMAN 1.0"},
- {-1,NULL}
-};
+static struct {
+ int prot;
+ char *name;
+ }
+prots[] =
+ {
+ {PROTOCOL_CORE,"PC NETWORK PROGRAM 1.0"},
+ {PROTOCOL_COREPLUS,"MICROSOFT NETWORKS 1.03"},
+ {PROTOCOL_LANMAN1,"MICROSOFT NETWORKS 3.0"},
+ {PROTOCOL_LANMAN1,"LANMAN1.0"},
+ {PROTOCOL_LANMAN2,"LM1.2X002"},
+ {PROTOCOL_LANMAN2,"Samba"},
+ {PROTOCOL_NT1,"NT LM 0.12"},
+ {PROTOCOL_NT1,"NT LANMAN 1.0"},
+ {-1,NULL}
+ };
/****************************************************************************
-send a login command.
+send a login command
****************************************************************************/
-BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
+BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setup)
{
BOOL was_null = (!inbuf && !outbuf);
int sesskey=0;
@@ -441,7 +299,6 @@ BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
pstring dev;
char *p;
int numprots;
- int tries=0;
if (was_null)
{
@@ -449,15 +306,11 @@ BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
}
-#if AJT
- if (strstr(service,"IPC$")) connect_as_ipc = True;
-#endif
-
- strcpy(dev,"A:");
+ pstrcpy(dev,"A:");
if (connect_as_printer)
- strcpy(dev,"LPT1:");
+ pstrcpy(dev,"LPT1:");
if (connect_as_ipc)
- strcpy(dev,"IPC");
+ pstrcpy(dev,"IPC");
if (start_session && !cli_send_session_request(inbuf,outbuf))
@@ -519,9 +372,7 @@ BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
Protocol = prots[SVAL(inbuf,smb_vwv0)].prot;
- if (Protocol < PROTOCOL_LANMAN1) {
- /* no extra params */
- } else if (Protocol < PROTOCOL_NT1) {
+ if (Protocol < PROTOCOL_NT1) {
sec_mode = SVAL(inbuf,smb_vwv1);
max_xmit = SVAL(inbuf,smb_vwv2);
sesskey = IVAL(inbuf,smb_vwv6);
@@ -534,10 +385,10 @@ BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
}
crypt_len = smb_buflen(inbuf);
memcpy(cryptkey,smb_buf(inbuf),8);
- DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
+ DEBUG(5,("max mux %d\n",SVAL(inbuf,smb_vwv3)));
max_vcs = SVAL(inbuf,smb_vwv4);
- DEBUG(3,("max vcs %d\n",max_vcs));
- DEBUG(3,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
+ DEBUG(5,("max vcs %d\n",max_vcs));
+ DEBUG(5,("max blk %d\n",SVAL(inbuf,smb_vwv5)));
} else {
/* NT protocol */
sec_mode = CVAL(inbuf,smb_vwv1);
@@ -550,17 +401,17 @@ BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
memcpy(cryptkey,smb_buf(inbuf),8);
if (IVAL(inbuf,smb_vwv9+1) & 1)
readbraw_supported = writebraw_supported = True;
- DEBUG(3,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
+ DEBUG(5,("max mux %d\n",SVAL(inbuf,smb_vwv1+1)));
max_vcs = SVAL(inbuf,smb_vwv2+1);
- DEBUG(3,("max vcs %d\n",max_vcs));
- DEBUG(3,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
- DEBUG(3,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
+ DEBUG(5,("max vcs %d\n",max_vcs));
+ DEBUG(5,("max raw %d\n",IVAL(inbuf,smb_vwv5+1)));
+ DEBUG(5,("capabilities 0x%x\n",IVAL(inbuf,smb_vwv9+1)));
}
- DEBUG(3,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
- DEBUG(3,("max xmt %d\n",max_xmit));
- DEBUG(3,("Got %d byte crypt key\n",crypt_len));
- DEBUG(3,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
+ DEBUG(5,("Sec mode %d\n",SVAL(inbuf,smb_vwv1)));
+ DEBUG(5,("max xmt %d\n",max_xmit));
+ DEBUG(5,("Got %d byte crypt key\n",crypt_len));
+ DEBUG(5,("Chose protocol [%s]\n",prots[SVAL(inbuf,smb_vwv0)].name));
doencrypt = ((sec_mode & 2) != 0);
@@ -581,26 +432,30 @@ BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
else
pass = (char *)getpass("Password: ");
- pstrcpy(smb_login_passwd, pass);
-
- /* use a blank username for the 2nd try with a blank password */
- if (tries++ && !*pass)
- *username = 0;
+ if(pass == NULL)
+ {
+ DEBUG(0, ("cli_send_login : no password available - logon failed.\n"));
+ return False;
+ }
if (Protocol >= PROTOCOL_LANMAN1 && use_setup)
{
fstring pword;
int passlen = strlen(pass)+1;
- strcpy(pword,pass);
+ fstrcpy(pword,pass);
+#ifdef SMB_PASSWD
if (doencrypt && *pass) {
- DEBUG(3,("Using encrypted passwords\n"));
+ DEBUG(5,("Using encrypted passwords\n"));
passlen = 24;
SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
}
+#else
+ doencrypt = False;
+#endif
/* if in share level security then don't send a password now */
- if (!(sec_mode & 1)) {strcpy(pword, "");passlen=1;}
+ if (!(sec_mode & 1)) {fstrcpy(pword, "");passlen=1;}
/* send a session setup command */
bzero(outbuf,smb_size);
@@ -657,13 +512,13 @@ BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
SVAL(inbuf,smb_err) == ERRbadpw)))
{
got_pass = False;
- DEBUG(3,("resending login\n"));
+ DEBUG(5,("resending login\n"));
goto get_pass;
}
DEBUG(0,("Session setup failed for username=%s myname=%s destname=%s %s\n",
username,myname,desthost,smb_errstr(inbuf)));
- DEBUG(0,("You might find the -U, -W or -n options useful\n"));
+ DEBUG(0,("You might find the -U or -n options useful\n"));
DEBUG(0,("Sometimes you have to use `-n USERNAME' (particularly with OS/2)\n"));
DEBUG(0,("Some servers also insist on uppercase-only passwords\n"));
if (was_null)
@@ -686,19 +541,11 @@ BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
/* use the returned uid from now on */
if (SVAL(inbuf,smb_uid) != uid)
- DEBUG(3,("Server gave us a UID of %d. We gave %d\n",
+ DEBUG(5,("Server gave us a UID of %d. We gave %d\n",
SVAL(inbuf,smb_uid),uid));
uid = SVAL(inbuf,smb_uid);
}
- if (sec_mode & 1) {
- if (SVAL(inbuf, smb_vwv2) & 1)
- DEBUG(1,("connected as guest "));
- DEBUG(1,("security=user\n"));
- } else {
- DEBUG(1,("security=share\n"));
- }
-
/* now we've got a connection - send a tcon message */
bzero(outbuf,smb_size);
@@ -714,48 +561,33 @@ BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
{
int passlen = strlen(pass)+1;
fstring pword;
- strcpy(pword,pass);
+ fstrcpy(pword,pass);
+#ifdef SMB_PASSWD
if (doencrypt && *pass) {
passlen=24;
SMBencrypt((uchar *)pass,(uchar *)cryptkey,(uchar *)pword);
}
+#endif
/* if in user level security then don't send a password now */
if ((sec_mode & 1)) {
- strcpy(pword, ""); passlen=1;
+ fstrcpy(pword, ""); passlen=1;
}
- if (Protocol <= PROTOCOL_COREPLUS) {
- set_message(outbuf,0,6 + strlen(service) + passlen + strlen(dev),True);
- CVAL(outbuf,smb_com) = SMBtcon;
- cli_setup_pkt(outbuf);
-
- p = smb_buf(outbuf);
- *p++ = 0x04;
- strcpy(p, service);
- p = skip_string(p,1);
- *p++ = 0x04;
- memcpy(p,pword,passlen);
- p += passlen;
- *p++ = 0x04;
- strcpy(p, dev);
- }
- else {
- set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
- CVAL(outbuf,smb_com) = SMBtconX;
- cli_setup_pkt(outbuf);
-
- SSVAL(outbuf,smb_vwv0,0xFF);
- SSVAL(outbuf,smb_vwv3,passlen);
-
- p = smb_buf(outbuf);
- memcpy(p,pword,passlen);
- p += passlen;
- strcpy(p,service);
- p = skip_string(p,1);
- strcpy(p,dev);
- }
+ set_message(outbuf,4,2 + strlen(service) + passlen + strlen(dev),True);
+ CVAL(outbuf,smb_com) = SMBtconX;
+ cli_setup_pkt(outbuf);
+
+ SSVAL(outbuf,smb_vwv0,0xFF);
+ SSVAL(outbuf,smb_vwv3,passlen);
+
+ p = smb_buf(outbuf);
+ memcpy(p,pword,passlen);
+ p += passlen;
+ strcpy(p,service);
+ p = skip_string(p,1);
+ strcpy(p,dev);
}
send_smb(Client,outbuf);
@@ -786,27 +618,19 @@ BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
}
- if (Protocol <= PROTOCOL_COREPLUS) {
- max_xmit = SVAL(inbuf,smb_vwv0);
+ max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
+ if (max_xmit <= 0)
+ max_xmit = BUFFER_SIZE - 4;
- cnum = SVAL(inbuf,smb_vwv1);
- }
- else {
- max_xmit = MIN(max_xmit,BUFFER_SIZE-4);
- if (max_xmit <= 0)
- max_xmit = BUFFER_SIZE - 4;
+ cnum = SVAL(inbuf,smb_tid);
- cnum = SVAL(inbuf,smb_tid);
- }
-
- DEBUG(3,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
+ DEBUG(5,("Connected with cnum=%d max_xmit=%d\n",cnum,max_xmit));
if (was_null)
{
free(inbuf);
free(outbuf);
}
-
return True;
}
@@ -814,12 +638,10 @@ BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup)
/****************************************************************************
send a logout command
****************************************************************************/
-void cli_send_logout(void )
+void cli_send_logout(void)
{
pstring inbuf,outbuf;
- DEBUG(5,("cli_send_logout\n"));
-
bzero(outbuf,smb_size);
set_message(outbuf,0,0,True);
CVAL(outbuf,smb_com) = SMBtdis;
@@ -843,15 +665,152 @@ void cli_send_logout(void )
/****************************************************************************
+ send a SMB trans or trans2 request
+ ****************************************************************************/
+static BOOL cli_send_trans_request(char *outbuf, int trans, char *name, int fid, int flags,
+ char *data,char *param,uint16 *setup, int ldata,int lparam,
+ int lsetup,int mdata,int mparam,int msetup)
+{
+ int i;
+ int this_ldata,this_lparam;
+ int tot_data=0,tot_param=0;
+ char *outdata,*outparam;
+ pstring inbuf;
+ char *p;
+
+ this_lparam = MIN(lparam,max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
+ this_ldata = MIN(ldata,max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
+
+ bzero(outbuf,smb_size);
+ set_message(outbuf,14+lsetup,0,True);
+ CVAL(outbuf,smb_com) = trans;
+ SSVAL(outbuf,smb_tid,cnum);
+ cli_setup_pkt(outbuf);
+
+ outparam = smb_buf(outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
+ outdata = outparam+this_lparam;
+
+ /* primary request */
+ SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
+ SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
+ SSVAL(outbuf,smb_mprcnt,mparam); /* mprcnt */
+ SSVAL(outbuf,smb_mdrcnt,mdata); /* mdrcnt */
+ SCVAL(outbuf,smb_msrcnt,msetup); /* msrcnt */
+ SSVAL(outbuf,smb_flags,flags); /* flags */
+ SIVAL(outbuf,smb_timeout,0); /* timeout */
+ SSVAL(outbuf,smb_pscnt,this_lparam); /* pscnt */
+ SSVAL(outbuf,smb_psoff,smb_offset(outparam,outbuf)); /* psoff */
+ SSVAL(outbuf,smb_dscnt,this_ldata); /* dscnt */
+ SSVAL(outbuf,smb_dsoff,smb_offset(outdata,outbuf)); /* dsoff */
+ SCVAL(outbuf,smb_suwcnt,lsetup); /* suwcnt */
+ for (i=0;i<lsetup;i++) /* setup[] */
+ SSVAL(outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
+ p = smb_buf(outbuf);
+ if (trans==SMBtrans)
+ strcpy(p,name); /* name[] */
+ else
+ {
+ *p++ = 0; /* put in a null smb_name */
+ *p++ = 'D'; *p++ = ' '; /* this was added because OS/2 does it */
+ }
+ if (this_lparam) /* param[] */
+ memcpy(outparam,param,this_lparam);
+ if (this_ldata) /* data[] */
+ memcpy(outdata,data,this_ldata);
+ set_message(outbuf,14+lsetup, /* wcnt, bcc */
+ PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
+
+ show_msg(outbuf);
+ send_smb(Client,outbuf);
+
+ if (this_ldata < ldata || this_lparam < lparam)
+ {
+ /* receive interim response */
+ if (!receive_smb(Client,inbuf,SHORT_TIMEOUT) || CVAL(inbuf,smb_rcls) != 0)
+ {
+ DEBUG(0,("%s request failed (%s)\n",
+ trans==SMBtrans?"SMBtrans":"SMBtrans2", smb_errstr(inbuf)));
+ return(False);
+ }
+
+ tot_data = this_ldata;
+ tot_param = this_lparam;
+
+ while (tot_data < ldata || tot_param < lparam)
+ {
+ this_lparam = MIN(lparam-tot_param,max_xmit - 500); /* hack */
+ this_ldata = MIN(ldata-tot_data,max_xmit - (500+this_lparam));
+
+ set_message(outbuf,trans==SMBtrans?8:9,0,True);
+ CVAL(outbuf,smb_com) = trans==SMBtrans ? SMBtranss : SMBtranss2;
+
+ outparam = smb_buf(outbuf);
+ outdata = outparam+this_lparam;
+
+ /* secondary request */
+ SSVAL(outbuf,smb_tpscnt,lparam); /* tpscnt */
+ SSVAL(outbuf,smb_tdscnt,ldata); /* tdscnt */
+ SSVAL(outbuf,smb_spscnt,this_lparam); /* pscnt */
+ SSVAL(outbuf,smb_spsoff,smb_offset(outparam,outbuf)); /* psoff */
+ SSVAL(outbuf,smb_spsdisp,tot_param); /* psdisp */
+ SSVAL(outbuf,smb_sdscnt,this_ldata); /* dscnt */
+ SSVAL(outbuf,smb_sdsoff,smb_offset(outdata,outbuf)); /* dsoff */
+ SSVAL(outbuf,smb_sdsdisp,tot_data); /* dsdisp */
+ if (trans==SMBtrans2)
+ SSVAL(outbuf,smb_sfid,fid); /* fid */
+ if (this_lparam) /* param[] */
+ memcpy(outparam,param,this_lparam);
+ if (this_ldata) /* data[] */
+ memcpy(outdata,data,this_ldata);
+ set_message(outbuf,trans==SMBtrans?8:9, /* wcnt, bcc */
+ PTR_DIFF(outdata+this_ldata,smb_buf(outbuf)),False);
+
+ show_msg(outbuf);
+ send_smb(Client,outbuf);
+
+ tot_data += this_ldata;
+ tot_param += this_lparam;
+ }
+ }
+
+ return(True);
+}
+
+
+
+/****************************************************************************
+call a remote api
+****************************************************************************/
+BOOL cli_call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt,int *rprcnt,
+ int *rdrcnt, char *param,char *data,
+ char **rparam, char **rdata)
+{
+ static char *inbuf=NULL;
+ static char *outbuf=NULL;
+
+ if (!inbuf) inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
+ if (!outbuf) outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
+
+ cli_send_trans_request(outbuf,SMBtrans,"\\PIPE\\LANMAN",0,0,
+ data,param,NULL,
+ drcnt,prcnt,0,
+ mdrcnt,mprcnt,0);
+
+ return (cli_receive_trans_response(inbuf,SMBtrans,
+ rdrcnt,rprcnt,
+ rdata,rparam));
+}
+
+
+/****************************************************************************
open the client sockets
****************************************************************************/
-BOOL cli_open_sockets(int port )
+BOOL cli_open_sockets(int port)
{
static int last_port;
char *host;
pstring service2;
extern int Client;
- BOOL failed = True;
if (port == 0) port=last_port;
last_port=port;
@@ -864,66 +823,38 @@ BOOL cli_open_sockets(int port )
}
else
{
- strcpy(service2,service);
+ pstrcpy(service2,service);
host = strtok(service2,"\\/");
- if (!host) {
- DEBUG(0,("Badly formed host name\n"));
- return(False);
- }
- strcpy(desthost,host);
+ pstrcpy(desthost,host);
}
- if (!(*myname)) {
- get_myname(myname,NULL);
- }
- strupper(myname);
+ DEBUG(5,("Opening sockets\n"));
- DEBUG(3,("Opening sockets\n"));
+ if (*myname == 0)
+ get_myname(myname,NULL);
+ strupper(myname);
if (!have_ip)
{
struct hostent *hp;
- if ((hp = Get_Hostbyname(host)))
- {
- putip((char *)&dest_ip,(char *)hp->h_addr);
- failed = False;
- }
- else
- {
-#ifdef USENMB
- /* Try and resolve the name with the netbios server */
- int bcast, count;
- struct in_addr *ip_list;
-
- if ((bcast = open_socket_in(SOCK_DGRAM, 0, 3,
- interpret_addr(lp_socket_address()))) != -1) {
- set_socket_options(bcast, "SO_BROADCAST");
-
- if ((ip_list = name_query(bcast, host, name_type, True, True, *iface_bcast(dest_ip),
- &count,0)) {
- dest_ip = ip_list[0];
- free(ip_list);
- failed = False;
- }
- close (bcast);
- }
-#endif
- if (failed) {
+ if ((hp = Get_Hostbyname(host)) == 0)
+ {
DEBUG(0,("Get_Hostbyname: Unknown host %s.\n",host));
return False;
}
- }
+
+ putip((char *)&dest_ip,(char *)hp->h_addr);
}
- Client = open_socket_out(SOCK_STREAM, &dest_ip, port, LONG_CONNECT_TIMEOUT);
+ Client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT);
if (Client == -1)
return False;
- DEBUG(3,("Connected\n"));
-
+ DEBUG(5,("Connected\n"));
+
set_socket_options(Client,user_socket_options);
-
+
return True;
}
@@ -954,3 +885,155 @@ BOOL cli_reopen_connection(char *inbuf,char *outbuf)
return(cli_send_login(inbuf,outbuf,True,True));
}
+/* error code stuff - put together by Merik Karman
+ merik@blackadder.dsh.oz.au */
+
+typedef struct
+{
+ char *name;
+ int code;
+ char *message;
+} err_code_struct;
+
+/* Dos Error Messages */
+err_code_struct dos_msgs[] = {
+ {"ERRbadfunc",1,"Invalid function."},
+ {"ERRbadfile",2,"File not found."},
+ {"ERRbadpath",3,"Directory invalid."},
+ {"ERRnofids",4,"No file descriptors available"},
+ {"ERRnoaccess",5,"Access denied."},
+ {"ERRbadfid",6,"Invalid file handle."},
+ {"ERRbadmcb",7,"Memory control blocks destroyed."},
+ {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
+ {"ERRbadmem",9,"Invalid memory block address."},
+ {"ERRbadenv",10,"Invalid environment."},
+ {"ERRbadformat",11,"Invalid format."},
+ {"ERRbadaccess",12,"Invalid open mode."},
+ {"ERRbaddata",13,"Invalid data."},
+ {"ERR",14,"reserved."},
+ {"ERRbaddrive",15,"Invalid drive specified."},
+ {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
+ {"ERRdiffdevice",17,"Not same device."},
+ {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
+ {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
+ {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
+ {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
+ {"ERRbadpipe",230,"Pipe invalid."},
+ {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
+ {"ERRpipeclosing",232,"Pipe close in progress."},
+ {"ERRnotconnected",233,"No process on other end of pipe."},
+ {"ERRmoredata",234,"There is more data to be returned."},
+ {NULL,-1,NULL}};
+
+/* Server Error Messages */
+err_code_struct server_msgs[] = {
+ {"ERRerror",1,"Non-specific error code."},
+ {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
+ {"ERRbadtype",3,"reserved."},
+ {"ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."},
+ {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
+ {"ERRinvnetname",6,"Invalid network name in tree connect."},
+ {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
+ {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
+ {"ERRqtoobig",50,"Print queue full -- no space."},
+ {"ERRqeof",51,"EOF on print queue dump."},
+ {"ERRinvpfid",52,"Invalid print file FID."},
+ {"ERRsmbcmd",64,"The server did not recognize the command received."},
+ {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
+ {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
+ {"ERRreserved",68,"reserved."},
+ {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
+ {"ERRreserved",70,"reserved."},
+ {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
+ {"ERRpaused",81,"Server is paused."},
+ {"ERRmsgoff",82,"Not receiving messages."},
+ {"ERRnoroom",83,"No room to buffer message."},
+ {"ERRrmuns",87,"Too many remote user names."},
+ {"ERRtimeout",88,"Operation timed out."},
+ {"ERRnoresource",89,"No resources currently available for request."},
+ {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
+ {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
+ {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
+ {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
+ {"ERRcontmpx",252,"Continue in MPX mode."},
+ {"ERRreserved",253,"reserved."},
+ {"ERRreserved",254,"reserved."},
+ {"ERRnosupport",0xFFFF,"Function not supported."},
+ {NULL,-1,NULL}};
+
+/* Hard Error Messages */
+err_code_struct hard_msgs[] = {
+ {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
+ {"ERRbadunit",20,"Unknown unit."},
+ {"ERRnotready",21,"Drive not ready."},
+ {"ERRbadcmd",22,"Unknown command."},
+ {"ERRdata",23,"Data error (CRC)."},
+ {"ERRbadreq",24,"Bad request structure length."},
+ {"ERRseek",25 ,"Seek error."},
+ {"ERRbadmedia",26,"Unknown media type."},
+ {"ERRbadsector",27,"Sector not found."},
+ {"ERRnopaper",28,"Printer out of paper."},
+ {"ERRwrite",29,"Write fault."},
+ {"ERRread",30,"Read fault."},
+ {"ERRgeneral",31,"General failure."},
+ {"ERRbadshare",32,"A open conflicts with an existing open."},
+ {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
+ {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
+ {"ERRFCBUnavail",35,"No FCBs are available to process request."},
+ {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
+ {NULL,-1,NULL}};
+
+
+struct
+{
+ int code;
+ char *class;
+ err_code_struct *err_msgs;
+} err_classes[] = {
+ {0,"SUCCESS",NULL},
+ {0x01,"ERRDOS",dos_msgs},
+ {0x02,"ERRSRV",server_msgs},
+ {0x03,"ERRHRD",hard_msgs},
+ {0x04,"ERRXOS",NULL},
+ {0xE1,"ERRRMX1",NULL},
+ {0xE2,"ERRRMX2",NULL},
+ {0xE3,"ERRRMX3",NULL},
+ {0xFF,"ERRCMD",NULL},
+ {-1,NULL,NULL}};
+
+
+/****************************************************************************
+return a SMB error string from a SMB buffer
+****************************************************************************/
+char *smb_errstr(char *inbuf)
+{
+ static pstring ret;
+ int class = CVAL(inbuf,smb_rcls);
+ int num = SVAL(inbuf,smb_err);
+ int i,j;
+
+ for (i=0;err_classes[i].class;i++)
+ if (err_classes[i].code == class)
+ {
+ if (err_classes[i].err_msgs)
+ {
+ err_code_struct *err = err_classes[i].err_msgs;
+ for (j=0;err[j].name;j++)
+ if (num == err[j].code)
+ {
+ if (DEBUGLEVEL > 0)
+ sprintf(ret,"%s - %s (%s)",err_classes[i].class,
+ err[j].name,err[j].message);
+ else
+ sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
+ return ret;
+ }
+ }
+
+ sprintf(ret,"%s - %d",err_classes[i].class,num);
+ return ret;
+ }
+
+ sprintf(ret,"ERROR: Unknown error (%d,%d)",class,num);
+ return(ret);
+}
diff --git a/source/client/clitar.c b/source/client/clitar.c
index 1e7c45691b2..d5bca8c5bbb 100644
--- a/source/client/clitar.c
+++ b/source/client/clitar.c
@@ -90,7 +90,7 @@ static void unfixtarname();
Write a tar header to buffer
****************************************************************************/
static void writetarheader(int f, char *aname, int size, time_t mtime,
- char *amode)
+ char *amode)
{
union hblock hb;
int i, chk, l;
@@ -99,21 +99,10 @@ static void writetarheader(int f, char *aname, int size, time_t mtime,
memset(hb.dummy, 0, sizeof(hb.dummy));
l=strlen(aname);
- if (l >= NAMSIZ) {
- /* write a GNU tar style long header */
- char *b;
- b = (char *)malloc(l+TBLOCK+100);
- if (!b) {
- DEBUG(0,("out of memory\n"));
- exit(1);
- }
- writetarheader(f, "/./@LongLink", l+1, 0, " 0 \0");
- memset(b, 0, l+TBLOCK+100);
- fixtarname(b, aname, l+1);
- i = strlen(b)+1;
- dotarbuf(f, b, TBLOCK*((i+(TBLOCK-1)/TBLOCK)));
- free(b);
- }
+ if (l >= NAMSIZ)
+ {
+ DEBUG(0, ("tar file %s name length exceeds NAMSIZ\n", aname));
+ }
/* use l + 1 to do the null too */
fixtarname(hb.dbuf.name, aname, (l >= NAMSIZ) ? NAMSIZ : l + 1);
@@ -130,13 +119,8 @@ static void writetarheader(int f, char *aname, int size, time_t mtime,
oct_it((long) size, 13, hb.dbuf.size);
oct_it((long) mtime, 13, hb.dbuf.mtime);
memcpy(hb.dbuf.chksum, " ", sizeof(hb.dbuf.chksum));
+ hb.dbuf.linkflag='0';
memset(hb.dbuf.linkname, 0, NAMSIZ);
- if (strcmp("/./@LongLink", aname) == 0) {
- /* we're doing a GNU tar long filename */
- hb.dbuf.linkflag='L';
- } else {
- hb.dbuf.linkflag='0';
- }
for (chk=0, i=sizeof(hb.dummy), jp=hb.dummy; --i>=0;) chk+=(0xFF & *jp++);
@@ -322,35 +306,27 @@ static void fixtarname(char *tptr, char *fp, int l)
* to lovely unix /'s :-} */
*tptr++='.';
- if(lp_client_code_page() == KANJI_CODEPAGE)
- {
- while (l > 0) {
- if (is_shift_jis (*fp)) {
- *tptr++ = *fp++;
- *tptr++ = *fp++;
- l -= 2;
- } else if (is_kana (*fp)) {
- *tptr++ = *fp++;
- l--;
- } else if (*fp == '\\') {
- *tptr++ = '/';
- fp++;
- l--;
- } else {
- *tptr++ = *fp++;
- l--;
- }
- }
- }
- else
- {
- while (l--)
- {
- *tptr=(*fp == '\\') ? '/' : *fp;
- tptr++;
+#ifdef KANJI
+ while (l > 0) {
+ if (is_shift_jis (*fp)) {
+ *tptr++ = *fp++;
+ *tptr++ = *fp++;
+ l -= 2;
+ } else if (is_kana (*fp)) {
+ *tptr++ = *fp++;
+ l--;
+ } else if (*fp == '\\') {
+ *tptr++ = '/';
fp++;
+ l--;
+ } else {
+ *tptr++ = *fp++;
+ l--;
}
}
+#else
+ while (l--) { *tptr=(*fp == '\\') ? '/' : *fp; tptr++; fp++; }
+#endif
}
/****************************************************************************
@@ -461,7 +437,7 @@ static int do_setrattr(char *fname, int attr, int setit)
set_message(outbuf,0,2 + strlen(fname),True);
CVAL(outbuf,smb_com) = SMBgetatr;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
p = smb_buf(outbuf);
*p++ = 4;
@@ -497,7 +473,7 @@ static int do_setrattr(char *fname, int attr, int setit)
set_message(outbuf,8,4 + strlen(fname),True);
CVAL(outbuf,smb_com) = SMBsetatr;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,attr);
@@ -537,7 +513,7 @@ static BOOL smbcreat(file_info finfo, int *fnum, char *inbuf, char *outbuf)
set_message(outbuf,3,2 + strlen(finfo.name),True);
CVAL(outbuf,smb_com) = SMBcreate;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,finfo.mode);
put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
@@ -576,7 +552,7 @@ static BOOL smbwrite(int fnum, int n, int low, int high, int left,
set_message(outbuf,5,n + 3, False);
CVAL(outbuf,smb_com) = SMBwrite;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,fnum);
SSVAL(outbuf,smb_vwv1,n);
@@ -615,7 +591,7 @@ static BOOL smbshut(file_info finfo, int fnum, char *inbuf, char *outbuf)
set_message(outbuf,3,0,True);
CVAL(outbuf,smb_com) = SMBclose;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,fnum);
put_dos_date3(outbuf,smb_vwv1,finfo.mtime);
@@ -648,7 +624,7 @@ static BOOL smbchkpath(char *fname, char *inbuf, char *outbuf)
set_message(outbuf,0,4 + strlen(fname),True);
CVAL(outbuf,smb_com) = SMBchkpth;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
p = smb_buf(outbuf);
*p++ = 4;
@@ -675,7 +651,7 @@ static BOOL smbmkdir(char *fname, char *inbuf, char *outbuf)
CVAL(outbuf,smb_com) = SMBmkdir;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
p = smb_buf(outbuf);
*p++ = 4;
@@ -798,7 +774,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
CVAL(outbuf,smb_com) = SMBopenX;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,0xFF);
SSVAL(outbuf,smb_vwv2,1);
@@ -834,7 +810,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
{
if (CVAL(inbuf,smb_rcls) == ERRSRV &&
SVAL(inbuf,smb_err) == ERRnoresource &&
- cli_reopen_connection(inbuf,outbuf))
+ reopen_connection(inbuf,outbuf))
{
do_atar(rname,lname,finfo1);
free(inbuf);free(outbuf);
@@ -930,7 +906,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
set_message(outbuf,10,0,True);
CVAL(outbuf,smb_com) = SMBreadX;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
if (close_done)
{
@@ -996,7 +972,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
set_message(outbuf,8,0,True);
CVAL(outbuf,smb_com) = SMBreadbraw;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,fnum);
SIVAL(outbuf,smb_vwv1,nread);
SSVAL(outbuf,smb_vwv3,MIN(finfo.size-nread,readbraw_size));
@@ -1048,7 +1024,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
set_message(outbuf,5,0,True);
CVAL(outbuf,smb_com) = SMBread;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,fnum);
SSVAL(outbuf,smb_vwv1,MIN(max_xmit-200,finfo.size - nread));
@@ -1074,7 +1050,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
* write out in 512 byte intervals */
if (dotarbuf(tarhandle,dataptr,datalen) != datalen)
{
- DEBUG(0,("Error writing to tar file - %s\n", strerror(errno)));
+ DEBUG(0,("Error writing local file\n"));
break;
}
@@ -1094,7 +1070,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
{
DEBUG(0, ("Didn't get entire file. size=%d, nread=%d\n", finfo.size, nread));
if (padit(inbuf, BUFFER_SIZE, finfo.size - nread))
- DEBUG(0,("Error writing tar file - %s\n", strerror(errno)));
+ DEBUG(0,("Error writing local file\n"));
}
/* round tar file to nearest block */
@@ -1111,7 +1087,7 @@ static void do_atar(char *rname,char *lname,file_info *finfo1)
set_message(outbuf,3,0,True);
CVAL(outbuf,smb_com) = SMBclose;
SSVAL(outbuf,smb_tid,cnum);
- cli_setup_pkt(outbuf);
+ setup_pkt(outbuf);
SSVAL(outbuf,smb_vwv0,fnum);
SIVALS(outbuf,smb_vwv1,-1);
@@ -1227,35 +1203,27 @@ static void unfixtarname(char *tptr, char *fp, int l)
if (*fp == '.') fp++;
if (*fp == '\\' || *fp == '/') fp++;
- if(lp_client_code_page() == KANJI_CODEPAGE)
- {
- while (l > 0) {
- if (is_shift_jis (*fp)) {
- *tptr++ = *fp++;
- *tptr++ = *fp++;
- l -= 2;
- } else if (is_kana (*fp)) {
- *tptr++ = *fp++;
- l--;
- } else if (*fp == '/') {
- *tptr++ = '\\';
- fp++;
- l--;
- } else {
- *tptr++ = *fp++;
- l--;
- }
- }
- }
- else
- {
- while (l--)
- {
- *tptr=(*fp == '/') ? '\\' : *fp;
- tptr++;
+#ifdef KANJI
+ while (l > 0) {
+ if (is_shift_jis (*fp)) {
+ *tptr++ = *fp++;
+ *tptr++ = *fp++;
+ l -= 2;
+ } else if (is_kana (*fp)) {
+ *tptr++ = *fp++;
+ l--;
+ } else if (*fp == '/') {
+ *tptr++ = '\\';
fp++;
+ l--;
+ } else {
+ *tptr++ = *fp++;
+ l--;
}
}
+#else
+ while (l--) { *tptr=(*fp == '/') ? '\\' : *fp; tptr++; fp++; }
+#endif
}
static void do_tarput()
@@ -1761,8 +1729,7 @@ int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind)
if ((tar_type=='x' && (tarhandle = open(argv[Optind], O_RDONLY)) == -1)
|| (tar_type=='c' && (tarhandle=creat(argv[Optind], 0644)) < 0))
{
- DEBUG(0,("Error opening local file %s - %s\n",
- argv[Optind], strerror(errno)));
+ DEBUG(0,("Error opening local file %s\n",argv[Optind]));
return(0);
}
}
diff --git a/source/client/ntclient.c b/source/client/ntclient.c
deleted file mode 100644
index 7e360981c02..00000000000
--- a/source/client/ntclient.c
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NT Domain Authentication SMB / MSRPC client
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1996-1997
-
- 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.
-*/
-
-#ifdef SYSLOG
-#undef SYSLOG
-#endif
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-extern pstring username;
-extern pstring smb_login_passwd;
-extern pstring workgroup;
-
-#define CLIENT_TIMEOUT (30*1000)
-
-#ifdef NTDOMAIN
-
-
-/****************************************************************************
-experimental nt login.
-****************************************************************************/
-BOOL do_nt_login(char *desthost, char *myhostname,
- int Client, int cnum)
-{
- DOM_CHAL clnt_chal;
- DOM_CHAL srv_chal;
-
- DOM_CRED clnt_cred;
-
- DOM_CHAL auth2_srv_chal;
-
- DOM_CRED sam_logon_clnt_cred;
- DOM_CRED sam_logon_rtn_cred;
- DOM_CRED sam_logon_srv_cred;
-
- DOM_CRED sam_logoff_clnt_cred;
- DOM_CRED sam_logoff_rtn_cred;
- DOM_CRED sam_logoff_srv_cred;
-
- DOM_ID_INFO_1 id1;
- LSA_USER_INFO user_info1;
- LSA_POL_HND pol;
- int i;
-
- UTIME zerotime;
-
- uchar sess_key[8];
- char nt_owf_mach_pwd[16];
- fstring mach_acct;
- fstring mach_pwd;
- fstring server_name;
-
- RPC_IFACE abstract;
- RPC_IFACE transfer;
-
- static char abs_data[16];
- static char trn_data[16];
-
- /* received from LSA Query Info Policy, level 5 */
- fstring level5_domain_name;
- pstring level5_domain_sid;
-
- /* received from LSA Query Info Policy, level 3 */
- fstring level3_domain_name;
- pstring level3_domain_sid;
-
- uint16 fnum;
- uint32 call_id = 0;
- char *inbuf,*outbuf;
-
- zerotime.time = 0;
-
- inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
- outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
-
- if (!inbuf || !outbuf)
- {
- DEBUG(0,("out of memory\n"));
- return False;
- }
-
- /******************* open the \PIPE\lsarpc file *****************/
-
- if ((fnum = rpc_pipe_open(inbuf, outbuf, PIPE_LSARPC, Client, cnum)) == 0xffff)
- {
- free(inbuf); free(outbuf);
- return False;
- }
-
- /**************** Set Named Pipe State ***************/
- if (!rpc_pipe_set_hnd_state(PIPE_LSARPC, fnum, 0x4300))
- {
- free(inbuf); free(outbuf);
- return False;
- }
-
- /******************* bind request on \PIPE\lsarpc *****************/
-
- /* create and send a MSRPC command with api LSA_OPENPOLICY */
-
- DEBUG(4,("LSA RPC Bind[%x]\n", fnum));
-
- for (i = 0; i < sizeof(trn_data); i++)
- {
- trn_data[i] = 2 * i;
- }
-
- for (i = 0; i < sizeof(abs_data); i++)
- {
- abs_data[i] = i;
- }
-
- /* create interface UUIDs. */
- make_rpc_iface(&abstract, abs_data, 0x0);
- make_rpc_iface(&transfer, trn_data, 0x2);
-
- if (!rpc_pipe_bind(PIPE_LSARPC, fnum, ++call_id, &abstract, &transfer))
- {
- free(inbuf); free(outbuf);
- return False;
- }
-
- /******************* Open Policy ********************/
-
- fstrcpy(server_name, ("\\\\"));
- fstrcpy(&server_name[2], myhostname);
-
- /* send an open policy request; receive a policy handle */
- if (!do_lsa_open_policy(fnum, ++call_id, server_name, &pol))
- {
- cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
- free(inbuf); free(outbuf);
- return False;
- }
-
- /**************** Query Info Policy, level 3 ********************/
-
- /* send a query info policy at level 3; receive an info policy */
- if (!do_lsa_query_info_pol(fnum, ++call_id, &pol, 0x3,
- level3_domain_name, level3_domain_sid))
- {
- cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
- free(inbuf); free(outbuf);
- return False;
- }
-
- /**************** Query Info Policy, level 5 ********************/
-
- /* send a query info policy at level 5; receive an info policy */
- if (!do_lsa_query_info_pol(fnum, ++call_id, &pol, 0x5,
- level5_domain_name, level5_domain_sid))
- {
- cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
- free(inbuf); free(outbuf);
- return False;
- }
-
- /******************* Open Policy ********************/
-
- /* send a close policy request; receive a close pol response */
- if (!do_lsa_close(fnum, ++call_id, &pol))
- {
- cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
- free(inbuf); free(outbuf);
- return False;
- }
-
- /******************* close the \PIPE\lsarpc file *******************/
-
- cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
-
-
-
- /******************* open the \PIPE\NETLOGON file *****************/
-
- if ((fnum = rpc_pipe_open(inbuf, outbuf, PIPE_NETLOGON, Client, cnum)) == 0xffff)
- {
- free(inbuf); free(outbuf);
- return False;
- }
-
- /**************** Set Named Pipe State ***************/
- if (!rpc_pipe_set_hnd_state(PIPE_NETLOGON, fnum, 0x4300))
- {
- free(inbuf); free(outbuf);
- return False;
- }
-
- /******************* bind request on \PIPE\NETLOGON *****************/
-
- if (!rpc_pipe_bind(PIPE_NETLOGON, fnum, ++call_id, &abstract, &transfer))
- {
- free(inbuf); free(outbuf);
- return False;
- }
-
- /******************* Request Challenge ********************/
-
- fstrcpy(mach_acct, myhostname);
- strlower(mach_pwd);
-
- fstrcpy(mach_pwd , myhostname);
- strcat(mach_acct, "$");
-
- SIVAL(clnt_chal.data, 0, 0x11111111);
- SIVAL(clnt_chal.data, 4, 0x22222222);
-
- /* send a client challenge; receive a server challenge */
- if (!do_lsa_req_chal(fnum, ++call_id, desthost, myhostname, &clnt_chal, &srv_chal))
- {
- cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
- free(inbuf); free(outbuf);
- return False;
- }
-
- /************ Long-term Session key (default) **********/
-
-#if 0
- /* DAMN! can't get the machine password - need become_root() to do it! */
- /* get the machine password */
- if (!get_md4pw(mach_acct, nt_owf_mach_pwd))
- {
- cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
- free(inbuf); free(outbuf);
- return False;
- }
-
- DEBUG(5,("got nt owf from smbpasswd entry: %s\n", mach_pwd));
-#else
-
- {
- char lm_owf_mach_pwd[16];
- nt_lm_owf_gen(mach_pwd, nt_owf_mach_pwd, lm_owf_mach_pwd);
- DEBUG(5,("generating nt owf from initial machine pwd: %s\n", mach_pwd));
- }
-
-#endif
-
- dump_data(6, nt_owf_mach_pwd, 16);
-
- /* calculate the session key */
- cred_session_key(&clnt_chal, &srv_chal, nt_owf_mach_pwd, sess_key);
-
-
- /******************* Authenticate 2 ********************/
-
- /* calculate auth-2 credentials */
- cred_create(sess_key, &clnt_chal, zerotime, &(clnt_cred.challenge));
-
- /* send client auth-2 challenge; receive an auth-2 challenge */
- if (!do_lsa_auth2(fnum, ++call_id, desthost, mach_acct, 2, myhostname,
- &(clnt_cred.challenge), 0x000001ff, &auth2_srv_chal))
- {
- cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
- free(inbuf); free(outbuf);
- return False;
- }
-
-
- /*********************** SAM Info ***********************/
-
- {
- char lm_owf_user_pwd[16];
- char nt_owf_user_pwd[16];
- nt_lm_owf_gen(smb_login_passwd, nt_owf_user_pwd, lm_owf_user_pwd);
-
-#ifdef DEBUG_PASSWORD
-
- DEBUG(100,("nt owf of user password: "));
- dump_data(100, lm_owf_user_pwd, 16);
-
- DEBUG(100,("nt owf of user password: "));
- dump_data(100, nt_owf_user_pwd, 16);
-
-#endif
-
- /* this is used in both the SAM Logon and the SAM Logoff */
- make_id_info1(&id1, workgroup, 0,
- getuid(), 0,
- username, myhostname,
- sess_key, lm_owf_user_pwd, nt_owf_user_pwd);
- }
-
- /*********************** SAM Logon **********************/
-
- clnt_cred.timestamp.time = sam_logon_clnt_cred.timestamp.time = time(NULL);
-
- /* calculate sam logon credentials, using the auth2 client challenge */
- cred_create(sess_key, &(clnt_cred.challenge), sam_logon_clnt_cred.timestamp,
- &(sam_logon_clnt_cred.challenge));
-
- /* send client sam-logon challenge; receive a sam-logon challenge */
- if (!do_lsa_sam_logon(fnum, ++call_id, sess_key, &clnt_cred,
- desthost, mach_acct,
- &sam_logon_clnt_cred, &sam_logon_rtn_cred,
- 1, 1, &id1, &user_info1,
- &sam_logon_srv_cred))
- {
- cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
- free(inbuf); free(outbuf);
- return False;
- }
-
- /*********************** SAM Logoff *********************/
-
- clnt_cred.timestamp.time = sam_logoff_clnt_cred.timestamp.time = time(NULL);
-
- /* calculate sam logoff credentials, using the sam logon return challenge */
- cred_create(sess_key, &(clnt_cred.challenge),
- sam_logoff_clnt_cred.timestamp,
- &(sam_logoff_clnt_cred.challenge));
-
- /* send client sam-logoff challenge; receive a sam-logoff challenge */
- if (!do_lsa_sam_logoff(fnum, ++call_id, sess_key, &clnt_cred,
- desthost, mach_acct,
- &sam_logoff_clnt_cred, &sam_logoff_rtn_cred,
- 1, 1, &id1,
- &sam_logoff_srv_cred))
- {
- cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
- free(inbuf); free(outbuf);
- return False;
- }
-
- /******************** close the \PIPE\NETLOGON file **************/
-
- cli_smb_close(inbuf, outbuf, Client, cnum, fnum);
-
- /* free memory used in all rpc transactions, above */
- free(inbuf); free(outbuf);
-
- return True;
-}
-#endif /* NTDOMAIN */
diff --git a/source/codepages/codepage_def.437 b/source/codepages/codepage_def.437
deleted file mode 100644
index d357c074e44..00000000000
--- a/source/codepages/codepage_def.437
+++ /dev/null
@@ -1,70 +0,0 @@
-#
-# 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.
-#
-
-# Codepage definition file for IBM Code Page 437 - MS-DOS Latin US
-# defines lower->upper mapping.
-# Written by Jeremy Allison <jallison@whistle.com>
-
-# The columns are :
-# lower upper map upper to lower map lower to upper
-#
- 0x87 0x80 True True
- 0x81 0x9A True True
- 0x82 0x90 True True
- 0x83 0x41 True False
- 0x84 0x8E True True
- 0x85 0x41 True False
- 0x86 0x8F True True
- 0x88 0x45 True False
- 0x89 0x45 True False
- 0x8A 0x45 True False
- 0x8B 0x49 True False
- 0x8C 0x49 True False
- 0x8D 0x49 True False
- 0x91 0x92 True True
- 0x93 0x4F True False
- 0x94 0x99 True True
- 0x95 0x4F True False
- 0x96 0x55 True False
- 0x97 0x55 True False
- 0x9B 0 False False
- 0x9C 0 False False
- 0x9D 0 False False
- 0xA0 0x41 True False
- 0xA1 0x49 True False
- 0xA2 0x4F True False
- 0xA3 0x55 True False
- 0xA4 0xA5 True True
- 0xA8 0 False False
- 0xAD 0 False False
- 0xAE 0 False False
- 0xAF 0 False False
- 0xE0 0 False False
- 0xE1 0 False False
- 0xE2 0 False False
- 0xE3 0 False False
- 0xE4 0 False False
- 0xE5 0 False False
- 0xE6 0 False False
- 0xE7 0 False False
- 0xE8 0 False False
- 0xE9 0 False False
- 0xEA 0 False False
- 0xEB 0 False False
- 0xEC 0 False False
- 0xED 0 False False
- 0xEE 0 False False
- 0xEF 0 False False
diff --git a/source/codepages/codepage_def.850 b/source/codepages/codepage_def.850
deleted file mode 100644
index e2466a707af..00000000000
--- a/source/codepages/codepage_def.850
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# 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.
-#
-
-# Codepage definition file for IBM Code Page 850 - MS-DOS Latin 1
-# defines lower->upper mapping.
-# Written by Jeremy Allison (jallison@whistle.com)
-
-# The columns are :
-# lower upper map upper to lower map lower to upper
-#
- 0x85 0xB7 True True
- 0xA0 0xB5 True True
- 0x83 0xB6 True True
- 0xC6 0xC7 True True
- 0x84 0x8E True True
- 0x86 0x8F True True
- 0x91 0x92 True True
- 0x87 0x80 True True
- 0x8A 0xD4 True True
- 0x82 0x90 True True
- 0x88 0xD2 True True
- 0x89 0xD3 True True
- 0x8D 0xDE True True
- 0xA1 0xD6 True True
- 0x8C 0xD7 True True
- 0x8B 0xD8 True True
- 0xD0 0xD1 True True
- 0xA4 0xA5 True True
- 0x95 0xE3 True True
- 0xA2 0xE0 True True
- 0x93 0xE2 True True
- 0xE4 0xE5 True True
- 0x94 0x99 True True
- 0x9B 0x9D True True
- 0x97 0xEB True True
- 0xA3 0xE9 True True
- 0x96 0xEA True True
- 0x81 0x9A True True
- 0xEC 0xED True True
- 0xE7 0xE8 True True
- 0x9C 0 False False
diff --git a/source/codepages/codepage_def.852 b/source/codepages/codepage_def.852
deleted file mode 100644
index ed1423428ca..00000000000
--- a/source/codepages/codepage_def.852
+++ /dev/null
@@ -1,63 +0,0 @@
-#
-# 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.
-#
-
-# Codepage definition file for IBM Code Page 852 - MS-DOS Latin 2
-# defines lower->upper mapping.
-# Written by Leos Bitto <bitto@altec.cz>
-
-# The columns are :
-# lower upper map upper to lower map lower to upper
-#
- 0x81 0x9A True True
- 0x82 0x90 True True
- 0x83 0xB6 True True
- 0x84 0x8E True True
- 0x85 0xDE True True
- 0x86 0x8F True True
- 0x87 0x80 True True
- 0x88 0x9D True True
- 0x89 0xD3 True True
- 0x8B 0x8A True True
- 0x8C 0xD7 True True
- 0x92 0x91 True True
- 0x93 0xE2 True True
- 0x94 0x99 True True
- 0x96 0x95 True True
- 0x98 0x97 True True
- 0x9C 0x9B True True
- 0x9F 0xAC True True
- 0xA0 0xB5 True True
- 0xA1 0xD6 True True
- 0xA2 0xE0 True True
- 0xA3 0xE9 True True
- 0xA5 0xA4 True True
- 0xA7 0xA6 True True
- 0xA9 0xA8 True True
- 0xAB 0x8D True True
- 0xAD 0xB8 True True
- 0xBE 0xBD True True
- 0xC7 0xC6 True True
- 0xD0 0xD1 True True
- 0xD4 0xD2 True True
- 0xD8 0xB7 True True
- 0xE4 0xE3 True True
- 0xE5 0xD5 True True
- 0xE7 0xE6 True True
- 0xEA 0xE8 True True
- 0xEC 0xED True True
- 0xEE 0xDD True True
- 0xFB 0xEB True True
- 0xFD 0xFC True True
diff --git a/source/codepages/codepage_def.932 b/source/codepages/codepage_def.932
deleted file mode 100644
index 8d9ff631fba..00000000000
--- a/source/codepages/codepage_def.932
+++ /dev/null
@@ -1,24 +0,0 @@
-#
-# 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.
-#
-
-# Codepage definition file for IBM Code Page 932 - MS-DOS Japanese SJIS
-# defines lower->upper mapping.
-# Written by Jeremy Allison <jallison@whistle.com>
-
-# The columns are :
-# lower upper map upper to lower map lower to upper
-#
-# This file is intentionaly empty - no mappings are done. \ No newline at end of file
diff --git a/source/include/byteorder.h b/source/include/byteorder.h
index 4d972a5cac2..a55789a4036 100644
--- a/source/include/byteorder.h
+++ b/source/include/byteorder.h
@@ -88,32 +88,6 @@ it also defines lots of intermediate macros, just ignore those :-)
*/
-/* some switch macros that do both store and read to and from SMB buffers */
-
-#define RW_PCVAL(read,inbuf,outbuf,len) \
- if (read) { PCVAL (inbuf,0,outbuf,len) } \
- else { PSCVAL(inbuf,0,outbuf,len) }
-
-#define RW_PIVAL(read,inbuf,outbuf,len) \
- if (read) { PIVAL (inbuf,0,outbuf,len) } \
- else { PSIVAL(inbuf,0,outbuf,len) }
-
-#define RW_PSVAL(read,inbuf,outbuf,len) \
- if (read) { PSVAL (inbuf,0,outbuf,len) } \
- else { PSSVAL(inbuf,0,outbuf,len) }
-
-#define RW_CVAL(read, inbuf, outbuf, offset) \
- if (read) (outbuf) = CVAL (inbuf,offset); \
- else SCVAL(inbuf,offset,outbuf);
-
-#define RW_IVAL(read, inbuf, outbuf, offset) \
- if (read) (outbuf)= IVAL (inbuf,offset); \
- else SIVAL(inbuf,offset,outbuf);
-
-#define RW_SVAL(read, inbuf, outbuf, offset) \
- if (read) (outbuf)= SVAL (inbuf,offset); \
- else SSVAL(inbuf,offset,outbuf);
-
#undef CAREFUL_ALIGNMENT
/* we know that the 386 can handle misalignment and has the "right"
@@ -132,7 +106,6 @@ it also defines lots of intermediate macros, just ignore those :-)
#if CAREFUL_ALIGNMENT
-
#define SVAL(buf,pos) (PVAL(buf,pos)|PVAL(buf,(pos)+1)<<8)
#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
#define SSVALX(buf,pos,val) (CVAL(buf,pos)=(val)&0xFF,CVAL(buf,pos+1)=(val)>>8)
@@ -143,56 +116,24 @@ it also defines lots of intermediate macros, just ignore those :-)
#define SIVAL(buf,pos,val) SIVALX((buf),(pos),((uint32)(val)))
#define SSVALS(buf,pos,val) SSVALX((buf),(pos),((int16)(val)))
#define SIVALS(buf,pos,val) SIVALX((buf),(pos),((int32)(val)))
-
#else
-
/* this handles things for architectures like the 386 that can handle
alignment errors */
/*
WARNING: This section is dependent on the length of int16 and int32
being correct
*/
-
-/* get single value from an SMB buffer */
#define SVAL(buf,pos) (*(uint16 *)((char *)(buf) + (pos)))
#define IVAL(buf,pos) (*(uint32 *)((char *)(buf) + (pos)))
#define SVALS(buf,pos) (*(int16 *)((char *)(buf) + (pos)))
#define IVALS(buf,pos) (*(int32 *)((char *)(buf) + (pos)))
-
-/* store single value in an SMB buffer */
#define SSVAL(buf,pos,val) SVAL(buf,pos)=((uint16)(val))
#define SIVAL(buf,pos,val) IVAL(buf,pos)=((uint32)(val))
#define SSVALS(buf,pos,val) SVALS(buf,pos)=((int16)(val))
#define SIVALS(buf,pos,val) IVALS(buf,pos)=((int32)(val))
-
#endif
-/* macros for reading / writing arrays */
-
-#define SMBMACRO(macro,buf,pos,val,len,size) \
-{ int l; for (l = 0; l < (len); l++) (val)[l] = macro((buf), (pos) + (size)*l); }
-
-#define SSMBMACRO(macro,buf,pos,val,len,size) \
-{ int l; for (l = 0; l < (len); l++) macro((buf), (pos) + (size)*l, (val)[l]); }
-
-/* reads multiple data from an SMB buffer */
-#define PCVAL(buf,pos,val,len) SMBMACRO(CVAL,buf,pos,val,len,1)
-#define PSVAL(buf,pos,val,len) SMBMACRO(SVAL,buf,pos,val,len,2)
-#define PIVAL(buf,pos,val,len) SMBMACRO(IVAL,buf,pos,val,len,4)
-#define PCVALS(buf,pos,val,len) SMBMACRO(CVALS,buf,pos,val,len,1)
-#define PSVALS(buf,pos,val,len) SMBMACRO(SVALS,buf,pos,val,len,2)
-#define PIVALS(buf,pos,val,len) SMBMACRO(IVALS,buf,pos,val,len,4)
-
-/* stores multiple data in an SMB buffer */
-#define PSCVAL(buf,pos,val,len) SSMBMACRO(SCVAL,buf,pos,val,len,1)
-#define PSSVAL(buf,pos,val,len) SSMBMACRO(SSVAL,buf,pos,val,len,2)
-#define PSIVAL(buf,pos,val,len) SSMBMACRO(SIVAL,buf,pos,val,len,4)
-#define PSCVALS(buf,pos,val,len) SSMBMACRO(SCVALS,buf,pos,val,len,1)
-#define PSSVALS(buf,pos,val,len) SSMBMACRO(SSVALS,buf,pos,val,len,2)
-#define PSIVALS(buf,pos,val,len) SSMBMACRO(SIVALS,buf,pos,val,len,4)
-
-
/* now the reverse routines - these are used in nmb packets (mostly) */
#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
#define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
@@ -201,43 +142,3 @@ it also defines lots of intermediate macros, just ignore those :-)
#define RIVAL(buf,pos) IREV(IVAL(buf,pos))
#define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
#define RSIVAL(buf,pos,val) SIVAL(buf,pos,IREV(val))
-
-#define DBG_RW_PCVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
- RW_PCVAL(read,inbuf,outbuf,len) \
- DEBUG(5,("%s%04x %s: ", \
- tab_depth(depth), PTR_DIFF(inbuf,base),string)); \
- if (charmode) print_asc(5, (unsigned char*)(outbuf), (len)); else \
- { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%02x ", (outbuf)[idx])); } } \
- DEBUG(5,("\n"));
-
-#define DBG_RW_PSVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
- RW_PSVAL(read,inbuf,outbuf,len) \
- DEBUG(5,("%s%04x %s: ", \
- tab_depth(depth), PTR_DIFF(inbuf,base),string)); \
- if (charmode) print_asc(5, (unsigned char*)(outbuf), 2*(len)); else \
- { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%04x ", (outbuf)[idx])); } } \
- DEBUG(5,("\n"));
-
-#define DBG_RW_PIVAL(charmode,string,depth,base,read,inbuf,outbuf,len) \
- RW_PIVAL(read,inbuf,outbuf,len) \
- DEBUG(5,("%s%04x %s: ", \
- tab_depth(depth), PTR_DIFF(inbuf,base),string)); \
- if (charmode) print_asc(5, (unsigned char*)(outbuf), 4*(len)); else \
- { int idx; for (idx = 0; idx < len; idx++) { DEBUG(5,("%08x ", (outbuf)[idx])); } } \
- DEBUG(5,("\n"));
-
-#define DBG_RW_CVAL(string,depth,base,read,inbuf,outbuf) \
- RW_CVAL(read,inbuf,outbuf,0) \
- DEBUG(5,("%s%04x %s: %02x\n", \
- tab_depth(depth), PTR_DIFF(inbuf,base), string, outbuf));
-
-#define DBG_RW_SVAL(string,depth,base,read,inbuf,outbuf) \
- RW_SVAL(read,inbuf,outbuf,0) \
- DEBUG(5,("%s%04x %s: %04x\n", \
- tab_depth(depth), PTR_DIFF(inbuf,base), string, outbuf));
-
-#define DBG_RW_IVAL(string,depth,base,read,inbuf,outbuf) \
- RW_IVAL(read,inbuf,outbuf,0) \
- DEBUG(5,("%s%04x %s: %08x\n", \
- tab_depth(depth), PTR_DIFF(inbuf,base), string, outbuf));
-
diff --git a/source/include/charset.h b/source/include/charset.h
index fb184897c07..5f5e2016ee1 100644
--- a/source/include/charset.h
+++ b/source/include/charset.h
@@ -63,13 +63,3 @@ extern void charset_initialise(void);
#define issafe(c) (isalnum((c&0xff)) || strchr("-._",c))
#endif
-/* Dynamic codepage files defines. */
-
-/* Version id for dynamically loadable codepage files. */
-#define CODEPAGE_FILE_VERSION_ID 0x1
-/* Version 1 codepage file header size. */
-#define CODEPAGE_HEADER_SIZE 8
-/* Offsets for codepage file header entries. */
-#define CODEPAGE_VERSION_OFFSET 0
-#define CODEPAGE_CLIENT_CODEPAGE_OFFSET 2
-#define CODEPAGE_LENGTH_OFFSET 4
diff --git a/source/include/includes.h b/source/include/includes.h
index 6c2b676b312..4e48e87a7c1 100644
--- a/source/include/includes.h
+++ b/source/include/includes.h
@@ -214,6 +214,9 @@ Here come some platform specific sections
#include <string.h>
#include <sys/vfs.h>
#include <netinet/in.h>
+#ifndef NO_ASMSIGNALH
+#include <asm/signal.h>
+#endif
#ifdef GLIBC2
#define _LINUX_C_LIB_VERSION_MAJOR 6
#include <termios.h>
@@ -229,7 +232,6 @@ Here come some platform specific sections
#define HAVE_MEMMOVE
#define USE_SIGPROCMASK
#define USE_WAITPID
-#define USE_SYSV_IPC
#if 0
/* SETFS disabled until we can check on some bug reports */
#if _LINUX_C_LIB_VERSION_MAJOR >= 5
@@ -277,7 +279,6 @@ typedef unsigned short mode_t;
#ifndef USE_WAITPID
#define USE_WAITPID
#endif
-#define USE_SYSV_IPC
/* SunOS doesn't have POSIX atexit */
#define atexit on_exit
#endif
@@ -315,8 +316,6 @@ extern int innetgr (const char *, const char *, const char *, const char *);
#define USE_STATVFS
#define USE_GETCWD
#define USE_SETSID
-#define USE_SYSV_IPC
-#define NO_SEMUN
#ifndef REPLACE_GETPASS
#define REPLACE_GETPASS
#endif /* REPLACE_GETPASS */
@@ -341,7 +340,7 @@ char *getwd(char *);
#define USE_WAITPID
#endif
-#ifdef SGI4
+#ifdef SGI
#include <netinet/tcp.h>
#include <sys/statfs.h>
#include <string.h>
@@ -354,10 +353,9 @@ char *getwd(char *);
#define USE_WAITPID
#define USE_DIRECT
#define USE_SETSID
-#define USE_SYSV_IPC
#endif
-#if defined(SGI5) || defined(SGI6)
+#ifdef SGI5
#include <arpa/inet.h>
#include <netinet/tcp.h>
#include <netinet/in_systm.h>
@@ -375,7 +373,6 @@ char *getwd(char *);
#define USE_STATVFS
#define USE_WAITPID
#define USE_SETSID
-#define USE_SYSV_IPC
#endif
@@ -432,8 +429,6 @@ extern struct passwd *getpwnam();
#define USE_STATVFS
#define USE_GETCWD
#define USE_SETSID
-#define USE_SYSV_IPC
-#define NO_SEMUN
#endif
@@ -459,8 +454,6 @@ char *mktemp(char *); /* No standard include */
#define PASSWORD_LENGTH 16
#define NEED_AUTH_PARAMETERS
#endif /* OSF1_ENH_SEC */
-#define USE_SYSV_IPC
-#define NO_SEMUN
#endif
@@ -569,8 +562,6 @@ char *mktemp(char *); /* No standard include */
#define USE_GETCWD
#define USE_SETSID
#define USE_SETRES
-#define USE_SYSV_IPC
-#define NO_SEMUN
#define DEFAULT_PRINTING PRINT_HPUX
/* Ken Weiss <krweiss@ucdavis.edu> tells us that SIGCLD_IGNORE is
not good for HPUX */
@@ -684,7 +675,6 @@ char *mktemp(char *); /* No standard include */
#include <sys/netinet/ip.h>
#include <dirent.h>
#include <string.h>
-#include <termios.h>
#include <fcntl.h>
#include <sys/statfs.h>
#include <sys/stropts.h>
@@ -1073,35 +1063,6 @@ struct spwd { /* fake shadow password structure */
#endif
#endif
-/* This defines the name of the printcap file. It is MOST UNLIKELY that
- this will change BUT! Specifying a file with the format of a printcap
- file but containing only a subset of the printers actually in your real
- printcap file is a quick-n-dirty way to allow dynamic access to a subset
- of available printers.
-*/
-#ifndef PRINTCAP_NAME
-#ifdef AIX
-#define PRINTCAP_NAME "/etc/qconfig"
-#elif defined(SYSV)
-#define PRINTCAP_NAME "lpstat"
-#else
-#define PRINTCAP_NAME "/etc/printcap"
-#endif
-#endif
-
-
-#ifdef USE_SYSV_IPC
-#include <sys/ipc.h>
-#include <sys/sem.h>
-#include <sys/shm.h>
-#ifdef NO_SEMUN
-union semun {
- int val;
- struct semid_ds *buf;
- unsigned short *array;
-};
-#endif
-#endif
#ifdef AFS_AUTH
#include <afs/stds.h>
@@ -1142,32 +1103,26 @@ extern char *sys_errlist[];
#include "version.h"
#include "smb.h"
#include "nameserv.h"
-#include "ubiqx/ubi_dLinkList.h"
-
+#include "proto.h"
#include "byteorder.h"
#include "kanji.h"
#include "charset.h"
-/***** automatically generated prototypes *****/
-#include "proto.h"
-
-
-
#ifndef S_IFREG
#define S_IFREG 0100000
#endif
#ifndef S_ISREG
-#define S_ISREG(x) ((S_IFREG & (x))!=0)
+#define S_ISREG(x) ((S_IFREG & x)!=0)
#endif
#ifndef S_ISDIR
-#define S_ISDIR(x) ((S_IFDIR & (x))!=0)
+#define S_ISDIR(x) ((S_IFDIR & x)!=0)
#endif
#if !defined(S_ISLNK) && defined(S_IFLNK)
-#define S_ISLNK(x) ((S_IFLNK & (x))!=0)
+#define S_ISLNK(x) ((S_IFLNK & x)!=0)
#endif
#ifdef UFC_CRYPT
@@ -1241,13 +1196,9 @@ it works and getting lots of bug reports */
#define QSORT_CAST (int (*)())
#endif
-#ifndef INADDR_LOOPBACK
-#define INADDR_LOOPBACK 0x7f000001
-#endif /* INADDR_LOOPBACK */
-
/* this is a rough check to see if this machine has a lstat() call.
it is not guaranteed to work */
-#if !defined(S_ISLNK)
+#if !(defined(S_ISLNK) || defined(S_IFLNK))
#define lstat stat
#endif
@@ -1285,8 +1236,51 @@ extern int errno;
#define strcpy(dest,src) StrCpy(dest,src)
#endif
-#if MEM_MAN
-#include "mem_man/mem_man.h"
+
+/* possibly wrap the malloc calls */
+#if WRAP_MALLOC
+
+/* undo the old malloc def if necessary */
+#ifdef malloc
+#define xx_old_malloc malloc
+#undef malloc
+#endif
+
+#define malloc(size) malloc_wrapped(size,__FILE__,__LINE__)
+
+/* undo the old realloc def if necessary */
+#ifdef realloc
+#define xx_old_realloc realloc
+#undef realloc
+#endif
+
+#define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__)
+
+/* undo the old free def if necessary */
+#ifdef free
+#define xx_old_free free
+#undef free
+#endif
+
+#define free(ptr) free_wrapped(ptr,__FILE__,__LINE__)
+
+/* and the malloc prototypes */
+void *malloc_wrapped(int,char *,int);
+void *realloc_wrapped(void *,int,char *,int);
+void free_wrapped(void *,char *,int);
+
+#endif
+
+
+#if WRAP_MEMCPY
+/* undo the old memcpy def if necessary */
+#ifdef memcpy
+#define xx_old_memcpy memcpy
+#undef memcpy
+#endif
+
+#define memcpy(d,s,l) memcpy_wrapped(d,s,l,__FILE__,__LINE__)
+void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line);
#endif
#endif
diff --git a/source/include/kanji.h b/source/include/kanji.h
index 5e8173ee14c..865ac3b2c90 100644
--- a/source/include/kanji.h
+++ b/source/include/kanji.h
@@ -27,6 +27,8 @@
#ifndef _KANJI_H_
#define _KANJI_H_
+#ifdef KANJI
+
/* FOR SHIFT JIS CODE */
#define is_shift_jis(c) \
((0x81 <= ((unsigned char) (c)) && ((unsigned char) (c)) <= 0x9f) \
@@ -105,32 +107,16 @@
#else /* not _KANJI_C_ */
-extern char *(*_dos_to_unix)(char *str, BOOL overwrite);
-extern char *(*_unix_to_dos)(char *str, BOOL overwrite);
-
-/*
- * The following is needed for AIX systems that have
- * their own #defines for strchr, strrchr, strstr
- * and strtok.
- */
-
-#ifdef strchr
-#undef strchr
-#endif /* strchr */
-
-#ifdef strrchr
-#undef strrchr
-#endif /* strrchr */
+extern char* (*_dos_to_unix) (const char *str, BOOL overwrite);
+extern char* (*_unix_to_dos) (const char *str, BOOL overwrite);
-#ifdef strstr
-#undef strstr
-#endif /* strstr */
+#define unix_to_dos (*_unix_to_dos)
+#define dos_to_unix (*_dos_to_unix)
-#ifdef strtok
-#undef strtok
-#endif /* strtok */
-
-/* Ensure we use our definitions. */
+extern char *sj_strtok (char *s1, const char *s2);
+extern char *sj_strchr (const char *s, int c);
+extern char *sj_strrchr (const char *s, int c);
+extern char *sj_strstr (const char *s1, const char *s2);
#define strchr sj_strchr
#define strrchr sj_strrchr
@@ -149,7 +135,13 @@ extern char *(*_unix_to_dos)(char *str, BOOL overwrite);
#define CAP_CODE (6)
#define DOSV_CODE SJIS_CODE
+int interpret_coding_system (char *str, int def);
+
+#else
+
#define unix_to_dos(x,y) unix2dos_format(x,y)
#define dos_to_unix(x,y) dos2unix_format(x,y)
+#endif /* not KANJI */
+
#endif /* _KANJI_H_ */
diff --git a/source/include/local.h b/source/include/local.h
index 10906d1ff1e..92d566cf82d 100644
--- a/source/include/local.h
+++ b/source/include/local.h
@@ -17,20 +17,13 @@
refer to the special "printers" service */
#define PRINTERS_NAME "printers"
-/* this affects server level security. With this set (recommended)
- samba will do a full NetWkstaUserLogon to confirm that the client
- really should have login rights. This can cause problems with
- machines in trust relationships in which case you can disable it
- here, but be warned, we have heard that some NT machines will then
- allow anyone in with any password! Make sure you test it. */
-#ifndef USE_NETWKSTAUSERLOGON
-#define USE_NETWKSTAUSERLOGON 1
-#endif
-
-/* define what facility to use for syslog */
-#ifndef SYSLOG_FACILITY
-#define SYSLOG_FACILITY LOG_DAEMON
-#endif
+/* This defines the name of the printcap file. It is MOST UNLIKELY that
+ this will change BUT! Specifying a file with the format of a printcap
+ file but containing only a subset of the printers actually in your real
+ printcap file is a quick-n-dirty way to allow dynamic access to a subset
+ of available printers.
+*/
+#define PRINTCAP_NAME "/etc/printcap"
/* set these to define the limits of the server. NOTE These are on a
per-client basis. Thus any one machine can't connect to more than
@@ -82,12 +75,6 @@
manager window? */
#define FSTYPE_STRING "Samba"
-
-/* the default guest account - normally set in the Makefile or smb.conf */
-#ifndef GUEST_ACCOUNT
-#define GUEST_ACCOUNT "nobody"
-#endif
-
/* do you want smbd to send a 1 byte packet to nmbd to trigger it to start
when smbd starts? */
#ifndef PRIME_NMBD
@@ -168,18 +155,4 @@
/* the directory to sit in when idle */
/* #define IDLE_DIR "/" */
-/* Timout (in seconds) to wait for an oplock break
- message to return from the client. */
-
-#define OPLOCK_BREAK_TIMEOUT 30
-
-/* Timout (in seconds) to add to the oplock break timeout
- to wait for the smbd to smbd message to return. */
-
-#define OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR 2
-
-/* the read preciction code has been disabled until some problems with
- it are worked out */
-#define USE_READ_PREDICTION 0
-
#endif
diff --git a/source/include/nameserv.h b/source/include/nameserv.h
index 98a6cb330ac..b0409572ec8 100644
--- a/source/include/nameserv.h
+++ b/source/include/nameserv.h
@@ -1,5 +1,3 @@
-#ifndef _NAMESERV_H_
-#define _NAMESERV_H_
/*
Unix SMB/Netbios implementation.
Version 1.9.
@@ -22,7 +20,7 @@
*/
-#define PERMANENT_TTL 0
+#define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
/* NTAS uses 2, NT uses 1, WfWg uses 0 */
#define MAINTAIN_LIST 2
@@ -31,44 +29,18 @@
#define MAX_DGRAM_SIZE (576) /* tcp/ip datagram limit is 576 bytes */
#define MIN_DGRAM_SIZE 12
-/*********************************************************
- Types of reply packet.
-**********************************************************/
-
-enum netbios_reply_type_code { NMB_QUERY, NMB_STATUS, NMB_REG, NMB_REG_REFRESH,
- NMB_REL, NMB_WAIT_ACK, NMB_MULTIHOMED_REG,
- WINS_REG, WINS_QUERY };
-
-/* From rfc1002, 4.2.1.2 */
-/* Question types. */
-#define QUESTION_TYPE_NB_QUERY 0x20
-#define QUESTION_TYPE_NB_STATUS 0x21
-
-/* Question class */
-#define QUESTION_CLASS_IN 0x1
-
-/* Opcode definitions */
-#define NMB_NAME_QUERY_OPCODE 0x0
-#define NMB_NAME_REG_OPCODE 0x05 /* see rfc1002.txt 4.2.2,3,5,6,7,8 */
-#define NMB_NAME_RELEASE_OPCODE 0x06 /* see rfc1002.txt 4.2.9,10,11 */
-#define NMB_WACK_OPCODE 0x07 /* see rfc1002.txt 4.2.16 */
-/* Ambiguity in rfc1002 about which of these is correct. */
-/* WinNT uses 8 by default but can be made to use 9. */
-#define NMB_NAME_REFRESH_OPCODE_8 0x08 /* see rfc1002.txt 4.2.4 */
-#define NMB_NAME_REFRESH_OPCODE_9 0x09 /* see rfc1002.txt 4.2.4 */
-#define NMB_NAME_MULTIHOMED_REG_OPCODE 0x0F /* Invented by Microsoft. */
+#define NMB_QUERY 0x20
+#define NMB_STATUS 0x21
+#define NMB_REG 0x05 /* see rfc1002.txt 4.2.2,3,5,6,7,8 */
+#define NMB_REG_REFRESH 0x09 /* see rfc1002.txt 4.2.4 */
+#define NMB_REL 0x06 /* see rfc1002.txt 4.2.9,10,11 */
+#define NMB_WAIT_ACK 0x07 /* see rfc1002.txt 4.2.16 */
/* XXXX what about all the other types?? 0x1, 0x2, 0x3, 0x4, 0x8? */
-/* Resource record types. rfc1002 4.2.1.3 */
-#define RR_TYPE_A 0x1
-#define RR_TYPE_NS 0x2
-#define RR_TYPE_NULL 0xA
-#define RR_TYPE_NB 0x20
-#define RR_TYPE_NBSTAT 0x21
-
-/* Resource record class. */
-#define RR_CLASS_IN 0x1
+#define FIND_SELF 0x01
+#define FIND_WINS 0x02
+#define FIND_LOCAL 0x04
/* NetBIOS flags */
#define NB_GROUP 0x80
@@ -76,300 +48,205 @@ enum netbios_reply_type_code { NMB_QUERY, NMB_STATUS, NMB_REG, NMB_REG_REFRESH,
#define NB_ACTIVE 0x04
#define NB_CONFL 0x08
#define NB_DEREG 0x10
-#define NB_BFLAG 0x00 /* Broadcast node type. */
-#define NB_PFLAG 0x20 /* Point-to-point node type. */
-#define NB_MFLAG 0x40 /* Mixed bcast & p-p node type. */
-#define NB_HFLAG 0x60 /* Microsoft 'hybrid' node type. */
-#define NB_NODETYPEMASK 0x60
-/* Mask applied to outgoing NetBIOS flags. */
-#define NB_FLGMSK 0xE0
-
-/* NetBIOS flag identifier. */
-#define NAME_GROUP(p) ((p)->nb_flags & NB_GROUP)
-#define NAME_BFLAG(p) (((p)->nb_flags & NB_NODETYPEMASK) == NB_BFLAG)
-#define NAME_PFLAG(p) (((p)->nb_flags & NB_NODETYPEMASK) == NB_PFLAG)
-#define NAME_MFLAG(p) (((p)->nb_flags & NB_NODETYPEMASK) == NB_MFLAG)
-#define NAME_HFLAG(p) (((p)->nb_flags & NB_NODETYPEMASK) == NB_HFLAG)
-
-/* Samba name state for a name in a namelist. */
-#define NAME_IS_ACTIVE(p) ((p)->nb_flags & NB_ACTIVE)
-#define NAME_IN_CONFLICT(p) ((p)->nb_flags & NB_CONFL)
-#define NAME_IS_DEREGISTERING(p) ((p)->nb_flags & NB_DEREG)
-
-/* Error codes for NetBIOS requests. */
-#define FMT_ERR 0x1 /* Packet format error. */
-#define SRV_ERR 0x2 /* Internal server error. */
-#define NAM_ERR 0x3 /* Name does not exist. */
-#define IMP_ERR 0x4 /* Request not implemented. */
-#define RFS_ERR 0x5 /* Request refused. */
-#define ACT_ERR 0x6 /* Active error - name owned by another host. */
-#define CFT_ERR 0x7 /* Name in conflict error. */
+#define NB_BFLAG 0x00 /* broadcast node type */
+#define NB_PFLAG 0x20 /* point-to-point node type */
+#define NB_MFLAG 0x40 /* mixed bcast & p-p node type */
+#define NB_HFLAG 0x60 /* microsoft 'hybrid' node type */
+#define NB_FLGMSK 0x60
#define REFRESH_TIME (15*60)
#define NAME_POLL_REFRESH_TIME (5*60)
#define NAME_POLL_INTERVAL 15
-/* Workgroup state identifiers. */
-#define AM_POTENTIAL_MASTER_BROWSER(work) ((work)->mst_state == MST_POTENTIAL)
-#define AM_LOCAL_MASTER_BROWSER(work) ((work)->mst_state == MST_BROWSER)
-#define AM_DOMAIN_MASTER_BROWSER(work) ((work)->dom_state == DOMAIN_MST)
-#define AM_DOMAIN_MEMBER(work) ((work)->log_state == LOGON_SRV)
-
-/* Microsoft browser NetBIOS name. */
+/* NetBIOS flag identifier */
+#define NAME_PERMANENT(p) ((p) & NB_PERM)
+#define NAME_ACTIVE(p) ((p) & NB_ACTIVE)
+#define NAME_CONFLICT(p) ((p) & NB_CONFL)
+#define NAME_DEREG(p) ((p) & NB_DEREG)
+#define NAME_GROUP(p) ((p) & NB_GROUP)
+
+#define NAME_BFLAG(p) (((p) & NB_FLGMSK) == NB_BFLAG)
+#define NAME_PFLAG(p) (((p) & NB_FLGMSK) == NB_PFLAG)
+#define NAME_MFLAG(p) (((p) & NB_FLGMSK) == NB_MFLAG)
+#define NAME_HFLAG(p) (((p) & NB_FLGMSK) == NB_HFLAG)
+
+/* server type identifiers */
+#define AM_MASTER(work) (work->ServerType & SV_TYPE_MASTER_BROWSER)
+#define AM_BACKUP(work) (work->ServerType & SV_TYPE_BACKUP_BROWSER)
+#define AM_DOMMST(work) (work->ServerType & SV_TYPE_DOMAIN_MASTER)
+#define AM_DOMMEM(work) (work->ServerType & SV_TYPE_DOMAIN_MEMBER)
+
+/* microsoft browser NetBIOS name */
#define MSBROWSE "\001\002__MSBROWSE__\002"
-/* Mail slots. */
+/* mail slots */
#define BROWSE_MAILSLOT "\\MAILSLOT\\BROWSE"
#define NET_LOGON_MAILSLOT "\\MAILSLOT\\NET\\NETLOGON"
-#define NT_LOGON_MAILSLOT "\\MAILSLOT\\NET\\NTLOGON"
-#define LANMAN_MAILSLOT "\\MAILSLOT\\LANMAN"
-
-/* Samba definitions for find_name_on_subnet(). */
-#define FIND_ANY_NAME 0
-#define FIND_SELF_NAME 1
-
-/*
- * The different name types that can be in namelists.
- *
- * SELF_NAME should only be on the broadcast and unicast subnets.
- * LMHOSTS_NAME should only be in the remote_broadcast_subnet.
- * REGISTER_NAME, DNS_NAME, DNSFAIL_NAME should only be in the wins_server_subnet.
- * WINS_PROXY_NAME should only be on the broadcast subnets.
- * PERMANENT_NAME can be on all subnets except remote_broadcast_subnet.
- *
- */
-
-enum name_source {LMHOSTS_NAME, REGISTER_NAME, SELF_NAME, DNS_NAME,
- DNSFAIL_NAME, PERMANENT_NAME, WINS_PROXY_NAME};
+
+enum name_source {STATUS_QUERY, LMHOSTS, REGISTER, SELF, DNS, DNSFAIL};
enum node_type {B_NODE=0, P_NODE=1, M_NODE=2, NBDD_NODE=3};
enum packet_type {NMB_PACKET, DGRAM_PACKET};
enum master_state
{
- MST_NONE,
- MST_POTENTIAL,
- MST_BACKUP,
- MST_MSB,
- MST_BROWSER,
- MST_UNBECOMING_MASTER
+ MST_POTENTIAL,
+ MST_BACK,
+ MST_MSB,
+ MST_BROWSER
};
enum domain_state
{
- DOMAIN_NONE,
- DOMAIN_WAIT,
- DOMAIN_MST
+ DOMAIN_NONE,
+ DOMAIN_WAIT,
+ DOMAIN_MST
};
enum logon_state
{
- LOGON_NONE,
- LOGON_WAIT,
- LOGON_SRV
+ LOGON_NONE,
+ LOGON_WAIT,
+ LOGON_SRV
};
-/* A netbios name structure. */
+enum state_type
+{
+ NAME_STATUS_DOM_SRV_CHK,
+ NAME_STATUS_SRV_CHK,
+ NAME_REGISTER_CHALLENGE,
+ NAME_REGISTER,
+ NAME_RELEASE,
+ NAME_QUERY_CONFIRM,
+ NAME_QUERY_SYNC_LOCAL,
+ NAME_QUERY_SYNC_REMOTE,
+ NAME_QUERY_DOM_SRV_CHK,
+ NAME_QUERY_SRV_CHK,
+ NAME_QUERY_FIND_MST,
+ NAME_QUERY_MST_CHK,
+ NAME_QUERY_DOMAIN
+};
+
+/* a netbios name structure */
struct nmb_name {
char name[17];
char scope[64];
- unsigned int name_type;
+ int name_type;
+};
+
+/* a netbios flags + ip address structure */
+/* this is used for multi-homed systems and for internet group names */
+struct nmb_ip
+{
+ struct in_addr ip; /* ip address of host that owns this name */
+ uint16 nb_flags; /* netbios flags */
};
-/* This is the structure used for the local netbios name list. */
+/* this is the structure used for the local netbios name list */
struct name_record
{
struct name_record *next;
struct name_record *prev;
- struct subnet_record *subnet;
+ struct nmb_name name; /* the netbios name */
+ struct nmb_ip *ip_flgs; /* the ip + flags */
+ int num_ips; /* number of ip+flags entries */
- struct nmb_name name; /* The netbios name. */
- uint16 nb_flags; /* Netbios flags. */
- int num_ips; /* Number of ip entries. */
- struct in_addr *ip; /* The ip list for this name. */
+ enum name_source source; /* where the name came from */
- enum name_source source; /* Where the name came from. */
-
- time_t death_time; /* The time the record must be removed (do not remove if 0). */
- time_t refresh_time; /* The time the record should be refreshed. */
+ time_t death_time; /* time record must be removed (do not remove if 0) */
+ time_t refresh_time; /* time record should be refreshed */
};
struct subnet_record;
-/* Browser cache for synchronising browse lists. */
+/* browse and backup server cache for synchronising browse list */
struct browse_cache_record
{
- struct browse_cache_record *next;
- struct browse_cache_record *prev;
-
- pstring lmb_name;
- pstring work_group;
- struct in_addr ip;
- time_t sync_time;
- time_t death_time; /* The time the record must be removed. */
+ struct browse_cache_record *next;
+ struct browse_cache_record *prev;
+
+ pstring name;
+ int type;
+ pstring group;
+ struct in_addr ip;
+ time_t sync_time;
+ BOOL synced;
+ BOOL local;
+ struct subnet_record *subnet;
};
-/* This is used to hold the list of servers in my domain, and is
- contained within lists of domains. */
-
+/* this is used to hold the list of servers in my domain, and is */
+/* contained within lists of domains */
struct server_record
{
struct server_record *next;
struct server_record *prev;
- struct subnet_record *subnet;
-
struct server_info_struct serv;
time_t death_time;
};
-/* A workgroup structure. It contains a list of servers. */
+/* a workgroup structure. it contains a list of servers */
struct work_record
{
struct work_record *next;
struct work_record *prev;
- struct subnet_record *subnet;
-
struct server_record *serverlist;
- /* Stage of development from non-local-master up to local-master browser. */
+ /* stage of development from non-local-master up to local-master browser */
enum master_state mst_state;
- /* Stage of development from non-domain-master to domain-master browser. */
+ /* stage of development from non-domain-master to domain master browser */
enum domain_state dom_state;
- /* Stage of development from non-logon-server to logon server. */
+ /* stage of development from non-logon-server to logon server */
enum logon_state log_state;
- /* Work group info. */
+ /* work group info */
fstring work_group;
- int token; /* Used when communicating with backup browsers. */
- fstring local_master_browser_name; /* Current local master browser. */
+ int token; /* used when communicating with backup browsers */
+ int ServerType;
- /* Announce info. */
+ /* announce info */
time_t lastannounce_time;
int announce_interval;
BOOL needannounce;
- /* Timeout time for this workgroup. 0 means permanent. */
- time_t death_time;
- /* Election info */
+ /* election info */
BOOL RunningElection;
BOOL needelection;
int ElectionCount;
uint32 ElectionCriterion;
-
- /* Domain master browser info. Used for efficient syncs. */
- struct nmb_name dmb_name;
- struct in_addr dmb_addr;
};
-/* typedefs needed to define copy & free functions for userdata. */
-struct userdata_struct;
-
-typedef struct userdata_struct * (*userdata_copy_fn)(struct userdata_struct *);
-typedef void (*userdata_free_fn)(struct userdata_struct *);
-
-/* Structure to define any userdata passed around. */
-
-struct userdata_struct {
- userdata_copy_fn copy_fn;
- userdata_free_fn free_fn;
- unsigned int userdata_len;
- char data[1];
-};
-
-struct response_record;
-struct packet_struct;
-struct res_rec;
-
-/* typedef to define the function called when this response packet comes in. */
-typedef void (*response_function)(struct subnet_record *, struct response_record *,
- struct packet_struct *);
-
-/* typedef to define the function called when this response record times out. */
-typedef void (*timeout_response_function)(struct subnet_record *,
- struct response_record *);
-
-/* typedef to define the function called when the request that caused this
- response record to be created is successful. */
-typedef void (*success_function)(struct subnet_record *, struct userdata_struct *, ...);
-
-/* typedef to define the function called when the request that caused this
- response record to be created is unsuccessful. */
-typedef void (*fail_function)(struct subnet_record *, struct response_record *, ...);
-
-/* List of typedefs for success and fail functions of the different query
- types. Used to catch any compile time prototype errors. */
-
-typedef void (*register_name_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct nmb_name *,
- uint16,
- int,
- struct in_addr);
-typedef void (*register_name_fail_function)( struct subnet_record *,
- struct response_record *,
- struct nmb_name *);
-
-typedef void (*release_name_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct nmb_name *,
- struct in_addr);
-typedef void (*release_name_fail_function)( struct subnet_record *,
- struct response_record *,
- struct nmb_name *);
-
-typedef void (*refresh_name_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct nmb_name *,
- uint16,
- int,
- struct in_addr);
-typedef void (*refresh_name_fail_function)( struct subnet_record *,
- struct response_record *,
- struct nmb_name *);
-
-typedef void (*query_name_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct nmb_name *,
- struct in_addr,
- struct res_rec *answers);
-
-typedef void (*query_name_fail_function)( struct subnet_record *,
- struct response_record *,
- struct nmb_name *,
- int);
-
-typedef void (*node_status_success_function)( struct subnet_record *,
- struct userdata_struct *,
- struct res_rec *,
- struct in_addr);
-typedef void (*node_status_fail_function)( struct subnet_record *,
- struct response_record *);
-
-/* Initiated name queries are recorded in this list to track any responses. */
-
+/* initiated name queries recorded in this list to track any responses... */
+/* sadly, we need to group everything together. i suppose that if this
+ gets unwieldy, then a union ought to be considered. oh for c++... */
struct response_record
{
struct response_record *next;
struct response_record *prev;
uint16 response_id;
+ enum state_type state;
- /* Callbacks for packets received or not. */
- response_function resp_fn;
- timeout_response_function timeout_fn;
+ int fd;
+ int quest_type;
+ struct nmb_name name;
+ int nb_flags;
+ time_t ttl;
- /* Callbacks for the request succeeding or not. */
- success_function success_fn;
- fail_function fail_fn;
-
- struct packet_struct *packet;
+ int server_type;
+ fstring my_name;
+ fstring my_comment;
- struct userdata_struct *userdata;
+ BOOL bcast;
+ BOOL recurse;
+ struct in_addr send_ip;
+ struct in_addr reply_to_ip;
+ int reply_id;
int num_msgs;
@@ -378,44 +255,44 @@ struct response_record
int repeat_count;
};
-/* A subnet structure. It contains a list of workgroups and netbios names. */
+/* a subnet structure. it contains a list of workgroups and netbios names*/
+
+/* note that a subnet of 255.255.255.255 contains all the WINS netbios names.
+ all communication from such nodes are on a non-broadcast basis: they
+ are point-to-point (P nodes) or mixed point-to-point and broadcast
+ (M nodes). M nodes use point-to-point as a preference, and will use
+ broadcasting for certain activities, or will resort to broadcasting as a
+ last resort, if the WINS server fails (users of wfwg will notice that their
+ machine often freezes for 30 seconds at a time intermittently, if the WINS
+ server is down).
-/*
B nodes will have their own, totally separate subnet record, with their
- own netbios name set. These do NOT interact with other subnet records'
- netbios names.
+ own netbios name set. these do NOT interact with other subnet records'
+ netbios names, INCLUDING the WINS one (with an ip "address", so called,
+ of 255.255.255.255)
+
+ there is a separate response list for each subnet record. in the case of
+ the 255.255.255.255 subnet record (WINS), the WINS server will be able to
+ use this to poll (infrequently!) each of its entries, to ensure that the
+ names are still in use.
+ XXXX this polling is a planned feature for a really over-cautious WINS server
*/
-enum subnet_type {
- NORMAL_SUBNET = 0, /* Subnet listed in interfaces list. */
- UNICAST_SUBNET = 1, /* Subnet for unicast packets. */
- REMOTE_BROADCAST_SUBNET = 2, /* Subnet for remote broadcasts. */
- WINS_SERVER_SUBNET = 3 /* Only created if we are a WINS server. */
-};
-
struct subnet_record
{
struct subnet_record *next;
struct subnet_record *prev;
- char *subnet_name; /* For Debug identification. */
- enum subnet_type type; /* To catagorize the subnet. */
-
- struct work_record *workgrouplist; /* List of workgroups. */
- struct name_record *namelist; /* List of netbios names. */
- struct response_record *responselist; /* List of responses expected. */
-
- BOOL namelist_changed;
- BOOL work_changed;
+ struct work_record *workgrouplist; /* list of workgroups */
+ struct name_record *namelist; /* list of netbios names */
+ struct response_record *responselist; /* list of responses expected */
struct in_addr bcast_ip;
struct in_addr mask_ip;
struct in_addr myip;
- int nmb_sock; /* socket to listen for unicast 137. */
- int dgram_sock; /* socket to listen for unicast 138. */
};
-/* A resource record. */
+/* a resource record */
struct res_rec {
struct nmb_name rr_name;
int rr_type;
@@ -425,7 +302,7 @@ struct res_rec {
char rdata[MAX_DGRAM_SIZE];
};
-/* An nmb packet. */
+/* define a nmb packet. */
struct nmb_packet
{
struct {
@@ -458,8 +335,7 @@ struct nmb_packet
};
-/* A datagram - this normally contains SMB data in the data[] array. */
-
+/* a datagram - this normally contains SMB data in the data[] array */
struct dgram_packet {
struct {
int msg_type;
@@ -480,14 +356,12 @@ struct dgram_packet {
char data[MAX_DGRAM_SIZE];
};
-/* Define a structure used to queue packets. This will be a linked
- list of nmb packets. */
-
+/* define a structure used to queue packets. this will be a linked
+ list of nmb packets */
struct packet_struct
{
struct packet_struct *next;
struct packet_struct *prev;
- BOOL locked;
struct in_addr ip;
int port;
int fd;
@@ -499,16 +373,8 @@ struct packet_struct
} packet;
};
-/* NETLOGON opcodes */
-
-#define QUERYFORPDC 7 /* Query for PDC. */
-#define QUERYFORPDC_R 12 /* Response to Query for PDC. */
-#define SAMLOGON 18
-#define SAMLOGON_R 19
-
-
-/* Ids for netbios packet types. */
+/* ids for netbios packet types */
#define ANN_HostAnnouncement 1
#define ANN_AnnouncementRequest 2
#define ANN_Election 8
@@ -521,48 +387,42 @@ struct packet_struct
#define ANN_LocalMasterAnnouncement 15
-/* Broadcast packet announcement intervals, in minutes. */
+/* broadcast packet announcement intervals, in minutes */
-/* Attempt to add domain logon and domain master names. */
+/* attempt to add domain logon and domain master names */
#define CHECK_TIME_ADD_DOM_NAMES 5
-/* Search for master browsers of workgroups samba knows about,
- except default. */
+/* search for master browsers of workgroups samba knows about,
+ except default */
#define CHECK_TIME_MST_BROWSE 5
-/* Request backup browser announcements from other servers. */
+/* request backup browser announcements from other servers */
#define CHECK_TIME_ANNOUNCE_BACKUP 15
-/* Request host announcements from other servers: min and max of interval. */
+/* request host announcements from other servers: min and max of interval */
#define CHECK_TIME_MIN_HOST_ANNCE 3
#define CHECK_TIME_MAX_HOST_ANNCE 12
-/* Announce as master to WINS server and any Primary Domain Controllers. */
+/* announce as master to WINS server and any Primary Domain Controllers */
#define CHECK_TIME_MST_ANNOUNCE 15
-/* Time between syncs from domain master browser to local master browsers. */
-#define CHECK_TIME_DMB_TO_LMB_SYNC 15
-
-/* Do all remote announcements this often. */
+/* do all remote announcements this often */
#define REMOTE_ANNOUNCE_INTERVAL 180
-/* Types of machine we can announce as. */
+/* Types of machine we can announce as */
#define ANNOUNCE_AS_NT 1
#define ANNOUNCE_AS_WIN95 2
#define ANNOUNCE_AS_WFW 3
/* Macro's to enumerate subnets either with or without
- the UNICAST subnet. */
+ the WINS subnet. */
extern struct subnet_record *subnetlist;
-extern struct subnet_record *unicast_subnet;
-extern struct subnet_record *wins_server_subnet;
-extern struct subnet_record *remote_broadcast_subnet;
+extern struct subnet_record *wins_subnet;
#define FIRST_SUBNET subnetlist
-#define NEXT_SUBNET_EXCLUDING_UNICAST(x) ((x)->next)
-#define NEXT_SUBNET_INCLUDING_UNICAST(x) (get_next_subnet_maybe_unicast((x)))
+#define NEXT_SUBNET_EXCLUDING_WINS(x) ((x)->next)
+#define NEXT_SUBNET_INCLUDING_WINS(x) ( ((x) == wins_subnet) ? NULL : \
+ (((x)->next == NULL) ? wins_subnet : \
+ (x)->next))
-/* To be removed. */
-enum state_type { TEST };
-#endif /* _NAMESERV_H_ */
diff --git a/source/include/nterr.h b/source/include/nterr.h
deleted file mode 100644
index 92f02612dbc..00000000000
--- a/source/include/nterr.h
+++ /dev/null
@@ -1,505 +0,0 @@
-/* these are the NT error codes less than 1000. They are here for when
- we start supporting NT error codes in Samba. They were extracted
- using a loop in smbclient then printing a netmon sniff to a file */
-
-#define NT_STATUS_UNSUCCESSFUL (1)
-#define NT_STATUS_NOT_IMPLEMENTED (2)
-#define NT_STATUS_INVALID_INFO_CLASS (3)
-#define NT_STATUS_INFO_LENGTH_MISMATCH (4)
-#define NT_STATUS_ACCESS_VIOLATION (5)
-#define NT_STATUS_IN_PAGE_ERROR (6)
-#define NT_STATUS_PAGEFILE_QUOTA (7)
-#define NT_STATUS_INVALID_HANDLE (8)
-#define NT_STATUS_BAD_INITIAL_STACK (9)
-#define NT_STATUS_BAD_INITIAL_PC (10)
-#define NT_STATUS_INVALID_CID (11)
-#define NT_STATUS_TIMER_NOT_CANCELED (12)
-#define NT_STATUS_INVALID_PARAMETER (13)
-#define NT_STATUS_NO_SUCH_DEVICE (14)
-#define NT_STATUS_NO_SUCH_FILE (15)
-#define NT_STATUS_INVALID_DEVICE_REQUEST (16)
-#define NT_STATUS_END_OF_FILE (17)
-#define NT_STATUS_WRONG_VOLUME (18)
-#define NT_STATUS_NO_MEDIA_IN_DEVICE (19)
-#define NT_STATUS_UNRECOGNIZED_MEDIA (20)
-#define NT_STATUS_NONEXISTENT_SECTOR (21)
-#define NT_STATUS_MORE_PROCESSING_REQUIRED (22)
-#define NT_STATUS_NO_MEMORY (23)
-#define NT_STATUS_CONFLICTING_ADDRESSES (24)
-#define NT_STATUS_NOT_MAPPED_VIEW (25)
-#define NT_STATUS_UNABLE_TO_FREE_VM (26)
-#define NT_STATUS_UNABLE_TO_DELETE_SECTION (27)
-#define NT_STATUS_INVALID_SYSTEM_SERVICE (28)
-#define NT_STATUS_ILLEGAL_INSTRUCTION (29)
-#define NT_STATUS_INVALID_LOCK_SEQUENCE (30)
-#define NT_STATUS_INVALID_VIEW_SIZE (31)
-#define NT_STATUS_INVALID_FILE_FOR_SECTION (32)
-#define NT_STATUS_ALREADY_COMMITTED (33)
-#define NT_STATUS_ACCESS_DENIED (34)
-#define NT_STATUS_BUFFER_TOO_SMALL (35)
-#define NT_STATUS_OBJECT_TYPE_MISMATCH (36)
-#define NT_STATUS_NONCONTINUABLE_EXCEPTION (37)
-#define NT_STATUS_INVALID_DISPOSITION (38)
-#define NT_STATUS_UNWIND (39)
-#define NT_STATUS_BAD_STACK (40)
-#define NT_STATUS_INVALID_UNWIND_TARGET (41)
-#define NT_STATUS_NOT_LOCKED (42)
-#define NT_STATUS_PARITY_ERROR (43)
-#define NT_STATUS_UNABLE_TO_DECOMMIT_VM (44)
-#define NT_STATUS_NOT_COMMITTED (45)
-#define NT_STATUS_INVALID_PORT_ATTRIBUTES (46)
-#define NT_STATUS_PORT_MESSAGE_TOO_LONG (47)
-#define NT_STATUS_INVALID_PARAMETER_MIX (48)
-#define NT_STATUS_INVALID_QUOTA_LOWER (49)
-#define NT_STATUS_DISK_CORRUPT_ERROR (50)
-#define NT_STATUS_OBJECT_NAME_INVALID (51)
-#define NT_STATUS_OBJECT_NAME_NOT_FOUND (52)
-#define NT_STATUS_OBJECT_NAME_COLLISION (53)
-#define NT_STATUS_HANDLE_NOT_WAITABLE (54)
-#define NT_STATUS_PORT_DISCONNECTED (55)
-#define NT_STATUS_DEVICE_ALREADY_ATTACHED (56)
-#define NT_STATUS_OBJECT_PATH_INVALID (57)
-#define NT_STATUS_OBJECT_PATH_NOT_FOUND (58)
-#define NT_STATUS_OBJECT_PATH_SYNTAX_BAD (59)
-#define NT_STATUS_DATA_OVERRUN (60)
-#define NT_STATUS_DATA_LATE_ERROR (61)
-#define NT_STATUS_DATA_ERROR (62)
-#define NT_STATUS_CRC_ERROR (63)
-#define NT_STATUS_SECTION_TOO_BIG (64)
-#define NT_STATUS_PORT_CONNECTION_REFUSED (65)
-#define NT_STATUS_INVALID_PORT_HANDLE (66)
-#define NT_STATUS_SHARING_VIOLATION (67)
-#define NT_STATUS_QUOTA_EXCEEDED (68)
-#define NT_STATUS_INVALID_PAGE_PROTECTION (69)
-#define NT_STATUS_MUTANT_NOT_OWNED (70)
-#define NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED (71)
-#define NT_STATUS_PORT_ALREADY_SET (72)
-#define NT_STATUS_SECTION_NOT_IMAGE (73)
-#define NT_STATUS_SUSPEND_COUNT_EXCEEDED (74)
-#define NT_STATUS_THREAD_IS_TERMINATING (75)
-#define NT_STATUS_BAD_WORKING_SET_LIMIT (76)
-#define NT_STATUS_INCOMPATIBLE_FILE_MAP (77)
-#define NT_STATUS_SECTION_PROTECTION (78)
-#define NT_STATUS_EAS_NOT_SUPPORTED (79)
-#define NT_STATUS_EA_TOO_LARGE (80)
-#define NT_STATUS_NONEXISTENT_EA_ENTRY (81)
-#define NT_STATUS_NO_EAS_ON_FILE (82)
-#define NT_STATUS_EA_CORRUPT_ERROR (83)
-#define NT_STATUS_FILE_LOCK_CONFLICT (84)
-#define NT_STATUS_LOCK_NOT_GRANTED (85)
-#define NT_STATUS_DELETE_PENDING (86)
-#define NT_STATUS_CTL_FILE_NOT_SUPPORTED (87)
-#define NT_STATUS_UNKNOWN_REVISION (88)
-#define NT_STATUS_REVISION_MISMATCH (89)
-#define NT_STATUS_INVALID_OWNER (90)
-#define NT_STATUS_INVALID_PRIMARY_GROUP (91)
-#define NT_STATUS_NO_IMPERSONATION_TOKEN (92)
-#define NT_STATUS_CANT_DISABLE_MANDATORY (93)
-#define NT_STATUS_NO_LOGON_SERVERS (94)
-#define NT_STATUS_NO_SUCH_LOGON_SESSION (95)
-#define NT_STATUS_NO_SUCH_PRIVILEGE (96)
-#define NT_STATUS_PRIVILEGE_NOT_HELD (97)
-#define NT_STATUS_INVALID_ACCOUNT_NAME (98)
-#define NT_STATUS_USER_EXISTS (99)
-#define NT_STATUS_NO_SUCH_USER (100)
-#define NT_STATUS_GROUP_EXISTS (101)
-#define NT_STATUS_NO_SUCH_GROUP (102)
-#define NT_STATUS_MEMBER_IN_GROUP (103)
-#define NT_STATUS_MEMBER_NOT_IN_GROUP (104)
-#define NT_STATUS_LAST_ADMIN (105)
-#define NT_STATUS_WRONG_PASSWORD (106)
-#define NT_STATUS_ILL_FORMED_PASSWORD (107)
-#define NT_STATUS_PASSWORD_RESTRICTION (108)
-#define NT_STATUS_LOGON_FAILURE (109)
-#define NT_STATUS_ACCOUNT_RESTRICTION (110)
-#define NT_STATUS_INVALID_LOGON_HOURS (111)
-#define NT_STATUS_INVALID_WORKSTATION (112)
-#define NT_STATUS_PASSWORD_EXPIRED (113)
-#define NT_STATUS_ACCOUNT_DISABLED (114)
-#define NT_STATUS_NONE_MAPPED (115)
-#define NT_STATUS_TOO_MANY_LUIDS_REQUESTED (116)
-#define NT_STATUS_LUIDS_EXHAUSTED (117)
-#define NT_STATUS_INVALID_SUB_AUTHORITY (118)
-#define NT_STATUS_INVALID_ACL (119)
-#define NT_STATUS_INVALID_SID (120)
-#define NT_STATUS_INVALID_SECURITY_DESCR (121)
-#define NT_STATUS_PROCEDURE_NOT_FOUND (122)
-#define NT_STATUS_INVALID_IMAGE_FORMAT (123)
-#define NT_STATUS_NO_TOKEN (124)
-#define NT_STATUS_BAD_INHERITANCE_ACL (125)
-#define NT_STATUS_RANGE_NOT_LOCKED (126)
-#define NT_STATUS_DISK_FULL (127)
-#define NT_STATUS_SERVER_DISABLED (128)
-#define NT_STATUS_SERVER_NOT_DISABLED (129)
-#define NT_STATUS_TOO_MANY_GUIDS_REQUESTED (130)
-#define NT_STATUS_GUIDS_EXHAUSTED (131)
-#define NT_STATUS_INVALID_ID_AUTHORITY (132)
-#define NT_STATUS_AGENTS_EXHAUSTED (133)
-#define NT_STATUS_INVALID_VOLUME_LABEL (134)
-#define NT_STATUS_SECTION_NOT_EXTENDED (135)
-#define NT_STATUS_NOT_MAPPED_DATA (136)
-#define NT_STATUS_RESOURCE_DATA_NOT_FOUND (137)
-#define NT_STATUS_RESOURCE_TYPE_NOT_FOUND (138)
-#define NT_STATUS_RESOURCE_NAME_NOT_FOUND (139)
-#define NT_STATUS_ARRAY_BOUNDS_EXCEEDED (140)
-#define NT_STATUS_FLOAT_DENORMAL_OPERAND (141)
-#define NT_STATUS_FLOAT_DIVIDE_BY_ZERO (142)
-#define NT_STATUS_FLOAT_INEXACT_RESULT (143)
-#define NT_STATUS_FLOAT_INVALID_OPERATION (144)
-#define NT_STATUS_FLOAT_OVERFLOW (145)
-#define NT_STATUS_FLOAT_STACK_CHECK (146)
-#define NT_STATUS_FLOAT_UNDERFLOW (147)
-#define NT_STATUS_INTEGER_DIVIDE_BY_ZERO (148)
-#define NT_STATUS_INTEGER_OVERFLOW (149)
-#define NT_STATUS_PRIVILEGED_INSTRUCTION (150)
-#define NT_STATUS_TOO_MANY_PAGING_FILES (151)
-#define NT_STATUS_FILE_INVALID (152)
-#define NT_STATUS_ALLOTTED_SPACE_EXCEEDED (153)
-#define NT_STATUS_INSUFFICIENT_RESOURCES (154)
-#define NT_STATUS_DFS_EXIT_PATH_FOUND (155)
-#define NT_STATUS_DEVICE_DATA_ERROR (156)
-#define NT_STATUS_DEVICE_NOT_CONNECTED (157)
-#define NT_STATUS_DEVICE_POWER_FAILURE (158)
-#define NT_STATUS_FREE_VM_NOT_AT_BASE (159)
-#define NT_STATUS_MEMORY_NOT_ALLOCATED (160)
-#define NT_STATUS_WORKING_SET_QUOTA (161)
-#define NT_STATUS_MEDIA_WRITE_PROTECTED (162)
-#define NT_STATUS_DEVICE_NOT_READY (163)
-#define NT_STATUS_INVALID_GROUP_ATTRIBUTES (164)
-#define NT_STATUS_BAD_IMPERSONATION_LEVEL (165)
-#define NT_STATUS_CANT_OPEN_ANONYMOUS (166)
-#define NT_STATUS_BAD_VALIDATION_CLASS (167)
-#define NT_STATUS_BAD_TOKEN_TYPE (168)
-#define NT_STATUS_BAD_MASTER_BOOT_RECORD (169)
-#define NT_STATUS_INSTRUCTION_MISALIGNMENT (170)
-#define NT_STATUS_INSTANCE_NOT_AVAILABLE (171)
-#define NT_STATUS_PIPE_NOT_AVAILABLE (172)
-#define NT_STATUS_INVALID_PIPE_STATE (173)
-#define NT_STATUS_PIPE_BUSY (174)
-#define NT_STATUS_ILLEGAL_FUNCTION (175)
-#define NT_STATUS_PIPE_DISCONNECTED (176)
-#define NT_STATUS_PIPE_CLOSING (177)
-#define NT_STATUS_PIPE_CONNECTED (178)
-#define NT_STATUS_PIPE_LISTENING (179)
-#define NT_STATUS_INVALID_READ_MODE (180)
-#define NT_STATUS_IO_TIMEOUT (181)
-#define NT_STATUS_FILE_FORCED_CLOSED (182)
-#define NT_STATUS_PROFILING_NOT_STARTED (183)
-#define NT_STATUS_PROFILING_NOT_STOPPED (184)
-#define NT_STATUS_COULD_NOT_INTERPRET (185)
-#define NT_STATUS_FILE_IS_A_DIRECTORY (186)
-#define NT_STATUS_NOT_SUPPORTED (187)
-#define NT_STATUS_REMOTE_NOT_LISTENING (188)
-#define NT_STATUS_DUPLICATE_NAME (189)
-#define NT_STATUS_BAD_NETWORK_PATH (190)
-#define NT_STATUS_NETWORK_BUSY (191)
-#define NT_STATUS_DEVICE_DOES_NOT_EXIST (192)
-#define NT_STATUS_TOO_MANY_COMMANDS (193)
-#define NT_STATUS_ADAPTER_HARDWARE_ERROR (194)
-#define NT_STATUS_INVALID_NETWORK_RESPONSE (195)
-#define NT_STATUS_UNEXPECTED_NETWORK_ERROR (196)
-#define NT_STATUS_BAD_REMOTE_ADAPTER (197)
-#define NT_STATUS_PRINT_QUEUE_FULL (198)
-#define NT_STATUS_NO_SPOOL_SPACE (199)
-#define NT_STATUS_PRINT_CANCELLED (200)
-#define NT_STATUS_NETWORK_NAME_DELETED (201)
-#define NT_STATUS_NETWORK_ACCESS_DENIED (202)
-#define NT_STATUS_BAD_DEVICE_TYPE (203)
-#define NT_STATUS_BAD_NETWORK_NAME (204)
-#define NT_STATUS_TOO_MANY_NAMES (205)
-#define NT_STATUS_TOO_MANY_SESSIONS (206)
-#define NT_STATUS_SHARING_PAUSED (207)
-#define NT_STATUS_REQUEST_NOT_ACCEPTED (208)
-#define NT_STATUS_REDIRECTOR_PAUSED (209)
-#define NT_STATUS_NET_WRITE_FAULT (210)
-#define NT_STATUS_PROFILING_AT_LIMIT (211)
-#define NT_STATUS_NOT_SAME_DEVICE (212)
-#define NT_STATUS_FILE_RENAMED (213)
-#define NT_STATUS_VIRTUAL_CIRCUIT_CLOSED (214)
-#define NT_STATUS_NO_SECURITY_ON_OBJECT (215)
-#define NT_STATUS_CANT_WAIT (216)
-#define NT_STATUS_PIPE_EMPTY (217)
-#define NT_STATUS_CANT_ACCESS_DOMAIN_INFO (218)
-#define NT_STATUS_CANT_TERMINATE_SELF (219)
-#define NT_STATUS_INVALID_SERVER_STATE (220)
-#define NT_STATUS_INVALID_DOMAIN_STATE (221)
-#define NT_STATUS_INVALID_DOMAIN_ROLE (222)
-#define NT_STATUS_NO_SUCH_DOMAIN (223)
-#define NT_STATUS_DOMAIN_EXISTS (224)
-#define NT_STATUS_DOMAIN_LIMIT_EXCEEDED (225)
-#define NT_STATUS_OPLOCK_NOT_GRANTED (226)
-#define NT_STATUS_INVALID_OPLOCK_PROTOCOL (227)
-#define NT_STATUS_INTERNAL_DB_CORRUPTION (228)
-#define NT_STATUS_INTERNAL_ERROR (229)
-#define NT_STATUS_GENERIC_NOT_MAPPED (230)
-#define NT_STATUS_BAD_DESCRIPTOR_FORMAT (231)
-#define NT_STATUS_INVALID_USER_BUFFER (232)
-#define NT_STATUS_UNEXPECTED_IO_ERROR (233)
-#define NT_STATUS_UNEXPECTED_MM_CREATE_ERR (234)
-#define NT_STATUS_UNEXPECTED_MM_MAP_ERROR (235)
-#define NT_STATUS_UNEXPECTED_MM_EXTEND_ERR (236)
-#define NT_STATUS_NOT_LOGON_PROCESS (237)
-#define NT_STATUS_LOGON_SESSION_EXISTS (238)
-#define NT_STATUS_INVALID_PARAMETER_1 (239)
-#define NT_STATUS_INVALID_PARAMETER_2 (240)
-#define NT_STATUS_INVALID_PARAMETER_3 (241)
-#define NT_STATUS_INVALID_PARAMETER_4 (242)
-#define NT_STATUS_INVALID_PARAMETER_5 (243)
-#define NT_STATUS_INVALID_PARAMETER_6 (244)
-#define NT_STATUS_INVALID_PARAMETER_7 (245)
-#define NT_STATUS_INVALID_PARAMETER_8 (246)
-#define NT_STATUS_INVALID_PARAMETER_9 (247)
-#define NT_STATUS_INVALID_PARAMETER_10 (248)
-#define NT_STATUS_INVALID_PARAMETER_11 (249)
-#define NT_STATUS_INVALID_PARAMETER_12 (250)
-#define NT_STATUS_REDIRECTOR_NOT_STARTED (251)
-#define NT_STATUS_REDIRECTOR_STARTED (252)
-#define NT_STATUS_STACK_OVERFLOW (253)
-#define NT_STATUS_NO_SUCH_PACKAGE (254)
-#define NT_STATUS_BAD_FUNCTION_TABLE (255)
-#define NT_STATUS_DIRECTORY_NOT_EMPTY (257)
-#define NT_STATUS_FILE_CORRUPT_ERROR (258)
-#define NT_STATUS_NOT_A_DIRECTORY (259)
-#define NT_STATUS_BAD_LOGON_SESSION_STATE (260)
-#define NT_STATUS_LOGON_SESSION_COLLISION (261)
-#define NT_STATUS_NAME_TOO_LONG (262)
-#define NT_STATUS_FILES_OPEN (263)
-#define NT_STATUS_CONNECTION_IN_USE (264)
-#define NT_STATUS_MESSAGE_NOT_FOUND (265)
-#define NT_STATUS_PROCESS_IS_TERMINATING (266)
-#define NT_STATUS_INVALID_LOGON_TYPE (267)
-#define NT_STATUS_NO_GUID_TRANSLATION (268)
-#define NT_STATUS_CANNOT_IMPERSONATE (269)
-#define NT_STATUS_IMAGE_ALREADY_LOADED (270)
-#define NT_STATUS_ABIOS_NOT_PRESENT (271)
-#define NT_STATUS_ABIOS_LID_NOT_EXIST (272)
-#define NT_STATUS_ABIOS_LID_ALREADY_OWNED (273)
-#define NT_STATUS_ABIOS_NOT_LID_OWNER (274)
-#define NT_STATUS_ABIOS_INVALID_COMMAND (275)
-#define NT_STATUS_ABIOS_INVALID_LID (276)
-#define NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE (277)
-#define NT_STATUS_ABIOS_INVALID_SELECTOR (278)
-#define NT_STATUS_NO_LDT (279)
-#define NT_STATUS_INVALID_LDT_SIZE (280)
-#define NT_STATUS_INVALID_LDT_OFFSET (281)
-#define NT_STATUS_INVALID_LDT_DESCRIPTOR (282)
-#define NT_STATUS_INVALID_IMAGE_NE_FORMAT (283)
-#define NT_STATUS_RXACT_INVALID_STATE (284)
-#define NT_STATUS_RXACT_COMMIT_FAILURE (285)
-#define NT_STATUS_MAPPED_FILE_SIZE_ZERO (286)
-#define NT_STATUS_TOO_MANY_OPENED_FILES (287)
-#define NT_STATUS_CANCELLED (288)
-#define NT_STATUS_CANNOT_DELETE (289)
-#define NT_STATUS_INVALID_COMPUTER_NAME (290)
-#define NT_STATUS_FILE_DELETED (291)
-#define NT_STATUS_SPECIAL_ACCOUNT (292)
-#define NT_STATUS_SPECIAL_GROUP (293)
-#define NT_STATUS_SPECIAL_USER (294)
-#define NT_STATUS_MEMBERS_PRIMARY_GROUP (295)
-#define NT_STATUS_FILE_CLOSED (296)
-#define NT_STATUS_TOO_MANY_THREADS (297)
-#define NT_STATUS_THREAD_NOT_IN_PROCESS (298)
-#define NT_STATUS_TOKEN_ALREADY_IN_USE (299)
-#define NT_STATUS_PAGEFILE_QUOTA_EXCEEDED (300)
-#define NT_STATUS_COMMITMENT_LIMIT (301)
-#define NT_STATUS_INVALID_IMAGE_LE_FORMAT (302)
-#define NT_STATUS_INVALID_IMAGE_NOT_MZ (303)
-#define NT_STATUS_INVALID_IMAGE_PROTECT (304)
-#define NT_STATUS_INVALID_IMAGE_WIN_16 (305)
-#define NT_STATUS_LOGON_SERVER_CONFLICT (306)
-#define NT_STATUS_TIME_DIFFERENCE_AT_DC (307)
-#define NT_STATUS_SYNCHRONIZATION_REQUIRED (308)
-#define NT_STATUS_DLL_NOT_FOUND (309)
-#define NT_STATUS_OPEN_FAILED (310)
-#define NT_STATUS_IO_PRIVILEGE_FAILED (311)
-#define NT_STATUS_ORDINAL_NOT_FOUND (312)
-#define NT_STATUS_ENTRYPOINT_NOT_FOUND (313)
-#define NT_STATUS_CONTROL_C_EXIT (314)
-#define NT_STATUS_LOCAL_DISCONNECT (315)
-#define NT_STATUS_REMOTE_DISCONNECT (316)
-#define NT_STATUS_REMOTE_RESOURCES (317)
-#define NT_STATUS_LINK_FAILED (318)
-#define NT_STATUS_LINK_TIMEOUT (319)
-#define NT_STATUS_INVALID_CONNECTION (320)
-#define NT_STATUS_INVALID_ADDRESS (321)
-#define NT_STATUS_DLL_INIT_FAILED (322)
-#define NT_STATUS_MISSING_SYSTEMFILE (323)
-#define NT_STATUS_UNHANDLED_EXCEPTION (324)
-#define NT_STATUS_APP_INIT_FAILURE (325)
-#define NT_STATUS_PAGEFILE_CREATE_FAILED (326)
-#define NT_STATUS_NO_PAGEFILE (327)
-#define NT_STATUS_INVALID_LEVEL (328)
-#define NT_STATUS_WRONG_PASSWORD_CORE (329)
-#define NT_STATUS_ILLEGAL_FLOAT_CONTEXT (330)
-#define NT_STATUS_PIPE_BROKEN (331)
-#define NT_STATUS_REGISTRY_CORRUPT (332)
-#define NT_STATUS_REGISTRY_IO_FAILED (333)
-#define NT_STATUS_NO_EVENT_PAIR (334)
-#define NT_STATUS_UNRECOGNIZED_VOLUME (335)
-#define NT_STATUS_SERIAL_NO_DEVICE_INITED (336)
-#define NT_STATUS_NO_SUCH_ALIAS (337)
-#define NT_STATUS_MEMBER_NOT_IN_ALIAS (338)
-#define NT_STATUS_MEMBER_IN_ALIAS (339)
-#define NT_STATUS_ALIAS_EXISTS (340)
-#define NT_STATUS_LOGON_NOT_GRANTED (341)
-#define NT_STATUS_TOO_MANY_SECRETS (342)
-#define NT_STATUS_SECRET_TOO_LONG (343)
-#define NT_STATUS_INTERNAL_DB_ERROR (344)
-#define NT_STATUS_FULLSCREEN_MODE (345)
-#define NT_STATUS_TOO_MANY_CONTEXT_IDS (346)
-#define NT_STATUS_LOGON_TYPE_NOT_GRANTED (347)
-#define NT_STATUS_NOT_REGISTRY_FILE (348)
-#define NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED (349)
-#define NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR (350)
-#define NT_STATUS_FT_MISSING_MEMBER (351)
-#define NT_STATUS_ILL_FORMED_SERVICE_ENTRY (352)
-#define NT_STATUS_ILLEGAL_CHARACTER (353)
-#define NT_STATUS_UNMAPPABLE_CHARACTER (354)
-#define NT_STATUS_UNDEFINED_CHARACTER (355)
-#define NT_STATUS_FLOPPY_VOLUME (356)
-#define NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND (357)
-#define NT_STATUS_FLOPPY_WRONG_CYLINDER (358)
-#define NT_STATUS_FLOPPY_UNKNOWN_ERROR (359)
-#define NT_STATUS_FLOPPY_BAD_REGISTERS (360)
-#define NT_STATUS_DISK_RECALIBRATE_FAILED (361)
-#define NT_STATUS_DISK_OPERATION_FAILED (362)
-#define NT_STATUS_DISK_RESET_FAILED (363)
-#define NT_STATUS_SHARED_IRQ_BUSY (364)
-#define NT_STATUS_FT_ORPHANING (365)
-#define NT_STATUS_PARTITION_FAILURE (370)
-#define NT_STATUS_INVALID_BLOCK_LENGTH (371)
-#define NT_STATUS_DEVICE_NOT_PARTITIONED (372)
-#define NT_STATUS_UNABLE_TO_LOCK_MEDIA (373)
-#define NT_STATUS_UNABLE_TO_UNLOAD_MEDIA (374)
-#define NT_STATUS_EOM_OVERFLOW (375)
-#define NT_STATUS_NO_MEDIA (376)
-#define NT_STATUS_NO_SUCH_MEMBER (378)
-#define NT_STATUS_INVALID_MEMBER (379)
-#define NT_STATUS_KEY_DELETED (380)
-#define NT_STATUS_NO_LOG_SPACE (381)
-#define NT_STATUS_TOO_MANY_SIDS (382)
-#define NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED (383)
-#define NT_STATUS_KEY_HAS_CHILDREN (384)
-#define NT_STATUS_CHILD_MUST_BE_VOLATILE (385)
-#define NT_STATUS_DEVICE_CONFIGURATION_ERROR (386)
-#define NT_STATUS_DRIVER_INTERNAL_ERROR (387)
-#define NT_STATUS_INVALID_DEVICE_STATE (388)
-#define NT_STATUS_IO_DEVICE_ERROR (389)
-#define NT_STATUS_DEVICE_PROTOCOL_ERROR (390)
-#define NT_STATUS_BACKUP_CONTROLLER (391)
-#define NT_STATUS_LOG_FILE_FULL (392)
-#define NT_STATUS_TOO_LATE (393)
-#define NT_STATUS_NO_TRUST_LSA_SECRET (394)
-#define NT_STATUS_NO_TRUST_SAM_ACCOUNT (395)
-#define NT_STATUS_TRUSTED_DOMAIN_FAILURE (396)
-#define NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE (397)
-#define NT_STATUS_EVENTLOG_FILE_CORRUPT (398)
-#define NT_STATUS_EVENTLOG_CANT_START (399)
-#define NT_STATUS_TRUST_FAILURE (400)
-#define NT_STATUS_MUTANT_LIMIT_EXCEEDED (401)
-#define NT_STATUS_NETLOGON_NOT_STARTED (402)
-#define NT_STATUS_ACCOUNT_EXPIRED (403)
-#define NT_STATUS_POSSIBLE_DEADLOCK (404)
-#define NT_STATUS_NETWORK_CREDENTIAL_CONFLICT (405)
-#define NT_STATUS_REMOTE_SESSION_LIMIT (406)
-#define NT_STATUS_EVENTLOG_FILE_CHANGED (407)
-#define NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT (408)
-#define NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT (409)
-#define NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT (410)
-#define NT_STATUS_DOMAIN_TRUST_INCONSISTENT (411)
-#define NT_STATUS_FS_DRIVER_REQUIRED (412)
-#define NT_STATUS_NO_USER_SESSION_KEY (514)
-#define NT_STATUS_USER_SESSION_DELETED (515)
-#define NT_STATUS_RESOURCE_LANG_NOT_FOUND (516)
-#define NT_STATUS_INSUFF_SERVER_RESOURCES (517)
-#define NT_STATUS_INVALID_BUFFER_SIZE (518)
-#define NT_STATUS_INVALID_ADDRESS_COMPONENT (519)
-#define NT_STATUS_INVALID_ADDRESS_WILDCARD (520)
-#define NT_STATUS_TOO_MANY_ADDRESSES (521)
-#define NT_STATUS_ADDRESS_ALREADY_EXISTS (522)
-#define NT_STATUS_ADDRESS_CLOSED (523)
-#define NT_STATUS_CONNECTION_DISCONNECTED (524)
-#define NT_STATUS_CONNECTION_RESET (525)
-#define NT_STATUS_TOO_MANY_NODES (526)
-#define NT_STATUS_TRANSACTION_ABORTED (527)
-#define NT_STATUS_TRANSACTION_TIMED_OUT (528)
-#define NT_STATUS_TRANSACTION_NO_RELEASE (529)
-#define NT_STATUS_TRANSACTION_NO_MATCH (530)
-#define NT_STATUS_TRANSACTION_RESPONDED (531)
-#define NT_STATUS_TRANSACTION_INVALID_ID (532)
-#define NT_STATUS_TRANSACTION_INVALID_TYPE (533)
-#define NT_STATUS_NOT_SERVER_SESSION (534)
-#define NT_STATUS_NOT_CLIENT_SESSION (535)
-#define NT_STATUS_CANNOT_LOAD_REGISTRY_FILE (536)
-#define NT_STATUS_DEBUG_ATTACH_FAILED (537)
-#define NT_STATUS_SYSTEM_PROCESS_TERMINATED (538)
-#define NT_STATUS_DATA_NOT_ACCEPTED (539)
-#define NT_STATUS_NO_BROWSER_SERVERS_FOUND (540)
-#define NT_STATUS_VDM_HARD_ERROR (541)
-#define NT_STATUS_DRIVER_CANCEL_TIMEOUT (542)
-#define NT_STATUS_REPLY_MESSAGE_MISMATCH (543)
-#define NT_STATUS_MAPPED_ALIGNMENT (544)
-#define NT_STATUS_IMAGE_CHECKSUM_MISMATCH (545)
-#define NT_STATUS_LOST_WRITEBEHIND_DATA (546)
-#define NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID (547)
-#define NT_STATUS_PASSWORD_MUST_CHANGE (548)
-#define NT_STATUS_NOT_FOUND (549)
-#define NT_STATUS_NOT_TINY_STREAM (550)
-#define NT_STATUS_RECOVERY_FAILURE (551)
-#define NT_STATUS_STACK_OVERFLOW_READ (552)
-#define NT_STATUS_FAIL_CHECK (553)
-#define NT_STATUS_DUPLICATE_OBJECTID (554)
-#define NT_STATUS_OBJECTID_EXISTS (555)
-#define NT_STATUS_CONVERT_TO_LARGE (556)
-#define NT_STATUS_RETRY (557)
-#define NT_STATUS_FOUND_OUT_OF_SCOPE (558)
-#define NT_STATUS_ALLOCATE_BUCKET (559)
-#define NT_STATUS_PROPSET_NOT_FOUND (560)
-#define NT_STATUS_MARSHALL_OVERFLOW (561)
-#define NT_STATUS_INVALID_VARIANT (562)
-#define NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND (563)
-#define NT_STATUS_ACCOUNT_LOCKED_OUT (564)
-#define NT_STATUS_HANDLE_NOT_CLOSABLE (565)
-#define NT_STATUS_CONNECTION_REFUSED (566)
-#define NT_STATUS_GRACEFUL_DISCONNECT (567)
-#define NT_STATUS_ADDRESS_ALREADY_ASSOCIATED (568)
-#define NT_STATUS_ADDRESS_NOT_ASSOCIATED (569)
-#define NT_STATUS_CONNECTION_INVALID (570)
-#define NT_STATUS_CONNECTION_ACTIVE (571)
-#define NT_STATUS_NETWORK_UNREACHABLE (572)
-#define NT_STATUS_HOST_UNREACHABLE (573)
-#define NT_STATUS_PROTOCOL_UNREACHABLE (574)
-#define NT_STATUS_PORT_UNREACHABLE (575)
-#define NT_STATUS_REQUEST_ABORTED (576)
-#define NT_STATUS_CONNECTION_ABORTED (577)
-#define NT_STATUS_BAD_COMPRESSION_BUFFER (578)
-#define NT_STATUS_USER_MAPPED_FILE (579)
-#define NT_STATUS_AUDIT_FAILED (580)
-#define NT_STATUS_TIMER_RESOLUTION_NOT_SET (581)
-#define NT_STATUS_CONNECTION_COUNT_LIMIT (582)
-#define NT_STATUS_LOGIN_TIME_RESTRICTION (583)
-#define NT_STATUS_LOGIN_WKSTA_RESTRICTION (584)
-#define NT_STATUS_IMAGE_MP_UP_MISMATCH (585)
-#define NT_STATUS_INSUFFICIENT_LOGON_INFO (592)
-#define NT_STATUS_BAD_DLL_ENTRYPOINT (593)
-#define NT_STATUS_BAD_SERVICE_ENTRYPOINT (594)
-#define NT_STATUS_LPC_REPLY_LOST (595)
-#define NT_STATUS_IP_ADDRESS_CONFLICT1 (596)
-#define NT_STATUS_IP_ADDRESS_CONFLICT2 (597)
-#define NT_STATUS_REGISTRY_QUOTA_LIMIT (598)
-#define NT_STATUS_PATH_NOT_COVERED (599)
-#define NT_STATUS_NO_CALLBACK_ACTIVE (600)
-#define NT_STATUS_LICENSE_QUOTA_EXCEEDED (601)
-#define NT_STATUS_PWD_TOO_SHORT (602)
-#define NT_STATUS_PWD_TOO_RECENT (603)
-#define NT_STATUS_PWD_HISTORY_CONFLICT (604)
-#define NT_STATUS_PLUGPLAY_NO_DEVICE (606)
-#define NT_STATUS_UNSUPPORTED_COMPRESSION (607)
-#define NT_STATUS_INVALID_HW_PROFILE (608)
-#define NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH (609)
-#define NT_STATUS_DRIVER_ORDINAL_NOT_FOUND (610)
-#define NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND (611)
-#define NT_STATUS_RESOURCE_NOT_OWNED (612)
-#define NT_STATUS_TOO_MANY_LINKS (613)
-#define NT_STATUS_QUOTA_LIST_INCONSISTENT (614)
-#define NT_STATUS_FILE_IS_OFFLINE (615)
diff --git a/source/include/proto.h b/source/include/proto.h
index a3fd1d1f0f2..6fb2e88d92c 100644
--- a/source/include/proto.h
+++ b/source/include/proto.h
@@ -6,28 +6,6 @@
BOOL check_access(int snum);
BOOL allow_access(char *deny_list,char *allow_list,char *cname,char *caddr);
-/*The following definitions come from asyncdns.c */
-
-int asyncdns_fd(void);
-void start_async_dns(void);
-void run_dns_queue(void);
-BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
- struct name_record **n);
-BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
- struct name_record **n);
-
-/*The following definitions come from cgi.c */
-
-void cgi_load_variables(FILE *f1);
-char *cgi_variable(char *name);
-char *cgi_vnum(int i, char **name);
-int cgi_boolean(char *name, int def);
-char *quotedup(char *s);
-char *urlquote(char *s);
-char *quotequotes(char *s);
-void quote_spaces(char *buf);
-void cgi_setup(char *rootdir);
-
/*The following definitions come from charcnv.c */
char *unix2dos_format(char *str,BOOL overwrite);
@@ -48,76 +26,40 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass);
/*The following definitions come from client.c */
-void cli_smb_close(char *inbuf, char *outbuf, int clnt_fd, int c_num, int f_num);
+void setup_pkt(char *outbuf);
void do_dir(char *inbuf,char *outbuf,char *Mask,int attribute,void (*fn)(),BOOL recurse_dir);
void cmd_help(void);
+BOOL reopen_connection(char *inbuf,char *outbuf);
+char *smb_errstr(char *inbuf);
/*The following definitions come from clientgen.c */
BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation);
-BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
- void (*fn)(char *, uint32, char *));
BOOL cli_session_setup(struct cli_state *cli,
char *user,
char *pass, int passlen,
char *ntpass, int ntpasslen,
char *workgroup);
BOOL cli_send_tconX(struct cli_state *cli,
- char *share, char *dev, char *pass, int passlen);
+ char *share, char *dev, char *pword, int passlen);
BOOL cli_tdis(struct cli_state *cli);
-BOOL cli_mv(struct cli_state *cli, char *fname_src, char *fname_dst);
-BOOL cli_unlink(struct cli_state *cli, char *fname);
-BOOL cli_mkdir(struct cli_state *cli, char *dname);
-BOOL cli_rmdir(struct cli_state *cli, char *dname);
-int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode);
-BOOL cli_close(struct cli_state *cli, int fnum);
-BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout);
-BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout);
-int cli_read(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size);
-int cli_write(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size);
-BOOL cli_getatr(struct cli_state *cli, char *fname,
- int *attr, uint32 *size, time_t *t);
-BOOL cli_setatr(struct cli_state *cli, char *fname, int attr, time_t t);
-BOOL cli_qpathinfo(struct cli_state *cli, char *fname,
- time_t *c_time, time_t *a_time, time_t *m_time, uint32 *size);
-BOOL cli_qpathinfo2(struct cli_state *cli, char *fname,
- time_t *c_time, time_t *a_time, time_t *m_time,
- time_t *w_time, uint32 *size);
-BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
- time_t *c_time, time_t *a_time, time_t *m_time, uint32 *size);
BOOL cli_negprot(struct cli_state *cli);
BOOL cli_session_request(struct cli_state *cli, char *host, int name_type,
char *myname);
BOOL cli_connect(struct cli_state *cli, char *host, struct in_addr *ip);
BOOL cli_initialise(struct cli_state *cli);
void cli_shutdown(struct cli_state *cli);
-char *cli_errstr(struct cli_state *cli);
-void cli_error(struct cli_state *cli, int *eclass, int *num);
-void cli_sockopt(struct cli_state *cli, char *options);
-int cli_setpid(struct cli_state *cli, int pid);
/*The following definitions come from clientutil.c */
-void cli_setup_pkt(char *outbuf);
-BOOL cli_call_api(char *pipe_name, int pipe_name_len,
- int prcnt,int drcnt, int srcnt,
- int mprcnt,int mdrcnt,
- int *rprcnt,int *rdrcnt,
- char *param,char *data, uint16 *setup,
- char **rparam,char **rdata);
-BOOL cli_receive_trans_response(char *inbuf,int trans,
- int *data_len,int *param_len,
- char **data,char **param);
-BOOL cli_send_trans_request(char *outbuf,int trans,
- char *name,int namelen, int fid,int flags,
- char *data,char *param,uint16 *setup,
- int ldata,int lparam,int lsetup,
- int mdata,int mparam,int msetup);
-BOOL cli_send_session_request(char *inbuf,char *outbuf);
-BOOL cli_send_login(char *inbuf,char *outbuf,BOOL start_session,BOOL use_setup);
-void cli_send_logout(void );
-BOOL cli_open_sockets(int port );
+BOOL cli_send_login(char *inbuf, char *outbuf, BOOL start_session, BOOL use_setup);
+void cli_send_logout(void);
+BOOL cli_call_api(int prcnt,int drcnt,int mprcnt,int mdrcnt,int *rprcnt,
+ int *rdrcnt, char *param,char *data,
+ char **rparam, char **rdata);
+BOOL cli_open_sockets(int port);
BOOL cli_reopen_connection(char *inbuf,char *outbuf);
+char *smb_errstr(char *inbuf);
/*The following definitions come from clitar.c */
@@ -130,21 +72,6 @@ int process_tar(char *inbuf, char *outbuf);
int clipfind(char **aret, int ret, char *tok);
int tar_parseargs(int argc, char *argv[], char *Optarg, int Optind);
-/*The following definitions come from credentials.c */
-
-char *credstr(uchar *cred);
-void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass,
- uchar session_key[8]);
-void cred_create(uchar session_key[8], DOM_CHAL *stor_cred, UTIME timestamp,
- DOM_CHAL *cred);
-int cred_assert(DOM_CHAL *cred, uchar session_key[8], DOM_CHAL *stored_cred,
- UTIME timestamp);
-BOOL clnt_deal_with_creds(uchar sess_key[8],
- DOM_CRED *sto_clnt_cred, DOM_CRED *rcv_srv_cred);
-BOOL deal_with_creds(uchar sess_key[8],
- DOM_CRED *sto_clnt_cred,
- DOM_CRED *rcv_clnt_cred, DOM_CRED *rtn_srv_cred);
-
/*The following definitions come from dir.c */
void init_dptrs(void);
@@ -169,9 +96,9 @@ void CloseDir(void *p);
char *ReadDirName(void *p);
BOOL SeekDir(void *p,int pos);
int TellDir(void *p);
-void DirCacheAdd( char *path, char *name, char *dname, int snum );
-char *DirCacheCheck( char *path, char *name, int snum );
-void DirCacheFlush( int snum );
+void DirCacheAdd(char *path,char *name,char *dname,int snum);
+char *DirCacheCheck(char *path,char *name,int snum);
+void DirCacheFlush(int snum);
/*The following definitions come from fault.c */
@@ -187,10 +114,7 @@ void load_interfaces(void);
void iface_set_default(char *ip,char *bcast,char *nmask);
BOOL ismyip(struct in_addr ip);
BOOL ismybcast(struct in_addr bcast);
-BOOL is_local_net(struct in_addr from);
int iface_count(void);
-BOOL we_are_multihomed();
-struct interface *get_interface(int n);
struct in_addr *iface_n_ip(int n);
struct in_addr *iface_bcast(struct in_addr ip);
struct in_addr *iface_nmask(struct in_addr ip);
@@ -198,16 +122,11 @@ struct in_addr *iface_ip(struct in_addr ip);
/*The following definitions come from ipc.c */
-int get_printerdrivernumber(int snum);
-int reply_trans(char *inbuf,char *outbuf, int size, int bufsize);
+int reply_trans(char *inbuf,char *outbuf);
/*The following definitions come from kanji.c */
-char *sj_strtok(char *s1, char *s2);
-char *sj_strstr(char *s1, char *s2);
-char *sj_strchr (char *s, int c);
-char *sj_strrchr(char *s, int c);
-int interpret_coding_system(char *str);
+int interpret_coding_system(char *str, int def);
/*The following definitions come from loadparm.c */
@@ -229,12 +148,11 @@ char *lp_passwd_program(void);
char *lp_passwd_chat(void);
char *lp_passwordserver(void);
char *lp_workgroup(void);
+char *lp_domain_controller(void);
char *lp_username_map(void);
char *lp_character_set(void);
char *lp_logon_script(void);
char *lp_logon_path(void);
-char *lp_logon_drive(void);
-char *lp_logon_home(void);
char *lp_remote_announce(void);
char *lp_remote_browse_sync(void);
char *lp_wins_server(void);
@@ -243,20 +161,10 @@ char *lp_socket_address(void);
char *lp_nis_home_map_name(void);
char *lp_announce_version(void);
char *lp_netbios_aliases(void);
-char *lp_driverfile(void);
-char *lp_domain_sid(void);
-char *lp_domain_other_sids(void);
-char *lp_domain_groups(void);
-char *lp_domain_admin_users(void);
-char *lp_domain_guest_users(void);
-char *lp_domain_hostsallow(void);
-char *lp_domain_hostsdeny(void);
BOOL lp_dns_proxy(void);
BOOL lp_wins_support(void);
-BOOL lp_we_are_a_wins_server(void);
BOOL lp_wins_proxy(void);
BOOL lp_local_master(void);
-BOOL lp_domain_controller(void);
BOOL lp_domain_master(void);
BOOL lp_domain_logons(void);
BOOL lp_preferred_master(void);
@@ -275,11 +183,8 @@ BOOL lp_browse_list(void);
BOOL lp_unix_realname(void);
BOOL lp_nis_home_map(void);
BOOL lp_time_server(void);
-BOOL lp_bind_interfaces_only(void);
int lp_os_level(void);
int lp_max_ttl(void);
-int lp_max_wins_ttl(void);
-int lp_min_wins_ttl(void);
int lp_max_log_size(void);
int lp_mangledstack(void);
int lp_maxxmit(void);
@@ -287,19 +192,18 @@ int lp_maxmux(void);
int lp_maxpacket(void);
int lp_keepalive(void);
int lp_passwordlevel(void);
-int lp_usernamelevel(void);
int lp_readsize(void);
int lp_shmem_size(void);
+int lp_shmem_hash_size(void);
int lp_deadtime(void);
int lp_maxprotocol(void);
int lp_security(void);
+int lp_printing(void);
int lp_maxdisksize(void);
int lp_lpqcachetime(void);
int lp_syslog(void);
int lp_client_code_page(void);
int lp_announce_as(void);
-int lp_lm_announce(void);
-int lp_lm_interval(void);
char *lp_preexec(int );
char *lp_postexec(int );
char *lp_rootpreexec(int );
@@ -332,8 +236,6 @@ char *lp_volume(int );
char *lp_mangled_map(int );
char *lp_veto_files(int );
char *lp_hide_files(int );
-char *lp_veto_oplocks(int );
-char *lp_driverlocation(int );
BOOL lp_alternate_permissions(int );
BOOL lp_revalidate(int );
BOOL lp_casesensitive(int );
@@ -354,7 +256,6 @@ BOOL lp_map_archive(int );
BOOL lp_locking(int );
BOOL lp_strict_locking(int );
BOOL lp_share_modes(int );
-BOOL lp_oplocks(int );
BOOL lp_onlyuser(int );
BOOL lp_manglednames(int );
BOOL lp_widelinks(int );
@@ -363,7 +264,6 @@ BOOL lp_syncalways(int );
BOOL lp_map_system(int );
BOOL lp_delete_readonly(int );
BOOL lp_fake_oplocks(int );
-BOOL lp_recursive_veto_delete(int );
BOOL lp_dos_filetimes(int );
int lp_create_mode(int );
int lp_force_create_mode(int );
@@ -372,26 +272,19 @@ int lp_force_dir_mode(int );
int lp_max_connections(int );
int lp_defaultcase(int );
int lp_minprintspace(int );
-int lp_printing(int );
char lp_magicchar(int );
BOOL lp_add_home(char *pszHomename, int iDefaultService, char *pszHomedir);
int lp_add_service(char *pszService, int iDefaultService);
BOOL lp_add_printer(char *pszPrintername, int iDefaultService);
BOOL lp_file_list_changed(void);
-BOOL lp_do_parameter(int snum, char *pszParmName, char *pszParmValue);
-int lp_next_parameter(int snum, int *i, char *label,
- char *value, int allparameters);
BOOL lp_snum_ok(int iService);
BOOL lp_loaded(void);
void lp_killunused(BOOL (*snumused)(int ));
BOOL lp_load(char *pszFname,BOOL global_only);
int lp_numservices(void);
-void lp_dump(FILE *f);
+void lp_dump(void);
int lp_servicenumber(char *pszServiceName);
char *volume_label(int snum);
-void lp_rename_service(int snum, char *new_name);
-void lp_remove_service(int snum);
-void lp_copy_service(int snum, char *new_name);
int lp_default_server_announce(void);
int lp_major_announce_version(void);
int lp_minor_announce_version(void);
@@ -401,54 +294,33 @@ int lp_minor_announce_version(void);
BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset);
BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode);
BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ecode);
-BOOL locking_init(int read_only);
-BOOL locking_end(void);
-BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok);
-BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token);
-int get_share_modes(int cnum, int token, uint32 dev, uint32 inode,
- share_mode_entry **shares);
-void del_share_mode(int token, int fnum);
-BOOL set_share_mode(int token, int fnum, uint16 port, uint16 op_type);
-BOOL remove_share_oplock(int fnum, int token);
-int share_mode_forall(void (*fn)(share_mode_entry *, char *));
-void share_status(FILE *f);
-
-/*The following definitions come from locking_shm.c */
-
-struct share_ops *locking_shm_init(int ronly);
-
-/*The following definitions come from locking_slow.c */
-
-struct share_ops *locking_slow_init(int ronly);
+BOOL start_share_mode_mgmt(void);
+BOOL stop_share_mode_mgmt(void);
+BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok);
+BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token);
+int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode,
+ min_share_mode_entry **old_shares);
+void del_share_mode(share_lock_token token, int fnum);
+BOOL set_share_mode(share_lock_token token, int fnum);
+BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok);
+BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token);
+int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode,
+ min_share_mode_entry **old_shares);
+void del_share_mode(share_lock_token token, int fnum);
+BOOL set_share_mode(share_lock_token token,int fnum);
/*The following definitions come from mangle.c */
int str_checksum(char *s);
BOOL is_8_3(char *fname, BOOL check_case);
-void reset_mangled_stack( int size );
+void create_mangled_stack(int size);
BOOL check_mangled_stack(char *s);
-BOOL is_mangled( char *s );
+BOOL is_mangled(char *s);
void mangle_name_83(char *s);
BOOL name_map_mangle(char *OutName,BOOL need83,int snum);
/*The following definitions come from md4.c */
-void mdfour(unsigned char *out, unsigned char *in, int n);
-
-/*The following definitions come from mem_man/mem_man.c */
-
-void *mem_malloc(size_t size,char *file,int line);
-char *mem_strdup(char *s, char *file, int line);
-int mem_free(void *ptr,char *file,int line);
-void mem_write_info(void *ptr,FILE *outfile);
-char *mem_query_file(void *ptr);
-int mem_query_line(void *ptr);
-int mem_test(void *ptr);
-void mem_write_status(FILE *outfile);
-void mem_write_verbose(FILE *outfile);
-void mem_write_errors(FILE *outfile);
-void mem_set_multiplier(int multiplier);
-void *mem_resize(void *ptr,size_t newsize);
/*The following definitions come from message.c */
@@ -457,344 +329,257 @@ int reply_sendstrt(char *inbuf,char *outbuf);
int reply_sendtxt(char *inbuf,char *outbuf);
int reply_sendend(char *inbuf,char *outbuf);
-/*The following definitions come from namequery.c */
-
-BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
- struct in_addr to_ip,char *master,char *rname,
- void (*fn)());
-struct in_addr *name_query(int fd,char *name,int name_type,
- BOOL bcast,BOOL recurse,
- struct in_addr to_ip, int *count, void (*fn)());
+/*The following definitions come from nameannounce.c */
+
+void announce_request(struct work_record *work, struct in_addr ip);
+void do_announce_request(char *info, char *to_name, int announce_type,
+ int from,
+ int to, struct in_addr dest_ip);
+void sync_server(enum state_type state, char *serv_name, char *work_name,
+ int name_type,
+ struct subnet_record *d,
+ struct in_addr ip);
+void do_announce_host(int command,
+ char *from_name, int from_type, struct in_addr from_ip,
+ char *to_name , int to_type , struct in_addr to_ip,
+ time_t announce_interval,
+ char *server_name, int server_type, char *server_comment);
+void announce_my_servers_removed(void);
+void announce_server(struct subnet_record *d, struct work_record *work,
+ char *name, char *comment, time_t ttl, int server_type);
+void announce_host(time_t t);
+void reset_announce_timer();
+void announce_master(time_t t);
+void announce_remote(time_t t);
+void browse_sync_remote(time_t t);
-/*The following definitions come from nmbd.c */
+/*The following definitions come from namebrowse.c */
-BOOL reload_services(BOOL test);
-int main(int argc,char *argv[]);
+void expire_browse_cache(time_t t);
+struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
+ time_t ttl, struct subnet_record *d,
+ struct in_addr ip, BOOL local);
+void do_browser_lists(time_t t);
-/*The following definitions come from nmbd_become_dmb.c */
+/*The following definitions come from nameconf.c */
-void unbecome_domain_master(char *workgroup_name);
-void add_domain_names(time_t t);
+int get_num_workgroups(void);
+int conf_workgroup_name_to_token(char *workgroup_name,char *default_name);
+char *conf_workgroup_name(int token);
+int conf_should_workgroup_member(int token);
+int conf_should_local_master(int token);
+int conf_should_domain_master(int token);
+char *conf_browsing_alias(int token);
+char *conf_browsing_alias_comment(int token);
+char *conf_alias_to_workgroup(char *alias);
+int conf_alias_to_token(char *alias);
+void read_smbbrowse_conf(char *default_name);
-/*The following definitions come from nmbd_become_lmb.c */
+/*The following definitions come from namedbname.c */
-void unbecome_local_master_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *released_name,
- struct in_addr released_ip);
-void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
- struct nmb_name *fail_name);
-void release_1d_name( struct subnet_record *subrec, char *workgroup_name);
-void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work);
-void become_local_master_browser(struct subnet_record *subrec, struct work_record *work);
-void set_workgroup_local_master_browser_name( struct work_record *work, char *newname);
+void set_samba_nb_type(void);
+BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2);
+BOOL ms_browser_name(char *name, int type);
+void remove_name(struct subnet_record *d, struct name_record *n);
+struct name_record *find_name(struct name_record *n,
+ struct nmb_name *name, int search);
+struct name_record *find_name_search(struct subnet_record **d,
+ struct nmb_name *name,
+ int search, struct in_addr ip);
+void dump_names(void);
+void load_netbios_names(void);
+void remove_netbios_name(struct subnet_record *d,
+ char *name,int type, enum name_source source,
+ struct in_addr ip);
+struct name_record *add_netbios_entry(struct subnet_record *d,
+ char *name, int type, int nb_flags,
+ int ttl, enum name_source source, struct in_addr ip,
+ BOOL new_only,BOOL wins);
+void expire_names(time_t t);
+struct name_record *dns_name_search(struct nmb_name *question, int Time);
+
+/*The following definitions come from namedbresp.c */
+
+void add_response_record(struct subnet_record *d,
+ struct response_record *n);
+void remove_response_record(struct subnet_record *d,
+ struct response_record *n);
+struct response_record *make_response_queue_record(enum state_type state,
+ int id,uint16 fd,
+ int quest_type, char *name,int type, int nb_flags, time_t ttl,
+ int server_type, char *my_name, char *my_comment,
+ BOOL bcast,BOOL recurse,
+ struct in_addr send_ip, struct in_addr reply_to_ip,
+ int reply_id);
+struct response_record *find_response_record(struct subnet_record **d,
+ uint16 id);
-/*The following definitions come from nmbd_browserdb.c */
+/*The following definitions come from namedbserver.c */
+
+void remove_old_servers(struct work_record *work, time_t t,
+ BOOL remove_all);
+struct server_record *find_server(struct work_record *work, char *name);
+struct server_record *add_server_entry(struct subnet_record *d,
+ struct work_record *work,
+ char *name,int servertype,
+ int ttl,char *comment,
+ BOOL replace);
+void expire_servers(time_t t);
+
+/*The following definitions come from namedbsubnet.c */
+
+struct subnet_record *find_subnet(struct in_addr bcast_ip);
+struct subnet_record *find_req_subnet(struct in_addr ip, BOOL bcast);
+struct subnet_record *find_subnet_all(struct in_addr bcast_ip);
+void add_workgroup_to_subnet( struct subnet_record *d, char *group);
+void add_my_subnets(char *group);
+void write_browse_list(time_t t);
+
+/*The following definitions come from namedbwork.c */
+
+struct work_record *remove_workgroup(struct subnet_record *d,
+ struct work_record *work,
+ BOOL remove_all_servers);
+struct work_record *find_workgroupstruct(struct subnet_record *d,
+ fstring name, BOOL add);
+void dump_workgroups(void);
-void remove_lmb_browser_entry(struct browse_cache_record *browc);
-void update_browser_death_time(struct browse_cache_record *browc);
-struct browse_cache_record *create_browser_in_lmb_cache(char *work_name, char *browser_name,
- struct in_addr ip);
-struct browse_cache_record *find_browser_in_lmb_cache( char *browser_name );
-void expire_lmb_browsers(time_t t);
-void remove_workgroup_lmb_browsers(char *work_group);
+/*The following definitions come from nameelect.c */
+
+void check_master_browser(time_t t);
+void browser_gone(char *work_name, struct in_addr ip);
+void send_election(struct subnet_record *d, char *group,uint32 criterion,
+ int timeup,char *name);
+void name_unregister_work(struct subnet_record *d, char *name, int name_type);
+void name_register_work(struct subnet_record *d, char *name, int name_type,
+ int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast);
+void become_local_master(struct subnet_record *d, struct work_record *work);
+void become_domain_master(struct subnet_record *d, struct work_record *work);
+void become_logon_server(struct subnet_record *d, struct work_record *work);
+void unbecome_local_master(struct subnet_record *d, struct work_record *work,
+ int remove_type);
+void unbecome_domain_master(struct subnet_record *d, struct work_record *work,
+ int remove_type);
+void unbecome_logon_server(struct subnet_record *d, struct work_record *work,
+ int remove_type);
+void run_elections(time_t t);
+void process_election(struct packet_struct *p,char *buf);
+BOOL check_elections(void);
-/*The following definitions come from nmbd_browsesync.c */
+/*The following definitions come from namelogon.c */
-void dmb_expire_and_sync_browser_lists(time_t t);
-void announce_and_sync_with_domain_master_browser( struct subnet_record *subrec,
- struct work_record *work);
+void process_logon_packet(struct packet_struct *p,char *buf,int len);
-/*The following definitions come from nmbd_elections.c */
+/*The following definitions come from namepacket.c */
-void check_master_browser_exists(time_t t);
-void run_elections(time_t t);
-void process_election(struct subnet_record *subrec, struct packet_struct *p, char *buf);
-BOOL check_elections(void);
+void debug_browse_data(char *outbuf, int len);
+void initiate_netbios_packet(uint16 *id,
+ int fd,int quest_type,char *name,int name_type,
+ int nb_flags,BOOL bcast,BOOL recurse,
+ struct in_addr to_ip);
+void reply_netbios_packet(struct packet_struct *p1,int trn_id,
+ int rcode, int rcv_code, int opcode,
+ BOOL recursion_available,
+ BOOL recursion_desired,
+ struct nmb_name *rr_name,int rr_type,int rr_class,int ttl,
+ char *data,int len);
+void queue_packet(struct packet_struct *packet);
+void run_packet_queue();
+void listen_for_packets(BOOL run_election);
+BOOL send_mailslot_reply(BOOL unique, char *mailslot,int fd,char *buf,int len,char *srcname,
+ char *dstname,int src_type,int dest_type,
+ struct in_addr dest_ip,struct in_addr src_ip);
-/*The following definitions come from nmbd_incomingdgrams.c */
+/*The following definitions come from namequery.c */
-void tell_become_backup(void);
-void process_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf);
-void process_workgroup_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf);
-void process_local_master_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf);
-void process_master_browser_announce(struct subnet_record *subrec,
- struct packet_struct *p,char *buf);
-void process_lm_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf);
-void process_get_backup_list_request(struct subnet_record *subrec,
- struct packet_struct *p,char *buf);
-void process_reset_browser(struct subnet_record *subrec,
- struct packet_struct *p,char *buf);
-void process_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf);
-void process_lm_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf);
-
-/*The following definitions come from nmbd_incomingrequests.c */
-
-void process_name_release_request(struct subnet_record *subrec,
- struct packet_struct *p);
-void process_name_refresh_request(struct subnet_record *subrec,
- struct packet_struct *p);
-void process_name_registration_request(struct subnet_record *subrec,
- struct packet_struct *p);
-void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p);
-void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p);
-
-/*The following definitions come from nmbd_lmhosts.c */
-
-void load_lmhosts_file(char *fname);
-BOOL find_name_in_lmhosts(struct nmb_name *nmbname, struct name_record **namerecp);
-
-/*The following definitions come from nmbd_logonnames.c */
-
-void add_logon_names(void);
-
-/*The following definitions come from nmbd_mynames.c */
-
-BOOL register_my_workgroup_and_names();
-void release_my_names();
+BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
+ struct in_addr to_ip,char *master,char *rname,
+ void (*fn)());
+BOOL name_query(int fd,char *name,int name_type,
+ BOOL bcast,BOOL recurse,
+ struct in_addr to_ip, struct in_addr *ip,void (*fn)());
+
+/*The following definitions come from nameresp.c */
+
+void expire_netbios_response_entries(time_t t);
+struct response_record *queue_netbios_pkt_wins(
+ int fd,int quest_type,enum state_type state,
+ char *name,int name_type,int nb_flags, time_t ttl,
+ int server_type, char *my_name, char *my_comment,
+ struct in_addr send_ip, struct in_addr reply_to_ip);
+struct response_record *queue_netbios_packet(struct subnet_record *d,
+ int fd,int quest_type,enum state_type state,char *name,
+ int name_type,int nb_flags, time_t ttl,
+ int server_type, char *my_name, char *my_comment,
+ BOOL bcast,BOOL recurse,
+ struct in_addr send_ip, struct in_addr reply_to_ip,
+ int reply_id);
+
+/*The following definitions come from nameserv.c */
+
+void remove_name_entry(struct subnet_record *d, char *name,int type);
+void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags);
+void add_domain_logon_names(void);
+void add_domain_master_bcast(void);
+void add_domain_master_wins(void);
+void add_domain_names(time_t t);
+void add_my_names(void);
+void remove_my_names();
void refresh_my_names(time_t t);
+void query_refresh_names(time_t t);
-/*The following definitions come from nmbd_namelistdb.c */
+/*The following definitions come from nameservreply.c */
-void set_samba_nb_type(void);
-BOOL ms_browser_name(char *name, int type);
-void remove_name_from_namelist(struct subnet_record *subrec,
- struct name_record *namerec);
-struct name_record *find_name_on_subnet(struct subnet_record *subrec,
- struct nmb_name *nmbname, BOOL self_only);
-struct name_record *find_name_for_remote_broadcast_subnet( struct nmb_name *nmbname,
- BOOL self_only);
-void update_name_ttl(struct name_record *namerec, int ttl);
-struct name_record *add_name_to_subnet(struct subnet_record *subrec,
- char *name, int type, uint16 nb_flags, int ttl,
- enum name_source source, int num_ips, struct in_addr *iplist);
-void standard_success_register(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname, uint16 nb_flags, int ttl,
- struct in_addr registered_ip);
-void standard_fail_register(struct subnet_record *subrec,
- struct response_record *rrec, struct nmb_name *nmbname);
-BOOL find_ip_in_name_record(struct name_record *namerec, struct in_addr ip);
-void add_ip_to_name_record(struct name_record *namerec, struct in_addr new_ip);
-void remove_ip_from_name_record( struct name_record *namerec, struct in_addr remove_ip);
-void standard_success_release(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname, struct in_addr released_ip);
-void expire_names_on_subnet(struct subnet_record *subrec, time_t t);
-void expire_names(time_t t);
-void add_samba_names_to_subnet(struct subnet_record *subrec);
-void dump_all_namelists();
-
-/*The following definitions come from nmbd_namequery.c */
-
-BOOL query_name(struct subnet_record *subrec, char *name, int type,
- query_name_success_function success_fn,
- query_name_fail_function fail_fn,
- struct userdata_struct *userdata);
-
-/*The following definitions come from nmbd_nameregister.c */
-
-BOOL register_name(struct subnet_record *subrec,
- char *name, int type, uint16 nb_flags,
- register_name_success_function success_fn,
- register_name_fail_function fail_fn,
- struct userdata_struct *userdata);
-BOOL refresh_name(struct subnet_record *subrec, struct name_record *namerec,
- refresh_name_success_function success_fn,
- refresh_name_fail_function fail_fn,
- struct userdata_struct *userdata);
-
-/*The following definitions come from nmbd_namerelease.c */
-
-BOOL release_name(struct subnet_record *subrec, struct name_record *namerec,
- release_name_success_function success_fn,
- release_name_fail_function fail_fn,
- struct userdata_struct *userdata);
-
-/*The following definitions come from nmbd_nodestatus.c */
-
-BOOL node_status(struct subnet_record *subrec, struct nmb_name *nmbname,
- struct in_addr send_ip, node_status_success_function success_fn,
- node_status_fail_function fail_fn, struct userdata_struct *userdata);
-
-/*The following definitions come from nmbd_packets.c */
-
-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,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- register_name_success_function success_fn,
- register_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname,
- uint16 nb_flags);
-struct response_record *queue_register_multihomed_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- register_name_success_function success_fn,
- register_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname,
- uint16 nb_flags,
- struct in_addr register_ip);
-struct response_record *queue_release_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- release_name_success_function success_fn,
- release_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname,
- uint16 nb_flags,
- struct in_addr release_ip);
-struct response_record *queue_refresh_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- refresh_name_success_function success_fn,
- refresh_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct name_record *namerec,
- struct in_addr refresh_ip);
-struct response_record *queue_query_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- query_name_success_function success_fn,
- query_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname);
-struct response_record *queue_node_status( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- node_status_success_function success_fn,
- node_status_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname,
- struct in_addr send_ip);
-void reply_netbios_packet(struct packet_struct *orig_packet,
- int rcode, enum netbios_reply_type_code rcv_code, int opcode,
- int ttl, char *data,int len);
-void queue_packet(struct packet_struct *packet);
-void process_browse_packet(struct packet_struct *p, char *buf,int len);
-void process_lanman_packet(struct packet_struct *p, char *buf,int len);
-BOOL validate_nmb_response_packet( struct nmb_packet *nmb );
-BOOL validate_nmb_packet( struct nmb_packet *nmb );
-void run_packet_queue();
-void retransmit_or_expire_response_records(time_t t);
-BOOL listen_for_packets(BOOL run_election);
-BOOL send_mailslot(BOOL unique, char *mailslot,char *buf,int len,
- char *srcname, int src_type,
- char *dstname, int dest_type,
- struct in_addr dest_ip,struct in_addr src_ip);
-
-/*The following definitions come from nmbd_processlogon.c */
-
-void process_logon_packet(struct packet_struct *p,char *buf,int len,
- char *mailslot);
-
-/*The following definitions come from nmbd_responserecordsdb.c */
-
-void add_response_record(struct subnet_record *subrec,
- struct response_record *rrec);
-void remove_response_record(struct subnet_record *subrec,
- struct response_record *rrec);
-struct response_record *make_response_record( struct subnet_record *subrec,
- struct packet_struct *p,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- success_function success_fn,
- fail_function fail_fn,
- struct userdata_struct *userdata);
-struct response_record *find_response_record(struct subnet_record **ppsubrec,
- uint16 id);
+void add_name_respond(struct subnet_record *d, int fd, struct in_addr from_ip,
+ uint16 response_id,
+ struct nmb_name *name,
+ int nb_flags, int ttl, struct in_addr register_ip,
+ BOOL new_owner, struct in_addr reply_to_ip);
+void reply_name_release(struct packet_struct *p);
+void reply_name_reg(struct packet_struct *p);
+void reply_name_status(struct packet_struct *p);
+void reply_name_query(struct packet_struct *p);
-/*The following definitions come from nmbd_sendannounce.c */
+/*The following definitions come from nameservresp.c */
-void send_browser_reset(int reset_type, char *to_name, int to_type, struct in_addr to_ip);
-void broadcast_announce_request(struct subnet_record *subrec, struct work_record *work);
-void announce_my_server_names(time_t t);
-void announce_my_lm_server_names(time_t t);
-void reset_announce_timer();
-void announce_myself_to_domain_master_browser(time_t t);
-void announce_my_servers_removed(void);
-void announce_remote(time_t t);
-void browse_sync_remote(time_t t);
+void debug_state_type(int state);
+void response_netbios_packet(struct packet_struct *p);
-/*The following definitions come from nmbd_serverlistdb.c */
-
-void remove_all_servers(struct work_record *work);
-struct server_record *find_server_in_workgroup(struct work_record *work, char *name);
-struct server_record *create_server_on_workgroup(struct work_record *work,
- char *name,int servertype,
- int ttl,char *comment);
-void update_server_ttl(struct server_record *servrec, int ttl);
-void expire_servers(struct work_record *work, time_t t);
-void write_browse_list(time_t t, BOOL force_write);
-
-/*The following definitions come from nmbd_subnetdb.c */
-
-BOOL create_subnets();
-BOOL we_are_a_wins_client();
-struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec);
-
-/*The following definitions come from nmbd_winsproxy.c */
-
-void make_wins_proxy_name_query_request( struct subnet_record *subrec,
- struct packet_struct *incoming_packet,
- struct nmb_name *question_name);
-
-/*The following definitions come from nmbd_winsserver.c */
-
-BOOL packet_is_for_wins_server(struct packet_struct *packet);
-BOOL initialise_wins(void);
-void wins_process_name_refresh_request(struct subnet_record *subrec,
- struct packet_struct *p);
-void wins_process_name_registration_request(struct subnet_record *subrec,
- struct packet_struct *p);
-void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
- struct packet_struct *p);
-void send_wins_name_query_response(int rcode, struct packet_struct *p,
- struct name_record *namerec);
-void wins_process_name_query_request(struct subnet_record *subrec,
- struct packet_struct *p);
-void wins_process_name_release_request(struct subnet_record *subrec,
- struct packet_struct *p);
-void initiate_wins_processing(time_t t);
-void wins_write_database(void);
-
-/*The following definitions come from nmbd_workgroupdb.c */
-
-struct work_record *find_workgroup_on_subnet(struct subnet_record *subrec,
- fstring name);
-struct work_record *create_workgroup_on_subnet(struct subnet_record *subrec,
- fstring name, int ttl);
-void update_workgroup_ttl(struct work_record *work, int ttl);
-void initiate_myworkgroup_startup(struct subnet_record *subrec, struct work_record *work);
-void dump_workgroups(void);
-void expire_workgroups_and_servers(time_t t);
+/*The following definitions come from namework.c */
+
+void reset_server(char *name, int state, struct in_addr ip);
+void tell_become_backup(void);
+BOOL same_context(struct dgram_packet *dgram);
+void process_browse_packet(struct packet_struct *p,char *buf,int len);
+
+/*The following definitions come from nmbd.c */
+
+BOOL reload_services(BOOL test);
/*The following definitions come from nmblib.c */
-char *lookup_opcode_name( int opcode );
void debug_nmb_packet(struct packet_struct *p);
char *namestr(struct nmb_name *n);
-struct packet_struct *copy_packet(struct packet_struct *packet);
+void free_nmb_packet(struct nmb_packet *nmb);
void free_packet(struct packet_struct *packet);
struct packet_struct *read_packet(int fd,enum packet_type packet_type);
void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope);
-BOOL nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2);
BOOL send_packet(struct packet_struct *p);
struct packet_struct *receive_packet(int fd,enum packet_type type,int t);
-/*The following definitions come from ntclient.c */
+/*The following definitions come from nmblookup.c */
+
+int main(int argc,char *argv[]);
+
+/*The following definitions come from nmbsync.c */
-BOOL do_nt_login(char *desthost, char *myhostname,
- int Client, int cnum);
+char *getsmbpass(char *pass);
+void sync_browse_lists(struct subnet_record *d, struct work_record *work,
+ char *name, int nm_type, struct in_addr ip, BOOL local);
/*The following definitions come from params.c */
-BOOL pm_process( char *FileName,
- BOOL (*sfunc)(char *),
- BOOL (*pfunc)(char *, char *) );
+BOOL pm_process(char *pszFileName,BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *));
/*The following definitions come from password.c */
@@ -828,8 +613,10 @@ void pcap_printer_fn(void (*fn)());
/*The following definitions come from pipes.c */
int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize);
-int reply_pipe_close(char *inbuf,char *outbuf);
-BOOL api_LsarpcSNPHS(int pnum, int cnum, char *param);
+BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len);
BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
@@ -841,11 +628,6 @@ int read_predict(int fd,int offset,char *buf,char **ptr,int num);
void do_read_prediction();
void invalidate_read_prediction(int fd);
-/*The following definitions come from print_svid.c */
-
-void sysv_printer_fn(void (*fn)());
-int sysv_printername_ok(char *name);
-
/*The following definitions come from printing.c */
void lpq_reset(int snum);
@@ -864,13 +646,15 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize);
BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize);
BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize);
BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize);
-BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize);
/*The following definitions come from replace.c */
char *Strstr(char *s, char *p);
time_t Mktime(struct tm *t);
int InNetGr(char *group,char *host,char *user,char *dom);
+void *malloc_wrapped(int size,char *file,int line);
+void *realloc_wrapped(void *ptr,int size,char *file,int line);
+void free_wrapped(void *ptr,char *file,int line);
void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line);
/*The following definitions come from reply.c */
@@ -926,281 +710,6 @@ int reply_writebs(char *inbuf,char *outbuf);
int reply_setattrE(char *inbuf,char *outbuf);
int reply_getattrE(char *inbuf,char *outbuf);
-/*The following definitions come from rpc_pipes/lsa_hnd.c */
-
-void init_lsa_policy_hnd(void);
-BOOL open_lsa_policy_hnd(LSA_POL_HND *hnd);
-BOOL set_lsa_policy_samr_rid(LSA_POL_HND *hnd, uint32 rid);
-BOOL set_lsa_policy_samr_pol_status(LSA_POL_HND *hnd, uint32 pol_status);
-BOOL set_lsa_policy_samr_sid(LSA_POL_HND *hnd, DOM_SID *sid);
-uint32 get_lsa_policy_samr_rid(LSA_POL_HND *hnd);
-BOOL close_lsa_policy_hnd(LSA_POL_HND *hnd);
-
-/*The following definitions come from rpc_pipes/lsaparse.c */
-
-void make_q_open_pol(LSA_Q_OPEN_POL *r_q, char *server_name,
- uint32 attributes, uint32 sec_qos,
- uint16 desired_access);
-char* lsa_io_q_open_pol(BOOL io, LSA_Q_OPEN_POL *r_q, char *q, char *base, int align, int depth);
-char* lsa_io_r_open_pol(BOOL io, LSA_R_OPEN_POL *r_p, char *q, char *base, int align, int depth);
-void make_q_query(LSA_Q_QUERY_INFO *q_q, LSA_POL_HND *hnd, uint16 info_class);
-char* lsa_io_q_query(BOOL io, LSA_Q_QUERY_INFO *q_q, char *q, char *base, int align, int depth);
-char* lsa_io_q_enum_trust_dom(BOOL io, LSA_Q_ENUM_TRUST_DOM *q_e, char *q, char *base, int align, int depth);
-void make_r_enum_trust_dom(LSA_R_ENUM_TRUST_DOM *r_e, LSA_POL_HND *hnd, uint32 status);
-char* lsa_io_r_enum_trust_dom(BOOL io, LSA_R_ENUM_TRUST_DOM *r_e, char *q, char *base, int align, int depth);
-void make_q_close(LSA_Q_CLOSE *q_c, LSA_POL_HND *hnd);
-char* lsa_io_q_close(BOOL io, LSA_Q_CLOSE *q_c, char *q, char *base, int align, int depth);
-void make_r_close(LSA_R_CLOSE *q_r, LSA_POL_HND *hnd);
-char* lsa_io_r_close(BOOL io, LSA_R_CLOSE *r_c, char *q, char *base, int align, int depth);
-char* lsa_io_r_query(BOOL io, LSA_R_QUERY_INFO *r_q, char *q, char *base, int align, int depth);
-char* lsa_io_q_lookup_sids(BOOL io, LSA_Q_LOOKUP_SIDS *q_s, char *q, char *base, int align, int depth);
-char* lsa_io_r_lookup_sids(BOOL io, LSA_R_LOOKUP_SIDS *r_s, char *q, char *base, int align, int depth);
-char* lsa_io_q_lookup_rids(BOOL io, LSA_Q_LOOKUP_RIDS *q_r, char *q, char *base, int align, int depth);
-char* lsa_io_r_lookup_rids(BOOL io, LSA_R_LOOKUP_RIDS *r_r, char *q, char *base, int align, int depth);
-void make_q_req_chal(LSA_Q_REQ_CHAL *q_c,
- char *logon_srv, char *logon_clnt,
- DOM_CHAL *clnt_chal);
-char* lsa_io_q_req_chal(BOOL io, LSA_Q_REQ_CHAL *q_c, char *q, char *base, int align, int depth);
-char* lsa_io_r_req_chal(BOOL io, LSA_R_REQ_CHAL *r_c, char *q, char *base, int align, int depth);
-void make_q_auth_2(LSA_Q_AUTH_2 *q_a,
- char *logon_srv, char *acct_name, uint16 sec_chan, char *comp_name,
- DOM_CHAL *clnt_chal, uint32 clnt_flgs);
-char* lsa_io_q_auth_2(BOOL io, LSA_Q_AUTH_2 *q_a, char *q, char *base, int align, int depth);
-char* lsa_io_r_auth_2(BOOL io, LSA_R_AUTH_2 *r_a, char *q, char *base, int align, int depth);
-void make_q_srv_pwset(LSA_Q_SRV_PWSET *q_s, char sess_key[8],
- char *logon_srv, char *acct_name, uint16 sec_chan, char *comp_name,
- DOM_CRED *cred, char nt_cypher[16]);
-char* lsa_io_q_srv_pwset(BOOL io, LSA_Q_SRV_PWSET *q_s, char *q, char *base, int align, int depth);
-char* lsa_io_r_srv_pwset(BOOL io, LSA_R_SRV_PWSET *r_s, char *q, char *base, int align, int depth);
-char* lsa_io_user_info(BOOL io, LSA_USER_INFO *usr, char *q, char *base, int align, int depth);
-char* lsa_io_q_sam_logon(BOOL io, LSA_Q_SAM_LOGON *q_l, char *q, char *base, int align, int depth);
-char* lsa_io_r_sam_logon(BOOL io, LSA_R_SAM_LOGON *r_l, char *q, char *base, int align, int depth);
-char* lsa_io_q_sam_logoff(BOOL io, LSA_Q_SAM_LOGOFF *q_l, char *q, char *base, int align, int depth);
-char* lsa_io_r_sam_logoff(BOOL io, LSA_R_SAM_LOGOFF *r_l, char *q, char *base, int align, int depth);
-
-/*The following definitions come from rpc_pipes/ntclientlsa.c */
-
-BOOL do_lsa_open_policy(uint16 fnum, uint32 call_id,
- char *server_name, LSA_POL_HND *hnd);
-BOOL do_lsa_query_info_pol(uint16 fnum, uint32 call_id,
- LSA_POL_HND *hnd, uint16 info_class,
- fstring domain_name, pstring domain_sid);
-BOOL do_lsa_close(uint16 fnum, uint32 call_id,
- LSA_POL_HND *hnd);
-
-/*The following definitions come from rpc_pipes/ntclientnet.c */
-
-BOOL do_lsa_req_chal(uint16 fnum, uint32 call_id,
- char *desthost, char *myhostname,
- DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal);
-BOOL do_lsa_auth2(uint16 fnum, uint32 call_id,
- char *logon_srv, char *acct_name, uint16 sec_chan, char *comp_name,
- DOM_CHAL *clnt_chal, uint32 neg_flags, DOM_CHAL *srv_chal);
-BOOL do_lsa_srv_pwset(uint16 fnum, uint32 call_id,
- uchar sess_key[8],
- char *logon_srv, char *mach_acct, uint16 sec_chan_type, char *comp_name,
- DOM_CRED *clnt_cred, DOM_CRED *srv_cred,
- char nt_owf_new_mach_pwd[16]);
-BOOL do_lsa_sam_logon(uint16 fnum, uint32 call_id,
- uchar sess_key[8], DOM_CRED *sto_clnt_cred,
- char *logon_srv, char *comp_name,
- DOM_CRED *clnt_cred, DOM_CRED *rtn_cred,
- uint16 logon_level, uint16 switch_value, DOM_ID_INFO_1 *id1,
- LSA_USER_INFO *user_info,
- DOM_CRED *srv_cred);
-BOOL do_lsa_sam_logoff(uint16 fnum, uint32 call_id,
- uchar sess_key[8], DOM_CRED *sto_clnt_cred,
- char *logon_srv, char *comp_name,
- DOM_CRED *clnt_cred, DOM_CRED *rtn_cred,
- uint16 logon_level, uint16 switch_value, DOM_ID_INFO_1 *id1,
- DOM_CRED *srv_cred);
-
-/*The following definitions come from rpc_pipes/ntclientpipe.c */
-
-uint16 rpc_pipe_open(char *inbuf, char *outbuf, char *rname, int Client, int cnum);
-BOOL rpc_pipe_set_hnd_state(char *pipe_name, uint16 fnum, uint16 device_state);
-BOOL rpc_pipe_bind(char *pipe_name, uint16 fnum, uint32 call_id,
- RPC_IFACE *abstract, RPC_IFACE *transfer);
-
-/*The following definitions come from rpc_pipes/pipe_hnd.c */
-
-void reset_chain_pnum(void);
-void init_rpc_pipe_hnd(void);
-int open_rpc_pipe_hnd(char *pipe_name, int cnum);
-char *get_rpc_pipe_hnd_name(int pnum);
-BOOL set_rpc_pipe_hnd_state(int pnum, int cnum, uint16 device_state);
-BOOL close_rpc_pipe_hnd(int pnum, int cnum);
-int get_rpc_pipe_num(char *buf, int where);
-
-/*The following definitions come from rpc_pipes/pipenetlog.c */
-
-BOOL api_netlogrpcTNP(int cnum,int uid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len);
-
-/*The following definitions come from rpc_pipes/pipentlsa.c */
-
-BOOL api_ntLsarpcTNP(int cnum,int uid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len);
-
-/*The following definitions come from rpc_pipes/pipesamr.c */
-
-BOOL api_samrTNP(int cnum,int uid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len);
-
-/*The following definitions come from rpc_pipes/pipesrvsvc.c */
-
-BOOL api_srvsvcTNP(int cnum,int uid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len);
-
-/*The following definitions come from rpc_pipes/pipeutil.c */
-
-void initrpcreply(char *inbuf, char *q);
-void endrpcreply(char *inbuf, char *q, int datalen, int rtnval, int *rlen);
-BOOL name_to_rid(char *user_name, uint32 *u_rid, uint32 *g_rid);
-char *dom_sid_to_string(DOM_SID *sid);
-int make_dom_sids(char *sids_str, DOM_SID *sids, int max_sids);
-int make_dom_gids(char *gids_str, DOM_GID *gids);
-int create_rpc_request(uint32 call_id, uint8 op_num, char *q, int data_len);
-int create_rpc_reply(uint32 call_id, char *q, int data_len);
-
-/*The following definitions come from rpc_pipes/pipewkssvc.c */
-
-BOOL api_wkssvcTNP(int cnum,int uid, char *param,char *data,
- int mdrcnt,int mprcnt,
- char **rdata,char **rparam,
- int *rdata_len,int *rparam_len);
-
-/*The following definitions come from rpc_pipes/samrparse.c */
-
-char* samr_io_q_close(BOOL io, SAMR_Q_CLOSE *q_u, char *q, char *base, int align, int depth);
-char* samr_io_r_close(BOOL io, SAMR_R_CLOSE *r_u, char *q, char *base, int align, int depth);
-char* samr_io_q_open_secret(BOOL io, SAMR_Q_OPEN_SECRET *q_u, char *q, char *base, int align, int depth);
-char* samr_io_r_open_secret(BOOL io, SAMR_R_OPEN_SECRET *r_u, char *q, char *base, int align, int depth);
-char* samr_io_q_lookup_rids(BOOL io, SAMR_Q_LOOKUP_RIDS *q_u, char *q, char *base, int align, int depth);
-void make_samr_r_lookup_rids(SAMR_R_LOOKUP_RIDS *r_u,
- uint32 num_rids, uint32 rid, uint32 status);
-char* samr_io_r_lookup_rids(BOOL io, SAMR_R_LOOKUP_RIDS *r_u, char *q, char *base, int align, int depth);
-char* samr_io_q_unknown_22(BOOL io, SAMR_Q_UNKNOWN_22 *q_u, char *q, char *base, int align, int depth);
-char* samr_io_r_unknown_22(BOOL io, SAMR_R_UNKNOWN_22 *r_u, char *q, char *base, int align, int depth);
-char* samr_io_q_unknown_24(BOOL io, SAMR_Q_UNKNOWN_24 *q_u, char *q, char *base, int align, int depth);
-void make_samr_r_unknown_24(SAMR_R_UNKNOWN_24 *r_u,
- uint16 unknown_0, NTTIME *expiry, char *mach_acct,
- uint32 unknown_id_0, uint32 status);
-char* samr_io_r_unknown_24(BOOL io, SAMR_R_UNKNOWN_24 *r_u, char *q, char *base, int align, int depth);
-char* samr_io_q_unknown_32(BOOL io, SAMR_Q_UNKNOWN_32 *q_u, char *q, char *base, int align, int depth);
-char* samr_io_r_unknown_32(BOOL io, SAMR_R_UNKNOWN_32 *r_u, char *q, char *base, int align, int depth);
-char* samr_io_q_open_policy(BOOL io, SAMR_Q_OPEN_POLICY *q_u, char *q, char *base, int align, int depth);
-char* samr_io_r_open_policy(BOOL io, SAMR_R_OPEN_POLICY *r_u, char *q, char *base, int align, int depth);
-
-/*The following definitions come from rpc_pipes/smbparse.c */
-
-char* smb_io_utime(BOOL io, UTIME *t, char *q, char *base, int align, int depth);
-char* smb_io_time(BOOL io, NTTIME *nttime, char *q, char *base, int align, int depth);
-void make_dom_sid(DOM_SID *sid, char *domsid);
-char* smb_io_dom_sid(BOOL io, DOM_SID *sid, char *q, char *base, int align, int depth);
-void make_uni_hdr(UNIHDR *hdr, int max_len, int len, uint16 terminate);
-char* smb_io_unihdr(BOOL io, UNIHDR *hdr, char *q, char *base, int align, int depth);
-void make_uni_hdr2(UNIHDR2 *hdr, int max_len, int len, uint16 terminate);
-char* smb_io_unihdr2(BOOL io, UNIHDR2 *hdr2, char *q, char *base, int align, int depth);
-void make_unistr(UNISTR *str, char *buf);
-char* smb_io_unistr(BOOL io, UNISTR *uni, char *q, char *base, int align, int depth);
-void make_unistr2(UNISTR2 *str, char *buf, int len);
-char* smb_io_unistr2(BOOL io, UNISTR2 *uni2, char *q, char *base, int align, int depth);
-void make_dom_sid2(DOM_SID2 *sid2, char *sid_str);
-char* smb_io_dom_sid2(BOOL io, DOM_SID2 *sid2, char *q, char *base, int align, int depth);
-void make_dom_rid2(DOM_RID2 *rid2, uint32 rid);
-char* smb_io_dom_rid2(BOOL io, DOM_RID2 *rid2, char *q, char *base, int align, int depth);
-void make_dom_rid3(DOM_RID3 *rid3, uint32 rid);
-char* smb_io_dom_rid3(BOOL io, DOM_RID3 *rid3, char *q, char *base, int align, int depth);
-void make_clnt_srv(DOM_CLNT_SRV *log, char *logon_srv, char *comp_name);
-char* smb_io_clnt_srv(BOOL io, DOM_CLNT_SRV *log, char *q, char *base, int align, int depth);
-void make_log_info(DOM_LOG_INFO *log, char *logon_srv, char *acct_name,
- uint16 sec_chan, char *comp_name);
-char* smb_io_log_info(BOOL io, DOM_LOG_INFO *log, char *q, char *base, int align, int depth);
-char* smb_io_chal(BOOL io, DOM_CHAL *chal, char *q, char *base, int align, int depth);
-char* smb_io_cred(BOOL io, DOM_CRED *cred, char *q, char *base, int align, int depth);
-void make_clnt_info2(DOM_CLNT_INFO2 *clnt,
- char *logon_srv, char *comp_name,
- DOM_CRED *clnt_cred);
-char* smb_io_clnt_info2(BOOL io, DOM_CLNT_INFO2 *clnt, char *q, char *base, int align, int depth);
-char* make_clnt_info(DOM_CLNT_INFO *clnt,
- char *logon_srv, char *acct_name,
- uint16 sec_chan, char *comp_name,
- DOM_CRED *cred);
-char* smb_io_clnt_info(BOOL io, DOM_CLNT_INFO *clnt, char *q, char *base, int align, int depth);
-void make_logon_id(DOM_LOGON_ID *log, uint32 log_id_low, uint32 log_id_high);
-char* smb_io_logon_id(BOOL io, DOM_LOGON_ID *log, char *q, char *base, int align, int depth);
-void make_arc4_owf(ARC4_OWF *hash, char data[16]);
-char* smb_io_arc4_owf(BOOL io, ARC4_OWF *hash, char *q, char *base, int align, int depth);
-void make_id_info1(DOM_ID_INFO_1 *id, char *domain_name,
- uint32 param_ctrl, uint32 log_id_low, uint32 log_id_high,
- char *user_name, char *wksta_name,
- char *sess_key,
- unsigned char lm_cypher[16], unsigned char nt_cypher[16]);
-char* smb_io_id_info1(BOOL io, DOM_ID_INFO_1 *id, char *q, char *base, int align, int depth);
-void make_sam_info(DOM_SAM_INFO *sam,
- char *logon_srv, char *comp_name, DOM_CRED *clnt_cred,
- DOM_CRED *rtn_cred, uint16 logon_level, uint16 switch_value,
- DOM_ID_INFO_1 *id1);
-char* smb_io_sam_info(BOOL io, DOM_SAM_INFO *sam, char *q, char *base, int align, int depth);
-char* smb_io_gid(BOOL io, DOM_GID *gid, char *q, char *base, int align, int depth);
-void make_rpc_hdr(RPC_HDR *hdr, enum RPC_PKT_TYPE pkt_type, uint8 frag,
- uint32 call_id, int data_len);
-char* smb_io_rpc_hdr(BOOL io, RPC_HDR *rpc, char *q, char *base, int align, int depth);
-void make_rpc_iface(RPC_IFACE *ifc, char data[16], uint32 version);
-char* smb_io_rpc_iface(BOOL io, RPC_IFACE *ifc, char *q, char *base, int align, int depth);
-void make_rpc_addr_str(RPC_ADDR_STR *str, char *name);
-char* smb_io_rpc_addr_str(BOOL io, RPC_ADDR_STR *str, char *q, char *base, int align, int depth);
-void make_rpc_hdr_bba(RPC_HDR_BBA *bba, uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid);
-char* smb_io_rpc_hdr_bba(BOOL io, RPC_HDR_BBA *rpc, char *q, char *base, int align, int depth);
-void make_rpc_hdr_rb(RPC_HDR_RB *rpc,
- uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid,
- uint32 num_elements, uint16 context_id, uint8 num_syntaxes,
- RPC_IFACE *abstract, RPC_IFACE *transfer);
-char* smb_io_rpc_hdr_rb(BOOL io, RPC_HDR_RB *rpc, char *q, char *base, int align, int depth);
-void make_rpc_results(RPC_RESULTS *res,
- uint8 num_results, uint16 result, uint16 reason);
-char* smb_io_rpc_results(BOOL io, RPC_RESULTS *res, char *q, char *base, int align, int depth);
-void make_rpc_hdr_ba(RPC_HDR_BA *rpc,
- uint16 max_tsize, uint16 max_rsize, uint32 assoc_gid,
- char *pipe_addr,
- uint8 num_results, uint16 result, uint16 reason,
- RPC_IFACE *transfer);
-char* smb_io_rpc_hdr_ba(BOOL io, RPC_HDR_BA *rpc, char *q, char *base, int align, int depth);
-void make_obj_attr(LSA_OBJ_ATTR *attr, uint32 attributes, uint32 sec_qos);
-char* smb_io_obj_attr(BOOL io, LSA_OBJ_ATTR *attr, char *q, char *base, int align, int depth);
-void make_rpc_hdr_rr(RPC_HDR_RR *hdr, enum RPC_PKT_TYPE pkt_type,
- uint32 call_id, int data_len, uint8 opnum);
-char* smb_io_rpc_hdr_rr(BOOL io, RPC_HDR_RR *rpc, char *q, char *base, int align, int depth);
-char* smb_io_pol_hnd(BOOL io, LSA_POL_HND *pol, char *q, char *base, int align, int depth);
-char* smb_io_dom_query_3(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align, int depth);
-char* smb_io_dom_query_5(BOOL io, DOM_QUERY_3 *d_q, char *q, char *base, int align, int depth);
-char* smb_io_dom_query(BOOL io, DOM_QUERY *d_q, char *q, char *base, int align, int depth);
-char* smb_io_dom_r_ref(BOOL io, DOM_R_REF *r_r, char *q, char *base, int align, int depth);
-char* smb_io_dom_name(BOOL io, DOM_NAME *name, char *q, char *base, int align, int depth);
-char* smb_io_neg_flags(BOOL io, NEG_FLAGS *neg, char *q, char *base, int align, int depth);
-
-/*The following definitions come from rpc_pipes/srvparse.c */
-
-char* srv_io_share_info1_str(BOOL io, SH_INFO_1_STR *sh1, char *q, char *base, int align, int depth);
-char* srv_io_share_info1(BOOL io, SH_INFO_1 *sh1, char *q, char *base, int align, int depth);
-char* srv_io_share_1_ctr(BOOL io, SHARE_INFO_1_CTR *ctr, char *q, char *base, int align, int depth);
-char* srv_io_q_net_share_enum(BOOL io, SRV_Q_NET_SHARE_ENUM *q_n, char *q, char *base, int align, int depth);
-char* srv_io_r_net_share_enum(BOOL io, SRV_R_NET_SHARE_ENUM *r_n, char *q, char *base, int align, int depth);
-
-/*The following definitions come from rpc_pipes/wksparse.c */
-
-char* wks_io_q_unknown_0(BOOL io, WKS_Q_UNKNOWN_0 *q_u, char *q, char *base, int align, int depth);
-char* wks_io_r_unknown_0(BOOL io, WKS_R_UNKNOWN_0 *r_u, char *q, char *base, int align, int depth);
-
/*The following definitions come from server.c */
void *dflt_sig(void);
@@ -1214,13 +723,14 @@ BOOL unix_convert(char *name,int cnum,pstring saved_last_component, BOOL *bad_pa
int disk_free(char *path,int *bsize,int *dfree,int *dsize);
int sys_disk_free(char *path,int *bsize,int *dfree,int *dsize);
BOOL check_name(char *name,int cnum);
+int fd_attempt_open(char *fname, int flags, int mode);
+void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr);
+int fd_attempt_close(file_fd_struct *fd_ptr);
void sync_file(int fnum);
-void close_file(int fnum, BOOL normal_close);
+void close_file(int fnum, int normal_close);
BOOL check_file_sharing(int cnum,char *fname);
-int check_share_mode( share_mode_entry *share, int deny_mode, char *fname,
- BOOL fcbopen, int *flags);
void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
- int mode,int oplock_request, int *Access,int *action);
+ int mode,int *Access,int *action);
int seek_file(int fnum,uint32 pos);
int read_file(int fnum,char *data,uint32 pos,int n);
int write_file(int fnum,char *data,int n);
@@ -1229,15 +739,10 @@ int find_service(char *service);
int cached_error_packet(char *inbuf,char *outbuf,int fnum,int line);
int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int line);
int error_packet(char *inbuf,char *outbuf,int error_class,uint32 error_code,int line);
-BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval);
-BOOL request_oplock_break(share_mode_entry *share_entry,
- uint32 dev, uint32 inode);
-BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int timeout);
BOOL snum_used(int snum);
BOOL reload_services(BOOL test);
int setup_groups(char *user, int uid, int gid, int *p_ngroups,
- int **p_igroups, gid_t **p_groups,
- int **p_attrs);
+ int **p_igroups, gid_t **p_groups);
int make_connection(char *service,char *user,char *password, int pwlen, char *dev,uint16 vuid);
int find_free_file(void );
int reply_corep(char *outbuf);
@@ -1256,37 +761,43 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize);
/*The following definitions come from shmem.c */
-struct shmem_ops *smb_shm_open(int ronly);
-
-/*The following definitions come from shmem_sysv.c */
-
-struct shmem_ops *sysv_shm_open(int ronly);
-
-/*The following definitions come from smbdes.c */
-
-void E_P16(unsigned char *p14,unsigned char *p16);
-void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
-void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key);
-void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key);
+BOOL smb_shm_create_hash_table( unsigned int size );
+BOOL smb_shm_open( char *file_name, int size);
+BOOL smb_shm_close( void );
+smb_shm_offset_t smb_shm_alloc(int size);
+BOOL smb_shm_free(smb_shm_offset_t offset);
+smb_shm_offset_t smb_shm_get_userdef_off(void);
+BOOL smb_shm_set_userdef_off(smb_shm_offset_t userdef_off);
+void * smb_shm_offset2addr(smb_shm_offset_t offset);
+smb_shm_offset_t smb_shm_addr2offset(void *addr);
+BOOL smb_shm_lock_hash_entry( unsigned int entry);
+BOOL smb_shm_unlock_hash_entry( unsigned int entry );
+BOOL smb_shm_get_usage(int *bytes_free,
+ int *bytes_used,
+ int *bytes_overhead);
/*The following definitions come from smbencrypt.c */
+void str_to_key(uchar *str,uchar *key);
+void D1(uchar *k, uchar *d, uchar *out);
+void E1(uchar *k, uchar *d, uchar *out);
+void E_P16(uchar *p14,uchar *p16);
+void E_P24(uchar *p21, uchar *c8, uchar *p24);
void SMBencrypt(uchar *passwd, uchar *c8, uchar *p24);
void E_md4hash(uchar *passwd, uchar *p16);
void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24);
-void nt_lm_owf_gen(char *pwd, char *nt_p16, char *p16);
-
-/*The following definitions come from smberr.c */
-
-char *smb_errstr(char *inbuf);
/*The following definitions come from smbpass.c */
int pw_file_lock(char *name, int type, int secs);
int pw_file_unlock(int fd);
-struct smb_passwd *get_smbpwd_entry(char *name, int smb_userid);
-BOOL add_smbpwd_entry(struct smb_passwd* pwd);
-BOOL mod_smbpwd_entry(struct smb_passwd* pwd);
+struct smb_passwd *get_smbpwnam(char *name);
+
+/*The following definitions come from smbpasswd.c */
+
+
+/*The following definitions come from smbrun.c */
+
/*The following definitions come from status.c */
@@ -1316,6 +827,13 @@ int sys_chown(char *fname,int uid,int gid);
int sys_chroot(char *dname);
struct hostent *sys_gethostbyname(char *name);
+/*The following definitions come from testparm.c */
+
+
+/*The following definitions come from testprns.c */
+
+int main(int argc, char *argv[]);
+
/*The following definitions come from time.c */
void GetTimeOfDay(struct timeval *tval);
@@ -1340,9 +858,6 @@ int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize);
int reply_transs2(char *inbuf,char *outbuf,int length,int bufsize);
int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize);
-/*The following definitions come from ubiqx/ubi_dLinkList.c */
-
-
/*The following definitions come from ufc.c */
char *ufc_crypt(char *key,char *salt);
@@ -1351,11 +866,11 @@ char *ufc_crypt(char *key,char *salt);
void init_uid(void);
BOOL become_guest(void);
-BOOL become_user(connection_struct *conn, int cnum, uint16 vuid);
+BOOL become_user(int cnum, uint16 vuid);
BOOL unbecome_user(void );
int smbrun(char *cmd,char *outfile,BOOL shared);
-void become_root(BOOL save_dir) ;
-void unbecome_root(BOOL restore_dir);
+void become_root(int save_dir) ;
+void unbecome_root(int restore_dir);
/*The following definitions come from username.c */
@@ -1380,16 +895,16 @@ BOOL in_group(gid_t group, int current_gid, int ngroups, int *groups);
char *StrCpy(char *dest,char *src);
char *StrnCpy(char *dest,char *src,int n);
void putip(void *dest,void *src);
-int name_mangle( char *In, char *Out, char name_type );
+int name_mangle(char *In,char *Out,char name_type);
BOOL file_exist(char *fname,struct stat *sbuf);
time_t file_modtime(char *fname);
BOOL directory_exist(char *dname,struct stat *st);
uint32 file_size(char *file_name);
char *attrib_string(int mode);
-int StrCaseCmp(char *s, char *t);
-int StrnCaseCmp(char *s, char *t, int n);
-BOOL strequal(char *s1, char *s2);
-BOOL strnequal(char *s1,char *s2,int n);
+int StrCaseCmp(const char *s, const char *t);
+int StrnCaseCmp(const char *s, const char *t, int n);
+BOOL strequal(const char *s1, const char *s2);
+BOOL strnequal(const char *s1,const char *s2,int n);
BOOL strcsequal(char *s1,char *s2);
void strlower(char *s);
void strupper(char *s);
@@ -1432,16 +947,11 @@ int read_data(int fd,char *buffer,int N);
int write_data(int fd,char *buffer,int N);
int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align);
int read_smb_length(int fd,char *inbuf,int timeout);
-BOOL receive_smb(int fd,char *buffer, int timeout);
-BOOL receive_local_message(int fd, char *buffer, int buffer_len, int timeout);
-BOOL push_local_message(char *buf, int msg_len);
-BOOL receive_message_or_smb(int smbfd, int oplock_fd,
- char *buffer, int buffer_len,
- int timeout, BOOL *got_smb);
+BOOL receive_smb(int fd,char *buffer,int timeout);
BOOL send_smb(int fd,char *buffer);
char *name_ptr(char *buf,int ofs);
int name_extract(char *buf,int ofs,char *name);
-int name_len( char *s );
+int name_len(char *s);
BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type);
void msleep(int t);
BOOL in_list(char *s,char *list,BOOL casesensitive);
@@ -1471,7 +981,6 @@ BOOL zero_ip(struct in_addr ip);
void reset_globals_after_fork();
char *client_name(void);
char *client_addr(void);
-char *automount_server(char *user_name);
void standard_sub_basic(char *str);
BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask);
int PutUniCode(char *dst,char *src);
@@ -1488,21 +997,21 @@ void free_namearray(name_compare_entry *name_array);
BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type);
int file_lock(char *name,int timeout);
void file_unlock(int fd);
-BOOL is_myname(char *s);
+BOOL is_myname(const char *s);
void set_remote_arch(enum remote_arch_types type);
enum remote_arch_types get_remote_arch();
-char *skip_unicode_string(char *buf,int n);
-char *unistrn2(uint16 *buf, int len);
-char *unistr2(uint16 *buf);
-int struni2(uint16 *p, char *buf);
-char *unistr(char *buf);
-int unistrncpy(char *dst, char *src, int len);
-int unistrcpy(char *dst, char *src);
void fstrcpy(char *dest, char *src);
void pstrcpy(char *dest, char *src);
-char *align4(char *q, char *base);
-char *align2(char *q, char *base);
-char *align_offset(char *q, char *base, int align_offset_len);
-void print_asc(int level, unsigned char *buf,int len);
-void dump_data(int level,char *buf1,int len);
-char *tab_depth(int depth);
+
+/*The following definitions come from vt_mode.c */
+
+int VT_Check(char *buffer);
+int VT_Start_utmp(void);
+int VT_Stop_utmp(void);
+void VT_AtExit(void);
+void VT_SigCLD(int sig);
+void VT_SigEXIT(int sig);
+int VT_Start(void);
+int VT_Output(char *Buffer);
+int VT_Input(char *Buffer,int Size);
+void VT_Process(void);
diff --git a/source/include/smb.h b/source/include/smb.h
index 401459becc2..a273d962b69 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -4,8 +4,6 @@
SMB parameters and setup
Copyright (C) Andrew Tridgell 1992-1997
Copyright (C) John H Terpstra 1996-1997
- Copyright (C) Luke Kenneth Casson Leighton 1996-1997
- Copyright (C) Paul Ashton 1997
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
@@ -24,6 +22,18 @@
#ifndef _SMB_H
#define _SMB_H
+#ifndef MAX_CONNECTIONS
+#define MAX_CONNECTIONS 127
+#endif
+
+#ifndef MAX_OPEN_FILES
+#define MAX_OPEN_FILES 50
+#endif
+
+#ifndef GUEST_ACCOUNT
+#define GUEST_ACCOUNT "nobody"
+#endif
+
#define BUFFER_SIZE (0xFFFF)
#define SAFETY_MARGIN 1024
@@ -32,6 +42,11 @@
#define SHMEM_SIZE 102400
#endif
+/* Default number of hash buckets used in shared memory share mode */
+#ifndef SHMEM_HASH_SIZE
+#define SHMEM_HASH_SIZE 113
+#endif
+
#define NMB_PORT 137
#define DGRAM_PORT 138
#define SMB_PORT 139
@@ -45,8 +60,10 @@
typedef int BOOL;
-/* limiting size of ipc replies */
-#define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
+/* offset in shared memory */
+typedef int smb_shm_offset_t;
+#define NULL_OFFSET (smb_shm_offset_t)(0)
+
/*
Samba needs type definitions for int16, int32, uint16 and uint32.
@@ -63,10 +80,6 @@ typedef short int16;
typedef int int32;
#endif
-#ifndef uint8
-typedef unsigned char uint8;
-#endif
-
#ifndef uint16
typedef unsigned short uint16;
#endif
@@ -137,11 +150,10 @@ implemented */
#define DENY_FCB 7
/* share types */
-#define STYPE_DISKTREE 0 /* Disk drive */
-#define STYPE_PRINTQ 1 /* Spooler queue */
-#define STYPE_DEVICE 2 /* Serial device */
-#define STYPE_IPC 3 /* Interprocess communication (IPC) */
-#define STYPE_HIDDEN 0x80000000 /* share is a hidden one (ends with $) */
+#define STYPE_DISKTREE 0 /* Disk drive */
+#define STYPE_PRINTQ 1 /* Spooler queue */
+#define STYPE_DEVICE 2 /* Serial device */
+#define STYPE_IPC 3 /* Interprocess communication (IPC) */
/* SMB X/Open error codes for the ERRdos error class */
#define ERRbadfunc 1 /* Invalid function (or system call) */
@@ -240,1101 +252,7 @@ typedef char fstring[128];
typedef fstring string;
-/* pipe strings */
-#define PIPE_LANMAN "\\PIPE\\LANMAN"
-#define PIPE_SRVSVC "\\PIPE\\srvsvc"
-#define PIPE_SAMR "\\PIPE\\samr"
-#define PIPE_WKSSVC "\\PIPE\\wkssvc"
-#define PIPE_NETLOGON "\\PIPE\\NETLOGON"
-#define PIPE_NTLSA "\\PIPE\\ntlsa"
-#define PIPE_NTSVCS "\\PIPE\\ntsvcs"
-#define PIPE_LSASS "\\PIPE\\lsass"
-#define PIPE_LSARPC "\\PIPE\\lsarpc"
-
-/* NETLOGON opcodes and data structures */
-
-enum RPC_PKT_TYPE
-{
- RPC_REQUEST = 0x00,
- RPC_RESPONSE = 0x02,
- RPC_BIND = 0x0B,
- RPC_BINDACK = 0x0C
-};
-
-#define NET_QUERYFORPDC 7 /* Query for PDC */
-#define NET_QUERYFORPDC_R 12 /* Response to Query for PDC */
-#define NET_SAMLOGON 18
-#define NET_SAMLOGON_R 19
-
-/* Allowable account control bits */
-#define ACB_DISABLED 1 /* 1 = User account disabled */
-#define ACB_HOMDIRREQ 2 /* 1 = Home directory required */
-#define ACB_PWNOTREQ 4 /* 1 = User password not required */
-#define ACB_TEMPDUP /* 1 = Temporary duplicate account */
-#define ACB_NORMAL /* 1 = Normal user account */
-#define ACB_MNS /* 1 = MNS logon user account */
-#define ACB_DOMTRUST /* 1 = Interdomain trust account */
-#define ACB_WSTRUST /* 1 = Workstation trust account */
-#define ACB_SVRTRUST /* 1 = Server trust account */
-#define ACB_PWNOEXP /* 1 = User password does not expire */
-#define ACB_AUTOLOCK /* 1 = Account auto locked */
-
-#define SAMR_CLOSE 0x01
-#define SAMR_OPEN_SECRET 0x07
-#define SAMR_LOOKUP_RIDS 0x11
-#define SAMR_UNKNOWN_3 0x03
-#define SAMR_UNKNOWN_22 0x22
-#define SAMR_UNKNOWN_24 0x24
-#define SAMR_UNKNOWN_34 0x34
-#define SAMR_OPEN_POLICY 0x39
-
-#define LSA_OPENPOLICY 0x2c
-#define LSA_QUERYINFOPOLICY 0x07
-#define LSA_ENUMTRUSTDOM 0x0d
-#define LSA_REQCHAL 0x04
-#define LSA_SRVPWSET 0x06
-#define LSA_SAMLOGON 0x02
-#define LSA_SAMLOGOFF 0x03
-#define LSA_AUTH2 0x0f
-#define LSA_CLOSE 0x00
-
-/* XXXX these are here to get a compile! */
-
-#define LSA_OPENSECRET 0xFF
-#define LSA_LOOKUPSIDS 0xFE
-#define LSA_LOOKUPRIDS 0xFD
-#define LSA_LOOKUPNAMES 0xFC
-
-/* srvsvc pipe */
-#define NETSERVERGETINFO 0x15
-#define NETSHAREENUM 0x0f
-
-/* well-known RIDs - Relative IDs */
-
-/* RIDs - Well-known users ... */
-#define DOMAIN_USER_RID_ADMIN (0x000001F4L)
-#define DOMAIN_USER_RID_GUEST (0x000001F5L)
-
-/* RIDs - well-known groups ... */
-#define DOMAIN_GROUP_RID_ADMINS (0x00000200L)
-#define DOMAIN_GROUP_RID_USERS (0x00000201L)
-#define DOMAIN_GROUP_RID_GUESTS (0x00000202L)
-
-/* RIDs - well-known aliases ... */
-#define DOMAIN_ALIAS_RID_ADMINS (0x00000220L)
-#define DOMAIN_ALIAS_RID_USERS (0x00000221L)
-#define DOMAIN_ALIAS_RID_GUESTS (0x00000222L)
-#define DOMAIN_ALIAS_RID_POWER_USERS (0x00000223L)
-
-#define DOMAIN_ALIAS_RID_ACCOUNT_OPS (0x00000224L)
-#define DOMAIN_ALIAS_RID_SYSTEM_OPS (0x00000225L)
-#define DOMAIN_ALIAS_RID_PRINT_OPS (0x00000226L)
-#define DOMAIN_ALIAS_RID_BACKUP_OPS (0x00000227L)
-
-#define DOMAIN_ALIAS_RID_REPLICATOR (0x00000228L)
-
-
-
-/* 32 bit time (sec) since 01jan1970 - cifs6.txt, section 3.5, page 30 */
-typedef struct time_info
-{
- uint32 time;
-
-} UTIME;
-
-/* 64 bit time (100usec) since ????? - cifs6.txt, section 3.5, page 30 */
-typedef struct nttime_info
-{
- uint32 low;
- uint32 high;
-
-} NTTIME;
-
-
-#define MAXSUBAUTHS 15 /* max sub authorities in a SID */
-
-/* DOM_SID - security id */
-typedef struct sid_info
-{
- uint8 sid_rev_num; /* SID revision number */
- uint8 num_auths; /* number of sub-authorities */
- uint8 id_auth[6]; /* Identifier Authority */
- uint32 sub_auths[MAXSUBAUTHS]; /* pointer to sub-authorities. */
-
-} DOM_SID;
-
-/* UNIHDR - unicode string header */
-typedef struct unihdr_info
-{
- uint16 uni_max_len;
- uint16 uni_str_len;
- uint32 undoc; /* usually has a value of 4 */
-
-} UNIHDR;
-
-/* UNIHDR2 - unicode string header and undocumented buffer */
-typedef struct unihdr2_info
-{
- UNIHDR unihdr;
- uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */
-
-} UNIHDR2;
-
-/* clueless as to what maximum length should be */
-#define MAX_UNISTRLEN 1024
-
-/* UNISTR - unicode string size and buffer */
-typedef struct unistr_info
-{
- uint16 buffer[MAX_UNISTRLEN]; /* unicode characters. ***MUST*** be null-terminated */
-
-} UNISTR;
-
-/* UNISTR2 - unicode string size and buffer */
-typedef struct unistr2_info
-{
- uint32 uni_max_len;
- uint32 undoc;
- uint32 uni_str_len;
- uint16 buffer[MAX_UNISTRLEN]; /* unicode characters. **NOT** necessarily null-terminated */
-
-} UNISTR2;
-
-/* DOM_SID2 - domain SID structure - SIDs stored in unicode */
-typedef struct domsid2_info
-{
- uint32 type; /* value is 5 */
- uint32 undoc; /* value is 0 */
-
- UNIHDR2 hdr; /* XXXX conflict between hdr and str for length */
- UNISTR str; /* XXXX conflict between hdr and str for length */
-
-} DOM_SID2;
-
-/* DOM_RID2 - domain RID structure for ntlsa pipe */
-typedef struct domrid2_info
-{
- uint32 type; /* value is 5 */
- uint32 undoc; /* value is non-zero */
- uint32 rid;
- uint32 rid_idx; /* don't know what this is */
-
-} DOM_RID2;
-
-/* DOM_RID3 - domain RID structure for samr pipe */
-typedef struct domrid3_info
-{
- uint32 rid; /* domain-relative (to a SID) id */
- uint32 type1; /* value is 0x1 */
- uint32 ptr_type; /* undocumented pointer */
- uint32 type2; /* value is 0x1 */
-
-} DOM_RID3;
-
-/* DOM_CLNT_SRV - client / server names */
-typedef struct clnt_srv_info
-{
- uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */
- UNISTR2 uni_logon_srv; /* logon server name */
- uint32 undoc_buffer2; /* undocumented 32 bit buffer pointer */
- UNISTR2 uni_comp_name; /* client machine name */
-
-} DOM_CLNT_SRV;
-
-/* DOM_LOG_INFO - login info */
-typedef struct log_info
-{
- uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */
- UNISTR2 uni_logon_srv; /* logon server name */
- UNISTR2 uni_acct_name; /* account name */
- uint16 sec_chan; /* secure channel type */
- UNISTR2 uni_comp_name; /* client machine name */
-
-} DOM_LOG_INFO;
-
-/* DOM_CHAL - challenge info */
-typedef struct chal_info
-{
- uchar data[8]; /* credentials */
-} DOM_CHAL;
-
-/* DOM_CREDs - timestamped client or server credentials */
-typedef struct cred_info
-{
- DOM_CHAL challenge; /* credentials */
- UTIME timestamp; /* credential time-stamp */
-
-} DOM_CRED;
-
-/* DOM_CLNT_INFO - client info */
-typedef struct clnt_info
-{
- DOM_LOG_INFO login;
- DOM_CRED cred;
-
-} DOM_CLNT_INFO;
-
-/* DOM_CLNT_INFO2 - client info */
-typedef struct clnt_info2
-{
- DOM_CLNT_SRV login;
- uint32 ptr_cred;
- DOM_CRED cred;
-
-} DOM_CLNT_INFO2;
-
-/* DOM_LOGON_ID - logon id */
-typedef struct logon_info
-{
- uint32 low;
- uint32 high;
-
-} DOM_LOGON_ID;
-
-/* ARC4_OWF */
-typedef struct arc4_owf_info
-{
- uint8 data[16];
-
-} ARC4_OWF;
-
-
-/* DOM_ID_INFO_1 */
-typedef struct id_info_1
-{
- uint32 ptr_id_info1; /* pointer to id_info_1 */
- UNIHDR hdr_domain_name; /* domain name unicode header */
- uint32 param_ctrl; /* param control */
- DOM_LOGON_ID logon_id; /* logon ID */
- UNIHDR hdr_user_name; /* user name unicode header */
- UNIHDR hdr_wksta_name; /* workgroup name unicode header */
- ARC4_OWF arc4_lm_owf; /* arc4 LM OWF Password */
- ARC4_OWF arc4_nt_owf; /* arc4 NT OWF Password */
- UNISTR2 uni_domain_name; /* domain name unicode string */
- UNISTR2 uni_user_name; /* user name unicode string */
- UNISTR2 uni_wksta_name; /* workgroup name unicode string */
-
-} DOM_ID_INFO_1;
-
-/* SAM_INFO - sam logon/off id structure */
-typedef struct sam_info
-{
- DOM_CLNT_INFO2 client;
- uint32 ptr_rtn_cred; /* pointer to return credentials */
- DOM_CRED rtn_cred; /* return credentials */
- uint16 logon_level;
- uint16 switch_value;
-
- union
- {
- DOM_ID_INFO_1 *id1; /* auth-level 1 */
-
- } auth;
-
-} DOM_SAM_INFO;
-
-/* DOM_GID - group id + user attributes */
-typedef struct gid_info
-{
- uint32 g_rid; /* a group RID */
- uint32 attr;
-
-} DOM_GID;
-
-/* RPC_HDR - ms rpc header */
-typedef struct rpc_hdr_info
-{
- uint8 major; /* 5 - RPC major version */
- uint8 minor; /* 0 - RPC minor version */
- uint8 pkt_type; /* 2 - RPC response packet */
- uint8 frag; /* 3 - first frag + last frag */
- uint32 pack_type; /* 0x1000 0000 - packed data representation */
- uint16 frag_len; /* fragment length - data size (bytes) inc header and tail. */
- uint16 auth_len; /* 0 - authentication length */
- uint32 call_id; /* call identifier. matches 12th uint32 of incoming RPC data. */
-
-} RPC_HDR;
-
-/* RPC_HDR_RR - ms request / response rpc header */
-typedef struct rpc_hdr_rr_info
-{
- RPC_HDR hdr;
-
- uint32 alloc_hint; /* allocation hint - data size (bytes) minus header and tail. */
- uint16 context_id; /* 0 - presentation context identifier */
- uint8 cancel_count; /* 0 - cancel count */
- uint8 opnum; /* request: 0 - reserved. response: opnum */
-
-} RPC_HDR_RR;
-
-/* the interfaces are numbered. as yet I haven't seen more than one interface
- * used on the same pipe name
- * srvsvc
- * abstract (0x4B324FC8, 0x01D31670, 0x475A7812, 0x88E16EBF, 0x00000003)
- * transfer (0x8A885D04, 0x11C91CEB, 0x0008E89F, 0x6048102B, 0x00000002)
- */
-/* RPC_IFACE */
-typedef struct rpc_iface_info
-{
- uint8 data[16]; /* 16 bytes of number */
- uint32 version; /* the interface number */
-
-} RPC_IFACE;
-
-
-/* this seems to be the same string name depending on the name of the pipe,
- * but is more likely to be linked to the interface name
- * "srvsvc", "\\PIPE\\ntsvcs"
- * "samr", "\\PIPE\\lsass"
- * "wkssvc", "\\PIPE\\wksvcs"
- * "NETLOGON", "\\PIPE\\NETLOGON"
- */
-/* RPC_ADDR_STR */
-typedef struct rpc_addr_info
-{
- uint16 len; /* length of the string including null terminator */
- fstring str; /* the string above in single byte, null terminated form */
-
-} RPC_ADDR_STR;
-
-/* RPC_HDR_BBA */
-typedef struct rpc_hdr_bba_info
-{
- uint16 max_tsize; /* maximum transmission fragment size (0x1630) */
- uint16 max_rsize; /* max receive fragment size (0x1630) */
- uint32 assoc_gid; /* associated group id (0x0) */
-
-} RPC_HDR_BBA;
-
-/* RPC_BIND_REQ - ms req bind */
-typedef struct rpc_bind_req_info
-{
- RPC_HDR_BBA bba;
-
- uint32 num_elements; /* the number of elements (0x1) */
- uint16 context_id; /* presentation context identifier (0x0) */
- uint8 num_syntaxes; /* the number of syntaxes (has always been 1?)(0x1) */
-
- RPC_IFACE abstract; /* num and vers. of interface client is using */
- RPC_IFACE transfer; /* num and vers. of interface to use for replies */
-
-} RPC_HDR_RB;
-
-/* RPC_RESULTS - can only cope with one reason, right now... */
-typedef struct rpc_results_info
-{
-/* uint8[] # 4-byte alignment padding, against SMB header */
-
- uint8 num_results; /* the number of results (0x01) */
-
-/* uint8[] # 4-byte alignment padding, against SMB header */
-
- uint16 result; /* result (0x00 = accept) */
- uint16 reason; /* reason (0x00 = no reason specified) */
-
-} RPC_RESULTS;
-
-/* RPC_HDR_BA */
-typedef struct rpc_hdr_ba_info
-{
- RPC_HDR_BBA bba;
-
- RPC_ADDR_STR addr ; /* the secondary address string, as described earlier */
- RPC_RESULTS res ; /* results and reasons */
- RPC_IFACE transfer; /* the transfer syntax from the request */
-
-} RPC_HDR_BA;
-
-
-/* DOM_QUERY - info class 3 and 5 LSA Query response */
-typedef struct dom_query_info
-{
- uint16 uni_dom_max_len; /* domain name string length * 2 */
- uint16 uni_dom_str_len; /* domain name string length * 2 */
- uint32 buffer_dom_name; /* undocumented domain name string buffer pointer */
- uint32 buffer_dom_sid; /* undocumented domain SID string buffer pointer */
- UNISTR2 uni_domain_name; /* domain name (unicode string) */
- DOM_SID dom_sid; /* domain SID */
-
-} DOM_QUERY;
-
-/* level 5 is same as level 3. we hope. */
-typedef DOM_QUERY DOM_QUERY_3;
-typedef DOM_QUERY DOM_QUERY_5;
-
-#define POL_HND_SIZE 20
-
-/* LSA_POL_HND */
-typedef struct lsa_policy_info
-{
- uint8 data[POL_HND_SIZE]; /* policy handle */
-
-} LSA_POL_HND;
-
-/* OBJ_ATTR (object attributes) */
-typedef struct object_attributes_info
-{
- uint32 len; /* 0x18 - length (in bytes) inc. the length field. */
- uint32 ptr_root_dir; /* 0 - root directory (pointer) */
- uint32 ptr_obj_name; /* 0 - object name (pointer) */
- uint32 attributes; /* 0 - attributes (undocumented) */
- uint32 ptr_sec_desc; /* 0 - security descriptior (pointer) */
- uint32 sec_qos; /* 0 - security quality of service */
-
-} LSA_OBJ_ATTR;
-
-/* LSA_Q_OPEN_POL - LSA Query Open Policy */
-typedef struct lsa_q_open_pol_info
-{
- uint32 ptr; /* undocumented buffer pointer */
- UNISTR2 uni_server_name; /* server name, starting with two '\'s */
- LSA_OBJ_ATTR attr ; /* object attributes */
-
- uint32 des_access; /* desired access attributes */
-
-} LSA_Q_OPEN_POL;
-
-/* LSA_R_OPEN_POL - response to LSA Open Policy */
-typedef struct lsa_r_open_pol_info
-{
- LSA_POL_HND pol; /* policy handle */
-
- uint32 status; /* return code */
-
-} LSA_R_OPEN_POL;
-
-/* LSA_Q_QUERY_INFO - LSA query info policy */
-typedef struct lsa_query_info
-{
- LSA_POL_HND pol; /* policy handle */
- uint16 info_class; /* info class */
-
-} LSA_Q_QUERY_INFO;
-
-/* LSA_R_QUERY_INFO - response to LSA query info policy */
-typedef struct lsa_r_query_info
-{
- uint32 undoc_buffer; /* undocumented buffer pointer */
- uint16 info_class; /* info class (same as info class in request) */
-
- union
- {
- DOM_QUERY_3 id3;
- DOM_QUERY_5 id5;
-
- } dom;
-
- uint32 status; /* return code */
-
-} LSA_R_QUERY_INFO;
-
-/* LSA_Q_ENUM_TRUST_DOM - LSA enumerate trusted domains */
-typedef struct lsa_enum_trust_dom_info
-{
- LSA_POL_HND pol; /* policy handle */
- uint32 enum_context; /* enumeration context handle */
- uint32 preferred_len; /* preferred maximum length */
-
-} LSA_Q_ENUM_TRUST_DOM;
-
-/* LSA_R_ENUM_TRUST_DOM - response to LSA enumerate trusted domains */
-typedef struct lsa_r_enum_trust_dom_info
-{
- LSA_POL_HND pol; /* policy handle */
-
- uint32 status; /* return code */
-
-} LSA_R_ENUM_TRUST_DOM;
-
-/* LSA_Q_CLOSE */
-typedef struct lsa_q_close_info
-{
- LSA_POL_HND pol; /* policy handle */
-
-} LSA_Q_CLOSE;
-
-/* LSA_R_CLOSE */
-typedef struct lsa_r_close_info
-{
- LSA_POL_HND pol; /* policy handle. should be all zeros. */
-
- uint32 status; /* return code */
-
-} LSA_R_CLOSE;
-
-
-#define MAX_REF_DOMAINS 10
-
-/* DOM_R_REF */
-typedef struct dom_ref_info
-{
- uint32 undoc_buffer; /* undocumented buffer pointer. */
- uint32 num_ref_doms_1; /* num referenced domains? */
- uint32 buffer_dom_name; /* undocumented domain name buffer pointer. */
- uint32 max_entries; /* 32 - max number of entries */
- uint32 num_ref_doms_2; /* 4 - num referenced domains? */
-
- UNIHDR2 hdr_dom_name; /* domain name unicode string header */
- UNIHDR2 hdr_ref_dom[MAX_REF_DOMAINS]; /* referenced domain unicode string headers */
-
- UNISTR uni_dom_name; /* domain name unicode string */
- DOM_SID ref_dom[MAX_REF_DOMAINS]; /* referenced domain SIDs */
-
-} DOM_R_REF;
-
-#define MAX_LOOKUP_SIDS 10
-
-/* LSA_Q_LOOKUP_SIDS - LSA Lookup SIDs */
-typedef struct lsa_q_lookup_sids
-{
- LSA_POL_HND pol_hnd; /* policy handle */
- uint32 num_entries;
- uint32 buffer_dom_sid; /* undocumented domain SID buffer pointer */
- uint32 buffer_dom_name; /* undocumented domain name buffer pointer */
- uint32 buffer_lookup_sids[MAX_LOOKUP_SIDS]; /* undocumented domain SID pointers to be looked up. */
- DOM_SID dom_sids[MAX_LOOKUP_SIDS]; /* domain SIDs to be looked up. */
- uint8 undoc[16]; /* completely undocumented 16 bytes */
-
-} LSA_Q_LOOKUP_SIDS;
-
-/* LSA_R_LOOKUP_SIDS - response to LSA Lookup SIDs */
-typedef struct lsa_r_lookup_sids
-{
- DOM_R_REF dom_ref; /* domain reference info */
-
- uint32 num_entries;
- uint32 undoc_buffer; /* undocumented buffer pointer */
- uint32 num_entries2;
-
- DOM_SID2 dom_sid[MAX_LOOKUP_SIDS]; /* domain SIDs being looked up */
-
- uint32 num_entries3;
-
- uint32 status; /* return code */
-
-} LSA_R_LOOKUP_SIDS;
-
-/* DOM_NAME - XXXX not sure about this structure */
-typedef struct dom_name_info
-{
- uint32 uni_str_len;
- UNISTR str;
-
-} DOM_NAME;
-
-
-#define UNKNOWN_LEN 1
-
-/* LSA_Q_LOOKUP_RIDS - LSA Lookup RIDs */
-typedef struct lsa_q_lookup_rids
-{
-
- LSA_POL_HND pol_hnd; /* policy handle */
- uint32 num_entries;
- uint32 num_entries2;
- uint32 buffer_dom_sid; /* undocumented domain SID buffer pointer */
- uint32 buffer_dom_name; /* undocumented domain name buffer pointer */
- DOM_NAME lookup_name[MAX_LOOKUP_SIDS]; /* names to be looked up */
- uint8 undoc[UNKNOWN_LEN]; /* completely undocumented bytes of unknown length */
-
-} LSA_Q_LOOKUP_RIDS;
-
-/* LSA_R_LOOKUP_RIDS - response to LSA Lookup RIDs by name */
-typedef struct lsa_r_lookup_rids
-{
- DOM_R_REF dom_ref; /* domain reference info */
-
- uint32 num_entries;
- uint32 undoc_buffer; /* undocumented buffer pointer */
-
- uint32 num_entries2;
- DOM_RID2 dom_rid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */
-
- uint32 num_entries3;
-
- uint32 status; /* return code */
-
-} LSA_R_LOOKUP_RIDS;
-
-
-
-/* NEG_FLAGS */
-typedef struct lsa_neg_flags_info
-{
- uint32 neg_flags; /* negotiated flags */
-
-} NEG_FLAGS;
-
-
-/* LSA_Q_REQ_CHAL */
-typedef struct lsa_q_req_chal_info
-{
- uint32 undoc_buffer; /* undocumented buffer pointer */
- UNISTR2 uni_logon_srv; /* logon server unicode string */
- UNISTR2 uni_logon_clnt; /* logon client unicode string */
- DOM_CHAL clnt_chal; /* client challenge */
-
-} LSA_Q_REQ_CHAL;
-
-
-/* LSA_R_REQ_CHAL */
-typedef struct lsa_r_req_chal_info
-{
- DOM_CHAL srv_chal; /* server challenge */
-
- uint32 status; /* return code */
-
-} LSA_R_REQ_CHAL;
-
-
-
-/* LSA_Q_AUTH_2 */
-typedef struct lsa_q_auth2_info
-{
- DOM_LOG_INFO clnt_id; /* client identification info */
- DOM_CHAL clnt_chal; /* client-calculated credentials */
-
- NEG_FLAGS clnt_flgs; /* usually 0x0000 01ff */
-
-} LSA_Q_AUTH_2;
-
-
-/* LSA_R_AUTH_2 */
-typedef struct lsa_r_auth2_info
-{
- DOM_CHAL srv_chal; /* server-calculated credentials */
- NEG_FLAGS srv_flgs; /* usually 0x0000 01ff */
-
- uint32 status; /* return code */
-
-} LSA_R_AUTH_2;
-
-
-/* LSA_Q_SRV_PWSET */
-typedef struct lsa_q_srv_pwset_info
-{
- DOM_CLNT_INFO clnt_id; /* client identification/authentication info */
- char pwd[16]; /* new password - undocumented. */
-
-} LSA_Q_SRV_PWSET;
-
-/* LSA_R_SRV_PWSET */
-typedef struct lsa_r_srv_pwset_info
-{
- DOM_CRED srv_cred; /* server-calculated credentials */
-
- uint32 status; /* return code */
-
-} LSA_R_SRV_PWSET;
-
-#define LSA_MAX_GROUPS 32
-#define LSA_MAX_SIDS 32
-
-/* LSA_USER_INFO */
-typedef struct lsa_q_user_info
-{
- uint32 ptr_user_info;
-
- NTTIME logon_time; /* logon time */
- NTTIME logoff_time; /* logoff time */
- NTTIME kickoff_time; /* kickoff time */
- NTTIME pass_last_set_time; /* password last set time */
- NTTIME pass_can_change_time; /* password can change time */
- NTTIME pass_must_change_time; /* password must change time */
-
- UNIHDR hdr_user_name; /* username unicode string header */
- UNIHDR hdr_full_name; /* user's full name unicode string header */
- UNIHDR hdr_logon_script; /* logon script unicode string header */
- UNIHDR hdr_profile_path; /* profile path unicode string header */
- UNIHDR hdr_home_dir; /* home directory unicode string header */
- UNIHDR hdr_dir_drive; /* home directory drive unicode string header */
-
- uint16 logon_count; /* logon count */
- uint16 bad_pw_count; /* bad password count */
-
- uint32 user_id; /* User ID */
- uint32 group_id; /* Group ID */
- uint32 num_groups; /* num groups */
- uint32 buffer_groups; /* undocumented buffer pointer to groups. */
- uint32 user_flgs; /* user flags */
-
- char user_sess_key[16]; /* unused user session key */
-
- UNIHDR hdr_logon_srv; /* logon server unicode string header */
- UNIHDR hdr_logon_dom; /* logon domain unicode string header */
-
- uint32 buffer_dom_id; /* undocumented logon domain id pointer */
- char padding[40]; /* unused padding bytes. expansion room */
-
- uint32 num_other_sids; /* 0 - num_sids */
- uint32 buffer_other_sids; /* NULL - undocumented pointer to SIDs. */
-
- UNISTR2 uni_user_name; /* username unicode string */
- UNISTR2 uni_full_name; /* user's full name unicode string */
- UNISTR2 uni_logon_script; /* logon script unicode string */
- UNISTR2 uni_profile_path; /* profile path unicode string */
- UNISTR2 uni_home_dir; /* home directory unicode string */
- UNISTR2 uni_dir_drive; /* home directory drive unicode string */
-
- uint32 num_groups2; /* num groups */
- DOM_GID gids[LSA_MAX_GROUPS]; /* group info */
-
- UNISTR2 uni_logon_srv; /* logon server unicode string */
- UNISTR2 uni_logon_dom; /* logon domain unicode string */
-
- DOM_SID dom_sid; /* domain SID */
- DOM_SID other_sids[LSA_MAX_SIDS]; /* undocumented - domain SIDs */
-
-} LSA_USER_INFO;
-
-
-/* LSA_Q_SAM_LOGON */
-typedef struct lsa_q_sam_logon_info
-{
- DOM_SAM_INFO sam_id;
-
-} LSA_Q_SAM_LOGON;
-
-/* LSA_R_SAM_LOGON */
-typedef struct lsa_r_sam_logon_info
-{
- uint32 buffer_creds; /* undocumented buffer pointer */
- DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */
-
- uint16 switch_value; /* 3 - indicates type of USER INFO */
- LSA_USER_INFO *user;
-
- uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */
-
- uint32 status; /* return code */
-
-} LSA_R_SAM_LOGON;
-
-
-/* LSA_Q_SAM_LOGOFF */
-typedef struct lsa_q_sam_logoff_info
-{
- DOM_SAM_INFO sam_id;
-
-} LSA_Q_SAM_LOGOFF;
-
-/* LSA_R_SAM_LOGOFF */
-typedef struct lsa_r_sam_logoff_info
-{
- uint32 buffer_creds; /* undocumented buffer pointer */
- DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */
-
- uint32 status; /* return code */
-
-} LSA_R_SAM_LOGOFF;
-
-
-/* SH_INFO_1 (pointers to level 1 share info strings) */
-typedef struct ptr_share_info1
-{
- uint32 ptr_netname; /* pointer to net name. */
- uint32 type; /* type of share. 0 - undocumented. */
- uint32 ptr_remark; /* pointer to comment. */
-
-} SH_INFO_1;
-
-/* SH_INFO_1_STR (level 1 share info strings) */
-typedef struct str_share_info1
-{
- UNISTR2 uni_netname; /* unicode string of net name */
- UNISTR2 uni_remark; /* unicode string of comment. */
-
-} SH_INFO_1_STR;
-
-/* oops - this is going to take up a *massive* amount of stack. */
-/* the UNISTR2s already have 1024 uint16 chars in them... */
-#define MAX_SHARE_ENTRIES 32
-
-/* SHARE_INFO_1_CONTAINER */
-typedef struct share_info_ctr
-{
- uint32 num_entries_read; /* EntriesRead */
- uint32 ptr_share_info; /* Buffer */
- uint32 num_entries_read2; /* EntriesRead */
- SH_INFO_1 info_1 [MAX_SHARE_ENTRIES]; /* share entry pointers */
- SH_INFO_1_STR info_1_str[MAX_SHARE_ENTRIES]; /* share entry strings */
- uint32 num_entries_read3; /* EntriesRead2 */
- uint32 padding; /* padding */
-
-} SHARE_INFO_1_CTR;
-
-
-/* SRV_Q_NET_SHARE_ENUM */
-typedef struct q_net_share_enum_info
-{
- uint32 ptr_srv_name; /* pointer (to server name?) */
- UNISTR2 uni_srv_name; /* server name */
-
- uint32 share_level; /* share level */
- uint32 switch_value; /* switch value */
-
- uint32 ptr_share_info; /* pointer to SHARE_INFO_1_CTR */
-
- union
- {
- SHARE_INFO_1_CTR info1; /* share info with 0 entries */
-
- } share;
-
- uint32 preferred_len; /* preferred maximum length (0xffff ffff) */
-
-} SRV_Q_NET_SHARE_ENUM;
-
-
-/* SRV_R_NET_SHARE_ENUM */
-typedef struct r_net_share_enum_info
-{
- uint32 share_level; /* share level */
- uint32 switch_value; /* switch value */
-
- uint32 ptr_share_info; /* pointer to SHARE_INFO_1_CTR */
- union
- {
- SHARE_INFO_1_CTR info1; /* share info container */
-
- } share;
-
- uint32 status; /* return status */
-
-} SRV_R_NET_SHARE_ENUM;
-
-
-/* SAMR_Q_CLOSE - probably a policy handle close */
-typedef struct q_samr_close_info
-{
- LSA_POL_HND pol; /* policy handle */
-
-} SAMR_Q_CLOSE;
-
-
-/* SAMR_R_CLOSE - probably a policy handle close */
-typedef struct r_samr_close_info
-{
- LSA_POL_HND pol; /* policy handle */
- uint32 status; /* return status */
-
-} SAMR_R_CLOSE;
-
-
-/****************************************************************************
-SAMR_Q_OPEN_SECRET - unknown_0 values seen associated with SIDs:
-
-0x0000 0200 and a specific domain sid - S-1-5-21-44c01ca6-797e5c3d-33f83fd0
-0x0000 0280 and a well-known domain sid - S-1-5-20
-0x2000 0000 and a well-known domain sid - S-1-5-20
-0x2000 0000 and a specific domain sid - S-1-5-21-44c01ca6-797e5c3d-33f83fd0
-*****************************************************************************/
-
-/* SAMR_Q_OPEN_SECRET - probably an open secret */
-typedef struct q_samr_open_secret_info
-{
- LSA_POL_HND pol; /* policy handle */
- uint32 unknown_0; /* 0x2000 0000; 0x0000 0211; 0x0000 0280; 0x0000 0200 - unknown */
- DOM_SID dom_sid; /* domain SID */
-
-} SAMR_Q_OPEN_SECRET;
-
-
-/* SAMR_R_OPEN_SECRET - probably an open */
-typedef struct r_samr_open_secret_info
-{
- LSA_POL_HND pol; /* policy handle associated with the SID */
- uint32 status; /* return status */
-
-} SAMR_R_OPEN_SECRET;
-
-
-/****************************************************************************
-SAMR_Q_LOOKUP_RIDS - do a conversion (only one!) from name to RID.
-
-the policy handle allocated by an "samr open secret" call is associated
-with a SID. this policy handle is what is queried here, *not* the SID
-itself. the response to the lookup rids is relative to this SID.
-*****************************************************************************/
-/* SAMR_Q_LOOKUP_RIDS - probably a "read SAM entry" */
-typedef struct q_samr_lookup_names_info
-{
- LSA_POL_HND pol; /* policy handle */
-
- uint32 num_rids1; /* 1 - number of rids being looked up */
- uint32 rid; /* 0000 03e8 - RID of the server being queried? */
- uint32 ptr; /* 0 - 32 bit unknown */
- uint32 num_rids2; /* 1 - number of rids being looked up */
-
- UNIHDR hdr_mach_acct; /* unicode machine account name header */
- UNISTR2 uni_mach_acct; /* unicode machine account name */
-
-} SAMR_Q_LOOKUP_RIDS;
-
-
-/* SAMR_R_LOOKUP_RIDS - probably an open */
-typedef struct r_samr_lookup_names_info
-{
- uint32 num_entries;
- uint32 undoc_buffer; /* undocumented buffer pointer */
-
- uint32 num_entries2;
- DOM_RID3 dom_rid[MAX_LOOKUP_SIDS]; /* domain RIDs being looked up */
-
- uint32 num_entries3;
-
- uint32 status; /* return code */
-
-} SAMR_R_LOOKUP_RIDS;
-
-
-/* SAMR_Q_UNKNOWN_22 - probably an open */
-typedef struct q_samr_unknown_22_info
-{
- LSA_POL_HND pol; /* policy handle */
- uint32 unknown_id_0; /* 0x0000 03E8 - 32 bit unknown id */
-
-} SAMR_Q_UNKNOWN_22;
-
-
-/* SAMR_R_UNKNOWN_22 - probably an open */
-typedef struct r_samr_unknown_22_info
-{
- LSA_POL_HND pol; /* policy handle associated with unknown id */
- uint32 status; /* return status */
-
-} SAMR_R_UNKNOWN_22;
-
-
-/* SAMR_Q_UNKNOWN_24 - probably a get sam info */
-typedef struct q_samr_unknown_24_info
-{
- LSA_POL_HND pol; /* policy handle associated with unknown id */
- uint16 unknown_0; /* 0x0015 or 0x0011 - 16 bit unknown */
-
-} SAMR_Q_UNKNOWN_24;
-
-
-/* SAMR_R_UNKNOWN_24 - probably a get sam info */
-typedef struct r_samr_unknown_24_info
-{
- uint32 ptr; /* pointer */
- uint16 unknown_0; /* 0x0015 or 0x0011 - 16 bit unknown (same as above) */
- uint16 unknown_1; /* 0x8b73 - 16 bit unknown */
- uint8 padding_0[16]; /* 0 - padding 16 bytes */
- NTTIME expiry; /* expiry time or something? */
- uint8 padding_1[24]; /* 0 - padding 24 bytes */
-
- UNIHDR hdr_mach_acct; /* unicode header for machine account */
- uint32 padding_2; /* 0 - padding 4 bytes */
-
- uint32 ptr_1; /* pointer */
- uint8 padding_3[32]; /* 0 - padding 32 bytes */
- uint32 padding_4; /* 0 - padding 4 bytes */
-
- uint32 ptr_2; /* pointer */
- uint32 padding_5; /* 0 - padding 4 bytes */
-
- uint32 ptr_3; /* pointer */
- uint8 padding_6[32]; /* 0 - padding 32 bytes */
-
- uint32 unknown_id_0; /* unknown id associated with policy handle */
- uint16 unknown_2; /* 0x0201 - 16 bit unknown */
- uint32 unknown_3; /* 0x0000 0080 - 32 bit unknown */
- uint16 unknown_4; /* 0x003f - 16 bit unknown */
- uint16 unknown_5; /* 0x003c - 16 bit unknown */
-
- uint8 padding_7[16]; /* 0 - padding 16 bytes */
- uint32 padding_8; /* 0 - padding 4 bytes */
-
- UNISTR2 uni_mach_acct; /* unicode string for machine account */
-
- uint8 padding_9[48]; /* 0 - padding 48 bytes */
-
- uint32 status; /* return status */
-
-} SAMR_R_UNKNOWN_24;
-
-
-/* SAMR_Q_UNKNOWN_32 - probably a "create SAM entry" */
-typedef struct q_samr_unknown_32_info
-{
- LSA_POL_HND pol; /* policy handle */
-
- UNIHDR hdr_mach_acct; /* unicode machine account name header */
- UNISTR2 uni_mach_acct; /* unicode machine account name */
-
- uint32 unknown_0; /* 32 bit unknown */
- uint16 unknown_1; /* 16 bit unknown */
- uint16 unknown_2; /* 16 bit unknown */
-
-} SAMR_Q_UNKNOWN_32;
-
-
-/* SAMR_R_UNKNOWN_32 - probably a "create SAM entry" */
-typedef struct r_samr_unknown_32_info
-{
- LSA_POL_HND pol; /* policy handle */
- uint32 unknown_0; /* 0x0000 0030 - 32 bit unknown */
- uint32 padding; /* 0 - 4 byte padding */
-
- uint32 status; /* return status - 0xC000 0099: user exists */
-
-} SAMR_R_UNKNOWN_32;
-
-
-/* SAMR_Q_OPEN_POLICY - probably an open */
-typedef struct q_samr_open_policy_info
-{
- uint32 ptr_srv_name; /* pointer (to server name?) */
- UNISTR2 uni_srv_name; /* unicode server name starting with '\\' */
-
- uint32 unknown_0; /* 32 bit unknown */
-
-} SAMR_Q_OPEN_POLICY;
-
-
-/* SAMR_R_OPEN_POLICY - probably an open */
-typedef struct r_samr_open_policy_info
-{
- LSA_POL_HND pol; /* policy handle */
- uint32 status; /* return status */
-
-} SAMR_R_OPEN_POLICY;
-
-
-/* WKS_Q_UNKNOWN_0 - probably a capabilities request */
-typedef struct q_wks_unknown_0_info
-{
- uint32 ptr_srv_name; /* pointer (to server name?) */
- UNISTR2 uni_srv_name; /* unicode server name starting with '\\' */
-
- uint32 unknown_0; /* 0x64 - 32 bit unknown */
- uint16 unknown_1; /* 16 bit unknown */
-
-} WKS_Q_UNKNOWN_0;
-
-
-/* WKS_R_UNKNOWN_0 - probably a capabilities request */
-typedef struct r_wks_unknown_0_info
-{
- uint32 unknown_0; /* 64 - unknown */
- uint32 ptr_1; /* pointer 1 */
- uint32 unknown_1; /* 0x0000 01f4 - unknown */
- uint32 ptr_srv_name; /* pointer to server name */
- uint32 ptr_dom_name; /* pointer to domain name */
- uint32 unknown_2; /* 4 - unknown */
- uint32 unknown_3; /* 0 - unknown */
-
- UNISTR2 uni_srv_name; /* unicode server name */
- UNISTR2 uni_dom_name; /* unicode domainn name */
- uint32 status; /* return status */
-
-} WKS_R_UNKNOWN_0;
-
-
-struct smb_passwd
-{
+struct smb_passwd {
int smb_userid;
char *smb_name;
unsigned char *smb_passwd; /* Null if no password */
@@ -1342,6 +260,7 @@ struct smb_passwd
/* Other fields / flags may be added later */
};
+
struct cli_state {
int fd;
int cnum;
@@ -1369,14 +288,12 @@ struct cli_state {
};
-struct current_user
-{
+struct current_user {
int cnum, id;
int uid, gid;
int ngroups;
gid_t *groups;
int *igroups;
- int *attrs;
};
typedef struct
@@ -1390,7 +307,6 @@ typedef struct
time_t atime;
time_t ctime;
pstring name;
-
} file_info;
@@ -1441,8 +357,6 @@ typedef struct
BOOL share_mode;
BOOL print_file;
BOOL modified;
- BOOL granted_oplock;
- BOOL sent_oplock_break;
char *name;
} files_struct;
@@ -1475,60 +389,35 @@ typedef struct
char *user; /* name of user who *opened* this connection */
int uid; /* uid of user who *opened* this connection */
int gid; /* gid of user who *opened* this connection */
-
uint16 vuid; /* vuid of user who *opened* this connection, or UID_FIELD_INVALID */
-
/* following groups stuff added by ih */
-
/* This groups info is valid for the user that *opened* the connection */
int ngroups;
gid_t *groups;
int *igroups; /* an integer version - some OSes are broken :-( */
- int *attrs;
-
time_t lastused;
BOOL used;
int num_files_open;
name_compare_entry *hide_list; /* Per-share list of files to return as hidden. */
name_compare_entry *veto_list; /* Per-share list of files to veto (never show). */
- name_compare_entry *veto_oplock_list; /* Per-share list of files to refuse oplocks on. */
-
} connection_struct;
-/* Domain controller authentication protocol info */
-struct dcinfo
-{
- DOM_CHAL clnt_chal; /* Initial challenge received from client */
- DOM_CHAL srv_chal; /* Initial server challenge */
- DOM_CRED clnt_cred; /* Last client credential */
- DOM_CRED srv_cred; /* Last server credential */
-
- uchar sess_key[8]; /* Session key */
- uchar md4pw[16]; /* md4(machine password) */
-};
typedef struct
{
int uid; /* uid of a validated user */
int gid; /* gid of a validated user */
-
fstring name; /* name of a validated user */
- fstring real_name; /* to store real name from password file - simeon */
BOOL guest;
-
/* following groups stuff added by ih */
/* This groups info is needed for when we become_user() for this uid */
- int n_groups;
- gid_t *groups;
- int *igroups; /* an integer version - some OSes are broken :-( */
- int *attrs; /* attributes associated with each gid */
-
- int n_sids;
- int *sids;
-
- /* per-user authentication information on NT RPCs */
- struct dcinfo dc;
-
+ int user_ngroups;
+ gid_t *user_groups;
+ int *user_igroups; /* an integer version - some OSes are broken :-( */
+#if (defined(NETGROUP) && defined(AUTOMOUNT))
+ char *home_share; /* to store NIS home of a user - simeon */
+#endif
+ char *real_name; /* to store real name from password file - simeon */
} user_struct;
@@ -1573,46 +462,40 @@ struct interface
struct in_addr nmask;
};
-/* struct returned by get_share_modes */
+/* share mode record pointed to in shared memory hash bucket */
+typedef struct
+{
+ smb_shm_offset_t next_offset; /* offset of next record in chain from hash bucket */
+ int locking_version;
+ int32 st_dev;
+ int32 st_ino;
+ int num_share_mode_entries;
+ smb_shm_offset_t share_mode_entries; /* Chain of share mode entries for this file */
+ char file_name[1];
+} share_mode_record;
+
+/* share mode entry pointed to by share_mode_record struct */
typedef struct
{
+ smb_shm_offset_t next_share_mode_entry;
int pid;
- uint16 op_port;
- uint16 op_type;
int share_mode;
struct timeval time;
} share_mode_entry;
+/* struct returned by get_share_modes */
+typedef struct
+{
+ int pid;
+ int share_mode;
+ struct timeval time;
+} min_share_mode_entry;
-/* each implementation of the share mode code needs
- to support the following operations */
-struct share_ops {
- BOOL (*stop_mgmt)(void);
- BOOL (*lock_entry)(int , uint32 , uint32 , int *);
- BOOL (*unlock_entry)(int , uint32 , uint32 , int );
- int (*get_entries)(int , int , uint32 , uint32 , share_mode_entry **);
- void (*del_entry)(int , int );
- BOOL (*set_entry)(int , int , uint16 , uint16 );
- BOOL (*remove_oplock)(int , int);
- int (*forall)(void (*)(share_mode_entry *, char *));
- void (*status)(FILE *);
-};
-
-/* each implementation of the shared memory code needs
- to support the following operations */
-struct shmem_ops {
- BOOL (*shm_close)( void );
- int (*shm_alloc)(int );
- BOOL (*shm_free)(int );
- int (*get_userdef_off)(void);
- void *(*offset2addr)(int );
- int (*addr2offset)(void *addr);
- BOOL (*lock_hash_entry)(unsigned int);
- BOOL (*unlock_hash_entry)( unsigned int );
- BOOL (*get_usage)(int *,int *,int *);
- unsigned (*hash_size)(void);
-};
+/* Token returned by lock_share_entry (actually ignored by FAST_SHARE_MODES code) */
+typedef int share_lock_token;
+/* Conversion to hash entry index from device and inode numbers. */
+#define HASH_ENTRY(dev,ino) ((( (uint32)(dev) )* ( (uint32)(ino) )) % lp_shmem_hash_size())
/* this is used for smbstatus */
struct connect_record
@@ -1628,9 +511,8 @@ struct connect_record
time_t start;
};
-#ifndef LOCKING_VERSION
-#define LOCKING_VERSION 4
-#endif /* LOCKING_VERSION */
+
+#define LOCKING_VERSION 3
/* these are useful macros for checking validity of handles */
#define VALID_FNUM(fnum) (((fnum) >= 0) && ((fnum) < MAX_OPEN_FILES))
@@ -1670,9 +552,12 @@ struct connect_record
#define MAP_ARCHIVE(cnum) (OPEN_CNUM(cnum) && lp_map_archive(SNUM(cnum)))
#define IS_HIDDEN_PATH(cnum,path) (is_in_path((path),Connections[(cnum)].hide_list))
#define IS_VETO_PATH(cnum,path) (is_in_path((path),Connections[(cnum)].veto_list))
-#define IS_VETO_OPLOCK_PATH(cnum,path) (is_in_path((path),Connections[(cnum)].veto_oplock_list))
+#ifdef SMB_PASSWD
#define SMBENCRYPT() (lp_encrypted_passwords())
+#else
+#define SMBENCRYPT() (False)
+#endif
/* the basic packet size, assuming no words or bytes */
#define smb_size 39
@@ -1792,38 +677,23 @@ struct connect_record
#define SMBfindnclose 0x35 /* Terminate a TRANSACT2_FINDNOTIFYFIRST */
#define SMBulogoffX 0x74 /* user logoff */
-/* NT SMB extensions. */
-#define SMBnttrans 0xA0 /* NT transact */
-#define SMBnttranss 0xA1 /* NT transact secondary */
-#define SMBntcreateX 0xA2 /* NT create and X */
-#define SMBntcancel 0xA4 /* NT cancel */
-
-/* These are the TRANS2 sub commands */
-#define TRANSACT2_OPEN 0
-#define TRANSACT2_FINDFIRST 1
-#define TRANSACT2_FINDNEXT 2
-#define TRANSACT2_QFSINFO 3
-#define TRANSACT2_SETFSINFO 4
-#define TRANSACT2_QPATHINFO 5
-#define TRANSACT2_SETPATHINFO 6
-#define TRANSACT2_QFILEINFO 7
-#define TRANSACT2_SETFILEINFO 8
-#define TRANSACT2_FSCTL 9
-#define TRANSACT2_IOCTL 0xA
-#define TRANSACT2_FINDNOTIFYFIRST 0xB
-#define TRANSACT2_FINDNOTIFYNEXT 0xC
-#define TRANSACT2_MKDIR 0xD
-#define TRANSACT2_SESSION_SETUP 0xE
-#define TRANSACT2_GET_DFS_REFERRAL 0x10
-#define TRANSACT2_REPORT_DFS_INCONSISTANCY 0x11
-
-/* These are the NT transact sub commands. */
-#define NT_TRANSACT_CREATE 1
-#define NT_TRANSACT_IOCTL 2
-#define NT_TRANSACT_SET_SECURITY_DESC 3
-#define NT_TRANSACT_NOTIFY_CHANGE 4
-#define NT_TRANSACT_RENAME 5
-#define NT_TRANSACT_QUERY_SECURITY_DESC 6
+
+/* these are the TRANS2 sub commands */
+#define TRANSACT2_OPEN 0
+#define TRANSACT2_FINDFIRST 1
+#define TRANSACT2_FINDNEXT 2
+#define TRANSACT2_QFSINFO 3
+#define TRANSACT2_SETFSINFO 4
+#define TRANSACT2_QPATHINFO 5
+#define TRANSACT2_SETPATHINFO 6
+#define TRANSACT2_QFILEINFO 7
+#define TRANSACT2_SETFILEINFO 8
+#define TRANSACT2_FSCTL 9
+#define TRANSACT2_IOCTL 10
+#define TRANSACT2_FINDNOTIFYFIRST 11
+#define TRANSACT2_FINDNOTIFYNEXT 12
+#define TRANSACT2_MKDIR 13
+
/* these are the trans2 sub fields for primary requests */
#define smb_tpscnt smb_vwv0
@@ -2083,97 +953,18 @@ enum case_handling {CASE_LOWER,CASE_UPPER};
#endif
-/* Defines needed for multi-codepage support. */
-#define KANJI_CODEPAGE 932
-
#ifdef KANJI
-/*
- * Default client code page - Japanese
- */
-#define DEFAULT_CLIENT_CODE_PAGE KANJI_CODEPAGE
+/* Default client code page - 932 - Japanese */
+#define DEFAULT_CLIENT_CODE_PAGE 932
#else /* KANJI */
-/*
- * Default client code page - 850 - Western European
- */
+/* Default client code page - 850 - Western European */
#define DEFAULT_CLIENT_CODE_PAGE 850
#endif /* KANJI */
-/*
- * Size of buffer to use when moving files across filesystems.
- */
+/* Size of buffer to use when moving files across filesystems. */
#define COPYBUF_SIZE (8*1024)
-/*
- * Integers used to override error codes.
- */
+/* Integers used to override error codes. */
extern int unix_ERR_class;
extern int unix_ERR_code;
-
-/*
- * Map the Core and Extended Oplock requesst bits down
- * to common bits (EXCLUSIVE_OPLOCK & BATCH_OPLOCK).
- */
-
-/*
- * Core protocol.
- */
-#define CORE_OPLOCK_REQUEST(inbuf) ((CVAL(inbuf,smb_flg)&((1<<5)|(1<<6)))>>5)
-
-/*
- * Extended protocol.
- */
-#define EXTENDED_OPLOCK_REQUEST(inbuf) ((SVAL(inbuf,smb_vwv2)&((1<<1)|(1<<2)))>>1)
-
-/* Lock types. */
-#define LOCKING_ANDX_SHARED_LOCK 0x1
-#define LOCKING_ANDX_OPLOCK_RELEASE 0x2
-#define LOCKING_ANDX_CHANGE_LOCKTYPE 0x4
-#define LOCKING_ANDX_CANCEL_LOCK 0x8
-#define LOCKING_ANDX_LARGE_FILES 0x10
-
-/* Oplock levels */
-#define OPLOCKLEVEL_NONE 0
-#define OPLOCKLEVEL_II 1
-
-/*
- * Bits we test with.
- */
-#define EXCLUSIVE_OPLOCK 1
-#define BATCH_OPLOCK 2
-
-#define CORE_OPLOCK_GRANTED (1<<5)
-#define EXTENDED_OPLOCK_GRANTED (1<<15)
-
-/*
- * Loopback command offsets.
- */
-
-#define UDP_CMD_LEN_OFFSET 0
-#define UDP_CMD_PORT_OFFSET 4
-#define UDP_CMD_HEADER_LEN 6
-
-#define UDP_MESSAGE_CMD_OFFSET 0
-
-/*
- * Oplock break command code to send over the udp socket.
- *
- * Form of this is :
- *
- * 0 2 6 10 14 18 22
- * +----+--------+--------+--------+-------+--------+
- * | cmd| pid | dev | inode | sec | usec |
- * +----+--------+--------+--------+-------+--------+
- */
-
-#define OPLOCK_BREAK_CMD 0x1
-#define OPLOCK_BREAK_PID_OFFSET 2
-#define OPLOCK_BREAK_DEV_OFFSET 6
-#define OPLOCK_BREAK_INODE_OFFSET 10
-#define OPLOCK_BREAK_SEC_OFFSET 14
-#define OPLOCK_BREAK_USEC_OFFSET 18
-#define OPLOCK_BREAK_MSG_LEN 22
-
-
-#define CMD_REPLY 0x8000
-
/* _SMB_H */
diff --git a/source/include/trans2.h b/source/include/trans2.h
index 5218604e0e1..9a2de631095 100644
--- a/source/include/trans2.h
+++ b/source/include/trans2.h
@@ -238,6 +238,13 @@ Byte offset Type name description
#define NT_FILE_ATTRIBUTE_NORMAL 0x80
+/* Function prototypes */
+
+
+int reply_findnclose(char *inbuf,char *outbuf,int length,int bufsize);
+
+int reply_findclose(char *inbuf,char *outbuf,int length,int bufsize);
+
#endif
diff --git a/source/include/version.h b/source/include/version.h
index 1d79e7103ec..0ca26ef5057 100644
--- a/source/include/version.h
+++ b/source/include/version.h
@@ -1 +1 @@
-#define VERSION "1.9.18alpha13"
+#define VERSION "1.9.17p5"
diff --git a/source/lib/access.c b/source/lib/access.c
index c338517ed67..599cb5ca7e3 100644
--- a/source/lib/access.c
+++ b/source/lib/access.c
@@ -70,8 +70,8 @@ BOOL check_access(int snum)
}
else
if (snum >= 0)
- DEBUG(0,("%s Denied connection from %s (%s) to %s\n",
- timestring(), client_name(),client_addr(),
+ DEBUG(0,("Denied connection from %s (%s) to %s\n",
+ client_name(),client_addr(),
lp_servicename(snum)));
}
diff --git a/source/lib/charcnv.c b/source/lib/charcnv.c
index e1a7ac01db5..28020448d83 100644
--- a/source/lib/charcnv.c
+++ b/source/lib/charcnv.c
@@ -107,18 +107,13 @@ char *unix2dos_format(char *str,BOOL overwrite)
char *dp;
if (!mapsinited) initmaps();
-
- if(lp_client_code_page() == KANJI_CODEPAGE)
- return (*_unix_to_dos)(str, overwrite);
- else {
- if (overwrite) {
- for (p = str; *p; p++) *p = unix2dos[(unsigned char)*p];
- return str;
- } else {
- for (p = str, dp = cvtbuf; *p; p++,dp++) *dp = unix2dos[(unsigned char)*p];
- *dp = 0;
- return cvtbuf;
- }
+ if (overwrite) {
+ for (p = str; *p; p++) *p = unix2dos[(unsigned char)*p];
+ return str;
+ } else {
+ for (p = str, dp = cvtbuf; *p; p++,dp++) *dp = unix2dos[(unsigned char)*p];
+ *dp = 0;
+ return cvtbuf;
}
}
@@ -131,18 +126,13 @@ char *dos2unix_format(char *str, BOOL overwrite)
char *dp;
if (!mapsinited) initmaps();
-
- if(lp_client_code_page() == KANJI_CODEPAGE)
- return (*_dos_to_unix)(str, overwrite);
- else {
- if (overwrite) {
- for (p = str; *p; p++) *p = dos2unix[(unsigned char)*p];
- return str;
- } else {
- for (p = str, dp = cvtbuf; *p; p++,dp++) *dp = dos2unix[(unsigned char)*p];
- *dp = 0;
- return cvtbuf;
- }
+ if (overwrite) {
+ for (p = str; *p; p++) *p = dos2unix[(unsigned char)*p];
+ return str;
+ } else {
+ for (p = str, dp = cvtbuf; *p; p++,dp++) *dp = dos2unix[(unsigned char)*p];
+ *dp = 0;
+ return cvtbuf;
}
}
diff --git a/source/lib/charset.c b/source/lib/charset.c
index e29e60303aa..c4f67e75fb1 100644
--- a/source/lib/charset.c
+++ b/source/lib/charset.c
@@ -28,7 +28,6 @@ extern int DEBUGLEVEL;
* Codepage definitions.
*/
-#if !defined(KANJI)
/* lower->upper mapping for IBM Code Page 850 - MS-DOS Latin 1 */
unsigned char cp_850[][4] = {
/* dec col/row oct hex description */
@@ -96,13 +95,74 @@ unsigned char cp_850[][4] = {
{0x9C,0,0,0}, /* Pound */
{0,0,0,0}
};
-#else /* KANJI */
+
+/* lower->upper mapping for IBM Code Page 437 - MS-DOS Latin US */
+unsigned char cp_437[][4] = {
+/* 135 08/07 207 87 c cedilla */
+/* 128 08/00 200 80 C cedilla */ {0x87,0x80,1,1},
+/* 129 08/01 201 81 u diaeresis */
+/* 154 09/10 232 9A U diaeresis */ {0x81,0x9A,1,1},
+/* 130 08/02 202 82 e acute */
+/* 144 09/00 220 90 E acute */ {0x82,0x90,1,1},
+/* 131 08/03 203 83 a circumflex */ {0x83,0x41,1,0},
+/* 132 08/04 204 84 a diaeresis */
+/* 142 08/14 216 8E A diaeresis */ {0x84,0x8E,1,1},
+/* 133 08/05 205 85 a grave */ {0x85,0x41,1,0},
+/* 134 08/06 206 86 a ring */ {0x86,0x8F,1,1},
+/* 136 08/08 210 88 e circumflex */ {0x88,0x45,1,0},
+/* 137 08/09 211 89 e diaeresis */ {0x89,0x45,1,0},
+/* 138 08/10 212 8A e grave */ {0x8A,0x45,1,0},
+/* 139 08/11 213 8B i diaeresis */ {0x8B,0x49,1,0},
+/* 140 08/12 214 8C i circumflex */ {0x8C,0x49,1,0},
+/* 141 08/13 215 8D i grave */ {0x8D,0x49,1,0},
+/* 145 09/01 221 91 ae diphthong */
+/* 146 09/02 222 92 AE diphthong */ {0x91,0x92,1,1},
+/* 147 09/03 223 93 o circumflex */ {0x93,0x4F,1,0},
+/* 148 09/04 224 94 o diaeresis */
+/* 153 09/09 231 99 O diaeresis */ {0x94,0x99,1,1},
+/* 149 09/05 225 95 o grave */ {0x95,0x4F,1,0},
+/* 150 09/06 226 96 u circumflex */ {0x96,0x55,1,0},
+/* 151 09/07 227 97 u grave */ {0x97,0x55,1,0},
+/* 152 ??/?? 201 98 u diaeresis */
+ {0x9B,0,0,0}, /* Cent */
+ {0x9C,0,0,0}, /* Pound */
+ {0x9D,0,0,0}, /* Yen */
+/* 160 10/00 240 A0 a acute */ {0xA0,0x41,1,0},
+/* 161 10/01 241 A1 i acute */ {0xA1,0x49,1,0},
+/* 162 10/02 242 A2 o acute */ {0xA2,0x4F,1,0},
+/* 163 10/03 243 A3 u acute */ {0xA3,0x55,1,0},
+/* 164 10/04 244 A4 n tilde */
+/* 165 10/05 245 A5 N tilde */ {0xA4,0xA5,1,1},
+/* Punctuation... */
+ {0xA8,0,0,0},
+ {0xAD,0,0,0},
+ {0xAE,0,0,0},
+ {0xAF,0,0,0},
+/* Greek character set */
+ {0xE0,0,0,0},
+ {0xE1,0,0,0},
+ {0xE2,0,0,0},
+ {0xE3,0,0,0},
+ {0xE4,0,0,0},
+ {0xE5,0,0,0},
+ {0xE6,0,0,0},
+ {0xE7,0,0,0},
+ {0xE8,0,0,0},
+ {0xE9,0,0,0},
+ {0xEA,0,0,0},
+ {0xEB,0,0,0},
+ {0xEC,0,0,0},
+ {0xED,0,0,0},
+ {0xEE,0,0,0},
+ {0xEF,0,0,0},
+ {0,0,0,0}
+};
+
/* lower->upper mapping for IBM Code Page 932 - MS-DOS Japanese SJIS */
unsigned char cp_932[][4] = {
{0,0,0,0}
};
-#endif /* KANJI */
-
+
char xx_dos_char_map[256];
char xx_upper_char_map[256];
char xx_lower_char_map[256];
@@ -132,13 +192,11 @@ static void add_dos_char(int lower, BOOL map_lower_to_upper,
map_upper_to_lower ? "True" : "False"));
if (lower) dos_char_map[lower] = 1;
if (upper) dos_char_map[upper] = 1;
- lower_char_map[lower] = (char)lower; /* Define tolower(lower) */
- upper_char_map[upper] = (char)upper; /* Define toupper(upper) */
if (lower && upper) {
if(map_upper_to_lower)
- lower_char_map[upper] = (char)lower;
+ lower_char_map[upper] = (char)lower;
if(map_lower_to_upper)
- upper_char_map[lower] = (char)upper;
+ upper_char_map[lower] = (char)upper;
}
}
@@ -167,163 +225,18 @@ void charset_initialise()
for (i=0; i<=255; i++) {
char c = (char)i;
upper_char_map[i] = lower_char_map[i] = c;
-
- /* Some systems have buggy isupper/islower for characters
- above 127. Best not to rely on them. */
- if(i < 128) {
- if (isupper(c)) lower_char_map[i] = tolower(c);
- if (islower(c)) upper_char_map[i] = toupper(c);
- }
+ if (isupper(c)) lower_char_map[i] = tolower(c);
+ if (islower(c)) upper_char_map[i] = toupper(c);
}
}
/****************************************************************************
-load the client codepage.
-****************************************************************************/
-
-typedef unsigned char (*codepage_p)[4];
-
-static codepage_p load_client_codepage( int client_codepage )
-{
- pstring codepage_file_name;
- unsigned char buf[8];
- FILE *fp = NULL;
- unsigned int size;
- codepage_p cp_p = NULL;
- struct stat st;
-
- DEBUG(5, ("load_client_codepage: loading codepage %d.\n", client_codepage));
-
- if(strlen(CODEPAGEDIR) + 14 > sizeof(codepage_file_name))
- {
- DEBUG(0,("load_client_codepage: filename too long to load\n"));
- return NULL;
- }
-
- strcpy(codepage_file_name, CODEPAGEDIR);
- strcat(codepage_file_name, "/");
- strcat(codepage_file_name, "codepage.");
- sprintf( &codepage_file_name[strlen(codepage_file_name)], "%03d",
- client_codepage);
-
- if(!file_exist(codepage_file_name,&st))
- {
- DEBUG(0,("load_client_codepage: filename %s does not exist.\n",
- codepage_file_name));
- return NULL;
- }
-
- /* Check if it is at least big enough to hold the required
- data. Should be 2 byte version, 2 byte codepage, 4 byte length,
- plus zero or more bytes of data. Note that the data cannot be more
- than 512 bytes - giving a max size of 520.
- */
- size = (unsigned int)st.st_size;
-
- if( size < CODEPAGE_HEADER_SIZE || size > (CODEPAGE_HEADER_SIZE + 256))
- {
- DEBUG(0,("load_client_codepage: file %s is an incorrect size for a \
-code page file.\n", codepage_file_name));
- return NULL;
- }
-
- /* Read the first 8 bytes of the codepage file - check
- the version number and code page number. All the data
- is held in little endian format.
- */
-
- if((fp = fopen( codepage_file_name, "r")) == NULL)
- {
- DEBUG(0,("load_client_codepage: cannot open file %s. Error was %s\n",
- codepage_file_name, strerror(errno)));
- return NULL;
- }
-
- if(fread( buf, 1, CODEPAGE_HEADER_SIZE, fp)!=CODEPAGE_HEADER_SIZE)
- {
- DEBUG(0,("load_client_codepage: cannot read header from file %s. Error was %s\n",
- codepage_file_name, strerror(errno)));
- goto clean_and_exit;
- }
-
- /* Check the version value */
- if(SVAL(buf,CODEPAGE_VERSION_OFFSET) != CODEPAGE_FILE_VERSION_ID)
- {
- DEBUG(0,("load_client_codepage: filename %s has incorrect version id. \
-Needed %hu, got %hu.\n",
- codepage_file_name, (uint16)CODEPAGE_FILE_VERSION_ID,
- SVAL(buf,CODEPAGE_VERSION_OFFSET)));
- goto clean_and_exit;
- }
-
- /* Check the codepage matches */
- if(SVAL(buf,CODEPAGE_CLIENT_CODEPAGE_OFFSET) != (uint16)client_codepage)
- {
- DEBUG(0,("load_client_codepage: filename %s has incorrect codepage. \
-Needed %hu, got %hu.\n",
- codepage_file_name, (uint16)client_codepage,
- SVAL(buf,CODEPAGE_CLIENT_CODEPAGE_OFFSET)));
- goto clean_and_exit;
- }
-
- /* Check the length is correct. */
- if(IVAL(buf,CODEPAGE_LENGTH_OFFSET) !=
- (unsigned int)(size - CODEPAGE_HEADER_SIZE))
- {
- DEBUG(0,("load_client_codepage: filename %s has incorrect size headers. \
-Needed %u, got %u.\n", codepage_file_name, size - CODEPAGE_HEADER_SIZE,
- IVAL(buf,CODEPAGE_LENGTH_OFFSET)));
- goto clean_and_exit;
- }
-
- size -= CODEPAGE_HEADER_SIZE; /* Remove header */
-
- /* Make sure the size is a multiple of 4. */
- if((size % 4 ) != 0)
- {
- DEBUG(0,("load_client_codepage: filename %s has a codepage size not a \
-multiple of 4.\n", codepage_file_name));
- goto clean_and_exit;
- }
-
- /* Allocate space for the code page file and read it all in. */
- if((cp_p = (codepage_p)malloc( size + 4 )) == NULL)
- {
- DEBUG(0,("load_client_codepage: malloc fail.\n"));
- goto clean_and_exit;
- }
-
- if(fread( (char *)cp_p, 1, size, fp)!=size)
- {
- DEBUG(0,("load_client_codepage: read fail on file %s. Error was %s.\n",
- codepage_file_name, strerror(errno)));
- goto clean_and_exit;
- }
-
- /* Ensure array is correctly terminated. */
- memset(((char *)cp_p) + size, '\0', 4);
-
- fclose(fp);
- return cp_p;
-
-clean_and_exit:
-
- /* pseudo destructor :-) */
-
- if(fp != NULL)
- fclose(fp);
- if(cp_p)
- free((char *)cp_p);
- return NULL;
-}
-
-/****************************************************************************
initialise the client codepage.
****************************************************************************/
void codepage_initialise(int client_codepage)
{
int i;
- codepage_p cp = NULL;
+ unsigned char (*cp)[4] = NULL;
static BOOL done = False;
if(done == True)
@@ -339,21 +252,30 @@ void codepage_initialise(int client_codepage)
/*
* Known client codepages - these can be added to.
*/
- cp = load_client_codepage( client_codepage );
-
- if(cp == NULL)
+ switch(client_codepage)
{
+ case 850:
+ cp = cp_850;
+ break;
+ case 437:
+ cp = cp_437;
+ break;
+ case 932:
+ cp = cp_932;
+ break;
+ default:
#ifdef KANJI
- DEBUG(6,("codepage_initialise: loading dynamic codepage file %s/codepage.%d \
-for code page %d failed. Using default client codepage 932\n",
- CODEPAGEDIR, client_codepage, client_codepage));
- cp = cp_932;
+ /* Use default codepage - currently 932 */
+ DEBUG(6,("codepage_initialise: Using default client codepage %d\n",
+ 932));
+ cp = cp_932;
#else /* KANJI */
- DEBUG(6,("codepage_initialise: loading dynamic codepage file %s/codepage.%d \
-for code page %d failed. Using default client codepage 850\n",
- CODEPAGEDIR, client_codepage, client_codepage));
- cp = cp_850;
+ /* Use default codepage - currently 850 */
+ DEBUG(6,("codepage_initialise: Using default client codepage %d\n",
+ 850));
+ cp = cp_850;
#endif /* KANJI */
+ break;
}
if(cp)
diff --git a/source/lib/getsmbpass.c b/source/lib/getsmbpass.c
index e8cb683d0b1..9008d40f910 100644
--- a/source/lib/getsmbpass.c
+++ b/source/lib/getsmbpass.c
@@ -45,7 +45,7 @@ static struct termio t;
return ioctl(fd, TCGETA, t);
}
- int tcsetattr(int fd, int flags, struct termio *t)
+ int tcsetattr(int fd, int flags, const struct termio *t)
{
if(flags & TCSAFLUSH)
ioctl(fd, TCFLSH, TCIOFLUSH);
@@ -76,7 +76,7 @@ static struct sgttyb t;
return ioctl(fd, TIOCGETP, (char *)t);
}
- int tcsetattr(int fd, int flags, struct sgttyb *t)
+ int tcsetattr(int fd, int flags, const struct sgttyb *t)
{
return ioctl(fd, TIOCSETP, (char *)t);
}
diff --git a/source/lib/interface.c b/source/lib/interface.c
index 0008ad889df..1dc605ff2fd 100644
--- a/source/lib/interface.c
+++ b/source/lib/interface.c
@@ -24,7 +24,7 @@
extern int DEBUGLEVEL;
struct in_addr ipzero;
-struct in_addr allones_ip;
+struct in_addr wins_ip;
struct in_addr loopback_ip;
static struct in_addr default_ip;
static struct in_addr default_bcast;
@@ -33,7 +33,7 @@ static BOOL got_ip=False;
static BOOL got_bcast=False;
static BOOL got_nmask=False;
-static struct interface *local_interfaces = NULL;
+struct interface *local_interfaces = NULL;
struct interface *last_iface;
@@ -262,7 +262,7 @@ static void interpret_interfaces(char *s, struct interface **interfaces,
struct in_addr ip;
ipzero = *interpret_addr2("0.0.0.0");
- allones_ip = *interpret_addr2("255.255.255.255");
+ wins_ip = *interpret_addr2("255.255.255.255");
loopback_ip = *interpret_addr2("127.0.0.1");
while (next_token(&ptr,token,NULL)) {
@@ -302,9 +302,9 @@ static void interpret_interfaces(char *s, struct interface **interfaces,
last_iface->next = iface;
}
last_iface = iface;
- DEBUG(2,("Added %s ip=%s ",description,inet_ntoa(iface->ip)));
- DEBUG(2,("bcast=%s ",inet_ntoa(iface->bcast)));
- DEBUG(2,("nmask=%s\n",inet_ntoa(iface->nmask)));
+ DEBUG(1,("Added %s ip=%s ",description,inet_ntoa(iface->ip)));
+ DEBUG(1,("bcast=%s ",inet_ntoa(iface->bcast)));
+ DEBUG(1,("nmask=%s\n",inet_ntoa(iface->nmask)));
}
if (*interfaces) return;
@@ -400,18 +400,6 @@ BOOL ismybcast(struct in_addr bcast)
}
/****************************************************************************
- check if a packet is from a local (known) net
- **************************************************************************/
-BOOL is_local_net(struct in_addr from)
-{
- struct interface *i;
- for (i=local_interfaces;i;i=i->next)
- if((from.s_addr & i->nmask.s_addr) == (i->ip.s_addr & i->nmask.s_addr))
- return True;
- return False;
-}
-
-/****************************************************************************
how many interfaces do we have
**************************************************************************/
int iface_count(void)
@@ -425,33 +413,6 @@ int iface_count(void)
}
/****************************************************************************
- True if we have two or more interfaces.
- **************************************************************************/
-BOOL we_are_multihomed()
-{
- static int multi = -1;
-
- if(multi == -1)
- multi = (iface_count() > 1 ? True : False);
-
- return multi;
-}
-
-/****************************************************************************
- return the Nth interface
- **************************************************************************/
-struct interface *get_interface(int n)
-{
- struct interface *i;
-
- for (i=local_interfaces;i && n;i=i->next)
- n--;
-
- if (i) return i;
- return NULL;
-}
-
-/****************************************************************************
return IP of the Nth interface
**************************************************************************/
struct in_addr *iface_n_ip(int n)
@@ -465,9 +426,6 @@ struct in_addr *iface_n_ip(int n)
return NULL;
}
-/****************************************************************************
-Try and find an interface that matches an ip. If we cannot, return NULL
- **************************************************************************/
static struct interface *iface_find(struct in_addr ip)
{
struct interface *i;
@@ -476,30 +434,25 @@ static struct interface *iface_find(struct in_addr ip)
for (i=local_interfaces;i;i=i->next)
if (same_net(i->ip,ip,i->nmask)) return i;
- return NULL;
+ return local_interfaces;
}
/* these 3 functions return the ip/bcast/nmask for the interface
- most appropriate for the given ip address. If they can't find
- an appropriate interface they return the requested field of the
- first known interface. */
+ most appropriate for the given ip address */
struct in_addr *iface_bcast(struct in_addr ip)
{
- struct interface *i = iface_find(ip);
- return(i ? &i->bcast : &local_interfaces->bcast);
+ return(&iface_find(ip)->bcast);
}
struct in_addr *iface_nmask(struct in_addr ip)
{
- struct interface *i = iface_find(ip);
- return(i ? &i->nmask : &local_interfaces->nmask);
+ return(&iface_find(ip)->nmask);
}
struct in_addr *iface_ip(struct in_addr ip)
{
- struct interface *i = iface_find(ip);
- return(i ? &i->ip : &local_interfaces->ip);
+ return(&iface_find(ip)->ip);
}
diff --git a/source/lib/kanji.c b/source/lib/kanji.c
index f6aace84116..479763fd406 100644
--- a/source/lib/kanji.c
+++ b/source/lib/kanji.c
@@ -23,14 +23,18 @@
and add all jis codes sequence type at 1995.8.16
Notes: Hexadecimal code by <ohki@gssm.otuka.tsukuba.ac.jp>
*/
+#ifdef KANJI
#define _KANJI_C_
#include "includes.h"
+/* coding system keep in */
+int coding_system = SJIS_CODE;
+
/* jis si/so sequence */
-static char jis_kso = JIS_KSO;
-static char jis_ksi = JIS_KSI;
-static char hex_tag = HEXTAG;
+char jis_kso = JIS_KSO;
+char jis_ksi = JIS_KSI;
+char hex_tag = HEXTAG;
/*******************************************************************
SHIFT JIS functions
@@ -39,11 +43,9 @@ static char hex_tag = HEXTAG;
search token from S1 separated any char of S2
S1 contain SHIFT JIS chars.
********************************************************************/
-char *sj_strtok(char *s1, char *s2)
+char *
+sj_strtok (char *s1, const char *s2)
{
- if (lp_client_code_page() != KANJI_CODEPAGE) {
- return strtok(s1, s2);
- } else {
static char *s = NULL;
char *q;
if (!s1) {
@@ -75,19 +77,16 @@ char *sj_strtok(char *s1, char *s2)
return q;
}
return NULL;
- }
}
/*******************************************************************
search string S2 from S1
S1 contain SHIFT JIS chars.
********************************************************************/
-char *sj_strstr(char *s1, char *s2)
+char *
+sj_strstr (const char *s1, const char *s2)
{
- if (lp_client_code_page() != KANJI_CODEPAGE) {
- return strstr(s1, s2);
- } else {
- int len = strlen ((char *) s2);
+ register int len = strlen ((char *) s2);
if (!*s2)
return (char *) s1;
for (;*s1;) {
@@ -102,18 +101,15 @@ char *sj_strstr(char *s1, char *s2)
}
}
return 0;
- }
}
/*******************************************************************
Search char C from beginning of S.
S contain SHIFT JIS chars.
********************************************************************/
-char *sj_strchr (char *s, int c)
+char *
+sj_strchr (const char *s, int c)
{
- if (lp_client_code_page() != KANJI_CODEPAGE) {
- return strchr(s, c);
- } else {
for (; *s; ) {
if (*s == c)
return (char *) s;
@@ -124,19 +120,16 @@ char *sj_strchr (char *s, int c)
}
}
return 0;
- }
}
/*******************************************************************
Search char C end of S.
S contain SHIFT JIS chars.
********************************************************************/
-char *sj_strrchr(char *s, int c)
+char *
+sj_strrchr (const char *s, int c)
{
- if (lp_client_code_page() != KANJI_CODEPAGE) {
- return strrchr(s, c);
- } else {
- char *q;
+ register char *q;
for (q = 0; *s; ) {
if (*s == c) {
@@ -149,7 +142,6 @@ char *sj_strrchr(char *s, int c)
}
}
return q;
- }
}
/*******************************************************************
@@ -161,7 +153,8 @@ static char cvtbuf[1024];
/*******************************************************************
EUC <-> SJIS
********************************************************************/
-static int euc2sjis (int hi, int lo)
+static int
+euc2sjis (register int hi, register int lo)
{
if (hi & 1)
return ((hi / 2 + (hi < 0xdf ? 0x31 : 0x71)) << 8) |
@@ -170,7 +163,8 @@ static int euc2sjis (int hi, int lo)
return ((hi / 2 + (hi < 0xdf ? 0x30 : 0x70)) << 8) | (lo - 2);
}
-static int sjis2euc (int hi, int lo)
+static int
+sjis2euc (register int hi, register int lo)
{
if (lo >= 0x9f)
return ((hi * 2 - (hi >= 0xe0 ? 0xe0 : 0x60)) << 8) | (lo + 2);
@@ -183,9 +177,10 @@ static int sjis2euc (int hi, int lo)
Convert FROM contain SHIFT JIS codes to EUC codes
return converted buffer
********************************************************************/
-static char *sj_to_euc(char *from, BOOL overwrite)
+static char *
+sj_to_euc (const char *from, BOOL overwrite)
{
- char *out;
+ register char *out;
char *save;
save = (char *) from;
@@ -215,9 +210,10 @@ static char *sj_to_euc(char *from, BOOL overwrite)
Convert FROM contain EUC codes to SHIFT JIS codes
return converted buffer
********************************************************************/
-static char *euc_to_sj(char *from, BOOL overwrite)
+static char *
+euc_to_sj (const char *from, BOOL overwrite)
{
- char *out;
+ register char *out;
char *save;
save = (char *) from;
@@ -246,7 +242,8 @@ static char *euc_to_sj(char *from, BOOL overwrite)
/*******************************************************************
JIS7,JIS8,JUNET <-> SJIS
********************************************************************/
-static int sjis2jis(int hi, int lo)
+static int
+sjis2jis (register int hi, register int lo)
{
if (lo >= 0x9f)
return ((hi * 2 - (hi >= 0xe0 ? 0x160 : 0xe0)) << 8) | (lo - 0x7e);
@@ -255,7 +252,8 @@ static int sjis2jis(int hi, int lo)
(lo - (lo >= 0x7f ? 0x20 : 0x1f));
}
-static int jis2sjis(int hi, int lo)
+static int
+jis2sjis (register int hi, register int lo)
{
if (hi & 1)
return ((hi / 2 + (hi < 0x5f ? 0x71 : 0xb1)) << 8) |
@@ -268,10 +266,11 @@ static int jis2sjis(int hi, int lo)
Convert FROM contain JIS codes to SHIFT JIS codes
return converted buffer
********************************************************************/
-static char *jis8_to_sj(char *from, BOOL overwrite)
+static char *
+jis8_to_sj (const char *from, BOOL overwrite)
{
- char *out;
- int shifted;
+ register char *out;
+ register int shifted;
char *save;
shifted = _KJ_ROMAN;
@@ -318,10 +317,11 @@ static char *jis8_to_sj(char *from, BOOL overwrite)
Convert FROM contain SHIFT JIS codes to JIS codes
return converted buffer
********************************************************************/
-static char *sj_to_jis8(char *from, BOOL overwrite)
+static char *
+sj_to_jis8 (const char *from, BOOL overwrite)
{
- char *out;
- int shifted;
+ register char *out;
+ register int shifted;
char *save;
shifted = _KJ_ROMAN;
@@ -374,10 +374,11 @@ static char *sj_to_jis8(char *from, BOOL overwrite)
Convert FROM contain 7 bits JIS codes to SHIFT JIS codes
return converted buffer
********************************************************************/
-static char *jis7_to_sj(char *from, BOOL overwrite)
+static char *
+jis7_to_sj (const char *from, BOOL overwrite)
{
- char *out;
- int shifted;
+ register char *out;
+ register int shifted;
char *save;
shifted = _KJ_ROMAN;
@@ -433,10 +434,11 @@ static char *jis7_to_sj(char *from, BOOL overwrite)
Convert FROM contain SHIFT JIS codes to 7 bits JIS codes
return converted buffer
********************************************************************/
-static char *sj_to_jis7(char *from, BOOL overwrite)
+static char *
+sj_to_jis7 (const char *from, BOOL overwrite)
{
- char *out;
- int shifted;
+ register char *out;
+ register int shifted;
char *save;
shifted = _KJ_ROMAN;
@@ -509,10 +511,11 @@ static char *sj_to_jis7(char *from, BOOL overwrite)
Convert FROM contain 7 bits JIS(junet) codes to SHIFT JIS codes
return converted buffer
********************************************************************/
-static char *junet_to_sj(char *from, BOOL overwrite)
+static char *
+junet_to_sj (const char *from, BOOL overwrite)
{
- char *out;
- int shifted;
+ register char *out;
+ register int shifted;
char *save;
shifted = _KJ_ROMAN;
@@ -565,10 +568,11 @@ static char *junet_to_sj(char *from, BOOL overwrite)
Convert FROM contain SHIFT JIS codes to 7 bits JIS(junet) codes
return converted buffer
********************************************************************/
-static char *sj_to_junet(char *from, BOOL overwrite)
+static char *
+sj_to_junet (const char *from, BOOL overwrite)
{
- char *out;
- int shifted;
+ register char *out;
+ register int shifted;
char *save;
shifted = _KJ_ROMAN;
@@ -634,7 +638,8 @@ static char *sj_to_junet(char *from, BOOL overwrite)
HEX <-> SJIS
********************************************************************/
/* ":xx" -> a byte */
-static char *hex_to_sj(char *from, BOOL overwrite)
+static char *
+hex_to_sj (const char *from, BOOL overwrite)
{
char *sp, *dp;
@@ -659,7 +664,8 @@ static char *hex_to_sj(char *from, BOOL overwrite)
/*******************************************************************
kanji/kana -> ":xx"
********************************************************************/
-static char *sj_to_hex(char *from, BOOL overwrite)
+static char *
+sj_to_hex (const char *from, BOOL overwrite)
{
unsigned char *sp, *dp;
@@ -695,7 +701,8 @@ static char *sj_to_hex(char *from, BOOL overwrite)
/*******************************************************************
kanji/kana -> ":xx"
********************************************************************/
-static char *sj_to_cap(char *from, BOOL overwrite)
+static char *
+sj_to_cap (const char *from, BOOL overwrite)
{
unsigned char *sp, *dp;
@@ -723,7 +730,8 @@ static char *sj_to_cap(char *from, BOOL overwrite)
/*******************************************************************
sj to sj
********************************************************************/
-static char *sj_to_sj(char *from, BOOL overwrite)
+static char *
+sj_to_sj (const char *from, BOOL overwrite)
{
if (!overwrite) {
strcpy (cvtbuf, (char *) from);
@@ -738,10 +746,11 @@ static char *sj_to_sj(char *from, BOOL overwrite)
_dos_to_unix _unix_to_dos
************************************************************************/
-char *(*_dos_to_unix)(char *str, BOOL overwrite) = sj_to_sj;
-char *(*_unix_to_dos)(char *str, BOOL overwrite) = sj_to_sj;
+char* (*_dos_to_unix) (const char *str, BOOL overwrite) = sj_to_sj;
+char* (*_unix_to_dos) (const char *str, BOOL overwrite) = sj_to_sj;
-static int setup_string_function(int codes)
+static int
+setup_string_function (int codes)
{
switch (codes) {
default:
@@ -787,9 +796,9 @@ static int setup_string_function(int codes)
/*
* Interpret coding system.
*/
-int interpret_coding_system(char *str)
+int interpret_coding_system(char *str, int def)
{
- int codes = UNKNOWN_CODE;
+ int codes = def;
if (strequal (str, "sjis")) {
codes = SJIS_CODE;
@@ -879,3 +888,7 @@ int interpret_coding_system(char *str)
}
return setup_string_function (codes);
}
+#else
+ int kanji_dummy_procedure(void)
+{return 0;}
+#endif /* KANJI */
diff --git a/source/lib/md4.c b/source/lib/md4.c
index 1c9c2e6ecd5..bdff075c7e7 100644
--- a/source/lib/md4.c
+++ b/source/lib/md4.c
@@ -1,171 +1,299 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- a implementation of MD4 designed for use in the SMB authentication protocol
- Copyright (C) Andrew Tridgell 1997
-
- 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.
+#ifdef SMB_PASSWD
+/*
+ This code is from rfc1186.
*/
+ /*
+ ** ********************************************************************
+ ** md4.c -- Implementation of MD4 Message Digest Algorithm **
+ ** Updated: 2/16/90 by Ronald L. Rivest **
+ ** (C) 1990 RSA Data Security, Inc. **
+ ** ********************************************************************
+ */
-/* NOTE: This code makes no attempt to be fast!
+ /*
+ ** To use MD4:
+ ** -- Include md4.h in your program
+ ** -- Declare an MDstruct MD to hold the state of the digest
+ ** computation.
+ ** -- Initialize MD using MDbegin(&MD)
+ ** -- For each full block (64 bytes) X you wish to process, call
+ ** MDupdate(&MD,X,512)
+ ** (512 is the number of bits in a full block.)
+ ** -- For the last block (less than 64 bytes) you wish to process,
+ ** MDupdate(&MD,X,n)
+ ** where n is the number of bits in the partial block. A partial
+ ** block terminates the computation, so every MD computation
+ ** should terminate by processing a partial block, even if it
+ ** has n = 0.
+ ** -- The message digest is available in MD.buffer[0] ...
+ ** MD.buffer[3]. (Least-significant byte of each word
+ ** should be output first.)
+ ** -- You can print out the digest using MDprint(&MD)
+ */
- It assumes that a int is at least 32 bits long
-*/
+ /* Implementation notes:
+ ** This implementation assumes that ints are 32-bit quantities.
+ ** If the machine stores the least-significant byte of an int in the
+ ** least-addressed byte (e.g., VAX and 8086), then LOWBYTEFIRST
+ ** should be set to TRUE. Otherwise (e.g., SUNS), LOWBYTEFIRST
+ ** should be set to FALSE. Note that on machines with LOWBYTEFIRST
+ ** FALSE the routine MDupdate modifies has a side-effect on its input
+ ** array (the order of bytes in each word are reversed). If this is
+ ** undesired a call to MDreverse(X) can reverse the bytes of X back
+ ** into order after each call to MDupdate.
+ */
-typedef unsigned int uint32;
-
-static uint32 A, B, C, D;
-
-static uint32 F(uint32 X, uint32 Y, uint32 Z)
-{
- return (X&Y) | ((~X)&Z);
-}
-
-static uint32 G(uint32 X, uint32 Y, uint32 Z)
-{
- return (X&Y) | (X&Z) | (Y&Z);
-}
-
-static uint32 H(uint32 X, uint32 Y, uint32 Z)
-{
- return X^Y^Z;
-}
-
-static uint32 lshift(uint32 x, int s)
-{
- x &= 0xFFFFFFFF;
- return ((x<<s)&0xFFFFFFFF) | (x>>(32-s));
-}
-
-#define ROUND1(a,b,c,d,k,s) a = lshift(a + F(b,c,d) + X[k], s)
-#define ROUND2(a,b,c,d,k,s) a = lshift(a + G(b,c,d) + X[k] + (uint32)0x5A827999,s)
-#define ROUND3(a,b,c,d,k,s) a = lshift(a + H(b,c,d) + X[k] + (uint32)0x6ED9EBA1,s)
-
-/* this applies md4 to 64 byte chunks */
-static void mdfour64(uint32 *M)
-{
- int j;
- uint32 AA, BB, CC, DD;
- uint32 X[16];
-
- for (j=0;j<16;j++)
- X[j] = M[j];
-
- AA = A; BB = B; CC = C; DD = D;
-
- ROUND1(A,B,C,D, 0, 3); ROUND1(D,A,B,C, 1, 7);
- ROUND1(C,D,A,B, 2, 11); ROUND1(B,C,D,A, 3, 19);
- ROUND1(A,B,C,D, 4, 3); ROUND1(D,A,B,C, 5, 7);
- ROUND1(C,D,A,B, 6, 11); ROUND1(B,C,D,A, 7, 19);
- ROUND1(A,B,C,D, 8, 3); ROUND1(D,A,B,C, 9, 7);
- ROUND1(C,D,A,B, 10, 11); ROUND1(B,C,D,A, 11, 19);
- ROUND1(A,B,C,D, 12, 3); ROUND1(D,A,B,C, 13, 7);
- ROUND1(C,D,A,B, 14, 11); ROUND1(B,C,D,A, 15, 19);
-
- ROUND2(A,B,C,D, 0, 3); ROUND2(D,A,B,C, 4, 5);
- ROUND2(C,D,A,B, 8, 9); ROUND2(B,C,D,A, 12, 13);
- ROUND2(A,B,C,D, 1, 3); ROUND2(D,A,B,C, 5, 5);
- ROUND2(C,D,A,B, 9, 9); ROUND2(B,C,D,A, 13, 13);
- ROUND2(A,B,C,D, 2, 3); ROUND2(D,A,B,C, 6, 5);
- ROUND2(C,D,A,B, 10, 9); ROUND2(B,C,D,A, 14, 13);
- ROUND2(A,B,C,D, 3, 3); ROUND2(D,A,B,C, 7, 5);
- ROUND2(C,D,A,B, 11, 9); ROUND2(B,C,D,A, 15, 13);
-
- ROUND3(A,B,C,D, 0, 3); ROUND3(D,A,B,C, 8, 9);
- ROUND3(C,D,A,B, 4, 11); ROUND3(B,C,D,A, 12, 15);
- ROUND3(A,B,C,D, 2, 3); ROUND3(D,A,B,C, 10, 9);
- ROUND3(C,D,A,B, 6, 11); ROUND3(B,C,D,A, 14, 15);
- ROUND3(A,B,C,D, 1, 3); ROUND3(D,A,B,C, 9, 9);
- ROUND3(C,D,A,B, 5, 11); ROUND3(B,C,D,A, 13, 15);
- ROUND3(A,B,C,D, 3, 3); ROUND3(D,A,B,C, 11, 9);
- ROUND3(C,D,A,B, 7, 11); ROUND3(B,C,D,A, 15, 15);
-
- A += AA; B += BB; C += CC; D += DD;
-
- A &= 0xFFFFFFFF; B &= 0xFFFFFFFF;
- C &= 0xFFFFFFFF; D &= 0xFFFFFFFF;
-
- for (j=0;j<16;j++)
- X[j] = 0;
-}
-
-static void copy64(uint32 *M, unsigned char *in)
-{
- int i;
-
- for (i=0;i<16;i++)
- M[i] = (in[i*4+3]<<24) | (in[i*4+2]<<16) |
- (in[i*4+1]<<8) | (in[i*4+0]<<0);
-}
-
-static void copy4(unsigned char *out,uint32 x)
-{
- out[0] = x&0xFF;
- out[1] = (x>>8)&0xFF;
- out[2] = (x>>16)&0xFF;
- out[3] = (x>>24)&0xFF;
-}
-
-/* produce a md4 message digest from data of length n bytes */
-void mdfour(unsigned char *out, unsigned char *in, int n)
-{
- unsigned char buf[128];
- uint32 M[16];
- uint32 b = n * 8;
- int i;
-
- A = 0x67452301;
- B = 0xefcdab89;
- C = 0x98badcfe;
- D = 0x10325476;
-
- while (n > 64) {
- copy64(M, in);
- mdfour64(M);
- in += 64;
- n -= 64;
- }
+#define TRUE 1
+#define FALSE 0
- for (i=0;i<128;i++)
- buf[i] = 0;
- memcpy(buf, in, n);
- buf[n] = 0x80;
-
- if (n <= 55) {
- copy4(buf+56, b);
- copy64(M, buf);
- mdfour64(M);
- } else {
- copy4(buf+120, b);
- copy64(M, buf);
- mdfour64(M);
- copy64(M, buf+64);
- mdfour64(M);
- }
+ /* Compile-time includes
+ */
+
+#include <stdio.h>
+#include "md4.h"
+
+#define uchar unsigned char
+#define int16 unsigned short
+#define uint32 unsigned int
+
+#include "byteorder.h"
+
+ /* Compile-time declarations of MD4 "magic constants".
+ */
+#define I0 0x67452301 /* Initial values for MD buffer */
+#define I1 0xefcdab89
+#define I2 0x98badcfe
+#define I3 0x10325476
+#define C2 013240474631 /* round 2 constant = sqrt(2) in octal */
+#define C3 015666365641 /* round 3 constant = sqrt(3) in octal */
+ /* C2 and C3 are from Knuth, The Art of Programming, Volume 2
+ ** (Seminumerical Algorithms), Second Edition (1981), Addison-Wesley.
+ ** Table 2, page 660.
+ */
- for (i=0;i<128;i++)
- buf[i] = 0;
- copy64(M, buf);
+#define fs1 3 /* round 1 shift amounts */
+#define fs2 7
+#define fs3 11
+#define fs4 19
+#define gs1 3 /* round 2 shift amounts */
+#define gs2 5
+#define gs3 9
+#define gs4 13
+#define hs1 3 /* round 3 shift amounts */
+#define hs2 9
+#define hs3 11
+#define hs4 15
- copy4(out, A);
- copy4(out+4, B);
- copy4(out+8, C);
- copy4(out+12, D);
+ /* Compile-time macro declarations for MD4.
+ ** Note: The "rot" operator uses the variable "tmp".
+ ** It assumes tmp is declared as unsigned int, so that the >>
+ ** operator will shift in zeros rather than extending the sign bit.
+ */
+#define f(X,Y,Z) ((X&Y) | ((~X)&Z))
+#define g(X,Y,Z) ((X&Y) | (X&Z) | (Y&Z))
+#define h(X,Y,Z) (X^Y^Z)
+#define rot(X,S) (tmp=X,(tmp<<S) | (tmp>>(32-S)))
+#define ff(A,B,C,D,i,s) A = rot((A + f(B,C,D) + X[i]),s)
+#define gg(A,B,C,D,i,s) A = rot((A + g(B,C,D) + X[i] + C2),s)
+#define hh(A,B,C,D,i,s) A = rot((A + h(B,C,D) + X[i] + C3),s)
+
+ /* MDprint(MDp)
+ ** Print message digest buffer MDp as 32 hexadecimal digits.
+ ** Order is from low-order byte of buffer[0] to high-order byte of
+ ** buffer[3].
+ ** Each byte is printed with high-order hexadecimal digit first.
+ ** This is a user-callable routine.
+ */
+ void
+ MDprint(MDp)
+ MDptr MDp;
+ { int i,j;
+ for (i=0;i<4;i++)
+ for (j=0;j<32;j=j+8)
+ printf("%02x",(MDp->buffer[i]>>j) & 0xFF);
+ }
+
+ /* MDbegin(MDp)
+ ** Initialize message digest buffer MDp.
+ ** This is a user-callable routine.
+ */
+ void
+ MDbegin(MDp)
+ MDptr MDp;
+ { int i;
+ MDp->buffer[0] = I0;
+ MDp->buffer[1] = I1;
+ MDp->buffer[2] = I2;
+ MDp->buffer[3] = I3;
+ for (i=0;i<8;i++) MDp->count[i] = 0;
+ MDp->done = 0;
+ }
+
+ /* MDreverse(X)
+ ** Reverse the byte-ordering of every int in X.
+ ** Assumes X is an array of 16 ints.
+ ** The macro revx reverses the byte-ordering of the next word of X.
+ */
+ void MDreverse(X)
+ unsigned int *X;
+ { register unsigned int t;
+ register unsigned int i;
+
+ for(i = 0; i < 16; i++) {
+ t = X[i];
+ SIVAL(X,i*4,t);
+ }
+ }
- A = B = C = D = 0;
-}
+ /* MDblock(MDp,X)
+ ** Update message digest buffer MDp->buffer using 16-word data block X.
+ ** Assumes all 16 words of X are full of data.
+ ** Does not update MDp->count.
+ ** This routine is not user-callable.
+ */
+ static void
+ MDblock(MDp,X)
+ MDptr MDp;
+ unsigned int *X;
+ {
+ register unsigned int tmp, A, B, C, D;
+ MDreverse(X);
+ A = MDp->buffer[0];
+ B = MDp->buffer[1];
+ C = MDp->buffer[2];
+ D = MDp->buffer[3];
+ /* Update the message digest buffer */
+ ff(A , B , C , D , 0 , fs1); /* Round 1 */
+ ff(D , A , B , C , 1 , fs2);
+ ff(C , D , A , B , 2 , fs3);
+ ff(B , C , D , A , 3 , fs4);
+ ff(A , B , C , D , 4 , fs1);
+ ff(D , A , B , C , 5 , fs2);
+ ff(C , D , A , B , 6 , fs3);
+ ff(B , C , D , A , 7 , fs4);
+ ff(A , B , C , D , 8 , fs1);
+ ff(D , A , B , C , 9 , fs2);
+ ff(C , D , A , B , 10 , fs3);
+ ff(B , C , D , A , 11 , fs4);
+ ff(A , B , C , D , 12 , fs1);
+ ff(D , A , B , C , 13 , fs2);
+ ff(C , D , A , B , 14 , fs3);
+ ff(B , C , D , A , 15 , fs4);
+ gg(A , B , C , D , 0 , gs1); /* Round 2 */
+ gg(D , A , B , C , 4 , gs2);
+ gg(C , D , A , B , 8 , gs3);
+ gg(B , C , D , A , 12 , gs4);
+ gg(A , B , C , D , 1 , gs1);
+ gg(D , A , B , C , 5 , gs2);
+ gg(C , D , A , B , 9 , gs3);
+ gg(B , C , D , A , 13 , gs4);
+ gg(A , B , C , D , 2 , gs1);
+ gg(D , A , B , C , 6 , gs2);
+ gg(C , D , A , B , 10 , gs3);
+ gg(B , C , D , A , 14 , gs4);
+ gg(A , B , C , D , 3 , gs1);
+ gg(D , A , B , C , 7 , gs2);
+ gg(C , D , A , B , 11 , gs3);
+ gg(B , C , D , A , 15 , gs4);
+ hh(A , B , C , D , 0 , hs1); /* Round 3 */
+ hh(D , A , B , C , 8 , hs2);
+ hh(C , D , A , B , 4 , hs3);
+ hh(B , C , D , A , 12 , hs4);
+ hh(A , B , C , D , 2 , hs1);
+ hh(D , A , B , C , 10 , hs2);
+ hh(C , D , A , B , 6 , hs3);
+ hh(B , C , D , A , 14 , hs4);
+ hh(A , B , C , D , 1 , hs1);
+ hh(D , A , B , C , 9 , hs2);
+ hh(C , D , A , B , 5 , hs3);
+ hh(B , C , D , A , 13 , hs4);
+ hh(A , B , C , D , 3 , hs1);
+ hh(D , A , B , C , 11 , hs2);
+ hh(C , D , A , B , 7 , hs3);
+ hh(B , C , D , A , 15 , hs4);
+ MDp->buffer[0] += A;
+ MDp->buffer[1] += B;
+ MDp->buffer[2] += C;
+ MDp->buffer[3] += D;
+ }
+ /* MDupdate(MDp,X,count)
+ ** Input: MDp -- an MDptr
+ ** X -- a pointer to an array of unsigned characters.
+ ** count -- the number of bits of X to use.
+ ** (if not a multiple of 8, uses high bits of last byte.)
+ ** Update MDp using the number of bits of X given by count.
+ ** This is the basic input routine for an MD4 user.
+ ** The routine completes the MD computation when count < 512, so
+ ** every MD computation should end with one call to MDupdate with a
+ ** count less than 512. A call with count 0 will be ignored if the
+ ** MD has already been terminated (done != 0), so an extra call with
+ ** count 0 can be given as a "courtesy close" to force termination
+ ** if desired.
+ */
+ void
+ MDupdate(MDp,X,count)
+ MDptr MDp;
+ unsigned char *X;
+ unsigned int count;
+ { unsigned int i, tmp, bit, byte, mask;
+ unsigned char XX[64];
+ unsigned char *p;
+ /* return with no error if this is a courtesy close with count
+ ** zero and MDp->done is true.
+ */
+ if (count == 0 && MDp->done) return;
+ /* check to see if MD is already done and report error */
+ if (MDp->done)
+ { printf("\nError: MDupdate MD already done."); return; }
+ /* Add count to MDp->count */
+ tmp = count;
+ p = MDp->count;
+ while (tmp)
+ { tmp += *p;
+ *p++ = tmp;
+ tmp = tmp >> 8;
+ }
+ /* Process data */
+ if (count == 512)
+ { /* Full block of data to handle */
+ MDblock(MDp,(unsigned int *)X);
+ }
+ else if (count > 512) /* Check for count too large */
+ { printf("\nError: MDupdate called with illegal count value %d."
+ ,count);
+ return;
+ }
+ else /* partial block -- must be last block so finish up */
+ { /* Find out how many bytes and residual bits there are */
+ byte = count >> 3;
+ bit = count & 7;
+ /* Copy X into XX since we need to modify it */
+ for (i=0;i<=byte;i++) XX[i] = X[i];
+ for (i=byte+1;i<64;i++) XX[i] = 0;
+ /* Add padding '1' bit and low-order zeros in last byte */
+ mask = 1 << (7 - bit);
+ XX[byte] = (XX[byte] | mask) & ~( mask - 1);
+ /* If room for bit count, finish up with this block */
+ if (byte <= 55)
+ { for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
+ MDblock(MDp,(unsigned int *)XX);
+ }
+ else /* need to do two blocks to finish up */
+ { MDblock(MDp,(unsigned int *)XX);
+ for (i=0;i<56;i++) XX[i] = 0;
+ for (i=0;i<8;i++) XX[56+i] = MDp->count[i];
+ MDblock(MDp,(unsigned int *)XX);
+ }
+ /* Set flag saying we're done with MD computation */
+ MDp->done = 1;
+ }
+ }
+ /*
+ ** End of md4.c
+ */
+#else
+ void md4_dummy() {;}
+#endif
diff --git a/source/lib/replace.c b/source/lib/replace.c
index b27909db034..67c18a15237 100644
--- a/source/lib/replace.c
+++ b/source/lib/replace.c
@@ -238,6 +238,73 @@ long nap(long milliseconds) {
#endif
+
+#if WRAP_MALLOC
+
+/* undo the wrapping temporarily */
+#undef malloc
+#undef realloc
+#undef free
+
+/****************************************************************************
+wrapper for malloc() to catch memory errors
+****************************************************************************/
+void *malloc_wrapped(int size,char *file,int line)
+{
+#ifdef xx_old_malloc
+ void *res = xx_old_malloc(size);
+#else
+ void *res = malloc(size);
+#endif
+ DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
+ file,line,
+ size,(unsigned int)res));
+ return(res);
+}
+
+/****************************************************************************
+wrapper for realloc() to catch memory errors
+****************************************************************************/
+void *realloc_wrapped(void *ptr,int size,char *file,int line)
+{
+#ifdef xx_old_realloc
+ void *res = xx_old_realloc(ptr,size);
+#else
+ void *res = realloc(ptr,size);
+#endif
+ DEBUG(3,("Realloc\n"));
+ DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
+ file,line,
+ (unsigned int)ptr));
+ DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
+ file,line,
+ size,(unsigned int)res));
+ return(res);
+}
+
+/****************************************************************************
+wrapper for free() to catch memory errors
+****************************************************************************/
+void free_wrapped(void *ptr,char *file,int line)
+{
+#ifdef xx_old_free
+ xx_old_free(ptr);
+#else
+ free(ptr);
+#endif
+ DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
+ file,line,(unsigned int)ptr));
+ return;
+}
+
+/* and re-do the define for spots lower in this file */
+#define malloc(size) malloc_wrapped(size,__FILE__,__LINE__)
+#define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__)
+#define free(ptr) free_wrapped(ptr,__FILE__,__LINE__)
+
+#endif
+
+
#if WRAP_MEMCPY
#undef memcpy
/*******************************************************************
diff --git a/source/lib/system.c b/source/lib/system.c
index 1486600339a..b149ccb4b98 100644
--- a/source/lib/system.c
+++ b/source/lib/system.c
@@ -194,24 +194,25 @@ now for utime()
********************************************************************/
int sys_utime(char *fname,struct utimbuf *times)
{
- /* if the modtime is 0 or -1 then ignore the call and
- return success */
- if (times->modtime == (time_t)0 || times->modtime == (time_t)-1)
- return 0;
-
- /* if the access time is 0 or -1 then set it to the modtime */
- if (times->actime == (time_t)0 || times->actime == (time_t)-1)
- times->actime = times->modtime;
-
- return(utime(dos_to_unix(fname,False),times));
+ /* if the modtime is 0 or -1 then ignore the call and
+ return success */
+ if (times->modtime == (time_t)0 || times->modtime == (time_t)-1)
+ return 0;
+
+ /* if the access time is 0 or -1 then set it to the modtime */
+ if (times->actime == (time_t)0 || times->actime == (time_t)-1)
+ times->actime = times->modtime;
+
+ return(utime(dos_to_unix(fname,False),times));
}
+
/*********************************************************
for rename across filesystems Patch from Warren Birnbaum
<warrenb@hpcvscdp.cv.hp.com>
**********************************************************/
-
-static int copy_reg(char *source, const char *dest)
+static int
+copy_reg (const char *source, const char *dest)
{
struct stat source_stats;
int ifd;
diff --git a/source/lib/time.c b/source/lib/time.c
index 5fc6595b6f1..ad6b04484c5 100644
--- a/source/lib/time.c
+++ b/source/lib/time.c
@@ -74,7 +74,6 @@ static int tm_diff(struct tm *a, struct tm *b)
int hours = 24*days + (a->tm_hour - b->tm_hour);
int minutes = 60*hours + (a->tm_min - b->tm_min);
int seconds = 60*minutes + (a->tm_sec - b->tm_sec);
-
return seconds;
}
@@ -94,11 +93,6 @@ init the time differences
void TimeInit(void)
{
serverzone = TimeZone(time(NULL));
-
- if ((serverzone % 60) != 0) {
- DEBUG(1,("WARNING: Your timezone is not a multiple of 1 minute.\n"));
- }
-
DEBUG(4,("Serverzone is %d\n",serverzone));
}
@@ -285,7 +279,7 @@ void put_long_date(char *p,time_t t)
}
/* this converts GMT to kludge-GMT */
- t -= LocTimeDiff(t) - serverzone;
+ t -= TimeDiff(t) - serverzone;
d = (double) (t);
@@ -463,19 +457,19 @@ char *timestring(void )
#ifdef NO_STRFTIME
fstrcpy(TimeBuf, asctime(tm));
#elif defined(CLIX) || defined(CONVEX)
- strftime(TimeBuf,100,"%m/%d/%Y %I:%M:%S %p",tm);
+ strftime(TimeBuf,100,"%m/%d/%y %I:%M:%S %p",tm);
#elif defined(AMPM)
- strftime(TimeBuf,100,"%m/%d/%Y %r",tm);
+ strftime(TimeBuf,100,"%D %r",tm);
#elif defined(TZ_TIME)
{
int zone = TimeDiff(t);
int absZoneMinutes = (zone<0 ? -zone : zone) / 60;
- size_t len = strftime(TimeBuf,sizeof(TimeBuf)-6,"%m/%d/%Y %T",tm);
+ size_t len = strftime(TimeBuf,sizeof(TimeBuf)-6,"%D %T",tm);
sprintf(TimeBuf+len," %c%02d%02d",
zone<0?'+':'-',absZoneMinutes/60,absZoneMinutes%60);
}
#else
- strftime(TimeBuf,100,"%m/%d/%Y %T",tm);
+ strftime(TimeBuf,100,"%D %T",tm);
#endif
return(TimeBuf);
}
diff --git a/source/lib/ufc.c b/source/lib/ufc.c
index 3330111c2f5..0fa5cfd3a0f 100644
--- a/source/lib/ufc.c
+++ b/source/lib/ufc.c
@@ -660,7 +660,7 @@ static char *output_conversion(v1, v2, salt)
* UNIX crypt function
*/
-static ufc_long *_ufc_doit(ufc_long , ufc_long, ufc_long, ufc_long, ufc_long);
+ufc_long *_ufc_doit(ufc_long , ufc_long, ufc_long, ufc_long, ufc_long);
char *ufc_crypt(char *key,char *salt)
{ ufc_long *s;
diff --git a/source/lib/username.c b/source/lib/username.c
index a7241d309f4..46b8f4cb332 100644
--- a/source/lib/username.c
+++ b/source/lib/username.c
@@ -22,9 +22,6 @@
#include "includes.h"
extern int DEBUGLEVEL;
-/* internal functions - modified versions of the ones in password.c */
-static struct passwd *uname_string_combinations(char *s, struct passwd * (*fn) (), int N);
-static struct passwd *uname_string_combinations2(char *s, int offset, struct passwd * (*fn) (), int N);
/****************************************************************************
get a users home directory. tries as-is then lower case
@@ -82,19 +79,11 @@ void map_username(char *user)
for (; (s=fgets_slash(NULL,80,f)); free(s)) {
char *unixname = s;
char *dosname = strchr(unixname,'=');
- BOOL break_if_mapped = False;
if (!dosname) continue;
*dosname++ = 0;
while (isspace(*unixname)) unixname++;
- if ('!' == *unixname)
- {
- break_if_mapped = True;
- unixname++;
- while (*unixname && isspace(*unixname)) unixname++;
- }
-
if (!*unixname || strchr("#;",*unixname)) continue;
{
@@ -110,10 +99,6 @@ void map_username(char *user)
StrnCpy(last_from,user,sizeof(last_from)-1);
sscanf(unixname,"%s",user);
StrnCpy(last_to,user,sizeof(last_to)-1);
- if(break_if_mapped) {
- free(s);
- break;
- }
}
}
@@ -156,8 +141,6 @@ Note that this changes user!
struct passwd *Get_Pwnam(char *user,BOOL allow_change)
{
fstring user2;
- int last_char;
- int usernamelevel = lp_usernamelevel();
struct passwd *ret;
@@ -189,19 +172,6 @@ struct passwd *Get_Pwnam(char *user,BOOL allow_change)
ret = _Get_Pwnam(user);
if (ret) return(ret);
- /* try with last letter capitalised */
- strlower(user);
- last_char = strlen(user)-1;
- user[last_char] = toupper(user[last_char]);
- DEBUG(3, ("Trying username %s\n", user));
- ret = _Get_Pwnam(user);
- if (ret) return(ret);
-
- /* try all combinations up to usernamelevel */
- strlower(user);
- ret = uname_string_combinations(user, _Get_Pwnam, usernamelevel);
- if (ret) return(ret);
-
if (allow_change)
fstrcpy(user,user2);
@@ -280,57 +250,4 @@ BOOL user_in_list(char *user,char *list)
return(False);
}
-/* The functions below have been taken from password.c and slightly modified */
-/****************************************************************************
-apply a function to upper/lower case combinations
-of a string and return true if one of them returns true.
-try all combinations with N uppercase letters.
-offset is the first char to try and change (start with 0)
-it assumes the string starts lowercased
-****************************************************************************/
-static struct passwd *uname_string_combinations2(char *s,int offset,struct passwd *(*fn)(),int N)
-{
- int len = strlen(s);
- int i;
- struct passwd *ret;
-
-#ifdef PASSWORD_LENGTH
- len = MIN(len,PASSWORD_LENGTH);
-#endif
-
- if (N <= 0 || offset >= len)
- return(fn(s));
-
-
- for (i=offset;i<(len-(N-1));i++)
-
- {
- char c = s[i];
- if (!islower(c)) continue;
- s[i] = toupper(c);
- ret = uname_string_combinations2(s,i+1,fn,N-1);
- if(ret) return(ret);
- s[i] = c;
- }
- return(NULL);
-}
-
-/****************************************************************************
-apply a function to upper/lower case combinations
-of a string and return true if one of them returns true.
-try all combinations with up to N uppercase letters.
-offset is the first char to try and change (start with 0)
-it assumes the string starts lowercased
-****************************************************************************/
-static struct passwd * uname_string_combinations(char *s,struct passwd * (*fn)(),int N)
-{
- int n;
- struct passwd *ret;
- for (n=1;n<=N;n++)
- {
- ret = uname_string_combinations2(s,0,fn,n);
- if(ret) return(ret);
- }
- return(NULL);
-}
diff --git a/source/lib/util.c b/source/lib/util.c
index 18f1240bbdd..54b2dc08ac8 100644
--- a/source/lib/util.c
+++ b/source/lib/util.c
@@ -21,10 +21,6 @@
#include "includes.h"
-#if (defined(NETGROUP) && defined (AUTOMOUNT))
-#include "rpcsvc/ypclnt.h"
-#endif
-
pstring scope = "";
int DEBUGLEVEL = 1;
@@ -76,12 +72,7 @@ static enum remote_arch_types ra_type = RA_UNKNOWN;
fstring remote_proto="UNKNOWN";
pstring myhostname="";
pstring user_socket_options="";
-
pstring sesssetup_user="";
-pstring samlogon_user="";
-
-BOOL sam_logon_in_ssb = False;
-
pstring myname = "";
fstring myworkgroup = "";
char **my_netbios_names;
@@ -102,10 +93,10 @@ void setup_logging(char *pname,BOOL interactive)
char *p = strrchr(pname,'/');
if (p) pname = p+1;
#ifdef LOG_DAEMON
- openlog(pname, LOG_PID, SYSLOG_FACILITY);
-#else /* for old systems that have no facility codes. */
+ openlog(pname, LOG_PID, LOG_DAEMON);
+#else /* LOG_DAEMON - for old systems that have no facility codes. */
openlog(pname, LOG_PID);
-#endif
+#endif /* LOG_DAEMON */
}
#endif
if (interactive) {
@@ -184,7 +175,6 @@ static void check_log_size(void)
debug_count=0;
}
-
/*******************************************************************
write an debug message on the debugfile. This is called by the DEBUG
macro
@@ -698,61 +688,48 @@ static int name_interpret(char *in,char *out)
/****************************************************************************
mangle a name into netbios format
-
- Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
****************************************************************************/
-int name_mangle( char *In, char *Out, char name_type )
- {
- int i;
- int c;
- int len;
- char buf[20];
- char *p = Out;
-
- /* Safely copy the input string, In, into buf[]. */
- (void)memset( buf, 0, 20 );
- if( '*' == In[0] )
- buf[0] = '*';
- else
- (void)sprintf( buf, "%-15.15s%c", In, name_type );
-
- /* Place the length of the first field into the output buffer. */
- p[0] = 32;
- p++;
+int name_mangle(char *In,char *Out,char name_type)
+{
+ fstring name;
+ char buf[20];
+ char *in = (char *)&buf[0];
+ char *out = (char *)Out;
+ char *p, *label;
+ int i;
- /* Now convert the name to the rfc1001/1002 format. */
- for( i = 0; i < 16; i++ )
- {
- c = toupper( buf[i] );
- p[i*2] = ( (c >> 4) & 0x000F ) + 'A';
- p[(i*2)+1] = (c & 0x000F) + 'A';
- }
- p += 32;
- p[0] = '\0';
+ if (In[0] != '*') {
+ StrnCpy(name,In,sizeof(name)-1);
+ sprintf(buf,"%-15.15s%c",name,name_type);
+ } else {
+ buf[0]='*';
+ memset(&buf[1],0,16);
+ }
- /* Add the scope string. */
- for( i = 0, len = 0; NULL != scope; i++, len++ )
+ *out++ = 32;
+ for (i=0;i<16;i++) {
+ char c = toupper(in[i]);
+ out[i*2] = (c>>4) + 'A';
+ out[i*2+1] = (c & 0xF) + 'A';
+ }
+ out[32]=0;
+ out += 32;
+
+ label = scope;
+ while (*label)
{
- switch( scope[i] )
- {
- case '\0':
- p[0] = len;
- if( len > 0 )
- p[len+1] = 0;
- return( name_len(Out) );
- case '.':
- p[0] = len;
- p += (len + 1);
- len = 0;
- break;
- default:
- p[len+1] = scope[i];
- break;
- }
+ p = strchr(label, '.');
+ if (p == 0)
+ p = label + strlen(label);
+ *out++ = p - label;
+ memcpy(out, label, p - label);
+ out += p - label;
+ label += p - label + (*p == '.');
}
+ *out = 0;
+ return(name_len(Out));
+}
- return( name_len(Out) );
- } /* name_mangle */
/*******************************************************************
check if a file exists
@@ -834,145 +811,131 @@ char *attrib_string(int mode)
/*******************************************************************
case insensitive string compararison
********************************************************************/
-int StrCaseCmp(char *s, char *t)
+int StrCaseCmp(const char *s, const char *t)
{
/* compare until we run out of string, either t or s, or find a difference */
/* We *must* use toupper rather than tolower here due to the
asynchronous upper to lower mapping.
*/
-#if !defined(KANJI_WIN95_COMPATIBILITY)
- if(lp_client_code_page() == KANJI_CODEPAGE)
+#if defined(KANJI) && !defined(KANJI_WIN95_COMPATIBILITY)
+ /* Win95 treats full width ascii characters as case sensitive. */
+ int diff;
+ for (;;)
{
- /* Win95 treats full width ascii characters as case sensitive. */
- int diff;
- for (;;)
- {
- if (!*s || !*t)
- return toupper (*s) - toupper (*t);
- else if (is_sj_alph (*s) && is_sj_alph (*t))
- {
- diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1));
- if (diff)
- return diff;
- s += 2;
- t += 2;
- }
- else if (is_shift_jis (*s) && is_shift_jis (*t))
- {
- diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
- if (diff)
- return diff;
- diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1));
- if (diff)
- return diff;
- s += 2;
- t += 2;
- }
- else if (is_shift_jis (*s))
- return 1;
- else if (is_shift_jis (*t))
- return -1;
- else
- {
- diff = toupper (*s) - toupper (*t);
- if (diff)
- return diff;
- s++;
- t++;
- }
- }
+ if (!*s || !*t)
+ return toupper (*s) - toupper (*t);
+ else if (is_sj_alph (*s) && is_sj_alph (*t))
+ {
+ diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1));
+ if (diff)
+ return diff;
+ s += 2;
+ t += 2;
+ }
+ else if (is_shift_jis (*s) && is_shift_jis (*t))
+ {
+ diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
+ if (diff)
+ return diff;
+ diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1));
+ if (diff)
+ return diff;
+ s += 2;
+ t += 2;
+ }
+ else if (is_shift_jis (*s))
+ return 1;
+ else if (is_shift_jis (*t))
+ return -1;
+ else
+ {
+ diff = toupper (*s) - toupper (*t);
+ if (diff)
+ return diff;
+ s++;
+ t++;
+ }
}
- else
-#endif /* KANJI_WIN95_COMPATIBILITY */
+#else /* KANJI */
+ while (*s && *t && toupper(*s) == toupper(*t))
{
- while (*s && *t && toupper(*s) == toupper(*t))
- {
- s++;
- t++;
- }
-
- return(toupper(*s) - toupper(*t));
+ s++; t++;
}
+
+ return(toupper(*s) - toupper(*t));
+#endif /* KANJI */
}
/*******************************************************************
case insensitive string compararison, length limited
********************************************************************/
-int StrnCaseCmp(char *s, char *t, int n)
+int StrnCaseCmp(const char *s, const char *t, int n)
{
/* compare until we run out of string, either t or s, or chars */
/* We *must* use toupper rather than tolower here due to the
asynchronous upper to lower mapping.
*/
-#if !defined(KANJI_WIN95_COMPATIBILITY)
- if(lp_client_code_page() == KANJI_CODEPAGE)
+#if defined(KANJI) && !defined(KANJI_WIN95_COMPATIBILITY)
+ /* Win95 treats full width ascii characters as case sensitive. */
+ int diff;
+ for (;n > 0;)
{
- /* Win95 treats full width ascii characters as case sensitive. */
- int diff;
- for (;n > 0;)
- {
- if (!*s || !*t)
- return toupper (*s) - toupper (*t);
- else if (is_sj_alph (*s) && is_sj_alph (*t))
- {
- diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1));
- if (diff)
- return diff;
- s += 2;
- t += 2;
- n -= 2;
- }
- else if (is_shift_jis (*s) && is_shift_jis (*t))
- {
- diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
- if (diff)
- return diff;
- diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1));
- if (diff)
- return diff;
- s += 2;
- t += 2;
- n -= 2;
- }
- else if (is_shift_jis (*s))
- return 1;
- else if (is_shift_jis (*t))
- return -1;
- else
- {
- diff = toupper (*s) - toupper (*t);
- if (diff)
- return diff;
- s++;
- t++;
- n--;
- }
- }
- return 0;
+ if (!*s || !*t)
+ return toupper (*s) - toupper (*t);
+ else if (is_sj_alph (*s) && is_sj_alph (*t))
+ {
+ diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1));
+ if (diff)
+ return diff;
+ s += 2;
+ t += 2;
+ n -= 2;
+ }
+ else if (is_shift_jis (*s) && is_shift_jis (*t))
+ {
+ diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
+ if (diff)
+ return diff;
+ diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1));
+ if (diff)
+ return diff;
+ s += 2;
+ t += 2;
+ n -= 2;
+ }
+ else if (is_shift_jis (*s))
+ return 1;
+ else if (is_shift_jis (*t))
+ return -1;
+ else
+ {
+ diff = toupper (*s) - toupper (*t);
+ if (diff)
+ return diff;
+ s++;
+ t++;
+ n--;
+ }
}
- else
-#endif /* KANJI_WIN95_COMPATIBILITY */
+ return 0;
+#else /* KANJI */
+ while (n-- && *s && *t && toupper(*s) == toupper(*t))
{
- while (n-- && *s && *t && toupper(*s) == toupper(*t))
- {
- s++;
- t++;
- }
+ s++; t++;
+ }
- /* not run out of chars - strings are different lengths */
- if (n)
- return(toupper(*s) - toupper(*t));
+ /* not run out of chars - strings are different lengths */
+ if (n) return(toupper(*s) - toupper(*t));
- /* identical up to where we run out of chars,
- and strings are same length */
- return(0);
- }
+ /* identical up to where we run out of chars, and strings are same length */
+ return(0);
+#endif /* KANJI */
}
/*******************************************************************
compare 2 strings
********************************************************************/
-BOOL strequal(char *s1, char *s2)
+BOOL strequal(const char *s1, const char *s2)
{
if (s1 == s2) return(True);
if (!s1 || !s2) return(False);
@@ -983,7 +946,7 @@ BOOL strequal(char *s1, char *s2)
/*******************************************************************
compare 2 strings up to and including the nth char.
******************************************************************/
-BOOL strnequal(char *s1,char *s2,int n)
+BOOL strnequal(const char *s1,const char *s2,int n)
{
if (s1 == s2) return(True);
if (!s1 || !s2 || !n) return(False);
@@ -1009,36 +972,27 @@ BOOL strcsequal(char *s1,char *s2)
void strlower(char *s)
{
while (*s)
- {
-#if !defined(KANJI_WIN95_COMPATIBILITY)
- if(lp_client_code_page() == KANJI_CODEPAGE)
- {
- /* Win95 treats full width ascii characters as case sensitive. */
- if (is_shift_jis (*s))
- {
- if (is_sj_upper (s[0], s[1]))
- s[1] = sj_tolower2 (s[1]);
- s += 2;
- }
- else if (is_kana (*s))
- {
- s++;
- }
- else
- {
- if (isupper(*s))
- *s = tolower(*s);
- s++;
- }
- }
- else
-#endif /* KANJI_WIN95_COMPATIBILITY */
{
+#if defined(KANJI) && !defined(KANJI_WIN95_COMPATIBILITY)
+ /* Win95 treats full width ascii characters as case sensitive. */
+ if (is_shift_jis (*s)) {
+ if (is_sj_upper (s[0], s[1])) {
+ s[1] = sj_tolower2 (s[1]);
+ }
+ s += 2;
+ } else if (is_kana (*s)) {
+ s++;
+ } else {
+ if (isupper(*s))
+ *s = tolower(*s);
+ s++;
+ }
+#else /* KANJI */
if (isupper(*s))
- *s = tolower(*s);
+ *s = tolower(*s);
s++;
+#endif /* KANJI */
}
- }
}
/*******************************************************************
@@ -1047,36 +1001,27 @@ void strlower(char *s)
void strupper(char *s)
{
while (*s)
- {
-#if !defined(KANJI_WIN95_COMPATIBILITY)
- if(lp_client_code_page() == KANJI_CODEPAGE)
- {
- /* Win95 treats full width ascii characters as case sensitive. */
- if (is_shift_jis (*s))
- {
- if (is_sj_lower (s[0], s[1]))
- s[1] = sj_toupper2 (s[1]);
- s += 2;
- }
- else if (is_kana (*s))
- {
- s++;
- }
- else
- {
- if (islower(*s))
- *s = toupper(*s);
- s++;
- }
- }
- else
-#endif /* KANJI_WIN95_COMPATIBILITY */
{
+#if defined(KANJI) && !defined(KANJI_WIN95_COMPATIBILITY)
+ /* Win95 treats full width ascii characters as case sensitive. */
+ if (is_shift_jis (*s)) {
+ if (is_sj_lower (s[0], s[1])) {
+ s[1] = sj_toupper2 (s[1]);
+ }
+ s += 2;
+ } else if (is_kana (*s)) {
+ s++;
+ } else {
+ if (islower(*s))
+ *s = toupper(*s);
+ s++;
+ }
+#else /* KANJI */
if (islower(*s))
- *s = toupper(*s);
+ *s = toupper(*s);
s++;
+#endif /* KANJI */
}
- }
}
/*******************************************************************
@@ -1108,30 +1053,24 @@ BOOL strisnormal(char *s)
void string_replace(char *s,char oldc,char newc)
{
while (*s)
- {
-#if !defined(KANJI_WIN95_COMPATIBILITY)
- if(lp_client_code_page() == KANJI_CODEPAGE)
- {
- /* Win95 treats full width ascii characters as case sensitive. */
- if (is_shift_jis (*s))
- s += 2;
- else if (is_kana (*s))
- s++;
- else
- {
- if (oldc == *s)
- *s = newc;
- s++;
- }
- }
- else
-#endif /* KANJI_WIN95_COMPATIBILITY */
{
+#if defined(KANJI) && !defined(KANJI_WIN95_COMPATIBILITY)
+ /* Win95 treats full width ascii characters as case sensitive. */
+ if (is_shift_jis (*s)) {
+ s += 2;
+ } else if (is_kana (*s)) {
+ s++;
+ } else {
+ if (oldc == *s)
+ *s = newc;
+ s++;
+ }
+#else /* KANJI */
if (oldc == *s)
- *s = newc;
+ *s = newc;
s++;
+#endif /* KANJI */
}
- }
}
/****************************************************************************
@@ -1165,9 +1104,10 @@ void dos_format(char *fname)
void show_msg(char *buf)
{
int i;
+ int j;
int bcc=0;
-
- if (DEBUGLEVEL < 5) return;
+ if (DEBUGLEVEL < 5)
+ return;
DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
smb_len(buf),
@@ -1183,17 +1123,35 @@ void show_msg(char *buf)
(int)SVAL(buf,smb_uid),
(int)SVAL(buf,smb_mid),
(int)CVAL(buf,smb_wct)));
-
for (i=0;i<(int)CVAL(buf,smb_wct);i++)
DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
-
bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
DEBUG(5,("smb_bcc=%d\n",bcc));
+ if (DEBUGLEVEL < 10)
+ return;
+ for (i = 0; i < MIN(bcc, 256); i += 16)
+ {
+ for (j = 0; j < 16 && i+j < MIN(bcc,256); j++)
+ {
+
+ DEBUG(10,("%2X ",CVAL(smb_buf(buf),i+j)));
+ if (j == 7) DEBUG(10, (" "));
+
+ }
+ DEBUG(10,(" "));
+
+ for (j = 0; j < 16 && i+j < MIN(bcc,256); j++)
+ {
+ unsigned char c = CVAL(smb_buf(buf),i+j);
+ if (c < 32 || c > 128) c = '.';
+ DEBUG(10,("%c",c));
- if (DEBUGLEVEL < 10) return;
+ if (j == 7) DEBUG(10, (" "));
+ }
- dump_data(10, smb_buf(buf), MIN(bcc, 512));
+ DEBUG(10,("\n"));
+}
}
/*******************************************************************
@@ -1496,7 +1454,7 @@ char *GetWd(char *str)
if (!sys_getwd(s))
{
- DEBUG(0,("Getwd failed, errno %s\n",strerror(errno)));
+ DEBUG(0,("Getwd failed, errno %d\n",errno));
return (NULL);
}
@@ -1734,30 +1692,22 @@ does a string have any uppercase chars in it?
BOOL strhasupper(char *s)
{
while (*s)
- {
-#if !defined(KANJI_WIN95_COMPATIBILITY)
- if(lp_client_code_page() == KANJI_CODEPAGE)
{
- /* Win95 treats full width ascii characters as case sensitive. */
- if (is_shift_jis (*s))
- s += 2;
- else if (is_kana (*s))
- s++;
- else
- {
- if (isupper(*s))
- return(True);
- s++;
- }
- }
- else
-#endif /* KANJI_WIN95_COMPATIBILITY */
- {
- if (isupper(*s))
- return(True);
+#if defined(KANJI) && !defined(KANJI_WIN95_COMPATIBILITY)
+ /* Win95 treats full width ascii characters as case sensitive. */
+ if (is_shift_jis (*s)) {
+ s += 2;
+ } else if (is_kana (*s)) {
+ s++;
+ } else {
+ if (isupper(*s)) return(True);
+ s++;
+ }
+#else /* KANJI */
+ if (isupper(*s)) return(True);
s++;
+#endif /* KANJI */
}
- }
return(False);
}
@@ -1767,38 +1717,24 @@ does a string have any lowercase chars in it?
BOOL strhaslower(char *s)
{
while (*s)
- {
-#if !defined(KANJI_WIN95_COMPATIBILITY)
- if(lp_client_code_page() == KANJI_CODEPAGE)
{
- /* Win95 treats full width ascii characters as case sensitive. */
- if (is_shift_jis (*s))
- {
- if (is_sj_upper (s[0], s[1]))
- return(True);
- if (is_sj_lower (s[0], s[1]))
- return (True);
- s += 2;
- }
- else if (is_kana (*s))
- {
- s++;
- }
- else
- {
- if (islower(*s))
- return(True);
- s++;
- }
- }
- else
-#endif /* KANJI_WIN95_COMPATIBILITY */
- {
- if (islower(*s))
- return(True);
+#if defined(KANJI) && !defined(KANJI_WIN95_COMPATIBILITY)
+ /* Win95 treats full width ascii characters as case sensitive. */
+ if (is_shift_jis (*s)) {
+ if (is_sj_upper (s[0], s[1])) return(True);
+ if (is_sj_lower (s[0], s[1])) return (True);
+ s += 2;
+ } else if (is_kana (*s)) {
+ s++;
+ } else {
+ if (islower(*s)) return(True);
+ s++;
+ }
+#else /* KANJI */
+ if (islower(*s)) return(True);
s++;
+#endif /* KANJI */
}
- }
return(False);
}
@@ -1808,33 +1744,27 @@ find the number of chars in a string
int count_chars(char *s,char c)
{
int count=0;
-
-#if !defined(KANJI_WIN95_COMPATIBILITY)
- if(lp_client_code_page() == KANJI_CODEPAGE)
- {
- /* Win95 treats full width ascii characters as case sensitive. */
- while (*s)
+#if defined(KANJI) && !defined(KANJI_WIN95_COMPATIBILITY)
+ /* Win95 treats full width ascii characters as case sensitive. */
+ while (*s)
{
- if (is_shift_jis (*s))
- s += 2;
- else
- {
- if (*s == c)
- count++;
- s++;
- }
+ if (is_shift_jis (*s))
+ s += 2;
+ else
+ {
+ if (*s == c)
+ count++;
+ s++;
}
}
- else
-#endif /* KANJI_WIN95_COMPATIBILITY */
- {
- while (*s)
+#else /* KANJI */
+ while (*s)
{
if (*s == c)
- count++;
+ count++;
s++;
}
- }
+#endif /* KANJI */
return(count);
}
@@ -1959,16 +1889,13 @@ int read_udp_socket(int fd,char *buf,int len)
bzero((char *)&lastip,sizeof(lastip));
ret = recvfrom(fd,buf,len,0,&sock,&socklen);
if (ret <= 0) {
- DEBUG(2,("read socket failed. ERRNO=%s\n",strerror(errno)));
+ DEBUG(2,("read socket failed. ERRNO=%d\n",errno));
return(0);
}
lastip = *(struct in_addr *) &sock.sa_data[2];
lastport = ntohs(((struct sockaddr_in *)&sock)->sin_port);
- DEBUG(10,("read_udp_socket: lastip %s lastport %d read: %d\n",
- inet_ntoa(lastip), lastport, ret));
-
return(ret);
}
@@ -2281,11 +2208,10 @@ int read_smb_length(int fd,char *inbuf,int timeout)
/****************************************************************************
- read an smb from a fd. Note that the buffer *MUST* be of size
- BUFFER_SIZE+SAFETY_MARGIN.
+ read an smb from a fd and return it's length
The timeout is in milli seconds
****************************************************************************/
-BOOL receive_smb(int fd,char *buffer, int timeout)
+BOOL receive_smb(int fd,char *buffer,int timeout)
{
int len,ret;
@@ -2312,202 +2238,6 @@ BOOL receive_smb(int fd,char *buffer, int timeout)
return(True);
}
-/****************************************************************************
- read a message from a udp fd.
-The timeout is in milli seconds
-****************************************************************************/
-BOOL receive_local_message(int fd, char *buffer, int buffer_len, int timeout)
-{
- struct sockaddr_in from;
- int fromlen = sizeof(from);
- int32 msg_len = 0;
-
- if(timeout != 0)
- {
- struct timeval to;
- fd_set fds;
- int selrtn;
-
- FD_ZERO(&fds);
- FD_SET(fd,&fds);
-
- to.tv_sec = timeout / 1000;
- to.tv_usec = (timeout % 1000) * 1000;
-
- selrtn = sys_select(&fds,&to);
-
- /* Check if error */
- if(selrtn == -1)
- {
- /* something is wrong. Maybe the socket is dead? */
- smb_read_error = READ_ERROR;
- return False;
- }
-
- /* Did we timeout ? */
- if (selrtn == 0)
- {
- smb_read_error = READ_TIMEOUT;
- return False;
- }
- }
-
- /*
- * Read a loopback udp message.
- */
- msg_len = recvfrom(fd, &buffer[UDP_CMD_HEADER_LEN],
- buffer_len - UDP_CMD_HEADER_LEN, 0,
- (struct sockaddr *)&from, &fromlen);
-
- if(msg_len < 0)
- {
- DEBUG(0,("receive_local_message. Error in recvfrom. (%s).\n",strerror(errno)));
- return False;
- }
-
- /* Validate message length. */
- if(msg_len > (buffer_len - UDP_CMD_HEADER_LEN))
- {
- DEBUG(0,("receive_local_message: invalid msg_len (%d) max can be %d\n",
- msg_len,
- buffer_len - UDP_CMD_HEADER_LEN));
- return False;
- }
-
- /* Validate message from address (must be localhost). */
- if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK))
- {
- DEBUG(0,("receive_local_message: invalid 'from' address \
-(was %x should be 127.0.0.1\n", from.sin_addr.s_addr));
- return False;
- }
-
- /* Setup the message header */
- SIVAL(buffer,UDP_CMD_LEN_OFFSET,msg_len);
- SSVAL(buffer,UDP_CMD_PORT_OFFSET,ntohs(from.sin_port));
-
- return True;
-}
-
-/****************************************************************************
- structure to hold a linked list of local udp messages.
- for processing.
-****************************************************************************/
-
-typedef struct _udp_message_list {
- struct _udp_message_list *msg_next;
- char *msg_buf;
- int msg_len;
-} udp_message_list;
-
-static udp_message_list *udp_msg_head = NULL;
-
-/****************************************************************************
- Function to push a linked list of local udp messages ready
- for processing.
-****************************************************************************/
-BOOL push_local_message(char *buf, int msg_len)
-{
- udp_message_list *msg = (udp_message_list *)malloc(sizeof(udp_message_list));
-
- if(msg == NULL)
- {
- DEBUG(0,("push_local_message: malloc fail (1)\n"));
- return False;
- }
-
- msg->msg_buf = (char *)malloc(msg_len);
- if(msg->msg_buf == NULL)
- {
- DEBUG(0,("push_local_message: malloc fail (2)\n"));
- free((char *)msg);
- return False;
- }
-
- memcpy(msg->msg_buf, buf, msg_len);
- msg->msg_len = msg_len;
-
- msg->msg_next = udp_msg_head;
- udp_msg_head = msg;
-
- return True;
-}
-
-/****************************************************************************
- Do a select on an two fd's - with timeout.
-
- If a local udp message has been pushed onto the
- queue (this can only happen during oplock break
- processing) return this first.
-
- If the first smbfd is ready then read an smb from it.
- if the second (loopback UDP) fd is ready then read a message
- from it and setup the buffer header to identify the length
- and from address.
- Returns False on timeout or error.
- Else returns True.
-
-The timeout is in milli seconds
-****************************************************************************/
-BOOL receive_message_or_smb(int smbfd, int oplock_fd,
- char *buffer, int buffer_len,
- int timeout, BOOL *got_smb)
-{
- fd_set fds;
- int selrtn;
- struct timeval to;
-
- *got_smb = False;
-
- /*
- * Check to see if we already have a message on the udp queue.
- * If so - copy and return it.
- */
-
- if(udp_msg_head)
- {
- udp_message_list *msg = udp_msg_head;
- memcpy(buffer, msg->msg_buf, MIN(buffer_len, msg->msg_len));
- udp_msg_head = msg->msg_next;
-
- /* Free the message we just copied. */
- free((char *)msg->msg_buf);
- free((char *)msg);
- return True;
- }
-
- FD_ZERO(&fds);
- FD_SET(smbfd,&fds);
- FD_SET(oplock_fd,&fds);
-
- to.tv_sec = timeout / 1000;
- to.tv_usec = (timeout % 1000) * 1000;
-
- selrtn = sys_select(&fds,timeout>0?&to:NULL);
-
- /* Check if error */
- if(selrtn == -1) {
- /* something is wrong. Maybe the socket is dead? */
- smb_read_error = READ_ERROR;
- return False;
- }
-
- /* Did we timeout ? */
- if (selrtn == 0) {
- smb_read_error = READ_TIMEOUT;
- return False;
- }
-
- if (FD_ISSET(smbfd,&fds))
- {
- *got_smb = True;
- return receive_smb(smbfd, buffer, 0);
- }
- else
- {
- return receive_local_message(oplock_fd, buffer, buffer_len, 0);
- }
-}
/****************************************************************************
send an smb to a fd
@@ -2566,27 +2296,21 @@ int name_extract(char *buf,int ofs,char *name)
strcpy(name,"");
if (d < -50 || d > 50) return(0);
return(name_interpret(p,name));
-}
+}
+
/****************************************************************************
return the total storage length of a mangled name
****************************************************************************/
-int name_len( char *s )
- {
- int len;
-
- /* If the two high bits of the byte are set, return 2. */
- if( 0xC0 == (*(unsigned char *)s & 0xC0) )
+int name_len(char *s)
+{
+ char *s0=s;
+ unsigned char c = *(unsigned char *)s;
+ if ((c & 0xC0) == 0xC0)
return(2);
-
- /* Add up the length bytes. */
- for( len = 1; (*s); s += (*s) + 1 )
- {
- len += *s + 1;
- }
-
- return( len );
- } /* name_len */
+ while (*s) s += (*s)+1;
+ return(PTR_DIFF(s,s0)+1);
+}
/****************************************************************************
send a single packet to a port on another machine
@@ -2622,8 +2346,8 @@ BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
if (!ret)
- DEBUG(0,("Packet send to %s(%d) failed ERRNO=%s\n",
- inet_ntoa(ip),port,strerror(errno)));
+ DEBUG(0,("Packet send to %s(%d) failed ERRNO=%d\n",
+ inet_ntoa(ip),port,errno));
close(out_fd);
return(ret);
@@ -2875,7 +2599,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
if (strequal(p1,"*")) return(True);
- DEBUG(8,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
+ DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
if (trans2) {
fstrcpy(ebase,p1);
@@ -2903,7 +2627,7 @@ BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
matched = do_match(sbase,ebase,case_sig) &&
(trans2 || do_match(sext,eext,case_sig));
- DEBUG(8,("mask_match returning %d\n", matched));
+ DEBUG(5,("mask_match returning %d\n", matched));
return matched;
}
@@ -3277,8 +3001,8 @@ int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
{
if (port) {
if (port == SMB_PORT || port == NMB_PORT)
- DEBUG(dlevel,("bind failed on port %d socket_addr=%s (%s)\n",
- port,inet_ntoa(sock.sin_addr),strerror(errno)));
+ DEBUG(dlevel,("bind failed on port %d socket_addr=%x (%s)\n",
+ port,socket_addr,strerror(errno)));
close(res);
if (dlevel > 0 && port < 1000)
@@ -3311,8 +3035,26 @@ int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
if (res == -1)
{ DEBUG(0,("socket error\n")); return -1; }
- if (type != SOCK_STREAM) return(res);
+#ifdef BIND_LOCAL_OUTPUT_SOCKET
+ {
+ struct sockaddr_in sock_in;
+ /* Bind the local part of this socket to the address
+ given in the socket address parameter. */
+
+ bzero((char *)&sock_in,sizeof(sock_in));
+ putip((char *)&sock_in.sin_addr,(char *)interpret_addr2(lp_socket_address()));
+ sock_in.sin_port = 0;
+ sock_in.sin_family = PF_INET;
+
+ if (bind(res, (struct sockaddr * ) &sock_in,sizeof(sock_in)) < 0)
+ DEBUG(0,("Failed to bind local socket address for output socket. Error was %s\n",
+ strerror(errno)));
+ }
+#endif /* BIND_LOCAL_OUTPUT_SOCKET */
+
+ if (type != SOCK_STREAM) return(res);
+
bzero((char *)&sock_out,sizeof(sock_out));
putip((char *)&sock_out.sin_addr,(char *)addr);
@@ -3541,10 +3283,6 @@ char *client_name(void)
strcpy(name_buf,"UNKNOWN");
- if (Client == -1) {
- return name_buf;
- }
-
if (getpeername(Client, &sa, &length) < 0) {
DEBUG(0,("getpeername failed\n"));
return name_buf;
@@ -3583,10 +3321,6 @@ char *client_addr(void)
strcpy(addr_buf,"0.0.0.0");
- if (Client == -1) {
- return addr_buf;
- }
-
if (getpeername(Client, &sa, &length) < 0) {
DEBUG(0,("getpeername failed\n"));
return addr_buf;
@@ -3598,105 +3332,44 @@ char *client_addr(void)
return addr_buf;
}
-char *automount_server(char *user_name)
-{
- static pstring server_name;
-
-#if (defined(NETGROUP) && defined (AUTOMOUNT))
- int nis_error; /* returned by yp all functions */
- char *nis_result; /* yp_match inits this */
- int nis_result_len; /* and set this */
- char *nis_domain; /* yp_get_default_domain inits this */
- char *nis_map = (char *)lp_nis_home_map_name();
- int home_server_len;
-
- /* set to default of local machine */
- pstrcpy(server_name, local_machine);
-
- if ((nis_error = yp_get_default_domain(&nis_domain)) != 0)
- {
- DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
- }
-
- DEBUG(5, ("NIS Domain: %s\n", nis_domain));
-
- if ((nis_error = yp_match(nis_domain, nis_map,
- user_name, strlen(user_name),
- &nis_result, &nis_result_len)) != 0)
- {
- DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
- }
-
- if (!nis_error && lp_nis_home_map())
- {
- home_server_len = strcspn(nis_result,":");
- DEBUG(5, ("NIS lookup succeeded. Home server length: %d\n",home_server_len));
- if (home_server_len > sizeof(pstring))
- {
- home_server_len = sizeof(pstring);
- }
- strncpy(server_name, nis_result, home_server_len);
- }
-#else
- /* use the local machine name instead of the auto-map server */
- pstrcpy(server_name, local_machine);
-#endif
-
- DEBUG(4,("Home server: %s\n", server_name));
-
- return server_name;
-}
-
/*******************************************************************
sub strings with useful parameters
Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
Paul Rippin <pr3245@nopc.eurostat.cec.be>
********************************************************************/
void standard_sub_basic(char *str)
-{
- char *s, *p;
- char pidstr[10];
- struct passwd *pass;
- char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
+ {
+ char *s, *p;
+ char pidstr[10];
+ struct passwd *pass;
- for (s = str ; (p = strchr(s,'%')) != NULL ; s = p )
- {
- switch (*(p+1))
- {
- case 'G' :
- {
- if ((pass = Get_Pwnam(sesssetup_user,False))!=NULL)
- {
- string_sub(p,"%G",gidtoname(pass->pw_gid));
- }
- else
- {
- p += 2;
- }
- break;
- }
- case 'N' : string_sub(p,"%N", automount_server(username)); break;
- case 'I' : string_sub(p,"%I", client_addr()); break;
- case 'L' : string_sub(p,"%L", local_machine); break;
- case 'M' : string_sub(p,"%M", client_name()); break;
- case 'R' : string_sub(p,"%R", remote_proto); break;
- case 'T' : string_sub(p,"%T", timestring()); break;
- case 'U' : string_sub(p,"%U", username); break;
- case 'a' : string_sub(p,"%a", remote_arch); break;
- case 'd' :
- {
- sprintf(pidstr,"%d",(int)getpid());
- string_sub(p,"%d", pidstr);
- break;
- }
- case 'h' : string_sub(p,"%h", myhostname); break;
- case 'm' : string_sub(p,"%m", remote_machine); break;
- case 'v' : string_sub(p,"%v", VERSION); break;
- case '\0': p++; break; /* don't run off end if last character is % */
- default : p+=2; break;
- }
- }
- return;
+ for (s = str ; (p = strchr(s,'%')) != NULL ; s = p )
+ {
+ switch (*(p+1))
+ {
+ case 'G' : if ((pass = Get_Pwnam(sesssetup_user,False))!=NULL)
+ string_sub(p,"%G",gidtoname(pass->pw_gid));
+ else
+ p += 2;
+ break;
+ case 'I' : string_sub(p,"%I",client_addr()); break;
+ case 'L' : string_sub(p,"%L",local_machine); break;
+ case 'M' : string_sub(p,"%M",client_name()); break;
+ case 'R' : string_sub(p,"%R",remote_proto); break;
+ case 'T' : string_sub(p,"%T",timestring()); break;
+ case 'U' : string_sub(p,"%U",sesssetup_user); break;
+ case 'a' : string_sub(p,"%a",remote_arch); break;
+ case 'd' : sprintf(pidstr,"%d",(int)getpid());
+ string_sub(p,"%d",pidstr);
+ break;
+ case 'h' : string_sub(p,"%h",myhostname); break;
+ case 'm' : string_sub(p,"%m",remote_machine); break;
+ case 'v' : string_sub(p,"%v",VERSION); break;
+ case '\0' : p++; break; /* don't run off end if last character is % */
+ default : p+=2; break;
+ }
+ }
+ return;
}
/*******************************************************************
@@ -3787,7 +3460,29 @@ check if a process exists. Does this work on all unixes?
****************************************************************************/
BOOL process_exists(int pid)
{
- return(kill(pid,0) == 0 || errno != ESRCH);
+#ifdef LINUX
+ fstring s;
+ sprintf(s,"/proc/%d",pid);
+ return(directory_exist(s,NULL));
+#else
+ {
+ static BOOL tested=False;
+ static BOOL ok=False;
+ fstring s;
+ if (!tested) {
+ tested = True;
+ sprintf(s,"/proc/%05d",(int)getpid());
+ ok = file_exist(s,NULL);
+ }
+ if (ok) {
+ sprintf(s,"/proc/%05d",pid);
+ return(file_exist(s,NULL));
+ }
+ }
+
+ /* CGH 8/16/96 - added ESRCH test */
+ return(pid == getpid() || kill(pid,0) == 0 || errno != ESRCH);
+#endif
}
@@ -3841,7 +3536,7 @@ my own panic function - not suitable for general use
********************************************************************/
void ajt_panic(void)
{
- system("/usr/bin/X11/xedit -display solen:0 /tmp/ERROR_FAULT");
+ system("/usr/bin/X11/xedit -display ljus:0 /tmp/ERROR_FAULT");
}
#endif
@@ -3896,24 +3591,24 @@ char *readdirname(void *p)
return(dname);
}
-/*******************************************************************
- Utility function used to decide if the last component
- of a path matches a (possibly wildcarded) entry in a namelist.
-********************************************************************/
+/*
+ * Utility function used to decide if the last component
+ * of a path matches a (possibly wildcarded) entry in a namelist.
+ */
BOOL is_in_path(char *name, name_compare_entry *namelist)
{
pstring last_component;
char *p;
- DEBUG(8, ("is_in_path: %s\n", name));
+ DEBUG(5, ("is_in_path: %s\n", name));
/* if we have no list it's obviously not in the path */
if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL)))
- {
- DEBUG(8,("is_in_path: no name list.\n"));
+ {
+ DEBUG(5,("is_in_path: no name list.\n"));
return False;
- }
+}
/* Get the last component of the unix name. */
p = strrchr(name, '/');
@@ -3927,7 +3622,7 @@ BOOL is_in_path(char *name, name_compare_entry *namelist)
/* look for a wildcard match. */
if (mask_match(last_component, namelist->name, case_sensitive, False))
{
- DEBUG(8,("is_in_path: mask match succeeded\n"));
+ DEBUG(5,("is_in_path: mask match succeeded\n"));
return True;
}
}
@@ -3936,29 +3631,29 @@ BOOL is_in_path(char *name, name_compare_entry *namelist)
if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
(!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
{
- DEBUG(8,("is_in_path: match succeeded\n"));
+ DEBUG(5,("is_in_path: match succeeded\n"));
return True;
}
}
}
- DEBUG(8,("is_in_path: match not found\n"));
+ DEBUG(5,("is_in_path: match not found\n"));
return False;
}
-/*******************************************************************
- Strip a '/' separated list into an array of
- name_compare_enties structures suitable for
- passing to is_in_path(). We do this for
- speed so we can pre-parse all the names in the list
- and don't do it for each call to is_in_path().
- namelist is modified here and is assumed to be
- a copy owned by the caller.
- We also check if the entry contains a wildcard to
- remove a potentially expensive call to mask_match
- if possible.
-********************************************************************/
-
+/*
+ * Strip a '/' separated list into an array of
+ * name_compare_enties structures suitable for
+ * passing to is_in_path(). We do this for
+ * speed so we can pre-parse all the names in the list
+ * and don't do it for each call to is_in_path().
+ * namelist is modified here and is assumed to be
+ * a copy owned by the caller.
+ * We also check if the entry contains a wildcard to
+ * remove a potentially expensive call to mask_match
+ * if possible.
+ */
+
void set_namearray(name_compare_entry **ppname_array, char *namelist)
{
char *name_end;
@@ -4099,7 +3794,7 @@ BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
#endif
- DEBUG(8,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
+ DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
lock.l_type = type;
lock.l_whence = SEEK_SET;
@@ -4147,7 +3842,7 @@ BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
}
/* everything went OK */
- DEBUG(8,("Lock call successful\n"));
+ DEBUG(5,("Lock call successful\n"));
return(True);
#else
@@ -4193,7 +3888,7 @@ void file_unlock(int fd)
is the name specified one of my netbios names
returns true is it is equal, false otherwise
********************************************************************/
-BOOL is_myname(char *s)
+BOOL is_myname(const char *s)
{
int n;
BOOL ret = False;
@@ -4246,304 +3941,51 @@ enum remote_arch_types get_remote_arch()
/*******************************************************************
-skip past some unicode strings in a buffer
-********************************************************************/
-char *skip_unicode_string(char *buf,int n)
-{
- while (n--)
- {
- while (*buf)
- buf += 2;
- buf += 2;
- }
- return(buf);
-}
-
-/*******************************************************************
-Return a ascii version of a unicode string
-Hack alert: uses fixed buffer(s) and only handles ascii strings
-********************************************************************/
-#define MAXUNI 1024
-char *unistrn2(uint16 *buf, int len)
-{
- static char lbufs[8][MAXUNI];
- static int nexti;
- char *lbuf = lbufs[nexti];
- char *p;
-
- nexti = (nexti+1)%8;
-
- DEBUG(10, ("unistrn2: "));
-
- for (p = lbuf; *buf && p-lbuf < MAXUNI-2 && len > 0; len--, p++, buf++)
- {
- DEBUG(10, ("%4x ", *buf));
- *p = *buf;
- }
-
- DEBUG(10,("\n"));
-
- *p = 0;
- return lbuf;
-}
-
-/*******************************************************************
-Return a ascii version of a unicode string
-Hack alert: uses fixed buffer(s) and only handles ascii strings
-********************************************************************/
-#define MAXUNI 1024
-char *unistr2(uint16 *buf)
-{
- static char lbufs[8][MAXUNI];
- static int nexti;
- char *lbuf = lbufs[nexti];
- char *p;
-
- nexti = (nexti+1)%8;
-
- DEBUG(10, ("unistr2: "));
-
- for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf++)
- {
- DEBUG(10, ("%4x ", *buf));
- *p = *buf;
- }
-
- DEBUG(10,("\n"));
-
- *p = 0;
- return lbuf;
-}
-
-/*******************************************************************
-create a null-terminated unicode string from a null-terminated ascii string.
-return number of unicode chars copied, excluding the null character.
-
-only handles ascii strings
+safe string copy into a fstring
********************************************************************/
-#define MAXUNI 1024
-int struni2(uint16 *p, char *buf)
+void fstrcpy(char *dest, char *src)
{
- int len = 0;
-
- if (p == NULL) return 0;
-
- DEBUG(10, ("struni2: "));
-
- if (buf != NULL)
- {
- for (; *buf && len < MAXUNI-2; len++, p++, buf++)
- {
- DEBUG(10, ("%2x ", *buf));
- *p = *buf;
- }
-
- DEBUG(10,("\n"));
+ int maxlength = sizeof(fstring) - 1;
+ if (!dest) {
+ DEBUG(0,("ERROR: NULL dest in fstrcpy\n"));
+ return;
}
- *p = 0;
-
- return len;
-}
-
-/*******************************************************************
-Return a ascii version of a unicode string
-Hack alert: uses fixed buffer(s) and only handles ascii strings
-********************************************************************/
-#define MAXUNI 1024
-char *unistr(char *buf)
-{
- static char lbufs[8][MAXUNI];
- static int nexti;
- char *lbuf = lbufs[nexti];
- char *p;
-
- nexti = (nexti+1)%8;
-
- for (p = lbuf; *buf && p-lbuf < MAXUNI-2; p++, buf += 2)
- {
- *p = *buf;
+ if (!src) {
+ *dest = 0;
+ return;
}
- *p = 0;
- return lbuf;
-}
-/*******************************************************************
-strncpy for unicode strings
-********************************************************************/
-int unistrncpy(char *dst, char *src, int len)
-{
- int num_wchars = 0;
-
- while (*src && len > 0)
- {
- *dst++ = *src++;
- *dst++ = *src++;
- len--;
- num_wchars++;
+ while (maxlength-- && *src)
+ *dest++ = *src++;
+ *dest = 0;
+ if (*src) {
+ DEBUG(0,("ERROR: string overflow by %d in fstrcpy\n",
+ strlen(src)));
}
- *dst++ = 0;
- *dst++ = 0;
-
- return num_wchars;
}
-
-/*******************************************************************
-strcpy for unicode strings. returns length (in num of wide chars)
-********************************************************************/
-int unistrcpy(char *dst, char *src)
-{
- int num_wchars = 0;
-
- while (*src)
- {
- *dst++ = *src++;
- *dst++ = *src++;
- num_wchars++;
- }
- *dst++ = 0;
- *dst++ = 0;
-
- return num_wchars;
-}
-
-
-/*******************************************************************
-safe string copy into a fstring
-********************************************************************/
-void fstrcpy(char *dest, char *src)
-{
- int maxlength = sizeof(fstring) - 1;
- if (!dest) {
- DEBUG(0,("ERROR: NULL dest in fstrcpy\n"));
- return;
- }
-
- if (!src) {
- *dest = 0;
- return;
- }
-
- while (maxlength-- && *src)
- *dest++ = *src++;
- *dest = 0;
- if (*src) {
- DEBUG(0,("ERROR: string overflow by %d in fstrcpy\n",
- strlen(src)));
- }
-}
-
/*******************************************************************
safe string copy into a pstring
********************************************************************/
void pstrcpy(char *dest, char *src)
{
- int maxlength = sizeof(pstring) - 1;
- if (!dest) {
- DEBUG(0,("ERROR: NULL dest in pstrcpy\n"));
- return;
- }
-
- if (!src) {
- *dest = 0;
- return;
- }
-
- while (maxlength-- && *src)
- *dest++ = *src++;
- *dest = 0;
- if (*src) {
- DEBUG(0,("ERROR: string overflow by %d in pstrcpy\n",
- strlen(src)));
- }
-}
-
-
-/*******************************************************************
-align a pointer to a multiple of 4 bytes
-********************************************************************/
-char *align4(char *q, char *base)
-{
- if ((q - base) & 3)
- {
- q += 4 - ((q - base) & 3);
+ int maxlength = sizeof(pstring) - 1;
+ if (!dest) {
+ DEBUG(0,("ERROR: NULL dest in pstrcpy\n"));
+ return;
}
- return q;
-}
-/*******************************************************************
-align a pointer to a multiple of 2 bytes
-********************************************************************/
-char *align2(char *q, char *base)
-{
- if ((q - base) & 1)
- {
- q++;
+ if (!src) {
+ *dest = 0;
+ return;
}
- return q;
-}
-/*******************************************************************
-align a pointer to a multiple of align_offset bytes. looks like it
-will work for offsets of 0, 2 and 4...
-********************************************************************/
-char *align_offset(char *q, char *base, int align_offset_len)
-{
- int mod = ((q - base) & (align_offset_len-1));
- if (align_offset_len != 0 && mod != 0)
- {
- q += align_offset_len - mod;
+ while (maxlength-- && *src)
+ *dest++ = *src++;
+ *dest = 0;
+ if (*src) {
+ DEBUG(0,("ERROR: string overflow by %d in pstrcpy\n",
+ strlen(src)));
}
- return q;
-}
-
-void print_asc(int level, unsigned char *buf,int len)
-{
- int i;
- for (i=0;i<len;i++)
- DEBUG(level,("%c", isprint(buf[i])?buf[i]:'.'));
-}
-
-void dump_data(int level,char *buf1,int len)
-{
- unsigned char *buf = (unsigned char *)buf1;
- int i=0;
- if (len<=0) return;
-
- DEBUG(level,("[%03X] ",i));
- for (i=0;i<len;) {
- DEBUG(level,("%02X ",(int)buf[i]));
- i++;
- if (i%8 == 0) DEBUG(level,(" "));
- if (i%16 == 0) {
- print_asc(level,&buf[i-16],8); DEBUG(level,(" "));
- print_asc(level,&buf[i-8],8); DEBUG(level,("\n"));
- if (i<len) DEBUG(level,("[%03X] ",i));
- }
- }
- if (i%16) {
- int n;
-
- n = 16 - (i%16);
- DEBUG(level,(" "));
- if (n>8) DEBUG(level,(" "));
- while (n--) DEBUG(level,(" "));
-
- n = MIN(8,i%16);
- print_asc(level,&buf[i-(i%16)],n); DEBUG(level,(" "));
- n = (i%16) - n;
- if (n>0) print_asc(level,&buf[i-n],n);
- DEBUG(level,("\n"));
- }
}
-
-char *tab_depth(int depth)
-{
- static pstring spaces;
- memset(spaces, ' ', depth * 4);
- spaces[depth * 4] = 0;
- return spaces;
-}
-
-
diff --git a/source/libsmb/clientgen.c b/source/libsmb/clientgen.c
index d827eadfe14..d50349501fe 100644
--- a/source/libsmb/clientgen.c
+++ b/source/libsmb/clientgen.c
@@ -24,7 +24,6 @@
#endif
#include "includes.h"
-#include "trans2.h"
extern int DEBUGLEVEL;
@@ -32,7 +31,7 @@ extern int DEBUGLEVEL;
/****************************************************************************
setup basics in a outgoing packet
****************************************************************************/
-static void cli_setup_packet(struct cli_state *cli)
+static void cli_setup_pkt(struct cli_state *cli)
{
SSVAL(cli->outbuf,smb_pid,cli->pid);
SSVAL(cli->outbuf,smb_uid,cli->uid);
@@ -58,14 +57,14 @@ static BOOL cli_send_trans(struct cli_state *cli,
char *outdata,*outparam;
char *p;
- this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */
- this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam));
+ this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*SIZEOFWORD)); /* hack */
+ this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*SIZEOFWORD+this_lparam));
bzero(cli->outbuf,smb_size);
set_message(cli->outbuf,14+lsetup,0,True);
CVAL(cli->outbuf,smb_com) = trans;
SSVAL(cli->outbuf,smb_tid, cli->cnum);
- cli_setup_packet(cli);
+ cli_setup_pkt(cli);
outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? strlen(name)+1 : 3);
outdata = outparam+this_lparam;
@@ -84,7 +83,7 @@ static BOOL cli_send_trans(struct cli_state *cli,
SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
SCVAL(cli->outbuf,smb_suwcnt,lsetup); /* suwcnt */
for (i=0;i<lsetup;i++) /* setup[] */
- SSVAL(cli->outbuf,smb_setup+i*2,setup[i]);
+ SSVAL(cli->outbuf,smb_setup+i*SIZEOFWORD,setup[i]);
p = smb_buf(cli->outbuf);
if (trans==SMBtrans) {
strcpy(p,name); /* name[] */
@@ -132,7 +131,7 @@ static BOOL cli_send_trans(struct cli_state *cli,
SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */
SSVAL(cli->outbuf,smb_sdsdisp,tot_data); /* dsdisp */
if (trans==SMBtrans2)
- SSVALS(cli->outbuf,smb_sfid,fid); /* fid */
+ SSVAL(cli->outbuf,smb_sfid,fid); /* fid */
if (this_lparam) /* param[] */
memcpy(outparam,param,this_lparam);
if (this_ldata) /* data[] */
@@ -244,7 +243,7 @@ static BOOL cli_api(struct cli_state *cli,
int *rdrcnt, char *param,char *data,
char **rparam, char **rdata)
{
- cli_send_trans(cli,SMBtrans,PIPE_LANMAN,0,0,
+ cli_send_trans(cli,SMBtrans,"\\PIPE\\LANMAN",0,0,
data,param,NULL,
drcnt,prcnt,0,
mdrcnt,mprcnt,0);
@@ -314,80 +313,6 @@ BOOL cli_NetWkstaUserLogon(struct cli_state *cli,char *user, char *workstation)
}
-/****************************************************************************
-call a NetServerEnum for the specified workgroup and servertype mask.
-This function then calls the specified callback function for each name returned.
-
-The callback function takes 3 arguments: the machine name, the server type and
-the comment.
-****************************************************************************/
-BOOL cli_NetServerEnum(struct cli_state *cli, char *workgroup, uint32 stype,
- void (*fn)(char *, uint32, char *))
-{
- char *rparam = NULL;
- char *rdata = NULL;
- int rdrcnt,rprcnt;
- char *p;
- pstring param;
- int uLevel = 1;
- int count = -1;
-
- /* send a SMBtrans command with api NetServerEnum */
- p = param;
- SSVAL(p,0,0x68); /* api number */
- p += 2;
- strcpy(p,"WrLehDz");
- p = skip_string(p,1);
-
- strcpy(p,"B16BBDz");
-
- p = skip_string(p,1);
- SSVAL(p,0,uLevel);
- SSVAL(p,2,BUFFER_SIZE);
- p += 4;
- SIVAL(p,0,stype);
- p += 4;
-
- pstrcpy(p, workgroup);
- p = skip_string(p,1);
-
- if (cli_api(cli,
- PTR_DIFF(p,param), /* param count */
- 0, /*data count */
- 8, /* mprcount */
- BUFFER_SIZE, /* mdrcount */
- &rprcnt,&rdrcnt,
- param, NULL,
- &rparam,&rdata)) {
- int res = SVAL(rparam,0);
- int converter=SVAL(rparam,2);
- int i;
-
- if (res == 0) {
- count=SVAL(rparam,4);
- p = rdata;
-
- for (i = 0;i < count;i++, p += 26) {
- char *sname = p;
- int comment_offset = (IVAL(p,22) & 0xFFFF)-converter;
- char *cmnt = comment_offset?(rdata+comment_offset):"";
- if (comment_offset < 0 || comment_offset > rdrcnt) continue;
-
- stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
-
- fn(sname, stype, cmnt);
- }
- }
- }
-
- if (rparam) free(rparam);
- if (rdata) free(rdata);
-
- return(count > 0);
-}
-
-
-
static struct {
int prot;
@@ -420,15 +345,17 @@ BOOL cli_session_setup(struct cli_state *cli,
fstring pword;
if (cli->protocol < PROTOCOL_LANMAN1)
- return True;
+ return False;
if (passlen > sizeof(pword)-1) {
return False;
}
if ((cli->sec_mode & 2) && *pass && passlen != 24) {
+#ifdef SMB_PASSWD
passlen = 24;
SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
+#endif
} else {
memcpy(pword, pass, passlen);
}
@@ -442,7 +369,7 @@ BOOL cli_session_setup(struct cli_state *cli,
if (cli->protocol < PROTOCOL_NT1) {
set_message(cli->outbuf,10,1 + strlen(user) + passlen,True);
CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
- cli_setup_packet(cli);
+ cli_setup_pkt(cli);
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
SSVAL(cli->outbuf,smb_vwv2,cli->max_xmit);
@@ -458,7 +385,7 @@ BOOL cli_session_setup(struct cli_state *cli,
} else {
set_message(cli->outbuf,13,0,True);
CVAL(cli->outbuf,smb_com) = SMBsesssetupX;
- cli_setup_packet(cli);
+ cli_setup_pkt(cli);
CVAL(cli->outbuf,smb_vwv0) = 0xFF;
SSVAL(cli->outbuf,smb_vwv2,BUFFER_SIZE);
@@ -504,31 +431,16 @@ BOOL cli_session_setup(struct cli_state *cli,
send a tconX
****************************************************************************/
BOOL cli_send_tconX(struct cli_state *cli,
- char *share, char *dev, char *pass, int passlen)
+ char *share, char *dev, char *pword, int passlen)
{
- fstring fullshare, pword;
char *p;
bzero(cli->outbuf,smb_size);
bzero(cli->inbuf,smb_size);
- if (cli->sec_mode & 1) {
- passlen = 1;
- pass = "";
- }
-
- if ((cli->sec_mode & 2) && *pass && passlen != 24) {
- passlen = 24;
- SMBencrypt((uchar *)pass,(uchar *)cli->cryptkey,(uchar *)pword);
- } else {
- memcpy(pword, pass, passlen);
- }
-
- sprintf(fullshare, "\\\\%s\\%s", cli->desthost, share);
-
set_message(cli->outbuf,4,
- 2 + strlen(fullshare) + passlen + strlen(dev),True);
+ 2 + strlen(share) + passlen + strlen(dev),True);
CVAL(cli->outbuf,smb_com) = SMBtconX;
- cli_setup_packet(cli);
+ cli_setup_pkt(cli);
SSVAL(cli->outbuf,smb_vwv0,0xFF);
SSVAL(cli->outbuf,smb_vwv3,passlen);
@@ -536,7 +448,7 @@ BOOL cli_send_tconX(struct cli_state *cli,
p = smb_buf(cli->outbuf);
memcpy(p,pword,passlen);
p += passlen;
- strcpy(p,fullshare);
+ strcpy(p,share);
p = skip_string(p,1);
strcpy(p,dev);
@@ -564,7 +476,7 @@ BOOL cli_tdis(struct cli_state *cli)
set_message(cli->outbuf,0,0,True);
CVAL(cli->outbuf,smb_com) = SMBtdis;
SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
+ cli_setup_pkt(cli);
send_smb(cli->fd,cli->outbuf);
if (!receive_smb(cli->fd,cli->inbuf,cli->timeout))
@@ -573,640 +485,6 @@ BOOL cli_tdis(struct cli_state *cli)
return CVAL(cli->inbuf,smb_rcls) == 0;
}
-/****************************************************************************
-rename a file
-****************************************************************************/
-BOOL cli_mv(struct cli_state *cli, char *fname_src, char *fname_dst)
-{
- char *p;
-
- bzero(cli->outbuf,smb_size);
- bzero(cli->inbuf,smb_size);
-
- set_message(cli->outbuf,1, 4 + strlen(fname_src) + strlen(fname_dst), True);
-
- CVAL(cli->outbuf,smb_com) = SMBmv;
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
-
- SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
-
- p = smb_buf(cli->outbuf);
- *p++ = 4;
- strcpy(p,fname_src);
- p = skip_string(p,1);
- *p++ = 4;
- strcpy(p,fname_dst);
-
- send_smb(cli->fd,cli->outbuf);
- if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
- return False;
- }
-
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
-
- return True;
-}
-
-/****************************************************************************
-delete a file
-****************************************************************************/
-BOOL cli_unlink(struct cli_state *cli, char *fname)
-{
- char *p;
-
- bzero(cli->outbuf,smb_size);
- bzero(cli->inbuf,smb_size);
-
- set_message(cli->outbuf,1, 2 + strlen(fname),True);
-
- CVAL(cli->outbuf,smb_com) = SMBunlink;
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
-
- SSVAL(cli->outbuf,smb_vwv0,aSYSTEM | aHIDDEN);
-
- p = smb_buf(cli->outbuf);
- *p++ = 4;
- strcpy(p,fname);
-
- send_smb(cli->fd,cli->outbuf);
- if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
- return False;
- }
-
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
-
- return True;
-}
-
-
-/****************************************************************************
-create a directory
-****************************************************************************/
-BOOL cli_mkdir(struct cli_state *cli, char *dname)
-{
- char *p;
-
- bzero(cli->outbuf,smb_size);
- bzero(cli->inbuf,smb_size);
-
- set_message(cli->outbuf,0, 2 + strlen(dname),True);
-
- CVAL(cli->outbuf,smb_com) = SMBmkdir;
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
-
- p = smb_buf(cli->outbuf);
- *p++ = 4;
- strcpy(p,dname);
-
- send_smb(cli->fd,cli->outbuf);
- if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
- return False;
- }
-
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
-
- return True;
-}
-
-/****************************************************************************
-remove a directory
-****************************************************************************/
-BOOL cli_rmdir(struct cli_state *cli, char *dname)
-{
- char *p;
-
- bzero(cli->outbuf,smb_size);
- bzero(cli->inbuf,smb_size);
-
- set_message(cli->outbuf,0, 2 + strlen(dname),True);
-
- CVAL(cli->outbuf,smb_com) = SMBrmdir;
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
-
- p = smb_buf(cli->outbuf);
- *p++ = 4;
- strcpy(p,dname);
-
- send_smb(cli->fd,cli->outbuf);
- if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
- return False;
- }
-
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
-
- return True;
-}
-
-
-
-/****************************************************************************
-open a file
-****************************************************************************/
-int cli_open(struct cli_state *cli, char *fname, int flags, int share_mode)
-{
- char *p;
- unsigned openfn=0;
- unsigned accessmode=0;
-
- if (flags & O_CREAT)
- openfn |= (1<<4);
- if (!(flags & O_EXCL)) {
- if (flags & O_TRUNC)
- openfn |= (1<<1);
- else
- openfn |= (1<<0);
- }
-
- accessmode = (share_mode<<4);
-
- if ((flags & O_RDWR) == O_RDWR) {
- accessmode |= 2;
- } else if ((flags & O_WRONLY) == O_WRONLY) {
- accessmode |= 1;
- }
-
- bzero(cli->outbuf,smb_size);
- bzero(cli->inbuf,smb_size);
-
- set_message(cli->outbuf,15,1 + strlen(fname),True);
-
- CVAL(cli->outbuf,smb_com) = SMBopenX;
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
-
- SSVAL(cli->outbuf,smb_vwv0,0xFF);
- SSVAL(cli->outbuf,smb_vwv2,0); /* no additional info */
- SSVAL(cli->outbuf,smb_vwv3,accessmode);
- SSVAL(cli->outbuf,smb_vwv4,aSYSTEM | aHIDDEN);
- SSVAL(cli->outbuf,smb_vwv5,0);
- SSVAL(cli->outbuf,smb_vwv8,openfn);
-
- p = smb_buf(cli->outbuf);
- strcpy(p,fname);
- p = skip_string(p,1);
-
- send_smb(cli->fd,cli->outbuf);
- if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
- return -1;
- }
-
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return -1;
- }
-
- return SVAL(cli->inbuf,smb_vwv2);
-}
-
-
-
-
-/****************************************************************************
- close a file
-****************************************************************************/
-BOOL cli_close(struct cli_state *cli, int fnum)
-{
- bzero(cli->outbuf,smb_size);
- bzero(cli->inbuf,smb_size);
-
- set_message(cli->outbuf,3,0,True);
-
- CVAL(cli->outbuf,smb_com) = SMBclose;
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
-
- SSVAL(cli->outbuf,smb_vwv0,fnum);
- SIVALS(cli->outbuf,smb_vwv1,-1);
-
- send_smb(cli->fd,cli->outbuf);
- if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
- return False;
- }
-
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
-
- return True;
-}
-
-
-/****************************************************************************
- lock a file
-****************************************************************************/
-BOOL cli_lock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
-{
- char *p;
-
- bzero(cli->outbuf,smb_size);
- bzero(cli->inbuf,smb_size);
-
- set_message(cli->outbuf,8,10,True);
-
- CVAL(cli->outbuf,smb_com) = SMBlockingX;
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
-
- CVAL(cli->outbuf,smb_vwv0) = 0xFF;
- SSVAL(cli->outbuf,smb_vwv2,fnum);
- CVAL(cli->outbuf,smb_vwv3) = 0;
- SIVALS(cli->outbuf, smb_vwv4, timeout);
- SSVAL(cli->outbuf,smb_vwv6,0);
- SSVAL(cli->outbuf,smb_vwv7,1);
-
- p = smb_buf(cli->outbuf);
- SSVAL(p, 0, cli->pid);
- SIVAL(p, 2, offset);
- SIVAL(p, 6, len);
-
- send_smb(cli->fd,cli->outbuf);
- if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
- return False;
- }
-
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
-
- return True;
-}
-
-/****************************************************************************
- unlock a file
-****************************************************************************/
-BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len, int timeout)
-{
- char *p;
-
- bzero(cli->outbuf,smb_size);
- bzero(cli->inbuf,smb_size);
-
- set_message(cli->outbuf,8,10,True);
-
- CVAL(cli->outbuf,smb_com) = SMBlockingX;
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
-
- CVAL(cli->outbuf,smb_vwv0) = 0xFF;
- SSVAL(cli->outbuf,smb_vwv2,fnum);
- CVAL(cli->outbuf,smb_vwv3) = 0;
- SIVALS(cli->outbuf, smb_vwv4, timeout);
- SSVAL(cli->outbuf,smb_vwv6,1);
- SSVAL(cli->outbuf,smb_vwv7,0);
-
- p = smb_buf(cli->outbuf);
- SSVAL(p, 0, cli->pid);
- SIVAL(p, 2, offset);
- SIVAL(p, 6, len);
-
- send_smb(cli->fd,cli->outbuf);
- if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
- return False;
- }
-
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
-
- return True;
-}
-
-
-/****************************************************************************
- read from a file
-****************************************************************************/
-int cli_read(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size)
-{
- char *p;
-
- bzero(cli->outbuf,smb_size);
- bzero(cli->inbuf,smb_size);
-
- set_message(cli->outbuf,10,0,True);
-
- CVAL(cli->outbuf,smb_com) = SMBreadX;
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
-
- CVAL(cli->outbuf,smb_vwv0) = 0xFF;
- SSVAL(cli->outbuf,smb_vwv2,fnum);
- SIVAL(cli->outbuf,smb_vwv3,offset);
- SSVAL(cli->outbuf,smb_vwv5,size);
- SSVAL(cli->outbuf,smb_vwv6,size);
-
- send_smb(cli->fd,cli->outbuf);
- if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
- return -1;
- }
-
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return -1;
- }
-
- size = SVAL(cli->inbuf, smb_vwv5);
- p = smb_base(cli->inbuf) + SVAL(cli->inbuf,smb_vwv6);
-
- memcpy(buf, p, size);
-
- return size;
-}
-
-
-/****************************************************************************
- write to a file
-****************************************************************************/
-int cli_write(struct cli_state *cli, int fnum, char *buf, uint32 offset, uint16 size)
-{
- char *p;
-
- bzero(cli->outbuf,smb_size);
- bzero(cli->inbuf,smb_size);
-
- set_message(cli->outbuf,12,size,True);
-
- CVAL(cli->outbuf,smb_com) = SMBwriteX;
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
-
- CVAL(cli->outbuf,smb_vwv0) = 0xFF;
- SSVAL(cli->outbuf,smb_vwv2,fnum);
- SIVAL(cli->outbuf,smb_vwv3,offset);
-
- SSVAL(cli->outbuf,smb_vwv10,size);
- SSVAL(cli->outbuf,smb_vwv11,smb_buf(cli->outbuf) - smb_base(cli->outbuf));
-
- p = smb_base(cli->outbuf) + SVAL(cli->outbuf,smb_vwv11);
- memcpy(p, buf, size);
-
- send_smb(cli->fd,cli->outbuf);
- if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
- return -1;
- }
-
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return -1;
- }
-
- return SVAL(cli->inbuf, smb_vwv2);
-}
-
-
-/****************************************************************************
-do a SMBgetatr call
-****************************************************************************/
-BOOL cli_getatr(struct cli_state *cli, char *fname,
- int *attr, uint32 *size, time_t *t)
-{
- char *p;
-
- bzero(cli->outbuf,smb_size);
- bzero(cli->inbuf,smb_size);
-
- set_message(cli->outbuf,0,strlen(fname)+2,True);
-
- CVAL(cli->outbuf,smb_com) = SMBgetatr;
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
-
- p = smb_buf(cli->outbuf);
- *p = 4;
- strcpy(p+1, fname);
-
- send_smb(cli->fd,cli->outbuf);
- if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
- return False;
- }
-
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
-
- if (size) {
- *size = IVAL(cli->inbuf, smb_vwv3);
- }
-
- if (t) {
- *t = make_unix_date3(cli->inbuf+smb_vwv1);
- }
-
- if (attr) {
- *attr = SVAL(cli->inbuf,smb_vwv0);
- }
-
-
- return True;
-}
-
-
-/****************************************************************************
-do a SMBsetatr call
-****************************************************************************/
-BOOL cli_setatr(struct cli_state *cli, char *fname, int attr, time_t t)
-{
- char *p;
-
- bzero(cli->outbuf,smb_size);
- bzero(cli->inbuf,smb_size);
-
- set_message(cli->outbuf,8,strlen(fname)+4,True);
-
- CVAL(cli->outbuf,smb_com) = SMBsetatr;
- SSVAL(cli->outbuf,smb_tid,cli->cnum);
- cli_setup_packet(cli);
-
- SSVAL(cli->outbuf,smb_vwv0, attr);
- put_dos_date3(cli->outbuf,smb_vwv1, t);
-
- p = smb_buf(cli->outbuf);
- *p = 4;
- strcpy(p+1, fname);
- p = skip_string(p,1);
- *p = 4;
-
- send_smb(cli->fd,cli->outbuf);
- if (!receive_smb(cli->fd,cli->inbuf,cli->timeout)) {
- return False;
- }
-
- if (CVAL(cli->inbuf,smb_rcls) != 0) {
- return False;
- }
-
- return True;
-}
-
-/****************************************************************************
-send a qpathinfo call
-****************************************************************************/
-BOOL cli_qpathinfo(struct cli_state *cli, char *fname,
- time_t *c_time, time_t *a_time, time_t *m_time, uint32 *size)
-{
- int data_len = 0;
- int param_len = 0;
- uint16 setup = TRANSACT2_QPATHINFO;
- pstring param;
- char *rparam=NULL, *rdata=NULL;
-
- param_len = strlen(fname) + 7;
-
- memset(param, 0, param_len);
- SSVAL(param, 0, SMB_INFO_STANDARD);
- pstrcpy(&param[6], fname);
-
- if (!cli_send_trans(cli, SMBtrans2, NULL, -1, 0,
- NULL, param, &setup,
- data_len, param_len, 1,
- cli->max_xmit, 10, 0)) {
- return False;
- }
-
- if (!cli_receive_trans(cli, SMBtrans2, &data_len, &param_len,
- &rdata, &rparam)) {
- return False;
- }
-
- if (!rdata || data_len < 22) {
- return False;
- }
-
- if (c_time) {
- *c_time = make_unix_date2(rdata+0);
- }
- if (a_time) {
- *a_time = make_unix_date2(rdata+4);
- }
- if (m_time) {
- *m_time = make_unix_date2(rdata+8);
- }
- if (size) {
- *size = IVAL(rdata, 12);
- }
-
- if (rdata) free(rdata);
- if (rparam) free(rparam);
- return True;
-}
-
-/****************************************************************************
-send a qpathinfo call with the SMB_QUERY_FILE_ALL_INFO info level
-****************************************************************************/
-BOOL cli_qpathinfo2(struct cli_state *cli, char *fname,
- time_t *c_time, time_t *a_time, time_t *m_time,
- time_t *w_time, uint32 *size)
-{
- int data_len = 0;
- int param_len = 0;
- uint16 setup = TRANSACT2_QPATHINFO;
- pstring param;
- char *rparam=NULL, *rdata=NULL;
-
- param_len = strlen(fname) + 7;
-
- memset(param, 0, param_len);
- SSVAL(param, 0, SMB_QUERY_FILE_ALL_INFO);
- pstrcpy(&param[6], fname);
-
- if (!cli_send_trans(cli, SMBtrans2, NULL, -1, 0,
- NULL, param, &setup,
- data_len, param_len, 1,
- cli->max_xmit, 10, 0)) {
- return False;
- }
-
- if (!cli_receive_trans(cli, SMBtrans2, &data_len, &param_len,
- &rdata, &rparam)) {
- return False;
- }
-
- if (!rdata || data_len < 22) {
- return False;
- }
-
- if (c_time) {
- *c_time = interpret_long_date(rdata+0) - cli->serverzone;
- }
- if (a_time) {
- *a_time = interpret_long_date(rdata+8) - cli->serverzone;
- }
- if (m_time) {
- *m_time = interpret_long_date(rdata+16) - cli->serverzone;
- }
- if (w_time) {
- *w_time = interpret_long_date(rdata+24) - cli->serverzone;
- }
- if (size) {
- *size = IVAL(rdata, 40);
- }
-
- if (rdata) free(rdata);
- if (rparam) free(rparam);
- return True;
-}
-
-
-/****************************************************************************
-send a qfileinfo call
-****************************************************************************/
-BOOL cli_qfileinfo(struct cli_state *cli, int fnum,
- time_t *c_time, time_t *a_time, time_t *m_time, uint32 *size)
-{
- int data_len = 0;
- int param_len = 0;
- uint16 setup = TRANSACT2_QFILEINFO;
- pstring param;
- char *rparam=NULL, *rdata=NULL;
-
- param_len = 4;
-
- memset(param, 0, param_len);
- SSVAL(param, 0, fnum);
- SSVAL(param, 2, SMB_INFO_STANDARD);
-
- if (!cli_send_trans(cli, SMBtrans2, NULL, -1, 0,
- NULL, param, &setup,
- data_len, param_len, 1,
- cli->max_xmit, 2, 0)) {
- return False;
- }
-
- if (!cli_receive_trans(cli, SMBtrans2, &data_len, &param_len,
- &rdata, &rparam)) {
- return False;
- }
-
- if (!rdata || data_len < 22) {
- return False;
- }
-
- if (c_time) {
- *c_time = make_unix_date2(rdata+0);
- }
- if (a_time) {
- *a_time = make_unix_date2(rdata+4);
- }
- if (m_time) {
- *m_time = make_unix_date2(rdata+8);
- }
- if (size) {
- *size = IVAL(rdata, 12);
- }
-
- if (rdata) free(rdata);
- if (rparam) free(rparam);
- return True;
-}
-
/****************************************************************************
send a negprot command
@@ -1237,7 +515,7 @@ BOOL cli_negprot(struct cli_state *cli)
}
CVAL(cli->outbuf,smb_com) = SMBnegprot;
- cli_setup_packet(cli);
+ cli_setup_pkt(cli);
CVAL(smb_buf(cli->outbuf),0) = 2;
@@ -1255,7 +533,19 @@ BOOL cli_negprot(struct cli_state *cli)
cli->protocol = prots[SVAL(cli->inbuf,smb_vwv0)].prot;
- if (cli->protocol >= PROTOCOL_NT1) {
+ if (cli->protocol < PROTOCOL_NT1) {
+ cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
+ cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
+ cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
+ cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60;
+ /* this time is converted to GMT by make_unix_date */
+ cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
+ if (cli->protocol >= PROTOCOL_COREPLUS) {
+ cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
+ cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
+ }
+ memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
+ } else {
/* NT protocol */
cli->sec_mode = CVAL(cli->inbuf,smb_vwv1);
cli->max_xmit = IVAL(cli->inbuf,smb_vwv3+1);
@@ -1267,20 +557,6 @@ BOOL cli_negprot(struct cli_state *cli)
if (IVAL(cli->inbuf,smb_vwv9+1) & 1)
cli->readbraw_supported =
cli->writebraw_supported = True;
- } else if (cli->protocol >= PROTOCOL_LANMAN1) {
- cli->sec_mode = SVAL(cli->inbuf,smb_vwv1);
- cli->max_xmit = SVAL(cli->inbuf,smb_vwv2);
- cli->sesskey = IVAL(cli->inbuf,smb_vwv6);
- cli->serverzone = SVALS(cli->inbuf,smb_vwv10)*60;
- /* this time is converted to GMT by make_unix_date */
- cli->servertime = make_unix_date(cli->inbuf+smb_vwv8);
- cli->readbraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x1) != 0);
- cli->writebraw_supported = ((SVAL(cli->inbuf,smb_vwv5) & 0x2) != 0);
- memcpy(cli->cryptkey,smb_buf(cli->inbuf),8);
- } else {
- /* the old core protocol */
- cli->sec_mode = 0;
- cli->serverzone = TimeDiff(time(NULL));
}
return True;
@@ -1397,38 +673,3 @@ void cli_shutdown(struct cli_state *cli)
if (cli->fd != -1) close(cli->fd);
memset(cli, 0, sizeof(*cli));
}
-
-/****************************************************************************
- return a description of the error
-****************************************************************************/
-char *cli_errstr(struct cli_state *cli)
-{
- return smb_errstr(cli->inbuf);
-}
-
-/****************************************************************************
- return error codes for the last packet
-****************************************************************************/
-void cli_error(struct cli_state *cli, int *eclass, int *num)
-{
- *eclass = CVAL(cli->inbuf,smb_rcls);
- *num = SVAL(cli->inbuf,smb_err);
-}
-
-/****************************************************************************
-set socket options on a open connection
-****************************************************************************/
-void cli_sockopt(struct cli_state *cli, char *options)
-{
- set_socket_options(cli->fd, options);
-}
-
-/****************************************************************************
-set the PID to use for smb messages. Return the old pid.
-****************************************************************************/
-int cli_setpid(struct cli_state *cli, int pid)
-{
- int ret = cli->pid;
- cli->pid = pid;
- return ret;
-}
diff --git a/source/libsmb/credentials.c b/source/libsmb/credentials.c
deleted file mode 100644
index b06ca6ffc6d..00000000000
--- a/source/libsmb/credentials.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- code to manipulate domain credentials
- Copyright (C) Andrew Tridgell 1997
-
- 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.
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-
-
-/****************************************************************************
-represent a credential as a string
-****************************************************************************/
-char *credstr(uchar *cred)
-{
- static fstring buf;
- sprintf(buf,"%02X%02X%02X%02X%02X%02X%02X%02X",
- cred[0], cred[1], cred[2], cred[3],
- cred[4], cred[5], cred[6], cred[7]);
- return buf;
-}
-
-
-/****************************************************************************
- setup the session key.
-Input: 8 byte challenge block
- 8 byte server challenge block
- 16 byte md4 encrypted password
-Output:
- 8 byte session key
-****************************************************************************/
-void cred_session_key(DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal, char *pass,
- uchar session_key[8])
-{
- uint32 sum[2];
- unsigned char sum2[8];
-
- sum[0] = IVAL(clnt_chal->data, 0) + IVAL(srv_chal->data, 0);
- sum[1] = IVAL(clnt_chal->data, 4) + IVAL(srv_chal->data, 4);
-
- SIVAL(sum2,0,sum[0]);
- SIVAL(sum2,4,sum[1]);
-
- cred_hash1(session_key, sum2,(unsigned char *)pass);
-
- /* debug output */
- DEBUG(4,("cred_session_key\n"));
-
- DEBUG(5,(" clnt_chal: %s\n", credstr(clnt_chal->data)));
- DEBUG(5,(" srv_chal : %s\n", credstr(srv_chal->data)));
- DEBUG(5,(" clnt+srv : %s\n", credstr(sum2)));
- DEBUG(5,(" sess_key : %s\n", credstr(session_key)));
-}
-
-
-/****************************************************************************
-create a credential
-
-Input:
- 8 byte sesssion key
- 8 byte stored credential
- 4 byte timestamp
-
-Output:
- 8 byte credential
-****************************************************************************/
-void cred_create(uchar session_key[8], DOM_CHAL *stor_cred, UTIME timestamp,
- DOM_CHAL *cred)
-{
- DOM_CHAL time_cred;
-
- SIVAL(time_cred.data, 0, IVAL(stor_cred->data, 0) + timestamp.time);
- SIVAL(time_cred.data, 4, IVAL(stor_cred->data, 4));
-
- cred_hash2(cred->data, time_cred.data, session_key);
-
- /* debug output*/
- DEBUG(4,("cred_create\n"));
-
- DEBUG(5,(" sess_key : %s\n", credstr(session_key)));
- DEBUG(5,(" stor_cred: %s\n", credstr(stor_cred->data)));
- DEBUG(5,(" timestamp: %lx\n" , timestamp.time));
- DEBUG(5,(" timecred : %s\n", credstr(time_cred.data)));
- DEBUG(5,(" calc_cred: %s\n", credstr(cred->data)));
-}
-
-
-/****************************************************************************
- check a supplied credential
-
-Input:
- 8 byte received credential
- 8 byte sesssion key
- 8 byte stored credential
- 4 byte timestamp
-
-Output:
- returns 1 if computed credential matches received credential
- returns 0 otherwise
-****************************************************************************/
-int cred_assert(DOM_CHAL *cred, uchar session_key[8], DOM_CHAL *stored_cred,
- UTIME timestamp)
-{
- DOM_CHAL cred2;
-
- cred_create(session_key, stored_cred, timestamp, &cred2);
-
- /* debug output*/
- DEBUG(4,("cred_assert\n"));
-
- DEBUG(5,(" challenge : %s\n", credstr(cred->data)));
- DEBUG(5,(" calculated: %s\n", credstr(cred2.data)));
-
- if (memcmp(cred->data, cred2.data, 8) == 0)
- {
- DEBUG(5, ("credentials check ok\n"));
- return True;
- }
- else
- {
- DEBUG(5, ("credentials check wrong\n"));
- return False;
- }
-}
-
-
-/****************************************************************************
- checks credentials; generates next step in the credential chain
-****************************************************************************/
-BOOL clnt_deal_with_creds(uchar sess_key[8],
- DOM_CRED *sto_clnt_cred, DOM_CRED *rcv_srv_cred)
-{
- UTIME new_clnt_time;
- uint32 new_cred;
-
- DEBUG(5,("clnt_deal_with_creds: %d\n", __LINE__));
-
- /* increment client time by one second */
- new_clnt_time.time = sto_clnt_cred->timestamp.time + 1;
-
- /* check that the received server credentials are valid */
- if (!cred_assert(&(rcv_srv_cred->challenge), sess_key,
- &(sto_clnt_cred->challenge), new_clnt_time))
- {
- return False;
- }
-
- /* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */
- new_cred = IVAL(sto_clnt_cred->challenge.data, 0);
- new_cred += new_clnt_time.time;
-
- /* store new seed in client credentials */
- SIVAL(sto_clnt_cred->challenge.data, 0, new_cred);
-
- DEBUG(5,(" new clnt cred: %s\n", credstr(sto_clnt_cred->challenge.data)));
- return True;
-}
-
-
-/****************************************************************************
- checks credentials; generates next step in the credential chain
-****************************************************************************/
-BOOL deal_with_creds(uchar sess_key[8],
- DOM_CRED *sto_clnt_cred,
- DOM_CRED *rcv_clnt_cred, DOM_CRED *rtn_srv_cred)
-{
- UTIME new_clnt_time;
- uint32 new_cred;
-
- DEBUG(5,("deal_with_creds: %d\n", __LINE__));
-
- /* check that the received client credentials are valid */
- if (!cred_assert(&(rcv_clnt_cred->challenge), sess_key,
- &(sto_clnt_cred->challenge), rcv_clnt_cred->timestamp))
- {
- return False;
- }
-
- /* increment client time by one second */
- new_clnt_time.time = rcv_clnt_cred->timestamp.time + 1;
-
- /* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */
- new_cred = IVAL(sto_clnt_cred->challenge.data, 0);
- new_cred += new_clnt_time.time;
-
- DEBUG(5,("deal_with_creds: new_cred[0]=%lx\n", new_cred));
-
- /* doesn't matter that server time is 0 */
- rtn_srv_cred->timestamp.time = 0;
-
- DEBUG(5,("deal_with_creds: new_clnt_time=%lx\n", new_clnt_time.time));
-
- /* create return credentials for inclusion in the reply */
- cred_create(sess_key, &(sto_clnt_cred->challenge), new_clnt_time,
- &(rtn_srv_cred->challenge));
-
- DEBUG(5,("deal_with_creds: clnt_cred=%s\n", credstr(sto_clnt_cred->challenge.data)));
-
- /* store new seed in client credentials */
- SIVAL(sto_clnt_cred->challenge.data, 0, new_cred);
-
- return True;
-}
-
-
diff --git a/source/libsmb/namequery.c b/source/libsmb/namequery.c
index 9915ee92a85..55f70be1222 100644
--- a/source/libsmb/namequery.c
+++ b/source/libsmb/namequery.c
@@ -189,25 +189,21 @@ BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
/****************************************************************************
do a netbios name query to find someones IP
- returns an array of IP addresses or NULL if none
- *count will be set to the number of addresses returned
****************************************************************************/
-struct in_addr *name_query(int fd,char *name,int name_type,
- BOOL bcast,BOOL recurse,
- struct in_addr to_ip, int *count, void (*fn)())
+BOOL name_query(int fd,char *name,int name_type,
+ BOOL bcast,BOOL recurse,
+ struct in_addr to_ip, struct in_addr *ip,void (*fn)())
{
BOOL found=False;
- int i, retries = 3;
+ int retries = 3;
int retry_time = bcast?250:2000;
struct timeval tval;
struct packet_struct p;
struct packet_struct *p2;
struct nmb_packet *nmb = &p.packet.nmb;
static int name_trn_id = 0;
- struct in_addr *ip_list = NULL;
bzero((char *)&p,sizeof(p));
- (*count) = 0;
if (!name_trn_id) name_trn_id = (time(NULL)%(unsigned)0x7FFF) +
(getpid()%(unsigned)100);
@@ -218,7 +214,7 @@ struct in_addr *name_query(int fd,char *name,int name_type,
nmb->header.response = False;
nmb->header.nm_flags.bcast = bcast;
nmb->header.nm_flags.recursion_available = False;
- nmb->header.nm_flags.recursion_desired = recurse;
+ nmb->header.nm_flags.recursion_desired = True;
nmb->header.nm_flags.trunc = False;
nmb->header.nm_flags.authoritative = False;
nmb->header.rcode = 0;
@@ -241,7 +237,7 @@ struct in_addr *name_query(int fd,char *name,int name_type,
GetTimeOfDay(&tval);
if (!send_packet(&p))
- return NULL;
+ return(False);
retries--;
@@ -252,7 +248,7 @@ struct in_addr *name_query(int fd,char *name,int name_type,
if (TvalDiff(&tval,&tval2) > retry_time) {
if (!retries) break;
if (!found && !send_packet(&p))
- return NULL;
+ return False;
GetTimeOfDay(&tval);
retries--;
}
@@ -260,7 +256,7 @@ struct in_addr *name_query(int fd,char *name,int name_type,
if ((p2=receive_packet(fd,NMB_PACKET,90)))
{
struct nmb_packet *nmb2 = &p2->packet.nmb;
- debug_nmb_packet(p2);
+ debug_nmb_packet(p2);
if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
!nmb2->header.response) {
@@ -283,17 +279,11 @@ struct in_addr *name_query(int fd,char *name,int name_type,
continue;
}
- ip_list = (struct in_addr *)Realloc(ip_list, sizeof(ip_list[0]) *
- ((*count)+nmb2->answers->rdlength/6));
- if (ip_list) {
- DEBUG(fn?3:2,("Got a positive name query response from %s ( ",
- inet_ntoa(p2->ip)));
- for (i=0;i<nmb2->answers->rdlength/6;i++) {
- putip((char *)&ip_list[(*count)],&nmb2->answers->rdata[2+i*6]);
- DEBUG(fn?3:2,("%s ",inet_ntoa(ip_list[(*count)])));
- (*count)++;
- }
- DEBUG(fn?3:2,(")\n"));
+ if (ip) {
+ putip((char *)ip,&nmb2->answers->rdata[2]);
+ DEBUG(fn?3:2,("Got a positive name query response from %s",
+ inet_ntoa(p2->ip)));
+ DEBUG(fn?3:2,(" (%s)\n",inet_ntoa(*ip)));
}
found=True; retries=0;
free_packet(p2);
@@ -301,5 +291,5 @@ struct in_addr *name_query(int fd,char *name,int name_type,
}
}
- return ip_list;
+ return(found);
}
diff --git a/source/libsmb/nmblib.c b/source/libsmb/nmblib.c
index 0335f01833b..95217b7eded 100644
--- a/source/libsmb/nmblib.c
+++ b/source/libsmb/nmblib.c
@@ -31,16 +31,14 @@ extern pstring myname;
extern struct in_addr ipzero;
static struct opcode_names {
- char *nmb_opcode_name;
- int opcode;
+ const char *nmb_opcode_name;
+ int opcode;
} nmb_header_opcode_names[] = {
- {"Query", 0 },
+ { "Query", 0 },
{"Registration", 5 },
{"Release", 6 },
{"WACK", 7 },
- {"Refresh", 8 },
- {"Refresh(altcode)", 9 },
- {"Multi-homed Registration", 15 },
+ {"refresh", 8 },
{0, -1 }
};
@@ -48,7 +46,7 @@ static struct opcode_names {
* Lookup a nmb opcode name.
****************************************************************************/
-char *lookup_opcode_name( int opcode )
+const char *lookup_opcode_name( int opcode )
{
struct opcode_names *op_namep;
int i;
@@ -207,7 +205,7 @@ static int parse_nmb_name(char *inbuf,int offset,int length, struct nmb_name *na
if (n==16) {
/* parse out the name type,
its always in the 16th byte of the name */
- name->name_type = ((unsigned char)name->name[15]) & 0xff;
+ name->name_type = name->name[15];
/* remove trailing spaces */
name->name[15] = 0;
@@ -251,7 +249,6 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
/* special case for wildcard name */
bzero(buf1,20);
buf1[0] = '*';
- buf1[15] = name->name_type;
} else {
sprintf(buf1,"%-15.15s%c",name->name,name->name_type);
}
@@ -295,9 +292,9 @@ char *namestr(struct nmb_name *n)
char *p = ret[i];
if (!n->scope[0])
- sprintf(p,"%s<%02x>",n->name,n->name_type);
+ sprintf(p,"%s(%x)",n->name,n->name_type);
else
- sprintf(p,"%s<%02x>.%s",n->name,n->name_type,n->scope);
+ sprintf(p,"%s(%x).%s",n->name,n->name_type,n->scope);
i = (i+1)%4;
return(p);
@@ -471,119 +468,9 @@ static BOOL parse_nmb(char *inbuf,int length,struct nmb_packet *nmb)
}
/*******************************************************************
- 'Copy constructor' for an nmb packet
- ******************************************************************/
-static struct packet_struct *copy_nmb_packet(struct packet_struct *packet)
-{
- struct nmb_packet *nmb;
- struct nmb_packet *copy_nmb;
- struct packet_struct *pkt_copy;
-
- if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)
- {
- DEBUG(0,("copy_nmb_packet: malloc fail.\n"));
- return NULL;
- }
-
- /* Structure copy of entire thing. */
-
- *pkt_copy = *packet;
-
- /* Ensure this copy is not locked. */
- pkt_copy->locked = False;
-
- /* Ensure this copy has no resource records. */
- nmb = &packet->packet.nmb;
- copy_nmb = &pkt_copy->packet.nmb;
-
- copy_nmb->answers = NULL;
- copy_nmb->nsrecs = NULL;
- copy_nmb->additional = NULL;
-
- /* Now copy any resource records. */
-
- if (nmb->answers)
- {
- if((copy_nmb->answers = (struct res_rec *)
- malloc(nmb->header.ancount * sizeof(struct res_rec))) == NULL)
- goto free_and_exit;
- memcpy((char *)copy_nmb->answers, (char *)nmb->answers,
- nmb->header.ancount * sizeof(struct res_rec));
- }
- if (nmb->nsrecs)
- {
- if((copy_nmb->nsrecs = (struct res_rec *)
- malloc(nmb->header.nscount * sizeof(struct res_rec))) == NULL)
- goto free_and_exit;
- memcpy((char *)copy_nmb->nsrecs, (char *)nmb->nsrecs,
- nmb->header.nscount * sizeof(struct res_rec));
- }
- if (nmb->additional)
- {
- if((copy_nmb->additional = (struct res_rec *)
- malloc(nmb->header.arcount * sizeof(struct res_rec))) == NULL)
- goto free_and_exit;
- memcpy((char *)copy_nmb->additional, (char *)nmb->additional,
- nmb->header.arcount * sizeof(struct res_rec));
- }
-
- return pkt_copy;
-
-free_and_exit:
-
- if(copy_nmb->answers)
- free((char *)copy_nmb->answers);
- if(copy_nmb->nsrecs)
- free((char *)copy_nmb->nsrecs);
- if(copy_nmb->additional)
- free((char *)copy_nmb->additional);
- free((char *)pkt_copy);
-
- DEBUG(0,("copy_nmb_packet: malloc fail in resource records.\n"));
- return NULL;
-}
-
-/*******************************************************************
- 'Copy constructor' for a dgram packet
- ******************************************************************/
-static struct packet_struct *copy_dgram_packet(struct packet_struct *packet)
-{
- struct packet_struct *pkt_copy;
-
- if(( pkt_copy = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)
- {
- DEBUG(0,("copy_dgram_packet: malloc fail.\n"));
- return NULL;
- }
-
- /* Structure copy of entire thing. */
-
- *pkt_copy = *packet;
-
- /* Ensure this copy is not locked. */
- pkt_copy->locked = False;
-
- /* There are no additional pointers in a dgram packet,
- we are finished. */
- return pkt_copy;
-}
-
-/*******************************************************************
- 'Copy constructor' for a generic packet
- ******************************************************************/
-struct packet_struct *copy_packet(struct packet_struct *packet)
-{
- if(packet->packet_type == NMB_PACKET)
- return copy_nmb_packet(packet);
- else if (packet->packet_type == DGRAM_PACKET)
- return copy_dgram_packet(packet);
- return NULL;
-}
-
-/*******************************************************************
free up any resources associated with an nmb packet
******************************************************************/
-static void free_nmb_packet(struct nmb_packet *nmb)
+void free_nmb_packet(struct nmb_packet *nmb)
{
if (nmb->answers) free(nmb->answers);
if (nmb->nsrecs) free(nmb->nsrecs);
@@ -591,24 +478,12 @@ static void free_nmb_packet(struct nmb_packet *nmb)
}
/*******************************************************************
- free up any resources associated with a dgram packet
- ******************************************************************/
-static void free_dgram_packet(struct dgram_packet *nmb)
-{
- /* We have nothing to do for a dgram packet. */
-}
-
-/*******************************************************************
free up any resources associated with a packet
******************************************************************/
void free_packet(struct packet_struct *packet)
{
- if (packet->locked)
- return;
if (packet->packet_type == NMB_PACKET)
free_nmb_packet(&packet->packet.nmb);
- else if (packet->packet_type == DGRAM_PACKET)
- free_dgram_packet(&packet->packet.dgram);
free(packet);
}
@@ -636,7 +511,6 @@ struct packet_struct *read_packet(int fd,enum packet_type packet_type)
packet->ip = lastip;
packet->port = lastport;
packet->fd = fd;
- packet->locked = False;
packet->timestamp = time(NULL);
packet->packet_type = packet_type;
switch (packet_type)
@@ -742,22 +616,12 @@ static int build_dgram(char *buf,struct packet_struct *p)
******************************************************************/
void make_nmb_name(struct nmb_name *n,char *name,int type,char *this_scope)
{
- StrnCpy(n->name,name,15);
+ fstrcpy(n->name,name);
strupper(n->name);
- n->name_type = (unsigned int)type & 0xFF;
- StrnCpy(n->scope,this_scope,63);
+ n->name_type = type;
+ fstrcpy(n->scope,this_scope);
}
-/*******************************************************************
- Compare two nmb names
- ******************************************************************/
-
-BOOL nmb_name_equal(struct nmb_name *n1, struct nmb_name *n2)
-{
- return ((n1->name_type == n2->name_type) &&
- strequal(n1->name ,n2->name ) &&
- strequal(n1->scope,n2->scope));
-}
/*******************************************************************
build a nmb packet ready for sending
@@ -830,7 +694,6 @@ BOOL send_packet(struct packet_struct *p)
{
case NMB_PACKET:
len = build_nmb(buf,p);
- debug_nmb_packet(p);
break;
case DGRAM_PACKET:
diff --git a/source/libsmb/nterr.c b/source/libsmb/nterr.c
deleted file mode 100644
index bda0f882a64..00000000000
--- a/source/libsmb/nterr.c
+++ /dev/null
@@ -1,514 +0,0 @@
-
-#include "nterr.h"
-
-static struct
-{
- char *nt_errstr;
- uint16 nt_errcode;
-
-} nt_errs[] =
-{
- { "NT_STATUS_UNSUCCESSFUL", NT_STATUS_UNSUCCESSFUL },
- { "NT_STATUS_NOT_IMPLEMENTED", NT_STATUS_NOT_IMPLEMENTED },
- { "NT_STATUS_INVALID_INFO_CLASS", NT_STATUS_INVALID_INFO_CLASS },
- { "NT_STATUS_INFO_LENGTH_MISMATCH", NT_STATUS_INFO_LENGTH_MISMATCH },
- { "NT_STATUS_ACCESS_VIOLATION", NT_STATUS_ACCESS_VIOLATION },
- { "NT_STATUS_IN_PAGE_ERROR", NT_STATUS_IN_PAGE_ERROR },
- { "NT_STATUS_PAGEFILE_QUOTA", NT_STATUS_PAGEFILE_QUOTA },
- { "NT_STATUS_INVALID_HANDLE", NT_STATUS_INVALID_HANDLE },
- { "NT_STATUS_BAD_INITIAL_STACK", NT_STATUS_BAD_INITIAL_STACK },
- { "NT_STATUS_BAD_INITIAL_PC", NT_STATUS_BAD_INITIAL_PC },
- { "NT_STATUS_INVALID_CID", NT_STATUS_INVALID_CID },
- { "NT_STATUS_TIMER_NOT_CANCELED", NT_STATUS_TIMER_NOT_CANCELED },
- { "NT_STATUS_INVALID_PARAMETER", NT_STATUS_INVALID_PARAMETER },
- { "NT_STATUS_NO_SUCH_DEVICE", NT_STATUS_NO_SUCH_DEVICE },
- { "NT_STATUS_NO_SUCH_FILE", NT_STATUS_NO_SUCH_FILE },
- { "NT_STATUS_INVALID_DEVICE_REQUEST", NT_STATUS_INVALID_DEVICE_REQUEST },
- { "NT_STATUS_END_OF_FILE", NT_STATUS_END_OF_FILE },
- { "NT_STATUS_WRONG_VOLUME", NT_STATUS_WRONG_VOLUME },
- { "NT_STATUS_NO_MEDIA_IN_DEVICE", NT_STATUS_NO_MEDIA_IN_DEVICE },
- { "NT_STATUS_UNRECOGNIZED_MEDIA", NT_STATUS_UNRECOGNIZED_MEDIA },
- { "NT_STATUS_NONEXISTENT_SECTOR", NT_STATUS_NONEXISTENT_SECTOR },
- { "NT_STATUS_MORE_PROCESSING_REQUIRED", NT_STATUS_MORE_PROCESSING_REQUIRED },
- { "NT_STATUS_NO_MEMORY", NT_STATUS_NO_MEMORY },
- { "NT_STATUS_CONFLICTING_ADDRESSES", NT_STATUS_CONFLICTING_ADDRESSES },
- { "NT_STATUS_NOT_MAPPED_VIEW", NT_STATUS_NOT_MAPPED_VIEW },
- { "NT_STATUS_UNABLE_TO_FREE_VM", NT_STATUS_UNABLE_TO_FREE_VM },
- { "NT_STATUS_UNABLE_TO_DELETE_SECTION", NT_STATUS_UNABLE_TO_DELETE_SECTION },
- { "NT_STATUS_INVALID_SYSTEM_SERVICE", NT_STATUS_INVALID_SYSTEM_SERVICE },
- { "NT_STATUS_ILLEGAL_INSTRUCTION", NT_STATUS_ILLEGAL_INSTRUCTION },
- { "NT_STATUS_INVALID_LOCK_SEQUENCE", NT_STATUS_INVALID_LOCK_SEQUENCE },
- { "NT_STATUS_INVALID_VIEW_SIZE", NT_STATUS_INVALID_VIEW_SIZE },
- { "NT_STATUS_INVALID_FILE_FOR_SECTION", NT_STATUS_INVALID_FILE_FOR_SECTION },
- { "NT_STATUS_ALREADY_COMMITTED", NT_STATUS_ALREADY_COMMITTED },
- { "NT_STATUS_ACCESS_DENIED", NT_STATUS_ACCESS_DENIED },
- { "NT_STATUS_BUFFER_TOO_SMALL", NT_STATUS_BUFFER_TOO_SMALL },
- { "NT_STATUS_OBJECT_TYPE_MISMATCH", NT_STATUS_OBJECT_TYPE_MISMATCH },
- { "NT_STATUS_NONCONTINUABLE_EXCEPTION", NT_STATUS_NONCONTINUABLE_EXCEPTION },
- { "NT_STATUS_INVALID_DISPOSITION", NT_STATUS_INVALID_DISPOSITION },
- { "NT_STATUS_UNWIND", NT_STATUS_UNWIND },
- { "NT_STATUS_BAD_STACK", NT_STATUS_BAD_STACK },
- { "NT_STATUS_INVALID_UNWIND_TARGET", NT_STATUS_INVALID_UNWIND_TARGET },
- { "NT_STATUS_NOT_LOCKED", NT_STATUS_NOT_LOCKED },
- { "NT_STATUS_PARITY_ERROR", NT_STATUS_PARITY_ERROR },
- { "NT_STATUS_UNABLE_TO_DECOMMIT_VM", NT_STATUS_UNABLE_TO_DECOMMIT_VM },
- { "NT_STATUS_NOT_COMMITTED", NT_STATUS_NOT_COMMITTED },
- { "NT_STATUS_INVALID_PORT_ATTRIBUTES", NT_STATUS_INVALID_PORT_ATTRIBUTES },
- { "NT_STATUS_PORT_MESSAGE_TOO_LONG", NT_STATUS_PORT_MESSAGE_TOO_LONG },
- { "NT_STATUS_INVALID_PARAMETER_MIX", NT_STATUS_INVALID_PARAMETER_MIX },
- { "NT_STATUS_INVALID_QUOTA_LOWER", NT_STATUS_INVALID_QUOTA_LOWER },
- { "NT_STATUS_DISK_CORRUPT_ERROR", NT_STATUS_DISK_CORRUPT_ERROR },
- { "NT_STATUS_OBJECT_NAME_INVALID", NT_STATUS_OBJECT_NAME_INVALID },
- { "NT_STATUS_OBJECT_NAME_NOT_FOUND", NT_STATUS_OBJECT_NAME_NOT_FOUND },
- { "NT_STATUS_OBJECT_NAME_COLLISION", NT_STATUS_OBJECT_NAME_COLLISION },
- { "NT_STATUS_HANDLE_NOT_WAITABLE", NT_STATUS_HANDLE_NOT_WAITABLE },
- { "NT_STATUS_PORT_DISCONNECTED", NT_STATUS_PORT_DISCONNECTED },
- { "NT_STATUS_DEVICE_ALREADY_ATTACHED", NT_STATUS_DEVICE_ALREADY_ATTACHED },
- { "NT_STATUS_OBJECT_PATH_INVALID", NT_STATUS_OBJECT_PATH_INVALID },
- { "NT_STATUS_OBJECT_PATH_NOT_FOUND", NT_STATUS_OBJECT_PATH_NOT_FOUND },
- { "NT_STATUS_OBJECT_PATH_SYNTAX_BAD", NT_STATUS_OBJECT_PATH_SYNTAX_BAD },
- { "NT_STATUS_DATA_OVERRUN", NT_STATUS_DATA_OVERRUN },
- { "NT_STATUS_DATA_LATE_ERROR", NT_STATUS_DATA_LATE_ERROR },
- { "NT_STATUS_DATA_ERROR", NT_STATUS_DATA_ERROR },
- { "NT_STATUS_CRC_ERROR", NT_STATUS_CRC_ERROR },
- { "NT_STATUS_SECTION_TOO_BIG", NT_STATUS_SECTION_TOO_BIG },
- { "NT_STATUS_PORT_CONNECTION_REFUSED", NT_STATUS_PORT_CONNECTION_REFUSED },
- { "NT_STATUS_INVALID_PORT_HANDLE", NT_STATUS_INVALID_PORT_HANDLE },
- { "NT_STATUS_SHARING_VIOLATION", NT_STATUS_SHARING_VIOLATION },
- { "NT_STATUS_QUOTA_EXCEEDED", NT_STATUS_QUOTA_EXCEEDED },
- { "NT_STATUS_INVALID_PAGE_PROTECTION", NT_STATUS_INVALID_PAGE_PROTECTION },
- { "NT_STATUS_MUTANT_NOT_OWNED", NT_STATUS_MUTANT_NOT_OWNED },
- { "NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED", NT_STATUS_SEMAPHORE_LIMIT_EXCEEDED },
- { "NT_STATUS_PORT_ALREADY_SET", NT_STATUS_PORT_ALREADY_SET },
- { "NT_STATUS_SECTION_NOT_IMAGE", NT_STATUS_SECTION_NOT_IMAGE },
- { "NT_STATUS_SUSPEND_COUNT_EXCEEDED", NT_STATUS_SUSPEND_COUNT_EXCEEDED },
- { "NT_STATUS_THREAD_IS_TERMINATING", NT_STATUS_THREAD_IS_TERMINATING },
- { "NT_STATUS_BAD_WORKING_SET_LIMIT", NT_STATUS_BAD_WORKING_SET_LIMIT },
- { "NT_STATUS_INCOMPATIBLE_FILE_MAP", NT_STATUS_INCOMPATIBLE_FILE_MAP },
- { "NT_STATUS_SECTION_PROTECTION", NT_STATUS_SECTION_PROTECTION },
- { "NT_STATUS_EAS_NOT_SUPPORTED", NT_STATUS_EAS_NOT_SUPPORTED },
- { "NT_STATUS_EA_TOO_LARGE", NT_STATUS_EA_TOO_LARGE },
- { "NT_STATUS_NONEXISTENT_EA_ENTRY", NT_STATUS_NONEXISTENT_EA_ENTRY },
- { "NT_STATUS_NO_EAS_ON_FILE", NT_STATUS_NO_EAS_ON_FILE },
- { "NT_STATUS_EA_CORRUPT_ERROR", NT_STATUS_EA_CORRUPT_ERROR },
- { "NT_STATUS_FILE_LOCK_CONFLICT", NT_STATUS_FILE_LOCK_CONFLICT },
- { "NT_STATUS_LOCK_NOT_GRANTED", NT_STATUS_LOCK_NOT_GRANTED },
- { "NT_STATUS_DELETE_PENDING", NT_STATUS_DELETE_PENDING },
- { "NT_STATUS_CTL_FILE_NOT_SUPPORTED", NT_STATUS_CTL_FILE_NOT_SUPPORTED },
- { "NT_STATUS_UNKNOWN_REVISION", NT_STATUS_UNKNOWN_REVISION },
- { "NT_STATUS_REVISION_MISMATCH", NT_STATUS_REVISION_MISMATCH },
- { "NT_STATUS_INVALID_OWNER", NT_STATUS_INVALID_OWNER },
- { "NT_STATUS_INVALID_PRIMARY_GROUP", NT_STATUS_INVALID_PRIMARY_GROUP },
- { "NT_STATUS_NO_IMPERSONATION_TOKEN", NT_STATUS_NO_IMPERSONATION_TOKEN },
- { "NT_STATUS_CANT_DISABLE_MANDATORY", NT_STATUS_CANT_DISABLE_MANDATORY },
- { "NT_STATUS_NO_LOGON_SERVERS", NT_STATUS_NO_LOGON_SERVERS },
- { "NT_STATUS_NO_SUCH_LOGON_SESSION", NT_STATUS_NO_SUCH_LOGON_SESSION },
- { "NT_STATUS_NO_SUCH_PRIVILEGE", NT_STATUS_NO_SUCH_PRIVILEGE },
- { "NT_STATUS_PRIVILEGE_NOT_HELD", NT_STATUS_PRIVILEGE_NOT_HELD },
- { "NT_STATUS_INVALID_ACCOUNT_NAME", NT_STATUS_INVALID_ACCOUNT_NAME },
- { "NT_STATUS_USER_EXISTS", NT_STATUS_USER_EXISTS },
- { "NT_STATUS_NO_SUCH_USER", NT_STATUS_NO_SUCH_USER },
- { "NT_STATUS_GROUP_EXISTS", NT_STATUS_GROUP_EXISTS },
- { "NT_STATUS_NO_SUCH_GROUP", NT_STATUS_NO_SUCH_GROUP },
- { "NT_STATUS_MEMBER_IN_GROUP", NT_STATUS_MEMBER_IN_GROUP },
- { "NT_STATUS_MEMBER_NOT_IN_GROUP", NT_STATUS_MEMBER_NOT_IN_GROUP },
- { "NT_STATUS_LAST_ADMIN", NT_STATUS_LAST_ADMIN },
- { "NT_STATUS_WRONG_PASSWORD", NT_STATUS_WRONG_PASSWORD },
- { "NT_STATUS_ILL_FORMED_PASSWORD", NT_STATUS_ILL_FORMED_PASSWORD },
- { "NT_STATUS_PASSWORD_RESTRICTION", NT_STATUS_PASSWORD_RESTRICTION },
- { "NT_STATUS_LOGON_FAILURE", NT_STATUS_LOGON_FAILURE },
- { "NT_STATUS_ACCOUNT_RESTRICTION", NT_STATUS_ACCOUNT_RESTRICTION },
- { "NT_STATUS_INVALID_LOGON_HOURS", NT_STATUS_INVALID_LOGON_HOURS },
- { "NT_STATUS_INVALID_WORKSTATION", NT_STATUS_INVALID_WORKSTATION },
- { "NT_STATUS_PASSWORD_EXPIRED", NT_STATUS_PASSWORD_EXPIRED },
- { "NT_STATUS_ACCOUNT_DISABLED", NT_STATUS_ACCOUNT_DISABLED },
- { "NT_STATUS_NONE_MAPPED", NT_STATUS_NONE_MAPPED },
- { "NT_STATUS_TOO_MANY_LUIDS_REQUESTED", NT_STATUS_TOO_MANY_LUIDS_REQUESTED },
- { "NT_STATUS_LUIDS_EXHAUSTED", NT_STATUS_LUIDS_EXHAUSTED },
- { "NT_STATUS_INVALID_SUB_AUTHORITY", NT_STATUS_INVALID_SUB_AUTHORITY },
- { "NT_STATUS_INVALID_ACL", NT_STATUS_INVALID_ACL },
- { "NT_STATUS_INVALID_SID", NT_STATUS_INVALID_SID },
- { "NT_STATUS_INVALID_SECURITY_DESCR", NT_STATUS_INVALID_SECURITY_DESCR },
- { "NT_STATUS_PROCEDURE_NOT_FOUND", NT_STATUS_PROCEDURE_NOT_FOUND },
- { "NT_STATUS_INVALID_IMAGE_FORMAT", NT_STATUS_INVALID_IMAGE_FORMAT },
- { "NT_STATUS_NO_TOKEN", NT_STATUS_NO_TOKEN },
- { "NT_STATUS_BAD_INHERITANCE_ACL", NT_STATUS_BAD_INHERITANCE_ACL },
- { "NT_STATUS_RANGE_NOT_LOCKED", NT_STATUS_RANGE_NOT_LOCKED },
- { "NT_STATUS_DISK_FULL", NT_STATUS_DISK_FULL },
- { "NT_STATUS_SERVER_DISABLED", NT_STATUS_SERVER_DISABLED },
- { "NT_STATUS_SERVER_NOT_DISABLED", NT_STATUS_SERVER_NOT_DISABLED },
- { "NT_STATUS_TOO_MANY_GUIDS_REQUESTED", NT_STATUS_TOO_MANY_GUIDS_REQUESTED },
- { "NT_STATUS_GUIDS_EXHAUSTED", NT_STATUS_GUIDS_EXHAUSTED },
- { "NT_STATUS_INVALID_ID_AUTHORITY", NT_STATUS_INVALID_ID_AUTHORITY },
- { "NT_STATUS_AGENTS_EXHAUSTED", NT_STATUS_AGENTS_EXHAUSTED },
- { "NT_STATUS_INVALID_VOLUME_LABEL", NT_STATUS_INVALID_VOLUME_LABEL },
- { "NT_STATUS_SECTION_NOT_EXTENDED", NT_STATUS_SECTION_NOT_EXTENDED },
- { "NT_STATUS_NOT_MAPPED_DATA", NT_STATUS_NOT_MAPPED_DATA },
- { "NT_STATUS_RESOURCE_DATA_NOT_FOUND", NT_STATUS_RESOURCE_DATA_NOT_FOUND },
- { "NT_STATUS_RESOURCE_TYPE_NOT_FOUND", NT_STATUS_RESOURCE_TYPE_NOT_FOUND },
- { "NT_STATUS_RESOURCE_NAME_NOT_FOUND", NT_STATUS_RESOURCE_NAME_NOT_FOUND },
- { "NT_STATUS_ARRAY_BOUNDS_EXCEEDED", NT_STATUS_ARRAY_BOUNDS_EXCEEDED },
- { "NT_STATUS_FLOAT_DENORMAL_OPERAND", NT_STATUS_FLOAT_DENORMAL_OPERAND },
- { "NT_STATUS_FLOAT_DIVIDE_BY_ZERO", NT_STATUS_FLOAT_DIVIDE_BY_ZERO },
- { "NT_STATUS_FLOAT_INEXACT_RESULT", NT_STATUS_FLOAT_INEXACT_RESULT },
- { "NT_STATUS_FLOAT_INVALID_OPERATION", NT_STATUS_FLOAT_INVALID_OPERATION },
- { "NT_STATUS_FLOAT_OVERFLOW", NT_STATUS_FLOAT_OVERFLOW },
- { "NT_STATUS_FLOAT_STACK_CHECK", NT_STATUS_FLOAT_STACK_CHECK },
- { "NT_STATUS_FLOAT_UNDERFLOW", NT_STATUS_FLOAT_UNDERFLOW },
- { "NT_STATUS_INTEGER_DIVIDE_BY_ZERO", NT_STATUS_INTEGER_DIVIDE_BY_ZERO },
- { "NT_STATUS_INTEGER_OVERFLOW", NT_STATUS_INTEGER_OVERFLOW },
- { "NT_STATUS_PRIVILEGED_INSTRUCTION", NT_STATUS_PRIVILEGED_INSTRUCTION },
- { "NT_STATUS_TOO_MANY_PAGING_FILES", NT_STATUS_TOO_MANY_PAGING_FILES },
- { "NT_STATUS_FILE_INVALID", NT_STATUS_FILE_INVALID },
- { "NT_STATUS_ALLOTTED_SPACE_EXCEEDED", NT_STATUS_ALLOTTED_SPACE_EXCEEDED },
- { "NT_STATUS_INSUFFICIENT_RESOURCES", NT_STATUS_INSUFFICIENT_RESOURCES },
- { "NT_STATUS_DFS_EXIT_PATH_FOUND", NT_STATUS_DFS_EXIT_PATH_FOUND },
- { "NT_STATUS_DEVICE_DATA_ERROR", NT_STATUS_DEVICE_DATA_ERROR },
- { "NT_STATUS_DEVICE_NOT_CONNECTED", NT_STATUS_DEVICE_NOT_CONNECTED },
- { "NT_STATUS_DEVICE_POWER_FAILURE", NT_STATUS_DEVICE_POWER_FAILURE },
- { "NT_STATUS_FREE_VM_NOT_AT_BASE", NT_STATUS_FREE_VM_NOT_AT_BASE },
- { "NT_STATUS_MEMORY_NOT_ALLOCATED", NT_STATUS_MEMORY_NOT_ALLOCATED },
- { "NT_STATUS_WORKING_SET_QUOTA", NT_STATUS_WORKING_SET_QUOTA },
- { "NT_STATUS_MEDIA_WRITE_PROTECTED", NT_STATUS_MEDIA_WRITE_PROTECTED },
- { "NT_STATUS_DEVICE_NOT_READY", NT_STATUS_DEVICE_NOT_READY },
- { "NT_STATUS_INVALID_GROUP_ATTRIBUTES", NT_STATUS_INVALID_GROUP_ATTRIBUTES },
- { "NT_STATUS_BAD_IMPERSONATION_LEVEL", NT_STATUS_BAD_IMPERSONATION_LEVEL },
- { "NT_STATUS_CANT_OPEN_ANONYMOUS", NT_STATUS_CANT_OPEN_ANONYMOUS },
- { "NT_STATUS_BAD_VALIDATION_CLASS", NT_STATUS_BAD_VALIDATION_CLASS },
- { "NT_STATUS_BAD_TOKEN_TYPE", NT_STATUS_BAD_TOKEN_TYPE },
- { "NT_STATUS_BAD_MASTER_BOOT_RECORD", NT_STATUS_BAD_MASTER_BOOT_RECORD },
- { "NT_STATUS_INSTRUCTION_MISALIGNMENT", NT_STATUS_INSTRUCTION_MISALIGNMENT },
- { "NT_STATUS_INSTANCE_NOT_AVAILABLE", NT_STATUS_INSTANCE_NOT_AVAILABLE },
- { "NT_STATUS_PIPE_NOT_AVAILABLE", NT_STATUS_PIPE_NOT_AVAILABLE },
- { "NT_STATUS_INVALID_PIPE_STATE", NT_STATUS_INVALID_PIPE_STATE },
- { "NT_STATUS_PIPE_BUSY", NT_STATUS_PIPE_BUSY },
- { "NT_STATUS_ILLEGAL_FUNCTION", NT_STATUS_ILLEGAL_FUNCTION },
- { "NT_STATUS_PIPE_DISCONNECTED", NT_STATUS_PIPE_DISCONNECTED },
- { "NT_STATUS_PIPE_CLOSING", NT_STATUS_PIPE_CLOSING },
- { "NT_STATUS_PIPE_CONNECTED", NT_STATUS_PIPE_CONNECTED },
- { "NT_STATUS_PIPE_LISTENING", NT_STATUS_PIPE_LISTENING },
- { "NT_STATUS_INVALID_READ_MODE", NT_STATUS_INVALID_READ_MODE },
- { "NT_STATUS_IO_TIMEOUT", NT_STATUS_IO_TIMEOUT },
- { "NT_STATUS_FILE_FORCED_CLOSED", NT_STATUS_FILE_FORCED_CLOSED },
- { "NT_STATUS_PROFILING_NOT_STARTED", NT_STATUS_PROFILING_NOT_STARTED },
- { "NT_STATUS_PROFILING_NOT_STOPPED", NT_STATUS_PROFILING_NOT_STOPPED },
- { "NT_STATUS_COULD_NOT_INTERPRET", NT_STATUS_COULD_NOT_INTERPRET },
- { "NT_STATUS_FILE_IS_A_DIRECTORY", NT_STATUS_FILE_IS_A_DIRECTORY },
- { "NT_STATUS_NOT_SUPPORTED", NT_STATUS_NOT_SUPPORTED },
- { "NT_STATUS_REMOTE_NOT_LISTENING", NT_STATUS_REMOTE_NOT_LISTENING },
- { "NT_STATUS_DUPLICATE_NAME", NT_STATUS_DUPLICATE_NAME },
- { "NT_STATUS_BAD_NETWORK_PATH", NT_STATUS_BAD_NETWORK_PATH },
- { "NT_STATUS_NETWORK_BUSY", NT_STATUS_NETWORK_BUSY },
- { "NT_STATUS_DEVICE_DOES_NOT_EXIST", NT_STATUS_DEVICE_DOES_NOT_EXIST },
- { "NT_STATUS_TOO_MANY_COMMANDS", NT_STATUS_TOO_MANY_COMMANDS },
- { "NT_STATUS_ADAPTER_HARDWARE_ERROR", NT_STATUS_ADAPTER_HARDWARE_ERROR },
- { "NT_STATUS_INVALID_NETWORK_RESPONSE", NT_STATUS_INVALID_NETWORK_RESPONSE },
- { "NT_STATUS_UNEXPECTED_NETWORK_ERROR", NT_STATUS_UNEXPECTED_NETWORK_ERROR },
- { "NT_STATUS_BAD_REMOTE_ADAPTER", NT_STATUS_BAD_REMOTE_ADAPTER },
- { "NT_STATUS_PRINT_QUEUE_FULL", NT_STATUS_PRINT_QUEUE_FULL },
- { "NT_STATUS_NO_SPOOL_SPACE", NT_STATUS_NO_SPOOL_SPACE },
- { "NT_STATUS_PRINT_CANCELLED", NT_STATUS_PRINT_CANCELLED },
- { "NT_STATUS_NETWORK_NAME_DELETED", NT_STATUS_NETWORK_NAME_DELETED },
- { "NT_STATUS_NETWORK_ACCESS_DENIED", NT_STATUS_NETWORK_ACCESS_DENIED },
- { "NT_STATUS_BAD_DEVICE_TYPE", NT_STATUS_BAD_DEVICE_TYPE },
- { "NT_STATUS_BAD_NETWORK_NAME", NT_STATUS_BAD_NETWORK_NAME },
- { "NT_STATUS_TOO_MANY_NAMES", NT_STATUS_TOO_MANY_NAMES },
- { "NT_STATUS_TOO_MANY_SESSIONS", NT_STATUS_TOO_MANY_SESSIONS },
- { "NT_STATUS_SHARING_PAUSED", NT_STATUS_SHARING_PAUSED },
- { "NT_STATUS_REQUEST_NOT_ACCEPTED", NT_STATUS_REQUEST_NOT_ACCEPTED },
- { "NT_STATUS_REDIRECTOR_PAUSED", NT_STATUS_REDIRECTOR_PAUSED },
- { "NT_STATUS_NET_WRITE_FAULT", NT_STATUS_NET_WRITE_FAULT },
- { "NT_STATUS_PROFILING_AT_LIMIT", NT_STATUS_PROFILING_AT_LIMIT },
- { "NT_STATUS_NOT_SAME_DEVICE", NT_STATUS_NOT_SAME_DEVICE },
- { "NT_STATUS_FILE_RENAMED", NT_STATUS_FILE_RENAMED },
- { "NT_STATUS_VIRTUAL_CIRCUIT_CLOSED", NT_STATUS_VIRTUAL_CIRCUIT_CLOSED },
- { "NT_STATUS_NO_SECURITY_ON_OBJECT", NT_STATUS_NO_SECURITY_ON_OBJECT },
- { "NT_STATUS_CANT_WAIT", NT_STATUS_CANT_WAIT },
- { "NT_STATUS_PIPE_EMPTY", NT_STATUS_PIPE_EMPTY },
- { "NT_STATUS_CANT_ACCESS_DOMAIN_INFO", NT_STATUS_CANT_ACCESS_DOMAIN_INFO },
- { "NT_STATUS_CANT_TERMINATE_SELF", NT_STATUS_CANT_TERMINATE_SELF },
- { "NT_STATUS_INVALID_SERVER_STATE", NT_STATUS_INVALID_SERVER_STATE },
- { "NT_STATUS_INVALID_DOMAIN_STATE", NT_STATUS_INVALID_DOMAIN_STATE },
- { "NT_STATUS_INVALID_DOMAIN_ROLE", NT_STATUS_INVALID_DOMAIN_ROLE },
- { "NT_STATUS_NO_SUCH_DOMAIN", NT_STATUS_NO_SUCH_DOMAIN },
- { "NT_STATUS_DOMAIN_EXISTS", NT_STATUS_DOMAIN_EXISTS },
- { "NT_STATUS_DOMAIN_LIMIT_EXCEEDED", NT_STATUS_DOMAIN_LIMIT_EXCEEDED },
- { "NT_STATUS_OPLOCK_NOT_GRANTED", NT_STATUS_OPLOCK_NOT_GRANTED },
- { "NT_STATUS_INVALID_OPLOCK_PROTOCOL", NT_STATUS_INVALID_OPLOCK_PROTOCOL },
- { "NT_STATUS_INTERNAL_DB_CORRUPTION", NT_STATUS_INTERNAL_DB_CORRUPTION },
- { "NT_STATUS_INTERNAL_ERROR", NT_STATUS_INTERNAL_ERROR },
- { "NT_STATUS_GENERIC_NOT_MAPPED", NT_STATUS_GENERIC_NOT_MAPPED },
- { "NT_STATUS_BAD_DESCRIPTOR_FORMAT", NT_STATUS_BAD_DESCRIPTOR_FORMAT },
- { "NT_STATUS_INVALID_USER_BUFFER", NT_STATUS_INVALID_USER_BUFFER },
- { "NT_STATUS_UNEXPECTED_IO_ERROR", NT_STATUS_UNEXPECTED_IO_ERROR },
- { "NT_STATUS_UNEXPECTED_MM_CREATE_ERR", NT_STATUS_UNEXPECTED_MM_CREATE_ERR },
- { "NT_STATUS_UNEXPECTED_MM_MAP_ERROR", NT_STATUS_UNEXPECTED_MM_MAP_ERROR },
- { "NT_STATUS_UNEXPECTED_MM_EXTEND_ERR", NT_STATUS_UNEXPECTED_MM_EXTEND_ERR },
- { "NT_STATUS_NOT_LOGON_PROCESS", NT_STATUS_NOT_LOGON_PROCESS },
- { "NT_STATUS_LOGON_SESSION_EXISTS", NT_STATUS_LOGON_SESSION_EXISTS },
- { "NT_STATUS_INVALID_PARAMETER_1", NT_STATUS_INVALID_PARAMETER_1 },
- { "NT_STATUS_INVALID_PARAMETER_2", NT_STATUS_INVALID_PARAMETER_2 },
- { "NT_STATUS_INVALID_PARAMETER_3", NT_STATUS_INVALID_PARAMETER_3 },
- { "NT_STATUS_INVALID_PARAMETER_4", NT_STATUS_INVALID_PARAMETER_4 },
- { "NT_STATUS_INVALID_PARAMETER_5", NT_STATUS_INVALID_PARAMETER_5 },
- { "NT_STATUS_INVALID_PARAMETER_6", NT_STATUS_INVALID_PARAMETER_6 },
- { "NT_STATUS_INVALID_PARAMETER_7", NT_STATUS_INVALID_PARAMETER_7 },
- { "NT_STATUS_INVALID_PARAMETER_8", NT_STATUS_INVALID_PARAMETER_8 },
- { "NT_STATUS_INVALID_PARAMETER_9", NT_STATUS_INVALID_PARAMETER_9 },
- { "NT_STATUS_INVALID_PARAMETER_10", NT_STATUS_INVALID_PARAMETER_10 },
- { "NT_STATUS_INVALID_PARAMETER_11", NT_STATUS_INVALID_PARAMETER_11 },
- { "NT_STATUS_INVALID_PARAMETER_12", NT_STATUS_INVALID_PARAMETER_12 },
- { "NT_STATUS_REDIRECTOR_NOT_STARTED", NT_STATUS_REDIRECTOR_NOT_STARTED },
- { "NT_STATUS_REDIRECTOR_STARTED", NT_STATUS_REDIRECTOR_STARTED },
- { "NT_STATUS_STACK_OVERFLOW", NT_STATUS_STACK_OVERFLOW },
- { "NT_STATUS_NO_SUCH_PACKAGE", NT_STATUS_NO_SUCH_PACKAGE },
- { "NT_STATUS_BAD_FUNCTION_TABLE", NT_STATUS_BAD_FUNCTION_TABLE },
- { "NT_STATUS_DIRECTORY_NOT_EMPTY", NT_STATUS_DIRECTORY_NOT_EMPTY },
- { "NT_STATUS_FILE_CORRUPT_ERROR", NT_STATUS_FILE_CORRUPT_ERROR },
- { "NT_STATUS_NOT_A_DIRECTORY", NT_STATUS_NOT_A_DIRECTORY },
- { "NT_STATUS_BAD_LOGON_SESSION_STATE", NT_STATUS_BAD_LOGON_SESSION_STATE },
- { "NT_STATUS_LOGON_SESSION_COLLISION", NT_STATUS_LOGON_SESSION_COLLISION },
- { "NT_STATUS_NAME_TOO_LONG", NT_STATUS_NAME_TOO_LONG },
- { "NT_STATUS_FILES_OPEN", NT_STATUS_FILES_OPEN },
- { "NT_STATUS_CONNECTION_IN_USE", NT_STATUS_CONNECTION_IN_USE },
- { "NT_STATUS_MESSAGE_NOT_FOUND", NT_STATUS_MESSAGE_NOT_FOUND },
- { "NT_STATUS_PROCESS_IS_TERMINATING", NT_STATUS_PROCESS_IS_TERMINATING },
- { "NT_STATUS_INVALID_LOGON_TYPE", NT_STATUS_INVALID_LOGON_TYPE },
- { "NT_STATUS_NO_GUID_TRANSLATION", NT_STATUS_NO_GUID_TRANSLATION },
- { "NT_STATUS_CANNOT_IMPERSONATE", NT_STATUS_CANNOT_IMPERSONATE },
- { "NT_STATUS_IMAGE_ALREADY_LOADED", NT_STATUS_IMAGE_ALREADY_LOADED },
- { "NT_STATUS_ABIOS_NOT_PRESENT", NT_STATUS_ABIOS_NOT_PRESENT },
- { "NT_STATUS_ABIOS_LID_NOT_EXIST", NT_STATUS_ABIOS_LID_NOT_EXIST },
- { "NT_STATUS_ABIOS_LID_ALREADY_OWNED", NT_STATUS_ABIOS_LID_ALREADY_OWNED },
- { "NT_STATUS_ABIOS_NOT_LID_OWNER", NT_STATUS_ABIOS_NOT_LID_OWNER },
- { "NT_STATUS_ABIOS_INVALID_COMMAND", NT_STATUS_ABIOS_INVALID_COMMAND },
- { "NT_STATUS_ABIOS_INVALID_LID", NT_STATUS_ABIOS_INVALID_LID },
- { "NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE", NT_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE },
- { "NT_STATUS_ABIOS_INVALID_SELECTOR", NT_STATUS_ABIOS_INVALID_SELECTOR },
- { "NT_STATUS_NO_LDT", NT_STATUS_NO_LDT },
- { "NT_STATUS_INVALID_LDT_SIZE", NT_STATUS_INVALID_LDT_SIZE },
- { "NT_STATUS_INVALID_LDT_OFFSET", NT_STATUS_INVALID_LDT_OFFSET },
- { "NT_STATUS_INVALID_LDT_DESCRIPTOR", NT_STATUS_INVALID_LDT_DESCRIPTOR },
- { "NT_STATUS_INVALID_IMAGE_NE_FORMAT", NT_STATUS_INVALID_IMAGE_NE_FORMAT },
- { "NT_STATUS_RXACT_INVALID_STATE", NT_STATUS_RXACT_INVALID_STATE },
- { "NT_STATUS_RXACT_COMMIT_FAILURE", NT_STATUS_RXACT_COMMIT_FAILURE },
- { "NT_STATUS_MAPPED_FILE_SIZE_ZERO", NT_STATUS_MAPPED_FILE_SIZE_ZERO },
- { "NT_STATUS_TOO_MANY_OPENED_FILES", NT_STATUS_TOO_MANY_OPENED_FILES },
- { "NT_STATUS_CANCELLED", NT_STATUS_CANCELLED },
- { "NT_STATUS_CANNOT_DELETE", NT_STATUS_CANNOT_DELETE },
- { "NT_STATUS_INVALID_COMPUTER_NAME", NT_STATUS_INVALID_COMPUTER_NAME },
- { "NT_STATUS_FILE_DELETED", NT_STATUS_FILE_DELETED },
- { "NT_STATUS_SPECIAL_ACCOUNT", NT_STATUS_SPECIAL_ACCOUNT },
- { "NT_STATUS_SPECIAL_GROUP", NT_STATUS_SPECIAL_GROUP },
- { "NT_STATUS_SPECIAL_USER", NT_STATUS_SPECIAL_USER },
- { "NT_STATUS_MEMBERS_PRIMARY_GROUP", NT_STATUS_MEMBERS_PRIMARY_GROUP },
- { "NT_STATUS_FILE_CLOSED", NT_STATUS_FILE_CLOSED },
- { "NT_STATUS_TOO_MANY_THREADS", NT_STATUS_TOO_MANY_THREADS },
- { "NT_STATUS_THREAD_NOT_IN_PROCESS", NT_STATUS_THREAD_NOT_IN_PROCESS },
- { "NT_STATUS_TOKEN_ALREADY_IN_USE", NT_STATUS_TOKEN_ALREADY_IN_USE },
- { "NT_STATUS_PAGEFILE_QUOTA_EXCEEDED", NT_STATUS_PAGEFILE_QUOTA_EXCEEDED },
- { "NT_STATUS_COMMITMENT_LIMIT", NT_STATUS_COMMITMENT_LIMIT },
- { "NT_STATUS_INVALID_IMAGE_LE_FORMAT", NT_STATUS_INVALID_IMAGE_LE_FORMAT },
- { "NT_STATUS_INVALID_IMAGE_NOT_MZ", NT_STATUS_INVALID_IMAGE_NOT_MZ },
- { "NT_STATUS_INVALID_IMAGE_PROTECT", NT_STATUS_INVALID_IMAGE_PROTECT },
- { "NT_STATUS_INVALID_IMAGE_WIN_16", NT_STATUS_INVALID_IMAGE_WIN_16 },
- { "NT_STATUS_LOGON_SERVER_CONFLICT", NT_STATUS_LOGON_SERVER_CONFLICT },
- { "NT_STATUS_TIME_DIFFERENCE_AT_DC", NT_STATUS_TIME_DIFFERENCE_AT_DC },
- { "NT_STATUS_SYNCHRONIZATION_REQUIRED", NT_STATUS_SYNCHRONIZATION_REQUIRED },
- { "NT_STATUS_DLL_NOT_FOUND", NT_STATUS_DLL_NOT_FOUND },
- { "NT_STATUS_OPEN_FAILED", NT_STATUS_OPEN_FAILED },
- { "NT_STATUS_IO_PRIVILEGE_FAILED", NT_STATUS_IO_PRIVILEGE_FAILED },
- { "NT_STATUS_ORDINAL_NOT_FOUND", NT_STATUS_ORDINAL_NOT_FOUND },
- { "NT_STATUS_ENTRYPOINT_NOT_FOUND", NT_STATUS_ENTRYPOINT_NOT_FOUND },
- { "NT_STATUS_CONTROL_C_EXIT", NT_STATUS_CONTROL_C_EXIT },
- { "NT_STATUS_LOCAL_DISCONNECT", NT_STATUS_LOCAL_DISCONNECT },
- { "NT_STATUS_REMOTE_DISCONNECT", NT_STATUS_REMOTE_DISCONNECT },
- { "NT_STATUS_REMOTE_RESOURCES", NT_STATUS_REMOTE_RESOURCES },
- { "NT_STATUS_LINK_FAILED", NT_STATUS_LINK_FAILED },
- { "NT_STATUS_LINK_TIMEOUT", NT_STATUS_LINK_TIMEOUT },
- { "NT_STATUS_INVALID_CONNECTION", NT_STATUS_INVALID_CONNECTION },
- { "NT_STATUS_INVALID_ADDRESS", NT_STATUS_INVALID_ADDRESS },
- { "NT_STATUS_DLL_INIT_FAILED", NT_STATUS_DLL_INIT_FAILED },
- { "NT_STATUS_MISSING_SYSTEMFILE", NT_STATUS_MISSING_SYSTEMFILE },
- { "NT_STATUS_UNHANDLED_EXCEPTION", NT_STATUS_UNHANDLED_EXCEPTION },
- { "NT_STATUS_APP_INIT_FAILURE", NT_STATUS_APP_INIT_FAILURE },
- { "NT_STATUS_PAGEFILE_CREATE_FAILED", NT_STATUS_PAGEFILE_CREATE_FAILED },
- { "NT_STATUS_NO_PAGEFILE", NT_STATUS_NO_PAGEFILE },
- { "NT_STATUS_INVALID_LEVEL", NT_STATUS_INVALID_LEVEL },
- { "NT_STATUS_WRONG_PASSWORD_CORE", NT_STATUS_WRONG_PASSWORD_CORE },
- { "NT_STATUS_ILLEGAL_FLOAT_CONTEXT", NT_STATUS_ILLEGAL_FLOAT_CONTEXT },
- { "NT_STATUS_PIPE_BROKEN", NT_STATUS_PIPE_BROKEN },
- { "NT_STATUS_REGISTRY_CORRUPT", NT_STATUS_REGISTRY_CORRUPT },
- { "NT_STATUS_REGISTRY_IO_FAILED", NT_STATUS_REGISTRY_IO_FAILED },
- { "NT_STATUS_NO_EVENT_PAIR", NT_STATUS_NO_EVENT_PAIR },
- { "NT_STATUS_UNRECOGNIZED_VOLUME", NT_STATUS_UNRECOGNIZED_VOLUME },
- { "NT_STATUS_SERIAL_NO_DEVICE_INITED", NT_STATUS_SERIAL_NO_DEVICE_INITED },
- { "NT_STATUS_NO_SUCH_ALIAS", NT_STATUS_NO_SUCH_ALIAS },
- { "NT_STATUS_MEMBER_NOT_IN_ALIAS", NT_STATUS_MEMBER_NOT_IN_ALIAS },
- { "NT_STATUS_MEMBER_IN_ALIAS", NT_STATUS_MEMBER_IN_ALIAS },
- { "NT_STATUS_ALIAS_EXISTS", NT_STATUS_ALIAS_EXISTS },
- { "NT_STATUS_LOGON_NOT_GRANTED", NT_STATUS_LOGON_NOT_GRANTED },
- { "NT_STATUS_TOO_MANY_SECRETS", NT_STATUS_TOO_MANY_SECRETS },
- { "NT_STATUS_SECRET_TOO_LONG", NT_STATUS_SECRET_TOO_LONG },
- { "NT_STATUS_INTERNAL_DB_ERROR", NT_STATUS_INTERNAL_DB_ERROR },
- { "NT_STATUS_FULLSCREEN_MODE", NT_STATUS_FULLSCREEN_MODE },
- { "NT_STATUS_TOO_MANY_CONTEXT_IDS", NT_STATUS_TOO_MANY_CONTEXT_IDS },
- { "NT_STATUS_LOGON_TYPE_NOT_GRANTED", NT_STATUS_LOGON_TYPE_NOT_GRANTED },
- { "NT_STATUS_NOT_REGISTRY_FILE", NT_STATUS_NOT_REGISTRY_FILE },
- { "NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED", NT_STATUS_NT_CROSS_ENCRYPTION_REQUIRED },
- { "NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR", NT_STATUS_DOMAIN_CTRLR_CONFIG_ERROR },
- { "NT_STATUS_FT_MISSING_MEMBER", NT_STATUS_FT_MISSING_MEMBER },
- { "NT_STATUS_ILL_FORMED_SERVICE_ENTRY", NT_STATUS_ILL_FORMED_SERVICE_ENTRY },
- { "NT_STATUS_ILLEGAL_CHARACTER", NT_STATUS_ILLEGAL_CHARACTER },
- { "NT_STATUS_UNMAPPABLE_CHARACTER", NT_STATUS_UNMAPPABLE_CHARACTER },
- { "NT_STATUS_UNDEFINED_CHARACTER", NT_STATUS_UNDEFINED_CHARACTER },
- { "NT_STATUS_FLOPPY_VOLUME", NT_STATUS_FLOPPY_VOLUME },
- { "NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND", NT_STATUS_FLOPPY_ID_MARK_NOT_FOUND },
- { "NT_STATUS_FLOPPY_WRONG_CYLINDER", NT_STATUS_FLOPPY_WRONG_CYLINDER },
- { "NT_STATUS_FLOPPY_UNKNOWN_ERROR", NT_STATUS_FLOPPY_UNKNOWN_ERROR },
- { "NT_STATUS_FLOPPY_BAD_REGISTERS", NT_STATUS_FLOPPY_BAD_REGISTERS },
- { "NT_STATUS_DISK_RECALIBRATE_FAILED", NT_STATUS_DISK_RECALIBRATE_FAILED },
- { "NT_STATUS_DISK_OPERATION_FAILED", NT_STATUS_DISK_OPERATION_FAILED },
- { "NT_STATUS_DISK_RESET_FAILED", NT_STATUS_DISK_RESET_FAILED },
- { "NT_STATUS_SHARED_IRQ_BUSY", NT_STATUS_SHARED_IRQ_BUSY },
- { "NT_STATUS_FT_ORPHANING", NT_STATUS_FT_ORPHANING },
- { "NT_STATUS_PARTITION_FAILURE", NT_STATUS_PARTITION_FAILURE },
- { "NT_STATUS_INVALID_BLOCK_LENGTH", NT_STATUS_INVALID_BLOCK_LENGTH },
- { "NT_STATUS_DEVICE_NOT_PARTITIONED", NT_STATUS_DEVICE_NOT_PARTITIONED },
- { "NT_STATUS_UNABLE_TO_LOCK_MEDIA", NT_STATUS_UNABLE_TO_LOCK_MEDIA },
- { "NT_STATUS_UNABLE_TO_UNLOAD_MEDIA", NT_STATUS_UNABLE_TO_UNLOAD_MEDIA },
- { "NT_STATUS_EOM_OVERFLOW", NT_STATUS_EOM_OVERFLOW },
- { "NT_STATUS_NO_MEDIA", NT_STATUS_NO_MEDIA },
- { "NT_STATUS_NO_SUCH_MEMBER", NT_STATUS_NO_SUCH_MEMBER },
- { "NT_STATUS_INVALID_MEMBER", NT_STATUS_INVALID_MEMBER },
- { "NT_STATUS_KEY_DELETED", NT_STATUS_KEY_DELETED },
- { "NT_STATUS_NO_LOG_SPACE", NT_STATUS_NO_LOG_SPACE },
- { "NT_STATUS_TOO_MANY_SIDS", NT_STATUS_TOO_MANY_SIDS },
- { "NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED", NT_STATUS_LM_CROSS_ENCRYPTION_REQUIRED },
- { "NT_STATUS_KEY_HAS_CHILDREN", NT_STATUS_KEY_HAS_CHILDREN },
- { "NT_STATUS_CHILD_MUST_BE_VOLATILE", NT_STATUS_CHILD_MUST_BE_VOLATILE },
- { "NT_STATUS_DEVICE_CONFIGURATION_ERROR", NT_STATUS_DEVICE_CONFIGURATION_ERROR },
- { "NT_STATUS_DRIVER_INTERNAL_ERROR", NT_STATUS_DRIVER_INTERNAL_ERROR },
- { "NT_STATUS_INVALID_DEVICE_STATE", NT_STATUS_INVALID_DEVICE_STATE },
- { "NT_STATUS_IO_DEVICE_ERROR", NT_STATUS_IO_DEVICE_ERROR },
- { "NT_STATUS_DEVICE_PROTOCOL_ERROR", NT_STATUS_DEVICE_PROTOCOL_ERROR },
- { "NT_STATUS_BACKUP_CONTROLLER", NT_STATUS_BACKUP_CONTROLLER },
- { "NT_STATUS_LOG_FILE_FULL", NT_STATUS_LOG_FILE_FULL },
- { "NT_STATUS_TOO_LATE", NT_STATUS_TOO_LATE },
- { "NT_STATUS_NO_TRUST_LSA_SECRET", NT_STATUS_NO_TRUST_LSA_SECRET },
- { "NT_STATUS_NO_TRUST_SAM_ACCOUNT", NT_STATUS_NO_TRUST_SAM_ACCOUNT },
- { "NT_STATUS_TRUSTED_DOMAIN_FAILURE", NT_STATUS_TRUSTED_DOMAIN_FAILURE },
- { "NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE", NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE },
- { "NT_STATUS_EVENTLOG_FILE_CORRUPT", NT_STATUS_EVENTLOG_FILE_CORRUPT },
- { "NT_STATUS_EVENTLOG_CANT_START", NT_STATUS_EVENTLOG_CANT_START },
- { "NT_STATUS_TRUST_FAILURE", NT_STATUS_TRUST_FAILURE },
- { "NT_STATUS_MUTANT_LIMIT_EXCEEDED", NT_STATUS_MUTANT_LIMIT_EXCEEDED },
- { "NT_STATUS_NETLOGON_NOT_STARTED", NT_STATUS_NETLOGON_NOT_STARTED },
- { "NT_STATUS_ACCOUNT_EXPIRED", NT_STATUS_ACCOUNT_EXPIRED },
- { "NT_STATUS_POSSIBLE_DEADLOCK", NT_STATUS_POSSIBLE_DEADLOCK },
- { "NT_STATUS_NETWORK_CREDENTIAL_CONFLICT", NT_STATUS_NETWORK_CREDENTIAL_CONFLICT },
- { "NT_STATUS_REMOTE_SESSION_LIMIT", NT_STATUS_REMOTE_SESSION_LIMIT },
- { "NT_STATUS_EVENTLOG_FILE_CHANGED", NT_STATUS_EVENTLOG_FILE_CHANGED },
- { "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT", NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT },
- { "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT", NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT },
- { "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT", NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT },
- { "NT_STATUS_DOMAIN_TRUST_INCONSISTENT", NT_STATUS_DOMAIN_TRUST_INCONSISTENT },
- { "NT_STATUS_FS_DRIVER_REQUIRED", NT_STATUS_FS_DRIVER_REQUIRED },
- { "NT_STATUS_NO_USER_SESSION_KEY", NT_STATUS_NO_USER_SESSION_KEY },
- { "NT_STATUS_USER_SESSION_DELETED", NT_STATUS_USER_SESSION_DELETED },
- { "NT_STATUS_RESOURCE_LANG_NOT_FOUND", NT_STATUS_RESOURCE_LANG_NOT_FOUND },
- { "NT_STATUS_INSUFF_SERVER_RESOURCES", NT_STATUS_INSUFF_SERVER_RESOURCES },
- { "NT_STATUS_INVALID_BUFFER_SIZE", NT_STATUS_INVALID_BUFFER_SIZE },
- { "NT_STATUS_INVALID_ADDRESS_COMPONENT", NT_STATUS_INVALID_ADDRESS_COMPONENT },
- { "NT_STATUS_INVALID_ADDRESS_WILDCARD", NT_STATUS_INVALID_ADDRESS_WILDCARD },
- { "NT_STATUS_TOO_MANY_ADDRESSES", NT_STATUS_TOO_MANY_ADDRESSES },
- { "NT_STATUS_ADDRESS_ALREADY_EXISTS", NT_STATUS_ADDRESS_ALREADY_EXISTS },
- { "NT_STATUS_ADDRESS_CLOSED", NT_STATUS_ADDRESS_CLOSED },
- { "NT_STATUS_CONNECTION_DISCONNECTED", NT_STATUS_CONNECTION_DISCONNECTED },
- { "NT_STATUS_CONNECTION_RESET", NT_STATUS_CONNECTION_RESET },
- { "NT_STATUS_TOO_MANY_NODES", NT_STATUS_TOO_MANY_NODES },
- { "NT_STATUS_TRANSACTION_ABORTED", NT_STATUS_TRANSACTION_ABORTED },
- { "NT_STATUS_TRANSACTION_TIMED_OUT", NT_STATUS_TRANSACTION_TIMED_OUT },
- { "NT_STATUS_TRANSACTION_NO_RELEASE", NT_STATUS_TRANSACTION_NO_RELEASE },
- { "NT_STATUS_TRANSACTION_NO_MATCH", NT_STATUS_TRANSACTION_NO_MATCH },
- { "NT_STATUS_TRANSACTION_RESPONDED", NT_STATUS_TRANSACTION_RESPONDED },
- { "NT_STATUS_TRANSACTION_INVALID_ID", NT_STATUS_TRANSACTION_INVALID_ID },
- { "NT_STATUS_TRANSACTION_INVALID_TYPE", NT_STATUS_TRANSACTION_INVALID_TYPE },
- { "NT_STATUS_NOT_SERVER_SESSION", NT_STATUS_NOT_SERVER_SESSION },
- { "NT_STATUS_NOT_CLIENT_SESSION", NT_STATUS_NOT_CLIENT_SESSION },
- { "NT_STATUS_CANNOT_LOAD_REGISTRY_FILE", NT_STATUS_CANNOT_LOAD_REGISTRY_FILE },
- { "NT_STATUS_DEBUG_ATTACH_FAILED", NT_STATUS_DEBUG_ATTACH_FAILED },
- { "NT_STATUS_SYSTEM_PROCESS_TERMINATED", NT_STATUS_SYSTEM_PROCESS_TERMINATED },
- { "NT_STATUS_DATA_NOT_ACCEPTED", NT_STATUS_DATA_NOT_ACCEPTED },
- { "NT_STATUS_NO_BROWSER_SERVERS_FOUND", NT_STATUS_NO_BROWSER_SERVERS_FOUND },
- { "NT_STATUS_VDM_HARD_ERROR", NT_STATUS_VDM_HARD_ERROR },
- { "NT_STATUS_DRIVER_CANCEL_TIMEOUT", NT_STATUS_DRIVER_CANCEL_TIMEOUT },
- { "NT_STATUS_REPLY_MESSAGE_MISMATCH", NT_STATUS_REPLY_MESSAGE_MISMATCH },
- { "NT_STATUS_MAPPED_ALIGNMENT", NT_STATUS_MAPPED_ALIGNMENT },
- { "NT_STATUS_IMAGE_CHECKSUM_MISMATCH", NT_STATUS_IMAGE_CHECKSUM_MISMATCH },
- { "NT_STATUS_LOST_WRITEBEHIND_DATA", NT_STATUS_LOST_WRITEBEHIND_DATA },
- { "NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID", NT_STATUS_CLIENT_SERVER_PARAMETERS_INVALID },
- { "NT_STATUS_PASSWORD_MUST_CHANGE", NT_STATUS_PASSWORD_MUST_CHANGE },
- { "NT_STATUS_NOT_FOUND", NT_STATUS_NOT_FOUND },
- { "NT_STATUS_NOT_TINY_STREAM", NT_STATUS_NOT_TINY_STREAM },
- { "NT_STATUS_RECOVERY_FAILURE", NT_STATUS_RECOVERY_FAILURE },
- { "NT_STATUS_STACK_OVERFLOW_READ", NT_STATUS_STACK_OVERFLOW_READ },
- { "NT_STATUS_FAIL_CHECK", NT_STATUS_FAIL_CHECK },
- { "NT_STATUS_DUPLICATE_OBJECTID", NT_STATUS_DUPLICATE_OBJECTID },
- { "NT_STATUS_OBJECTID_EXISTS", NT_STATUS_OBJECTID_EXISTS },
- { "NT_STATUS_CONVERT_TO_LARGE", NT_STATUS_CONVERT_TO_LARGE },
- { "NT_STATUS_RETRY", NT_STATUS_RETRY },
- { "NT_STATUS_FOUND_OUT_OF_SCOPE", NT_STATUS_FOUND_OUT_OF_SCOPE },
- { "NT_STATUS_ALLOCATE_BUCKET", NT_STATUS_ALLOCATE_BUCKET },
- { "NT_STATUS_PROPSET_NOT_FOUND", NT_STATUS_PROPSET_NOT_FOUND },
- { "NT_STATUS_MARSHALL_OVERFLOW", NT_STATUS_MARSHALL_OVERFLOW },
- { "NT_STATUS_INVALID_VARIANT", NT_STATUS_INVALID_VARIANT },
- { "NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND", NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND },
- { "NT_STATUS_ACCOUNT_LOCKED_OUT", NT_STATUS_ACCOUNT_LOCKED_OUT },
- { "NT_STATUS_HANDLE_NOT_CLOSABLE", NT_STATUS_HANDLE_NOT_CLOSABLE },
- { "NT_STATUS_CONNECTION_REFUSED", NT_STATUS_CONNECTION_REFUSED },
- { "NT_STATUS_GRACEFUL_DISCONNECT", NT_STATUS_GRACEFUL_DISCONNECT },
- { "NT_STATUS_ADDRESS_ALREADY_ASSOCIATED", NT_STATUS_ADDRESS_ALREADY_ASSOCIATED },
- { "NT_STATUS_ADDRESS_NOT_ASSOCIATED", NT_STATUS_ADDRESS_NOT_ASSOCIATED },
- { "NT_STATUS_CONNECTION_INVALID", NT_STATUS_CONNECTION_INVALID },
- { "NT_STATUS_CONNECTION_ACTIVE", NT_STATUS_CONNECTION_ACTIVE },
- { "NT_STATUS_NETWORK_UNREACHABLE", NT_STATUS_NETWORK_UNREACHABLE },
- { "NT_STATUS_HOST_UNREACHABLE", NT_STATUS_HOST_UNREACHABLE },
- { "NT_STATUS_PROTOCOL_UNREACHABLE", NT_STATUS_PROTOCOL_UNREACHABLE },
- { "NT_STATUS_PORT_UNREACHABLE", NT_STATUS_PORT_UNREACHABLE },
- { "NT_STATUS_REQUEST_ABORTED", NT_STATUS_REQUEST_ABORTED },
- { "NT_STATUS_CONNECTION_ABORTED", NT_STATUS_CONNECTION_ABORTED },
- { "NT_STATUS_BAD_COMPRESSION_BUFFER", NT_STATUS_BAD_COMPRESSION_BUFFER },
- { "NT_STATUS_USER_MAPPED_FILE", NT_STATUS_USER_MAPPED_FILE },
- { "NT_STATUS_AUDIT_FAILED", NT_STATUS_AUDIT_FAILED },
- { "NT_STATUS_TIMER_RESOLUTION_NOT_SET", NT_STATUS_TIMER_RESOLUTION_NOT_SET },
- { "NT_STATUS_CONNECTION_COUNT_LIMIT", NT_STATUS_CONNECTION_COUNT_LIMIT },
- { "NT_STATUS_LOGIN_TIME_RESTRICTION", NT_STATUS_LOGIN_TIME_RESTRICTION },
- { "NT_STATUS_LOGIN_WKSTA_RESTRICTION", NT_STATUS_LOGIN_WKSTA_RESTRICTION },
- { "NT_STATUS_IMAGE_MP_UP_MISMATCH", NT_STATUS_IMAGE_MP_UP_MISMATCH },
- { "NT_STATUS_INSUFFICIENT_LOGON_INFO", NT_STATUS_INSUFFICIENT_LOGON_INFO },
- { "NT_STATUS_BAD_DLL_ENTRYPOINT", NT_STATUS_BAD_DLL_ENTRYPOINT },
- { "NT_STATUS_BAD_SERVICE_ENTRYPOINT", NT_STATUS_BAD_SERVICE_ENTRYPOINT },
- { "NT_STATUS_LPC_REPLY_LOST", NT_STATUS_LPC_REPLY_LOST },
- { "NT_STATUS_IP_ADDRESS_CONFLICT1", NT_STATUS_IP_ADDRESS_CONFLICT1 },
- { "NT_STATUS_IP_ADDRESS_CONFLICT2", NT_STATUS_IP_ADDRESS_CONFLICT2 },
- { "NT_STATUS_REGISTRY_QUOTA_LIMIT", NT_STATUS_REGISTRY_QUOTA_LIMIT },
- { "NT_STATUS_PATH_NOT_COVERED", NT_STATUS_PATH_NOT_COVERED },
- { "NT_STATUS_NO_CALLBACK_ACTIVE", NT_STATUS_NO_CALLBACK_ACTIVE },
- { "NT_STATUS_LICENSE_QUOTA_EXCEEDED", NT_STATUS_LICENSE_QUOTA_EXCEEDED },
- { "NT_STATUS_PWD_TOO_SHORT", NT_STATUS_PWD_TOO_SHORT },
- { "NT_STATUS_PWD_TOO_RECENT", NT_STATUS_PWD_TOO_RECENT },
- { "NT_STATUS_PWD_HISTORY_CONFLICT", NT_STATUS_PWD_HISTORY_CONFLICT },
- { "NT_STATUS_PLUGPLAY_NO_DEVICE", NT_STATUS_PLUGPLAY_NO_DEVICE },
- { "NT_STATUS_UNSUPPORTED_COMPRESSION", NT_STATUS_UNSUPPORTED_COMPRESSION },
- { "NT_STATUS_INVALID_HW_PROFILE", NT_STATUS_INVALID_HW_PROFILE },
- { "NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH", NT_STATUS_INVALID_PLUGPLAY_DEVICE_PATH },
- { "NT_STATUS_DRIVER_ORDINAL_NOT_FOUND", NT_STATUS_DRIVER_ORDINAL_NOT_FOUND },
- { "NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND", NT_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND },
- { "NT_STATUS_RESOURCE_NOT_OWNED", NT_STATUS_RESOURCE_NOT_OWNED },
- { "NT_STATUS_TOO_MANY_LINKS", NT_STATUS_TOO_MANY_LINKS },
- { "NT_STATUS_QUOTA_LIST_INCONSISTENT", NT_STATUS_QUOTA_LIST_INCONSISTENT },
- { "NT_STATUS_FILE_IS_OFFLINE", NT_STATUS_FILE_IS_OFFLINE },
- { NULL, 0 }
-};
-
diff --git a/source/libsmb/smbdes.c b/source/libsmb/smbdes.c
deleted file mode 100644
index e4f8280f9bc..00000000000
--- a/source/libsmb/smbdes.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
-
- a partial implementation of DES designed for use in the
- SMB authentication protocol
-
- Copyright (C) Andrew Tridgell 1997
-
- 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.
-*/
-
-
-/* NOTES:
-
- This code makes no attempt to be fast! In fact, it is a very
- slow implementation
-
- This code is NOT a complete DES implementation. It implements only
- the minimum necessary for SMB authentication, as used by all SMB
- products (including every copy of Microsoft Windows95 ever sold)
-
- In particular, it can only do a unchained forward DES pass. This
- means it is not possible to use this code for encryption/decryption
- of data, instead it is only useful as a "hash" algorithm.
-
- There is no entry point into this code that allows normal DES operation.
-
- I believe this means that this code does not come under ITAR
- regulations but this is NOT a legal opinion. If you are concerned
- about the applicability of ITAR regulations to this code then you
- should confirm it for yourself (and maybe let me know if you come
- up with a different answer to the one above)
-*/
-
-
-
-static int perm1[56] = {57, 49, 41, 33, 25, 17, 9,
- 1, 58, 50, 42, 34, 26, 18,
- 10, 2, 59, 51, 43, 35, 27,
- 19, 11, 3, 60, 52, 44, 36,
- 63, 55, 47, 39, 31, 23, 15,
- 7, 62, 54, 46, 38, 30, 22,
- 14, 6, 61, 53, 45, 37, 29,
- 21, 13, 5, 28, 20, 12, 4};
-
-static int perm2[48] = {14, 17, 11, 24, 1, 5,
- 3, 28, 15, 6, 21, 10,
- 23, 19, 12, 4, 26, 8,
- 16, 7, 27, 20, 13, 2,
- 41, 52, 31, 37, 47, 55,
- 30, 40, 51, 45, 33, 48,
- 44, 49, 39, 56, 34, 53,
- 46, 42, 50, 36, 29, 32};
-
-static int perm3[64] = {58, 50, 42, 34, 26, 18, 10, 2,
- 60, 52, 44, 36, 28, 20, 12, 4,
- 62, 54, 46, 38, 30, 22, 14, 6,
- 64, 56, 48, 40, 32, 24, 16, 8,
- 57, 49, 41, 33, 25, 17, 9, 1,
- 59, 51, 43, 35, 27, 19, 11, 3,
- 61, 53, 45, 37, 29, 21, 13, 5,
- 63, 55, 47, 39, 31, 23, 15, 7};
-
-static int perm4[48] = { 32, 1, 2, 3, 4, 5,
- 4, 5, 6, 7, 8, 9,
- 8, 9, 10, 11, 12, 13,
- 12, 13, 14, 15, 16, 17,
- 16, 17, 18, 19, 20, 21,
- 20, 21, 22, 23, 24, 25,
- 24, 25, 26, 27, 28, 29,
- 28, 29, 30, 31, 32, 1};
-
-static int perm5[32] = { 16, 7, 20, 21,
- 29, 12, 28, 17,
- 1, 15, 23, 26,
- 5, 18, 31, 10,
- 2, 8, 24, 14,
- 32, 27, 3, 9,
- 19, 13, 30, 6,
- 22, 11, 4, 25};
-
-
-static int perm6[64] ={ 40, 8, 48, 16, 56, 24, 64, 32,
- 39, 7, 47, 15, 55, 23, 63, 31,
- 38, 6, 46, 14, 54, 22, 62, 30,
- 37, 5, 45, 13, 53, 21, 61, 29,
- 36, 4, 44, 12, 52, 20, 60, 28,
- 35, 3, 43, 11, 51, 19, 59, 27,
- 34, 2, 42, 10, 50, 18, 58, 26,
- 33, 1, 41, 9, 49, 17, 57, 25};
-
-
-static int sc[16] = {1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1};
-
-static int sbox[8][4][16] = {
- {{14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7},
- {0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8},
- {4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0},
- {15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13}},
-
- {{15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10},
- {3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5},
- {0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15},
- {13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9}},
-
- {{10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8},
- {13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1},
- {13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7},
- {1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12}},
-
- {{7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15},
- {13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9},
- {10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4},
- {3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14}},
-
- {{2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9},
- {14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6},
- {4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14},
- {11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3}},
-
- {{12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11},
- {10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8},
- {9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6},
- {4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13}},
-
- {{4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1},
- {13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6},
- {1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2},
- {6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12}},
-
- {{13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7},
- {1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2},
- {7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8},
- {2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11}}};
-
-static void permute(char *out, char *in, int *p, int n)
-{
- int i;
- for (i=0;i<n;i++)
- out[i] = in[p[i]-1];
-}
-
-static void lshift(char *d, int count, int n)
-{
- char out[64];
- int i;
- for (i=0;i<n;i++)
- out[i] = d[(i+count)%n];
- for (i=0;i<n;i++)
- d[i] = out[i];
-}
-
-static void concat(char *out, char *in1, char *in2, int l1, int l2)
-{
- while (l1--)
- *out++ = *in1++;
- while (l2--)
- *out++ = *in2++;
-}
-
-static void xor(char *out, char *in1, char *in2, int n)
-{
- int i;
- for (i=0;i<n;i++)
- out[i] = in1[i] ^ in2[i];
-}
-
-static void dohash(char *out, char *in, char *key)
-{
- int i, j, k;
- char pk1[56];
- char c[28];
- char d[28];
- char cd[56];
- char ki[16][48];
- char pd1[64];
- char l[32], r[32];
- char rl[64];
-
- permute(pk1, key, perm1, 56);
-
- for (i=0;i<28;i++)
- c[i] = pk1[i];
- for (i=0;i<28;i++)
- d[i] = pk1[i+28];
-
- for (i=0;i<16;i++) {
- lshift(c, sc[i], 28);
- lshift(d, sc[i], 28);
-
- concat(cd, c, d, 28, 28);
- permute(ki[i], cd, perm2, 48);
- }
-
- permute(pd1, in, perm3, 64);
-
- for (j=0;j<32;j++) {
- l[j] = pd1[j];
- r[j] = pd1[j+32];
- }
-
- for (i=0;i<16;i++) {
- char er[48];
- char erk[48];
- char b[8][6];
- char cb[32];
- char pcb[32];
- char r2[32];
-
- permute(er, r, perm4, 48);
-
- xor(erk, er, ki[i], 48);
-
- for (j=0;j<8;j++)
- for (k=0;k<6;k++)
- b[j][k] = erk[j*6 + k];
-
- for (j=0;j<8;j++) {
- int m, n;
- m = (b[j][0]<<1) | b[j][5];
-
- n = (b[j][1]<<3) | (b[j][2]<<2) | (b[j][3]<<1) | b[j][4];
-
- for (k=0;k<4;k++)
- b[j][k] = (sbox[j][m][n] & (1<<(3-k)))?1:0;
- }
-
- for (j=0;j<8;j++)
- for (k=0;k<4;k++)
- cb[j*4+k] = b[j][k];
- permute(pcb, cb, perm5, 32);
-
- xor(r2, l, pcb, 32);
-
- for (j=0;j<32;j++)
- l[j] = r[j];
-
- for (j=0;j<32;j++)
- r[j] = r2[j];
- }
-
- concat(rl, r, l, 32, 32);
-
- permute(out, rl, perm6, 64);
-}
-
-static void str_to_key(unsigned char *str,unsigned char *key)
-{
- int i;
-
- key[0] = str[0]>>1;
- key[1] = ((str[0]&0x01)<<6) | (str[1]>>2);
- key[2] = ((str[1]&0x03)<<5) | (str[2]>>3);
- key[3] = ((str[2]&0x07)<<4) | (str[3]>>4);
- key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5);
- key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6);
- key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7);
- key[7] = str[6]&0x7F;
- for (i=0;i<8;i++) {
- key[i] = (key[i]<<1);
- }
-}
-
-
-static void smbhash(unsigned char *out, unsigned char *in, unsigned char *key)
-{
- int i;
- char outb[64];
- char inb[64];
- char keyb[64];
- unsigned char key2[8];
-
- str_to_key(key, key2);
-
- for (i=0;i<64;i++) {
- inb[i] = (in[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
- keyb[i] = (key2[i/8] & (1<<(7-(i%8)))) ? 1 : 0;
- outb[i] = 0;
- }
-
- dohash(outb, inb, keyb);
-
- for (i=0;i<8;i++) {
- out[i] = 0;
- }
-
- for (i=0;i<64;i++) {
- if (outb[i])
- out[i/8] |= (1<<(7-(i%8)));
- }
-}
-
-void E_P16(unsigned char *p14,unsigned char *p16)
-{
- unsigned char sp8[8] = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
- smbhash(p16, sp8, p14);
- smbhash(p16+8, sp8, p14+7);
-}
-
-void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24)
-{
- smbhash(p24, c8, p21);
- smbhash(p24+8, c8, p21+7);
- smbhash(p24+16, c8, p21+14);
-}
-
-void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key)
-{
- unsigned char buf[8];
-
- smbhash(buf, in, key);
- smbhash(out, buf, key+9);
-}
-
-void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key)
-{
- unsigned char buf[8];
- static unsigned char key2[8];
-
- smbhash(buf, in, key);
- key2[0] = key[7];
- smbhash(out, buf, key2);
-}
-
diff --git a/source/libsmb/smbencrypt.c b/source/libsmb/smbencrypt.c
index 38d414cf23d..8bb21cfed20 100644
--- a/source/libsmb/smbencrypt.c
+++ b/source/libsmb/smbencrypt.c
@@ -1,3 +1,4 @@
+#ifdef SMB_PASSWD
/*
Unix SMB/Netbios implementation.
Version 1.9.
@@ -21,11 +22,84 @@
*/
#include "includes.h"
+#include "des.h"
+#include "md4.h"
extern int DEBUGLEVEL;
#include "byteorder.h"
+void str_to_key(uchar *str,uchar *key)
+{
+ void des_set_odd_parity(des_cblock *);
+ int i;
+
+ key[0] = str[0]>>1;
+ key[1] = ((str[0]&0x01)<<6) | (str[1]>>2);
+ key[2] = ((str[1]&0x03)<<5) | (str[2]>>3);
+ key[3] = ((str[2]&0x07)<<4) | (str[3]>>4);
+ key[4] = ((str[3]&0x0F)<<3) | (str[4]>>5);
+ key[5] = ((str[4]&0x1F)<<2) | (str[5]>>6);
+ key[6] = ((str[5]&0x3F)<<1) | (str[6]>>7);
+ key[7] = str[6]&0x7F;
+ for (i=0;i<8;i++) {
+ key[i] = (key[i]<<1);
+ }
+ des_set_odd_parity((des_cblock *)key);
+}
+
+void D1(uchar *k, uchar *d, uchar *out)
+{
+ des_key_schedule ks;
+ des_cblock deskey;
+
+ str_to_key(k,(uchar *)deskey);
+#ifdef __FreeBSD__
+ des_set_key(&deskey,ks);
+#else /* __FreeBSD__ */
+ des_set_key((des_cblock *)deskey,ks);
+#endif /* __FreeBsd */
+ des_ecb_encrypt((des_cblock *)d,(des_cblock *)out, ks, DES_DECRYPT);
+}
+
+void E1(uchar *k, uchar *d, uchar *out)
+{
+ des_key_schedule ks;
+ des_cblock deskey;
+
+ str_to_key(k,(uchar *)deskey);
+#ifdef __FreeBSD__
+ des_set_key(&deskey,ks);
+#else /* __FreeBsd__ */
+ des_set_key((des_cblock *)deskey,ks);
+#endif /* __FreeBsd__ */
+ des_ecb_encrypt((des_cblock *)d,(des_cblock *)out, ks, DES_ENCRYPT);
+}
+
+void E_P16(uchar *p14,uchar *p16)
+{
+ uchar sp7[7];
+ /* the following constant makes us compatible with other
+ implementations. Note that publishing this constant does not reduce the
+ security of the encryption mechanism */
+ uchar sp8[] = {0xAA,0xD3,0xB4,0x35,0xB5,0x14,0x4,0xEE};
+ uchar x[8];
+
+ memset(sp7,'\0',7);
+
+ D1(sp7, sp8, x);
+ E1(p14, x, p16);
+ E1(p14+7, x, p16+8);
+}
+
+void E_P24(uchar *p21, uchar *c8, uchar *p24)
+{
+ E1(p21, c8, p24);
+ E1(p21+7, c8, p24+8);
+ E1(p21+14, c8, p24+16);
+}
+
+
/*
This implements the X/Open SMB password encryption
It takes a password, a 8 byte "crypt key" and puts 24 bytes of
@@ -81,20 +155,28 @@ static int _my_mbstowcs(int16 *dst, uchar *src, int len)
void E_md4hash(uchar *passwd, uchar *p16)
{
- int len;
+ int i, len;
int16 wpwd[129];
-
+ MDstruct MD;
+
/* Password cannot be longer than 128 characters */
len = strlen((char *)passwd);
if(len > 128)
len = 128;
/* Password must be converted to NT unicode */
- _my_mbstowcs(wpwd, passwd, len);
+ _my_mbstowcs( wpwd, passwd, len);
wpwd[len] = 0; /* Ensure string is null terminated */
/* Calculate length in bytes */
len = _my_wcslen(wpwd) * sizeof(int16);
-
- mdfour(p16, (unsigned char *)wpwd, len);
+
+ MDbegin(&MD);
+ for(i = 0; i + 64 <= len; i += 64)
+ MDupdate(&MD,wpwd + (i/2), 512);
+ MDupdate(&MD,wpwd + (i/2),(len-i)*8);
+ SIVAL(p16,0,MD.buffer[0]);
+ SIVAL(p16,4,MD.buffer[1]);
+ SIVAL(p16,8,MD.buffer[2]);
+ SIVAL(p16,12,MD.buffer[3]);
}
/* Does the NT MD4 hash then des encryption. */
@@ -109,27 +191,6 @@ void SMBNTencrypt(uchar *passwd, uchar *c8, uchar *p24)
E_P24(p21, c8, p24);
}
-/* Does both the NT and LM owfs of a user's password */
-
-void nt_lm_owf_gen(char *pwd, char *nt_p16, char *p16)
-{
- char passwd[130];
- StrnCpy(passwd, pwd, sizeof(passwd)-1);
-
- /* Calculate the MD4 hash (NT compatible) of the password */
- memset(nt_p16, '\0', 16);
- E_md4hash((uchar *)passwd, (uchar *)nt_p16);
-
- /* Mangle the passwords into Lanman format */
- passwd[14] = '\0';
- strupper(passwd);
-
- /* Calculate the SMB (lanman) hash functions of the password */
-
- memset(p16, '\0', 16);
- E_P16((uchar *) passwd, (uchar *)p16);
-
- /* clear out local copy of user's password (just being paranoid). */
- bzero(passwd, sizeof(passwd));
-}
-
+#else
+ void smbencrypt_dummy(void){}
+#endif
diff --git a/source/libsmb/smberr.c b/source/libsmb/smberr.c
deleted file mode 100644
index 5149568c045..00000000000
--- a/source/libsmb/smberr.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- Copyright (C) Andrew Tridgell 1997
-
- 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.
-*/
-
-#ifdef SYSLOG
-#undef SYSLOG
-#endif
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-/* error code stuff - put together by Merik Karman
- merik@blackadder.dsh.oz.au */
-
-typedef struct
-{
- char *name;
- int code;
- char *message;
-} err_code_struct;
-
-/* Dos Error Messages */
-err_code_struct dos_msgs[] = {
- {"ERRbadfunc",1,"Invalid function."},
- {"ERRbadfile",2,"File not found."},
- {"ERRbadpath",3,"Directory invalid."},
- {"ERRnofids",4,"No file descriptors available"},
- {"ERRnoaccess",5,"Access denied."},
- {"ERRbadfid",6,"Invalid file handle."},
- {"ERRbadmcb",7,"Memory control blocks destroyed."},
- {"ERRnomem",8,"Insufficient server memory to perform the requested function."},
- {"ERRbadmem",9,"Invalid memory block address."},
- {"ERRbadenv",10,"Invalid environment."},
- {"ERRbadformat",11,"Invalid format."},
- {"ERRbadaccess",12,"Invalid open mode."},
- {"ERRbaddata",13,"Invalid data."},
- {"ERR",14,"reserved."},
- {"ERRbaddrive",15,"Invalid drive specified."},
- {"ERRremcd",16,"A Delete Directory request attempted to remove the server's current directory."},
- {"ERRdiffdevice",17,"Not same device."},
- {"ERRnofiles",18,"A File Search command can find no more files matching the specified criteria."},
- {"ERRbadshare",32,"The sharing mode specified for an Open conflicts with existing FIDs on the file."},
- {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
- {"ERRnosuchshare", 67, "You specified an invalid share name"},
- {"ERRfilexists",80,"The file named in a Create Directory, Make New File or Link request already exists."},
- {"ERRbadpipe",230,"Pipe invalid."},
- {"ERRpipebusy",231,"All instances of the requested pipe are busy."},
- {"ERRpipeclosing",232,"Pipe close in progress."},
- {"ERRnotconnected",233,"No process on other end of pipe."},
- {"ERRmoredata",234,"There is more data to be returned."},
- {"ERRinvgroup",2455,"Invalid workgroup (try the -W option)"},
- {NULL,-1,NULL}};
-
-/* Server Error Messages */
-err_code_struct server_msgs[] = {
- {"ERRerror",1,"Non-specific error code."},
- {"ERRbadpw",2,"Bad password - name/password pair in a Tree Connect or Session Setup are invalid."},
- {"ERRbadtype",3,"reserved."},
- {"ERRaccess",4,"The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID."},
- {"ERRinvnid",5,"The tree ID (TID) specified in a command was invalid."},
- {"ERRinvnetname",6,"Invalid network name in tree connect."},
- {"ERRinvdevice",7,"Invalid device - printer request made to non-printer connection or non-printer request made to printer connection."},
- {"ERRqfull",49,"Print queue full (files) -- returned by open print file."},
- {"ERRqtoobig",50,"Print queue full -- no space."},
- {"ERRqeof",51,"EOF on print queue dump."},
- {"ERRinvpfid",52,"Invalid print file FID."},
- {"ERRsmbcmd",64,"The server did not recognize the command received."},
- {"ERRsrverror",65,"The server encountered an internal error, e.g., system file unavailable."},
- {"ERRfilespecs",67,"The file handle (FID) and pathname parameters contained an invalid combination of values."},
- {"ERRreserved",68,"reserved."},
- {"ERRbadpermits",69,"The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute."},
- {"ERRreserved",70,"reserved."},
- {"ERRsetattrmode",71,"The attribute mode in the Set File Attribute request is invalid."},
- {"ERRpaused",81,"Server is paused."},
- {"ERRmsgoff",82,"Not receiving messages."},
- {"ERRnoroom",83,"No room to buffer message."},
- {"ERRrmuns",87,"Too many remote user names."},
- {"ERRtimeout",88,"Operation timed out."},
- {"ERRnoresource",89,"No resources currently available for request."},
- {"ERRtoomanyuids",90,"Too many UIDs active on this session."},
- {"ERRbaduid",91,"The UID is not known as a valid ID on this session."},
- {"ERRusempx",250,"Temp unable to support Raw, use MPX mode."},
- {"ERRusestd",251,"Temp unable to support Raw, use standard read/write."},
- {"ERRcontmpx",252,"Continue in MPX mode."},
- {"ERRreserved",253,"reserved."},
- {"ERRreserved",254,"reserved."},
- {"ERRnosupport",0xFFFF,"Function not supported."},
- {NULL,-1,NULL}};
-
-/* Hard Error Messages */
-err_code_struct hard_msgs[] = {
- {"ERRnowrite",19,"Attempt to write on write-protected diskette."},
- {"ERRbadunit",20,"Unknown unit."},
- {"ERRnotready",21,"Drive not ready."},
- {"ERRbadcmd",22,"Unknown command."},
- {"ERRdata",23,"Data error (CRC)."},
- {"ERRbadreq",24,"Bad request structure length."},
- {"ERRseek",25 ,"Seek error."},
- {"ERRbadmedia",26,"Unknown media type."},
- {"ERRbadsector",27,"Sector not found."},
- {"ERRnopaper",28,"Printer out of paper."},
- {"ERRwrite",29,"Write fault."},
- {"ERRread",30,"Read fault."},
- {"ERRgeneral",31,"General failure."},
- {"ERRbadshare",32,"An open conflicts with an existing open."},
- {"ERRlock",33,"A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process."},
- {"ERRwrongdisk",34,"The wrong disk was found in a drive."},
- {"ERRFCBUnavail",35,"No FCBs are available to process request."},
- {"ERRsharebufexc",36,"A sharing buffer has been exceeded."},
- {NULL,-1,NULL}};
-
-
-struct
-{
- int code;
- char *class;
- err_code_struct *err_msgs;
-} err_classes[] = {
- {0,"SUCCESS",NULL},
- {0x01,"ERRDOS",dos_msgs},
- {0x02,"ERRSRV",server_msgs},
- {0x03,"ERRHRD",hard_msgs},
- {0x04,"ERRXOS",NULL},
- {0xE1,"ERRRMX1",NULL},
- {0xE2,"ERRRMX2",NULL},
- {0xE3,"ERRRMX3",NULL},
- {0xFF,"ERRCMD",NULL},
- {-1,NULL,NULL}};
-
-
-/****************************************************************************
-return a SMB error string from a SMB buffer
-****************************************************************************/
-char *smb_errstr(char *inbuf)
-{
- static pstring ret;
- int class = CVAL(inbuf,smb_rcls);
- int num = SVAL(inbuf,smb_err);
- int i,j;
-
- for (i=0;err_classes[i].class;i++)
- if (err_classes[i].code == class)
- {
- if (err_classes[i].err_msgs)
- {
- err_code_struct *err = err_classes[i].err_msgs;
- for (j=0;err[j].name;j++)
- if (num == err[j].code)
- {
- if (DEBUGLEVEL > 0)
- sprintf(ret,"%s - %s (%s)",err_classes[i].class,
- err[j].name,err[j].message);
- else
- sprintf(ret,"%s - %s",err_classes[i].class,err[j].name);
- return ret;
- }
- }
-
- sprintf(ret,"%s - %d",err_classes[i].class,num);
- return ret;
- }
-
- sprintf(ret,"Error: Unknown error (%d,%d)",class,num);
- return(ret);
-}
diff --git a/source/locking/locking.c b/source/locking/locking.c
index d654d038c81..559c7284b36 100644
--- a/source/locking/locking.c
+++ b/source/locking/locking.c
@@ -25,10 +25,6 @@
May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
locking to deal with multiple share modes per open file.
-
- September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
- support.
-
*/
#include "includes.h"
@@ -36,8 +32,6 @@ extern int DEBUGLEVEL;
extern connection_struct Connections[];
extern files_struct Files[];
-static struct share_ops *share_ops;
-
/****************************************************************************
utility function called to see if a file region is locked
****************************************************************************/
@@ -52,7 +46,7 @@ BOOL is_locked(int fnum,int cnum,uint32 count,uint32 offset)
return(False);
return(fcntl_lock(Files[fnum].fd_ptr->fd,F_GETLK,offset,count,
- (Files[fnum].can_write?F_WRLCK:F_RDLCK)));
+ (Files[fnum].can_write?F_WRLCK:F_RDLCK)));
}
@@ -74,7 +68,7 @@ BOOL do_lock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *ec
if (Files[fnum].can_lock && OPEN_FNUM(fnum) && (Files[fnum].cnum == cnum))
ok = fcntl_lock(Files[fnum].fd_ptr->fd,F_SETLK,offset,count,
- (Files[fnum].can_write?F_WRLCK:F_RDLCK));
+ (Files[fnum].can_write?F_WRLCK:F_RDLCK));
if (!ok) {
*eclass = ERRDOS;
@@ -106,106 +100,1202 @@ BOOL do_unlock(int fnum,int cnum,uint32 count,uint32 offset,int *eclass,uint32 *
return True; /* Did unlock */
}
-
-
-/****************************************************************************
- initialise the locking functions
-****************************************************************************/
-BOOL locking_init(int read_only)
-{
- if (share_ops) return True;
-
#ifdef FAST_SHARE_MODES
- share_ops = locking_shm_init(read_only);
- if (!share_ops) {
- DEBUG(0,("ERROR: Failed to initialise fast share modes - trying slow code\n"));
- }
- if (share_ops) return True;
-#endif
-
- share_ops = locking_slow_init(read_only);
- if (!share_ops) {
- DEBUG(0,("ERROR: Failed to initialise share modes!\n"));
- return False;
- }
-
- return True;
+/*******************************************************************
+ initialize the shared memory for share_mode management
+ ******************************************************************/
+BOOL start_share_mode_mgmt(void)
+{
+ pstring shmem_file_name;
+
+ pstrcpy(shmem_file_name,lp_lockdir());
+ if (!directory_exist(shmem_file_name,NULL))
+ mkdir(shmem_file_name,0755);
+ trim_string(shmem_file_name,"","/");
+ if (!*shmem_file_name) return(False);
+ strcat(shmem_file_name, "/SHARE_MEM_FILE");
+ return smb_shm_open(shmem_file_name, lp_shmem_size());
}
+
/*******************************************************************
- deinitialize the share_mode management
+ deinitialize the shared memory for share_mode management
******************************************************************/
-BOOL locking_end(void)
+BOOL stop_share_mode_mgmt(void)
{
- if (share_ops)
- return share_ops->stop_mgmt();
- return True;
+ return smb_shm_close();
}
-
/*******************************************************************
- lock a hash bucket entry
+ lock a hash bucket entry in shared memory for share_mode management
******************************************************************/
-BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok)
+BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
{
- return share_ops->lock_entry(cnum, dev, inode, ptok);
+ return smb_shm_lock_hash_entry(HASH_ENTRY(dev, inode));
}
/*******************************************************************
- unlock a hash bucket entry
+ unlock a hash bucket entry in shared memory for share_mode management
******************************************************************/
-BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token)
+BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
{
- return share_ops->unlock_entry(cnum, dev, inode, token);
+ return smb_shm_unlock_hash_entry(HASH_ENTRY(dev, inode));
}
/*******************************************************************
-get all share mode entries for a dev/inode pair.
+get all share mode entries in shared memory for a dev/inode pair.
********************************************************************/
-int get_share_modes(int cnum, int token, uint32 dev, uint32 inode,
- share_mode_entry **shares)
+int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode,
+ min_share_mode_entry **old_shares)
{
- return share_ops->get_entries(cnum, token, dev, inode, shares);
-}
+ smb_shm_offset_t *mode_array;
+ unsigned int hash_entry = HASH_ENTRY(dev, inode);
+ share_mode_record *file_scanner_p;
+ share_mode_record *file_prev_p;
+ share_mode_entry *entry_scanner_p;
+ share_mode_entry *entry_prev_p;
+ int num_entries;
+ int num_entries_copied;
+ BOOL found = False;
+ min_share_mode_entry *share_array = (min_share_mode_entry *)0;
+
+ *old_shares = 0;
+
+ if(hash_entry > lp_shmem_hash_size() )
+ {
+ DEBUG(0,
+ ("PANIC ERROR : get_share_modes (FAST_SHARE_MODES): hash_entry %d too large \
+(max = %d)\n",
+ hash_entry, lp_shmem_hash_size() ));
+ return 0;
+ }
+
+ mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
+
+ if(mode_array[hash_entry] == NULL_OFFSET)
+ {
+ DEBUG(5,("get_share_modes (FAST_SHARE_MODES): hash bucket %d empty\n", hash_entry));
+ return 0;
+ }
+
+ file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
+ file_prev_p = file_scanner_p;
+ while(file_scanner_p)
+ {
+ if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
+ {
+ found = True;
+ break;
+ }
+ else
+ {
+ file_prev_p = file_scanner_p ;
+ file_scanner_p = (share_mode_record *)smb_shm_offset2addr(
+ file_scanner_p->next_offset);
+ }
+ }
+
+ if(!found)
+ {
+ DEBUG(5,("get_share_modes (FAST_SHARE_MODES): no entry for \
+file dev = %d, ino = %d in hash_bucket %d\n", dev, inode, hash_entry));
+ return (0);
+ }
+
+ if(file_scanner_p->locking_version != LOCKING_VERSION)
+ {
+ DEBUG(0,("ERROR:get_share_modes (FAST_SHARE_MODES): Deleting old share mode \
+record due to old locking version %d for file dev = %d, inode = %d in hash \
+bucket %d\n",file_scanner_p->locking_version, dev, inode, hash_entry));
+ if(file_prev_p == file_scanner_p)
+ mode_array[hash_entry] = file_scanner_p->next_offset;
+ else
+ file_prev_p->next_offset = file_scanner_p->next_offset;
+ smb_shm_free(smb_shm_addr2offset(file_scanner_p));
+ return (0);
+ }
+
+ /* Allocate the old_shares array */
+ num_entries = file_scanner_p->num_share_mode_entries;
+ if(num_entries)
+ {
+ *old_shares = share_array = (min_share_mode_entry *)
+ malloc(num_entries * sizeof(min_share_mode_entry));
+ if(*old_shares == 0)
+ {
+ DEBUG(0,("get_share_modes (FAST_SHARE_MODES): malloc fail !\n"));
+ return 0;
+ }
+ }
+
+ num_entries_copied = 0;
+
+ entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
+ file_scanner_p->share_mode_entries);
+ entry_prev_p = entry_scanner_p;
+ while(entry_scanner_p)
+ {
+ int pid = entry_scanner_p->pid;
+
+ if (pid && !process_exists(pid))
+ {
+ /* Delete this share mode entry */
+ share_mode_entry *delete_entry_p = entry_scanner_p;
+ int share_mode = entry_scanner_p->share_mode;
+
+ if(entry_prev_p == entry_scanner_p)
+ {
+ /* We are at start of list */
+ file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
+ entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
+ file_scanner_p->share_mode_entries);
+ entry_prev_p = entry_scanner_p;
+ }
+ else
+ {
+ entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
+ entry_scanner_p = (share_mode_entry*)
+ smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
+ }
+ /* Decrement the number of share mode entries on this share mode record */
+ file_scanner_p->num_share_mode_entries -= 1;
+
+ /* PARANOIA TEST */
+ if(file_scanner_p->num_share_mode_entries < 0)
+ {
+ DEBUG(0,("PANIC ERROR:get_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
+for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
+ dev, inode, hash_entry));
+ return 0;
+ }
+
+ DEBUG(0,("get_share_modes (FAST_SHARE_MODES): process %d no longer exists and \
+it left a share mode entry with mode 0x%X for file dev = %d, ino = %d in hash \
+bucket %d (number of entries now = %d)\n",
+ pid, share_mode, dev, inode, hash_entry,
+ file_scanner_p->num_share_mode_entries));
+
+ smb_shm_free(smb_shm_addr2offset(delete_entry_p));
+ }
+ else
+ {
+ /* This is a valid share mode entry and the process that
+ created it still exists. Copy it into the output array.
+ */
+ share_array[num_entries_copied].pid = entry_scanner_p->pid;
+ share_array[num_entries_copied].share_mode = entry_scanner_p->share_mode;
+ memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->time,
+ sizeof(struct timeval));
+ num_entries_copied++;
+ DEBUG(5,("get_share_modes (FAST_SHARE_MODES): Read share mode \
+record mode 0x%X pid=%d\n", entry_scanner_p->share_mode, entry_scanner_p->pid));
+ entry_prev_p = entry_scanner_p;
+ entry_scanner_p = (share_mode_entry *)
+ smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
+ }
+ }
+
+ /* If no valid share mode entries were found then this record shouldn't exist ! */
+ if(num_entries_copied == 0)
+ {
+ DEBUG(0,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
+hash bucket %d has a share mode record but no entries - deleting\n",
+ dev, inode, hash_entry));
+ if(*old_shares)
+ free((char *)*old_shares);
+ *old_shares = 0;
+
+ if(file_prev_p == file_scanner_p)
+ mode_array[hash_entry] = file_scanner_p->next_offset;
+ else
+ file_prev_p->next_offset = file_scanner_p->next_offset;
+ smb_shm_free(smb_shm_addr2offset(file_scanner_p));
+ }
+
+ DEBUG(5,("get_share_modes (FAST_SHARE_MODES): file with dev %d, inode %d in \
+hash bucket %d returning %d entries\n", dev, inode, hash_entry,
+ num_entries_copied));
+
+ return(num_entries_copied);
+}
/*******************************************************************
del the share mode of a file.
********************************************************************/
-void del_share_mode(int token, int fnum)
+void del_share_mode(share_lock_token token, int fnum)
{
- share_ops->del_entry(token, fnum);
+ uint32 dev, inode;
+ smb_shm_offset_t *mode_array;
+ unsigned int hash_entry;
+ share_mode_record *file_scanner_p;
+ share_mode_record *file_prev_p;
+ share_mode_entry *entry_scanner_p;
+ share_mode_entry *entry_prev_p;
+ BOOL found = False;
+ int pid = getpid();
+
+ dev = Files[fnum].fd_ptr->dev;
+ inode = Files[fnum].fd_ptr->inode;
+
+ hash_entry = HASH_ENTRY(dev, inode);
+
+ if(hash_entry > lp_shmem_hash_size() )
+ {
+ DEBUG(0,
+ ("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
+(max = %d)\n",
+ hash_entry, lp_shmem_hash_size() ));
+ return;
+ }
+
+ mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
+
+ if(mode_array[hash_entry] == NULL_OFFSET)
+ {
+ DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): hash bucket %d empty\n",
+ hash_entry));
+ return;
+ }
+
+ file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
+ file_prev_p = file_scanner_p;
+
+ while(file_scanner_p)
+ {
+ if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
+ {
+ found = True;
+ break;
+ }
+ else
+ {
+ file_prev_p = file_scanner_p ;
+ file_scanner_p = (share_mode_record *)
+ smb_shm_offset2addr(file_scanner_p->next_offset);
+ }
+ }
+
+ if(!found)
+ {
+ DEBUG(0,("ERROR:del_share_mode (FAST_SHARE_MODES): no entry found for dev %d, \
+inode %d in hash bucket %d\n", dev, inode, hash_entry));
+ return;
+ }
+
+ if(file_scanner_p->locking_version != LOCKING_VERSION)
+ {
+ DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): Deleting old share mode \
+record due to old locking version %d for file dev %d, inode %d hash bucket %d\n",
+ file_scanner_p->locking_version, dev, inode, hash_entry ));
+ if(file_prev_p == file_scanner_p)
+ mode_array[hash_entry] = file_scanner_p->next_offset;
+ else
+ file_prev_p->next_offset = file_scanner_p->next_offset;
+ smb_shm_free(smb_shm_addr2offset(file_scanner_p));
+ return;
+ }
+
+ found = False;
+ entry_scanner_p = (share_mode_entry*)smb_shm_offset2addr(
+ file_scanner_p->share_mode_entries);
+ entry_prev_p = entry_scanner_p;
+ while(entry_scanner_p)
+ {
+ if( (pid == entry_scanner_p->pid) &&
+ (memcmp(&entry_scanner_p->time,
+ &Files[fnum].open_time,sizeof(struct timeval)) == 0) )
+ {
+ found = True;
+ break;
+ }
+ else
+ {
+ entry_prev_p = entry_scanner_p;
+ entry_scanner_p = (share_mode_entry *)
+ smb_shm_offset2addr(entry_scanner_p->next_share_mode_entry);
+ }
+ }
+
+ if (found)
+ {
+ /* Decrement the number of entries in the record. */
+ file_scanner_p->num_share_mode_entries -= 1;
+
+ DEBUG(2,("del_share_modes (FAST_SHARE_MODES): \
+Deleting share mode entry dev = %d, inode = %d in hash bucket %d (num entries now = %d)\n",
+ dev, inode, hash_entry, file_scanner_p->num_share_mode_entries));
+ if(entry_prev_p == entry_scanner_p)
+ /* We are at start of list */
+ file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
+ else
+ entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
+ smb_shm_free(smb_shm_addr2offset(entry_scanner_p));
+
+ /* PARANOIA TEST */
+ if(file_scanner_p->num_share_mode_entries < 0)
+ {
+ DEBUG(0,("PANIC ERROR:del_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
+for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
+ dev, inode, hash_entry));
+ return;
+ }
+
+ /* If we deleted the last share mode entry then remove the share mode record. */
+ if(file_scanner_p->num_share_mode_entries == 0)
+ {
+ DEBUG(2,("del_share_modes (FAST_SHARE_MODES): num entries = 0, deleting share_mode \
+record dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
+ if(file_prev_p == file_scanner_p)
+ mode_array[hash_entry] = file_scanner_p->next_offset;
+ else
+ file_prev_p->next_offset = file_scanner_p->next_offset;
+ smb_shm_free(smb_shm_addr2offset(file_scanner_p));
+ }
+ }
+ else
+ {
+ DEBUG(0,("ERROR: del_share_modes (FAST_SHARE_MODES): No share mode record found \
+dev = %d, inode = %d in hash bucket %d\n", dev, inode, hash_entry));
+ }
}
/*******************************************************************
set the share mode of a file. Return False on fail, True on success.
********************************************************************/
-BOOL set_share_mode(int token, int fnum, uint16 port, uint16 op_type)
+BOOL set_share_mode(share_lock_token token, int fnum)
{
- return share_ops->set_entry(token, fnum, port, op_type);
+ files_struct *fs_p = &Files[fnum];
+ int32 dev, inode;
+ smb_shm_offset_t *mode_array;
+ unsigned int hash_entry;
+ share_mode_record *file_scanner_p;
+ share_mode_record *file_prev_p;
+ share_mode_entry *new_entry_p;
+ smb_shm_offset_t new_entry_offset;
+ BOOL found = False;
+
+ dev = fs_p->fd_ptr->dev;
+ inode = fs_p->fd_ptr->inode;
+
+ hash_entry = HASH_ENTRY(dev, inode);
+ if(hash_entry > lp_shmem_hash_size() )
+ {
+ DEBUG(0,
+ ("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): hash_entry %d too large \
+(max = %d)\n",
+ hash_entry, lp_shmem_hash_size() ));
+ return False;
+ }
+
+ mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
+
+ file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[hash_entry]);
+ file_prev_p = file_scanner_p;
+
+ while(file_scanner_p)
+ {
+ if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
+ {
+ found = True;
+ break;
+ }
+ else
+ {
+ file_prev_p = file_scanner_p ;
+ file_scanner_p = (share_mode_record *)
+ smb_shm_offset2addr(file_scanner_p->next_offset);
+ }
+ }
+
+ if(!found)
+ {
+ /* We must create a share_mode_record */
+ share_mode_record *new_mode_p = NULL;
+ smb_shm_offset_t new_offset = smb_shm_alloc( sizeof(share_mode_record) +
+ strlen(fs_p->name) + 1);
+ if(new_offset == NULL_OFFSET)
+ {
+ DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail !\n"));
+ return False;
+ }
+ new_mode_p = smb_shm_offset2addr(new_offset);
+ new_mode_p->locking_version = LOCKING_VERSION;
+ new_mode_p->st_dev = dev;
+ new_mode_p->st_ino = inode;
+ new_mode_p->num_share_mode_entries = 0;
+ new_mode_p->share_mode_entries = NULL_OFFSET;
+ strcpy(new_mode_p->file_name, fs_p->name);
+
+ /* Chain onto the start of the hash chain (in the hope we will be used first). */
+ new_mode_p->next_offset = mode_array[hash_entry];
+ mode_array[hash_entry] = new_offset;
+
+ file_scanner_p = new_mode_p;
+
+ DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share record for %s (dev %d \
+inode %d in hash bucket %d\n", fs_p->name, dev, inode, hash_entry));
+ }
+
+ /* Now create the share mode entry */
+ new_entry_offset = smb_shm_alloc( sizeof(share_mode_entry));
+ if(new_entry_offset == NULL_OFFSET)
+ {
+ smb_shm_offset_t delete_offset = mode_array[hash_entry];
+ DEBUG(0,("ERROR:set_share_mode (FAST_SHARE_MODES): smb_shm_alloc fail 1!\n"));
+ /* Unlink the damaged record */
+ mode_array[hash_entry] = file_scanner_p->next_offset;
+ /* And delete it */
+ smb_shm_free( delete_offset );
+ return False;
+ }
+
+ new_entry_p = smb_shm_offset2addr(new_entry_offset);
+
+ new_entry_p->pid = getpid();
+ new_entry_p->share_mode = fs_p->share_mode;
+ memcpy( (char *)&new_entry_p->time, (char *)&fs_p->open_time, sizeof(struct timeval));
+
+ /* Chain onto the share_mode_record */
+ new_entry_p->next_share_mode_entry = file_scanner_p->share_mode_entries;
+ file_scanner_p->share_mode_entries = new_entry_offset;
+
+ /* PARANOIA TEST */
+ if(file_scanner_p->num_share_mode_entries < 0)
+ {
+ DEBUG(0,("PANIC ERROR:set_share_mode (FAST_SHARE_MODES): num_share_mode_entries < 0 (%d) \
+for dev = %d, ino = %d, hashbucket %d\n", file_scanner_p->num_share_mode_entries,
+ dev, inode, hash_entry));
+ return False;
+ }
+
+ /* Increment the share_mode_entries counter */
+ file_scanner_p->num_share_mode_entries += 1;
+
+ DEBUG(3,("set_share_mode (FAST_SHARE_MODES): Created share entry for %s with mode \
+0x%X pid=%d (num_entries now = %d)\n",fs_p->name, fs_p->share_mode, new_entry_p->pid,
+ file_scanner_p->num_share_mode_entries));
+
+ return(True);
+}
+
+#else /* FAST_SHARE_MODES */
+
+/* SHARE MODE LOCKS USING SLOW DESCRIPTION FILES */
+
+/*******************************************************************
+ name a share file
+ ******************************************************************/
+static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name)
+{
+ strcpy(name,lp_lockdir());
+ standard_sub(cnum,name);
+ trim_string(name,"","/");
+ if (!*name) return(False);
+ name += strlen(name);
+
+ sprintf(name,"/share.%u.%u",dev,inode);
+ return(True);
}
/*******************************************************************
-Remove an oplock port and mode entry from a share mode.
+Force a share file to be deleted.
********************************************************************/
-BOOL remove_share_oplock(int fnum, int token)
+static int delete_share_file( int cnum, char *fname )
{
- return share_ops->remove_oplock(fnum, token);
+ /* the share file could be owned by anyone, so do this as root */
+ become_root(0);
+
+ if(unlink(fname) != 0) {
+ DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
+ fname, strerror(errno)));
+ } else {
+ DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
+ }
+
+ unbecome_root(0);
+
+ return 0;
+}
+
+/*******************************************************************
+ lock a share mode file.
+ ******************************************************************/
+BOOL lock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token *ptok)
+{
+ pstring fname;
+ int fd;
+ int ret = True;
+
+ *ptok = (share_lock_token)-1;
+
+ if(!share_name(cnum, dev, inode, fname))
+ return False;
+
+ /* we need to do this as root */
+ become_root(0);
+
+ {
+ int old_umask;
+ BOOL gotlock = False;
+ old_umask = umask(0);
+
+ /*
+ * There was a race condition in the original slow share mode code.
+ * A smbd could open a share mode file, and before getting
+ * the lock, another smbd could delete the last entry for
+ * the share mode file and delete the file entry from the
+ * directory. Thus this smbd would be left with a locked
+ * share mode fd attached to a file that no longer had a
+ * directory entry. Thus another smbd would think that
+ * there were no outstanding opens on the file. To fix
+ * this we now check we can do a stat() call on the filename
+ * before allowing the lock to proceed, and back out completely
+ * and try the open again if we cannot.
+ * Jeremy Allison (jallison@whistle.com).
+ */
+
+ do
+ {
+ struct stat dummy_stat;
+#ifdef SECURE_SHARE_MODES
+ fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0600);
+#else /* SECURE_SHARE_MODES */
+ fd = (share_lock_token)open(fname,O_RDWR|O_CREAT,0666);
+#endif /* SECURE_SHARE_MODES */
+
+ if(fd < 0)
+ {
+ DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n",
+ fname, strerror(errno)));
+ ret = False;
+ break;
+ }
+
+ /* At this point we have an open fd to the share mode file.
+ Lock the first byte exclusively to signify a lock. */
+ if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False)
+ {
+ DEBUG(0,("ERROR lock_share_entry: fcntl_lock failed with %s\n",
+ strerror(errno)));
+ close(fd);
+ ret = False;
+ break;
+ }
+
+ /*
+ * If we cannot stat the filename, the file was deleted between
+ * the open and the lock call. Back out and try again.
+ */
+
+ if(stat(fname, &dummy_stat)!=0)
+ {
+ DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n",
+ fname, strerror(errno)));
+ close(fd);
+ }
+ else
+ gotlock = True;
+ } while(!gotlock);
+
+ umask(old_umask);
+ }
+
+ *ptok = (share_lock_token)fd;
+
+ /* return to our previous privilage level */
+ unbecome_root(0);
+
+ return ret;
+}
+
+/*******************************************************************
+ unlock a share mode file.
+ ******************************************************************/
+BOOL unlock_share_entry(int cnum, uint32 dev, uint32 inode, share_lock_token token)
+{
+ int fd = (int)token;
+ int ret = True;
+ struct stat sb;
+ pstring fname;
+
+ /* Fix for zero length share files from
+ Gerald Werner <wernerg@mfldclin.edu> */
+
+ share_name(cnum, dev, inode, fname);
+
+ /* get the share mode file size */
+ if(fstat((int)token, &sb) != 0)
+ {
+ DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n",
+ fname, strerror(errno)));
+ sb.st_size = 1;
+ ret = False;
+ }
+
+ /* If the file was zero length, we must delete before
+ doing the unlock to avoid a race condition (see
+ the code in lock_share_mode_entry for details.
+ */
+
+ /* remove the share file if zero length */
+ if(sb.st_size == 0)
+ delete_share_file(cnum, fname);
+
+ /* token is the fd of the open share mode file. */
+ /* Unlock the first byte. */
+ if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False)
+ {
+ DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n",
+ strerror(errno)));
+ ret = False;
+ }
+
+ close((int)token);
+ return ret;
}
+/*******************************************************************
+Read a share file into a buffer.
+********************************************************************/
+
+static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file)
+{
+ struct stat sb;
+ char *buf;
+ int size;
+
+ *out = 0;
+ *p_new_file = False;
+
+ if(fstat(fd, &sb) != 0)
+ {
+ DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
+ fname, strerror(errno)));
+ return -1;
+ }
+
+ if(sb.st_size == 0)
+ {
+ *p_new_file = True;
+ return 0;
+ }
+
+ /* Allocate space for the file */
+ if((buf = (char *)malloc(sb.st_size)) == NULL)
+ {
+ DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size));
+ return -1;
+ }
+
+ if(lseek(fd, 0, SEEK_SET) != 0)
+ {
+ DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \
+for share file %s (%s)\n", fname, strerror(errno)));
+ if(buf)
+ free(buf);
+ return -1;
+ }
+
+ if (read(fd,buf,sb.st_size) != sb.st_size)
+ {
+ DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n",
+ fname, strerror(errno)));
+ if(buf)
+ free(buf);
+ return -1;
+ }
+
+ if (IVAL(buf,0) != LOCKING_VERSION) {
+ DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \
+locking version (was %d, should be %d).\n",fname, IVAL(buf,0), LOCKING_VERSION));
+ if(buf)
+ free(buf);
+ delete_share_file(cnum, fname);
+ return -1;
+ }
+
+ /* Sanity check for file contents */
+ size = sb.st_size;
+ size -= 10; /* Remove the header */
+
+ /* Remove the filename component. */
+ size -= SVAL(buf, 8);
+
+ /* The remaining size must be a multiple of 16 - error if not. */
+ if((size % 16) != 0)
+ {
+ DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \
+deleting it.\n", fname));
+ if(buf)
+ free(buf);
+ delete_share_file(cnum, fname);
+ return -1;
+ }
+
+ *out = buf;
+ return 0;
+}
/*******************************************************************
-call the specified function on each entry under management by the
-share mode system
+get all share mode entries in a share file for a dev/inode pair.
********************************************************************/
-int share_mode_forall(void (*fn)(share_mode_entry *, char *))
+int get_share_modes(int cnum, share_lock_token token, uint32 dev, uint32 inode,
+ min_share_mode_entry **old_shares)
{
- return share_ops->forall(fn);
+ int fd = (int)token;
+ pstring fname;
+ int i;
+ int num_entries;
+ int num_entries_copied;
+ int newsize;
+ min_share_mode_entry *share_array;
+ char *buf = 0;
+ char *base = 0;
+ BOOL new_file;
+
+ *old_shares = 0;
+
+ /* Read the share file header - this is of the form:
+ 0 - locking version.
+ 4 - number of share mode entries.
+ 8 - 2 byte name length
+ [n bytes] file name (zero terminated).
+
+ Followed by <n> share mode entries of the form :
+
+ 0 - tv_sec
+ 4 - tv_usec
+ 8 - share_mode
+ 12 - pid
+
+ */
+
+ share_name(cnum, dev, inode, fname);
+
+ if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0)
+ {
+ DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n",
+ fname));
+ return 0;
+ }
+
+ if(new_file == True)
+ return 0;
+
+ num_entries = IVAL(buf,4);
+
+ DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n",
+ fname, num_entries));
+
+ /* PARANOIA TEST */
+ if(num_entries < 0)
+ {
+ DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \
+for share file %d\n", num_entries, fname));
+ return 0;
+ }
+
+ if(num_entries)
+ {
+ *old_shares = share_array = (min_share_mode_entry *)
+ malloc(num_entries * sizeof(min_share_mode_entry));
+ if(*old_shares == 0)
+ {
+ DEBUG(0,("get_share_modes: malloc fail !\n"));
+ return 0;
+ }
+ }
+ else
+ {
+ /* No entries - just delete the file. */
+ DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n",
+ fname));
+ if(buf)
+ free(buf);
+ delete_share_file(cnum, fname);
+ return 0;
+ }
+
+ num_entries_copied = 0;
+ base = buf + 10 + SVAL(buf,8);
+
+ for( i = 0; i < num_entries; i++)
+ {
+ int pid;
+ char *p = base + (i*16);
+
+ pid = IVAL(p,12);
+
+ if(!process_exists(pid))
+ {
+ DEBUG(0,("get_share_modes: process %d no longer exists and \
+it left a share mode entry with mode 0x%X in share file %s\n",
+ pid, IVAL(p,8), fname));
+ continue;
+ }
+ share_array[num_entries_copied].time.tv_sec = IVAL(p,0);
+ share_array[num_entries_copied].time.tv_usec = IVAL(p,4);
+ share_array[num_entries_copied].share_mode = IVAL(p,8);
+ share_array[num_entries_copied].pid = pid;
+
+ num_entries_copied++;
+ }
+
+ if(num_entries_copied == 0)
+ {
+ /* Delete the whole file. */
+ DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n",
+ fname));
+ if(*old_shares)
+ free((char *)*old_shares);
+ *old_shares = 0;
+ if(buf)
+ free(buf);
+ delete_share_file(cnum, fname);
+ return 0;
+ }
+
+ /* If we deleted some entries we need to re-write the whole number of
+ share mode entries back into the file. */
+
+ if(num_entries_copied != num_entries)
+ {
+ if(lseek(fd, 0, SEEK_SET) != 0)
+ {
+ DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \
+position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
+ if(*old_shares)
+ free((char *)*old_shares);
+ *old_shares = 0;
+ if(buf)
+ free(buf);
+ return 0;
+ }
+
+ SIVAL(buf, 4, num_entries_copied);
+ for( i = 0; i < num_entries_copied; i++)
+ {
+ char *p = base + (i*16);
+
+ SIVAL(p,12,share_array[i].pid);
+ SIVAL(p,8,share_array[i].share_mode);
+ SIVAL(p,0,share_array[i].time.tv_sec);
+ SIVAL(p,4,share_array[i].time.tv_usec);
+ }
+
+ newsize = (base - buf) + (16*num_entries_copied);
+ if(write(fd, buf, newsize) != newsize)
+ {
+ DEBUG(0,("ERROR: get_share_modes: failed to re-write share \
+mode file %s (%s)\n", fname, strerror(errno)));
+ if(*old_shares)
+ free((char *)*old_shares);
+ *old_shares = 0;
+ if(buf)
+ free(buf);
+ return 0;
+ }
+ /* Now truncate the file at this point. */
+ if(ftruncate(fd, newsize)!= 0)
+ {
+ DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \
+mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
+ if(*old_shares)
+ free((char *)*old_shares);
+ *old_shares = 0;
+ if(buf)
+ free(buf);
+ return 0;
+ }
+ }
+
+ if(buf)
+ free(buf);
+
+ DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname,
+ num_entries_copied));
+
+ return num_entries_copied;
}
/*******************************************************************
-dump the state of the system
+del a share mode from a share mode file.
+********************************************************************/
+void del_share_mode(share_lock_token token, int fnum)
+{
+ pstring fname;
+ int fd = (int)token;
+ char *buf = 0;
+ char *base = 0;
+ int num_entries;
+ int newsize;
+ int i;
+ files_struct *fs_p = &Files[fnum];
+ int pid;
+ BOOL deleted = False;
+ BOOL new_file;
+
+ share_name(fs_p->cnum, fs_p->fd_ptr->dev,
+ fs_p->fd_ptr->inode, fname);
+
+ if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
+ {
+ DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n",
+ fname));
+ return;
+ }
+
+ if(new_file == True)
+ {
+ DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
+ fname));
+ delete_share_file(fs_p->cnum, fname);
+ return;
+ }
+
+ num_entries = IVAL(buf,4);
+
+ DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n",
+ fname, num_entries));
+
+ /* PARANOIA TEST */
+ if(num_entries < 0)
+ {
+ DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
+for share file %d\n", num_entries, fname));
+ return;
+ }
+
+ if(num_entries == 0)
+ {
+ /* No entries - just delete the file. */
+ DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n",
+ fname));
+ if(buf)
+ free(buf);
+ delete_share_file(fs_p->cnum, fname);
+ return;
+ }
+
+ pid = getpid();
+
+ /* Go through the entries looking for the particular one
+ we have set - delete it.
+ */
+
+ base = buf + 10 + SVAL(buf,8);
+
+ for(i = 0; i < num_entries; i++)
+ {
+ char *p = base + (i*16);
+
+ if((IVAL(p,0) != fs_p->open_time.tv_sec) || (IVAL(p,4) != fs_p->open_time.tv_usec) ||
+ (IVAL(p,8) != fs_p->share_mode) || (IVAL(p,12) != pid))
+ continue;
+
+ DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n",
+ i, num_entries, fname));
+
+ /* Remove this entry. */
+ if(i != num_entries - 1)
+ memcpy(p, p + 16, (num_entries - i - 1)*16);
+
+ deleted = True;
+ break;
+ }
+
+ if(!deleted)
+ {
+ DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname));
+ if(buf)
+ free(buf);
+ return;
+ }
+
+ num_entries--;
+ SIVAL(buf,4, num_entries);
+
+ if(num_entries == 0)
+ {
+ /* Deleted the last entry - remove the file. */
+ DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n",
+ fname));
+ if(buf)
+ free(buf);
+ delete_share_file(fs_p->cnum,fname);
+ return;
+ }
+
+ /* Re-write the file - and truncate it at the correct point. */
+ if(lseek(fd, 0, SEEK_SET) != 0)
+ {
+ DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \
+position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
+ if(buf)
+ free(buf);
+ return;
+ }
+
+ newsize = (base - buf) + (16*num_entries);
+ if(write(fd, buf, newsize) != newsize)
+ {
+ DEBUG(0,("ERROR: del_share_mode: failed to re-write share \
+mode file %s (%s)\n", fname, strerror(errno)));
+ if(buf)
+ free(buf);
+ return;
+ }
+ /* Now truncate the file at this point. */
+ if(ftruncate(fd, newsize) != 0)
+ {
+ DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \
+mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
+ if(buf)
+ free(buf);
+ return;
+ }
+}
+
+/*******************************************************************
+set the share mode of a file
********************************************************************/
-void share_status(FILE *f)
+BOOL set_share_mode(share_lock_token token,int fnum)
{
- share_ops->status(f);
+ files_struct *fs_p = &Files[fnum];
+ pstring fname;
+ int fd = (int)token;
+ int pid = (int)getpid();
+ struct stat sb;
+ char *buf;
+ int num_entries;
+ int header_size;
+ char *p;
+
+ share_name(fs_p->cnum, fs_p->fd_ptr->dev,
+ fs_p->fd_ptr->inode, fname);
+
+ if(fstat(fd, &sb) != 0)
+ {
+ DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n",
+ fname));
+ return False;
+ }
+
+ /* Sanity check for file contents (if it's not a new share file). */
+ if(sb.st_size != 0)
+ {
+ int size = sb.st_size;
+
+ /* Allocate space for the file plus one extra entry */
+ if((buf = (char *)malloc(sb.st_size + 16)) == NULL)
+ {
+ DEBUG(0,("set_share_mode: malloc for file size %d fail !\n", sb.st_size + 16));
+ return False;
+ }
+
+ if(lseek(fd, 0, SEEK_SET) != 0)
+ {
+ DEBUG(0,("ERROR: set_share_mode: Failed to reset position \
+to 0 for share file %s (%s)\n", fname, strerror(errno)));
+ if(buf)
+ free(buf);
+ return False;
+ }
+
+ if (read(fd,buf,sb.st_size) != sb.st_size)
+ {
+ DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n",
+ fname, strerror(errno)));
+ if(buf)
+ free(buf);
+ return False;
+ }
+
+ if (IVAL(buf,0) != LOCKING_VERSION)
+ {
+ DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \
+locking version (was %d, should be %d).\n",fname, IVAL(buf,0), LOCKING_VERSION));
+ if(buf)
+ free(buf);
+ delete_share_file(fs_p->cnum, fname);
+ return False;
+ }
+
+ size -= (10 + SVAL(buf, 8)); /* Remove the header */
+
+ /* The remaining size must be a multiple of 16 - error if not. */
+ if((size % 16) != 0)
+ {
+ DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \
+deleting it.\n", fname));
+ if(buf)
+ free(buf);
+ delete_share_file(fs_p->cnum, fname);
+ return False;
+ }
+
+ }
+ else
+ {
+ /* New file - just use a single_entry. */
+ if((buf = (char *)malloc(10 + strlen(fs_p->name) + 1 + 16)) == NULL)
+ {
+ DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n"));
+ return False;
+ }
+ SIVAL(buf,0,LOCKING_VERSION);
+ SIVAL(buf,4,0);
+ SSVAL(buf,8,strlen(fs_p->name) + 1);
+ strcpy(buf + 10, fs_p->name);
+ }
+
+ num_entries = IVAL(buf,4);
+ header_size = 10 + SVAL(buf,8);
+ p = buf + header_size + (num_entries * 16);
+ SIVAL(p,0,fs_p->open_time.tv_sec);
+ SIVAL(p,4,fs_p->open_time.tv_usec);
+ SIVAL(p,8,fs_p->share_mode);
+ SIVAL(p,12,pid);
+
+ num_entries++;
+
+ SIVAL(buf,4,num_entries);
+
+ if(lseek(fd, 0, SEEK_SET) != 0)
+ {
+ DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \
+0 for share file %s (%s)\n", fname, strerror(errno)));
+ if(buf)
+ free(buf);
+ return False;
+ }
+
+ if (write(fd,buf,header_size + (num_entries*16)) != (header_size + (num_entries*16)))
+ {
+ DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \
+deleting it (%s).\n",fname, strerror(errno)));
+ delete_share_file(fs_p->cnum, fname);
+ if(buf)
+ free(buf);
+ return False;
+ }
+
+ /* Now truncate the file at this point - just for safety. */
+ if(ftruncate(fd, header_size + (16*num_entries))!= 0)
+ {
+ DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \
+mode file %s to size %d (%s)\n", fname, header_size + (16*num_entries), strerror(errno)));
+ if(buf)
+ free(buf);
+ return False;
+ }
+
+ if(buf)
+ free(buf);
+
+ DEBUG(3,("set_share_mode: Created share file %s with \
+mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid));
+
+ return True;
}
+#endif /* FAST_SHARE_MODES */
diff --git a/source/locking/locking_shm.c b/source/locking/locking_shm.c
deleted file mode 100644
index 2e3278d3ddd..00000000000
--- a/source/locking/locking_shm.c
+++ /dev/null
@@ -1,698 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- shared memory locking implementation
- Copyright (C) Andrew Tridgell 1992-1997
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Revision History:
-
- 12 aug 96: Erik.Devriendt@te6.siemens.be
- added support for shared memory implementation of share mode locking
-
- May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
- locking to deal with multiple share modes per open file.
-
- September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
- support.
-
- October 1997 - split into separate file (tridge)
-*/
-
-#ifdef FAST_SHARE_MODES
-
-#include "includes.h"
-extern int DEBUGLEVEL;
-extern connection_struct Connections[];
-extern files_struct Files[];
-
-static struct shmem_ops *shmops;
-
-/* share mode record pointed to in shared memory hash bucket */
-typedef struct
-{
- int next_offset; /* offset of next record in chain from hash bucket */
- int locking_version;
- int32 st_dev;
- int32 st_ino;
- int num_share_mode_entries;
- int share_mode_entries; /* Chain of share mode entries for this file */
- char file_name[1];
-} share_mode_record;
-
-/* share mode entry pointed to by share_mode_record struct */
-typedef struct
-{
- int next_share_mode_entry;
- share_mode_entry e;
-} shm_share_mode_entry;
-
-static int read_only;
-
-
-/* Conversion to hash entry index from device and inode numbers. */
-#define HASH_ENTRY(dev,ino) ((((uint32)(dev)) ^ ((uint32)(ino))) % shmops->hash_size())
-
-
-/*******************************************************************
- deinitialize the shared memory for share_mode management
- ******************************************************************/
-static BOOL shm_stop_share_mode_mgmt(void)
-{
- return shmops->shm_close();
-}
-
-/*******************************************************************
- lock a hash bucket entry in shared memory for share_mode management
- ******************************************************************/
-static BOOL shm_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok)
-{
- return shmops->lock_hash_entry(HASH_ENTRY(dev, inode));
-}
-
-/*******************************************************************
- unlock a hash bucket entry in shared memory for share_mode management
- ******************************************************************/
-static BOOL shm_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token)
-{
- return shmops->unlock_hash_entry(HASH_ENTRY(dev, inode));
-}
-
-/*******************************************************************
-get all share mode entries in shared memory for a dev/inode pair.
-********************************************************************/
-static int shm_get_share_modes(int cnum, int token, uint32 dev, uint32 inode,
- share_mode_entry **old_shares)
-{
- int *mode_array;
- unsigned int hash_entry = HASH_ENTRY(dev, inode);
- share_mode_record *file_scanner_p;
- share_mode_record *file_prev_p;
- shm_share_mode_entry *entry_scanner_p;
- shm_share_mode_entry *entry_prev_p;
- int num_entries;
- int num_entries_copied;
- BOOL found = False;
- share_mode_entry *share_array = (share_mode_entry *)0;
-
- *old_shares = 0;
-
- mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
-
- if(mode_array[hash_entry] == 0)
- {
- DEBUG(5,("get_share_modes hash bucket %d empty\n", hash_entry));
- return 0;
- }
-
- file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]);
- file_prev_p = file_scanner_p;
- while(file_scanner_p)
- {
- if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
- {
- found = True;
- break;
- }
- else
- {
- file_prev_p = file_scanner_p ;
- file_scanner_p = (share_mode_record *)shmops->offset2addr(
- file_scanner_p->next_offset);
- }
- }
-
- if(!found)
- {
- DEBUG(5,("get_share_modes no entry for file dev = %d ino = %d\n",
- dev, inode));
- return (0);
- }
-
- if(file_scanner_p->locking_version != LOCKING_VERSION)
- {
- DEBUG(0,("ERROR: get_share_modes Deleting old share mode v1 %d dev=%d ino=%d\n",
- file_scanner_p->locking_version, dev, inode));
- if(file_prev_p == file_scanner_p)
- mode_array[hash_entry] = file_scanner_p->next_offset;
- else
- file_prev_p->next_offset = file_scanner_p->next_offset;
- shmops->shm_free(shmops->addr2offset(file_scanner_p));
- return (0);
- }
-
- /* Allocate the old_shares array */
- num_entries = file_scanner_p->num_share_mode_entries;
- if(num_entries)
- {
- *old_shares = share_array = (share_mode_entry *)
- malloc(num_entries * sizeof(share_mode_entry));
- if(*old_shares == 0)
- {
- DEBUG(0,("get_share_modes: malloc fail!\n"));
- return 0;
- }
- }
-
- num_entries_copied = 0;
-
- entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr(
- file_scanner_p->share_mode_entries);
- entry_prev_p = entry_scanner_p;
- while(entry_scanner_p)
- {
- int pid = entry_scanner_p->e.pid;
-
- if (pid && !process_exists(pid))
- {
- /* Delete this share mode entry */
- shm_share_mode_entry *delete_entry_p = entry_scanner_p;
-
- if(entry_prev_p == entry_scanner_p)
- {
- /* We are at start of list */
- file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
- entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr(
- file_scanner_p->share_mode_entries);
- entry_prev_p = entry_scanner_p;
- }
- else
- {
- entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
- entry_scanner_p = (shm_share_mode_entry*)
- shmops->offset2addr(entry_scanner_p->next_share_mode_entry);
- }
- /* Decrement the number of share mode entries on this share mode record */
- file_scanner_p->num_share_mode_entries -= 1;
-
- /* PARANOIA TEST */
- if(file_scanner_p->num_share_mode_entries < 0)
- {
- DEBUG(0,("PANIC ERROR: get_share_mode: entries=%d dev=%d ino=%d\n",
- file_scanner_p->num_share_mode_entries,dev, inode));
- return 0;
- }
-
- DEBUG(0,("get_share_modes: process %d no longer exists\n", pid));
-
- shmops->shm_free(shmops->addr2offset(delete_entry_p));
- }
- else
- {
- /* This is a valid share mode entry and the process that
- created it still exists. Copy it into the output array.
- */
- share_array[num_entries_copied].pid = entry_scanner_p->e.pid;
- share_array[num_entries_copied].share_mode = entry_scanner_p->e.share_mode;
- share_array[num_entries_copied].op_port = entry_scanner_p->e.op_port;
- share_array[num_entries_copied].op_type = entry_scanner_p->e.op_type;
- memcpy(&share_array[num_entries_copied].time, &entry_scanner_p->e.time,
- sizeof(struct timeval));
- num_entries_copied++;
- DEBUG(5,("get_share_modes Read share mode 0x%X pid=%d\n",
- entry_scanner_p->e.share_mode, entry_scanner_p->e.pid));
- entry_prev_p = entry_scanner_p;
- entry_scanner_p = (shm_share_mode_entry *)
- shmops->offset2addr(entry_scanner_p->next_share_mode_entry);
- }
- }
-
- /* If no valid share mode entries were found then this record shouldn't exist ! */
- if(num_entries_copied == 0)
- {
- DEBUG(0,("get_share_modes: file with dev %d inode %d empty\n",
- dev, inode));
- if(*old_shares)
- free((char *)*old_shares);
- *old_shares = 0;
-
- if(file_prev_p == file_scanner_p)
- mode_array[hash_entry] = file_scanner_p->next_offset;
- else
- file_prev_p->next_offset = file_scanner_p->next_offset;
- shmops->shm_free(shmops->addr2offset(file_scanner_p));
- }
-
- DEBUG(5,("get_share_modes: file with dev %d inode %d -> %d entries\n",
- dev, inode, num_entries_copied));
-
- return(num_entries_copied);
-}
-
-/*******************************************************************
-del the share mode of a file.
-********************************************************************/
-static void shm_del_share_mode(int token, int fnum)
-{
- uint32 dev, inode;
- int *mode_array;
- unsigned int hash_entry;
- share_mode_record *file_scanner_p;
- share_mode_record *file_prev_p;
- shm_share_mode_entry *entry_scanner_p;
- shm_share_mode_entry *entry_prev_p;
- BOOL found = False;
- int pid = getpid();
-
- dev = Files[fnum].fd_ptr->dev;
- inode = Files[fnum].fd_ptr->inode;
-
- hash_entry = HASH_ENTRY(dev, inode);
-
- mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
-
- if(mode_array[hash_entry] == 0)
- {
- DEBUG(0,("PANIC ERROR:del_share_mode hash bucket %d empty\n",
- hash_entry));
- return;
- }
-
- file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]);
- file_prev_p = file_scanner_p;
-
- while(file_scanner_p)
- {
- if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
- {
- found = True;
- break;
- }
- else
- {
- file_prev_p = file_scanner_p ;
- file_scanner_p = (share_mode_record *)
- shmops->offset2addr(file_scanner_p->next_offset);
- }
- }
-
- if(!found)
- {
- DEBUG(0,("ERROR: del_share_mode no entry for dev %d inode %d\n",
- dev, inode));
- return;
- }
-
- if(file_scanner_p->locking_version != LOCKING_VERSION)
- {
- DEBUG(0,("ERROR: del_share_modes Deleting old share mode v1 %d dev=%d ino=%d\n",
- file_scanner_p->locking_version, dev, inode));
- if(file_prev_p == file_scanner_p)
- mode_array[hash_entry] = file_scanner_p->next_offset;
- else
- file_prev_p->next_offset = file_scanner_p->next_offset;
- shmops->shm_free(shmops->addr2offset(file_scanner_p));
- return;
- }
-
- found = False;
- entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr(
- file_scanner_p->share_mode_entries);
- entry_prev_p = entry_scanner_p;
- while(entry_scanner_p)
- {
- if( (pid == entry_scanner_p->e.pid) &&
- (memcmp(&entry_scanner_p->e.time,
- &Files[fnum].open_time,sizeof(struct timeval)) == 0) )
- {
- found = True;
- break;
- }
- else
- {
- entry_prev_p = entry_scanner_p;
- entry_scanner_p = (shm_share_mode_entry *)
- shmops->offset2addr(entry_scanner_p->next_share_mode_entry);
- }
- }
-
- if (found)
- {
- /* Decrement the number of entries in the record. */
- file_scanner_p->num_share_mode_entries -= 1;
-
- DEBUG(2,("del_share_modes Deleting share mode entry dev=%d ino=%d\n",
- dev, inode));
- if(entry_prev_p == entry_scanner_p)
- /* We are at start of list */
- file_scanner_p->share_mode_entries = entry_scanner_p->next_share_mode_entry;
- else
- entry_prev_p->next_share_mode_entry = entry_scanner_p->next_share_mode_entry;
- shmops->shm_free(shmops->addr2offset(entry_scanner_p));
-
- /* PARANOIA TEST */
- if(file_scanner_p->num_share_mode_entries < 0)
- {
- DEBUG(0,("PANIC ERROR:del_share_mode num_share_mode_entries=%d\n",
- file_scanner_p->num_share_mode_entries));
- return;
- }
-
- /* If we deleted the last share mode entry then remove the share mode record. */
- if(file_scanner_p->num_share_mode_entries == 0)
- {
- DEBUG(2,("del_share_modes num entries = 0, deleting share_mode dev=%d ino=%d\n",
- dev, inode));
- if(file_prev_p == file_scanner_p)
- mode_array[hash_entry] = file_scanner_p->next_offset;
- else
- file_prev_p->next_offset = file_scanner_p->next_offset;
- shmops->shm_free(shmops->addr2offset(file_scanner_p));
- }
- }
- else
- {
- DEBUG(0,("ERROR: del_share_modes No share mode dev=%d ino=%d\n",
- dev, inode));
- }
-}
-
-/*******************************************************************
-set the share mode of a file. Return False on fail, True on success.
-********************************************************************/
-static BOOL shm_set_share_mode(int token, int fnum, uint16 port, uint16 op_type)
-{
- files_struct *fs_p = &Files[fnum];
- int32 dev, inode;
- int *mode_array;
- unsigned int hash_entry;
- share_mode_record *file_scanner_p;
- share_mode_record *file_prev_p;
- shm_share_mode_entry *new_entry_p;
- int new_entry_offset;
- BOOL found = False;
-
- dev = fs_p->fd_ptr->dev;
- inode = fs_p->fd_ptr->inode;
-
- hash_entry = HASH_ENTRY(dev, inode);
-
- mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
-
- file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]);
- file_prev_p = file_scanner_p;
-
- while(file_scanner_p)
- {
- if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
- {
- found = True;
- break;
- }
- else
- {
- file_prev_p = file_scanner_p ;
- file_scanner_p = (share_mode_record *)
- shmops->offset2addr(file_scanner_p->next_offset);
- }
- }
-
- if(!found)
- {
- /* We must create a share_mode_record */
- share_mode_record *new_mode_p = NULL;
- int new_offset = shmops->shm_alloc(sizeof(share_mode_record) +
- strlen(fs_p->name) + 1);
- if(new_offset == 0) {
- DEBUG(0,("ERROR:set_share_mode shmops->shm_alloc fail!\n"));
- return False;
- }
- new_mode_p = shmops->offset2addr(new_offset);
- new_mode_p->locking_version = LOCKING_VERSION;
- new_mode_p->st_dev = dev;
- new_mode_p->st_ino = inode;
- new_mode_p->num_share_mode_entries = 0;
- new_mode_p->share_mode_entries = 0;
- strcpy(new_mode_p->file_name, fs_p->name);
-
- /* Chain onto the start of the hash chain (in the hope we will be used first). */
- new_mode_p->next_offset = mode_array[hash_entry];
- mode_array[hash_entry] = new_offset;
-
- file_scanner_p = new_mode_p;
-
- DEBUG(3,("set_share_mode: Created share record for %s (dev %d inode %d)\n",
- fs_p->name, dev, inode));
- }
-
- /* Now create the share mode entry */
- new_entry_offset = shmops->shm_alloc(sizeof(shm_share_mode_entry));
- if(new_entry_offset == 0) {
- int delete_offset = mode_array[hash_entry];
- DEBUG(0,("ERROR:set_share_mode: shmops->shm_alloc fail 1!\n"));
- /* Unlink the damaged record */
- mode_array[hash_entry] = file_scanner_p->next_offset;
- /* And delete it */
- shmops->shm_free( delete_offset );
- return False;
- }
-
- new_entry_p = shmops->offset2addr(new_entry_offset);
-
- new_entry_p->e.pid = getpid();
- new_entry_p->e.share_mode = fs_p->share_mode;
- new_entry_p->e.op_port = port;
- new_entry_p->e.op_type = op_type;
- memcpy( (char *)&new_entry_p->e.time, (char *)&fs_p->open_time, sizeof(struct timeval));
-
- /* Chain onto the share_mode_record */
- new_entry_p->next_share_mode_entry = file_scanner_p->share_mode_entries;
- file_scanner_p->share_mode_entries = new_entry_offset;
-
- /* PARANOIA TEST */
- if(file_scanner_p->num_share_mode_entries < 0)
- {
- DEBUG(0,("PANIC ERROR:set_share_mode num_share_mode_entries=%d\n",
- file_scanner_p->num_share_mode_entries));
- return False;
- }
-
- /* Increment the share_mode_entries counter */
- file_scanner_p->num_share_mode_entries += 1;
-
- DEBUG(3,("set_share_mode: Created share entry for %s with mode 0x%X pid=%d\n",
- fs_p->name, fs_p->share_mode, new_entry_p->e.pid));
-
- return(True);
-}
-
-/*******************************************************************
-Remove an oplock port and mode entry from a share mode.
-********************************************************************/
-static BOOL shm_remove_share_oplock(int fnum, int token)
-{
- uint32 dev, inode;
- int *mode_array;
- unsigned int hash_entry;
- share_mode_record *file_scanner_p;
- share_mode_record *file_prev_p;
- shm_share_mode_entry *entry_scanner_p;
- shm_share_mode_entry *entry_prev_p;
- BOOL found = False;
- int pid = getpid();
-
- dev = Files[fnum].fd_ptr->dev;
- inode = Files[fnum].fd_ptr->inode;
-
- hash_entry = HASH_ENTRY(dev, inode);
-
- mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
-
- if(mode_array[hash_entry] == 0)
- {
- DEBUG(0,("PANIC ERROR:remove_share_oplock: hash bucket %d empty\n",
- hash_entry));
- return False;
- }
-
- file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[hash_entry]);
- file_prev_p = file_scanner_p;
-
- while(file_scanner_p)
- {
- if( (file_scanner_p->st_dev == dev) && (file_scanner_p->st_ino == inode) )
- {
- found = True;
- break;
- }
- else
- {
- file_prev_p = file_scanner_p ;
- file_scanner_p = (share_mode_record *)
- shmops->offset2addr(file_scanner_p->next_offset);
- }
- }
-
- if(!found)
- {
- DEBUG(0,("ERROR:remove_share_oplock: no entry found for dev=%d ino=%d\n",
- dev, inode));
- return False;
- }
-
- if(file_scanner_p->locking_version != LOCKING_VERSION)
- {
- DEBUG(0,("ERROR: remove_share_oplock: Deleting old share mode v1=%d dev=%d ino=%d\n",
- file_scanner_p->locking_version, dev, inode));
- if(file_prev_p == file_scanner_p)
- mode_array[hash_entry] = file_scanner_p->next_offset;
- else
- file_prev_p->next_offset = file_scanner_p->next_offset;
- shmops->shm_free(shmops->addr2offset(file_scanner_p));
- return False;
- }
-
- found = False;
- entry_scanner_p = (shm_share_mode_entry*)shmops->offset2addr(
- file_scanner_p->share_mode_entries);
- entry_prev_p = entry_scanner_p;
- while(entry_scanner_p)
- {
- if( (pid == entry_scanner_p->e.pid) &&
- (entry_scanner_p->e.share_mode == Files[fnum].share_mode) &&
- (memcmp(&entry_scanner_p->e.time,
- &Files[fnum].open_time,sizeof(struct timeval)) == 0) )
- {
- /* Delete the oplock info. */
- entry_scanner_p->e.op_port = 0;
- entry_scanner_p->e.op_type = 0;
- found = True;
- break;
- }
- else
- {
- entry_prev_p = entry_scanner_p;
- entry_scanner_p = (shm_share_mode_entry *)
- shmops->offset2addr(entry_scanner_p->next_share_mode_entry);
- }
- }
-
- if(!found)
- {
- DEBUG(0,("ERROR: remove_share_oplock: No oplock granted. dev=%d ino=%d\n",
- dev, inode));
- return False;
- }
-
- return True;
-}
-
-
-/*******************************************************************
-call the specified function on each entry under management by the
-share mode system
-********************************************************************/
-static int shm_share_forall(void (*fn)(share_mode_entry *, char *))
-{
- int i, count=0;
- int *mode_array;
- share_mode_record *file_scanner_p;
-
- mode_array = (int *)shmops->offset2addr(shmops->get_userdef_off());
-
- for( i = 0; i < shmops->hash_size(); i++) {
- shmops->lock_hash_entry(i);
- if(mode_array[i] == 0) {
- shmops->unlock_hash_entry(i);
- continue;
- }
-
- file_scanner_p = (share_mode_record *)shmops->offset2addr(mode_array[i]);
- while((file_scanner_p != 0) &&
- (file_scanner_p->num_share_mode_entries != 0)) {
- shm_share_mode_entry *entry_scanner_p =
- (shm_share_mode_entry *)
- shmops->offset2addr(file_scanner_p->share_mode_entries);
-
- while(entry_scanner_p != 0) {
-
- if (process_exists(entry_scanner_p->e.pid)) {
- fn(&entry_scanner_p->e,
- file_scanner_p->file_name);
- count++;
- }
-
- entry_scanner_p =
- (shm_share_mode_entry *)
- shmops->offset2addr(
- entry_scanner_p->next_share_mode_entry);
- } /* end while entry_scanner_p */
- file_scanner_p = (share_mode_record *)
- shmops->offset2addr(file_scanner_p->next_offset);
- } /* end while file_scanner_p */
- shmops->unlock_hash_entry(i);
- } /* end for */
-
- return count;
-}
-
-
-/*******************************************************************
-dump the state of the system
-********************************************************************/
-static void shm_share_status(FILE *f)
-{
- int bytes_free, bytes_used, bytes_overhead, bytes_total;
-
- shmops->get_usage(&bytes_free, &bytes_used, &bytes_overhead);
- bytes_total = bytes_free + bytes_used + bytes_overhead;
-
- fprintf(f, "Share mode memory usage (bytes):\n");
- fprintf(f, " %d(%d%%) free + %d(%d%%) used + %d(%d%%) overhead = %d(100%%) total\n",
- bytes_free, (bytes_free * 100)/bytes_total,
- bytes_used, (bytes_used * 100)/bytes_total,
- bytes_overhead, (bytes_overhead * 100)/bytes_total,
- bytes_total);
-}
-
-
-static struct share_ops share_ops = {
- shm_stop_share_mode_mgmt,
- shm_lock_share_entry,
- shm_unlock_share_entry,
- shm_get_share_modes,
- shm_del_share_mode,
- shm_set_share_mode,
- shm_remove_share_oplock,
- shm_share_forall,
- shm_share_status,
-};
-
-/*******************************************************************
- initialize the shared memory for share_mode management
- ******************************************************************/
-struct share_ops *locking_shm_init(int ronly)
-{
- read_only = ronly;
-
-#ifdef USE_SYSV_IPC
- shmops = sysv_shm_open(read_only);
- if (shmops) return &share_ops;
-#endif
-
- shmops = smb_shm_open(read_only);
- if (shmops) return &share_ops;
-
- return NULL;
-}
-
-#else
- int locking_shm_dummy_procedure(void)
-{return 0;}
-#endif
-
-
-
diff --git a/source/locking/locking_slow.c b/source/locking/locking_slow.c
deleted file mode 100644
index 935ed09f60d..00000000000
--- a/source/locking/locking_slow.c
+++ /dev/null
@@ -1,1052 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- slow (lockfile) locking implementation
- Copyright (C) Andrew Tridgell 1992-1997
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Revision History:
-
- 12 aug 96: Erik.Devriendt@te6.siemens.be
- added support for shared memory implementation of share mode locking
-
- May 1997. Jeremy Allison (jallison@whistle.com). Modified share mode
- locking to deal with multiple share modes per open file.
-
- September 1997. Jeremy Allison (jallison@whistle.com). Added oplock
- support.
-
- October 1997 - split into separate file (tridge)
-*/
-
-#include "includes.h"
-extern int DEBUGLEVEL;
-extern connection_struct Connections[];
-extern files_struct Files[];
-
-/*
- * Locking file header lengths & offsets.
- */
-#define SMF_VERSION_OFFSET 0
-#define SMF_NUM_ENTRIES_OFFSET 4
-#define SMF_FILENAME_LEN_OFFSET 8
-#define SMF_HEADER_LENGTH 10
-
-#define SMF_ENTRY_LENGTH 20
-
-/*
- * Share mode record offsets.
- */
-
-#define SME_SEC_OFFSET 0
-#define SME_USEC_OFFSET 4
-#define SME_SHAREMODE_OFFSET 8
-#define SME_PID_OFFSET 12
-#define SME_PORT_OFFSET 16
-#define SME_OPLOCK_TYPE_OFFSET 18
-
-/* we need world read for smbstatus to function correctly */
-#ifdef SECURE_SHARE_MODES
-#define SHARE_FILE_MODE 0600
-#else
-#define SHARE_FILE_MODE 0644
-#endif
-
-static int read_only;
-
-/*******************************************************************
- deinitialize share_mode management
- ******************************************************************/
-static BOOL slow_stop_share_mode_mgmt(void)
-{
- return True;
-}
-
-
-/*******************************************************************
- name a share file
- ******************************************************************/
-static BOOL share_name(int cnum, uint32 dev, uint32 inode, char *name)
-{
- strcpy(name,lp_lockdir());
- trim_string(name,"","/");
- if (!*name) return(False);
- name += strlen(name);
-
- sprintf(name,"/share.%u.%u",dev,inode);
- return(True);
-}
-
-/*******************************************************************
-Force a share file to be deleted.
-********************************************************************/
-static int delete_share_file( int cnum, char *fname )
-{
- if (read_only) return -1;
-
- /* the share file could be owned by anyone, so do this as root */
- become_root(False);
-
- if(unlink(fname) != 0)
- {
- DEBUG(0,("delete_share_file: Can't delete share file %s (%s)\n",
- fname, strerror(errno)));
- }
- else
- {
- DEBUG(5,("delete_share_file: Deleted share file %s\n", fname));
- }
-
- /* return to our previous privilage level */
- unbecome_root(False);
-
- return 0;
-}
-
-/*******************************************************************
- lock a share mode file.
- ******************************************************************/
-static BOOL slow_lock_share_entry(int cnum, uint32 dev, uint32 inode, int *ptok)
-{
- pstring fname;
- int fd;
- int ret = True;
-
- *ptok = (int)-1;
-
- if(!share_name(cnum, dev, inode, fname))
- return False;
-
- if (read_only) return True;
-
- /* we need to do this as root */
- become_root(False);
-
- {
- BOOL gotlock = False;
- /*
- * There was a race condition in the original slow share mode code.
- * A smbd could open a share mode file, and before getting
- * the lock, another smbd could delete the last entry for
- * the share mode file and delete the file entry from the
- * directory. Thus this smbd would be left with a locked
- * share mode fd attached to a file that no longer had a
- * directory entry. Thus another smbd would think that
- * there were no outstanding opens on the file. To fix
- * this we now check we can do a stat() call on the filename
- * before allowing the lock to proceed, and back out completely
- * and try the open again if we cannot.
- * Jeremy Allison (jallison@whistle.com).
- */
-
- do
- {
- struct stat dummy_stat;
-
- fd = (int)open(fname,read_only?O_RDONLY:(O_RDWR|O_CREAT),
- SHARE_FILE_MODE);
-
- if(fd < 0)
- {
- DEBUG(0,("ERROR lock_share_entry: failed to open share file %s. Error was %s\n",
- fname, strerror(errno)));
- ret = False;
- break;
- }
-
- /* At this point we have an open fd to the share mode file.
- Lock the first byte exclusively to signify a lock. */
- if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False)
- {
- DEBUG(0,("ERROR lock_share_entry: fcntl_lock on file %s failed with %s\n",
- fname, strerror(errno)));
- close(fd);
- ret = False;
- break;
- }
-
- /*
- * If we cannot stat the filename, the file was deleted between
- * the open and the lock call. Back out and try again.
- */
-
- if(stat(fname, &dummy_stat)!=0)
- {
- DEBUG(2,("lock_share_entry: Re-issuing open on %s to fix race. Error was %s\n",
- fname, strerror(errno)));
- close(fd);
- }
- else
- gotlock = True;
- } while(!gotlock);
-
- /*
- * We have to come here if any of the above calls fail
- * as we don't want to return and leave ourselves running
- * as root !
- */
- }
-
- *ptok = (int)fd;
-
- /* return to our previous privilage level */
- unbecome_root(False);
-
- return ret;
-}
-
-/*******************************************************************
- unlock a share mode file.
- ******************************************************************/
-static BOOL slow_unlock_share_entry(int cnum, uint32 dev, uint32 inode, int token)
-{
- int fd = (int)token;
- int ret = True;
- struct stat sb;
- pstring fname;
-
- if (read_only) return True;
-
- /* Fix for zero length share files from
- Gerald Werner <wernerg@mfldclin.edu> */
-
- share_name(cnum, dev, inode, fname);
-
- /* get the share mode file size */
- if(fstat((int)token, &sb) != 0)
- {
- DEBUG(0,("ERROR: unlock_share_entry: Failed to do stat on share file %s (%s)\n",
- fname, strerror(errno)));
- sb.st_size = 1;
- ret = False;
- }
-
- /* If the file was zero length, we must delete before
- doing the unlock to avoid a race condition (see
- the code in lock_share_mode_entry for details.
- */
-
- /* remove the share file if zero length */
- if(sb.st_size == 0)
- delete_share_file(cnum, fname);
-
- /* token is the fd of the open share mode file. */
- /* Unlock the first byte. */
- if(fcntl_lock(fd, F_SETLKW, 0, 1, F_UNLCK) == False)
- {
- DEBUG(0,("ERROR unlock_share_entry: fcntl_lock failed with %s\n",
- strerror(errno)));
- ret = False;
- }
-
- close(fd);
- return ret;
-}
-
-/*******************************************************************
-Read a share file into a buffer.
-********************************************************************/
-static int read_share_file(int cnum, int fd, char *fname, char **out, BOOL *p_new_file)
-{
- struct stat sb;
- char *buf;
- int size;
-
- *out = 0;
- *p_new_file = False;
-
- if(fstat(fd, &sb) != 0)
- {
- DEBUG(0,("ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
- fname, strerror(errno)));
- return -1;
- }
-
- if(sb.st_size == 0)
- {
- *p_new_file = True;
- return 0;
- }
-
- /* Allocate space for the file */
- if((buf = (char *)malloc(sb.st_size)) == NULL)
- {
- DEBUG(0,("read_share_file: malloc for file size %d fail !\n", sb.st_size));
- return -1;
- }
-
- if(lseek(fd, 0, SEEK_SET) != 0)
- {
- DEBUG(0,("ERROR: read_share_file: Failed to reset position to 0 \
-for share file %s (%s)\n", fname, strerror(errno)));
- if(buf)
- free(buf);
- return -1;
- }
-
- if (read(fd,buf,sb.st_size) != sb.st_size)
- {
- DEBUG(0,("ERROR: read_share_file: Failed to read share file %s (%s)\n",
- fname, strerror(errno)));
- if(buf)
- free(buf);
- return -1;
- }
-
- if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION) {
- DEBUG(0,("ERROR: read_share_file: share file %s has incorrect \
-locking version (was %d, should be %d).\n",fname,
- IVAL(buf,SMF_VERSION_OFFSET), LOCKING_VERSION));
- if(buf)
- free(buf);
- delete_share_file(cnum, fname);
- return -1;
- }
-
- /* Sanity check for file contents */
- size = sb.st_size;
- size -= SMF_HEADER_LENGTH; /* Remove the header */
-
- /* Remove the filename component. */
- size -= SVAL(buf, SMF_FILENAME_LEN_OFFSET);
-
- /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
- if((size % SMF_ENTRY_LENGTH) != 0)
- {
- DEBUG(0,("ERROR: read_share_file: share file %s is an incorrect length - \
-deleting it.\n", fname));
- if(buf)
- free(buf);
- delete_share_file(cnum, fname);
- return -1;
- }
-
- *out = buf;
- return 0;
-}
-
-/*******************************************************************
-get all share mode entries in a share file for a dev/inode pair.
-********************************************************************/
-static int slow_get_share_modes(int cnum, int token, uint32 dev, uint32 inode,
- share_mode_entry **old_shares)
-{
- int fd = (int)token;
- pstring fname;
- int i;
- int num_entries;
- int num_entries_copied;
- int newsize;
- share_mode_entry *share_array;
- char *buf = 0;
- char *base = 0;
- BOOL new_file;
-
- *old_shares = 0;
-
- /* Read the share file header - this is of the form:
- 0 - locking version.
- 4 - number of share mode entries.
- 8 - 2 byte name length
- [n bytes] file name (zero terminated).
-
- Followed by <n> share mode entries of the form :
-
- 0 - tv_sec
- 4 - tv_usec
- 8 - share_mode
- 12 - pid
- 16 - oplock port (if oplocks in use) - 2 bytes.
- */
-
- share_name(cnum, dev, inode, fname);
-
- if(read_share_file( cnum, fd, fname, &buf, &new_file) != 0)
- {
- DEBUG(0,("ERROR: get_share_modes: Failed to read share file %s\n",
- fname));
- return 0;
- }
-
- if(new_file == True)
- return 0;
-
- num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
-
- DEBUG(5,("get_share_modes: share file %s has %d share mode entries.\n",
- fname, num_entries));
-
- /* PARANOIA TEST */
- if(num_entries < 0)
- {
- DEBUG(0,("PANIC ERROR:get_share_mode: num_share_mode_entries < 0 (%d) \
-for share file %d\n", num_entries, fname));
- return 0;
- }
-
- if(num_entries)
- {
- *old_shares = share_array = (share_mode_entry *)
- malloc(num_entries * sizeof(share_mode_entry));
- if(*old_shares == 0)
- {
- DEBUG(0,("get_share_modes: malloc fail !\n"));
- return 0;
- }
- }
- else
- {
- /* No entries - just delete the file. */
- DEBUG(0,("get_share_modes: share file %s has no share mode entries - deleting.\n",
- fname));
- if(buf)
- free(buf);
- delete_share_file(cnum, fname);
- return 0;
- }
-
- num_entries_copied = 0;
- base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
-
- for( i = 0; i < num_entries; i++)
- {
- int pid;
- char *p = base + (i*SMF_ENTRY_LENGTH);
-
- pid = IVAL(p,SME_PID_OFFSET);
-
- if(!process_exists(pid))
- {
- DEBUG(0,("get_share_modes: process %d no longer exists and \
-it left a share mode entry with mode 0x%X in share file %s\n",
- pid, IVAL(p,SME_SHAREMODE_OFFSET), fname));
- continue;
- }
- share_array[num_entries_copied].time.tv_sec = IVAL(p,SME_SEC_OFFSET);
- share_array[num_entries_copied].time.tv_usec = IVAL(p,SME_USEC_OFFSET);
- share_array[num_entries_copied].share_mode = IVAL(p,SME_SHAREMODE_OFFSET);
- share_array[num_entries_copied].pid = pid;
- share_array[num_entries_copied].op_port = SVAL(p,SME_PORT_OFFSET);
- share_array[num_entries_copied].op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
-
- num_entries_copied++;
- }
-
- if(num_entries_copied == 0)
- {
- /* Delete the whole file. */
- DEBUG(0,("get_share_modes: share file %s had no valid entries - deleting it !\n",
- fname));
- if(*old_shares)
- free((char *)*old_shares);
- *old_shares = 0;
- if(buf)
- free(buf);
- delete_share_file(cnum, fname);
- return 0;
- }
-
- /* If we deleted some entries we need to re-write the whole number of
- share mode entries back into the file. */
-
- if(num_entries_copied != num_entries)
- {
- if(lseek(fd, 0, SEEK_SET) != 0)
- {
- DEBUG(0,("ERROR: get_share_modes: lseek failed to reset to \
-position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
- if(*old_shares)
- free((char *)*old_shares);
- *old_shares = 0;
- if(buf)
- free(buf);
- return 0;
- }
-
- SIVAL(buf, SMF_NUM_ENTRIES_OFFSET, num_entries_copied);
- for( i = 0; i < num_entries_copied; i++)
- {
- char *p = base + (i*SMF_ENTRY_LENGTH);
-
- SIVAL(p,SME_PID_OFFSET,share_array[i].pid);
- SIVAL(p,SME_SHAREMODE_OFFSET,share_array[i].share_mode);
- SIVAL(p,SME_SEC_OFFSET,share_array[i].time.tv_sec);
- SIVAL(p,SME_USEC_OFFSET,share_array[i].time.tv_usec);
- SSVAL(p,SME_PORT_OFFSET,share_array[i].op_port);
- SSVAL(p,SME_OPLOCK_TYPE_OFFSET,share_array[i].op_type);
- }
-
- newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries_copied);
- if(write(fd, buf, newsize) != newsize)
- {
- DEBUG(0,("ERROR: get_share_modes: failed to re-write share \
-mode file %s (%s)\n", fname, strerror(errno)));
- if(*old_shares)
- free((char *)*old_shares);
- *old_shares = 0;
- if(buf)
- free(buf);
- return 0;
- }
- /* Now truncate the file at this point. */
- if(ftruncate(fd, newsize)!= 0)
- {
- DEBUG(0,("ERROR: get_share_modes: failed to ftruncate share \
-mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
- if(*old_shares)
- free((char *)*old_shares);
- *old_shares = 0;
- if(buf)
- free(buf);
- return 0;
- }
- }
-
- if(buf)
- free(buf);
-
- DEBUG(5,("get_share_modes: Read share file %s returning %d entries\n",fname,
- num_entries_copied));
-
- return num_entries_copied;
-}
-
-/*******************************************************************
-del a share mode from a share mode file.
-********************************************************************/
-static void slow_del_share_mode(int token, int fnum)
-{
- pstring fname;
- int fd = (int)token;
- char *buf = 0;
- char *base = 0;
- int num_entries;
- int newsize;
- int i;
- files_struct *fs_p = &Files[fnum];
- int pid;
- BOOL deleted = False;
- BOOL new_file;
-
- share_name(fs_p->cnum, fs_p->fd_ptr->dev,
- fs_p->fd_ptr->inode, fname);
-
- if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
- {
- DEBUG(0,("ERROR: del_share_mode: Failed to read share file %s\n",
- fname));
- return;
- }
-
- if(new_file == True)
- {
- DEBUG(0,("ERROR:del_share_mode: share file %s is new (size zero), deleting it.\n",
- fname));
- delete_share_file(fs_p->cnum, fname);
- return;
- }
-
- num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
-
- DEBUG(5,("del_share_mode: share file %s has %d share mode entries.\n",
- fname, num_entries));
-
- /* PARANOIA TEST */
- if(num_entries < 0)
- {
- DEBUG(0,("PANIC ERROR:del_share_mode: num_share_mode_entries < 0 (%d) \
-for share file %d\n", num_entries, fname));
- return;
- }
-
- if(num_entries == 0)
- {
- /* No entries - just delete the file. */
- DEBUG(0,("del_share_mode: share file %s has no share mode entries - deleting.\n",
- fname));
- if(buf)
- free(buf);
- delete_share_file(fs_p->cnum, fname);
- return;
- }
-
- pid = getpid();
-
- /* Go through the entries looking for the particular one
- we have set - delete it.
- */
-
- base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
-
- for(i = 0; i < num_entries; i++)
- {
- char *p = base + (i*SMF_ENTRY_LENGTH);
-
- if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) ||
- (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
- (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) ||
- (IVAL(p,SME_PID_OFFSET) != pid))
- continue;
-
- DEBUG(5,("del_share_mode: deleting entry number %d (of %d) from the share file %s\n",
- i, num_entries, fname));
-
- /* Remove this entry. */
- if(i != num_entries - 1)
- memcpy(p, p + SMF_ENTRY_LENGTH, (num_entries - i - 1)*SMF_ENTRY_LENGTH);
-
- deleted = True;
- break;
- }
-
- if(!deleted)
- {
- DEBUG(0,("del_share_mode: entry not found in share file %s\n", fname));
- if(buf)
- free(buf);
- return;
- }
-
- num_entries--;
- SIVAL(buf,SMF_NUM_ENTRIES_OFFSET, num_entries);
-
- if(num_entries == 0)
- {
- /* Deleted the last entry - remove the file. */
- DEBUG(5,("del_share_mode: removed last entry in share file - deleting share file %s\n",
- fname));
- if(buf)
- free(buf);
- delete_share_file(fs_p->cnum,fname);
- return;
- }
-
- /* Re-write the file - and truncate it at the correct point. */
- if(lseek(fd, 0, SEEK_SET) != 0)
- {
- DEBUG(0,("ERROR: del_share_mode: lseek failed to reset to \
-position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
- if(buf)
- free(buf);
- return;
- }
-
- newsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
- if(write(fd, buf, newsize) != newsize)
- {
- DEBUG(0,("ERROR: del_share_mode: failed to re-write share \
-mode file %s (%s)\n", fname, strerror(errno)));
- if(buf)
- free(buf);
- return;
- }
- /* Now truncate the file at this point. */
- if(ftruncate(fd, newsize) != 0)
- {
- DEBUG(0,("ERROR: del_share_mode: failed to ftruncate share \
-mode file %s to size %d (%s)\n", fname, newsize, strerror(errno)));
- if(buf)
- free(buf);
- return;
- }
-}
-
-/*******************************************************************
-set the share mode of a file
-********************************************************************/
-static BOOL slow_set_share_mode(int token,int fnum, uint16 port, uint16 op_type)
-{
- files_struct *fs_p = &Files[fnum];
- pstring fname;
- int fd = (int)token;
- int pid = (int)getpid();
- struct stat sb;
- char *buf;
- int num_entries;
- int header_size;
- char *p;
-
- share_name(fs_p->cnum, fs_p->fd_ptr->dev,
- fs_p->fd_ptr->inode, fname);
-
- if(fstat(fd, &sb) != 0)
- {
- DEBUG(0,("ERROR: set_share_mode: Failed to do stat on share file %s\n",
- fname));
- return False;
- }
-
- /* Sanity check for file contents (if it's not a new share file). */
- if(sb.st_size != 0)
- {
- int size = sb.st_size;
-
- /* Allocate space for the file plus one extra entry */
- if((buf = (char *)malloc(sb.st_size + SMF_ENTRY_LENGTH)) == NULL)
- {
- DEBUG(0,("set_share_mode: malloc for file size %d fail !\n",
- sb.st_size + SMF_ENTRY_LENGTH));
- return False;
- }
-
- if(lseek(fd, 0, SEEK_SET) != 0)
- {
- DEBUG(0,("ERROR: set_share_mode: Failed to reset position \
-to 0 for share file %s (%s)\n", fname, strerror(errno)));
- if(buf)
- free(buf);
- return False;
- }
-
- if (read(fd,buf,sb.st_size) != sb.st_size)
- {
- DEBUG(0,("ERROR: set_share_mode: Failed to read share file %s (%s)\n",
- fname, strerror(errno)));
- if(buf)
- free(buf);
- return False;
- }
-
- if (IVAL(buf,SMF_VERSION_OFFSET) != LOCKING_VERSION)
- {
- DEBUG(0,("ERROR: set_share_mode: share file %s has incorrect \
-locking version (was %d, should be %d).\n",fname, IVAL(buf,SMF_VERSION_OFFSET),
- LOCKING_VERSION));
- if(buf)
- free(buf);
- delete_share_file(fs_p->cnum, fname);
- return False;
- }
-
- size -= (SMF_HEADER_LENGTH + SVAL(buf, SMF_FILENAME_LEN_OFFSET)); /* Remove the header */
-
- /* The remaining size must be a multiple of SMF_ENTRY_LENGTH - error if not. */
- if((size % SMF_ENTRY_LENGTH) != 0)
- {
- DEBUG(0,("ERROR: set_share_mode: share file %s is an incorrect length - \
-deleting it.\n", fname));
- if(buf)
- free(buf);
- delete_share_file(fs_p->cnum, fname);
- return False;
- }
-
- }
- else
- {
- /* New file - just use a single_entry. */
- if((buf = (char *)malloc(SMF_HEADER_LENGTH +
- strlen(fs_p->name) + 1 + SMF_ENTRY_LENGTH)) == NULL)
- {
- DEBUG(0,("ERROR: set_share_mode: malloc failed for single entry.\n"));
- return False;
- }
- SIVAL(buf,SMF_VERSION_OFFSET,LOCKING_VERSION);
- SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,0);
- SSVAL(buf,SMF_FILENAME_LEN_OFFSET,strlen(fs_p->name) + 1);
- strcpy(buf + SMF_HEADER_LENGTH, fs_p->name);
- }
-
- num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
- header_size = SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
- p = buf + header_size + (num_entries * SMF_ENTRY_LENGTH);
- SIVAL(p,SME_SEC_OFFSET,fs_p->open_time.tv_sec);
- SIVAL(p,SME_USEC_OFFSET,fs_p->open_time.tv_usec);
- SIVAL(p,SME_SHAREMODE_OFFSET,fs_p->share_mode);
- SIVAL(p,SME_PID_OFFSET,pid);
- SSVAL(p,SME_PORT_OFFSET,port);
- SSVAL(p,SME_OPLOCK_TYPE_OFFSET,op_type);
-
- num_entries++;
-
- SIVAL(buf,SMF_NUM_ENTRIES_OFFSET,num_entries);
-
- if(lseek(fd, 0, SEEK_SET) != 0)
- {
- DEBUG(0,("ERROR: set_share_mode: (1) Failed to reset position to \
-0 for share file %s (%s)\n", fname, strerror(errno)));
- if(buf)
- free(buf);
- return False;
- }
-
- if (write(fd,buf,header_size + (num_entries*SMF_ENTRY_LENGTH)) !=
- (header_size + (num_entries*SMF_ENTRY_LENGTH)))
- {
- DEBUG(2,("ERROR: set_share_mode: Failed to write share file %s - \
-deleting it (%s).\n",fname, strerror(errno)));
- delete_share_file(fs_p->cnum, fname);
- if(buf)
- free(buf);
- return False;
- }
-
- /* Now truncate the file at this point - just for safety. */
- if(ftruncate(fd, header_size + (SMF_ENTRY_LENGTH*num_entries))!= 0)
- {
- DEBUG(0,("ERROR: set_share_mode: failed to ftruncate share \
-mode file %s to size %d (%s)\n", fname, header_size + (SMF_ENTRY_LENGTH*num_entries),
- strerror(errno)));
- if(buf)
- free(buf);
- return False;
- }
-
- if(buf)
- free(buf);
-
- DEBUG(3,("set_share_mode: Created share file %s with \
-mode 0x%X pid=%d\n",fname,fs_p->share_mode,pid));
-
- return True;
-}
-
-/*******************************************************************
-Remove an oplock port and mode entry from a share mode.
-********************************************************************/
-static BOOL slow_remove_share_oplock(int fnum, int token)
-{
- pstring fname;
- int fd = (int)token;
- char *buf = 0;
- char *base = 0;
- int num_entries;
- int fsize;
- int i;
- files_struct *fs_p = &Files[fnum];
- int pid;
- BOOL found = False;
- BOOL new_file;
-
- share_name(fs_p->cnum, fs_p->fd_ptr->dev,
- fs_p->fd_ptr->inode, fname);
-
- if(read_share_file( fs_p->cnum, fd, fname, &buf, &new_file) != 0)
- {
- DEBUG(0,("ERROR: remove_share_oplock: Failed to read share file %s\n",
- fname));
- return False;
- }
-
- if(new_file == True)
- {
- DEBUG(0,("ERROR: remove_share_oplock: share file %s is new (size zero), \
-deleting it.\n", fname));
- delete_share_file(fs_p->cnum, fname);
- return False;
- }
-
- num_entries = IVAL(buf,SMF_NUM_ENTRIES_OFFSET);
-
- DEBUG(5,("remove_share_oplock: share file %s has %d share mode entries.\n",
- fname, num_entries));
-
- /* PARANOIA TEST */
- if(num_entries < 0)
- {
- DEBUG(0,("PANIC ERROR:remove_share_oplock: num_share_mode_entries < 0 (%d) \
-for share file %d\n", num_entries, fname));
- return False;
- }
-
- if(num_entries == 0)
- {
- /* No entries - just delete the file. */
- DEBUG(0,("remove_share_oplock: share file %s has no share mode entries - deleting.\n",
- fname));
- if(buf)
- free(buf);
- delete_share_file(fs_p->cnum, fname);
- return False;
- }
-
- pid = getpid();
-
- /* Go through the entries looking for the particular one
- we have set - remove the oplock settings on it.
- */
-
- base = buf + SMF_HEADER_LENGTH + SVAL(buf,SMF_FILENAME_LEN_OFFSET);
-
- for(i = 0; i < num_entries; i++)
- {
- char *p = base + (i*SMF_ENTRY_LENGTH);
-
- if((IVAL(p,SME_SEC_OFFSET) != fs_p->open_time.tv_sec) ||
- (IVAL(p,SME_USEC_OFFSET) != fs_p->open_time.tv_usec) ||
- (IVAL(p,SME_SHAREMODE_OFFSET) != fs_p->share_mode) ||
- (IVAL(p,SME_PID_OFFSET) != pid))
- continue;
-
- DEBUG(5,("remove_share_oplock: clearing oplock on entry number %d (of %d) \
-from the share file %s\n", i, num_entries, fname));
-
- SSVAL(p,SME_PORT_OFFSET,0);
- SSVAL(p,SME_OPLOCK_TYPE_OFFSET,0);
- found = True;
- break;
- }
-
- if(!found)
- {
- DEBUG(0,("remove_share_oplock: entry not found in share file %s\n", fname));
- if(buf)
- free(buf);
- return False;
- }
-
- /* Re-write the file - and truncate it at the correct point. */
- if(lseek(fd, 0, SEEK_SET) != 0)
- {
- DEBUG(0,("ERROR: remove_share_oplock: lseek failed to reset to \
-position 0 for share mode file %s (%s)\n", fname, strerror(errno)));
- if(buf)
- free(buf);
- return False;
- }
-
- fsize = (base - buf) + (SMF_ENTRY_LENGTH*num_entries);
- if(write(fd, buf, fsize) != fsize)
- {
- DEBUG(0,("ERROR: remove_share_oplock: failed to re-write share \
-mode file %s (%s)\n", fname, strerror(errno)));
- if(buf)
- free(buf);
- return False;
- }
-
- return True;
-}
-
-
-
-/*******************************************************************
-call the specified function on each entry under management by the
-share ode system
-********************************************************************/
-static int slow_share_forall(void (*fn)(share_mode_entry *, char *))
-{
- int i, count=0;
- void *dir;
- char *s;
- share_mode_entry e;
-
- dir = opendir(lp_lockdir());
- if (!dir) {
- return(0);
- }
-
- while ((s=readdirname(dir))) {
- char *buf;
- char *base;
- int fd;
- pstring lname;
- uint32 dev,inode;
- BOOL new_file;
- pstring fname;
-
- if (sscanf(s,"share.%u.%u",&dev,&inode)!=2) continue;
-
- strcpy(lname,lp_lockdir());
- trim_string(lname,NULL,"/");
- strcat(lname,"/");
- strcat(lname,s);
-
- fd = open(lname,read_only?O_RDONLY:O_RDWR,0);
- if (fd < 0) {
- continue;
- }
-
- /* Lock the share mode file while we read it. */
- if(!read_only &&
- fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False) {
- close(fd);
- continue;
- }
-
- if(read_share_file( 0, fd, lname, &buf, &new_file)) {
- close(fd);
- continue;
- }
- strcpy( fname, &buf[10]);
- close(fd);
-
- base = buf + SMF_HEADER_LENGTH +
- SVAL(buf,SMF_FILENAME_LEN_OFFSET);
- for( i = 0; i < IVAL(buf, SMF_NUM_ENTRIES_OFFSET); i++) {
- char *p = base + (i*SMF_ENTRY_LENGTH);
- e.pid = IVAL(p,SME_PID_OFFSET);
- e.share_mode = IVAL(p,SME_SHAREMODE_OFFSET);
- e.time.tv_sec = IVAL(p,SME_SEC_OFFSET);
- e.time.tv_usec = IVAL(p,SME_USEC_OFFSET);
- e.op_port = SVAL(p,SME_PORT_OFFSET);
- e.pid = SVAL(p,SME_PID_OFFSET);
- e.op_type = SVAL(p,SME_OPLOCK_TYPE_OFFSET);
-
- if (process_exists(e.pid)) {
- fn(&e, fname);
- count++;
- }
- } /* end for i */
-
- if(buf)
- free(buf);
- base = 0;
- } /* end while */
- closedir(dir);
-
- return count;
-}
-
-
-/*******************************************************************
-dump the state of the system
-********************************************************************/
-static void slow_share_status(FILE *f)
-{
-
-}
-
-
-static struct share_ops share_ops = {
- slow_stop_share_mode_mgmt,
- slow_lock_share_entry,
- slow_unlock_share_entry,
- slow_get_share_modes,
- slow_del_share_mode,
- slow_set_share_mode,
- slow_remove_share_oplock,
- slow_share_forall,
- slow_share_status,
-};
-
-/*******************************************************************
- initialize the slow share_mode management
- ******************************************************************/
-struct share_ops *locking_slow_init(int ronly)
-{
-
- read_only = ronly;
-
- if (!directory_exist(lp_lockdir(),NULL)) {
- if (!read_only)
- mkdir(lp_lockdir(),0755);
- if (!directory_exist(lp_lockdir(),NULL))
- return NULL;
- }
-
- return &share_ops;
-}
diff --git a/source/locking/shmem.c b/source/locking/shmem.c
index 864f7c298b6..fcd9f3ad0d7 100644
--- a/source/locking/shmem.c
+++ b/source/locking/shmem.c
@@ -34,16 +34,6 @@ extern int DEBUGLEVEL;
#define SMB_SHM_VERSION 2
-/* we need world read for smbstatus to function correctly */
-#ifdef SECURE_SHARE_MODES
-#define SHM_FILE_MODE 0600
-#else
-#define SHM_FILE_MODE 0644
-#endif
-
-#define SHMEM_HASH_SIZE 113
-
-
/* WARNING : offsets are used because mmap() does not guarantee that all processes have the
shared memory mapped to the same address */
@@ -53,8 +43,8 @@ struct SmbShmHeader
int smb_shm_version;
int total_size; /* in bytes */
BOOL consistent;
- int first_free_off;
- int userdef_off; /* a userdefined offset. can be used to store root of tree or list */
+ smb_shm_offset_t first_free_off;
+ smb_shm_offset_t userdef_off; /* a userdefined offset. can be used to store root of tree or list */
struct { /* a cell is a range of bytes of sizeof(struct SmbShmBlockDesc) size */
int cells_free;
int cells_used;
@@ -65,12 +55,12 @@ struct SmbShmHeader
#define SMB_SHM_NOT_FREE_OFF (-1)
struct SmbShmBlockDesc
{
- int next; /* offset of next block in the free list or SMB_SHM_NOT_FREE_OFF when block in use */
+ smb_shm_offset_t next; /* offset of next block in the free list or SMB_SHM_NOT_FREE_OFF when block in use */
int size; /* user size in BlockDescSize units */
};
#define EOList_Addr (struct SmbShmBlockDesc *)( 0 )
-#define EOList_Off 0
+#define EOList_Off (NULL_OFFSET)
#define CellSize sizeof(struct SmbShmBlockDesc)
@@ -85,8 +75,6 @@ static int smb_shm_times_locked = 0;
static BOOL smb_shm_initialize_called = False;
-static int read_only;
-
static BOOL smb_shm_global_lock(void)
{
if (smb_shm_fd < 0)
@@ -102,14 +90,11 @@ static BOOL smb_shm_global_lock(void)
DEBUG(5,("smb_shm_global_lock : locked %d times\n",smb_shm_times_locked));
return True;
}
-
- if (read_only)
- return True;
/* Do an exclusive wait lock on the first byte of the file */
if (fcntl_lock(smb_shm_fd, F_SETLKW, 0, 1, F_WRLCK) == False)
{
- DEBUG(0,("ERROR smb_shm_global_lock : fcntl_lock failed with code %s\n",strerror(errno)));
+ DEBUG(0,("ERROR smb_shm_global_lock : fcntl_lock failed with code %d\n",errno));
smb_shm_times_locked--;
return False;
}
@@ -139,14 +124,11 @@ static BOOL smb_shm_global_unlock(void)
DEBUG(5,("smb_shm_global_unlock : still locked %d times\n",smb_shm_times_locked));
return True;
}
-
- if (read_only)
- return True;
/* Do a wait unlock on the first byte of the file */
if (fcntl_lock(smb_shm_fd, F_SETLKW, 0, 1, F_UNLCK) == False)
{
- DEBUG(0,("ERROR smb_shm_global_unlock : fcntl_lock failed with code %s\n",strerror(errno)));
+ DEBUG(0,("ERROR smb_shm_global_unlock : fcntl_lock failed with code %d\n",errno));
smb_shm_times_locked++;
return False;
}
@@ -155,148 +137,19 @@ static BOOL smb_shm_global_unlock(void)
}
-
-static void *smb_shm_offset2addr(int offset)
-{
- if (offset == 0 )
- return (void *)(0);
-
- if (!smb_shm_header_p)
- return (void *)(0);
-
- return (void *)((char *)smb_shm_header_p + offset );
-}
-
-static int smb_shm_addr2offset(void *addr)
-{
- if (!addr)
- return 0;
-
- if (!smb_shm_header_p)
- return 0;
-
- return (int)((char *)addr - (char *)smb_shm_header_p);
-}
-
-
-
-static int smb_shm_alloc(int size)
-{
- unsigned num_cells ;
- struct SmbShmBlockDesc *scanner_p;
- struct SmbShmBlockDesc *prev_p;
- struct SmbShmBlockDesc *new_p;
- int result_offset;
-
-
- if( !smb_shm_header_p )
- {
- /* not mapped yet */
- DEBUG(0,("ERROR smb_shm_alloc : shmem not mapped\n"));
- return 0;
- }
-
- smb_shm_global_lock();
-
- if( !smb_shm_header_p->consistent)
- {
- DEBUG(0,("ERROR smb_shm_alloc : shmem not consistent\n"));
- smb_shm_global_unlock();
- return 0;
- }
-
-
- /* calculate the number of cells */
- num_cells = (size + CellSize -1) / CellSize;
-
- /* set start of scan */
- prev_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off);
- scanner_p = prev_p ;
-
- /* scan the free list to find a matching free space */
- while ( ( scanner_p != EOList_Addr ) && ( scanner_p->size < num_cells ) )
- {
- prev_p = scanner_p;
- scanner_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(scanner_p->next);
- }
-
- /* at this point scanner point to a block header or to the end of the list */
- if ( scanner_p == EOList_Addr )
- {
- DEBUG(0,("ERROR smb_shm_alloc : alloc of %d bytes failed, no free space found\n",size));
- smb_shm_global_unlock();
- return (0);
- }
-
- /* going to modify shared mem */
- smb_shm_header_p->consistent = False;
-
- /* if we found a good one : scanner == the good one */
- if ( scanner_p->size <= num_cells + 2 )
- {
- /* there is no use in making a new one, it will be too small anyway
- * we will link out scanner
- */
- if ( prev_p == scanner_p )
- {
- smb_shm_header_p->first_free_off = scanner_p->next ;
- }
- else
- {
- prev_p->next = scanner_p->next ;
- }
- smb_shm_header_p->statistics.cells_free -= scanner_p->size;
- smb_shm_header_p->statistics.cells_used += scanner_p->size;
- }
- else
- {
- /* Make a new one */
- new_p = scanner_p + 1 + num_cells;
- new_p->size = scanner_p->size - num_cells - 1;
- new_p->next = scanner_p->next;
- scanner_p->size = num_cells;
- scanner_p->next = smb_shm_addr2offset(new_p);
-
- if ( prev_p != scanner_p )
- {
- prev_p->next = smb_shm_addr2offset(new_p) ;
- }
- else
- {
- smb_shm_header_p->first_free_off = smb_shm_addr2offset(new_p) ;
- }
- smb_shm_header_p->statistics.cells_free -= num_cells+1;
- smb_shm_header_p->statistics.cells_used += num_cells;
- smb_shm_header_p->statistics.cells_system += 1;
- }
-
- result_offset = smb_shm_addr2offset( &(scanner_p[1]) );
- scanner_p->next = SMB_SHM_NOT_FREE_OFF ;
-
- /* end modification of shared mem */
- smb_shm_header_p->consistent = True;
-
- DEBUG(6,("smb_shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset ));
-
- smb_shm_global_unlock();
- return ( result_offset );
-}
-
-
-
-
/*
* Function to create the hash table for the share mode entries. Called
* when smb shared memory is global locked.
*/
-static BOOL smb_shm_create_hash_table( unsigned int size )
+
+BOOL smb_shm_create_hash_table( unsigned int size )
{
- size *= sizeof(int);
+ size *= sizeof(smb_shm_offset_t);
smb_shm_global_lock();
smb_shm_header_p->userdef_off = smb_shm_alloc( size );
- if(smb_shm_header_p->userdef_off == 0)
+ if(smb_shm_header_p->userdef_off == NULL_OFFSET)
{
DEBUG(0,("smb_shm_create_hash_table: Failed to create hash table of size %d\n",size));
smb_shm_global_unlock();
@@ -318,13 +171,14 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth
int free_slot = -1;
int erased_slot;
- smb_shm_processes_fd = open(processreg_file,
- read_only?O_RDONLY:(O_RDWR|O_CREAT),
- SHM_FILE_MODE);
-
+#ifndef SECURE_SHARE_MODES
+ smb_shm_processes_fd = open(processreg_file, O_RDWR | O_CREAT, 0666);
+#else /* SECURE_SHARE_MODES */
+ smb_shm_processes_fd = open(processreg_file, O_RDWR | O_CREAT, 0600);
+#endif /* SECURE_SHARE_MODES */
if ( smb_shm_processes_fd < 0 )
{
- DEBUG(0,("ERROR smb_shm_register_process : processreg_file open failed with code %s\n",strerror(errno)));
+ DEBUG(0,("ERROR smb_shm_register_process : processreg_file open failed with code %d\n",errno));
return False;
}
@@ -354,7 +208,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth
}
if (nb_read < 0)
{
- DEBUG(0,("ERROR smb_shm_register_process : processreg_file read failed with code %s\n",strerror(errno)));
+ DEBUG(0,("ERROR smb_shm_register_process : processreg_file read failed with code %d\n",errno));
close(smb_shm_processes_fd);
return False;
}
@@ -366,7 +220,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth
lseek(smb_shm_processes_fd, free_slot, SEEK_SET);
if(write(smb_shm_processes_fd, &pid, sizeof(pid)) < 0)
{
- DEBUG(0,("ERROR smb_shm_register_process : processreg_file write failed with code %s\n",strerror(errno)));
+ DEBUG(0,("ERROR smb_shm_register_process : processreg_file write failed with code %d\n",errno));
close(smb_shm_processes_fd);
return False;
}
@@ -378,6 +232,7 @@ static BOOL smb_shm_register_process(char *processreg_file, pid_t pid, BOOL *oth
static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid)
{
+ int old_umask;
int smb_shm_processes_fd = -1;
int nb_read;
pid_t other_pid;
@@ -386,10 +241,12 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid)
BOOL found = False;
+ old_umask = umask(0);
smb_shm_processes_fd = open(processreg_file, O_RDWR);
+ umask(old_umask);
if ( smb_shm_processes_fd < 0 )
{
- DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file open failed with code %s\n",strerror(errno)));
+ DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file open failed with code %d\n",errno));
return False;
}
@@ -405,7 +262,7 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid)
erased_slot = lseek(smb_shm_processes_fd, seek_back, SEEK_CUR);
if(write(smb_shm_processes_fd, &other_pid, sizeof(other_pid)) < 0)
{
- DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file write failed with code %s\n",strerror(errno)));
+ DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file write failed with code %d\n",errno));
close(smb_shm_processes_fd);
return False;
}
@@ -416,7 +273,7 @@ static BOOL smb_shm_unregister_process(char *processreg_file, pid_t pid)
}
if (nb_read < 0)
{
- DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file read failed with code %s\n",strerror(errno)));
+ DEBUG(0,("ERROR smb_shm_unregister_process : processreg_file read failed with code %d\n",errno));
close(smb_shm_processes_fd);
return False;
}
@@ -486,7 +343,7 @@ static BOOL smb_shm_initialize(int size)
smb_shm_header_p->smb_shm_version = SMB_SHM_VERSION;
smb_shm_header_p->total_size = size;
smb_shm_header_p->first_free_off = AlignedHeaderSize;
- smb_shm_header_p->userdef_off = 0;
+ smb_shm_header_p->userdef_off = NULL_OFFSET;
first_free_block_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off);
first_free_block_p->next = EOList_Off;
@@ -524,7 +381,128 @@ static void smb_shm_solve_neighbors(struct SmbShmBlockDesc *head_p )
-static BOOL smb_shm_close( void )
+BOOL smb_shm_open( char *file_name, int size)
+{
+ int filesize;
+ BOOL created_new = False;
+ BOOL other_processes = True;
+ int old_umask;
+
+ DEBUG(5,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size));
+
+ old_umask = umask(0);
+#ifndef SECURE_SHARE_MODES
+ smb_shm_fd = open(file_name, O_RDWR | O_CREAT, 0666);
+#else /* SECURE_SHARE_MODES */
+ smb_shm_fd = open(file_name, O_RDWR | O_CREAT, 0600);
+#endif /* SECURE_SHARE_MODE */
+ umask(old_umask);
+ if ( smb_shm_fd < 0 )
+ {
+ DEBUG(0,("ERROR smb_shm_open : open failed with code %d\n",errno));
+ return False;
+ }
+
+ if (!smb_shm_global_lock())
+ {
+ DEBUG(0,("ERROR smb_shm_open : can't do smb_shm_global_lock\n"));
+ return False;
+ }
+
+ if( (filesize = lseek(smb_shm_fd, 0, SEEK_END)) < 0)
+ {
+ DEBUG(0,("ERROR smb_shm_open : lseek failed with code %d\n",errno));
+ smb_shm_global_unlock();
+ close(smb_shm_fd);
+ return False;
+ }
+
+ /* return the file offset to 0 to save on later seeks */
+ lseek(smb_shm_fd,0,SEEK_SET);
+
+ if (filesize == 0)
+ {
+ /* we just created a new one */
+ created_new = True;
+ }
+
+ /* to find out if some other process is already mapping the file,
+ we use a registration file containing the processids of the file mapping processes
+ */
+
+ /* construct processreg file name */
+ strcpy(smb_shm_processreg_name, file_name);
+ strcat(smb_shm_processreg_name, ".processes");
+
+ if (! smb_shm_register_process(smb_shm_processreg_name, getpid(), &other_processes))
+ {
+ smb_shm_global_unlock();
+ close(smb_shm_fd);
+ return False;
+ }
+
+ if (created_new || !other_processes)
+ {
+ /* we just created a new one, or are the first opener, lets set it size */
+ if( ftruncate(smb_shm_fd, size) <0)
+ {
+ DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %d\n",errno));
+ smb_shm_unregister_process(smb_shm_processreg_name, getpid());
+ smb_shm_global_unlock();
+ close(smb_shm_fd);
+ return False;
+ }
+
+ /* paranoia */
+ lseek(smb_shm_fd,0,SEEK_SET);
+
+ filesize = size;
+ }
+
+ if (size != filesize )
+ {
+ /* the existing file has a different size and we are not the first opener.
+ Since another process is still using it, we will use the file size */
+ DEBUG(0,("WARNING smb_shm_open : filesize (%d) != expected size (%d), using filesize\n",filesize,size));
+ size = filesize;
+ }
+
+ smb_shm_header_p = (struct SmbShmHeader *)mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, smb_shm_fd, 0);
+ /* WARNING, smb_shm_header_p can be different for different processes mapping the same file ! */
+ if (smb_shm_header_p == (struct SmbShmHeader *)(-1))
+ {
+ DEBUG(0,("ERROR smb_shm_open : mmap failed with code %d\n",errno));
+ smb_shm_unregister_process(smb_shm_processreg_name, getpid());
+ smb_shm_global_unlock();
+ close(smb_shm_fd);
+ return False;
+ }
+
+
+ if (created_new || !other_processes)
+ {
+ smb_shm_initialize(size);
+ /* Create the hash buckets for the share file entries. */
+ smb_shm_create_hash_table( lp_shmem_hash_size() );
+ }
+ else if (!smb_shm_validate_header(size) )
+ {
+ /* existing file is corrupt, samba admin should remove it by hand */
+ DEBUG(0,("ERROR smb_shm_open : corrupt shared mem file, remove it manually\n"));
+ munmap((caddr_t)smb_shm_header_p, size);
+ smb_shm_unregister_process(smb_shm_processreg_name, getpid());
+ smb_shm_global_unlock();
+ close(smb_shm_fd);
+ return False;
+ }
+
+ smb_shm_global_unlock();
+ return True;
+
+}
+
+
+BOOL smb_shm_close( void )
{
if(smb_shm_initialize_called == False)
@@ -536,7 +514,7 @@ static BOOL smb_shm_close( void )
if ((smb_shm_header_p != NULL) &&
(munmap((caddr_t)smb_shm_header_p, smb_shm_header_p->total_size) < 0))
{
- DEBUG(0,("ERROR smb_shm_close : munmap failed with code %s\n",strerror(errno)));
+ DEBUG(0,("ERROR smb_shm_close : munmap failed with code %d\n",errno));
}
smb_shm_global_lock();
@@ -555,8 +533,111 @@ static BOOL smb_shm_close( void )
return True;
}
+smb_shm_offset_t smb_shm_alloc(int size)
+{
+ unsigned num_cells ;
+ struct SmbShmBlockDesc *scanner_p;
+ struct SmbShmBlockDesc *prev_p;
+ struct SmbShmBlockDesc *new_p;
+ smb_shm_offset_t result_offset;
+
+
+ if( !smb_shm_header_p )
+ {
+ /* not mapped yet */
+ DEBUG(0,("ERROR smb_shm_alloc : shmem not mapped\n"));
+ return NULL_OFFSET;
+ }
+
+ smb_shm_global_lock();
-static BOOL smb_shm_free(int offset)
+ if( !smb_shm_header_p->consistent)
+ {
+ DEBUG(0,("ERROR smb_shm_alloc : shmem not consistent\n"));
+ smb_shm_global_unlock();
+ return NULL_OFFSET;
+ }
+
+
+ /* calculate the number of cells */
+ num_cells = (size + CellSize -1) / CellSize;
+
+ /* set start of scan */
+ prev_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(smb_shm_header_p->first_free_off);
+ scanner_p = prev_p ;
+
+ /* scan the free list to find a matching free space */
+ while ( ( scanner_p != EOList_Addr ) && ( scanner_p->size < num_cells ) )
+ {
+ prev_p = scanner_p;
+ scanner_p = (struct SmbShmBlockDesc *)smb_shm_offset2addr(scanner_p->next);
+ }
+
+ /* at this point scanner point to a block header or to the end of the list */
+ if ( scanner_p == EOList_Addr )
+ {
+ DEBUG(0,("ERROR smb_shm_alloc : alloc of %d bytes failed, no free space found\n",size));
+ smb_shm_global_unlock();
+ return (NULL_OFFSET);
+ }
+
+ /* going to modify shared mem */
+ smb_shm_header_p->consistent = False;
+
+ /* if we found a good one : scanner == the good one */
+ if ( scanner_p->size <= num_cells + 2 )
+ {
+ /* there is no use in making a new one, it will be too small anyway
+ * we will link out scanner
+ */
+ if ( prev_p == scanner_p )
+ {
+ smb_shm_header_p->first_free_off = scanner_p->next ;
+ }
+ else
+ {
+ prev_p->next = scanner_p->next ;
+ }
+ smb_shm_header_p->statistics.cells_free -= scanner_p->size;
+ smb_shm_header_p->statistics.cells_used += scanner_p->size;
+ }
+ else
+ {
+ /* Make a new one */
+ new_p = scanner_p + 1 + num_cells;
+ new_p->size = scanner_p->size - num_cells - 1;
+ new_p->next = scanner_p->next;
+ scanner_p->size = num_cells;
+ scanner_p->next = smb_shm_addr2offset(new_p);
+
+ if ( prev_p != scanner_p )
+ {
+ prev_p->next = smb_shm_addr2offset(new_p) ;
+ }
+ else
+ {
+ smb_shm_header_p->first_free_off = smb_shm_addr2offset(new_p) ;
+ }
+ smb_shm_header_p->statistics.cells_free -= num_cells+1;
+ smb_shm_header_p->statistics.cells_used += num_cells;
+ smb_shm_header_p->statistics.cells_system += 1;
+ }
+
+ result_offset = smb_shm_addr2offset( &(scanner_p[1]) );
+ scanner_p->next = SMB_SHM_NOT_FREE_OFF ;
+
+ /* end modification of shared mem */
+ smb_shm_header_p->consistent = True;
+
+ DEBUG(6,("smb_shm_alloc : request for %d bytes, allocated %d bytes at offset %d\n",size,scanner_p->size*CellSize,result_offset ));
+
+ smb_shm_global_unlock();
+ return ( result_offset );
+}
+
+
+
+BOOL smb_shm_free(smb_shm_offset_t offset)
{
struct SmbShmBlockDesc *header_p ; /* pointer to header of block to free */
struct SmbShmBlockDesc *scanner_p ; /* used to scan the list */
@@ -635,20 +716,52 @@ static BOOL smb_shm_free(int offset)
}
}
-static int smb_shm_get_userdef_off(void)
+smb_shm_offset_t smb_shm_get_userdef_off(void)
{
if (!smb_shm_header_p)
- return 0;
+ return NULL_OFFSET;
else
return smb_shm_header_p->userdef_off;
}
+BOOL smb_shm_set_userdef_off(smb_shm_offset_t userdef_off)
+{
+ if (!smb_shm_header_p)
+ return False;
+ else
+ smb_shm_header_p->userdef_off = userdef_off;
+ return True;
+}
+
+void * smb_shm_offset2addr(smb_shm_offset_t offset)
+{
+ if (offset == NULL_OFFSET )
+ return (void *)(0);
+
+ if (!smb_shm_header_p)
+ return (void *)(0);
+
+ return (void *)((char *)smb_shm_header_p + offset );
+}
+
+smb_shm_offset_t smb_shm_addr2offset(void *addr)
+{
+ if (!addr)
+ return NULL_OFFSET;
+
+ if (!smb_shm_header_p)
+ return NULL_OFFSET;
+
+ return (smb_shm_offset_t)((char *)addr - (char *)smb_shm_header_p);
+}
+
/*******************************************************************
Lock a particular hash bucket entry.
******************************************************************/
-static BOOL smb_shm_lock_hash_entry( unsigned int entry)
+
+BOOL smb_shm_lock_hash_entry( unsigned int entry)
{
- int start = (smb_shm_header_p->userdef_off + (entry * sizeof(int)));
+ int start = (smb_shm_header_p->userdef_off + (entry * sizeof(smb_shm_offset_t)));
if (smb_shm_fd < 0)
{
@@ -656,10 +769,16 @@ static BOOL smb_shm_lock_hash_entry( unsigned int entry)
return False;
}
+ if(entry >= lp_shmem_hash_size())
+ {
+ DEBUG(0,("ERROR smb_shm_lock_hash_entry : hash entry size too big (%d)\n", entry));
+ return False;
+ }
+
/* Do an exclusive wait lock on the 4 byte region mapping into this entry */
- if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(int), F_WRLCK) == False)
+ if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(smb_shm_offset_t), F_WRLCK) == False)
{
- DEBUG(0,("ERROR smb_shm_lock_hash_entry : fcntl_lock failed with code %s\n",strerror(errno)));
+ DEBUG(0,("ERROR smb_shm_lock_hash_entry : fcntl_lock failed with code %d\n",errno));
return False;
}
@@ -670,9 +789,10 @@ static BOOL smb_shm_lock_hash_entry( unsigned int entry)
/*******************************************************************
Unlock a particular hash bucket entry.
******************************************************************/
-static BOOL smb_shm_unlock_hash_entry( unsigned int entry )
+
+BOOL smb_shm_unlock_hash_entry( unsigned int entry )
{
- int start = (smb_shm_header_p->userdef_off + (entry * sizeof(int)));
+ int start = (smb_shm_header_p->userdef_off + (entry * sizeof(smb_shm_offset_t)));
if (smb_shm_fd < 0)
{
@@ -680,10 +800,16 @@ static BOOL smb_shm_unlock_hash_entry( unsigned int entry )
return False;
}
+ if(entry >= lp_shmem_hash_size())
+ {
+ DEBUG(0,("ERROR smb_shm_unlock_hash_entry : hash entry size too big (%d)\n", entry));
+ return False;
+ }
+
/* Do a wait lock on the 4 byte region mapping into this entry */
- if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(int), F_UNLCK) == False)
+ if (fcntl_lock(smb_shm_fd, F_SETLKW, start, sizeof(smb_shm_offset_t), F_UNLCK) == False)
{
- DEBUG(0,("ERROR smb_shm_unlock_hash_entry : fcntl_lock failed with code %s\n",strerror(errno)));
+ DEBUG(0,("ERROR smb_shm_unlock_hash_entry : fcntl_lock failed with code %d\n",errno));
return False;
}
@@ -694,7 +820,8 @@ static BOOL smb_shm_unlock_hash_entry( unsigned int entry )
/*******************************************************************
Gather statistics on shared memory usage.
******************************************************************/
-static BOOL smb_shm_get_usage(int *bytes_free,
+
+BOOL smb_shm_get_usage(int *bytes_free,
int *bytes_used,
int *bytes_overhead)
{
@@ -711,163 +838,6 @@ static BOOL smb_shm_get_usage(int *bytes_free,
return True;
}
-/*******************************************************************
-hash a number into a hash_entry
- ******************************************************************/
-static unsigned smb_shm_hash_size(void)
-{
- return SHMEM_HASH_SIZE;
-}
-
-static struct shmem_ops shmops = {
- smb_shm_close,
- smb_shm_alloc,
- smb_shm_free,
- smb_shm_get_userdef_off,
- smb_shm_offset2addr,
- smb_shm_addr2offset,
- smb_shm_lock_hash_entry,
- smb_shm_unlock_hash_entry,
- smb_shm_get_usage,
- smb_shm_hash_size,
-};
-
-/*******************************************************************
- open the shared memory
- ******************************************************************/
-struct shmem_ops *smb_shm_open(int ronly)
-{
- pstring file_name;
- int filesize;
- BOOL created_new = False;
- BOOL other_processes = True;
- int size = lp_shmem_size();
-
- read_only = ronly;
-
- pstrcpy(file_name,lp_lockdir());
- if (!directory_exist(file_name,NULL)) {
- if (read_only) return NULL;
- mkdir(file_name,0755);
- }
- trim_string(file_name,"","/");
- if (!*file_name) return(False);
- strcat(file_name, "/SHARE_MEM_FILE");
-
- DEBUG(5,("smb_shm_open : using shmem file %s to be of size %d\n",file_name,size));
-
- smb_shm_fd = open(file_name, read_only?O_RDONLY:(O_RDWR|O_CREAT),
- SHM_FILE_MODE);
-
- if ( smb_shm_fd < 0 )
- {
- DEBUG(0,("ERROR smb_shm_open : open failed with code %s\n",strerror(errno)));
- return NULL;
- }
-
- if (!smb_shm_global_lock())
- {
- DEBUG(0,("ERROR smb_shm_open : can't do smb_shm_global_lock\n"));
- return NULL;
- }
-
- if( (filesize = lseek(smb_shm_fd, 0, SEEK_END)) < 0)
- {
- DEBUG(0,("ERROR smb_shm_open : lseek failed with code %s\n",strerror(errno)));
- smb_shm_global_unlock();
- close(smb_shm_fd);
- return NULL;
- }
-
- /* return the file offset to 0 to save on later seeks */
- lseek(smb_shm_fd,0,SEEK_SET);
-
- if (filesize == 0)
- {
- /* we just created a new one */
- created_new = True;
- }
-
- /* to find out if some other process is already mapping the file,
- we use a registration file containing the processids of the file mapping processes
- */
-
- /* construct processreg file name */
- strcpy(smb_shm_processreg_name, file_name);
- strcat(smb_shm_processreg_name, ".processes");
-
- if (!read_only &&
- !smb_shm_register_process(smb_shm_processreg_name, getpid(), &other_processes))
- {
- smb_shm_global_unlock();
- close(smb_shm_fd);
- return NULL;
- }
-
- if (!read_only && (created_new || !other_processes))
- {
- /* we just created a new one, or are the first opener, lets set it size */
- if( ftruncate(smb_shm_fd, size) <0)
- {
- DEBUG(0,("ERROR smb_shm_open : ftruncate failed with code %s\n",strerror(errno)));
- smb_shm_unregister_process(smb_shm_processreg_name, getpid());
- smb_shm_global_unlock();
- close(smb_shm_fd);
- return NULL;
- }
-
- /* paranoia */
- lseek(smb_shm_fd,0,SEEK_SET);
-
- filesize = size;
- }
-
- if (size != filesize )
- {
- /* the existing file has a different size and we are not the first opener.
- Since another process is still using it, we will use the file size */
- DEBUG(0,("WARNING smb_shm_open : filesize (%d) != expected size (%d), using filesize\n",filesize,size));
- size = filesize;
- }
-
- smb_shm_header_p = (struct SmbShmHeader *)mmap(NULL, size,
- read_only?PROT_READ:
- (PROT_READ | PROT_WRITE),
- MAP_FILE | MAP_SHARED,
- smb_shm_fd, 0);
- /* WARNING, smb_shm_header_p can be different for different processes mapping the same file ! */
- if (smb_shm_header_p == (struct SmbShmHeader *)(-1))
- {
- DEBUG(0,("ERROR smb_shm_open : mmap failed with code %s\n",strerror(errno)));
- smb_shm_unregister_process(smb_shm_processreg_name, getpid());
- smb_shm_global_unlock();
- close(smb_shm_fd);
- return NULL;
- }
-
-
- if (!read_only && (created_new || !other_processes))
- {
- smb_shm_initialize(size);
- /* Create the hash buckets for the share file entries. */
- smb_shm_create_hash_table(SHMEM_HASH_SIZE);
- }
- else if (!smb_shm_validate_header(size) )
- {
- /* existing file is corrupt, samba admin should remove it by hand */
- DEBUG(0,("ERROR smb_shm_open : corrupt shared mem file, remove it manually\n"));
- munmap((caddr_t)smb_shm_header_p, size);
- smb_shm_unregister_process(smb_shm_processreg_name, getpid());
- smb_shm_global_unlock();
- close(smb_shm_fd);
- return NULL;
- }
-
- smb_shm_global_unlock();
- return &shmops;
-}
-
-
#else /* FAST_SHARE_MODES */
int shmem_dummy_procedure(void)
{return 0;}
diff --git a/source/locking/shmem_sysv.c b/source/locking/shmem_sysv.c
deleted file mode 100644
index 665cd8e7b4d..00000000000
--- a/source/locking/shmem_sysv.c
+++ /dev/null
@@ -1,706 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- Shared memory functions - SYSV IPC implementation
- Copyright (C) Andrew Tridgell 1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-
-#ifdef USE_SYSV_IPC
-
-extern int DEBUGLEVEL;
-
-#define SHMEM_KEY ((key_t)0x280267)
-#define SEMAPHORE_KEY (SHMEM_KEY+2)
-
-#define SHM_MAGIC 0x53484100
-#define SHM_VERSION 2
-
-#ifdef SHM_R
-#define IPC_PERMS ((SHM_R | SHM_W) | (SHM_R>>3) | (SHM_R>>6))
-#else
-#define IPC_PERMS 0644
-#endif
-
-#ifdef SECURE_SEMAPHORES
-/* secure semaphores are slow because we have to do a become_root()
- on every call! */
-#define SEMAPHORE_PERMS IPC_PERMS
-#else
-#define SEMAPHORE_PERMS 0666
-#endif
-
-#ifdef SEMMSL
-#define SHMEM_HASH_SIZE (SEMMSL-1)
-#else
-#define SHMEM_HASH_SIZE 63
-#endif
-
-#define MIN_SHM_SIZE 0x1000
-
-static int shm_id;
-static int sem_id;
-static int shm_size;
-static int hash_size;
-static int global_lock_count;
-
-struct ShmHeader {
- int shm_magic;
- int shm_version;
- int total_size; /* in bytes */
- BOOL consistent;
- int first_free_off;
- int userdef_off; /* a userdefined offset. can be used to store
- root of tree or list */
- struct { /* a cell is a range of bytes of sizeof(struct
- ShmBlockDesc) size */
- int cells_free;
- int cells_used;
- int cells_system; /* number of cells used as allocated
- block descriptors */
- } statistics;
-};
-
-#define SHM_NOT_FREE_OFF (-1)
-struct ShmBlockDesc
-{
- int next; /* offset of next block in the free list or
- SHM_NOT_FREE_OFF when block in use */
- int size; /* user size in BlockDescSize units */
-};
-
-#define EOList_Addr NULL
-#define EOList_Off (0)
-
-#define CellSize sizeof(struct ShmBlockDesc)
-
-/* HeaderSize aligned on a 8 byte boundary */
-#define AlignedHeaderSize ((sizeof(struct ShmHeader)+7) & ~7)
-
-static struct ShmHeader *shm_header_p = NULL;
-static BOOL shm_initialize_called = False;
-
-static int read_only;
-
-static BOOL sem_change(int i, int op)
-{
-#ifdef SECURE_SEMAPHORES
- extern struct current_user current_user;
- int became_root=0;
-#endif
- struct sembuf sb;
- int ret;
-
- if (read_only) return True;
-
-#ifdef SECURE_SEMAPHORES
- if (current_user.uid != 0) {
- become_root(0);
- became_root = 1;
- }
-#endif
-
- sb.sem_num = i;
- sb.sem_op = op;
- sb.sem_flg = 0;
-
- ret = semop(sem_id, &sb, 1);
-
- if (ret != 0) {
- DEBUG(0,("ERROR: sem_change(%d,%d) failed (%s)\n",
- i, op, strerror(errno)));
- }
-
-#ifdef SECURE_SEMAPHORES
- if (became_root) {
- unbecome_root(0);
- }
-#endif
-
- return ret == 0;
-}
-
-static BOOL global_lock(void)
-{
- global_lock_count++;
- if (global_lock_count == 1)
- return sem_change(0, -1);
- return True;
-}
-
-static BOOL global_unlock(void)
-{
- global_lock_count--;
- if (global_lock_count == 0)
- return sem_change(0, 1);
- return True;
-}
-
-static void *shm_offset2addr(int offset)
-{
- if (offset == 0 )
- return (void *)(0);
-
- if (!shm_header_p)
- return (void *)(0);
-
- return (void *)((char *)shm_header_p + offset);
-}
-
-static int shm_addr2offset(void *addr)
-{
- if (!addr)
- return 0;
-
- if (!shm_header_p)
- return 0;
-
- return (int)((char *)addr - (char *)shm_header_p);
-}
-
-
-static int shm_alloc(int size)
-{
- unsigned num_cells ;
- struct ShmBlockDesc *scanner_p;
- struct ShmBlockDesc *prev_p;
- struct ShmBlockDesc *new_p;
- int result_offset;
-
-
- if (!shm_header_p) {
- /* not mapped yet */
- DEBUG(0,("ERROR shm_alloc : shmem not mapped\n"));
- return 0;
- }
-
- global_lock();
-
- if (!shm_header_p->consistent) {
- DEBUG(0,("ERROR shm_alloc : shmem not consistent\n"));
- global_unlock();
- return 0;
- }
-
- /* calculate the number of cells */
- num_cells = (size + (CellSize-1)) / CellSize;
-
- /* set start of scan */
- prev_p = (struct ShmBlockDesc *)shm_offset2addr(shm_header_p->first_free_off);
- scanner_p = prev_p ;
-
- /* scan the free list to find a matching free space */
- while ((scanner_p != EOList_Addr) && (scanner_p->size < num_cells)) {
- prev_p = scanner_p;
- scanner_p = (struct ShmBlockDesc *)shm_offset2addr(scanner_p->next);
- }
-
- /* at this point scanner point to a block header or to the end of
- the list */
- if (scanner_p == EOList_Addr) {
- DEBUG(0,("ERROR shm_alloc : alloc of %d bytes failed\n",size));
- global_unlock();
- return (0);
- }
-
- /* going to modify shared mem */
- shm_header_p->consistent = False;
-
- /* if we found a good one : scanner == the good one */
- if (scanner_p->size > num_cells + 2) {
- /* Make a new one */
- new_p = scanner_p + 1 + num_cells;
- new_p->size = scanner_p->size - (num_cells + 1);
- new_p->next = scanner_p->next;
- scanner_p->size = num_cells;
- scanner_p->next = shm_addr2offset(new_p);
-
- shm_header_p->statistics.cells_free -= 1;
- shm_header_p->statistics.cells_system += 1;
- }
-
- /* take it from the free list */
- if (prev_p == scanner_p) {
- shm_header_p->first_free_off = scanner_p->next;
- } else {
- prev_p->next = scanner_p->next;
- }
- shm_header_p->statistics.cells_free -= scanner_p->size;
- shm_header_p->statistics.cells_used += scanner_p->size;
-
- result_offset = shm_addr2offset(&(scanner_p[1]));
- scanner_p->next = SHM_NOT_FREE_OFF;
-
- /* end modification of shared mem */
- shm_header_p->consistent = True;
-
- global_unlock();
-
- DEBUG(6,("shm_alloc : allocated %d bytes at offset %d\n",
- size,result_offset));
-
- return result_offset;
-}
-
-static void shm_solve_neighbors(struct ShmBlockDesc *head_p )
-{
- struct ShmBlockDesc *next_p;
-
- /* Check if head_p and head_p->next are neighbors and if so
- join them */
- if ( head_p == EOList_Addr ) return ;
- if ( head_p->next == EOList_Off ) return ;
-
- next_p = (struct ShmBlockDesc *)shm_offset2addr(head_p->next);
- if ((head_p + head_p->size + 1) == next_p) {
- head_p->size += next_p->size + 1; /* adapt size */
- head_p->next = next_p->next; /* link out */
-
- shm_header_p->statistics.cells_free += 1;
- shm_header_p->statistics.cells_system -= 1;
- }
-}
-
-
-static BOOL shm_free(int offset)
-{
- struct ShmBlockDesc *header_p; /* pointer to header of
- block to free */
- struct ShmBlockDesc *scanner_p; /* used to scan the list */
- struct ShmBlockDesc *prev_p; /* holds previous in the
- list */
-
- if (!shm_header_p) {
- /* not mapped yet */
- DEBUG(0,("ERROR shm_free : shmem not mapped\n"));
- return False;
- }
-
- global_lock();
-
- if (!shm_header_p->consistent) {
- DEBUG(0,("ERROR shm_free : shmem not consistent\n"));
- global_unlock();
- return False;
- }
-
- /* make pointer to header of block */
- header_p = ((struct ShmBlockDesc *)shm_offset2addr(offset) - 1);
-
- if (header_p->next != SHM_NOT_FREE_OFF) {
- DEBUG(0,("ERROR shm_free : bad offset (%d)\n",offset));
- global_unlock();
- return False;
- }
-
- /* find a place in the free_list to put the header in */
-
- /* set scanner and previous pointer to start of list */
- prev_p = (struct ShmBlockDesc *)
- shm_offset2addr(shm_header_p->first_free_off);
- scanner_p = prev_p ;
-
- while ((scanner_p != EOList_Addr) &&
- (scanner_p < header_p)) {
- /* while we didn't scan past its position */
- prev_p = scanner_p ;
- scanner_p = (struct ShmBlockDesc *)
- shm_offset2addr(scanner_p->next);
- }
-
- shm_header_p->consistent = False;
-
- DEBUG(6,("shm_free : freeing %d bytes at offset %d\n",
- header_p->size*CellSize,offset));
-
- if (scanner_p == prev_p) {
- shm_header_p->statistics.cells_free += header_p->size;
- shm_header_p->statistics.cells_used -= header_p->size;
-
- /* we must free it at the beginning of the list */
- shm_header_p->first_free_off = shm_addr2offset(header_p);
- /* set the free_list_pointer to this block_header */
-
- /* scanner is the one that was first in the list */
- header_p->next = shm_addr2offset(scanner_p);
- shm_solve_neighbors(header_p);
-
- shm_header_p->consistent = True;
- } else {
- shm_header_p->statistics.cells_free += header_p->size;
- shm_header_p->statistics.cells_used -= header_p->size;
-
- prev_p->next = shm_addr2offset(header_p);
- header_p->next = shm_addr2offset(scanner_p);
- shm_solve_neighbors(header_p) ;
- shm_solve_neighbors(prev_p) ;
-
- shm_header_p->consistent = True;
- }
-
- global_unlock();
- return True;
-}
-
-
-/*
- * Function to create the hash table for the share mode entries. Called
- * when smb shared memory is global locked.
- */
-static BOOL shm_create_hash_table(unsigned int hash_entries)
-{
- int size = hash_entries * sizeof(int);
-
- global_lock();
- shm_header_p->userdef_off = shm_alloc(size);
-
- if(shm_header_p->userdef_off == 0) {
- DEBUG(0,("shm_create_hash_table: Failed to create hash table of size %d\n",
- size));
- global_unlock();
- return False;
- }
-
- /* Clear hash buckets. */
- memset(shm_offset2addr(shm_header_p->userdef_off), '\0', size);
- global_unlock();
- return True;
-}
-
-
-static BOOL shm_validate_header(int size)
-{
- if(!shm_header_p) {
- /* not mapped yet */
- DEBUG(0,("ERROR shm_validate_header : shmem not mapped\n"));
- return False;
- }
-
- if(shm_header_p->shm_magic != SHM_MAGIC) {
- DEBUG(0,("ERROR shm_validate_header : bad magic\n"));
- return False;
- }
-
- if(shm_header_p->shm_version != SHM_VERSION) {
- DEBUG(0,("ERROR shm_validate_header : bad version %X\n",
- shm_header_p->shm_version));
- return False;
- }
-
- if(shm_header_p->total_size != size) {
- DEBUG(0,("ERROR shmem size mismatch (old = %d, new = %d)\n",
- shm_header_p->total_size,size));
- return False;
- }
-
- if(!shm_header_p->consistent) {
- DEBUG(0,("ERROR shmem not consistent\n"));
- return False;
- }
- return True;
-}
-
-
-static BOOL shm_initialize(int size)
-{
- struct ShmBlockDesc * first_free_block_p;
-
- DEBUG(5,("shm_initialize : initializing shmem size %d\n",size));
-
- if( !shm_header_p ) {
- /* not mapped yet */
- DEBUG(0,("ERROR shm_initialize : shmem not mapped\n"));
- return False;
- }
-
- shm_header_p->shm_magic = SHM_MAGIC;
- shm_header_p->shm_version = SHM_VERSION;
- shm_header_p->total_size = size;
- shm_header_p->first_free_off = AlignedHeaderSize;
- shm_header_p->userdef_off = 0;
-
- first_free_block_p = (struct ShmBlockDesc *)
- shm_offset2addr(shm_header_p->first_free_off);
- first_free_block_p->next = EOList_Off;
- first_free_block_p->size =
- (size - (AlignedHeaderSize+CellSize))/CellSize;
- shm_header_p->statistics.cells_free = first_free_block_p->size;
- shm_header_p->statistics.cells_used = 0;
- shm_header_p->statistics.cells_system = 1;
-
- shm_header_p->consistent = True;
-
- shm_initialize_called = True;
-
- return True;
-}
-
-static BOOL shm_close( void )
-{
- return True;
-}
-
-
-static int shm_get_userdef_off(void)
-{
- if (!shm_header_p)
- return 0;
- else
- return shm_header_p->userdef_off;
-}
-
-
-/*******************************************************************
- Lock a particular hash bucket entry.
- ******************************************************************/
-static BOOL shm_lock_hash_entry(unsigned int entry)
-{
- return sem_change(entry+1, -1);
-}
-
-/*******************************************************************
- Unlock a particular hash bucket entry.
- ******************************************************************/
-static BOOL shm_unlock_hash_entry(unsigned int entry)
-{
- return sem_change(entry+1, 1);
-}
-
-
-/*******************************************************************
- Gather statistics on shared memory usage.
- ******************************************************************/
-static BOOL shm_get_usage(int *bytes_free,
- int *bytes_used,
- int *bytes_overhead)
-{
- if(!shm_header_p) {
- /* not mapped yet */
- DEBUG(0,("ERROR shm_free : shmem not mapped\n"));
- return False;
- }
-
- *bytes_free = shm_header_p->statistics.cells_free * CellSize;
- *bytes_used = shm_header_p->statistics.cells_used * CellSize;
- *bytes_overhead = shm_header_p->statistics.cells_system * CellSize +
- AlignedHeaderSize;
-
- return True;
-}
-
-
-/*******************************************************************
-hash a number into a hash_entry
- ******************************************************************/
-static unsigned shm_hash_size(void)
-{
- return hash_size;
-}
-
-
-static struct shmem_ops shmops = {
- shm_close,
- shm_alloc,
- shm_free,
- shm_get_userdef_off,
- shm_offset2addr,
- shm_addr2offset,
- shm_lock_hash_entry,
- shm_unlock_hash_entry,
- shm_get_usage,
- shm_hash_size,
-};
-
-/*******************************************************************
- open the shared memory
- ******************************************************************/
-struct shmem_ops *sysv_shm_open(int ronly)
-{
- BOOL created_new = False;
- BOOL other_processes;
- struct shmid_ds shm_ds;
- struct semid_ds sem_ds;
- union semun su;
- int i;
- int pid;
-
- read_only = ronly;
-
- shm_size = lp_shmem_size();
-
- DEBUG(4,("Trying sysv shmem open of size %d\n", shm_size));
-
- /* first the semaphore */
- sem_id = semget(SEMAPHORE_KEY, 0, 0);
- if (sem_id == -1) {
- if (read_only) return NULL;
-
- hash_size = SHMEM_HASH_SIZE;
-
- while (hash_size > 1) {
- sem_id = semget(SEMAPHORE_KEY, hash_size+1,
- IPC_CREAT|IPC_EXCL| SEMAPHORE_PERMS);
- if (sem_id != -1 ||
- (errno != EINVAL && errno != ENOSPC)) break;
- hash_size -= 5;
- }
-
- if (sem_id == -1) {
- DEBUG(0,("Can't create or use semaphore %s\n",
- strerror(errno)));
- }
-
- if (sem_id != -1) {
- su.val = 1;
- for (i=0;i<hash_size+1;i++) {
- if (semctl(sem_id, i, SETVAL, su) != 0) {
- DEBUG(1,("Failed to init semaphore %d\n", i));
- }
- }
- }
- }
- if (shm_id == -1) {
- sem_id = semget(SEMAPHORE_KEY, 0, 0);
- }
- if (sem_id == -1) {
- DEBUG(0,("Can't create or use semaphore %s\n",
- strerror(errno)));
- return NULL;
- }
-
- su.buf = &sem_ds;
- if (semctl(sem_id, 0, IPC_STAT, su) != 0) {
- DEBUG(0,("ERROR shm_open : can't IPC_STAT\n"));
- }
- hash_size = sem_ds.sem_nsems-1;
-
- if (!read_only) {
- if (sem_ds.sem_perm.cuid != 0 || sem_ds.sem_perm.cgid != 0) {
- DEBUG(0,("ERROR: root did not create the semaphore\n"));
- return NULL;
- }
-
- if (semctl(sem_id, 0, GETVAL, su) == 0 &&
- !process_exists((pid=semctl(sem_id, 0, GETPID, su)))) {
- DEBUG(0,("WARNING: clearing global IPC lock set by dead process %d\n",
- pid));
- su.val = 1;
- if (semctl(sem_id, 0, SETVAL, su) != 0) {
- DEBUG(0,("ERROR: Failed to clear global lock\n"));
- }
- }
-
- sem_ds.sem_perm.mode = SEMAPHORE_PERMS;
- if (semctl(sem_id, 0, IPC_SET, su) != 0) {
- DEBUG(0,("ERROR shm_open : can't IPC_SET\n"));
- }
- }
-
-
-
- if (!global_lock())
- return NULL;
-
-
- for (i=1;i<hash_size+1;i++) {
- if (semctl(sem_id, i, GETVAL, su) == 0 &&
- !process_exists((pid=semctl(sem_id, i, GETPID, su)))) {
- DEBUG(1,("WARNING: clearing IPC lock %d set by dead process %d\n",
- i, pid));
- su.val = 1;
- if (semctl(sem_id, i, SETVAL, su) != 0) {
- DEBUG(0,("ERROR: Failed to clear IPC lock %d\n", i));
- }
- }
- }
-
- /* try to use an existing key */
- shm_id = shmget(SHMEM_KEY, shm_size, 0);
-
- /* if that failed then create one */
- if (shm_id == -1) {
- if (read_only) return NULL;
- while (shm_size > MIN_SHM_SIZE) {
- shm_id = shmget(SHMEM_KEY, shm_size,
- IPC_CREAT | IPC_EXCL | IPC_PERMS);
- if (shm_id != -1 ||
- (errno != EINVAL && errno != ENOSPC)) break;
- shm_size *= 0.8;
- }
- created_new = (shm_id != -1);
- }
-
- if (shm_id == -1) {
- DEBUG(0,("Can't create or use IPC area\n"));
- global_unlock();
- return NULL;
- }
-
-
- shm_header_p = (struct ShmHeader *)shmat(shm_id, 0,
- read_only?SHM_RDONLY:0);
- if ((int)shm_header_p == -1) {
- DEBUG(0,("Can't attach to IPC area\n"));
- global_unlock();
- return NULL;
- }
-
- /* to find out if some other process is already mapping the file,
- we use a registration file containing the processids of the file
- mapping processes */
- if (shmctl(shm_id, IPC_STAT, &shm_ds) != 0) {
- DEBUG(0,("ERROR shm_open : can't IPC_STAT\n"));
- }
-
- if (!read_only) {
- if (shm_ds.shm_perm.cuid != 0 || shm_ds.shm_perm.cgid != 0) {
- DEBUG(0,("ERROR: root did not create the shmem\n"));
- global_unlock();
- return NULL;
- }
- }
-
- shm_size = shm_ds.shm_segsz;
-
- other_processes = (shm_ds.shm_nattch > 1);
-
- if (!read_only && !other_processes) {
- memset((char *)shm_header_p, 0, shm_size);
- shm_initialize(shm_size);
- shm_create_hash_table(hash_size);
- DEBUG(3,("Initialised IPC area of size %d\n", shm_size));
- } else if (!shm_validate_header(shm_size)) {
- /* existing file is corrupt, samba admin should remove
- it by hand */
- DEBUG(0,("ERROR shm_open : corrupt IPC area - remove it!\n"));
- global_unlock();
- return NULL;
- }
-
- global_unlock();
- return &shmops;
-}
-
-
-
-#else
- int ipc_dummy_procedure(void)
-{return 0;}
-#endif
diff --git a/source/md4.h b/source/md4.h
new file mode 100644
index 00000000000..3f60d75fe3c
--- /dev/null
+++ b/source/md4.h
@@ -0,0 +1,58 @@
+/*
+ This code is from rfc1186.
+*/
+
+ /*
+ ** ********************************************************************
+ ** md4.h -- Header file for implementation of **
+ ** MD4 Message Digest Algorithm **
+ ** Updated: 2/13/90 by Ronald L. Rivest **
+ ** (C) 1990 RSA Data Security, Inc. **
+ ** ********************************************************************
+ */
+
+ /* MDstruct is the data structure for a message digest computation.
+ */
+ typedef struct {
+ unsigned int buffer[4]; /* Holds 4-word result of MD computation */
+ unsigned char count[8]; /* Number of bits processed so far */
+ unsigned int done; /* Nonzero means MD computation finished */
+ } MDstruct, *MDptr;
+
+ /* MDbegin(MD)
+
+
+
+ ** Input: MD -- an MDptr
+ ** Initialize the MDstruct prepatory to doing a message digest
+ ** computation.
+ */
+ extern void MDbegin();
+
+ /* MDupdate(MD,X,count)
+ ** Input: MD -- an MDptr
+ ** X -- a pointer to an array of unsigned characters.
+ ** count -- the number of bits of X to use (an unsigned int).
+ ** Updates MD using the first "count" bits of X.
+ ** The array pointed to by X is not modified.
+ ** If count is not a multiple of 8, MDupdate uses high bits of
+ ** last byte.
+ ** This is the basic input routine for a user.
+ ** The routine terminates the MD computation when count < 512, so
+ ** every MD computation should end with one call to MDupdate with a
+ ** count less than 512. Zero is OK for a count.
+ */
+ extern void MDupdate();
+
+ /* MDprint(MD)
+ ** Input: MD -- an MDptr
+ ** Prints message digest buffer MD as 32 hexadecimal digits.
+ ** Order is from low-order byte of buffer[0] to high-order byte
+ ** of buffer[3].
+ ** Each byte is printed with high-order hexadecimal digit first.
+ */
+ extern void MDprint();
+
+ /*
+ ** End of md4.h
+ */
diff --git a/source/nameannounce.c b/source/nameannounce.c
new file mode 100644
index 00000000000..b03a51021dd
--- /dev/null
+++ b/source/nameannounce.c
@@ -0,0 +1,562 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ SMB Version handling
+ Copyright (C) John H Terpstra 1995-1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Revision History:
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+*/
+
+#include "includes.h"
+
+#define TEST_CODE
+
+extern int DEBUGLEVEL;
+extern BOOL CanRecurse;
+
+extern struct in_addr ipzero;
+
+extern pstring myname;
+extern fstring myworkgroup;
+extern char **my_netbios_names;
+
+extern int ClientDGRAM;
+extern int ClientNMB;
+
+/* this is our domain/workgroup/server database */
+extern struct subnet_record *subnetlist;
+
+extern int updatecount;
+extern int workgroup_count;
+
+extern struct in_addr wins_ip;
+
+extern pstring scope;
+
+/****************************************************************************
+ send a announce request to the local net
+ **************************************************************************/
+void announce_request(struct work_record *work, struct in_addr ip)
+{
+ pstring outbuf;
+ char *p;
+
+ if (!work) return;
+
+ work->needannounce = True;
+
+ DEBUG(2,("sending announce request to %s for workgroup %s\n",
+ inet_ntoa(ip),work->work_group));
+
+ bzero(outbuf,sizeof(outbuf));
+ p = outbuf;
+ CVAL(p,0) = ANN_AnnouncementRequest;
+ p++;
+
+ CVAL(p,0) = work->token; /* (local) unique workgroup token id */
+ p++;
+ StrnCpy(p,myname,16);
+ strupper(p);
+ p = skip_string(p,1);
+
+ /* XXXX note: if we sent the announcement request to 0x1d instead
+ of 0x1e, then we could get the master browser to announce to
+ us instead of the members of the workgroup. wha-hey! */
+
+ send_mailslot_reply(False, BROWSE_MAILSLOT,ClientDGRAM,
+ outbuf,PTR_DIFF(p,outbuf),
+ myname,work->work_group,0x20,0x1e,ip,*iface_ip(ip));
+}
+
+
+/****************************************************************************
+ request an announcement
+ **************************************************************************/
+void do_announce_request(char *info, char *to_name, int announce_type,
+ int from,
+ int to, struct in_addr dest_ip)
+{
+ pstring outbuf;
+ char *p;
+
+ bzero(outbuf,sizeof(outbuf));
+ p = outbuf;
+ CVAL(p,0) = announce_type;
+ p++;
+
+ DEBUG(2,("sending announce type %d: info %s to %s - server %s(%x)\n",
+ announce_type, info, inet_ntoa(dest_ip),to_name,to));
+
+ StrnCpy(p,info,16);
+ strupper(p);
+ p = skip_string(p,1);
+
+ send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
+ outbuf,PTR_DIFF(p,outbuf),
+ myname,to_name,from,to,dest_ip,*iface_ip(dest_ip));
+}
+
+
+/****************************************************************************
+ find a server responsible for a workgroup, and sync browse lists
+ control ends up back here via response_name_query.
+ **************************************************************************/
+void sync_server(enum state_type state, char *serv_name, char *work_name,
+ int name_type,
+ struct subnet_record *d,
+ struct in_addr ip)
+{
+ /* with a domain master we can get the whole list (not local only list) */
+ BOOL local_only = (state != NAME_STATUS_DOM_SRV_CHK);
+
+ add_browser_entry(serv_name, name_type, work_name, 0, d, ip, local_only);
+
+ if (state == NAME_STATUS_DOM_SRV_CHK)
+ {
+ /* announce ourselves as a master browser to serv_name */
+ do_announce_request(myname, serv_name, ANN_MasterAnnouncement,
+ 0x20, 0, ip);
+ }
+}
+
+
+/****************************************************************************
+ send a host announcement packet
+ **************************************************************************/
+void do_announce_host(int command,
+ char *from_name, int from_type, struct in_addr from_ip,
+ char *to_name , int to_type , struct in_addr to_ip,
+ time_t announce_interval,
+ char *server_name, int server_type, char *server_comment)
+{
+ pstring outbuf;
+ char *p;
+
+ bzero(outbuf,sizeof(outbuf));
+ p = outbuf+1;
+
+ /* command type */
+ CVAL(outbuf,0) = command;
+
+ /* announcement parameters */
+ CVAL(p,0) = updatecount;
+ SIVAL(p,1,announce_interval*1000); /* ms - despite the spec */
+
+ StrnCpy(p+5,server_name,16);
+ strupper(p+5);
+
+ CVAL(p,21) = 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 */
+
+ pstrcpy(p+31,server_comment);
+ p += 31;
+ p = skip_string(p,1);
+
+ debug_browse_data(outbuf, PTR_DIFF(p,outbuf));
+
+ /* send the announcement */
+ send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,outbuf,
+ PTR_DIFF(p,outbuf),
+ from_name, to_name,
+ from_type, to_type,
+ to_ip, from_ip);
+}
+
+
+/****************************************************************************
+announce all samba's server entries as 'gone'.
+****************************************************************************/
+void announce_my_servers_removed(void)
+{
+ struct subnet_record *d;
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ struct work_record *work;
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ struct server_record *s;
+ for (s = work->serverlist; s; s = s->next)
+ {
+ if (!is_myname(s->serv.name)) continue;
+ announce_server(d, work, s->serv.name, s->serv.comment, 0, 0);
+ }
+ }
+ }
+}
+
+
+/****************************************************************************
+ announce a server entry
+ ****************************************************************************/
+void announce_server(struct subnet_record *d, struct work_record *work,
+ char *name, char *comment, time_t ttl, int server_type)
+{
+ /* domain type cannot have anything in it that might confuse
+ a client into thinking that the domain is in fact a server.
+ (SV_TYPE_SERVER_UNIX, for example)
+ */
+ uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
+ BOOL wins_iface = ip_equal(d->bcast_ip, wins_ip);
+
+ if(wins_iface)
+ {
+ DEBUG(0,("announce_server: error - announcement requested on WINS \
+interface for workgroup %s, name %s\n", work->work_group, name));
+ return;
+ }
+
+ /* Only do domain announcements if we are a master and it's
+ our name we're being asked to announce. */
+ if (AM_MASTER(work) && strequal(myname,name))
+ {
+ DEBUG(3,("sending local master announce to %s for %s(1e)\n",
+ inet_ntoa(d->bcast_ip),work->work_group));
+
+ do_announce_host(ANN_LocalMasterAnnouncement,
+ name , 0x00, d->myip,
+ work->work_group, 0x1e, d->bcast_ip,
+ ttl,
+ name, server_type, comment);
+
+ DEBUG(3,("sending domain announce to %s for %s\n",
+ inet_ntoa(d->bcast_ip),work->work_group));
+
+ /* XXXX should we do a domain-announce-kill? */
+ if (server_type != 0)
+ {
+ do_announce_host(ANN_DomainAnnouncement,
+ name , 0x00, d->myip,
+ MSBROWSE, 0x01, d->bcast_ip,
+ ttl,
+ work->work_group, server_type ? domain_type : 0,
+ name);
+ }
+ }
+ else
+ {
+ DEBUG(3,("sending host announce to %s for %s(1d)\n",
+ inet_ntoa(d->bcast_ip),work->work_group));
+
+ do_announce_host(ANN_HostAnnouncement,
+ name , 0x00, d->myip,
+ work->work_group, 0x1d, d->bcast_ip,
+ ttl,
+ name, server_type, comment);
+ }
+}
+
+/****************************************************************************
+ construct a host announcement unicast
+ **************************************************************************/
+void announce_host(time_t t)
+{
+ struct subnet_record *d;
+ pstring comment;
+ char *my_name;
+
+ StrnCpy(comment, lp_serverstring(), 43);
+
+ my_name = *myname ? myname : "NoName";
+
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ struct work_record *work;
+
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ uint32 stype = work->ServerType;
+ struct server_record *s;
+
+ /* must work on the code that does announcements at up to
+ 30 seconds later if a master browser sends us a request
+ announce.
+ */
+
+ if (work->needannounce) {
+ /* drop back to a max 3 minute announce - this is to prevent a
+ single lost packet from stuffing things up for too long */
+ work->announce_interval = MIN(work->announce_interval,
+ CHECK_TIME_MIN_HOST_ANNCE*60);
+ work->lastannounce_time = t - (work->announce_interval+1);
+ }
+
+ /* announce every minute at first then progress to every 12 mins */
+ if (work->lastannounce_time &&
+ (t - work->lastannounce_time) < work->announce_interval)
+ continue;
+
+ if (work->announce_interval < CHECK_TIME_MAX_HOST_ANNCE * 60)
+ work->announce_interval += 60;
+
+ work->lastannounce_time = t;
+
+ for (s = work->serverlist; s; s = s->next) {
+ if (is_myname(s->serv.name)) {
+ /* If we are any kind of browser or logon server, only
+ announce it for our primary name, not our aliases. */
+ if(!strequal(myname, s->serv.name))
+ stype &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_POTENTIAL_BROWSER|
+ SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER);
+ announce_server(d,work,s->serv.name,comment,
+ work->announce_interval,stype);
+ }
+ }
+
+ if (work->needannounce)
+ {
+ work->needannounce = False;
+ break;
+ /* sorry: can't do too many announces. do some more later */
+ }
+ }
+ }
+}
+
+/* Announce timer. Moved into global static so it can be reset
+ when a machine becomes a master browser. */
+static time_t announce_timer_last=0;
+
+/****************************************************************************
+ Reset the announce_timer so that a master browser announce will be done
+ immediately.
+ ****************************************************************************/
+
+void reset_announce_timer()
+{
+ announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60);
+}
+
+/****************************************************************************
+ announce myself as a master to all other domain master browsers.
+
+ this actually gets done in search_and_sync_workgroups() via the
+ NAME_QUERY_DOM_SRV_CHK command, if there is a response from the
+ name query initiated here. see response_name_query()
+ **************************************************************************/
+void announce_master(time_t t)
+{
+ struct subnet_record *d;
+ struct work_record *work;
+ BOOL am_master = False; /* are we a master of some sort? :-) */
+
+ if (!announce_timer_last) announce_timer_last = t;
+ if (t-announce_timer_last < CHECK_TIME_MST_ANNOUNCE * 60)
+ {
+ DEBUG(10,("announce_master: t (%d) - last(%d) < %d\n",
+ t, announce_timer_last, CHECK_TIME_MST_ANNOUNCE * 60 ));
+ return;
+ }
+
+ if(wins_subnet == NULL)
+ {
+ DEBUG(10,("announce_master: no wins subnet, ignoring.\n"));
+ return;
+ }
+
+ announce_timer_last = t;
+
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ struct work_record *work;
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ if (AM_MASTER(work))
+ {
+ am_master = True;
+ DEBUG(4,( "announce_master: am_master = %d for \
+workgroup %s\n", am_master, work->work_group));
+ }
+ }
+ }
+
+ if (!am_master) return; /* only proceed if we are a master browser */
+
+ /* Note that we don't do this if we are domain master browser
+ and that we *only* do this on the WINS subnet. */
+
+ /* Try and find our workgroup on the WINS subnet */
+ work = find_workgroupstruct(wins_subnet, myworkgroup, False);
+
+ if (work)
+ {
+ char *name;
+ int type;
+
+ {
+ /* assume that the domain master browser we want to sync
+ with is our own domain.
+ */
+ name = work->work_group;
+ type = 0x1b;
+ }
+
+ /* check the existence of a dmb for this workgroup, and if
+ one exists at the specified ip, sync with it and announce
+ ourselves as a master browser to it
+ */
+
+ if (!lp_wins_support() && *lp_wins_server() )
+ {
+ DEBUG(4, ("Local Announce: find %s<%02x> from WINS server %s\n",
+ name, type, lp_wins_server()));
+
+ queue_netbios_pkt_wins(ClientNMB,
+ NMB_QUERY,NAME_QUERY_DOM_SRV_CHK,
+ name, type, 0,0,0,
+ work->work_group,NULL,
+ ipzero, ipzero);
+ }
+ else if(lp_wins_support())
+ {
+ /* We are the WINS server - query ourselves for the dmb name. */
+
+ struct nmb_name netb_name;
+ struct subnet_record *d = 0;
+ struct name_record *nr = 0;
+
+ make_nmb_name(&netb_name, name, type, scope);
+
+ if ((nr = find_name_search(&d, &netb_name, FIND_WINS, ipzero)) == 0)
+ {
+ DEBUG(0, ("announce_master: unable to find domain master browser for workgroup %s \
+in our own WINS database.\n", work->work_group));
+ return;
+ }
+
+ /* Check that this isn't one of our addresses (ie. we are not domain master
+ ourselves) */
+ if(ismyip(nr->ip_flgs[0].ip) || ip_equal(nr->ip_flgs[0].ip, ipzero))
+ {
+ DEBUG(4, ("announce_master: domain master ip found (%s) for workgroup %s \
+is one of our interfaces.\n", work->work_group, inet_ntoa(nr->ip_flgs[0].ip) ));
+ return;
+ }
+
+ /* Issue a NAME_STATUS_DOM_SRV_CHK immediately - short circuit the
+ NAME_QUERY_DOM_SRV_CHK which is done only if we are talking to a
+ remote WINS server. */
+
+ DEBUG(4, ("announce_master: doing name status for %s<%02x> to domain master ip %s \
+for workgroup %s\n", name, type, inet_ntoa(nr->ip_flgs[0].ip), work->work_group ));
+
+ queue_netbios_packet(wins_subnet, ClientNMB,
+ NMB_STATUS,NAME_STATUS_DOM_SRV_CHK,
+ name, type, 0,0,0,
+ work->work_group,NULL,
+ False, False, nr->ip_flgs[0].ip, nr->ip_flgs[0].ip, 0);
+ }
+
+ }
+}
+
+/****************************************************************************
+ do all the "remote" announcements. These are used to put ourselves
+ on a remote browse list. They are done blind, no checking is done to
+ see if there is actually a browse master at the other end.
+ **************************************************************************/
+void announce_remote(time_t t)
+{
+ char *s,*ptr;
+ static time_t last_time = 0;
+ pstring s2;
+ struct in_addr addr;
+ char *comment,*workgroup;
+ int stype = lp_default_server_announce();
+
+ if (last_time && t < last_time + REMOTE_ANNOUNCE_INTERVAL)
+ return;
+
+ last_time = t;
+
+ s = lp_remote_announce();
+ if (!*s) return;
+
+ comment = lp_serverstring();
+ workgroup = myworkgroup;
+
+ for (ptr=s; next_token(&ptr,s2,NULL); )
+ {
+ /* the entries are of the form a.b.c.d/WORKGROUP with
+ WORKGROUP being optional */
+ char *wgroup;
+ int n;
+
+ wgroup = strchr(s2,'/');
+ if (wgroup) *wgroup++ = 0;
+ if (!wgroup || !*wgroup)
+ wgroup = workgroup;
+
+ addr = *interpret_addr2(s2);
+
+ /* Announce all our names including aliases */
+ for (n=0; my_netbios_names[n]; n++)
+ {
+ char *name = my_netbios_names[n];
+ do_announce_host(ANN_HostAnnouncement,name,0x20,*iface_ip(addr),
+ wgroup,0x1e,addr,
+ REMOTE_ANNOUNCE_INTERVAL,
+ name,stype,comment);
+ }
+ }
+}
+
+/****************************************************************************
+ do all the "remote" browse synchronisation stuff.
+ These are used to put our browse lists into remote browse lists.
+ **************************************************************************/
+void browse_sync_remote(time_t t)
+{
+ char *s,*ptr;
+ static time_t last_time = 0;
+ pstring s2;
+ struct in_addr addr;
+
+ if (last_time && t < last_time + REMOTE_ANNOUNCE_INTERVAL)
+ return;
+
+ last_time = t;
+
+ s = lp_remote_browse_sync();
+ if (!*s) return;
+
+ for (ptr=s; next_token(&ptr,s2,NULL); )
+ {
+ /* the entries are of the form a.b.c.d */
+ int n;
+
+ addr = *interpret_addr2(s2);
+
+ /* Announce all our names including aliases */
+ for (n=0; my_netbios_names[n]; n++)
+ {
+ char *name = my_netbios_names[n];
+ do_announce_request(name, "*", ANN_MasterAnnouncement, 0x20, 0, addr);
+ }
+ }
+}
diff --git a/source/nameannounce.doc b/source/nameannounce.doc
new file mode 100644
index 00000000000..e04a59209a1
--- /dev/null
+++ b/source/nameannounce.doc
@@ -0,0 +1,265 @@
+/*
+ Unix SMB/Netbios documentation.
+ Version 0.2
+ Copyright (C) Luke Leighton Andrew Tridgell 1996
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Document name: nameannounce.doc
+
+ Revision History:
+
+ 0.0 - 02jul96 : lkcl@pires.co.uk
+ created
+
+ 0.1 - 22jul96 : Andrew.Tridgell@anu.edu.au
+ tridge's comments on first revision
+
+ 0.2 - 05aug96 : lkcl@pires.co.uk
+ actioned tridge comments about pdc -> domain master
+ documented NAME_QUERY_ANNOUNCE_HOST
+
+*/
+
+
+this module deals with announcements: the sending of announcement requests
+and the sending of announcements either to refresh other servers' records
+or as a response to announcement requests.
+
+
+/*************************************************************************
+ announce_master()
+ *************************************************************************/
+
+this function is responsible for announcing samba as a master browser
+to all known domain masters.
+
+this announcement is sent out at CHECK_TIME_MST_ANNOUNCE minute
+intervals, only if samba is a master browser on one or more of
+its local interfaces.
+
+if no domain controller has been specified (lp_domain_controller())
+samba goes through its list of servers looking for domain master
+browsers. when it finds one (other than itself) it will either
+initiate a NAME_QUERY_PDC_SRV_CHK by broadcast or with a WINS
+server. this will result in a NAME_STATUS_PDC_SRV_CHK, which
+will result in a sync browse list and an announcement
+ANN_MasterAnnounce being sent (see sync_server()).
+
+if a domain controller has been specified, samba will search for
+a domain master browser for its workgroup (either by directed
+packet or by broadcast if it cannot resolve the domain controller
+name using DNS), which results in the same action as listed above.
+
+------------
+NOTE FROM TRIDGE:
+
+PDC in the above should really be DMB (domain master browser). They
+might be separate entities.
+
+I also propose a simpler scheme :-)
+
+If a DMB is not configured with lp_domain_controller() (perhaps
+renamed to lp_domain_master()?) then just don't do master
+announcements. Remember that most peoples networks are very simple and
+don't need DMB capabilities. Those that do need them will have more
+complex network topologies and they really need to choose themselves
+which box will act as the "hub" for netbios name resolution. Doing it
+via name queries will just lead to lag and propogation delays, because
+if two parts of the net choose different DMBs then the data will be
+very slow to propoogate.
+
+If a DMB is configured then just send the master announcemnt to that
+box! Thats all that needs to be done. Just send a udp 138 packet and
+forget it. If the recipient is indeed a DMB (as it should be if the
+config file is correct) then it should initiate a browse list sync
+with us at some later time, but that is take care of by smbd and nmbd
+doesn't even need to know it happened.
+
+Additionally, if a DMB is configured we need to sync our workgroup
+list and server list with them occasionally. Note that this is only
+time a non-DMB should do a browse sync, and it should only do it with
+a DMB. Essentially WAN based netbios is just a simple star. There is a
+DMB in the centre, and the individual master browsers for each subnet
+talk to it, but never talk to each other. If they start talking to
+each other then the network load will go as the square of the number
+of machines, which will result in meltdown :-)
+-------------
+
+
+/*************************************************************************
+ announce_host()
+ *************************************************************************/
+
+this complex-looking function is responsible for announcing samba's
+existence to other servers by broadcast. the actual announcement
+is carried out by announce_server().
+
+the time period between samba's announcement will stretch from one
+minute to twelve minutes by one minute. if samba has received an
+announce request from a master browser, then it should answer at
+any random interval between zero and thirty seconds after the
+request is received. this is to ensure that the master browser
+does not get overloaded with responses!
+
+
+/*************************************************************************
+ announce_server()
+ *************************************************************************/
+
+this function is responsible for sending announcement packets.
+these packets are received by other servers, which will then
+update their records accordingly: what services we have, our
+name, our comment field and our time to live (to name a few).
+
+if samba is a non-master then we need to see if there is a
+domain master (on a remote subnet) that we need to announce to
+it.
+
+if samba is not the WINS server (and it is using another
+WINS server) then we need to do a name query to the WINS
+server to ask it what the domain controller is. this is done
+using a samba 'state' NAME_QUERY_ANNOUNCE_HOST, which passes
+sufficient information on to be able to carry out the
+host announcement using a unicasted do_announce_host() if and
+when a reply comes back. if there is no reply to the name query,
+this is not necessarily an error - there may genuinely be no
+domain master currently up and running for samba's workgroup.
+
+if samba is a WINS server, then samba will need to look up the
+domain controller for its workgroup in its WINS records. an
+over-cautious samba could carry out a name query on that
+domain controller to make sure that it is alive and that samba's
+WINS records are up-to-date. in any event, it will send a unicast
+do_announce_host() to inform the domain master browser, if one
+exists, of samba's server status.
+
+if we are a master browser, then using do_announce_host() we
+must send a broadcast announcement on the local interface
+notifying members of that workgroup that we are their master
+browser, and another announcement indicating to all backup
+browsers and master browsers that we are a master browser.
+
+(note: if another master browser receives this broadcasted
+announcement and thinks that it is also the master browser
+for this workgroup, it stops being a master browser and forces
+an election).
+
+if we are not a master browser, then we send a broacast
+announcement notifying the master browser that we are a member
+of its workgroup, on the local interface.
+
+
+/*************************************************************************
+ remove_my_servers()
+ *************************************************************************/
+
+this function is responsible for informing other servers that
+samba is about to go down. it announces, on all subnets, that
+samba's time to live is zero and that it has no services.
+
+
+/*************************************************************************
+ do_announce_host()
+ *************************************************************************/
+
+this function is responsible for sending out an announcement
+MAILSLOT browse packet. it contains information such as the
+time to live, name of the server, services that the server
+offers etc.
+
+the format of this MAILSLOT browse packet is described in
+draft-heizer-cifs-v1-spec-00.txt 3.9.50.4.1 page 165-6.
+
+
+/*************************************************************************
+ announce_backup()
+ *************************************************************************/
+
+this function is responsible for getting master browsers and domain
+controllers to send us lists of backup servers. this is done by
+sending an ANN_GetBackupListReq browse mailslot.
+
+the local master browser, or domain master browser, should respond
+with an ANN_GetBackupListResp browse mailslot containing the list
+of backup servers.
+
+--------------
+NOTE FROM TRIDGE: I don't see why nmbd should ever send one of
+these. The only reason I can see for any part of Samba sending one of
+these is if we implement it in smbclient.
+
+This packet is used to request a list of backup master browsers from
+the master browser. It is used by clients (not servers!) to spread the
+browse load over more than one server. The only server that needs to
+know what the list of backups is is the master browser, and as it is
+also responsible for generating this list it will never ask anyone
+else for it.
+--------------
+
+
+/*************************************************************************
+ sync_server()
+ *************************************************************************/
+
+this function is responsible for initiating a sync browse list
+sequence and, if necessary, carrying out an ANN_MasterAnnouncement
+to the domain master browser (that we are also sync'ing browse lists
+with).
+
+see nameservresp.c:response_name_status_check().
+
+
+/*************************************************************************
+ announce_request()
+ *************************************************************************/
+
+this function is responsible for sending an announcement request to
+another server. this server should respond with an announcement.
+
+if the announce request is sent to WORKGROUP(0x1e) then members of
+the workgroup will respond (with ANN_HostAnnounce packets)
+
+if the announce request is sent to WORKGROUP(0x1d) then the master
+browser of the workgroup should respond (ANN_LocalMasterAnnounce).
+this is untested.
+
+if the announce request is sent to ^1^2__MSBROWSE__^2(0x1) then
+(and this is pure speculation), all backup browsers and master
+browsers should respond with ANN_DomainAnnounce packets.
+this is untested.
+
+-----------
+NOTE FROM TRIDGE:
+
+I had great trouble getting machines to actually respond to this
+packet. Either we have the format wrong or MS chose not to implement
+it.
+
+Not implementing it doesn't break anything, it just means a new master
+browser won't get a complete server list as quickly.
+
+Also note that this packet should be used as little as possible as it
+could easily cause meltdown if too many servers used it. Imagine a
+dozen samba servers on a net all sending this packet! You will get 244
+responses all within 30 seconds. now imagine 50 samba servers ....
+
+So I think we should restrict ourselves to sending this packet only if
+we are already the master browser for a workgroup. We could send a
+single "announce request" when we become the master, just to prime our
+server lists. From then on the normal announce cycles should take care
+of keeping it uptodate.
+-----------
+
diff --git a/source/namebrowse.c b/source/namebrowse.c
new file mode 100644
index 00000000000..ae5f00ce10e
--- /dev/null
+++ b/source/namebrowse.c
@@ -0,0 +1,246 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Revision History:
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+*/
+
+#include "includes.h"
+#include "smb.h"
+
+extern int ClientNMB;
+
+extern int DEBUGLEVEL;
+
+extern struct in_addr wins_ip;
+
+/* this is our browse master/backup cache database */
+static struct browse_cache_record *browserlist = NULL;
+
+
+/***************************************************************************
+ add a browser into the list
+ **************************************************************************/
+static void add_browse_cache(struct browse_cache_record *b)
+{
+ struct browse_cache_record *b2;
+
+ if (!browserlist)
+ {
+ browserlist = b;
+ b->prev = NULL;
+ b->next = NULL;
+ return;
+ }
+
+ for (b2 = browserlist; b2->next; b2 = b2->next) ;
+
+ b2->next = b;
+ b->next = NULL;
+ b->prev = b2;
+}
+
+
+/*******************************************************************
+ remove old browse entries
+ ******************************************************************/
+void expire_browse_cache(time_t t)
+{
+ struct browse_cache_record *b;
+ struct browse_cache_record *nextb;
+
+ /* expire old entries in the serverlist */
+ for (b = browserlist; b; b = nextb)
+ {
+ if (b->synced && b->sync_time < t)
+ {
+ DEBUG(3,("Removing dead cached browser %s\n",b->name));
+ nextb = b->next;
+
+ if (b->prev) b->prev->next = b->next;
+ if (b->next) b->next->prev = b->prev;
+
+ if (browserlist == b) browserlist = b->next;
+
+ free(b);
+ }
+ else
+ {
+ nextb = b->next;
+ }
+ }
+}
+
+/****************************************************************************
+ add a browser entry
+ ****************************************************************************/
+struct browse_cache_record *add_browser_entry(char *name, int type, char *wg,
+ time_t ttl, struct subnet_record *d,
+ struct in_addr ip, BOOL local)
+{
+ BOOL newentry=False;
+
+ struct browse_cache_record *b;
+
+ /* search for the entry: if it's already in the cache, update that entry */
+ for (b = browserlist; b; b = b->next)
+ {
+ if (ip_equal(ip,b->ip) && strequal(b->group, wg)) break;
+ }
+
+ if (b && b->synced)
+ {
+ /* entries get left in the cache for a while. this stops sync'ing too
+ often if the network is large */
+ DEBUG(4, ("browser %s %s %s already sync'd at time %d\n",
+ b->name, b->group, inet_ntoa(b->ip), b->sync_time));
+ return NULL;
+ }
+
+ if (!b)
+ {
+ newentry = True;
+ b = (struct browse_cache_record *)malloc(sizeof(*b));
+
+ if (!b) return(NULL);
+
+ bzero((char *)b,sizeof(*b));
+ }
+
+ /* update the entry */
+ ttl = time(NULL)+ttl;
+
+ StrnCpy(b->name ,name,sizeof(b->name )-1);
+ StrnCpy(b->group,wg ,sizeof(b->group)-1);
+ strupper(b->name);
+ strupper(b->group);
+
+ b->ip = ip;
+ b->type = type;
+ b->local = local; /* local server list sync or complete sync required */
+ b->subnet = d;
+
+ if (newentry || ttl < b->sync_time)
+ b->sync_time = ttl;
+
+ if (newentry)
+ {
+ b->synced = False;
+ add_browse_cache(b);
+
+ DEBUG(3,("Added cache entry %s %s(%2x) %s ttl %d\n",
+ wg, name, type, inet_ntoa(ip),ttl));
+ }
+ else
+ {
+ DEBUG(3,("Updated cache entry %s %s(%2x) %s ttl %d\n",
+ wg, name, type, inet_ntoa(ip),ttl));
+ }
+
+ return(b);
+}
+
+
+/****************************************************************************
+find a server responsible for a workgroup, and sync browse lists
+**************************************************************************/
+static void start_sync_browse_entry(struct browse_cache_record *b)
+{
+ struct subnet_record *d = b->subnet;
+ struct work_record *work;
+
+ /* Check panic conditions - these should not be true. */
+ if(b->subnet != wins_subnet) {
+ DEBUG(0,
+ ("start_sync_browse_entry: ERROR sync requested on non-WINS subnet.\n"));
+ return;
+ }
+
+ if (!(work = find_workgroupstruct(d, b->group, False))) {
+ DEBUG(0, ("start_sync_browse_entry: failed to get a \
+workgroup for a browse cache entry workgroup %s, server %s\n",
+ b->group, b->name));
+ return;
+ }
+
+ DEBUG(4, ("start_sync_browse_entry: Initiating %s sync with %s<0x20>, \
+workgroup %s\n",
+ b->local ? "local" : "remote", b->name, b->group));
+
+ /* first check whether the server we intend to sync with exists. if it
+ doesn't, the server must have died. o dear. */
+
+ /* see response_netbios_packet() or expire_netbios_response_entries() */
+ /* We cheat here by using the my_comment field of the response_record
+ struct as the workgroup name we are going to do the sync for.
+ This is because the reply packet doesn't include the workgroup, but
+ we need it when the reply comes back.
+ */
+ queue_netbios_packet(d,ClientNMB,NMB_QUERY,
+ b->local?NAME_QUERY_SYNC_LOCAL:NAME_QUERY_SYNC_REMOTE,
+ b->name,0x20,0,0,0,NULL,b->group,
+ False,False,b->ip,b->ip, 0);
+
+ b->synced = True;
+}
+
+
+/****************************************************************************
+ search through browser list for an entry to sync with
+ **************************************************************************/
+void do_browser_lists(time_t t)
+{
+ struct browse_cache_record *b;
+ static time_t last = 0;
+
+ if (t-last < 20)
+ {
+ DEBUG(9,("do_browser_lists: returning due to t(%d) - last(%d) < 20\n",
+ t, last));
+ return; /* don't do too many of these at once! */
+ /* XXXX equally this period should not be too long
+ the server may die in the intervening gap */
+ }
+ last = t;
+
+ /* pick any entry in the list, preferably one whose time is up */
+ for (b = browserlist; b && b->next; b = b->next)
+ {
+ if (b->sync_time < t && b->synced == False) break;
+ }
+
+ if (b && !b->synced)
+ {
+ /* sync with the selected entry then remove some dead entries */
+ DEBUG(4,("do_browser_lists: Initiating sync with %s, workgroup %s\n",
+ b->name, b->group));
+ start_sync_browse_entry(b);
+ }
+ else
+ {
+ DEBUG(9, ("do_browser_lists: no entries to sync.\n"));
+ }
+
+ expire_browse_cache(t - 60);
+}
+
diff --git a/source/namebrowse.doc b/source/namebrowse.doc
new file mode 100644
index 00000000000..82713d85708
--- /dev/null
+++ b/source/namebrowse.doc
@@ -0,0 +1,149 @@
+/*
+ Unix SMB/Netbios documentation.
+ Version 0.1
+ Copyright (C) Luke Leighton Andrew Tridgell 1996
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Document name: namebrowse.doc
+
+ Revision History:
+
+ 0.0 - 02jul96 : lkcl@pires.co.uk
+ created
+
+ 0.1 - 22jul96 Andrew.Tridgell@anu.edu.au
+ tridge's comments on first revision
+*/
+
+this module deals with queueing servers that samba must sync browse
+lists with. it will always issue a name query immediately before
+actually carrying out the NetServerEnum call, to ensure that time
+is not wasted by a remote server's failure.
+
+this module was created to minimise the amount of NetServerEnum calls
+that samba may be asked to perform, by maintaining the name of a server
+for up to a minute after the NetServerEnum call was issued, and
+disallowing further NetServerEnum calls to this remote server until
+the entry is removed.
+
+samba can ask for a NetServerEnum call to be issued to grab a remote
+server's list of servers and workgroups either in its capacity as
+a domain master browser, as a local master browser.
+
+samba does not deal with becoming a backup master browser properly
+at present.
+
+-------------
+NOTE FROM TRIDGE:
+
+Yes, samba can send these either in its capacity as a DMB or as a
+MB. There are only two situations:
+
+- If samba is a DMB then it should sync with the "local only" bit set
+with any master browser that has sent it a "master announce".
+
+- if samba is not a DMB then it can only sync with the DMB, and should
+not set the "local only" bit.
+
+Note that samba should never sync with other non-DMB servers when it
+is not a DMB.
+
+Try to do a sync under any other circumstances is dangerous without a
+multi-threaded nmbd. I have a print server at home that knows some SMB
+and NBT, but if you try to sync browse lists with it then it clogs up,
+and also clogs up nmbd while it times out the connection. If we
+follow the above two rules then we can't get into this sort of
+trouble as:
+
+- if we are a DMB and a master browser sends us a "master announce"
+then it is expecting to receive a NetServerEnum SMB connection soon,
+and must be capabable of handling it.
+
+- if we are not a DMB then we will only sync with the DMB, which must
+be capable of doing this stuff or things are really in a mess :-)
+--------------
+
+
+/*************************************************************************
+ do_browser_lists()
+ *************************************************************************/
+
+this function is responsible for finding an appropriate entry in the
+sync browser cache, initiating a name query (which results in a
+NetServerEnum call if there is a positive response), and then
+removing all entries that have been actioned and have been around
+for over a minute.
+
+
+/*************************************************************************
+ start_sync_browse_entry()
+ *************************************************************************/
+
+this function is responsible for initiating a name query. if a
+positive response is received, then this will result in a
+NetServerEnum api call.
+
+samba will only initiate this process if it is a master browser
+for this workgroup.
+
+-----------
+NOTE FROM TRIDGE:
+
+I'd actually prefer to skip the name query completely if we can
+resolve the DMBs name via gethostbyname(). For the name query to work
+we either have to have WINS working, or we need to know the broadcast
+address of the network that the DMB is on. This makes us too dependent
+on too many thing being right.
+
+If the gethostbyname() fails then sure, go for a normal name query,
+but if it works then we have saved ourselves a lot of trouble and
+gained a lot of robustness.
+
+This is best handled by a generic "resolve netbios name" routine that
+tries DNS first then resorts to WINS or bcast if that fails. It also
+needs to cache the results.
+-------------
+
+
+/*************************************************************************
+ add_browser_entry()
+ *************************************************************************/
+
+this function is responsible for adding a browser into the list of
+servers to sync browse lists with. if the server entry has already
+been added and syncing browse lists has already been initiated, it
+will not be added again.
+
+
+/*************************************************************************
+ expire_browse_cache()
+ *************************************************************************/
+
+this function is responsible for removing entries that have had the
+sync browse list initiated (whether that succeeded or not is beyond
+this function's scope) and have been in the cache for a while.
+
+
+/*************************************************************************
+ add_browse_entry()
+ *************************************************************************/
+
+this function is responsible for adding a new entry into the list
+of servers to sync browse lists with at some point in the near future.
+
+
+
+
diff --git a/source/namedbname.c b/source/namedbname.c
new file mode 100644
index 00000000000..51571d786a8
--- /dev/null
+++ b/source/namedbname.c
@@ -0,0 +1,601 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ 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.
+
+ Module name: namedbname.c
+
+ Revision History:
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+ 04 jul 96: lkcl@pires.co.uk
+ created module namedbname containing name database functions
+*/
+
+#include "includes.h"
+
+extern int DEBUGLEVEL;
+
+extern pstring scope;
+extern struct in_addr ipzero;
+extern struct in_addr wins_ip;
+extern BOOL updatedlists;
+
+extern struct subnet_record *subnetlist;
+
+#define WINS_LIST "wins.dat"
+
+uint16 nb_type = 0; /* samba's NetBIOS name type */
+
+
+/****************************************************************************
+ samba's NetBIOS name type
+
+ XXXX maybe functionality could be set: B, M, P or H name registration
+ and resolution could be set through nb_type. just a thought.
+ ****************************************************************************/
+void set_samba_nb_type(void)
+{
+ if (lp_wins_support() || (*lp_wins_server()))
+ {
+ nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */
+ }
+ else
+ {
+ nb_type = NB_BFLAG; /* samba is broadcast-only node type */
+ }
+}
+
+
+/****************************************************************************
+ true if two netbios names are equal
+****************************************************************************/
+BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2)
+{
+ return n1->name_type == n2->name_type &&
+ strequal(n1->name ,n2->name ) &&
+ strequal(n1->scope,n2->scope);
+}
+
+
+/****************************************************************************
+ true if the netbios name is ^1^2__MSBROWSE__^2^1
+
+ note: this name is registered if as a master browser or backup browser
+ you are responsible for a workgroup (when you announce a domain by
+ broadcasting on your local subnet, you announce it as coming from this
+ name: see announce_host()).
+
+ **************************************************************************/
+BOOL ms_browser_name(char *name, int type)
+{
+ return strequal(name,MSBROWSE) && type == 0x01;
+}
+
+
+/****************************************************************************
+ add a netbios name into the namelist
+ **************************************************************************/
+static void add_name(struct subnet_record *d, struct name_record *n)
+{
+ struct name_record *n2;
+
+ if (!d) return;
+
+ if (!d->namelist)
+ {
+ d->namelist = n;
+ n->prev = NULL;
+ n->next = NULL;
+ return;
+ }
+
+ for (n2 = d->namelist; n2->next; n2 = n2->next) ;
+
+ n2->next = n;
+ n->next = NULL;
+ n->prev = n2;
+
+ if((d == wins_subnet) && lp_wins_support())
+ updatedlists = True;
+}
+
+
+/****************************************************************************
+ remove a name from the namelist. The pointer must be an element just
+ retrieved
+ **************************************************************************/
+void remove_name(struct subnet_record *d, struct name_record *n)
+{
+ struct name_record *nlist;
+ if (!d) return;
+
+ nlist = d->namelist;
+
+ while (nlist && nlist != n) nlist = nlist->next;
+
+ if (nlist)
+ {
+ if (nlist->next) nlist->next->prev = nlist->prev;
+ if (nlist->prev) nlist->prev->next = nlist->next;
+
+ if(nlist == d->namelist)
+ d->namelist = nlist->next;
+
+ if(nlist->ip_flgs != NULL)
+ free(nlist->ip_flgs);
+ free(nlist);
+ }
+
+ if((d == wins_subnet) && lp_wins_support())
+ updatedlists = True;
+}
+
+
+/****************************************************************************
+ find a name in a namelist.
+ **************************************************************************/
+struct name_record *find_name(struct name_record *n,
+ struct nmb_name *name, int search)
+{
+ struct name_record *ret;
+
+ for (ret = n; ret; ret = ret->next)
+ {
+ if (name_equal(&ret->name,name))
+ {
+ /* self search: self names only */
+ if ((search&FIND_SELF) == FIND_SELF && ret->source != SELF)
+ {
+ continue;
+ }
+ DEBUG(9,("find_name: found name %s(%02x)\n",
+ name->name, name->name_type));
+ return ret;
+ }
+ }
+ DEBUG(9,("find_name: name %s(%02x) NOT FOUND\n", name->name,
+ name->name_type));
+ return NULL;
+}
+
+
+/****************************************************************************
+ find a name in the domain database namelist
+ search can be any of:
+ FIND_SELF - look exclusively for names the samba server has added for itself
+ FIND_LOCAL - look for names in the local subnet record.
+ FIND_WINS - look for names in the WINS record
+ **************************************************************************/
+struct name_record *find_name_search(struct subnet_record **d,
+ struct nmb_name *name,
+ int search, struct in_addr ip)
+{
+ if (d == NULL) return NULL; /* bad error! */
+
+ if (search & FIND_LOCAL) {
+ if (*d != NULL) {
+ struct name_record *n = find_name((*d)->namelist, name, search);
+ DEBUG(4,("find_name on local: %s %s search %x\n",
+ namestr(name),inet_ntoa(ip), search));
+ if (n) return n;
+ }
+ }
+
+ if (!(search & FIND_WINS)) return NULL;
+
+ /* find WINS subnet record. */
+ *d = wins_subnet;
+
+ if (*d == NULL) return NULL;
+
+ DEBUG(4,("find_name on WINS: %s %s search %x\n",
+ namestr(name),inet_ntoa(ip), search));
+ return find_name((*d)->namelist, name, search);
+}
+
+
+/****************************************************************************
+ dump a copy of the name table
+ **************************************************************************/
+void dump_names(void)
+{
+ struct name_record *n;
+ fstring fname, fnamenew;
+ time_t t = time(NULL);
+
+ FILE *f;
+
+ if(lp_wins_support() == False || wins_subnet == 0)
+ return;
+
+ fstrcpy(fname,lp_lockdir());
+ trim_string(fname,NULL,"/");
+ strcat(fname,"/");
+ strcat(fname,WINS_LIST);
+ fstrcpy(fnamenew,fname);
+ strcat(fnamenew,".");
+
+ f = fopen(fnamenew,"w");
+
+ if (!f)
+ {
+ DEBUG(3,("Can't open %s - %s\n",fnamenew,strerror(errno)));
+ return;
+ }
+
+ DEBUG(4,("Dump of WINS name table:\n"));
+
+ for (n = wins_subnet->namelist; n; n = n->next)
+ {
+ int i;
+
+ DEBUG(4,("%15s ", inet_ntoa(wins_subnet->bcast_ip)));
+ DEBUG(4,("%15s ", inet_ntoa(wins_subnet->mask_ip)));
+ DEBUG(4,("%-19s TTL=%ld ",
+ namestr(&n->name),
+ n->death_time?n->death_time-t:0));
+
+ for (i = 0; i < n->num_ips; i++)
+ {
+ DEBUG(4,("%15s NB=%2x source=%d",
+ inet_ntoa(n->ip_flgs[i].ip),
+ n->ip_flgs[i].nb_flags,n->source));
+
+ }
+ DEBUG(4,("\n"));
+
+ if (f && ((n->source == REGISTER) || (n->source == SELF)))
+ {
+ /* XXXX i have little imagination as to how to output nb_flags as
+ anything other than as a hexadecimal number :-) */
+
+ fprintf(f, "%s#%02x %ld ",
+ n->name.name,n->name.name_type, /* XXXX ignore scope for now */
+ n->death_time);
+
+ for (i = 0; i < n->num_ips; i++)
+ {
+ fprintf(f, "%s %2x%c ",
+ inet_ntoa(n->ip_flgs[i].ip),
+ n->ip_flgs[i].nb_flags, (n->source == REGISTER ? 'R' : 'S'));
+ }
+ fprintf(f, "\n");
+ }
+
+ }
+
+ fclose(f);
+ unlink(fname);
+ chmod(fnamenew,0644);
+ rename(fnamenew,fname);
+
+ DEBUG(3,("Wrote wins database %s\n",fname));
+}
+
+
+/****************************************************************************
+ load a netbios name database file
+
+ XXXX we cannot cope with loading Internet Group names, yet
+ ****************************************************************************/
+void load_netbios_names(void)
+{
+ struct subnet_record *d = wins_subnet;
+ fstring fname;
+
+ FILE *f;
+ pstring line;
+
+ if (!d) return;
+
+ fstrcpy(fname,lp_lockdir());
+ trim_string(fname,NULL,"/");
+ strcat(fname,"/");
+ strcat(fname,WINS_LIST);
+
+ f = fopen(fname,"r");
+
+ if (!f) {
+ DEBUG(2,("Can't open wins database file %s\n",fname));
+ return;
+ }
+
+ while (!feof(f))
+ {
+ pstring name_str, ip_str, ttd_str, nb_flags_str;
+
+ pstring name;
+ int type = 0;
+ unsigned int nb_flags;
+ time_t ttd;
+ struct in_addr ipaddr;
+
+ enum name_source source;
+
+ char *ptr;
+ int count = 0;
+
+ char *p;
+
+ if (!fgets_slash(line,sizeof(pstring),f)) continue;
+
+ if (*line == '#') continue;
+
+ ptr = line;
+
+ if (next_token(&ptr,name_str ,NULL)) ++count;
+ if (next_token(&ptr,ttd_str ,NULL)) ++count;
+ if (next_token(&ptr,ip_str ,NULL)) ++count;
+ if (next_token(&ptr,nb_flags_str,NULL)) ++count;
+
+ if (count <= 0) continue;
+
+ if (count != 4) {
+ DEBUG(0,("Ill formed wins line"));
+ DEBUG(0,("[%s]: name#type abs_time ip nb_flags\n",line));
+ continue;
+ }
+
+ /* Deal with SELF or REGISTER name encoding. Default is REGISTER
+ for compatibility with old nmbds. */
+ if(nb_flags_str[strlen(nb_flags_str)-1] == 'S')
+ {
+ DEBUG(5,("Ignoring SELF name %s\n", line));
+ continue;
+ }
+
+ if(nb_flags_str[strlen(nb_flags_str)-1] == 'R')
+ nb_flags_str[strlen(nb_flags_str)-1] = '\0';
+
+ /* netbios name. # divides the name from the type (hex): netbios#xx */
+ pstrcpy(name,name_str);
+
+ p = strchr(name,'#');
+
+ if (p) {
+ *p = 0;
+ sscanf(p+1,"%x",&type);
+ }
+
+ /* decode the netbios flags (hex) and the time-to-die (seconds) */
+ sscanf(nb_flags_str,"%x",&nb_flags);
+ sscanf(ttd_str,"%ld",&ttd);
+
+ ipaddr = *interpret_addr2(ip_str);
+
+ if (ip_equal(ipaddr,ipzero)) {
+ source = SELF;
+ }
+ else
+ {
+ source = REGISTER;
+ }
+
+ DEBUG(4, ("add WINS line: %s#%02x %ld %s %2x\n",
+ name,type, ttd, inet_ntoa(ipaddr), nb_flags));
+
+ /* add all entries that have 60 seconds or more to live */
+ if (ttd - 60 > time(NULL) || ttd == 0)
+ {
+ time_t t = (ttd?ttd-time(NULL):0) / 3;
+
+ /* add netbios entry read from the wins.dat file. IF it's ok */
+ add_netbios_entry(d,name,type,nb_flags,t,source,ipaddr,True,True);
+ }
+ }
+
+ fclose(f);
+}
+
+
+/****************************************************************************
+ remove an entry from the name list
+ ****************************************************************************/
+void remove_netbios_name(struct subnet_record *d,
+ char *name,int type, enum name_source source,
+ struct in_addr ip)
+{
+ struct nmb_name nn;
+ struct name_record *n;
+
+ make_nmb_name(&nn, name, type, scope);
+ n = find_name_search(&d, &nn, FIND_LOCAL, ip);
+
+ if (n && n->source == source) remove_name(d,n);
+}
+
+
+/****************************************************************************
+ add an entry to the name list.
+
+ this is a multi-purpose function.
+
+ it adds samba's own names in to its records on each interface, keeping a
+ record of whether it is a master browser, domain master, or WINS server.
+
+ it also keeps a record of WINS entries.
+
+ ****************************************************************************/
+struct name_record *add_netbios_entry(struct subnet_record *d,
+ char *name, int type, int nb_flags,
+ int ttl, enum name_source source, struct in_addr ip,
+ BOOL new_only,BOOL wins)
+{
+ struct name_record *n;
+ struct name_record *n2=NULL;
+ struct subnet_record *found_subnet = 0;
+ int search = 0;
+ BOOL self = (source == SELF);
+
+ /* add the name to the WINS list if the name comes from a directed query */
+ search |= wins ? FIND_WINS : FIND_LOCAL;
+
+ /* If it's a local search then we need to set the subnet
+ we are looking at. */
+ if(search & FIND_LOCAL)
+ found_subnet = d;
+
+ /* search for SELF names only */
+ search |= self ? FIND_SELF : 0;
+
+ if (!self)
+ {
+ if (!wins && (type != 0x1b))
+ {
+ /* the only broadcast (non-WINS) names we are adding are ours
+ (SELF) and Domain Master type names */
+ return NULL;
+ }
+ if(wins && (type == 0x1d))
+ {
+ /* Do not allow any 0x1d names to be registered in a WINS,
+ database although we return success for them.
+ */
+ return NULL;
+ }
+ }
+
+ n = (struct name_record *)malloc(sizeof(*n));
+ if (!n) return(NULL);
+
+ bzero((char *)n,sizeof(*n));
+
+ n->num_ips = 1; /* XXXX ONLY USE THIS FUNCTION FOR ONE ENTRY */
+ n->ip_flgs = (struct nmb_ip*)malloc(sizeof(*n->ip_flgs) * n->num_ips);
+ if (!n->ip_flgs)
+ {
+ free(n);
+ return NULL;
+ }
+
+ bzero((char *)n->ip_flgs, sizeof(*n->ip_flgs) * n->num_ips);
+
+ make_nmb_name(&n->name,name,type,scope);
+
+ if ((n2 = find_name_search(&found_subnet, &n->name, search, new_only?ipzero:ip)))
+ {
+ free(n->ip_flgs);
+ free(n);
+ if (new_only || (n2->source==SELF && source!=SELF)) return n2;
+ n = n2;
+ d = found_subnet;
+ }
+
+ if (ttl)
+ n->death_time = time(NULL)+ttl*3;
+ n->refresh_time = time(NULL)+GET_TTL(ttl);
+
+ /* XXXX only one entry expected with this function */
+ n->ip_flgs[0].ip = ip;
+ n->ip_flgs[0].nb_flags = nb_flags;
+
+ n->source = source;
+
+ if (!n2) add_name(d,n);
+
+ DEBUG(3,("Added netbios name %s at %s ttl=%d nb_flags=%2x to interface %s\n",
+ namestr(&n->name),inet_ntoa(ip),ttl,nb_flags,
+ ip_equal(d->bcast_ip, wins_ip) ? "WINS" : (char *)inet_ntoa(d->bcast_ip)));
+
+ return(n);
+}
+
+
+/*******************************************************************
+ expires old names in the namelist
+ ******************************************************************/
+void expire_names(time_t t)
+{
+ struct name_record *n;
+ struct name_record *next;
+ struct subnet_record *d;
+
+ /* expire old names */
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ {
+ for (n = d->namelist; n; n = next)
+ {
+ next = n->next;
+ if (n->death_time && n->death_time < t)
+ {
+ if (n->source == SELF)
+ {
+ DEBUG(3,("not expiring SELF name %s\n", namestr(&n->name)));
+ n->death_time += 300;
+ continue;
+ }
+ DEBUG(3,("Removing dead name %s\n", namestr(&n->name)));
+
+ if (n->prev) n->prev->next = n->next;
+ if (n->next) n->next->prev = n->prev;
+
+ if (d->namelist == n) d->namelist = n->next;
+
+ if(n->ip_flgs != NULL)
+ free(n->ip_flgs);
+ free(n);
+ }
+ }
+ }
+}
+
+
+/***************************************************************************
+ assume a WINS name is a dns name, and do a gethostbyname() on it.
+ ****************************************************************************/
+struct name_record *dns_name_search(struct nmb_name *question, int Time)
+{
+ int name_type = question->name_type;
+ char *qname = question->name;
+ BOOL dns_type = (name_type == 0x20 || name_type == 0);
+ struct in_addr dns_ip;
+
+ if (wins_subnet == NULL)
+ return NULL;
+
+ DEBUG(3,("Search for %s - ", namestr(question)));
+
+ /* only do DNS lookups if the query is for type 0x20 or type 0x0 */
+ if (!dns_type)
+ {
+ DEBUG(3,("types 0x20 0x0 only: name not found\n"));
+ return NULL;
+ }
+
+ /* look it up with DNS */
+ dns_ip.s_addr = interpret_addr(qname);
+
+ if (!dns_ip.s_addr)
+ {
+ /* no luck with DNS. We could possibly recurse here XXXX */
+ DEBUG(3,("not found. no recursion.\n"));
+ /* add the fail to WINS cache of names. give it 1 hour in the cache */
+ add_netbios_entry(wins_subnet,qname,name_type,NB_ACTIVE,60*60,DNSFAIL,dns_ip,
+ True, True);
+ return NULL;
+ }
+
+ DEBUG(3,("found with DNS: %s\n", inet_ntoa(dns_ip)));
+
+ /* add it to our WINS cache of names. give it 2 hours in the cache */
+ return add_netbios_entry(wins_subnet,qname,name_type,NB_ACTIVE,2*60*60,DNS,dns_ip,
+ True,True);
+}
diff --git a/source/namedbname.doc b/source/namedbname.doc
new file mode 100644
index 00000000000..34a791dbb89
--- /dev/null
+++ b/source/namedbname.doc
@@ -0,0 +1,182 @@
+/*
+ Unix SMB/Netbios documentation.
+ Version 0.0
+ Copyright (C) Luke Leighton Andrew Tridgell 1996
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Document name: namedbname.doc
+
+ Revision History:
+
+ 0.0 - 02jul96 : lkcl@pires.co.uk
+ created
+*/
+
+this module deals with the NetBIOS name database for samba. it deals
+directly with adding, removing, finding, loading and saving of names.
+
+/*************************************************************************
+ search_for_name()
+ *************************************************************************/
+
+this function is responsible for finding a name in the appropriate part
+of samba's NetBIOS name database. if the name cannot be found, then it
+should look the name up using DNS. later modifications will be to
+forward the request on to another WINS server, should samba not be able
+to find out about the requested name (this will be implemented through
+issuing a new type of samba 'state').
+
+the name is first searched for in the NetBIOS cache. if it cannot be
+found, then it if the name looks like it's a server-type name (0x20
+0x0 or 0x1b) then DNS is used to look for the name.
+
+if DNS fails, then a record of this failure is kept. if it succeeds, then
+a new NetBIOS entry is added.
+
+the successfully found name is returned. on failure, NULL is returned.
+
+
+/*************************************************************************
+ expire_names()
+ *************************************************************************/
+
+this function is responsible for removing old NetBIOS names from its
+database. no further action is required.
+
+for over-zealous WINS systems, the use of query_refresh_names() is
+recommended. this function initiates polling of hosts that have
+registered with samba in its capacity as a WINS server. an alternative
+means to achieve the same end as query_refresh_names() is to
+reduce the time to live when the name is registered with samba,
+except that in this instance the responsibility for refreshing the
+name is with the owner of the name, not the server with which the name
+is registered.
+
+
+/*************************************************************************
+ add_netbios_entry()
+ *************************************************************************/
+
+this function is responsible for adding or updating a NetBIOS name
+in the database. into the local interface records, the only names
+that will be added are those of domain master browsers and
+samba's own names. into the WINS records, all names are added.
+
+the name to be added / updated will be looked up in the records.
+if it is found, then we will not overwrite the entry if the flag
+'newonly' is True, or if the name is being added as a non-SELF
+(non-samba) name and the records indicate that samba owns the
+name.
+
+otherwise, the name is added or updated with the new details.
+
+
+/*************************************************************************
+ remove_netbios_entry()
+ *************************************************************************/
+
+this function is responsible for removing a NetBIOS entry from
+the database. the name is searched for in the records using
+find_name_search(). if the ip is zero, then the ip is ignored.
+
+the name is removed if the expected source (e.g SELF, REGISTER)
+matches that in the database.
+
+
+/*************************************************************************
+ load_netbios_names()
+ *************************************************************************/
+
+this function is responsible for loading any NetBIOS names that samba,
+in its WINS capacity, has written out to disk. all the relevant details
+are recorded in this file, including the time-to-live. should the
+time left to live be small, the name is not added back in to samba's
+WINS database.
+
+
+/*************************************************************************
+ dump_names()
+ *************************************************************************/
+
+this function is responsible for outputting NetBIOS names in two formats.
+firstly, as debugging information, and secondly, all names that have been
+registered with samba in its capacity as a WINS server are written to
+disk.
+
+writing all WINS names allows two things. firstly, if samba's NetBIOS
+daemon dies or is terminated, on restarting the daemon most if not all
+of the registered WINS names will be preserved (which is a good reason
+why query_netbios_names() should be used).
+
+
+/*************************************************************************
+ find_name_search()
+ *************************************************************************/
+
+this function is a wrapper around find_name(). find_name_search() can
+be told whether to search for the name in a local subnet structure or
+in the WINS database. on top of this, it can be told to search only
+for samba's SELF names.
+
+if it finds the name in the WINS database, it will set the subnet_record
+and also return the name it finds.
+
+
+/*************************************************************************
+ find_name()
+ *************************************************************************/
+
+this function is a low-level search function that searches a single
+interface's NetBIOS records for a name. if the ip to be found is
+zero then the ip address is ignored. this is to enable a name to
+be found without knowing its ip address, and also to find the exact
+name if a large number of group names are added with different ip
+addresses.
+
+
+/*************************************************************************
+ remove_name()
+ *************************************************************************/
+
+this function is responsible for removing a specific NetBIOS entry
+from a subnet list's records. only if the pointer to the entry is
+in the list will the name be removed.
+
+
+/*************************************************************************
+ add_name()
+ *************************************************************************/
+
+this function is responsible for adding a NetBIOS entry into a
+subnet list's records.
+
+
+/*************************************************************************
+ ms_browser_name()
+ *************************************************************************/
+
+this function returns True if the NetBIOS name passed to it is
+^1^2__MSBROWSE__^2^1
+
+
+/*************************************************************************
+ name_equal()
+ *************************************************************************/
+
+this function returns True if the two NetBIOS names passed to it
+match in name, type and scope: the NetBIOS names are equal.
+
+
diff --git a/source/namedbresp.c b/source/namedbresp.c
new file mode 100644
index 00000000000..c8a31a6c79b
--- /dev/null
+++ b/source/namedbresp.c
@@ -0,0 +1,168 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios library routines
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ 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.
+
+ Module name: namedbresp.c
+
+*/
+
+#include "includes.h"
+
+extern int ClientNMB;
+extern int ClientDGRAM;
+
+extern struct subnet_record *subnetlist;
+
+extern int DEBUGLEVEL;
+
+extern pstring scope;
+extern pstring myname;
+extern struct in_addr ipzero;
+
+int num_response_packets = 0;
+
+/***************************************************************************
+ add an expected response record into the list
+ **************************************************************************/
+void add_response_record(struct subnet_record *d,
+ struct response_record *n)
+{
+ struct response_record *n2;
+
+ if (!d) return;
+
+ num_response_packets++; /* count of total number of packets still around */
+
+ DEBUG(4,("adding response record id:%d num_records:%d\n",
+ n->response_id, num_response_packets));
+
+ if (!d->responselist)
+ {
+ d->responselist = n;
+ n->prev = NULL;
+ n->next = NULL;
+ return;
+ }
+
+ for (n2 = d->responselist; n2->next; n2 = n2->next) ;
+
+ n2->next = n;
+ n->next = NULL;
+ n->prev = n2;
+}
+
+
+/***************************************************************************
+ remove an expected response record from the list
+ **************************************************************************/
+void remove_response_record(struct subnet_record *d,
+ struct response_record *n)
+{
+ if (!d) return;
+
+ if (n->prev) n->prev->next = n->next;
+ if (n->next) n->next->prev = n->prev;
+
+ if (d->responselist == n) d->responselist = n->next;
+
+ free(n);
+
+ num_response_packets--; /* count of total number of packets still around */
+}
+
+
+/****************************************************************************
+ create a name query response record
+ **************************************************************************/
+struct response_record *make_response_queue_record(enum state_type state,
+ int id,uint16 fd,
+ int quest_type, char *name,int type, int nb_flags, time_t ttl,
+ int server_type, char *my_name, char *my_comment,
+ BOOL bcast,BOOL recurse,
+ struct in_addr send_ip, struct in_addr reply_to_ip,
+ int reply_id)
+{
+ struct response_record *n;
+
+ if (!name || !name[0]) return NULL;
+
+ if (!(n = (struct response_record *)malloc(sizeof(*n))))
+ return(NULL);
+
+ bzero((char *)n, sizeof(*n));
+
+ n->response_id = id;
+ n->state = state;
+ n->fd = fd;
+ n->quest_type = quest_type;
+ make_nmb_name(&n->name, name, type, scope);
+ n->nb_flags = nb_flags;
+ n->ttl = ttl;
+ n->server_type = server_type;
+ n->bcast = bcast;
+ n->recurse = recurse;
+ n->send_ip = send_ip;
+ n->reply_to_ip = reply_to_ip;
+ n->reply_id = reply_id;
+ if(my_name)
+ StrnCpy(n->my_name, my_name, sizeof(n->my_name)-1);
+ else
+ *n->my_name = 0;
+ if(my_comment)
+ StrnCpy(n->my_comment, my_comment, sizeof(n->my_comment)-1);
+ else
+ *n->my_comment = 0;
+ n->repeat_interval = 1; /* XXXX should be in ms */
+ n->repeat_count = 3; /* 3 retries */
+ n->repeat_time = time(NULL) + n->repeat_interval; /* initial retry time */
+
+ n->num_msgs = 0;
+
+ return n;
+}
+
+
+/****************************************************************************
+ find a response in a subnet's name query response list.
+ **************************************************************************/
+struct response_record *find_response_record(struct subnet_record **d,
+ uint16 id)
+{
+ struct response_record *n;
+
+ if (!d) return NULL;
+
+ for ((*d) = FIRST_SUBNET; (*d); (*d) = NEXT_SUBNET_INCLUDING_WINS(*d))
+ {
+ for (n = (*d)->responselist; n; n = n->next)
+ {
+ if (n->response_id == id) {
+ DEBUG(4, ("found response record on %s: %d\n",
+ inet_ntoa((*d)->bcast_ip), id));
+ return n;
+ }
+ }
+ }
+
+ *d = NULL;
+
+ return NULL;
+}
+
+
diff --git a/source/namedbresp.doc b/source/namedbresp.doc
new file mode 100644
index 00000000000..a54c0702758
--- /dev/null
+++ b/source/namedbresp.doc
@@ -0,0 +1,100 @@
+/*
+ Unix SMB/Netbios documentation.
+ Version 0.1
+ Copyright (C) Luke Leighton Andrew Tridgell 1996
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Document name: namedbresp.doc
+
+ Revision History:
+
+ 0.0 - 02jul96 : lkcl@pires.co.uk
+ created
+
+ 0.1 - 22jul96 Andrew.Tridgell@anu.edu.au
+ tridge's comments on first revision
+*/
+
+module namedbresp deals with the maintenance of the list of expected
+responses - creating, finding and removal.
+
+module nameresp deals with the initial transmission, re-transmission
+and time-out of netbios response records.
+
+
+/*************************************************************************
+ find_response_record()
+ *************************************************************************/
+
+this function is responsible for matching the unique response transaction
+id with an expected response record. as a side-effect of this search,
+it will find the subnet (or the WINS pseudo-subnet) that samba expected
+the response to come from.
+
+
+/*************************************************************************
+ make_response_queue_record()
+ *************************************************************************/
+
+this function is responsible for creating a response record, which will
+be queued awaiting a response.
+
+the number of retries is set to 3, and the retry period set to 1 second.
+if no response is received, then the packet is re-transmitted, which is
+why so much information is stored in the response record.
+
+the number of expected responses queued is kept, so listen_for_packets()
+knows it must time-out after 1 second if one or more responses are
+expected.
+
+
+/*************************************************************************
+ remove_response_record()
+ *************************************************************************/
+
+this function is responsible for removing a response record from the
+expected response queue. the number of expected responses is decreased.
+
+
+/*************************************************************************
+ add_response_record()
+ *************************************************************************/
+
+this function is responsible for adding the response record created by
+make_response_queue_record() into the appropriate response record queue.
+
+
+-----------------
+NOTE FROM TRIDGE:
+
+namedbresp.c is interesting because it implements a novel way of
+getting most of the advantages of a multi-threaded nmbd daemon without
+the portability problems.
+
+The NBT specs (rfc1001/1002) talk about the 16 bit IDs in the packets
+as being used to ensure that packets are unique, and to stop packets
+from being confused. It suggests incrementing the ID by 1 each time.
+
+Instead Luke uses these IDs to identify individual threads of control
+in nmbd. So when nmbd sends out a NBT packet as part of some complex
+processing, it adds to a linked list the information required to
+continue the processing when the reply comes in (or it times
+out). When a reply arrives this list can be searched to find the
+matching query and the next step in the processing can be carried out.
+
+This is really good stuff, and allows for much more complex behaviour
+than was possible with the old nmbd.
+----------------
diff --git a/source/namedbserver.c b/source/namedbserver.c
new file mode 100644
index 00000000000..9223cb6ce6a
--- /dev/null
+++ b/source/namedbserver.c
@@ -0,0 +1,212 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Revision History:
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+ 04 jul 96: lkcl@pires.co.uk
+ created module namedbserver containing server database functions
+
+*/
+
+#include "includes.h"
+#include "smb.h"
+
+extern int ClientNMB;
+extern int ClientDGRAM;
+
+extern int DEBUGLEVEL;
+
+extern pstring myname;
+extern fstring myworkgroup;
+
+/* this is our domain/workgroup/server database */
+extern struct subnet_record *subnetlist;
+
+extern BOOL updatedlists;
+
+
+/*******************************************************************
+ expire old servers in the serverlist
+ time of -1 indicates everybody dies except those with time of 0
+ remove_all_servers indicates everybody dies.
+ ******************************************************************/
+void remove_old_servers(struct work_record *work, time_t t,
+ BOOL remove_all)
+{
+ struct server_record *s;
+ struct server_record *nexts;
+
+ /* expire old entries in the serverlist */
+ for (s = work->serverlist; s; s = nexts)
+ {
+ if (remove_all || (s->death_time && (t == -1 || s->death_time < t)))
+ {
+ DEBUG(3,("Removing dead server %s\n",s->serv.name));
+ updatedlists = True;
+ nexts = s->next;
+
+ if (s->prev) s->prev->next = s->next;
+ if (s->next) s->next->prev = s->prev;
+
+ if (work->serverlist == s)
+ work->serverlist = s->next;
+
+ free(s);
+ }
+ else
+ {
+ nexts = s->next;
+ }
+ }
+}
+
+
+/***************************************************************************
+ add a server into the list
+ **************************************************************************/
+static void add_server(struct work_record *work,struct server_record *s)
+{
+ struct server_record *s2;
+
+ if (!work->serverlist) {
+ work->serverlist = s;
+ s->prev = NULL;
+ s->next = NULL;
+ return;
+ }
+
+ for (s2 = work->serverlist; s2->next; s2 = s2->next) ;
+
+ s2->next = s;
+ s->next = NULL;
+ s->prev = s2;
+}
+
+
+/****************************************************************************
+ find a server in a server list.
+ **************************************************************************/
+struct server_record *find_server(struct work_record *work, char *name)
+{
+ struct server_record *ret;
+
+ if (!work) return NULL;
+
+ for (ret = work->serverlist; ret; ret = ret->next)
+ {
+ if (strequal(ret->serv.name,name))
+ {
+ return ret;
+ }
+ }
+ return NULL;
+}
+
+
+/****************************************************************************
+ add a server entry
+ ****************************************************************************/
+struct server_record *add_server_entry(struct subnet_record *d,
+ struct work_record *work,
+ char *name,int servertype,
+ int ttl,char *comment,
+ BOOL replace)
+{
+ BOOL newentry=False;
+ struct server_record *s;
+
+ if (name[0] == '*')
+ {
+ return (NULL);
+ }
+
+ s = find_server(work, name);
+
+ if (s && !replace)
+ {
+ DEBUG(4,("Not replacing %s\n",name));
+ return(s);
+ }
+
+ if (!s || s->serv.type != servertype || !strequal(s->serv.comment, comment))
+ updatedlists=True;
+
+ if (!s)
+ {
+ newentry = True;
+ s = (struct server_record *)malloc(sizeof(*s));
+
+ if (!s) return(NULL);
+
+ bzero((char *)s,sizeof(*s));
+ }
+
+
+ /* update the entry */
+ StrnCpy(s->serv.name,name,sizeof(s->serv.name)-1);
+ StrnCpy(s->serv.comment,comment,sizeof(s->serv.comment)-1);
+ strupper(s->serv.name);
+ s->serv.type = servertype;
+ s->death_time = servertype ? (ttl?time(NULL)+ttl*3:0) : (time(NULL)-1);
+
+ /* for a domain entry, the comment field refers to the server name */
+
+ if (s->serv.type & SV_TYPE_DOMAIN_ENUM) strupper(s->serv.comment);
+
+ if (newentry)
+ {
+ add_server(work, s);
+
+ DEBUG(3,("Added "));
+ }
+ else
+ {
+ DEBUG(3,("Updated "));
+ }
+
+ DEBUG(3,("server entry %s of type %x (%s) to %s %s\n",
+ name,servertype,comment,
+ work->work_group,inet_ntoa(d->bcast_ip)));
+
+ return(s);
+}
+
+
+/*******************************************************************
+ expire old servers in the serverlist
+ ******************************************************************/
+void expire_servers(time_t t)
+{
+ struct subnet_record *d;
+
+ for (d = FIRST_SUBNET; d ; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ {
+ struct work_record *work;
+
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ remove_old_servers(work, t, False);
+ }
+ }
+}
+
diff --git a/source/namedbsubnet.c b/source/namedbsubnet.c
new file mode 100644
index 00000000000..4f0b647996d
--- /dev/null
+++ b/source/namedbsubnet.c
@@ -0,0 +1,363 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Revision History:
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+ 04 jul 96: lkcl@pires.co.uk
+ created module namedbsubnet containing subnet database functions
+
+*/
+
+#include "includes.h"
+#include "smb.h"
+
+extern int ClientNMB;
+extern int ClientDGRAM;
+
+extern int DEBUGLEVEL;
+
+extern struct in_addr wins_ip;
+extern struct in_addr ipzero;
+
+extern pstring myname;
+extern fstring myworkgroup;
+extern char **my_netbios_names;
+
+BOOL updatedlists = True;
+int updatecount = 0;
+
+/* local interfaces structure */
+extern struct interface *local_interfaces;
+
+/* this is our domain/workgroup/server database */
+struct subnet_record *subnetlist = NULL;
+
+/* WINS subnet - keep this separate so enumeration code doesn't
+ run onto it by mistake. */
+struct subnet_record *wins_subnet = NULL;
+
+extern uint16 nb_type; /* samba's NetBIOS name type */
+
+/****************************************************************************
+ add a domain into the list
+ **************************************************************************/
+static void add_subnet(struct subnet_record *d)
+{
+ struct subnet_record *d2;
+
+ if (!subnetlist)
+ {
+ subnetlist = d;
+ d->prev = NULL;
+ d->next = NULL;
+ return;
+ }
+
+ for (d2 = subnetlist; d2->next; d2 = d2->next);
+
+ d2->next = d;
+ d->next = NULL;
+ d->prev = d2;
+}
+
+
+/****************************************************************************
+ find a subnet in the subnetlist - not including WINS.
+ **************************************************************************/
+struct subnet_record *find_subnet(struct in_addr bcast_ip)
+{
+ struct subnet_record *d;
+
+ /* search through subnet list for broadcast/netmask that matches
+ the source ip address. */
+
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ if (same_net(bcast_ip, d->bcast_ip, d->mask_ip))
+ return d;
+ }
+
+ return (NULL);
+}
+
+
+/****************************************************************************
+ finds the appropriate subnet structure. directed packets (non-bcast) are
+ assumed to come from a point-to-point (P or M node), and so the subnet we
+ return in this instance is the WINS 'pseudo-subnet' with ip 255.255.255.255
+ ****************************************************************************/
+struct subnet_record *find_req_subnet(struct in_addr ip, BOOL bcast)
+{
+ if (bcast)
+ {
+ /* identify the subnet the broadcast request came from */
+ return find_subnet(*iface_bcast(ip));
+ }
+ /* Return the subnet with the pseudo-ip of 255.255.255.255 */
+ return wins_subnet;
+}
+
+/****************************************************************************
+ find a subnet in the subnetlist - if the subnet is not found
+ then return the WINS subnet.
+ **************************************************************************/
+struct subnet_record *find_subnet_all(struct in_addr bcast_ip)
+{
+ struct subnet_record *d = find_subnet(bcast_ip);
+ if(!d)
+ return wins_subnet;
+ return d;
+}
+
+/****************************************************************************
+ create a domain entry
+ ****************************************************************************/
+static struct subnet_record *make_subnet(struct in_addr bcast_ip, struct in_addr mask_ip, BOOL add)
+{
+ struct subnet_record *d;
+ d = (struct subnet_record *)malloc(sizeof(*d));
+
+ if (!d) return(NULL);
+
+ bzero((char *)d,sizeof(*d));
+
+ DEBUG(4, ("making subnet %s ", inet_ntoa(bcast_ip)));
+ DEBUG(4, ("%s\n", inet_ntoa(mask_ip)));
+
+ d->bcast_ip = bcast_ip;
+ d->mask_ip = mask_ip;
+ d->workgrouplist = NULL;
+
+ if(add)
+ add_subnet(d);
+
+ return d;
+}
+
+/****************************************************************************
+ add a domain entry. creates a workgroup, if necessary, and adds the domain
+ to the named a workgroup.
+ ****************************************************************************/
+static struct subnet_record *add_subnet_entry(struct in_addr bcast_ip,
+ struct in_addr mask_ip, char *name,
+ BOOL create_subnets, BOOL add)
+{
+ struct subnet_record *d = NULL;
+
+ if (zero_ip(bcast_ip))
+ bcast_ip = *iface_bcast(bcast_ip);
+
+ /* Note that we should also add into the WINS subnet as add_subnet_entry
+ should be called to add NetBIOS names and server entries on all
+ interfaces, including the WINS interface
+ */
+
+ if(create_subnets == True)
+ {
+ /* Create new subnets. */
+ if((d = make_subnet(bcast_ip, mask_ip, add)) == NULL)
+ {
+ DEBUG(0,("add_subnet_entry: Unable to create subnet %s\n",
+ inet_ntoa(bcast_ip) ));
+ return NULL;
+ }
+ return d;
+ }
+ if(ip_equal(bcast_ip, wins_ip))
+ return wins_subnet;
+ return find_subnet(bcast_ip);
+}
+
+/****************************************************************************
+ Add a workgroup into a subnet, and if it's our primary workgroup,
+ add the required names to it.
+**************************************************************************/
+
+void add_workgroup_to_subnet( struct subnet_record *d, char *group)
+{
+ struct work_record *w = NULL;
+
+ DEBUG(5,("add_workgroup_to_subnet: Adding workgroup %s to subnet %s\n",
+ group, inet_ntoa(d->bcast_ip)));
+
+ /* This next statement creates the workgroup struct if it doesn't
+ already exist.
+ */
+ if((w = find_workgroupstruct(d, group, True)) == NULL)
+ {
+ DEBUG(0,("add_workgroup_to_subnet: Unable to add workgroup %s to subnet %s\n",
+ group, inet_ntoa(d->bcast_ip) ));
+ return;
+ }
+
+ /* add WORKGROUP(00) entries into name database
+ or register with WINS server, if it's our workgroup.
+ */
+ if (strequal(myworkgroup, group))
+ {
+ int n;
+
+ add_my_name_entry(d,group,0x0 ,nb_type|NB_ACTIVE|NB_GROUP);
+ add_my_name_entry(d,group,0x1e,nb_type|NB_ACTIVE|NB_GROUP);
+
+ /* Add all our server names to the workgroup list. We remove any
+ browser or logon server flags from all but the primary name.
+ */
+ for( n = 0; my_netbios_names[n]; n++)
+ {
+ char *name = my_netbios_names[n];
+ int stype = w->ServerType;
+
+ if(!strequal(myname, name))
+ stype &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_POTENTIAL_BROWSER|
+ SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER);
+
+ add_server_entry(d,w,name,stype|SV_TYPE_LOCAL_LIST_ONLY,0,
+ lp_serverstring(),True);
+ DEBUG(3,("add_workgroup_to_subnet: Added server name entry %s \
+to subnet %s\n", name, inet_ntoa(d->bcast_ip)));
+ }
+ }
+}
+
+/****************************************************************************
+ create subnet / workgroup / server entries
+
+ - add or create the subnet lists
+ - add or create the workgroup entries in each subnet entry
+ - register appropriate NetBIOS names for the workgroup entries
+
+**************************************************************************/
+void add_my_subnets(char *group)
+{
+ static BOOL create_subnets = True;
+ struct subnet_record *d = NULL;
+ struct interface *i = NULL;
+
+ if (*group == '*') return;
+
+ /* Create subnets from all the local interfaces and thread them onto
+ the linked list.
+ */
+ for (i = local_interfaces; i; i = i->next)
+ {
+ add_subnet_entry(i->bcast,i->nmask,group, create_subnets, True);
+ }
+
+ /* If we are using WINS, then we must add the workgroup to the WINS
+ subnet. This is used as a place to keep collated server lists.
+ */
+
+ /* Create the WINS subnet if we are using WINS - but don't thread it
+ onto the linked subnet list.
+ */
+ if (lp_wins_support() || lp_wins_server())
+ {
+ struct in_addr wins_nmask = ipzero;
+ wins_subnet = add_subnet_entry(wins_ip, wins_nmask, group, create_subnets, False);
+ }
+
+ /* Ensure we only create the subnets once. */
+ create_subnets = False;
+
+ /* Now we have created all the subnets - we can add the names
+ that make us a client member in the workgroup.
+ */
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ add_workgroup_to_subnet(d, group);
+}
+
+/*******************************************************************
+ write out browse.dat
+ ******************************************************************/
+void write_browse_list(time_t t)
+{
+ struct subnet_record *d;
+ pstring fname,fnamenew;
+ FILE *f;
+
+ static time_t lasttime = 0;
+
+ if (!lasttime) lasttime = t;
+ if (!updatedlists || t - lasttime < 5) return;
+
+ lasttime = t;
+ updatedlists = False;
+ updatecount++;
+
+ dump_names();
+ dump_workgroups();
+
+ pstrcpy(fname,lp_lockdir());
+ trim_string(fname,NULL,"/");
+ strcat(fname,"/");
+ strcat(fname,SERVER_LIST);
+ pstrcpy(fnamenew,fname);
+ strcat(fnamenew,".");
+
+ f = fopen(fnamenew,"w");
+
+ if (!f)
+ {
+ DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno)));
+ return;
+ }
+
+ for (d = FIRST_SUBNET; d ; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ {
+ struct work_record *work;
+ for (work = d->workgrouplist; work ; work = work->next)
+ {
+ struct server_record *s;
+ for (s = work->serverlist; s ; s = s->next)
+ {
+ fstring tmp;
+
+ /* don't list domains I don't have a master for */
+ if ((s->serv.type & SV_TYPE_DOMAIN_ENUM) && !s->serv.comment[0])
+ {
+ continue;
+ }
+
+ /* output server details, plus what workgroup/domain
+ they're in. without the domain information, the
+ combined list of all servers in all workgroups gets
+ sent to anyone asking about any workgroup! */
+
+ sprintf(tmp, "\"%s\"", s->serv.name);
+ fprintf(f, "%-25s ", tmp);
+ fprintf(f, "%08x ", s->serv.type);
+ sprintf(tmp, "\"%s\" ", s->serv.comment);
+ fprintf(f, "%-30s", tmp);
+ fprintf(f, "\"%s\"\n", work->work_group);
+ }
+ }
+ }
+
+ fclose(f);
+ unlink(fname);
+ chmod(fnamenew,0644);
+ rename(fnamenew,fname);
+ DEBUG(3,("Wrote browse list %s\n",fname));
+}
+
diff --git a/source/namedbwork.c b/source/namedbwork.c
new file mode 100644
index 00000000000..a6260aab467
--- /dev/null
+++ b/source/namedbwork.c
@@ -0,0 +1,245 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Revision History:
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+ 04 jul 96: lkcl@pires.co.uk
+ created module namedbwork containing workgroup database functions
+
+*/
+
+#include "includes.h"
+#include "smb.h"
+
+extern int ClientNMB;
+
+extern int DEBUGLEVEL;
+
+/* this is our domain/workgroup/server database */
+extern struct subnet_record *subnetlist;
+
+extern struct in_addr wins_ip;
+
+extern fstring myworkgroup;
+
+int workgroup_count = 0; /* unique index key: one for each workgroup */
+
+
+
+/****************************************************************************
+ add a workgroup into the domain list
+ **************************************************************************/
+static void add_workgroup(struct work_record *work, struct subnet_record *d)
+{
+ struct work_record *w2;
+
+ if (!work || !d) return;
+
+ if (!d->workgrouplist)
+ {
+ d->workgrouplist = work;
+ work->prev = NULL;
+ work->next = NULL;
+ return;
+ }
+
+ for (w2 = d->workgrouplist; w2->next; w2 = w2->next);
+
+ w2->next = work;
+ work->next = NULL;
+ work->prev = w2;
+}
+
+
+/****************************************************************************
+ create a blank workgroup
+ **************************************************************************/
+static struct work_record *make_workgroup(char *name)
+{
+ struct work_record *work;
+ struct subnet_record *d;
+ int t = -1;
+
+ if (!name || !name[0]) return NULL;
+
+ work = (struct work_record *)malloc(sizeof(*work));
+ if (!work) return(NULL);
+ bzero((char *)work, sizeof(*work));
+
+ StrnCpy(work->work_group,name,sizeof(work->work_group)-1);
+ work->serverlist = NULL;
+
+ work->ServerType = lp_default_server_announce() | (lp_local_master() ?
+ SV_TYPE_POTENTIAL_BROWSER : 0 );
+ work->RunningElection = False;
+ work->ElectionCount = 0;
+ work->announce_interval = 0;
+ work->needelection = False;
+ work->needannounce = True;
+ work->mst_state = MST_POTENTIAL;
+ work->dom_state = DOMAIN_NONE;
+ work->log_state = LOGON_NONE;
+
+ /* make sure all token representations of workgroups are unique */
+
+ for (d = FIRST_SUBNET; d && t == -1; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ {
+ struct work_record *w;
+ for (w = d->workgrouplist; w && t == -1; w = w->next)
+ {
+ if (strequal(w->work_group, work->work_group)) t = w->token;
+ }
+ }
+
+ if (t == -1)
+ {
+ work->token = ++workgroup_count;
+ }
+ else
+ {
+ work->token = t;
+ }
+
+
+ /* WfWg uses 01040b01 */
+ /* Win95 uses 01041501 */
+ /* NTAS uses ???????? */
+ work->ElectionCriterion = (MAINTAIN_LIST)|(ELECTION_VERSION<<8);
+ work->ElectionCriterion |= (lp_os_level() << 24);
+ if (lp_domain_master()) {
+ work->ElectionCriterion |= 0x80;
+ }
+
+ return work;
+}
+
+
+/*******************************************************************
+ remove workgroups
+ ******************************************************************/
+struct work_record *remove_workgroup(struct subnet_record *d,
+ struct work_record *work,
+ BOOL remove_all_servers)
+{
+ struct work_record *ret_work = NULL;
+
+ if (!d || !work) return NULL;
+
+ DEBUG(3,("Removing old workgroup %s\n", work->work_group));
+
+ ret_work = work->next;
+
+ remove_old_servers(work, -1, remove_all_servers);
+
+ if (!work->serverlist)
+ {
+ if (work->prev) work->prev->next = work->next;
+ if (work->next) work->next->prev = work->prev;
+
+ if (d->workgrouplist == work) d->workgrouplist = work->next;
+
+ free(work);
+ }
+
+ return ret_work;
+}
+
+
+/****************************************************************************
+ find a workgroup in the workgrouplist
+ only create it if the domain allows it, or the parameter 'add' insists
+ that it get created/added anyway. this allows us to force entries in
+ lmhosts file to be added.
+ **************************************************************************/
+struct work_record *find_workgroupstruct(struct subnet_record *d,
+ fstring name, BOOL add)
+{
+ struct work_record *ret, *work;
+
+ if (!d) return NULL;
+
+ DEBUG(4, ("workgroup search for %s: ", name));
+
+ for (ret = d->workgrouplist; ret; ret = ret->next) {
+ if (!strcmp(ret->work_group,name)) {
+ DEBUG(4, ("found\n"));
+ return(ret);
+ }
+ }
+
+ if (!add) {
+ DEBUG(4, ("not found\n"));
+ return NULL;
+ }
+
+ DEBUG(4,("not found: creating\n"));
+
+ if ((work = make_workgroup(name)))
+ {
+ if (!ip_equal(d->bcast_ip, wins_ip) &&
+ lp_preferred_master() && lp_local_master() &&
+ strequal(myworkgroup, name))
+ {
+ DEBUG(3, ("preferred master startup for %s\n", work->work_group));
+ work->needelection = True;
+ work->ElectionCriterion |= (1<<3);
+ }
+ add_workgroup(work, d);
+ return(work);
+ }
+ return NULL;
+}
+
+
+/****************************************************************************
+ dump a copy of the workgroup/domain database
+ **************************************************************************/
+void dump_workgroups(void)
+{
+ struct subnet_record *d;
+
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ {
+ if (d->workgrouplist)
+ {
+ struct work_record *work;
+
+ DEBUG(4,("dump domain bcast=%15s: ", inet_ntoa(d->bcast_ip)));
+ DEBUG(4,(" netmask=%15s:\n", inet_ntoa(d->mask_ip)));
+
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ DEBUG(4,("\t%s(%d)\n", work->work_group, work->token));
+ if (work->serverlist)
+ {
+ struct server_record *s;
+ for (s = work->serverlist; s; s = s->next)
+ {
+ DEBUG(4,("\t\t%s %8x (%s)\n",
+ s->serv.name, s->serv.type, s->serv.comment));
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/source/nameelect.c b/source/nameelect.c
new file mode 100644
index 00000000000..e43c3149444
--- /dev/null
+++ b/source/nameelect.c
@@ -0,0 +1,846 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ 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.
+
+ Module name: nameelect.c
+
+ Revision History:
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+ 04 jul 96: lkcl@pires.co.uk
+ added system to become a master browser by stages.
+
+
+*/
+
+#include "includes.h"
+
+extern int ClientNMB;
+extern int ClientDGRAM;
+
+extern int DEBUGLEVEL;
+extern pstring scope;
+
+extern pstring myname;
+extern fstring myworkgroup;
+extern struct in_addr ipzero;
+extern struct in_addr wins_ip;
+
+/* here are my election parameters */
+
+extern time_t StartupTime;
+
+extern struct subnet_record *subnetlist;
+
+extern uint16 nb_type; /* samba's NetBIOS name type */
+
+
+/*******************************************************************
+ occasionally check to see if the master browser is around
+ ******************************************************************/
+void check_master_browser(time_t t)
+{
+ static time_t lastrun=0;
+ struct subnet_record *d;
+
+ if (!lastrun) lastrun = t;
+ if (t < lastrun + CHECK_TIME_MST_BROWSE * 60) return;
+
+ lastrun = t;
+
+ dump_workgroups();
+
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ struct work_record *work;
+
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ if (strequal(work->work_group, myworkgroup) && !AM_MASTER(work))
+ {
+ if (lp_local_master() && lp_preferred_master())
+ {
+ /* potential master browser - not a master browser. force
+ becoming a master browser, hence the log message.
+ */
+
+ DEBUG(2,("%s potential master for %s %s - force election\n",
+ timestring(), work->work_group,
+ inet_ntoa(d->bcast_ip)));
+
+ browser_gone(work->work_group, d->bcast_ip);
+ }
+ else
+ {
+ /* if we are not the browse master of a workgroup,
+ and we can't find a browser on the subnet, do
+ something about it.
+ */
+
+ queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_MST_CHK,
+ work->work_group,0x1d,0,0,0,NULL,NULL,
+ True,False,d->bcast_ip,d->bcast_ip, 0);
+ }
+ }
+ }
+ }
+}
+
+
+/*******************************************************************
+ what to do if a master browser DOESN't exist.
+
+ option 1: force an election, and participate in it
+ option 2: force an election, and let everyone else participate.
+
+ ******************************************************************/
+void browser_gone(char *work_name, struct in_addr ip)
+{
+ struct subnet_record *d = find_subnet(ip);
+ struct work_record *work = find_workgroupstruct(d, work_name, False);
+
+ /* i don't know about this workgroup, therefore i don't care */
+ if (!work || !d) return;
+
+ /* don't do election stuff on the WINS subnet */
+ if (ip_equal(d->bcast_ip,wins_ip))
+ return;
+
+ if (strequal(work->work_group, myworkgroup))
+ {
+
+ if (lp_local_master())
+ {
+ /* we have discovered that there is no local master
+ browser, and we are configured to initiate
+ an election under exactly such circumstances.
+ */
+ DEBUG(2,("Forcing election on %s %s\n",
+ work->work_group,inet_ntoa(d->bcast_ip)));
+
+ /* we can attempt to become master browser */
+ work->needelection = True;
+ }
+ else
+ {
+ /* we need to force an election, because we are configured
+ not to _become_ the local master, but we still _need_ one,
+ having detected that one doesn't exist.
+ */
+
+ /* local interfaces: force an election */
+ send_election(d, work->work_group, 0, 0, myname);
+
+ /* only removes workgroup completely on a local interface
+ persistent lmhosts entries on a local interface _will_ be removed).
+ */
+ remove_workgroup(d, work,True);
+ add_workgroup_to_subnet(d, work->work_group);
+ }
+ }
+}
+
+
+/****************************************************************************
+ send an election packet
+ **************************************************************************/
+void send_election(struct subnet_record *d, char *group,uint32 criterion,
+ int timeup,char *name)
+{
+ pstring outbuf;
+ char *p;
+
+ if (!d) return;
+
+ DEBUG(2,("Sending election to %s for workgroup %s\n",
+ inet_ntoa(d->bcast_ip),group));
+
+ bzero(outbuf,sizeof(outbuf));
+ p = outbuf;
+ CVAL(p,0) = ANN_Election; /* election */
+ p++;
+
+ CVAL(p,0) = (criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION;
+ SIVAL(p,1,criterion);
+ SIVAL(p,5,timeup*1000); /* ms - despite the spec */
+ p += 13;
+ pstrcpy(p,name);
+ strupper(p);
+ p = skip_string(p,1);
+
+ send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
+ outbuf,PTR_DIFF(p,outbuf),
+ name,group,0,0x1e,d->bcast_ip,*iface_ip(d->bcast_ip));
+}
+
+
+/****************************************************************************
+ un-register a SELF name that got rejected.
+
+ if this name happens to be rejected when samba is in the process
+ of becoming a master browser (registering __MSBROWSE__, WORKGROUP(1d)
+ or WORKGROUP(1b)) then we must stop being a master browser. sad.
+
+ **************************************************************************/
+void name_unregister_work(struct subnet_record *d, char *name, int name_type)
+{
+ struct work_record *work;
+ int remove_type_local = 0;
+ int remove_type_domain = 0;
+ int remove_type_logon = 0;
+
+ remove_netbios_name(d,name,name_type,SELF,ipzero);
+
+ if (!(work = find_workgroupstruct(d, name, False))) return;
+
+ /* work out what to unbecome, from the name type being removed */
+
+ if (ms_browser_name(name, name_type))
+ {
+ remove_type_local |= SV_TYPE_MASTER_BROWSER;
+ }
+ if (AM_MASTER(work) && strequal(name, myworkgroup) && name_type == 0x1d)
+ {
+ remove_type_local |= SV_TYPE_MASTER_BROWSER;
+ }
+ if (AM_DOMMST(work) && strequal(name, myworkgroup) && name_type == 0x1b)
+ {
+ remove_type_domain |= SV_TYPE_DOMAIN_MASTER;
+ }
+ if (AM_DOMMEM(work) && strequal(name, myworkgroup) && name_type == 0x1c)
+ {
+ remove_type_logon|= SV_TYPE_DOMAIN_MEMBER;
+ }
+
+ if (remove_type_local ) unbecome_local_master (d, work, remove_type_local );
+ if (remove_type_domain) unbecome_domain_master(d, work, remove_type_domain);
+ if (remove_type_logon ) unbecome_logon_server (d, work, remove_type_logon );
+}
+
+
+/****************************************************************************
+ registers a name.
+
+ if the name being added is a SELF name, we must additionally check
+ whether to proceed to the next stage in samba becoming a master browser.
+
+ **************************************************************************/
+void name_register_work(struct subnet_record *d, char *name, int name_type,
+ int nb_flags, time_t ttl, struct in_addr ip, BOOL bcast)
+{
+ enum name_source source = (ismyip(ip) || ip_equal(ip, ipzero)) ?
+ SELF : REGISTER;
+
+ if (source == SELF)
+ {
+ struct work_record *work = find_workgroupstruct(d,
+ myworkgroup, False);
+
+ add_netbios_entry(d,name,name_type,nb_flags,ttl,source,ip,True,!bcast);
+
+ if (work)
+ {
+ int add_type_local = False;
+ int add_type_domain = False;
+ int add_type_logon = False;
+
+ DEBUG(4,("checking next stage: name_register_work %s\n", name));
+
+ /* work out what to become, from the name type being added */
+
+ if (ms_browser_name(name, name_type))
+ {
+ add_type_local = True;
+ }
+ if (strequal(name, myworkgroup) && name_type == 0x1d)
+ {
+ add_type_local = True;
+ }
+ if (strequal(name, myworkgroup) && name_type == 0x1b)
+ {
+ add_type_domain = True;
+ }
+ if (strequal(name, myworkgroup) && name_type == 0x1c)
+ {
+ add_type_logon = True;
+ }
+
+ if (add_type_local ) become_local_master (d, work);
+ if (add_type_domain) become_domain_master(d, work);
+ if (add_type_logon ) become_logon_server (d, work);
+ }
+ }
+}
+
+
+/*******************************************************************
+ become the local master browser.
+
+ this is done in stages. note that this could take a while,
+ particularly on a broadcast subnet, as we have to wait for
+ the implicit registration of each name to be accepted.
+
+ as each name is successfully registered, become_local_master() is
+ called again, in order to initiate the next stage. see
+ dead_netbios_entry() - deals with implicit name registration
+ and response_name_reg() - deals with explicit registration
+ with a WINS server.
+
+ stage 1: was MST_POTENTIAL - go to MST_POTENTIAL and register ^1^2__MSBROWSE__^2^1.
+ stage 2: was MST_BACK - go to MST_MSB and register WORKGROUP(0x1d)
+ stage 3: was MST_MSB - go to MST_BROWSER and stay there
+
+ XXXX note: this code still does not cope with the distinction
+ between different types of nodes, particularly between M and P
+ nodes. that comes later.
+
+ ******************************************************************/
+void become_local_master(struct subnet_record *d, struct work_record *work)
+{
+ /* domain type must be limited to domain enum + server type. it must
+ not have SV_TYPE_SERVER or anything else with SERVER in it, else
+ clients get confused and start thinking this entry is a server
+ not a workgroup
+ */
+ uint32 domain_type = SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT;
+
+ if (!work || !d)
+ return;
+
+ if (!lp_local_master())
+ {
+ DEBUG(0,("Samba not configured as a local master browser.\n"));
+ return;
+ }
+
+ DEBUG(2,("Becoming master for %s %s (currently at stage %d)\n",
+ work->work_group,inet_ntoa(d->bcast_ip),work->mst_state));
+
+ switch (work->mst_state)
+ {
+ case MST_POTENTIAL: /* while we were nothing but a server... */
+ {
+ DEBUG(3,("go to first stage: register ^1^2__MSBROWSE__^2^1\n"));
+ work->mst_state = MST_BACK; /* an election win was successful */
+
+ work->ElectionCriterion |= 0x5;
+
+ /* update our server status */
+ work->ServerType &= ~SV_TYPE_POTENTIAL_BROWSER;
+ add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
+ 0,lp_serverstring(),True);
+
+ /* add special browser name */
+ add_my_name_entry(d,MSBROWSE,0x01,nb_type|NB_ACTIVE|NB_GROUP);
+
+ /* DON'T do anything else after calling add_my_name_entry() */
+ break;
+ }
+
+ case MST_BACK: /* while nothing had happened except we won an election... */
+ {
+ DEBUG(3,("go to second stage: register as master browser\n"));
+ work->mst_state = MST_MSB; /* registering MSBROWSE was successful */
+
+ /* add server entry on successful registration of MSBROWSE */
+ add_server_entry(d,work,work->work_group,domain_type|SV_TYPE_LOCAL_LIST_ONLY,
+ 0,myname,True);
+
+ /* add master name */
+ add_my_name_entry(d,work->work_group,0x1d,nb_type|NB_ACTIVE);
+
+ /* DON'T do anything else after calling add_my_name_entry() */
+ break;
+ }
+
+ case MST_MSB: /* while we were still only registered MSBROWSE state... */
+ {
+ int i = 0;
+ struct server_record *sl;
+
+ DEBUG(3,("2nd stage complete: registered as master browser for workgroup %s \
+on subnet %s\n", work->work_group, inet_ntoa(d->bcast_ip)));
+ work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
+
+ /* update our server status */
+ work->ServerType |= SV_TYPE_MASTER_BROWSER;
+
+ DEBUG(3,("become_local_master: updating our server %s to type %x\n",
+ myname, work->ServerType));
+
+ add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
+ 0,lp_serverstring(),True);
+
+ /* Count the number of servers we have on our list. If it's
+ less than 10 (just a heuristic) request the servers
+ to announce themselves.
+ */
+ for( sl = work->serverlist; sl != NULL; sl = sl->next)
+ i++;
+
+ if (i < 10)
+ {
+ /* ask all servers on our local net to announce to us */
+ announce_request(work, d->bcast_ip);
+ }
+
+ /* Reset the announce master timer so that we do an announce as soon as possible
+ now we are a master. */
+ reset_announce_timer();
+
+ DEBUG(0,("Samba is now a local master browser for workgroup %s on subnet %s\n",
+ work->work_group, inet_ntoa(d->bcast_ip)));
+
+ break;
+ }
+
+ case MST_BROWSER:
+ {
+ /* don't have to do anything: just report success */
+ DEBUG(3,("3rd stage: become master browser!\n"));
+ break;
+ }
+ }
+}
+
+
+/*******************************************************************
+ become the domain master browser.
+
+ this is done in stages. note that this could take a while,
+ particularly on a broadcast subnet, as we have to wait for
+ the implicit registration of each name to be accepted.
+
+ as each name is successfully registered, become_domain_master() is
+ called again, in order to initiate the next stage. see
+ dead_netbios_entry() - deals with implicit name registration
+ and response_name_reg() - deals with explicit registration
+ with a WINS server.
+
+ stage 1: was DOMAIN_NONE - go to DOMAIN_MST
+
+ XXXX note: this code still does not cope with the distinction
+ between different types of nodes, particularly between M and P
+ nodes. that comes later.
+
+ ******************************************************************/
+void become_domain_master(struct subnet_record *d, struct work_record *work)
+{
+ /* domain type must be limited to domain enum + server type. it must
+ not have SV_TYPE_SERVER or anything else with SERVER in it, else
+ clients get confused and start thinking this entry is a server
+ not a workgroup
+ */
+
+ if (!work || !d) return;
+
+ if (!lp_domain_master())
+ {
+ DEBUG(0,("Samba not configured as a domain master browser.\n"));
+ return;
+ }
+
+ DEBUG(2,("Becoming domain master for %s %s (currently at stage %d)\n",
+ work->work_group,inet_ntoa(d->bcast_ip),work->dom_state));
+
+ switch (work->dom_state)
+ {
+ case DOMAIN_NONE: /* while we were nothing but a server... */
+ {
+ DEBUG(3,("become_domain_master: go to first stage: register <1b> name\n"));
+ work->dom_state = DOMAIN_WAIT;
+
+ /* XXXX the 0x1b is domain master browser name */
+ add_my_name_entry(d, work->work_group,0x1b,nb_type|NB_ACTIVE);
+
+ /* DON'T do anything else after calling add_my_name_entry() */
+ break;
+ }
+
+ case DOMAIN_WAIT:
+ {
+ work->dom_state = DOMAIN_MST; /* ... become domain master */
+ DEBUG(3,("become_domain_master: first stage - register as domain member\n"));
+
+ /* update our server status */
+ work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER;
+ add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY,
+ 0, lp_serverstring(),True);
+
+ DEBUG(0,("Samba is now a domain master browser for workgroup %s on subnet %s\n",
+ work->work_group, inet_ntoa(d->bcast_ip)));
+
+ if (d == wins_subnet)
+ {
+ /* ok! we successfully registered by unicast with the
+ WINS server. we now expect to become the domain
+ master on the local subnets. if this fails, it's
+ probably a 1.9.16p2 to 1.9.16p11 server's fault.
+
+ this is a configuration issue that should be addressed
+ by the network administrator - you shouldn't have
+ several machines configured as a domain master browser
+ for the same WINS scope (except if they are 1.9.17 or
+ greater, and you know what you're doing.
+
+ see DOMAIN.txt.
+
+ */
+ add_domain_master_bcast();
+ }
+ break;
+ }
+
+ case DOMAIN_MST:
+ {
+ /* don't have to do anything: just report success */
+ DEBUG(3,("domain second stage: there isn't one!\n"));
+ break;
+ }
+ }
+}
+
+
+/*******************************************************************
+ become a logon server.
+ ******************************************************************/
+void become_logon_server(struct subnet_record *d, struct work_record *work)
+{
+ if (!work || !d) return;
+
+ if (!lp_domain_logons())
+ {
+ DEBUG(0,("samba not configured as a logon master.\n"));
+ return;
+ }
+
+ DEBUG(2,("Becoming logon server for %s %s (currently at stage %d)\n",
+ work->work_group,inet_ntoa(d->bcast_ip),work->log_state));
+
+ switch (work->log_state)
+ {
+ case LOGON_NONE: /* while we were nothing but a server... */
+ {
+ DEBUG(3,("go to first stage: register <1c> name\n"));
+ work->log_state = LOGON_WAIT;
+
+ /* XXXX the 0x1c is apparently something to do with domain logons */
+ add_my_name_entry(d, myworkgroup,0x1c,nb_type|NB_ACTIVE|NB_GROUP);
+
+ /* DON'T do anything else after calling add_my_name_entry() */
+ break;
+ }
+
+ case LOGON_WAIT:
+ {
+ work->log_state = LOGON_SRV; /* ... become logon server */
+ DEBUG(3,("logon second stage: register \n"));
+
+ /* update our server status */
+ work->ServerType |= SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER;
+ add_server_entry(d,work,myname,work->ServerType|SV_TYPE_LOCAL_LIST_ONLY
+ ,0, lp_serverstring(),True);
+
+ /* DON'T do anything else after calling add_my_name_entry() */
+ break;
+ }
+
+ case LOGON_SRV:
+ {
+ DEBUG(3,("logon third stage: there isn't one!\n"));
+ break;
+ }
+ }
+}
+
+
+/*******************************************************************
+ unbecome the local master browser. initates removal of necessary netbios
+ names, and tells the world that we are no longer a master browser.
+
+ XXXX this _should_ be used to demote to a backup master browser, without
+ going straight to non-master browser. another time.
+
+ ******************************************************************/
+void unbecome_local_master(struct subnet_record *d, struct work_record *work,
+ int remove_type)
+{
+ /* can only remove master types with this function */
+
+ if (remove_type & SV_TYPE_MASTER_BROWSER)
+ {
+ DEBUG(2,("Becoming local non-master for %s\n",work->work_group));
+
+ /* no longer a master browser of any sort */
+
+ work->ServerType &= ~SV_TYPE_MASTER_BROWSER;
+ work->ServerType |= SV_TYPE_POTENTIAL_BROWSER;
+ work->ElectionCriterion &= ~0x4;
+ work->mst_state = MST_POTENTIAL;
+
+ /* announce ourselves as no longer active as a master browser. */
+ announce_server(d, work, work->work_group, myname, 0, 0);
+ remove_name_entry(d,MSBROWSE ,0x01);
+ remove_name_entry(d,work->work_group,0x1d);
+ }
+}
+
+
+/*******************************************************************
+ unbecome the domain master browser. initates removal of necessary netbios
+ names, and tells the world that we are no longer a domain browser.
+ ******************************************************************/
+void unbecome_domain_master(struct subnet_record *d, struct work_record *work,
+ int remove_type)
+{
+ DEBUG(2,("Becoming domain non-master for %s\n",work->work_group));
+
+ /* can only remove master or domain types with this function */
+
+ if (remove_type & SV_TYPE_DOMAIN_MASTER)
+ {
+ /* no longer a domain master browser of any sort */
+
+ work->dom_state = DOMAIN_NONE;
+ work->ServerType &= ~SV_TYPE_DOMAIN_MASTER;
+
+ /* announce ourselves as no longer active as a master browser on
+ all our local subnets. */
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ work = find_workgroupstruct(d, myworkgroup, False);
+
+ announce_server(d, work, work->work_group, myname, 0, 0);
+ /* Remove the name entry without any NetBIOS traffic as that's
+ how it was registered. */
+ remove_name_entry(d,work->work_group,0x1b);
+ }
+
+ /* Unregister the 1b name from the WINS server. */
+ if(wins_subnet != NULL)
+ remove_name_entry(wins_subnet, myworkgroup, 0x1b);
+ }
+}
+
+
+/*******************************************************************
+ unbecome the logon server. initates removal of necessary netbios
+ names, and tells the world that we are no longer a logon server.
+ ******************************************************************/
+void unbecome_logon_server(struct subnet_record *d, struct work_record *work,
+ int remove_type)
+{
+ DEBUG(2,("Becoming logon non-server for %s\n",work->work_group));
+
+ /* can only remove master or domain types with this function */
+
+ if (remove_type & SV_TYPE_DOMAIN_MEMBER)
+ {
+ /* no longer a master browser of any sort */
+
+ work->log_state = LOGON_NONE;
+ work->ServerType &= ~SV_TYPE_DOMAIN_MEMBER;
+
+ /* announce ourselves as no longer active as a master browser. */
+ announce_server(d, work, work->work_group, myname, 0, 0);
+ remove_name_entry(d,work->work_group,0x1c);
+ }
+}
+
+
+/*******************************************************************
+ run the election
+ ******************************************************************/
+void run_elections(time_t t)
+{
+ static time_t lastime = 0;
+
+ struct subnet_record *d;
+
+ /* send election packets once a second */
+ if (lastime && t-lastime <= 0) return;
+
+ lastime = t;
+
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ struct work_record *work;
+
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ if (work->RunningElection)
+ {
+ send_election(d,work->work_group, work->ElectionCriterion,
+ t-StartupTime,myname);
+
+ if (work->ElectionCount++ >= 4)
+ {
+ /* I won! now what :-) */
+ DEBUG(2,(">>> Won election on %s %s <<<\n",
+ work->work_group,inet_ntoa(d->bcast_ip)));
+
+ work->RunningElection = False;
+ work->mst_state = MST_POTENTIAL;
+
+ become_local_master(d, work);
+ }
+ }
+ }
+ }
+}
+
+
+/*******************************************************************
+ work out if I win an election
+ ******************************************************************/
+static BOOL win_election(struct work_record *work,int version,uint32 criterion,
+ int timeup,char *name)
+{
+ int mytimeup = time(NULL) - StartupTime;
+ uint32 mycriterion = work->ElectionCriterion;
+
+ /* If local master is false then never win
+ in election broadcasts. */
+ if(!lp_local_master())
+ {
+ DEBUG(3,("win_election: Losing election as local master == False\n"));
+ return False;
+ }
+
+ DEBUG(4,("election comparison: %x:%x %x:%x %d:%d %s:%s\n",
+ version,ELECTION_VERSION,
+ criterion,mycriterion,
+ timeup,mytimeup,
+ name,myname));
+
+ if (version > ELECTION_VERSION) return(False);
+ if (version < ELECTION_VERSION) return(True);
+
+ if (criterion > mycriterion) return(False);
+ if (criterion < mycriterion) return(True);
+
+ if (timeup > mytimeup) return(False);
+ if (timeup < mytimeup) return(True);
+
+ if (strcasecmp(myname,name) > 0) return(False);
+
+ return(True);
+}
+
+
+/*******************************************************************
+ process a election packet
+
+ An election dynamically decides who will be the master.
+ ******************************************************************/
+void process_election(struct packet_struct *p,char *buf)
+{
+ struct dgram_packet *dgram = &p->packet.dgram;
+ struct in_addr ip = dgram->header.source_ip;
+ struct subnet_record *d = find_subnet(ip);
+ int version = CVAL(buf,0);
+ uint32 criterion = IVAL(buf,1);
+ int timeup = IVAL(buf,5)/1000;
+ char *name = buf+13;
+ struct work_record *work;
+
+ if (!d) return;
+
+ if (ip_equal(d->bcast_ip,wins_ip))
+ {
+ DEBUG(0,("Unexpected election request from %s %s on WINS net\n",
+ name, inet_ntoa(p->ip)));
+ return;
+ }
+
+ name[15] = 0;
+
+ DEBUG(3,("Election request from %s %s vers=%d criterion=%08x timeup=%d\n",
+ name,inet_ntoa(p->ip),version,criterion,timeup));
+
+ if (same_context(dgram)) return;
+
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ if (!strequal(work->work_group, myworkgroup))
+ continue;
+
+ if (win_election(work, version,criterion,timeup,name))
+ {
+ if (!work->RunningElection)
+ {
+ work->needelection = True;
+ work->ElectionCount=0;
+ work->mst_state = MST_POTENTIAL;
+ }
+ }
+ else
+ {
+ work->needelection = False;
+
+ if (work->RunningElection || AM_MASTER(work))
+ {
+ work->RunningElection = False;
+ DEBUG(3,(">>> Lost election on %s %s <<<\n",
+ work->work_group,inet_ntoa(d->bcast_ip)));
+ if (AM_MASTER(work))
+ {
+ unbecome_local_master(d, work, SV_TYPE_MASTER_BROWSER);
+ }
+ }
+ }
+ }
+}
+
+
+/****************************************************************************
+ checks whether a browser election is to be run on any workgroup
+
+ this function really ought to return the time between election
+ packets (which depends on whether samba intends to be a domain
+ master or a master browser) in milliseconds.
+
+ ***************************************************************************/
+BOOL check_elections(void)
+{
+ struct subnet_record *d;
+ BOOL run_any_election = False;
+
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ struct work_record *work;
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ run_any_election |= work->RunningElection;
+
+ if (work->needelection && !work->RunningElection)
+ {
+ DEBUG(3,(">>> Starting election on %s %s <<<\n",
+ work->work_group,inet_ntoa(d->bcast_ip)));
+ work->ElectionCount = 0;
+ work->RunningElection = True;
+ work->needelection = False;
+ }
+ }
+ }
+ return run_any_election;
+}
+
diff --git a/source/nameelect.doc b/source/nameelect.doc
new file mode 100644
index 00000000000..df025e2069a
--- /dev/null
+++ b/source/nameelect.doc
@@ -0,0 +1,256 @@
+/*
+ Unix SMB/Netbios documentation.
+ Version 0.1
+ Copyright (C) Luke Leighton Andrew Tridgell 1996
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Document name: nameelect.doc
+
+ Revision History:
+
+ 0.0 - 02jul96 : lkcl@pires.co.uk
+ created
+
+ 0.1 - 22jul96 Andrew.Tridgell@anu.edu.au
+ tridge's comments on first revision
+*/
+
+the module nameelect.c deals with initiating, winning, losing
+browsing elections, and checking if browsers are still around,
+and the consequences of getting involved in all this.
+
+an election packet can be received at any time, which will initiate
+an election. samba can also detect that there is no longer a
+master browser and will initiate an election.
+
+there is one way to become a master browser, but there are two
+ways to un-become a master browser. if you lose an election, you
+must stop being a master browser. if you fail to register your
+unique special browser names (either on your local subnet or with
+the WINS server) then you must stop being a master browser.
+
+this is a double fail-safe mechanism to ensure that there is only
+one master browser per workgroup per subnet (and one domain master
+browser - per domain (workgroup) per wide area network).
+
+(a wide area network is created when one or more servers on a
+broadcast-isolated subnet point to the same WINS server).
+
+--------
+NOTE FROM TRIDGE:
+
+I'd say "domain master browser" not "WINS server" here. WINS doesn't
+have much to do with browsing, it is the WAN varient of name
+resolution. The name resolution and browsing functions of a netbios
+network are almost entirely separate. Both grew out of systems that
+could only be used on local networks.
+
+To adapt them to WANs, WINS was added for name resolution, and "domain
+master browsers" were added for browse lists. It would be perfectly
+possible to have a WINS server that doesn't even listen to UDP port
+138.
+--------
+
+/*************************************************************************
+ check_elections()
+ *************************************************************************/
+
+this function returns True if samba is in the process of running an
+election on any of its interfaces. a better version of this function
+should return the time-out period in between election packets, in
+milliseconds.
+
+
+/*************************************************************************
+ process_election()
+ *************************************************************************/
+
+this function is responsible for dealing with the receipt of an election
+browse MAILSLOT packet.
+
+if samba is running an election, it checks the criteria in the packet
+received using win_election() to see if it has lost the election or if
+it should join in the election.
+
+if it loses the election, then it becomes a non-master.
+
+
+/*************************************************************************
+ win_election()
+ *************************************************************************/
+
+this function returns True if samba has won an election. the criteria
+in order of precedence are:
+
+the election version; the election criteria; the time since samba was
+started; and as a last resort, a name comparison is used.
+
+
+/*************************************************************************
+ run_elections()
+ *************************************************************************/
+
+this function is responsible for sending out election packets if
+samba is running in an election. once the fourth packet is sent
+out, it is assumed that we have won, and samba initiates becoming
+a master browser.
+
+(it looks like samba sends out an extra packet just to be sure...)
+
+
+/*************************************************************************
+ become_nonmaster()
+ *************************************************************************/
+
+this function is responsible for down-grading samba's status from
+either domain master to master browser or nothing, or master browser
+to nothing, depending on its current status.
+
+samba can become a non-master in three ways: by losing an election -
+see process_election(); by having one of its special browser names
+de-registered - see name_unregister_work(); by receiving and
+processing a browser reset packet - see process_reset_browser().
+
+when samba stops being a domain master, it must release its unique
+0x1b name. when samba stops being a master browser, it must release
+its unique 0x1d name.
+
+becoming non-master is done on a per-subnet basis.
+
+
+/*************************************************************************
+ become_master()
+ *************************************************************************/
+
+this function is responsible for slowly turning samba into a
+local master browser or a domain master browser.
+
+
+this is done in stages. note that this could take a while,
+particularly on a broadcast subnet, as we have to wait for
+the implicit registration of each name to be accepted.
+
+as each name is successfully registered, become_master() is
+called again via name_register_work(), in order to initiate
+the next stage (see dead_netbios_entry() - deals with implicit
+name registration and response_name_reg() - deals with explicit
+registration with a WINS server).
+
+stage 1: was MST_NONE - go to MST_NONE and register ^1^2__MSBROWSE__^2^1.
+stage 2: was MST_WON - go to MST_MSB and register WORKGROUP(0x1d)
+stage 3: was MST_MSB - go to MST_BROWSER and register WORKGROUP(0x1b)
+stage 4: was MST_BROWSER - go to MST_DOMAIN (do not pass GO, do not...)
+
+note that this code still does not cope with the distinction
+between different types of nodes, particularly between M and P
+nodes (see rfc1001.txt). that will be developed later.
+
+
+/*************************************************************************
+ name_register_work()
+ *************************************************************************/
+
+this function is called when a NetBIOS name is successfully
+registered. it will add the registered name into samba's NetBIOS
+records.
+
+it has the additional responsibility that when samba is becoming
+a master browser, it must initiate the next stage in the progress
+towards becoming a master browser.
+
+implicit name registration is done through dead_netbios_entry()
+by time-out. explicit name registration is done through
+response_name_reg() with a WINS server.
+
+
+/*************************************************************************
+ name_unregister_work()
+ *************************************************************************/
+
+this function is called when there is an objection to a NetBIOS
+name being registered. this will always be done through a negative
+response to a name registration, whether it be by a host that
+already owns the unique name being registered on a subnet, or
+by a WINS server.
+
+the name being objected to must be removed from samba's records.
+
+it has the additional responsibility of checking whether samba is
+currently a master browser or not, and if so it should initiate
+becoming a non-master.
+
+
+
+/*************************************************************************
+ send_election()
+ *************************************************************************/
+
+this function is responsible for sending a browse mailslot
+datagram election packet (of type ANN_Election). it constructs
+the packet with all the relevant info needed to participate:
+election version; election criteria; time since startup and
+our name.
+
+this function can be used to ensure that initiate but lose an
+election by specifying a criteria and time up of zero. this
+is necessary if we are a master browser and we are about to
+go down (politely!) - see nmbd.c:sig_term().
+
+
+/*************************************************************************
+ browser_gone()
+ *************************************************************************/
+
+this function is responsible for dealing with the instance when
+the master browser we thought was present on a subnet is no longer
+responding.
+
+if it is samba's workgroup, and it's a local interface, samba
+detects that it can participate in an election on that interface
+and potentially become a master browser or domain master.
+
+if it's a local subnet and not one of samba's workgroups, then
+samba will force an election (which it is not obliged to do).
+remove_workgroup() will be expected to remove all references
+to this workgroup and the servers in it from the database.
+
+if it's a remote subnet and not one of samba's workgroups then
+no election is forced, and remove_workgroup() will be expected
+to remove all server entries from this workgroup _except_ those
+added from the lmhosts file. if there are entries added from
+the lmhosts file, then the workgroup entry will remain,
+otherwise it too will be removed.
+
+
+/*************************************************************************
+ check_master_browser()
+ *************************************************************************/
+
+this function is responsible for periodically checking whether
+master browsers that samba expects to be alive are alive. this
+is done every CHECK_TIME_MST_BROWSE minutes.
+
+for every workgroup record for which samba is not a master browser,
+on both local and remote interfaces, samba will initiate a
+broadcast query for a master browser on that subnet.
+
+(browser_gone() will be called to deal with the case where no
+response is received to the NAME_QUERY_MST_CHK initiated here.
+no action is required when a response _is_ received, however:
+see nameservresp.c:response_process() and dead_netbios_entry()
+for details)
+
+
diff --git a/source/namelogon.c b/source/namelogon.c
new file mode 100644
index 00000000000..1f57139d56a
--- /dev/null
+++ b/source/namelogon.c
@@ -0,0 +1,145 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Revision History:
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+*/
+
+#include "includes.h"
+
+extern int ClientDGRAM;
+
+#define TEST_CODE /* want to debug unknown browse packets */
+
+extern int DEBUGLEVEL;
+
+extern pstring myname;
+
+
+/****************************************************************************
+ process a domain logon packet
+
+ **************************************************************************/
+void process_logon_packet(struct packet_struct *p,char *buf,int len)
+{
+ struct dgram_packet *dgram = &p->packet.dgram;
+ char *logname,*q;
+ fstring reply_name;
+ BOOL add_slashes = False;
+ pstring outbuf;
+ int code,reply_code;
+ char unknown_byte = 0;
+ uint16 request_count = 0;
+ uint16 token = 0;
+
+ if (!lp_domain_logons())
+ {
+ DEBUG(3,("No domain logons\n"));
+ return;
+ }
+
+
+ code = SVAL(buf,0);
+ switch (code)
+ {
+ case 0:
+ {
+ char *machine = buf+2;
+ char *user = skip_string(machine,1);
+ char *tmp;
+ logname = skip_string(user,1);
+ tmp = skip_string(logname,1);
+ unknown_byte = CVAL(tmp,0);
+ request_count = SVAL(tmp,1);
+ token = SVAL(tmp,3);
+
+ reply_code = 0x6;
+ fstrcpy(reply_name,myname);
+ strupper(reply_name);
+ add_slashes = True;
+ DEBUG(3,("Domain login request from %s(%s) user=%s token=%x\n",
+ machine,inet_ntoa(p->ip),user,token));
+ break;
+ }
+ case 7:
+ {
+ char *machine = buf+2;
+ logname = skip_string(machine,1);
+ token = SVAL(skip_string(logname,1),0);
+
+ fstrcpy(reply_name,lp_domain_controller());
+ if (!*reply_name)
+ {
+ /* oo! no domain controller. must be us, then */
+ fstrcpy(reply_name,myname);
+ reply_code = 0xC;
+ }
+ else
+ {
+ /* refer logon request to the domain controller */
+ reply_code = 0x7;
+ }
+
+ strupper(reply_name);
+ DEBUG(3,("GETDC request from %s(%s), reporting %s 0x%x token=%x\n",
+ machine,inet_ntoa(p->ip), reply_name, reply_code,token));
+ break;
+ }
+ default:
+ {
+ DEBUG(3,("Unknown domain request %d\n",code));
+ return;
+ }
+ }
+
+ bzero(outbuf,sizeof(outbuf));
+ q = outbuf;
+ SSVAL(q,0,reply_code);
+ q += 2;
+
+ if (token == 0xffff || /* LM 2.0 or later */
+ token == 0xfffe) /* WfWg networking */
+ {
+ if (add_slashes)
+ {
+ strcpy(q,"\\\\");
+ q += 2;
+ }
+ strcpy(q, reply_name);
+ strupper(q);
+ q = skip_string(q,1);
+
+ if (token == 0xffff) /* LM 2.0 or later */
+ {
+ SSVAL(q,0,token);
+ q += 2;
+ }
+ }
+
+ SSVAL(q,0,0xFFFF);
+ q += 2;
+
+ send_mailslot_reply(True, logname,ClientDGRAM,outbuf,PTR_DIFF(q,outbuf),
+ myname,&dgram->source_name.name[0],0x20,0,p->ip,
+ *iface_ip(p->ip));
+}
diff --git a/source/namelogon.doc b/source/namelogon.doc
new file mode 100644
index 00000000000..c4a97d0cf16
--- /dev/null
+++ b/source/namelogon.doc
@@ -0,0 +1,36 @@
+/*
+ Unix SMB/Netbios documentation.
+ Version 0.0
+ Copyright (C) Luke Leighton Andrew Tridgell 1996
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Document name: namelogon.doc
+
+ Revision History:
+
+ 0.0 - 02jul96 : lkcl@pires.co.uk
+ created
+*/
+
+this module deals with the first stage of domain logons. there is much
+more work to be done on this: it's all totally undocumented.
+
+
+/*************************************************************************
+ process_logon_packet()
+ *************************************************************************/
+
+a function that processes logon packets (the most helpful comment yet :-).
diff --git a/source/namepacket.c b/source/namepacket.c
new file mode 100644
index 00000000000..fb8e4d2bf5b
--- /dev/null
+++ b/source/namepacket.c
@@ -0,0 +1,642 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Revision History:
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+*/
+
+#include "includes.h"
+
+extern int ClientNMB;
+extern int ClientDGRAM;
+
+extern int DEBUGLEVEL;
+
+extern int num_response_packets;
+
+BOOL CanRecurse = True;
+extern pstring scope;
+extern struct in_addr wins_ip;
+extern struct in_addr loopback_ip;
+
+static uint16 name_trn_id=0;
+
+
+/***************************************************************************
+ updates the unique transaction identifier
+ **************************************************************************/
+void debug_browse_data(char *outbuf, int len)
+{
+ int i,j;
+ for (i = 0; i < len; i+= 16)
+ {
+ DEBUG(4, ("%3x char ", i));
+
+ for (j = 0; j < 16; j++)
+ {
+ unsigned char x = outbuf[i+j];
+ if (x < 32 || x > 127) x = '.';
+
+ if (i+j >= len) break;
+ DEBUG(4, ("%c", x));
+ }
+
+ DEBUG(4, (" hex ", i));
+
+ for (j = 0; j < 16; j++)
+ {
+ if (i+j >= len) break;
+ DEBUG(4, (" %02x", (unsigned char)outbuf[i+j]));
+ }
+
+ DEBUG(4, ("\n"));
+ }
+
+}
+
+
+/***************************************************************************
+ updates the unique transaction identifier
+ **************************************************************************/
+static void update_name_trn_id(void)
+{
+ if (!name_trn_id)
+ {
+ name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100);
+ }
+ name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
+}
+
+
+/****************************************************************************
+ initiate a netbios packet
+ ****************************************************************************/
+void initiate_netbios_packet(uint16 *id,
+ int fd,int quest_type,char *name,int name_type,
+ int nb_flags,BOOL bcast,BOOL recurse,
+ struct in_addr to_ip)
+{
+ struct packet_struct p;
+ struct nmb_packet *nmb = &p.packet.nmb;
+ struct res_rec additional_rec;
+ char *packet_type = "unknown";
+ int opcode = -1;
+
+ if (!id) return;
+
+ if (quest_type == NMB_STATUS) { packet_type = "nmb_status"; opcode = 0; }
+ if (quest_type == NMB_QUERY ) { packet_type = "nmb_query"; opcode = 0; }
+ if (quest_type == NMB_REG ) { packet_type = "nmb_reg"; opcode = 5; }
+ if (quest_type == NMB_REG_REFRESH ) { packet_type = "nmb_reg_refresh"; opcode = 9; }
+ if (quest_type == NMB_REL ) { packet_type = "nmb_rel"; opcode = 6; }
+
+ DEBUG(4,("initiating netbios packet: %s %s(%x) (bcast=%s) %s\n",
+ packet_type, name, name_type, BOOLSTR(bcast), inet_ntoa(to_ip)));
+
+ if (opcode == -1) return;
+
+ bzero((char *)&p,sizeof(p));
+
+ if (*id == 0xffff) {
+ update_name_trn_id();
+ *id = name_trn_id; /* allow resending with same id */
+ }
+
+ nmb->header.name_trn_id = *id;
+ nmb->header.opcode = opcode;
+ nmb->header.response = False;
+
+ nmb->header.nm_flags.bcast = bcast;
+ nmb->header.nm_flags.recursion_available = False;
+ nmb->header.nm_flags.recursion_desired = recurse;
+ nmb->header.nm_flags.trunc = False;
+ nmb->header.nm_flags.authoritative = False;
+
+ nmb->header.rcode = 0;
+ nmb->header.qdcount = 1;
+ nmb->header.ancount = 0;
+ nmb->header.nscount = 0;
+ nmb->header.arcount = (quest_type==NMB_REG ||
+ quest_type==NMB_REL ||
+ quest_type==NMB_REG_REFRESH) ? 1 : 0;
+
+ make_nmb_name(&nmb->question.question_name,name,name_type,scope);
+
+ nmb->question.question_type = quest_type == NMB_STATUS ? 0x21 : 0x20;
+ nmb->question.question_class = 0x1;
+
+ if (quest_type == NMB_REG ||
+ quest_type == NMB_REG_REFRESH ||
+ quest_type == NMB_REL)
+ {
+ nmb->additional = &additional_rec;
+ bzero((char *)nmb->additional,sizeof(*nmb->additional));
+
+ nmb->additional->rr_name = nmb->question.question_name;
+ nmb->additional->rr_type = 0x20;
+ nmb->additional->rr_class = 0x1;
+
+ if (quest_type == NMB_REG || quest_type == NMB_REG_REFRESH)
+ nmb->additional->ttl = lp_max_ttl();
+ else
+ nmb->additional->ttl = 0;
+
+ nmb->additional->rdlength = 6;
+ nmb->additional->rdata[0] = nb_flags;
+ putip(&nmb->additional->rdata[2],(char *)iface_ip(to_ip));
+ }
+
+ p.ip = to_ip;
+ p.port = NMB_PORT;
+ p.fd = fd;
+ p.timestamp = time(NULL);
+ p.packet_type = NMB_PACKET;
+
+ debug_nmb_packet(&p);
+
+ if (!send_packet(&p)) {
+ DEBUG(3,("send_packet to %s %d failed\n",inet_ntoa(p.ip),p.port));
+ *id = 0xffff;
+ }
+
+ return;
+}
+
+
+/****************************************************************************
+ reply to a netbios name packet. see rfc1002.txt
+ ****************************************************************************/
+void reply_netbios_packet(struct packet_struct *p1,int trn_id,
+ int rcode, int rcv_code, int opcode,
+ BOOL recursion_available,
+ BOOL recursion_desired,
+ struct nmb_name *rr_name,int rr_type,int rr_class,int ttl,
+ char *data,int len)
+{
+ struct packet_struct p;
+ struct nmb_packet *nmb = &p.packet.nmb;
+ struct res_rec answers;
+ char *packet_type = "unknown";
+
+ p = *p1;
+
+ switch (rcv_code)
+ {
+ case NMB_STATUS:
+ {
+ packet_type = "nmb_status";
+ break;
+ }
+ case NMB_QUERY:
+ {
+ packet_type = "nmb_query";
+ break;
+ }
+ case NMB_REG:
+ {
+ packet_type = "nmb_reg";
+ break;
+ }
+ case NMB_REL:
+ {
+ packet_type = "nmb_rel";
+ break;
+ }
+ case NMB_WAIT_ACK:
+ {
+ packet_type = "nmb_wack";
+ break;
+ }
+ default:
+ {
+ DEBUG(1,("replying netbios packet: %s %s %s\n",
+ packet_type, namestr(rr_name), inet_ntoa(p.ip)));
+
+ return;
+ }
+ }
+
+ DEBUG(4,("replying netbios packet: %s %s %s\n",
+ packet_type, namestr(rr_name), inet_ntoa(p.ip)));
+
+ nmb->header.name_trn_id = trn_id;
+ nmb->header.opcode = opcode;
+ nmb->header.response = True;
+ nmb->header.nm_flags.bcast = False;
+ nmb->header.nm_flags.recursion_available = recursion_available;
+ nmb->header.nm_flags.recursion_desired = recursion_desired;
+ nmb->header.nm_flags.trunc = False;
+ nmb->header.nm_flags.authoritative = True;
+
+ nmb->header.qdcount = 0;
+ nmb->header.ancount = 1;
+ nmb->header.nscount = 0;
+ nmb->header.arcount = 0;
+ nmb->header.rcode = rcode;
+
+ bzero((char*)&nmb->question,sizeof(nmb->question));
+
+ nmb->answers = &answers;
+ bzero((char*)nmb->answers,sizeof(*nmb->answers));
+
+ nmb->answers->rr_name = *rr_name;
+ nmb->answers->rr_type = rr_type;
+ nmb->answers->rr_class = rr_class;
+ nmb->answers->ttl = ttl;
+
+ if (data && len)
+ {
+ nmb->answers->rdlength = len;
+ memcpy(nmb->answers->rdata, data, len);
+ }
+
+ p.packet_type = NMB_PACKET;
+
+ debug_nmb_packet(&p);
+
+ send_packet(&p);
+}
+
+
+/*******************************************************************
+ the global packet linked-list. incoming entries are added to the
+ end of this list. it is supposed to remain fairly short so we
+ won't bother with an end pointer.
+ ******************************************************************/
+static struct packet_struct *packet_queue = NULL;
+
+/*******************************************************************
+ queue a packet into the packet queue
+ ******************************************************************/
+void queue_packet(struct packet_struct *packet)
+{
+ struct packet_struct *p;
+
+ if (!packet_queue) {
+ packet->prev = NULL;
+ packet->next = NULL;
+ packet_queue = packet;
+ return;
+ }
+
+ /* find the bottom */
+ for (p=packet_queue;p->next;p=p->next) ;
+
+ p->next = packet;
+ packet->next = NULL;
+ packet->prev = p;
+}
+
+/****************************************************************************
+ determine if a packet is for us. Note that to have any chance of
+ being efficient we need to drop as many packets as possible at this
+ stage as subsequent processing is expensive.
+
+ We also must make absolutely sure we don't tread on another machines
+ property by answering a packet that is not for us.
+ ****************************************************************************/
+static BOOL listening(struct packet_struct *p,struct nmb_name *n)
+{
+ struct subnet_record *d;
+ struct name_record *n1;
+
+ /* We explicitly don't search WINS here - this will be done
+ in find_name_search if it was a packet from a non-local subnet. */
+ d = find_subnet(p->ip);
+
+ n1 = find_name_search(&d,n,FIND_LOCAL|FIND_WINS|FIND_SELF,p->ip);
+
+ return (n1 != NULL);
+}
+
+
+/****************************************************************************
+ process udp 138 datagrams
+ ****************************************************************************/
+static void process_dgram(struct packet_struct *p)
+{
+ char *buf;
+ char *buf2;
+ int len;
+ struct dgram_packet *dgram = &p->packet.dgram;
+
+ /* if we aren't listening to the destination name then ignore the packet */
+ if (!listening(p,&dgram->dest_name))
+ {
+ DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s(%x) from %s\n",
+ dgram->dest_name.name, dgram->dest_name.name_type, inet_ntoa(p->ip)));
+ return;
+ }
+
+ if (dgram->header.msg_type != 0x10 &&
+ dgram->header.msg_type != 0x11 &&
+ dgram->header.msg_type != 0x12)
+ {
+ /* don't process error packets etc yet */
+ DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s(%d) from %s as it is \
+ an error packet of type %x\n",
+ dgram->dest_name.name, dgram->dest_name.name_type,
+ inet_ntoa(p->ip), dgram->header.msg_type));
+ return;
+ }
+
+ buf = &dgram->data[0];
+ buf -= 4; /* XXXX for the pseudo tcp length -
+ someday I need to get rid of this */
+
+ if (CVAL(buf,smb_com) != SMBtrans) return;
+
+ len = SVAL(buf,smb_vwv11);
+ buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
+
+ DEBUG(4,("process_dgram: datagram from %s to %s for %s of type %d len=%d\n",
+ namestr(&dgram->source_name),namestr(&dgram->dest_name),
+ smb_buf(buf),CVAL(buf2,0),len));
+
+
+ if (len <= 0) return;
+
+ /* datagram packet received for the browser mailslot */
+ if (strequal(smb_buf(buf),BROWSE_MAILSLOT)) {
+ process_browse_packet(p,buf2,len);
+ return;
+ }
+
+ /* datagram packet received for the domain log on mailslot */
+ if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT)) {
+ process_logon_packet(p,buf2,len);
+ return;
+ }
+}
+
+/****************************************************************************
+ process a nmb packet
+ ****************************************************************************/
+static void process_nmb(struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+
+ debug_nmb_packet(p);
+
+ switch (nmb->header.opcode)
+ {
+ case 8: /* what is this?? */
+ case NMB_REG:
+ case NMB_REG_REFRESH:
+ {
+ if (nmb->header.response)
+ {
+ if (nmb->header.ancount ==0) break;
+ response_netbios_packet(p); /* response to registration dealt
+ with here */
+ }
+ else
+ {
+ if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
+ reply_name_reg(p);
+ }
+ break;
+ }
+
+ case 0:
+ {
+ if (nmb->header.response)
+ {
+ switch (nmb->question.question_type)
+ {
+ case 0x0:
+ {
+ response_netbios_packet(p);
+ break;
+ }
+ }
+ return;
+ }
+ else if (nmb->header.qdcount>0)
+ {
+ switch (nmb->question.question_type)
+ {
+ case NMB_QUERY:
+ {
+ reply_name_query(p);
+ break;
+ }
+ case NMB_STATUS:
+ {
+ reply_name_status(p);
+ break;
+ }
+ }
+ return;
+ }
+ break;
+ }
+
+ case NMB_REL:
+ {
+ if (nmb->header.response)
+ {
+ if (nmb->header.ancount ==0) break;
+ response_netbios_packet(p); /* response to release dealt
+ with here */
+ }
+ else
+ {
+ if (nmb->header.qdcount==0 || nmb->header.arcount==0) break;
+ reply_name_release(p);
+ }
+ break;
+ }
+ }
+}
+
+
+/*******************************************************************
+ run elements off the packet queue till its empty
+ ******************************************************************/
+void run_packet_queue()
+{
+ struct packet_struct *p;
+
+ while ((p=packet_queue))
+ {
+ switch (p->packet_type)
+ {
+ case NMB_PACKET:
+ process_nmb(p);
+ break;
+
+ case DGRAM_PACKET:
+ process_dgram(p);
+ break;
+ }
+
+ packet_queue = packet_queue->next;
+ if (packet_queue) packet_queue->prev = NULL;
+ free_packet(p);
+ }
+}
+
+/****************************************************************************
+ listens for NMB or DGRAM packets, and queues them
+ ***************************************************************************/
+void listen_for_packets(BOOL run_election)
+{
+ fd_set fds;
+ int selrtn;
+ struct timeval timeout;
+
+ FD_ZERO(&fds);
+ FD_SET(ClientNMB,&fds);
+ FD_SET(ClientDGRAM,&fds);
+
+ /* during elections and when expecting a netbios response packet we
+ need to send election packets at tighter intervals
+
+ ideally it needs to be the interval (in ms) between time now and
+ the time we are expecting the next netbios packet */
+
+ timeout.tv_sec = (run_election||num_response_packets) ? 1:NMBD_SELECT_LOOP;
+ timeout.tv_usec = 0;
+
+ /* We can only take term signals when we are in the select. */
+ BlockSignals(False, SIGTERM);
+ selrtn = sys_select(&fds,&timeout);
+ BlockSignals(True, SIGTERM);
+
+ if (FD_ISSET(ClientNMB,&fds))
+ {
+ struct packet_struct *packet = read_packet(ClientNMB, NMB_PACKET);
+ if (packet)
+ {
+ if ((ip_equal(loopback_ip, packet->ip) ||
+ ismyip(packet->ip)) &&
+ packet->port == NMB_PORT)
+ {
+ DEBUG(7,("discarding own packet from %s:%d\n",
+ inet_ntoa(packet->ip),packet->port));
+ free_packet(packet);
+ }
+ else
+ {
+ queue_packet(packet);
+ }
+ }
+ }
+
+ if (FD_ISSET(ClientDGRAM,&fds))
+ {
+ struct packet_struct *packet = read_packet(ClientDGRAM, DGRAM_PACKET);
+ if (packet)
+ {
+ if ((ip_equal(loopback_ip, packet->ip) ||
+ ismyip(packet->ip)) &&
+ packet->port == DGRAM_PORT)
+ {
+ DEBUG(7,("discarding own packet from %s:%d\n",
+ inet_ntoa(packet->ip),packet->port));
+ free_packet(packet);
+ }
+ else
+ {
+ queue_packet(packet);
+ }
+ }
+ }
+}
+
+
+
+/****************************************************************************
+ construct and send a netbios DGRAM
+
+ Note that this currently sends all answers to port 138. thats the
+ wrong things to do! I should send to the requestors port. XXX
+ **************************************************************************/
+BOOL send_mailslot_reply(BOOL unique, char *mailslot,int fd,char *buf,int len,char *srcname,
+ char *dstname,int src_type,int dest_type,
+ struct in_addr dest_ip,struct in_addr src_ip)
+{
+ struct packet_struct p;
+ struct dgram_packet *dgram = &p.packet.dgram;
+ char *ptr,*p2;
+ char tmp[4];
+
+ /* ha ha. no. do NOT send packets to 255.255.255.255: it's a pseudo address */
+ if (ip_equal(wins_ip, dest_ip)) return False;
+
+ bzero((char *)&p,sizeof(p));
+
+ update_name_trn_id();
+
+ /* DIRECT GROUP or UNIQUE datagram */
+ dgram->header.msg_type = unique ? 0x10 : 0x11;
+ dgram->header.flags.node_type = M_NODE;
+ dgram->header.flags.first = True;
+ dgram->header.flags.more = False;
+ dgram->header.dgm_id = name_trn_id;
+ dgram->header.source_ip = src_ip;
+ dgram->header.source_port = DGRAM_PORT;
+ dgram->header.dgm_length = 0; /* let build_dgram() handle this */
+ dgram->header.packet_offset = 0;
+
+ make_nmb_name(&dgram->source_name,srcname,src_type,scope);
+ make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
+
+ ptr = &dgram->data[0];
+
+ /* now setup the smb part */
+ ptr -= 4; /* XXX ugliness because of handling of tcp SMB length */
+ memcpy(tmp,ptr,4);
+ set_message(ptr,17,17 + len,True);
+ memcpy(ptr,tmp,4);
+
+ CVAL(ptr,smb_com) = SMBtrans;
+ SSVAL(ptr,smb_vwv1,len);
+ SSVAL(ptr,smb_vwv11,len);
+ SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
+ SSVAL(ptr,smb_vwv13,3);
+ SSVAL(ptr,smb_vwv14,1);
+ SSVAL(ptr,smb_vwv15,1);
+ SSVAL(ptr,smb_vwv16,2);
+ p2 = smb_buf(ptr);
+ strcpy(p2,mailslot);
+ p2 = skip_string(p2,1);
+
+ memcpy(p2,buf,len);
+ p2 += len;
+
+ dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length */
+
+ p.ip = dest_ip;
+ p.port = DGRAM_PORT;
+ p.fd = ClientDGRAM;
+ p.timestamp = time(NULL);
+ p.packet_type = DGRAM_PACKET;
+
+ DEBUG(4,("send mailslot %s from %s %s", mailslot,
+ inet_ntoa(src_ip),namestr(&dgram->source_name)));
+ DEBUG(4,("to %s %s\n", inet_ntoa(dest_ip),namestr(&dgram->dest_name)));
+
+ return(send_packet(&p));
+}
diff --git a/source/namepacket.doc b/source/namepacket.doc
new file mode 100644
index 00000000000..159a50738c5
--- /dev/null
+++ b/source/namepacket.doc
@@ -0,0 +1,133 @@
+/*
+ Unix SMB/Netbios documentation.
+ Version 0.0
+ Copyright (C) Luke Leighton Andrew Tridgell 1996
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Document name: namepacket.doc
+
+ Revision History:
+
+ 0.0 - 02jul96 : lkcl@pires.co.uk
+ created
+*/
+
+this module deals with packets: sending, receiving, queueing
+and some basic interpretation (e.g it excludes datagram
+error packets at the moment).
+
+the packet queueing mechanism was originally introduced when
+samba dealt with responses by sending a packet, receiving
+packets and queueing all packets that didn't match up with
+the response expected. this is fine in a single-thread
+environment, but samba now deals with response packets by
+queueing the responses. to some extent, therefore, this
+queue_packet mechanism is redundant.
+
+
+/*************************************************************************
+ send_mailslot_reply()
+ *************************************************************************/
+
+this function is responsible for sending a MAILSLOT packet.
+
+it will _not_ send packets to the pseudo WINS subnet's address of
+255.255.255.255: this would be disastrous.
+
+each packet sent out has a unique transaction identifier. this is done
+so that responses can be matched later with the original purpose for
+the packet being sent out in the first place.
+
+
+/*************************************************************************
+ listen_for_packets()
+ *************************************************************************/
+
+this function is responsible for reading NMB and DGRAM packets, and then
+queueing them. it will normally time-out for NMBD_SELECT_LOOP seconds, but
+if there is an election currently running or we are expecting a response
+then this time is reduced to 1 second.
+
+note: the time-out period needs refining to the millisecond level.
+
+
+/*************************************************************************
+ queue_packet()
+ *************************************************************************/
+
+this function is responsible for queueing any NMB and DGRAM packets passed
+to it. these packets will be removed from the queue in run_packet_queue().
+
+
+/*************************************************************************
+ run_packet_queue()
+ *************************************************************************/
+
+this function is responsible for taking a packet off the queue,
+identifying whether it is an NMB or a DGRAM packet, processing
+it accordingly and deleting it. this process continues until
+there are no more packets on the queue.
+
+
+/*************************************************************************
+ process_nmb()
+ *************************************************************************/
+
+this function receives a packet identified as a netbios packet.
+it further identifies whether it is a response or a query packet.
+by identifying the type of packet (name registration, query etc)
+process_nmb() will call the appropriate function to deal with the
+type of packet received.
+
+
+/*************************************************************************
+ process_dgram()
+ *************************************************************************/
+
+this function is responsible for identifying whether the datagram
+packet received is a browser packet or a domain logon packet. it
+also does some filtering of certain types of packets (e.g it
+filters out error packets).
+
+
+/*************************************************************************
+ reply_netbios_packet()
+ *************************************************************************/
+
+this function is responsible for sending a reply to another NetBIOS
+packet from another host. it can be used to send a reply to a name
+registration, name release, name query or name status request.
+
+the reply can be either a positive or a negative one.
+
+
+/*************************************************************************
+ initiate_netbios_packet()
+ *************************************************************************/
+
+this function is responsible for construction a netbios packet and sending
+it. if the packet has not had a unique transaction id allocated to it,
+then initiate_netbios_packet() will give it one.
+
+
+/*************************************************************************
+ update_name_trn_id()
+ *************************************************************************/
+
+this function is responsible for allocating unique transaction identifiers
+for each new packet sent on the network.
+
+
diff --git a/source/namequery.doc b/source/namequery.doc
new file mode 100644
index 00000000000..4337cfb7e2a
--- /dev/null
+++ b/source/namequery.doc
@@ -0,0 +1,83 @@
+/*
+ Unix SMB/Netbios documentation.
+ Version 0.0
+ Copyright (C) Luke Leighton Andrew Tridgell 1996
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Document name: namequery.doc
+
+ Revision History:
+
+ 0.0 - 02jul96 : lkcl@pires.co.uk
+ created
+*/
+
+this module contains non-threaded versions of name status and name
+query functions. if a multi-threaded nmbd was to be written, these
+functions would be the starting point.
+
+at the moment, the expected response queueing system is used to
+replace these functions without needing to multi-thread nmbd.
+
+these functions are used in smbclient and nmblookup at present to
+avoid having the vast quantities of complex and unused code needed
+to support even a simple name query (or providing stubs for the
+unused side of these functions).
+
+there is a down-side to these functions, which is all microsoft's
+fault. microsoft machines always always reply to queries on the
+priveleged ports, rather than following the usual tcp/ip mechanism
+of replying on the client's port (the exception to this i am led
+to believe is windows nt 3.50).
+
+as a result of this, in order to receive a response to a name
+query from a microsoft machine, we must be able to listen on
+the priveleged netbios name server ports. this is simply not
+possible with some versions of unix, unless you have root access.
+
+it is also not possible if you run smbclient or nmblookup on an
+interface that already has been claimed by the netbios name server
+daemon nmbd.
+
+all in all, i wish that microsoft would fix this.
+
+a solution does exist: nmbd _does_ actually reply on the client's
+port, so if smbclient and nmblookup were to use nmbd as a proxy
+forwarder of queries (or to use samba's WINS capabilities) then
+a query could be made without needing access to the priveleged
+ports. in order to do this properly, samba must implement secured
+netbios name server functionality (see rfc1001.txt 15.1.6).
+(lkcl 01aug96: samba now supports secured name registration)
+
+/*************************************************************************
+ name_query()
+ *************************************************************************/
+
+
+
+/*************************************************************************
+ name_status()
+ *************************************************************************/
+
+
+
+/*************************************************************************
+ _interpret_node_status()
+ *************************************************************************/
+
+
+this is a older version of interpret_node_status().
+
diff --git a/source/nameresp.c b/source/nameresp.c
new file mode 100644
index 00000000000..c40dd16a888
--- /dev/null
+++ b/source/nameresp.c
@@ -0,0 +1,326 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios library routines
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ 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.
+
+ Module name: nameresp.c
+
+*/
+
+#include "includes.h"
+
+extern int ClientNMB;
+extern int ClientDGRAM;
+
+extern struct subnet_record *subnetlist;
+
+extern int DEBUGLEVEL;
+
+extern pstring scope;
+extern struct in_addr ipzero;
+extern struct in_addr wins_ip;
+
+
+/***************************************************************************
+ deals with an entry before it dies
+ **************************************************************************/
+static void dead_netbios_entry(struct subnet_record *d,
+ struct response_record *n)
+{
+ DEBUG(3,("Removing dead netbios entry for %s %s (num_msgs=%d)\n",
+ inet_ntoa(n->send_ip), namestr(&n->name), n->num_msgs));
+
+ debug_state_type(n->state);
+
+ switch (n->state)
+ {
+ case NAME_QUERY_CONFIRM:
+ {
+ if (!lp_wins_support()) return; /* only if we're a WINS server */
+
+ if (n->num_msgs == 0)
+ {
+ /* oops. name query had no response. check that the name is
+ unique and then remove it from our WINS database */
+
+ /* IMPORTANT: see query_refresh_names() */
+
+ if ((!NAME_GROUP(n->nb_flags)))
+ {
+ struct subnet_record *d1 = wins_subnet;
+ if (d1)
+ {
+ /* remove the name that had been registered with us,
+ and we're now getting no response when challenging.
+ see rfc1001.txt 15.5.2
+ */
+ remove_netbios_name(d1, n->name.name, n->name.name_type,
+ REGISTER, n->send_ip);
+ }
+ }
+ }
+ break;
+ }
+
+ case NAME_QUERY_MST_CHK:
+ {
+ /* if no response received, the master browser must have gone
+ down on that subnet, without telling anyone. */
+
+ /* IMPORTANT: see response_netbios_packet() */
+
+ if (n->num_msgs == 0)
+ browser_gone(n->name.name, n->send_ip);
+ break;
+ }
+
+ case NAME_RELEASE:
+ {
+ /* if no response received, it must be OK for us to release the
+ name. nobody objected (including a potentially dead or deaf
+ WINS server) */
+
+ /* IMPORTANT: see response_name_release() */
+
+ if (ismyip(n->send_ip))
+ {
+ name_unregister_work(d,n->name.name,n->name.name_type);
+ }
+ if (!n->bcast && n->num_msgs == 0)
+ {
+ DEBUG(0,("WINS server did not respond to name release!\n"));
+ /* XXXX whoops. we have problems. must deal with this */
+ }
+ break;
+ }
+
+ case NAME_REGISTER_CHALLENGE:
+ {
+ /* name challenge: no reply. we can reply to the person that
+ wanted the unique name and tell them that they can have it
+ */
+
+ add_name_respond(d,n->fd,d->myip, n->reply_id ,&n->name,
+ n->nb_flags, GET_TTL(0),
+ n->reply_to_ip, True, n->reply_to_ip);
+
+ if (!n->bcast && n->num_msgs == 0)
+ {
+ DEBUG(1,("WINS server did not respond to name registration!\n"));
+ /* XXXX whoops. we have problems. must deal with this */
+ }
+ break;
+ }
+
+ case NAME_REGISTER:
+ {
+ /* if no response received, and we are using a broadcast registration
+ method, it must be OK for us to register the name: nobody objected
+ on that subnet. if we are using a WINS server, then the WINS
+ server must be dead or deaf.
+ */
+ if (n->num_msgs == 0)
+ {
+ if (n->bcast)
+ {
+ /* broadcast method: implicit acceptance of the name registration
+ by not receiving any objections. */
+
+ /* IMPORTANT: see response_name_reg() */
+
+ name_register_work(d,n->name.name,n->name.name_type,
+ n->nb_flags, n->ttl, n->reply_to_ip, n->bcast);
+ }
+ else
+ {
+ /* received no response. rfc1001.txt states that after retrying,
+ we should assume the WINS server is dead, and fall back to
+ broadcasting (see bits about M nodes: can't find any right
+ now) */
+
+ DEBUG(1,("WINS server did not respond to name registration!\n"));
+ /* XXXX whoops. we have problems. must deal with this */
+ }
+ }
+ break;
+ }
+
+ case NAME_QUERY_DOMAIN:
+ {
+ /* if no response was received, there is no domain controller for
+ this DOMAIN registered within WINS. it's ok for us to register
+ the DOMAIN<1b> name.
+ */
+
+ if (n->num_msgs == 0)
+ {
+ struct work_record *work = find_workgroupstruct(d,n->name.name,False);
+ if (work && d)
+ {
+ become_domain_master(d,work);
+ }
+ }
+ else
+ {
+ DEBUG(1, ("nmbd configured as domain master and one already exists\n"));
+ }
+ break;
+ }
+
+ default:
+ {
+ /* nothing to do but delete the dead expected-response structure */
+ /* this is normal. */
+ break;
+ }
+ }
+}
+
+
+/*******************************************************************
+ remove old name response entries
+
+ XXXX retry code needs to be added, including a retry wait period and a count
+ see name_query() and name_status() for suggested implementation.
+
+ ******************************************************************/
+void expire_netbios_response_entries(time_t t)
+{
+ struct subnet_record *d;
+
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ {
+ struct response_record *n, *nextn;
+
+ for (n = d->responselist; n; n = nextn)
+ {
+ nextn = n->next;
+
+ if (n->repeat_time <= t)
+ {
+ if (n->repeat_count > 0)
+ {
+ /* resend the entry */
+ initiate_netbios_packet(&n->response_id, n->fd, n->quest_type,
+ n->name.name, n->name.name_type,
+ n->nb_flags, n->bcast, n->recurse, n->send_ip);
+
+ n->repeat_time += n->repeat_interval; /* XXXX ms needed */
+ n->repeat_count--;
+
+ }
+ else
+ {
+ DEBUG(4,("timeout response %d for %s %s\n",
+ n->response_id, namestr(&n->name),
+ inet_ntoa(n->send_ip)));
+
+ dead_netbios_entry(d,n); /* process the non-response */
+ remove_response_record(d,n); /* remove the non-response */
+
+ continue;
+ }
+ }
+ }
+ }
+}
+
+
+/****************************************************************************
+ wrapper function to override a broadcast message and send it to the WINS
+ name server instead, if it exists. if wins is false, and there has been no
+ WINS server specified, the packet will NOT be sent.
+ ****************************************************************************/
+struct response_record *queue_netbios_pkt_wins(
+ int fd,int quest_type,enum state_type state,
+ char *name,int name_type,int nb_flags, time_t ttl,
+ int server_type, char *my_name, char *my_comment,
+ struct in_addr send_ip, struct in_addr reply_to_ip)
+{
+ /* XXXX note: please see rfc1001.txt section 10 for details on this
+ function: it is currently inappropriate to use this - it will do
+ for now - once there is a clarification of B, M and P nodes and
+ which one samba is supposed to be
+ */
+
+ if ((!lp_wins_support()) && (*lp_wins_server()))
+ {
+ /* samba is not a WINS server, and we are using a WINS server */
+ struct in_addr real_wins_ip;
+ real_wins_ip = *interpret_addr2(lp_wins_server());
+
+ if (!zero_ip(real_wins_ip))
+ {
+ send_ip = real_wins_ip;
+ }
+ else
+ {
+ /* oops. smb.conf's wins server parameter MUST be a host_name
+ or an ip_address. */
+ DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
+ }
+ }
+
+ if (zero_ip(send_ip)) return NULL;
+
+ return queue_netbios_packet(wins_subnet,fd, quest_type, state,
+ name, name_type, nb_flags, ttl,
+ server_type,my_name,my_comment,
+ False, True, send_ip, reply_to_ip, 0);
+}
+
+
+/****************************************************************************
+ initiate a netbios name query to find someone's or someones' IP
+ this is intended to be used (not exclusively) for broadcasting to
+ master browsers (WORKGROUP(1d or 1b) or __MSBROWSE__(1)) to get
+ complete lists across a wide area network
+ ****************************************************************************/
+struct response_record *queue_netbios_packet(struct subnet_record *d,
+ int fd,int quest_type,enum state_type state,char *name,
+ int name_type,int nb_flags, time_t ttl,
+ int server_type, char *my_name, char *my_comment,
+ BOOL bcast,BOOL recurse,
+ struct in_addr send_ip, struct in_addr reply_to_ip,
+ int reply_id)
+{
+ struct response_record *n;
+ uint16 id = 0xffff;
+
+ /* ha ha. no. do NOT broadcast to 255.255.255.255: it's a pseudo address */
+ if (ip_equal(wins_ip, send_ip)) return NULL;
+
+ initiate_netbios_packet(&id, fd, quest_type, name, name_type,
+ nb_flags, bcast, recurse, send_ip);
+
+ if (id == 0xffff) {
+ DEBUG(4,("did not initiate netbios packet: %s\n", inet_ntoa(send_ip)));
+ return NULL;
+ }
+
+ if ((n = make_response_queue_record(state,id,fd,
+ quest_type,name,name_type,nb_flags,ttl,
+ server_type,my_name, my_comment,
+ bcast,recurse,send_ip,reply_to_ip,
+ reply_id)))
+ {
+ add_response_record(d,n);
+ return n;
+ }
+ return NULL;
+}
diff --git a/source/nameresp.doc b/source/nameresp.doc
new file mode 100644
index 00000000000..cfe63500c88
--- /dev/null
+++ b/source/nameresp.doc
@@ -0,0 +1,178 @@
+/*
+ Unix SMB/Netbios documentation.
+ Version 0.0
+ Copyright (C) Luke Leighton Andrew Tridgell 1996
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Document name: nameresp.doc
+
+ Revision History:
+
+ 0.0 - 02jul96 : lkcl@pires.co.uk
+ created
+*/
+
+the netbios expected response code is a key part of samba's NetBIOS
+handling capabilities. it allows samba to carry on dealing with
+other things while expecting a response from one or more hosts.
+
+this allows samba to simultaneously deal with registering its names
+with another WINS server, register its names on its local subnets,
+query any hosts that have registered with samba in its capacity as
+a WINS server, and at a later date it will be also be able handle
+END-NODE CHALLENGES (see rfc1001.txt 15.2.2.2 and 15.2.2.3 - secured
+NBNS functionality).
+
+all at once!
+
+when a netbios packet is sent out by samba and it expects a response,
+a record of all the relevant information is kept (most importantly,
+the unique transaction id associated which will come back to us in
+a response packet is recorded, and also recorded is the reason that
+the original packet was sent out by samba in the first place!).
+
+if a response is received, then the unique transaction identifier
+returned in the response packet is searched for in the expected
+response records. the record indicates why the initial request was
+made (and therefore the type of response can be verified) and
+appropriate action can be taken.
+
+when no responses, after a number of retries, are not received, then
+samba may take appropriate action. this is a crucial part of samba's
+operation: for a key number of NetBIOS operations, no response is an
+implicit positive response.
+
+module nameresp deals with the initial transmission, re-transmission
+and time-out of netbios response records.
+
+module namedbresp deals with the maintenance of the list of expected
+responses - creation, finding and removal.
+
+
+/*************************************************************************
+ queue_netbios_packet()
+ *************************************************************************/
+
+this function is responsible for sending out a netbios packet, and then
+making a record of the information that was sent out. a response will
+be expected later (or not, as the case may be).
+
+if a response is received, response_netbios_packet() will deal with it.
+otherwise, it will be dealt with in expire_netbios_response_entries().
+
+
+/*************************************************************************
+ queue_netbios_pkt_wins()
+ *************************************************************************/
+
+this function is a wrapper around queue_netbios_packet(). there is
+some confusion about B, M and P nodes (see rfc1001.txt section 10) -
+confusion introduced by luke :-) - which needs sorting out.
+
+for example, rfc1001.txt 15.2.3 - an M node must attempt to register a
+name first as a B node, then attempt to register as an M node. negative
+responses on either of these attempts is a failure to register the
+name.
+
+this is NOT the case with a P node.
+
+
+/*************************************************************************
+ expire_netbios_response_entries()
+ *************************************************************************/
+
+this function is responsible for dealing with queued response records
+that have not received a response packet matching their unique
+transaction id.
+
+if the retry count for any record is non-zero, and its time-out period
+has expired, the retry count is reduced, the time-out period is stepped
+forward and the packet is re-transmitted (from the information stored
+in the queued response record) with the same unique transaction id of
+the initial attempt at soliciting a response.
+
+if the retry count is zero, then the packet is assumed to have expired.
+dead_netbios_entry() is called to deal with the possibility of an error
+or a problem (or in certain instances, no answer is an implicit
+positive response!).
+
+the expected response record is then deleted, and the number of expected
+responses reduced. when this count gets to zero, listen_for_packets()
+will no longer time-out for 1 second on account of expecting response
+packets.
+
+
+/*************************************************************************
+ dead_netbios_entry()
+ *************************************************************************/
+
+this function is responsible for dealing with the case when a NetBIOS
+response to a packet sent out by samba was not received. for certain
+transactions, this may be normal. for others, under certain conditions
+it may constitute either an error or a problem with or failure of one
+or more hosts.
+
+- NAME_QUERY_CONFIRM
+
+when a samba 'state' of type NAME_QUERY_CONFIRM is sent, a response
+may or may not be forthcoming. if no response is received to a unique
+name, then the record is removed from samba's WINS database. non-unique
+names are simply expected to die off on a time-to-live basis (see
+rfc1001.txt 15.1.3.4)
+
+query_refresh_names() issues this samba 'state'
+response_name_query_sync() deals with responses to NAME_QUERY_CONFIRM.
+
+- NAME_QUERY_MST_CHK
+
+when a samba 'state' of type NAME_QUERY_MST_CHK is sent, and a response
+is not received, this implies that a master browser will have failed.
+remedial action may need to be taken, for example if samba is a member
+of that workgroup and it is also a potential master browser it could
+force an election.
+
+check_master_browser() issues this samba 'state'.
+response_process() does nothing if a response is received. this is normal.
+
+- NAME_RELEASE
+
+when a samba 'state' of type NAME_RELEASE is sent, and a response is
+not received, it is assumed to be acceptable to release the name. if the
+original response was sent to another WINS server, then that WINS server
+may be inaccessible or may have failed. if so, then at a later date
+samba should take this into account (see rfc1001.txt 10.3).
+
+remove_name_entry() issues this samba 'state'
+response_name_rel() deals with responses to NAME_RELEASE.
+
+- NAME_REGISTER
+
+when a samba 'state' of type NAME_REGISTER is sent, and a response is
+not received, if the registration was done by broadcast, it is assumed
+that there are no objections to the registration of this name, and samba
+adds the name to the appropriate subnet record name database. if the
+registration was point-to-point (i.e with another WINS server) then that
+WINS server may be inaccessible or may have failed. if so, then at a later
+date samba should take this into account (see rfc1001.txt 10.3).
+
+add_my_name_entry() issues this samba 'state'
+response_name_reg() deals with responses to NAME_REGISTER.
+
+no action is taken for any other kinds of samba 'states' if a response
+is not received. this is not to say that action may not be appropriate,
+just that it's not been looked at yet :-)
+
+
diff --git a/source/nameserv.c b/source/nameserv.c
new file mode 100644
index 00000000000..bc37d1c424e
--- /dev/null
+++ b/source/nameserv.c
@@ -0,0 +1,507 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ 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.
+
+ Module name: nameserv.c
+
+ Revision History:
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+ 04 jul 96: lkcl@pires.co.uk
+ module nameserv contains name server management functions
+*/
+
+#include "includes.h"
+
+extern int ClientNMB;
+
+extern int DEBUGLEVEL;
+
+extern pstring scope;
+extern pstring myname;
+extern fstring myworkgroup;
+extern char **my_netbios_names;
+extern struct in_addr ipzero;
+extern struct in_addr wins_ip;
+
+extern struct subnet_record *subnetlist;
+
+extern uint16 nb_type; /* samba's NetBIOS type */
+
+/****************************************************************************
+ remove an entry from the name list
+
+ note: the name will _always_ be removed
+ XXXX at present, the name is removed _even_ if a WINS server says keep it.
+
+ ****************************************************************************/
+void remove_name_entry(struct subnet_record *d, char *name,int type)
+{
+ /* XXXX BUG: if samba is offering WINS support, it should still broadcast
+ a de-registration packet to the local subnet before removing the
+ name from its local-subnet name database. */
+
+ int search = FIND_SELF;
+ struct name_record n;
+ struct name_record *n2=NULL;
+
+ make_nmb_name(&n.name,name,type,scope);
+
+ if(d == wins_subnet)
+ search |= FIND_WINS;
+ else
+ search |= FIND_LOCAL;
+
+ if ((n2 = find_name_search(&d, &n.name, search, ipzero)))
+ {
+ /* check name isn't already being de-registered */
+ if (NAME_DEREG(n2->ip_flgs[0].nb_flags))
+ return;
+
+ /* mark the name as in the process of deletion. */
+ n2->ip_flgs[0].nb_flags &= NB_DEREG;
+ }
+
+ if (!n2) return;
+
+ /* Only remove names with non-zero death times. */
+ if(n2->death_time == 0)
+ {
+ DEBUG(5,("remove_name_entry: Name %s(%d) has zero ttl - not removing.\n",
+ name, type));
+ return;
+ }
+
+ /* remove the name immediately. even if the spec says we should
+ first try to release them, this is too dangerous with our current
+ name structures as otherwise we will end up replying to names we
+ don't really own */
+ remove_netbios_name(d,name,type,SELF,n2->ip_flgs[0].ip);
+
+ if (ip_equal(d->bcast_ip, wins_ip))
+ {
+ if (!lp_wins_support())
+ {
+ /* not a WINS server: we have to release them on the network */
+ queue_netbios_pkt_wins(ClientNMB,NMB_REL,NAME_RELEASE,
+ name, type, 0, 0,0,NULL,NULL,
+ ipzero, ipzero);
+ }
+ }
+ else
+ {
+ /* local interface: release them on the network */
+ queue_netbios_packet(d,ClientNMB,NMB_REL,NAME_RELEASE,
+ name, type, 0, 0,0,NULL,NULL,
+ True, False, d->bcast_ip, d->bcast_ip, 0);
+ }
+}
+
+
+/****************************************************************************
+ add an entry to the name list
+
+ big note: our name will _always_ be added (if there are no objections).
+ it's just a matter of when this will be done (e.g after a time-out).
+
+ ****************************************************************************/
+void add_my_name_entry(struct subnet_record *d,char *name,int type,int nb_flags)
+{
+ BOOL re_reg = False;
+ struct nmb_name n;
+
+ if (!d) return;
+
+ /* not that it particularly matters, but if the SELF name already exists,
+ it must be re-registered, rather than just registered */
+
+ make_nmb_name(&n, name, type, scope);
+ if (find_name(d->namelist, &n, SELF))
+ re_reg = True;
+
+ /* XXXX BUG: if samba is offering WINS support, it should still add the
+ name entry to a local-subnet name database. see rfc1001.txt 15.1.1 p28
+ regarding the point about M-nodes. */
+
+ if (ip_equal(d->bcast_ip, wins_ip))
+ {
+ if (lp_wins_support())
+ {
+ /* we are a WINS server. */
+ if(lp_wins_support())
+ {
+ DEBUG(4,("add_my_name_entry: samba as WINS server adding: "));
+ }
+
+ /* this will call add_netbios_entry() */
+ name_register_work(d, name, type, nb_flags,0, ipzero, False);
+ }
+ else
+ {
+ DEBUG(4,("add_my_name_entry registering name %s with WINS server.\n",
+ name));
+
+ /* a time-to-live allows us to refresh this name with the WINS server. */
+ queue_netbios_pkt_wins(ClientNMB,
+ re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
+ name, type, nb_flags, GET_TTL(0),0,NULL,NULL,
+ ipzero, ipzero);
+ }
+ }
+ else
+ {
+ /* broadcast the packet, but it comes from ipzero */
+ queue_netbios_packet(d,ClientNMB,
+ re_reg ? NMB_REG_REFRESH : NMB_REG, NAME_REGISTER,
+ name, type, nb_flags, GET_TTL(0),0,NULL,NULL,
+ True, False, d->bcast_ip, ipzero, 0);
+ }
+}
+
+
+/****************************************************************************
+ add the internet group <1c> domain logon names by wins unicast and broadcast.
+ ****************************************************************************/
+void add_domain_logon_names(void)
+{
+ struct subnet_record *d;
+
+ if (!lp_domain_logons()) return;
+
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ {
+ struct work_record *work = find_workgroupstruct(d, myworkgroup, True);
+
+ if (work && work->log_state == LOGON_NONE)
+ {
+ struct nmb_name n;
+ make_nmb_name(&n,myworkgroup,0x1c,scope);
+
+ if (!find_name(d->namelist, &n, FIND_SELF))
+ {
+ /* logon servers are group names. don't expect failure */
+
+ DEBUG(0,("%s attempting to become logon server for %s %s\n",
+ timestring(), myworkgroup, inet_ntoa(d->bcast_ip)));
+
+ become_logon_server(d, work);
+ }
+ }
+ }
+}
+
+
+/****************************************************************************
+ add the <1b> domain master names by broadcast.
+ ****************************************************************************/
+void add_domain_master_bcast(void)
+{
+ struct subnet_record *d;
+
+ if (!lp_domain_master()) return;
+
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ struct work_record *work = find_workgroupstruct(d, myworkgroup, True);
+
+ if (work && work->dom_state == DOMAIN_NONE)
+ {
+ struct nmb_name n;
+ make_nmb_name(&n,myworkgroup,0x1b,scope);
+
+ if (!find_name(d->namelist, &n, FIND_SELF))
+ {
+ DEBUG(0,("%s add_domain_names: attempting to become domain \
+master browser on workgroup %s %s\n",
+ timestring(), myworkgroup, inet_ntoa(d->bcast_ip)));
+
+ /* send out a query to establish whether there's a
+ domain controller on the local subnet. if not,
+ we can become a domain controller. it's only
+ polite that we check, before claiming the
+ NetBIOS name 0x1b.
+ */
+
+ DEBUG(0,("add_domain_names:querying subnet %s \
+for domain master on workgroup %s\n",
+ inet_ntoa(d->bcast_ip), myworkgroup));
+
+ queue_netbios_packet(d,ClientNMB,NMB_QUERY,
+ NAME_QUERY_DOMAIN,
+ myworkgroup, 0x1b,
+ 0, 0,0,NULL,NULL,
+ True, False,
+ d->bcast_ip, d->bcast_ip, 0);
+ }
+ }
+ }
+}
+
+
+/****************************************************************************
+ add the <1b> domain master name by wins unicast.
+ ****************************************************************************/
+void add_domain_master_wins(void)
+{
+ struct work_record *work;
+
+ if (!lp_domain_master() || wins_subnet == NULL) return;
+
+ work = find_workgroupstruct(wins_subnet, myworkgroup, True);
+
+ if (work && work->dom_state == DOMAIN_NONE)
+ {
+ struct nmb_name n;
+ make_nmb_name(&n,myworkgroup,0x1b,scope);
+
+ if (!find_name(wins_subnet->namelist, &n, FIND_SELF))
+ {
+ DEBUG(0,("%s add_domain_names: attempting to become domain \
+master browser on workgroup %s %s\n",
+ timestring(), myworkgroup, inet_ntoa(wins_subnet->bcast_ip)));
+
+ if (lp_wins_support())
+ {
+ /* use the wins server's capabilities (indirectly). if
+ someone has already registered the domain<1b>
+ name with the WINS server, then the WINS
+ server's job is to _check_ that the owner still
+ wants it, before giving it away.
+ */
+
+ DEBUG(1,("%s initiate become domain master for %s\n",
+ timestring(), myworkgroup));
+
+ become_domain_master(wins_subnet, work);
+ }
+ else
+ {
+ /* send out a query to establish whether there's a
+ domain controller on the WINS subnet. if not,
+ we can become a domain controller. it's only
+ polite that we check, before claiming the
+ NetBIOS name 0x1b.
+ */
+
+ DEBUG(0,("add_domain_names:querying WINS \
+for domain master on workgroup %s\n", myworkgroup));
+
+ queue_netbios_pkt_wins(ClientNMB,NMB_QUERY,
+ NAME_QUERY_DOMAIN,
+ myworkgroup, 0x1b,
+ 0, 0,0,NULL,NULL,
+ ipzero, ipzero);
+ }
+ }
+ }
+}
+
+
+/****************************************************************************
+ add the domain logon server and domain master browser names
+
+ this code was written so that several samba servers can co-operate in
+ sharing the task of (one server) being a domain master, and of being
+ domain logon servers.
+
+ **************************************************************************/
+void add_domain_names(time_t t)
+{
+ static time_t lastrun = 0;
+
+ if (lastrun != 0 && t < lastrun + CHECK_TIME_ADD_DOM_NAMES * 60) return;
+ lastrun = t;
+
+ /* do the "internet group" - <1c> names */
+ add_domain_logon_names();
+
+ /* do the domain master names */
+ if (wins_subnet != NULL)
+ {
+ /* if the registration of the <1b> name is successful, then
+ add_domain_master_bcast() will be called. this will
+ result in domain logon services being gracefully provided,
+ as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
+
+ which, due to a bug in namelogon.c from 1.9.16p2 to 1.9.16p11
+ cannot _provide_ domain master / domain logon services!!!
+
+ */
+ add_domain_master_wins();
+ }
+ else
+ {
+ add_domain_master_bcast();
+ }
+}
+
+/****************************************************************************
+ add the magic samba names, useful for finding samba servers
+ **************************************************************************/
+void add_my_names(void)
+{
+ struct subnet_record *d;
+ /* each subnet entry, including WINS pseudo-subnet, has SELF names */
+
+ /* XXXX if there was a transport layer added to samba (ipx/spx etc) then
+ there would be yet _another_ for-loop, this time on the transport type
+ */
+
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ {
+ int n;
+ BOOL wins = (lp_wins_support() && (d == wins_subnet));
+
+ /* Add all our names including aliases. */
+ for (n=0; my_netbios_names[n]; n++)
+ {
+ add_my_name_entry(d, my_netbios_names[n],0x20,nb_type|NB_ACTIVE);
+ add_my_name_entry(d, my_netbios_names[n],0x03,nb_type|NB_ACTIVE);
+ add_my_name_entry(d, my_netbios_names[n],0x00,nb_type|NB_ACTIVE);
+ }
+
+ /* these names are added permanently (ttl of zero) and will NOT be
+ refreshed with the WINS server */
+ add_netbios_entry(d,"*",0x0,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
+ add_netbios_entry(d,"*",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
+ add_netbios_entry(d,"__SAMBA__",0x20,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
+ add_netbios_entry(d,"__SAMBA__",0x00,nb_type|NB_ACTIVE,0,SELF,d->myip,False,wins);
+ }
+}
+
+
+/****************************************************************************
+ remove all the samba names... from a WINS server if necessary.
+ **************************************************************************/
+void remove_my_names()
+{
+ struct subnet_record *d;
+
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ {
+ struct name_record *n, *next;
+
+ for (n = d->namelist; n; n = next)
+ {
+ next = n->next;
+ if (n->source == SELF)
+ {
+ /* get all SELF names removed from the WINS server's database */
+ /* XXXX note: problem occurs if this removes the wrong one! */
+
+ remove_name_entry(d,n->name.name, n->name.name_type);
+ }
+ }
+ }
+}
+
+
+/*******************************************************************
+ refresh my own names
+ ******************************************************************/
+void refresh_my_names(time_t t)
+{
+ struct subnet_record *d;
+
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ {
+ struct name_record *n;
+
+ for (n = d->namelist; n; n = n->next)
+ {
+ /* each SELF name has an individual time to be refreshed */
+ if (n->source == SELF && n->refresh_time < t &&
+ n->death_time != 0)
+ {
+ add_my_name_entry(d,n->name.name,n->name.name_type,
+ n->ip_flgs[0].nb_flags);
+ /* they get a new lease on life :-) */
+ n->death_time += GET_TTL(0);
+ n->refresh_time += GET_TTL(0);
+ }
+ }
+ }
+}
+
+
+/*******************************************************************
+ queries names occasionally. an over-cautious, non-trusting WINS server!
+
+ this function has been added because nmbd could be restarted. it
+ is generally a good idea to check all the names that have been
+ reloaded from file.
+
+ XXXX which names to poll and which not can be refined at a later date.
+ ******************************************************************/
+void query_refresh_names(time_t t)
+{
+ struct name_record *n;
+ struct subnet_record *d = wins_subnet;
+
+ static time_t lasttime = 0;
+
+ int count = 0;
+ int name_refresh_time = NAME_POLL_REFRESH_TIME;
+ int max_count = name_refresh_time * 2 / NAME_POLL_INTERVAL;
+ if (max_count > 10) max_count = 10;
+
+ name_refresh_time = NAME_POLL_INTERVAL * max_count / 2;
+
+ /* if (!lp_poll_wins()) return; polling of registered names allowed */
+
+ if (!d) return;
+
+ if (!lasttime) lasttime = t;
+ if (t - lasttime < NAME_POLL_INTERVAL) return;
+
+ lasttime = time(NULL);
+
+ for (n = d->namelist; n; n = n->next)
+ {
+ /* only do unique, registered names */
+
+ if (n->source != REGISTER) continue;
+ if (!NAME_GROUP(n->ip_flgs[0].nb_flags)) continue;
+
+ if (n->refresh_time < t)
+ {
+ DEBUG(3,("Polling name %s\n", namestr(&n->name)));
+
+ queue_netbios_packet(d,ClientNMB,NMB_QUERY,NAME_QUERY_CONFIRM,
+ n->name.name, n->name.name_type,
+ 0,0,0,NULL,NULL,
+ False,False,n->ip_flgs[0].ip,n->ip_flgs[0].ip,
+ 0);
+ count++;
+ }
+
+ if (count >= max_count)
+ {
+ /* don't do too many of these at once, but do enough to
+ cover everyone in the list */
+ return;
+ }
+
+ /* this name will be checked on again, if it's not removed */
+ n->refresh_time += name_refresh_time;
+ }
+}
+
diff --git a/source/nameserv.doc b/source/nameserv.doc
new file mode 100644
index 00000000000..af4934ade21
--- /dev/null
+++ b/source/nameserv.doc
@@ -0,0 +1,159 @@
+/*
+ Unix SMB/Netbios documentation.
+ Version 0.0
+ Copyright (C) Luke Leighton Andrew Tridgell 1996
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Document name: nameserv.doc
+
+ Revision History:
+
+ 0.0 - 02jul96 : lkcl@pires.co.uk
+ created
+*/
+
+this module deals with general maintenance of NetBIOS names.
+
+/*************************************************************************
+ query_refresh_names()
+ *************************************************************************/
+
+this function is responsible for polling all names registered in the
+WINS database. it is planned to enable this function should samba
+detect an inconsistency on the network, which could occur if the
+samba NetBIOS daemon dies and is restarted.
+
+polling is done very infrequently, but all names will be covered
+within a period NAME_POLL_REFRESH_TIME. a group of at most ten names
+will be queried at once, at intervals of NAME_POLL_INTERVAL seconds.
+if the total number of names queried in this way will take too long,
+then the time that an individual name will next be polled is
+increased accordingly.
+
+name query polling is functionality over-and-above the normal
+requirement (see rfc1001.txt 15.1.7 point 7). it is normally the
+responsibility of the owner of a name to re-register the name at
+regular intervals.
+
+
+/*************************************************************************
+ refresh_my_names()
+ *************************************************************************/
+
+this function is responsible for refreshing samba's names that have
+been registered with other servers on a local subnet, or with another
+WINS server if samba is using one.
+
+samba's names' refresh_time will be updated through the use of the function
+add_my_name_entry().
+
+
+/*************************************************************************
+ remove_my_names()
+ *************************************************************************/
+
+this function is responsible for removing all samba's SELF names. it
+is used when samba receives a SIG_TERM. samba at present does not wait
+for the WINS server to reply to the name releases sent out.
+
+
+/*************************************************************************
+ add_my_names()
+ *************************************************************************/
+
+this function is responsible for adding and registering if necessary all
+samba's SELF names, on each of its local subnets and with another WINS
+server if samba is using one.
+
+/*************************************************************************
+ add_my_name_entry()
+ *************************************************************************/
+
+this function is responsible for registering or re-registering one of
+samba's names, either on the local subnet or with another WINS server
+if samba is using one.
+
+if the name is already in samba's database, then it is re-registered,
+otherwise it is simply registered.
+
+if the name is being registered in a WINS capacity (the subnet to which
+the name should be added is the WINS pseudo-subnet) then we add the entry
+immediately if samba is a WINS server. it uses name_register_work()
+because if the name is being added as part of becoming a master browser,
+we want to carry on that process. if the name is registered with another
+WINS server, we must wait for an answer from that WINS server. either
+name_register_work() or name_unregister_work() will be called as a result.
+
+if the name is being registered on a local subnet, then it is
+broadcast. an explicit rejection from another host will result
+in name_unregister_work() being called. no response will, after
+retrying, result in name_register_work() being called.
+
+what ever method is used, the name will either be registered
+or rejected, and what ever process was taking place (becoming
+a master browser for example) will carry on.
+
+expire_netbios_response_entries() is responsible for taking further
+action if no response to the registration is received.
+
+note that there may be a large number of function calls on the
+stack if become_master() is called and samba is configured as
+a WINS server. the loop will be:
+
+become_master(), add_my_name_entry(), name_register_work() and
+back to become_master() with the new value of the workgroup
+'state'.
+
+
+/*************************************************************************
+ remove_name_entry()
+ *************************************************************************/
+
+this function is responsible for removing a NetBIOS name. if the name
+being removed is registered on a local subnet, a name release should be
+broadcast on the local subnet.
+
+if the name is being released in a WINS capacity (the subnet to
+which the name should be added is the WINS pseudo-subnet) then we
+remove the entry immediately if samba is a WINS server. it uses
+name_unregister_work() because if the name is being added as part of
+becoming a master browser, we want to terminate that process. if the
+name is released from another WINS server, we must wait for an
+answer from that WINS server. name_unregister_work() will
+definitely be called as a result, because at present we ignore
+negative responses for a name release from a WINS server.
+
+if the name is being releasedd on a local subnet, then it is
+broadcast. name_unregister_work() will definitely be called
+because we ignore negative name releases at present.
+
+what ever method is used, the name will be released. (NOT TRUE!
+see response_name_release())
+
+expire_netbios_response_entries() is responsible for taking further action
+if no response to the name release is received.
+
+
+/*************************************************************************
+ load_netbios_names()
+ *************************************************************************/
+
+this function is responsible for loading any NetBIOS names that samba,
+in its WINS capacity, has written out to disk. all the relevant details
+are recorded in this file, including the time-to-live. should the
+time left to live be small, the name is not added back in to samba's
+WINS database.
+
diff --git a/source/nameservreply.c b/source/nameservreply.c
new file mode 100644
index 00000000000..61c2f80882f
--- /dev/null
+++ b/source/nameservreply.c
@@ -0,0 +1,674 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ 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.
+
+ Module name: nameservreply.c
+
+ Revision History:
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+ 04 jul 96: lkcl@pires.co.uk
+ created module nameservreply containing NetBIOS reply functions
+
+*/
+
+#include "includes.h"
+
+extern int ClientNMB;
+
+extern int DEBUGLEVEL;
+
+extern struct in_addr wins_ip;
+
+/****************************************************************************
+send a registration / release response: pos/neg
+**************************************************************************/
+static void send_name_response(int fd, struct in_addr from_ip,
+ int name_trn_id, int opcode, BOOL success,
+ BOOL recursion_available, BOOL recursion_desired,
+ struct nmb_name *reply_name, int nb_flags, int ttl,
+ struct in_addr ip)
+{
+ char rdata[6];
+ struct packet_struct p;
+
+ int rcode = 0;
+
+ if (success == False)
+ {
+ /* NEGATIVE RESPONSE */
+ rcode = 6;
+ }
+ else if (opcode == NMB_REG && !recursion_available)
+ {
+ /* END-NODE CHALLENGE REGISTRATION RESPONSE */
+ rcode = 0;
+ }
+
+ rdata[0] = nb_flags;
+ rdata[1] = 0;
+ putip(&rdata[2],(char *)&ip);
+
+ p.ip = from_ip;
+ p.port = NMB_PORT;
+ p.fd = fd;
+ p.timestamp = time(NULL);
+ p.packet_type = NMB_PACKET;
+
+ reply_netbios_packet(&p,name_trn_id,
+ rcode,opcode,opcode,
+ recursion_available, recursion_desired,
+ reply_name, 0x20, 0x1,
+ ttl,
+ rdata, 6);
+}
+
+/****************************************************************************
+ add a netbios entry. respond to the (possibly new) owner.
+ **************************************************************************/
+void add_name_respond(struct subnet_record *d, int fd, struct in_addr from_ip,
+ uint16 response_id,
+ struct nmb_name *name,
+ int nb_flags, int ttl, struct in_addr register_ip,
+ BOOL new_owner, struct in_addr reply_to_ip)
+{
+ /* register the old or the new owners' ip */
+ add_netbios_entry(d,name->name,name->name_type,
+ nb_flags,ttl,REGISTER,register_ip,False,True);
+
+ /* reply yes or no to the host that requested the name */
+ /* see rfc1002.txt - 4.2.10 and 4.2.11 */
+
+ send_name_response(fd, reply_to_ip, response_id, NMB_REG,
+ new_owner,
+ True, True,
+ name, nb_flags, ttl, reply_to_ip);
+}
+
+
+/****************************************************************************
+reply to a name release
+****************************************************************************/
+void reply_name_release(struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ struct in_addr ip;
+ int nb_flags = nmb->additional->rdata[0];
+ BOOL bcast = nmb->header.nm_flags.bcast;
+ struct name_record *n;
+ struct subnet_record *d = NULL;
+ int search = 0;
+ BOOL success = False;
+
+ putip((char *)&ip,&nmb->additional->rdata[2]);
+
+ DEBUG(3,("Name release on name %s\n",
+ namestr(&nmb->question.question_name)));
+
+ if (!(d = find_req_subnet(p->ip, bcast)))
+ {
+ DEBUG(3,("response packet: bcast %s not known\n",
+ inet_ntoa(p->ip)));
+ return;
+ }
+
+ if (bcast)
+ search |= FIND_LOCAL;
+ else
+ search |= FIND_WINS;
+
+ n = find_name_search(&d, &nmb->question.question_name,
+ search, ip);
+
+ /* XXXX under what conditions should we reject the removal?? */
+ /* For now - remove if the names match and the group bit matches. */
+ if (n && (n->source != SELF) && (NAME_GROUP(n->ip_flgs[0].nb_flags) == NAME_GROUP(nb_flags)))
+ {
+ success = True;
+
+ /* If it's a group name not ending in 1c (not an internet name)
+ then just allow it to fade out of existance by timing out. */
+ if(NAME_GROUP(nb_flags) && (n->name.name_type != 0x1c))
+ {
+ DEBUG(5, ("reply_name_release: Allow group name %s(%d) to fade out on \
+subnet %s\n", namestr(&nmb->question.question_name), n->name.name_type,
+ inet_ntoa(d->bcast_ip)));
+ }
+ else
+ {
+ DEBUG(5, ("reply_name_release: Removing name %s on subnet %s\n",
+ namestr(&nmb->question.question_name), inet_ntoa(d->bcast_ip)));
+ remove_name(d,n);
+ n = NULL;
+ }
+ }
+
+ if (bcast) return;
+
+ /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
+ send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REL,
+ success, False, False,
+ &nmb->question.question_name, nb_flags, 0, ip);
+}
+
+
+/****************************************************************************
+reply to a reg request
+**************************************************************************/
+void reply_name_reg(struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ struct nmb_name *question = &nmb->question.question_name;
+
+ struct nmb_name *reply_name = question;
+
+ char *qname = question->name;
+ int qname_type = question->name_type;
+
+ BOOL bcast = nmb->header.nm_flags.bcast;
+
+ int ttl = GET_TTL(nmb->additional->ttl);
+ int nb_flags = nmb->additional->rdata[0];
+ BOOL group = NAME_GROUP(nb_flags);
+
+ struct subnet_record *d = NULL;
+ struct name_record *n = NULL;
+
+ BOOL success = True;
+ BOOL secured_redirect = False;
+
+ struct in_addr ip, from_ip;
+ int search = 0;
+
+ putip((char *)&from_ip,&nmb->additional->rdata[2]);
+ ip = from_ip;
+
+ DEBUG(3,("Name registration for name %s at %s - ",
+ namestr(question),inet_ntoa(ip)));
+
+ if (group && qname_type != 0x1c)
+ {
+ /* apparently we should return 255.255.255.255 for group queries
+ (email from MS) */
+ ip = *interpret_addr2("255.255.255.255");
+ }
+
+ if (!(d = find_req_subnet(p->ip, bcast)))
+ {
+ DEBUG(3,("reply_name_reg: subnet %s not known\n",
+ inet_ntoa(p->ip)));
+ return;
+ }
+
+ if (bcast)
+ search |= FIND_LOCAL;
+ else
+ search |= FIND_WINS;
+
+ /* see if the name already exists */
+ n = find_name_search(&d, question, search, from_ip);
+
+ if (n)
+ {
+ DEBUG(3,("found\n"));
+ if (!group) /* unique names */
+ {
+ if (n->source == SELF || NAME_GROUP(n->ip_flgs[0].nb_flags))
+ {
+ /* no-one can register one of samba's names, nor can they
+ register a name that's a group name as a unique name */
+
+ success = False;
+ }
+ else if(!ip_equal(ip, n->ip_flgs[0].ip))
+ {
+ /* XXXX rfc1001.txt says:
+ * if we are doing secured WINS, we must send a Wait-Acknowledge
+ * packet (WACK) to the person who wants the name, then do a
+ * name query on the person who currently owns the unique name.
+ * if the current owner still says they own it, the person who wants
+ * the name can't have it. if they do not, or are not alive, they can.
+ */
+
+ secured_redirect = True;
+
+ reply_name = &n->name;
+ }
+ else
+ {
+ n->ip_flgs[0].ip = ip;
+ n->death_time = ttl?p->timestamp+ttl*3:0;
+ DEBUG(3,("%s owner: %s\n",namestr(&n->name),inet_ntoa(n->ip_flgs[0].ip)));
+ }
+ }
+ else
+ {
+ /* refresh the name */
+ if (n->source != SELF)
+ {
+ n->death_time = ttl?p->timestamp + ttl*3:0;
+ }
+ }
+
+ /* XXXX bug reported by terryt@ren.pc.athabascau.ca */
+ /* names that people have checked for and not found get DNSFAILed.
+ we need to update the name record if someone then registers */
+
+ if (n->source == DNSFAIL)
+ n->source = REGISTER;
+
+ }
+ else
+ {
+ DEBUG(3,("not found\n"));
+ /* add the name to our name/subnet, or WINS, database */
+ n = add_netbios_entry(d,qname,qname_type,nb_flags,ttl,REGISTER,ip,
+ True,!bcast);
+ }
+
+ /* if samba owns a unique name on a subnet, then it must respond and
+ disallow the attempted registration. if the registration is
+ successful by broadcast, only then is there no need to respond
+ (implicit registration: see rfc1001.txt 15.2.1).
+ */
+
+ if (bcast && success) return;
+
+ if (secured_redirect)
+ {
+ char rdata[2];
+
+ /* XXXX i am confused. RSVAL or SSVAL? assume NMB byte ordering */
+ RSSVAL(rdata,0,(nmb->header.opcode&0xf) + ((nb_flags&0xff) << 4));
+
+ /* XXXX mistake in rfc1002.txt? 4.2.16: NULL is 0xa see 4.2.1.3
+ type = 0x0a; see rfc1002.txt 4.2.1.3
+ class = 0x01; see rfc1002.txt 4.2.16
+ */
+
+ /* send WAIT ACKNOWLEDGEMENT see rfc1002.txt 4.2.16 */
+ reply_netbios_packet(p,nmb->header.name_trn_id,
+ 0,NMB_WAIT_ACK,NMB_WAIT_ACK,
+ False,False,
+ reply_name, 0x0a, 0x01,
+ 15*1000, /* 15 seconds long enough to wait? */
+ rdata, 2);
+
+ /* initiate some enquiries to the current owner. */
+ queue_netbios_packet(d,ClientNMB,NMB_QUERY,
+ NAME_REGISTER_CHALLENGE,
+ reply_name->name,reply_name->name_type,
+ nb_flags,0,0,NULL,NULL,
+ False, False,
+ n->ip_flgs[0].ip, p->ip,
+ nmb->header.name_trn_id);
+ }
+ else
+ {
+ /* Send a NAME REGISTRATION RESPONSE (pos/neg) see rfc1002.txt 4.2.5-6
+ or an END-NODE CHALLENGE REGISTRATION RESPONSE see rfc1002.txt 4.2.7
+ */
+
+ send_name_response(p->fd,p->ip, nmb->header.name_trn_id, NMB_REG,
+ success,
+ True, True,
+ reply_name, nb_flags, ttl, ip);
+ }
+}
+
+/* this is used to sort names for a name status into a sensible order
+ we put our own names first, then in alphabetical order */
+static int status_compare(char *n1,char *n2)
+{
+ extern pstring myname;
+ int l1,l2,l3;
+
+ /* its a bit tricky because the names are space padded */
+ for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ;
+ for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ;
+ l3 = strlen(myname);
+
+ if ((l1==l3) && strncmp(n1,myname,l3) == 0 &&
+ (l2!=l3 || strncmp(n2,myname,l3) != 0))
+ return -1;
+
+ if ((l2==l3) && strncmp(n2,myname,l3) == 0 &&
+ (l1!=l3 || strncmp(n1,myname,l3) != 0))
+ return 1;
+
+ return memcmp(n1,n2,18);
+}
+
+
+/****************************************************************************
+ reply to a name status query
+
+ combine the list of the local interface on which the query was made with
+ the names registered via wins.
+ ****************************************************************************/
+void reply_name_status(struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ char *qname = nmb->question.question_name.name;
+ int ques_type = nmb->question.question_name.name_type;
+ char rdata[MAX_DGRAM_SIZE];
+ char *countptr, *buf, *bufend, *buf0;
+ int names_added,i;
+ struct name_record *n;
+ struct subnet_record *d = NULL;
+ int search = FIND_SELF | FIND_WINS | FIND_LOCAL;
+
+ /* NOTE: we always treat a name status lookup as a bcast */
+ if (!(d = find_req_subnet(p->ip, True)))
+ {
+ DEBUG(3,("Name status req: bcast %s not known\n",
+ inet_ntoa(p->ip)));
+ return;
+ }
+
+ DEBUG(3,("Name status for name %s %s\n",
+ namestr(&nmb->question.question_name),
+ inet_ntoa(p->ip)));
+
+ n = find_name_search(&d, &nmb->question.question_name,
+ search, p->ip);
+
+ if (!n) return;
+
+ /* XXXX hack, we should calculate exactly how many will fit */
+ bufend = &rdata[MAX_DGRAM_SIZE] - 18;
+ countptr = buf = rdata;
+ buf += 1;
+ buf0 = buf;
+
+ names_added = 0;
+
+ n = d->namelist;
+
+ while (buf < bufend)
+ {
+ if (n->source == SELF)
+ {
+ int name_type = n->name.name_type;
+
+ /* check if we want to exclude other workgroup names
+ from the response. if we don't exclude them, windows clients
+ get confused and will respond with an error for NET VIEW */
+
+ if (!strequal(n->name.name,"*") &&
+ !strequal(n->name.name,"__SAMBA__") &&
+ (name_type < 0x1b || name_type >= 0x20 ||
+ ques_type < 0x1b || ques_type >= 0x20 ||
+ strequal(qname, n->name.name)))
+ {
+ /* start with first bit of putting info in buffer: the name */
+ bzero(buf,18);
+ sprintf(buf,"%-15.15s",n->name.name);
+ strupper(buf);
+
+ /* put name type and netbios flags in buffer */
+ buf[15] = name_type;
+ buf[16] = n->ip_flgs[0].nb_flags;
+
+ buf += 18;
+
+ names_added++;
+ }
+ }
+
+ /* remove duplicate names */
+ qsort(buf0,names_added,18,QSORT_CAST status_compare);
+
+ for (i=1;i<names_added;i++) {
+ if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0) {
+ names_added--;
+ if (names_added == i) break;
+ memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
+ i--;
+ }
+ }
+
+ buf = buf0 + 18*names_added;
+
+ n = n->next;
+
+ if (!n)
+ {
+ /* end of this name list: add wins names too? */
+ struct subnet_record *w_d;
+
+ if (!(w_d = wins_subnet)) break;
+
+ if (w_d != d)
+ {
+ d = w_d;
+ n = d->namelist; /* start on the wins name list */
+ }
+ }
+ if (!n) break;
+ }
+
+ SCVAL(countptr,0,names_added);
+
+ /* we don't send any stats as they could be used to attack
+ the protocol */
+ bzero(buf,64);
+
+ buf += 46;
+
+ /* Send a POSITIVE NAME STATUS RESPONSE */
+ reply_netbios_packet(p,nmb->header.name_trn_id,
+ 0,NMB_STATUS,0,False, False,
+ &nmb->question.question_name,
+ 0x21, 0x01,
+ 0, rdata,PTR_DIFF(buf,rdata));
+}
+
+
+/***************************************************************************
+reply to a name query.
+
+with broadcast name queries:
+
+ - only reply if the query is for one of YOUR names. all other machines on
+ the network will be doing the same thing (that is, only replying to a
+ broadcast query if they own it)
+ NOTE: broadcast name queries should only be sent out by a machine
+ if they HAVEN'T been configured to use WINS. this is generally bad news
+ in a wide area tcp/ip network and should be rectified by the systems
+ administrator. USE WINS! :-)
+ - the exception to this is if the query is for a Primary Domain Controller
+ type name (0x1b), in which case, a reply is sent.
+
+ - NEVER send a negative response to a broadcast query. no-one else will!
+
+with directed name queries:
+
+ - if you are the WINS server, you are expected to respond with either
+ a negative response, a positive response, or a wait-for-acknowledgement
+ packet, and then later on a pos/neg response.
+
+****************************************************************************/
+void reply_name_query(struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ struct nmb_name *question = &nmb->question.question_name;
+ int name_type = question->name_type;
+
+ BOOL bcast = nmb->header.nm_flags.bcast;
+ BOOL query_is_to_wins_server = (!bcast &&
+ nmb->header.nm_flags.recursion_desired);
+ int ttl=0;
+ int rcode = 0;
+ int nb_flags = 0;
+ struct in_addr retip;
+ char rdata[6];
+ struct subnet_record *d = NULL;
+ BOOL success = True;
+ struct name_record *n = NULL;
+ BOOL acting_as_wins_server = lp_wins_support();
+
+ /* directed queries are for WINS server: broadcasts are local SELF queries.
+ the exception is Domain Master names. */
+
+ if (query_is_to_wins_server)
+ {
+ /* queries to the WINS server involve the WINS server subnet */
+ if (!(d = wins_subnet))
+ {
+ DEBUG(3,("name query: wins search %s not known\n",
+ inet_ntoa(p->ip)));
+ success = False;
+ }
+ }
+ else
+ {
+ /* queries to the WINS client involve, unfortunately, the WINS subnet
+ because it contains WINS client (SELF) entries, as _well_ as WINS
+ server entries. not good.
+ */
+
+ if (!(d = find_subnet(*iface_bcast(p->ip))))
+ {
+ DEBUG(3,("name query: interface for %s not known\n",
+ inet_ntoa(p->ip)));
+ success = False;
+ }
+ }
+
+ DEBUG(3,("Name query from %s for name %s<0x%x>\n",
+ inet_ntoa(p->ip), question->name, question->name_type));
+
+ if (!bcast && (name_type == 0x1d) && lp_wins_support())
+ {
+ /* see WINS manager HELP - 'How WINS Handles Special Names' */
+ /* a WINS query (unicasted) for a 0x1d name must always return False */
+ success = False;
+ }
+
+ if (success)
+ {
+ /* look up the name in the cache */
+ n = find_name_search(&d, question, FIND_LOCAL, p->ip);
+
+ /* check for a previous DNS lookup */
+ if (!n && (n = find_name_search(&d, question, FIND_WINS, p->ip))) {
+ if (n->source != DNS && n->source != DNSFAIL) {
+ n = NULL;
+ } else {
+ DEBUG(5,("Found DNS cache entry %s\n", namestr(&n->name)));
+ }
+ }
+
+ /* it is a name that already failed DNS lookup or it's expired */
+ if (n && (n->source == DNSFAIL ||
+ (n->death_time && n->death_time < p->timestamp)))
+ {
+ success = False;
+ }
+
+ /* do we want to do dns lookups? */
+ /* XXXX this DELAYS nmbd while it does a search. lp_dns_proxy()
+ can be switched off, to ensure that the blocking doesn't occur.
+ a better solution would be to fork, but this will require a
+ mechanism to carry on processing after the query is resolved
+ (similar to the netbios queue).
+ */
+ if (success && !n && (lp_dns_proxy() || !bcast))
+ {
+ n = dns_name_search(question, p->timestamp);
+ }
+ }
+
+ if (!n) success = False;
+
+ if (success)
+ {
+ if (bcast && n->source != SELF && name_type != 0x1b)
+ {
+ /* don't respond to broadcast queries unless the query is for
+ a name we own or it is for a Primary Domain Controller name */
+
+ if (!lp_wins_proxy() ||
+ same_net(p->ip,n->ip_flgs[0].ip,*iface_nmask(p->ip)))
+ {
+ /* never reply with a negative response to broadcast queries */
+ return;
+ }
+ }
+
+ /* name is directed query, or it's self, or it's a Domain Master type
+ name, or we're replying on behalf of a caller because they are on a
+ different subnet and cannot hear the broadcast. XXXX lp_wins_proxy
+ should be switched off in environments where broadcasts are forwarded
+ */
+
+ /* XXXX note: for proxy servers, we should forward the query on to
+ another WINS server if the name is not in our database, or we are
+ not a WINS server ourselves
+ */
+ ttl = n->death_time ? n->death_time - p->timestamp : GET_TTL(0);
+ retip = n->ip_flgs[0].ip;
+ nb_flags = n->ip_flgs[0].nb_flags;
+ }
+
+ if (!success && bcast) return; /* never reply negative response to bcasts */
+
+ /* if the IP is 0 then substitute my IP */
+ if (zero_ip(retip)) retip = *iface_ip(p->ip);
+
+ /* SPECIAL CASE... If we are a WINS server and the request is explicitly
+ *to* the WINS server and the name type is WORKGROUP<0x1e> we should
+ respond with the local broadcast address 255.255.255.255.
+ */
+ if(!bcast && (name_type == 0x1e) && lp_wins_support())
+ retip = *interpret_addr2("255.255.255.255");
+
+ if (success)
+ {
+ rcode = 0;
+ DEBUG(3,("OK %s\n",inet_ntoa(retip)));
+ }
+ else
+ {
+ rcode = 3;
+ DEBUG(3,("UNKNOWN\n"));
+ }
+
+ if (success)
+ {
+ rdata[0] = nb_flags;
+ rdata[1] = 0;
+ putip(&rdata[2],(char *)&retip);
+ }
+
+ /* see rfc1002.txt 4.2.13 */
+
+ reply_netbios_packet(p,nmb->header.name_trn_id,
+ rcode,NMB_QUERY,0,
+ (query_is_to_wins_server && acting_as_wins_server ?
+ True : False), /* recursion_available flag */
+ True, /* recursion_desired_flag */
+ &nmb->question.question_name,
+ 0x20, 0x01,
+ ttl,
+ rdata, success ? 6 : 0);
+}
diff --git a/source/nameservreply.doc b/source/nameservreply.doc
new file mode 100644
index 00000000000..a5acf8a9c26
--- /dev/null
+++ b/source/nameservreply.doc
@@ -0,0 +1,213 @@
+/*
+ Unix SMB/Netbios documentation.
+ Version 0.0
+ Copyright (C) Luke Leighton Andrew Tridgell 1996
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Document name: nameservreply.doc
+
+ Revision History:
+
+ 0.0 - 02jul96 : lkcl@pires.co.uk
+ created
+*/
+
+/*************************************************************************
+ reply_name_query()
+ *************************************************************************/
+
+this function is responsible for replying to a NetBIOS name query.
+
+there are two kinds of name queries: directed, and broadcast. directed
+queries are usually sent to samba in its WINS capacity. such hosts are
+termed 'point-to-point' hosts. broadcast queries are usually sent from
+'broadcast' or 'mixed' hosts.
+
+broadcasting is used by either older NetBIOS hosts, new NetBIOS hosts that
+have not had WINS capabilities added and new NetBIOS hosts that think the
+WINS server has died.
+
+the samba NetBIOS name database is divided into sections, on a
+per-subnet basis. there is also a WINS NetBIOS name database, and for
+convenience this is added as a pseudo-subnet with the ip address of
+255.255.255.255.
+
+the local subnet NetBIOS name databases only contain samba's names.
+the reason for this is that if a broadcast query is received, a NetBIOS
+hosts is only expected to respond if that query is for one of its own
+names (the exception to this is if a host is configured as a 'proxy'
+server, in which case, samba should redirect the query to another WINS
+server).
+
+the WINS pseudo-subnet NetBIOS database contains all NetBIOS names
+that are not 'special browser' type names (regarding this i am a
+_bit_ confused :-). names of type 0x01, 0x1d and 0x1e i consider to
+be 'special browser' names. at the moment. maybe.
+
+the type of search to be initiated is determined. if the NetBIOS name
+type is a non-special-browser name, then the WINS database is included
+in the search.
+
+if the name is not a special browser name, then we need to find the
+right subnet that the query came from. this is done using
+find_req_subnet(). this also has the benefit of stopping any queries
+from subnets that samba does not know about.
+
+if the query is a broadcast query, then the database of the local subnet
+is included in the search.
+
+the name is then searched for in the appropriate NetBIOS data structures.
+if it is found, then we need to check whether it is appropriate for us
+to reply to such a query.
+
+we will only reply if the query is a directed query, the name belongs to
+samba on that subnet, or the name is a domain master browser type,
+or we're doing replies on behalf of hosts on subnets not known to the
+host issuing the query. in the latter instance, it would be appropriate
+if samba is using a WINS server for it to forward the name query on to
+this WINS server.
+
+reply_name_query() then takes note of all the information that is
+needed to construct a reply to the caller. a negative reply (if the
+name is unknown to samba) or a positive reply (the name is known to
+samba) is then issued.
+
+
+/*************************************************************************
+ reply_name_status()
+ *************************************************************************/
+
+this function is responsible for constructing a reply to a NetBIOS
+name status query. this response contains all samba's NetBIOS names
+on the subnet that the query came in from.
+
+a reply will only be made if the NetBIOS name being queried exists.
+
+see rfc1001.txt and rfc1002.txt for details of the name status reply.
+
+
+/*************************************************************************
+ reply_name_reg()
+ *************************************************************************/
+
+this function is responsible for updating the NetBIOS name database
+from registration packets sent out by hosts wishing to register a
+name, and for informing them, if necessary, if this is acceptable
+or not.
+
+name registration can be done by broadcast or by point-to-point,
+i.e the registration is sent directly to samba in its capacity as
+a WINS server.
+
+if the name registration is done by broadcast (see rfc1001.txt 15.2.1),
+then samba's involvement in replying is limited to whether that name
+is owned by samba or not, on the relevant subnet.
+
+if the name registration is done point-to-point (see rfc1001.txt 15.2.2)
+then samba will first need to check its WINS name database records and
+proceed accordingly.
+
+samba looks for the appropriate subnet record that the registration
+should be added to / checked against, using find_req_subnet().
+
+next, the name is searched for in the local database or the WINS
+database as appropriate.
+
+if the name is not found, then it is added to the NetBIOS name database,
+using add_netbios_entry(), which may choose not to add the name (not
+that this affects the registration of the name on the network in any way).
+it will only add names to the WINS database, and even then it will only
+add non-special-browser type names.
+
+if the name is found, then samba must decide whether to accept the name
+or not. a group name is always added. for unique names, further checks
+need to be carried out.
+
+firstly, if the name in the database is one of samba's names, or if the
+name in the database is a group name, then it cannot be added as a unique
+name belonging to someone else. it is therefore rejected.
+
+secondly, if the ip address of the name being registered does not match
+against the ip in the database, then the unique name may belong to
+someone else. a check needs to be carried out with the owner in case
+they still wish to keep this name. a detailed discussion of what action
+to take is in rfc1001.txt 15.2.2.2 and 15.2.2.3.
+
+samba currently implements non-secured WINS, whereupon the responsibility
+for checking the name is passed on to the host doing the registration.
+rfc1001.txt refers to this as an END-NODE CHALLENGE REGISTRATION RESPONSE.
+(samba itself cannot yet cope with receiving such responses if it
+registers its names with another WINS server).
+
+having decided what kind of response to send (if any - acceptance of
+name registrations by broadcast is implicit), samba will send either a
+positive or negative NAME REGISTRATION RESPONSE, or an END-NODE CHALLENGE
+REGISTRATION RESPONSE to the host that initially sent the registration.
+
+whew.
+
+
+/*************************************************************************
+ reply_name_release()
+ *************************************************************************/
+
+this function is responsible for removing a NetBIOS name from the
+database when a server sends a release packet.
+
+samba looks for the appropriate subnet record that the release should
+be removed from, using find_req_subnet(). next, the name is searched
+for in the local database or the WINS database as appropriate.
+
+if the name is found, it is removed from the database and a
+positive reply is sent confirming this. if the name is not
+found, a negative reply is sent.
+
+a reply is _not_ sent if the release was done by broadcast: the
+release is implicit, and we should be grateful that they bothered
+to tell us. if the release was done by directed packet, then
+we deal with it as a WINS server and must reply (pos / neg).
+
+at present, the criteria for removing a name have yet to be
+developed / experimented with. at present, the only flags that
+are checked are the NetBIOS flags.
+
+
+/*************************************************************************
+ send_name_response()
+ *************************************************************************/
+
+this function is a wrap around reply_netbios_packet(). it sends
+a response to a name registration or release packet, minimising
+the function parameters needed to do this.
+
+if the function is called with the parameter 'success' set to
+True, then a positive response (to the registration or release)
+is made (see rfc1002.txt 4.2.5 and 4.2.10). if this parameter
+is False, then a negative response is issued (see rfc1002.txt
+4.2.6 and 4.2.11)
+
+if the function is called with a registration code, and the
+parameter 'recurse' is False, then an End-Node Challenge
+Registration response is issued (see rfc1002.txt 4.2.7)
+
+note: this function could also easily be used for name conflict
+demand (see rfc1002.txt 4.2.8).
+
+note: End-Node Challenge Registration response is only sent in
+non-secured NetBIOS Name Server implementations. samba now
+implements secured NetBIOS Name Server functionality (see
+rfc1001.txt 15.1.6).
+
diff --git a/source/nameservresp.c b/source/nameservresp.c
new file mode 100644
index 00000000000..5ab70d7a4de
--- /dev/null
+++ b/source/nameservresp.c
@@ -0,0 +1,851 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Revision History:
+
+ Module name: nameservresp.c
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+ 05 jul 96: lkcl@pires.co.uk
+ created module nameservresp containing NetBIOS response functions
+
+*/
+
+#include "includes.h"
+
+extern int ClientNMB;
+
+extern int DEBUGLEVEL;
+
+extern pstring scope;
+extern fstring myworkgroup;
+extern struct in_addr ipzero;
+extern struct in_addr wins_ip;
+extern struct in_addr ipzero;
+
+
+#define GET_TTL(ttl) ((ttl)?MIN(ttl,lp_max_ttl()):lp_max_ttl())
+
+
+/****************************************************************************
+ response for a reg release received. samba has asked a WINS server if it
+ could release a name.
+ **************************************************************************/
+static void response_name_release(struct nmb_name *ans_name,
+ struct subnet_record *d, struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ char *name = ans_name->name;
+ int type = ans_name->name_type;
+
+ DEBUG(4,("response name release received\n"));
+
+ if (nmb->header.rcode == 0 && nmb->answers->rdata)
+ {
+ /* IMPORTANT: see expire_netbios_response_entries() */
+
+ struct in_addr found_ip;
+ putip((char*)&found_ip,&nmb->answers->rdata[2]);
+
+ /* NOTE: we only release our own names at present */
+ if (ismyip(found_ip))
+ {
+ name_unregister_work(d,name,type);
+ }
+ else
+ {
+ DEBUG(2,("name release for different ip! %s %s\n",
+ inet_ntoa(found_ip), namestr(ans_name)));
+ }
+ }
+ else
+ {
+ DEBUG(2,("name release for %s rejected!\n", namestr(ans_name)));
+
+ /* XXXX PANIC! what to do if it's one of samba's own names? */
+
+ /* XXXX do we honestly care if our name release was rejected?
+ only if samba is issuing the release on behalf of some out-of-sync
+ server. if it's one of samba's SELF names, we don't care. */
+ }
+}
+
+
+/****************************************************************************
+response for a reg request received
+**************************************************************************/
+static void response_name_reg(struct nmb_name *ans_name,
+ struct subnet_record *d, struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ BOOL bcast = nmb->header.nm_flags.bcast;
+ char *name = ans_name->name;
+ int type = ans_name->name_type;
+
+ DEBUG(4,("response name registration received!\n"));
+
+#if 1
+ /* This code is neccesitated due to bugs in earlier versions of
+ Samba (up to 1.9.16p11). They respond to a broadcast
+ name registration of WORKGROUP<1b> when they should
+ not. Hence, until these versions are gone, we should
+ treat such errors as success for this particular
+ case only. jallison@whistle.com.
+ */
+ if ( ((d != wins_subnet) && (nmb->header.rcode == 6) && strequal(myworkgroup, name) &&
+ (type == 0x1b)) ||
+ (nmb->header.rcode == 0 && nmb->answers->rdata))
+#else
+ if (nmb->header.rcode == 0 && nmb->answers->rdata)
+#endif
+ {
+ /* IMPORTANT: see expire_netbios_response_entries() */
+
+ int nb_flags = nmb->answers->rdata[0];
+ int ttl = nmb->answers->ttl;
+ struct in_addr found_ip;
+
+ putip((char*)&found_ip,&nmb->answers->rdata[2]);
+
+ name_register_work(d,name,type,nb_flags,ttl,found_ip,bcast);
+ }
+ else
+ {
+ DEBUG(2,("name registration for %s rejected by ip %s!\n",
+ namestr(ans_name), inet_ntoa(p->ip)));
+
+ /* oh dear. we have problems. possibly unbecome a master browser. */
+ name_unregister_work(d,name,type);
+ }
+}
+
+/****************************************************************************
+ response from a name query server check. states of type NAME_QUERY_DOM_SRV_CHK,
+ NAME_QUERY_SRV_CHK, and NAME_QUERY_FIND_MST dealt with here.
+ ****************************************************************************/
+static void response_server_check(struct nmb_name *ans_name,
+ struct response_record *n, struct subnet_record *d, struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ struct in_addr send_ip;
+ enum state_type cmd;
+
+ /* This next fix was from Bernhard Laeser <nlaesb@ascom.ch>
+ who noticed we were replying directly back to the server
+ we sent to - rather than reading the response.
+ */
+
+ if (nmb->header.rcode == 0 && nmb->answers->rdata)
+ putip((char*)&send_ip,&nmb->answers->rdata[2]);
+ else
+ {
+
+ DEBUG(2,("response_server_check: name query for %s failed\n",
+ namestr(ans_name)));
+ return;
+ }
+
+ /* issue another state: this time to do a name status check */
+
+ cmd = (n->state == NAME_QUERY_DOM_SRV_CHK) ?
+ NAME_STATUS_DOM_SRV_CHK : NAME_STATUS_SRV_CHK;
+
+ /* initiate a name status check on address given in the reply
+ record. In addition, the workgroup being checked has been stored
+ in the response_record->my_name (see announce_master) we
+ also propagate this into the same field. */
+ queue_netbios_packet(d,ClientNMB,NMB_STATUS, cmd,
+ ans_name->name, ans_name->name_type,
+ 0,0,0,n->my_name,NULL,
+ False,False,send_ip,n->reply_to_ip, 0);
+}
+
+
+/****************************************************************************
+ interpret a node status response. this is pretty hacked: we need two bits of
+ info. a) the name of the workgroup b) the name of the server. it will also
+ add all the names it finds into the namelist.
+****************************************************************************/
+static BOOL interpret_node_status(struct subnet_record *d,
+ char *p, struct nmb_name *name,int t,
+ char *serv_name, struct in_addr ip, BOOL bcast)
+{
+ int numnames = CVAL(p,0);
+ BOOL found = False;
+
+ DEBUG(4,("received %d names\n",numnames));
+
+ p += 1;
+
+ if (serv_name) *serv_name = 0;
+
+ while (numnames--)
+ {
+ char qname[17];
+ int type;
+ fstring flags;
+ int nb_flags;
+
+ BOOL group = False;
+ BOOL add = False;
+
+ *flags = 0;
+
+ StrnCpy(qname,p,15);
+ type = CVAL(p,15);
+ nb_flags = p[16];
+ trim_string(qname,NULL," ");
+
+ p += 18;
+
+ if (NAME_GROUP (nb_flags)) { strcat(flags,"<GROUP> "); group=True;}
+ if (NAME_BFLAG (nb_flags)) { strcat(flags,"B "); }
+ if (NAME_PFLAG (nb_flags)) { strcat(flags,"P "); }
+ if (NAME_MFLAG (nb_flags)) { strcat(flags,"M "); }
+ if (NAME_HFLAG (nb_flags)) { strcat(flags,"H "); }
+ if (NAME_DEREG (nb_flags)) { strcat(flags,"<DEREGISTERING> "); }
+ if (NAME_CONFLICT (nb_flags)) { strcat(flags,"<CONFLICT> "); }
+ if (NAME_ACTIVE (nb_flags)) { strcat(flags,"<ACTIVE> "); add=True; }
+ if (NAME_PERMANENT(nb_flags)) { strcat(flags,"<PERMANENT> "); add=True;}
+
+ /* we want the server name */
+ if (serv_name && !*serv_name && !group && type == 0x20)
+ {
+ StrnCpy(serv_name,qname,15);
+ serv_name[15] = 0;
+ }
+
+ /* looking for a name and type? */
+ if (name && !found && (t == type))
+ {
+ /* take a guess at some of the name types we're going to ask for.
+ evaluate whether they are group names or no... */
+ if (((t == 0x1b || t == 0x1d || t == 0x20 ) && !group) ||
+ ((t == 0x1c || t == 0x1e ) && group))
+ {
+ found = True;
+ make_nmb_name(name,qname,type,scope);
+ }
+ }
+
+ DEBUG(4,("\t%s(0x%x)\t%s\n",qname,type,flags));
+ }
+ DEBUG(4,("num_good_sends=%d num_good_receives=%d\n",
+ IVAL(p,20),IVAL(p,24)));
+ return found;
+}
+
+
+/****************************************************************************
+ response from a name status check. states of type NAME_STATUS_DOM_SRV_CHK
+ and NAME_STATUS_SRV_CHK dealt with here.
+ ****************************************************************************/
+static void response_name_status_check(struct in_addr ip,
+ struct nmb_packet *nmb, BOOL bcast,
+ struct response_record *n, struct subnet_record *d)
+{
+ /* NMB_STATUS arrives: contains workgroup name and server name required.
+ amongst other things. */
+
+ struct nmb_name name;
+ fstring serv_name;
+
+ if (interpret_node_status(d,nmb->answers->rdata,
+ &name,0x20,serv_name,ip,bcast))
+ {
+ if (*serv_name)
+ {
+ /* response_record->my_name contains the
+ workgroup name to sync with. See
+ response_server_check() */
+ sync_server(n->state,serv_name,
+ n->my_name,name.name_type, d, n->send_ip);
+ }
+ }
+ else
+ {
+ DEBUG(1,("No 0x20 name type in interpret_node_status()\n"));
+ }
+}
+
+
+/****************************************************************************
+ response from a name query for secured WINS registration. a state of
+ NAME_REGISTER_CHALLENGE is dealt with here.
+ ****************************************************************************/
+static void response_name_query_register(struct nmb_packet *nmb,
+ struct nmb_name *ans_name,
+ struct response_record *n, struct subnet_record *d)
+{
+ struct in_addr register_ip;
+ BOOL new_owner;
+
+ DEBUG(4, ("Name query at %s ip %s - ",
+ namestr(&n->name), inet_ntoa(n->send_ip)));
+
+ if (!name_equal(&n->name, ans_name))
+ {
+ /* someone gave us the wrong name as a reply. oops. */
+ /* XXXX should say to them 'oi! release that name!' */
+
+ DEBUG(4,("unexpected name received: %s\n", namestr(ans_name)));
+ return;
+ }
+
+ if (nmb->header.rcode == 0 && nmb->answers->rdata)
+ {
+ /* we had sent out a name query to the current owner
+ of a name because someone else wanted it. now they
+ have responded saying that they still want the name,
+ so the other host can't have it.
+ */
+
+ /* first check all the details are correct */
+
+ int nb_flags = nmb->answers->rdata[0];
+ struct in_addr found_ip;
+
+ putip((char*)&found_ip,&nmb->answers->rdata[2]);
+
+ if (nb_flags != n->nb_flags)
+ {
+ /* someone gave us the wrong nb_flags as a reply. oops. */
+ /* XXXX should say to them 'oi! release that name!' */
+
+ DEBUG(4,("expected nb_flags: %d\n", n->nb_flags));
+ DEBUG(4,("unexpected nb_flags: %d\n", nb_flags));
+ return;
+ }
+
+ if (!ip_equal(n->send_ip, found_ip))
+ {
+ /* someone gave us the wrong ip as a reply. oops. */
+ /* XXXX should say to them 'oi! release that name!' */
+
+ DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip)));
+ DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip)));
+ return;
+ }
+
+ DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
+
+ /* fine: now tell the other host they can't have the name */
+ register_ip = n->send_ip;
+ new_owner = False;
+ }
+ else
+ {
+ DEBUG(4, (" NEGATIVE RESPONSE!\n"));
+
+ /* the owner didn't want the name: the other host can have it */
+ register_ip = n->reply_to_ip;
+ new_owner = True;
+ }
+
+ /* register the old or the new owners' ip */
+ add_name_respond(d, n->fd, d->myip, n->reply_id,&n->name,n->nb_flags,
+ GET_TTL(0), register_ip,
+ new_owner, n->reply_to_ip);
+
+ remove_response_record(d,n); /* remove the response record */
+}
+
+
+/****************************************************************************
+ response from a name query to sync browse lists or to update our netbios
+ entry. states of type NAME_QUERY_SYNC and NAME_QUERY_CONFIRM
+ ****************************************************************************/
+static void response_name_query_sync(struct nmb_packet *nmb,
+ struct nmb_name *ans_name, BOOL bcast,
+ struct response_record *n, struct subnet_record *d)
+{
+ DEBUG(4, ("Name query at %s ip %s - ",
+ namestr(&n->name), inet_ntoa(n->send_ip)));
+
+ if (!name_equal(&n->name, ans_name))
+ {
+ /* someone gave us the wrong name as a reply. oops. */
+ DEBUG(4,("unexpected name received: %s\n", namestr(ans_name)));
+ return;
+ }
+
+ if (nmb->header.rcode == 0 && nmb->answers->rdata)
+ {
+ int nb_flags = nmb->answers->rdata[0];
+ struct in_addr found_ip;
+
+ putip((char*)&found_ip,&nmb->answers->rdata[2]);
+
+ if (!ip_equal(n->send_ip, found_ip))
+ {
+ /* someone gave us the wrong ip as a reply. oops. */
+ DEBUG(4,("expected ip: %s\n", inet_ntoa(n->send_ip)));
+ DEBUG(4,("unexpected ip: %s\n", inet_ntoa(found_ip)));
+ return;
+ }
+
+ DEBUG(4, (" OK: %s\n", inet_ntoa(found_ip)));
+
+ if (n->state == NAME_QUERY_SYNC_LOCAL ||
+ n->state == NAME_QUERY_SYNC_REMOTE)
+ {
+ struct work_record *work = NULL;
+ /* We cheat here as we know that the workgroup name has
+ been placed in the my_comment field of the
+ response_record struct by the code in
+ start_sync_browse_entry().
+ */
+ if ((work = find_workgroupstruct(d, n->my_comment, False)))
+ {
+ BOOL local_list_only = n->state == NAME_QUERY_SYNC_LOCAL;
+
+ /* the server is there: sync quick before it (possibly) dies! */
+ sync_browse_lists(d, work, ans_name->name, ans_name->name_type,
+ found_ip, local_list_only);
+ }
+ }
+ else
+ {
+ /* update our netbios name list (re-register it if necessary) */
+ add_netbios_entry(d, ans_name->name, ans_name->name_type,
+ nb_flags,GET_TTL(0),REGISTER,
+ found_ip,False,!bcast);
+ }
+ }
+ else
+ {
+ DEBUG(4, (" NEGATIVE RESPONSE!\n"));
+
+ if (n->state == NAME_QUERY_CONFIRM)
+ {
+ /* XXXX remove_netbios_entry()? */
+ /* lots of things we ought to do, here. if we get here,
+ then we're in a mess: our name database doesn't match
+ reality. sort it out
+ */
+ remove_netbios_name(d,n->name.name, n->name.name_type,
+ REGISTER,n->send_ip);
+ }
+ }
+}
+
+/****************************************************************************
+ response from a name query for DOMAIN<1b>
+ NAME_QUERY_DOMAIN is dealt with here - we are trying to become a domain
+ master browser and WINS replied - check it's our address.
+ ****************************************************************************/
+static void response_name_query_domain(struct nmb_name *ans_name,
+ struct nmb_packet *nmb,
+ struct response_record *n, struct subnet_record *d)
+{
+ DEBUG(4, ("response_name_query_domain: Got %s response from %s for query \
+for %s\n", nmb->header.rcode == 0 ? "success" : "failure",
+ inet_ntoa(n->send_ip), namestr(ans_name)));
+
+ /* Check the name is correct and ip address returned is our own. If it is then we
+ just remove the response record.
+ */
+ if (name_equal(&n->name, ans_name) && (nmb->header.rcode == 0) && (nmb->answers->rdata))
+ {
+ struct in_addr found_ip;
+
+ putip((char*)&found_ip,&nmb->answers->rdata[2]);
+ /* Samba 1.9.16p11 servers seem to return the broadcast address for this
+ query. */
+ if (ismyip(found_ip) || ip_equal(wins_ip, found_ip) || ip_equal(ipzero, found_ip))
+ {
+ DEBUG(4, ("response_name_query_domain: WINS server returned our ip \
+address. Pretending we never received response.\n"));
+ n->num_msgs = 0;
+ n->repeat_count = 0;
+ n->repeat_time = 0;
+ }
+ else
+ {
+ DEBUG(0,("response_name_query_domain: WINS server already has a \
+domain master browser registered %s at address %s\n",
+ namestr(ans_name), inet_ntoa(found_ip)));
+ }
+ }
+ else
+ {
+ /* Negative/incorrect response. No domain master
+ browser was registered - pretend we didn't get this response.
+ */
+ n->num_msgs = 0;
+ n->repeat_count = 0;
+ n->repeat_time = 0;
+ }
+
+}
+
+/****************************************************************************
+ report the response record type
+ ****************************************************************************/
+static void debug_rr_type(int rr_type)
+{
+ switch (rr_type)
+ {
+ case NMB_STATUS: DEBUG(3,("Name status ")); break;
+ case NMB_QUERY : DEBUG(3,("Name query ")); break;
+ case NMB_REG : DEBUG(3,("Name registration ")); break;
+ case NMB_REL : DEBUG(3,("Name release ")); break;
+ default : DEBUG(1,("wrong response packet type received")); break;
+ }
+}
+
+/****************************************************************************
+ report the response record nmbd state
+ ****************************************************************************/
+void debug_state_type(int state)
+{
+ /* report the state type to help debugging */
+ switch (state)
+ {
+ case NAME_QUERY_DOM_SRV_CHK : DEBUG(4,("NAME_QUERY_DOM_SRV_CHK\n")); break;
+ case NAME_QUERY_SRV_CHK : DEBUG(4,("NAME_QUERY_SRV_CHK\n")); break;
+ case NAME_QUERY_FIND_MST : DEBUG(4,("NAME_QUERY_FIND_MST\n")); break;
+ case NAME_QUERY_MST_CHK : DEBUG(4,("NAME_QUERY_MST_CHK\n")); break;
+ case NAME_QUERY_CONFIRM : DEBUG(4,("NAME_QUERY_CONFIRM\n")); break;
+ case NAME_QUERY_SYNC_LOCAL : DEBUG(4,("NAME_QUERY_SYNC_LOCAL\n")); break;
+ case NAME_QUERY_SYNC_REMOTE : DEBUG(4,("NAME_QUERY_SYNC_REMOTE\n")); break;
+ case NAME_QUERY_DOMAIN : DEBUG(4,("NAME_QUERY_DOMAIN\n")); break;
+
+ case NAME_REGISTER : DEBUG(4,("NAME_REGISTER\n")); break;
+ case NAME_REGISTER_CHALLENGE : DEBUG(4,("NAME_REGISTER_CHALLENGE\n"));break;
+
+ case NAME_RELEASE : DEBUG(4,("NAME_RELEASE\n")); break;
+
+ case NAME_STATUS_DOM_SRV_CHK : DEBUG(4,("NAME_STATUS_DOM_SRV_CHK\n")); break;
+ case NAME_STATUS_SRV_CHK : DEBUG(4,("NAME_STATUS_SRV_CHK\n")); break;
+
+ default: break;
+ }
+}
+
+/****************************************************************************
+ report any problems with the fact that a response has been received.
+
+ (responses for certain types of operations are only expected from one host)
+ ****************************************************************************/
+static BOOL response_problem_check(struct response_record *n,
+ struct nmb_packet *nmb, char *ans_name)
+{
+ switch (nmb->answers->rr_type)
+ {
+ case NMB_REL:
+ {
+ if (n->num_msgs > 1)
+ {
+ DEBUG(1,("more than one release name response received!\n"));
+ return True;
+ }
+ break;
+ }
+
+ case NMB_REG:
+ {
+ if (n->num_msgs > 1)
+ {
+ DEBUG(1,("more than one register name response received!\n"));
+ return True;
+ }
+ break;
+ }
+
+ case NMB_QUERY:
+ {
+ if (n->num_msgs > 1)
+ {
+ if (nmb->header.rcode == 0 && nmb->answers->rdata)
+ {
+ int nb_flags = nmb->answers->rdata[0];
+
+ if ((!NAME_GROUP(nb_flags)))
+ {
+ /* oh dear. more than one person responded to a
+ unique name.
+ there is either a network problem, a
+ configuration problem
+ or a server is mis-behaving */
+
+ /* XXXX mark the name as in conflict, and then let the
+ person who just responded know that they
+ must also mark it
+ as in conflict, and therefore must NOT use it.
+ see rfc1001.txt 15.1.3.5 */
+
+ /* this may cause problems for some
+ early versions of nmbd */
+
+ switch (n->state)
+ {
+ case NAME_QUERY_FIND_MST:
+ {
+ /* query for ^1^2__MSBROWSE__^2^1 expect
+ lots of responses */
+ return False;
+ }
+ case NAME_QUERY_DOM_SRV_CHK:
+ case NAME_QUERY_SRV_CHK:
+ case NAME_QUERY_MST_CHK:
+ {
+ if (!strequal(ans_name,n->name.name))
+ {
+ /* one subnet, one master browser
+ per workgroup */
+ /* XXXX force an election? */
+
+ DEBUG(3,("more than one master browser replied!\n"));
+ return True;
+ }
+ break;
+ }
+ default: break;
+ }
+ DEBUG(3,("Unique Name conflict detected!\n"));
+ return True;
+ }
+ }
+ else
+ {
+ /* we have received a negative reply,
+ having already received
+ at least one response (pos/neg).
+ something's really wrong! */
+
+ DEBUG(3,("wierd name query problem detected!\n"));
+ return True;
+ }
+ }
+ }
+ }
+ return False;
+}
+
+#if 0
+/****************************************************************************
+ check that the response received is compatible with the response record
+ ****************************************************************************/
+static BOOL response_compatible(struct response_record *n,
+ struct nmb_packet *nmb)
+{
+ switch (n->state)
+ {
+ case NAME_RELEASE:
+ {
+ if (nmb->answers->rr_type != 0x20)
+ {
+ DEBUG(1,("Name release reply has wrong answer rr_type\n"));
+ return False;
+ }
+ break;
+ }
+
+ case NAME_REGISTER:
+ {
+ if (nmb->answers->rr_type != 0x20)
+ {
+ DEBUG(1,("Name register reply has wrong answer rr_type\n"));
+ return False;
+ }
+ break;
+ }
+
+ case NAME_REGISTER_CHALLENGE: /* this is a query: we then do a register */
+ case NAME_QUERY_CONFIRM:
+ case NAME_QUERY_SYNC_LOCAL:
+ case NAME_QUERY_SYNC_REMOTE:
+ case NAME_QUERY_DOM_SRV_CHK:
+ case NAME_QUERY_SRV_CHK:
+ case NAME_QUERY_FIND_MST:
+ case NAME_QUERY_MST_CHK:
+ {
+ if (nmb->answers->rr_type != 0x20)
+ {
+ DEBUG(1,("Name query reply has wrong answer rr_type\n"));
+ return False;
+ }
+ break;
+ }
+
+ case NAME_STATUS_DOM_SRV_CHK:
+ case NAME_STATUS_SRV_CHK:
+ {
+ if (nmb->answers->rr_type != 0x21)
+ {
+ DEBUG(1,("Name status reply has wrong answer rr_type\n"));
+ return False;
+ }
+ break;
+ }
+
+ default:
+ {
+ DEBUG(1,("unknown state type received in response_netbios_packet\n"));
+ return False;
+ }
+ }
+ return True;
+}
+#endif
+
+
+/****************************************************************************
+ process the response packet received
+ ****************************************************************************/
+static void response_process(struct subnet_record *d, struct packet_struct *p,
+ struct response_record *n, struct nmb_packet *nmb,
+ BOOL bcast, struct nmb_name *ans_name)
+{
+ switch (n->state)
+ {
+ case NAME_RELEASE:
+ {
+ response_name_release(ans_name, d, p);
+ break;
+ }
+
+ case NAME_REGISTER:
+ {
+ response_name_reg(ans_name, d, p);
+ break;
+ }
+
+ case NAME_REGISTER_CHALLENGE:
+ {
+ response_name_query_register(nmb, ans_name, n, d);
+ break;
+ }
+
+ case NAME_QUERY_DOM_SRV_CHK:
+ case NAME_QUERY_SRV_CHK:
+ case NAME_QUERY_FIND_MST:
+ {
+ response_server_check(ans_name, n, d, p);
+ break;
+ }
+
+ case NAME_STATUS_DOM_SRV_CHK:
+ case NAME_STATUS_SRV_CHK:
+ {
+ response_name_status_check(p->ip, nmb, bcast, n, d);
+ break;
+ }
+
+ case NAME_QUERY_CONFIRM:
+ case NAME_QUERY_SYNC_LOCAL:
+ case NAME_QUERY_SYNC_REMOTE:
+ {
+ response_name_query_sync(nmb, ans_name, bcast, n, d);
+ break;
+ }
+ case NAME_QUERY_MST_CHK:
+ {
+ /* no action required here. it's when NO responses are received
+ that we need to do something. see expire_name_query_entries() */
+
+ DEBUG(4, ("Master browser exists for %s at %s (just checking!)\n",
+ namestr(&n->name), inet_ntoa(n->send_ip)));
+ break;
+ }
+
+ case NAME_QUERY_DOMAIN:
+ {
+ /* We were asking to be a domain master browser, and someone
+ replied. If it was the WINS server and the IP it is
+ returning is our own - then remove the record and pretend
+ we didn't get a response. Else we do nothing and let
+ dead_netbios_entry deal with it.
+ We can only become domain master browser
+ when no broadcast responses are received and WINS
+ either contains no entry for the DOMAIN<1b> name or
+ contains our IP address.
+ */
+ response_name_query_domain(ans_name, nmb, n, d);
+ break;
+ }
+ default:
+ {
+ DEBUG(1,("unknown state type received in response_netbios_packet\n"));
+ break;
+ }
+ }
+}
+
+
+/****************************************************************************
+ response from a netbios packet.
+ ****************************************************************************/
+void response_netbios_packet(struct packet_struct *p)
+{
+ struct nmb_packet *nmb = &p->packet.nmb;
+ struct nmb_name *ans_name = NULL;
+ BOOL bcast = nmb->header.nm_flags.bcast;
+ struct response_record *n;
+ struct subnet_record *d = NULL;
+
+ if (!(n = find_response_record(&d,nmb->header.name_trn_id))) {
+ DEBUG(2,("unknown netbios response id %d (received late or from nmblookup?)\n",
+ nmb->header.name_trn_id));
+ return;
+ }
+
+ if (!d)
+ {
+ DEBUG(2,("response packet: subnet %s not known\n", inet_ntoa(p->ip)));
+ return;
+ }
+
+ /* args wrong way round: spotted by ccm@shentel.net */
+ if (!same_net(d->bcast_ip, p->ip, d->mask_ip)) /* copes with WINS 'subnet' */
+ {
+ DEBUG(2,("response from %s. ", inet_ntoa(p->ip)));
+ DEBUG(2,("expected on subnet %s. hmm.\n", inet_ntoa(d->bcast_ip)));
+ }
+
+ if (nmb->answers == NULL)
+ {
+ /* hm. the packet received was a response, but with no answer. wierd! */
+ DEBUG(2,("NMB packet response from %s (bcast=%s) - UNKNOWN\n",
+ inet_ntoa(p->ip), BOOLSTR(bcast)));
+ return;
+ }
+
+ ans_name = &nmb->answers->rr_name;
+ DEBUG(3,("response for %s from %s(%d) (bcast=%s)\n",
+ namestr(ans_name), inet_ntoa(p->ip), p->port, BOOLSTR(bcast)));
+
+ debug_rr_type(nmb->answers->rr_type);
+
+ n->num_msgs++; /* count number of responses received */
+ n->repeat_count = 0; /* don't resend: see expire_netbios_packets() */
+
+ debug_state_type(n->state);
+
+ /* problem checking: multiple responses etc */
+ if (response_problem_check(n, nmb, ans_name->name))
+ return;
+
+ /* now deal with the current state */
+ response_process(d, p, n, nmb, bcast, ans_name);
+}
diff --git a/source/nameservresp.doc b/source/nameservresp.doc
new file mode 100644
index 00000000000..635db45084f
--- /dev/null
+++ b/source/nameservresp.doc
@@ -0,0 +1,191 @@
+/*
+ Unix SMB/Netbios documentation.
+ Version 0.0
+ Copyright (C) Luke Leighton Andrew Tridgell 1996
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Document name: nameservresp.doc
+
+ Revision History:
+
+ 0.0 - 02jul96 : lkcl@pires.co.uk
+ created
+*/
+
+this module deals with the receipt of response packets. the
+response packets are expected to be received, and there is a
+record of this kept (see also: modules nameresp and namedbresp)
+
+point of interest to design purists: every function in this
+module is static except response_netbios_packet().
+
+/*************************************************************************
+ response_netbios_packet()
+ *************************************************************************/
+
+this function receives netbios response packets. the samba server
+(or a rogue tcp/ip system, or nmblookup) will have sent out a packet
+requesting a response. a client (or a rogue tcp/ip system) responds
+to that request.
+
+this function checks the validity of the packet it receives.
+the expected response records are searched for the transaction id,
+to see if it's a response expected by the samba server. if it isn't
+it's reported as such, and ignored.
+
+if the response is found, then the subnet it was expected from will
+also have been found. the subnet it actually came in on can be
+checked against the subnet it was expected from and reported,
+otherwise this function just carries on.
+
+the number of responses received is increased, and the number of
+retries left to be sent is set to zero.
+
+after debug information is reported, and validation of the netbios
+packet (e.g only one response from one machine is expected for some
+functions) has occurred, the packet is processed. when the initial
+request was sent out, the expected response record was flagged with,
+for lack of a better word, a samba 'state' type. whenever a
+response is received, the appropriate function is called to carry on
+where the program control flow was interrupted while awaiting exactly
+such a response.
+
+please note that _not_ receiving a response is dealt with in another
+area of code - expire_netbios_response_entries().
+
+
+/*************************************************************************
+ response_name_query_sync()
+ *************************************************************************/
+
+this function receives responses to samba 'states' NAME_QUERY_SYNC and
+NAME_QUERY_CONFIRM.
+
+NAME_QUERY_SYNC: name query a server before synchronising browse lists.
+NAME_QUERY_CONFIRM: name query a server to check that it's alive.
+
+a NAME_QUERY_SYNC will be carried out in order to check that a server
+is alive before syncing browse lists. we don't want to delay the SMB
+NetServerEnum api just because the server has gone down: we have too
+much else to do.
+
+a NAME_QUERY_CONFIRM is just a name query to see whether the server is
+alive. these queries are sent out by samba's WINS server side, to verify
+its netbios name database of all machines that have registered with it.
+
+we don't normally expect a negative response from such a query, although
+we may do so if the query was sent to another WINS server. the registered
+entry should be removed if we receive a negative response.
+
+
+/*************************************************************************
+ response_name_status_check()
+ *************************************************************************/
+
+this function receives responses to samba 'states' NAME_STATUS_SRV_CHK
+and NAME_STATUS_DOM_SRV_CHK
+
+NAME_STATUS_DOM_SRV_CHK: name status a domain master browser
+ confirm its domain and then initiate syncing
+ its browse list.
+
+NAME_STATUS_SRV_CHK: same as NAME_STATUS_DOM_SRV_CHK except the
+ name status is issued to a master browser.
+
+if we don't know what workgroup a server is responsible for, but we
+know that there is a master browser at a certain ip, we can issue a
+name status check. from the response received, there will be
+a master browser netbios entry. this will allow us to synchronise
+browse lists with that machine and then add the information to the
+correct part of samba's workgroup - server database.
+
+
+/*************************************************************************
+ response_server_check()
+ *************************************************************************/
+
+this function receives responses to samba 'states' NAME_QUERY_DOM_SRV_CHK,
+NAME_QUERY_SRV_CHK and NAME_QUERY_FIND_MST.
+
+NAME_QUERY_FIND_MST: issued as a broadcast when we wish to find out all
+ master browsers (i.e all servers that have registered
+ the NetBIOS name ^1^2__MSBROWSE__^2(0x1), and then
+ issue a NAME_STATUS_MASTER_CHECK on any servers that
+ respond, which will initiate a sync browse lists.
+
+NAME_QUERY_DOM_SRV_CHK: same as a NAME_QUERY_FIND_MST except this is sent
+ to a domain master browser.
+
+NAME_QUERY_SRV_CHK: same as a NAME_QUERY_DOM_SRV_CHK except this is sent to
+ a master browser.
+
+the purpose of each of these states is to do a broadcast name query, or
+a name query directed at a WINS server, then to all hosts that respond,
+we issue a name status check, which will confirm for us the workgroup
+or domain name, and then initiate issuing a sync browse list call with
+that server.
+
+a NAME_QUERY_SRV_CHK is sent when samba receives a list of backup
+browsers. it checks to see if that server is alive (by doing a
+name query on a server) and then syncs browse lists with it.
+
+
+/*************************************************************************
+ response_name_reg()
+ *************************************************************************/
+
+this function is responsible for dealing with samba's registration
+attempts, by broadcast to a local subnet, or point-to-point with
+another WINS server.
+
+please note that it cannot cope with END-NODE CHALLENGE REGISTRATION
+RESPONSEs at present.
+
+when a response is received, samba determines if the response is a
+positive or a negative one. if it is a positive response, the name
+is added to samba's database.
+
+when a negative response is received, samba will remove the name
+from its database. if, however, the name is a browser type (0x1b is
+a domain master browser type name; or 0x1d, which is a local master
+browser type name) then it must also stop being a domain master
+browser or master browser respectively, depending on what kind
+of name was rejected.
+
+(when no response is received, then expire_netbios_response_entries()
+is expected to deal with this. the only case that is dealt with here
+at present is when the registration was done by broadcast. if there
+is no challenge to the broadcast registration, it is implicitly
+assumed that claiming the name is acceptable).
+
+
+/*************************************************************************
+ response_name_release()
+ *************************************************************************/
+
+this function is responsible for removing samba's NetBIOS name when
+samba contacts another WINS server with which it had registered the
+name.
+
+only positive name releases are expected and dealt with. exactly what
+to do if a negative name release (i.e someone says 'oi! you have to
+keep that name!') is received is uncertain.
+
+(when no response is received, then expire_netbios_response_entries()
+is expected to deal with this. if there is no challenge to the release
+of the name, the name is then removed from that subnet's NetBIOS
+name database).
+
diff --git a/source/namework.c b/source/namework.c
new file mode 100644
index 00000000000..2de4a3016f7
--- /dev/null
+++ b/source/namework.c
@@ -0,0 +1,724 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines and daemon - version 2
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Revision History:
+
+ 14 jan 96: lkcl@pires.co.uk
+ added multiple workgroup domain master support
+
+*/
+
+#include "includes.h"
+
+extern int ClientNMB;
+extern int ClientDGRAM;
+
+#define TEST_CODE /* want to debug unknown browse packets */
+
+extern int DEBUGLEVEL;
+extern pstring scope;
+extern BOOL CanRecurse;
+
+extern pstring myname;
+extern fstring myworkgroup;
+
+extern int ClientNMB;
+extern int ClientDGRAM;
+
+extern struct in_addr ipzero;
+
+extern int workgroup_count; /* total number of workgroups we know about */
+
+/* this is our domain/workgroup/server database */
+extern struct subnet_record *subnetlist;
+
+extern int updatecount;
+
+/* backup request types: which servers are to be included */
+#define MASTER_TYPE (SV_TYPE_MASTER_BROWSER)
+#define DOMCTL_TYPE (SV_TYPE_DOMAIN_CTRL )
+
+extern time_t StartupTime;
+
+extern BOOL updatedlists;
+
+/****************************************************************************
+tell a server to become a backup browser
+state - 0x01 become backup instead of master
+ - 0x02 remove all entries in browse list and become non-master
+ - 0x04 stop master browser service altogether. NT ignores this
+**************************************************************************/
+void reset_server(char *name, int state, struct in_addr ip)
+{
+ char outbuf[20];
+ char *p;
+
+ bzero(outbuf,sizeof(outbuf));
+ p = outbuf;
+
+ CVAL(p,0) = ANN_ResetBrowserState;
+ CVAL(p,2) = state;
+ p += 2;
+
+ DEBUG(2,("sending reset to %s %s of state %d\n",
+ name,inet_ntoa(ip),state));
+
+ send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
+ outbuf,PTR_DIFF(p,outbuf),
+ myname,name,0x20,0x1d,ip,*iface_ip(ip));
+}
+
+
+/****************************************************************************
+tell a server to become a backup browser
+**************************************************************************/
+void tell_become_backup(void)
+{
+ /* XXXX note: this function is currently unsuitable for use, as it
+ does not properly check that a server is in a fit state to become
+ a backup browser before asking it to be one.
+ */
+
+ struct subnet_record *d;
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ struct work_record *work;
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ struct server_record *s;
+ int num_servers = 0;
+ int num_backups = 0;
+
+ for (s = work->serverlist; s; s = s->next)
+ {
+ if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
+
+ num_servers++;
+
+ if (is_myname(s->serv.name)) continue;
+
+ if (s->serv.type & SV_TYPE_BACKUP_BROWSER) {
+ num_backups++;
+ continue;
+ }
+
+ if (s->serv.type & SV_TYPE_MASTER_BROWSER) continue;
+
+ if (!(s->serv.type & SV_TYPE_POTENTIAL_BROWSER)) continue;
+
+ DEBUG(3,("num servers: %d num backups: %d\n",
+ num_servers, num_backups));
+
+ /* make first server a backup server. thereafter make every
+ tenth server a backup server */
+ if (num_backups != 0 && (num_servers+9) / num_backups > 10)
+ {
+ continue;
+ }
+
+ DEBUG(2,("sending become backup to %s %s for %s\n",
+ s->serv.name, inet_ntoa(d->bcast_ip),
+ work->work_group));
+
+ /* type 11 request from MYNAME(20) to WG(1e) for SERVER */
+ do_announce_request(s->serv.name, work->work_group,
+ ANN_BecomeBackup, 0x20, 0x1e, d->bcast_ip);
+ }
+ }
+ }
+}
+
+
+/*******************************************************************
+ same context: scope. should check name_type as well, and makes sure
+ we don't process messages from ourselves
+ ******************************************************************/
+BOOL same_context(struct dgram_packet *dgram)
+{
+ if (!strequal(dgram->dest_name .scope,scope )) return(True);
+ if ( is_myname(dgram->source_name.name)) return(True);
+
+ return(False);
+}
+
+
+/*******************************************************************
+ process a domain announcement frame
+
+ Announce frames come in 3 types. Servers send host announcements
+ (command=1) to let the master browswer know they are
+ available. Master browsers send local master announcements
+ (command=15) to let other masters and backups that they are the
+ master. They also send domain announcements (command=12) to register
+ the domain
+
+ The comment field of domain announcements contains the master
+ browser name. The servertype is used by NetServerEnum to select
+ resources. We just have to pass it to smbd (via browser.dat) and let
+ the client choose using bit masks.
+ ******************************************************************/
+static void process_localnet_announce(struct packet_struct *p,uint16 command,char *buf)
+{
+ struct dgram_packet *dgram = &p->packet.dgram;
+ struct subnet_record *d = find_subnet(p->ip); /* Explicitly exclude WINS - local nets only */
+ int update_count = CVAL(buf,0);
+
+ int ttl = IVAL(buf,1)/1000;
+ char *name = buf+5;
+ int osmajor=CVAL(buf,21);
+ int osminor=CVAL(buf,22);
+ uint32 servertype = IVAL(buf,23);
+ uint32 browse_type= CVAL(buf,27);
+ uint32 browse_sig = CVAL(buf,29);
+ char *comment = buf+31;
+
+ struct work_record *work;
+ char *work_name;
+ char *serv_name = dgram->source_name.name;
+ BOOL add = False;
+
+ comment[43] = 0;
+
+ DEBUG(4,("Announce(%d) %s(%x)",command,name,name[15]));
+ DEBUG(4,("%s count=%d ttl=%d OS=(%d,%d) type=%08x sig=%4x %4x comment=%s\n",
+ namestr(&dgram->dest_name),update_count,ttl,osmajor,osminor,
+ servertype,browse_type,browse_sig,comment));
+
+ name[15] = 0;
+
+ if (dgram->dest_name.name_type == 0 && command == ANN_HostAnnouncement)
+ {
+ DEBUG(2,("Announce to nametype(0) not supported yet\n"));
+ return;
+ }
+
+ if (command == ANN_DomainAnnouncement &&
+ ((!strequal(dgram->dest_name.name, MSBROWSE)) ||
+ dgram->dest_name.name_type != 0x1))
+ {
+ DEBUG(0,("Announce(%d) from %s should be __MSBROWSE__(1) not %s\n",
+ command, inet_ntoa(p->ip), namestr(&dgram->dest_name)));
+ return;
+ }
+
+ if (!strequal(dgram->dest_name.scope,scope )) return;
+
+ if (command == ANN_DomainAnnouncement) {
+ /* XXXX if we are a master browser for the workgroup work_name,
+ then there is a local subnet configuration problem. only
+ we should be sending out such domain announcements, because
+ as the master browser, that is our job.
+
+ stop being a master browser, and force an election. this will
+ sort out the network problem. hopefully.
+ */
+
+ work_name = name;
+ add = True;
+ } else {
+ work_name = dgram->dest_name.name;
+ }
+
+ /* we need some way of finding out about new workgroups
+ that appear to be sending packets to us. The name_type checks make
+ sure we don't add host names as workgroups */
+ if (command == ANN_HostAnnouncement &&
+ (dgram->dest_name.name_type == 0x1d ||
+ dgram->dest_name.name_type == 0x1e))
+ add = True;
+
+ DEBUG(4,("search for workgroup: %s (add? %s)\n",
+ work_name, BOOLSTR(add)));
+
+ if (!(work = find_workgroupstruct(d, work_name,add)))
+ return;
+
+ DEBUG(4, ("workgroup %s on %s\n", work->work_group, serv_name));
+
+ ttl = GET_TTL(ttl);
+
+ /* add them to our browse list, and update the browse.dat file */
+ add_server_entry(d,work,name,servertype|SV_TYPE_LOCAL_LIST_ONLY,ttl,comment,True);
+ updatedlists = True;
+
+#if 0
+ /* the tell become backup code is broken, no great harm is done by
+ disabling it */
+ tell_become_backup();
+#endif
+}
+
+/*******************************************************************
+ process a master announcement frame
+ Domain master browsers recieve these from local masters. The Domain
+ master should then issue a sync with the local master, asking for
+ that machines local server list.
+ ******************************************************************/
+static void process_master_announce(struct packet_struct *p,char *buf)
+{
+ struct dgram_packet *dgram = &p->packet.dgram;
+ char *name = buf;
+ struct work_record *work;
+ name[15] = 0;
+
+ DEBUG(3,("process_master_announce: Master Announce from %s (%s)\n",name,inet_ntoa(p->ip)));
+
+ if (same_context(dgram)) return;
+
+ if (!wins_subnet)
+ {
+ DEBUG(3,("process_master_announce: No wins subnet !\n"));
+ return;
+ }
+
+ if (!lp_domain_master())
+ {
+ DEBUG(3,("process_master_announce: Not configured as domain master - ignoring master announce.\n"));
+ return;
+ }
+
+ for (work = wins_subnet->workgrouplist; work; work = work->next)
+ {
+ if (AM_MASTER(work) || AM_DOMMST(work))
+ {
+ /* merge browse lists with them */
+ add_browser_entry(name,0x1d, work->work_group,30,wins_subnet,p->ip,True);
+ }
+ }
+}
+
+/*******************************************************************
+ process a receive backup list request
+
+ we receive a list of servers, and we attempt to locate them all on
+ our local subnet, and sync browse lists with them on the workgroup
+ they are said to be in.
+
+ XXXX NOTE: this function is in overdrive. it should not really do
+ half of what it actually does (it should pick _one_ name from the
+ list received and sync with it at regular intervals, rather than
+ sync with them all only once!)
+
+ ******************************************************************/
+static void process_rcv_backup_list(struct packet_struct *p,char *buf)
+{
+ struct dgram_packet *dgram = &p->packet.dgram;
+ int count = CVAL(buf,0);
+ uint32 info = IVAL(buf,1); /* XXXX caller's incremental info */
+ char *buf1;
+
+ DEBUG(3,("Receive Backup ack for %s from %s total=%d info=%d\n",
+ namestr(&dgram->dest_name), inet_ntoa(p->ip),
+ count, info));
+
+ if (same_context(dgram)) return;
+
+ if (count <= 0) return;
+
+ /* go through the list of servers attempting to sync browse lists */
+ for (buf1 = buf+5; *buf1 && count; buf1 = skip_string(buf1, 1), --count)
+ {
+ struct in_addr back_ip;
+ /* struct subnet_record *d; */
+
+ DEBUG(4,("Searching for backup browser %s at %s...\n",
+ buf1, inet_ntoa(p->ip)));
+
+ /* XXXX assume name is a DNS name NOT a netbios name. a more complete
+ approach is to use reply_name_query functionality to find the name */
+
+ back_ip = *interpret_addr2(buf1);
+
+ if (zero_ip(back_ip))
+ {
+ DEBUG(4,("Failed to find backup browser server using DNS\n"));
+ continue;
+ }
+
+ DEBUG(4,("Found browser server at %s\n", inet_ntoa(back_ip)));
+ DEBUG(4,("END THIS LOOP: CODE NEEDS UPDATING\n"));
+
+#if 0
+ /* XXXX function needs work */
+ continue;
+
+ if ((d = find_subnet(back_ip)))
+ {
+ struct subnet_record *d1;
+ for (d1 = subnetlist; d1; d1 = d1->next)
+ {
+ struct work_record *work;
+ for (work = d1->workgrouplist; work; work = work->next)
+ {
+ if (work->token == 0 /* token */)
+ {
+ queue_netbios_packet(d1,ClientNMB,NMB_QUERY,NAME_QUERY_SRV_CHK,
+ work->work_group,0x1d,
+ 0,0,0,NULL,NULL,
+ False,False,back_ip,back_ip,
+ 0);
+ return;
+ }
+ }
+ }
+ }
+#endif
+ }
+}
+
+
+/****************************************************************************
+ send a backup list response.
+ **************************************************************************/
+static void send_backup_list(char *work_name, struct nmb_name *src_name,
+ int token, uint32 info,
+ int name_type, struct in_addr ip)
+{
+ char outbuf[1024];
+ char *p, *countptr, *nameptr;
+ int count = 0;
+ char *theirname = src_name->name;
+
+ DEBUG(3,("sending backup list of %s to %s: %s(%x) %s(%x)\n",
+ work_name, inet_ntoa(ip),
+ myname,0x0,theirname,0x0));
+
+ if (name_type == 0x1d)
+ {
+ DEBUG(4,("master browsers: "));
+ }
+ else if (name_type == 0x1b)
+ {
+ DEBUG(4,("domain controllers: "));
+ }
+ else
+ {
+ DEBUG(0,("backup request for unknown type %0x\n", name_type));
+ return;
+ }
+
+ bzero(outbuf,sizeof(outbuf));
+ p = outbuf;
+
+ CVAL(p,0) = ANN_GetBackupListResp; /* backup list response */
+
+ p++;
+ countptr = p;
+
+ SIVAL(p,1,info); /* the sender's unique info */
+
+ p += 5;
+
+ nameptr = p;
+
+#if 0
+
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ {
+ struct work_record *work;
+
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ struct server_record *s;
+
+ if (!strequal(work->work_group, work_name)) continue;
+
+ for (s = work->serverlist; s; s = s->next)
+ {
+ BOOL found = False;
+ char *n;
+
+ if (s->serv.type & SV_TYPE_DOMAIN_ENUM) continue;
+
+ for (n = nameptr; n < p; n = skip_string(n, 1))
+ {
+ if (strequal(n, s->serv.name)) found = True;
+ }
+
+ if (found) continue; /* exclude names already added */
+
+ /* workgroup request: include all backup browsers in the list */
+ /* domain request: include all domain members in the list */
+
+ if ((name_type == 0x1d && (s->serv.type & MASTER_TYPE)) ||
+ (name_type == 0x1b && (s->serv.type & DOMCTL_TYPE)))
+ {
+ DEBUG(4, ("%s ", s->serv.name));
+
+ count++;
+ strcpy(p,s->serv.name);
+ strupper(p);
+ p = skip_string(p,1);
+ }
+ }
+ }
+ }
+
+#endif
+
+ count++;
+ strcpy(p,myname);
+ strupper(p);
+ p = skip_string(p,1);
+
+ if (count == 0)
+ {
+ DEBUG(4, ("none\n"));
+ }
+ else
+ {
+ DEBUG(4, (" - count %d\n", count));
+ }
+
+ CVAL(countptr, 0) = count;
+
+ {
+ int len = PTR_DIFF(p, outbuf);
+ debug_browse_data(outbuf, len);
+ }
+ send_mailslot_reply(False,BROWSE_MAILSLOT,ClientDGRAM,
+ outbuf,PTR_DIFF(p,outbuf),
+ myname,theirname,0x0,0x0,ip,*iface_ip(ip));
+}
+
+
+/*******************************************************************
+ process a send backup list request
+
+ A client sends a backup list request to ask for a list of servers on
+ the net that maintain server lists for a domain. A server is then
+ chosen from this list to send NetServerEnum commands to to list
+ available servers.
+
+ Currently samba only sends back one name in the backup list, its
+ own. For larger nets we'll have to add backups and send "become
+ backup" requests occasionally.
+ ******************************************************************/
+static void process_send_backup_list(struct packet_struct *p,char *buf)
+{
+ struct dgram_packet *dgram = &p->packet.dgram;
+ struct in_addr ip = dgram->header.source_ip;
+ struct subnet_record *d;
+ struct work_record *work;
+
+ int token = CVAL(buf,0); /* sender's key index for the workgroup */
+ uint32 info = IVAL(buf,1); /* XXXX don't know: some sort of info */
+ int name_type = dgram->dest_name.name_type;
+
+ if (same_context(dgram)) return;
+
+ if (name_type != 0x1b && name_type != 0x1d) {
+ DEBUG(0,("backup request to wrong type %d from %s\n",
+ name_type,inet_ntoa(ip)));
+ return;
+ }
+
+ for (d = subnetlist; d; d = d->next)
+ {
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ if (strequal(work->work_group, dgram->dest_name.name))
+ {
+ DEBUG(2,("sending backup list to %s %s id=%x\n",
+ namestr(&dgram->dest_name),inet_ntoa(ip),info));
+
+ send_backup_list(work->work_group,&dgram->source_name,
+ token,info,name_type,ip);
+ return;
+ }
+ }
+ }
+}
+
+
+/*******************************************************************
+ process a reset browser state
+
+ diagnostic packet:
+ 0x1 - stop being a master browser and become a backup browser.
+ 0x2 - discard browse lists, stop being a master browser, try again.
+ 0x4 - stop being a master browser forever. no way. ain't gonna.
+
+ ******************************************************************/
+static void process_reset_browser(struct packet_struct *p,char *buf)
+{
+ struct dgram_packet *dgram = &p->packet.dgram;
+ int state = CVAL(buf,0);
+
+ DEBUG(1,("received diagnostic browser reset request to %s state=0x%X\n",
+ namestr(&dgram->dest_name), state));
+
+ /* stop being a master but still deal with being a backup browser */
+ if (state & 0x1)
+ {
+ struct subnet_record *d;
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_EXCLUDING_WINS(d))
+ {
+ struct work_record *work;
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ if (AM_MASTER(work))
+ {
+ unbecome_local_master(d,work,SV_TYPE_MASTER_BROWSER);
+ }
+ }
+ }
+ }
+
+ /* XXXX documentation inconsistency: the above description does not
+ exactly tally with what is implemented for state & 0x2
+ */
+
+ /* totally delete all servers and start afresh */
+ if (state & 0x2)
+ {
+ struct subnet_record *d;
+ for (d = FIRST_SUBNET; d; d = NEXT_SUBNET_INCLUDING_WINS(d))
+ {
+ struct work_record *work;
+ for (work=d->workgrouplist;work;work=remove_workgroup(d,work,True));
+ }
+ add_my_subnets(myworkgroup);
+ }
+
+ /* stop browsing altogether. i don't think this is a good idea! */
+ if (state & 0x4)
+ {
+ DEBUG(1,("ignoring request to stop being a browser. sorry!\n"));
+ }
+}
+
+/*******************************************************************
+ process a announcement request
+
+ clients send these when they want everyone to send an announcement
+ immediately. This can cause quite a storm of packets!
+ ******************************************************************/
+static void process_announce_request(struct packet_struct *p,char *buf)
+{
+ struct dgram_packet *dgram = &p->packet.dgram;
+ struct work_record *work;
+ struct in_addr ip = dgram->header.source_ip;
+ struct subnet_record *d = find_subnet(ip); /* Explicitly NO WINS */
+ int token = CVAL(buf,0);
+ char *name = buf+1;
+
+ name[15] = 0;
+
+ DEBUG(3,("process_announce_request: Announce request from %s to %s token=0x%X\n",
+ name,namestr(&dgram->dest_name), token));
+
+ if (is_myname(dgram->source_name.name)) return;
+
+ /* XXXX BUG or FEATURE?: need to ensure that we are a member of
+ this workgroup before announcing, particularly as we only
+ respond on local interfaces anyway.
+
+ if (strequal(dgram->dest_name, myworkgroup) return; ???
+ */
+
+ if (!d)
+ {
+ DEBUG(3,("process_announce_request: No local interface to announce to %s\n",
+ name));
+ return;
+ }
+
+ for (work = d->workgrouplist; work; work = work->next)
+ {
+ /* XXXX BUG: the destination name type should also be checked,
+ not just the name. e.g if the name is WORKGROUP(0x1d) then
+ we should only respond if we own that name */
+
+ if (strequal(dgram->dest_name.name,work->work_group))
+ {
+ work->needannounce = True;
+ }
+ }
+}
+
+
+
+/****************************************************************************
+process a browse frame
+****************************************************************************/
+void process_browse_packet(struct packet_struct *p,char *buf,int len)
+{
+ int command = CVAL(buf,0);
+ switch (command)
+ {
+ case ANN_HostAnnouncement:
+ case ANN_DomainAnnouncement:
+ case ANN_LocalMasterAnnouncement:
+ {
+ debug_browse_data(buf, len);
+ process_localnet_announce(p,command,buf+1);
+ break;
+ }
+
+ case ANN_AnnouncementRequest:
+ {
+ process_announce_request(p,buf+1);
+ break;
+ }
+
+ case ANN_Election:
+ {
+ process_election(p,buf+1);
+ break;
+ }
+
+ case ANN_GetBackupListReq:
+ {
+ debug_browse_data(buf, len);
+ process_send_backup_list(p,buf+1);
+ break;
+ }
+
+ case ANN_GetBackupListResp:
+ {
+ debug_browse_data(buf, len);
+ process_rcv_backup_list(p, buf+1);
+ break;
+ }
+
+ case ANN_ResetBrowserState:
+ {
+ process_reset_browser(p, buf+1);
+ break;
+ }
+
+ case ANN_MasterAnnouncement:
+ {
+ process_master_announce(p,buf+1);
+ break;
+ }
+
+ default:
+ {
+ struct dgram_packet *dgram = &p->packet.dgram;
+ DEBUG(4,("ignoring browse packet %d from %s %s to %s\n",
+ command, namestr(&dgram->source_name),
+ inet_ntoa(p->ip), namestr(&dgram->dest_name)));
+ }
+ }
+}
+
+
diff --git a/source/namework.doc b/source/namework.doc
new file mode 100644
index 00000000000..958a86c8668
--- /dev/null
+++ b/source/namework.doc
@@ -0,0 +1,363 @@
+/*
+ Unix SMB/Netbios documentation.
+ Version 0.1
+ Copyright (C) Luke Leighton Andrew Tridgell 1996
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ Document name: namework.doc
+
+ Revision History:
+
+ 0.0 - 02jul96 : lkcl@pires.co.uk
+ created
+
+ 0.1 - 22jul96 Andrew.Tridgell@anu.edu.au
+ tridge's comments on first revision
+*/
+
+the module namework.c deals with NetBIOS datagram packets, primarily.
+it deals with nmbd's workgroup browser side and the domain log in
+side. none of the functionality here has specification documents available.
+empirical observation of packet traces has been the order of the day,
+along with some guess-work.
+
+beware!
+
+the receipt of datagram packets for workgroup browsing are dealt with here.
+some of the functions listed here will call others outside of this
+module, or will activate functionality dealt with by other modules
+(namedb, nameannounce, nameelect, namelogon, and namebrowse).
+
+
+/*************************************************************************
+ process_browse_packet()
+ *************************************************************************/
+
+this function is responsible for further identifying which type of
+browser datagram packet has been received, and dealing with it
+accordingly. if the packet is not dealt with, then an error is
+logged along with the type of packet that has been received.
+
+if listening_type() was in use, then it would be used here.
+
+the types of packets received and dealt with are:
+
+- ANN_HostAnnouncement
+- ANN_DomainAnnouncement
+- ANN_LocalMasterAnnouncement
+
+these are all identical in format and can all be processed by
+process_announce(). an announcement is received from a host
+(either a master browser telling us about itself, a server
+telling us about itself or a master browser telling us about
+a domain / workgroup)
+
+- ANN_AnnouncementRequest
+
+these are sent by master browsers or by servers. it is a
+request to announce ourselves as appropriate by sending
+either a ANN_HostAnnouncement datagram or both an
+ANN_DomainAnnouncement and an ANN_LocalMasterAnnouncement
+if we are a master browser (but not both).
+
+- ANN_Election
+
+this is an election datagram. if samba has been configured
+as a domain master then it will also send out election
+datagrams.
+
+- ANN_GetBackupListReq
+
+this is a request from another server for us to send a
+backup list of all servers that we know about. we respond
+by sending a datagram ANN_GetBackupListResp. the protocol
+here is a little dicey.
+
+- ANN_GetBackupListResp
+
+this is a response from another server that we have sent an
+ANN_GetBackupListReq to. the protocol is a little dicey.
+
+- ANN_BecomeBackup
+
+this is a message sent by a master browser to a
+potential master browser, indicating that it should become
+a backup master browser for the workgroup it is a member
+of. samba does not respond at present to such datagrams,
+and it also sends out such datagrams for the wrong reasons
+(this code has now been disabled until this is fixed).
+
+- ANN_ResetBrowserState
+
+this datagram is sent for trouble-shooting purposes.
+it asks a browser to clear out its server lists, or to
+stop becoming a master browser altogether. NT/AS and
+samba do not implement this latter option.
+
+- ANN_MasterAnnouncement
+
+this datagram is sent by a master browser to a domain master
+browser. it is a way to ensure that master browsers are kept in sync
+with a domain master browser across a wide area network. on
+receipt of an ANN_MasterAnnouncement we should sync browse lists with
+the sender.
+
+(i never got the hang of this one when i was experimenting.
+i forget exactly what it's for, and i never fully worked
+out how to coax a server to send it. :-)
+
+NOTE FROM TRIDGE: The reason you didn't work out how to coax a server
+into sending it is that you can't (or shouldn't try!). Basically these
+"master announce" datagrams are the way that separate netbios subnets
+are linked together to form a complete browse net. The way it works is
+that the local master decides it is going to inform the domain master
+of its presence, then sends this master announce to the domain
+master. The domain master then syncs with the local master using a
+"local only" sync. The whole transaction is initiated by the local
+master, not the domain master, so the domain master should not do any
+of this if it does not first receive a "master announcement". The
+local domain masters need to be configured to know the IP address of
+the domain master.
+
+
+/*************************************************************************
+ listening_type()
+ *************************************************************************/
+
+
+a datagram packet is sent from one NetBIOS name of a specific type
+to another NetBIOS name of a specific type. certain types of
+datagrams are only expected from certain types of NetBIOS names.
+
+this function is intended to catch errors in the type of datagrams
+received from different NetBIOS names. it is currently incomplete
+due to lack of information on the types of names and the datagrams
+they send.
+
+
+/*************************************************************************
+ process_announce_request()
+ *************************************************************************/
+
+this function is responsible for dealing with announcement requests.
+if the type of name that the request is sent to matches our current
+status, then we should respond. otherwise, the datagram should be
+ignored.
+
+samba only responds on its local subnets.
+
+at present, just the name is checked to see if the packet is for us.
+what should be done is that if we own the name (e.g WORGROUP(0x1d)
+or WORKGROUP(0x1b) then we should respond, otherwise, ignore the
+datagram.
+
+if the name is for us, and we are a member of that workgroup, then
+samba should respond.
+
+note that samba does not respond immediately. this is to ensure that
+if the master browser for the workgroup that samba is a member of
+sends out a broadcast request announcement, that that master browser
+is not swamped with replies. it is therefore up to samba to reply
+at some random interval. hence, a flag is set indicating the need
+to announce later.
+
+
+/*************************************************************************
+ process_reset_browser()
+ *************************************************************************/
+
+this function is responsible for dealing with reset state datagrams.
+there are three kinds of diagnostic reset requests:
+
+- stop being a master browser
+- discard browse lists, stop being a master browser, and run for re-election
+- stop being a master browser forever.
+
+samba and windows nt do not implement the latter option.
+
+there appears to be a discrepancy between this description and the
+code actually implemented.
+
+
+/*************************************************************************
+ process_send_backup_list()
+ *************************************************************************/
+
+this function is part of samba's domain master browser functionality.
+
+it is responsible for giving master browsers a list of other browsers
+that maintain backup lists of servers for that master browser's workgroup.
+
+it is also responsible for giving master browsers a list of domain master
+browsers for that local master browser's domain.
+
+a correct way to think of this function is that it is a 'request to
+send out a backup list for the requested workgroup or domain'.
+
+i have some suspicions and intuitions about this function and how it
+is to actually be used. there is no documentation on this, so it is a
+matter of experimenting until it's right.
+
+
+/*************************************************************************
+ send_backup_list()
+ *************************************************************************/
+
+this function is responsible for compiling a list of either master
+browsers and backup master browsers or domain master browsers and
+backup domain master browsers. samba constructs this list from its
+workgroup / server database.
+
+the list is then sent to the host that requested it by sending an
+ANN_GetBackupListResp datagram to this host.
+
+
+NOTE FROM TRIDGE: The "backup list" stuff is only relevant to
+local subnets. It has nothing to do with PDCs or domain masters. Its
+function is twofold:
+
+1) spread the browsing load over multiple servers so one server
+doesn't get overloaded with browse requests
+2) make sure the database doesn't get lost completely if the master
+goes down
+
+To accomplish this a few things are supposed to be done:
+
+- the master browser maintains a list of "backup browsers".
+
+- backup browsers are are machines that are just like ordinary servers
+but also maintain a browse list and respond to "NetServerEnum"
+requests
+
+- when a server initially announces itself to the master it may set
+its "maintain browse list" flag to auto.
+
+- when a master browser sees a server announcement with "auto" set it
+may send a "become backup" to that server telling it to become a
+backup.
+
+- the master has a simple algorithm to determine how many backups it wants
+given the number of hosts on the net
+
+- when a client wishes to get a browse list it asks the master for a
+backup list. The master sends it the current list of backup browsers,
+including itself. The client caches this list. The client then sends
+the NetServerEnum to a random member of this list easch time it wants
+to browse. This spreads the load.
+
+
+
+/*************************************************************************
+ process_rcv_backup_list()
+ *************************************************************************/
+
+this function is implemented with a slightly over-kill algorithm.
+the correct functionality is to pick any three names at random from
+the list that is received from this datagram, and then at intervals
+contact _one_ of them for a list of browser, in order to update
+samba's browse list.
+
+samba contacts every single one of the backup browsers listed, through
+the use of a NAME_QUERY_SRV_CHK 'state'.
+
+
+/*************************************************************************
+ process_master_announce()
+ *************************************************************************/
+
+this function is responsible for synchronising browse lists with a
+master browser that contacts samba in its capacity as a domain master
+browser.
+
+the function add_browser_entry() is used to add the server that
+contacts us to our list of browser to sync browse lists with at
+some point in the near future.
+
+
+/*************************************************************************
+ process_announce()
+ *************************************************************************/
+
+this function is responsible for dealing with the three types of
+announcement type datagrams that samba recognises. some appropriate
+type-checking is done on the name that the datagram is sent to.
+
+samba does not at present deal with LanManager announcements.
+
+these announcements are for updating the browse entry records.
+each browse entry has a time-to-live associated with it. each server
+must refresh its entry with all other servers by broadcasting
+Announcements. if it does not do so, then other servers will not
+know about that machine, and the records on each server of that
+other machine will die.
+
+if an ANN_DomainAnnouncement is received, then this will be from
+a master browser. only one machine on any given broadcast area (e.g
+a subnet) should be broadcasting such announcements. the information
+it contains tells other servers that there is a master browser for
+this workgroup. if another server thinks that it is also a master
+browser for the same workgroup, then it should stop being a master
+browser and force an election.
+
+if an ANN_LocalMasterAnnouncement is received, then a master browser
+is telling us that it exists. i am uncertain that anything else
+actually needs to be done with this, other than to shout 'hooray' and
+'thank you for informing me of this fact'.
+
+
+/*************************************************************************
+ listening_name()
+ *************************************************************************/
+
+this function is an over-simplified way of identifying whether we
+should be responding to a datagram that has been received.
+
+
+/*************************************************************************
+ same_context()
+ *************************************************************************/
+
+this function helps us to identify whether we should be responding to
+a datagram that has been received.
+
+
+/*************************************************************************
+ tell_become_backup()
+ *************************************************************************/
+
+this function is part of samba's domain master browser capabilities.
+it is responsible for finding appropriate servers to tell to become a
+backup master browser for the domain that samba controls.
+
+other servers that contact samba asking for a list of backup browsers
+will then be given that server's name, and that server can expect to
+receive NetServerEnum requests for lists of servers and workgroups.
+
+this function must be updated before it is in a fit state to be used.
+it must properly check whether a server is prepared to become a backup
+browser before actually asking it to be one.
+
+
+/*************************************************************************
+ reset_server()
+ *************************************************************************/
+
+this function is responsible for issuing an ANN_ResetBrowserState to
+the specified server, asking it to reset its browser information.
+
+see process_reset_browser() for details on this function.
+
+
diff --git a/source/nmbd/asyncdns.c b/source/nmbd/asyncdns.c
deleted file mode 100644
index 1ee9dab0658..00000000000
--- a/source/nmbd/asyncdns.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- a async DNS handler
- Copyright (C) Andrew Tridgell 1997
-
- 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.
- */
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-/***************************************************************************
- Add a DNS result to the name cache.
-****************************************************************************/
-
-static struct name_record *add_dns_result(struct nmb_name *question, struct in_addr addr)
-{
- int name_type = question->name_type;
- char *qname = question->name;
-
-
- if (!addr.s_addr) {
- /* add the fail to WINS cache of names. give it 1 hour in the cache */
- DEBUG(3,("add_dns_result: Negative DNS answer for %s\n", qname));
- add_name_to_subnet(wins_server_subnet,qname,name_type,
- NB_ACTIVE, 60*60, DNSFAIL_NAME, 1, &addr);
- return NULL;
- }
-
- /* add it to our WINS cache of names. give it 2 hours in the cache */
- DEBUG(3,("add_dns_result: DNS gave answer for %s of %s\n", qname, inet_ntoa(addr)));
-
- return add_name_to_subnet(wins_server_subnet,qname,name_type,
- NB_ACTIVE, 2*60*60, DNS_NAME, 1, &addr);
-}
-
-
-
-#ifndef SYNC_DNS
-
-static int fd_in = -1, fd_out = -1;
-static int child_pid = -1;
-static int in_dns;
-
-/* this is the structure that is passed between the parent and child */
-struct query_record {
- struct nmb_name name;
- struct in_addr result;
-};
-
-/* a queue of pending requests waiting to be sent to the DNS child */
-static struct packet_struct *dns_queue;
-
-/* the packet currently being processed by the dns child */
-static struct packet_struct *dns_current;
-
-
-/***************************************************************************
- return the fd used to gather async dns replies. This is added to the select
- loop
- ****************************************************************************/
-int asyncdns_fd(void)
-{
- return fd_in;
-}
-
-/***************************************************************************
- handle DNS queries arriving from the parent
- ****************************************************************************/
-static void asyncdns_process(void)
-{
- struct query_record r;
- fstring qname;
-
- DEBUGLEVEL = -1;
-
- while (1) {
- if (read_data(fd_in, (char *)&r, sizeof(r)) != sizeof(r))
- break;
-
- fstrcpy(qname, r.name.name);
-
- r.result.s_addr = interpret_addr(qname);
-
- if (write_data(fd_out, (char *)&r, sizeof(r)) != sizeof(r))
- break;
- }
-
- _exit(0);
-}
-
-/**************************************************************************** **
- catch a sigterm
- We need a separate term handler here so we don't release any
- names that our parent is going to release, or overwrite a
- WINS db that our parent is going to write.
- **************************************************************************** */
-
-static int sig_term()
-{
- BlockSignals(True,SIGTERM);
-
- DEBUG(0,("async dns child. Got SIGTERM: going down...\n"));
-
- exit(0);
- /* Keep compiler happy.. */
- return 0;
-}
-
-/***************************************************************************
- create a child process to handle DNS lookups
- ****************************************************************************/
-void start_async_dns(void)
-{
- int fd1[2], fd2[2];
-
- signal(SIGCLD, SIG_IGN);
-
- if (pipe(fd1) || pipe(fd2)) {
- return;
- }
-
- child_pid = fork();
-
- if (child_pid) {
- fd_in = fd1[0];
- fd_out = fd2[1];
- close(fd1[1]);
- close(fd2[0]);
- return;
- }
-
- fd_in = fd2[0];
- fd_out = fd1[1];
-
- signal(SIGUSR2, SIG_IGN);
- signal(SIGUSR1, SIG_IGN);
- signal(SIGHUP, SIG_IGN);
- signal( SIGTERM, SIGNAL_CAST sig_term );
-
- asyncdns_process();
-}
-
-
-/***************************************************************************
-check if a particular name is already being queried
- ****************************************************************************/
-static BOOL query_current(struct query_record *r)
-{
- return dns_current &&
- nmb_name_equal(&r->name,
- &dns_current->packet.nmb.question.question_name);
-}
-
-
-/***************************************************************************
- write a query to the child process
- ****************************************************************************/
-static BOOL write_child(struct packet_struct *p)
-{
- struct query_record r;
-
- r.name = p->packet.nmb.question.question_name;
-
- return write_data(fd_out, (char *)&r, sizeof(r)) == sizeof(r);
-}
-
-/***************************************************************************
- check the DNS queue
- ****************************************************************************/
-void run_dns_queue(void)
-{
- struct query_record r;
- struct packet_struct *p, *p2;
- struct name_record *namerec;
- int size;
-
- if (fd_in == -1)
- return;
-
- if (!process_exists(child_pid)) {
- close(fd_in);
- start_async_dns();
- }
-
- if ((size=read_data(fd_in, (char *)&r, sizeof(r))) != sizeof(r)) {
- if (size) {
- DEBUG(0,("Incomplete DNS answer from child!\n"));
- fd_in = -1;
- }
- return;
- }
-
- namerec = add_dns_result(&r.name, r.result);
-
- if (dns_current) {
- if (query_current(&r)) {
- DEBUG(3,("DNS calling send_wins_name_query_response\n"));
- in_dns = 1;
- if(namerec == NULL)
- send_wins_name_query_response(NAM_ERR, dns_current, NULL);
- else
- send_wins_name_query_response(0,dns_current,namerec);
- in_dns = 0;
- }
-
- dns_current->locked = False;
- free_packet(dns_current);
- dns_current = NULL;
- }
-
- /* loop over the whole dns queue looking for entries that
- match the result we just got */
- for (p = dns_queue; p;) {
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
-
- if (nmb_name_equal(question, &r.name)) {
- DEBUG(3,("DNS calling send_wins_name_query_response\n"));
- in_dns = 1;
- if(namerec == NULL)
- send_wins_name_query_response(NAM_ERR, p, NULL);
- else
- send_wins_name_query_response(0,p,namerec);
- in_dns = 0;
- p->locked = False;
-
- if (p->prev)
- p->prev->next = p->next;
- else
- dns_queue = p->next;
- if (p->next)
- p->next->prev = p->prev;
- p2 = p->next;
- free_packet(p);
- p = p2;
- } else {
- p = p->next;
- }
- }
-
- if (dns_queue) {
- dns_current = dns_queue;
- dns_queue = dns_queue->next;
- if (dns_queue) dns_queue->prev = NULL;
- dns_current->next = NULL;
-
- if (!write_child(dns_current)) {
- DEBUG(3,("failed to send DNS query to child!\n"));
- return;
- }
- }
-
-}
-
-/***************************************************************************
-queue a DNS query
- ****************************************************************************/
-BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
- struct name_record **n)
-{
- if (in_dns || fd_in == -1)
- return False;
-
- if (!dns_current) {
- if (!write_child(p)) {
- DEBUG(3,("failed to send DNS query to child!\n"));
- return False;
- }
- dns_current = p;
- p->locked = True;
- } else {
- p->locked = True;
- p->next = dns_queue;
- p->prev = NULL;
- if (p->next)
- p->next->prev = p;
- dns_queue = p;
- }
-
- DEBUG(3,("added DNS query for %s\n", namestr(question)));
- return True;
-}
-
-#else
-
-
-/***************************************************************************
- we use this then we can't do async DNS lookups
- ****************************************************************************/
-BOOL queue_dns_query(struct packet_struct *p,struct nmb_name *question,
- struct name_record **n)
-{
- char *qname = question->name;
- struct in_addr dns_ip;
-
- DEBUG(3,("DNS search for %s - ", namestr(question)));
-
- dns_ip.s_addr = interpret_addr(qname);
-
- *n = add_dns_result(question, dns_ip);
- if(*n == NULL)
- send_wins_name_query_response(NAM_ERR, p, NULL);
- else
- send_wins_name_query_response(0, p, *n);
- return False;
-}
-#endif
diff --git a/source/nmbd/nmbd.c b/source/nmbd/nmbd.c
index 86f01d8e795..b9f08b17615 100644
--- a/source/nmbd/nmbd.c
+++ b/source/nmbd/nmbd.c
@@ -34,9 +34,8 @@ pstring servicesf = CONFIGFILE;
extern pstring scope;
-int ClientNMB = -1;
-int ClientDGRAM = -1;
-int global_nmb_port = -1;
+int ClientNMB = -1;
+int ClientDGRAM = -1;
extern pstring myhostname;
static pstring host_file;
@@ -47,52 +46,49 @@ extern char **my_netbios_names;
/* are we running as a daemon ? */
static BOOL is_daemon = False;
-/* have we found LanMan clients yet? */
-BOOL found_lm_clients = False;
-
/* what server type are we currently */
-time_t StartupTime = 0;
+time_t StartupTime =0;
extern struct in_addr ipzero;
-/**************************************************************************** **
+ /****************************************************************************
catch a sigterm
- **************************************************************************** */
+ ****************************************************************************/
static int sig_term()
{
BlockSignals(True,SIGTERM);
DEBUG(0,("Got SIGTERM: going down...\n"));
- /* Write out wins.dat file if samba is a WINS server */
- wins_write_database();
+ /* write out wins.dat file if samba is a WINS server */
+ dump_names();
- /* Remove all SELF registered names. */
- release_my_names();
+ /* remove all samba names, with wins server if necessary. */
+ remove_my_names();
- /* Announce all server entries as 0 time-to-live, 0 type. */
+ /* announce all server entries as 0 time-to-live, 0 type */
+ /* XXXX don't care if we never receive a response back... yet */
announce_my_servers_removed();
+ /* XXXX other things: if we are a master browser, force an election? */
+
exit(0);
/* Keep compiler happy.. */
return 0;
-} /* sig_term */
+}
-/**************************************************************************** **
- catch a sighup
- **************************************************************************** */
+/****************************************************************************
+catch a sighup
+****************************************************************************/
static int sig_hup(void)
{
- BlockSignals( True, SIGHUP );
-
- DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) );
+ BlockSignals(True,SIGHUP);
- write_browse_list( 0, True );
-
- dump_all_namelists();
- reload_services( True );
+ DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
+ dump_names();
+ reload_services(True);
set_samba_nb_type();
@@ -101,333 +97,271 @@ static int sig_hup(void)
signal(SIGHUP,SIGNAL_CAST sig_hup);
#endif
return(0);
-} /* sig_hup */
+}
-/**************************************************************************** **
- catch a sigpipe
- **************************************************************************** */
+/****************************************************************************
+catch a sigpipe
+****************************************************************************/
static int sig_pipe(void)
{
- BlockSignals( True, SIGPIPE );
+ BlockSignals(True,SIGPIPE);
- DEBUG( 0, ("Got SIGPIPE\n") );
- if ( !is_daemon )
+ DEBUG(0,("Got SIGPIPE\n"));
+ if (!is_daemon)
exit(1);
- BlockSignals( False, SIGPIPE );
+ BlockSignals(False,SIGPIPE);
return(0);
-} /* sig_pipe */
+}
#if DUMP_CORE
-/**************************************************************************** **
- prepare to dump a core file - carefully!
- **************************************************************************** */
+/*******************************************************************
+prepare to dump a core file - carefully!
+********************************************************************/
static BOOL dump_core(void)
{
char *p;
pstring dname;
- pstrcpy( dname, debugf );
- if ((p=strrchr(dname,'/')))
- *p=0;
- strcat( dname, "/corefiles" );
- mkdir( dname, 0700 );
- sys_chown( dname, getuid(), getgid() );
- chmod( dname, 0700 );
- if ( chdir(dname) )
- return( False );
- umask( ~(0700) );
+ pstrcpy(dname,debugf);
+ if ((p=strrchr(dname,'/'))) *p=0;
+ strcat(dname,"/corefiles");
+ mkdir(dname,0700);
+ sys_chown(dname,getuid(),getgid());
+ chmod(dname,0700);
+ if (chdir(dname)) return(False);
+ umask(~(0700));
#ifndef NO_GETRLIMIT
#ifdef RLIMIT_CORE
{
struct rlimit rlp;
- getrlimit( RLIMIT_CORE, &rlp );
- rlp.rlim_cur = MAX( 4*1024*1024, rlp.rlim_cur );
- setrlimit( RLIMIT_CORE, &rlp );
- getrlimit( RLIMIT_CORE, &rlp );
- DEBUG( 3, ( "Core limits now %d %d\n", rlp.rlim_cur, rlp.rlim_max ) );
+ getrlimit(RLIMIT_CORE, &rlp);
+ rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
+ setrlimit(RLIMIT_CORE, &rlp);
+ getrlimit(RLIMIT_CORE, &rlp);
+ DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
}
#endif
#endif
- DEBUG( 0, ( "Dumping core in %s\n",dname ) );
- return( True );
-} /* dump_core */
+ DEBUG(0,("Dumping core in %s\n",dname));
+ return(True);
+}
#endif
-/**************************************************************************** **
- possibly continue after a fault
- **************************************************************************** */
+/****************************************************************************
+possibly continue after a fault
+****************************************************************************/
static void fault_continue(void)
{
#if DUMP_CORE
dump_core();
#endif
-} /* fault_continue */
+}
-/**************************************************************************** **
- expire old names from the namelist and server list
- **************************************************************************** */
+/*******************************************************************
+ expire old names from the namelist and server list
+ ******************************************************************/
static void expire_names_and_servers(time_t t)
{
static time_t lastrun = 0;
- if ( !lastrun )
- lastrun = t;
- if ( t < (lastrun + 5) )
- return;
+ if (!lastrun) lastrun = t;
+ if (t < lastrun + 5) return;
lastrun = t;
-
- /*
- * Expire any timed out names on all the broadcast
- * subnets and those registered with the WINS server.
- * (nmbd_namelistdb.c)
- */
+
expire_names(t);
+ expire_servers(t);
+}
- /*
- * Go through all the broadcast subnets and for each
- * workgroup known on that subnet remove any expired
- * server names. If a workgroup has an empty serverlist
- * and has itself timed out then remove the workgroup.
- * (nmbd_workgroupdb.c)
- */
- expire_workgroups_and_servers(t);
-} /* expire_names_and_servers */
-
-/**************************************************************************** **
+/*****************************************************************************
reload the services file
- **************************************************************************** */
+ **************************************************************************/
BOOL reload_services(BOOL test)
{
BOOL ret;
extern fstring remote_machine;
- strcpy( remote_machine, "nmbd" );
+ strcpy(remote_machine,"nmbd");
- if ( lp_loaded() )
- {
- pstring fname;
- pstrcpy( fname,lp_configfile());
- if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
+ if (lp_loaded())
{
- pstrcpy(servicesf,fname);
- test = False;
+ pstring fname;
+ pstrcpy(fname,lp_configfile());
+ if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
+ {
+ pstrcpy(servicesf,fname);
+ test = False;
+ }
}
- }
- if ( test && !lp_file_list_changed() )
+ if (test && !lp_file_list_changed())
return(True);
- ret = lp_load( servicesf, True );
+ ret = lp_load(servicesf,True);
/* perhaps the config filename is now set */
- if ( !test )
- {
- DEBUG( 3, ( "services not loaded\n" ) );
- reload_services( True );
+ if (!test) {
+ DEBUG(3,("services not loaded\n"));
+ reload_services(True);
}
/* Do a sanity check for a misconfigured nmbd */
- if( lp_wins_support() && *lp_wins_server() )
- {
+ if(lp_wins_support() && *lp_wins_server()) {
DEBUG(0,("ERROR: both 'wins support = true' and 'wins server = <server>' \
cannot be set in the smb.conf file. nmbd aborting.\n"));
exit(10);
}
return(ret);
-} /* reload_services */
+}
+
+
+
+/****************************************************************************
+load a netbios hosts file
+****************************************************************************/
+static void load_hosts_file(char *fname)
+{
+ FILE *f = fopen(fname,"r");
+ pstring line;
+ if (!f) {
+ DEBUG(2,("Can't open lmhosts file %s\n",fname));
+ return;
+ }
+
+ while (!feof(f))
+ {
+ pstring ip,name,flags,extra;
+ struct subnet_record *d;
+ char *ptr;
+ int count = 0;
+ struct in_addr ipaddr;
+ enum name_source source = LMHOSTS;
+
+ if (!fgets_slash(line,sizeof(pstring),f)) continue;
+
+ if (*line == '#') continue;
+
+ strcpy(ip,"");
+ strcpy(name,"");
+ strcpy(flags,"");
+
+ ptr = line;
+
+ if (next_token(&ptr,ip ,NULL)) ++count;
+ if (next_token(&ptr,name ,NULL)) ++count;
+ if (next_token(&ptr,flags,NULL)) ++count;
+ if (next_token(&ptr,extra,NULL)) ++count;
+
+ if (count <= 0) continue;
+
+ if (count > 0 && count < 2) {
+ DEBUG(0,("Ill formed hosts line [%s]\n",line));
+ continue;
+ }
+
+ if (count >= 4) {
+ DEBUG(0,("too many columns in %s (obsolete syntax)\n",fname));
+ continue;
+ }
+
+ DEBUG(4, ("lmhost entry: %s %s %s\n", ip, name, flags));
+
+ if (strchr(flags,'G') || strchr(flags,'S')) {
+ DEBUG(0,("group flag in %s ignored (obsolete)\n",fname));
+ continue;
+ }
+
+ if (strchr(flags,'M')) {
+ source = SELF;
+ pstrcpy(myname,name);
+ }
+
+ ipaddr = *interpret_addr2(ip);
+ d = find_subnet_all(ipaddr);
+ if (d) {
+ add_netbios_entry(d,name,0x00,NB_ACTIVE,0,source,ipaddr,True,True);
+ add_netbios_entry(d,name,0x20,NB_ACTIVE,0,source,ipaddr,True,True);
+ }
+ }
+
+ fclose(f);
+}
+
-/**************************************************************************** **
- The main select loop.
- **************************************************************************** */
+/****************************************************************************
+ The main select loop.
+ ***************************************************************************/
static void process(void)
{
BOOL run_election;
- while( True )
- {
- time_t t = time(NULL);
-
- /*
- * Check all broadcast subnets to see if
- * we need to run an election on any of them.
- * (nmbd_elections.c)
- */
- run_election = check_elections();
-
- /*
- * Read incoming UDP packets.
- * (nmbd_packets.c)
- */
- if(listen_for_packets(run_election))
- return;
-
- /*
- * Process all incoming packets
- * read above. This calls the success and
- * failure functions registered when response
- * packets arrrive, and also deals with request
- * packets from other sources.
- * (nmbd_packets.c)
- */
- run_packet_queue();
-
- /*
- * Run any elections - initiate becoming
- * a local master browser if we have won.
- * (nmbd_elections.c)
- */
- run_elections(t);
-
- /*
- * Send out any broadcast announcements
- * of our server names. This also announces
- * the workgroup name if we are a local
- * master browser.
- * (nmbd_sendannounce.c)
- */
- announce_my_server_names(t);
-
- /*
- * Send out any LanMan broadcast announcements
- * of our server names.
- * (nmbd_sendannounce.c)
- */
- announce_my_lm_server_names(t);
-
- /*
- * If we are a local master browser, periodically
- * announce ourselves to the domain master browser.
- * This also deals with syncronising the domain master
- * browser server lists with ourselves as a local
- * master browser.
- * (nmbd_sendannounce.c)
- */
- announce_myself_to_domain_master_browser(t);
-
- /*
- * Fullfill any remote announce requests.
- * (nmbd_sendannounce.c)
- */
- announce_remote(t);
-
- /*
- * Fullfill any remote browse sync announce requests.
- * (nmbd_sendannounce.c)
- */
- browse_sync_remote(t);
-
- /*
- * Scan the broadcast subnets, and WINS client
- * namelists and refresh any that need refreshing.
- * (nmbd_mynames.c)
- */
- refresh_my_names(t);
-
- /*
- * Scan the subnet namelists and server lists and
- * expire thos that have timed out.
- * (nmbd.c)
- */
- expire_names_and_servers(t);
-
- /*
- * Write out a snapshot of our current browse list into
- * the browse.dat file. This is used by smbd to service
- * incoming NetServerEnum calls - used to synchronise
- * browse lists over subnets.
- * (nmbd_serverlistdb.c)
- */
- write_browse_list(t, False);
-
- /*
- * If we are a domain master browser, we have a list of
- * local master browsers we should synchronise browse
- * lists with (these are added by an incoming local
- * master browser announcement packet). Expire any of
- * these that are no longer current, and pull the server
- * lists from each of these known local master browsers.
- * (nmbd_browsesync.c)
- */
- dmb_expire_and_sync_browser_lists(t);
-
- /*
- * Check that there is a local master browser for our
- * workgroup for all our broadcast subnets. If one
- * is not found, start an election (which we ourselves
- * may or may not participate in, depending on the
- * setting of the 'local master' parameter.
- * (nmbd_elections.c)
- */
- check_master_browser_exists(t);
-
- /*
- * If we are configured as a logon server, attempt to
- * register the special NetBIOS names to become such
- * (WORKGROUP<1c> name) on all broadcast subnets and
- * with the WINS server (if used). If we are configured
- * to become a domain master browser, attempt to register
- * the special NetBIOS name (WORKGROUP<1b> name) to
- * become such.
- * (nmbd_become_dmb.c)
- */
- add_domain_names(t);
-
- /*
- * If we are a WINS server, do any timer dependent
- * processing required.
- * (nmbd_winsserver.c)
- */
- initiate_wins_processing(t);
-
- /*
- * Go through the repsonse record queue and time out or re-transmit
- * and expired entries.
- * (nmbd_packets.c)
- */
- retransmit_or_expire_response_records(t);
- }
-} /* process */
+ while (True)
+ {
+ time_t t = time(NULL);
+ run_election = check_elections();
+ listen_for_packets(run_election);
+
+ run_packet_queue();
+ run_elections(t);
+
+ announce_host(t);
+ announce_master(t);
+ announce_remote(t);
+ browse_sync_remote(t);
+
+ query_refresh_names(t);
+ expire_names_and_servers(t);
+ expire_netbios_response_entries(t);
+ refresh_my_names(t);
-/**************************************************************************** **
- open the socket communication
- **************************************************************************** */
+ write_browse_list(t);
+ do_browser_lists(t);
+ check_master_browser(t);
+ add_domain_names(t);
+ }
+}
+
+
+/****************************************************************************
+ open the socket communication
+****************************************************************************/
static BOOL open_sockets(BOOL isdaemon, int port)
{
- /* The sockets opened here will be used to receive broadcast
- packets *only*. Interface specific sockets are opened in
- make_subnet() in namedbsubnet.c. Thus we bind to the
- address "0.0.0.0". The parameter 'socket address' is
- now deprecated.
- */
-
- if ( isdaemon )
- ClientNMB = open_socket_in(SOCK_DGRAM, port,0,0);
+ struct hostent *hp;
+
+ /* get host info */
+ if ((hp = Get_Hostbyname(myhostname)) == 0) {
+ DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",myhostname));
+ return False;
+ }
+
+ if (isdaemon)
+ ClientNMB = open_socket_in(SOCK_DGRAM, port,0,interpret_addr(lp_socket_address()));
else
ClientNMB = 0;
- ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,0);
+ ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3,interpret_addr(lp_socket_address()));
- if ( ClientNMB == -1 )
- return( False );
+ if (ClientNMB == -1)
+ return(False);
- signal( SIGPIPE, SIGNAL_CAST sig_pipe );
+ signal(SIGPIPE, SIGNAL_CAST sig_pipe);
- set_socket_options( ClientNMB, "SO_BROADCAST" );
- set_socket_options( ClientDGRAM, "SO_BROADCAST" );
+ set_socket_options(ClientNMB,"SO_BROADCAST");
+ set_socket_options(ClientDGRAM,"SO_BROADCAST");
- DEBUG( 3, ( "open_sockets: Broadcast sockets opened.\n" ) );
- return( True );
-} /* open_sockets */
+ DEBUG(3,("Sockets opened.\n"));
+ return True;
+}
-/**************************************************************************** **
- initialise connect, service and file structs
- **************************************************************************** */
+/****************************************************************************
+ initialise connect, service and file structs
+****************************************************************************/
static BOOL init_structs()
{
extern fstring local_machine;
@@ -437,325 +371,278 @@ static BOOL init_structs()
int nodup;
pstring nbname;
- if (! *myname)
- {
- fstrcpy( myname, myhostname );
- p = strchr( myname, '.' );
- if (p)
- *p = 0;
+ if (! *myname) {
+ fstrcpy(myname,myhostname);
+ p = strchr(myname,'.');
+ if (p) *p = 0;
}
- strupper( myname );
+ strupper(myname);
/* Add any NETBIOS name aliases. Ensure that the first entry
- is equal to myname.
- */
+ is equal to myname. */
/* Work out the max number of netbios aliases that we have */
- ptr = lp_netbios_aliases();
- for( namecount=0; next_token(&ptr,nbname,NULL); namecount++ )
+ ptr=lp_netbios_aliases();
+ for (namecount=0; next_token(&ptr,nbname,NULL); namecount++)
;
- if ( *myname )
- namecount++;
+ if (*myname)
+ namecount++;
/* Allocate space for the netbios aliases */
- my_netbios_names = (char **)malloc( sizeof(char *) * (namecount+1) );
- if( NULL == my_netbios_names )
+ if((my_netbios_names=(char **)malloc(sizeof(char *)*(namecount+1))) == NULL)
{
- DEBUG( 0, ( "init_structs: malloc fail.\n" ) );
- return( False );
+ DEBUG(0,("init_structs: malloc fail.\n"));
+ return False;
}
/* Use the myname string first */
namecount=0;
- if ( *myname )
+ if (*myname)
my_netbios_names[namecount++] = myname;
- ptr = lp_netbios_aliases();
- while ( next_token( &ptr, nbname, NULL ) )
- {
- strupper( nbname );
+ ptr=lp_netbios_aliases();
+ while (next_token(&ptr,nbname,NULL)) {
+ strupper(nbname);
/* Look for duplicates */
nodup=1;
- for( n=0; n<namecount; n++ )
- {
- if( 0 == strcmp( nbname, my_netbios_names[n] ) )
+ for(n=0; n<namecount; n++) {
+ if (strcmp(nbname, my_netbios_names[n])==0)
nodup=0;
}
if (nodup)
- my_netbios_names[namecount++] = strdup( nbname );
+ my_netbios_names[namecount++]=strdup(nbname);
}
/* Check the strdups succeeded. */
- for( n = 0; n < namecount; n++ )
- if( NULL == my_netbios_names[n] )
+ for(n = 0; n < namecount; n++)
+ if(my_netbios_names[n]==NULL)
{
DEBUG(0,("init_structs: malloc fail when allocating names.\n"));
return False;
}
/* Terminate name list */
- my_netbios_names[namecount++] = NULL;
+ my_netbios_names[namecount++]=NULL;
- fstrcpy( local_machine, myname );
- trim_string( local_machine, " ", " " );
- p = strchr( local_machine, ' ' );
- if (p)
+ fstrcpy(local_machine,myname);
+ trim_string(local_machine," "," ");
+ p = strchr(local_machine,' ');
+ if (p)
*p = 0;
- strlower( local_machine );
+ strlower(local_machine);
- DEBUG( 5, ("Netbios name list:-\n") );
- for( n=0; my_netbios_names[n]; n++ )
- DEBUG( 5, ( "my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n] ) );
+ DEBUG(5, ("Netbios name list:-\n"));
+ for (n=0; my_netbios_names[n]; n++)
+ DEBUG(5, ("my_netbios_names[%d]=\"%s\"\n", n, my_netbios_names[n]));
- return( True );
-} /* init_structs */
+ return True;
+}
-/**************************************************************************** **
- usage on the program
- **************************************************************************** */
+/****************************************************************************
+usage on the program
+****************************************************************************/
static void usage(char *pname)
{
DEBUG(0,("Incorrect program usage - is the command line correct?\n"));
- printf( "Usage: %s [-n name] [-D] [-p port] [-d debuglevel] ", pname );
- printf( "[-l log basename]\n" );
- printf( "Version %s\n", VERSION );
- printf( "\t-D become a daemon\n" );
- printf( "\t-p port listen on the specified port\n" );
- printf( "\t-d debuglevel set the debuglevel\n" );
- printf( "\t-l log basename. Basename for log/debug files\n" );
- printf( "\t-n netbiosname. " );
- printf( "the netbios name to advertise for this host\n");
- printf( "\t-H hosts file load a netbios hosts file\n" );
- printf( "\n");
-} /* usage */
-
-
-/**************************************************************************** **
- main program
- **************************************************************************** */
-int main(int argc,char *argv[])
+ printf("Usage: %s [-n name] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname);
+ printf("Version %s\n",VERSION);
+ printf("\t-D become a daemon\n");
+ printf("\t-p port listen on the specified port\n");
+ printf("\t-d debuglevel set the debuglevel\n");
+ printf("\t-l log basename. Basename for log/debug files\n");
+ printf("\t-n netbiosname. the netbios name to advertise for this host\n");
+ printf("\t-H hosts file load a netbios hosts file\n");
+ printf("\n");
+}
+
+
+/****************************************************************************
+ main program
+ **************************************************************************/
+ int main(int argc,char *argv[])
{
+ int port = NMB_PORT;
int opt;
extern FILE *dbf;
extern char *optarg;
char pidFile[100] = { 0 };
- global_nmb_port = NMB_PORT;
*host_file = 0;
StartupTime = time(NULL);
TimeInit();
- strcpy( debugf, NMBLOGFILE );
+ strcpy(debugf,NMBLOGFILE);
- setup_logging( argv[0], False );
+ setup_logging(argv[0],False);
charset_initialise();
#ifdef LMHOSTSFILE
- strcpy( host_file, LMHOSTSFILE );
+ strcpy(host_file,LMHOSTSFILE);
#endif
/* this is for people who can't start the program correctly */
- while (argc > 1 && (*argv[1] != '-'))
- {
+ while (argc > 1 && (*argv[1] != '-')) {
argv++;
argc--;
}
- fault_setup( fault_continue );
+ fault_setup(fault_continue);
- signal( SIGHUP, SIGNAL_CAST sig_hup );
- signal( SIGTERM, SIGNAL_CAST sig_term );
+ signal(SIGHUP ,SIGNAL_CAST sig_hup);
+ signal(SIGTERM,SIGNAL_CAST sig_term);
- while((opt = getopt(argc, argv, "as:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:")) != EOF)
+ while ((opt = getopt(argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:f:")) != EOF)
{
switch (opt)
- {
+ {
case 'f':
strncpy(pidFile, optarg, sizeof(pidFile));
break;
- case 's':
- pstrcpy(servicesf,optarg);
- break;
- case 'N':
- case 'B':
- case 'I':
- case 'C':
- case 'G':
- DEBUG(0,("Obsolete option '%c' used\n",opt));
- break;
- case 'H':
- pstrcpy(host_file,optarg);
- break;
- case 'n':
- pstrcpy(myname,optarg);
- strupper(myname);
- break;
- case 'l':
- sprintf(debugf,"%s.nmb",optarg);
- break;
- case 'i':
- pstrcpy(scope,optarg);
- strupper(scope);
- break;
- case 'a':
- {
- extern BOOL append_log;
- append_log = !append_log;
- }
- break;
- case 'D':
- is_daemon = True;
- break;
- case 'd':
- DEBUGLEVEL = atoi(optarg);
- break;
- case 'p':
- global_nmb_port = atoi(optarg);
- break;
- case 'h':
- usage(argv[0]);
- exit(0);
- break;
- default:
- if (!is_a_socket(0))
- {
- usage(argv[0]);
- }
- break;
- }
+ case 's':
+ pstrcpy(servicesf,optarg);
+ break;
+ case 'N':
+ case 'B':
+ case 'I':
+ case 'C':
+ case 'G':
+ DEBUG(0,("Obsolete option '%c' used\n",opt));
+ break;
+ case 'H':
+ pstrcpy(host_file,optarg);
+ break;
+ case 'n':
+ pstrcpy(myname,optarg);
+ strupper(myname);
+ break;
+ case 'l':
+ sprintf(debugf,"%s.nmb",optarg);
+ break;
+ case 'i':
+ pstrcpy(scope,optarg);
+ strupper(scope);
+ break;
+ case 'D':
+ is_daemon = True;
+ break;
+ case 'd':
+ DEBUGLEVEL = atoi(optarg);
+ break;
+ case 'p':
+ port = atoi(optarg);
+ break;
+ case 'h':
+ usage(argv[0]);
+ exit(0);
+ break;
+ default:
+ if (!is_a_socket(0)) {
+ usage(argv[0]);
+ }
+ break;
+ }
}
DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
DEBUG(1,("Copyright Andrew Tridgell 1994-1997\n"));
- if( !get_myname( myhostname, NULL) )
+ if(!get_myname(myhostname,NULL))
{
DEBUG(0,("Unable to get my hostname - exiting.\n"));
return -1;
}
- if ( !reload_services(False) )
- return(-1);
+ if (!reload_services(False))
+ return(-1);
codepage_initialise(lp_client_code_page());
if(!init_structs())
return -1;
- reload_services( True );
+ reload_services(True);
- fstrcpy( myworkgroup, lp_workgroup() );
+ pstrcpy(myworkgroup, lp_workgroup());
- if (strequal(myworkgroup,"*"))
- {
+ if (strequal(myworkgroup,"*")) {
DEBUG(0,("ERROR: a workgroup name of * is no longer supported\n"));
exit(1);
}
set_samba_nb_type();
- if (!is_daemon && !is_a_socket(0))
- {
+ if (!is_daemon && !is_a_socket(0)) {
DEBUG(0,("standard input is not a socket, assuming -D option\n"));
is_daemon = True;
}
- if (is_daemon)
- {
+ if (is_daemon) {
DEBUG(2,("%s becoming a daemon\n",timestring()));
become_daemon();
}
- if (!directory_exist(lp_lockdir(), NULL))
- {
- mkdir(lp_lockdir(), 0755);
- }
-
if (*pidFile)
- {
- int fd;
- char buf[20];
+ {
+ int fd;
+ char buf[20];
+ if ((fd = open(pidFile,
#ifdef O_NONBLOCK
- fd = open( pidFile, O_NONBLOCK | O_CREAT | O_WRONLY | O_TRUNC, 0644 );
-#else
- fd = open( pidFile, O_CREAT | O_WRONLY | O_TRUNC, 0644 );
+ O_NONBLOCK |
#endif
- if ( fd < 0 )
- {
- DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
- exit(1);
- }
- if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
- {
- DEBUG(0,("ERROR: nmbd is already running\n"));
- exit(1);
- }
- sprintf(buf, "%u\n", (unsigned int) getpid());
- if (write(fd, buf, strlen(buf)) < 0)
- {
- DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
- exit(1);
- }
+ O_CREAT | O_WRONLY | O_TRUNC, 0644)) < 0)
+ {
+ DEBUG(0,("ERROR: can't open %s: %s\n", pidFile, strerror(errno)));
+ exit(1);
+ }
+ if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)==False)
+ {
+ DEBUG(0,("ERROR: nmbd is already running\n"));
+ exit(1);
+ }
+ sprintf(buf, "%u\n", (unsigned int) getpid());
+ if (write(fd, buf, strlen(buf)) < 0)
+ {
+ DEBUG(0,("ERROR: can't write to %s: %s\n", pidFile, strerror(errno)));
+ exit(1);
+ }
/* Leave pid file open & locked for the duration... */
- }
+ }
- DEBUG( 3, ( "Opening sockets %d\n", global_nmb_port ) );
+ DEBUG(3,("Opening sockets %d\n", port));
- if ( !open_sockets( is_daemon, global_nmb_port ) )
- return 1;
+ if (!open_sockets(is_daemon,port)) return 1;
- /* Determine all the IP addresses we have. */
load_interfaces();
+ add_my_subnets(myworkgroup);
- /* Create an nmbd subnet record for each of the above. */
- if( False == create_subnets() )
- {
- DEBUG(0,("ERROR: Failed when creating subnet lists. Exiting.\n"));
- exit(1);
- }
+ add_my_names();
- /* Load in any static local names. */
- if ( *host_file )
- {
- load_lmhosts_file(host_file);
- DEBUG(3,("Loaded hosts file\n"));
- }
+ DEBUG(3,("Checked names\n"));
+
+ load_netbios_names();
- /* If we are acting as a WINS server, initialise data structures. */
- if( !initialise_wins() )
- {
- DEBUG( 0, ( "nmbd: Failed when initialising WINS server.\n" ) );
- exit(1);
+ DEBUG(3,("Loaded names\n"));
+
+ if (*host_file) {
+ load_hosts_file(host_file);
+ DEBUG(3,("Loaded hosts file\n"));
}
- /*
- * Register nmbd primary workgroup and nmbd names on all
- * the broadcast subnets, and on the WINS server (if specified).
- * Also initiate the startup of our primary workgroup (start
- * elections if we are setup as being able to be a local
- * master browser.
- */
+ write_browse_list(time(NULL));
- if( False == register_my_workgroup_and_names() )
- {
- DEBUG(0,("ERROR: Failed when creating my my workgroup. Exiting.\n"));
- exit(1);
- }
+ DEBUG(3,("Dumped names\n"));
/* We can only take sigterm signals in the select. */
- BlockSignals( True, SIGTERM );
-
+ BlockSignals(True,SIGTERM);
process();
close_sockets();
if (dbf)
fclose(dbf);
return(0);
-} /* main */
-
-/* ========================================================================== */
+}
diff --git a/source/nmbd/nmbd_become_dmb.c b/source/nmbd/nmbd_become_dmb.c
deleted file mode 100644
index 37fceb9bf1e..00000000000
--- a/source/nmbd/nmbd_become_dmb.c
+++ /dev/null
@@ -1,471 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-extern pstring scope;
-extern pstring myname;
-extern fstring myworkgroup;
-extern char **my_netbios_names;
-extern struct in_addr ipzero;
-extern struct in_addr allones_ip;
-
-extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
-
-static void become_domain_master_browser_bcast(char *);
-
-/*******************************************************************
- Unbecome a domain master browser - name release success function.
- ******************************************************************/
-
-static void unbecome_dmb_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *released_name,
- struct in_addr released_ip)
-{
- struct work_record *work = find_workgroup_on_subnet(subrec, released_name->name);
- struct server_record *servrec;
-
- if(!work)
- {
- DEBUG(0,("unbecome_dmb_success: Cannot find workgroup %s on subnet %s\n",
- released_name->name, subrec->subnet_name));
- return;
- }
-
- if((servrec = find_server_in_workgroup( work, myname)) == NULL)
- {
- DEBUG(0,("unbecome_dmb_success: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- myname, released_name->name, subrec->subnet_name));
- return;
- }
-
- /* Set the state in the workgroup structure. */
- work->dom_state = DOMAIN_NONE;
-
- /* Update our server status. */
- servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
-
- /* Tell the namelist writer to write out a change. */
- subrec->work_changed = True;
-
- /* Remove any list of local master browsers we are syncing with. */
- remove_workgroup_lmb_browsers(released_name->name);
-
- /* Delete the known domain master browser name from the workgroup
- struct. */
- bzero((char *)&work->dmb_name, sizeof(work->dmb_name));
- putip((char *)&work->dmb_addr, &ipzero);
-
- DEBUG(0,("\n ***** Samba server %s has stopped being a domain master browser \
-for workgroup %s on subnet %s *****\n\n", myname, work->work_group, subrec->subnet_name));
-
-}
-
-/*******************************************************************
- Unbecome a domain master browser - name release fail function.
- ******************************************************************/
-
-static void unbecome_dmb_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *released_name)
-{
- DEBUG(0,("unbecome_dmb_fail: Failed to unbecome domain master browser for \
-workgroup %s on subnet %s.\n", released_name->name, subrec->subnet_name));
-}
-
-/*******************************************************************
- Unbecome a domain master browser.
- ******************************************************************/
-
-void unbecome_domain_master(char *workgroup_name)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
-
- if(work && (work->dom_state == DOMAIN_MST))
- {
- struct name_record *namerec;
- struct nmb_name nmbname;
- make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
-
- /* We can only do this if we are a domain master already. */
- DEBUG(2,("unbecome_domain_master: attempting to stop being a domain \
-master browser for workgroup %s on subnet %s\n",
- work->work_group, subrec->subnet_name));
-
- /* Find the WORKGROUP<1b> name on the subnet namelist. */
- if((namerec = find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME))==NULL)
- {
- DEBUG(0,("unbecome_domain_master: Cannot find name %s on subnet %s.\n",
- namestr(&nmbname), subrec->subnet_name));
- continue;
- }
- release_name(subrec, namerec,
- unbecome_dmb_success,
- unbecome_dmb_fail,
- NULL);
- }
- }
-}
-
-/****************************************************************************
- Fail to become a Domain Master Browser on a subnet.
- ****************************************************************************/
-
-static void become_domain_master_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *fail_name)
-{
- struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
- struct server_record *servrec;
-
- if(!work)
- {
- DEBUG(0,("become_domain_master_fail: Error - cannot find \
-workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
- return;
- }
-
- /* Set the state back to DOMAIN_NONE. */
- work->dom_state = DOMAIN_NONE;
-
- if((servrec = find_server_in_workgroup( work, myname)) == NULL)
- {
- DEBUG(0,("become_domain_master_fail: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- myname, work->work_group, subrec->subnet_name));
- return;
- }
-
- /* Update our server status. */
- servrec->serv.type &= ~SV_TYPE_DOMAIN_MASTER;
-
- /* Tell the namelist writer to write out a change. */
- subrec->work_changed = True;
-
- DEBUG(0,("become_domain_master_fail: Failed to become a domain master browser for \
-workgroup %s on subnet %s. Couldn't register name %s.\n",
- work->work_group, subrec->subnet_name, namestr(fail_name)));
-}
-
-/****************************************************************************
- Become a Domain Master Browser on a subnet.
- ****************************************************************************/
-
-static void become_domain_master_stage2(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *registered_name,
- uint16 nb_flags,
- int ttl, struct in_addr registered_ip)
-{
- struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
- struct server_record *servrec;
-
- if(!work)
- {
- DEBUG(0,("become_domain_master_stage2: Error - cannot find \
-workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
- return;
- }
-
- if((servrec = find_server_in_workgroup( work, myname)) == NULL)
- {
- DEBUG(0,("become_domain_master_stage2: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- myname, registered_name->name, subrec->subnet_name));
- work->dom_state = DOMAIN_NONE;
- return;
- }
-
- /* Set the state in the workgroup structure. */
- work->dom_state = DOMAIN_MST; /* Become domain master. */
-
- /* Update our server status. */
- servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MASTER);
-
- /* Tell the namelist writer to write out a change. */
- subrec->work_changed = True;
-
- DEBUG(0,("\n ***** Samba server %s is now a domain master browser \
-for workgroup %s on subnet %s *****\n\n", myname, work->work_group, subrec->subnet_name));
-
- if(subrec == unicast_subnet)
- {
- struct nmb_name nmbname;
- struct in_addr my_first_ip;
-
- /* Put our name and first IP address into the
- workgroup struct as domain master browser. This
- will stop us syncing with ourself if we are also
- a local master browser. */
-
- make_nmb_name(&nmbname, myname, 0x20, scope);
-
- work->dmb_name = nmbname;
- /* Pick the first interface ip address as the domain master browser ip. */
- my_first_ip = *iface_n_ip(0);
-
- putip((char *)&work->dmb_addr, &my_first_ip);
-
- /* We successfully registered by unicast with the
- WINS server. We now expect to become the domain
- master on the local subnets. If this fails, it's
- probably a 1.9.16p2 to 1.9.16p11 server's fault.
-
- This is a configuration issue that should be addressed
- by the network administrator - you shouldn't have
- several machines configured as a domain master browser
- for the same WINS scope (except if they are 1.9.17 or
- greater, and you know what you're doing.
-
- see docs/DOMAIN.txt.
-
- */
- become_domain_master_browser_bcast(work->work_group);
- }
-}
-
-/****************************************************************************
- Start the name registration process when becoming a Domain Master Browser
- on a subnet.
- ****************************************************************************/
-
-static void become_domain_master_stage1(struct subnet_record *subrec, char *wg_name)
-{
- struct work_record *work;
-
- DEBUG(2,("become_domain_master_stage1: Becoming domain master browser for \
-workgroup %s on subnet %s\n", wg_name, subrec->subnet_name));
-
- /* First, find the workgroup on the subnet. */
- if((work = find_workgroup_on_subnet( subrec, wg_name )) == NULL)
- {
- DEBUG(0,("become_domain_master_stage1: Error - unable to find workgroup %s on subnet %s.\n",
- wg_name, subrec->subnet_name));
- return;
- }
-
- DEBUG(3,("become_domain_master_stage1: go to first stage: register <1b> name\n"));
- work->dom_state = DOMAIN_WAIT;
-
- /* WORKGROUP<1b> is the domain master browser name. */
- register_name(subrec, work->work_group,0x1b,samba_nb_type,
- become_domain_master_stage2,
- become_domain_master_fail, NULL);
-}
-
-/****************************************************************************
- Function called when a query for a WORKGROUP<1b> name succeeds.
- This is normally a fail condition as it means there is already
- a domain master browser for a workgroup and we were trying to
- become one.
-****************************************************************************/
-
-static void become_domain_master_query_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname, struct in_addr ip,
- struct res_rec *rrec)
-{
- /* If the given ip is not ours, then we can't become a domain
- controler as the name is already registered.
- */
-
- /* BUG note. Samba 1.9.16p11 servers seem to return the broadcast
- address or zero ip for this query. Pretend this is ok. */
-
- if(ismyip(ip) || ip_equal(allones_ip, ip) || ip_equal(ipzero, ip))
- {
- DEBUG(3,("become_domain_master_query_success: Our address (%s) returned \
-in query for name %s (domain master browser name) on subnet %s. \
-Continuing with domain master code.\n",
- inet_ntoa(ip), namestr(nmbname), subrec->subnet_name));
-
- become_domain_master_stage1(subrec, nmbname->name);
- }
- else
- {
- DEBUG(0,("become_domain_master_query_success: There is already a domain \
-master browser at IP %s for workgroup %s registered on subnet %s.\n",
- inet_ntoa(ip), nmbname->name, subrec->subnet_name));
- }
-}
-
-/****************************************************************************
- Function called when a query for a WORKGROUP<1b> name fails.
- This is normally a success condition as it then allows us to register
- our own Domain Master Browser name.
- ****************************************************************************/
-
-static void become_domain_master_query_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *question_name, int fail_code)
-{
- /* If the query was unicast, and the error is not NAM_ERR (name didn't exist),
- then this is a failure. Otherwise, not finding the name is what we want. */
- if((subrec == unicast_subnet) && (fail_code != NAM_ERR))
- {
- DEBUG(0,("become_domain_master_query_fail: Error %d returned when \
-querying WINS server for name %s.\n",
- fail_code, namestr(question_name)));
- return;
- }
-
- /* Otherwise - not having the name allows us to register it. */
- become_domain_master_stage1(subrec, question_name->name);
-}
-
-/****************************************************************************
- Attempt to become a domain master browser on all broadcast subnets.
- ****************************************************************************/
-
-static void become_domain_master_browser_bcast(char *workgroup_name)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
-
- if (work && (work->dom_state == DOMAIN_NONE))
- {
- struct nmb_name nmbname;
- make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
-
- /*
- * Check for our name on the given broadcast subnet first, only initiate
- * further processing if we cannot find it.
- */
-
- if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
- {
- DEBUG(0,("become_domain_master_browser_bcast: At time %s attempting to become domain \
-master browser on workgroup %s on subnet %s\n", timestring(),
- workgroup_name, subrec->subnet_name));
-
- /* Send out a query to establish whether there's a
- domain controller on the local subnet. If not,
- we can become a domain controller.
- */
-
- DEBUG(0,("become_domain_master_browser_bcast: querying subnet %s \
-for domain master browser on workgroup %s\n", subrec->subnet_name, workgroup_name));
-
- query_name(subrec, nmbname.name, nmbname.name_type,
- become_domain_master_query_success,
- become_domain_master_query_fail,
- NULL);
- }
- }
- }
-}
-
-/****************************************************************************
- Attempt to become a domain master browser by registering with WINS.
- ****************************************************************************/
-
-static void become_domain_master_browser_wins(char *workgroup_name)
-{
- struct work_record *work;
-
- work = find_workgroup_on_subnet(unicast_subnet, workgroup_name);
-
- if (work && (work->dom_state == DOMAIN_NONE))
- {
- struct nmb_name nmbname;
-
- make_nmb_name(&nmbname,workgroup_name,0x1b,scope);
-
- /*
- * Check for our name on the unicast subnet first, only initiate
- * further processing if we cannot find it.
- */
-
- if (find_name_on_subnet(unicast_subnet, &nmbname, FIND_SELF_NAME) == NULL)
- {
- DEBUG(0,("%s become_domain_master_browser_wins: attempting to become domain \
-master browser on workgroup %s, subnet %s.\n",
- timestring(), workgroup_name, unicast_subnet->subnet_name));
-
- /* Send out a query to establish whether there's a
- domain master broswer registered with WINS. If not,
- we can become a domain master browser.
- */
-
- DEBUG(0,("become_domain_master_browser_wins: querying WINS server at IP %s \
-for domain master browser name %s on workgroup %s\n",
- inet_ntoa(unicast_subnet->myip), namestr(&nmbname), workgroup_name));
-
- query_name(unicast_subnet, nmbname.name, nmbname.name_type,
- become_domain_master_query_success,
- become_domain_master_query_fail,
- NULL);
- }
- }
-}
-
-/****************************************************************************
- Add the domain logon server and domain master browser names
- if we are set up to do so.
- **************************************************************************/
-
-void add_domain_names(time_t t)
-{
- static time_t lastrun = 0;
-
- if ((lastrun != 0) && (t < lastrun + (CHECK_TIME_ADD_DOM_NAMES * 60)))
- return;
-
- lastrun = t;
-
- /* Do the "internet group" - <1c> names. */
- if (lp_domain_logons())
- add_logon_names();
-
- /* Do the domain master names. */
- if(lp_domain_master())
- {
- if(we_are_a_wins_client())
- {
- /* We register the WORKGROUP<1b> name with the WINS
- server first, and call add_domain_master_bcast()
- only if this is successful.
-
- This results in domain logon services being gracefully provided,
- as opposed to the aggressive nature of 1.9.16p2 to 1.9.16p11.
- 1.9.16p2 to 1.9.16p11 - due to a bug in namelogon.c,
- cannot provide domain master / domain logon services.
- */
- become_domain_master_browser_wins(myworkgroup);
- }
- else
- become_domain_master_browser_bcast(myworkgroup);
- }
-}
diff --git a/source/nmbd/nmbd_become_lmb.c b/source/nmbd/nmbd_become_lmb.c
deleted file mode 100644
index 6dcd61d76c1..00000000000
--- a/source/nmbd/nmbd_become_lmb.c
+++ /dev/null
@@ -1,563 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-extern pstring scope;
-extern pstring myname;
-
-extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
-
-/*******************************************************************
- Utility function to add a name to the unicast subnet, or add in
- our IP address if it already exists.
-******************************************************************/
-
-static void insert_permanent_name_into_unicast( struct subnet_record *subrec,
- struct nmb_name *nmbname, uint16 nb_type )
-{
- struct name_record *namerec;
-
- if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) == NULL)
- {
- /* The name needs to be created on the unicast subnet. */
- add_name_to_subnet( unicast_subnet, nmbname->name, nmbname->name_type,
- nb_type, PERMANENT_TTL, PERMANENT_NAME, 1, &subrec->myip);
- }
- else
- {
- /* The name already exists on the unicast subnet. Add our local
- IP for the given broadcast subnet to the name. */
- add_ip_to_name_record( namerec, subrec->myip);
- }
-}
-
-/*******************************************************************
- Utility function to remove a name from the unicast subnet.
-******************************************************************/
-
-static void remove_permanent_name_from_unicast( struct subnet_record *subrec,
- struct nmb_name *nmbname )
-{
- struct name_record *namerec;
-
- if((namerec = find_name_on_subnet(unicast_subnet, nmbname, FIND_SELF_NAME)) != NULL)
- {
- /* Remove this broadcast subnet IP address from the name. */
- remove_ip_from_name_record( namerec, subrec->myip);
- if(namerec->num_ips == 0)
- remove_name_from_namelist( unicast_subnet, namerec);
- }
-}
-
-/*******************************************************************
- Utility function always called to set our workgroup and server
- state back to potential browser, or none.
-******************************************************************/
-
-static void reset_workgroup_state( struct subnet_record *subrec, char *workgroup_name )
-{
- struct work_record *work;
- struct server_record *servrec;
- struct nmb_name nmbname;
-
- if((work = find_workgroup_on_subnet( subrec, workgroup_name)) == NULL)
- {
- DEBUG(0,("reset_workgroup_state: Error - cannot find workgroup %s on \
-subnet %s.\n", workgroup_name, subrec->subnet_name ));
- return;
- }
-
- if((servrec = find_server_in_workgroup( work, myname)) == NULL)
- {
- DEBUG(0,("reset_workgroup_state: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- myname, work->work_group, subrec->subnet_name));
- work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
- return;
- }
-
- /* Update our server status - remove any master flag and replace
- it with the potential browser flag. */
- servrec->serv.type &= ~SV_TYPE_MASTER_BROWSER;
- servrec->serv.type |= (lp_local_master() ? SV_TYPE_POTENTIAL_BROWSER : 0);
-
- /* Tell the namelist writer to write out a change. */
- subrec->work_changed = True;
-
- /* Reset our election flags. */
- work->ElectionCriterion &= ~0x4;
-
- work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
-
- /* Forget who the local master browser was for
- this workgroup. */
-
- set_workgroup_local_master_browser_name( work, "");
-
- /*
- * Ensure the IP address of this subnet is not registered as one
- * of the IP addresses of the WORKGROUP<1d> name on the unicast
- * subnet. This undoes what we did below when we became a local
- * master browser.
- */
-
- make_nmb_name(&nmbname, work->work_group, 0x1d, scope);
-
- remove_permanent_name_from_unicast( subrec, &nmbname);
-
-}
-
-/*******************************************************************
- Unbecome the local master browser name release success function.
-******************************************************************/
-
-void unbecome_local_master_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *released_name,
- struct in_addr released_ip)
-{
- DEBUG(3,("unbecome_local_master_success: released name %s.\n",
- namestr(released_name)));
-
- /* Now reset the workgroup and server state. */
- reset_workgroup_state( subrec, released_name->name );
-
- DEBUG(0,("\n***** Samba name server %s has stopped being a local master browser for workgroup %s \
-on subnet %s *****\n\n", myname, released_name->name, subrec->subnet_name));
-
-}
-
-/*******************************************************************
- Unbecome the local master browser name release fail function.
-******************************************************************/
-
-void unbecome_local_master_fail(struct subnet_record *subrec, struct response_record *rrec,
- struct nmb_name *fail_name)
-{
- struct name_record *namerec;
-
- DEBUG(0,("unbecome_local_master_fail: failed to release name %s. \
-Removing from namelist anyway.\n", namestr(fail_name)));
-
- /* Do it anyway. */
- namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
- if(namerec)
- remove_name_from_namelist(subrec, namerec);
-
- /* Now reset the workgroup and server state. */
- reset_workgroup_state( subrec, fail_name->name );
-
- DEBUG(0,("\n***** Samba name server %s has stopped being a local master browser for workgroup %s \
-on subnet %s *****\n\n", myname, fail_name->name, subrec->subnet_name));
-
-}
-
-/*******************************************************************
- Utility function to remove the WORKGROUP<1d> name called by both
- success and fail of releasing the MSBROWSE name.
-******************************************************************/
-
-void release_1d_name( struct subnet_record *subrec, char *workgroup_name)
-{
- struct nmb_name nmbname;
- struct name_record *namerec;
-
- make_nmb_name(&nmbname, workgroup_name, 0x1d, scope);
- if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
- {
- release_name(subrec, namerec,
- unbecome_local_master_success,
- unbecome_local_master_fail,
- NULL);
- }
-}
-
-/*******************************************************************
- Unbecome the local master browser MSBROWSE name release success function.
-******************************************************************/
-
-static void release_msbrowse_name_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *released_name,
- struct in_addr released_ip)
-{
- DEBUG(4,("release_msbrowse_name_success: Released name %s on subnet %s\n.",
- namestr(released_name), subrec->subnet_name ));
-
- /* Remove the permanent MSBROWSE name added into the unicast subnet. */
- remove_permanent_name_from_unicast( subrec, released_name);
-
- release_1d_name( subrec, userdata->data );
-}
-
-/*******************************************************************
- Unbecome the local master browser MSBROWSE name release fail function.
-******************************************************************/
-
-static void release_msbrowse_name_fail( struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *fail_name)
-{
- struct userdata_struct *userdata = rrec->userdata;
- struct name_record *namerec;
-
- DEBUG(4,("release_msbrowse_name_fail: Failed to release name %s on subnet %s\n.",
- namestr(fail_name), subrec->subnet_name ));
-
- /* Release the name anyway. */
- namerec = find_name_on_subnet(subrec, fail_name, FIND_SELF_NAME);
- if(namerec)
- remove_name_from_namelist(subrec, namerec);
-
- /* Remove the permanent MSBROWSE name added into the unicast subnet. */
- remove_permanent_name_from_unicast( subrec, fail_name);
-
- release_1d_name( subrec, userdata->data );
-}
-
-/*******************************************************************
- Unbecome the local master browser.
-******************************************************************/
-
-void unbecome_local_master_browser(struct subnet_record *subrec, struct work_record *work)
-{
- struct server_record *servrec;
- struct name_record *namerec;
- struct nmb_name nmbname;
- struct userdata_struct *userdata;
- char ud[sizeof(struct userdata_struct) + sizeof(fstring)+1];
-
- /* Sanity check. */
-
- DEBUG(2,("unbecome_local_master_browser: unbecoming local master for workgroup %s \
-on subnet %s\n",work->work_group, subrec->subnet_name));
-
- if((servrec = find_server_in_workgroup( work, myname)) == NULL)
- {
- DEBUG(0,("unbecome_local_master_browser: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- myname, work->work_group, subrec->subnet_name));
- work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
- return;
- }
-
- /* Set the state to unbecoming. */
- work->mst_state = MST_UNBECOMING_MASTER;
-
- /* Setup the userdata for the MSBROWSE name release. */
- /* Setup the userdata_struct - this is copied so we can use
- a stack variable for this. */
- userdata = (struct userdata_struct *)ud;
-
- userdata->copy_fn = NULL;
- userdata->free_fn = NULL;
- userdata->userdata_len = strlen(work->work_group)+1;
- strcpy(userdata->data, work->work_group);
-
- /* Deregister any browser names we may have. */
- make_nmb_name(&nmbname, MSBROWSE, 0x1, scope);
- if((namerec = find_name_on_subnet( subrec, &nmbname, FIND_SELF_NAME))!=NULL)
- {
- release_name(subrec, namerec,
- release_msbrowse_name_success,
- release_msbrowse_name_fail,
- userdata);
- }
-}
-
-/****************************************************************************
- Success in registering the WORKGROUP<1d> name.
- We are now *really* a local master browser.
- ****************************************************************************/
-
-static void become_local_master_stage2(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *registered_name,
- uint16 nb_flags,
- int ttl, struct in_addr registered_ip)
-{
- int i = 0;
- struct server_record *sl;
- struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
- struct server_record *servrec;
-
- if(!work)
- {
- DEBUG(0,("become_local_master_stage2: Error - cannot find \
-workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
- return;
- }
-
- if((servrec = find_server_in_workgroup( work, myname)) == NULL)
- {
- DEBUG(0,("become_local_master_stage2: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- myname, registered_name->name, subrec->subnet_name));
- work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
- return;
- }
-
- DEBUG(3,("become_local_master_stage2: registered as master browser for workgroup %s \
-on subnet %s\n", work->work_group, subrec->subnet_name));
-
- work->mst_state = MST_BROWSER; /* registering WORKGROUP(1d) succeeded */
-
- /* update our server status */
- servrec->serv.type |= SV_TYPE_MASTER_BROWSER;
- servrec->serv.type &= ~SV_TYPE_POTENTIAL_BROWSER;
-
- /* Tell the namelist writer to write out a change. */
- subrec->work_changed = True;
-
- /* Add this name to the workgroup as local master browser. */
- set_workgroup_local_master_browser_name( work, myname);
-
- /* Count the number of servers we have on our list. If it's
- less than 10 (just a heuristic) request the servers
- to announce themselves.
- */
- for( sl = work->serverlist; sl != NULL; sl = sl->next)
- i++;
-
- if (i < 10)
- {
- /* Ask all servers on our local net to announce to us. */
- broadcast_announce_request(subrec, work);
- }
-
- /*
- * Now we are a local master on a broadcast subnet, we need to add
- * the WORKGROUP<1d> name to the unicast subnet so that we can answer
- * unicast requests sent to this name. We can create this name directly on
- * the unicast subnet as a WINS server always returns true when registering
- * this name, and discards the registration. We use the number of IP
- * addresses registered to this name as a reference count, as we
- * remove this broadcast subnet IP address from it when we stop becoming a local
- * master browser for this broadcast subnet.
- */
-
- insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
-
- /* Reset the announce master browser timer so that we try and tell a domain
- master browser as soon as possible that we are a local master browser. */
- reset_announce_timer();
-
- DEBUG(0,("\n***** Samba name server %s is now a local master browser for workgroup %s \
-on subnet %s *****\n\n", myname, work->work_group, subrec->subnet_name));
-
-}
-
-/****************************************************************************
- Failed to register the WORKGROUP<1d> name.
- ****************************************************************************/
-static void become_local_master_fail2(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *fail_name)
-{
- struct work_record *work = find_workgroup_on_subnet( subrec, fail_name->name);
-
- DEBUG(0,("become_local_master_fail2: failed to register name %s on subnet %s. \
-Failed to become a local master browser.\n", namestr(fail_name), subrec->subnet_name));
-
- if(!work)
- {
- DEBUG(0,("become_local_master_fail2: Error - cannot find \
-workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
- return;
- }
-
- /* Roll back all the way by calling unbecome_local_master_browser(). */
- unbecome_local_master_browser(subrec, work);
-}
-
-/****************************************************************************
- Success in registering the MSBROWSE name.
- ****************************************************************************/
-
-static void become_local_master_stage1(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *registered_name,
- uint16 nb_flags,
- int ttl, struct in_addr registered_ip)
-{
- char *work_name = userdata->data;
- struct work_record *work = find_workgroup_on_subnet( subrec, work_name);
-
- if(!work)
- {
- DEBUG(0,("become_local_master_stage1: Error - cannot find \
-workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
- return;
- }
-
- DEBUG(3,("become_local_master_stage1: go to stage 2: register the %s<1d> name.\n",
- work->work_group));
-
- work->mst_state = MST_MSB; /* Registering MSBROWSE was successful. */
-
- /*
- * We registered the MSBROWSE name on a broadcast subnet, now need to add
- * the MSBROWSE name to the unicast subnet so that we can answer
- * unicast requests sent to this name. We create this name directly on
- * the unicast subnet.
- */
-
- insert_permanent_name_into_unicast( subrec, registered_name, nb_flags);
-
- /* Attempt to register the WORKGROUP<1d> name. */
- register_name(subrec, work->work_group,0x1d,samba_nb_type,
- become_local_master_stage2,
- become_local_master_fail2,
- NULL);
-}
-
-/****************************************************************************
- Failed to register the MSBROWSE name.
- ****************************************************************************/
-
-static void become_local_master_fail1(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *fail_name)
-{
- char *work_name = rrec->userdata->data;
- struct work_record *work = find_workgroup_on_subnet(subrec, work_name);
- struct server_record *servrec;
-
- if(!work)
- {
- DEBUG(0,("become_local_master_fail1: Error - cannot find \
-workgroup %s on subnet %s\n", work_name, subrec->subnet_name));
- return;
- }
-
- if((servrec = find_server_in_workgroup(work, myname)) == NULL)
- {
- DEBUG(0,("become_local_master_fail1: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- myname, work->work_group, subrec->subnet_name));
- return;
- }
-
- reset_workgroup_state( subrec, work->work_group );
-
- DEBUG(0,("become_local_master_fail1: Failed to become a local master browser for \
-workgroup %s on subnet %s. Couldn't register name %s.\n",
- work->work_group, subrec->subnet_name, namestr(fail_name)));
-}
-
-/******************************************************************
- Become the local master browser on a subnet.
- This gets called if we win an election on this subnet.
-
- Stage 1: mst_state was MST_POTENTIAL - go to MST_BACK register ^1^2__MSBROWSE__^2^1.
- Stage 2: mst_state was MST_BACKUP - go to MST_MSB and register WORKGROUP<1d>.
- Stage 3: mst_state was MST_MSB - go to MST_BROWSER.
-******************************************************************/
-
-void become_local_master_browser(struct subnet_record *subrec, struct work_record *work)
-{
- struct server_record *servrec;
- struct userdata_struct *userdata;
- char ud[sizeof(struct userdata_struct) + sizeof(fstring)+1];
-
- /* Sanity check. */
- if (!lp_local_master())
- {
- DEBUG(0,("become_local_master_browser: Samba not configured as a local master browser.\n"));
- return;
- }
-
- if(!AM_POTENTIAL_MASTER_BROWSER(work))
- {
- DEBUG(2,("become_local_master_browser: Awaiting potential browser state. Current state is %d\n",
- work->mst_state ));
- return;
- }
-
- if((servrec = find_server_in_workgroup( work, myname)) == NULL)
- {
- DEBUG(0,("become_local_master_browser: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- myname, work->work_group, subrec->subnet_name));
- return;
- }
-
- DEBUG(2,("become_local_master_browser: Starting to become a master browser for workgroup \
-%s on subnet %s\n", work->work_group, subrec->subnet_name));
-
- DEBUG(3,("become_local_master_browser: first stage - attempt to register ^1^2__MSBROWSE__^2^1\n"));
- work->mst_state = MST_BACKUP; /* an election win was successful */
-
- work->ElectionCriterion |= 0x5;
-
- /* Tell the namelist writer to write out a change. */
- subrec->work_changed = True;
-
- /* Setup the userdata_struct - this is copied so we can use
- a stack variable for this. */
- userdata = (struct userdata_struct *)ud;
-
- userdata->copy_fn = NULL;
- userdata->free_fn = NULL;
- userdata->userdata_len = strlen(work->work_group)+1;
- strcpy(userdata->data, work->work_group);
-
- /* Register the special browser group name. */
- register_name(subrec, MSBROWSE, 0x01, samba_nb_type|NB_GROUP,
- become_local_master_stage1,
- become_local_master_fail1,
- userdata);
-}
-
-/***************************************************************
- Utility function to set the local master browser name. Does
- some sanity checking as old versions of Samba seem to sometimes
- say that the master browser name for a workgroup is the same
- as the workgroup name.
-****************************************************************/
-
-void set_workgroup_local_master_browser_name( struct work_record *work, char *newname)
-{
- DEBUG(5,("set_workgroup_local_master_browser_name: setting local master name to '%s' \
-for workgroup %s.\n", newname, work->work_group ));
-
-#if 0
- /*
- * Apparently some sites use the workgroup name as the local
- * master browser name. Arrrrggghhhhh ! (JRA).
- */
- if(strequal( work->work_group, newname))
- {
- DEBUG(5, ("set_workgroup_local_master_browser_name: Refusing to set \
-local_master_browser_name for workgroup %s to workgroup name.\n",
- work->work_group ));
- return;
- }
-#endif
-
- StrnCpy(work->local_master_browser_name, newname,
- sizeof(work->local_master_browser_name)-1);
-}
diff --git a/source/nmbd/nmbd_browserdb.c b/source/nmbd/nmbd_browserdb.c
deleted file mode 100644
index b2db7443707..00000000000
--- a/source/nmbd/nmbd_browserdb.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-#include "smb.h"
-
-extern int DEBUGLEVEL;
-
-/* This is our local master browser list database. */
-struct browse_cache_record *lmb_browserlist = NULL;
-
-/***************************************************************************
-Add a browser into the lmb list.
-**************************************************************************/
-
-static void add_to_lmb_browse_cache(struct browse_cache_record *browc)
-{
- struct browse_cache_record *browc2;
-
- if (lmb_browserlist == NULL)
- {
- lmb_browserlist = browc;
- browc->prev = NULL;
- browc->next = NULL;
- return;
- }
-
- for (browc2 = lmb_browserlist; browc2->next; browc2 = browc2->next)
- ;
-
- browc2->next = browc;
- browc->next = NULL;
- browc->prev = browc2;
-}
-
-/*******************************************************************
-Remove a lmb browser entry.
-******************************************************************/
-
-void remove_lmb_browser_entry(struct browse_cache_record *browc)
-{
- if (browc->prev)
- browc->prev->next = browc->next;
- if (browc->next)
- browc->next->prev = browc->prev;
-
- if (lmb_browserlist == browc)
- lmb_browserlist = browc->next;
-
- free((char *)browc);
-}
-
-/****************************************************************************
-Update a browser death time.
-****************************************************************************/
-
-void update_browser_death_time(struct browse_cache_record *browc)
-{
- /* Allow the new lmb to miss an announce period before we remove it. */
- browc->death_time = time(NULL) + (CHECK_TIME_MST_ANNOUNCE + 2)*60;
-}
-
-/****************************************************************************
-Create a browser entry.
-****************************************************************************/
-
-struct browse_cache_record *create_browser_in_lmb_cache(char *work_name, char *browser_name,
- struct in_addr ip)
-{
- struct browse_cache_record *browc;
- time_t now = time(NULL);
-
- browc = (struct browse_cache_record *)malloc(sizeof(*browc));
-
- if (browc == NULL)
- {
- DEBUG(0,("create_browser_in_lmb_cache: malloc fail !\n"));
- return(NULL);
- }
-
- bzero((char *)browc,sizeof(*browc));
-
- /* For a new lmb entry we want to sync with it after one minute. This
- will allow it time to send out a local announce and build its
- browse list. */
-
- browc->sync_time = now + 60;
-
- /* Allow the new lmb to miss an announce period before we remove it. */
- browc->death_time = now + (CHECK_TIME_MST_ANNOUNCE + 2)*60;
-
- StrnCpy(browc->lmb_name, browser_name,sizeof(browc->lmb_name)-1);
- StrnCpy(browc->work_group,work_name,sizeof(browc->work_group)-1);
- strupper(browc->lmb_name);
- strupper(browc->work_group);
-
- browc->ip = ip;
-
- add_to_lmb_browse_cache(browc);
-
- DEBUG(3,("create_browser_in_lmb_cache: Added lmb cache entry for workgroup %s name %s IP %s ttl %d\n",
- browc->work_group, browc->lmb_name, inet_ntoa(ip), browc->death_time));
-
- return(browc);
-}
-
-/****************************************************************************
-Find a browser entry.
-****************************************************************************/
-
-struct browse_cache_record *find_browser_in_lmb_cache( char *browser_name )
-{
- struct browse_cache_record *browc = NULL;
-
- for( browc = lmb_browserlist; browc; browc = browc->next)
- if(strequal( browser_name, browc->lmb_name))
- break;
-
- return browc;
-}
-
-/*******************************************************************
- Expire timed out browsers in the browserlist.
-******************************************************************/
-
-void expire_lmb_browsers(time_t t)
-{
- struct browse_cache_record *browc;
- struct browse_cache_record *nextbrowc;
-
- for (browc = lmb_browserlist; browc; browc = nextbrowc)
- {
- nextbrowc = browc->next;
-
- if (browc->death_time < t)
- {
- DEBUG(3,("expire_lmb_browsers: Removing timed out lmb entry %s\n",browc->lmb_name));
- remove_lmb_browser_entry(browc);
- }
- }
-}
-
-/*******************************************************************
- Remove browsers from a named workgroup in the browserlist.
-******************************************************************/
-
-void remove_workgroup_lmb_browsers(char *work_group)
-{
- struct browse_cache_record *browc;
- struct browse_cache_record *nextbrowc;
-
- for (browc = lmb_browserlist; browc; browc = nextbrowc)
- {
- nextbrowc = browc->next;
-
- if (strequal(work_group, browc->work_group))
- {
- DEBUG(3,("remove_workgroup_browsers: Removing lmb entry %s\n",browc->lmb_name));
- remove_lmb_browser_entry(browc);
- }
- }
-}
-
diff --git a/source/nmbd/nmbd_browsesync.c b/source/nmbd/nmbd_browsesync.c
deleted file mode 100644
index b899e2e8bc5..00000000000
--- a/source/nmbd/nmbd_browsesync.c
+++ /dev/null
@@ -1,458 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-#include "smb.h"
-
-extern int DEBUGLEVEL;
-extern pstring scope;
-extern struct in_addr ipzero;
-extern pstring myname;
-
-/* This is our local master browser list database. */
-extern struct browse_cache_record *lmb_browserlist;
-
-static struct work_record *call_work;
-static struct subnet_record *call_subrec;
-
-/*******************************************************************
- This is the NetServerEnum callback.
- ******************************************************************/
-
-static void callback(char *sname, uint32 stype, char *comment)
-{
- struct work_record *work;
-
- stype &= ~SV_TYPE_LOCAL_LIST_ONLY;
-
- if (stype & SV_TYPE_DOMAIN_ENUM)
- {
- /* See if we can find the workgroup on this subnet. */
- if(( work = find_workgroup_on_subnet( call_subrec, sname )) != NULL)
- {
- /* We already know about this workgroup - update the ttl. */
- update_workgroup_ttl( work, lp_max_ttl() );
- }
- else
- {
- /* Create the workgroup on the subnet. */
- create_workgroup_on_subnet( call_subrec, sname, lp_max_ttl() );
- }
- }
- else
- {
- /* Server entry. */
- struct server_record *servrec;
-
- work = call_work;
-
- if(( servrec = find_server_in_workgroup( work, sname )) != NULL)
- {
- /* Check that this is not a locally known server - if so ignore the
- entry. */
- if(!(servrec->serv.type & SV_TYPE_LOCAL_LIST_ONLY))
- {
- /* We already know about this server - update the ttl. */
- update_server_ttl(servrec, lp_max_ttl() );
- /* Update the type. */
- servrec->serv.type = stype;
- }
- }
- else
- {
- /* Create the server in the workgroup. */
- create_server_on_workgroup(work, sname,stype,lp_max_ttl(),comment);
- }
- }
-}
-
-/*******************************************************************
- Synchronise browse lists with another browse server.
- Log in on the remote server's SMB port to their IPC$ service,
- do a NetServerEnum and update our server and workgroup databases.
-******************************************************************/
-
-static void sync_browse_lists(struct subnet_record *subrec, struct work_record *work,
- char *name, int nm_type, struct in_addr ip, BOOL local)
-{
- extern fstring local_machine;
- static struct cli_state cli;
- uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0;
-
- DEBUG(2,("%s: sync_browse_lists: Sync browse lists with server %s<%02x> at IP %s for workgroup %s\n",
- timestring(), name, nm_type, inet_ntoa(ip), work->work_group ));
-
- /* Check we're not trying to sync with ourselves. This can happen if we are
- a domain *and* a local master browser. */
- if(ismyip(ip))
- {
- DEBUG(2,("sync_browse_lists: We are both a domain and a local master browser for workgroup %s. \
-Do not sync with ourselves.\n", work->work_group ));
- return;
- }
-
- if (!cli_initialise(&cli) || !cli_connect(&cli, name, &ip))
- {
- DEBUG(0,("sync_browse_lists: Failed to start browse sync with %s\n", name));
- return;
- }
-
- if (!cli_session_request(&cli, name, nm_type, local_machine))
- {
- DEBUG(0,("sync_browse_lists: %s rejected the browse sync session\n",name));
- cli_shutdown(&cli);
- return;
- }
-
- if (!cli_negprot(&cli))
- {
- DEBUG(0,("sync_browse_lists: %s rejected the negprot\n",name));
- cli_shutdown(&cli);
- return;
- }
-
- if (!cli_session_setup(&cli, "", "", 1, "", 0, work->work_group))
- {
- DEBUG(0,("sync_browse_lists: %s rejected the browse sync sessionsetup\n",
- name));
- cli_shutdown(&cli);
- return;
- }
-
- if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1))
- {
- DEBUG(0,("sync_browse_lists: %s refused browse sync IPC$ connect\n", name));
- cli_shutdown(&cli);
- return;
- }
-
- call_work = work;
- call_subrec = subrec;
-
- /* Fetch a workgroup list. */
- cli_NetServerEnum(&cli, work->work_group,
- local_type|SV_TYPE_DOMAIN_ENUM,
- callback);
-
- /* Now fetch a server list. */
- cli_NetServerEnum(&cli, work->work_group,
- local?SV_TYPE_LOCAL_LIST_ONLY:SV_TYPE_ALL,
- callback);
-
- cli_shutdown(&cli);
-}
-
-/****************************************************************************
-As a domain master browser, do a sync with a local master browser.
-**************************************************************************/
-
-static void sync_with_lmb(struct browse_cache_record *browc)
-{
- struct work_record *work;
-
- if (!(work = find_workgroup_on_subnet(unicast_subnet, browc->work_group))) {
- DEBUG(0, ("sync_with_lmb: failed to get a \
-workgroup for a local master browser cache entry workgroup %s, server %s\n",
- browc->work_group, browc->lmb_name));
- return;
- }
-
- /* We should only be doing this if we are a domain master browser for
- the given workgroup. Ensure this is so. */
-
- if(!AM_DOMAIN_MASTER_BROWSER(work))
- {
- DEBUG(0,("sync_with_lmb: We are trying to sync with a local master browser %s \
-for workgroup %s and we are not a domain master browser on this workgroup. Error !\n",
- browc->lmb_name, browc->work_group));
- return;
- }
-
- DEBUG(2, ("sync_with_lmb: Initiating sync with local master browser %s<0x20> at IP %s for \
-workgroup %s\n", browc->lmb_name, inet_ntoa(browc->ip), browc->work_group));
-
- sync_browse_lists(unicast_subnet, work, browc->lmb_name, 0x20, browc->ip, True);
-
- browc->sync_time += (CHECK_TIME_DMB_TO_LMB_SYNC * 60);
-}
-
-/****************************************************************************
-Sync or expire any local master browsers.
-**************************************************************************/
-
-void dmb_expire_and_sync_browser_lists(time_t t)
-{
- static time_t last_run = 0;
- struct browse_cache_record *browc;
-
- /* Only do this every 20 seconds. */
- if (t - last_run < 20)
- return;
-
- last_run = t;
-
- expire_lmb_browsers(t);
-
- for (browc = lmb_browserlist; browc; browc = browc->next)
- {
- if (browc->sync_time < t)
- sync_with_lmb(browc);
- }
-}
-
-/****************************************************************************
-As a local master browser, send an announce packet to the domain master browser.
-**************************************************************************/
-
-static void announce_local_master_browser_to_domain_master_browser( struct work_record *work)
-{
- pstring outbuf;
- char *p;
-
- if(ismyip(work->dmb_addr))
- {
- DEBUG(2,("announce_local_master_browser_to_domain_master_browser: We are both a domain \
-and a local master browser for workgroup %s. \
-Do not announce to ourselves.\n", work->work_group ));
- return;
- }
-
- bzero(outbuf,sizeof(outbuf));
- p = outbuf;
- CVAL(p,0) = ANN_MasterAnnouncement;
- p++;
-
- StrnCpy(p,myname,15);
- strupper(p);
- p = skip_string(p,1);
-
- DEBUG(4,("announce_local_master_browser_to_domain_master_browser: Sending local master announce \
-to %s for workgroup %s.\n", namestr(&work->dmb_name), work->work_group ));
-
- send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
- myname, 0x0, work->dmb_name.name, 0x20, work->dmb_addr, FIRST_SUBNET->myip);
-
-}
-
-/****************************************************************************
-As a local master browser, do a sync with a domain master browser.
-**************************************************************************/
-
-static void sync_with_dmb(struct work_record *work)
-{
- DEBUG(2, ("sync_with_dmb: Initiating sync with domain master browser %s at IP %s for \
-workgroup %s\n", namestr(&work->dmb_name), inet_ntoa(work->dmb_addr), work->work_group));
-
- sync_browse_lists(unicast_subnet, work, work->dmb_name.name, work->dmb_name.name_type,
- work->dmb_addr, False);
-}
-
-/****************************************************************************
- Function called when a node status query to a domain master browser IP succeeds.
-****************************************************************************/
-
-static void domain_master_node_status_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct res_rec *answers,
- struct in_addr from_ip)
-{
- struct work_record *work = find_workgroup_on_subnet( subrec, userdata->data);
-
- if(work == NULL)
- {
- DEBUG(0,("domain_master_node_status_success: Unable to find workgroup %s on subnet %s.\n",
- userdata->data, subrec->subnet_name));
- return;
- }
-
- DEBUG(3,("domain_master_node_status_success: Success in node status for workgroup %s from ip %s\n",
- work->work_group, inet_ntoa(from_ip) ));
-
- /* Go through the list of names found at answers->rdata and look for
- the first SERVER<0x20> name. */
-
- if(answers->rdata != NULL)
- {
- char *p = answers->rdata;
- int numnames = CVAL(p, 0);
-
- p += 1;
-
- while (numnames--)
- {
- char qname[17];
- uint16 nb_flags;
- int name_type;
-
- StrnCpy(qname,p,15);
- name_type = CVAL(p,15);
- nb_flags = get_nb_flags(&p[16]);
- trim_string(qname,NULL," ");
-
- p += 18;
-
- if(!(nb_flags & NB_GROUP) && (name_type == 0x20))
- {
- struct nmb_name nmbname;
-
- make_nmb_name(&nmbname, qname, name_type, scope);
-
- /* Copy the dmb name and IP address
- into the workgroup struct. */
-
- work->dmb_name = nmbname;
- putip((char *)&work->dmb_addr, &from_ip);
-
- /* Do the local master browser announcement to the domain
- master browser name and IP. */
- announce_local_master_browser_to_domain_master_browser( work );
-
- /* Now synchronise lists with the domain master browser. */
- sync_with_dmb(work);
- break;
- }
- }
- }
- else
- DEBUG(0,("domain_master_node_status_success: Failed to find a SERVER<0x20> \
-name in reply from IP %s.\n", inet_ntoa(from_ip) ));
-}
-
-/****************************************************************************
- Function called when a node status query to a domain master browser IP fails.
-****************************************************************************/
-
-static void domain_master_node_status_fail(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- struct userdata_struct *userdata = rrec->userdata;
-
- DEBUG(0,("domain_master_node_status_fail: Doing a node status request to \
-the domain master browser for workgroup %s at IP %s failed. Cannot sync browser \
-lists.\n", userdata->data, inet_ntoa(rrec->packet->ip) ));
-
-}
-
-/****************************************************************************
- Function called when a query for a WORKGROUP<1b> name succeeds.
-****************************************************************************/
-
-static void find_domain_master_name_query_success(struct subnet_record *subrec,
- struct userdata_struct *userdata_in,
- struct nmb_name *q_name, struct in_addr answer_ip, struct res_rec *rrec)
-{
- /*
- * Unfortunately, finding the IP address of the Domain Master Browser,
- * as we have here, is not enough. We need to now do a sync to the
- * SERVERNAME<0x20> NetBIOS name, as only recent NT servers will
- * respond to the SMBSERVER name. To get this name from IP
- * address we do a Node status request, and look for the first
- * NAME<0x20> in the response, and take that as the server name.
- * We also keep a cache of the Domain Master Browser name for this
- * workgroup in the Workgroup struct, so that if the same IP addess
- * is returned every time, we don't need to do the node status
- * request.
- */
-
- struct work_record *work;
- struct nmb_name nmbname;
- struct userdata_struct *userdata;
- char ud[sizeof(struct userdata_struct) + sizeof(fstring)+1];
-
- if (!(work = find_workgroup_on_subnet(subrec, q_name->name))) {
- DEBUG(0, ("find_domain_master_name_query_success: failed to find \
-workgroup %s\n", q_name->name ));
- return;
- }
-
- /* First check if we already have a dmb for this workgroup. */
-
- if(!ip_equal(work->dmb_addr, ipzero) && ip_equal(work->dmb_addr, answer_ip))
- {
- /* Do the local master browser announcement to the domain
- master browser name and IP. */
- announce_local_master_browser_to_domain_master_browser( work );
-
- /* Now synchronise lists with the domain master browser. */
- sync_with_dmb(work);
- return;
- }
- else
- putip((char *)&work->dmb_addr, &ipzero);
-
- /* Now initiate the node status request. */
- bzero((char *)&nmbname, sizeof(nmbname));
- nmbname.name[0] = '*';
-
- /* Put the workgroup name into the userdata so we know
- what workgroup we're talking to when the reply comes
- back. */
-
- /* Setup the userdata_struct - this is copied so we can use
- a stack variable for this. */
- userdata = (struct userdata_struct *)ud;
-
- userdata->copy_fn = NULL;
- userdata->free_fn = NULL;
- userdata->userdata_len = strlen(work->work_group)+1;
- strcpy(userdata->data, work->work_group);
-
- node_status( subrec, &nmbname, answer_ip,
- domain_master_node_status_success,
- domain_master_node_status_fail,
- userdata);
-}
-
-/****************************************************************************
- Function called when a query for a WORKGROUP<1b> name fails.
- ****************************************************************************/
-static void find_domain_master_name_query_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *question_name, int fail_code)
-{
- DEBUG(0,("find_domain_master_name_query_fail: Unable to find the Domain Master \
-Browser name %s for the workgroup %s. Unable to sync browse lists in this workgroup.\n",
- namestr(question_name), question_name->name ));
-}
-
-/****************************************************************************
-As a local master browser for a workgroup find the domain master browser
-name, announce ourselves as local master browser to it and then pull the
-full domain browse lists from it onto the given subnet.
-**************************************************************************/
-
-void announce_and_sync_with_domain_master_browser( struct subnet_record *subrec,
- struct work_record *work)
-{
- struct nmb_name nmbname;
-
- make_nmb_name(&nmbname,work->work_group,0x1b,scope);
-
- /* First, query for the WORKGROUP<1b> name from the WINS server. */
- query_name(unicast_subnet, nmbname.name, nmbname.name_type,
- find_domain_master_name_query_success,
- find_domain_master_name_query_fail,
- NULL);
-
-}
diff --git a/source/nmbd/nmbd_elections.c b/source/nmbd/nmbd_elections.c
deleted file mode 100644
index 5c3c4c7a013..00000000000
--- a/source/nmbd/nmbd_elections.c
+++ /dev/null
@@ -1,348 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-extern pstring myname;
-extern fstring myworkgroup;
-
-/* Election parameters. */
-extern time_t StartupTime;
-
-/****************************************************************************
- Send an election datagram packet.
-**************************************************************************/
-static void send_election_dgram(struct subnet_record *subrec, char *workgroup_name,
- uint32 criterion, int timeup,char *server_name)
-{
- pstring outbuf;
- char *p;
-
- DEBUG(2,("send_election_dgram: Sending election packet for workgroup %s on subnet %s\n",
- workgroup_name, subrec->subnet_name ));
-
- bzero(outbuf,sizeof(outbuf));
- p = outbuf;
- CVAL(p,0) = ANN_Election; /* Election opcode. */
- p++;
-
- CVAL(p,0) = (criterion == 0 && timeup == 0) ? 0 : ELECTION_VERSION;
- SIVAL(p,1,criterion);
- SIVAL(p,5,timeup*1000); /* ms - Despite what the spec says. */
- p += 13;
- pstrcpy(p,server_name);
- strupper(p);
- p = skip_string(p,1);
-
- send_mailslot(False, BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
- server_name, 0,
- workgroup_name, 0x1e,
- subrec->bcast_ip, subrec->myip);
-}
-
-/*******************************************************************
- We found a current master browser on one of our broadcast interfaces.
-******************************************************************/
-
-static void check_for_master_browser_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *answer_name,
- struct in_addr answer_ip, struct res_rec *rrec)
-{
- DEBUG(3,("check_for_master_browser_success: Local master browser for workgroup %s exists at \
-IP %s (just checking).\n", answer_name->name, inet_ntoa(answer_ip) ));
-}
-
-/*******************************************************************
- We failed to find a current master browser on one of our broadcast interfaces.
-******************************************************************/
-
-static void check_for_master_browser_fail( struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *question_name,
- int fail_code)
-{
- char *workgroup_name = question_name->name;
- struct work_record *work = find_workgroup_on_subnet(subrec, workgroup_name);
-
- if(work == NULL)
- {
- DEBUG(0,("check_for_master_browser_fail: Unable to find workgroup %s on subnet %s.=\n",
- workgroup_name, subrec->subnet_name ));
- return;
- }
-
- if (strequal(work->work_group, myworkgroup))
- {
-
- if (lp_local_master())
- {
- /* We have discovered that there is no local master
- browser, and we are configured to initiate
- an election that we will participate in.
- */
- DEBUG(2,("check_for_master_browser_fail: Forcing election on workgroup %s subnet %s\n",
- work->work_group, subrec->subnet_name ));
-
- /* Setting this means we will participate when the
- election is run in run_elections(). */
- work->needelection = True;
- }
- else
- {
- /* We need to force an election, because we are configured
- not to become the local master, but we still need one,
- having detected that one doesn't exist.
- */
- send_election_dgram(subrec, work->work_group, 0, 0, myname);
- }
- }
-}
-
-/*******************************************************************
- Ensure there is a local master browser for a workgroup on our
- broadcast interfaces.
-******************************************************************/
-
-void check_master_browser_exists(time_t t)
-{
- static time_t lastrun=0;
- struct subnet_record *subrec;
- char *workgroup_name = myworkgroup;
-
- if (!lastrun)
- lastrun = t;
-
- if (t < (lastrun + (CHECK_TIME_MST_BROWSE * 60)))
- return;
-
- lastrun = t;
-
- dump_workgroups();
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work;
-
- for (work = subrec->workgrouplist; work; work = work->next)
- {
- if (strequal(work->work_group, workgroup_name) && !AM_LOCAL_MASTER_BROWSER(work))
- {
- /* Do a name query for the local master browser on this net. */
- query_name( subrec, work->work_group, 0x1d,
- check_for_master_browser_success,
- check_for_master_browser_fail,
- NULL);
- }
- }
- }
-}
-
-/*******************************************************************
- Run an election.
-******************************************************************/
-
-void run_elections(time_t t)
-{
- static time_t lastime = 0;
-
- struct subnet_record *subrec;
-
- /* Send election packets once a second - note */
- if (lastime && (t - lastime <= 0))
- return;
-
- lastime = t;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work;
-
- for (work = subrec->workgrouplist; work; work = work->next)
- {
- if (work->RunningElection)
- {
- send_election_dgram(subrec, work->work_group, work->ElectionCriterion,
- t - StartupTime, myname);
-
- 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",
- work->work_group, subrec->subnet_name ));
-
- work->RunningElection = False;
-
- become_local_master_browser(subrec, work);
- }
- }
- }
- }
-}
-
-/*******************************************************************
- Determine if I win an election.
-******************************************************************/
-
-static BOOL win_election(struct work_record *work, int version,
- uint32 criterion, int timeup, char *server_name)
-{
- int mytimeup = time(NULL) - StartupTime;
- uint32 mycriterion = work->ElectionCriterion;
-
- /* If local master is false then never win
- in election broadcasts. */
- if(!lp_local_master())
- {
- DEBUG(3,("win_election: Losing election as local master == False\n"));
- return False;
- }
-
- DEBUG(4,("win_election: election comparison: %x:%x %x:%x %d:%d %s:%s\n",
- version, ELECTION_VERSION,
- criterion, mycriterion,
- timeup, mytimeup,
- server_name, myname));
-
- if (version > ELECTION_VERSION)
- return(False);
- if (version < ELECTION_VERSION)
- return(True);
-
- if (criterion > mycriterion)
- return(False);
- if (criterion < mycriterion)
- return(True);
-
- if (timeup > mytimeup)
- return(False);
- if (timeup < mytimeup)
- return(True);
-
- if (strcasecmp(myname, server_name) > 0)
- return(False);
-
- return(True);
-}
-
-/*******************************************************************
- Process an incoming election datagram packet.
-******************************************************************/
-
-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);
- int timeup = IVAL(buf,5)/1000;
- char *server_name = buf+13;
- struct work_record *work;
- char *workgroup_name = dgram->dest_name.name;
-
- server_name[15] = 0;
-
- DEBUG(3,("process_election: Election request from %s at IP %s on subnet %s for workgroup %s.\n",
- server_name,inet_ntoa(p->ip), subrec->subnet_name, workgroup_name ));
-
- DEBUG(5,("process_election: vers=%d criterion=%08x timeup=%d\n", version,criterion,timeup));
-
- if(( work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL)
- {
- DEBUG(0,("process_election: Cannot find workgroup %s on subnet %s.\n",
- workgroup_name, subrec->subnet_name ));
- return;
- }
-
- if (!strequal(work->work_group, myworkgroup))
- {
- DEBUG(3,("process_election: ignoring election request for workgroup %s on subnet %s as this \
-is not my workgroup.\n", work->work_group, subrec->subnet_name ));
- return;
- }
-
- if (win_election(work, version,criterion,timeup,server_name))
- {
- /* We take precedence over the requesting server. */
- if (!work->RunningElection)
- {
- /* We weren't running an election - start running one. */
-
- work->needelection = True;
- work->ElectionCount=0;
- }
-
- /* Note that if we were running an election for this workgroup on this
- subnet already, we just ignore the server we take precedence over. */
- }
- else
- {
- /* We lost. Stop participating. */
- work->needelection = False;
-
- if (work->RunningElection || AM_LOCAL_MASTER_BROWSER(work))
- {
- work->RunningElection = False;
- DEBUG(3,("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);
- }
- }
-}
-
-/****************************************************************************
- This function looks over all the workgroups known on all the broadcast
- subnets and decides if a browser election is to be run on that workgroup.
- It returns True if any election packets need to be sent (this will then
- be done by run_elections().
-***************************************************************************/
-
-BOOL check_elections(void)
-{
- struct subnet_record *subrec;
- BOOL run_any_election = False;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work;
- for (work = subrec->workgrouplist; work; work = work->next)
- {
- run_any_election |= work->RunningElection;
-
- /* Only start an election if we are in the potential browser state. */
- if (work->needelection && !work->RunningElection && AM_POTENTIAL_MASTER_BROWSER(work))
- {
- DEBUG(3,("check_elections: >>> Starting election for workgroup %s on subnet %s <<<\n",
- work->work_group, subrec->subnet_name ));
-
- work->ElectionCount = 0;
- work->RunningElection = True;
- work->needelection = False;
- }
- }
- }
- return run_any_election;
-}
diff --git a/source/nmbd/nmbd_incomingdgrams.c b/source/nmbd/nmbd_incomingdgrams.c
deleted file mode 100644
index 452516b64ee..00000000000
--- a/source/nmbd/nmbd_incomingdgrams.c
+++ /dev/null
@@ -1,769 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-extern pstring myname;
-extern fstring myworkgroup;
-extern BOOL found_lm_clients;
-
-#if 0
-
-/* XXXX note: This function is currently unsuitable for use, as it
- does not properly check that a server is in a fit state to become
- a backup browser before asking it to be one.
- The code is left here to be worked on at a later date.
-*/
-
-/****************************************************************************
-Tell a server to become a backup browser
-**************************************************************************/
-
-void tell_become_backup(void)
-{
- struct subnet_record *subrec;
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work;
- for (work = subrec->workgrouplist; work; work = work->next)
- {
- struct server_record *servrec;
- int num_servers = 0;
- int num_backups = 0;
-
- for (servrec = work->serverlist; servrec; servrec = servrec->next)
- {
- num_servers++;
-
- if (is_myname(servrec->serv.name))
- continue;
-
- if (servrec->serv.type & SV_TYPE_BACKUP_BROWSER)
- {
- num_backups++;
- continue;
- }
-
- if (servrec->serv.type & SV_TYPE_MASTER_BROWSER)
- continue;
-
- if (!(servrec->serv.type & SV_TYPE_POTENTIAL_BROWSER))
- continue;
-
- DEBUG(3,("num servers: %d num backups: %d\n",
- num_servers, num_backups));
-
- /* make first server a backup server. thereafter make every
- tenth server a backup server */
- if (num_backups != 0 && (num_servers+9) / num_backups > 10)
- continue;
-
- DEBUG(2,("sending become backup to %s %s for %s\n",
- servrec->serv.name, inet_ntoa(subrec->bcast_ip),
- work->work_group));
-
- /* type 11 request from MYNAME(20) to WG(1e) for SERVER */
- do_announce_request(servrec->serv.name, work->work_group,
- ANN_BecomeBackup, 0x20, 0x1e, subrec->bcast_ip);
- }
- }
- }
-}
-#endif
-
-/*******************************************************************
- Process an incoming host announcement packet.
-*******************************************************************/
-
-void process_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int ttl = IVAL(buf,1)/1000;
- char *announce_name = buf+5;
- uint32 servertype = IVAL(buf,23);
- char *comment = buf+31;
- struct work_record *work;
- struct server_record *servrec;
- char *work_name;
- char *source_name = dgram->source_name.name;
-
- comment[43] = 0;
-
- DEBUG(3,("process_host_announce: from %s<%02x> IP %s to \
-%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
- namestr(&dgram->dest_name),announce_name));
-
- DEBUG(5,("process_host_announce: ttl=%d server type=%08x comment=%s\n",
- ttl, servertype,comment));
-
- /* Filter servertype to remove impossible bits. */
- servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
-
- /* A host announcement must be sent to the name WORKGROUP<1d>. */
- if(dgram->dest_name.name_type != 0x1d)
- {
- DEBUG(2,("process_host_announce: incorrect name type for destination from IP %s \
-(was %02x) should be 0x1d. Allowing packet anyway.\n",
- inet_ntoa(p->ip), dgram->dest_name.name_type));
- /* Change it so it was. */
- dgram->dest_name.name_type = 0x1d;
- }
-
- /* For a host announce the workgroup name is the destination name. */
- work_name = dgram->dest_name.name;
-
- /*
- * Syntax servers version 5.1 send HostAnnounce packets to
- * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>
- * instead of WORKGROUP<1d> name. So to fix this we check if
- * the workgroup name is our own name, and if so change it
- * to be our primary workgroup name.
- */
-
- if(strequal(work_name, myname))
- work_name = myworkgroup;
-
- /*
- * We are being very agressive here in adding a workgroup
- * name on the basis of a host announcing itself as being
- * in that workgroup. Maybe we should wait for the workgroup
- * announce instead ? JRA.
- */
-
- if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL)
- {
- /* We have no record of this workgroup. Add it. */
- if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
- return;
- }
-
- if((servrec = find_server_in_workgroup( work, announce_name))==NULL)
- {
- /* If this server is not already in the workgroup, add it. */
- create_server_on_workgroup(work, announce_name,
- servertype|SV_TYPE_LOCAL_LIST_ONLY,
- ttl, comment);
- }
- else
- {
- /* Update the record. */
- servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
- update_server_ttl( servrec, ttl);
- StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1);
- }
-
- subrec->work_changed = True;
-}
-
-/*******************************************************************
- Process an incoming WORKGROUP announcement packet.
-*******************************************************************/
-
-void process_workgroup_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int ttl = IVAL(buf,1)/1000;
- char *workgroup_announce_name = buf+5;
- uint32 servertype = IVAL(buf,23);
- char *master_name = buf+31;
- struct work_record *work;
- char *source_name = dgram->source_name.name;
-
- master_name[43] = 0;
-
- DEBUG(3,("process_workgroup_announce: from %s<%02x> IP %s to \
-%s for workgroup %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
- namestr(&dgram->dest_name),workgroup_announce_name));
-
- DEBUG(5,("process_workgroup_announce: ttl=%d server type=%08x master browser=%s\n",
- ttl, servertype, master_name));
-
- /* Workgroup announcements must only go to the MSBROWSE name. */
- if (!strequal(dgram->dest_name.name, MSBROWSE) || (dgram->dest_name.name_type != 0x1))
- {
- DEBUG(0,("process_workgroup_announce: from IP %s should be to __MSBROWSE__<0x01> not %s\n",
- inet_ntoa(p->ip), namestr(&dgram->dest_name)));
- return;
- }
-
- if ((work = find_workgroup_on_subnet(subrec, workgroup_announce_name))==NULL)
- {
- /* We have no record of this workgroup. Add it. */
- if((work = create_workgroup_on_subnet(subrec, workgroup_announce_name, ttl))==NULL)
- return;
- }
- else
- {
- /* Update the workgroup death_time. */
- update_workgroup_ttl(work, ttl);
- }
-
- if(*work->local_master_browser_name == '\0')
- {
- /* Set the master browser name. */
- set_workgroup_local_master_browser_name( work, master_name );
- }
-
- subrec->work_changed = True;
-}
-
-/*******************************************************************
- Process an incoming local master browser announcement packet.
-*******************************************************************/
-
-void process_local_master_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int ttl = IVAL(buf,1)/1000;
- char *server_name = buf+5;
- uint32 servertype = IVAL(buf,23);
- char *comment = buf+31;
- char *work_name;
- struct work_record *work;
- struct server_record *servrec;
- char *source_name = dgram->source_name.name;
-
- comment[43] = 0;
-
- DEBUG(3,("process_local_master_announce: from %s<%02x> IP %s to \
-%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
- namestr(&dgram->dest_name),server_name));
-
- DEBUG(5,("process_local_master_announce: ttl=%d server type=%08x comment=%s\n",
- ttl, servertype, comment));
-
- /* A local master announcement must be sent to the name WORKGROUP<1e>. */
- if(dgram->dest_name.name_type != 0x1e)
- {
- DEBUG(0,("process_local_master_announce: incorrect name type for destination from IP %s \
-(was %02x) should be 0x1e. Ignoring packet.\n",
- inet_ntoa(p->ip), dgram->dest_name.name_type));
- return;
- }
-
- /* Filter servertype to remove impossible bits. */
- servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
-
- /* For a local master announce the workgroup name is the destination name. */
- work_name = dgram->dest_name.name;
-
- if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL)
- {
- /* We have no record of this workgroup. Add it. */
- if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
- return;
- }
-
- /* If we think we're the local master browser for this workgroup,
- we should never have got this packet. We don't see our own
- packets.
- */
- if(AM_LOCAL_MASTER_BROWSER(work))
- {
- DEBUG(0,("process_local_master_announce: Server %s at IP %s is announcing itself as \
-a local master browser for workgroup %s and we think we are master. Forcing election.\n",
- server_name, inet_ntoa(p->ip), work_name));
-
- /* Samba nmbd versions 1.9.17 to 1.9.17p4 have a bug in that when
- they have become a local master browser once, they will never
- stop sending local master announcements. To fix this we send
- them a reset browser packet, with level 0x2 on the __SAMBA__
- name that only they should be listening to. */
-
- send_browser_reset( 0x2, "__SAMBA__" , 0x20, p->ip);
-
- /* We should demote ourself and force an election. */
-
- unbecome_local_master_browser( subrec, work);
-
- /* The actual election requests are handled in
- nmbd_election.c */
-
- work->needelection = True;
- return;
- }
-
- /* Find the server record on this workgroup. If it doesn't exist, add it. */
-
- if((servrec = find_server_in_workgroup( work, server_name))==NULL)
- {
- /* If this server is not already in the workgroup, add it. */
- create_server_on_workgroup(work, server_name,
- servertype|SV_TYPE_LOCAL_LIST_ONLY,
- ttl, comment);
- }
- else
- {
- /* Update the record. */
- servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
- update_server_ttl(servrec, ttl);
- StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1);
- }
-
- set_workgroup_local_master_browser_name( work, server_name );
-
- subrec->work_changed = True;
-}
-
-/*******************************************************************
- Process a domain master announcement frame.
- Domain master browsers receive these from local masters. The Domain
- master should then issue a sync with the local master, asking for
- that machines local server list.
-******************************************************************/
-
-void process_master_browser_announce(struct subnet_record *subrec,
- struct packet_struct *p,char *buf)
-{
- char *local_master_name = buf;
- struct work_record *work;
- struct browse_cache_record *browrec;
-
- local_master_name[15] = 0;
-
- DEBUG(3,("process_master_browser_announce: Local master announce from %s IP %s.\n",
- local_master_name, inet_ntoa(p->ip)));
-
- if (!lp_domain_master())
- {
- DEBUG(0,("process_master_browser_announce: Not configured as domain \
-master - ignoring master announce.\n"));
- return;
- }
-
- if((work = find_workgroup_on_subnet(subrec, myworkgroup)) == NULL)
- {
- DEBUG(0,("process_master_browser_announce: Cannot find workgroup %s on subnet %s\n",
- myworkgroup, subrec->subnet_name));
- return;
- }
-
- if(!AM_DOMAIN_MASTER_BROWSER(work))
- {
- DEBUG(0,("process_master_browser_announce: Local master announce made to us from \
-%s IP %s and we are not a domain master browser.\n", local_master_name, inet_ntoa(p->ip)));
- return;
- }
-
- /* Add this host as a local master browser entry on the browse lists.
- This causes a sync request to be made to it at a later date.
- */
-
- if((browrec = find_browser_in_lmb_cache( local_master_name )) == NULL)
- {
- /* Add it. */
- create_browser_in_lmb_cache( work->work_group, local_master_name, p->ip);
- }
- else
- update_browser_death_time(browrec);
-}
-
-/*******************************************************************
- Process an incoming LanMan host announcement packet.
-*******************************************************************/
-
-void process_lm_host_announce(struct subnet_record *subrec, struct packet_struct *p, char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- uint32 servertype = IVAL(buf,1);
- int osmajor=CVAL(buf,5); /* major version of node software */
- int osminor=CVAL(buf,6); /* minor version of node software */
- int ttl = SVAL(buf,7);
- char *announce_name = buf+9;
- struct work_record *work;
- struct server_record *servrec;
- char *work_name;
- char *source_name = dgram->source_name.name;
- pstring comment;
- char *s = buf+9;
-
- s = skip_string(s,1);
- StrnCpy(comment, s, 43);
-
- DEBUG(3,("process_lm_host_announce: LM Announcement from %s<%02x> IP %s to \
-%s for server %s.\n", source_name, source_name[15], inet_ntoa(p->ip),
- namestr(&dgram->dest_name),announce_name));
-
- DEBUG(5,("process_lm_host_announce: os=(%d,%d) ttl=%d server type=%08x comment=%s\n",
- osmajor, osminor, ttl, servertype,comment));
-
- if ((osmajor < 36) || (osmajor > 38) || (osminor !=0))
- {
- DEBUG(5,("process_lm_host_announce: LM Announcement packet does not " \
- "originate from OS/2 Warp client. Ignoring packet.\n"));
- /* Could have been from a Windows machine (with its LM Announce enabled),
- or a Samba server. Then don't disrupt the current browse list. */
- return;
- }
-
- /* Filter servertype to remove impossible bits. */
- servertype &= ~(SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM);
-
- /* A LanMan host announcement must be sent to the name WORKGROUP<00>. */
- if(dgram->dest_name.name_type != 0x00)
- {
- DEBUG(2,("process_lm_host_announce: incorrect name type for destination from IP %s \
-(was %02x) should be 0x00. Allowing packet anyway.\n",
- inet_ntoa(p->ip), dgram->dest_name.name_type));
- /* Change it so it was. */
- dgram->dest_name.name_type = 0x00;
- }
-
- /* For a LanMan host announce the workgroup name is the destination name. */
- work_name = dgram->dest_name.name;
-
- /*
- * Syntax servers version 5.1 send HostAnnounce packets to
- * *THE WRONG NAME*. They send to LOCAL_MASTER_BROWSER_NAME<00>
- * instead of WORKGROUP<1d> name. So to fix this we check if
- * the workgroup name is our own name, and if so change it
- * to be our primary workgroup name. This code is probably
- * not needed in the LanMan announce code, but it won't hurt.
- */
-
- if(strequal(work_name, myname))
- work_name = myworkgroup;
-
- /*
- * We are being very agressive here in adding a workgroup
- * name on the basis of a host announcing itself as being
- * in that workgroup. Maybe we should wait for the workgroup
- * announce instead ? JRA.
- */
-
- if ((work = find_workgroup_on_subnet(subrec, work_name))==NULL)
- {
- /* We have no record of this workgroup. Add it. */
- if((work = create_workgroup_on_subnet(subrec, work_name, ttl))==NULL)
- return;
- }
-
- if((servrec = find_server_in_workgroup( work, announce_name))==NULL)
- {
- /* If this server is not already in the workgroup, add it. */
- create_server_on_workgroup(work, announce_name,
- servertype|SV_TYPE_LOCAL_LIST_ONLY,
- ttl, comment);
- }
- else
- {
- /* Update the record. */
- servrec->serv.type = servertype|SV_TYPE_LOCAL_LIST_ONLY;
- update_server_ttl( servrec, ttl);
- StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1);
- }
-
- subrec->work_changed = True;
- found_lm_clients = True;
-}
-
-/****************************************************************************
- Send a backup list response.
-*****************************************************************************/
-
-static void send_backup_list_response(struct subnet_record *subrec,
- struct work_record *work,
- struct nmb_name *send_to_name,
- unsigned char max_number_requested,
- uint32 token, struct in_addr sendto_ip)
-{
- char outbuf[1024];
- char *p, *countptr, *nameptr;
- int count = 0;
- int len;
- struct server_record *servrec;
-
- bzero(outbuf,sizeof(outbuf));
-
- DEBUG(3,("send_backup_list_response: sending backup list for workgroup %s to %s IP %s\n",
- work->work_group, namestr(send_to_name), inet_ntoa(sendto_ip)));
-
- p = outbuf;
-
- SCVAL(p,0,ANN_GetBackupListResp); /* Backup list response opcode. */
- p++;
-
- countptr = p;
- p++;
-
- SIVAL(p,0,token); /* The sender's unique info. */
- p += 4;
-
- nameptr = p;
-
- /* We always return at least one name - our own. */
- count = 1;
- StrnCpy(p,myname,15);
- strupper(p);
- p = skip_string(p,1);
-
- /* Look for backup browsers in this workgroup. */
- for (servrec = work->serverlist; servrec; servrec = servrec->next)
- {
- len = PTR_DIFF(p, outbuf);
- if((sizeof(outbuf) - len) < 16)
- break;
-
- if(count >= max_number_requested)
- break;
-
- if(strnequal(servrec->serv.name, myname,15))
- continue;
-
- if(!(servrec->serv.type & SV_TYPE_BACKUP_BROWSER))
- continue;
-
- StrnCpy(p, servrec->serv.name, 15);
- strupper(p);
- count++;
-
- DEBUG(5,("send_backup_list_response: Adding server %s number %d\n",
- p, count));
-
- p = skip_string(p,1);
- }
-
- SCVAL(countptr, 0, count);
-
- len = PTR_DIFF(p, outbuf);
-
- DEBUG(4,("send_backup_list_response: sending response to %s<00> IP %s with %d servers.\n",
- send_to_name->name, inet_ntoa(sendto_ip), count));
-
- send_mailslot(True, BROWSE_MAILSLOT,
- outbuf,PTR_DIFF(p,outbuf),
- myname, 0,
- send_to_name->name,0,
- sendto_ip, subrec->myip);
-}
-
-/*******************************************************************
- Process a send backup list request packet.
-
- A client sends a backup list request to ask for a list of servers on
- the net that maintain server lists for a domain. A server is then
- chosen from this list to send NetServerEnum commands to to list
- available servers.
-
-********************************************************************/
-
-void process_get_backup_list_request(struct subnet_record *subrec,
- struct packet_struct *p,char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- struct work_record *work;
- unsigned char max_number_requested = CVAL(buf,0);
- uint32 token = IVAL(buf,1); /* Sender's key index for the workgroup. */
- int name_type = dgram->dest_name.name_type;
- char *workgroup_name = dgram->dest_name.name;
-
- DEBUG(3,("process_get_backup_list_request: request from %s IP %s to %s.\n",
- namestr(&dgram->source_name), inet_ntoa(p->ip),
- namestr(&dgram->dest_name)));
-
- /* We have to be a master browser, or a domain master browser
- for the requested workgroup. That means it must be our
- workgroup. */
-
- if(strequal(workgroup_name, myworkgroup) == False)
- {
- DEBUG(7,("process_get_backup_list_request: Ignoring announce request for workgroup %s.\n",
- workgroup_name));
- return;
- }
-
- if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL)
- {
- DEBUG(0,("process_get_backup_list_request: Cannot find workgroup %s on \
-subnet %s.\n", workgroup_name, subrec->subnet_name));
- return;
- }
-
- if(name_type == 0x1b)
- {
- /* We must be a domain master browser in order to
- process this packet. */
-
- if(!AM_DOMAIN_MASTER_BROWSER(work))
- {
- DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \
-and I am not a domain master browser.\n", workgroup_name));
- return;
- }
- }
- else if (name_type == 0x1d)
- {
- /* We must be a local master browser in order to
- process this packet. */
-
- if(!AM_LOCAL_MASTER_BROWSER(work))
- {
- DEBUG(0,("process_get_backup_list_request: domain list requested for workgroup %s \
-and I am not a local master browser.\n", workgroup_name));
- return;
- }
- }
- else
- {
- DEBUG(0,("process_get_backup_list_request: Invalid name type %x - should be 0x1b or 0x1d.\n",
- name_type));
- return;
- }
-
- send_backup_list_response(subrec, work, &dgram->source_name,
- max_number_requested, token, p->ip);
-}
-
-/*******************************************************************
- Process a reset browser state packet.
-
- Diagnostic packet:
- 0x1 - Stop being a master browser and become a backup browser.
- 0x2 - Discard browse lists, stop being a master browser, try again.
- 0x4 - Stop being a master browser forever.
-
-******************************************************************/
-
-void process_reset_browser(struct subnet_record *subrec,
- struct packet_struct *p,char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int state = CVAL(buf,0);
- struct subnet_record *sr;
-
- DEBUG(1,("process_reset_browser: received diagnostic browser reset \
-request from %s IP %s state=0x%X\n",
- namestr(&dgram->source_name), inet_ntoa(p->ip), state));
-
- /* Stop being a local master browser on all our broadcast subnets. */
- if (state & 0x1)
- {
- for (sr = FIRST_SUBNET; sr; sr = NEXT_SUBNET_EXCLUDING_UNICAST(sr))
- {
- struct work_record *work;
- for (work = sr->workgrouplist; work; work = work->next)
- {
- if (AM_LOCAL_MASTER_BROWSER(work))
- {
- unbecome_local_master_browser(sr, work);
- work->needelection = True;
- }
- }
- }
- }
-
- /* Discard our browse lists. */
- if (state & 0x2)
- {
- /*
- * Calling expire_workgroups_and_servers with a -1
- * time causes all servers not marked with a PERMANENT_TTL
- * on the workgroup lists to be discarded, and all
- * workgroups with empty server lists to be discarded.
- * This means we keep our own server names and workgroup
- * as these have a PERMANENT_TTL.
- */
-
- expire_workgroups_and_servers(-1);
- }
-
- /* Request to stop browsing altogether. */
- if (state & 0x4)
- DEBUG(1,("process_reset_browser: ignoring request to stop being a browser.\n"));
-}
-
-/*******************************************************************
- Process an announcement request packet.
- We don't respond immediately, we just check it's a request for
- our workgroup and then set the flag telling the announce code
- in nmbd_sendannounce.c:announce_my_server_names that an
- announcement is needed soon.
-******************************************************************/
-
-void process_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- struct work_record *work;
- char *workgroup_name = dgram->dest_name.name;
-
- DEBUG(3,("process_announce_request: Announce request from %s IP %s to %s.\n",
- namestr(&dgram->source_name), inet_ntoa(p->ip),
- namestr(&dgram->dest_name)));
-
- /* We only send announcement requests on our workgroup. */
- if(strequal(workgroup_name, myworkgroup) == False)
- {
- DEBUG(7,("process_announce_request: Ignoring announce request for workgroup %s.\n",
- workgroup_name));
- return;
- }
-
- if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL)
- {
- DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",
- workgroup_name));
- return;
- }
-
- work->needannounce = True;
-}
-
-/*******************************************************************
- Process a LanMan announcement request packet.
- We don't respond immediately, we just check it's a request for
- our workgroup and then set the flag telling that we have found
- a LanMan client (DOS or OS/2) and that we will have to start
- sending LanMan announcements (unless specifically disabled
- through the "lm_announce" parameter in smb.conf)
-******************************************************************/
-
-void process_lm_announce_request(struct subnet_record *subrec, struct packet_struct *p, char *buf)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- struct work_record *work;
- char *workgroup_name = dgram->dest_name.name;
-
- DEBUG(3,("process_lm_announce_request: Announce request from %s IP %s to %s.\n",
- namestr(&dgram->source_name), inet_ntoa(p->ip),
- namestr(&dgram->dest_name)));
-
- /* We only send announcement requests on our workgroup. */
- if(strequal(workgroup_name, myworkgroup) == False)
- {
- DEBUG(7,("process_lm_announce_request: Ignoring announce request for workgroup %s.\n",
- workgroup_name));
- return;
- }
-
- if((work = find_workgroup_on_subnet(subrec, workgroup_name)) == NULL)
- {
- DEBUG(0,("process_announce_request: Unable to find workgroup %s on subnet !\n",
- workgroup_name));
- return;
- }
-
- found_lm_clients = True;
-}
diff --git a/source/nmbd/nmbd_incomingrequests.c b/source/nmbd/nmbd_incomingrequests.c
deleted file mode 100644
index 73abdf00504..00000000000
--- a/source/nmbd/nmbd_incomingrequests.c
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
- This file contains all the code to process NetBIOS requests coming
- in on port 137. It does not deal with the code needed to service
- WINS server requests, but only broadcast and unicast requests.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-/****************************************************************************
-Send a name release response.
-**************************************************************************/
-
-static void send_name_release_response(int rcode, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- char rdata[6];
-
- memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- NMB_REL, /* nmbd type code. */
- NMB_NAME_RELEASE_OPCODE, /* opcode. */
- 0, /* ttl. */
- rdata, /* data to send. */
- 6); /* data length. */
-}
-
-/****************************************************************************
-Process a name release packet on a broadcast subnet.
-Ignore it if it's not one of our names.
-****************************************************************************/
-
-void process_name_release_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct in_addr owner_ip;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- BOOL group = (nb_flags & NB_GROUP) ? True : False;
- struct name_record *namerec;
- int rcode = 0;
-
- putip((char *)&owner_ip,&nmb->additional->rdata[2]);
-
- if(!bcast)
- {
- /* We should only get broadcast name release packets here.
- Anyone trying to release unicast should be going to a WINS
- server. If the code gets here, then either we are not a wins
- server and they sent it anyway, or we are a WINS server and
- the request was malformed. Either way, log an error here.
- and send an error reply back.
- */
- DEBUG(0,("process_name_release_request: unicast name release request \
-received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
- namestr(question), inet_ntoa(owner_ip), subrec->subnet_name));
-
- send_name_release_response(FMT_ERR, p);
- return;
- }
-
- DEBUG(3,("process_name_release_request: Name release on name %s, \
-subnet %s from owner IP %s\n",
- namestr(&nmb->question.question_name),
- subrec->subnet_name, inet_ntoa(owner_ip)));
-
- /* If someone is releasing a broadcast group name, just ignore it. */
- if( group && !ismyip(owner_ip) )
- return;
-
- namerec = find_name_on_subnet(subrec, &nmb->question.question_name, FIND_ANY_NAME);
-
- /* We only care about someone trying to release one of our names. */
- if (namerec && ((namerec->source == SELF_NAME) || (namerec->source == PERMANENT_NAME)))
- {
- rcode = ACT_ERR;
- DEBUG(0, ("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",
- namestr(&nmb->question.question_name), inet_ntoa(owner_ip), subrec->subnet_name));
- }
-
- if(rcode == 0)
- return;
-
- /* Send a NAME RELEASE RESPONSE (pos/neg) see rfc1002.txt 4.2.10-11 */
- send_name_release_response(rcode, p);
-}
-
-/****************************************************************************
-Send a name registration response.
-**************************************************************************/
-
-static void send_name_registration_response(int rcode, int ttl, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- char rdata[6];
-
- memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- NMB_REG, /* nmbd type code. */
- NMB_NAME_REG_OPCODE, /* opcode. */
- ttl, /* ttl. */
- rdata, /* data to send. */
- 6); /* data length. */
-}
-
-/****************************************************************************
-Process a name refresh request on a broadcast subnet.
-**************************************************************************/
-
-void process_name_refresh_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
-
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- struct in_addr from_ip;
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
-
- if(!bcast)
- {
- /* We should only get broadcast name refresh packets here.
- Anyone trying to refresh unicast should be going to a WINS
- server. If the code gets here, then either we are not a wins
- server and they sent it anyway, or we are a WINS server and
- 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 \
-received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
- namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
-
- send_name_registration_response(FMT_ERR, 0, p);
- return;
- }
-
- /* Just log a message. We really don't care about broadcast name
- refreshes. */
-
- DEBUG(3,("process_name_refresh_request: Name refresh for name %s \
-IP %s on subnet %s\n", namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
-
-}
-
-/****************************************************************************
-Process a name registration request on a broadcast subnet.
-**************************************************************************/
-
-void process_name_registration_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- BOOL group = (nb_flags & NB_GROUP) ? True : False;
- struct name_record *namerec = NULL;
- int ttl = nmb->additional->ttl;
- struct in_addr from_ip;
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
-
- if(!bcast)
- {
- /* We should only get broadcast name registration packets here.
- Anyone trying to register unicast should be going to a WINS
- server. If the code gets here, then either we are not a wins
- server and they sent it anyway, or we are a WINS server and
- the request was malformed. Either way, log an error here.
- and send an error reply back.
- */
- DEBUG(0,("process_name_registration_request: unicast name registration request \
-received for name %s from IP %s on subnet %s. Error - should be sent to WINS server\n",
- namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
-
- send_name_registration_response(FMT_ERR, 0, p);
- return;
- }
-
- DEBUG(3,("process_name_registration_request: Name registration for name %s \
-IP %s on subnet %s\n", namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
-
- /* See if the name already exists. */
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- /*
- * If the name being registered exists and is a WINS_PROXY_NAME
- * then delete the WINS proxy name entry so we don't reply erroneously
- * later to queries.
- */
-
- if((namerec != NULL) && (namerec->source == WINS_PROXY_NAME))
- {
- remove_name_from_namelist( subrec, namerec );
- namerec = NULL;
- }
-
- if (!group)
- {
- /* Unique name. */
-
- if ((namerec != NULL) &&
- ((namerec->source == SELF_NAME) || (namerec->source == PERMANENT_NAME) ||
- NAME_GROUP(namerec))
- )
- {
- /* No-one can register one of Samba's names, nor can they
- register a name that's a group name as a unique name */
-
- send_name_registration_response(ACT_ERR, 0, p);
- return;
- }
- else if(namerec != NULL)
- {
- /* Update the namelist record with the new information. */
- namerec->ip[0] = from_ip;
- update_name_ttl(namerec, ttl);
-
- DEBUG(3,("process_name_registration_request: Updated name record %s \
-with IP %s on subnet %s\n",namestr(&namerec->name),inet_ntoa(from_ip), subrec->subnet_name));
- return;
- }
- }
- else
- {
- /* Group name. */
-
- if((namerec != NULL) && !NAME_GROUP(namerec) &&
- ((namerec->source == SELF_NAME) || (namerec->source == PERMANENT_NAME))
- )
- {
- /* Disallow group names when we have a unique name. */
- send_name_registration_response(ACT_ERR, 0, p);
- return;
- }
- }
-}
-
-/****************************************************************************
-This is used to sort names for a name status into a sensible order.
-We put our own names first, then in alphabetical order.
-**************************************************************************/
-
-static int status_compare(char *n1,char *n2)
-{
- extern pstring myname;
- int l1,l2,l3;
-
- /* It's a bit tricky because the names are space padded */
- for (l1=0;l1<15 && n1[l1] && n1[l1] != ' ';l1++) ;
- for (l2=0;l2<15 && n2[l2] && n2[l2] != ' ';l2++) ;
- l3 = strlen(myname);
-
- if ((l1==l3) && strncmp(n1,myname,l3) == 0 &&
- (l2!=l3 || strncmp(n2,myname,l3) != 0))
- return -1;
-
- if ((l2==l3) && strncmp(n2,myname,l3) == 0 &&
- (l1!=l3 || strncmp(n1,myname,l3) != 0))
- return 1;
-
- return memcmp(n1,n2,18);
-}
-
-
-/****************************************************************************
- Process a node status query
- ****************************************************************************/
-
-void process_node_status_request(struct subnet_record *subrec, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- char *qname = nmb->question.question_name.name;
- int ques_type = nmb->question.question_name.name_type;
- char rdata[MAX_DGRAM_SIZE];
- char *countptr, *buf, *bufend, *buf0;
- int names_added,i;
- struct name_record *namerec;
-
- DEBUG(3,("process_node_status_request: status request for name %s from IP %s on \
-subnet %s.\n", namestr(&nmb->question.question_name), inet_ntoa(p->ip),
- subrec->subnet_name));
-
- 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 \
-subnet %s - name not found.\n", namestr(&nmb->question.question_name),
- inet_ntoa(p->ip), subrec->subnet_name));
-
- return;
- }
-
- /* XXXX hack, we should calculate exactly how many will fit. */
- bufend = &rdata[MAX_DGRAM_SIZE] - 18;
- countptr = buf = rdata;
- buf += 1;
- buf0 = buf;
-
- names_added = 0;
-
- namerec = subrec->namelist;
-
- while (buf < bufend)
- {
- if ((namerec->source == SELF_NAME) || (namerec->source == PERMANENT_NAME))
- {
- int name_type = namerec->name.name_type;
-
- if (!strequal(namerec->name.name,"*") &&
- !strequal(namerec->name.name,"__SAMBA__") &&
- (name_type < 0x1b || name_type >= 0x20 ||
- ques_type < 0x1b || ques_type >= 0x20 ||
- strequal(qname, namerec->name.name)))
- {
- /* Start with the name. */
- bzero(buf,18);
- sprintf(buf,"%-15.15s",namerec->name.name);
- strupper(buf);
-
- /* Put the name type and netbios flags in the buffer. */
- buf[15] = name_type;
- set_nb_flags(&buf[16],namerec->nb_flags);
- buf[16] |= NB_ACTIVE; /* all our names are active */
-
- buf += 18;
-
- names_added++;
- }
- }
-
- /* Remove duplicate names. */
- qsort(buf0,names_added,18,QSORT_CAST status_compare);
-
- for (i=1;i<names_added;i++)
- {
- if (memcmp(buf0 + 18*i,buf0 + 18*(i-1),16) == 0)
- {
- names_added--;
- if (names_added == i)
- break;
- memmove(buf0 + 18*i,buf0 + 18*(i+1),18*(names_added-i));
- i--;
- }
- }
-
- buf = buf0 + 18*names_added;
-
- namerec = namerec->next;
-
- if (!namerec)
- {
- /* End of the subnet specific name list. Now
- add the names on the unicast subnet . */
- struct subnet_record *uni_subrec = unicast_subnet;
-
- if (uni_subrec != subrec)
- {
- subrec = uni_subrec;
- namerec = subrec->namelist;
- }
- }
- if (!namerec)
- break;
-
- }
-
- SCVAL(countptr,0,names_added);
-
- /* We don't send any stats as they could be used to attack
- the protocol. */
- bzero(buf,64);
-
- buf += 46;
-
- /* Send a NODE STATUS RESPONSE */
- reply_netbios_packet(p, /* Packet to reply to. */
- 0, /* Result code. */
- NMB_STATUS, /* nmbd type code. */
- NMB_NAME_QUERY_OPCODE, /* opcode. */
- 0, /* ttl. */
- rdata, /* data to send. */
- PTR_DIFF(buf,rdata)); /* data length. */
-}
-
-
-/***************************************************************************
-Process a name query.
-
-For broadcast name queries:
-
- - Only reply if the query is for one of YOUR names.
- - NEVER send a negative response to a broadcast query.
-
-****************************************************************************/
-
-void process_name_query_request(struct subnet_record *subrec, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- int name_type = question->name_type;
- BOOL bcast = nmb->header.nm_flags.bcast;
- int ttl=0;
- int rcode = 0;
- char *prdata = NULL;
- char rdata[6];
- BOOL success = False;
- struct name_record *namerec = NULL;
- int reply_data_len = 0;
- int i;
-
- DEBUG(3,("process_name_query_request: Name query from %s on subnet %s for name %s\n",
- inet_ntoa(p->ip), subrec->subnet_name, namestr(question)));
-
- /* Look up the name in the cache - if the request is a broadcast request that
- came from a subnet we don't know about then search all the broadcast subnets
- for a match (as we don't know what interface the request came in on). */
-
- if(subrec == remote_broadcast_subnet)
- namerec = find_name_for_remote_broadcast_subnet( question, FIND_ANY_NAME);
- else
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
-
- /* Check if it is a name that expired */
- if (namerec && ((namerec->death_time != PERMANENT_TTL) && (namerec->death_time < p->timestamp)))
- {
- DEBUG(5,("process_name_query_request: expired name %s\n", namestr(&namerec->name)));
- namerec = NULL;
- }
-
- if (namerec)
- {
-
- /*
- * Always respond to unicast queries.
- * Don't respond to broadcast queries unless the query is for
- * a name we own, a Primary Domain Controller name, or a WINS_PROXY
- * name with type 0 or 0x20. WINS_PROXY names are only ever added
- * into the namelist if we were configured as a WINS proxy.
- */
-
- if (!bcast ||
- (bcast && ((name_type == 0x1b) || (namerec->source == SELF_NAME) ||
- (namerec->source == PERMANENT_NAME) ||
- ((namerec->source == WINS_PROXY_NAME) && ((name_type == 0) || (name_type == 0x20)))))
- )
- {
-
- /* The requested name is a directed query, or it's SELF or PERMANENT or WINS_PROXY,
- or it's a Domain Master type. */
-
- /*
- * If this is a WINS_PROXY_NAME, then ceck that none of the IP
- * addresses we are returning is on the same broadcast subnet
- * as the requesting packet. If it is then don't reply as the
- * actual machine will be replying also and we don't want two
- * replies to a broadcast query.
- */
-
- if(namerec->source == WINS_PROXY_NAME)
- {
- for( i = 0; i < namerec->num_ips; i++)
- {
- if(same_net( namerec->ip[i], subrec->myip, subrec->mask_ip ))
- {
- DEBUG(5,("process_name_query_request: name %s is a WINS proxy name and is also \
-on the same subnet (%s) as the requestor. Not replying.\n",
- namestr(&namerec->name), subrec->subnet_name ));
- return;
- }
- }
- }
-
- ttl = (namerec->death_time != PERMANENT_TTL) ?
- namerec->death_time - p->timestamp : lp_max_ttl();
-
- /* Copy all known ip addresses into the return data. */
- /* Optimise for the common case of one IP address so
- we don't need a malloc. */
-
- if(namerec->num_ips == 1 )
- prdata = rdata;
- else
- {
- if((prdata = (char *)malloc( namerec->num_ips * 6 )) == NULL)
- {
- DEBUG(0,("process_name_query_request: malloc fail !\n"));
- return;
- }
- }
-
- for( i = 0; i < namerec->num_ips; i++)
- {
- set_nb_flags(&prdata[i*6],namerec->nb_flags);
- putip((char *)&prdata[2+(i*6)], &namerec->ip[i]);
- }
- reply_data_len = namerec->num_ips * 6;
- success = True;
- }
- }
-
- /*
- * If a machine is broadcasting a name lookup request and we have lp_wins_proxy()
- * set we should initiate a WINS query here. On success we add the resolved name
- * into our namelist with a type of WINS_PROXY_NAME and then reply to the query.
- */
-
- if(!success && (namerec == NULL) && we_are_a_wins_client() && lp_wins_proxy() &&
- bcast && (subrec != remote_broadcast_subnet))
- {
- make_wins_proxy_name_query_request( subrec, p, question );
- return;
- }
-
- if (!success && bcast)
- {
- if((prdata != rdata) && (prdata != NULL))
- free(rdata);
- return; /* Never reply with a negative response to broadcasts. */
- }
-
- /*
- * Final check. From observation, if a unicast packet is sent
- * to a non-WINS server with the recursion desired bit set
- * then never send a negative response.
- */
-
- if(!success && !bcast && nmb->header.nm_flags.recursion_desired)
- {
- if((prdata != rdata) && (prdata != NULL))
- free(rdata);
- return;
- }
-
- if (success)
- {
- rcode = 0;
- DEBUG(3,("OK\n"));
- }
- else
- {
- rcode = NAM_ERR;
- DEBUG(3,("UNKNOWN\n"));
- }
-
- /* See rfc1002.txt 4.2.13. */
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- NMB_QUERY, /* nmbd type code. */
- NMB_NAME_QUERY_OPCODE, /* opcode. */
- ttl, /* ttl. */
- prdata, /* data to send. */
- reply_data_len); /* data length. */
-
- if((prdata != rdata) && (prdata != NULL))
- free(prdata);
-}
diff --git a/source/nmbd/nmbd_lmhosts.c b/source/nmbd/nmbd_lmhosts.c
deleted file mode 100644
index 2dd1db81cd5..00000000000
--- a/source/nmbd/nmbd_lmhosts.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Jeremy Allison 1994-1997
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Revision History:
-
- Handle lmhosts file reading.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-/****************************************************************************
-Load a lmhosts file.
-****************************************************************************/
-void load_lmhosts_file(char *fname)
-{
- FILE *fp = fopen(fname,"r");
- pstring line;
- if (!fp) {
- DEBUG(2,("load_lmhosts_file: Can't open lmhosts file %s. Error was %s\n",
- fname, strerror(errno)));
- return;
- }
-
- while (!feof(fp))
- {
- pstring ip,name,flags,extra;
- struct subnet_record *subrec = NULL;
- char *ptr;
- int count = 0;
- struct in_addr ipaddr;
- enum name_source source = LMHOSTS_NAME;
- int name_type = -1;
-
- if (!fgets_slash(line,sizeof(pstring),fp))
- continue;
-
- if (*line == '#')
- continue;
-
- strcpy(ip,"");
- strcpy(name,"");
- strcpy(flags,"");
-
- ptr = line;
-
- if (next_token(&ptr,ip ,NULL))
- ++count;
- if (next_token(&ptr,name ,NULL))
- ++count;
- if (next_token(&ptr,flags,NULL))
- ++count;
- if (next_token(&ptr,extra,NULL))
- ++count;
-
- if (count <= 0)
- continue;
-
- if (count > 0 && count < 2)
- {
- DEBUG(0,("load_lmhosts_file: Ill formed hosts line [%s]\n",line));
- continue;
- }
-
- if (count >= 4)
- {
- DEBUG(0,("load_lmhosts_file: too many columns in lmhosts file %s (obsolete syntax)\n",
- fname));
- continue;
- }
-
- DEBUG(4, ("load_lmhosts_file: lmhost entry: %s %s %s\n", ip, name, flags));
-
- if (strchr(flags,'G') || strchr(flags,'S'))
- {
- DEBUG(0,("load_lmhosts_file: group flag in %s ignored (obsolete)\n",fname));
- continue;
- }
-
- ipaddr = *interpret_addr2(ip);
-
- /* Extra feature. If the name ends in '#XX', where XX is a hex number,
- then only add that name type. */
- if((ptr = strchr(name, '#')) != NULL)
- {
- char *endptr;
-
- ptr++;
- name_type = (int)strtol(ptr, &endptr,0);
-
- if(!*ptr || (endptr == ptr))
- {
- DEBUG(0,("load_lmhosts_file: invalid name %s containing '#'.\n", name));
- continue;
- }
-
- *(--ptr) = '\0'; /* Truncate at the '#' */
- }
-
- /* We find a relevent subnet to put this entry on, then add it. */
- /* Go through all the broadcast subnets and see if the mask matches. */
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- if(same_net(ipaddr, subrec->bcast_ip, subrec->mask_ip))
- break;
- }
-
- /* If none match add the name to the remote_broadcast_subnet. */
- if(subrec == NULL)
- subrec = remote_broadcast_subnet;
-
- if(name_type == -1)
- {
- /* Add the (0) and (0x20) names directly into the namelist for this subnet. */
- add_name_to_subnet(subrec,name,0x00,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
- add_name_to_subnet(subrec,name,0x20,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
- }
- else
- {
- /* Add the given name type to the subnet namelist. */
- add_name_to_subnet(subrec,name,name_type,(uint16)NB_ACTIVE,PERMANENT_TTL,source,1,&ipaddr);
- }
- }
-
- fclose(fp);
-}
-
-/****************************************************************************
- Find a name read from the lmhosts file. We secretly check the names on
- the remote_broadcast_subnet as if the name was added to a regular broadcast
- subnet it will be found by normal name query processing.
-****************************************************************************/
-
-BOOL find_name_in_lmhosts(struct nmb_name *nmbname, struct name_record **namerecp)
-{
- struct name_record *namerec;
-
- *namerecp = NULL;
-
- if((namerec = find_name_on_subnet(remote_broadcast_subnet, nmbname,
- FIND_ANY_NAME))==NULL)
- return False;
-
- if(!NAME_IS_ACTIVE(namerec) || (namerec->source != LMHOSTS_NAME))
- return False;
-
- *namerecp = namerec;
- return True;
-}
diff --git a/source/nmbd/nmbd_logonnames.c b/source/nmbd/nmbd_logonnames.c
deleted file mode 100644
index b2431ec0a76..00000000000
--- a/source/nmbd/nmbd_logonnames.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-extern pstring scope;
-extern pstring myname;
-extern fstring myworkgroup;
-extern char **my_netbios_names;
-extern struct in_addr ipzero;
-extern struct in_addr allones_ip;
-
-extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
-
-/****************************************************************************
- Fail to become a Logon server on a subnet.
- ****************************************************************************/
-static void become_logon_server_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *fail_name)
-{
- struct work_record *work = find_workgroup_on_subnet(subrec, fail_name->name);
- struct server_record *servrec;
-
- if(!work)
- {
- DEBUG(0,("become_logon_server_fail: Error - cannot find \
-workgroup %s on subnet %s\n", fail_name->name, subrec->subnet_name));
- return;
- }
-
- if((servrec = find_server_in_workgroup( work, myname)) == NULL)
- {
- DEBUG(0,("become_logon_server_fail: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- myname, fail_name->name, subrec->subnet_name));
- work->log_state = LOGON_NONE;
- return;
- }
-
- /* Set the state back to LOGON_NONE. */
- work->log_state = LOGON_NONE;
-
- servrec->serv.type &= ~SV_TYPE_DOMAIN_CTRL;
-
- DEBUG(0,("become_logon_server_fail: Failed to become a domain master for \
-workgroup %s on subnet %s. Couldn't register name %s.\n",
- work->work_group, subrec->subnet_name, namestr(fail_name)));
-
-}
-
-/****************************************************************************
- Become a Logon server on a subnet.
- ****************************************************************************/
-
-static void become_logon_server_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *registered_name,
- uint16 nb_flags,
- int ttl, struct in_addr registered_ip)
-{
- struct work_record *work = find_workgroup_on_subnet( subrec, registered_name->name);
- struct server_record *servrec;
-
- if(!work)
- {
- DEBUG(0,("become_logon_server_success: Error - cannot find \
-workgroup %s on subnet %s\n", registered_name->name, subrec->subnet_name));
- return;
- }
-
- if((servrec = find_server_in_workgroup( work, myname)) == NULL)
- {
- DEBUG(0,("become_logon_server_success: Error - cannot find server %s \
-in workgroup %s on subnet %s\n",
- myname, registered_name->name, subrec->subnet_name));
- work->log_state = LOGON_NONE;
- return;
- }
-
- /* Set the state in the workgroup structure. */
- work->log_state = LOGON_SRV; /* Become domain master. */
-
- /* Update our server status. */
- servrec->serv.type |= (SV_TYPE_NT|SV_TYPE_DOMAIN_MEMBER);
- /* To allow Win95 policies to load we need to set type domain
- controller.
- */
- servrec->serv.type |= SV_TYPE_DOMAIN_CTRL;
-
- /* Tell the namelist writer to write out a change. */
- subrec->work_changed = True;
-
- DEBUG(0,("become_logon_server_success: Samba is now a logon server\
-for workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name));
-}
-
-/*******************************************************************
- Become a logon server by attempting to register the WORKGROUP<1c>
- group name.
-******************************************************************/
-
-static void become_logon_server(struct subnet_record *subrec,
- struct work_record *work)
-{
- DEBUG(2,("become_logon_server: Atempting to become logon server for workgroup %s \
-on subnet %s\n", work->work_group,subrec->subnet_name));
-
- DEBUG(3,("become_logon_server: go to first stage: register %s<1c> name\n",
- work->work_group));
- work->log_state = LOGON_WAIT;
-
- register_name(subrec, work->work_group,0x1c,samba_nb_type|NB_GROUP,
- become_logon_server_success,
- become_logon_server_fail, NULL);
-}
-
-/*****************************************************************************
- Add the internet group <1c> logon names by unicast and broadcast.
- ****************************************************************************/
-void add_logon_names(void)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- struct work_record *work = find_workgroup_on_subnet(subrec, myworkgroup);
-
- if (work && (work->log_state == LOGON_NONE))
- {
- struct nmb_name nmbname;
- make_nmb_name(&nmbname,myworkgroup,0x1c,scope);
-
- if (find_name_on_subnet(subrec, &nmbname, FIND_SELF_NAME) == NULL)
- {
- DEBUG(0,("add_domain_logon_names: At time %s attempting to become \
-logon server for workgroup %s on subnet %s\n", timestring(), myworkgroup,
- subrec->subnet_name));
- become_logon_server(subrec, work);
- }
- }
- }
-}
diff --git a/source/nmbd/nmbd_mynames.c b/source/nmbd/nmbd_mynames.c
deleted file mode 100644
index 660b5450699..00000000000
--- a/source/nmbd/nmbd_mynames.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-extern char **my_netbios_names;
-extern pstring myname;
-extern fstring myworkgroup;
-
-extern uint16 samba_nb_type; /* Samba's NetBIOS type. */
-
-/****************************************************************************
- Fail funtion when registering my netbios names.
- **************************************************************************/
-
-static void my_name_register_failed(struct subnet_record *subrec,
- struct response_record *rrec, struct nmb_name *nmbname)
-{
- DEBUG(0,("my_name_register_failed: Failed to register my name %s on subnet %s.\n",
- namestr(nmbname), subrec->subnet_name));
-}
-
-/****************************************************************************
- Add my workgroup and my given names to the subnet lists.
- Also add the magic Samba names.
- **************************************************************************/
-
-BOOL register_my_workgroup_and_names()
-{
- struct subnet_record *subrec;
- struct work_record *work;
- int i;
-
- for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- /* Create the workgroup on the subnet. */
- if((work = create_workgroup_on_subnet(subrec, myworkgroup, PERMANENT_TTL)) == NULL)
- {
- DEBUG(0,("register_my_workgroup_and_names: Failed to create my workgroup %s on subnet %s. \
-Exiting.\n", myworkgroup, subrec->subnet_name));
- return False;
- }
-
- /* Each subnet entry, except for the remote_announce_broadcast subnet
- and the wins_server_subnet has the magic Samba names. */
- add_samba_names_to_subnet(subrec);
-
- /* Register all our names including aliases. */
- for (i=0; my_netbios_names[i]; i++)
- {
- register_name(subrec, my_netbios_names[i],0x20,samba_nb_type,
- NULL,
- my_name_register_failed, NULL);
- register_name(subrec, my_netbios_names[i],0x03,samba_nb_type,
- NULL,
- my_name_register_failed, NULL);
- register_name(subrec, my_netbios_names[i],0x00,samba_nb_type,
- NULL,
- my_name_register_failed, NULL);
- }
-
- /* Initiate election processing, register the workgroup names etc. */
- initiate_myworkgroup_startup(subrec, work);
- }
-
- /* If we are not a WINS client, we still need to add the magic Samba
- names and the netbios names to the unicast subnet directly. This is
- to allow unicast node status requests and queries to still work
- in a broadcast only environment. */
-
- if(we_are_a_wins_client() == False)
- {
- add_samba_names_to_subnet(unicast_subnet);
-
- for (i=0; my_netbios_names[i]; i++)
- {
- add_name_to_subnet(unicast_subnet, my_netbios_names[i],0x20,samba_nb_type, PERMANENT_TTL,
- SELF_NAME, 1, &FIRST_SUBNET->myip);
-
- add_name_to_subnet(unicast_subnet, my_netbios_names[i],0x3,samba_nb_type, PERMANENT_TTL,
- SELF_NAME, 1, &FIRST_SUBNET->myip);
-
- add_name_to_subnet(unicast_subnet, my_netbios_names[i],0x0,samba_nb_type, PERMANENT_TTL,
- SELF_NAME, 1, &FIRST_SUBNET->myip);
- }
- }
-
- return True;
-}
-
-/****************************************************************************
- Remove all the names we registered.
-**************************************************************************/
-
-void release_my_names()
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- struct name_record *namerec, *nextnamerec;
-
- for (namerec = subrec->namelist; namerec; namerec = nextnamerec)
- {
- nextnamerec = namerec->next;
- if ((namerec->source == SELF_NAME) && !NAME_IS_DEREGISTERING(namerec))
- release_name(subrec, namerec, standard_success_release,
- NULL, NULL);
- }
- }
-}
-
-/*******************************************************************
- Refresh our registered names.
- ******************************************************************/
-
-void refresh_my_names(time_t t)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- struct name_record *namerec;
-
- for (namerec = subrec->namelist; namerec; namerec = namerec->next)
- {
- /* Each SELF name has an individual time to be refreshed. */
- if ((namerec->source == SELF_NAME) && (namerec->refresh_time < t) &&
- (namerec->death_time != PERMANENT_TTL))
- {
- /* We cheat here and pretend the refresh is going to be
- successful & update the refresh times. This stops
- multiple refresh calls being done. We actually
- deal with refresh failure in the fail_fn.
- */
- refresh_name(subrec, namerec, NULL, NULL, NULL);
- namerec->death_time += lp_max_ttl();
- namerec->refresh_time += lp_max_ttl();
- }
- }
- }
-}
diff --git a/source/nmbd/nmbd_namelistdb.c b/source/nmbd/nmbd_namelistdb.c
deleted file mode 100644
index dfd8a80baa1..00000000000
--- a/source/nmbd/nmbd_namelistdb.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-extern pstring scope;
-extern char **my_netbios_names;
-
-uint16 samba_nb_type = 0; /* samba's NetBIOS name type */
-
-
-/****************************************************************************
- Set Samba's NetBIOS name type.
- ****************************************************************************/
-
-void set_samba_nb_type(void)
-{
- if (lp_wins_support() || (*lp_wins_server()))
- samba_nb_type = NB_MFLAG; /* samba is a 'hybrid' node type */
- else
- samba_nb_type = NB_BFLAG; /* samba is broadcast-only node type */
-}
-
-/****************************************************************************
- Returns True if the netbios name is ^1^2__MSBROWSE__^2^1.
-
- Note: This name is registered if as a master browser or backup browser
- you are responsible for a workgroup (when you announce a domain by
- broadcasting on your local subnet, you announce it as coming from this
- name: see announce_host()).
-
- **************************************************************************/
-
-BOOL ms_browser_name(char *name, int type)
-{
- return (strequal(name,MSBROWSE) && (type == 0x01));
-}
-
-/****************************************************************************
- Add a netbios name into a namelist.
- **************************************************************************/
-
-static void add_name_to_namelist(struct subnet_record *subrec,
- struct name_record *namerec)
-{
- struct name_record *namerec2;
-
- if (!subrec->namelist)
- {
- subrec->namelist = namerec;
- namerec->prev = NULL;
- namerec->next = NULL;
- return;
- }
-
- for (namerec2 = subrec->namelist; namerec2->next; namerec2 = namerec2->next)
- ;
-
- namerec2->next = namerec;
- namerec->next = NULL;
- namerec->prev = namerec2;
- namerec->subnet = subrec;
-
- subrec->namelist_changed = True;
-}
-
-/****************************************************************************
- Remove a name from the namelist.
- **************************************************************************/
-
-void remove_name_from_namelist(struct subnet_record *subrec,
- struct name_record *namerec)
-{
- if (namerec->next)
- namerec->next->prev = namerec->prev;
- if (namerec->prev)
- namerec->prev->next = namerec->next;
-
- if(namerec == subrec->namelist)
- subrec->namelist = namerec->next;
-
- if(namerec->ip != NULL)
- free((char *)namerec->ip);
- free((char *)namerec);
-
- subrec->namelist_changed = True;
-}
-
-
-/****************************************************************************
- Find a name in a subnet.
- **************************************************************************/
-
-struct name_record *find_name_on_subnet(struct subnet_record *subrec,
- struct nmb_name *nmbname, BOOL self_only)
-{
- struct name_record *namerec = subrec->namelist;
- struct name_record *name_ret;
-
- for (name_ret = namerec; name_ret; name_ret = name_ret->next)
- {
- if (nmb_name_equal(&name_ret->name, nmbname))
- {
- /* Self names only - these include permanent names. */
- if (self_only && (name_ret->source != SELF_NAME) &&
- (name_ret->source != PERMANENT_NAME) )
- {
- continue;
- }
- DEBUG(9,("find_name_on_subnet: on subnet %s - found name %s source=%d\n",
- subrec->subnet_name, namestr(nmbname), name_ret->source));
- return name_ret;
- }
- }
- DEBUG(9,("find_name_on_subnet: on subnet %s - name %s NOT FOUND\n",
- subrec->subnet_name, namestr(nmbname)));
- return NULL;
-}
-
-/****************************************************************************
- Find a name over all known broadcast subnets.
-**************************************************************************/
-
-struct name_record *find_name_for_remote_broadcast_subnet( struct nmb_name *nmbname,
- BOOL self_only)
-{
- struct subnet_record *subrec;
- struct name_record *namerec = NULL;
-
- for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- if((namerec = find_name_on_subnet(subrec, nmbname, self_only))!= NULL)
- break;
- }
-
- return namerec;
-}
-
-/****************************************************************************
- Update the ttl of an entry in a subnet name list.
- ****************************************************************************/
-
-void update_name_ttl(struct name_record *namerec, int ttl)
-{
- time_t time_now = time(NULL);
-
- if(namerec->death_time != PERMANENT_TTL)
- namerec->death_time = time_now + ttl;
-
- namerec->refresh_time = time_now + (ttl/2);
-
- namerec->subnet->namelist_changed = True;
-}
-
-/****************************************************************************
- Add an entry to a subnet name list.
- ****************************************************************************/
-
-struct name_record *add_name_to_subnet(struct subnet_record *subrec,
- char *name, int type, uint16 nb_flags, int ttl,
- enum name_source source, int num_ips, struct in_addr *iplist)
-{
- struct name_record *namerec;
- time_t time_now = time(NULL);
-
- if((namerec = (struct name_record *)malloc(sizeof(*namerec))) == NULL)
- {
- DEBUG(0,("add_name_to_subnet: malloc fail.\n"));
- return NULL;
- }
-
- bzero((char *)namerec,sizeof(*namerec));
-
- namerec->subnet = subrec;
-
- namerec->num_ips = num_ips;
- namerec->ip = (struct in_addr *)malloc(sizeof(struct in_addr) * namerec->num_ips);
- if (!namerec->ip)
- {
- DEBUG(0,("add_name_to_subnet: malloc fail when creating ip_flgs.\n"));
- free((char *)namerec);
- return NULL;
- }
-
- bzero((char *)namerec->ip, sizeof(struct in_addr) * namerec->num_ips);
-
- memcpy(&namerec->ip[0], iplist, num_ips * sizeof(struct in_addr));
-
- make_nmb_name(&namerec->name,name,type,scope);
-
- /* Setup the death_time and refresh_time. */
- if(ttl == PERMANENT_TTL)
- namerec->death_time = PERMANENT_TTL;
- else
- namerec->death_time = time_now + ttl;
-
- namerec->refresh_time = time_now + (ttl/2);
-
- /* Enter the name as active. */
- namerec->nb_flags = nb_flags | NB_ACTIVE;
-
- /* If it's our primary name, flag it as so. */
- if(strequal(my_netbios_names[0],name))
- namerec->nb_flags |= NB_PERM;
-
- namerec->source = source;
-
- add_name_to_namelist(subrec,namerec);
-
- DEBUG(3,("add_name_to_subnet: Added netbios name %s with first IP %s ttl=%d nb_flags=%2x to subnet %s\n",
- namestr(&namerec->name),inet_ntoa(*iplist),ttl,(unsigned int)nb_flags,
- subrec->subnet_name));
-
- subrec->namelist_changed = True;
-
- return(namerec);
-}
-
-/*******************************************************************
- Utility function automatically called when a name refresh or register
- succeeds. By definition this is a SELF_NAME (or we wouldn't be registering
- it).
- ******************************************************************/
-
-void standard_success_register(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname, uint16 nb_flags, int ttl,
- struct in_addr registered_ip)
-{
- struct name_record *namerec = find_name_on_subnet(subrec, nmbname, FIND_SELF_NAME);
-
- if(namerec == NULL)
- add_name_to_subnet(subrec, nmbname->name, nmbname->name_type,
- nb_flags, ttl, SELF_NAME, 1, &registered_ip);
- else
- update_name_ttl(namerec, ttl);
-}
-
-/*******************************************************************
- Utility function automatically called when a name refresh or register
- fails.
- ******************************************************************/
-
-void standard_fail_register(struct subnet_record *subrec,
- struct response_record *rrec, struct nmb_name *nmbname)
-{
- struct name_record *namerec = find_name_on_subnet(subrec, nmbname, FIND_SELF_NAME);
-
- DEBUG(0,("standard_fail_register: Failed to register/refresh name %s on subnet %s\n",
- namestr(nmbname), subrec->subnet_name));
-
- /* Remove the name from the subnet. */
- if(namerec)
- remove_name_from_namelist(subrec, namerec);
-}
-
-/*******************************************************************
- Utility function to remove an IP address from a name record.
- ******************************************************************/
-
-static void remove_nth_ip_in_record( struct name_record *namerec, int ind)
-{
- if(ind != namerec->num_ips)
- memmove( (char *)(&namerec->ip[ind]), (char *)(&namerec->ip[ind+1]),
- ( namerec->num_ips - ind - 1) * sizeof(struct in_addr));
-
- namerec->num_ips--;
- namerec->subnet->namelist_changed = True;
-}
-
-/*******************************************************************
- Utility function to check if an IP address exists in a name record.
- ******************************************************************/
-
-BOOL find_ip_in_name_record(struct name_record *namerec, struct in_addr ip)
-{
- int i;
-
- for(i = 0; i < namerec->num_ips; i++)
- if(ip_equal( namerec->ip[i], ip))
- return True;
-
- return False;
-}
-
-/*******************************************************************
- Utility function to add an IP address to a name record.
- ******************************************************************/
-
-void add_ip_to_name_record(struct name_record *namerec, struct in_addr new_ip)
-{
- struct in_addr *new_list;
-
- /* Don't add one we already have. */
- if(find_ip_in_name_record( namerec, new_ip))
- return;
-
- if((new_list = (struct in_addr *)malloc( (namerec->num_ips + 1)*sizeof(struct in_addr)) )== NULL)
- {
- DEBUG(0,("add_ip_to_name_record: Malloc fail !\n"));
- return;
- }
-
- memcpy((char *)new_list, (char *)namerec->ip, namerec->num_ips *sizeof(struct in_addr));
- new_list[namerec->num_ips] = new_ip;
-
- free((char *)namerec->ip);
- namerec->ip = new_list;
- namerec->num_ips += 1;
-
- namerec->subnet->namelist_changed = True;
-}
-
-/*******************************************************************
- Utility function to remove an IP address from a name record.
- ******************************************************************/
-
-void remove_ip_from_name_record( struct name_record *namerec, struct in_addr remove_ip)
-{
- /* Try and find the requested ip address - remove it. */
- int i;
- int orig_num = namerec->num_ips;
-
- for(i = 0; i < orig_num; i++)
- if( ip_equal( remove_ip, namerec->ip[i]) )
- {
- remove_nth_ip_in_record( namerec, i);
- break;
- }
-}
-
-/*******************************************************************
- Utility function that release_name callers can plug into as the
- success function when a name release is successful. Used to save
- duplication of success_function code.
- ******************************************************************/
-
-void standard_success_release(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname, struct in_addr released_ip)
-{
- struct name_record *namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME);
-
- if(namerec == NULL)
- {
- DEBUG(0,("standard_success_release: Name release for name %s IP %s on subnet %s. Name \
-was not found on subnet.\n", namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name));
- return;
- }
- else
- {
- int orig_num = namerec->num_ips;
-
- remove_ip_from_name_record( namerec, released_ip);
-
- if(namerec->num_ips == orig_num)
- DEBUG(0,("standard_success_release: Name release for name %s IP %s on subnet %s. This ip \
-is not known for this name.\n", namestr(nmbname), inet_ntoa(released_ip), subrec->subnet_name ));
- }
-
- if (namerec->num_ips == 0)
- remove_name_from_namelist(subrec, namerec);
-}
-
-/*******************************************************************
- Expires old names in a subnet namelist.
- ******************************************************************/
-
-void expire_names_on_subnet(struct subnet_record *subrec, time_t t)
-{
- struct name_record *namerec;
- struct name_record *next_namerec;
-
- for (namerec = subrec->namelist; namerec; namerec = next_namerec)
- {
- next_namerec = namerec->next;
- if ((namerec->death_time != PERMANENT_TTL) && (namerec->death_time < t))
- {
- if (namerec->source == SELF_NAME)
- {
- DEBUG(3,("expire_names_on_subnet: Subnet %s not expiring SELF name %s\n",
- subrec->subnet_name, namestr(&namerec->name)));
- namerec->death_time += 300;
- namerec->subnet->namelist_changed = True;
- continue;
- }
- DEBUG(3,("expire_names_on_subnet: Subnet %s - removing expired name %s\n",
- subrec->subnet_name, namestr(&namerec->name)));
-
- remove_name_from_namelist(subrec, namerec);
- }
- }
-}
-
-/*******************************************************************
- Expires old names in all subnet namelists.
- ******************************************************************/
-
-void expire_names(time_t t)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- expire_names_on_subnet(subrec, t);
- }
-}
-
-/****************************************************************************
- Add the magic samba names, useful for finding samba servers.
- These go directly into the name list for a particular subnet,
- without going through the normal registration process.
- When adding them to the unicast subnet, add them as a list of
- all broadcast subnet IP addresses.
-**************************************************************************/
-
-void add_samba_names_to_subnet(struct subnet_record *subrec)
-{
- struct in_addr *iplist = &subrec->myip;
- int num_ips = 1;
-
- /* These names are added permanently (ttl of zero) and will NOT be
- refreshed. */
-
- if((subrec == unicast_subnet) || (subrec == wins_server_subnet))
- {
- struct subnet_record *bcast_subrecs;
- int i;
- /* Create an IP list containing all our known subnets. */
-
- num_ips = iface_count();
- if((iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) )) == NULL)
- {
- DEBUG(0,("add_samba_names_to_subnet: Malloc fail !\n"));
- return;
- }
-
- for(bcast_subrecs = FIRST_SUBNET, i = 0; bcast_subrecs;
- bcast_subrecs = NEXT_SUBNET_EXCLUDING_UNICAST(bcast_subrecs), i++)
- iplist[i] = bcast_subrecs->myip;
-
- }
-
- add_name_to_subnet(subrec,"*",0x0,samba_nb_type, PERMANENT_TTL,
- PERMANENT_NAME, num_ips, iplist);
- add_name_to_subnet(subrec,"*",0x20,samba_nb_type,PERMANENT_TTL,
- PERMANENT_NAME, num_ips, iplist);
- add_name_to_subnet(subrec,"__SAMBA__",0x20,samba_nb_type,PERMANENT_TTL,
- PERMANENT_NAME, num_ips, iplist);
- add_name_to_subnet(subrec,"__SAMBA__",0x00,samba_nb_type,PERMANENT_TTL,
- PERMANENT_NAME, num_ips, iplist);
-
- if(iplist != &subrec->myip)
- free((char *)iplist);
-}
-
-/****************************************************************************
- Dump the contents of the namelists on all the subnets (including unicast)
- into a file. Initiated by SIGHUP - used to debug the state of the namelists.
-**************************************************************************/
-
-static void dump_subnet_namelist( struct subnet_record *subrec, FILE *fp)
-{
- struct name_record *namerec;
- char *src_type;
- struct tm *tm;
- int i;
-
- fprintf(fp, "Subnet %s\n----------------------\n", subrec->subnet_name);
- for (namerec = subrec->namelist; namerec; namerec = namerec->next)
- {
- fprintf(fp,"\tName = %s\t", namestr(&namerec->name));
- switch(namerec->source)
- {
- case LMHOSTS_NAME:
- src_type = "LMHOSTS_NAME";
- break;
- case WINS_PROXY_NAME:
- src_type = "WINS_PROXY_NAME";
- break;
- case REGISTER_NAME:
- src_type = "REGISTER_NAME";
- break;
- case SELF_NAME:
- src_type = "SELF_NAME";
- break;
- case DNS_NAME:
- src_type = "DNS_NAME";
- break;
- case DNSFAIL_NAME:
- src_type = "DNSFAIL_NAME";
- break;
- case PERMANENT_NAME:
- src_type = "PERMANENT_NAME";
- break;
- default:
- src_type = "unknown!";
- break;
- }
- fprintf(fp, "Source = %s\nb_flags = %x\t", src_type, namerec->nb_flags);
-
- if(namerec->death_time != PERMANENT_TTL)
- {
- tm = LocalTime(&namerec->death_time);
- fprintf(fp, "death_time = %s\t", asctime(tm));
- }
- else
- fprintf(fp, "death_time = PERMANENT\t");
-
- if(namerec->refresh_time != PERMANENT_TTL)
- {
- tm = LocalTime(&namerec->refresh_time);
- fprintf(fp, "refresh_time = %s\n", asctime(tm));
- }
- else
- fprintf(fp, "refresh_time = PERMANENT\n");
-
- fprintf(fp, "\t\tnumber of IPS = %d", namerec->num_ips);
- for(i = 0; i < namerec->num_ips; i++)
- fprintf(fp, "\t%s", inet_ntoa(namerec->ip[i]));
-
- fprintf(fp, "\n\n");
- }
-}
-
-/****************************************************************************
- Dump the contents of the namelists on all the subnets (including unicast)
- into a file. Initiated by SIGHUP - used to debug the state of the namelists.
-**************************************************************************/
-
-void dump_all_namelists()
-{
- fstring fname;
- FILE *fp;
- struct subnet_record *subrec;
-
- pstrcpy(fname,lp_lockdir());
- trim_string(fname,NULL,"/");
- strcat(fname,"/");
- strcat(fname,"namelist.debug");
-
- fp = fopen(fname,"w");
-
- if (!fp)
- {
- DEBUG(0,("dump_all_namelists: Can't open file %s. Error was %s\n",
- fname,strerror(errno)));
- return;
- }
-
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- dump_subnet_namelist( subrec, fp);
-
- if(!we_are_a_wins_client())
- dump_subnet_namelist(unicast_subnet, fp);
-
- if(remote_broadcast_subnet->namelist != NULL)
- dump_subnet_namelist(remote_broadcast_subnet, fp);
-
- if(wins_server_subnet != NULL)
- dump_subnet_namelist( wins_server_subnet, fp);
- fclose(fp);
-}
diff --git a/source/nmbd/nmbd_namequery.c b/source/nmbd/nmbd_namequery.c
deleted file mode 100644
index 5d98935fec7..00000000000
--- a/source/nmbd/nmbd_namequery.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-extern pstring scope;
-
-/****************************************************************************
- Deal with a response packet when querying a name.
-****************************************************************************/
-
-static void query_name_response(struct subnet_record *subrec,
- struct response_record *rrec, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- BOOL success = False;
- struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
- struct in_addr answer_ip;
-
- /* Ensure we don't retry the query but leave the response record cleanup
- to the timeout code. We may get more answer responses in which case
- we should mark the name in conflict.. */
- rrec->repeat_count = 0;
-
- if(rrec->num_msgs == 1)
- {
- /* This is the first response. */
-
- if(nmb->header.opcode == NMB_WACK_OPCODE)
- {
- /* WINS server is telling us to wait. Pretend we didn't get
- the response but don't send out any more query requests. */
-
- DEBUG(5,("query_name_response: WACK from WINS server %s in querying \
-name %s on subnet %s.\n", inet_ntoa(p->ip), namestr(question_name), subrec->subnet_name));
-
- rrec->repeat_count = 0;
- /* How long we should wait for. */
- rrec->repeat_time = p->timestamp + nmb->answers->ttl;
- rrec->num_msgs--;
- return;
- }
- else if(nmb->header.rcode != 0)
- {
- success = False;
-
- DEBUG(5,("query_name_response: On subnet %s - negative response \
-from IP %s for name %s. Error code was %d.\n", subrec->subnet_name, inet_ntoa(p->ip),
- namestr(question_name), nmb->header.rcode));
- }
- else
- {
- success = True;
-
- putip((char *)&answer_ip,&nmb->answers->rdata[2]);
- DEBUG(5,("query_name_response: On subnet %s - positive response from IP %s\
-for name %s. IP of that name is %s\n", subrec->subnet_name, inet_ntoa(p->ip),
- namestr(question_name), inet_ntoa(answer_ip)));
-
- /* Interestingly, we could add these names to our namelists, and
- change nmbd to a model that checked its own name cache first,
- before sending out a query. This is a task for another day, though.
- */
- }
- }
- else if( rrec->num_msgs > 1)
- {
- DEBUG(0,("query_name_response: Multiple (%d) responses received for a query on \
-subnet %s for name %s. This response was from IP %s\n",
- rrec->num_msgs, subrec->subnet_name, namestr(question_name),
- inet_ntoa(rrec->packet->ip) ));
-
- /* We have already called the success or fail function, so we
- don't call again here. Leave the response record around in
- case we get more responses. */
-
- return;
- }
-
- if(success && rrec->success_fn)
- (*rrec->success_fn)(subrec, rrec->userdata, question_name, answer_ip, nmb->answers);
- else if( rrec->fail_fn)
- (*rrec->fail_fn)(subrec, rrec, question_name, nmb->header.rcode);
-
-}
-
-/****************************************************************************
- Deal with a timeout when querying a name.
-****************************************************************************/
-
-static void query_name_timeout_response(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- /* We can only fail here, never succeed. */
- BOOL failed = True;
- struct nmb_name *question_name = &sent_nmb->question.question_name;
-
- if(rrec->num_msgs != 0)
- {
- /* We got at least one response, and have called the success/fail
- function already. */
-
- failed = False;
- }
-
- if(failed)
- {
- DEBUG(5,("query_name_timeout_response: No response to querying name %s on subnet %s.\n",
- namestr(question_name), subrec->subnet_name));
-
- if(rrec->fail_fn)
- (*rrec->fail_fn)(subrec, rrec, question_name, 0);
- }
-
- remove_response_record(subrec, rrec);
-}
-
-/****************************************************************************
- Lookup a name on our local namelists. We check the lmhosts file first. If the
- name is not there we look for the name on the given subnet.
-****************************************************************************/
-
-static BOOL query_local_namelists(struct subnet_record *subrec, struct nmb_name *nmbname,
- struct name_record **namerecp)
-{
- struct name_record *namerec;
-
- *namerecp = NULL;
-
- if(find_name_in_lmhosts(nmbname, namerecp))
- return True;
-
- if((namerec = find_name_on_subnet(subrec, nmbname, FIND_ANY_NAME))==NULL)
- return False;
-
- if(NAME_IS_ACTIVE(namerec) && ((namerec->source == SELF_NAME) ||
- (namerec->source == LMHOSTS_NAME)) )
- {
- *namerecp = namerec;
- return True;
- }
- return False;
-}
-
-/****************************************************************************
- Try and query for a name.
-****************************************************************************/
-
-BOOL query_name(struct subnet_record *subrec, char *name, int type,
- query_name_success_function success_fn,
- query_name_fail_function fail_fn,
- struct userdata_struct *userdata)
-{
- struct nmb_name nmbname;
- struct name_record *namerec;
-
- make_nmb_name(&nmbname, name, type, scope);
-
- /*
- * We need to check our local namelists first.
- * It may be an magic name, lmhosts name or just
- * a name we have registered.
- */
-
- if(query_local_namelists(subrec, &nmbname, &namerec) == True)
- {
- struct res_rec rrec;
- int i;
-
- bzero((char *)&rrec, sizeof(struct res_rec));
-
- /* Fake up the needed res_rec just in case it's used. */
- rrec.rr_name = nmbname;
- rrec.rr_type = RR_TYPE_NB;
- rrec.rr_class = RR_CLASS_IN;
- rrec.ttl = PERMANENT_TTL;
- rrec.rdlength = namerec->num_ips * 6;
- if(rrec.rdlength > MAX_DGRAM_SIZE)
- {
- DEBUG(0,("query_name: nmbd internal error - there are %d ip addresses for name %s.\n",
- namerec->num_ips, namestr(&nmbname) ));
- return False;
- }
-
- for( i = 0; i < namerec->num_ips; i++)
- {
- set_nb_flags( &rrec.rdata[i*6], namerec->nb_flags );
- putip( &rrec.rdata[(i*6) + 2], (char *)&namerec->ip[i]);
- }
-
- /* Call the success function directly. */
- if(success_fn)
- (*success_fn)(subrec, userdata, &nmbname, namerec->ip[0], &rrec);
- return False;
- }
-
- if(queue_query_name( subrec,
- query_name_response,
- query_name_timeout_response,
- success_fn,
- fail_fn,
- userdata,
- &nmbname) == NULL)
- {
- DEBUG(0,("query_name: Failed to send packet trying to query name %s\n",
- namestr(&nmbname)));
- return True;
- }
- return False;
-}
diff --git a/source/nmbd/nmbd_nameregister.c b/source/nmbd/nmbd_nameregister.c
deleted file mode 100644
index cdaef1a767c..00000000000
--- a/source/nmbd/nmbd_nameregister.c
+++ /dev/null
@@ -1,392 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-extern pstring scope;
-extern fstring myworkgroup;
-
-/****************************************************************************
- Deal with a response packet when registering one of our names.
-****************************************************************************/
-
-static void register_name_response(struct subnet_record *subrec,
- struct response_record *rrec, struct packet_struct *p)
-{
- /*
- * If we are registering broadcast, then getting a response is an
- * error - we do not have the name. If we are registering unicast,
- * then we expect to get a response.
- */
-
- struct nmb_packet *nmb = &p->packet.nmb;
- BOOL bcast = nmb->header.nm_flags.bcast;
- BOOL success = True;
- struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
- struct nmb_name *answer_name = &nmb->answers->rr_name;
- int ttl;
- uint16 nb_flags;
- struct in_addr registered_ip;
-
- /* Sanity check. Ensure that the answer name in the incoming packet is the
- same as the requested name in the outgoing packet. */
-
- if(!nmb_name_equal(question_name, answer_name))
- {
- DEBUG(0,("register_name_response: Answer name %s differs from question \
-name %s.\n", namestr(answer_name), namestr(question_name)));
- return;
- }
-
- if(bcast)
- {
- /*
- * Special hack to cope with old Samba nmbd's.
- * Earlier versions of Samba (up to 1.9.16p11) respond
- * to a broadcast name registration of WORKGROUP<1b> when
- * they should not. Hence, until these versions are gone,
- * we should treat such errors as success for this particular
- * case only. jallison@whistle.com.
- */
-
-#if 1 /* OLD_SAMBA_SERVER_HACK */
- if((nmb->header.rcode == ACT_ERR) && strequal(myworkgroup, answer_name->name) &&
- (answer_name->name_type == 0x1b))
- {
- /* Pretend we did not get this. */
- rrec->num_msgs--;
-
- DEBUG(5,("register_name_response: Ignoring broadcast response to \
-registration of name %s due to old Samba server bug.\n", namestr(answer_name)));
- return;
- }
-#endif /* OLD_SAMBA_SERVER_HACK */
-
- /* Someone else has the name. Log the problem. */
- DEBUG(1,("register_name_response: Failed to register \
-name %s on subnet %s via broadcast. Error code was %d. Reject came from IP %s\n",
- namestr(answer_name),
- subrec->subnet_name, nmb->header.rcode, inet_ntoa(p->ip)));
- success = False;
- }
- else
- {
- /* Unicast - check to see if the response allows us to have the name. */
- if(nmb->header.rcode != 0)
- {
- /* Error code - we didn't get the name. */
- success = False;
-
- DEBUG(0,("register_name_response: server at IP %s rejected our \
-name registration of %s with error code %d.\n", inet_ntoa(p->ip),
- namestr(answer_name), nmb->header.rcode));
-
- }
- else if(nmb->header.opcode == NMB_WACK_OPCODE)
- {
- /* WINS server is telling us to wait. Pretend we didn't get
- the response but don't send out any more register requests. */
-
- DEBUG(5,("register_name_response: WACK from WINS server %s in registering \
-name %s on subnet %s.\n", inet_ntoa(p->ip), namestr(answer_name), subrec->subnet_name));
-
- rrec->repeat_count = 0;
- /* How long we should wait for. */
- rrec->repeat_time = p->timestamp + nmb->answers->ttl;
- rrec->num_msgs--;
- return;
- }
- else
- {
- success = True;
- /* Get the data we need to pass to the success function. */
- nb_flags = get_nb_flags(nmb->answers->rdata);
- putip((char*)&registered_ip,&nmb->answers->rdata[2]);
- ttl = nmb->answers->ttl;
- }
- }
-
- DEBUG(5,("register_name_response: %s in registering name %s on subnet %s.\n",
- success ? "success" : "failure", namestr(answer_name), subrec->subnet_name));
-
- if(success)
- {
- /* Enter the registered name into the subnet name database before calling
- the success function. */
- standard_success_register(subrec, rrec->userdata, answer_name, nb_flags, ttl, registered_ip);
- if( rrec->success_fn)
- (*rrec->success_fn)(subrec, rrec->userdata, answer_name, nb_flags, ttl, registered_ip);
- }
- else
- {
- if( rrec->fail_fn)
- (*rrec->fail_fn)(subrec, rrec, question_name);
- /* Remove the name. */
- standard_fail_register( subrec, rrec, question_name);
- }
-
- /* Ensure we don't retry. */
- remove_response_record(subrec, rrec);
-}
-
-/****************************************************************************
- Deal with a timeout when registering one of our names.
-****************************************************************************/
-
-static void register_name_timeout_response(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- /*
- * If we are registering unicast, then NOT getting a response is an
- * error - we do not have the name. If we are registering broadcast,
- * then we don't expect to get a response.
- */
-
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- BOOL bcast = sent_nmb->header.nm_flags.bcast;
- BOOL success = False;
- struct nmb_name *question_name = &sent_nmb->question.question_name;
- uint16 nb_flags;
- int ttl;
- struct in_addr registered_ip;
-
- if(bcast)
- {
- if(rrec->num_msgs == 0)
- {
- /* Not receiving a message is success for broadcast registration. */
- success = True;
-
- /* Pull the success values from the original request packet. */
- nb_flags = get_nb_flags(sent_nmb->additional->rdata);
- ttl = sent_nmb->additional->ttl;
- putip(&registered_ip,&sent_nmb->additional->rdata[2]);
- }
- }
- else
- {
- /* Unicast - if no responses then it's an error. */
- if(rrec->num_msgs == 0)
- {
- DEBUG(2,("register_name_timeout_response: WINS server at address %s is not \
-responding.\n", inet_ntoa(rrec->packet->ip)));
-
- /* Keep trying to contact the WINS server periodically. This allows
- us to work correctly if the WINS server is down temporarily when
- we come up. */
-
- /* Reset the number of attempts to zero and double the interval between
- retries. Max out at 5 minutes. */
- rrec->repeat_count = 3;
- rrec->repeat_interval *= 2;
- if(rrec->repeat_interval > (5 * 60))
- rrec->repeat_interval = (5 * 60);
- rrec->repeat_time = time(NULL) + rrec->repeat_interval;
-
- DEBUG(5,("register_name_timeout_response: increasing WINS timeout to %d seconds.\n",
- rrec->repeat_interval));
- return; /* Don't remove the response record. */
- }
- }
-
- DEBUG(5,("register_name_timeout_response: %s in registering name %s on subnet %s.\n",
- success ? "success" : "failure", namestr(question_name), subrec->subnet_name));
- if(success)
- {
- /* Enter the registered name into the subnet name database before calling
- the success function. */
- standard_success_register(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
- if( rrec->success_fn)
- (*rrec->success_fn)(subrec, rrec->userdata, question_name, nb_flags, ttl, registered_ip);
- }
- else
- {
- if( rrec->fail_fn)
- (*rrec->fail_fn)(subrec, rrec, question_name);
- /* Remove the name. */
- standard_fail_register( subrec, rrec, question_name);
- }
-
- /* Ensure we don't retry. */
- remove_response_record(subrec, rrec);
-}
-
-/****************************************************************************
- Try and register one of our names on the unicast subnet - multihomed.
-****************************************************************************/
-
-static BOOL multihomed_register_name( struct nmb_name *nmbname, uint16 nb_flags,
- register_name_success_function success_fn,
- register_name_fail_function fail_fn,
- struct userdata_struct *userdata)
-{
- /*
- If we are adding a group name, we just send multiple
- register name packets to the WINS server (this is an
- internet group name.
-
- If we are adding a unique name, We need first to add
- our names to the unicast subnet namelist. This is
- because when a WINS server receives a multihomed
- registration request, the first thing it does is to
- send a name query to the registering machine, to see
- if it has put the name in it's local namelist.
- We need the name there so the query response code in
- nmbd_incomingrequests.c will find it.
-
- We are adding this name prematurely (we don't really
- have it yet), but as this is on the unicast subnet
- only we will get away with this (only the WINS server
- will ever query names from us on this subnet).
- */
-
- int num_ips=0;
- int i;
- struct in_addr *ip_list = NULL;
- struct subnet_record *subrec;
-
- for(subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec) )
- num_ips++;
-
- if((ip_list = (struct in_addr *)malloc(num_ips * sizeof(struct in_addr)))==NULL)
- {
- DEBUG(0,("multihomed_register_name: malloc fail !\n"));
- return True;
- }
-
- for(subrec = FIRST_SUBNET, i = 0; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec), i++ )
- ip_list[i] = subrec->myip;
-
- add_name_to_subnet(unicast_subnet, nmbname->name, nmbname->name_type,
- nb_flags, lp_max_ttl(), SELF_NAME, num_ips, ip_list);
-
- /* Now try and register the name, num_ips times. On the last time use
- the given success and fail functions. */
-
- for( i = 0; i < num_ips; i++)
- {
- if(queue_register_multihomed_name( unicast_subnet,
- register_name_response,
- register_name_timeout_response,
- (i == num_ips - 1) ? success_fn : NULL,
- (i == num_ips - 1) ? fail_fn : NULL,
- (i == num_ips - 1) ? userdata : NULL,
- nmbname,
- nb_flags,
- ip_list[i]) == NULL)
- {
- DEBUG(0,("multihomed_register_name: Failed to send packet trying to \
-register name %s IP %s\n", namestr(nmbname), inet_ntoa(ip_list[i]) ));
-
- free((char *)ip_list);
- return True;
- }
- }
-
- free((char *)ip_list);
-
- return False;
-}
-
-/****************************************************************************
- Try and register one of our names.
-****************************************************************************/
-
-BOOL register_name(struct subnet_record *subrec,
- char *name, int type, uint16 nb_flags,
- register_name_success_function success_fn,
- register_name_fail_function fail_fn,
- struct userdata_struct *userdata)
-{
- struct nmb_name nmbname;
-
- make_nmb_name(&nmbname, name, type, scope);
-
- /* Always set the NB_ACTIVE flag on the name we are
- registering. Doesn't make sense without it.
- */
-
- nb_flags |= NB_ACTIVE;
-
- /* If this is the unicast subnet, and we are a multi-homed
- host, then register a multi-homed name. */
-
- if( (subrec == unicast_subnet) && we_are_multihomed())
- return multihomed_register_name(&nmbname, nb_flags,
- success_fn, fail_fn,
- userdata);
-
- if(queue_register_name( subrec,
- register_name_response,
- register_name_timeout_response,
- success_fn,
- fail_fn,
- userdata,
- &nmbname,
- nb_flags) == NULL)
- {
- DEBUG(0,("register_name: Failed to send packet trying to register name %s\n",
- namestr(&nmbname)));
- return True;
- }
- return False;
-}
-
-/****************************************************************************
- Try and refresh one of our names.
-****************************************************************************/
-
-BOOL refresh_name(struct subnet_record *subrec, struct name_record *namerec,
- refresh_name_success_function success_fn,
- refresh_name_fail_function fail_fn,
- struct userdata_struct *userdata)
-{
- int i;
-
- /*
- * Go through and refresh the name for all known ip addresses.
- * Only call the success/fail function on the last one (it should
- * only be done once).
- */
-
- for( i = 0; i < namerec->num_ips; i++)
- {
- if(queue_refresh_name( subrec,
- register_name_response,
- register_name_timeout_response,
- (i == (namerec->num_ips - 1)) ? success_fn : NULL,
- (i == (namerec->num_ips - 1)) ? fail_fn : NULL,
- (i == (namerec->num_ips - 1)) ? userdata : NULL,
- namerec,
- namerec->ip[i]) == NULL)
- {
- DEBUG(0,("refresh_name: Failed to send packet trying to refresh name %s\n",
- namestr(&namerec->name)));
- return True;
- }
- }
- return False;
-}
diff --git a/source/nmbd/nmbd_namerelease.c b/source/nmbd/nmbd_namerelease.c
deleted file mode 100644
index 8632dd76553..00000000000
--- a/source/nmbd/nmbd_namerelease.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-extern pstring scope;
-
-/****************************************************************************
- Deal with a response packet when releasing one of our names.
-****************************************************************************/
-
-static void release_name_response(struct subnet_record *subrec,
- struct response_record *rrec, struct packet_struct *p)
-{
- /*
- * If we are releasing broadcast, then getting a response is an
- * error. If we are releasing unicast, then we expect to get a response.
- */
-
- struct nmb_packet *nmb = &p->packet.nmb;
- BOOL bcast = nmb->header.nm_flags.bcast;
- BOOL success = True;
- struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
- struct nmb_name *answer_name = &nmb->answers->rr_name;
- struct in_addr released_ip;
-
- /* Sanity check. Ensure that the answer name in the incoming packet is the
- same as the requested name in the outgoing packet. */
-
- if(!nmb_name_equal(question_name, answer_name))
- {
- DEBUG(0,("release_name_response: Answer name %s differs from question \
-name %s.\n", namestr(answer_name), namestr(question_name)));
- return;
- }
-
- if(bcast)
- {
- /* Someone sent a response. This shouldn't happen/ */
- DEBUG(1,("release_name_response: A response for releasing name %s was received on a\
-broadcast subnet %s. This should not happen !\n", namestr(answer_name), subrec->subnet_name));
- return;
- }
- else
- {
- /* Unicast - check to see if the response allows us to release the name. */
- if(nmb->header.rcode != 0)
- {
- /* Error code - we were told not to release the name ! What now ! */
- success = False;
-
- DEBUG(0,("release_name_response: WINS server at IP %s rejected our \
-name release of name %s with error code %d.\n", inet_ntoa(p->ip),
- namestr(answer_name), nmb->header.rcode));
-
- }
- else if(nmb->header.opcode == NMB_WACK_OPCODE)
- {
- /* WINS server is telling us to wait. Pretend we didn't get
- the response but don't send out any more release requests. */
-
- DEBUG(5,("release_name_response: WACK from WINS server %s in releasing \
-name %s on subnet %s.\n", inet_ntoa(p->ip), namestr(answer_name), subrec->subnet_name));
-
- rrec->repeat_count = 0;
- /* How long we should wait for. */
- rrec->repeat_time = p->timestamp + nmb->answers->ttl;
- rrec->num_msgs--;
- return;
- }
- }
-
- DEBUG(5,("release_name_response: %s in releasing name %s on subnet %s.\n",
- success ? "success" : "failure", namestr(answer_name), subrec->subnet_name));
-
- if(success)
- {
- putip((char*)&released_ip ,&nmb->answers->rdata[2]);
-
- if(rrec->success_fn)
- (*rrec->success_fn)(subrec, rrec->userdata, answer_name, released_ip);
- standard_success_release( subrec, rrec->userdata, answer_name, released_ip);
- }
- else
- {
- /* We have no standard_fail_release - maybe we should add one ? */
- if(rrec->fail_fn)
- (*rrec->fail_fn)(subrec, rrec, answer_name);
- }
-
- remove_response_record(subrec, rrec);
-}
-
-/****************************************************************************
- Deal with a timeout when releasing one of our names.
-****************************************************************************/
-
-static void release_name_timeout_response(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- /*
- * If we are releasing unicast, then NOT getting a response is an
- * error - we could not release the name. If we are releasing broadcast,
- * then we don't expect to get a response.
- */
-
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- BOOL bcast = sent_nmb->header.nm_flags.bcast;
- BOOL success = False;
- struct nmb_name *question_name = &sent_nmb->question.question_name;
- struct in_addr released_ip;
-
- if(bcast)
- {
- if(rrec->num_msgs == 0)
- {
- /* Not receiving a message is success for broadcast release. */
- success = True;
-
- /* Get the ip address we were trying to release. */
- putip((char*)&released_ip ,&sent_nmb->additional->rdata[2]);
- }
- }
- else
- {
- /* Unicast - if no responses then it's an error. */
- if(rrec->num_msgs == 0)
- {
- DEBUG(2,("release_name_timeout_response: WINS server at address %s is not \
-responding.\n", inet_ntoa(rrec->packet->ip)));
-
- /* Keep trying to contact the WINS server periodically. This allows
- us to work correctly if the WINS server is down temporarily when
- we want to delete the name. */
-
- /* Reset the number of attempts to zero and double the interval between
- retries. Max out at 5 minutes. */
- rrec->repeat_count = 3;
- rrec->repeat_interval *= 2;
- if(rrec->repeat_interval > (5 * 60))
- rrec->repeat_interval = (5 * 60);
- rrec->repeat_time = time(NULL) + rrec->repeat_interval;
-
- DEBUG(5,("release_name_timeout_response: increasing WINS timeout to %d seconds.\n",
- rrec->repeat_interval));
- return; /* Don't remove the response record. */
- }
- }
-
- DEBUG(5,("release_name_timeout_response: %s in releasing name %s on subnet %s.\n",
- success ? "success" : "failure", namestr(question_name), subrec->subnet_name));
-
- if(success && rrec->success_fn)
- {
- if(rrec->success_fn)
- (*rrec->success_fn)(subrec, rrec->userdata, question_name, released_ip);
- standard_success_release( subrec, rrec->userdata, question_name, released_ip);
- }
- else
- {
- /* We have no standard_fail_release - maybe we should add one ? */
- if( rrec->fail_fn)
- (*rrec->fail_fn)(subrec, rrec, question_name);
- }
-
- remove_response_record(subrec, rrec);
-}
-
-/****************************************************************************
- Try and release one of our names.
-****************************************************************************/
-
-BOOL release_name(struct subnet_record *subrec, struct name_record *namerec,
- release_name_success_function success_fn,
- release_name_fail_function fail_fn,
- struct userdata_struct *userdata)
-{
- int i;
-
- /* Ensure it's a SELF name, and in the ACTIVE state. */
- if((namerec->source != SELF_NAME) || !NAME_IS_ACTIVE(namerec))
- {
- DEBUG(0,("release_name: Cannot release name %s from subnet %s. Source was %d \n",
- namestr(&namerec->name), subrec->subnet_name, namerec->source));
- return True;
- }
-
- /* Set the name into the deregistering state. */
- namerec->nb_flags |= NB_DEREG;
-
- /*
- * Go through and release the name for all known ip addresses.
- * Only call the success/fail function on the last one (it should
- * only be done once).
- */
-
- for( i = 0; i < namerec->num_ips; i++)
- {
- if(queue_release_name( subrec,
- release_name_response,
- release_name_timeout_response,
- (i == (namerec->num_ips - 1)) ? success_fn : NULL,
- (i == (namerec->num_ips - 1)) ? fail_fn : NULL,
- (i == (namerec->num_ips - 1)) ? userdata : NULL,
- &namerec->name,
- namerec->nb_flags,
- namerec->ip[i]) == NULL)
- {
- DEBUG(0,("release_name: Failed to send packet trying to release name %s IP %s\n",
- namestr(&namerec->name), inet_ntoa(namerec->ip[i]) ));
- return True;
- }
- }
- return False;
-}
diff --git a/source/nmbd/nmbd_nodestatus.c b/source/nmbd/nmbd_nodestatus.c
deleted file mode 100644
index 267446c69dc..00000000000
--- a/source/nmbd/nmbd_nodestatus.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-extern pstring scope;
-
-/****************************************************************************
- Deal with a successful node status response.
-****************************************************************************/
-static void node_status_response(struct subnet_record *subrec,
- struct response_record *rrec, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question_name = &rrec->packet->packet.nmb.question.question_name;
- struct nmb_name *answer_name = &nmb->answers->rr_name;
-
- /* Sanity check. Ensure that the answer name in the incoming packet is the
- same as the requested name in the outgoing packet. */
-
- if(!nmb_name_equal(question_name, answer_name))
- {
- DEBUG(0,("node_status_response: Answer name %s differs from question \
-name %s.\n", namestr(answer_name), namestr(question_name)));
- return;
- }
-
- DEBUG(5,("node_status_response: response from name %s on subnet %s.\n",
- namestr(answer_name), subrec->subnet_name));
-
- /* Just send the whole answer resource record for the success function
- to parse. */
- if(rrec->success_fn)
- (*rrec->success_fn)(subrec, rrec->userdata, nmb->answers, p->ip);
-
- /* Ensure we don't retry. */
- remove_response_record(subrec, rrec);
-}
-
-/****************************************************************************
- Deal with a timeout when requesting a node status.
-****************************************************************************/
-static void node_status_timeout_response(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- struct nmb_packet *sent_nmb = &rrec->packet->packet.nmb;
- struct nmb_name *question_name = &sent_nmb->question.question_name;
-
- DEBUG(5,("node_status_timeout_response: failed to get node status from name %s on subnet %s\n",
- namestr(question_name), subrec->subnet_name));
-
- if( rrec->fail_fn)
- (*rrec->fail_fn)(subrec, rrec);
-
- /* Ensure we don't retry. */
- remove_response_record(subrec, rrec);
-}
-
-/****************************************************************************
- Try and do a node status to a name - given the name & IP address.
-****************************************************************************/
-
-BOOL node_status(struct subnet_record *subrec, struct nmb_name *nmbname,
- struct in_addr send_ip, node_status_success_function success_fn,
- node_status_fail_function fail_fn, struct userdata_struct *userdata)
-{
- if(queue_node_status( subrec,
- node_status_response, node_status_timeout_response,
- success_fn, fail_fn, userdata, nmbname, send_ip)==NULL)
- {
- DEBUG(0,("node_status: Failed to send packet trying to get node status for \
-name %s, IP address %s\n", namestr(nmbname), inet_ntoa(send_ip)));
- return True;
- }
- return False;
-}
diff --git a/source/nmbd/nmbd_packets.c b/source/nmbd/nmbd_packets.c
deleted file mode 100644
index 4fb05439673..00000000000
--- a/source/nmbd/nmbd_packets.c
+++ /dev/null
@@ -1,1831 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int ClientNMB;
-extern int ClientDGRAM;
-extern int global_nmb_port;
-
-extern int DEBUGLEVEL;
-
-extern int num_response_packets;
-
-extern pstring scope;
-extern struct in_addr loopback_ip;
-
-/*******************************************************************
- The global packet linked-list. Incoming entries are
- added to the end of this list. It is supposed to remain fairly
- short so we won't bother with an end pointer.
-******************************************************************/
-
-static struct packet_struct *packet_queue = NULL;
-
-/***************************************************************************
-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 )
-{
- struct subnet_record *subrec;
-
- for( subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- if(ip_equal(local_ip, subrec->myip))
- return subrec->nmb_sock;
-
- return ClientNMB;
-}
-
-/***************************************************************************
-Get/Set problematic nb_flags as network byte order 16 bit int.
-**************************************************************************/
-
-uint16 get_nb_flags(char *buf)
-{
- return ((((uint16)*buf)&0xFFFF) & NB_FLGMSK);
-}
-
-void set_nb_flags(char *buf, uint16 nb_flags)
-{
- *buf++ = ((nb_flags & NB_FLGMSK) & 0xFF);
- *buf = '\0';
-}
-
-/***************************************************************************
-Dumps out the browse packet data.
-**************************************************************************/
-
-static void debug_browse_data(char *outbuf, int len)
-{
- int i,j;
- for (i = 0; i < len; i+= 16)
- {
- DEBUG(4, ("%3x char ", i));
-
- for (j = 0; j < 16; j++)
- {
- unsigned char x = outbuf[i+j];
- if (x < 32 || x > 127)
- x = '.';
-
- if (i+j >= len)
- break;
- DEBUG(4, ("%c", x));
- }
-
- DEBUG(4, (" hex ", i));
-
- for (j = 0; j < 16; j++)
- {
- if (i+j >= len)
- break;
- DEBUG(4, (" %02x", (unsigned char)outbuf[i+j]));
- }
-
- DEBUG(4, ("\n"));
- }
-}
-
-/***************************************************************************
- Generates the unique transaction identifier
-**************************************************************************/
-
-static uint16 name_trn_id=0;
-
-static uint16 generate_name_trn_id(void)
-{
-
- if (!name_trn_id)
- {
- name_trn_id = (time(NULL)%(unsigned)0x7FFF) + (getpid()%(unsigned)100);
- }
- name_trn_id = (name_trn_id+1) % (unsigned)0x7FFF;
- return name_trn_id;
-}
-
-/***************************************************************************
- Either loops back or sends out a completed NetBIOS packet.
-**************************************************************************/
-
-static BOOL send_netbios_packet(struct packet_struct *p)
-{
- BOOL loopback_this_packet = False;
-
- /* Check if we are sending to or from ourselves as a WINS server. */
- if(ismyip(p->ip) && (p->port == global_nmb_port))
- loopback_this_packet = True;
-
- if(loopback_this_packet)
- {
- struct packet_struct *lo_packet = NULL;
- DEBUG(5,("send_netbios_packet: sending packet to ourselves.\n"));
- if((lo_packet = copy_packet(p)) == NULL)
- return False;
- queue_packet(lo_packet);
- }
- else if (!send_packet(p))
- {
- DEBUG(0,("send_netbios_packet: send_packet() to IP %s port %d failed\n",
- inet_ntoa(p->ip),p->port));
- return False;
- }
-
- return True;
-}
-
-/***************************************************************************
- Sets up the common elements of an outgoing NetBIOS packet.
-**************************************************************************/
-
-static struct packet_struct *create_and_init_netbios_packet(struct nmb_name *nmbname,
- BOOL bcast,
- struct in_addr to_ip)
-{
- struct packet_struct *packet = NULL;
- struct nmb_packet *nmb = NULL;
-
- /* Allocate the packet_struct we will return. */
- if((packet = (struct packet_struct *)malloc(sizeof(*packet))) == NULL)
- {
- DEBUG(0,("create_and_init_netbios_packet: malloc fail (1) for packet struct.\n"));
- return NULL;
- }
-
- bzero((char *)packet,sizeof(*packet));
-
- nmb = &packet->packet.nmb;
-
- nmb->header.name_trn_id = generate_name_trn_id();
- nmb->header.response = False;
- nmb->header.nm_flags.recursion_desired = False;
- nmb->header.nm_flags.recursion_available = False;
- nmb->header.nm_flags.trunc = False;
- nmb->header.nm_flags.authoritative = False;
- nmb->header.nm_flags.bcast = bcast;
-
- nmb->header.rcode = 0;
- nmb->header.qdcount = 1;
- nmb->header.ancount = 0;
- nmb->header.nscount = 0;
-
- nmb->question.question_name = *nmbname;
- nmb->question.question_type = QUESTION_TYPE_NB_QUERY;
- nmb->question.question_class = QUESTION_CLASS_IN;
-
- packet->ip = to_ip;
- packet->port = NMB_PORT;
- packet->fd = ClientNMB;
- packet->timestamp = time(NULL);
- packet->packet_type = NMB_PACKET;
- packet->locked = False;
-
- return packet; /* Caller must free. */
-}
-
-/***************************************************************************
- Sets up the common elements of register, refresh or release packet.
-**************************************************************************/
-
-static BOOL create_and_init_additional_record(struct packet_struct *packet,
- uint16 nb_flags,
- struct in_addr *register_ip)
-{
- struct nmb_packet *nmb = &packet->packet.nmb;
-
- if((nmb->additional = (struct res_rec *)malloc(sizeof(struct res_rec))) == NULL)
- {
- DEBUG(0,("initiate_name_register_packet: malloc fail for additional record.\n"));
- return False;
- }
-
- bzero((char *)nmb->additional,sizeof(struct res_rec));
-
- nmb->additional->rr_name = nmb->question.question_name;
- nmb->additional->rr_type = RR_TYPE_NB;
- nmb->additional->rr_class = RR_CLASS_IN;
-
- nmb->additional->ttl = lp_max_ttl();
-
- nmb->additional->rdlength = 6;
-
- set_nb_flags(nmb->additional->rdata,nb_flags);
-
- /* Set the address for the name we are registering. */
- putip(&nmb->additional->rdata[2], register_ip);
-
- /* Ensure that we send out the file descriptor to give us the
- the specific source address we are registering as our
- IP source address. */
-
- packet->fd = find_subnet_fd_for_address( *register_ip );
-
- return True;
-}
-
-/***************************************************************************
- Sends out a name query.
-**************************************************************************/
-
-static BOOL initiate_name_query_packet( struct packet_struct *packet)
-{
- struct nmb_packet *nmb = NULL;
-
- nmb = &packet->packet.nmb;
-
- nmb->header.opcode = NMB_NAME_QUERY_OPCODE;
- nmb->header.arcount = 0;
-
- nmb->header.nm_flags.recursion_desired = True;
-
- DEBUG(4,("initiate_name_query_packet: sending query for name %s (bcast=%s) to IP %s\n",
- namestr(&nmb->question.question_name),
- BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip)));
-
- return send_netbios_packet( packet );
-}
-
-/***************************************************************************
- Sends out a name register.
-**************************************************************************/
-
-static BOOL initiate_name_register_packet( struct packet_struct *packet,
- uint16 nb_flags, struct in_addr *register_ip)
-{
- struct nmb_packet *nmb = &packet->packet.nmb;
-
- nmb->header.opcode = NMB_NAME_REG_OPCODE;
- nmb->header.arcount = 1;
-
- nmb->header.nm_flags.recursion_desired = True;
-
- if(create_and_init_additional_record(packet, nb_flags, register_ip) == False)
- return False;
-
- DEBUG(4,("initiate_name_register_packet: sending registration for name %s (bcast=%s) to IP %s\n",
- namestr(&nmb->additional->rr_name),
- BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip)));
-
- return send_netbios_packet( packet );
-}
-
-/***************************************************************************
- Sends out a multihomed name register.
-**************************************************************************/
-
-static BOOL initiate_multihomed_name_register_packet( struct packet_struct *packet,
- uint16 nb_flags, struct in_addr *register_ip)
-{
- struct nmb_packet *nmb = &packet->packet.nmb;
- char second_ip_buf[25];
-
- strcpy(second_ip_buf, inet_ntoa(packet->ip));
-
- nmb->header.opcode = NMB_NAME_MULTIHOMED_REG_OPCODE;
- nmb->header.arcount = 1;
-
- nmb->header.nm_flags.recursion_desired = True;
-
- if(create_and_init_additional_record(packet, nb_flags, register_ip) == False)
- return False;
-
- DEBUG(4,("initiate_multihomed_name_register_packet: sending registration \
-for name %s IP %s (bcast=%s) to IP %s\n",
- namestr(&nmb->additional->rr_name), inet_ntoa(*register_ip),
- BOOLSTR(nmb->header.nm_flags.bcast), second_ip_buf ));
-
- return send_netbios_packet( packet );
-}
-
-/***************************************************************************
- Sends out a name refresh.
-**************************************************************************/
-
-static BOOL initiate_name_refresh_packet( struct packet_struct *packet,
- uint16 nb_flags, struct in_addr *refresh_ip)
-{
- struct nmb_packet *nmb = &packet->packet.nmb;
-
- nmb->header.opcode = NMB_NAME_REFRESH_OPCODE_8;
- nmb->header.arcount = 1;
-
- nmb->header.nm_flags.recursion_desired = False;
-
- if(create_and_init_additional_record(packet, nb_flags, refresh_ip) == False)
- return False;
-
- DEBUG(4,("initiate_name_refresh_packet: sending refresh for name %s (bcast=%s) to IP %s\n",
- namestr(&nmb->additional->rr_name),
- BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip)));
-
- return send_netbios_packet( packet );
-}
-
-/***************************************************************************
- Sends out a name release.
-**************************************************************************/
-
-static BOOL initiate_name_release_packet( struct packet_struct *packet,
- uint16 nb_flags, struct in_addr *release_ip)
-{
- struct nmb_packet *nmb = &packet->packet.nmb;
-
- nmb->header.opcode = NMB_NAME_RELEASE_OPCODE;
- nmb->header.arcount = 1;
-
- nmb->header.nm_flags.recursion_desired = False;
-
- if(create_and_init_additional_record(packet, nb_flags, release_ip) == False)
- return False;
-
- DEBUG(4,("initiate_name_release_packet: sending release for name %s (bcast=%s) to IP %s\n",
- namestr(&nmb->additional->rr_name),
- BOOLSTR(nmb->header.nm_flags.bcast), inet_ntoa(packet->ip)));
-
- return send_netbios_packet( packet );
-}
-
-/***************************************************************************
- Sends out a node status.
-**************************************************************************/
-
-static BOOL initiate_node_status_packet( struct packet_struct *packet )
-{
- struct nmb_packet *nmb = &packet->packet.nmb;
-
- nmb->header.opcode = NMB_NAME_QUERY_OPCODE;
- nmb->header.arcount = 0;
-
- nmb->header.nm_flags.recursion_desired = False;
-
- nmb->question.question_type = QUESTION_TYPE_NB_STATUS;
-
- DEBUG(4,("initiate_node_status_packet: sending node status request for name %s to IP %s\n",
- namestr(&nmb->question.question_name),
- inet_ntoa(packet->ip)));
-
- return send_netbios_packet( packet );
-}
-
-/****************************************************************************
- Simplification functions for queuing standard packets.
- These should be the only publicly callable functions for sending
- out packets.
-****************************************************************************/
-
-/****************************************************************************
- Assertion - we should never be sending nmbd packets on the remote
- broadcast subnet.
-****************************************************************************/
-
-static BOOL assert_check_subnet(struct subnet_record *subrec)
-{
- if( subrec == remote_broadcast_subnet)
- {
- DEBUG(0,("assert_check_subnet: Attempt to send packet on remote broadcast subnet. \
-This is a bug.\n"));
- return True;
- }
- return False;
-}
-
-/****************************************************************************
- Queue a register name packet to the broadcast address of a subnet.
-****************************************************************************/
-
-struct response_record *queue_register_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- register_name_success_function success_fn,
- register_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname,
- uint16 nb_flags)
-{
- struct packet_struct *p;
- struct response_record *rrec;
- BOOL bcast = (subrec == unicast_subnet) ? False : True;
-
- if(assert_check_subnet(subrec))
- return NULL;
-
- if(( p = create_and_init_netbios_packet(nmbname, bcast,
- subrec->bcast_ip)) == NULL)
- return NULL;
-
- if(initiate_name_register_packet( p, nb_flags,
- iface_ip(subrec->bcast_ip)) == False)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- if((rrec = make_response_record(subrec, /* subnet record. */
- p, /* packet we sent. */
- resp_fn, /* function to call on response. */
- timeout_fn, /* function to call on timeout. */
- (success_function)success_fn, /* function to call on operation success. */
- (fail_function)fail_fn, /* function to call on operation fail. */
- userdata)) == NULL)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- return rrec;
-}
-
-/****************************************************************************
- Queue a multihomed register name packet to the broadcast address of a subnet.
-****************************************************************************/
-
-struct response_record *queue_register_multihomed_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- register_name_success_function success_fn,
- register_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname,
- uint16 nb_flags,
- struct in_addr register_ip)
-{
- struct packet_struct *p;
- struct response_record *rrec;
- BOOL bcast = False;
- BOOL ret;
-
- /* Sanity check. */
- if(subrec != unicast_subnet)
- {
- DEBUG(0,("queue_register_multihomed_name: should only be done on \
-unicast subnet. subnet is %s\n.", subrec->subnet_name ));
- return NULL;
- }
-
- if(assert_check_subnet(subrec))
- return NULL;
-
- if(( p = create_and_init_netbios_packet(nmbname, bcast,
- subrec->bcast_ip)) == NULL)
- return NULL;
-
- if (nb_flags & NB_GROUP)
- ret = initiate_name_register_packet( p, nb_flags, &register_ip);
- else
- ret = initiate_multihomed_name_register_packet( p, nb_flags, &register_ip);
-
- if(ret == False)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- if((rrec = make_response_record(subrec, /* subnet record. */
- p, /* packet we sent. */
- resp_fn, /* function to call on response. */
- timeout_fn, /* function to call on timeout. */
- (success_function)success_fn, /* function to call on operation success. */
- (fail_function)fail_fn, /* function to call on operation fail. */
- userdata)) == NULL)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- return rrec;
-}
-
-/****************************************************************************
- Queue a release name packet to the broadcast address of a subnet.
-****************************************************************************/
-
-struct response_record *queue_release_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- release_name_success_function success_fn,
- release_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname,
- uint16 nb_flags,
- struct in_addr release_ip)
-{
- BOOL bcast = (subrec == unicast_subnet) ? False : True;
- struct packet_struct *p;
- struct response_record *rrec;
-
- if(assert_check_subnet(subrec))
- return NULL;
-
- if(( p = create_and_init_netbios_packet(nmbname, bcast,
- subrec->bcast_ip)) == NULL)
- return NULL;
-
- if(initiate_name_release_packet( p, nb_flags, &release_ip) == False)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- if((rrec = make_response_record(subrec, /* subnet record. */
- p, /* packet we sent. */
- resp_fn, /* function to call on response. */
- timeout_fn, /* function to call on timeout. */
- (success_function)success_fn, /* function to call on operation success. */
- (fail_function)fail_fn, /* function to call on operation fail. */
- userdata)) == NULL)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- return rrec;
-}
-
-/****************************************************************************
- Queue a refresh name packet to the broadcast address of a subnet.
-****************************************************************************/
-
-struct response_record *queue_refresh_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- refresh_name_success_function success_fn,
- refresh_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct name_record *namerec,
- struct in_addr refresh_ip)
-{
- BOOL bcast = (subrec == unicast_subnet) ? False : True;
- struct packet_struct *p;
- struct response_record *rrec;
-
- if(assert_check_subnet(subrec))
- return NULL;
-
- if(( p = create_and_init_netbios_packet(&namerec->name, bcast,
- subrec->bcast_ip)) == NULL)
- return NULL;
-
- if(initiate_name_refresh_packet( p, namerec->nb_flags, &refresh_ip) == False)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- if((rrec = make_response_record(subrec, /* subnet record. */
- p, /* packet we sent. */
- resp_fn, /* function to call on response. */
- timeout_fn, /* function to call on timeout. */
- (success_function)success_fn, /* function to call on operation success. */
- (fail_function)fail_fn, /* function to call on operation fail. */
- userdata)) == NULL)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- return rrec;
-}
-
-/****************************************************************************
- Queue a query name packet to the broadcast address of a subnet.
-****************************************************************************/
-
-struct response_record *queue_query_name( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- query_name_success_function success_fn,
- query_name_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname)
-{
- struct packet_struct *p;
- struct response_record *rrec;
- BOOL bcast = True;
-
- if ((subrec == unicast_subnet) || (subrec == wins_server_subnet))
- bcast = False;
-
- if(assert_check_subnet(subrec))
- return NULL;
-
- if(( p = create_and_init_netbios_packet(nmbname, bcast,
- subrec->bcast_ip)) == NULL)
- return NULL;
-
- if(initiate_name_query_packet( p ) == False)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- if((rrec = make_response_record(subrec, /* subnet record. */
- p, /* packet we sent. */
- resp_fn, /* function to call on response. */
- timeout_fn, /* function to call on timeout. */
- (success_function)success_fn, /* function to call on operation success. */
- (fail_function)fail_fn, /* function to call on operation fail. */
- userdata)) == NULL)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- return rrec;
-}
-
-/****************************************************************************
- Queue a node status packet to a given name and address.
-****************************************************************************/
-
-struct response_record *queue_node_status( struct subnet_record *subrec,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- node_status_success_function success_fn,
- node_status_fail_function fail_fn,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname,
- struct in_addr send_ip)
-{
- struct packet_struct *p;
- struct response_record *rrec;
- BOOL bcast = False;
-
- /* Sanity check. */
- if(subrec != unicast_subnet)
- {
- DEBUG(0,("queue_register_multihomed_name: should only be done on \
-unicast subnet. subnet is %s\n.", subrec->subnet_name ));
- return NULL;
- }
-
- if(assert_check_subnet(subrec))
- return NULL;
-
- if(( p = create_and_init_netbios_packet(nmbname, bcast,
- send_ip)) == NULL)
- return NULL;
-
- if(initiate_node_status_packet(p) == False)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- if((rrec = make_response_record(subrec, /* subnet record. */
- p, /* packet we sent. */
- resp_fn, /* function to call on response. */
- timeout_fn, /* function to call on timeout. */
- (success_function)success_fn, /* function to call on operation success. */
- (fail_function)fail_fn, /* function to call on operation fail. */
- userdata)) == NULL)
- {
- p->locked = False;
- free_packet(p);
- return NULL;
- }
-
- return rrec;
-}
-
-/****************************************************************************
- Reply to a netbios name packet. see rfc1002.txt
-****************************************************************************/
-
-void reply_netbios_packet(struct packet_struct *orig_packet,
- int rcode, enum netbios_reply_type_code rcv_code, int opcode,
- int ttl, char *data,int len)
-{
- struct packet_struct packet;
- struct nmb_packet *nmb = NULL;
- struct res_rec answers;
- struct nmb_packet *orig_nmb = &orig_packet->packet.nmb;
- BOOL loopback_this_packet = False;
- char *packet_type = "unknown";
-
- /* Check if we are sending to or from ourselves. */
- if(ismyip(orig_packet->ip) && (orig_packet->port == global_nmb_port))
- loopback_this_packet = True;
-
- nmb = &packet.packet.nmb;
-
- /* Do a partial copy of the packet. We clear the locked flag and
- the resource record pointers. */
- packet = *orig_packet; /* Full structure copy. */
- packet.locked = False;
- nmb->answers = NULL;
- nmb->nsrecs = NULL;
- nmb->additional = NULL;
-
- switch (rcv_code)
- {
- case NMB_STATUS:
- {
- packet_type = "nmb_status";
- nmb->header.nm_flags.recursion_desired = False;
- nmb->header.nm_flags.recursion_available = False;
- break;
- }
- case NMB_QUERY:
- {
- packet_type = "nmb_query";
- nmb->header.nm_flags.recursion_desired = True;
- nmb->header.nm_flags.recursion_available = True;
- break;
- }
- case NMB_REG:
- case NMB_REG_REFRESH:
- {
- packet_type = "nmb_reg";
- nmb->header.nm_flags.recursion_desired = True;
- nmb->header.nm_flags.recursion_available = True;
- break;
- }
- case NMB_REL:
- {
- packet_type = "nmb_rel";
- nmb->header.nm_flags.recursion_desired = False;
- nmb->header.nm_flags.recursion_available = False;
- break;
- }
- case NMB_WAIT_ACK:
- {
- packet_type = "nmb_wack";
- nmb->header.nm_flags.recursion_desired = False;
- nmb->header.nm_flags.recursion_available = False;
- break;
- }
- case WINS_REG:
- {
- packet_type = "wins_reg";
- nmb->header.nm_flags.recursion_desired = True;
- nmb->header.nm_flags.recursion_available = True;
- break;
- }
- case WINS_QUERY:
- {
- packet_type = "wins_query";
- nmb->header.nm_flags.recursion_desired = True;
- nmb->header.nm_flags.recursion_available = True;
- break;
- }
-
- default:
- {
- DEBUG(0,("reply_netbios_packet: Unknown packet type: %s %s to ip %s\n",
- packet_type, namestr(&orig_nmb->question.question_name),
- inet_ntoa(packet.ip)));
-
- return;
- }
- }
-
- DEBUG(4,("reply_netbios_packet: sending a reply of packet type: %s %s to ip %s \
-for id %hu\n",
- packet_type, namestr(&orig_nmb->question.question_name),
- inet_ntoa(packet.ip), orig_nmb->header.name_trn_id));
-
- nmb->header.name_trn_id = orig_nmb->header.name_trn_id;
- nmb->header.opcode = opcode;
- nmb->header.response = True;
- nmb->header.nm_flags.bcast = False;
- nmb->header.nm_flags.trunc = False;
- nmb->header.nm_flags.authoritative = True;
-
- nmb->header.rcode = rcode;
- nmb->header.qdcount = 0;
- nmb->header.ancount = 1;
- nmb->header.nscount = 0;
- nmb->header.arcount = 0;
-
- bzero((char*)&nmb->question,sizeof(nmb->question));
-
- nmb->answers = &answers;
- bzero((char*)nmb->answers,sizeof(*nmb->answers));
-
- nmb->answers->rr_name = orig_nmb->question.question_name;
- nmb->answers->rr_type = orig_nmb->question.question_type;
- nmb->answers->rr_class = orig_nmb->question.question_class;
- nmb->answers->ttl = ttl;
-
- if (data && len)
- {
- nmb->answers->rdlength = len;
- memcpy(nmb->answers->rdata, data, len);
- }
-
- packet.packet_type = NMB_PACKET;
- /* Ensure we send out on the same fd that the original
- packet came in on to give the correct source IP address. */
- packet.fd = orig_packet->fd;
- packet.timestamp = time(NULL);
-
- debug_nmb_packet(&packet);
-
- if(loopback_this_packet)
- {
- struct packet_struct *lo_packet;
- DEBUG(5,("reply_netbios_packet: sending packet to ourselves.\n"));
- if((lo_packet = copy_packet(&packet)) == NULL)
- return;
- queue_packet(lo_packet);
- }
- else if (!send_packet(&packet))
- {
- DEBUG(0,("reply_netbios_packet: send_packet to IP %s port %d failed\n",
- inet_ntoa(packet.ip),packet.port));
- }
-}
-
-/*******************************************************************
- Queue a packet into a packet queue
-******************************************************************/
-
-void queue_packet(struct packet_struct *packet)
-{
- struct packet_struct *p;
-
- if (!packet_queue)
- {
- packet->prev = NULL;
- packet->next = NULL;
- packet_queue = packet;
- return;
- }
-
- /* find the bottom */
- for (p=packet_queue;p->next;p=p->next)
- ;
-
- p->next = packet;
- packet->next = NULL;
- packet->prev = p;
-}
-
-/****************************************************************************
- Try and find a matching subnet record for a datagram port 138 packet.
-****************************************************************************/
-
-static struct subnet_record *find_subnet_for_dgram_browse_packet(struct packet_struct *p)
-{
- struct subnet_record *subrec;
-
- /* Go through all the broadcast subnets and see if the mask matches. */
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip))
- return subrec;
- }
-
- /* If the subnet record is the remote announce broadcast subnet,
- hack it here to be the first subnet. This is really gross and
- is needed due to people turning on port 137/138 broadcast
- forwarding on their routers. May fire and brimstone rain
- down upon them...
- */
-
- return FIRST_SUBNET;
-}
-
-/****************************************************************************
-Dispatch a browse frame from port 138 to the correct processing function.
-****************************************************************************/
-
-void process_browse_packet(struct packet_struct *p, char *buf,int len)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int command = CVAL(buf,0);
- struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p);
-
- /* Drop the packet if it's a different NetBIOS scope, or
- the source is from one of our names. */
-
- if (!strequal(dgram->dest_name.scope,scope ))
- {
- DEBUG(7,("process_browse_packet: Discarding datagram from IP %s. Scope (%s) \
-mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, scope));
- return;
- }
-
- if (is_myname(dgram->source_name.name))
- {
- DEBUG(0,("process_browse_packet: Discarding datagram from IP %s. Source name \
-%s is one of our names !\n", inet_ntoa(p->ip), namestr(&dgram->source_name)));
- return;
- }
-
- switch (command)
- {
- case ANN_HostAnnouncement:
- {
- debug_browse_data(buf, len);
- process_host_announce(subrec, p, buf+1);
- break;
- }
- case ANN_DomainAnnouncement:
- {
- debug_browse_data(buf, len);
- process_workgroup_announce(subrec, p, buf+1);
- break;
- }
- case ANN_LocalMasterAnnouncement:
- {
- debug_browse_data(buf, len);
- process_local_master_announce(subrec, p, buf+1);
- break;
- }
- case ANN_AnnouncementRequest:
- {
- process_announce_request(subrec, p, buf+1);
- break;
- }
- case ANN_Election:
- {
- process_election(subrec, p, buf+1);
- break;
- }
- case ANN_GetBackupListReq:
- {
- debug_browse_data(buf, len);
-
- /* This is one occasion where we change a subnet that is
- given to us. If the packet was sent to WORKGROUP<1b> instead
- of WORKGROUP<1d> then it was unicast to us a domain master
- browser. Change subrec to unicast.
- */
- if(dgram->dest_name.name_type == 0x1b)
- subrec = unicast_subnet;
-
- process_get_backup_list_request(subrec, p, buf+1);
- break;
- }
- case ANN_GetBackupListResp:
- {
- debug_browse_data(buf, len);
- /* We never send ANN_GetBackupListReq so we
- should never get these. */
- DEBUG(0,("process_browse_packet: Discarding GetBackupListResponse \
-packet from %s IP %s\n", namestr(&dgram->source_name), inet_ntoa(p->ip)));
- break;
- }
- case ANN_ResetBrowserState:
- {
- process_reset_browser(subrec, p, buf+1);
- break;
- }
- case ANN_MasterAnnouncement:
- {
- /* Master browser datagrams must be processed
- on the unicast subnet. */
- subrec = unicast_subnet;
-
- process_master_browser_announce(subrec, p, buf+1);
- break;
- }
- default:
- {
- DEBUG(0,("process_browse_packet: On subnet %s ignoring browse packet \
-command code %d from %s IP %s to %s\n",
- subrec->subnet_name, command, namestr(&dgram->source_name),
- inet_ntoa(p->ip), namestr(&dgram->dest_name)));
- }
- }
-}
-
-/****************************************************************************
- Dispatch a LanMan browse frame from port 138 to the correct processing function.
-****************************************************************************/
-
-void process_lanman_packet(struct packet_struct *p, char *buf,int len)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- int command = SVAL(buf,0);
- struct subnet_record *subrec = find_subnet_for_dgram_browse_packet(p);
-
- /* Drop the packet if it's a different NetBIOS scope, or
- the source is from one of our names. */
-
- if (!strequal(dgram->dest_name.scope,scope ))
- {
- DEBUG(7,("process_lanman_packet: Discarding datagram from IP %s. Scope (%s) \
-mismatch with our scope (%s).\n", inet_ntoa(p->ip), dgram->dest_name.scope, scope));
- return;
- }
-
- if (is_myname(dgram->source_name.name))
- {
- DEBUG(0,("process_lanman_packet: Discarding datagram from IP %s. Source name \
-%s is one of our names !\n", inet_ntoa(p->ip), namestr(&dgram->source_name)));
- return;
- }
-
- switch (command)
- {
- case ANN_HostAnnouncement:
- {
- debug_browse_data(buf, len);
- process_lm_host_announce(subrec, p, buf+1);
- break;
- }
- case ANN_AnnouncementRequest:
- {
- process_lm_announce_request(subrec, p, buf+1);
- break;
- }
- default:
- {
- DEBUG(0,("process_lanman_packet: On subnet %s ignoring browse packet \
-command code %d from %s IP %s to %s\n",
- subrec->subnet_name, command, namestr(&dgram->source_name),
- inet_ntoa(p->ip), namestr(&dgram->dest_name)));
- }
- }
-}
-
-/****************************************************************************
- Determine if a packet is for us on port 138. Note that to have any chance of
- being efficient we need to drop as many packets as possible at this
- stage as subsequent processing is expensive.
-****************************************************************************/
-
-static BOOL listening(struct packet_struct *p,struct nmb_name *nbname)
-{
- struct subnet_record *subrec = NULL;
-
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip))
- break;
- }
-
- if(subrec == NULL)
- subrec = unicast_subnet;
-
- return (find_name_on_subnet(subrec, nbname, FIND_SELF_NAME) != NULL);
-}
-
-/****************************************************************************
- Process udp 138 datagrams
-****************************************************************************/
-
-static void process_dgram(struct packet_struct *p)
-{
- char *buf;
- char *buf2;
- int len;
- struct dgram_packet *dgram = &p->packet.dgram;
-
- /* If we aren't listening to the destination name then ignore the packet */
- if (!listening(p,&dgram->dest_name))
- {
- DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from %s\n",
- namestr(&dgram->dest_name), inet_ntoa(p->ip)));
- return;
- }
-
- if (dgram->header.msg_type != 0x10 &&
- dgram->header.msg_type != 0x11 &&
- dgram->header.msg_type != 0x12)
- {
- /* Don't process error packets etc yet */
- DEBUG(5,("process_dgram: ignoring dgram packet sent to name %s from IP %s as it is \
- an error packet of type %x\n",
- namestr(&dgram->dest_name), inet_ntoa(p->ip), dgram->header.msg_type));
- return;
- }
-
- buf = &dgram->data[0];
- buf -= 4; /* XXXX for the pseudo tcp length -
- someday I need to get rid of this */
-
- if (CVAL(buf,smb_com) != SMBtrans)
- return;
-
- len = SVAL(buf,smb_vwv11);
- buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
-
- DEBUG(4,("process_dgram: datagram from %s to %s IP %s for %s of type %d len=%d\n",
- namestr(&dgram->source_name),namestr(&dgram->dest_name),
- inet_ntoa(p->ip), smb_buf(buf),CVAL(buf2,0),len));
-
-
- if (len <= 0)
- return;
-
- /* Datagram packet received for the browser mailslot */
- if (strequal(smb_buf(buf),BROWSE_MAILSLOT))
- {
- process_browse_packet(p,buf2,len);
- return;
- }
-
- /* Datagram packet received for the LAN Manager mailslot */
- if (strequal(smb_buf(buf),LANMAN_MAILSLOT)) {
- process_lanman_packet(p,buf2,len);
- return;
- }
-
- /* Datagram packet received for the domain logon mailslot */
- if (strequal(smb_buf(buf),NET_LOGON_MAILSLOT))
- {
- process_logon_packet(p,buf2,len,NET_LOGON_MAILSLOT);
- return;
- }
-
- /* Datagram packet received for the NT domain logon mailslot */
- if (strequal(smb_buf(buf),NT_LOGON_MAILSLOT))
- {
- process_logon_packet(p,buf2,len,NT_LOGON_MAILSLOT);
- return;
- }
-}
-
-/****************************************************************************
- Validate a response nmb packet.
-****************************************************************************/
-
-BOOL validate_nmb_response_packet( struct nmb_packet *nmb )
-{
- BOOL ignore = False;
-
- switch (nmb->header.opcode)
- {
- case NMB_NAME_REG_OPCODE:
- case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
- case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
- if (nmb->header.ancount == 0)
- {
- DEBUG(0,("validate_nmb_response_packet: Bad REG/REFRESH Packet. "));
- ignore = True;
- }
- break;
-
- case NMB_NAME_QUERY_OPCODE:
- if ((nmb->header.ancount != 0) && (nmb->header.ancount != 1))
- {
- DEBUG(0,("validate_nmb_response_packet: Bad QUERY Packet. "));
- ignore = True;
- }
- break;
- case NMB_NAME_RELEASE_OPCODE:
- if (nmb->header.ancount == 0)
- {
- DEBUG(0,("validate_nmb_response_packet: Bad RELEASE Packet. "));
- ignore = True;
- }
- break;
- case NMB_WACK_OPCODE:
- /* Check WACK response here. */
- if (nmb->header.ancount != 1)
- {
- DEBUG(0,("validate_nmb_response_packet: Bad WACK Packet. "));
- ignore = True;
- }
- break;
- default:
- DEBUG(0,("validate_nmb_response_packet: Ignoring packet with unknown opcode %d.\n",
- nmb->header.opcode));
- return True;
- }
-
- if(ignore)
- DEBUG(0,("Ignoring response packet with opcode %d.\n", nmb->header.opcode));
-
- return ignore;
-}
-
-/****************************************************************************
- Validate a request nmb packet.
-****************************************************************************/
-
-BOOL validate_nmb_packet( struct nmb_packet *nmb )
-{
- BOOL ignore = False;
-
- switch (nmb->header.opcode)
- {
- case NMB_NAME_REG_OPCODE:
- case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
- case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
- case NMB_NAME_MULTIHOMED_REG_OPCODE:
- if (nmb->header.qdcount==0 || nmb->header.arcount==0)
- {
- DEBUG(0,("validate_nmb_packet: Bad REG/REFRESH Packet. "));
- ignore = True;
- }
- break;
-
- case NMB_NAME_QUERY_OPCODE:
- if ((nmb->header.qdcount == 0) ||
- ((nmb->question.question_type != QUESTION_TYPE_NB_QUERY) &&
- (nmb->question.question_type != QUESTION_TYPE_NB_STATUS)))
- {
- DEBUG(0,("validate_nmb_packet: Bad QUERY Packet. "));
- ignore = True;
- }
- break;
-
- case NMB_NAME_RELEASE_OPCODE:
- if (nmb->header.qdcount==0 || nmb->header.arcount==0)
- {
- DEBUG(0,("validate_nmb_packet: Bad RELEASE Packet. "));
- ignore = True;
- }
- break;
- default:
- DEBUG(0,("validate_nmb_packet: Ignoring packet with unknown opcode %d.\n",
- nmb->header.opcode));
- return True;
- }
-
- if(ignore)
- DEBUG(0,("validate_nmb_packet: Ignoring request packet with opcode %d.\n", nmb->header.opcode));
-
- return ignore;
-}
-
-/****************************************************************************
- Find a subnet (and potentially a response record) for a packet.
-****************************************************************************/
-
-static struct subnet_record *find_subnet_for_nmb_packet( struct packet_struct *p,
- struct response_record **pprrec)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct response_record *rrec = NULL;
- struct subnet_record *subrec = NULL;
-
- if(pprrec != NULL)
- *pprrec = NULL;
-
- if(nmb->header.response)
- {
- /* It's a response packet. Find a record for it or it's an error. */
-
- rrec = find_response_record( &subrec, nmb->header.name_trn_id);
- if(rrec == NULL)
- {
- DEBUG(0,("find_subnet_for_nmb_packet: response record not found for response id %hu\n",
- nmb->header.name_trn_id));
- return NULL;
- }
-
- if(subrec == NULL)
- {
- DEBUG(0,("find_subnet_for_nmb_packet: subnet record not found for response id %hu\n",
- nmb->header.name_trn_id));
- return NULL;
- }
-
- if(pprrec != NULL)
- *pprrec = rrec;
- return subrec;
- }
-
- /* Try and see what subnet this packet belongs to. */
-
- /* WINS server ? */
- if(packet_is_for_wins_server(p))
- 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;
-
- /* Go through all the broadcast subnets and see if the mask matches. */
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- if(same_net(p->ip, subrec->bcast_ip, subrec->mask_ip))
- return subrec;
- }
-
- /* If none match it must have been a directed broadcast - assign
- the remote_broadcast_subnet. */
- return remote_broadcast_subnet;
-}
-
-/****************************************************************************
- Process a nmb request packet - validate the packet and route it.
-****************************************************************************/
-
-static void process_nmb_request(struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct subnet_record *subrec = NULL;
-
- debug_nmb_packet(p);
-
- /* Ensure we have a good packet. */
- if(validate_nmb_packet(nmb))
- return;
-
- /* Allocate a subnet to this packet - if we cannot - fail. */
- if((subrec = find_subnet_for_nmb_packet(p, NULL))==NULL)
- return;
-
- switch (nmb->header.opcode)
- {
- case NMB_NAME_REG_OPCODE:
- if(subrec == wins_server_subnet)
- wins_process_name_registration_request(subrec, p);
- else
- process_name_registration_request(subrec, p);
- break;
-
- case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
- case NMB_NAME_REFRESH_OPCODE_9:
- if(subrec == wins_server_subnet)
- wins_process_name_refresh_request(subrec, p);
- else
- process_name_refresh_request(subrec, p);
- break;
-
- case NMB_NAME_MULTIHOMED_REG_OPCODE:
- if(subrec == wins_server_subnet)
- wins_process_multihomed_name_registration_request(subrec, p);
- else
- {
- DEBUG(0,("process_nmb_request: Multihomed registration request must be \
-directed at a WINS server.\n"));
- }
- break;
-
- case NMB_NAME_QUERY_OPCODE:
- switch (nmb->question.question_type)
- {
- case QUESTION_TYPE_NB_QUERY:
- {
- if(subrec == wins_server_subnet)
- wins_process_name_query_request(subrec, p);
- else
- process_name_query_request(subrec, p);
- break;
- }
- case QUESTION_TYPE_NB_STATUS:
- {
- if(subrec == wins_server_subnet)
- {
- DEBUG(0,("process_nmb_request: NB_STATUS request directed at WINS server is \
-not allowed.\n"));
- break;
- }
- else
- process_node_status_request(subrec, p);
- break;
- }
- }
- break;
-
- case NMB_NAME_RELEASE_OPCODE:
- if(subrec == wins_server_subnet)
- wins_process_name_release_request(subrec, p);
- else
- process_name_release_request(subrec, p);
- break;
- }
-}
-
-/****************************************************************************
- Process a nmb response packet - validate the packet and route it.
- to either the WINS server or a normal response.
-****************************************************************************/
-
-static void process_nmb_response(struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct subnet_record *subrec = NULL;
- struct response_record *rrec = NULL;
-
- debug_nmb_packet(p);
-
- if(validate_nmb_response_packet(nmb))
- return;
-
- if((subrec = find_subnet_for_nmb_packet(p, &rrec))==NULL)
- return;
-
- if(rrec == NULL)
- {
- DEBUG(0,("process_nmb_response: response packet received but no response record \
-found for id = %hu. Ignoring packet.\n", nmb->header.name_trn_id));
- return;
- }
-
- /* Increment the number of responses received for this record. */
- rrec->num_msgs++;
- /* Ensure we don't re-send the request. */
- rrec->repeat_count = 0;
-
- /* Call the response received function for this packet. */
- (*rrec->resp_fn)(subrec, rrec, p);
-}
-
-
-/*******************************************************************
- Run elements off the packet queue till its empty
-******************************************************************/
-
-void run_packet_queue()
-{
- struct packet_struct *p;
-
- while ((p = packet_queue))
- {
- packet_queue = p->next;
- if (packet_queue)
- packet_queue->prev = NULL;
- p->next = p->prev = NULL;
-
- switch (p->packet_type)
- {
- case NMB_PACKET:
- if(p->packet.nmb.header.response)
- process_nmb_response(p);
- else
- process_nmb_request(p);
- break;
-
- case DGRAM_PACKET:
- process_dgram(p);
- break;
- }
- free_packet(p);
- }
-}
-
-/*******************************************************************
- Retransmit or timeout elements from all the outgoing subnet response
- record queues.
-******************************************************************/
-
-void retransmit_or_expire_response_records(time_t t)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- struct response_record *rrec, *nextrrec;
-
- for (rrec = subrec->responselist; rrec; rrec = nextrrec)
- {
- nextrrec = rrec->next;
-
- if (rrec->repeat_time <= t)
- {
- if (rrec->repeat_count > 0)
- {
- /* Resend while we have a non-zero repeat_count. */
- if(!send_packet(rrec->packet))
- {
- DEBUG(0,("retransmit_or_expire_response_records: Failed to resend packet id %hu \
-to IP %s on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip),
- subrec->subnet_name));
- }
- rrec->repeat_time += rrec->repeat_interval;
- rrec->repeat_count--;
- }
- else
- {
- DEBUG(4,("retransmit_or_expire_response_records: timeout for packet id %hu to IP %s \
-on subnet %s\n", rrec->response_id, inet_ntoa(rrec->packet->ip),
- subrec->subnet_name));
-
- /* Call the timeout function. This will deal with removing the
- timed out packet. */
- if(rrec->timeout_fn)
- (*rrec->timeout_fn)(subrec, rrec);
- else
- {
- /* We must remove the record ourself if there is
- no timeout function. */
- remove_response_record(subrec, rrec);
- }
- } /* rrec->repeat_count > 0 */
- } /* rrec->repeat_time <= t */
- } /* end for rrec */
- } /* end for subnet */
-}
-
-/****************************************************************************
- Create an fd_set containing all the sockets in the subnet structures,
- plus the broadcast sockets.
-***************************************************************************/
-
-static BOOL create_listen_fdset(fd_set **ppset, int **psock_array, int *listen_number)
-{
- int *sock_array = NULL;
- struct subnet_record *subrec = NULL;
- int count = 0;
- int num = 0;
- fd_set *pset = (fd_set *)malloc(sizeof(fd_set));
-
- if(pset == NULL)
- {
- DEBUG(0,("create_listen_fdset: malloc fail !\n"));
- return True;
- }
-
- /* Check that we can add all the fd's we need. */
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- count++;
-
- if((count*2) + 2 > FD_SETSIZE)
- {
- DEBUG(0,("create_listen_fdset: Too many file descriptors needed (%d). We can \
-only use %d.\n", (count*2) + 2, FD_SETSIZE));
- return True;
- }
-
- if((sock_array = (int *)malloc(((count*2) + 2)*sizeof(int))) == NULL)
- {
- DEBUG(0,("create_listen_fdset: malloc fail for socket array.\n"));
- return True;
- }
-
- FD_ZERO(pset);
-
- /* Add in the broadcast socket on 137. */
- FD_SET(ClientNMB,pset);
- sock_array[num++] = ClientNMB;
-
- /* Add in the 137 sockets on all the interfaces. */
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- FD_SET(subrec->nmb_sock,pset);
- sock_array[num++] = subrec->nmb_sock;
- }
-
- /* Add in the broadcast socket on 138. */
- FD_SET(ClientDGRAM,pset);
- sock_array[num++] = ClientDGRAM;
-
- /* Add in the 138 sockets on all the interfaces. */
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- FD_SET(subrec->dgram_sock,pset);
- sock_array[num++] = subrec->dgram_sock;
- }
-
- *listen_number = (count*2) + 2;
- *ppset = pset;
- *psock_array = sock_array;
-
- return False;
-}
-
-/****************************************************************************
- Listens for NMB or DGRAM packets, and queues them.
-***************************************************************************/
-
-BOOL listen_for_packets(BOOL run_election)
-{
- static fd_set *listen_set = NULL;
- static int listen_number = 0;
- static int *sock_array = NULL;
-
- fd_set fds;
- int selrtn;
- struct timeval timeout;
-#ifndef SYNC_DNS
- int dns_fd;
-#endif
-
- if(listen_set == NULL)
- {
- if(create_listen_fdset(&listen_set, &sock_array, &listen_number))
- {
- DEBUG(0,("listen_for_packets: Fatal error. unable to create listen set. Exiting.\n"));
- return True;
- }
- }
-
- memcpy((char *)&fds, (char *)listen_set, sizeof(fd_set));
-
-#ifndef SYNC_DNS
- dns_fd = asyncdns_fd();
- if (dns_fd != -1) {
- FD_SET(dns_fd, &fds);
- }
-#endif
-
-
- /*
- * During elections and when expecting a netbios response packet we
- * need to send election packets at tighter intervals.
- * Ideally it needs to be the interval (in ms) between time now and
- * the time we are expecting the next netbios packet.
- */
-
- timeout.tv_sec = (run_election||num_response_packets) ? 1 : NMBD_SELECT_LOOP;
- timeout.tv_usec = 0;
-
- /* We can only take term signals when we are in the select. */
- BlockSignals(False, SIGTERM);
- selrtn = sys_select(&fds,&timeout);
- BlockSignals(True, SIGTERM);
-
- if(selrtn > 0)
- {
- int i;
-
-#ifndef SYNC_DNS
- if (dns_fd != -1 && FD_ISSET(dns_fd,&fds)) {
- run_dns_queue();
- }
-#endif
-
- for(i = 0; i < listen_number; i++)
- {
- if(i < (listen_number/2))
- {
- /* Processing a 137 socket. */
- if (FD_ISSET(sock_array[i],&fds))
- {
- struct packet_struct *packet = read_packet(sock_array[i], NMB_PACKET);
- if (packet)
- {
- /*
- * If we got a packet on the broadcast socket and interfaces
- * only is set then check it came from one of our local nets.
- */
- if(lp_bind_interfaces_only() && (sock_array[i] == ClientNMB) &&
- (!is_local_net(packet->ip)))
- {
- DEBUG(7,("discarding nmb packet sent to broadcast socket from %s:%d\n",
- inet_ntoa(packet->ip),packet->port));
- free_packet(packet);
- }
- else if ((ip_equal(loopback_ip, packet->ip) ||
- ismyip(packet->ip)) && packet->port == global_nmb_port)
- {
- DEBUG(7,("discarding own packet from %s:%d\n",
- inet_ntoa(packet->ip),packet->port));
- free_packet(packet);
- }
- else
- {
- /* Save the file descriptor this packet came in on. */
- packet->fd = sock_array[i];
- queue_packet(packet);
- }
- }
- }
- }
- else
- {
- /* Processing a 138 socket. */
-
- if (FD_ISSET(sock_array[i],&fds))
- {
- struct packet_struct *packet = read_packet(sock_array[i], DGRAM_PACKET);
- if (packet)
- {
- /*
- * If we got a packet on the broadcast socket and interfaces
- * only is set then check it came from one of our local nets.
- */
- if(lp_bind_interfaces_only() && (sock_array[i] == ClientDGRAM) &&
- (!is_local_net(packet->ip)))
- {
- DEBUG(7,("discarding dgram packet sent to broadcast socket from %s:%d\n",
- inet_ntoa(packet->ip),packet->port));
- free_packet(packet);
- }
- else if ((ip_equal(loopback_ip, packet->ip) ||
- ismyip(packet->ip)) && packet->port == DGRAM_PORT)
- {
- DEBUG(7,("discarding own packet from %s:%d\n",
- inet_ntoa(packet->ip),packet->port));
- free_packet(packet);
- }
- else
- {
- /* Save the file descriptor this packet came in on. */
- packet->fd = sock_array[i];
- queue_packet(packet);
- }
- }
- }
- } /* end processing 138 socket. */
- } /* end for */
- } /* end if selret > 0 */
- return False;
-}
-
-/****************************************************************************
- Construct and send a netbios DGRAM.
- Note that this currently sends all packets to port 138.
-**************************************************************************/
-
-BOOL send_mailslot(BOOL unique, char *mailslot,char *buf,int len,
- char *srcname, int src_type,
- char *dstname, int dest_type,
- struct in_addr dest_ip,struct in_addr src_ip)
-{
- BOOL loopback_this_packet = False;
- struct packet_struct p;
- struct dgram_packet *dgram = &p.packet.dgram;
- char *ptr,*p2;
- char tmp[4];
-
- bzero((char *)&p,sizeof(p));
-
- if(ismyip(dest_ip))
- loopback_this_packet = True;
-
- generate_name_trn_id();
-
- /* DIRECT GROUP or UNIQUE datagram. */
- dgram->header.msg_type = unique ? 0x10 : 0x11;
- dgram->header.flags.node_type = M_NODE;
- dgram->header.flags.first = True;
- dgram->header.flags.more = False;
- dgram->header.dgm_id = name_trn_id;
- dgram->header.source_ip = src_ip;
- dgram->header.source_port = DGRAM_PORT;
- dgram->header.dgm_length = 0; /* Let build_dgram() handle this. */
- dgram->header.packet_offset = 0;
-
- make_nmb_name(&dgram->source_name,srcname,0,scope);
- make_nmb_name(&dgram->dest_name,dstname,dest_type,scope);
-
- ptr = &dgram->data[0];
-
- /* Setup the smb part. */
- ptr -= 4; /* XXX Ugliness because of handling of tcp SMB length. */
- memcpy(tmp,ptr,4);
- set_message(ptr,17,17 + len,True);
- memcpy(ptr,tmp,4);
-
- CVAL(ptr,smb_com) = SMBtrans;
- SSVAL(ptr,smb_vwv1,len);
- SSVAL(ptr,smb_vwv11,len);
- SSVAL(ptr,smb_vwv12,70 + strlen(mailslot));
- SSVAL(ptr,smb_vwv13,3);
- SSVAL(ptr,smb_vwv14,1);
- SSVAL(ptr,smb_vwv15,1);
- SSVAL(ptr,smb_vwv16,2);
- p2 = smb_buf(ptr);
- strcpy(p2,mailslot);
- p2 = skip_string(p2,1);
-
- memcpy(p2,buf,len);
- p2 += len;
-
- dgram->datasize = PTR_DIFF(p2,ptr+4); /* +4 for tcp length. */
-
- p.ip = dest_ip;
- p.port = DGRAM_PORT;
- p.fd = ClientDGRAM;
- p.timestamp = time(NULL);
- p.packet_type = DGRAM_PACKET;
-
- DEBUG(4,("send_mailslot: Sending to mailslot %s from %s IP %s ", mailslot,
- namestr(&dgram->source_name), inet_ntoa(src_ip)));
- DEBUG(4,("to %s IP %s\n", namestr(&dgram->dest_name), inet_ntoa(dest_ip)));
-
- debug_browse_data(buf, len);
-
- if(loopback_this_packet)
- {
- struct packet_struct *lo_packet = NULL;
- DEBUG(5,("send_mailslot: sending packet to ourselves.\n"));
- if((lo_packet = copy_packet(&p)) == NULL)
- return False;
- queue_packet(lo_packet);
- return True;
- }
- else
- return(send_packet(&p));
-}
diff --git a/source/nmbd/nmbd_processlogon.c b/source/nmbd/nmbd_processlogon.c
deleted file mode 100644
index cd2fbfd0a56..00000000000
--- a/source/nmbd/nmbd_processlogon.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Revision History:
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-extern pstring myname;
-extern fstring myworkgroup;
-
-/****************************************************************************
-Process a domain logon packet
-**************************************************************************/
-
-void process_logon_packet(struct packet_struct *p,char *buf,int len,
- char *mailslot)
-{
- struct dgram_packet *dgram = &p->packet.dgram;
- pstring my_name;
- fstring reply_name;
- BOOL add_slashes = False;
- pstring outbuf;
- int code,reply_code;
- char unknown_byte = 0;
- uint16 request_count = 0;
- uint16 token = 0;
-
- uint32 ntversion;
- uint16 lmnttoken;
- uint16 lm20token;
- uint32 allowableaccount; /* Control bits, i.e. 0x80 == workstation trust a/c. */
- uint32 domainsidsize;
- uint16 requestcount;
- char *domainsid;
- char *getdc;
- char *uniuser; /* Unicode user name. */
- pstring ascuser;
- char *unicomp; /* Unicode computer name. */
- struct smb_passwd *smb_pass; /* To check if machine account exists */
-
- if (!lp_domain_logons())
- {
- DEBUG(3,("process_logon_packet: Logon packet received from IP %s and domain \
-logons are not enabled.\n", inet_ntoa(p->ip) ));
- return;
- }
-
- strcpy(my_name, myname);
- strupper(my_name);
-
- code = SVAL(buf,0);
- DEBUG(1,("process_logon_packet: Logon from %s: code = %x\n", inet_ntoa(p->ip), code));
-
- switch (code)
- {
- case 0:
- {
- char *q = buf + 2;
- char *machine = q;
- char *user = skip_string(machine,1);
-
- getdc = skip_string(user,1);
- q = skip_string(getdc,1);
- unknown_byte = CVAL(q,0);
- request_count = SVAL(q,1);
- token = SVAL(q,3);
-
- reply_code = 0x6;
- strcpy(reply_name,my_name);
- add_slashes = True;
-
- DEBUG(3,("process_logon_packet: Domain login request from %s at IP %s user=%s token=%x\n",
- machine,inet_ntoa(p->ip),user,token));
-
- q = outbuf;
- SSVAL(q, 0, 6); q += 2;
-
- strcpy(reply_name, "\\\\");
- strcat(reply_name, my_name);
- strcpy(q, reply_name); q = skip_string(q, 1); /* PDC name */
-
- SSVAL(q, 0, token); q += 2;
-
- dump_data(4, outbuf, PTR_DIFF(q, outbuf));
-
- send_mailslot(True, getdc,
- outbuf,PTR_DIFF(q,outbuf),
- dgram->dest_name.name,
- dgram->dest_name.name_type,
- dgram->source_name.name,
- dgram->source_name.name_type,
- p->ip, *iface_ip(p->ip));
- break;
- }
-
- case QUERYFORPDC:
- {
- char *q = buf + 2;
- char *machine = q;
-
- getdc = skip_string(machine,1);
- unicomp = skip_string(getdc,1);
-
- q = align2(unicomp, buf);
-
- q = skip_unicode_string(q, 1);
-
- ntversion = IVAL(q, 0); q += 4;
- lmnttoken = SVAL(q, 0); q += 2;
- lm20token = SVAL(q, 0); q += 2;
-
- /* Construct reply. */
-
- q = outbuf;
- SSVAL(q, 0, QUERYFORPDC_R); q += 2;
-
- strcpy(reply_name,my_name);
- strcpy(q, reply_name); q = skip_string(q, 1); /* PDC name */
-
- if (strcmp(mailslot, NT_LOGON_MAILSLOT)==0) {
- q = align2(q, buf);
-
- PutUniCode(q, my_name); /* PDC name */
- q = skip_unicode_string(q, 1);
- PutUniCode(q, myworkgroup); /* Domain name*/
- q = skip_unicode_string(q, 1);
-
- SIVAL(q, 0, ntversion); q += 4;
- SSVAL(q, 0, lmnttoken); q += 2;
- SSVAL(q, 0, lm20token); q += 2;
- }
-
- DEBUG(3,("process_logon_packet: GETDC request from %s at IP %s, \
-reporting %s domain %s 0x%x ntversion=%x lm_nt token=%x lm_20 token=%x\n",
- machine,inet_ntoa(p->ip), reply_name, lp_workgroup(),
- QUERYFORPDC_R, (uint32)ntversion, (uint32)lmnttoken,
- (uint32)lm20token ));
-
- dump_data(4, outbuf, PTR_DIFF(q, outbuf));
-
- send_mailslot(True, getdc,
- outbuf,PTR_DIFF(q,outbuf),
- dgram->dest_name.name,
- dgram->dest_name.name_type,
- dgram->source_name.name,
- dgram->source_name.name_type,
- p->ip, *iface_ip(p->ip));
- return;
- }
-
- case SAMLOGON:
- {
- char *q = buf + 2;
-
- requestcount = SVAL(q, 0); q += 2;
- unicomp = q;
- uniuser = skip_unicode_string(unicomp,1);
- getdc = skip_unicode_string(uniuser,1);
- q = skip_string(getdc,1);
- allowableaccount = IVAL(q, 0); q += 4;
- domainsidsize = IVAL(q, 0); q += 4;
- domainsid = q;
- q += domainsidsize + 3;
- ntversion = IVAL(q, 0); q += 4;
- lmnttoken = SVAL(q, 0); q += 2;
- lm20token = SVAL(q, 0); q += 2;
-
- DEBUG(3,("process_logon_packet: SAMLOGON sidsize %d ntv %d\n", domainsidsize, ntversion));
-
- /*
- * If MACHINE$ is in our password database then respond, else ignore.
- * Let's ignore the SID.
- */
-
- strcpy(ascuser, unistr(uniuser));
- DEBUG(3,("process_logon_packet: SAMLOGON user %s\n", ascuser));
-
- strcpy(reply_name,"\\\\"); /* Here it wants \\LOGONSERVER. */
- strcpy(reply_name+2,my_name);
-
- smb_pass = get_smbpwd_entry(ascuser, 0);
-
- if(!smb_pass)
- {
- DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, not in password file\n",
- unistr(unicomp),inet_ntoa(p->ip), ascuser));
- return;
- }
- else
- {
- DEBUG(3,("process_logon_packet: SAMLOGON request from %s(%s) for %s, returning logon svr %s domain %s code %x token=%x\n",
- unistr(unicomp),inet_ntoa(p->ip), ascuser, reply_name, myworkgroup,
- SAMLOGON_R ,lmnttoken));
- }
-
- /* Construct reply. */
-
- q = outbuf;
- SSVAL(q, 0, SAMLOGON_R); q += 2;
-
- PutUniCode(q, reply_name); q = skip_unicode_string(q, 1);
- unistrcpy(q, uniuser); q = skip_unicode_string(q, 1); /* User name (workstation trust account) */
- PutUniCode(q, lp_workgroup()); q = skip_unicode_string(q, 1); /* Domain name. */
-
- SIVAL(q, 0, ntversion); q += 4;
- SSVAL(q, 0, lmnttoken); q += 2;
- SSVAL(q, 0, lm20token); q += 2;
-
- dump_data(4, outbuf, PTR_DIFF(q, outbuf));
-
- send_mailslot(True, getdc,
- outbuf,PTR_DIFF(q,outbuf),
- dgram->dest_name.name,
- dgram->dest_name.name_type,
- dgram->source_name.name,
- dgram->source_name.name_type,
- p->ip, *iface_ip(p->ip));
- break;
- }
-
- default:
- {
- DEBUG(3,("process_logon_packet: Unknown domain request %d\n",code));
- return;
- }
- }
-}
diff --git a/source/nmbd/nmbd_responserecordsdb.c b/source/nmbd/nmbd_responserecordsdb.c
deleted file mode 100644
index bc0c0745f53..00000000000
--- a/source/nmbd/nmbd_responserecordsdb.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios library routines
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int ClientNMB;
-
-extern int DEBUGLEVEL;
-
-extern pstring scope;
-extern pstring myname;
-extern struct in_addr ipzero;
-
-int num_response_packets = 0;
-
-/***************************************************************************
- Add an expected response record into the list
- **************************************************************************/
-
-void add_response_record(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- struct response_record *rrec2;
-
- num_response_packets++; /* count of total number of packets still around */
-
- DEBUG(4,("add_response_record: adding response record id:%hu to subnet %s. num_records:%d\n",
- rrec->response_id, subrec->subnet_name, num_response_packets));
-
- if (!subrec->responselist)
- {
- subrec->responselist = rrec;
- rrec->prev = NULL;
- rrec->next = NULL;
- return;
- }
-
- for (rrec2 = subrec->responselist; rrec2->next; rrec2 = rrec2->next)
- ;
-
- rrec2->next = rrec;
- rrec->next = NULL;
- rrec->prev = rrec2;
-}
-
-/***************************************************************************
- Remove an expected response record from the list
- **************************************************************************/
-
-void remove_response_record(struct subnet_record *subrec,
- struct response_record *rrec)
-{
- if (rrec->prev)
- rrec->prev->next = rrec->next;
- if (rrec->next)
- rrec->next->prev = rrec->prev;
-
- if (subrec->responselist == rrec)
- subrec->responselist = rrec->next;
-
- if(rrec->userdata)
- {
- if(rrec->userdata->free_fn)
- (*rrec->userdata->free_fn)(rrec->userdata);
- else
- free((char *)rrec->userdata);
- }
-
- /* Ensure we can delete. */
- rrec->packet->locked = False;
- free_packet(rrec->packet);
-
- free((char *)rrec);
-
- num_response_packets--; /* count of total number of packets still around */
-}
-
-/****************************************************************************
- Create a response record for an outgoing packet.
- **************************************************************************/
-
-struct response_record *make_response_record( struct subnet_record *subrec,
- struct packet_struct *p,
- response_function resp_fn,
- timeout_response_function timeout_fn,
- success_function success_fn,
- fail_function fail_fn,
- struct userdata_struct *userdata)
-{
- struct response_record *rrec;
- struct nmb_packet *nmb = &p->packet.nmb;
-
- if (!(rrec = (struct response_record *)malloc(sizeof(*rrec))))
- {
- DEBUG(0,("make_response_queue_record: malloc fail for response_record.\n"));
- return NULL;
- }
-
- bzero((char *)rrec, sizeof(*rrec));
-
- rrec->response_id = nmb->header.name_trn_id;
-
- rrec->resp_fn = resp_fn;
- rrec->timeout_fn = timeout_fn;
- rrec->success_fn = success_fn;
- rrec->fail_fn = fail_fn;
-
- rrec->packet = p;
-
- if(userdata)
- {
- /* Intelligent userdata. */
- if(userdata->copy_fn)
- {
- if((rrec->userdata = (*userdata->copy_fn)(userdata)) == NULL)
- {
- DEBUG(0,("make_response_queue_record: copy fail for userdata.\n"));
- free(rrec);
- return NULL;
- }
- }
- else
- {
- /* Primitive userdata, do a memcpy. */
- if((rrec->userdata = (struct userdata_struct *)
- malloc(sizeof(struct userdata_struct)+userdata->userdata_len)) == NULL)
- {
- DEBUG(0,("make_response_queue_record: malloc fail for userdata.\n"));
- free(rrec);
- return NULL;
- }
- rrec->userdata->copy_fn = userdata->copy_fn;
- rrec->userdata->free_fn = userdata->free_fn;
- rrec->userdata->userdata_len = userdata->userdata_len;
- memcpy(rrec->userdata->data, userdata->data, userdata->userdata_len);
- }
- }
- else
- rrec->userdata = NULL;
-
- rrec->num_msgs = 0;
-
- if(!nmb->header.nm_flags.bcast)
- rrec->repeat_interval = 5; /* 5 seconds for unicast packets. */
- else
- rrec->repeat_interval = 1; /* XXXX should be in ms */
- rrec->repeat_count = 3; /* 3 retries */
- rrec->repeat_time = time(NULL) + rrec->repeat_interval; /* initial retry time */
-
- /* Lock the packet so we won't lose it while it's on the list. */
- p->locked = True;
-
- add_response_record(subrec, rrec);
-
- return rrec;
-}
-
-/****************************************************************************
- Find a response in a subnet's name query response list.
- **************************************************************************/
-
-static struct response_record *find_response_record_on_subnet(
- struct subnet_record *subrec, uint16 id)
-{
- struct response_record *rrec = NULL;
-
- for (rrec = subrec->responselist; rrec; rrec = rrec->next)
- {
- if (rrec->response_id == id)
- {
- DEBUG(4, ("find_response_record: found response record id = %hu on subnet %s\n",
- id, subrec->subnet_name));
- break;
- }
- }
- return rrec;
-}
-
-/****************************************************************************
- Find a response in any subnet's name query response list.
- **************************************************************************/
-
-struct response_record *find_response_record(struct subnet_record **ppsubrec,
- uint16 id)
-{
- struct response_record *rrec = NULL;
-
- for ((*ppsubrec) = FIRST_SUBNET; (*ppsubrec);
- (*ppsubrec) = NEXT_SUBNET_INCLUDING_UNICAST(*ppsubrec))
- {
- if((rrec = find_response_record_on_subnet(*ppsubrec, id)) != NULL)
- return rrec;
- }
-
- /* There should never be response records on the remote_broadcast subnet.
- Sanity check to ensure this is so. */
- if(remote_broadcast_subnet->responselist != NULL)
- {
- DEBUG(0,("find_response_record: response record found on subnet %s. This should \
-never happen !\n", remote_broadcast_subnet->subnet_name));
- }
-
- /* Now check the WINS server subnet if it exists. */
- if(wins_server_subnet != NULL)
- {
- *ppsubrec = wins_server_subnet;
- if((rrec = find_response_record_on_subnet(*ppsubrec, id))!= NULL)
- return rrec;
- }
-
- DEBUG(0,("find_response_record: repsonse packet id %hu received with no \
-matching record.\n", id));
-
- *ppsubrec = NULL;
-
- return NULL;
-}
diff --git a/source/nmbd/nmbd_sendannounce.c b/source/nmbd/nmbd_sendannounce.c
deleted file mode 100644
index aac3dad3662..00000000000
--- a/source/nmbd/nmbd_sendannounce.c
+++ /dev/null
@@ -1,583 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- SMB Version handling
- Copyright (C) John H Terpstra 1995-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-extern pstring myname;
-extern fstring myworkgroup;
-extern char **my_netbios_names;
-extern int updatecount;
-extern BOOL found_lm_clients;
-
-/****************************************************************************
- Send a browser reset packet.
-**************************************************************************/
-
-void send_browser_reset(int reset_type, char *to_name, int to_type, struct in_addr to_ip)
-{
- pstring outbuf;
- char *p;
-
- DEBUG(3,("send_browser_reset: sending reset request type %d to %s<%02x> IP %s.\n",
- reset_type, to_name, to_type, inet_ntoa(to_ip) ));
-
- bzero(outbuf,sizeof(outbuf));
- p = outbuf;
- CVAL(p,0) = ANN_ResetBrowserState;
- p++;
- CVAL(p,0) = reset_type;
- p++;
-
- send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
- myname, 0x0, to_name, to_type, to_ip, FIRST_SUBNET->myip);
-}
-
-/****************************************************************************
- Broadcast a packet to the local net requesting that all servers in this
- workgroup announce themselves to us.
- **************************************************************************/
-
-void broadcast_announce_request(struct subnet_record *subrec, struct work_record *work)
-{
- pstring outbuf;
- char *p;
-
- work->needannounce = True;
-
- DEBUG(3,("broadcast_announce_request: sending announce request for workgroup %s \
-to subnet %s\n", work->work_group, subrec->subnet_name));
-
- bzero(outbuf,sizeof(outbuf));
- p = outbuf;
- CVAL(p,0) = ANN_AnnouncementRequest;
- p++;
-
- CVAL(p,0) = work->token; /* (local) Unique workgroup token id. */
- p++;
- StrnCpy(p,myname,15);
- strupper(p);
- p = skip_string(p,1);
-
- send_mailslot(False, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
- myname, 0x0, work->work_group,0x1e, subrec->bcast_ip, subrec->myip);
-}
-
-/****************************************************************************
- Broadcast an announcement.
- **************************************************************************/
-
-static void send_announcement(struct subnet_record *subrec, int announce_type,
- char *from_name, char *to_name, int to_type, struct in_addr to_ip,
- time_t announce_interval,
- char *server_name, int server_type, char *server_comment)
-{
- pstring outbuf;
- char *p;
-
- bzero(outbuf,sizeof(outbuf));
- p = outbuf+1;
-
- CVAL(outbuf,0) = announce_type;
-
- /* Announcement parameters. */
- CVAL(p,0) = updatecount;
- SIVAL(p,1,announce_interval*1000); /* Milliseconds - despite the spec. */
-
- StrnCpy(p+5,server_name,15);
- strupper(p+5);
-
- 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. */
-
- pstrcpy(p+31,server_comment);
- p += 31;
- p = skip_string(p,1);
-
- send_mailslot(False,BROWSE_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
- from_name, 0x0, to_name, to_type, to_ip, subrec->myip);
-}
-
-/****************************************************************************
- Broadcast a LanMan announcement.
-**************************************************************************/
-
-static void send_lm_announcement(struct subnet_record *subrec, int announce_type,
- char *from_name, char *to_name, int to_type, struct in_addr to_ip,
- time_t announce_interval,
- char *server_name, int server_type, char *server_comment)
-{
- pstring outbuf;
- char *p=outbuf;
-
- bzero(outbuf,sizeof(outbuf));
-
- SSVAL(p,0,announce_type);
- SIVAL(p,2,server_type & ~SV_TYPE_LOCAL_LIST_ONLY);
- CVAL(p,6) = lp_major_announce_version(); /* Major version. */
- CVAL(p,7) = lp_minor_announce_version(); /* Minor version. */
- SSVAL(p,8,announce_interval); /* In seconds - according to spec. */
-
- p += 10;
- StrnCpy(p,server_name,15);
- strupper(p);
- p = skip_string(p,1);
- pstrcpy(p,server_comment);
- p = skip_string(p,1);
-
- send_mailslot(False,LANMAN_MAILSLOT, outbuf, PTR_DIFF(p,outbuf),
- from_name, 0x0, to_name, to_type, to_ip, subrec->myip);
-}
-
-/****************************************************************************
- We are a local master browser. Announce this to WORKGROUP<1e>.
-****************************************************************************/
-
-static void send_local_master_announcement(struct subnet_record *subrec, struct work_record *work,
- struct server_record *servrec)
-{
- /* Ensure we don't have the prohibited bit set. */
- uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
-
- DEBUG(3,("send_local_master_announcement: type %x for name %s on subnet %s for workgroup %s\n",
- type, myname, subrec->subnet_name, work->work_group));
-
- send_announcement(subrec, ANN_LocalMasterAnnouncement,
- myname, /* From nbt name. */
- work->work_group, 0x1e, /* To nbt name. */
- subrec->bcast_ip, /* To ip. */
- work->announce_interval, /* Time until next announce. */
- myname, /* Name to announce. */
- type, /* Type field. */
- servrec->serv.comment);
-}
-
-/****************************************************************************
- Announce the workgroup WORKGROUP to MSBROWSE<01>.
-****************************************************************************/
-
-static void send_workgroup_announcement(struct subnet_record *subrec, struct work_record *work)
-{
- DEBUG(3,("send_workgroup_announcement: on subnet %s for workgroup %s\n",
- subrec->subnet_name, work->work_group));
-
- send_announcement(subrec, ANN_DomainAnnouncement,
- myname, /* From nbt name. */
- MSBROWSE, 0x1, /* To nbt name. */
- subrec->bcast_ip, /* To ip. */
- work->announce_interval, /* Time until next announce. */
- work->work_group, /* Name to announce. */
- SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT, /* workgroup announce flags. */
- myname); /* From name as comment. */
-}
-
-/****************************************************************************
- Announce the given host to WORKGROUP<1d>.
-****************************************************************************/
-
-static void send_host_announcement(struct subnet_record *subrec, struct work_record *work,
- struct server_record *servrec)
-{
- /* Ensure we don't have the prohibited bits set. */
- uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
-
- DEBUG(3,("send_host_announcement: type %x for host %s on subnet %s for workgroup %s\n",
- type, servrec->serv.name, subrec->subnet_name, work->work_group));
-
- send_announcement(subrec, ANN_HostAnnouncement,
- servrec->serv.name, /* From nbt name. */
- work->work_group, 0x1d, /* To nbt name. */
- subrec->bcast_ip, /* To ip. */
- work->announce_interval, /* Time until next announce. */
- servrec->serv.name, /* Name to announce. */
- type, /* Type field. */
- servrec->serv.comment);
-}
-
-/****************************************************************************
- Announce the given LanMan host
-****************************************************************************/
-
-static void send_lm_host_announcement(struct subnet_record *subrec, struct work_record *work,
- struct server_record *servrec, int lm_interval)
-{
- /* Ensure we don't have the prohibited bits set. */
- uint32 type = servrec->serv.type & ~SV_TYPE_LOCAL_LIST_ONLY;
-
- DEBUG(3,("send_lm_host_announcement: type %x for host %s on subnet %s for workgroup %s, ttl: %d\n",
- type, servrec->serv.name, subrec->subnet_name, work->work_group, lm_interval));
-
- send_lm_announcement(subrec, ANN_HostAnnouncement,
- servrec->serv.name, /* From nbt name. */
- work->work_group, 0x00, /* To nbt name. */
- subrec->bcast_ip, /* To ip. */
- lm_interval, /* Time until next announce. */
- servrec->serv.name, /* Name to announce. */
- type, /* Type field. */
- servrec->serv.comment);
-}
-
-/****************************************************************************
- Announce a server record.
- ****************************************************************************/
-
-static void announce_server(struct subnet_record *subrec, struct work_record *work,
- struct server_record *servrec)
-{
- /* Only do domain announcements if we are a master and it's
- our primary name we're being asked to announce. */
-
- if (AM_LOCAL_MASTER_BROWSER(work) && strequal(myname,servrec->serv.name))
- {
- send_local_master_announcement(subrec, work, servrec);
- send_workgroup_announcement(subrec, work);
- }
- else
- {
- send_host_announcement(subrec, work, servrec);
- }
-}
-
-/****************************************************************************
- Go through all my registered names on all broadcast subnets and announce
- them if the timeout requires it.
- **************************************************************************/
-
-void announce_my_server_names(time_t t)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work = find_workgroup_on_subnet(subrec, myworkgroup);
-
- if(work)
- {
- struct server_record *servrec;
-
- if (work->needannounce)
- {
- /* Drop back to a max 3 minute announce. This is to prevent a
- single lost packet from breaking things for too long. */
-
- work->announce_interval = MIN(work->announce_interval,
- CHECK_TIME_MIN_HOST_ANNCE*60);
- work->lastannounce_time = t - (work->announce_interval+1);
- work->needannounce = False;
- }
-
- /* Announce every minute at first then progress to every 12 mins */
- if ((t - work->lastannounce_time) < work->announce_interval)
- continue;
-
- if (work->announce_interval < (CHECK_TIME_MAX_HOST_ANNCE * 60))
- work->announce_interval += 60;
-
- work->lastannounce_time = t;
-
- for (servrec = work->serverlist; servrec; servrec = servrec->next)
- {
- if (is_myname(servrec->serv.name))
- announce_server(subrec, work, servrec);
- }
- } /* if work */
- } /* for subrec */
-}
-
-/****************************************************************************
- Go through all my registered names on all broadcast subnets and announce
- them as a LanMan server if the timeout requires it.
-**************************************************************************/
-
-void announce_my_lm_server_names(time_t t)
-{
- struct subnet_record *subrec;
- static time_t last_lm_announce_time=0;
- int announce_interval = lp_lm_interval();
- int lm_announce = lp_lm_announce();
-
- if ((announce_interval <= 0) || (lm_announce <= 0))
- {
- /* user absolutely does not want LM announcements to be sent. */
- return;
- }
-
- if ((lm_announce >= 2) && (!found_lm_clients))
- {
- /* has been set to 2 (Auto) but no LM clients detected (yet). */
- return;
- }
-
- /* Otherwise: must have been set to 1 (Yes), or LM clients *have*
- been detected. */
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work = find_workgroup_on_subnet(subrec, myworkgroup);
-
- if(work)
- {
- struct server_record *servrec;
-
- if (last_lm_announce_time && ((t - last_lm_announce_time) < announce_interval ))
- continue;
-
- last_lm_announce_time = t;
-
- for (servrec = work->serverlist; servrec; servrec = servrec->next)
- {
- if (is_myname(servrec->serv.name))
- /* skipping equivalent of announce_server() */
- send_lm_host_announcement(subrec, work, servrec, announce_interval);
- }
- } /* if work */
- } /* for subrec */
-}
-
-/* Announce timer. Moved into global static so it can be reset
- when a machine becomes a local master browser. */
-static time_t announce_timer_last=0;
-
-/****************************************************************************
- Reset the announce_timer so that a local master browser announce will be done
- immediately.
- ****************************************************************************/
-
-void reset_announce_timer()
-{
- announce_timer_last = time(NULL) - (CHECK_TIME_MST_ANNOUNCE * 60);
-}
-
-/****************************************************************************
- Announce myself as a local master browser to a domain master browser.
- **************************************************************************/
-
-void announce_myself_to_domain_master_browser(time_t t)
-{
- struct subnet_record *subrec;
- struct work_record *work;
-
- if(!we_are_a_wins_client())
- {
- DEBUG(10,("announce_myself_to_domain_master_browser: no unicast subnet, ignoring.\n"));
- return;
- }
-
- if (!announce_timer_last)
- announce_timer_last = t;
-
- if ((t-announce_timer_last) < (CHECK_TIME_MST_ANNOUNCE * 60))
- {
- DEBUG(10,("announce_myself_to_domain_master_browser: t (%d) - last(%d) < %d\n",
- t, announce_timer_last, CHECK_TIME_MST_ANNOUNCE * 60 ));
- return;
- }
-
- announce_timer_last = t;
-
- /* Look over all our broadcast subnets to see if any of them
- has the state set as local master browser. */
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- for (work = subrec->workgrouplist; work; work = work->next)
- {
- if (AM_LOCAL_MASTER_BROWSER(work))
- {
- DEBUG(4,( "announce_myself_to_domain_master_browser: I am a local master browser for \
-workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name));
-
- /* Look in nmbd_browsersync.c for the rest of this code. */
- announce_and_sync_with_domain_master_browser(subrec, work);
- }
- }
- }
-}
-
-/****************************************************************************
-Announce all samba's server entries as 'gone'.
-This must *only* be called on shutdown.
-****************************************************************************/
-
-void announce_my_servers_removed(void)
-{
- struct subnet_record *subrec;
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_EXCLUDING_UNICAST(subrec))
- {
- struct work_record *work;
- for (work = subrec->workgrouplist; work; work = work->next)
- {
- struct server_record *servrec;
-
- work->announce_interval = 0;
- for (servrec = work->serverlist; servrec; servrec = servrec->next)
- {
- if (!is_myname(servrec->serv.name))
- continue;
- servrec->serv.type = 0;
- if(AM_LOCAL_MASTER_BROWSER(work))
- send_local_master_announcement(subrec, work, servrec);
- send_host_announcement(subrec, work, servrec);
- send_lm_host_announcement(subrec, work, servrec, 0);
- }
- }
- }
-}
-
-/****************************************************************************
- Do all the "remote" announcements. These are used to put ourselves
- on a remote browse list. They are done blind, no checking is done to
- see if there is actually a local master browser at the other end.
- **************************************************************************/
-
-void announce_remote(time_t t)
-{
- char *s,*ptr;
- static time_t last_time = 0;
- pstring s2;
- struct in_addr addr;
- char *comment;
- int stype = lp_default_server_announce();
-
- if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL)))
- return;
-
- last_time = t;
-
- s = lp_remote_announce();
- if (!*s)
- return;
-
- comment = lp_serverstring();
-
- for (ptr=s; next_token(&ptr,s2,NULL); )
- {
- /* The entries are of the form a.b.c.d/WORKGROUP with
- WORKGROUP being optional */
- char *wgroup;
- int i;
-
- wgroup = strchr(s2,'/');
- if (wgroup)
- *wgroup++ = 0;
- if (!wgroup || !*wgroup)
- wgroup = myworkgroup;
-
- addr = *interpret_addr2(s2);
-
- /* Announce all our names including aliases */
- /* Give the ip address as the address of our first
- broadcast subnet. */
-
- for(i=0; my_netbios_names[i]; i++)
- {
- char *name = my_netbios_names[i];
-
- DEBUG(5,("announce_remote: Doing remote announce for server %s to IP %s.\n",
- name, inet_ntoa(addr) ));
-
- send_announcement(FIRST_SUBNET, ANN_HostAnnouncement,
- name, /* From nbt name. */
- wgroup, 0x1e, /* To nbt name. */
- addr, /* To ip. */
- REMOTE_ANNOUNCE_INTERVAL, /* Time until next announce. */
- name, /* Name to announce. */
- stype, /* Type field. */
- comment);
- }
- }
-}
-
-/****************************************************************************
- Implement the 'remote browse sync' feature Andrew added.
- These are used to put our browse lists into remote browse lists.
- **************************************************************************/
-
-void browse_sync_remote(time_t t)
-{
- char *s,*ptr;
- static time_t last_time = 0;
- pstring s2;
- struct in_addr addr;
- struct work_record *work;
- pstring outbuf;
- char *p;
-
- if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL)))
- return;
-
- last_time = t;
-
- s = lp_remote_browse_sync();
- if (!*s)
- return;
-
- /*
- * We only do this if we are the local master browser
- * for our workgroup on the firsst subnet.
- */
-
- if((work = find_workgroup_on_subnet(FIRST_SUBNET, myworkgroup)) == NULL)
- {
- DEBUG(0,("browse_sync_remote: Cannot find workgroup %s on subnet %s\n",
- myworkgroup, FIRST_SUBNET->subnet_name ));
- return;
- }
-
- if(!AM_LOCAL_MASTER_BROWSER(work))
- {
- DEBUG(5,("browse_sync_remote: We can only do this if we are a local master browser \
-for workgroup %s on subnet %s.\n", myworkgroup, FIRST_SUBNET->subnet_name ));
- return;
- }
-
- bzero(outbuf,sizeof(outbuf));
- p = outbuf;
- CVAL(p,0) = ANN_MasterAnnouncement;
- p++;
-
- StrnCpy(p,myname,15);
- strupper(p);
- p = skip_string(p,1);
-
- for (ptr=s; next_token(&ptr,s2,NULL); )
- {
- /* The entries are of the form a.b.c.d */
- addr = *interpret_addr2(s2);
-
- DEBUG(5,("announce_remote: Doing remote browse sync announce for server %s to IP %s.\n",
- myname, inet_ntoa(addr) ));
-
- send_mailslot(True, BROWSE_MAILSLOT, outbuf,PTR_DIFF(p,outbuf),
- myname, 0x0, "*", 0x0, addr, FIRST_SUBNET->myip);
- }
-}
diff --git a/source/nmbd/nmbd_serverlistdb.c b/source/nmbd/nmbd_serverlistdb.c
deleted file mode 100644
index b3dca36c846..00000000000
--- a/source/nmbd/nmbd_serverlistdb.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-#include "smb.h"
-
-extern int ClientNMB;
-
-extern int DEBUGLEVEL;
-
-extern pstring myname;
-extern fstring myworkgroup;
-extern char **my_netbios_names;
-
-int updatecount = 0;
-
-/*******************************************************************
- Remove all the servers in a work group.
- ******************************************************************/
-
-void remove_all_servers(struct work_record *work)
-{
- struct server_record *servrec;
- struct server_record *nexts;
-
- for (servrec = work->serverlist; servrec; servrec = nexts)
- {
- DEBUG(7,("remove_all_servers: Removing server %s\n",servrec->serv.name));
- nexts = servrec->next;
-
- if (servrec->prev)
- servrec->prev->next = servrec->next;
- if (servrec->next)
- servrec->next->prev = servrec->prev;
-
- if (work->serverlist == servrec)
- work->serverlist = servrec->next;
-
- free((char *)servrec);
-
- }
-
- work->subnet->work_changed = True;
-}
-
-/***************************************************************************
- Add a server into the a workgroup serverlist.
- **************************************************************************/
-
-static void add_server_to_workgroup(struct work_record *work,
- struct server_record *servrec)
-{
- struct server_record *servrec2;
-
- if (!work->serverlist)
- {
- work->serverlist = servrec;
- servrec->prev = NULL;
- servrec->next = NULL;
- return;
- }
-
- for (servrec2 = work->serverlist; servrec2->next; servrec2 = servrec2->next)
- ;
-
- servrec2->next = servrec;
- servrec->next = NULL;
- servrec->prev = servrec2;
- work->subnet->work_changed = True;
-}
-
-/****************************************************************************
- Find a server in a server list.
- **************************************************************************/
-
-struct server_record *find_server_in_workgroup(struct work_record *work, char *name)
-{
- struct server_record *ret;
-
- for (ret = work->serverlist; ret; ret = ret->next)
- {
- if (strequal(ret->serv.name,name))
- return ret;
- }
- return NULL;
-}
-
-
-/****************************************************************************
- Remove a server entry from this workgroup.
- ****************************************************************************/
-
-static void remove_server_from_workgroup(struct work_record *work, struct server_record *servrec)
-{
- if (servrec->prev)
- servrec->prev->next = servrec->next;
- if (servrec->next)
- servrec->next->prev = servrec->prev;
-
- if (work->serverlist == servrec)
- work->serverlist = servrec->next;
-
- free((char *)servrec);
- work->subnet->work_changed = True;
-}
-
-/****************************************************************************
- Create a server entry on this workgroup.
- ****************************************************************************/
-
-struct server_record *create_server_on_workgroup(struct work_record *work,
- char *name,int servertype,
- int ttl,char *comment)
-{
- struct server_record *servrec;
-
- if (name[0] == '*')
- {
- DEBUG(7,("create_server_on_workgroup: not adding name starting with '*' (%s)\n",
- name));
- return (NULL);
- }
-
- if((servrec = find_server_in_workgroup(work, name)) != NULL)
- {
- DEBUG(0,("create_server_on_workgroup: Server %s already exists on \
-workgroup %s. This is a bug.\n", name, work->work_group));
- return NULL;
- }
-
- if((servrec = (struct server_record *)malloc(sizeof(*servrec))) == NULL)
- {
- DEBUG(0,("create_server_entry_on_workgroup: malloc fail !\n"));
- return NULL;
- }
-
- bzero((char *)servrec,sizeof(*servrec));
-
- servrec->subnet = work->subnet;
-
- StrnCpy(servrec->serv.name,name,sizeof(servrec->serv.name)-1);
- StrnCpy(servrec->serv.comment,comment,sizeof(servrec->serv.comment)-1);
- strupper(servrec->serv.name);
- servrec->serv.type = servertype;
-
- update_server_ttl(servrec, ttl);
-
- add_server_to_workgroup(work, servrec);
-
- DEBUG(3,("create_server_on_workgroup: Created server entry %s of type %x (%s) on \
-workgroup %s.\n", name,servertype,comment, work->work_group));
-
- work->subnet->work_changed = True;
-
- return(servrec);
-}
-
-/*******************************************************************
- Update the ttl field of a server record.
-*******************************************************************/
-
-void update_server_ttl(struct server_record *servrec, int ttl)
-{
- if(ttl > lp_max_ttl())
- ttl = lp_max_ttl();
-
- if(is_myname(servrec->serv.name))
- servrec->death_time = PERMANENT_TTL;
- else
- servrec->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL;
-
- servrec->subnet->work_changed = True;
-}
-
-/*******************************************************************
- Expire old servers in the serverlist. A time of -1 indicates
- everybody dies except those with a death_time of PERMANENT_TTL (which is 0).
- This should only be called from expire_workgroups_and_servers().
- ******************************************************************/
-
-void expire_servers(struct work_record *work, time_t t)
-{
- struct server_record *servrec;
- struct server_record *nexts;
-
- for (servrec = work->serverlist; servrec; servrec = nexts)
- {
- nexts = servrec->next;
-
- if ((servrec->death_time != PERMANENT_TTL) && ((t == -1) || (servrec->death_time < t)))
- {
- DEBUG(3,("expire_old_servers: Removing timed out server %s\n",servrec->serv.name));
- remove_server_from_workgroup(work, servrec);
- work->subnet->work_changed = True;
- }
- }
-}
-
-/*******************************************************************
- Decide if we should write out a server record for this server.
- We return zero if we should not. Check if we've already written
- out this server record from an earlier subnet.
-******************************************************************/
-
-static uint32 write_this_server_name( struct subnet_record *subrec,
- struct work_record *work,
- struct server_record *servrec)
-{
- struct subnet_record *ssub;
- struct work_record *iwork;
- struct server_record *sserv;
-
- /* Go through all the subnets we have already seen. */
- for (ssub = FIRST_SUBNET; ssub != subrec; ssub = NEXT_SUBNET_INCLUDING_UNICAST(ssub))
- {
- for(iwork = ssub->workgrouplist; iwork; iwork = iwork->next)
- {
- if((sserv = find_server_in_workgroup( iwork, servrec->serv.name)) != NULL)
- {
- /*
- * We have already written out this server record, don't
- * do it again. This gives precedence to servers we have seen
- * on the broadcast subnets over servers that may have been
- * added via a sync on the unicast_subet.
- *
- * The correct way to do this is to have a serverlist file
- * per subnet - this means changes to smbd as well. I may
- * add this at a later date (JRA).
- */
-
- return 0;
- }
- }
- }
-
- return servrec->serv.type;
-}
-
-/*******************************************************************
- Decide if we should write out a workgroup record for this workgroup.
- We return zero if we should not. Don't write out myworkgroup (we've
- already done it) and also don't write out a second workgroup record
- on the unicast subnet that we've already written out on one of the
- broadcast subnets.
-******************************************************************/
-
-static uint32 write_this_workgroup_name( struct subnet_record *subrec,
- struct work_record *work)
-{
- struct subnet_record *ssub;
-
- if(strequal(myworkgroup, work->work_group))
- return 0;
-
- /* This is a workgroup we have seen on a broadcast subnet. All
- these have the same type. */
-
- if(subrec != unicast_subnet)
- return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY);
-
- for(ssub = FIRST_SUBNET; ssub; ssub = NEXT_SUBNET_EXCLUDING_UNICAST(ssub))
- {
- /* This is the unicast subnet so check if we've already written out
- this subnet when we passed over the broadcast subnets. */
-
- if(find_workgroup_on_subnet( ssub, work->work_group) != NULL)
- return 0;
- }
-
- /* All workgroups on the unicast subnet (except our own, which we
- have already written out) cannot be local. */
-
- return (SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT);
-}
-
-/*******************************************************************
- Write out the browse.dat file.
- ******************************************************************/
-
-void write_browse_list(time_t t, BOOL force_write)
-{
- struct subnet_record *subrec;
- struct work_record *work;
- struct server_record *servrec;
- pstring fname,fnamenew;
- uint32 stype;
- fstring tmp;
- int i;
- FILE *fp;
- BOOL list_changed = force_write;
- static time_t lasttime = 0;
-
- if (!lasttime)
- lasttime = t;
- if (t - lasttime < 5)
- return;
-
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- if(subrec->work_changed)
- {
- list_changed = True;
- break;
- }
- }
-
- if(!list_changed)
- return;
-
- lasttime = t;
- updatecount++;
-
- dump_workgroups();
-
- pstrcpy(fname,lp_lockdir());
- trim_string(fname,NULL,"/");
- strcat(fname,"/");
- strcat(fname,SERVER_LIST);
- pstrcpy(fnamenew,fname);
- strcat(fnamenew,".");
-
- fp = fopen(fnamenew,"w");
-
- if (!fp)
- {
- DEBUG(0,("write_browse_list: Can't open file %s. Error was %s\n",
- fnamenew,strerror(errno)));
- return;
- }
-
- /*
- * Write out a record for our workgroup. Use the record from the first
- * subnet.
- */
-
- if((work = find_workgroup_on_subnet(FIRST_SUBNET, myworkgroup)) == NULL)
- {
- DEBUG(0,("write_browse_list: Fatal error - cannot find my workgroup %s\n",
- myworkgroup));
- fclose(fp);
- return;
- }
-
- sprintf(tmp, "\"%s\"", work->work_group);
- fprintf(fp, "%-25s ", tmp);
- fprintf(fp, "%08x ", SV_TYPE_DOMAIN_ENUM|SV_TYPE_NT|SV_TYPE_LOCAL_LIST_ONLY);
- sprintf(tmp, "\"%s\" ", work->local_master_browser_name);
- fprintf(fp, "%-30s", tmp);
- fprintf(fp, "\"%s\"\n", work->work_group);
-
- /*
- * We need to do something special for our own names.
- * This is due to the fact that we may be a local master browser on
- * one of our broadcast subnets, and a domain master on the unicast
- * subnet. We iterate over the subnets and only write out the name
- * once.
- */
-
- for (i=0; my_netbios_names[i]; i++)
- {
- stype = 0;
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- if((work = find_workgroup_on_subnet( subrec, myworkgroup )) == NULL)
- continue;
- if((servrec = find_server_in_workgroup( work, my_netbios_names[i])) == NULL)
- continue;
-
- stype |= servrec->serv.type;
- }
-
- /* Output server details, plus what workgroup they're in. */
- sprintf(tmp, "\"%s\"", my_netbios_names[i]);
- fprintf(fp, "%-25s ", tmp);
- fprintf(fp, "%08x ", stype);
- sprintf(tmp, "\"%s\" ", lp_serverstring());
- fprintf(fp, "%-30s", tmp);
- fprintf(fp, "\"%s\"\n", myworkgroup);
- }
-
- for (subrec = FIRST_SUBNET; subrec ; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- subrec->work_changed = False;
-
- for (work = subrec->workgrouplist; work ; work = work->next)
- {
- /* Write out a workgroup record for a workgroup. */
- uint32 wg_type = write_this_workgroup_name( subrec, work);
-
- if(wg_type)
- {
- sprintf(tmp, "\"%s\"", work->work_group);
- fprintf(fp, "%-25s ", tmp);
-
- fprintf(fp, "%08x ", wg_type);
- sprintf(tmp, "\"%s\" ", work->local_master_browser_name);
- fprintf(fp, "%-30s", tmp);
- fprintf(fp, "\"%s\"\n", work->work_group);
- }
-
- /* Now write out any server records a workgroup may have. */
-
- for (servrec = work->serverlist; servrec ; servrec = servrec->next)
- {
- uint32 serv_type;
-
- /* We have already written our names here. */
- if(is_myname(servrec->serv.name))
- continue;
-
- serv_type = write_this_server_name(subrec, work, servrec);
-
- if(serv_type)
- {
- /* Output server details, plus what workgroup they're in. */
- sprintf(tmp, "\"%s\"", servrec->serv.name);
- fprintf(fp, "%-25s ", tmp);
- fprintf(fp, "%08x ", serv_type);
- sprintf(tmp, "\"%s\" ", servrec->serv.comment);
- fprintf(fp, "%-30s", tmp);
- fprintf(fp, "\"%s\"\n", work->work_group);
- }
- }
- }
- }
-
- fclose(fp);
- unlink(fname);
- chmod(fnamenew,0644);
- rename(fnamenew,fname);
- DEBUG(3,("write_browse_list: Wrote browse list into file %s\n",fname));
-}
diff --git a/source/nmbd/nmbd_subnetdb.c b/source/nmbd/nmbd_subnetdb.c
deleted file mode 100644
index 93aecc21f29..00000000000
--- a/source/nmbd/nmbd_subnetdb.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- Revision History:
-
-*/
-
-#include "includes.h"
-#include "smb.h"
-
-extern int ClientNMB;
-extern int ClientDGRAM;
-extern int global_nmb_port;
-
-extern int DEBUGLEVEL;
-
-extern pstring myname;
-extern fstring myworkgroup;
-extern char **my_netbios_names;
-extern struct in_addr ipzero;
-
-/* This is the broadcast subnets database. */
-struct subnet_record *subnetlist = NULL;
-
-/* Extra subnets - keep these separate so enumeration code doesn't
- run onto it by mistake. */
-
-struct subnet_record *unicast_subnet = NULL;
-struct subnet_record *remote_broadcast_subnet = NULL;
-struct subnet_record *wins_server_subnet = NULL;
-
-extern uint16 samba_nb_type; /* Samba's NetBIOS name type. */
-
-/****************************************************************************
- Add a subnet into the list.
- **************************************************************************/
-
-static void add_subnet(struct subnet_record *subrec)
-{
- struct subnet_record *subrec2;
-
- if (!subnetlist)
- {
- subnetlist = subrec;
- subrec->prev = NULL;
- subrec->next = NULL;
- return;
- }
-
- for (subrec2 = subnetlist; subrec2->next; subrec2 = subrec2->next)
- ;
-
- subrec2->next = subrec;
- subrec->next = NULL;
- subrec->prev = subrec2;
-}
-
-/****************************************************************************
- Create a subnet entry.
- ****************************************************************************/
-
-static struct subnet_record *make_subnet(char *name, enum subnet_type type,
- struct in_addr myip, struct in_addr bcast_ip,
- struct in_addr mask_ip)
-{
- struct subnet_record *subrec = NULL;
- int nmb_sock, dgram_sock;
-
- /* Check if we are creating a non broadcast subnet - if so don't create
- sockets.
- */
-
- if(type != NORMAL_SUBNET)
- {
- nmb_sock = -1;
- dgram_sock = -1;
- }
- else
- {
- /*
- * Attempt to open the sockets on port 137/138 for this interface
- * and bind them.
- * Fail the subnet creation if this fails.
- */
-
- if((nmb_sock = open_socket_in(SOCK_DGRAM, global_nmb_port,0, myip.s_addr)) == -1)
- {
- DEBUG(0,("make_subnet: Failed to open nmb socket on interface %s \
-for port %d. Error was %s\n", inet_ntoa(myip), global_nmb_port, strerror(errno)));
- return NULL;
- }
-
- if((dgram_sock = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3, myip.s_addr)) == -1)
- {
- DEBUG(0,("make_subnet: Failed to open dgram socket on interface %s \
-for port %d. Error was %s\n", inet_ntoa(myip), DGRAM_PORT, strerror(errno)));
- return NULL;
- }
-
- /* Make sure we can broadcast from these sockets. */
- set_socket_options(nmb_sock,"SO_BROADCAST");
- set_socket_options(dgram_sock,"SO_BROADCAST");
-
- }
-
- subrec = (struct subnet_record *)malloc(sizeof(*subrec));
-
- if (!subrec)
- {
- DEBUG(0,("make_subnet: malloc fail !\n"));
- close(nmb_sock);
- close(dgram_sock);
- return(NULL);
- }
-
- bzero((char *)subrec,sizeof(*subrec));
-
- if((subrec->subnet_name = strdup(name)) == NULL)
- {
- DEBUG(0,("make_subnet: malloc fail for subnet name !\n"));
- close(nmb_sock);
- close(dgram_sock);
- free((char *)subrec);
- return(NULL);
- }
-
- DEBUG(2, ("making subnet name:%s ", name ));
- DEBUG(2, ("Broadcast address:%s ", inet_ntoa(bcast_ip)));
- DEBUG(2, ("Subnet mask:%s\n", inet_ntoa(mask_ip)));
-
- subrec->namelist_changed = False;
- subrec->work_changed = False;
-
- subrec->bcast_ip = bcast_ip;
- subrec->mask_ip = mask_ip;
- subrec->myip = myip;
- subrec->type = type;
- subrec->nmb_sock = nmb_sock;
- subrec->dgram_sock = dgram_sock;
-
- return subrec;
-}
-
-/****************************************************************************
- Create subnet entries.
-**************************************************************************/
-
-BOOL create_subnets()
-{
- int num_interfaces = iface_count();
- int i;
- struct in_addr unicast_ip;
-
- if(num_interfaces == 0)
- {
- DEBUG(0,("create_subnets: No local interfaces !\n"));
- return False;
- }
-
- /*
- * Create subnets from all the local interfaces and thread them onto
- * the linked list.
- */
-
- for (i = 0 ; i < num_interfaces; i++)
- {
- struct subnet_record *subrec;
- struct interface *iface = get_interface(i);
-
- if((subrec = make_subnet(inet_ntoa(iface->ip), NORMAL_SUBNET,
- iface->ip, iface->bcast,iface->nmask)) == NULL)
- return False;
- add_subnet(subrec);
- }
-
- /*
- * If we have been configured to use a WINS server, then try and
- * get the ip address of it here. If we are the WINS server then
- * set the unicast subnet address to be the first of our own real
- * addresses.
- */
-
- if(*lp_wins_server())
- {
- struct in_addr real_wins_ip;
- real_wins_ip = *interpret_addr2(lp_wins_server());
-
- if (!zero_ip(real_wins_ip))
- {
- unicast_ip = real_wins_ip;
- }
- else
- {
- /* The smb.conf's wins server parameter MUST be a host_name
- or an ip_address. */
- DEBUG(0,("invalid smb.conf parameter 'wins server'\n"));
- return False;
- }
- }
- else if(lp_we_are_a_wins_server())
- {
- /* Pick the first interface ip address as the WINS server ip. */
- unicast_ip = *iface_n_ip(0);
- }
- else
- {
- /* We should not be using a WINS server at all. Set the
- ip address of the subnet to be zero. */
- unicast_ip = ipzero;
- }
-
- /*
- * Create the unicast and remote broadcast subnets.
- * Don't put these onto the linked list.
- * The ip address of the unicast subnet is set to be
- * the WINS server address, if it exists, or ipzero if not.
- */
-
- unicast_subnet = make_subnet( "UNICAST_SUBNET", UNICAST_SUBNET,
- unicast_ip, unicast_ip, unicast_ip);
-
- remote_broadcast_subnet = make_subnet( "REMOTE_BROADCAST_SUBNET",
- REMOTE_BROADCAST_SUBNET,
- ipzero, ipzero, ipzero);
-
- if((unicast_subnet == NULL) || (remote_broadcast_subnet == NULL))
- return False;
-
- /*
- * If we are WINS server, create the WINS_SERVER_SUBNET - don't put on
- * the linked list.
- */
-
- if (lp_we_are_a_wins_server())
- {
- if((wins_server_subnet = make_subnet("WINS_SERVER_SUBNET",
- WINS_SERVER_SUBNET,
- ipzero, ipzero, ipzero)) == NULL)
- return False;
- }
-
- return True;
-}
-
-/*******************************************************************
-Function to tell us if we can use the unicast subnet.
-******************************************************************/
-
-BOOL we_are_a_wins_client()
-{
- static int cache_we_are_a_wins_client = -1;
-
- if(cache_we_are_a_wins_client == -1)
- cache_we_are_a_wins_client = (ip_equal(ipzero, unicast_subnet->myip) ?
- False : True);
-
- return cache_we_are_a_wins_client;
-}
-
-/*******************************************************************
-Access function used by NEXT_SUBNET_INCLUDING_UNICAST
-******************************************************************/
-
-struct subnet_record *get_next_subnet_maybe_unicast(struct subnet_record *subrec)
-{
- if(subrec == unicast_subnet)
- return NULL;
- else if((subrec->next == NULL) && we_are_a_wins_client())
- return unicast_subnet;
- else
- return subrec->next;
-}
diff --git a/source/nmbd/nmbd_winsproxy.c b/source/nmbd/nmbd_winsproxy.c
deleted file mode 100644
index 4f2326795d5..00000000000
--- a/source/nmbd/nmbd_winsproxy.c
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
-
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-extern int DEBUGLEVEL;
-
-/****************************************************************************
-Function called when the name lookup succeeded.
-****************************************************************************/
-
-static void wins_proxy_name_query_request_success( struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *nmbname, struct in_addr ip, struct res_rec *rrec)
-{
- struct packet_struct *original_packet;
- struct subnet_record *orig_broadcast_subnet;
- struct name_record *namerec;
- uint16 nb_flags;
- int num_ips;
- int i;
- int ttl;
- struct in_addr *iplist;
-
- /* Extract the original packet and the original broadcast subnet from
- the userdata. */
-
- memcpy( (char *)&orig_broadcast_subnet, userdata->data, sizeof(struct subnet_record *) );
- memcpy( (char *)&original_packet, &userdata->data[sizeof(struct subnet_record *)],
- sizeof(struct packet_struct *) );
-
- nb_flags = get_nb_flags( rrec->rdata );
-
- num_ips = rrec->rdlength / 6;
- if(num_ips == 0)
- {
- DEBUG(0,("wins_proxy_name_query_request_success: Invalid number of IP records (0) \
-returned for name %s.\n", namestr(nmbname) ));
- return;
- }
-
- if(num_ips == 1)
- iplist = &ip;
- else
- {
- if((iplist = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr) )) == NULL)
- {
- DEBUG(0,("wins_proxy_name_query_request_success: malloc fail !\n"));
- return;
- }
-
- for(i = 0; i < num_ips; i++)
- putip( (char *)&iplist[i], (char *)&rrec->rdata[ (i*6) + 2]);
- }
-
- /* Add the queried name to the original subnet as a WINS_PROXY_NAME. */
-
- if(rrec == PERMANENT_TTL)
- ttl = lp_max_ttl();
-
- namerec = add_name_to_subnet( orig_broadcast_subnet, nmbname->name, nmbname->name_type,
- nb_flags, ttl, WINS_PROXY_NAME, num_ips, iplist);
-
- if(iplist != &ip)
- free((char *)iplist);
-
- /*
- * Check that none of the IP addresses we are returning is on the
- * same broadcast subnet as the original requesting packet. If it
- * is then don't reply (although we still need to add the name
- * to the cache) as the actual machine will be replying also
- * and we don't want two replies to a broadcast query.
- */
-
- if(namerec && original_packet->packet.nmb.header.nm_flags.bcast)
- {
- for( i = 0; i < namerec->num_ips; i++)
- {
- if(same_net( namerec->ip[i], orig_broadcast_subnet->myip, orig_broadcast_subnet->mask_ip ))
- {
- DEBUG(5,("wins_proxy_name_query_request_success: name %s is a WINS proxy name and is also \
-on the same subnet (%s) as the requestor. Not replying.\n",
- namestr(&namerec->name), orig_broadcast_subnet->subnet_name ));
- return;
- }
- }
- }
-
- /* Finally reply to the original name query. */
- reply_netbios_packet(original_packet, /* Packet to reply to. */
- 0, /* Result code. */
- NMB_QUERY, /* nmbd type code. */
- NMB_NAME_QUERY_OPCODE, /* opcode. */
- ttl, /* ttl. */
- rrec->rdata, /* data to send. */
- rrec->rdlength); /* data length. */
-}
-
-/****************************************************************************
-Function called when the name lookup failed.
-****************************************************************************/
-
-static void wins_proxy_name_query_request_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *question_name, int fail_code)
-{
- DEBUG(4,("wins_proxy_name_query_request_fail: WINS server returned error code %d for lookup \
-of name %s.\n", fail_code, namestr(question_name) ));
-}
-
-/****************************************************************************
-Function to make a deep copy of the userdata we will need when the WINS
-proxy query returns.
-****************************************************************************/
-
-static struct userdata_struct *wins_proxy_userdata_copy_fn(struct userdata_struct *userdata)
-{
- struct packet_struct *p, *copy_of_p;
- struct userdata_struct *new_userdata =
- (struct userdata_struct *)malloc( userdata->userdata_len );
-
- if(new_userdata == NULL)
- return NULL;
-
- new_userdata->copy_fn = userdata->copy_fn;
- new_userdata->free_fn = userdata->free_fn;
- new_userdata->userdata_len = userdata->userdata_len;
-
- /* Copy the subnet_record pointer. */
- memcpy( new_userdata->data, userdata->data, sizeof(struct subnet_record *) );
-
- /* Extract the pointer to the packet struct */
- memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)],
- sizeof(struct packet_struct *) );
-
- /* Do a deep copy of the packet. */
- if((copy_of_p = copy_packet(p)) == NULL)
- {
- free((char *)new_userdata);
- return NULL;
- }
-
- /* Lock the copy. */
- copy_of_p->locked = True;
-
- memcpy( &new_userdata->data[sizeof(struct subnet_record *)], (char *)&copy_of_p,
- sizeof(struct packet_struct *) );
-
- return new_userdata;
-}
-
-/****************************************************************************
-Function to free the deep copy of the userdata we used when the WINS
-proxy query returned.
-****************************************************************************/
-
-static void wins_proxy_userdata_free_fn(struct userdata_struct *userdata)
-{
- struct packet_struct *p;
-
- /* Extract the pointer to the packet struct */
- memcpy((char *)&p, &userdata->data[sizeof(struct subnet_record *)],
- sizeof(struct packet_struct *));
-
- /* Unlock the packet. */
- p->locked = False;
-
- free_packet(p);
- free((char *)userdata);
-}
-
-/****************************************************************************
- Make a WINS query on behalf of a broadcast client name query request.
-****************************************************************************/
-
-void make_wins_proxy_name_query_request( struct subnet_record *subrec,
- struct packet_struct *incoming_packet,
- struct nmb_name *question_name)
-{
- char ud[sizeof(struct userdata_struct) + sizeof(struct subrec *) +
- sizeof(struct packet_struct *)];
- struct userdata_struct *userdata = (struct userdata_struct *)ud;
-
- bzero(ud, sizeof(ud));
-
- userdata->copy_fn = wins_proxy_userdata_copy_fn;
- userdata->free_fn = wins_proxy_userdata_free_fn;
- userdata->userdata_len = sizeof(ud);
- memcpy( userdata->data, (char *)&subrec, sizeof(struct subnet_record *));
- memcpy( &userdata->data[sizeof(struct subnet_record *)], (char *)&incoming_packet,
- sizeof(struct packet_struct *));
-
- /* Now use the unicast subnet to query the name with the WINS server. */
- query_name( unicast_subnet, question_name->name, question_name->name_type,
- wins_proxy_name_query_request_success,
- wins_proxy_name_query_request_fail,
- userdata);
-}
diff --git a/source/nmbd/nmbd_winsserver.c b/source/nmbd/nmbd_winsserver.c
deleted file mode 100644
index bd8febd65d4..00000000000
--- a/source/nmbd/nmbd_winsserver.c
+++ /dev/null
@@ -1,1566 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
-
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-
-#define WINS_LIST "wins.dat"
-
-extern int DEBUGLEVEL;
-extern struct in_addr ipzero;
-
-/****************************************************************************
-Determine if this packet should be allocated to the WINS server.
-*****************************************************************************/
-
-BOOL packet_is_for_wins_server(struct packet_struct *packet)
-{
- struct nmb_packet *nmb = &packet->packet.nmb;
-
- /* Only unicast packets go to a WINS server. */
- if((wins_server_subnet == NULL) || (nmb->header.nm_flags.bcast == True))
- {
- DEBUG(10, ("packet_is_for_wins_server: failing WINS test #1.\n"));
- return False;
- }
-
- /* Check for node status requests. */
- if (nmb->question.question_type != QUESTION_TYPE_NB_QUERY)
- return False;
-
- switch(nmb->header.opcode)
- {
- /*
- * A WINS server issues WACKS, not receives them.
- */
- case NMB_WACK_OPCODE:
- DEBUG(10, ("packet_is_for_wins_server: failing WINS test #2 (WACK).\n"));
- return False;
- /*
- * A WINS server only processes registration and
- * release requests, not responses.
- */
- case NMB_NAME_REG_OPCODE:
- case NMB_NAME_MULTIHOMED_REG_OPCODE:
- case NMB_NAME_REFRESH_OPCODE_8: /* ambiguity in rfc1002 about which is correct. */
- case NMB_NAME_REFRESH_OPCODE_9: /* WinNT uses 8 by default. */
- if(nmb->header.response)
- {
- DEBUG(10, ("packet_is_for_wins_server: failing WINS test #3 (response = 1).\n"));
- return False;
- }
- break;
-
- case NMB_NAME_RELEASE_OPCODE:
- if(nmb->header.response)
- {
- DEBUG(10, ("packet_is_for_wins_server: failing WINS test #4 (response = 1).\n"));
- return False;
- }
- break;
-
- /*
- * Only process unicast name queries with rd = 1.
- */
- case NMB_NAME_QUERY_OPCODE:
- if(!nmb->header.response && !nmb->header.nm_flags.recursion_desired)
- {
- DEBUG(10, ("packet_is_for_wins_server: failing WINS test #5 (response = 1).\n"));
- return False;
- }
- break;
- }
-
- return True;
-}
-
-/****************************************************************************
-Utility function to decide what ttl to give a register/refresh request.
-*****************************************************************************/
-
-static int get_ttl_from_packet(struct nmb_packet *nmb)
-{
- int ttl = nmb->additional->ttl;
-
- if(ttl < lp_min_wins_ttl() )
- ttl = lp_min_wins_ttl();
-
- if(ttl > lp_max_wins_ttl() )
- ttl = lp_max_wins_ttl();
-
- return ttl;
-}
-
-/****************************************************************************
-Load or create the WINS database.
-*****************************************************************************/
-
-BOOL initialise_wins(void)
-{
- fstring fname;
- time_t time_now = time(NULL);
- FILE *fp;
- pstring line;
-
- if(!lp_we_are_a_wins_server())
- return True;
-
- add_samba_names_to_subnet(wins_server_subnet);
-
-#ifndef SYNC_DNS
- /* Setup the async dns. */
- start_async_dns();
-#endif
-
- fstrcpy(fname,lp_lockdir());
- trim_string(fname,NULL,"/");
- strcat(fname,"/");
- strcat(fname,WINS_LIST);
-
- if((fp = fopen(fname,"r")) == NULL)
- {
- DEBUG(2,("initialise_wins: Can't open wins database file %s. Error was %s\n",
- fname, strerror(errno) ));
- return True;
- }
-
- while (!feof(fp))
- {
- pstring name_str, ip_str, ttl_str, nb_flags_str;
- unsigned int num_ips;
- pstring name;
- struct in_addr *ip_list;
- int type = 0;
- uint16 nb_flags;
- time_t ttl;
- enum name_source source;
- char *ptr;
- char *p;
- BOOL got_token;
- BOOL was_ip;
- int i;
-
- /* Read a line from the wins.dat file. Strips whitespace
- from the beginning and end of the line.
- */
- if (!fgets_slash(line,sizeof(pstring),fp))
- continue;
-
- if (*line == '#')
- continue;
-
- ptr = line;
-
- /*
- * Now we handle multiple IP addresses per name we need
- * to iterate over the line twice. The first time to
- * determine how many IP addresses there are, the second
- * time to actually parse them into the ip_list array.
- */
-
- if (!next_token(&ptr,name_str,NULL))
- {
- DEBUG(0,("initialise_wins: Failed to parse name when parsing line %s\n", line ));
- continue;
- }
-
- if (!next_token(&ptr,ttl_str,NULL))
- {
- DEBUG(0,("initialise_wins: Failed to parse time to live when parsing line %s\n", line ));
- continue;
- }
-
- /*
- * Determine the number of IP addresses per line.
- */
- num_ips = 0;
- do
- {
- got_token = next_token(&ptr,ip_str,NULL);
- was_ip = False;
-
- if(got_token && strchr(ip_str, '.'))
- {
- num_ips++;
- was_ip = True;
- }
- } while( got_token && was_ip);
-
- if(num_ips == 0)
- {
- DEBUG(0,("initialise_wins: Missing IP address when parsing line %s\n", line ));
- continue;
- }
-
- if(!got_token)
- {
- DEBUG(0,("initialise_wins: Missing nb_flags when parsing line %s\n", line ));
- continue;
- }
-
- /* Allocate the space for the ip_list. */
- if((ip_list = (struct in_addr *)malloc( num_ips * sizeof(struct in_addr))) == NULL)
- {
- DEBUG(0,("initialise_wins: Malloc fail !\n"));
- return False;
- }
-
- /* Reset and re-parse the line. */
- ptr = line;
- next_token(&ptr,name_str,NULL);
- next_token(&ptr,ttl_str,NULL);
- for(i = 0; i < num_ips; i++)
- {
- next_token(&ptr, ip_str, NULL);
- ip_list[i] = *interpret_addr2(ip_str);
- if (ip_equal(ip_list[i], ipzero))
- source = SELF_NAME;
- }
- next_token(&ptr,nb_flags_str,NULL);
-
- /*
- * Deal with SELF or REGISTER name encoding. Default is REGISTER
- * for compatibility with old nmbds.
- */
-
- if(nb_flags_str[strlen(nb_flags_str)-1] == 'S')
- {
- DEBUG(5,("initialise_wins: Ignoring SELF name %s\n", line));
- free((char *)ip_list);
- continue;
- }
-
- if(nb_flags_str[strlen(nb_flags_str)-1] == 'R')
- nb_flags_str[strlen(nb_flags_str)-1] = '\0';
-
- /* Netbios name. # divides the name from the type (hex): netbios#xx */
- pstrcpy(name,name_str);
-
- if((p = strchr(name,'#')) != NULL)
- {
- *p = 0;
- sscanf(p+1,"%x",&type);
- }
-
- /* Decode the netbios flags (hex) and the time-to-live (in seconds). */
- sscanf(nb_flags_str,"%hx",&nb_flags);
- sscanf(ttl_str,"%ld",&ttl);
-
- /* add all entries that have 60 seconds or more to live */
- if ((ttl - 60) > time_now || ttl == PERMANENT_TTL)
- {
- struct name_record *namerec;
-
- if(ttl != PERMANENT_TTL)
- ttl -= time_now;
-
- DEBUG(4, ("initialise_wins: add name: %s#%02x ttl = %ld first IP %s flags = %2hx\n",
- name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
-
- namerec = add_name_to_subnet(wins_server_subnet, name, type, nb_flags,
- ttl, REGISTER_NAME, num_ips, ip_list);
-
- }
- else
- {
- DEBUG(4, ("initialise_wins: not adding name (ttl problem) %s#%02x ttl = %ld first IP %s flags = %2hx\n",
- name, type, ttl, inet_ntoa(ip_list[0]), nb_flags));
- }
-
- free((char *)ip_list);
- }
-
- fclose(fp);
- return True;
-}
-
-/****************************************************************************
-Send a WINS WACK (Wait ACKnowledgement) response.
-**************************************************************************/
-
-static void send_wins_wack_response(int ttl, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- unsigned char rdata[2];
-
- rdata[0] = rdata[1] = 0;
-
- /* Taken from nmblib.c - we need to send back almost
- identical bytes from the requesting packet header. */
-
- rdata[0] = (nmb->header.opcode & 0xF) << 3;
- if (nmb->header.nm_flags.authoritative &&
- nmb->header.response) rdata[0] |= 0x4;
- if (nmb->header.nm_flags.trunc) rdata[0] |= 0x2;
- if (nmb->header.nm_flags.recursion_desired) rdata[0] |= 0x1;
- if (nmb->header.nm_flags.recursion_available &&
- nmb->header.response) rdata[1] |= 0x80;
- if (nmb->header.nm_flags.bcast) rdata[1] |= 0x10;
-
- reply_netbios_packet(p, /* Packet to reply to. */
- 0, /* Result code. */
- NMB_WAIT_ACK, /* nmbd type code. */
- NMB_WACK_OPCODE, /* opcode. */
- ttl, /* ttl. */
- (char *)rdata, /* data to send. */
- 2); /* data length. */
-}
-
-/****************************************************************************
-Send a WINS name registration response.
-**************************************************************************/
-
-static void send_wins_name_registration_response(int rcode, int ttl, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- char rdata[6];
-
- memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- WINS_REG, /* nmbd type code. */
- NMB_NAME_REG_OPCODE, /* opcode. */
- ttl, /* ttl. */
- rdata, /* data to send. */
- 6); /* data length. */
-}
-
-/***********************************************************************
- Deal with a name refresh request to a WINS server.
-************************************************************************/
-
-void wins_process_name_refresh_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- BOOL group = (nb_flags & NB_GROUP) ? True : False;
- struct name_record *namerec = NULL;
- int ttl = get_ttl_from_packet(nmb);
- struct in_addr from_ip;
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
-
- if(bcast)
- {
- /*
- * We should only get unicast name refresh packets here.
- * Anyone trying to refresh broadcast should not be going to a WINS
- * server. Log an error here.
- */
-
- DEBUG(0,("wins_process_name_refresh_request: broadcast name refresh request \
-received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
- namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
- return;
- }
-
- DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s \
-IP %s\n", namestr(question), inet_ntoa(from_ip) ));
-
- /*
- * See if the name already exists.
- */
-
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- /*
- * If this is a refresh request and the name doesn't exist then
- * fail it.
- */
-
- if(namerec == NULL)
- {
- DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s and \
-the name does not exist.\n", namestr(question) ));
- send_wins_name_registration_response(NAM_ERR, 0, p);
- return;
- }
-
- /*
- * Check that the group bits for the refreshing name and the
- * name in our database match.
- */
-
- if((namerec != NULL) && ((group && !NAME_GROUP(namerec)) || (!group && NAME_GROUP(namerec))) )
- {
- DEBUG(3,("wins_process_name_refresh_request: Name %s group bit = %s \
-does not match group bit in WINS for this name.\n", namestr(question), group ? "True" : "False" ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
-
- /*
- * For a unique name check that the person refreshing the name is one of the registered IP
- * addresses. If not - fail the refresh. Do the same for group names with a type of 0x1c.
- * Just return success for unique 0x1d refreshes. For normal group names update the ttl
- * and return success.
- */
-
- if((!group || (group && (question->name_type == 0x1c))) && find_ip_in_name_record(namerec, from_ip ))
- {
- /*
- * Update the ttl.
- */
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
- else if(group)
- {
- /*
- * Normal groups are all registered with an IP address of 255.255.255.255
- * so we can't search for the IP address.
- */
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
- else if(!group && (question->name_type == 0x1d))
- {
- /*
- * Special name type - just pretend the refresh succeeded.
- */
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
- else
- {
- /*
- * Fail the refresh.
- */
-
- DEBUG(3,("wins_process_name_refresh_request: Name refresh for name %s with IP %s and \
-is IP is not known to the name.\n", namestr(question), inet_ntoa(from_ip) ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
-}
-
-/***********************************************************************
- Deal with a name registration request query success to a client that
- owned the name.
-
- We have a locked pointer to the original packet stashed away in the
- userdata pointer. The success here is actually a failure as it means
- the client we queried wants to keep the name, so we must return
- a registration failure to the original requestor.
-************************************************************************/
-
-static void wins_register_query_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *question_name,
- struct in_addr ip,
- struct res_rec *answers)
-{
- struct packet_struct *orig_reg_packet;
-
- memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
-
- DEBUG(3,("wins_register_query_success: Original client at IP %s still wants the \
-name %s. Rejecting registration request.\n", inet_ntoa(ip), namestr(question_name) ));
-
- send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
-
- orig_reg_packet->locked = False;
- free_packet(orig_reg_packet);
-}
-
-/***********************************************************************
- Deal with a name registration request query failure to a client that
- owned the name.
-
- We have a locked pointer to the original packet stashed away in the
- userdata pointer. The failure here is actually a success as it means
- the client we queried didn't want to keep the name, so we can remove
- the old name record and then successfully add the new name.
-************************************************************************/
-
-static void wins_register_query_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *question_name,
- int rcode)
-{
- struct userdata_struct *userdata = rrec->userdata;
- struct packet_struct *orig_reg_packet;
- struct nmb_packet *nmb;
- struct name_record *namerec = NULL;
- uint16 nb_flags;
- BOOL group;
-
- memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
-
- nmb = &orig_reg_packet->packet.nmb;
-
- nb_flags = get_nb_flags(nmb->additional->rdata);
- group = (nb_flags & NB_GROUP) ? True : False;
-
- /*
- * We want to just add the name, as we now know the original owner
- * didn't want it. But we can't just do that as an arbitary
- * amount of time may have taken place between the name query
- * request and this timeout/error response. So we check that
- * the name still exists and is in the same state - if so
- * we remove it and call wins_process_name_registration_request()
- * as we know it will do the right thing now.
- */
-
- namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
-
- if((namerec != NULL) && (namerec->source == REGISTER_NAME) &&
- ip_equal(rrec->packet->ip, *namerec->ip) )
- {
- remove_name_from_namelist( subrec, namerec);
- namerec = NULL;
- }
-
- if(namerec == NULL)
- wins_process_name_registration_request(subrec, orig_reg_packet);
- else
- DEBUG(2,("wins_register_query_fail: The state of the WINS database changed between \
-querying for name %s in order to replace it and this reply.\n", namestr(question_name) ));
-
- orig_reg_packet->locked = False;
- free_packet(orig_reg_packet);
-}
-
-/***********************************************************************
- Deal with a name registration request to a WINS server.
-
- Use the following pseudocode :
-
- registering_group
- |
- |
- +--------name exists
- | |
- | |
- | +--- existing name is group
- | | |
- | | |
- | | +--- add name (return).
- | |
- | |
- | +--- exiting name is unique
- | |
- | |
- | +--- query existing owner (return).
- |
- |
- +--------name doesn't exist
- |
- |
- +--- add name (return).
-
- registering_unique
- |
- |
- +--------name exists
- | |
- | |
- | +--- existing name is group
- | | |
- | | |
- | | +--- fail add (return).
- | |
- | |
- | +--- exiting name is unique
- | |
- | |
- | +--- query existing owner (return).
- |
- |
- +--------name doesn't exist
- |
- |
- +--- add name (return).
-
- As can be seen from the above, the two cases may be collapsed onto each
- other with the exception of the case where the name already exists and
- is a group name. This case we handle with an if statement.
-
-************************************************************************/
-
-void wins_process_name_registration_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- int ttl = get_ttl_from_packet(nmb);
- struct name_record *namerec = NULL;
- struct in_addr from_ip;
- BOOL registering_group_name = (nb_flags & NB_GROUP) ? True : False;;
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
-
- if(bcast)
- {
- /*
- * We should only get unicast name registration packets here.
- * Anyone trying to register broadcast should not be going to a WINS
- * server. Log an error here.
- */
-
- DEBUG(0,("wins_process_name_registration_request: broadcast name registration request \
-received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
- namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
- return;
- }
-
- DEBUG(3,("wins_process_name_registration_request: %s name registration for name %s \
-IP %s\n", registering_group_name ? "Group" : "Unique", namestr(question), inet_ntoa(from_ip) ));
-
- /*
- * See if the name already exists.
- */
-
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- /*
- * Deal with the case where the name found was a dns entry.
- * Remove it as we now have a NetBIOS client registering the
- * name.
- */
-
- if((namerec != NULL) && ((namerec->source == DNS_NAME) || (namerec->source == DNSFAIL_NAME)))
- {
- DEBUG(5,("wins_process_name_registration_request: Name (%s) in WINS was a dns lookup \
-- removing it.\n", namestr(question) ));
- remove_name_from_namelist( subrec, namerec);
- namerec = NULL;
- }
-
- /*
- * Reject if the name exists and is not a REGISTER_NAME.
- * (ie. Don't allow any static names to be overwritten.
- */
-
- if((namerec != NULL) && (namerec->source != REGISTER_NAME))
- {
- DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
-already exists in WINS with source type %d.\n", namestr(question), namerec->source ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
-
- /*
- * Special policy decisions based on MS documentation.
- * 1). All group names (except names ending in 0x1c) are added as 255.255.255.255.
- * 2). All unique names ending in 0x1d are ignored, although a positive response is sent.
- */
-
- /*
- * A group name is always added as the local broadcast address, except
- * for group names ending in 0x1c.
- * Group names with type 0x1c are registered with individual IP addresses.
- */
-
- if(registering_group_name && (question->name_type != 0x1c))
- from_ip = *interpret_addr2("255.255.255.255");
-
- /*
- * Ignore all attempts to register a unique 0x1d name, although return success.
- */
-
- if(!registering_group_name && (question->name_type == 0x1d))
- {
- DEBUG(3,("wins_process_name_registration_request: Ignoring request \
-to register name %s from IP %s.", namestr(question), inet_ntoa(p->ip) ));
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
-
- /*
- * Next two cases are the 'if statement' mentioned above.
- */
-
- if((namerec != NULL) && NAME_GROUP(namerec))
- {
- if(registering_group_name)
- {
- /*
- * If we are adding a group name, the name exists and is also a group entry just add this
- * IP address to it and update the ttl.
- */
-
- DEBUG(3,("wins_process_name_registration_request: Adding IP %s to group name %s.\n",
- inet_ntoa(from_ip), namestr(question) ));
- /*
- * Check the ip address is not already in the group.
- */
- if(!find_ip_in_name_record(namerec, from_ip))
- add_ip_to_name_record(namerec, from_ip);
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
- else
- {
- /*
- * If we are adding a unique name, the name exists in the WINS db
- * and is a group name then reject the registration.
- */
-
- DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
-already exists in WINS as a GROUP name.\n", namestr(question) ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
- }
-
- /*
- * From here on down we know that if the name exists in the WINS db it is
- * a unique name, not a group name.
- */
-
- /*
- * If the name exists and is one of our names then check the
- * registering IP address. If it's not one of ours then automatically
- * reject without doing the query - we know we will reject it.
- */
-
- if((namerec != NULL) && (is_myname(namerec->name.name)) )
- {
- if(!ismyip(from_ip))
- {
- DEBUG(3,("wins_process_name_registration_request: Attempt to register name %s. Name \
-is one of our (WINS server) names. Denying registration.\n", namestr(question) ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
- else
- {
- /*
- * It's one of our names and one of our IP's - update the ttl.
- */
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
- }
-
- /*
- * If the name exists and it is a unique registration and the registering IP
- * is the same as the the (single) already registered IP then just update the ttl.
- */
-
- if(!registering_group_name && (namerec != NULL) && (namerec->num_ips == 1) &&
- ip_equal(namerec->ip[0], from_ip))
- {
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
-
- /*
- * Finally if the name exists do a query to the registering machine
- * to see if they still claim to have the name.
- */
-
- if(namerec != NULL)
- {
- char ud[sizeof(struct userdata_struct) + sizeof(struct packet_struct *)];
- struct userdata_struct *userdata = (struct userdata_struct *)&ud;
-
- /*
- * First send a WACK to the registering machine.
- */
-
- send_wins_wack_response(60, p);
-
- /*
- * When the reply comes back we need the original packet.
- * Lock this so it won't be freed and then put it into
- * the userdata structure.
- */
-
- p->locked = True;
-
- userdata = (struct userdata_struct *)ud;
-
- userdata->copy_fn = NULL;
- userdata->free_fn = NULL;
- userdata->userdata_len = sizeof(struct packet_struct *);
- memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
-
- /*
- * As query_name uses the subnet broadcast address as the destination
- * of the packet we temporarily change the subnet broadcast address to
- * be the first IP address of the name owner and send the packet. This
- * is a *horrible* hack but the alternative is to add the destination
- * address parameter to all query_name() calls. I hate this code :-).
- */
-
- subrec->bcast_ip = *namerec->ip;
-
- query_name( subrec, question->name, question->name_type,
- wins_register_query_success,
- wins_register_query_fail,
- userdata);
- subrec->bcast_ip = ipzero;
- return;
- }
-
- /*
- * Name did not exist - add it.
- */
-
- add_name_to_subnet(subrec, question->name, question->name_type,
- nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
-
- send_wins_name_registration_response(0, ttl, p);
-}
-
-/***********************************************************************
- Deal with a mutihomed name query success to the machine that
- requested the multihomed name registration.
-
- We have a locked pointer to the original packet stashed away in the
- userdata pointer.
-************************************************************************/
-
-static void wins_multihomed_register_query_success(struct subnet_record *subrec,
- struct userdata_struct *userdata,
- struct nmb_name *question_name,
- struct in_addr ip,
- struct res_rec *answers)
-{
- struct packet_struct *orig_reg_packet;
- struct nmb_packet *nmb;
- struct name_record *namerec = NULL;
- struct in_addr from_ip;
- int ttl;
-
- memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
-
- nmb = &orig_reg_packet->packet.nmb;
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
- ttl = get_ttl_from_packet(nmb);
-
- /*
- * We want to just add the new IP, as we now know the requesting
- * machine claims to own it. But we can't just do that as an arbitary
- * amount of time may have taken place between the name query
- * request and this response. So we check that
- * the name still exists and is in the same state - if so
- * we just add the extra IP and update the ttl.
- */
-
- namerec = find_name_on_subnet(subrec, question_name, FIND_ANY_NAME);
-
- if( (namerec == NULL) || (namerec->source != REGISTER_NAME) )
- {
- DEBUG(3,("wins_multihomed_register_query_success: name %s is not in the correct state to add \
-a subsequent IP addess.\n", namestr(question_name) ));
- send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
- return;
- }
-
- if(!find_ip_in_name_record(namerec, from_ip))
- add_ip_to_name_record(namerec, from_ip);
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, orig_reg_packet);
-
-}
-
-/***********************************************************************
- Deal with a name registration request query failure to a client that
- owned the name.
-
- We have a locked pointer to the original packet stashed away in the
- userdata pointer.
-************************************************************************/
-
-static void wins_multihomed_register_query_fail(struct subnet_record *subrec,
- struct response_record *rrec,
- struct nmb_name *question_name,
- int rcode)
-{
- struct userdata_struct *userdata = rrec->userdata;
- struct packet_struct *orig_reg_packet;
-
- memcpy((char *)&orig_reg_packet, userdata->data, sizeof(struct packet_struct *));
-
- DEBUG(3,("wins_multihomed_register_query_fail: Registering machine at IP %s failed to answer \
-query successfully for name %s.\n", inet_ntoa(orig_reg_packet->ip), namestr(question_name) ));
- send_wins_name_registration_response(RFS_ERR, 0, orig_reg_packet);
- return;
-}
-
-/***********************************************************************
- Deal with a multihomed name registration request to a WINS server.
- These cannot be group name registrations.
-***********************************************************************/
-
-void wins_process_multihomed_name_registration_request( struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- int ttl = get_ttl_from_packet(nmb);
- struct name_record *namerec = NULL;
- struct in_addr from_ip;
- BOOL group = (nb_flags & NB_GROUP) ? True : False;;
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
-
- if(bcast)
- {
- /*
- * We should only get unicast name registration packets here.
- * Anyone trying to register broadcast should not be going to a WINS
- * server. Log an error here.
- */
-
- DEBUG(0,("wins_process_multihomed_name_registration_request: broadcast name registration request \
-received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
- namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
- return;
- }
-
- /*
- * Only unique names should be registered multihomed.
- */
-
- if(group)
- {
- DEBUG(0,("wins_process_multihomed_name_registration_request: group name registration request \
-received for name %s from IP %s on subnet %s. Errror - group names should not be multihomed.\n",
- namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
- return;
- }
-
- DEBUG(3,("wins_process_multihomed_name_registration_request: name registration for name %s \
-IP %s\n", namestr(question), inet_ntoa(from_ip) ));
-
- /*
- * Deal with policy regarding 0x1d names.
- */
-
- if(question->name_type == 0x1d)
- {
- DEBUG(3,("wins_process_multihomed_name_registration_request: Ignoring request \
-to register name %s from IP %s.", namestr(question), inet_ntoa(p->ip) ));
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
-
- /*
- * See if the name already exists.
- */
-
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- /*
- * Deal with the case where the name found was a dns entry.
- * Remove it as we now have a NetBIOS client registering the
- * name.
- */
-
- if((namerec != NULL) && ((namerec->source == DNS_NAME) || (namerec->source == DNSFAIL_NAME)))
- {
- DEBUG(5,("wins_process_multihomed_name_registration_request: Name (%s) in WINS was a dns lookup \
-- removing it.\n", namestr(question) ));
- remove_name_from_namelist( subrec, namerec);
- namerec = NULL;
- }
-
- /*
- * Reject if the name exists and is not a REGISTER_NAME.
- * (ie. Don't allow any static names to be overwritten.
- */
-
- if((namerec != NULL) && (namerec->source != REGISTER_NAME))
- {
- DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
-already exists in WINS with source type %d.\n", namestr(question), namerec->source ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
-
- /*
- * Reject if the name exists and is a GROUP name.
- */
-
- if((namerec != NULL) && NAME_GROUP(namerec))
- {
- DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
-already exists in WINS as a GROUP name.\n", namestr(question) ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
-
- /*
- * From here on down we know that if the name exists in the WINS db it is
- * a unique name, not a group name.
- */
-
- /*
- * If the name exists and is one of our names then check the
- * registering IP address. If it's not one of ours then automatically
- * reject without doing the query - we know we will reject it.
- */
-
- if((namerec != NULL) && (is_myname(namerec->name.name)) )
- {
- if(!ismyip(from_ip))
- {
- DEBUG(3,("wins_process_multihomed_name_registration_request: Attempt to register name %s. Name \
-is one of our (WINS server) names. Denying registration.\n", namestr(question) ));
- send_wins_name_registration_response(RFS_ERR, 0, p);
- return;
- }
- else
- {
- /*
- * It's one of our names and one of our IP's. Ensure the IP is in the record and
- * update the ttl.
- */
- if(!find_ip_in_name_record(namerec, from_ip))
- add_ip_to_name_record(namerec, from_ip);
- update_name_ttl(namerec, ttl);
- send_wins_name_registration_response(0, ttl, p);
- return;
- }
- }
-
- /*
- * If the name exists do a query to the owner
- * to see if they still want the name.
- */
-
- if(namerec != NULL)
- {
- char ud[sizeof(struct userdata_struct) + sizeof(struct packet_struct *)];
- struct userdata_struct *userdata = (struct userdata_struct *)&ud;
-
- /*
- * First send a WACK to the registering machine.
- */
-
- send_wins_wack_response(60, p);
-
- /*
- * When the reply comes back we need the original packet.
- * Lock this so it won't be freed and then put it into
- * the userdata structure.
- */
-
- p->locked = True;
-
- userdata = (struct userdata_struct *)ud;
-
- userdata->copy_fn = NULL;
- userdata->free_fn = NULL;
- userdata->userdata_len = sizeof(struct packet_struct *);
- memcpy(userdata->data, (char *)&p, sizeof(struct packet_struct *) );
-
- /*
- * As query_name uses the subnet broadcast address as the destination
- * of the packet we temporarily change the subnet broadcast address to
- * be the IP address of the requesting machine and send the packet. This
- * is a *horrible* hack but the alternative is to add the destination
- * address parameter to all query_name() calls. I hate this code :-).
- */
-
- subrec->bcast_ip = p->ip;
- query_name( subrec, question->name, question->name_type,
- wins_multihomed_register_query_success,
- wins_multihomed_register_query_fail,
- userdata);
- subrec->bcast_ip = ipzero;
- return;
- }
-
- /*
- * Name did not exist - add it.
- */
-
- add_name_to_subnet(subrec, question->name, question->name_type,
- nb_flags, ttl, REGISTER_NAME, 1, &from_ip);
-
- send_wins_name_registration_response(0, ttl, p);
-}
-
-/***********************************************************************
- Deal with the special name query for *<1b>.
-***********************************************************************/
-
-static void process_wins_dmb_query_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct name_record *namerec = NULL;
- char *prdata;
- int num_ips;
-
- /*
- * Go through all the names in the WINS db looking for those
- * ending in <1b>. Use this to calculate the number of IP
- * addresses we need to return.
- */
-
- num_ips = 0;
- for(namerec = subrec->namelist; namerec; namerec = namerec->next)
- {
- if(namerec->name.name_type == 0x1b)
- num_ips += namerec->num_ips;
- }
-
- if(num_ips == 0)
- {
- /*
- * There are no 0x1b names registered. Return name query fail.
- */
- send_wins_name_query_response(NAM_ERR, p, NULL);
- return;
- }
-
- if((prdata = (char *)malloc( num_ips * 6 )) == NULL)
- {
- DEBUG(0,("process_wins_dmb_query_request: Malloc fail !.\n"));
- return;
- }
-
- /*
- * Go through all the names again in the WINS db looking for those
- * ending in <1b>. Add their IP addresses into the list we will
- * return.
- */
-
- num_ips = 0;
- for(namerec = subrec->namelist; namerec; namerec = namerec->next)
- {
- if(namerec->name.name_type == 0x1b)
- {
- int i;
- for(i = 0; i < namerec->num_ips; i++)
- {
- set_nb_flags(&prdata[num_ips * 6],namerec->nb_flags);
- putip((char *)&prdata[(num_ips * 6) + 2], &namerec->ip[i]);
- num_ips++;
- }
- }
- }
-
- /*
- * Send back the reply containing the IP list.
- */
-
- reply_netbios_packet(p, /* Packet to reply to. */
- 0, /* Result code. */
- WINS_QUERY, /* nmbd type code. */
- NMB_NAME_QUERY_OPCODE, /* opcode. */
- lp_min_wins_ttl(), /* ttl. */
- prdata, /* data to send. */
- num_ips*6); /* data length. */
-
- free(prdata);
-}
-
-/****************************************************************************
-Send a WINS name query response.
-**************************************************************************/
-
-void send_wins_name_query_response(int rcode, struct packet_struct *p,
- struct name_record *namerec)
-{
- char rdata[6];
- char *prdata = rdata;
- int reply_data_len = 0;
- int ttl = 0;
- int i = 0;
- int j;
-
- bzero(rdata,6);
-
- if(rcode == 0)
- {
- int same_net_index;
-
- ttl = (namerec->death_time != PERMANENT_TTL) ?
- namerec->death_time - p->timestamp : lp_max_wins_ttl();
-
- /* Copy all known ip addresses into the return data. */
- /* Optimise for the common case of one IP address so
- we don't need a malloc. */
-
- if(namerec->num_ips == 1 )
- prdata = rdata;
- else
- {
- if((prdata = (char *)malloc( namerec->num_ips * 6 )) == NULL)
- {
- DEBUG(0,("send_wins_name_query_response: malloc fail !\n"));
- return;
- }
-
- /*
- * Look over the known IP addresses and see if one of them
- * is on the same (local) net as the requesting IP address. If so then
- * put that IP address into the packet as the first IP.
- * We can only do this for local nets as they're the only
- * ones we know the netmask for.
- */
-
- same_net_index = -1;
- i = 0;
-
- if(is_local_net(p->ip))
- {
- struct in_addr *n_mask = iface_nmask(p->ip);
-
- for( j = 0; j < namerec->num_ips; j++)
- {
- if(same_net( namerec->ip[j], p->ip, *n_mask))
- {
- set_nb_flags(&prdata[0],namerec->nb_flags);
- putip((char *)&prdata[2], &namerec->ip[j]);
- same_net_index = j;
- i = 1;
- }
- }
- }
- }
-
- for(; i < namerec->num_ips; i++)
- {
- if(i == same_net_index)
- continue;
- set_nb_flags(&prdata[i*6],namerec->nb_flags);
- putip((char *)&prdata[2+(i*6)], &namerec->ip[i]);
- }
- reply_data_len = namerec->num_ips * 6;
-
- }
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- WINS_QUERY, /* nmbd type code. */
- NMB_NAME_QUERY_OPCODE, /* opcode. */
- ttl, /* ttl. */
- prdata, /* data to send. */
- reply_data_len); /* data length. */
-
- if((prdata != rdata) && (prdata != NULL))
- free(prdata);
-}
-
-/***********************************************************************
- Deal with a name query.
-***********************************************************************/
-
-void wins_process_name_query_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- struct name_record *namerec = NULL;
-
- DEBUG(3,("wins_process_name_query: name query for name %s from IP %s\n",
- namestr(question), inet_ntoa(p->ip) ));
-
- /*
- * Special name code. If the queried name is *<1b> then search
- * the entire WINS database and return a list of all the IP addresses
- * registered to any <1b> name. This is to allow domain master browsers
- * to discover other domains that may not have a presence on their subnet.
- */
-
- if(strequal( question->name, "*") && (question->name_type == 0x1b))
- {
- process_wins_dmb_query_request( subrec, p);
- return;
- }
-
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- if(namerec != NULL)
- {
- /*
- * If it's a DNSFAIL_NAME then reply name not found.
- */
-
- if(namerec->source == DNSFAIL_NAME)
- {
- DEBUG(3,("wins_process_name_query: name query for name %s returning DNS fail.\n",
- namestr(question) ));
- send_wins_name_query_response(NAM_ERR, p, namerec);
- return;
- }
-
- /*
- * If the name has expired then reply name not found.
- */
-
- if((namerec->death_time != PERMANENT_TTL) && (namerec->death_time < p->timestamp))
- {
- DEBUG(3,("wins_process_name_query: name query for name %s - name expired. Returning fail.\n",
- namestr(question) ));
- send_wins_name_query_response(NAM_ERR, p, namerec);
- return;
- }
-
- DEBUG(3,("wins_process_name_query: name query for name %s returning first IP %s.\n",
- namestr(question), inet_ntoa(namerec->ip[0]) ));
-
- send_wins_name_query_response(0, p, namerec);
- return;
- }
-
- /*
- * Name not found in WINS - try a dns query if it's a 0x20 name.
- */
-
- if(lp_dns_proxy() &&
- ((question->name_type == 0x20) || question->name_type == 0))
- {
-
- DEBUG(3,("wins_process_name_query: name query for name %s not found - doing dns lookup.\n",
- namestr(question) ));
-
- queue_dns_query(p, question, &namerec);
- return;
- }
-
- /*
- * Name not found - return error.
- */
-
- send_wins_name_query_response(NAM_ERR, p, NULL);
-}
-
-/****************************************************************************
-Send a WINS name release response.
-**************************************************************************/
-
-static void send_wins_name_release_response(int rcode, struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- char rdata[6];
-
- memcpy(&rdata[0], &nmb->additional->rdata[0], 6);
-
- reply_netbios_packet(p, /* Packet to reply to. */
- rcode, /* Result code. */
- NMB_REL, /* nmbd type code. */
- NMB_NAME_RELEASE_OPCODE, /* opcode. */
- 0, /* ttl. */
- rdata, /* data to send. */
- 6); /* data length. */
-}
-
-/***********************************************************************
- Deal with a name release.
-***********************************************************************/
-
-void wins_process_name_release_request(struct subnet_record *subrec,
- struct packet_struct *p)
-{
- struct nmb_packet *nmb = &p->packet.nmb;
- struct nmb_name *question = &nmb->question.question_name;
- BOOL bcast = nmb->header.nm_flags.bcast;
- uint16 nb_flags = get_nb_flags(nmb->additional->rdata);
- struct name_record *namerec = NULL;
- struct in_addr from_ip;
- BOOL releasing_group_name = (nb_flags & NB_GROUP) ? True : False;;
-
- putip((char *)&from_ip,&nmb->additional->rdata[2]);
-
- if(bcast)
- {
- /*
- * We should only get unicast name registration packets here.
- * Anyone trying to register broadcast should not be going to a WINS
- * server. Log an error here.
- */
-
- DEBUG(0,("wins_process_name_release_request: broadcast name registration request \
-received for name %s from IP %s on subnet %s. Error - should not be sent to WINS server\n",
- namestr(question), inet_ntoa(from_ip), subrec->subnet_name));
- return;
- }
-
- DEBUG(3,("wins_process_name_release_request: %s name release for name %s \
-IP %s\n", releasing_group_name ? "Group" : "Unique", namestr(question), inet_ntoa(from_ip) ));
-
- /*
- * Deal with policy regarding 0x1d names.
- */
-
- if(!releasing_group_name && (question->name_type == 0x1d))
- {
- DEBUG(3,("wins_process_name_release_request: Ignoring request \
-to release name %s from IP %s.", namestr(question), inet_ntoa(p->ip) ));
- send_wins_name_release_response(0, p);
- return;
- }
-
- /*
- * See if the name already exists.
- */
-
- namerec = find_name_on_subnet(subrec, question, FIND_ANY_NAME);
-
- if((namerec == NULL) || ((namerec != NULL) && (namerec->source != REGISTER_NAME)) )
- {
- send_wins_name_release_response(NAM_ERR, p);
- return;
- }
-
- /*
- * Check that the sending machine has permission to release this name.
- * If it's a group name not ending in 0x1c then just say yes and let
- * the group time out.
- */
-
- if(releasing_group_name && (question->name_type != 0x1c))
- {
- send_wins_name_release_response(0, p);
- return;
- }
-
- /*
- * Check that the releasing node is on the list of IP addresses
- * for this name. Disallow the release if not.
- */
-
- if(!find_ip_in_name_record(namerec, from_ip))
- {
- DEBUG(3,("wins_process_name_release_request: Refusing request to \
-release name %s as IP %s is not one of the known IP's for this name.\n",
- namestr(question), inet_ntoa(from_ip) ));
- send_wins_name_release_response(NAM_ERR, p);
- return;
- }
-
- /*
- * Release the name and then remove the IP from the known list.
- */
-
- send_wins_name_release_response(0, p);
- remove_ip_from_name_record(namerec, from_ip);
-
- /*
- * Remove the name entirely if no IP addresses left.
- */
- if (namerec->num_ips == 0)
- remove_name_from_namelist(subrec, namerec);
-
-}
-
-/*******************************************************************
- WINS time dependent processing.
-******************************************************************/
-
-void initiate_wins_processing(time_t t)
-{
- static time_t lasttime = 0;
-
- if (!lasttime)
- lasttime = t;
- if (t - lasttime < 5)
- return;
-
- if(!lp_we_are_a_wins_server())
- return;
-
- expire_names_on_subnet(wins_server_subnet, t);
-
- if(wins_server_subnet->namelist_changed)
- wins_write_database();
-
- wins_server_subnet->namelist_changed = False;
-}
-
-/*******************************************************************
- Write out the current WINS database.
-******************************************************************/
-
-void wins_write_database(void)
-{
- struct name_record *namerec;
- fstring fname, fnamenew;
-
- FILE *fp;
-
- if(!lp_we_are_a_wins_server())
- return;
-
- fstrcpy(fname,lp_lockdir());
- trim_string(fname,NULL,"/");
- strcat(fname,"/");
- strcat(fname,WINS_LIST);
- fstrcpy(fnamenew,fname);
- strcat(fnamenew,".");
-
- if((fp = fopen(fnamenew,"w")) == NULL)
- {
- DEBUG(0,("wins_write_database: Can't open %s. Error was %s\n", fnamenew, strerror(errno)));
- return;
- }
-
- DEBUG(4,("wins_write_database: Dump of WINS name list.\n"));
-
- for (namerec = wins_server_subnet->namelist; namerec; namerec = namerec->next)
- {
- int i;
- struct tm *tm;
-
- DEBUG(4,("%-19s ", namestr(&namerec->name) ));
-
- if(namerec->death_time != PERMANENT_TTL)
- {
- tm = LocalTime(&namerec->death_time);
- DEBUG(4,("TTL = %s", asctime(tm) ));
- }
- else
- DEBUG(4,("TTL = PERMANENT\t"));
-
- for (i = 0; i < namerec->num_ips; i++)
- DEBUG(4,("%15s ", inet_ntoa(namerec->ip[i]) ));
- DEBUG(4,("%2x\n", namerec->nb_flags ));
-
- if (namerec->source == REGISTER_NAME)
- {
- fprintf(fp, "%s#%02x %ld ",
- namerec->name.name,namerec->name.name_type, /* Ignore scope. */
- namerec->death_time);
-
- for (i = 0; i < namerec->num_ips; i++)
- fprintf(fp, "%s ", inet_ntoa(namerec->ip[i]));
- fprintf(fp, "%2xR\n", namerec->nb_flags);
- }
- }
-
- fclose(fp);
- unlink(fname);
- chmod(fnamenew,0644);
- rename(fnamenew,fname);
-}
diff --git a/source/nmbd/nmbd_workgroupdb.c b/source/nmbd/nmbd_workgroupdb.c
deleted file mode 100644
index 828e29a024d..00000000000
--- a/source/nmbd/nmbd_workgroupdb.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- NBT netbios routines and daemon - version 2
- Copyright (C) Andrew Tridgell 1994-1997
- Copyright (C) Luke Kenneth Casson Leighton 1994-1997
- Copyright (C) Jeremy Allison 1994-1997
-
- 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.
-
-*/
-
-#include "includes.h"
-#include "smb.h"
-
-extern int ClientNMB;
-
-extern int DEBUGLEVEL;
-
-extern pstring myname;
-extern fstring myworkgroup;
-extern char **my_netbios_names;
-extern uint16 samba_nb_type;
-extern struct in_addr ipzero;
-
-int workgroup_count = 0; /* unique index key: one for each workgroup */
-
-/****************************************************************************
- Add a workgroup into the list.
- **************************************************************************/
-
-static void add_workgroup(struct subnet_record *subrec, struct work_record *work)
-{
- struct work_record *w2;
-
- work->subnet = subrec;
-
- if (!subrec->workgrouplist)
- {
- subrec->workgrouplist = work;
- work->prev = NULL;
- work->next = NULL;
- return;
- }
-
- for (w2 = subrec->workgrouplist; w2->next; w2 = w2->next)
- ;
-
- w2->next = work;
- work->next = NULL;
- work->prev = w2;
-
- subrec->work_changed = True;
-}
-
-/****************************************************************************
- Create an empty workgroup.
- **************************************************************************/
-
-static struct work_record *create_workgroup(char *name, int ttl)
-{
- struct work_record *work;
- struct subnet_record *subrec;
- int t = -1;
-
- if((work = (struct work_record *)malloc(sizeof(*work))) == NULL)
- {
- DEBUG(0,("create_workgroup: malloc fail !\n"));
- return NULL;
- }
- bzero((char *)work, sizeof(*work));
-
- StrnCpy(work->work_group,name,sizeof(work->work_group)-1);
- work->serverlist = NULL;
-
- work->RunningElection = False;
- work->ElectionCount = 0;
- work->announce_interval = 0;
- work->needelection = False;
- work->needannounce = True;
- work->lastannounce_time = time(NULL);
- work->mst_state = lp_local_master() ? MST_POTENTIAL : MST_NONE;
- work->dom_state = DOMAIN_NONE;
- work->log_state = LOGON_NONE;
-
- work->death_time = (ttl != PERMANENT_TTL) ? time(NULL)+(ttl*3) : PERMANENT_TTL;
-
- /* Make sure all token representations of workgroups are unique. */
-
- for (subrec = FIRST_SUBNET; subrec && (t == -1);
- subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- struct work_record *w;
- for (w = subrec->workgrouplist; w && t == -1; w = w->next)
- {
- if (strequal(w->work_group, work->work_group))
- t = w->token;
- }
- }
-
- if (t == -1)
- work->token = ++workgroup_count;
- else
- work->token = t;
-
- /* No known local master browser as yet. */
- *work->local_master_browser_name = '\0';
-
- /* No known domain master browser as yet. */
- *work->dmb_name.name = '\0';
- putip((char *)&work->dmb_addr, &ipzero);
-
- /* WfWg uses 01040b01 */
- /* Win95 uses 01041501 */
- /* NTAS uses ???????? */
- work->ElectionCriterion = (MAINTAIN_LIST)|(ELECTION_VERSION<<8);
- work->ElectionCriterion |= (lp_os_level() << 24);
- if (lp_domain_master())
- work->ElectionCriterion |= 0x80;
-
- return work;
-}
-
-/*******************************************************************
- Remove a workgroup.
- ******************************************************************/
-
-static struct work_record *remove_workgroup_from_subnet(struct subnet_record *subrec,
- struct work_record *work)
-{
- struct work_record *ret_work = NULL;
-
- DEBUG(3,("remove_workgroup: Removing workgroup %s\n", work->work_group));
-
- ret_work = work->next;
-
- remove_all_servers(work);
-
- if (!work->serverlist)
- {
- if (work->prev)
- work->prev->next = work->next;
- if (work->next)
- work->next->prev = work->prev;
-
- if (subrec->workgrouplist == work)
- subrec->workgrouplist = work->next;
-
- free((char *)work);
- }
-
- subrec->work_changed = True;
-
- return ret_work;
-}
-
-
-/****************************************************************************
- Find a workgroup in the workgroup list of a subnet.
- **************************************************************************/
-
-struct work_record *find_workgroup_on_subnet(struct subnet_record *subrec,
- fstring name)
-{
- struct work_record *ret;
-
- DEBUG(4, ("find_workgroup_on_subnet: workgroup search for %s on subnet %s: ",
- name, subrec->subnet_name));
-
- for (ret = subrec->workgrouplist; ret; ret = ret->next)
- {
- if (!strcmp(ret->work_group,name))
- {
- DEBUG(4, ("found\n"));
- return(ret);
- }
- }
- DEBUG(4, ("not found\n"));
- return NULL;
-}
-
-/****************************************************************************
- Create a workgroup in the workgroup list of the subnet.
- **************************************************************************/
-
-struct work_record *create_workgroup_on_subnet(struct subnet_record *subrec,
- fstring name, int ttl)
-{
- struct work_record *work = NULL;
-
- DEBUG(4,("create_workgroup_on_subnet: creating group %s on subnet %s\n",
- name, subrec->subnet_name));
-
- if ((work = create_workgroup(name, ttl)))
- {
- add_workgroup(subrec, work);
-
- subrec->work_changed = True;
-
- return(work);
- }
-
- return NULL;
-}
-
-/****************************************************************************
- Update a workgroup ttl.
- **************************************************************************/
-
-void update_workgroup_ttl(struct work_record *work, int ttl)
-{
- if(work->death_time != PERMANENT_TTL)
- work->death_time = time(NULL)+(ttl*3);
- work->subnet->work_changed = True;
-}
-
-/****************************************************************************
- Fail function called if we cannot register the WORKGROUP<0> and
- WORKGROUP<1e> names on the net.
-**************************************************************************/
-
-static void fail_register(struct subnet_record *subrec, struct response_record *rrec,
- struct nmb_name *nmbname)
-{
- DEBUG(0,("fail_register: Failed to register name %s on subnet %s.\n",
- namestr(nmbname), subrec->subnet_name));
-}
-
-/****************************************************************************
- If the workgroup is our primary workgroup, add the required names to it.
-**************************************************************************/
-
-void initiate_myworkgroup_startup(struct subnet_record *subrec, struct work_record *work)
-{
- int i;
-
- if(!strequal(myworkgroup, work->work_group))
- return;
-
- /* If this is a broadcast subnet then start elections on it
- if we are so configured. */
-
- if ((subrec != unicast_subnet) && (subrec != remote_broadcast_subnet) &&
- (subrec != wins_server_subnet) && lp_preferred_master() &&
- lp_local_master())
- {
- DEBUG(3, ("initiate_myworkgroup_startup: preferred master startup for \
-workgroup %s on subnet %s\n", work->work_group, subrec->subnet_name));
- work->needelection = True;
- work->ElectionCriterion |= (1<<3);
- }
-
- /* Register the WORKGROUP<0> and WORKGROUP<1e> names on the network. */
-
- register_name(subrec,myworkgroup,0x0,samba_nb_type|NB_GROUP,
- NULL,
- fail_register,NULL);
-
- register_name(subrec,myworkgroup,0x1e,samba_nb_type|NB_GROUP,
- NULL,
- fail_register,NULL);
-
- for( i = 0; my_netbios_names[i]; i++)
- {
- char *name = my_netbios_names[i];
- int stype = lp_default_server_announce() | (lp_local_master() ?
- SV_TYPE_POTENTIAL_BROWSER : 0 );
-
- if(!strequal(myname, name))
- stype &= ~(SV_TYPE_MASTER_BROWSER|SV_TYPE_POTENTIAL_BROWSER|
- SV_TYPE_DOMAIN_MASTER|SV_TYPE_DOMAIN_MEMBER);
-
- create_server_on_workgroup(work,name,stype|SV_TYPE_LOCAL_LIST_ONLY,
- PERMANENT_TTL, lp_serverstring());
- DEBUG(3,("initiate_myworkgroup_startup: Added server name entry %s \
-on subnet %s\n", name, subrec->subnet_name));
- }
-}
-
-/****************************************************************************
- Dump a copy of the workgroup database into the log file.
- **************************************************************************/
-
-void dump_workgroups(void)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- if (subrec->workgrouplist)
- {
- struct work_record *work;
-
- DEBUG(4,("dump_workgroups: dump workgroup on subnet %15s: ", subrec->subnet_name));
- DEBUG(4,(" netmask=%15s:\n", inet_ntoa(subrec->mask_ip)));
-
- for (work = subrec->workgrouplist; work; work = work->next)
- {
- DEBUG(4,("\t%s(%d) current master browser = %s\n", work->work_group,
- work->token,
- *work->local_master_browser_name ? work->local_master_browser_name : "UNKNOWN" ));
- if (work->serverlist)
- {
- struct server_record *servrec;
- for (servrec = work->serverlist; servrec; servrec = servrec->next)
- {
- DEBUG(4,("\t\t%s %8x (%s)\n",
- servrec->serv.name, servrec->serv.type, servrec->serv.comment));
- }
- }
- }
- }
- }
-}
-
-/****************************************************************************
- Expire any dead servers on all workgroups. If the workgroup has expired
- remove it.
- **************************************************************************/
-
-void expire_workgroups_and_servers(time_t t)
-{
- struct subnet_record *subrec;
-
- for (subrec = FIRST_SUBNET; subrec; subrec = NEXT_SUBNET_INCLUDING_UNICAST(subrec))
- {
- struct work_record *work;
- struct work_record *nextwork;
-
- for (work = subrec->workgrouplist; work; work = nextwork)
- {
- nextwork = work->next;
- expire_servers(work, t);
-
- if ((work->serverlist == NULL) && (work->death_time != PERMANENT_TTL) &&
- ((t == -1) || (work->death_time < t)))
- {
- DEBUG(3,("expire_workgroups_and_servers: Removing timed out workgroup %s\n",
- work->work_group));
- remove_workgroup_from_subnet(subrec, work);
- }
- }
- }
-}
diff --git a/source/nmbsync.c b/source/nmbsync.c
new file mode 100644
index 00000000000..de2f7aa00f1
--- /dev/null
+++ b/source/nmbsync.c
@@ -0,0 +1,191 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ NBT netbios routines to synchronise browse lists
+ Copyright (C) Andrew Tridgell 1994-1997
+
+ 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.
+
+*/
+
+/* We *must have REPLACE_GETPASS defined here before the includes. */
+#define REPLACE_GETPASS
+#include "includes.h"
+
+extern int ClientNMB;
+extern int ClientDGRAM;
+
+extern int DEBUGLEVEL;
+
+extern pstring myname;
+
+extern int name_type;
+extern int max_protocol;
+extern struct in_addr dest_ip;
+extern int pid;
+extern int gid;
+extern int uid;
+extern int mid;
+extern BOOL got_pass;
+extern BOOL have_ip;
+extern pstring workgroup;
+extern pstring service;
+extern pstring desthost;
+extern BOOL connect_as_ipc;
+
+/****************************************************************************
+fudge for getpass function
+****************************************************************************/
+char *getsmbpass(char *pass)
+{
+ return "dummy"; /* return anything: it should be ignored anyway */
+}
+
+/****************************************************************************
+adds information retrieved from a NetServerEnum call
+****************************************************************************/
+static BOOL add_info(struct subnet_record *d, struct work_record *work, int servertype)
+{
+ char *rparam = NULL;
+ char *rdata = NULL;
+ int rdrcnt,rprcnt;
+ char *p;
+ pstring param;
+ int uLevel = 1;
+ int count = -1;
+
+ /* now send a SMBtrans command with api ServerEnum? */
+ p = param;
+ SSVAL(p,0,0x68); /* api number */
+ p += 2;
+ strcpy(p,"WrLehDz");
+ p = skip_string(p,1);
+
+ strcpy(p,"B16BBDz");
+
+ p = skip_string(p,1);
+ SSVAL(p,0,uLevel);
+ SSVAL(p,2,BUFFER_SIZE - SAFETY_MARGIN); /* buf length */
+ p += 4;
+ SIVAL(p,0,servertype);
+ p += 4;
+
+ pstrcpy(p, work->work_group);
+ p = skip_string(p,1);
+
+ if (cli_call_api(PTR_DIFF(p,param),0, 8,BUFFER_SIZE - SAFETY_MARGIN,
+ &rprcnt,&rdrcnt, param,NULL,
+ &rparam,&rdata))
+ {
+ int res = SVAL(rparam,0);
+ int converter=SVAL(rparam,2);
+ int i;
+
+ if (res == 0)
+ {
+ count=SVAL(rparam,4);
+ p = rdata;
+
+ for (i = 0;i < count;i++, p += 26)
+ {
+ char *sname = p;
+ uint32 stype = IVAL(p,18) & ~SV_TYPE_LOCAL_LIST_ONLY;
+ int comment_offset = IVAL(p,22) & 0xFFFF;
+ char *cmnt = comment_offset?(rdata+comment_offset-converter):"";
+
+ struct work_record *w = work;
+
+ DEBUG(4, ("\t%-16.16s %08x %s\n", sname, stype, cmnt));
+
+ if (stype & SV_TYPE_DOMAIN_ENUM)
+ {
+ /* creates workgroup on remote subnet */
+ if ((w = find_workgroupstruct(d,sname,True)))
+ {
+ announce_request(w, d->bcast_ip);
+ }
+ }
+
+ if (w)
+ add_server_entry(d,w,sname,stype,lp_max_ttl(),cmnt,False);
+ }
+ }
+ }
+
+ if (rparam) free(rparam);
+ if (rdata) free(rdata);
+
+ return(True);
+}
+
+
+/*******************************************************************
+ synchronise browse lists with another browse server.
+
+ log in on the remote server's SMB port to their IPC$ service,
+ do a NetServerEnum and update our server and workgroup databases.
+ ******************************************************************/
+void sync_browse_lists(struct subnet_record *d, struct work_record *work,
+ char *name, int nm_type, struct in_addr ip, BOOL local)
+{
+ uint32 local_type = local ? SV_TYPE_LOCAL_LIST_ONLY : 0;
+
+ if (!d || !work ) return;
+
+ if(d != wins_subnet) {
+ DEBUG(0,
+ ("sync_browse_lists: ERROR sync requested on non-WINS subnet.\n"));
+ return;
+ }
+
+ pid = getpid();
+ uid = getuid();
+ gid = getgid();
+ mid = pid + 100;
+ name_type = nm_type;
+
+ got_pass = True;
+
+ DEBUG(0,("sync_browse_lists: Sync browse lists with %s for %s %s\n",
+ name, work->work_group, inet_ntoa(ip)));
+
+ strcpy(workgroup,work->work_group);
+ fstrcpy(desthost,name);
+ dest_ip = ip;
+
+ if (zero_ip(dest_ip)) return;
+ have_ip = True;
+
+ connect_as_ipc = True;
+
+ /* connect as server and get domains, then servers */
+
+ sprintf(service,"\\\\%s\\IPC$", name);
+ strupper(service);
+
+ if (cli_open_sockets(SMB_PORT))
+ {
+ if (cli_send_login(NULL,NULL,True,True))
+ {
+ add_info(d, work, local_type|SV_TYPE_DOMAIN_ENUM);
+ if(local)
+ add_info(d, work, SV_TYPE_LOCAL_LIST_ONLY);
+ else
+ add_info(d, work, SV_TYPE_ALL);
+ }
+
+ close_sockets();
+ }
+}
diff --git a/source/param/loadparm.c b/source/param/loadparm.c
index b2a016d8a5e..244d6ed8bfc 100644
--- a/source/param/loadparm.c
+++ b/source/param/loadparm.c
@@ -49,11 +49,6 @@
#include "includes.h"
-/* Set default coding system for KANJI if none specified in Makefile. */
-#ifndef KANJI
-#define KANJI "sjis"
-#endif /* KANJI */
-
BOOL bLoaded = False;
extern int DEBUGLEVEL;
@@ -64,6 +59,14 @@ extern pstring myname;
#define GLOBAL_NAME "global"
#endif
+#ifndef PRINTCAP_NAME
+#ifdef AIX
+#define PRINTCAP_NAME "/etc/qconfig"
+#else
+#define PRINTCAP_NAME "/etc/printcap"
+#endif
+#endif
+
#ifndef PRINTERS_NAME
#define PRINTERS_NAME "printers"
#endif
@@ -82,7 +85,7 @@ extern pstring myname;
typedef enum
{
P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,
- P_STRING,P_USTRING,P_GSTRING,P_UGSTRING,P_ENUM
+ P_STRING,P_USTRING,P_GSTRING,P_UGSTRING
} parm_type;
typedef enum
@@ -94,6 +97,9 @@ int keepalive=0;
extern BOOL use_getwd_cache;
extern int extra_time_offset;
+#ifdef KANJI
+extern int coding_system;
+#endif
/*
* This structure describes global (ie., server-wide) parameters.
@@ -118,19 +124,13 @@ typedef struct
char *szSocketOptions;
char *szValidChars;
char *szWorkGroup;
- char *szDomainAdminUsers;
- char *szDomainGuestUsers;
- char *szDomainHostsallow;
- char *szDomainHostsdeny;
+ char *szDomainController;
char *szUsernameMap;
char *szCharacterSet;
char *szLogonScript;
char *szLogonPath;
- char *szLogonDrive;
- char *szLogonHome;
char *szSmbrun;
char *szWINSserver;
- char *szCodingSystem;
char *szInterfaces;
char *szRemoteAnnounce;
char *szRemoteBrowseSync;
@@ -138,31 +138,24 @@ typedef struct
char *szNISHomeMapName;
char *szAnnounceVersion; /* This is initialised in init_globals */
char *szNetbiosAliases;
- char *szDomainSID;
- char *szDomainOtherSIDs;
- char *szDomainGroups;
- char *szDriverFile;
int max_log_size;
int mangled_stack;
int max_xmit;
int max_mux;
int max_packet;
int pwordlevel;
- int unamelevel;
int deadtime;
int maxprotocol;
int security;
+ int printing;
int maxdisksize;
int lpqcachetime;
int syslog;
int os_level;
int max_ttl;
- int max_wins_ttl;
- int min_wins_ttl;
int ReadSize;
- int lm_announce;
- int lm_interval;
int shmem_size;
+ int shmem_hash_size;
int client_code_page;
int announce_as; /* This is initialised in init_globals */
BOOL bDNSproxy;
@@ -170,7 +163,6 @@ typedef struct
BOOL bWINSproxy;
BOOL bLocalMaster;
BOOL bPreferredMaster;
- BOOL bDomainController;
BOOL bDomainMaster;
BOOL bDomainLogons;
BOOL bEncryptPasswords;
@@ -187,7 +179,6 @@ typedef struct
BOOL bUnixRealname;
BOOL bNISHomeMap;
BOOL bTimeServer;
- BOOL bBindInterfacesOnly;
} global;
static global Globals;
@@ -220,7 +211,6 @@ typedef struct
char *szLpresumecommand;
char *szPrintername;
char *szPrinterDriver;
- char *szPrinterDriverLocation;
char *szDontdescend;
char *szHostsallow;
char *szHostsdeny;
@@ -229,7 +219,6 @@ typedef struct
char *szMangledMap;
char *szVetoFiles;
char *szHideFiles;
- char *szVetoOplockFiles;
char *comment;
char *force_user;
char *force_group;
@@ -243,7 +232,6 @@ typedef struct
int iDir_force_mode;
int iMaxConnections;
int iDefaultCase;
- int iPrinting;
BOOL bAlternatePerm;
BOOL bRevalidate;
BOOL bCaseSensitive;
@@ -266,7 +254,6 @@ typedef struct
BOOL bLocking;
BOOL bStrictLocking;
BOOL bShareModes;
- BOOL bOpLocks;
BOOL bOnlyUser;
BOOL bMangledNames;
BOOL bWidelinks;
@@ -276,7 +263,6 @@ typedef struct
BOOL *copymap;
BOOL bDeleteReadonly;
BOOL bFakeOplocks;
- BOOL bDeleteVetoFiles;
BOOL bDosFiletimes;
char dummy[3]; /* for alignment */
} service;
@@ -306,7 +292,6 @@ static service sDefault =
NULL, /* szLpresumecommand */
NULL, /* szPrintername */
NULL, /* szPrinterDriver - this is set in init_globals() */
- NULL, /* szPrinterDriverLocation */
NULL, /* szDontdescend */
NULL, /* szHostsallow */
NULL, /* szHostsdeny */
@@ -315,7 +300,6 @@ static service sDefault =
NULL, /* szMangledMap */
NULL, /* szVetoFiles */
NULL, /* szHideFiles */
- NULL, /* szVetoOplockFiles */
NULL, /* comment */
NULL, /* force user */
NULL, /* force group */
@@ -329,7 +313,6 @@ static service sDefault =
0000, /* iDir_force_mode */
0, /* iMaxConnections */
CASE_LOWER, /* iDefaultCase */
- DEFAULT_PRINTING, /* iPrinting */
False, /* bAlternatePerm */
False, /* revalidate */
False, /* case sensitive */
@@ -352,7 +335,6 @@ static service sDefault =
True, /* bLocking */
False, /* bStrictLocking */
True, /* bShareModes */
- True, /* bOpLocks */
False, /* bOnlyUser */
True, /* bMangledNames */
True, /* bWidelinks */
@@ -362,7 +344,6 @@ static service sDefault =
NULL, /* copymap */
False, /* bDeleteReadonly */
False, /* bFakeOplocks */
- False, /* bDeleteVetoFiles */
False, /* bDosFiletimes */
"" /* dummy */
};
@@ -383,249 +364,209 @@ static int default_server_announce;
static BOOL handle_valid_chars(char *pszParmValue, char **ptr);
static BOOL handle_include(char *pszParmValue, char **ptr);
static BOOL handle_copy(char *pszParmValue, char **ptr);
+static BOOL handle_protocol(char *pszParmValue,int *val);
+static BOOL handle_security(char *pszParmValue,int *val);
+static BOOL handle_case(char *pszParmValue,int *val);
+static BOOL handle_printing(char *pszParmValue,int *val);
static BOOL handle_character_set(char *pszParmValue,char **ptr);
-static BOOL handle_coding_system(char *pszParmValue,char **ptr);
+static BOOL handle_announce_as(char *pszParmValue, int *val);
+#ifdef KANJI
+static BOOL handle_coding_system(char *pszParmValue,int *val);
+#endif /* KANJI */
static void set_default_server_announce_type(void);
-struct enum_list {
- int value;
- char *name;
-};
-
-static struct enum_list enum_protocol[] = {{PROTOCOL_NT1, "NT1"}, {PROTOCOL_LANMAN2, "LANMAN2"},
- {PROTOCOL_LANMAN1, "LANMAN1"}, {PROTOCOL_CORE,"CORE"},
- {PROTOCOL_COREPLUS, "COREPLUS"},
- {PROTOCOL_COREPLUS, "CORE+"}, {-1, NULL}};
-
-static struct enum_list enum_security[] = {{SEC_SHARE, "SHARE"}, {SEC_USER, "USER"},
- {SEC_SERVER, "SERVER"}, {-1, NULL}};
-
-static struct enum_list enum_printing[] = {{PRINT_SYSV, "sysv"}, {PRINT_AIX, "aix"},
- {PRINT_HPUX, "hpux"}, {PRINT_BSD, "bsd"},
- {PRINT_QNX, "qnx"}, {PRINT_PLP, "plp"},
- {PRINT_LPRNG, "lprng"}, {-1, NULL}};
-
-static struct enum_list enum_announce_as[] = {{ANNOUNCE_AS_NT, "NT"}, {ANNOUNCE_AS_WIN95, "win95"},
- {ANNOUNCE_AS_WFW, "WfW"}, {-1, NULL}};
-
-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 parm_struct
+struct parm_struct
{
- char *label;
- parm_type type;
- parm_class class;
- void *ptr;
- BOOL (*special)();
- struct enum_list *enum_list;
+ char *label;
+ parm_type type;
+ parm_class class;
+ void *ptr;
+ BOOL (*special)();
} parm_table[] =
{
- {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL},
- {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL, NULL},
- {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL, NULL},
- {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL, NULL},
- {"protocol", P_ENUM, P_GLOBAL, &Globals.maxprotocol, NULL, enum_protocol},
- {"security", P_ENUM, P_GLOBAL, &Globals.security, NULL, enum_security},
- {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL, NULL},
- {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL, NULL},
- {"announce as", P_ENUM, P_GLOBAL, &Globals.announce_as, NULL, enum_announce_as},
- {"encrypt passwords",P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL, NULL},
- {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL, NULL},
- {"read prediction", P_BOOL, P_GLOBAL, &Globals.bReadPrediction, NULL, NULL},
- {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL, NULL},
- {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL, NULL},
- {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL, NULL},
- {"use rhosts", P_BOOL, P_GLOBAL, &Globals.bUseRhosts, NULL, NULL},
- {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL, NULL},
- {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL, NULL},
- {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL, NULL},
- {"interfaces", P_STRING, P_GLOBAL, &Globals.szInterfaces, NULL, NULL},
- {"bind interfaces only", P_BOOL,P_GLOBAL, &Globals.bBindInterfacesOnly,NULL, NULL},
- {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL},
- {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL, NULL},
- {"netbios name", P_UGSTRING,P_GLOBAL, myname, NULL, NULL},
- {"netbios aliases", P_STRING, P_GLOBAL, &Globals.szNetbiosAliases, NULL, NULL},
- {"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL, NULL},
- {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL, NULL},
- {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL},
- {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL},
- {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL, NULL},
- {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL},
- {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL, NULL},
- {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL, NULL},
- {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL},
- {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL, NULL},
- {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL},
- {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL, NULL},
- {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL},
- {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL},
- {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL},
- {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL},
- {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL, NULL},
- {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL, NULL},
- {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL, NULL},
- {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL, NULL},
- {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL, NULL},
- {"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars, NULL},
- {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkGroup, NULL, NULL},
-#ifdef NTDOMAIN
- {"domain sid", P_USTRING, P_GLOBAL, &Globals.szDomainSID, NULL, NULL},
- {"domain other sids",P_STRING, P_GLOBAL, &Globals.szDomainOtherSIDs, NULL, NULL},
- {"domain groups", P_STRING, P_GLOBAL, &Globals.szDomainGroups, NULL, NULL},
- {"domain controller",P_BOOL , P_GLOBAL, &Globals.bDomainController,NULL, NULL},
- {"domain admin users",P_STRING, P_GLOBAL, &Globals.szDomainAdminUsers, NULL, NULL},
- {"domain guest users",P_STRING, P_GLOBAL, &Globals.szDomainGuestUsers, NULL, NULL},
- {"domain hosts allow",P_STRING, P_GLOBAL, &Globals.szDomainHostsallow, NULL, NULL},
- {"domain allow hosts",P_STRING, P_GLOBAL, &Globals.szDomainHostsallow, NULL, NULL},
- {"domain hosts deny", P_STRING, P_GLOBAL, &Globals.szDomainHostsdeny, NULL, NULL},
- {"domain deny hosts", P_STRING, P_GLOBAL, &Globals.szDomainHostsdeny, NULL, NULL},
-#endif /* NTDOMAIN */
- {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL, NULL},
- {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set, NULL},
- {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL, NULL},
- {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL, NULL},
- {"logon drive", P_STRING, P_GLOBAL, &Globals.szLogonDrive, NULL, NULL},
- {"logon home", P_STRING, P_GLOBAL, &Globals.szLogonHome, NULL, NULL},
- {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL, NULL},
- {"remote browse sync",P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync,NULL, NULL},
- {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL, NULL},
- {"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL, NULL},
- {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL, NULL},
- {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL, NULL},
- {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL, NULL},
- {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL, NULL},
- {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL, NULL},
- {"max packet", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL, NULL},
- {"packet size", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL, NULL},
- {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL, NULL},
- {"username level", P_INTEGER, P_GLOBAL, &Globals.unamelevel, NULL, NULL},
- {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL, NULL},
- {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL, NULL},
- {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL, NULL},
- {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL, NULL},
- {"shared mem size", P_INTEGER, P_GLOBAL, &Globals.shmem_size, NULL, NULL},
- {"coding system", P_STRING, P_GLOBAL, &Globals.szCodingSystem, handle_coding_system, NULL},
- {"client code page", P_INTEGER, P_GLOBAL, &Globals.client_code_page, NULL, NULL},
- {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL, NULL},
- {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL, NULL},
- {"max wins ttl", P_INTEGER, P_GLOBAL, &Globals.max_wins_ttl, NULL, NULL},
- {"min wins ttl", P_INTEGER, P_GLOBAL, &Globals.min_wins_ttl, NULL, NULL},
- {"lm announce", P_ENUM, P_GLOBAL, &Globals.lm_announce, NULL, enum_lm_announce},
- {"lm interval", P_INTEGER, P_GLOBAL, &Globals.lm_interval, NULL, NULL},
- {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bDNSproxy, NULL, NULL},
- {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL, NULL},
- {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL, NULL},
- {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL, NULL},
- {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL, NULL},
- {"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL, NULL},
- {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL, NULL},
- {"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL, NULL},
- {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL, NULL},
- {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL, NULL},
- {"unix realname", P_BOOL, P_GLOBAL, &Globals.bUnixRealname, NULL, NULL},
- {"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL, NULL},
- {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL, NULL},
- {"printer driver file", P_STRING, P_GLOBAL, &Globals.szDriverFile, NULL, NULL},
- {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL, NULL},
- {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL, NULL},
- {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy, NULL},
- {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include, NULL},
- {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL},
- {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL, NULL},
- {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL, NULL},
- {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL, NULL},
- {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL, NULL},
- {"alternate permissions",P_BOOL,P_LOCAL, &sDefault.bAlternatePerm, NULL, NULL},
- {"revalidate", P_BOOL, P_LOCAL, &sDefault.bRevalidate, NULL, NULL},
- {"default case", P_ENUM, P_LOCAL, &sDefault.iDefaultCase, NULL, enum_case},
- {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL},
- {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL, NULL},
- {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL, NULL},
- {"short preserve case",P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve,NULL, NULL},
- {"mangle case", P_BOOL, P_LOCAL, &sDefault.bCaseMangle, NULL, NULL},
- {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL, NULL},
- {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL},
- {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL, NULL},
- {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL},
- {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL},
- {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL, NULL},
- {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL},
- {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL},
- {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL, NULL},
- {"guest account", P_STRING, P_LOCAL, &sDefault.szGuestaccount, NULL, NULL},
- {"invalid users", P_STRING, P_LOCAL, &sDefault.szInvalidUsers, NULL, NULL},
- {"valid users", P_STRING, P_LOCAL, &sDefault.szValidUsers, NULL, NULL},
- {"admin users", P_STRING, P_LOCAL, &sDefault.szAdminUsers, NULL, NULL},
- {"read list", P_STRING, P_LOCAL, &sDefault.readlist, NULL, NULL},
- {"write list", P_STRING, P_LOCAL, &sDefault.writelist, NULL, NULL},
- {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL},
- {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL, NULL},
- {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL},
- {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL, NULL},
- {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL, NULL},
- {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL},
- {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL},
- {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL, NULL},
- {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL, NULL},
- {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL, NULL},
- {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL},
- {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL, NULL},
- {"force create mode",P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL, NULL},
- {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL},
- {"directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL, NULL},
- {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL, NULL},
- {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL, NULL},
- {"status", P_BOOL, P_LOCAL, &sDefault.status, NULL, NULL},
- {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL, NULL},
- {"delete veto files",P_BOOL, P_LOCAL, &sDefault.bDeleteVetoFiles, NULL, NULL},
- {"veto files", P_STRING, P_LOCAL, &sDefault.szVetoFiles, NULL, NULL},
- {"hide files", P_STRING, P_LOCAL, &sDefault.szHideFiles, NULL, NULL},
- {"veto oplock files",P_STRING, P_LOCAL, &sDefault.szVetoOplockFiles,NULL, NULL},
- {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL},
- {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL, NULL},
- {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL},
- {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL, NULL},
- {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL},
- {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL, NULL},
- {"postscript", P_BOOL, P_LOCAL, &sDefault.bPostscript, NULL, NULL},
- {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL, NULL},
- {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL, NULL},
- {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL, NULL},
- {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL, NULL},
- {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL, NULL},
- {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL, NULL},
- {"oplocks", P_BOOL, P_LOCAL, &sDefault.bOpLocks, NULL, NULL},
- {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL, NULL},
- {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL, NULL},
- {"follow symlinks", P_BOOL, P_LOCAL, &sDefault.bSymlinks, NULL, NULL},
- {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL, NULL},
- {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL, NULL},
- {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL, NULL},
- {"printing", P_ENUM, P_LOCAL, &sDefault.iPrinting, NULL, enum_printing},
- {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL, NULL},
- {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL, NULL},
- {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL, NULL},
- {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL, NULL},
- {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand,NULL, NULL},
- {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL},
- {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL, NULL},
- {"printer driver", P_STRING, P_LOCAL, &sDefault.szPrinterDriver, NULL, NULL},
- {"printer driver location", P_STRING, P_LOCAL, &sDefault.szPrinterDriverLocation, NULL, NULL},
- {"hosts allow", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL, NULL},
- {"allow hosts", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL, NULL},
- {"hosts deny", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL},
- {"deny hosts", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL, NULL},
- {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL, NULL},
- {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL, NULL},
- {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL, NULL},
- {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL, NULL},
- {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL, NULL},
- {"dos filetimes", P_BOOL, P_LOCAL, &sDefault.bDosFiletimes, NULL, NULL},
-
- {NULL, P_BOOL, P_NONE, NULL, NULL, NULL}
+ {"debuglevel", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
+ {"log level", P_INTEGER, P_GLOBAL, &DEBUGLEVEL, NULL},
+ {"syslog", P_INTEGER, P_GLOBAL, &Globals.syslog, NULL},
+ {"syslog only", P_BOOL, P_GLOBAL, &Globals.bSyslogOnly, NULL},
+ {"protocol", P_INTEGER, P_GLOBAL, &Globals.maxprotocol,handle_protocol},
+ {"security", P_INTEGER, P_GLOBAL, &Globals.security,handle_security},
+ {"printing", P_INTEGER, P_GLOBAL, &Globals.printing,handle_printing},
+ {"max disk size", P_INTEGER, P_GLOBAL, &Globals.maxdisksize, NULL},
+ {"lpq cache time", P_INTEGER, P_GLOBAL, &Globals.lpqcachetime, NULL},
+ {"announce as", P_INTEGER, P_GLOBAL, &Globals.announce_as, handle_announce_as},
+ {"encrypt passwords",P_BOOL, P_GLOBAL, &Globals.bEncryptPasswords, NULL},
+ {"getwd cache", P_BOOL, P_GLOBAL, &use_getwd_cache, NULL},
+ {"read prediction", P_BOOL, P_GLOBAL, &Globals.bReadPrediction, NULL},
+ {"read bmpx", P_BOOL, P_GLOBAL, &Globals.bReadbmpx, NULL},
+ {"read raw", P_BOOL, P_GLOBAL, &Globals.bReadRaw, NULL},
+ {"write raw", P_BOOL, P_GLOBAL, &Globals.bWriteRaw, NULL},
+ {"use rhosts", P_BOOL, P_GLOBAL, &Globals.bUseRhosts, NULL},
+ {"load printers", P_BOOL, P_GLOBAL, &Globals.bLoadPrinters, NULL},
+ {"null passwords", P_BOOL, P_GLOBAL, &Globals.bNullPasswords, NULL},
+ {"strip dot", P_BOOL, P_GLOBAL, &Globals.bStripDot, NULL},
+ {"interfaces", P_STRING, P_GLOBAL, &Globals.szInterfaces, NULL},
+ {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL},
+ {"socket options", P_GSTRING, P_GLOBAL, user_socket_options, NULL},
+ {"netbios name", P_UGSTRING,P_GLOBAL, myname, NULL},
+ {"netbios aliases", P_STRING, P_GLOBAL, &Globals.szNetbiosAliases, NULL},
+ {"smbrun", P_STRING, P_GLOBAL, &Globals.szSmbrun, NULL},
+ {"log file", P_STRING, P_GLOBAL, &Globals.szLogFile, NULL},
+ {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL},
+ {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL},
+ {"hosts equiv", P_STRING, P_GLOBAL, &Globals.szHostsEquiv, NULL},
+ {"preload", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
+ {"auto services", P_STRING, P_GLOBAL, &Globals.szAutoServices, NULL},
+ {"server string", P_STRING, P_GLOBAL, &Globals.szServerString, NULL},
+ {"printcap name", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
+ {"printcap", P_STRING, P_GLOBAL, &Globals.szPrintcapname, NULL},
+ {"lock dir", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
+ {"lock directory", P_STRING, P_GLOBAL, &Globals.szLockDir, NULL},
+ {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
+ {"root dir", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
+ {"root", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL},
+ {"default service", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
+ {"default", P_STRING, P_GLOBAL, &Globals.szDefaultService, NULL},
+ {"message command", P_STRING, P_GLOBAL, &Globals.szMsgCommand, NULL},
+ {"dfree command", P_STRING, P_GLOBAL, &Globals.szDfree, NULL},
+ {"passwd program", P_STRING, P_GLOBAL, &Globals.szPasswdProgram, NULL},
+ {"passwd chat", P_STRING, P_GLOBAL, &Globals.szPasswdChat, NULL},
+ {"valid chars", P_STRING, P_GLOBAL, &Globals.szValidChars, handle_valid_chars},
+ {"workgroup", P_USTRING, P_GLOBAL, &Globals.szWorkGroup, NULL},
+ {"domain controller",P_STRING, P_GLOBAL, &Globals.szDomainController,NULL},
+ {"username map", P_STRING, P_GLOBAL, &Globals.szUsernameMap, NULL},
+ {"character set", P_STRING, P_GLOBAL, &Globals.szCharacterSet, handle_character_set},
+ {"logon script", P_STRING, P_GLOBAL, &Globals.szLogonScript, NULL},
+ {"logon path", P_STRING, P_GLOBAL, &Globals.szLogonPath, NULL},
+ {"remote announce", P_STRING, P_GLOBAL, &Globals.szRemoteAnnounce, NULL},
+ {"remote browse sync", P_STRING, P_GLOBAL, &Globals.szRemoteBrowseSync, NULL},
+ {"socket address", P_STRING, P_GLOBAL, &Globals.szSocketAddress, NULL},
+ {"homedir map", P_STRING, P_GLOBAL, &Globals.szNISHomeMapName, NULL},
+ {"announce version", P_STRING, P_GLOBAL, &Globals.szAnnounceVersion, NULL},
+ {"max log size", P_INTEGER, P_GLOBAL, &Globals.max_log_size, NULL},
+ {"mangled stack", P_INTEGER, P_GLOBAL, &Globals.mangled_stack, NULL},
+ {"max mux", P_INTEGER, P_GLOBAL, &Globals.max_mux, NULL},
+ {"max xmit", P_INTEGER, P_GLOBAL, &Globals.max_xmit, NULL},
+ {"max packet", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL},
+ {"packet size", P_INTEGER, P_GLOBAL, &Globals.max_packet, NULL},
+ {"password level", P_INTEGER, P_GLOBAL, &Globals.pwordlevel, NULL},
+ {"keepalive", P_INTEGER, P_GLOBAL, &keepalive, NULL},
+ {"deadtime", P_INTEGER, P_GLOBAL, &Globals.deadtime, NULL},
+ {"time offset", P_INTEGER, P_GLOBAL, &extra_time_offset, NULL},
+ {"read size", P_INTEGER, P_GLOBAL, &Globals.ReadSize, NULL},
+ {"shared mem size", P_INTEGER, P_GLOBAL, &Globals.shmem_size, NULL},
+ {"shared file entries", P_INTEGER, P_GLOBAL, &Globals.shmem_hash_size, NULL},
+#ifdef KANJI
+ {"coding system", P_INTEGER, P_GLOBAL, &coding_system, handle_coding_system},
+#endif /* KANJI */
+ {"client code page", P_INTEGER, P_GLOBAL, &Globals.client_code_page, NULL},
+ {"os level", P_INTEGER, P_GLOBAL, &Globals.os_level, NULL},
+ {"max ttl", P_INTEGER, P_GLOBAL, &Globals.max_ttl, NULL},
+ {"dns proxy", P_BOOL, P_GLOBAL, &Globals.bDNSproxy, NULL},
+ {"wins support", P_BOOL, P_GLOBAL, &Globals.bWINSsupport, NULL},
+ {"wins proxy", P_BOOL, P_GLOBAL, &Globals.bWINSproxy, NULL},
+ {"wins server", P_STRING, P_GLOBAL, &Globals.szWINSserver, NULL},
+ {"preferred master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
+ {"prefered master", P_BOOL, P_GLOBAL, &Globals.bPreferredMaster, NULL},
+ {"local master", P_BOOL, P_GLOBAL, &Globals.bLocalMaster, NULL},
+ {"domain master", P_BOOL, P_GLOBAL, &Globals.bDomainMaster, NULL},
+ {"domain logons", P_BOOL, P_GLOBAL, &Globals.bDomainLogons, NULL},
+ {"browse list", P_BOOL, P_GLOBAL, &Globals.bBrowseList, NULL},
+ {"unix realname", P_BOOL, P_GLOBAL, &Globals.bUnixRealname, NULL},
+ {"NIS homedir", P_BOOL, P_GLOBAL, &Globals.bNISHomeMap, NULL},
+ {"time server", P_BOOL, P_GLOBAL, &Globals.bTimeServer, NULL},
+ {"-valid", P_BOOL, P_LOCAL, &sDefault.valid, NULL},
+ {"comment", P_STRING, P_LOCAL, &sDefault.comment, NULL},
+ {"copy", P_STRING, P_LOCAL, &sDefault.szCopy, handle_copy},
+ {"include", P_STRING, P_LOCAL, &sDefault.szInclude, handle_include},
+ {"exec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL},
+ {"preexec", P_STRING, P_LOCAL, &sDefault.szPreExec, NULL},
+ {"postexec", P_STRING, P_LOCAL, &sDefault.szPostExec, NULL},
+ {"root preexec", P_STRING, P_LOCAL, &sDefault.szRootPreExec, NULL},
+ {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL},
+ {"alternate permissions",P_BOOL,P_LOCAL, &sDefault.bAlternatePerm, NULL},
+ {"revalidate", P_BOOL, P_LOCAL, &sDefault.bRevalidate, NULL},
+ {"default case", P_INTEGER, P_LOCAL, &sDefault.iDefaultCase, handle_case},
+ {"case sensitive", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL},
+ {"casesignames", P_BOOL, P_LOCAL, &sDefault.bCaseSensitive, NULL},
+ {"preserve case", P_BOOL, P_LOCAL, &sDefault.bCasePreserve, NULL},
+ {"short preserve case",P_BOOL, P_LOCAL, &sDefault.bShortCasePreserve,NULL},
+ {"mangle case", P_BOOL, P_LOCAL, &sDefault.bCaseMangle, NULL},
+ {"mangling char", P_CHAR, P_LOCAL, &sDefault.magic_char, NULL},
+ {"browseable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL},
+ {"browsable", P_BOOL, P_LOCAL, &sDefault.bBrowseable, NULL},
+ {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL},
+ {"path", P_STRING, P_LOCAL, &sDefault.szPath, NULL},
+ {"directory", P_STRING, P_LOCAL, &sDefault.szPath, NULL},
+ {"username", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
+ {"user", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
+ {"users", P_STRING, P_LOCAL, &sDefault.szUsername, NULL},
+ {"guest account", P_STRING, P_LOCAL, &sDefault.szGuestaccount, NULL},
+ {"invalid users", P_STRING, P_LOCAL, &sDefault.szInvalidUsers, NULL},
+ {"valid users", P_STRING, P_LOCAL, &sDefault.szValidUsers, NULL},
+ {"admin users", P_STRING, P_LOCAL, &sDefault.szAdminUsers, NULL},
+ {"read list", P_STRING, P_LOCAL, &sDefault.readlist, NULL},
+ {"write list", P_STRING, P_LOCAL, &sDefault.writelist, NULL},
+ {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL},
+ {"force user", P_STRING, P_LOCAL, &sDefault.force_user, NULL},
+ {"force group", P_STRING, P_LOCAL, &sDefault.force_group, NULL},
+ {"group", P_STRING, P_LOCAL, &sDefault.force_group, NULL},
+ {"read only", P_BOOL, P_LOCAL, &sDefault.bRead_only, NULL},
+ {"write ok", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
+ {"writeable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
+ {"writable", P_BOOLREV, P_LOCAL, &sDefault.bRead_only, NULL},
+ {"max connections", P_INTEGER, P_LOCAL, &sDefault.iMaxConnections, NULL},
+ {"min print space", P_INTEGER, P_LOCAL, &sDefault.iMinPrintSpace, NULL},
+ {"create mask", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL},
+ {"create mode", P_OCTAL, P_LOCAL, &sDefault.iCreate_mask, NULL},
+ {"force create mode",P_OCTAL, P_LOCAL, &sDefault.iCreate_force_mode, NULL},
+ {"directory mask", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL},
+ {"directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_mask, NULL},
+ {"force directory mode", P_OCTAL, P_LOCAL, &sDefault.iDir_force_mode, NULL},
+ {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL},
+ {"status", P_BOOL, P_LOCAL, &sDefault.status, NULL},
+ {"hide dot files", P_BOOL, P_LOCAL, &sDefault.bHideDotFiles, NULL},
+ {"veto files", P_STRING, P_LOCAL, &sDefault.szVetoFiles, NULL},
+ {"hide files", P_STRING, P_LOCAL, &sDefault.szHideFiles, NULL},
+ {"guest only", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL},
+ {"only guest", P_BOOL, P_LOCAL, &sDefault.bGuest_only, NULL},
+ {"guest ok", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL},
+ {"public", P_BOOL, P_LOCAL, &sDefault.bGuest_ok, NULL},
+ {"print ok", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL},
+ {"printable", P_BOOL, P_LOCAL, &sDefault.bPrint_ok, NULL},
+ {"postscript", P_BOOL, P_LOCAL, &sDefault.bPostscript, NULL},
+ {"map system", P_BOOL, P_LOCAL, &sDefault.bMap_system, NULL},
+ {"map hidden", P_BOOL, P_LOCAL, &sDefault.bMap_hidden, NULL},
+ {"map archive", P_BOOL, P_LOCAL, &sDefault.bMap_archive, NULL},
+ {"locking", P_BOOL, P_LOCAL, &sDefault.bLocking, NULL},
+ {"strict locking", P_BOOL, P_LOCAL, &sDefault.bStrictLocking, NULL},
+ {"share modes", P_BOOL, P_LOCAL, &sDefault.bShareModes, NULL},
+ {"only user", P_BOOL, P_LOCAL, &sDefault.bOnlyUser, NULL},
+ {"wide links", P_BOOL, P_LOCAL, &sDefault.bWidelinks, NULL},
+ {"follow symlinks", P_BOOL, P_LOCAL, &sDefault.bSymlinks, NULL},
+ {"sync always", P_BOOL, P_LOCAL, &sDefault.bSyncAlways, NULL},
+ {"mangled names", P_BOOL, P_LOCAL, &sDefault.bMangledNames, NULL},
+ {"fake oplocks", P_BOOL, P_LOCAL, &sDefault.bFakeOplocks, NULL},
+ {"print command", P_STRING, P_LOCAL, &sDefault.szPrintcommand, NULL},
+ {"lpq command", P_STRING, P_LOCAL, &sDefault.szLpqcommand, NULL},
+ {"lprm command", P_STRING, P_LOCAL, &sDefault.szLprmcommand, NULL},
+ {"lppause command", P_STRING, P_LOCAL, &sDefault.szLppausecommand, NULL},
+ {"lpresume command", P_STRING, P_LOCAL, &sDefault.szLpresumecommand,NULL},
+ {"printer", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL},
+ {"printer name", P_STRING, P_LOCAL, &sDefault.szPrintername, NULL},
+ {"printer driver", P_STRING, P_LOCAL, &sDefault.szPrinterDriver, NULL},
+ {"hosts allow", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL},
+ {"allow hosts", P_STRING, P_LOCAL, &sDefault.szHostsallow, NULL},
+ {"hosts deny", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL},
+ {"deny hosts", P_STRING, P_LOCAL, &sDefault.szHostsdeny, NULL},
+ {"dont descend", P_STRING, P_LOCAL, &sDefault.szDontdescend, NULL},
+ {"magic script", P_STRING, P_LOCAL, &sDefault.szMagicScript, NULL},
+ {"magic output", P_STRING, P_LOCAL, &sDefault.szMagicOutput, NULL},
+ {"mangled map", P_STRING, P_LOCAL, &sDefault.szMangledMap, NULL},
+ {"delete readonly", P_BOOL, P_LOCAL, &sDefault.bDeleteReadonly, NULL},
+ {"dos filetimes", P_BOOL, P_LOCAL, &sDefault.bDosFiletimes, NULL},
+
+ {NULL, P_BOOL, P_NONE, NULL, NULL}
};
@@ -663,9 +604,12 @@ static void init_globals(void)
#endif
string_set(&Globals.szPasswdChat,"*old*password* %o\\n *new*password* %n\\n *new*password* %n\\n *changed*");
string_set(&Globals.szWorkGroup, WORKGROUP);
+#ifdef SMB_PASSWD
string_set(&Globals.szPasswdProgram, SMB_PASSWD);
+#else
+ string_set(&Globals.szPasswdProgram, "/bin/passwd");
+#endif
string_set(&Globals.szPrintcapname, PRINTCAP_NAME);
- string_set(&Globals.szDriverFile, DRIVERFILE);
string_set(&Globals.szLockDir, LOCKDIR);
string_set(&Globals.szRootdir, "/");
string_set(&Globals.szSmbrun, SMBRUN);
@@ -674,12 +618,6 @@ static void init_globals(void)
string_set(&Globals.szServerString,s);
sprintf(s,"%d.%d", DEFAULT_MAJOR_VERSION, DEFAULT_MINOR_VERSION);
string_set(&Globals.szAnnounceVersion,s);
-
- string_set(&Globals.szLogonDrive, "");
- /* %N is the NIS auto.home server if -DAUTOHOME is used, else same as %L */
- string_set(&Globals.szLogonHome, "\\\\%N\\%U");
- string_set(&Globals.szLogonPath, "\\\\%N\\%U\\profile");
-
Globals.bLoadPrinters = True;
Globals.bUseRhosts = False;
Globals.max_packet = 65535;
@@ -688,12 +626,12 @@ static void init_globals(void)
Globals.max_mux = 50; /* This is *needed* for profile support. */
Globals.lpqcachetime = 10;
Globals.pwordlevel = 0;
- Globals.unamelevel = 0;
Globals.deadtime = 0;
Globals.max_log_size = 5000;
Globals.maxprotocol = PROTOCOL_NT1;
Globals.security = SEC_SHARE;
Globals.bEncryptPasswords = False;
+ Globals.printing = DEFAULT_PRINTING;
Globals.bReadRaw = True;
Globals.bWriteRaw = True;
Globals.bReadPrediction = False;
@@ -703,23 +641,21 @@ static void init_globals(void)
Globals.syslog = 1;
Globals.bSyslogOnly = False;
Globals.os_level = 0;
- Globals.max_ttl = 60*60*4; /* 4 hours default */
- Globals.max_wins_ttl = 60*60*24*3; /* 3 days default */
- Globals.min_wins_ttl = 60*60*6; /* 6 hours default */
+ Globals.max_ttl = 60*60*4; /* 2 hours default */
Globals.ReadSize = 16*1024;
- Globals.lm_announce = 2; /* = Auto: send only if LM clients found */
- Globals.lm_interval = 60;
Globals.shmem_size = SHMEM_SIZE;
+ Globals.shmem_hash_size = SHMEM_HASH_SIZE;
Globals.announce_as = ANNOUNCE_AS_NT;
Globals.bUnixRealname = False;
#if (defined(NETGROUP) && defined(AUTOMOUNT))
Globals.bNISHomeMap = False;
string_set(&Globals.szNISHomeMapName, "auto.home");
#endif
- interpret_coding_system(KANJI);
+#ifdef KANJI
+ coding_system = interpret_coding_system (KANJI, SJIS_CODE);
+#endif /* KANJI */
Globals.client_code_page = DEFAULT_CLIENT_CODE_PAGE;
Globals.bTimeServer = False;
- Globals.bBindInterfacesOnly = False;
/* these parameters are set to defaults that are more appropriate
for the increasing samba install base:
@@ -741,6 +677,17 @@ static void init_globals(void)
Globals.bWINSsupport = False;
Globals.bWINSproxy = False;
+/* this parameter is currently set to the default functionality
+ in samba. given that w95 and NT is starting to use DNS for
+ server resolution, i expect that at some point it would be
+ sensible to default this to False.
+
+ this parameter is added because nmbd is a single process, and
+ gethostbyname is a blocking call, which can take out nmbd for
+ several seconds while a dns lookup is performed.
+
+ */
+
Globals.bDNSproxy = True;
}
@@ -760,7 +707,7 @@ Initialise the sDefault parameter structure.
static void init_locals(void)
{
/* choose defaults depending on the type of printing */
- switch (sDefault.iPrinting)
+ switch (Globals.printing)
{
case PRINT_BSD:
case PRINT_AIX:
@@ -884,12 +831,11 @@ FN_GLOBAL_STRING(lp_passwd_program,&Globals.szPasswdProgram)
FN_GLOBAL_STRING(lp_passwd_chat,&Globals.szPasswdChat)
FN_GLOBAL_STRING(lp_passwordserver,&Globals.szPasswordServer)
FN_GLOBAL_STRING(lp_workgroup,&Globals.szWorkGroup)
+FN_GLOBAL_STRING(lp_domain_controller,&Globals.szDomainController)
FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet)
FN_GLOBAL_STRING(lp_logon_script,&Globals.szLogonScript)
FN_GLOBAL_STRING(lp_logon_path,&Globals.szLogonPath)
-FN_GLOBAL_STRING(lp_logon_drive,&Globals.szLogonDrive)
-FN_GLOBAL_STRING(lp_logon_home,&Globals.szLogonHome)
FN_GLOBAL_STRING(lp_remote_announce,&Globals.szRemoteAnnounce)
FN_GLOBAL_STRING(lp_remote_browse_sync,&Globals.szRemoteBrowseSync)
FN_GLOBAL_STRING(lp_wins_server,&Globals.szWINSserver)
@@ -898,24 +844,11 @@ FN_GLOBAL_STRING(lp_socket_address,&Globals.szSocketAddress)
FN_GLOBAL_STRING(lp_nis_home_map_name,&Globals.szNISHomeMapName)
FN_GLOBAL_STRING(lp_announce_version,&Globals.szAnnounceVersion)
FN_GLOBAL_STRING(lp_netbios_aliases,&Globals.szNetbiosAliases)
-FN_GLOBAL_STRING(lp_driverfile,&Globals.szDriverFile)
-
-#ifdef NTDOMAIN
-FN_GLOBAL_STRING(lp_domain_sid,&Globals.szDomainSID)
-FN_GLOBAL_STRING(lp_domain_other_sids,&Globals.szDomainOtherSIDs)
-FN_GLOBAL_STRING(lp_domain_groups,&Globals.szDomainGroups)
-FN_GLOBAL_STRING(lp_domain_admin_users,&Globals.szDomainAdminUsers)
-FN_GLOBAL_STRING(lp_domain_guest_users,&Globals.szDomainGuestUsers)
-FN_GLOBAL_STRING(lp_domain_hostsallow,&Globals.szDomainHostsallow)
-FN_GLOBAL_STRING(lp_domain_hostsdeny,&Globals.szDomainHostsdeny)
-#endif /* NTDOMAIN */
FN_GLOBAL_BOOL(lp_dns_proxy,&Globals.bDNSproxy)
FN_GLOBAL_BOOL(lp_wins_support,&Globals.bWINSsupport)
-FN_GLOBAL_BOOL(lp_we_are_a_wins_server,&Globals.bWINSsupport)
FN_GLOBAL_BOOL(lp_wins_proxy,&Globals.bWINSproxy)
FN_GLOBAL_BOOL(lp_local_master,&Globals.bLocalMaster)
-FN_GLOBAL_BOOL(lp_domain_controller,&Globals.bDomainController)
FN_GLOBAL_BOOL(lp_domain_master,&Globals.bDomainMaster)
FN_GLOBAL_BOOL(lp_domain_logons,&Globals.bDomainLogons)
FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
@@ -934,12 +867,9 @@ FN_GLOBAL_BOOL(lp_browse_list,&Globals.bBrowseList)
FN_GLOBAL_BOOL(lp_unix_realname,&Globals.bUnixRealname)
FN_GLOBAL_BOOL(lp_nis_home_map,&Globals.bNISHomeMap)
FN_GLOBAL_BOOL(lp_time_server,&Globals.bTimeServer)
-FN_GLOBAL_BOOL(lp_bind_interfaces_only,&Globals.bBindInterfacesOnly)
FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
FN_GLOBAL_INTEGER(lp_max_ttl,&Globals.max_ttl)
-FN_GLOBAL_INTEGER(lp_max_wins_ttl,&Globals.max_wins_ttl)
-FN_GLOBAL_INTEGER(lp_min_wins_ttl,&Globals.max_wins_ttl)
FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
FN_GLOBAL_INTEGER(lp_mangledstack,&Globals.mangled_stack)
FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
@@ -947,19 +877,18 @@ FN_GLOBAL_INTEGER(lp_maxmux,&Globals.max_mux)
FN_GLOBAL_INTEGER(lp_maxpacket,&Globals.max_packet)
FN_GLOBAL_INTEGER(lp_keepalive,&keepalive)
FN_GLOBAL_INTEGER(lp_passwordlevel,&Globals.pwordlevel)
-FN_GLOBAL_INTEGER(lp_usernamelevel,&Globals.unamelevel)
FN_GLOBAL_INTEGER(lp_readsize,&Globals.ReadSize)
FN_GLOBAL_INTEGER(lp_shmem_size,&Globals.shmem_size)
+FN_GLOBAL_INTEGER(lp_shmem_hash_size,&Globals.shmem_hash_size)
FN_GLOBAL_INTEGER(lp_deadtime,&Globals.deadtime)
FN_GLOBAL_INTEGER(lp_maxprotocol,&Globals.maxprotocol)
FN_GLOBAL_INTEGER(lp_security,&Globals.security)
+FN_GLOBAL_INTEGER(lp_printing,&Globals.printing)
FN_GLOBAL_INTEGER(lp_maxdisksize,&Globals.maxdisksize)
FN_GLOBAL_INTEGER(lp_lpqcachetime,&Globals.lpqcachetime)
FN_GLOBAL_INTEGER(lp_syslog,&Globals.syslog)
FN_GLOBAL_INTEGER(lp_client_code_page,&Globals.client_code_page)
FN_GLOBAL_INTEGER(lp_announce_as,&Globals.announce_as)
-FN_GLOBAL_INTEGER(lp_lm_announce,&Globals.lm_announce)
-FN_GLOBAL_INTEGER(lp_lm_interval,&Globals.lm_interval)
FN_LOCAL_STRING(lp_preexec,szPreExec)
FN_LOCAL_STRING(lp_postexec,szPostExec)
@@ -993,8 +922,6 @@ FN_LOCAL_STRING(lp_volume,volume)
FN_LOCAL_STRING(lp_mangled_map,szMangledMap)
FN_LOCAL_STRING(lp_veto_files,szVetoFiles)
FN_LOCAL_STRING(lp_hide_files,szHideFiles)
-FN_LOCAL_STRING(lp_veto_oplocks,szVetoFiles)
-FN_LOCAL_STRING(lp_driverlocation,szPrinterDriverLocation)
FN_LOCAL_BOOL(lp_alternate_permissions,bAlternatePerm)
FN_LOCAL_BOOL(lp_revalidate,bRevalidate)
@@ -1016,7 +943,6 @@ FN_LOCAL_BOOL(lp_map_archive,bMap_archive)
FN_LOCAL_BOOL(lp_locking,bLocking)
FN_LOCAL_BOOL(lp_strict_locking,bStrictLocking)
FN_LOCAL_BOOL(lp_share_modes,bShareModes)
-FN_LOCAL_BOOL(lp_oplocks,bOpLocks)
FN_LOCAL_BOOL(lp_onlyuser,bOnlyUser)
FN_LOCAL_BOOL(lp_manglednames,bMangledNames)
FN_LOCAL_BOOL(lp_widelinks,bWidelinks)
@@ -1025,7 +951,6 @@ FN_LOCAL_BOOL(lp_syncalways,bSyncAlways)
FN_LOCAL_BOOL(lp_map_system,bMap_system)
FN_LOCAL_BOOL(lp_delete_readonly,bDeleteReadonly)
FN_LOCAL_BOOL(lp_fake_oplocks,bFakeOplocks)
-FN_LOCAL_BOOL(lp_recursive_veto_delete,bDeleteVetoFiles)
FN_LOCAL_BOOL(lp_dos_filetimes,bDosFiletimes)
FN_LOCAL_INTEGER(lp_create_mode,iCreate_mask)
@@ -1035,7 +960,6 @@ FN_LOCAL_INTEGER(lp_force_dir_mode,iDir_force_mode)
FN_LOCAL_INTEGER(lp_max_connections,iMaxConnections)
FN_LOCAL_INTEGER(lp_defaultcase,iDefaultCase)
FN_LOCAL_INTEGER(lp_minprintspace,iMinPrintSpace)
-FN_LOCAL_INTEGER(lp_printing,iPrinting)
FN_LOCAL_CHAR(lp_magicchar,magic_char)
@@ -1052,6 +976,8 @@ static void copy_service( service *pserviceDest,
static BOOL service_ok(int iService);
static BOOL do_parameter(char *pszParmName, char *pszParmValue);
static BOOL do_section(char *pszSectionName);
+static void dump_globals(void);
+static void dump_a_service(service *pService);
static void init_copymap(service *pservice);
@@ -1222,8 +1148,6 @@ BOOL lp_add_printer(char *pszPrintername, int iDefaultService)
iSERVICE(i).bRead_only = False;
/* No share modes on printer services. */
iSERVICE(i).bShareModes = False;
- /* No oplocks on printer services. */
- iSERVICE(i).bOpLocks = False;
/* Printer services must be printable. */
iSERVICE(i).bPrint_ok = True;
@@ -1363,7 +1287,6 @@ static void copy_service(service *pserviceDest,
break;
case P_INTEGER:
- case P_ENUM:
case P_OCTAL:
*(int *)dest_ptr = *(int *)src_ptr;
break;
@@ -1506,26 +1429,93 @@ BOOL lp_file_list_changed(void)
return(False);
}
+#ifdef KANJI
/***************************************************************************
handle the interpretation of the coding system parameter
*************************************************************************/
-static BOOL handle_coding_system(char *pszParmValue,char **ptr)
+static BOOL handle_coding_system(char *pszParmValue,int *val)
{
- string_set(ptr,pszParmValue);
- interpret_coding_system(pszParmValue);
- return(True);
+ *val = interpret_coding_system(pszParmValue,*val);
+ return(True);
}
+#endif /* KANJI */
/***************************************************************************
handle the interpretation of the character set system parameter
***************************************************************************/
static BOOL handle_character_set(char *pszParmValue,char **ptr)
{
- string_set(ptr,pszParmValue);
- interpret_character_set(pszParmValue);
- return(True);
+ string_set(ptr,pszParmValue);
+ interpret_character_set(pszParmValue);
+ return(True);
+}
+
+
+/***************************************************************************
+handle the interpretation of the protocol parameter
+***************************************************************************/
+static BOOL handle_protocol(char *pszParmValue,int *val)
+{
+ *val = interpret_protocol(pszParmValue,*val);
+ return(True);
+}
+
+/***************************************************************************
+handle the interpretation of the security parameter
+***************************************************************************/
+static BOOL handle_security(char *pszParmValue,int *val)
+{
+ *val = interpret_security(pszParmValue,*val);
+ return(True);
+}
+
+/***************************************************************************
+handle the interpretation of the default case
+***************************************************************************/
+static BOOL handle_case(char *pszParmValue,int *val)
+{
+ if (strnequal(pszParmValue,"LOWER", 5))
+ *val = CASE_LOWER;
+ else if (strnequal(pszParmValue,"UPPER", 5))
+ *val = CASE_UPPER;
+ return(True);
}
+/***************************************************************************
+handle the interpretation of the printing system
+***************************************************************************/
+static BOOL handle_printing(char *pszParmValue,int *val)
+{
+ if (strnequal(pszParmValue,"sysv", 4))
+ *val = PRINT_SYSV;
+ else if (strnequal(pszParmValue,"aix", 3))
+ *val = PRINT_AIX;
+ else if (strnequal(pszParmValue,"hpux", 4))
+ *val = PRINT_HPUX;
+ else if (strnequal(pszParmValue,"bsd", 3))
+ *val = PRINT_BSD;
+ else if (strnequal(pszParmValue,"qnx",3))
+ *val = PRINT_QNX;
+ else if (strnequal(pszParmValue,"plp", 3))
+ *val = PRINT_PLP;
+ else if (strnequal(pszParmValue,"lprng", 5))
+ *val = PRINT_LPRNG;
+ return(True);
+}
+
+/***************************************************************************
+handle the announce as parameter
+***************************************************************************/
+static BOOL handle_announce_as(char *pszParmValue,int *val)
+{
+ if (strnequal(pszParmValue,"NT", 2))
+ *val = ANNOUNCE_AS_NT;
+ else if (strnequal(pszParmValue,"win95", 5))
+ *val = ANNOUNCE_AS_WIN95;
+ else if (strnequal(pszParmValue,"WfW", 3))
+ *val = ANNOUNCE_AS_WFW;
+ return True;
+}
/***************************************************************************
handle the valid chars lines
@@ -1629,15 +1619,18 @@ static void init_copymap(service *pservice)
/***************************************************************************
-Process a parameter for a particular service number. If snum < 0
-then assume we are in the globals
+Process a parameter.
***************************************************************************/
-BOOL lp_do_parameter(int snum, char *pszParmName, char *pszParmValue)
+static BOOL do_parameter(char *pszParmName, char *pszParmValue)
{
- int parmnum, i;
+ int parmnum;
void *parm_ptr=NULL; /* where we are going to store the result */
void *def_ptr=NULL;
+ if (!bInGlobalSection && bGlobalOnly) return(True);
+
+ DEBUG(3,("doing parameter %s = %s\n",pszParmName,pszParmValue));
+
parmnum = map_parameter(pszParmName);
if (parmnum < 0)
@@ -1649,32 +1642,37 @@ BOOL lp_do_parameter(int snum, char *pszParmName, char *pszParmValue)
def_ptr = parm_table[parmnum].ptr;
/* we might point at a service, the default service or a global */
- if (snum < 0) {
+ if (bInGlobalSection)
parm_ptr = def_ptr;
- } else {
- if (parm_table[parmnum].class == P_GLOBAL) {
+ else
+ {
+ if (parm_table[parmnum].class == P_GLOBAL)
+ {
DEBUG(0,( "Global parameter %s found in service section!\n",pszParmName));
return(True);
}
- parm_ptr = ((char *)pSERVICE(snum)) + PTR_DIFF(def_ptr,&sDefault);
- }
+ parm_ptr = ((char *)pSERVICE(iServiceIndex)) + PTR_DIFF(def_ptr,&sDefault);
+ }
- if (snum >= 0) {
- if (!iSERVICE(snum).copymap)
- init_copymap(pSERVICE(snum));
-
- /* this handles the aliases - set the copymap for other entries with
- the same data pointer */
- for (i=0;parm_table[i].label;i++)
- if (parm_table[i].ptr == parm_table[parmnum].ptr)
- iSERVICE(snum).copymap[i] = False;
- }
+ if (!bInGlobalSection)
+ {
+ int i;
+ if (!iSERVICE(iServiceIndex).copymap)
+ init_copymap(pSERVICE(iServiceIndex));
+
+ /* this handles the aliases - set the copymap for other entries with
+ the same data pointer */
+ for (i=0;parm_table[i].label;i++)
+ if (parm_table[i].ptr == parm_table[parmnum].ptr)
+ iSERVICE(iServiceIndex).copymap[i] = False;
+ }
/* if it is a special case then go ahead */
- if (parm_table[parmnum].special) {
- parm_table[parmnum].special(pszParmValue,parm_ptr);
- return(True);
- }
+ if (parm_table[parmnum].special)
+ {
+ parm_table[parmnum].special(pszParmValue,parm_ptr);
+ return(True);
+ }
/* now switch on the type of variable it is */
switch (parm_table[parmnum].type)
@@ -1717,134 +1715,50 @@ BOOL lp_do_parameter(int snum, char *pszParmName, char *pszParmValue)
strcpy((char *)parm_ptr,pszParmValue);
strupper((char *)parm_ptr);
break;
-
- case P_ENUM:
- for (i=0;parm_table[parmnum].enum_list[i].name;i++) {
- if (strequal(pszParmValue, parm_table[parmnum].enum_list[i].name)) {
- *(int *)parm_ptr = parm_table[parmnum].enum_list[i].value;
- break;
- }
- }
- break;
}
return(True);
}
/***************************************************************************
-Process a parameter.
-***************************************************************************/
-static BOOL do_parameter(char *pszParmName, char *pszParmValue)
-{
- if (!bInGlobalSection && bGlobalOnly) return(True);
-
- DEBUG(3,("doing parameter %s = %s\n",pszParmName,pszParmValue));
-
- return lp_do_parameter(bInGlobalSection?-2:iServiceIndex, pszParmName, pszParmValue);
-}
-
-
-/***************************************************************************
print a parameter of the specified type
***************************************************************************/
-static void print_parameter(struct parm_struct *p,void *ptr, FILE *f)
+static void print_parameter(parm_type type,void *ptr)
{
- int i;
- switch (p->type) {
- case P_ENUM:
- for (i=0;p->enum_list[i].name;i++) {
- if (*(int *)ptr == p->enum_list[i].value) {
- fprintf(f,"%s",p->enum_list[i].name);
- break;
- }
- }
- break;
-
- case P_BOOL:
- fprintf(f,"%s",BOOLSTR(*(BOOL *)ptr));
- break;
+ switch (type)
+ {
+ case P_BOOL:
+ printf("%s",BOOLSTR(*(BOOL *)ptr));
+ break;
- case P_BOOLREV:
- fprintf(f,"%s",BOOLSTR(! *(BOOL *)ptr));
- break;
+ case P_BOOLREV:
+ printf("%s",BOOLSTR(! *(BOOL *)ptr));
+ break;
- case P_INTEGER:
- fprintf(f,"%d",*(int *)ptr);
- break;
+ case P_INTEGER:
+ printf("%d",*(int *)ptr);
+ break;
- case P_CHAR:
- fprintf(f,"%c",*(char *)ptr);
- break;
+ case P_CHAR:
+ printf("%c",*(char *)ptr);
+ break;
- case P_OCTAL:
- fprintf(f,"0%o",*(int *)ptr);
- break;
+ case P_OCTAL:
+ printf("0%o",*(int *)ptr);
+ break;
- case P_GSTRING:
- case P_UGSTRING:
- if ((char *)ptr)
- fprintf(f,"%s",(char *)ptr);
- break;
-
- case P_STRING:
- case P_USTRING:
- if (*(char **)ptr)
- fprintf(f,"%s",*(char **)ptr);
- break;
- }
-}
-
+ case P_GSTRING:
+ case P_UGSTRING:
+ if ((char *)ptr)
+ printf("%s",(char *)ptr);
+ break;
-/***************************************************************************
-print a parameter of the specified type
-***************************************************************************/
-static void parameter_string(struct parm_struct *p,void *ptr,char *s)
-{
- int i;
- s[0] = 0;
-
- switch (p->type) {
- case P_ENUM:
- for (i=0;p->enum_list[i].name;i++) {
- if (*(int *)ptr == p->enum_list[i].value) {
- sprintf(s,"%s",p->enum_list[i].name);
- break;
- }
- }
- break;
-
- case P_BOOL:
- sprintf(s, "%s",BOOLSTR(*(BOOL *)ptr));
- break;
-
- case P_BOOLREV:
- sprintf(s, "%s",BOOLSTR(! *(BOOL *)ptr));
- break;
-
- case P_INTEGER:
- sprintf(s, "%d",*(int *)ptr);
- break;
-
- case P_CHAR:
- sprintf(s, "%c",*(char *)ptr);
- break;
-
- case P_OCTAL:
- sprintf(s, "0%o",*(int *)ptr);
- break;
-
- case P_GSTRING:
- case P_UGSTRING:
- if ((char *)ptr)
- sprintf(s, "%s",(char *)ptr);
- break;
-
- case P_STRING:
- case P_USTRING:
- if (*(char **)ptr)
- sprintf(s, "%s",*(char **)ptr);
- break;
- }
+ case P_STRING:
+ case P_USTRING:
+ if (*(char **)ptr)
+ printf("%s",*(char **)ptr);
+ break;
+ }
}
@@ -1860,7 +1774,6 @@ static BOOL equal_parameter(parm_type type,void *ptr1,void *ptr2)
return(*((BOOL *)ptr1) == *((BOOL *)ptr2));
case P_INTEGER:
- case P_ENUM:
case P_OCTAL:
return(*((int *)ptr1) == *((int *)ptr2));
@@ -1941,32 +1854,32 @@ static BOOL do_section(char *pszSectionName)
/***************************************************************************
Display the contents of the global structure.
***************************************************************************/
-static void dump_globals(FILE *f)
+static void dump_globals(void)
{
int i;
- fprintf(f, "# Global parameters\n");
+ printf("Global parameters:\n");
for (i=0;parm_table[i].label;i++)
if (parm_table[i].class == P_GLOBAL &&
parm_table[i].ptr &&
(i == 0 || (parm_table[i].ptr != parm_table[i-1].ptr)))
{
- fprintf(f,"\t%s = ",parm_table[i].label);
- print_parameter(&parm_table[i],parm_table[i].ptr, f);
- fprintf(f,"\n");
+ printf("\t%s: ",parm_table[i].label);
+ print_parameter(parm_table[i].type,parm_table[i].ptr);
+ printf("\n");
}
}
/***************************************************************************
Display the contents of a single services record.
***************************************************************************/
-static void dump_a_service(service *pService, FILE *f)
+static void dump_a_service(service *pService)
{
int i;
if (pService == &sDefault)
- fprintf(f,"\n\n# Default service parameters\n");
+ printf("\nDefault service parameters:\n");
else
- fprintf(f,"\n[%s]\n",pService->szService);
+ printf("\nService parameters [%s]:\n",pService->szService);
for (i=0;parm_table[i].label;i++)
if (parm_table[i].class == P_LOCAL &&
@@ -1980,69 +1893,14 @@ static void dump_a_service(service *pService, FILE *f)
((char *)pService) + pdiff,
((char *)&sDefault) + pdiff))
{
- fprintf(f,"\t%s = ",parm_table[i].label);
- print_parameter(&parm_table[i],
- ((char *)pService) + pdiff, f);
- fprintf(f,"\n");
+ printf("\t%s: ",parm_table[i].label);
+ print_parameter(parm_table[i].type,
+ ((char *)pService) + pdiff);
+ printf("\n");
}
}
}
-
-/***************************************************************************
-return info about the next service in a service. snum==-1 gives the default
-serice and snum==-2 gives the globals
-
-return 0 when out of parameters
-***************************************************************************/
-int lp_next_parameter(int snum, int *i, char *label,
- char *value, int allparameters)
-{
- if (snum == -2) {
- /* do the globals */
- for (;parm_table[*i].label;(*i)++)
- if (parm_table[*i].class == P_GLOBAL &&
- parm_table[*i].ptr &&
- (*parm_table[*i].label != '-') &&
- ((*i) == 0 ||
- (parm_table[*i].ptr != parm_table[(*i)-1].ptr))) {
- strcpy(label, parm_table[*i].label);
- parameter_string(&parm_table[*i],
- parm_table[*i].ptr,
- value);
- (*i)++;
- return 1;
- }
- return 0;
- } else {
- service *pService = (snum==-1?&sDefault:pSERVICE(snum));
-
- for (;parm_table[*i].label;(*i)++)
- if (parm_table[*i].class == P_LOCAL &&
- parm_table[*i].ptr &&
- (*parm_table[*i].label != '-') &&
- ((*i) == 0 ||
- (parm_table[*i].ptr != parm_table[(*i)-1].ptr))) {
- int pdiff = PTR_DIFF(parm_table[*i].ptr,&sDefault);
-
- if (snum == -1 || allparameters ||
- !equal_parameter(parm_table[*i].type,
- ((char *)pService) + pdiff,
- ((char *)&sDefault) + pdiff)) {
- strcpy(label, parm_table[*i].label);
- parameter_string(&parm_table[*i],
- ((char *)pService) + pdiff,
- value);
- (*i)++;
- return 1;
- }
- }
- }
-
- return 0;
-}
-
-
#if 0
/***************************************************************************
Display the contents of a single copy structure.
@@ -2151,7 +2009,7 @@ void lp_killunused(BOOL (*snumused)(int ))
{
int i;
for (i=0;i<iNumServices;i++)
- if (VALID(i) && (!snumused || !snumused(i)))
+ if (VALID(i) && !snumused(i))
{
iSERVICE(i).valid = False;
free_service(pSERVICE(i));
@@ -2214,13 +2072,13 @@ int lp_numservices(void)
/***************************************************************************
Display the contents of the services array in human-readable form.
***************************************************************************/
-void lp_dump(FILE *f)
+void lp_dump(void)
{
int iService;
- dump_globals(f);
+ dump_globals();
- dump_a_service(&sDefault, f);
+ dump_a_service(&sDefault);
for (iService = 0; iService < iNumServices; iService++)
{
@@ -2228,12 +2086,11 @@ void lp_dump(FILE *f)
{
if (iSERVICE(iService).szService[0] == '\0')
break;
- dump_a_service(pSERVICE(iService), f);
+ dump_a_service(pSERVICE(iService));
}
}
}
-
/***************************************************************************
Return the number of the service with the given name, or -1 if it doesn't
exist. Note that this is a DIFFERENT ANIMAL from the internal function
@@ -2246,7 +2103,7 @@ int lp_servicenumber(char *pszServiceName)
for (iService = iNumServices - 1; iService >= 0; iService--)
if (VALID(iService) &&
- strequal(lp_servicename(iService), pszServiceName))
+ strwicmp(iSERVICE(iService).szService, pszServiceName) == 0)
break;
if (iService < 0)
@@ -2311,38 +2168,6 @@ static void set_default_server_announce_type()
#endif
}
-
-/*******************************************************************
-rename a service
-********************************************************************/
-void lp_rename_service(int snum, char *new_name)
-{
- string_set(&pSERVICE(snum)->szService, new_name);
-}
-
-/*******************************************************************
-remove a service
-********************************************************************/
-void lp_remove_service(int snum)
-{
- pSERVICE(snum)->valid = False;
-}
-
-/*******************************************************************
-copy a service
-********************************************************************/
-void lp_copy_service(int snum, char *new_name)
-{
- char *oldname = lp_servicename(snum);
- do_section(new_name);
- if (snum >= 0) {
- snum = lp_servicenumber(new_name);
- if (snum >= 0)
- lp_do_parameter(snum, "copy", oldname);
- }
-}
-
-
/*******************************************************************
Get the default server type we will announce as via nmbd.
********************************************************************/
@@ -2397,4 +2222,3 @@ int lp_minor_announce_version(void)
minor_version = atoi(p);
return minor_version;
}
-
diff --git a/source/param/params.c b/source/param/params.c
index a0a259c0070..0fdde0348ff 100644
--- a/source/param/params.c
+++ b/source/param/params.c
@@ -1,569 +1,326 @@
-/* -------------------------------------------------------------------------- **
- * Microsoft Network Services for Unix, AKA., Andrew Tridgell's SAMBA.
- *
- * This module Copyright (C) 1990, 1991, 1992, 1993, 1994 Karl Auer
- *
- * Rewritten almost completely by Christopher R. Hertel
- * at the University of Minnesota, September, 1997.
- * This module Copyright (C) 1997 by the University of Minnesota
- * -------------------------------------------------------------------------- **
- *
- * 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.
- *
- * -------------------------------------------------------------------------- **
- *
- * Module name: params
- *
- * -------------------------------------------------------------------------- **
- *
- * This module performs lexical analysis and initial parsing of a
- * Windows-like parameter file. It recognizes and handles four token
- * types: section-name, parameter-name, parameter-value, and
- * end-of-file. Comments and line continuation are handled
- * internally.
- *
- * The entry point to the module is function pm_process(). This
- * function opens the source file, calls the Parse() function to parse
- * the input, and then closes the file when either the EOF is reached
- * or a fatal error is encountered.
- *
- * A sample parameter file might look like this:
- *
- * [section one]
- * parameter one = value string
- * parameter two = another value
- * [section two]
- * new parameter = some value or t'other
- *
- * The parameter file is divided into sections by section headers:
- * section names enclosed in square brackets (eg. [section one]).
- * Each section contains parameter lines, each of which consist of a
- * parameter name and value delimited by an equal sign. Roughly, the
- * syntax is:
- *
- * <file> :== { <section> } EOF
- *
- * <section> :== <section header> { <parameter line> }
- *
- * <section header> :== '[' NAME ']'
- *
- * <parameter line> :== NAME '=' VALUE '\n'
- *
- * Blank lines and comment lines are ignored. Comment lines are lines
- * beginning with either a semicolon (';') or a pound sign ('#').
- *
- * All whitespace in section names and parameter names is compressed
- * to single spaces. Leading and trailing whitespace is stipped from
- * both names and values.
- *
- * Only the first equals sign in a parameter line is significant.
- * Parameter values may contain equals signs, square brackets and
- * semicolons. Internal whitespace is retained in parameter values,
- * with the exception of the '\r' character, which is stripped for
- * historic reasons. Parameter names may not start with a left square
- * bracket, an equal sign, a pound sign, or a semicolon, because these
- * are used to identify other tokens.
- *
- * -------------------------------------------------------------------------- **
- */
+/*
+ Unix SMB/Netbios implementation.
+ Version 1.9.
+ Parameter loading utlities
+ Copyright (C) Karl Auer 1993,1994,1997
+
+ 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.
+*/
+
+/**************************************************************************
+PARAMS.C
+
+Copyright (C) 1990, 1991, 1992, 1993, 1994 Karl Auer
+
+This module provides for streamlines retrieval of information from a
+Windows-like parameter files. There is a function which will search for
+all sections in the file and call a specified function with each. There is
+a similar function which will call a specified function for all parameters
+in a section. The idea is that you pass the addresses of suitable functions
+to a single function in this module which will then enumerate all sections,
+and within each section all parameters, to your program.
+
+Parameter files contain text lines (newline delimited) which consist of
+either a section name in square brackets or a parameter name, delimited
+from the parameter value by an equals sign. Blank lines or lines where the
+first non-whitespace character is a colon are ignored. All whitespace in
+section names and parameter names is compressed to single spaces. Leading
+and trailing whitespace on parameter names and parameter values is stripped.
+
+Only the first equals sign in a parameter line is significant - parameter
+values may contain equals signs, square brackets and semicolons. Internal
+whitespace is retained in parameter values. Parameter names may not start
+with a square bracket, an equals sign or a semicolon, for obvious reasons.
+
+A sample parameter file might look like this:
+
+[things]
+this=1
+that=2
+[other things]
+the other = 3
+
+**************************************************************************/
#include "includes.h"
-/* -------------------------------------------------------------------------- **
- * Constants...
- */
-
-#define BUFR_INC 1024
-
-
-/* -------------------------------------------------------------------------- **
- * Variables...
- *
- * DEBUGLEVEL - The ubiquitous DEBUGLEVEL. This determines which DEBUG()
- * messages will be produced.
- * bufr - pointer to a global buffer. This is probably a kludge,
- * but it was the nicest kludge I could think of (for now).
- * bSize - The size of the global buffer <bufr>.
- */
+#include "smb.h"
+/* local variable pointing to passed filename */
+static char *pszParmFile = NULL;
extern int DEBUGLEVEL;
-static char *bufr = NULL;
-static int bSize = 0;
-
-/* -------------------------------------------------------------------------- **
- * Functions...
- */
-
-static int EatWhitespace( FILE *InFile )
- /* ------------------------------------------------------------------------ **
- * Scan past whitespace (see ctype(3C)) and return the first non-whitespace
- * character, or newline, or EOF.
- *
- * Input: InFile - Input source.
- *
- * Output: The next non-whitespace character in the input stream.
- *
- * Notes: Because the config files use a line-oriented grammar, we
- * explicitly exclude the newline character from the list of
- * whitespace characters.
- * - Note that both EOF (-1) and the nul character ('\0') are
- * considered end-of-file markers.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- int c;
-
- for( c = getc( InFile ); isspace( c ) && ('\n' != c); c = getc( InFile ) )
- ;
- return( c );
- } /* EatWhitespace */
-
-static int EatComment( FILE *InFile )
- /* ------------------------------------------------------------------------ **
- * Scan to the end of a comment.
- *
- * Input: InFile - Input source.
- *
- * Output: The character that marks the end of the comment. Normally,
- * this will be a newline, but it *might* be an EOF.
- *
- * Notes: Because the config files use a line-oriented grammar, we
- * explicitly exclude the newline character from the list of
- * whitespace characters.
- * - Note that both EOF (-1) and the nul character ('\0') are
- * considered end-of-file markers.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- int c;
-
- for( c = getc( InFile ); ('\n'!=c) && (EOF!=c) && (c>0); c = getc( InFile ) )
- ;
- return( c );
- } /* EatComment */
-
-static int Continuation( char *line, int pos )
- /* ------------------------------------------------------------------------ **
- * Scan backards within a string to discover if the last non-whitespace
- * character is a line-continuation character ('\\').
- *
- * Input: line - A pointer to a buffer containing the string to be
- * scanned.
- * pos - This is taken to be the offset of the end of the
- * string. This position is *not* scanned.
- *
- * Output: The offset of the '\\' character if it was found, or -1 to
- * indicate that it was not.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- pos--;
- while( (pos >= 0) && isspace(line[pos]) )
- pos--;
-
- return( ((pos >= 0) && ('\\' == line[pos])) ? pos : -1 );
- } /* Continuation */
-
-
-static BOOL Section( FILE *InFile, BOOL (*sfunc)(char *) )
- /* ------------------------------------------------------------------------ **
- * Scan a section name, and pass the name to function sfunc().
- *
- * Input: InFile - Input source.
- * sfunc - Pointer to the function to be called if the section
- * name is successfully read.
- *
- * Output: True if the section name was read and True was returned from
- * <sfunc>. False if <sfunc> failed or if a lexical error was
- * encountered.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- int c;
- int i;
- int end;
- char *func = "params.c:Section() -";
-
- i = 0; /* <i> is the offset of the next free byte in bufr[] and */
- end = 0; /* <end> is the current "end of string" offset. In most */
- /* cases these will be the same, but if the last */
- /* character written to bufr[] is a space, then <end> */
- /* will be one less than <i>. */
-
- c = EatWhitespace( InFile ); /* We've already got the '['. Scan */
- /* past initial white space. */
-
- while( (EOF != c) && (c > 0) )
- {
-
- /* Check that the buffer is big enough for the next character. */
- if( i > (bSize - 2) )
- {
- bSize += BUFR_INC;
- bufr = Realloc( bufr, bSize );
- if( NULL == bufr )
- {
- DEBUG(0, ("%s Memory re-allocation failure.", func) );
- return( False );
- }
- }
- /* Handle a single character. */
- switch( c )
+/**************************************************************************
+Strip all leading whitespace from a string.
+**************************************************************************/
+static void trimleft(char *psz)
+{
+ char *pszDest;
+
+ pszDest = psz;
+ if (psz != NULL)
+ {
+ while (*psz != '\0' && isspace(*psz))
+ psz++;
+ while (*psz != '\0')
+ *pszDest++ = *psz++;
+ *pszDest = '\0';
+ }
+}
+
+/**************************************************************************
+Strip all trailing whitespace from a string.
+**************************************************************************/
+static void trimright(char *psz)
+{
+ char *pszTemp;
+
+ if (psz != NULL && psz[0] != '\0')
+ {
+ pszTemp = psz + strlen(psz) - 1;
+ while (isspace(*pszTemp))
+ *pszTemp-- = '\0';
+ }
+}
+
+/***********************************************************************
+Collapse each whitespace area in a string to a single space.
+***********************************************************************/
+static void collapse_spaces(char *psz)
+{
+ while (*psz)
+ if (isspace(*psz))
{
- case ']': /* Found the closing bracket. */
- bufr[end] = '\0';
- if( 0 == end ) /* Don't allow an empty name. */
- {
- DEBUG(0, ("%s Empty section name in configuration file.\n", func ));
- return( False );
- }
- if( !sfunc( bufr ) ) /* Got a valid name. Deal with it. */
- return( False );
- (void)EatComment( InFile ); /* Finish off the line. */
- return( True );
-
- case '\n': /* Got newline before closing ']'. */
- i = Continuation( bufr, i ); /* Check for line continuation. */
- if( i < 0 )
- {
- bufr[end] = '\0';
- DEBUG(0, ("%s Badly formed line in configuration file: %s\n",
- func, bufr ));
- return( False );
- }
- end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i);
- c = getc( InFile ); /* Continue with next line. */
- break;
-
- default: /* All else are a valid name chars. */
- if( isspace( c ) ) /* One space per whitespace region. */
- {
- bufr[end] = ' ';
- i = end + 1;
- c = EatWhitespace( InFile );
- }
- else /* All others copy verbatim. */
- {
- bufr[i++] = c;
- end = i;
- c = getc( InFile );
- }
+ *psz++ = ' ';
+ trimleft(psz);
}
- }
-
- /* We arrive here if we've met the EOF before the closing bracket. */
- DEBUG(0, ("%s Unexpected EOF in the configuration file: %s\n", func, bufr ));
- return( False );
- } /* Section */
-
-static BOOL Parameter( FILE *InFile, BOOL (*pfunc)(char *, char *), int c )
- /* ------------------------------------------------------------------------ **
- * Scan a parameter name and value, and pass these two fields to pfunc().
- *
- * Input: InFile - The input source.
- * pfunc - A pointer to the function that will be called to
- * process the parameter, once it has been scanned.
- * c - The first character of the parameter name, which
- * would have been read by Parse(). Unlike a comment
- * line or a section header, there is no lead-in
- * character that can be discarded.
- *
- * Output: True if the parameter name and value were scanned and processed
- * successfully, else False.
- *
- * Notes: This function is in two parts. The first loop scans the
- * parameter name. Internal whitespace is compressed, and an
- * equal sign (=) terminates the token. Leading and trailing
- * whitespace is discarded. The second loop scans the parameter
- * value. When both have been successfully identified, they are
- * passed to pfunc() for processing.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- int i = 0; /* Position within bufr. */
- int end = 0; /* bufr[end] is current end-of-string. */
- int vstart = 0; /* Starting position of the parameter value. */
- char *func = "params.c:Parameter() -";
-
- /* Read the parameter name. */
- while( 0 == vstart ) /* Loop until we've found the start of the value. */
- {
-
- if( i > (bSize - 2) ) /* Ensure there's space for next char. */
+ else
+ psz++;
+}
+
+/**************************************************************************
+Return the value of the first non-white character in the specified string.
+The terminating NUL counts as non-white for the purposes of this function.
+Note - no check for a NULL string! What would we return?
+**************************************************************************/
+static int firstnonwhite(char *psz)
+{
+ while (isspace(*psz) && (*psz != '\0'))
+ psz++;
+ return (*psz);
+}
+
+
+/**************************************************************************
+Identifies all parameters in the current section, calls the parameter
+function for each. Ignores comment lines, stops and backs up in file when
+a section is encountered. Returns True on success, False on error.
+**************************************************************************/
+static BOOL enumerate_parameters(FILE *fileIn, BOOL (*pfunc)(char *,char *))
+{
+ pstring szBuf;
+ char *pszTemp;
+ BOOL bRetval;
+ long lFileOffset;
+ int cTemp;
+ BOOL bParmFound;
+
+ bRetval = False;
+ bParmFound = False;
+ while (True)
+ {
+ /* first remember where we are */
+ if ((lFileOffset = ftell(fileIn)) >= 0L)
{
- bSize += BUFR_INC;
- bufr = Realloc( bufr, bSize );
- if( NULL == bufr )
- {
- DEBUG(0, ("%s Memory re-allocation failure.", func) );
- return( False );
- }
+ /* then get and check a line */
+ if (fgets_slash(szBuf, sizeof(szBuf)-1, fileIn) == NULL)
+ {
+ /* stop - return OK unless file error */
+ bRetval = !ferror(fileIn);
+ if (!bRetval)
+ DEBUG(0,( "Read error on configuration file (enumerating parameters)!\n"));
+ break;
+ }
+ else
+ /* if first non-white is a '[', stop (new section) */
+ if ((cTemp = firstnonwhite(szBuf)) == '[')
+ {
+ /* restore position to start of new section */
+ if (fseek(fileIn, lFileOffset, SEEK_SET) < 0L)
+ {
+ DEBUG(0,( "Seek error on configuration file!\n"));
+ break;
+ }
+
+ /* return success */
+ bRetval = True;
+ break;
+ }
+ else
+ /* if it's a semicolon or line is blank, ignore the line */
+ if (!cTemp || strchr(";#",cTemp))
+ {
+ continue;
+ }
+ else
+ /* if no equals sign and line contains non-whitespace */
+ /* then line is badly formed */
+ if ((pszTemp = strchr(szBuf, '=')) == NULL)
+ {
+ DEBUG(0,( "Ignoring badly formed line: %s", szBuf));
+ }
+ else
+ {
+ /* Note that we have found a parameter */
+ bParmFound = True;
+ /* cut line at the equals sign */
+ *pszTemp++ = '\0';
+ /* trim leading and trailing space from both halves */
+ trimright(szBuf);
+ trimleft(szBuf);
+ trimright(pszTemp);
+ trimleft(pszTemp);
+ /* process the parameter iff passed pointer not NULL */
+ if (pfunc != NULL)
+ if (!pfunc(szBuf, pszTemp))
+ break;
+ }
}
-
- switch( c )
- {
- case '=': /* Equal sign marks end of param name. */
- if( 0 == end ) /* Don't allow an empty name. */
- {
- DEBUG(0, ("%s Invalid parameter name in config. file.\n", func ));
- return( False );
- }
- bufr[end++] = '\0'; /* Mark end of string & advance. */
- i = end; /* New string starts here. */
- vstart = end; /* New string is parameter value. */
- bufr[i] = '\0'; /* New string is nul, for now. */
- break;
-
- case '\n': /* Find continuation char, else error. */
- i = Continuation( bufr, i );
- if( i < 0 )
- {
- bufr[end] = '\0';
- DEBUG(1,("%s Ignoring badly formed line in configuration file: %s\n",
- func, bufr ));
- return( True );
- }
- end = ( (i > 0) && (' ' == bufr[i - 1]) ) ? (i - 1) : (i);
- c = getc( InFile ); /* Read past eoln. */
- break;
-
- case '\0': /* Shouldn't have EOF within param name. */
- case EOF:
- bufr[i] = '\0';
- DEBUG(1,("%s Unexpected end-of-file at: %s\n", func, bufr ));
- return( True );
-
- default:
- if( isspace( c ) ) /* One ' ' per whitespace region. */
- {
- bufr[end] = ' ';
- i = end + 1;
- c = EatWhitespace( InFile );
- }
- else /* All others verbatim. */
- {
- bufr[i++] = c;
- end = i;
- c = getc( InFile );
- }
- }
- }
-
- /* Now parse the value. */
- c = EatWhitespace( InFile ); /* Again, trim leading whitespace. */
- while( (EOF !=c) && (c > 0) )
- {
-
- if( i > (bSize - 2) ) /* Make sure there's enough room. */
+ }
+ return (bRetval);
+}
+
+
+/***********************************************************************
+Close up s by n chars, at offset start.
+***********************************************************************/
+static void closestr(char *s, int start, int n)
+{
+ char *src;
+ char *dest;
+ int len;
+
+ if (n > 0)
+ if ((src = dest = s) != NULL)
{
- bSize += BUFR_INC;
- bufr = Realloc( bufr, bSize );
- if( NULL == bufr )
- {
- DEBUG(0, ("%s Memory re-allocation failure.", func) );
- return( False );
- }
+ len = strlen(s);
+ if (start >= 0 && start < len - n)
+ {
+ src += start + n;
+ dest += start;
+
+ while (*src)
+ *dest++ = *src++;
+ *dest = '\0';
+ }
}
-
- switch( c )
+}
+
+/**************************************************************************
+Identifies all sections in the parameter file, calls passed section_func()
+for each, passing the section name, then calls enumerate_parameters().
+Returns True on success, False on failure. Note that the section and
+parameter names will have all internal whitespace areas collapsed to a
+single space for processing.
+**************************************************************************/
+static BOOL enumerate_sections(FILE *fileIn,
+ BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *))
+{
+ pstring szBuf;
+ BOOL bRetval;
+ BOOL bSectionFound;
+
+ /* this makes sure we get include lines right */
+ enumerate_parameters(fileIn, pfunc);
+
+ bRetval = False;
+ bSectionFound = False;
+ while (True)
+ {
+ if (fgets_slash(szBuf, sizeof(szBuf)-1, fileIn) == NULL)
{
- case '\r': /* Explicitly remove '\r' because the older */
- c = getc( InFile ); /* version called fgets_slash() which also */
- break; /* removes them. */
-
- case '\n': /* Marks end of value unless there's a '\'. */
- i = Continuation( bufr, i );
- if( i < 0 )
- c = 0;
- else
- {
- for( end = i; (end >= 0) && isspace(bufr[end]); end-- )
- ;
- c = getc( InFile );
- }
- break;
-
- default: /* All others verbatim. Note that spaces do */
- bufr[i++] = c; /* not advance <end>. This allows trimming */
- if( !isspace( c ) ) /* of whitespace at the end of the line. */
- end = i;
- c = getc( InFile );
- break;
+ /* stop - return OK unless file error */
+ bRetval = !ferror(fileIn);
+ if (!bRetval)
+ DEBUG(0,( "Read error on configuration file (enumerating sections)!\n"));
+ break;
}
- }
- bufr[end] = '\0'; /* End of value. */
-
- return( pfunc( bufr, &bufr[vstart] ) ); /* Pass name & value to pfunc(). */
- } /* Parameter */
-
-static BOOL Parse( FILE *InFile,
- BOOL (*sfunc)(char *),
- BOOL (*pfunc)(char *, char *) )
- /* ------------------------------------------------------------------------ **
- * Scan & parse the input.
- *
- * Input: InFile - Input source.
- * sfunc - Function to be called when a section name is scanned.
- * See Section().
- * pfunc - Function to be called when a parameter is scanned.
- * See Parameter().
- *
- * Output: True if the file was successfully scanned, else False.
- *
- * Notes: The input can be viewed in terms of 'lines'. There are four
- * types of lines:
- * Blank - May contain whitespace, otherwise empty.
- * Comment - First non-whitespace character is a ';' or '#'.
- * The remainder of the line is ignored.
- * Section - First non-whitespace character is a '['.
- * Parameter - The default case.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- int c;
-
- c = EatWhitespace( InFile );
- while( (EOF != c) && (c > 0) )
- {
- switch( c )
+ else
{
- case '\n': /* Blank line. */
- c = EatWhitespace( InFile );
- break;
-
- case ';': /* Comment line. */
- case '#':
- c = EatComment( InFile );
- break;
-
- case '[': /* Section Header. */
- if( !Section( InFile, sfunc ) )
- return( False );
- c = EatWhitespace( InFile );
- break;
-
- case '\\': /* Bogus backslash. */
- c = EatWhitespace( InFile );
- break;
-
- default: /* Parameter line. */
- if( !Parameter( InFile, pfunc, c ) )
- return( False );
- c = EatWhitespace( InFile );
- break;
+ trimleft(szBuf);
+ trimright(szBuf);
+ if (szBuf[0] == '[')
+ {
+ closestr(szBuf, 0, 1);
+ if (strlen(szBuf) > 1)
+ if (szBuf[strlen(szBuf) - 1] == ']')
+ {
+ /* found a section - note the fact */
+ bSectionFound = True;
+ /* remove trailing metabracket */
+ szBuf[strlen(szBuf) - 1] = '\0';
+ /* remove leading and trailing whitespace from name */
+ trimleft(szBuf);
+ trimright(szBuf);
+ /* reduce all internal whitespace to one space */
+ collapse_spaces(szBuf);
+ /* process it - stop if the processing fails */
+ if (sfunc != NULL)
+ if (!sfunc(szBuf))
+ break;
+ if (!enumerate_parameters(fileIn, pfunc))
+ break;
+ }
+ }
}
- }
- return( True );
- } /* Parse */
-
-static FILE *OpenConfFile( char *FileName )
- /* ------------------------------------------------------------------------ **
- * Open a configuration file.
- *
- * Input: FileName - The pathname of the config file to be opened.
- *
- * Output: A pointer of type (FILE *) to the opened file, or NULL if the
- * file could not be opened.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- FILE *OpenedFile;
- char *func = "params.c:OpenConfFile() -";
-
- if( NULL == FileName || 0 == *FileName )
- {
- DEBUG( 0, ("%s No configuration filename specified.\n", func) );
- return( NULL );
- }
-
- OpenedFile = fopen( FileName, "r" );
- if( NULL == OpenedFile )
- {
- DEBUG( 0,
- ("%s Unable to open configuration file \"%s\":\n\t%s\n",
- func, FileName, strerror(errno)) );
- }
-
- return( OpenedFile );
- } /* OpenConfFile */
-
-BOOL pm_process( char *FileName,
- BOOL (*sfunc)(char *),
- BOOL (*pfunc)(char *, char *) )
- /* ------------------------------------------------------------------------ **
- * Process the named parameter file.
- *
- * Input: FileName - The pathname of the parameter file to be opened.
- * sfunc - A pointer to a function that will be called when
- * a section name is discovered.
- * pfunc - A pointer to a function that will be called when
- * a parameter name and value are discovered.
- *
- * Output: TRUE if the file was successfully parsed, else FALSE.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- int result;
- FILE *InFile;
- char *func = "params.c:pm_process() -";
-
- InFile = OpenConfFile( FileName ); /* Open the config file. */
- if( NULL == InFile )
- return( False );
-
- DEBUG( 3, ("%s Processing configuration file \"%s\"\n", func, FileName) );
-
- if( NULL != bufr ) /* If we already have a buffer */
- result = Parse( InFile, sfunc, pfunc ); /* (recursive call), then just */
- /* use it. */
-
- else /* If we don't have a buffer */
- { /* allocate one, then parse, */
- bSize = BUFR_INC; /* then free. */
- bufr = (char *)malloc( bSize );
- if( NULL == bufr )
+ }
+
+ return (bRetval);
+}
+
+/**************************************************************************
+Process the passed parameter file.
+
+Returns True if successful, else False.
+**************************************************************************/
+BOOL pm_process(char *pszFileName,BOOL (*sfunc)(char *),BOOL (*pfunc)(char *,char *))
+{
+ FILE *fileIn;
+ BOOL bRetval;
+
+ bRetval = False;
+
+ /* record the filename for use in error messages one day... */
+ pszParmFile = pszFileName;
+
+ if (pszParmFile == NULL || strlen(pszParmFile) < 1)
+ DEBUG(0,( "No configuration filename specified!\n"));
+ else
+ if ((fileIn = fopen(pszParmFile, "r")) == NULL)
+ DEBUG(0,( "Unable to open configuration file \"%s\"!\n", pszParmFile));
+ else
{
- DEBUG(0,("%s memory allocation failure.\n", func));
- fclose(InFile);
- return( False );
+ DEBUG(3,("Processing configuration file \"%s\"\n", pszParmFile));
+ bRetval = enumerate_sections(fileIn, sfunc, pfunc);
+ fclose(fileIn);
}
- result = Parse( InFile, sfunc, pfunc );
- free( bufr );
- bufr = NULL;
- bSize = 0;
- }
-
- fclose(InFile);
- if( !result ) /* Generic failure. */
- {
- DEBUG(0,("%s Failed. Error returned from params.c:parse().\n", func));
- return( False );
- }
+ if (!bRetval)
+ DEBUG(0,("pm_process retuned false\n"));
+ return (bRetval);
+}
- return( True ); /* Generic success. */
- } /* pm_process */
-/* -------------------------------------------------------------------------- */
diff --git a/source/passdb/smbpass.c b/source/passdb/smbpass.c
index 4109383fb47..a31a10cef4b 100644
--- a/source/passdb/smbpass.c
+++ b/source/passdb/smbpass.c
@@ -1,3 +1,4 @@
+#ifdef SMB_PASSWD
/*
* Unix SMB/Netbios implementation. Version 1.9. SMB parameters and setup
* Copyright (C) Andrew Tridgell 1992-1997 Modified by Jeremy Allison 1995.
@@ -103,11 +104,10 @@ static int gethexpwd(char *p, char *pwd)
return (True);
}
-/*************************************************************************
- Routine to search the smbpasswd file for an entry matching the username
- or user id. if the name is NULL, then the smb_uid is used instead.
- *************************************************************************/
-struct smb_passwd *get_smbpwd_entry(char *name, int smb_userid)
+/*
+ * Routine to search the smbpasswd file for an entry matching the username.
+ */
+struct smb_passwd *get_smbpwnam(char *name)
{
/* Static buffers we will return. */
static struct smb_passwd pw_buf;
@@ -128,28 +128,19 @@ struct smb_passwd *get_smbpwd_entry(char *name, int smb_userid)
DEBUG(0, ("No SMB password file set\n"));
return (NULL);
}
- DEBUG(10, ("get_smbpwd_entry: opening file %s\n", pfile));
-
- if (name != NULL)
- {
- DEBUG(10, ("get_smbpwd_entry: search by name: %s\n", name));
- }
- else
- {
- DEBUG(10, ("get_smbpwd_entry: search by smb_userid: %x\n", smb_userid));
- }
+ DEBUG(10, ("get_smbpwnam: opening file %s\n", pfile));
fp = fopen(pfile, "r");
if (fp == NULL) {
- DEBUG(0, ("get_smbpwd_entry: unable to open file %s\n", pfile));
+ DEBUG(0, ("get_smbpwnam: unable to open file %s\n", pfile));
return NULL;
}
/* Set a 16k buffer to do more efficient reads */
setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
if ((lockfd = pw_file_lock(pfile, F_RDLCK, 5)) < 0) {
- DEBUG(0, ("get_smbpwd_entry: unable to lock file %s\n", pfile));
+ DEBUG(0, ("get_smbpwnam: unable to lock file %s\n", pfile));
fclose(fp);
return NULL;
}
@@ -185,10 +176,10 @@ struct smb_passwd *get_smbpwd_entry(char *name, int smb_userid)
linebuf[linebuf_len - 1] = '\0';
#ifdef DEBUG_PASSWORD
- DEBUG(100, ("get_smbpwd_entry: got line |%s|\n", linebuf));
+ DEBUG(100, ("get_smbpwnam: got line |%s|\n", linebuf));
#endif
if ((linebuf[0] == 0) && feof(fp)) {
- DEBUG(4, ("get_smbpwd_entry: end of file reached\n"));
+ DEBUG(4, ("get_smbpwnam: end of file reached\n"));
break;
}
/*
@@ -205,12 +196,12 @@ struct smb_passwd *get_smbpwd_entry(char *name, int smb_userid)
*/
if (linebuf[0] == '#' || linebuf[0] == '\0') {
- DEBUG(6, ("get_smbpwd_entry: skipping comment or blank line\n"));
+ DEBUG(6, ("get_smbpwnam: skipping comment or blank line\n"));
continue;
}
p = (unsigned char *) strchr(linebuf, ':');
if (p == NULL) {
- DEBUG(0, ("get_smbpwd_entry: malformed password entry (no :)\n"));
+ DEBUG(0, ("get_smbpwnam: malformed password entry (no :)\n"));
continue;
}
/*
@@ -219,89 +210,55 @@ struct smb_passwd *get_smbpwd_entry(char *name, int smb_userid)
*/
strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
user_name[PTR_DIFF(p, linebuf)] = '\0';
+ if (!strequal(user_name, name))
+ continue;
- /* get smb uid */
-
+ /* User name matches - get uid and password */
p++; /* Go past ':' */
if (!isdigit(*p)) {
- DEBUG(0, ("get_smbpwd_entry: malformed password entry (uid not number)\n"));
+ DEBUG(0, ("get_smbpwnam: malformed password entry (uid not number)\n"));
fclose(fp);
pw_file_unlock(lockfd);
return NULL;
}
-
uidval = atoi((char *) p);
-
while (*p && isdigit(*p))
- {
p++;
- }
-
- if (*p != ':')
- {
- DEBUG(0, ("get_smbpwd_entry: malformed password entry (no : after uid)\n"));
+ if (*p != ':') {
+ DEBUG(0, ("get_smbpwnam: malformed password entry (no : after uid)\n"));
fclose(fp);
pw_file_unlock(lockfd);
return NULL;
}
-
- if (name != NULL)
- {
- /* search is by user name */
- if (!strequal(user_name, name)) continue;
- DEBUG(10, ("get_smbpwd_entry: found by name: %s\n", user_name));
- }
- else
- {
- /* search is by user id */
- if (uidval != smb_userid) continue;
- DEBUG(10, ("get_smbpwd_entry: found by smb_userid: %x\n", uidval));
- }
-
- /* if we're here, the entry has been found (either by name or uid) */
-
/*
* Now get the password value - this should be 32 hex digits
* which are the ascii representations of a 16 byte string.
* Get two at a time and put them into the password.
*/
-
- /* skip the ':' */
p++;
-
- if (*p == '*' || *p == 'X')
- {
+ if (*p == '*' || *p == 'X') {
/* Password deliberately invalid - end here. */
- DEBUG(10, ("get_smbpwd_entry: entry invalidated for user %s\n", user_name));
+ DEBUG(10, ("get_smbpwnam: entry invalidated for user %s\n", user_name));
fclose(fp);
pw_file_unlock(lockfd);
return NULL;
}
-
- if (linebuf_len < (PTR_DIFF(p, linebuf) + 33))
- {
- DEBUG(0, ("get_smbpwd_entry: malformed password entry (passwd too short)\n"));
+ if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
+ DEBUG(0, ("get_smbpwnam: malformed password entry (passwd too short)\n"));
fclose(fp);
pw_file_unlock(lockfd);
return (False);
}
-
- if (p[32] != ':')
- {
- DEBUG(0, ("get_smbpwd_entry: malformed password entry (no terminating :)\n"));
+ if (p[32] != ':') {
+ DEBUG(0, ("get_smbpwnam: malformed password entry (no terminating :)\n"));
fclose(fp);
pw_file_unlock(lockfd);
return NULL;
}
-
- if (!strncasecmp((char *) p, "NO PASSWORD", 11))
- {
+ if (!strncasecmp((char *) p, "NO PASSWORD", 11)) {
pw_buf.smb_passwd = NULL;
- }
- else
- {
- if (!gethexpwd((char *)p, (char *)smbpwd))
- {
+ } else {
+ if(!gethexpwd((char *)p,(char *)smbpwd)) {
DEBUG(0, ("Malformed Lanman password entry (non hex chars)\n"));
fclose(fp);
pw_file_unlock(lockfd);
@@ -309,7 +266,6 @@ struct smb_passwd *get_smbpwd_entry(char *name, int smb_userid)
}
pw_buf.smb_passwd = smbpwd;
}
-
pw_buf.smb_name = user_name;
pw_buf.smb_userid = uidval;
pw_buf.smb_nt_passwd = NULL;
@@ -327,7 +283,7 @@ struct smb_passwd *get_smbpwd_entry(char *name, int smb_userid)
fclose(fp);
pw_file_unlock(lockfd);
- DEBUG(5, ("get_smbpwd_entrye: returning passwd entry for user %s, uid %d\n",
+ DEBUG(5, ("get_smbpwname: returning passwd entry for user %s, uid %d\n",
user_name, uidval));
return &pw_buf;
}
@@ -336,537 +292,8 @@ struct smb_passwd *get_smbpwd_entry(char *name, int smb_userid)
pw_file_unlock(lockfd);
return NULL;
}
-
-/*
- * Routine to search the smbpasswd file for an entry matching the username.
- */
-BOOL add_smbpwd_entry(struct smb_passwd* pwd)
+#else
+ void smbpass_dummy(void)
{
- /* Static buffers we will return. */
- static pstring user_name;
-
- char linebuf[256];
- char readbuf[16 * 1024];
- unsigned char c;
- unsigned char *p;
- long linebuf_len;
- FILE *fp;
- int lockfd;
- char *pfile = lp_smb_passwd_file();
-
- int i;
- int wr_len;
-
- int fd;
- int new_entry_length;
- char *new_entry;
- long offpos;
-
- if (!*pfile)
- {
- DEBUG(0, ("No SMB password file set\n"));
- return False;
- }
- DEBUG(10, ("add_smbpwd_entry: opening file %s\n", pfile));
-
- fp = fopen(pfile, "r+");
-
- if (fp == NULL)
- {
- DEBUG(0, ("add_smbpwd_entry: unable to open file %s\n", pfile));
- return False;
- }
- /* Set a 16k buffer to do more efficient reads */
- setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
-
- if ((lockfd = pw_file_lock(pfile, F_RDLCK | F_WRLCK, 5)) < 0)
- {
- DEBUG(0, ("add_smbpwd_entry: unable to lock file %s\n", pfile));
- fclose(fp);
- return False;
- }
- /* make sure it is only rw by the owner */
- chmod(pfile, 0600);
-
- /* We have a write lock on the file. */
- /*
- * Scan the file, a line at a time and check if the name matches.
- */
- while (!feof(fp))
- {
- linebuf[0] = '\0';
-
- fgets(linebuf, 256, fp);
- if (ferror(fp))
- {
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- /*
- * Check if the string is terminated with a newline - if not
- * then we must keep reading and discard until we get one.
- */
- linebuf_len = strlen(linebuf);
- if (linebuf[linebuf_len - 1] != '\n')
- {
- c = '\0';
- while (!ferror(fp) && !feof(fp))
- {
- c = fgetc(fp);
- if (c == '\n')
- {
- break;
- }
- }
- }
- else
- {
- linebuf[linebuf_len - 1] = '\0';
- }
-
-#ifdef DEBUG_PASSWORD
- DEBUG(100, ("add_smbpwd_entry: got line |%s|\n", linebuf));
-#endif
-
- if ((linebuf[0] == 0) && feof(fp))
- {
- DEBUG(4, ("add_smbpwd_entry: end of file reached\n"));
- break;
- }
-
- /*
- * The line we have should be of the form :-
- *
- * username:uid:[32hex bytes]:....other flags presently
- * ignored....
- *
- * or,
- *
- * username:uid:[32hex bytes]:[32hex bytes]:....ignored....
- *
- * if Windows NT compatible passwords are also present.
- */
-
- if (linebuf[0] == '#' || linebuf[0] == '\0')
- {
- DEBUG(6, ("add_smbpwd_entry: skipping comment or blank line\n"));
- continue;
- }
-
- p = (unsigned char *) strchr(linebuf, ':');
-
- if (p == NULL)
- {
- DEBUG(0, ("add_smbpwd_entry: malformed password entry (no :)\n"));
- continue;
- }
-
- /*
- * As 256 is shorter than a pstring we don't need to check
- * length here - if this ever changes....
- */
- strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
- user_name[PTR_DIFF(p, linebuf)] = '\0';
- if (strequal(user_name, pwd->smb_name))
- {
- DEBUG(6, ("add_smbpwd_entry: entry already exists\n"));
- return False;
- }
- }
-
- /* ok - entry doesn't exist. we can add it */
-
- /* Create a new smb passwd entry and set it to the given password. */
- /* The add user write needs to be atomic - so get the fd from
- the fp and do a raw write() call.
- */
- fd = fileno(fp);
-
- if((offpos = lseek(fd, 0, SEEK_END)) == -1)
- {
- DEBUG(0, ("add_smbpwd_entry(lseek): Failed to add entry for user %s to file %s. \
-Error was %s\n", pwd->smb_name, pfile, strerror(errno)));
-
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- new_entry_length = strlen(pwd->smb_name) + 1 + 15 + 1 + 32 + 1 + 32 + 1 + 2;
-
- if((new_entry = (char *)malloc( new_entry_length )) == 0)
- {
- DEBUG(0, ("add_smbpwd_entry(malloc): Failed to add entry for user %s to file %s. \
-Error was %s\n",
- pwd->smb_name, pfile, strerror(errno)));
-
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- sprintf(new_entry, "%s:%u:", pwd->smb_name, (unsigned)pwd->smb_userid);
- p = (unsigned char *)&new_entry[strlen(new_entry)];
-
- for( i = 0; i < 16; i++)
- {
- sprintf((char *)&p[i*2], "%02X", pwd->smb_passwd[i]);
- }
- p += 32;
-
- *p++ = ':';
-
- for( i = 0; i < 16; i++)
- {
- sprintf((char *)&p[i*2], "%02X", pwd->smb_nt_passwd[i]);
- }
- p += 32;
-
- *p++ = ':';
- sprintf((char *)p,"\n");
-
-#ifdef DEBUG_PASSWORD
- DEBUG(100, ("add_smbpwd_entry(%d): new_entry_len %d entry_len %d made line |%s|\n",
- fd, new_entry_length, strlen(new_entry), new_entry));
+} /* To avoid compiler complaints */
#endif
-
- if ((wr_len = write(fd, new_entry, strlen(new_entry))) != strlen(new_entry))
- {
- DEBUG(0, ("add_smbpwd_entry(write): %d Failed to add entry for user %s to file %s. \
-Error was %s\n", wr_len, pwd->smb_name, pfile, strerror(errno)));
-
- /* Remove the entry we just wrote. */
- if(ftruncate(fd, offpos) == -1)
- {
- DEBUG(0, ("add_smbpwd_entry: ERROR failed to ftruncate file %s. \
-Error was %s. Password file may be corrupt ! Please examine by hand !\n",
- pwd->smb_name, strerror(errno)));
- }
-
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- fclose(fp);
- pw_file_unlock(lockfd);
- return True;
-}
-/*
- * Routine to search the smbpasswd file for an entry matching the username.
- * and then modify its password entry
- */
-BOOL mod_smbpwd_entry(struct smb_passwd* pwd)
-{
- /* Static buffers we will return. */
- static pstring user_name;
-
- char linebuf[256];
- char readbuf[16 * 1024];
- unsigned char c;
- char ascii_p16[66];
- unsigned char *p = NULL;
- long linebuf_len = 0;
- FILE *fp;
- int lockfd;
- char *pfile = lp_smb_passwd_file();
- BOOL found_entry = False;
-
- long pwd_seekpos = 0;
-
- int i;
- int wr_len;
- int fd;
-
- if (!*pfile)
- {
- DEBUG(0, ("No SMB password file set\n"));
- return False;
- }
- DEBUG(10, ("mod_smbpwd_entry: opening file %s\n", pfile));
-
- fp = fopen(pfile, "r+");
-
- if (fp == NULL)
- {
- DEBUG(0, ("mod_smbpwd_entry: unable to open file %s\n", pfile));
- return False;
- }
- /* Set a 16k buffer to do more efficient reads */
- setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
-
- if ((lockfd = pw_file_lock(pfile, F_RDLCK | F_WRLCK, 5)) < 0)
- {
- DEBUG(0, ("mod_smbpwd_entry: unable to lock file %s\n", pfile));
- fclose(fp);
- return False;
- }
- /* make sure it is only rw by the owner */
- chmod(pfile, 0600);
-
- /* We have a write lock on the file. */
- /*
- * Scan the file, a line at a time and check if the name matches.
- */
- while (!feof(fp))
- {
- pwd_seekpos = ftell(fp);
-
- linebuf[0] = '\0';
-
- fgets(linebuf, 256, fp);
- if (ferror(fp))
- {
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- /*
- * Check if the string is terminated with a newline - if not
- * then we must keep reading and discard until we get one.
- */
- linebuf_len = strlen(linebuf);
- if (linebuf[linebuf_len - 1] != '\n')
- {
- c = '\0';
- while (!ferror(fp) && !feof(fp))
- {
- c = fgetc(fp);
- if (c == '\n')
- {
- break;
- }
- }
- }
- else
- {
- linebuf[linebuf_len - 1] = '\0';
- }
-
-#ifdef DEBUG_PASSWORD
- DEBUG(100, ("mod_smbpwd_entry: got line |%s|\n", linebuf));
-#endif
-
- if ((linebuf[0] == 0) && feof(fp))
- {
- DEBUG(4, ("mod_smbpwd_entry: end of file reached\n"));
- break;
- }
-
- /*
- * The line we have should be of the form :-
- *
- * username:uid:[32hex bytes]:....other flags presently
- * ignored....
- *
- * or,
- *
- * username:uid:[32hex bytes]:[32hex bytes]:....ignored....
- *
- * if Windows NT compatible passwords are also present.
- */
-
- if (linebuf[0] == '#' || linebuf[0] == '\0')
- {
- DEBUG(6, ("mod_smbpwd_entry: skipping comment or blank line\n"));
- continue;
- }
-
- p = (unsigned char *) strchr(linebuf, ':');
-
- if (p == NULL)
- {
- DEBUG(0, ("mod_smbpwd_entry: malformed password entry (no :)\n"));
- continue;
- }
-
- /*
- * As 256 is shorter than a pstring we don't need to check
- * length here - if this ever changes....
- */
- strncpy(user_name, linebuf, PTR_DIFF(p, linebuf));
- user_name[PTR_DIFF(p, linebuf)] = '\0';
- if (strequal(user_name, pwd->smb_name))
- {
- found_entry = True;
- break;
- }
- }
-
- if (!found_entry) return False;
-
- DEBUG(6, ("mod_smbpwd_entry: entry exists\n"));
-
- /* User name matches - get uid and password */
- p++; /* Go past ':' */
-
- if (!isdigit(*p))
- {
- DEBUG(0, ("mod_smbpwd_entry: malformed password entry (uid not number)\n"));
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- while (*p && isdigit(*p))
- p++;
- if (*p != ':')
- {
- DEBUG(0, ("mod_smbpwd_entry: malformed password entry (no : after uid)\n"));
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
- /*
- * Now get the password value - this should be 32 hex digits
- * which are the ascii representations of a 16 byte string.
- * Get two at a time and put them into the password.
- */
- p++;
-
- /* record exact password position */
- pwd_seekpos += PTR_DIFF(p, linebuf);
-
- if (*p == '*' || *p == 'X')
- {
- /* Password deliberately invalid - end here. */
- DEBUG(10, ("get_smbpwd_entry: entry invalidated for user %s\n", user_name));
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- if (linebuf_len < (PTR_DIFF(p, linebuf) + 33))
- {
- DEBUG(0, ("mod_smbpwd_entry: malformed password entry (passwd too short)\n"));
- fclose(fp);
- pw_file_unlock(lockfd);
- return (False);
- }
-
- if (p[32] != ':')
- {
- DEBUG(0, ("mod_smbpwd_entry: malformed password entry (no terminating :)\n"));
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- if (*p == '*' || *p == 'X')
- {
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
- if (!strncasecmp((char *) p, "NO PASSWORD", 11))
- {
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- /* Now check if the NT compatible password is
- available. */
- p += 33; /* Move to the first character of the line after
- the lanman password. */
- if (linebuf_len < (PTR_DIFF(p, linebuf) + 33))
- {
- DEBUG(0, ("mod_smbpwd_entry: malformed password entry (passwd too short)\n"));
- fclose(fp);
- pw_file_unlock(lockfd);
- return (False);
- }
-
- if (p[32] != ':')
- {
- DEBUG(0, ("mod_smbpwd_entry: malformed password entry (no terminating :)\n"));
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- if (*p == '*' || *p == 'X')
- {
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- /* whew. entry is correctly formed. */
-
- /*
- * Do an atomic write into the file at the position defined by
- * seekpos.
- */
-
- /* The mod user write needs to be atomic - so get the fd from
- the fp and do a raw write() call.
- */
-
- fd = fileno(fp);
-
- if (lseek(fd, pwd_seekpos - 1, SEEK_SET) != pwd_seekpos - 1)
- {
- DEBUG(1, ("mod_smbpwd_entry: seek fail on file %s.\n", pfile));
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- /* Sanity check - ensure the character is a ':' */
- if (read(fd, &c, 1) != 1)
- {
- DEBUG(1, ("mod_smbpwd_entry: read fail on file %s.\n", pfile));
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- if (c != ':')
- {
- DEBUG(1, ("mod_smbpwd_entry: check on passwd file %s failed.\n", pfile));
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- /* Create the 32 byte representation of the new p16 */
- for (i = 0; i < 16; i++)
- {
- sprintf(&ascii_p16[i*2], "%02X", (uchar) pwd->smb_passwd[i]);
- }
- if (pwd->smb_nt_passwd != NULL)
- {
- /* Add on the NT md4 hash */
- ascii_p16[32] = ':';
- for (i = 0; i < 16; i++)
- {
- sprintf(&ascii_p16[(i*2)+33], "%02X", (uchar) pwd->smb_nt_passwd[i]);
- }
- wr_len = 65;
- }
- else
- {
- wr_len = 32;
- }
-
-#ifdef DEBUG_PASSWORD
- DEBUG(100,("mod_smbpwd_entry: "));
- dump_data(100, ascii_p16, wr_len);
-#endif
-
- if (write(fd, ascii_p16, wr_len) != wr_len)
- {
- DEBUG(1, ("mod_smbpwd_entry: write failed in passwd file %s\n", pfile));
- fclose(fp);
- pw_file_unlock(lockfd);
- return False;
- }
-
- fclose(fp);
- pw_file_unlock(lockfd);
- return True;
-}
diff --git a/source/printing/pcap.c b/source/printing/pcap.c
index ff0a2b54772..65195ab1af6 100644
--- a/source/printing/pcap.c
+++ b/source/printing/pcap.c
@@ -7,8 +7,6 @@
Re-working by Martin Kiff, 1994
Re-written again by Andrew Tridgell
-
- Modified for SVID support by Norm Jacobs, 1997
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
@@ -51,9 +49,6 @@
* Opening a pipe for "lpc status" and reading that would probably
* be pretty effective. Code to do this already exists in the freely
* distributable PCNFS server code.
- *
- * Modified to call SVID/XPG4 support if printcap name is set to "lpstat"
- * in smb.conf under Solaris.
*/
#include "includes.h"
@@ -260,17 +255,10 @@ BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname)
DEBUG(0,( "No printcap file name configured!\n"));
return(False);
}
-
-#ifdef SYSV
- if (strequal(psz, "lpstat"))
- return (sysv_printername_ok(pszPrintername));
-#endif
-
#ifdef AIX
if (strlocate(psz,"/qconfig") != NULL)
return(ScanQconfig(psz,pszPrintername));
#endif
-
if ((pfile = fopen(psz, "r")) == NULL)
{
DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
@@ -304,6 +292,7 @@ BOOL pcap_printername_ok(char *pszPrintername, char *pszPrintcapname)
}
}
+
fclose(pfile);
return(False);
}
@@ -328,13 +317,6 @@ void pcap_printer_fn(void (*fn)())
return;
}
-#ifdef SYSV
- if (strequal(psz, "lpstat")) {
- sysv_printer_fn(fn);
- return;
- }
-#endif
-
#ifdef AIX
if (strlocate(psz,"/qconfig") != NULL)
{
@@ -342,7 +324,6 @@ void pcap_printer_fn(void (*fn)())
return;
}
#endif
-
if ((pfile = fopen(psz, "r")) == NULL)
{
DEBUG(0,( "Unable to open printcap file %s for read!\n", psz));
diff --git a/source/printing/print_svid.c b/source/printing/print_svid.c
deleted file mode 100644
index 5b98036e08e..00000000000
--- a/source/printing/print_svid.c
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 1997 by Norm Jacobs, Colorado Springs, Colorado, USA
- * Copyright (C) 1997 by Sun Microsystem, Inc.
- * All Rights Reserved
- *
- * 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.
- */
-
-/*
- * This module implements support for gathering and comparing available
- * printer information on a SVID or XPG4 compliant system. It does this
- * through the use of the SVID/XPG4 command "lpstat(1)".
- *
- * The expectations is that execution of the command "lpstat -v" will
- * generate responses in the form of:
- *
- * device for serial: /dev/term/b
- * system for fax: server
- * system for color: server (as printer chroma)
- */
-
-
-#include "includes.h"
-#include "smb.h"
-
-#ifdef SYSV
-
-extern int DEBUGLEVEL;
-
-typedef struct printer {
- char *name;
- struct printer *next;
-} printer_t;
-static printer_t *printers = NULL;
-
-static void populate_printers()
-{
- FILE *fp;
-
- if ((fp = popen("/usr/bin/lpstat -v", "r")) != NULL) {
- char buf[BUFSIZ];
-
- while (fgets(buf, sizeof (buf), fp) != NULL) {
- printer_t *ptmp;
- char *name, *tmp;
-
- /* eat "system/device for " */
- if (((tmp = strchr(buf, ' ')) == NULL) ||
- ((tmp = strchr(++tmp, ' ')) == NULL))
- continue;
- name = tmp++;
-
- /* truncate the ": ..." */
- if ((tmp = strchr(name, ':')) != NULL)
- *tmp = NULL;
-
- /* add it to the cache */
- if ((ptmp = malloc(sizeof (*ptmp))) != NULL) {
- memset(ptmp, NULL, sizeof (*ptmp));
- ptmp->name = strdup(name);
- ptmp->next = printers;
- printers = ptmp;
- }
- }
- pclose(fp);
- } else {
- DEBUG(0,( "Unable to run lpstat!\n"));
- }
-}
-
-
-/*
- * provide the equivalent of pcap_printer_fn() for SVID/XPG4 conforming
- * systems. It was unclear why pcap_printer_fn() was tossing names longer
- * than 8 characters. I suspect that its a protocol limit, but amazingly
- * names longer than 8 characters appear to work with my test
- * clients (Win95/NT).
- */
-void sysv_printer_fn(void (*fn)())
-{
- printer_t *tmp;
-
- if (printers == NULL)
- populate_printers();
- for (tmp = printers; tmp != NULL; tmp = tmp->next)
- (fn)(tmp->name, "");
-}
-
-
-/*
- * provide the equivalent of pcap_printername_ok() for SVID/XPG4 conforming
- * systems.
- */
-int sysv_printername_ok(char *name)
-{
- printer_t *tmp;
-
- if (printers == NULL)
- populate_printers();
- for (tmp = printers; tmp != NULL; tmp = tmp->next)
- if (strcmp(tmp->name, name) == 0)
- return (True);
- return (False);
-}
-
-#else
-/* this keeps fussy compilers happy */
- void print_svid_dummy(void) {}
-#endif
diff --git a/source/printing/printing.c b/source/printing/printing.c
index ccca91a2531..51fd3a992eb 100644
--- a/source/printing/printing.c
+++ b/source/printing/printing.c
@@ -832,7 +832,7 @@ static BOOL parse_lpq_entry(int snum,char *line,
{
BOOL ret;
- switch (lp_printing(snum))
+ switch (lp_printing())
{
case PRINT_SYSV:
ret = parse_lpq_sysv(line,buf,first);
@@ -887,21 +887,18 @@ static BOOL parse_lpq_entry(int snum,char *line,
if (strstr(line,stat0_strings[i])) {
StrnCpy(status->message,line,sizeof(status->message)-1);
status->status=LPSTAT_OK;
- return ret;
}
case LPSTAT_STOPPED:
for (i=0; stat1_strings[i]; i++)
if (strstr(line,stat1_strings[i])) {
StrnCpy(status->message,line,sizeof(status->message)-1);
status->status=LPSTAT_STOPPED;
- return ret;
}
case LPSTAT_ERROR:
for (i=0; stat2_strings[i]; i++)
if (strstr(line,stat2_strings[i])) {
StrnCpy(status->message,line,sizeof(status->message)-1);
status->status=LPSTAT_ERROR;
- return ret;
}
break;
}
diff --git a/source/script/installcp.sh b/source/script/installcp.sh
deleted file mode 100755
index c4f917113bc..00000000000
--- a/source/script/installcp.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/sh
-LIBDIR=$1
-CODEPAGEDIR=$2
-BINDIR=$3
-
-shift
-shift
-shift
-
-echo Installing codepage files in $CODEPAGEDIR
-for d in $LIBDIR $CODEPAGEDIR; do
-if [ ! -d $d ]; then
-mkdir $d
-if [ ! -d $d ]; then
- echo Failed to make directory $d
- exit 1
-fi
-fi
-done
-
-for p in $*; do
- echo Creating codepage file $CODEPAGEDIR/codepage.$p from codepage_def.$p
- $BINDIR/make_smbcodepage c $p codepage_def.$p $CODEPAGEDIR/codepage.$p
-done
-
-
-cat << EOF
-======================================================================
-The code pages have been installed. You may uninstall them using the
-command "make uninstallcp" or make "uninstall" to uninstall binaries,
-man pages, shell scripts and code pages.
-======================================================================
-EOF
-
-exit 0
-
diff --git a/source/script/mkproto.awk b/source/script/mkproto.awk
index 1ccf2fb2b0a..f2b76f20c97 100644
--- a/source/script/mkproto.awk
+++ b/source/script/mkproto.awk
@@ -64,7 +64,7 @@ BEGIN {
next;
}
-!/^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^smb_shm_offset_t|^shm_offset_t|^enum remote_arch_types|arc4_key/ {
+!/^unsigned|^mode_t|^DIR|^user|^int|^char|^uint|^struct|^BOOL|^void|^time|^smb_shm_offset_t|^shm_offset_t|^enum remote_arch_types/ {
next;
}
diff --git a/source/script/smbtar b/source/script/smbtar
index dcf01edb208..a947476dc6b 100644
--- a/source/script/smbtar
+++ b/source/script/smbtar
@@ -88,7 +88,7 @@ while getopts rivl:b:d:N:s:p:x:u:Xt: c; do
server="$OPTARG"
;;
b) # specify [b]locksize
- blocksize="$OPTARG"
+ blocksize="blocksize $OPTARG"
case "$OPTARG" in
[0-9]*) ;;
*) echo >&2 "$0: Error, block size not numeric: -b $OPTARG"
diff --git a/source/script/uninstallcp.sh b/source/script/uninstallcp.sh
deleted file mode 100755
index bd7013c358f..00000000000
--- a/source/script/uninstallcp.sh
+++ /dev/null
@@ -1,33 +0,0 @@
-#!/bin/sh
-
-CPDIR=$1
-shift
-
-if [ ! -d $CPDIR ]; then
- echo Directory $CPDIR does not exist!
- echo Do a "make installcp" or "make install" first.
- exit 1
-fi
-
-for p in $*; do
- if [ ! -f $CPDIR/codepage.$p ]; then
- echo $CPDIR/codepage.$p does not exist!
- else
- echo Removing $CPDIR/codepage.$p
- rm -f $CPDIR/codepage.$p
- if [ -f $CPDIR/codepage.$p ]; then
- echo Cannot remove $CPDIR/codepage.$p... does $USER have privileges?
- fi
- fi
-done
-
-cat << EOF
-======================================================================
-The code pages have been uninstalled. You may reinstall them using
-the command "make installcp" or "make install" to install binaries,
-man pages, shell scripts and code pages. You may recover a previous version
-(if any with "make revert").
-======================================================================
-EOF
-
-exit 0
diff --git a/source/smbadduser b/source/smbadduser
deleted file mode 100755
index e4e1b273d14..00000000000
--- a/source/smbadduser
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/csh
-#
-# smbadduser - Written by Mike Zakharoff
-#
-unalias *
-set path = ($path /usr/local/samba/bin)
-
-set smbpasswd = /usr/local/samba/private/smbpasswd
-set user_map = /usr/local/samba/lib/users.map
-#
-# Set to site specific passwd command
-#
-#set passwd = "cat /etc/passwd"
-#set passwd = "niscat passwd.org_dir"
-set passwd = "ypcat passwd"
-
-set line = "----------------------------------------------------------"
-if ($#argv == 0) then
- echo $line
- echo "Written: Mike Zakharoff email: michael.j.zakharoff@boeing.com"
- echo ""
- echo " 1) Updates $smbpasswd"
- echo " 2) Updates $user_map"
- echo " 3) Executes smbpasswd for each new user"
- echo ""
- echo "smbadduser unixid:ntid unixid:ntid ..."
- echo ""
- echo "Example: smbadduser zak:zakharoffm johns:smithj"
- echo $line
- exit 1
-endif
-
-touch $smbpasswd $user_map
-set new = ()
-foreach one ($argv)
- echo $one | grep ':' >& /dev/null
- if ($status != 0) then
- echo "ERROR: Must use unixid:ntid like -> zak:zakharoffm"
- continue
- endif
- set unix = `echo $one | awk -F: '{print $1}'`
- set ntid = `echo $one | awk -F: '{print $2}'`
-
- set usr = `eval $passwd | awk -F: '$1==USR {print $1}' USR=$unix`
- if ($#usr != 1) then
- echo "ERROR: $unix Not in passwd database SKIPPING..."
- continue
- endif
- set tmp = `cat $smbpasswd | awk -F: '$1==USR {print $1}' USR=$unix`
- if ($#tmp != 0) then
- echo "ERROR: $unix is already in $smbpasswd SKIPPING..."
- continue
- endif
-
- echo "Adding: $unix to $smbpasswd"
- eval $passwd | \
- awk -F: '$1==USR { \
- printf( "%s:%s:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX:%s:%s:%s\n", $1, $3, $5, $6, $7) }' USR=$unix >> $smbpasswd
- if ($unix != $ntid) then
- echo "Adding: {$unix = $ntid} to $user_map"
- echo "$unix = $ntid" >> $user_map
- endif
- set new = ($new $unix)
-end
-
-#
-# Enter password for new users
-#
-foreach one ($new)
- echo $line
- echo "ENTER password for $one"
- smbpasswd $one
-end
diff --git a/source/smbd/chgpasswd.c b/source/smbd/chgpasswd.c
index 17401410cec..bed81138b24 100644
--- a/source/smbd/chgpasswd.c
+++ b/source/smbd/chgpasswd.c
@@ -124,15 +124,15 @@ static int dochild(int master,char *slavedev, char *name, char *passwordprogram)
slavedev));
return(False);
}
-#if defined(SVR4) || defined(SUNOS5) || defined(SCO)
+#if defined(SVR4) || defined(SUNOS5)
ioctl(slave, I_PUSH, "ptem");
ioctl(slave, I_PUSH, "ldterm");
-#else /* defined(SVR4) || defined(SUNOS5) || defined(SCO) */
+#else /* defined(SVR4) || defined(SUNOS5) */
if (ioctl(slave,TIOCSCTTY,0) <0) {
DEBUG(3,("Error in ioctl call for slave pty\n"));
/* return(False); */
}
-#endif /* defined(SVR4) || defined(SUNOS5) || defined(SCO) */
+#endif /* defined(SVR4) || defined(SUNOS5) */
/* Close master. */
close(master);
diff --git a/source/smbd/dir.c b/source/smbd/dir.c
index c12305499a5..567bc14424e 100644
--- a/source/smbd/dir.c
+++ b/source/smbd/dir.c
@@ -470,12 +470,12 @@ BOOL get_dir_entry(int cnum,char *mask,int dirtype,char *fname,int *size,int *mo
if (isrootdir && (strequal(filename,"..") || strequal(filename,".")))
continue;
- pstrcpy(fname,filename);
+ strcpy(fname,filename);
*path = 0;
- pstrcpy(path,Connections[cnum].dirpath);
+ strcpy(path,Connections[cnum].dirpath);
if(needslash)
strcat(path,"/");
- pstrcpy(pathreal,path);
+ strcpy(pathreal,path);
strcat(path,fname);
strcat(pathreal,dname);
if (sys_stat(pathreal,&sbuf) != 0)
@@ -628,133 +628,97 @@ int TellDir(void *p)
}
-/* -------------------------------------------------------------------------- **
- * This section manages a global directory cache.
- * (It should probably be split into a separate module. crh)
- * -------------------------------------------------------------------------- **
- */
+static int dir_cache_size = 0;
+static struct dir_cache {
+ struct dir_cache *next;
+ struct dir_cache *prev;
+ char *path;
+ char *name;
+ char *dname;
+ int snum;
+} *dir_cache = NULL;
-typedef struct
- {
- ubi_dlNode node;
- char *path;
- char *name;
- char *dname;
- int snum;
- } dir_cache_entry;
-
-static ubi_dlList dir_cache[1] = { { NULL, NULL, 0 } };
-
-void DirCacheAdd( char *path, char *name, char *dname, int snum )
- /* ------------------------------------------------------------------------ **
- * Add an entry to the directory cache.
- *
- * Input: path -
- * name -
- * dname -
- * snum -
- *
- * Output: None.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- int pathlen;
- int namelen;
- dir_cache_entry *entry;
-
- /* Allocate the structure & string space in one go so that it can be freed
- * in one call to free().
- */
- pathlen = strlen( path ) +1; /* Bytes required to store path (with nul). */
- namelen = strlen( name ) +1; /* Bytes required to store name (with nul). */
- entry = (dir_cache_entry *)malloc( sizeof( dir_cache_entry )
- + pathlen
- + namelen
- + strlen( dname ) +1 );
- if( NULL == entry ) /* Not adding to the cache is not fatal, */
- return; /* so just return as if nothing happened. */
-
- /* Set pointers correctly and load values. */
- entry->path = strcpy( (char *)&entry[1], path);
- entry->name = strcpy( &(entry->path[pathlen]), name);
- entry->dname = strcpy( &(entry->name[namelen]), dname);
- entry->snum = snum;
-
- /* Add the new entry to the linked list. */
- (void)ubi_dlAddHead( dir_cache, entry );
- DEBUG( 4, ("Added dir cache entry %s %s -> %s\n", path, name, dname ) );
-
- /* Free excess cache entries. */
- while( DIRCACHESIZE < dir_cache->count )
- free( ubi_dlRemTail( dir_cache ) );
-
- } /* DirCacheAdd */
-
-
-char *DirCacheCheck( char *path, char *name, int snum )
- /* ------------------------------------------------------------------------ **
- * Search for an entry to the directory cache.
- *
- * Input: path -
- * name -
- * snum -
- *
- * Output: The dname string of the located entry, or NULL if the entry was
- * not found.
- *
- * Notes: This uses a linear search, which is is okay because of
- * the small size of the cache. Use a splay tree or hash
- * for large caches.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- dir_cache_entry *entry;
+/*******************************************************************
+add an entry to the directory cache
+********************************************************************/
+void DirCacheAdd(char *path,char *name,char *dname,int snum)
+{
+ int count;
+ struct dir_cache *entry = (struct dir_cache *)malloc(sizeof(*entry));
+ if (!entry) return;
+ entry->path = strdup(path);
+ entry->name = strdup(name);
+ entry->dname = strdup(dname);
+ entry->snum = snum;
+ if (!entry->path || !entry->name || !entry->dname) return;
+
+ entry->next = dir_cache;
+ entry->prev = NULL;
+ if (entry->next) entry->next->prev = entry;
+ dir_cache = entry;
+
+ DEBUG(4,("Added dir cache entry %s %s -> %s\n",path,name,dname));
+
+ if (dir_cache_size == DIRCACHESIZE) {
+ for (entry=dir_cache, count=1;
+ entry->next && count < dir_cache_size + 1;
+ entry=entry->next, count++) ;
+ if (entry->next || count != dir_cache_size + 1) {
+ DEBUG(0,("DirCache bug - please report %d %d\n",dir_cache_size,count));
+ }
+ free(entry->path);
+ free(entry->name);
+ free(entry->dname);
+ if (entry->prev) entry->prev->next = entry->next;
+ free(entry);
+ } else {
+ dir_cache_size++;
+ }
+}
- for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache );
- NULL != entry;
- entry = (dir_cache_entry *)ubi_dlNext( entry ) )
- {
- if( entry->snum == snum
- && 0 == strcmp( name, entry->name )
- && 0 == strcmp( path, entry->path ) )
- {
- DEBUG(4, ("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname));
- return( entry->dname );
- }
+
+/*******************************************************************
+check for an entry in the directory cache
+********************************************************************/
+char *DirCacheCheck(char *path,char *name,int snum)
+{
+ struct dir_cache *entry;
+
+ for (entry=dir_cache; entry; entry=entry->next) {
+ if (entry->snum == snum &&
+ strcmp(path,entry->path) == 0 &&
+ strcmp(name,entry->name) == 0) {
+ DEBUG(4,("Got dir cache hit on %s %s -> %s\n",path,name,entry->dname));
+ return(entry->dname);
}
+ }
return(NULL);
- } /* DirCacheCheck */
-
-void DirCacheFlush( int snum )
- /* ------------------------------------------------------------------------ **
- * Remove all cache entries which have an snum that matches the input.
- *
- * Input: snum -
- *
- * Output: None.
- *
- * ------------------------------------------------------------------------ **
- */
- {
- dir_cache_entry *entry;
- ubi_dlNodePtr next;
+}
- for( entry = (dir_cache_entry *)ubi_dlFirst( dir_cache ); NULL != entry; )
- {
- next = ubi_dlNext( entry );
- if( entry->snum == snum )
- free( ubi_dlRemThis( dir_cache, entry ) );
- entry = (dir_cache_entry *)next;
+/*******************************************************************
+flush entries in the dir_cache
+********************************************************************/
+void DirCacheFlush(int snum)
+{
+ struct dir_cache *entry,*next;
+
+ for (entry=dir_cache; entry; entry=next) {
+ if (entry->snum == snum) {
+ free(entry->path);
+ free(entry->dname);
+ free(entry->name);
+ next = entry->next;
+ if (entry->prev) entry->prev->next = entry->next;
+ if (entry->next) entry->next->prev = entry->prev;
+ if (dir_cache == entry) dir_cache = entry->next;
+ free(entry);
+ dir_cache_size--;
+ } else {
+ next = entry->next;
}
- } /* DirCacheFlush */
-
-/* -------------------------------------------------------------------------- **
- * End of the section that manages the global directory cache.
- * -------------------------------------------------------------------------- **
- */
+ }
+}
#ifdef REPLACE_GETWD
diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c
index 50ad831eb30..c63a54c2ac2 100644
--- a/source/smbd/ipc.c
+++ b/source/smbd/ipc.c
@@ -52,6 +52,8 @@ extern fstring myworkgroup;
#define ERROR_INVALID_LEVEL 124
#define ERROR_MORE_DATA 234
+#define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
+
#define ACCESS_READ 0x01
#define ACCESS_WRITE 0x02
#define ACCESS_CREATE 0x04
@@ -62,8 +64,6 @@ extern fstring myworkgroup;
#define QNLEN 12 /* queue name maximum length */
extern int Client;
-extern int oplock_sock;
-extern int smb_read_error;
static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
@@ -146,12 +146,7 @@ static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
-#ifdef CONFUSE_NETMONITOR_MSRPC_DECODING
- /* if you don't want Net Monitor to decode your packets, do this!!! */
- align = ((this_lparam+1)%4);
-#else
align = (this_lparam%4);
-#endif
set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
if (this_lparam)
@@ -445,7 +440,7 @@ static void PackDriverData(struct pack_desc* desc)
}
static int check_printq_info(struct pack_desc* desc,
- int uLevel, char *id1, char *id2)
+ int uLevel, char *id1, const char* id2)
{
desc->subformat = NULL;
switch( uLevel ) {
@@ -469,10 +464,6 @@ static int check_printq_info(struct pack_desc* desc,
case 5:
desc->format = "z";
break;
- case 52:
- desc->format = "WzzzzzzzzN";
- desc->subformat = "z";
- break;
default: return False;
}
if (strcmp(desc->format,id1) != 0) return False;
@@ -532,18 +523,11 @@ static void fill_printq_info(int cnum, int snum, int uLevel,
int count, print_queue_struct* queue,
print_status_struct* status)
{
- switch (uLevel) {
- case 1:
- case 2:
- PACKS(desc,"B13",SERVICE(snum));
- break;
- case 3:
- case 4:
- case 5:
- PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
- break;
+ if (uLevel < 3) {
+ PACKS(desc,"B13",SERVICE(snum));
+ } else {
+ PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
}
-
if (uLevel == 1 || uLevel == 2) {
PACKS(desc,"B",""); /* alignment */
PACKI(desc,"W",5); /* priority */
@@ -591,119 +575,10 @@ static void fill_printq_info(int cnum, int snum, int uLevel,
for (i=0;i<count;i++)
fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
}
-
- if (uLevel==52) {
- int i,ok=0;
- pstring tok,driver,short_name;
- char *p,*q;
- FILE *f;
- pstring fname;
-
- strcpy(fname,lp_driverfile());
-
- f=fopen(fname,"r");
- if (!f) {
- DEBUG(0,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
- }
-
- p=(char *)malloc(8192*sizeof(char));
- bzero(p, 8192*sizeof(char));
- q=p;
-
- /* lookup the long printer driver name in the file description */
- while (f && !feof(f) && !ok)
- {
- fgets(p,8191,f);
- p[strlen(p)-1]='\0';
- next_token(&p,tok,":");
- if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1;
- }
-
- fclose(f);
-
- next_token(&p,short_name,":");
- next_token(&p,driver,":");
-
- PACKI(desc,"W",0x0400); /* don't know */
- PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
-
- if (ok)
- {
- PACKS(desc,"z",driver); /* Driver Name */
- PACKS(desc,"z",short_name); /* short printer name */
- DEBUG(3,("Driver:%s:\n",driver));
- DEBUG(3,("short name:%s:\n",short_name));
- }
- else
- {
- PACKS(desc,"z","");
- PACKS(desc,"z","");
- }
-
- PACKS(desc,"z","");
- PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
- PACKS(desc,"z","EMF");
- PACKS(desc,"z","");
- if (ok)
- PACKS(desc,"z",driver); /* driver name */
- else
- PACKS(desc,"z","");
- PACKI(desc,"N",count); /* number of files to copy */
- for (i=0;i<count;i++)
- {
- next_token(&p,tok,",");
- PACKS(desc,"z",tok); /* driver files to copy */
- DEBUG(3,("file:%s:\n",tok));
- }
- free(q);
- }
-
+
DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
}
-/* This function returns the number of file for a given driver */
-int get_printerdrivernumber(int snum)
-{
- int i=0,ok=0;
- pstring tok;
- char *p,*q;
- FILE *f;
- pstring fname;
-
- strcpy(fname,lp_driverfile());
-
- DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
- f=fopen(fname,"r");
- if (!f) {
- DEBUG(0,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
- return(0);
- }
-
- p=(char *)malloc(8192*sizeof(char));
- q=p; /* need it to free memory because p change ! */
-
- /* lookup the long printer driver name in the file description */
- while (!feof(f) && !ok)
- {
- fgets(p,8191,f);
- next_token(&p,tok,":");
- if(!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))) ok=1;
- }
-
- if (ok) {
- /* skip 2 fields */
- next_token(&p,tok,":"); /* short name */
- next_token(&p,tok,":"); /* driver name */
- /* count the number of files */
- while (next_token(&p,tok,","))
- i++;
- }
- fclose(f);
- free(q);
-
- return(i);
-}
-
static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
int mdrcnt,int mprcnt,
char **rdata,char **rparam,
@@ -749,14 +624,7 @@ static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
if (snum < 0 || !VALID_SNUM(snum)) return(False);
- if (uLevel==52)
- {
- count = get_printerdrivernumber(snum);
- DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
- }
- else
- count = get_printqueue(snum,cnum,&queue,&status);
-
+ count = get_printqueue(snum,cnum,&queue,&status);
if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
desc.base = *rdata;
desc.buflen = mdrcnt;
@@ -1733,19 +1601,17 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
name[l] = 0;
DEBUG(3,("Setting print name to %s\n",name));
-
- become_root(True);
+ become_root(1);
+
for (i=0;i<MAX_OPEN_FILES;i++)
if (Files[i].open && Files[i].print_file)
{
pstring wd;
- int fcnum = Files[i].cnum;
GetWd(wd);
- unbecome_user();
- if (!become_user(&Connections[fcnum], fcnum,vuid) ||
- !become_service(fcnum,True))
+ if (!become_user(Files[i].cnum,vuid) ||
+ !become_service(Files[i].cnum,True))
break;
if (sys_rename(Files[i].name,name) == 0)
@@ -1753,7 +1619,7 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
break;
}
- unbecome_root(True);
+ unbecome_root(1);
}
desc.errcode=NERR_Success;
@@ -2132,6 +1998,9 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
/* get NIS home of a previously validated user - simeon */
user_struct *vuser = get_valid_user_struct(vuid);
DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
+#if (defined(NETGROUP) && defined(AUTOMOUNT))
+ DEBUG(3,(" HOMESHR for %s is %s\n", vuser->name, vuser->home_share));
+#endif
*rparam_len = 6;
*rparam = REALLOC(*rparam,*rparam_len);
@@ -2189,17 +2058,29 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
{
SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
- SIVALS(p,usri11_password_age,-1); /* password age */
+ SIVALS(p,usri11_password_age,0xffffffff); /* password age */
SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
- strcpy(p2, lp_logon_path());
+ if (*lp_logon_path())
+ {
+ strcpy(p2,lp_logon_path());
+ }
+ else
+ {
+#if (defined(NETGROUP) && defined(AUTOMOUNT))
+ strcpy(p2, vuser->home_share);
+#else
+ strcpy(p2,"\\\\%L\\%U");
+#endif
+ }
+ standard_sub_basic(p2);
p2 = skip_string(p2,1);
SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
strcpy(p2,"");
p2 = skip_string(p2,1);
SIVAL(p,usri11_last_logon,0); /* last logon */
SIVAL(p,usri11_last_logoff,0); /* last logoff */
- SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
- SSVALS(p,usri11_num_logons,-1); /* num logons */
+ SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */
+ SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */
SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
strcpy(p2,"\\\\*");
p2 = skip_string(p2,1);
@@ -2209,7 +2090,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
strcpy(p2,"");
p2 = skip_string(p2,1);
- SIVALS(p,usri11_max_storage,-1); /* max storage */
+ SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */
SSVAL(p,usri11_units_per_week,168); /* units per week */
SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
@@ -2227,7 +2108,19 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
SSVAL(p,42,
Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
- strcpy(p2,lp_logon_path());
+ if (*lp_logon_path())
+ {
+ strcpy(p2,lp_logon_path());
+ }
+ else
+ {
+#if (defined(NETGROUP) && defined(AUTOMOUNT))
+ strcpy(p2, vuser->home_share);
+#else
+ strcpy(p2,"\\\\%L\\%U");
+#endif
+ }
+ standard_sub_basic(p2);
p2 = skip_string(p2,1);
SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
*p2++ = 0;
@@ -2331,7 +2224,6 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
int uLevel;
struct pack_desc desc;
char* name;
- char* logon_script;
uLevel = SVAL(p,0);
name = p + 2;
@@ -2374,14 +2266,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
PACKS(&desc,"z",mypath); /* computer */
}
PACKS(&desc,"z",myworkgroup);/* domain */
-
-/* JHT - By calling lp_logon_script() and standard_sub() we have */
-/* made sure all macros are fully substituted and available */
- logon_script = lp_logon_script();
- standard_sub( cnum, logon_script );
- PACKS(&desc,"z", logon_script); /* script path */
-/* End of JHT mods */
-
+ PACKS(&desc,"z",lp_logon_script()); /* script path */
PACKI(&desc,"D",0x00000000); /* reserved */
}
@@ -2869,25 +2754,14 @@ static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
struct
{
char * name;
- char * pipe_clnt_name;
-#ifdef NTDOMAIN
- char * pipe_srv_name;
-#endif
+ char * pipename;
int subcommand;
BOOL (*fn) ();
} api_fd_commands [] =
{
-#ifdef NTDOMAIN
- { "TransactNmPipe", "lsarpc", "lsass", 0x26, api_ntLsarpcTNP },
- { "TransactNmPipe", "samr", "lsass", 0x26, api_samrTNP },
- { "TransactNmPipe", "srvsvc", "lsass", 0x26, api_srvsvcTNP },
- { "TransactNmPipe", "wkssvc", "ntsvcs", 0x26, api_wkssvcTNP },
- { "TransactNmPipe", "NETLOGON", "NETLOGON", 0x26, api_netlogrpcTNP },
- { NULL, NULL, NULL, -1, (BOOL (*)())api_Unsupported }
-#else
- { "TransactNmPipe" , "lsarpc", 0x26, api_LsarpcTNP },
+ { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
+ { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP },
{ NULL, NULL, -1, (BOOL (*)())api_Unsupported }
-#endif
};
/****************************************************************************
@@ -2901,17 +2775,11 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
char *rparam = NULL;
int rdata_len = 0;
int rparam_len = 0;
-
- BOOL reply = False;
- BOOL bind_req = False;
- BOOL set_nphs = False;
-
+ BOOL reply=False;
int i;
int fd;
int subcommand;
- char *pipe_name;
- DEBUG(5,("api_fd_reply\n"));
/* First find out the name of this file. */
if (suwcnt != 2)
{
@@ -2922,113 +2790,46 @@ static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
/* Get the file handle and hence the file name. */
fd = setup[1];
subcommand = setup[0];
- pipe_name = get_rpc_pipe_hnd_name(fd);
-
- if (pipe_name == NULL)
- {
- DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", fd));
- }
-
- DEBUG(3,("Got API command %d on pipe %s (fd %x)",
- subcommand, pipe_name, fd));
- DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
- tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
- for (i = 0; api_fd_commands[i].name; i++)
- {
- if (strequal(api_fd_commands[i].pipe_clnt_name, pipe_name) &&
- api_fd_commands[i].subcommand == subcommand &&
- api_fd_commands[i].fn)
- {
- DEBUG(3,("Doing %s\n", api_fd_commands[i].name));
- break;
- }
- }
-
- rdata = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024);
- rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
+ DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
+ DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
+ tdscnt,tpscnt,mdrcnt,mprcnt));
-#ifdef NTDOMAIN
- /* RPC Pipe command 0x26. */
- if (data != NULL && api_fd_commands[i].subcommand == 0x26)
- {
- RPC_HDR hdr;
-
- /* process the rpc header */
- char *q = smb_io_rpc_hdr(True, &hdr, data, data, 4, 0);
-
- /* bind request received */
- if ((bind_req = ((q != NULL) && (hdr.pkt_type == RPC_BIND))))
- {
- RPC_HDR_RB hdr_rb;
-
- /* decode the bind request */
- char *p = smb_io_rpc_hdr_rb(True, &hdr_rb, q, data, 4, 0);
-
- if ((bind_req = (p != NULL)))
+ for (i=0;api_fd_commands[i].name;i++)
+ if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
+ api_fd_commands[i].subcommand == subcommand &&
+ api_fd_commands[i].fn)
{
- RPC_HDR_BA hdr_ba;
- fstring ack_pipe_name;
-
- /* name has to be \PIPE\xxxxx */
- strcpy(ack_pipe_name, "\\PIPE\\");
- strcat(ack_pipe_name, api_fd_commands[i].pipe_srv_name);
-
- /* make a bind acknowledgement */
- make_rpc_hdr_ba(&hdr_ba,
- hdr_rb.bba.max_tsize, hdr_rb.bba.max_rsize, hdr_rb.bba.assoc_gid,
- ack_pipe_name,
- 0x1, 0x0, 0x0,
- &(hdr_rb.transfer));
-
- p = smb_io_rpc_hdr_ba(False, &hdr_ba, rdata + 0x10, rdata, 4, 0);
-
- rdata_len = PTR_DIFF(p, rdata);
-
- make_rpc_hdr(&hdr, RPC_BINDACK, 0x0, hdr.call_id, rdata_len);
-
- p = smb_io_rpc_hdr(False, &hdr, rdata, rdata, 4, 0);
-
- reply = (p != NULL);
+ DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
+ break;
}
- }
- }
-#endif
-
- /* Set Named Pipe Handle state */
- if (subcommand == 0x1)
- {
- set_nphs = True;
- reply = api_LsarpcSNPHS(fd, cnum, params);
- }
-
- if (!bind_req && !set_nphs)
- {
- DEBUG(10,("calling api_fd_command\n"));
-
- reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
+
+ rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
+ rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
+
+ reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
&rdata,&rparam,&rdata_len,&rparam_len);
- DEBUG(10,("called api_fd_command\n"));
- }
-
- if (rdata_len > mdrcnt || rparam_len > mprcnt)
- {
- reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
+
+ if (rdata_len > mdrcnt ||
+ rparam_len > mprcnt)
+ {
+ reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
&rdata,&rparam,&rdata_len,&rparam_len);
- }
+ }
+
/* if we get False back then it's actually unsupported */
if (!reply)
- {
api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
&rdata,&rparam,&rdata_len,&rparam_len);
- }
/* now send the reply */
send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
- if (rdata ) free(rdata );
- if (rparam) free(rparam);
+ if (rdata)
+ free(rdata);
+ if (rparam)
+ free(rparam);
return(-1);
}
@@ -3181,31 +2982,25 @@ static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
int suwcnt,int tdscnt,int tpscnt,
int msrcnt,int mdrcnt,int mprcnt)
{
- DEBUG(3,("named pipe command on <%s> name\n", name));
- if (strequal(name,"LANMAN"))
- {
- return api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
- }
+ if (strequal(name,"LANMAN"))
+ return(api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
- if (strlen(name) < 1)
- {
- return api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
- }
+if (strlen(name) < 1)
+ return(api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
- if (setup)
- {
- DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
- }
- return 0;
+ DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
+ name,(int)setup[0],(int)setup[1]));
+
+ return(0);
}
/****************************************************************************
reply to a SMBtrans
****************************************************************************/
-int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
+int reply_trans(char *inbuf,char *outbuf)
{
fstring name;
@@ -3229,7 +3024,6 @@ int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
int dsoff = SVAL(inbuf,smb_vwv12);
int suwcnt = CVAL(inbuf,smb_vwv13);
- bzero(name, sizeof(name));
fstrcpy(name,smb_buf(inbuf));
if (dscnt > tdscnt || pscnt > tpscnt) {
@@ -3268,18 +3062,12 @@ int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
/* receive the rest of the trans packet */
while (pscnt < tpscnt || dscnt < tdscnt)
{
- BOOL ret;
int pcnt,poff,dcnt,doff,pdisp,ddisp;
- ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,SMB_SECONDARY_WAIT);
-
- if ((ret && (CVAL(inbuf, smb_com) != SMBtrans)) || !ret)
+ if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
+ CVAL(inbuf, smb_com) != SMBtrans)
{
- if(ret)
- DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
- else
- DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
- (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
+ DEBUG(2,("Invalid secondary trans2 packet\n"));
if (params) free(params);
if (data) free(data);
if (setup) free(setup);
@@ -3314,18 +3102,11 @@ int reply_trans(char *inbuf,char *outbuf, int size, int bufsize)
DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
+
if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
- {
- DEBUG(5,("calling named_pipe\n"));
outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
- }
- else
- {
- DEBUG(3,("invalid pipe name\n"));
- outsize = 0;
- }
if (data) free(data);
diff --git a/source/smbd/mangle.c b/source/smbd/mangle.c
index bf264757155..66e8233df28 100644
--- a/source/smbd/mangle.c
+++ b/source/smbd/mangle.c
@@ -26,33 +26,27 @@ extern int case_default;
extern BOOL case_mangle;
/****************************************************************************
- * Provide a checksum on a string
- *
- * Input: s - the nul-terminated character string for which the checksum
- * will be calculated.
- * Output: The checksum value calculated for s.
- *
- ****************************************************************************/
+provide a checksum on a string
+****************************************************************************/
int str_checksum(char *s)
- {
+{
int res = 0;
int c;
int i=0;
-
- while( *s )
+ while (*s)
{
- c = *s;
- res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
- s++; i++;
+ c = *s;
+ res ^= (c << (i % 15)) ^ (c >> (15-(i%15)));
+ s++; i++;
}
return(res);
- } /* str_checksum */
+}
/****************************************************************************
return True if a name is a special msdos reserved name
****************************************************************************/
static BOOL is_reserved_msdos(char *fname)
- {
+{
char upperFname[13];
char *p;
@@ -78,7 +72,7 @@ static BOOL is_reserved_msdos(char *fname)
return (True) ;
return (False);
- } /* is_reserved_msdos */
+}
@@ -86,37 +80,34 @@ static BOOL is_reserved_msdos(char *fname)
return True if a name is in 8.3 dos format
****************************************************************************/
BOOL is_8_3(char *fname, BOOL check_case)
- {
+{
int len;
char *dot_pos;
char *slash_pos = strrchr(fname,'/');
int l;
- if( slash_pos )
- fname = slash_pos+1;
+ if (slash_pos) fname = slash_pos+1;
len = strlen(fname);
DEBUG(5,("checking %s for 8.3\n",fname));
- if( check_case && case_mangle )
- {
+ if (check_case && case_mangle)
switch (case_default)
{
case CASE_LOWER:
- if (strhasupper(fname)) return(False);
- break;
+ if (strhasupper(fname)) return(False);
+ break;
case CASE_UPPER:
- if (strhaslower(fname)) return(False);
- break;
+ if (strhaslower(fname)) return(False);
+ break;
}
- }
/* can't be longer than 12 chars */
- if( len == 0 || len > 12 )
+ if (len == 0 || len > 12)
return(False);
/* can't be an MS-DOS Special file such as lpt1 or even lpt1.txt */
- if( is_reserved_msdos(fname) )
+ if (is_reserved_msdos(fname))
return(False);
/* can't contain invalid dos chars */
@@ -130,218 +121,180 @@ BOOL is_8_3(char *fname, BOOL check_case)
dot_pos = strchr(fname,'.');
- {
+ {
char *p = fname;
-
- if(lp_client_code_page() == KANJI_CODEPAGE)
+#ifdef KANJI
+ dot_pos = 0;
+ while (*p)
{
- dot_pos = 0;
- while (*p)
- {
- if (is_shift_jis (*p))
- p += 2;
- else if (is_kana (*p))
- p ++;
- else
- {
- if (*p == '.' && !dot_pos)
- dot_pos = (char *) p;
- if (!isdoschar(*p))
- return(False);
- p++;
- }
- }
+ if (is_shift_jis (*p)) {
+ p += 2;
+ } else if (is_kana (*p)) {
+ p ++;
+ } else {
+ if (*p == '.' && !dot_pos)
+ dot_pos = (char *) p;
+ if (!isdoschar(*p))
+ return(False);
+ p++;
+ }
}
- else
+#else
+ while (*p)
{
- while (*p)
- {
- if (!isdoschar(*p))
- return(False);
- p++;
- }
- }
- }
+ if (!isdoschar(*p))
+ return(False);
+ p++;
+ }
+#endif /* KANJI */
+ }
/* no dot and less than 9 means OK */
if (!dot_pos)
return(len <= 8);
-
+
l = PTR_DIFF(dot_pos,fname);
/* base must be at least 1 char except special cases . and .. */
- if( l == 0 )
+ if (l == 0)
return(strcmp(fname,".") == 0 || strcmp(fname,"..") == 0);
/* base can't be greater than 8 */
- if( l > 8 )
+ if (l > 8)
return(False);
- if( lp_strip_dot() &&
+ if (lp_strip_dot() &&
len - l == 1 &&
- !strchr(dot_pos+1,'.') )
+ !strchr(dot_pos+1,'.'))
{
- *dot_pos = 0;
- return(True);
+ *dot_pos = 0;
+ return(True);
}
/* extension must be between 1 and 3 */
- if( (len - l < 2 ) || (len - l > 4) )
+ if ( (len - l < 2 ) || (len - l > 4) )
return(False);
/* extension can't have a dot */
- if( strchr(dot_pos+1,'.') )
+ if (strchr(dot_pos+1,'.'))
return(False);
/* must be in 8.3 format */
return(True);
- } /* is_8_3 */
-
-/* -------------------------------------------------------------------------- **
- * This section creates and maintains a stack of name mangling results.
- * The original comments read: "keep a stack of name mangling results - just
- * so file moves and copies have a chance of working" (whatever that means).
- *
- * There are three functions to manage the stack:
- * reset_mangled_stack() -
- * push_mangled_name() -
- * check_mangled_stack() -
- */
+}
+
+
+/*
+keep a stack of name mangling results - just
+so file moves and copies have a chance of working
+*/
fstring *mangled_stack = NULL;
int mangled_stack_size = 0;
int mangled_stack_len = 0;
/****************************************************************************
- * create the mangled stack CRH
- ****************************************************************************/
-void reset_mangled_stack( int size )
- {
- if( mangled_stack )
- {
- free(mangled_stack);
- mangled_stack_size = 0;
- mangled_stack_len = 0;
- }
-
- if( size > 0 )
+create the mangled stack
+****************************************************************************/
+void create_mangled_stack(int size)
+{
+ if (mangled_stack)
{
- mangled_stack = (fstring *)malloc( sizeof(fstring) * size );
- if( mangled_stack )
- mangled_stack_size = size;
+ free(mangled_stack);
+ mangled_stack_size = 0;
+ mangled_stack_len = 0;
}
- else
- mangled_stack = NULL;
- } /* create_mangled_stack */
+ if (size > 0)
+ mangled_stack = (fstring *)malloc(sizeof(fstring)*size);
+ if (mangled_stack) mangled_stack_size = size;
+}
/****************************************************************************
- * push a mangled name onto the stack CRH
- ****************************************************************************/
+push a mangled name onto the stack
+****************************************************************************/
static void push_mangled_name(char *s)
- {
+{
int i;
char *p;
- /* If the stack doesn't exist... Fail. */
- if( !mangled_stack )
+ if (!mangled_stack)
return;
- /* If name <s> is already on the stack, move it to the top. */
- for( i=0; i<mangled_stack_len; i++ )
- {
- if( strcmp( s, mangled_stack[i] ) == 0 )
+ for (i=0;i<mangled_stack_len;i++)
+ if (strcmp(s,mangled_stack[i]) == 0)
{
- array_promote( mangled_stack[0],sizeof(fstring), i );
- return;
+ array_promote(mangled_stack[0],sizeof(fstring),i);
+ return;
}
- }
- /* If name <s> wasn't already there, add it to the top of the stack. */
- memmove( mangled_stack[1], mangled_stack[0],
- sizeof(fstring) * MIN(mangled_stack_len, mangled_stack_size-1) );
- strcpy( mangled_stack[0], s );
- mangled_stack_len = MIN( mangled_stack_size, mangled_stack_len+1 );
-
- /* Hmmm...
- * Find the last dot '.' in the name,
- * if there are any upper case characters past the last dot
- * and there are no more than three characters past the last dot
- * then terminate the name *at* the last dot.
- */
- p = strrchr( mangled_stack[0], '.' );
- if( p && (!strhasupper(p+1)) && (strlen(p+1) < (size_t)4) )
+ memmove(mangled_stack[1],mangled_stack[0],
+ sizeof(fstring)*MIN(mangled_stack_len,mangled_stack_size-1));
+ strcpy(mangled_stack[0],s);
+ p = strrchr(mangled_stack[0],'.');
+ if (p && (!strhasupper(p+1)) && (strlen(p+1) < 4))
*p = 0;
-
- } /* push_mangled_name */
+ mangled_stack_len = MIN(mangled_stack_size,mangled_stack_len+1);
+}
/****************************************************************************
- * check for a name on the mangled name stack CRH
- ****************************************************************************/
+check for a name on the mangled name stack
+****************************************************************************/
BOOL check_mangled_stack(char *s)
- {
+{
int i;
pstring tmpname;
char extension[5];
- char *p = strrchr( s, '.' );
+ char *p = strrchr(s,'.');
BOOL check_extension = False;
extension[0] = 0;
- /* If the stack doesn't exist, fail. */
- if( !mangled_stack )
- return(False);
+ if (!mangled_stack) return(False);
- /* If there is a file extension, then we need to play with it, too. */
- if( p )
+ if (p)
{
- check_extension = True;
- StrnCpy( extension, p, 4 );
- strlower( extension ); /* XXXXXXX */
+ check_extension = True;
+ StrnCpy(extension,p,4);
+ strlower(extension); /* XXXXXXX */
}
- for( i=0; i<mangled_stack_len; i++ )
+ for (i=0;i<mangled_stack_len;i++)
{
- strcpy(tmpname,mangled_stack[i]);
- mangle_name_83(tmpname);
- if( strequal(tmpname,s) )
- {
- strcpy(s,mangled_stack[i]);
- break;
- }
- if( check_extension && !strchr(mangled_stack[i],'.') )
- {
- pstrcpy(tmpname,mangled_stack[i]);
- strcat(tmpname,extension);
+ strcpy(tmpname,mangled_stack[i]);
mangle_name_83(tmpname);
- if( strequal(tmpname,s) )
- {
- strcpy(s,mangled_stack[i]);
- strcat(s,extension);
- break;
- }
- }
+ if (strequal(tmpname,s))
+ {
+ strcpy(s,mangled_stack[i]);
+ break;
+ }
+ if (check_extension && !strchr(mangled_stack[i],'.'))
+ {
+ pstrcpy(tmpname,mangled_stack[i]);
+ strcat(tmpname,extension);
+ mangle_name_83(tmpname);
+ if (strequal(tmpname,s))
+ {
+ strcpy(s,mangled_stack[i]);
+ strcat(s,extension);
+ break;
+ }
+ }
}
- if( i < mangled_stack_len )
+ if (i < mangled_stack_len)
{
- DEBUG(3,("Found %s on mangled stack as %s\n",s,mangled_stack[i]));
- array_promote(mangled_stack[0],sizeof(fstring),i);
- return(True);
+ DEBUG(3,("Found %s on mangled stack as %s\n",s,mangled_stack[i]));
+ array_promote(mangled_stack[0],sizeof(fstring),i);
+ return(True);
}
return(False);
- } /* check_mangled_stack */
-
-
-/* End of the mangled stack section.
- * -------------------------------------------------------------------------- **
- */
-
+}
-static char *map_filename( char *s, /* This is null terminated */
- char *pattern, /* This isn't. */
- int len ) /* This is the length of pattern. */
- {
+static char *map_filename(char *s, /* This is null terminated */
+ char *pattern, /* This isn't. */
+ int len) /* This is the length of pattern. */
+{
static pstring matching_bit; /* The bit of the string which matches */
/* a * in pattern if indeed there is a * */
char *sp; /* Pointer into s. */
@@ -350,68 +303,57 @@ static char *map_filename( char *s, /* This is null terminated */
pstring pat;
StrnCpy(pat, pattern, len); /* Get pattern into a proper string! */
- pstrcpy(matching_bit,""); /* Match but no star gets this. */
+ pstrcpy(matching_bit,""); /* Match but no star gets this. */
pp = pat; /* Initialise the pointers. */
sp = s;
- if( (len == 1) && (*pattern == '*') )
- {
+ if ((len == 1) && (*pattern == '*')) {
return NULL; /* Impossible, too ambiguous for */
- } /* words! */
+ /* words! */
+ }
while ((*sp) /* Not the end of the string. */
&& (*pp) /* Not the end of the pattern. */
&& (*sp == *pp) /* The two match. */
- && (*pp != '*')) /* No wildcard. */
- {
+ && (*pp != '*')) { /* No wildcard. */
sp++; /* Keep looking. */
pp++;
- }
-
- if( !*sp && !*pp ) /* End of pattern. */
- return( matching_bit ); /* Simple match. Return empty string. */
-
- if (*pp == '*')
- {
+ }
+ if (!*sp && !*pp) /* End of pattern. */
+ return matching_bit; /* Simple match. Return empty string. */
+ if (*pp == '*') {
pp++; /* Always interrested in the chacter */
/* after the '*' */
- if (!*pp) /* It is at the end of the pattern. */
- {
+ if (!*pp) { /* It is at the end of the pattern. */
StrnCpy(matching_bit, s, sp-s);
return matching_bit;
- }
- else
- {
+ } else {
/* The next character in pattern must match a character further */
/* along s than sp so look for that character. */
match_start = sp;
- while( (*sp) /* Not the end of s. */
+ while ((*sp) /* Not the end of s. */
&& (*sp != *pp)) /* Not the same */
sp++; /* Keep looking. */
- if (!*sp) /* Got to the end without a match. */
- {
+ if (!*sp) { /* Got to the end without a match. */
return NULL;
- } /* Still hope for a match. */
- else
- {
+ } else { /* Still hope for a match. */
/* Now sp should point to a matching character. */
StrnCpy(matching_bit, match_start, sp-match_start);
/* Back to needing a stright match again. */
- while( (*sp) /* Not the end of the string. */
+ while ((*sp) /* Not the end of the string. */
&& (*pp) /* Not the end of the pattern. */
- && (*sp == *pp) ) /* The two match. */
- {
+ && (*sp == *pp)) { /* The two match. */
sp++; /* Keep looking. */
pp++;
- }
+ }
if (!*sp && !*pp) /* Both at end so it matched */
return matching_bit;
else
return NULL;
- }
}
}
+ }
return NULL; /* No match. */
- } /* map_filename */
+}
/* this is the magic char used for mangling */
@@ -419,24 +361,22 @@ char magic_char = '~';
/****************************************************************************
-return True if the name could be a mangled name
+determine whther is name could be a mangled name
****************************************************************************/
-BOOL is_mangled( char *s )
- {
+BOOL is_mangled(char *s)
+{
char *m = strchr(s,magic_char);
+ if (!m) return(False);
- if( !m )
- return(False);
-
- /* we use two base 36 chars before the extension */
- if( m[1] == '.' || m[1] == 0 ||
+ /* we use two base 36 chars efore the extension */
+ if (m[1] == '.' || m[1] == 0 ||
m[2] == '.' || m[2] == 0 ||
- (m[3] != '.' && m[3] != 0) )
- return( is_mangled(m+1) );
+ (m[3] != '.' && m[3] != 0))
+ return(is_mangled(m+1));
/* it could be */
return(True);
- } /* is_mangled */
+}
@@ -444,14 +384,14 @@ BOOL is_mangled( char *s )
return a base 36 character. v must be from 0 to 35.
****************************************************************************/
static char base36(unsigned int v)
- {
+{
static char basechars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return basechars[v % 36];
- } /* base36 */
+}
static void do_fwd_mangled_map(char *s, char *MangledMap)
- {
+{
/* MangledMap is a series of name pairs in () separated by spaces.
* If s matches the first of the pair then the name given is the
* second of the pair. A * means any number of any character and if
@@ -471,8 +411,7 @@ static void do_fwd_mangled_map(char *s, char *MangledMap)
char *np; /* Points into new_string. */
DEBUG(5,("Mangled Mapping '%s' map '%s'\n", s, MangledMap));
- while (*start)
- {
+ while (*start) {
while ((*start) && (*start != '('))
start++;
if (!*start)
@@ -482,14 +421,12 @@ static void do_fwd_mangled_map(char *s, char *MangledMap)
DEBUG(5,("Start of first in pair '%s'\n", start));
while ((*end) && !((*end == ' ') || (*end == ')')))
end++;
- if (!*end)
- {
+ if (!*end) {
start = end;
continue; /* Always check for the end. */
- }
+ }
DEBUG(5,("End of first in pair '%s'\n", end));
- if ((match_string = map_filename(s, start, end-start)))
- {
+ if ((match_string = map_filename(s, start, end-start))) {
DEBUG(5,("Found a match\n"));
/* Found a match. */
start = end+1; /* Point to start of what it is to become. */
@@ -500,13 +437,11 @@ static void do_fwd_mangled_map(char *s, char *MangledMap)
&& (*end != ')') /* Not the end of the pattern. */
&& (*end != '*')) /* Not a wildcard. */
*np++ = *end++;
- if (!*end)
- {
+ if (!*end) {
start = end;
continue; /* Always check for the end. */
- }
- if (*end == '*')
- {
+ }
+ if (*end == '*') {
pstrcpy(np, match_string);
np += strlen(match_string);
end++; /* Skip the '*' */
@@ -514,28 +449,27 @@ static void do_fwd_mangled_map(char *s, char *MangledMap)
&& (*end != ')') /* Not the end of the pattern. */
&& (*end != '*')) /* Not a wildcard. */
*np++ = *end++;
- }
- if (!*end)
- {
+ }
+ if (!*end) {
start = end;
continue; /* Always check for the end. */
- }
+ }
*np++ = '\0'; /* NULL terminate it. */
DEBUG(5,("End of second in pair '%s'\n", end));
pstrcpy(s, new_string); /* Substitute with the new name. */
DEBUG(5,("s is now '%s'\n", s));
- }
+ }
start = end; /* Skip a bit which cannot be wanted */
/* anymore. */
start++;
- }
- } /* do_fwd_mangled_map */
+ }
+}
/****************************************************************************
do the actual mangling to 8.3 format
****************************************************************************/
void mangle_name_83(char *s)
- {
+{
int csum = str_checksum(s);
char *p;
char extension[4];
@@ -547,127 +481,114 @@ void mangle_name_83(char *s)
base[0]=0;
p = strrchr(s,'.');
- if( p && (strlen(p+1) < (size_t)4) )
+ if (p && (strlen(p+1)<4) )
{
- BOOL all_normal = (strisnormal(p+1)); /* XXXXXXXXX */
-
- if (all_normal && p[1] != 0)
- {
- *p = 0;
- csum = str_checksum(s);
- *p = '.';
- }
+ BOOL all_normal = (strisnormal(p+1)); /* XXXXXXXXX */
+ if (all_normal && p[1] != 0)
+ {
+ *p = 0;
+ csum = str_checksum(s);
+ *p = '.';
+ }
}
+
strupper(s);
DEBUG(5,("Mangling name %s to ",s));
- if( p )
+ if (p)
{
- if (p == s)
- strcpy(extension,"___");
- else
- {
- *p++ = 0;
- while (*p && extlen < 3)
- {
- if(lp_client_code_page() == KANJI_CODEPAGE)
- {
- if (is_shift_jis (*p))
- {
- if (extlen < 2)
- {
- extension[extlen++] = p[0];
- extension[extlen++] = p[1];
- }
- else
- {
- extension[extlen++] = base36 (((unsigned char) *p) % 36);
- }
- p += 2;
- }
- else
- {
- if( is_kana (*p) )
- {
- extension[extlen++] = p[0];
- p++;
- }
- else
- {
- if (isdoschar (*p) && *p != '.')
- extension[extlen++] = p[0];
- p++;
- }
- }
- }
- else
- {
- if (isdoschar(*p) && *p != '.')
- extension[extlen++] = *p;
- p++;
- }
- }
- extension[extlen] = 0;
- }
+ if (p == s)
+ strcpy(extension,"___");
+ else
+ {
+ *p++ = 0;
+ while (*p && extlen < 3)
+ {
+#ifdef KANJI
+ if (is_shift_jis (*p))
+ {
+ if (extlen < 2)
+ {
+ extension[extlen++] = p[0];
+ extension[extlen++] = p[1];
+ }
+ else
+ {
+ extension[extlen++] = base36 (((unsigned char) *p) % 36);
+ }
+ p += 2;
+ }
+ else if (is_kana (*p))
+ {
+ extension[extlen++] = p[0];
+ p++;
+ }
+ else
+ {
+ if (isdoschar (*p) && *p != '.')
+ extension[extlen++] = p[0];
+ p++;
+ }
+#else
+ if (isdoschar(*p) && *p != '.')
+ extension[extlen++] = *p;
+ p++;
+#endif /* KANJI */
+ }
+ extension[extlen] = 0;
+ }
}
p = s;
while (*p && baselen < 5)
{
- if(lp_client_code_page() == KANJI_CODEPAGE)
- {
+#ifdef KANJI
if (is_shift_jis (*p))
- {
- if (baselen < 4)
- {
- base[baselen++] = p[0];
- base[baselen++] = p[1];
- }
- else
- {
- base[baselen++] = base36 (((unsigned char) *p) % 36);
- }
- p += 2;
- }
- else
- {
- if( is_kana (*p) )
- {
- base[baselen++] = p[0];
- p++;
- }
- else
- {
- if (isdoschar (*p) && *p != '.')
- base[baselen++] = p[0];
- p++;
- }
- }
- }
- else
- {
+ {
+ if (baselen < 4)
+ {
+ base[baselen++] = p[0];
+ base[baselen++] = p[1];
+ }
+ else
+ {
+ base[baselen++] = base36 (((unsigned char) *p) % 36);
+ }
+ p += 2;
+ }
+ else if (is_kana (*p))
+ {
+ base[baselen++] = p[0];
+ p++;
+ }
+ else
+ {
+ if (isdoschar (*p) && *p != '.')
+ base[baselen++] = p[0];
+ p++;
+ }
+#else
if (isdoschar(*p) && *p != '.')
- base[baselen++] = *p;
+ base[baselen++] = *p;
p++;
- }
+#endif /* KANJI */
}
base[baselen] = 0;
csum = csum % (36*36);
- sprintf(s,"%s%c%c%c",base,magic_char,base36(csum/36),base36(csum%36));
+ sprintf(s,"%s%c%c%c",base,magic_char,base36(csum/36),base36(csum%36));
- if( *extension )
+ if (*extension)
{
- strcat(s,".");
- strcat(s,extension);
+ strcat(s,".");
+ strcat(s,extension);
}
DEBUG(5,("%s\n",s));
-
- } /* mangle_name_83 */
+}
@@ -675,74 +596,65 @@ void mangle_name_83(char *s)
work out if a name is illegal, even for long names
******************************************************************/
static BOOL illegal_name(char *name)
- {
+{
static unsigned char illegal[256];
static BOOL initialised=False;
unsigned char *s;
- if( !initialised )
- {
+ if (!initialised) {
char *ill = "*\\/?<>|\":";
initialised = True;
bzero((char *)illegal,256);
- for( s = (unsigned char *)ill; *s; s++ )
+ for (s = (unsigned char *)ill; *s; s++)
illegal[*s] = True;
- }
+ }
- if(lp_client_code_page() == KANJI_CODEPAGE)
- {
- for (s = (unsigned char *)name; *s;)
- {
- if (is_shift_jis (*s))
- s += 2;
- else
- {
- if (illegal[*s])
- return(True);
- else
- s++;
- }
- }
- }
- else
- {
- for (s = (unsigned char *)name;*s;s++)
- if (illegal[*s]) return(True);
+#ifdef KANJI
+ for (s = (unsigned char *)name; *s;) {
+ if (is_shift_jis (*s)) {
+ s += 2;
+ } else if (illegal[*s]) {
+ return(True);
+ } else {
+ s++;
}
+ }
+#else
+ for (s = (unsigned char *)name;*s;s++)
+ if (illegal[*s]) return(True);
+#endif
+
return(False);
- } /* illegal_name */
+}
/****************************************************************************
convert a filename to DOS format. return True if successful.
****************************************************************************/
BOOL name_map_mangle(char *OutName,BOOL need83,int snum)
- {
+{
#ifdef MANGLE_LONG_FILENAMES
- if( !need83 && illegal_name(OutName) )
- need83 = True;
+ if (!need83 && illegal_name(OutName)) need83 = True;
#endif
/* apply any name mappings */
{
- char *map = lp_mangled_map(snum);
-
- if (map && *map)
- do_fwd_mangled_map(OutName,map);
+ char *map = lp_mangled_map(snum);
+ if (map && *map)
+ do_fwd_mangled_map(OutName,map);
}
/* check if it's already in 8.3 format */
- if( need83 && !is_8_3(OutName, True) )
- {
- if( !lp_manglednames(snum) )
- return(False);
+ if (need83 && !is_8_3(OutName, True)) {
+ if (!lp_manglednames(snum)) return(False);
/* mangle it into 8.3 */
push_mangled_name(OutName);
mangle_name_83(OutName);
- }
+ }
return(True);
- } /* name_map_mangle */
+}
+
diff --git a/source/smbd/password.c b/source/smbd/password.c
index 1c72f0cfa6e..0d9db08dd98 100644
--- a/source/smbd/password.c
+++ b/source/smbd/password.c
@@ -36,6 +36,7 @@ static char this_user[100]="";
static char this_salt[100]="";
static char this_crypted[100]="";
+#ifdef SMB_PASSWD
/* Data to do lanman1/2 password challenge. */
static unsigned char saved_challenge[8];
static BOOL challenge_sent=False;
@@ -45,24 +46,17 @@ Get the next challenge value - no repeats.
********************************************************************/
void generate_next_challenge(char *challenge)
{
- unsigned char buf[16];
- static int counter = 0;
- struct timeval tval;
- int v1,v2;
-
- /* get a sort-of random number */
- GetTimeOfDay(&tval);
- v1 = (counter++) + getpid() + tval.tv_sec;
- v2 = (counter++) * getpid() + tval.tv_usec;
- SIVAL(challenge,0,v1);
- SIVAL(challenge,4,v2);
-
- /* mash it up with md4 */
- mdfour(buf, (unsigned char *)challenge, 8);
-
- memcpy(saved_challenge, buf, 8);
- memcpy(challenge,buf,8);
- challenge_sent = True;
+ static int counter = 0;
+ struct timeval tval;
+ int v1,v2;
+ GetTimeOfDay(&tval);
+ v1 = (counter++) + getpid() + tval.tv_sec;
+ v2 = (counter++) * getpid() + tval.tv_usec;
+ SIVAL(challenge,0,v1);
+ SIVAL(challenge,4,v2);
+ E1((uchar *)challenge,(uchar *)"SAMBA",(uchar *)saved_challenge);
+ memcpy(challenge,saved_challenge,8);
+ challenge_sent = True;
}
/*******************************************************************
@@ -84,6 +78,7 @@ BOOL last_challenge(char *challenge)
memcpy(challenge,saved_challenge,8);
return(True);
}
+#endif
/* this holds info on user ids that are already validated for this VC */
static user_struct *validated_users = NULL;
@@ -96,10 +91,10 @@ tell random client vuid's (normally zero) from valid vuids.
****************************************************************************/
user_struct *get_valid_user_struct(uint16 vuid)
{
- if (vuid == UID_FIELD_INVALID)
+ if(vuid == UID_FIELD_INVALID)
return NULL;
vuid -= VUID_OFFSET;
- if ((vuid >= (uint16)num_validated_users) ||
+ if((vuid >= (uint16)num_validated_users) ||
(validated_users[vuid].uid == -1) || (validated_users[vuid].gid == -1))
return NULL;
return &validated_users[vuid];
@@ -111,28 +106,19 @@ invalidate a uid
void invalidate_vuid(uint16 vuid)
{
user_struct *vuser = get_valid_user_struct(vuid);
-
- if (vuser == NULL) return;
+ if(vuser == 0)
+ return;
vuser->uid = -1;
vuser->gid = -1;
-
- vuser->n_sids = 0;
-
- /* same number of igroups as groups as attrs */
- vuser->n_groups = 0;
-
- if (vuser->groups && (vuser->groups != (gid_t *)vuser->igroups))
- free(vuser->groups);
-
- if (vuser->igroups) free(vuser->igroups);
- if (vuser->attrs ) free(vuser->attrs);
- if (vuser->sids ) free(vuser->sids);
-
- vuser->attrs = NULL;
- vuser->sids = NULL;
- vuser->igroups = NULL;
- vuser->groups = NULL;
+ vuser->user_ngroups = 0;
+ if(vuser->user_groups &&
+ (vuser->user_groups != (gid_t *)vuser->user_igroups))
+ free(vuser->user_groups);
+ vuser->user_groups = NULL;
+ if(vuser->user_igroups)
+ free(vuser->user_igroups);
+ vuser->user_igroups = NULL;
}
@@ -142,7 +128,7 @@ return a validated username
char *validated_username(uint16 vuid)
{
user_struct *vuser = get_valid_user_struct(vuid);
- if (vuser == NULL)
+ if(vuser == 0)
return 0;
return(vuser->name);
}
@@ -155,12 +141,22 @@ tell random client vuid's (normally zero) from valid vuids.
uint16 register_vuid(int uid,int gid, char *name,BOOL guest)
{
user_struct *vuser;
+
+#if (defined(NETGROUP) && defined (AUTOMOUNT))
+ int nis_error; /* returned by yp all functions */
+ char *nis_result; /* yp_match inits this */
+ int nis_result_len; /* and set this */
+ char *nis_domain; /* yp_get_default_domain inits this */
+ char *nis_map = (char *)lp_nis_home_map_name();
+ int home_server_len;
+#endif
struct passwd *pwfile; /* for getting real name from passwd file */
+ int real_name_len;
#if 0
/*
* After observing MS-Exchange services writing to a Samba share
- * I belive this code is incorrect. Each service does its own
+ * I belive this code is incorrect. Each service does it's own
* sessionsetup_and_X for the same user, and as each service shuts
* down, it does a user_logoff_and_X. As we are consolidating multiple
* sessionsetup_and_X's onto the same vuid here, when the first service
@@ -173,7 +169,7 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest)
int i;
for(i = 0; i < num_validated_users; i++) {
vuser = &validated_users[i];
- if ( vuser->uid == uid )
+ if( vuser->uid == uid )
return (uint16)(i + VUID_OFFSET); /* User already validated */
}
#endif
@@ -197,31 +193,58 @@ uint16 register_vuid(int uid,int gid, char *name,BOOL guest)
vuser->guest = guest;
strcpy(vuser->name,name);
- vuser->n_sids = 0;
- vuser->sids = NULL;
-
- vuser->n_groups = 0;
- vuser->groups = NULL;
- vuser->igroups = NULL;
- vuser->attrs = NULL;
+ vuser->user_ngroups = 0;
+ vuser->user_groups = NULL;
+ vuser->user_igroups = NULL;
/* Find all the groups this uid is in and store them.
Used by become_user() */
setup_groups(name,uid,gid,
- &vuser->n_groups,
- &vuser->igroups,
- &vuser->groups,
- &vuser->attrs);
+ &vuser->user_ngroups,
+ &vuser->user_igroups,
+ &vuser->user_groups);
DEBUG(3,("uid %d registered to name %s\n",uid,name));
+#if (defined(NETGROUP) && defined (AUTOMOUNT))
+ vuser->home_share = NULL;
+ DEBUG(3, ("Setting default HOMESHR to: \\\\logon server\\HOMES\n"));
+ vuser->home_share = Realloc(vuser->home_share, 32);
+ strcpy(vuser->home_share,"\\\\%L\\HOMES");
+
+ if (nis_error = yp_get_default_domain(&nis_domain))
+ DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
+ DEBUG(3, ("NIS Domain: %s\n", nis_domain));
+
+ if (nis_error = yp_match(nis_domain, nis_map, vuser->name, strlen(vuser->name),
+ &nis_result, &nis_result_len))
+ DEBUG(3, ("YP Error: %s\n", yperr_string(nis_error)));
+ if (!nis_error && lp_nis_home_map()) {
+ home_server_len = strcspn(nis_result,":");
+ DEBUG(3, ("NIS lookup succeeded\n\tHome server length: %d\n",home_server_len));
+ vuser->home_share = (char *)Realloc(vuser->home_share, home_server_len+12);
+ DEBUG(3, ("\tAllocated %d bytes for HOMESHR\n",home_server_len+12 ));
+ strcpy(vuser->home_share,"\\\\");
+ strncat(vuser->home_share, nis_result, home_server_len);
+ strcat(vuser->home_share,"\\homes");
+ DEBUG(2,("\tUser = %s\n\tUID = %d\n\tNIS result = %s\n\tHOMESHR = %s\n",
+ vuser->name, vuser->uid, nis_result, vuser->home_share));
+ }
+#endif
+
+ vuser->real_name = NULL;
DEBUG(3, ("Clearing default real name\n"));
- fstrcpy(vuser->real_name, "<Full Name>\0");
+ vuser->real_name = Realloc(vuser->real_name, 15);
+ strcpy(vuser->real_name, "<Full Name>\0");
if (lp_unix_realname()) {
- if ((pwfile=getpwnam(vuser->name))!= NULL)
+ if((pwfile=getpwnam(vuser->name))!= NULL)
{
DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->name,pwfile->pw_gecos));
- fstrcpy(vuser->real_name, pwfile->pw_gecos);
+ real_name_len = strcspn(pwfile->pw_gecos, ",");
+ DEBUG(3, ("Real name length: %d\n", real_name_len));
+ vuser->real_name = (char *)Realloc(vuser->real_name, real_name_len+1);
+ strncpy(vuser->real_name, pwfile->pw_gecos, real_name_len);
+ vuser->real_name[real_name_len]='\0';
}
}
@@ -378,7 +401,7 @@ static char *PAM_password;
* echo off means password.
*/
static int PAM_conv (int num_msg,
- struct pam_message **msg,
+ const struct pam_message **msg,
struct pam_response **resp,
void *appdata_ptr) {
int replies = 0;
@@ -674,7 +697,7 @@ static int linux_bigcrypt(char *password,char *salt1, char *crypted)
for ( i=strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) {
char * p = crypt(password,salt) + 2;
- if (strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0)
+ if(strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0)
return(0);
password += LINUX_PASSWORD_SEG_CHARS;
crypted += strlen(p);
@@ -781,10 +804,6 @@ Hence we make a direct return to avoid a second chance!!!
return(linux_bigcrypt(password,this_salt,this_crypted));
#endif
-#ifdef HPUX_10_TRUSTED
- return(bigcrypt(password,this_salt,this_crypted));
-#endif
-
#ifdef NO_CRYPT
DEBUG(1,("Warning - no crypt available\n"));
return(False);
@@ -793,6 +812,7 @@ Hence we make a direct return to avoid a second chance!!!
#endif
}
+#ifdef SMB_PASSWD
/****************************************************************************
core of smb password checking routine.
****************************************************************************/
@@ -802,10 +822,10 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha
unsigned char p21[21];
unsigned char p24[24];
- if (part_passwd == NULL)
+ if(part_passwd == NULL)
DEBUG(10,("No password set - allowing access\n"));
/* No password set - always true ! */
- if (part_passwd == NULL)
+ if(part_passwd == NULL)
return 1;
memset(p21,'\0',21);
@@ -834,6 +854,7 @@ BOOL smb_password_check(char *password, unsigned char *part_passwd, unsigned cha
#endif
return (memcmp(p24, password, 24) == 0);
}
+#endif
/****************************************************************************
check if a username/password is OK
@@ -843,16 +864,21 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd)
pstring pass2;
int level = lp_passwordlevel();
struct passwd *pass;
+#ifdef SMB_PASSWD
char challenge[8];
struct smb_passwd *smb_pass;
BOOL challenge_done = False;
+#endif
if (password) password[pwlen] = 0;
+#ifdef SMB_PASSWD
if (pwlen == 24)
challenge_done = last_challenge(challenge);
+#endif
#if DEBUG_PASSWORD
+#ifdef SMB_PASSWD
if (challenge_done)
{
int i;
@@ -860,9 +886,10 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd)
for( i = 0; i < 24; i++)
DEBUG(100,("%0x ", (unsigned char)password[i]));
DEBUG(100,("]\n"));
- } else {
- DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password));
}
+ else
+#endif
+ DEBUG(100,("checking user=[%s] pass=[%s]\n",user,password));
#endif
if (!password)
@@ -879,9 +906,11 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd)
else
pass = Get_Pwnam(user,True);
+#ifdef SMB_PASSWD
+
DEBUG(4,("SMB Password - pwlen = %d, challenge_done = %d\n", pwlen, challenge_done));
- if ((pwlen == 24) && challenge_done)
+ if((pwlen == 24) && challenge_done)
{
DEBUG(4,("Checking SMB password for user %s (l=24)\n",user));
@@ -891,30 +920,29 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd)
return(False);
}
- /* non-null username indicates search by username not smb userid */
- smb_pass = get_smbpwd_entry(user, 0);
- if (!smb_pass)
+ smb_pass = get_smbpwnam(user);
+ if(!smb_pass)
{
DEBUG(3,("Couldn't find user %s in smb_passwd file.\n", user));
return(False);
}
/* Ensure the uid's match */
- if (smb_pass->smb_userid != pass->pw_uid)
+ if(smb_pass->smb_userid != pass->pw_uid)
{
DEBUG(3,("Error : UNIX and SMB uids in password files do not match !\n"));
return(False);
}
- if (Protocol >= PROTOCOL_NT1)
+ if(Protocol >= PROTOCOL_NT1)
{
/* We have the NT MD4 hash challenge available - see if we can
use it (ie. does it exist in the smbpasswd file).
*/
- if (smb_pass->smb_nt_passwd != NULL)
+ if(smb_pass->smb_nt_passwd != NULL)
{
DEBUG(4,("Checking NT MD4 password\n"));
- if (smb_password_check(password,
+ if(smb_password_check(password,
smb_pass->smb_nt_passwd,
(unsigned char *)challenge))
{
@@ -936,6 +964,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd)
DEBUG(3,("Error smb_password_check failed\n"));
}
+#endif
DEBUG(4,("Checking password for user %s (l=%d)\n",user,pwlen));
@@ -1017,7 +1046,6 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd)
/* extract relevant info */
strcpy(this_user,pass->pw_name);
strcpy(this_salt,pass->pw_passwd);
- this_salt[2] = 0;
strcpy(this_crypted,pass->pw_passwd);
if (!*this_crypted) {
@@ -1058,7 +1086,7 @@ BOOL password_ok(char *user,char *password, int pwlen, struct passwd *pwd)
}
/* give up? */
- if (level < 1)
+ if(level < 1)
{
update_protected_database(user,False);
@@ -1479,7 +1507,6 @@ BOOL check_hosts_equiv(char *user)
return(False);
}
-
static struct cli_state cli;
/****************************************************************************
@@ -1565,6 +1592,7 @@ BOOL server_validate(char *user, char *domain,
char *ntpass, int ntpasslen)
{
extern fstring local_machine;
+ fstring share;
if (!cli.initialised) {
DEBUG(1,("password server %s is not connected\n", cli.desthost));
@@ -1583,13 +1611,14 @@ BOOL server_validate(char *user, char *domain,
}
- if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
+ sprintf(share,"\\\\%s\\IPC$", cli.desthost);
+
+ if (!cli_send_tconX(&cli, share, "IPC", "", 1)) {
DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost));
return False;
}
-#if USE_NETWKSTAUSERLOGON
if (!cli_NetWkstaUserLogon(&cli,user,local_machine)) {
DEBUG(1,("password server %s failed NetWkstaUserLogon\n", cli.desthost));
cli_tdis(&cli);
@@ -1609,7 +1638,6 @@ BOOL server_validate(char *user, char *domain,
cli_tdis(&cli);
return False;
}
-#endif
DEBUG(3,("password server %s accepted the password\n", cli.desthost));
@@ -1619,3 +1647,6 @@ BOOL server_validate(char *user, char *domain,
}
+
+
+
diff --git a/source/smbd/pipes.c b/source/smbd/pipes.c
index e2f704e6af9..2cc6eea506f 100644
--- a/source/smbd/pipes.c
+++ b/source/smbd/pipes.c
@@ -2,9 +2,7 @@
Unix SMB/Netbios implementation.
Version 1.9.
Pipe SMB reply routines
- Copyright (C) Andrew Tridgell 1992-1997,
- Copyright (C) Luke Kenneth Casson Leighton 1996-1997.
- Copyright (C) Paul Ashton 1997.
+ Copyright (C) Andrew Tridgell 1992-1997
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
@@ -37,35 +35,34 @@
/* look in server.c for some explanation of these variables */
extern int Protocol;
extern int DEBUGLEVEL;
+extern int chain_fnum;
extern char magic_char;
+extern connection_struct Connections[];
+extern files_struct Files[];
extern BOOL case_sensitive;
extern pstring sesssetup_user;
extern int Client;
extern fstring myworkgroup;
-#define VALID_PNUM(pnum) (((pnum) >= 0) && ((pnum) < MAX_OPEN_PIPES))
-#define OPEN_PNUM(pnum) (VALID_PNUM(pnum) && Pipes[pnum].open)
-#define PNUM_OK(pnum,c) (OPEN_PNUM(pnum) && (c)==Pipes[pnum].cnum)
-
-/* this macro should always be used to extract an pnum (smb_fid) from
- a packet to ensure chaining works correctly */
-#define GETPNUM(buf,where) (chain_pnum!= -1?chain_pnum:SVAL(buf,where))
+/* this macro should always be used to extract an fnum (smb_fid) from
+a packet to ensure chaining works correctly */
+#define GETFNUM(buf,where) (chain_fnum!= -1?chain_fnum:SVAL(buf,where))
char * known_pipes [] =
{
"lsarpc",
-#if NTDOMAIN
- "NETLOGON",
- "srvsvc",
- "wkssvc",
- "samr",
-#endif
NULL
};
/****************************************************************************
reply to an open and X on a named pipe
+ In fact what we do is to open a regular file with the same name in
+ /tmp. This can then be closed as normal. Reading and writing won't
+ make much sense, but will do *something*. The real reason for this
+ support is to be able to do transactions on them (well, on lsarpc
+ for domain login purposes...).
+
This code is basically stolen from reply_open_and_X with some
wrinkles to handle pipes.
****************************************************************************/
@@ -73,10 +70,21 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
{
pstring fname;
int cnum = SVAL(inbuf,smb_tid);
- int pnum = -1;
+ int fnum = -1;
+ int smb_mode = SVAL(inbuf,smb_vwv3);
+ int smb_attr = SVAL(inbuf,smb_vwv5);
+#if 0
+ int open_flags = SVAL(inbuf,smb_vwv2);
+ int smb_sattr = SVAL(inbuf,smb_vwv4);
+ uint32 smb_time = make_unix_date3(inbuf+smb_vwv6);
+#endif
int smb_ofun = SVAL(inbuf,smb_vwv8);
+ int unixmode;
int size=0,fmode=0,mtime=0,rmode=0;
+ struct stat sbuf;
+ int smb_action = 0;
int i;
+ BOOL bad_path = False;
/* XXXX we need to handle passed times, sattr and flags */
pstrcpy(fname,smb_buf(inbuf));
@@ -103,67 +111,97 @@ int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize)
/* Known pipes arrive with DIR attribs. Remove it so a regular file */
/* can be opened and add it in after the open. */
DEBUG(3,("Known pipe %s opening.\n",fname));
+ smb_attr &= ~aDIR;
+ Connections[cnum].read_only = 0;
smb_ofun |= 0x10; /* Add Create it not exists flag */
- pnum = open_rpc_pipe_hnd(fname, cnum);
- if (pnum < 0) return(ERROR(ERRSRV,ERRnofids));
+ unix_convert(fname,cnum,0,&bad_path);
+
+ fnum = find_free_file();
+ if (fnum < 0)
+ return(ERROR(ERRSRV,ERRnofids));
+
+ if (!check_name(fname,cnum))
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+
+ unixmode = unix_mode(cnum,smb_attr);
+
+ open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
+ &rmode,&smb_action);
+
+ if (!Files[fnum].open)
+ {
+ /* Change the error code if bad_path was set. */
+ if((errno == ENOENT) && bad_path)
+ {
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadpath;
+ }
+ return(UNIXERROR(ERRDOS,ERRnoaccess));
+ }
+
+ if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
+ close_file(fnum, 0);
+ return(ERROR(ERRDOS,ERRnoaccess));
+ }
+
+ size = sbuf.st_size;
+ fmode = dos_mode(cnum,fname,&sbuf);
+ mtime = sbuf.st_mtime;
+ if (fmode & aDIR) {
+ close_file(fnum, 0);
+ return(ERROR(ERRDOS,ERRnoaccess));
+ }
/* Prepare the reply */
set_message(outbuf,15,0,True);
+ /* Put things back the way they were. */
+ Connections[cnum].read_only = 1;
+
/* Mark the opened file as an existing named pipe in message mode. */
SSVAL(outbuf,smb_vwv9,2);
SSVAL(outbuf,smb_vwv10,0xc700);
-
if (rmode == 2)
{
DEBUG(4,("Resetting open result to open from create.\n"));
rmode = 1;
}
- SSVAL(outbuf,smb_vwv2, pnum + 0x800); /* mark file handle up into high range */
+ SSVAL(outbuf,smb_vwv2,fnum);
SSVAL(outbuf,smb_vwv3,fmode);
put_dos_date3(outbuf,smb_vwv4,mtime);
SIVAL(outbuf,smb_vwv6,size);
SSVAL(outbuf,smb_vwv8,rmode);
- SSVAL(outbuf,smb_vwv11,0);
+ SSVAL(outbuf,smb_vwv11,smb_action);
- return chain_reply(inbuf,outbuf,length,bufsize);
-}
+ chain_fnum = fnum;
-
-/****************************************************************************
- reply to a close
-****************************************************************************/
-int reply_pipe_close(char *inbuf,char *outbuf)
-{
- int pnum = get_rpc_pipe_num(inbuf,smb_vwv0);
- int cnum = SVAL(inbuf,smb_tid);
- int outsize = set_message(outbuf,0,0,True);
-
- DEBUG(5,("reply_pipe_close: pnum:%x cnum:%x\n", pnum, cnum));
-
- if (!close_rpc_pipe_hnd(pnum, cnum)) return(ERROR(ERRDOS,ERRbadfid));
-
- return(outsize);
+ DEBUG(4,("Opened pipe %s with handle %d, saved name %s.\n",
+ fname, fnum, Files[fnum].name));
+
+ return chain_reply(inbuf,outbuf,length,bufsize);
}
/****************************************************************************
api_LsarpcSNPHS
- SetNamedPipeHandleState on \PIPE\lsarpc.
+ SetNamedPipeHandleState on \PIPE\lsarpc. We can't really do much here,
+ so just blithely return True. This is really only for NT domain stuff,
+ we we're only handling that - don't assume Samba now does complete
+ named pipe handling.
****************************************************************************/
-BOOL api_LsarpcSNPHS(int pnum, int cnum, char *param)
+BOOL api_LsarpcSNPHS(int cnum,int uid, char *param,char *data,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len)
{
uint16 id;
- if (!param) return False;
-
id = param[0] + (param[1] << 8);
DEBUG(4,("lsarpc SetNamedPipeHandleState to code %x\n",id));
-
- return set_rpc_pipe_hnd_state(pnum, cnum, id);
+ return(True);
}
@@ -319,4 +357,3 @@ BOOL api_LsarpcTNP(int cnum,int uid, char *param,char *data,
}
return(True);
}
-
diff --git a/source/smbd/quotas.c b/source/smbd/quotas.c
index 562d8fd5db5..2d238dfaf17 100644
--- a/source/smbd/quotas.c
+++ b/source/smbd/quotas.c
@@ -417,133 +417,6 @@ BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
return (True);
}
-#elif defined (SGI6)
-/****************************************************************************
-try to get the disk space from disk quotas (IRIX 6.2 version)
-****************************************************************************/
-
-#include <sys/quota.h>
-#include <mntent.h>
-
-BOOL disk_quotas(char *path, int *bsize, int *dfree, int *dsize)
-{
- uid_t euser_id;
- int r;
- struct dqblk D;
- struct fs_disk_quota F;
- struct stat S;
- FILE *fp;
- struct mntent *mnt;
- int devno;
- int found;
-
- /* find the block device file */
-
- if ( stat(path, &S) == -1 ) {
- return(False) ;
- }
-
- devno = S.st_dev ;
-
- fp = setmntent(MOUNTED,"r");
- found = False ;
-
- while ((mnt = getmntent(fp))) {
- if ( stat(mnt->mnt_dir,&S) == -1 )
- continue ;
- if (S.st_dev == devno) {
- found = True ;
- break ;
- }
- }
- endmntent(fp) ;
-
- if (!found) {
- return(False);
- }
-
- euser_id=geteuid();
- seteuid(0);
-
- /* Use softlimit to determine disk space, except when it has been exceeded */
-
- *bsize = 512;
-
- if ( 0 == strcmp ( mnt->mnt_type, "efs" ))
- {
- r=quotactl (Q_GETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &D);
-
- seteuid(euser_id); /* Restore the original uid status. */
-
- if (r==-1)
- return(False);
-
- /* Use softlimit to determine disk space, except when it has been exceeded */
- if (
- (D.dqb_bsoftlimit && D.dqb_curblocks>=D.dqb_bsoftlimit) ||
- (D.dqb_bhardlimit && D.dqb_curblocks>=D.dqb_bhardlimit) ||
- (D.dqb_fsoftlimit && D.dqb_curfiles>=D.dqb_fsoftlimit) ||
- (D.dqb_fhardlimit && D.dqb_curfiles>=D.dqb_fhardlimit)
- )
- {
- *dfree = 0;
- *dsize = D.dqb_curblocks;
- }
- else if (D.dqb_bsoftlimit==0 && D.dqb_bhardlimit==0)
- {
- return(False);
- }
- else
- {
- *dfree = D.dqb_bsoftlimit - D.dqb_curblocks;
- *dsize = D.dqb_bsoftlimit;
- }
-
- }
- else if ( 0 == strcmp ( mnt->mnt_type, "xfs" ))
- {
- r=quotactl (Q_XGETQUOTA, mnt->mnt_fsname, euser_id, (caddr_t) &F);
-
- seteuid(euser_id); /* Restore the original uid status. */
-
- if (r==-1)
- return(False);
-
- /* Use softlimit to determine disk space, except when it has been exceeded */
- if (
- (F.d_blk_softlimit && F.d_bcount>=F.d_blk_softlimit) ||
- (F.d_blk_hardlimit && F.d_bcount>=F.d_blk_hardlimit) ||
- (F.d_ino_softlimit && F.d_icount>=F.d_ino_softlimit) ||
- (F.d_ino_hardlimit && F.d_icount>=F.d_ino_hardlimit)
- )
- {
- /*
- * Fixme!: these are __uint64_t, this may truncate values
- */
- *dfree = 0;
- *dsize = (int) F.d_bcount;
- }
- else if (F.d_blk_softlimit==0 && F.d_blk_hardlimit==0)
- {
- return(False);
- }
- else
- {
- *dfree = (int)(F.d_blk_softlimit - F.d_bcount);
- *dsize = (int)F.d_blk_softlimit;
- }
-
- }
- else
- {
- seteuid(euser_id); /* Restore the original uid status. */
- return(False);
- }
-
- return (True);
-
-}
-
#else
#ifdef __FreeBSD__
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index c903c7a1fd2..856ea594ab3 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -26,7 +26,6 @@
#include "includes.h"
#include "trans2.h"
-#include "nterr.h"
/* look in server.c for some explanation of these variables */
extern int Protocol;
@@ -43,7 +42,6 @@ extern BOOL short_case_preserve;
extern pstring sesssetup_user;
extern fstring myworkgroup;
extern int Client;
-extern int global_oplock_break;
/* this macro should always be used to extract an fnum (smb_fid) from
a packet to ensure chaining works correctly */
@@ -67,60 +65,49 @@ static void overflow_attack(int len)
****************************************************************************/
int reply_special(char *inbuf,char *outbuf)
{
- int outsize = 4;
- int msg_type = CVAL(inbuf,0);
- int msg_flags = CVAL(inbuf,1);
- pstring name1,name2;
- extern fstring remote_machine;
- extern fstring local_machine;
- int len;
- char name_type = 0;
-
- *name1 = *name2 = 0;
-
- smb_setlen(outbuf,0);
-
+ int outsize = 4;
+ int msg_type = CVAL(inbuf,0);
+ int msg_flags = CVAL(inbuf,1);
+ pstring name1,name2;
+ extern fstring remote_machine;
+ extern fstring local_machine;
+ char *p;
+
+ *name1 = *name2 = 0;
+
+ smb_setlen(outbuf,0);
+
switch (msg_type) {
- case 0x81: /* session request */
- CVAL(outbuf,0) = 0x82;
- CVAL(outbuf,3) = 0;
- if (name_len(inbuf+4) > 50 ||
- name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
- DEBUG(0,("Invalid name length in session request\n"));
- return(0);
- }
- name_extract(inbuf,4,name1);
- name_extract(inbuf,4 + name_len(inbuf + 4),name2);
+ case 0x81: /* session request */
+ CVAL(outbuf,0) = 0x82;
+ CVAL(outbuf,3) = 0;
+ if (name_len(inbuf+4) > 50 || name_len(inbuf+4 + name_len(inbuf + 4)) > 50) {
+ DEBUG(0,("Invalid name length in session request\n"));
+ return(0);
+ }
+ name_extract(inbuf,4,name1);
+ name_extract(inbuf,4 + name_len(inbuf + 4),name2);
DEBUG(2,("netbios connect: name1=%s name2=%s\n",
name1,name2));
- fstrcpy(remote_machine,name2);
- remote_machine[15] = 0;
- trim_string(remote_machine," "," ");
- strlower(remote_machine);
+ fstrcpy(remote_machine,name2);
+ trim_string(remote_machine," "," ");
+ p = strchr(remote_machine,' ');
+ strlower(remote_machine);
+ if (p) *p = 0;
- fstrcpy(local_machine,name1);
- len = strlen(local_machine);
- if (len == 16) {
- name_type = local_machine[15];
- local_machine[15] = 0;
- }
- trim_string(local_machine," "," ");
- strlower(local_machine);
-
- if (name_type == 'R') {
- /* We are being asked for a pathworks session ---
- no thanks! */
- CVAL(outbuf, 0) = 0x83;
- break;
- }
+ fstrcpy(local_machine,name1);
+ trim_string(local_machine," "," ");
+ p = strchr(local_machine,' ');
+ strlower(local_machine);
+ if (p) *p = 0;
- add_session_user(remote_machine);
+ add_session_user(remote_machine);
- reload_services(True);
- reopen_logs();
+ reload_services(True);
+ reopen_logs();
- break;
+ break;
case 0x89: /* session keepalive request
(some old clients produce this?) */
@@ -134,15 +121,15 @@ int reply_special(char *inbuf,char *outbuf)
DEBUG(0,("Unexpected session response\n"));
break;
- case 0x85: /* session keepalive */
- default:
- return(0);
- }
-
+ case 0x85: /* session keepalive */
+ default:
+ return(0);
+ }
+
DEBUG(5,("%s init msg_type=0x%x msg_flags=0x%x\n",
timestring(),msg_type,msg_flags));
-
- return(outsize);
+
+ return(outsize);
}
@@ -256,6 +243,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
int connection_num;
uint16 vuid = SVAL(inbuf,smb_uid);
int passlen = SVAL(inbuf,smb_vwv3);
+ BOOL doencrypt = SMBENCRYPT();
*service = *user = *password = *devicename = 0;
@@ -274,7 +262,7 @@ int reply_tcon_and_X(char *inbuf,char *outbuf,int length,int bufsize)
password[passlen]=0;
path = smb_buf(inbuf) + passlen;
- if (passlen != 24) {
+ if (!doencrypt || passlen != 24) {
if (strequal(password," "))
*password = 0;
passlen = strlen(password);
@@ -407,10 +395,9 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
}
memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
- smb_apasswd[smb_apasslen] = 0;
pstrcpy(user,smb_buf(inbuf)+smb_apasslen);
- if (!doencrypt && (lp_security() != SEC_SERVER)) {
+ if (lp_security() != SEC_SERVER && !doencrypt) {
smb_apasslen = strlen(smb_apasswd);
}
} else {
@@ -448,10 +435,8 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
/* Save the lanman2 password and the NT md4 password. */
smb_apasslen = passlen1;
memcpy(smb_apasswd,p,smb_apasslen);
- smb_apasswd[smb_apasslen] = 0;
smb_ntpasslen = passlen2;
memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
- smb_ntpasswd[smb_ntpasslen] = 0;
} else {
/* both Win95 and WinNT stuff up the password lengths for
non-encrypting systems. Uggh.
@@ -496,45 +481,9 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
/* If name ends in $ then I think it's asking about whether a */
/* computer with that name (minus the $) has access. For now */
/* say yes to everything ending in $. */
- if (user[strlen(user) - 1] == '$')
- {
-#ifdef NTDOMAIN
- struct smb_passwd *smb_pass; /* To check if machine account exists */
-/*
- PAXX: Ack. We don't want to do this. The workstation trust account
- with a $ on the end should exist in the local password database
- or be mapped to something generic, but not modified. For NT
- domain support we must reject this used in certain circumstances
- with a code to indicate to the client that it is an invalid use
- of a workstation trust account. NTWKS needs this error to join
- a domain. This may be the source of future bugs if we cannot
- be sure whether to reject this or not.
-*/
- /* non-null user name indicates search by username not by smb userid */
- smb_pass = get_smbpwd_entry(user, 0);
-
- if (!smb_pass)
- {
- /* lkclXXXX: if workstation entry doesn't exist, indicate logon failure */
- DEBUG(4,("Workstation trust account %s doesn't exist.",user));
- SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
- CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
- return(ERROR(NT_STATUS_LOGON_FAILURE, 0xc000)); /* decimal 109 NT error, 0xc000 */
- }
- else
- {
- /* PAXX: This is the NO LOGON workstation trust account stuff */
- /* lkclXXXX: if the workstation *does* exist, indicate failure differently! */
- DEBUG(4,("No Workstation trust account %s",user));
- SSVAL(outbuf, smb_flg2, 0xc003); /* PAXX: Someone please unhack this */
- CVAL(outbuf, smb_reh) = 1; /* PAXX: Someone please unhack this */
- return(ERROR(NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT, 0xc000)); /* decimal 409 NT error, 0xc000 */
- }
-
- computer_id = True;
-#else /* not NTDOMAIN, leave this in. PAXX: Someone get rid of this */
+ if (user[strlen(user) - 1] == '$') {
+ computer_id = True;
user[strlen(user) - 1] = '\0';
-#endif
}
@@ -656,7 +605,7 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
if (!done_sesssetup)
max_send = MIN(max_send,smb_bufsize);
- DEBUG(6,("Client requested max send size of %d\n", max_send));
+ DEBUG(5,(" Client requested max send size of %d\n", max_send));
done_sesssetup = True;
@@ -697,17 +646,6 @@ int reply_chkpth(char *inbuf,char *outbuf)
unix_ERR_class = ERRDOS;
unix_ERR_code = ERRbadpath;
}
-
-#if 0
- /* Ugly - NT specific hack - maybe not needed ? (JRA) */
- if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
- (get_remote_arch() == RA_WINNT))
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbaddirectory;
- }
-#endif
-
return(UNIXERROR(ERRDOS,ERRbadpath));
}
@@ -1170,8 +1108,6 @@ int reply_open(char *inbuf,char *outbuf)
int rmode=0;
struct stat sbuf;
BOOL bad_path = False;
- files_struct *fsp;
- int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
cnum = SVAL(inbuf,smb_tid);
@@ -1196,12 +1132,9 @@ int reply_open(char *inbuf,char *outbuf)
unixmode = unix_mode(cnum,aARCH);
- open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,
- oplock_request,&rmode,NULL);
-
- fsp = &Files[fnum];
+ open_file_shared(fnum,cnum,fname,share_mode,3,unixmode,&rmode,NULL);
- if (!fsp->open)
+ if (!Files[fnum].open)
{
if((errno == ENOENT) && bad_path)
{
@@ -1211,8 +1144,8 @@ int reply_open(char *inbuf,char *outbuf)
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
- if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
- close_file(fnum,False);
+ if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
+ close_file(fnum, 0);
return(ERROR(ERRDOS,ERRnoaccess));
}
@@ -1222,7 +1155,7 @@ int reply_open(char *inbuf,char *outbuf)
if (fmode & aDIR) {
DEBUG(3,("attempt to open a directory %s\n",fname));
- close_file(fnum,False);
+ close_file(fnum, 0);
return(ERROR(ERRDOS,ERRnoaccess));
}
@@ -1233,12 +1166,10 @@ int reply_open(char *inbuf,char *outbuf)
SIVAL(outbuf,smb_vwv4,size);
SSVAL(outbuf,smb_vwv6,rmode);
- if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+ if (lp_fake_oplocks(SNUM(cnum))) {
+ CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
}
- if(fsp->granted_oplock)
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
return(outsize);
}
@@ -1253,11 +1184,7 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
int fnum = -1;
int smb_mode = SVAL(inbuf,smb_vwv3);
int smb_attr = SVAL(inbuf,smb_vwv5);
- /* Breakout the oplock request bits so we can set the
- reply bits separately. */
- BOOL ex_oplock_request = EXTENDED_OPLOCK_REQUEST(inbuf);
- BOOL core_oplock_request = CORE_OPLOCK_REQUEST(inbuf);
- BOOL oplock_request = ex_oplock_request | core_oplock_request;
+ BOOL oplock_request = BITSETW(inbuf+smb_vwv2,1);
#if 0
int open_flags = SVAL(inbuf,smb_vwv2);
int smb_sattr = SVAL(inbuf,smb_vwv4);
@@ -1269,7 +1196,6 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
struct stat sbuf;
int smb_action = 0;
BOOL bad_path = False;
- files_struct *fsp;
/* If it's an IPC, pass off the pipe handler. */
if (IS_IPC(cnum))
@@ -1297,11 +1223,9 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
unixmode = unix_mode(cnum,smb_attr | aARCH);
open_file_shared(fnum,cnum,fname,smb_mode,smb_ofun,unixmode,
- oplock_request, &rmode,&smb_action);
+ &rmode,&smb_action);
- fsp = &Files[fnum];
-
- if (!fsp->open)
+ if (!Files[fnum].open)
{
if((errno == ENOENT) && bad_path)
{
@@ -1311,8 +1235,8 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
return(UNIXERROR(ERRDOS,ERRnoaccess));
}
- if (fstat(fsp->fd_ptr->fd,&sbuf) != 0) {
- close_file(fnum,False);
+ if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
+ close_file(fnum, 0);
return(ERROR(ERRDOS,ERRnoaccess));
}
@@ -1320,34 +1244,12 @@ int reply_open_and_X(char *inbuf,char *outbuf,int length,int bufsize)
fmode = dos_mode(cnum,fname,&sbuf);
mtime = sbuf.st_mtime;
if (fmode & aDIR) {
- close_file(fnum,False);
+ close_file(fnum, 0);
return(ERROR(ERRDOS,ERRnoaccess));
}
- /* If the caller set the extended oplock request bit
- and we granted one (by whatever means) - set the
- correct bit for extended oplock reply.
- */
-
- if (ex_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
- smb_action |= EXTENDED_OPLOCK_GRANTED;
- }
-
- if(ex_oplock_request && fsp->granted_oplock) {
- smb_action |= EXTENDED_OPLOCK_GRANTED;
- }
-
- /* If the caller set the core oplock request bit
- and we granted one (by whatever means) - set the
- correct bit for core oplock reply.
- */
-
- if (core_oplock_request && lp_fake_oplocks(SNUM(cnum))) {
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
- }
-
- if(core_oplock_request && fsp->granted_oplock) {
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+ if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
+ smb_action |= (1<<15);
}
set_message(outbuf,15,0,True);
@@ -1382,7 +1284,7 @@ int reply_ulogoffX(char *inbuf,char *outbuf,int length,int bufsize)
int i;
for (i=0;i<MAX_OPEN_FILES;i++)
if (Files[i].uid == vuser->uid && Files[i].open) {
- close_file(i,False);
+ close_file(i, 0);
}
}
@@ -1409,8 +1311,6 @@ int reply_mknew(char *inbuf,char *outbuf)
mode_t unixmode;
int ofun = 0;
BOOL bad_path = False;
- files_struct *fsp;
- int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
com = SVAL(inbuf,smb_com);
cnum = SVAL(inbuf,smb_tid);
@@ -1452,12 +1352,9 @@ int reply_mknew(char *inbuf,char *outbuf)
}
/* Open file in dos compatibility share mode. */
- open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode,
- oplock_request, NULL, NULL);
+ open_file_shared(fnum,cnum,fname,(DENY_FCB<<4)|0xF, ofun, unixmode, NULL, NULL);
- fsp = &Files[fnum];
-
- if (!fsp->open)
+ if (!Files[fnum].open)
{
if((errno == ENOENT) && bad_path)
{
@@ -1470,13 +1367,10 @@ int reply_mknew(char *inbuf,char *outbuf)
outsize = set_message(outbuf,1,0,True);
SSVAL(outbuf,smb_vwv0,fnum);
- if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+ if (lp_fake_oplocks(SNUM(cnum))) {
+ CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
}
-
- if(fsp->granted_oplock)
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
-
+
DEBUG(2,("new file %s\n",fname));
DEBUG(3,("%s mknew %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode));
@@ -1497,8 +1391,6 @@ int reply_ctemp(char *inbuf,char *outbuf)
int createmode;
mode_t unixmode;
BOOL bad_path = False;
- files_struct *fsp;
- int oplock_request = CORE_OPLOCK_REQUEST(inbuf);
cnum = SVAL(inbuf,smb_tid);
createmode = SVAL(inbuf,smb_vwv0);
@@ -1526,12 +1418,9 @@ int reply_ctemp(char *inbuf,char *outbuf)
/* Open file in dos compatibility share mode. */
/* We should fail if file exists. */
- open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode,
- oplock_request, NULL, NULL);
-
- fsp = &Files[fnum];
+ open_file_shared(fnum,cnum,fname2,(DENY_FCB<<4)|0xF, 0x10, unixmode, NULL, NULL);
- if (!fsp->open)
+ if (!Files[fnum].open)
{
if((errno == ENOENT) && bad_path)
{
@@ -1546,13 +1435,10 @@ int reply_ctemp(char *inbuf,char *outbuf)
CVAL(smb_buf(outbuf),0) = 4;
strcpy(smb_buf(outbuf) + 1,fname2);
- if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
+ if (lp_fake_oplocks(SNUM(cnum))) {
+ CVAL(outbuf,smb_flg) |= (CVAL(inbuf,smb_flg) & (1<<5));
}
- if(fsp->granted_oplock)
- CVAL(outbuf,smb_flg) |= CORE_OPLOCK_GRANTED;
-
DEBUG(2,("created temp file %s\n",fname2));
DEBUG(3,("%s ctemp %s fd=%d fnum=%d cnum=%d dmode=%d umode=%o\n",timestring(),fname2,Files[fnum].fd_ptr->fd,fnum,cnum,createmode,unixmode));
@@ -1700,20 +1586,6 @@ int reply_readbraw(char *inbuf, char *outbuf)
int fd;
char *fname;
- /*
- * Special check if an oplock break has been issued
- * and the readraw request croses on the wire, we must
- * return a zero length response here.
- */
-
- if(global_oplock_break)
- {
- _smb_setlen(header,0);
- transfer_file(0,Client,0,header,4,0);
- DEBUG(5,("readbraw - oplock break finished\n"));
- return -1;
- }
-
cnum = SVAL(inbuf,smb_tid);
fnum = GETFNUM(inbuf,smb_vwv0);
@@ -2314,12 +2186,7 @@ int reply_close(char *inbuf,char *outbuf)
cnum = SVAL(inbuf,smb_tid);
- /* If it's an IPC, pass off to the pipe handler. */
- if (IS_IPC(cnum))
- return reply_pipe_close(inbuf,outbuf);
-
fnum = GETFNUM(inbuf,smb_vwv0);
-
CHECK_FNUM(fnum,cnum);
if(HAS_CACHED_ERROR(fnum)) {
@@ -2330,9 +2197,9 @@ int reply_close(char *inbuf,char *outbuf)
mtime = make_unix_date3(inbuf+smb_vwv1);
/* try and set the date */
- set_filetime(cnum, Files[fnum].name,mtime);
+ set_filetime(cnum,Files[fnum].name,mtime);
- close_file(fnum,True);
+ close_file(fnum, 1);
/* We have a cached error */
if(eclass || err)
@@ -2377,9 +2244,9 @@ int reply_writeclose(char *inbuf,char *outbuf)
nwritten = write_file(fnum,data,numtowrite);
- set_filetime(cnum, Files[fnum].name,mtime);
+ set_filetime(cnum,Files[fnum].name,mtime);
- close_file(fnum,True);
+ close_file(fnum, 1);
DEBUG(3,("%s writeclose fnum=%d cnum=%d num=%d wrote=%d (numopen=%d)\n",
timestring(),fnum,cnum,numtowrite,nwritten,
@@ -2576,8 +2443,7 @@ int reply_printopen(char *inbuf,char *outbuf)
return(ERROR(ERRDOS,ERRnoaccess));
/* Open for exclusive use, write only. */
- open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0),
- 0, NULL, NULL);
+ open_file_shared(fnum,cnum,fname2,(DENY_ALL<<4)|1, 0x12, unix_mode(cnum,0), NULL, NULL);
if (!Files[fnum].open)
return(UNIXERROR(ERRDOS,ERRnoaccess));
@@ -2611,7 +2477,7 @@ int reply_printclose(char *inbuf,char *outbuf)
if (!CAN_PRINT(cnum))
return(ERROR(ERRDOS,ERRnoaccess));
- close_file(fnum,True);
+ close_file(fnum, 1);
DEBUG(3,("%s printclose fd=%d fnum=%d cnum=%d\n",timestring(),Files[fnum].fd_ptr->fd,fnum,cnum));
@@ -2667,7 +2533,7 @@ int reply_printqueue(char *inbuf,char *outbuf)
DEBUG(5,("connection not open or not a printer, using cnum %d\n",cnum));
}
- if (!become_user(&Connections[cnum], cnum, vuid))
+ if (!become_user(cnum,vuid))
return(ERROR(ERRSRV,ERRinvnid));
{
@@ -2779,66 +2645,6 @@ int reply_mkdir(char *inbuf,char *outbuf)
return(outsize);
}
-/****************************************************************************
-Static function used by reply_rmdir to delete an entire directory
-tree recursively.
-****************************************************************************/
-static BOOL recursive_rmdir(char *directory)
-{
- char *dname = NULL;
- BOOL ret = False;
- void *dirptr = OpenDir(-1, directory, False);
-
- if(dirptr == NULL)
- return True;
-
- while((dname = ReadDirName(dirptr)))
- {
- pstring fullname;
- struct stat st;
-
- if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0))
- continue;
-
- /* Construct the full name. */
- if(strlen(directory) + strlen(dname) + 1 >= sizeof(fullname))
- {
- errno = ENOMEM;
- ret = True;
- break;
- }
- strcpy(fullname, directory);
- strcat(fullname, "/");
- strcat(fullname, dname);
-
- if(sys_lstat(fullname, &st) != 0)
- {
- ret = True;
- break;
- }
-
- if(st.st_mode & S_IFDIR)
- {
- if(recursive_rmdir(fullname)!=0)
- {
- ret = True;
- break;
- }
- if(sys_rmdir(fullname) != 0)
- {
- ret = True;
- break;
- }
- }
- else if(sys_unlink(fullname) != 0)
- {
- ret = True;
- break;
- }
- }
- CloseDir(dirptr);
- return ret;
-}
/****************************************************************************
reply to a rmdir
@@ -2907,15 +2713,10 @@ int reply_rmdir(char *inbuf,char *outbuf)
if(sys_lstat(fullname, &st) != 0)
break;
if(st.st_mode & S_IFDIR)
- {
- if(lp_recursive_veto_delete(SNUM(cnum)))
{
- if(recursive_rmdir(fullname) != 0)
+ if(sys_rmdir(fullname) != 0)
break;
}
- if(sys_rmdir(fullname) != 0)
- break;
- }
else if(sys_unlink(fullname) != 0)
break;
}
@@ -3176,23 +2977,14 @@ int reply_mv(char *inbuf,char *outbuf)
error = ERRnoaccess;
sprintf(fname,"%s/%s",directory,dname);
- if (!can_rename(fname,cnum)) {
- DEBUG(6,("rename %s refused\n", fname));
- continue;
- }
+ if (!can_rename(fname,cnum)) continue;
pstrcpy(destname,newname);
- if (!resolve_wildcards(fname,destname)) {
- DEBUG(6,("resolve_wildcards %s %s failed\n",
- fname, destname));
- continue;
- }
+ if (!resolve_wildcards(fname,destname)) continue;
if (file_exist(destname,NULL)) {
- DEBUG(6,("file_exist %s\n",
- destname));
- error = 183;
- continue;
+ error = 183;
+ continue;
}
if (!sys_rename(fname,destname)) count++;
DEBUG(3,("reply_mv : doing rename on %s -> %s\n",fname,destname));
@@ -3248,7 +3040,7 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
fnum1 = find_free_file();
if (fnum1<0) return(False);
open_file_shared(fnum1,cnum,src,(DENY_NONE<<4),
- 1,0,0,&Access,&action);
+ 1,0,&Access,&action);
if (!Files[fnum1].open) return(False);
@@ -3257,14 +3049,14 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
fnum2 = find_free_file();
if (fnum2<0) {
- close_file(fnum1,False);
+ close_file(fnum1, 0);
return(False);
}
open_file_shared(fnum2,cnum,dest,(DENY_NONE<<4)|1,
- ofun,st.st_mode,0,&Access,&action);
+ ofun,st.st_mode,&Access,&action);
if (!Files[fnum2].open) {
- close_file(fnum1,False);
+ close_file(fnum1, 0);
return(False);
}
@@ -3275,8 +3067,8 @@ static BOOL copy_file(char *src,char *dest1,int cnum,int ofun,
if (st.st_size)
ret = transfer_file(Files[fnum1].fd_ptr->fd,Files[fnum2].fd_ptr->fd,st.st_size,NULL,0,0);
- close_file(fnum1,False);
- close_file(fnum2,False);
+ close_file(fnum1, 0);
+ close_file(fnum2, 0);
return(ret == st.st_size);
}
@@ -3463,10 +3255,7 @@ int reply_setdir(char *inbuf,char *outbuf)
int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
{
int fnum = GETFNUM(inbuf,smb_vwv2);
- unsigned char locktype = CVAL(inbuf,smb_vwv3);
-#if 0
- unsigned char oplocklevel = CVAL(inbuf,smb_vwv3+1);
-#endif
+ uint16 locktype = SVAL(inbuf,smb_vwv3);
uint16 num_ulocks = SVAL(inbuf,smb_vwv6);
uint16 num_locks = SVAL(inbuf,smb_vwv7);
uint32 count, offset;
@@ -3483,55 +3272,6 @@ int reply_lockingX(char *inbuf,char *outbuf,int length,int bufsize)
CHECK_ERROR(fnum);
data = smb_buf(inbuf);
-
- /* Check if this is an oplock break on a file
- we have granted an oplock on.
- */
- if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE))
- {
- int token;
- files_struct *fsp = &Files[fnum];
- uint32 dev = fsp->fd_ptr->dev;
- uint32 inode = fsp->fd_ptr->inode;
-
- DEBUG(5,("reply_lockingX: oplock break reply from client for fnum = %d\n",
- fnum));
- /*
- * Make sure we have granted an oplock on this file.
- */
- if(!fsp->granted_oplock)
- {
- DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \
-no oplock granted on this file.\n", fnum));
- return ERROR(ERRDOS,ERRlock);
- }
-
- /* Remove the oplock flag from the sharemode. */
- lock_share_entry(fsp->cnum, dev, inode, &token);
- if(remove_share_oplock( fnum, token)==False) {
- DEBUG(0,("reply_lockingX: failed to remove share oplock for fnum %d, \
-dev = %x, inode = %x\n",
- fnum, dev, inode));
- unlock_share_entry(fsp->cnum, dev, inode, token);
- } else {
- unlock_share_entry(fsp->cnum, dev, inode, token);
-
- /* Clear the granted flag and return. */
- fsp->granted_oplock = False;
- }
-
- /* if this is a pure oplock break request then don't send a reply */
- if (num_locks == 0 && num_ulocks == 0)
- {
- /* Sanity check - ensure a pure oplock break is not a
- chained request. */
- if(CVAL(inbuf,smb_vwv0) != 0xff)
- DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n",
- (unsigned int)CVAL(inbuf,smb_vwv0) ));
- return -1;
- }
- }
-
/* Data now points at the beginning of the list
of smb_unlkrng structs */
for(i = 0; i < (int)num_ulocks; i++) {
@@ -3566,7 +3306,7 @@ dev = %x, inode = %x\n",
set_message(outbuf,2,0,True);
DEBUG(3,("%s lockingX fnum=%d cnum=%d type=%d num_locks=%d num_ulocks=%d\n",
- timestring(),fnum,cnum,(unsigned int)locktype,num_locks,num_ulocks));
+ timestring(),fnum,cnum,locktype,num_locks,num_ulocks));
chain_fnum = fnum;
@@ -3863,7 +3603,7 @@ not setting timestamps of 0\n",
}
/* Set the date on this file */
- if(file_utime(cnum, Files[fnum].name, &unix_times))
+ if(file_utime(cnum,Files[fnum].name, &unix_times))
return(ERROR(ERRDOS,ERRnoaccess));
DEBUG(3,("%s reply_setattrE fnum=%d cnum=%d actime=%d modtime=%d\n",
@@ -3919,3 +3659,8 @@ int reply_getattrE(char *inbuf,char *outbuf)
return(outsize);
}
+
+
+
+
+
diff --git a/source/smbd/server.c b/source/smbd/server.c
index bf66e1ca4be..5883557273c 100644
--- a/source/smbd/server.c
+++ b/source/smbd/server.c
@@ -84,17 +84,9 @@ int chain_fnum = -1;
/* number of open connections */
static int num_connections_open = 0;
-/* Oplock ipc UDP socket. */
-int oplock_sock = -1;
-uint16 oplock_port = 0;
-/* Current number of oplocks we have outstanding. */
-int32 global_oplocks_open = 0;
-
-BOOL global_oplock_break = False;
-
extern fstring remote_machine;
-extern pstring OriginalDir;
+pstring OriginalDir;
/* these can be set by some functions to override the error codes */
int unix_ERR_class=SUCCESS;
@@ -187,7 +179,7 @@ int dos_mode(int cnum,char *path,struct stat *sbuf)
int result = 0;
extern struct current_user current_user;
- DEBUG(8,("dos_mode: %d %s\n", cnum, path));
+ DEBUG(5,("dos_mode: %d %s\n", cnum, path));
if (CAN_WRITE(cnum) && !lp_alternate_permissions(SNUM(cnum))) {
if (!((sbuf->st_mode & S_IWOTH) ||
@@ -214,12 +206,10 @@ int dos_mode(int cnum,char *path,struct stat *sbuf)
if (S_ISDIR(sbuf->st_mode))
result = aDIR | (result & aRONLY);
-#ifdef S_ISLNK
#if LINKS_READ_ONLY
if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
result |= aRONLY;
#endif
-#endif
/* hide files with a name starting with a . */
if (lp_hide_dot_files(SNUM(cnum)))
@@ -241,19 +231,20 @@ int dos_mode(int cnum,char *path,struct stat *sbuf)
result |= aHIDDEN;
}
- DEBUG(8,("dos_mode returning "));
+ DEBUG(5,("dos_mode returning "));
- if (result & aHIDDEN) DEBUG(8, ("h"));
- if (result & aRONLY ) DEBUG(8, ("r"));
- if (result & aSYSTEM) DEBUG(8, ("s"));
- if (result & aDIR ) DEBUG(8, ("d"));
- if (result & aARCH ) DEBUG(8, ("a"));
+ if (result & aHIDDEN) DEBUG(5, ("h"));
+ if (result & aRONLY ) DEBUG(5, ("r"));
+ if (result & aSYSTEM) DEBUG(5, ("s"));
+ if (result & aDIR ) DEBUG(5, ("d"));
+ if (result & aARCH ) DEBUG(5, ("a"));
- DEBUG(8,("\n"));
+ DEBUG(5,("\n"));
return(result);
}
+
/*******************************************************************
chmod a file - but preserve some bits
********************************************************************/
@@ -318,8 +309,6 @@ int file_utime(int cnum, char *fname, struct utimbuf *times)
struct stat sb;
int ret = -1;
- errno = 0;
-
if(sys_utime(fname, times) == 0)
return 0;
@@ -355,25 +344,25 @@ int file_utime(int cnum, char *fname, struct utimbuf *times)
return ret;
}
-
+
/*******************************************************************
Change a filetime - possibly allowing DOS semantics.
*******************************************************************/
-
+
BOOL set_filetime(int cnum, char *fname, time_t mtime)
-{
+{
struct utimbuf times;
- if (null_mtime(mtime)) return(True);
+ if (null_mtime(mtime)) return(True);
times.modtime = times.actime = mtime;
-
+
if (file_utime(cnum, fname, &times)) {
DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
}
-
+
return(True);
-}
+}
/****************************************************************************
check if two filenames are equal
@@ -452,7 +441,7 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache)
return(True);
}
-#if 0
+#if 0
/*
* This code I believe is incorrect - and commenting it out
* is the correct fix for the bug mentioned below in the
@@ -465,7 +454,7 @@ static BOOL scan_directory(char *path, char *name,int cnum,BOOL docache)
*/
if (mangled)
check_mangled_stack(name);
-#endif
+#endif
/* open the directory */
if (!(cur_dir = OpenDir(cnum, path, True)))
@@ -792,13 +781,13 @@ int disk_free(char *path,int *bsize,int *dfree,int *dsize)
/* maybe dfree and dfreeq are calculated using different bsizes
so convert dfree from bsize into bsizeq */
/* avoid overflows due to multiplication, so do not:
- *dfree = ((*dfree) * (*bsize)) / (bsizeq);
+ *dfree = ((*dfree) * (*bsize)) / (bsizeq);
bsize and bsizeq are powers of 2 so its better to
to divide them getting a multiplication or division factor
for dfree. Rene Nieuwenhuizen (07-10-1997) */
- if (*bsize >= bsizeq)
+ if (*bsize >= bsizeq)
*dfree = *dfree * (*bsize / bsizeq);
- else
+ else
*dfree = *dfree / (bsizeq / *bsize);
*dfree = ( *dfree < dfreeq ) ? *dfree : dfreeq ;
*bsize = bsizeq;
@@ -890,7 +879,7 @@ if ((*bsize) < 512 || (*bsize)>0xFFFF) *bsize = 1024;
/* maybe dfree and dfreeq are calculated using different bsizes
so convert dfree from bsize into bsizeq */
/* avoid overflows due to multiplication, so do not:
- *dfree = ((*dfree) * (*bsize)) / (bsizeq);
+ *dfree = ((*dfree) * (*bsize)) / (bsizeq);
bsize and bsizeq are powers of 2 so its better to
to divide them getting a multiplication or division factor
for dfree. Rene Nieuwenhuizen (07-10-1997) */
@@ -943,7 +932,6 @@ BOOL check_name(char *name,int cnum)
/* Patch from David Clerc <David.Clerc@cui.unige.ch>
University of Geneva */
-#ifdef S_ISLNK
if (!lp_symlinks(SNUM(cnum)))
{
struct stat statbuf;
@@ -954,7 +942,6 @@ BOOL check_name(char *name,int cnum)
ret=0;
}
}
-#endif
if (!ret)
DEBUG(5,("check_name on %s failed\n",name));
@@ -982,7 +969,8 @@ static void check_for_pipe(char *fname)
/****************************************************************************
fd support routines - attempt to do a sys_open
****************************************************************************/
-static int fd_attempt_open(char *fname, int flags, int mode)
+
+int fd_attempt_open(char *fname, int flags, int mode)
{
int fd = sys_open(fname,flags,mode);
@@ -1034,7 +1022,7 @@ static int fd_attempt_open(char *fname, int flags, int mode)
fd support routines - attempt to find an already open file by dev
and inode - increments the ref_count of the returned file_fd_struct *.
****************************************************************************/
-static file_fd_struct *fd_get_already_open(struct stat *sbuf)
+file_fd_struct *fd_get_already_open(struct stat *sbuf)
{
int i;
file_fd_struct *fd_ptr;
@@ -1061,7 +1049,7 @@ static file_fd_struct *fd_get_already_open(struct stat *sbuf)
fd support routines - attempt to find a empty slot in the FileFd array.
Increments the ref_count of the returned entry.
****************************************************************************/
-static file_fd_struct *fd_get_new()
+file_fd_struct *fd_get_new()
{
int i;
file_fd_struct *fd_ptr;
@@ -1094,7 +1082,8 @@ n"));
fd support routines - attempt to re-open an already open fd as O_RDWR.
Save the already open fd (we cannot close due to POSIX file locking braindamage.
****************************************************************************/
-static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
+
+void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
{
int fd = sys_open( fname, O_RDWR, mode);
@@ -1114,7 +1103,7 @@ static void fd_attempt_reopen(char *fname, int mode, file_fd_struct *fd_ptr)
fd support routines - attempt to close the file referenced by this fd.
Decrements the ref_count and returns it.
****************************************************************************/
-static int fd_attempt_close(file_fd_struct *fd_ptr)
+int fd_attempt_close(file_fd_struct *fd_ptr)
{
DEBUG(3,("fd_attempt_close on file_fd_struct %d, fd = %d, dev = %x, inode = %x, open_flags = %d, ref_count = %d.\n",
fd_ptr - &FileFd[0],
@@ -1150,11 +1139,9 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct
pstring fname;
struct stat statbuf;
file_fd_struct *fd_ptr;
- files_struct *fsp = &Files[fnum];
- fsp->open = False;
- fsp->fd_ptr = 0;
- fsp->granted_oplock = False;
+ Files[fnum].open = False;
+ Files[fnum].fd_ptr = 0;
errno = EPERM;
pstrcpy(fname,fname1);
@@ -1285,7 +1272,7 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct
if (sys_disk_free(dname,&dum1,&dum2,&dum3) <
lp_minprintspace(SNUM(cnum))) {
fd_attempt_close(fd_ptr);
- fsp->fd_ptr = 0;
+ Files[fnum].fd_ptr = 0;
if(fd_ptr->ref_count == 0)
sys_unlink(fname);
errno = ENOSPC;
@@ -1321,27 +1308,25 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct
fd_ptr->dev = (uint32)sbuf->st_dev;
fd_ptr->inode = (uint32)sbuf->st_ino;
- fsp->fd_ptr = fd_ptr;
+ Files[fnum].fd_ptr = fd_ptr;
Connections[cnum].num_files_open++;
- fsp->mode = sbuf->st_mode;
- GetTimeOfDay(&fsp->open_time);
- fsp->uid = current_user.id;
- fsp->size = 0;
- fsp->pos = -1;
- fsp->open = True;
- fsp->mmap_ptr = NULL;
- fsp->mmap_size = 0;
- fsp->can_lock = True;
- fsp->can_read = ((flags & O_WRONLY)==0);
- fsp->can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
- fsp->share_mode = 0;
- fsp->print_file = Connections[cnum].printer;
- fsp->modified = False;
- fsp->granted_oplock = False;
- fsp->sent_oplock_break = False;
- fsp->cnum = cnum;
- string_set(&fsp->name,dos_to_unix(fname,False));
- fsp->wbmpx_ptr = NULL;
+ Files[fnum].mode = sbuf->st_mode;
+ GetTimeOfDay(&Files[fnum].open_time);
+ Files[fnum].uid = current_user.id;
+ Files[fnum].size = 0;
+ Files[fnum].pos = -1;
+ Files[fnum].open = True;
+ Files[fnum].mmap_ptr = NULL;
+ Files[fnum].mmap_size = 0;
+ Files[fnum].can_lock = True;
+ Files[fnum].can_read = ((flags & O_WRONLY)==0);
+ Files[fnum].can_write = ((flags & (O_WRONLY|O_RDWR))!=0);
+ Files[fnum].share_mode = 0;
+ Files[fnum].print_file = Connections[cnum].printer;
+ Files[fnum].modified = False;
+ Files[fnum].cnum = cnum;
+ string_set(&Files[fnum].name,dos_to_unix(fname,False));
+ Files[fnum].wbmpx_ptr = NULL;
/*
* If the printer is marked as postscript output a leading
@@ -1350,8 +1335,8 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct
* This has a similar effect as CtrlD=0 in WIN.INI file.
* tim@fsg.com 09/06/94
*/
- if (fsp->print_file && POSTSCRIPT(cnum) &&
- fsp->can_write)
+ if (Files[fnum].print_file && POSTSCRIPT(cnum) &&
+ Files[fnum].can_write)
{
DEBUG(3,("Writing postscript line\n"));
write_file(fnum,"%!\n",3);
@@ -1359,23 +1344,23 @@ static void open_file(int fnum,int cnum,char *fname1,int flags,int mode, struct
DEBUG(2,("%s %s opened file %s read=%s write=%s (numopen=%d fnum=%d)\n",
timestring(),Connections[cnum].user,fname,
- BOOLSTR(fsp->can_read),BOOLSTR(fsp->can_write),
+ BOOLSTR(Files[fnum].can_read),BOOLSTR(Files[fnum].can_write),
Connections[cnum].num_files_open,fnum));
}
#if USE_MMAP
/* mmap it if read-only */
- if (!fsp->can_write)
+ if (!Files[fnum].can_write)
{
- fsp->mmap_size = file_size(fname);
- fsp->mmap_ptr = (char *)mmap(NULL,fsp->mmap_size,
- PROT_READ,MAP_SHARED,fsp->fd_ptr->fd,0);
+ Files[fnum].mmap_size = file_size(fname);
+ Files[fnum].mmap_ptr = (char *)mmap(NULL,Files[fnum].mmap_size,
+ PROT_READ,MAP_SHARED,Files[fnum].fd_ptr->fd,0);
- if (fsp->mmap_ptr == (char *)-1 || !fsp->mmap_ptr)
+ if (Files[fnum].mmap_ptr == (char *)-1 || !Files[fnum].mmap_ptr)
{
DEBUG(3,("Failed to mmap() %s - %s\n",fname,strerror(errno)));
- fsp->mmap_ptr = NULL;
+ Files[fnum].mmap_ptr = NULL;
}
}
#endif
@@ -1434,18 +1419,18 @@ static void check_magic(int fnum,int cnum)
/****************************************************************************
close a file - possibly invalidating the read prediction
-If normal_close is 1 then this came from a normal SMBclose (or equivalent)
-operation otherwise it came as the result of some other operation such as
+If normal_close is 1 then this came from a normal SMBclose (or equivalent)
+operation otherwise it came as the result of some other operation such as
the closing of the connection. In the latter case printing and
magic scripts are not run
****************************************************************************/
-void close_file(int fnum, BOOL normal_close)
+void close_file(int fnum, int normal_close)
{
files_struct *fs_p = &Files[fnum];
int cnum = fs_p->cnum;
uint32 dev = fs_p->fd_ptr->dev;
uint32 inode = fs_p->fd_ptr->inode;
- int token;
+ share_lock_token token;
#if USE_READ_PREDICTION
invalidate_read_prediction(fs_p->fd_ptr->fd);
@@ -1454,17 +1439,17 @@ void close_file(int fnum, BOOL normal_close)
fs_p->open = False;
Connections[cnum].num_files_open--;
if(fs_p->wbmpx_ptr)
- {
- free((char *)fs_p->wbmpx_ptr);
- fs_p->wbmpx_ptr = NULL;
- }
+ {
+ free((char *)fs_p->wbmpx_ptr);
+ fs_p->wbmpx_ptr = NULL;
+ }
#if USE_MMAP
if(fs_p->mmap_ptr)
- {
- munmap(fs_p->mmap_ptr,fs_p->mmap_size);
- fs_p->mmap_ptr = NULL;
- }
+ {
+ munmap(fs_p->mmap_ptr,fs_p->mmap_size);
+ fs_p->mmap_ptr = NULL;
+ }
#endif
if (lp_share_modes(SNUM(cnum)))
@@ -1484,12 +1469,7 @@ void close_file(int fnum, BOOL normal_close)
/* check for magic scripts */
if (normal_close)
- check_magic(fnum,cnum);
-
- if(fs_p->granted_oplock == True)
- global_oplocks_open--;
-
- fs_p->sent_oplock_break = False;
+ check_magic(fnum,cnum);
DEBUG(2,("%s %s closed file %s (numopen=%d)\n",
timestring(),Connections[cnum].user,fs_p->name,
@@ -1507,8 +1487,7 @@ static int access_table(int new_deny,int old_deny,int old_mode,
if (new_deny == DENY_ALL || old_deny == DENY_ALL) return(AFAIL);
if (new_deny == DENY_DOS || old_deny == DENY_DOS) {
- int pid = getpid();
- if (old_deny == new_deny && share_pid == pid)
+ if (old_deny == new_deny && share_pid == getpid())
return(AALL);
if (old_mode == 0) return(AREAD);
@@ -1557,79 +1536,28 @@ BOOL check_file_sharing(int cnum,char *fname)
{
int i;
int ret = False;
- share_mode_entry *old_shares = 0;
+ min_share_mode_entry *old_shares = 0;
int num_share_modes;
struct stat sbuf;
- int token;
+ share_lock_token token;
int pid = getpid();
- uint32 dev, inode;
if(!lp_share_modes(SNUM(cnum)))
return True;
if (stat(fname,&sbuf) == -1) return(True);
- dev = (uint32)sbuf.st_dev;
- inode = (uint32)sbuf.st_ino;
-
- lock_share_entry(cnum, dev, inode, &token);
- num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares);
-
- /*
- * Check if the share modes will give us access.
- */
+ lock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &token);
+ num_share_modes = get_share_modes(cnum, token,
+ (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, &old_shares);
- if(num_share_modes != 0)
+ for( i = 0; i < num_share_modes; i++)
{
- BOOL broke_oplock;
-
- do
- {
-
- broke_oplock = False;
- for(i = 0; i < num_share_modes; i++)
- {
- share_mode_entry *share_entry = &old_shares[i];
-
- /*
- * Break oplocks before checking share modes. See comment in
- * open_file_shared for details.
- * Check if someone has an oplock on this file. If so we must
- * break it before continuing.
- */
- if(share_entry->op_type & BATCH_OPLOCK)
- {
-
- DEBUG(5,("check_file_sharing: breaking oplock (%x) on file %s, \
-dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode));
-
- /* Oplock break.... */
- unlock_share_entry(cnum, dev, inode, token);
- if(request_oplock_break(share_entry, dev, inode) == False)
- {
- free((char *)old_shares);
- DEBUG(0,("check_file_sharing: FAILED when breaking oplock (%x) on file %s, \
-dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode));
- return False;
- }
- lock_share_entry(cnum, dev, inode, &token);
- broke_oplock = True;
- break;
- }
+ if (old_shares[i].share_mode != DENY_DOS)
+ goto free_and_exit;
- /* someone else has a share lock on it, check to see
- if we can too */
- if ((share_entry->share_mode != DENY_DOS) || (share_entry->pid != pid))
- goto free_and_exit;
-
- } /* end for */
-
- if(broke_oplock)
- {
- free((char *)old_shares);
- num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares);
- }
- } while(broke_oplock);
+ if(old_shares[i].pid != pid)
+ goto free_and_exit;
}
/* XXXX exactly what share mode combinations should be allowed for
@@ -1640,7 +1568,7 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode));
free_and_exit:
- unlock_share_entry(cnum, dev, inode, token);
+ unlock_share_entry(cnum, (uint32)sbuf.st_dev, (uint32)sbuf.st_ino, token);
if(old_shares != NULL)
free((char *)old_shares);
return(ret);
@@ -1651,8 +1579,8 @@ free_and_exit:
Helper for open_file_shared.
Truncate a file after checking locking; close file if locked.
**************************************************************************/
-static void truncate_unless_locked(int fnum, int cnum, int token,
- BOOL *share_locked)
+static void truncate_unless_locked(int fnum, int cnum, share_lock_token token,
+ BOOL *share_locked)
{
if (Files[fnum].can_write){
if (is_locked(fnum,cnum,0x3FFFFFFF,0)){
@@ -1661,7 +1589,7 @@ static void truncate_unless_locked(int fnum, int cnum, int token,
if (*share_locked && lp_share_modes(SNUM(cnum)))
unlock_share_entry( cnum, Files[fnum].fd_ptr->dev,
Files[fnum].fd_ptr->inode, token);
- close_file(fnum,False);
+ close_file(fnum, 0);
/* Share mode no longer locked. */
*share_locked = False;
errno = EACCES;
@@ -1673,52 +1601,12 @@ static void truncate_unless_locked(int fnum, int cnum, int token,
}
}
-/****************************************************************************
-check if we can open a file with a share mode
-****************************************************************************/
-int check_share_mode( share_mode_entry *share, int deny_mode, char *fname,
- BOOL fcbopen, int *flags)
-{
- int old_open_mode = share->share_mode &0xF;
- int old_deny_mode = (share->share_mode >>4)&7;
-
- if (old_deny_mode > 4 || old_open_mode > 2)
- {
- DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n",
- deny_mode,old_deny_mode,old_open_mode,fname));
- return False;
- }
-
- {
- int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
- share->pid,fname);
-
- if ((access_allowed == AFAIL) ||
- (!fcbopen && (access_allowed == AREAD && *flags == O_RDWR)) ||
- (access_allowed == AREAD && *flags == O_WRONLY) ||
- (access_allowed == AWRITE && *flags == O_RDONLY))
- {
- DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s,fcbopen = %d, flags = %d) = %d\n",
- deny_mode,old_deny_mode,old_open_mode,
- share->pid,fname, fcbopen, *flags, access_allowed));
- return False;
- }
-
- if (access_allowed == AREAD)
- *flags = O_RDONLY;
-
- if (access_allowed == AWRITE)
- *flags = O_WRONLY;
-
- }
- return True;
-}
/****************************************************************************
open a file with a share mode
****************************************************************************/
void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
- int mode,int oplock_request, int *Access,int *action)
+ int mode,int *Access,int *action)
{
files_struct *fs_p = &Files[fnum];
int flags=0;
@@ -1728,10 +1616,9 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
BOOL file_existed = file_exist(fname,&sbuf);
BOOL share_locked = False;
BOOL fcbopen = False;
- int token;
+ share_lock_token token;
uint32 dev = 0;
uint32 inode = 0;
- int num_share_modes = 0;
fs_p->open = False;
fs_p->fd_ptr = 0;
@@ -1803,8 +1690,10 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
if (lp_share_modes(SNUM(cnum)))
{
+ int num_shares = 0;
int i;
- share_mode_entry *old_shares = 0;
+ min_share_mode_entry *old_shares = 0;
+
if (file_existed)
{
@@ -1812,77 +1701,58 @@ void open_file_shared(int fnum,int cnum,char *fname,int share_mode,int ofun,
inode = (uint32)sbuf.st_ino;
lock_share_entry(cnum, dev, inode, &token);
share_locked = True;
- num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares);
+ num_shares = get_share_modes(cnum, token, dev, inode, &old_shares);
}
- /*
- * Check if the share modes will give us access.
- */
-
- if(share_locked && (num_share_modes != 0))
+ for(i = 0; i < num_shares; i++)
{
- BOOL broke_oplock;
+ /* someone else has a share lock on it, check to see
+ if we can too */
+ int old_open_mode = old_shares[i].share_mode &0xF;
+ int old_deny_mode = (old_shares[i].share_mode >>4)&7;
- do
+ if (old_deny_mode > 4 || old_open_mode > 2)
{
+ DEBUG(0,("Invalid share mode found (%d,%d,%d) on file %s\n",
+ deny_mode,old_deny_mode,old_open_mode,fname));
+ free((char *)old_shares);
+ if(share_locked)
+ unlock_share_entry(cnum, dev, inode, token);
+ errno = EACCES;
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadshare;
+ return;
+ }
- broke_oplock = False;
- for(i = 0; i < num_share_modes; i++)
- {
- share_mode_entry *share_entry = &old_shares[i];
-
- /*
- * By observation of NetBench, oplocks are broken *before* share
- * modes are checked. This allows a file to be closed by the client
- * if the share mode would deny access and the client has an oplock.
- * Check if someone has an oplock on this file. If so we must break
- * it before continuing.
- */
- if(share_entry->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
- {
-
- DEBUG(5,("open_file_shared: breaking oplock (%x) on file %s, \
-dev = %x, inode = %x\n", share_entry->op_type, fname, dev, inode));
-
- /* Oplock break.... */
- unlock_share_entry(cnum, dev, inode, token);
- if(request_oplock_break(share_entry, dev, inode) == False)
- {
- free((char *)old_shares);
- DEBUG(0,("open_file_shared: FAILED when breaking oplock (%x) on file %s, \
-dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode));
- errno = EACCES;
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadshare;
- return;
- }
- lock_share_entry(cnum, dev, inode, &token);
- broke_oplock = True;
- break;
- }
-
- /* someone else has a share lock on it, check to see
- if we can too */
- if(check_share_mode(share_entry, deny_mode, fname, fcbopen, &flags) == False)
- {
- free((char *)old_shares);
- unlock_share_entry(cnum, dev, inode, token);
- errno = EACCES;
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbadshare;
- return;
- }
-
- } /* end for */
+ {
+ int access_allowed = access_table(deny_mode,old_deny_mode,old_open_mode,
+ old_shares[i].pid,fname);
- if(broke_oplock)
+ if ((access_allowed == AFAIL) ||
+ (!fcbopen && (access_allowed == AREAD && flags == O_RDWR)) ||
+ (access_allowed == AREAD && flags == O_WRONLY) ||
+ (access_allowed == AWRITE && flags == O_RDONLY))
{
+ DEBUG(2,("Share violation on file (%d,%d,%d,%d,%s) = %d\n",
+ deny_mode,old_deny_mode,old_open_mode,
+ old_shares[i].pid,fname,
+ access_allowed));
free((char *)old_shares);
- num_share_modes = get_share_modes(cnum, token, dev, inode, &old_shares);
+ if(share_locked)
+ unlock_share_entry(cnum, dev, inode, token);
+ errno = EACCES;
+ unix_ERR_class = ERRDOS;
+ unix_ERR_code = ERRbadshare;
+ return;
}
- } while(broke_oplock);
+
+ if (access_allowed == AREAD)
+ flags = O_RDONLY;
+
+ if (access_allowed == AWRITE)
+ flags = O_WRONLY;
+ }
}
-
if(old_shares != 0)
free((char *)old_shares);
}
@@ -1939,32 +1809,7 @@ dev = %x, inode = %x\n", old_shares[i].op_type, fname, dev, inode));
file (which expects the share_mode_entry to be there).
*/
if (lp_share_modes(SNUM(cnum)))
- {
- uint16 port = 0;
- /* JRA. Currently this only services Exlcusive and batch
- oplocks (no other opens on this file). This needs to
- be extended to level II oplocks (multiple reader
- oplocks). */
-
- if(oplock_request && (num_share_modes == 0) && lp_oplocks(SNUM(cnum)) &&
- !IS_VETO_OPLOCK_PATH(cnum,fname))
- {
- fs_p->granted_oplock = True;
- fs_p->sent_oplock_break = False;
- global_oplocks_open++;
- port = oplock_port;
-
- DEBUG(5,("open_file_shared: granted oplock (%x) on file %s, \
-dev = %x, inode = %x\n", oplock_request, fname, dev, inode));
-
- }
- else
- {
- port = 0;
- oplock_request = 0;
- }
- set_share_mode(token, fnum, port, oplock_request);
- }
+ set_share_mode(token, fnum);
if ((flags2&O_TRUNC) && file_existed)
truncate_unless_locked(fnum,cnum,token,&share_locked);
@@ -2215,7 +2060,11 @@ struct
{EPERM,ERRDOS,ERRnoaccess},
{EACCES,ERRDOS,ERRnoaccess},
{ENOENT,ERRDOS,ERRbadfile},
+#if 0 /* Go back to old method for now. */
+ {ENOTDIR,ERRDOS,ERRbaddirectory},
+#else
{ENOTDIR,ERRDOS,ERRbadpath},
+#endif
{EIO,ERRHRD,ERRgeneral},
{EBADF,ERRSRV,ERRsrverror},
{EINVAL,ERRSRV,ERRsrverror},
@@ -2236,6 +2085,23 @@ struct
{0,0,0}
};
+#if 0 /* Go back to old method for now. */
+/* Mapping for old clients. */
+
+struct
+{
+ int new_smb_error;
+ int old_smb_error;
+ int protocol_level;
+ enum remote_arch_types valid_ra_type;
+} old_client_errmap[] =
+{
+ {ERRbaddirectory, ERRbadpath, (int)PROTOCOL_NT1, RA_WINNT},
+ {0,0,0}
+};
+
+#endif /* Go back to old method for now. */
+
/****************************************************************************
create an error packet from errno
****************************************************************************/
@@ -2266,6 +2132,32 @@ int unix_error_packet(char *inbuf,char *outbuf,int def_class,uint32 def_code,int
}
}
+#if 0 /* Go back to old method for now. */
+
+ /* Make sure we don't return error codes that old
+ clients don't understand. */
+
+ /* JRA - unfortunately, WinNT needs some error codes
+ for apps to work correctly, Win95 will break if
+ these error codes are returned. But they both
+ negotiate the *same* protocol. So we need to use
+ the revolting 'remote_arch' enum to tie break.
+
+ There must be a better way of doing this...
+ */
+
+ for(i = 0; old_client_errmap[i].new_smb_error != 0; i++)
+ {
+ if(((Protocol < old_client_errmap[i].protocol_level) ||
+ (old_client_errmap[i].valid_ra_type != get_remote_arch())) &&
+ (old_client_errmap[i].new_smb_error == ecode))
+ {
+ ecode = old_client_errmap[i].old_smb_error;
+ break;
+ }
+ }
+#endif /* Go back to old method for now. */
+
return(error_packet(inbuf,outbuf,eclass,ecode,line));
}
@@ -2373,780 +2265,104 @@ static BOOL open_sockets(BOOL is_daemon,int port)
extern int Client;
if (is_daemon)
- {
- int num_interfaces = iface_count();
- int fd_listenset[FD_SETSIZE];
- fd_set listen_set;
- int s;
- int i;
-
- /* Stop zombies */
+ {
+ int s;
+ struct sockaddr addr;
+ int in_addrlen = sizeof(addr);
+
+ /* Stop zombies */
#ifdef SIGCLD_IGNORE
- signal(SIGCLD, SIG_IGN);
+ signal(SIGCLD, SIG_IGN);
#else
- signal(SIGCLD, SIGNAL_CAST sig_cld);
+ signal(SIGCLD, SIGNAL_CAST sig_cld);
#endif
- if(atexit_set == 0)
- atexit(killkids);
-
- FD_ZERO(&listen_set);
-
- if(lp_interfaces() && lp_bind_interfaces_only())
- {
- /* We have been given an interfaces line, and been
- told to only bind to those interfaces. Create a
- socket per interface and bind to only these.
- */
-
- if(num_interfaces > FD_SETSIZE)
- {
- DEBUG(0,("open_sockets: Too many interfaces specified to bind to. Number was %d \
-max can be %d\n", num_interfaces, FD_SETSIZE));
- return False;
- }
-
- /* Now open a listen socket for each of the interfaces. */
- for(i = 0; i < num_interfaces; i++)
- {
- struct in_addr *ifip = iface_n_ip(i);
-
- if(ifip == NULL)
- {
- DEBUG(0,("open_sockets: interface %d has NULL IP address !\n", i));
- continue;
- }
- s = fd_listenset[i] = open_socket_in(SOCK_STREAM, port, 0, ifip->s_addr);
- if(s == -1)
- return False;
- /* ready to listen */
- if (listen(s, 5) == -1)
- {
- DEBUG(0,("listen: %s\n",strerror(errno)));
- close(s);
- return False;
- }
- FD_SET(s,&listen_set);
- }
- }
- else
- {
- /* Just bind to 0.0.0.0 - accept connections from anywhere. */
- num_interfaces = 1;
-
/* open an incoming socket */
s = open_socket_in(SOCK_STREAM, port, 0,interpret_addr(lp_socket_address()));
if (s == -1)
- return(False);
+ return(False);
/* ready to listen */
if (listen(s, 5) == -1)
- {
- DEBUG(0,("open_sockets: listen: %s\n",strerror(errno)));
- close(s);
- return False;
- }
-
- fd_listenset[0] = s;
- FD_SET(s,&listen_set);
- }
-
- /* now accept incoming connections - forking a new process
- for each incoming connection */
- DEBUG(2,("waiting for a connection\n"));
- while (1)
- {
- fd_set lfds;
- int num;
-
- memcpy((char *)&lfds, (char *)&listen_set, sizeof(listen_set));
-
- num = sys_select(&lfds,NULL);
-
- if (num == -1 && errno == EINTR)
- continue;
-
- /* Find the sockets that are read-ready - accept on these. */
- for( ; num > 0; num--)
- {
- struct sockaddr addr;
- int in_addrlen = sizeof(addr);
-
- s = -1;
- for(i = 0; i < num_interfaces; i++)
- {
- if(FD_ISSET(fd_listenset[i],&lfds))
- {
- s = fd_listenset[i];
- /* Clear this so we don't look at it again. */
- FD_CLR(fd_listenset[i],&lfds);
- break;
- }
- }
+ {
+ DEBUG(0,("listen: %s\n",strerror(errno)));
+ close(s);
+ return False;
+ }
+
+ if(atexit_set == 0)
+ atexit(killkids);
- Client = accept(s,&addr,&in_addrlen);
+ /* now accept incoming connections - forking a new process
+ for each incoming connection */
+ DEBUG(2,("waiting for a connection\n"));
+ while (1)
+ {
+ Client = accept(s,&addr,&in_addrlen);
- if (Client == -1 && errno == EINTR)
- continue;
+ if (Client == -1 && errno == EINTR)
+ continue;
- if (Client == -1)
- {
- DEBUG(0,("open_sockets: accept: %s\n",strerror(errno)));
- continue;
- }
+ if (Client == -1)
+ {
+ DEBUG(0,("accept: %s\n",strerror(errno)));
+ continue;
+ }
#ifdef NO_FORK_DEBUG
#ifndef NO_SIGNAL_TEST
- signal(SIGPIPE, SIGNAL_CAST sig_pipe);
- signal(SIGCLD, SIGNAL_CAST SIG_DFL);
-#endif /* NO_SIGNAL_TEST */
- return True;
-#else /* NO_FORK_DEBUG */
- if (Client != -1 && fork()==0)
- {
- /* Child code ... */
-
-#ifndef NO_SIGNAL_TEST
signal(SIGPIPE, SIGNAL_CAST sig_pipe);
signal(SIGCLD, SIGNAL_CAST SIG_DFL);
-#endif /* NO_SIGNAL_TEST */
- /* close the listening socket(s) */
- for(i = 0; i < num_interfaces; i++)
- close(fd_listenset[i]);
-
- /* close our standard file descriptors */
- close_low_fds();
- am_parent = 0;
-
- set_socket_options(Client,"SO_KEEPALIVE");
- set_socket_options(Client,user_socket_options);
-
- /* Reset global variables in util.c so that
- client substitutions will be done correctly
- in the process.
- */
- reset_globals_after_fork();
- return True;
- }
- close(Client); /* The parent doesn't need this socket */
-#endif /NO_FORK_DEBUG */
- } /* end for num */
- } /* end while 1 */
- } /* end if is_daemon */
- else
- {
- /* Started from inetd. fd 0 is the socket. */
- /* We will abort gracefully when the client or remote system
- goes away */
-#ifndef NO_SIGNAL_TEST
- signal(SIGPIPE, SIGNAL_CAST sig_pipe);
#endif
- Client = dup(0);
-
- /* close our standard file descriptors */
- close_low_fds();
-
- set_socket_options(Client,"SO_KEEPALIVE");
- set_socket_options(Client,user_socket_options);
- }
-
- return True;
-}
-
-/****************************************************************************
- process an smb from the client - split out from the process() code so
- it can be used by the oplock break code.
-****************************************************************************/
-
-static void process_smb(char *inbuf, char *outbuf)
-{
- extern int Client;
- static int trans_num;
- int msg_type = CVAL(inbuf,0);
- int32 len = smb_len(inbuf);
- int nread = len + 4;
-
- if (trans_num == 0) {
- /* on the first packet, check the global hosts allow/ hosts
- deny parameters before doing any parsing of the packet
- passed to us by the client. This prevents attacks on our
- parsing code from hosts not in the hosts allow list */
- if (!check_access(-1)) {
- /* send a negative session response "not listining on calling
- name" */
- static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
- DEBUG(1,("%s Connection denied from %s\n",
- timestring(),client_addr()));
- send_smb(Client,(char *)buf);
- exit_server("connection denied");
- }
- }
-
- DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
- DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
-
-#ifdef WITH_VTP
- if(trans_num == 1 && VT_Check(inbuf))
- {
- VT_Process();
- return;
- }
+ return True;
+#else
+ if (Client != -1 && fork()==0)
+ {
+ /* Child code ... */
+#ifndef NO_SIGNAL_TEST
+ signal(SIGPIPE, SIGNAL_CAST sig_pipe);
+ signal(SIGCLD, SIGNAL_CAST SIG_DFL);
#endif
+ /* close the listening socket */
+ close(s);
- if (msg_type == 0)
- show_msg(inbuf);
-
- nread = construct_reply(inbuf,outbuf,nread,max_send);
-
- if(nread > 0)
- {
- if (CVAL(outbuf,0) == 0)
- show_msg(outbuf);
-
- if (nread != smb_len(outbuf) + 4)
- {
- DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
- nread, smb_len(outbuf)));
- }
- else
- send_smb(Client,outbuf);
- }
- trans_num++;
-}
-
-/****************************************************************************
- open the oplock IPC socket communication
-****************************************************************************/
-static BOOL open_oplock_ipc()
-{
- struct sockaddr_in sock_name;
- int len = sizeof(sock_name);
-
- DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n"));
-
- /* Open a lookback UDP socket on a random port. */
- oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK));
- if (oplock_sock == -1)
- {
- DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \
-address %x. Error was %s\n", htonl(INADDR_LOOPBACK), strerror(errno)));
- oplock_port = 0;
- return(False);
- }
-
- /* Find out the transient UDP port we have been allocated. */
- if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0)
- {
- DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n",
- strerror(errno)));
- close(oplock_sock);
- oplock_sock = -1;
- oplock_port = 0;
- return False;
- }
- oplock_port = ntohs(sock_name.sin_port);
-
- DEBUG(3,("open_oplock ipc: pid = %d, oplock_port = %u\n",
- getpid(), oplock_port));
-
- return True;
-}
-
-/****************************************************************************
- process an oplock break message.
-****************************************************************************/
-static BOOL process_local_message(int sock, char *buffer, int buf_size)
-{
- int32 msg_len;
- uint16 from_port;
- char *msg_start;
-
- msg_len = IVAL(buffer,UDP_CMD_LEN_OFFSET);
- from_port = SVAL(buffer,UDP_CMD_PORT_OFFSET);
-
- msg_start = &buffer[UDP_CMD_HEADER_LEN];
-
- DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n",
- msg_len, from_port));
-
- /* Switch on message command - currently OPLOCK_BREAK_CMD is the
- only valid request. */
-
- switch(SVAL(msg_start,UDP_MESSAGE_CMD_OFFSET))
- {
- case OPLOCK_BREAK_CMD:
- /* Ensure that the msg length is correct. */
- if(msg_len != OPLOCK_BREAK_MSG_LEN)
- {
- DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, \
-should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN));
- return False;
- }
- {
- uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET);
- uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
- uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
- struct timeval tval;
- struct sockaddr_in toaddr;
-
- tval.tv_sec = IVAL(msg_start, OPLOCK_BREAK_SEC_OFFSET);
- tval.tv_usec = IVAL(msg_start, OPLOCK_BREAK_USEC_OFFSET);
-
- DEBUG(5,("process_local_message: oplock break request from \
-pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode));
-
- /*
- * If we have no record of any currently open oplocks,
- * it's not an error, as a close command may have
- * just been issued on the file that was oplocked.
- * Just return success in this case.
- */
-
- if(global_oplocks_open != 0)
- {
- if(oplock_break(dev, inode, &tval) == False)
- {
- DEBUG(0,("process_local_message: oplock break failed - \
-not returning udp message.\n"));
- return False;
- }
- }
- else
- {
- DEBUG(3,("process_local_message: oplock break requested with no outstanding \
-oplocks. Returning success.\n"));
- }
-
- /* Send the message back after OR'ing in the 'REPLY' bit. */
- SSVAL(msg_start,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD | CMD_REPLY);
+ /* close our standard file descriptors */
+ close_low_fds();
+ am_parent = 0;
- bzero((char *)&toaddr,sizeof(toaddr));
- toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- toaddr.sin_port = htons(from_port);
- toaddr.sin_family = AF_INET;
-
- if(sendto( sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0,
- (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0)
- {
- DEBUG(0,("process_local_message: sendto process %d failed. Errno was %s\n",
- remotepid, strerror(errno)));
- return False;
- }
-
- DEBUG(5,("process_local_message: oplock break reply sent to \
-pid %d, port %d, for file dev = %x, inode = %x\n", remotepid,
- from_port, dev, inode));
-
- }
- break;
- /*
- * Keep this as a debug case - eventually we can remove it.
- */
- case 0x8001:
- DEBUG(0,("process_local_message: Received unsolicited break \
-reply - dumping info.\n"));
-
- if(msg_len != OPLOCK_BREAK_MSG_LEN)
- {
- DEBUG(0,("process_local_message: ubr: incorrect length for reply \
-(was %d, should be %d).\n", msg_len, OPLOCK_BREAK_MSG_LEN));
- return False;
- }
-
- {
- uint32 remotepid = IVAL(msg_start,OPLOCK_BREAK_PID_OFFSET);
- uint32 dev = IVAL(msg_start,OPLOCK_BREAK_DEV_OFFSET);
- uint32 inode = IVAL(msg_start, OPLOCK_BREAK_INODE_OFFSET);
-
- DEBUG(0,("process_local_message: unsolicited oplock break reply from \
-pid %d, port %d, dev = %x, inode = %x\n", remotepid, from_port, dev, inode));
-
- }
- return False;
-
- default:
- DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n",
- (unsigned int)SVAL(msg_start,0)));
- return False;
- }
- return True;
-}
-
-/****************************************************************************
- Process an oplock break directly.
-****************************************************************************/
-BOOL oplock_break(uint32 dev, uint32 inode, struct timeval *tval)
-{
- extern int Client;
- static char *inbuf = NULL;
- static char *outbuf = NULL;
- files_struct *fsp = NULL;
- int fnum;
- time_t start_time;
- BOOL shutdown_server = False;
-
- DEBUG(3,("%s oplock_break: called for dev = %x, inode = %x. Current \
-global_oplocks_open = %d\n", timestring(), dev, inode, global_oplocks_open));
-
- /* We need to search the file open table for the
- entry containing this dev and inode, and ensure
- we have an oplock on it. */
- for( fnum = 0; fnum < MAX_OPEN_FILES; fnum++)
- {
- if(OPEN_FNUM(fnum))
- {
- if((Files[fnum].fd_ptr->dev == dev) && (Files[fnum].fd_ptr->inode == inode) &&
- (Files[fnum].open_time.tv_sec == tval->tv_sec) &&
- (Files[fnum].open_time.tv_usec == tval->tv_usec)) {
- fsp = &Files[fnum];
- break;
- }
- }
- }
-
- if(fsp == NULL)
- {
- /* The file could have been closed in the meantime - return success. */
- DEBUG(0,("%s oplock_break: cannot find open file with dev = %x, inode = %x (fnum = %d) \
-allowing break to succeed.\n", timestring(), dev, inode, fnum));
- return True;
- }
-
- /* Ensure we have an oplock on the file */
-
- /* There is a potential race condition in that an oplock could
- have been broken due to another udp request, and yet there are
- still oplock break messages being sent in the udp message
- queue for this file. So return true if we don't have an oplock,
- as we may have just freed it.
- */
-
- if(!fsp->granted_oplock)
- {
- DEBUG(0,("%s oplock_break: file %s (fnum = %d, dev = %x, inode = %x) has no oplock. Allowing break to succeed regardless.\n", timestring(), fsp->name, fnum, dev, inode));
- return True;
- }
-
- /* mark the oplock break as sent - we don't want to send twice! */
- if (fsp->sent_oplock_break)
- {
- DEBUG(0,("%s oplock_break: ERROR: oplock_break already sent for file %s (fnum = %d, dev = %x, inode = %x)\n", timestring(), fsp->name, fnum, dev, inode));
-
- /* We have to fail the open here as we cannot send another oplock break on this
- file whilst we are awaiting a response from the client - neither can we
- allow another open to succeed while we are waiting for the client. */
- return False;
- }
-
- /* Now comes the horrid part. We must send an oplock break to the client,
- and then process incoming messages until we get a close or oplock release.
- At this point we know we need a new inbuf/outbuf buffer pair.
- We cannot use these staticaly as we may recurse into here due to
- messages crossing on the wire.
- */
-
- if((inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL)
- {
- DEBUG(0,("oplock_break: malloc fail for input buffer.\n"));
- return False;
- }
-
- if((outbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN))==NULL)
- {
- DEBUG(0,("oplock_break: malloc fail for output buffer.\n"));
- free(inbuf);
- inbuf = NULL;
- return False;
- }
-
- /* Prepare the SMBlockingX message. */
- bzero(outbuf,smb_size);
- set_message(outbuf,8,0,True);
-
- SCVAL(outbuf,smb_com,SMBlockingX);
- SSVAL(outbuf,smb_tid,fsp->cnum);
- SSVAL(outbuf,smb_pid,0xFFFF);
- SSVAL(outbuf,smb_uid,0);
- SSVAL(outbuf,smb_mid,0xFFFF);
- SCVAL(outbuf,smb_vwv0,0xFF);
- SSVAL(outbuf,smb_vwv2,fnum);
- SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE);
- /* Change this when we have level II oplocks. */
- SCVAL(outbuf,smb_vwv3+1,OPLOCKLEVEL_NONE);
-
- send_smb(Client, outbuf);
-
- /* Remember we just sent an oplock break on this file. */
- fsp->sent_oplock_break = True;
-
- /* We need this in case a readraw crosses on the wire. */
- global_oplock_break = True;
-
- /* Process incoming messages. */
-
- /* JRA - If we don't get a break from the client in OPLOCK_BREAK_TIMEOUT
- seconds we should just die.... */
-
- start_time = time(NULL);
-
- while(OPEN_FNUM(fnum) && fsp->granted_oplock)
- {
- if(receive_smb(Client,inbuf,OPLOCK_BREAK_TIMEOUT * 1000) == False)
- {
- /*
- * Die if we got an error.
- */
-
- if (smb_read_error == READ_EOF)
- DEBUG(0,("%s oplock_break: end of file from client\n", timestring()));
-
- if (smb_read_error == READ_ERROR)
- DEBUG(0,("%s oplock_break: receive_smb error (%s)\n",
- timestring(), strerror(errno)));
-
- if (smb_read_error == READ_TIMEOUT)
- DEBUG(0,("%s oplock_break: receive_smb timed out after %d seconds.\n",
- timestring(), OPLOCK_BREAK_TIMEOUT));
-
- DEBUG(0,("%s oplock_break failed for file %s (fnum = %d, dev = %x, \
-inode = %x).\n", timestring(), fsp->name, fnum, dev, inode));
- shutdown_server = True;
- break;
- }
- process_smb(inbuf, outbuf);
-
- /*
- * Die if we go over the time limit.
- */
-
- if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT)
- {
- DEBUG(0,("%s oplock_break: no break received from client within \
-%d seconds.\n", timestring(), OPLOCK_BREAK_TIMEOUT));
- DEBUG(0,("%s oplock_break failed for file %s (fnum = %d, dev = %x, \
-inode = %x).\n", timestring(), fsp->name, fnum, dev, inode));
- shutdown_server = True;
- break;
- }
- }
-
- /* Free the buffers we've been using to recurse. */
- free(inbuf);
- free(outbuf);
-
- /* We need this in case a readraw crossed on the wire. */
- if(global_oplock_break)
- global_oplock_break = False;
-
- /*
- * If the client did not respond we must die.
- */
-
- if(shutdown_server)
- {
- DEBUG(0,("%s oplock_break: client failure in break - shutting down this smbd.\n",
- timestring()));
- close_sockets();
- close(oplock_sock);
- exit_server("oplock break failure");
- }
-
- if(OPEN_FNUM(fnum))
- {
- /* The lockingX reply will have removed the oplock flag
- from the sharemode. */
- /* Paranoia.... */
- fsp->granted_oplock = False;
- fsp->sent_oplock_break = False;
- global_oplocks_open--;
- }
-
- /* Santity check - remove this later. JRA */
- if(global_oplocks_open < 0)
- {
- DEBUG(0,("oplock_break: global_oplocks_open < 0 (%d). PANIC ERROR\n",
- global_oplocks_open));
- exit_server("oplock_break: global_oplocks_open < 0");
- }
-
- DEBUG(3,("%s oplock_break: returning success for fnum = %d, dev = %x, inode = %x. Current \
-global_oplocks_open = %d\n", timestring(), fnum, dev, inode, global_oplocks_open));
-
- return True;
-}
-
-/****************************************************************************
-Send an oplock break message to another smbd process. If the oplock is held
-by the local smbd then call the oplock break function directly.
-****************************************************************************/
-
-BOOL request_oplock_break(share_mode_entry *share_entry,
- uint32 dev, uint32 inode)
-{
- char op_break_msg[OPLOCK_BREAK_MSG_LEN];
- struct sockaddr_in addr_out;
- int pid = getpid();
-
- if(pid == share_entry->pid)
- {
- /* We are breaking our own oplock, make sure it's us. */
- if(share_entry->op_port != oplock_port)
- {
- DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \
-should be %d\n", pid, share_entry->op_port, oplock_port));
- return False;
+ set_socket_options(Client,"SO_KEEPALIVE");
+ set_socket_options(Client,user_socket_options);
+
+ /* Reset global variables in util.c so that
+ client substitutions will be done correctly
+ in the process.
+ */
+ reset_globals_after_fork();
+ return True;
+ }
+ close(Client); /* The parent doesn't need this socket */
+#endif
+ }
}
-
- DEBUG(5,("request_oplock_break: breaking our own oplock\n"));
-
- /* Call oplock break direct. */
- return oplock_break(dev, inode, &share_entry->time);
- }
-
- /* We need to send a OPLOCK_BREAK_CMD message to the
- port in the share mode entry. */
-
- SSVAL(op_break_msg,UDP_MESSAGE_CMD_OFFSET,OPLOCK_BREAK_CMD);
- SIVAL(op_break_msg,OPLOCK_BREAK_PID_OFFSET,pid);
- SIVAL(op_break_msg,OPLOCK_BREAK_DEV_OFFSET,dev);
- SIVAL(op_break_msg,OPLOCK_BREAK_INODE_OFFSET,inode);
- SIVAL(op_break_msg,OPLOCK_BREAK_SEC_OFFSET,(uint32)share_entry->time.tv_sec);
- SIVAL(op_break_msg,OPLOCK_BREAK_USEC_OFFSET,(uint32)share_entry->time.tv_usec);
-
- /* set the address and port */
- bzero((char *)&addr_out,sizeof(addr_out));
- addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- addr_out.sin_port = htons( share_entry->op_port );
- addr_out.sin_family = AF_INET;
-
- DEBUG(3,("%s request_oplock_break: sending a oplock break message to pid %d on port %d \
-for dev = %x, inode = %x\n", timestring(), share_entry->pid, share_entry->op_port, dev, inode));
-
- if(sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0,
- (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0)
- {
- DEBUG(0,("%s request_oplock_break: failed when sending a oplock break message \
-to pid %d on port %d for dev = %x, inode = %x. Error was %s\n",
- timestring(), share_entry->pid, share_entry->op_port, dev, inode,
- strerror(errno)));
- return False;
- }
-
- /*
- * Now we must await the oplock broken message coming back
- * from the target smbd process. Timeout if it fails to
- * return in (OPLOCK_BREAK_TIMEOUT + OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) seconds.
- * While we get messages that aren't ours, loop.
- */
-
- while(1)
- {
- char op_break_reply[UDP_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN];
- int32 reply_msg_len;
- uint16 reply_from_port;
- char *reply_msg_start;
-
- if(receive_local_message(oplock_sock, op_break_reply, sizeof(op_break_reply),
- (OPLOCK_BREAK_TIMEOUT+OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) * 1000) == False)
+ else
{
- if(smb_read_error == READ_TIMEOUT)
- {
- DEBUG(0,("%s request_oplock_break: no response received to oplock break request to \
-pid %d on port %d for dev = %x, inode = %x\n", timestring(), share_entry->pid,
- share_entry->op_port, dev, inode));
- /*
- * This is a hack to make handling of failing clients more robust.
- * If a oplock break response message is not received in the timeout
- * period we may assume that the smbd servicing that client holding
- * the oplock has died and the client changes were lost anyway, so
- * we should continue to try and open the file.
- */
- break;
- }
- else
- DEBUG(0,("%s request_oplock_break: error in response received to oplock break request to \
-pid %d on port %d for dev = %x, inode = %x. Error was (%s).\n", timestring, share_entry->pid,
- share_entry->op_port, dev, inode, strerror(errno)));
- return False;
- }
-
- /*
- * If the response we got was not an answer to our message, but
- * was a completely different request, push it onto the pending
- * udp message stack so that we can deal with it in the main loop.
- * It may be another oplock break request to us.
- */
-
- /*
- * Local note from JRA. There exists the possibility of a denial
- * of service attack here by allowing non-root processes running
- * on a local machine sending many of these pending messages to
- * a smbd port. Currently I'm not sure how to restrict the messages
- * I will queue (although I could add a limit to the queue) to
- * those received by root processes only. There should be a
- * way to make this bulletproof....
- */
-
- reply_msg_len = IVAL(op_break_reply,UDP_CMD_LEN_OFFSET);
- reply_from_port = SVAL(op_break_reply,UDP_CMD_PORT_OFFSET);
-
- reply_msg_start = &op_break_reply[UDP_CMD_HEADER_LEN];
+ /* We will abort gracefully when the client or remote system
+ goes away */
+#ifndef NO_SIGNAL_TEST
+ signal(SIGPIPE, SIGNAL_CAST sig_pipe);
+#endif
+ Client = dup(0);
- if(reply_msg_len != OPLOCK_BREAK_MSG_LEN)
- {
- /* Ignore it. */
- DEBUG(0,("%s request_oplock_break: invalid message length received. Ignoring\n",
- timestring()));
- continue;
- }
+ /* close our standard file descriptors */
+ close_low_fds();
- if(((SVAL(reply_msg_start,UDP_MESSAGE_CMD_OFFSET) & CMD_REPLY) == 0) ||
- (reply_from_port != share_entry->op_port) ||
- (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET],
- &op_break_msg[OPLOCK_BREAK_PID_OFFSET],
- OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) != 0))
- {
- DEBUG(3,("%s request_oplock_break: received other message whilst awaiting \
-oplock break response from pid %d on port %d for dev = %x, inode = %x.\n",
- timestring(), share_entry->pid, share_entry->op_port, dev, inode));
- if(push_local_message(op_break_reply, sizeof(op_break_reply)) == False)
- return False;
- continue;
+ set_socket_options(Client,"SO_KEEPALIVE");
+ set_socket_options(Client,user_socket_options);
}
- break;
- }
-
- DEBUG(3,("%s request_oplock_break: broke oplock.\n", timestring()));
-
return True;
}
-/****************************************************************************
-Get the next SMB packet, doing the local message processing automatically.
-****************************************************************************/
-
-BOOL receive_next_smb(int smbfd, int oplockfd, char *inbuf, int bufsize, int timeout)
-{
- BOOL got_smb = False;
- BOOL ret;
-
- do
- {
- ret = receive_message_or_smb(smbfd,oplockfd,inbuf,bufsize,
- timeout,&got_smb);
-
- if(ret && !got_smb)
- {
- /* Deal with oplock break requests from other smbd's. */
- process_local_message(oplock_sock, inbuf, bufsize);
- continue;
- }
- }
- while(ret && !got_smb);
-
- return ret;
-}
/****************************************************************************
check if a snum is in use
@@ -3203,7 +2419,7 @@ BOOL reload_services(BOOL test)
}
}
- reset_mangled_stack( lp_mangledstack() );
+ create_mangled_stack(lp_mangledstack());
/* this forces service parameters to be flushed */
become_service(-1,True);
@@ -3232,8 +2448,7 @@ static int sig_hup()
Setup the groups a user belongs to.
****************************************************************************/
int setup_groups(char *user, int uid, int gid, int *p_ngroups,
- int **p_igroups, gid_t **p_groups,
- int **p_attrs)
+ int **p_igroups, gid_t **p_groups)
{
if (-1 == initgroups(user,gid))
{
@@ -3248,25 +2463,19 @@ int setup_groups(char *user, int uid, int gid, int *p_ngroups,
{
int i,ngroups;
int *igroups;
- int *attrs;
gid_t grp = 0;
ngroups = getgroups(0,&grp);
if (ngroups <= 0)
ngroups = 32;
igroups = (int *)malloc(sizeof(int)*ngroups);
- attrs = (int *)malloc(sizeof(int)*ngroups);
for (i=0;i<ngroups;i++)
- {
- attrs [i] = 0x7; /* XXXX don't know what NT user attributes are yet! */
igroups[i] = 0x42424242;
- }
ngroups = getgroups(ngroups,(gid_t *)igroups);
if (igroups[0] == 0x42424242)
ngroups = 0;
*p_ngroups = ngroups;
- *p_attrs = attrs;
/* The following bit of code is very strange. It is due to the
fact that some OSes use int* and some use gid_t* for
@@ -3288,18 +2497,16 @@ int setup_groups(char *user, int uid, int gid, int *p_ngroups,
groups_use_ints = False;
if (groups_use_ints)
- {
+ {
*p_igroups = igroups;
*p_groups = (gid_t *)igroups;
- }
+ }
else
- {
+ {
gid_t *groups = (gid_t *)igroups;
igroups = (int *)malloc(sizeof(int)*ngroups);
for (i=0;i<ngroups;i++)
- {
igroups[i] = groups[i];
- }
*p_igroups = igroups;
*p_groups = (gid_t *)groups;
}
@@ -3425,17 +2632,8 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de
}
/* admin user check */
-
- /* JRA - original code denied admin user if the share was
- marked read_only. Changed as I don't think this is needed,
- but old code left in case there is a problem here.
- */
- if (user_in_list(user,lp_admin_users(snum))
-#if 0
- && !pcon->read_only)
-#else
- )
-#endif
+ if (user_in_list(user,lp_admin_users(snum)) &&
+ !pcon->read_only)
{
pcon->admin_user = True;
DEBUG(0,("%s logged in as admin user (root privileges)\n",user));
@@ -3456,7 +2654,6 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de
pcon->dirptr = NULL;
pcon->veto_list = NULL;
pcon->hide_list = NULL;
- pcon->veto_oplock_list = NULL;
string_set(&pcon->dirpath,"");
string_set(&pcon->user,user);
@@ -3509,15 +2706,12 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de
/* groups stuff added by ih */
pcon->ngroups = 0;
- pcon->igroups = NULL;
pcon->groups = NULL;
- pcon->attrs = NULL;
if (!IS_IPC(cnum))
{
/* Find all the groups this uid is in and store them. Used by become_user() */
- setup_groups(pcon->user,pcon->uid,pcon->gid,
- &pcon->ngroups,&pcon->igroups,&pcon->groups,&pcon->attrs);
+ setup_groups(pcon->user,pcon->uid,pcon->gid,&pcon->ngroups,&pcon->igroups,&pcon->groups);
/* check number of connections */
if (!claim_connection(cnum,
@@ -3546,7 +2740,7 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de
smbrun(cmd,NULL,False);
}
- if (!become_user(&Connections[cnum], cnum,pcon->vuid))
+ if (!become_user(cnum,pcon->vuid))
{
DEBUG(0,("Can't become connected user!\n"));
pcon->open = False;
@@ -3607,7 +2801,6 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de
{
set_namearray( &pcon->veto_list, lp_veto_files(SNUM(cnum)));
set_namearray( &pcon->hide_list, lp_hide_files(SNUM(cnum)));
- set_namearray( &pcon->veto_oplock_list, lp_veto_oplocks(SNUM(cnum)));
}
{
@@ -3630,35 +2823,14 @@ int make_connection(char *service,char *user,char *password, int pwlen, char *de
****************************************************************************/
int find_free_file(void )
{
- int i;
- static int first_file;
-
- /* we want to give out file handles differently on each new
- connection because of a common bug in MS clients where they try to
- reuse a file descriptor from an earlier smb connection. This code
- increases the chance that the errant client will get an error rather
- than causing corruption */
- if (first_file == 0) {
- first_file = (getpid() ^ (int)time(NULL)) % MAX_OPEN_FILES;
- if (first_file == 0) first_file = 1;
- }
-
- for (i=first_file;i<MAX_OPEN_FILES;i++)
- if (!Files[i].open) {
- memset(&Files[i], 0, sizeof(Files[i]));
- return(i);
- }
-
- /* returning a file handle of 0 is a bad idea - so we start at 1 */
- for (i=1;i<first_file;i++)
- if (!Files[i].open) {
- memset(&Files[i], 0, sizeof(Files[i]));
- return(i);
- }
-
-
- DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
- return(-1);
+ int i;
+ /* we start at 1 here for an obscure reason I can't now remember,
+ but I think is important :-) */
+ for (i=1;i<MAX_OPEN_FILES;i++)
+ if (!Files[i].open)
+ return(i);
+ DEBUG(1,("ERROR! Out of file structures - perhaps increase MAX_OPEN_FILES?\n"));
+ return(-1);
}
/****************************************************************************
@@ -3743,9 +2915,11 @@ int reply_lanman1(char *outbuf)
set_message(outbuf,13,doencrypt?8:0,True);
SSVAL(outbuf,smb_vwv1,secword);
+#ifdef SMB_PASSWD
/* Create a token value and add it to the outgoing packet. */
if (doencrypt)
generate_next_challenge(smb_buf(outbuf));
+#endif
Protocol = PROTOCOL_LANMAN1;
@@ -3792,14 +2966,18 @@ int reply_lanman2(char *outbuf)
if (doencrypt) {
crypt_len = 8;
if (!cli) {
+#ifdef SMB_PASSWD
generate_next_challenge(cryptkey);
+#endif
} else {
memcpy(cryptkey, cli->cryptkey, 8);
+#ifdef SMB_PASSWD
set_challenge(cli->cryptkey);
+#endif
}
}
- set_message(outbuf,13,crypt_len,True);
+ set_message(outbuf,13,doencrypt?8:0,True);
SSVAL(outbuf,smb_vwv1,secword);
SIVAL(outbuf,smb_vwv6,getpid());
if (doencrypt)
@@ -3829,7 +3007,8 @@ int reply_nt1(char *outbuf)
/*
other valid capabilities which we may support at some time...
CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
- CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
+ CAP_LARGE_FILES|CAP_LARGE_READX|
+ CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
*/
int secword=0;
@@ -3852,18 +3031,23 @@ int reply_nt1(char *outbuf)
if (doencrypt) {
crypt_len = 8;
if (!cli) {
+#ifdef SMB_PASSWD
generate_next_challenge(cryptkey);
+#endif
} else {
memcpy(cryptkey, cli->cryptkey, 8);
+#ifdef SMB_PASSWD
set_challenge(cli->cryptkey);
+#endif
}
}
- if (lp_readraw() && lp_writeraw()) {
- capabilities |= CAP_RAW_MODE;
+ if (lp_readraw() && lp_writeraw())
+ {
+ capabilities |= CAP_RAW_MODE;
}
- if (lp_security() >= SEC_USER) secword |= 1;
+ if (lp_security()>=SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
/* decide where (if) to put the encryption challenge, and
@@ -4088,7 +3272,7 @@ static void close_open_files(int cnum)
int i;
for (i=0;i<MAX_OPEN_FILES;i++)
if( Files[i].cnum == cnum && Files[i].open) {
- close_file(i,False);
+ close_file(i, 0);
}
}
@@ -4101,6 +3285,10 @@ void close_cnum(int cnum, uint16 vuid)
{
DirCacheFlush(SNUM(cnum));
+ close_open_files(cnum);
+ dptr_closecnum(cnum);
+
+ /* after this we are running as root, so be careful! */
unbecome_user();
if (!OPEN_CNUM(cnum))
@@ -4121,11 +3309,8 @@ void close_cnum(int cnum, uint16 vuid)
if (lp_status(SNUM(cnum)))
yield_connection(cnum,"STATUS.",MAXSTATUS);
- close_open_files(cnum);
- dptr_closecnum(cnum);
-
/* execute any "postexec = " line */
- if (*lp_postexec(SNUM(cnum)) && become_user(&Connections[cnum], cnum,vuid))
+ if (*lp_postexec(SNUM(cnum)) && become_user(cnum,vuid))
{
pstring cmd;
strcpy(cmd,lp_postexec(SNUM(cnum)));
@@ -4158,7 +3343,6 @@ void close_cnum(int cnum, uint16 vuid)
free_namearray(Connections[cnum].veto_list);
free_namearray(Connections[cnum].hide_list);
- free_namearray(Connections[cnum].veto_oplock_list);
string_set(&Connections[cnum].user,"");
string_set(&Connections[cnum].dirpath,"");
@@ -4413,7 +3597,9 @@ void exit_server(char *reason)
#endif
}
- locking_end();
+#ifdef FAST_SHARE_MODES
+ stop_share_mode_mgmt();
+#endif /* FAST_SHARE_MODES */
DEBUG(3,("%s Server exit (%s)\n",timestring(),reason?reason:""));
exit(0);
@@ -4649,7 +3835,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
unbecome_user();
/* does this protocol need to be run as the connected user? */
- if ((flags & AS_USER) && !become_user(&Connections[cnum], cnum,session_tag)) {
+ if ((flags & AS_USER) && !become_user(cnum,session_tag)) {
if (flags & AS_GUEST)
flags &= ~AS_USER;
else
@@ -4822,7 +4008,6 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
chain_size = 0;
chain_fnum = -1;
- reset_chain_pnum();
bzero(outbuf,smb_size);
@@ -4853,11 +4038,14 @@ int construct_reply(char *inbuf,char *outbuf,int size,int bufsize)
return(outsize);
}
+
/****************************************************************************
process commands from the client
****************************************************************************/
static void process(void)
{
+ static int trans_num = 0;
+ int nread;
extern int Client;
InBuffer = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
@@ -4879,36 +4067,35 @@ static void process(void)
}
#endif
- /* re-initialise the timezone */
- TimeInit();
-
while (True)
- {
- int deadtime = lp_deadtime()*60;
- int counter;
- int last_keepalive=0;
- int service_load_counter = 0;
- BOOL got_smb = False;
-
- if (deadtime <= 0)
- deadtime = DEFAULT_SMBD_TIMEOUT;
+ {
+ int32 len;
+ int msg_type;
+ int msg_flags;
+ int type;
+ int deadtime = lp_deadtime()*60;
+ int counter;
+ int last_keepalive=0;
+ int service_load_counter = 0;
+
+ if (deadtime <= 0)
+ deadtime = DEFAULT_SMBD_TIMEOUT;
#if USE_READ_PREDICTION
- if (lp_readprediction())
- do_read_prediction();
+ if (lp_readprediction())
+ do_read_prediction();
#endif
- errno = 0;
+ errno = 0;
- for (counter=SMBD_SELECT_LOOP;
- !receive_message_or_smb(Client,oplock_sock,
- InBuffer,BUFFER_SIZE,SMBD_SELECT_LOOP*1000,&got_smb);
- counter += SMBD_SELECT_LOOP)
- {
- int i;
- time_t t;
- BOOL allidle = True;
- extern int keepalive;
+ for (counter=SMBD_SELECT_LOOP;
+ !receive_smb(Client,InBuffer,SMBD_SELECT_LOOP*1000);
+ counter += SMBD_SELECT_LOOP)
+ {
+ int i;
+ time_t t;
+ BOOL allidle = True;
+ extern int keepalive;
if (counter > 365 * 3600) /* big number of seconds. */
{
@@ -4916,79 +4103,126 @@ static void process(void)
service_load_counter = 0;
}
- if (smb_read_error == READ_EOF)
- {
- DEBUG(3,("end of file from client\n"));
- return;
- }
+ if (smb_read_error == READ_EOF) {
+ DEBUG(3,("end of file from client\n"));
+ return;
+ }
- if (smb_read_error == READ_ERROR)
- {
- DEBUG(3,("receive_smb error (%s) exiting\n",
- strerror(errno)));
- return;
- }
+ if (smb_read_error == READ_ERROR) {
+ DEBUG(3,("receive_smb error (%s) exiting\n",
+ strerror(errno)));
+ return;
+ }
- t = time(NULL);
+ t = time(NULL);
- /* become root again if waiting */
- unbecome_user();
+ /* become root again if waiting */
+ unbecome_user();
- /* check for smb.conf reload */
- if (counter >= service_load_counter + SMBD_RELOAD_CHECK)
+ /* check for smb.conf reload */
+ if (counter >= service_load_counter + SMBD_RELOAD_CHECK)
{
service_load_counter = counter;
/* reload services, if files have changed. */
- reload_services(True);
+ reload_services(True);
}
- /* automatic timeout if all connections are closed */
- if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT)
- {
- DEBUG(2,("%s Closing idle connection\n",timestring()));
- return;
- }
+ /* automatic timeout if all connections are closed */
+ if (num_connections_open==0 && counter >= IDLE_CLOSED_TIMEOUT) {
+ DEBUG(2,("%s Closing idle connection\n",timestring()));
+ return;
+ }
- if (keepalive && (counter-last_keepalive)>keepalive)
- {
- struct cli_state *cli = server_client();
- if (!send_keepalive(Client)) {
- DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
- return;
- }
- /* also send a keepalive to the password server if its still
- connected */
- if (cli && cli->initialised)
- send_keepalive(cli->fd);
- last_keepalive = counter;
+ if (keepalive && (counter-last_keepalive)>keepalive) {
+ struct cli_state *cli = server_client();
+ if (!send_keepalive(Client)) {
+ DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
+ return;
+ }
+ /* also send a keepalive to the password server if its still
+ connected */
+ if (cli && cli->initialised)
+ send_keepalive(cli->fd);
+ last_keepalive = counter;
+ }
+
+ /* check for connection timeouts */
+ for (i=0;i<MAX_CONNECTIONS;i++)
+ if (Connections[i].open)
+ {
+ /* close dirptrs on connections that are idle */
+ if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
+ dptr_idlecnum(i);
+
+ if (Connections[i].num_files_open > 0 ||
+ (t-Connections[i].lastused)<deadtime)
+ allidle = False;
+ }
+
+ if (allidle && num_connections_open>0) {
+ DEBUG(2,("%s Closing idle connection 2\n",timestring()));
+ return;
+ }
+ }
+
+ if (trans_num == 0) {
+ /* on the first packet, check the global hosts allow/ hosts
+ deny parameters before doing any parsing of the packet
+ passed to us by the client. This prevents attacks on our
+ parsing code from hosts not in the hosts allow list */
+ if (!check_access(-1)) {
+ /* send a negative session response "not listining
+ on calling name" */
+ static unsigned char buf[5] = {0x83, 0, 0, 1, 0x81};
+ DEBUG(1,("%s Connection denied from %s\n",
+ timestring(),client_addr()));
+ send_smb(Client,(char *)buf);
+ exit_server("connection denied");
+ }
}
- /* check for connection timeouts */
- for (i=0;i<MAX_CONNECTIONS;i++)
- if (Connections[i].open)
- {
- /* close dirptrs on connections that are idle */
- if ((t-Connections[i].lastused)>DPTR_IDLE_TIMEOUT)
- dptr_idlecnum(i);
- if (Connections[i].num_files_open > 0 ||
- (t-Connections[i].lastused)<deadtime)
- allidle = False;
- }
+ msg_type = CVAL(InBuffer,0);
+ msg_flags = CVAL(InBuffer,1);
+ type = CVAL(InBuffer,smb_com);
- if (allidle && num_connections_open>0)
- {
- DEBUG(2,("%s Closing idle connection 2\n",timestring()));
+ len = smb_len(InBuffer);
+
+ DEBUG(6,("got message type 0x%x of len 0x%x\n",msg_type,len));
+
+ nread = len + 4;
+
+ DEBUG(3,("%s Transaction %d of length %d\n",timestring(),trans_num,nread));
+
+#ifdef WITH_VTP
+ if(trans_num == 1 && VT_Check(InBuffer)) {
+ VT_Process();
return;
}
- }
+#endif
- if(got_smb)
- process_smb(InBuffer, OutBuffer);
- else
- process_local_message(oplock_sock, InBuffer, BUFFER_SIZE);
- }
+
+ if (msg_type == 0)
+ show_msg(InBuffer);
+
+ nread = construct_reply(InBuffer,OutBuffer,nread,max_send);
+
+ if(nread > 0) {
+ if (CVAL(OutBuffer,0) == 0)
+ show_msg(OutBuffer);
+
+ if (nread != smb_len(OutBuffer) + 4)
+ {
+ DEBUG(0,("ERROR: Invalid message response size! %d %d\n",
+ nread,
+ smb_len(OutBuffer)));
+ }
+ else
+ send_smb(Client,OutBuffer);
+ }
+ trans_num++;
+ }
}
@@ -5031,14 +4265,6 @@ static void init_structs(void )
fd_ptr->real_open_flags = -1;
}
- /* for RPC pipes */
- init_rpc_pipe_hnd();
-
-#ifdef NTDOMAIN
- /* for LSA handles */
- init_lsa_policy_hnd();
-#endif
-
init_dptrs();
}
@@ -5073,9 +4299,7 @@ static void usage(char *pname)
int port = SMB_PORT;
int opt;
extern char *optarg;
- char pidFile[100];
-
- *pidFile = '\0';
+ char pidFile[100] = { 0 };
#ifdef NEED_AUTH_PARAMETERS
set_auth_parameters(argc,argv);
@@ -5230,10 +4454,6 @@ static void usage(char *pname)
become_daemon();
}
- if (!directory_exist(lp_lockdir(), NULL)) {
- mkdir(lp_lockdir(), 0755);
- }
-
if (*pidFile)
{
int fd;
@@ -5265,8 +4485,10 @@ static void usage(char *pname)
if (!open_sockets(is_daemon,port))
exit(1);
- if (!locking_init(0))
+#ifdef FAST_SHARE_MODES
+ if (!start_share_mode_mgmt())
exit(1);
+#endif /* FAST_SHARE_MODES */
/* possibly reload the services file. */
reload_services(True);
@@ -5279,10 +4501,6 @@ static void usage(char *pname)
DEBUG(2,("%s changed root to %s\n",timestring(),lp_rootdir()));
}
- /* Setup the oplock IPC socket. */
- if(!open_oplock_ipc())
- exit(1);
-
process();
close_sockets();
diff --git a/source/smbd/trans2.c b/source/smbd/trans2.c
index 0ca678b7682..b976553a9f4 100644
--- a/source/smbd/trans2.c
+++ b/source/smbd/trans2.c
@@ -30,8 +30,6 @@ extern connection_struct Connections[];
extern files_struct Files[];
extern BOOL case_sensitive;
extern int Client;
-extern int oplock_sock;
-extern int smb_read_error;
/****************************************************************************
Send the required number of replies back.
@@ -168,7 +166,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
char *params = *pparams;
int16 open_mode = SVAL(params, 2);
int16 open_attr = SVAL(params,6);
- BOOL oplock_request = (((SVAL(params,0)|(1<<1))>>1) | ((SVAL(params,0)|(1<<2))>>1));
+ BOOL oplock_request = BITSETW(params,1);
#if 0
BOOL return_additional_info = BITSETW(params,0);
int16 open_sattr = SVAL(params, 4);
@@ -215,7 +213,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
open_file_shared(fnum,cnum,fname,open_mode,open_ofun,unixmode,
- oplock_request, &rmode,&smb_action);
+ &rmode,&smb_action);
if (!Files[fnum].open)
{
@@ -228,7 +226,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
}
if (fstat(Files[fnum].fd_ptr->fd,&sbuf) != 0) {
- close_file(fnum,False);
+ close_file(fnum, 0);
return(ERROR(ERRDOS,ERRnoaccess));
}
@@ -237,7 +235,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
mtime = sbuf.st_mtime;
inode = sbuf.st_ino;
if (fmode & aDIR) {
- close_file(fnum,False);
+ close_file(fnum, 0);
return(ERROR(ERRDOS,ERRnoaccess));
}
@@ -254,7 +252,7 @@ static int call_trans2open(char *inbuf, char *outbuf, int bufsize, int cnum,
SSVAL(params,12,rmode);
if (oplock_request && lp_fake_oplocks(SNUM(cnum))) {
- smb_action |= EXTENDED_OPLOCK_GRANTED;
+ smb_action |= (1<<15);
}
SSVAL(params,18,smb_action);
@@ -321,7 +319,7 @@ static int get_lanman2_dir_entry(int cnum,char *path_mask,int dirtype,int info_l
reskey = TellDir(Connections[cnum].dirptr);
- DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
+ DEBUG(6,("get_lanman2_dir_entry:readdir on dirptr 0x%x now at offset %d\n",
Connections[cnum].dirptr,TellDir(Connections[cnum].dirptr)));
if (!dname)
@@ -609,17 +607,6 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum
unix_ERR_class = ERRDOS;
unix_ERR_code = ERRbadpath;
}
-
-#if 0
- /* Ugly - NT specific hack - maybe not needed ? (JRA) */
- if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
- (get_remote_arch() == RA_WINNT))
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbaddirectory;
- }
-#endif
-
return(ERROR(ERRDOS,ERRbadpath));
}
@@ -654,17 +641,6 @@ static int call_trans2findfirst(char *inbuf, char *outbuf, int bufsize, int cnum
unix_ERR_class = ERRDOS;
unix_ERR_code = ERRbadpath;
}
-
-#if 0
- /* Ugly - NT specific hack - maybe not needed ? (JRA) */
- if((errno == ENOTDIR) && (Protocol >= PROTOCOL_NT1) &&
- (get_remote_arch() == RA_WINNT))
- {
- unix_ERR_class = ERRDOS;
- unix_ERR_code = ERRbaddirectory;
- }
-#endif
-
return (UNIXERROR(ERRDOS,ERRbadpath));
}
return(ERROR(ERRDOS,ERRbadpath));
@@ -1183,32 +1159,12 @@ static int call_trans2qfilepathinfo(char *inbuf, char *outbuf, int length,
data_size = 4;
break;
- /* Get the 8.3 name - used if NT SMB was negotiated. */
- case SMB_QUERY_FILE_ALT_NAME_INFO:
- {
- pstring short_name;
- pstrcpy(short_name,fname);
- /* Mangle if not already 8.3 */
- if(!is_8_3(short_name, True))
- {
- if(!name_map_mangle(short_name,True,SNUM(cnum)))
- *short_name = '\0';
- }
- strncpy(pdata + 4,short_name,12);
- (pdata + 4)[12] = 0;
- strupper(pdata + 4);
- l = strlen(pdata + 4);
- data_size = 4 + l;
- SIVAL(pdata,0,l);
- }
- break;
-
case SMB_QUERY_FILE_NAME_INFO:
+ case SMB_QUERY_FILE_ALT_NAME_INFO:
data_size = 4 + l;
SIVAL(pdata,0,l);
pstrcpy(pdata+4,fname);
break;
-
case SMB_QUERY_FILE_ALLOCATION_INFO:
case SMB_QUERY_FILE_END_OF_FILEINFO:
data_size = 8;
@@ -1391,14 +1347,6 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
tvs.modtime=MAX(interpret_long_date(pdata+16),
interpret_long_date(pdata+24));
-#if 0 /* Needs more testing... */
- /* Test from Luke to prevent Win95 from
- setting incorrect values here.
- */
- if (tvs.actime < tvs.modtime)
- return(ERROR(ERRDOS,ERRnoaccess));
-#endif /* Needs more testing... */
-
/* attributes */
mode = IVAL(pdata,32);
break;
@@ -1435,7 +1383,7 @@ static int call_trans2setfilepathinfo(char *inbuf, char *outbuf, int length,
*/
if (st.st_mtime != tvs.modtime || st.st_atime != tvs.actime)
{
- if(file_utime(cnum, fname, &tvs)!=0)
+ if(file_utime(cnum,fname, &tvs)!=0)
{
return(ERROR(ERRDOS,ERRnoaccess));
}
@@ -1704,19 +1652,11 @@ int reply_trans2(char *inbuf,char *outbuf,int length,int bufsize)
while( num_data_sofar < total_data || num_params_sofar < total_params)
{
- BOOL ret;
-
- ret = receive_next_smb(Client,oplock_sock,inbuf,bufsize,
- SMB_SECONDARY_WAIT);
-
- if((ret && (CVAL(inbuf, smb_com) != SMBtranss2)) || !ret)
+ if(!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
+ CVAL(inbuf, smb_com) != SMBtranss2)
{
outsize = set_message(outbuf,0,0,True);
- if(ret)
- DEBUG(0,("reply_trans2: Invalid secondary trans2 packet\n"));
- else
- DEBUG(0,("reply_trans2: %s in getting secondary trans2 response.\n",
- (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
+ DEBUG(2,("Invalid secondary trans2 packet\n"));
free(params);
free(data);
return(ERROR(ERRSRV,ERRerror));
diff --git a/source/smbd/uid.c b/source/smbd/uid.c
index b36fa4df067..db1e5e94c3b 100644
--- a/source/smbd/uid.c
+++ b/source/smbd/uid.c
@@ -23,13 +23,15 @@
extern int DEBUGLEVEL;
+extern connection_struct Connections[];
+
static int initial_uid;
static int initial_gid;
/* what user is current? */
struct current_user current_user;
-pstring OriginalDir;
+extern pstring OriginalDir;
/****************************************************************************
initialise the uid routines
@@ -181,19 +183,19 @@ BOOL become_guest(void)
/*******************************************************************
check if a username is OK
********************************************************************/
-static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
+static BOOL check_user_ok(int cnum,user_struct *vuser,int snum)
{
int i;
- for (i=0;i<conn->uid_cache.entries;i++)
- if (conn->uid_cache.list[i] == vuser->uid) return(True);
+ for (i=0;i<Connections[cnum].uid_cache.entries;i++)
+ if (Connections[cnum].uid_cache.list[i] == vuser->uid) return(True);
if (!user_ok(vuser->name,snum)) return(False);
- i = conn->uid_cache.entries % UID_CACHE_SIZE;
- conn->uid_cache.list[i] = vuser->uid;
+ i = Connections[cnum].uid_cache.entries % UID_CACHE_SIZE;
+ Connections[cnum].uid_cache.list[i] = vuser->uid;
- if (conn->uid_cache.entries < UID_CACHE_SIZE)
- conn->uid_cache.entries++;
+ if (Connections[cnum].uid_cache.entries < UID_CACHE_SIZE)
+ Connections[cnum].uid_cache.entries++;
return(True);
}
@@ -202,7 +204,7 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
/****************************************************************************
become the user of a connection number
****************************************************************************/
-BOOL become_user(connection_struct *conn, int cnum, uint16 vuid)
+BOOL become_user(int cnum, uint16 vuid)
{
user_struct *vuser = get_valid_user_struct(vuid);
int snum,gid;
@@ -215,27 +217,23 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid)
unbecome_user();
- if (!(VALID_CNUM(cnum) && conn->open)) {
+ if (!OPEN_CNUM(cnum)) {
DEBUG(2,("Connection %d not open\n",cnum));
return(False);
}
- snum = conn->service;
+ snum = Connections[cnum].service;
- if (conn->force_user ||
+ if (Connections[cnum].force_user ||
lp_security() == SEC_SHARE ||
!(vuser) || (vuser->guest) ||
- !check_user_ok(conn, vuser, snum))
- {
- uid = conn->uid;
- gid = conn->gid;
- current_user.groups = conn->groups;
- current_user.igroups = conn->igroups;
- current_user.ngroups = conn->ngroups;
- current_user.attrs = conn->attrs;
- }
- else
- {
+ !check_user_ok(cnum,vuser,snum)) {
+ uid = Connections[cnum].uid;
+ gid = Connections[cnum].gid;
+ current_user.groups = Connections[cnum].groups;
+ current_user.igroups = Connections[cnum].igroups;
+ current_user.ngroups = Connections[cnum].ngroups;
+ } else {
if (!vuser) {
DEBUG(2,("Invalid vuid used %d\n",vuid));
return(False);
@@ -244,11 +242,10 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid)
if(!*lp_force_group(snum))
gid = vuser->gid;
else
- gid = conn->gid;
- current_user.ngroups = vuser->n_groups;
- current_user.groups = vuser->groups;
- current_user.igroups = vuser->igroups;
- current_user.attrs = vuser->attrs;
+ gid = Connections[cnum].gid;
+ current_user.groups = vuser->user_groups;
+ current_user.igroups = vuser->user_igroups;
+ current_user.ngroups = vuser->user_ngroups;
}
if (initial_uid == 0)
@@ -256,15 +253,17 @@ BOOL become_user(connection_struct *conn, int cnum, uint16 vuid)
if (!become_gid(gid)) return(False);
#ifndef NO_SETGROUPS
- if (!(VALID_CNUM(cnum) && conn->ipc)) {
+ if (!IS_IPC(cnum)) {
/* groups stuff added by ih/wreu */
if (current_user.ngroups > 0)
if (setgroups(current_user.ngroups,current_user.groups)<0)
DEBUG(0,("setgroups call failed!\n"));
+ } else {
+ current_user.ngroups = 0;
}
#endif
- if (!conn->admin_user && !become_uid(uid))
+ if (!Connections[cnum].admin_user && !become_uid(uid))
return(False);
}
@@ -321,7 +320,8 @@ BOOL unbecome_user(void )
current_user.uid = initial_uid;
current_user.gid = initial_gid;
-
+ current_user.ngroups = 0;
+
if (ChDir(OriginalDir) != 0)
DEBUG(0,("%s chdir(%s) failed in unbecome_user\n",
timestring(),OriginalDir));
@@ -480,6 +480,8 @@ int smbrun(char *cmd,char *outfile,BOOL shared)
return 1;
}
+
+
static struct current_user current_user_saved;
static int become_root_depth;
static pstring become_root_dir;
@@ -492,7 +494,7 @@ after the operation
Set save_dir if you also need to save/restore the CWD
****************************************************************************/
-void become_root(BOOL save_dir)
+void become_root(int save_dir)
{
if (become_root_depth) {
DEBUG(0,("ERROR: become root depth is non zero\n"));
@@ -512,7 +514,7 @@ When the privilaged operation is over call this
Set save_dir if you also need to save/restore the CWD
****************************************************************************/
-void unbecome_root(BOOL restore_dir)
+void unbecome_root(int restore_dir)
{
if (become_root_depth != 1) {
DEBUG(0,("ERROR: unbecome root depth is %d\n",
@@ -553,3 +555,6 @@ void unbecome_root(BOOL restore_dir)
become_root_depth = 0;
}
+
+
+
diff --git a/source/utils/make_printerdef.c b/source/utils/make_printerdef.c
deleted file mode 100644
index 22621112739..00000000000
--- a/source/utils/make_printerdef.c
+++ /dev/null
@@ -1,301 +0,0 @@
- /*
- Unix SMB/Netbios implementation.
- Version 1.9.
- Create printer definition files.
-
- Copyright (C) Jean-Francois.Micouleau@utc.fr, 10/26/97
-
- 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.
-*/
-
-#include "includes.h"
-
-/*
-#define DEBUG
-*/
-char *files_to_copy;
-char *driverfile;
-char buffer[50][255];
-char sub_dir[50][2][255];
-
-void usage(char *name)
-{
- fprintf(stderr,"%s: printer.def \"Printer Name\"\n", name);
-}
-
-/*
- This function split a line in two parts
- on both side of the equal sign
- "entry=value"
-*/
-char *scan(char *chaine,char **entry)
-{
- char *value;
- char *temp;
- int i=0;
-
- *entry=(char *)malloc(255*sizeof(char));
- value=(char *)malloc(255*sizeof(char));
- strcpy(*entry,chaine);
- temp=chaine;
- while( temp[i]!='=' && temp[i]!='\0') {
- i++;
- }
- (*entry)[i]='\0';
- strcpy(value,temp+i+1);
- return (value);
-}
-
-void build_subdir()
-{
- int i=0;
- char *entry;
- char *data;
-
- while (*buffer[i]!='\0') {
- data=scan(buffer[i],&entry);
-#ifdef DEBUG
- fprintf(stderr,"\tentry=data %s:%s\n",entry,data);
-#endif
-
- if (strcmp(data,"11")==0) {
- strcpy(sub_dir[i][0],entry);
- strcpy(sub_dir[i][1],"");
- }
- if (strcmp(data,"23")==0) {
- strcpy(sub_dir[i][0],entry);
- strcpy(sub_dir[i][1],"color\\");
- }
-#ifdef DEBUG
- fprintf(stderr,"\tsubdir %s:%s\n",sub_dir[i][0],sub_dir[i][1]);
-#endif
- i++;
- }
-}
-
-/*
- Lockup an entry in a file
- Return all the lines between the entry and the next one or the end of file
- An entry is something between braces.
-*/
-void lookup_entry(FILE *fichier,char *chaine)
-{
- int found=0,pointeur=0,i=0;
- char *temp,*temp2;
-
- temp=(char *)malloc(255*sizeof(char));
- temp2=(char *)malloc(255*sizeof(char));
-
- *buffer[0]='\0';
-
- strcpy(temp2,"[");
- strcat(temp2,chaine);
- strcat(temp2,"]");
-
- rewind(fichier);
-#ifdef DEBUG
- fprintf(stderr,"\tLooking for %s\n",chaine);
-#endif
-
- while (!feof(fichier) && found==0) {
- *temp='\0';
- fgets(temp,255,fichier);
- if (strncmp(temp,temp2,strlen(temp2))==0) found=1;
- }
-
-
- while (!feof(fichier) && found==1) {
- *temp='\0';
- fgets(temp,255,fichier);
- if (*temp=='[') {
- found=2;
- *buffer[pointeur]='\0';
- }
- else {
- strcpy(buffer[pointeur],temp);
- i=strlen(buffer[pointeur])-1;
- while (buffer[pointeur][i]=='\r' || buffer[pointeur][i]=='\n')
- buffer[pointeur][i--]='\0';
- pointeur++;
- }
- }
-#ifdef DEBUG
- fprintf(stderr,"\t\tFound %d entries\n",pointeur-1);
-#endif
-}
-
-
-
-char *find_desc(FILE *fichier,char *text)
-{
- char *chaine;
- char *long_desc;
- char *short_desc;
- char *crap = NULL;
- char *p;
-
- int found=0;
-
- chaine=(char *)malloc(255*sizeof(char));
- long_desc=(char *)malloc(40*sizeof(char));
- short_desc=(char *)malloc(13*sizeof(char));
-
- while (!feof(fichier) && found==0)
- {
- fgets(chaine,255,fichier);
-
- long_desc=strtok(chaine,"=");
- crap=strtok(NULL,",");
-
- p=long_desc;
- while(*p!='"' && *p!='\0')
- p++;
- if (*p=='"' && *(p+1)!='\0') p++;
- long_desc=p;
-
- if (*p!='\0')
- {
- p++;
- while(*p!='\"')
- p++;
- *p='\0';
- }
- if (!strcmp(text,long_desc)) found=1;
- }
- free(chaine);
- while(*crap==' ') crap++;
- strcpy(short_desc,crap);
- if (found) return(short_desc);
- else return(NULL);
-}
-
-void scan_copyfiles(FILE *fichier, char *chaine)
-{
- char *part;
- int i;
- char direc[255];
-#ifdef DEBUG
- fprintf(stderr,"In scan_copyfiles Lookup up of %s\n",chaine);
-#endif
- part=strtok(chaine,", ");
- do {
- /* If the entry start with a @ then it's a file to copy
- else it's an entry refering to files to copy
- the main difference is when it's an entry
- you can have a directory to append before the file name
- */
- if (*part=='@') {
- strcpy(files_to_copy,", ");
- strcpy(files_to_copy,part);
- } else {
- lookup_entry(fichier,part);
- i=0;
- strcpy(direc,"");
- while (*sub_dir[i][0]!='\0') {
-#ifdef DEBUG
- fprintf(stderr,"\tsubdir %s:%s\n",sub_dir[i][0],sub_dir[i][1]);
-#endif
- if (strcmp(sub_dir[i][0],part)==0)
- strcpy(direc,sub_dir[i][1]);
- i++;
- }
- i=0;
- while (*buffer[i]!='\0') {
- strcat(files_to_copy,", ");
- strcat(files_to_copy,direc);
- strcat(files_to_copy,buffer[i]);
- i++;
- }
- }
- part=strtok(NULL,", ");
- }
- while (part!=NULL);
-}
-
-
-void scan_short_desc(FILE *fichier, char *short_desc)
-{
- int i=0;
- char *chaine;
- char *temp;
- char *copyfiles=0,*datasection=0,*datafile=0,*helpfile=0;
-
- chaine=(char *)malloc(255*sizeof(char));
- temp=(char *)malloc(255*sizeof(char));
-
- driverfile=short_desc;
-
- lookup_entry(fichier,short_desc);
-
- while(*buffer[i]!='\0') {
-#ifdef DEBUG
- fprintf(stderr,"\tLookup up of %s\n",buffer[i]);
-#endif
- if (strncmp(buffer[i],"CopyFiles",9)==0) copyfiles=scan(buffer[i],&temp);
- if (strncmp(buffer[i],"DataSection",11)==0) datasection=scan(buffer[i],&temp);
- if (strncmp(buffer[i],"DataFile",8)==0) datafile=scan(buffer[i],&temp);
- if (strncmp(buffer[i],"DriverFile",10)==0) driverfile=scan(buffer[i],&temp);
- if (strncmp(buffer[i],"HelpFile",8)==0) helpfile=scan(buffer[i],&temp);
- i++;
- }
- if (i) fprintf(stderr,"End of section found\n");
-
- fprintf(stderr,"CopyFiles: %s\n",copyfiles);
- fprintf(stderr,"Datasection: %s\n",datasection);
- fprintf(stderr,"Datafile: %s\n",datafile);
- fprintf(stderr,"Driverfile: %s\n",driverfile);
- fprintf(stderr,"Helpfile: %s\n",helpfile);
- if (copyfiles) scan_copyfiles(fichier,copyfiles);
-/* if (datasection) scan_copyfiles(fichier,datasection);*/
- if (datafile) scan_copyfiles(fichier,datafile);
- if (helpfile) scan_copyfiles(fichier,helpfile);
-}
-
-int main(int argc, char *argv[])
-{
- char *short_desc;
- FILE *inf_file;
-
- if (argc!=3)
- {
- usage(argv[0]);
- return(-1);
- }
-
- inf_file=fopen(argv[1],"r");
- if (!inf_file)
- {
- fprintf(stderr,"Description file not found, bye\n");
- return(-1);
- }
-
- short_desc=find_desc(inf_file,argv[2]);
- if (short_desc==NULL)
- {
- fprintf(stderr,"Printer not found\n");
- return(-1);
- }
- else fprintf(stderr,"Found:%s\n",short_desc);
-
- lookup_entry(inf_file,"DestinationDirs");
- build_subdir();
-
- files_to_copy=(char *)malloc(2048*sizeof(char));
- scan_short_desc(inf_file,short_desc);
- fprintf(stdout,"%s:%s:%s:",argv[2],short_desc,driverfile);
- fprintf(stdout,"%s\n",files_to_copy);
- return 0;
-}
-
diff --git a/source/utils/make_smbcodepage.c b/source/utils/make_smbcodepage.c
deleted file mode 100644
index b4cb1523349..00000000000
--- a/source/utils/make_smbcodepage.c
+++ /dev/null
@@ -1,472 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- Create codepage files from codepage_def.XXX files.
-
- Copyright (C) Jeremy Allison 1997
-
- 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.
-*/
-
-#include "includes.h"
-
-static char *prog_name = NULL;
-
-/*
- * Print program usage and die.
- */
-
-void codepage_usage(char *progname)
-{
- fprintf(stderr, "Usage is : %s [c|d] <codepage> <inputfile> <outputfile>\n",
- progname);
- exit(1);
-}
-
-/*
- * Read a line from a buffer into a line buffer. Ensure null
- * terminated.
- */
-
-void read_line( char **buf, char *line_buf, int size)
-{
- char *p = *buf;
- int num = 0;
-
- for(; *p && (*p != '\n'); p++)
- {
- if(num < (size - 1))
- line_buf[num++] = *p;
- }
- if(*p)
- p++; /* Go past the '\n' */
- line_buf[num] = '\0';
- *buf = p;
-}
-
-/*
- * Strip comment lines and blank lines from the data.
- * Copies into a new buffer and frees the old.
- * Returns the number of lines copied.
- */
-
-int clean_data( char **buf, uint32 *size)
-{
- char linebuf[512];
- char *p = *buf;
- int num_lines = 0;
- char *newbuf = (char *)malloc( *size + 1);
- char *newbuf_p = NULL;
-
- if(newbuf == NULL)
- {
- fprintf(stderr, "%s: malloc fail for size %d.\n", prog_name, *size + 1);
- exit(1);
- }
-
- newbuf_p = newbuf;
- *newbuf_p = '\0';
-
- while( *p )
- {
- char *cp;
-
- read_line( &p, linebuf, sizeof(linebuf));
- /* Null terminate after comment. */
- if((cp = strchr( linebuf, '#'))!= NULL)
- *cp = '\0';
-
- for(cp = linebuf;*cp && isspace(*cp); cp++)
- ;
-
- if(*cp == '\0')
- continue;
-
- strcpy(newbuf_p, cp);
- num_lines++;
- newbuf_p += (strlen(newbuf_p) + 1);
- }
-
- free(*buf);
- *buf = newbuf;
- return num_lines;
-}
-
-/*
- * Parse a byte from a codepage file.
- */
-
-BOOL parse_byte(char *buf, unsigned char *bp)
-{
- unsigned int b;
- char *endptr = NULL;
-
- b = (unsigned int)strtol(buf, &endptr, 0);
- if(endptr == buf || b > 255)
- return False;
-
- *bp = (unsigned char)b;
- return True;
-}
-
-/*
- * Parse a bool from a codepage file.
- */
-
-BOOL parse_bool(char *buf, unsigned char *bp)
-{
- if(isdigit(*buf))
- {
- char *endptr = NULL;
-
- *bp = (unsigned char)strtol(buf, &endptr, 0);
- if(endptr == buf )
- return False;
- if(*bp != 0)
- *bp = 1;
- } else {
- if(strcasecmp(buf, "True") && strcasecmp(buf, "False"))
- return False;
- if(strcasecmp(buf, "True")==0)
- *bp = 1;
- else
- *bp = 0;
- }
- return True;
-}
-
-/*
- * Print a parse error and exit.
- */
-
-void parse_error(char *buf, char *msg)
-{
- fprintf(stderr, "%s: %s whilst parsing line \n%s\n", prog_name,
- msg, buf);
- exit(1);
-}
-
-/*
- * Create a compiled codepage file from a codepage definition file.
- */
-
-int do_compile(int codepage, char *input_file, char *output_file)
-{
- FILE *fp = NULL;
- uint32 size = 0;
- char *buf = NULL;
- char output_buf[CODEPAGE_HEADER_SIZE + 512];
- int num_lines = 0;
- int i = 0;
- struct stat st;
-
- /* Get the size of the input file. Read the entire thing into memory. */
- if(stat((char *)input_file, &st)!= 0)
- {
- fprintf(stderr, "%s: failed to get the file size for file %s. Error was %s\n",
- prog_name, input_file, strerror(errno));
- exit(1);
- }
-
- size = (uint32)st.st_size;
-
- /* I don't believe these things should be bigger than 100k :-) */
- if(size > 100*1024)
- {
- fprintf(stderr, "%s: filesize %d is too large for a codepage definition file. \
-The maximum size I will believe is 100k.\n", prog_name, size);
- exit(1);
- }
-
- if((fp = fopen(input_file, "r")) == NULL)
- {
- fprintf(stderr, "%s: cannot open file %s for input.\n", prog_name, input_file);
- exit(1);
- }
-
- /* As we will be reading text, allocate one more byte for a '\0' */
- if((buf = (char *)malloc( size + 1 )) == NULL)
- {
- fprintf(stderr, "%s: malloc fail for size %d.\n", prog_name, size + 1);
- fclose(fp);
- exit(1);
- }
-
- if(fread( buf, 1, size, fp) != size)
- {
- fprintf(stderr, "%s: read failed for file %s. Error was %s.\n", prog_name,
- input_file, strerror(errno));
- free((char *)buf);
- fclose(fp);
- exit(1);
- }
-
- /* Null terminate the text read. */
- buf[size] = '\0';
-
- /* Go through the data line by line, strip out comments (anything
- after a '#' to end-of-line) and blank lines. The rest should be
- the codepage data.
- */
-
- num_lines = clean_data( &buf, &size);
-
- /* There can be a maximum of 128 lines. */
- if(num_lines > 128)
- {
- fprintf(stderr, "%s: There can be a maximum 128 lines of data in a codepage \
-definition file. File %s has %d.\n", prog_name, input_file, num_lines);
- exit(1);
- }
-
- /* Setup the output file header. */
- SSVAL(output_buf,CODEPAGE_VERSION_OFFSET,CODEPAGE_FILE_VERSION_ID);
- SSVAL(output_buf,CODEPAGE_CLIENT_CODEPAGE_OFFSET,(uint16)codepage);
- SIVAL(output_buf,CODEPAGE_LENGTH_OFFSET,(num_lines * 4));
-
- /* Now convert the lines into the compiled form. */
- for(i = 0; i < num_lines; i++)
- {
- char token_buf[512];
- char *p = buf;
- unsigned char b = 0;
-
- /* Get the 'lower' value. */
- if(!next_token(&p, token_buf, NULL))
- parse_error(buf, "cannot parse first value");
- if(!parse_byte( token_buf, &b))
- parse_error(buf, "first value doesn't resolve to a byte");
-
- /* Add this to the output buffer. */
- SCVAL(output_buf,CODEPAGE_HEADER_SIZE+(i*4),b);
-
- /* Get the 'upper' value. */
- if(!next_token(&p, token_buf, NULL))
- parse_error(buf, "cannot parse second value");
- if(!parse_byte( token_buf, &b))
- parse_error(buf, "second value doesn't resolve to a byte");
-
- /* Add this to the output buffer. */
- SCVAL(output_buf,CODEPAGE_HEADER_SIZE+(i*4) + 1,b);
-
- /* Get the 'upper to lower' value. */
- if(!next_token(&p, token_buf, NULL))
- parse_error(buf, "cannot parse third value");
- if(!parse_bool( token_buf, &b))
- parse_error(buf, "third value doesn't resolve to a boolean");
-
- /* Add this to the output buffer. */
- SCVAL(output_buf,CODEPAGE_HEADER_SIZE+(i*4) + 2,b);
-
- /* Get the 'lower to upper' value. */
- if(!next_token(&p, token_buf, NULL))
- parse_error(buf, "cannot parse fourth value");
- if(!parse_bool( token_buf, &b))
- parse_error(buf, "fourth value doesn't resolve to a boolean");
-
- /* Add this to the output buffer. */
- SCVAL(output_buf,CODEPAGE_HEADER_SIZE+(i*4) + 3,b);
-
- buf += (strlen(buf) + 1);
- }
-
- /* Now write out the output_buf. */
- if((fp = fopen(output_file, "w"))==NULL)
- {
- fprintf(stderr, "%s: Cannot open output file %s. Error was %s.\n",
- prog_name, output_file, strerror(errno));
- exit(1);
- }
-
- if(fwrite(output_buf, 1, CODEPAGE_HEADER_SIZE + (num_lines*4), fp) !=
- CODEPAGE_HEADER_SIZE + (num_lines*4))
- {
- fprintf(stderr, "%s: Cannot write output file %s. Error was %s.\n",
- prog_name, output_file, strerror(errno));
- exit(1);
- }
-
- fclose(fp);
-
- return 0;
-}
-
-/*
- * Placeholder for now.
- */
-
-int do_decompile( int codepage, char *input_file, char *output_file)
-{
- uint32 size = 0;
- struct stat st;
- char header_buf[CODEPAGE_HEADER_SIZE];
- char *buf = NULL;
- FILE *fp = NULL;
- int num_lines = 0;
- int i = 0;
-
- /* Get the size of the input file. Read the entire thing into memory. */
- if(stat((char *)input_file, &st)!= 0)
- {
- fprintf(stderr, "%s: failed to get the file size for file %s. Error was %s\n",
- prog_name, input_file, strerror(errno));
- exit(1);
- }
-
- size = (uint32)st.st_size;
-
- if( size < CODEPAGE_HEADER_SIZE || size > (CODEPAGE_HEADER_SIZE + 256))
- {
- fprintf(stderr, "%s: file %s is an incorrect size for a \
-code page file.\n", prog_name, input_file);
- exit(1);
- }
-
- /* Read the first 8 bytes of the codepage file - check
- the version number and code page number. All the data
- is held in little endian format.
- */
-
- if((fp = fopen( input_file, "r")) == NULL)
- {
- fprintf(stderr, "%s: cannot open file %s. Error was %s\n",
- prog_name, input_file, strerror(errno));
- exit(1);
- }
-
- if(fread( header_buf, 1, CODEPAGE_HEADER_SIZE, fp)!=CODEPAGE_HEADER_SIZE)
- {
- fprintf(stderr, "%s: cannot read header from file %s. Error was %s\n",
- prog_name, input_file, strerror(errno));
- exit(1);
- }
-
- /* Check the version value */
- if(SVAL(header_buf,CODEPAGE_VERSION_OFFSET) != CODEPAGE_FILE_VERSION_ID)
- {
- fprintf(stderr, "%s: filename %s has incorrect version id. \
-Needed %hu, got %hu.\n",
- prog_name, input_file, (uint16)CODEPAGE_FILE_VERSION_ID,
- SVAL(header_buf,CODEPAGE_VERSION_OFFSET));
- exit(1);
- }
-
- /* Check the codepage matches */
- if(SVAL(header_buf,CODEPAGE_CLIENT_CODEPAGE_OFFSET) != (uint16)codepage)
- {
- fprintf(stderr, "%s: filename %s has incorrect codepage. \
-Needed %hu, got %hu.\n",
- prog_name, input_file, (uint16)codepage,
- SVAL(header_buf,CODEPAGE_CLIENT_CODEPAGE_OFFSET));
- exit(1);
- }
-
- /* Check the length is correct. */
- if(IVAL(header_buf,CODEPAGE_LENGTH_OFFSET) !=
- (unsigned int)(size - CODEPAGE_HEADER_SIZE))
- {
- fprintf(stderr, "%s: filename %s has incorrect size headers. \
-Needed %u, got %u.\n", prog_name, input_file, size - CODEPAGE_HEADER_SIZE,
- IVAL(header_buf,CODEPAGE_LENGTH_OFFSET));
- exit(1);
- }
-
- size -= CODEPAGE_HEADER_SIZE; /* Remove header */
-
- /* Make sure the size is a multiple of 4. */
- if((size % 4 ) != 0)
- {
- fprintf(stderr, "%s: filename %s has a codepage size not a \
-multiple of 4.\n", prog_name, input_file);
- exit(1);
- }
-
- /* Allocate space for the code page file and read it all in. */
- if((buf = (char *)malloc( size )) == NULL)
- {
- fprintf (stderr, "%s: malloc fail for size %d.\n",
- prog_name, size );
- exit(1);
- }
-
- if(fread( buf, 1, size, fp)!=size)
- {
- fprintf(stderr, "%s: read fail on file %s. Error was %s.\n",
- prog_name, input_file, strerror(errno));
- exit(1);
- }
-
- fclose(fp);
-
- /* Now dump the codepage into an ascii file. */
- if((fp = fopen(output_file, "w")) == NULL)
- {
- fprintf(stderr, "%s: cannot open file %s. Error was %s\n",
- prog_name, output_file, strerror(errno));
- exit(1);
- }
-
- fprintf(fp, "#\n# Codepage definition file for IBM Code Page %d.\n#\n",
- codepage);
- fprintf(fp, "# This file was automatically generated.\n#\n");
- fprintf(fp, "# defines lower->upper mapping.\n");
- fprintf(fp, "#\n#The columns are :\n# lower\tupper\tu-t-l\tl-t-u\n#\n");
-
- num_lines = size / 4;
- for( i = 0; i < num_lines; i++)
- {
- fprintf(fp, "0x%02X\t0x%02X\t%s\t%s\n", CVAL(buf, (i*4)), CVAL(buf, (i*4)+1),
- CVAL(buf, (i*4)+2) ? "True" : "False",
- CVAL(buf, (i*4)+3) ? "True" : "False");
- }
- fclose(fp);
- return 0;
-}
-
-int main(int argc, char **argv)
-{
- int codepage = 0;
- char *input_file = NULL;
- char *output_file = NULL;
- BOOL compile = False;
-
- prog_name = argv[0];
-
- if(argc != 5)
- codepage_usage(prog_name);
-
- if(argv[1][0] != 'c' && argv[1][0] != 'C' && argv[1][0] != 'd' &&
- argv[1][0] != 'D')
- codepage_usage(prog_name);
-
- input_file = argv[3];
- output_file = argv[4];
-
- /* Are we compiling or decompiling. */
- if(argv[1][0] == 'c' || argv[1][0] == 'C')
- compile = True;
-
- /* Convert the second argument into a client codepage value. */
- if((codepage = atoi(argv[2])) == 0)
- {
- fprintf(stderr, "%s: %s is not a valid codepage.\n", prog_name, argv[2]);
- exit(1);
- }
-
- if(compile)
- return do_compile( codepage, input_file, output_file);
- else
- return do_decompile( codepage, input_file, output_file);
-}
diff --git a/source/utils/nmblookup.c b/source/utils/nmblookup.c
index b14887afabe..aebbc4292ca 100644
--- a/source/utils/nmblookup.c
+++ b/source/utils/nmblookup.c
@@ -35,17 +35,21 @@ extern struct in_addr ipzero;
int ServerFD= -1;
-int RootPort = 0;
-
/****************************************************************************
open the socket communication
**************************************************************************/
static BOOL open_sockets(void)
{
- ServerFD = open_socket_in( SOCK_DGRAM,
- (RootPort ? 137 :0),
- 3,
- interpret_addr(lp_socket_address()) );
+ struct hostent *hp;
+
+ /* get host info */
+ if ((hp = Get_Hostbyname(myhostname)) == 0)
+ {
+ DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",myhostname));
+ return False;
+ }
+
+ ServerFD = open_socket_in(SOCK_DGRAM, 0,3,interpret_addr(lp_socket_address()));
if (ServerFD == -1)
return(False);
@@ -77,12 +81,8 @@ static void usage(void)
printf("Version %s\n",VERSION);
printf("\t-d debuglevel set the debuglevel\n");
printf("\t-B broadcast address the address to use for broadcasts\n");
- printf("\t-U unicast address the address to use for unicast\n");
printf("\t-M searches for a master browser\n");
- printf("\t-R set recursion desired in packet\n");
printf("\t-S lookup node status as well\n");
- printf("\t-r Use root port 137 (Win95 only replies to this)\n");
- printf("\t-A Do a node status on <name> as an IP Address\n");
printf("\n");
}
@@ -102,11 +102,8 @@ int main(int argc,char *argv[])
int i;
static pstring servicesf = CONFIGFILE;
struct in_addr bcast_addr;
- BOOL use_bcast = True;
BOOL got_bcast = False;
- BOOL lookup_by_ip = False;
- BOOL recursion_desired = False;
-
+
DEBUGLEVEL = 1;
*lookup = 0;
@@ -116,20 +113,13 @@ int main(int argc,char *argv[])
charset_initialise();
- while ((opt = getopt(argc, argv, "d:B:U:i:s:SMrhAR")) != EOF)
+ while ((opt = getopt(argc, argv, "p:d:B:i:s:SMh")) != EOF)
switch (opt)
{
case 'B':
iface_set_default(NULL,optarg,NULL);
bcast_addr = *interpret_addr2(optarg);
got_bcast = True;
- use_bcast = True;
- break;
- case 'U':
- iface_set_default(NULL,optarg,NULL);
- bcast_addr = *interpret_addr2(optarg);
- got_bcast = True;
- use_bcast = False;
break;
case 'i':
fstrcpy(scope,optarg);
@@ -141,25 +131,16 @@ int main(int argc,char *argv[])
case 'S':
find_status = True;
break;
- case 'R':
- recursion_desired = True;
- break;
case 'd':
DEBUGLEVEL = atoi(optarg);
break;
case 's':
pstrcpy(servicesf, optarg);
break;
- case 'r':
- RootPort = -1;
- break;
case 'h':
usage();
exit(0);
break;
- case 'A':
- lookup_by_ip = True;
- break;
default:
usage();
exit(1);
@@ -186,23 +167,13 @@ int main(int argc,char *argv[])
for (i=optind;i<argc;i++)
{
- int j, count, retries = 2;
+ BOOL bcast = True;
+ int retries = 2;
char *p;
struct in_addr ip;
- struct in_addr *ip_list;
fstrcpy(lookup,argv[i]);
- if(lookup_by_ip)
- {
- strcpy(lookup,"*");
- ip = *interpret_addr2(argv[i]);
- printf("Looking up status of %s\n",inet_ntoa(ip));
- name_status(ServerFD,lookup,lookup_type,True,ip,NULL,NULL,NULL);
- printf("\n");
- continue;
- }
-
if (find_master) {
if (*lookup == '-') {
strcpy(lookup,"\01\02__MSBROWSE__\02");
@@ -217,26 +188,30 @@ int main(int argc,char *argv[])
if (p) {
*p = 0;
sscanf(p+1,"%x",&lookup_type);
+ bcast = False;
retries = 1;
}
- if ((ip_list = name_query(ServerFD,lookup,lookup_type,use_bcast,recursion_desired,
- bcast_addr,&count,NULL))) {
- for (j=0;j<count;j++)
- printf("%s %s<%02x>\n",inet_ntoa(ip_list[j]),lookup, lookup_type);
-
- /* We can only do find_status if the ip address returned
- was valid - ie. name_query returned true.
- */
- if (find_status) {
- printf("Looking up status of %s\n",inet_ntoa(ip_list[0]));
- name_status(ServerFD,lookup,lookup_type,True,ip_list[0],NULL,NULL,NULL);
- printf("\n");
- }
- } else {
- printf("name_query failed to find name %s\n", lookup);
+ if (name_query(ServerFD,lookup,lookup_type,bcast,True,
+ bcast_addr,&ip,NULL))
+ {
+ printf("%s %s\n",inet_ntoa(ip),lookup);
+
+ /* We can only do find_status if the ip address returned
+ was valid - ie. name_query returned true.
+ */
+ if (find_status)
+ {
+ printf("Looking up status of %s\n",inet_ntoa(ip));
+ name_status(ServerFD,lookup,lookup_type,True,ip,NULL,NULL,NULL);
+ printf("\n");
+ }
+ }
+ else
+ {
+ printf("name_query failed to find name %s\n", lookup);
}
}
-
+
return(0);
}
diff --git a/source/utils/smbpasswd.c b/source/utils/smbpasswd.c
index 225b7fde83d..161555d52cc 100644
--- a/source/utils/smbpasswd.c
+++ b/source/utils/smbpasswd.c
@@ -1,3 +1,5 @@
+#ifdef SMB_PASSWD
+
/*
* Unix SMB/Netbios implementation. Version 1.9. smbpasswd module. Copyright
* (C) Jeremy Allison 1995-1997.
@@ -18,6 +20,7 @@
*/
#include "includes.h"
+#include "des.h"
/* Static buffers we will return. */
static struct smb_passwd pw_buf;
@@ -48,7 +51,7 @@ static int gethexpwd(char *p, char *pwd)
return (True);
}
-static struct smb_passwd *
+struct smb_passwd *
_my_get_smbpwnam(FILE * fp, char *name, BOOL * valid_old_pwd,
BOOL *got_valid_nt_entry, long *pwd_seekpos)
{
@@ -375,30 +378,20 @@ static void usage(char *name)
* Open the smbpaswd file XXXX - we need to parse smb.conf to get the
* filename
*/
- fp = fopen(pfile, "r+");
- if (!fp && errno == ENOENT) {
- fp = fopen(pfile, "w");
- if (fp) {
- fprintf(fp, "# Samba SMB password file\n");
- fclose(fp);
- fp = fopen(pfile, "r+");
- }
- }
- if (!fp) {
- err = errno;
- fprintf(stderr, "%s: Failed to open password file %s.\n",
- argv[0], pfile);
- errno = err;
- perror(argv[0]);
- exit(err);
+ if ((fp = fopen(pfile, "r+")) == NULL) {
+ err = errno;
+ fprintf(stderr, "%s: Failed to open password file %s.\n",
+ argv[0], pfile);
+ errno = err;
+ perror(argv[0]);
+ exit(err);
}
-
/* Set read buffer to 16k for effiecient reads */
setvbuf(fp, readbuf, _IOFBF, sizeof(readbuf));
/* make sure it is only rw by the owner */
chmod(pfile, 0600);
-
+
/* Lock the smbpasswd file for write. */
if ((lockfd = pw_file_lock(pfile, F_WRLCK, 5)) < 0) {
err = errno;
@@ -424,8 +417,10 @@ static void usage(char *name)
/* Create a new smb passwd entry and set it to the given password. */
{
int fd;
+ int i;
int new_entry_length;
char *new_entry;
+ char *p;
long offpos;
/* The add user write needs to be atomic - so get the fd from
@@ -435,7 +430,7 @@ static void usage(char *name)
if((offpos = lseek(fd, 0, SEEK_END)) == -1) {
fprintf(stderr, "%s: Failed to add entry for user %s to file %s. \
-Error was %s\n", argv[0], pwd->pw_name, pfile, strerror(errno));
+Error was %d\n", argv[0], pwd->pw_name, pfile, errno);
fclose(fp);
pw_file_unlock(lockfd);
exit(1);
@@ -447,13 +442,13 @@ Error was %s\n", argv[0], pwd->pw_name, pfile, strerror(errno));
strlen(pwd->pw_shell) + 1;
if((new_entry = (char *)malloc( new_entry_length )) == 0) {
fprintf(stderr, "%s: Failed to add entry for user %s to file %s. \
-Error was %s\n", argv[0], pwd->pw_name, pfile, strerror(errno));
+Error was %d\n", argv[0], pwd->pw_name, pfile, errno);
fclose(fp);
pw_file_unlock(lockfd);
exit(1);
}
- sprintf(new_entry, "%s:%u:", pwd->pw_name, (unsigned)pwd->pw_uid);
+ sprintf(new_entry, "%s:%u:", pwd->pw_name, pwd->pw_uid);
p = &new_entry[strlen(new_entry)];
for( i = 0; i < 16; i++)
sprintf(&p[i*2], "%02X", new_p16[i]);
@@ -467,12 +462,12 @@ Error was %s\n", argv[0], pwd->pw_name, pfile, strerror(errno));
pwd->pw_dir, pwd->pw_shell);
if(write(fd, new_entry, strlen(new_entry)) != strlen(new_entry)) {
fprintf(stderr, "%s: Failed to add entry for user %s to file %s. \
-Error was %s\n", argv[0], pwd->pw_name, pfile, strerror(errno));
+Error was %d\n", argv[0], pwd->pw_name, pfile, errno);
/* Remove the entry we just wrote. */
if(ftruncate(fd, offpos) == -1) {
fprintf(stderr, "%s: ERROR failed to ftruncate file %s. \
-Error was %s. Password file may be corrupt ! Please examine by hand !\n",
- argv[0], pwd->pw_name, strerror(errno));
+Error was %d. Password file may be corrupt ! Please examine by hand !\n",
+ argv[0], pwd->pw_name, errno);
}
fclose(fp);
pw_file_unlock(lockfd);
@@ -483,9 +478,6 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n",
pw_file_unlock(lockfd);
exit(0);
}
- } else {
- /* the entry already existed */
- add_user = False;
}
/* If we are root or the password is 'NO PASSWORD' then
@@ -579,3 +571,14 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n",
return 0;
}
+#else
+
+#include "includes.h"
+
+int
+main(int argc, char **argv)
+{
+ printf("smb password encryption not selected in Makefile\n");
+ return 0;
+}
+#endif
diff --git a/source/utils/status.c b/source/utils/status.c
index 1a05f2b1afe..6fa85c0a630 100644
--- a/source/utils/status.c
+++ b/source/utils/status.c
@@ -53,53 +53,80 @@ int Ucrit_pid[100]; /* Ugly !!! */ /* added by OH */
int Ucrit_MaxPid=0; /* added by OH */
unsigned int Ucrit_IsActive = 0; /* added by OH */
-/* we need these because we link to locking*.o */
- void become_root(BOOL save_dir) {}
- void unbecome_root(BOOL restore_dir) {}
-connection_struct Connections[MAX_CONNECTIONS];
-files_struct Files[MAX_OPEN_FILES];
-struct current_user current_user;
+#ifndef FAST_SHARE_MODES
+static char *read_share_file(int fd, char *fname, char *progname)
+{
+ struct stat sb;
+ char *buf;
+ int size;
+ if(fstat(fd, &sb) != 0)
+ {
+ printf("%s: ERROR: read_share_file: Failed to do stat on share file %s (%s)\n",
+ progname, fname, strerror(errno));
+ return 0;
+ }
-static void print_share_mode(share_mode_entry *e, char *fname)
-{
- static int count;
- if (count==0) {
- printf("Locked files:\n");
- printf("Pid DenyMode R/W Oplock Name\n");
- printf("--------------------------------------------------\n");
- }
- count++;
-
- printf("%-5d ",e->pid);
- switch ((e->share_mode>>4)&0xF) {
- case DENY_NONE: printf("DENY_NONE "); break;
- case DENY_ALL: printf("DENY_ALL "); break;
- case DENY_DOS: printf("DENY_DOS "); break;
- case DENY_READ: printf("DENY_READ "); break;
- case DENY_WRITE:printf("DENY_WRITE "); break;
- }
- switch (e->share_mode&0xF) {
- case 0: printf("RDONLY "); break;
- case 1: printf("WRONLY "); break;
- case 2: printf("RDWR "); break;
- }
-
- if((e->op_type &
- (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) ==
- (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
- printf("EXCLUSIVE+BATCH ");
- else if (e->op_type & EXCLUSIVE_OPLOCK)
- printf("EXCLUSIVE ");
- else if (e->op_type & BATCH_OPLOCK)
- printf("BATCH ");
- else
- printf("NONE ");
-
- printf(" %s %s",fname,asctime(LocalTime((time_t *)&e->time.tv_sec)));
-}
+ if(sb.st_size == 0)
+ {
+ return 0;
+ }
+ /* Allocate space for the file */
+ if((buf = (char *)malloc(sb.st_size)) == NULL)
+ {
+ printf("%s: read_share_file: malloc for file size %d fail !\n",
+ progname, (int)sb.st_size);
+ return 0;
+ }
+
+ if(lseek(fd, 0, SEEK_SET) != 0)
+ {
+ printf("%s: ERROR: read_share_file: Failed to reset position to 0 \
+for share file %s (%s)\n", progname, fname, strerror(errno));
+ if(buf)
+ free(buf);
+ return 0;
+ }
+
+ if (read(fd,buf,sb.st_size) != sb.st_size)
+ {
+ printf("%s: ERROR: read_share_file: Failed to read share file %s (%s)\n",
+ progname, fname, strerror(errno));
+ if(buf)
+ free(buf);
+ return 0;
+ }
+
+ if (IVAL(buf,0) != LOCKING_VERSION) {
+ printf("%s: ERROR: read_share_file: share file %s has incorrect \
+locking version (was %d, should be %d).\n",fname,
+ progname, IVAL(buf,0), LOCKING_VERSION);
+ if(buf)
+ free(buf);
+ return 0;
+ }
+
+ /* Sanity check for file contents */
+ size = sb.st_size;
+ size -= 10; /* Remove the header */
+
+ /* Remove the filename component. */
+ size -= SVAL(buf, 8);
+
+ /* The remaining size must be a multiple of 16 - error if not. */
+ if((size % 16) != 0)
+ {
+ printf("%s: ERROR: read_share_file: share file %s is an incorrect length.\n",
+ progname, fname);
+ if(buf)
+ free(buf);
+ return 0;
+ }
+ return buf;
+}
+#endif /* FAST_SHARE_MODES */
int main(int argc, char *argv[])
{
@@ -109,8 +136,19 @@ static void print_share_mode(share_mode_entry *e, char *fname)
static pstring servicesf = CONFIGFILE;
extern char *optarg;
int verbose = 0, brief =0;
+ BOOL firstopen=True;
BOOL processes_only=False;
int last_pid=0;
+#ifdef FAST_SHARE_MODES
+ pstring shmem_file_name;
+ share_mode_record *file_scanner_p;
+ smb_shm_offset_t *mode_array;
+ int bytes_free, bytes_used, bytes_overhead, bytes_total;
+#else /* FAST_SHARE_MODES */
+ void *dir;
+ char *s;
+#endif /* FAST_SHARE_MODES */
+ int i;
struct session_record *ptr;
@@ -263,16 +301,178 @@ static void print_share_mode(share_mode_entry *e, char *fname)
printf("\n");
- locking_init(1);
+#ifdef FAST_SHARE_MODES
+ /*******************************************************************
+ initialize the shared memory for share_mode management
+ ******************************************************************/
+
+ strcpy(shmem_file_name,lp_lockdir());
+ trim_string(shmem_file_name,"","/");
+ if (!*shmem_file_name) exit(-1);
+ strcat(shmem_file_name, "/SHARE_MEM_FILE");
+ if(!smb_shm_open(shmem_file_name, lp_shmem_size())) exit(-1);
+
+ mode_array = (smb_shm_offset_t *)smb_shm_offset2addr(smb_shm_get_userdef_off());
+ if(mode_array == NULL)
+ {
+ printf("%s: base of shared memory hash array == 0! Exiting.\n", argv[0]);
+ smb_shm_close();
+ exit(-1);
+ }
- if (share_mode_forall(print_share_mode) <= 0)
- printf("No locked files\n");
+ for( i = 0; i < lp_shmem_hash_size(); i++)
+ {
+ smb_shm_lock_hash_entry(i);
+ if(mode_array[i] == NULL_OFFSET)
+ {
+ smb_shm_unlock_hash_entry(i);
+ continue;
+ }
+ file_scanner_p = (share_mode_record *)smb_shm_offset2addr(mode_array[i]);
+ while((file_scanner_p != 0) && (file_scanner_p->num_share_mode_entries != 0))
+ {
+ share_mode_entry *entry_scanner_p =
+ (share_mode_entry *)smb_shm_offset2addr(
+ file_scanner_p->share_mode_entries);
- printf("\n");
+ while(entry_scanner_p != 0)
+ {
+ struct timeval t;
+ int pid = entry_scanner_p->pid;
+ int mode = entry_scanner_p->share_mode;
+
+ t.tv_sec = entry_scanner_p->time.tv_sec;
+ t.tv_usec = entry_scanner_p->time.tv_usec;
+ strcpy(fname, file_scanner_p->file_name);
+#else /* FAST_SHARE_MODES */
+
+ /* For slow share modes go through all the files in
+ the share mode directory and read the entries in
+ each.
+ */
+
+ dir = opendir(lp_lockdir());
+ if (!dir)
+ {
+ printf("%s: Unable to open lock directory %s.\n", argv[0], lp_lockdir());
+ return(0);
+ }
+ while ((s=readdirname(dir))) {
+ char *buf;
+ char *base;
+ int fd;
+ pstring lname;
+ uint32 dev,inode;
+
+ if (sscanf(s,"share.%u.%u",&dev,&inode)!=2) continue;
+
+ strcpy(lname,lp_lockdir());
+ trim_string(lname,NULL,"/");
+ strcat(lname,"/");
+ strcat(lname,s);
+
+ fd = open(lname,O_RDWR,0);
+ if (fd < 0)
+ {
+ printf("%s: Unable to open share file %s.\n", argv[0], lname);
+ continue;
+ }
+
+ /* Lock the share mode file while we read it. */
+ if(fcntl_lock(fd, F_SETLKW, 0, 1, F_WRLCK) == False)
+ {
+ printf("%s: Unable to lock open share file %s.\n", argv[0], lname);
+ close(fd);
+ continue;
+ }
+
+ if(( buf = read_share_file( fd, lname, argv[0] )) == NULL)
+ {
+ close(fd);
+ continue;
+ }
+ strcpy( fname, &buf[10]);
+ close(fd);
+
+ base = buf + 10 + SVAL(buf,8);
+ for( i = 0; i < IVAL(buf, 4); i++)
+ {
+ char *p = base + (i*16);
+ struct timeval t;
+ int pid = IVAL(p,12);
+ int mode = IVAL(p,8);
+
+ t.tv_sec = IVAL(p,0);
+ t.tv_usec = IVAL(p,4);
+#endif /* FAST_SHARE_MODES */
+
+ fname[sizeof(fname)-1] = 0;
+
+ if (firstopen) {
+ firstopen=False;
+ printf("Locked files:\n");
+ printf("Pid DenyMode R/W Name\n");
+ printf("------------------------------\n");
+ }
- share_status(stdout);
- locking_end();
+ printf("%-5d ",pid);
+ switch ((mode>>4)&0xF)
+ {
+ case DENY_NONE: printf("DENY_NONE "); break;
+ case DENY_ALL: printf("DENY_ALL "); break;
+ case DENY_DOS: printf("DENY_DOS "); break;
+ case DENY_READ: printf("DENY_READ "); break;
+ case DENY_WRITE:printf("DENY_WRITE "); break;
+ }
+ switch (mode&0xF)
+ {
+ case 0: printf("RDONLY "); break;
+ case 1: printf("WRONLY "); break;
+ case 2: printf("RDWR "); break;
+ }
+ printf(" %s %s",fname,asctime(LocalTime((time_t *)&t.tv_sec)));
+
+#ifdef FAST_SHARE_MODES
+
+ entry_scanner_p = (share_mode_entry *)smb_shm_offset2addr(
+ entry_scanner_p->next_share_mode_entry);
+ } /* end while entry_scanner_p */
+ file_scanner_p = (share_mode_record *)smb_shm_offset2addr(
+ file_scanner_p->next_offset);
+ } /* end while file_scanner_p */
+ smb_shm_unlock_hash_entry(i);
+ } /* end for */
+
+ smb_shm_get_usage(&bytes_free, &bytes_used, &bytes_overhead);
+ bytes_total = bytes_free + bytes_used + bytes_overhead;
+
+ /*******************************************************************
+ deinitialize the shared memory for share_mode management
+ ******************************************************************/
+ smb_shm_close();
+
+#else /* FAST_SHARE_MODES */
+ } /* end for i */
+
+ if(buf)
+ free(buf);
+ base = 0;
+ } /* end while */
+ closedir(dir);
+
+#endif /* FAST_SHARE_MODES */
+ if (firstopen)
+ printf("No locked files\n");
+#ifdef FAST_SHARE_MODES
+ printf("\nShare mode memory usage (bytes):\n");
+ printf(" %d(%d%%) free + %d(%d%%) used + %d(%d%%) overhead = %d(100%%) total\n",
+ bytes_free, (bytes_free * 100)/bytes_total,
+ bytes_used, (bytes_used * 100)/bytes_total,
+ bytes_overhead, (bytes_overhead * 100)/bytes_total,
+ bytes_total);
+
+#endif /* FAST_SHARE_MODES */
return (0);
}
diff --git a/source/utils/testparm.c b/source/utils/testparm.c
index ca364cb8c94..81e69cd76fb 100644
--- a/source/utils/testparm.c
+++ b/source/utils/testparm.c
@@ -82,7 +82,7 @@ extern int DEBUGLEVEL;
printf("Press enter to see a dump of your service definitions\n");
fflush(stdout);
getc(stdin);
- lp_dump(stdout);
+ lp_dump();
}
if (argc == 4)
diff --git a/source/utils/torture.c b/source/utils/torture.c
deleted file mode 100644
index 8711af3fe1a..00000000000
--- a/source/utils/torture.c
+++ /dev/null
@@ -1,919 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- SMB torture tester
- Copyright (C) Andrew Tridgell 1997
-
- 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.
-*/
-
-#ifdef SYSLOG
-#undef SYSLOG
-#endif
-
-#include "includes.h"
-
-static fstring host, workgroup, share, password, username, myname;
-static int max_protocol = PROTOCOL_NT1;
-static char *sockops="";
-
-
-static struct timeval tp1,tp2;
-
-static void start_timer()
-{
- gettimeofday(&tp1,NULL);
-}
-
-static double end_timer()
-{
- gettimeofday(&tp2,NULL);
- return((tp2.tv_sec - tp1.tv_sec) +
- (tp2.tv_usec - tp1.tv_usec)*1.0e-6);
-}
-
-
-static BOOL open_connection(struct cli_state *c)
-{
- if (!cli_initialise(c) || !cli_connect(c, host, NULL)) {
- printf("Failed to connect with %s\n", host);
- return False;
- }
-
- if (!cli_session_request(c, host, 0x20, myname)) {
- printf("%s rejected the session\n",host);
- cli_shutdown(c);
- return False;
- }
-
- c->protocol = max_protocol;
-
- if (!cli_negprot(c)) {
- printf("%s rejected the negprot (%s)\n",host, cli_errstr(c));
- cli_shutdown(c);
- return False;
- }
-
- if (!cli_session_setup(c, username, password, strlen(password),
- "", 0, workgroup)) {
- printf("%s rejected the sessionsetup (%s)\n", host, cli_errstr(c));
- cli_shutdown(c);
- return False;
- }
-
- if (!cli_send_tconX(c, share, "A:", password, strlen(password)+1)) {
- printf("%s refused tree connect (%s)\n", host, cli_errstr(c));
- cli_shutdown(c);
- return False;
- }
-
- return True;
-}
-
-
-
-static void close_connection(struct cli_state *c)
-{
- if (!cli_tdis(c)) {
- printf("tdis failed (%s)\n", cli_errstr(c));
- }
-
- cli_shutdown(c);
-}
-
-
-static BOOL wait_lock(struct cli_state *c, int fnum, uint32 offset, uint32 len)
-{
- while (!cli_lock(c, fnum, offset, len, -1)) {
- int eclass, num;
- cli_error(c, &eclass, &num);
- if (eclass != ERRDOS || num != ERRlock) {
- printf("lock failed (%s)\n",
- cli_errstr(c));
- return False;
- }
- }
- return True;
-}
-
-
-static BOOL rw_torture(struct cli_state *c, int numops)
-{
- char *lockfname = "\\torture.lck";
- fstring fname;
- int fnum;
- int fnum2;
- int pid2, pid = getpid();
- int i;
-
- fnum2 = cli_open(c, lockfname, O_RDWR | O_CREAT | O_EXCL,
- DENY_NONE);
- if (fnum2 == -1)
- fnum2 = cli_open(c, lockfname, O_RDWR, DENY_NONE);
- if (fnum2 == -1) {
- printf("open of %s failed (%s)\n", lockfname, cli_errstr(c));
- return False;
- }
-
-
- for (i=0;i<numops;i++) {
- unsigned n = (unsigned)random()%10;
- if (i % 10 == 0) {
- printf("%d\r", i); fflush(stdout);
- }
- sprintf(fname,"\\torture.%u", n);
-
- if (!wait_lock(c, fnum2, n*sizeof(int), sizeof(int))) {
- return False;
- }
-
- fnum = cli_open(c, fname, O_RDWR | O_CREAT | O_TRUNC, DENY_ALL);
- if (fnum == -1) {
- printf("open failed (%s)\n", cli_errstr(c));
- break;
- }
-
- if (cli_write(c, fnum, (char *)&pid, 0, sizeof(pid)) != sizeof(pid)) {
- printf("write failed (%s)\n", cli_errstr(c));
- }
-
- pid2 = 0;
-
- if (cli_read(c, fnum, (char *)&pid2, 0, sizeof(pid)) != sizeof(pid)) {
- printf("read failed (%s)\n", cli_errstr(c));
- }
-
- if (pid2 != pid) {
- printf("data corruption!\n");
- }
-
- if (!cli_close(c, fnum)) {
- printf("close failed (%s)\n", cli_errstr(c));
- }
-
- if (!cli_unlink(c, fname)) {
- printf("unlink failed (%s)\n", cli_errstr(c));
- }
-
- if (!cli_unlock(c, fnum2, n*sizeof(int), sizeof(int), -1)) {
- printf("unlock failed (%s)\n", cli_errstr(c));
- }
- }
-
- cli_close(c, fnum2);
- cli_unlink(c, lockfname);
-
- printf("%d\n", i);
-
- return True;
-}
-
-static void usage(void)
-{
- printf("Usage: smbtorture \\\\server\\share <options>\n");
-
- printf("\t-U user%%pass\n");
- printf("\t-N numprocs\n");
- printf("\t-n my_netbios_name\n");
- printf("\t-W workgroup\n");
- printf("\t-o num_operations\n");
- printf("\t-O socket_options\n");
- printf("\t-m maximum protocol\n");
- printf("\n");
-
- exit(1);
-}
-
-
-
-static void run_torture(int numops)
-{
- static struct cli_state cli;
-
- if (open_connection(&cli)) {
- cli_sockopt(&cli, sockops);
-
- printf("pid %d OK\n", getpid());
-
- rw_torture(&cli, numops);
-
- close_connection(&cli);
- }
-}
-
-/*
- This test checks for two things:
-
- 1) correct support for retaining locks over a close (ie. the server
- must not use posix semantics)
- 2) support for lock timeouts
- */
-static void run_locktest1(void)
-{
- static struct cli_state cli1, cli2;
- char *fname = "\\locktest.lck";
- int fnum1, fnum2, fnum3;
- time_t t1, t2;
-
- if (!open_connection(&cli1) || !open_connection(&cli2)) {
- return;
- }
- cli_sockopt(&cli1, sockops);
- cli_sockopt(&cli2, sockops);
-
- printf("starting locktest1\n");
-
- cli_unlink(&cli1, fname);
-
- fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
- if (fnum1 == -1) {
- printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
- return;
- }
- fnum2 = cli_open(&cli1, fname, O_RDWR, DENY_NONE);
- if (fnum2 == -1) {
- printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli1));
- return;
- }
- fnum3 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
- if (fnum3 == -1) {
- printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli2));
- return;
- }
-
- if (!cli_lock(&cli1, fnum1, 0, 4, 0)) {
- printf("lock1 failed (%s)\n", cli_errstr(&cli1));
- return;
- }
-
-
- if (cli_lock(&cli2, fnum3, 0, 4, 0)) {
- printf("lock2 succeeded! This is a locking bug\n");
- return;
- } else {
- int eclass, num;
- cli_error(&cli2, &eclass, &num);
- if (eclass != ERRDOS || num != ERRlock) {
- printf("error should have been ERRDOS/ERRlock (%s)\n",
- cli_errstr(&cli2));
- return;
- }
- }
-
-
- printf("Testing lock timeouts\n");
- t1 = time(NULL);
- if (cli_lock(&cli2, fnum3, 0, 4, 10*1000)) {
- printf("lock3 succeeded! This is a locking bug\n");
- return;
- } else {
- int eclass, num;
- cli_error(&cli2, &eclass, &num);
- if (eclass != ERRDOS || num != ERRlock) {
- printf("error should have been ERRDOS/ERRlock (%s)\n",
- cli_errstr(&cli2));
- return;
- }
- }
- t2 = time(NULL);
-
- if (t2 - t1 < 5) {
- printf("error: This server appears not to support timed lock requests\n");
- }
-
- if (!cli_close(&cli1, fnum2)) {
- printf("close1 failed (%s)\n", cli_errstr(&cli1));
- return;
- }
-
- if (cli_lock(&cli2, fnum3, 0, 4, 0)) {
- printf("lock4 succeeded! This is a locking bug\n");
- return;
- } else {
- int eclass, num;
- cli_error(&cli2, &eclass, &num);
- if (eclass != ERRDOS || num != ERRlock) {
- printf("error should have been ERRDOS/ERRlock (%s)\n",
- cli_errstr(&cli2));
- return;
- }
- }
-
- if (!cli_close(&cli1, fnum1)) {
- printf("close2 failed (%s)\n", cli_errstr(&cli1));
- return;
- }
-
- if (!cli_close(&cli2, fnum3)) {
- printf("close3 failed (%s)\n", cli_errstr(&cli2));
- return;
- }
-
- if (!cli_unlink(&cli1, fname)) {
- printf("unlink failed (%s)\n", cli_errstr(&cli1));
- return;
- }
-
-
- close_connection(&cli1);
- close_connection(&cli2);
-
- printf("Passed locktest1\n");
-}
-
-
-/*
- This test checks that
-
- 1) the server supports multiple locking contexts on the one SMB
- connection, distinguished by PID.
-
- 2) the server correctly fails overlapping locks made by the same PID (this
- goes against POSIX behaviour, which is why it is tricky to implement)
-
- 3) the server denies unlock requests by an incorrect client PID
-*/
-static void run_locktest2(void)
-{
- static struct cli_state cli;
- char *fname = "\\locktest.lck";
- int fnum1, fnum2, fnum3;
-
- if (!open_connection(&cli)) {
- return;
- }
-
- cli_sockopt(&cli, sockops);
-
- printf("starting locktest2\n");
-
- cli_unlink(&cli, fname);
-
- cli_setpid(&cli, 1);
-
- fnum1 = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
- if (fnum1 == -1) {
- printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
- return;
- }
-
- fnum2 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
- if (fnum2 == -1) {
- printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli));
- return;
- }
-
- cli_setpid(&cli, 2);
-
- fnum3 = cli_open(&cli, fname, O_RDWR, DENY_NONE);
- if (fnum3 == -1) {
- printf("open3 of %s failed (%s)\n", fname, cli_errstr(&cli));
- return;
- }
-
- cli_setpid(&cli, 1);
-
- if (!cli_lock(&cli, fnum1, 0, 4, 0)) {
- printf("lock1 failed (%s)\n", cli_errstr(&cli));
- return;
- }
-
- if (cli_lock(&cli, fnum2, 0, 4, 0)) {
- printf("lock2 succeeded! This is a locking bug\n");
- } else {
- int eclass, num;
- cli_error(&cli, &eclass, &num);
- if (eclass != ERRDOS || num != ERRlock) {
- printf("error should have been ERRDOS/ERRlock (%s)\n",
- cli_errstr(&cli));
- return;
- }
- }
-
- cli_setpid(&cli, 2);
-
- if (cli_unlock(&cli, fnum1, 0, 4, 0)) {
- printf("unlock1 succeeded! This is a locking bug\n");
- }
-
- if (cli_lock(&cli, fnum3, 0, 4, 0)) {
- printf("lock3 succeeded! This is a locking bug\n");
- } else {
- int eclass, num;
- cli_error(&cli, &eclass, &num);
- if (eclass != ERRDOS || num != ERRlock) {
- printf("error should have been ERRDOS/ERRlock (%s)\n",
- cli_errstr(&cli));
- return;
- }
- }
-
- cli_setpid(&cli, 1);
-
- if (!cli_close(&cli, fnum1)) {
- printf("close1 failed (%s)\n", cli_errstr(&cli));
- return;
- }
-
- if (!cli_close(&cli, fnum2)) {
- printf("close2 failed (%s)\n", cli_errstr(&cli));
- return;
- }
-
- if (!cli_close(&cli, fnum3)) {
- printf("close3 failed (%s)\n", cli_errstr(&cli));
- return;
- }
-
- close_connection(&cli);
-
- printf("locktest2 finished\n");
-}
-
-
-/*
- This test checks that
-
- 1) the server supports the full offset range in lock requests
-*/
-static void run_locktest3(int numops)
-{
- static struct cli_state cli1, cli2;
- char *fname = "\\locktest.lck";
- int fnum1, fnum2, i;
- uint32 offset;
-
-#define NEXT_OFFSET offset += (~(uint32)0) / numops
-
- if (!open_connection(&cli1) || !open_connection(&cli2)) {
- return;
- }
- cli_sockopt(&cli1, sockops);
- cli_sockopt(&cli2, sockops);
-
- printf("starting locktest3\n");
-
- cli_unlink(&cli1, fname);
-
- fnum1 = cli_open(&cli1, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
- if (fnum1 == -1) {
- printf("open of %s failed (%s)\n", fname, cli_errstr(&cli1));
- return;
- }
- fnum2 = cli_open(&cli2, fname, O_RDWR, DENY_NONE);
- if (fnum2 == -1) {
- printf("open2 of %s failed (%s)\n", fname, cli_errstr(&cli2));
- return;
- }
-
- for (offset=i=0;i<numops;i++) {
- NEXT_OFFSET;
- if (!cli_lock(&cli1, fnum1, offset-1, 1, 0)) {
- printf("lock1 %d failed (%s)\n",
- i,
- cli_errstr(&cli1));
- return;
- }
-
- if (!cli_lock(&cli2, fnum2, offset-2, 1, 0)) {
- printf("lock2 %d failed (%s)\n",
- i,
- cli_errstr(&cli1));
- return;
- }
- }
-
- for (offset=i=0;i<numops;i++) {
- NEXT_OFFSET;
-
- if (cli_lock(&cli1, fnum1, offset-2, 1, 0)) {
- printf("error: lock1 %d succeeded!\n", i);
- return;
- }
-
- if (cli_lock(&cli2, fnum2, offset-1, 1, 0)) {
- printf("error: lock2 %d succeeded!\n", i);
- return;
- }
-
- if (cli_lock(&cli1, fnum1, offset-1, 1, 0)) {
- printf("error: lock3 %d succeeded!\n", i);
- return;
- }
-
- if (cli_lock(&cli2, fnum2, offset-2, 1, 0)) {
- printf("error: lock4 %d succeeded!\n", i);
- return;
- }
- }
-
- for (offset=i=0;i<numops;i++) {
- NEXT_OFFSET;
-
- if (!cli_unlock(&cli1, fnum1, offset-1, 1, 0)) {
- printf("unlock1 %d failed (%s)\n",
- i,
- cli_errstr(&cli1));
- return;
- }
-
- if (!cli_unlock(&cli2, fnum2, offset-2, 1, 0)) {
- printf("unlock2 %d failed (%s)\n",
- i,
- cli_errstr(&cli1));
- return;
- }
- }
-
- if (!cli_close(&cli1, fnum1)) {
- printf("close1 failed (%s)\n", cli_errstr(&cli1));
- }
-
- if (!cli_close(&cli2, fnum2)) {
- printf("close2 failed (%s)\n", cli_errstr(&cli2));
- }
-
- if (!cli_unlink(&cli1, fname)) {
- printf("unlink failed (%s)\n", cli_errstr(&cli1));
- return;
- }
-
- close_connection(&cli1);
- close_connection(&cli2);
-
- printf("finished locktest3\n");
-}
-
-
-/*
- This test checks that
-
- 1) the server does not allow an unlink on a file that is open
-*/
-static void run_unlinktest(void)
-{
- static struct cli_state cli;
- char *fname = "\\unlink.tst";
- int fnum;
-
- if (!open_connection(&cli)) {
- return;
- }
-
- cli_sockopt(&cli, sockops);
-
- printf("starting unlink test\n");
-
- cli_unlink(&cli, fname);
-
- cli_setpid(&cli, 1);
-
- fnum = cli_open(&cli, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
- if (fnum == -1) {
- printf("open of %s failed (%s)\n", fname, cli_errstr(&cli));
- return;
- }
-
- if (cli_unlink(&cli, fname)) {
- printf("error: server allowed unlink on an open file\n");
- }
-
- cli_close(&cli, fnum);
- cli_unlink(&cli, fname);
-
- close_connection(&cli);
-
- printf("unlink test finished\n");
-}
-
-
-
-static void browse_callback(char *sname, uint32 stype, char *comment)
-{
- printf("\t%20.20s %08x %s\n", sname, stype, comment);
-}
-
-
-/*
- This test checks the browse list code
-
-*/
-static void run_browsetest(void)
-{
- static struct cli_state cli;
-
- printf("starting browse test\n");
-
- if (!open_connection(&cli)) {
- return;
- }
-
- printf("domain list:\n");
- cli_NetServerEnum(&cli, workgroup,
- SV_TYPE_DOMAIN_ENUM,
- browse_callback);
-
- printf("machine list:\n");
- cli_NetServerEnum(&cli, workgroup,
- SV_TYPE_ALL,
- browse_callback);
-
- close_connection(&cli);
-
- printf("browse test finished\n");
-}
-
-
-/*
- This checks how the getatr calls works
-*/
-static void run_attrtest(void)
-{
- static struct cli_state cli;
- int fnum;
- time_t t, t2;
- char *fname = "\\attrib.tst";
-
- printf("starting attrib test\n");
-
- if (!open_connection(&cli)) {
- return;
- }
-
- cli_unlink(&cli, fname);
- fnum = cli_open(&cli, fname,
- O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
- cli_close(&cli, fnum);
- if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
- printf("getatr failed (%s)\n", cli_errstr(&cli));
- }
-
- if (abs(t - time(NULL)) > 2) {
- printf("ERROR: SMBgetatr bug. time is %s",
- ctime(&t));
- t = time(NULL);
- }
-
- t2 = t-60*60*24; /* 1 day ago */
-
- if (!cli_setatr(&cli, fname, 0, t2)) {
- printf("setatr failed (%s)\n", cli_errstr(&cli));
- }
-
- if (!cli_getatr(&cli, fname, NULL, NULL, &t)) {
- printf("getatr failed (%s)\n", cli_errstr(&cli));
- }
-
- if (t != t2) {
- printf("ERROR: getatr/setatr bug. times are\n%s",
- ctime(&t));
- printf("%s", ctime(&t2));
- }
-
- cli_unlink(&cli, fname);
-
- close_connection(&cli);
-
- printf("attrib test finished\n");
-}
-
-
-/*
- This checks a couple of trans2 calls
-*/
-static void run_trans2test(void)
-{
- static struct cli_state cli;
- int fnum;
- uint32 size;
- time_t c_time, a_time, m_time, w_time, m_time2;
- char *fname = "\\trans2.tst";
- char *dname = "\\trans2";
- char *fname2 = "\\trans2\\trans2.tst";
-
- printf("starting trans2 test\n");
-
- if (!open_connection(&cli)) {
- return;
- }
-
- cli_unlink(&cli, fname);
- fnum = cli_open(&cli, fname,
- O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
- if (!cli_qfileinfo(&cli, fnum, &c_time, &a_time, &m_time, &size)) {
- printf("ERROR: qfileinfo failed (%s)\n", cli_errstr(&cli));
- }
- cli_close(&cli, fnum);
-
- sleep(2);
-
- cli_unlink(&cli, fname);
- fnum = cli_open(&cli, fname,
- O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
- cli_close(&cli, fnum);
-
- if (!cli_qpathinfo(&cli, fname, &c_time, &a_time, &m_time, &size)) {
- printf("ERROR: qpathinfo failed (%s)\n", cli_errstr(&cli));
- } else {
- if (c_time != m_time) {
- printf("create time=%s", ctime(&c_time));
- printf("modify time=%s", ctime(&m_time));
- printf("This system appears to have sticky create times\n");
- }
- if (a_time % (60*60) == 0) {
- printf("access time=%s", ctime(&a_time));
- printf("This system appears to set a midnight access time\n");
- }
-
- if (abs(m_time - time(NULL)) > 60*60*24*7) {
- printf("ERROR: totally incorrect times - maybe word reversed?\n");
- }
- }
-
-
- cli_unlink(&cli, fname);
- fnum = cli_open(&cli, fname,
- O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
- cli_close(&cli, fnum);
- if (!cli_qpathinfo2(&cli, fname, &c_time, &a_time, &m_time,
- &w_time, &size)) {
- printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
- } else {
- if (w_time < 60*60*24*2) {
- printf("write time=%s", ctime(&w_time));
- printf("This system appears to set a initial 0 write time\n");
- }
- }
-
- cli_unlink(&cli, fname);
-
-
- /* check if the server updates the directory modification time
- when creating a new file */
- if (!cli_mkdir(&cli, dname)) {
- printf("ERROR: mkdir failed (%s)\n", cli_errstr(&cli));
- }
- sleep(3);
- if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time,
- &w_time, &size)) {
- printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
- }
-
- fnum = cli_open(&cli, fname2,
- O_RDWR | O_CREAT | O_TRUNC, DENY_NONE);
- cli_write(&cli, fnum, (char *)&fnum, 0, sizeof(fnum));
- cli_close(&cli, fnum);
- if (!cli_qpathinfo2(&cli, "\\trans2\\", &c_time, &a_time, &m_time2,
- &w_time, &size)) {
- printf("ERROR: qpathinfo2 failed (%s)\n", cli_errstr(&cli));
- } else {
- if (m_time2 == m_time)
- printf("This system does not update directory modification times\n");
- }
- cli_unlink(&cli, fname2);
- cli_rmdir(&cli, dname);
-
-
- close_connection(&cli);
-
- printf("trans2 test finished\n");
-}
-
-
-static void create_procs(int nprocs, int numops)
-{
- int i, status;
-
- for (i=0;i<nprocs;i++) {
- if (fork() == 0) {
- int mypid = getpid();
- srandom(mypid ^ time(NULL));
- run_torture(numops);
- _exit(0);
- }
- }
-
- for (i=0;i<nprocs;i++)
- waitpid(0, &status, 0);
-}
-
-
-
-/****************************************************************************
- main program
-****************************************************************************/
- int main(int argc,char *argv[])
-{
- int nprocs=1, numops=100;
- int opt;
- char *p;
- int gotpass = 0;
- extern char *optarg;
- extern int optind;
- extern FILE *dbf;
-
- dbf = stdout;
-
- charset_initialise();
-
- if (argc < 2) {
- usage();
- }
-
- if (strncmp(argv[1], "\\\\", 2)) {
- usage();
- }
-
- fstrcpy(host, &argv[1][2]);
- p = strchr(&host[2],'\\');
- if (!p) {
- usage();
- }
- *p = 0;
- fstrcpy(share, p+1);
-
- get_myname(myname,NULL);
-
- if (*username == 0 && getenv("LOGNAME")) {
- strcpy(username,getenv("LOGNAME"));
- }
-
- argc--;
- argv++;
-
-
- while ((opt = getopt(argc, argv, "hW:U:n:N:O:o:m:")) != EOF) {
- switch (opt) {
- case 'W':
- fstrcpy(workgroup,optarg);
- break;
- case 'm':
- max_protocol = interpret_protocol(optarg, max_protocol);
- break;
- case 'N':
- nprocs = atoi(optarg);
- break;
- case 'o':
- numops = atoi(optarg);
- break;
- case 'O':
- sockops = optarg;
- break;
- case 'n':
- fstrcpy(myname, optarg);
- break;
- case 'U':
- strcpy(username,optarg);
- p = strchr(username,'%');
- if (p) {
- *p = 0;
- strcpy(password, p+1);
- gotpass = 1;
- }
- break;
- default:
- printf("Unknown option %c (%d)\n", (char)opt, opt);
- usage();
- }
- }
-
-
- while (!gotpass) {
- p = getpass("Password:");
- if (p) {
- strcpy(password, p);
- gotpass = 1;
- }
- }
-
- printf("host=%s share=%s user=%s myname=%s\n",
- host, share, username, myname);
-
- start_timer();
- create_procs(nprocs, numops);
- printf("rw_torture: %g secs\n", end_timer());
-
- run_locktest1();
- run_locktest2();
- run_locktest3(numops);
- run_unlinktest();
- run_browsetest();
- run_attrtest();
- run_trans2test();
-
- return(0);
-}
-
-
diff --git a/source/web/cgi.c b/source/web/cgi.c
deleted file mode 100644
index f165c56110b..00000000000
--- a/source/web/cgi.c
+++ /dev/null
@@ -1,621 +0,0 @@
-/*
- some simple CGI helper routines
- Copyright (C) Andrew Tridgell 1997
-
- 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.
-*/
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <pwd.h>
-
-#define MAX_VARIABLES 10000
-
-#ifdef DEBUG_COMMENTS
-extern void print_title(char *fmt, ...);
-#endif
-
-struct var {
- char *name;
- char *value;
-};
-
-static struct var variables[MAX_VARIABLES];
-static int num_variables;
-static int content_length;
-static int request_post;
-static int request_get;
-static char *query_string;
-
-static void unescape(char *buf)
-{
- char *p=buf;
-
- while ((p=strchr(p,'+')))
- *p = ' ';
-
- p = buf;
-
- while (p && *p && (p=strchr(p,'%'))) {
- int c1 = p[1];
- int c2 = p[2];
-
- if (c1 >= '0' && c1 <= '9')
- c1 = c1 - '0';
- else if (c1 >= 'A' && c1 <= 'F')
- c1 = 10 + c1 - 'A';
- else if (c1 >= 'a' && c1 <= 'f')
- c1 = 10 + c1 - 'a';
- else {p++; continue;}
-
- if (c2 >= '0' && c2 <= '9')
- c2 = c2 - '0';
- else if (c2 >= 'A' && c2 <= 'F')
- c2 = 10 + c2 - 'A';
- else if (c2 >= 'a' && c2 <= 'f')
- c2 = 10 + c2 - 'a';
- else {p++; continue;}
-
- *p = (c1<<4) | c2;
-
- memcpy(p+1, p+3, strlen(p+3)+1);
- p++;
- }
-}
-
-
-static char *grab_line(FILE *f, int *cl)
-{
- char *ret;
- int i = 0;
- int len = 1024;
-
- ret = (char *)malloc(len);
- if (!ret) return NULL;
-
-
- while ((*cl)) {
- int c = fgetc(f);
- (*cl)--;
-
- if (c == EOF) {
- (*cl) = 0;
- break;
- }
-
- if (c == '\r') continue;
-
- if (strchr("\n&", c)) break;
-
- ret[i++] = c;
-
- if (i == len-1) {
- char *ret2;
- ret2 = (char *)realloc(ret, len*2);
- if (!ret2) return ret;
- len *= 2;
- ret = ret2;
- }
- }
-
-
- ret[i] = 0;
- return ret;
-}
-
-/***************************************************************************
- load all the variables passed to the CGI program. May have multiple variables
- with the same name and the same or different values. Takes a file parameter
- for simulating CGI invocation eg loading saved preferences.
- ***************************************************************************/
-void cgi_load_variables(FILE *f1)
-{
- FILE *f = f1;
- static char *line;
- char *p, *s, *tok;
- int len;
-
-#ifdef DEBUG_COMMENTS
- char dummy[100]="";
- print_title(dummy);
- printf("<!== Start dump in cgi_load_variables() %s ==>\n",__FILE__);
-#endif
-
- if (!f1) {
- f = stdin;
- if (!content_length) {
- p = getenv("CONTENT_LENGTH");
- len = p?atoi(p):0;
- } else {
- len = content_length;
- }
- } else {
- fseek(f, 0, SEEK_END);
- len = ftell(f);
- fseek(f, 0, SEEK_SET);
- }
-
-
- if (len > 0 &&
- (f1 || request_post ||
- ((s=getenv("REQUEST_METHOD")) &&
- strcasecmp(s,"POST")==0))) {
- while (len && (line=grab_line(f, &len))) {
- p = strchr(line,'=');
- if (!p) continue;
-
- *p = 0;
-
- variables[num_variables].name = strdup(line);
- variables[num_variables].value = strdup(p+1);
-
- free(line);
-
- if (!variables[num_variables].name ||
- !variables[num_variables].value)
- continue;
-
- unescape(variables[num_variables].value);
- unescape(variables[num_variables].name);
-
-#ifdef DEBUG_COMMENTS
- printf("<!== POST var %s has value \"%s\" ==>\n",
- variables[num_variables].name,
- variables[num_variables].value);
-#endif
-
- num_variables++;
- if (num_variables == MAX_VARIABLES) break;
- }
- }
-
- if (f1) {
-#ifdef DEBUG_COMMENTS
- printf("<!== End dump in cgi_load_variables() ==>\n");
-#endif
- return;
- }
-
- fclose(stdin);
-
- if ((s=query_string) || (s=getenv("QUERY_STRING"))) {
- for (tok=strtok(s,"&;");tok;tok=strtok(NULL,"&;")) {
- p = strchr(tok,'=');
- if (!p) continue;
-
- *p = 0;
-
- variables[num_variables].name = strdup(tok);
- variables[num_variables].value = strdup(p+1);
-
- if (!variables[num_variables].name ||
- !variables[num_variables].value)
- continue;
-
- unescape(variables[num_variables].value);
- unescape(variables[num_variables].name);
-
-#ifdef DEBUG_COMMENTS
- printf("<!== Commandline var %s has value \"%s\" ==>\n",
- variables[num_variables].name,
- variables[num_variables].value);
-#endif
- num_variables++;
- if (num_variables == MAX_VARIABLES) break;
- }
-
- }
-#ifdef DEBUG_COMMENTS
- printf("<!== End dump in cgi_load_variables() ==>\n");
-#endif
-}
-
-
-/***************************************************************************
- find a variable passed via CGI
- Doesn't quite do what you think in the case of POST text variables, because
- if they exist they might have a value of "" or even " ", depending on the
- browser. Also doesn't allow for variables[] containing multiple variables
- with the same name and the same or different values.
- ***************************************************************************/
-char *cgi_variable(char *name)
-{
- int i;
-
- for (i=0;i<num_variables;i++)
- if (strcmp(variables[i].name, name) == 0)
- return variables[i].value;
- return NULL;
-}
-
-/***************************************************************************
-return a particular cgi variable
- ***************************************************************************/
-char *cgi_vnum(int i, char **name)
-{
- if (i < 0 || i >= num_variables) return NULL;
- *name = variables[i].name;
- return variables[i].value;
-}
-
-/***************************************************************************
- return the value of a CGI boolean variable.
- ***************************************************************************/
-int cgi_boolean(char *name, int def)
-{
- char *p = cgi_variable(name);
-
- if (!p) return def;
-
- return strcmp(p, "1") == 0;
-}
-
-/***************************************************************************
-like strdup() but quotes < > and &
- ***************************************************************************/
-char *quotedup(char *s)
-{
- int i, n=0;
- int len;
- char *ret;
- char *d;
-
- if (!s) return strdup("");
-
- len = strlen(s);
-
- for (i=0;i<len;i++)
- if (s[i] == '<' || s[i] == '>' || s[i] == '&')
- n++;
-
- ret = malloc(len + n*6 + 1);
-
- if (!ret) return NULL;
-
- d = ret;
-
- for (i=0;i<len;i++) {
- switch (s[i]) {
- case '<':
- strcpy(d, "&lt;");
- d += 4;
- break;
-
- case '>':
- strcpy(d, "&gt;");
- d += 4;
- break;
-
- case '&':
- strcpy(d, "&amp;");
- d += 5;
- break;
-
- default:
- *d++ = s[i];
- }
- }
-
- *d = 0;
-
- return ret;
-}
-
-
-/***************************************************************************
-like strdup() but quotes a wide range of characters
- ***************************************************************************/
-char *urlquote(char *s)
-{
- int i, n=0;
- int len;
- char *ret;
- char *d;
- char *qlist = "\"\n\r'&<> \t+;";
-
- if (!s) return strdup("");
-
- len = strlen(s);
-
- for (i=0;i<len;i++)
- if (strchr(qlist, s[i])) n++;
-
- ret = malloc(len + n*2 + 1);
-
- if (!ret) return NULL;
-
- d = ret;
-
- for (i=0;i<len;i++) {
- if (strchr(qlist,s[i])) {
- sprintf(d, "%%%02X", (int)s[i]);
- d += 3;
- } else {
- *d++ = s[i];
- }
- }
-
- *d = 0;
-
- return ret;
-}
-
-
-/***************************************************************************
-like strdup() but quotes " characters
- ***************************************************************************/
-char *quotequotes(char *s)
-{
- int i, n=0;
- int len;
- char *ret;
- char *d;
-
- if (!s) return strdup("");
-
- len = strlen(s);
-
- for (i=0;i<len;i++)
- if (s[i] == '"')
- n++;
-
- ret = malloc(len + n*6 + 1);
-
- if (!ret) return NULL;
-
- d = ret;
-
- for (i=0;i<len;i++) {
- switch (s[i]) {
- case '"':
- strcpy(d, "&quot;");
- d += 6;
- break;
-
- default:
- *d++ = s[i];
- }
- }
-
- *d = 0;
-
- return ret;
-}
-
-
-/***************************************************************************
-quote spaces in a buffer
- ***************************************************************************/
-void quote_spaces(char *buf)
-{
- while (*buf) {
- if (*buf == ' ') *buf = '+';
- buf++;
- }
-}
-
-
-
-/***************************************************************************
-tell a browser about a fatal error in the http processing
- ***************************************************************************/
-static void cgi_setup_error(char *err, char *header, char *info)
-{
- printf("HTTP/1.1 %s\r\n%sConnection: close\r\nContent-Type: text/html\r\n\r\n<HTML><HEAD><TITLE>%s</TITLE></HEAD><BODY><H1>%s</H1>%s<p></BODY></HTML>\r\n", err, header, err, err, info);
- exit(0);
-}
-
-
-/***************************************************************************
-decode a base64 string in-place - simple and slow algorithm
- ***************************************************************************/
-static void base64_decode(char *s)
-{
- char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- int bit_offset, byte_offset, idx, i;
- unsigned char *d = (unsigned char *)s;
- char *p;
-
- i=0;
-
- while (*s && (p=strchr(b64,*s))) {
- idx = (int)(p - b64);
- byte_offset = (i*6)/8;
- bit_offset = (i*6)%8;
- d[byte_offset] &= ~((1<<(8-bit_offset))-1);
- if (bit_offset < 3) {
- d[byte_offset] |= (idx << (2-bit_offset));
- } else {
- d[byte_offset] |= (idx >> (bit_offset-2));
- d[byte_offset+1] = 0;
- d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
- }
- s++; i++;
- }
-}
-
-
-/***************************************************************************
-handle a http authentication line
- ***************************************************************************/
-static int cgi_handle_authorization(char *line)
-{
- char *p, *user, *pass;
- struct passwd *pwd;
- int ret=0;
-
- if (strncasecmp(line,"Basic ", 6)) {
- cgi_setup_error("401 Bad Authorization", "",
- "Only basic authorization is understood");
- }
- line += 6;
- while (line[0] == ' ') line++;
- base64_decode(line);
- if (!(p=strchr(line,':'))) {
- cgi_setup_error("401 Bad Authorization", "",
- "username/password must be supplied");
- }
- *p = 0;
- user = line;
- pass = p+1;
-
- /* currently only allow connections as root */
- if (strcasecmp(user,"root")) {
- cgi_setup_error("401 Bad Authorization", "",
- "incorrect username/password");
- }
-
- pwd = getpwnam(user);
-
- if (!strcmp((char *)crypt(pass, pwd->pw_passwd),pwd->pw_passwd)) {
- ret = 1;
- }
-
- memset(pass, 0, strlen(pass));
-
- return ret;
-}
-
-
-/***************************************************************************
-handle a file download
- ***************************************************************************/
-static void cgi_download(char *file)
-{
- struct stat st;
- char buf[1024];
- int fd, l, i;
- char *p;
-
- /* sanitise the filename */
- for (i=0;file[i];i++) {
- if (!isalnum(file[i]) && !strchr("/.-_", file[i])) {
- cgi_setup_error("404 File Not Found","",
- "Illegal character in filename");
- }
- }
-
- if (strstr(file,"..")) {
- cgi_setup_error("404 File Not Found","",
- "Relative paths not allowed");
- }
-
- if (!file_exist(file, &st)) {
- cgi_setup_error("404 File Not Found","",
- "The requested file was not found");
- }
- fd = open(file,O_RDONLY);
- if (fd == -1) {
- cgi_setup_error("404 File Not Found","",
- "The requested file was not found");
- }
- printf("HTTP/1.1 200 OK\r\n");
- if ((p=strrchr(file,'.'))) {
- if (strcmp(p,".gif")==0 || strcmp(p,".jpg")==0) {
- printf("Content-Type: image/gif\r\n");
- } else {
- printf("Content-Type: text/html\r\n");
- }
- }
- printf("Content-Length: %d\r\n\r\n", (int)st.st_size);
- while ((l=read(fd,buf,sizeof(buf)))>0) {
- fwrite(buf, 1, l, stdout);
- }
- close(fd);
- exit(0);
-}
-
-
-/***************************************************************************
-setup the cgi framework, handling the possability that this program is either
-run as a true cgi program by a web browser or is itself a mini web server
- ***************************************************************************/
-void cgi_setup(char *rootdir)
-{
- int authenticated = 0;
- char line[1024];
- char *url=NULL;
- char *p;
-
- if (chdir(rootdir)) {
- cgi_setup_error("400 Server Error", "",
- "chdir failed - the server is not configured correctly");
- }
-
- if (getenv("CONTENT_LENGTH") || getenv("REQUEST_METHOD")) {
- /* assume we are running under a real web server */
- return;
- }
-
- /* we are a mini-web server. We need to read the request from stdin
- and handle authentication etc */
- while (fgets(line, sizeof(line)-1, stdin)) {
- if (line[0] == '\r' || line[0] == '\n') break;
- if (strncasecmp(line,"GET ", 4)==0) {
- request_get = 1;
- url = strdup(&line[4]);
- } else if (strncasecmp(line,"POST ", 5)==0) {
- request_post = 1;
- url = strdup(&line[5]);
- } else if (strncasecmp(line,"PUT ", 4)==0) {
- cgi_setup_error("400 Bad Request", "",
- "This server does not accept PUT requests");
- } else if (strncasecmp(line,"Authorization: ", 15)==0) {
- authenticated = cgi_handle_authorization(&line[15]);
- } else if (strncasecmp(line,"Content-Length: ", 16)==0) {
- content_length = atoi(&line[16]);
- }
- /* ignore all other requests! */
- }
-
- if (!authenticated) {
- cgi_setup_error("401 Authorization Required",
- "WWW-Authenticate: Basic realm=\"root\"\r\n",
- "You must be authenticated to use this service");
- }
-
- if (!url) {
- cgi_setup_error("400 Bad Request", "",
- "You must specify a GET or POST request");
- }
-
- /* trim the URL */
- if ((p = strchr(url,' ')) || (p=strchr(url,'\t'))) {
- *p = 0;
- }
- while (*url && strchr("\r\n",url[strlen(url)-1])) {
- url[strlen(url)-1] = 0;
- }
-
- /* anything following a ? in the URL is part of the query string */
- if ((p=strchr(url,'?'))) {
- query_string = p+1;
- *p = 0;
- }
-
- if (strcmp(url,"/")) {
- cgi_download(url+1);
- }
-
- printf("HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n");
-
-}
-
-
diff --git a/source/wsmbconf.c b/source/wsmbconf.c
deleted file mode 100644
index 8abdd6d3985..00000000000
--- a/source/wsmbconf.c
+++ /dev/null
@@ -1,237 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- html smb.conf editing - prototype only
- Copyright (C) Andrew Tridgell 1997
-
- 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.
-*/
-
-#ifdef SYSLOG
-#undef SYSLOG
-#endif
-
-#include "includes.h"
-#include "smb.h"
-
-#define SDEFAULTS "Service defaults"
-#define SGLOBAL "Global Parameters"
-#define GLOBALS_SNUM -2
-#define DEFAULTS_SNUM -1
-
-static pstring servicesf = CONFIGFILE;
-
-
-/* start the page with standard stuff */
-static void print_header(void)
-{
- printf("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\">\n");
- printf("<HTML>\n<HEAD>\n<TITLE>smb.conf</TITLE>\n</HEAD>\n<BODY>\n\n");
-}
-
-
-/* finish off the page */
-static void print_footer(void)
-{
- printf("\n</BODY>\n</HTML>\n");
-}
-
-/* display a servce, ready for editing */
-static void show_service(int snum, int allparameters)
-{
- int i = 0;
- pstring label, value;
- char *sname;
-
- if (snum == GLOBALS_SNUM)
- sname = SGLOBAL;
- else if (snum == DEFAULTS_SNUM)
- sname = SDEFAULTS;
- else sname = lp_servicename(snum);
-
- printf("\n<p><table border=0>\n<tr>\n<td></td><td>\n\n");
- printf("<form method=POST>\n");
- printf("<H3>%s</H3>\n", sname);
- printf("<input type=hidden name=service value=\"%s\">\n", sname);
- printf("<input type=submit name=request value=Change>\n");
- printf("<input type=submit name=request value=Rename>\n");
- printf("<input type=submit name=request value=Copy>\n");
- printf("<input type=submit name=request value=Remove>\n");
- printf("<br><input name=newvalue><br>\n");
- printf("<select name=parameter size=5>\n");
-
- while (lp_next_parameter(snum, &i, label, value, allparameters)) {
- printf("<option value=\"%s\">%s = %s\n",
- label, label, value);
- }
-
- printf("</select>\n");
- printf("</form>\n</td>\n</tr>\n</table>\n");
-
- printf("<p>\n");
-}
-
-
-/* loop over all services, displaying them one after the other */
-static void show_services(void)
-{
- int i;
- int n;
- int allparameters = cgi_boolean("allparameters", 0);
-
- printf("<FORM METHOD=POST>\n");
- printf("<p>Show all parameters?\n");
- printf("<INPUT NAME=allparameters TYPE=checkbox VALUE=1 %s>\n",
- allparameters?"CHECKED":"");
-
- printf("<INPUT TYPE=submit NAME=reload VALUE=Reload>\n");
-
- printf("</FORM>\n");
-
- n = lp_numservices();
-
- show_service(GLOBALS_SNUM, allparameters);
- show_service(DEFAULTS_SNUM, allparameters);
-
- for (i=0;i<n;i++)
- if (VALID_SNUM(i))
- show_service(i, allparameters);
-}
-
-
-/* load the smb.conf file into loadparm. */
-static int load_config(void)
-{
- setuid(0);
- if (!lp_load(servicesf,False)) {
- printf("<b>Can't load %s - using defaults</b><p>\n",
- servicesf);
- }
- return 1;
-}
-
-
-static int save_reload(void)
-{
- FILE *f;
-
- f = fopen(servicesf,"w");
- if (!f) {
- printf("failed to open %s for writing\n", servicesf);
- return 0;
- }
-
- fprintf(f, "# Samba config file created using wsmbconf\n");
-
- lp_dump(f);
-
- fclose(f);
-
- lp_killunused(NULL);
-
- if (!lp_load(servicesf,False)) {
- printf("Can't reload %s\n", servicesf);
- return 0;
- }
-
- return 1;
-}
-
-static void process_requests(void)
-{
- char *req = cgi_variable("request");
- char *newvalue = cgi_variable("newvalue");
- char *parameter = cgi_variable("parameter");
- char *service = cgi_variable("service");
- int snum=0;
-
- if (!req) return;
-
- if (service) {
- /* work out what service it is */
- if (strcmp(service,SGLOBAL) == 0) {
- snum = GLOBALS_SNUM;
- } else if (strcmp(service,SDEFAULTS) == 0) {
- snum = DEFAULTS_SNUM;
- } else {
- snum = lp_servicenumber(service);
- if (snum < 0) return;
- }
- }
-
- if (!newvalue)
- newvalue = "";
-
- if (strcmp(req,"Change") == 0) {
- /* change the value of a parameter */
- if (!parameter || !service) return;
-
- lp_do_parameter(snum, parameter, newvalue);
- } else if (strcmp(req,"Rename") == 0) {
- /* rename a service */
- if (!newvalue || !service) return;
-
- lp_rename_service(snum, newvalue);
- } else if (strcmp(req,"Remove") == 0) {
- /* remove a service */
- if (!service) return;
-
- lp_remove_service(snum);
- } else if (strcmp(req,"Copy") == 0) {
- /* copy a service */
- if (!service || !newvalue) return;
-
- lp_copy_service(snum, newvalue);
- }
-
- save_reload();
-}
-
-
-int main(int argc, char *argv[])
-{
- extern char *optarg;
- extern int optind;
- extern FILE *dbf;
- int opt;
-
- dbf = fopen("/dev/null", "w");
-
- if (!dbf) dbf = stderr;
-
- cgi_setup(WEB_ROOT);
-
-
- while ((opt = getopt(argc, argv,"s:")) != EOF) {
- switch (opt) {
- case 's':
- pstrcpy(servicesf,optarg);
- break;
- }
- }
-
-
- print_header();
-
- charset_initialise();
-
- if (load_config()) {
- cgi_load_variables(NULL);
- process_requests();
- show_services();
- }
- print_footer();
- return 0;
-}
diff --git a/source/wsmbstatus.c b/source/wsmbstatus.c
deleted file mode 100644
index 2762b8610e7..00000000000
--- a/source/wsmbstatus.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- Unix SMB/Netbios implementation.
- Version 1.9.
- html status reporting
- Copyright (C) Andrew Tridgell 1997
-
- 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.
-*/
-
-#ifdef SYSLOG
-#undef SYSLOG
-#endif
-
-#include "includes.h"
-
-static void print_header(void)
-{
- printf("Content-type: text/html\n\n");
- printf("<HTML>\n<HEAD>\n<TITLE>smbstatus</TITLE>\n</HEAD>\n<BODY>\n\n");
-}
-
-static void print_footer(void)
-{
- printf("\n</BODY>\n</HTML>\n");
-}
-
-static void show_connections(void)
-{
- static pstring servicesf = CONFIGFILE;
- pstring fname;
- FILE *f;
- struct connect_record crec;
-
- if (!lp_load(servicesf,False)) {
- printf("Can't load %s - run testparm to debug it\n", servicesf);
- return;
- }
-
- strcpy(fname,lp_lockdir());
- standard_sub_basic(fname);
- trim_string(fname,"","/");
- strcat(fname,"/STATUS..LCK");
-
- f = fopen(fname,"r");
- if (!f) {
- printf("Couldn't open status file %s\n",fname);
- if (!lp_status(-1))
- printf("You need to have status=yes in your smb config file\n");
- return;
- }
-
-
- printf("\nSamba version %s\n<p>",VERSION);
-
- while (!feof(f)) {
- if (fread(&crec,sizeof(crec),1,f) != 1)
- break;
- if (crec.magic == 0x280267 && process_exists(crec.pid)) {
- printf("%-10.10s %-8s %-8s %5d %-8s (%s) %s<br>",
- crec.name,uidtoname(crec.uid),
- gidtoname(crec.gid),crec.pid,
- crec.machine,crec.addr,
- asctime(LocalTime(&crec.start)));
- }
- }
- fclose(f);
-}
-
-int main(int argc, char *argv[])
-{
- print_header();
- show_connections();
- print_footer();
- return 0;
-}