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
00030
00031
00032
00033
00034
00035
00036
00037 #include "dhcpd.h"
00038 #include <dns/result.h>
00039
00040 char *ddns_standard_tag = "ddns-dhcid";
00041 char *ddns_interim_tag = "ddns-txt";
00042
00043 #ifdef NSUPDATE
00044
00045 static void ddns_fwd_srv_connector(struct lease *lease,
00046 struct iasubopt *lease6,
00047 struct binding_scope **inscope,
00048 dhcp_ddns_cb_t *ddns_cb,
00049 isc_result_t eresult);
00050
00051
00052
00053
00054
00055 static void data_string_append (struct data_string *ds1,
00056 struct data_string *ds2)
00057 {
00058 memcpy (ds1 -> buffer -> data + ds1 -> len,
00059 ds2 -> data,
00060 ds2 -> len);
00061 ds1 -> len += ds2 -> len;
00062 }
00063
00064
00065
00066
00067
00068 int
00069 ddns_updates(struct packet *packet, struct lease *lease, struct lease *old,
00070 struct iasubopt *lease6, struct iasubopt *old6,
00071 struct option_state *options)
00072 {
00073 unsigned long ddns_ttl = DEFAULT_DDNS_TTL;
00074 struct data_string ddns_hostname;
00075 struct data_string ddns_domainname;
00076 struct data_string old_ddns_fwd_name;
00077 struct data_string ddns_fwd_name;
00078 struct data_string ddns_dhcid;
00079 struct binding_scope **scope = NULL;
00080 struct data_string d1;
00081 struct option_cache *oc;
00082 int s1, s2;
00083 int result = 0;
00084 int server_updates_a = 1;
00085 struct buffer *bp = (struct buffer *)0;
00086 int ignorep = 0, client_ignorep = 0;
00087 int rev_name_len;
00088 int i;
00089
00090 dhcp_ddns_cb_t *ddns_cb;
00091 int do_remove = 0;
00092
00093 if ((ddns_update_style != DDNS_UPDATE_STYLE_STANDARD) &&
00094 (ddns_update_style != DDNS_UPDATE_STYLE_INTERIM))
00095 return (0);
00096
00097
00098
00099
00100
00101
00102
00103
00104 if (lease != NULL) {
00105 if ((old != NULL) && (old->ddns_cb != NULL)) {
00106 ddns_cancel(old->ddns_cb, MDL);
00107 old->ddns_cb = NULL;
00108 }
00109 } else if (lease6 != NULL) {
00110 if ((old6 != NULL) && (old6->ddns_cb != NULL)) {
00111 ddns_cancel(old6->ddns_cb, MDL);
00112 old6->ddns_cb = NULL;
00113 }
00114 } else {
00115 log_fatal("Impossible condition at %s:%d.", MDL);
00116
00117 result = 0;
00118 return(0);
00119 }
00120
00121
00122 ddns_cb = ddns_cb_alloc(MDL);
00123 if (ddns_cb == NULL) {
00124 return(0);
00125 }
00126
00127
00128
00129
00130 ddns_cb->flags = DDNS_UPDATE_ADDR | DDNS_UPDATE_PTR |
00131 DDNS_ACTIVE_LEASE;
00132
00133
00134
00135
00136
00137
00138 if (lease != NULL) {
00139 scope = &(lease->scope);
00140 ddns_cb->address = lease->ip_addr;
00141 if (lease->flags & STATIC_LEASE)
00142 ddns_cb->flags |= DDNS_STATIC_LEASE;
00143 } else if (lease6 != NULL) {
00144 scope = &(lease6->scope);
00145 memcpy(ddns_cb->address.iabuf, lease6->addr.s6_addr, 16);
00146 ddns_cb->address.len = 16;
00147 }
00148
00149 memset (&d1, 0, sizeof(d1));
00150 memset (&ddns_hostname, 0, sizeof (ddns_hostname));
00151 memset (&ddns_domainname, 0, sizeof (ddns_domainname));
00152 memset (&old_ddns_fwd_name, 0, sizeof (ddns_fwd_name));
00153 memset (&ddns_fwd_name, 0, sizeof (ddns_fwd_name));
00154 memset (&ddns_dhcid, 0, sizeof (ddns_dhcid));
00155
00156
00157
00158 if (!(oc = lookup_option(&server_universe, options,
00159 SV_CLIENT_UPDATES)) ||
00160 evaluate_boolean_option_cache(&client_ignorep, packet, lease, NULL,
00161 packet->options, options, scope,
00162 oc, MDL)) {
00163
00164
00165
00166 if (!(oc = lookup_option (&fqdn_universe, packet -> options,
00167 FQDN_SERVER_UPDATE)) ||
00168 evaluate_boolean_option_cache(&ignorep, packet, lease,
00169 NULL, packet->options,
00170 options, scope, oc, MDL))
00171 goto noclient;
00172
00173
00174 if (!(oc = lookup_option (&fqdn_universe, packet -> options,
00175 FQDN_DOMAINNAME)))
00176 goto noclient;
00177 if (!(oc = lookup_option (&fqdn_universe, packet -> options,
00178 FQDN_FQDN)) ||
00179 !evaluate_option_cache(&ddns_fwd_name, packet, lease,
00180 NULL, packet->options,
00181 options, scope, oc, MDL))
00182 goto noclient;
00183 ddns_cb->flags &= ~DDNS_UPDATE_ADDR;
00184 server_updates_a = 0;
00185 goto client_updates;
00186 }
00187 noclient:
00188
00189
00190
00191 if ((oc = lookup_option (&server_universe, options,
00192 SV_DO_FORWARD_UPDATES)) &&
00193 !evaluate_boolean_option_cache(&ignorep, packet, lease,
00194 NULL, packet->options,
00195 options, scope, oc, MDL)) {
00196 goto out;
00197 }
00198
00199
00200
00201
00202
00203 if ((lease != NULL) && (lease->flags & STATIC_LEASE)) {
00204 if (!(oc = lookup_option(&server_universe, options,
00205 SV_UPDATE_STATIC_LEASES)) ||
00206 !evaluate_boolean_option_cache(&ignorep, packet, lease,
00207 NULL, packet->options,
00208 options, scope, oc, MDL))
00209 goto out;
00210 }
00211
00212
00213
00214
00215 oc = lookup_option(&server_universe, options, SV_DDNS_HOST_NAME);
00216 if (oc)
00217 s1 = evaluate_option_cache(&ddns_hostname, packet, lease,
00218 NULL, packet->options,
00219 options, scope, oc, MDL);
00220 else
00221 s1 = 0;
00222
00223 oc = lookup_option(&server_universe, options, SV_DDNS_DOMAIN_NAME);
00224 if (oc)
00225 s2 = evaluate_option_cache(&ddns_domainname, packet, lease,
00226 NULL, packet->options,
00227 options, scope, oc, MDL);
00228 else
00229 s2 = 0;
00230
00231 if (s1 && s2) {
00232 if (ddns_hostname.len + ddns_domainname.len > 253) {
00233 log_error ("ddns_update: host.domain name too long");
00234
00235 goto out;
00236 }
00237
00238 buffer_allocate (&ddns_fwd_name.buffer,
00239 ddns_hostname.len + ddns_domainname.len + 2,
00240 MDL);
00241 if (ddns_fwd_name.buffer) {
00242 ddns_fwd_name.data = ddns_fwd_name.buffer->data;
00243 data_string_append (&ddns_fwd_name, &ddns_hostname);
00244 ddns_fwd_name.buffer->data[ddns_fwd_name.len] = '.';
00245 ddns_fwd_name.len++;
00246 data_string_append (&ddns_fwd_name, &ddns_domainname);
00247 ddns_fwd_name.buffer->data[ddns_fwd_name.len] ='\0';
00248 ddns_fwd_name.terminated = 1;
00249 }
00250 }
00251 client_updates:
00252
00253
00254 if (find_bound_string(&old_ddns_fwd_name, *scope, "ddns-fwd-name")) {
00255
00256 if (old_ddns_fwd_name.len != ddns_fwd_name.len ||
00257 memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data,
00258 old_ddns_fwd_name.len)) {
00259
00260
00261
00262
00263 do_remove = 1;
00264 goto in;
00265 }
00266
00267 #if defined (DDNS_UPDATE_SLOW_TRANSITION)
00268
00269
00270
00271
00272
00273
00274 if (((ddns_update_style == DDNS_UPDATE_STYLE_STANDARD) &&
00275 find_bound_string(&ddns_dhcid, *scope, ddns_interim_tag)) ||
00276 ((ddns_update_style == DDNS_UPDATE_STYLE_INTERIM) &&
00277 find_bound_string(&ddns_dhcid, *scope, ddns_standard_tag))) {
00278 data_string_forget(&ddns_dhcid, MDL);
00279 do_remove = 1;
00280 goto in;
00281 }
00282 #endif
00283
00284
00285
00286
00287 if (!(oc = lookup_option(&server_universe, options,
00288 SV_UPDATE_OPTIMIZATION)) ||
00289 evaluate_boolean_option_cache(&ignorep, packet, lease,
00290 NULL, packet->options,
00291 options, scope, oc, MDL)) {
00292 result = 1;
00293 goto noerror;
00294 }
00295
00296
00297
00298
00299 } else if (find_bound_string(&old_ddns_fwd_name, *scope,
00300 "ddns-client-fqdn")) {
00301
00302
00303 if (old_ddns_fwd_name.len == ddns_fwd_name.len &&
00304 !memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data,
00305 old_ddns_fwd_name.len) &&
00306 (!(oc = lookup_option(&server_universe, options,
00307 SV_UPDATE_OPTIMIZATION)) ||
00308 evaluate_boolean_option_cache(&ignorep, packet, lease,
00309 NULL, packet->options,
00310 options, scope, oc, MDL))) {
00311 goto noerror;
00312 }
00313 }
00314 in:
00315
00316
00317
00318
00319 if ((!ddns_fwd_name.len) || (ddns_fwd_name.len > 255)) {
00320 if (ddns_fwd_name.len > 255) {
00321 log_error ("client provided fqdn: too long");
00322 }
00323
00324
00325 if (do_remove != 0) {
00326 (void) ddns_removals(lease, lease6, NULL, ISC_TRUE);
00327 }
00328 goto out;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 ddns_ttl = DEFAULT_DDNS_TTL;
00348 if (lease != NULL) {
00349 if (lease->ends <= cur_time) {
00350 ddns_ttl = 0;
00351 } else {
00352 ddns_ttl = (lease->ends - cur_time)/2;
00353 }
00354 }
00355 #ifndef USE_OLD_DDNS_TTL
00356 else if (lease6 != NULL) {
00357 ddns_ttl = lease6->prefer/2;
00358 }
00359
00360 if (ddns_ttl > MAX_DEFAULT_DDNS_TTL) {
00361 ddns_ttl = MAX_DEFAULT_DDNS_TTL;
00362 }
00363 #endif
00364
00365 if ((oc = lookup_option(&server_universe, options, SV_DDNS_TTL))) {
00366 if (evaluate_option_cache(&d1, packet, lease, NULL,
00367 packet->options, options,
00368 scope, oc, MDL)) {
00369 if (d1.len == sizeof (u_int32_t))
00370 ddns_ttl = getULong (d1.data);
00371 data_string_forget (&d1, MDL);
00372 }
00373 }
00374
00375 ddns_cb->ttl = ddns_ttl;
00376
00377
00378
00379
00380 oc = lookup_option(&server_universe, options, SV_DDNS_REV_DOMAIN_NAME);
00381 if (oc)
00382 s1 = evaluate_option_cache(&d1, packet, lease, NULL,
00383 packet->options, options,
00384 scope, oc, MDL);
00385 else
00386 s1 = 0;
00387
00388
00389
00390
00391
00392 if (ddns_cb->address.len == 4) {
00393 char buf[17];
00394
00395 rev_name_len = snprintf(buf, sizeof(buf), "%u.%u.%u.%u.",
00396 ddns_cb->address.iabuf[3] & 0xff,
00397 ddns_cb->address.iabuf[2] & 0xff,
00398 ddns_cb->address.iabuf[1] & 0xff,
00399 ddns_cb->address.iabuf[0] & 0xff) + 1;
00400
00401 if (s1) {
00402 rev_name_len += d1.len;
00403
00404 if (rev_name_len > 255) {
00405 log_error("ddns_update: Calculated rev domain "
00406 "name too long.");
00407 s1 = 0;
00408 data_string_forget(&d1, MDL);
00409 }
00410 }
00411 } else if (ddns_cb->address.len == 16) {
00412
00413
00414
00415
00416 rev_name_len = sizeof("0.1.2.3.4.5.6.7."
00417 "8.9.a.b.c.d.e.f."
00418 "0.1.2.3.4.5.6.7."
00419 "8.9.a.b.c.d.e.f."
00420 "ip6.arpa.");
00421
00422
00423 s1 = 1;
00424 } else {
00425 log_fatal("invalid address length %d", ddns_cb->address.len);
00426
00427 return 0;
00428 }
00429
00430
00431 if ((oc = lookup_option(&server_universe, options,
00432 SV_DO_REVERSE_UPDATES)) &&
00433 !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL,
00434 packet->options, options,
00435 scope, oc, MDL)) {
00436 ddns_cb->flags &= ~DDNS_UPDATE_PTR;
00437 }
00438
00439 if (s1) {
00440 buffer_allocate(&ddns_cb->rev_name.buffer, rev_name_len, MDL);
00441 if (ddns_cb->rev_name.buffer != NULL) {
00442 struct data_string *rname = &ddns_cb->rev_name;
00443 rname->data = rname->buffer->data;
00444
00445 if (ddns_cb->address.len == 4) {
00446 rname->len =
00447 sprintf((char *)rname->buffer->data,
00448 "%u.%u.%u.%u.",
00449 ddns_cb->address.iabuf[3] & 0xff,
00450 ddns_cb->address.iabuf[2] & 0xff,
00451 ddns_cb->address.iabuf[1] & 0xff,
00452 ddns_cb->address.iabuf[0] & 0xff);
00453
00454
00455
00456
00457
00458 data_string_append(rname, &d1);
00459 rname->buffer->data[rname->len] = '\0';
00460 } else if (ddns_cb->address.len == 16) {
00461 char *p = (char *)&rname->buffer->data;
00462 unsigned char *a = ddns_cb->address.iabuf + 15;
00463 for (i=0; i<16; i++) {
00464 sprintf(p, "%x.%x.",
00465 (*a & 0xF), ((*a >> 4) & 0xF));
00466 p += 4;
00467 a -= 1;
00468 }
00469 strcat(p, "ip6.arpa.");
00470 rname->len = strlen((const char *)rname->data);
00471 }
00472
00473 rname->terminated = 1;
00474 }
00475
00476 if (d1.data != NULL)
00477 data_string_forget(&d1, MDL);
00478 }
00479
00480
00481
00482
00483
00484 data_string_copy(&ddns_cb->fwd_name, &ddns_fwd_name, MDL);
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495 if ((ddns_cb->flags & DDNS_UPDATE_ADDR) != 0) {
00496 int ddns_type;
00497 int ddns_len;
00498 if (ddns_update_style == DDNS_UPDATE_STYLE_STANDARD) {
00499
00500 ddns_cb->lease_tag = ddns_standard_tag;
00501 ddns_cb->dhcid_class = dns_rdatatype_dhcid;
00502 ddns_type = 1;
00503 ddns_len = 4;
00504 } else {
00505
00506 ddns_cb->lease_tag = ddns_interim_tag;
00507 ddns_cb->dhcid_class = dns_rdatatype_txt;
00508
00509 ddns_type = DHO_DHCP_CLIENT_IDENTIFIER;
00510
00511 ddns_len = 0;
00512 }
00513
00514
00515 if (lease6 != NULL) {
00516 if (lease6->ia->iaid_duid.len < ddns_len)
00517 goto badfqdn;
00518 result = get_dhcid(ddns_cb, 2,
00519 lease6->ia->iaid_duid.data + ddns_len,
00520 lease6->ia->iaid_duid.len - ddns_len);
00521 } else if ((lease != NULL) &&
00522 (lease->uid != NULL) &&
00523 (lease->uid_len != 0)) {
00524
00525
00526
00527 if ((ddns_update_style == DDNS_UPDATE_STYLE_STANDARD) &&
00528 (lease->uid[0] == 255)) {
00529 if (lease->uid_len < 5)
00530 goto badfqdn;
00531 result = get_dhcid(ddns_cb, 2,
00532 lease->uid + 5,
00533 lease->uid_len - 5);
00534 } else {
00535 result = get_dhcid(ddns_cb, ddns_type,
00536 lease->uid,
00537 lease->uid_len);
00538 }
00539 } else if (lease != NULL)
00540 result = get_dhcid(ddns_cb, 0,
00541 lease->hardware_addr.hbuf,
00542 lease->hardware_addr.hlen);
00543 else
00544 log_fatal("Impossible condition at %s:%d.", MDL);
00545
00546 if (!result)
00547 goto badfqdn;
00548 }
00549
00550
00551
00552
00553
00554 if (ddns_cb->flags & DDNS_UPDATE_ADDR) {
00555 oc = lookup_option(&server_universe, options,
00556 SV_DDNS_CONFLICT_DETECT);
00557 if (oc &&
00558 !evaluate_boolean_option_cache(&ignorep, packet, lease,
00559 NULL, packet->options,
00560 options, scope, oc, MDL))
00561 ddns_cb->flags |= DDNS_CONFLICT_OVERRIDE;
00562
00563 }
00564
00565
00566
00567
00568
00569
00570
00571 if (do_remove) {
00572
00573
00574
00575
00576 (void) ddns_removals(lease, lease6, ddns_cb, ISC_TRUE);
00577 }
00578 else {
00579 ddns_fwd_srv_connector(lease, lease6, scope, ddns_cb,
00580 ISC_R_SUCCESS);
00581 }
00582 ddns_cb = NULL;
00583
00584 noerror:
00585
00586
00587
00588
00589
00590
00591 if ((oc = lookup_option (&server_universe, options, SV_FQDN_REPLY)) &&
00592 !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL,
00593 packet->options, options,
00594 scope, oc, MDL)) {
00595 goto badfqdn;
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605 } else if (client_ignorep &&
00606 (oc = lookup_option(&fqdn_universe, packet->options,
00607 FQDN_SERVER_UPDATE)) &&
00608 !evaluate_boolean_option_cache(&ignorep, packet, lease, NULL,
00609 packet->options, options,
00610 scope, oc, MDL)) {
00611 oc = lookup_option(&fqdn_universe, packet->options, FQDN_FQDN);
00612 if (oc && evaluate_option_cache(&d1, packet, lease, NULL,
00613 packet->options, options,
00614 scope, oc, MDL)) {
00615 if (d1.len == 0 ||
00616 !buffer_allocate(&bp, d1.len + 5, MDL))
00617 goto badfqdn;
00618
00619
00620 bp->data[0] = 0;
00621 if (!save_option_buffer(&fqdn_universe, options,
00622 bp, &bp->data[0], 1,
00623 FQDN_SERVER_UPDATE, 0))
00624 goto badfqdn;
00625
00626
00627 bp->data[1] = 0;
00628 if (!save_option_buffer(&fqdn_universe, options,
00629 bp, &bp->data[1], 1,
00630 FQDN_NO_CLIENT_UPDATE, 0))
00631 goto badfqdn;
00632
00633
00634 oc = lookup_option(&fqdn_universe, packet->options,
00635 FQDN_ENCODED);
00636 if (oc &&
00637 evaluate_boolean_option_cache(&ignorep, packet,
00638 lease, NULL,
00639 packet->options,
00640 options, scope,
00641 oc, MDL))
00642 bp->data[2] = 1;
00643 else
00644 bp->data[2] = 0;
00645
00646 if (!save_option_buffer(&fqdn_universe, options,
00647 bp, &bp->data[2], 1,
00648 FQDN_ENCODED, 0))
00649 goto badfqdn;
00650
00651
00652 bp->data[3] = 255;
00653 if (!save_option_buffer(&fqdn_universe, options,
00654 bp, &bp->data[3], 1,
00655 FQDN_RCODE1, 0))
00656 goto badfqdn;
00657
00658 bp->data[4] = 255;
00659 if (!save_option_buffer(&fqdn_universe, options,
00660 bp, &bp->data[4], 1,
00661 FQDN_RCODE2, 0))
00662 goto badfqdn;
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672 memcpy(&bp->data[5], d1.data, d1.len);
00673 if (!save_option_buffer(&fqdn_universe, options,
00674 bp, &bp->data[5], d1.len,
00675 FQDN_FQDN, 0))
00676 goto badfqdn;
00677
00678 data_string_forget(&d1, MDL);
00679 }
00680
00681
00682
00683
00684
00685
00686 } else if ((oc = lookup_option(&fqdn_universe, packet->options,
00687 FQDN_ENCODED)) &&
00688 buffer_allocate(&bp, ddns_fwd_name.len + 5, MDL)) {
00689 bp -> data [0] = server_updates_a;
00690 if (!save_option_buffer(&fqdn_universe, options,
00691 bp, &bp->data [0], 1,
00692 FQDN_SERVER_UPDATE, 0))
00693 goto badfqdn;
00694 bp -> data [1] = server_updates_a;
00695 if (!save_option_buffer(&fqdn_universe, options,
00696 bp, &bp->data [1], 1,
00697 FQDN_NO_CLIENT_UPDATE, 0))
00698 goto badfqdn;
00699
00700
00701 if (evaluate_boolean_option_cache(&ignorep, packet, lease,
00702 NULL, packet->options,
00703 options, scope, oc, MDL))
00704 bp -> data [2] = 1;
00705 else
00706 bp -> data [2] = 0;
00707 if (!save_option_buffer(&fqdn_universe, options,
00708 bp, &bp->data [2], 1,
00709 FQDN_ENCODED, 0))
00710 goto badfqdn;
00711 bp -> data [3] = 255;
00712 if (!save_option_buffer(&fqdn_universe, options,
00713 bp, &bp->data [3], 1,
00714 FQDN_RCODE1, 0))
00715 goto badfqdn;
00716 bp -> data [4] = 255;
00717 if (!save_option_buffer(&fqdn_universe, options,
00718 bp, &bp->data [4], 1,
00719 FQDN_RCODE2, 0))
00720 goto badfqdn;
00721 if (ddns_fwd_name.len) {
00722 memcpy (&bp -> data [5],
00723 ddns_fwd_name.data, ddns_fwd_name.len);
00724 if (!save_option_buffer(&fqdn_universe, options,
00725 bp, &bp->data [5],
00726 ddns_fwd_name.len,
00727 FQDN_FQDN, 0))
00728 goto badfqdn;
00729 }
00730 }
00731
00732 badfqdn:
00733 out:
00734
00735
00736
00737 if (ddns_cb != NULL) {
00738 ddns_cb_free(ddns_cb, MDL);
00739 }
00740
00741 data_string_forget(&d1, MDL);
00742 data_string_forget(&ddns_hostname, MDL);
00743 data_string_forget(&ddns_domainname, MDL);
00744 data_string_forget(&old_ddns_fwd_name, MDL);
00745 data_string_forget(&ddns_fwd_name, MDL);
00746 if (bp)
00747 buffer_dereference(&bp, MDL);
00748
00749 return result;
00750 }
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777 isc_result_t
00778 ddns_update_lease_text(dhcp_ddns_cb_t *ddns_cb,
00779 struct binding_scope **inscope)
00780 {
00781 struct binding_scope **scope = NULL;
00782 struct lease *lease = NULL;
00783 struct iasubopt *lease6 = NULL;
00784 struct ipv6_pool *pool = NULL;
00785 struct in6_addr addr;
00786 struct data_string lease_dhcid;
00787
00788
00789
00790
00791
00792 if (ddns_cb->flags & DDNS_STATIC_LEASE)
00793 return (ISC_R_SUCCESS);
00794
00795
00796
00797
00798
00799
00800 if ((ddns_cb->flags & DDNS_ACTIVE_LEASE) == 0)
00801 return (ISC_R_SUCCESS);
00802
00803 if (inscope != NULL) {
00804 scope = inscope;
00805 } else if (ddns_cb->address.len == 4) {
00806 if (find_lease_by_ip_addr(&lease, ddns_cb->address, MDL) != 0){
00807 scope = &(lease->scope);
00808 }
00809 } else if (ddns_cb->address.len == 16) {
00810 memcpy(&addr, &ddns_cb->address.iabuf, 16);
00811 if ((find_ipv6_pool(&pool, D6O_IA_TA, &addr) ==
00812 ISC_R_SUCCESS) ||
00813 (find_ipv6_pool(&pool, D6O_IA_NA, &addr) ==
00814 ISC_R_SUCCESS)) {
00815 if (iasubopt_hash_lookup(&lease6, pool->leases,
00816 &addr, 16, MDL)) {
00817 scope = &(lease6->scope);
00818 }
00819 ipv6_pool_dereference(&pool, MDL);
00820 }
00821 } else {
00822 log_fatal("Impossible condition at %s:%d.", MDL);
00823 }
00824
00825 if (scope == NULL) {
00826
00827 if (lease) {
00828 lease_dereference(&lease, MDL);
00829 }
00830 else if (lease6) {
00831 iasubopt_dereference(&lease6, MDL);
00832 }
00833
00834 return(ISC_R_FAILURE);
00835 }
00836
00837
00838 switch(ddns_cb->state) {
00839 case DDNS_STATE_REM_PTR:
00840 unset(*scope, "ddns-rev-name");
00841 if ((ddns_cb->flags & DDNS_CLIENT_DID_UPDATE) != 0) {
00842 unset(*scope, "ddns-client-fqdn");
00843 }
00844 break;
00845
00846 case DDNS_STATE_ADD_PTR:
00847 case DDNS_STATE_CLEANUP:
00848 bind_ds_value(scope, "ddns-rev-name", &ddns_cb->rev_name);
00849 if ((ddns_cb->flags & DDNS_UPDATE_ADDR) == 0) {
00850 bind_ds_value(scope, "ddns-client-fqdn",
00851 &ddns_cb->fwd_name);
00852 }
00853 break;
00854
00855 case DDNS_STATE_ADD_FW_YXDHCID:
00856 case DDNS_STATE_ADD_FW_NXDOMAIN:
00857 bind_ds_value(scope, "ddns-fwd-name", &ddns_cb->fwd_name);
00858
00859 if (ddns_cb->lease_tag == ddns_standard_tag) {
00860 bind_ds_value(scope, ddns_standard_tag, &ddns_cb->dhcid);
00861 } else {
00862
00863 memset(&lease_dhcid, 0, sizeof(lease_dhcid));
00864 dhcid_tolease(&ddns_cb->dhcid, &lease_dhcid);
00865 bind_ds_value(scope, ddns_interim_tag, &lease_dhcid);
00866 data_string_forget(&lease_dhcid, MDL);
00867 }
00868 break;
00869
00870 case DDNS_STATE_REM_FW_NXRR:
00871 case DDNS_STATE_REM_FW_YXDHCID:
00872 unset(*scope, "ddns-fwd-name");
00873 unset(*scope, ddns_cb->lease_tag);
00874 break;
00875 }
00876
00877
00878 if (lease) {
00879 write_lease(lease);
00880 lease_dereference(&lease, MDL);
00881 } else if (lease6) {
00882 write_ia(lease6->ia);
00883 iasubopt_dereference(&lease6, MDL);
00884 }
00885
00886 return(ISC_R_SUCCESS);
00887 }
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906 void
00907 update_lease_failed(struct lease *lease,
00908 struct iasubopt *lease6,
00909 dhcp_ddns_cb_t *ddns_cb,
00910 dhcp_ddns_cb_t *ddns_cb_set,
00911 const char * file, int line)
00912 {
00913 char lease_address[MAX_ADDRESS_STRING_LEN + 64];
00914 char reason[128];
00915
00916 sprintf(reason, "unknown");
00917 sprintf(lease_address, "unknown");
00918
00919
00920
00921
00922
00923
00924 if (ddns_cb != NULL) {
00925 strncpy(lease_address, piaddr(ddns_cb->address),
00926 MAX_ADDRESS_STRING_LEN);
00927
00928 if (ddns_cb->address.len == 4) {
00929 sprintf(reason, "duplicate IPv4 fixed-address entry");
00930 } else if (ddns_cb->address.len == 16) {
00931 sprintf(reason, "duplicate IPv6 fixed-address6 entry "
00932 "or overlapping pools");
00933 } else {
00934
00935
00936
00937
00938 sprintf(reason, "corrupted ddns_cb structure (address "
00939 "length is %d)", ddns_cb->address.len);
00940 }
00941 }
00942
00943 log_error("Failed to properly update internal lease structure with "
00944 "DDNS");
00945 log_error("control block structures. Tried to update lease for"
00946 "%s address, ddns_cb=%p.", lease_address, ddns_cb);
00947
00948 log_error("%s", "");
00949 log_error("This condition can occur, if DHCP server configuration is "
00950 "inconsistent.");
00951 log_error("In particular, please do check that your configuration:");
00952 log_error("a) does not have overlapping pools (especially containing");
00953 log_error(" %s address).", lease_address);
00954 log_error("b) there are no duplicate fixed-address or fixed-address6");
00955 log_error("entries for the %s address.", lease_address);
00956 log_error("%s", "");
00957 log_error("Possible reason for this failure: %s", reason);
00958
00959 log_fatal("%s(%d): Failed to update lease database with DDNS info for "
00960 "address %s. Lease database inconsistent. Unable to recover."
00961 " Terminating.", file, line, lease_address);
00962 }
00963
00964
00965
00966
00967
00968
00969
00970
00971 void
00972 safe_lease_update(struct lease *lease,
00973 dhcp_ddns_cb_t *oldcb,
00974 dhcp_ddns_cb_t *newcb,
00975 const char *file, int line)
00976 {
00977 if (lease == NULL) {
00978
00979 log_fatal("Impossible condition at %s:%d (called from %s:%d).",
00980 MDL, file, line);
00981 }
00982
00983 if ( (lease->ddns_cb == NULL) && (newcb == NULL) ) {
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995 log_error("%s(%d): Invalid lease update. Tried to "
00996 "clear already NULL DDNS control block "
00997 "pointer for lease %s.",
00998 file, line, piaddr(lease->ip_addr) );
00999
01000 #if defined (DNS_UPDATES_MEMORY_CHECKS)
01001 update_lease_failed(lease, NULL, oldcb, newcb, file, line);
01002 #endif
01003
01004
01005
01006
01007 return;
01008 }
01009
01010 if ( (lease->ddns_cb != NULL) && (lease->ddns_cb != oldcb) ) {
01011
01012
01013
01014
01015
01016 log_error("%s(%d): Failed to update internal lease "
01017 "structure with DDNS control block. Existing"
01018 " ddns_cb structure does not match "
01019 "expectations.IPv4=%s, old ddns_cb=%p, tried"
01020 "to update to new ddns_cb=%p", file, line,
01021 piaddr(lease->ip_addr), oldcb, newcb);
01022
01023 #if defined (DNS_UPDATES_MEMORY_CHECKS)
01024 update_lease_failed(lease, NULL, oldcb, newcb, file, line);
01025 #endif
01026
01027
01028
01029
01030 return;
01031 }
01032
01033
01034
01035
01036 lease->ddns_cb = newcb;
01037 }
01038
01039 void
01040 safe_lease6_update(struct iasubopt *lease6,
01041 dhcp_ddns_cb_t *oldcb,
01042 dhcp_ddns_cb_t *newcb,
01043 const char *file, int line)
01044 {
01045 char addrbuf[MAX_ADDRESS_STRING_LEN];
01046
01047 if (lease6 == NULL) {
01048
01049 log_fatal("Impossible condition at %s:%d (called from %s:%d).",
01050 MDL, file, line);
01051 }
01052
01053 if ( (lease6->ddns_cb == NULL) && (newcb == NULL) ) {
01054 inet_ntop(AF_INET6, &lease6->addr, addrbuf,
01055 MAX_ADDRESS_STRING_LEN);
01056
01057
01058
01059
01060 log_error("%s(%d): Failed to update internal lease "
01061 "structure. Tried to clear already NULL "
01062 "DDNS control block pointer for lease %s.",
01063 file, line, addrbuf);
01064
01065 #if defined (DNS_UPDATES_MEMORY_CHECKS)
01066 update_lease_failed(NULL, lease6, oldcb, newcb, file, line);
01067 #endif
01068
01069
01070
01071
01072
01073 return;
01074 }
01075
01076 if ( (lease6->ddns_cb != NULL) && (lease6->ddns_cb != oldcb) ) {
01077
01078
01079
01080
01081
01082 inet_ntop(AF_INET6, &lease6->addr, addrbuf,
01083 MAX_ADDRESS_STRING_LEN);
01084
01085 log_error("%s(%d): Failed to update internal lease "
01086 "structure with DDNS control block. Existing"
01087 " ddns_cb structure does not match "
01088 "expectations.IPv6=%s, old ddns_cb=%p, tried"
01089 "to update to new ddns_cb=%p", file, line,
01090 addrbuf, oldcb, newcb);
01091
01092 #if defined (DNS_UPDATES_MEMORY_CHECKS)
01093 update_lease_failed(NULL, lease6, oldcb, newcb, file, line);
01094 #endif
01095
01096
01097
01098
01099 return;
01100 }
01101
01102
01103
01104 lease6->ddns_cb = newcb;
01105 }
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122 isc_result_t
01123 ddns_update_lease_ptr(struct lease *lease,
01124 struct iasubopt *lease6,
01125 dhcp_ddns_cb_t *ddns_cb,
01126 dhcp_ddns_cb_t *ddns_cb_set,
01127 const char * file, int line)
01128 {
01129 char ddns_address[MAX_ADDRESS_STRING_LEN];
01130 sprintf(ddns_address, "unknown");
01131 if (ddns_cb == NULL) {
01132 log_info("%s(%d): No control block for lease update",
01133 file, line);
01134 return (ISC_R_FAILURE);
01135 }
01136 else {
01137 strncpy(ddns_address, piaddr(ddns_cb->address),
01138 MAX_ADDRESS_STRING_LEN);
01139 }
01140 #if defined (DEBUG_DNS_UPDATES)
01141 log_info("%s(%d): Updating lease_ptr for ddns_cp=%p (addr=%s)",
01142 file, line, ddns_cb, ddns_address );
01143 #endif
01144
01145
01146
01147
01148
01149 if (ddns_cb->flags & DDNS_STATIC_LEASE) {
01150 #if defined (DEBUG_DNS_UPDATES)
01151 log_info("lease is static, returning");
01152 #endif
01153 return (ISC_R_SUCCESS);
01154 }
01155
01156
01157
01158
01159
01160 if ((ddns_cb->address.len == 16) &&
01161 ((ddns_cb->flags & DDNS_ACTIVE_LEASE) == 0)) {
01162 return (ISC_R_SUCCESS);
01163 }
01164
01165 if (lease != NULL) {
01166 safe_lease_update(lease, ddns_cb, ddns_cb_set,
01167 file, line);
01168 } else if (lease6 != NULL) {
01169 safe_lease6_update(lease6, ddns_cb, ddns_cb_set,
01170 file, line);
01171 } else if (ddns_cb->address.len == 4) {
01172 struct lease *find_lease = NULL;
01173 if (find_lease_by_ip_addr(&find_lease,
01174 ddns_cb->address, MDL) != 0) {
01175 #if defined (DEBUG_DNS_UPDATES)
01176 log_info("%s(%d): find_lease_by_ip_addr(%s) successful:"
01177 "lease=%p", file, line, ddns_address,
01178 find_lease);
01179 #endif
01180
01181 safe_lease_update(find_lease, ddns_cb,
01182 ddns_cb_set, file, line);
01183 lease_dereference(&find_lease, MDL);
01184 }
01185 else {
01186 log_error("%s(%d): ddns_update_lease_ptr failed. "
01187 "Lease for %s not found.",
01188 file, line, piaddr(ddns_cb->address));
01189
01190 #if defined (DNS_UPDATES_MEMORY_CHECKS)
01191 update_lease_failed(NULL, NULL, ddns_cb, ddns_cb_set,
01192 file, line);
01193 #endif
01194
01195
01196
01197
01198 return(ISC_R_FAILURE);
01199
01200 }
01201 } else if (ddns_cb->address.len == 16) {
01202 struct iasubopt *find_lease6 = NULL;
01203 struct ipv6_pool *pool = NULL;
01204 struct in6_addr addr;
01205 char addrbuf[MAX_ADDRESS_STRING_LEN];
01206
01207 memcpy(&addr, &ddns_cb->address.iabuf, 16);
01208 if ((find_ipv6_pool(&pool, D6O_IA_TA, &addr) !=
01209 ISC_R_SUCCESS) &&
01210 (find_ipv6_pool(&pool, D6O_IA_NA, &addr) !=
01211 ISC_R_SUCCESS)) {
01212 inet_ntop(AF_INET6, &addr, addrbuf,
01213 MAX_ADDRESS_STRING_LEN);
01214 log_error("%s(%d): Pool for lease %s not found.",
01215 file, line, addrbuf);
01216 #if defined (DNS_UPDATES_MEMORY_CHECKS)
01217 update_lease_failed(NULL, NULL, ddns_cb, ddns_cb_set,
01218 file, line);
01219 #endif
01220
01221
01222
01223
01224 return(ISC_R_FAILURE);
01225 }
01226
01227 if (iasubopt_hash_lookup(&find_lease6, pool->leases,
01228 &addr, 16, MDL)) {
01229 find_lease6->ddns_cb = ddns_cb_set;
01230 iasubopt_dereference(&find_lease6, MDL);
01231 } else {
01232 inet_ntop(AF_INET6, &addr, addrbuf,
01233 MAX_ADDRESS_STRING_LEN);
01234 log_error("%s(%d): Lease %s not found within pool.",
01235 file, line, addrbuf);
01236 #if defined (DNS_UPDATES_MEMORY_CHECKS)
01237 update_lease_failed(NULL, NULL, ddns_cb, ddns_cb_set,
01238 file, line);
01239 #endif
01240
01241
01242
01243
01244 return(ISC_R_FAILURE);
01245 }
01246 ipv6_pool_dereference(&pool, MDL);
01247 } else {
01248
01249 log_fatal("Impossible condition at %s:%d, called from %s:%d.",
01250 MDL, file, line);
01251 }
01252
01253 return(ISC_R_SUCCESS);
01254 }
01255
01256 void
01257 ddns_ptr_add(dhcp_ddns_cb_t *ddns_cb,
01258 isc_result_t eresult)
01259 {
01260 if (eresult == ISC_R_SUCCESS) {
01261 log_info("Added reverse map from %.*s to %.*s",
01262 (int)ddns_cb->rev_name.len,
01263 (const char *)ddns_cb->rev_name.data,
01264 (int)ddns_cb->fwd_name.len,
01265 (const char *)ddns_cb->fwd_name.data);
01266
01267 ddns_update_lease_text(ddns_cb, NULL);
01268 } else {
01269 log_error("Unable to add reverse map from %.*s to %.*s: %s",
01270 (int)ddns_cb->rev_name.len,
01271 (const char *)ddns_cb->rev_name.data,
01272 (int)ddns_cb->fwd_name.len,
01273 (const char *)ddns_cb->fwd_name.data,
01274 isc_result_totext (eresult));
01275 }
01276
01277 ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
01278 ddns_cb_free(ddns_cb, MDL);
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289 commit_leases();
01290 return;
01291 }
01292
01293
01294
01295
01296
01297
01298
01299
01300 void
01301 ddns_ptr_remove(dhcp_ddns_cb_t *ddns_cb,
01302 isc_result_t eresult)
01303 {
01304 isc_result_t result = eresult;
01305
01306 switch(eresult) {
01307 case ISC_R_SUCCESS:
01308 log_info("Removed reverse map on %.*s",
01309 (int)ddns_cb->rev_name.len,
01310 (const char *)ddns_cb->rev_name.data);
01311
01312 case DNS_R_NXRRSET:
01313 case DNS_R_NXDOMAIN:
01314
01315
01316
01317 ddns_update_lease_text(ddns_cb, NULL);
01318
01319
01320 result = ISC_R_SUCCESS;
01321 #if defined (DEBUG_DNS_UPDATES)
01322 log_info("DDNS: removed map or no reverse map to remove %.*s",
01323 (int)ddns_cb->rev_name.len,
01324 (const char *)ddns_cb->rev_name.data);
01325 #endif
01326 break;
01327
01328 default:
01329 log_error("Can't remove reverse map on %.*s: %s",
01330 (int)ddns_cb->rev_name.len,
01331 (const char *)ddns_cb->rev_name.data,
01332 isc_result_totext (eresult));
01333 break;
01334 }
01335
01336 ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
01337 ddns_fwd_srv_connector(NULL, NULL, NULL, ddns_cb->next_op, result);
01338 ddns_cb_free(ddns_cb, MDL);
01339 return;
01340 }
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371 void
01372 ddns_fwd_srv_add2(dhcp_ddns_cb_t *ddns_cb,
01373 isc_result_t eresult)
01374 {
01375 isc_result_t result;
01376 const char *logstr = NULL;
01377 char ddns_address[MAX_ADDRESS_STRING_LEN];
01378
01379
01380 strcpy(ddns_address, piaddr(ddns_cb->address));
01381
01382 switch(eresult) {
01383 case ISC_R_SUCCESS:
01384 log_info("Added new forward map from %.*s to %s",
01385 (int)ddns_cb->fwd_name.len,
01386 (const char *)ddns_cb->fwd_name.data,
01387 ddns_address);
01388
01389 ddns_update_lease_text(ddns_cb, NULL);
01390
01391 if ((ddns_cb->flags & DDNS_UPDATE_PTR) != 0) {
01392
01393 if (ddns_cb->zone != NULL) {
01394 ddns_cb_forget_zone(ddns_cb);
01395 }
01396
01397 ddns_cb->state = DDNS_STATE_ADD_PTR;
01398 ddns_cb->cur_func = ddns_ptr_add;
01399
01400 result = ddns_modify_ptr(ddns_cb, MDL);
01401 if (result == ISC_R_SUCCESS) {
01402 return;
01403 }
01404 }
01405 break;
01406
01407 case DNS_R_YXRRSET:
01408 case DNS_R_YXDOMAIN:
01409 logstr = "DHCID mismatch, belongs to another client.";
01410 break;
01411
01412 case DNS_R_NXRRSET:
01413 case DNS_R_NXDOMAIN:
01414 logstr = "Has an address record but no DHCID, not mine.";
01415 break;
01416
01417 default:
01418 logstr = isc_result_totext(eresult);
01419 break;
01420 }
01421
01422 if (logstr != NULL) {
01423 log_error("Forward map from %.*s to %s FAILED: %s",
01424 (int)ddns_cb->fwd_name.len,
01425 (const char *)ddns_cb->fwd_name.data,
01426 ddns_address, logstr);
01427 }
01428
01429 ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
01430 ddns_cb_free(ddns_cb, MDL);
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441 commit_leases();
01442 return;
01443 }
01444
01445 void
01446 ddns_fwd_srv_add1(dhcp_ddns_cb_t *ddns_cb,
01447 isc_result_t eresult)
01448 {
01449 isc_result_t result;
01450 char ddns_address[MAX_ADDRESS_STRING_LEN];
01451
01452
01453 strcpy(ddns_address, piaddr(ddns_cb->address));
01454
01455 switch(eresult) {
01456 case ISC_R_SUCCESS:
01457 log_info ("Added new forward map from %.*s to %s",
01458 (int)ddns_cb->fwd_name.len,
01459 (const char *)ddns_cb->fwd_name.data,
01460 ddns_address);
01461
01462 ddns_update_lease_text(ddns_cb, NULL);
01463
01464 if ((ddns_cb->flags & DDNS_UPDATE_PTR) != 0) {
01465
01466 if (ddns_cb->zone != NULL) {
01467 ddns_cb_forget_zone(ddns_cb);
01468 }
01469
01470 ddns_cb->state = DDNS_STATE_ADD_PTR;
01471 ddns_cb->cur_func = ddns_ptr_add;
01472
01473 result = ddns_modify_ptr(ddns_cb, MDL);
01474 if (result == ISC_R_SUCCESS) {
01475 return;
01476 }
01477 }
01478 break;
01479
01480 case DNS_R_YXDOMAIN:
01481
01482 ddns_cb->state = DDNS_STATE_ADD_FW_YXDHCID;
01483 ddns_cb->cur_func = ddns_fwd_srv_add2;
01484
01485 result = ddns_modify_fwd(ddns_cb, MDL);
01486 if (result == ISC_R_SUCCESS) {
01487 return;
01488 }
01489 break;
01490
01491 default:
01492 log_error ("Unable to add forward map from %.*s to %s: %s",
01493 (int)ddns_cb->fwd_name.len,
01494 (const char *)ddns_cb->fwd_name.data,
01495 ddns_address,
01496 isc_result_totext (eresult));
01497 break;
01498 }
01499
01500 ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
01501 ddns_cb_free(ddns_cb, MDL);
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512 commit_leases();
01513 return;
01514 }
01515
01516 static void
01517 ddns_fwd_srv_connector(struct lease *lease,
01518 struct iasubopt *lease6,
01519 struct binding_scope **inscope,
01520 dhcp_ddns_cb_t *ddns_cb,
01521 isc_result_t eresult)
01522 {
01523 isc_result_t result = ISC_R_FAILURE;
01524
01525 if (ddns_cb == NULL) {
01526
01527 return;
01528 }
01529
01530 if (eresult == ISC_R_SUCCESS) {
01531
01532
01533
01534
01535
01536 if (ddns_cb->flags & DDNS_UPDATE_ADDR) {
01537 ddns_cb->state = DDNS_STATE_ADD_FW_NXDOMAIN;
01538 ddns_cb->cur_func = ddns_fwd_srv_add1;
01539 result = ddns_modify_fwd(ddns_cb, MDL);
01540 } else if ((ddns_cb->flags & DDNS_UPDATE_PTR) &&
01541 (ddns_cb->rev_name.len != 0)) {
01542 ddns_cb->state = DDNS_STATE_ADD_PTR;
01543 ddns_cb->cur_func = ddns_ptr_add;
01544 result = ddns_modify_ptr(ddns_cb, MDL);
01545 } else {
01546 ddns_update_lease_text(ddns_cb, inscope);
01547 }
01548 }
01549
01550 if (result == ISC_R_SUCCESS) {
01551 ddns_update_lease_ptr(lease, lease6, ddns_cb, ddns_cb, MDL);
01552 } else {
01553 ddns_cb_free(ddns_cb, MDL);
01554 }
01555
01556 return;
01557 }
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572 void
01573 ddns_fwd_srv_rem2(dhcp_ddns_cb_t *ddns_cb,
01574 isc_result_t eresult)
01575 {
01576 if (eresult == ISC_R_SUCCESS) {
01577 ddns_update_lease_text(ddns_cb, NULL);
01578
01579
01580 if ((ddns_cb->flags & DDNS_UPDATE_PTR) != 0) {
01581
01582 if (ddns_cb->zone != NULL) {
01583 ddns_cb_forget_zone(ddns_cb);
01584 }
01585
01586 ddns_cb->state = DDNS_STATE_REM_PTR;
01587 ddns_cb->cur_func = ddns_ptr_remove;
01588
01589 eresult = ddns_modify_ptr(ddns_cb, MDL);
01590 if (eresult == ISC_R_SUCCESS) {
01591 return;
01592 }
01593 }
01594 }
01595
01596 ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
01597 ddns_fwd_srv_connector(NULL, NULL, NULL, ddns_cb->next_op, eresult);
01598 ddns_cb_free(ddns_cb, MDL);
01599 return;
01600 }
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610 void
01611 ddns_fwd_srv_rem1(dhcp_ddns_cb_t *ddns_cb,
01612 isc_result_t eresult)
01613 {
01614 isc_result_t result = eresult;
01615 char ddns_address[MAX_ADDRESS_STRING_LEN];
01616
01617 switch(eresult) {
01618 case ISC_R_SUCCESS:
01619
01620 strcpy(ddns_address, piaddr(ddns_cb->address));
01621 log_info("Removed forward map from %.*s to %s",
01622 (int)ddns_cb->fwd_name.len,
01623 (const char*)ddns_cb->fwd_name.data,
01624 ddns_address);
01625
01626
01627 ddns_cb->state = DDNS_STATE_REM_FW_NXRR;
01628 ddns_cb->cur_func = ddns_fwd_srv_rem2;
01629 result = ddns_modify_fwd(ddns_cb, MDL);
01630 if (result == ISC_R_SUCCESS) {
01631 return;
01632 }
01633 break;
01634
01635 case DNS_R_NXRRSET:
01636 case DNS_R_NXDOMAIN:
01637 ddns_update_lease_text(ddns_cb, NULL);
01638
01639 #if defined (DEBUG_DNS_UPDATES)
01640 log_info("DDNS: no forward map to remove. %p", ddns_cb);
01641 #endif
01642
01643
01644 if ((ddns_cb->flags & DDNS_UPDATE_PTR) != 0) {
01645
01646 if (ddns_cb->zone != NULL) {
01647 ddns_cb_forget_zone(ddns_cb);
01648 }
01649
01650 ddns_cb->state = DDNS_STATE_REM_PTR;
01651 ddns_cb->cur_func = ddns_ptr_remove;
01652
01653 result = ddns_modify_ptr(ddns_cb, MDL);
01654 if (result == ISC_R_SUCCESS) {
01655 return;
01656 }
01657 }
01658 else {
01659
01660 eresult = ISC_R_SUCCESS;
01661 }
01662 break;
01663
01664 default:
01665 break;
01666 }
01667
01668 ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL, MDL);
01669 ddns_fwd_srv_connector(NULL, NULL, NULL, ddns_cb->next_op, eresult);
01670 ddns_cb_free(ddns_cb, MDL);
01671 }
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697 isc_result_t
01698 ddns_removals(struct lease *lease,
01699 struct iasubopt *lease6,
01700 dhcp_ddns_cb_t *add_ddns_cb,
01701 isc_boolean_t active)
01702 {
01703 isc_result_t rcode, execute_add = ISC_R_FAILURE;
01704 struct binding_scope **scope = NULL;
01705 isc_result_t result = ISC_R_FAILURE;
01706 dhcp_ddns_cb_t *ddns_cb = NULL;
01707 struct data_string leaseid;
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732 if (add_ddns_cb == NULL) {
01733 if ((lease != NULL) && (lease->ddns_cb != NULL)) {
01734 ddns_cb = lease->ddns_cb;
01735
01736
01737
01738
01739
01740 if (((ddns_cb->state == DDNS_STATE_ADD_PTR) ||
01741 (ddns_cb->state == DDNS_STATE_ADD_FW_NXDOMAIN) ||
01742 (ddns_cb->state == DDNS_STATE_ADD_FW_YXDHCID)) ||
01743 ((active == ISC_FALSE) &&
01744 ((ddns_cb->flags & DDNS_ACTIVE_LEASE) != 0))) {
01745
01746 ddns_cancel(lease->ddns_cb, MDL);
01747 lease->ddns_cb = NULL;
01748 } else {
01749
01750 if (ddns_cb->next_op != NULL) {
01751 ddns_cb_free(ddns_cb->next_op, MDL);
01752 ddns_cb->next_op = NULL;
01753 }
01754 #if defined (DEBUG_DNS_UPDATES)
01755 log_info("DDNS %s(%d): removal already in "
01756 "progress new ddns_cb=%p",
01757 MDL, ddns_cb);
01758 #endif
01759 return (ISC_R_SUCCESS);
01760 }
01761 } else if ((lease6 != NULL) && (lease6->ddns_cb != NULL)) {
01762 ddns_cb = lease6->ddns_cb;
01763
01764
01765
01766
01767
01768 if (((ddns_cb->state == DDNS_STATE_ADD_PTR) ||
01769 (ddns_cb->state == DDNS_STATE_ADD_FW_NXDOMAIN) ||
01770 (ddns_cb->state == DDNS_STATE_ADD_FW_YXDHCID)) ||
01771 ((active == ISC_FALSE) &&
01772 ((ddns_cb->flags & DDNS_ACTIVE_LEASE) != 0))) {
01773
01774 ddns_cancel(lease6->ddns_cb, MDL);
01775 lease6->ddns_cb = NULL;
01776 } else {
01777
01778 if (ddns_cb->next_op != NULL) {
01779 ddns_cb_free(ddns_cb->next_op, MDL);
01780 ddns_cb->next_op = NULL;
01781 }
01782 #if defined (DEBUG_DNS_UPDATES)
01783 log_info("DDNS %s(%d): removal already in "
01784 "progress new ddns_cb=%p",
01785 MDL, ddns_cb);
01786 #endif
01787 return (ISC_R_SUCCESS);
01788 }
01789 }
01790 ddns_cb = NULL;
01791 }
01792
01793
01794 ddns_cb = ddns_cb_alloc(MDL);
01795 if (ddns_cb == NULL) {
01796 goto cleanup;
01797 }
01798
01799
01800
01801
01802
01803
01804 if (lease != NULL) {
01805 scope = &(lease->scope);
01806 ddns_cb->address = lease->ip_addr;
01807 if (lease->flags & STATIC_LEASE)
01808 ddns_cb->flags |= DDNS_STATIC_LEASE;
01809 } else if (lease6 != NULL) {
01810 scope = &(lease6->scope);
01811 memcpy(&ddns_cb->address.iabuf, lease6->addr.s6_addr, 16);
01812 ddns_cb->address.len = 16;
01813 } else
01814 goto cleanup;
01815
01816
01817
01818
01819
01820
01821
01822
01823 if (active == ISC_TRUE) {
01824 ddns_cb->flags |= DDNS_ACTIVE_LEASE;
01825 }
01826
01827
01828 if (*scope == NULL)
01829 goto cleanup;
01830
01831 if ((ddns_update_style != DDNS_UPDATE_STYLE_STANDARD) &&
01832 (ddns_update_style != DDNS_UPDATE_STYLE_INTERIM))
01833 goto cleanup;
01834
01835
01836 ddns_cb->flags |= DDNS_UPDATE_ADDR | DDNS_UPDATE_PTR;
01837
01838
01839 execute_add = ISC_R_SUCCESS;
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851 if (!find_bound_string(&ddns_cb->fwd_name, *scope, "ddns-fwd-name")) {
01852
01853 ddns_cb->flags &= ~DDNS_UPDATE_ADDR;
01854 execute_add = ISC_R_FAILURE;
01855
01856
01857 if (find_bound_string(&ddns_cb->fwd_name, *scope,
01858 "ddns-client-fqdn")) {
01859 ddns_cb->flags |= DDNS_CLIENT_DID_UPDATE;
01860 }
01861 }
01862
01863
01864
01865
01866
01867
01868
01869 memset(&leaseid, 0, sizeof(leaseid));
01870 if (find_bound_string (&leaseid, *scope, ddns_standard_tag)) {
01871
01872 ddns_cb->lease_tag = ddns_standard_tag;
01873 ddns_cb->dhcid_class = dns_rdatatype_dhcid;
01874 data_string_copy(&ddns_cb->dhcid, &leaseid, MDL);
01875 data_string_forget(&leaseid, MDL);
01876 } else if (find_bound_string (&leaseid, *scope, ddns_interim_tag)) {
01877
01878 ddns_cb->lease_tag = ddns_interim_tag;
01879 ddns_cb->dhcid_class = dns_rdatatype_txt;
01880 if (dhcid_fromlease(&ddns_cb->dhcid, &leaseid) !=
01881 ISC_R_SUCCESS) {
01882
01883
01884
01885
01886 ddns_cb->flags &= ~DDNS_UPDATE_ADDR;
01887 }
01888 data_string_forget(&leaseid, MDL);
01889 } else {
01890 ddns_cb->flags &= ~DDNS_UPDATE_ADDR;
01891 }
01892
01893
01894
01895
01896
01897
01898 if (!find_bound_string(&ddns_cb->rev_name, *scope, "ddns-rev-name")) {
01899 ddns_cb->flags &= ~DDNS_UPDATE_PTR;
01900 }
01901
01902
01903
01904
01905
01906 ddns_cb->next_op = add_ddns_cb;
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916 if ((ddns_cb->flags & DDNS_UPDATE_ADDR) != 0) {
01917 if (ddns_cb->fwd_name.len != 0) {
01918 ddns_cb->state = DDNS_STATE_REM_FW_YXDHCID;
01919 ddns_cb->cur_func = ddns_fwd_srv_rem1;
01920
01921 rcode = ddns_modify_fwd(ddns_cb, MDL);
01922 if (rcode == ISC_R_SUCCESS) {
01923 ddns_update_lease_ptr(lease, lease6, ddns_cb,
01924 ddns_cb, MDL);
01925 return (ISC_R_SUCCESS);
01926 }
01927
01928
01929
01930
01931
01932 execute_add = ISC_R_FAILURE;
01933 goto cleanup;
01934 }
01935 else {
01936
01937 unset(*scope, "ddns-fwd-name");
01938 unset(*scope, ddns_cb->lease_tag);
01939 }
01940 }
01941
01942 if ((ddns_cb->flags & DDNS_UPDATE_PTR) != 0) {
01943 ddns_cb->state = DDNS_STATE_REM_PTR;
01944 ddns_cb->cur_func = ddns_ptr_remove;
01945
01946
01947
01948
01949
01950
01951 if (execute_add != ISC_R_SUCCESS) {
01952 ddns_cb->next_op = NULL;
01953 ddns_fwd_srv_connector(lease, lease6, scope,
01954 add_ddns_cb, execute_add);
01955 add_ddns_cb = NULL;
01956 }
01957 else {
01958 result = ISC_R_SUCCESS;
01959 }
01960
01961 rcode = ddns_modify_ptr(ddns_cb, MDL);
01962 if (rcode == ISC_R_SUCCESS) {
01963 ddns_update_lease_ptr(lease, lease6, ddns_cb, ddns_cb,
01964 MDL);
01965 return (result);
01966 }
01967
01968
01969
01970 execute_add = ISC_R_FAILURE;
01971 goto cleanup;
01972 }
01973
01974 cleanup:
01975
01976
01977
01978
01979
01980
01981 ddns_fwd_srv_connector(lease, lease6, scope, add_ddns_cb, execute_add);
01982 if (ddns_cb != NULL)
01983 ddns_cb_free(ddns_cb, MDL);
01984
01985 return (result);
01986 }
01987
01988 #endif