int smbfs_smb_move(struct smbnode *src, struct smbnode *tdnp, const char *tname, int tnmlen, u_int16_t flags, struct smb_cred *scred) { struct smb_rq *rqp; struct smb_share *ssp = src->n_mount->sm_share; struct mbchain *mbp; int error; error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_MOVE, scred, &rqp); if (error) return error; smb_rq_getrequest(rqp, &mbp); smb_rq_wstart(rqp); mb_put_uint16le(mbp, SMB_TID_UNKNOWN); mb_put_uint16le(mbp, 0x20); /* delete target file */ mb_put_uint16le(mbp, flags); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_ASCII); do { error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0); if (error) break; mb_put_uint8(mbp, SMB_DT_ASCII); error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen); if (error) break; smb_rq_bend(rqp); error = smb_rq_simple(rqp); } while(0); smb_rq_done(rqp); return error; }
int smbfs_smb_setfsize(struct smbnode *np, u_quad_t newsize, struct smb_cred *scred) { struct smb_share *ssp = np->n_mount->sm_share; struct smb_rq *rqp; struct mbchain *mbp; int error; if (newsize >= (1LL << 32)) { if (!(SMB_CAPS(SSTOVC(ssp)) & SMB_CAP_LARGE_FILES)) return EFBIG; return smbfs_smb_seteof(np, (int64_t)newsize, scred); } error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp); if (error) return error; smb_rq_getrequest(rqp, &mbp); smb_rq_wstart(rqp); mb_put_mem(mbp, (void *)&np->n_fid, 2, MB_MSYSTEM); mb_put_uint16le(mbp, 0); mb_put_uint32le(mbp, newsize); mb_put_uint16le(mbp, 0); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_DATA); mb_put_uint16le(mbp, 0); smb_rq_bend(rqp); error = smb_rq_simple(rqp); smb_rq_done(rqp); return error; }
static int smbfs_smb_seteof(struct smbnode *np, int64_t newsize, struct smb_cred *scred) { struct smb_t2rq *t2p; struct smb_share *ssp = np->n_mount->sm_share; struct mbchain *mbp; int error; error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, scred, &t2p); if (error) return error; mbp = &t2p->t2_tparam; mb_init(mbp); mb_put_mem(mbp, (void *)&np->n_fid, 2, MB_MSYSTEM); mb_put_uint16le(mbp, SMB_SET_FILE_END_OF_FILE_INFO); mb_put_uint32le(mbp, 0); mbp = &t2p->t2_tdata; mb_init(mbp); mb_put_int64le(mbp, newsize); mb_put_uint32le(mbp, 0); /* padding */ mb_put_uint16le(mbp, 0); t2p->t2_maxpcount = 2; t2p->t2_maxdcount = 0; error = smb_t2_request(t2p); smb_t2_done(t2p); return error; }
static int mb_put_acl(mbchain_t *mbp, i_ntacl_t *acl) { i_ntace_t **acep; uint16_t acl_len, *acl_len_p; int i, cnt0, error; cnt0 = mbp->mb_count; ERRCHK(mb_put_uint8(mbp, acl->acl_revision)); ERRCHK(mb_put_uint8(mbp, 0)); /* pad1 */ acl_len_p = mb_reserve(mbp, sizeof (*acl_len_p)); if (acl_len_p == NULL) { error = ENOMEM; goto errout; } ERRCHK(mb_put_uint16le(mbp, acl->acl_acecount)); ERRCHK(mb_put_uint16le(mbp, 0)); /* pad2 */ acep = &acl->acl_acevec[0]; for (i = 0; i < acl->acl_acecount; i++) { ERRCHK(mb_put_ace(mbp, *acep)); acep++; } /* Fill in acl_len_p */ acl_len = mbp->mb_count - cnt0; *acl_len_p = htoles(acl_len); /* Success! */ return (0); errout: return (error); }
int smbfs_smb_setfsize(struct smbnode *np, int newsize, struct smb_cred *scred) { struct smb_share *ssp = np->n_mount->sm_share; struct smb_rq rq, *rqp = &rq; struct mbchain *mbp; int error; if (!smbfs_smb_seteof(np, (int64_t) newsize, scred)) { np->n_flag |= NFLUSHWIRE; return (0); } error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_WRITE, scred); if (error) return error; smb_rq_getrequest(rqp, &mbp); smb_rq_wstart(rqp); mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); mb_put_uint16le(mbp, 0); mb_put_uint32le(mbp, newsize); mb_put_uint16le(mbp, 0); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_DATA); mb_put_uint16le(mbp, 0); smb_rq_bend(rqp); error = smb_rq_simple(rqp); smb_rq_done(rqp); return error; }
static int smb_smb_write(struct smb_share *ssp, uint16_t fid, uint32_t *lenp, uio_t *uiop, smb_cred_t *scred, int timo) { struct smb_rq *rqp; struct mbchain *mbp; struct mdchain *mdp; int error; uint32_t off32; uint16_t cnt, rcnt, todo; uint8_t wc; ASSERT(uiop->uio_loffset <= UINT32_MAX); off32 = (uint32_t)uiop->uio_loffset; ASSERT(*lenp <= UINT16_MAX); cnt = (uint16_t)*lenp; /* This next is an "estimate" of planned writes. */ todo = (uint16_t)min(uiop->uio_resid, UINT16_MAX); error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp); if (error) return (error); smb_rq_getrequest(rqp, &mbp); smb_rq_wstart(rqp); mb_put_uint16le(mbp, fid); mb_put_uint16le(mbp, cnt); mb_put_uint32le(mbp, off32); mb_put_uint16le(mbp, todo); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_DATA); mb_put_uint16le(mbp, cnt); error = mb_put_uio(mbp, uiop, *lenp); if (error) goto out; smb_rq_bend(rqp); if (timo == 0) timo = smb_timo_write; error = smb_rq_simple_timed(rqp, timo); if (error) goto out; smb_rq_getreply(rqp, &mdp); error = md_get_uint8(mdp, &wc); if (error) goto out; if (wc != 1) { error = EBADRPC; goto out; } error = md_get_uint16le(mdp, &rcnt); if (error) goto out; *lenp = rcnt; out: smb_rq_done(rqp); return (error); }
static inline int smb_smb_read(struct smb_share *ssp, u_int16_t fid, size_t *len, size_t *rresid, struct uio *uio, struct smb_cred *scred) { struct smb_rq *rqp; struct mbchain *mbp; struct mdchain *mdp; u_int16_t resid, bc; u_int8_t wc; int error, rlen, blksz; /* Cannot read at/beyond 4G */ if (uio->uio_offset >= (1LL << 32)) return (EFBIG); error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_READ, scred, &rqp); if (error) return error; blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 16; rlen = *len = min(blksz, *len); smb_rq_getrequest(rqp, &mbp); smb_rq_wstart(rqp); mb_put_mem(mbp, (void *)&fid, sizeof(fid), MB_MSYSTEM); mb_put_uint16le(mbp, rlen); mb_put_uint32le(mbp, uio->uio_offset); mb_put_uint16le(mbp, min(uio->uio_resid, 0xffff)); smb_rq_wend(rqp); smb_rq_bstart(rqp); smb_rq_bend(rqp); do { error = smb_rq_simple(rqp); if (error) break; smb_rq_getreply(rqp, &mdp); md_get_uint8(mdp, &wc); if (wc != 5) { error = EBADRPC; break; } md_get_uint16le(mdp, &resid); md_get_mem(mdp, NULL, 4 * 2, MB_MSYSTEM); md_get_uint16le(mdp, &bc); md_get_uint8(mdp, NULL); /* ignore buffer type */ md_get_uint16le(mdp, &resid); if (resid == 0) { *rresid = resid; break; } error = md_get_uio(mdp, uio, resid); if (error) break; *rresid = resid; } while(0); smb_rq_done(rqp); return error; }
static inline int smb_smb_writex(struct smb_share *ssp, u_int16_t fid, size_t *len, size_t *rresid, struct uio *uio, struct smb_cred *scred) { struct smb_rq *rqp; struct mbchain *mbp; struct mdchain *mdp; int error; u_int8_t wc; u_int16_t resid; error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE_ANDX, scred, &rqp); if (error) return (error); smb_rq_getrequest(rqp, &mbp); smb_rq_wstart(rqp); mb_put_uint8(mbp, 0xff); /* no secondary command */ mb_put_uint8(mbp, 0); /* MBZ */ mb_put_uint16le(mbp, 0); /* offset to secondary */ mb_put_mem(mbp, (void *)&fid, sizeof(fid), MB_MSYSTEM); mb_put_uint32le(mbp, uio->uio_offset); mb_put_uint32le(mbp, 0); /* MBZ (timeout) */ mb_put_uint16le(mbp, 0); /* !write-thru */ mb_put_uint16le(mbp, 0); *len = min(SSTOVC(ssp)->vc_wxmax, *len); mb_put_uint16le(mbp, *len >> 16); mb_put_uint16le(mbp, *len); mb_put_uint16le(mbp, 64); /* data offset from header start */ mb_put_uint32le(mbp, uio->uio_offset >> 32); /* OffsetHigh */ smb_rq_wend(rqp); smb_rq_bstart(rqp); do { mb_put_uint8(mbp, 0xee); /* mimic xp pad byte! */ error = mb_put_uio(mbp, uio, *len); if (error) break; smb_rq_bend(rqp); error = smb_rq_simple(rqp); if (error) break; smb_rq_getreply(rqp, &mdp); md_get_uint8(mdp, &wc); if (wc != 6) { error = EBADRPC; break; } md_get_uint8(mdp, NULL); md_get_uint8(mdp, NULL); md_get_uint16(mdp, NULL); md_get_uint16le(mdp, &resid); *rresid = resid; } while(0); smb_rq_done(rqp); return (error); }
static inline int smb_smb_write(struct smb_share *ssp, u_int16_t fid, size_t *len, size_t *rresid, struct uio *uio, struct smb_cred *scred) { struct smb_rq *rqp; struct mbchain *mbp; struct mdchain *mdp; u_int16_t resid; u_int8_t wc; int error, blksz; /* Cannot write at/beyond 4G */ if (uio->uio_offset >= (1LL << 32)) return (EFBIG); blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 16; if (blksz > 0xffff) blksz = 0xffff; resid = *len = min(blksz, *len); error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp); if (error) return error; smb_rq_getrequest(rqp, &mbp); smb_rq_wstart(rqp); mb_put_mem(mbp, (void *)&fid, sizeof(fid), MB_MSYSTEM); mb_put_uint16le(mbp, resid); mb_put_uint32le(mbp, uio->uio_offset); mb_put_uint16le(mbp, min(uio->uio_resid, 0xffff)); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_DATA); mb_put_uint16le(mbp, resid); do { error = mb_put_uio(mbp, uio, resid); if (error) break; smb_rq_bend(rqp); error = smb_rq_simple(rqp); if (error) break; smb_rq_getreply(rqp, &mdp); md_get_uint8(mdp, &wc); if (wc != 1) { error = EBADRPC; break; } md_get_uint16le(mdp, &resid); *rresid = resid; } while(0); smb_rq_done(rqp); return error; }
int smbfs_smb_open(struct smbnode *np, int accmode, struct smb_cred *scred) { struct smb_rq *rqp; struct smb_share *ssp = np->n_mount->sm_share; struct mbchain *mbp; struct mdchain *mdp; u_int8_t wc; u_int16_t fid, wattr, grantedmode; int error; rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK); error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_OPEN, scred); if (error) { free(rqp, M_SMBFSDATA); return error; } smb_rq_getrequest(rqp, &mbp); smb_rq_wstart(rqp); mb_put_uint16le(mbp, accmode); mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_ASCII); do { error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0); if (error) break; smb_rq_bend(rqp); error = smb_rq_simple(rqp); if (error) break; smb_rq_getreply(rqp, &mdp); if (md_get_uint8(mdp, &wc) != 0 || wc != 7) { error = EBADRPC; break; } md_get_uint16(mdp, &fid); md_get_uint16le(mdp, &wattr); md_get_uint32(mdp, NULL); /* mtime */ md_get_uint32(mdp, NULL); /* fsize */ md_get_uint16le(mdp, &grantedmode); /* * TODO: refresh attributes from this reply */ } while(0); smb_rq_done(rqp); free(rqp, M_SMBFSDATA); if (error) return error; np->n_fid = fid; np->n_rwstate = grantedmode; return 0; }
/* * This differs from smbfs_fullpath in * 1) no pad byte * 2) Unicode is always used * 3) no end null bytes */ int smb2fs_fullpath(struct mbchain *mbp, struct smbnode *dnp, const char *namep, size_t in_name_len, const char *strm_namep, size_t in_strm_name_len, int name_flags, uint8_t sep_char) { int error = 0; const char *name = (namep ? namep : NULL); const char *strm_name = (strm_namep ? strm_namep : NULL); size_t name_len = in_name_len; size_t strm_name_len = in_strm_name_len; size_t len = 0; uint8_t stream_sep_char = ':'; if (dnp != NULL) { struct smbmount *smp = dnp->n_mount; error = smb_fphelp(smp, mbp, dnp, TRUE, &len); if (error) { return error; } } if (name) { /* Add separator char only if we added a path from above */ if (len > 0) { error = mb_put_uint16le(mbp, sep_char); if (error) { return error; } } error = smb_put_dmem(mbp, name, name_len, name_flags, TRUE, NULL); if (error) { return error; } } /* Add Stream Name */ if (strm_name) { /* Add separator char */ error = mb_put_uint16le(mbp, stream_sep_char); if (error) { return error; } error = smb_put_dmem(mbp, strm_name, strm_name_len, name_flags, TRUE, NULL); if (error) { return error; } } return error; }
static __inline int smb_smb_write(struct smb_share *ssp, u_int16_t fid, int *len, int *rresid, struct uio *uio, struct smb_cred *scred) { struct smb_rq *rqp; struct mbchain *mbp; struct mdchain *mdp; u_int16_t resid; u_int8_t wc; int error, blksz; /* write data must be real */ KKASSERT(uio->uio_segflg != UIO_NOCOPY); blksz = SSTOVC(ssp)->vc_txmax - SMB_HDRLEN - 16; if (blksz > 0xffff) blksz = 0xffff; resid = *len = min(blksz, *len); error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_WRITE, scred, &rqp); if (error) return error; smb_rq_getrequest(rqp, &mbp); smb_rq_wstart(rqp); mb_put_mem(mbp, (caddr_t)&fid, sizeof(fid), MB_MSYSTEM); mb_put_uint16le(mbp, resid); mb_put_uint32le(mbp, uio->uio_offset); mb_put_uint16le(mbp, (unsigned short)szmin(uio->uio_resid, 0xffff)); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_DATA); mb_put_uint16le(mbp, resid); do { error = mb_put_uio(mbp, uio, resid); if (error) break; smb_rq_bend(rqp); error = smb_rq_simple(rqp); if (error) break; smb_rq_getreply(rqp, &mdp); md_get_uint8(mdp, &wc); if (wc != 1) { error = EBADRPC; break; } md_get_uint16le(mdp, &resid); *rresid = resid; } while(0); smb_rq_done(rqp); return error; }
/* * Setup a request for NT DIRECTORY CHANGE NOTIFY. */ int smbfs_smb_nt_dirnotify_setup(struct smbnode *dnp, struct smb_rq **rqpp, struct smb_cred *scred, void (*notifyhook)(void *), void *notifyarg) { struct smb_rq *rqp; struct smb_share *ssp = dnp->n_mount->sm_share; struct mbchain *mbp; int error; error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_NT_TRANSACT, scred, &rqp); if (error) return error; smb_rq_getrequest(rqp, &mbp); smb_rq_wstart(rqp); mb_put_uint8(mbp, 0xff); /* Max setup words to return */ mb_put_uint16le(mbp, 0); /* Flags (according to Samba) */ mb_put_uint32le(mbp, 0); /* Total parameter bytes being sent*/ mb_put_uint32le(mbp, 0); /* Total data bytes being sent */ mb_put_uint32le(mbp, 10*1024); /* Max parameter bytes to return */ mb_put_uint32le(mbp, 0); /* Max data bytes to return */ mb_put_uint32le(mbp, 0); /* Parameter bytes sent this buffer */ mb_put_uint32le(mbp, 0); /* Offset (from h. start) to Param */ mb_put_uint32le(mbp, 0); /* Data bytes sent this buffer */ mb_put_uint32le(mbp, 0); /* Offset (from h. start) to Data */ mb_put_uint8(mbp, 4); /* Count of setup words */ mb_put_uint16le(mbp, SMB_NTTRANS_NOTIFY_CHANGE); /* Trans func code */ /* NT TRANSACT NOTIFY CHANGE: Request Change Notification */ mb_put_uint32le(mbp, FILE_NOTIFY_CHANGE_NAME|FILE_NOTIFY_CHANGE_ATTRIBUTES| FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE| FILE_NOTIFY_CHANGE_CREATION); /* CompletionFilter */ mb_put_mem(mbp, (void *)&dnp->n_fid, 2, MB_MSYSTEM); /* FID */ mb_put_uint8(mbp, 0); /* WatchTree - Watch all subdirs too */ mb_put_uint8(mbp, 0); /* Reserved - must be zero */ smb_rq_wend(rqp); smb_rq_bstart(rqp); smb_rq_bend(rqp); /* No timeout */ rqp->sr_timo = -1; smb_rq_setcallback(rqp, notifyhook, notifyarg); error = smb_rq_enqueue(rqp); if (!error) *rqpp = rqp; else smb_rq_done(rqp); return (error); }
/* * If both dir and name are NULL, then in target there's already a looked-up * entry that wants to be opened. */ int ncp_open_create_file_or_subdir(struct nwmount *nmp,struct vnode *dvp,int namelen, char *name, int open_create_mode, u_int32_t create_attributes, int desired_acc_rights, struct ncp_open_info *nop, struct thread *td,struct ucred *cred) { struct ncp_conn *conn=NWFSTOCONN(nmp); struct ncp_rq *rqp; u_int16_t search_attribs = SA_ALL & (~SA_SUBDIR_FILES); u_int8_t volnum; u_int32_t dirent; int error; error = ncp_rq_alloc(87, conn, td, cred, &rqp); if (error) return error; volnum = nmp->n_volume; dirent = VTONW(dvp)->n_fid.f_id; if ((create_attributes & aDIR) != 0) { search_attribs |= SA_SUBDIR_FILES; } mb_put_uint8(&rqp->rq, 1);/* subfunction */ mb_put_uint8(&rqp->rq, nmp->name_space); mb_put_uint8(&rqp->rq, open_create_mode); mb_put_uint16le(&rqp->rq, search_attribs); mb_put_uint32le(&rqp->rq, IM_ALL); mb_put_uint32le(&rqp->rq, create_attributes); /* * The desired acc rights seem to be the inherited rights mask for * directories */ mb_put_uint16le(&rqp->rq, desired_acc_rights); ncp_rq_dbase_path(rqp, volnum, dirent, namelen, name, &nmp->m.nls); error = ncp_request(rqp); if (error) { if (error == NWE_FILE_NO_CREATE_PRIV) error = EACCES; return error; } md_get_uint32le(&rqp->rp, &nop->origfh); md_get_uint8(&rqp->rp, &nop->action); md_get_uint8(&rqp->rp, NULL); /* skip */ error = ncp_extract_file_info(nmp, rqp, &nop->fattr, 1); ncp_rq_done(rqp); ConvertToNWfromDWORD(nop->origfh, &nop->fh); return error; }
int ncp_search_for_file_or_subdir(struct nwmount *nmp, struct nw_search_seq *seq, struct nw_entry_info *target, struct thread *td,struct ucred *cred) { struct ncp_conn *conn = NWFSTOCONN(nmp); struct ncp_rq *rqp; int error; error = ncp_rq_alloc(87, conn, td, cred, &rqp); if (error) return error; mb_put_uint8(&rqp->rq, 3); /* subfunction */ mb_put_uint8(&rqp->rq, nmp->name_space); mb_put_uint8(&rqp->rq, 0); /* data stream */ mb_put_uint16le(&rqp->rq, 0xffff); /* Search attribs */ mb_put_uint32le(&rqp->rq, IM_ALL); /* return info mask */ mb_put_mem(&rqp->rq, (caddr_t)seq, 9, MB_MSYSTEM); mb_put_uint8(&rqp->rq, 2); /* 2 byte pattern */ mb_put_uint8(&rqp->rq, 0xff); /* following is a wildcard */ mb_put_uint8(&rqp->rq, '*'); rqp->nr_minrplen = sizeof(*seq) + 1 + NCP_INFOSZ + 1; error = ncp_request(rqp); if (error) return error; md_get_mem(&rqp->rp, (caddr_t)seq, sizeof(*seq), MB_MSYSTEM); md_get_uint8(&rqp->rp, NULL); /* skip */ error = ncp_extract_file_info(nmp, rqp, target, 1); ncp_rq_done(rqp); return error; }
int smbio_close_file(void *ctx, int fid) { struct smb_usr_rq *rqp; mbchain_t mbp; int error; u_int16_t fid16 = fid; error = smb_usr_rq_init(ctx, SMB_COM_CLOSE, 0, &rqp); if (error) return error; mbp = smb_usr_rq_getrequest(rqp); smb_usr_rq_wstart(rqp); mb_put_uint16le(mbp, fid16); /* * Never set the modify time on close. Just a really bad idea! * * Leach and SNIA docs say to send zero here. X/Open says * 0 and -1 both are leaving timestamp up to the server. * Win9x treats zero as a real time-to-be-set! We send -1, * same as observed with smbclient. */ mb_put_uint32le(mbp, -1); smb_usr_rq_wend(rqp); smb_usr_rq_bstart(rqp); smb_usr_rq_bend(rqp); error = smb_usr_rq_simple(rqp); smb_usr_rq_done(rqp); return error; }
/* * Returns information for a (one-component) name relative to the specified * directory. */ int ncp_obtain_info(struct nwmount *nmp, u_int32_t dirent, int namelen, char *path, struct nw_entry_info *target, struct thread *td,struct ucred *cred) { struct ncp_conn *conn=NWFSTOCONN(nmp); struct ncp_rq *rqp; int error; u_char volnum = nmp->n_volume, ns; if (target == NULL) { NCPFATAL("target == NULL\n"); return EINVAL; } ns = (path == NULL || path[0] == 0) ? NW_NS_DOS : nmp->name_space; error = ncp_rq_alloc(87, conn, td, cred, &rqp); if (error) return error; mb_put_uint8(&rqp->rq, 6); /* subfunction */ mb_put_uint8(&rqp->rq, ns); mb_put_uint8(&rqp->rq, ns); /* DestNameSpace */ mb_put_uint16le(&rqp->rq, 0xff); /* get all */ mb_put_uint32le(&rqp->rq, IM_ALL); ncp_rq_dbase_path(rqp, volnum, dirent, namelen, path, &nmp->m.nls); error = ncp_request(rqp); if (error) return error; error = ncp_extract_file_info(nmp, rqp, target, path != NULL); ncp_rq_done(rqp); return error; }
int smb_smb_ssnclose(struct smb_vc *vcp, struct smb_cred *scred) { struct smb_rq *rqp; struct mbchain *mbp; int error; if (vcp->vc_smbuid == SMB_UID_UNKNOWN) return 0; if (smb_smb_nomux(vcp, scred, __func__) != 0) return EINVAL; error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_LOGOFF_ANDX, scred, &rqp); if (error) return error; mbp = &rqp->sr_rq; smb_rq_wstart(rqp); mb_put_uint8(mbp, 0xff); mb_put_uint8(mbp, 0); mb_put_uint16le(mbp, 0); smb_rq_wend(rqp); smb_rq_bstart(rqp); smb_rq_bend(rqp); error = smb_rq_simple(rqp); SMBSDEBUG("%d\n", error); smb_rq_done(rqp); return error; }
int ncp_nsrename(struct ncp_conn *conn, int volume, int ns, int oldtype, struct ncp_nlstables *nt, nwdirent fdir, char *old_name, int oldlen, nwdirent tdir, char *new_name, int newlen, struct thread *td, struct ucred *cred) { struct ncp_rq *rqp; int error; error = ncp_rq_alloc(87, conn, td, cred, &rqp); if (error) return error; mb_put_uint8(&rqp->rq, 4); mb_put_uint8(&rqp->rq, ns); mb_put_uint8(&rqp->rq, 1); /* RRenameToMySelf */ mb_put_uint16le(&rqp->rq, oldtype); /* source Handle Path */ mb_put_uint8(&rqp->rq, volume); mb_put_mem(&rqp->rq, (c_caddr_t)&fdir, sizeof(fdir), MB_MSYSTEM); mb_put_uint8(&rqp->rq, 1); mb_put_uint8(&rqp->rq, 1); /* 1 source component */ /* dest Handle Path */ mb_put_uint8(&rqp->rq, volume); mb_put_mem(&rqp->rq, (c_caddr_t)&tdir, sizeof(tdir), MB_MSYSTEM); mb_put_uint8(&rqp->rq, 1); mb_put_uint8(&rqp->rq, 1); /* 1 destination component */ ncp_rq_pathstring(rqp, oldlen, old_name, nt); ncp_rq_pathstring(rqp, newlen, new_name, nt); error = ncp_request(rqp); if (!error) ncp_rq_done(rqp); return error; }
int smb_smb_ssnclose(struct smb_vc *vcp, struct smb_cred *scred) { struct smb_rq *rqp; struct mbchain *mbp; int error; KASSERT(scred->scr_l == vcp->vc_iod->iod_l); if (vcp->vc_smbuid == SMB_UID_UNKNOWN) return 0; error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_LOGOFF_ANDX, scred, &rqp); if (error) return error; mbp = &rqp->sr_rq; smb_rq_wstart(rqp); mb_put_uint8(mbp, 0xff); mb_put_uint8(mbp, 0); mb_put_uint16le(mbp, 0); smb_rq_wend(rqp); smb_rq_bstart(rqp); smb_rq_bend(rqp); error = smb_rq_simple(rqp); SMBSDEBUG(("%d\n", error)); smb_rq_done(rqp); return error; }
int smbfs_smb_rename(struct smbnode *src, struct smbnode *tdnp, const char *tname, int tnmlen, struct smb_cred *scred) { struct smb_rq *rqp; struct smb_share *ssp = src->n_mount->sm_share; struct mbchain *mbp; int error; error = smb_rq_alloc(SSTOCP(ssp), SMB_COM_RENAME, scred, &rqp); if (error) return (error); smb_rq_getrequest(rqp, &mbp); smb_rq_wstart(rqp); mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_ASCII); do { error = smbfs_fullpath(mbp, SSTOVC(ssp), src, NULL, 0); if (error) break; mb_put_uint8(mbp, SMB_DT_ASCII); error = smbfs_fullpath(mbp, SSTOVC(ssp), tdnp, tname, tnmlen); if (error) break; smb_rq_bend(rqp); error = smb_rq_simple(rqp); } while(0); smb_rq_done(rqp); return error; }
int smb_put_asunistring(struct smb_rq *rqp, const char *src) { struct mbchain *mbp = &rqp->sr_rq; struct iconv_drv *dp = rqp->sr_vc->vc_toserver; u_char c; int error; while (*src) { iconv_convmem(dp, &c, src++, 1); error = mb_put_uint16le(mbp, c); if (error) return error; } return mb_put_uint16le(mbp, 0); }
int smb_smb_echo(struct smb_vc *vcp, struct smb_cred *scred, int timo) { struct smb_rq *rqp; struct mbchain *mbp; int error; error = smb_rq_alloc(VCTOCP(vcp), SMB_COM_ECHO, scred, &rqp); if (error) return (error); mbp = &rqp->sr_rq; smb_rq_wstart(rqp); mb_put_uint16le(mbp, 1); /* echo count */ smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint32le(mbp, atomic_inc_32_nv(&smbechoes)); smb_rq_bend(rqp); /* * Note: the IOD calls this, so * this request must not wait for * connection state changes, etc. */ rqp->sr_flags |= SMBR_NORECONNECT; error = smb_rq_simple_timed(rqp, timo); SMBSDEBUG("%d\n", error); smb_rq_done(rqp); return (error); }
int smbfs_smb_delete(struct smbnode *np, struct smb_cred *scred) { struct smb_rq *rqp; struct smb_share *ssp = np->n_mount->sm_share; struct mbchain *mbp; int error; rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK); error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_DELETE, scred); if (error) { free(rqp, M_SMBFSDATA); return error; } smb_rq_getrequest(rqp, &mbp); smb_rq_wstart(rqp); mb_put_uint16le(mbp, SMB_FA_SYSTEM | SMB_FA_HIDDEN); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, SMB_DT_ASCII); error = smbfs_fullpath(mbp, SSTOVC(ssp), np, NULL, 0); if (!error) { smb_rq_bend(rqp); error = smb_rq_simple(rqp); } smb_rq_done(rqp); free(rqp, M_SMBFSDATA); return error; }
int ncp_modify_file_or_subdir_dos_info(struct nwmount *nmp, struct vnode *vp, u_int32_t info_mask, struct nw_modify_dos_info *info, struct thread *td,struct ucred *cred) { struct nwnode *np=VTONW(vp); struct ncp_rq *rqp; u_int8_t volnum = nmp->n_volume; u_int32_t dirent = np->n_fid.f_id; struct ncp_conn *conn=NWFSTOCONN(nmp); int error; error = ncp_rq_alloc(87, conn, td, cred, &rqp); if (error) return error; mb_put_uint8(&rqp->rq, 7); /* subfunction */ mb_put_uint8(&rqp->rq, nmp->name_space); mb_put_uint8(&rqp->rq, 0); /* reserved */ mb_put_uint16le(&rqp->rq, SA_ALL); /* search attribs: all */ mb_put_uint32le(&rqp->rq, info_mask); mb_put_mem(&rqp->rq, (caddr_t)info, sizeof(*info), MB_MSYSTEM); ncp_rq_dbase_path(rqp, volnum, dirent, 0, NULL, NULL); error = ncp_request(rqp); if (!error) ncp_rq_done(rqp); return error; }
/* * Given a request with it's body already composed, * rewind to the start and fill in the SMB header. * This is called after the request is enqueued, * so we have the final MID, seq num. etc. */ void smb_rq_fillhdr(struct smb_rq *rqp) { struct mbchain mbtmp, *mbp = &mbtmp; mblk_t *m; /* * Fill in the SMB header using a dup of the first mblk, * which points at the same data but has its own wptr, * so we can rewind without trashing the message. */ m = dupb(rqp->sr_rq.mb_top); m->b_wptr = m->b_rptr; /* rewind */ mb_initm(mbp, m); mb_put_mem(mbp, SMB_SIGNATURE, 4, MB_MSYSTEM); mb_put_uint8(mbp, rqp->sr_cmd); mb_put_uint32le(mbp, 0); /* status */ mb_put_uint8(mbp, rqp->sr_rqflags); mb_put_uint16le(mbp, rqp->sr_rqflags2); mb_put_uint16le(mbp, 0); /* pid-high */ mb_put_mem(mbp, NULL, 8, MB_MZERO); /* MAC sig. (later) */ mb_put_uint16le(mbp, 0); /* reserved */ mb_put_uint16le(mbp, rqp->sr_rqtid); mb_put_uint16le(mbp, rqp->sr_pid); mb_put_uint16le(mbp, rqp->sr_rquid); mb_put_uint16le(mbp, rqp->sr_mid); /* This will free the mblk from dupb. */ mb_done(mbp); }
/* * NT level. Specially for win9x */ int smbfs_smb_setpattrNT(struct smbnode *np, u_short attr, struct timespec *mtime, struct timespec *atime, struct smb_cred *scred) { struct smb_t2rq *t2p; struct smb_share *ssp = np->n_mount->sm_share; struct smb_vc *vcp = SSTOVC(ssp); struct mbchain *mbp; int64_t tm; int error, tzoff; /* * SMB_SET_FILE_BASIC_INFO isn't supported for * SMB_TRANS2_SET_PATH_INFORMATION, * so use SMB_SET_FILE_BASIC_INFORMATION instead, * but it requires SMB_CAP_INFOLEVEL_PASSTHRU capability. */ if ((SMB_CAPS(vcp) & SMB_CAP_INFOLEVEL_PASSTHRU) == 0) return smbfs_smb_setptime2(np, mtime, atime, attr, scred); error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_PATH_INFORMATION, scred, &t2p); if (error) return error; mbp = &t2p->t2_tparam; mb_init(mbp); mb_put_uint16le(mbp, SMB_SET_FILE_BASIC_INFORMATION); mb_put_uint32le(mbp, 0); /* MBZ */ error = smbfs_fullpath(mbp, vcp, np, NULL, 0); if (error) { smb_t2_done(t2p); return error; } tzoff = vcp->vc_sopt.sv_tz; mbp = &t2p->t2_tdata; mb_init(mbp); mb_put_int64le(mbp, 0); /* creation time */ if (atime) { smb_time_local2NT(atime, tzoff, &tm); } else tm = 0; mb_put_int64le(mbp, tm); if (mtime) { smb_time_local2NT(mtime, tzoff, &tm); } else tm = 0; mb_put_int64le(mbp, tm); mb_put_int64le(mbp, tm); /* change time */ mb_put_uint32le(mbp, attr); /* attr */ mb_put_uint32le(mbp, 0); /* padding */ t2p->t2_maxpcount = 2; t2p->t2_maxdcount = 0; error = smb_t2_request(t2p); smb_t2_done(t2p); return error; }
/* * Set DOS file attributes. * Looks like this call can be used only if SMB_CAP_NT_SMBS bit is on. */ int smbfs_smb_setfattrNT(struct smbnode *np, u_int16_t attr, struct timespec *mtime, struct timespec *atime, struct smb_cred *scred) { struct smb_t2rq *t2p; struct smb_share *ssp = np->n_mount->sm_share; struct mbchain *mbp; int64_t tm; int error, svtz; error = smb_t2_alloc(SSTOCP(ssp), SMB_TRANS2_SET_FILE_INFORMATION, scred, &t2p); if (error) return error; svtz = SSTOVC(ssp)->vc_sopt.sv_tz; mbp = &t2p->t2_tparam; mb_init(mbp); mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); mb_put_uint16le(mbp, SMB_SET_FILE_BASIC_INFO); mb_put_uint32le(mbp, 0); mbp = &t2p->t2_tdata; mb_init(mbp); mb_put_int64le(mbp, 0); /* creation time */ if (atime) { smb_time_local2NT(atime, svtz, &tm); } else tm = 0; mb_put_int64le(mbp, tm); if (mtime) { smb_time_local2NT(mtime, svtz, &tm); } else tm = 0; mb_put_int64le(mbp, tm); mb_put_int64le(mbp, tm); /* change time */ mb_put_uint16le(mbp, attr); mb_put_uint32le(mbp, 0); /* padding */ mb_put_uint16le(mbp, 0); t2p->t2_maxpcount = 2; t2p->t2_maxdcount = 0; error = smb_t2_request(t2p); smb_t2_done(t2p); return error; }
/* * Set file atime and mtime. Doesn't supported by core dialect. */ int smbfs_smb_setftime(struct smbnode *np, struct timespec *mtime, struct timespec *atime, struct smb_cred *scred) { struct smb_rq *rqp; struct smb_share *ssp = np->n_mount->sm_share; struct mbchain *mbp; u_int16_t date, time; int error, tzoff; rqp = malloc(sizeof(struct smb_rq), M_SMBFSDATA, M_WAITOK); error = smb_rq_init(rqp, SSTOCP(ssp), SMB_COM_SET_INFORMATION2, scred); if (error) { free(rqp, M_SMBFSDATA); return error; } tzoff = SSTOVC(ssp)->vc_sopt.sv_tz; smb_rq_getrequest(rqp, &mbp); smb_rq_wstart(rqp); mb_put_mem(mbp, (caddr_t)&np->n_fid, 2, MB_MSYSTEM); mb_put_uint32le(mbp, 0); /* creation time */ if (atime) smb_time_unix2dos(atime, tzoff, &date, &time, NULL); else time = date = 0; mb_put_uint16le(mbp, date); mb_put_uint16le(mbp, time); if (mtime) smb_time_unix2dos(mtime, tzoff, &date, &time, NULL); else time = date = 0; mb_put_uint16le(mbp, date); mb_put_uint16le(mbp, time); smb_rq_wend(rqp); smb_rq_bstart(rqp); smb_rq_bend(rqp); error = smb_rq_simple(rqp); SMBSDEBUG("%d\n", error); smb_rq_done(rqp); free(rqp, M_SMBFSDATA); return error; }
int smbfs_fullpath(struct mbchain *mbp, struct smb_vc *vcp, struct smbnode *dnp, const char *name, int nmlen) { int caseopt = SMB_CS_NONE; int error; if (SMB_UNICODE_STRINGS(vcp)) { error = mb_put_padbyte(mbp); if (error) return error; } if (SMB_DIALECT(vcp) < SMB_DIALECT_LANMAN1_0) caseopt |= SMB_CS_UPPER; if (dnp != NULL) { error = smb_put_dmem(mbp, vcp, dnp->n_rpath, dnp->n_rplen, caseopt); if (error) return error; if (name) { /* Put the separator */ if (SMB_UNICODE_STRINGS(vcp)) error = mb_put_uint16le(mbp, '\\'); else error = mb_put_uint8(mbp, '\\'); if (error) return error; /* Put the name */ error = smb_put_dmem(mbp, vcp, name, nmlen, caseopt); if (error) return error; } } /* Put NULL terminator. */ if (SMB_UNICODE_STRINGS(vcp)) error = mb_put_uint16le(mbp, 0); else error = mb_put_uint8(mbp, 0); return error; }