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