1671dfc47SDavid du Colombier #include <u.h>
2671dfc47SDavid du Colombier #include <libc.h>
3671dfc47SDavid du Colombier #include <fcall.h>
4671dfc47SDavid du Colombier #include <thread.h>
5671dfc47SDavid du Colombier #include <9p.h>
6671dfc47SDavid du Colombier #include "cifs.h"
7671dfc47SDavid du Colombier
8671dfc47SDavid du Colombier static char magic[] = { 0xff, 'S', 'M', 'B' };
9671dfc47SDavid du Colombier
10671dfc47SDavid du Colombier Session *
cifsdial(char * host,char * called,char * sysname)11671dfc47SDavid du Colombier cifsdial(char *host, char *called, char *sysname)
12671dfc47SDavid du Colombier {
13671dfc47SDavid du Colombier int nbt, fd;
14671dfc47SDavid du Colombier char *addr;
15671dfc47SDavid du Colombier Session *s;
16671dfc47SDavid du Colombier
17671dfc47SDavid du Colombier if(Debug)
18671dfc47SDavid du Colombier fprint(2, "cifsdial: host=%s called=%s sysname=%s\n", host, called, sysname);
19671dfc47SDavid du Colombier
20671dfc47SDavid du Colombier if((addr = netmkaddr(host, "tcp", "cifs")) == nil)
21671dfc47SDavid du Colombier return nil;
22671dfc47SDavid du Colombier
23671dfc47SDavid du Colombier nbt = 0;
24671dfc47SDavid du Colombier if((fd = dial(addr, nil, nil, nil)) == -1){
25671dfc47SDavid du Colombier nbt = 1;
26671dfc47SDavid du Colombier if((fd = nbtdial(host, called, sysname)) == -1)
27671dfc47SDavid du Colombier return nil;
28671dfc47SDavid du Colombier }
29671dfc47SDavid du Colombier
30671dfc47SDavid du Colombier s = emalloc9p(sizeof(Session));
31671dfc47SDavid du Colombier memset(s, 0, sizeof(Session));
32671dfc47SDavid du Colombier
33671dfc47SDavid du Colombier s->fd = fd;
34671dfc47SDavid du Colombier s->nbt = nbt;
35671dfc47SDavid du Colombier s->mtu = MTU;
36671dfc47SDavid du Colombier s->pid = getpid();
37671dfc47SDavid du Colombier s->mid = time(nil) ^ getpid();
38671dfc47SDavid du Colombier s->uid = NO_UID;
39671dfc47SDavid du Colombier s->seq = 0;
40671dfc47SDavid du Colombier s->seqrun = 0;
41671dfc47SDavid du Colombier s->secmode = SECMODE_SIGN_ENABLED; /* hope for the best */
42671dfc47SDavid du Colombier s->flags2 = FL2_KNOWS_LONG_NAMES | FL2_HAS_LONG_NAMES | FL2_PAGEING_IO;
43671dfc47SDavid du Colombier s->macidx = -1;
44671dfc47SDavid du Colombier
45671dfc47SDavid du Colombier return s;
46671dfc47SDavid du Colombier }
47671dfc47SDavid du Colombier
48671dfc47SDavid du Colombier void
cifsclose(Session * s)49671dfc47SDavid du Colombier cifsclose(Session *s)
50671dfc47SDavid du Colombier {
51671dfc47SDavid du Colombier if(s->fd)
52671dfc47SDavid du Colombier close(s->fd);
53671dfc47SDavid du Colombier free(s);
54671dfc47SDavid du Colombier }
55671dfc47SDavid du Colombier
56671dfc47SDavid du Colombier Pkt *
cifshdr(Session * s,Share * sp,int cmd)57671dfc47SDavid du Colombier cifshdr(Session *s, Share *sp, int cmd)
58671dfc47SDavid du Colombier {
59671dfc47SDavid du Colombier Pkt *p;
60671dfc47SDavid du Colombier int sign, tid, dfs;
61671dfc47SDavid du Colombier
62671dfc47SDavid du Colombier dfs = 0;
63671dfc47SDavid du Colombier tid = NO_TID;
64671dfc47SDavid du Colombier Active = IDLE_TIME;
65*976d3a68SDavid du Colombier werrstr("");
66671dfc47SDavid du Colombier sign = s->secmode & SECMODE_SIGN_ENABLED? FL2_PACKET_SIGNATURES: 0;
67671dfc47SDavid du Colombier
68671dfc47SDavid du Colombier if(sp){
69671dfc47SDavid du Colombier tid = sp->tid;
70671dfc47SDavid du Colombier // FIXME! if(sp->options & SMB_SHARE_IS_IN_DFS)
71671dfc47SDavid du Colombier // FIXME! dfs = FL2_DFS;
72671dfc47SDavid du Colombier }
73671dfc47SDavid du Colombier
74671dfc47SDavid du Colombier p = emalloc9p(sizeof(Pkt) + MTU);
75671dfc47SDavid du Colombier memset(p, 0, sizeof(Pkt) +MTU);
76671dfc47SDavid du Colombier
77671dfc47SDavid du Colombier p->buf = (uchar *)p + sizeof(Pkt);
78671dfc47SDavid du Colombier p->s = s;
79671dfc47SDavid du Colombier
80671dfc47SDavid du Colombier qlock(&s->seqlock);
81671dfc47SDavid du Colombier if(s->seqrun){
82671dfc47SDavid du Colombier p->seq = s->seq;
83671dfc47SDavid du Colombier s->seq = (s->seq + 2) % 0x10000;
84671dfc47SDavid du Colombier }
85671dfc47SDavid du Colombier qunlock(&s->seqlock);
86671dfc47SDavid du Colombier
87671dfc47SDavid du Colombier nbthdr(p);
88671dfc47SDavid du Colombier pmem(p, magic, nelem(magic));
89671dfc47SDavid du Colombier p8(p, cmd);
90671dfc47SDavid du Colombier pl32(p, 0); /* status (error) */
91671dfc47SDavid du Colombier p8(p, FL_CASELESS_NAMES | FL_CANNONICAL_NAMES); /* flags */
92671dfc47SDavid du Colombier pl16(p, s->flags2 | dfs | sign); /* flags2 */
93671dfc47SDavid du Colombier pl16(p, (s->pid >> 16) & 0xffff); /* PID MS bits */
94671dfc47SDavid du Colombier pl32(p, p->seq); /* MAC / sequence number */
95671dfc47SDavid du Colombier pl32(p, 0); /* MAC */
96671dfc47SDavid du Colombier pl16(p, 0); /* padding */
97671dfc47SDavid du Colombier
98671dfc47SDavid du Colombier pl16(p, tid);
99671dfc47SDavid du Colombier pl16(p, s->pid & 0xffff);
100671dfc47SDavid du Colombier pl16(p, s->uid);
101671dfc47SDavid du Colombier pl16(p, s->mid);
102671dfc47SDavid du Colombier
103671dfc47SDavid du Colombier p->wordbase = p8(p, 0); /* filled in by pbytes() */
104671dfc47SDavid du Colombier
105671dfc47SDavid du Colombier return p;
106671dfc47SDavid du Colombier }
107671dfc47SDavid du Colombier
108671dfc47SDavid du Colombier void
pbytes(Pkt * p)109671dfc47SDavid du Colombier pbytes(Pkt *p)
110671dfc47SDavid du Colombier {
111671dfc47SDavid du Colombier int n;
112671dfc47SDavid du Colombier
113671dfc47SDavid du Colombier assert(p->wordbase != nil); /* cifshdr not called */
114671dfc47SDavid du Colombier assert(p->bytebase == nil); /* called twice */
115671dfc47SDavid du Colombier
116671dfc47SDavid du Colombier n = p->pos - p->wordbase;
117671dfc47SDavid du Colombier assert(n % 2 != 0); /* even addr */
118671dfc47SDavid du Colombier *p->wordbase = n / 2;
119671dfc47SDavid du Colombier
120671dfc47SDavid du Colombier p->bytebase = pl16(p, 0); /* filled in by cifsrpc() */
121671dfc47SDavid du Colombier }
122671dfc47SDavid du Colombier
123671dfc47SDavid du Colombier static void
dmp(int seq,uchar * buf)124671dfc47SDavid du Colombier dmp(int seq, uchar *buf)
125671dfc47SDavid du Colombier {
126671dfc47SDavid du Colombier int i;
127671dfc47SDavid du Colombier
128671dfc47SDavid du Colombier if(seq == 99)
129671dfc47SDavid du Colombier print("\n ");
130671dfc47SDavid du Colombier else
131671dfc47SDavid du Colombier print("%+2d ", seq);
132671dfc47SDavid du Colombier for(i = 0; i < 8; i++)
133671dfc47SDavid du Colombier print("%02x ", buf[i] & 0xff);
134671dfc47SDavid du Colombier print("\n");
135671dfc47SDavid du Colombier }
136671dfc47SDavid du Colombier
137671dfc47SDavid du Colombier int
cifsrpc(Pkt * p)138671dfc47SDavid du Colombier cifsrpc(Pkt *p)
139671dfc47SDavid du Colombier {
140671dfc47SDavid du Colombier int flags2, got, err;
141671dfc47SDavid du Colombier uint tid, uid, seq;
142671dfc47SDavid du Colombier uchar *pos;
143671dfc47SDavid du Colombier char m[nelem(magic)];
144671dfc47SDavid du Colombier
145671dfc47SDavid du Colombier pos = p->pos;
146671dfc47SDavid du Colombier if(p->bytebase){
147671dfc47SDavid du Colombier p->pos = p->bytebase;
148671dfc47SDavid du Colombier pl16(p, pos - (p->bytebase + 2)); /* 2 = sizeof bytecount */
149671dfc47SDavid du Colombier }
150671dfc47SDavid du Colombier p->pos = pos;
151671dfc47SDavid du Colombier
152671dfc47SDavid du Colombier if(p->s->secmode & SECMODE_SIGN_ENABLED)
153671dfc47SDavid du Colombier macsign(p, p->seq);
154671dfc47SDavid du Colombier
155671dfc47SDavid du Colombier qlock(&p->s->rpclock);
156671dfc47SDavid du Colombier got = nbtrpc(p);
157671dfc47SDavid du Colombier qunlock(&p->s->rpclock);
158671dfc47SDavid du Colombier if(got == -1)
159671dfc47SDavid du Colombier return -1;
160671dfc47SDavid du Colombier
161671dfc47SDavid du Colombier gmem(p, m, nelem(magic));
162671dfc47SDavid du Colombier if(memcmp(m, magic, nelem(magic)) != 0){
163671dfc47SDavid du Colombier werrstr("cifsrpc: bad magic number in packet %20ux%02ux%02ux%02ux",
164671dfc47SDavid du Colombier m[0], m[1], m[2], m[3]);
165671dfc47SDavid du Colombier return -1;
166671dfc47SDavid du Colombier }
167671dfc47SDavid du Colombier
168671dfc47SDavid du Colombier g8(p); /* cmd */
169671dfc47SDavid du Colombier err = gl32(p); /* errcode */
170671dfc47SDavid du Colombier g8(p); /* flags */
171671dfc47SDavid du Colombier flags2 = gl16(p); /* flags2 */
172671dfc47SDavid du Colombier gl16(p); /* PID MS bits */
173671dfc47SDavid du Colombier seq = gl32(p); /* reserved */
174671dfc47SDavid du Colombier gl32(p); /* MAC (if in use) */
175671dfc47SDavid du Colombier gl16(p); /* Padding */
176671dfc47SDavid du Colombier tid = gl16(p); /* TID */
177671dfc47SDavid du Colombier gl16(p); /* PID lsbs */
178671dfc47SDavid du Colombier uid = gl16(p); /* UID */
179671dfc47SDavid du Colombier gl16(p); /* mid */
180671dfc47SDavid du Colombier g8(p); /* word count */
181671dfc47SDavid du Colombier
182671dfc47SDavid du Colombier if(p->s->secmode & SECMODE_SIGN_ENABLED){
183671dfc47SDavid du Colombier if(macsign(p, p->seq+1) != 0 && p->s->seqrun){
184671dfc47SDavid du Colombier werrstr("cifsrpc: invalid packet signature");
185671dfc47SDavid du Colombier print("MAC signature bad\n");
186671dfc47SDavid du Colombier // FIXME: for debug only return -1;
187671dfc47SDavid du Colombier }
188671dfc47SDavid du Colombier }else{
189671dfc47SDavid du Colombier /*
190671dfc47SDavid du Colombier * We allow the sequence number of zero as some old samba
191671dfc47SDavid du Colombier * servers seem to fall back to this unexpectedly
192671dfc47SDavid du Colombier * after reporting sequence numbers correctly for a while.
193671dfc47SDavid du Colombier *
194671dfc47SDavid du Colombier * Some other samba servers seem to always report a sequence
195671dfc47SDavid du Colombier * number of zero if MAC signing is disabled, so we have to
196671dfc47SDavid du Colombier * catch that too.
197671dfc47SDavid du Colombier */
198671dfc47SDavid du Colombier if(p->s->seqrun && seq != p->seq && seq != 0){
199*976d3a68SDavid du Colombier print("%ux != %ux bad sequence number\n", seq, p->seq);
200671dfc47SDavid du Colombier return -1;
201671dfc47SDavid du Colombier }
202671dfc47SDavid du Colombier }
203671dfc47SDavid du Colombier
204671dfc47SDavid du Colombier p->tid = tid;
205671dfc47SDavid du Colombier if(p->s->uid == NO_UID)
206671dfc47SDavid du Colombier p->s->uid = uid;
207671dfc47SDavid du Colombier
208671dfc47SDavid du Colombier if(flags2 & FL2_NT_ERRCODES){
209*976d3a68SDavid du Colombier /* is it a real error rather than info/warning/chatter? */
210671dfc47SDavid du Colombier if((err & 0xF0000000) == 0xC0000000){
211671dfc47SDavid du Colombier werrstr("%s", nterrstr(err));
212671dfc47SDavid du Colombier return -1;
213671dfc47SDavid du Colombier }
214671dfc47SDavid du Colombier }else{
215671dfc47SDavid du Colombier if(err){
216671dfc47SDavid du Colombier werrstr("%s", doserrstr(err));
217671dfc47SDavid du Colombier return -1;
218671dfc47SDavid du Colombier }
219671dfc47SDavid du Colombier }
220671dfc47SDavid du Colombier return got;
221671dfc47SDavid du Colombier }
222671dfc47SDavid du Colombier
223671dfc47SDavid du Colombier
224671dfc47SDavid du Colombier /*
225671dfc47SDavid du Colombier * Some older servers (old samba) prefer to talk older
226671dfc47SDavid du Colombier * dialects but if given no choice they will talk the
227671dfc47SDavid du Colombier * more modern ones, so we don't give them the choice.
228671dfc47SDavid du Colombier */
229671dfc47SDavid du Colombier int
CIFSnegotiate(Session * s,long * svrtime,char * domain,int domlen,char * cname,int cnamlen)230*976d3a68SDavid du Colombier CIFSnegotiate(Session *s, long *svrtime, char *domain, int domlen, char *cname,
231*976d3a68SDavid du Colombier int cnamlen)
232671dfc47SDavid du Colombier {
233671dfc47SDavid du Colombier int d, i;
234671dfc47SDavid du Colombier char *ispeak = "NT LM 0.12";
235*976d3a68SDavid du Colombier static char *dialects[] = {
236671dfc47SDavid du Colombier // { "PC NETWORK PROGRAM 1.0"},
237671dfc47SDavid du Colombier // { "MICROSOFT NETWORKS 1.03"},
238671dfc47SDavid du Colombier // { "MICROSOFT NETWORKS 3.0"},
239671dfc47SDavid du Colombier // { "LANMAN1.0"},
240671dfc47SDavid du Colombier // { "LM1.2X002"},
241671dfc47SDavid du Colombier // { "NT LANMAN 1.0"},
242671dfc47SDavid du Colombier { "NT LM 0.12" },
243671dfc47SDavid du Colombier };
244671dfc47SDavid du Colombier Pkt *p;
245671dfc47SDavid du Colombier
246671dfc47SDavid du Colombier p = cifshdr(s, nil, SMB_COM_NEGOTIATE);
247671dfc47SDavid du Colombier pbytes(p);
248671dfc47SDavid du Colombier for(i = 0; i < nelem(dialects); i++){
249671dfc47SDavid du Colombier p8(p, STR_DIALECT);
250671dfc47SDavid du Colombier pstr(p, dialects[i]);
251671dfc47SDavid du Colombier }
252671dfc47SDavid du Colombier
253671dfc47SDavid du Colombier if(cifsrpc(p) == -1){
254671dfc47SDavid du Colombier free(p);
255671dfc47SDavid du Colombier return -1;
256671dfc47SDavid du Colombier }
257671dfc47SDavid du Colombier
258671dfc47SDavid du Colombier d = gl16(p);
259671dfc47SDavid du Colombier if(d < 0 || d > nelem(dialects)){
260671dfc47SDavid du Colombier werrstr("no CIFS dialect in common");
261671dfc47SDavid du Colombier free(p);
262671dfc47SDavid du Colombier return -1;
263671dfc47SDavid du Colombier }
264671dfc47SDavid du Colombier
265671dfc47SDavid du Colombier if(strcmp(dialects[d], ispeak) != 0){
266671dfc47SDavid du Colombier werrstr("%s dialect unsupported", dialects[d]);
267671dfc47SDavid du Colombier free(p);
268671dfc47SDavid du Colombier return -1;
269671dfc47SDavid du Colombier }
270671dfc47SDavid du Colombier
271671dfc47SDavid du Colombier s->secmode = g8(p); /* Security mode */
272671dfc47SDavid du Colombier
273671dfc47SDavid du Colombier gl16(p); /* Max outstanding requests */
274671dfc47SDavid du Colombier gl16(p); /* Max VCs */
275671dfc47SDavid du Colombier s->mtu = gl32(p); /* Max buffer size */
276671dfc47SDavid du Colombier gl32(p); /* Max raw buffer size (depricated) */
277671dfc47SDavid du Colombier gl32(p); /* Session key */
278671dfc47SDavid du Colombier s->caps = gl32(p); /* Server capabilities */
279671dfc47SDavid du Colombier *svrtime = gvtime(p); /* fileserver time */
280671dfc47SDavid du Colombier s->tz = (short)gl16(p) * 60; /* TZ in mins, is signed (SNIA doc is wrong) */
281671dfc47SDavid du Colombier s->challen = g8(p); /* Encryption key length */
282671dfc47SDavid du Colombier gl16(p);
283671dfc47SDavid du Colombier gmem(p, s->chal, s->challen); /* Get the challenge */
284671dfc47SDavid du Colombier gstr(p, domain, domlen); /* source domain */
285671dfc47SDavid du Colombier
286671dfc47SDavid du Colombier { /* NetApp Filer seem not to report its called name */
287671dfc47SDavid du Colombier char *cn = emalloc9p(cnamlen);
288671dfc47SDavid du Colombier
289671dfc47SDavid du Colombier gstr(p, cn, cnamlen); /* their name */
290671dfc47SDavid du Colombier if(strlen(cn) > 0)
291671dfc47SDavid du Colombier memcpy(cname, cn, cnamlen);
292671dfc47SDavid du Colombier free(cn);
293671dfc47SDavid du Colombier }
294671dfc47SDavid du Colombier
295671dfc47SDavid du Colombier if(s->caps & CAP_UNICODE)
296671dfc47SDavid du Colombier s->flags2 |= FL2_UNICODE;
297671dfc47SDavid du Colombier
298671dfc47SDavid du Colombier free(p);
299671dfc47SDavid du Colombier return 0;
300671dfc47SDavid du Colombier }
301671dfc47SDavid du Colombier
302671dfc47SDavid du Colombier int
CIFSsession(Session * s)303671dfc47SDavid du Colombier CIFSsession(Session *s)
304671dfc47SDavid du Colombier {
305671dfc47SDavid du Colombier char os[64], *q;
306671dfc47SDavid du Colombier Rune r;
307671dfc47SDavid du Colombier Pkt *p;
308671dfc47SDavid du Colombier enum {
309671dfc47SDavid du Colombier mycaps = CAP_UNICODE | CAP_LARGE_FILES | CAP_NT_SMBS |
310671dfc47SDavid du Colombier CAP_NT_FIND | CAP_STATUS32,
311671dfc47SDavid du Colombier };
312671dfc47SDavid du Colombier
313671dfc47SDavid du Colombier s->seqrun = 1; /* activate the sequence number generation/checking */
314671dfc47SDavid du Colombier
315671dfc47SDavid du Colombier p = cifshdr(s, nil, SMB_COM_SESSION_SETUP_ANDX);
316671dfc47SDavid du Colombier p8(p, 0xFF); /* No secondary command */
317671dfc47SDavid du Colombier p8(p, 0); /* Reserved (must be zero) */
318671dfc47SDavid du Colombier pl16(p, 0); /* Offset to next command */
319671dfc47SDavid du Colombier pl16(p, MTU); /* my max buffer size */
320671dfc47SDavid du Colombier pl16(p, 1); /* my max multiplexed pending requests */
321671dfc47SDavid du Colombier pl16(p, 0); /* Virtual connection # */
322671dfc47SDavid du Colombier pl32(p, 0); /* Session key (if vc != 0) */
323671dfc47SDavid du Colombier
324671dfc47SDavid du Colombier
325671dfc47SDavid du Colombier if((s->secmode & SECMODE_PW_ENCRYPT) == 0) {
326671dfc47SDavid du Colombier pl16(p, utflen(Sess->auth->resp[0])*2 + 2); /* passwd size */
327671dfc47SDavid du Colombier pl16(p, utflen(Sess->auth->resp[0])*2 + 2); /* passwd size (UPPER CASE) */
328671dfc47SDavid du Colombier pl32(p, 0); /* Reserved */
329671dfc47SDavid du Colombier pl32(p, mycaps);
330671dfc47SDavid du Colombier pbytes(p);
331671dfc47SDavid du Colombier
332671dfc47SDavid du Colombier for(q = Sess->auth->resp[0]; *q; ){
333671dfc47SDavid du Colombier q += chartorune(&r, q);
334671dfc47SDavid du Colombier pl16(p, toupperrune(r));
335671dfc47SDavid du Colombier }
336671dfc47SDavid du Colombier pl16(p, 0);
337671dfc47SDavid du Colombier
338671dfc47SDavid du Colombier for(q = Sess->auth->resp[0]; *q; ){
339671dfc47SDavid du Colombier q += chartorune(&r, q);
340671dfc47SDavid du Colombier pl16(p, r);
341671dfc47SDavid du Colombier }
342671dfc47SDavid du Colombier pl16(p, 0);
343671dfc47SDavid du Colombier }else{
344671dfc47SDavid du Colombier pl16(p, Sess->auth->len[0]); /* LM passwd size */
345671dfc47SDavid du Colombier pl16(p, Sess->auth->len[1]); /* NTLM passwd size */
346671dfc47SDavid du Colombier pl32(p, 0); /* Reserved */
347671dfc47SDavid du Colombier pl32(p, mycaps);
348671dfc47SDavid du Colombier pbytes(p);
349671dfc47SDavid du Colombier
350671dfc47SDavid du Colombier pmem(p, Sess->auth->resp[0], Sess->auth->len[0]);
351671dfc47SDavid du Colombier pmem(p, Sess->auth->resp[1], Sess->auth->len[1]);
352671dfc47SDavid du Colombier }
353671dfc47SDavid du Colombier
354671dfc47SDavid du Colombier pstr(p, Sess->auth->user); /* Account name */
355671dfc47SDavid du Colombier pstr(p, Sess->auth->windom); /* Primary domain */
356671dfc47SDavid du Colombier pstr(p, "plan9"); /* Client OS */
357671dfc47SDavid du Colombier pstr(p, argv0); /* Client LAN Manager type */
358671dfc47SDavid du Colombier
359671dfc47SDavid du Colombier if(cifsrpc(p) == -1){
360671dfc47SDavid du Colombier free(p);
361671dfc47SDavid du Colombier return -1;
362671dfc47SDavid du Colombier }
363671dfc47SDavid du Colombier
364671dfc47SDavid du Colombier g8(p); /* Reserved (0) */
365671dfc47SDavid du Colombier gl16(p); /* Offset to next command wordcount */
366671dfc47SDavid du Colombier Sess->isguest = gl16(p) & 1; /* logged in as guest */
367671dfc47SDavid du Colombier
368671dfc47SDavid du Colombier gl16(p);
369671dfc47SDavid du Colombier gl16(p);
370671dfc47SDavid du Colombier /* no security blob here - we don't understand extended security anyway */
371671dfc47SDavid du Colombier gstr(p, os, sizeof(os));
372671dfc47SDavid du Colombier s->remos = estrdup9p(os);
373671dfc47SDavid du Colombier
374671dfc47SDavid du Colombier free(p);
375671dfc47SDavid du Colombier return 0;
376671dfc47SDavid du Colombier }
377671dfc47SDavid du Colombier
378671dfc47SDavid du Colombier
CIFStreeconnect(Session * s,char * cname,char * tree,Share * sp)379671dfc47SDavid du Colombier CIFStreeconnect(Session *s, char *cname, char *tree, Share *sp)
380671dfc47SDavid du Colombier {
381671dfc47SDavid du Colombier int len;
382671dfc47SDavid du Colombier char *resp, *path;
383671dfc47SDavid du Colombier char zeros[24];
384671dfc47SDavid du Colombier Pkt *p;
385671dfc47SDavid du Colombier
386671dfc47SDavid du Colombier resp = Sess->auth->resp[0];
387671dfc47SDavid du Colombier len = Sess->auth->len[0];
388671dfc47SDavid du Colombier if((s->secmode & SECMODE_USER) != SECMODE_USER){
389671dfc47SDavid du Colombier memset(zeros, 0, sizeof(zeros));
390671dfc47SDavid du Colombier resp = zeros;
391671dfc47SDavid du Colombier len = sizeof(zeros);
392671dfc47SDavid du Colombier }
393671dfc47SDavid du Colombier
394671dfc47SDavid du Colombier p = cifshdr(s, nil, SMB_COM_TREE_CONNECT_ANDX);
395671dfc47SDavid du Colombier p8(p, 0xFF); /* Secondary command */
396671dfc47SDavid du Colombier p8(p, 0); /* Reserved */
397671dfc47SDavid du Colombier pl16(p, 0); /* Offset to next Word Count */
398671dfc47SDavid du Colombier pl16(p, 0); /* Flags */
399671dfc47SDavid du Colombier
400671dfc47SDavid du Colombier if((s->secmode & SECMODE_PW_ENCRYPT) == 0){
401671dfc47SDavid du Colombier pl16(p, len+1); /* password len, including null */
402671dfc47SDavid du Colombier pbytes(p);
403671dfc47SDavid du Colombier pascii(p, resp);
404671dfc47SDavid du Colombier }else{
405671dfc47SDavid du Colombier pl16(p, len);
406671dfc47SDavid du Colombier pbytes(p);
407671dfc47SDavid du Colombier pmem(p, resp, len);
408671dfc47SDavid du Colombier }
409671dfc47SDavid du Colombier
410671dfc47SDavid du Colombier path = smprint("//%s/%s", cname, tree);
411671dfc47SDavid du Colombier strupr(path);
412671dfc47SDavid du Colombier ppath(p, path); /* path */
413671dfc47SDavid du Colombier free(path);
414671dfc47SDavid du Colombier
415671dfc47SDavid du Colombier pascii(p, "?????"); /* service type any (so we can do RAP calls) */
416671dfc47SDavid du Colombier
417671dfc47SDavid du Colombier if(cifsrpc(p) == -1){
418671dfc47SDavid du Colombier free(p);
419671dfc47SDavid du Colombier return -1;
420671dfc47SDavid du Colombier }
421671dfc47SDavid du Colombier g8(p); /* Secondary command */
422671dfc47SDavid du Colombier g8(p); /* Reserved */
423671dfc47SDavid du Colombier gl16(p); /* Offset to next command */
424671dfc47SDavid du Colombier sp->options = g8(p); /* options supported */
425671dfc47SDavid du Colombier sp->tid = p->tid; /* get received TID from packet header */
426671dfc47SDavid du Colombier free(p);
427671dfc47SDavid du Colombier return 0;
428671dfc47SDavid du Colombier }
429671dfc47SDavid du Colombier
430671dfc47SDavid du Colombier int
CIFSlogoff(Session * s)431671dfc47SDavid du Colombier CIFSlogoff(Session *s)
432671dfc47SDavid du Colombier {
433671dfc47SDavid du Colombier int rc;
434671dfc47SDavid du Colombier Pkt *p;
435671dfc47SDavid du Colombier
436671dfc47SDavid du Colombier p = cifshdr(s, nil, SMB_COM_LOGOFF_ANDX);
437671dfc47SDavid du Colombier p8(p, 0xFF); /* No ANDX command */
438671dfc47SDavid du Colombier p8(p, 0); /* Reserved (must be zero) */
439671dfc47SDavid du Colombier pl16(p, 0); /* offset ot ANDX */
440671dfc47SDavid du Colombier pbytes(p);
441671dfc47SDavid du Colombier rc = cifsrpc(p);
442671dfc47SDavid du Colombier
443671dfc47SDavid du Colombier free(p);
444671dfc47SDavid du Colombier return rc;
445671dfc47SDavid du Colombier }
446671dfc47SDavid du Colombier
447671dfc47SDavid du Colombier int
CIFStreedisconnect(Session * s,Share * sp)448671dfc47SDavid du Colombier CIFStreedisconnect(Session *s, Share *sp)
449671dfc47SDavid du Colombier {
450671dfc47SDavid du Colombier int rc;
451671dfc47SDavid du Colombier Pkt *p;
452671dfc47SDavid du Colombier
453671dfc47SDavid du Colombier p = cifshdr(s, sp, SMB_COM_TREE_DISCONNECT);
454671dfc47SDavid du Colombier pbytes(p);
455671dfc47SDavid du Colombier rc = cifsrpc(p);
456671dfc47SDavid du Colombier
457671dfc47SDavid du Colombier free(p);
458671dfc47SDavid du Colombier return rc;
459671dfc47SDavid du Colombier }
460671dfc47SDavid du Colombier
461671dfc47SDavid du Colombier
462671dfc47SDavid du Colombier int
CIFSdeletefile(Session * s,Share * sp,char * name)463671dfc47SDavid du Colombier CIFSdeletefile(Session *s, Share *sp, char *name)
464671dfc47SDavid du Colombier {
465671dfc47SDavid du Colombier int rc;
466671dfc47SDavid du Colombier Pkt *p;
467671dfc47SDavid du Colombier
468671dfc47SDavid du Colombier p = cifshdr(s, sp, SMB_COM_DELETE);
469671dfc47SDavid du Colombier pl16(p, ATTR_HIDDEN|ATTR_SYSTEM); /* search attributes */
470671dfc47SDavid du Colombier pbytes(p);
471671dfc47SDavid du Colombier p8(p, STR_ASCII); /* buffer format */
472671dfc47SDavid du Colombier ppath(p, name);
473671dfc47SDavid du Colombier rc = cifsrpc(p);
474671dfc47SDavid du Colombier
475671dfc47SDavid du Colombier free(p);
476671dfc47SDavid du Colombier return rc;
477671dfc47SDavid du Colombier }
478671dfc47SDavid du Colombier
479671dfc47SDavid du Colombier int
CIFSdeletedirectory(Session * s,Share * sp,char * name)480671dfc47SDavid du Colombier CIFSdeletedirectory(Session *s, Share *sp, char *name)
481671dfc47SDavid du Colombier {
482671dfc47SDavid du Colombier int rc;
483671dfc47SDavid du Colombier Pkt *p;
484671dfc47SDavid du Colombier
485671dfc47SDavid du Colombier p = cifshdr(s, sp, SMB_COM_DELETE_DIRECTORY);
486671dfc47SDavid du Colombier pbytes(p);
487671dfc47SDavid du Colombier p8(p, STR_ASCII); /* buffer format */
488671dfc47SDavid du Colombier ppath(p, name);
489671dfc47SDavid du Colombier rc = cifsrpc(p);
490671dfc47SDavid du Colombier
491671dfc47SDavid du Colombier free(p);
492671dfc47SDavid du Colombier return rc;
493671dfc47SDavid du Colombier }
494671dfc47SDavid du Colombier
495671dfc47SDavid du Colombier int
CIFScreatedirectory(Session * s,Share * sp,char * name)496671dfc47SDavid du Colombier CIFScreatedirectory(Session *s, Share *sp, char *name)
497671dfc47SDavid du Colombier {
498671dfc47SDavid du Colombier int rc;
499671dfc47SDavid du Colombier Pkt *p;
500671dfc47SDavid du Colombier
501671dfc47SDavid du Colombier p = cifshdr(s, sp, SMB_COM_CREATE_DIRECTORY);
502671dfc47SDavid du Colombier pbytes(p);
503671dfc47SDavid du Colombier p8(p, STR_ASCII);
504671dfc47SDavid du Colombier ppath(p, name);
505671dfc47SDavid du Colombier rc = cifsrpc(p);
506671dfc47SDavid du Colombier
507671dfc47SDavid du Colombier free(p);
508671dfc47SDavid du Colombier return rc;
509671dfc47SDavid du Colombier }
510671dfc47SDavid du Colombier
511671dfc47SDavid du Colombier int
CIFSrename(Session * s,Share * sp,char * old,char * new)512671dfc47SDavid du Colombier CIFSrename(Session *s, Share *sp, char *old, char *new)
513671dfc47SDavid du Colombier {
514671dfc47SDavid du Colombier int rc;
515671dfc47SDavid du Colombier Pkt *p;
516671dfc47SDavid du Colombier
517671dfc47SDavid du Colombier p = cifshdr(s, sp, SMB_COM_RENAME);
518671dfc47SDavid du Colombier pl16(p, ATTR_HIDDEN|ATTR_SYSTEM|ATTR_DIRECTORY); /* search attributes */
519671dfc47SDavid du Colombier pbytes(p);
520671dfc47SDavid du Colombier p8(p, STR_ASCII);
521671dfc47SDavid du Colombier ppath(p, old);
522671dfc47SDavid du Colombier p8(p, STR_ASCII);
523671dfc47SDavid du Colombier ppath(p, new);
524671dfc47SDavid du Colombier rc = cifsrpc(p);
525671dfc47SDavid du Colombier
526671dfc47SDavid du Colombier free(p);
527671dfc47SDavid du Colombier return rc;
528671dfc47SDavid du Colombier }
529671dfc47SDavid du Colombier
530671dfc47SDavid du Colombier
531671dfc47SDavid du Colombier /* for NT4/Win2k/XP */
532671dfc47SDavid du Colombier int
CIFS_NT_opencreate(Session * s,Share * sp,char * name,int flags,int options,int attrs,int access,int share,int action,int * result,FInfo * fi)533671dfc47SDavid du Colombier CIFS_NT_opencreate(Session *s, Share *sp, char *name, int flags, int options,
534671dfc47SDavid du Colombier int attrs, int access, int share, int action, int *result, FInfo *fi)
535671dfc47SDavid du Colombier {
536671dfc47SDavid du Colombier Pkt *p;
537671dfc47SDavid du Colombier int fh;
538671dfc47SDavid du Colombier
539671dfc47SDavid du Colombier p = cifshdr(s, sp, SMB_COM_NT_CREATE_ANDX);
540671dfc47SDavid du Colombier p8(p, 0xFF); /* Secondary command */
541671dfc47SDavid du Colombier p8(p, 0); /* Reserved */
542671dfc47SDavid du Colombier pl16(p, 0); /* Offset to next command */
543671dfc47SDavid du Colombier p8(p, 0); /* Reserved */
544671dfc47SDavid du Colombier pl16(p, utflen(name) *2); /* file name len */
545671dfc47SDavid du Colombier pl32(p, flags); /* Flags */
546671dfc47SDavid du Colombier pl32(p, 0); /* fid of cwd, if relative path */
547671dfc47SDavid du Colombier pl32(p, access); /* access desired */
548671dfc47SDavid du Colombier pl64(p, 0); /* initial allocation size */
549671dfc47SDavid du Colombier pl32(p, attrs); /* Extended attributes */
550671dfc47SDavid du Colombier pl32(p, share); /* Share Access */
551671dfc47SDavid du Colombier pl32(p, action); /* What to do on success/failure */
552671dfc47SDavid du Colombier pl32(p, options); /* Options */
553671dfc47SDavid du Colombier pl32(p, SECURITY_IMPERSONATION); /* Impersonation level */
554671dfc47SDavid du Colombier p8(p, SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY); /* security flags */
555671dfc47SDavid du Colombier pbytes(p);
556671dfc47SDavid du Colombier p8(p, 0); /* FIXME: padding? */
557671dfc47SDavid du Colombier ppath(p, name); /* filename */
558671dfc47SDavid du Colombier
559671dfc47SDavid du Colombier if(cifsrpc(p) == -1){
560671dfc47SDavid du Colombier free(p);
561671dfc47SDavid du Colombier return -1;
562671dfc47SDavid du Colombier }
563671dfc47SDavid du Colombier
564671dfc47SDavid du Colombier memset(fi, 0, sizeof(FInfo));
565671dfc47SDavid du Colombier g8(p); /* Secondary command */
566671dfc47SDavid du Colombier g8(p); /* Reserved */
567671dfc47SDavid du Colombier gl16(p); /* Offset to next command */
568671dfc47SDavid du Colombier g8(p); /* oplock granted */
569671dfc47SDavid du Colombier fh = gl16(p); /* FID for opened object */
570671dfc47SDavid du Colombier *result = gl32(p); /* create action taken */
571671dfc47SDavid du Colombier gl64(p); /* creation time */
572671dfc47SDavid du Colombier fi->accessed = gvtime(p); /* last access time */
573671dfc47SDavid du Colombier fi->written = gvtime(p); /* last written time */
574671dfc47SDavid du Colombier fi->changed = gvtime(p); /* change time */
575671dfc47SDavid du Colombier fi->attribs = gl32(p); /* extended attributes */
576671dfc47SDavid du Colombier gl64(p); /* bytes allocated */
577671dfc47SDavid du Colombier fi->size = gl64(p); /* file size */
578671dfc47SDavid du Colombier
579671dfc47SDavid du Colombier free(p);
580671dfc47SDavid du Colombier return fh;
581671dfc47SDavid du Colombier }
582671dfc47SDavid du Colombier
583671dfc47SDavid du Colombier /* for Win95/98/ME */
CIFS_SMB_opencreate(Session * s,Share * sp,char * name,int access,int attrs,int action,int * result)584671dfc47SDavid du Colombier CIFS_SMB_opencreate(Session *s, Share *sp, char *name, int access,
585671dfc47SDavid du Colombier int attrs, int action, int *result)
586671dfc47SDavid du Colombier {
587671dfc47SDavid du Colombier Pkt *p;
588671dfc47SDavid du Colombier int fh;
589671dfc47SDavid du Colombier
590671dfc47SDavid du Colombier p = cifshdr(s, sp, SMB_COM_OPEN_ANDX);
591671dfc47SDavid du Colombier p8(p, 0xFF); /* Secondary command */
592671dfc47SDavid du Colombier p8(p, 0); /* Reserved */
593671dfc47SDavid du Colombier pl16(p, 0); /* Offset to next command */
594671dfc47SDavid du Colombier pl16(p, 0); /* Flags (0 == no stat(2) info) */
595671dfc47SDavid du Colombier pl16(p, access); /* desired access */
596671dfc47SDavid du Colombier pl16(p, ATTR_HIDDEN|ATTR_SYSTEM);/* search attributes */
597671dfc47SDavid du Colombier pl16(p, attrs); /* file attribytes */
598671dfc47SDavid du Colombier pdatetime(p, 0); /* creation time (0 == now) */
599671dfc47SDavid du Colombier pl16(p, action); /* What to do on success/failure */
600671dfc47SDavid du Colombier pl32(p, 0); /* allocation size */
601671dfc47SDavid du Colombier pl32(p, 0); /* reserved */
602671dfc47SDavid du Colombier pl32(p, 0); /* reserved */
603671dfc47SDavid du Colombier pbytes(p);
604671dfc47SDavid du Colombier ppath(p, name); /* filename */
605671dfc47SDavid du Colombier
606671dfc47SDavid du Colombier if(cifsrpc(p) == -1){
607671dfc47SDavid du Colombier free(p);
608671dfc47SDavid du Colombier return -1;
609671dfc47SDavid du Colombier }
610671dfc47SDavid du Colombier
611671dfc47SDavid du Colombier g8(p); /* Secondary command */
612671dfc47SDavid du Colombier g8(p); /* Reserved */
613671dfc47SDavid du Colombier gl16(p); /* Offset to next command */
614671dfc47SDavid du Colombier fh = gl16(p); /* FID for opened object */
615671dfc47SDavid du Colombier gl16(p); /* extended attributes */
616671dfc47SDavid du Colombier gvtime(p); /* last written time */
617671dfc47SDavid du Colombier gl32(p); /* file size */
618671dfc47SDavid du Colombier gl16(p); /* file type (disk/fifo/printer etc) */
619671dfc47SDavid du Colombier gl16(p); /* device status (for fifos) */
620671dfc47SDavid du Colombier *result = gl16(p); /* access granted */
621671dfc47SDavid du Colombier
622671dfc47SDavid du Colombier free(p);
623671dfc47SDavid du Colombier return fh;
624671dfc47SDavid du Colombier }
625671dfc47SDavid du Colombier
626671dfc47SDavid du Colombier vlong
CIFSwrite(Session * s,Share * sp,int fh,uvlong off,void * buf,vlong n)627671dfc47SDavid du Colombier CIFSwrite(Session *s, Share *sp, int fh, uvlong off, void *buf, vlong n)
628671dfc47SDavid du Colombier {
629671dfc47SDavid du Colombier Pkt *p;
630671dfc47SDavid du Colombier vlong got;
631671dfc47SDavid du Colombier
632671dfc47SDavid du Colombier /* FIXME: Payload should be padded to long boundary */
633671dfc47SDavid du Colombier assert((n & 0xffffffff00000000LL) == 0 || s->caps & CAP_LARGE_FILES);
634671dfc47SDavid du Colombier assert((off & 0xffffffff00000000LL) == 0 || s->caps & CAP_LARGE_FILES);
635671dfc47SDavid du Colombier assert(n < s->mtu - T2HDRLEN || s->caps & CAP_LARGE_WRITEX);
636671dfc47SDavid du Colombier
637671dfc47SDavid du Colombier p = cifshdr(s, sp, SMB_COM_WRITE_ANDX);
638671dfc47SDavid du Colombier p8(p, 0xFF); /* Secondary command */
639671dfc47SDavid du Colombier p8(p, 0); /* Reserved */
640671dfc47SDavid du Colombier pl16(p, 0); /* Offset to next command */
641671dfc47SDavid du Colombier pl16(p, fh); /* File handle */
642671dfc47SDavid du Colombier pl32(p, off & 0xffffffff); /* LSBs of Offset */
643671dfc47SDavid du Colombier pl32(p, 0); /* Reserved (0) */
644671dfc47SDavid du Colombier pl16(p, s->nocache); /* Write mode (0 - write through) */
645671dfc47SDavid du Colombier pl16(p, 0); /* Bytes remaining */
646671dfc47SDavid du Colombier pl16(p, n >> 16); /* MSBs of length */
647671dfc47SDavid du Colombier pl16(p, n & 0xffffffff); /* LSBs of length */
648671dfc47SDavid du Colombier pl16(p, T2HDRLEN); /* Offset to data, in bytes */
649671dfc47SDavid du Colombier pl32(p, off >> 32); /* MSBs of offset */
650671dfc47SDavid du Colombier pbytes(p);
651671dfc47SDavid du Colombier
652671dfc47SDavid du Colombier p->pos = p->buf +T2HDRLEN +NBHDRLEN;
653671dfc47SDavid du Colombier pmem(p, buf, n); /* Data */
654671dfc47SDavid du Colombier
655671dfc47SDavid du Colombier if(cifsrpc(p) == -1){
656671dfc47SDavid du Colombier free(p);
657671dfc47SDavid du Colombier return -1;
658671dfc47SDavid du Colombier }
659671dfc47SDavid du Colombier
660671dfc47SDavid du Colombier g8(p); /* Secondary command */
661671dfc47SDavid du Colombier g8(p); /* Reserved */
662671dfc47SDavid du Colombier gl16(p); /* Offset to next command */
663671dfc47SDavid du Colombier got = gl16(p); /* LSWs of bytes written */
664671dfc47SDavid du Colombier gl16(p); /* remaining (space ?) */
665671dfc47SDavid du Colombier got |= (gl16(p) << 16); /* MSWs of bytes written */
666671dfc47SDavid du Colombier
667671dfc47SDavid du Colombier free(p);
668671dfc47SDavid du Colombier return got;
669671dfc47SDavid du Colombier }
670671dfc47SDavid du Colombier
671671dfc47SDavid du Colombier vlong
CIFSread(Session * s,Share * sp,int fh,uvlong off,void * buf,vlong n,vlong minlen)672671dfc47SDavid du Colombier CIFSread(Session *s, Share *sp, int fh, uvlong off, void *buf, vlong n,
673671dfc47SDavid du Colombier vlong minlen)
674671dfc47SDavid du Colombier {
675671dfc47SDavid du Colombier int doff;
676671dfc47SDavid du Colombier vlong got;
677671dfc47SDavid du Colombier Pkt *p;
678671dfc47SDavid du Colombier
679671dfc47SDavid du Colombier assert((n & 0xffffffff00000000LL) == 0 || s->caps & CAP_LARGE_FILES);
680671dfc47SDavid du Colombier assert((off & 0xffffffff00000000LL) == 0 || s->caps & CAP_LARGE_FILES);
681671dfc47SDavid du Colombier assert(n < s->mtu - T2HDRLEN || s->caps & CAP_LARGE_READX);
682671dfc47SDavid du Colombier
683671dfc47SDavid du Colombier p = cifshdr(s, sp, SMB_COM_READ_ANDX);
684671dfc47SDavid du Colombier p8(p, 0xFF); /* Secondary command */
685671dfc47SDavid du Colombier p8(p, 0); /* Reserved */
686671dfc47SDavid du Colombier pl16(p, 0); /* Offset to next command */
687671dfc47SDavid du Colombier pl16(p, fh); /* File handle */
688671dfc47SDavid du Colombier pl32(p, off & 0xffffffff); /* Offset to beginning of write */
689671dfc47SDavid du Colombier pl16(p, n); /* Maximum number of bytes to return */
690671dfc47SDavid du Colombier pl16(p, minlen); /* Minimum number of bytes to return */
691671dfc47SDavid du Colombier pl32(p, (uint)n >> 16); /* MSBs of maxlen */
692671dfc47SDavid du Colombier pl16(p, 0); /* Bytes remaining to satisfy request */
693671dfc47SDavid du Colombier pl32(p, off >> 32); /* MS 32 bits of offset */
694671dfc47SDavid du Colombier pbytes(p);
695671dfc47SDavid du Colombier
696671dfc47SDavid du Colombier if(cifsrpc(p) == -1){
697671dfc47SDavid du Colombier free(p);
698671dfc47SDavid du Colombier return -1;
699671dfc47SDavid du Colombier }
700671dfc47SDavid du Colombier
701671dfc47SDavid du Colombier g8(p); /* Secondary command */
702671dfc47SDavid du Colombier g8(p); /* Reserved */
703671dfc47SDavid du Colombier gl16(p); /* Offset to next command */
704671dfc47SDavid du Colombier gl16(p); /* Remaining */
705671dfc47SDavid du Colombier gl16(p); /* Compression mode */
706671dfc47SDavid du Colombier gl16(p); /* Reserved */
707671dfc47SDavid du Colombier got = gl16(p); /* length */
708671dfc47SDavid du Colombier doff = gl16(p); /* Offset from header to data */
709671dfc47SDavid du Colombier got |= gl16(p) << 16;
710671dfc47SDavid du Colombier
711671dfc47SDavid du Colombier p->pos = p->buf + doff + NBHDRLEN;
712671dfc47SDavid du Colombier
713671dfc47SDavid du Colombier gmem(p, buf, got); /* data */
714671dfc47SDavid du Colombier free(p);
715671dfc47SDavid du Colombier return got;
716671dfc47SDavid du Colombier }
717671dfc47SDavid du Colombier
718671dfc47SDavid du Colombier int
CIFSflush(Session * s,Share * sp,int fh)719671dfc47SDavid du Colombier CIFSflush(Session *s, Share *sp, int fh)
720671dfc47SDavid du Colombier {
721671dfc47SDavid du Colombier int rc;
722671dfc47SDavid du Colombier Pkt *p;
723671dfc47SDavid du Colombier
724671dfc47SDavid du Colombier p = cifshdr(s, sp, SMB_COM_FLUSH);
725671dfc47SDavid du Colombier pl16(p, fh); /* fid */
726671dfc47SDavid du Colombier pbytes(p);
727671dfc47SDavid du Colombier rc = cifsrpc(p);
728671dfc47SDavid du Colombier
729671dfc47SDavid du Colombier free(p);
730671dfc47SDavid du Colombier return rc;
731671dfc47SDavid du Colombier }
732671dfc47SDavid du Colombier
733671dfc47SDavid du Colombier /*
734671dfc47SDavid du Colombier * Setting the time of last write to -1 gives "now" if the file
735671dfc47SDavid du Colombier * was written and leaves it the same if the file wasn't written.
736671dfc47SDavid du Colombier */
737671dfc47SDavid du Colombier int
CIFSclose(Session * s,Share * sp,int fh)738671dfc47SDavid du Colombier CIFSclose(Session *s, Share *sp, int fh)
739671dfc47SDavid du Colombier {
740671dfc47SDavid du Colombier int rc;
741671dfc47SDavid du Colombier Pkt *p;
742671dfc47SDavid du Colombier
743671dfc47SDavid du Colombier p = cifshdr(s, sp, SMB_COM_CLOSE);
744671dfc47SDavid du Colombier pl16(p, fh); /* fid */
745671dfc47SDavid du Colombier pl32(p, ~0L); /* Time of last write (none) */
746671dfc47SDavid du Colombier pbytes(p);
747671dfc47SDavid du Colombier rc = cifsrpc(p);
748671dfc47SDavid du Colombier
749671dfc47SDavid du Colombier free(p);
750671dfc47SDavid du Colombier return rc;
751671dfc47SDavid du Colombier }
752671dfc47SDavid du Colombier
753671dfc47SDavid du Colombier
754671dfc47SDavid du Colombier int
CIFSfindclose2(Session * s,Share * sp,int sh)755671dfc47SDavid du Colombier CIFSfindclose2(Session *s, Share *sp, int sh)
756671dfc47SDavid du Colombier {
757671dfc47SDavid du Colombier int rc;
758671dfc47SDavid du Colombier Pkt *p;
759671dfc47SDavid du Colombier
760671dfc47SDavid du Colombier p = cifshdr(s, sp, SMB_COM_FIND_CLOSE2);
761671dfc47SDavid du Colombier pl16(p, sh); /* sid */
762671dfc47SDavid du Colombier pbytes(p);
763671dfc47SDavid du Colombier rc = cifsrpc(p);
764671dfc47SDavid du Colombier
765671dfc47SDavid du Colombier free(p);
766671dfc47SDavid du Colombier return rc;
767671dfc47SDavid du Colombier }
768671dfc47SDavid du Colombier
769671dfc47SDavid du Colombier
770671dfc47SDavid du Colombier int
CIFSecho(Session * s)771671dfc47SDavid du Colombier CIFSecho(Session *s)
772671dfc47SDavid du Colombier {
773671dfc47SDavid du Colombier Pkt *p;
774671dfc47SDavid du Colombier int rc;
775671dfc47SDavid du Colombier
776671dfc47SDavid du Colombier p = cifshdr(s, nil, SMB_COM_ECHO);
777671dfc47SDavid du Colombier pl16(p, 1); /* number of replies */
778671dfc47SDavid du Colombier pbytes(p);
779671dfc47SDavid du Colombier pascii(p, "abcdefghijklmnopqrstuvwxyz"); /* data */
780671dfc47SDavid du Colombier
781671dfc47SDavid du Colombier rc = cifsrpc(p);
782671dfc47SDavid du Colombier free(p);
783671dfc47SDavid du Colombier return rc;
784671dfc47SDavid du Colombier }
785671dfc47SDavid du Colombier
786671dfc47SDavid du Colombier
787671dfc47SDavid du Colombier int
CIFSsetinfo(Session * s,Share * sp,char * path,FInfo * fip)788671dfc47SDavid du Colombier CIFSsetinfo(Session *s, Share *sp, char *path, FInfo *fip)
789671dfc47SDavid du Colombier {
790671dfc47SDavid du Colombier int rc;
791671dfc47SDavid du Colombier Pkt *p;
792671dfc47SDavid du Colombier
793671dfc47SDavid du Colombier p = cifshdr(s, sp, SMB_COM_SET_INFORMATION);
794671dfc47SDavid du Colombier pl16(p, fip->attribs);
795671dfc47SDavid du Colombier pl32(p, time(nil) - s->tz); /* modified time */
796671dfc47SDavid du Colombier pl64(p, 0); /* reserved */
797671dfc47SDavid du Colombier pl16(p, 0); /* reserved */
798671dfc47SDavid du Colombier
799671dfc47SDavid du Colombier pbytes(p);
800671dfc47SDavid du Colombier p8(p, STR_ASCII); /* buffer format */
801671dfc47SDavid du Colombier ppath(p, path);
802671dfc47SDavid du Colombier
803671dfc47SDavid du Colombier rc = cifsrpc(p);
804671dfc47SDavid du Colombier free(p);
805671dfc47SDavid du Colombier return rc;
806671dfc47SDavid du Colombier }
807