1 #include "headers.h" 2 3 static int 4 getlock(SmbBuffer *b, int large, ushort *pidp, uvlong *offsetp, uvlong *lengthp) 5 { 6 ulong ohigh, olow; 7 ulong lhigh, llow; 8 if (!smbbuffergets(b, pidp)) 9 return 0; 10 if (large && !smbbuffergetbytes(b, nil, 2)) 11 return 0; 12 if (large) { 13 if (!smbbuffergetl(b, &ohigh) || !smbbuffergetl(b, &olow) 14 || !smbbuffergetl(b, &lhigh) || !smbbuffergetl(b, &llow)) 15 return 0; 16 *offsetp = ((uvlong)ohigh << 32) | olow; 17 *lengthp = ((uvlong)lhigh << 32) | llow; 18 return 1; 19 } 20 if (!smbbuffergetl(b, &olow) || !smbbuffergetl(b, &llow)) 21 return 0; 22 *offsetp = olow; 23 *lengthp = llow; 24 return 1; 25 } 26 27 SmbProcessResult 28 smbcomlockingandx(SmbSession *s, SmbHeader *h, uchar *pdata, SmbBuffer *b) 29 { 30 uchar andxcommand; 31 ushort andxoffset; 32 ulong andxoffsetfixup; 33 ushort fid; 34 uchar locktype; 35 uchar oplocklevel; 36 ulong timeout; 37 ushort numberofunlocks; 38 ushort numberoflocks; 39 SmbTree *t; 40 SmbFile *f; 41 int l; 42 SmbProcessResult pr; 43 ulong backupoffset; 44 int large; 45 46 if (!smbcheckwordcount("comlockingandx", h, 8)) 47 return SmbProcessResultFormat; 48 49 andxcommand = *pdata++; 50 pdata++; 51 andxoffset = smbnhgets(pdata); pdata += 2; 52 fid = smbnhgets(pdata); pdata += 2; 53 locktype = *pdata++; 54 oplocklevel = *pdata++; 55 timeout = smbnhgetl(pdata); pdata += 4; 56 numberofunlocks = smbnhgets(pdata); pdata += 2; 57 numberoflocks = smbnhgets(pdata); 58 smblogprint(h->command, "smbcomlockingandx: fid 0x%.4ux locktype 0x%.2ux oplocklevel 0x%.2ux timeout %lud numberofunlocks %d numberoflocks %ud\n", 59 fid, locktype, oplocklevel, timeout, numberofunlocks, numberoflocks); 60 large = locktype & 0x10; 61 locktype &= ~0x10; 62 if (locktype != 0 || oplocklevel != 0) { 63 smblogprint(-1, "smbcomlockingandx: locktype 0x%.2ux unimplemented\n", locktype); 64 return SmbProcessResultUnimp; 65 } 66 if (oplocklevel != 0) { 67 smblogprint(-1, "smbcomlockingandx: oplocklevel 0x%.2ux unimplemented\n", oplocklevel); 68 return SmbProcessResultUnimp; 69 } 70 t = smbidmapfind(s->tidmap, h->tid); 71 if (t == nil) { 72 smbseterror(s, ERRSRV, ERRinvtid); 73 error: 74 return SmbProcessResultError; 75 } 76 f = smbidmapfind(s->fidmap, fid); 77 if (f == nil) { 78 smbseterror(s, ERRDOS, ERRbadfid); 79 goto error; 80 } 81 backupoffset = smbbufferreadoffset(b); 82 for (l = 0; l < numberofunlocks; l++) { 83 ushort pid; 84 uvlong offset; 85 uvlong length; 86 if (!getlock(b, large, &pid, &offset, &length)) { 87 pr = SmbProcessResultFormat; 88 goto done; 89 } 90 smblogprint(h->command, "smbcomlockingandx: unlock pid 0x%.4ux offset %llud length %llud\n", 91 pid, offset, length); 92 smbsharedfileunlock(f->sf, s, h->pid, offset, offset + length); 93 } 94 for (l = 0; l < numberoflocks; l++) { 95 ushort pid; 96 uvlong offset; 97 uvlong length; 98 if (!getlock(b, large, &pid, &offset, &length)) { 99 pr = SmbProcessResultFormat; 100 goto done; 101 } 102 smblogprint(h->command, "smbcomlockingandx: lock pid 0x%.4ux offset %llud length %llud\n", 103 pid, offset, length); 104 if (!smbsharedfilelock(f->sf, s, h->pid, offset, offset + length)) 105 break; 106 } 107 if (l < numberoflocks) { 108 ushort i; 109 ushort pid; 110 uvlong offset; 111 uvlong length; 112 smbbufferreadbackup(b, backupoffset); 113 for (i = 0; i < l; i++) { 114 assert(getlock(b, large, &pid, &offset, &length)); 115 smbsharedfileunlock(f->sf, s, h->pid, offset, offset + length); 116 } 117 smbseterror(s, ERRDOS, ERRlock); 118 goto error; 119 } 120 h->wordcount = 2; 121 if (!smbbufferputandxheader(s->response, h, &s->peerinfo, andxcommand, &andxoffsetfixup) 122 || !smbbufferputs(s->response, 0)) { // bytecount 0 123 pr = SmbProcessResultMisc; 124 goto done; 125 } 126 if (andxcommand != SMB_COM_NO_ANDX_COMMAND) 127 pr = smbchaincommand(s, h, andxoffsetfixup, andxcommand, andxoffset, b); 128 else 129 pr = SmbProcessResultReply; 130 done: 131 return pr; 132 } 133