LCOV - code coverage report
Current view: top level - source4/wrepl_server - wrepl_out_push.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 9 63 14.3 %
Date: 2024-04-21 15:09:00 Functions: 1 4 25.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    
       4             :    WINS Replication server
       5             :    
       6             :    Copyright (C) Stefan Metzmacher      2005
       7             :    
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "librpc/gen_ndr/winsrepl.h"
      24             : #include "wrepl_server/wrepl_server.h"
      25             : #include "libcli/composite/composite.h"
      26             : #include "nbt_server/wins/winsdb.h"
      27             : 
      28             : static void wreplsrv_out_partner_push(struct wreplsrv_partner *partner, bool propagate);
      29             : 
      30           0 : static void wreplsrv_push_handler_creq(struct composite_context *creq)
      31             : {
      32           0 :         struct wreplsrv_partner *partner = talloc_get_type(creq->async.private_data, struct wreplsrv_partner);
      33           0 :         struct wreplsrv_push_notify_io *old_notify_io;
      34             : 
      35           0 :         partner->push.last_status = wreplsrv_push_notify_recv(partner->push.creq);
      36           0 :         partner->push.creq = NULL;
      37             : 
      38           0 :         old_notify_io = partner->push.notify_io;
      39           0 :         partner->push.notify_io = NULL;
      40             : 
      41           0 :         if (NT_STATUS_IS_OK(partner->push.last_status)) {
      42           0 :                 partner->push.error_count = 0;
      43           0 :                 DEBUG(2,("wreplsrv_push_notify(%s): %s\n",
      44             :                          partner->address, nt_errstr(partner->push.last_status)));
      45           0 :                 goto done;
      46             :         }
      47             : 
      48           0 :         partner->push.error_count++;
      49             : 
      50           0 :         if (partner->push.error_count > 1) {
      51           0 :                 DEBUG(1,("wreplsrv_push_notify(%s): %s: error_count: %u: giving up\n",
      52             :                          partner->address, nt_errstr(partner->push.last_status),
      53             :                          partner->push.error_count));
      54           0 :                 goto done;
      55             :         }
      56             : 
      57           0 :         DEBUG(1,("wreplsrv_push_notify(%s): %s: error_count: %u: retry\n",
      58             :                  partner->address, nt_errstr(partner->push.last_status),
      59             :                  partner->push.error_count));
      60           0 :         wreplsrv_out_partner_push(partner, old_notify_io->in.propagate);
      61           0 : done:
      62           0 :         talloc_free(old_notify_io);
      63           0 : }
      64             : 
      65           0 : static void wreplsrv_out_partner_push(struct wreplsrv_partner *partner, bool propagate)
      66             : {
      67             :         /* a push for this partner is currently in progress, so we're done */
      68           0 :         if (partner->push.creq) return;
      69             : 
      70             :         /* now prepare the push notify */
      71           0 :         partner->push.notify_io = talloc(partner, struct wreplsrv_push_notify_io);
      72           0 :         if (!partner->push.notify_io) {
      73           0 :                 goto nomem;
      74             :         }
      75             : 
      76           0 :         partner->push.notify_io->in.partner       = partner;
      77           0 :         partner->push.notify_io->in.inform        = partner->push.use_inform;
      78           0 :         partner->push.notify_io->in.propagate     = propagate;
      79           0 :         partner->push.creq = wreplsrv_push_notify_send(partner->push.notify_io, partner->push.notify_io);
      80           0 :         if (!partner->push.creq) {
      81           0 :                 DEBUG(1,("wreplsrv_push_notify_send(%s) failed nomem?\n",
      82             :                          partner->address));
      83           0 :                 goto nomem;
      84             :         }
      85             : 
      86           0 :         partner->push.creq->async.fn              = wreplsrv_push_handler_creq;
      87           0 :         partner->push.creq->async.private_data    = partner;
      88             : 
      89           0 :         return;
      90           0 : nomem:
      91           0 :         talloc_free(partner->push.notify_io);
      92           0 :         partner->push.notify_io = NULL;
      93           0 :         DEBUG(1,("wreplsrv_out_partner_push(%s,%u) failed nomem? (ignoring)\n",
      94             :                  partner->address, propagate));
      95           0 :         return;
      96             : }
      97             : 
      98           0 : static uint32_t wreplsrv_calc_change_count(struct wreplsrv_partner *partner, uint64_t maxVersionID)
      99             : {
     100           0 :         uint64_t tmp_diff = UINT32_MAX;
     101             : 
     102             :         /* catch an overflow */
     103           0 :         if (partner->push.maxVersionID > maxVersionID) {
     104           0 :                 goto done;
     105             :         }
     106             : 
     107           0 :         tmp_diff = maxVersionID - partner->push.maxVersionID;
     108             : 
     109           0 :         if (tmp_diff > UINT32_MAX) {
     110           0 :                 tmp_diff = UINT32_MAX;
     111           0 :                 goto done;
     112             :         }
     113             : 
     114           0 : done:
     115           0 :         partner->push.maxVersionID = maxVersionID;
     116           0 :         return (uint32_t)(tmp_diff & UINT32_MAX);
     117             : }
     118             : 
     119        3626 : NTSTATUS wreplsrv_out_push_run(struct wreplsrv_service *service)
     120             : {
     121          31 :         struct wreplsrv_partner *partner;
     122          31 :         uint64_t seqnumber;
     123          31 :         uint32_t change_count;
     124             : 
     125        3626 :         seqnumber = winsdb_get_maxVersion(service->wins_db);
     126             : 
     127        6736 :         for (partner = service->partners; partner; partner = partner->next) {
     128             :                 /* if it's not a push partner, go to the next partner */
     129        3110 :                 if (!(partner->type & WINSREPL_PARTNER_PUSH)) continue;
     130             : 
     131             :                 /* if push notifies are disabled for this partner, go to the next partner */
     132        3110 :                 if (partner->push.change_count == 0) continue;
     133             : 
     134             :                 /* get the actual change count for the partner */
     135           0 :                 change_count = wreplsrv_calc_change_count(partner, seqnumber);
     136             : 
     137             :                 /* if the configured change count isn't reached, go to the next partner */
     138           0 :                 if (change_count < partner->push.change_count) continue;
     139             : 
     140           0 :                 wreplsrv_out_partner_push(partner, false);
     141             :         }
     142             : 
     143        3626 :         return NT_STATUS_OK;
     144             : }

Generated by: LCOV version 1.14