1/* salloc.c
2
3   Memory allocation for the DHCP server... */
4
5/*
6 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1996-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
36static char copyright[] =
37"$Id: salloc.c,v 1.3 2005/08/11 17:13:30 drochner Exp $ Copyright (c) 2004 Internet Systems Consortium.  All rights reserved.\n";
38#endif /* not lint */
39
40#include "dhcpd.h"
41#include <omapip/omapip_p.h>
42
43#if defined (COMPACT_LEASES)
44struct lease *free_leases;
45
46# if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
47struct lease *lease_hunks;
48
49void relinquish_lease_hunks ()
50{
51	struct lease *c, *n, **p, *f;
52	int i;
53
54	/* Account for all the leases on the free list. */
55	for (n = lease_hunks; n; n = n -> next) {
56	    for (i = 1; i < n -> starts + 1; i++) {
57		p = &free_leases;
58		for (c = free_leases; c; c = c -> next) {
59		    if (c == &n [i]) {
60			*p = c -> next;
61			n -> ends++;
62			break;
63		    }
64		    p = &c -> next;
65		}
66		if (!c) {
67		    log_info ("lease %s refcnt %d",
68			      piaddr (n [i].ip_addr), n [i].refcnt);
69		    dump_rc_history (&n [i]);
70		}
71	    }
72	}
73
74	for (c = lease_hunks; c; c = n) {
75		n = c -> next;
76		if (c -> ends != c -> starts) {
77			log_info ("lease hunk %lx leases %ld free %ld",
78				  (unsigned long)c, (unsigned long)c -> starts,
79				  (unsigned long)c -> ends);
80		}
81		dfree (c, MDL);
82	}
83
84	/* Free all the rogue leases. */
85	for (c = free_leases; c; c = n) {
86		n = c -> next;
87		dfree (c, MDL);
88	}
89}
90#endif
91
92struct lease *new_leases (n, file, line)
93	unsigned n;
94	const char *file;
95	int line;
96{
97	struct lease *rval;
98#if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
99	rval = dmalloc ((n + 1) * sizeof (struct lease), file, line);
100	memset (rval, 0, sizeof (struct lease));
101	rval -> starts = n;
102	rval -> next = lease_hunks;
103	lease_hunks = rval;
104	rval++;
105#else
106	rval = dmalloc (n * sizeof (struct lease), file, line);
107#endif
108	return rval;
109}
110
111/* If we are allocating leases in aggregations, there's really no way
112   to free one, although perhaps we can maintain a free list. */
113
114isc_result_t dhcp_lease_free (omapi_object_t *lo,
115			      const char *file, int line)
116{
117	struct lease *lease;
118	if (lo -> type != dhcp_type_lease)
119		return ISC_R_INVALIDARG;
120	lease = (struct lease *)lo;
121	memset (lease, 0, sizeof (struct lease));
122	lease -> next = free_leases;
123	free_leases = lease;
124	return ISC_R_SUCCESS;
125}
126
127isc_result_t dhcp_lease_get (omapi_object_t **lp,
128			     const char *file, int line)
129{
130	struct lease **lease = (struct lease **)lp;
131	struct lease *lt;
132
133	if (free_leases) {
134		lt = free_leases;
135		free_leases = lt -> next;
136		*lease = lt;
137		return ISC_R_SUCCESS;
138	}
139	return ISC_R_NOMEMORY;
140}
141#endif /* COMPACT_LEASES */
142
143OMAPI_OBJECT_ALLOC (lease, struct lease, dhcp_type_lease)
144OMAPI_OBJECT_ALLOC (class, struct class, dhcp_type_class)
145OMAPI_OBJECT_ALLOC (pool, struct pool, dhcp_type_pool)
146
147#if !defined (NO_HOST_FREES)	/* Scary debugging mode - don't enable! */
148OMAPI_OBJECT_ALLOC (host, struct host_decl, dhcp_type_host)
149#else
150isc_result_t host_allocate (struct host_decl **p, const char *file, int line)
151{
152	return omapi_object_allocate ((omapi_object_t **)p,
153				      dhcp_type_host, 0, file, line);
154}
155
156isc_result_t host_reference (struct host_decl **pptr, struct host_decl *ptr,
157			       const char *file, int line)
158{
159	return omapi_object_reference ((omapi_object_t **)pptr,
160				       (omapi_object_t *)ptr, file, line);
161}
162
163isc_result_t host_dereference (struct host_decl **ptr,
164			       const char *file, int line)
165{
166	if ((*ptr) -> refcnt == 1) {
167		log_error ("host dereferenced with refcnt == 1.");
168#if defined (DEBUG_RC_HISTORY)
169		dump_rc_history ();
170#endif
171		abort ();
172	}
173	return omapi_object_dereference ((omapi_object_t **)ptr, file, line);
174}
175#endif
176
177struct lease_state *free_lease_states;
178
179struct lease_state *new_lease_state (file, line)
180	const char *file;
181	int line;
182{
183	struct lease_state *rval;
184
185	if (free_lease_states) {
186		rval = free_lease_states;
187		free_lease_states =
188			(struct lease_state *)(free_lease_states -> next);
189 		dmalloc_reuse (rval, file, line, 0);
190	} else {
191		rval = dmalloc (sizeof (struct lease_state), file, line);
192		if (!rval)
193			return rval;
194	}
195	memset (rval, 0, sizeof *rval);
196	if (!option_state_allocate (&rval -> options, file, line)) {
197		free_lease_state (rval, file, line);
198		return (struct lease_state *)0;
199	}
200	return rval;
201}
202
203void free_lease_state (ptr, file, line)
204	struct lease_state *ptr;
205	const char *file;
206	int line;
207{
208	if (ptr -> options)
209		option_state_dereference (&ptr -> options, file, line);
210	if (ptr -> packet)
211		packet_dereference (&ptr -> packet, file, line);
212	if (ptr -> shared_network)
213		shared_network_dereference (&ptr -> shared_network,
214					    file, line);
215
216	data_string_forget (&ptr -> parameter_request_list, file, line);
217	data_string_forget (&ptr -> filename, file, line);
218	data_string_forget (&ptr -> server_name, file, line);
219	ptr -> next = free_lease_states;
220	free_lease_states = ptr;
221	dmalloc_reuse (free_lease_states, (char *)0, 0, 0);
222}
223
224#if defined (DEBUG_MEMORY_LEAKAGE) || \
225		defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
226void relinquish_free_lease_states ()
227{
228	struct lease_state *cs, *ns;
229
230	for (cs = free_lease_states; cs; cs = ns) {
231		ns = cs -> next;
232		dfree (cs, MDL);
233	}
234	free_lease_states = (struct lease_state *)0;
235}
236#endif
237
238struct permit *new_permit (file, line)
239	const char *file;
240	int line;
241{
242	struct permit *permit = ((struct permit *)
243				 dmalloc (sizeof (struct permit), file, line));
244	if (!permit)
245		return permit;
246	memset (permit, 0, sizeof *permit);
247	return permit;
248}
249
250void free_permit (permit, file, line)
251	struct permit *permit;
252	const char *file;
253	int line;
254{
255	if (permit -> type == permit_class)
256		class_dereference (&permit -> class, MDL);
257	dfree (permit, file, line);
258}
259