diff options
author | sheldonh <sheldonh@FreeBSD.org> | 2001-12-14 11:06:03 +0000 |
---|---|---|
committer | sheldonh <sheldonh@FreeBSD.org> | 2001-12-14 11:06:03 +0000 |
commit | 4e260b134ff188548ec2c8a16a37570a4abf1257 (patch) | |
tree | 672d7786f89ed3b67f221098cb86cf0bc53ad5e3 /contrib/smbfs/lib/smb | |
download | FreeBSD-src-4e260b134ff188548ec2c8a16a37570a4abf1257.zip FreeBSD-src-4e260b134ff188548ec2c8a16a37570a4abf1257.tar.gz |
Import smbfs-1.4.1.
This is Boris Popov's SMB/CIFS file system implementation for FreeBSD.
Obtained from: Boris Popov via ftp://ftp.butya.kz/pub/smbfs/
Diffstat (limited to 'contrib/smbfs/lib/smb')
-rw-r--r-- | contrib/smbfs/lib/smb/Makefile | 50 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/cfopt.c | 123 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/ctx.c | 773 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/file.c | 80 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/kiconv.c | 61 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/mbuf.c | 467 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/nb.c | 191 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/nb_name.c | 198 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/nb_net.c | 201 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/nbns_rq.c | 380 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/nls.c | 214 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/print.c | 97 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/rap.c | 404 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/rcfile.c | 499 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/rcfile_priv.h | 20 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/rq.c | 179 | ||||
-rw-r--r-- | contrib/smbfs/lib/smb/subr.c | 243 |
17 files changed, 4180 insertions, 0 deletions
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; +} |