00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #define DNS_NAME_USEINLINE 1
00023
00024 #include <config.h>
00025
00026 #include <isc/mem.h>
00027 #include <isc/string.h>
00028 #include <isc/util.h>
00029
00030 #include <dns/compress.h>
00031 #include <dns/fixedname.h>
00032 #include <dns/rbt.h>
00033 #include <dns/result.h>
00034
00035 #define CCTX_MAGIC ISC_MAGIC('C', 'C', 'T', 'X')
00036 #define VALID_CCTX(x) ISC_MAGIC_VALID(x, CCTX_MAGIC)
00037
00038 #define DCTX_MAGIC ISC_MAGIC('D', 'C', 'T', 'X')
00039 #define VALID_DCTX(x) ISC_MAGIC_VALID(x, DCTX_MAGIC)
00040
00041
00042
00043
00044
00045 isc_result_t
00046 dns_compress_init(dns_compress_t *cctx, int edns, isc_mem_t *mctx) {
00047 unsigned int i;
00048
00049 REQUIRE(cctx != NULL);
00050 REQUIRE(mctx != NULL);
00051
00052 cctx->allowed = 0;
00053 cctx->edns = edns;
00054 for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++)
00055 cctx->table[i] = NULL;
00056 cctx->mctx = mctx;
00057 cctx->count = 0;
00058 cctx->magic = CCTX_MAGIC;
00059 return (ISC_R_SUCCESS);
00060 }
00061
00062 void
00063 dns_compress_invalidate(dns_compress_t *cctx) {
00064 dns_compressnode_t *node;
00065 unsigned int i;
00066
00067 REQUIRE(VALID_CCTX(cctx));
00068
00069 cctx->magic = 0;
00070 for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++) {
00071 while (cctx->table[i] != NULL) {
00072 node = cctx->table[i];
00073 cctx->table[i] = cctx->table[i]->next;
00074 if ((node->offset & 0x8000) != 0)
00075 isc_mem_put(cctx->mctx, node->r.base,
00076 node->r.length);
00077 if (node->count < DNS_COMPRESS_INITIALNODES)
00078 continue;
00079 isc_mem_put(cctx->mctx, node, sizeof(*node));
00080 }
00081 }
00082 cctx->allowed = 0;
00083 cctx->edns = -1;
00084 }
00085
00086 void
00087 dns_compress_setmethods(dns_compress_t *cctx, unsigned int allowed) {
00088 REQUIRE(VALID_CCTX(cctx));
00089
00090 cctx->allowed &= ~DNS_COMPRESS_ALL;
00091 cctx->allowed |= (allowed & DNS_COMPRESS_ALL);
00092 }
00093
00094 unsigned int
00095 dns_compress_getmethods(dns_compress_t *cctx) {
00096 REQUIRE(VALID_CCTX(cctx));
00097 return (cctx->allowed & DNS_COMPRESS_ALL);
00098 }
00099
00100 void
00101 dns_compress_setsensitive(dns_compress_t *cctx, isc_boolean_t sensitive) {
00102 REQUIRE(VALID_CCTX(cctx));
00103
00104 if (sensitive)
00105 cctx->allowed |= DNS_COMPRESS_CASESENSITIVE;
00106 else
00107 cctx->allowed &= ~DNS_COMPRESS_CASESENSITIVE;
00108 }
00109
00110 isc_boolean_t
00111 dns_compress_getsensitive(dns_compress_t *cctx) {
00112 REQUIRE(VALID_CCTX(cctx));
00113
00114 return (ISC_TF((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0));
00115 }
00116
00117 int
00118 dns_compress_getedns(dns_compress_t *cctx) {
00119 REQUIRE(VALID_CCTX(cctx));
00120 return (cctx->edns);
00121 }
00122
00123 #define NODENAME(node, name) \
00124 do { \
00125 (name)->length = (node)->r.length; \
00126 (name)->labels = (node)->labels; \
00127 (name)->ndata = (node)->r.base; \
00128 (name)->attributes = DNS_NAMEATTR_ABSOLUTE; \
00129 } while (0)
00130
00131
00132
00133
00134
00135
00136 isc_boolean_t
00137 dns_compress_findglobal(dns_compress_t *cctx, const dns_name_t *name,
00138 dns_name_t *prefix, isc_uint16_t *offset)
00139 {
00140 dns_name_t tname, nname;
00141 dns_compressnode_t *node = NULL;
00142 unsigned int labels, hash, n;
00143
00144 REQUIRE(VALID_CCTX(cctx));
00145 REQUIRE(dns_name_isabsolute(name) == ISC_TRUE);
00146 REQUIRE(offset != NULL);
00147
00148 if (cctx->count == 0)
00149 return (ISC_FALSE);
00150
00151 labels = dns_name_countlabels(name);
00152 INSIST(labels > 0);
00153
00154 dns_name_init(&tname, NULL);
00155 dns_name_init(&nname, NULL);
00156
00157 for (n = 0; n < labels - 1; n++) {
00158 dns_name_getlabelsequence(name, n, labels - n, &tname);
00159 hash = dns_name_hash(&tname, ISC_FALSE) %
00160 DNS_COMPRESS_TABLESIZE;
00161 for (node = cctx->table[hash]; node != NULL; node = node->next)
00162 {
00163 NODENAME(node, &nname);
00164 if ((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0) {
00165 if (dns_name_caseequal(&nname, &tname))
00166 break;
00167 } else {
00168 if (dns_name_equal(&nname, &tname))
00169 break;
00170 }
00171 }
00172 if (node != NULL)
00173 break;
00174 }
00175
00176
00177
00178
00179 if (node == NULL)
00180 return (ISC_FALSE);
00181
00182 if (n == 0)
00183 dns_name_reset(prefix);
00184 else
00185 dns_name_getlabelsequence(name, 0, n, prefix);
00186
00187 *offset = (node->offset & 0x7fff);
00188 return (ISC_TRUE);
00189 }
00190
00191 static inline unsigned int
00192 name_length(const dns_name_t *name) {
00193 isc_region_t r;
00194 dns_name_toregion(name, &r);
00195 return (r.length);
00196 }
00197
00198 void
00199 dns_compress_add(dns_compress_t *cctx, const dns_name_t *name,
00200 const dns_name_t *prefix, isc_uint16_t offset)
00201 {
00202 dns_name_t tname, xname;
00203 unsigned int start;
00204 unsigned int n;
00205 unsigned int count;
00206 unsigned int hash;
00207 dns_compressnode_t *node;
00208 unsigned int length;
00209 unsigned int tlength;
00210 isc_uint16_t toffset;
00211 unsigned char *tmp;
00212 isc_region_t r;
00213
00214 REQUIRE(VALID_CCTX(cctx));
00215 REQUIRE(dns_name_isabsolute(name));
00216
00217 if (offset > 0x4000)
00218 return;
00219 dns_name_init(&tname, NULL);
00220 dns_name_init(&xname, NULL);
00221
00222 n = dns_name_countlabels(name);
00223 count = dns_name_countlabels(prefix);
00224 if (dns_name_isabsolute(prefix))
00225 count--;
00226 if (count == 0)
00227 return;
00228 start = 0;
00229 dns_name_toregion(name, &r);
00230 length = r.length;
00231 tmp = isc_mem_get(cctx->mctx, length);
00232 if (tmp == NULL)
00233 return;
00234 memmove(tmp, r.base, r.length);
00235 r.base = tmp;
00236 dns_name_fromregion(&xname, &r);
00237
00238 while (count > 0) {
00239 if (offset >= 0x4000)
00240 break;
00241 dns_name_getlabelsequence(&xname, start, n, &tname);
00242 hash = dns_name_hash(&tname, ISC_FALSE) %
00243 DNS_COMPRESS_TABLESIZE;
00244 tlength = name_length(&tname);
00245 toffset = (isc_uint16_t)(offset + (length - tlength));
00246
00247
00248
00249 if (cctx->count < DNS_COMPRESS_INITIALNODES)
00250 node = &cctx->initialnodes[cctx->count];
00251 else {
00252 node = isc_mem_get(cctx->mctx,
00253 sizeof(dns_compressnode_t));
00254 if (node == NULL) {
00255 if (start == 0)
00256 isc_mem_put(cctx->mctx,
00257 r.base, r.length);
00258 return;
00259 }
00260 }
00261 node->count = cctx->count++;
00262 if (start == 0)
00263 toffset |= 0x8000;
00264 node->offset = toffset;
00265 dns_name_toregion(&tname, &node->r);
00266 node->labels = (isc_uint8_t)dns_name_countlabels(&tname);
00267 node->next = cctx->table[hash];
00268 cctx->table[hash] = node;
00269 start++;
00270 n--;
00271 count--;
00272 }
00273 }
00274
00275 void
00276 dns_compress_rollback(dns_compress_t *cctx, isc_uint16_t offset) {
00277 unsigned int i;
00278 dns_compressnode_t *node;
00279
00280 REQUIRE(VALID_CCTX(cctx));
00281
00282 for (i = 0; i < DNS_COMPRESS_TABLESIZE; i++) {
00283 node = cctx->table[i];
00284
00285
00286
00287
00288
00289
00290 while (node != NULL && (node->offset & 0x7fff) >= offset) {
00291 cctx->table[i] = node->next;
00292 if ((node->offset & 0x8000) != 0)
00293 isc_mem_put(cctx->mctx, node->r.base,
00294 node->r.length);
00295 if (node->count >= DNS_COMPRESS_INITIALNODES)
00296 isc_mem_put(cctx->mctx, node, sizeof(*node));
00297 cctx->count--;
00298 node = cctx->table[i];
00299 }
00300 }
00301 }
00302
00303
00304
00305
00306
00307 void
00308 dns_decompress_init(dns_decompress_t *dctx, int edns,
00309 dns_decompresstype_t type) {
00310
00311 REQUIRE(dctx != NULL);
00312 REQUIRE(edns >= -1 && edns <= 255);
00313
00314 dctx->allowed = DNS_COMPRESS_NONE;
00315 dctx->edns = edns;
00316 dctx->type = type;
00317 dctx->magic = DCTX_MAGIC;
00318 }
00319
00320 void
00321 dns_decompress_invalidate(dns_decompress_t *dctx) {
00322
00323 REQUIRE(VALID_DCTX(dctx));
00324
00325 dctx->magic = 0;
00326 }
00327
00328 void
00329 dns_decompress_setmethods(dns_decompress_t *dctx, unsigned int allowed) {
00330
00331 REQUIRE(VALID_DCTX(dctx));
00332
00333 switch (dctx->type) {
00334 case DNS_DECOMPRESS_ANY:
00335 dctx->allowed = DNS_COMPRESS_ALL;
00336 break;
00337 case DNS_DECOMPRESS_NONE:
00338 dctx->allowed = DNS_COMPRESS_NONE;
00339 break;
00340 case DNS_DECOMPRESS_STRICT:
00341 dctx->allowed = allowed;
00342 break;
00343 }
00344 }
00345
00346 unsigned int
00347 dns_decompress_getmethods(dns_decompress_t *dctx) {
00348
00349 REQUIRE(VALID_DCTX(dctx));
00350
00351 return (dctx->allowed);
00352 }
00353
00354 int
00355 dns_decompress_edns(dns_decompress_t *dctx) {
00356
00357 REQUIRE(VALID_DCTX(dctx));
00358
00359 return (dctx->edns);
00360 }
00361
00362 dns_decompresstype_t
00363 dns_decompress_type(dns_decompress_t *dctx) {
00364
00365 REQUIRE(VALID_DCTX(dctx));
00366
00367 return (dctx->type);
00368 }