dbwrap_watch: Add dsize to DEBUG, avoid casts
[kai/samba-autobuild/.git] / source3 / lib / messages_dgm.c
1 /*
2  * Unix SMB/CIFS implementation.
3  * Samba internal messaging functions
4  * Copyright (C) 2013 by Volker Lendecke
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 "replace.h"
21 #include "system/network.h"
22 #include "system/filesys.h"
23 #include "system/dir.h"
24 #include "lib/util/debug.h"
25 #include "lib/unix_msg/unix_msg.h"
26 #include "lib/messages_dgm.h"
27 #include "poll_funcs/poll_funcs_tevent.h"
28 #include "lib/util/genrand.h"
29
30 struct sun_path_buf {
31         /*
32          * This will carry enough for a socket path
33          */
34         char buf[sizeof(struct sockaddr_un)];
35 };
36
37 struct messaging_dgm_context {
38         pid_t pid;
39         struct poll_funcs *msg_callbacks;
40         void *tevent_handle;
41         struct unix_msg_ctx *dgm_ctx;
42         struct sun_path_buf socket_dir;
43         struct sun_path_buf lockfile_dir;
44         int lockfile_fd;
45
46         void (*recv_cb)(const uint8_t *msg,
47                         size_t msg_len,
48                         int *fds,
49                         size_t num_fds,
50                         void *private_data);
51         void *recv_cb_private_data;
52
53         bool *have_dgm_context;
54 };
55
56 static struct messaging_dgm_context *global_dgm_context;
57
58 static void messaging_dgm_recv(struct unix_msg_ctx *ctx,
59                                uint8_t *msg, size_t msg_len,
60                                int *fds, size_t num_fds,
61                                void *private_data);
62
63 static int messaging_dgm_context_destructor(struct messaging_dgm_context *c);
64
65 static int messaging_dgm_lockfile_create(struct messaging_dgm_context *ctx,
66                                          pid_t pid, int *plockfile_fd,
67                                          uint64_t *punique)
68 {
69         char buf[64];
70         int lockfile_fd;
71         struct sun_path_buf lockfile_name;
72         struct flock lck;
73         uint64_t unique;
74         int unique_len, ret;
75         ssize_t written;
76
77         ret = snprintf(lockfile_name.buf, sizeof(lockfile_name.buf),
78                        "%s/%u", ctx->lockfile_dir.buf, (unsigned)pid);
79         if (ret < 0) {
80                 return errno;
81         }
82         if ((unsigned)ret >= sizeof(lockfile_name.buf)) {
83                 return ENAMETOOLONG;
84         }
85
86         /* no O_EXCL, existence check is via the fcntl lock */
87
88         lockfile_fd = open(lockfile_name.buf, O_NONBLOCK|O_CREAT|O_RDWR,
89                            0644);
90
91         if ((lockfile_fd == -1) &&
92             ((errno == ENXIO) /* Linux */ ||
93              (errno == ENODEV) /* Linux kernel bug */ ||
94              (errno == EOPNOTSUPP) /* FreeBSD */)) {
95                 /*
96                  * Huh -- a socket? This might be a stale socket from
97                  * an upgrade of Samba. Just unlink and retry, nobody
98                  * else is supposed to be here at this time.
99                  *
100                  * Yes, this is racy, but I don't see a way to deal
101                  * with this properly.
102                  */
103                 unlink(lockfile_name.buf);
104
105                 lockfile_fd = open(lockfile_name.buf,
106                                    O_NONBLOCK|O_CREAT|O_WRONLY,
107                                    0644);
108         }
109
110         if (lockfile_fd == -1) {
111                 ret = errno;
112                 DEBUG(1, ("%s: open failed: %s\n", __func__, strerror(errno)));
113                 return ret;
114         }
115
116         lck = (struct flock) {
117                 .l_type = F_WRLCK,
118                 .l_whence = SEEK_SET
119         };
120
121         ret = fcntl(lockfile_fd, F_SETLK, &lck);
122         if (ret == -1) {
123                 ret = errno;
124                 DEBUG(1, ("%s: fcntl failed: %s\n", __func__, strerror(ret)));
125                 goto fail_close;
126         }
127
128         /*
129          * Directly using the binary value for
130          * SERVERID_UNIQUE_ID_NOT_TO_VERIFY is a layering
131          * violation. But including all of ndr here just for this
132          * seems to be a bit overkill to me. Also, messages_dgm might
133          * be replaced sooner or later by something streams-based,
134          * where unique_id generation will be handled differently.
135          */
136
137         do {
138                 generate_random_buffer((uint8_t *)&unique, sizeof(unique));
139         } while (unique == UINT64_C(0xFFFFFFFFFFFFFFFF));
140
141         unique_len = snprintf(buf, sizeof(buf), "%ju\n", (uintmax_t)unique);
142
143         /* shorten a potentially preexisting file */
144
145         ret = ftruncate(lockfile_fd, unique_len);
146         if (ret == -1) {
147                 ret = errno;
148                 DEBUG(1, ("%s: ftruncate failed: %s\n", __func__,
149                           strerror(ret)));
150                 goto fail_unlink;
151         }
152
153         written = write(lockfile_fd, buf, unique_len);
154         if (written != unique_len) {
155                 ret = errno;
156                 DEBUG(1, ("%s: write failed: %s\n", __func__, strerror(ret)));
157                 goto fail_unlink;
158         }
159
160         *plockfile_fd = lockfile_fd;
161         *punique = unique;
162         return 0;
163
164 fail_unlink:
165         unlink(lockfile_name.buf);
166 fail_close:
167         close(lockfile_fd);
168         return ret;
169 }
170
171 int messaging_dgm_init(struct tevent_context *ev,
172                        uint64_t *punique,
173                        const char *socket_dir,
174                        const char *lockfile_dir,
175                        void (*recv_cb)(const uint8_t *msg,
176                                        size_t msg_len,
177                                        int *fds,
178                                        size_t num_fds,
179                                        void *private_data),
180                        void *recv_cb_private_data)
181 {
182         struct messaging_dgm_context *ctx;
183         int ret;
184         struct sockaddr_un socket_address;
185         size_t len;
186         static bool have_dgm_context = false;
187
188         if (have_dgm_context) {
189                 return EEXIST;
190         }
191
192         ctx = talloc_zero(NULL, struct messaging_dgm_context);
193         if (ctx == NULL) {
194                 goto fail_nomem;
195         }
196         ctx->pid = getpid();
197         ctx->recv_cb = recv_cb;
198         ctx->recv_cb_private_data = recv_cb_private_data;
199
200         len = strlcpy(ctx->lockfile_dir.buf, lockfile_dir,
201                       sizeof(ctx->lockfile_dir.buf));
202         if (len >= sizeof(ctx->lockfile_dir.buf)) {
203                 TALLOC_FREE(ctx);
204                 return ENAMETOOLONG;
205         }
206
207         len = strlcpy(ctx->socket_dir.buf, socket_dir,
208                       sizeof(ctx->socket_dir.buf));
209         if (len >= sizeof(ctx->socket_dir.buf)) {
210                 TALLOC_FREE(ctx);
211                 return ENAMETOOLONG;
212         }
213
214         socket_address = (struct sockaddr_un) { .sun_family = AF_UNIX };
215         len = snprintf(socket_address.sun_path,
216                        sizeof(socket_address.sun_path),
217                        "%s/%u", socket_dir, (unsigned)ctx->pid);
218         if (len >= sizeof(socket_address.sun_path)) {
219                 TALLOC_FREE(ctx);
220                 return ENAMETOOLONG;
221         }
222
223         ret = messaging_dgm_lockfile_create(ctx, ctx->pid, &ctx->lockfile_fd,
224                                             punique);
225         if (ret != 0) {
226                 DEBUG(1, ("%s: messaging_dgm_create_lockfile failed: %s\n",
227                           __func__, strerror(ret)));
228                 TALLOC_FREE(ctx);
229                 return ret;
230         }
231
232         ctx->msg_callbacks = poll_funcs_init_tevent(ctx);
233         if (ctx->msg_callbacks == NULL) {
234                 goto fail_nomem;
235         }
236
237         ctx->tevent_handle = poll_funcs_tevent_register(
238                 ctx, ctx->msg_callbacks, ev);
239         if (ctx->tevent_handle == NULL) {
240                 goto fail_nomem;
241         }
242
243         unlink(socket_address.sun_path);
244
245         ret = unix_msg_init(&socket_address, ctx->msg_callbacks, 1024,
246                             messaging_dgm_recv, ctx, &ctx->dgm_ctx);
247         if (ret != 0) {
248                 DEBUG(1, ("unix_msg_init failed: %s\n", strerror(ret)));
249                 TALLOC_FREE(ctx);
250                 return ret;
251         }
252         talloc_set_destructor(ctx, messaging_dgm_context_destructor);
253
254         ctx->have_dgm_context = &have_dgm_context;
255
256         global_dgm_context = ctx;
257         return 0;
258
259 fail_nomem:
260         TALLOC_FREE(ctx);
261         return ENOMEM;
262 }
263
264 static int messaging_dgm_context_destructor(struct messaging_dgm_context *c)
265 {
266         /*
267          * First delete the socket to avoid races. The lockfile is the
268          * indicator that we're still around.
269          */
270         unix_msg_free(c->dgm_ctx);
271
272         if (getpid() == c->pid) {
273                 struct sun_path_buf name;
274                 int ret;
275
276                 ret = snprintf(name.buf, sizeof(name.buf), "%s/%u",
277                                c->lockfile_dir.buf, (unsigned)c->pid);
278                 if ((ret < 0) || ((size_t)ret >= sizeof(name.buf))) {
279                         /*
280                          * We've checked the length when creating, so this
281                          * should never happen
282                          */
283                         abort();
284                 }
285                 unlink(name.buf);
286         }
287         close(c->lockfile_fd);
288
289         if (c->have_dgm_context != NULL) {
290                 *c->have_dgm_context = false;
291         }
292
293         return 0;
294 }
295
296 void messaging_dgm_destroy(void)
297 {
298         TALLOC_FREE(global_dgm_context);
299 }
300
301 int messaging_dgm_send(pid_t pid,
302                        const struct iovec *iov, int iovlen,
303                        const int *fds, size_t num_fds)
304 {
305         struct messaging_dgm_context *ctx = global_dgm_context;
306         struct sockaddr_un dst;
307         ssize_t dst_pathlen;
308         int ret;
309
310         if (ctx == NULL) {
311                 return ENOTCONN;
312         }
313
314         dst = (struct sockaddr_un) { .sun_family = AF_UNIX };
315
316         dst_pathlen = snprintf(dst.sun_path, sizeof(dst.sun_path),
317                                "%s/%u", ctx->socket_dir.buf, (unsigned)pid);
318         if (dst_pathlen < 0) {
319                 return errno;
320         }
321         if ((size_t)dst_pathlen >= sizeof(dst.sun_path)) {
322                 return ENAMETOOLONG;
323         }
324
325         DEBUG(10, ("%s: Sending message to %u\n", __func__, (unsigned)pid));
326
327         ret = unix_msg_send(ctx->dgm_ctx, &dst, iov, iovlen, fds, num_fds);
328
329         return ret;
330 }
331
332 static void messaging_dgm_recv(struct unix_msg_ctx *ctx,
333                                uint8_t *msg, size_t msg_len,
334                                int *fds, size_t num_fds,
335                                void *private_data)
336 {
337         struct messaging_dgm_context *dgm_ctx = talloc_get_type_abort(
338                 private_data, struct messaging_dgm_context);
339
340         dgm_ctx->recv_cb(msg, msg_len, fds, num_fds,
341                          dgm_ctx->recv_cb_private_data);
342 }
343
344 static int messaging_dgm_read_unique(int fd, uint64_t *punique)
345 {
346         char buf[25];
347         ssize_t rw_ret;
348         unsigned long long unique;
349         char *endptr;
350
351         rw_ret = pread(fd, buf, sizeof(buf)-1, 0);
352         if (rw_ret == -1) {
353                 return errno;
354         }
355         buf[rw_ret] = '\0';
356
357         unique = strtoull(buf, &endptr, 10);
358         if ((unique == 0) && (errno == EINVAL)) {
359                 return EINVAL;
360         }
361         if ((unique == ULLONG_MAX) && (errno == ERANGE)) {
362                 return ERANGE;
363         }
364         if (endptr[0] != '\n') {
365                 return EINVAL;
366         }
367         *punique = unique;
368         return 0;
369 }
370
371 int messaging_dgm_get_unique(pid_t pid, uint64_t *unique)
372 {
373         struct messaging_dgm_context *ctx = global_dgm_context;
374         struct sun_path_buf lockfile_name;
375         int ret, fd;
376
377         if (ctx == NULL) {
378                 return EBADF;
379         }
380
381         if (pid == getpid()) {
382                 /*
383                  * Protect against losing our own lock
384                  */
385                 return messaging_dgm_read_unique(ctx->lockfile_fd, unique);
386         }
387
388         ret = snprintf(lockfile_name.buf, sizeof(lockfile_name.buf),
389                        "%s/%u", ctx->lockfile_dir.buf, (int)pid);
390         if (ret < 0) {
391                 return errno;
392         }
393         if ((size_t)ret >= sizeof(lockfile_name.buf)) {
394                 return ENAMETOOLONG;
395         }
396
397         fd = open(lockfile_name.buf, O_NONBLOCK|O_RDONLY, 0);
398         if (fd == -1) {
399                 return errno;
400         }
401
402         ret = messaging_dgm_read_unique(fd, unique);
403         close(fd);
404         return ret;
405 }
406
407 int messaging_dgm_cleanup(pid_t pid)
408 {
409         struct messaging_dgm_context *ctx = global_dgm_context;
410         struct sun_path_buf lockfile_name, socket_name;
411         int fd, len, ret;
412         struct flock lck = {};
413
414         if (ctx == NULL) {
415                 return ENOTCONN;
416         }
417
418         len = snprintf(socket_name.buf, sizeof(socket_name.buf), "%s/%u",
419                        ctx->socket_dir.buf, (unsigned)pid);
420         if (len < 0) {
421                 return errno;
422         }
423         if ((size_t)len >= sizeof(socket_name.buf)) {
424                 return ENAMETOOLONG;
425         }
426
427         len = snprintf(lockfile_name.buf, sizeof(lockfile_name.buf), "%s/%u",
428                        ctx->lockfile_dir.buf, (unsigned)pid);
429         if (len < 0) {
430                 return errno;
431         }
432         if ((size_t)len >= sizeof(lockfile_name.buf)) {
433                 return ENAMETOOLONG;
434         }
435
436         fd = open(lockfile_name.buf, O_NONBLOCK|O_WRONLY, 0);
437         if (fd == -1) {
438                 ret = errno;
439                 if (ret != ENOENT) {
440                         DEBUG(10, ("%s: open(%s) failed: %s\n", __func__,
441                                    lockfile_name.buf, strerror(ret)));
442                 }
443                 return ret;
444         }
445
446         lck.l_type = F_WRLCK;
447         lck.l_whence = SEEK_SET;
448         lck.l_start = 0;
449         lck.l_len = 0;
450
451         ret = fcntl(fd, F_SETLK, &lck);
452         if (ret != 0) {
453                 ret = errno;
454                 if ((ret != EACCES) && (ret != EAGAIN)) {
455                         DEBUG(10, ("%s: Could not get lock: %s\n", __func__,
456                                    strerror(ret)));
457                 }
458                 close(fd);
459                 return ret;
460         }
461
462         DEBUG(10, ("%s: Cleaning up : %s\n", __func__, strerror(ret)));
463
464         (void)unlink(socket_name.buf);
465         (void)unlink(lockfile_name.buf);
466         (void)close(fd);
467         return 0;
468 }
469
470 int messaging_dgm_wipe(void)
471 {
472         struct messaging_dgm_context *ctx = global_dgm_context;
473         DIR *msgdir;
474         struct dirent *dp;
475         pid_t our_pid = getpid();
476         int ret;
477
478         if (ctx == NULL) {
479                 return ENOTCONN;
480         }
481
482         /*
483          * We scan the socket directory and not the lock directory. Otherwise
484          * we would race against messaging_dgm_lockfile_create's open(O_CREAT)
485          * and fcntl(SETLK).
486          */
487
488         msgdir = opendir(ctx->socket_dir.buf);
489         if (msgdir == NULL) {
490                 return errno;
491         }
492
493         while ((dp = readdir(msgdir)) != NULL) {
494                 unsigned long pid;
495
496                 pid = strtoul(dp->d_name, NULL, 10);
497                 if (pid == 0) {
498                         /*
499                          * . and .. and other malformed entries
500                          */
501                         continue;
502                 }
503                 if ((pid_t)pid == our_pid) {
504                         /*
505                          * fcntl(F_GETLK) will succeed for ourselves, we hold
506                          * that lock ourselves.
507                          */
508                         continue;
509                 }
510
511                 ret = messaging_dgm_cleanup(pid);
512                 DEBUG(10, ("messaging_dgm_cleanup(%lu) returned %s\n",
513                            pid, ret ? strerror(ret) : "ok"));
514         }
515         closedir(msgdir);
516
517         return 0;
518 }
519
520 void *messaging_dgm_register_tevent_context(TALLOC_CTX *mem_ctx,
521                                             struct tevent_context *ev)
522 {
523         struct messaging_dgm_context *ctx = global_dgm_context;
524
525         if (ctx == NULL) {
526                 return NULL;
527         }
528         return poll_funcs_tevent_register(mem_ctx, ctx->msg_callbacks, ev);
529 }