1 #include "headers.h"
2
3 static int
getlock(SmbBuffer * b,int large,ushort * pidp,uvlong * offsetp,uvlong * lengthp)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
smbcomlockingandx(SmbSession * s,SmbHeader * h,uchar * pdata,SmbBuffer * b)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