1a90cf9f2SGordon Ross /* 2a90cf9f2SGordon Ross * CDDL HEADER START 3a90cf9f2SGordon Ross * 4a90cf9f2SGordon Ross * The contents of this file are subject to the terms of the 5a90cf9f2SGordon Ross * Common Development and Distribution License (the "License"). 6a90cf9f2SGordon Ross * You may not use this file except in compliance with the License. 7a90cf9f2SGordon Ross * 8a90cf9f2SGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9a90cf9f2SGordon Ross * or http://www.opensolaris.org/os/licensing. 10a90cf9f2SGordon Ross * See the License for the specific language governing permissions 11a90cf9f2SGordon Ross * and limitations under the License. 12a90cf9f2SGordon Ross * 13a90cf9f2SGordon Ross * When distributing Covered Code, include this CDDL HEADER in each 14a90cf9f2SGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15a90cf9f2SGordon Ross * If applicable, add the following below this CDDL HEADER, with the 16a90cf9f2SGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying 17a90cf9f2SGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner] 18a90cf9f2SGordon Ross * 19a90cf9f2SGordon Ross * CDDL HEADER END 20a90cf9f2SGordon Ross */ 21a90cf9f2SGordon Ross 22a90cf9f2SGordon Ross /* 23a90cf9f2SGordon Ross * Copyright (c) 2007, 2010, Oracle and/or its affiliates. 24*93bc28dbSGordon Ross * Copyright 2017 Nexenta Systems, Inc. All rights reserved. 25a90cf9f2SGordon Ross */ 26a90cf9f2SGordon Ross 27a90cf9f2SGordon Ross /* 28a90cf9f2SGordon Ross * Dispatch function for SMB2_CHANGE_NOTIFY 29a90cf9f2SGordon Ross */ 30a90cf9f2SGordon Ross 31a90cf9f2SGordon Ross #include <smbsrv/smb2_kproto.h> 32a90cf9f2SGordon Ross 33bfe5e737SGordon Ross /* For the output DataOffset fields in here. */ 34bfe5e737SGordon Ross #define DATA_OFF (SMB2_HDR_SIZE + 8) 35bfe5e737SGordon Ross 36a90cf9f2SGordon Ross static smb_sdrc_t smb2_change_notify_async(smb_request_t *); 37a90cf9f2SGordon Ross 38a90cf9f2SGordon Ross smb_sdrc_t 39a90cf9f2SGordon Ross smb2_change_notify(smb_request_t *sr) 40a90cf9f2SGordon Ross { 41a90cf9f2SGordon Ross uint16_t StructSize; 42a90cf9f2SGordon Ross uint16_t iFlags; 43a90cf9f2SGordon Ross uint32_t oBufLength; 44a90cf9f2SGordon Ross smb2fid_t smb2fid; 45a90cf9f2SGordon Ross uint32_t CompletionFilter; 46a90cf9f2SGordon Ross uint32_t reserved; 47a90cf9f2SGordon Ross uint32_t status; 48a90cf9f2SGordon Ross int rc = 0; 49a90cf9f2SGordon Ross 50a90cf9f2SGordon Ross /* 51a90cf9f2SGordon Ross * SMB2 Change Notify request 52a90cf9f2SGordon Ross */ 53a90cf9f2SGordon Ross rc = smb_mbc_decodef( 54a90cf9f2SGordon Ross &sr->smb_data, "wwlqqll", 55a90cf9f2SGordon Ross &StructSize, /* w */ 56a90cf9f2SGordon Ross &iFlags, /* w */ 57a90cf9f2SGordon Ross &oBufLength, /* l */ 58a90cf9f2SGordon Ross &smb2fid.persistent, /* q */ 59a90cf9f2SGordon Ross &smb2fid.temporal, /* q */ 60a90cf9f2SGordon Ross &CompletionFilter, /* l */ 61a90cf9f2SGordon Ross &reserved); /* l */ 62a90cf9f2SGordon Ross if (rc || StructSize != 32) 63a90cf9f2SGordon Ross return (SDRC_ERROR); 64a90cf9f2SGordon Ross 65a90cf9f2SGordon Ross status = smb2sr_lookup_fid(sr, &smb2fid); 66*93bc28dbSGordon Ross DTRACE_SMB2_START(op__ChangeNotify, smb_request_t *, sr); 67*93bc28dbSGordon Ross 68bfe5e737SGordon Ross if (status != 0) 69*93bc28dbSGordon Ross goto errout; /* Bad FID */ 70a90cf9f2SGordon Ross 71a90cf9f2SGordon Ross CompletionFilter &= FILE_NOTIFY_VALID_MASK; 72a90cf9f2SGordon Ross if (iFlags & SMB2_WATCH_TREE) 73bfe5e737SGordon Ross CompletionFilter |= FILE_NOTIFY_CHANGE_EV_SUBDIR; 74a90cf9f2SGordon Ross 75a90cf9f2SGordon Ross if (oBufLength > smb2_max_trans) 76a90cf9f2SGordon Ross oBufLength = smb2_max_trans; 77a90cf9f2SGordon Ross 78bfe5e737SGordon Ross /* 79bfe5e737SGordon Ross * Check for events and consume, non-blocking. 80bfe5e737SGordon Ross * Special return STATUS_PENDING means: 81bfe5e737SGordon Ross * No events; caller must call "act2" next. 82bfe5e737SGordon Ross * SMB2 does that in the "async" handler. 83bfe5e737SGordon Ross */ 84bfe5e737SGordon Ross status = smb_notify_act1(sr, oBufLength, CompletionFilter); 85bfe5e737SGordon Ross if (status == NT_STATUS_PENDING) { 86bfe5e737SGordon Ross status = smb2sr_go_async(sr, smb2_change_notify_async); 87bfe5e737SGordon Ross } 88bfe5e737SGordon Ross 89*93bc28dbSGordon Ross errout: 90bfe5e737SGordon Ross sr->smb2_status = status; 91*93bc28dbSGordon Ross if (status != NT_STATUS_PENDING) { 92*93bc28dbSGordon Ross DTRACE_SMB2_DONE(op__ChangeNotify, smb_request_t *, sr); 93*93bc28dbSGordon Ross } 94bfe5e737SGordon Ross 95*93bc28dbSGordon Ross if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_SUCCESS) { 96bfe5e737SGordon Ross oBufLength = sr->raw_data.chain_offset; 97bfe5e737SGordon Ross (void) smb_mbc_encodef( 98bfe5e737SGordon Ross &sr->reply, "wwlC", 99bfe5e737SGordon Ross 9, /* StructSize */ /* w */ 100bfe5e737SGordon Ross DATA_OFF, /* w */ 101bfe5e737SGordon Ross oBufLength, /* l */ 102bfe5e737SGordon Ross &sr->raw_data); /* C */ 103bfe5e737SGordon Ross } else { 104a90cf9f2SGordon Ross smb2sr_put_error(sr, status); 105bfe5e737SGordon Ross } 106bfe5e737SGordon Ross 107a90cf9f2SGordon Ross return (SDRC_SUCCESS); 108a90cf9f2SGordon Ross } 109a90cf9f2SGordon Ross 110a90cf9f2SGordon Ross /* 111bfe5e737SGordon Ross * This is called when the dispatch loop has made it to the end of a 112bfe5e737SGordon Ross * compound request, and we had a notify that will require blocking. 113a90cf9f2SGordon Ross */ 114bfe5e737SGordon Ross static smb_sdrc_t 115bfe5e737SGordon Ross smb2_change_notify_async(smb_request_t *sr) 116bfe5e737SGordon Ross { 117bfe5e737SGordon Ross uint32_t status; 118bfe5e737SGordon Ross 119bfe5e737SGordon Ross status = smb_notify_act2(sr); 120bfe5e737SGordon Ross if (status == NT_STATUS_PENDING) { 121bfe5e737SGordon Ross /* See next: smb2_change_notify_finish */ 122bfe5e737SGordon Ross return (SDRC_SR_KEPT); 123bfe5e737SGordon Ross } 124bfe5e737SGordon Ross 125bfe5e737SGordon Ross /* Note: Never NT_STATUS_NOTIFY_ENUM_DIR here. */ 126bfe5e737SGordon Ross ASSERT(status != NT_STATUS_NOTIFY_ENUM_DIR); 127bfe5e737SGordon Ross 128bfe5e737SGordon Ross if (status != 0) 129bfe5e737SGordon Ross smb2sr_put_error(sr, status); 130a90cf9f2SGordon Ross 131a90cf9f2SGordon Ross return (SDRC_SUCCESS); 132a90cf9f2SGordon Ross } 133bfe5e737SGordon Ross 134bfe5e737SGordon Ross /* 135bfe5e737SGordon Ross * This is called via taskq_dispatch in smb_notify.c 136bfe5e737SGordon Ross * to finish up an NT transact notify change request. 137bfe5e737SGordon Ross * Build an SMB2 Change Notify reply and send it. 138bfe5e737SGordon Ross */ 139bfe5e737SGordon Ross void 140bfe5e737SGordon Ross smb2_change_notify_finish(void *arg) 141bfe5e737SGordon Ross { 142bfe5e737SGordon Ross smb_request_t *sr = arg; 143bfe5e737SGordon Ross uint32_t status; 144bfe5e737SGordon Ross uint32_t oBufLength; 145bfe5e737SGordon Ross 146bfe5e737SGordon Ross SMB_REQ_VALID(sr); 147bfe5e737SGordon Ross 148bfe5e737SGordon Ross /* 149bfe5e737SGordon Ross * Common part of notify, puts data in sr->raw_data 150bfe5e737SGordon Ross */ 151bfe5e737SGordon Ross status = smb_notify_act3(sr); 152bfe5e737SGordon Ross 153*93bc28dbSGordon Ross sr->smb2_status = status; 154*93bc28dbSGordon Ross DTRACE_SMB2_DONE(op__ChangeNotify, smb_request_t *, sr); 155*93bc28dbSGordon Ross 156*93bc28dbSGordon Ross if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_SUCCESS) { 157bfe5e737SGordon Ross oBufLength = sr->raw_data.chain_offset; 158bfe5e737SGordon Ross (void) smb_mbc_encodef( 159bfe5e737SGordon Ross &sr->reply, "wwlC", 160bfe5e737SGordon Ross 9, /* StructSize */ /* w */ 161bfe5e737SGordon Ross DATA_OFF, /* w */ 162bfe5e737SGordon Ross oBufLength, /* l */ 163bfe5e737SGordon Ross &sr->raw_data); /* C */ 164bfe5e737SGordon Ross } else { 165bfe5e737SGordon Ross smb2sr_put_error(sr, status); 166bfe5e737SGordon Ross } 167bfe5e737SGordon Ross 168bfe5e737SGordon Ross smb2sr_finish_async(sr); 169bfe5e737SGordon Ross } 170