00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00032 #include "dhcpd.h"
00033 #include "arpa/nameser.h"
00034 #include <isc/md5.h>
00035 #include <isc/sha2.h>
00036 #include <dns/result.h>
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 dns_zone_hash_t *dns_zone_hash;
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150 typedef struct dhcp_ddns_rdata {
00151 dns_rdata_t rdata;
00152 dns_rdatalist_t rdatalist;
00153 dns_rdataset_t rdataset;
00154 } dhcp_ddns_data_t;
00155
00156 #if defined (NSUPDATE)
00157 #if defined (DNS_ZONE_LOOKUP)
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 typedef struct dhcp_ddns_ns {
00172 struct dhcp_ddns_ns *next;
00173 struct data_string oname;
00174 char *zname;
00175
00176 dns_clientresevent_t *eventp;
00177
00178
00179 dns_name_t *ns_name;
00180 dns_rdataset_t *rdataset;
00181 dns_rdatatype_t rdtype;
00182
00183 struct in_addr addrs[DHCP_MAXNS];
00184 struct in6_addr addrs6[DHCP_MAXNS];
00185 int num_addrs;
00186 int num_addrs6;
00187 int ttl;
00188
00189 void *transaction;
00190 } dhcp_ddns_ns_t;
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207 dhcp_ddns_ns_t *dns_outstanding_ns = NULL;
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 void
00225 add_to_ns_queue(dhcp_ddns_ns_t *ns_cb)
00226 {
00227 ns_cb->next = dns_outstanding_ns;
00228 dns_outstanding_ns = ns_cb;
00229 }
00230
00231
00232 void
00233 remove_from_ns_queue(dhcp_ddns_ns_t *ns_cb)
00234 {
00235 dhcp_ddns_ns_t **foo;
00236
00237 foo = &dns_outstanding_ns;
00238 while (*foo) {
00239 if (*foo == ns_cb) {
00240 *foo = ns_cb->next;
00241 break;
00242 }
00243 foo = &((*foo)->next);
00244 }
00245 ns_cb->next = NULL;
00246 }
00247
00248 isc_result_t
00249 find_in_ns_queue(dhcp_ddns_ns_t *ns_cb)
00250 {
00251 dhcp_ddns_ns_t *temp_cb;
00252 int in_len, temp_len;
00253
00254 in_len = strlen(ns_cb->zname);
00255
00256 for(temp_cb = dns_outstanding_ns;
00257 temp_cb != NULL;
00258 temp_cb = temp_cb->next) {
00259 temp_len = strlen(temp_cb->zname);
00260 if (temp_len > in_len)
00261 continue;
00262 if (strcmp(temp_cb->zname,
00263 ns_cb->zname + (in_len - temp_len)) == 0)
00264 return(ISC_R_SUCCESS);
00265 }
00266 return(ISC_R_NOTFOUND);
00267 }
00268
00269 void cache_found_zone (dhcp_ddns_ns_t *);
00270 #endif
00271
00272 void ddns_interlude(isc_task_t *, isc_event_t *);
00273
00274 #if defined (TRACING)
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310 #define TRACE_PTR_LEN 8
00311
00312 typedef struct dhcp_ddns_map {
00313 char old_pointer[TRACE_PTR_LEN];
00314 void *new_pointer;
00315 struct dhcp_ddns_map *next;
00316 } dhcp_ddns_map_t;
00317
00318
00319 static dhcp_ddns_map_t *ddns_map;
00320
00321 trace_type_t *trace_ddns_input;
00322 trace_type_t *trace_ddns_output;
00323
00324
00325
00326
00327
00328
00329
00330 void
00331 trace_ddns_input_write(dhcp_ddns_cb_t *ddns_cb, isc_result_t result)
00332 {
00333 trace_iov_t iov[2];
00334 u_int32_t old_result;
00335 char old_pointer[TRACE_PTR_LEN];
00336
00337 old_result = htonl((u_int32_t)result);
00338 memset(old_pointer, 0, TRACE_PTR_LEN);
00339 memcpy(old_pointer, &ddns_cb, sizeof(ddns_cb));
00340
00341 iov[0].len = sizeof(old_result);
00342 iov[0].buf = (char *)&old_result;
00343 iov[1].len = TRACE_PTR_LEN;
00344 iov[1].buf = old_pointer;
00345 trace_write_packet_iov(trace_ddns_input, 2, iov, MDL);
00346 }
00347
00348
00349
00350
00351
00352
00353
00354 static void
00355 trace_ddns_input_read(trace_type_t *ttype, unsigned length,
00356 char *buf)
00357 {
00358 u_int32_t old_result;
00359 char old_pointer[TRACE_PTR_LEN];
00360 dns_clientupdateevent_t *eventp;
00361 void *new_pointer;
00362 dhcp_ddns_map_t *ddns_map_ptr;
00363
00364 if (length < (sizeof(old_result) + TRACE_PTR_LEN)) {
00365 log_error("trace_ddns_input_read: data too short");
00366 return;
00367 }
00368
00369 memcpy(&old_result, buf, sizeof(old_result));
00370 memcpy(old_pointer, buf + sizeof(old_result), TRACE_PTR_LEN);
00371
00372
00373 for (ddns_map_ptr = ddns_map;
00374 ddns_map_ptr != NULL;
00375 ddns_map_ptr = ddns_map_ptr->next) {
00376 if ((ddns_map_ptr->new_pointer != NULL) &&
00377 memcmp(ddns_map_ptr->old_pointer,
00378 old_pointer, TRACE_PTR_LEN) == 0) {
00379 new_pointer = ddns_map_ptr->new_pointer;
00380 ddns_map_ptr->new_pointer = NULL;
00381 memset(ddns_map_ptr->old_pointer, 0, TRACE_PTR_LEN);
00382 break;
00383 }
00384 }
00385 if (ddns_map_ptr == NULL) {
00386 log_error("trace_dns_input_read: unable to map cb pointer");
00387 return;
00388 }
00389
00390 eventp = (dns_clientupdateevent_t *)
00391 isc_event_allocate(dhcp_gbl_ctx.mctx,
00392 dhcp_gbl_ctx.task,
00393 0,
00394 ddns_interlude,
00395 new_pointer,
00396 sizeof(dns_clientupdateevent_t));
00397 if (eventp == NULL) {
00398 log_error("trace_ddns_input_read: unable to allocate event");
00399 return;
00400 }
00401 eventp->result = ntohl(old_result);
00402
00403
00404 ddns_interlude(dhcp_gbl_ctx.task, (isc_event_t *)eventp);
00405
00406 return;
00407 }
00408
00409 static void
00410 trace_ddns_input_stop(trace_type_t *ttype)
00411 {
00412 }
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 isc_result_t
00432 trace_ddns_output_write(dns_client_t *client, dns_rdataclass_t rdclass,
00433 dns_name_t *zonename, dns_namelist_t *prerequisites,
00434 dns_namelist_t *updates, isc_sockaddrlist_t *servers,
00435 dns_tsec_t *tsec, unsigned int options,
00436 isc_task_t *task, isc_taskaction_t action, void *arg,
00437 dns_clientupdatetrans_t **transp)
00438 {
00439 isc_result_t result;
00440 u_int32_t old_result;
00441 char old_pointer[TRACE_PTR_LEN];
00442 dhcp_ddns_map_t *ddns_map_ptr;
00443
00444 if (trace_playback() != 0) {
00445
00446 unsigned buflen = 0;
00447 char *inbuf = NULL;
00448
00449 result = trace_get_packet(&trace_ddns_output,
00450 &buflen, &inbuf);
00451 if (result != ISC_R_SUCCESS) {
00452 log_error("trace_ddns_output_write: no input found");
00453 return (ISC_R_FAILURE);
00454 }
00455 if (buflen < (sizeof(old_result) + TRACE_PTR_LEN)) {
00456 log_error("trace_ddns_output_write: data too short");
00457 dfree(inbuf, MDL);
00458 return (ISC_R_FAILURE);
00459 }
00460 memcpy(&old_result, inbuf, sizeof(old_result));
00461 result = ntohl(old_result);
00462 memcpy(old_pointer, inbuf + sizeof(old_result), TRACE_PTR_LEN);
00463 dfree(inbuf, MDL);
00464
00465
00466 for (ddns_map_ptr = ddns_map;
00467 ddns_map_ptr != NULL;
00468 ddns_map_ptr = ddns_map_ptr->next) {
00469 if (ddns_map_ptr->new_pointer == NULL) {
00470 break;
00471 }
00472 }
00473
00474
00475
00476
00477
00478 if (ddns_map_ptr == NULL) {
00479 ddns_map_ptr = dmalloc(sizeof(*ddns_map_ptr), MDL);
00480 if (ddns_map_ptr == NULL) {
00481 log_error("trace_ddns_output_write: "
00482 "unable to allocate map entry");
00483 return(ISC_R_FAILURE);
00484 }
00485 ddns_map_ptr->next = ddns_map;
00486 ddns_map = ddns_map_ptr;
00487 }
00488
00489 memcpy(ddns_map_ptr->old_pointer, old_pointer, TRACE_PTR_LEN);
00490 ddns_map_ptr->new_pointer = arg;
00491 }
00492 else {
00493
00494 result = dns_client_startupdate(client, rdclass, zonename,
00495 prerequisites, updates,
00496 servers, tsec, options,
00497 task, action, arg, transp);
00498 }
00499
00500 if (trace_record() != 0) {
00501
00502 trace_iov_t iov[3];
00503 old_result = htonl((u_int32_t)result);
00504 memset(old_pointer, 0, TRACE_PTR_LEN);
00505 memcpy(old_pointer, &arg, sizeof(arg));
00506 iov[0].len = sizeof(old_result);
00507 iov[0].buf = (char *)&old_result;
00508 iov[1].len = TRACE_PTR_LEN;
00509 iov[1].buf = old_pointer;
00510
00511
00512 iov[2].len = sizeof(dhcp_ddns_cb_t);
00513 iov[2].buf = (char *)arg;
00514
00515 trace_write_packet_iov(trace_ddns_output, 3, iov, MDL);
00516 }
00517
00518 return(result);
00519 }
00520
00521 static void
00522 trace_ddns_output_read(trace_type_t *ttype, unsigned length,
00523 char *buf)
00524 {
00525 log_error("unaccounted for ddns output.");
00526 }
00527
00528 static void
00529 trace_ddns_output_stop(trace_type_t *ttype)
00530 {
00531 }
00532
00533 void
00534 trace_ddns_init()
00535 {
00536 trace_ddns_output = trace_type_register("ddns-output", NULL,
00537 trace_ddns_output_read,
00538 trace_ddns_output_stop, MDL);
00539 trace_ddns_input = trace_type_register("ddns-input", NULL,
00540 trace_ddns_input_read,
00541 trace_ddns_input_stop, MDL);
00542 ddns_map = NULL;
00543 }
00544
00545 #define ddns_update trace_ddns_output_write
00546 #else
00547 #define ddns_update dns_client_startupdate
00548 #endif
00549
00550 #define zone_resolve dns_client_startresolve
00551
00552
00553
00554
00555
00556 dhcp_ddns_cb_t *
00557 ddns_cb_alloc(const char *file, int line)
00558 {
00559 dhcp_ddns_cb_t *ddns_cb;
00560 int i;
00561
00562 ddns_cb = dmalloc(sizeof(*ddns_cb), file, line);
00563 if (ddns_cb != NULL) {
00564 ISC_LIST_INIT(ddns_cb->zone_server_list);
00565 for (i = 0; i < DHCP_MAXNS; i++) {
00566 ISC_LINK_INIT(&ddns_cb->zone_addrs[i], link);
00567 }
00568 }
00569
00570 #if defined (DEBUG_DNS_UPDATES)
00571 log_info("%s(%d): Allocating ddns_cb=%p", file, line, ddns_cb);
00572 #endif
00573
00574 return(ddns_cb);
00575 }
00576
00577 void
00578 ddns_cb_free(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
00579 {
00580 #if defined (DEBUG_DNS_UPDATES)
00581 log_info("%s(%d): freeing ddns_cb=%p", file, line, ddns_cb);
00582 #endif
00583
00584 data_string_forget(&ddns_cb->fwd_name, file, line);
00585 data_string_forget(&ddns_cb->rev_name, file, line);
00586 data_string_forget(&ddns_cb->dhcid, file, line);
00587
00588 if (ddns_cb->zone != NULL) {
00589 forget_zone((struct dns_zone **)&ddns_cb->zone);
00590 }
00591
00592
00593 if (ddns_cb->transaction != NULL)
00594 log_error("Impossible memory leak at %s:%d (attempt to free "
00595 "DDNS Control Block before transaction).", MDL);
00596
00597 dfree(ddns_cb, file, line);
00598 }
00599
00600 void
00601 ddns_cb_forget_zone(dhcp_ddns_cb_t *ddns_cb)
00602 {
00603 int i;
00604
00605 forget_zone(&ddns_cb->zone);
00606 ddns_cb->zone_name[0] = 0;
00607 ISC_LIST_INIT(ddns_cb->zone_server_list);
00608 for (i = 0; i < DHCP_MAXNS; i++) {
00609 ISC_LINK_INIT(&ddns_cb->zone_addrs[i], link);
00610 }
00611 }
00612
00613 isc_result_t find_tsig_key (ns_tsig_key **key, const char *zname,
00614 struct dns_zone *zone)
00615 {
00616 ns_tsig_key *tkey;
00617
00618 if (!zone)
00619 return ISC_R_NOTFOUND;
00620
00621 if (!zone -> key) {
00622 return DHCP_R_KEY_UNKNOWN;
00623 }
00624
00625 if ((!zone -> key -> name ||
00626 strlen (zone -> key -> name) > NS_MAXDNAME) ||
00627 (!zone -> key -> algorithm ||
00628 strlen (zone -> key -> algorithm) > NS_MAXDNAME) ||
00629 (!zone -> key) ||
00630 (!zone -> key -> key) ||
00631 (zone -> key -> key -> len == 0)) {
00632 return DHCP_R_INVALIDKEY;
00633 }
00634 tkey = dmalloc (sizeof *tkey, MDL);
00635 if (!tkey) {
00636 nomem:
00637 return ISC_R_NOMEMORY;
00638 }
00639 memset (tkey, 0, sizeof *tkey);
00640 tkey -> data = dmalloc (zone -> key -> key -> len, MDL);
00641 if (!tkey -> data) {
00642 dfree (tkey, MDL);
00643 goto nomem;
00644 }
00645 strcpy (tkey -> name, zone -> key -> name);
00646 strcpy (tkey -> alg, zone -> key -> algorithm);
00647 memcpy (tkey -> data,
00648 zone -> key -> key -> value, zone -> key -> key -> len);
00649 tkey -> len = zone -> key -> key -> len;
00650 *key = tkey;
00651 return ISC_R_SUCCESS;
00652 }
00653
00654 void tkey_free (ns_tsig_key **key)
00655 {
00656 if ((*key) -> data)
00657 dfree ((*key) -> data, MDL);
00658 dfree ((*key), MDL);
00659 *key = (ns_tsig_key *)0;
00660 }
00661 #endif
00662
00663 isc_result_t remove_dns_zone (struct dns_zone *zone)
00664 {
00665 struct dns_zone *tz = NULL;
00666
00667 if (dns_zone_hash) {
00668 dns_zone_hash_lookup(&tz, dns_zone_hash, zone->name, 0, MDL);
00669 if (tz != NULL) {
00670 dns_zone_hash_delete(dns_zone_hash, tz->name, 0, MDL);
00671 dns_zone_dereference(&tz, MDL);
00672 }
00673 }
00674
00675 return (ISC_R_SUCCESS);
00676 }
00677
00678 isc_result_t enter_dns_zone (struct dns_zone *zone)
00679 {
00680 struct dns_zone *tz = (struct dns_zone *)0;
00681
00682 if (dns_zone_hash) {
00683 dns_zone_hash_lookup (&tz,
00684 dns_zone_hash, zone -> name, 0, MDL);
00685 if (tz == zone) {
00686 dns_zone_dereference (&tz, MDL);
00687 return ISC_R_SUCCESS;
00688 }
00689 if (tz) {
00690 dns_zone_hash_delete (dns_zone_hash,
00691 zone -> name, 0, MDL);
00692 dns_zone_dereference (&tz, MDL);
00693 }
00694 } else {
00695 if (!dns_zone_new_hash(&dns_zone_hash, DNS_HASH_SIZE, MDL))
00696 return ISC_R_NOMEMORY;
00697 }
00698
00699 dns_zone_hash_add (dns_zone_hash, zone -> name, 0, zone, MDL);
00700 return ISC_R_SUCCESS;
00701 }
00702
00703 isc_result_t dns_zone_lookup (struct dns_zone **zone, const char *name)
00704 {
00705 int len;
00706 char *tname = (char *)0;
00707 isc_result_t status;
00708
00709 if (!dns_zone_hash)
00710 return ISC_R_NOTFOUND;
00711
00712 len = strlen (name);
00713 if (name [len - 1] != '.') {
00714 tname = dmalloc ((unsigned)len + 2, MDL);
00715 if (!tname)
00716 return ISC_R_NOMEMORY;
00717 strcpy (tname, name);
00718 tname [len] = '.';
00719 tname [len + 1] = 0;
00720 name = tname;
00721 }
00722 if (!dns_zone_hash_lookup (zone, dns_zone_hash, name, 0, MDL))
00723 status = ISC_R_NOTFOUND;
00724 else if ((*zone)->timeout && (*zone)->timeout < cur_time) {
00725 dns_zone_hash_delete(dns_zone_hash, (*zone)->name, 0, MDL);
00726 dns_zone_dereference(zone, MDL);
00727 status = ISC_R_NOTFOUND;
00728 } else
00729 status = ISC_R_SUCCESS;
00730
00731 if (tname)
00732 dfree (tname, MDL);
00733 return status;
00734 }
00735
00736 int dns_zone_dereference (ptr, file, line)
00737 struct dns_zone **ptr;
00738 const char *file;
00739 int line;
00740 {
00741 struct dns_zone *dns_zone;
00742
00743 if ((ptr == NULL) || (*ptr == NULL)) {
00744 log_error("%s(%d): null pointer", file, line);
00745 #if defined (POINTER_DEBUG)
00746 abort();
00747 #else
00748 return (0);
00749 #endif
00750 }
00751
00752 dns_zone = *ptr;
00753 *ptr = NULL;
00754 --dns_zone->refcnt;
00755 rc_register(file, line, ptr, dns_zone, dns_zone->refcnt, 1, RC_MISC);
00756 if (dns_zone->refcnt > 0)
00757 return (1);
00758
00759 if (dns_zone->refcnt < 0) {
00760 log_error("%s(%d): negative refcnt!", file, line);
00761 #if defined (DEBUG_RC_HISTORY)
00762 dump_rc_history(dns_zone);
00763 #endif
00764 #if defined (POINTER_DEBUG)
00765 abort();
00766 #else
00767 return (0);
00768 #endif
00769 }
00770
00771 if (dns_zone->name)
00772 dfree(dns_zone->name, file, line);
00773 if (dns_zone->key)
00774 omapi_auth_key_dereference(&dns_zone->key, file, line);
00775 if (dns_zone->primary)
00776 option_cache_dereference(&dns_zone->primary, file, line);
00777 if (dns_zone->secondary)
00778 option_cache_dereference(&dns_zone->secondary, file, line);
00779 if (dns_zone->primary6)
00780 option_cache_dereference(&dns_zone->primary6, file, line);
00781 if (dns_zone->secondary6)
00782 option_cache_dereference(&dns_zone->secondary6, file, line);
00783 dfree(dns_zone, file, line);
00784 return (1);
00785 }
00786
00787 #if defined (NSUPDATE)
00788 #if defined (DNS_ZONE_LOOKUP)
00789
00790
00791
00792
00793
00794 void
00795 zone_addr_to_ns(dhcp_ddns_ns_t *ns_cb,
00796 dns_rdataset_t *rdataset)
00797 {
00798 dns_rdata_t rdata;
00799 dns_rdata_in_a_t a;
00800 dns_rdata_in_aaaa_t aaaa;
00801
00802 dns_rdata_init(&rdata);
00803 dns_rdataset_current(rdataset, &rdata);
00804 switch (rdataset->type) {
00805 case dns_rdatatype_a:
00806 (void) dns_rdata_tostruct(&rdata, &a, NULL);
00807 memcpy(&ns_cb->addrs[ns_cb->num_addrs], &a.in_addr, 4);
00808 ns_cb->num_addrs++;
00809 dns_rdata_freestruct(&a);
00810 break;
00811 case dns_rdatatype_aaaa:
00812 (void) dns_rdata_tostruct(&rdata, &aaaa, NULL);
00813 memcpy(&ns_cb->addrs6[ns_cb->num_addrs6], &aaaa.in6_addr, 16);
00814 ns_cb->num_addrs6++;
00815 dns_rdata_freestruct(&aaaa);
00816 break;
00817 default:
00818 break;
00819 }
00820
00821 if ((ns_cb->ttl == 0) || (ns_cb->ttl > rdataset->ttl))
00822 ns_cb->ttl = rdataset->ttl;
00823 }
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856 void
00857 find_zone_addrs(isc_task_t *taskp,
00858 isc_event_t *eventp)
00859 {
00860 dns_clientresevent_t *ddns_event = (dns_clientresevent_t *)eventp;
00861 dhcp_ddns_ns_t *ns_cb = (dhcp_ddns_ns_t *)eventp->ev_arg;
00862 dns_name_t *ns_name = NULL;
00863 dns_rdataset_t *rdataset;
00864 isc_result_t result;
00865 dns_name_t *name;
00866 dns_rdata_t rdata = DNS_RDATA_INIT;
00867 dns_rdata_ns_t ns;
00868
00869
00870
00871 dns_client_destroyrestrans(&ns_cb->transaction);
00872
00873
00874
00875
00876
00877
00878 if (ddns_event->result == ISC_R_SUCCESS) {
00879
00880 for (name = ISC_LIST_HEAD(ddns_event->answerlist);
00881 name != NULL;
00882 name = ISC_LIST_NEXT(name, link)) {
00883
00884 for (rdataset = ISC_LIST_HEAD(name->list);
00885 rdataset != NULL;
00886 rdataset = ISC_LIST_NEXT(rdataset, link)) {
00887
00888 for (result = dns_rdataset_first(rdataset);
00889 result == ISC_R_SUCCESS;
00890 result = dns_rdataset_next(rdataset)) {
00891
00892
00893 zone_addr_to_ns(ns_cb, rdataset);
00894
00895
00896
00897
00898 if (ns_cb->num_addrs +
00899 ns_cb->num_addrs6 >= DHCP_MAXNS)
00900 goto done;
00901 }
00902 }
00903 }
00904 }
00905
00906
00907
00908
00909
00910 for (ns_name = ns_cb->ns_name;
00911 ns_name != NULL;
00912 ns_name = ISC_LIST_NEXT(ns_name, link)) {
00913
00914 if (ns_name == ns_cb->ns_name) {
00915
00916 rdataset = ns_cb->rdataset;
00917 } else {
00918 rdataset = ISC_LIST_HEAD(ns_name->list);
00919 }
00920
00921 for (;
00922 rdataset != NULL;
00923 rdataset = ISC_LIST_NEXT(rdataset, link)) {
00924
00925 if (rdataset->type != dns_rdatatype_ns)
00926 continue;
00927 dns_rdata_init(&rdata);
00928
00929 if (rdataset == ns_cb->rdataset) {
00930
00931 if (ns_cb->rdtype == dns_rdatatype_a) {
00932 ns_cb->rdtype = dns_rdatatype_aaaa;
00933 } else {
00934 ns_cb->rdtype = dns_rdatatype_a;
00935 if (dns_rdataset_next(rdataset) !=
00936 ISC_R_SUCCESS)
00937 continue;
00938 }
00939 } else {
00940 if ((!dns_rdataset_isassociated(rdataset)) ||
00941 (dns_rdataset_first(rdataset) !=
00942 ISC_R_SUCCESS))
00943 continue;
00944 }
00945
00946 dns_rdataset_current(rdataset, &rdata);
00947 if (dns_rdata_tostruct(&rdata, &ns, NULL) !=
00948 ISC_R_SUCCESS)
00949 continue;
00950
00951
00952 ns_cb->ns_name = ns_name;
00953 ns_cb->rdataset = rdataset;
00954
00955
00956 result = zone_resolve(dhcp_gbl_ctx.dnsclient, &ns.name,
00957 dns_rdataclass_in,
00958 ns_cb->rdtype,
00959 DNS_CLIENTRESOPT_NODNSSEC,
00960 dhcp_gbl_ctx.task,
00961 find_zone_addrs,
00962 (void *)ns_cb,
00963 &ns_cb->transaction);
00964
00965
00966 dns_rdata_freestruct(&ns);
00967
00968 if (result == ISC_R_SUCCESS)
00969
00970
00971
00972
00973 goto cleanup;
00974
00975 log_error("find_zone_ns: unable to continue "
00976 "resolve: %s %s",
00977 ns_cb->zname,
00978 isc_result_totext(result));
00979
00980
00981
00982
00983
00984
00985 goto done;
00986 }
00987 }
00988
00989 done:
00990
00991
00992
00993
00994
00995 if ((ns_cb->num_addrs != 0) ||
00996 (ns_cb->num_addrs6 != 0))
00997 cache_found_zone(ns_cb);
00998
00999 dns_client_freeresanswer(dhcp_gbl_ctx.dnsclient,
01000 &ns_cb->eventp->answerlist);
01001 isc_event_free((isc_event_t **)&ns_cb->eventp);
01002
01003 remove_from_ns_queue(ns_cb);
01004 data_string_forget(&ns_cb->oname, MDL);
01005 dfree(ns_cb, MDL);
01006
01007 cleanup:
01008
01009
01010 dns_client_freeresanswer(dhcp_gbl_ctx.dnsclient,
01011 &ddns_event->answerlist);
01012 isc_event_free(&eventp);
01013
01014 return;
01015
01016 }
01017
01018
01019
01020
01021
01022
01023
01024 void
01025 find_zone_ns(isc_task_t *taskp,
01026 isc_event_t *eventp)
01027 {
01028 dns_clientresevent_t *ddns_event = (dns_clientresevent_t *)eventp;
01029 dhcp_ddns_ns_t *ns_cb = (dhcp_ddns_ns_t *)eventp->ev_arg;
01030 dns_fixedname_t zname0;
01031 dns_name_t *zname = NULL, *ns_name = NULL;
01032 dns_rdataset_t *rdataset;
01033 isc_result_t result;
01034 dns_rdata_t rdata = DNS_RDATA_INIT;
01035 dns_rdata_ns_t ns;
01036
01037
01038 dns_client_destroyrestrans(&ns_cb->transaction);
01039
01040 if (ddns_event->result != ISC_R_SUCCESS) {
01041
01042
01043
01044 ns_cb->zname = strchr(ns_cb->zname, '.');
01045 if ((ns_cb->zname == NULL) ||
01046 (ns_cb->zname[1] == 0)) {
01047
01048 goto cleanup;
01049 }
01050 ns_cb->zname++;
01051
01052
01053
01054 if (((result = dhcp_isc_name((unsigned char *)ns_cb->zname,
01055 &zname0, &zname))
01056 != ISC_R_SUCCESS) ||
01057 ((result = zone_resolve(dhcp_gbl_ctx.dnsclient,
01058 zname, dns_rdataclass_in,
01059 dns_rdatatype_ns,
01060 DNS_CLIENTRESOPT_NODNSSEC,
01061 dhcp_gbl_ctx.task,
01062 find_zone_ns,
01063 (void *)ns_cb,
01064 &ns_cb->transaction))
01065 != ISC_R_SUCCESS)) {
01066 log_error("find_zone_ns: Unable to build "
01067 "name or start resolve: %s %s",
01068 ns_cb->zname,
01069 isc_result_totext(result));
01070 goto cleanup;
01071 }
01072
01073
01074
01075 dns_client_freeresanswer(dhcp_gbl_ctx.dnsclient,
01076 &ddns_event->answerlist);
01077 isc_event_free(&eventp);
01078 return;
01079 }
01080
01081
01082
01083
01084 ns_cb->eventp = ddns_event;
01085 for (ns_name = ISC_LIST_HEAD(ddns_event->answerlist);
01086 ns_name != NULL;
01087 ns_name = ISC_LIST_NEXT(ns_name, link)) {
01088
01089 for (rdataset = ISC_LIST_HEAD(ns_name->list);
01090 rdataset != NULL;
01091 rdataset = ISC_LIST_NEXT(rdataset, link)) {
01092
01093 if (rdataset->type != dns_rdatatype_ns)
01094 continue;
01095
01096 if ((!dns_rdataset_isassociated(rdataset)) ||
01097 (dns_rdataset_first(rdataset) !=
01098 ISC_R_SUCCESS))
01099 continue;
01100
01101 dns_rdataset_current(rdataset, &rdata);
01102 if (dns_rdata_tostruct(&rdata, &ns, NULL) !=
01103 ISC_R_SUCCESS)
01104 continue;
01105
01106
01107 ns_cb->ns_name = ns_name;
01108 ns_cb->rdataset = rdataset;
01109
01110
01111 result = zone_resolve(dhcp_gbl_ctx.dnsclient, &ns.name,
01112 dns_rdataclass_in,
01113 ns_cb->rdtype,
01114 DNS_CLIENTRESOPT_NODNSSEC,
01115 dhcp_gbl_ctx.task,
01116 find_zone_addrs,
01117 (void *)ns_cb,
01118 &ns_cb->transaction);
01119
01120
01121 dns_rdata_freestruct(&ns);
01122
01123 if (result == ISC_R_SUCCESS)
01124
01125
01126
01127
01128 return;
01129
01130 log_error("find_zone_ns: unable to continue "
01131 "resolve: %s %s",
01132 ns_cb->zname,
01133 isc_result_totext(result));
01134
01135
01136
01137
01138
01139 goto cleanup;
01140 }
01141 }
01142
01143 cleanup:
01144
01145
01146
01147
01148 dns_client_freeresanswer(dhcp_gbl_ctx.dnsclient,
01149 &ddns_event->answerlist);
01150 isc_event_free(&eventp);
01151
01152 remove_from_ns_queue(ns_cb);
01153
01154 data_string_forget(&ns_cb->oname, MDL);
01155 dfree(ns_cb, MDL);
01156 return;
01157
01158 }
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168 isc_result_t
01169 find_zone_start(dhcp_ddns_cb_t *ddns_cb, int direction)
01170 {
01171 isc_result_t status = ISC_R_NOTFOUND;
01172 dhcp_ddns_ns_t *ns_cb;
01173 dns_fixedname_t zname0;
01174 dns_name_t *zname = NULL;
01175
01176
01177
01178
01179
01180
01181 ns_cb = dmalloc(sizeof(*ns_cb), MDL);
01182 if (ns_cb == NULL) {
01183 log_error("find_zone_start: unable to allocate cb");
01184 return(ISC_R_FAILURE);
01185 }
01186 ns_cb->rdtype = dns_rdatatype_a;
01187
01188
01189 if (direction == FIND_FORWARD) {
01190 data_string_copy(&ns_cb->oname, &ddns_cb->fwd_name, MDL);
01191 } else {
01192 data_string_copy(&ns_cb->oname, &ddns_cb->rev_name, MDL);
01193 }
01194 ns_cb->zname = (char *)ns_cb->oname.data;
01195
01196
01197
01198
01199
01200 if (find_in_ns_queue(ns_cb) == ISC_R_SUCCESS) {
01201 data_string_forget(&ns_cb->oname, MDL);
01202 dfree(ns_cb, MDL);
01203 return (ISC_R_SUCCESS);
01204 }
01205
01206
01207
01208 if (((status = dhcp_isc_name((unsigned char *)ns_cb->zname,
01209 &zname0, &zname))
01210 != ISC_R_SUCCESS) ||
01211 ((status = zone_resolve(dhcp_gbl_ctx.dnsclient,
01212 zname, dns_rdataclass_in,
01213 dns_rdatatype_ns,
01214 DNS_CLIENTRESOPT_NODNSSEC,
01215 dhcp_gbl_ctx.task,
01216 find_zone_ns,
01217 (void *)ns_cb,
01218 &ns_cb->transaction))
01219 != ISC_R_SUCCESS)) {
01220 log_error("find_zone_start: Unable to build "
01221 "name or start resolve: %s %s",
01222 ns_cb->zname,
01223 isc_result_totext(status));
01224
01225
01226 data_string_forget(&ns_cb->oname, MDL);
01227 dfree(ns_cb, MDL);
01228 } else {
01229
01230
01231 add_to_ns_queue(ns_cb);
01232 }
01233
01234 return (status);
01235 }
01236 #endif
01237
01238 isc_result_t
01239 find_cached_zone(dhcp_ddns_cb_t *ddns_cb, int direction)
01240 {
01241 isc_result_t status = ISC_R_NOTFOUND;
01242 const char *np;
01243 struct dns_zone *zone = NULL;
01244 struct data_string nsaddrs;
01245 struct in_addr zone_addr;
01246 struct in6_addr zone_addr6;
01247 int ix;
01248
01249 if (direction == FIND_FORWARD) {
01250 np = (const char *)ddns_cb->fwd_name.data;
01251 } else {
01252 np = (const char *)ddns_cb->rev_name.data;
01253 }
01254
01255
01256 if ((np == NULL) || (*np == '\0')) {
01257 return (DHCP_R_INVALIDARG);
01258 }
01259
01260
01261
01262
01263 for (;;) {
01264 status = dns_zone_lookup(&zone, np);
01265 if (status == ISC_R_SUCCESS)
01266 break;
01267
01268 np = strchr(np, '.');
01269 if (np == NULL)
01270 break;
01271 np++;
01272 }
01273
01274 if (status != ISC_R_SUCCESS)
01275 return (status);
01276
01277
01278
01279
01280
01281 if ((zone->flags & DNS_ZONE_INACTIVE) != 0) {
01282 dns_zone_dereference(&zone, MDL);
01283 return (ISC_R_FAILURE);
01284 }
01285
01286
01287 if (strlen(zone->name) > sizeof(ddns_cb->zone_name)) {
01288 dns_zone_dereference(&zone, MDL);
01289 return (ISC_R_NOSPACE);
01290 }
01291 strcpy((char *)&ddns_cb->zone_name[0], zone->name);
01292
01293 memset (&nsaddrs, 0, sizeof nsaddrs);
01294 ix = 0;
01295
01296 if (zone->primary) {
01297 if (evaluate_option_cache(&nsaddrs, NULL, NULL, NULL,
01298 NULL, NULL, &global_scope,
01299 zone->primary, MDL)) {
01300 int ip = 0;
01301 while (ix < DHCP_MAXNS) {
01302 if (ip + 4 > nsaddrs.len)
01303 break;
01304 memcpy(&zone_addr, &nsaddrs.data[ip], 4);
01305 isc_sockaddr_fromin(&ddns_cb->zone_addrs[ix],
01306 &zone_addr,
01307 NS_DEFAULTPORT);
01308 ISC_LIST_APPEND(ddns_cb->zone_server_list,
01309 &ddns_cb->zone_addrs[ix],
01310 link);
01311 ip += 4;
01312 ix++;
01313 }
01314 data_string_forget(&nsaddrs, MDL);
01315 }
01316 }
01317
01318 if (zone->primary6) {
01319 if (evaluate_option_cache(&nsaddrs, NULL, NULL, NULL,
01320 NULL, NULL, &global_scope,
01321 zone->primary6, MDL)) {
01322 int ip = 0;
01323 while (ix < DHCP_MAXNS) {
01324 if (ip + 16 > nsaddrs.len)
01325 break;
01326 memcpy(&zone_addr6, &nsaddrs.data[ip], 16);
01327 isc_sockaddr_fromin6(&ddns_cb->zone_addrs[ix],
01328 &zone_addr6,
01329 NS_DEFAULTPORT);
01330 ISC_LIST_APPEND(ddns_cb->zone_server_list,
01331 &ddns_cb->zone_addrs[ix],
01332 link);
01333 ip += 16;
01334 ix++;
01335 }
01336 data_string_forget(&nsaddrs, MDL);
01337 }
01338 }
01339
01340 if (zone->secondary) {
01341 if (evaluate_option_cache(&nsaddrs, NULL, NULL, NULL,
01342 NULL, NULL, &global_scope,
01343 zone->secondary, MDL)) {
01344 int ip = 0;
01345 while (ix < DHCP_MAXNS) {
01346 if (ip + 4 > nsaddrs.len)
01347 break;
01348 memcpy(&zone_addr, &nsaddrs.data[ip], 4);
01349 isc_sockaddr_fromin(&ddns_cb->zone_addrs[ix],
01350 &zone_addr,
01351 NS_DEFAULTPORT);
01352 ISC_LIST_APPEND(ddns_cb->zone_server_list,
01353 &ddns_cb->zone_addrs[ix],
01354 link);
01355 ip += 4;
01356 ix++;
01357 }
01358 data_string_forget (&nsaddrs, MDL);
01359 }
01360 }
01361
01362 if (zone->secondary6) {
01363 if (evaluate_option_cache(&nsaddrs, NULL, NULL, NULL,
01364 NULL, NULL, &global_scope,
01365 zone->secondary6, MDL)) {
01366 int ip = 0;
01367 while (ix < DHCP_MAXNS) {
01368 if (ip + 16 > nsaddrs.len)
01369 break;
01370 memcpy(&zone_addr6, &nsaddrs.data[ip], 16);
01371 isc_sockaddr_fromin6(&ddns_cb->zone_addrs[ix],
01372 &zone_addr6,
01373 NS_DEFAULTPORT);
01374 ISC_LIST_APPEND(ddns_cb->zone_server_list,
01375 &ddns_cb->zone_addrs[ix],
01376 link);
01377 ip += 16;
01378 ix++;
01379 }
01380 data_string_forget (&nsaddrs, MDL);
01381 }
01382 }
01383
01384 dns_zone_reference(&ddns_cb->zone, zone, MDL);
01385 dns_zone_dereference (&zone, MDL);
01386 return ISC_R_SUCCESS;
01387 }
01388
01389 void forget_zone (struct dns_zone **zone)
01390 {
01391 dns_zone_dereference (zone, MDL);
01392 }
01393
01394 void repudiate_zone (struct dns_zone **zone)
01395 {
01396
01397 if ((zone == NULL) || (*zone == NULL)) {
01398 log_info("Null argument to repudiate zone");
01399 return;
01400 }
01401
01402 (*zone)->flags |= DNS_ZONE_INACTIVE;
01403 dns_zone_dereference(zone, MDL);
01404 }
01405
01406 #if defined (DNS_ZONE_LOOKUP)
01407 void cache_found_zone(dhcp_ddns_ns_t *ns_cb)
01408 {
01409 struct dns_zone *zone = NULL;
01410 int len, remove_zone = 0;
01411
01412
01413 if (dns_zone_lookup(&zone, ns_cb->zname) == ISC_R_SUCCESS) {
01414
01415 if (zone->timeout == 0)
01416 return;
01417
01418
01419 if (zone->primary)
01420 option_cache_dereference(&zone->primary, MDL);
01421 if (zone->primary6)
01422 option_cache_dereference(&zone->primary6, MDL);
01423
01424
01425
01426 remove_zone = 1;
01427 } else if (dns_zone_allocate(&zone, MDL) == 0) {
01428 return;
01429 } else {
01430
01431
01432
01433
01434
01435 len = strlen(ns_cb->zname);
01436 zone->name = dmalloc(len + 2, MDL);
01437 if (zone->name == NULL) {
01438 goto cleanup;
01439 }
01440
01441
01442 strcpy(zone->name, ns_cb->zname);
01443 if (zone->name[len-1] != '.') {
01444 zone->name[len] = '.';
01445 zone->name[len+1] = 0;
01446 }
01447 }
01448
01449 zone->timeout = cur_time + ns_cb->ttl;
01450
01451 if (ns_cb->num_addrs != 0) {
01452 len = ns_cb->num_addrs * sizeof(struct in_addr);
01453 if ((!option_cache_allocate(&zone->primary, MDL)) ||
01454 (!buffer_allocate(&zone->primary->data.buffer,
01455 len, MDL))) {
01456 if (remove_zone == 1)
01457 remove_dns_zone(zone);
01458 goto cleanup;
01459 }
01460 memcpy(zone->primary->data.buffer->data, ns_cb->addrs, len);
01461 zone->primary->data.data =
01462 &zone->primary->data.buffer->data[0];
01463 zone->primary->data.len = len;
01464 }
01465 if (ns_cb->num_addrs6 != 0) {
01466 len = ns_cb->num_addrs6 * sizeof(struct in6_addr);
01467 if ((!option_cache_allocate(&zone->primary6, MDL)) ||
01468 (!buffer_allocate(&zone->primary6->data.buffer,
01469 len, MDL))) {
01470 if (remove_zone == 1)
01471 remove_dns_zone(zone);
01472 goto cleanup;
01473 }
01474 memcpy(zone->primary6->data.buffer->data, ns_cb->addrs6, len);
01475 zone->primary6->data.data =
01476 &zone->primary6->data.buffer->data[0];
01477 zone->primary6->data.len = len;
01478 }
01479
01480 enter_dns_zone(zone);
01481
01482 cleanup:
01483 dns_zone_dereference(&zone, MDL);
01484 return;
01485 }
01486 #endif
01487
01512 int get_std_dhcid(dhcp_ddns_cb_t *ddns_cb,
01513 int type,
01514 const u_int8_t *identifier,
01515 unsigned id_len)
01516 {
01517 struct data_string *id = &ddns_cb->dhcid;
01518 isc_sha256_t sha256;
01519 unsigned char buf[ISC_SHA256_DIGESTLENGTH];
01520 unsigned char fwd_buf[256];
01521 unsigned fwd_buflen = 0;
01522
01523
01524 if (type < 0 || type > 65535)
01525 return (0);
01526
01527
01528 if (MRns_name_pton((char *)ddns_cb->fwd_name.data, fwd_buf, 256) == -1)
01529 return (0);
01530 while(fwd_buf[fwd_buflen] != 0) {
01531 fwd_buflen += fwd_buf[fwd_buflen] + 1;
01532 }
01533 fwd_buflen++;
01534
01535 if (!buffer_allocate(&id->buffer,
01536 ISC_SHA256_DIGESTLENGTH + 2 + 1,
01537 MDL))
01538 return (0);
01539 id->data = id->buffer->data;
01540
01541
01542 putUShort(id->buffer->data, (unsigned)type);
01543
01544
01545 putUChar(id->buffer->data + 2, 1u);
01546
01547
01548 isc_sha256_init(&sha256);
01549 isc_sha256_update(&sha256, identifier, id_len);
01550 isc_sha256_update(&sha256, fwd_buf, fwd_buflen);
01551 isc_sha256_final(buf, &sha256);
01552
01553 memcpy(id->buffer->data + 3, &buf, ISC_SHA256_DIGESTLENGTH);
01554
01555 id->len = ISC_SHA256_DIGESTLENGTH + 2 + 1;
01556
01557 return (1);
01558 }
01559
01581 int get_int_dhcid (dhcp_ddns_cb_t *ddns_cb,
01582 int type,
01583 const u_int8_t *data,
01584 unsigned len)
01585 {
01586 struct data_string *id = &ddns_cb->dhcid;
01587 unsigned char buf[ISC_MD5_DIGESTLENGTH];
01588 isc_md5_t md5;
01589 int i;
01590
01591
01592 if (type < 0 || type > 65535)
01593 return (0);
01594
01595
01596
01597
01598
01599 if (!buffer_allocate(&id -> buffer,
01600 (ISC_MD5_DIGESTLENGTH * 2) + 4, MDL))
01601 return (0);
01602 id->data = id->buffer->data;
01603
01604
01605
01606
01607
01608
01609 id->buffer->data[0] = ISC_MD5_DIGESTLENGTH * 2 + 2;
01610
01611
01612 id->buffer->data[1] = "0123456789abcdef"[(type >> 4) & 0xf];
01613
01614
01615
01616
01617 id->buffer->data[2] = "0123456789abcdef"[type % 15];
01618
01619
01620 isc_md5_init(&md5);
01621 isc_md5_update(&md5, data, len);
01622 isc_md5_final(&md5, buf);
01623
01624
01625 for (i = 0; i < ISC_MD5_DIGESTLENGTH; i++) {
01626 id->buffer->data[i * 2 + 3] =
01627 "0123456789abcdef"[(buf[i] >> 4) & 0xf];
01628 id->buffer->data[i * 2 + 4] =
01629 "0123456789abcdef"[buf[i] & 0xf];
01630 }
01631
01632 id->len = ISC_MD5_DIGESTLENGTH * 2 + 3;
01633 id->buffer->data[id->len] = 0;
01634 id->terminated = 1;
01635
01636 return (1);
01637 }
01638
01639 int get_dhcid(dhcp_ddns_cb_t *ddns_cb,
01640 int type,
01641 const u_int8_t *identifier,
01642 unsigned id_len)
01643 {
01644 if (ddns_cb->dhcid_class == dns_rdatatype_dhcid)
01645 return get_std_dhcid(ddns_cb, type, identifier, id_len);
01646 else
01647 return get_int_dhcid(ddns_cb, type, identifier, id_len);
01648 }
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661 void
01662 dhcid_tolease(struct data_string *dhcid,
01663 struct data_string *leaseid)
01664 {
01665
01666 data_string_copy(leaseid, dhcid, MDL);
01667 leaseid->data++;
01668 leaseid->len--;
01669 }
01670
01671 isc_result_t
01672 dhcid_fromlease(struct data_string *dhcid,
01673 struct data_string *leaseid)
01674 {
01675 if (!buffer_allocate(&dhcid->buffer, leaseid->len + 2, MDL)) {
01676 return(ISC_R_FAILURE);
01677 }
01678
01679 dhcid->data = dhcid->buffer->data;
01680
01681 dhcid->buffer->data[0] = leaseid->len;
01682 memcpy(dhcid->buffer->data + 1, leaseid->data, leaseid->len);
01683 dhcid->len = leaseid->len + 1;
01684 if (leaseid->terminated == 1) {
01685 dhcid->buffer->data[dhcid->len] = 0;
01686 dhcid->terminated = 1;
01687 }
01688
01689 return(ISC_R_SUCCESS);
01690 }
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700 static isc_result_t
01701 make_dns_dataset(dns_rdataclass_t dataclass,
01702 dns_rdatatype_t datatype,
01703 dhcp_ddns_data_t *dataspace,
01704 unsigned char *data,
01705 int datalen,
01706 int ttl)
01707 {
01708 dns_rdata_t *rdata = &dataspace->rdata;
01709 dns_rdatalist_t *rdatalist = &dataspace->rdatalist;
01710 dns_rdataset_t *rdataset = &dataspace->rdataset;
01711
01712 isc_region_t region;
01713
01714
01715 dns_rdata_init(rdata);
01716
01717 if (data == NULL) {
01718
01719 rdata->flags = DNS_RDATA_UPDATE;
01720 rdata->type = datatype;
01721 rdata->rdclass = dataclass;
01722 } else {
01723 switch(datatype) {
01724 case dns_rdatatype_a:
01725 case dns_rdatatype_aaaa:
01726 case dns_rdatatype_txt:
01727 case dns_rdatatype_dhcid:
01728 case dns_rdatatype_ptr:
01729
01730
01731 region.base = data;
01732 region.length = datalen;
01733 dns_rdata_fromregion(rdata, dataclass, datatype,
01734 ®ion);
01735 break;
01736 default:
01737 return(DHCP_R_INVALIDARG);
01738 break;
01739 }
01740 }
01741
01742
01743 dns_rdatalist_init(rdatalist);
01744 rdatalist->type = datatype;
01745 rdatalist->rdclass = dataclass;
01746 rdatalist->ttl = ttl;
01747 ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
01748
01749
01750 dns_rdataset_init(rdataset);
01751 dns_rdatalist_tordataset(rdatalist, rdataset);
01752
01753 return(ISC_R_SUCCESS);
01754 }
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777 static isc_result_t
01778 ddns_modify_fwd_add1(dhcp_ddns_cb_t *ddns_cb,
01779 dhcp_ddns_data_t *dataspace,
01780 dns_name_t *pname,
01781 dns_name_t *uname)
01782 {
01783 isc_result_t result;
01784
01785
01786 if ((ddns_cb->flags & DDNS_INCLUDE_RRSET) != 0) {
01787
01788 result = make_dns_dataset(dns_rdataclass_none,
01789 ddns_cb->address_type,
01790 dataspace, NULL, 0, 0);
01791 } else {
01792
01793 result = make_dns_dataset(dns_rdataclass_none,
01794 dns_rdatatype_any,
01795 dataspace, NULL, 0, 0);
01796 }
01797 if (result != ISC_R_SUCCESS) {
01798 return(result);
01799 }
01800 ISC_LIST_APPEND(pname->list, &dataspace->rdataset, link);
01801 dataspace++;
01802
01803
01804
01805 result = make_dns_dataset(dns_rdataclass_in, ddns_cb->address_type,
01806 dataspace,
01807 (unsigned char *)ddns_cb->address.iabuf,
01808 ddns_cb->address.len, ddns_cb->ttl);
01809 if (result != ISC_R_SUCCESS) {
01810 return(result);
01811 }
01812 ISC_LIST_APPEND(uname->list, &dataspace->rdataset, link);
01813 dataspace++;
01814
01815
01816 result = make_dns_dataset(dns_rdataclass_in, ddns_cb->dhcid_class,
01817 dataspace,
01818 (unsigned char *)ddns_cb->dhcid.data,
01819 ddns_cb->dhcid.len, ddns_cb->ttl);
01820 if (result != ISC_R_SUCCESS) {
01821 return(result);
01822 }
01823 ISC_LIST_APPEND(uname->list, &dataspace->rdataset, link);
01824
01825 return(ISC_R_SUCCESS);
01826 }
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856 static isc_result_t
01857 ddns_modify_fwd_add2(dhcp_ddns_cb_t *ddns_cb,
01858 dhcp_ddns_data_t *dataspace,
01859 dns_name_t *pname,
01860 dns_name_t *uname)
01861 {
01862 isc_result_t result = ISC_R_SUCCESS;
01863
01864
01865
01866
01867
01868 if ((ddns_cb->flags & DDNS_CONFLICT_OVERRIDE) == 0) {
01869
01870
01871 result = make_dns_dataset(dns_rdataclass_in, ddns_cb->dhcid_class,
01872 dataspace,
01873 (unsigned char *)ddns_cb->dhcid.data,
01874 ddns_cb->dhcid.len, 0);
01875 if (result != ISC_R_SUCCESS) {
01876 return(result);
01877 }
01878 ISC_LIST_APPEND(pname->list, &dataspace->rdataset, link);
01879 dataspace++;
01880 } else {
01881
01882
01883 result = make_dns_dataset(dns_rdataclass_any,
01884 ddns_cb->dhcid_class,
01885 dataspace, NULL, 0, 0);
01886 if (result != ISC_R_SUCCESS) {
01887 return(result);
01888 }
01889 ISC_LIST_APPEND(uname->list, &dataspace->rdataset, link);
01890 dataspace++;
01891
01892
01893 result = make_dns_dataset(dns_rdataclass_in, ddns_cb->dhcid_class,
01894 dataspace,
01895 (unsigned char *)ddns_cb->dhcid.data,
01896 ddns_cb->dhcid.len, ddns_cb->ttl);
01897 if (result != ISC_R_SUCCESS) {
01898 return(result);
01899 }
01900 ISC_LIST_APPEND(uname->list, &dataspace->rdataset, link);
01901 dataspace++;
01902 }
01903
01904
01905
01906 result = make_dns_dataset(dns_rdataclass_any, ddns_cb->address_type,
01907 dataspace, NULL, 0, 0);
01908 if (result != ISC_R_SUCCESS) {
01909 return(result);
01910 }
01911 ISC_LIST_APPEND(uname->list, &dataspace->rdataset, link);
01912 dataspace++;
01913
01914
01915 result = make_dns_dataset(dns_rdataclass_in, ddns_cb->address_type,
01916 dataspace,
01917 (unsigned char *)ddns_cb->address.iabuf,
01918 ddns_cb->address.len, ddns_cb->ttl);
01919 if (result != ISC_R_SUCCESS) {
01920 return(result);
01921 }
01922 ISC_LIST_APPEND(uname->list, &dataspace->rdataset, link);
01923
01924 return(ISC_R_SUCCESS);
01925 }
01926
01927
01928
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949 static isc_result_t
01950 ddns_modify_fwd_rem1(dhcp_ddns_cb_t *ddns_cb,
01951 dhcp_ddns_data_t *dataspace,
01952 dns_name_t *pname,
01953 dns_name_t *uname)
01954 {
01955 isc_result_t result = ISC_R_SUCCESS;
01956
01957
01958
01959 result = make_dns_dataset(dns_rdataclass_in, ddns_cb->dhcid_class,
01960 dataspace,
01961 (unsigned char *)ddns_cb->dhcid.data,
01962 ddns_cb->dhcid.len, 0);
01963 if (result != ISC_R_SUCCESS) {
01964 return(result);
01965 }
01966 ISC_LIST_APPEND(pname->list, &dataspace->rdataset, link);
01967 dataspace++;
01968
01969
01970
01971 result = make_dns_dataset(dns_rdataclass_none, ddns_cb->address_type,
01972 dataspace,
01973 (unsigned char *)ddns_cb->address.iabuf,
01974 ddns_cb->address.len, 0);
01975 if (result != ISC_R_SUCCESS) {
01976 return(result);
01977 }
01978 ISC_LIST_APPEND(uname->list, &dataspace->rdataset, link);
01979
01980 return(ISC_R_SUCCESS);
01981 }
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996 static isc_result_t
01997 ddns_modify_fwd_rem2(dhcp_ddns_cb_t *ddns_cb,
01998 dhcp_ddns_data_t *dataspace,
01999 dns_name_t *pname,
02000 dns_name_t *uname)
02001 {
02002 isc_result_t result;
02003
02004
02005
02006 result = make_dns_dataset(dns_rdataclass_none, dns_rdatatype_a,
02007 dataspace, NULL, 0, 0);
02008 if (result != ISC_R_SUCCESS) {
02009 return(result);
02010 }
02011 ISC_LIST_APPEND(pname->list, &dataspace->rdataset, link);
02012 dataspace++;
02013
02014
02015 result = make_dns_dataset(dns_rdataclass_none, dns_rdatatype_aaaa,
02016 dataspace, NULL, 0, 0);
02017 if (result != ISC_R_SUCCESS) {
02018 return(result);
02019 }
02020 ISC_LIST_APPEND(pname->list, &dataspace->rdataset, link);
02021 dataspace++;
02022
02023
02024
02025 result = make_dns_dataset(dns_rdataclass_none, ddns_cb->dhcid_class,
02026 dataspace,
02027 (unsigned char *)ddns_cb->dhcid.data,
02028 ddns_cb->dhcid.len, 0);
02029 if (result != ISC_R_SUCCESS) {
02030 return(result);
02031 }
02032 ISC_LIST_APPEND(uname->list, &dataspace->rdataset, link);
02033
02034 return(ISC_R_SUCCESS);
02035 }
02036
02037
02038
02039
02040
02041
02042 void ddns_interlude(isc_task_t *taskp,
02043 isc_event_t *eventp)
02044 {
02045 dhcp_ddns_cb_t *ddns_cb = (dhcp_ddns_cb_t *)eventp->ev_arg;
02046 dns_clientupdateevent_t *ddns_event = (dns_clientupdateevent_t *)eventp;
02047 isc_result_t eresult = ddns_event->result;
02048 isc_result_t result;
02049
02050
02051
02052 isc_event_free(&eventp);
02053
02054 #if defined (TRACING)
02055 if (trace_record()) {
02056 trace_ddns_input_write(ddns_cb, eresult);
02057 }
02058 #endif
02059
02060 #if defined (DEBUG_DNS_UPDATES)
02061 print_dns_status(DDNS_PRINT_INBOUND, ddns_cb, eresult);
02062 #endif
02063
02064
02065 dns_client_destroyupdatetrans(&ddns_cb->transaction);
02066
02067
02068
02069 if ((eresult == ISC_R_CANCELED) ||
02070 ((ddns_cb->flags & DDNS_ABORT) != 0)) {
02071 #if defined (DEBUG_DNS_UPDATES)
02072 log_info("DDNS: completeing transaction cancellation cb=%p, "
02073 "flags=%x, %s",
02074 ddns_cb, ddns_cb->flags, isc_result_totext(eresult));
02075 #endif
02076 if ((ddns_cb->flags & DDNS_ABORT) == 0) {
02077 log_info("DDNS: cleaning up lease pointer for a cancel "
02078 "cb=%p", ddns_cb);
02079
02080
02081
02082
02083
02084
02085 ddns_cb->cur_func(ddns_cb, eresult);
02086 return;
02087 }
02088
02089 if (ddns_cb->next_op != NULL) {
02090
02091 ddns_cb_free(ddns_cb->next_op, MDL);
02092 }
02093 ddns_cb_free(ddns_cb, MDL);
02094 return;
02095 }
02096
02097
02098 if ((eresult == DNS_R_NOTAUTH) ||
02099 (eresult == DNS_R_NOTZONE)) {
02100 int i;
02101
02102
02103 log_error("DDNS: bad zone information, repudiating zone %s",
02104 ddns_cb->zone_name);
02105 repudiate_zone(&ddns_cb->zone);
02106 ddns_cb->zone_name[0] = 0;
02107 ISC_LIST_INIT(ddns_cb->zone_server_list);
02108 for (i = 0; i < DHCP_MAXNS; i++) {
02109 ISC_LINK_INIT(&ddns_cb->zone_addrs[i], link);
02110 }
02111
02112 if ((ddns_cb->state == DDNS_STATE_ADD_PTR) ||
02113 (ddns_cb->state == DDNS_STATE_REM_PTR)) {
02114 result = ddns_modify_ptr(ddns_cb, MDL);
02115 } else {
02116 result = ddns_modify_fwd(ddns_cb, MDL);
02117 }
02118
02119 if (result != ISC_R_SUCCESS) {
02120
02121
02122 log_info("DDNS: Failed to retry after zone failure");
02123 ddns_cb->cur_func(ddns_cb, result);
02124 }
02125 return;
02126 } else {
02127
02128 ddns_cb->cur_func(ddns_cb, eresult);
02129 }
02130
02131 return;
02132 }
02133
02134
02135
02136
02137
02138
02139
02140 isc_result_t
02141 ddns_modify_fwd(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
02142 {
02143 isc_result_t result;
02144 dns_tsec_t *tsec_key = NULL;
02145
02146 unsigned char *clientname;
02147 dhcp_ddns_data_t *dataspace = NULL;
02148 dns_namelist_t prereqlist, updatelist;
02149 dns_fixedname_t zname0, pname0, uname0;
02150 dns_name_t *zname = NULL, *pname, *uname;
02151
02152 isc_sockaddrlist_t *zlist = NULL;
02153
02154
02155 clientname = (unsigned char *)ddns_cb->fwd_name.data;
02156
02157
02158 if (ddns_cb->address.len == 4) {
02159 ddns_cb->address_type = dns_rdatatype_a;
02160 } else if (ddns_cb->address.len == 16) {
02161 ddns_cb->address_type = dns_rdatatype_aaaa;
02162 } else {
02163 return DHCP_R_INVALIDARG;
02164 }
02165
02166
02167
02168
02169
02170
02171
02172
02173
02174 if (ddns_cb->zone == NULL) {
02175 result = find_cached_zone(ddns_cb, FIND_FORWARD);
02176 #if defined (DNS_ZONE_LOOKUP)
02177 if (result == ISC_R_NOTFOUND) {
02178
02179
02180
02181
02182 if (find_zone_start(ddns_cb, FIND_FORWARD)
02183 == ISC_R_SUCCESS) {
02184
02185
02186
02187
02188
02189
02190
02191
02192 goto cleanup;
02193 }
02194 }
02195 #endif
02196 if (result != ISC_R_SUCCESS)
02197 goto cleanup;
02198 }
02199
02200
02201
02202
02203
02204
02205 if (ddns_cb->zone) {
02206
02207 result = dhcp_isc_name(ddns_cb->zone_name, &zname0, &zname);
02208 if (result != ISC_R_SUCCESS) {
02209 log_error("Unable to build name for zone for "
02210 "fwd update: %s %s",
02211 ddns_cb->zone_name,
02212 isc_result_totext(result));
02213 goto cleanup;
02214 }
02215
02216 if (!(ISC_LIST_EMPTY(ddns_cb->zone_server_list))) {
02217
02218 zlist = &ddns_cb->zone_server_list;
02219 }
02220
02221
02222 if (ddns_cb->zone->key != NULL) {
02223
02224
02225
02226
02227
02228
02229 tsec_key = ddns_cb->zone->key->tsec_key;
02230 if (tsec_key == NULL) {
02231 log_error("No tsec for use with key %s",
02232 ddns_cb->zone->key->name);
02233 }
02234 }
02235 }
02236
02237
02238 if (((result = dhcp_isc_name(clientname, &pname0, &pname))
02239 != ISC_R_SUCCESS) ||
02240 ((result = dhcp_isc_name(clientname, &uname0, &uname))
02241 != ISC_R_SUCCESS)) {
02242 log_error("Unable to build name for fwd update: %s %s",
02243 clientname, isc_result_totext(result));
02244 goto cleanup;
02245 }
02246
02247
02248 dataspace = isc_mem_get(dhcp_gbl_ctx.mctx, sizeof(*dataspace) * 4);
02249 if (dataspace == NULL) {
02250 log_error("Unable to allocate memory for fwd update");
02251 result = ISC_R_NOMEMORY;
02252 goto cleanup;
02253 }
02254
02255 ISC_LIST_INIT(prereqlist);
02256 ISC_LIST_INIT(updatelist);
02257
02258 switch(ddns_cb->state) {
02259 case DDNS_STATE_ADD_FW_NXDOMAIN:
02260 result = ddns_modify_fwd_add1(ddns_cb, dataspace,
02261 pname, uname);
02262 if (result != ISC_R_SUCCESS) {
02263 goto cleanup;
02264 }
02265 ISC_LIST_APPEND(prereqlist, pname, link);
02266 break;
02267 case DDNS_STATE_ADD_FW_YXDHCID:
02268 result = ddns_modify_fwd_add2(ddns_cb, dataspace,
02269 pname, uname);
02270 if (result != ISC_R_SUCCESS) {
02271 goto cleanup;
02272 }
02273
02274
02275
02276
02277
02278 if ((ddns_cb->flags & DDNS_CONFLICT_OVERRIDE) == 0) {
02279 ISC_LIST_APPEND(prereqlist, pname, link);
02280 }
02281
02282 break;
02283 case DDNS_STATE_REM_FW_YXDHCID:
02284 result = ddns_modify_fwd_rem1(ddns_cb, dataspace,
02285 pname, uname);
02286 if (result != ISC_R_SUCCESS) {
02287 goto cleanup;
02288 }
02289 ISC_LIST_APPEND(prereqlist, pname, link);
02290 break;
02291 case DDNS_STATE_REM_FW_NXRR:
02292 result = ddns_modify_fwd_rem2(ddns_cb, dataspace,
02293 pname, uname);
02294 if (result != ISC_R_SUCCESS) {
02295 goto cleanup;
02296 }
02297 ISC_LIST_APPEND(prereqlist, pname, link);
02298 break;
02299
02300 default:
02301 log_error("Invalid operation in ddns code.");
02302 result = DHCP_R_INVALIDARG;
02303 goto cleanup;
02304 break;
02305 }
02306
02307
02308
02309
02310
02311 ISC_LIST_APPEND(updatelist, uname, link);
02312
02313
02314 result = ddns_update(dhcp_gbl_ctx.dnsclient,
02315 dns_rdataclass_in, zname,
02316 &prereqlist, &updatelist,
02317 zlist, tsec_key,
02318 DNS_CLIENTRESOPT_ALLOWRUN,
02319 dhcp_gbl_ctx.task,
02320 ddns_interlude,
02321 (void *)ddns_cb,
02322 &ddns_cb->transaction);
02323 if (result == ISC_R_FAMILYNOSUPPORT) {
02324 log_info("Unable to perform DDNS update, "
02325 "address family not supported");
02326 }
02327
02328 #if defined (DEBUG_DNS_UPDATES)
02329 print_dns_status(DDNS_PRINT_OUTBOUND, ddns_cb, result);
02330 #endif
02331
02332 cleanup:
02333 #if defined (DEBUG_DNS_UPDATES)
02334 if (result != ISC_R_SUCCESS) {
02335 log_info("DDNS: %s(%d): error in ddns_modify_fwd %s for %p",
02336 file, line, isc_result_totext(result), ddns_cb);
02337 }
02338 #endif
02339
02340 if (dataspace != NULL) {
02341 isc_mem_put(dhcp_gbl_ctx.mctx, dataspace,
02342 sizeof(*dataspace) * 4);
02343 }
02344 return(result);
02345 }
02346
02347
02348 isc_result_t
02349 ddns_modify_ptr(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
02350 {
02351 isc_result_t result;
02352 dns_tsec_t *tsec_key = NULL;
02353 unsigned char *ptrname;
02354 dhcp_ddns_data_t *dataspace = NULL;
02355 dns_namelist_t updatelist;
02356 dns_fixedname_t zname0, uname0;
02357 dns_name_t *zname = NULL, *uname;
02358 isc_sockaddrlist_t *zlist = NULL;
02359 unsigned char buf[256];
02360 int buflen;
02361
02362
02363
02364
02365
02366
02367
02368
02369 result = find_cached_zone(ddns_cb, FIND_REVERSE);
02370
02371 #if defined (DNS_ZONE_LOOKUP)
02372 if (result == ISC_R_NOTFOUND) {
02373
02374
02375
02376
02377 if (find_zone_start(ddns_cb, FIND_REVERSE) == ISC_R_SUCCESS) {
02378
02379
02380
02381
02382
02383
02384
02385
02386 goto cleanup;
02387 }
02388 }
02389 #endif
02390 if (result != ISC_R_SUCCESS)
02391 goto cleanup;
02392
02393
02394 if ((result == ISC_R_SUCCESS) &&
02395 !(ISC_LIST_EMPTY(ddns_cb->zone_server_list))) {
02396
02397 result = dhcp_isc_name(ddns_cb->zone_name, &zname0, &zname);
02398 if (result != ISC_R_SUCCESS) {
02399 log_error("Unable to build name for zone for "
02400 "fwd update: %s %s",
02401 ddns_cb->zone_name,
02402 isc_result_totext(result));
02403 goto cleanup;
02404 }
02405
02406 if (!(ISC_LIST_EMPTY(ddns_cb->zone_server_list))) {
02407 zlist = &ddns_cb->zone_server_list;
02408 }
02409
02410
02411
02412
02413
02414
02415
02416 if ((ddns_cb->zone != NULL) && (ddns_cb->zone->key != NULL)) {
02417 tsec_key = ddns_cb->zone->key->tsec_key;
02418 if (tsec_key == NULL) {
02419 log_error("No tsec for use with key %s",
02420 ddns_cb->zone->key->name);
02421 }
02422 }
02423 }
02424
02425
02426
02427 ptrname = (unsigned char *)ddns_cb->rev_name.data;
02428
02429 if ((result = dhcp_isc_name(ptrname, &uname0, &uname))
02430 != ISC_R_SUCCESS) {
02431 log_error("Unable to build name for fwd update: %s %s",
02432 ptrname, isc_result_totext(result));
02433 goto cleanup;
02434 }
02435
02436
02437
02438
02439
02440
02441 dataspace = isc_mem_get(dhcp_gbl_ctx.mctx, sizeof(*dataspace) * 2);
02442 if (dataspace == NULL) {
02443 log_error("Unable to allocate memory for fwd update");
02444 result = ISC_R_NOMEMORY;
02445 goto cleanup;
02446 }
02447
02448 ISC_LIST_INIT(updatelist);
02449
02450
02451
02452
02453
02454
02455 result = make_dns_dataset(dns_rdataclass_any, dns_rdatatype_ptr,
02456 &dataspace[0], NULL, 0, 0);
02457 if (result != ISC_R_SUCCESS) {
02458 goto cleanup;
02459 }
02460 ISC_LIST_APPEND(uname->list, &dataspace[0].rdataset, link);
02461
02462
02463
02464
02465
02466 if (ddns_cb->state == DDNS_STATE_ADD_PTR) {
02467 #if 0
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480 if (ddns_cb->fwd_name.len == 1) {
02481
02482 buf[0] = 0;
02483 buflen = 1;
02484 } else {
02485 unsigned char *cp;
02486 buf[0] = '.';
02487 memcpy(&buf[1], ddns_cb->fwd_name.data,
02488 ddns_cb->fwd_name.len);
02489 for(cp = buf + ddns_cb->fwd_name.len, buflen = 0;
02490 cp != buf;
02491 cp--) {
02492 if (*cp == '.') {
02493 *cp = buflen;
02494 buflen = 0;
02495 } else {
02496 buflen++;
02497 }
02498 }
02499 *cp = buflen;
02500 buflen = ddns_cb->fwd_name.len + 1;
02501 }
02502 #endif
02503
02504
02505
02506 if (MRns_name_pton((char *)ddns_cb->fwd_name.data,
02507 buf, 256) == -1) {
02508 goto cleanup;
02509 }
02510 buflen = 0;
02511 while (buf[buflen] != 0) {
02512 buflen += buf[buflen] + 1;
02513 }
02514 buflen++;
02515
02516 result = make_dns_dataset(dns_rdataclass_in,
02517 dns_rdatatype_ptr,
02518 &dataspace[1],
02519 buf, buflen, ddns_cb->ttl);
02520 if (result != ISC_R_SUCCESS) {
02521 goto cleanup;
02522 }
02523 ISC_LIST_APPEND(uname->list, &dataspace[1].rdataset, link);
02524 }
02525
02526 ISC_LIST_APPEND(updatelist, uname, link);
02527
02528
02529
02530
02531
02532
02533
02534
02535 result = ddns_update((dns_client_t *)dhcp_gbl_ctx.dnsclient,
02536 dns_rdataclass_in, zname,
02537 NULL, &updatelist,
02538 zlist, tsec_key,
02539 DNS_CLIENTRESOPT_ALLOWRUN,
02540 dhcp_gbl_ctx.task,
02541 ddns_interlude, (void *)ddns_cb,
02542 &ddns_cb->transaction);
02543 if (result == ISC_R_FAMILYNOSUPPORT) {
02544 log_info("Unable to perform DDNS update, "
02545 "address family not supported");
02546 }
02547
02548 #if defined (DEBUG_DNS_UPDATES)
02549 print_dns_status(DDNS_PRINT_OUTBOUND, ddns_cb, result);
02550 #endif
02551
02552 cleanup:
02553 #if defined (DEBUG_DNS_UPDATES)
02554 if (result != ISC_R_SUCCESS) {
02555 log_info("DDNS: %s(%d): error in ddns_modify_ptr %s for %p",
02556 file, line, isc_result_totext(result), ddns_cb);
02557 }
02558 #endif
02559
02560 if (dataspace != NULL) {
02561 isc_mem_put(dhcp_gbl_ctx.mctx, dataspace,
02562 sizeof(*dataspace) * 2);
02563 }
02564 return(result);
02565 }
02566
02567 void
02568 ddns_cancel(dhcp_ddns_cb_t *ddns_cb, const char *file, int line) {
02569 ddns_cb->flags |= DDNS_ABORT;
02570 if (ddns_cb->transaction != NULL) {
02571 dns_client_cancelupdate((dns_clientupdatetrans_t *)
02572 ddns_cb->transaction);
02573 }
02574 ddns_cb->lease = NULL;
02575
02576 #if defined (DEBUG_DNS_UPDATES)
02577 log_info("DDNS: %s(%d): cancelling transaction for %p",
02578 file, line, ddns_cb);
02579 #endif
02580 }
02581
02582 #endif
02583
02584 HASH_FUNCTIONS (dns_zone, const char *, struct dns_zone, dns_zone_hash_t,
02585 dns_zone_reference, dns_zone_dereference, do_case_hash)