From 6db12f718007592cf971b22f376fde796e637727 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 12 Jun 2000 05:32:28 +0000 Subject: split all the change notify code out into a separate module smbd/notify.c. All the data structures are now private to that module. this is in preparation for Linux kernel support for change notify (coming soon to a CVS tree near you) (This used to be commit 1bb0aad4f66dbfa2d0f767ea90f926affff20b17) --- source3/smbd/notify.c | 392 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 source3/smbd/notify.c (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c new file mode 100644 index 0000000000..26be17c590 --- /dev/null +++ b/source3/smbd/notify.c @@ -0,0 +1,392 @@ +#define OLD_NTDOMAIN 1 +/* + Unix SMB/Netbios implementation. + Version 1.9. + SMB NT transaction handling + Copyright (C) Jeremy Allison 1994-1998 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +extern int DEBUGLEVEL; + +/**************************************************************************** + This is the structure to keep the information needed to + determine if a directory has changed. +*****************************************************************************/ + +typedef struct { + time_t modify_time; /* Info from the directory we're monitoring. */ + time_t status_time; /* Info from the directory we're monitoring. */ + time_t total_time; /* Total time of all directory entries - don't care if it wraps. */ + unsigned int num_entries; /* Zero or the number of files in the directory. */ +} change_hash_data; + +/**************************************************************************** + This is the structure to queue to implement NT change + notify. It consists of smb_size bytes stored from the + transact command (to keep the mid, tid etc around). + Plus the fid to examine and the time to check next. +*****************************************************************************/ + +typedef struct { + ubi_slNode msg_next; + files_struct *fsp; + connection_struct *conn; + uint32 flags; + time_t next_check_time; + change_hash_data change_data; + char request_buf[smb_size]; +} change_notify_buf; + +static ubi_slList change_notify_queue = { NULL, (ubi_slNodePtr)&change_notify_queue, 0}; + +/**************************************************************************** + Setup the common parts of the return packet and send it. +*****************************************************************************/ + +static void change_notify_reply_packet(char *inbuf, int error_class, uint32 error_code) +{ + char outbuf[smb_size+38]; + + memset(outbuf, '\0', sizeof(outbuf)); + construct_reply_common(inbuf, outbuf); + + /* + * If we're returning a 'too much in the directory changed' we need to + * set this is an NT error status flags. If we don't then the (probably + * untested) code in the NT redirector has a bug in that it doesn't re-issue + * the change notify.... Ah - I *love* it when I get so deeply into this I + * can even determine how MS failed to test stuff and why.... :-). JRA. + */ + + if(error_class == 0) /* NT Error. */ + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + + ERROR(error_class,error_code); + + /* + * Seems NT needs a transact command with an error code + * in it. This is a longer packet than a simple error. + */ + set_message(outbuf,18,0,False); + + send_smb(smbd_server_fd(),outbuf); +} + +/**************************************************************************** + Create the hash we will use to determine if the contents changed. +*****************************************************************************/ + +static BOOL create_directory_notify_hash( change_notify_buf *cnbp, change_hash_data *change_data) +{ + SMB_STRUCT_STAT st; + files_struct *fsp = cnbp->fsp; + + memset((char *)change_data, '\0', sizeof(change_data)); + + /* + * Store the current timestamp on the directory we are monitoring. + */ + + if(dos_stat(fsp->fsp_name, &st) < 0) { + DEBUG(0,("create_directory_notify_hash: Unable to stat name = %s. \ +Error was %s\n", fsp->fsp_name, strerror(errno) )); + return False; + } + + change_data->modify_time = st.st_mtime; + change_data->status_time = st.st_ctime; + + /* + * If we are to watch for changes that are only stored + * in inodes of files, not in the directory inode, we must + * scan the directory and produce a unique identifier with + * which we can determine if anything changed. We use the + * modify and change times from all the files in the + * directory, added together (ignoring wrapping if it's + * larger than the max time_t value). + */ + + if(cnbp->flags & (FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE)) { + pstring full_name; + char *p; + char *fname; + size_t remaining_len; + size_t fullname_len; + void *dp = OpenDir(cnbp->conn, fsp->fsp_name, True); + + if(dp == NULL) { + DEBUG(0,("create_directory_notify_hash: Unable to open directory = %s. \ +Error was %s\n", fsp->fsp_name, strerror(errno) )); + return False; + } + + change_data->num_entries = 0; + + pstrcpy(full_name, fsp->fsp_name); + pstrcat(full_name, "/"); + + fullname_len = strlen(full_name); + remaining_len = sizeof(full_name) - fullname_len - 1; + p = &full_name[fullname_len]; + + while ((fname = ReadDirName(dp))) { + if(strequal(fname, ".") || strequal(fname, "..")) + continue; + + change_data->num_entries++; + safe_strcpy( p, fname, remaining_len); + + memset(&st, '\0', sizeof(st)); + + /* + * Do the stat - but ignore errors. + */ + + if(dos_stat(full_name, &st) < 0) { + DEBUG(5,("create_directory_notify_hash: Unable to stat content file = %s. \ +Error was %s\n", fsp->fsp_name, strerror(errno) )); + } + change_data->total_time += (st.st_mtime + st.st_ctime); + } + + CloseDir(dp); + } + + return True; +} + +/**************************************************************************** + Delete entries by fnum from the change notify pending queue. +*****************************************************************************/ + +void remove_pending_change_notify_requests_by_fid(files_struct *fsp) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + change_notify_buf *prev = NULL; + + while(cnbp != NULL) { + if(cnbp->fsp->fnum == fsp->fnum) { + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + continue; + } + + prev = cnbp; + cnbp = (change_notify_buf *)ubi_slNext(cnbp); + } +} + +/**************************************************************************** + Delete entries by mid from the change notify pending queue. Always send reply. +*****************************************************************************/ + +void remove_pending_change_notify_requests_by_mid(int mid) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + change_notify_buf *prev = NULL; + + while(cnbp != NULL) { + if(SVAL(cnbp->request_buf,smb_mid) == mid) { + change_notify_reply_packet(cnbp->request_buf,0,0xC0000000 |NT_STATUS_CANCELLED); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + continue; + } + + prev = cnbp; + cnbp = (change_notify_buf *)ubi_slNext(cnbp); + } +} + +/**************************************************************************** + Delete entries by filename and cnum from the change notify pending queue. + Always send reply. +*****************************************************************************/ + +void remove_pending_change_notify_requests_by_filename(files_struct *fsp) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + change_notify_buf *prev = NULL; + + while(cnbp != NULL) { + /* + * We know it refers to the same directory if the connection number and + * the filename are identical. + */ + if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { + change_notify_reply_packet(cnbp->request_buf,0,0xC0000000 |NT_STATUS_CANCELLED); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + continue; + } + + prev = cnbp; + cnbp = (change_notify_buf *)ubi_slNext(cnbp); + } +} + +/**************************************************************************** + Process the change notify queue. Note that this is only called as root. + Returns True if there are still outstanding change notify requests on the + queue. +*****************************************************************************/ + +BOOL process_pending_change_notify_queue(time_t t) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + change_notify_buf *prev = NULL; + + if(cnbp == NULL) + return False; + + if(cnbp->next_check_time >= t) + return True; + + /* + * It's time to check. Go through the queue and see if + * the timestamps changed. + */ + + while((cnbp != NULL) && (cnbp->next_check_time <= t)) { + change_hash_data change_data; + connection_struct *conn = cnbp->conn; + uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : + SVAL(cnbp->request_buf,smb_uid); + + ZERO_STRUCT(change_data); + + /* + * Ensure we don't have any old chain_fsp values + * sitting around.... + */ + chain_size = 0; + file_chain_reset(); + + if(!become_user(conn,vuid)) { + DEBUG(0,("process_pending_change_notify_queue: Unable to become user vuid=%d.\n", + vuid )); + /* + * Remove the entry and return an error to the client. + */ + change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + continue; + } + + if(!become_service(conn,True)) { + DEBUG(0,("process_pending_change_notify_queue: Unable to become service Error was %s.\n", strerror(errno) )); + /* + * Remove the entry and return an error to the client. + */ + change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + unbecome_user(); + continue; + } + + if(!create_directory_notify_hash( cnbp, &change_data)) { + DEBUG(0,("process_pending_change_notify_queue: Unable to create change data for \ +directory %s\n", cnbp->fsp->fsp_name )); + /* + * Remove the entry and return an error to the client. + */ + change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + unbecome_user(); + continue; + } + + if(memcmp( (char *)&cnbp->change_data, (char *)&change_data, sizeof(change_data))) { + /* + * Remove the entry and return a change notify to the client. + */ + DEBUG(5,("process_pending_change_notify_queue: directory name = %s changed.\n", + cnbp->fsp->fsp_name )); + change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_NOTIFY_ENUM_DIR); + free((char *)ubi_slRemNext( &change_notify_queue, prev)); + cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); + unbecome_user(); + continue; + } + + unbecome_user(); + + /* + * Move to the next in the list. + */ + prev = cnbp; + cnbp = (change_notify_buf *)ubi_slNext(cnbp); + } + + return (cnbp != NULL); +} + +/**************************************************************************** + Return true if there are pending change notifies. +****************************************************************************/ +BOOL change_notifies_pending(void) +{ + change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); + return (cnbp != NULL); +} + +/**************************************************************************** + * Now queue an entry on the notify change stack. We timestamp + * the entry we are adding so that we know when to scan next. + * We only need to save smb_size bytes from this incoming packet + * as we will always by returning a 'read the directory yourself' + * error. +****************************************************************************/ +BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, uint32 flags) +{ + change_notify_buf *cnbp; + + if((cnbp = (change_notify_buf *)malloc(sizeof(change_notify_buf))) == NULL) { + DEBUG(0,("call_nt_transact_notify_change: malloc fail !\n" )); + return -1; + } + + ZERO_STRUCTP(cnbp); + + memcpy(cnbp->request_buf, inbuf, smb_size); + cnbp->fsp = fsp; + cnbp->conn = conn; + cnbp->next_check_time = time(NULL) + lp_change_notify_timeout(); + cnbp->flags = flags; + + if (!create_directory_notify_hash(cnbp, &cnbp->change_data)) { + free((char *)cnbp); + return False; + } + + /* + * Adding to the tail enables us to check only + * the head when scanning for change, as this entry + * is forced to have the first timeout expiration. + */ + + ubi_slAddTail(&change_notify_queue, cnbp); + + return True; +} + +#undef OLD_NTDOMAIN -- cgit From 2b37fd8435fa2ee20395e028d0371a0eca7785ff Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 12 Jun 2000 05:34:14 +0000 Subject: fixed comments at top of module (This used to be commit 02577ab7d275dfb49e104f3358cb3caa66b3b09e) --- source3/smbd/notify.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 26be17c590..3af9da238f 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -1,9 +1,10 @@ #define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. - Version 1.9. - SMB NT transaction handling + Version 3.0 + change notify handling Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Andrew Tridgell 2000 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -- cgit From b2d01bd2dbfed8b35cc324fad42eac562fcad3b4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 12 Jun 2000 15:53:31 +0000 Subject: totally rewrote the async signal, notification and oplock notification handling in Samba. This was needed due to several limitations and races in the previous code - as a side effect the new code is much cleaner :) in summary: - changed sys_select() to avoid a signal/select race condition. It is a rare race but once we have signals doing notification and oplocks it is important. - changed our main processing loop to take advantage of the new sys_select semantics - split the notify code into implementaion dependent and general parts. Added the following structure that defines an implementation: struct cnotify_fns { void * (*register_notify)(connection_struct *conn, char *path, uint32 flags); BOOL (*check_notify)(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *data, time_t t); void (*remove_notify)(void *data); }; then I wrote two implementations, one using hash/poll (like our old code) and the other using the new Linux kernel change notify. It should be easy to add other change notify implementations by creating a sructure of the above type. - fixed a bug in change notify where we were returning the wrong error code. - rewrote the core change notify code to be much simpler - moved to real-time signals for leases and change notify Amazingly, it all seems to work. I was very surprised! (This used to be commit 44766c39e0027c762bee8b33b12c621c109a3267) --- source3/smbd/notify.c | 401 +++++++++++++++----------------------------------- 1 file changed, 117 insertions(+), 284 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 3af9da238f..40867a71ee 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -3,8 +3,8 @@ Unix SMB/Netbios implementation. Version 3.0 change notify handling - Copyright (C) Jeremy Allison 1994-1998 Copyright (C) Andrew Tridgell 2000 + Copyright (C) Jeremy Allison 1994-1998 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,221 +25,128 @@ extern int DEBUGLEVEL; -/**************************************************************************** - This is the structure to keep the information needed to - determine if a directory has changed. -*****************************************************************************/ - -typedef struct { - time_t modify_time; /* Info from the directory we're monitoring. */ - time_t status_time; /* Info from the directory we're monitoring. */ - time_t total_time; /* Total time of all directory entries - don't care if it wraps. */ - unsigned int num_entries; /* Zero or the number of files in the directory. */ -} change_hash_data; +static struct cnotify_fns *cnotify; /**************************************************************************** This is the structure to queue to implement NT change notify. It consists of smb_size bytes stored from the transact command (to keep the mid, tid etc around). - Plus the fid to examine and the time to check next. + Plus the fid to examine and notify private data *****************************************************************************/ -typedef struct { - ubi_slNode msg_next; - files_struct *fsp; - connection_struct *conn; - uint32 flags; - time_t next_check_time; - change_hash_data change_data; - char request_buf[smb_size]; -} change_notify_buf; +struct change_notify { + struct change_notify *next, *prev; + files_struct *fsp; + connection_struct *conn; + uint32 flags; + char request_buf[smb_size]; + void *change_data; +}; -static ubi_slList change_notify_queue = { NULL, (ubi_slNodePtr)&change_notify_queue, 0}; +static struct change_notify *change_notify_list; /**************************************************************************** Setup the common parts of the return packet and send it. *****************************************************************************/ - -static void change_notify_reply_packet(char *inbuf, int error_class, uint32 error_code) +static void change_notify_reply_packet(char *inbuf, uint32 error_code) { - char outbuf[smb_size+38]; - - memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(inbuf, outbuf); + char outbuf[smb_size+38]; - /* - * If we're returning a 'too much in the directory changed' we need to - * set this is an NT error status flags. If we don't then the (probably - * untested) code in the NT redirector has a bug in that it doesn't re-issue - * the change notify.... Ah - I *love* it when I get so deeply into this I - * can even determine how MS failed to test stuff and why.... :-). JRA. - */ + memset(outbuf, '\0', sizeof(outbuf)); + construct_reply_common(inbuf, outbuf); - if(error_class == 0) /* NT Error. */ - SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - - ERROR(error_class,error_code); + /* + * If we're returning a 'too much in the directory changed' we need to + * set this is an NT error status flags. If we don't then the (probably + * untested) code in the NT redirector has a bug in that it doesn't re-issue + * the change notify.... Ah - I *love* it when I get so deeply into this I + * can even determine how MS failed to test stuff and why.... :-). JRA. + */ + + SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); + ERROR(0,error_code); - /* - * Seems NT needs a transact command with an error code - * in it. This is a longer packet than a simple error. - */ - set_message(outbuf,18,0,False); + /* + * Seems NT needs a transact command with an error code + * in it. This is a longer packet than a simple error. + */ + set_message(outbuf,18,0,False); - send_smb(smbd_server_fd(),outbuf); + send_smb(smbd_server_fd(),outbuf); } /**************************************************************************** - Create the hash we will use to determine if the contents changed. +remove an entry from the list and free it, also closing any +directory handle if necessary +Notice the horrible stuff we have to do because this is a singly linked list. *****************************************************************************/ - -static BOOL create_directory_notify_hash( change_notify_buf *cnbp, change_hash_data *change_data) +static void change_notify_remove(struct change_notify *cnbp) { - SMB_STRUCT_STAT st; - files_struct *fsp = cnbp->fsp; - - memset((char *)change_data, '\0', sizeof(change_data)); - - /* - * Store the current timestamp on the directory we are monitoring. - */ - - if(dos_stat(fsp->fsp_name, &st) < 0) { - DEBUG(0,("create_directory_notify_hash: Unable to stat name = %s. \ -Error was %s\n", fsp->fsp_name, strerror(errno) )); - return False; - } - - change_data->modify_time = st.st_mtime; - change_data->status_time = st.st_ctime; - - /* - * If we are to watch for changes that are only stored - * in inodes of files, not in the directory inode, we must - * scan the directory and produce a unique identifier with - * which we can determine if anything changed. We use the - * modify and change times from all the files in the - * directory, added together (ignoring wrapping if it's - * larger than the max time_t value). - */ - - if(cnbp->flags & (FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_LAST_WRITE)) { - pstring full_name; - char *p; - char *fname; - size_t remaining_len; - size_t fullname_len; - void *dp = OpenDir(cnbp->conn, fsp->fsp_name, True); - - if(dp == NULL) { - DEBUG(0,("create_directory_notify_hash: Unable to open directory = %s. \ -Error was %s\n", fsp->fsp_name, strerror(errno) )); - return False; - } - - change_data->num_entries = 0; - - pstrcpy(full_name, fsp->fsp_name); - pstrcat(full_name, "/"); - - fullname_len = strlen(full_name); - remaining_len = sizeof(full_name) - fullname_len - 1; - p = &full_name[fullname_len]; - - while ((fname = ReadDirName(dp))) { - if(strequal(fname, ".") || strequal(fname, "..")) - continue; - - change_data->num_entries++; - safe_strcpy( p, fname, remaining_len); - - memset(&st, '\0', sizeof(st)); - - /* - * Do the stat - but ignore errors. - */ - - if(dos_stat(full_name, &st) < 0) { - DEBUG(5,("create_directory_notify_hash: Unable to stat content file = %s. \ -Error was %s\n", fsp->fsp_name, strerror(errno) )); - } - change_data->total_time += (st.st_mtime + st.st_ctime); - } - - CloseDir(dp); - } - - return True; + cnotify->remove_notify(cnbp->change_data); + DLIST_REMOVE(change_notify_list, cnbp); + ZERO_STRUCTP(cnbp); + free(cnbp); } + /**************************************************************************** Delete entries by fnum from the change notify pending queue. *****************************************************************************/ - void remove_pending_change_notify_requests_by_fid(files_struct *fsp) { - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - change_notify_buf *prev = NULL; - - while(cnbp != NULL) { - if(cnbp->fsp->fnum == fsp->fnum) { - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - continue; - } - - prev = cnbp; - cnbp = (change_notify_buf *)ubi_slNext(cnbp); - } + struct change_notify *cnbp, *next; + + for (cnbp=change_notify_list; cnbp; cnbp=next) { + next=cnbp->next; + if (cnbp->fsp->fnum == fsp->fnum) { + change_notify_remove(cnbp); + } + } } /**************************************************************************** Delete entries by mid from the change notify pending queue. Always send reply. *****************************************************************************/ - void remove_pending_change_notify_requests_by_mid(int mid) { - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - change_notify_buf *prev = NULL; - - while(cnbp != NULL) { - if(SVAL(cnbp->request_buf,smb_mid) == mid) { - change_notify_reply_packet(cnbp->request_buf,0,0xC0000000 |NT_STATUS_CANCELLED); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - continue; - } - - prev = cnbp; - cnbp = (change_notify_buf *)ubi_slNext(cnbp); - } + struct change_notify *cnbp, *next; + + for (cnbp=change_notify_list; cnbp; cnbp=next) { + next=cnbp->next; + if(SVAL(cnbp->request_buf,smb_mid) == mid) { + change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED); + change_notify_remove(cnbp); + } + } } /**************************************************************************** Delete entries by filename and cnum from the change notify pending queue. Always send reply. *****************************************************************************/ - void remove_pending_change_notify_requests_by_filename(files_struct *fsp) { - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - change_notify_buf *prev = NULL; - - while(cnbp != NULL) { - /* - * We know it refers to the same directory if the connection number and - * the filename are identical. - */ - if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp->request_buf,0,0xC0000000 |NT_STATUS_CANCELLED); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - continue; - } - - prev = cnbp; - cnbp = (change_notify_buf *)ubi_slNext(cnbp); - } + struct change_notify *cnbp, *next; + + for (cnbp=change_notify_list; cnbp; cnbp=next) { + next=cnbp->next; + /* + * We know it refers to the same directory if the connection number and + * the filename are identical. + */ + if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { + change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED); + change_notify_remove(cnbp); + } + } +} + +/**************************************************************************** + Return true if there are pending change notifies. +****************************************************************************/ +BOOL change_notifies_pending(void) +{ + return (change_notify_list != NULL); } /**************************************************************************** @@ -247,121 +154,36 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp) Returns True if there are still outstanding change notify requests on the queue. *****************************************************************************/ - BOOL process_pending_change_notify_queue(time_t t) { - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - change_notify_buf *prev = NULL; - - if(cnbp == NULL) - return False; - - if(cnbp->next_check_time >= t) - return True; - - /* - * It's time to check. Go through the queue and see if - * the timestamps changed. - */ - - while((cnbp != NULL) && (cnbp->next_check_time <= t)) { - change_hash_data change_data; - connection_struct *conn = cnbp->conn; - uint16 vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : - SVAL(cnbp->request_buf,smb_uid); - - ZERO_STRUCT(change_data); - - /* - * Ensure we don't have any old chain_fsp values - * sitting around.... - */ - chain_size = 0; - file_chain_reset(); - - if(!become_user(conn,vuid)) { - DEBUG(0,("process_pending_change_notify_queue: Unable to become user vuid=%d.\n", - vuid )); - /* - * Remove the entry and return an error to the client. - */ - change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - continue; - } - - if(!become_service(conn,True)) { - DEBUG(0,("process_pending_change_notify_queue: Unable to become service Error was %s.\n", strerror(errno) )); - /* - * Remove the entry and return an error to the client. - */ - change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - unbecome_user(); - continue; - } - - if(!create_directory_notify_hash( cnbp, &change_data)) { - DEBUG(0,("process_pending_change_notify_queue: Unable to create change data for \ -directory %s\n", cnbp->fsp->fsp_name )); - /* - * Remove the entry and return an error to the client. - */ - change_notify_reply_packet(cnbp->request_buf,ERRSRV,ERRaccess); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - unbecome_user(); - continue; - } - - if(memcmp( (char *)&cnbp->change_data, (char *)&change_data, sizeof(change_data))) { - /* - * Remove the entry and return a change notify to the client. - */ - DEBUG(5,("process_pending_change_notify_queue: directory name = %s changed.\n", - cnbp->fsp->fsp_name )); - change_notify_reply_packet(cnbp->request_buf,0,NT_STATUS_NOTIFY_ENUM_DIR); - free((char *)ubi_slRemNext( &change_notify_queue, prev)); - cnbp = (change_notify_buf *)(prev ? ubi_slNext(prev) : ubi_slFirst(&change_notify_queue)); - unbecome_user(); - continue; - } - - unbecome_user(); - - /* - * Move to the next in the list. - */ - prev = cnbp; - cnbp = (change_notify_buf *)ubi_slNext(cnbp); - } - - return (cnbp != NULL); -} + struct change_notify *cnbp, *next; + uint16 vuid; + + for (cnbp=change_notify_list; cnbp; cnbp=next) { + next=cnbp->next; + + vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); + + if (cnotify->check_notify(cnbp->conn, vuid, cnbp->fsp->fsp_name, cnbp->flags, cnbp->change_data, t)) { + change_notify_reply_packet(cnbp->request_buf,STATUS_NOTIFY_ENUM_DIR); + change_notify_remove(cnbp); + } + } -/**************************************************************************** - Return true if there are pending change notifies. -****************************************************************************/ -BOOL change_notifies_pending(void) -{ - change_notify_buf *cnbp = (change_notify_buf *)ubi_slFirst( &change_notify_queue ); - return (cnbp != NULL); + return (change_notify_list != NULL); } /**************************************************************************** - * Now queue an entry on the notify change stack. We timestamp - * the entry we are adding so that we know when to scan next. + * Now queue an entry on the notify change list. * We only need to save smb_size bytes from this incoming packet * as we will always by returning a 'read the directory yourself' * error. ****************************************************************************/ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, uint32 flags) { - change_notify_buf *cnbp; + struct change_notify *cnbp; - if((cnbp = (change_notify_buf *)malloc(sizeof(change_notify_buf))) == NULL) { + if((cnbp = (struct change_notify *)malloc(sizeof(*cnbp))) == NULL) { DEBUG(0,("call_nt_transact_notify_change: malloc fail !\n" )); return -1; } @@ -371,23 +193,34 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, memcpy(cnbp->request_buf, inbuf, smb_size); cnbp->fsp = fsp; cnbp->conn = conn; - cnbp->next_check_time = time(NULL) + lp_change_notify_timeout(); cnbp->flags = flags; + cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, flags); - if (!create_directory_notify_hash(cnbp, &cnbp->change_data)) { - free((char *)cnbp); + if (!cnbp->change_data) { + free(cnbp); return False; } + + DLIST_ADD(change_notify_list, cnbp); + + return True; +} + + +/**************************************************************************** +initialise the change notify subsystem +****************************************************************************/ +BOOL init_change_notify(void) +{ + cnotify = hash_notify_init(); - /* - * Adding to the tail enables us to check only - * the head when scanning for change, as this entry - * is forced to have the first timeout expiration. - */ - - ubi_slAddTail(&change_notify_queue, cnbp); + if (!cnotify) { + DEBUG(0,("Failed to init change notify system\n")); + return False; + } return True; } + #undef OLD_NTDOMAIN -- cgit From c8de9b8fe14fe1e6e85652d543615dc187949a1a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 12 Jun 2000 17:06:00 +0000 Subject: enable the Linux change notify code and change some notify debug code (This used to be commit c6be511fcc1be79619a0184f03d4c33dbfe12f04) --- source3/smbd/notify.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 40867a71ee..c577d0aef3 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -212,7 +212,10 @@ initialise the change notify subsystem ****************************************************************************/ BOOL init_change_notify(void) { - cnotify = hash_notify_init(); +#if HAVE_KERNEL_CHANGE_NOTIFY + cnotify = kernel_notify_init(); +#endif + if (!cnotify) cnotify = hash_notify_init(); if (!cnotify) { DEBUG(0,("Failed to init change notify system\n")); -- cgit From cc5502a4d01bfc4946fbd198aad75ea03e9734d3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 14 Jun 2000 07:11:27 +0000 Subject: allow the notify implementation to choose the select timeout change (This used to be commit b1441d9622609af5ef598c5e1e1f5af438dc0731) --- source3/smbd/notify.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index c577d0aef3..912ab43e9e 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -144,9 +144,9 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp) /**************************************************************************** Return true if there are pending change notifies. ****************************************************************************/ -BOOL change_notifies_pending(void) +int change_notify_timeout(void) { - return (change_notify_list != NULL); + return cnotify->select_time; } /**************************************************************************** -- cgit From da3053048c3d224a20d6383ac6682d31059cd46c Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sun, 11 Mar 2001 00:32:10 +0000 Subject: Merge of new 2.2 code into HEAD (Gerald I hate you :-) :-). Allows new SAMR RPC code to merge with new passdb code. Currently rpcclient doesn't compile. I'm working on it... Jeremy. (This used to be commit 0be41d5158ea4e645e93e8cd30617c038416e549) --- source3/smbd/notify.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 912ab43e9e..429723c19e 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -1,4 +1,3 @@ -#define OLD_NTDOMAIN 1 /* Unix SMB/Netbios implementation. Version 3.0 @@ -224,6 +223,3 @@ BOOL init_change_notify(void) return True; } - - -#undef OLD_NTDOMAIN -- cgit From f63ee18c684af33342de2c5757f9fdf0b7d84997 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 9 Jun 2001 01:38:54 +0000 Subject: *Wonderful* patch from Andrew Bartlett that will help ensure tdb's are cleaned on clients abending connections. Thanks Andrew ! Jeremy. (This used to be commit 1b3977c5367a0b713b194f369abd9872ae01ac2a) --- source3/smbd/notify.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 429723c19e..3c21ce1e1b 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -71,7 +71,8 @@ static void change_notify_reply_packet(char *inbuf, uint32 error_code) */ set_message(outbuf,18,0,False); - send_smb(smbd_server_fd(),outbuf); + if (!send_smb(smbd_server_fd(),outbuf)) + exit_server("change_notify_reply_packet: send_smb failed.\n"); } /**************************************************************************** -- cgit From e8e98c9ea0690e3acf1126b50882e59e1056c7b3 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 27 Aug 2001 08:19:43 +0000 Subject: converted smbd to use NTSTATUS by default major changes include: - added NSTATUS type - added automatic mapping between dos and nt error codes - changed all ERROR() calls to ERROR_DOS() and many to ERROR_NT() these calls auto-translate to the client error code system - got rid of the cached error code and the writebmpx code We eventually will need to also: - get rid of BOOL, so we don't lose error info - replace all ERROR_DOS() calls with ERROR_NT() calls but that is too much for one night (This used to be commit 83d9896c1ea8be796192b51a4678c2a3b87f7518) --- source3/smbd/notify.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 3c21ce1e1b..a2a979b776 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -54,16 +54,7 @@ static void change_notify_reply_packet(char *inbuf, uint32 error_code) memset(outbuf, '\0', sizeof(outbuf)); construct_reply_common(inbuf, outbuf); - /* - * If we're returning a 'too much in the directory changed' we need to - * set this is an NT error status flags. If we don't then the (probably - * untested) code in the NT redirector has a bug in that it doesn't re-issue - * the change notify.... Ah - I *love* it when I get so deeply into this I - * can even determine how MS failed to test stuff and why.... :-). JRA. - */ - - SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_32_BIT_ERROR_CODES); - ERROR(0,error_code); + ERROR_NT(error_code); /* * Seems NT needs a transact command with an error code -- cgit From 19fea3242cf6234786b6cbb60631e0071f31ff9f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 4 Sep 2001 07:13:01 +0000 Subject: the next stage in the NTSTATUS/WERROR change. smbd and nmbd now compile, but the client code still needs some work (This used to be commit dcd6e735f709a9231860ceb9682db40ff26c9a66) --- source3/smbd/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index a2a979b776..5aa0b4ad3f 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -47,7 +47,7 @@ static struct change_notify *change_notify_list; /**************************************************************************** Setup the common parts of the return packet and send it. *****************************************************************************/ -static void change_notify_reply_packet(char *inbuf, uint32 error_code) +static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) { char outbuf[smb_size+38]; -- cgit From 61b2794968faa35dc91edce17e9b91e5366c3514 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Mon, 17 Sep 2001 11:25:41 +0000 Subject: move to SAFE_FREE() (This used to be commit a95943fde0ad89ae3f2deca2f7ba9cb5ab612b74) --- source3/smbd/notify.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 5aa0b4ad3f..68b51aeabb 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -76,7 +76,7 @@ static void change_notify_remove(struct change_notify *cnbp) cnotify->remove_notify(cnbp->change_data); DLIST_REMOVE(change_notify_list, cnbp); ZERO_STRUCTP(cnbp); - free(cnbp); + SAFE_FREE(cnbp); } @@ -188,7 +188,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, flags); if (!cnbp->change_data) { - free(cnbp); + SAFE_FREE(cnbp); return False; } -- cgit From dc1fc3ee8ec2199bc73bb5d7ec711c6800f61d65 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Tue, 2 Oct 2001 04:29:50 +0000 Subject: Removed 'extern int DEBUGLEVEL' as it is now in the smb.h header. (This used to be commit 2d0922b0eabfdc0aaf1d0797482fef47ed7fde8e) --- source3/smbd/notify.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 68b51aeabb..999821354e 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -22,8 +22,6 @@ #include "includes.h" -extern int DEBUGLEVEL; - static struct cnotify_fns *cnotify; /**************************************************************************** -- cgit From 4bb9cebf84e1addc135c18b1227e7c00e7c03163 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 19 Oct 2001 08:37:32 +0000 Subject: Tidy up debug in notify code. Jeremy. (This used to be commit 7707c5e07385ce5ac3732715d586ad6c6b41de65) --- source3/smbd/notify.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 999821354e..d333e0f75a 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -28,7 +28,7 @@ static struct cnotify_fns *cnotify; This is the structure to queue to implement NT change notify. It consists of smb_size bytes stored from the transact command (to keep the mid, tid etc around). - Plus the fid to examine and notify private data + Plus the fid to examine and notify private data. *****************************************************************************/ struct change_notify { @@ -65,10 +65,10 @@ static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) } /**************************************************************************** -remove an entry from the list and free it, also closing any -directory handle if necessary -Notice the horrible stuff we have to do because this is a singly linked list. + Remove an entry from the list and free it, also closing any + directory handle if necessary. *****************************************************************************/ + static void change_notify_remove(struct change_notify *cnbp) { cnotify->remove_notify(cnbp->change_data); @@ -77,10 +77,10 @@ static void change_notify_remove(struct change_notify *cnbp) SAFE_FREE(cnbp); } - /**************************************************************************** Delete entries by fnum from the change notify pending queue. *****************************************************************************/ + void remove_pending_change_notify_requests_by_fid(files_struct *fsp) { struct change_notify *cnbp, *next; @@ -96,6 +96,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp) /**************************************************************************** Delete entries by mid from the change notify pending queue. Always send reply. *****************************************************************************/ + void remove_pending_change_notify_requests_by_mid(int mid) { struct change_notify *cnbp, *next; @@ -113,6 +114,7 @@ void remove_pending_change_notify_requests_by_mid(int mid) Delete entries by filename and cnum from the change notify pending queue. Always send reply. *****************************************************************************/ + void remove_pending_change_notify_requests_by_filename(files_struct *fsp) { struct change_notify *cnbp, *next; @@ -133,6 +135,7 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp) /**************************************************************************** Return true if there are pending change notifies. ****************************************************************************/ + int change_notify_timeout(void) { return cnotify->select_time; @@ -143,6 +146,7 @@ int change_notify_timeout(void) Returns True if there are still outstanding change notify requests on the queue. *****************************************************************************/ + BOOL process_pending_change_notify_queue(time_t t) { struct change_notify *cnbp, *next; @@ -152,8 +156,9 @@ BOOL process_pending_change_notify_queue(time_t t) next=cnbp->next; vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); - + if (cnotify->check_notify(cnbp->conn, vuid, cnbp->fsp->fsp_name, cnbp->flags, cnbp->change_data, t)) { + DEBUG(10,("process_pending_change_notify_queue: dir %s changed !\n", cnbp->fsp->fsp_name )); change_notify_reply_packet(cnbp->request_buf,STATUS_NOTIFY_ENUM_DIR); change_notify_remove(cnbp); } @@ -163,11 +168,12 @@ BOOL process_pending_change_notify_queue(time_t t) } /**************************************************************************** - * Now queue an entry on the notify change list. - * We only need to save smb_size bytes from this incoming packet - * as we will always by returning a 'read the directory yourself' - * error. + Now queue an entry on the notify change list. + We only need to save smb_size bytes from this incoming packet + as we will always by returning a 'read the directory yourself' + error. ****************************************************************************/ + BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, uint32 flags) { struct change_notify *cnbp; @@ -195,10 +201,10 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, return True; } - /**************************************************************************** -initialise the change notify subsystem + Initialise the change notify subsystem. ****************************************************************************/ + BOOL init_change_notify(void) { #if HAVE_KERNEL_CHANGE_NOTIFY -- cgit From d876260d885ad991526544756609ea38e4867028 Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Mon, 5 Nov 2001 00:02:38 +0000 Subject: Don't put a \n on the end of the arg to exit_server() (This used to be commit dfb8566220c3e90ca2b757ea124f53aed103269e) --- source3/smbd/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index d333e0f75a..52df3558aa 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -61,7 +61,7 @@ static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) set_message(outbuf,18,0,False); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("change_notify_reply_packet: send_smb failed.\n"); + exit_server("change_notify_reply_packet: send_smb failed."); } /**************************************************************************** -- cgit From cd68afe31256ad60748b34f7318a180cfc2127cc Mon Sep 17 00:00:00 2001 From: Tim Potter Date: Wed, 30 Jan 2002 06:08:46 +0000 Subject: Removed version number from file header. Changed "SMB/Netbios" to "SMB/CIFS" in file header. (This used to be commit 6a58c9bd06d0d7502a24bf5ce5a2faf0a146edfa) --- source3/smbd/notify.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 52df3558aa..0895ddaf87 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -1,6 +1,5 @@ /* - Unix SMB/Netbios implementation. - Version 3.0 + Unix SMB/CIFS implementation. change notify handling Copyright (C) Andrew Tridgell 2000 Copyright (C) Jeremy Allison 1994-1998 -- cgit From d0fe43f918eae56d60398231f53266698d732fd7 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 12 Dec 2002 02:01:56 +0000 Subject: Added "kernel change notify" boolean to allow easier valgrind testing. Jeremy. (This used to be commit faf89f214f326bc07f728b354062b2287cda1208) --- source3/smbd/notify.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 0895ddaf87..de1b331778 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -207,7 +207,8 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, BOOL init_change_notify(void) { #if HAVE_KERNEL_CHANGE_NOTIFY - cnotify = kernel_notify_init(); + if (lp_kernel_change_notify()) + cnotify = kernel_notify_init(); #endif if (!cnotify) cnotify = hash_notify_init(); -- cgit From 08634e26e45d3dd935727e43587a137c72417cd3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jul 2003 06:19:37 +0000 Subject: SMB signing is now working with change notify. Need to fix the disconnect when bad signature received, plus check the oplock breaks.... Jermey. (This used to be commit dd83931a00ec0a2c4b78b939c54bc101ec82312f) --- source3/smbd/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index de1b331778..a0398d5a10 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -178,7 +178,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, struct change_notify *cnbp; if((cnbp = (struct change_notify *)malloc(sizeof(*cnbp))) == NULL) { - DEBUG(0,("call_nt_transact_notify_change: malloc fail !\n" )); + DEBUG(0,("change_notify_set: malloc fail !\n" )); return -1; } -- cgit From 0c9433c03188a2d1b49318dd8535d10b7805ce42 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 24 Jul 2003 06:56:56 +0000 Subject: Ensure everywhere we defer an incoming SMB request (blocking lock queue, in oplock break state, change notify queue) we also push the MID onto the deferred signing queue. Tomorrow I will test this with valgrind and oplock tests. Jeremy. (This used to be commit 33a377f3726c85379ba5b962dd7c8ead337b892f) --- source3/smbd/notify.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index a0398d5a10..e7903719ad 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -197,6 +197,9 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, DLIST_ADD(change_notify_list, cnbp); + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(inbuf,smb_mid)); + return True; } -- cgit From b925d197f5c1829f7bb8c18de2557c0ccc2d94a9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Sat, 2 Aug 2003 08:48:01 +0000 Subject: Ensure we don't leak any sign records on cancel of pending requests. Jeremy. (This used to be commit 9a8ffc239c0f1aada713de7e9e007066738d8874) --- source3/smbd/notify.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index e7903719ad..9adf827c79 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -44,6 +44,7 @@ static struct change_notify *change_notify_list; /**************************************************************************** Setup the common parts of the return packet and send it. *****************************************************************************/ + static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) { char outbuf[smb_size+38]; -- cgit From 110abf10d208769bf6bcfc0604874cb1bed0406a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 7 Aug 2003 02:59:52 +0000 Subject: Turns out I had my packet sequences wrong for oplock break code. I was storing the mid of the oplock break - I should have been storing the mid from the open. There are thus 2 types of deferred packet sequence returns - ones that increment the sequence number (returns from oplock causing opens) and ones that don't (change notify returns etc). Running with signing forced on does lead to some interesting tests :-). Jeremy. (This used to be commit 85907f02cec566502d9e4adabbd414020a26064d) --- source3/smbd/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 9adf827c79..ca6f2b783f 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -199,7 +199,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, DLIST_ADD(change_notify_list, cnbp); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid)); + srv_defer_sign_response(SVAL(inbuf,smb_mid), True); return True; } -- cgit From 3fe18a46a33cc1c0a0ecfefc61618356d7746a15 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 21 Oct 2003 17:40:58 +0000 Subject: Fix signing miss-sequence noticed by Stefan Metzmacher Jeremy. (This used to be commit 63f331564396e7a4f16dce95bb98d3b6c4b75351) --- source3/smbd/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index ca6f2b783f..9adf827c79 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -199,7 +199,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, DLIST_ADD(change_notify_list, cnbp); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid), True); + srv_defer_sign_response(SVAL(inbuf,smb_mid)); return True; } -- cgit From acf9d61421faa6c0055d57fdee7db300dc5431aa Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 7 Dec 2004 18:25:53 +0000 Subject: r4088: Get medieval on our ass about malloc.... :-). Take control of all our allocation functions so we can funnel through some well known functions. Should help greatly with malloc checking. HEAD patch to follow. Jeremy. (This used to be commit 620f2e608f70ba92f032720c031283d295c5c06a) --- source3/smbd/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 9adf827c79..92b86f350c 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -178,7 +178,7 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, { struct change_notify *cnbp; - if((cnbp = (struct change_notify *)malloc(sizeof(*cnbp))) == NULL) { + if((cnbp = SMB_MALLOC_P(struct change_notify)) == NULL) { DEBUG(0,("change_notify_set: malloc fail !\n" )); return -1; } -- cgit From f2f55d703d0dd549a83809d3e5cc5151569b48d6 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 27 Jun 2005 22:53:56 +0000 Subject: r7963: Add aio support to 3.0. Jeremy. (This used to be commit 1de27da47051af08790317f5b48b02719d6b9934) --- source3/smbd/notify.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 92b86f350c..ad49dc0a21 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -60,6 +60,7 @@ static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) */ set_message(outbuf,18,0,False); + show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) exit_server("change_notify_reply_packet: send_smb failed."); } -- cgit From c0dad16e0ff95a800dfbe11ca3c6303d882687a9 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 27 Oct 2005 23:30:25 +0000 Subject: r11344: I don't think share mode conflicts occur on deleting a directory when you've got permissions. Need to write a smbtorture test for this. Jeremy. (This used to be commit e959a5be393eb59b8987eb6967a2ee5d11978f41) --- source3/smbd/notify.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index ad49dc0a21..bc76cfb322 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -82,13 +82,14 @@ static void change_notify_remove(struct change_notify *cnbp) Delete entries by fnum from the change notify pending queue. *****************************************************************************/ -void remove_pending_change_notify_requests_by_fid(files_struct *fsp) +void remove_pending_change_notify_requests_by_fid(files_struct *fsp, NTSTATUS status) { struct change_notify *cnbp, *next; for (cnbp=change_notify_list; cnbp; cnbp=next) { next=cnbp->next; if (cnbp->fsp->fnum == fsp->fnum) { + change_notify_reply_packet(cnbp->request_buf,status); change_notify_remove(cnbp); } } @@ -116,7 +117,7 @@ void remove_pending_change_notify_requests_by_mid(int mid) Always send reply. *****************************************************************************/ -void remove_pending_change_notify_requests_by_filename(files_struct *fsp) +void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTATUS status) { struct change_notify *cnbp, *next; @@ -127,7 +128,7 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp) * the filename are identical. */ if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED); + change_notify_reply_packet(cnbp->request_buf,status); change_notify_remove(cnbp); } } -- cgit From 543ff192b37feff91fd77c336177cb628bd1e08a Mon Sep 17 00:00:00 2001 From: James Peach Date: Thu, 19 Jan 2006 00:30:16 +0000 Subject: r13027: Support file change notifications from FAM. (This used to be commit 652b511ff24ce41c7745a0e00363e619e5027828) --- source3/smbd/notify.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index bc76cfb322..df3d45d20b 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -212,9 +212,15 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, BOOL init_change_notify(void) { + cnotify = NULL; + #if HAVE_KERNEL_CHANGE_NOTIFY - if (lp_kernel_change_notify()) + if (cnotify == NULL && lp_kernel_change_notify()) cnotify = kernel_notify_init(); +#endif +#if HAVE_FAM_CHANGE_NOTIFY + if (cnotify == NULL && lp_fam_change_notify()) + cnotify = fam_notify_init(); #endif if (!cnotify) cnotify = hash_notify_init(); -- cgit From 8fbdd112b2c69a54d05807163bfc52b34f4d0424 Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 13 Feb 2006 04:07:15 +0000 Subject: r13482: Push the FAM notification file descriptor into the select set to avoid unnecessary polling. (This used to be commit 1dce945ccbba25092cf54890301c8f78f8aede33) --- source3/smbd/notify.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index df3d45d20b..b2d0fc3326 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -206,6 +206,15 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, return True; } +int change_notify_fd(void) +{ + if (cnotify) { + return cnotify->notification_fd; + } + + return -1; +} + /**************************************************************************** Initialise the change notify subsystem. ****************************************************************************/ -- cgit From 2602e5fab165d426e3a87e0cdcf8f7c67596e501 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 12 May 2006 23:10:01 +0000 Subject: r15555: Make "change notify timeout" a per-share parameter - used when there's no kernel or FAM change notify. If set to zero this will turn off change notify for the share except when we ourselves change something (renames / deletes etc. ). Designed to help on large directory shares where a new changenotify is issued between each delete. This will be fixed correctly when we move to internal change notify (eg. back-port Samba4 changenotify). Jeremy. (This used to be commit 5a17bffbcd5082fde79c241468a0ff2b5903d540) --- source3/smbd/notify.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index b2d0fc3326..829ca3a736 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -135,7 +135,19 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTAT } /**************************************************************************** - Return true if there are pending change notifies. + Set the current change notify timeout to the lowest value across all service + values. +****************************************************************************/ + +void set_change_notify_timeout(int val) +{ + if (val > 0) { + cnotify->select_time = MIN(cnotify->select_time, val); + } +} + +/**************************************************************************** + Longest time to sleep for before doing a change notify scan. ****************************************************************************/ int change_notify_timeout(void) -- cgit From 5bb49b08f3d79ef9ee17dbbd64ce90dc438d96df Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 18 Dec 2006 04:25:21 +0000 Subject: r20237: Replace exit_server with exit_server_cleanly where appropriate. All send_smb failures should be clean exits. All times when we exit as a matter of policy should also be clean exits. (This used to be commit d6382092e72120a3c89ffe81975e8898d454bf06) --- source3/smbd/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 829ca3a736..4ec53567dd 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -62,7 +62,7 @@ static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server("change_notify_reply_packet: send_smb failed."); + exit_server_cleanly("change_notify_reply_packet: send_smb failed."); } /**************************************************************************** -- cgit From 98c082489bec0a0ce4db1daf4390e785381f229a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 28 Dec 2006 21:50:31 +0000 Subject: r20394: This is a *VERY* early start of my work on notify. Checking in because Jeremy was bugging me. Potentially this becomes quite intrusive, I'm not sure if I should open a temporary branch for this. Jeremy, Jerry, do you think 3_0 is the right place for this? Volker (This used to be commit bcf5c751cbe203c00814642e26440cf88f300bce) --- source3/smbd/notify.c | 293 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 282 insertions(+), 11 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 4ec53567dd..2a5d7fc552 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -35,22 +35,75 @@ struct change_notify { files_struct *fsp; connection_struct *conn; uint32 flags; + uint32 max_param_count; char request_buf[smb_size]; void *change_data; }; static struct change_notify *change_notify_list; +static BOOL notify_marshall_changes(struct notify_changes *changes, + prs_struct *ps) +{ + int i; + UNISTR uni_name; + + for (i=0; inum_changes; i++) { + struct notify_change *c = &changes->changes[i]; + size_t namelen; + uint32 u32_tmp; /* Temp arg to prs_uint32 to avoid + * signed/unsigned issues */ + + namelen = convert_string_allocate( + NULL, CH_UNIX, CH_UTF16LE, c->name, strlen(c->name)+1, + &uni_name.buffer, True); + if ((namelen == -1) || (uni_name.buffer == NULL)) { + goto fail; + } + + namelen -= 2; /* Dump NULL termination */ + + /* + * Offset to next entry, only if there is one + */ + + u32_tmp = (i == changes->num_changes-1) ? 0 : namelen + 12; + if (!prs_uint32("offset", ps, 1, &u32_tmp)) goto fail; + + u32_tmp = c->action; + if (!prs_uint32("action", ps, 1, &u32_tmp)) goto fail; + + u32_tmp = namelen; + if (!prs_uint32("namelen", ps, 1, &u32_tmp)) goto fail; + + if (!prs_unistr("name", ps, 1, &uni_name)) goto fail; + + /* + * Not NULL terminated, decrease by the 2 UCS2 \0 chars + */ + prs_set_offset(ps, prs_offset(ps)-2); + + SAFE_FREE(uni_name.buffer); + } + + return True; + + fail: + SAFE_FREE(uni_name.buffer); + return False; +} + /**************************************************************************** Setup the common parts of the return packet and send it. *****************************************************************************/ -static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) +static void change_notify_reply_packet(struct change_notify *notify, + NTSTATUS error_code) { char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(inbuf, outbuf); + construct_reply_common(notify->request_buf, outbuf); ERROR_NT(error_code); @@ -65,6 +118,47 @@ static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) exit_server_cleanly("change_notify_reply_packet: send_smb failed."); } +static void change_notify_reply(struct change_notify *notify) +{ + char *outbuf = NULL; + prs_struct ps; + size_t buflen = smb_size+38+notify->max_param_count; + + if (!prs_init(&ps, 0, NULL, False) + || !notify_marshall_changes(notify->fsp->notify, &ps)) { + change_notify_reply_packet(notify, NT_STATUS_NO_MEMORY); + goto done; + } + + if (prs_offset(&ps) > notify->max_param_count) { + /* + * We exceed what the client is willing to accept. Send + * nothing. + */ + change_notify_reply_packet(notify, NT_STATUS_OK); + goto done; + } + + if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { + change_notify_reply_packet(notify, NT_STATUS_NO_MEMORY); + goto done; + } + + memset(outbuf, '\0', sizeof(outbuf)); + construct_reply_common(notify->request_buf, outbuf); + + if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), + prs_offset(&ps), NULL, 0) == -1) { + exit_server("change_notify_reply_packet: send_smb failed."); + } + + done: + SAFE_FREE(outbuf); + prs_mem_free(&ps); + notify->fsp->notify->num_changes = 0; + TALLOC_FREE(notify->fsp->notify->changes); +} + /**************************************************************************** Remove an entry from the list and free it, also closing any directory handle if necessary. @@ -89,7 +183,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp, NTSTATUS st for (cnbp=change_notify_list; cnbp; cnbp=next) { next=cnbp->next; if (cnbp->fsp->fnum == fsp->fnum) { - change_notify_reply_packet(cnbp->request_buf,status); + change_notify_reply_packet(cnbp, status); change_notify_remove(cnbp); } } @@ -106,7 +200,7 @@ void remove_pending_change_notify_requests_by_mid(int mid) for (cnbp=change_notify_list; cnbp; cnbp=next) { next=cnbp->next; if(SVAL(cnbp->request_buf,smb_mid) == mid) { - change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED); + change_notify_reply_packet(cnbp, NT_STATUS_CANCELLED); change_notify_remove(cnbp); } } @@ -128,7 +222,7 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTAT * the filename are identical. */ if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp->request_buf,status); + change_notify_reply_packet(cnbp, status); change_notify_remove(cnbp); } } @@ -171,9 +265,13 @@ BOOL process_pending_change_notify_queue(time_t t) vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); - if (cnotify->check_notify(cnbp->conn, vuid, cnbp->fsp->fsp_name, cnbp->flags, cnbp->change_data, t)) { - DEBUG(10,("process_pending_change_notify_queue: dir %s changed !\n", cnbp->fsp->fsp_name )); - change_notify_reply_packet(cnbp->request_buf,STATUS_NOTIFY_ENUM_DIR); + if ((cnbp->fsp->notify->num_changes != 0) + || cnotify->check_notify(cnbp->conn, vuid, + cnbp->fsp->fsp_name, cnbp->flags, + cnbp->change_data, t)) { + DEBUG(10,("process_pending_change_notify_queue: dir " + "%s changed !\n", cnbp->fsp->fsp_name )); + change_notify_reply(cnbp); change_notify_remove(cnbp); } } @@ -188,13 +286,14 @@ BOOL process_pending_change_notify_queue(time_t t) error. ****************************************************************************/ -BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, uint32 flags) +BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, + uint32 flags, uint32 max_param_count) { struct change_notify *cnbp; if((cnbp = SMB_MALLOC_P(struct change_notify)) == NULL) { DEBUG(0,("change_notify_set: malloc fail !\n" )); - return -1; + return False; } ZERO_STRUCTP(cnbp); @@ -203,7 +302,9 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, cnbp->fsp = fsp; cnbp->conn = conn; cnbp->flags = flags; - cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, flags); + cnbp->max_param_count = max_param_count; + cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, + flags); if (!cnbp->change_data) { SAFE_FREE(cnbp); @@ -227,6 +328,174 @@ int change_notify_fd(void) return -1; } +/* notify message definition + +Offset Data length. +0 SMB_DEV_T dev 8 +8 SMB_INO_T inode 8 +16 uint32 action 4 +20.. name +*/ + +#define MSG_NOTIFY_MESSAGE_SIZE 21 /* Includes at least the '\0' terminator */ + +struct notify_message { + SMB_DEV_T dev; + SMB_INO_T inode; + uint32_t action; + char *name; +}; + +static DATA_BLOB notify_message_to_buf(const struct notify_message *msg) +{ + DATA_BLOB result; + size_t len; + + len = strlen(msg->name); + + result = data_blob(NULL, MSG_NOTIFY_MESSAGE_SIZE + len); + if (!result.data) { + return result; + } + + SDEV_T_VAL(result.data, 0, msg->dev); + SINO_T_VAL(result.data, 8, msg->inode); + SIVAL(result.data, 16, msg->action); + memcpy(result.data+20, msg->name, len+1); + + return result; +} + +static BOOL buf_to_notify_message(void *buf, size_t len, + struct notify_message *msg) +{ + if (len < MSG_NOTIFY_MESSAGE_SIZE) { + DEBUG(0, ("Got invalid notify message of len %d\n", len)); + return False; + } + + msg->dev = DEV_T_VAL(buf, 0); + msg->inode = INO_T_VAL(buf, 8); + msg->action = IVAL(buf, 16); + msg->name = ((char *)buf)+20; + return True; +} + +void notify_action(connection_struct *conn, const char *parent, + const char *name, uint32_t action) +{ + struct share_mode_lock *lck; + SMB_STRUCT_STAT sbuf; + int i; + struct notify_message msg; + DATA_BLOB blob; + + struct process_id *pids; + int num_pids; + + if (SMB_VFS_STAT(conn, parent, &sbuf) != 0) { + /* + * Not 100% critical, ignore failure + */ + return; + } + + if (!(lck = get_share_mode_lock(NULL, sbuf.st_dev, sbuf.st_ino, + NULL, NULL))) { + return; + } + + msg.dev = sbuf.st_dev; + msg.inode = sbuf.st_ino; + msg.action = action; + msg.name = CONST_DISCARD(char *, name); + + blob = notify_message_to_buf(&msg); + if (blob.data == NULL) { + DEBUG(0, ("notify_message_to_buf failed\n")); + return; + } + + pids = NULL; + num_pids = 0; + + become_root_uid_only(); + + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + int j; + struct process_id *tmp; + + for (j=0; jpid, &pids[j])) { + break; + } + } + + if (j < num_pids) { + /* + * Already sent to that process, skip it + */ + continue; + } + + message_send_pid(lck->share_modes[i].pid, MSG_SMB_NOTIFY, + blob.data, blob.length, True); + + if (!(tmp = TALLOC_REALLOC_ARRAY(lck, pids, struct process_id, + num_pids+1))) { + DEBUG(0, ("realloc failed\n")); + break; + } + pids = tmp; + pids[num_pids] = e->pid; + num_pids += 1; + } + + unbecome_root_uid_only(); + + data_blob_free(&blob); + TALLOC_FREE(lck); +} + +static void notify_message(int msgtype, struct process_id pid, + void *buf, size_t len) +{ + struct notify_message msg; + files_struct *fsp; + struct notify_change *changes, *change; + + if (!buf_to_notify_message(buf, len, &msg)) { + return; + } + + DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n", + (unsigned)msg.dev, (double)msg.inode, msg.action)); + + if (!(fsp = file_find_dir_lowest_id(msg.dev, msg.inode))) { + DEBUG(10, ("notify_message: did not find fsp\n")); + return; + } + + if (!(changes = TALLOC_REALLOC_ARRAY( + fsp->notify, fsp->notify->changes, + struct notify_change, fsp->notify->num_changes+1))) { + DEBUG(0, ("talloc_realloc failed\n")); + return; + } + + fsp->notify->changes = changes; + + change = &(fsp->notify->changes[fsp->notify->num_changes]); + + if (!(change->name = talloc_strdup(changes, msg.name))) { + DEBUG(0, ("talloc_strdup failed\n")); + return; + } + change->action = msg.action; + fsp->notify->num_changes += 1; +} + /**************************************************************************** Initialise the change notify subsystem. ****************************************************************************/ @@ -250,5 +519,7 @@ BOOL init_change_notify(void) return False; } + message_register(MSG_SMB_NOTIFY, notify_message); + return True; } -- cgit From 165f5f3f40317c1e75d60a977270f903f7475f69 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 31 Dec 2006 10:16:03 +0000 Subject: r20433: Work in progress: Survive more of RAW-NOTIFY. call_nt_transact_notify_change() is now sync if there are changes around. A notify_message does a direct reply from within the message, so process_pending_change_notify_queue is not needed anymore for samba-generated events. Next step is to restructure the kernel-mechanisms to generate messages. Volker (This used to be commit c813f71d0036ec52c99a97e60fe33ee47d0635fa) --- source3/smbd/notify.c | 98 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 71 insertions(+), 27 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 2a5d7fc552..674505ac5b 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -33,7 +33,6 @@ static struct cnotify_fns *cnotify; struct change_notify { struct change_notify *next, *prev; files_struct *fsp; - connection_struct *conn; uint32 flags; uint32 max_param_count; char request_buf[smb_size]; @@ -97,13 +96,13 @@ static BOOL notify_marshall_changes(struct notify_changes *changes, Setup the common parts of the return packet and send it. *****************************************************************************/ -static void change_notify_reply_packet(struct change_notify *notify, +static void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) { char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(notify->request_buf, outbuf); + construct_reply_common(request_buf, outbuf); ERROR_NT(error_code); @@ -118,34 +117,34 @@ static void change_notify_reply_packet(struct change_notify *notify, exit_server_cleanly("change_notify_reply_packet: send_smb failed."); } -static void change_notify_reply(struct change_notify *notify) +void change_notify_reply(const char *request_buf, uint32 max_param_count, + files_struct *fsp) { char *outbuf = NULL; prs_struct ps; - size_t buflen = smb_size+38+notify->max_param_count; + size_t buflen = smb_size+38+max_param_count; if (!prs_init(&ps, 0, NULL, False) - || !notify_marshall_changes(notify->fsp->notify, &ps)) { - change_notify_reply_packet(notify, NT_STATUS_NO_MEMORY); + || !notify_marshall_changes(fsp->notify, &ps)) { + change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; } - if (prs_offset(&ps) > notify->max_param_count) { + if (prs_offset(&ps) > max_param_count) { /* * We exceed what the client is willing to accept. Send * nothing. */ - change_notify_reply_packet(notify, NT_STATUS_OK); + change_notify_reply_packet(request_buf, NT_STATUS_OK); goto done; } if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { - change_notify_reply_packet(notify, NT_STATUS_NO_MEMORY); + change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; } - memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(notify->request_buf, outbuf); + construct_reply_common(request_buf, outbuf); if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), prs_offset(&ps), NULL, 0) == -1) { @@ -155,8 +154,8 @@ static void change_notify_reply(struct change_notify *notify) done: SAFE_FREE(outbuf); prs_mem_free(&ps); - notify->fsp->notify->num_changes = 0; - TALLOC_FREE(notify->fsp->notify->changes); + fsp->notify->num_changes = 0; + TALLOC_FREE(fsp->notify->changes); } /**************************************************************************** @@ -183,7 +182,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp, NTSTATUS st for (cnbp=change_notify_list; cnbp; cnbp=next) { next=cnbp->next; if (cnbp->fsp->fnum == fsp->fnum) { - change_notify_reply_packet(cnbp, status); + change_notify_reply_packet(cnbp->request_buf, status); change_notify_remove(cnbp); } } @@ -200,7 +199,8 @@ void remove_pending_change_notify_requests_by_mid(int mid) for (cnbp=change_notify_list; cnbp; cnbp=next) { next=cnbp->next; if(SVAL(cnbp->request_buf,smb_mid) == mid) { - change_notify_reply_packet(cnbp, NT_STATUS_CANCELLED); + change_notify_reply_packet(cnbp->request_buf, + NT_STATUS_CANCELLED); change_notify_remove(cnbp); } } @@ -222,7 +222,7 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTAT * the filename are identical. */ if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp, status); + change_notify_reply_packet(cnbp->request_buf, status); change_notify_remove(cnbp); } } @@ -265,13 +265,25 @@ BOOL process_pending_change_notify_queue(time_t t) vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); - if ((cnbp->fsp->notify->num_changes != 0) - || cnotify->check_notify(cnbp->conn, vuid, - cnbp->fsp->fsp_name, cnbp->flags, - cnbp->change_data, t)) { + if (cnbp->fsp->notify->num_changes != 0) { + DEBUG(10,("process_pending_change_notify_queue: %s " + "has %d changes!\n", cnbp->fsp->fsp_name, + cnbp->fsp->notify->num_changes)); + change_notify_reply(cnbp->request_buf, + cnbp->max_param_count, + cnbp->fsp); + change_notify_remove(cnbp); + continue; + } + + if (cnotify->check_notify(cnbp->fsp->conn, vuid, + cnbp->fsp->fsp_name, cnbp->flags, + cnbp->change_data, t)) { DEBUG(10,("process_pending_change_notify_queue: dir " "%s changed !\n", cnbp->fsp->fsp_name )); - change_notify_reply(cnbp); + change_notify_reply(cnbp->request_buf, + cnbp->max_param_count, + cnbp->fsp); change_notify_remove(cnbp); } } @@ -300,7 +312,6 @@ BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, memcpy(cnbp->request_buf, inbuf, smb_size); cnbp->fsp = fsp; - cnbp->conn = conn; cnbp->flags = flags; cnbp->max_param_count = max_param_count; cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, @@ -393,6 +404,9 @@ void notify_action(connection_struct *conn, const char *parent, struct process_id *pids; int num_pids; + DEBUG(10, ("notify_action: parent=%s, name=%s, action=%u\n", + parent, name, (unsigned)action)); + if (SMB_VFS_STAT(conn, parent, &sbuf) != 0) { /* * Not 100% critical, ignore failure @@ -458,12 +472,13 @@ void notify_action(connection_struct *conn, const char *parent, TALLOC_FREE(lck); } -static void notify_message(int msgtype, struct process_id pid, - void *buf, size_t len) +static void notify_message_callback(int msgtype, struct process_id pid, + void *buf, size_t len) { struct notify_message msg; files_struct *fsp; struct notify_change *changes, *change; + struct change_notify *cnbp; if (!buf_to_notify_message(buf, len, &msg)) { return; @@ -472,7 +487,24 @@ static void notify_message(int msgtype, struct process_id pid, DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n", (unsigned)msg.dev, (double)msg.inode, msg.action)); - if (!(fsp = file_find_dir_lowest_id(msg.dev, msg.inode))) { + fsp = NULL; + + for (cnbp = change_notify_list; cnbp != NULL; cnbp = cnbp->next) { + if ((cnbp->fsp->dev == msg.dev) + && (cnbp->fsp->inode == msg.inode)) { + break; + } + } + + if (cnbp != NULL) { + DEBUG(10, ("Found pending change notify for %s\n", + cnbp->fsp->fsp_name)); + fsp = cnbp->fsp; + SMB_ASSERT(fsp->notify->num_changes == 0); + } + + if ((fsp == NULL) + && !(fsp = file_find_dir_lowest_id(msg.dev, msg.inode))) { DEBUG(10, ("notify_message: did not find fsp\n")); return; } @@ -494,6 +526,18 @@ static void notify_message(int msgtype, struct process_id pid, } change->action = msg.action; fsp->notify->num_changes += 1; + + if (cnbp != NULL) { + /* + * Respond directly, we have a someone waiting for this change + */ + DEBUG(10, ("Found pending cn for %s, responding directly\n", + cnbp->fsp->fsp_name)); + change_notify_reply(cnbp->request_buf, cnbp->max_param_count, + cnbp->fsp); + change_notify_remove(cnbp); + return; + } } /**************************************************************************** @@ -519,7 +563,7 @@ BOOL init_change_notify(void) return False; } - message_register(MSG_SMB_NOTIFY, notify_message); + message_register(MSG_SMB_NOTIFY, notify_message_callback); return True; } -- cgit From 200bd10b32107b4ce8fc72cc2abbf5a247708ba6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 31 Dec 2006 17:52:24 +0000 Subject: r20442: Slight rewrite of the change notify infrastructure. This now survives the first of the raw-notify subtests, the one-level test_notify_dir without any flags around yet. The tricky part was getting the data structures right, I hope the next tests don't let that fall over. fsp->notify is now by default NULL, meaning that nobody has issued a changenotify call. This means nobody is interested in changes for this directory. If that has happened, notify_change_buf collects the changes if no current request is outstanding, and it collects the requests if no change has happened since the last request. Happy New Year, somewhere on this planet it's already 2007 :-) Volker P.S: Jeremy, there's a question for you in smbd/files.c line 367. (This used to be commit ce0ad24988075465addcac0b9afc872e909135af) --- source3/smbd/notify.c | 202 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 136 insertions(+), 66 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 674505ac5b..9957c1fc5d 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -22,6 +22,7 @@ #include "includes.h" static struct cnotify_fns *cnotify; +static struct notify_mid_map *notify_changes_by_mid; /**************************************************************************** This is the structure to queue to implement NT change @@ -41,14 +42,15 @@ struct change_notify { static struct change_notify *change_notify_list; -static BOOL notify_marshall_changes(struct notify_changes *changes, +static BOOL notify_marshall_changes(unsigned num_changes, + struct notify_change *changes, prs_struct *ps) { int i; UNISTR uni_name; - for (i=0; inum_changes; i++) { - struct notify_change *c = &changes->changes[i]; + for (i=0; inum_changes-1) ? 0 : namelen + 12; + u32_tmp = (i == num_changes-1) ? 0 : namelen + 12; if (!prs_uint32("offset", ps, 1, &u32_tmp)) goto fail; u32_tmp = c->action; @@ -96,8 +98,7 @@ static BOOL notify_marshall_changes(struct notify_changes *changes, Setup the common parts of the return packet and send it. *****************************************************************************/ -static void change_notify_reply_packet(const char *request_buf, - NTSTATUS error_code) +void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) { char outbuf[smb_size+38]; @@ -118,14 +119,14 @@ static void change_notify_reply_packet(const char *request_buf, } void change_notify_reply(const char *request_buf, uint32 max_param_count, - files_struct *fsp) + unsigned num_changes, struct notify_change *changes) { char *outbuf = NULL; prs_struct ps; size_t buflen = smb_size+38+max_param_count; if (!prs_init(&ps, 0, NULL, False) - || !notify_marshall_changes(fsp->notify, &ps)) { + || !notify_marshall_changes(num_changes, changes, &ps)) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; } @@ -154,8 +155,6 @@ void change_notify_reply(const char *request_buf, uint32 max_param_count, done: SAFE_FREE(outbuf); prs_mem_free(&ps); - fsp->notify->num_changes = 0; - TALLOC_FREE(fsp->notify->changes); } /**************************************************************************** @@ -171,39 +170,100 @@ static void change_notify_remove(struct change_notify *cnbp) SAFE_FREE(cnbp); } -/**************************************************************************** - Delete entries by fnum from the change notify pending queue. -*****************************************************************************/ +NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, + struct files_struct *fsp) +{ + struct notify_change_request *request = NULL; + struct notify_mid_map *map = NULL; + + if (!(request = SMB_MALLOC_P(struct notify_change_request)) + || !(map = SMB_MALLOC_P(struct notify_mid_map))) { + SAFE_FREE(request); + return NT_STATUS_NO_MEMORY; + } -void remove_pending_change_notify_requests_by_fid(files_struct *fsp, NTSTATUS status) + request->mid_map = map; + map->req = request; + + memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); + request->max_param_count = max_param_count; + request->fsp = fsp; + DLIST_ADD_END(fsp->notify->requests, request, + struct notify_change_request *); + + map->mid = SVAL(inbuf, smb_mid); + DLIST_ADD(notify_changes_by_mid, map); + + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(inbuf,smb_mid)); + + return NT_STATUS_OK; +} + +static void change_notify_remove_request(struct notify_change_request *remove_req) { - struct change_notify *cnbp, *next; + files_struct *fsp; + struct notify_change_request *req; - for (cnbp=change_notify_list; cnbp; cnbp=next) { - next=cnbp->next; - if (cnbp->fsp->fnum == fsp->fnum) { - change_notify_reply_packet(cnbp->request_buf, status); - change_notify_remove(cnbp); + /* + * Paranoia checks, the fsp referenced must must have the request in + * its list of pending requests + */ + + fsp = remove_req->fsp; + SMB_ASSERT(fsp->notify != NULL); + + for (req = fsp->notify->requests; req; req = req->next) { + if (req == remove_req) { + break; } } + SMB_ASSERT(req != NULL); + + DLIST_REMOVE(fsp->notify->requests, req); + DLIST_REMOVE(notify_changes_by_mid, req->mid_map); + SAFE_FREE(req->mid_map); + SAFE_FREE(req); } /**************************************************************************** Delete entries by mid from the change notify pending queue. Always send reply. *****************************************************************************/ -void remove_pending_change_notify_requests_by_mid(int mid) +void remove_pending_change_notify_requests_by_mid(uint16 mid) { - struct change_notify *cnbp, *next; + struct notify_mid_map *map; - for (cnbp=change_notify_list; cnbp; cnbp=next) { - next=cnbp->next; - if(SVAL(cnbp->request_buf,smb_mid) == mid) { - change_notify_reply_packet(cnbp->request_buf, - NT_STATUS_CANCELLED); - change_notify_remove(cnbp); + for (map = notify_changes_by_mid; map; map = map->next) { + if (map->mid == mid) { + break; } } + + if (map == NULL) { + return; + } + + change_notify_reply_packet(map->req->request_buf, NT_STATUS_CANCELLED); + change_notify_remove_request(map->req); +} + +/**************************************************************************** + Delete entries by fnum from the change notify pending queue. +*****************************************************************************/ + +void remove_pending_change_notify_requests_by_fid(files_struct *fsp, + NTSTATUS status) +{ + if (fsp->notify == NULL) { + return; + } + + while (fsp->notify->requests != NULL) { + change_notify_reply_packet( + fsp->notify->requests->request_buf, status); + change_notify_remove_request(fsp->notify->requests); + } } /**************************************************************************** @@ -271,7 +331,8 @@ BOOL process_pending_change_notify_queue(time_t t) cnbp->fsp->notify->num_changes)); change_notify_reply(cnbp->request_buf, cnbp->max_param_count, - cnbp->fsp); + cnbp->fsp->notify->num_changes, + cnbp->fsp->notify->changes); change_notify_remove(cnbp); continue; } @@ -283,7 +344,8 @@ BOOL process_pending_change_notify_queue(time_t t) "%s changed !\n", cnbp->fsp->fsp_name )); change_notify_reply(cnbp->request_buf, cnbp->max_param_count, - cnbp->fsp); + cnbp->fsp->notify->num_changes, + cnbp->fsp->notify->changes); change_notify_remove(cnbp); } } @@ -472,43 +534,42 @@ void notify_action(connection_struct *conn, const char *parent, TALLOC_FREE(lck); } -static void notify_message_callback(int msgtype, struct process_id pid, - void *buf, size_t len) +static void notify_fsp(files_struct *fsp, struct notify_message *msg) { - struct notify_message msg; - files_struct *fsp; - struct notify_change *changes, *change; - struct change_notify *cnbp; + struct notify_change *change, *changes; - if (!buf_to_notify_message(buf, len, &msg)) { + if (fsp->notify == NULL) { + /* + * Nobody is waiting, don't queue + */ return; } - DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n", - (unsigned)msg.dev, (double)msg.inode, msg.action)); + if (fsp->notify->requests != NULL) { + /* + * Someone is waiting for the change, trigger the reply + * immediately + */ - fsp = NULL; + struct notify_change_request *req = fsp->notify->requests; + struct notify_change onechange; - for (cnbp = change_notify_list; cnbp != NULL; cnbp = cnbp->next) { - if ((cnbp->fsp->dev == msg.dev) - && (cnbp->fsp->inode == msg.inode)) { - break; - } - } + onechange.action = msg->action; + onechange.name = msg->name; - if (cnbp != NULL) { - DEBUG(10, ("Found pending change notify for %s\n", - cnbp->fsp->fsp_name)); - fsp = cnbp->fsp; - SMB_ASSERT(fsp->notify->num_changes == 0); - } + change_notify_reply(req->request_buf, req->max_param_count, + 1, &onechange); - if ((fsp == NULL) - && !(fsp = file_find_dir_lowest_id(msg.dev, msg.inode))) { - DEBUG(10, ("notify_message: did not find fsp\n")); + DLIST_REMOVE(fsp->notify->requests, req); + SAFE_FREE(req); return; } + /* + * Someone has triggered a notify previously, queue the change for + * later. TODO: Limit the number of changes queued. + */ + if (!(changes = TALLOC_REALLOC_ARRAY( fsp->notify, fsp->notify->changes, struct notify_change, fsp->notify->num_changes+1))) { @@ -520,24 +581,33 @@ static void notify_message_callback(int msgtype, struct process_id pid, change = &(fsp->notify->changes[fsp->notify->num_changes]); - if (!(change->name = talloc_strdup(changes, msg.name))) { + if (!(change->name = talloc_strdup(changes, msg->name))) { DEBUG(0, ("talloc_strdup failed\n")); return; } - change->action = msg.action; + change->action = msg->action; fsp->notify->num_changes += 1; - if (cnbp != NULL) { - /* - * Respond directly, we have a someone waiting for this change - */ - DEBUG(10, ("Found pending cn for %s, responding directly\n", - cnbp->fsp->fsp_name)); - change_notify_reply(cnbp->request_buf, cnbp->max_param_count, - cnbp->fsp); - change_notify_remove(cnbp); + return; +} + +static void notify_message_callback(int msgtype, struct process_id pid, + void *buf, size_t len) +{ + struct notify_message msg; + files_struct *fsp; + + if (!buf_to_notify_message(buf, len, &msg)) { return; } + + DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n", + (unsigned)msg.dev, (double)msg.inode, msg.action)); + + for(fsp = fsp_find_di_first(msg.dev, msg.inode); fsp; + fsp = fsp_find_di_next(fsp)) { + notify_fsp(fsp, &msg); + } } /**************************************************************************** -- cgit From dbc231a1c627ac8f83ce36c4139e3ac9b1477cf6 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 31 Dec 2006 18:10:47 +0000 Subject: r20443: Fix a compiler warning (This used to be commit 19781d71fc5a8146109395cd53c04cf13cc48652) --- source3/smbd/notify.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 9957c1fc5d..49a516b907 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -443,7 +443,8 @@ static BOOL buf_to_notify_message(void *buf, size_t len, struct notify_message *msg) { if (len < MSG_NOTIFY_MESSAGE_SIZE) { - DEBUG(0, ("Got invalid notify message of len %d\n", len)); + DEBUG(0, ("Got invalid notify message of len %d\n", + (int)len)); return False; } -- cgit From 92d02f7afe439a51f5a2eab3e1db8d628c170a6c Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 1 Jan 2007 18:11:32 +0000 Subject: r20451: Survive the first of the filter-tests (mkdir). Add lots of TODOs :-) Volker (This used to be commit 0e953884a15873b0962ab1ab064d6b3a436726c0) --- source3/smbd/notify.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 49a516b907..f94ff76e7b 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -171,7 +171,7 @@ static void change_notify_remove(struct change_notify *cnbp) } NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, - struct files_struct *fsp) + uint32 filter, struct files_struct *fsp) { struct notify_change_request *request = NULL; struct notify_mid_map *map = NULL; @@ -187,6 +187,7 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); request->max_param_count = max_param_count; + request->filter = filter; request->fsp = fsp; DLIST_ADD_END(fsp->notify->requests, request, struct notify_change_request *); @@ -406,16 +407,18 @@ int change_notify_fd(void) Offset Data length. 0 SMB_DEV_T dev 8 8 SMB_INO_T inode 8 -16 uint32 action 4 -20.. name +16 uint32 filter 4 +20 uint32 action 4 +24.. name */ -#define MSG_NOTIFY_MESSAGE_SIZE 21 /* Includes at least the '\0' terminator */ +#define MSG_NOTIFY_MESSAGE_SIZE 25 /* Includes at least the '\0' terminator */ struct notify_message { SMB_DEV_T dev; SMB_INO_T inode; - uint32_t action; + uint32 filter; + uint32 action; char *name; }; @@ -433,8 +436,9 @@ static DATA_BLOB notify_message_to_buf(const struct notify_message *msg) SDEV_T_VAL(result.data, 0, msg->dev); SINO_T_VAL(result.data, 8, msg->inode); - SIVAL(result.data, 16, msg->action); - memcpy(result.data+20, msg->name, len+1); + SIVAL(result.data, 16, msg->filter); + SIVAL(result.data, 20, msg->action); + memcpy(result.data+24, msg->name, len+1); return result; } @@ -450,13 +454,14 @@ static BOOL buf_to_notify_message(void *buf, size_t len, msg->dev = DEV_T_VAL(buf, 0); msg->inode = INO_T_VAL(buf, 8); - msg->action = IVAL(buf, 16); - msg->name = ((char *)buf)+20; + msg->filter = IVAL(buf, 16); + msg->action = IVAL(buf, 20); + msg->name = ((char *)buf)+24; return True; } void notify_action(connection_struct *conn, const char *parent, - const char *name, uint32_t action) + const char *name, uint32 filter, uint32_t action) { struct share_mode_lock *lck; SMB_STRUCT_STAT sbuf; @@ -484,6 +489,7 @@ void notify_action(connection_struct *conn, const char *parent, msg.dev = sbuf.st_dev; msg.inode = sbuf.st_ino; + msg.filter = filter; msg.action = action; msg.name = CONST_DISCARD(char *, name); @@ -546,10 +552,13 @@ static void notify_fsp(files_struct *fsp, struct notify_message *msg) return; } - if (fsp->notify->requests != NULL) { + if ((fsp->notify->requests != NULL) + && (fsp->notify->requests->filter & msg->filter)) { /* * Someone is waiting for the change, trigger the reply - * immediately + * immediately. + * + * TODO: do we have to walk the lists of requests pending? */ struct notify_change_request *req = fsp->notify->requests; @@ -560,15 +569,14 @@ static void notify_fsp(files_struct *fsp, struct notify_message *msg) change_notify_reply(req->request_buf, req->max_param_count, 1, &onechange); - - DLIST_REMOVE(fsp->notify->requests, req); - SAFE_FREE(req); + change_notify_remove_request(req); return; } /* * Someone has triggered a notify previously, queue the change for - * later. TODO: Limit the number of changes queued. + * later. TODO: Limit the number of changes queued, test how filters + * apply here. Do we have to store them? */ if (!(changes = TALLOC_REALLOC_ARRAY( -- cgit From b2efff8fe5cdfd031a7b6f814993a9c234a66ee8 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 7 Jan 2007 18:08:50 +0000 Subject: r20597: Survive some of the notify mask tests. (This used to be commit e4a2e63272dc5b20413597179d06b0185c4a6817) --- source3/smbd/notify.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index f94ff76e7b..bcd8fcb0ab 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -541,6 +541,20 @@ void notify_action(connection_struct *conn, const char *parent, TALLOC_FREE(lck); } +void notify_fname(connection_struct *conn, const char *path, + uint32 filter, uint32 action) +{ + char *parent; + const char *name; + + if (!parent_dirname_talloc(tmp_talloc_ctx(), path, &parent, &name)) { + return; + } + + notify_action(conn, parent, name, filter, action); + TALLOC_FREE(parent); +} + static void notify_fsp(files_struct *fsp, struct notify_message *msg) { struct notify_change *change, *changes; -- cgit From c79be5713ab5e01e4291b3b66e593c133f8fa9d7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 8 Jan 2007 08:00:53 +0000 Subject: r20602: Fix coverity ID 339. SMB_ASSERT does not panic without -DDEVELOPER. Volker (This used to be commit 33b5950bec407e295b2c6139e21d062e376df330) --- source3/smbd/notify.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index bcd8fcb0ab..6bedb17261 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -219,7 +219,10 @@ static void change_notify_remove_request(struct notify_change_request *remove_re break; } } - SMB_ASSERT(req != NULL); + + if (req == NULL) { + smb_panic("notify_req not found in fsp's requests\n"); + } DLIST_REMOVE(fsp->notify->requests, req); DLIST_REMOVE(notify_changes_by_mid, req->mid_map); -- cgit From 46fdae1b6b1b8e3285447193cb10e5a2a444d431 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 9 Jan 2007 16:12:54 +0000 Subject: r20634: A *LOT* more work is necessary before touching notify remotely starts to make sense. Until then, remove it from the tree to keep the diff between 3_0_24 and 3_0 small. Volker (This used to be commit f146a85e74c84e78a11e616a1cbeaeef4693a0e0) --- source3/smbd/notify.c | 467 +++----------------------------------------------- 1 file changed, 28 insertions(+), 439 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 6bedb17261..4ec53567dd 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -22,7 +22,6 @@ #include "includes.h" static struct cnotify_fns *cnotify; -static struct notify_mid_map *notify_changes_by_mid; /**************************************************************************** This is the structure to queue to implement NT change @@ -34,76 +33,24 @@ static struct notify_mid_map *notify_changes_by_mid; struct change_notify { struct change_notify *next, *prev; files_struct *fsp; + connection_struct *conn; uint32 flags; - uint32 max_param_count; char request_buf[smb_size]; void *change_data; }; static struct change_notify *change_notify_list; -static BOOL notify_marshall_changes(unsigned num_changes, - struct notify_change *changes, - prs_struct *ps) -{ - int i; - UNISTR uni_name; - - for (i=0; iname, strlen(c->name)+1, - &uni_name.buffer, True); - if ((namelen == -1) || (uni_name.buffer == NULL)) { - goto fail; - } - - namelen -= 2; /* Dump NULL termination */ - - /* - * Offset to next entry, only if there is one - */ - - u32_tmp = (i == num_changes-1) ? 0 : namelen + 12; - if (!prs_uint32("offset", ps, 1, &u32_tmp)) goto fail; - - u32_tmp = c->action; - if (!prs_uint32("action", ps, 1, &u32_tmp)) goto fail; - - u32_tmp = namelen; - if (!prs_uint32("namelen", ps, 1, &u32_tmp)) goto fail; - - if (!prs_unistr("name", ps, 1, &uni_name)) goto fail; - - /* - * Not NULL terminated, decrease by the 2 UCS2 \0 chars - */ - prs_set_offset(ps, prs_offset(ps)-2); - - SAFE_FREE(uni_name.buffer); - } - - return True; - - fail: - SAFE_FREE(uni_name.buffer); - return False; -} - /**************************************************************************** Setup the common parts of the return packet and send it. *****************************************************************************/ -void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) +static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) { char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(request_buf, outbuf); + construct_reply_common(inbuf, outbuf); ERROR_NT(error_code); @@ -118,45 +65,6 @@ void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) exit_server_cleanly("change_notify_reply_packet: send_smb failed."); } -void change_notify_reply(const char *request_buf, uint32 max_param_count, - unsigned num_changes, struct notify_change *changes) -{ - char *outbuf = NULL; - prs_struct ps; - size_t buflen = smb_size+38+max_param_count; - - if (!prs_init(&ps, 0, NULL, False) - || !notify_marshall_changes(num_changes, changes, &ps)) { - change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); - goto done; - } - - if (prs_offset(&ps) > max_param_count) { - /* - * We exceed what the client is willing to accept. Send - * nothing. - */ - change_notify_reply_packet(request_buf, NT_STATUS_OK); - goto done; - } - - if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { - change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); - goto done; - } - - construct_reply_common(request_buf, outbuf); - - if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), - prs_offset(&ps), NULL, 0) == -1) { - exit_server("change_notify_reply_packet: send_smb failed."); - } - - done: - SAFE_FREE(outbuf); - prs_mem_free(&ps); -} - /**************************************************************************** Remove an entry from the list and free it, also closing any directory handle if necessary. @@ -170,103 +78,37 @@ static void change_notify_remove(struct change_notify *cnbp) SAFE_FREE(cnbp); } -NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, - uint32 filter, struct files_struct *fsp) -{ - struct notify_change_request *request = NULL; - struct notify_mid_map *map = NULL; - - if (!(request = SMB_MALLOC_P(struct notify_change_request)) - || !(map = SMB_MALLOC_P(struct notify_mid_map))) { - SAFE_FREE(request); - return NT_STATUS_NO_MEMORY; - } - - request->mid_map = map; - map->req = request; - - memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); - request->max_param_count = max_param_count; - request->filter = filter; - request->fsp = fsp; - DLIST_ADD_END(fsp->notify->requests, request, - struct notify_change_request *); - - map->mid = SVAL(inbuf, smb_mid); - DLIST_ADD(notify_changes_by_mid, map); - - /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid)); - - return NT_STATUS_OK; -} - -static void change_notify_remove_request(struct notify_change_request *remove_req) -{ - files_struct *fsp; - struct notify_change_request *req; - - /* - * Paranoia checks, the fsp referenced must must have the request in - * its list of pending requests - */ - - fsp = remove_req->fsp; - SMB_ASSERT(fsp->notify != NULL); - - for (req = fsp->notify->requests; req; req = req->next) { - if (req == remove_req) { - break; - } - } - - if (req == NULL) { - smb_panic("notify_req not found in fsp's requests\n"); - } - - DLIST_REMOVE(fsp->notify->requests, req); - DLIST_REMOVE(notify_changes_by_mid, req->mid_map); - SAFE_FREE(req->mid_map); - SAFE_FREE(req); -} - /**************************************************************************** - Delete entries by mid from the change notify pending queue. Always send reply. + Delete entries by fnum from the change notify pending queue. *****************************************************************************/ -void remove_pending_change_notify_requests_by_mid(uint16 mid) +void remove_pending_change_notify_requests_by_fid(files_struct *fsp, NTSTATUS status) { - struct notify_mid_map *map; + struct change_notify *cnbp, *next; - for (map = notify_changes_by_mid; map; map = map->next) { - if (map->mid == mid) { - break; + for (cnbp=change_notify_list; cnbp; cnbp=next) { + next=cnbp->next; + if (cnbp->fsp->fnum == fsp->fnum) { + change_notify_reply_packet(cnbp->request_buf,status); + change_notify_remove(cnbp); } } - - if (map == NULL) { - return; - } - - change_notify_reply_packet(map->req->request_buf, NT_STATUS_CANCELLED); - change_notify_remove_request(map->req); } /**************************************************************************** - Delete entries by fnum from the change notify pending queue. + Delete entries by mid from the change notify pending queue. Always send reply. *****************************************************************************/ -void remove_pending_change_notify_requests_by_fid(files_struct *fsp, - NTSTATUS status) +void remove_pending_change_notify_requests_by_mid(int mid) { - if (fsp->notify == NULL) { - return; - } + struct change_notify *cnbp, *next; - while (fsp->notify->requests != NULL) { - change_notify_reply_packet( - fsp->notify->requests->request_buf, status); - change_notify_remove_request(fsp->notify->requests); + for (cnbp=change_notify_list; cnbp; cnbp=next) { + next=cnbp->next; + if(SVAL(cnbp->request_buf,smb_mid) == mid) { + change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED); + change_notify_remove(cnbp); + } } } @@ -286,7 +128,7 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTAT * the filename are identical. */ if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp->request_buf, status); + change_notify_reply_packet(cnbp->request_buf,status); change_notify_remove(cnbp); } } @@ -329,27 +171,9 @@ BOOL process_pending_change_notify_queue(time_t t) vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); - if (cnbp->fsp->notify->num_changes != 0) { - DEBUG(10,("process_pending_change_notify_queue: %s " - "has %d changes!\n", cnbp->fsp->fsp_name, - cnbp->fsp->notify->num_changes)); - change_notify_reply(cnbp->request_buf, - cnbp->max_param_count, - cnbp->fsp->notify->num_changes, - cnbp->fsp->notify->changes); - change_notify_remove(cnbp); - continue; - } - - if (cnotify->check_notify(cnbp->fsp->conn, vuid, - cnbp->fsp->fsp_name, cnbp->flags, - cnbp->change_data, t)) { - DEBUG(10,("process_pending_change_notify_queue: dir " - "%s changed !\n", cnbp->fsp->fsp_name )); - change_notify_reply(cnbp->request_buf, - cnbp->max_param_count, - cnbp->fsp->notify->num_changes, - cnbp->fsp->notify->changes); + if (cnotify->check_notify(cnbp->conn, vuid, cnbp->fsp->fsp_name, cnbp->flags, cnbp->change_data, t)) { + DEBUG(10,("process_pending_change_notify_queue: dir %s changed !\n", cnbp->fsp->fsp_name )); + change_notify_reply_packet(cnbp->request_buf,STATUS_NOTIFY_ENUM_DIR); change_notify_remove(cnbp); } } @@ -364,24 +188,22 @@ BOOL process_pending_change_notify_queue(time_t t) error. ****************************************************************************/ -BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, - uint32 flags, uint32 max_param_count) +BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, uint32 flags) { struct change_notify *cnbp; if((cnbp = SMB_MALLOC_P(struct change_notify)) == NULL) { DEBUG(0,("change_notify_set: malloc fail !\n" )); - return False; + return -1; } ZERO_STRUCTP(cnbp); memcpy(cnbp->request_buf, inbuf, smb_size); cnbp->fsp = fsp; + cnbp->conn = conn; cnbp->flags = flags; - cnbp->max_param_count = max_param_count; - cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, - flags); + cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, flags); if (!cnbp->change_data) { SAFE_FREE(cnbp); @@ -405,237 +227,6 @@ int change_notify_fd(void) return -1; } -/* notify message definition - -Offset Data length. -0 SMB_DEV_T dev 8 -8 SMB_INO_T inode 8 -16 uint32 filter 4 -20 uint32 action 4 -24.. name -*/ - -#define MSG_NOTIFY_MESSAGE_SIZE 25 /* Includes at least the '\0' terminator */ - -struct notify_message { - SMB_DEV_T dev; - SMB_INO_T inode; - uint32 filter; - uint32 action; - char *name; -}; - -static DATA_BLOB notify_message_to_buf(const struct notify_message *msg) -{ - DATA_BLOB result; - size_t len; - - len = strlen(msg->name); - - result = data_blob(NULL, MSG_NOTIFY_MESSAGE_SIZE + len); - if (!result.data) { - return result; - } - - SDEV_T_VAL(result.data, 0, msg->dev); - SINO_T_VAL(result.data, 8, msg->inode); - SIVAL(result.data, 16, msg->filter); - SIVAL(result.data, 20, msg->action); - memcpy(result.data+24, msg->name, len+1); - - return result; -} - -static BOOL buf_to_notify_message(void *buf, size_t len, - struct notify_message *msg) -{ - if (len < MSG_NOTIFY_MESSAGE_SIZE) { - DEBUG(0, ("Got invalid notify message of len %d\n", - (int)len)); - return False; - } - - msg->dev = DEV_T_VAL(buf, 0); - msg->inode = INO_T_VAL(buf, 8); - msg->filter = IVAL(buf, 16); - msg->action = IVAL(buf, 20); - msg->name = ((char *)buf)+24; - return True; -} - -void notify_action(connection_struct *conn, const char *parent, - const char *name, uint32 filter, uint32_t action) -{ - struct share_mode_lock *lck; - SMB_STRUCT_STAT sbuf; - int i; - struct notify_message msg; - DATA_BLOB blob; - - struct process_id *pids; - int num_pids; - - DEBUG(10, ("notify_action: parent=%s, name=%s, action=%u\n", - parent, name, (unsigned)action)); - - if (SMB_VFS_STAT(conn, parent, &sbuf) != 0) { - /* - * Not 100% critical, ignore failure - */ - return; - } - - if (!(lck = get_share_mode_lock(NULL, sbuf.st_dev, sbuf.st_ino, - NULL, NULL))) { - return; - } - - msg.dev = sbuf.st_dev; - msg.inode = sbuf.st_ino; - msg.filter = filter; - msg.action = action; - msg.name = CONST_DISCARD(char *, name); - - blob = notify_message_to_buf(&msg); - if (blob.data == NULL) { - DEBUG(0, ("notify_message_to_buf failed\n")); - return; - } - - pids = NULL; - num_pids = 0; - - become_root_uid_only(); - - for (i=0; inum_share_modes; i++) { - struct share_mode_entry *e = &lck->share_modes[i]; - int j; - struct process_id *tmp; - - for (j=0; jpid, &pids[j])) { - break; - } - } - - if (j < num_pids) { - /* - * Already sent to that process, skip it - */ - continue; - } - - message_send_pid(lck->share_modes[i].pid, MSG_SMB_NOTIFY, - blob.data, blob.length, True); - - if (!(tmp = TALLOC_REALLOC_ARRAY(lck, pids, struct process_id, - num_pids+1))) { - DEBUG(0, ("realloc failed\n")); - break; - } - pids = tmp; - pids[num_pids] = e->pid; - num_pids += 1; - } - - unbecome_root_uid_only(); - - data_blob_free(&blob); - TALLOC_FREE(lck); -} - -void notify_fname(connection_struct *conn, const char *path, - uint32 filter, uint32 action) -{ - char *parent; - const char *name; - - if (!parent_dirname_talloc(tmp_talloc_ctx(), path, &parent, &name)) { - return; - } - - notify_action(conn, parent, name, filter, action); - TALLOC_FREE(parent); -} - -static void notify_fsp(files_struct *fsp, struct notify_message *msg) -{ - struct notify_change *change, *changes; - - if (fsp->notify == NULL) { - /* - * Nobody is waiting, don't queue - */ - return; - } - - if ((fsp->notify->requests != NULL) - && (fsp->notify->requests->filter & msg->filter)) { - /* - * Someone is waiting for the change, trigger the reply - * immediately. - * - * TODO: do we have to walk the lists of requests pending? - */ - - struct notify_change_request *req = fsp->notify->requests; - struct notify_change onechange; - - onechange.action = msg->action; - onechange.name = msg->name; - - change_notify_reply(req->request_buf, req->max_param_count, - 1, &onechange); - change_notify_remove_request(req); - return; - } - - /* - * Someone has triggered a notify previously, queue the change for - * later. TODO: Limit the number of changes queued, test how filters - * apply here. Do we have to store them? - */ - - if (!(changes = TALLOC_REALLOC_ARRAY( - fsp->notify, fsp->notify->changes, - struct notify_change, fsp->notify->num_changes+1))) { - DEBUG(0, ("talloc_realloc failed\n")); - return; - } - - fsp->notify->changes = changes; - - change = &(fsp->notify->changes[fsp->notify->num_changes]); - - if (!(change->name = talloc_strdup(changes, msg->name))) { - DEBUG(0, ("talloc_strdup failed\n")); - return; - } - change->action = msg->action; - fsp->notify->num_changes += 1; - - return; -} - -static void notify_message_callback(int msgtype, struct process_id pid, - void *buf, size_t len) -{ - struct notify_message msg; - files_struct *fsp; - - if (!buf_to_notify_message(buf, len, &msg)) { - return; - } - - DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n", - (unsigned)msg.dev, (double)msg.inode, msg.action)); - - for(fsp = fsp_find_di_first(msg.dev, msg.inode); fsp; - fsp = fsp_find_di_next(fsp)) { - notify_fsp(fsp, &msg); - } -} - /**************************************************************************** Initialise the change notify subsystem. ****************************************************************************/ @@ -659,7 +250,5 @@ BOOL init_change_notify(void) return False; } - message_register(MSG_SMB_NOTIFY, notify_message_callback); - return True; } -- cgit From 940192ddcc9d23e3bec806b4419d5845eeac0fd0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 17 Jan 2007 16:23:45 +0000 Subject: r20854: Ok, now I think we're at a point where looking at notify starts to make sense again :-) Volker (This used to be commit 5533cdeec1b0cdee39b1d89e2320587dc9281ee6) --- source3/smbd/notify.c | 467 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 439 insertions(+), 28 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 4ec53567dd..6bedb17261 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -22,6 +22,7 @@ #include "includes.h" static struct cnotify_fns *cnotify; +static struct notify_mid_map *notify_changes_by_mid; /**************************************************************************** This is the structure to queue to implement NT change @@ -33,24 +34,76 @@ static struct cnotify_fns *cnotify; struct change_notify { struct change_notify *next, *prev; files_struct *fsp; - connection_struct *conn; uint32 flags; + uint32 max_param_count; char request_buf[smb_size]; void *change_data; }; static struct change_notify *change_notify_list; +static BOOL notify_marshall_changes(unsigned num_changes, + struct notify_change *changes, + prs_struct *ps) +{ + int i; + UNISTR uni_name; + + for (i=0; iname, strlen(c->name)+1, + &uni_name.buffer, True); + if ((namelen == -1) || (uni_name.buffer == NULL)) { + goto fail; + } + + namelen -= 2; /* Dump NULL termination */ + + /* + * Offset to next entry, only if there is one + */ + + u32_tmp = (i == num_changes-1) ? 0 : namelen + 12; + if (!prs_uint32("offset", ps, 1, &u32_tmp)) goto fail; + + u32_tmp = c->action; + if (!prs_uint32("action", ps, 1, &u32_tmp)) goto fail; + + u32_tmp = namelen; + if (!prs_uint32("namelen", ps, 1, &u32_tmp)) goto fail; + + if (!prs_unistr("name", ps, 1, &uni_name)) goto fail; + + /* + * Not NULL terminated, decrease by the 2 UCS2 \0 chars + */ + prs_set_offset(ps, prs_offset(ps)-2); + + SAFE_FREE(uni_name.buffer); + } + + return True; + + fail: + SAFE_FREE(uni_name.buffer); + return False; +} + /**************************************************************************** Setup the common parts of the return packet and send it. *****************************************************************************/ -static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) +void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) { char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(inbuf, outbuf); + construct_reply_common(request_buf, outbuf); ERROR_NT(error_code); @@ -65,6 +118,45 @@ static void change_notify_reply_packet(char *inbuf, NTSTATUS error_code) exit_server_cleanly("change_notify_reply_packet: send_smb failed."); } +void change_notify_reply(const char *request_buf, uint32 max_param_count, + unsigned num_changes, struct notify_change *changes) +{ + char *outbuf = NULL; + prs_struct ps; + size_t buflen = smb_size+38+max_param_count; + + if (!prs_init(&ps, 0, NULL, False) + || !notify_marshall_changes(num_changes, changes, &ps)) { + change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); + goto done; + } + + if (prs_offset(&ps) > max_param_count) { + /* + * We exceed what the client is willing to accept. Send + * nothing. + */ + change_notify_reply_packet(request_buf, NT_STATUS_OK); + goto done; + } + + if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { + change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); + goto done; + } + + construct_reply_common(request_buf, outbuf); + + if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), + prs_offset(&ps), NULL, 0) == -1) { + exit_server("change_notify_reply_packet: send_smb failed."); + } + + done: + SAFE_FREE(outbuf); + prs_mem_free(&ps); +} + /**************************************************************************** Remove an entry from the list and free it, also closing any directory handle if necessary. @@ -78,38 +170,104 @@ static void change_notify_remove(struct change_notify *cnbp) SAFE_FREE(cnbp); } -/**************************************************************************** - Delete entries by fnum from the change notify pending queue. -*****************************************************************************/ +NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, + uint32 filter, struct files_struct *fsp) +{ + struct notify_change_request *request = NULL; + struct notify_mid_map *map = NULL; + + if (!(request = SMB_MALLOC_P(struct notify_change_request)) + || !(map = SMB_MALLOC_P(struct notify_mid_map))) { + SAFE_FREE(request); + return NT_STATUS_NO_MEMORY; + } + + request->mid_map = map; + map->req = request; + + memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); + request->max_param_count = max_param_count; + request->filter = filter; + request->fsp = fsp; + DLIST_ADD_END(fsp->notify->requests, request, + struct notify_change_request *); + + map->mid = SVAL(inbuf, smb_mid); + DLIST_ADD(notify_changes_by_mid, map); -void remove_pending_change_notify_requests_by_fid(files_struct *fsp, NTSTATUS status) + /* Push the MID of this packet on the signing queue. */ + srv_defer_sign_response(SVAL(inbuf,smb_mid)); + + return NT_STATUS_OK; +} + +static void change_notify_remove_request(struct notify_change_request *remove_req) { - struct change_notify *cnbp, *next; + files_struct *fsp; + struct notify_change_request *req; - for (cnbp=change_notify_list; cnbp; cnbp=next) { - next=cnbp->next; - if (cnbp->fsp->fnum == fsp->fnum) { - change_notify_reply_packet(cnbp->request_buf,status); - change_notify_remove(cnbp); + /* + * Paranoia checks, the fsp referenced must must have the request in + * its list of pending requests + */ + + fsp = remove_req->fsp; + SMB_ASSERT(fsp->notify != NULL); + + for (req = fsp->notify->requests; req; req = req->next) { + if (req == remove_req) { + break; } } + + if (req == NULL) { + smb_panic("notify_req not found in fsp's requests\n"); + } + + DLIST_REMOVE(fsp->notify->requests, req); + DLIST_REMOVE(notify_changes_by_mid, req->mid_map); + SAFE_FREE(req->mid_map); + SAFE_FREE(req); } /**************************************************************************** Delete entries by mid from the change notify pending queue. Always send reply. *****************************************************************************/ -void remove_pending_change_notify_requests_by_mid(int mid) +void remove_pending_change_notify_requests_by_mid(uint16 mid) { - struct change_notify *cnbp, *next; + struct notify_mid_map *map; - for (cnbp=change_notify_list; cnbp; cnbp=next) { - next=cnbp->next; - if(SVAL(cnbp->request_buf,smb_mid) == mid) { - change_notify_reply_packet(cnbp->request_buf,NT_STATUS_CANCELLED); - change_notify_remove(cnbp); + for (map = notify_changes_by_mid; map; map = map->next) { + if (map->mid == mid) { + break; } } + + if (map == NULL) { + return; + } + + change_notify_reply_packet(map->req->request_buf, NT_STATUS_CANCELLED); + change_notify_remove_request(map->req); +} + +/**************************************************************************** + Delete entries by fnum from the change notify pending queue. +*****************************************************************************/ + +void remove_pending_change_notify_requests_by_fid(files_struct *fsp, + NTSTATUS status) +{ + if (fsp->notify == NULL) { + return; + } + + while (fsp->notify->requests != NULL) { + change_notify_reply_packet( + fsp->notify->requests->request_buf, status); + change_notify_remove_request(fsp->notify->requests); + } } /**************************************************************************** @@ -128,7 +286,7 @@ void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTAT * the filename are identical. */ if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp->request_buf,status); + change_notify_reply_packet(cnbp->request_buf, status); change_notify_remove(cnbp); } } @@ -171,9 +329,27 @@ BOOL process_pending_change_notify_queue(time_t t) vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); - if (cnotify->check_notify(cnbp->conn, vuid, cnbp->fsp->fsp_name, cnbp->flags, cnbp->change_data, t)) { - DEBUG(10,("process_pending_change_notify_queue: dir %s changed !\n", cnbp->fsp->fsp_name )); - change_notify_reply_packet(cnbp->request_buf,STATUS_NOTIFY_ENUM_DIR); + if (cnbp->fsp->notify->num_changes != 0) { + DEBUG(10,("process_pending_change_notify_queue: %s " + "has %d changes!\n", cnbp->fsp->fsp_name, + cnbp->fsp->notify->num_changes)); + change_notify_reply(cnbp->request_buf, + cnbp->max_param_count, + cnbp->fsp->notify->num_changes, + cnbp->fsp->notify->changes); + change_notify_remove(cnbp); + continue; + } + + if (cnotify->check_notify(cnbp->fsp->conn, vuid, + cnbp->fsp->fsp_name, cnbp->flags, + cnbp->change_data, t)) { + DEBUG(10,("process_pending_change_notify_queue: dir " + "%s changed !\n", cnbp->fsp->fsp_name )); + change_notify_reply(cnbp->request_buf, + cnbp->max_param_count, + cnbp->fsp->notify->num_changes, + cnbp->fsp->notify->changes); change_notify_remove(cnbp); } } @@ -188,22 +364,24 @@ BOOL process_pending_change_notify_queue(time_t t) error. ****************************************************************************/ -BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, uint32 flags) +BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, + uint32 flags, uint32 max_param_count) { struct change_notify *cnbp; if((cnbp = SMB_MALLOC_P(struct change_notify)) == NULL) { DEBUG(0,("change_notify_set: malloc fail !\n" )); - return -1; + return False; } ZERO_STRUCTP(cnbp); memcpy(cnbp->request_buf, inbuf, smb_size); cnbp->fsp = fsp; - cnbp->conn = conn; cnbp->flags = flags; - cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, flags); + cnbp->max_param_count = max_param_count; + cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, + flags); if (!cnbp->change_data) { SAFE_FREE(cnbp); @@ -227,6 +405,237 @@ int change_notify_fd(void) return -1; } +/* notify message definition + +Offset Data length. +0 SMB_DEV_T dev 8 +8 SMB_INO_T inode 8 +16 uint32 filter 4 +20 uint32 action 4 +24.. name +*/ + +#define MSG_NOTIFY_MESSAGE_SIZE 25 /* Includes at least the '\0' terminator */ + +struct notify_message { + SMB_DEV_T dev; + SMB_INO_T inode; + uint32 filter; + uint32 action; + char *name; +}; + +static DATA_BLOB notify_message_to_buf(const struct notify_message *msg) +{ + DATA_BLOB result; + size_t len; + + len = strlen(msg->name); + + result = data_blob(NULL, MSG_NOTIFY_MESSAGE_SIZE + len); + if (!result.data) { + return result; + } + + SDEV_T_VAL(result.data, 0, msg->dev); + SINO_T_VAL(result.data, 8, msg->inode); + SIVAL(result.data, 16, msg->filter); + SIVAL(result.data, 20, msg->action); + memcpy(result.data+24, msg->name, len+1); + + return result; +} + +static BOOL buf_to_notify_message(void *buf, size_t len, + struct notify_message *msg) +{ + if (len < MSG_NOTIFY_MESSAGE_SIZE) { + DEBUG(0, ("Got invalid notify message of len %d\n", + (int)len)); + return False; + } + + msg->dev = DEV_T_VAL(buf, 0); + msg->inode = INO_T_VAL(buf, 8); + msg->filter = IVAL(buf, 16); + msg->action = IVAL(buf, 20); + msg->name = ((char *)buf)+24; + return True; +} + +void notify_action(connection_struct *conn, const char *parent, + const char *name, uint32 filter, uint32_t action) +{ + struct share_mode_lock *lck; + SMB_STRUCT_STAT sbuf; + int i; + struct notify_message msg; + DATA_BLOB blob; + + struct process_id *pids; + int num_pids; + + DEBUG(10, ("notify_action: parent=%s, name=%s, action=%u\n", + parent, name, (unsigned)action)); + + if (SMB_VFS_STAT(conn, parent, &sbuf) != 0) { + /* + * Not 100% critical, ignore failure + */ + return; + } + + if (!(lck = get_share_mode_lock(NULL, sbuf.st_dev, sbuf.st_ino, + NULL, NULL))) { + return; + } + + msg.dev = sbuf.st_dev; + msg.inode = sbuf.st_ino; + msg.filter = filter; + msg.action = action; + msg.name = CONST_DISCARD(char *, name); + + blob = notify_message_to_buf(&msg); + if (blob.data == NULL) { + DEBUG(0, ("notify_message_to_buf failed\n")); + return; + } + + pids = NULL; + num_pids = 0; + + become_root_uid_only(); + + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + int j; + struct process_id *tmp; + + for (j=0; jpid, &pids[j])) { + break; + } + } + + if (j < num_pids) { + /* + * Already sent to that process, skip it + */ + continue; + } + + message_send_pid(lck->share_modes[i].pid, MSG_SMB_NOTIFY, + blob.data, blob.length, True); + + if (!(tmp = TALLOC_REALLOC_ARRAY(lck, pids, struct process_id, + num_pids+1))) { + DEBUG(0, ("realloc failed\n")); + break; + } + pids = tmp; + pids[num_pids] = e->pid; + num_pids += 1; + } + + unbecome_root_uid_only(); + + data_blob_free(&blob); + TALLOC_FREE(lck); +} + +void notify_fname(connection_struct *conn, const char *path, + uint32 filter, uint32 action) +{ + char *parent; + const char *name; + + if (!parent_dirname_talloc(tmp_talloc_ctx(), path, &parent, &name)) { + return; + } + + notify_action(conn, parent, name, filter, action); + TALLOC_FREE(parent); +} + +static void notify_fsp(files_struct *fsp, struct notify_message *msg) +{ + struct notify_change *change, *changes; + + if (fsp->notify == NULL) { + /* + * Nobody is waiting, don't queue + */ + return; + } + + if ((fsp->notify->requests != NULL) + && (fsp->notify->requests->filter & msg->filter)) { + /* + * Someone is waiting for the change, trigger the reply + * immediately. + * + * TODO: do we have to walk the lists of requests pending? + */ + + struct notify_change_request *req = fsp->notify->requests; + struct notify_change onechange; + + onechange.action = msg->action; + onechange.name = msg->name; + + change_notify_reply(req->request_buf, req->max_param_count, + 1, &onechange); + change_notify_remove_request(req); + return; + } + + /* + * Someone has triggered a notify previously, queue the change for + * later. TODO: Limit the number of changes queued, test how filters + * apply here. Do we have to store them? + */ + + if (!(changes = TALLOC_REALLOC_ARRAY( + fsp->notify, fsp->notify->changes, + struct notify_change, fsp->notify->num_changes+1))) { + DEBUG(0, ("talloc_realloc failed\n")); + return; + } + + fsp->notify->changes = changes; + + change = &(fsp->notify->changes[fsp->notify->num_changes]); + + if (!(change->name = talloc_strdup(changes, msg->name))) { + DEBUG(0, ("talloc_strdup failed\n")); + return; + } + change->action = msg->action; + fsp->notify->num_changes += 1; + + return; +} + +static void notify_message_callback(int msgtype, struct process_id pid, + void *buf, size_t len) +{ + struct notify_message msg; + files_struct *fsp; + + if (!buf_to_notify_message(buf, len, &msg)) { + return; + } + + DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n", + (unsigned)msg.dev, (double)msg.inode, msg.action)); + + for(fsp = fsp_find_di_first(msg.dev, msg.inode); fsp; + fsp = fsp_find_di_next(fsp)) { + notify_fsp(fsp, &msg); + } +} + /**************************************************************************** Initialise the change notify subsystem. ****************************************************************************/ @@ -250,5 +659,7 @@ BOOL init_change_notify(void) return False; } + message_register(MSG_SMB_NOTIFY, notify_message_callback); + return True; } -- cgit From 90f59d441223ba9b32b0d788901c9de5cf4b3bc7 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 17 Jan 2007 18:23:37 +0000 Subject: r20856: Make "struct notify_mid_map" private to notify.c (This used to be commit beecef0c70521d28dd88552d661281d9c585eb22) --- source3/smbd/notify.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 6bedb17261..3b01c2c786 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -40,6 +40,17 @@ struct change_notify { void *change_data; }; +/* + * For NTCancel, we need to find the notify_change_request indexed by + * mid. Separate list here. + */ + +struct notify_mid_map { + struct notify_mid_map *prev, *next; + struct notify_change_request *req; + uint16 mid; +}; + static struct change_notify *change_notify_list; static BOOL notify_marshall_changes(unsigned num_changes, -- cgit From ab41ff67f1308389a130c3a4ff804545d8998dd1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 17 Jan 2007 18:26:37 +0000 Subject: r20858: change_notify_reply_packet is static (This used to be commit a1d0644d156c360d52fb837d3eecddb202135ebe) --- source3/smbd/notify.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 3b01c2c786..2c762bd759 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -109,7 +109,8 @@ static BOOL notify_marshall_changes(unsigned num_changes, Setup the common parts of the return packet and send it. *****************************************************************************/ -void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) +static void change_notify_reply_packet(const char *request_buf, + NTSTATUS error_code) { char outbuf[smb_size+38]; @@ -126,7 +127,8 @@ void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) - exit_server_cleanly("change_notify_reply_packet: send_smb failed."); + exit_server_cleanly("change_notify_reply_packet: send_smb " + "failed."); } void change_notify_reply(const char *request_buf, uint32 max_param_count, -- cgit From d5206610cd67f88e2cc7d5b2b434e320e81c29d5 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 21 Jan 2007 11:49:00 +0000 Subject: r20931: This changes the notify infrastructure from a polling-based to an event-driven based approach. The only remaining hook into the backend is now void *(*notify_add)(TALLOC_CTX *mem_ctx, struct event_context *event_ctx, files_struct *fsp, uint32 *filter); (Should we put this through the VFS, so that others can more easily plug in?) The trick here is that the backend can pick filter bits that the main smbd should not handle anymore. Thanks to tridge for this idea. The backend can notify the main smbd process via void notify_fsp(files_struct *fsp, uint32 action, char *name); The core patch is not big, what makes this more than 1800 lines are the individual backends that are considerably changed but can be reviewed one by one. Based on this I'll continue with inotify now. Volker (This used to be commit 9cd6a8a82792b7b6967141565d043b6337836a5d) --- source3/smbd/notify.c | 226 +++++++++++--------------------------------------- 1 file changed, 48 insertions(+), 178 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 2c762bd759..ce7680b49a 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -3,6 +3,7 @@ change notify handling Copyright (C) Andrew Tridgell 2000 Copyright (C) Jeremy Allison 1994-1998 + Copyright (C) Volker Lendecke 2007 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,22 +25,6 @@ static struct cnotify_fns *cnotify; static struct notify_mid_map *notify_changes_by_mid; -/**************************************************************************** - This is the structure to queue to implement NT change - notify. It consists of smb_size bytes stored from the - transact command (to keep the mid, tid etc around). - Plus the fid to examine and notify private data. -*****************************************************************************/ - -struct change_notify { - struct change_notify *next, *prev; - files_struct *fsp; - uint32 flags; - uint32 max_param_count; - char request_buf[smb_size]; - void *change_data; -}; - /* * For NTCancel, we need to find the notify_change_request indexed by * mid. Separate list here. @@ -51,9 +36,7 @@ struct notify_mid_map { uint16 mid; }; -static struct change_notify *change_notify_list; - -static BOOL notify_marshall_changes(unsigned num_changes, +static BOOL notify_marshall_changes(int num_changes, struct notify_change *changes, prs_struct *ps) { @@ -132,12 +115,17 @@ static void change_notify_reply_packet(const char *request_buf, } void change_notify_reply(const char *request_buf, uint32 max_param_count, - unsigned num_changes, struct notify_change *changes) + int num_changes, struct notify_change *changes) { char *outbuf = NULL; prs_struct ps; size_t buflen = smb_size+38+max_param_count; + if (num_changes == -1) { + change_notify_reply_packet(request_buf, NT_STATUS_OK); + return; + } + if (!prs_init(&ps, 0, NULL, False) || !notify_marshall_changes(num_changes, changes, &ps)) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); @@ -170,19 +158,6 @@ void change_notify_reply(const char *request_buf, uint32 max_param_count, prs_mem_free(&ps); } -/**************************************************************************** - Remove an entry from the list and free it, also closing any - directory handle if necessary. -*****************************************************************************/ - -static void change_notify_remove(struct change_notify *cnbp) -{ - cnotify->remove_notify(cnbp->change_data); - DLIST_REMOVE(change_notify_list, cnbp); - ZERO_STRUCTP(cnbp); - SAFE_FREE(cnbp); -} - NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, uint32 filter, struct files_struct *fsp) { @@ -202,6 +177,10 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, request->max_param_count = max_param_count; request->filter = filter; request->fsp = fsp; + + request->backend_data = cnotify->notify_add(NULL, smbd_event_context(), + fsp, &request->filter); + DLIST_ADD_END(fsp->notify->requests, request, struct notify_change_request *); @@ -240,6 +219,7 @@ static void change_notify_remove_request(struct notify_change_request *remove_re DLIST_REMOVE(fsp->notify->requests, req); DLIST_REMOVE(notify_changes_by_mid, req->mid_map); SAFE_FREE(req->mid_map); + TALLOC_FREE(req->backend_data); SAFE_FREE(req); } @@ -283,141 +263,6 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp, } } -/**************************************************************************** - Delete entries by filename and cnum from the change notify pending queue. - Always send reply. -*****************************************************************************/ - -void remove_pending_change_notify_requests_by_filename(files_struct *fsp, NTSTATUS status) -{ - struct change_notify *cnbp, *next; - - for (cnbp=change_notify_list; cnbp; cnbp=next) { - next=cnbp->next; - /* - * We know it refers to the same directory if the connection number and - * the filename are identical. - */ - if((cnbp->fsp->conn == fsp->conn) && strequal(cnbp->fsp->fsp_name,fsp->fsp_name)) { - change_notify_reply_packet(cnbp->request_buf, status); - change_notify_remove(cnbp); - } - } -} - -/**************************************************************************** - Set the current change notify timeout to the lowest value across all service - values. -****************************************************************************/ - -void set_change_notify_timeout(int val) -{ - if (val > 0) { - cnotify->select_time = MIN(cnotify->select_time, val); - } -} - -/**************************************************************************** - Longest time to sleep for before doing a change notify scan. -****************************************************************************/ - -int change_notify_timeout(void) -{ - return cnotify->select_time; -} - -/**************************************************************************** - Process the change notify queue. Note that this is only called as root. - Returns True if there are still outstanding change notify requests on the - queue. -*****************************************************************************/ - -BOOL process_pending_change_notify_queue(time_t t) -{ - struct change_notify *cnbp, *next; - uint16 vuid; - - for (cnbp=change_notify_list; cnbp; cnbp=next) { - next=cnbp->next; - - vuid = (lp_security() == SEC_SHARE) ? UID_FIELD_INVALID : SVAL(cnbp->request_buf,smb_uid); - - if (cnbp->fsp->notify->num_changes != 0) { - DEBUG(10,("process_pending_change_notify_queue: %s " - "has %d changes!\n", cnbp->fsp->fsp_name, - cnbp->fsp->notify->num_changes)); - change_notify_reply(cnbp->request_buf, - cnbp->max_param_count, - cnbp->fsp->notify->num_changes, - cnbp->fsp->notify->changes); - change_notify_remove(cnbp); - continue; - } - - if (cnotify->check_notify(cnbp->fsp->conn, vuid, - cnbp->fsp->fsp_name, cnbp->flags, - cnbp->change_data, t)) { - DEBUG(10,("process_pending_change_notify_queue: dir " - "%s changed !\n", cnbp->fsp->fsp_name )); - change_notify_reply(cnbp->request_buf, - cnbp->max_param_count, - cnbp->fsp->notify->num_changes, - cnbp->fsp->notify->changes); - change_notify_remove(cnbp); - } - } - - return (change_notify_list != NULL); -} - -/**************************************************************************** - Now queue an entry on the notify change list. - We only need to save smb_size bytes from this incoming packet - as we will always by returning a 'read the directory yourself' - error. -****************************************************************************/ - -BOOL change_notify_set(char *inbuf, files_struct *fsp, connection_struct *conn, - uint32 flags, uint32 max_param_count) -{ - struct change_notify *cnbp; - - if((cnbp = SMB_MALLOC_P(struct change_notify)) == NULL) { - DEBUG(0,("change_notify_set: malloc fail !\n" )); - return False; - } - - ZERO_STRUCTP(cnbp); - - memcpy(cnbp->request_buf, inbuf, smb_size); - cnbp->fsp = fsp; - cnbp->flags = flags; - cnbp->max_param_count = max_param_count; - cnbp->change_data = cnotify->register_notify(conn, fsp->fsp_name, - flags); - - if (!cnbp->change_data) { - SAFE_FREE(cnbp); - return False; - } - - DLIST_ADD(change_notify_list, cnbp); - - /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid)); - - return True; -} - -int change_notify_fd(void) -{ - if (cnotify) { - return cnotify->notification_fd; - } - - return -1; -} - /* notify message definition Offset Data length. @@ -571,7 +416,7 @@ void notify_fname(connection_struct *conn, const char *path, TALLOC_FREE(parent); } -static void notify_fsp(files_struct *fsp, struct notify_message *msg) +void notify_fsp(files_struct *fsp, uint32 action, char *name) { struct notify_change *change, *changes; @@ -582,8 +427,7 @@ static void notify_fsp(files_struct *fsp, struct notify_message *msg) return; } - if ((fsp->notify->requests != NULL) - && (fsp->notify->requests->filter & msg->filter)) { + if (fsp->notify->requests != NULL) { /* * Someone is waiting for the change, trigger the reply * immediately. @@ -594,8 +438,18 @@ static void notify_fsp(files_struct *fsp, struct notify_message *msg) struct notify_change_request *req = fsp->notify->requests; struct notify_change onechange; - onechange.action = msg->action; - onechange.name = msg->name; + if (name == NULL) { + /* + * Catch-all change, possibly from notify_hash.c + */ + change_notify_reply(req->request_buf, + req->max_param_count, + -1, NULL); + return; + } + + onechange.action = action; + onechange.name = name; change_notify_reply(req->request_buf, req->max_param_count, 1, &onechange); @@ -609,6 +463,19 @@ static void notify_fsp(files_struct *fsp, struct notify_message *msg) * apply here. Do we have to store them? */ + if ((fsp->notify->num_changes > 30) || (name == NULL)) { + /* + * W2k3 seems to store at most 30 changes. + */ + TALLOC_FREE(fsp->notify->changes); + fsp->notify->num_changes = -1; + return; + } + + if (fsp->notify->num_changes == -1) { + return; + } + if (!(changes = TALLOC_REALLOC_ARRAY( fsp->notify, fsp->notify->changes, struct notify_change, fsp->notify->num_changes+1))) { @@ -620,11 +487,11 @@ static void notify_fsp(files_struct *fsp, struct notify_message *msg) change = &(fsp->notify->changes[fsp->notify->num_changes]); - if (!(change->name = talloc_strdup(changes, msg->name))) { + if (!(change->name = talloc_strdup(changes, name))) { DEBUG(0, ("talloc_strdup failed\n")); return; } - change->action = msg->action; + change->action = action; fsp->notify->num_changes += 1; return; @@ -645,7 +512,10 @@ static void notify_message_callback(int msgtype, struct process_id pid, for(fsp = fsp_find_di_first(msg.dev, msg.inode); fsp; fsp = fsp_find_di_next(fsp)) { - notify_fsp(fsp, &msg); + if ((fsp->notify->requests != NULL) + && (fsp->notify->requests->filter & msg.filter)) { + notify_fsp(fsp, msg.action, msg.name); + } } } @@ -659,11 +529,11 @@ BOOL init_change_notify(void) #if HAVE_KERNEL_CHANGE_NOTIFY if (cnotify == NULL && lp_kernel_change_notify()) - cnotify = kernel_notify_init(); + cnotify = kernel_notify_init(smbd_event_context()); #endif #if HAVE_FAM_CHANGE_NOTIFY if (cnotify == NULL && lp_fam_change_notify()) - cnotify = fam_notify_init(); + cnotify = fam_notify_init(smbd_event_context()); #endif if (!cnotify) cnotify = hash_notify_init(); -- cgit From 420e577004cdb9e00d290d3681df3b3196336d81 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sun, 21 Jan 2007 16:05:49 +0000 Subject: r20932: This is the basic infrastructure for inotify support. This is far from being complete, in particular the various mask bits are not correctly supported yet. Checkin in now, I want to see how the build farm likes it. Volker (This used to be commit c9a5d011a91359b242f6c26f46e96ecea6a44a3b) --- source3/smbd/notify.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index ce7680b49a..2493dea9ef 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -527,6 +527,11 @@ BOOL init_change_notify(void) { cnotify = NULL; +#if HAVE_INOTIFY + if ((cnotify == NULL) && lp_kernel_change_notify()) { + cnotify = inotify_notify_init(smbd_event_context()); + } +#endif #if HAVE_KERNEL_CHANGE_NOTIFY if (cnotify == NULL && lp_kernel_change_notify()) cnotify = kernel_notify_init(smbd_event_context()); -- cgit From db8ee51cf26372eee5eed9bf177762fe090f720f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 23 Jan 2007 20:38:14 +0000 Subject: r20982: Fix a segfault -- I wonder why my make test did not show this earlier... (This used to be commit 4984b0627c84cc192868238c0936ca1a38628cd8) --- source3/smbd/notify.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 2493dea9ef..c2f4572e7e 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -512,7 +512,8 @@ static void notify_message_callback(int msgtype, struct process_id pid, for(fsp = fsp_find_di_first(msg.dev, msg.inode); fsp; fsp = fsp_find_di_next(fsp)) { - if ((fsp->notify->requests != NULL) + if ((fsp->notify != NULL) + && (fsp->notify->requests != NULL) && (fsp->notify->requests->filter & msg.filter)) { notify_fsp(fsp, msg.action, msg.name); } -- cgit From caf8c6a76be051559ffcfe97084edca43e0a3cee Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 30 Jan 2007 22:22:06 +0000 Subject: r21064: The core of this patch is void message_register(int msg_type, void (*fn)(int msg_type, struct process_id pid, - void *buf, size_t len)) + void *buf, size_t len, + void *private_data), + void *private_data) { struct dispatch_fns *dfn; So this adds a (so far unused) private pointer that is passed from message_register to the message handler. A prerequisite to implement a tiny samba4-API compatible wrapper around our messaging system. That itself is necessary for the Samba4 notify system. Yes, I know, I could import the whole Samba4 messaging system, but I want to do it step by step and I think getting notify in is more important in this step. Volker (This used to be commit c8ae60ed65dcce9660ee39c75488f2838cf9a28b) --- source3/smbd/notify.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index c2f4572e7e..d920633b0a 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -498,7 +498,8 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name) } static void notify_message_callback(int msgtype, struct process_id pid, - void *buf, size_t len) + void *buf, size_t len, + void *private_data) { struct notify_message msg; files_struct *fsp; @@ -548,7 +549,7 @@ BOOL init_change_notify(void) return False; } - message_register(MSG_SMB_NOTIFY, notify_message_callback); + message_register(MSG_SMB_NOTIFY, notify_message_callback, NULL); return True; } -- cgit From 9ee97d2f7d4e3c7e14d32825c5ee23b136ce4e07 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 12:24:59 +0000 Subject: r21077: A step to minimize the diff later: This pulls in unmodified files from Samba4, not compiled yet. This way the modifications become visible later. ntvfs/common/notify.c -> smbd/notify_internal.c ntvfs/sysdep/inotify.c -> smbd/notify_inotify.c Naturally I had to disable notify again :-) Volker (This used to be commit cdb7d582b7397faa5926bff5783da7fef4209948) --- source3/smbd/notify.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index d920633b0a..4c82b9fca8 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -529,11 +529,6 @@ BOOL init_change_notify(void) { cnotify = NULL; -#if HAVE_INOTIFY - if ((cnotify == NULL) && lp_kernel_change_notify()) { - cnotify = inotify_notify_init(smbd_event_context()); - } -#endif #if HAVE_KERNEL_CHANGE_NOTIFY if (cnotify == NULL && lp_kernel_change_notify()) cnotify = kernel_notify_init(smbd_event_context()); -- cgit From 113e21f0a57af49d61cfb0dd1afd38b4a8fd5128 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 13:47:37 +0000 Subject: r21084: Make the Samba4 files compile in Samba3, not activated yet. Volker (This used to be commit c24854433a28cc066072a7107e29aa7fe2bec3c8) --- source3/smbd/notify.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 4c82b9fca8..97192d6e63 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -548,3 +548,30 @@ BOOL init_change_notify(void) return True; } + +struct sys_notify_context *sys_notify_context_create(struct share_params *scfg, + TALLOC_CTX *mem_ctx, + struct event_context *ev) +{ + struct sys_notify_context *ctx; + + if (!(ctx = TALLOC_P(mem_ctx, struct sys_notify_context))) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + + ctx->ev = ev; + ctx->private_data = NULL; + return ctx; +} + +NTSTATUS sys_notify_watch(struct sys_notify_context *ctx, + struct notify_entry *e, + void (*callback)(struct sys_notify_context *ctx, + void *private_data, + struct notify_event *ev), + void *private_data, void *handle) +{ + return inotify_watch(ctx, e, callback, private_data, handle); +} + -- cgit From 547f77778abc45bf329dcb53182127d72596c812 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 14:14:57 +0000 Subject: r21087: Make the param list of notify_fname match notify_trigger (This used to be commit defa28f9c3eda85a072b972fffd2d5de8bcf01f7) --- source3/smbd/notify.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 97192d6e63..9cb121a039 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -402,8 +402,8 @@ void notify_action(connection_struct *conn, const char *parent, TALLOC_FREE(lck); } -void notify_fname(connection_struct *conn, const char *path, - uint32 filter, uint32 action) +void notify_fname(connection_struct *conn, uint32 action, uint32 filter, + const char *path) { char *parent; const char *name; -- cgit From 3af5838096872039ac201385763f1e4c0fafb034 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 14:28:08 +0000 Subject: r21090: Add some helper routines (This used to be commit 985dde8ed0a7e6da5adf9c55654a4fd362b22acb) --- source3/smbd/notify.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 9cb121a039..2907bd7e0f 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -521,6 +521,44 @@ static void notify_message_callback(int msgtype, struct process_id pid, } } +char *notify_filter_string(TALLOC_CTX *mem_ctx, uint32 filter) +{ + char *result = NULL; + + result = talloc_strdup(mem_ctx, ""); + + if (filter & FILE_NOTIFY_CHANGE_FILE_NAME) + result = talloc_asprintf_append(result, "FILE_NAME|"); + if (filter & FILE_NOTIFY_CHANGE_DIR_NAME) + result = talloc_asprintf_append(result, "DIR_NAME|"); + if (filter & FILE_NOTIFY_CHANGE_ATTRIBUTES) + result = talloc_asprintf_append(result, "ATTRIBUTES|"); + if (filter & FILE_NOTIFY_CHANGE_SIZE) + result = talloc_asprintf_append(result, "SIZE|"); + if (filter & FILE_NOTIFY_CHANGE_LAST_WRITE) + result = talloc_asprintf_append(result, "LAST_WRITE|"); + if (filter & FILE_NOTIFY_CHANGE_LAST_ACCESS) + result = talloc_asprintf_append(result, "LAST_ACCESS|"); + if (filter & FILE_NOTIFY_CHANGE_CREATION) + result = talloc_asprintf_append(result, "CREATION|"); + if (filter & FILE_NOTIFY_CHANGE_EA) + result = talloc_asprintf_append(result, "EA|"); + if (filter & FILE_NOTIFY_CHANGE_SECURITY) + result = talloc_asprintf_append(result, "SECURITY|"); + if (filter & FILE_NOTIFY_CHANGE_STREAM_NAME) + result = talloc_asprintf_append(result, "STREAM_NAME|"); + if (filter & FILE_NOTIFY_CHANGE_STREAM_SIZE) + result = talloc_asprintf_append(result, "STREAM_SIZE|"); + if (filter & FILE_NOTIFY_CHANGE_STREAM_WRITE) + result = talloc_asprintf_append(result, "STREAM_WRITE|"); + + if (result == NULL) return NULL; + if (*result == '\0') return result; + + result[strlen(result)-1] = '\0'; + return result; +} + /**************************************************************************** Initialise the change notify subsystem. ****************************************************************************/ -- cgit From accbfaa4c3ffe669cc29aac8a85c4144ad234e43 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 14:36:50 +0000 Subject: r21091: Fix the build without inotify (This used to be commit 686345b7ed727db7b1d9bc164208ecfb612837b6) --- source3/smbd/notify.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 2907bd7e0f..49219bcca5 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -610,6 +610,10 @@ NTSTATUS sys_notify_watch(struct sys_notify_context *ctx, struct notify_event *ev), void *private_data, void *handle) { +#ifdef HAVE_INOTIFY return inotify_watch(ctx, e, callback, private_data, handle); +#else + return NT_STATUS_OK; +#endif } -- cgit From 2852ecc67ebded7758a07d8fb72eef53bfa1c63a Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 14:42:56 +0000 Subject: r21092: Ok, that's the one that activates the Samba4 notify backend. Now to clean up / fix lots of stuff. Volker (This used to be commit 9e7443fa1417c01be903b15073825dc4def78d99) --- source3/smbd/notify.c | 97 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 40 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 49219bcca5..93a6357d0c 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -159,7 +159,8 @@ void change_notify_reply(const char *request_buf, uint32 max_param_count, } NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, - uint32 filter, struct files_struct *fsp) + uint32 filter, BOOL recursive, + struct files_struct *fsp) { struct notify_change_request *request = NULL; struct notify_mid_map *map = NULL; @@ -177,9 +178,7 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, request->max_param_count = max_param_count; request->filter = filter; request->fsp = fsp; - - request->backend_data = cnotify->notify_add(NULL, smbd_event_context(), - fsp, &request->filter); + request->backend_data = NULL; DLIST_ADD_END(fsp->notify->requests, request, struct notify_change_request *); @@ -343,6 +342,18 @@ void notify_action(connection_struct *conn, const char *parent, return; } + { + char *fullpath; + + if (asprintf(&fullpath, "%s/%s/%s", conn->connectpath, + parent, name) != -1) { + notify_trigger(conn->notify_ctx, action, filter, + fullpath); + SAFE_FREE(fullpath); + } + return; + } + if (!(lck = get_share_mode_lock(NULL, sbuf.st_dev, sbuf.st_ino, NULL, NULL))) { return; @@ -405,20 +416,21 @@ void notify_action(connection_struct *conn, const char *parent, void notify_fname(connection_struct *conn, uint32 action, uint32 filter, const char *path) { - char *parent; - const char *name; + char *fullpath; - if (!parent_dirname_talloc(tmp_talloc_ctx(), path, &parent, &name)) { + if (asprintf(&fullpath, "%s/%s", conn->connectpath, path) == -1) { + DEBUG(0, ("asprintf failed\n")); return; } - notify_action(conn, parent, name, filter, action); - TALLOC_FREE(parent); + notify_trigger(conn->notify_ctx, action, filter, fullpath); + SAFE_FREE(fullpath); } -void notify_fsp(files_struct *fsp, uint32 action, char *name) +void notify_fsp(files_struct *fsp, uint32 action, const char *name) { struct notify_change *change, *changes; + char *name2; if (fsp->notify == NULL) { /* @@ -427,35 +439,12 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name) return; } - if (fsp->notify->requests != NULL) { - /* - * Someone is waiting for the change, trigger the reply - * immediately. - * - * TODO: do we have to walk the lists of requests pending? - */ - - struct notify_change_request *req = fsp->notify->requests; - struct notify_change onechange; - - if (name == NULL) { - /* - * Catch-all change, possibly from notify_hash.c - */ - change_notify_reply(req->request_buf, - req->max_param_count, - -1, NULL); + if (!(name2 = talloc_strdup(fsp->notify, name))) { + DEBUG(0, ("talloc_strdup failed\n")); return; } - onechange.action = action; - onechange.name = name; - - change_notify_reply(req->request_buf, req->max_param_count, - 1, &onechange); - change_notify_remove_request(req); - return; - } + string_replace(name2, '/', '\\'); /* * Someone has triggered a notify previously, queue the change for @@ -468,6 +457,7 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name) * W2k3 seems to store at most 30 changes. */ TALLOC_FREE(fsp->notify->changes); + TALLOC_FREE(name2); fsp->notify->num_changes = -1; return; } @@ -480,6 +470,7 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name) fsp->notify, fsp->notify->changes, struct notify_change, fsp->notify->num_changes+1))) { DEBUG(0, ("talloc_realloc failed\n")); + TALLOC_FREE(name2); return; } @@ -487,14 +478,40 @@ void notify_fsp(files_struct *fsp, uint32 action, char *name) change = &(fsp->notify->changes[fsp->notify->num_changes]); - if (!(change->name = talloc_strdup(changes, name))) { - DEBUG(0, ("talloc_strdup failed\n")); - return; - } + change->name = talloc_move(changes, &name2); change->action = action; fsp->notify->num_changes += 1; + if (fsp->notify->requests == NULL) { + /* + * Nobody is waiting, so don't send anything. The ot + */ + return; + } + + if (action == NOTIFY_ACTION_OLD_NAME) { + /* + * We have to send the two rename events in one reply. So hold + * the first part back. + */ return; + } + + /* + * Someone is waiting for the change, trigger the reply immediately. + * + * TODO: do we have to walk the lists of requests pending? + */ + + change_notify_reply(fsp->notify->requests->request_buf, + fsp->notify->requests->max_param_count, + fsp->notify->num_changes, + fsp->notify->changes); + + change_notify_remove_request(fsp->notify->requests); + + TALLOC_FREE(fsp->notify->changes); + fsp->notify->num_changes = 0; } static void notify_message_callback(int msgtype, struct process_id pid, -- cgit From 9974656d3be3fb01af59bfefe592475e92bdceb0 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Wed, 31 Jan 2007 16:56:27 +0000 Subject: r21093: Remove the hash and dnotify backends. Disabling FAM for this checkin, I'm working on that right now. Volker (This used to be commit 01c9fb17281e99300b339d2cfc0acac7ca94843c) --- source3/smbd/notify.c | 204 -------------------------------------------------- 1 file changed, 204 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 93a6357d0c..5c1143a28e 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -22,7 +22,6 @@ #include "includes.h" -static struct cnotify_fns *cnotify; static struct notify_mid_map *notify_changes_by_mid; /* @@ -262,157 +261,6 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp, } } -/* notify message definition - -Offset Data length. -0 SMB_DEV_T dev 8 -8 SMB_INO_T inode 8 -16 uint32 filter 4 -20 uint32 action 4 -24.. name -*/ - -#define MSG_NOTIFY_MESSAGE_SIZE 25 /* Includes at least the '\0' terminator */ - -struct notify_message { - SMB_DEV_T dev; - SMB_INO_T inode; - uint32 filter; - uint32 action; - char *name; -}; - -static DATA_BLOB notify_message_to_buf(const struct notify_message *msg) -{ - DATA_BLOB result; - size_t len; - - len = strlen(msg->name); - - result = data_blob(NULL, MSG_NOTIFY_MESSAGE_SIZE + len); - if (!result.data) { - return result; - } - - SDEV_T_VAL(result.data, 0, msg->dev); - SINO_T_VAL(result.data, 8, msg->inode); - SIVAL(result.data, 16, msg->filter); - SIVAL(result.data, 20, msg->action); - memcpy(result.data+24, msg->name, len+1); - - return result; -} - -static BOOL buf_to_notify_message(void *buf, size_t len, - struct notify_message *msg) -{ - if (len < MSG_NOTIFY_MESSAGE_SIZE) { - DEBUG(0, ("Got invalid notify message of len %d\n", - (int)len)); - return False; - } - - msg->dev = DEV_T_VAL(buf, 0); - msg->inode = INO_T_VAL(buf, 8); - msg->filter = IVAL(buf, 16); - msg->action = IVAL(buf, 20); - msg->name = ((char *)buf)+24; - return True; -} - -void notify_action(connection_struct *conn, const char *parent, - const char *name, uint32 filter, uint32_t action) -{ - struct share_mode_lock *lck; - SMB_STRUCT_STAT sbuf; - int i; - struct notify_message msg; - DATA_BLOB blob; - - struct process_id *pids; - int num_pids; - - DEBUG(10, ("notify_action: parent=%s, name=%s, action=%u\n", - parent, name, (unsigned)action)); - - if (SMB_VFS_STAT(conn, parent, &sbuf) != 0) { - /* - * Not 100% critical, ignore failure - */ - return; - } - - { - char *fullpath; - - if (asprintf(&fullpath, "%s/%s/%s", conn->connectpath, - parent, name) != -1) { - notify_trigger(conn->notify_ctx, action, filter, - fullpath); - SAFE_FREE(fullpath); - } - return; - } - - if (!(lck = get_share_mode_lock(NULL, sbuf.st_dev, sbuf.st_ino, - NULL, NULL))) { - return; - } - - msg.dev = sbuf.st_dev; - msg.inode = sbuf.st_ino; - msg.filter = filter; - msg.action = action; - msg.name = CONST_DISCARD(char *, name); - - blob = notify_message_to_buf(&msg); - if (blob.data == NULL) { - DEBUG(0, ("notify_message_to_buf failed\n")); - return; - } - - pids = NULL; - num_pids = 0; - - become_root_uid_only(); - - for (i=0; inum_share_modes; i++) { - struct share_mode_entry *e = &lck->share_modes[i]; - int j; - struct process_id *tmp; - - for (j=0; jpid, &pids[j])) { - break; - } - } - - if (j < num_pids) { - /* - * Already sent to that process, skip it - */ - continue; - } - - message_send_pid(lck->share_modes[i].pid, MSG_SMB_NOTIFY, - blob.data, blob.length, True); - - if (!(tmp = TALLOC_REALLOC_ARRAY(lck, pids, struct process_id, - num_pids+1))) { - DEBUG(0, ("realloc failed\n")); - break; - } - pids = tmp; - pids[num_pids] = e->pid; - num_pids += 1; - } - - unbecome_root_uid_only(); - - data_blob_free(&blob); - TALLOC_FREE(lck); -} - void notify_fname(connection_struct *conn, uint32 action, uint32 filter, const char *path) { @@ -514,30 +362,6 @@ void notify_fsp(files_struct *fsp, uint32 action, const char *name) fsp->notify->num_changes = 0; } -static void notify_message_callback(int msgtype, struct process_id pid, - void *buf, size_t len, - void *private_data) -{ - struct notify_message msg; - files_struct *fsp; - - if (!buf_to_notify_message(buf, len, &msg)) { - return; - } - - DEBUG(10, ("Received notify_message for 0x%x/%.0f: %d\n", - (unsigned)msg.dev, (double)msg.inode, msg.action)); - - for(fsp = fsp_find_di_first(msg.dev, msg.inode); fsp; - fsp = fsp_find_di_next(fsp)) { - if ((fsp->notify != NULL) - && (fsp->notify->requests != NULL) - && (fsp->notify->requests->filter & msg.filter)) { - notify_fsp(fsp, msg.action, msg.name); - } - } -} - char *notify_filter_string(TALLOC_CTX *mem_ctx, uint32 filter) { char *result = NULL; @@ -576,34 +400,6 @@ char *notify_filter_string(TALLOC_CTX *mem_ctx, uint32 filter) return result; } -/**************************************************************************** - Initialise the change notify subsystem. -****************************************************************************/ - -BOOL init_change_notify(void) -{ - cnotify = NULL; - -#if HAVE_KERNEL_CHANGE_NOTIFY - if (cnotify == NULL && lp_kernel_change_notify()) - cnotify = kernel_notify_init(smbd_event_context()); -#endif -#if HAVE_FAM_CHANGE_NOTIFY - if (cnotify == NULL && lp_fam_change_notify()) - cnotify = fam_notify_init(smbd_event_context()); -#endif - if (!cnotify) cnotify = hash_notify_init(); - - if (!cnotify) { - DEBUG(0,("Failed to init change notify system\n")); - return False; - } - - message_register(MSG_SMB_NOTIFY, notify_message_callback, NULL); - - return True; -} - struct sys_notify_context *sys_notify_context_create(struct share_params *scfg, TALLOC_CTX *mem_ctx, struct event_context *ev) -- cgit From 240a3fd644bbc94e5872f699c9b90649b52b98a1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 1 Feb 2007 13:36:02 +0000 Subject: r21108: Send sys_notify_watch through the VFS, FAM is next (This used to be commit 603a96761391f36ae9a1c8777d3333ab5c02eb34) --- source3/smbd/notify.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 5c1143a28e..8719c83bba 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -400,7 +400,7 @@ char *notify_filter_string(TALLOC_CTX *mem_ctx, uint32 filter) return result; } -struct sys_notify_context *sys_notify_context_create(struct share_params *scfg, +struct sys_notify_context *sys_notify_context_create(connection_struct *conn, TALLOC_CTX *mem_ctx, struct event_context *ev) { @@ -412,6 +412,7 @@ struct sys_notify_context *sys_notify_context_create(struct share_params *scfg, } ctx->ev = ev; + ctx->conn = conn; ctx->private_data = NULL; return ctx; } @@ -423,10 +424,7 @@ NTSTATUS sys_notify_watch(struct sys_notify_context *ctx, struct notify_event *ev), void *private_data, void *handle) { -#ifdef HAVE_INOTIFY - return inotify_watch(ctx, e, callback, private_data, handle); -#else - return NT_STATUS_OK; -#endif + return SMB_VFS_NOTIFY_WATCH(ctx->conn, ctx, e, callback, private_data, + handle); } -- cgit From 0d0e322d4d1fb1a9b1b5fb7825af093b48306826 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 2 Feb 2007 14:55:21 +0000 Subject: r21123: Make notify_fsp() static to notify.c. Volker (This used to be commit d663b729c0b3f4265fa90a5df8534ad52b8f04eb) --- source3/smbd/notify.c | 82 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 68 insertions(+), 14 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 8719c83bba..cf60720bc7 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -22,6 +22,19 @@ #include "includes.h" +struct notify_change_request { + struct notify_change_request *prev, *next; + struct files_struct *fsp; /* backpointer for cancel by mid */ + char request_buf[smb_size]; + uint32 filter; + uint32 max_param_count; + uint32 current_bufsize; + struct notify_mid_map *mid_map; + void *backend_data; +}; + +static void notify_fsp(files_struct *fsp, uint32 action, const char *name); + static struct notify_mid_map *notify_changes_by_mid; /* @@ -114,19 +127,20 @@ static void change_notify_reply_packet(const char *request_buf, } void change_notify_reply(const char *request_buf, uint32 max_param_count, - int num_changes, struct notify_change *changes) + struct notify_change_buf *notify_buf) { char *outbuf = NULL; prs_struct ps; size_t buflen = smb_size+38+max_param_count; - if (num_changes == -1) { + if (notify_buf->num_changes == -1) { change_notify_reply_packet(request_buf, NT_STATUS_OK); return; } if (!prs_init(&ps, 0, NULL, False) - || !notify_marshall_changes(num_changes, changes, &ps)) { + || !notify_marshall_changes(notify_buf->num_changes, + notify_buf->changes, &ps)) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; } @@ -155,6 +169,49 @@ void change_notify_reply(const char *request_buf, uint32 max_param_count, done: SAFE_FREE(outbuf); prs_mem_free(&ps); + + TALLOC_FREE(notify_buf->changes); + notify_buf->num_changes = 0; +} + +static void notify_callback(void *private_data, const struct notify_event *e) +{ + files_struct *fsp = (files_struct *)private_data; + DEBUG(10, ("notify_callback called for %s\n", fsp->fsp_name)); + notify_fsp(fsp, e->action, e->path); +} + +NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, + BOOL recursive) +{ + char *fullpath; + struct notify_entry e; + NTSTATUS status; + + SMB_ASSERT(fsp->notify == NULL); + + if (!(fsp->notify = TALLOC_ZERO_P(NULL, struct notify_change_buf))) { + DEBUG(0, ("talloc failed\n")); + return NT_STATUS_NO_MEMORY; + } + + if (asprintf(&fullpath, "%s/%s", fsp->conn->connectpath, + fsp->fsp_name) == -1) { + DEBUG(0, ("asprintf failed\n")); + return NT_STATUS_NO_MEMORY; + } + + e.path = fullpath; + e.filter = filter; + e.subdir_filter = 0; + if (recursive) { + e.subdir_filter = filter; + } + + status = notify_add(fsp->conn->notify_ctx, &e, notify_callback, fsp); + SAFE_FREE(fullpath); + + return status; } NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, @@ -175,6 +232,7 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); request->max_param_count = max_param_count; + request->current_bufsize = 0; request->filter = filter; request->fsp = fsp; request->backend_data = NULL; @@ -275,7 +333,7 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter, SAFE_FREE(fullpath); } -void notify_fsp(files_struct *fsp, uint32 action, const char *name) +static void notify_fsp(files_struct *fsp, uint32 action, const char *name) { struct notify_change *change, *changes; char *name2; @@ -290,19 +348,19 @@ void notify_fsp(files_struct *fsp, uint32 action, const char *name) if (!(name2 = talloc_strdup(fsp->notify, name))) { DEBUG(0, ("talloc_strdup failed\n")); return; - } + } string_replace(name2, '/', '\\'); /* * Someone has triggered a notify previously, queue the change for - * later. TODO: Limit the number of changes queued, test how filters - * apply here. Do we have to store them? + * later. */ - if ((fsp->notify->num_changes > 30) || (name == NULL)) { + if ((fsp->notify->num_changes > 1000) || (name == NULL)) { /* - * W2k3 seems to store at most 30 changes. + * The real number depends on the client buf, just provide a + * guard against a DoS here. */ TALLOC_FREE(fsp->notify->changes); TALLOC_FREE(name2); @@ -353,13 +411,9 @@ void notify_fsp(files_struct *fsp, uint32 action, const char *name) change_notify_reply(fsp->notify->requests->request_buf, fsp->notify->requests->max_param_count, - fsp->notify->num_changes, - fsp->notify->changes); + fsp->notify); change_notify_remove_request(fsp->notify->requests); - - TALLOC_FREE(fsp->notify->changes); - fsp->notify->num_changes = 0; } char *notify_filter_string(TALLOC_CTX *mem_ctx, uint32 filter) -- cgit From 0829e1ad1c3646efecf50729f493b9ee72ef0517 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 19 Apr 2007 22:40:32 +0000 Subject: r22391: Looks bigger than it is. Make "inbuf" available to all callers of smb_setlen (via set_message() calls). This will allow the server to reflect back the correct encryption context. Jeremy. (This used to be commit 2d80a96120a5fe2fe726f00746d36d85044c4bdb) --- source3/smbd/notify.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index cf60720bc7..d18bbb180f 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -107,6 +107,7 @@ static BOOL notify_marshall_changes(int num_changes, static void change_notify_reply_packet(const char *request_buf, NTSTATUS error_code) { + const char *inbuf = request_buf; char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); @@ -118,7 +119,7 @@ static void change_notify_reply_packet(const char *request_buf, * Seems NT needs a transact command with an error code * in it. This is a longer packet than a simple error. */ - set_message(outbuf,18,0,False); + set_message(inbuf,outbuf,18,0,False); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) @@ -161,7 +162,7 @@ void change_notify_reply(const char *request_buf, uint32 max_param_count, construct_reply_common(request_buf, outbuf); - if (send_nt_replies(outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), + if (send_nt_replies(request_buf, outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), prs_offset(&ps), NULL, 0) == -1) { exit_server("change_notify_reply_packet: send_smb failed."); } -- cgit From 87d18ac48853e1d63d127b03ea6dbc7568e334f4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Mon, 7 May 2007 20:53:10 +0000 Subject: r22755: Second half of r22754. As it stands now, string_replace expects a pstring. Give it one, although I hate putting it in :-) Thanks to Tom Bork! :-) (This used to be commit f4ea3fd36543120fa7d712e6e650c704e4e23759) --- source3/smbd/notify.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index d18bbb180f..b2ac26764a 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -337,7 +337,7 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter, static void notify_fsp(files_struct *fsp, uint32 action, const char *name) { struct notify_change *change, *changes; - char *name2; + pstring name2; if (fsp->notify == NULL) { /* @@ -346,11 +346,7 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) return; } - if (!(name2 = talloc_strdup(fsp->notify, name))) { - DEBUG(0, ("talloc_strdup failed\n")); - return; - } - + pstrcpy(name2, name); string_replace(name2, '/', '\\'); /* @@ -364,7 +360,6 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) * guard against a DoS here. */ TALLOC_FREE(fsp->notify->changes); - TALLOC_FREE(name2); fsp->notify->num_changes = -1; return; } @@ -377,7 +372,6 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) fsp->notify, fsp->notify->changes, struct notify_change, fsp->notify->num_changes+1))) { DEBUG(0, ("talloc_realloc failed\n")); - TALLOC_FREE(name2); return; } @@ -385,7 +379,11 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) change = &(fsp->notify->changes[fsp->notify->num_changes]); - change->name = talloc_move(changes, &name2); + if (!(change->name = talloc_strdup(changes, name2))) { + DEBUG(0, ("talloc_strdup failed\n")); + return; + } + change->action = action; fsp->notify->num_changes += 1; @@ -401,7 +399,7 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) * We have to send the two rename events in one reply. So hold * the first part back. */ - return; + return; } /* -- cgit From 28bc066aa843d97741b6507f4936516ff39b3d48 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 12 Jun 2007 19:59:38 +0000 Subject: r23450: max_params_return is complete fiction when getting a changenotify request. Ignore it. Should fix bug #4689 but more tests and valgrinding will follow. Jeremy. (This used to be commit c23e08cc09b8de860ab9c7ac9d0e7c2502dfccd9) --- source3/smbd/notify.c | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index b2ac26764a..5491f8eaf8 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -27,7 +27,6 @@ struct notify_change_request { struct files_struct *fsp; /* backpointer for cancel by mid */ char request_buf[smb_size]; uint32 filter; - uint32 max_param_count; uint32 current_bufsize; struct notify_mid_map *mid_map; void *backend_data; @@ -127,12 +126,12 @@ static void change_notify_reply_packet(const char *request_buf, "failed."); } -void change_notify_reply(const char *request_buf, uint32 max_param_count, +void change_notify_reply(const char *request_buf, struct notify_change_buf *notify_buf) { char *outbuf = NULL; prs_struct ps; - size_t buflen = smb_size+38+max_param_count; + size_t buflen; if (notify_buf->num_changes == -1) { change_notify_reply_packet(request_buf, NT_STATUS_OK); @@ -146,14 +145,7 @@ void change_notify_reply(const char *request_buf, uint32 max_param_count, goto done; } - if (prs_offset(&ps) > max_param_count) { - /* - * We exceed what the client is willing to accept. Send - * nothing. - */ - change_notify_reply_packet(request_buf, NT_STATUS_OK); - goto done; - } + buflen = smb_size+38+prs_offset(&ps) + 4 /* padding */; if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); @@ -215,7 +207,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, return status; } -NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, +NTSTATUS change_notify_add_request(const char *inbuf, uint32 filter, BOOL recursive, struct files_struct *fsp) { @@ -232,7 +224,6 @@ NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param_count, map->req = request; memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); - request->max_param_count = max_param_count; request->current_bufsize = 0; request->filter = filter; request->fsp = fsp; @@ -409,7 +400,6 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) */ change_notify_reply(fsp->notify->requests->request_buf, - fsp->notify->requests->max_param_count, fsp->notify); change_notify_remove_request(fsp->notify->requests); -- cgit From b1ce226af8b61ad7e3c37860a59c6715012e738b Mon Sep 17 00:00:00 2001 From: James Peach Date: Fri, 15 Jun 2007 21:58:49 +0000 Subject: r23510: Tidy calls to smb_panic by removing trailing newlines. Print the failed expression in SMB_ASSERT. (This used to be commit 171dc060e2a576d724eed1ca65636bdafffd7713) --- source3/smbd/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 5491f8eaf8..9074990be7 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -261,7 +261,7 @@ static void change_notify_remove_request(struct notify_change_request *remove_re } if (req == NULL) { - smb_panic("notify_req not found in fsp's requests\n"); + smb_panic("notify_req not found in fsp's requests"); } DLIST_REMOVE(fsp->notify->requests, req); -- cgit From 32ba5145b8c8385f56a1e8f025c7be1bc848077b Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 16 Jun 2007 11:48:11 +0000 Subject: r23518: Remove the silly assumption that string_replace requires a pstring. Jeremy, I am always very confused about the different length arguments in convert_string and friends. Can you take a look at the change in string_replace and verify it's ok? Thanks! While at it, remove the pstring limit for strhasupper and strhaslower. (This used to be commit e6e5703658aeaeb0cca5d7281095e17553001d4b) --- source3/smbd/notify.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 9074990be7..1b75916942 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -328,7 +328,7 @@ void notify_fname(connection_struct *conn, uint32 action, uint32 filter, static void notify_fsp(files_struct *fsp, uint32 action, const char *name) { struct notify_change *change, *changes; - pstring name2; + char *tmp; if (fsp->notify == NULL) { /* @@ -337,9 +337,6 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) return; } - pstrcpy(name2, name); - string_replace(name2, '/', '\\'); - /* * Someone has triggered a notify previously, queue the change for * later. @@ -370,11 +367,14 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) change = &(fsp->notify->changes[fsp->notify->num_changes]); - if (!(change->name = talloc_strdup(changes, name2))) { + if (!(tmp = talloc_strdup(changes, name))) { DEBUG(0, ("talloc_strdup failed\n")); return; } + string_replace(tmp, '/', '\\'); + change->name = tmp; + change->action = action; fsp->notify->num_changes += 1; -- cgit From 35d09869edf09b2af394a3eea1ee7b9ef1ba696b Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 5 Jul 2007 18:28:18 +0000 Subject: r23728: First part of bugfix for #4763. Limit notify responses to client max buf size. Jeremy. (This used to be commit 6113f56919a3cd7fd753808dbbe473603851bc3c) --- source3/smbd/notify.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 1b75916942..746a8f47e5 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -22,6 +22,9 @@ #include "includes.h" +/* Max size we can send to client in a notify response. */ +extern int max_send; + struct notify_change_request { struct notify_change_request *prev, *next; struct files_struct *fsp; /* backpointer for cancel by mid */ @@ -147,6 +150,15 @@ void change_notify_reply(const char *request_buf, buflen = smb_size+38+prs_offset(&ps) + 4 /* padding */; + if (buflen > max_send) { + /* + * We exceed what the client is willing to accept. Send + * nothing. + */ + change_notify_reply_packet(request_buf, NT_STATUS_OK); + goto done; + } + if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; -- cgit From 10c83ace04f675eb88e9686725795b0e965510e8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 6 Jul 2007 21:46:43 +0000 Subject: r23735: Second part of the bugfix for #4763 This should coalesce identical adjacent notify records - making the "too large" bug very rare indeed. Please test. Jeremy. (This used to be commit 1aaa1f5bbe9222acbe3dea1daa1c6c5ce72e1c2c) --- source3/smbd/notify.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 746a8f47e5..cbafeccd94 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -50,6 +50,17 @@ struct notify_mid_map { uint16 mid; }; +static BOOL notify_change_record_identical(struct notify_change *c1, + struct notify_change *c2) +{ + /* Note this is deliberately case sensitive. */ + if (c1->action == c2->action && + strcmp(c1->name, c2->name) == 0) { + return True; + } + return False; +} + static BOOL notify_marshall_changes(int num_changes, struct notify_change *changes, prs_struct *ps) @@ -58,11 +69,20 @@ static BOOL notify_marshall_changes(int num_changes, UNISTR uni_name; for (i=0; iname, strlen(c->name)+1, &uni_name.buffer, True); -- cgit From d824b98f80ba186030cbb70b3a1e5daf80469ecd Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Mon, 9 Jul 2007 19:25:36 +0000 Subject: r23779: Change from v2 or later to v3 or later. Jeremy. (This used to be commit 407e6e695b8366369b7c76af1ff76869b45347b3) --- source3/smbd/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index cbafeccd94..eecf9fa57c 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -7,7 +7,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, -- cgit From 5e54558c6dea67b56bbfaba5698f3a434d3dffb6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 00:52:41 +0000 Subject: r23784: use the GPLv3 boilerplate as recommended by the FSF and the license text (This used to be commit b0132e94fc5fef936aa766fb99a306b3628e9f07) --- source3/smbd/notify.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index eecf9fa57c..6ab4266c19 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -16,8 +16,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + along with this program. If not, see . */ #include "includes.h" -- cgit From ed9e0d9a3acfa6ab05639da5c29e2edb07a9fb67 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Jul 2007 23:01:02 +0000 Subject: r23939: Fixes for notify returns. Returned param value must fix inside max_param or return NT_STATUS_OK. Jeremy. (This used to be commit ab4af60d1ab4583fd27deb63b3f7baa1ede3473d) --- source3/smbd/notify.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 6ab4266c19..40dcecee26 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -21,15 +21,12 @@ #include "includes.h" -/* Max size we can send to client in a notify response. */ -extern int max_send; - struct notify_change_request { struct notify_change_request *prev, *next; struct files_struct *fsp; /* backpointer for cancel by mid */ char request_buf[smb_size]; uint32 filter; - uint32 current_bufsize; + uint32 max_param; struct notify_mid_map *mid_map; void *backend_data; }; @@ -61,8 +58,9 @@ static BOOL notify_change_record_identical(struct notify_change *c1, } static BOOL notify_marshall_changes(int num_changes, - struct notify_change *changes, - prs_struct *ps) + uint32 max_offset, + struct notify_change *changes, + prs_struct *ps) { int i; UNISTR uni_name; @@ -112,6 +110,11 @@ static BOOL notify_marshall_changes(int num_changes, prs_set_offset(ps, prs_offset(ps)-2); SAFE_FREE(uni_name.buffer); + + if (prs_offset(ps) > max_offset) { + /* Too much data for client. */ + return False; + } } return True; @@ -148,7 +151,7 @@ static void change_notify_reply_packet(const char *request_buf, "failed."); } -void change_notify_reply(const char *request_buf, +void change_notify_reply(const char *request_buf, uint32 max_param, struct notify_change_buf *notify_buf) { char *outbuf = NULL; @@ -160,16 +163,10 @@ void change_notify_reply(const char *request_buf, return; } - if (!prs_init(&ps, 0, NULL, False) - || !notify_marshall_changes(notify_buf->num_changes, - notify_buf->changes, &ps)) { - change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); - goto done; - } - - buflen = smb_size+38+prs_offset(&ps) + 4 /* padding */; + prs_init(&ps, 0, NULL, False); - if (buflen > max_send) { + if (!notify_marshall_changes(notify_buf->num_changes, max_param, + notify_buf->changes, &ps)) { /* * We exceed what the client is willing to accept. Send * nothing. @@ -238,7 +235,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, return status; } -NTSTATUS change_notify_add_request(const char *inbuf, +NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param, uint32 filter, BOOL recursive, struct files_struct *fsp) { @@ -255,11 +252,11 @@ NTSTATUS change_notify_add_request(const char *inbuf, map->req = request; memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); - request->current_bufsize = 0; + request->max_param = max_param; request->filter = filter; request->fsp = fsp; request->backend_data = NULL; - + DLIST_ADD_END(fsp->notify->requests, request, struct notify_change_request *); @@ -431,6 +428,7 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) */ change_notify_reply(fsp->notify->requests->request_buf, + fsp->notify->requests->max_param, fsp->notify); change_notify_remove_request(fsp->notify->requests); -- cgit From cf0962789447d881cfeb220b4d20bcbcf0197fe8 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 17 Jul 2007 23:57:13 +0000 Subject: r23940: Added missing line that was deleted accidently. Should fix the build. Jeremy. (This used to be commit b085366d5b982b635561f1d3211a6f3197258e6f) --- source3/smbd/notify.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 40dcecee26..872ec86644 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -175,6 +175,8 @@ void change_notify_reply(const char *request_buf, uint32 max_param, goto done; } + buflen = smb_size+38+prs_offset(&ps) + 4 /* padding */; + if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; -- cgit From 921ac7da4f00b86b853dd0874c7ca0d4c8677486 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 18 Jul 2007 00:18:57 +0000 Subject: r23941: Don't use "False" when you mean "MARSHALL". Jeremy. (This used to be commit 57d4d5f2cd1ad7bae28f40478f4c2f9b6a475ce6) --- source3/smbd/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 872ec86644..d003cfa88f 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -163,7 +163,7 @@ void change_notify_reply(const char *request_buf, uint32 max_param, return; } - prs_init(&ps, 0, NULL, False); + prs_init(&ps, 0, NULL, MARSHALL); if (!notify_marshall_changes(notify_buf->num_changes, max_param, notify_buf->changes, &ps)) { -- cgit From 3c5811c272db98d037892d26cf5eb22275c1e6e4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 10 Aug 2007 14:01:14 +0000 Subject: r24314: Attempt to fix bug 4868 (This used to be commit 0ced8fcfe124f99159061143f29775aacd6e1c8f) --- source3/smbd/notify.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index d003cfa88f..6c77f4c270 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -160,6 +160,7 @@ void change_notify_reply(const char *request_buf, uint32 max_param, if (notify_buf->num_changes == -1) { change_notify_reply_packet(request_buf, NT_STATUS_OK); + notify_buf->num_changes = 0; return; } -- cgit From b41b38031f8eeec916e0e5f9fb80cd8ecd5e22cd Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 07:39:11 +0000 Subject: r24398: Convert call_nt_transact_notify_change to the new API (This used to be commit 607b3ab8bc6052770f0324b57f3db6e1c11a7005) --- source3/smbd/notify.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 6c77f4c270..8474ca6446 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -24,7 +24,7 @@ struct notify_change_request { struct notify_change_request *prev, *next; struct files_struct *fsp; /* backpointer for cancel by mid */ - char request_buf[smb_size]; + uint8 request_buf[smb_size]; uint32 filter; uint32 max_param; struct notify_mid_map *mid_map; @@ -128,14 +128,14 @@ static BOOL notify_marshall_changes(int num_changes, Setup the common parts of the return packet and send it. *****************************************************************************/ -static void change_notify_reply_packet(const char *request_buf, +static void change_notify_reply_packet(const uint8 *request_buf, NTSTATUS error_code) { - const char *inbuf = request_buf; + const char *inbuf = (char *)request_buf; char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(request_buf, outbuf); + construct_reply_common(inbuf, outbuf); ERROR_NT(error_code); @@ -151,7 +151,7 @@ static void change_notify_reply_packet(const char *request_buf, "failed."); } -void change_notify_reply(const char *request_buf, uint32 max_param, +void change_notify_reply(const uint8 *request_buf, uint32 max_param, struct notify_change_buf *notify_buf) { char *outbuf = NULL; @@ -183,9 +183,9 @@ void change_notify_reply(const char *request_buf, uint32 max_param, goto done; } - construct_reply_common(request_buf, outbuf); + construct_reply_common((char *)request_buf, outbuf); - if (send_nt_replies(request_buf, outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), + if (send_nt_replies((char *)request_buf, outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), prs_offset(&ps), NULL, 0) == -1) { exit_server("change_notify_reply_packet: send_smb failed."); } @@ -238,7 +238,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, return status; } -NTSTATUS change_notify_add_request(const char *inbuf, uint32 max_param, +NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param, uint32 filter, BOOL recursive, struct files_struct *fsp) { -- cgit From 6a5bdb79e136f8cf123e36070640244ad924b274 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 07:58:56 +0000 Subject: r24399: Change change_notify_reply to use send_nt_replies_new (This used to be commit be67bb50eef88f4d56f48e785c1e5865616f5f33) --- source3/smbd/notify.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 8474ca6446..144af093cf 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -154,9 +154,8 @@ static void change_notify_reply_packet(const uint8 *request_buf, void change_notify_reply(const uint8 *request_buf, uint32 max_param, struct notify_change_buf *notify_buf) { - char *outbuf = NULL; prs_struct ps; - size_t buflen; + struct smb_request *req = NULL; if (notify_buf->num_changes == -1) { change_notify_reply_packet(request_buf, NT_STATUS_OK); @@ -176,22 +175,18 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, goto done; } - buflen = smb_size+38+prs_offset(&ps) + 4 /* padding */; - - if (!(outbuf = SMB_MALLOC_ARRAY(char, buflen))) { + if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; } - construct_reply_common((char *)request_buf, outbuf); + init_smb_request(req, request_buf); - if (send_nt_replies((char *)request_buf, outbuf, buflen, NT_STATUS_OK, prs_data_p(&ps), - prs_offset(&ps), NULL, 0) == -1) { - exit_server("change_notify_reply_packet: send_smb failed."); - } + send_nt_replies_new(req, NT_STATUS_OK, prs_data_p(&ps), + prs_offset(&ps), NULL, 0); done: - SAFE_FREE(outbuf); + TALLOC_FREE(req); prs_mem_free(&ps); TALLOC_FREE(notify_buf->changes); -- cgit From 52a738301aae2b646ffdb621f2c09ad943ad3f63 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 14 Aug 2007 08:23:54 +0000 Subject: r24400: Fix a valgrind bug (This used to be commit 7c65deaed734f5623813922637877b94fc9a6259) --- source3/smbd/notify.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 144af093cf..cf64acae07 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -180,10 +180,12 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, goto done; } + smb_setlen(NULL, request_buf, smb_size); + init_smb_request(req, request_buf); - send_nt_replies_new(req, NT_STATUS_OK, prs_data_p(&ps), - prs_offset(&ps), NULL, 0); + send_nt_replies(req, NT_STATUS_OK, prs_data_p(&ps), + prs_offset(&ps), NULL, 0); done: TALLOC_FREE(req); -- cgit From f65041cbf18d9e3778e549179edb3e134a1608b1 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 17 Aug 2007 10:05:14 +0000 Subject: r24512: Fix RAW-NOTIFY With the inbuf consistency checks we have to more correctly fake the inbuf (This used to be commit 2b8ecda30fc57bb4027b7208d22d85d213074158) --- source3/smbd/notify.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index cf64acae07..0bdf466092 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -156,6 +156,7 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, { prs_struct ps; struct smb_request *req = NULL; + uint8 tmp_request[smb_size]; if (notify_buf->num_changes == -1) { change_notify_reply_packet(request_buf, NT_STATUS_OK); @@ -180,9 +181,16 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, goto done; } - smb_setlen(NULL, request_buf, smb_size); + memcpy(tmp_request, request_buf, smb_size); - init_smb_request(req, request_buf); + /* + * We're only interested in the header fields here + */ + + smb_setlen(NULL, (char *)tmp_request, smb_size); + SCVAL(tmp_request, smb_wct, 0); + + init_smb_request(req, tmp_request); send_nt_replies(req, NT_STATUS_OK, prs_data_p(&ps), prs_offset(&ps), NULL, 0); -- cgit From 929e1d99209e20a9c2c95c8bdfc8eaa37b2c2291 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Thu, 30 Aug 2007 19:48:31 +0000 Subject: r24809: Consolidate the use of temporary talloc contexts. This adds the two functions talloc_stackframe() and talloc_tos(). * When a new talloc stackframe is allocated with talloc_stackframe(), then * the TALLOC_CTX returned with talloc_tos() is reset to that new * frame. Whenever that stack frame is TALLOC_FREE()'ed, then the reverse * happens: The previous talloc_tos() is restored. * * This API is designed to be robust in the sense that if someone forgets to * TALLOC_FREE() a stackframe, then the next outer one correctly cleans up and * resets the talloc_tos(). The original motivation for this patch was to get rid of the sid_string_static & friends buffers. Explicitly passing talloc context everywhere clutters code too much for my taste, so an implicit talloc_tos() is introduced here. Many of these static buffers are replaced by a single static pointer. The intended use would thus be that low-level functions can rather freely push stuff to talloc_tos, the upper layers clean up by freeing the stackframe. The more of these stackframes are used and correctly freed the more exact the memory cleanup happens. This patch removes the main_loop_talloc_ctx, tmp_talloc_ctx and lp_talloc_ctx (did I forget any?) So, never do a tmp_ctx = talloc_init("foo"); anymore, instead, use tmp_ctx = talloc_stackframe() :-) Volker (This used to be commit 6585ea2cb7f417e14540495b9c7380fe9c8c717b) --- source3/smbd/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 0bdf466092..da80c25407 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -176,7 +176,7 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, goto done; } - if (!(req = talloc(tmp_talloc_ctx(), struct smb_request))) { + if (!(req = talloc(talloc_tos(), struct smb_request))) { change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); goto done; } -- cgit From e5a951325a6cac8567af3a66de6d2df577508ae4 Mon Sep 17 00:00:00 2001 From: "Gerald (Jerry) Carter" Date: Wed, 10 Oct 2007 15:34:30 -0500 Subject: [GLUE] Rsync SAMBA_3_2_0 SVN r25598 in order to create the v3-2-test branch. (This used to be commit 5c6c8e1fe93f340005110a7833946191659d88ab) --- source3/smbd/notify.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index da80c25407..b8c5085b41 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -131,11 +131,10 @@ static BOOL notify_marshall_changes(int num_changes, static void change_notify_reply_packet(const uint8 *request_buf, NTSTATUS error_code) { - const char *inbuf = (char *)request_buf; char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); - construct_reply_common(inbuf, outbuf); + construct_reply_common((char *)request_buf, outbuf); ERROR_NT(error_code); @@ -143,7 +142,7 @@ static void change_notify_reply_packet(const uint8 *request_buf, * Seems NT needs a transact command with an error code * in it. This is a longer packet than a simple error. */ - set_message(inbuf,outbuf,18,0,False); + set_message(outbuf,18,0,False); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) @@ -187,7 +186,7 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, * We're only interested in the header fields here */ - smb_setlen(NULL, (char *)tmp_request, smb_size); + smb_setlen((char *)tmp_request, smb_size); SCVAL(tmp_request, smb_wct, 0); init_smb_request(req, tmp_request); -- cgit From 30191d1a5704ad2b158386b511558972d539ce47 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Thu, 18 Oct 2007 17:40:25 -0700 Subject: RIP BOOL. Convert BOOL -> bool. I found a few interesting bugs in various places whilst doing this (places that assumed BOOL == int). I also need to fix the Samba4 pidl generation (next checkin). Jeremy. (This used to be commit f35a266b3cbb3e5fa6a86be60f34fe340a3ca71f) --- source3/smbd/notify.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index b8c5085b41..ecb7d9dce8 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -46,7 +46,7 @@ struct notify_mid_map { uint16 mid; }; -static BOOL notify_change_record_identical(struct notify_change *c1, +static bool notify_change_record_identical(struct notify_change *c1, struct notify_change *c2) { /* Note this is deliberately case sensitive. */ @@ -57,7 +57,7 @@ static BOOL notify_change_record_identical(struct notify_change *c1, return False; } -static BOOL notify_marshall_changes(int num_changes, +static bool notify_marshall_changes(int num_changes, uint32 max_offset, struct notify_change *changes, prs_struct *ps) @@ -210,7 +210,7 @@ static void notify_callback(void *private_data, const struct notify_event *e) } NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, - BOOL recursive) + bool recursive) { char *fullpath; struct notify_entry e; @@ -243,7 +243,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, } NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param, - uint32 filter, BOOL recursive, + uint32 filter, bool recursive, struct files_struct *fsp) { struct notify_change_request *request = NULL; -- cgit From c3250149e12338fac5093991b385ad2807c92d1f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 30 Oct 2007 16:22:24 -0700 Subject: Add new parameter, "min receivefile size" (by default set to zero). If non-zero, writeX calls greater than this value will be left in the socket buffer for later handling with recvfile (or userspace equivalent). Definition of recvfile for your system is left as an exercise for the reader (I'm working on getting splice working :-). Jeremy. (This used to be commit 11c03b75ddbcb6e36b231bb40a1773d1c550621c) --- source3/smbd/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index ecb7d9dce8..0dd7fbb20e 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -189,7 +189,7 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, smb_setlen((char *)tmp_request, smb_size); SCVAL(tmp_request, smb_wct, 0); - init_smb_request(req, tmp_request); + init_smb_request(req, tmp_request,0); send_nt_replies(req, NT_STATUS_OK, prs_data_p(&ps), prs_offset(&ps), NULL, 0); -- cgit From afc93255d183eefb68e45b8ec6275f6a62cf9795 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Wed, 26 Dec 2007 17:12:36 -0800 Subject: Add SMB encryption. Still fixing client decrypt but negotiation works. Jeremy. (This used to be commit d78045601af787731f0737b8627450018902b104) --- source3/smbd/notify.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 0dd7fbb20e..baab48f77e 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -131,6 +131,7 @@ static bool notify_marshall_changes(int num_changes, static void change_notify_reply_packet(const uint8 *request_buf, NTSTATUS error_code) { + const char *inbuf = (const char *)request_buf; char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); @@ -142,7 +143,7 @@ static void change_notify_reply_packet(const uint8 *request_buf, * Seems NT needs a transact command with an error code * in it. This is a longer packet than a simple error. */ - set_message(outbuf,18,0,False); + srv_set_message((const char *)request_buf, outbuf,18,0,False); show_msg(outbuf); if (!send_smb(smbd_server_fd(),outbuf)) -- cgit From 9254bb4ef1c3c3a52ea8e935edb0e7a86ec3ea7a Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 4 Jan 2008 12:56:23 -0800 Subject: Refactor the crypto code after a very helpful conversation with Volker. Mostly making sure we have data on the incoming packet type, not stored in the smb header. Jeremy. (This used to be commit c4e5a505043965eec77b5bb9bc60957e8f3b97c8) --- source3/smbd/notify.c | 46 ++++++++++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 20 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index baab48f77e..7287210802 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -128,10 +128,10 @@ static bool notify_marshall_changes(int num_changes, Setup the common parts of the return packet and send it. *****************************************************************************/ -static void change_notify_reply_packet(const uint8 *request_buf, +static void change_notify_reply_packet(connection_struct *conn, + const uint8 *request_buf, NTSTATUS error_code) { - const char *inbuf = (const char *)request_buf; char outbuf[smb_size+38]; memset(outbuf, '\0', sizeof(outbuf)); @@ -143,15 +143,18 @@ static void change_notify_reply_packet(const uint8 *request_buf, * Seems NT needs a transact command with an error code * in it. This is a longer packet than a simple error. */ - srv_set_message((const char *)request_buf, outbuf,18,0,False); + srv_set_message(outbuf,18,0,False); show_msg(outbuf); - if (!send_smb(smbd_server_fd(),outbuf)) - exit_server_cleanly("change_notify_reply_packet: send_smb " + if (!srv_send_smb(smbd_server_fd(), + outbuf, + IS_CONN_ENCRYPTED(conn))) + exit_server_cleanly("change_notify_reply_packet: srv_send_smb " "failed."); } -void change_notify_reply(const uint8 *request_buf, uint32 max_param, +void change_notify_reply(connection_struct *conn, + const uint8 *request_buf, uint32 max_param, struct notify_change_buf *notify_buf) { prs_struct ps; @@ -159,7 +162,7 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, uint8 tmp_request[smb_size]; if (notify_buf->num_changes == -1) { - change_notify_reply_packet(request_buf, NT_STATUS_OK); + change_notify_reply_packet(conn, request_buf, NT_STATUS_OK); notify_buf->num_changes = 0; return; } @@ -172,12 +175,12 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, * We exceed what the client is willing to accept. Send * nothing. */ - change_notify_reply_packet(request_buf, NT_STATUS_OK); + change_notify_reply_packet(conn, request_buf, NT_STATUS_OK); goto done; } if (!(req = talloc(talloc_tos(), struct smb_request))) { - change_notify_reply_packet(request_buf, NT_STATUS_NO_MEMORY); + change_notify_reply_packet(conn, request_buf, NT_STATUS_NO_MEMORY); goto done; } @@ -190,9 +193,9 @@ void change_notify_reply(const uint8 *request_buf, uint32 max_param, smb_setlen((char *)tmp_request, smb_size); SCVAL(tmp_request, smb_wct, 0); - init_smb_request(req, tmp_request,0); + init_smb_request(req, tmp_request,0, conn->encrypted_tid); - send_nt_replies(req, NT_STATUS_OK, prs_data_p(&ps), + send_nt_replies(conn, req, NT_STATUS_OK, prs_data_p(&ps), prs_offset(&ps), NULL, 0); done: @@ -243,9 +246,10 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, return status; } -NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param, - uint32 filter, bool recursive, - struct files_struct *fsp) +NTSTATUS change_notify_add_request(const struct smb_request *req, + uint32 max_param, + uint32 filter, bool recursive, + struct files_struct *fsp) { struct notify_change_request *request = NULL; struct notify_mid_map *map = NULL; @@ -259,7 +263,7 @@ NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param, request->mid_map = map; map->req = request; - memcpy(request->request_buf, inbuf, sizeof(request->request_buf)); + memcpy(request->request_buf, req->inbuf, sizeof(request->request_buf)); request->max_param = max_param; request->filter = filter; request->fsp = fsp; @@ -268,11 +272,11 @@ NTSTATUS change_notify_add_request(const uint8 *inbuf, uint32 max_param, DLIST_ADD_END(fsp->notify->requests, request, struct notify_change_request *); - map->mid = SVAL(inbuf, smb_mid); + map->mid = SVAL(req->inbuf, smb_mid); DLIST_ADD(notify_changes_by_mid, map); /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(inbuf,smb_mid)); + srv_defer_sign_response(SVAL(req->inbuf,smb_mid)); return NT_STATUS_OK; } @@ -325,7 +329,8 @@ void remove_pending_change_notify_requests_by_mid(uint16 mid) return; } - change_notify_reply_packet(map->req->request_buf, NT_STATUS_CANCELLED); + change_notify_reply_packet(map->req->fsp->conn, + map->req->request_buf, NT_STATUS_CANCELLED); change_notify_remove_request(map->req); } @@ -341,7 +346,7 @@ void remove_pending_change_notify_requests_by_fid(files_struct *fsp, } while (fsp->notify->requests != NULL) { - change_notify_reply_packet( + change_notify_reply_packet(fsp->conn, fsp->notify->requests->request_buf, status); change_notify_remove_request(fsp->notify->requests); } @@ -435,7 +440,8 @@ static void notify_fsp(files_struct *fsp, uint32 action, const char *name) * TODO: do we have to walk the lists of requests pending? */ - change_notify_reply(fsp->notify->requests->request_buf, + change_notify_reply(fsp->conn, + fsp->notify->requests->request_buf, fsp->notify->requests->max_param, fsp->notify); -- cgit From 3f55798be06af3923820aa047b21b9f7a030a2c3 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 8 Jan 2008 22:48:22 -0800 Subject: ensure uni_name.buffer is initialised merge from http://samba.org/~tridge/3_0-ctdb Jeremy. (This used to be commit dec77b387cd9024eb33bb0617c7543814e9c9212) --- source3/smbd/notify.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 7287210802..5c26cac219 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -65,6 +65,8 @@ static bool notify_marshall_changes(int num_changes, int i; UNISTR uni_name; + uni_name.buffer = NULL; + for (i=0; i Date: Fri, 11 Jan 2008 23:17:23 -0800 Subject: Fix CID 505 - don't copy uninitialized memory. Jeremy. (This used to be commit 0d2c77e8d3a83f2c5e78fa076f22919ef9d124b9) --- source3/smbd/notify.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 5c26cac219..55009ce0b1 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -235,6 +235,7 @@ NTSTATUS change_notify_create(struct files_struct *fsp, uint32 filter, return NT_STATUS_NO_MEMORY; } + ZERO_STRUCT(e); e.path = fullpath; e.filter = filter; e.subdir_filter = 0; -- cgit From e06aa46b9fab1e107fea8f6453fb13deffa91e96 Mon Sep 17 00:00:00 2001 From: Marc VanHeyningen Date: Fri, 14 Mar 2008 14:26:28 -0800 Subject: Coverity fixes (This used to be commit 3fc85d22590550f0539215d020e4411bf5b14363) --- source3/smbd/notify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index 55009ce0b1..ffdf1c22e7 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -169,7 +169,7 @@ void change_notify_reply(connection_struct *conn, return; } - prs_init(&ps, 0, NULL, MARSHALL); + prs_init_empty(&ps, NULL, MARSHALL); if (!notify_marshall_changes(notify_buf->num_changes, max_param, notify_buf->changes, &ps)) { -- cgit From bb869741ddc3d82da02c96bef592dab6074ff142 Mon Sep 17 00:00:00 2001 From: Tim Prouty Date: Mon, 3 Mar 2008 13:32:54 -0800 Subject: Cleanup size_t return values in convert_string_allocate This patch is the first iteration of an inside-out conversion to cleanup functions in charcnv.c returning size_t == -1 to indicate failure. (This used to be commit 59124382d2894a1b194b48dd82bc5f956959eb48) --- source3/smbd/notify.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index ffdf1c22e7..eb3384d9a4 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -82,10 +82,9 @@ static bool notify_marshall_changes(int num_changes, c = &changes[i]; - namelen = convert_string_allocate( - NULL, CH_UNIX, CH_UTF16LE, c->name, strlen(c->name)+1, - &uni_name.buffer, True); - if ((namelen == -1) || (uni_name.buffer == NULL)) { + if (!convert_string_allocate(NULL, CH_UNIX, CH_UTF16LE, + c->name, strlen(c->name)+1, &uni_name.buffer, + &namelen, True) || (uni_name.buffer == NULL)) { goto fail; } -- cgit From d314f7eab5d6fd5c14849abc553c43642b26cf54 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Tue, 17 Jun 2008 10:46:20 +0200 Subject: Add some debug to notify (This used to be commit 4394235378f85ccb911d662d95f1545a14240bdf) --- source3/smbd/notify.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source3/smbd/notify.c') diff --git a/source3/smbd/notify.c b/source3/smbd/notify.c index eb3384d9a4..139dfe7d5b 100644 --- a/source3/smbd/notify.c +++ b/source3/smbd/notify.c @@ -114,6 +114,9 @@ static bool notify_marshall_changes(int num_changes, if (prs_offset(ps) > max_offset) { /* Too much data for client. */ + DEBUG(10, ("Client only wanted %d bytes, trying to " + "marshall %d bytes\n", (int)max_offset, + (int)prs_offset(ps))); return False; } } @@ -256,6 +259,9 @@ NTSTATUS change_notify_add_request(const struct smb_request *req, struct notify_change_request *request = NULL; struct notify_mid_map *map = NULL; + DEBUG(10, ("change_notify_add_request: Adding request for %s: " + "max_param = %d\n", fsp->fsp_name, (int)max_param)); + if (!(request = SMB_MALLOC_P(struct notify_change_request)) || !(map = SMB_MALLOC_P(struct notify_mid_map))) { SAFE_FREE(request); -- cgit