]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - contrib/bind9/lib/dns/peer.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / contrib / bind9 / lib / dns / peer.c
1 /*
2  * Copyright (C) 2004-2006  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 2000, 2001, 2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15  * PERFORMANCE OF THIS SOFTWARE.
16  */
17
18 /* $Id: peer.c,v 1.19.18.8 2006/02/28 03:10:48 marka Exp $ */
19
20 /*! \file */
21
22 #include <config.h>
23
24 #include <isc/mem.h>
25 #include <isc/string.h>
26 #include <isc/util.h>
27 #include <isc/sockaddr.h>
28
29 #include <dns/bit.h>
30 #include <dns/fixedname.h>
31 #include <dns/name.h>
32 #include <dns/peer.h>
33
34 /*%
35  * Bit positions in the dns_peer_t structure flags field
36  */
37 #define BOGUS_BIT                       0
38 #define SERVER_TRANSFER_FORMAT_BIT      1
39 #define TRANSFERS_BIT                   2
40 #define PROVIDE_IXFR_BIT                3
41 #define REQUEST_IXFR_BIT                4
42 #define SUPPORT_EDNS_BIT                5
43 #define SERVER_UDPSIZE_BIT              6
44 #define SERVER_MAXUDP_BIT               7
45
46 static void
47 peerlist_delete(dns_peerlist_t **list);
48
49 static void
50 peer_delete(dns_peer_t **peer);
51
52 isc_result_t
53 dns_peerlist_new(isc_mem_t *mem, dns_peerlist_t **list) {
54         dns_peerlist_t *l;
55
56         REQUIRE(list != NULL);
57
58         l = isc_mem_get(mem, sizeof(*l));
59         if (l == NULL)
60                 return (ISC_R_NOMEMORY);
61
62         ISC_LIST_INIT(l->elements);
63         l->mem = mem;
64         l->refs = 1;
65         l->magic = DNS_PEERLIST_MAGIC;
66
67         *list = l;
68
69         return (ISC_R_SUCCESS);
70 }
71
72 void
73 dns_peerlist_attach(dns_peerlist_t *source, dns_peerlist_t **target) {
74         REQUIRE(DNS_PEERLIST_VALID(source));
75         REQUIRE(target != NULL);
76         REQUIRE(*target == NULL);
77
78         source->refs++;
79
80         ENSURE(source->refs != 0xffffffffU);
81
82         *target = source;
83 }
84
85 void
86 dns_peerlist_detach(dns_peerlist_t **list) {
87         dns_peerlist_t *plist;
88
89         REQUIRE(list != NULL);
90         REQUIRE(*list != NULL);
91         REQUIRE(DNS_PEERLIST_VALID(*list));
92
93         plist = *list;
94         *list = NULL;
95
96         REQUIRE(plist->refs > 0);
97
98         plist->refs--;
99
100         if (plist->refs == 0)
101                 peerlist_delete(&plist);
102 }
103
104 static void
105 peerlist_delete(dns_peerlist_t **list) {
106         dns_peerlist_t *l;
107         dns_peer_t *server, *stmp;
108
109         REQUIRE(list != NULL);
110         REQUIRE(DNS_PEERLIST_VALID(*list));
111
112         l = *list;
113
114         REQUIRE(l->refs == 0);
115
116         server = ISC_LIST_HEAD(l->elements);
117         while (server != NULL) {
118                 stmp = ISC_LIST_NEXT(server, next);
119                 ISC_LIST_UNLINK(l->elements, server, next);
120                 dns_peer_detach(&server);
121                 server = stmp;
122         }
123
124         l->magic = 0;
125         isc_mem_put(l->mem, l, sizeof(*l));
126
127         *list = NULL;
128 }
129
130 void
131 dns_peerlist_addpeer(dns_peerlist_t *peers, dns_peer_t *peer) {
132         dns_peer_t *p = NULL;
133
134         dns_peer_attach(peer, &p);
135
136         /*
137          * More specifics to front of list.
138          */
139         for (p = ISC_LIST_HEAD(peers->elements);
140              p != NULL;
141              p = ISC_LIST_NEXT(p, next))
142                 if (p->prefixlen < peer->prefixlen)
143                         break;
144
145         if (p != NULL)
146                 ISC_LIST_INSERTBEFORE(peers->elements, p, peer, next);
147         else
148                 ISC_LIST_APPEND(peers->elements, peer, next);
149                 
150 }
151
152 isc_result_t
153 dns_peerlist_peerbyaddr(dns_peerlist_t *servers,
154                         isc_netaddr_t *addr, dns_peer_t **retval)
155 {
156         dns_peer_t *server;
157         isc_result_t res;
158
159         REQUIRE(retval != NULL);
160         REQUIRE(DNS_PEERLIST_VALID(servers));
161
162         server = ISC_LIST_HEAD(servers->elements);
163         while (server != NULL) {
164                 if (isc_netaddr_eqprefix(addr, &server->address,
165                                          server->prefixlen))
166                         break;
167
168                 server = ISC_LIST_NEXT(server, next);
169         }
170
171         if (server != NULL) {
172                 *retval = server;
173                 res = ISC_R_SUCCESS;
174         } else {
175                 res = ISC_R_NOTFOUND;
176         }
177
178         return (res);
179 }
180
181
182
183 isc_result_t
184 dns_peerlist_currpeer(dns_peerlist_t *peers, dns_peer_t **retval) {
185         dns_peer_t *p = NULL;
186
187         p = ISC_LIST_TAIL(peers->elements);
188
189         dns_peer_attach(p, retval);
190
191         return (ISC_R_SUCCESS);
192 }
193
194 isc_result_t
195 dns_peer_new(isc_mem_t *mem, isc_netaddr_t *addr, dns_peer_t **peerptr) {
196         unsigned int prefixlen = 0;
197
198         REQUIRE(peerptr != NULL);
199         switch(addr->family) {
200         case AF_INET:
201                 prefixlen = 32;
202                 break;
203         case AF_INET6:
204                  prefixlen = 128;
205                 break;
206         default:
207                 INSIST(0);
208         }
209
210         return (dns_peer_newprefix(mem, addr, prefixlen, peerptr));
211 }
212
213 isc_result_t
214 dns_peer_newprefix(isc_mem_t *mem, isc_netaddr_t *addr, unsigned int prefixlen,
215                    dns_peer_t **peerptr)
216
217         dns_peer_t *peer;
218
219         REQUIRE(peerptr != NULL);
220
221         peer = isc_mem_get(mem, sizeof(*peer));
222         if (peer == NULL)
223                 return (ISC_R_NOMEMORY);
224
225         peer->magic = DNS_PEER_MAGIC;
226         peer->address = *addr;
227         peer->prefixlen = prefixlen;
228         peer->mem = mem;
229         peer->bogus = ISC_FALSE;
230         peer->transfer_format = dns_one_answer;
231         peer->transfers = 0;
232         peer->request_ixfr = ISC_FALSE;
233         peer->provide_ixfr = ISC_FALSE;
234         peer->key = NULL;
235         peer->refs = 1;
236         peer->transfer_source = NULL;
237         peer->notify_source = NULL;
238         peer->query_source = NULL;
239
240         memset(&peer->bitflags, 0x0, sizeof(peer->bitflags));
241
242         ISC_LINK_INIT(peer, next);
243
244         *peerptr = peer;
245
246         return (ISC_R_SUCCESS);
247 }
248
249 void
250 dns_peer_attach(dns_peer_t *source, dns_peer_t **target) {
251         REQUIRE(DNS_PEER_VALID(source));
252         REQUIRE(target != NULL);
253         REQUIRE(*target == NULL);
254
255         source->refs++;
256
257         ENSURE(source->refs != 0xffffffffU);
258
259         *target = source;
260 }
261
262 void
263 dns_peer_detach(dns_peer_t **peer) {
264         dns_peer_t *p;
265
266         REQUIRE(peer != NULL);
267         REQUIRE(*peer != NULL);
268         REQUIRE(DNS_PEER_VALID(*peer));
269
270         p = *peer;
271
272         REQUIRE(p->refs > 0);
273
274         *peer = NULL;
275         p->refs--;
276
277         if (p->refs == 0)
278                 peer_delete(&p);
279 }
280
281 static void
282 peer_delete(dns_peer_t **peer) {
283         dns_peer_t *p;
284         isc_mem_t *mem;
285
286         REQUIRE(peer != NULL);
287         REQUIRE(DNS_PEER_VALID(*peer));
288
289         p = *peer;
290
291         REQUIRE(p->refs == 0);
292
293         mem = p->mem;
294         p->mem = NULL;
295         p->magic = 0;
296
297         if (p->key != NULL) {
298                 dns_name_free(p->key, mem);
299                 isc_mem_put(mem, p->key, sizeof(dns_name_t));
300         }
301
302         if (p->transfer_source != NULL) {
303                 isc_mem_put(mem, p->transfer_source,
304                             sizeof(*p->transfer_source));
305         }
306
307         isc_mem_put(mem, p, sizeof(*p));
308
309         *peer = NULL;
310 }
311
312 isc_result_t
313 dns_peer_setbogus(dns_peer_t *peer, isc_boolean_t newval) {
314         isc_boolean_t existed;
315
316         REQUIRE(DNS_PEER_VALID(peer));
317
318         existed = DNS_BIT_CHECK(BOGUS_BIT, &peer->bitflags);
319
320         peer->bogus = newval;
321         DNS_BIT_SET(BOGUS_BIT, &peer->bitflags);
322
323         return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
324 }
325
326 isc_result_t
327 dns_peer_getbogus(dns_peer_t *peer, isc_boolean_t *retval) {
328         REQUIRE(DNS_PEER_VALID(peer));
329         REQUIRE(retval != NULL);
330
331         if (DNS_BIT_CHECK(BOGUS_BIT, &peer->bitflags)) {
332                 *retval = peer->bogus;
333                 return (ISC_R_SUCCESS);
334         } else
335                 return (ISC_R_NOTFOUND);
336 }
337
338
339 isc_result_t
340 dns_peer_setprovideixfr(dns_peer_t *peer, isc_boolean_t newval) {
341         isc_boolean_t existed;
342
343         REQUIRE(DNS_PEER_VALID(peer));
344
345         existed = DNS_BIT_CHECK(PROVIDE_IXFR_BIT, &peer->bitflags);
346
347         peer->provide_ixfr = newval;
348         DNS_BIT_SET(PROVIDE_IXFR_BIT, &peer->bitflags);
349
350         return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
351 }
352
353 isc_result_t
354 dns_peer_getprovideixfr(dns_peer_t *peer, isc_boolean_t *retval) {
355         REQUIRE(DNS_PEER_VALID(peer));
356         REQUIRE(retval != NULL);
357
358         if (DNS_BIT_CHECK(PROVIDE_IXFR_BIT, &peer->bitflags)) {
359                 *retval = peer->provide_ixfr;
360                 return (ISC_R_SUCCESS);
361         } else {
362                 return (ISC_R_NOTFOUND);
363         }
364 }
365
366 isc_result_t
367 dns_peer_setrequestixfr(dns_peer_t *peer, isc_boolean_t newval) {
368         isc_boolean_t existed;
369
370         REQUIRE(DNS_PEER_VALID(peer));
371
372         existed = DNS_BIT_CHECK(REQUEST_IXFR_BIT, &peer->bitflags);
373
374         peer->request_ixfr = newval;
375         DNS_BIT_SET(REQUEST_IXFR_BIT, &peer->bitflags);
376
377         return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
378 }
379
380 isc_result_t
381 dns_peer_getrequestixfr(dns_peer_t *peer, isc_boolean_t *retval) {
382         REQUIRE(DNS_PEER_VALID(peer));
383         REQUIRE(retval != NULL);
384
385         if (DNS_BIT_CHECK(REQUEST_IXFR_BIT, &peer->bitflags)) {
386                 *retval = peer->request_ixfr;
387                 return (ISC_R_SUCCESS);
388         } else
389                 return (ISC_R_NOTFOUND);
390 }
391
392 isc_result_t
393 dns_peer_setsupportedns(dns_peer_t *peer, isc_boolean_t newval) {
394         isc_boolean_t existed;
395
396         REQUIRE(DNS_PEER_VALID(peer));
397
398         existed = DNS_BIT_CHECK(SUPPORT_EDNS_BIT, &peer->bitflags);
399
400         peer->support_edns = newval;
401         DNS_BIT_SET(SUPPORT_EDNS_BIT, &peer->bitflags);
402
403         return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
404 }
405
406 isc_result_t
407 dns_peer_getsupportedns(dns_peer_t *peer, isc_boolean_t *retval) {
408         REQUIRE(DNS_PEER_VALID(peer));
409         REQUIRE(retval != NULL);
410
411         if (DNS_BIT_CHECK(SUPPORT_EDNS_BIT, &peer->bitflags)) {
412                 *retval = peer->support_edns;
413                 return (ISC_R_SUCCESS);
414         } else
415                 return (ISC_R_NOTFOUND);
416 }
417
418 isc_result_t
419 dns_peer_settransfers(dns_peer_t *peer, isc_uint32_t newval) {
420         isc_boolean_t existed;
421
422         REQUIRE(DNS_PEER_VALID(peer));
423
424         existed = DNS_BIT_CHECK(TRANSFERS_BIT, &peer->bitflags);
425
426         peer->transfers = newval;
427         DNS_BIT_SET(TRANSFERS_BIT, &peer->bitflags);
428
429         return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
430 }
431
432 isc_result_t
433 dns_peer_gettransfers(dns_peer_t *peer, isc_uint32_t *retval) {
434         REQUIRE(DNS_PEER_VALID(peer));
435         REQUIRE(retval != NULL);
436
437         if (DNS_BIT_CHECK(TRANSFERS_BIT, &peer->bitflags)) {
438                 *retval = peer->transfers;
439                 return (ISC_R_SUCCESS);
440         } else {
441                 return (ISC_R_NOTFOUND);
442         }
443 }
444
445 isc_result_t
446 dns_peer_settransferformat(dns_peer_t *peer, dns_transfer_format_t newval) {
447         isc_boolean_t existed;
448
449         REQUIRE(DNS_PEER_VALID(peer));
450
451         existed = DNS_BIT_CHECK(SERVER_TRANSFER_FORMAT_BIT,
452                                  &peer->bitflags);
453
454         peer->transfer_format = newval;
455         DNS_BIT_SET(SERVER_TRANSFER_FORMAT_BIT, &peer->bitflags);
456
457         return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
458 }
459
460 isc_result_t
461 dns_peer_gettransferformat(dns_peer_t *peer, dns_transfer_format_t *retval) {
462         REQUIRE(DNS_PEER_VALID(peer));
463         REQUIRE(retval != NULL);
464
465         if (DNS_BIT_CHECK(SERVER_TRANSFER_FORMAT_BIT, &peer->bitflags)) {
466                 *retval = peer->transfer_format;
467                 return (ISC_R_SUCCESS);
468         } else {
469                 return (ISC_R_NOTFOUND);
470         }
471 }
472
473 isc_result_t
474 dns_peer_getkey(dns_peer_t *peer, dns_name_t **retval) {
475         REQUIRE(DNS_PEER_VALID(peer));
476         REQUIRE(retval != NULL);
477
478         if (peer->key != NULL) {
479                 *retval = peer->key;
480         }
481
482         return (peer->key == NULL ? ISC_R_NOTFOUND : ISC_R_SUCCESS);
483 }
484
485 isc_result_t
486 dns_peer_setkey(dns_peer_t *peer, dns_name_t **keyval) {
487         isc_boolean_t exists = ISC_FALSE;
488
489         if (peer->key != NULL) {
490                 dns_name_free(peer->key, peer->mem);
491                 isc_mem_put(peer->mem, peer->key, sizeof(dns_name_t));
492                 exists = ISC_TRUE;
493         }
494
495         peer->key = *keyval;
496         *keyval = NULL;
497
498         return (exists ? ISC_R_EXISTS : ISC_R_SUCCESS);
499 }
500
501 isc_result_t
502 dns_peer_setkeybycharp(dns_peer_t *peer, const char *keyval) {
503         isc_buffer_t b;
504         dns_fixedname_t fname;
505         dns_name_t *name;
506         isc_result_t result;
507
508         dns_fixedname_init(&fname);
509         isc_buffer_init(&b, keyval, strlen(keyval));
510         isc_buffer_add(&b, strlen(keyval));
511         result = dns_name_fromtext(dns_fixedname_name(&fname), &b,
512                                    dns_rootname, ISC_FALSE, NULL);
513         if (result != ISC_R_SUCCESS)
514                 return (result);
515
516         name = isc_mem_get(peer->mem, sizeof(dns_name_t));
517         if (name == NULL)
518                 return (ISC_R_NOMEMORY);
519
520         dns_name_init(name, NULL);
521         result = dns_name_dup(dns_fixedname_name(&fname), peer->mem, name);
522         if (result != ISC_R_SUCCESS) {
523                 isc_mem_put(peer->mem, name, sizeof(dns_name_t));
524                 return (result);
525         }
526
527         result = dns_peer_setkey(peer, &name);
528         if (result != ISC_R_SUCCESS)
529                 isc_mem_put(peer->mem, name, sizeof(dns_name_t));
530
531         return (result);
532 }
533
534 isc_result_t
535 dns_peer_settransfersource(dns_peer_t *peer,
536                            const isc_sockaddr_t *transfer_source)
537 {
538         REQUIRE(DNS_PEER_VALID(peer));
539
540         if (peer->transfer_source != NULL) {
541                 isc_mem_put(peer->mem, peer->transfer_source,
542                             sizeof(*peer->transfer_source));
543                 peer->transfer_source = NULL;
544         }
545         if (transfer_source != NULL) {
546                 peer->transfer_source = isc_mem_get(peer->mem,
547                                                 sizeof(*peer->transfer_source));
548                 if (peer->transfer_source == NULL)
549                         return (ISC_R_NOMEMORY);
550
551                 *peer->transfer_source = *transfer_source;
552         }
553         return (ISC_R_SUCCESS);
554 }
555
556 isc_result_t
557 dns_peer_gettransfersource(dns_peer_t *peer, isc_sockaddr_t *transfer_source) {
558         REQUIRE(DNS_PEER_VALID(peer));
559         REQUIRE(transfer_source != NULL);
560
561         if (peer->transfer_source == NULL)
562                 return (ISC_R_NOTFOUND);
563         *transfer_source = *peer->transfer_source;
564         return (ISC_R_SUCCESS);
565 }
566
567 isc_result_t
568 dns_peer_setnotifysource(dns_peer_t *peer,
569                          const isc_sockaddr_t *notify_source)
570 {
571         REQUIRE(DNS_PEER_VALID(peer));
572
573         if (peer->notify_source != NULL) {
574                 isc_mem_put(peer->mem, peer->notify_source,
575                             sizeof(*peer->notify_source));
576                 peer->notify_source = NULL;
577         }
578         if (notify_source != NULL) {
579                 peer->notify_source = isc_mem_get(peer->mem,
580                                                 sizeof(*peer->notify_source));
581                 if (peer->notify_source == NULL)
582                         return (ISC_R_NOMEMORY);
583
584                 *peer->notify_source = *notify_source;
585         }
586         return (ISC_R_SUCCESS);
587 }
588
589 isc_result_t
590 dns_peer_getnotifysource(dns_peer_t *peer, isc_sockaddr_t *notify_source) {
591         REQUIRE(DNS_PEER_VALID(peer));
592         REQUIRE(notify_source != NULL);
593
594         if (peer->notify_source == NULL)
595                 return (ISC_R_NOTFOUND);
596         *notify_source = *peer->notify_source;
597         return (ISC_R_SUCCESS);
598 }
599
600 isc_result_t
601 dns_peer_setquerysource(dns_peer_t *peer, const isc_sockaddr_t *query_source) {
602         REQUIRE(DNS_PEER_VALID(peer));
603
604         if (peer->query_source != NULL) {
605                 isc_mem_put(peer->mem, peer->query_source,
606                             sizeof(*peer->query_source));
607                 peer->query_source = NULL;
608         }
609         if (query_source != NULL) {
610                 peer->query_source = isc_mem_get(peer->mem,
611                                                 sizeof(*peer->query_source));
612                 if (peer->query_source == NULL)
613                         return (ISC_R_NOMEMORY);
614
615                 *peer->query_source = *query_source;
616         }
617         return (ISC_R_SUCCESS);
618 }
619
620 isc_result_t
621 dns_peer_getquerysource(dns_peer_t *peer, isc_sockaddr_t *query_source) {
622         REQUIRE(DNS_PEER_VALID(peer));
623         REQUIRE(query_source != NULL);
624
625         if (peer->query_source == NULL)
626                 return (ISC_R_NOTFOUND);
627         *query_source = *peer->query_source;
628         return (ISC_R_SUCCESS);
629 }
630
631 isc_result_t
632 dns_peer_setudpsize(dns_peer_t *peer, isc_uint16_t udpsize) {
633         isc_boolean_t existed;
634
635         REQUIRE(DNS_PEER_VALID(peer));
636
637         existed = DNS_BIT_CHECK(SERVER_UDPSIZE_BIT, &peer->bitflags);
638
639         peer->udpsize = udpsize;
640         DNS_BIT_SET(SERVER_UDPSIZE_BIT, &peer->bitflags);
641
642         return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
643 }
644
645 isc_result_t
646 dns_peer_getudpsize(dns_peer_t *peer, isc_uint16_t *udpsize) {
647
648         REQUIRE(DNS_PEER_VALID(peer));
649         REQUIRE(udpsize != NULL);
650
651         if (DNS_BIT_CHECK(SERVER_UDPSIZE_BIT, &peer->bitflags)) {
652                 *udpsize = peer->udpsize;
653                 return (ISC_R_SUCCESS);
654         } else {
655                 return (ISC_R_NOTFOUND);
656         }
657 }
658
659 isc_result_t
660 dns_peer_setmaxudp(dns_peer_t *peer, isc_uint16_t maxudp) {
661         isc_boolean_t existed;
662
663         REQUIRE(DNS_PEER_VALID(peer));
664
665         existed = DNS_BIT_CHECK(SERVER_MAXUDP_BIT, &peer->bitflags);
666
667         peer->maxudp = maxudp;
668         DNS_BIT_SET(SERVER_MAXUDP_BIT, &peer->bitflags);
669
670         return (existed ? ISC_R_EXISTS : ISC_R_SUCCESS);
671 }
672
673 isc_result_t
674 dns_peer_getmaxudp(dns_peer_t *peer, isc_uint16_t *maxudp) {
675
676         REQUIRE(DNS_PEER_VALID(peer));
677         REQUIRE(maxudp != NULL);
678
679         if (DNS_BIT_CHECK(SERVER_MAXUDP_BIT, &peer->bitflags)) {
680                 *maxudp = peer->maxudp;
681                 return (ISC_R_SUCCESS);
682         } else {
683                 return (ISC_R_NOTFOUND);
684         }
685 }