xref: /netbsd-src/external/mpl/bind/dist/lib/isc/portset.c (revision bcda20f65a8566e103791ec395f7f499ef322704)
1*bcda20f6Schristos /*	$NetBSD: portset.c,v 1.7 2025/01/26 16:25:38 christos Exp $	*/
2d68c78b8Schristos 
3d68c78b8Schristos /*
4d68c78b8Schristos  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
5d68c78b8Schristos  *
68596601aSchristos  * SPDX-License-Identifier: MPL-2.0
78596601aSchristos  *
8d68c78b8Schristos  * This Source Code Form is subject to the terms of the Mozilla Public
9d68c78b8Schristos  * License, v. 2.0. If a copy of the MPL was not distributed with this
10fce770bdSchristos  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
11d68c78b8Schristos  *
12d68c78b8Schristos  * See the COPYRIGHT file distributed with this work for additional
13d68c78b8Schristos  * information regarding copyright ownership.
14d68c78b8Schristos  */
15d68c78b8Schristos 
16d68c78b8Schristos /*! \file */
17d68c78b8Schristos 
18d4a20c3eSchristos #include <inttypes.h>
195606745fSchristos #include <stdbool.h>
20d4a20c3eSchristos 
21d68c78b8Schristos #include <isc/mem.h>
22d68c78b8Schristos #include <isc/portset.h>
23d68c78b8Schristos #include <isc/string.h>
24d68c78b8Schristos #include <isc/types.h>
25d68c78b8Schristos #include <isc/util.h>
26d68c78b8Schristos 
27d4a20c3eSchristos #define ISC_PORTSET_BUFSIZE (65536 / (sizeof(uint32_t) * 8))
28d68c78b8Schristos 
29d68c78b8Schristos /*%
30d68c78b8Schristos  * Internal representation of portset.  It's an array of 32-bit integers, each
31d68c78b8Schristos  * bit corresponding to a single port in the ascending order.  For example,
32d68c78b8Schristos  * the second most significant bit of buf[0] corresponds to port 1.
33d68c78b8Schristos  */
34d68c78b8Schristos struct isc_portset {
35d68c78b8Schristos 	unsigned int nports; /*%< number of ports in the set */
36d4a20c3eSchristos 	uint32_t buf[ISC_PORTSET_BUFSIZE];
37d68c78b8Schristos };
38d68c78b8Schristos 
398596601aSchristos static bool
40d68c78b8Schristos portset_isset(isc_portset_t *portset, in_port_t port) {
41*bcda20f6Schristos 	return (portset->buf[port >> 5] & ((uint32_t)1 << (port & 31))) != 0;
42d68c78b8Schristos }
43d68c78b8Schristos 
448596601aSchristos static void
45d68c78b8Schristos portset_add(isc_portset_t *portset, in_port_t port) {
46d68c78b8Schristos 	if (!portset_isset(portset, port)) {
47d68c78b8Schristos 		portset->nports++;
48d4a20c3eSchristos 		portset->buf[port >> 5] |= ((uint32_t)1 << (port & 31));
49d68c78b8Schristos 	}
50d68c78b8Schristos }
51d68c78b8Schristos 
528596601aSchristos static void
53d68c78b8Schristos portset_remove(isc_portset_t *portset, in_port_t port) {
54d68c78b8Schristos 	if (portset_isset(portset, port)) {
55d68c78b8Schristos 		portset->nports--;
56d4a20c3eSchristos 		portset->buf[port >> 5] &= ~((uint32_t)1 << (port & 31));
57d68c78b8Schristos 	}
58d68c78b8Schristos }
59d68c78b8Schristos 
60d68c78b8Schristos isc_result_t
61d68c78b8Schristos isc_portset_create(isc_mem_t *mctx, isc_portset_t **portsetp) {
62d68c78b8Schristos 	isc_portset_t *portset;
63d68c78b8Schristos 
64d68c78b8Schristos 	REQUIRE(portsetp != NULL && *portsetp == NULL);
65d68c78b8Schristos 
66d68c78b8Schristos 	portset = isc_mem_get(mctx, sizeof(*portset));
67*bcda20f6Schristos 	*portset = (isc_portset_t){ 0 };
68d68c78b8Schristos 	*portsetp = portset;
69d68c78b8Schristos 
70*bcda20f6Schristos 	return ISC_R_SUCCESS;
71d68c78b8Schristos }
72d68c78b8Schristos 
73d68c78b8Schristos void
74d68c78b8Schristos isc_portset_destroy(isc_mem_t *mctx, isc_portset_t **portsetp) {
75d68c78b8Schristos 	isc_portset_t *portset;
76d68c78b8Schristos 
77d68c78b8Schristos 	REQUIRE(portsetp != NULL);
78d68c78b8Schristos 	portset = *portsetp;
79d68c78b8Schristos 
80d68c78b8Schristos 	isc_mem_put(mctx, portset, sizeof(*portset));
81d68c78b8Schristos }
82d68c78b8Schristos 
83d4a20c3eSchristos bool
84d68c78b8Schristos isc_portset_isset(isc_portset_t *portset, in_port_t port) {
85d68c78b8Schristos 	REQUIRE(portset != NULL);
86d68c78b8Schristos 
87*bcda20f6Schristos 	return portset_isset(portset, port);
88d68c78b8Schristos }
89d68c78b8Schristos 
90d68c78b8Schristos unsigned int
91d68c78b8Schristos isc_portset_nports(isc_portset_t *portset) {
92d68c78b8Schristos 	REQUIRE(portset != NULL);
93d68c78b8Schristos 
94*bcda20f6Schristos 	return portset->nports;
95d68c78b8Schristos }
96d68c78b8Schristos 
97d68c78b8Schristos void
98d68c78b8Schristos isc_portset_add(isc_portset_t *portset, in_port_t port) {
99d68c78b8Schristos 	REQUIRE(portset != NULL);
100d68c78b8Schristos 
101d68c78b8Schristos 	portset_add(portset, port);
102d68c78b8Schristos }
103d68c78b8Schristos 
104d68c78b8Schristos void
105d68c78b8Schristos isc_portset_remove(isc_portset_t *portset, in_port_t port) {
106d68c78b8Schristos 	portset_remove(portset, port);
107d68c78b8Schristos }
108d68c78b8Schristos 
109d68c78b8Schristos void
110d68c78b8Schristos isc_portset_addrange(isc_portset_t *portset, in_port_t port_lo,
1115606745fSchristos 		     in_port_t port_hi) {
112d68c78b8Schristos 	in_port_t p;
113d68c78b8Schristos 
114d68c78b8Schristos 	REQUIRE(portset != NULL);
115d68c78b8Schristos 	REQUIRE(port_lo <= port_hi);
116d68c78b8Schristos 
117d68c78b8Schristos 	p = port_lo;
118d68c78b8Schristos 	do {
119d68c78b8Schristos 		portset_add(portset, p);
120d68c78b8Schristos 	} while (p++ < port_hi);
121d68c78b8Schristos }
122d68c78b8Schristos 
123d68c78b8Schristos void
124d68c78b8Schristos isc_portset_removerange(isc_portset_t *portset, in_port_t port_lo,
1255606745fSchristos 			in_port_t port_hi) {
126d68c78b8Schristos 	in_port_t p;
127d68c78b8Schristos 
128d68c78b8Schristos 	REQUIRE(portset != NULL);
129d68c78b8Schristos 	REQUIRE(port_lo <= port_hi);
130d68c78b8Schristos 
131d68c78b8Schristos 	p = port_lo;
132d68c78b8Schristos 	do {
133d68c78b8Schristos 		portset_remove(portset, p);
134d68c78b8Schristos 	} while (p++ < port_hi);
135d68c78b8Schristos }
136