portset.c revision 290001
1/* 2 * Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC") 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 13 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 * PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17/* $Id: portset.c,v 1.4 2008/06/24 23:24:35 marka Exp $ */ 18 19/*! \file */ 20 21#include <config.h> 22 23#include <isc/mem.h> 24#include <isc/portset.h> 25#include <isc/string.h> 26#include <isc/types.h> 27#include <isc/util.h> 28 29#define ISC_PORTSET_BUFSIZE (65536 / (sizeof(isc_uint32_t) * 8)) 30 31/*% 32 * Internal representation of portset. It's an array of 32-bit integers, each 33 * bit corresponding to a single port in the ascending order. For example, 34 * the second most significant bit of buf[0] corresponds to port 1. 35 */ 36struct isc_portset { 37 unsigned int nports; /*%< number of ports in the set */ 38 isc_uint32_t buf[ISC_PORTSET_BUFSIZE]; 39}; 40 41static inline isc_boolean_t 42portset_isset(isc_portset_t *portset, in_port_t port) { 43 return (ISC_TF((portset->buf[port >> 5] & (1 << (port & 31))) != 0)); 44} 45 46static inline void 47portset_add(isc_portset_t *portset, in_port_t port) { 48 if (!portset_isset(portset, port)) { 49 portset->nports++; 50 portset->buf[port >> 5] |= (1 << (port & 31)); 51 } 52} 53 54static inline void 55portset_remove(isc_portset_t *portset, in_port_t port) { 56 if (portset_isset(portset, port)) { 57 portset->nports--; 58 portset->buf[port >> 5] &= ~(1 << (port & 31)); 59 } 60} 61 62isc_result_t 63isc_portset_create(isc_mem_t *mctx, isc_portset_t **portsetp) { 64 isc_portset_t *portset; 65 66 REQUIRE(portsetp != NULL && *portsetp == NULL); 67 68 portset = isc_mem_get(mctx, sizeof(*portset)); 69 if (portset == NULL) 70 return (ISC_R_NOMEMORY); 71 72 /* Make the set 'empty' by default */ 73 memset(portset, 0, sizeof(*portset)); 74 *portsetp = portset; 75 76 return (ISC_R_SUCCESS); 77} 78 79void 80isc_portset_destroy(isc_mem_t *mctx, isc_portset_t **portsetp) { 81 isc_portset_t *portset; 82 83 REQUIRE(portsetp != NULL); 84 portset = *portsetp; 85 86 isc_mem_put(mctx, portset, sizeof(*portset)); 87} 88 89isc_boolean_t 90isc_portset_isset(isc_portset_t *portset, in_port_t port) { 91 REQUIRE(portset != NULL); 92 93 return (portset_isset(portset, port)); 94} 95 96unsigned int 97isc_portset_nports(isc_portset_t *portset) { 98 REQUIRE(portset != NULL); 99 100 return (portset->nports); 101} 102 103void 104isc_portset_add(isc_portset_t *portset, in_port_t port) { 105 REQUIRE(portset != NULL); 106 107 portset_add(portset, port); 108} 109 110void 111isc_portset_remove(isc_portset_t *portset, in_port_t port) { 112 portset_remove(portset, port); 113} 114 115void 116isc_portset_addrange(isc_portset_t *portset, in_port_t port_lo, 117 in_port_t port_hi) 118{ 119 in_port_t p; 120 121 REQUIRE(portset != NULL); 122 REQUIRE(port_lo <= port_hi); 123 124 p = port_lo; 125 do { 126 portset_add(portset, p); 127 } while (p++ < port_hi); 128} 129 130void 131isc_portset_removerange(isc_portset_t *portset, in_port_t port_lo, 132 in_port_t port_hi) 133{ 134 in_port_t p; 135 136 REQUIRE(portset != NULL); 137 REQUIRE(port_lo <= port_hi); 138 139 p = port_lo; 140 do { 141 portset_remove(portset, p); 142 } while (p++ < port_hi); 143} 144