123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804 |
- #include <u.h>
- #include <libc.h>
- #include <fcall.h>
- #include <thread.h>
- #include <9p.h>
- #include "cifs.h"
- static char magic[] = { 0xff, 'S', 'M', 'B' };
- Session *
- cifsdial(char *host, char *called, char *sysname)
- {
- int nbt, fd;
- char *addr;
- Session *s;
- if(Debug)
- fprint(2, "cifsdial: host=%s called=%s sysname=%s\n", host, called, sysname);
- if((addr = netmkaddr(host, "tcp", "cifs")) == nil)
- return nil;
- nbt = 0;
- if((fd = dial(addr, nil, nil, nil)) == -1){
- nbt = 1;
- if((fd = nbtdial(host, called, sysname)) == -1)
- return nil;
- }
- s = emalloc9p(sizeof(Session));
- memset(s, 0, sizeof(Session));
- s->fd = fd;
- s->nbt = nbt;
- s->mtu = MTU;
- s->pid = getpid();
- s->mid = time(nil) ^ getpid();
- s->uid = NO_UID;
- s->seq = 0;
- s->seqrun = 0;
- s->secmode = SECMODE_SIGN_ENABLED; /* hope for the best */
- s->flags2 = FL2_KNOWS_LONG_NAMES | FL2_HAS_LONG_NAMES | FL2_PAGEING_IO;
- s->macidx = -1;
- return s;
- }
- void
- cifsclose(Session *s)
- {
- if(s->fd)
- close(s->fd);
- free(s);
- }
- Pkt *
- cifshdr(Session *s, Share *sp, int cmd)
- {
- Pkt *p;
- int sign, tid, dfs;
- dfs = 0;
- tid = NO_TID;
- Active = IDLE_TIME;
- sign = s->secmode & SECMODE_SIGN_ENABLED? FL2_PACKET_SIGNATURES: 0;
- if(sp){
- tid = sp->tid;
- // FIXME! if(sp->options & SMB_SHARE_IS_IN_DFS)
- // FIXME! dfs = FL2_DFS;
- }
- p = emalloc9p(sizeof(Pkt) + MTU);
- memset(p, 0, sizeof(Pkt) +MTU);
- p->buf = (uchar *)p + sizeof(Pkt);
- p->s = s;
- qlock(&s->seqlock);
- if(s->seqrun){
- p->seq = s->seq;
- s->seq = (s->seq + 2) % 0x10000;
- }
- qunlock(&s->seqlock);
- nbthdr(p);
- pmem(p, magic, nelem(magic));
- p8(p, cmd);
- pl32(p, 0); /* status (error) */
- p8(p, FL_CASELESS_NAMES | FL_CANNONICAL_NAMES); /* flags */
- pl16(p, s->flags2 | dfs | sign); /* flags2 */
- pl16(p, (s->pid >> 16) & 0xffff); /* PID MS bits */
- pl32(p, p->seq); /* MAC / sequence number */
- pl32(p, 0); /* MAC */
- pl16(p, 0); /* padding */
- pl16(p, tid);
- pl16(p, s->pid & 0xffff);
- pl16(p, s->uid);
- pl16(p, s->mid);
- p->wordbase = p8(p, 0); /* filled in by pbytes() */
- return p;
- }
- void
- pbytes(Pkt *p)
- {
- int n;
- assert(p->wordbase != nil); /* cifshdr not called */
- assert(p->bytebase == nil); /* called twice */
- n = p->pos - p->wordbase;
- assert(n % 2 != 0); /* even addr */
- *p->wordbase = n / 2;
- p->bytebase = pl16(p, 0); /* filled in by cifsrpc() */
- }
- static void
- dmp(int seq, uchar *buf)
- {
- int i;
- if(seq == 99)
- print("\n ");
- else
- print("%+2d ", seq);
- for(i = 0; i < 8; i++)
- print("%02x ", buf[i] & 0xff);
- print("\n");
- }
- int
- cifsrpc(Pkt *p)
- {
- int flags2, got, err;
- uint tid, uid, seq;
- uchar *pos;
- char m[nelem(magic)];
- pos = p->pos;
- if(p->bytebase){
- p->pos = p->bytebase;
- pl16(p, pos - (p->bytebase + 2)); /* 2 = sizeof bytecount */
- }
- p->pos = pos;
- if(p->s->secmode & SECMODE_SIGN_ENABLED)
- macsign(p, p->seq);
- qlock(&p->s->rpclock);
- got = nbtrpc(p);
- qunlock(&p->s->rpclock);
- if(got == -1)
- return -1;
- gmem(p, m, nelem(magic));
- if(memcmp(m, magic, nelem(magic)) != 0){
- werrstr("cifsrpc: bad magic number in packet %20ux%02ux%02ux%02ux",
- m[0], m[1], m[2], m[3]);
- return -1;
- }
- g8(p); /* cmd */
- err = gl32(p); /* errcode */
- g8(p); /* flags */
- flags2 = gl16(p); /* flags2 */
- gl16(p); /* PID MS bits */
- seq = gl32(p); /* reserved */
- gl32(p); /* MAC (if in use) */
- gl16(p); /* Padding */
- tid = gl16(p); /* TID */
- gl16(p); /* PID lsbs */
- uid = gl16(p); /* UID */
- gl16(p); /* mid */
- g8(p); /* word count */
- if(p->s->secmode & SECMODE_SIGN_ENABLED){
- if(macsign(p, p->seq+1) != 0 && p->s->seqrun){
- werrstr("cifsrpc: invalid packet signature");
- print("MAC signature bad\n");
- // FIXME: for debug only return -1;
- }
- }else{
- /*
- * We allow the sequence number of zero as some old samba
- * servers seem to fall back to this unexpectedly
- * after reporting sequence numbers correctly for a while.
- *
- * Some other samba servers seem to always report a sequence
- * number of zero if MAC signing is disabled, so we have to
- * catch that too.
- */
- if(p->s->seqrun && seq != p->seq && seq != 0){
- werrstr("%ux != %ux bad sequence number", seq, p->seq);
- return -1;
- }
- }
- p->tid = tid;
- if(p->s->uid == NO_UID)
- p->s->uid = uid;
- if(flags2 & FL2_NT_ERRCODES){
- /* is it a real error rather than info/warning/chatter */
- if((err & 0xF0000000) == 0xC0000000){
- werrstr("%s", nterrstr(err));
- return -1;
- }
- }else{
- if(err){
- werrstr("%s", doserrstr(err));
- return -1;
- }
- }
- return got;
- }
- /*
- * Some older servers (old samba) prefer to talk older
- * dialects but if given no choice they will talk the
- * more modern ones, so we don't give them the choice.
- */
- int
- CIFSnegotiate(Session *s, long *svrtime, char *domain, int domlen, char *cname, int cnamlen)
- {
- int d, i;
- char *ispeak = "NT LM 0.12";
- char *dialects[] = {
- // { "PC NETWORK PROGRAM 1.0"},
- // { "MICROSOFT NETWORKS 1.03"},
- // { "MICROSOFT NETWORKS 3.0"},
- // { "LANMAN1.0"},
- // { "LM1.2X002"},
- // { "NT LANMAN 1.0"},
- { "NT LM 0.12" },
- };
- Pkt *p;
- p = cifshdr(s, nil, SMB_COM_NEGOTIATE);
- pbytes(p);
- for(i = 0; i < nelem(dialects); i++){
- p8(p, STR_DIALECT);
- pstr(p, dialects[i]);
- }
- if(cifsrpc(p) == -1){
- free(p);
- return -1;
- }
- d = gl16(p);
- if(d < 0 || d > nelem(dialects)){
- werrstr("no CIFS dialect in common");
- free(p);
- return -1;
- }
- if(strcmp(dialects[d], ispeak) != 0){
- werrstr("%s dialect unsupported", dialects[d]);
- free(p);
- return -1;
- }
- s->secmode = g8(p); /* Security mode */
- gl16(p); /* Max outstanding requests */
- gl16(p); /* Max VCs */
- s->mtu = gl32(p); /* Max buffer size */
- gl32(p); /* Max raw buffer size (depricated) */
- gl32(p); /* Session key */
- s->caps = gl32(p); /* Server capabilities */
- *svrtime = gvtime(p); /* fileserver time */
- s->tz = (short)gl16(p) * 60; /* TZ in mins, is signed (SNIA doc is wrong) */
- s->challen = g8(p); /* Encryption key length */
- gl16(p);
- gmem(p, s->chal, s->challen); /* Get the challenge */
- gstr(p, domain, domlen); /* source domain */
- { /* NetApp Filer seem not to report its called name */
- char *cn = emalloc9p(cnamlen);
- gstr(p, cn, cnamlen); /* their name */
- if(strlen(cn) > 0)
- memcpy(cname, cn, cnamlen);
- free(cn);
- }
- if(s->caps & CAP_UNICODE)
- s->flags2 |= FL2_UNICODE;
- free(p);
- return 0;
- }
- int
- CIFSsession(Session *s)
- {
- char os[64], *q;
- Rune r;
- Pkt *p;
- enum {
- mycaps = CAP_UNICODE | CAP_LARGE_FILES | CAP_NT_SMBS |
- CAP_NT_FIND | CAP_STATUS32,
- };
- s->seqrun = 1; /* activate the sequence number generation/checking */
- p = cifshdr(s, nil, SMB_COM_SESSION_SETUP_ANDX);
- p8(p, 0xFF); /* No secondary command */
- p8(p, 0); /* Reserved (must be zero) */
- pl16(p, 0); /* Offset to next command */
- pl16(p, MTU); /* my max buffer size */
- pl16(p, 1); /* my max multiplexed pending requests */
- pl16(p, 0); /* Virtual connection # */
- pl32(p, 0); /* Session key (if vc != 0) */
- if((s->secmode & SECMODE_PW_ENCRYPT) == 0) {
- pl16(p, utflen(Sess->auth->resp[0])*2 + 2); /* passwd size */
- pl16(p, utflen(Sess->auth->resp[0])*2 + 2); /* passwd size (UPPER CASE) */
- pl32(p, 0); /* Reserved */
- pl32(p, mycaps);
- pbytes(p);
- for(q = Sess->auth->resp[0]; *q; ){
- q += chartorune(&r, q);
- pl16(p, toupperrune(r));
- }
- pl16(p, 0);
- for(q = Sess->auth->resp[0]; *q; ){
- q += chartorune(&r, q);
- pl16(p, r);
- }
- pl16(p, 0);
- }else{
- pl16(p, Sess->auth->len[0]); /* LM passwd size */
- pl16(p, Sess->auth->len[1]); /* NTLM passwd size */
- pl32(p, 0); /* Reserved */
- pl32(p, mycaps);
- pbytes(p);
- pmem(p, Sess->auth->resp[0], Sess->auth->len[0]);
- pmem(p, Sess->auth->resp[1], Sess->auth->len[1]);
- }
- pstr(p, Sess->auth->user); /* Account name */
- pstr(p, Sess->auth->windom); /* Primary domain */
- pstr(p, "plan9"); /* Client OS */
- pstr(p, argv0); /* Client LAN Manager type */
- if(cifsrpc(p) == -1){
- free(p);
- return -1;
- }
- g8(p); /* Reserved (0) */
- gl16(p); /* Offset to next command wordcount */
- Sess->isguest = gl16(p) & 1; /* logged in as guest */
- gl16(p);
- gl16(p);
- /* no security blob here - we don't understand extended security anyway */
- gstr(p, os, sizeof(os));
- s->remos = estrdup9p(os);
- free(p);
- return 0;
- }
- CIFStreeconnect(Session *s, char *cname, char *tree, Share *sp)
- {
- int len;
- char *resp, *path;
- char zeros[24];
- Pkt *p;
- resp = Sess->auth->resp[0];
- len = Sess->auth->len[0];
- if((s->secmode & SECMODE_USER) != SECMODE_USER){
- memset(zeros, 0, sizeof(zeros));
- resp = zeros;
- len = sizeof(zeros);
- }
- p = cifshdr(s, nil, SMB_COM_TREE_CONNECT_ANDX);
- p8(p, 0xFF); /* Secondary command */
- p8(p, 0); /* Reserved */
- pl16(p, 0); /* Offset to next Word Count */
- pl16(p, 0); /* Flags */
- if((s->secmode & SECMODE_PW_ENCRYPT) == 0){
- pl16(p, len+1); /* password len, including null */
- pbytes(p);
- pascii(p, resp);
- }else{
- pl16(p, len);
- pbytes(p);
- pmem(p, resp, len);
- }
- path = smprint("//%s/%s", cname, tree);
- strupr(path);
- ppath(p, path); /* path */
- free(path);
- pascii(p, "?????"); /* service type any (so we can do RAP calls) */
- if(cifsrpc(p) == -1){
- free(p);
- return -1;
- }
- g8(p); /* Secondary command */
- g8(p); /* Reserved */
- gl16(p); /* Offset to next command */
- sp->options = g8(p); /* options supported */
- sp->tid = p->tid; /* get received TID from packet header */
- free(p);
- return 0;
- }
- int
- CIFSlogoff(Session *s)
- {
- int rc;
- Pkt *p;
- p = cifshdr(s, nil, SMB_COM_LOGOFF_ANDX);
- p8(p, 0xFF); /* No ANDX command */
- p8(p, 0); /* Reserved (must be zero) */
- pl16(p, 0); /* offset ot ANDX */
- pbytes(p);
- rc = cifsrpc(p);
- free(p);
- return rc;
- }
- int
- CIFStreedisconnect(Session *s, Share *sp)
- {
- int rc;
- Pkt *p;
- p = cifshdr(s, sp, SMB_COM_TREE_DISCONNECT);
- pbytes(p);
- rc = cifsrpc(p);
- free(p);
- return rc;
- }
- int
- CIFSdeletefile(Session *s, Share *sp, char *name)
- {
- int rc;
- Pkt *p;
- p = cifshdr(s, sp, SMB_COM_DELETE);
- pl16(p, ATTR_HIDDEN|ATTR_SYSTEM); /* search attributes */
- pbytes(p);
- p8(p, STR_ASCII); /* buffer format */
- ppath(p, name);
- rc = cifsrpc(p);
- free(p);
- return rc;
- }
- int
- CIFSdeletedirectory(Session *s, Share *sp, char *name)
- {
- int rc;
- Pkt *p;
- p = cifshdr(s, sp, SMB_COM_DELETE_DIRECTORY);
- pbytes(p);
- p8(p, STR_ASCII); /* buffer format */
- ppath(p, name);
- rc = cifsrpc(p);
- free(p);
- return rc;
- }
- int
- CIFScreatedirectory(Session *s, Share *sp, char *name)
- {
- int rc;
- Pkt *p;
- p = cifshdr(s, sp, SMB_COM_CREATE_DIRECTORY);
- pbytes(p);
- p8(p, STR_ASCII);
- ppath(p, name);
- rc = cifsrpc(p);
- free(p);
- return rc;
- }
- int
- CIFSrename(Session *s, Share *sp, char *old, char *new)
- {
- int rc;
- Pkt *p;
- p = cifshdr(s, sp, SMB_COM_RENAME);
- pl16(p, ATTR_HIDDEN|ATTR_SYSTEM|ATTR_DIRECTORY); /* search attributes */
- pbytes(p);
- p8(p, STR_ASCII);
- ppath(p, old);
- p8(p, STR_ASCII);
- ppath(p, new);
- rc = cifsrpc(p);
- free(p);
- return rc;
- }
- /* for NT4/Win2k/XP */
- 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)
- {
- Pkt *p;
- int fh;
- p = cifshdr(s, sp, SMB_COM_NT_CREATE_ANDX);
- p8(p, 0xFF); /* Secondary command */
- p8(p, 0); /* Reserved */
- pl16(p, 0); /* Offset to next command */
- p8(p, 0); /* Reserved */
- pl16(p, utflen(name) *2); /* file name len */
- pl32(p, flags); /* Flags */
- pl32(p, 0); /* fid of cwd, if relative path */
- pl32(p, access); /* access desired */
- pl64(p, 0); /* initial allocation size */
- pl32(p, attrs); /* Extended attributes */
- pl32(p, share); /* Share Access */
- pl32(p, action); /* What to do on success/failure */
- pl32(p, options); /* Options */
- pl32(p, SECURITY_IMPERSONATION); /* Impersonation level */
- p8(p, SECURITY_CONTEXT_TRACKING | SECURITY_EFFECTIVE_ONLY); /* security flags */
- pbytes(p);
- p8(p, 0); /* FIXME: padding? */
- ppath(p, name); /* filename */
- if(cifsrpc(p) == -1){
- free(p);
- return -1;
- }
- memset(fi, 0, sizeof(FInfo));
- g8(p); /* Secondary command */
- g8(p); /* Reserved */
- gl16(p); /* Offset to next command */
- g8(p); /* oplock granted */
- fh = gl16(p); /* FID for opened object */
- *result = gl32(p); /* create action taken */
- gl64(p); /* creation time */
- fi->accessed = gvtime(p); /* last access time */
- fi->written = gvtime(p); /* last written time */
- fi->changed = gvtime(p); /* change time */
- fi->attribs = gl32(p); /* extended attributes */
- gl64(p); /* bytes allocated */
- fi->size = gl64(p); /* file size */
- free(p);
- return fh;
- }
- /* for Win95/98/ME */
- CIFS_SMB_opencreate(Session *s, Share *sp, char *name, int access,
- int attrs, int action, int *result)
- {
- Pkt *p;
- int fh;
- p = cifshdr(s, sp, SMB_COM_OPEN_ANDX);
- p8(p, 0xFF); /* Secondary command */
- p8(p, 0); /* Reserved */
- pl16(p, 0); /* Offset to next command */
- pl16(p, 0); /* Flags (0 == no stat(2) info) */
- pl16(p, access); /* desired access */
- pl16(p, ATTR_HIDDEN|ATTR_SYSTEM);/* search attributes */
- pl16(p, attrs); /* file attribytes */
- pdatetime(p, 0); /* creation time (0 == now) */
- pl16(p, action); /* What to do on success/failure */
- pl32(p, 0); /* allocation size */
- pl32(p, 0); /* reserved */
- pl32(p, 0); /* reserved */
- pbytes(p);
- ppath(p, name); /* filename */
- if(cifsrpc(p) == -1){
- free(p);
- return -1;
- }
- g8(p); /* Secondary command */
- g8(p); /* Reserved */
- gl16(p); /* Offset to next command */
- fh = gl16(p); /* FID for opened object */
- gl16(p); /* extended attributes */
- gvtime(p); /* last written time */
- gl32(p); /* file size */
- gl16(p); /* file type (disk/fifo/printer etc) */
- gl16(p); /* device status (for fifos) */
- *result = gl16(p); /* access granted */
- free(p);
- return fh;
- }
- vlong
- CIFSwrite(Session *s, Share *sp, int fh, uvlong off, void *buf, vlong n)
- {
- Pkt *p;
- vlong got;
- /* FIXME: Payload should be padded to long boundary */
- assert((n & 0xffffffff00000000LL) == 0 || s->caps & CAP_LARGE_FILES);
- assert((off & 0xffffffff00000000LL) == 0 || s->caps & CAP_LARGE_FILES);
- assert(n < s->mtu - T2HDRLEN || s->caps & CAP_LARGE_WRITEX);
- p = cifshdr(s, sp, SMB_COM_WRITE_ANDX);
- p8(p, 0xFF); /* Secondary command */
- p8(p, 0); /* Reserved */
- pl16(p, 0); /* Offset to next command */
- pl16(p, fh); /* File handle */
- pl32(p, off & 0xffffffff); /* LSBs of Offset */
- pl32(p, 0); /* Reserved (0) */
- pl16(p, s->nocache); /* Write mode (0 - write through) */
- pl16(p, 0); /* Bytes remaining */
- pl16(p, n >> 16); /* MSBs of length */
- pl16(p, n & 0xffffffff); /* LSBs of length */
- pl16(p, T2HDRLEN); /* Offset to data, in bytes */
- pl32(p, off >> 32); /* MSBs of offset */
- pbytes(p);
- p->pos = p->buf +T2HDRLEN +NBHDRLEN;
- pmem(p, buf, n); /* Data */
- if(cifsrpc(p) == -1){
- free(p);
- return -1;
- }
- g8(p); /* Secondary command */
- g8(p); /* Reserved */
- gl16(p); /* Offset to next command */
- got = gl16(p); /* LSWs of bytes written */
- gl16(p); /* remaining (space ?) */
- got |= (gl16(p) << 16); /* MSWs of bytes written */
- free(p);
- return got;
- }
- vlong
- CIFSread(Session *s, Share *sp, int fh, uvlong off, void *buf, vlong n,
- vlong minlen)
- {
- int doff;
- vlong got;
- Pkt *p;
- assert((n & 0xffffffff00000000LL) == 0 || s->caps & CAP_LARGE_FILES);
- assert((off & 0xffffffff00000000LL) == 0 || s->caps & CAP_LARGE_FILES);
- assert(n < s->mtu - T2HDRLEN || s->caps & CAP_LARGE_READX);
- p = cifshdr(s, sp, SMB_COM_READ_ANDX);
- p8(p, 0xFF); /* Secondary command */
- p8(p, 0); /* Reserved */
- pl16(p, 0); /* Offset to next command */
- pl16(p, fh); /* File handle */
- pl32(p, off & 0xffffffff); /* Offset to beginning of write */
- pl16(p, n); /* Maximum number of bytes to return */
- pl16(p, minlen); /* Minimum number of bytes to return */
- pl32(p, (uint)n >> 16); /* MSBs of maxlen */
- pl16(p, 0); /* Bytes remaining to satisfy request */
- pl32(p, off >> 32); /* MS 32 bits of offset */
- pbytes(p);
- if(cifsrpc(p) == -1){
- free(p);
- return -1;
- }
- g8(p); /* Secondary command */
- g8(p); /* Reserved */
- gl16(p); /* Offset to next command */
- gl16(p); /* Remaining */
- gl16(p); /* Compression mode */
- gl16(p); /* Reserved */
- got = gl16(p); /* length */
- doff = gl16(p); /* Offset from header to data */
- got |= gl16(p) << 16;
- p->pos = p->buf + doff + NBHDRLEN;
- gmem(p, buf, got); /* data */
- free(p);
- return got;
- }
- int
- CIFSflush(Session *s, Share *sp, int fh)
- {
- int rc;
- Pkt *p;
- p = cifshdr(s, sp, SMB_COM_FLUSH);
- pl16(p, fh); /* fid */
- pbytes(p);
- rc = cifsrpc(p);
- free(p);
- return rc;
- }
- /*
- * Setting the time of last write to -1 gives "now" if the file
- * was written and leaves it the same if the file wasn't written.
- */
- int
- CIFSclose(Session *s, Share *sp, int fh)
- {
- int rc;
- Pkt *p;
- p = cifshdr(s, sp, SMB_COM_CLOSE);
- pl16(p, fh); /* fid */
- pl32(p, ~0L); /* Time of last write (none) */
- pbytes(p);
- rc = cifsrpc(p);
- free(p);
- return rc;
- }
- int
- CIFSfindclose2(Session *s, Share *sp, int sh)
- {
- int rc;
- Pkt *p;
- p = cifshdr(s, sp, SMB_COM_FIND_CLOSE2);
- pl16(p, sh); /* sid */
- pbytes(p);
- rc = cifsrpc(p);
- free(p);
- return rc;
- }
- int
- CIFSecho(Session *s)
- {
- Pkt *p;
- int rc;
- p = cifshdr(s, nil, SMB_COM_ECHO);
- pl16(p, 1); /* number of replies */
- pbytes(p);
- pascii(p, "abcdefghijklmnopqrstuvwxyz"); /* data */
- rc = cifsrpc(p);
- free(p);
- return rc;
- }
- int
- CIFSsetinfo(Session *s, Share *sp, char *path, FInfo *fip)
- {
- int rc;
- Pkt *p;
- p = cifshdr(s, sp, SMB_COM_SET_INFORMATION);
- pl16(p, fip->attribs);
- pl32(p, time(nil) - s->tz); /* modified time */
- pl64(p, 0); /* reserved */
- pl16(p, 0); /* reserved */
- pbytes(p);
- p8(p, STR_ASCII); /* buffer format */
- ppath(p, path);
- rc = cifsrpc(p);
- free(p);
- return rc;
- }
|