summaryrefslogtreecommitdiff
path: root/common/memory.c
blob: 8e31154aa5d1bacf6b0fab1b21cb73f8ebcfa6d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/* memory.c

   Memory-resident database... */

/*
 * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
 * Copyright (c) 1995-2003 by Internet Software Consortium
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 *   Internet Systems Consortium, Inc.
 *   PO Box 360
 *   Newmarket, NH 03857 USA
 *   <info@isc.org>
 *   https://www.isc.org/
 *
 */

#include "dhcpd.h"

struct group *root_group;
group_hash_t *group_name_hash;
int (*group_write_hook) (struct group_object *);

isc_result_t delete_group (struct group_object *group, int writep)
{
	struct group_object *d;

	/* The group should exist and be hashed - if not, it's invalid. */
	if (group_name_hash) {
		d = (struct group_object *)0;
		group_hash_lookup (&d, group_name_hash, group -> name,
				   strlen (group -> name), MDL);
	} else
		return DHCP_R_INVALIDARG;
	if (!d)
		return DHCP_R_INVALIDARG;

	/* Also not okay to delete a group that's not the one in
	   the hash table. */
	if (d != group)
		return DHCP_R_INVALIDARG;

	/* If it's dynamic, and we're deleting it, we can just blow away the
	   hash table entry. */
	if ((group -> flags & GROUP_OBJECT_DYNAMIC) &&
	    !(group -> flags & GROUP_OBJECT_STATIC)) {
		group_hash_delete (group_name_hash,
				   group -> name, strlen (group -> name), MDL);
	} else {
		group -> flags |= GROUP_OBJECT_DELETED;
		if (group -> group)
			group_dereference (&group -> group, MDL);
	}

	/* Store the group declaration in the lease file. */
	if (writep && group_write_hook) {
		if (!(*group_write_hook) (group))
			return ISC_R_IOERROR;
	}
	return ISC_R_SUCCESS;
}

isc_result_t supersede_group (struct group_object *group, int writep)
{
	struct group_object *t;

	/* Register the group in the group name hash table,
	   so we can look it up later. */
	if (group_name_hash) {
		t = (struct group_object *)0;
		group_hash_lookup (&t, group_name_hash,
			group -> name,
			     strlen (group -> name), MDL);
		if (t && t != group) {
			/* If this isn't a dynamic entry, then we need to flag
			   the replacement as not dynamic either - otherwise,
			   if the dynamic entry is deleted later, the static
			   entry will come back next time the server is stopped
			   and restarted. */
			if (!(t -> flags & GROUP_OBJECT_DYNAMIC))
				group -> flags |= GROUP_OBJECT_STATIC;

			/* Delete the old object if it hasn't already been
			   deleted.  If it has already been deleted, get rid of
			   the hash table entry.  This is a legitimate
			   situation - a deleted static object needs to be kept
			   around so we remember it's deleted. */
			if (!(t -> flags & GROUP_OBJECT_DELETED))
				delete_group (t, 0);
			else {
				group_hash_delete (group_name_hash,
						   group -> name,
						   strlen (group -> name),
						   MDL);
				group_object_dereference (&t, MDL);
			}
		}
	} else {
		group_new_hash(&group_name_hash, GROUP_HASH_SIZE, MDL);
		t = (struct group_object *)0;
	}

	/* Add the group to the group name hash if it's not
	   already there, and also thread it into the list of
	   dynamic groups if appropriate. */
	if (!t) {
		group_hash_add (group_name_hash, group -> name,
				strlen (group -> name), group, MDL);
	}

	/* Store the group declaration in the lease file. */
	if (writep && group_write_hook) {
		if (!(*group_write_hook) (group))
			return ISC_R_IOERROR;
	}
	return ISC_R_SUCCESS;
}

int clone_group (struct group **gp, struct group *group,
		 const char *file, int line)
{
	struct group *g = (struct group *)0;

	/* Normally gp should contain the null pointer, but for convenience
	   it's permissible to clone a group into itself. */
	if (*gp && *gp != group)
		return 0;
	if (!group_allocate (&g, file, line))
		return 0;
	if (group == *gp)
		*gp = (struct group *)0;
	group_reference (gp, g, file, line);
	g -> authoritative = group -> authoritative;
	group_reference (&g -> next, group, file, line);
	group_dereference (&g, file, line);
	return 1;
}