]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/bind9/lib/isc/counter.c
Fix multiple vulnerabilities in file(1) and libmagic(3).
[FreeBSD/releng/9.2.git] / contrib / bind9 / lib / isc / counter.c
1 /*
2  * Copyright (C) 2014  Internet Systems Consortium, Inc. ("ISC")
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14  * PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 /*! \file */
18
19 #include <config.h>
20
21 #include <stddef.h>
22
23 #include <isc/counter.h>
24 #include <isc/magic.h>
25 #include <isc/mem.h>
26 #include <isc/util.h>
27
28 #define COUNTER_MAGIC                   ISC_MAGIC('C', 'n', 't', 'r')
29 #define VALID_COUNTER(r)                ISC_MAGIC_VALID(r, COUNTER_MAGIC)
30
31 struct isc_counter {
32         unsigned int    magic;
33         isc_mem_t       *mctx;
34         isc_mutex_t     lock;
35         unsigned int    references;
36         unsigned int    limit;
37         unsigned int    used;
38 };
39
40 isc_result_t
41 isc_counter_create(isc_mem_t *mctx, int limit, isc_counter_t **counterp) {
42         isc_result_t result;
43         isc_counter_t *counter;
44
45         REQUIRE(counterp != NULL && *counterp == NULL);
46
47         counter = isc_mem_get(mctx, sizeof(*counter));
48         if (counter == NULL)
49                 return (ISC_R_NOMEMORY);
50
51         result = isc_mutex_init(&counter->lock);
52         if (result != ISC_R_SUCCESS) {
53                 isc_mem_put(mctx, counter, sizeof(*counter));
54                 return (result);
55         }
56
57         counter->mctx = NULL;
58         isc_mem_attach(mctx, &counter->mctx);
59
60         counter->references = 1;
61         counter->limit = limit;
62         counter->used = 0;
63
64         counter->magic = COUNTER_MAGIC;
65         *counterp = counter;
66         return (ISC_R_SUCCESS);
67 }
68
69 isc_result_t
70 isc_counter_increment(isc_counter_t *counter) {
71         isc_result_t result = ISC_R_SUCCESS;
72
73         LOCK(&counter->lock);
74         counter->used++;
75         if (counter->limit != 0 && counter->used >= counter->limit)
76                 result = ISC_R_QUOTA;
77         UNLOCK(&counter->lock);
78
79         return (result);
80 }
81
82 unsigned int
83 isc_counter_used(isc_counter_t *counter) {
84         REQUIRE(VALID_COUNTER(counter));
85
86         return (counter->used);
87 }
88
89 void
90 isc_counter_setlimit(isc_counter_t *counter, int limit) {
91         REQUIRE(VALID_COUNTER(counter));
92
93         LOCK(&counter->lock);
94         counter->limit = limit;
95         UNLOCK(&counter->lock);
96 }
97
98 void
99 isc_counter_attach(isc_counter_t *source, isc_counter_t **targetp) {
100         REQUIRE(VALID_COUNTER(source));
101         REQUIRE(targetp != NULL && *targetp == NULL);
102
103         LOCK(&source->lock);
104         source->references++;
105         INSIST(source->references > 0);
106         UNLOCK(&source->lock);
107
108         *targetp = source;
109 }
110
111 static void
112 destroy(isc_counter_t *counter) {
113         counter->magic = 0;
114         isc_mutex_destroy(&counter->lock);
115         isc_mem_putanddetach(&counter->mctx, counter, sizeof(*counter));
116 }
117
118 void
119 isc_counter_detach(isc_counter_t **counterp) {
120         isc_counter_t *counter;
121         isc_boolean_t want_destroy = ISC_FALSE;
122
123         REQUIRE(counterp != NULL && *counterp != NULL);
124         counter = *counterp;
125         REQUIRE(VALID_COUNTER(counter));
126
127         *counterp = NULL;
128
129         LOCK(&counter->lock);
130         INSIST(counter->references > 0);
131         counter->references--;
132         if (counter->references == 0)
133                 want_destroy = ISC_TRUE;
134         UNLOCK(&counter->lock);
135
136         if (want_destroy)
137                 destroy(counter);
138 }