1 /* memory.c
2 
3    Memory-resident database... */
4 
5 /*
6  * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1995-2003 by Internet Software Consortium
8  *
9  * This Source Code Form is subject to the terms of the Mozilla Public
10  * License, v. 2.0. If a copy of the MPL was not distributed with this
11  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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  *   https://www.isc.org/
26  *
27  */
28 
29 #include "dhcpd.h"
30 
31 struct group *root_group;
32 group_hash_t *group_name_hash;
33 int (*group_write_hook) (struct group_object *);
34 
delete_group(struct group_object * group,int writep)35 isc_result_t delete_group (struct group_object *group, int writep)
36 {
37 	struct group_object *d;
38 
39 	/* The group should exist and be hashed - if not, it's invalid. */
40 	if (group_name_hash) {
41 		d = (struct group_object *)0;
42 		group_hash_lookup (&d, group_name_hash, group -> name,
43 				   strlen (group -> name), MDL);
44 	} else
45 		return DHCP_R_INVALIDARG;
46 	if (!d)
47 		return DHCP_R_INVALIDARG;
48 
49 	/* Also not okay to delete a group that's not the one in
50 	   the hash table. */
51 	if (d != group)
52 		return DHCP_R_INVALIDARG;
53 
54 	/* If it's dynamic, and we're deleting it, we can just blow away the
55 	   hash table entry. */
56 	if ((group -> flags & GROUP_OBJECT_DYNAMIC) &&
57 	    !(group -> flags & GROUP_OBJECT_STATIC)) {
58 		group_hash_delete (group_name_hash,
59 				   group -> name, strlen (group -> name), MDL);
60 	} else {
61 		group -> flags |= GROUP_OBJECT_DELETED;
62 		if (group -> group)
63 			group_dereference (&group -> group, MDL);
64 	}
65 
66 	/* Store the group declaration in the lease file. */
67 	if (writep && group_write_hook) {
68 		if (!(*group_write_hook) (group))
69 			return ISC_R_IOERROR;
70 	}
71 	return ISC_R_SUCCESS;
72 }
73 
supersede_group(struct group_object * group,int writep)74 isc_result_t supersede_group (struct group_object *group, int writep)
75 {
76 	struct group_object *t;
77 
78 	/* Register the group in the group name hash table,
79 	   so we can look it up later. */
80 	if (group_name_hash) {
81 		t = (struct group_object *)0;
82 		group_hash_lookup (&t, group_name_hash,
83 			group -> name,
84 			     strlen (group -> name), MDL);
85 		if (t && t != group) {
86 			/* If this isn't a dynamic entry, then we need to flag
87 			   the replacement as not dynamic either - otherwise,
88 			   if the dynamic entry is deleted later, the static
89 			   entry will come back next time the server is stopped
90 			   and restarted. */
91 			if (!(t -> flags & GROUP_OBJECT_DYNAMIC))
92 				group -> flags |= GROUP_OBJECT_STATIC;
93 
94 			/* Delete the old object if it hasn't already been
95 			   deleted.  If it has already been deleted, get rid of
96 			   the hash table entry.  This is a legitimate
97 			   situation - a deleted static object needs to be kept
98 			   around so we remember it's deleted. */
99 			if (!(t -> flags & GROUP_OBJECT_DELETED))
100 				delete_group (t, 0);
101 			else {
102 				group_hash_delete (group_name_hash,
103 						   group -> name,
104 						   strlen (group -> name),
105 						   MDL);
106 				group_object_dereference (&t, MDL);
107 			}
108 		}
109 	} else {
110 		group_new_hash(&group_name_hash, GROUP_HASH_SIZE, MDL);
111 		t = (struct group_object *)0;
112 	}
113 
114 	/* Add the group to the group name hash if it's not
115 	   already there, and also thread it into the list of
116 	   dynamic groups if appropriate. */
117 	if (!t) {
118 		group_hash_add (group_name_hash, group -> name,
119 				strlen (group -> name), group, MDL);
120 	}
121 
122 	/* Store the group declaration in the lease file. */
123 	if (writep && group_write_hook) {
124 		if (!(*group_write_hook) (group))
125 			return ISC_R_IOERROR;
126 	}
127 	return ISC_R_SUCCESS;
128 }
129 
clone_group(struct group ** gp,struct group * group,const char * file,int line)130 int clone_group (struct group **gp, struct group *group,
131 		 const char *file, int line)
132 {
133 	struct group *g = (struct group *)0;
134 
135 	/* Normally gp should contain the null pointer, but for convenience
136 	   it's permissible to clone a group into itself. */
137 	if (*gp && *gp != group)
138 		return 0;
139 	if (!group_allocate (&g, file, line))
140 		return 0;
141 	if (group == *gp)
142 		*gp = (struct group *)0;
143 	group_reference (gp, g, file, line);
144 	g -> authoritative = group -> authoritative;
145 	group_reference (&g -> next, group, file, line);
146 	group_dereference (&g, file, line);
147 	return 1;
148 }
149