1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2014 Nexenta Systems, Inc. All rights reserved. 14 */ 15 16 /* 17 * Dispatch function for SMB2_SET_INFO 18 * 19 * [MS-FSCC 2.4] If a file system does not support ... 20 * an Information Classs, NT_STATUS_INVALID_PARAMETER... 21 */ 22 23 #include <smbsrv/smb2_kproto.h> 24 #include <smbsrv/smb_fsops.h> 25 #include <smbsrv/ntifs.h> 26 27 static uint32_t smb2_setf_rename(smb_request_t *, smb_setinfo_t *); 28 static uint32_t smb2_setf_link(smb_request_t *, smb_setinfo_t *); 29 30 static uint32_t smb2_setf_seek(smb_request_t *, smb_setinfo_t *); 31 static uint32_t smb2_setf_full_ea(smb_request_t *, smb_setinfo_t *); 32 static uint32_t smb2_setf_mode(smb_request_t *, smb_setinfo_t *); 33 34 static uint32_t smb2_setf_pipe(smb_request_t *, smb_setinfo_t *); 35 static uint32_t smb2_setf_valid_len(smb_request_t *, smb_setinfo_t *); 36 static uint32_t smb2_setf_shortname(smb_request_t *, smb_setinfo_t *); 37 38 39 uint32_t 40 smb2_setinfo_file(smb_request_t *sr, smb_setinfo_t *si, int InfoClass) 41 { 42 smb_ofile_t *of = sr->fid_ofile; 43 uint32_t status; 44 45 si->si_node = of->f_node; 46 47 switch (InfoClass) { 48 case FileBasicInformation: /* 4 */ 49 status = smb_set_basic_info(sr, si); 50 break; 51 case FileRenameInformation: /* 10 */ 52 status = smb2_setf_rename(sr, si); 53 break; 54 case FileLinkInformation: /* 11 */ 55 status = smb2_setf_link(sr, si); 56 break; 57 case FileDispositionInformation: /* 13 */ 58 status = smb_set_disposition_info(sr, si); 59 break; 60 case FilePositionInformation: /* 14 */ 61 status = smb2_setf_seek(sr, si); 62 break; 63 case FileFullEaInformation: /* 15 */ 64 status = smb2_setf_full_ea(sr, si); 65 break; 66 case FileModeInformation: /* 16 */ 67 status = smb2_setf_mode(sr, si); 68 break; 69 case FileAllocationInformation: /* 19 */ 70 status = smb_set_alloc_info(sr, si); 71 break; 72 case FileEndOfFileInformation: /* 20 */ 73 status = smb_set_eof_info(sr, si); 74 break; 75 case FilePipeInformation: /* 23 */ 76 status = smb2_setf_pipe(sr, si); 77 break; 78 case FileValidDataLengthInformation: /* 39 */ 79 status = smb2_setf_valid_len(sr, si); 80 break; 81 case FileShortNameInformation: /* 40 */ 82 status = smb2_setf_shortname(sr, si); 83 break; 84 default: 85 status = NT_STATUS_INVALID_INFO_CLASS; 86 break; 87 } 88 89 return (status); 90 } 91 92 93 /* 94 * FileRenameInformation 95 * See also: smb_set_rename_info() 96 */ 97 static uint32_t 98 smb2_setf_rename(smb_request_t *sr, smb_setinfo_t *si) 99 { 100 char *fname; 101 uint8_t flags; 102 uint64_t rootdir; 103 uint32_t namelen; 104 uint32_t status = 0; 105 int rc; 106 107 rc = smb_mbc_decodef(&si->si_data, "b7.ql", 108 &flags, &rootdir, &namelen); 109 if (rc == 0) { 110 rc = smb_mbc_decodef(&si->si_data, "%#U", 111 sr, namelen, &fname); 112 } 113 if (rc != 0) 114 return (NT_STATUS_INFO_LENGTH_MISMATCH); 115 116 if ((rootdir != 0) || (namelen == 0) || (namelen >= SMB_MAXPATHLEN)) { 117 return (NT_STATUS_INVALID_PARAMETER); 118 } 119 120 status = smb_setinfo_rename(sr, si->si_node, fname, flags); 121 122 return (status); 123 } 124 125 /* 126 * FileLinkInformation 127 */ 128 static uint32_t 129 smb2_setf_link(smb_request_t *sr, smb_setinfo_t *si) 130 { 131 char *fname; 132 uint8_t flags; 133 uint64_t rootdir; 134 uint32_t namelen; 135 uint32_t status = 0; 136 int rc; 137 138 rc = smb_mbc_decodef(&si->si_data, "b7.ql", 139 &flags, &rootdir, &namelen); 140 if (rc == 0) { 141 rc = smb_mbc_decodef(&si->si_data, "%#U", 142 sr, namelen, &fname); 143 } 144 if (rc != 0) 145 return (NT_STATUS_INFO_LENGTH_MISMATCH); 146 147 if ((rootdir != 0) || (namelen == 0) || (namelen >= SMB_MAXPATHLEN)) { 148 return (NT_STATUS_INVALID_PARAMETER); 149 } 150 151 status = smb_setinfo_link(sr, si->si_node, fname, flags); 152 153 return (status); 154 } 155 156 157 /* 158 * FilePositionInformation 159 */ 160 static uint32_t 161 smb2_setf_seek(smb_request_t *sr, smb_setinfo_t *si) 162 { 163 smb_ofile_t *of = sr->fid_ofile; 164 uint64_t newoff; 165 166 if (smb_mbc_decodef(&si->si_data, "q", &newoff) != 0) 167 return (NT_STATUS_INVALID_PARAMETER); 168 169 ASSERT(of->f_magic == SMB_OFILE_MAGIC); 170 mutex_enter(&of->f_mutex); 171 of->f_seek_pos = newoff; 172 mutex_exit(&of->f_mutex); 173 174 return (0); 175 } 176 177 /* 178 * FileFullEaInformation 179 * We could put EAs in a named stream... 180 */ 181 /* ARGSUSED */ 182 static uint32_t 183 smb2_setf_full_ea(smb_request_t *sr, smb_setinfo_t *si) 184 { 185 return (NT_STATUS_EAS_NOT_SUPPORTED); 186 } 187 188 /* 189 * FileModeInformation [MS-FSCC 2.4.24] 190 * FILE_WRITE_THROUGH 191 * FILE_SEQUENTIAL_ONLY 192 * FILE_NO_INTERMEDIATE_BUFFERING 193 * etc. 194 */ 195 static uint32_t 196 smb2_setf_mode(smb_request_t *sr, smb_setinfo_t *si) 197 { 198 _NOTE(ARGUNUSED(sr)) 199 uint32_t Mode; 200 201 if (smb_mbc_decodef(&si->si_data, "l", &Mode) != 0) 202 return (NT_STATUS_INVALID_PARAMETER); 203 204 #if 0 /* XXX - todo */ 205 if (Mode & FILE_WRITE_THROUGH) { 206 /* store this in the ofile */ 207 } 208 #endif 209 210 return (NT_STATUS_SUCCESS); 211 } 212 213 214 215 /* 216 * FilePipeInformation 217 */ 218 static uint32_t 219 smb2_setf_pipe(smb_request_t *sr, smb_setinfo_t *si) 220 { 221 _NOTE(ARGUNUSED(si)) 222 smb_ofile_t *of = sr->fid_ofile; 223 uint32_t ReadMode; 224 uint32_t CompletionMode; 225 uint32_t status; 226 227 if (smb_mbc_decodef(&si->si_data, "ll", 228 &ReadMode, &CompletionMode) != 0) 229 return (NT_STATUS_INFO_LENGTH_MISMATCH); 230 231 switch (of->f_ftype) { 232 case SMB_FTYPE_BYTE_PIPE: 233 case SMB_FTYPE_MESG_PIPE: 234 /* 235 * XXX: Do we need to actually do anything with 236 * ReadMode or CompletionMode? If so, (later) 237 * store these in the opipe object. 238 * 239 * See also: smb2_sif_pipe() 240 */ 241 status = 0; 242 break; 243 case SMB_FTYPE_DISK: 244 case SMB_FTYPE_PRINTER: 245 default: 246 status = NT_STATUS_INVALID_PARAMETER; 247 } 248 249 return (status); 250 } 251 252 /* 253 * FileValidDataLengthInformation 254 */ 255 /* ARGSUSED */ 256 static uint32_t 257 smb2_setf_valid_len(smb_request_t *sr, smb_setinfo_t *si) 258 { 259 smb_ofile_t *of = sr->fid_ofile; 260 uint64_t eod; 261 int rc; 262 263 if (smb_mbc_decodef(&si->si_data, "q", &eod) != 0) 264 return (NT_STATUS_INFO_LENGTH_MISMATCH); 265 266 rc = smb_fsop_set_data_length(sr, of->f_cr, of->f_node, eod); 267 if (rc != 0) 268 return (smb_errno2status(rc)); 269 270 return (0); 271 } 272 273 /* 274 * FileShortNameInformation 275 * We can (optionally) support supply short names, 276 * but you can't change them. 277 */ 278 static uint32_t 279 smb2_setf_shortname(smb_request_t *sr, smb_setinfo_t *si) 280 { 281 _NOTE(ARGUNUSED(si)) 282 smb_ofile_t *of = sr->fid_ofile; 283 284 if (of->f_ftype != SMB_FTYPE_DISK) 285 return (NT_STATUS_INVALID_PARAMETER); 286 if ((of->f_tree->t_flags & SMB_TREE_SHORTNAMES) == 0) 287 return (NT_STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME); 288 289 return (NT_STATUS_ACCESS_DENIED); 290 } 291