~ubuntu-branches/ubuntu/wily/389-ds-base/wily

« back to all changes in this revision

Viewing changes to ldap/servers/slapd/snmp_collator.c

  • Committer: Package Import Robot
  • Author(s): Krzysztof Klimonda
  • Date: 2012-03-27 14:26:16 UTC
  • Revision ID: package-import@ubuntu.com-20120327142616-xt24t6nffm3f7ybz
Tags: upstream-1.2.11.7
ImportĀ upstreamĀ versionĀ 1.2.11.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** BEGIN COPYRIGHT BLOCK
 
2
 * This Program is free software; you can redistribute it and/or modify it under
 
3
 * the terms of the GNU General Public License as published by the Free Software
 
4
 * Foundation; version 2 of the License.
 
5
 * 
 
6
 * This Program is distributed in the hope that it will be useful, but WITHOUT
 
7
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 
8
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 
9
 * 
 
10
 * You should have received a copy of the GNU General Public License along with
 
11
 * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
12
 * Place, Suite 330, Boston, MA 02111-1307 USA.
 
13
 * 
 
14
 * In addition, as a special exception, Red Hat, Inc. gives You the additional
 
15
 * right to link the code of this Program with code not covered under the GNU
 
16
 * General Public License ("Non-GPL Code") and to distribute linked combinations
 
17
 * including the two, subject to the limitations in this paragraph. Non-GPL Code
 
18
 * permitted under this exception must only link to the code of this Program
 
19
 * through those well defined interfaces identified in the file named EXCEPTION
 
20
 * found in the source code files (the "Approved Interfaces"). The files of
 
21
 * Non-GPL Code may instantiate templates or use macros or inline functions from
 
22
 * the Approved Interfaces without causing the resulting work to be covered by
 
23
 * the GNU General Public License. Only Red Hat, Inc. may make changes or
 
24
 * additions to the list of Approved Interfaces. You must obey the GNU General
 
25
 * Public License in all respects for all of the Program code and other code used
 
26
 * in conjunction with the Program except the Non-GPL Code covered by this
 
27
 * exception. If you modify this file, you may extend this exception to your
 
28
 * version of the file, but you are not obligated to do so. If you do not wish to
 
29
 * provide this exception without modification, you must delete this exception
 
30
 * statement from your version and license this file solely under the GPL without
 
31
 * exception. 
 
32
 * 
 
33
 * 
 
34
 * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
 
35
 * Copyright (C) 2005 Red Hat, Inc.
 
36
 * All rights reserved.
 
37
 * END COPYRIGHT BLOCK **/
 
38
 
 
39
#ifdef HAVE_CONFIG_H
 
40
#  include <config.h>
 
41
#endif
 
42
 
 
43
#include <stdio.h>
 
44
#include <stdlib.h>
 
45
#include <sys/types.h>
 
46
#include <sys/stat.h>
 
47
#ifndef  _WIN32
 
48
#include <sys/ipc.h>
 
49
#include <sys/msg.h>
 
50
#include <dirent.h>
 
51
#include <semaphore.h>
 
52
#endif
 
53
#include <time.h>
 
54
#include <signal.h>
 
55
#include <string.h>
 
56
#include <errno.h>
 
57
 
 
58
#include "agtmmap.h"
 
59
#include "slap.h"
 
60
#include "prthread.h"
 
61
#include "prlock.h"
 
62
#include "prerror.h"
 
63
#include "prcvar.h"
 
64
#include "plstr.h"
 
65
 
 
66
#ifdef HPUX
 
67
/* HP-UX doesn't define SEM_FAILED like other platforms, so
 
68
 * we define it ourselves. */
 
69
#define SEM_FAILED ((sem_t *)(-1))
 
70
#endif
 
71
 
 
72
#define SNMP_NUM_SEM_WAITS 10
 
73
 
 
74
#include "snmp_collator.h" 
 
75
#include "../snmp/ntagt/nslagtcom_nt.h"
 
76
 
 
77
/* stevross: safe to assume port should be at most 5 digits ? */
 
78
#define PORT_LEN 5
 
79
/* strlen of url portions ie "ldap://:/" */
 
80
#define URL_CHARS_LEN 9 
 
81
 
 
82
static char *make_ds_url(char *host, int port);
 
83
#ifdef DEBUG_SNMP_INTERACTION
 
84
static void print_snmp_interaction_table();
 
85
#endif /* DEBUG_SNMP_INTERACTION */
 
86
static int search_interaction_table(char *dsURL, int *isnew);
 
87
static void loadConfigStats();
 
88
static Slapi_Entry *getConfigEntry( Slapi_Entry **e );
 
89
static void freeConfigEntry( Slapi_Entry **e );
 
90
static void snmp_update_ops_table();
 
91
static void snmp_update_entries_table();
 
92
static void snmp_update_interactions_table();
 
93
static void snmp_update_cache_stats();
 
94
static void snmp_collator_create_semaphore();
 
95
static void snmp_collator_sem_wait();
 
96
 
 
97
/* snmp stats stuff */
 
98
struct agt_stats_t *stats=NULL;
 
99
 
 
100
/* mmap stuff */
 
101
static int hdl;
 
102
 
 
103
/* collator stuff */
 
104
static char *tmpstatsfile = AGT_STATS_FILE;
 
105
#ifdef _WIN32
 
106
static TCHAR szStatsFile[_MAX_PATH];
 
107
static TCHAR szTempDir[_MAX_PATH];
 
108
static HANDLE hParentProcess = NULL;
 
109
static HANDLE hStatSlot = NULL;
 
110
static HANDLE hLogFile = INVALID_HANDLE_VALUE;
 
111
static TCHAR szSpoolRootDir[_MAX_PATH];
 
112
#else
 
113
static char szStatsFile[_MAX_PATH];
 
114
static char stats_sem_name[_MAX_PATH];
 
115
#endif /* _WIN32*/
 
116
static Slapi_Eq_Context snmp_eq_ctx;
 
117
static int snmp_collator_stopped = 0;
 
118
 
 
119
/* synchronization stuff */
 
120
static PRLock           *interaction_table_mutex;
 
121
static sem_t            *stats_sem;
 
122
 
 
123
 
 
124
/***********************************************************************************
 
125
*
 
126
* int snmp_collator_init()
 
127
*
 
128
*       initializes the global variables used by snmp
 
129
*
 
130
************************************************************************************/
 
131
 
 
132
static int snmp_collator_init(){
 
133
        int i;
 
134
 
 
135
        /*
 
136
         * Create the global SNMP counters
 
137
         */
 
138
        g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds              = slapi_counter_new();
 
139
        g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds                 = slapi_counter_new();
 
140
        g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds             = slapi_counter_new();
 
141
        g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds             = slapi_counter_new();
 
142
        g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors          = slapi_counter_new();
 
143
        g_get_global_snmp_vars()->ops_tbl.dsInOps                       = slapi_counter_new();
 
144
        g_get_global_snmp_vars()->ops_tbl.dsReadOps                     = slapi_counter_new();
 
145
        g_get_global_snmp_vars()->ops_tbl.dsCompareOps                  = slapi_counter_new();
 
146
        g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps                 = slapi_counter_new();
 
147
        g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps              = slapi_counter_new();
 
148
        g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps              = slapi_counter_new();
 
149
        g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps                = slapi_counter_new();
 
150
        g_get_global_snmp_vars()->ops_tbl.dsListOps                     = slapi_counter_new();
 
151
        g_get_global_snmp_vars()->ops_tbl.dsSearchOps                   = slapi_counter_new();
 
152
        g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps           = slapi_counter_new();
 
153
        g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps       = slapi_counter_new();
 
154
        g_get_global_snmp_vars()->ops_tbl.dsReferrals                   = slapi_counter_new();
 
155
        g_get_global_snmp_vars()->ops_tbl.dsChainings                   = slapi_counter_new();
 
156
        g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors              = slapi_counter_new();
 
157
        g_get_global_snmp_vars()->ops_tbl.dsErrors                      = slapi_counter_new();
 
158
        g_get_global_snmp_vars()->ops_tbl.dsConnections                 = slapi_counter_new();
 
159
        g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq               = slapi_counter_new();
 
160
        g_get_global_snmp_vars()->ops_tbl.dsBytesRecv                   = slapi_counter_new();
 
161
        g_get_global_snmp_vars()->ops_tbl.dsBytesSent                   = slapi_counter_new();
 
162
        g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned             = slapi_counter_new();
 
163
        g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned           = slapi_counter_new();
 
164
        g_get_global_snmp_vars()->entries_tbl.dsMasterEntries           = slapi_counter_new();
 
165
        g_get_global_snmp_vars()->entries_tbl.dsCopyEntries             = slapi_counter_new();
 
166
        g_get_global_snmp_vars()->entries_tbl.dsCacheEntries            = slapi_counter_new();
 
167
        g_get_global_snmp_vars()->entries_tbl.dsCacheHits               = slapi_counter_new();
 
168
        g_get_global_snmp_vars()->entries_tbl.dsSlaveHits               = slapi_counter_new();
 
169
 
 
170
        /* Initialize the global interaction table */
 
171
        for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++)
 
172
        {
 
173
                g_get_global_snmp_vars()->int_tbl[i].dsIntIndex                    = i + 1;
 
174
                strncpy(g_get_global_snmp_vars()->int_tbl[i].dsName, "Not Available",
 
175
                        sizeof(g_get_global_snmp_vars()->int_tbl[i].dsName));
 
176
                g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation              = 0;
 
177
                g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt           = 0;
 
178
                g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess           = 0;
 
179
                g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess    = 0;
 
180
                g_get_global_snmp_vars()->int_tbl[i].dsFailures                    = 0;
 
181
                g_get_global_snmp_vars()->int_tbl[i].dsSuccesses                   = 0;
 
182
                strncpy(g_get_global_snmp_vars()->int_tbl[i].dsURL, "Not Available",
 
183
                        sizeof(g_get_global_snmp_vars()->int_tbl[i].dsURL));
 
184
        }
 
185
 
 
186
        /* Get the semaphore */
 
187
        snmp_collator_sem_wait();
 
188
 
 
189
        /* Initialize the mmap structure */
 
190
        memset((void *) stats, 0, sizeof(*stats));
 
191
 
 
192
        /* Load header stats table */
 
193
        strncpy(stats->hdr_stats.dsVersion, SLAPD_VERSION_STR,
 
194
                (sizeof(stats->hdr_stats.dsVersion)/sizeof(char)) - 1);
 
195
        stats->hdr_stats.restarted = 0;                  
 
196
        stats->hdr_stats.startTime = time(0);           /* This is a bit off, hope it's ok */
 
197
        loadConfigStats();
 
198
 
 
199
        /* update the mmap'd tables */
 
200
        snmp_update_ops_table();
 
201
        snmp_update_entries_table();
 
202
        snmp_update_interactions_table();
 
203
 
 
204
        /* Release the semaphore */
 
205
        sem_post(stats_sem);
 
206
 
 
207
        /* create lock for interaction table */
 
208
        interaction_table_mutex = PR_NewLock();
 
209
 
 
210
        return 0;
 
211
}
 
212
 
 
213
 
 
214
 
 
215
/***********************************************************************************
 
216
 * given the name, whether or not it was successful and the URL updates snmp 
 
217
 * interaction table appropriately
 
218
 *
 
219
 *
 
220
************************************************************************************/
 
221
 
 
222
void set_snmp_interaction_row(char *host, int port, int error)
 
223
{
 
224
  int index;
 
225
  int isnew;
 
226
  char *dsName;
 
227
  char *dsURL;
 
228
 
 
229
  /* stevross: our servers don't have a concept of dsName as a distinguished name
 
230
               as specified in the MIB. Make this "Not Available" for now waiting for
 
231
               sometime in the future when we do
 
232
   */
 
233
               
 
234
               
 
235
  dsName = "Not Available";
 
236
 
 
237
  dsURL= make_ds_url(host, port);
 
238
 
 
239
  /* lock around here to avoid race condition of two threads trying to update table at same time */
 
240
  PR_Lock(interaction_table_mutex);     
 
241
      index = search_interaction_table(dsURL, &isnew);
 
242
  
 
243
      if(isnew){
 
244
          /* fillin the new row from scratch*/
 
245
          g_get_global_snmp_vars()->int_tbl[index].dsIntIndex                     = index;
 
246
          strncpy(g_get_global_snmp_vars()->int_tbl[index].dsName, dsName,
 
247
                  sizeof(g_get_global_snmp_vars()->int_tbl[index].dsName));
 
248
          g_get_global_snmp_vars()->int_tbl[index].dsTimeOfCreation               = time(0);
 
249
          g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt            = time(0);
 
250
          if(error == 0){
 
251
              g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess        = time(0);
 
252
              g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 0;
 
253
              g_get_global_snmp_vars()->int_tbl[index].dsFailures                 = 0;
 
254
              g_get_global_snmp_vars()->int_tbl[index].dsSuccesses                = 1;
 
255
          }else{
 
256
              g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess        = 0;
 
257
              g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 1;
 
258
              g_get_global_snmp_vars()->int_tbl[index].dsFailures                 = 1;
 
259
              g_get_global_snmp_vars()->int_tbl[index].dsSuccesses                = 0;
 
260
          }
 
261
          strncpy(g_get_global_snmp_vars()->int_tbl[index].dsURL, dsURL,
 
262
                  sizeof(g_get_global_snmp_vars()->int_tbl[index].dsURL));                       
 
263
      }else{
 
264
        /* just update the appropriate fields */
 
265
           g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastAttempt          = time(0);
 
266
          if(error == 0){
 
267
             g_get_global_snmp_vars()->int_tbl[index].dsTimeOfLastSuccess        = time(0);
 
268
             g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess = 0;
 
269
             g_get_global_snmp_vars()->int_tbl[index].dsSuccesses                += 1;
 
270
          }else{
 
271
             g_get_global_snmp_vars()->int_tbl[index].dsFailuresSinceLastSuccess +=1;
 
272
             g_get_global_snmp_vars()->int_tbl[index].dsFailures                 +=1;
 
273
          }
 
274
 
 
275
      }
 
276
  PR_Unlock(interaction_table_mutex);     
 
277
  /* free the memory allocated for dsURL in call to ds_make_url */
 
278
  if(dsURL != NULL){
 
279
    slapi_ch_free( (void**)&dsURL );
 
280
  }
 
281
}
 
282
 
 
283
/***********************************************************************************
 
284
 * Given: host and port
 
285
 * Returns: ldapUrl in form of
 
286
 *    ldap://host.mcom.com:port/
 
287
 * 
 
288
 *    this should point to root DSE 
 
289
************************************************************************************/
 
290
static char *make_ds_url(char *host, int port){
 
291
 
 
292
  char *url;
 
293
  
 
294
   url = slapi_ch_smprintf("ldap://%s:%d/",host, port);
 
295
 
 
296
   return url;
 
297
}
 
298
 
 
299
 
 
300
/***********************************************************************************
 
301
 * searches the table for the url specified 
 
302
 * If there, returns index to update stats
 
303
 * if, not there returns index of oldest interaction, and isnew flag is set
 
304
 * so caller can rewrite this row
 
305
************************************************************************************/
 
306
 
 
307
static int search_interaction_table(char *dsURL, int *isnew)
 
308
{
 
309
  int i;
 
310
  int index = 0;
 
311
  time_t oldestattempt;
 
312
  time_t currentattempt;
 
313
   
 
314
   oldestattempt = g_get_global_snmp_vars()->int_tbl[0].dsTimeOfLastAttempt;
 
315
   *isnew = 1;
 
316
   
 
317
   for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++){
 
318
       if(!strcmp(g_get_global_snmp_vars()->int_tbl[i].dsURL, "Not Available"))
 
319
       {
 
320
           /* found it -- this is new, first time for this row */
 
321
           index = i;
 
322
           break;
 
323
       }else  if(!strcmp(g_get_global_snmp_vars()->int_tbl[i].dsURL, dsURL)){
 
324
           /* found it  -- it was already there*/
 
325
           *isnew = 0;
 
326
           index = i;
 
327
           break;
 
328
       }else{
 
329
          /* not found so figure out oldest row */ 
 
330
          currentattempt = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt;
 
331
         
 
332
          if(currentattempt <= oldestattempt){
 
333
              index=i;
 
334
              oldestattempt = currentattempt;
 
335
          }
 
336
       }
 
337
 
 
338
   }
 
339
   
 
340
   return index;
 
341
 
 
342
}
 
343
 
 
344
#ifdef DEBUG_SNMP_INTERACTION
 
345
/* for debuging until subagent part working, print contents of interaction table */
 
346
static void print_snmp_interaction_table()
 
347
 
348
  int i;
 
349
  for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++)
 
350
  {
 
351
    fprintf(stderr, "                dsIntIndex: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsIntIndex);
 
352
    fprintf(stderr, "                    dsName: %s \n",   g_get_global_snmp_vars()->int_tbl[i].dsName);
 
353
    fprintf(stderr, "          dsTimeOfCreation: %ld \n", g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation);
 
354
    fprintf(stderr, "       dsTimeOfLastAttempt: %ld \n", g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt);
 
355
    fprintf(stderr, "       dsTimeOfLastSuccess: %ld \n", g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess);
 
356
    fprintf(stderr, "dsFailuresSinceLastSuccess: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess);
 
357
    fprintf(stderr, "                dsFailures: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsFailures);
 
358
    fprintf(stderr, "               dsSuccesses: %d \n", g_get_global_snmp_vars()->int_tbl[i].dsSuccesses);
 
359
    fprintf(stderr, "                     dsURL: %s \n", g_get_global_snmp_vars()->int_tbl[i].dsURL);
 
360
    fprintf(stderr, "\n");
 
361
  }
 
362
}
 
363
#endif /* DEBUG_SNMP_INTERACTION */
 
364
 
 
365
/*-------------------------------------------------------------------------
 
366
 *
 
367
 * sc_setevent:  Sets the specified event (NT only).  The input event has
 
368
 *               to be created by the subagent during its initialization.
 
369
 *
 
370
 * Returns:  None
 
371
 *
 
372
 *-----------------------------------------------------------------------*/
 
373
 
 
374
#ifdef _WIN32
 
375
void sc_setevent(char *ev)
 
376
{
 
377
  HANDLE hTrapEvent;
 
378
  DWORD err = NO_ERROR;
 
379
  
 
380
  /*
 
381
   * Set the event handle to force NT SNMP service to call the subagent
 
382
   * DLL to generate a trap.  Any error will be ignored as the subagent
 
383
   * may not have been loaded.
 
384
   */
 
385
  if ((hTrapEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, 
 
386
                              (LPCTSTR) ev)) != NULL)
 
387
  {
 
388
    if (SetEvent(hTrapEvent) == FALSE)
 
389
      err = GetLastError();
 
390
  }
 
391
  else
 
392
    err = GetLastError();
 
393
 
 
394
  if (err != NO_ERROR)
 
395
  {
 
396
          fprintf(stderr, "Failed to set trap (error = %d).\n", err);
 
397
  }
 
398
}
 
399
#endif
 
400
 
 
401
 
 
402
 
 
403
/***********************************************************************************
 
404
*
 
405
* int snmp_collator_start()
 
406
*
 
407
*   open the memory map and initialize the variables 
 
408
*       initializes the global variables used by snmp
 
409
*   
 
410
*       starts the collator thread
 
411
************************************************************************************/
 
412
 
 
413
int snmp_collator_start()
 
414
{
 
415
 
 
416
  int err;
 
417
  char *statspath = config_get_rundir();
 
418
  char *instdir = config_get_configdir();
 
419
  char *instname = NULL;
 
420
 
 
421
  /*
 
422
   * Get directory for our stats file
 
423
   */
 
424
  if (NULL == statspath) {
 
425
     statspath = slapi_ch_strdup("/tmp");
 
426
  }
 
427
 
 
428
  instname = PL_strrstr(instdir, "slapd-");
 
429
  if (!instname) {
 
430
      instname = PL_strrstr(instdir, "/");
 
431
      if (instname) {
 
432
          instname++;
 
433
      }
 
434
  }
 
435
  PR_snprintf(szStatsFile, sizeof(szStatsFile), "%s/%s%s",
 
436
              statspath, instname, AGT_STATS_EXTENSION);
 
437
  PR_snprintf(stats_sem_name, sizeof(stats_sem_name), "/%s%s",
 
438
              instname, AGT_STATS_EXTENSION);
 
439
  tmpstatsfile = szStatsFile;
 
440
  slapi_ch_free_string(&statspath);
 
441
  slapi_ch_free_string(&instdir);
 
442
 
 
443
  /* open the memory map */
 
444
  if ((err = agt_mopen_stats(tmpstatsfile, O_RDWR,  &hdl) != 0))
 
445
  {
 
446
    if (err != EEXIST)      /* Ignore if file already exists */
 
447
    {
 
448
      slapi_log_error(SLAPI_LOG_FATAL, "snmp collator", "Failed to open stats file (%s) "
 
449
                      "(error %d): %s.\n", szStatsFile, err, slapd_system_strerror(err));
 
450
      exit(1);
 
451
    }
 
452
  }
 
453
 
 
454
  /* Create semaphore for stats file access */
 
455
  snmp_collator_create_semaphore();
 
456
 
 
457
  /* point stats struct at mmap data */
 
458
  stats = (struct agt_stats_t *) mmap_tbl [hdl].fp;
 
459
 
 
460
  /* initialize stats data */
 
461
  snmp_collator_init();
 
462
 
 
463
  /* Arrange to be called back periodically to update the mmap'd stats file. */
 
464
  snmp_eq_ctx = slapi_eq_repeat(snmp_collator_update, NULL, (time_t)0,
 
465
                                SLAPD_SNMP_UPDATE_INTERVAL);
 
466
  return 0;
 
467
}
 
468
 
 
469
 
 
470
/***********************************************************************************
 
471
*
 
472
* int snmp_collator_stop()
 
473
*
 
474
*       stops the collator thread
 
475
*   closes the memory map
 
476
*   cleans up any needed memory
 
477
*       
 
478
************************************************************************************/
 
479
 
 
480
int snmp_collator_stop()
 
481
{
 
482
        int err;
 
483
 
 
484
        if (snmp_collator_stopped) {
 
485
                return 0;
 
486
        }
 
487
 
 
488
        /* Abort any pending events */
 
489
        slapi_eq_cancel(snmp_eq_ctx);
 
490
        snmp_collator_stopped = 1;
 
491
 
 
492
   /* acquire the semaphore */
 
493
   snmp_collator_sem_wait();
 
494
 
 
495
   /* close the memory map */
 
496
   if ((err = agt_mclose_stats(hdl)) != 0)
 
497
   {
 
498
        fprintf(stderr, "Failed to close stats file (%s) (error = %d).", 
 
499
            AGT_STATS_FILE, err);
 
500
   }
 
501
 
 
502
   if (remove(tmpstatsfile) != 0)
 
503
   {
 
504
       fprintf(stderr, "Failed to remove (%s) (error =  %d).\n", 
 
505
            tmpstatsfile, errno);
 
506
   }
 
507
 
 
508
   /* close and delete semaphore */
 
509
   sem_close(stats_sem);
 
510
   sem_unlink(stats_sem_name);
 
511
 
 
512
   /* delete lock */
 
513
   if (interaction_table_mutex) {
 
514
       PR_DestroyLock(interaction_table_mutex);
 
515
   }
 
516
 
 
517
#ifdef _WIN32
 
518
   /* send the event so server down trap gets set on NT */
 
519
   sc_setevent(MAGT_NSEV_SNMPTRAP);
 
520
 
 
521
#endif
 
522
   /* stevross: I probably need to free stats too... make sure to add that later */
 
523
  
 
524
return 0;
 
525
}
 
526
 
 
527
/*
 
528
 * snmp_collator_create_semaphore()
 
529
 *
 
530
 * Create a semaphore to synchronize access to the stats file with
 
531
 * the SNMP sub-agent.  NSPR doesn't support a trywait function
 
532
 * for semaphores, so we just use POSIX semaphores directly.
 
533
 */
 
534
static void
 
535
snmp_collator_create_semaphore()
 
536
{
 
537
    /* First just try to create the semaphore.  This should usually just work. */
 
538
    if ((stats_sem = sem_open(stats_sem_name, O_CREAT | O_EXCL, SLAPD_DEFAULT_FILE_MODE, 1)) == SEM_FAILED) {
 
539
        if (errno == EEXIST) {
 
540
            /* It appears that we didn't exit cleanly last time and left the semaphore
 
541
             * around.  Recreate it since we don't know what state it is in. */
 
542
            if (sem_unlink(stats_sem_name) != 0) {
 
543
                LDAPDebug( LDAP_DEBUG_ANY, "Failed to delete old semaphore for stats file (%s). "
 
544
                          "Error %d (%s).\n", szStatsFile, errno, slapd_system_strerror(errno) );
 
545
                exit(1);
 
546
            }
 
547
 
 
548
            if ((stats_sem = sem_open(stats_sem_name, O_CREAT | O_EXCL, SLAPD_DEFAULT_FILE_MODE, 1)) == SEM_FAILED) {
 
549
                /* No dice */
 
550
                LDAPDebug( LDAP_DEBUG_ANY, "Failed to create semaphore for stats file (%s). Error %d (%s).\n",
 
551
                         szStatsFile, errno, slapd_system_strerror(errno) );
 
552
                exit(1);
 
553
            }
 
554
        } else {
 
555
            /* Some other problem occurred creating the semaphore. */
 
556
            LDAPDebug( LDAP_DEBUG_ANY, "Failed to create semaphore for stats file (%s). Error %d.(%s)\n",
 
557
                     szStatsFile, errno, slapd_system_strerror(errno) );
 
558
            exit(1);
 
559
        }
 
560
    }
 
561
 
 
562
    /* If we've reached this point, everything should be good. */
 
563
    return;
 
564
}
 
565
 
 
566
/*
 
567
 * snmp_collator_sem_wait()
 
568
 *
 
569
 * A wrapper used to get the semaphore.  We don't want to block,
 
570
 * but we want to retry a specified number of times in case the
 
571
 * semaphore is help by the sub-agent.
 
572
 */
 
573
static void
 
574
snmp_collator_sem_wait()
 
575
{
 
576
    int i = 0;
 
577
    int got_sem = 0;
 
578
 
 
579
    if (SEM_FAILED == stats_sem) {
 
580
        LDAPDebug1Arg(LDAP_DEBUG_ANY, 
 
581
           "semaphore for stats file (%s) is not available.\n", szStatsFile);
 
582
        return;
 
583
    }
 
584
 
 
585
    for (i=0; i < SNMP_NUM_SEM_WAITS; i++) {
 
586
        if (sem_trywait(stats_sem) == 0) {
 
587
            got_sem = 1;
 
588
            break;
 
589
        }
 
590
        PR_Sleep(PR_SecondsToInterval(1));
 
591
    }
 
592
 
 
593
    if (!got_sem) {
 
594
        /* If we've been unable to get the semaphore, there's
 
595
         * something wrong (likely the sub-agent went out to
 
596
         * lunch).  We remove the old semaphore and recreate
 
597
         * a new one to avoid hanging up the server. */
 
598
        sem_close(stats_sem);
 
599
        sem_unlink(stats_sem_name);
 
600
        snmp_collator_create_semaphore();
 
601
    }
 
602
}
 
603
 
 
604
 
 
605
 
 
606
/***********************************************************************************
 
607
*
 
608
* int snmp_collator_update()
 
609
*
 
610
* Event callback function that updates the mmap'd stats file
 
611
* for the SNMP sub-agent.  This will use a semaphore while
 
612
* updating the stats file to prevent the SNMP sub-agent from
 
613
* reading it in the middle of an update.
 
614
*
 
615
************************************************************************************/
 
616
 
 
617
void
 
618
snmp_collator_update(time_t start_time, void *arg)
 
619
{
 
620
    if (snmp_collator_stopped) {
 
621
        return;
 
622
    }
 
623
 
 
624
    /* force an update of the backend cache stats. */
 
625
    snmp_update_cache_stats();
 
626
 
 
627
    /* get the semaphore */
 
628
    snmp_collator_sem_wait();
 
629
 
 
630
    /* just update the update time in the header */
 
631
    if( stats != NULL){
 
632
        stats->hdr_stats.updateTime = time(0);          
 
633
    }
 
634
 
 
635
    /* update the mmap'd tables */
 
636
    snmp_update_ops_table();
 
637
    snmp_update_entries_table();
 
638
    snmp_update_interactions_table();
 
639
 
 
640
    /* release the semaphore */
 
641
    sem_post(stats_sem);
 
642
}
 
643
 
 
644
/*
 
645
 * snmp_update_ops_table()
 
646
 *
 
647
 * Updates the mmap'd operations table.  The semaphore
 
648
 * should be acquired before you call this.
 
649
 */
 
650
static void
 
651
snmp_update_ops_table()
 
652
{
 
653
    stats->ops_stats.dsAnonymousBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds);
 
654
    stats->ops_stats.dsUnAuthBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds);
 
655
    stats->ops_stats.dsSimpleAuthBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds);
 
656
    stats->ops_stats.dsStrongAuthBinds = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds);
 
657
    stats->ops_stats.dsBindSecurityErrors = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors);
 
658
    stats->ops_stats.dsInOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsInOps);
 
659
    stats->ops_stats.dsReadOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReadOps);
 
660
    stats->ops_stats.dsCompareOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsCompareOps);
 
661
    stats->ops_stats.dsAddEntryOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps);
 
662
    stats->ops_stats.dsRemoveEntryOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps);
 
663
    stats->ops_stats.dsModifyEntryOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps);
 
664
    stats->ops_stats.dsModifyRDNOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps);
 
665
    stats->ops_stats.dsListOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsListOps);
 
666
    stats->ops_stats.dsSearchOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSearchOps);
 
667
    stats->ops_stats.dsOneLevelSearchOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps);
 
668
    stats->ops_stats.dsWholeSubtreeSearchOps = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps);
 
669
    stats->ops_stats.dsReferrals = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferrals);
 
670
    stats->ops_stats.dsChainings = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsChainings);
 
671
    stats->ops_stats.dsSecurityErrors = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors);
 
672
    stats->ops_stats.dsErrors = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsErrors);
 
673
    stats->ops_stats.dsConnections = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnections);
 
674
    stats->ops_stats.dsConnectionSeq = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq);
 
675
    stats->ops_stats.dsBytesRecv = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesRecv);
 
676
    stats->ops_stats.dsBytesSent = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesSent);
 
677
    stats->ops_stats.dsEntriesReturned = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned);
 
678
    stats->ops_stats.dsReferralsReturned = slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned);
 
679
}
 
680
 
 
681
/*
 
682
 * snmp_update_entries_table()
 
683
 *
 
684
 * Updated the mmap'd entries table.  The semaphore should
 
685
 * be acquired before you call this.
 
686
 */
 
687
static void
 
688
snmp_update_entries_table()
 
689
{
 
690
    stats->entries_stats.dsMasterEntries = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsMasterEntries);
 
691
    stats->entries_stats.dsCopyEntries = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCopyEntries);
 
692
    stats->entries_stats.dsCacheEntries = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries);
 
693
    stats->entries_stats.dsCacheHits = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheHits);
 
694
    stats->entries_stats.dsSlaveHits = slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsSlaveHits);
 
695
}
 
696
 
 
697
/*
 
698
 * snmp_update_interactions_table()
 
699
 *
 
700
 * Updates the mmap'd interactions table.  The semaphore should
 
701
 * be acquired before you call this.
 
702
 */
 
703
static void
 
704
snmp_update_interactions_table()
 
705
{
 
706
    int i;
 
707
 
 
708
    for(i=0; i < NUM_SNMP_INT_TBL_ROWS; i++) {
 
709
        stats->int_stats[i].dsIntIndex = i;
 
710
        strncpy(stats->int_stats[i].dsName, g_get_global_snmp_vars()->int_tbl[i].dsName,
 
711
                sizeof(stats->int_stats[i].dsName));
 
712
        stats->int_stats[i].dsTimeOfCreation = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfCreation;
 
713
        stats->int_stats[i].dsTimeOfLastAttempt = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastAttempt;
 
714
        stats->int_stats[i].dsTimeOfLastSuccess = g_get_global_snmp_vars()->int_tbl[i].dsTimeOfLastSuccess;
 
715
        stats->int_stats[i].dsFailuresSinceLastSuccess = g_get_global_snmp_vars()->int_tbl[i].dsFailuresSinceLastSuccess;
 
716
        stats->int_stats[i].dsFailures = g_get_global_snmp_vars()->int_tbl[i].dsFailures;
 
717
        stats->int_stats[i].dsSuccesses = g_get_global_snmp_vars()->int_tbl[i].dsSuccesses;
 
718
        strncpy(stats->int_stats[i].dsURL, g_get_global_snmp_vars()->int_tbl[i].dsURL,
 
719
                sizeof(stats->int_stats[i].dsURL));
 
720
    }
 
721
}
 
722
 
 
723
/*
 
724
 * snmp_update_cache_stats()
 
725
 *
 
726
 * Reads the backend cache stats from the backend monitor entry and 
 
727
 * updates the global counter used by the SNMP sub-agent as well as
 
728
 * the SNMP monitor entry.
 
729
 */
 
730
static void
 
731
snmp_update_cache_stats()
 
732
{
 
733
    Slapi_Backend       *be, *be_next;
 
734
    char                *cookie = NULL;
 
735
    Slapi_PBlock        *search_result_pb = NULL;
 
736
    Slapi_Entry         **search_entries;
 
737
    int                 search_result;
 
738
 
 
739
    /* set the cache hits/cache entries info */
 
740
    be = slapi_get_first_backend(&cookie);
 
741
    if (!be)
 
742
        return;
 
743
 
 
744
    be_next = slapi_get_next_backend(cookie);
 
745
 
 
746
    slapi_ch_free ((void **) &cookie);
 
747
 
 
748
    /* for now, only do it if there is only 1 backend, otherwise don't know 
 
749
     * which backend to pick */
 
750
    if(be_next == NULL)
 
751
    {
 
752
        Slapi_DN monitordn;
 
753
        slapi_sdn_init(&monitordn);
 
754
        be_getmonitordn(be,&monitordn);
 
755
   
 
756
        /* do a search on the monitor dn to get info */
 
757
        search_result_pb = slapi_search_internal( slapi_sdn_get_dn(&monitordn),
 
758
                LDAP_SCOPE_BASE,
 
759
                "objectclass=*", 
 
760
                NULL,
 
761
                NULL,
 
762
                0);
 
763
        slapi_sdn_done(&monitordn);
 
764
 
 
765
        slapi_pblock_get( search_result_pb, SLAPI_PLUGIN_INTOP_RESULT, &search_result);
 
766
 
 
767
        if(search_result == 0)
 
768
        {
 
769
            slapi_pblock_get( search_result_pb,SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES,
 
770
                    &search_entries);
 
771
 
 
772
            /* set the entrycachehits */
 
773
            slapi_counter_set_value(g_get_global_snmp_vars()->entries_tbl.dsCacheHits,
 
774
                    slapi_entry_attr_get_ulonglong(search_entries[0], "entrycachehits"));
 
775
                    
 
776
            /* set the currententrycachesize */
 
777
            slapi_counter_set_value(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries,
 
778
                    slapi_entry_attr_get_ulonglong(search_entries[0], "currententrycachesize"));
 
779
        }
 
780
 
 
781
        slapi_free_search_results_internal(search_result_pb);
 
782
        slapi_pblock_destroy(search_result_pb);
 
783
    }
 
784
}
 
785
 
 
786
static void
 
787
add_counter_to_value(Slapi_Entry *e, const char *type, PRUint64 countervalue)
 
788
{
 
789
        char value[40];
 
790
        PR_snprintf(value,sizeof(value),"%" NSPRIu64, countervalue);
 
791
        slapi_entry_attr_set_charptr( e, type, value);
 
792
}
 
793
 
 
794
void
 
795
snmp_as_entry(Slapi_Entry *e)
 
796
{
 
797
        add_counter_to_value(e,"AnonymousBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAnonymousBinds));
 
798
        add_counter_to_value(e,"UnAuthBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsUnAuthBinds));
 
799
        add_counter_to_value(e,"SimpleAuthBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSimpleAuthBinds));
 
800
        add_counter_to_value(e,"StrongAuthBinds", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsStrongAuthBinds));
 
801
        add_counter_to_value(e,"BindSecurityErrors", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBindSecurityErrors));
 
802
        add_counter_to_value(e,"InOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsInOps));
 
803
        add_counter_to_value(e,"ReadOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReadOps));
 
804
        add_counter_to_value(e,"CompareOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsCompareOps));
 
805
        add_counter_to_value(e,"AddEntryOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsAddEntryOps));
 
806
        add_counter_to_value(e,"RemoveEntryOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsRemoveEntryOps));
 
807
        add_counter_to_value(e,"ModifyEntryOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyEntryOps));
 
808
        add_counter_to_value(e,"ModifyRDNOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsModifyRDNOps));
 
809
        add_counter_to_value(e,"ListOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsListOps));
 
810
        add_counter_to_value(e,"SearchOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSearchOps));
 
811
        add_counter_to_value(e,"OneLevelSearchOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsOneLevelSearchOps));
 
812
        add_counter_to_value(e,"WholeSubtreeSearchOps", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsWholeSubtreeSearchOps));
 
813
        add_counter_to_value(e,"Referrals", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferrals));
 
814
        add_counter_to_value(e,"Chainings", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsChainings));
 
815
        add_counter_to_value(e,"SecurityErrors", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsSecurityErrors));
 
816
        add_counter_to_value(e,"Errors", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsErrors));
 
817
        add_counter_to_value(e,"Connections", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnections));
 
818
        add_counter_to_value(e,"ConnectionSeq", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsConnectionSeq));
 
819
        add_counter_to_value(e,"BytesRecv", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesRecv));
 
820
        add_counter_to_value(e,"BytesSent", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsBytesSent));
 
821
        add_counter_to_value(e,"EntriesReturned", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsEntriesReturned));
 
822
        add_counter_to_value(e,"ReferralsReturned", slapi_counter_get_value(g_get_global_snmp_vars()->ops_tbl.dsReferralsReturned));
 
823
        add_counter_to_value(e,"MasterEntries", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsMasterEntries));
 
824
        add_counter_to_value(e,"CopyEntries", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCopyEntries));
 
825
        add_counter_to_value(e,"CacheEntries", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheEntries));
 
826
        add_counter_to_value(e,"CacheHits", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsCacheHits));
 
827
        add_counter_to_value(e,"SlaveHits", slapi_counter_get_value(g_get_global_snmp_vars()->entries_tbl.dsSlaveHits));
 
828
}
 
829
 
 
830
/*
 
831
 * loadConfigStats()
 
832
 *
 
833
 * Reads the header table SNMP settings and sets them in the mmap'd stats
 
834
 * file.  This should be done only when the semaphore is held.
 
835
 */
 
836
static void
 
837
loadConfigStats() {
 
838
        Slapi_Entry *entry = NULL;
 
839
        char *name = NULL;
 
840
        char *desc = NULL;
 
841
        char *org = NULL;
 
842
        char *loc = NULL;
 
843
        char *contact = NULL;
 
844
 
 
845
        /* Read attributes from SNMP config entry */
 
846
        getConfigEntry( &entry );
 
847
        if ( entry != NULL ) {
 
848
                name = slapi_entry_attr_get_charptr( entry, SNMP_NAME_ATTR );
 
849
                desc = slapi_entry_attr_get_charptr( entry, SNMP_DESC_ATTR );
 
850
                org = slapi_entry_attr_get_charptr( entry, SNMP_ORG_ATTR );
 
851
                loc = slapi_entry_attr_get_charptr( entry, SNMP_LOC_ATTR );
 
852
                contact = slapi_entry_attr_get_charptr( entry, SNMP_CONTACT_ATTR );
 
853
                freeConfigEntry( &entry );
 
854
        }
 
855
 
 
856
        /* Load stats into table */
 
857
        if ( name != NULL) {
 
858
                PL_strncpyz(stats->hdr_stats.dsName, name, SNMP_FIELD_LENGTH);
 
859
        }
 
860
 
 
861
        if ( desc != NULL) {
 
862
                PL_strncpyz(stats->hdr_stats.dsDescription, desc, SNMP_FIELD_LENGTH);
 
863
        }
 
864
 
 
865
        if ( org != NULL) {
 
866
                PL_strncpyz(stats->hdr_stats.dsOrganization, org, SNMP_FIELD_LENGTH);
 
867
        }
 
868
 
 
869
        if ( loc != NULL) {
 
870
                PL_strncpyz(stats->hdr_stats.dsLocation, loc, SNMP_FIELD_LENGTH);
 
871
        }
 
872
 
 
873
        if ( contact != NULL) {
 
874
                PL_strncpyz(stats->hdr_stats.dsContact, contact, SNMP_FIELD_LENGTH);
 
875
        }
 
876
 
 
877
        /* Free strings */
 
878
        slapi_ch_free((void **) &name);
 
879
        slapi_ch_free((void **) &desc);
 
880
        slapi_ch_free((void **) &org);
 
881
        slapi_ch_free((void **) &loc);
 
882
        slapi_ch_free((void **) &contact);
 
883
}
 
884
 
 
885
static Slapi_Entry *
 
886
getConfigEntry( Slapi_Entry **e ) {
 
887
        Slapi_DN        sdn;
 
888
 
 
889
        /* SNMP_CONFIG_DN: no need to be normalized */
 
890
        slapi_sdn_init_normdn_byref( &sdn, SNMP_CONFIG_DN );
 
891
        slapi_search_internal_get_entry( &sdn, NULL, e,
 
892
                        plugin_get_default_component_id());
 
893
        slapi_sdn_done( &sdn );
 
894
        return *e;
 
895
}
 
896
 
 
897
static void
 
898
freeConfigEntry( Slapi_Entry **e ) {
 
899
        if ( (e != NULL) && (*e != NULL) ) {
 
900
                slapi_entry_free( *e );
 
901
                *e = NULL;
 
902
        }
 
903
}
 
904