smbd: avoid a panic in close_directory()
[samba4-gss.git] / source3 / smbd / notify_msg.c
blob0ea992c4929317d6df125d861e05c5150564ff51
1 /*
2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Volker Lendecke 2014
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "librpc/gen_ndr/notify.h"
22 #include "librpc/gen_ndr/messaging.h"
23 #include "lib/dbwrap/dbwrap.h"
24 #include "lib/dbwrap/dbwrap_rbt.h"
25 #include "lib/util/server_id.h"
26 #include "messages.h"
27 #include "proto.h"
28 #include "globals.h"
29 #include "tdb.h"
30 #include "util_tdb.h"
31 #include "lib/util/server_id_db.h"
32 #include "smbd/notifyd/notifyd.h"
34 struct notify_context {
35 struct server_id notifyd;
36 struct messaging_context *msg_ctx;
38 struct smbd_server_connection *sconn;
39 void (*callback)(struct smbd_server_connection *sconn,
40 void *private_data, struct timespec when,
41 const struct notify_event *ctx);
44 static void notify_handler(struct messaging_context *msg, void *private_data,
45 uint32_t msg_type, struct server_id src,
46 DATA_BLOB *data);
47 static int notify_context_destructor(struct notify_context *ctx);
49 struct notify_context *notify_init(
50 TALLOC_CTX *mem_ctx, struct messaging_context *msg,
51 struct smbd_server_connection *sconn,
52 void (*callback)(struct smbd_server_connection *sconn,
53 void *, struct timespec,
54 const struct notify_event *))
56 struct server_id_db *names_db;
57 struct notify_context *ctx;
58 NTSTATUS status;
60 ctx = talloc(mem_ctx, struct notify_context);
61 if (ctx == NULL) {
62 return NULL;
64 ctx->msg_ctx = msg;
66 ctx->sconn = sconn;
67 ctx->callback = callback;
69 names_db = messaging_names_db(msg);
70 if (!server_id_db_lookup_one(names_db, "notify-daemon",
71 &ctx->notifyd)) {
72 DBG_WARNING("No notify daemon around\n");
73 TALLOC_FREE(ctx);
74 return NULL;
78 struct server_id_buf tmp;
79 DBG_DEBUG("notifyd=%s\n",
80 server_id_str_buf(ctx->notifyd, &tmp));
83 if (callback != NULL) {
84 status = messaging_register(msg, ctx, MSG_PVFS_NOTIFY,
85 notify_handler);
86 if (!NT_STATUS_IS_OK(status)) {
87 DBG_WARNING("messaging_register failed: %s\n",
88 nt_errstr(status));
89 TALLOC_FREE(ctx);
90 return NULL;
94 talloc_set_destructor(ctx, notify_context_destructor);
96 return ctx;
99 static int notify_context_destructor(struct notify_context *ctx)
101 if (ctx->callback != NULL) {
102 messaging_deregister(ctx->msg_ctx, MSG_PVFS_NOTIFY, ctx);
105 return 0;
108 static void notify_handler(struct messaging_context *msg, void *private_data,
109 uint32_t msg_type, struct server_id src,
110 DATA_BLOB *data)
112 struct notify_context *ctx = talloc_get_type_abort(
113 private_data, struct notify_context);
114 struct notify_event_msg *event_msg;
115 struct notify_event event;
117 if (data->length < offsetof(struct notify_event_msg, path) + 1) {
118 DBG_WARNING("message too short: %zu\n", data->length);
119 return;
121 if (data->data[data->length-1] != 0) {
122 DBG_WARNING("path not 0-terminated\n");
123 return;
126 event_msg = (struct notify_event_msg *)data->data;
128 event.action = event_msg->action;
129 event.path = event_msg->path;
130 event.private_data = event_msg->private_data;
132 DBG_DEBUG("Got notify_event action=%"PRIu32", private_data=%p, "
133 "path=%s\n",
134 event.action,
135 event.private_data,
136 event.path);
138 ctx->callback(ctx->sconn, event.private_data, event_msg->when, &event);
141 NTSTATUS notify_add(struct notify_context *ctx,
142 const char *path, uint32_t filter, uint32_t subdir_filter,
143 void *private_data)
145 struct notify_rec_change_msg msg = {};
146 struct iovec iov[2];
147 size_t pathlen;
148 NTSTATUS status;
150 if (ctx == NULL) {
151 return NT_STATUS_NOT_IMPLEMENTED;
154 DBG_DEBUG("path=[%s], filter=%"PRIu32", subdir_filter=%"PRIu32", "
155 "private_data=%p\n",
156 path,
157 filter,
158 subdir_filter,
159 private_data);
161 pathlen = strlen(path)+1;
163 clock_gettime_mono(&msg.instance.creation_time);
164 msg.instance.filter = filter;
165 msg.instance.subdir_filter = subdir_filter;
166 msg.instance.private_data = private_data;
168 iov[0].iov_base = &msg;
169 iov[0].iov_len = offsetof(struct notify_rec_change_msg, path);
170 iov[1].iov_base = discard_const_p(char, path);
171 iov[1].iov_len = pathlen;
173 status = messaging_send_iov(
174 ctx->msg_ctx, ctx->notifyd, MSG_SMB_NOTIFY_REC_CHANGE,
175 iov, ARRAY_SIZE(iov), NULL, 0);
177 if (!NT_STATUS_IS_OK(status)) {
178 DBG_DEBUG("messaging_send_iov returned %s\n",
179 nt_errstr(status));
180 return status;
183 return NT_STATUS_OK;
186 NTSTATUS notify_remove(struct notify_context *ctx, void *private_data,
187 char *path)
189 struct notify_rec_change_msg msg = {};
190 struct iovec iov[2];
191 NTSTATUS status;
193 /* see if change notify is enabled at all */
194 if (ctx == NULL) {
195 return NT_STATUS_NOT_IMPLEMENTED;
198 msg.instance.private_data = private_data;
200 iov[0].iov_base = &msg;
201 iov[0].iov_len = offsetof(struct notify_rec_change_msg, path);
202 iov[1].iov_base = path;
203 iov[1].iov_len = strlen(path)+1;
205 status = messaging_send_iov(
206 ctx->msg_ctx, ctx->notifyd, MSG_SMB_NOTIFY_REC_CHANGE,
207 iov, ARRAY_SIZE(iov), NULL, 0);
209 return status;
212 void notify_trigger(struct notify_context *ctx,
213 uint32_t action, uint32_t filter,
214 const char *dir, const char *name)
216 struct notify_trigger_msg msg;
217 struct iovec iov[4];
218 char slash = '/';
220 DBG_DEBUG("notify_trigger called action=0x%"PRIx32", "
221 "filter=0x%"PRIx32", dir=%s, name=%s\n",
222 action,
223 filter,
224 dir,
225 name);
227 if (ctx == NULL) {
228 return;
231 msg.when = timespec_current();
232 msg.action = action;
233 msg.filter = filter;
235 iov[0].iov_base = &msg;
236 iov[0].iov_len = offsetof(struct notify_trigger_msg, path);
237 iov[1].iov_base = discard_const_p(char, dir);
238 iov[1].iov_len = strlen(dir);
239 iov[2].iov_base = &slash;
240 iov[2].iov_len = 1;
241 iov[3].iov_base = discard_const_p(char, name);
242 iov[3].iov_len = strlen(name)+1;
244 messaging_send_iov(
245 ctx->msg_ctx, ctx->notifyd, MSG_SMB_NOTIFY_TRIGGER,
246 iov, ARRAY_SIZE(iov), NULL, 0);