1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <smbsrv/smb_incl.h> 29 #include <sys/sdt.h> 30 #include <sys/vfs.h> 31 #include <sys/vfs_opreg.h> 32 #include <sys/vnode.h> 33 #include <sys/fem.h> 34 35 fem_t *smb_fcn_ops = NULL; 36 37 int smb_fem_fcn_create(femarg_t *, char *, vattr_t *, vcexcl_t, int, 38 vnode_t **, cred_t *, int, caller_context_t *, vsecattr_t *); 39 int smb_fem_fcn_remove(femarg_t *, char *, cred_t *, 40 caller_context_t *, int); 41 int smb_fem_fcn_rename(femarg_t *, char *, vnode_t *, char *, 42 cred_t *, caller_context_t *, int); 43 int smb_fem_fcn_mkdir(femarg_t *, char *, vattr_t *, vnode_t **, 44 cred_t *, caller_context_t *, int, vsecattr_t *); 45 int smb_fem_fcn_rmdir(femarg_t *, char *, vnode_t *, cred_t *, 46 caller_context_t *, int); 47 int smb_fem_fcn_link(femarg_t *, vnode_t *, char *, cred_t *, 48 caller_context_t *, int); 49 int smb_fem_fcn_symlink(femarg_t *, char *, vattr_t *, 50 char *, cred_t *, caller_context_t *, int); 51 52 static const fs_operation_def_t smb_fcn_tmpl[] = { 53 VOPNAME_CREATE, { .femop_create = smb_fem_fcn_create }, 54 VOPNAME_REMOVE, {.femop_remove = smb_fem_fcn_remove}, 55 VOPNAME_RENAME, {.femop_rename = smb_fem_fcn_rename}, 56 VOPNAME_MKDIR, {.femop_mkdir = smb_fem_fcn_mkdir}, 57 VOPNAME_RMDIR, {.femop_rmdir = smb_fem_fcn_rmdir}, 58 VOPNAME_LINK, {.femop_link = smb_fem_fcn_link}, 59 VOPNAME_SYMLINK, {.femop_symlink = smb_fem_fcn_symlink}, 60 NULL, NULL 61 }; 62 63 int 64 smb_fem_init() 65 { 66 return (fem_create("smb_fcn_ops", smb_fcn_tmpl, &smb_fcn_ops)); 67 } 68 69 void 70 smb_fem_shutdown() 71 { 72 if (smb_fcn_ops) 73 fem_free(smb_fcn_ops); 74 } 75 76 void 77 smb_fem_fcn_install(smb_node_t *node) 78 { 79 (void) fem_install(node->vp, smb_fcn_ops, (void *)node, OPARGUNIQ, 80 (fem_func_t)smb_node_ref, (fem_func_t)smb_node_release); 81 } 82 83 void 84 smb_fem_fcn_uninstall(smb_node_t *node) 85 { 86 (void) fem_uninstall(node->vp, smb_fcn_ops, (void *)node); 87 } 88 89 /* 90 * smb_fem_fcn_create() 91 * 92 * This monitor will catch only changes to VREG files and not to extended 93 * attribute files. This is fine because, for CIFS files, stream creates 94 * should not trigger any file change notification on the VDIR directory 95 * being monitored. Creates of any other kind of extended attribute in 96 * the directory will also not trigger any file change notification on the 97 * VDIR directory being monitored. 98 */ 99 100 int 101 smb_fem_fcn_create( 102 femarg_t *arg, 103 char *name, 104 vattr_t *vap, 105 vcexcl_t excl, 106 int mode, 107 vnode_t **vpp, 108 cred_t *cr, 109 int flag, 110 caller_context_t *ct, 111 vsecattr_t *vsecp) 112 { 113 smb_node_t *dnode; 114 int error; 115 116 dnode = (smb_node_t *)arg->fa_fnode->fn_available; 117 118 ASSERT(dnode); 119 120 error = vnext_create(arg, name, vap, excl, mode, vpp, cr, flag, 121 ct, vsecp); 122 123 if (error == 0) 124 smb_process_node_notify_change_queue(dnode); 125 126 return (error); 127 } 128 129 /* 130 * smb_fem_fcn_remove() 131 * 132 * This monitor will catch only changes to VREG files and to not extended 133 * attribute files. This is fine because, for CIFS files, stream deletes 134 * should not trigger any file change notification on the VDIR directory 135 * being monitored. Deletes of any other kind of extended attribute in 136 * the directory will also not trigger any file change notification on the 137 * VDIR directory being monitored. 138 */ 139 140 int 141 smb_fem_fcn_remove( 142 femarg_t *arg, 143 char *name, 144 cred_t *cr, 145 caller_context_t *ct, 146 int flags) 147 { 148 smb_node_t *dnode; 149 int error; 150 151 dnode = (smb_node_t *)arg->fa_fnode->fn_available; 152 153 ASSERT(dnode); 154 155 error = vnext_remove(arg, name, cr, ct, flags); 156 157 if (error == 0) 158 smb_process_node_notify_change_queue(dnode); 159 160 return (error); 161 } 162 163 int 164 smb_fem_fcn_rename( 165 femarg_t *arg, 166 char *snm, 167 vnode_t *tdvp, 168 char *tnm, 169 cred_t *cr, 170 caller_context_t *ct, 171 int flags) 172 { 173 smb_node_t *dnode; 174 int error; 175 176 dnode = (smb_node_t *)arg->fa_fnode->fn_available; 177 178 ASSERT(dnode); 179 180 error = vnext_rename(arg, snm, tdvp, tnm, cr, ct, flags); 181 182 if (error == 0) 183 smb_process_node_notify_change_queue(dnode); 184 185 return (error); 186 } 187 188 int 189 smb_fem_fcn_mkdir( 190 femarg_t *arg, 191 char *name, 192 vattr_t *vap, 193 vnode_t **vpp, 194 cred_t *cr, 195 caller_context_t *ct, 196 int flags, 197 vsecattr_t *vsecp) 198 { 199 smb_node_t *dnode; 200 int error; 201 202 dnode = (smb_node_t *)arg->fa_fnode->fn_available; 203 204 ASSERT(dnode); 205 206 error = vnext_mkdir(arg, name, vap, vpp, cr, ct, flags, vsecp); 207 208 if (error == 0) 209 smb_process_node_notify_change_queue(dnode); 210 211 return (error); 212 } 213 214 int 215 smb_fem_fcn_rmdir( 216 femarg_t *arg, 217 char *name, 218 vnode_t *cdir, 219 cred_t *cr, 220 caller_context_t *ct, 221 int flags) 222 { 223 smb_node_t *dnode; 224 int error; 225 226 dnode = (smb_node_t *)arg->fa_fnode->fn_available; 227 228 ASSERT(dnode); 229 230 error = vnext_rmdir(arg, name, cdir, cr, ct, flags); 231 232 if (error == 0) 233 smb_process_node_notify_change_queue(dnode); 234 235 return (error); 236 } 237 238 int 239 smb_fem_fcn_link( 240 femarg_t *arg, 241 vnode_t *svp, 242 char *tnm, 243 cred_t *cr, 244 caller_context_t *ct, 245 int flags) 246 { 247 smb_node_t *dnode; 248 int error; 249 250 dnode = (smb_node_t *)arg->fa_fnode->fn_available; 251 252 ASSERT(dnode); 253 254 error = vnext_link(arg, svp, tnm, cr, ct, flags); 255 256 if (error == 0) 257 smb_process_node_notify_change_queue(dnode); 258 259 return (error); 260 } 261 262 int 263 smb_fem_fcn_symlink( 264 femarg_t *arg, 265 char *linkname, 266 vattr_t *vap, 267 char *target, 268 cred_t *cr, 269 caller_context_t *ct, 270 int flags) 271 { 272 smb_node_t *dnode; 273 int error; 274 275 dnode = (smb_node_t *)arg->fa_fnode->fn_available; 276 277 ASSERT(dnode); 278 279 error = vnext_symlink(arg, linkname, vap, target, cr, ct, flags); 280 281 if (error == 0) 282 smb_process_node_notify_change_queue(dnode); 283 284 return (error); 285 } 286