1 /* $NetBSD: compress.h,v 1.1 2024/02/18 20:57:35 christos Exp $ */ 2 3 /* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 5 * 6 * SPDX-License-Identifier: MPL-2.0 7 * 8 * This Source Code Form is subject to the terms of the Mozilla Public 9 * License, v. 2.0. If a copy of the MPL was not distributed with this 10 * file, you can obtain one at https://mozilla.org/MPL/2.0/. 11 * 12 * See the COPYRIGHT file distributed with this work for additional 13 * information regarding copyright ownership. 14 */ 15 16 #ifndef DNS_COMPRESS_H 17 #define DNS_COMPRESS_H 1 18 19 #include <inttypes.h> 20 #include <stdbool.h> 21 22 #include <isc/lang.h> 23 #include <isc/region.h> 24 25 #include <dns/name.h> 26 #include <dns/types.h> 27 28 ISC_LANG_BEGINDECLS 29 30 /*! \file dns/compress.h 31 * Direct manipulation of the structures is strongly discouraged. 32 * 33 * A name compression context handles compression of multiple DNS names 34 * in relation to a single DNS message. The context can be used to 35 * selectively turn on/off compression for specific names (depending on 36 * the RR type) by using \c dns_compress_setmethods(). Alternately, 37 * compression can be disabled completely using \c 38 * dns_compress_disable(). 39 * 40 * \c dns_compress_setmethods() is intended for use by RDATA towire() 41 * implementations, whereas \c dns_compress_disable() is intended to be 42 * used by a nameserver's configuration manager. 43 */ 44 45 #define DNS_COMPRESS_NONE 0x00 /*%< no compression */ 46 #define DNS_COMPRESS_GLOBAL14 0x01 /*%< "normal" compression. */ 47 #define DNS_COMPRESS_ALL 0x01 /*%< all compression. */ 48 #define DNS_COMPRESS_CASESENSITIVE 0x02 /*%< case sensitive compression. */ 49 #define DNS_COMPRESS_ENABLED 0x04 50 51 /* 52 * DNS_COMPRESS_TABLESIZE must be a power of 2. The compress code 53 * utilizes this assumption. 54 */ 55 #define DNS_COMPRESS_TABLEBITS 6 56 #define DNS_COMPRESS_TABLESIZE (1U << DNS_COMPRESS_TABLEBITS) 57 #define DNS_COMPRESS_TABLEMASK (DNS_COMPRESS_TABLESIZE - 1) 58 #define DNS_COMPRESS_INITIALNODES 24 59 #define DNS_COMPRESS_ARENA_SIZE 640 60 61 typedef struct dns_compressnode dns_compressnode_t; 62 63 struct dns_compressnode { 64 dns_compressnode_t *next; 65 uint16_t offset; 66 uint16_t count; 67 isc_region_t r; 68 dns_name_t name; 69 }; 70 71 struct dns_compress { 72 unsigned int magic; /*%< Magic number. */ 73 unsigned int allowed; /*%< Allowed methods. */ 74 int edns; /*%< Edns version or -1. */ 75 /*% Global compression table. */ 76 dns_compressnode_t *table[DNS_COMPRESS_TABLESIZE]; 77 /*% Preallocated arena for names. */ 78 unsigned char arena[DNS_COMPRESS_ARENA_SIZE]; 79 off_t arena_off; 80 /*% Preallocated nodes for the table. */ 81 dns_compressnode_t initialnodes[DNS_COMPRESS_INITIALNODES]; 82 uint16_t count; /*%< Number of nodes. */ 83 isc_mem_t *mctx; /*%< Memory context. */ 84 }; 85 86 typedef enum { 87 DNS_DECOMPRESS_ANY, /*%< Any compression */ 88 DNS_DECOMPRESS_STRICT, /*%< Allowed compression */ 89 DNS_DECOMPRESS_NONE /*%< No compression */ 90 } dns_decompresstype_t; 91 92 struct dns_decompress { 93 unsigned int magic; /*%< Magic number. */ 94 unsigned int allowed; /*%< Allowed methods. */ 95 int edns; /*%< Edns version or -1. */ 96 dns_decompresstype_t type; /*%< Strict checking */ 97 }; 98 99 isc_result_t 100 dns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx); 101 /*%< 102 * Initialise the compression context structure pointed to by 103 * 'cctx'. A freshly initialized context has name compression 104 * enabled, but no methods are set. Please use \c 105 * dns_compress_setmethods() to set a compression method. 106 * 107 * Requires: 108 * \li 'cctx' is a valid dns_compress_t structure. 109 * \li 'mctx' is an initialized memory context. 110 * Ensures: 111 * \li cctx->global is initialized. 112 * 113 * Returns: 114 * \li #ISC_R_SUCCESS 115 */ 116 117 void 118 dns_compress_invalidate(dns_compress_t *cctx); 119 120 /*%< 121 * Invalidate the compression structure pointed to by cctx. 122 * 123 * Requires: 124 *\li 'cctx' to be initialized. 125 */ 126 127 void 128 dns_compress_setmethods(dns_compress_t *cctx, unsigned int allowed); 129 130 /*%< 131 * Sets allowed compression methods. 132 * 133 * Requires: 134 *\li 'cctx' to be initialized. 135 */ 136 137 unsigned int 138 dns_compress_getmethods(dns_compress_t *cctx); 139 140 /*%< 141 * Gets allowed compression methods. 142 * 143 * Requires: 144 *\li 'cctx' to be initialized. 145 * 146 * Returns: 147 *\li allowed compression bitmap. 148 */ 149 150 void 151 dns_compress_disable(dns_compress_t *cctx); 152 /*%< 153 * Disables all name compression in the context. Once disabled, 154 * name compression cannot currently be re-enabled. 155 * 156 * Requires: 157 *\li 'cctx' to be initialized. 158 * 159 */ 160 161 void 162 dns_compress_setsensitive(dns_compress_t *cctx, bool sensitive); 163 164 /* 165 * Preserve the case of compressed domain names. 166 * 167 * Requires: 168 * 'cctx' to be initialized. 169 */ 170 171 bool 172 dns_compress_getsensitive(dns_compress_t *cctx); 173 /* 174 * Return whether case is to be preserved when compressing 175 * domain names. 176 * 177 * Requires: 178 * 'cctx' to be initialized. 179 */ 180 181 int 182 dns_compress_getedns(dns_compress_t *cctx); 183 184 /*%< 185 * Gets edns value. 186 * 187 * Requires: 188 *\li 'cctx' to be initialized. 189 * 190 * Returns: 191 *\li -1 .. 255 192 */ 193 194 bool 195 dns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name, 196 dns_name_t *prefix, uint16_t *offset); 197 /*%< 198 * Finds longest possible match of 'name' in the global compression table. 199 * 200 * Requires: 201 *\li 'cctx' to be initialized. 202 *\li 'name' to be a absolute name. 203 *\li 'prefix' to be initialized. 204 *\li 'offset' to point to an uint16_t. 205 * 206 * Ensures: 207 *\li 'prefix' and 'offset' are valid if true is returned. 208 * 209 * Returns: 210 *\li #true / #false 211 */ 212 213 void 214 dns_compress_add(dns_compress_t *cctx, const dns_name_t *name, 215 const dns_name_t *prefix, uint16_t offset); 216 /*%< 217 * Add compression pointers for 'name' to the compression table, 218 * not replacing existing pointers. 219 * 220 * Requires: 221 *\li 'cctx' initialized 222 * 223 *\li 'name' must be initialized and absolute, and must remain 224 * valid until the message compression is complete. 225 * 226 *\li 'prefix' must be a prefix returned by 227 * dns_compress_findglobal(), or the same as 'name'. 228 */ 229 230 void 231 dns_compress_rollback(dns_compress_t *cctx, uint16_t offset); 232 233 /*%< 234 * Remove any compression pointers from global table >= offset. 235 * 236 * Requires: 237 *\li 'cctx' is initialized. 238 */ 239 240 void 241 dns_decompress_init(dns_decompress_t *dctx, int edns, 242 dns_decompresstype_t type); 243 244 /*%< 245 * Initializes 'dctx'. 246 * Records 'edns' and 'type' into the structure. 247 * 248 * Requires: 249 *\li 'dctx' to be a valid pointer. 250 */ 251 252 void 253 dns_decompress_invalidate(dns_decompress_t *dctx); 254 255 /*%< 256 * Invalidates 'dctx'. 257 * 258 * Requires: 259 *\li 'dctx' to be initialized 260 */ 261 262 void 263 dns_decompress_setmethods(dns_decompress_t *dctx, unsigned int allowed); 264 265 /*%< 266 * Sets 'dctx->allowed' to 'allowed'. 267 * 268 * Requires: 269 *\li 'dctx' to be initialized 270 */ 271 272 unsigned int 273 dns_decompress_getmethods(dns_decompress_t *dctx); 274 275 /*%< 276 * Returns 'dctx->allowed' 277 * 278 * Requires: 279 *\li 'dctx' to be initialized 280 */ 281 282 int 283 dns_decompress_edns(dns_decompress_t *dctx); 284 285 /*%< 286 * Returns 'dctx->edns' 287 * 288 * Requires: 289 *\li 'dctx' to be initialized 290 */ 291 292 dns_decompresstype_t 293 dns_decompress_type(dns_decompress_t *dctx); 294 295 /*%< 296 * Returns 'dctx->type' 297 * 298 * Requires: 299 *\li 'dctx' to be initialized 300 */ 301 302 ISC_LANG_ENDDECLS 303 304 #endif /* DNS_COMPRESS_H */ 305