aboutsummaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorSheldon Hearn <sheldonh@FreeBSD.org>2001-12-14 11:06:03 +0000
committerSheldon Hearn <sheldonh@FreeBSD.org>2001-12-14 11:06:03 +0000
commitc45579ad414930948f2c8d4eb07fc751561bd80a (patch)
treee768c6a88c2d313249d65750629373e620851a01 /contrib
parent3ce63c45f7443b1152d8caa78ddd835658eae771 (diff)
parentf1b9d12761de3c33754f03e6d2a5bf9f1b40aad9 (diff)
downloadsrc-c45579ad414930948f2c8d4eb07fc751561bd80a.tar.gz
src-c45579ad414930948f2c8d4eb07fc751561bd80a.zip
This commit was generated by cvs2svn to compensate for changes in r87866,
which included commits to RCS files with non-trunk default branches.
Notes
Notes: svn path=/head/; revision=87867
Diffstat (limited to 'contrib')
-rw-r--r--contrib/smbfs/COPYRIGHT29
-rw-r--r--contrib/smbfs/CREDITS10
-rw-r--r--contrib/smbfs/HISTORY130
-rw-r--r--contrib/smbfs/INSTALL68
-rw-r--r--contrib/smbfs/Makefile87
-rw-r--r--contrib/smbfs/Makefile.inc43
-rw-r--r--contrib/smbfs/README50
-rw-r--r--contrib/smbfs/config.mk.in37
-rwxr-xr-xcontrib/smbfs/configure3
-rw-r--r--contrib/smbfs/examples/dot.nsmbrc57
-rwxr-xr-xcontrib/smbfs/examples/print/lj6l22
-rwxr-xr-xcontrib/smbfs/examples/print/ljspool4
-rw-r--r--contrib/smbfs/examples/print/printcap.sample7
-rwxr-xr-xcontrib/smbfs/examples/print/tolj5
-rw-r--r--contrib/smbfs/examples/smbfs.sh.sample37
-rw-r--r--contrib/smbfs/include/cflib.h86
-rw-r--r--contrib/smbfs/include/netsmb/nb_lib.h147
-rw-r--r--contrib/smbfs/include/netsmb/smb_lib.h256
-rw-r--r--contrib/smbfs/include/netsmb/smb_rap.h74
-rw-r--r--contrib/smbfs/lib/Makefile21
-rw-r--r--contrib/smbfs/lib/Makefile.inc18
-rw-r--r--contrib/smbfs/lib/smb/Makefile50
-rw-r--r--contrib/smbfs/lib/smb/cfopt.c123
-rw-r--r--contrib/smbfs/lib/smb/ctx.c773
-rw-r--r--contrib/smbfs/lib/smb/file.c80
-rw-r--r--contrib/smbfs/lib/smb/kiconv.c61
-rw-r--r--contrib/smbfs/lib/smb/mbuf.c467
-rw-r--r--contrib/smbfs/lib/smb/nb.c191
-rw-r--r--contrib/smbfs/lib/smb/nb_name.c198
-rw-r--r--contrib/smbfs/lib/smb/nb_net.c201
-rw-r--r--contrib/smbfs/lib/smb/nbns_rq.c380
-rw-r--r--contrib/smbfs/lib/smb/nls.c214
-rw-r--r--contrib/smbfs/lib/smb/print.c97
-rw-r--r--contrib/smbfs/lib/smb/rap.c404
-rw-r--r--contrib/smbfs/lib/smb/rcfile.c499
-rw-r--r--contrib/smbfs/lib/smb/rcfile_priv.h20
-rw-r--r--contrib/smbfs/lib/smb/rq.c179
-rw-r--r--contrib/smbfs/lib/smb/subr.c243
-rw-r--r--contrib/smbfs/mount_smbfs/Makefile18
-rw-r--r--contrib/smbfs/mount_smbfs/getmntopts.c108
-rw-r--r--contrib/smbfs/mount_smbfs/mntopts.h91
-rw-r--r--contrib/smbfs/mount_smbfs/mount_smbfs.8158
-rw-r--r--contrib/smbfs/mount_smbfs/mount_smbfs.c265
-rw-r--r--contrib/smbfs/smbutil/Makefile9
-rw-r--r--contrib/smbfs/smbutil/common.h17
-rw-r--r--contrib/smbfs/smbutil/dumptree.c134
-rw-r--r--contrib/smbfs/smbutil/login.c202
-rw-r--r--contrib/smbfs/smbutil/lookup.c110
-rw-r--r--contrib/smbfs/smbutil/print.c152
-rw-r--r--contrib/smbfs/smbutil/smbutil.1124
-rw-r--r--contrib/smbfs/smbutil/smbutil.c155
-rw-r--r--contrib/smbfs/smbutil/view.c127
52 files changed, 7041 insertions, 0 deletions
diff --git a/contrib/smbfs/COPYRIGHT b/contrib/smbfs/COPYRIGHT
new file mode 100644
index 000000000000..583923c35597
--- /dev/null
+++ b/contrib/smbfs/COPYRIGHT
@@ -0,0 +1,29 @@
+ Copyright (c) 2000, 2001 Boris Popov
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+ This product includes software developed by Boris Popov.
+ 4. Neither the name of the author nor the names of any co-contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
diff --git a/contrib/smbfs/CREDITS b/contrib/smbfs/CREDITS
new file mode 100644
index 000000000000..e9228afccf31
--- /dev/null
+++ b/contrib/smbfs/CREDITS
@@ -0,0 +1,10 @@
+
+ In the development process next sources were used:
+
+Various documents from the Microsoft ftp site.
+HTML docs published by Thursby Software.
+
+Special thanks to the Samba team for permission to use their source
+code as reference.
+
+Author - Boris Popov <bp@butya.kz>, <bp@freebsd.org>
diff --git a/contrib/smbfs/HISTORY b/contrib/smbfs/HISTORY
new file mode 100644
index 000000000000..888c8142be27
--- /dev/null
+++ b/contrib/smbfs/HISTORY
@@ -0,0 +1,130 @@
+16.04.2001 1.4.1
+ - Kernel side of smbfs committed in the FreeBSD-current. It controlled
+ by following options: LIBMCHAIN, LIBICONV, NETSMB, NETSMBCRYPTO and SMBFS.
+ - Removed static dependency on the libiconv library, option WITH_ICONV
+ removed as well. If you use libiconv support, make sure that the latest
+ port is installed.
+ - Multiple mount/umount operations called in parallel can cause kernel
+ panic - fixed.
+ - Misc code cleanups.
+
+26.02.2001 1.3.6
+ - Names of some options is the config.mk.in file are changed. The old ones
+ are still supported.
+ - Synch with changes in the recent -current (you'll need kernel compiled
+ from sources at least as of Feb 24).
+ - In all previous versions of smbfs signals weren't properly masked,
+ which caused erratical behavior of some programs (ftp(1) for example).
+ - Mounted shares may become "frozen" (no timeout occurs) if server died or
+ disconnected for some reason - fixed.
+
+09.02.2001 1.3.5
+ - The user and server names was swapped in the "TreeConnect"
+ request (fixed by Jonathan Hanna).
+ - smb requester could cause a panic if there is no free mbufs - fixed.
+ - It is possible to use smbfs with devfs now, but it wasn't tested under
+ SMP. Also note that device permissions will be wrong, because devfs
+ do not allow passing of credentials to the cloning function.
+ - nsmbX device moved from the /dev/net directory to /dev directory.
+
+31.01.2001 1.3.4
+ - Maintance: synch with changes in the recent -current
+
+28.01.2001 1.3.3
+ - Connection handling engine rewritten in order to reduce number of
+ possible deadlocks during reconnect operations.
+ - Directory traversals should be faster on large directories.
+ - smbfs now can talk to the NetApp servers (thanks to Jonathan Hanna).
+ - smbfs.sh.sample script updated (ideas from Nikolai Saoukh).
+ - Minor bug fixes.
+
+19.11.2000 1.3.2
+ - synch with changes in the recent -current
+ - nail down a nasty bug which may cause incorrect values supplied as
+ domain name (reported by Harald Weis).
+ - There was a bug in the directory listing code which caused long directory
+ traversals to fail (reported by A G F Keahan).
+
+29.10.2000 1.3.1
+ - An attempt was made to get rid from the possible kernel stack overflow.
+ - Now connection will be restored properly under -stable.
+ NOTE: NT servers have an 'AutoDisconnect' feature which will drop client
+ connection after some time of idleing. smbfs will restore connection on
+ the next request, but one may wish to setup a cron job with a simple
+ 'ls /ntmount' command.
+
+20.10.2000 1.3.0
+ - Network IO engine significantly reworked. Now it uses kernel threads
+ to implement 'smbiod' process which handles network traffic for each VC.
+ Previous model were incapable to serve large number of mount points and
+ didn't work well with intensive IO operations performed on a different
+ files on the same mount point. Special care was taken on better
+ usage of MP systems.
+ Unfortunately, kernel threads aren't supported by FreeBSD 3.X and for
+ now it is excluded from the list of supported systems.
+ - Reduce overhead caused by using single hash table for each mount point.
+
+26.09.2000 1.2.8 (never released)
+ - More SMP related bugs are fixed.
+ - Make smbfs compatible with the Linux emulator.
+ - smbfs now known to work with IBM LanManager (special thanks to
+ Eugen Averin <mad@euinf.dp.ua>)
+ - Fix problem with files bigger than 2GB (reported by Lee McKenna)
+ - Please note that smbfs may not work properly with FreeBSD 3.X.
+
+16.08.2000 1.2.7
+ - Maintance: use better algorithm to detect SYSCTL_HANDLER_ARGS changes
+ to avoid compilation problems on various versions of FreeBSD.
+
+07.08.2000 1.2.6
+ - Fix iconv support, was broken in the 1.2.5
+ - Minor corrections to 'smbutil view' command.
+ - Fix kernel memory leak caused by two subsequent and identical
+ 'smbutil login' commands.
+
+25.07.2000 1.2.5
+ - NetBIOS name resolver added. '-I' option still supported. WINS server
+ can be specified in the nsmbrc file (nbns variable). To use resolver
+ with Win9X machines you have to specify WINS server in the config file.
+
+12.07.2000 1.2.4
+ - Variable SRCTREE in the config.mk replaced with SYSDIR and should
+ point to the sys directory. '/usr/src/sys' for example.
+ - Correct problem with the keep-alive packets
+
+04.07.2000 1.2.3
+ - Killed some bugs related to the out-of-mbufs condition.
+ - new keyword 'addr' added to the config file to specify server address.
+ - Another attempt to make reconnection procedure more stable.
+
+21.06.2000 1.2.2
+ - Device handles wasn't freed under FreeBSD 3.4 - fixed.
+ Implement correct handling of multiple connections to the same NT
+ server (thanks to kit <kit.mitchell@team.xtra.co.nz>) for report.
+ More misc fixes for an NT servers.
+
+11.06.2000 1.2.1
+ - More bug fixes in the connection handling mechanism.
+ mount_smbfs(8) manpage has now proper description for an '-N' option.
+ smbutil supports new commands:
+ 'print' - send file to the remote printer
+ 'view' - list shares available on the specified host
+ 'login' - create permanent connection to remote host
+ 'logout'- counterpart of 'login'
+ 'crypt' - produce an encrypted password to store in the .nsmbrc file.
+
+01.06.2000 1.1.2
+ - Support for FreeBSD 3.4 added (see INSTALL file for details).
+ Add advisory locking support in order to make fcntl(2), flock(2)
+ system calls actually work on smbfs.
+ Few non-serious bugs fixed.
+
+16.05.2000 1.0.5
+ - fix authentication code, this caused troubles with NT server.
+ (Thanks to Neil Blakey-Milner and Andrew Zavjalov for testing)
+ Some documentation changes.
+
+14.05.2000 1.0.2
+ - first public release
+
+Boris Popov <bp@butya.kz>
diff --git a/contrib/smbfs/INSTALL b/contrib/smbfs/INSTALL
new file mode 100644
index 000000000000..1ae864d277bb
--- /dev/null
+++ b/contrib/smbfs/INSTALL
@@ -0,0 +1,68 @@
+ 1. Building
+ ===========
+
+ Copy config.in file to the config.local and edit it for your needs. Build
+process requires kernel sources in order to compile KLD module. If you want
+to use encrypted passwords you'll need an src/sys/crypto directory (sys-crypto
+cvsup collection) because encryption process involves DES algorithm.
+
+ Note for FreeBSD-current: it have kernel module sources in the base
+tree and requires options LIBMCHAIN and LIBICONV included in the kernel
+config file. smbfs can be either compiled in the kernel or loaded as module.
+
+ If FreeBSD machine and SMB server uses different character sets you
+may consider install ports/converters/iconv package (version 2.0 required).
+
+ Type 'make' to compile.
+
+ If you're running any previous version of smbfs, unmount all mounted
+shares and unload an old module via 'kldunload smbfs' command.
+
+
+ 2. Installing
+ =============
+
+ 'make install' command will copy compiled binaries to /usr/local/bin
+directory and KLD module into /modules directory.
+
+ If you're running smbfs for the first time, it is also necessary to
+run 'make makedev' command in order to create /dev/nsmb0 device.
+
+ 3. Configuring
+ ==============
+
+ KLD module can be loaded either manually:
+
+ kldload smbfs.ko
+
+ or via loader.conf(5) file:
+
+ smbfs_load="YES"
+
+ However it is not strictly necessary because mount_smbfs(8) command
+will load it automatically.
+
+ Copy ./examples/dot.nsmbrc file into your home directory with ./.nsmbrc
+name and edit it for your needs.
+
+
+ 4. Running
+ ==========
+
+ Please read mount_smbfs man page to get overview of command options.
+
+ Here is a quick example:
+
+ mount_smbfs -I hostname //bp@myserver/myshare /mnt
+
+ If something goes wrong, please try to find a problem and, if it is a bug
+ send me detailed description or patch. Before complaining about a bug, please
+ check the same operations with smbclient program included in the Samba package.
+
+
+
+ 5. Deinstalling
+ ===============
+
+ All files can be completly removed by typing 'make deinstall' in the
+working directory.
diff --git a/contrib/smbfs/Makefile b/contrib/smbfs/Makefile
new file mode 100644
index 000000000000..6729780dda53
--- /dev/null
+++ b/contrib/smbfs/Makefile
@@ -0,0 +1,87 @@
+# $Id: Makefile,v 1.12 2001/04/16 04:34:26 bp Exp $
+#
+# Valid targets:
+# install installs binaries and man pages
+# deinstall undo install (except man pages)
+# install-src copy .h files in /usr/local/include
+# install-lib copy lib files in /usr/lib
+# deinstall-lib,
+# deinstall-src undo corresponding install-* target
+# clean cleanup source tree
+
+.if ${MACHINE_ARCH} != "i386"
+. error "only IA32 machines supported"
+.endif
+
+CONFIG_INT?= config.int
+CONFIG_MK?= config.mk
+
+CFGDEPEND=
+
+.ifmake !configure && !clean
+. if !exists(${CONFIG_INT})
+. error "Run 'make configure' before build"
+. else
+. include "${CONFIG_INT}"
+. endif
+.else
+. if exists(${CONFIG_MK})
+CFGDEPEND= ${CONFIG_MK}
+
+${CONFIG_MK}: config.mk.in
+ @echo Your ${CONFIG_MK} file is older than the config.mk.in file
+ @echo Please check for possible changes
+ @false
+
+. include "${CONFIG_MK}"
+. endif
+.endif
+
+BUILDKLD?=yes
+PREFIX?=/usr/local
+SYSDIR?=/usr/src/sys
+
+configure::
+.if ${CFGDEPEND} == ${CONFIG_MK}
+ @echo Using ${CFGDEPEND} file...
+.endif
+ echo PREFIX= ${PREFIX} > ${CONFIG_INT}
+ echo SYSDIR=${SYSDIR} >> ${CONFIG_INT}
+ echo KMODDIR=${KMODDIR} >> ${CONFIG_INT}
+ echo SINGLEKLD=yes >> ${CONFIG_INT}
+.if !defined(WITHOUT_CRYPT)
+ echo ENCRYPTED_PASSWD=yes >> ${CONFIG_INT}
+.endif
+.if defined(SMP_SUPPORT) || defined(SMP)
+ echo SMP=yes >> ${CONFIG_INT}
+.endif
+
+SUBDIR=
+
+.if defined(COMPLETEBUILD) || (${BUILDKLD} == yes && !exists(${SYSDIR}/netsmb/smb.h))
+SUBDIR+= kernel/modules
+.endif
+
+SUBDIR+= lib
+
+SUBDIR+= mount_smbfs smbutil
+
+install-src install-lib deinstall-lib deinstall-src:
+ cd kernel && make ${.TARGET}
+ cd lib && make ${.TARGET}
+
+
+makedev:
+ @-( if [ `mount -t devfs | wc -l` = 0 ]; then \
+ cd /dev && && rm -f nsmb* && mknod nsmb0 c 144 0; \
+ else \
+ echo This operation is not required with devfs; \
+ fi; \
+ )
+
+cleandepend deinstall: _SUBDIRUSE
+
+clean: _SUBDIRUSE
+ rm -f ${CONFIG_INT}
+
+.include <bsd.subdir.mk>
diff --git a/contrib/smbfs/Makefile.inc b/contrib/smbfs/Makefile.inc
new file mode 100644
index 000000000000..0e7173ceb998
--- /dev/null
+++ b/contrib/smbfs/Makefile.inc
@@ -0,0 +1,43 @@
+# $Id: Makefile.inc,v 1.9 2001/04/16 04:34:26 bp Exp $
+
+.ifmake !clean && !cleandepend
+.if !defined(PREFIX)
+.include "config.int"
+.endif
+.endif
+
+BINDIR?=${PREFIX}/bin
+SMBSBINDIR=${PREFIX}/sbin
+MANDIR=${PREFIX}/man/man
+
+CFLAGS += -Wall -I../kernel/mysys
+
+.include <bsd.libnames.mk>
+
+.if !defined(LIBSMB) || defined(COMPLETEBUILD)
+CFLAGS += -L../lib/smb -L../lib/nb
+CFLAGS += -I../include
+LIBSMB = ../lib/smb/libsmb.a
+.endif
+
+.if !exists(${SYSDIR}/netsmb/smb.h)
+CFLAGS += -I../kernel
+.endif
+
+.if defined(SMBGDB)
+CFLAGS+= -ggdb
+.endif
+
+deinstall:
+ @(if test -f ${BINDIR}/${PROG}; then \
+ echo removing ${BINDIR}/${PROG}; \
+ rm -f ${BINDIR}/${PROG}; \
+ fi;)
+ @(if test -f ${MANDIR}1/${MAN1}.gz ; then \
+ echo removing ${MANDIR}1/${MAN1}.gz; \
+ rm -f ${MANDIR}1/${MAN1}.gz; \
+ fi;)
+ @(if test -f ${MANDIR}8/${MAN8}.gz ; then \
+ echo removing ${MANDIR}8/${MAN8}.gz; \
+ rm -f ${MANDIR}8/${MAN8}.gz; \
+ fi;)
diff --git a/contrib/smbfs/README b/contrib/smbfs/README
new file mode 100644
index 000000000000..a85b43508cbb
--- /dev/null
+++ b/contrib/smbfs/README
@@ -0,0 +1,50 @@
+
+
+ SMB/CIFS protocol and SMB/CIFS file system implementation
+ for FreeBSD, version 1.4.
+
+ This is native SMB/CIFS filesystem (smbfs for short) for FreeBSD.
+It is a complete, kernel side implementation of SMB requester and filesystem.
+
+ Supportted platforms:
+ FreeBSD 4.X
+
+ FreeBSD-current kernel module is included in the base source
+ tree.
+
+ I'm would be very grateful for any feedback, bug reports etc.
+
+ Supported SMB servers:
+ Samba
+ Windows 95/98/ME/2000/NT4.0 (SPs 4, 5, 6)
+ IBM LanManager
+ NetApp
+
+ An updated versions of this package can be retrieved from ftp server:
+
+ ftp://ftp.butya.kz/pub/smbfs/smbfs.tar.gz
+
+ Perfomance
+ ==========
+
+ There is some perfomance benchmarks over 10Mbit network:
+
+ Win95 machine as server:
+IOZONE: auto-test mode
+ MB reclen bytes/sec written bytes/sec read
+ 1 512 339791 323416
+ 1 1024 481067 431568
+ 1 2048 648394 588674
+ 1 4096 630130 583555
+ 1 8192 671088 618514
+
+ Samba 2.0.6 as server:
+IOZONE: auto-test mode
+ MB reclen bytes/sec written bytes/sec read
+ 1 512 409200 437191
+ 1 1024 545600 596523
+ 1 2048 729444 798915
+ 1 4096 871543 919299
+ 1 8192 900790 1024562
+
+Author: Boris Popov <bp@freebsd.org>
diff --git a/contrib/smbfs/config.mk.in b/contrib/smbfs/config.mk.in
new file mode 100644
index 000000000000..328a115960b4
--- /dev/null
+++ b/contrib/smbfs/config.mk.in
@@ -0,0 +1,37 @@
+# SMBFS build configuration
+# copy this file to config.mk and edit as needed.
+# If you want to disable an option just comment it with '#' char.
+#
+# $Id: config.mk.in,v 1.16 2001/04/16 04:34:26 bp Exp $
+
+# Where your kernel source tree located (/usr/src/sys for example)
+SYSDIR=/usr/src/sys
+
+# Where the kernel module gets installed
+KMODDIR=/modules
+
+# Where all files get installed
+PREFIX?=/usr/local
+
+# Build shared smb library, or link all executables statically
+USE_SHAREDLIBS=no
+
+# Comment this to disable support for encrypted passwords (requires
+# src/sys/crypto directory). By default, NT and Win* machines use encrypted
+# passwords.
+ENCRYPTED_PASSWD=yes
+
+# Uncomment this option if kernel compiled with SMP suppport.
+# SMP_SUPPORT=
+
+# This turns on debug logging, be careful - it produces a lot of kernel
+# messages.
+#KDEBUG+= -DSMB_SOCKET_DEBUG
+#KDEBUG+= -DSMB_SOCKETDATA_DEBUG
+#KDEBUG+= -DSMB_VNODE_DEBUG
+
+# Compile binaries with debugging symbols
+#SMBGDB=yes
+
+# Build kernel module (don't touch that)
+SINGLEKLD=yes
diff --git a/contrib/smbfs/configure b/contrib/smbfs/configure
new file mode 100755
index 000000000000..1d38e525e10d
--- /dev/null
+++ b/contrib/smbfs/configure
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+make configure $*
diff --git a/contrib/smbfs/examples/dot.nsmbrc b/contrib/smbfs/examples/dot.nsmbrc
new file mode 100644
index 000000000000..b630fa8bda40
--- /dev/null
+++ b/contrib/smbfs/examples/dot.nsmbrc
@@ -0,0 +1,57 @@
+# $Id: dot.nsmbrc,v 1.6 2000/07/16 01:52:06 bp Exp $
+#
+# Example for .nsmbrc file
+#
+# smbfs lookups configuration files in next order:
+# 1. ~/.nsmbrc
+# 2. /usr/local/etc/nsmb.conf - if this file found it will
+# override values with same keys from user files.
+#
+#
+# This file consist from a set of sections. Each section started by section name
+# surrounded with square brackets:
+# [section_name]
+#
+# End of the section marked either by new section or by the end of file.
+# Each section can contain zero or more parameters:
+# [section_name]
+# key=value
+#
+# where 'key' represents parameter name and 'value' a value assigned
+# to this parameter.
+#
+# SMB library uses next forms of section names:
+# A) [default]
+# B) [SERVER]
+# C) [SERVER:USER]
+# D) [SERVER:USER:SHARE]
+#
+# Here is the map of possible keywords:
+#
+# keyword/section A B C D Comment
+#
+# addr - + - - IP or IPX address of SMB server
+# charsets - + + + local:remote charset pair
+# nbns + + - - address of NetBIOS name server (WINS)
+# nbscope + + - - NetBIOS scope
+# nbtimeout + + - - timeout for NetBIOS name servers
+# password - - + + a plain text password used to access to the given share
+# retry_count + + - - number of retries before connection marked as broken
+# timeout + + - - SMB request timeout
+# workgroup + + + + name of workgroup
+#
+
+# A simple configuration example:
+
+# First, define a workgroup.
+[default]
+workgroup=SALES
+
+# The 'FSERVER' is an NT server.
+[FSERVER]
+charsets=koi8-r:cp866
+addr=fserv.coolcorp.com
+
+[FSERVER:JOE]
+# use persistent password cache for user 'joe'
+password=$$1767877DF
diff --git a/contrib/smbfs/examples/print/lj6l b/contrib/smbfs/examples/print/lj6l
new file mode 100755
index 000000000000..578611a32f2b
--- /dev/null
+++ b/contrib/smbfs/examples/print/lj6l
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+# Sample input filter to print on HP Laser Jet printers
+# Installed in /usr/local/libexec/hp6l
+
+DEVICE="ljet3"
+PAPERSIZE="a4"
+
+printf "\033&k2G" || exit 2
+
+read first_line
+first_two_chars=`expr "$first_line" : '\(..\)'`
+
+if [ "$first_two_chars" = "%!" ]; then
+ exec 3>&1 1>&2
+ /usr/local/bin/gs -sPAPERSIZE=${PAPERSIZE} -dSAFER -dNOPAUSE -q -sDEVICE=${DEVICE} \
+ -sOutputFile=/dev/fd/3 - && exit 0
+else
+ echo $first_line && cat && printf "\033&l0H" && exit 0
+fi
+
+exit 2
diff --git a/contrib/smbfs/examples/print/ljspool b/contrib/smbfs/examples/print/ljspool
new file mode 100755
index 000000000000..32b09ea56d41
--- /dev/null
+++ b/contrib/smbfs/examples/print/ljspool
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+/usr/local/libexec/lj6l | /usr/local/libexec/tolj && exit 0
+exit 2
diff --git a/contrib/smbfs/examples/print/printcap.sample b/contrib/smbfs/examples/print/printcap.sample
new file mode 100644
index 000000000000..6d1e8992ad86
--- /dev/null
+++ b/contrib/smbfs/examples/print/printcap.sample
@@ -0,0 +1,7 @@
+# $Id: printcap.sample,v 1.1 2000/06/11 08:13:28 bp Exp $
+
+# Sample printcap entry for NetWare printer
+fserverlj|LJ6L on the fserver:\
+ :sh:lp=/dev/null:\
+ :if=/usr/local/libexec/ljspool: \
+ :sd=/var/spool/output/nwhost:lf=/var/log/lpd-errs:
diff --git a/contrib/smbfs/examples/print/tolj b/contrib/smbfs/examples/print/tolj
new file mode 100755
index 000000000000..e74cb90a7506
--- /dev/null
+++ b/contrib/smbfs/examples/print/tolj
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+QUEUE="//joe@fserver/lj"
+
+/usr/local/bin/smbutil print ${QUEUE} -
diff --git a/contrib/smbfs/examples/smbfs.sh.sample b/contrib/smbfs/examples/smbfs.sh.sample
new file mode 100644
index 000000000000..7908de26cc64
--- /dev/null
+++ b/contrib/smbfs/examples/smbfs.sh.sample
@@ -0,0 +1,37 @@
+#!/bin/sh
+#
+# $Id: smbfs.sh.sample,v 1.3 2001/01/13 04:50:36 bp Exp $
+#
+# Location: /usr/local/etc/rc.d/smbfs.sh
+#
+# Simple script to mount smbfs file systems at startup.
+# It assumes that all mount points described in fstab file and password
+# entries listed in /root/.nsmbrc file. See mount_smbfs(8) for details.
+#
+
+mount="/sbin/mount -o -N"
+umount=/sbin/umount
+HOME=/root; export HOME
+vols=`awk -- '/^\/.*[[:space:]]+smbfs[[:space:]]+/ { print $2 }' /etc/fstab`
+
+case "$1" in
+start)
+ echo -n "smbfs: "
+ for vol in ${vols}; do
+ $mount $vol
+ echo -n "$vol "
+ done
+ ;;
+stop)
+ echo -n "unmounting smbfs mount points: "
+ for vol in ${vols}; do
+ $umount $vol
+ echo -n "$vol "
+ done
+ ;;
+*)
+ echo "Usage: `basename $0` {start|stop}" >&2
+ exit 64
+esac
+
+echo "Done"
diff --git a/contrib/smbfs/include/cflib.h b/contrib/smbfs/include/cflib.h
new file mode 100644
index 000000000000..61e3c2321387
--- /dev/null
+++ b/contrib/smbfs/include/cflib.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: cflib.h,v 1.3 2000/07/11 01:51:49 bp Exp $
+ */
+#ifndef _zzzzzz_RCFILE_H_
+#define _zzzzzz_RCFILE_H_
+
+struct rcfile;
+
+/*
+ * A unified options parser
+ */
+enum opt_argtype {OPTARG_STR, OPTARG_INT, OPTARG_BOOL};
+
+struct opt_args;
+
+typedef int opt_callback_t (struct opt_args*);
+
+#define OPTFL_NONE 0x0000
+#define OPTFL_HAVEMIN 0x0001
+#define OPTFL_HAVEMAX 0x0002
+#define OPTFL_MINMAX NAFL_HAVEMIN | NAFL_HAVEMAX
+
+struct opt_args {
+ enum opt_argtype type;
+ int opt; /* command line option */
+ char * name; /* rc file equiv */
+ int flag; /* OPTFL_* */
+ int ival; /* int/bool values, or max len for str value */
+ char * str; /* string value */
+ int min; /* min for ival */
+ int max; /* max for ival */
+ opt_callback_t *fn; /* call back to validate */
+};
+
+extern int cf_opterr, cf_optind, cf_optopt, cf_optreset;
+extern const char *cf_optarg;
+
+__BEGIN_DECLS
+
+int opt_args_parse(struct rcfile *, struct opt_args *, const char *,
+ opt_callback_t *);
+int opt_args_parseopt(struct opt_args *, int, char *, opt_callback_t *);
+
+int cf_getopt(int, char * const *, const char *);
+
+int rc_open(const char *, const char *, struct rcfile **);
+int rc_close(struct rcfile *);
+int rc_merge(const char *, struct rcfile **);
+int rc_getstringptr(struct rcfile *, const char *, const char *, char **);
+int rc_getstring(struct rcfile *, const char *, const char *, size_t, char *);
+int rc_getint(struct rcfile *, const char *, const char *, int *);
+int rc_getbool(struct rcfile *, const char *, const char *, int *);
+
+__END_DECLS
+
+#endif /* _zzzzzz_RCFILE_H_ */
diff --git a/contrib/smbfs/include/netsmb/nb_lib.h b/contrib/smbfs/include/netsmb/nb_lib.h
new file mode 100644
index 000000000000..dbbdc6b2e458
--- /dev/null
+++ b/contrib/smbfs/include/netsmb/nb_lib.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: nb_lib.h,v 1.2 2000/07/17 01:49:27 bp Exp $
+ */
+#ifndef _NETSMB_NB_LIB_H_
+#define _NETSMB_NB_LIB_H_
+
+/*
+ * Error codes
+ */
+#define NBERR_INVALIDFORMAT 0x0001
+#define NBERR_SRVFAILURE 0x0002
+#define NBERR_NAMENOTFOUND 0x0003
+#define NBERR_IMP 0x0004
+#define NBERR_REFUSED 0x0005
+#define NBERR_ACTIVE 0x0006
+#define NBERR_HOSTNOTFOUND 0x0101
+#define NBERR_TOOMANYREDIRECTS 0x0102
+#define NBERR_INVALIDRESPONSE 0x0103
+#define NBERR_NAMETOOLONG 0x0104
+#define NBERR_NOBCASTIFS 0x0105
+#define NBERR_MAX 0x0106
+#define NBERROR(e) ((e) | SMB_NB_ERROR)
+
+#define NBCF_RESOLVED 0x0001
+
+/*
+ * nb environment
+ */
+struct nb_ctx {
+ int nb_flags;
+ int nb_timo;
+ char * nb_scope; /* NetBIOS scope */
+ char * nb_nsname; /* name server */
+ struct sockaddr_in nb_ns; /* ip addr of name server */
+ struct sockaddr_in nb_lastns;
+};
+
+/*
+ * resource record
+ */
+struct nbns_rr {
+ u_char * rr_name; /* compressed NETBIOS name */
+ u_int16_t rr_type;
+ u_int16_t rr_class;
+ u_int32_t rr_ttl;
+ u_int16_t rr_rdlength;
+ u_char * rr_data;
+};
+
+#define NBRQF_BROADCAST 0x0001
+/*
+ * nbns request
+ */
+struct nbns_rq {
+ int nr_opcode;
+ int nr_nmflags;
+ int nr_rcode;
+ int nr_qdcount;
+ int nr_ancount;
+ int nr_nscount;
+ int nr_arcount;
+ struct nb_name* nr_qdname;
+ u_int16_t nr_qdtype;
+ u_int16_t nr_qdclass;
+ struct sockaddr_in nr_dest; /* receiver of query */
+ struct sockaddr_in nr_sender; /* sender of response */
+ int nr_rpnmflags;
+ int nr_rprcode;
+ u_int16_t nr_rpancount;
+ u_int16_t nr_rpnscount;
+ u_int16_t nr_rparcount;
+ u_int16_t nr_trnid;
+ struct nb_ctx * nr_nbd;
+ struct mbdata nr_rq;
+ struct mbdata nr_rp;
+ struct nb_ifdesc *nr_if;
+ int nr_flags;
+ int nr_fd;
+};
+
+struct nb_ifdesc {
+ int id_flags;
+ struct in_addr id_addr;
+ struct in_addr id_mask;
+ char id_name[16]; /* actually IFNAMSIZ */
+ struct nb_ifdesc * id_next;
+};
+
+struct sockaddr;
+
+__BEGIN_DECLS
+
+int nb_name_len(struct nb_name *);
+int nb_name_encode(struct nb_name *, u_char *);
+int nb_encname_len(const char *);
+
+int nb_snballoc(int namelen, struct sockaddr_nb **);
+void nb_snbfree(struct sockaddr*);
+int nb_sockaddr(struct sockaddr *, struct nb_name *, struct sockaddr_nb **);
+
+int nb_resolvehost_in(const char *, struct sockaddr **);
+int nbns_resolvename(const char *, struct nb_ctx *, struct sockaddr **);
+int nb_getlocalname(char *name);
+int nb_enum_if(struct nb_ifdesc **, int);
+
+const char *nb_strerror(int error);
+
+int nb_ctx_create(struct nb_ctx **);
+void nb_ctx_done(struct nb_ctx *);
+int nb_ctx_setns(struct nb_ctx *, const char *);
+int nb_ctx_setscope(struct nb_ctx *, const char *);
+int nb_ctx_resolve(struct nb_ctx *);
+int nb_ctx_readrcsection(struct rcfile *, struct nb_ctx *, const char *, int);
+
+__END_DECLS
+
+#endif /* !_NETSMB_NB_LIB_H_ */
diff --git a/contrib/smbfs/include/netsmb/smb_lib.h b/contrib/smbfs/include/netsmb/smb_lib.h
new file mode 100644
index 000000000000..24fccb86dc70
--- /dev/null
+++ b/contrib/smbfs/include/netsmb/smb_lib.h
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2000-2001 Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: smb_lib.h,v 1.22 2001/04/10 05:37:22 bp Exp $
+ */
+#ifndef _NETSMB_SMB_LIB_H_
+#define _NETSMB_SMB_LIB_H_
+
+#include <netsmb/smb.h>
+#include <netsmb/smb_dev.h>
+
+#define SMB_CFG_FILE "/usr/local/etc/nsmb.conf"
+
+#define STDPARAM_ARGS 'A':case 'B':case 'C':case 'E':case 'I': \
+ case 'L':case 'M': \
+ case 'N':case 'U':case 'R':case 'S':case 'T': \
+ case 'W':case 'O':case 'P'
+
+#define STDPARAM_OPT "A:BCE:I:L:M:NO:P:U:R:S:T:W:"
+
+/*
+ * bits to indicate the source of error
+ */
+#define SMB_ERRTYPE_MASK 0xf0000
+#define SMB_SYS_ERROR 0x00000
+#define SMB_RAP_ERROR 0x10000
+#define SMB_NB_ERROR 0x20000
+
+#ifndef min
+#define min(a,b) (((a)<(b)) ? (a) : (b))
+#endif
+
+#define getb(buf,ofs) (((const u_int8_t *)(buf))[ofs])
+#define setb(buf,ofs,val) (((u_int8_t*)(buf))[ofs])=val
+#define getbw(buf,ofs) ((u_int16_t)(getb(buf,ofs)))
+#define getw(buf,ofs) (*((u_int16_t*)(&((u_int8_t*)(buf))[ofs])))
+#define getdw(buf,ofs) (*((u_int32_t*)(&((u_int8_t*)(buf))[ofs])))
+
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+
+#define getwle(buf,ofs) (*((u_int16_t*)(&((u_int8_t*)(buf))[ofs])))
+#define getdle(buf,ofs) (*((u_int32_t*)(&((u_int8_t*)(buf))[ofs])))
+#define getwbe(buf,ofs) (ntohs(getwle(buf,ofs)))
+#define getdbe(buf,ofs) (ntohl(getdle(buf,ofs)))
+
+#define setwle(buf,ofs,val) getwle(buf,ofs)=val
+#define setwbe(buf,ofs,val) getwle(buf,ofs)=htons(val)
+#define setdle(buf,ofs,val) getdle(buf,ofs)=val
+#define setdbe(buf,ofs,val) getdle(buf,ofs)=htonl(val)
+
+#else /* (BYTE_ORDER == LITTLE_ENDIAN) */
+#error "Macros for Big-Endians are incomplete"
+#define getwle(buf,ofs) ((u_int16_t)(getb(buf, ofs) | (getb(buf, ofs + 1) << 8)))
+#define getdle(buf,ofs) ((u_int32_t)(getb(buf, ofs) | \
+ (getb(buf, ofs + 1) << 8) | \
+ (getb(buf, ofs + 2) << 16) | \
+ (getb(buf, ofs + 3) << 24)))
+#define getwbe(buf,ofs) (*((u_int16_t*)(&((u_int8_t*)(buf))[ofs])))
+#define getdbe(buf,ofs) (*((u_int32_t*)(&((u_int8_t*)(buf))[ofs])))
+/*
+#define setwle(buf,ofs,val) getwle(buf,ofs)=val
+#define setdle(buf,ofs,val) getdle(buf,ofs)=val
+*/
+#define setwbe(buf,ofs,val) getwle(buf,ofs)=val
+#define setdbe(buf,ofs,val) getdle(buf,ofs)=val
+
+#endif /* (BYTE_ORDER == LITTLE_ENDIAN) */
+
+/*
+ * SMB work context. Used to store all values which is necessary
+ * to establish connection to an SMB server.
+ */
+struct smb_ctx {
+ int ct_flags; /* SMBCF_ */
+ int ct_fd; /* handle of connection */
+ int ct_parsedlevel;
+ int ct_minlevel;
+ int ct_maxlevel;
+ char * ct_srvaddr; /* hostname or IP address of server */
+ char ct_locname[SMB_MAXUSERNAMELEN + 1];
+ const char * ct_uncnext;
+ struct nb_ctx * ct_nb;
+ struct smbioc_ossn ct_ssn;
+ struct smbioc_oshare ct_sh;
+};
+
+#define SMBCF_NOPWD 0x0001 /* don't ask for a password */
+#define SMBCF_SRIGHTS 0x0002 /* share access rights was supplied */
+#define SMBCF_LOCALE 0x0004 /* use current locale */
+#define SMBCF_RESOLVED 0x8000 /* structure has been verified */
+
+/*
+ * request handling structures
+ */
+struct mbuf {
+ int m_len;
+ int m_maxlen;
+ char * m_data;
+ struct mbuf * m_next;
+};
+
+struct mbdata {
+ struct mbuf * mb_top;
+ struct mbuf * mb_cur;
+ char * mb_pos;
+ int mb_count;
+};
+
+#define M_ALIGNFACTOR (sizeof(long))
+#define M_ALIGN(len) (((len) + M_ALIGNFACTOR - 1) & ~(M_ALIGNFACTOR - 1))
+#define M_BASESIZE (sizeof(struct mbuf))
+#define M_MINSIZE (256 - M_BASESIZE)
+#define M_TOP(m) ((char*)(m) + M_BASESIZE)
+#define mtod(m,t) ((t)(m)->m_data)
+#define M_TRAILINGSPACE(m) ((m)->m_maxlen - (m)->m_len)
+
+struct smb_rq {
+ u_char rq_cmd;
+ struct mbdata rq_rq;
+ struct mbdata rq_rp;
+ struct smb_ctx *rq_ctx;
+ int rq_wcount;
+ int rq_bcount;
+};
+
+struct smb_bitname {
+ u_int bn_bit;
+ char *bn_name;
+};
+
+extern struct rcfile *smb_rc;
+
+__BEGIN_DECLS
+
+struct sockaddr;
+
+int smb_lib_init(void);
+int smb_open_rcfile(void);
+void smb_error(const char *, int,...);
+char *smb_printb(char *, int, const struct smb_bitname *);
+void *smb_dumptree(void);
+
+/*
+ * Context management
+ */
+int smb_ctx_init(struct smb_ctx *, int, char *[], int, int, int);
+void smb_ctx_done(struct smb_ctx *);
+int smb_ctx_parseunc(struct smb_ctx *, const char *, int, const char **);
+int smb_ctx_setcharset(struct smb_ctx *, const char *);
+int smb_ctx_setserver(struct smb_ctx *, const char *);
+int smb_ctx_setuser(struct smb_ctx *, const char *);
+int smb_ctx_setshare(struct smb_ctx *, const char *, int);
+int smb_ctx_setscope(struct smb_ctx *, const char *);
+int smb_ctx_setworkgroup(struct smb_ctx *, const char *);
+int smb_ctx_setpassword(struct smb_ctx *, const char *);
+int smb_ctx_setsrvaddr(struct smb_ctx *, const char *);
+int smb_ctx_opt(struct smb_ctx *, int, const char *);
+int smb_ctx_lookup(struct smb_ctx *, int, int);
+int smb_ctx_login(struct smb_ctx *);
+int smb_ctx_readrc(struct smb_ctx *);
+int smb_ctx_resolve(struct smb_ctx *);
+int smb_ctx_setflags(struct smb_ctx *, int, int, int);
+
+int smb_smb_open_print_file(struct smb_ctx *, int, int, const char *, smbfh*);
+int smb_smb_close_print_file(struct smb_ctx *, smbfh);
+
+int smb_read(struct smb_ctx *, smbfh, off_t, size_t, char *);
+int smb_write(struct smb_ctx *, smbfh, off_t, size_t, const char *);
+
+#define smb_rq_getrequest(rqp) (&(rqp)->rq_rq)
+#define smb_rq_getreply(rqp) (&(rqp)->rq_rp)
+
+int smb_rq_init(struct smb_ctx *, u_char, size_t, struct smb_rq **);
+void smb_rq_done(struct smb_rq *);
+void smb_rq_wend(struct smb_rq *);
+int smb_rq_simple(struct smb_rq *);
+int smb_rq_dmem(struct mbdata *, const char *, size_t);
+int smb_rq_dstring(struct mbdata *, const char *);
+
+int smb_t2_request(struct smb_ctx *, int, int, const char *,
+ int, void *, int, void *, int *, void *, int *, void *);
+
+void smb_simplecrypt(char *dst, const char *src);
+int smb_simpledecrypt(char *dst, const char *src);
+
+int m_getm(struct mbuf *, size_t, struct mbuf **);
+int m_lineup(struct mbuf *, struct mbuf **);
+int mb_init(struct mbdata *, size_t);
+int mb_initm(struct mbdata *, struct mbuf *);
+int mb_done(struct mbdata *);
+int mb_fit(struct mbdata *mbp, size_t size, char **pp);
+int mb_put_uint8(struct mbdata *, u_int8_t);
+int mb_put_uint16be(struct mbdata *, u_int16_t);
+int mb_put_uint16le(struct mbdata *, u_int16_t);
+int mb_put_uint32be(struct mbdata *, u_int32_t);
+int mb_put_uint32le(struct mbdata *, u_int32_t);
+int mb_put_int64be(struct mbdata *, int64_t);
+int mb_put_int64le(struct mbdata *, int64_t);
+int mb_put_mem(struct mbdata *, const char *, size_t);
+int mb_put_pstring(struct mbdata *mbp, const char *s);
+int mb_put_mbuf(struct mbdata *, struct mbuf *);
+
+int mb_get_uint8(struct mbdata *, u_int8_t *);
+int mb_get_uint16(struct mbdata *, u_int16_t *);
+int mb_get_uint16le(struct mbdata *, u_int16_t *);
+int mb_get_uint16be(struct mbdata *, u_int16_t *);
+int mb_get_uint32(struct mbdata *, u_int32_t *);
+int mb_get_uint32be(struct mbdata *, u_int32_t *);
+int mb_get_uint32le(struct mbdata *, u_int32_t *);
+int mb_get_int64(struct mbdata *, int64_t *);
+int mb_get_int64be(struct mbdata *, int64_t *);
+int mb_get_int64le(struct mbdata *, int64_t *);
+int mb_get_mem(struct mbdata *, char *, size_t);
+
+extern u_char nls_lower[256], nls_upper[256];
+
+int nls_setrecode(const char *, const char *);
+int nls_setlocale(const char *);
+char* nls_str_toext(char *, const char *);
+char* nls_str_toloc(char *, const char *);
+void* nls_mem_toext(void *, const void *, int);
+void* nls_mem_toloc(void *, const void *, int);
+char* nls_str_upper(char *, const char *);
+char* nls_str_lower(char *, const char *);
+
+__END_DECLS
+
+#endif /* _NETSMB_SMB_LIB_H_ */
diff --git a/contrib/smbfs/include/netsmb/smb_rap.h b/contrib/smbfs/include/netsmb/smb_rap.h
new file mode 100644
index 000000000000..cb867a5faf6b
--- /dev/null
+++ b/contrib/smbfs/include/netsmb/smb_rap.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2000-2001, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: smb_rap.h,v 1.3 2001/04/10 05:37:22 bp Exp $
+ */
+#ifndef _NETSMB_SMB_RAP_H_
+#define _NETSMB_SMB_RAP_H_
+
+struct smb_rap {
+ char * r_sparam;
+ char * r_nparam;
+ char * r_sdata;
+ char * r_ndata;
+ char * r_pbuf; /* rq parameters */
+ int r_plen; /* rq param len */
+ char * r_npbuf;
+ char * r_dbuf; /* rq data */
+ int r_dlen; /* rq data len */
+ char * r_ndbuf;
+ u_int32_t r_result;
+ char * r_rcvbuf;
+ int r_rcvbuflen;
+ int r_entries;
+};
+
+struct smb_share_info_1 {
+ char shi1_netname[13];
+ char shi1_pad;
+ u_int16_t shi1_type;
+ u_int32_t shi1_remark; /* char * */
+};
+
+__BEGIN_DECLS
+
+int smb_rap_create(int, const char *, const char *, struct smb_rap **);
+void smb_rap_done(struct smb_rap *);
+int smb_rap_request(struct smb_rap *, struct smb_ctx *);
+int smb_rap_setNparam(struct smb_rap *, long);
+int smb_rap_setPparam(struct smb_rap *, void *);
+int smb_rap_error(struct smb_rap *, int);
+
+int smb_rap_NetShareEnum(struct smb_ctx *, int, void *, int, int *, int *);
+
+__END_DECLS
+
+#endif /* _NETSMB_SMB_RAP_H_ */
diff --git a/contrib/smbfs/lib/Makefile b/contrib/smbfs/lib/Makefile
new file mode 100644
index 000000000000..21474fb4fe64
--- /dev/null
+++ b/contrib/smbfs/lib/Makefile
@@ -0,0 +1,21 @@
+# $Id: Makefile,v 1.5 2001/02/24 15:56:04 bp Exp $
+
+.ifmake !clean && !cleandepend
+.include "../config.int"
+.endif
+
+#.if defined(COMPLETEBUILD) || !exists(/usr/lib/libnls.a)
+#SUBDIR+= nls
+#.endif
+
+#.if defined(COMPLETEBUILD) || !exists(/usr/lib/libnb.a)
+#SUBDIR+= nb
+#.endif
+
+.if defined(COMPLETEBUILD) || !exists(/usr/lib/libsmb.a)
+SUBDIR+= smb
+.endif
+
+deinstall install-lib deinstall-lib install-src deinstall-src: _SUBDIRUSE
+
+.include <bsd.subdir.mk>
diff --git a/contrib/smbfs/lib/Makefile.inc b/contrib/smbfs/lib/Makefile.inc
new file mode 100644
index 000000000000..43bd23ef2c56
--- /dev/null
+++ b/contrib/smbfs/lib/Makefile.inc
@@ -0,0 +1,18 @@
+#
+
+CFLAGS+= -I${.CURDIR}/../../include
+CFLAGS+= -I${.CURDIR}/../../kernel/mysys
+CFLAGS+= -Wall ${BPCFLAGS}
+
+.if !exists(${SYSDIR}/netsmb/smb.h)
+CFLAGS+= -I${.CURDIR}/../../kernel
+.endif
+
+.if defined(SMBGDB)
+CFLAGS+= -ggdb
+.endif
+
+CLEANFILES+=.depend
+
+deinstall: deinstall-lib deinstall-src
+
diff --git a/contrib/smbfs/lib/smb/Makefile b/contrib/smbfs/lib/smb/Makefile
new file mode 100644
index 000000000000..9b76203dbc2a
--- /dev/null
+++ b/contrib/smbfs/lib/smb/Makefile
@@ -0,0 +1,50 @@
+# $Id: Makefile,v 1.12 2001/04/16 14:27:35 bp Exp $
+
+LIB= smb
+
+NOPROFILE= yes
+
+#SHLIB_MAJOR= 1
+#SHLIB_MINOR= 0
+
+NOMAN=
+
+SRCS= rcfile.c ctx.c cfopt.c subr.c nls.c rap.c mbuf.c rq.c file.c \
+ print.c \
+ kiconv.c \
+ nb.c nb_name.c nb_net.c nbns_rq.c
+
+.ifmake !clean && !cleandepend
+.if !defined(PREFIX)
+.include "../../config.int"
+.endif
+.endif
+
+DESTDIR=${PREFIX}/
+LIBDIR=lib
+
+.if !defined(USE_SHAREDLIBS)
+NOPIC= yes
+.endif
+
+install-src: install-lib
+
+deinstall-src: deinstall-lib
+
+.include <bsd.lib.mk>
+
+install-lib: afterinstall _SUBDIR
+.if !defined(NOMAN)
+afterinstall: realinstall maninstall
+.else
+afterinstall: realinstall
+.endif
+
+deinstall-lib:
+ rm -f ${DESTDIR}/${LIBDIR}/lib${LIB}.a
+.if defined(SHLIB_NAME)
+ rm -f ${DESTDIR}/${SHLIBDIR}/${SHLIB_NAME}
+.endif
+.if defined(SHLIB_LINK)
+ rm -f ${DESTDIR}/${SHLIBDIR}/${SHLIB_LINK}
+.endif
diff --git a/contrib/smbfs/lib/smb/cfopt.c b/contrib/smbfs/lib/smb/cfopt.c
new file mode 100644
index 000000000000..5328b2ff52fb
--- /dev/null
+++ b/contrib/smbfs/lib/smb/cfopt.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: cfopt.c,v 1.3 2000/07/11 01:51:49 bp Exp $
+ */
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include <cflib.h>
+
+extern char *__progname;
+
+int cf_opterr = 1, /* if error message should be printed */
+ cf_optind = 1, /* index into parent argv vector */
+ cf_optopt, /* character checked for validity */
+ cf_optreset; /* reset getopt */
+const char* cf_optarg; /* argument associated with option */
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+int
+cf_getopt(nargc, nargv, ostr)
+ int nargc;
+ char * const *nargv;
+ const char *ostr;
+{
+ static const char *place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+ int tmpind;
+
+ if (cf_optreset || !*place) { /* update scanning pointer */
+ cf_optreset = 0;
+ tmpind = cf_optind;
+ while (1) {
+ if (tmpind >= nargc) {
+ place = EMSG;
+ return (-1);
+ }
+ if (*(place = nargv[tmpind]) != '-') {
+ tmpind++;
+ continue; /* lookup next option */
+ }
+ if (place[1] && *++place == '-') { /* found "--" */
+ cf_optind = ++tmpind;
+ place = EMSG;
+ return (-1);
+ }
+ cf_optind = tmpind;
+ break;
+ }
+ } /* option letter okay? */
+ if ((cf_optopt = (int)*place++) == (int)':' ||
+ !(oli = strchr(ostr, cf_optopt))) {
+ /*
+ * if the user didn't specify '-' as an option,
+ * assume it means -1.
+ */
+ if (cf_optopt == (int)'-')
+ return (-1);
+ if (!*place)
+ ++cf_optind;
+ if (cf_opterr && *ostr != ':')
+ (void)fprintf(stderr,
+ "%s: illegal option -- %c\n", __progname, cf_optopt);
+ return (BADCH);
+ }
+ if (*++oli != ':') { /* don't need argument */
+ cf_optarg = NULL;
+ if (!*place)
+ ++cf_optind;
+ }
+ else { /* need an argument */
+ if (*place) /* no white space */
+ cf_optarg = place;
+ else if (nargc <= ++cf_optind) { /* no arg */
+ place = EMSG;
+ if (*ostr == ':')
+ return (BADARG);
+ if (cf_opterr)
+ (void)fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ __progname, cf_optopt);
+ return (BADCH);
+ }
+ else /* white space */
+ cf_optarg = nargv[cf_optind];
+ place = EMSG;
+ ++cf_optind;
+ }
+ return (cf_optopt); /* dump back option letter */
+}
diff --git a/contrib/smbfs/lib/smb/ctx.c b/contrib/smbfs/lib/smb/ctx.c
new file mode 100644
index 000000000000..6ecb190419bc
--- /dev/null
+++ b/contrib/smbfs/lib/smb/ctx.c
@@ -0,0 +1,773 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: ctx.c,v 1.21 2001/04/06 15:47:14 bp Exp $
+ */
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/mount.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <sys/iconv.h>
+
+#define NB_NEEDRESOLVER
+
+#include <netsmb/smb_lib.h>
+#include <netsmb/netbios.h>
+#include <netsmb/nb_lib.h>
+#include <netsmb/smb_conn.h>
+#include <cflib.h>
+
+/*
+ * Prescan command line for [-U user] argument
+ * and fill context with defaults
+ */
+int
+smb_ctx_init(struct smb_ctx *ctx, int argc, char *argv[],
+ int minlevel, int maxlevel, int sharetype)
+{
+ int opt, error = 0;
+ const char *arg, *cp;
+
+ bzero(ctx,sizeof(*ctx));
+ error = nb_ctx_create(&ctx->ct_nb);
+ if (error)
+ return error;
+ ctx->ct_fd = -1;
+ ctx->ct_parsedlevel = SMBL_NONE;
+ ctx->ct_minlevel = minlevel;
+ ctx->ct_maxlevel = maxlevel;
+
+ ctx->ct_ssn.ioc_opt = SMBVOPT_CREATE;
+ ctx->ct_ssn.ioc_timeout = 15;
+ ctx->ct_ssn.ioc_retrycount = 4;
+ ctx->ct_ssn.ioc_owner = SMBM_ANY_OWNER;
+ ctx->ct_ssn.ioc_group = SMBM_ANY_GROUP;
+ ctx->ct_ssn.ioc_mode = SMBM_EXEC;
+ ctx->ct_ssn.ioc_rights = SMBM_DEFAULT;
+
+ ctx->ct_sh.ioc_opt = SMBVOPT_CREATE;
+ ctx->ct_sh.ioc_owner = SMBM_ANY_OWNER;
+ ctx->ct_sh.ioc_group = SMBM_ANY_GROUP;
+ ctx->ct_sh.ioc_mode = SMBM_EXEC;
+ ctx->ct_sh.ioc_rights = SMBM_DEFAULT;
+ ctx->ct_sh.ioc_owner = SMBM_ANY_OWNER;
+ ctx->ct_sh.ioc_group = SMBM_ANY_GROUP;
+
+ nb_ctx_setscope(ctx->ct_nb, "");
+ smb_ctx_setuser(ctx, getpwuid(geteuid())->pw_name);
+ endpwent();
+ if (argv == NULL)
+ return 0;
+ for (opt = 1; opt < argc; opt++) {
+ cp = argv[opt];
+ if (strncmp(cp, "//", 2) != 0)
+ continue;
+ error = smb_ctx_parseunc(ctx, cp, sharetype, (const char**)&cp);
+ if (error)
+ return error;
+ ctx->ct_uncnext = cp;
+ break;
+ }
+ while (error == 0 && (opt = cf_getopt(argc, argv, ":E:L:U:")) != -1) {
+ arg = cf_optarg;
+ switch (opt) {
+ case 'E':
+ error = smb_ctx_setcharset(ctx, arg);
+ if (error)
+ return error;
+ break;
+ case 'L':
+ error = nls_setlocale(optarg);
+ if (error)
+ break;
+ break;
+ case 'U':
+ error = smb_ctx_setuser(ctx, arg);
+ break;
+ }
+ }
+ cf_optind = cf_optreset = 1;
+ return error;
+}
+
+void
+smb_ctx_done(struct smb_ctx *ctx)
+{
+ if (ctx->ct_ssn.ioc_server)
+ nb_snbfree(ctx->ct_ssn.ioc_server);
+ if (ctx->ct_ssn.ioc_local)
+ nb_snbfree(ctx->ct_ssn.ioc_local);
+ if (ctx->ct_srvaddr)
+ free(ctx->ct_srvaddr);
+ if (ctx->ct_nb)
+ nb_ctx_done(ctx->ct_nb);
+}
+
+static int
+getsubstring(const char *p, u_char sep, char *dest, int maxlen, const char **next)
+{
+ int len;
+
+ maxlen--;
+ for (len = 0; len < maxlen && *p != sep; p++, len++, dest++) {
+ if (*p == 0)
+ return EINVAL;
+ *dest = *p;
+ }
+ *dest = 0;
+ *next = *p ? p + 1 : p;
+ return 0;
+}
+
+/*
+ * Here we expect something like "[proto:]//[user@]host[/share][/path]"
+ */
+int
+smb_ctx_parseunc(struct smb_ctx *ctx, const char *unc, int sharetype,
+ const char **next)
+{
+ const char *p = unc;
+ char *p1;
+ char tmp[1024];
+ int error ;
+
+ ctx->ct_parsedlevel = SMBL_NONE;
+ if (*p++ != '/' || *p++ != '/') {
+ smb_error("UNC should start with '//'", 0);
+ return EINVAL;
+ }
+ p1 = tmp;
+ error = getsubstring(p, '@', p1, sizeof(tmp), &p);
+ if (!error) {
+ if (ctx->ct_maxlevel < SMBL_VC) {
+ smb_error("no user name required", 0);
+ return EINVAL;
+ }
+ if (*p1 == 0) {
+ smb_error("empty user name", 0);
+ return EINVAL;
+ }
+ error = smb_ctx_setuser(ctx, tmp);
+ if (error)
+ return error;
+ ctx->ct_parsedlevel = SMBL_VC;
+ }
+ error = getsubstring(p, '/', p1, sizeof(tmp), &p);
+ if (error) {
+ error = getsubstring(p, '\0', p1, sizeof(tmp), &p);
+ if (error) {
+ smb_error("no server name found", 0);
+ return error;
+ }
+ }
+ if (*p1 == 0) {
+ smb_error("empty server name", 0);
+ return EINVAL;
+ }
+ error = smb_ctx_setserver(ctx, tmp);
+ if (error)
+ return error;
+ if (sharetype == SMB_ST_NONE) {
+ *next = p;
+ return 0;
+ }
+ if (*p != 0 && ctx->ct_maxlevel < SMBL_SHARE) {
+ smb_error("no share name required", 0);
+ return EINVAL;
+ }
+ error = getsubstring(p, '/', p1, sizeof(tmp), &p);
+ if (error) {
+ error = getsubstring(p, '\0', p1, sizeof(tmp), &p);
+ if (error) {
+ smb_error("unexpected end of line", 0);
+ return error;
+ }
+ }
+ if (*p1 == 0 && ctx->ct_minlevel >= SMBL_SHARE) {
+ smb_error("empty share name", 0);
+ return EINVAL;
+ }
+ *next = p;
+ if (*p1 == 0)
+ return 0;
+ error = smb_ctx_setshare(ctx, p1, sharetype);
+ return error;
+}
+
+int
+smb_ctx_setcharset(struct smb_ctx *ctx, const char *arg)
+{
+ char *cp, *servercs, *localcs;
+ int cslen = sizeof(ctx->ct_ssn.ioc_localcs);
+ int scslen, lcslen, error;
+
+ cp = strchr(arg, ':');
+ lcslen = cp ? (cp - arg) : 0;
+ if (lcslen == 0 || lcslen >= cslen) {
+ smb_error("invalid local charset specification (%s)", 0, arg);
+ return EINVAL;
+ }
+ scslen = (size_t)strlen(++cp);
+ if (scslen == 0 || scslen >= cslen) {
+ smb_error("invalid server charset specification (%s)", 0, arg);
+ return EINVAL;
+ }
+ localcs = memcpy(ctx->ct_ssn.ioc_localcs, arg, lcslen);
+ localcs[lcslen] = 0;
+ servercs = strcpy(ctx->ct_ssn.ioc_servercs, cp);
+ error = nls_setrecode(localcs, servercs);
+ if (error == 0)
+ return 0;
+ smb_error("can't initialize iconv support (%s:%s)",
+ error, localcs, servercs);
+ localcs[0] = 0;
+ servercs[0] = 0;
+ return error;
+}
+
+int
+smb_ctx_setserver(struct smb_ctx *ctx, const char *name)
+{
+ if (strlen(name) >= SMB_MAXSRVNAMELEN) {
+ smb_error("server name '%s' too long", 0, name);
+ return ENAMETOOLONG;
+ }
+ nls_str_upper(ctx->ct_ssn.ioc_srvname, name);
+ return 0;
+}
+
+int
+smb_ctx_setuser(struct smb_ctx *ctx, const char *name)
+{
+ if (strlen(name) >= SMB_MAXUSERNAMELEN) {
+ smb_error("user name '%s' too long", 0, name);
+ return ENAMETOOLONG;
+ }
+ nls_str_upper(ctx->ct_ssn.ioc_user, name);
+ return 0;
+}
+
+int
+smb_ctx_setworkgroup(struct smb_ctx *ctx, const char *name)
+{
+ if (strlen(name) >= SMB_MAXUSERNAMELEN) {
+ smb_error("workgroup name '%s' too long", 0, name);
+ return ENAMETOOLONG;
+ }
+ nls_str_upper(ctx->ct_ssn.ioc_workgroup, name);
+ return 0;
+}
+
+int
+smb_ctx_setpassword(struct smb_ctx *ctx, const char *passwd)
+{
+ if (passwd == NULL)
+ return EINVAL;
+ if (strlen(passwd) >= SMB_MAXPASSWORDLEN) {
+ smb_error("password too long", 0);
+ return ENAMETOOLONG;
+ }
+ if (strncmp(passwd, "$$1", 3) == 0)
+ smb_simpledecrypt(ctx->ct_ssn.ioc_password, passwd);
+ else
+ strcpy(ctx->ct_ssn.ioc_password, passwd);
+ strcpy(ctx->ct_sh.ioc_password, ctx->ct_ssn.ioc_password);
+ return 0;
+}
+
+int
+smb_ctx_setshare(struct smb_ctx *ctx, const char *share, int stype)
+{
+ if (strlen(share) >= SMB_MAXSHARENAMELEN) {
+ smb_error("share name '%s' too long", 0, share);
+ return ENAMETOOLONG;
+ }
+ nls_str_upper(ctx->ct_sh.ioc_share, share);
+ if (share[0] != 0)
+ ctx->ct_parsedlevel = SMBL_SHARE;
+ ctx->ct_sh.ioc_stype = stype;
+ return 0;
+}
+
+int
+smb_ctx_setsrvaddr(struct smb_ctx *ctx, const char *addr)
+{
+ if (addr == NULL || addr[0] == 0)
+ return EINVAL;
+ if (ctx->ct_srvaddr)
+ free(ctx->ct_srvaddr);
+ if ((ctx->ct_srvaddr = strdup(addr)) == NULL)
+ return ENOMEM;
+ return 0;
+}
+
+static int
+smb_parse_owner(char *pair, uid_t *uid, gid_t *gid)
+{
+ struct group *gr;
+ struct passwd *pw;
+ char *cp;
+
+ cp = strchr(pair, ':');
+ if (cp) {
+ *cp++ = '\0';
+ if (*cp) {
+ gr = getgrnam(cp);
+ if (gr) {
+ *gid = gr->gr_gid;
+ } else
+ smb_error("Invalid group name %s, ignored",
+ 0, cp);
+ }
+ }
+ if (*pair) {
+ pw = getpwnam(pair);
+ if (pw) {
+ *uid = pw->pw_uid;
+ } else
+ smb_error("Invalid user name %s, ignored", 0, pair);
+ }
+ endpwent();
+ return 0;
+}
+
+int
+smb_ctx_opt(struct smb_ctx *ctx, int opt, const char *arg)
+{
+ int error = 0;
+ char *p, *cp;
+
+ switch(opt) {
+ case 'U':
+ break;
+ case 'I':
+ error = smb_ctx_setsrvaddr(ctx, arg);
+ break;
+ case 'M':
+ ctx->ct_ssn.ioc_rights = strtol(arg, &cp, 8);
+ if (*cp == '/') {
+ ctx->ct_sh.ioc_rights = strtol(cp + 1, &cp, 8);
+ ctx->ct_flags |= SMBCF_SRIGHTS;
+ }
+ break;
+ case 'N':
+ ctx->ct_flags |= SMBCF_NOPWD;
+ break;
+ case 'O':
+ p = strdup(arg);
+ cp = strchr(p, '/');
+ if (cp) {
+ *cp++ = '\0';
+ error = smb_parse_owner(cp, &ctx->ct_sh.ioc_owner,
+ &ctx->ct_sh.ioc_group);
+ }
+ if (*p && error == 0) {
+ error = smb_parse_owner(cp, &ctx->ct_ssn.ioc_owner,
+ &ctx->ct_ssn.ioc_group);
+ }
+ free(p);
+ break;
+ case 'P':
+/* ctx->ct_ssn.ioc_opt |= SMBCOPT_PERMANENT;*/
+ break;
+ case 'R':
+ ctx->ct_ssn.ioc_retrycount = atoi(arg);
+ break;
+ case 'T':
+ ctx->ct_ssn.ioc_timeout = atoi(arg);
+ break;
+ case 'W':
+ error = smb_ctx_setworkgroup(ctx, arg);
+ break;
+ }
+ return error;
+}
+
+#if 0
+static void
+smb_hexdump(const u_char *buf, int len) {
+ int ofs = 0;
+
+ while (len--) {
+ if (ofs % 16 == 0)
+ printf("\n%02X: ", ofs);
+ printf("%02x ", *buf++);
+ ofs++;
+ }
+ printf("\n");
+}
+#endif
+
+
+static int
+smb_addiconvtbl(const char *to, const char *from, const u_char *tbl)
+{
+ int error;
+
+ error = kiconv_add_xlat_table(to, from, tbl);
+ if (error && error != EEXIST) {
+ smb_error("can not setup kernel iconv table (%s:%s)", error,
+ from, to);
+ return error;
+ }
+ return 0;
+}
+
+/*
+ * Verify context before connect operation(s),
+ * lookup specified server and try to fill all forgotten fields.
+ */
+int
+smb_ctx_resolve(struct smb_ctx *ctx)
+{
+ struct smbioc_ossn *ssn = &ctx->ct_ssn;
+ struct smbioc_oshare *sh = &ctx->ct_sh;
+ struct nb_name nn;
+ struct sockaddr *sap;
+ struct sockaddr_nb *salocal, *saserver;
+ char *cp;
+ u_char cstbl[256];
+ u_int i;
+ int error = 0;
+
+ ctx->ct_flags &= ~SMBCF_RESOLVED;
+ if (ssn->ioc_srvname[0] == 0) {
+ smb_error("no server name specified", 0);
+ return EINVAL;
+ }
+ if (ssn->ioc_user[0] == 0) {
+ smb_error("no user name specified for server %s",
+ 0, ssn->ioc_srvname);
+ return EINVAL;
+ }
+ if (ctx->ct_minlevel >= SMBL_SHARE && sh->ioc_share[0] == 0) {
+ smb_error("no share name specified for %s@%s",
+ 0, ssn->ioc_user, ssn->ioc_srvname);
+ return EINVAL;
+ }
+ error = nb_ctx_resolve(ctx->ct_nb);
+ if (error)
+ return error;
+ if (ssn->ioc_localcs[0] == 0)
+ strcpy(ssn->ioc_localcs, "default"); /* XXX: locale name ? */
+ error = smb_addiconvtbl("tolower", ssn->ioc_localcs, nls_lower);
+ if (error)
+ return error;
+ error = smb_addiconvtbl("toupper", ssn->ioc_localcs, nls_upper);
+ if (error)
+ return error;
+ if (ssn->ioc_servercs[0] != 0) {
+ for(i = 0; i < sizeof(cstbl); i++)
+ cstbl[i] = i;
+ nls_mem_toext(cstbl, cstbl, sizeof(cstbl));
+ error = smb_addiconvtbl(ssn->ioc_servercs, ssn->ioc_localcs, cstbl);
+ if (error)
+ return error;
+ for(i = 0; i < sizeof(cstbl); i++)
+ cstbl[i] = i;
+ nls_mem_toloc(cstbl, cstbl, sizeof(cstbl));
+ error = smb_addiconvtbl(ssn->ioc_localcs, ssn->ioc_servercs, cstbl);
+ if (error)
+ return error;
+ }
+ if (ctx->ct_srvaddr) {
+ error = nb_resolvehost_in(ctx->ct_srvaddr, &sap);
+ } else {
+ error = nbns_resolvename(ssn->ioc_srvname, ctx->ct_nb, &sap);
+ }
+ if (error) {
+ smb_error("can't get server address", error);
+ return error;
+ }
+ nn.nn_scope = ctx->ct_nb->nb_scope;
+ nn.nn_type = NBT_SERVER;
+ strcpy(nn.nn_name, ssn->ioc_srvname);
+ error = nb_sockaddr(sap, &nn, &saserver);
+ nb_snbfree(sap);
+ if (error) {
+ smb_error("can't allocate server address", error);
+ return error;
+ }
+ ssn->ioc_server = (struct sockaddr*)saserver;
+ if (ctx->ct_locname[0] == 0) {
+ error = nb_getlocalname(ctx->ct_locname);
+ if (error) {
+ smb_error("can't get local name", error);
+ return error;
+ }
+ nls_str_upper(ctx->ct_locname, ctx->ct_locname);
+ }
+ strcpy(nn.nn_name, ctx->ct_locname);
+ nn.nn_type = NBT_WKSTA;
+ nn.nn_scope = ctx->ct_nb->nb_scope;
+ error = nb_sockaddr(NULL, &nn, &salocal);
+ if (error) {
+ nb_snbfree((struct sockaddr*)saserver);
+ smb_error("can't allocate local address", error);
+ return error;
+ }
+ ssn->ioc_local = (struct sockaddr*)salocal;
+ ssn->ioc_lolen = salocal->snb_len;
+ ssn->ioc_svlen = saserver->snb_len;
+ if (ssn->ioc_password[0] == 0 && (ctx->ct_flags & SMBCF_NOPWD) == 0) {
+ cp = getpass("Password:");
+ error = smb_ctx_setpassword(ctx, cp);
+ if (error)
+ return error;
+ }
+ ctx->ct_flags |= SMBCF_RESOLVED;
+ return 0;
+}
+
+static int
+smb_ctx_gethandle(struct smb_ctx *ctx)
+{
+ int fd, i;
+ char buf[20];
+
+ /*
+ * First try to open as clone
+ */
+ fd = open("/dev/"NSMB_NAME, O_RDWR);
+ if (fd >= 0) {
+ ctx->ct_fd = fd;
+ return 0;
+ }
+ /*
+ * well, no clone capabilities available - we have to scan
+ * all devices in order to get free one
+ */
+ for (i = 0; i < 1024; i++) {
+ snprintf(buf, sizeof(buf), "/dev/%s%d", NSMB_NAME, i);
+ fd = open(buf, O_RDWR);
+ if (fd >= 0) {
+ ctx->ct_fd = fd;
+ return 0;
+ }
+ }
+ /*
+ * This is a compatibility with old /dev/net/nsmb device
+ */
+ for (i = 0; i < 1024; i++) {
+ snprintf(buf, sizeof(buf), "/dev/net/%s%d", NSMB_NAME, i);
+ fd = open(buf, O_RDWR);
+ if (fd >= 0) {
+ ctx->ct_fd = fd;
+ return 0;
+ }
+ if (errno == ENOENT)
+ return ENOENT;
+ }
+ return ENOENT;
+}
+
+int
+smb_ctx_lookup(struct smb_ctx *ctx, int level, int flags)
+{
+ struct smbioc_lookup rq;
+ int error;
+
+ if ((ctx->ct_flags & SMBCF_RESOLVED) == 0) {
+ smb_error("smb_ctx_lookup() data is not resolved", 0);
+ return EINVAL;
+ }
+ if (ctx->ct_fd != -1) {
+ close(ctx->ct_fd);
+ ctx->ct_fd = -1;
+ }
+ error = smb_ctx_gethandle(ctx);
+ if (error) {
+ smb_error("can't get handle to requester (no /dev/net/nsmb* device)", 0);
+ return EINVAL;
+ }
+ bzero(&rq, sizeof(rq));
+ bcopy(&ctx->ct_ssn, &rq.ioc_ssn, sizeof(struct smbioc_ossn));
+ bcopy(&ctx->ct_sh, &rq.ioc_sh, sizeof(struct smbioc_oshare));
+ rq.ioc_flags = flags;
+ rq.ioc_level = level;
+ if (ioctl(ctx->ct_fd, SMBIOC_LOOKUP, &rq) == -1) {
+ error = errno;
+ if (flags & SMBLK_CREATE)
+ smb_error("unable to open connection", error);
+ return error;
+ }
+ return 0;
+}
+
+int
+smb_ctx_login(struct smb_ctx *ctx)
+{
+ struct smbioc_ossn *ssn = &ctx->ct_ssn;
+ struct smbioc_oshare *sh = &ctx->ct_sh;
+ int error;
+
+ if ((ctx->ct_flags & SMBCF_RESOLVED) == 0) {
+ smb_error("smb_ctx_resolve() should be called first", 0);
+ return EINVAL;
+ }
+ if (ctx->ct_fd != -1) {
+ close(ctx->ct_fd);
+ ctx->ct_fd = -1;
+ }
+ error = smb_ctx_gethandle(ctx);
+ if (error) {
+ smb_error("can't get handle to requester", 0);
+ return EINVAL;
+ }
+ if (ioctl(ctx->ct_fd, SMBIOC_OPENSESSION, ssn) == -1) {
+ error = errno;
+ smb_error("can't open session to server %s", error, ssn->ioc_srvname);
+ return error;
+ }
+ if (sh->ioc_share[0] == 0)
+ return 0;
+ if (ioctl(ctx->ct_fd, SMBIOC_OPENSHARE, sh) == -1) {
+ error = errno;
+ smb_error("can't connect to share //%s/%s", error,
+ ssn->ioc_srvname, sh->ioc_share);
+ return error;
+ }
+ return 0;
+}
+
+int
+smb_ctx_setflags(struct smb_ctx *ctx, int level, int mask, int flags)
+{
+ struct smbioc_flags fl;
+
+ if (ctx->ct_fd == -1)
+ return EINVAL;
+ fl.ioc_level = level;
+ fl.ioc_mask = mask;
+ fl.ioc_flags = flags;
+ if (ioctl(ctx->ct_fd, SMBIOC_SETFLAGS, &fl) == -1)
+ return errno;
+ return 0;
+}
+
+/*
+ * level values:
+ * 0 - default
+ * 1 - server
+ * 2 - server:user
+ * 3 - server:user:share
+ */
+static int
+smb_ctx_readrcsection(struct smb_ctx *ctx, const char *sname, int level)
+{
+ char *p;
+ int error;
+
+ if (level > 0) {
+ rc_getstringptr(smb_rc, sname, "charsets", &p);
+ if (p) {
+ error = smb_ctx_setcharset(ctx, p);
+ if (error)
+ smb_error("charset specification in the section '%s' ignored", error, sname);
+ }
+ }
+ if (level <= 1) {
+ rc_getint(smb_rc, sname, "timeout", &ctx->ct_ssn.ioc_timeout);
+ rc_getint(smb_rc, sname, "retry_count", &ctx->ct_ssn.ioc_retrycount);
+ }
+ if (level == 1) {
+ rc_getstringptr(smb_rc, sname, "addr", &p);
+ if (p) {
+ error = smb_ctx_setsrvaddr(ctx, p);
+ if (error) {
+ smb_error("invalid address specified in the section %s", 0, sname);
+ return error;
+ }
+ }
+ }
+ if (level >= 2) {
+ rc_getstringptr(smb_rc, sname, "password", &p);
+ if (p)
+ smb_ctx_setpassword(ctx, p);
+ }
+ rc_getstringptr(smb_rc, sname, "workgroup", &p);
+ if (p)
+ smb_ctx_setworkgroup(ctx, p);
+ return 0;
+}
+
+/*
+ * read rc file as follows:
+ * 1. read [default] section
+ * 2. override with [server] section
+ * 3. override with [server:user:share] section
+ * Since abcence of rcfile is not fatal, silently ignore this fact.
+ * smb_rc file should be closed by caller.
+ */
+int
+smb_ctx_readrc(struct smb_ctx *ctx)
+{
+ char sname[SMB_MAXSRVNAMELEN + SMB_MAXUSERNAMELEN + SMB_MAXSHARENAMELEN + 4];
+/* char *p;*/
+
+ if (smb_open_rcfile() != 0)
+ return 0;
+
+ if (ctx->ct_ssn.ioc_user[0] == 0 || ctx->ct_ssn.ioc_srvname[0] == 0)
+ return 0;
+
+ smb_ctx_readrcsection(ctx, "default", 0);
+ nb_ctx_readrcsection(smb_rc, ctx->ct_nb, "default", 0);
+ smb_ctx_readrcsection(ctx, ctx->ct_ssn.ioc_srvname, 1);
+ nb_ctx_readrcsection(smb_rc, ctx->ct_nb, ctx->ct_ssn.ioc_srvname, 1);
+ /*
+ * SERVER:USER parameters
+ */
+ snprintf(sname, sizeof(sname), "%s:%s", ctx->ct_ssn.ioc_srvname,
+ ctx->ct_ssn.ioc_user);
+ smb_ctx_readrcsection(ctx, sname, 2);
+
+ if (ctx->ct_sh.ioc_share[0] != 0) {
+ /*
+ * SERVER:USER:SHARE parameters
+ */
+ snprintf(sname, sizeof(sname), "%s:%s:%s", ctx->ct_ssn.ioc_srvname,
+ ctx->ct_ssn.ioc_user, ctx->ct_sh.ioc_share);
+ smb_ctx_readrcsection(ctx, sname, 3);
+ }
+ return 0;
+}
+
diff --git a/contrib/smbfs/lib/smb/file.c b/contrib/smbfs/lib/smb/file.c
new file mode 100644
index 000000000000..9408576ad2fb
--- /dev/null
+++ b/contrib/smbfs/lib/smb/file.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: file.c,v 1.2 2001/04/16 04:33:01 bp Exp $
+ */
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/mount.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+
+#include <netsmb/smb_lib.h>
+#include <netsmb/smb_conn.h>
+#include <cflib.h>
+
+int
+smb_read(struct smb_ctx *ctx, smbfh fh, off_t offset, size_t count, char *dst)
+{
+ struct smbioc_rw rwrq;
+
+ rwrq.ioc_fh = fh;
+ rwrq.ioc_base = dst;
+ rwrq.ioc_cnt = count;
+ rwrq.ioc_offset = offset;
+ if (ioctl(ctx->ct_fd, SMBIOC_READ, &rwrq) == -1)
+ return -1;
+ return rwrq.ioc_cnt;
+}
+
+int
+smb_write(struct smb_ctx *ctx, smbfh fh, off_t offset, size_t count,
+ const char *src)
+{
+ struct smbioc_rw rwrq;
+
+ rwrq.ioc_fh = fh;
+ (const char*)rwrq.ioc_base = src;
+ rwrq.ioc_cnt = count;
+ rwrq.ioc_offset = offset;
+ if (ioctl(ctx->ct_fd, SMBIOC_WRITE, &rwrq) == -1)
+ return -1;
+ return rwrq.ioc_cnt;
+}
diff --git a/contrib/smbfs/lib/smb/kiconv.c b/contrib/smbfs/lib/smb/kiconv.c
new file mode 100644
index 000000000000..ce69c84bb72c
--- /dev/null
+++ b/contrib/smbfs/lib/smb/kiconv.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2000-2001, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: kiconv.c,v 1.2 2001/04/16 04:33:01 bp Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/iconv.h>
+#include <sys/sysctl.h>
+#include <ctype.h>
+#include <errno.h>
+
+int
+kiconv_add_xlat_table(const char *to, const char *from, const u_char *table)
+{
+ struct iconv_add_in din;
+ struct iconv_add_out dout;
+ int olen;
+
+ if (strlen(from) > ICONV_CSNMAXLEN || strlen(to) > ICONV_CSNMAXLEN)
+ return EINVAL;
+ din.ia_version = ICONV_ADD_VER;
+ strcpy(din.ia_converter, "xlat");
+ strcpy(din.ia_from, from);
+ strcpy(din.ia_to, to);
+ din.ia_data = table;
+ din.ia_datalen = 256;
+ olen = sizeof(dout);
+ if (sysctlbyname("kern.iconv.add", &dout, &olen, &din, sizeof(din)) == -1)
+ return errno;
+ return 0;
+}
+
diff --git a/contrib/smbfs/lib/smb/mbuf.c b/contrib/smbfs/lib/smb/mbuf.c
new file mode 100644
index 000000000000..fa31486c0401
--- /dev/null
+++ b/contrib/smbfs/lib/smb/mbuf.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: mbuf.c,v 1.6 2001/02/24 15:56:04 bp Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/mchain.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netsmb/smb_lib.h>
+
+#define MBERROR(format, args...) printf("%s(%d): "format, __FUNCTION__ , \
+ __LINE__ ,## args)
+
+static int
+m_get(size_t len, struct mbuf **mpp)
+{
+ struct mbuf *m;
+
+ len = M_ALIGN(len);
+ if (len < M_MINSIZE)
+ len = M_MINSIZE;
+ m = malloc(M_BASESIZE + len);
+ if (m == NULL)
+ return ENOMEM;
+ bzero(m, M_BASESIZE + len);
+ m->m_maxlen = len;
+ m->m_data = M_TOP(m);
+ *mpp = m;
+ return 0;
+}
+
+static void
+m_free(struct mbuf *m)
+{
+ free(m);
+}
+
+static void
+m_freem(struct mbuf *m0)
+{
+ struct mbuf *m;
+
+ while (m0) {
+ m = m0->m_next;
+ m_free(m0);
+ m0 = m;
+ }
+}
+
+static size_t
+m_totlen(struct mbuf *m0)
+{
+ struct mbuf *m = m0;
+ int len = 0;
+
+ while (m) {
+ len += m->m_len;
+ m = m->m_next;
+ }
+ return len;
+}
+
+int
+m_lineup(struct mbuf *m0, struct mbuf **mpp)
+{
+ struct mbuf *nm, *m;
+ char *dp;
+ size_t len;
+ int error;
+
+ if (m0->m_next == NULL) {
+ *mpp = m0;
+ return 0;
+ }
+ if ((error = m_get(m_totlen(m0), &nm)) != 0)
+ return error;
+ dp = mtod(nm, char *);
+ while (m0) {
+ len = m0->m_len;
+ bcopy(m0->m_data, dp, len);
+ dp += len;
+ m = m0->m_next;
+ m_free(m0);
+ m0 = m;
+ }
+ *mpp = nm;
+ return 0;
+}
+
+int
+mb_init(struct mbdata *mbp, size_t size)
+{
+ struct mbuf *m;
+ int error;
+
+ if ((error = m_get(size, &m)) != 0)
+ return error;
+ return mb_initm(mbp, m);
+}
+
+int
+mb_initm(struct mbdata *mbp, struct mbuf *m)
+{
+ bzero(mbp, sizeof(*mbp));
+ mbp->mb_top = mbp->mb_cur = m;
+ mbp->mb_pos = mtod(m, char *);
+ return 0;
+}
+
+int
+mb_done(struct mbdata *mbp)
+{
+ if (mbp->mb_top) {
+ m_freem(mbp->mb_top);
+ mbp->mb_top = NULL;
+ }
+ return 0;
+}
+
+/*
+int
+mb_fixhdr(struct mbdata *mbp)
+{
+ struct mbuf *m = mbp->mb_top;
+ int len = 0;
+
+ while (m) {
+ len += m->m_len;
+ m = m->m_next;
+ }
+ mbp->mb_top->m_pkthdr.len = len;
+ return len;
+}
+*/
+int
+m_getm(struct mbuf *top, size_t len, struct mbuf **mpp)
+{
+ struct mbuf *m, *mp;
+ int error;
+
+ for (mp = top; ; mp = mp->m_next) {
+ len -= M_TRAILINGSPACE(mp);
+ if (mp->m_next == NULL)
+ break;
+
+ }
+ if (len > 0) {
+ if ((error = m_get(len, &m)) != 0)
+ return error;
+ mp->m_next = m;
+ }
+ *mpp = top;
+ return 0;
+}
+
+/*
+ * Routines to put data in a buffer
+ */
+#define MB_PUT(t) int error; t *p; \
+ if ((error = mb_fit(mbp, sizeof(t), (char**)&p)) != 0) \
+ return error
+
+/*
+ * Check if object of size 'size' fit to the current position and
+ * allocate new mbuf if not. Advance pointers and increase length of mbuf(s).
+ * Return pointer to the object placeholder or NULL if any error occured.
+ */
+int
+mb_fit(struct mbdata *mbp, size_t size, char **pp)
+{
+ struct mbuf *m, *mn;
+ int error;
+
+ m = mbp->mb_cur;
+ if (M_TRAILINGSPACE(m) < (int)size) {
+ if ((error = m_get(size, &mn)) != 0)
+ return error;
+ mbp->mb_pos = mtod(mn, char *);
+ mbp->mb_cur = m->m_next = mn;
+ m = mn;
+ }
+ m->m_len += size;
+ *pp = mbp->mb_pos;
+ mbp->mb_pos += size;
+ mbp->mb_count += size;
+ return 0;
+}
+
+int
+mb_put_uint8(struct mbdata *mbp, u_int8_t x)
+{
+ MB_PUT(u_int8_t);
+ *p = x;
+ return 0;
+}
+
+int
+mb_put_uint16be(struct mbdata *mbp, u_int16_t x)
+{
+ MB_PUT(u_int16_t);
+ setwbe(p, 0, x);
+ return 0;
+}
+
+int
+mb_put_uint16le(struct mbdata *mbp, u_int16_t x)
+{
+ MB_PUT(u_int16_t);
+ setwle(p, 0, x);
+ return 0;
+}
+
+int
+mb_put_uint32be(struct mbdata *mbp, u_int32_t x)
+{
+ MB_PUT(u_int32_t);
+ setdbe(p, 0, x);
+ return 0;
+}
+
+int
+mb_put_uint32le(struct mbdata *mbp, u_int32_t x)
+{
+ MB_PUT(u_int32_t);
+ setdle(p, 0, x);
+ return 0;
+}
+
+int
+mb_put_int64be(struct mbdata *mbp, int64_t x)
+{
+ MB_PUT(int64_t);
+ *p = htobeq(x);
+ return 0;
+}
+
+int
+mb_put_int64le(struct mbdata *mbp, int64_t x)
+{
+ MB_PUT(int64_t);
+ *p = htoleq(x);
+ return 0;
+}
+
+int
+mb_put_mem(struct mbdata *mbp, const char *source, size_t size)
+{
+ struct mbuf *m;
+ char * dst;
+ size_t cplen;
+ int error;
+
+ if (size == 0)
+ return 0;
+ m = mbp->mb_cur;
+ if ((error = m_getm(m, size, &m)) != 0)
+ return error;
+ while (size > 0) {
+ cplen = M_TRAILINGSPACE(m);
+ if (cplen == 0) {
+ m = m->m_next;
+ continue;
+ }
+ if (cplen > size)
+ cplen = size;
+ dst = mtod(m, char *) + m->m_len;
+ if (source) {
+ bcopy(source, dst, cplen);
+ source += cplen;
+ } else
+ bzero(dst, cplen);
+ size -= cplen;
+ m->m_len += cplen;
+ mbp->mb_count += cplen;
+ }
+ mbp->mb_pos = mtod(m, char *) + m->m_len;
+ mbp->mb_cur = m;
+ return 0;
+}
+
+int
+mb_put_mbuf(struct mbdata *mbp, struct mbuf *m)
+{
+ mbp->mb_cur->m_next = m;
+ while (m) {
+ mbp->mb_count += m->m_len;
+ if (m->m_next == NULL)
+ break;
+ m = m->m_next;
+ }
+ mbp->mb_pos = mtod(m, char *) + m->m_len;
+ mbp->mb_cur = m;
+ return 0;
+}
+
+int
+mb_put_pstring(struct mbdata *mbp, const char *s)
+{
+ int error, len = strlen(s);
+
+ if (len > 255) {
+ len = 255;
+ }
+ if ((error = mb_put_uint8(mbp, len)) != 0)
+ return error;
+ return mb_put_mem(mbp, s, len);
+}
+
+/*
+ * Routines for fetching data from an mbuf chain
+ */
+#define mb_left(m,p) (mtod(m, char *) + (m)->m_len - (p))
+
+int
+mb_get_uint8(struct mbdata *mbp, u_int8_t *x)
+{
+ return mb_get_mem(mbp, x, 1);
+}
+
+int
+mb_get_uint16(struct mbdata *mbp, u_int16_t *x)
+{
+ return mb_get_mem(mbp, (char *)x, 2);
+}
+
+int
+mb_get_uint16le(struct mbdata *mbp, u_int16_t *x)
+{
+ u_int16_t v;
+ int error = mb_get_uint16(mbp, &v);
+
+ *x = letohs(v);
+ return error;
+}
+
+int
+mb_get_uint16be(struct mbdata *mbp, u_int16_t *x) {
+ u_int16_t v;
+ int error = mb_get_uint16(mbp, &v);
+
+ *x = betohs(v);
+ return error;
+}
+
+int
+mb_get_uint32(struct mbdata *mbp, u_int32_t *x)
+{
+ return mb_get_mem(mbp, (char *)x, 4);
+}
+
+int
+mb_get_uint32be(struct mbdata *mbp, u_int32_t *x)
+{
+ u_int32_t v;
+ int error;
+
+ error = mb_get_uint32(mbp, &v);
+ *x = betohl(v);
+ return error;
+}
+
+int
+mb_get_uint32le(struct mbdata *mbp, u_int32_t *x)
+{
+ u_int32_t v;
+ int error;
+
+ error = mb_get_uint32(mbp, &v);
+ *x = letohl(v);
+ return error;
+}
+
+int
+mb_get_int64(struct mbdata *mbp, int64_t *x)
+{
+ return mb_get_mem(mbp, (char *)x, 8);
+}
+
+int
+mb_get_int64be(struct mbdata *mbp, int64_t *x)
+{
+ int64_t v;
+ int error;
+
+ error = mb_get_int64(mbp, &v);
+ *x = betohq(v);
+ return error;
+}
+
+int
+mb_get_int64le(struct mbdata *mbp, int64_t *x)
+{
+ int64_t v;
+ int error;
+
+ error = mb_get_int64(mbp, &v);
+ *x = letohq(v);
+ return error;
+}
+
+int
+mb_get_mem(struct mbdata *mbp, char * target, size_t size)
+{
+ struct mbuf *m = mbp->mb_cur;
+ u_int count;
+
+ while (size > 0) {
+ if (m == NULL) {
+ MBERROR("incomplete copy\n");
+ return EBADRPC;
+ }
+ count = mb_left(m, mbp->mb_pos);
+ if (count == 0) {
+ mbp->mb_cur = m = m->m_next;
+ if (m)
+ mbp->mb_pos = mtod(m, char *);
+ continue;
+ }
+ if (count > size)
+ count = size;
+ size -= count;
+ if (target) {
+ if (count == 1) {
+ *target++ = *mbp->mb_pos;
+ } else {
+ bcopy(mbp->mb_pos, target, count);
+ target += count;
+ }
+ }
+ mbp->mb_pos += count;
+ }
+ return 0;
+}
diff --git a/contrib/smbfs/lib/smb/nb.c b/contrib/smbfs/lib/smb/nb.c
new file mode 100644
index 000000000000..2be9ab02a4f8
--- /dev/null
+++ b/contrib/smbfs/lib/smb/nb.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2000, 2001 Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: nb.c,v 1.4 2001/04/16 04:33:01 bp Exp $
+ */
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <cflib.h>
+
+#include <netsmb/netbios.h>
+#include <netsmb/smb_lib.h>
+#include <netsmb/nb_lib.h>
+
+int
+nb_ctx_create(struct nb_ctx **ctxpp)
+{
+ struct nb_ctx *ctx;
+
+ ctx = malloc(sizeof(struct nb_ctx));
+ if (ctx == NULL)
+ return ENOMEM;
+ bzero(ctx, sizeof(struct nb_ctx));
+ *ctxpp = ctx;
+ return 0;
+}
+
+void
+nb_ctx_done(struct nb_ctx *ctx)
+{
+ if (ctx == NULL)
+ return;
+ if (ctx->nb_scope)
+ free(ctx->nb_scope);
+}
+
+int
+nb_ctx_setns(struct nb_ctx *ctx, const char *addr)
+{
+ if (addr == NULL || addr[0] == 0)
+ return EINVAL;
+ if (ctx->nb_nsname)
+ free(ctx->nb_nsname);
+ if ((ctx->nb_nsname = strdup(addr)) == NULL)
+ return ENOMEM;
+ return 0;
+}
+
+int
+nb_ctx_setscope(struct nb_ctx *ctx, const char *scope)
+{
+ size_t slen = strlen(scope);
+
+ if (slen >= 128) {
+ smb_error("scope '%s' is too long", 0, scope);
+ return ENAMETOOLONG;
+ }
+ if (ctx->nb_scope)
+ free(ctx->nb_scope);
+ ctx->nb_scope = malloc(slen + 1);
+ if (ctx->nb_scope == NULL)
+ return ENOMEM;
+ nls_str_upper(ctx->nb_scope, scope);
+ return 0;
+}
+
+int
+nb_ctx_resolve(struct nb_ctx *ctx)
+{
+ struct sockaddr *sap;
+ int error;
+
+ ctx->nb_flags &= ~NBCF_RESOLVED;
+
+ if (ctx->nb_nsname == NULL) {
+ ctx->nb_ns.sin_addr.s_addr = htonl(INADDR_BROADCAST);
+ } else {
+ error = nb_resolvehost_in(ctx->nb_nsname, &sap);
+ if (error) {
+ smb_error("can't resolve %s", error, ctx->nb_nsname);
+ return error;
+ }
+ if (sap->sa_family != AF_INET) {
+ smb_error("unsupported address family %d", 0, sap->sa_family);
+ return EINVAL;
+ }
+ bcopy(sap, &ctx->nb_ns, sizeof(ctx->nb_ns));
+ free(sap);
+ }
+ ctx->nb_ns.sin_port = htons(137);
+ ctx->nb_ns.sin_family = AF_INET;
+ ctx->nb_ns.sin_len = sizeof(ctx->nb_ns);
+ ctx->nb_flags |= NBCF_RESOLVED;
+ return 0;
+}
+
+/*
+ * used level values:
+ * 0 - default
+ * 1 - server
+ */
+int
+nb_ctx_readrcsection(struct rcfile *rcfile, struct nb_ctx *ctx,
+ const char *sname, int level)
+{
+ char *p;
+ int error;
+
+ if (level > 1)
+ return EINVAL;
+ rc_getint(rcfile, sname, "nbtimeout", &ctx->nb_timo);
+ rc_getstringptr(rcfile, sname, "nbns", &p);
+ if (p) {
+ error = nb_ctx_setns(ctx, p);
+ if (error) {
+ smb_error("invalid address specified in the section %s", 0, sname);
+ return error;
+ }
+ }
+ rc_getstringptr(rcfile, sname, "nbscope", &p);
+ if (p)
+ nb_ctx_setscope(ctx, p);
+ return 0;
+}
+
+static const char *nb_err_rcode[] = {
+ "bad request/response format",
+ "NBNS server failure",
+ "no such name",
+ "unsupported request",
+ "request rejected",
+ "name already registered"
+};
+
+static const char *nb_err[] = {
+ "host not found",
+ "too many redirects",
+ "invalid response",
+ "NETBIOS name too long",
+ "no interface to broadcast on and no NBNS server specified"
+};
+
+const char *
+nb_strerror(int error)
+{
+ if (error == 0)
+ return NULL;
+ if (error <= NBERR_ACTIVE)
+ return nb_err_rcode[error - 1];
+ else if (error >= NBERR_HOSTNOTFOUND && error < NBERR_MAX)
+ return nb_err[error - NBERR_HOSTNOTFOUND];
+ else
+ return NULL;
+}
+
diff --git a/contrib/smbfs/lib/smb/nb_name.c b/contrib/smbfs/lib/smb/nb_name.c
new file mode 100644
index 000000000000..24b1a80cf9df
--- /dev/null
+++ b/contrib/smbfs/lib/smb/nb_name.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: nb_name.c,v 1.1 2000/07/16 01:52:07 bp Exp $
+ */
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <netsmb/netbios.h>
+#include <netsmb/smb_lib.h>
+#include <netsmb/nb_lib.h>
+
+int
+nb_snballoc(int namelen, struct sockaddr_nb **dst)
+{
+ struct sockaddr_nb *snb;
+ int slen;
+
+ slen = namelen + sizeof(*snb) - sizeof(snb->snb_name);
+ snb = malloc(slen);
+ if (snb == NULL)
+ return ENOMEM;
+ bzero(snb, slen);
+ snb->snb_family = AF_NETBIOS;
+ snb->snb_len = slen;
+ *dst = snb;
+ return 0;
+}
+
+void
+nb_snbfree(struct sockaddr *snb)
+{
+ free(snb);
+}
+
+/*
+ * Create a full NETBIOS address
+ */
+int
+nb_sockaddr(struct sockaddr *peer, struct nb_name *np,
+ struct sockaddr_nb **dst)
+
+{
+ struct sockaddr_nb *snb;
+ int nmlen, error;
+
+ if (peer && (peer->sa_family != AF_INET && peer->sa_family != AF_IPX))
+ return EPROTONOSUPPORT;
+ nmlen = nb_name_len(np);
+ if (nmlen < NB_ENCNAMELEN)
+ return EINVAL;
+ error = nb_snballoc(nmlen, &snb);
+ if (error)
+ return error;
+ if (nmlen != nb_name_encode(np, snb->snb_name))
+ printf("a bug somewhere in the nb_name* code\n");
+ if (peer)
+ memcpy(&snb->snb_tran, peer, peer->sa_len);
+ *dst = snb;
+ return 0;
+}
+
+int
+nb_name_len(struct nb_name *np)
+{
+ u_char *name;
+ int len, sclen;
+
+ len = 1 + NB_ENCNAMELEN;
+ if (np->nn_scope == NULL)
+ return len + 1;
+ sclen = 0;
+ for (name = np->nn_scope; *name; name++) {
+ if (*name == '.') {
+ sclen = 0;
+ } else {
+ if (sclen < NB_MAXLABLEN) {
+ sclen++;
+ len++;
+ }
+ }
+ }
+ return len + 1;
+}
+
+int
+nb_encname_len(const char *str)
+{
+ const u_char *cp = (const u_char *)str;
+ int len, blen;
+
+ if ((cp[0] & 0xc0) == 0xc0)
+ return -1; /* first two bytes are offset to name */
+
+ len = 1;
+ for (;;) {
+ blen = *cp;
+ if (blen++ == 0)
+ break;
+ len += blen;
+ cp += blen;
+ }
+ return len;
+}
+
+#define NBENCODE(c) ((u_short)(((u_char)(c) >> 4) | \
+ (((u_char)(c) & 0xf) << 8)) + 0x4141)
+
+static void
+memsetw(char *dst, int n, u_short word)
+{
+ while (n--) {
+ *(u_short*)dst = word;
+ dst += 2;
+ }
+}
+
+int
+nb_name_encode(struct nb_name *np, u_char *dst)
+{
+ u_char *name, *plen;
+ u_char *cp = dst;
+ int i, lblen;
+
+ *cp++ = NB_ENCNAMELEN;
+ name = np->nn_name;
+ if (name[0] == '*' && name[1] == 0) {
+ *(u_short*)cp = NBENCODE('*');
+ memsetw(cp + 2, NB_NAMELEN - 1, NBENCODE(' '));
+ cp += NB_ENCNAMELEN;
+ } else {
+ for (i = 0; *name && i < NB_NAMELEN; i++, cp += 2, name++)
+ *(u_short*)cp = NBENCODE(toupper(*name));
+ i = NB_NAMELEN - i - 1;
+ if (i > 0) {
+ memsetw(cp, i, NBENCODE(' '));
+ cp += i * 2;
+ }
+ *(u_short*)cp = NBENCODE(np->nn_type);
+ cp += 2;
+ }
+ *cp = 0;
+ if (np->nn_scope == NULL)
+ return nb_encname_len(dst);
+ plen = cp++;
+ lblen = 0;
+ for (name = np->nn_scope; ; name++) {
+ if (*name == '.' || *name == 0) {
+ *plen = lblen;
+ plen = cp++;
+ *plen = 0;
+ if (*name == 0)
+ break;
+ } else {
+ if (lblen < NB_MAXLABLEN) {
+ *cp++ = *name;
+ lblen++;
+ }
+ }
+ }
+ return nb_encname_len(dst);
+}
+
diff --git a/contrib/smbfs/lib/smb/nb_net.c b/contrib/smbfs/lib/smb/nb_net.c
new file mode 100644
index 000000000000..c0a206069e96
--- /dev/null
+++ b/contrib/smbfs/lib/smb/nb_net.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: nb_net.c,v 1.4 2001/02/16 02:46:12 bp Exp $
+ */
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <netsmb/netbios.h>
+#include <netsmb/smb_lib.h>
+#include <netsmb/nb_lib.h>
+
+int
+nb_getlocalname(char *name)
+{
+ char buf[1024], *cp;
+
+ if (gethostname(buf, sizeof(buf)) != 0)
+ return errno;
+ cp = strchr(buf, '.');
+ if (cp)
+ *cp = 0;
+ strcpy(name, buf);
+ return 0;
+}
+
+int
+nb_resolvehost_in(const char *name, struct sockaddr **dest)
+{
+ struct hostent* h;
+ struct sockaddr_in *sinp;
+ int len;
+
+ h = gethostbyname(name);
+ if (!h) {
+ warnx("can't get server address `%s': ", name);
+ herror(NULL);
+ return ENETDOWN;
+ }
+ if (h->h_addrtype != AF_INET) {
+ warnx("address for `%s' is not in the AF_INET family", name);
+ return EAFNOSUPPORT;
+ }
+ if (h->h_length != 4) {
+ warnx("address for `%s' has invalid length", name);
+ return EAFNOSUPPORT;
+ }
+ len = sizeof(struct sockaddr_in);
+ sinp = malloc(len);
+ if (sinp == NULL)
+ return ENOMEM;
+ bzero(sinp, len);
+ sinp->sin_len = len;
+ sinp->sin_family = h->h_addrtype;
+ memcpy(&sinp->sin_addr.s_addr, h->h_addr, 4);
+ sinp->sin_port = htons(SMB_TCP_PORT);
+ *dest = (struct sockaddr*)sinp;
+ return 0;
+}
+
+int
+nb_enum_if(struct nb_ifdesc **iflist, int maxif)
+{
+ struct ifconf ifc;
+ struct ifreq *ifrqp;
+ struct nb_ifdesc *ifd;
+ struct in_addr iaddr, imask;
+ char *ifrdata, *iname;
+ int s, rdlen, ifcnt, error, iflags, i;
+
+ *iflist = NULL;
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s == -1)
+ return errno;
+
+ rdlen = maxif * sizeof(struct ifreq);
+ ifrdata = malloc(rdlen);
+ if (ifrdata == NULL) {
+ error = ENOMEM;
+ goto bad;
+ }
+ ifc.ifc_len = rdlen;
+ ifc.ifc_buf = ifrdata;
+ if (ioctl(s, SIOCGIFCONF, &ifc) != 0) {
+ error = errno;
+ goto bad;
+ }
+ ifrqp = ifc.ifc_req;
+ ifcnt = ifc.ifc_len / sizeof(struct ifreq);
+ error = 0;
+ for (i = 0; i < ifcnt; i++, ifrqp++) {
+ if (ioctl(s, SIOCGIFFLAGS, ifrqp) != 0)
+ continue;
+ iflags = ifrqp->ifr_flags;
+ if ((iflags & IFF_UP) == 0 || (iflags & IFF_BROADCAST) == 0)
+ continue;
+
+ if (ioctl(s, SIOCGIFADDR, ifrqp) != 0 ||
+ ifrqp->ifr_addr.sa_family != AF_INET)
+ continue;
+ iname = ifrqp->ifr_name;
+ if (strlen(iname) >= sizeof(ifd->id_name))
+ continue;
+ iaddr = (*(struct sockaddr_in *)&ifrqp->ifr_addr).sin_addr;
+
+ if (ioctl(s, SIOCGIFNETMASK, ifrqp) != 0)
+ continue;
+ imask = ((struct sockaddr_in *)&ifrqp->ifr_addr)->sin_addr;
+
+ ifd = malloc(sizeof(struct nb_ifdesc));
+ if (ifd == NULL)
+ return ENOMEM;
+ bzero(ifd, sizeof(struct nb_ifdesc));
+ strcpy(ifd->id_name, iname);
+ ifd->id_flags = iflags;
+ ifd->id_addr = iaddr;
+ ifd->id_mask = imask;
+ ifd->id_next = *iflist;
+ *iflist = ifd;
+ }
+bad:
+ free(ifrdata);
+ close(s);
+ return error;
+}
+
+/*ARGSUSED*/
+/*int
+nbns_resolvename(const char *name, struct sockaddr **dest)
+{
+ printf("NetBIOS name resolver is not included in this distribution.\n");
+ printf("Please use '-I' option to specify an IP address of server.\n");
+ return EHOSTUNREACH;
+}*/
+/*
+int
+nb_hostlookup(struct nb_name *np, const char *server, const char *hint,
+ struct sockaddr_nb **dst)
+{
+ struct sockaddr_nb *snb;
+ int error;
+
+ error = nb_sockaddr(NULL, np, &snb);
+ if (error)
+ return error;
+ do {
+ if (hint) {
+ error = nb_resolvehost_in(host, snb);
+ if (error)
+ break;
+ } else {
+ error = nb_resolvename(server);
+ }
+ } while(0);
+ if (!error) {
+ *dst = snb;
+ } else
+ nb_snbfree(snb);
+ return error;
+}
+*/ \ No newline at end of file
diff --git a/contrib/smbfs/lib/smb/nbns_rq.c b/contrib/smbfs/lib/smb/nbns_rq.c
new file mode 100644
index 000000000000..5ea22f1d34ea
--- /dev/null
+++ b/contrib/smbfs/lib/smb/nbns_rq.c
@@ -0,0 +1,380 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: nbns_rq.c,v 1.5 2001/02/17 03:07:24 bp Exp $
+ */
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <err.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#define NB_NEEDRESOLVER
+#include <netsmb/netbios.h>
+#include <netsmb/smb_lib.h>
+#include <netsmb/nb_lib.h>
+
+
+static int nbns_rq_create(int opcode, struct nb_ctx *ctx, struct nbns_rq **rqpp);
+static void nbns_rq_done(struct nbns_rq *rqp);
+static int nbns_rq_getrr(struct nbns_rq *rqp, struct nbns_rr *rrp);
+static int nbns_rq_prepare(struct nbns_rq *rqp);
+static int nbns_rq(struct nbns_rq *rqp);
+
+static struct nb_ifdesc *nb_iflist;
+
+int
+nbns_resolvename(const char *name, struct nb_ctx *ctx, struct sockaddr **adpp)
+{
+ struct nbns_rq *rqp;
+ struct nb_name nn;
+ struct nbns_rr rr;
+ struct sockaddr_in *dest;
+ int error, rdrcount, len;
+
+ if (strlen(name) > NB_NAMELEN)
+ return NBERROR(NBERR_NAMETOOLONG);
+ error = nbns_rq_create(NBNS_OPCODE_QUERY, ctx, &rqp);
+ if (error)
+ return error;
+ bzero(&nn, sizeof(nn));
+ strcpy(nn.nn_name, name);
+ nn.nn_scope = ctx->nb_scope;
+ nn.nn_type = NBT_SERVER;
+ rqp->nr_nmflags = NBNS_NMFLAG_RD;
+ rqp->nr_qdname = &nn;
+ rqp->nr_qdtype = NBNS_QUESTION_TYPE_NB;
+ rqp->nr_qdclass = NBNS_QUESTION_CLASS_IN;
+ rqp->nr_qdcount = 1;
+ dest = &rqp->nr_dest;
+ *dest = ctx->nb_ns;
+ dest->sin_family = AF_INET;
+ dest->sin_len = sizeof(*dest);
+ if (dest->sin_port == 0)
+ dest->sin_port = htons(137);
+ if (dest->sin_addr.s_addr == INADDR_ANY)
+ dest->sin_addr.s_addr = htonl(INADDR_BROADCAST);
+ if (dest->sin_addr.s_addr == INADDR_BROADCAST)
+ rqp->nr_flags |= NBRQF_BROADCAST;
+ error = nbns_rq_prepare(rqp);
+ if (error) {
+ nbns_rq_done(rqp);
+ return error;
+ }
+ rdrcount = NBNS_MAXREDIRECTS;
+ for (;;) {
+ error = nbns_rq(rqp);
+ if (error)
+ break;
+ if ((rqp->nr_rpnmflags & NBNS_NMFLAG_AA) == 0) {
+ if (rdrcount-- == 0) {
+ error = NBERROR(NBERR_TOOMANYREDIRECTS);
+ break;
+ }
+ error = nbns_rq_getrr(rqp, &rr);
+ if (error)
+ break;
+ error = nbns_rq_getrr(rqp, &rr);
+ if (error)
+ break;
+ bcopy(rr.rr_data, &dest->sin_addr, 4);
+ rqp->nr_flags &= ~NBRQF_BROADCAST;
+ continue;
+ }
+ if (rqp->nr_rpancount == 0) {
+ error = NBERROR(NBERR_HOSTNOTFOUND);
+ break;
+ }
+ error = nbns_rq_getrr(rqp, &rr);
+ if (error)
+ break;
+ len = sizeof(struct sockaddr_in);
+ dest = malloc(len);
+ if (dest == NULL)
+ return ENOMEM;
+ bzero(dest, len);
+ dest->sin_len = len;
+ dest->sin_family = AF_INET;
+ bcopy(rr.rr_data + 2, &dest->sin_addr.s_addr, 4);
+ dest->sin_port = htons(SMB_TCP_PORT);
+ *adpp = (struct sockaddr*)dest;
+ ctx->nb_lastns = rqp->nr_sender;
+ break;
+ }
+ nbns_rq_done(rqp);
+ return error;
+}
+
+int
+nbns_rq_create(int opcode, struct nb_ctx *ctx, struct nbns_rq **rqpp)
+{
+ struct nbns_rq *rqp;
+ static u_int16_t trnid;
+ int error;
+
+ rqp = malloc(sizeof(*rqp));
+ if (rqp == NULL)
+ return ENOMEM;
+ bzero(rqp, sizeof(*rqp));
+ error = mb_init(&rqp->nr_rq, NBDG_MAXSIZE);
+ if (error) {
+ free(rqp);
+ return error;
+ }
+ rqp->nr_opcode = opcode;
+ rqp->nr_nbd = ctx;
+ rqp->nr_trnid = trnid++;
+ *rqpp = rqp;
+ return 0;
+}
+
+void
+nbns_rq_done(struct nbns_rq *rqp)
+{
+ if (rqp == NULL)
+ return;
+ if (rqp->nr_fd >= 0)
+ close(rqp->nr_fd);
+ mb_done(&rqp->nr_rq);
+ mb_done(&rqp->nr_rp);
+ free(rqp);
+}
+
+/*
+ * Extract resource record from the packet. Assume that there is only
+ * one mbuf.
+ */
+int
+nbns_rq_getrr(struct nbns_rq *rqp, struct nbns_rr *rrp)
+{
+ struct mbdata *mbp = &rqp->nr_rp;
+ u_char *cp;
+ int error, len;
+
+ bzero(rrp, sizeof(*rrp));
+ cp = mbp->mb_pos;
+ len = nb_encname_len(cp);
+ if (len < 1)
+ return NBERROR(NBERR_INVALIDRESPONSE);
+ rrp->rr_name = cp;
+ error = mb_get_mem(mbp, NULL, len);
+ if (error)
+ return error;
+ mb_get_uint16be(mbp, &rrp->rr_type);
+ mb_get_uint16be(mbp, &rrp->rr_class);
+ mb_get_uint32be(mbp, &rrp->rr_ttl);
+ mb_get_uint16be(mbp, &rrp->rr_rdlength);
+ rrp->rr_data = mbp->mb_pos;
+ error = mb_get_mem(mbp, NULL, rrp->rr_rdlength);
+ return error;
+}
+
+int
+nbns_rq_prepare(struct nbns_rq *rqp)
+{
+ struct nb_ctx *ctx = rqp->nr_nbd;
+ struct mbdata *mbp = &rqp->nr_rq;
+ u_int8_t nmflags;
+ u_char *cp;
+ int len, error;
+
+ error = mb_init(&rqp->nr_rp, NBDG_MAXSIZE);
+ if (error)
+ return error;
+ if (rqp->nr_dest.sin_addr.s_addr == INADDR_BROADCAST) {
+ rqp->nr_nmflags |= NBNS_NMFLAG_BCAST;
+ if (nb_iflist == NULL) {
+ error = nb_enum_if(&nb_iflist, 100);
+ if (error)
+ return error;
+ }
+ } else
+ rqp->nr_nmflags &= ~NBNS_NMFLAG_BCAST;
+ mb_put_uint16be(mbp, rqp->nr_trnid);
+ nmflags = ((rqp->nr_opcode & 0x1F) << 3) | ((rqp->nr_nmflags & 0x70) >> 4);
+ mb_put_uint8(mbp, nmflags);
+ mb_put_uint8(mbp, (rqp->nr_nmflags & 0x0f) << 4 /* rcode */);
+ mb_put_uint16be(mbp, rqp->nr_qdcount);
+ mb_put_uint16be(mbp, rqp->nr_ancount);
+ mb_put_uint16be(mbp, rqp->nr_nscount);
+ mb_put_uint16be(mbp, rqp->nr_arcount);
+ if (rqp->nr_qdcount) {
+ if (rqp->nr_qdcount > 1)
+ return EINVAL;
+ len = nb_name_len(rqp->nr_qdname);
+ error = mb_fit(mbp, len, (char**)&cp);
+ if (error)
+ return error;
+ nb_name_encode(rqp->nr_qdname, cp);
+ mb_put_uint16be(mbp, rqp->nr_qdtype);
+ mb_put_uint16be(mbp, rqp->nr_qdclass);
+ }
+ m_lineup(mbp->mb_top, &mbp->mb_top);
+ if (ctx->nb_timo == 0)
+ ctx->nb_timo = 1; /* by default 1 second */
+ return 0;
+}
+
+static int
+nbns_rq_recv(struct nbns_rq *rqp)
+{
+ struct mbdata *mbp = &rqp->nr_rp;
+ void *rpdata = mtod(mbp->mb_top, void *);
+ fd_set rd, wr, ex;
+ struct timeval tv;
+ struct sockaddr_in sender;
+ int s = rqp->nr_fd;
+ int n, len;
+
+ FD_ZERO(&rd);
+ FD_ZERO(&wr);
+ FD_ZERO(&ex);
+ FD_SET(s, &rd);
+
+ tv.tv_sec = rqp->nr_nbd->nb_timo;
+ tv.tv_usec = 0;
+
+ n = select(s + 1, &rd, &wr, &ex, &tv);
+ if (n == -1)
+ return -1;
+ if (n == 0)
+ return ETIMEDOUT;
+ if (FD_ISSET(s, &rd) == 0)
+ return ETIMEDOUT;
+ len = sizeof(sender);
+ n = recvfrom(s, rpdata, mbp->mb_top->m_maxlen, 0,
+ (struct sockaddr*)&sender, &len);
+ if (n < 0)
+ return errno;
+ mbp->mb_top->m_len = mbp->mb_count = n;
+ rqp->nr_sender = sender;
+ return 0;
+}
+
+static int
+nbns_rq_opensocket(struct nbns_rq *rqp)
+{
+ struct sockaddr_in locaddr;
+ int opt, s;
+
+ s = rqp->nr_fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s < 0)
+ return errno;
+ if (rqp->nr_flags & NBRQF_BROADCAST) {
+ opt = 1;
+ if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &opt, sizeof(opt)) < 0)
+ return errno;
+ if (rqp->nr_if == NULL)
+ return NBERROR(NBERR_NOBCASTIFS);
+ bzero(&locaddr, sizeof(locaddr));
+ locaddr.sin_family = AF_INET;
+ locaddr.sin_len = sizeof(locaddr);
+ locaddr.sin_addr = rqp->nr_if->id_addr;
+ rqp->nr_dest.sin_addr.s_addr = rqp->nr_if->id_addr.s_addr | ~rqp->nr_if->id_mask.s_addr;
+ if (bind(s, (struct sockaddr*)&locaddr, sizeof(locaddr)) < 0)
+ return errno;
+ }
+ return 0;
+}
+
+static int
+nbns_rq_send(struct nbns_rq *rqp)
+{
+ struct mbdata *mbp = &rqp->nr_rq;
+ int s = rqp->nr_fd;
+
+ if (sendto(s, mtod(mbp->mb_top, char *), mbp->mb_count, 0,
+ (struct sockaddr*)&rqp->nr_dest, sizeof(rqp->nr_dest)) < 0)
+ return errno;
+ return 0;
+}
+
+int
+nbns_rq(struct nbns_rq *rqp)
+{
+ struct mbdata *mbp = &rqp->nr_rq;
+ u_int16_t rpid;
+ u_int8_t nmflags;
+ int error, retrycount;
+
+ rqp->nr_if = nb_iflist;
+again:
+ error = nbns_rq_opensocket(rqp);
+ if (error)
+ return error;
+ retrycount = 3; /* XXX - configurable */
+ for (;;) {
+ error = nbns_rq_send(rqp);
+ if (error)
+ return error;
+ error = nbns_rq_recv(rqp);
+ if (error) {
+ if (error != ETIMEDOUT || retrycount == 0) {
+ if ((rqp->nr_nmflags & NBNS_NMFLAG_BCAST) &&
+ rqp->nr_if != NULL &&
+ rqp->nr_if->id_next != NULL) {
+ rqp->nr_if = rqp->nr_if->id_next;
+ close(rqp->nr_fd);
+ goto again;
+ } else
+ return error;
+ }
+ retrycount--;
+ continue;
+ }
+ mbp = &rqp->nr_rp;
+ if (mbp->mb_count < 12)
+ return NBERROR(NBERR_INVALIDRESPONSE);
+ mb_get_uint16be(mbp, &rpid);
+ if (rpid != rqp->nr_trnid)
+ return NBERROR(NBERR_INVALIDRESPONSE);
+ break;
+ }
+ mb_get_uint8(mbp, &nmflags);
+ rqp->nr_rpnmflags = (nmflags & 7) << 4;
+ mb_get_uint8(mbp, &nmflags);
+ rqp->nr_rpnmflags |= (nmflags & 0xf0) >> 4;
+ rqp->nr_rprcode = nmflags & 0xf;
+ if (rqp->nr_rprcode)
+ return NBERROR(rqp->nr_rprcode);
+ mb_get_uint16be(mbp, &rpid); /* QDCOUNT */
+ mb_get_uint16be(mbp, &rqp->nr_rpancount);
+ mb_get_uint16be(mbp, &rqp->nr_rpnscount);
+ mb_get_uint16be(mbp, &rqp->nr_rparcount);
+ return 0;
+}
diff --git a/contrib/smbfs/lib/smb/nls.c b/contrib/smbfs/lib/smb/nls.c
new file mode 100644
index 000000000000..7517c6e0eb41
--- /dev/null
+++ b/contrib/smbfs/lib/smb/nls.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2000-2001, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: nls.c,v 1.8 2001/04/16 12:46:46 bp Exp $
+ */
+
+#include <sys/types.h>
+#include <sys/iconv.h>
+#include <sys/sysctl.h>
+#include <ctype.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <stdio.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <err.h>
+#include <netsmb/smb_lib.h>
+
+/*
+ * prototype iconv* functions
+ */
+typedef void *iconv_t;
+
+static iconv_t (*my_iconv_open)(const char *, const char *);
+static size_t(*my_iconv)(iconv_t, const char **, size_t *, char **, size_t *);
+static int(*my_iconv_close)(iconv_t);
+
+u_char nls_lower[256];
+u_char nls_upper[256];
+
+static iconv_t nls_toext, nls_toloc;
+static int iconv_loaded;
+static void *iconv_lib;
+
+int
+nls_setlocale(const char *name)
+{
+ int i;
+
+ if (setlocale(LC_CTYPE, name) == NULL) {
+ warnx("can't set locale '%s'\n", name);
+ return EINVAL;
+ }
+ for (i = 0; i < 256; i++) {
+ nls_lower[i] = tolower(i);
+ nls_upper[i] = toupper(i);
+ }
+ return 0;
+}
+
+int
+nls_setrecode(const char *local, const char *external)
+{
+ iconv_t icd;
+
+ if (iconv_loaded == 2)
+ return ENOENT;
+ else if (iconv_loaded == 0) {
+ iconv_loaded++;
+ iconv_lib = dlopen("libiconv.so", RTLD_LAZY | RTLD_GLOBAL);
+ if (iconv_lib == NULL) {
+ warn("Unable to load iconv library: %s\n", dlerror());
+ iconv_loaded++;
+ return ENOENT;
+ }
+ my_iconv_open = dlsym(iconv_lib, "iconv_open");
+ my_iconv = dlsym(iconv_lib, "iconv");
+ my_iconv_close = dlsym(iconv_lib, "iconv_close");
+ }
+ if (nls_toext)
+ my_iconv_close(nls_toext);
+ if (nls_toloc)
+ my_iconv_close(nls_toloc);
+ nls_toext = nls_toloc = (iconv_t)0;
+ icd = my_iconv_open(external, local);
+ if (icd == (iconv_t)-1)
+ return errno;
+ nls_toext = icd;
+ icd = my_iconv_open(local, external);
+ if (icd == (iconv_t)-1) {
+ my_iconv_close(nls_toext);
+ nls_toext = (iconv_t)0;
+ return errno;
+ }
+ nls_toloc = icd;
+ return 0;
+}
+
+char *
+nls_str_toloc(char *dst, const char *src)
+{
+ char *p = dst;
+ int inlen, outlen;
+
+ if (!iconv_loaded)
+ return strcpy(dst, src);
+
+ if (nls_toloc == (iconv_t)0)
+ return strcpy(dst, src);
+ inlen = outlen = strlen(src);
+ my_iconv(nls_toloc, NULL, NULL, &p, &outlen);
+ my_iconv(nls_toloc, &src, &inlen, &p, &outlen);
+ *p = 0;
+ return dst;
+}
+
+char *
+nls_str_toext(char *dst, const char *src)
+{
+ char *p = dst;
+ int inlen, outlen;
+
+ if (!iconv_loaded)
+ return strcpy(dst, src);
+
+ if (nls_toext == (iconv_t)0)
+ return strcpy(dst, src);
+ inlen = outlen = strlen(src);
+ my_iconv(nls_toext, NULL, NULL, &p, &outlen);
+ my_iconv(nls_toext, &src, &inlen, &p, &outlen);
+ *p = 0;
+ return dst;
+}
+
+void *
+nls_mem_toloc(void *dst, const void *src, int size)
+{
+ char *p = dst;
+ const char *s = src;
+ int inlen, outlen;
+
+ if (!iconv_loaded)
+ return memcpy(dst, src, size);
+
+ if (size == 0)
+ return NULL;
+
+ if (nls_toloc == (iconv_t)0)
+ return memcpy(dst, src, size);
+ inlen = outlen = size;
+ my_iconv(nls_toloc, NULL, NULL, &p, &outlen);
+ my_iconv(nls_toloc, &s, &inlen, &p, &outlen);
+ return dst;
+}
+
+void *
+nls_mem_toext(void *dst, const void *src, int size)
+{
+ char *p = dst;
+ const char *s = src;
+ int inlen, outlen;
+
+ if (size == 0)
+ return NULL;
+
+ if (!iconv_loaded || nls_toext == (iconv_t)0)
+ return memcpy(dst, src, size);
+
+ inlen = outlen = size;
+ my_iconv(nls_toext, NULL, NULL, &p, &outlen);
+ my_iconv(nls_toext, &s, &inlen, &p, &outlen);
+ return dst;
+}
+
+char *
+nls_str_upper(char *dst, const char *src)
+{
+ char *p = dst;
+
+ while (*src)
+ *dst++ = toupper(*src++);
+ *dst = 0;
+ return p;
+}
+
+char *
+nls_str_lower(char *dst, const char *src)
+{
+ char *p = dst;
+
+ while (*src)
+ *dst++ = tolower(*src++);
+ *dst = 0;
+ return p;
+}
diff --git a/contrib/smbfs/lib/smb/print.c b/contrib/smbfs/lib/smb/print.c
new file mode 100644
index 000000000000..243ad5b29394
--- /dev/null
+++ b/contrib/smbfs/lib/smb/print.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: print.c,v 1.4 2001/04/16 04:33:01 bp Exp $
+ */
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/mount.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+
+/*#include <netnb/netbios.h>*/
+
+#include <netsmb/smb_lib.h>
+#include <netsmb/smb_conn.h>
+#include <cflib.h>
+
+int
+smb_smb_open_print_file(struct smb_ctx *ctx, int setuplen, int mode,
+ const char *ident, smbfh *fhp)
+{
+ struct smb_rq *rqp;
+ struct mbdata *mbp;
+ int error;
+
+ error = smb_rq_init(ctx, SMB_COM_OPEN_PRINT_FILE, 2, &rqp);
+ if (error)
+ return error;
+ mbp = smb_rq_getrequest(rqp);
+ mb_put_uint16le(mbp, setuplen);
+ mb_put_uint16le(mbp, mode);
+ smb_rq_wend(rqp);
+ mb_put_uint8(mbp, SMB_DT_ASCII);
+ smb_rq_dstring(mbp, ident);
+ error = smb_rq_simple(rqp);
+ if (!error) {
+ mbp = smb_rq_getreply(rqp);
+ mb_get_uint16(mbp, fhp);
+ }
+ smb_rq_done(rqp);
+ return error;
+}
+
+int
+smb_smb_close_print_file(struct smb_ctx *ctx, smbfh fh)
+{
+ struct smb_rq *rqp;
+ struct mbdata *mbp;
+ int error;
+
+ error = smb_rq_init(ctx, SMB_COM_CLOSE_PRINT_FILE, 0, &rqp);
+ if (error)
+ return error;
+ mbp = smb_rq_getrequest(rqp);
+ mb_put_mem(mbp, (char*)&fh, 2);
+ smb_rq_wend(rqp);
+ error = smb_rq_simple(rqp);
+ smb_rq_done(rqp);
+ return error;
+}
diff --git a/contrib/smbfs/lib/smb/rap.c b/contrib/smbfs/lib/smb/rap.c
new file mode 100644
index 000000000000..952f66670b9e
--- /dev/null
+++ b/contrib/smbfs/lib/smb/rap.c
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: rap.c,v 1.8 2001/02/24 15:56:05 bp Exp $
+ *
+ * This is very simple implementation of RAP protocol.
+ */
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <sysexits.h>
+
+#include <sys/mchain.h>
+
+#include <netsmb/smb_lib.h>
+#include <netsmb/smb_conn.h>
+#include <netsmb/smb_rap.h>
+
+/*#include <sys/ioctl.h>*/
+
+static int
+smb_rap_parserqparam(const char *s, char **next, int *rlen)
+{
+ char *np;
+ int len, m;
+
+ m = 1;
+ switch (*s++) {
+ case 'L':
+ case 'T':
+ case 'W':
+ len = 2;
+ break;
+ case 'D':
+ case 'O':
+ len = 4;
+ break;
+ case 'b':
+ case 'F':
+ len = 1;
+ break;
+ case 'r':
+ case 's':
+ len = 0;
+ break;
+ default:
+ return EINVAL;
+ }
+ if (isdigit(*s)) {
+ len *= strtoul(s, &np, 10);
+ s = np;
+ }
+ *rlen = len;
+ *(const char**)next = s;
+ return 0;
+}
+
+static int
+smb_rap_parserpparam(const char *s, char **next, int *rlen)
+{
+ char *np;
+ int len, m;
+
+ m = 1;
+ switch (*s++) {
+ case 'e':
+ case 'h':
+ len = 2;
+ break;
+ case 'i':
+ len = 4;
+ break;
+ case 'g':
+ len = 1;
+ break;
+ default:
+ return EINVAL;
+ }
+ if (isdigit(*s)) {
+ len *= strtoul(s, &np, 10);
+ s = np;
+ }
+ *rlen = len;
+ *(const char**)next = s;
+ return 0;
+}
+
+static int
+smb_rap_parserpdata(const char *s, char **next, int *rlen)
+{
+ char *np;
+ int len, m;
+
+ m = 1;
+ switch (*s++) {
+ case 'B':
+ len = 1;
+ break;
+ case 'W':
+ len = 2;
+ break;
+ case 'D':
+ case 'O':
+ case 'z':
+ len = 4;
+ break;
+ default:
+ return EINVAL;
+ }
+ if (isdigit(*s)) {
+ len *= strtoul(s, &np, 10);
+ s = np;
+ }
+ *rlen = len;
+ *(const char**)next = s;
+ return 0;
+}
+
+static int
+smb_rap_rqparam_z(struct smb_rap *rap, const char *value)
+{
+ int len = strlen(value) + 1;
+
+ bcopy(value, rap->r_npbuf, len);
+ rap->r_npbuf += len;
+ rap->r_plen += len;
+ return 0;
+}
+
+static int
+smb_rap_rqparam(struct smb_rap *rap, char ptype, char plen, long value)
+{
+ char *p = rap->r_npbuf;
+ int len;
+
+ switch (ptype) {
+ case 'L':
+ case 'W':
+ setwle(p, 0, value);
+ len = 2;
+ break;
+ case 'D':
+ setdle(p, 0, value);
+ len = 4;
+ break;
+ case 'b':
+ memset(p, value, plen);
+ len = plen;
+ default:
+ return EINVAL;
+ }
+ rap->r_npbuf += len;
+ rap->r_plen += len;
+ return 0;
+}
+
+int
+smb_rap_create(int fn, const char *param, const char *data,
+ struct smb_rap **rapp)
+{
+ struct smb_rap *rap;
+ char *p;
+ int plen, len;
+
+ rap = malloc(sizeof(*rap));
+ if (rap == NULL)
+ return NULL;
+ bzero(rap, sizeof(*rap));
+ p = rap->r_sparam = rap->r_nparam = strdup(param);
+ rap->r_sdata = rap->r_ndata = strdup(data);
+ /*
+ * Calculate length of request parameter block
+ */
+ len = 2 + strlen(param) + 1 + strlen(data) + 1;
+
+ while (*p) {
+ if (smb_rap_parserqparam(p, &p, &plen) != 0)
+ break;
+ len += plen;
+ }
+ rap->r_pbuf = rap->r_npbuf = malloc(len);
+ smb_rap_rqparam(rap, 'W', 1, fn);
+ smb_rap_rqparam_z(rap, rap->r_sparam);
+ smb_rap_rqparam_z(rap, rap->r_sdata);
+ *rapp = rap;
+ return 0;
+}
+
+void
+smb_rap_done(struct smb_rap *rap)
+{
+ if (rap->r_sparam)
+ free(rap->r_sparam);
+ if (rap->r_sdata)
+ free(rap->r_sdata);
+ free(rap);
+}
+
+int
+smb_rap_setNparam(struct smb_rap *rap, long value)
+{
+ char *p = rap->r_nparam;
+ char ptype = *p;
+ int error, plen;
+
+ error = smb_rap_parserqparam(p, &p, &plen);
+ if (error)
+ return error;
+ switch (ptype) {
+ case 'L':
+ rap->r_rcvbuflen = value;
+ /* FALLTHROUGH */
+ case 'W':
+ case 'D':
+ case 'b':
+ error = smb_rap_rqparam(rap, ptype, plen, value);
+ break;
+ default:
+ return EINVAL;
+ }
+ rap->r_nparam = p;
+ return 0;
+}
+
+int
+smb_rap_setPparam(struct smb_rap *rap, void *value)
+{
+ char *p = rap->r_nparam;
+ char ptype = *p;
+ int error, plen;
+
+ error = smb_rap_parserqparam(p, &p, &plen);
+ if (error)
+ return error;
+ switch (ptype) {
+ case 'r':
+ rap->r_rcvbuf = value;
+ break;
+ default:
+ return EINVAL;
+ }
+ rap->r_nparam = p;
+ return 0;
+}
+
+static int
+smb_rap_getNparam(struct smb_rap *rap, long *value)
+{
+ char *p = rap->r_nparam;
+ char ptype = *p;
+ int error, plen;
+
+ error = smb_rap_parserpparam(p, &p, &plen);
+ if (error)
+ return error;
+ switch (ptype) {
+ case 'h':
+ *value = letohs(*(u_int16_t*)rap->r_npbuf);
+ break;
+ default:
+ return EINVAL;
+ }
+ rap->r_npbuf += plen;
+ rap->r_nparam = p;
+ return 0;
+}
+
+int
+smb_rap_request(struct smb_rap *rap, struct smb_ctx *ctx)
+{
+ u_int16_t *rp, conv;
+ u_int32_t *p32;
+ char *dp, *p = rap->r_nparam;
+ char ptype;
+ int error, rdatacnt, rparamcnt, entries, done, dlen;
+
+ rdatacnt = rap->r_rcvbuflen;
+ rparamcnt = rap->r_plen;
+ error = smb_t2_request(ctx, 0, 0, "\\PIPE\\LANMAN",
+ rap->r_plen, rap->r_pbuf, /* int tparamcnt, void *tparam */
+ 0, NULL, /* int tdatacnt, void *tdata */
+ &rparamcnt, rap->r_pbuf, /* rparamcnt, void *rparam */
+ &rdatacnt, rap->r_rcvbuf /* int *rdatacnt, void *rdata */
+ );
+ if (error)
+ return error;
+ rp = (u_int16_t*)rap->r_pbuf;
+ rap->r_result = letohs(*rp++);
+ conv = letohs(*rp++);
+ rap->r_npbuf = (char*)rp;
+ rap->r_entries = entries = 0;
+ done = 0;
+ while (!done && *p) {
+ ptype = *p;
+ switch (ptype) {
+ case 'e':
+ rap->r_entries = entries = letohs(*(u_int16_t*)rap->r_npbuf);
+ rap->r_npbuf += 2;
+ p++;
+ break;
+ default:
+ done = 1;
+ }
+/* error = smb_rap_parserpparam(p, &p, &plen);
+ if (error) {
+ smb_error("reply parameter mismath %s", 0, p);
+ return EBADRPC;
+ }*/
+ }
+ rap->r_nparam = p;
+ /*
+ * In general, unpacking entries we may need to relocate
+ * entries for proper alingning. For now use them as is.
+ */
+ dp = rap->r_rcvbuf;
+ while (entries--) {
+ p = rap->r_sdata;
+ while (*p) {
+ ptype = *p;
+ error = smb_rap_parserpdata(p, &p, &dlen);
+ if (error) {
+ smb_error("reply data mismath %s", 0, p);
+ return EBADRPC;
+ }
+ switch (ptype) {
+ case 'z':
+ p32 = (u_int32_t*)dp;
+ *p32 = (*p32 & 0xffff) - conv;
+ break;
+ }
+ dp += dlen;
+ }
+ }
+ return error;
+}
+
+int
+smb_rap_error(struct smb_rap *rap, int error)
+{
+ if (error)
+ return error;
+ if (rap->r_result == 0)
+ return 0;
+ return rap->r_result | SMB_RAP_ERROR;
+}
+
+int
+smb_rap_NetShareEnum(struct smb_ctx *ctx, int sLevel, void *pbBuffer,
+ int cbBuffer, int *pcEntriesRead, int *pcTotalAvail)
+{
+ struct smb_rap *rap;
+ long lval;
+ int error;
+
+ error = smb_rap_create(0, "WrLeh", "B13BWz", &rap);
+ if (error)
+ return error;
+ smb_rap_setNparam(rap, sLevel); /* W - sLevel */
+ smb_rap_setPparam(rap, pbBuffer); /* r - pbBuffer */
+ smb_rap_setNparam(rap, cbBuffer); /* L - cbBuffer */
+ error = smb_rap_request(rap, ctx);
+ if (error == 0) {
+ *pcEntriesRead = rap->r_entries;
+ error = smb_rap_getNparam(rap, &lval);
+ *pcTotalAvail = lval;
+ }
+ error = smb_rap_error(rap, error);
+ smb_rap_done(rap);
+ return error;
+}
diff --git a/contrib/smbfs/lib/smb/rcfile.c b/contrib/smbfs/lib/smb/rcfile.c
new file mode 100644
index 000000000000..79f6bd75a0b1
--- /dev/null
+++ b/contrib/smbfs/lib/smb/rcfile.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: rcfile.c,v 1.5 2001/04/16 12:46:46 bp Exp $
+ */
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <unistd.h>
+#include <err.h>
+
+#include <cflib.h>
+#include "rcfile_priv.h"
+
+SLIST_HEAD(rcfile_head, rcfile);
+static struct rcfile_head pf_head = {NULL};
+
+static struct rcfile* rc_cachelookup(const char *filename);
+static struct rcsection *rc_findsect(struct rcfile *rcp, const char *sectname);
+static struct rcsection *rc_addsect(struct rcfile *rcp, const char *sectname);
+static int rc_freesect(struct rcfile *rcp, struct rcsection *rsp);
+static struct rckey *rc_sect_findkey(struct rcsection *rsp, const char *keyname);
+static struct rckey *rc_sect_addkey(struct rcsection *rsp, const char *name, const char *value);
+static void rc_key_free(struct rckey *p);
+static void rc_parse(struct rcfile *rcp);
+
+
+/*
+ * open rcfile and load its content, if already open - return previous handle
+ */
+int
+rc_open(const char *filename, const char *mode, struct rcfile **rcfile)
+{
+ struct rcfile *rcp;
+ FILE *f;
+
+ rcp = rc_cachelookup(filename);
+ if (rcp) {
+ *rcfile = rcp;
+ return 0;
+ }
+ f = fopen(filename, mode);
+ if (f == NULL)
+ return errno;
+ rcp = malloc(sizeof(struct rcfile));
+ if (rcp == NULL) {
+ fclose(f);
+ return ENOMEM;
+ }
+ bzero(rcp, sizeof(struct rcfile));
+ rcp->rf_name = strdup(filename);
+ rcp->rf_f = f;
+ SLIST_INSERT_HEAD(&pf_head, rcp, rf_next);
+ rc_parse(rcp);
+ *rcfile = rcp;
+ return 0;
+}
+
+int
+rc_merge(const char *filename, struct rcfile **rcfile)
+{
+ struct rcfile *rcp = *rcfile;
+ FILE *f, *t;
+
+ if (rcp == NULL) {
+ return rc_open(filename, "r", rcfile);
+ }
+ f = fopen (filename, "r");
+ if (f == NULL)
+ return errno;
+ t = rcp->rf_f;
+ rcp->rf_f = f;
+ rc_parse(rcp);
+ rcp->rf_f = t;
+ fclose(f);
+ return 0;
+}
+
+int
+rc_close(struct rcfile *rcp)
+{
+ struct rcsection *p, *n;
+
+ fclose(rcp->rf_f);
+ for(p = SLIST_FIRST(&rcp->rf_sect); p;) {
+ n = p;
+ p = SLIST_NEXT(p,rs_next);
+ rc_freesect(rcp, n);
+ }
+ free(rcp->rf_name);
+ SLIST_REMOVE(&pf_head, rcp, rcfile, rf_next);
+ free(rcp);
+ return 0;
+}
+
+static struct rcfile*
+rc_cachelookup(const char *filename)
+{
+ struct rcfile *p;
+
+ SLIST_FOREACH(p, &pf_head, rf_next)
+ if (strcmp (filename, p->rf_name) == 0)
+ return p;
+ return 0;
+}
+
+static struct rcsection *
+rc_findsect(struct rcfile *rcp, const char *sectname)
+{
+ struct rcsection *p;
+
+ SLIST_FOREACH(p, &rcp->rf_sect, rs_next)
+ if (strcmp(p->rs_name, sectname)==0)
+ return p;
+ return NULL;
+}
+
+static struct rcsection *
+rc_addsect(struct rcfile *rcp, const char *sectname)
+{
+ struct rcsection *p;
+
+ p = rc_findsect(rcp, sectname);
+ if (p) return p;
+ p = malloc(sizeof(*p));
+ if (!p) return NULL;
+ p->rs_name = strdup(sectname);
+ SLIST_INIT(&p->rs_keys);
+ SLIST_INSERT_HEAD(&rcp->rf_sect, p, rs_next);
+ return p;
+}
+
+static int
+rc_freesect(struct rcfile *rcp, struct rcsection *rsp)
+{
+ struct rckey *p,*n;
+
+ SLIST_REMOVE(&rcp->rf_sect, rsp, rcsection, rs_next);
+ for(p = SLIST_FIRST(&rsp->rs_keys);p;) {
+ n = p;
+ p = SLIST_NEXT(p,rk_next);
+ rc_key_free(n);
+ }
+ free(rsp->rs_name);
+ free(rsp);
+ return 0;
+}
+
+static struct rckey *
+rc_sect_findkey(struct rcsection *rsp, const char *keyname)
+{
+ struct rckey *p;
+
+ SLIST_FOREACH(p, &rsp->rs_keys, rk_next)
+ if (strcmp(p->rk_name, keyname)==0)
+ return p;
+ return NULL;
+}
+
+static struct rckey *
+rc_sect_addkey(struct rcsection *rsp, const char *name, const char *value)
+{
+ struct rckey *p;
+
+ p = rc_sect_findkey(rsp, name);
+ if (p) {
+ free(p->rk_value);
+ } else {
+ p = malloc(sizeof(*p));
+ if (!p) return NULL;
+ SLIST_INSERT_HEAD(&rsp->rs_keys, p, rk_next);
+ p->rk_name = strdup(name);
+ }
+ p->rk_value = value ? strdup(value) : strdup("");
+ return p;
+}
+
+#if 0
+void
+rc_sect_delkey(struct rcsection *rsp, struct rckey *p)
+{
+
+ SLIST_REMOVE(&rsp->rs_keys, p, rckey, rk_next);
+ rc_key_free(p);
+ return;
+}
+#endif
+
+static void
+rc_key_free(struct rckey *p)
+{
+ free(p->rk_value);
+ free(p->rk_name);
+ free(p);
+}
+
+enum { stNewLine, stHeader, stSkipToEOL, stGetKey, stGetValue};
+
+static void
+rc_parse(struct rcfile *rcp)
+{
+ FILE *f = rcp->rf_f;
+ int state = stNewLine, c;
+ struct rcsection *rsp = NULL;
+ struct rckey *rkp = NULL;
+ char buf[2048];
+ char *next = buf, *last = &buf[sizeof(buf)-1];
+
+ while ((c = getc (f)) != EOF) {
+ if (c == '\r')
+ continue;
+ if (state == stNewLine) {
+ next = buf;
+ if (isspace(c))
+ continue; /* skip leading junk */
+ if (c == '[') {
+ state = stHeader;
+ rsp = NULL;
+ continue;
+ }
+ if (c == '#' || c == ';') {
+ state = stSkipToEOL;
+ } else { /* something meaningfull */
+ state = stGetKey;
+ }
+ }
+ if (state == stSkipToEOL || next == last) {/* ignore long lines */
+ if (c == '\n'){
+ state = stNewLine;
+ next = buf;
+ }
+ continue;
+ }
+ if (state == stHeader) {
+ if (c == ']') {
+ *next = 0;
+ next = buf;
+ rsp = rc_addsect(rcp, buf);
+ state = stSkipToEOL;
+ } else
+ *next++ = c;
+ continue;
+ }
+ if (state == stGetKey) {
+ if (c == ' ' || c == '\t')/* side effect: 'key name='*/
+ continue; /* become 'keyname=' */
+ if (c == '\n') { /* silently ignore ... */
+ state = stNewLine;
+ continue;
+ }
+ if (c != '=') {
+ *next++ = c;
+ continue;
+ }
+ *next = 0;
+ if (rsp == NULL) {
+ fprintf(stderr, "Key '%s' defined before section\n", buf);
+ state = stSkipToEOL;
+ continue;
+ }
+ rkp = rc_sect_addkey(rsp, buf, NULL);
+ next = buf;
+ state = stGetValue;
+ continue;
+ }
+ /* only stGetValue left */
+ if (state != stGetValue) {
+ fprintf(stderr, "Well, I can't parse file '%s'\n",rcp->rf_name);
+ state = stSkipToEOL;
+ }
+ if (c != '\n') {
+ *next++ = c;
+ continue;
+ }
+ *next = 0;
+ rkp->rk_value = strdup(buf);
+ state = stNewLine;
+ rkp = NULL;
+ } /* while */
+ if (c == EOF && state == stGetValue) {
+ *next = 0;
+ rkp->rk_value = strdup(buf);
+ }
+ return;
+}
+
+int
+rc_getstringptr(struct rcfile *rcp, const char *section, const char *key,
+ char **dest)
+{
+ struct rcsection *rsp;
+ struct rckey *rkp;
+
+ *dest = NULL;
+ rsp = rc_findsect(rcp, section);
+ if (!rsp) return ENOENT;
+ rkp = rc_sect_findkey(rsp,key);
+ if (!rkp) return ENOENT;
+ *dest = rkp->rk_value;
+ return 0;
+}
+
+int
+rc_getstring(struct rcfile *rcp, const char *section, const char *key,
+ size_t maxlen, char *dest)
+{
+ char *value;
+ int error;
+
+ error = rc_getstringptr(rcp, section, key, &value);
+ if (error)
+ return error;
+ if (strlen(value) >= maxlen) {
+ warnx("line too long for key '%s' in section '%s', max = %d\n", key, section, maxlen);
+ return EINVAL;
+ }
+ strcpy(dest, value);
+ return 0;
+}
+
+int
+rc_getint(struct rcfile *rcp, const char *section, const char *key, int *value)
+{
+ struct rcsection *rsp;
+ struct rckey *rkp;
+
+ rsp = rc_findsect(rcp, section);
+ if (!rsp)
+ return ENOENT;
+ rkp = rc_sect_findkey(rsp, key);
+ if (!rkp)
+ return ENOENT;
+ errno = 0;
+ *value = strtol(rkp->rk_value, NULL, 0);
+ if (errno) {
+ warnx("invalid int value '%s' for key '%s' in section '%s'\n", rkp->rk_value, key, section);
+ return errno;
+ }
+ return 0;
+}
+
+/*
+ * 1,yes,true
+ * 0,no,false
+ */
+int
+rc_getbool(struct rcfile *rcp, const char *section, const char *key, int *value)
+{
+ struct rcsection *rsp;
+ struct rckey *rkp;
+ char *p;
+
+ rsp = rc_findsect(rcp, section);
+ if (!rsp) return ENOENT;
+ rkp = rc_sect_findkey(rsp,key);
+ if (!rkp) return ENOENT;
+ p = rkp->rk_value;
+ while (*p && isspace(*p)) p++;
+ if (*p == '0' || strcasecmp(p,"no") == 0 || strcasecmp(p,"false") == 0) {
+ *value = 0;
+ return 0;
+ }
+ if (*p == '1' || strcasecmp(p,"yes") == 0 || strcasecmp(p,"true") == 0) {
+ *value = 1;
+ return 0;
+ }
+ fprintf(stderr, "invalid boolean value '%s' for key '%s' in section '%s' \n",p, key, section);
+ return EINVAL;
+}
+
+/*
+ * Unified command line/rc file parser
+ */
+int
+opt_args_parse(struct rcfile *rcp, struct opt_args *ap, const char *sect,
+ opt_callback_t *callback)
+{
+ int len, error;
+
+ for (; ap->opt; ap++) {
+ switch (ap->type) {
+ case OPTARG_STR:
+ if (rc_getstringptr(rcp, sect, ap->name, &ap->str) != 0)
+ break;
+ len = strlen(ap->str);
+ if (len > ap->ival) {
+ warnx("rc: argument for option '%c' (%s) too long\n", ap->opt, ap->name);
+ return EINVAL;
+ }
+ callback(ap);
+ break;
+ case OPTARG_BOOL:
+ error = rc_getbool(rcp, sect, ap->name, &ap->ival);
+ if (error == ENOENT)
+ break;
+ if (error)
+ return EINVAL;
+ callback(ap);
+ break;
+ case OPTARG_INT:
+ if (rc_getint(rcp, sect, ap->name, &ap->ival) != 0)
+ break;
+ if (((ap->flag & OPTFL_HAVEMIN) && ap->ival < ap->min) ||
+ ((ap->flag & OPTFL_HAVEMAX) && ap->ival > ap->max)) {
+ warnx("rc: argument for option '%c' (%s) should be in [%d-%d] range\n",
+ ap->opt, ap->name, ap->min, ap->max);
+ return EINVAL;
+ }
+ callback(ap);
+ break;
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
+int
+opt_args_parseopt(struct opt_args *ap, int opt, char *arg,
+ opt_callback_t *callback)
+{
+ int len;
+
+ for (; ap->opt; ap++) {
+ if (ap->opt != opt)
+ continue;
+ switch (ap->type) {
+ case OPTARG_STR:
+ ap->str = arg;
+ if (arg) {
+ len = strlen(ap->str);
+ if (len > ap->ival) {
+ warnx("opt: Argument for option '%c' (%s) too long\n", ap->opt, ap->name);
+ return EINVAL;
+ }
+ callback(ap);
+ }
+ break;
+ case OPTARG_BOOL:
+ ap->ival = 0;
+ callback(ap);
+ break;
+ case OPTARG_INT:
+ errno = 0;
+ ap->ival = strtol(arg, NULL, 0);
+ if (errno) {
+ warnx("opt: Invalid integer value for option '%c' (%s).\n",ap->opt,ap->name);
+ return EINVAL;
+ }
+ if (((ap->flag & OPTFL_HAVEMIN) &&
+ (ap->ival < ap->min)) ||
+ ((ap->flag & OPTFL_HAVEMAX) &&
+ (ap->ival > ap->max))) {
+ warnx("opt: Argument for option '%c' (%s) should be in [%d-%d] range\n",ap->opt,ap->name,ap->min,ap->max);
+ return EINVAL;
+ }
+ callback(ap);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ return 0;
+}
+
diff --git a/contrib/smbfs/lib/smb/rcfile_priv.h b/contrib/smbfs/lib/smb/rcfile_priv.h
new file mode 100644
index 000000000000..5909d0c7cd90
--- /dev/null
+++ b/contrib/smbfs/lib/smb/rcfile_priv.h
@@ -0,0 +1,20 @@
+
+struct rckey {
+ SLIST_ENTRY(rckey) rk_next;
+ char *rk_name;
+ char *rk_value;
+};
+
+struct rcsection {
+ SLIST_ENTRY(rcsection) rs_next;
+ SLIST_HEAD(rckey_head,rckey) rs_keys;
+ char *rs_name;
+};
+
+struct rcfile {
+ SLIST_ENTRY(rcfile) rf_next;
+ SLIST_HEAD(rcsec_head, rcsection) rf_sect;
+ char *rf_name;
+ FILE *rf_f;
+};
+
diff --git a/contrib/smbfs/lib/smb/rq.c b/contrib/smbfs/lib/smb/rq.c
new file mode 100644
index 000000000000..c4107537cee0
--- /dev/null
+++ b/contrib/smbfs/lib/smb/rq.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: rq.c,v 1.7 2001/04/16 04:33:01 bp Exp $
+ */
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <sysexits.h>
+
+#include <sys/mchain.h>
+
+#include <netsmb/smb_lib.h>
+#include <netsmb/smb_conn.h>
+#include <netsmb/smb_rap.h>
+
+
+int
+smb_rq_init(struct smb_ctx *ctx, u_char cmd, size_t rpbufsz, struct smb_rq **rqpp)
+{
+ struct smb_rq *rqp;
+
+ rqp = malloc(sizeof(*rqp));
+ if (rqp == NULL)
+ return ENOMEM;
+ bzero(rqp, sizeof(*rqp));
+ rqp->rq_cmd = cmd;
+ rqp->rq_ctx = ctx;
+ mb_init(&rqp->rq_rq, M_MINSIZE);
+ mb_init(&rqp->rq_rp, rpbufsz);
+ *rqpp = rqp;
+ return 0;
+}
+
+void
+smb_rq_done(struct smb_rq *rqp)
+{
+ mb_done(&rqp->rq_rp);
+ mb_done(&rqp->rq_rq);
+ free(rqp);
+}
+
+void
+smb_rq_wend(struct smb_rq *rqp)
+{
+ if (rqp->rq_rq.mb_count & 1)
+ smb_error("smbrq_wend: odd word count\n", 0);
+ rqp->rq_wcount = rqp->rq_rq.mb_count / 2;
+ rqp->rq_rq.mb_count = 0;
+}
+
+int
+smb_rq_dmem(struct mbdata *mbp, const char *src, size_t size)
+{
+ struct mbuf *m;
+ char * dst;
+ int cplen, error;
+
+ if (size == 0)
+ return 0;
+ m = mbp->mb_cur;
+ if ((error = m_getm(m, size, &m)) != 0)
+ return error;
+ while (size > 0) {
+ cplen = M_TRAILINGSPACE(m);
+ if (cplen == 0) {
+ m = m->m_next;
+ continue;
+ }
+ if (cplen > (int)size)
+ cplen = size;
+ dst = mtod(m, char *) + m->m_len;
+ nls_mem_toext(dst, src, cplen);
+ size -= cplen;
+ src += cplen;
+ m->m_len += cplen;
+ mbp->mb_count += cplen;
+ }
+ mbp->mb_pos = mtod(m, char *) + m->m_len;
+ mbp->mb_cur = m;
+ return 0;
+}
+
+int
+smb_rq_dstring(struct mbdata *mbp, const char *s)
+{
+ return smb_rq_dmem(mbp, s, strlen(s) + 1);
+}
+
+int
+smb_rq_simple(struct smb_rq *rqp)
+{
+ struct smbioc_rq krq;
+ struct mbdata *mbp;
+ char *data;
+
+ mbp = smb_rq_getrequest(rqp);
+ m_lineup(mbp->mb_top, &mbp->mb_top);
+ data = mtod(mbp->mb_top, char*);
+ bzero(&krq, sizeof(krq));
+ krq.ioc_cmd = rqp->rq_cmd;
+ krq.ioc_twc = rqp->rq_wcount;
+ krq.ioc_twords = data;
+ krq.ioc_tbc = mbp->mb_count;
+ krq.ioc_tbytes = data + rqp->rq_wcount * 2;
+ mbp = smb_rq_getreply(rqp);
+ krq.ioc_rpbufsz = mbp->mb_top->m_maxlen;
+ krq.ioc_rpbuf = mtod(mbp->mb_top, char *);
+ if (ioctl(rqp->rq_ctx->ct_fd, SMBIOC_REQUEST, &krq) == -1)
+ return errno;
+ mbp->mb_top->m_len = krq.ioc_rwc * 2 + krq.ioc_rbc;
+ rqp->rq_wcount = krq.ioc_rwc;
+ rqp->rq_bcount = krq.ioc_rbc;
+ return 0;
+}
+
+int
+smb_t2_request(struct smb_ctx *ctx, int setup, int setupcount,
+ const char *name,
+ int tparamcnt, void *tparam,
+ int tdatacnt, void *tdata,
+ int *rparamcnt, void *rparam,
+ int *rdatacnt, void *rdata)
+{
+ struct smbioc_t2rq krq;
+
+ bzero(&krq, sizeof(krq));
+ krq.ioc_setup[0] = setup;
+ krq.ioc_setupcnt = setupcount;
+ (const char*)krq.ioc_name = name;
+ krq.ioc_tparamcnt = tparamcnt;
+ krq.ioc_tparam = tparam;
+ krq.ioc_tdatacnt = tdatacnt;
+ krq.ioc_tdata = tdata;
+ krq.ioc_rparamcnt = *rparamcnt;
+ krq.ioc_rparam = rparam;
+ krq.ioc_rdatacnt = *rdatacnt;
+ krq.ioc_rdata = rdata;
+ if (ioctl(ctx->ct_fd, SMBIOC_T2RQ, &krq) == -1)
+ return errno;
+ *rparamcnt = krq.ioc_rparamcnt;
+ *rdatacnt = krq.ioc_rdatacnt;
+ return 0;
+}
diff --git a/contrib/smbfs/lib/smb/subr.c b/contrib/smbfs/lib/smb/subr.c
new file mode 100644
index 000000000000..9541b629b51c
--- /dev/null
+++ b/contrib/smbfs/lib/smb/subr.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: subr.c,v 1.11 2001/04/16 04:33:01 bp Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/sysctl.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <err.h>
+
+#include <netsmb/netbios.h>
+#include <netsmb/smb_lib.h>
+#include <netsmb/nb_lib.h>
+#include <cflib.h>
+
+extern char *__progname;
+
+static int smblib_initialized;
+
+struct rcfile *smb_rc;
+
+int
+smb_lib_init(void)
+{
+ int error;
+ int kv;
+ size_t kvlen = sizeof(kv);
+
+ if (smblib_initialized)
+ return 0;
+#if __FreeBSD_version > 400000
+ error = sysctlbyname("net.smb.version", &kv, &kvlen, NULL, 0);
+ if (error) {
+ warnx("%s: can't find kernel module\n", __FUNCTION__);
+ return error;
+ }
+ if (NSMB_VERSION != kv) {
+ warnx("%s: kernel module version(%d) don't match library(%d).\n", __FUNCTION__, kv, NSMB_VERSION);
+ return EINVAL;
+ }
+#endif
+ if ((error = nls_setlocale("")) != 0) {
+ warnx("%s: can't initialise locale\n", __FUNCTION__);
+ return error;
+ }
+ smblib_initialized++;
+ return 0;
+}
+
+/*
+ * Print a (descriptive) error message
+ * error values:
+ * 0 - no specific error code available;
+ * 1..32767 - system error
+ */
+void
+smb_error(const char *fmt, int error,...) {
+ va_list ap;
+ const char *cp;
+ int errtype = error & SMB_ERRTYPE_MASK;
+
+ fprintf(stderr, "%s: ", __progname);
+ va_start(ap, error);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (error == -1)
+ error = errno;
+ else
+ error &= ~SMB_ERRTYPE_MASK;
+ switch (errtype) {
+ case SMB_SYS_ERROR:
+ if (error)
+ fprintf(stderr, ": syserr = %s\n", strerror(error));
+ else
+ fprintf(stderr, "\n");
+ break;
+ case SMB_RAP_ERROR:
+ fprintf(stderr, ": raperr = %d (0x%04x)\n", error, error);
+ break;
+ case SMB_NB_ERROR:
+ cp = nb_strerror(error);
+ if (cp == NULL)
+ fprintf(stderr, ": nberr = unknown (0x%04x)\n", error);
+ else
+ fprintf(stderr, ": nberr = %s\n", cp);
+ break;
+ default:
+ fprintf(stderr, "\n");
+ }
+}
+
+char *
+smb_printb(char *dest, int flags, const struct smb_bitname *bnp) {
+ int first = 1;
+
+ strcpy(dest, "<");
+ for(; bnp->bn_bit; bnp++) {
+ if (flags & bnp->bn_bit) {
+ strcat(dest, bnp->bn_name);
+ first = 0;
+ }
+ if (!first && (flags & bnp[1].bn_bit))
+ strcat(dest, "|");
+ }
+ strcat(dest, ">");
+ return dest;
+}
+
+/*
+ * first read ~/.smbrc, next try to merge SMB_CFG_FILE
+ */
+int
+smb_open_rcfile(void)
+{
+ char *home, *fn;
+ int error;
+
+ home = getenv("HOME");
+ if (home) {
+ fn = malloc(strlen(home) + 20);
+ sprintf(fn, "%s/.nsmbrc", home);
+ error = rc_open(fn, "r", &smb_rc);
+ free(fn);
+ }
+ error = rc_merge(SMB_CFG_FILE, &smb_rc);
+ if (smb_rc == NULL) {
+ printf("Warning: no cfg file(s) found.\n");
+ return ENOENT;
+ }
+ return 0;
+}
+
+void *
+smb_dumptree(void)
+{
+ size_t len;
+ void *p;
+ int error;
+
+ error = sysctlbyname("net.smb.treedump", NULL, &len, NULL, 0);
+ if (error)
+ return NULL;
+ p = malloc(len);
+ if (p == NULL)
+ return NULL;
+ error = sysctlbyname("net.smb.treedump", p, &len, NULL, 0);
+ if (error) {
+ free(p);
+ return NULL;
+ }
+ return p;
+}
+
+void
+smb_simplecrypt(char *dst, const char *src)
+{
+ int ch, pos;
+
+ *dst++ = '$';
+ *dst++ = '$';
+ *dst++ = '1';
+ pos = 27;
+ while (*src) {
+ ch = *src++;
+ if (isascii(ch))
+ ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
+ islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
+ ch ^= pos;
+ pos += 13;
+ sprintf(dst, "%02x", ch);
+ dst += 2;
+ }
+ *dst = 0;
+}
+
+int
+smb_simpledecrypt(char *dst, const char *src)
+{
+ char *ep, hexval[3];
+ int len, ch, pos;
+
+ if (strncmp(src, "$$1", 3) != 0)
+ return EINVAL;
+ src += 3;
+ len = strlen(src);
+ if (len & 1)
+ return EINVAL;
+ len /= 2;
+ hexval[2] = 0;
+ pos = 27;
+ while (len--) {
+ hexval[0] = *src++;
+ hexval[1] = *src++;
+ ch = strtoul(hexval, &ep, 16);
+ if (*ep != 0)
+ return EINVAL;
+ ch ^= pos;
+ pos += 13;
+ if (isascii(ch))
+ ch = (isupper(ch) ? ('A' + (ch - 'A' + 13) % 26) :
+ islower(ch) ? ('a' + (ch - 'a' + 13) % 26) : ch);
+ *dst++ = ch;
+ }
+ *dst = 0;
+ return 0;
+}
diff --git a/contrib/smbfs/mount_smbfs/Makefile b/contrib/smbfs/mount_smbfs/Makefile
new file mode 100644
index 000000000000..ffd79c9d4a56
--- /dev/null
+++ b/contrib/smbfs/mount_smbfs/Makefile
@@ -0,0 +1,18 @@
+# $Id: Makefile,v 1.7 2001/04/16 04:34:26 bp Exp $
+
+PROG= mount_smbfs
+SRCS= mount_smbfs.c getmntopts.c
+MAN8= mount_smbfs.8
+
+BINDIR= /sbin
+#NOSHARED=yes
+
+MOUNT= ${.CURDIR}/../mount
+CFLAGS+= -DSMBFS -I${MOUNT}
+
+.PATH: ${MOUNT}
+
+LDADD+= -lsmb
+DPADD+= ${LIBSMB}
+
+.include <bsd.prog.mk>
diff --git a/contrib/smbfs/mount_smbfs/getmntopts.c b/contrib/smbfs/mount_smbfs/getmntopts.c
new file mode 100644
index 000000000000..895b61c4e682
--- /dev/null
+++ b/contrib/smbfs/mount_smbfs/getmntopts.c
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (c) 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)getmntopts.c 8.3 (Berkeley) 3/29/95";
+#else
+static const char rcsid[] =
+ "$Id: getmntopts.c,v 1.1 2000/03/29 01:26:41 bp Exp $";
+#endif
+#endif /* not lint */
+
+#include <sys/param.h>
+
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "mntopts.h"
+
+int getmnt_silent = 0;
+
+void
+getmntopts(options, m0, flagp, altflagp)
+ const char *options;
+ const struct mntopt *m0;
+ int *flagp;
+ int *altflagp;
+{
+ const struct mntopt *m;
+ int negative, len;
+ char *opt, *optbuf, *p;
+ int *thisflagp;
+
+ /* Copy option string, since it is about to be torn asunder... */
+ if ((optbuf = strdup(options)) == NULL)
+ err(1, NULL);
+
+ for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) {
+ /* Check for "no" prefix. */
+ if (opt[0] == 'n' && opt[1] == 'o') {
+ negative = 1;
+ opt += 2;
+ } else
+ negative = 0;
+
+ /*
+ * for options with assignments in them (ie. quotas)
+ * ignore the assignment as it's handled elsewhere
+ */
+ p = strchr(opt, '=');
+ if (p)
+ *++p = '\0';
+
+ /* Scan option table. */
+ for (m = m0; m->m_option != NULL; ++m) {
+ len = strlen(m->m_option);
+ if (strncasecmp(opt, m->m_option, len) == 0)
+ if ( m->m_option[len] == '\0'
+ || m->m_option[len] == '='
+ )
+ break;
+ }
+
+ /* Save flag, or fail if option is not recognized. */
+ if (m->m_option) {
+ thisflagp = m->m_altloc ? altflagp : flagp;
+ if (negative == m->m_inverse)
+ *thisflagp |= m->m_flag;
+ else
+ *thisflagp &= ~m->m_flag;
+ } else if (!getmnt_silent) {
+ errx(1, "-o %s: option not supported", opt);
+ }
+ }
+
+ free(optbuf);
+}
diff --git a/contrib/smbfs/mount_smbfs/mntopts.h b/contrib/smbfs/mount_smbfs/mntopts.h
new file mode 100644
index 000000000000..5b6d52e69fee
--- /dev/null
+++ b/contrib/smbfs/mount_smbfs/mntopts.h
@@ -0,0 +1,91 @@
+/*-
+ * Copyright (c) 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)mntopts.h 8.7 (Berkeley) 3/29/95
+ * $Id: mntopts.h,v 1.1 2000/03/29 01:26:41 bp Exp $
+ */
+
+struct mntopt {
+ const char *m_option; /* option name */
+ int m_inverse; /* if a negative option, e.g. "dev" */
+ int m_flag; /* bit to set, e.g. MNT_RDONLY */
+ int m_altloc; /* 1 => set bit in altflags */
+};
+
+/* User-visible MNT_ flags. */
+#define MOPT_ASYNC { "async", 0, MNT_ASYNC, 0 }
+#define MOPT_NOATIME { "atime", 1, MNT_NOATIME, 0 }
+#define MOPT_NODEV { "dev", 1, MNT_NODEV, 0 }
+#define MOPT_NOEXEC { "exec", 1, MNT_NOEXEC, 0 }
+#define MOPT_NOSUID { "suid", 1, MNT_NOSUID, 0 }
+#define MOPT_NOSYMFOLLOW { "symfollow", 1, MNT_NOSYMFOLLOW, 0 }
+#define MOPT_RDONLY { "rdonly", 0, MNT_RDONLY, 0 }
+#define MOPT_SYNC { "sync", 0, MNT_SYNCHRONOUS, 0 }
+#define MOPT_UNION { "union", 0, MNT_UNION, 0 }
+#define MOPT_USERQUOTA { "userquota", 0, 0, 0 }
+#define MOPT_GROUPQUOTA { "groupquota", 0, 0, 0 }
+#define MOPT_NOCLUSTERR { "clusterr", 1, MNT_NOCLUSTERR, 0 }
+#define MOPT_NOCLUSTERW { "clusterw", 1, MNT_NOCLUSTERW, 0 }
+#define MOPT_SUIDDIR { "suiddir", 0, MNT_SUIDDIR, 0 }
+
+/* Control flags. */
+#define MOPT_FORCE { "force", 0, MNT_FORCE, 0 }
+#define MOPT_UPDATE { "update", 0, MNT_UPDATE, 0 }
+#define MOPT_RO { "ro", 0, MNT_RDONLY, 0 }
+#define MOPT_RW { "rw", 1, MNT_RDONLY, 0 }
+
+/* This is parsed by mount(8), but is ignored by specific mount_*(8)s. */
+#define MOPT_AUTO { "auto", 0, 0, 0 }
+
+#define MOPT_FSTAB_COMPAT \
+ MOPT_RO, \
+ MOPT_RW, \
+ MOPT_AUTO
+
+/* Standard options which all mounts can understand. */
+#define MOPT_STDOPTS \
+ MOPT_USERQUOTA, \
+ MOPT_GROUPQUOTA, \
+ MOPT_FSTAB_COMPAT, \
+ MOPT_NOATIME, \
+ MOPT_NODEV, \
+ MOPT_NOEXEC, \
+ MOPT_SUIDDIR, /* must be before MOPT_NOSUID */ \
+ MOPT_NOSUID, \
+ MOPT_NOSYMFOLLOW, \
+ MOPT_RDONLY, \
+ MOPT_UNION, \
+ MOPT_NOCLUSTERR, \
+ MOPT_NOCLUSTERW
+
+void getmntopts __P((const char *, const struct mntopt *, int *, int *));
+extern int getmnt_silent;
diff --git a/contrib/smbfs/mount_smbfs/mount_smbfs.8 b/contrib/smbfs/mount_smbfs/mount_smbfs.8
new file mode 100644
index 000000000000..b2c68d2d47ad
--- /dev/null
+++ b/contrib/smbfs/mount_smbfs/mount_smbfs.8
@@ -0,0 +1,158 @@
+.\" $Id: mount_smbfs.8,v 1.8 2000/06/09 13:52:56 bp Exp $
+.Dd Mar 10, 2000
+.Dt MOUNT_SMBFS 8
+.Os FreeBSD
+.Sh NAME
+.Nm mount_smbfs
+.Nd mounts a shared resource from an SMB file server
+.Sh SYNOPSIS
+.Nm mount_smbfs
+.Op Fl E Ar cs1:cs2
+.Op Fl I Ar host
+.Op Fl L Ar locale
+.Op Fl M Ar crights:srights
+.Op Fl N
+.Op Fl O Ar cowner:cgroup/sowner:sgroup
+.Op Fl R Ar retrycount
+.Op Fl T Ar timeout
+.Op Fl W Ar workgroup
+.Op Fl c Ar case
+.Op Fl d Ar mode
+.Op Fl f Ar mode
+.Op Fl g Ar gid
+.Op Fl n Ar opt
+.Op Fl u Ar uid
+.Ar //user@server/share
+.Ar node
+.Sh DESCRIPTION
+The
+.Nm
+command mounts a share from a remote server using SMB/CIFS protocol.
+.Pp
+The options are:
+.Bl -tag -width indent
+.It Fl E Ar cs1:cs2
+Specifies local
+.Ar (cs1)
+and server's
+.Ar (cs2)
+character sets.
+.It Fl I Ar host
+Do not use NetBIOS name resolver and connect directly to
+.Ar host ,
+which can be either a valid DNS name or an IP address.
+.It Fl L Ar locale
+Use
+.Ar locale
+for lower/upper case conversion routines.
+Set the locale for case conversion.
+By default
+.Nm
+tries to use an environment variable
+.Ev LC_*
+to determine it.
+.It Fl M Ar crights:srights
+Assign access rights to the newly created connection.
+See
+.Xr nsmb 8
+for theory.
+.It Fl N
+Do not ask for a password.
+At run time,
+.Nm
+reads the
+.Pa ~/.nsmbrc
+file for additional configuration parameters and a password.
+If no password is found the
+.Nm
+prompts for it.
+.It Fl O Ar cowner:cgroup/sowner:sgroup
+Assign owner/group attributes to the newly created connection.
+See
+.Xr nsmb 8
+for theory.
+.It Fl R Ar retrycount
+How many retries should be done before the SMB requester decides to drop
+the connection.
+.It Fl T Ar timeout
+Timeout in seconds for each request.
+.It Fl W Ar workgroup
+This option specifies the workgroup to be used in the authentication request.
+.It Fl c Ar case
+Set a
+.Ar case
+option which affects name representation.
+.Ar case
+can be one of the following:
+.Bl -tag -width "ValueXX"
+.It Em Value
+.Em Meaning
+.It l
+All existing file names converted to lower case.
+Newly created file gets a lower case.
+.It u
+All existing file names converted to upper case.
+Newly created file gets an upper case unde.
+.El
+.It Fl f Ar mode , Fl d Ar mode
+Specify permissions that should be assigned to files and directories.
+The values must be specified as octal numbers.
+Default value for the file mode
+is taken from mount point, default value for the dir mode adds execute
+permission where the file mode gives read permission.
+
+Note that these permissions can differ from the rights granted by SMB
+server.
+.It Fl u Ar uid , Fl g Ar gid
+User id and group id assigned to files.
+The default is owner and group id from
+directory where the volume is mounted.
+.It Ar //user@server/share
+The
+.Nm
+command will use
+.Ar server
+as the NetBIOS name of remote computer,
+.Ar user
+as the remote user name and
+.Ar share
+as the resource name on a remote server.
+.It Ar node
+Path to mount point.
+.El
+.Sh FILES
+.Bl -tag -width /var/log/wtmp -compact
+.It Pa ~/.nsmbrc
+Keeps static parameters for connections and other information.
+See
+.Pa ./examples/dot.nsmbrc
+for details.
+.El
+
+.Sh EXAMPLES
+The following examples illustrate how to connect to a SMB server
+.Em SAMBA
+as user
+.Em GUEST
+and mount shares
+.Em PUBLIC
+and
+.Em TMP :
+.Bd -literal -offset indent
+mount_smbfs -I samba.mydomain.com //guest@samba/public /smb/public
+mount_smbfs -I 192.168.20.3 -E koi8-r:cp866 //guest@samba/tmp /smb/tmp
+.Ed
+.Pp
+It is possible to use
+.Xr fstab 5
+for smbfs mounts:
+.Bd -literal -offset indent
+//guest@samba/public /smb/public smbfs rw,noauto 0 0
+.Ed
+
+.Sh BUGS
+Please report bugs to the author.
+
+.Sh AUTHORS
+.An Boris Popov Aq bp@butya.kz ,
+.Aq bp@freebsd.org
diff --git a/contrib/smbfs/mount_smbfs/mount_smbfs.c b/contrib/smbfs/mount_smbfs/mount_smbfs.c
new file mode 100644
index 000000000000..3122bc41a772
--- /dev/null
+++ b/contrib/smbfs/mount_smbfs/mount_smbfs.c
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2000-2001, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: mount_smbfs.c,v 1.13 2001/04/16 12:46:46 bp Exp $
+ */
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/errno.h>
+#include <sys/mount.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <err.h>
+#include <sysexits.h>
+
+#include <cflib.h>
+
+#include <netsmb/smb.h>
+#include <netsmb/smb_conn.h>
+#include <netsmb/smb_lib.h>
+
+#include <fs/smbfs/smbfs.h>
+
+#include "mntopts.h"
+
+static char mount_point[MAXPATHLEN + 1];
+static void usage(void);
+
+static struct mntopt mopts[] = {
+ MOPT_STDOPTS,
+ { NULL }
+};
+
+
+int
+main(int argc, char *argv[])
+{
+ struct smb_ctx sctx, *ctx = &sctx;
+ struct smbfs_args mdata;
+ struct stat st;
+ struct vfsconf vfc;
+ char *next;
+ int opt, error, mntflags, caseopt;
+
+ if (argc == 2) {
+ if (strcmp(argv[1], "-h") == 0) {
+ usage();
+ } else if (strcmp(argv[1], "-v") == 0) {
+ errx(EX_OK, "version %d.%d.%d", SMBFS_VERSION / 100000,
+ (SMBFS_VERSION % 10000) / 1000,
+ (SMBFS_VERSION % 1000) / 100);
+ }
+ }
+ if (argc < 3)
+ usage();
+
+ error = getvfsbyname(SMBFS_VFSNAME, &vfc);
+ if (error && vfsisloadable(SMBFS_VFSNAME)) {
+ if(vfsload(SMBFS_VFSNAME))
+ err(EX_OSERR, "vfsload("SMBFS_VFSNAME")");
+ endvfsent();
+ error = getvfsbyname(SMBFS_VFSNAME, &vfc);
+ }
+ if (error)
+ errx(EX_OSERR, "SMB filesystem is not available");
+
+ if (smb_lib_init() != 0)
+ exit(1);
+
+ mntflags = error = 0;
+ bzero(&mdata, sizeof(mdata));
+ mdata.uid = mdata.gid = -1;
+ caseopt = SMB_CS_NONE;
+
+ if (smb_ctx_init(ctx, argc, argv, SMBL_SHARE, SMBL_SHARE, SMB_ST_DISK) != 0)
+ exit(1);
+ if (smb_ctx_readrc(ctx) != 0)
+ exit(1);
+ if (smb_rc)
+ rc_close(smb_rc);
+
+ while ((opt = getopt(argc, argv, STDPARAM_OPT"c:d:f:g:l:n:o:u:w:")) != -1) {
+ switch (opt) {
+ case STDPARAM_ARGS:
+ error = smb_ctx_opt(ctx, opt, optarg);
+ if (error)
+ exit(1);
+ break;
+ case 'u': {
+ struct passwd *pwd;
+
+ pwd = isdigit(optarg[0]) ?
+ getpwuid(atoi(optarg)) : getpwnam(optarg);
+ if (pwd == NULL)
+ errx(EX_NOUSER, "unknown user '%s'", optarg);
+ mdata.uid = pwd->pw_uid;
+ break;
+ }
+ case 'g': {
+ struct group *grp;
+
+ grp = isdigit(optarg[0]) ?
+ getgrgid(atoi(optarg)) : getgrnam(optarg);
+ if (grp == NULL)
+ errx(EX_NOUSER, "unknown group '%s'", optarg);
+ mdata.gid = grp->gr_gid;
+ break;
+ }
+ case 'd':
+ errno = 0;
+ mdata.dir_mode = strtol(optarg, &next, 8);
+ if (errno || *next != 0)
+ errx(EX_DATAERR, "invalid value for directory mode");
+ break;
+ case 'f':
+ errno = 0;
+ mdata.file_mode = strtol(optarg, &next, 8);
+ if (errno || *next != 0)
+ errx(EX_DATAERR, "invalid value for file mode");
+ break;
+ case '?':
+ usage();
+ /*NOTREACHED*/
+ case 'n': {
+ char *inp, *nsp;
+
+ nsp = inp = optarg;
+ while ((nsp = strsep(&inp, ",;:")) != NULL) {
+ if (strcasecmp(nsp, "LONG") == 0)
+ mdata.flags |= SMBFS_MOUNT_NO_LONG;
+ else
+ errx(EX_DATAERR, "unknown suboption '%s'", nsp);
+ }
+ break;
+ };
+ case 'o':
+ getmntopts(optarg, mopts, &mntflags, 0);
+ break;
+ case 'c':
+ switch (optarg[0]) {
+ case 'l':
+ caseopt |= SMB_CS_LOWER;
+ break;
+ case 'u':
+ caseopt |= SMB_CS_UPPER;
+ break;
+ default:
+ errx(EX_DATAERR, "invalid suboption '%c' for -c",
+ optarg[0]);
+ }
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (optind == argc - 2)
+ optind++;
+
+ if (optind != argc - 1)
+ usage();
+ realpath(argv[optind], mount_point);
+
+ if (stat(mount_point, &st) == -1)
+ err(EX_OSERR, "could not find mount point %s", mount_point);
+ if (!S_ISDIR(st.st_mode)) {
+ errno = ENOTDIR;
+ err(EX_OSERR, "can't mount on %s", mount_point);
+ }
+/*
+ if (smb_getextattr(mount_point, &einfo) == 0)
+ errx(EX_OSERR, "can't mount on %s twice", mount_point);
+*/
+ if (mdata.uid == -1)
+ mdata.uid = st.st_uid;
+ if (mdata.gid == -1)
+ mdata.gid = st.st_gid;
+ if (mdata.file_mode == 0 )
+ mdata.file_mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+ if (mdata.dir_mode == 0) {
+ mdata.dir_mode = mdata.file_mode;
+ if (mdata.dir_mode & S_IRUSR)
+ mdata.dir_mode |= S_IXUSR;
+ if (mdata.dir_mode & S_IRGRP)
+ mdata.dir_mode |= S_IXGRP;
+ if (mdata.dir_mode & S_IROTH)
+ mdata.dir_mode |= S_IXOTH;
+ }
+ /*
+ * For now, let connection be private for this mount
+ */
+ ctx->ct_ssn.ioc_opt |= SMBVOPT_PRIVATE;
+ ctx->ct_ssn.ioc_owner = ctx->ct_sh.ioc_owner = 0; /* root */
+ ctx->ct_ssn.ioc_group = ctx->ct_sh.ioc_group = mdata.gid;
+ opt = 0;
+ if (mdata.dir_mode & S_IXGRP)
+ opt |= SMBM_EXECGRP;
+ if (mdata.dir_mode & S_IXOTH)
+ opt |= SMBM_EXECOTH;
+ ctx->ct_ssn.ioc_rights |= opt;
+ ctx->ct_sh.ioc_rights |= opt;
+ error = smb_ctx_resolve(ctx);
+ if (error)
+ exit(1);
+ error = smb_ctx_lookup(ctx, SMBL_SHARE, SMBLK_CREATE);
+ if (error) {
+ exit(1);
+ }
+ strcpy(mdata.mount_point,mount_point);
+ mdata.version = SMBFS_VERSION;
+ mdata.dev = ctx->ct_fd;
+ mdata.caseopt = caseopt;
+ error = mount(SMBFS_VFSNAME, mdata.mount_point, mntflags, (void*)&mdata);
+ smb_ctx_done(ctx);
+ if (error) {
+ smb_error("mount error: %s", error, mdata.mount_point);
+ exit(1);
+ }
+ return 0;
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "%s\n%s\n%s\n%s\n",
+ "usage: mount_smbfs [-Chv] [-U user] [-connection options]",
+ " [-M mode] [-c case] [-d mode] [-f mode]",
+ " [-g gid] [-l locale] [-n os2] [-u uid] [-w scheme]",
+ " /user@server/share node");
+
+ exit (1);
+}
diff --git a/contrib/smbfs/smbutil/Makefile b/contrib/smbfs/smbutil/Makefile
new file mode 100644
index 000000000000..de768c1b534c
--- /dev/null
+++ b/contrib/smbfs/smbutil/Makefile
@@ -0,0 +1,9 @@
+# $Id: Makefile,v 1.7 2001/04/16 04:34:26 bp Exp $
+
+PROG= smbutil
+SRCS= smbutil.c dumptree.c login.c lookup.c view.c print.c
+
+DPADD= ${LIBSMB}
+LDADD= -lsmb
+
+.include <bsd.prog.mk>
diff --git a/contrib/smbfs/smbutil/common.h b/contrib/smbfs/smbutil/common.h
new file mode 100644
index 000000000000..8cca8468ae62
--- /dev/null
+++ b/contrib/smbfs/smbutil/common.h
@@ -0,0 +1,17 @@
+
+#define iprintf(ident,args...) do { printf("%-" # ident "s", ""); \
+ printf(## args);}while(0)
+
+extern int verbose;
+
+int cmd_dumptree(int argc, char *argv[]);
+int cmd_login(int argc, char *argv[]);
+int cmd_logout(int argc, char *argv[]);
+int cmd_lookup(int argc, char *argv[]);
+int cmd_print(int argc, char *argv[]);
+int cmd_view(int argc, char *argv[]);
+void login_usage(void);
+void logout_usage(void);
+void lookup_usage(void);
+void print_usage(void);
+void view_usage(void);
diff --git a/contrib/smbfs/smbutil/dumptree.c b/contrib/smbfs/smbutil/dumptree.c
new file mode 100644
index 000000000000..3bf86ff69ae9
--- /dev/null
+++ b/contrib/smbfs/smbutil/dumptree.c
@@ -0,0 +1,134 @@
+#include <sys/param.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <netsmb/smb_lib.h>
+#include <netsmb/smb_conn.h>
+
+#include "common.h"
+
+#define DEFBIT(bit) {bit, #bit}
+
+static struct smb_bitname conn_caps[] = {
+ DEFBIT(SMB_CAP_RAW_MODE),
+ DEFBIT(SMB_CAP_MPX_MODE),
+ DEFBIT(SMB_CAP_UNICODE),
+ DEFBIT(SMB_CAP_LARGE_FILES),
+ DEFBIT(SMB_CAP_NT_SMBS),
+ DEFBIT(SMB_CAP_NT_FIND),
+ DEFBIT(SMB_CAP_EXT_SECURITY),
+ {0, NULL}
+};
+
+static struct smb_bitname vc_flags[] = {
+ DEFBIT(SMBV_PERMANENT),
+ {SMBV_PRIVATE, "private"},
+ {SMBV_SINGLESHARE, "singleshare"},
+ {SMBV_ENCRYPT, "encpwd"},
+ {SMBV_WIN95, "win95"},
+ {SMBV_LONGNAMES,"longnames"},
+ {0, NULL}
+};
+
+static struct smb_bitname ss_flags[] = {
+ DEFBIT(SMBS_PERMANENT),
+ {0, NULL}
+};
+
+static char *conn_proto[] = {
+ "unknown",
+ "PC NETWORK PROGRAM 1.0, PCLAN1.0",
+ "MICROSOFT NETWORKS 1.03",
+ "MICROSOFT NETWORKS 3.0, LANMAN1.0",
+ "LM1.2X002, DOS LM1.2X002",
+ "DOS LANMAN2.1, LANMAN2.1",
+ "NT LM 0.12, Windows for Workgroups 3.1a, NT LANMAN 1.0"
+};
+
+static char *iod_state[] = {
+ "Not connected",
+ "Reconnecting",
+ "Transport activated",
+ "Session active",
+ "Session dead"
+};
+
+static void
+print_vcinfo(struct smb_vc_info *vip)
+{
+ char buf[200];
+
+ printf("VC: \\\\%s\\%s\n", vip->srvname, vip->vcname);
+ printf("(%s:%s) %o", user_from_uid(vip->uid, 0),
+ group_from_gid(vip->gid, 0), vip->mode);
+ printf("\n");
+ if (!verbose)
+ return;
+ iprintf(4, "state: %s\n", iod_state[vip->iodstate]);
+ iprintf(4, "flags: 0x%04x %s\n", vip->flags,
+ smb_printb(buf, vip->flags, vc_flags));
+ iprintf(4, "usecount: %d\n", vip->usecount);
+ iprintf(4, "dialect: %d (%s)\n", vip->sopt.sv_proto, conn_proto[vip->sopt.sv_proto]);
+ iprintf(4, "smode: %d\n", vip->sopt.sv_sm);
+ iprintf(4, "caps: 0x%04x %s\n", vip->sopt.sv_caps,
+ smb_printb(buf, vip->sopt.sv_caps, conn_caps));
+ iprintf(4, "maxmux: %d\n", vip->sopt.sv_maxmux);
+ iprintf(4, "maxvcs: %d\n", vip->sopt.sv_maxvcs);
+}
+
+static void
+print_shareinfo(struct smb_share_info *sip)
+{
+ char buf[200];
+
+ iprintf(4, "Share: %s", sip->sname);
+ printf("(%s:%s) %o", user_from_uid(sip->uid, 0),
+ group_from_gid(sip->gid, 0), sip->mode);
+ printf("\n");
+ if (!verbose)
+ return;
+ iprintf(8, "flags: 0x%04x %s\n", sip->flags,
+ smb_printb(buf, sip->flags, ss_flags));
+ iprintf(8, "usecount: %d\n", sip->usecount);
+}
+
+int
+cmd_dumptree(int argc, char *argv[])
+{
+ void *p, *op;
+ int *itype;
+
+ printf("SMB connections:\n");
+ p = smb_dumptree();
+ if (p == NULL) {
+ printf("None\n");
+ return 0;
+ }
+ op = p;
+ for (;;) {
+ itype = p;
+ if (*itype == SMB_INFO_NONE)
+ break;
+ switch (*itype) {
+ case SMB_INFO_VC:
+ print_vcinfo(p);
+ p = (struct smb_vc_info*)p + 1;
+ break;
+ case SMB_INFO_SHARE:
+ print_shareinfo(p);
+ p = (struct smb_share_info*)p + 1;
+ break;
+ default:
+ printf("Out of sync\n");
+ free(op);
+ return 1;
+
+ }
+ }
+ free(op);
+ printf("\n");
+ return 0;
+}
diff --git a/contrib/smbfs/smbutil/login.c b/contrib/smbfs/smbutil/login.c
new file mode 100644
index 000000000000..2b3a45278b0d
--- /dev/null
+++ b/contrib/smbfs/smbutil/login.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: login.c,v 1.5 2001/01/28 07:35:00 bp Exp $
+ */
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <sysexits.h>
+
+#include <cflib.h>
+
+#include <netsmb/smb_lib.h>
+#include <netsmb/smb_conn.h>
+
+#include "common.h"
+
+
+int
+cmd_login(int argc, char *argv[])
+{
+ struct smb_ctx sctx, *ctx = &sctx;
+ int error, opt, setprimary = 0, level;
+
+ if (argc < 2)
+ login_usage();
+ if (smb_ctx_init(ctx, argc, argv, SMBL_VC, SMBL_SHARE, SMB_ST_ANY) != 0)
+ exit(1);
+ if (smb_ctx_readrc(ctx) != 0)
+ exit(1);
+ if (smb_rc)
+ rc_close(smb_rc);
+ while ((opt = getopt(argc, argv, STDPARAM_OPT"D")) != EOF) {
+ switch(opt){
+ case STDPARAM_ARGS:
+ error = smb_ctx_opt(ctx, opt, optarg);
+ if (error)
+ exit(1);
+ break;
+ case 'D':
+ setprimary = 1;
+ break;
+ default:
+ login_usage();
+ /*NOTREACHED*/
+ }
+ }
+ if (smb_ctx_resolve(ctx) != 0)
+ exit(1);
+ level = ctx->ct_parsedlevel;
+ error = smb_ctx_lookup(ctx, level, 0);
+ if (error == 0) {
+ smb_error("connection already exists", error);
+ exit(0);
+ }
+ error = smb_ctx_lookup(ctx, level, SMBLK_CREATE);
+ if (error) {
+ smb_error("could not login to server %s", error, ctx->ct_ssn.ioc_srvname);
+ exit(1);
+ }
+ switch (level) {
+ case SMBL_VC:
+ opt = SMBV_PERMANENT;
+ break;
+ case SMBL_SHARE:
+ opt = SMBS_PERMANENT;
+ break;
+ default:
+ smb_error("unknown connection level %d", 0, level);
+ exit(1);
+ }
+ error = smb_ctx_setflags(ctx, level, opt, opt);
+ if (error && error != EACCES) {
+ smb_error("Can't make connection permanent", error);
+ exit(1);
+ }
+ printf("Connected to %s%s%s\n", ctx->ct_ssn.ioc_user,
+ level == SMBL_SHARE ? "@" : "",
+ level == SMBL_SHARE ? ctx->ct_sh.ioc_share : "");
+ return 0;
+}
+
+int
+cmd_logout(int argc, char *argv[])
+{
+ struct smb_ctx sctx, *ctx = &sctx;
+ int error, opt, level;
+
+ if (argc < 2)
+ logout_usage();
+ if (smb_ctx_init(ctx, argc, argv, SMBL_VC, SMBL_SHARE, SMB_ST_ANY) != 0)
+ exit(1);
+ if (smb_ctx_readrc(ctx) != 0)
+ exit(1);
+ if (smb_rc)
+ rc_close(smb_rc);
+ while ((opt = getopt(argc, argv, STDPARAM_OPT)) != EOF){
+ switch (opt) {
+ case STDPARAM_ARGS:
+ error = smb_ctx_opt(ctx, opt, optarg);
+ if (error)
+ exit(1);
+ break;
+ default:
+ logout_usage();
+ /*NOTREACHED*/
+ }
+ }
+ ctx->ct_ssn.ioc_opt &= ~SMBVOPT_CREATE;
+ ctx->ct_sh.ioc_opt &= ~SMBSOPT_CREATE;
+ if (smb_ctx_resolve(ctx) != 0)
+ exit(1);
+ level = ctx->ct_parsedlevel;
+ error = smb_ctx_lookup(ctx, level, 0);
+ if (error == ENOENT) {
+/* ctx->ct_ssn.ioc_opt |= SMBCOPT_SINGLE;
+ error = smb_ctx_login(ctx);
+ if (error == ENOENT) {
+ ctx->ct_ssn.ioc_opt |= SMBCOPT_PRIVATE;
+ error = smb_ctx_login(ctx);
+ if (error == ENOENT) {
+ ctx->ct_ssn.ioc_opt &= ~SMBCOPT_SINGLE;
+ error = smb_ctx_login(ctx);
+ }
+ }*/
+ if (error) {
+ smb_error("There is no connection to %s", error, ctx->ct_ssn.ioc_srvname);
+ exit(1);
+ }
+ }
+ if (error)
+ exit(1);
+ switch (level) {
+ case SMBL_VC:
+ opt = SMBV_PERMANENT;
+ break;
+ case SMBL_SHARE:
+ opt = SMBS_PERMANENT;
+ break;
+ default:
+ smb_error("unknown connection level %d", 0, level);
+ exit(1);
+ }
+ error = smb_ctx_setflags(ctx, level, opt, 0);
+ if (error && error != EACCES) {
+ smb_error("Can't release connection", error);
+ exit(1);
+ }
+ printf("Connection unmarked as permanent and will be closed when possible\n");
+ exit(0);
+}
+
+void
+login_usage(void)
+{
+ printf(
+ "usage: smbutil login [-E cs1:cs2] [-I host] [-L locale] [-M crights:srights]\n"
+ " [-N cowner:cgroup/sowner:sgroup] [-P]\n"
+ " [-R retrycount] [-T timeout]\n"
+ " [-W workgroup] //user@server\n");
+ exit(1);
+}
+
+void
+logout_usage(void)
+{
+ printf("usage: smbutil logout [user@server]\n");
+ exit(1);
+}
diff --git a/contrib/smbfs/smbutil/lookup.c b/contrib/smbfs/smbutil/lookup.c
new file mode 100644
index 000000000000..143242f31d55
--- /dev/null
+++ b/contrib/smbfs/smbutil/lookup.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: lookup.c,v 1.3 2000/10/15 14:26:49 bp Exp $
+ */
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <err.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <sysexits.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <cflib.h>
+
+#include <netsmb/netbios.h>
+#include <netsmb/smb_lib.h>
+#include <netsmb/nb_lib.h>
+#include <netsmb/smb_conn.h>
+
+#include "common.h"
+
+
+int
+cmd_lookup(int argc, char *argv[])
+{
+ struct nb_ctx *ctx;
+ struct sockaddr *sap;
+ char *hostname;
+ int error, opt;
+
+ if (argc < 2)
+ lookup_usage();
+ error = nb_ctx_create(&ctx);
+ if (error) {
+ smb_error("unable to create nbcontext", error);
+ exit(1);
+ }
+ if (smb_open_rcfile() == 0) {
+ if (nb_ctx_readrcsection(smb_rc, ctx, "default", 0) != 0)
+ exit(1);
+ rc_close(smb_rc);
+ }
+ while ((opt = getopt(argc, argv, "w:")) != EOF) {
+ switch(opt){
+ case 'w':
+ nb_ctx_setns(ctx, optarg);
+ break;
+ default:
+ lookup_usage();
+ /*NOTREACHED*/
+ }
+ }
+ if (optind >= argc)
+ lookup_usage();
+ if (nb_ctx_resolve(ctx) != 0)
+ exit(1);
+ hostname = argv[argc - 1];
+/* printf("Looking for %s...\n", hostname);*/
+ error = nbns_resolvename(hostname, ctx, &sap);
+ if (error) {
+ smb_error("unable to resolve %s", error, hostname);
+ exit(1);
+ }
+ printf("Got response from %s\n", inet_ntoa(ctx->nb_lastns.sin_addr));
+ printf("IP address of %s: %s\n", hostname, inet_ntoa(((struct sockaddr_in*)sap)->sin_addr));
+ return 0;
+}
+
+
+void
+lookup_usage(void)
+{
+ printf("usage: smbutil lookup [-w host] name\n");
+ exit(1);
+}
diff --git a/contrib/smbfs/smbutil/print.c b/contrib/smbfs/smbutil/print.c
new file mode 100644
index 000000000000..4d7168c71c6e
--- /dev/null
+++ b/contrib/smbfs/smbutil/print.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: print.c,v 1.4 2001/01/28 07:35:01 bp Exp $
+ */
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <sysexits.h>
+
+#include <cflib.h>
+
+#include <netsmb/smb_lib.h>
+#include <netsmb/smb_conn.h>
+
+#include "common.h"
+
+int
+cmd_print(int argc, char *argv[])
+{
+ struct smb_ctx sctx, *ctx = &sctx;
+ smbfh fh;
+ off_t offset;
+ char buf[8192];
+ char *filename;
+ char fnamebuf[256];
+ int error, opt, i, file, count;
+
+ if (argc < 2)
+ view_usage();
+ if (smb_ctx_init(ctx, argc, argv, SMBL_SHARE, SMBL_SHARE, SMB_ST_PRINTER) != 0)
+ exit(1);
+ if (smb_ctx_readrc(ctx) != 0)
+ exit(1);
+ if (smb_rc)
+ rc_close(smb_rc);
+ while ((opt = getopt(argc, argv, STDPARAM_OPT)) != EOF) {
+ switch(opt){
+ case STDPARAM_ARGS:
+ error = smb_ctx_opt(ctx, opt, optarg);
+ if (error)
+ exit(1);
+ break;
+ default:
+ view_usage();
+ /*NOTREACHED*/
+ }
+ }
+ if (optind + 1 >= argc)
+ print_usage();
+ filename = argv[optind + 1];
+
+ if (strcmp(filename, "-") == 0) {
+ file = 0; /* stdin */
+ filename = "stdin";
+ } else {
+ file = open(filename, O_RDONLY, 0);
+ if (file < 0) {
+ smb_error("could not open file %s\n", errno, filename);
+ exit(1);
+ }
+ }
+
+ if (smb_ctx_resolve(ctx) != 0)
+ exit(1);
+ error = smb_ctx_lookup(ctx, SMBL_SHARE, SMBLK_CREATE);
+ if (error) {
+ smb_error("could not login to server %s", error, ctx->ct_ssn.ioc_srvname);
+ exit(1);
+ }
+ snprintf(fnamebuf, sizeof(fnamebuf), "%s_%s_%s", ctx->ct_ssn.ioc_user,
+ ctx->ct_ssn.ioc_srvname, filename);
+ error = smb_smb_open_print_file(ctx, 0, 1, fnamebuf, &fh);
+ if (error) {
+ smb_error("could not open print job", error);
+ exit(1);
+ }
+ offset = 0;
+ error = 0;
+ for(;;) {
+ count = read(file, buf, sizeof(buf));
+ if (count == 0)
+ break;
+ if (count < 0) {
+ error = errno;
+ smb_error("error reading input file\n", error);
+ break;
+ }
+ i = smb_write(ctx, fh, offset, count, buf);
+ if (i < 0) {
+ error = errno;
+ smb_error("error writing spool file\n", error);
+ break;
+ }
+ if (i != count) {
+ smb_error("incomplete write to spool file\n", 0);
+ error = EIO;
+ break;
+ }
+ offset += count;
+ }
+ close(file);
+ error = smb_smb_close_print_file(ctx, fh);
+ if (error)
+ smb_error("an error while closing spool file\n", error);
+ return error ? 1 : 0;
+}
+
+
+void
+print_usage(void)
+{
+ printf(
+ "usage: smbutil print [connection optinons] //user@server/share\n"
+ );
+ exit(1);
+}
+
diff --git a/contrib/smbfs/smbutil/smbutil.1 b/contrib/smbfs/smbutil/smbutil.1
new file mode 100644
index 000000000000..11ee0f0619e9
--- /dev/null
+++ b/contrib/smbfs/smbutil/smbutil.1
@@ -0,0 +1,124 @@
+.\" $Id: smbutil.1,v 1.3 2000/07/17 01:49:27 bp Exp $
+.Dd Feb 14, 2000
+.Dt SMBUTIL 1
+.Os
+.Sh NAME
+.Nm smbutil
+.Nd Interface to SMB requester
+.Sh SYNOPSIS
+.Nm smbutil
+.Op Fl hv
+.Ar command
+.Op Fl options
+.Op Ar args
+.Sh DESCRIPTION
+The
+.Nm
+command used to control SMB requester and issue various commands.
+.Pp
+There are two types of options - global and local to specified command.
+.Pp
+The global options are:
+.Bl -tag -width indent
+.It Fl h
+Print short help message.
+.It Fl v
+Verbose output.
+.El
+.Pp
+The commands and local options are:
+.Bl -tag -width indent
+.It Em crypt Op password
+Slightly encrypt clear text password to use it in the
+.Pa ~/.nsmbrc
+file. The encrypted password starts with '$$1' symbols.
+Warning: the encryption function is very weak and intented only to hide
+clear text password.
+If
+.Ar password
+is ommited from command line, program will prompt for one.
+.It Em help Ar command
+Print usage information about
+.Ar command .
+.It Em lc
+List active connections and their parameters.
+.It Xo
+.Em login
+.Op Fl connection\ options
+.Ar //user@server Ns Op Ar /share
+.Xc
+Login/attach to the specified
+.Ar server
+and/or
+.Ar share
+as
+.Ar user .
+This command will create and authenticate connection to an SMB server, and
+will leave it active after exit.
+Thus, one can login only once and then
+use other SMB commands without authentication procedure and additional
+connections.
+For the description of
+.Op Fl connection\ options
+see
+.Xr mount_smbfs 8
+command (all uppercase options are connection options).
+.It Xo
+.Em logout
+.Ar //user@server Ns Op Ar /share
+.Xc
+Logout/detach from the specified
+.Ar server
+and/or
+.Ar share
+as
+.Ar user .
+This command will destroy connection created by
+.Ar login
+command. A connection may not be closed immediately if it used by other
+programs.
+.It Xo
+.Em lookup
+.Op Fl w Ar host
+.Ar name
+.Xc
+Resolve given
+.Ar name
+to IP address.
+NetBIOS name server can be directly specified via
+.Op Fl w
+option.
+.It Xo
+.Em print
+.Op Fl connection\ options
+.Ar //user@server/share
+.Ar file
+.Xc
+Send given
+.Ar file
+to the specified queue on the remote server.
+If
+.Ar file
+is '-', then standard input will be used.
+.It Xo
+.Em view
+.Op Fl connection\ options
+.Ar //user@server
+.Xc
+List resources avaliable on the specified
+.Ar server
+for the user
+.Ar user .
+.El
+.Sh FILES
+.Bl -tag -width /var/log/wtmp -compact
+.It Pa ~/.nsmbrc
+keeps description for each connection.
+See
+.Pa ./examples/dot.nsmbrc
+for details.
+.Sh AUTHORS
+.An Boris Popov Aq bp@butya.kz ,
+.Aq bp@freebsd.org
+.Sh BUGS
+Please report any bugs to the author.
diff --git a/contrib/smbfs/smbutil/smbutil.c b/contrib/smbfs/smbutil/smbutil.c
new file mode 100644
index 000000000000..d66003f4346f
--- /dev/null
+++ b/contrib/smbfs/smbutil/smbutil.c
@@ -0,0 +1,155 @@
+#include <sys/param.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <err.h>
+#include <sysexits.h>
+
+#include <netsmb/smb_lib.h>
+#include <netsmb/smb_conn.h>
+
+#include "common.h"
+
+extern char *__progname;
+
+static void help(void);
+static void help_usage(void);
+static int cmd_crypt(int argc, char *argv[]);
+static int cmd_help(int argc, char *argv[]);
+
+int verbose;
+
+typedef int cmd_fn_t (int argc, char *argv[]);
+typedef void cmd_usage_t (void);
+
+#define CMDFL_NO_KMOD 0x0001
+
+static struct commands {
+ const char * name;
+ cmd_fn_t* fn;
+ cmd_usage_t * usage;
+ int flags;
+} commands[] = {
+ {"crypt", cmd_crypt, NULL, CMDFL_NO_KMOD},
+ {"help", cmd_help, help_usage, CMDFL_NO_KMOD},
+ {"lc", cmd_dumptree, NULL},
+ {"login", cmd_login, login_usage},
+ {"logout", cmd_logout, logout_usage},
+ {"lookup", cmd_lookup, lookup_usage, CMDFL_NO_KMOD},
+ {"print", cmd_print, print_usage},
+ {"view", cmd_view, view_usage},
+ {NULL, NULL}
+};
+
+static struct commands *
+lookupcmd(const char *name)
+{
+ struct commands *cmd;
+
+ for (cmd = commands; cmd->name; cmd++) {
+ if (strcmp(cmd->name, name) == 0)
+ return cmd;
+ }
+ return NULL;
+}
+
+int
+cmd_crypt(int argc, char *argv[])
+{
+ char *cp, *psw;
+
+ if (argc < 2)
+ psw = getpass("Password:");
+ else
+ psw = argv[1];
+ cp = malloc(strlen(psw + 4));
+ if (cp == NULL)
+ errx(EX_DATAERR, "out of memory");
+ smb_simplecrypt(cp, psw);
+ printf("%s\n", cp);
+ free(cp);
+ exit(0);
+}
+
+int
+cmd_help(int argc, char *argv[])
+{
+ struct commands *cmd;
+ char *cp;
+
+ if (argc < 2)
+ help_usage();
+ cp = argv[1];
+ cmd = lookupcmd(cp);
+ if (cmd == NULL)
+ errx(EX_DATAERR, "unknown command %s", cp);
+ if (cmd->usage == NULL)
+ errx(EX_DATAERR, "no specific help for command %s", cp);
+ cmd->usage();
+ exit(0);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct commands *cmd;
+ char *cp;
+ int opt;
+
+ if (argc < 2)
+ help();
+
+ while ((opt = getopt(argc, argv, "hv")) != EOF) {
+ switch (opt) {
+ case 'h':
+ help();
+ /*NOTREACHED */
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ warnx("invalid option %c", opt);
+ help();
+ /*NOTREACHED */
+ }
+ }
+ if (optind >= argc)
+ help();
+
+ cp = argv[optind];
+ cmd = lookupcmd(cp);
+ if (cmd == NULL)
+ errx(EX_DATAERR, "unknown command %s", cp);
+
+ if ((cmd->flags & CMDFL_NO_KMOD) == 0 && smb_lib_init() != 0)
+ exit(1);
+
+ argc -= optind;
+ argv += optind;
+ optind = optreset = 1;
+ return cmd->fn(argc, argv);
+}
+
+static void
+help(void) {
+ printf("\n");
+ printf("usage: %s [-hv] command [args]\n", __progname);
+ printf("where commands are:\n"
+ " crypt [password] slightly encrypt password\n"
+ " help command display help on \"command\"\n"
+ " lc display active connections\n"
+ " login //user@host[/share] login to the specified host\n"
+ " logout //user@host[/share] logout from the specified host\n"
+ " print //user@host/share file print file to the specified remote printer\n"
+ " view //user@host list resources on the specified host\n"
+ "\n");
+ exit(1);
+}
+
+static void
+help_usage(void) {
+ printf("usage: smbutil help command\n");
+ exit(1);
+}
diff --git a/contrib/smbfs/smbutil/view.c b/contrib/smbfs/smbutil/view.c
new file mode 100644
index 000000000000..d69928ab8326
--- /dev/null
+++ b/contrib/smbfs/smbutil/view.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2000, Boris Popov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Boris Popov.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: view.c,v 1.7 2001/01/28 07:35:01 bp Exp $
+ */
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/stat.h>
+#include <sys/iconv.h>
+#include <err.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <sysexits.h>
+
+#include <cflib.h>
+
+#include <netsmb/smb_lib.h>
+#include <netsmb/smb_conn.h>
+#include <netsmb/smb_rap.h>
+
+#include "common.h"
+
+static char *shtype[] = {
+ "disk",
+ "printer",
+ "pipe",
+ "comm",
+ "unknown"
+};
+
+int
+cmd_view(int argc, char *argv[])
+{
+ struct smb_ctx sctx, *ctx = &sctx;
+ struct smb_share_info_1 *rpbuf, *ep;
+ char *cp;
+ int error, opt, bufsize, i, entries, total;
+
+ if (argc < 2)
+ view_usage();
+ if (smb_ctx_init(ctx, argc, argv, SMBL_VC, SMBL_VC, SMB_ST_ANY) != 0)
+ exit(1);
+ if (smb_ctx_readrc(ctx) != 0)
+ exit(1);
+ if (smb_rc)
+ rc_close(smb_rc);
+ while ((opt = getopt(argc, argv, STDPARAM_OPT)) != EOF) {
+ switch(opt){
+ case STDPARAM_ARGS:
+ error = smb_ctx_opt(ctx, opt, optarg);
+ if (error)
+ exit(1);
+ break;
+ default:
+ view_usage();
+ /*NOTREACHED*/
+ }
+ }
+ smb_ctx_setshare(ctx, "IPC$", SMB_ST_ANY);
+ if (smb_ctx_resolve(ctx) != 0)
+ exit(1);
+ error = smb_ctx_lookup(ctx, SMBL_SHARE, SMBLK_CREATE);
+ if (error) {
+ smb_error("could not login to server %s", error, ctx->ct_ssn.ioc_srvname);
+ exit(1);
+ }
+ printf("Share Type Comment\n");
+ printf("-------------------------------\n");
+ bufsize = 65535;
+ rpbuf = malloc(bufsize);
+ error = smb_rap_NetShareEnum(ctx, 1, rpbuf, bufsize, &entries, &total);
+ if (error &&
+ error != (SMB_ERROR_MORE_DATA | SMB_RAP_ERROR)) {
+ smb_error("unable to list resources", error);
+ exit(1);
+ }
+ for (ep = rpbuf, i = 0; i < entries; i++, ep++) {
+ cp = (char*)rpbuf + ep->shi1_remark;
+ printf("%-12s %-10s %s\n", ep->shi1_netname,
+ shtype[ep->shi1_type],
+ ep->shi1_remark ? nls_str_toloc(cp, cp) : "");
+ }
+ printf("\n%d shares listed from %d available\n", entries, total);
+ free(rpbuf);
+ return 0;
+}
+
+
+void
+view_usage(void)
+{
+ printf(
+ "usage: smbutil view [connection optinons] //[user@]server\n"
+ );
+ exit(1);
+}
+