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