Line data Source code
1 : /*
2 : *
3 : * registry.c
4 : *
5 : * $Source: /Users/ekr/tmp/nrappkit-dump/nrappkit/src/registry/registry.c,v $
6 : * $Revision: 1.6 $
7 : * $Date: 2007/11/21 00:09:12 $
8 : *
9 : * Datastore for tracking configuration and related info.
10 : *
11 : *
12 : * Copyright (C) 2005, Network Resonance, Inc.
13 : * Copyright (C) 2006, Network Resonance, Inc.
14 : * All Rights Reserved
15 : *
16 : * Redistribution and use in source and binary forms, with or without
17 : * modification, are permitted provided that the following conditions
18 : * are met:
19 : *
20 : * 1. Redistributions of source code must retain the above copyright
21 : * notice, this list of conditions and the following disclaimer.
22 : * 2. Redistributions in binary form must reproduce the above copyright
23 : * notice, this list of conditions and the following disclaimer in the
24 : * documentation and/or other materials provided with the distribution.
25 : * 3. Neither the name of Network Resonance, Inc. nor the name of any
26 : * contributors to this software may be used to endorse or promote
27 : * products derived from this software without specific prior written
28 : * permission.
29 : *
30 : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
31 : * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 : * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
34 : * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35 : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36 : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37 : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38 : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40 : * POSSIBILITY OF SUCH DAMAGE.
41 : *
42 : *
43 : */
44 :
45 : #include <assert.h>
46 : #include <string.h>
47 : #ifndef _MSC_VER
48 : #include <strings.h>
49 : #include <sys/param.h>
50 : #include <netinet/in.h>
51 : #endif
52 : #ifdef OPENSSL
53 : #include <openssl/ssl.h>
54 : #endif
55 : #include <ctype.h>
56 : #include "registry.h"
57 : #include "registry_int.h"
58 : #include "registry_vtbl.h"
59 : #include "r_assoc.h"
60 : #include "nr_common.h"
61 : #include "r_log.h"
62 : #include "r_errors.h"
63 : #include "r_macros.h"
64 : #include "c2ru.h"
65 :
66 : /* vtbl used to switch hit between local and remote invocations */
67 : static nr_registry_module *reg_vtbl = 0;
68 :
69 : /* must be in the order the types are numbered */
70 : static char *typenames[] = { "char", "UCHAR", "INT2", "UINT2", "INT4", "UINT4", "INT8", "UINT8", "double", "Data", "string", "registry" };
71 :
72 : int NR_LOG_REGISTRY=0;
73 :
74 : NR_registry NR_TOP_LEVEL_REGISTRY = "";
75 :
76 : int
77 0 : NR_reg_init(void *mode)
78 : {
79 : int r, _status;
80 0 : nr_registry_module *module = (nr_registry_module*)mode;
81 : #ifdef SANITY_CHECKS
82 : NR_registry registry;
83 : #endif
84 :
85 0 : if (reg_vtbl) {
86 0 : if (reg_vtbl != module) {
87 0 : r_log(LOG_GENERIC,LOG_ERR,"Can't reinitialize registry in different mode");
88 0 : ABORT(R_INTERNAL);
89 : }
90 :
91 0 : return(0);
92 : }
93 :
94 0 : reg_vtbl = module;
95 :
96 0 : if ((r=reg_vtbl->vtbl->init(mode)))
97 0 : ABORT(r);
98 :
99 : #ifdef SANITY_CHECKS
100 0 : if ((r=NR_reg_get_registry(NR_TOP_LEVEL_REGISTRY, registry)))
101 0 : ABORT(r);
102 0 : assert(strcmp(registry, NR_TOP_LEVEL_REGISTRY) == 0);
103 : #endif
104 :
105 0 : r_log_init();
106 0 : r_log_register("registry",&NR_LOG_REGISTRY);
107 :
108 0 : _status=0;
109 : abort:
110 0 : r_log(NR_LOG_REGISTRY,
111 : (_status ? LOG_ERR : LOG_INFO),
112 : (_status ? "Couldn't initialize registry" : "Initialized registry"));
113 0 : return(_status);
114 : }
115 :
116 : int
117 0 : NR_reg_initted(void)
118 : {
119 0 : return reg_vtbl!=0;
120 : }
121 :
122 : #define NRREGGET(func, method, type) \
123 : int \
124 : func(NR_registry name, type *out) \
125 : { \
126 : return reg_vtbl->vtbl->method(name, out); \
127 : }
128 :
129 0 : NRREGGET(NR_reg_get_char, get_char, char)
130 0 : NRREGGET(NR_reg_get_uchar, get_uchar, UCHAR)
131 0 : NRREGGET(NR_reg_get_int2, get_int2, INT2)
132 0 : NRREGGET(NR_reg_get_uint2, get_uint2, UINT2)
133 0 : NRREGGET(NR_reg_get_int4, get_int4, INT4)
134 0 : NRREGGET(NR_reg_get_uint4, get_uint4, UINT4)
135 0 : NRREGGET(NR_reg_get_int8, get_int8, INT8)
136 0 : NRREGGET(NR_reg_get_uint8, get_uint8, UINT8)
137 0 : NRREGGET(NR_reg_get_double, get_double, double)
138 :
139 : int
140 0 : NR_reg_get_registry(NR_registry name, NR_registry out)
141 : {
142 0 : return reg_vtbl->vtbl->get_registry(name, out);
143 : }
144 :
145 : int
146 0 : NR_reg_get_bytes(NR_registry name, UCHAR *out, size_t size, size_t *length)
147 : {
148 0 : return reg_vtbl->vtbl->get_bytes(name, out, size, length);
149 : }
150 :
151 : int
152 0 : NR_reg_get_string(NR_registry name, char *out, size_t size)
153 : {
154 0 : return reg_vtbl->vtbl->get_string(name, out, size);
155 : }
156 :
157 : int
158 0 : NR_reg_get_length(NR_registry name, size_t *length)
159 : {
160 0 : return reg_vtbl->vtbl->get_length(name, length);
161 : }
162 :
163 : int
164 0 : NR_reg_get_type(NR_registry name, NR_registry_type type)
165 : {
166 0 : return reg_vtbl->vtbl->get_type(name, type);
167 : }
168 :
169 : #define NRREGSET(func, method, type) \
170 : int \
171 : func(NR_registry name, type data) \
172 : { \
173 : return reg_vtbl->vtbl->method(name, data); \
174 : }
175 :
176 0 : NRREGSET(NR_reg_set_char, set_char, char)
177 0 : NRREGSET(NR_reg_set_uchar, set_uchar, UCHAR)
178 0 : NRREGSET(NR_reg_set_int2, set_int2, INT2)
179 0 : NRREGSET(NR_reg_set_uint2, set_uint2, UINT2)
180 0 : NRREGSET(NR_reg_set_int4, set_int4, INT4)
181 0 : NRREGSET(NR_reg_set_uint4, set_uint4, UINT4)
182 0 : NRREGSET(NR_reg_set_int8, set_int8, INT8)
183 0 : NRREGSET(NR_reg_set_uint8, set_uint8, UINT8)
184 0 : NRREGSET(NR_reg_set_double, set_double, double)
185 0 : NRREGSET(NR_reg_set_string, set_string, char*)
186 :
187 : int
188 0 : NR_reg_set_registry(NR_registry name)
189 : {
190 0 : return reg_vtbl->vtbl->set_registry(name);
191 : }
192 :
193 : int
194 0 : NR_reg_set_bytes(NR_registry name, unsigned char *data, size_t length)
195 : {
196 0 : return reg_vtbl->vtbl->set_bytes(name, data, length);
197 : }
198 :
199 :
200 : int
201 0 : NR_reg_del(NR_registry name)
202 : {
203 0 : return reg_vtbl->vtbl->del(name);
204 : }
205 :
206 : int
207 0 : NR_reg_fin(NR_registry name)
208 : {
209 0 : return reg_vtbl->vtbl->fin(name);
210 : }
211 :
212 : int
213 0 : NR_reg_get_child_count(char *parent, unsigned int *count)
214 : {
215 : assert(sizeof(count) == sizeof(size_t));
216 0 : return reg_vtbl->vtbl->get_child_count(parent, (size_t*)count);
217 : }
218 :
219 : int
220 0 : NR_reg_get_child_registry(char *parent, unsigned int i, NR_registry child)
221 : {
222 : int r, _status;
223 : size_t count;
224 0 : NR_registry *children=0;
225 :
226 0 : if ((r=reg_vtbl->vtbl->get_child_count(parent, &count)))
227 0 : ABORT(r);
228 :
229 0 : if (i >= count)
230 0 : ABORT(R_NOT_FOUND);
231 : else {
232 0 : count++;
233 0 : children = (NR_registry *)RCALLOC(count * sizeof(NR_registry));
234 0 : if (!children)
235 0 : ABORT(R_NO_MEMORY);
236 :
237 0 : if ((r=reg_vtbl->vtbl->get_children(parent, children, count, &count)))
238 0 : ABORT(r);
239 :
240 0 : if (i >= count)
241 0 : ABORT(R_NOT_FOUND);
242 :
243 0 : strncpy(child, children[i], sizeof(NR_registry));
244 : }
245 :
246 0 : _status=0;
247 : abort:
248 0 : RFREE(children);
249 0 : return(_status);
250 : }
251 :
252 : int
253 0 : NR_reg_get_children(NR_registry parent, NR_registry *children, size_t size, size_t *length)
254 : {
255 0 : return reg_vtbl->vtbl->get_children(parent, children, size, length);
256 : }
257 :
258 : int
259 0 : NR_reg_dump()
260 : {
261 : int r, _status;
262 :
263 0 : if ((r=reg_vtbl->vtbl->dump(0)))
264 0 : ABORT(r);
265 :
266 0 : _status=0;
267 : abort:
268 0 : return(_status);
269 : }
270 :
271 : // convenience methods, call RFREE on the returned data
272 : int
273 0 : NR_reg_alloc_data(NR_registry name, Data *data)
274 : {
275 : int r, _status;
276 : size_t length;
277 0 : UCHAR *tmp = 0;
278 : size_t sanity_check;
279 :
280 0 : if ((r=NR_reg_get_length(name, &length)))
281 0 : ABORT(r);
282 :
283 0 : if (!(tmp = (void*)RMALLOC(length)))
284 0 : ABORT(R_NO_MEMORY);
285 :
286 0 : if ((r=NR_reg_get_bytes(name, tmp, length, &sanity_check)))
287 0 : ABORT(r);
288 :
289 0 : assert(length == sanity_check);
290 :
291 0 : data->len = length;
292 0 : data->data = tmp;
293 :
294 0 : _status=0;
295 : abort:
296 0 : if (_status) {
297 0 : if (tmp) RFREE(tmp);
298 : }
299 0 : return(_status);
300 : }
301 :
302 : int
303 0 : NR_reg_alloc_string(NR_registry name, char **data)
304 : {
305 : int r, _status;
306 : size_t length;
307 0 : char *tmp = 0;
308 :
309 0 : if ((r=NR_reg_get_length(name, &length)))
310 0 : ABORT(r);
311 :
312 0 : if (!(tmp = (void*)RMALLOC(length+1)))
313 0 : ABORT(R_NO_MEMORY);
314 :
315 0 : if ((r=NR_reg_get_string(name, tmp, length+1)))
316 0 : ABORT(r);
317 :
318 0 : assert(length == strlen(tmp));
319 :
320 0 : *data = tmp;
321 :
322 0 : _status=0;
323 : abort:
324 0 : if (_status) {
325 0 : if (tmp) RFREE(tmp);
326 : }
327 0 : return(_status);
328 : }
329 :
330 :
331 : char *
332 0 : nr_reg_type_name(int type)
333 : {
334 0 : if ((type < NR_REG_TYPE_CHAR) || (type > NR_REG_TYPE_REGISTRY))
335 0 : return(NULL);
336 :
337 0 : return(typenames[type]);
338 : }
339 :
340 : int
341 0 : nr_reg_compute_type(char *typename, int *type)
342 : {
343 : int _status;
344 : int i;
345 :
346 : #ifdef SANITY_CHECKS
347 0 : assert(!strcasecmp(typenames[NR_REG_TYPE_CHAR], "char"));
348 0 : assert(!strcasecmp(typenames[NR_REG_TYPE_UCHAR], "UCHAR"));
349 0 : assert(!strcasecmp(typenames[NR_REG_TYPE_INT2], "INT2"));
350 0 : assert(!strcasecmp(typenames[NR_REG_TYPE_UINT2], "UINT2"));
351 0 : assert(!strcasecmp(typenames[NR_REG_TYPE_INT4], "INT4"));
352 0 : assert(!strcasecmp(typenames[NR_REG_TYPE_UINT4], "UINT4"));
353 0 : assert(!strcasecmp(typenames[NR_REG_TYPE_INT8], "INT8"));
354 0 : assert(!strcasecmp(typenames[NR_REG_TYPE_UINT8], "UINT8"));
355 0 : assert(!strcasecmp(typenames[NR_REG_TYPE_DOUBLE], "double"));
356 0 : assert(!strcasecmp(typenames[NR_REG_TYPE_BYTES], "Data"));
357 0 : assert(!strcasecmp(typenames[NR_REG_TYPE_STRING], "string"));
358 0 : assert(!strcasecmp(typenames[NR_REG_TYPE_REGISTRY], "registry"));
359 : assert(sizeof(typenames)/sizeof(*typenames) == (NR_REG_TYPE_REGISTRY+1));
360 : #endif
361 :
362 0 : for (i = 0; i < sizeof(typenames)/sizeof(*typenames); ++i) {
363 0 : if (!strcasecmp(typenames[i], typename)) {
364 0 : *type = i;
365 0 : return 0;
366 : }
367 : }
368 0 : ABORT(R_BAD_ARGS);
369 :
370 : _status=0;
371 : abort:
372 0 : return(_status);
373 : }
374 :
375 : /* More convenience functions: the same as their parents but they
376 : take a prefix and a suffix */
377 : #define NRGET2(func, type, get) \
378 : int \
379 : func(NR_registry parent, char *child, type *out) \
380 : { \
381 : int r, _status; \
382 : NR_registry registry; \
383 : \
384 : if ((r = NR_reg_make_registry(parent, child, registry))) \
385 : ABORT(r); \
386 : \
387 : if ((r = get(registry, out))) { \
388 : ABORT(r); \
389 : } \
390 : \
391 : _status = 0; \
392 : abort: \
393 : return (_status); \
394 : }
395 :
396 0 : NRGET2(NR_reg_get2_char, char, NR_reg_get_char)
397 0 : NRGET2(NR_reg_get2_uchar, UCHAR, NR_reg_get_uchar)
398 0 : NRGET2(NR_reg_get2_int2, INT2, NR_reg_get_int2)
399 0 : NRGET2(NR_reg_get2_uint2, UINT2, NR_reg_get_uint2)
400 0 : NRGET2(NR_reg_get2_int4, INT4, NR_reg_get_int4)
401 0 : NRGET2(NR_reg_get2_uint4, UINT4, NR_reg_get_uint4)
402 0 : NRGET2(NR_reg_get2_int8, INT8, NR_reg_get_int8)
403 0 : NRGET2(NR_reg_get2_uint8, UINT8, NR_reg_get_uint8)
404 0 : NRGET2(NR_reg_get2_double, double, NR_reg_get_double)
405 0 : NRGET2(NR_reg_alloc2_string, char*, NR_reg_alloc_string)
406 0 : NRGET2(NR_reg_alloc2_data, Data, NR_reg_alloc_data)
407 :
408 : int
409 0 : NR_reg_get2_bytes(NR_registry parent, char *child, UCHAR *out, size_t size, size_t *length)
410 : {
411 : int r, _status;
412 : NR_registry registry;
413 :
414 0 : if ((r=NR_reg_make_registry(parent, child, registry)))
415 0 : ABORT(r);
416 :
417 0 : if ((r=NR_reg_get_bytes(registry, out, size, length)))
418 0 : ABORT(r);
419 :
420 0 : _status = 0;
421 : abort:
422 0 : return (_status);
423 : }
424 :
425 : int
426 0 : NR_reg_get2_string(NR_registry parent, char *child, char *out, size_t size)
427 : {
428 : int r, _status;
429 : NR_registry registry;
430 :
431 0 : if ((r=NR_reg_make_registry(parent, child, registry)))
432 0 : ABORT(r);
433 :
434 0 : if ((r=NR_reg_get_string(registry, out, size)))
435 0 : ABORT(r);
436 :
437 0 : _status = 0;
438 : abort:
439 0 : return (_status);
440 : }
441 :
442 : /* More convenience functions: the same as their parents but they
443 : take a prefix and a suffix */
444 : #define NRSET2(func, type, set) \
445 : int \
446 : func(NR_registry parent, char *child, type in) \
447 : { \
448 : int r, _status; \
449 : NR_registry registry; \
450 : \
451 : if ((r = NR_reg_make_registry(parent, child, registry))) \
452 : ABORT(r); \
453 : \
454 : if ((r = set(registry, in))) { \
455 : ABORT(r); \
456 : } \
457 : \
458 : _status = 0; \
459 : abort: \
460 : return (_status); \
461 : }
462 :
463 0 : NRSET2(NR_reg_set2_char, char, NR_reg_set_char)
464 0 : NRSET2(NR_reg_set2_uchar, UCHAR, NR_reg_set_uchar)
465 0 : NRSET2(NR_reg_set2_int2, INT2, NR_reg_set_int2)
466 0 : NRSET2(NR_reg_set2_uint2, UINT2, NR_reg_set_uint2)
467 0 : NRSET2(NR_reg_set2_int4, INT4, NR_reg_set_int4)
468 0 : NRSET2(NR_reg_set2_uint4, UINT4, NR_reg_set_uint4)
469 0 : NRSET2(NR_reg_set2_int8, INT8, NR_reg_set_int8)
470 0 : NRSET2(NR_reg_set2_uint8, UINT8, NR_reg_set_uint8)
471 0 : NRSET2(NR_reg_set2_double, double, NR_reg_set_double)
472 0 : NRSET2(NR_reg_set2_string, char*, NR_reg_set_string)
473 :
474 : int
475 0 : NR_reg_set2_bytes(NR_registry prefix, char *name, UCHAR *data, size_t length)
476 : {
477 : int r, _status;
478 : NR_registry registry;
479 :
480 0 : if ((r = NR_reg_make_registry(prefix, name, registry)))
481 0 : ABORT(r);
482 :
483 0 : if ((r = NR_reg_set_bytes(registry, data, length)))
484 0 : ABORT(r);
485 :
486 0 : _status = 0;
487 : abort:
488 0 : return (_status);
489 : }
490 :
491 :
492 : int
493 0 : NR_reg_make_child_registry(NR_registry parent, NR_registry descendant, unsigned int generation, NR_registry child)
494 : {
495 : int _status;
496 : size_t length;
497 :
498 0 : length = strlen(parent);
499 :
500 0 : if (strncasecmp(parent, descendant, length))
501 0 : ABORT(R_BAD_ARGS);
502 :
503 0 : while (descendant[length] != '\0') {
504 0 : if (descendant[length] == '.') {
505 0 : if (generation == 0)
506 0 : break;
507 :
508 0 : --generation;
509 : }
510 :
511 0 : ++length;
512 0 : if (length >= sizeof(NR_registry))
513 0 : ABORT(R_BAD_ARGS);
514 : }
515 :
516 0 : strncpy(child, descendant, length);
517 0 : child[length] = '\0';
518 :
519 0 : _status=0;
520 : abort:
521 0 : return(_status);
522 : }
523 :
524 : int
525 0 : NR_reg_get2_child_count(NR_registry base, NR_registry name, unsigned int *count)
526 : {
527 : int r, _status;
528 : NR_registry registry;
529 :
530 0 : if ((r=nr_c2ru_make_registry(base, name, registry)))
531 0 : ABORT(r);
532 :
533 0 : if (r=NR_reg_get_child_count(registry,count))
534 0 : ABORT(r);
535 :
536 0 : _status=0;
537 : abort:
538 0 : return(_status);
539 : }
540 :
541 : int
542 0 : NR_reg_get2_child_registry(NR_registry base, NR_registry name, unsigned int i, NR_registry child)
543 : {
544 : int r, _status;
545 : NR_registry registry;
546 :
547 0 : if ((r=nr_c2ru_make_registry(base, name, registry)))
548 0 : ABORT(r);
549 :
550 0 : if (r=NR_reg_get_child_registry(registry, i, child))
551 0 : ABORT(r);
552 :
553 0 : _status=0;
554 : abort:
555 0 : return(_status);
556 : }
557 :
558 :
559 : /* requires parent already in legal form */
560 : int
561 0 : NR_reg_make_registry(NR_registry parent, char *child, NR_registry out)
562 : {
563 : int r, _status;
564 : int plen;
565 : int clen;
566 : char *c;
567 : int i;
568 :
569 0 : if ((r=nr_reg_is_valid(parent)))
570 0 : ABORT(r);
571 :
572 0 : if (*child == '.')
573 0 : ABORT(R_BAD_ARGS);
574 :
575 0 : clen = strlen(child);
576 0 : if (!clen)
577 0 : ABORT(R_BAD_ARGS);
578 0 : plen = strlen(parent);
579 0 : if ((plen + clen + 2) > sizeof(NR_registry))
580 0 : ABORT(R_BAD_ARGS);
581 :
582 0 : if (out != parent)
583 0 : strcpy(out, parent);
584 :
585 0 : c = &(out[plen]);
586 :
587 0 : if (parent[0] != '\0') {
588 0 : *c = '.';
589 0 : ++c;
590 : }
591 :
592 0 : for (i = 0; i < clen; ++i, ++c) {
593 0 : *c = child[i];
594 0 : if (isspace(*c) || *c == '.' || *c == '/' || ! isprint(*c))
595 0 : *c = '_';
596 : }
597 :
598 0 : *c = '\0';
599 :
600 0 : _status = 0;
601 : abort:
602 0 : return _status;
603 : }
604 :
|