1258945Sroberto/*
2258945Sroberto * Copyright (C) 2008  Internet Systems Consortium, Inc. ("ISC")
3258945Sroberto *
4258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any
5258945Sroberto * purpose with or without fee is hereby granted, provided that the above
6258945Sroberto * copyright notice and this permission notice appear in all copies.
7258945Sroberto *
8258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
9258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10258945Sroberto * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
11258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14258945Sroberto * PERFORMANCE OF THIS SOFTWARE.
15258945Sroberto */
16258945Sroberto
17258945Sroberto/* $Id: portset.c,v 1.4 2008/06/24 23:24:35 marka Exp $ */
18258945Sroberto
19258945Sroberto/*! \file */
20258945Sroberto
21258945Sroberto#include <config.h>
22258945Sroberto
23258945Sroberto#include <isc/mem.h>
24258945Sroberto#include <isc/portset.h>
25258945Sroberto#include <isc/string.h>
26258945Sroberto#include <isc/types.h>
27258945Sroberto#include <isc/util.h>
28258945Sroberto
29258945Sroberto#define ISC_PORTSET_BUFSIZE (65536 / (sizeof(isc_uint32_t) * 8))
30258945Sroberto
31258945Sroberto/*%
32258945Sroberto * Internal representation of portset.  It's an array of 32-bit integers, each
33258945Sroberto * bit corresponding to a single port in the ascending order.  For example,
34258945Sroberto * the second most significant bit of buf[0] corresponds to port 1.
35258945Sroberto */
36258945Srobertostruct isc_portset {
37258945Sroberto	unsigned int nports;	/*%< number of ports in the set */
38258945Sroberto	isc_uint32_t buf[ISC_PORTSET_BUFSIZE];
39258945Sroberto};
40258945Sroberto
41258945Srobertostatic inline isc_boolean_t
42258945Srobertoportset_isset(isc_portset_t *portset, in_port_t port) {
43258945Sroberto	return (ISC_TF((portset->buf[port >> 5] & (1 << (port & 31))) != 0));
44258945Sroberto}
45258945Sroberto
46258945Srobertostatic inline void
47258945Srobertoportset_add(isc_portset_t *portset, in_port_t port) {
48258945Sroberto	if (!portset_isset(portset, port)) {
49258945Sroberto		portset->nports++;
50258945Sroberto		portset->buf[port >> 5] |= (1 << (port & 31));
51258945Sroberto	}
52258945Sroberto}
53258945Sroberto
54258945Srobertostatic inline void
55258945Srobertoportset_remove(isc_portset_t *portset, in_port_t port) {
56258945Sroberto	if (portset_isset(portset, port)) {
57258945Sroberto		portset->nports--;
58258945Sroberto		portset->buf[port >> 5] &= ~(1 << (port & 31));
59258945Sroberto	}
60258945Sroberto}
61258945Sroberto
62258945Srobertoisc_result_t
63258945Srobertoisc_portset_create(isc_mem_t *mctx, isc_portset_t **portsetp) {
64258945Sroberto	isc_portset_t *portset;
65258945Sroberto
66258945Sroberto	REQUIRE(portsetp != NULL && *portsetp == NULL);
67258945Sroberto
68258945Sroberto	portset = isc_mem_get(mctx, sizeof(*portset));
69258945Sroberto	if (portset == NULL)
70258945Sroberto		return (ISC_R_NOMEMORY);
71258945Sroberto
72258945Sroberto	/* Make the set 'empty' by default */
73258945Sroberto	memset(portset, 0, sizeof(*portset));
74258945Sroberto	*portsetp = portset;
75258945Sroberto
76258945Sroberto	return (ISC_R_SUCCESS);
77258945Sroberto}
78258945Sroberto
79258945Srobertovoid
80258945Srobertoisc_portset_destroy(isc_mem_t *mctx, isc_portset_t **portsetp) {
81258945Sroberto	isc_portset_t *portset;
82258945Sroberto
83258945Sroberto	REQUIRE(portsetp != NULL);
84258945Sroberto	portset = *portsetp;
85258945Sroberto
86258945Sroberto	isc_mem_put(mctx, portset, sizeof(*portset));
87258945Sroberto}
88258945Sroberto
89258945Srobertoisc_boolean_t
90258945Srobertoisc_portset_isset(isc_portset_t *portset, in_port_t port) {
91258945Sroberto	REQUIRE(portset != NULL);
92258945Sroberto
93258945Sroberto	return (portset_isset(portset, port));
94258945Sroberto}
95258945Sroberto
96258945Srobertounsigned int
97258945Srobertoisc_portset_nports(isc_portset_t *portset) {
98258945Sroberto	REQUIRE(portset != NULL);
99258945Sroberto
100258945Sroberto	return (portset->nports);
101258945Sroberto}
102258945Sroberto
103258945Srobertovoid
104258945Srobertoisc_portset_add(isc_portset_t *portset, in_port_t port) {
105258945Sroberto	REQUIRE(portset != NULL);
106258945Sroberto
107258945Sroberto	portset_add(portset, port);
108258945Sroberto}
109258945Sroberto
110258945Srobertovoid
111258945Srobertoisc_portset_remove(isc_portset_t *portset, in_port_t port) {
112258945Sroberto	portset_remove(portset, port);
113258945Sroberto}
114258945Sroberto
115258945Srobertovoid
116258945Srobertoisc_portset_addrange(isc_portset_t *portset, in_port_t port_lo,
117258945Sroberto		     in_port_t port_hi)
118258945Sroberto{
119258945Sroberto	in_port_t p;
120258945Sroberto
121258945Sroberto	REQUIRE(portset != NULL);
122258945Sroberto	REQUIRE(port_lo <= port_hi);
123258945Sroberto
124258945Sroberto	p = port_lo;
125258945Sroberto	do {
126258945Sroberto		portset_add(portset, p);
127258945Sroberto	} while (p++ < port_hi);
128258945Sroberto}
129258945Sroberto
130258945Srobertovoid
131258945Srobertoisc_portset_removerange(isc_portset_t *portset, in_port_t port_lo,
132258945Sroberto			in_port_t port_hi)
133258945Sroberto{
134258945Sroberto	in_port_t p;
135258945Sroberto
136258945Sroberto	REQUIRE(portset != NULL);
137258945Sroberto	REQUIRE(port_lo <= port_hi);
138258945Sroberto
139258945Sroberto	p = port_lo;
140258945Sroberto	do {
141258945Sroberto		portset_remove(portset, p);
142258945Sroberto	} while (p++ < port_hi);
143258945Sroberto}
144