1 /* $NetBSD: ssu.c,v 1.6 2014/12/10 04:37:58 christos Exp $ */
2
3 /*
4 * Copyright (C) 2004-2008, 2010, 2011, 2013, 2014 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 2000, 2001, 2003 Internet Software Consortium.
6 *
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /*! \file */
21 /*
22 * Id: ssu.c,v 1.38 2011/01/06 23:47:00 tbox Exp
23 * Principal Author: Brian Wellington
24 */
25
26 #include <config.h>
27
28 #include <isc/magic.h>
29 #include <isc/mem.h>
30 #include <isc/netaddr.h>
31 #include <isc/result.h>
32 #include <isc/string.h>
33 #include <isc/util.h>
34
35 #include <dns/dlz.h>
36 #include <dns/fixedname.h>
37 #include <dns/name.h>
38 #include <dns/ssu.h>
39
40 #include <dst/gssapi.h>
41 #include <dst/dst.h>
42
43 #define SSUTABLEMAGIC ISC_MAGIC('S', 'S', 'U', 'T')
44 #define VALID_SSUTABLE(table) ISC_MAGIC_VALID(table, SSUTABLEMAGIC)
45
46 #define SSURULEMAGIC ISC_MAGIC('S', 'S', 'U', 'R')
47 #define VALID_SSURULE(table) ISC_MAGIC_VALID(table, SSURULEMAGIC)
48
49 struct dns_ssurule {
50 unsigned int magic;
51 isc_boolean_t grant; /*%< is this a grant or a deny? */
52 unsigned int matchtype; /*%< which type of pattern match? */
53 dns_name_t *identity; /*%< the identity to match */
54 dns_name_t *name; /*%< the name being updated */
55 unsigned int ntypes; /*%< number of data types covered */
56 dns_rdatatype_t *types; /*%< the data types. Can include ANY, */
57 /*%< defaults to all but SIG,SOA,NS if NULL */
58 ISC_LINK(dns_ssurule_t) link;
59 };
60
61 struct dns_ssutable {
62 unsigned int magic;
63 isc_mem_t *mctx;
64 unsigned int references;
65 isc_mutex_t lock;
66 dns_dlzdb_t *dlzdatabase;
67 ISC_LIST(dns_ssurule_t) rules;
68 };
69
70 isc_result_t
dns_ssutable_create(isc_mem_t * mctx,dns_ssutable_t ** tablep)71 dns_ssutable_create(isc_mem_t *mctx, dns_ssutable_t **tablep) {
72 isc_result_t result;
73 dns_ssutable_t *table;
74
75 REQUIRE(tablep != NULL && *tablep == NULL);
76 REQUIRE(mctx != NULL);
77
78 table = isc_mem_get(mctx, sizeof(dns_ssutable_t));
79 if (table == NULL)
80 return (ISC_R_NOMEMORY);
81 result = isc_mutex_init(&table->lock);
82 if (result != ISC_R_SUCCESS) {
83 isc_mem_put(mctx, table, sizeof(dns_ssutable_t));
84 return (result);
85 }
86 table->references = 1;
87 table->mctx = NULL;
88 isc_mem_attach(mctx, &table->mctx);
89 ISC_LIST_INIT(table->rules);
90 table->magic = SSUTABLEMAGIC;
91 *tablep = table;
92 return (ISC_R_SUCCESS);
93 }
94
95 static inline void
destroy(dns_ssutable_t * table)96 destroy(dns_ssutable_t *table) {
97 isc_mem_t *mctx;
98
99 REQUIRE(VALID_SSUTABLE(table));
100
101 mctx = table->mctx;
102 while (!ISC_LIST_EMPTY(table->rules)) {
103 dns_ssurule_t *rule = ISC_LIST_HEAD(table->rules);
104 if (rule->identity != NULL) {
105 dns_name_free(rule->identity, mctx);
106 isc_mem_put(mctx, rule->identity, sizeof(dns_name_t));
107 }
108 if (rule->name != NULL) {
109 dns_name_free(rule->name, mctx);
110 isc_mem_put(mctx, rule->name, sizeof(dns_name_t));
111 }
112 if (rule->types != NULL)
113 isc_mem_put(mctx, rule->types,
114 rule->ntypes * sizeof(dns_rdatatype_t));
115 ISC_LIST_UNLINK(table->rules, rule, link);
116 rule->magic = 0;
117 isc_mem_put(mctx, rule, sizeof(dns_ssurule_t));
118 }
119 DESTROYLOCK(&table->lock);
120 table->magic = 0;
121 isc_mem_putanddetach(&table->mctx, table, sizeof(dns_ssutable_t));
122 }
123
124 void
dns_ssutable_attach(dns_ssutable_t * source,dns_ssutable_t ** targetp)125 dns_ssutable_attach(dns_ssutable_t *source, dns_ssutable_t **targetp) {
126 REQUIRE(VALID_SSUTABLE(source));
127 REQUIRE(targetp != NULL && *targetp == NULL);
128
129 LOCK(&source->lock);
130
131 INSIST(source->references > 0);
132 source->references++;
133 INSIST(source->references != 0);
134
135 UNLOCK(&source->lock);
136
137 *targetp = source;
138 }
139
140 void
dns_ssutable_detach(dns_ssutable_t ** tablep)141 dns_ssutable_detach(dns_ssutable_t **tablep) {
142 dns_ssutable_t *table;
143 isc_boolean_t done = ISC_FALSE;
144
145 REQUIRE(tablep != NULL);
146 table = *tablep;
147 REQUIRE(VALID_SSUTABLE(table));
148
149 LOCK(&table->lock);
150
151 INSIST(table->references > 0);
152 if (--table->references == 0)
153 done = ISC_TRUE;
154 UNLOCK(&table->lock);
155
156 *tablep = NULL;
157
158 if (done)
159 destroy(table);
160 }
161
162 isc_result_t
dns_ssutable_addrule(dns_ssutable_t * table,isc_boolean_t grant,dns_name_t * identity,unsigned int matchtype,dns_name_t * name,unsigned int ntypes,dns_rdatatype_t * types)163 dns_ssutable_addrule(dns_ssutable_t *table, isc_boolean_t grant,
164 dns_name_t *identity, unsigned int matchtype,
165 dns_name_t *name, unsigned int ntypes,
166 dns_rdatatype_t *types)
167 {
168 dns_ssurule_t *rule;
169 isc_mem_t *mctx;
170 isc_result_t result;
171
172 REQUIRE(VALID_SSUTABLE(table));
173 REQUIRE(dns_name_isabsolute(identity));
174 REQUIRE(dns_name_isabsolute(name));
175 REQUIRE(matchtype <= DNS_SSUMATCHTYPE_MAX);
176 if (matchtype == DNS_SSUMATCHTYPE_WILDCARD)
177 REQUIRE(dns_name_iswildcard(name));
178 if (ntypes > 0)
179 REQUIRE(types != NULL);
180
181 mctx = table->mctx;
182 rule = isc_mem_get(mctx, sizeof(dns_ssurule_t));
183 if (rule == NULL)
184 return (ISC_R_NOMEMORY);
185
186 rule->identity = NULL;
187 rule->name = NULL;
188 rule->types = NULL;
189
190 rule->grant = grant;
191
192 rule->identity = isc_mem_get(mctx, sizeof(dns_name_t));
193 if (rule->identity == NULL) {
194 result = ISC_R_NOMEMORY;
195 goto failure;
196 }
197 dns_name_init(rule->identity, NULL);
198 result = dns_name_dup(identity, mctx, rule->identity);
199 if (result != ISC_R_SUCCESS)
200 goto failure;
201
202 rule->name = isc_mem_get(mctx, sizeof(dns_name_t));
203 if (rule->name == NULL) {
204 result = ISC_R_NOMEMORY;
205 goto failure;
206 }
207 dns_name_init(rule->name, NULL);
208 result = dns_name_dup(name, mctx, rule->name);
209 if (result != ISC_R_SUCCESS)
210 goto failure;
211
212 rule->matchtype = matchtype;
213
214 rule->ntypes = ntypes;
215 if (ntypes > 0) {
216 rule->types = isc_mem_get(mctx,
217 ntypes * sizeof(dns_rdatatype_t));
218 if (rule->types == NULL) {
219 result = ISC_R_NOMEMORY;
220 goto failure;
221 }
222 memmove(rule->types, types, ntypes * sizeof(dns_rdatatype_t));
223 } else
224 rule->types = NULL;
225
226 rule->magic = SSURULEMAGIC;
227 ISC_LIST_INITANDAPPEND(table->rules, rule, link);
228
229 return (ISC_R_SUCCESS);
230
231 failure:
232 if (rule->identity != NULL) {
233 if (dns_name_dynamic(rule->identity))
234 dns_name_free(rule->identity, mctx);
235 isc_mem_put(mctx, rule->identity, sizeof(dns_name_t));
236 }
237 if (rule->name != NULL) {
238 if (dns_name_dynamic(rule->name))
239 dns_name_free(rule->name, mctx);
240 isc_mem_put(mctx, rule->name, sizeof(dns_name_t));
241 }
242 if (rule->types != NULL)
243 isc_mem_put(mctx, rule->types,
244 ntypes * sizeof(dns_rdatatype_t));
245 isc_mem_put(mctx, rule, sizeof(dns_ssurule_t));
246
247 return (result);
248 }
249
250 static inline isc_boolean_t
isusertype(dns_rdatatype_t type)251 isusertype(dns_rdatatype_t type) {
252 return (ISC_TF(type != dns_rdatatype_ns &&
253 type != dns_rdatatype_soa &&
254 type != dns_rdatatype_rrsig));
255 }
256
257 static void
reverse_from_address(dns_name_t * tcpself,isc_netaddr_t * tcpaddr)258 reverse_from_address(dns_name_t *tcpself, isc_netaddr_t *tcpaddr) {
259 char buf[16 * 4 + sizeof("IP6.ARPA.")];
260 isc_result_t result;
261 unsigned char *ap;
262 isc_buffer_t b;
263 unsigned long l;
264
265 switch (tcpaddr->family) {
266 case AF_INET:
267 l = ntohl(tcpaddr->type.in.s_addr);
268 result = isc_string_printf(buf, sizeof(buf),
269 "%lu.%lu.%lu.%lu.IN-ADDR.ARPA.",
270 (l >> 0) & 0xff, (l >> 8) & 0xff,
271 (l >> 16) & 0xff, (l >> 24) & 0xff);
272 RUNTIME_CHECK(result == ISC_R_SUCCESS);
273 break;
274 case AF_INET6:
275 ap = tcpaddr->type.in6.s6_addr;
276 result = isc_string_printf(buf, sizeof(buf),
277 "%x.%x.%x.%x.%x.%x.%x.%x."
278 "%x.%x.%x.%x.%x.%x.%x.%x."
279 "%x.%x.%x.%x.%x.%x.%x.%x."
280 "%x.%x.%x.%x.%x.%x.%x.%x."
281 "IP6.ARPA.",
282 ap[15] & 0x0f, (ap[15] >> 4) & 0x0f,
283 ap[14] & 0x0f, (ap[14] >> 4) & 0x0f,
284 ap[13] & 0x0f, (ap[13] >> 4) & 0x0f,
285 ap[12] & 0x0f, (ap[12] >> 4) & 0x0f,
286 ap[11] & 0x0f, (ap[11] >> 4) & 0x0f,
287 ap[10] & 0x0f, (ap[10] >> 4) & 0x0f,
288 ap[9] & 0x0f, (ap[9] >> 4) & 0x0f,
289 ap[8] & 0x0f, (ap[8] >> 4) & 0x0f,
290 ap[7] & 0x0f, (ap[7] >> 4) & 0x0f,
291 ap[6] & 0x0f, (ap[6] >> 4) & 0x0f,
292 ap[5] & 0x0f, (ap[5] >> 4) & 0x0f,
293 ap[4] & 0x0f, (ap[4] >> 4) & 0x0f,
294 ap[3] & 0x0f, (ap[3] >> 4) & 0x0f,
295 ap[2] & 0x0f, (ap[2] >> 4) & 0x0f,
296 ap[1] & 0x0f, (ap[1] >> 4) & 0x0f,
297 ap[0] & 0x0f, (ap[0] >> 4) & 0x0f);
298 RUNTIME_CHECK(result == ISC_R_SUCCESS);
299 break;
300 default:
301 INSIST(0);
302 }
303 isc_buffer_init(&b, buf, strlen(buf));
304 isc_buffer_add(&b, strlen(buf));
305 result = dns_name_fromtext(tcpself, &b, dns_rootname, 0, NULL);
306 RUNTIME_CHECK(result == ISC_R_SUCCESS);
307 }
308
309 static void
stf_from_address(dns_name_t * stfself,isc_netaddr_t * tcpaddr)310 stf_from_address(dns_name_t *stfself, isc_netaddr_t *tcpaddr) {
311 char buf[sizeof("X.X.X.X.Y.Y.Y.Y.2.0.0.2.IP6.ARPA.")];
312 isc_result_t result;
313 unsigned char *ap;
314 isc_buffer_t b;
315 unsigned long l;
316
317 switch(tcpaddr->family) {
318 case AF_INET:
319 l = ntohl(tcpaddr->type.in.s_addr);
320 result = isc_string_printf(buf, sizeof(buf),
321 "%lx.%lx.%lx.%lx.%lx.%lx.%lx.%lx"
322 "2.0.0.2.IP6.ARPA.",
323 l & 0xf, (l >> 4) & 0xf,
324 (l >> 8) & 0xf, (l >> 12) & 0xf,
325 (l >> 16) & 0xf, (l >> 20) & 0xf,
326 (l >> 24) & 0xf, (l >> 28) & 0xf);
327 RUNTIME_CHECK(result == ISC_R_SUCCESS);
328 break;
329 case AF_INET6:
330 ap = tcpaddr->type.in6.s6_addr;
331 result = isc_string_printf(buf, sizeof(buf),
332 "%x.%x.%x.%x.%x.%x.%x.%x."
333 "%x.%x.%x.%x.IP6.ARPA.",
334 ap[5] & 0x0f, (ap[5] >> 4) & 0x0f,
335 ap[4] & 0x0f, (ap[4] >> 4) & 0x0f,
336 ap[3] & 0x0f, (ap[3] >> 4) & 0x0f,
337 ap[2] & 0x0f, (ap[2] >> 4) & 0x0f,
338 ap[1] & 0x0f, (ap[1] >> 4) & 0x0f,
339 ap[0] & 0x0f, (ap[0] >> 4) & 0x0f);
340 RUNTIME_CHECK(result == ISC_R_SUCCESS);
341 break;
342 default:
343 INSIST(0);
344 }
345 isc_buffer_init(&b, buf, strlen(buf));
346 isc_buffer_add(&b, strlen(buf));
347 result = dns_name_fromtext(stfself, &b, dns_rootname, 0, NULL);
348 RUNTIME_CHECK(result == ISC_R_SUCCESS);
349 }
350
351 isc_boolean_t
dns_ssutable_checkrules(dns_ssutable_t * table,dns_name_t * signer,dns_name_t * name,isc_netaddr_t * tcpaddr,dns_rdatatype_t type,const dst_key_t * key)352 dns_ssutable_checkrules(dns_ssutable_t *table, dns_name_t *signer,
353 dns_name_t *name, isc_netaddr_t *tcpaddr,
354 dns_rdatatype_t type,
355 const dst_key_t *key)
356 {
357 dns_ssurule_t *rule;
358 unsigned int i;
359 dns_fixedname_t fixed;
360 dns_name_t *wildcard;
361 dns_name_t *tcpself;
362 dns_name_t *stfself;
363 isc_result_t result;
364
365 REQUIRE(VALID_SSUTABLE(table));
366 REQUIRE(signer == NULL || dns_name_isabsolute(signer));
367 REQUIRE(dns_name_isabsolute(name));
368
369 if (signer == NULL && tcpaddr == NULL)
370 return (ISC_FALSE);
371
372 for (rule = ISC_LIST_HEAD(table->rules);
373 rule != NULL;
374 rule = ISC_LIST_NEXT(rule, link))
375 {
376 switch (rule->matchtype) {
377 case DNS_SSUMATCHTYPE_NAME:
378 case DNS_SSUMATCHTYPE_SUBDOMAIN:
379 case DNS_SSUMATCHTYPE_WILDCARD:
380 case DNS_SSUMATCHTYPE_SELF:
381 case DNS_SSUMATCHTYPE_SELFSUB:
382 case DNS_SSUMATCHTYPE_SELFWILD:
383 if (signer == NULL)
384 continue;
385 if (dns_name_iswildcard(rule->identity)) {
386 if (!dns_name_matcheswildcard(signer,
387 rule->identity))
388 continue;
389 } else {
390 if (!dns_name_equal(signer, rule->identity))
391 continue;
392 }
393 break;
394 case DNS_SSUMATCHTYPE_SELFKRB5:
395 case DNS_SSUMATCHTYPE_SELFMS:
396 case DNS_SSUMATCHTYPE_SUBDOMAINKRB5:
397 case DNS_SSUMATCHTYPE_SUBDOMAINMS:
398 if (signer == NULL)
399 continue;
400 break;
401 case DNS_SSUMATCHTYPE_TCPSELF:
402 case DNS_SSUMATCHTYPE_6TO4SELF:
403 if (tcpaddr == NULL)
404 continue;
405 break;
406 }
407
408 switch (rule->matchtype) {
409 case DNS_SSUMATCHTYPE_NAME:
410 if (!dns_name_equal(name, rule->name))
411 continue;
412 break;
413 case DNS_SSUMATCHTYPE_SUBDOMAIN:
414 if (!dns_name_issubdomain(name, rule->name))
415 continue;
416 break;
417 case DNS_SSUMATCHTYPE_WILDCARD:
418 if (!dns_name_matcheswildcard(name, rule->name))
419 continue;
420 break;
421 case DNS_SSUMATCHTYPE_SELF:
422 if (!dns_name_equal(signer, name))
423 continue;
424 break;
425 case DNS_SSUMATCHTYPE_SELFSUB:
426 if (!dns_name_issubdomain(name, signer))
427 continue;
428 break;
429 case DNS_SSUMATCHTYPE_SELFWILD:
430 dns_fixedname_init(&fixed);
431 wildcard = dns_fixedname_name(&fixed);
432 result = dns_name_concatenate(dns_wildcardname, signer,
433 wildcard, NULL);
434 if (result != ISC_R_SUCCESS)
435 continue;
436 if (!dns_name_matcheswildcard(name, wildcard))
437 continue;
438 break;
439 case DNS_SSUMATCHTYPE_SELFKRB5:
440 if (!dst_gssapi_identitymatchesrealmkrb5(signer, name,
441 rule->identity))
442 continue;
443 break;
444 case DNS_SSUMATCHTYPE_SELFMS:
445 if (!dst_gssapi_identitymatchesrealmms(signer, name,
446 rule->identity))
447 continue;
448 break;
449 case DNS_SSUMATCHTYPE_SUBDOMAINKRB5:
450 if (!dns_name_issubdomain(name, rule->name))
451 continue;
452 if (!dst_gssapi_identitymatchesrealmkrb5(signer, NULL,
453 rule->identity))
454 continue;
455 break;
456 case DNS_SSUMATCHTYPE_SUBDOMAINMS:
457 if (!dns_name_issubdomain(name, rule->name))
458 continue;
459 if (!dst_gssapi_identitymatchesrealmms(signer, NULL,
460 rule->identity))
461 continue;
462 break;
463 case DNS_SSUMATCHTYPE_TCPSELF:
464 dns_fixedname_init(&fixed);
465 tcpself = dns_fixedname_name(&fixed);
466 reverse_from_address(tcpself, tcpaddr);
467 if (dns_name_iswildcard(rule->identity)) {
468 if (!dns_name_matcheswildcard(tcpself,
469 rule->identity))
470 continue;
471 } else {
472 if (!dns_name_equal(tcpself, rule->identity))
473 continue;
474 }
475 if (!dns_name_equal(tcpself, name))
476 continue;
477 break;
478 case DNS_SSUMATCHTYPE_6TO4SELF:
479 dns_fixedname_init(&fixed);
480 stfself = dns_fixedname_name(&fixed);
481 stf_from_address(stfself, tcpaddr);
482 if (dns_name_iswildcard(rule->identity)) {
483 if (!dns_name_matcheswildcard(stfself,
484 rule->identity))
485 continue;
486 } else {
487 if (!dns_name_equal(stfself, rule->identity))
488 continue;
489 }
490 if (!dns_name_equal(stfself, name))
491 continue;
492 break;
493 case DNS_SSUMATCHTYPE_EXTERNAL:
494 if (!dns_ssu_external_match(rule->identity, signer,
495 name, tcpaddr, type, key,
496 table->mctx))
497 continue;
498 break;
499 case DNS_SSUMATCHTYPE_DLZ:
500 if (!dns_dlz_ssumatch(table->dlzdatabase, signer,
501 name, tcpaddr, type, key))
502 continue;
503 break;
504 }
505
506 if (rule->ntypes == 0) {
507 /*
508 * If this is a DLZ rule, then the DLZ ssu
509 * checks will have already checked
510 * the type.
511 */
512 if (rule->matchtype != DNS_SSUMATCHTYPE_DLZ &&
513 !isusertype(type))
514 continue;
515 } else {
516 for (i = 0; i < rule->ntypes; i++) {
517 if (rule->types[i] == dns_rdatatype_any ||
518 rule->types[i] == type)
519 break;
520 }
521 if (i == rule->ntypes)
522 continue;
523 }
524 return (rule->grant);
525 }
526
527 return (ISC_FALSE);
528 }
529
530 isc_boolean_t
dns_ssurule_isgrant(const dns_ssurule_t * rule)531 dns_ssurule_isgrant(const dns_ssurule_t *rule) {
532 REQUIRE(VALID_SSURULE(rule));
533 return (rule->grant);
534 }
535
536 dns_name_t *
dns_ssurule_identity(const dns_ssurule_t * rule)537 dns_ssurule_identity(const dns_ssurule_t *rule) {
538 REQUIRE(VALID_SSURULE(rule));
539 return (rule->identity);
540 }
541
542 unsigned int
dns_ssurule_matchtype(const dns_ssurule_t * rule)543 dns_ssurule_matchtype(const dns_ssurule_t *rule) {
544 REQUIRE(VALID_SSURULE(rule));
545 return (rule->matchtype);
546 }
547
548 dns_name_t *
dns_ssurule_name(const dns_ssurule_t * rule)549 dns_ssurule_name(const dns_ssurule_t *rule) {
550 REQUIRE(VALID_SSURULE(rule));
551 return (rule->name);
552 }
553
554 unsigned int
dns_ssurule_types(const dns_ssurule_t * rule,dns_rdatatype_t ** types)555 dns_ssurule_types(const dns_ssurule_t *rule, dns_rdatatype_t **types) {
556 REQUIRE(VALID_SSURULE(rule));
557 REQUIRE(types != NULL && *types != NULL);
558 *types = rule->types;
559 return (rule->ntypes);
560 }
561
562 isc_result_t
dns_ssutable_firstrule(const dns_ssutable_t * table,dns_ssurule_t ** rule)563 dns_ssutable_firstrule(const dns_ssutable_t *table, dns_ssurule_t **rule) {
564 REQUIRE(VALID_SSUTABLE(table));
565 REQUIRE(rule != NULL && *rule == NULL);
566 *rule = ISC_LIST_HEAD(table->rules);
567 return (*rule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE);
568 }
569
570 isc_result_t
dns_ssutable_nextrule(dns_ssurule_t * rule,dns_ssurule_t ** nextrule)571 dns_ssutable_nextrule(dns_ssurule_t *rule, dns_ssurule_t **nextrule) {
572 REQUIRE(VALID_SSURULE(rule));
573 REQUIRE(nextrule != NULL && *nextrule == NULL);
574 *nextrule = ISC_LIST_NEXT(rule, link);
575 return (*nextrule != NULL ? ISC_R_SUCCESS : ISC_R_NOMORE);
576 }
577
578 /*
579 * Create a specialised SSU table that points at an external DLZ database
580 */
581 isc_result_t
dns_ssutable_createdlz(isc_mem_t * mctx,dns_ssutable_t ** tablep,dns_dlzdb_t * dlzdatabase)582 dns_ssutable_createdlz(isc_mem_t *mctx, dns_ssutable_t **tablep,
583 dns_dlzdb_t *dlzdatabase)
584 {
585 isc_result_t result;
586 dns_ssurule_t *rule;
587 dns_ssutable_t *table = NULL;
588
589 REQUIRE(tablep != NULL && *tablep == NULL);
590
591 result = dns_ssutable_create(mctx, &table);
592 if (result != ISC_R_SUCCESS)
593 return (result);
594
595 table->dlzdatabase = dlzdatabase;
596
597 rule = isc_mem_get(table->mctx, sizeof(dns_ssurule_t));
598 if (rule == NULL) {
599 dns_ssutable_detach(&table);
600 return (ISC_R_NOMEMORY);
601 }
602
603 rule->identity = NULL;
604 rule->name = NULL;
605 rule->types = NULL;
606 rule->grant = ISC_TRUE;
607 rule->matchtype = DNS_SSUMATCHTYPE_DLZ;
608 rule->ntypes = 0;
609 rule->types = NULL;
610 rule->magic = SSURULEMAGIC;
611
612 ISC_LIST_INITANDAPPEND(table->rules, rule, link);
613 *tablep = table;
614 return (ISC_R_SUCCESS);
615 }
616