Print this page
NEX-14666 Need to provide SMB 2.1 Client
NEX-17187 panic in smbfs_acl_store
NEX-17231 smbfs create xattr files finds wrong file
NEX-17224 smbfs lookup EINVAL should be ENOENT
NEX-17260 SMB1 client fails to list directory after NEX-14666
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
and: (cleanup)


  18  *    without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30  * SUCH DAMAGE.
  31  *
  32  * $Id: smbfs_subr.c,v 1.18 2005/02/02 00:22:23 lindak Exp $
  33  */
  34 
  35 /*
  36  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  37  * Use is subject to license terms.


  38  */
  39 
  40 /*
  41  * Time conversion functions (to/from DOS, NT times)
  42  * From BSD/Darwin smbfs_subr.c
  43  */
  44 
  45 #include <sys/param.h>
  46 #include <sys/systm.h>
  47 #include <sys/time.h>
  48 #include <sys/vnode.h>
  49 #include <sys/sunddi.h>
  50 
  51 #include <netsmb/smb_osdep.h>
  52 
  53 #include <netsmb/smb.h>
  54 #include <netsmb/smb_conn.h>
  55 #include <netsmb/smb_subr.h>
  56 
  57 /*
  58  * Time & date conversion routines taken from msdosfs. Although leap
  59  * year calculation is bogus, it's sufficient before 2100 :)
  60  */
  61 /*
  62  * This is the format of the contents of the deTime field in the direntry
  63  * structure.
  64  * We don't use bitfields because we don't know how compilers for
  65  * arbitrary machines will lay them out.
  66  */
  67 #define DT_2SECONDS_MASK        0x1F    /* seconds divided by 2 */
  68 #define DT_2SECONDS_SHIFT       0
  69 #define DT_MINUTES_MASK         0x7E0   /* minutes */
  70 #define DT_MINUTES_SHIFT        5
  71 #define DT_HOURS_MASK           0xF800  /* hours */
  72 #define DT_HOURS_SHIFT          11
  73 
  74 /*
  75  * This is the format of the contents of the deDate field in the direntry
  76  * structure.
  77  */
  78 #define DD_DAY_MASK             0x1F    /* day of month */
  79 #define DD_DAY_SHIFT            0
  80 #define DD_MONTH_MASK           0x1E0   /* month */
  81 #define DD_MONTH_SHIFT          5
  82 #define DD_YEAR_MASK            0xFE00  /* year - 1980 */
  83 #define DD_YEAR_SHIFT           9
  84 /*
  85  * Total number of days that have passed for each month in a regular year.
  86  */
  87 static ushort_t regyear[] = {
  88         31, 59, 90, 120, 151, 181,
  89         212, 243, 273, 304, 334, 365
  90 };
  91 
  92 /*
  93  * Total number of days that have passed for each month in a leap year.
  94  */
  95 static ushort_t leapyear[] = {
  96         31, 60, 91, 121, 152, 182,
  97         213, 244, 274, 305, 335, 366
  98 };
  99 
 100 /*
 101  * Variables used to remember parts of the last time conversion.  Maybe we
 102  * can avoid a full conversion.
 103  */
 104 static ulong_t  lasttime;
 105 static ulong_t  lastday;
 106 static ushort_t lastddate;
 107 static ushort_t lastdtime;
 108 
 109 /* Lock for the lastxxx variables */
 110 static kmutex_t lastdt_lock;
 111 
 112 /*
 113  * Number of seconds between 1970 and 1601 year
 114  * (134774 days)
 115  */
 116 const uint64_t DIFF1970TO1601 = 11644473600ULL;
 117 const uint32_t TEN_MIL = 10000000UL;
 118 
 119 /*
 120  * Convert NT time (tenths of microseconds since 1601)
 121  * to Unix seconds+nanoseconds since 1970.  Any time
 122  * earlier than 1970 is converted to Unix time zero.
 123  * Both are GMT-based (no time zone adjustments).
 124  */
 125 void
 126 smb_time_NT2local(uint64_t nt_time, struct timespec *tsp)
 127 {
 128         uint64_t nt_sec;        /* seconds */
 129         uint64_t nt_tus;        /* tenths of uSec. */
 130 
 131         /* Optimize time zero. */
 132         if (nt_time == 0) {


 175  * Time zone conversion stuff, only used in old dialects.
 176  * Don't adjust time zero for either conversion.
 177  */
 178 void
 179 smb_time_local2server(struct timespec *tsp, int tzoff, long *seconds)
 180 {
 181         if (tsp->tv_sec <= (tzoff * 60))
 182                 *seconds = 0;
 183         else
 184                 *seconds = tsp->tv_sec - (tzoff * 60);
 185 }
 186 
 187 void
 188 smb_time_server2local(ulong_t seconds, int tzoff, struct timespec *tsp)
 189 {
 190         if (seconds == 0)
 191                 tsp->tv_sec = 0;
 192         else
 193                 tsp->tv_sec = seconds + tzoff * 60;
 194         tsp->tv_nsec = 0;
 195 }
 196 
 197 /*
 198  * Time conversions to/from DOS format, for old dialects.
 199  */
 200 
 201 void
 202 smb_time_unix2dos(struct timespec *tsp, int tzoff, u_int16_t *ddp,
 203         u_int16_t *dtp, u_int8_t *dhp)
 204 {
 205         long t;
 206         ulong_t days, year, month, inc;
 207         ushort_t *months;
 208 
 209         mutex_enter(&lastdt_lock);
 210 
 211         /*
 212          * If the time from the last conversion is the same as now, then
 213          * skip the computations and use the saved result.
 214          */
 215         smb_time_local2server(tsp, tzoff, &t);
 216         t &= ~1;
 217         if (lasttime != t) {
 218                 lasttime = t;
 219                 if (t < 0) {
 220                         /*
 221                          * This is before 1970, so it's before 1980,
 222                          * and can't be represented as a DOS time.
 223                          * Just represent it as the DOS epoch.
 224                          */
 225                         lastdtime = 0;
 226                         lastddate = (1 << DD_DAY_SHIFT)
 227                             + (1 << DD_MONTH_SHIFT)
 228                             + ((1980 - 1980) << DD_YEAR_SHIFT);
 229                 } else {
 230                         lastdtime = (((t / 2) % 30) << DT_2SECONDS_SHIFT)
 231                             + (((t / 60) % 60) << DT_MINUTES_SHIFT)
 232                             + (((t / 3600) % 24) << DT_HOURS_SHIFT);
 233 
 234                         /*
 235                          * If the number of days since 1970 is the same as
 236                          * the last time we did the computation then skip
 237                          * all this leap year and month stuff.
 238                          */
 239                         days = t / (24 * 60 * 60);
 240                         if (days != lastday) {
 241                                 lastday = days;
 242                                 for (year = 1970; ; year++) {
 243                                         /*
 244                                          * XXX - works in 2000, but won't
 245                                          * work in 2100.
 246                                          */
 247                                         inc = year & 0x03 ? 365 : 366;
 248                                         if (days < inc)
 249                                                 break;
 250                                         days -= inc;
 251                                 }
 252                                 /*
 253                                  * XXX - works in 2000, but won't work in 2100.
 254                                  */
 255                                 months = year & 0x03 ? regyear : leapyear;
 256                                 for (month = 0; days >= months[month]; month++)
 257                                         ;
 258                                 if (month > 0)
 259                                         days -= months[month - 1];
 260                                 lastddate = ((days + 1) << DD_DAY_SHIFT)
 261                                     + ((month + 1) << DD_MONTH_SHIFT);
 262                                 /*
 263                                  * Remember DOS's idea of time is relative
 264                                  * to 1980, but UN*X's is relative to 1970.
 265                                  * If somehow we get a time before 1980 then
 266                                  * don't give totally crazy results.
 267                                  */
 268                                 if (year > 1980)
 269                                         lastddate += (year - 1980) <<
 270                                             DD_YEAR_SHIFT;
 271                         }
 272                 }
 273         }
 274         if (dhp)
 275                 *dhp = (tsp->tv_sec & 1) * 100 + tsp->tv_nsec / 10000000;
 276 
 277         *ddp = lastddate;
 278         *dtp = lastdtime;
 279 
 280         mutex_exit(&lastdt_lock);
 281 }
 282 
 283 /*
 284  * The number of seconds between Jan 1, 1970 and Jan 1, 1980. In that
 285  * interval there were 8 regular years and 2 leap years.
 286  */
 287 #define SECONDSTO1980   (((8 * 365) + (2 * 366)) * (24 * 60 * 60))
 288 
 289 static ushort_t lastdosdate;
 290 static ulong_t  lastseconds;
 291 
 292 void
 293 smb_dos2unixtime(uint_t dd, uint_t dt, uint_t dh, int tzoff,
 294         struct timespec *tsp)
 295 {
 296         ulong_t seconds;
 297         ulong_t month;
 298         ulong_t year;
 299         ulong_t days;
 300         ushort_t *months;
 301 
 302         if (dd == 0) {
 303                 tsp->tv_sec = 0;
 304                 tsp->tv_nsec = 0;
 305                 return;
 306         }
 307         seconds = (((dt & DT_2SECONDS_MASK) >> DT_2SECONDS_SHIFT) << 1)
 308             + ((dt & DT_MINUTES_MASK) >> DT_MINUTES_SHIFT) * 60
 309             + ((dt & DT_HOURS_MASK) >> DT_HOURS_SHIFT) * 3600
 310             + dh / 100;
 311 
 312         /*
 313          * If the year, month, and day from the last conversion are the
 314          * same then use the saved value.
 315          */
 316         mutex_enter(&lastdt_lock);
 317         if (lastdosdate != dd) {
 318                 lastdosdate = (ushort_t)dd;
 319                 days = 0;
 320                 year = (dd & DD_YEAR_MASK) >> DD_YEAR_SHIFT;
 321                 days = year * 365;
 322                 days += year / 4 + 1;   /* add in leap days */
 323                 /*
 324                  * XXX - works in 2000, but won't work in 2100.
 325                  */
 326                 if ((year & 0x03) == 0)
 327                         days--;         /* if year is a leap year */
 328                 months = year & 0x03 ? regyear : leapyear;
 329                 month = (dd & DD_MONTH_MASK) >> DD_MONTH_SHIFT;
 330                 if (month < 1 || month > 12) {
 331                         month = 1;
 332                 }
 333                 if (month > 1)
 334                         days += months[month - 2];
 335                 days += ((dd & DD_DAY_MASK) >> DD_DAY_SHIFT) - 1;
 336                 lastseconds = (days * 24 * 60 * 60) + SECONDSTO1980;
 337         }
 338         smb_time_server2local(seconds + lastseconds, tzoff, tsp);
 339         tsp->tv_nsec = (dh % 100) * 10000000;
 340         mutex_exit(&lastdt_lock);
 341 }
 342 
 343 void
 344 smb_time_init(void)
 345 {
 346         mutex_init(&lastdt_lock, NULL, MUTEX_DEFAULT, NULL);
 347 }
 348 
 349 void
 350 smb_time_fini(void)
 351 {
 352         mutex_destroy(&lastdt_lock);
 353 }


  18  *    without specific prior written permission.
  19  *
  20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  30  * SUCH DAMAGE.
  31  *
  32  * $Id: smbfs_subr.c,v 1.18 2005/02/02 00:22:23 lindak Exp $
  33  */
  34 
  35 /*
  36  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  37  * Use is subject to license terms.
  38  *
  39  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  40  */
  41 
  42 /*
  43  * Time conversion functions (to/from DOS, NT times)
  44  * From BSD/Darwin smbfs_subr.c
  45  */
  46 
  47 #include <sys/param.h>
  48 #include <sys/systm.h>
  49 #include <sys/time.h>
  50 #include <sys/vnode.h>
  51 #include <sys/sunddi.h>
  52 
  53 #include <netsmb/smb_osdep.h>
  54 
  55 #include <netsmb/smb.h>
  56 #include <netsmb/smb_conn.h>
  57 #include <netsmb/smb_subr.h>
  58 
  59 /*























































  60  * Number of seconds between 1970 and 1601 year
  61  * (134774 days)
  62  */
  63 const uint64_t DIFF1970TO1601 = 11644473600ULL;
  64 const uint32_t TEN_MIL = 10000000UL;
  65 
  66 /*
  67  * Convert NT time (tenths of microseconds since 1601)
  68  * to Unix seconds+nanoseconds since 1970.  Any time
  69  * earlier than 1970 is converted to Unix time zero.
  70  * Both are GMT-based (no time zone adjustments).
  71  */
  72 void
  73 smb_time_NT2local(uint64_t nt_time, struct timespec *tsp)
  74 {
  75         uint64_t nt_sec;        /* seconds */
  76         uint64_t nt_tus;        /* tenths of uSec. */
  77 
  78         /* Optimize time zero. */
  79         if (nt_time == 0) {


 122  * Time zone conversion stuff, only used in old dialects.
 123  * Don't adjust time zero for either conversion.
 124  */
 125 void
 126 smb_time_local2server(struct timespec *tsp, int tzoff, long *seconds)
 127 {
 128         if (tsp->tv_sec <= (tzoff * 60))
 129                 *seconds = 0;
 130         else
 131                 *seconds = tsp->tv_sec - (tzoff * 60);
 132 }
 133 
 134 void
 135 smb_time_server2local(ulong_t seconds, int tzoff, struct timespec *tsp)
 136 {
 137         if (seconds == 0)
 138                 tsp->tv_sec = 0;
 139         else
 140                 tsp->tv_sec = seconds + tzoff * 60;
 141         tsp->tv_nsec = 0;






























































































































































 142 }