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