1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2000-2001 Boris Popov 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/clock.h> 34 #include <sys/malloc.h> 35 #include <sys/time.h> 36 #include <sys/vnode.h> 37 #include <sys/sysctl.h> 38 #include <sys/iconv.h> 39 40 #include <netsmb/smb.h> 41 #include <netsmb/smb_conn.h> 42 #include <netsmb/smb_subr.h> 43 #include <netsmb/smb_rq.h> 44 #include <netsmb/smb_dev.h> 45 46 #include <fs/smbfs/smbfs.h> 47 #include <fs/smbfs/smbfs_node.h> 48 #include <fs/smbfs/smbfs_subr.h> 49 50 MALLOC_DEFINE(M_SMBFSDATA, "smbfs_data", "SMBFS private data"); 51 MALLOC_DEFINE(M_SMBFSCRED, "smbfs_cred", "SMBFS cred data"); 52 53 void 54 smb_time_local2server(struct timespec *tsp, int tzoff, u_long *seconds) 55 { 56 *seconds = tsp->tv_sec - tzoff * 60 /*- tz_minuteswest * 60 - 57 (wall_cmos_clock ? adjkerntz : 0)*/; 58 } 59 60 void 61 smb_time_server2local(u_long seconds, int tzoff, struct timespec *tsp) 62 { 63 tsp->tv_sec = seconds + tzoff * 60; 64 } 65 66 /* 67 * Number of seconds between 1970 and 1601 year 68 */ 69 static int64_t DIFF1970TO1601 = 11644473600ULL; 70 71 /* 72 * Time from server comes as UTC, so no need to use tz 73 */ 74 void 75 smb_time_NT2local(int64_t nsec, int tzoff, struct timespec *tsp) 76 { 77 smb_time_server2local(nsec / 10000000 - DIFF1970TO1601, 0, tsp); 78 } 79 80 void 81 smb_time_local2NT(struct timespec *tsp, int tzoff, int64_t *nsec) 82 { 83 u_long seconds; 84 85 smb_time_local2server(tsp, 0, &seconds); 86 *nsec = (((int64_t)(seconds) & ~1) + DIFF1970TO1601) * (int64_t)10000000; 87 } 88 89 void 90 smb_time_unix2dos(struct timespec *tsp, int tzoff, u_int16_t *ddp, 91 u_int16_t *dtp, u_int8_t *dhp) 92 { 93 struct timespec tt; 94 u_long t; 95 96 tt = *tsp; 97 smb_time_local2server(tsp, tzoff, &t); 98 tt.tv_sec = t; 99 timespec2fattime(&tt, 1, ddp, dtp, dhp); 100 } 101 102 void 103 smb_dos2unixtime(u_int dd, u_int dt, u_int dh, int tzoff, 104 struct timespec *tsp) 105 { 106 107 fattime2timespec(dd, dt, dh, 1, tsp); 108 smb_time_server2local(tsp->tv_sec, tzoff, tsp); 109 } 110 111 int 112 smbfs_fullpath(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *dnp, 113 const char *name, int nmlen) 114 { 115 int caseopt = SMB_CS_NONE; 116 int error; 117 118 if (SMB_UNICODE_STRINGS(vcp)) { 119 error = mb_put_padbyte(mbp); 120 if (error) 121 return error; 122 } 123 if (SMB_DIALECT(vcp) < SMB_DIALECT_LANMAN1_0) 124 caseopt |= SMB_CS_UPPER; 125 if (dnp != NULL) { 126 error = smb_put_dmem(mbp, vcp, dnp->n_rpath, dnp->n_rplen, 127 caseopt); 128 if (error) 129 return error; 130 if (name) { 131 /* Put the separator */ 132 if (SMB_UNICODE_STRINGS(vcp)) 133 error = mb_put_uint16le(mbp, '\\'); 134 else 135 error = mb_put_uint8(mbp, '\\'); 136 if (error) 137 return error; 138 /* Put the name */ 139 error = smb_put_dmem(mbp, vcp, name, nmlen, caseopt); 140 if (error) 141 return error; 142 } 143 } 144 /* Put NULL terminator. */ 145 if (SMB_UNICODE_STRINGS(vcp)) 146 error = mb_put_uint16le(mbp, 0); 147 else 148 error = mb_put_uint8(mbp, 0); 149 return error; 150 } 151 152 int 153 smbfs_fname_tolocal(struct smb_vc *vcp, char *name, int *nmlen, int caseopt) 154 { 155 int copt = (caseopt == SMB_CS_LOWER ? KICONV_FROM_LOWER : 156 (caseopt == SMB_CS_UPPER ? KICONV_FROM_UPPER : 0)); 157 int error = 0; 158 size_t ilen = *nmlen; 159 size_t olen; 160 char *ibuf = name; 161 char outbuf[SMB_MAXFNAMELEN]; 162 char *obuf = outbuf; 163 164 if (vcp->vc_tolocal) { 165 olen = sizeof(outbuf); 166 bzero(outbuf, sizeof(outbuf)); 167 168 /* 169 error = iconv_conv_case 170 (vcp->vc_tolocal, NULL, NULL, &obuf, &olen, copt); 171 if (error) return error; 172 */ 173 174 error = iconv_conv_case(vcp->vc_tolocal, 175 __DECONST(const char **, &ibuf), &ilen, &obuf, &olen, copt); 176 if (error && SMB_UNICODE_STRINGS(vcp)) { 177 /* 178 * If using unicode, leaving a file name as it was when 179 * convert fails will cause a problem because the file name 180 * will contain NULL. 181 * Here, put '?' and give converted file name. 182 */ 183 *obuf = '?'; 184 olen--; 185 error = 0; 186 } 187 if (!error) { 188 *nmlen = sizeof(outbuf) - olen; 189 memcpy(name, outbuf, *nmlen); 190 } 191 } 192 return error; 193 } 194 195 void * 196 smbfs_malloc_scred(void) 197 { 198 return (malloc(sizeof(struct smb_cred), M_SMBFSCRED, M_WAITOK)); 199 } 200 201 void 202 smbfs_free_scred(void *scred) 203 { 204 free(scred, M_SMBFSCRED); 205 } 206