38 #include <dns/result.h>
45 static void ddns_fwd_srv_connector(
struct lease *
lease,
49 isc_result_t eresult);
55 static void data_string_append (
struct data_string *ds1,
58 memcpy (ds1 ->
buffer -> data + ds1 -> len,
61 ds1 -> len += ds2 -> len;
84 int server_updates_a = 1;
86 int ignorep = 0, client_ignorep = 0;
105 if ((old != NULL) && (old->
ddns_cb != NULL)) {
109 }
else if (lease6 != NULL) {
110 if ((old6 != NULL) && (old6->
ddns_cb != NULL)) {
123 if (ddns_cb == NULL) {
139 scope = &(lease->
scope);
143 }
else if (lease6 != NULL) {
144 scope = &(lease6->
scope);
149 memset (&d1, 0,
sizeof(d1));
150 memset (&ddns_hostname, 0,
sizeof (ddns_hostname));
151 memset (&ddns_domainname, 0,
sizeof (ddns_domainname));
152 memset (&old_ddns_fwd_name, 0,
sizeof (ddns_fwd_name));
153 memset (&ddns_fwd_name, 0,
sizeof (ddns_fwd_name));
154 memset (&ddns_dhcid, 0,
sizeof (ddns_dhcid));
161 packet->
options, options, scope,
170 options, scope, oc,
MDL))
181 options, scope, oc,
MDL))
184 server_updates_a = 0;
195 options, scope, oc,
MDL)) {
208 options, scope, oc,
MDL))
219 options, scope, oc,
MDL);
226 if ((s1 == 0) && (lease && lease->
host && lease->
host->
name)) {
231 options, scope, oc,
MDL)) {
235 MDL) && ddns_hostname.len > 0));
243 options, scope, oc,
MDL);
248 if (ddns_hostname.len + ddns_domainname.len > 253) {
249 log_error (
"ddns_update: host.domain name too long");
256 ddns_domainname.len + 2,
MDL)) {
257 ddns_fwd_name.data = ddns_fwd_name.buffer->data;
258 data_string_append (&ddns_fwd_name, &ddns_hostname);
259 ddns_fwd_name.buffer->data[ddns_fwd_name.len] =
'.';
261 data_string_append (&ddns_fwd_name, &ddns_domainname);
262 ddns_fwd_name.buffer->data[ddns_fwd_name.len] =
'\0';
263 ddns_fwd_name.terminated = 1;
271 if (old_ddns_fwd_name.len != ddns_fwd_name.len ||
272 memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data,
273 old_ddns_fwd_name.len)) {
282 #if defined (DDNS_UPDATE_SLOW_TRANSITION)
306 options, scope, oc,
MDL)) {
315 "ddns-client-fqdn")) {
318 if (old_ddns_fwd_name.len == ddns_fwd_name.len &&
319 !memcmp (old_ddns_fwd_name.data, ddns_fwd_name.data,
320 old_ddns_fwd_name.len) &&
325 options, scope, oc,
MDL))) {
334 if ((!ddns_fwd_name.len) || (ddns_fwd_name.len > 255)) {
335 if (ddns_fwd_name.len > 255) {
336 log_error (
"client provided fqdn: too long");
340 if (do_remove != 0) {
370 #ifndef USE_OLD_DDNS_TTL
371 else if (lease6 != NULL) {
372 ddns_ttl = lease6->
prefer/2;
384 if (d1.len == sizeof (u_int32_t))
390 ddns_cb->
ttl = ddns_ttl;
410 rev_name_len = snprintf(buf,
sizeof(buf),
"%u.%u.%u.%u.",
417 rev_name_len += d1.len;
419 if (rev_name_len > 255) {
420 log_error(
"ddns_update: Calculated rev domain "
431 rev_name_len =
sizeof(
"0.1.2.3.4.5.6.7."
456 rev_name_len,
MDL)) {
473 data_string_append(rname, &d1);
478 for (i=0; i<16; i++) {
480 (*a & 0xF), ((*a >> 4) & 0xF));
484 strcat(p,
"ip6.arpa.");
485 rname->
len = strlen((
const char *)rname->
data);
530 if (lease6 != NULL) {
536 }
else if ((lease != NULL) &&
537 (lease->
uid != NULL) &&
543 (lease->
uid[0] == 255)) {
554 }
else if (lease != NULL)
575 options, scope, oc,
MDL))
594 ddns_fwd_srv_connector(lease, lease6, scope, ddns_cb,
620 }
else if (client_ignorep &&
687 memcpy(&bp->
data[5], d1.data, d1.len);
689 bp, &bp->
data[5], d1.len,
704 bp ->
data [0] = server_updates_a;
706 bp, &bp->
data [0], 1,
709 bp ->
data [1] = server_updates_a;
711 bp, &bp->
data [1], 1,
718 options, scope, oc,
MDL))
723 bp, &bp->
data [2], 1,
726 bp ->
data [3] = 255;
728 bp, &bp->
data [3], 1,
731 bp ->
data [4] = 255;
733 bp, &bp->
data [4], 1,
736 if (ddns_fwd_name.len) {
737 memcpy (&bp ->
data [5],
738 ddns_fwd_name.data, ddns_fwd_name.len);
752 if (ddns_cb != NULL) {
797 struct lease *lease = NULL;
800 struct in6_addr addr;
808 return (ISC_R_SUCCESS);
816 return (ISC_R_SUCCESS);
818 if (inscope != NULL) {
822 scope = &(lease->
scope);
830 if (iasubopt_hash_lookup(&lease6, pool->
leases,
832 scope = &(lease6->
scope);
843 lease_dereference(&lease,
MDL);
849 return(ISC_R_FAILURE);
853 switch(ddns_cb->
state) {
855 unset(*scope,
"ddns-rev-name");
857 unset(*scope,
"ddns-client-fqdn");
878 memset(&lease_dhcid, 0,
sizeof(lease_dhcid));
887 unset(*scope,
"ddns-fwd-name");
895 lease_dereference(&lease,
MDL);
901 return(ISC_R_SUCCESS);
922 update_lease_failed(
struct lease *lease,
931 sprintf(reason,
"unknown");
932 sprintf(lease_address,
"unknown");
939 if (ddns_cb != NULL) {
944 sprintf(reason,
"duplicate IPv4 fixed-address entry");
946 sprintf(reason,
"duplicate IPv6 fixed-address6 entry "
947 "or overlapping pools");
953 sprintf(reason,
"corrupted ddns_cb structure (address "
958 log_error(
"Failed to properly update internal lease structure with "
960 log_error(
"control block structures. Tried to update lease for"
961 "%s address, ddns_cb=%p.", lease_address, ddns_cb);
964 log_error(
"This condition can occur, if DHCP server configuration is "
966 log_error(
"In particular, please do check that your configuration:");
967 log_error(
"a) does not have overlapping pools (especially containing");
968 log_error(
" %s address).", lease_address);
969 log_error(
"b) there are no duplicate fixed-address or fixed-address6");
970 log_error(
"entries for the %s address.", lease_address);
972 log_error(
"Possible reason for this failure: %s", reason);
974 log_fatal(
"%s(%d): Failed to update lease database with DDNS info for "
975 "address %s. Lease database inconsistent. Unable to recover."
976 " Terminating.", file, line, lease_address);
987 safe_lease_update(
struct lease *lease,
990 const char *file,
int line)
994 log_fatal(
"Impossible condition at %s:%d (called from %s:%d).",
998 if ( (lease->
ddns_cb == NULL) && (newcb == NULL) ) {
1010 log_error(
"%s(%d): Invalid lease update. Tried to "
1011 "clear already NULL DDNS control block "
1012 "pointer for lease %s.",
1015 #if defined (DNS_UPDATES_MEMORY_CHECKS)
1016 update_lease_failed(lease, NULL, oldcb, newcb, file, line);
1031 log_error(
"%s(%d): Failed to update internal lease "
1032 "structure with DDNS control block. Existing"
1033 " ddns_cb structure does not match "
1034 "expectations.IPv4=%s, old ddns_cb=%p, tried"
1035 "to update to new ddns_cb=%p", file, line,
1038 #if defined (DNS_UPDATES_MEMORY_CHECKS)
1039 update_lease_failed(lease, NULL, oldcb, newcb, file, line);
1055 safe_lease6_update(
struct iasubopt *lease6,
1058 const char *file,
int line)
1062 if (lease6 == NULL) {
1064 log_fatal(
"Impossible condition at %s:%d (called from %s:%d).",
1068 if ( (lease6->
ddns_cb == NULL) && (newcb == NULL) ) {
1069 inet_ntop(AF_INET6, &lease6->
addr, addrbuf,
1075 log_error(
"%s(%d): Failed to update internal lease "
1076 "structure. Tried to clear already NULL "
1077 "DDNS control block pointer for lease %s.",
1078 file, line, addrbuf);
1080 #if defined (DNS_UPDATES_MEMORY_CHECKS)
1081 update_lease_failed(NULL, lease6, oldcb, newcb, file, line);
1097 inet_ntop(AF_INET6, &lease6->
addr, addrbuf,
1100 log_error(
"%s(%d): Failed to update internal lease "
1101 "structure with DDNS control block. Existing"
1102 " ddns_cb structure does not match "
1103 "expectations.IPv6=%s, old ddns_cb=%p, tried"
1104 "to update to new ddns_cb=%p", file, line,
1105 addrbuf, oldcb, newcb);
1107 #if defined (DNS_UPDATES_MEMORY_CHECKS)
1108 update_lease_failed(NULL, lease6, oldcb, newcb, file, line);
1138 ddns_update_lease_ptr(
struct lease *lease,
1142 const char * file,
int line)
1145 sprintf(ddns_address,
"unknown");
1146 if (ddns_cb == NULL) {
1147 log_info(
"%s(%d): No control block for lease update",
1149 return (ISC_R_FAILURE);
1154 #if defined (DEBUG_DNS_UPDATES)
1155 log_info(
"%s(%d): Updating lease_ptr for ddns_cp=%p (addr=%s)",
1156 file, line, ddns_cb, ddns_address );
1164 #if defined (DEBUG_DNS_UPDATES)
1165 log_info(
"lease is static, returning");
1167 return (ISC_R_SUCCESS);
1176 return (ISC_R_SUCCESS);
1179 if (lease != NULL) {
1180 safe_lease_update(lease, ddns_cb, ddns_cb_set,
1182 }
else if (lease6 != NULL) {
1183 safe_lease6_update(lease6, ddns_cb, ddns_cb_set,
1189 #if defined (DEBUG_DNS_UPDATES)
1190 log_info(
"%s(%d): find_lease_by_ip_addr(%s) successful:"
1191 "lease=%p", file, line, ddns_address,
1195 safe_lease_update(find_lease, ddns_cb,
1196 ddns_cb_set, file, line);
1197 lease_dereference(&find_lease,
MDL);
1200 log_error(
"%s(%d): ddns_update_lease_ptr failed. "
1201 "Lease for %s not found.",
1204 #if defined (DNS_UPDATES_MEMORY_CHECKS)
1205 update_lease_failed(NULL, NULL, ddns_cb, ddns_cb_set,
1212 return(ISC_R_FAILURE);
1216 struct iasubopt *find_lease6 = NULL;
1218 struct in6_addr addr;
1226 inet_ntop(AF_INET6, &addr, addrbuf,
1228 log_error(
"%s(%d): Pool for lease %s not found.",
1229 file, line, addrbuf);
1230 #if defined (DNS_UPDATES_MEMORY_CHECKS)
1231 update_lease_failed(NULL, NULL, ddns_cb, ddns_cb_set,
1238 return(ISC_R_FAILURE);
1241 if (iasubopt_hash_lookup(&find_lease6, pool->
leases,
1243 find_lease6->
ddns_cb = ddns_cb_set;
1246 inet_ntop(AF_INET6, &addr, addrbuf,
1248 log_error(
"%s(%d): Lease %s not found within pool.",
1249 file, line, addrbuf);
1250 #if defined (DNS_UPDATES_MEMORY_CHECKS)
1251 update_lease_failed(NULL, NULL, ddns_cb, ddns_cb_set,
1258 return(ISC_R_FAILURE);
1263 log_fatal(
"Impossible condition at %s:%d, called from %s:%d.",
1267 return(ISC_R_SUCCESS);
1272 isc_result_t eresult)
1274 if (eresult == ISC_R_SUCCESS) {
1275 log_info(
"Added reverse map from %.*s to %.*s",
1281 ddns_update_lease_text(ddns_cb, NULL);
1283 log_error(
"Unable to add reverse map from %.*s to %.*s: %s",
1288 isc_result_totext (eresult));
1291 ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL,
MDL);
1316 isc_result_t eresult)
1318 isc_result_t result = eresult;
1322 log_info(
"Removed reverse map on %.*s",
1327 case DNS_R_NXDOMAIN:
1331 ddns_update_lease_text(ddns_cb, NULL);
1334 result = ISC_R_SUCCESS;
1335 #if defined (DEBUG_DNS_UPDATES)
1336 log_info(
"DDNS: removed map or no reverse map to remove %.*s",
1343 log_error(
"Can't remove reverse map on %.*s: %s",
1346 isc_result_totext (eresult));
1350 ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL,
MDL);
1351 ddns_fwd_srv_connector(NULL, NULL, NULL, ddns_cb->
next_op, result);
1387 isc_result_t eresult)
1389 isc_result_t result;
1390 const char *logstr = NULL;
1398 log_info(
"Added new forward map from %.*s to %s",
1403 ddns_update_lease_text(ddns_cb, NULL);
1407 if (ddns_cb->
zone != NULL) {
1415 if (result == ISC_R_SUCCESS) {
1422 case DNS_R_YXDOMAIN:
1423 logstr =
"DHCID mismatch, belongs to another client.";
1427 case DNS_R_NXDOMAIN:
1428 logstr =
"Has an address record but no DHCID, not mine.";
1432 logstr = isc_result_totext(eresult);
1436 if (logstr != NULL) {
1437 log_error(
"Forward map from %.*s to %s FAILED: %s",
1440 ddns_address, logstr);
1443 ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL,
MDL);
1461 isc_result_t eresult)
1463 isc_result_t result;
1471 log_info (
"Added new forward map from %.*s to %s",
1476 ddns_update_lease_text(ddns_cb, NULL);
1480 if (ddns_cb->
zone != NULL) {
1488 if (result == ISC_R_SUCCESS) {
1494 case DNS_R_YXDOMAIN:
1497 ddns_cb->
cur_func = ddns_fwd_srv_add2;
1500 if (result == ISC_R_SUCCESS) {
1506 log_error (
"Unable to add forward map from %.*s to %s: %s",
1510 isc_result_totext (eresult));
1514 ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL,
MDL);
1531 ddns_fwd_srv_connector(
struct lease *lease,
1535 isc_result_t eresult)
1537 isc_result_t result = ISC_R_FAILURE;
1539 if (ddns_cb == NULL) {
1544 if (eresult == ISC_R_SUCCESS) {
1552 ddns_cb->
cur_func = ddns_fwd_srv_add1;
1560 ddns_update_lease_text(ddns_cb, inscope);
1564 if (result == ISC_R_SUCCESS) {
1565 ddns_update_lease_ptr(lease, lease6, ddns_cb, ddns_cb,
MDL);
1588 isc_result_t eresult)
1590 if (eresult == ISC_R_SUCCESS) {
1591 ddns_update_lease_text(ddns_cb, NULL);
1596 if (ddns_cb->
zone != NULL) {
1601 ddns_cb->
cur_func = ddns_ptr_remove;
1604 if (eresult == ISC_R_SUCCESS) {
1610 ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL,
MDL);
1611 ddns_fwd_srv_connector(NULL, NULL, NULL, ddns_cb->
next_op, eresult);
1626 isc_result_t eresult)
1628 isc_result_t result = eresult;
1635 log_info(
"Removed forward map from %.*s to %s",
1642 ddns_cb->
cur_func = ddns_fwd_srv_rem2;
1644 if (result == ISC_R_SUCCESS) {
1650 case DNS_R_NXDOMAIN:
1651 ddns_update_lease_text(ddns_cb, NULL);
1653 #if defined (DEBUG_DNS_UPDATES)
1654 log_info(
"DDNS: no forward map to remove. %p", ddns_cb);
1660 if (ddns_cb->
zone != NULL) {
1665 ddns_cb->
cur_func = ddns_ptr_remove;
1668 if (result == ISC_R_SUCCESS) {
1674 eresult = ISC_R_SUCCESS;
1682 ddns_update_lease_ptr(NULL, NULL, ddns_cb, NULL,
MDL);
1683 ddns_fwd_srv_connector(NULL, NULL, NULL, ddns_cb->
next_op, eresult);
1715 isc_boolean_t active)
1717 isc_result_t rcode, execute_add = ISC_R_FAILURE;
1719 isc_result_t result = ISC_R_FAILURE;
1746 if (add_ddns_cb == NULL) {
1747 if ((lease != NULL) && (lease->
ddns_cb != NULL)) {
1757 ((active == ISC_FALSE) &&
1764 if (ddns_cb->
next_op != NULL) {
1768 #if defined (DEBUG_DNS_UPDATES)
1769 log_info(
"DDNS %s(%d): removal already in "
1770 "progress new ddns_cb=%p",
1773 return (ISC_R_SUCCESS);
1775 }
else if ((lease6 != NULL) && (lease6->
ddns_cb != NULL)) {
1785 ((active == ISC_FALSE) &&
1792 if (ddns_cb->
next_op != NULL) {
1796 #if defined (DEBUG_DNS_UPDATES)
1797 log_info(
"DDNS %s(%d): removal already in "
1798 "progress new ddns_cb=%p",
1801 return (ISC_R_SUCCESS);
1809 if (ddns_cb == NULL) {
1818 if (lease != NULL) {
1819 scope = &(lease->
scope);
1823 }
else if (lease6 != NULL) {
1824 scope = &(lease6->
scope);
1837 if (active == ISC_TRUE) {
1853 execute_add = ISC_R_SUCCESS;
1868 execute_add = ISC_R_FAILURE;
1872 "ddns-client-fqdn")) {
1883 memset(&leaseid, 0,
sizeof(leaseid));
1920 ddns_cb->
next_op = add_ddns_cb;
1933 ddns_cb->
cur_func = ddns_fwd_srv_rem1;
1936 if (rcode == ISC_R_SUCCESS) {
1937 ddns_update_lease_ptr(lease, lease6, ddns_cb,
1939 return (ISC_R_SUCCESS);
1946 execute_add = ISC_R_FAILURE;
1951 unset(*scope,
"ddns-fwd-name");
1958 ddns_cb->
cur_func = ddns_ptr_remove;
1965 if (execute_add != ISC_R_SUCCESS) {
1967 ddns_fwd_srv_connector(lease, lease6, scope,
1968 add_ddns_cb, execute_add);
1972 result = ISC_R_SUCCESS;
1976 if (rcode == ISC_R_SUCCESS) {
1977 ddns_update_lease_ptr(lease, lease6, ddns_cb, ddns_cb,
1984 execute_add = ISC_R_FAILURE;
1995 ddns_fwd_srv_connector(lease, lease6, scope, add_ddns_cb, execute_add);
1996 if (ddns_cb != NULL)
int data_string_new(struct data_string *new_string, const char *src, unsigned int len, const char *file, int line)
Constructs a null-terminated data_string from a char* and length.
int find_lease(struct lease **, struct packet *, struct shared_network *, int *, int *, struct lease *, const char *, int)
#define DDNS_STATIC_LEASE
#define SV_USE_HOST_DECL_NAMES
const char * piaddr(const struct iaddr addr)
#define FQDN_NO_CLIENT_UPDATE
struct dhcp_ddns_cb * ddns_cb
#define DDNS_STATE_ADD_FW_NXDOMAIN
int get_dhcid(dhcp_ddns_cb_t *, int, const u_int8_t *, unsigned)
struct universe server_universe
isc_result_t ddns_modify_ptr(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
#define DDNS_STATE_REM_PTR
struct dhcp_ddns_cb * ddns_cb
#define SV_DDNS_REV_DOMAIN_NAME
int find_bound_string(struct data_string *value, struct binding_scope *scope, const char *name)
dhcp_ddns_cb_t * ddns_cb_alloc(const char *file, int line)
void data_string_forget(struct data_string *data, const char *file, int line)
int log_error(const char *,...) __attribute__((__format__(__printf__
#define DDNS_UPDATE_STYLE_STANDARD
struct binding_scope * scope
#define DDNS_STATE_REM_FW_YXDHCID
struct data_string fwd_name
#define DDNS_ACTIVE_LEASE
#define DDNS_CLIENT_DID_UPDATE
struct option_state * options
void ddns_cb_free(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
#define SV_DDNS_HOST_NAME
void log_fatal(const char *,...) __attribute__((__format__(__printf__
void dhcid_tolease(struct data_string *, struct data_string *)
struct data_string rev_name
struct hardware hardware_addr
int unset(struct binding_scope *scope, const char *name)
int evaluate_option_cache(struct data_string *result, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
#define MAX_ADDRESS_STRING_LEN
dns_rdataclass_t dhcid_class
#define SV_UPDATE_OPTIMIZATION
#define DDNS_STATE_ADD_PTR
int buffer_allocate(struct buffer **ptr, unsigned len, const char *file, int line)
int write_lease(struct lease *lease)
struct dhcp_ddns_cb * next_op
#define DDNS_CONFLICT_OVERRIDE
struct data_string iaid_duid
#define DDNS_UPDATE_STYLE_INTERIM
int save_option_buffer(struct universe *universe, struct option_state *options, struct buffer *bp, unsigned char *buffer, unsigned length, unsigned code, int terminatep)
isc_result_t dhcid_fromlease(struct data_string *, struct data_string *)
void ddns_cancel(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)
struct option_cache * lookup_option(struct universe *universe, struct option_state *options, unsigned code)
int int log_info(const char *,...) __attribute__((__format__(__printf__
u_int32_t getULong(const unsigned char *)
isc_result_t ipv6_pool_dereference(struct ipv6_pool **pool, const char *file, int line)
de-reference an IPv6 pool structure.
isc_result_t find_ipv6_pool(struct ipv6_pool **pool, u_int16_t type, const struct in6_addr *addr)
#define SV_DO_REVERSE_UPDATES
#define SV_DDNS_DOMAIN_NAME
isc_result_t ddns_removals(struct lease *, struct iasubopt *, struct dhcp_ddns_cb *, isc_boolean_t)
int evaluate_boolean_option_cache(int *ignorep, struct packet *packet, struct lease *lease, struct client_state *client_state, struct option_state *in_options, struct option_state *cfg_options, struct binding_scope **scope, struct option_cache *oc, const char *file, int line)
int ddns_updates(struct packet *, struct lease *, struct lease *, struct iasubopt *, struct iasubopt *, struct option_state *)
isc_result_t iasubopt_dereference(struct iasubopt **iasubopt, const char *file, int line)
#define FQDN_SERVER_UPDATE
#define DDNS_STATE_ADD_FW_YXDHCID
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
void ddns_cb_forget_zone(dhcp_ddns_cb_t *ddns_cb)
struct universe fqdn_universe
int write_ia(const struct ia_xx *)
#define SV_DDNS_CONFLICT_DETECT
#define DHO_DHCP_CLIENT_IDENTIFIER
const unsigned char * data
int bind_ds_value(struct binding_scope **scope, const char *name, struct data_string *value)
struct binding_scope * scope
void data_string_copy(struct data_string *dest, const struct data_string *src, const char *file, int line)
#define SV_UPDATE_STATIC_LEASES
int find_lease_by_ip_addr(struct lease **, struct iaddr, const char *, int)
#define DDNS_STATE_CLEANUP
#define DDNS_STATE_REM_FW_NXRR
#define MAX_DEFAULT_DDNS_TTL
#define SV_CLIENT_UPDATES
#define SV_DO_FORWARD_UPDATES
int buffer_dereference(struct buffer **ptr, const char *file, int line)
isc_result_t ddns_modify_fwd(dhcp_ddns_cb_t *ddns_cb, const char *file, int line)