diff options
52 files changed, 7041 insertions, 0 deletions
diff --git a/contrib/smbfs/COPYRIGHT b/contrib/smbfs/COPYRIGHT new file mode 100644 index 0000000..583923c --- /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 0000000..e9228af --- /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 0000000..888c814 --- /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 0000000..1ae864d --- /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 0000000..6729780 --- /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 0000000..0e7173c --- /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 0000000..a85b435 --- /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 0000000..328a115 --- /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 0000000..1d38e52 --- /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 0000000..b630fa8 --- /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 0000000..578611a --- /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 0000000..32b09ea --- /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 0000000..6d1e899 --- /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 0000000..e74cb90 --- /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 0000000..7908de2 --- /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 0000000..61e3c23 --- /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 0000000..dbbdc6b --- /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 0000000..24fccb8 --- /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 0000000..cb867a5 --- /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 0000000..21474fb --- /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 0000000..43bd23e --- /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 0000000..9b76203 --- /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 0000000..5328b2f --- /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 0000000..6ecb190 --- /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 0000000..9408576 --- /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 0000000..ce69c84 --- /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 0000000..fa31486 --- /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 0000000..2be9ab0 --- /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 0000000..24b1a80 --- /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 0000000..c0a2060 --- /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 0000000..5ea22f1 --- /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 0000000..7517c6e --- /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 0000000..243ad5b --- /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 0000000..952f666 --- /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 0000000..79f6bd7 --- /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 0000000..5909d0c --- /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 0000000..c410753 --- /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 0000000..9541b62 --- /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 0000000..ffd79c9 --- /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 0000000..895b61c --- /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 0000000..5b6d52e --- /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 0000000..b2c68d2 --- /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 0000000..3122bc4 --- /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 0000000..de768c1 --- /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 0000000..8cca846 --- /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 0000000..3bf86ff --- /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 0000000..2b3a452 --- /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 0000000..143242f --- /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 0000000..4d7168c --- /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 0000000..11ee0f0 --- /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 0000000..d66003f --- /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 0000000..d69928a --- /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); +} + |