1139776Simp/*- 2206361Sjoel * Copyright (c) 2000-2001 Boris Popov 375374Sbp * All rights reserved. 475374Sbp * 575374Sbp * Redistribution and use in source and binary forms, with or without 675374Sbp * modification, are permitted provided that the following conditions 775374Sbp * are met: 875374Sbp * 1. Redistributions of source code must retain the above copyright 975374Sbp * notice, this list of conditions and the following disclaimer. 1075374Sbp * 2. Redistributions in binary form must reproduce the above copyright 1175374Sbp * notice, this list of conditions and the following disclaimer in the 1275374Sbp * documentation and/or other materials provided with the distribution. 1375374Sbp * 1475374Sbp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1575374Sbp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1675374Sbp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1775374Sbp * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1875374Sbp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1975374Sbp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2075374Sbp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2175374Sbp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2275374Sbp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2375374Sbp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2475374Sbp * SUCH DAMAGE. 2575374Sbp * 2675374Sbp * $FreeBSD$ 2775374Sbp */ 2875374Sbp#include <sys/param.h> 2975374Sbp#include <sys/systm.h> 3075374Sbp#include <sys/kernel.h> 31163652Sphk#include <sys/clock.h> 3275374Sbp#include <sys/malloc.h> 3375374Sbp#include <sys/time.h> 3475374Sbp#include <sys/vnode.h> 3575374Sbp#include <sys/sysctl.h> 3675374Sbp#include <sys/iconv.h> 3775374Sbp 3875374Sbp#include <netsmb/smb.h> 3975374Sbp#include <netsmb/smb_conn.h> 4075374Sbp#include <netsmb/smb_subr.h> 4175374Sbp#include <netsmb/smb_rq.h> 4275374Sbp#include <netsmb/smb_dev.h> 4375374Sbp 4475374Sbp#include <fs/smbfs/smbfs.h> 4575374Sbp#include <fs/smbfs/smbfs_node.h> 4675374Sbp#include <fs/smbfs/smbfs_subr.h> 4775374Sbp 48151897SrwatsonMALLOC_DEFINE(M_SMBFSDATA, "smbfs_data", "SMBFS private data"); 49242386SdavideMALLOC_DEFINE(M_SMBFSCRED, "smbfs_cred", "SMBFS cred data"); 5075374Sbp 5175374Sbpvoid 5275374Sbpsmb_time_local2server(struct timespec *tsp, int tzoff, u_long *seconds) 5375374Sbp{ 54110299Sphk *seconds = tsp->tv_sec - tzoff * 60 /*- tz_minuteswest * 60 - 5575374Sbp (wall_cmos_clock ? adjkerntz : 0)*/; 5675374Sbp} 5775374Sbp 5875374Sbpvoid 5975374Sbpsmb_time_server2local(u_long seconds, int tzoff, struct timespec *tsp) 6075374Sbp{ 6175374Sbp tsp->tv_sec = seconds + tzoff * 60; 62110299Sphk /*+ tz_minuteswest * 60 + (wall_cmos_clock ? adjkerntz : 0)*/; 6375374Sbp} 6475374Sbp 6575374Sbp/* 6675374Sbp * Number of seconds between 1970 and 1601 year 6775374Sbp */ 68145974Sanholtstatic int64_t DIFF1970TO1601 = 11644473600ULL; 6975374Sbp 7075374Sbp/* 7175374Sbp * Time from server comes as UTC, so no need to use tz 7275374Sbp */ 7375374Sbpvoid 7475374Sbpsmb_time_NT2local(int64_t nsec, int tzoff, struct timespec *tsp) 7575374Sbp{ 7675374Sbp smb_time_server2local(nsec / 10000000 - DIFF1970TO1601, 0, tsp); 7775374Sbp} 7875374Sbp 7975374Sbpvoid 8075374Sbpsmb_time_local2NT(struct timespec *tsp, int tzoff, int64_t *nsec) 8175374Sbp{ 8275374Sbp u_long seconds; 8375374Sbp 8475374Sbp smb_time_local2server(tsp, 0, &seconds); 8575374Sbp *nsec = (((int64_t)(seconds) & ~1) + DIFF1970TO1601) * (int64_t)10000000; 8675374Sbp} 8775374Sbp 8875374Sbpvoid 8975374Sbpsmb_time_unix2dos(struct timespec *tsp, int tzoff, u_int16_t *ddp, 9075374Sbp u_int16_t *dtp, u_int8_t *dhp) 9175374Sbp{ 92163652Sphk struct timespec tt; 93163652Sphk u_long t; 9475374Sbp 95163652Sphk tt = *tsp; 9675374Sbp smb_time_local2server(tsp, tzoff, &t); 97163652Sphk tt.tv_sec = t; 98163652Sphk timespec2fattime(&tt, 1, ddp, dtp, dhp); 9975374Sbp} 10075374Sbp 10175374Sbpvoid 10275374Sbpsmb_dos2unixtime(u_int dd, u_int dt, u_int dh, int tzoff, 10375374Sbp struct timespec *tsp) 10475374Sbp{ 10575374Sbp 106163652Sphk fattime2timespec(dd, dt, dh, 1, tsp); 107163652Sphk smb_time_server2local(tsp->tv_sec, tzoff, tsp); 10875374Sbp} 10975374Sbp 11075374Sbpint 11175374Sbpsmbfs_fullpath(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *dnp, 11275374Sbp const char *name, int nmlen) 11375374Sbp{ 11475374Sbp int caseopt = SMB_CS_NONE; 11575374Sbp int error; 11675374Sbp 117227650Skevlo if (SMB_UNICODE_STRINGS(vcp)) { 118227650Skevlo error = mb_put_padbyte(mbp); 119227650Skevlo if (error) 120227650Skevlo return error; 121227650Skevlo } 12275374Sbp if (SMB_DIALECT(vcp) < SMB_DIALECT_LANMAN1_0) 12375374Sbp caseopt |= SMB_CS_UPPER; 12475374Sbp if (dnp != NULL) { 125243396Sdavide error = smb_put_dmem(mbp, vcp, dnp->n_rpath, dnp->n_rplen, 126243396Sdavide caseopt); 12775374Sbp if (error) 12875374Sbp return error; 129243396Sdavide if (name) { 130243396Sdavide /* Put the separator */ 131243396Sdavide if (SMB_UNICODE_STRINGS(vcp)) 132243396Sdavide error = mb_put_uint16le(mbp, '\\'); 133243396Sdavide else 134243396Sdavide error = mb_put_uint8(mbp, '\\'); 135243396Sdavide if (error) 136243396Sdavide return error; 137243396Sdavide /* Put the name */ 138243396Sdavide error = smb_put_dmem(mbp, vcp, name, nmlen, caseopt); 139243396Sdavide if (error) 140243396Sdavide return error; 141243396Sdavide } 14275374Sbp } 143243396Sdavide /* Put NULL terminator. */ 144243396Sdavide if (SMB_UNICODE_STRINGS(vcp)) 145243396Sdavide error = mb_put_uint16le(mbp, 0); 146243396Sdavide else 147227650Skevlo error = mb_put_uint8(mbp, 0); 14875374Sbp return error; 14975374Sbp} 15075374Sbp 15175374Sbpint 152145872Stakawatasmbfs_fname_tolocal(struct smb_vc *vcp, char *name, int *nmlen, int caseopt) 15375374Sbp{ 154145872Stakawata int copt = (caseopt == SMB_CS_LOWER ? KICONV_FROM_LOWER : 155145872Stakawata (caseopt == SMB_CS_UPPER ? KICONV_FROM_UPPER : 0)); 156145872Stakawata int error = 0; 157145900Stakawata size_t ilen = *nmlen; 158145900Stakawata size_t olen; 159145872Stakawata char *ibuf = name; 160145872Stakawata char outbuf[SMB_MAXFNAMELEN]; 161145872Stakawata char *obuf = outbuf; 162145872Stakawata 163145872Stakawata if (vcp->vc_tolocal) { 164145872Stakawata olen = sizeof(outbuf); 165145872Stakawata bzero(outbuf, sizeof(outbuf)); 166145872Stakawata 167145872Stakawata /* 168145872Stakawata error = iconv_conv_case 169145872Stakawata (vcp->vc_tolocal, NULL, NULL, &obuf, &olen, copt); 170145872Stakawata if (error) return error; 171145872Stakawata */ 172145872Stakawata 173278435Sdim error = iconv_conv_case(vcp->vc_tolocal, 174278435Sdim __DECONST(const char **, &ibuf), &ilen, &obuf, &olen, copt); 175227650Skevlo if (error && SMB_UNICODE_STRINGS(vcp)) { 176227650Skevlo /* 177227650Skevlo * If using unicode, leaving a file name as it was when 178227650Skevlo * convert fails will cause a problem because the file name 179227650Skevlo * will contain NULL. 180227650Skevlo * Here, put '?' and give converted file name. 181227650Skevlo */ 182227650Skevlo *obuf = '?'; 183227650Skevlo olen--; 184227650Skevlo error = 0; 185227650Skevlo } 186145872Stakawata if (!error) { 187145872Stakawata *nmlen = sizeof(outbuf) - olen; 188145872Stakawata memcpy(name, outbuf, *nmlen); 189145872Stakawata } 190145872Stakawata } 191145872Stakawata return error; 19275374Sbp} 193242386Sdavide 194242386Sdavidevoid * 195242386Sdavidesmbfs_malloc_scred(void) 196242386Sdavide{ 197242386Sdavide return (malloc(sizeof(struct smb_cred), M_SMBFSCRED, M_WAITOK)); 198242386Sdavide} 199242386Sdavide 200242386Sdavidevoid 201242386Sdavidesmbfs_free_scred(void *scred) 202242386Sdavide{ 203242386Sdavide free(scred, M_SMBFSCRED); 204242386Sdavide} 205