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