summaryrefslogtreecommitdiffstats
path: root/sys/netsmb/smb_subr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netsmb/smb_subr.c')
-rw-r--r--sys/netsmb/smb_subr.c352
1 files changed, 352 insertions, 0 deletions
diff --git a/sys/netsmb/smb_subr.c b/sys/netsmb/smb_subr.c
new file mode 100644
index 0000000..f4634d4
--- /dev/null
+++ b/sys/netsmb/smb_subr.c
@@ -0,0 +1,352 @@
+/*
+ * 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.
+ *
+ * $FreeBSD$
+ */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/lock.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#include <sys/signalvar.h>
+#include <sys/mbuf.h>
+
+#include <sys/iconv.h>
+
+#include <netsmb/smb.h>
+#include <netsmb/smb_conn.h>
+#include <netsmb/smb_rq.h>
+#include <netsmb/smb_subr.h>
+
+MALLOC_DEFINE(M_SMBDATA, "SMBDATA", "Misc netsmb data");
+MALLOC_DEFINE(M_SMBSTR, "SMBSTR", "netsmb string data");
+MALLOC_DEFINE(M_SMBTEMP, "SMBTEMP", "Temp netsmb data");
+
+smb_unichar smb_unieol = 0;
+
+void
+smb_makescred(struct smb_cred *scred, struct thread *td, struct ucred *cred)
+{
+ if (td) {
+ scred->scr_td = td;
+ scred->scr_cred = cred ? cred : td->td_ucred;
+ } else {
+ scred->scr_td = NULL;
+ scred->scr_cred = cred ? cred : NULL;
+ }
+}
+
+int
+smb_proc_intr(struct proc *p)
+{
+ sigset_t tmpset;
+
+ if (p == NULL)
+ return 0;
+ tmpset = p->p_siglist;
+ SIGSETNAND(tmpset, p->p_sigmask);
+ SIGSETNAND(tmpset, p->p_sigignore);
+ if (SIGNOTEMPTY(p->p_siglist) && SMB_SIGMASK(tmpset))
+ return EINTR;
+ return 0;
+}
+
+char *
+smb_strdup(const char *s)
+{
+ char *p;
+ int len;
+
+ len = s ? strlen(s) + 1 : 1;
+ p = malloc(len, M_SMBSTR, M_WAITOK);
+ if (s)
+ bcopy(s, p, len);
+ else
+ *p = 0;
+ return p;
+}
+
+/*
+ * duplicate string from a user space.
+ */
+char *
+smb_strdupin(char *s, int maxlen)
+{
+ char *p, bt;
+ int len = 0;
+
+ for (p = s; ;p++) {
+ if (copyin(p, &bt, 1))
+ return NULL;
+ len++;
+ if (maxlen && len > maxlen)
+ return NULL;
+ if (bt == 0)
+ break;
+ }
+ p = malloc(len, M_SMBSTR, M_WAITOK);
+ copyin(s, p, len);
+ return p;
+}
+
+/*
+ * duplicate memory block from a user space.
+ */
+void *
+smb_memdupin(void *umem, int len)
+{
+ char *p;
+
+ if (len > 8 * 1024)
+ return NULL;
+ p = malloc(len, M_SMBSTR, M_WAITOK);
+ if (copyin(umem, p, len) == 0)
+ return p;
+ free(p, M_SMBSTR);
+ return NULL;
+}
+
+/*
+ * duplicate memory block in the kernel space.
+ */
+void *
+smb_memdup(const void *umem, int len)
+{
+ char *p;
+
+ if (len > 8 * 1024)
+ return NULL;
+ p = malloc(len, M_SMBSTR, M_WAITOK);
+ if (p == NULL)
+ return NULL;
+ bcopy(umem, p, len);
+ return p;
+}
+
+void
+smb_strfree(char *s)
+{
+ free(s, M_SMBSTR);
+}
+
+void
+smb_memfree(void *s)
+{
+ free(s, M_SMBSTR);
+}
+
+void *
+smb_zmalloc(unsigned long size, struct malloc_type *type, int flags)
+{
+
+ return malloc(size, type, flags | M_ZERO);
+}
+
+void
+smb_strtouni(u_int16_t *dst, const char *src)
+{
+ while (*src) {
+ *dst++ = htoles(*src++);
+ }
+ *dst = 0;
+}
+
+#ifdef SMB_SOCKETDATA_DEBUG
+void
+m_dumpm(struct mbuf *m) {
+ char *p;
+ int len;
+ printf("d=");
+ while(m) {
+ p=mtod(m,char *);
+ len=m->m_len;
+ printf("(%d)",len);
+ while(len--){
+ printf("%02x ",((int)*(p++)) & 0xff);
+ }
+ m=m->m_next;
+ };
+ printf("\n");
+}
+#endif
+
+int
+smb_maperror(int eclass, int eno)
+{
+ if (eclass == 0 && eno == 0)
+ return 0;
+ switch (eclass) {
+ case ERRDOS:
+ switch (eno) {
+ case ERRbadfunc:
+ case ERRbadmcb:
+ case ERRbadenv:
+ case ERRbadformat:
+ case ERRrmuns:
+ return EINVAL;
+ case ERRbadfile:
+ case ERRbadpath:
+ case ERRremcd:
+ case 66: /* nt returns it when share not available */
+ case 67: /* observed from nt4sp6 when sharename wrong */
+ return ENOENT;
+ case ERRnofids:
+ return EMFILE;
+ case ERRnoaccess:
+ case ERRbadshare:
+ return EACCES;
+ case ERRbadfid:
+ return EBADF;
+ case ERRnomem:
+ return ENOMEM; /* actually remote no mem... */
+ case ERRbadmem:
+ return EFAULT;
+ case ERRbadaccess:
+ return EACCES;
+ case ERRbaddata:
+ return E2BIG;
+ case ERRbaddrive:
+ case ERRnotready: /* nt */
+ return ENXIO;
+ case ERRdiffdevice:
+ return EXDEV;
+ case ERRnofiles:
+ return 0; /* eeof ? */
+ return ETXTBSY;
+ case ERRlock:
+ return EDEADLK;
+ case ERRfilexists:
+ return EEXIST;
+ case 123: /* dunno what is it, but samba maps as noent */
+ return ENOENT;
+ case 145: /* samba */
+ return ENOTEMPTY;
+ case 183:
+ return EEXIST;
+ }
+ break;
+ case ERRSRV:
+ switch (eno) {
+ case ERRerror:
+ return EINVAL;
+ case ERRbadpw:
+ return EAUTH;
+ case ERRaccess:
+ return EACCES;
+ case ERRinvnid:
+ return ENETRESET;
+ case ERRinvnetname:
+ SMBERROR("NetBIOS name is invalid\n");
+ return EAUTH;
+ case 3: /* reserved and returned */
+ return EIO;
+ case 2239: /* NT: account exists but disabled */
+ return EPERM;
+ }
+ break;
+ case ERRHRD:
+ switch (eno) {
+ case ERRnowrite:
+ return EROFS;
+ case ERRbadunit:
+ return ENODEV;
+ case ERRnotready:
+ case ERRbadcmd:
+ case ERRdata:
+ return EIO;
+ case ERRbadreq:
+ return EBADRPC;
+ case ERRbadshare:
+ return ETXTBSY;
+ case ERRlock:
+ return EDEADLK;
+ }
+ break;
+ }
+ SMBERROR("Unmapped error %d:%d\n", eclass, eno);
+ return EBADRPC;
+}
+
+static int
+smb_copy_iconv(struct mbchain *mbp, c_caddr_t src, caddr_t dst, int len)
+{
+ int outlen = len;
+
+ return iconv_conv((struct iconv_drv*)mbp->mb_udata, &src, &len, &dst, &outlen);
+}
+
+int
+smb_put_dmem(struct mbchain *mbp, struct smb_vc *vcp, const char *src,
+ int size, int caseopt)
+{
+ struct iconv_drv *dp = vcp->vc_toserver;
+
+ if (size == 0)
+ return 0;
+ if (dp == NULL) {
+ return mb_put_mem(mbp, src, size, MB_MSYSTEM);
+ }
+ mbp->mb_copy = smb_copy_iconv;
+ mbp->mb_udata = dp;
+ return mb_put_mem(mbp, src, size, MB_MCUSTOM);
+}
+
+int
+smb_put_dstring(struct mbchain *mbp, struct smb_vc *vcp, const char *src,
+ int caseopt)
+{
+ int error;
+
+ error = smb_put_dmem(mbp, vcp, src, strlen(src), caseopt);
+ if (error)
+ return error;
+ return mb_put_uint8(mbp, 0);
+}
+
+int
+smb_put_asunistring(struct smb_rq *rqp, const char *src)
+{
+ struct mbchain *mbp = &rqp->sr_rq;
+ struct iconv_drv *dp = rqp->sr_vc->vc_toserver;
+ u_char c;
+ int error;
+
+ while (*src) {
+ iconv_convmem(dp, &c, src++, 1);
+ error = mb_put_uint16le(mbp, c);
+ if (error)
+ return error;
+ }
+ return mb_put_uint16le(mbp, 0);
+}
OpenPOWER on IntegriCloud