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