LCOV - code coverage report
Current view: top level - source3/smbd - notify_msg.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 73 86 84.9 %
Date: 2021-08-25 13:27:56 Functions: 6 6 100.0 %

          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       17321 : 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             :         struct server_id_db *names_db;
      57             :         struct notify_context *ctx;
      58             :         NTSTATUS status;
      59             : 
      60       17321 :         ctx = talloc(mem_ctx, struct notify_context);
      61       17321 :         if (ctx == NULL) {
      62           0 :                 return NULL;
      63             :         }
      64       17321 :         ctx->msg_ctx = msg;
      65             : 
      66       17321 :         ctx->sconn = sconn;
      67       17321 :         ctx->callback = callback;
      68             : 
      69       17321 :         names_db = messaging_names_db(msg);
      70       17321 :         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             :                 struct server_id_buf tmp;
      79       17321 :                 DBG_DEBUG("notifyd=%s\n",
      80             :                           server_id_str_buf(ctx->notifyd, &tmp));
      81             :         }
      82             : 
      83       17321 :         if (callback != NULL) {
      84       17321 :                 status = messaging_register(msg, ctx, MSG_PVFS_NOTIFY,
      85             :                                             notify_handler);
      86       17321 :                 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       17321 :         talloc_set_destructor(ctx, notify_context_destructor);
      95             : 
      96       17321 :         return ctx;
      97             : }
      98             : 
      99       17307 : static int notify_context_destructor(struct notify_context *ctx)
     100             : {
     101       17307 :         if (ctx->callback != NULL) {
     102       17307 :                 messaging_deregister(ctx->msg_ctx, MSG_PVFS_NOTIFY, ctx);
     103             :         }
     104             : 
     105       17307 :         return 0;
     106             : }
     107             : 
     108        1953 : 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        1953 :         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;
     116             : 
     117        1953 :         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        1953 :         if (data->data[data->length-1] != 0) {
     122           0 :                 DBG_WARNING("path not 0-terminated\n");
     123           0 :                 return;
     124             :         }
     125             : 
     126        1953 :         event_msg = (struct notify_event_msg *)data->data;
     127             : 
     128        1953 :         event.action = event_msg->action;
     129        1953 :         event.path = event_msg->path;
     130        1953 :         event.private_data = event_msg->private_data;
     131             : 
     132        1953 :         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        1953 :         ctx->callback(ctx->sconn, event.private_data, event_msg->when, &event);
     139             : }
     140             : 
     141        1850 : NTSTATUS notify_add(struct notify_context *ctx,
     142             :                     const char *path, uint32_t filter, uint32_t subdir_filter,
     143             :                     void *private_data)
     144             : {
     145        1850 :         struct notify_rec_change_msg msg = {};
     146             :         struct iovec iov[2];
     147             :         size_t pathlen;
     148             :         NTSTATUS status;
     149             : 
     150        1850 :         if (ctx == NULL) {
     151           2 :                 return NT_STATUS_NOT_IMPLEMENTED;
     152             :         }
     153             : 
     154        1848 :         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        1848 :         pathlen = strlen(path)+1;
     162             : 
     163        1848 :         clock_gettime_mono(&msg.instance.creation_time);
     164        1848 :         msg.instance.filter = filter;
     165        1848 :         msg.instance.subdir_filter = subdir_filter;
     166        1848 :         msg.instance.private_data = private_data;
     167             : 
     168        1848 :         iov[0].iov_base = &msg;
     169        1848 :         iov[0].iov_len = offsetof(struct notify_rec_change_msg, path);
     170        1848 :         iov[1].iov_base = discard_const_p(char, path);
     171        1848 :         iov[1].iov_len = pathlen;
     172             : 
     173        1848 :         status =  messaging_send_iov(
     174             :                 ctx->msg_ctx, ctx->notifyd, MSG_SMB_NOTIFY_REC_CHANGE,
     175             :                 iov, ARRAY_SIZE(iov), NULL, 0);
     176             : 
     177        1848 :         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        1848 :         return NT_STATUS_OK;
     184             : }
     185             : 
     186        1850 : NTSTATUS notify_remove(struct notify_context *ctx, void *private_data,
     187             :                        char *path)
     188             : {
     189        1850 :         struct notify_rec_change_msg msg = {};
     190             :         struct iovec iov[2];
     191             :         NTSTATUS status;
     192             : 
     193             :         /* see if change notify is enabled at all */
     194        1850 :         if (ctx == NULL) {
     195           2 :                 return NT_STATUS_NOT_IMPLEMENTED;
     196             :         }
     197             : 
     198        1848 :         msg.instance.private_data = private_data;
     199             : 
     200        1848 :         iov[0].iov_base = &msg;
     201        1848 :         iov[0].iov_len = offsetof(struct notify_rec_change_msg, path);
     202        1848 :         iov[1].iov_base = path;
     203        1848 :         iov[1].iov_len = strlen(path)+1;
     204             : 
     205        1848 :         status = messaging_send_iov(
     206             :                 ctx->msg_ctx, ctx->notifyd, MSG_SMB_NOTIFY_REC_CHANGE,
     207             :                 iov, ARRAY_SIZE(iov), NULL, 0);
     208             : 
     209        1848 :         return status;
     210             : }
     211             : 
     212      384916 : void notify_trigger(struct notify_context *ctx,
     213             :                     uint32_t action, uint32_t filter,
     214             :                     const char *dir, const char *name)
     215             : {
     216             :         struct notify_trigger_msg msg;
     217             :         struct iovec iov[4];
     218      384916 :         char slash = '/';
     219             : 
     220      384916 :         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      384916 :         if (ctx == NULL) {
     228       80338 :                 return;
     229             :         }
     230             : 
     231      304578 :         msg.when = timespec_current();
     232      304578 :         msg.action = action;
     233      304578 :         msg.filter = filter;
     234             : 
     235      304578 :         iov[0].iov_base = &msg;
     236      304578 :         iov[0].iov_len = offsetof(struct notify_trigger_msg, path);
     237      304578 :         iov[1].iov_base = discard_const_p(char, dir);
     238      304578 :         iov[1].iov_len = strlen(dir);
     239      304578 :         iov[2].iov_base = &slash;
     240      304578 :         iov[2].iov_len = 1;
     241      304578 :         iov[3].iov_base = discard_const_p(char, name);
     242      304578 :         iov[3].iov_len = strlen(name)+1;
     243             : 
     244      304578 :         messaging_send_iov(
     245             :                 ctx->msg_ctx, ctx->notifyd, MSG_SMB_NOTIFY_TRIGGER,
     246             :                 iov, ARRAY_SIZE(iov), NULL, 0);
     247             : }

Generated by: LCOV version 1.13