Merge from vendor branch DHCP:
[dragonfly.git] / contrib / dhcp-3.0 / common / memory.c
1 /* memory.c
2
3    Memory-resident database... */
4
5 /*
6  * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1995-2003 by Internet Software Consortium
8  *
9  * Permission to use, copy, modify, and distribute this software for any
10  * purpose with or without fee is hereby granted, provided that the above
11  * copyright notice and this permission notice appear in all copies.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
16  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20  *
21  *   Internet Systems Consortium, Inc.
22  *   950 Charter Street
23  *   Redwood City, CA 94063
24  *   <info@isc.org>
25  *   http://www.isc.org/
26  *
27  * This software has been written for Internet Systems Consortium
28  * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29  * To learn more about Internet Systems Consortium, see
30  * ``http://www.isc.org/''.  To learn more about Vixie Enterprises,
31  * see ``http://www.vix.com''.   To learn more about Nominum, Inc., see
32  * ``http://www.nominum.com''.
33  */
34
35 #ifndef lint
36 static char copyright[] =
37 "$Id: memory.c,v 1.66.2.5 2004/06/10 17:59:19 dhankins Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
38 #endif /* not lint */
39
40 #include "dhcpd.h"
41
42 struct group *root_group;
43 group_hash_t *group_name_hash;
44 int (*group_write_hook) (struct group_object *);
45
46 isc_result_t delete_group (struct group_object *group, int writep)
47 {
48         struct group_object *d;
49
50         /* The group should exist and be hashed - if not, it's invalid. */
51         if (group_name_hash) {
52                 d = (struct group_object *)0;
53                 group_hash_lookup (&d, group_name_hash, group -> name,
54                                    strlen (group -> name), MDL);
55         } else
56                 return ISC_R_INVALIDARG;
57         if (!d)
58                 return ISC_R_INVALIDARG;
59
60         /* Also not okay to delete a group that's not the one in
61            the hash table. */
62         if (d != group)
63                 return ISC_R_INVALIDARG;
64
65         /* If it's dynamic, and we're deleting it, we can just blow away the
66            hash table entry. */
67         if ((group -> flags & GROUP_OBJECT_DYNAMIC) &&
68             !(group -> flags & GROUP_OBJECT_STATIC)) {
69                 group_hash_delete (group_name_hash,
70                                    group -> name, strlen (group -> name), MDL);
71         } else {
72                 group -> flags |= GROUP_OBJECT_DELETED;
73                 if (group -> group)
74                         group_dereference (&group -> group, MDL);
75         }
76
77         /* Store the group declaration in the lease file. */
78         if (writep && group_write_hook) {
79                 if (!(*group_write_hook) (group))
80                         return ISC_R_IOERROR;
81         }
82         return ISC_R_SUCCESS;
83 }
84
85 isc_result_t supersede_group (struct group_object *group, int writep)
86 {
87         struct group_object *t, *u;
88         isc_result_t status;
89
90         /* Register the group in the group name hash table,
91            so we can look it up later. */
92         if (group_name_hash) {
93                 t = (struct group_object *)0;
94                 group_hash_lookup (&t, group_name_hash,
95                         group -> name,
96                              strlen (group -> name), MDL);
97                 if (t && t != group) {
98                         /* If this isn't a dynamic entry, then we need to flag
99                            the replacement as not dynamic either - otherwise,
100                            if the dynamic entry is deleted later, the static
101                            entry will come back next time the server is stopped
102                            and restarted. */
103                         if (!(t -> flags & GROUP_OBJECT_DYNAMIC))
104                                 group -> flags |= GROUP_OBJECT_STATIC;
105
106                         /* Delete the old object if it hasn't already been
107                            deleted.  If it has already been deleted, get rid of
108                            the hash table entry.  This is a legitimate
109                            situation - a deleted static object needs to be kept
110                            around so we remember it's deleted. */
111                         if (!(t -> flags & GROUP_OBJECT_DELETED))
112                                 delete_group (t, 0);
113                         else {
114                                 group_hash_delete (group_name_hash,
115                                                    group -> name,
116                                                    strlen (group -> name),
117                                                    MDL);
118                                 group_object_dereference (&t, MDL);
119                         }
120                 }
121         } else {
122                 group_new_hash (&group_name_hash, 0, MDL);
123                 t = (struct group_object *)0;
124         }
125
126         /* Add the group to the group name hash if it's not
127            already there, and also thread it into the list of
128            dynamic groups if appropriate. */
129         if (!t) {
130                 group_hash_add (group_name_hash, group -> name,
131                                 strlen (group -> name), group, MDL);
132         }
133
134         /* Store the group declaration in the lease file. */
135         if (writep && group_write_hook) {
136                 if (!(*group_write_hook) (group))
137                         return ISC_R_IOERROR;
138         }
139         return ISC_R_SUCCESS;
140 }
141
142 int clone_group (struct group **gp, struct group *group,
143                  const char *file, int line)
144 {
145         isc_result_t status;
146         struct group *g = (struct group *)0;
147
148         /* Normally gp should contain the null pointer, but for convenience
149            it's permissible to clone a group into itself. */
150         if (*gp && *gp != group)
151                 return 0;
152         if (!group_allocate (&g, file, line))
153                 return 0;
154         if (group == *gp)
155                 *gp = (struct group *)0;
156         group_reference (gp, g, file, line);
157         g -> authoritative = group -> authoritative;
158         group_reference (&g -> next, group, file, line);
159         group_dereference (&g, file, line);
160         return 1;
161 }