~ubuntu-branches/ubuntu/gutsy/cyrus-sasl2/gutsy-201105300151

« back to all changes in this revision

Viewing changes to saslauthd/saslcache.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott James Remnant
  • Date: 2006-11-27 12:59:40 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20061127125940-na3q3g3tkydvyvgl
Tags: 2.1.22.dfsg1-4ubuntu1
* Merge from debian unstable, remaining changes:
  - remove stop links from rc0 and rc6
  - build against db4.3 instead of 4.2
  - build against heimdal-dev instead of libkrb5-dev
  - depend on, don't recommend, modules

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*******************************************************************************
 
2
 * *****************************************************************************
 
3
 * *
 
4
 * * saslcache.c
 
5
 * *
 
6
 * * Description:  A small utility that can attach to saslauthd's shared
 
7
 * *               memory region and display/dump information in the cache.
 
8
 * *
 
9
 * * Copyright (C) 2003 Jeremy Rumpf
 
10
 * *
 
11
 * * Redistribution and use in source and binary forms, with or without
 
12
 * * modification, are permitted provided that the following conditions
 
13
 * * are met:
 
14
 * *
 
15
 * * 1. Redistributions of source code must retain the above copyright
 
16
 * *    notice, this list of conditions and the following disclaimer.
 
17
 * *
 
18
 * * 2. Redistributions in binary form must reproduce the above copyright
 
19
 * *    notice, this list of conditions and the following disclaimer in the
 
20
 * *    documentation and/or other materials provided with the distribution.
 
21
 * *
 
22
 * * THIS SOFTWARE IS PROVIDED ``AS IS''. ANY EXPRESS OR IMPLIED WARRANTIES,
 
23
 * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
24
 * * IN NO EVENT SHALL JEREMY RUMPF OR ANY CONTRIBUTER TO THIS SOFTWARE BE
 
25
 * * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
26
 * * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
 
27
 * * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
28
 * * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
29
 * * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
30
 * * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 
31
 * * THE POSSIBILITY OF SUCH DAMAGE
 
32
 * *
 
33
 * * Jeremy Rumpf
 
34
 * * jrumpf@heavyload.net
 
35
 * *
 
36
 * ******************************************************************************
 
37
 ********************************************************************************/
 
38
 
 
39
/****************************************
 
40
* * includes
 
41
*****************************************/
 
42
#include <sys/types.h>
 
43
#include <sys/stat.h>
 
44
#include <sys/fcntl.h>
 
45
#include <sys/mman.h>
 
46
#include <errno.h>
 
47
#include <unistd.h>
 
48
#include <stdio.h>
 
49
#include <string.h>
 
50
#include <time.h>
 
51
 
 
52
#include "cache.h"
 
53
 
 
54
 
 
55
/****************************************
 
56
* * declarations/protos
 
57
*****************************************/
 
58
void    show_usage(void);
 
59
void    dump_cache_stats(void);
 
60
void    dump_cache_users(void);
 
61
char    *make_time(time_t);
 
62
 
 
63
/****************************************
 
64
* * module globals
 
65
*****************************************/
 
66
static  void            *shm_base = NULL;
 
67
static  struct bucket   *table = NULL;
 
68
static  struct stats    *table_stats = NULL;
 
69
 
 
70
/****************************************
 
71
*****************************************/
 
72
 
 
73
 
 
74
/*************************************************************
 
75
* * Main
 
76
**************************************************************/
 
77
int main(int argc, char **argv) {
 
78
 
 
79
        int             option;
 
80
        int             dump_user_info = 0;
 
81
        int             dump_stat_info = 0;
 
82
        char            *file = NULL;
 
83
        int             file_fd;
 
84
        int             shmid = 0;
 
85
        char            shmid_buff[256];
 
86
        char            cache_magic[64];
 
87
        struct stat     stat_buff;
 
88
 
 
89
        while ((option = getopt(argc, argv, "dm:s")) != -1) {
 
90
                switch(option) {
 
91
 
 
92
                        case 'd':
 
93
                                dump_user_info = 1;
 
94
                                break;
 
95
 
 
96
                        case 's':
 
97
                                dump_stat_info = 1;
 
98
                                break;
 
99
 
 
100
                        case 'm':
 
101
                                file = strdup(optarg);
 
102
                                break;
 
103
 
 
104
                        default:
 
105
                                show_usage();
 
106
                }
 
107
        }
 
108
 
 
109
        if (file == NULL)
 
110
                file = PATH_SASLAUTHD_RUNDIR "/cache.mmap";
 
111
 
 
112
        if (stat(file, &stat_buff) == -1) {
 
113
                fprintf(stderr, "could not stat mmap file: %s\n", file);
 
114
                fprintf(stderr, "stat: %s\n", strerror(errno));
 
115
                exit(1);
 
116
        }
 
117
 
 
118
        if ((file_fd = open(file, O_RDONLY)) < 0) {
 
119
                fprintf(stderr, "could not open mmap file: %s\n", file);
 
120
                fprintf(stderr, "open: %s\n", strerror(errno));
 
121
                fprintf(stderr, "perhaps saslcache -m <path>\n");
 
122
                exit(1);
 
123
        }
 
124
 
 
125
        if ((shm_base = mmap(NULL, stat_buff.st_size, PROT_READ, MAP_SHARED, file_fd, 0))== (void *)-1) {
 
126
                fprintf(stderr, "could not mmap shared memory file: %s\n", file);
 
127
                fprintf(stderr, "mmap: %s\n", strerror(errno));
 
128
                exit(1);
 
129
        }       
 
130
 
 
131
        memcpy(cache_magic, shm_base, 64);
 
132
        cache_magic[63] = '\0';
 
133
 
 
134
        if (strcmp(cache_magic, CACHE_CACHE_MAGIC) != 0) {
 
135
                fprintf(stderr, "mmap file [%s] is not a valid saslauthd cache\n", file);
 
136
                exit(1);
 
137
        }
 
138
 
 
139
        table_stats = shm_base + 64;
 
140
        (char *)table = (char *)table_stats + 128;
 
141
 
 
142
        if (dump_stat_info == 0 && dump_user_info == 0)
 
143
                dump_stat_info = 1;
 
144
 
 
145
        if (dump_stat_info)
 
146
                dump_cache_stats();
 
147
 
 
148
        if (dump_user_info)
 
149
                dump_cache_users();
 
150
 
 
151
        exit(0);        
 
152
}
 
153
 
 
154
 
 
155
/****************************************************
 
156
* * Dump a delimited record for each item in the
 
157
* * cache to stdout.
 
158
****************************************************/
 
159
void dump_cache_users(void) {
 
160
 
 
161
        unsigned int            x;
 
162
        struct bucket           *ref_bucket;
 
163
        time_t                  epoch_to;
 
164
 
 
165
        epoch_to = time(NULL) - table_stats->timeout;
 
166
 
 
167
        fprintf(stdout, "\"user\",\"realm\",\"service\",\"created\",\"created_localtime\"\n");
 
168
 
 
169
        for (x = 0; x < (table_stats->table_size * table_stats->max_buckets_per); x++) {
 
170
 
 
171
                ref_bucket = table + x;
 
172
 
 
173
                if (ref_bucket->created > epoch_to && *(ref_bucket->creds) != '\0') {
 
174
                        fprintf(stderr, "\"%s\",", ref_bucket->creds + ref_bucket->user_offt);
 
175
                        fprintf(stderr, "\"%s\",", ref_bucket->creds + ref_bucket->realm_offt);
 
176
                        fprintf(stderr, "\"%s\",", ref_bucket->creds + ref_bucket->service_offt);
 
177
                        fprintf(stderr, "\"%lu\",", ref_bucket->created);
 
178
                        fprintf(stderr, "\"%s\"\n", make_time(ref_bucket->created));
 
179
                }
 
180
        }
 
181
}
 
182
 
 
183
/****************************************************
 
184
* * Dump some usage statistics about the cred cache.
 
185
* * (clean this up someday)
 
186
****************************************************/
 
187
void dump_cache_stats(void) {
 
188
 
 
189
        unsigned int            x, y, z;
 
190
        float                   a;
 
191
        unsigned int            max_chain_length = 0;
 
192
        unsigned int            min_chain_length = 0;
 
193
        unsigned int            buckets_in_use = 0;
 
194
        unsigned int            slots_in_use = 0;
 
195
        unsigned int            slots_max_chain = 0;
 
196
        unsigned int            slots_min_chain = 0;
 
197
        time_t                  epoch_to;
 
198
 
 
199
 
 
200
        min_chain_length = table_stats->max_buckets_per;
 
201
        epoch_to = time(NULL) - table_stats->timeout;
 
202
 
 
203
        for (x = 0; x < table_stats->table_size; x++) {
 
204
 
 
205
                z = 0;
 
206
 
 
207
                for (y = (x * table_stats->max_buckets_per); y < ((x + 1) * table_stats->max_buckets_per); y++) { 
 
208
                        if (table[y].created > epoch_to) {
 
209
                                buckets_in_use++;
 
210
                                z++;
 
211
                        }
 
212
                }
 
213
 
 
214
                if (z == min_chain_length)
 
215
                        slots_min_chain++;
 
216
 
 
217
                if (z == max_chain_length)
 
218
                        slots_max_chain++;
 
219
 
 
220
                if (z > 0)
 
221
                        slots_in_use++;
 
222
 
 
223
                if (z > max_chain_length) {
 
224
                        max_chain_length = z;
 
225
                        slots_max_chain = 1;
 
226
                }
 
227
 
 
228
                if (z < min_chain_length) {
 
229
                        min_chain_length = z;
 
230
                        slots_min_chain = 1;
 
231
                }
 
232
        }
 
233
 
 
234
        fprintf(stdout, "----------------------------------------\n");
 
235
        fprintf(stdout, "Saslauthd Cache Detail:\n");
 
236
        fprintf(stdout, "\n");
 
237
        fprintf(stdout, "  timeout (seconds)           :  %d\n", table_stats->timeout);
 
238
        fprintf(stdout, "  total slots allocated       :  %d\n", table_stats->table_size);
 
239
        fprintf(stdout, "  slots in use                :  %d\n", slots_in_use);
 
240
        fprintf(stdout, "  total buckets               :  %d\n", (table_stats->max_buckets_per * table_stats->table_size));
 
241
        fprintf(stdout, "  buckets per slot            :  %d\n", table_stats->max_buckets_per);
 
242
        fprintf(stdout, "  buckets in use              :  %d\n", buckets_in_use);
 
243
        fprintf(stdout, "  hash table size (bytes)     :  %d\n", table_stats->bytes);
 
244
        fprintf(stdout, "  bucket size (bytes)         :  %d\n", table_stats->sizeof_bucket);
 
245
        fprintf(stdout, "  minimum slot allocation     :  %d\n", min_chain_length);
 
246
        fprintf(stdout, "  maximum slot allocation     :  %d\n", max_chain_length);
 
247
        fprintf(stdout, "  slots at maximum allocation :  %d\n", slots_max_chain);
 
248
        fprintf(stdout, "  slots at minimum allocation :  %d\n", slots_min_chain);
 
249
 
 
250
        if (table_stats->table_size == 0)
 
251
                a = 0;
 
252
        else
 
253
                a = slots_in_use / (float)table_stats->table_size;
 
254
 
 
255
        fprintf(stdout, "  overall hash table load     :  %0.2f\n", a);
 
256
        fprintf(stdout, "\n");
 
257
        fprintf(stdout, "  hits*                       :  %d\n", table_stats->hits);
 
258
        fprintf(stdout, "  misses*                     :  %d\n", table_stats->misses);
 
259
        fprintf(stdout, "  total lookup attempts*      :  %d\n", table_stats->attempts);
 
260
 
 
261
        if (table_stats->attempts == 0)
 
262
                a = 0;
 
263
        else
 
264
                a = (table_stats->hits / (float)table_stats->attempts) * 100;
 
265
 
 
266
        fprintf(stdout, "  hit ratio*                  :  %0.2f\n", a);
 
267
        fprintf(stdout, "  flock failures*             :  %d\n", table_stats->lock_failures);
 
268
        fprintf(stdout, "----------------------------------------\n");
 
269
        fprintf(stdout, "* May not be completely accurate\n");
 
270
        fprintf(stdout, "----------------------------------------\n\n");
 
271
}
 
272
 
 
273
 
 
274
/**************************************************
 
275
* * Create a human readable time representation
 
276
****************************************************/
 
277
char    *make_time(time_t epoch) {
 
278
 
 
279
        static char     created_str[128];
 
280
        struct  tm      *tm_st = NULL;
 
281
 
 
282
 
 
283
        tm_st = localtime(&epoch);      
 
284
 
 
285
        if (tm_st == NULL) 
 
286
                return "unknown";
 
287
 
 
288
        strftime(created_str, 127, "%c", tm_st);
 
289
        created_str[127] = '\0';
 
290
 
 
291
        return created_str;
 
292
}
 
293
 
 
294
 
 
295
/**************************************************
 
296
* * Dump out the usage information and exit
 
297
****************************************************/
 
298
void show_usage(void) {
 
299
 
 
300
    fprintf(stderr, "usage: saslcache [options]\n\n");
 
301
    fprintf(stderr, "option information:\n");
 
302
    fprintf(stderr, "  -d             Dumps a csv list of information in the cache.\n");
 
303
    fprintf(stderr, "  -f             Purges all entries from the cache.\n");
 
304
    fprintf(stderr, "  -m <path>      Alternate path to the cache.mmap file.\n");
 
305
    fprintf(stderr, "                 Defaults to: %s\n", PATH_SASLAUTHD_RUNDIR "/cache.mmap");
 
306
    fprintf(stderr, "  -s             Dumps general statistic information about the cache.\n");
 
307
    fprintf(stderr, "\n");
 
308
    fprintf(stderr, "  All data is delivered to stdout.\n");
 
309
 
 
310
    exit(1);
 
311
 
 
312
}
 
313