Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : *
4 : * Copyright (C) Volker Lendecke 2014
5 : *
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.
10 : *
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.
15 : *
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/>.
18 : */
19 :
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"
33 :
34 : struct notify_context {
35 : struct server_id notifyd;
36 : struct messaging_context *msg_ctx;
37 :
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);
42 : };
43 :
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);
48 :
49 20637 : 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 *))
55 : {
56 344 : struct server_id_db *names_db;
57 344 : struct notify_context *ctx;
58 344 : NTSTATUS status;
59 :
60 20637 : ctx = talloc(mem_ctx, struct notify_context);
61 20637 : if (ctx == NULL) {
62 0 : return NULL;
63 : }
64 20637 : ctx->msg_ctx = msg;
65 :
66 20637 : ctx->sconn = sconn;
67 20637 : ctx->callback = callback;
68 :
69 20637 : names_db = messaging_names_db(msg);
70 20637 : if (!server_id_db_lookup_one(names_db, "notify-daemon",
71 : &ctx->notifyd)) {
72 0 : DBG_WARNING("No notify daemon around\n");
73 0 : TALLOC_FREE(ctx);
74 0 : return NULL;
75 : }
76 :
77 : {
78 344 : struct server_id_buf tmp;
79 20637 : DBG_DEBUG("notifyd=%s\n",
80 : server_id_str_buf(ctx->notifyd, &tmp));
81 : }
82 :
83 20637 : if (callback != NULL) {
84 20637 : status = messaging_register(msg, ctx, MSG_PVFS_NOTIFY,
85 : notify_handler);
86 20637 : if (!NT_STATUS_IS_OK(status)) {
87 0 : DBG_WARNING("messaging_register failed: %s\n",
88 : nt_errstr(status));
89 0 : TALLOC_FREE(ctx);
90 0 : return NULL;
91 : }
92 : }
93 :
94 20637 : talloc_set_destructor(ctx, notify_context_destructor);
95 :
96 20637 : return ctx;
97 : }
98 :
99 20623 : static int notify_context_destructor(struct notify_context *ctx)
100 : {
101 20623 : if (ctx->callback != NULL) {
102 20623 : messaging_deregister(ctx->msg_ctx, MSG_PVFS_NOTIFY, ctx);
103 : }
104 :
105 20623 : return 0;
106 : }
107 :
108 1969 : static void notify_handler(struct messaging_context *msg, void *private_data,
109 : uint32_t msg_type, struct server_id src,
110 : DATA_BLOB *data)
111 : {
112 1969 : struct notify_context *ctx = talloc_get_type_abort(
113 : private_data, struct notify_context);
114 14 : struct notify_event_msg *event_msg;
115 14 : struct notify_event event;
116 :
117 1969 : if (data->length < offsetof(struct notify_event_msg, path) + 1) {
118 0 : DBG_WARNING("message too short: %zu\n", data->length);
119 0 : return;
120 : }
121 1969 : if (data->data[data->length-1] != 0) {
122 0 : DBG_WARNING("path not 0-terminated\n");
123 0 : return;
124 : }
125 :
126 1969 : event_msg = (struct notify_event_msg *)data->data;
127 :
128 1969 : event.action = event_msg->action;
129 1969 : event.path = event_msg->path;
130 1969 : event.private_data = event_msg->private_data;
131 :
132 1969 : DBG_DEBUG("Got notify_event action=%"PRIu32", private_data=%p, "
133 : "path=%s\n",
134 : event.action,
135 : event.private_data,
136 : event.path);
137 :
138 1969 : ctx->callback(ctx->sconn, event.private_data, event_msg->when, &event);
139 : }
140 :
141 1866 : NTSTATUS notify_add(struct notify_context *ctx,
142 : const char *path, uint32_t filter, uint32_t subdir_filter,
143 : void *private_data)
144 : {
145 1866 : struct notify_rec_change_msg msg = {};
146 16 : struct iovec iov[2];
147 16 : size_t pathlen;
148 16 : NTSTATUS status;
149 :
150 1866 : if (ctx == NULL) {
151 2 : return NT_STATUS_NOT_IMPLEMENTED;
152 : }
153 :
154 1864 : DBG_DEBUG("path=[%s], filter=%"PRIu32", subdir_filter=%"PRIu32", "
155 : "private_data=%p\n",
156 : path,
157 : filter,
158 : subdir_filter,
159 : private_data);
160 :
161 1864 : pathlen = strlen(path)+1;
162 :
163 1864 : clock_gettime_mono(&msg.instance.creation_time);
164 1864 : msg.instance.filter = filter;
165 1864 : msg.instance.subdir_filter = subdir_filter;
166 1864 : msg.instance.private_data = private_data;
167 :
168 1864 : iov[0].iov_base = &msg;
169 1864 : iov[0].iov_len = offsetof(struct notify_rec_change_msg, path);
170 1864 : iov[1].iov_base = discard_const_p(char, path);
171 1864 : iov[1].iov_len = pathlen;
172 :
173 1864 : status = messaging_send_iov(
174 : ctx->msg_ctx, ctx->notifyd, MSG_SMB_NOTIFY_REC_CHANGE,
175 : iov, ARRAY_SIZE(iov), NULL, 0);
176 :
177 1864 : if (!NT_STATUS_IS_OK(status)) {
178 0 : DBG_DEBUG("messaging_send_iov returned %s\n",
179 : nt_errstr(status));
180 0 : return status;
181 : }
182 :
183 1864 : return NT_STATUS_OK;
184 : }
185 :
186 1866 : NTSTATUS notify_remove(struct notify_context *ctx, void *private_data,
187 : char *path)
188 : {
189 1866 : struct notify_rec_change_msg msg = {};
190 16 : struct iovec iov[2];
191 16 : NTSTATUS status;
192 :
193 : /* see if change notify is enabled at all */
194 1866 : if (ctx == NULL) {
195 2 : return NT_STATUS_NOT_IMPLEMENTED;
196 : }
197 :
198 1864 : msg.instance.private_data = private_data;
199 :
200 1864 : iov[0].iov_base = &msg;
201 1864 : iov[0].iov_len = offsetof(struct notify_rec_change_msg, path);
202 1864 : iov[1].iov_base = path;
203 1864 : iov[1].iov_len = strlen(path)+1;
204 :
205 1864 : status = messaging_send_iov(
206 : ctx->msg_ctx, ctx->notifyd, MSG_SMB_NOTIFY_REC_CHANGE,
207 : iov, ARRAY_SIZE(iov), NULL, 0);
208 :
209 1864 : return status;
210 : }
211 :
212 359797 : void notify_trigger(struct notify_context *ctx,
213 : uint32_t action, uint32_t filter,
214 : const char *dir, const char *name)
215 : {
216 960 : struct notify_trigger_msg msg;
217 960 : struct iovec iov[4];
218 359797 : char slash = '/';
219 :
220 359797 : 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);
226 :
227 359797 : if (ctx == NULL) {
228 40392 : return;
229 : }
230 :
231 319405 : msg.when = timespec_current();
232 319405 : msg.action = action;
233 319405 : msg.filter = filter;
234 :
235 319405 : iov[0].iov_base = &msg;
236 319405 : iov[0].iov_len = offsetof(struct notify_trigger_msg, path);
237 319405 : iov[1].iov_base = discard_const_p(char, dir);
238 319405 : iov[1].iov_len = strlen(dir);
239 319405 : iov[2].iov_base = &slash;
240 319405 : iov[2].iov_len = 1;
241 319405 : iov[3].iov_base = discard_const_p(char, name);
242 319405 : iov[3].iov_len = strlen(name)+1;
243 :
244 319405 : messaging_send_iov(
245 : ctx->msg_ctx, ctx->notifyd, MSG_SMB_NOTIFY_TRIGGER,
246 : iov, ARRAY_SIZE(iov), NULL, 0);
247 : }
|