Remove building with NOCRYPTO option
[minix.git] / external / bsd / bind / dist / lib / dns / portlist.c
blobc1b4bae850a3b7686af201c13e3a48fdb88d25ec
1 /* $NetBSD: portlist.c,v 1.5 2014/12/10 04:37:58 christos Exp $ */
3 /*
4 * Copyright (C) 2004-2007, 2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2003 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: portlist.c,v 1.13 2007/06/19 23:47:16 tbox Exp */
22 /*! \file */
24 #include <config.h>
26 #include <stdlib.h>
28 #include <isc/magic.h>
29 #include <isc/mem.h>
30 #include <isc/mutex.h>
31 #include <isc/net.h>
32 #include <isc/refcount.h>
33 #include <isc/result.h>
34 #include <isc/string.h>
35 #include <isc/types.h>
36 #include <isc/util.h>
38 #include <dns/types.h>
39 #include <dns/portlist.h>
41 #define DNS_PORTLIST_MAGIC ISC_MAGIC('P','L','S','T')
42 #define DNS_VALID_PORTLIST(p) ISC_MAGIC_VALID(p, DNS_PORTLIST_MAGIC)
44 typedef struct dns_element {
45 in_port_t port;
46 isc_uint16_t flags;
47 } dns_element_t;
49 struct dns_portlist {
50 unsigned int magic;
51 isc_mem_t *mctx;
52 isc_refcount_t refcount;
53 isc_mutex_t lock;
54 dns_element_t *list;
55 unsigned int allocated;
56 unsigned int active;
59 #define DNS_PL_INET 0x0001
60 #define DNS_PL_INET6 0x0002
61 #define DNS_PL_ALLOCATE 16
63 static int
64 compare(const void *arg1, const void *arg2) {
65 const dns_element_t *e1 = (const dns_element_t *)arg1;
66 const dns_element_t *e2 = (const dns_element_t *)arg2;
68 if (e1->port < e2->port)
69 return (-1);
70 if (e1->port > e2->port)
71 return (1);
72 return (0);
75 isc_result_t
76 dns_portlist_create(isc_mem_t *mctx, dns_portlist_t **portlistp) {
77 dns_portlist_t *portlist;
78 isc_result_t result;
80 REQUIRE(portlistp != NULL && *portlistp == NULL);
82 portlist = isc_mem_get(mctx, sizeof(*portlist));
83 if (portlist == NULL)
84 return (ISC_R_NOMEMORY);
85 result = isc_mutex_init(&portlist->lock);
86 if (result != ISC_R_SUCCESS) {
87 isc_mem_put(mctx, portlist, sizeof(*portlist));
88 return (result);
90 result = isc_refcount_init(&portlist->refcount, 1);
91 if (result != ISC_R_SUCCESS) {
92 DESTROYLOCK(&portlist->lock);
93 isc_mem_put(mctx, portlist, sizeof(*portlist));
94 return (result);
96 portlist->list = NULL;
97 portlist->allocated = 0;
98 portlist->active = 0;
99 portlist->mctx = NULL;
100 isc_mem_attach(mctx, &portlist->mctx);
101 portlist->magic = DNS_PORTLIST_MAGIC;
102 *portlistp = portlist;
103 return (ISC_R_SUCCESS);
106 static dns_element_t *
107 find_port(dns_element_t *list, unsigned int len, in_port_t port) {
108 unsigned int xtry = len / 2;
109 unsigned int min = 0;
110 unsigned int max = len - 1;
111 unsigned int last = len;
113 for (;;) {
114 if (list[xtry].port == port)
115 return (&list[xtry]);
116 if (port > list[xtry].port) {
117 if (xtry == max)
118 break;
119 min = xtry;
120 xtry = xtry + (max - xtry + 1) / 2;
121 INSIST(xtry <= max);
122 if (xtry == last)
123 break;
124 last = min;
125 } else {
126 if (xtry == min)
127 break;
128 max = xtry;
129 xtry = xtry - (xtry - min + 1) / 2;
130 INSIST(xtry >= min);
131 if (xtry == last)
132 break;
133 last = max;
136 return (NULL);
139 isc_result_t
140 dns_portlist_add(dns_portlist_t *portlist, int af, in_port_t port) {
141 dns_element_t *el;
142 isc_result_t result;
144 REQUIRE(DNS_VALID_PORTLIST(portlist));
145 REQUIRE(af == AF_INET || af == AF_INET6);
147 LOCK(&portlist->lock);
148 if (portlist->active != 0) {
149 el = find_port(portlist->list, portlist->active, port);
150 if (el != NULL) {
151 if (af == AF_INET)
152 el->flags |= DNS_PL_INET;
153 else
154 el->flags |= DNS_PL_INET6;
155 result = ISC_R_SUCCESS;
156 goto unlock;
160 if (portlist->allocated <= portlist->active) {
161 unsigned int allocated;
162 allocated = portlist->allocated + DNS_PL_ALLOCATE;
163 el = isc_mem_get(portlist->mctx, sizeof(*el) * allocated);
164 if (el == NULL) {
165 result = ISC_R_NOMEMORY;
166 goto unlock;
168 if (portlist->list != NULL) {
169 memmove(el, portlist->list,
170 portlist->allocated * sizeof(*el));
171 isc_mem_put(portlist->mctx, portlist->list,
172 portlist->allocated * sizeof(*el));
174 portlist->list = el;
175 portlist->allocated = allocated;
177 portlist->list[portlist->active].port = port;
178 if (af == AF_INET)
179 portlist->list[portlist->active].flags = DNS_PL_INET;
180 else
181 portlist->list[portlist->active].flags = DNS_PL_INET6;
182 portlist->active++;
183 qsort(portlist->list, portlist->active, sizeof(*el), compare);
184 result = ISC_R_SUCCESS;
185 unlock:
186 UNLOCK(&portlist->lock);
187 return (result);
190 void
191 dns_portlist_remove(dns_portlist_t *portlist, int af, in_port_t port) {
192 dns_element_t *el;
194 REQUIRE(DNS_VALID_PORTLIST(portlist));
195 REQUIRE(af == AF_INET || af == AF_INET6);
197 LOCK(&portlist->lock);
198 if (portlist->active != 0) {
199 el = find_port(portlist->list, portlist->active, port);
200 if (el != NULL) {
201 if (af == AF_INET)
202 el->flags &= ~DNS_PL_INET;
203 else
204 el->flags &= ~DNS_PL_INET6;
205 if (el->flags == 0) {
206 *el = portlist->list[portlist->active];
207 portlist->active--;
208 qsort(portlist->list, portlist->active,
209 sizeof(*el), compare);
213 UNLOCK(&portlist->lock);
216 isc_boolean_t
217 dns_portlist_match(dns_portlist_t *portlist, int af, in_port_t port) {
218 dns_element_t *el;
219 isc_boolean_t result = ISC_FALSE;
221 REQUIRE(DNS_VALID_PORTLIST(portlist));
222 REQUIRE(af == AF_INET || af == AF_INET6);
223 LOCK(&portlist->lock);
224 if (portlist->active != 0) {
225 el = find_port(portlist->list, portlist->active, port);
226 if (el != NULL) {
227 if (af == AF_INET && (el->flags & DNS_PL_INET) != 0)
228 result = ISC_TRUE;
229 if (af == AF_INET6 && (el->flags & DNS_PL_INET6) != 0)
230 result = ISC_TRUE;
233 UNLOCK(&portlist->lock);
234 return (result);
237 void
238 dns_portlist_attach(dns_portlist_t *portlist, dns_portlist_t **portlistp) {
240 REQUIRE(DNS_VALID_PORTLIST(portlist));
241 REQUIRE(portlistp != NULL && *portlistp == NULL);
243 isc_refcount_increment(&portlist->refcount, NULL);
244 *portlistp = portlist;
247 void
248 dns_portlist_detach(dns_portlist_t **portlistp) {
249 dns_portlist_t *portlist;
250 unsigned int count;
252 REQUIRE(portlistp != NULL);
253 portlist = *portlistp;
254 REQUIRE(DNS_VALID_PORTLIST(portlist));
255 *portlistp = NULL;
256 isc_refcount_decrement(&portlist->refcount, &count);
257 if (count == 0) {
258 portlist->magic = 0;
259 isc_refcount_destroy(&portlist->refcount);
260 if (portlist->list != NULL)
261 isc_mem_put(portlist->mctx, portlist->list,
262 portlist->allocated *
263 sizeof(*portlist->list));
264 DESTROYLOCK(&portlist->lock);
265 isc_mem_putanddetach(&portlist->mctx, portlist,
266 sizeof(*portlist));