1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * SPDX-License-Identifier: MPL-2.0
5 *
6 * This Source Code Form is subject to the terms of the Mozilla Public
7 * License, v. 2.0. If a copy of the MPL was not distributed with this
8 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9 *
10 * See the COPYRIGHT file distributed with this work for additional
11 * information regarding copyright ownership.
12 */
13
14 /*! \file */
15
16 #include <stdbool.h>
17
18 #include <isc/mem.h>
19 #include <isc/util.h>
20
21 #include <dns/acl.h>
22
23 #include <ns/listenlist.h>
24
25 static void
26 destroy(ns_listenlist_t *list);
27
28 isc_result_t
ns_listenelt_create(isc_mem_t * mctx,in_port_t port,isc_dscp_t dscp,dns_acl_t * acl,ns_listenelt_t ** target)29 ns_listenelt_create(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
30 dns_acl_t *acl, ns_listenelt_t **target) {
31 ns_listenelt_t *elt = NULL;
32 REQUIRE(target != NULL && *target == NULL);
33 elt = isc_mem_get(mctx, sizeof(*elt));
34 elt->mctx = mctx;
35 ISC_LINK_INIT(elt, link);
36 elt->port = port;
37 elt->dscp = dscp;
38 elt->acl = acl;
39 *target = elt;
40 return (ISC_R_SUCCESS);
41 }
42
43 void
ns_listenelt_destroy(ns_listenelt_t * elt)44 ns_listenelt_destroy(ns_listenelt_t *elt) {
45 if (elt->acl != NULL) {
46 dns_acl_detach(&elt->acl);
47 }
48 isc_mem_put(elt->mctx, elt, sizeof(*elt));
49 }
50
51 isc_result_t
ns_listenlist_create(isc_mem_t * mctx,ns_listenlist_t ** target)52 ns_listenlist_create(isc_mem_t *mctx, ns_listenlist_t **target) {
53 ns_listenlist_t *list = NULL;
54 REQUIRE(target != NULL && *target == NULL);
55 list = isc_mem_get(mctx, sizeof(*list));
56 list->mctx = mctx;
57 list->refcount = 1;
58 ISC_LIST_INIT(list->elts);
59 *target = list;
60 return (ISC_R_SUCCESS);
61 }
62
63 static void
destroy(ns_listenlist_t * list)64 destroy(ns_listenlist_t *list) {
65 ns_listenelt_t *elt, *next;
66 for (elt = ISC_LIST_HEAD(list->elts); elt != NULL; elt = next) {
67 next = ISC_LIST_NEXT(elt, link);
68 ns_listenelt_destroy(elt);
69 }
70 isc_mem_put(list->mctx, list, sizeof(*list));
71 }
72
73 void
ns_listenlist_attach(ns_listenlist_t * source,ns_listenlist_t ** target)74 ns_listenlist_attach(ns_listenlist_t *source, ns_listenlist_t **target) {
75 INSIST(source->refcount > 0);
76 source->refcount++;
77 *target = source;
78 }
79
80 void
ns_listenlist_detach(ns_listenlist_t ** listp)81 ns_listenlist_detach(ns_listenlist_t **listp) {
82 ns_listenlist_t *list = *listp;
83 *listp = NULL;
84 INSIST(list->refcount > 0);
85 list->refcount--;
86 if (list->refcount == 0) {
87 destroy(list);
88 }
89 }
90
91 isc_result_t
ns_listenlist_default(isc_mem_t * mctx,in_port_t port,isc_dscp_t dscp,bool enabled,ns_listenlist_t ** target)92 ns_listenlist_default(isc_mem_t *mctx, in_port_t port, isc_dscp_t dscp,
93 bool enabled, ns_listenlist_t **target) {
94 isc_result_t result;
95 dns_acl_t *acl = NULL;
96 ns_listenelt_t *elt = NULL;
97 ns_listenlist_t *list = NULL;
98
99 REQUIRE(target != NULL && *target == NULL);
100 if (enabled) {
101 result = dns_acl_any(mctx, &acl);
102 } else {
103 result = dns_acl_none(mctx, &acl);
104 }
105 if (result != ISC_R_SUCCESS) {
106 goto cleanup;
107 }
108
109 result = ns_listenelt_create(mctx, port, dscp, acl, &elt);
110 if (result != ISC_R_SUCCESS) {
111 goto cleanup_acl;
112 }
113
114 result = ns_listenlist_create(mctx, &list);
115 if (result != ISC_R_SUCCESS) {
116 goto cleanup_listenelt;
117 }
118
119 ISC_LIST_APPEND(list->elts, elt, link);
120
121 *target = list;
122 return (ISC_R_SUCCESS);
123
124 cleanup_listenelt:
125 ns_listenelt_destroy(elt);
126 cleanup_acl:
127 dns_acl_detach(&acl);
128 cleanup:
129 return (result);
130 }
131