1 /* srp-mdns-proxy.c 2 * 3 * Copyright (c) 2019-2024 Apple Inc. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * https://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 * This file contains the SRP Advertising Proxy, which is an SRP Server 18 * that offers registered addresses using mDNS. 19 */ 20 21 #include <stdlib.h> 22 #include <string.h> 23 #include <stdio.h> 24 #include <time.h> 25 #include <unistd.h> 26 #include <pwd.h> 27 #include <errno.h> 28 #include <sys/socket.h> 29 #include <netinet/in.h> 30 #include <arpa/inet.h> 31 #include <fcntl.h> 32 #include <time.h> 33 #include <dns_sd.h> 34 #include <net/if.h> 35 #include <inttypes.h> 36 #include <sys/resource.h> 37 #include <ctype.h> 38 #include <mdns/pf.h> 39 40 #include "srp.h" 41 #include "dns-msg.h" 42 #include "srp-crypto.h" 43 #include "ioloop.h" 44 #include "srp-gw.h" 45 #include "srp-proxy.h" 46 #include "srp-mdns-proxy.h" 47 #include "dnssd-proxy.h" 48 #include "config-parse.h" 49 #include "cti-services.h" 50 #include "route.h" 51 #include "adv-ctl-server.h" 52 #include "srp-replication.h" 53 #include "ioloop-common.h" 54 #include "thread-device.h" 55 #include "nat64-macos.h" 56 #include "srp-dnssd.h" 57 #include "ifpermit.h" 58 #include "state-machine.h" 59 #include "thread-service.h" 60 #include "omr-watcher.h" 61 #include "omr-publisher.h" 62 #include "service-publisher.h" 63 64 65 #if SRP_FEATURE_NAT64 66 #include "nat64.h" 67 #endif 68 69 70 #ifdef SRP_TEST_SERVER 71 #include "srp-test-runner.h" 72 #endif 73 74 #define ADDRESS_RECORD_TTL 4500 75 #define OTHER_RECORD_TTL 4500 76 77 #define _DNSSD_API_AVAILABLE_FALL_2024 (1) 78 79 static const char local_suffix_ld[] = ".local"; 80 static const char *local_suffix = &local_suffix_ld[1]; 81 82 os_log_t global_os_log; 83 void *dns_service_op_not_to_be_freed; 84 srp_server_t *srp_servers; 85 const uint8_t thread_anycast_preamble[7] = { 0, 0, 0, 0xff, 0xfe, 0, 0xfc }; 86 const uint8_t thread_rloc_preamble[6] = { 0, 0, 0, 0xff, 0xfe, 0 }; 87 88 extern int num_push_sessions; 89 extern int dp_num_outstanding_queries; 90 extern int num_push_sessions_dropped_for_load; 91 extern int num_queries_dropped_for_load; 92 93 //====================================================================================================================== 94 // MARK: - Forward references 95 96 static bool register_host_record(adv_host_t *host, adv_record_t *record, const bool skipping); 97 static void register_host_record_completion(DNSServiceRef sdref, DNSRecordRef rref, 98 DNSServiceFlags flags, DNSServiceErrorType error_code, void *context); 99 static bool register_instance(adv_instance_t *instance); 100 static void register_instance_completion(DNSServiceRef sdref, DNSServiceFlags flags, DNSServiceErrorType error_code, 101 const char *name, const char *regtype, const char *domain, void *context); 102 static void update_from_host(adv_host_t *host); 103 static void start_host_update(adv_host_t *host); 104 static void prepare_update(adv_host_t *host, client_update_t *client_update); 105 static void delete_host(void *context); 106 static void lease_callback(void *context); 107 static void adv_host_finalize(adv_host_t *host); 108 static void adv_record_finalize(adv_record_t *record); 109 static void adv_update_finalize(adv_update_t *update); 110 111 //====================================================================================================================== 112 // MARK: - Functions 113 114 void 115 srp_mdns_shared_record_remove(srp_server_t *server_state, adv_record_t *record) 116 { 117 RETAIN_HERE(record, adv_record); 118 if (record->rref != NULL) { 119 if (record->shared_txn != 0 && record->shared_txn == (intptr_t)server_state->shared_registration_txn) { 120 INFO("removing rref %p", record->rref); 121 int err = dns_service_remove_record(server_state, 122 server_state->shared_registration_txn->sdref, record->rref, 0); 123 // We can't release the record here if we got an error removing it, because if we get an error removing it, 124 // it doesn't get removed from the list. This should never happen, but if it does, the record will leak. 125 if (err == kDNSServiceErr_NoError) { 126 RELEASE_HERE(record, adv_record); // Release the DNSService callback's reference 127 } else { 128 // At this point we should never see an error calling DNSServiceRemoveRecord, so if we do, call 129 // attention to it. 130 if (!record->update_pending) { 131 FAULT("DNSServiceRemoveRecord(%p, %p, %p, 0) returned %d", 132 server_state->shared_registration_txn->sdref, record, record->rref, err); 133 } 134 } 135 } else { 136 INFO("didn't remove stale rref %p because %lx != %p", 137 record->rref, record->shared_txn, server_state->shared_registration_txn); 138 } 139 record->rref = NULL; 140 } 141 record->shared_txn = 0; 142 RELEASE_HERE(record, adv_record); 143 } 144 145 146 static void 147 adv_record_finalize(adv_record_t *record) 148 { 149 // We should not be able to get to the finalize function without having removed the rref, because the DNSService 150 // callback always holds a reference to the record. 151 if (record->update != NULL) { 152 RELEASE_HERE(record->update, adv_update); 153 } 154 if (record->host != NULL) { 155 RELEASE_HERE(record->host, adv_host); 156 } 157 158 free(record->rdata); 159 free(record); 160 } 161 162 static void 163 adv_instance_finalize(adv_instance_t *instance) 164 { 165 if (instance->txn != NULL) { 166 ioloop_dnssd_txn_cancel_srp(instance->host->server_state, instance->txn); 167 ioloop_dnssd_txn_release(instance->txn); 168 } 169 if (instance->txt_data != NULL) { 170 free(instance->txt_data); 171 } 172 if (instance->instance_name != NULL) { 173 free(instance->instance_name); 174 } 175 if (instance->service_type != NULL) { 176 free(instance->service_type); 177 } 178 if (instance->host != NULL) { 179 RELEASE_HERE(instance->host, adv_host); 180 instance->host = NULL; 181 } 182 if (instance->message != NULL) { 183 ioloop_message_release(instance->message); 184 instance->message = NULL; 185 } 186 if (instance->update != NULL) { 187 RELEASE_HERE(instance->update, adv_update); 188 instance->update = NULL; 189 } 190 if (instance->retry_wakeup != NULL) { 191 ioloop_wakeup_release(instance->retry_wakeup); 192 instance->retry_wakeup = NULL; 193 } 194 free(instance); 195 } 196 197 void 198 adv_instance_context_release(void *NONNULL context) 199 { 200 adv_instance_t *instance = context; 201 RELEASE_HERE(instance, adv_instance); 202 } 203 204 void 205 adv_instance_retain_(adv_instance_t *instance, const char *file, int line) 206 { 207 RETAIN(instance, adv_instance); 208 } 209 210 void 211 adv_instance_release_(adv_instance_t *instance, const char *file, int line) 212 { 213 RELEASE(instance, adv_instance); 214 } 215 216 void 217 adv_record_retain_(adv_record_t *record, const char *file, int line) 218 { 219 RETAIN(record, adv_record); 220 } 221 222 void 223 adv_record_release_(adv_record_t *record, const char *file, int line) 224 { 225 RELEASE(record, adv_record); 226 } 227 228 #define DECLARE_VEC_CREATE(type) \ 229 static type ## _vec_t * \ 230 type ## _vec_create(int size) \ 231 { \ 232 type ## _vec_t *vec; \ 233 \ 234 vec = calloc(1, sizeof(*vec)); \ 235 if (vec != NULL) { \ 236 if (size == 0) { \ 237 size = 1; \ 238 } \ 239 vec->vec = calloc(size, sizeof (*(vec->vec))); \ 240 if (vec->vec == NULL) { \ 241 free(vec); \ 242 vec = NULL; \ 243 } else { \ 244 RETAIN_HERE(vec, type##_vec); \ 245 } \ 246 } \ 247 return vec; \ 248 } 249 250 #define DECLARE_VEC_COPY(type) \ 251 static type ## _vec_t * \ 252 type ## _vec_copy(type ## _vec_t *vec) \ 253 { \ 254 type ## _vec_t *new_vec; \ 255 int i; \ 256 \ 257 new_vec = type ## _vec_create(vec->num); \ 258 if (new_vec != NULL) { \ 259 for (i = 0; i < vec->num; i++) { \ 260 if (vec->vec[i] != NULL) { \ 261 new_vec->vec[i] = vec->vec[i]; \ 262 RETAIN_HERE(new_vec->vec[i], type); \ 263 } \ 264 } \ 265 new_vec->num = vec->num; \ 266 } \ 267 return new_vec; \ 268 } 269 270 #define DECLARE_VEC_FINALIZE(type) \ 271 static void \ 272 type ## _vec_finalize(type ## _vec_t *vec) \ 273 { \ 274 int i; \ 275 \ 276 for (i = 0; i < vec->num; i++) { \ 277 if (vec->vec[i] != NULL) { \ 278 RELEASE_HERE(vec->vec[i], type); \ 279 vec->vec[i] = NULL; \ 280 } \ 281 } \ 282 free(vec->vec); \ 283 free(vec); \ 284 } 285 286 DECLARE_VEC_CREATE(adv_instance); 287 DECLARE_VEC_COPY(adv_instance); 288 DECLARE_VEC_FINALIZE(adv_instance); 289 290 DECLARE_VEC_CREATE(adv_record); 291 DECLARE_VEC_COPY(adv_record); 292 DECLARE_VEC_FINALIZE(adv_record); 293 294 static void 295 srp_dump_server_stats(srp_server_t *server_state, bool full, bool periodic) 296 { 297 // For testing, emit a count of how many hosts, services and address records there are 298 int host_count = 0; 299 int a_record_count = 0; 300 int aaaa_record_count = 0; 301 int instance_count = 0; 302 int matter_host_count = 0; 303 int hap_host_count = 0; 304 int64_t now = ioloop_timenow(); 305 static int last_num_push_sessions; 306 static int last_dp_num_outstanding_queries; 307 static int last_num_push_sessions_dropped_for_load; 308 static int last_num_queries_dropped_for_load; 309 310 for (adv_host_t *hp = server_state->hosts; hp != NULL; hp = hp->next) { 311 if (hp->removed) { 312 continue; 313 } 314 host_count++; 315 int expiry; 316 if (hp->lease_expiry < now) { 317 expiry = -1; 318 } else { 319 expiry = (int)((hp->lease_expiry - now) / 1000); // This should never be >MAXINT 320 } 321 if (full) { 322 INFO("host " PRI_S_SRP " key_id %xu stable %" PRIx64 " lease %d key_lease %d expiry %d" PUB_S_SRP PUB_S_SRP, 323 hp->name, hp->key_id, hp->server_stable_id, hp->lease_interval, hp->key_lease, expiry, 324 hp->removed ? " removed" : "", hp->update_pending ? " update-pending" : ""); 325 } 326 if (hp->addresses != NULL) { 327 for (int i = 0; i < hp->addresses->num; i++) { 328 if (hp->addresses->vec[i] != NULL) { 329 adv_record_t *record = hp->addresses->vec[i]; 330 if (record->rrtype == dns_rrtype_a) { 331 if (full) { 332 IPv4_ADDR_GEN_SRP(record->rdata, addr_buf); 333 INFO(" IN A " PRI_IPv4_ADDR_SRP PRI_S_SRP, IPv4_ADDR_PARAM_SRP(record->rdata, addr_buf), 334 record->shared_txn == (intptr_t)server_state->shared_registration_txn ? " live" : ""); 335 } 336 a_record_count++; 337 } else if (record->rrtype == dns_rrtype_aaaa) { 338 if (full) { 339 IPv6_ADDR_GEN_SRP((const uint8_t *)record->rdata, addr_buf); 340 INFO(" IN AAAA " PRI_IPv6_ADDR_SRP PRI_S_SRP, IPv6_ADDR_PARAM_SRP(record->rdata, addr_buf), 341 record->shared_txn == (intptr_t)server_state->shared_registration_txn ? " live" : ""); 342 } 343 aaaa_record_count++; 344 } 345 } 346 } 347 } 348 bool matter_instance_present = false, hap_instance_present = false; 349 if (hp->instances != NULL) { 350 for (int i = 0; i < hp->instances->num; i++) { 351 adv_instance_t *instance = hp->instances->vec[i]; 352 if (instance != NULL) { 353 if (full) { 354 char txt_buf[DNS_DATA_SIZE]; 355 if (instance->txt_data != NULL) { 356 dns_txt_data_print(txt_buf, DNS_DATA_SIZE, instance->txt_length, instance->txt_data); 357 } else { 358 txt_buf[0] = 0; 359 } 360 const char *status = "removed"; 361 if (!instance->removed) { 362 if (instance->txn == NULL) { 363 status = "unregistered"; 364 } else if (instance->shared_txn != (intptr_t)server_state->shared_registration_txn) { 365 status = "stale"; 366 } else { 367 status = "live"; 368 } 369 } 370 INFO(" " PUB_S_SRP " instance " PRI_S_SRP " " PRI_S_SRP " %d (" PRI_S_SRP ")", 371 status, instance->instance_name, instance->service_type, instance->port, txt_buf); 372 } 373 if (!instance->removed) { 374 instance_count++; 375 if (instance->service_type != NULL) { 376 const char matter_prefix[] = "_matter"; 377 const char hap_prefix[] = "_hap._udp"; 378 if (!strncmp(instance->service_type, matter_prefix, sizeof(matter_prefix) - 1)) { 379 matter_instance_present = true; 380 } else if (!strncmp(instance->service_type, hap_prefix, sizeof(hap_prefix) - 1)) { 381 hap_instance_present = true; 382 } 383 } 384 } 385 } 386 } 387 } 388 if (matter_instance_present) { 389 matter_host_count++; 390 } else if (hap_instance_present) { // If both, only count matter. 391 hap_host_count++; 392 } 393 } 394 INFO(PUB_S_SRP "%d hosts (%d matter, %d hap), %d instances, %d a records, %d aaaa records at %.6lf", 395 periodic ? "" : "after update, ", host_count, matter_host_count, hap_host_count, instance_count, a_record_count, 396 aaaa_record_count, srp_fractional_time()); 397 398 #if STUB_ROUTER 399 route_state_t *route_state = server_state->route_state; 400 if (route_state) { 401 SEGMENTED_IPv6_ADDR_GEN_SRP(&route_state->srp_listener_ip_address, addr_buf); 402 // do we have an SRP listener? 403 if (route_state->srp_listener != NULL) { 404 INFO("have SRP listener on " PRI_SEGMENTED_IPv6_ADDR_SRP "/%d", 405 SEGMENTED_IPv6_ADDR_PARAM_SRP(&route_state->srp_listener_ip_address, addr_buf), 406 route_state->srp_service_listen_port); 407 } else { 408 INFO("no SRP listener"); 409 } 410 411 // are we publishing anycast services? 412 INFO(PUB_S_SRP "advertising anycast service", route_state->advertising_srp_anycast_service ? "" : "not "); 413 414 // are we publishing unicast service? 415 if (route_state->advertising_srp_unicast_service) { 416 INFO("advertising unicast service on " PRI_SEGMENTED_IPv6_ADDR_SRP "/%d", 417 SEGMENTED_IPv6_ADDR_PARAM_SRP(&route_state->srp_listener_ip_address, addr_buf), 418 route_state->srp_service_listen_port); 419 } else { 420 INFO("not advertising unicast service"); 421 } 422 423 // what SRP replication peers do we see? and how many are we actively connected to? 424 srpl_dump_connection_states(server_state); 425 426 // are we publishing OMR prefix? 427 if (route_state->omr_publisher != NULL && 428 omr_publisher_publishing_prefix(route_state->omr_publisher)) 429 { 430 omr_prefix_t *prefix = omr_publisher_published_prefix_get(route_state->omr_publisher); 431 SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, prefix_buf); 432 INFO("publishing " PUB_S_SRP " OMR prefix " PRI_SEGMENTED_IPv6_ADDR_SRP "/%d", 433 omr_publisher_publishing_dhcp(route_state->omr_publisher) ? "dhcp" : "ula", 434 SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_buf), 435 prefix->prefix_length); 436 } else { 437 INFO("not publishing OMR prefix"); 438 } 439 440 // what prefixes do we see on Thread? 441 if (route_state->omr_watcher != NULL) { 442 omr_prefix_t *thread_prefixes = omr_watcher_prefixes_get(route_state->omr_watcher); 443 for (struct omr_prefix *prefix = thread_prefixes; prefix != NULL; prefix = prefix->next) { 444 SEGMENTED_IPv6_ADDR_GEN_SRP(prefix->prefix.s6_addr, prefix_buf); 445 INFO("OMR prefix " PRI_SEGMENTED_IPv6_ADDR_SRP "/%d seen on thread" PUB_S_SRP PUB_S_SRP 446 PUB_S_SRP, SEGMENTED_IPv6_ADDR_PARAM_SRP(prefix->prefix.s6_addr, prefix_buf), 447 prefix->prefix_length, prefix->user ? " (user)" : "", prefix->ncp ? " (ncp)": "", 448 prefix->stable ? " (stable)" : ""); 449 } 450 } 451 452 // are we publishing infrastructure prefix? 453 interface_t *interface; 454 bool is_advertising = false; 455 for (interface = route_state->interfaces; interface; interface = interface->next) { 456 if (interface->our_prefix_advertised) { 457 SEGMENTED_IPv6_ADDR_GEN_SRP(interface->ipv6_prefix.s6_addr, ipv6_prefix_buf); 458 INFO("advertising infrastructure prefix " PRI_SEGMENTED_IPv6_ADDR_SRP " on " PUB_S_SRP, 459 SEGMENTED_IPv6_ADDR_PARAM_SRP(interface->ipv6_prefix.s6_addr, ipv6_prefix_buf), 460 interface->name); 461 is_advertising = true; 462 } 463 } 464 if (!is_advertising) { 465 INFO("not advertising infrastructure prefix"); 466 } 467 } 468 #endif // STUB_ROUTER 469 470 // how many DNS push queries added since last state dump? 471 // how many DNS queries seen since last state dump? 472 // how many DNS queries dropped for load? 473 // how many DNS Push connections dropped for load? 474 INFO("%d push sessions and %d queries added, %d push sessions and %d queries dropped for load", 475 num_push_sessions - last_num_push_sessions, 476 dp_num_outstanding_queries - last_dp_num_outstanding_queries, 477 num_push_sessions_dropped_for_load - last_num_push_sessions_dropped_for_load, 478 num_queries_dropped_for_load - last_num_queries_dropped_for_load); 479 last_num_push_sessions = num_push_sessions; 480 last_dp_num_outstanding_queries = dp_num_outstanding_queries; 481 last_num_push_sessions_dropped_for_load = num_push_sessions_dropped_for_load; 482 last_num_queries_dropped_for_load = num_queries_dropped_for_load; 483 } 484 485 // We call advertise_finished when a client request has finished, successfully or otherwise. 486 #if SRP_FEATURE_REPLICATION 487 static bool 488 srp_replication_advertise_finished(adv_host_t *host, char *hostname, srp_server_t *server_state, 489 srpl_connection_t *srpl_connection, comm_t *connection, int rcode, bool last) 490 { 491 if (server_state->srp_replication_enabled) { 492 INFO("hostname = " PRI_S_SRP " host = %p server_state = %p srpl_connection = %p connection = %p rcode = " 493 PUB_S_SRP, hostname, host, server_state, srpl_connection, connection, dns_rcode_name(rcode)); 494 if (connection == NULL) { 495 // connection is the SRP client connection on which an update arrived. If it's null, 496 // this is an SRP replication update, not an actual client we're communicating with. 497 INFO("replication advertise finished: host " PRI_S_SRP ": rcode = " PUB_S_SRP, 498 hostname, dns_rcode_name(rcode)); 499 if (srpl_connection != NULL) { 500 if (last) { 501 srpl_advertise_finished_event_send(hostname, rcode, server_state); 502 #ifdef SRP_TEST_SERVER 503 if (srpl_connection->srpl_advertise_finished_callback != NULL) { 504 srpl_connection->srpl_advertise_finished_callback(srpl_connection); 505 } 506 #endif 507 } 508 509 if (host != NULL && host->srpl_connection != NULL) { 510 if (rcode == dns_rcode_noerror) { 511 host->update_server_id = host->srpl_connection->remote_partner_id; 512 host->server_stable_id = host->srpl_connection->stashed_host.server_stable_id; 513 INFO("replicated host " PRI_S_SRP " server stable ID %" PRIx64, hostname, host->server_stable_id); 514 } 515 516 // This is the safest place to clear this pointer--we do not want the srpl_connection pointer to not 517 // get reset because of some weird sequence of events, leaving this host unable to be further updated 518 // or worse. 519 srpl_connection_release(host->srpl_connection); 520 host->srpl_connection = NULL; 521 } else { 522 if (host != NULL) { 523 INFO("disconnected host " PRI_S_SRP " server stable ID %" PRIx64, hostname, host->server_stable_id); 524 } 525 } 526 } else { 527 if (host != NULL) { 528 INFO("context-free host " PRI_S_SRP " server stable ID %" PRIx64, hostname, host->server_stable_id); 529 } 530 } 531 return true; 532 } 533 534 if (host != NULL) { 535 if (rcode == dns_rcode_noerror) { 536 memcpy(&host->server_stable_id, &host->server_state->ula_prefix, sizeof(host->server_stable_id)); 537 } 538 INFO("local host " PRI_S_SRP " server stable ID %" PRIx64, hostname, host->server_stable_id); 539 srpl_srp_client_update_finished_event_send(host, rcode); 540 host->update_server_id = 0; 541 } 542 } else 543 { 544 if (host != NULL && host->server_state != NULL) { 545 memcpy(&host->server_stable_id, &host->server_state->ula_prefix, sizeof(host->server_stable_id)); 546 host->update_server_id = 0; 547 } 548 } 549 return false; 550 } 551 #endif // SRP_FEATURE_REPLICATION 552 553 static void 554 srp_ml_eid_mapping_callback(void *context, cti_status_t status) 555 { 556 adv_record_t *arec = context; 557 adv_host_t *host = arec->host; 558 SEGMENTED_IPv6_ADDR_GEN_SRP(arec->rdata, omr_buf); 559 if (status == kCTIStatus_NoError) { 560 if (host == NULL) { 561 INFO("mapping for address " PRI_SEGMENTED_IPv6_ADDR_SRP " was orphaned.", 562 SEGMENTED_IPv6_ADDR_PARAM_SRP(arec->rdata, omr_buf)); 563 } else { 564 INFO("mapping for address " PRI_SEGMENTED_IPv6_ADDR_SRP " to host " PRI_S_SRP " succeeded", 565 SEGMENTED_IPv6_ADDR_PARAM_SRP(arec->rdata, omr_buf), host->name); 566 } 567 } else { 568 if (host == NULL) { 569 INFO("orphaned mapping for address " PRI_SEGMENTED_IPv6_ADDR_SRP " failed: %d", 570 SEGMENTED_IPv6_ADDR_PARAM_SRP(arec->rdata, omr_buf), status); 571 } else { 572 INFO("mapping for address " PRI_SEGMENTED_IPv6_ADDR_SRP " to host " PRI_S_SRP " failed: %d", 573 SEGMENTED_IPv6_ADDR_PARAM_SRP(arec->rdata, omr_buf), host->name, status); 574 } 575 } 576 RELEASE_HERE(arec, adv_record); 577 } 578 579 // We call advertise_finished when a client request has finished, successfully or otherwise. 580 static void 581 advertise_finished(adv_host_t *host, char *hostname, srp_server_t *server_state, srpl_connection_t *srpl_connection, 582 comm_t *connection, message_t *message, int rcode, client_update_t *client, bool send_response, 583 bool last) 584 { 585 struct iovec iov; 586 dns_wire_t response; 587 588 #if SRP_FEATURE_REPLICATION 589 if (srp_replication_advertise_finished(host, hostname, server_state, srpl_connection, connection, rcode, last)) { 590 return; 591 } 592 #else 593 (void)host; 594 (void)server_state; 595 (void)srpl_connection; 596 (void)last; 597 #endif // SRP_FEATURE_REPLICATION 598 INFO("host " PRI_S_SRP ": rcode = " PUB_S_SRP ", lease = %d, key_lease = %d connection = %p", hostname, dns_rcode_name(rcode), 599 client ? client->host_lease : 0, client ? client->key_lease : 0, connection); 600 601 // This can happen if we turn off replication in the middle of an update of a replicated host. 602 if (connection == NULL) { 603 return; 604 } 605 if (!send_response) { 606 INFO("not sending response."); 607 return; 608 } 609 610 memset(&response, 0, DNS_HEADER_SIZE); 611 response.id = message->wire.id; 612 response.bitfield = message->wire.bitfield; 613 dns_rcode_set(&response, rcode); 614 dns_qr_set(&response, dns_qr_response); 615 616 iov.iov_base = &response; 617 // If this was a successful update, send back the lease time, which will either 618 // be what the client asked for, or a shorter lease, depending on what limit has 619 // been set. 620 if (client != NULL) { 621 dns_towire_state_t towire; 622 memset(&towire, 0, sizeof towire); 623 towire.p = &response.data[0]; // We start storing RR data here. 624 towire.lim = &response.data[DNS_DATA_SIZE]; // This is the limit to how much we can store. 625 towire.message = &response; 626 response.qdcount = 0; 627 response.ancount = 0; 628 response.nscount = 0; 629 response.arcount = htons(1); 630 dns_edns0_header_to_wire(&towire, DNS_MAX_UDP_PAYLOAD, 0, 0, 1); 631 dns_rdlength_begin(&towire); 632 dns_u16_to_wire(&towire, dns_opt_update_lease); // OPTION-CODE 633 dns_edns0_option_begin(&towire); // OPTION-LENGTH 634 dns_u32_to_wire(&towire, client->host_lease); // LEASE (e.g. 1 hour) 635 dns_u32_to_wire(&towire, client->key_lease); // KEY-LEASE (7 days) 636 dns_edns0_option_end(&towire); // Now we know OPTION-LENGTH 637 dns_rdlength_end(&towire); 638 // It should not be possible for this to happen; if it does, the client 639 // might not renew its lease in a timely manner. 640 if (towire.error) { 641 ERROR("unexpectedly failed to send EDNS0 lease option."); 642 iov.iov_len = DNS_HEADER_SIZE; 643 } else { 644 iov.iov_len = towire.p - (uint8_t *)&response; 645 } 646 } else { 647 iov.iov_len = DNS_HEADER_SIZE; 648 } 649 ioloop_send_message(connection, message, &iov, 1); 650 } 651 652 static void 653 retry_callback(void *context) 654 { 655 adv_host_t *host = (adv_host_t *)context; 656 if (host->update == NULL) { 657 update_from_host(host); 658 } else { 659 start_host_update(host); 660 } 661 } 662 663 static void 664 srp_adv_host_context_release(void *context) 665 { 666 adv_host_t *host = context; 667 RELEASE_HERE(host, adv_host); 668 } 669 670 static void 671 wait_retry(adv_host_t *host) 672 { 673 int64_t now = ioloop_timenow(); 674 #define MIN_HOST_RETRY_INTERVAL 15 675 #define MAX_HOST_RETRY_INTERVAL 120 676 // If we've been retrying long enough for the lease to expire, give up. 677 if (!host->lease_expiry || host->lease_expiry < now) { 678 INFO("host lease has expired, not retrying: lease_expiry = %" PRId64 679 " now = %" PRId64 " difference = %" PRId64, host->lease_expiry, now, host->lease_expiry - now); 680 delete_host(host); 681 return; 682 } 683 if (host->retry_interval == 0) { 684 host->retry_interval = MIN_HOST_RETRY_INTERVAL; 685 } else if (host->retry_interval < MAX_HOST_RETRY_INTERVAL) { 686 host->retry_interval *= 2; 687 } 688 INFO("waiting %d seconds...", host->retry_interval); 689 ioloop_add_wake_event(host->retry_wakeup, host, retry_callback, srp_adv_host_context_release, host->retry_interval * 1000); 690 RETAIN_HERE(host, adv_host); 691 } 692 693 static void 694 shared_registration_fail(void *context, int UNUSED status) 695 { 696 srp_server_t *server_state = context; 697 dnssd_txn_t *txn = server_state->shared_registration_txn; 698 DNSServiceRef sdref = txn == NULL ? NULL : txn->sdref; 699 INFO("shared registration failed: txn %p sdref %p", server_state->shared_registration_txn, sdref); 700 if (txn != NULL) { 701 ioloop_dnssd_txn_cancel(txn); 702 ioloop_dnssd_txn_release(txn); 703 server_state->shared_registration_txn = NULL; 704 } 705 } 706 707 bool 708 srp_mdns_shared_registration_txn_setup(srp_server_t *server_state) 709 { 710 if (server_state->shared_registration_txn == NULL) { 711 DNSServiceRef sdref; 712 int err = DNSServiceCreateConnection(&sdref); 713 if (err != kDNSServiceErr_NoError) { 714 return false; 715 } 716 server_state->shared_registration_txn = ioloop_dnssd_txn_add(sdref, server_state, NULL, shared_registration_fail); 717 if (server_state->shared_registration_txn == NULL) { 718 ERROR("unable to create shared connection for registration."); 719 dns_service_op_not_to_be_freed = NULL; 720 DNSServiceRefDeallocate(sdref); 721 return false; 722 } 723 dns_service_op_not_to_be_freed = server_state->shared_registration_txn->sdref; 724 INFO("server_state->shared_registration_txn = %p sdref = %p", server_state->shared_registration_txn, sdref); 725 } 726 return true; 727 } 728 729 static void 730 record_txn_forget(adv_record_t *record, intptr_t affected_service_pointer, 731 const char *parent_type, const void *parent_pointer, const char *hostname) 732 { 733 if (record == NULL) { 734 return; 735 } 736 if (record->rref != NULL && record->shared_txn == affected_service_pointer) { 737 INFO("forgetting rref %p on " PUB_S_SRP " %p " PRI_S_SRP, record->rref, parent_type, parent_pointer, hostname); 738 record->rref = NULL; 739 } 740 } 741 742 static void 743 record_vec_txns_forget(adv_record_vec_t *records, intptr_t affected_service_pointer, 744 const char *parent_type, const void *parent_pointer, const char *hostname) 745 { 746 if (records == NULL) { 747 return; 748 } 749 for (int i = 0; i < records->num; i++) { 750 record_txn_forget(records->vec[i], affected_service_pointer, parent_type, parent_pointer, hostname); 751 } 752 } 753 754 static void 755 instance_vec_txns_forget(adv_instance_vec_t *instances, intptr_t affected_service_pointer, 756 const char *parent_type, const void *parent_pointer, const char *hostname) 757 { 758 if (instances == NULL) { 759 return; 760 } 761 for (int i = 0; i < instances->num; i++) { 762 adv_instance_t *instance = instances->vec[i]; 763 if (instance != NULL && instance->txn != NULL && instance->txn->sdref != NULL && 764 instance->shared_txn == affected_service_pointer) 765 { 766 INFO("forgetting sdref %p on " PUB_S_SRP " %p " PRI_S_SRP " instance " PRI_S_SRP " . " PRI_S_SRP, 767 instance->txn->sdref, 768 parent_type, parent_pointer, hostname, instance->instance_name, instance->service_type); 769 instance->txn->sdref = NULL; 770 } 771 } 772 } 773 774 static void 775 host_txns_forget(adv_host_t *host, intptr_t affected_service_pointer) 776 { 777 // We call this when the shared transaction fails for some reason. That failure invalidates all the subsidiary 778 // RecordRefs and ServiceRefs hanging off of the shared transaction; to avoid holding on to invalid pointers, 779 // we traverse the registration database and NULL out all the rrefs and sdrefs that relate to the subsidiary 780 // service pointer. 781 record_vec_txns_forget(host->addresses, affected_service_pointer, "host", host, host->name); 782 instance_vec_txns_forget(host->instances, affected_service_pointer, "host", host, host->name); 783 record_txn_forget(host->key_record, affected_service_pointer, "host key", host, host->name); 784 if (host->update != NULL) { 785 record_vec_txns_forget(host->update->remove_addresses, affected_service_pointer, 786 "host update remove addresses", host->update, host->name); 787 record_vec_txns_forget(host->update->add_addresses, affected_service_pointer, 788 "host update add addresses", host->update, host->name); 789 record_txn_forget(host->update->key, affected_service_pointer, "host update key", host->update, host->name); 790 instance_vec_txns_forget(host->update->update_instances, affected_service_pointer, 791 "host update update instances", host->update, host->name); 792 instance_vec_txns_forget(host->update->remove_instances, affected_service_pointer, 793 "host update remove instances", host->update, host->name); 794 instance_vec_txns_forget(host->update->renew_instances, affected_service_pointer, 795 "host update renew instances", host->update, host->name); 796 instance_vec_txns_forget(host->update->add_instances, affected_service_pointer, 797 "host update add instances", host->update, host->name); 798 } 799 } 800 801 static void 802 service_disconnected(srp_server_t *server_state, intptr_t service_pointer) 803 { 804 if (service_pointer == (intptr_t)server_state->shared_registration_txn && 805 server_state->shared_registration_txn != NULL) 806 { 807 INFO("server_state->shared_registration_txn = %p sdref = %p", 808 server_state->shared_registration_txn, server_state->shared_registration_txn->sdref); 809 // For every host that's active right now that has transactions on this shared transaction, forget all those 810 // transactions. The txn_cancel following this will free all of the memory in the client stub. 811 for (adv_host_t *host = server_state->hosts; host != NULL; host = host->next) { 812 host_txns_forget(host, service_pointer); 813 } 814 dns_service_op_not_to_be_freed = NULL; 815 ioloop_dnssd_txn_cancel(server_state->shared_registration_txn); 816 ioloop_dnssd_txn_release(server_state->shared_registration_txn); 817 server_state->shared_registration_txn = NULL; 818 } 819 } 820 821 static void 822 adv_record_vec_remove_update(adv_record_vec_t *vec, adv_update_t *update) 823 { 824 for (int i = 0; i < vec->num; i++) { 825 if (vec->vec[i] != NULL && vec->vec[i]->update != NULL && vec->vec[i]->update == update) { 826 RELEASE_HERE(vec->vec[i]->update, adv_update); 827 vec->vec[i]->update = NULL; 828 } 829 } 830 } 831 832 static void 833 adv_instance_vec_remove_update(adv_instance_vec_t *vec, adv_update_t *update) 834 { 835 for (int i = 0; i < vec->num; i++) { 836 if (vec->vec[i] != NULL && vec->vec[i]->update != NULL && vec->vec[i]->update == update) { 837 RELEASE_HERE(vec->vec[i]->update, adv_update); 838 vec->vec[i]->update = NULL; 839 } 840 } 841 } 842 843 static void 844 adv_instances_cancel(adv_instance_vec_t *instances) 845 { 846 for (int i = 0; i < instances->num; i++) { 847 adv_instance_t *instance = instances->vec[i]; 848 if (instance != NULL) { 849 if (instance->txn != NULL) { 850 ioloop_dnssd_txn_cancel_srp(instance->host->server_state, instance->txn); 851 ioloop_dnssd_txn_release(instance->txn); 852 instance->txn = NULL; 853 } 854 if (instance->retry_wakeup != NULL) { 855 ioloop_cancel_wake_event(instance->retry_wakeup); 856 ioloop_wakeup_release(instance->retry_wakeup); 857 instance->retry_wakeup = NULL; 858 } 859 } 860 } 861 } 862 863 static void 864 adv_update_free_instance_vectors(adv_update_t *NONNULL update) 865 { 866 if (update->update_instances != NULL) { 867 adv_instance_vec_remove_update(update->update_instances, update); 868 adv_instances_cancel(update->update_instances); 869 RELEASE_HERE(update->update_instances, adv_instance_vec); 870 update->update_instances = NULL; 871 } 872 if (update->remove_instances != NULL) { 873 adv_instance_vec_remove_update(update->remove_instances, update); 874 RELEASE_HERE(update->remove_instances, adv_instance_vec); 875 update->remove_instances = NULL; 876 } 877 if (update->renew_instances != NULL) { 878 adv_instance_vec_remove_update(update->renew_instances, update); 879 RELEASE_HERE(update->renew_instances, adv_instance_vec); 880 update->renew_instances = NULL; 881 } 882 if (update->add_instances != NULL) { 883 adv_instance_vec_remove_update(update->add_instances, update); 884 adv_instances_cancel(update->add_instances); 885 RELEASE_HERE(update->add_instances, adv_instance_vec); 886 update->add_instances = NULL; 887 } 888 } 889 890 static void 891 adv_update_finalize(adv_update_t *NONNULL update) 892 { 893 if (update->host != NULL) { 894 RELEASE_HERE(update->host, adv_host); 895 } 896 897 if (update->client != NULL) { 898 srp_parse_client_updates_free(update->client); 899 update->client = NULL; 900 } 901 902 if (update->remove_addresses != NULL) { 903 adv_record_vec_remove_update(update->remove_addresses, update); 904 RELEASE_HERE(update->remove_addresses, adv_record_vec); 905 } 906 907 if (update->add_addresses != NULL) { 908 adv_record_vec_remove_update(update->add_addresses, update); 909 RELEASE_HERE(update->add_addresses, adv_record_vec); 910 } 911 912 adv_update_free_instance_vectors(update); 913 if (update->key != NULL) { 914 RELEASE_HERE(update->key, adv_record); 915 } 916 free(update); 917 } 918 919 static void 920 adv_update_cancel(adv_update_t *NONNULL update) 921 { 922 adv_host_t *host = update->host; 923 bool faulted = false; 924 925 RETAIN_HERE(update, adv_update); // ensure that update remains valid for the duration of this function call. 926 927 if (host != NULL) { 928 RETAIN_HERE(host, adv_host); // in case the update is holding the last reference to the host 929 RELEASE_HERE(update->host, adv_host); 930 update->host = NULL; 931 932 INFO("cancelling update %p for host " PRI_S_SRP, update, host->registered_name); 933 934 if (host->update == update) { 935 RELEASE_HERE(host->update, adv_update); 936 host->update = NULL; 937 } 938 939 // In case we needed to re-register some of the host's addresses, remove the update pointer from them. 940 if (host->addresses != NULL) { 941 for (int i = 0; i < host->addresses->num; i++) { 942 adv_record_t *record = host->addresses->vec[i]; 943 if (record->update == update) { 944 RELEASE_HERE(host->addresses->vec[i]->update, adv_update); 945 record->update = NULL; 946 } 947 } 948 } 949 } else { 950 INFO("canceling update with no host."); 951 } 952 953 adv_update_free_instance_vectors(update); 954 955 if (update->add_addresses != NULL) { 956 // Any record that we attempted to add as part of this update should be removed because the update failed. 957 for (int i = 0; i < update->add_addresses->num; i++) { 958 adv_record_t *record = update->add_addresses->vec[i]; 959 if (record != NULL) { 960 if (host == NULL) { 961 if (!faulted) { 962 FAULT("unable to clean up host address registration because host object is gone from update."); 963 faulted = true; 964 } 965 } else { 966 if (record->rref != NULL) { 967 srp_mdns_shared_record_remove(host->server_state, record); 968 } 969 } 970 } 971 } 972 adv_record_vec_remove_update(update->add_addresses, update); 973 RELEASE_HERE(update->add_addresses, adv_record_vec); 974 update->add_addresses = NULL; 975 } 976 977 if (update->remove_addresses != NULL) { 978 adv_record_vec_remove_update(update->remove_addresses, update); 979 RELEASE_HERE(update->remove_addresses, adv_record_vec); 980 update->remove_addresses = NULL; 981 } 982 983 if (update->key != NULL) { 984 if (update->key->update != NULL) { 985 RELEASE_HERE(update->key->update, adv_update); 986 update->key->update = NULL; 987 } 988 // Any record that we attempted to add as part of this update should be removed because the update failed. 989 if (update->key->rref != NULL) { 990 if (host == NULL) { 991 if (!faulted) { 992 FAULT("unable to clean up host key registration because host object is gone from update."); 993 faulted = true; 994 } 995 } else { 996 srp_mdns_shared_record_remove(host->server_state, update->key); 997 } 998 } 999 RELEASE_HERE(update->key, adv_record); 1000 update->key = NULL; 1001 } 1002 if (host != NULL) { 1003 RELEASE_HERE(host, adv_host); 1004 } 1005 RELEASE_HERE(update, adv_update); 1006 } 1007 1008 static void 1009 update_failed(adv_update_t *update, int rcode, bool expire, bool send_response) 1010 { 1011 // Retain the update for the life of this function call, since we may well release the last other reference to it. 1012 RETAIN_HERE(update, adv_update); 1013 1014 // If we still have a client waiting for the result of this update, tell it we failed. 1015 // Updates that have never worked are abandoned when the client is notified. 1016 if (update->client != NULL) { 1017 adv_host_t *host = update->host; 1018 client_update_t *client = update->client; 1019 adv_update_cancel(update); 1020 advertise_finished(host, host->name, host->server_state, host->srpl_connection, 1021 client->connection, client->message, rcode, NULL, send_response, true); 1022 srp_parse_client_updates_free(client); 1023 update->client = NULL; 1024 // If we don't have a lease yet, or the old lease has expired, remove the host. 1025 // However, if the expire flag is false, it's because we're already finalizing the 1026 // host, so doing an expiry here would double free the host. In this case, we leave 1027 // it to the caller to do the expiry (really, to finalize the host). 1028 if (expire && (host->lease_expiry == 0 || host->lease_expiry <= ioloop_timenow())) { 1029 delete_host(host); 1030 } 1031 RELEASE_HERE(update, adv_update); 1032 return; 1033 } 1034 adv_update_cancel(update); 1035 RELEASE_HERE(update, adv_update); 1036 } 1037 1038 static void 1039 host_addr_free(adv_host_t *host) 1040 { 1041 int i; 1042 1043 // We can't actually deallocate the address vector until the host object is collected, so deallocate the address 1044 // records. 1045 if (host->addresses != NULL) { 1046 for (i = 0; i < host->addresses->num; i++) { 1047 if (host->addresses->vec[i] != NULL) { 1048 INFO("Removing AAAA record for " PRI_S_SRP, host->registered_name); 1049 srp_mdns_shared_record_remove(host->server_state, host->addresses->vec[i]); 1050 RELEASE_HERE(host->addresses->vec[i], adv_record); 1051 host->addresses->vec[i] = NULL; 1052 } 1053 } 1054 host->addresses->num = 0; 1055 } 1056 } 1057 1058 // Free just those parts that are no longer needed when the host is no longer valid. 1059 static void 1060 host_invalidate(adv_host_t *host) 1061 { 1062 // Get rid of the retry wake event. 1063 if (host->retry_wakeup != NULL) { 1064 ioloop_cancel_wake_event(host->retry_wakeup); 1065 } 1066 if (host->re_register_wakeup != NULL) { 1067 ioloop_cancel_wake_event(host->re_register_wakeup); 1068 } 1069 1070 // Remove the address records. 1071 host_addr_free(host); 1072 1073 // Remove the services. 1074 if (host->instances != NULL) { 1075 adv_instances_cancel(host->instances); 1076 RELEASE_HERE(host->instances, adv_instance_vec); 1077 host->instances = NULL; 1078 } 1079 1080 if (host->update != NULL) { 1081 RELEASE_HERE(host->update, adv_update); 1082 host->update = NULL; 1083 } 1084 if (host->key_record != NULL) { 1085 srp_mdns_shared_record_remove(host->server_state, host->key_record); 1086 RELEASE_HERE(host->key_record, adv_record); 1087 host->key_record = NULL; 1088 } 1089 host->update = NULL; 1090 host->removed = true; 1091 } 1092 1093 // Free everything associated with the host, including the host object. 1094 static void 1095 adv_host_finalize(adv_host_t *host) 1096 { 1097 // Just in case this hasn't happened yet, free the non-identifying host data and cancel any outstanding 1098 // transactions. 1099 host_invalidate(host); 1100 1101 if (host->addresses != NULL) { 1102 RELEASE_HERE(host->addresses, adv_record_vec); 1103 host->addresses = NULL; 1104 } 1105 1106 if (host->key_rdata != NULL) { 1107 free(host->key_rdata); 1108 host->key_rdata = NULL; 1109 } 1110 if (host->key_record != NULL) { 1111 RELEASE_HERE(host->key_record, adv_record); 1112 host->key_record = NULL; 1113 } 1114 1115 if (host->message != NULL) { 1116 ioloop_message_release(host->message); 1117 host->message = NULL; 1118 } 1119 1120 // We definitely don't want a lease callback at this point. 1121 if (host->lease_wakeup != NULL) { 1122 ioloop_cancel_wake_event(host->lease_wakeup); 1123 ioloop_wakeup_release(host->lease_wakeup); 1124 host->lease_wakeup = NULL; // this will make us crash if we use it after free 1125 } 1126 // Get rid of the retry wake event. 1127 if (host->retry_wakeup != NULL) { 1128 ioloop_cancel_wake_event(host->retry_wakeup); 1129 ioloop_wakeup_release(host->retry_wakeup); 1130 host->retry_wakeup = NULL; 1131 } 1132 1133 if (host->re_register_wakeup != NULL) { 1134 ioloop_cancel_wake_event(host->re_register_wakeup); 1135 ioloop_wakeup_release(host->re_register_wakeup); 1136 host->re_register_wakeup = NULL; 1137 } 1138 INFO("removed " PRI_S_SRP ", key_id %x", host->name ? host->name : "<null>", host->key_id); 1139 1140 // In the default case, host->name and host->registered_name point to the same memory: we don't want a double free. 1141 if (host->registered_name == host->name) { 1142 host->registered_name = NULL; 1143 } 1144 if (host->name != NULL) { 1145 free(host->name); 1146 } 1147 if (host->registered_name != NULL) { 1148 free(host->registered_name); 1149 } 1150 free(host); 1151 } 1152 1153 void 1154 srp_adv_host_release_(adv_host_t *host, const char *file, int line) 1155 { 1156 RELEASE(host, adv_host); 1157 } 1158 1159 void 1160 srp_adv_host_retain_(adv_host_t *host, const char *file, int line) 1161 { 1162 RETAIN(host, adv_host); 1163 } 1164 1165 bool 1166 srp_adv_host_valid(adv_host_t *host) 1167 { 1168 // If the host has been removed, it's not valid. 1169 if (host->removed) { 1170 return false; 1171 } 1172 // If there is no key data, the host is invalid. 1173 if (host->key_rdata == NULL) { 1174 return false; 1175 } 1176 return true; 1177 } 1178 1179 int 1180 srp_current_valid_host_count(srp_server_t *server_state) 1181 { 1182 adv_host_t *host; 1183 int count = 0; 1184 for (host = server_state->hosts; host; host = host->next) { 1185 if (srp_adv_host_valid(host)) { 1186 count++; 1187 } 1188 } 1189 return count; 1190 } 1191 1192 int 1193 srp_hosts_to_array(srp_server_t *server_state, adv_host_t **host_array, int max) 1194 { 1195 int count = 0; 1196 for (adv_host_t *host = server_state->hosts; count < max && host != NULL; host = host->next) { 1197 if (srp_adv_host_valid(host)) { 1198 host_array[count] = host; 1199 RETAIN_HERE(host_array[count], adv_host); 1200 count++; 1201 } 1202 } 1203 return count; 1204 } 1205 1206 adv_host_t * 1207 srp_adv_host_copy_(srp_server_t *server_state, dns_name_t *name, const char *file, int line) 1208 { 1209 for (adv_host_t *host = server_state->hosts; host; host = host->next) { 1210 if (srp_adv_host_valid(host) && dns_names_equal_text(name, host->name)) { 1211 RETAIN(host, adv_host); 1212 return host; 1213 } 1214 } 1215 return NULL; 1216 } 1217 1218 static void 1219 host_remove(adv_host_t *host) 1220 { 1221 // This host is no longer valid. Get rid of the associated transactions and other stuff that's not required to 1222 // identify it, and then release the host list reference to it. 1223 host_invalidate(host); 1224 // Note that while adv_host_finalize calls host_invalidate, adv_host_finalize won't necessarily be called here because there 1225 // may be outstanding references on the host. It's okay to call host_invalidate twice--the second time it should be 1226 // a no-op. 1227 RELEASE_HERE(host, adv_host); 1228 } 1229 1230 static adv_host_t ** 1231 host_ready(adv_host_t *host) 1232 { 1233 adv_host_t **p_hosts; 1234 1235 // Find the host on the list of hosts. 1236 for (p_hosts = &host->server_state->hosts; *p_hosts != NULL; p_hosts = &(*p_hosts)->next) { 1237 if (*p_hosts == host) { 1238 break; 1239 } 1240 } 1241 if (*p_hosts == NULL) { 1242 ERROR("called with nonexistent host."); 1243 return NULL; 1244 } 1245 1246 // It's possible that we got an update to this host, but haven't processed it yet. In this 1247 // case, we don't want to get rid of the host, but we do want to get rid of it later if the 1248 // update fails. So postpone the removal for a bit. 1249 if (host->update != NULL) { 1250 INFO("reached with pending updates on host " PRI_S_SRP ".", host->registered_name); 1251 ioloop_add_wake_event(host->lease_wakeup, host, lease_callback, srp_adv_host_context_release, 10 * 1000); 1252 RETAIN_HERE(host, adv_host); 1253 host->lease_expiry = ioloop_timenow() + 10 * 1000; // ten seconds 1254 return NULL; 1255 } 1256 1257 return p_hosts; 1258 } 1259 1260 static void 1261 lease_callback(void *context) 1262 { 1263 int64_t now = ioloop_timenow(); 1264 adv_host_t **p_hosts, *host = context; 1265 int i, num_instances = 0; 1266 1267 p_hosts = host_ready(host); 1268 if (p_hosts == NULL) { 1269 INFO("host expired"); 1270 return; 1271 } 1272 1273 INFO("host " PRI_S_SRP, host->name); 1274 1275 // If the host entry lease has expired, any instance leases have also. 1276 if (host->lease_expiry < now) { 1277 delete_host(host); 1278 return; 1279 } 1280 1281 INFO("host " PRI_S_SRP " is still alive", host->name); 1282 1283 if (host->instances == NULL) { 1284 INFO("no instances"); 1285 return; 1286 } 1287 1288 // Find instances that have expired and release them. 1289 for (i = 0; i < host->instances->num; i++) { 1290 adv_instance_t *instance = host->instances->vec[i]; 1291 if (instance == NULL) { 1292 continue; 1293 } 1294 if (instance->lease_expiry < now) { 1295 INFO("host " PRI_S_SRP " instance " PRI_S_SRP "." PRI_S_SRP " has expired", 1296 host->name, instance->instance_name, instance->service_type); 1297 // We have to release the transaction so that we can release the reference the transaction has to the instance. 1298 if (instance->txn != NULL) { 1299 dnssd_txn_t *txn = instance->txn; 1300 instance->txn = NULL; 1301 ioloop_dnssd_txn_release(txn); 1302 } 1303 host->instances->vec[i] = NULL; 1304 RELEASE_HERE(instance, adv_instance); 1305 continue; 1306 } else { 1307 INFO("host " PRI_S_SRP " instance " PRI_S_SRP "." PRI_S_SRP " has not expired", 1308 host->name, instance->instance_name, instance->service_type); 1309 } 1310 num_instances++; 1311 } 1312 1313 int64_t next_lease_expiry = host->lease_expiry; 1314 1315 // Get rid of holes in the host instance vector and compute the next lease callback time 1316 int j = 0; 1317 1318 for (i = 0; i < host->instances->num; i++) { 1319 if (host->instances->vec[i] != NULL) { 1320 adv_instance_t *instance = host->instances->vec[i]; 1321 host->instances->vec[j++] = instance; 1322 if (next_lease_expiry > instance->lease_expiry) { 1323 next_lease_expiry = instance->lease_expiry; 1324 } 1325 } 1326 } 1327 INFO("host " PRI_S_SRP " lost %d instances", host->name, host->instances->num - j); 1328 host->instances->num = j; 1329 1330 // Now set a timer for the next lease expiry event 1331 uint64_t when = next_lease_expiry - now; 1332 if (when > INT32_MAX) { 1333 when = INT32_MAX; 1334 } 1335 1336 ioloop_add_wake_event(host->lease_wakeup, host, lease_callback, srp_adv_host_context_release, (uint32_t)when); 1337 RETAIN_HERE(host, adv_host); 1338 } 1339 1340 // Called when we definitely want to make all the advertisements associated with a host go away. 1341 static void 1342 delete_host(void *context) 1343 { 1344 adv_host_t **p_hosts, *host = context; 1345 1346 1347 p_hosts = host_ready(host); 1348 if (p_hosts == NULL) { 1349 return; 1350 } 1351 1352 INFO("deleting host " PRI_S_SRP, host->name); 1353 1354 // De-link the host. 1355 *p_hosts = host->next; 1356 1357 // Get rid of any transactions attached to the host, any timer events, and any other associated data. 1358 host_remove(host); 1359 } 1360 1361 // We remember the message that produced this instance so that if we get an update that doesn't update everything, 1362 // we know which instances /were/ updated by this particular message. instance->recent_message is a copy of the pointer 1363 // to the message that most recently updated this instance. When we set instance->recent_message, we don't yet know 1364 // if the update is going to succeed; if it fails, we can't have changed update->message. If it succeeds, then when we 1365 // get down to srp_mdns_update_finished, we can compare the message that did the update to instance->recent_message; if they 1366 // are the same, then we set the message on the instance. 1367 // Note that we only set instance->recent_message during register_instance_completion, so there's no timing race that 1368 // could happen as a result of receiving a second update to the same instance before the first has been processed. 1369 static void 1370 set_instance_message(adv_instance_t *instance, message_t *message) 1371 { 1372 if (message != NULL && (ptrdiff_t)message == instance->recent_message) { 1373 if (instance->message != NULL) { 1374 ioloop_message_release(instance->message); 1375 } 1376 instance->message = message; 1377 ioloop_message_retain(instance->message); 1378 instance->recent_message = 0; 1379 } 1380 } 1381 1382 void 1383 srp_mdns_update_finished(adv_update_t *update) 1384 { 1385 adv_host_t *host = update->host; 1386 client_update_t *client = update->client; 1387 int num_addresses = 0; 1388 adv_record_vec_t *addresses = NULL; 1389 int num_instances = 0; 1390 adv_instance_vec_t *instances = NULL; 1391 int i, j; 1392 int num_host_addresses = 0; 1393 int num_add_addresses = 0; 1394 int num_host_instances = 0; 1395 int num_add_instances = 0; 1396 message_t *message = NULL; 1397 client_update_t *remaining_updates = NULL; 1398 srp_server_t *server_state = host->server_state; 1399 1400 // Get the message that produced the update, if any 1401 if (client != NULL) { 1402 message = client->message; 1403 } 1404 1405 // Once an update has finished, we need to apply all of the proposed changes to the host object. 1406 if (host->addresses != NULL) { 1407 for (i = 0; i < host->addresses->num; i++) { 1408 if (host->addresses->vec[i] != NULL && 1409 (update->remove_addresses == NULL || update->remove_addresses->vec[i] == NULL)) 1410 { 1411 num_host_addresses++; 1412 } 1413 } 1414 } 1415 1416 if (update->add_addresses != NULL) { 1417 for (i = 0; i < update->add_addresses->num; i++) { 1418 if (update->add_addresses->vec[i] != NULL) { 1419 num_add_addresses++; 1420 } 1421 } 1422 } 1423 1424 num_addresses = num_host_addresses + num_add_addresses; 1425 if (num_addresses > 0) { 1426 addresses = adv_record_vec_create(num_addresses); 1427 if (addresses == NULL) { 1428 update_failed(update, dns_rcode_servfail, true, true); 1429 return; 1430 } 1431 1432 j = 0; 1433 1434 if (host->addresses != NULL) { 1435 for (i = 0; i < host->addresses->num; i++) { 1436 adv_record_t *rec = host->addresses->vec[i]; 1437 if (rec != NULL && (update->remove_addresses == NULL || update->remove_addresses->vec[i] == NULL)) 1438 { 1439 #ifdef DEBUG_VERBOSE 1440 uint8_t *rdp = rec->rdata; 1441 if (rec->rrtype == dns_rrtype_aaaa) { 1442 SEGMENTED_IPv6_ADDR_GEN_SRP(rdp, rdp_buf); 1443 INFO("retaining " PRI_SEGMENTED_IPv6_ADDR_SRP "on host " PRI_S_SRP, 1444 SEGMENTED_IPv6_ADDR_PARAM_SRP(rdp, rdp_buf), host->registered_name); 1445 } else { 1446 IPv4_ADDR_GEN_SRP(rdp, rdp_buf); 1447 INFO("retaining " PRI_IPv4_ADDR_SRP "on host " PRI_S_SRP, 1448 IPv4_ADDR_PARAM_SRP(rdp, rdp_buf), host->registered_name); 1449 } 1450 #endif 1451 addresses->vec[j] = rec; 1452 RETAIN_HERE(addresses->vec[j], adv_record); 1453 j++; 1454 } 1455 } 1456 } 1457 if (update->add_addresses != NULL) { 1458 for (i = 0; i < update->add_addresses->num; i++) { 1459 adv_record_t *rec = update->add_addresses->vec[i]; 1460 if (rec != NULL) { 1461 #ifdef DEBUG_VERBOSE 1462 uint8_t *rdp = rec->rdata; 1463 if (rec->rrtype == dns_rrtype_aaaa) { 1464 SEGMENTED_IPv6_ADDR_GEN_SRP(rdp, rdp_buf); 1465 INFO("adding " PRI_SEGMENTED_IPv6_ADDR_SRP "to host " PRI_S_SRP, 1466 SEGMENTED_IPv6_ADDR_PARAM_SRP(rdp, rdp_buf), host->registered_name); 1467 } else { 1468 IPv4_ADDR_GEN_SRP(rdp, rdp_buf); 1469 INFO("adding " PRI_IPv4_ADDR_SRP "to host " PRI_S_SRP, 1470 IPv4_ADDR_PARAM_SRP(rdp, rdp_buf), host->registered_name); 1471 } 1472 #endif 1473 addresses->vec[j] = rec; 1474 RETAIN_HERE(addresses->vec[j], adv_record); 1475 j++; 1476 if (rec->update != NULL) { 1477 RELEASE_HERE(update->add_addresses->vec[i]->update, adv_update); 1478 update->add_addresses->vec[i]->update = NULL; 1479 } 1480 RELEASE_HERE(update->add_addresses->vec[i], adv_record); 1481 update->add_addresses->vec[i] = NULL; 1482 } 1483 } 1484 } 1485 addresses->num = j; 1486 } 1487 1488 // Do the same for instances. 1489 if (host->instances != NULL) { 1490 for (i = 0; i < host->instances->num; i++) { 1491 // We're counting the number of non-NULL instances in the host instance vector, which is probably always 1492 // going to be the same as host->instances->num, but we are not relying on this. 1493 if (host->instances->vec[i] != NULL) { 1494 num_host_instances++; 1495 } 1496 } 1497 } 1498 1499 if (update->add_instances != NULL) { 1500 for (i = 0; i < update->add_instances->num; i++) { 1501 if (update->add_instances->vec[i] != NULL) { 1502 num_add_instances++; 1503 } 1504 } 1505 } 1506 1507 num_instances = num_add_instances + num_host_instances; 1508 instances = adv_instance_vec_create(num_instances); 1509 if (instances == NULL) { 1510 if (addresses != NULL) { 1511 RELEASE_HERE(addresses, adv_record_vec); 1512 addresses = NULL; 1513 } 1514 update_failed(update, dns_rcode_servfail, true, true); 1515 return; 1516 } 1517 1518 j = 0; 1519 if (host->instances != NULL) { 1520 for (i = 0; i < host->instances->num; i++) { 1521 if (j == num_instances) { 1522 FAULT("j (%d) == num_instances (%d)", j, num_instances); 1523 break; 1524 } 1525 if (update->update_instances != NULL && update->update_instances->vec[i] != NULL) { 1526 adv_instance_t *instance = update->update_instances->vec[i]; 1527 if (update->remove_instances != NULL && update->remove_instances->vec[i] != NULL) { 1528 adv_instance_t *removed_instance = update->remove_instances->vec[i]; 1529 INFO("removed instance " PRI_S_SRP " " PRI_S_SRP " %d", 1530 removed_instance->instance_name, removed_instance->service_type, removed_instance->port); 1531 INFO("added instance " PRI_S_SRP " " PRI_S_SRP " %d", 1532 instance->instance_name, instance->service_type, instance->port); 1533 } else { 1534 INFO("updated instance " PRI_S_SRP " " PRI_S_SRP " %d", 1535 instance->instance_name, instance->service_type, instance->port); 1536 } 1537 instances->vec[j] = instance; 1538 RETAIN_HERE(instances->vec[j], adv_instance); 1539 j++; 1540 RELEASE_HERE(update->update_instances->vec[i], adv_instance); 1541 update->update_instances->vec[i] = NULL; 1542 if (instance->update != NULL) { 1543 RELEASE_HERE(instance->update, adv_update); 1544 instance->update = NULL; 1545 } 1546 set_instance_message(instance, message); 1547 } else { 1548 if (update->remove_instances != NULL && update->remove_instances->vec[i] != NULL) { 1549 adv_instance_t *instance = update->remove_instances->vec[i]; 1550 INFO("removed instance " PRI_S_SRP " " PRI_S_SRP " %d", 1551 instance->instance_name, instance->service_type, instance->port); 1552 instances->vec[j] = instance; 1553 RETAIN_HERE(instances->vec[j], adv_instance); 1554 j++; 1555 instance->removed = true; 1556 if (message != NULL) { 1557 if (instance->message != NULL) { 1558 ioloop_message_release(instance->message); 1559 } 1560 instance->message = message; 1561 ioloop_message_retain(instance->message); 1562 } 1563 if (instance->txn == NULL) { 1564 ERROR("instance " PRI_S_SRP "." PRI_S_SRP " for host " PRI_S_SRP " has no connection.", 1565 instance->instance_name, instance->service_type, host->name); 1566 } else { 1567 ioloop_dnssd_txn_cancel_srp(host->server_state, instance->txn); 1568 ioloop_dnssd_txn_release(instance->txn); 1569 instance->txn = NULL; 1570 } 1571 } else { 1572 if (host->instances->vec[i] != NULL) { 1573 adv_instance_t *instance = host->instances->vec[i]; 1574 INFO("kept instance " PRI_S_SRP " " PRI_S_SRP " %d, instance->message = %p", 1575 instance->instance_name, instance->service_type, instance->port, instance->message); 1576 instances->vec[j] = instance; 1577 RETAIN_HERE(instances->vec[j], adv_instance); 1578 j++; 1579 set_instance_message(instance, message); 1580 } 1581 } 1582 } 1583 } 1584 } 1585 1586 // Set the message on all of the instances that were renewed to the current message. 1587 if (update->renew_instances != NULL) { 1588 for (i = 0; i < update->renew_instances->num; i++) { 1589 adv_instance_t *instance = update->renew_instances->vec[i]; 1590 if (instance != NULL) { 1591 if (message != NULL) { // Should never not be NULL for a renew, of course. 1592 if (instance->message != NULL) { 1593 ioloop_message_release(instance->message); 1594 } 1595 instance->message = message; 1596 ioloop_message_retain(instance->message); 1597 } 1598 instance->recent_message = 0; 1599 INFO("renewed instance " PRI_S_SRP " " PRI_S_SRP " %d", 1600 instance->instance_name, instance->service_type, instance->port); 1601 } 1602 } 1603 } 1604 1605 if (update->add_instances != NULL) { 1606 for (i = 0; i < update->add_instances->num; i++) { 1607 adv_instance_t *instance = update->add_instances->vec[i]; 1608 if (instance != NULL) { 1609 INFO("added instance " PRI_S_SRP " " PRI_S_SRP " %d", 1610 instance->instance_name, instance->service_type, instance->port); 1611 instances->vec[j] = instance; 1612 RETAIN_HERE(instances->vec[j], adv_instance); 1613 j++; 1614 RELEASE_HERE(update->add_instances->vec[i], adv_instance); 1615 update->add_instances->vec[i] = NULL; 1616 if (instance->update != NULL) { 1617 RELEASE_HERE(instance->update, adv_update); 1618 instance->update = NULL; 1619 } 1620 set_instance_message(instance, message); 1621 } 1622 } 1623 } 1624 instances->num = j; 1625 // Clear "skip update" flag on instances. 1626 for (i = 0; i < instances->num; i++) { 1627 if (instances->vec[i] != NULL) { 1628 instances->vec[i]->skip_update = false; 1629 } 1630 } 1631 1632 // At this point we can safely modify the host object because we aren't doing any more 1633 // allocations. 1634 if (host->addresses != NULL) { 1635 RELEASE_HERE(host->addresses, adv_record_vec); 1636 } 1637 host->addresses = addresses; // Either NULL or else returned retained by adv_record_vec_create(). 1638 1639 if (host->instances != NULL) { 1640 for (i = 0; i < host->instances->num; i++) { 1641 adv_instance_t *instance = host->instances->vec[i]; 1642 if (instance != NULL) { 1643 INFO("old host instance %d " PRI_S_SRP "." PRI_S_SRP " for host " PRI_S_SRP " has ref_count %d", 1644 i, instance->instance_name, instance->service_type, host->name, instance->ref_count); 1645 } else { 1646 INFO("old host instance %d is NULL", i); 1647 } 1648 } 1649 RELEASE_HERE(host->instances, adv_instance_vec); 1650 } 1651 host->instances = instances; 1652 1653 if (host->key_record != NULL && update->key != NULL && host->key_record != update->key) { 1654 srp_mdns_shared_record_remove(host->server_state, host->key_record); 1655 RELEASE_HERE(host->key_record, adv_record); 1656 host->key_record = NULL; 1657 } 1658 if (host->key_record == NULL && update->key != NULL) { 1659 host->key_record = update->key; 1660 RETAIN_HERE(host->key_record, adv_record); 1661 if (update->key->update != NULL) { 1662 RELEASE_HERE(update->key->update, adv_update); 1663 update->key->update = NULL; 1664 } 1665 } 1666 1667 // Remove any instances that are to be removed 1668 if (update->remove_addresses != NULL) { 1669 for (i = 0; i < update->remove_addresses->num; i++) { 1670 adv_record_t *record = update->remove_addresses->vec[i]; 1671 if (record != NULL) { 1672 srp_mdns_shared_record_remove(host->server_state, record); 1673 } 1674 } 1675 } 1676 1677 time_t lease_offset = 0; 1678 1679 if (client) { 1680 if (host->message != NULL) { 1681 ioloop_message_release(host->message); 1682 } 1683 host->message = client->message; 1684 ioloop_message_retain(host->message); 1685 advertise_finished(host, host->name, host->server_state, host->srpl_connection, 1686 client->connection, client->message, dns_rcode_noerror, client, true, 1687 client->next == NULL); 1688 remaining_updates = client->next; 1689 client->next = NULL; 1690 srp_parse_client_updates_free(client); 1691 update->client = NULL; 1692 if (host->message->received_time != 0) { 1693 host->update_time = host->message->received_time; 1694 lease_offset = srp_time() - host->update_time; 1695 INFO("setting host update time based on message received time: %ld, lease offset = %ld", 1696 host->update_time, lease_offset); 1697 } else { 1698 INFO("setting host update time based on current time: %ld", host->message->received_time); 1699 host->update_time = srp_time(); 1700 } 1701 } else { 1702 INFO("lease offset = %ld", lease_offset); 1703 lease_offset = srp_time() - host->update_time; 1704 } 1705 RETAIN_HERE(update, adv_update); // We need to hold a reference to the update since this might be the last. 1706 1707 // The update should still be on the host. 1708 if (host->update == NULL) { 1709 ERROR("p_update is null."); 1710 } else { 1711 RELEASE_HERE(host->update, adv_update); 1712 host->update = NULL; 1713 } 1714 1715 // Reset the retry interval, since we succeeded in updating. 1716 host->retry_interval = 0; 1717 1718 // Set the lease time based on this update. Even if we scheduled an update for the next time we 1719 // enter the dispatch loop, we still want to schedule a lease expiry here, because it's possible 1720 // that in the process of returning to the dispatch loop, the scheduled update will be removed. 1721 if (0) { 1722 #if STUB_ROUTER 1723 } else if (server_state->stub_router_enabled) { 1724 host->lease_interval = update->host_lease; 1725 host->key_lease = update->key_lease; 1726 #endif 1727 } else { 1728 // For the Thread in Mobile use case, use the duration of the key lease to determine when to expire host 1729 // entries, rather than expiring them when the host lease expires. This is technically out of spec, but 1730 // accomplishes part of the stated goal of keeping usable cached data around for use immediately after 1731 // connecting to a Thread mesh. 1732 host->lease_interval = update->key_lease; 1733 host->key_lease = update->key_lease; 1734 } 1735 1736 // It would probably be harmless to set this for replications, since the value currently wouldn't change, 1737 // but to avoid future issues we only set this if it's a direct SRP update and not a replicated update. 1738 // We know it's a direct SRP update because host->message->lease is zero. It would not be zero if we 1739 // had received this as an SRP update, but is always zero when received directly via UDP. 1740 INFO("host->message->lease = %d, host->lease_interval = %d, host->key_lease = %d", 1741 host->message->lease, host->lease_interval, host->key_lease); 1742 if (host->message->lease == 0) { 1743 host->message->lease = host->lease_interval; 1744 host->message->key_lease = host->key_lease; 1745 } 1746 1747 // We want the lease expiry event to fire the next time the lease on any instance expires, or 1748 // at the time the lease for the current update would expire, whichever is sooner. 1749 int64_t next_lease_expiry = INT64_MAX; 1750 int64_t now = ioloop_timenow(); 1751 1752 #define LEASE_EXPIRY_DEBUGGING 1 1753 // update->lease_expiry is nonzero if we are re-doing a previous registration. 1754 if (update->lease_expiry != 0) { 1755 if (update->lease_expiry < now) { 1756 #ifdef LEASE_EXPIRY_DEBUGGING 1757 ERROR("lease expiry for host " PRI_S_SRP " happened %" PRIu64 " milliseconds ago.", 1758 host->registered_name, now - update->lease_expiry); 1759 #endif 1760 // Expire the lease when next we hit the run loop 1761 next_lease_expiry = now; 1762 } else { 1763 #ifdef LEASE_EXPIRY_DEBUGGING 1764 INFO("lease_expiry (1) for host " PRI_S_SRP " set to %" PRId64, host->name, 1765 (int64_t)(update->lease_expiry - now)); 1766 #endif 1767 next_lease_expiry = update->lease_expiry; 1768 } 1769 host->lease_expiry = update->lease_expiry; 1770 } 1771 // This is the more usual case. 1772 else { 1773 #ifdef LEASE_EXPIRY_DEBUGGING 1774 INFO("lease_expiry (2) for host " PRI_S_SRP " set to %ld", host->name, (host->lease_interval - lease_offset) * 1000); 1775 #endif 1776 next_lease_expiry = now + (host->lease_interval - lease_offset) * 1000; 1777 if (next_lease_expiry < now) { 1778 next_lease_expiry = now; 1779 } 1780 host->lease_expiry = next_lease_expiry; 1781 } 1782 1783 // We're doing two things here: setting the lease expiry on instances that were touched by the current 1784 // update, and also finding the soonest update. 1785 for (i = 0; i < host->instances->num; i++) { 1786 adv_instance_t *instance = host->instances->vec[i]; 1787 1788 if (instance != NULL) { 1789 // This instance was updated by the current update, so set its lease time to 1790 // next_lease_expiry. 1791 if (instance->message == message) { 1792 if (instance->removed) { 1793 #ifdef LEASE_EXPIRY_DEBUGGING 1794 INFO("lease_expiry (7) for host " PRI_S_SRP " removed instance " PRI_S_SRP "." PRI_S_SRP 1795 " left at %" PRId64, host->name, instance->instance_name, instance->service_type, 1796 (int64_t)(instance->lease_expiry - now)); 1797 #endif 1798 } else { 1799 #ifdef LEASE_EXPIRY_DEBUGGING 1800 INFO("lease_expiry (4) for host " PRI_S_SRP " instance " PRI_S_SRP "." PRI_S_SRP " set to %" PRId64, 1801 host->name, instance->instance_name, instance->service_type, 1802 (int64_t)(host->lease_expiry - now)); 1803 #endif 1804 instance->lease_expiry = host->lease_expiry; 1805 } 1806 } 1807 // Instance was not updated by this update, so see if it expires sooner than this update 1808 // (which is likely). 1809 else if (instance->lease_expiry > now && instance->lease_expiry < next_lease_expiry) { 1810 #ifdef LEASE_EXPIRY_DEBUGGING 1811 INFO("lease_expiry (3) for host " PRI_S_SRP " instance " PRI_S_SRP "." PRI_S_SRP " set to %" PRId64, 1812 host->name, instance->instance_name, instance->service_type, 1813 (int64_t)(instance->lease_expiry - now)); 1814 #endif 1815 next_lease_expiry = instance->lease_expiry; 1816 } else { 1817 if (instance->lease_expiry <= now) { 1818 #ifdef LEASE_EXPIRY_DEBUGGING 1819 INFO("lease_expiry (5) for host " PRI_S_SRP " instance " PRI_S_SRP "." PRI_S_SRP 1820 " in the past at %" PRId64, 1821 host->name, instance->instance_name, instance->service_type, 1822 (int64_t)(now - instance->lease_expiry)); 1823 #endif 1824 next_lease_expiry = now; 1825 #ifdef LEASE_EXPIRY_DEBUGGING 1826 } else { 1827 INFO("lease_expiry (6) for host " PRI_S_SRP " instance " PRI_S_SRP "." PRI_S_SRP 1828 " is later than next_lease_expiry by %" PRId64, host->name, instance->instance_name, 1829 instance->service_type, (int64_t)(next_lease_expiry - instance->lease_expiry)); 1830 1831 #endif 1832 } 1833 } 1834 } 1835 } 1836 1837 // Now set a timer for the next lease expiry. 1838 uint64_t when = next_lease_expiry - now; 1839 if (when > INT32_MAX) { 1840 when = INT32_MAX; 1841 } 1842 1843 if (next_lease_expiry == now) { 1844 INFO("scheduling immediate call to lease_callback in the run loop for " PRI_S_SRP, host->name); 1845 ioloop_run_async(lease_callback, host); 1846 } else { 1847 INFO("scheduling wakeup to lease_callback in %" PRIu64 " for host " PRI_S_SRP, 1848 when / 1000, host->name); 1849 ioloop_add_wake_event(host->lease_wakeup, host, lease_callback, srp_adv_host_context_release, (uint32_t)when); 1850 RETAIN_HERE(host, adv_host); 1851 } 1852 1853 // Instance vectors can hold circular references to the update object, which won't get freed until we call 1854 // adv_update_finalize, which we will never do because of the circular reference. So break any remaining 1855 // circular references before releasing the update. 1856 adv_update_free_instance_vectors(update); 1857 1858 // This is letting go of the reference we retained earlier in this function, not some outstanding reference retained elsewhere. 1859 RELEASE_HERE(update, adv_update); 1860 1861 // If we were processing an SRP update, we may have additional updates to do. Start the next one now if so. 1862 if (remaining_updates != NULL) { 1863 srp_update_start(remaining_updates); 1864 } else { 1865 srp_dump_server_stats(server_state, false, false); 1866 } 1867 } 1868 1869 #ifdef USE_DNSSERVICE_QUEUING 1870 static void 1871 process_dnsservice_error(adv_update_t *update, int err) 1872 { 1873 if (err != kDNSServiceErr_NoError) { 1874 update_failed(update, dns_rcode_servfail, true, true); 1875 if (err == kDNSServiceErr_ServiceNotRunning || err == kDNSServiceErr_DefunctConnection || err == 1) { 1876 if (err == 1) { 1877 FAULT("bogus error code 1"); 1878 } 1879 if (update->host != NULL) { 1880 if (update->host->server_state != NULL) { 1881 service_disconnected(update->host->server_state, 1882 (intptr_t)update->host->server_state->shared_registration_txn); 1883 } 1884 wait_retry(update->host); 1885 } 1886 } 1887 } 1888 } 1889 #endif // USE_DNSSERVICE_QUEUING 1890 1891 #define GENERATE_WAKEUP(ptr) \ 1892 if ((*ptr) == NULL) { \ 1893 (*ptr) = ioloop_wakeup_create(); \ 1894 } \ 1895 if ((*ptr) == NULL) { \ 1896 ERROR("unable to make wakeup " #ptr); \ 1897 } else 1898 1899 static void 1900 srp_instance_retry_callback(void *context) 1901 { 1902 adv_instance_t *instance = context; 1903 adv_host_t *host = instance->host; 1904 if (host == NULL || host->removed) { 1905 INFO("no longer updating instance %p because host is no longer valid.", instance); 1906 return; 1907 } 1908 INFO("re-registering updating instance %p.", instance); 1909 register_instance(instance); 1910 } 1911 1912 static void 1913 srp_schedule_instance_retry(adv_instance_t *instance) 1914 { 1915 GENERATE_WAKEUP(&instance->retry_wakeup) { 1916 if (instance->wakeup_interval == 0) { 1917 instance->wakeup_interval = 5 * 1000; 1918 } else { 1919 instance->wakeup_interval *= 2; 1920 } 1921 unsigned interval = instance->wakeup_interval * 1.5 - (srp_random32() % instance->wakeup_interval); 1922 RETAIN_HERE(instance, adv_instance); 1923 ioloop_add_wake_event(instance->retry_wakeup, instance, srp_instance_retry_callback, adv_instance_context_release, interval); 1924 INFO("will attempt to reregister instance %p in %.3lf seconds", instance, ((double)interval) / 1000.0); 1925 } 1926 } 1927 1928 static void 1929 srp_host_record_retry_callback(void *context) 1930 { 1931 adv_host_t *host = context; 1932 if (host != NULL) { 1933 host->re_register_pending = false; 1934 } 1935 if (host == NULL || host->removed) { 1936 INFO("no longer updating host %p because host is no longer valid.", host); 1937 return; 1938 } 1939 1940 if (host->addresses != NULL) { 1941 for (int i = 0; i < host->addresses->num; i++) { 1942 adv_record_t *record = host->addresses->vec[i]; 1943 if (record != NULL) { 1944 INFO("re-registering host record %p.", record); 1945 register_host_record(host, record, false); 1946 } 1947 } 1948 } 1949 if (host->key_record != NULL) { 1950 INFO("re-registering host record %p.", host->key_record); 1951 register_host_record(host, host->key_record, false); 1952 } 1953 } 1954 1955 static void 1956 srp_schedule_host_record_retry(adv_record_t *record) 1957 { 1958 // If the host isn't valid or we're already re-registering, don't schedule a retry. 1959 if (record->host == NULL || record->host->removed) { 1960 INFO("will not attempt to reregister record %p", record); 1961 return; 1962 } 1963 if (record->host->re_register_pending) { 1964 INFO("already scheduled attempt to reregister record %p", record); 1965 return; 1966 } 1967 1968 adv_host_t *host = record->host; 1969 GENERATE_WAKEUP(&host->re_register_wakeup) { 1970 if (host->wakeup_interval == 0) { 1971 host->wakeup_interval = 5 * 1000; 1972 } else { 1973 host->wakeup_interval *= 2; 1974 } 1975 unsigned interval = host->wakeup_interval * 1.5 - (srp_random32() % host->wakeup_interval); 1976 RETAIN_HERE(host, adv_host); 1977 ioloop_add_wake_event(host->re_register_wakeup, host, srp_host_record_retry_callback, srp_adv_host_context_release, interval); 1978 INFO("will attempt to reregister record %p in %.3lf seconds", record, ((double)interval) / 1000.0); 1979 } 1980 } 1981 1982 1983 // When the host registration has completed, we get this callback. Completion either means that we succeeded in 1984 // registering the record, or that something went wrong and the registration has failed. 1985 static void 1986 register_instance_completion(DNSServiceRef sdref, DNSServiceFlags flags, DNSServiceErrorType error_code, 1987 const char *name, const char *regtype, const char *domain, void *context) 1988 { 1989 (void)flags; 1990 (void)sdref; 1991 adv_instance_t *instance = context; 1992 adv_update_t *update = instance->update; 1993 adv_host_t *host = instance->host; 1994 1995 // Retain the instance for the life of this function, just in case we release stuff that is holding the last reference to it. 1996 RETAIN_HERE(instance, adv_instance); 1997 1998 // It's possible that we could restart a host update due to an error while a callback is still pending on a stale 1999 // update. In this case, we just cancel all of the work that's been done on the stale update (it's probably already 2000 // moot anyway. 2001 if (update != NULL && host->update != update) { 2002 INFO("registration for service " PRI_S_SRP "." PRI_S_SRP " completed with invalid state.", name, regtype); 2003 RELEASE_HERE(instance->update, adv_update); 2004 instance->update = NULL; 2005 RELEASE_HERE(instance, adv_instance); 2006 return; 2007 } 2008 2009 // We will generally get a callback on success or failure of the initial registration; this is what causes 2010 // the update to complete or fail. We may get subsequent callbacks because of name conflicts. So the first 2011 // time we get a callback, instance->update will always be valid; thereafter, it will not, so null it out. 2012 if (update != NULL) { 2013 RETAIN_HERE(update, adv_update); // We need to hold onto this until we are done with the update. 2014 RELEASE_HERE(instance->update, adv_update); 2015 instance->update = NULL; 2016 } 2017 2018 if (error_code == kDNSServiceErr_NoError || error_code == kDNSServiceErr_NameConflict) { 2019 INFO("registration for service " PRI_S_SRP "." PRI_S_SRP "." PRI_S_SRP " -> " 2020 PRI_S_SRP " has completed" PUB_S_SRP ".", instance->instance_name, instance->service_type, domain, 2021 host->registered_name, error_code == kDNSServiceErr_NoError ? ":" : " with a conflict"); 2022 INFO("registration is under " PRI_S_SRP "." PRI_S_SRP PRI_S_SRP, name, regtype, 2023 domain); 2024 2025 if (error_code != kDNSServiceErr_NoError) { 2026 if (instance->txn == NULL) { 2027 FAULT("instance->txn is NULL for instance %p!", instance); 2028 } else { 2029 ioloop_dnssd_txn_cancel_srp(host->server_state, instance->txn); 2030 ioloop_dnssd_txn_release(instance->txn); 2031 instance->txn = NULL; 2032 } 2033 srp_schedule_instance_retry(instance); 2034 } 2035 2036 // In principle update->instance should always be non-NULL here because a no-error response should 2037 // only happen once or not at all. But just to be safe... 2038 if (update != NULL) { 2039 if (instance->update_pending) { 2040 if (update->client != NULL) { 2041 instance->recent_message = (ptrdiff_t)update->client->message; // for comparison later in srp_mdns_update_finished 2042 } 2043 update->num_instances_completed++; 2044 if (update->num_records_completed == update->num_records_started && 2045 update->num_instances_completed == update->num_instances_started) 2046 { 2047 srp_mdns_update_finished(update); 2048 } 2049 RELEASE_HERE(update, adv_update); 2050 instance->update_pending = false; 2051 update = NULL; 2052 } 2053 } else { 2054 INFO("re-update succeeded for instance " PRI_S_SRP " (" PRI_S_SRP 2055 " " PRI_S_SRP " " PRI_S_SRP ")", instance->instance_name, name, regtype, domain); 2056 } 2057 } else { 2058 INFO("registration for service " PRI_S_SRP "." PRI_S_SRP "." PRI_S_SRP " -> " 2059 PRI_S_SRP " failed with code %d", instance->instance_name, instance->service_type, domain, 2060 host->registered_name, error_code); 2061 2062 // If the reason this failed is that we couldn't talk to mDNSResponder, or mDNSResponder disconnected, then we want to retry 2063 // later on in the hopes that mDNSResponder will come back. 2064 if (error_code == kDNSServiceErr_ServiceNotRunning || error_code == kDNSServiceErr_DefunctConnection) { 2065 service_disconnected(host->server_state, instance->shared_txn); 2066 instance->shared_txn = 0; 2067 wait_retry(host); 2068 } else { 2069 if (update != NULL) { 2070 update_failed(update, (error_code == kDNSServiceErr_NameConflict 2071 ? dns_rcode_yxdomain 2072 : dns_rcode_servfail), true, true); 2073 if (instance->update != NULL) { 2074 RELEASE_HERE(instance->update, adv_update); 2075 instance->update = NULL; 2076 } 2077 RELEASE_HERE(update, adv_update); 2078 } else { 2079 } 2080 } 2081 2082 // The transaction still holds a reference to the instance. instance->txn should never be NULL here. When we cancel 2083 // the transaction, the reference the transaction held on the instance will be released. 2084 if (instance->txn == NULL) { 2085 FAULT("instance->txn is NULL for instance %p!", instance); 2086 } else { 2087 ioloop_dnssd_txn_cancel_srp(host->server_state, instance->txn); 2088 ioloop_dnssd_txn_release(instance->txn); 2089 instance->txn = NULL; 2090 } 2091 } 2092 RELEASE_HERE(instance, adv_instance); 2093 } 2094 2095 static bool 2096 extract_instance_name(char *instance_name, size_t instance_name_max, 2097 char *service_type, size_t service_type_max, service_instance_t *instance) 2098 { 2099 dns_name_t *end_of_service_type = instance->service->rr->name->next; 2100 size_t service_index; 2101 service_t *service, *base_type; 2102 if (end_of_service_type != NULL) { 2103 if (end_of_service_type->next != NULL) { 2104 end_of_service_type = end_of_service_type->next; 2105 } 2106 } 2107 dns_name_print_to_limit(instance->service->rr->name, end_of_service_type, service_type, service_type_max); 2108 2109 // It's possible that the registration might include subtypes. If so, we need to convert them to the 2110 // format that DNSServiceRegister expects: service_type,subtype,subtype... 2111 service_index = strlen(service_type); 2112 base_type = instance->service->base_type; 2113 for (service = instance->service->next; service != NULL && service->base_type == base_type; service = service->next) 2114 { 2115 if (service_index + service->rr->name->len + 2 > service_type_max) { 2116 ERROR("service name: " PRI_S_SRP " is too long for additional subtype " PRI_S_SRP, 2117 service_type, service->rr->name->data); 2118 return false; 2119 } 2120 service_type[service_index++] = ','; 2121 memcpy(&service_type[service_index], service->rr->name->data, service->rr->name->len + 1); 2122 service_index += service->rr->name->len; 2123 } 2124 2125 // Make a presentation-format version of the service instance name. 2126 dns_name_print_to_limit(instance->name, instance->name != NULL ? instance->name->next : NULL, 2127 instance_name, instance_name_max); 2128 return true; 2129 } 2130 2131 void 2132 srp_format_time_offset(char *buf, size_t buf_len, time_t offset) 2133 { 2134 struct tm tm_now; 2135 time_t when = time(NULL) - offset; 2136 localtime_r(&when, &tm_now); 2137 strftime(buf, buf_len, "%F %T", &tm_now); 2138 } 2139 2140 DNSServiceAttributeRef 2141 srp_message_tsr_attribute_generate(message_t *message, uint32_t key_id, char *time_buf, size_t time_buf_size) 2142 { 2143 DNSServiceAttributeRef attribute = DNSServiceAttributeCreate(); 2144 if (attribute == NULL) { 2145 ERROR("Failed to create new DNSServiceAttributeRef"); 2146 } else { 2147 uint32_t offset = 0; 2148 2149 if (message != NULL && message->received_time != 0) { 2150 offset = (uint32_t)(srp_time() - message->received_time); 2151 srp_format_time_offset(time_buf, time_buf_size, offset); 2152 } else { 2153 static char msg[] = "now"; 2154 if (time_buf_size < sizeof(msg)) { 2155 FAULT("bogus time buf size %zd", time_buf_size); 2156 time_buf[0] = 0; 2157 } else { 2158 memcpy(time_buf, msg, sizeof(msg)); 2159 } 2160 } 2161 if (_DNSSD_API_AVAILABLE_FALL_2024) { 2162 DNSServiceAttributeSetHostKeyHash(attribute, key_id); 2163 } 2164 DNSServiceAttributeSetTimestamp(attribute, offset); 2165 } 2166 return attribute; 2167 } 2168 2169 DNSServiceAttributeRef 2170 srp_adv_instance_tsr_attribute_generate(adv_instance_t *instance, char *time_buf, size_t time_buf_size) 2171 { 2172 message_t *message = NULL; 2173 if (instance->update != NULL && instance->update->client != NULL && instance->update->client->message != NULL) { 2174 message = instance->update->client->message; 2175 } else if (instance->update == NULL && instance->message != NULL) { 2176 message = instance->message; 2177 } 2178 return srp_message_tsr_attribute_generate(message, instance->host->key_id, time_buf, time_buf_size); 2179 } 2180 2181 static bool 2182 register_instance(adv_instance_t *instance) 2183 { 2184 int err = kDNSServiceErr_Unknown; 2185 bool exit_status = false; 2186 srp_server_t *server_state = instance->host->server_state; 2187 2188 // If we don't yet have a shared connection, create one. 2189 if (!srp_mdns_shared_registration_txn_setup(server_state)) { 2190 goto exit; 2191 } 2192 DNSServiceRef service_ref = server_state->shared_registration_txn->sdref; 2193 2194 INFO(PUB_S_SRP "DNSServiceRegister(%p, " PRI_S_SRP ", " PRI_S_SRP ", " PRI_S_SRP ", %d, %p)", 2195 instance->skip_update ? "skipping " : "", service_ref, instance->instance_name, instance->service_type, 2196 instance->host->registered_name, instance->port, instance); 2197 2198 if (instance->skip_update) { 2199 if (instance->update->client != NULL) { 2200 instance->recent_message = (ptrdiff_t)instance->update->client->message; // for comparison later in srp_mdns_update_finished 2201 } 2202 exit_status = true; 2203 goto exit; 2204 } 2205 2206 char time_buf[TSR_TIMESTAMP_STRING_LEN]; 2207 DNSServiceAttributeRef tsr_attribute = 2208 srp_adv_instance_tsr_attribute_generate(instance, time_buf, sizeof(time_buf)); 2209 if (tsr_attribute == NULL) { 2210 err = kDNSServiceErr_NoMemory; 2211 } else { 2212 uint32_t flags = kDNSServiceFlagsShareConnection | kDNSServiceFlagsNoAutoRename; 2213 if (_DNSSD_API_AVAILABLE_FALL_2024) { 2214 flags |= kDNSServiceFlagsKnownUnique; 2215 } 2216 err = dns_service_register_wa(server_state, &service_ref, flags, 2217 server_state->advertise_interface, 2218 instance->instance_name, instance->service_type, local_suffix, 2219 instance->host->registered_name, htons(instance->port), instance->txt_length, 2220 instance->txt_data, tsr_attribute, register_instance_completion, instance); 2221 DNSServiceAttributeDeallocate(tsr_attribute); 2222 if (err == kDNSServiceErr_NoError) { 2223 INFO("DNSServiceRegister, TSR for instance " PRI_S_SRP " host " PRI_S_SRP " set to " PUB_S_SRP 2224 "(instance %p sdref %p)", instance->instance_name, 2225 instance->host->name == NULL ? "<null>" : instance->host->name, time_buf, instance, service_ref); 2226 } 2227 } 2228 2229 // This would happen if we pass NULL for regtype, which we don't, or if we run out of memory, or if 2230 // the server isn't running; in the second two cases, we can always try again later. 2231 if (err != kDNSServiceErr_NoError) { 2232 if (err == kDNSServiceErr_ServiceNotRunning || err == kDNSServiceErr_DefunctConnection || 2233 err == kDNSServiceErr_BadParam || err == kDNSServiceErr_BadReference || err == 1) 2234 { 2235 if (err == 1) { 2236 FAULT("bogus error code 1"); 2237 } 2238 INFO("DNSServiceRegister failed: " PUB_S_SRP " (instance %p)", 2239 err == kDNSServiceErr_ServiceNotRunning ? "not running" : "defunct", instance); 2240 service_disconnected(server_state, (intptr_t)server_state->shared_registration_txn); 2241 } else { 2242 INFO("DNSServiceRegister failed: %d (instance %p)", err, instance); 2243 } 2244 goto exit; 2245 } 2246 if (instance->update != NULL) { 2247 instance->update->num_instances_started++; 2248 instance->update_pending = true; 2249 } 2250 // After DNSServiceRegister succeeds, it creates a copy of DNSServiceRef that indirectly uses the shared connection, 2251 // so we update it here. 2252 instance->txn = ioloop_dnssd_txn_add_subordinate(service_ref, instance, adv_instance_context_release, NULL); 2253 if (instance->txn == NULL) { 2254 ERROR("no memory for instance transaction."); 2255 goto exit; 2256 } 2257 instance->shared_txn = (intptr_t)server_state->shared_registration_txn; 2258 RETAIN_HERE(instance, adv_instance); // for the callback 2259 exit_status = true; 2260 2261 exit: 2262 return exit_status; 2263 } 2264 2265 // When we get a late name conflict on the hostname, we need to update the host registration and all of the 2266 // service registrations. To do this, we construct an update and then apply it. If there is already an update 2267 // in progress, we put this update at the end of the list. 2268 static void 2269 update_from_host(adv_host_t *host) 2270 { 2271 adv_update_t *update = NULL; 2272 int i; 2273 2274 if (host->update != NULL) { 2275 ERROR("already have an update."); 2276 } 2277 2278 // Allocate the update structure. 2279 update = calloc(1, sizeof *update); 2280 if (update == NULL) { 2281 ERROR("no memory for update."); 2282 goto fail; 2283 } 2284 RETAIN_HERE(update, adv_update); 2285 2286 if (host->addresses != NULL) { 2287 update->add_addresses = adv_record_vec_copy(host->addresses); 2288 if (update->add_addresses == NULL) { 2289 ERROR("no memory for addresses"); 2290 goto fail; 2291 } 2292 for (i = 0; i < update->add_addresses->num; i++) { 2293 if (update->add_addresses->vec[i] != NULL) { 2294 update->add_addresses->vec[i]->update = update; 2295 RETAIN_HERE(update, adv_update); 2296 } 2297 } 2298 } 2299 2300 // We can never update more instances than currently exist for this host. 2301 if (host->instances != NULL) { 2302 update->update_instances = adv_instance_vec_copy(host->instances); 2303 if (update->update_instances == NULL) { 2304 ERROR("no memory for update_instances"); 2305 goto fail; 2306 } 2307 for (i = 0; i < update->update_instances->num; i++) { 2308 if (update->update_instances->vec[i] != NULL) { 2309 update->update_instances->vec[i]->update = update; 2310 RETAIN_HERE(update, adv_update); 2311 } 2312 } 2313 2314 // We aren't actually adding or deleting any instances, but... 2315 update->remove_instances = adv_instance_vec_create(host->instances->num); 2316 if (update->remove_instances == NULL) { 2317 ERROR("no memory for remove_instances"); 2318 goto fail; 2319 } 2320 update->remove_instances->num = host->instances->num; 2321 2322 update->add_instances = adv_instance_vec_create(host->instances->num); 2323 if (update->add_instances == NULL) { 2324 ERROR("no memory for add_instances"); 2325 goto fail; 2326 } 2327 update->add_instances->num = host->instances->num; 2328 } 2329 2330 2331 // At this point we have figured out all the work we need to do, so hang it off an update structure. 2332 update->host = host; 2333 RETAIN_HERE(update->host, adv_host); 2334 update->host_lease = host->lease_interval; 2335 update->key_lease = host->key_lease; 2336 update->lease_expiry = host->lease_expiry; 2337 2338 // Stash the update on the host. 2339 host->update = update; 2340 RETAIN_HERE(host->update, adv_update); // host gets a reference 2341 RELEASE_HERE(update, adv_update); // we're done with our reference. 2342 start_host_update(host); 2343 return; 2344 2345 fail: 2346 if (update != NULL) { 2347 adv_update_cancel(update); 2348 RELEASE_HERE(update, adv_update); 2349 } 2350 wait_retry(host); 2351 return; 2352 } 2353 2354 // When the host registration has completed, we get this callback. Completion either means that we succeeded in 2355 // registering the record, or that something went wrong and the registration has failed. 2356 static void 2357 register_host_record_completion(DNSServiceRef sdref, DNSRecordRef rref, 2358 DNSServiceFlags flags, DNSServiceErrorType error_code, void *context) 2359 { 2360 adv_record_t *record = context; 2361 adv_host_t *host = NULL; 2362 adv_update_t *update = NULL; 2363 (void)sdref; 2364 (void)rref; 2365 (void)error_code; 2366 (void)flags; 2367 2368 // This can happen if for some reason DNSServiceRemoveRecord returns something other than success. In this case, all 2369 // the cleanup that can be done has already been done, and all we can do is ignore the problem. 2370 if (record->rref == NULL) { 2371 ERROR("null rref"); 2372 return; 2373 } 2374 // For analyzer, can't actually happen. 2375 if (record == NULL) { 2376 ERROR("null record"); 2377 return; 2378 } 2379 host = record->host; 2380 if (host == NULL) { 2381 ERROR("no host"); 2382 return; 2383 } 2384 2385 // Make sure record remains valid for the duration of this call. 2386 RETAIN_HERE(record, adv_record); 2387 2388 // It's possible that we could restart a host update due to an error while a callback is still pending on a stale 2389 // update. In this case, we just cancel all of the work that's been done on the stale update (it's probably already 2390 // moot anyway. 2391 if (record->update != NULL && host->update != record->update) { 2392 INFO("registration for host record completed with invalid state."); 2393 adv_update_cancel(record->update); 2394 RELEASE_HERE(record->update, adv_update); 2395 record->update = NULL; 2396 srp_mdns_shared_record_remove(host->server_state, record); // This will prevent further callbacks and release the reference held by the transaction. 2397 RELEASE_HERE(record, adv_record); // The callback has a reference to the record. 2398 RELEASE_HERE(record, adv_record); // Release the reference to the record that we retained at the beginning 2399 return; 2400 2401 } 2402 update = record->update; 2403 if (update != NULL) { 2404 RETAIN_HERE(update, adv_update); 2405 } 2406 2407 if (error_code == kDNSServiceErr_NoError || error_code == kDNSServiceErr_NameConflict) { 2408 // If the update is pending, it means that we just finished registering this record for the first time, 2409 // so we can count it as complete and check to see if there is any work left to do; if not, we call 2410 // srp_mdns_update_finished to apply the update to the host object. 2411 const char *note = " has completed."; 2412 if (record->update_pending) { 2413 record->update_pending = false; 2414 if (update != NULL) { 2415 update->num_records_completed++; 2416 if (update->num_records_completed == update->num_records_started && 2417 update->num_instances_completed == update->num_instances_started) 2418 { 2419 srp_mdns_update_finished(update); 2420 } 2421 } 2422 } else { 2423 note = " got spurious success callback after completion."; 2424 } 2425 2426 if (error_code != kDNSServiceErr_NoError) { 2427 // Shared record is no longer good. 2428 srp_mdns_shared_record_remove(host->server_state, record); 2429 note = " completed with conflict."; 2430 srp_schedule_host_record_retry(record); 2431 } 2432 2433 if (record->rrtype == dns_rrtype_a) { 2434 IPv4_ADDR_GEN_SRP(record->rdata, addr_buf); 2435 INFO("registration for host " PRI_S_SRP " address " PRI_IPv4_ADDR_SRP PUB_S_SRP, 2436 host->registered_name, IPv4_ADDR_PARAM_SRP(record->rdata, addr_buf), note); 2437 } else if (record->rrtype == dns_rrtype_aaaa) { 2438 SEGMENTED_IPv6_ADDR_GEN_SRP(record->rdata, addr_buf); 2439 INFO("registration for host " PRI_S_SRP " address " PRI_SEGMENTED_IPv6_ADDR_SRP PUB_S_SRP, 2440 host->registered_name, SEGMENTED_IPv6_ADDR_PARAM_SRP(record->rdata, addr_buf), note); 2441 } else if (record->rrtype == dns_rrtype_key) { 2442 INFO("registration for host " PRI_S_SRP " key" PUB_S_SRP, host->registered_name, note); 2443 } else { 2444 INFO("registration for host " PRI_S_SRP " unknown record type %d " PUB_S_SRP, host->registered_name, record->rrtype, note); 2445 } 2446 } else { 2447 if (record->rrtype == dns_rrtype_a) { 2448 IPv4_ADDR_GEN_SRP(record->rdata, addr_buf); 2449 INFO("registration for host " PRI_S_SRP " address " PRI_IPv4_ADDR_SRP " failed, error code = %d.", 2450 host->registered_name, IPv4_ADDR_PARAM_SRP(record->rdata, addr_buf), error_code); 2451 } else if (record->rrtype == dns_rrtype_aaaa) { 2452 SEGMENTED_IPv6_ADDR_GEN_SRP(record->rdata, addr_buf); 2453 INFO("registration for host " PRI_S_SRP " address " PRI_SEGMENTED_IPv6_ADDR_SRP " failed, error code = %d.", 2454 host->registered_name, SEGMENTED_IPv6_ADDR_PARAM_SRP(record->rdata, addr_buf), error_code); 2455 } else if (record->rrtype == dns_rrtype_key) { 2456 INFO("registration for host " PRI_S_SRP " key failed, error code = %d.", host->registered_name, error_code); 2457 } else { 2458 INFO("registration for host " PRI_S_SRP " unknown record type %d failed, error code = %d.", 2459 host->registered_name, record->rrtype, error_code); 2460 } 2461 2462 // If the reason this failed is that we couldn't talk to mDNSResponder, or mDNSResponder disconnected, then we want to retry 2463 // later on in the hopes that mDNSResponder will come back. 2464 if (error_code == kDNSServiceErr_ServiceNotRunning || error_code == kDNSServiceErr_DefunctConnection) { 2465 service_disconnected(host->server_state, record->shared_txn); 2466 if (update != NULL) { 2467 wait_retry(host); 2468 } 2469 } else { 2470 // The other error we could get is a name conflict. This means that some other advertising proxy or host on 2471 // the network is advertising the hostname we chose, and either got there first with no TSR record, or got 2472 // its copy of the host information later than ours. So if we get a name conflict, it's up to the client or 2473 // the replication peer to make the next move. 2474 2475 if (update != NULL) { 2476 update_failed(update, (error_code == kDNSServiceErr_NameConflict 2477 ? dns_rcode_yxdomain 2478 : dns_rcode_servfail), true, true); 2479 } else { 2480 } 2481 } 2482 // Regardless of what else happens, this transaction is dead, so get rid of our references to it. 2483 srp_mdns_shared_record_remove(host->server_state, record); 2484 } 2485 if (update != NULL) { 2486 RELEASE_HERE(update, adv_update); 2487 } 2488 RELEASE_HERE(record, adv_record); // Release the reference to the record that we retained at the beginning 2489 } 2490 2491 static adv_instance_t * 2492 adv_instance_create(service_instance_t *raw, adv_host_t *host, adv_update_t *update) 2493 { 2494 char service_type[DNS_MAX_LABEL_SIZE_ESCAPED * 2 + 2]; // sizeof '.' + sizeof '\0'. 2495 char instance_name[DNS_MAX_NAME_SIZE_ESCAPED + 1]; 2496 uint8_t *txt_data; 2497 2498 // Allocate the raw registration 2499 adv_instance_t *instance = calloc(1, sizeof *instance); 2500 if (instance == NULL) { 2501 ERROR("adv_instance:create: unable to allocate raw registration struct."); 2502 return NULL; 2503 } 2504 RETAIN_HERE(instance, adv_instance); 2505 instance->host = host; 2506 RETAIN_HERE(instance->host, adv_host); 2507 instance->update = update; 2508 RETAIN_HERE(instance->update, adv_update); 2509 2510 // SRV records have priority, weight and port, but DNSServiceRegister only uses port. 2511 instance->port = (raw->srv == NULL) ? 0 : raw->srv->data.srv.port; 2512 2513 // Make a presentation-format version of the service name. 2514 if (!extract_instance_name(instance_name, sizeof instance_name, service_type, sizeof service_type, raw)) { 2515 RELEASE_HERE(instance, adv_instance); 2516 return NULL; 2517 } 2518 2519 instance->instance_name = strdup(instance_name); 2520 if (instance->instance_name == NULL) { 2521 ERROR("adv_instance:create: unable to allocate instance name."); 2522 RELEASE_HERE(instance, adv_instance); 2523 return NULL; 2524 } 2525 instance->service_type = strdup(service_type); 2526 if (instance->service_type == NULL) { 2527 ERROR("adv_instance:create: unable to allocate instance type."); 2528 RELEASE_HERE(instance, adv_instance); 2529 return NULL; 2530 } 2531 2532 // Allocate the text record buffer 2533 if (raw->txt != NULL) { 2534 txt_data = malloc(raw->txt->data.txt.len); 2535 if (txt_data == NULL) { 2536 RELEASE_HERE(instance, adv_instance); 2537 ERROR("adv_instance:create: unable to allocate txt_data buffer"); 2538 return NULL; 2539 } 2540 // Format the txt buffer as required by DNSServiceRegister(). 2541 memcpy(txt_data, raw->txt->data.txt.data, raw->txt->data.txt.len); 2542 instance->txt_data = txt_data; 2543 instance->txt_length = raw->txt->data.txt.len; 2544 } else { 2545 instance->txt_data = NULL; 2546 instance->txt_length = 0; 2547 } 2548 2549 // If the service_instance_t is marked to skip updating, mark the adv_instance_t as well. 2550 instance->skip_update = raw->skip_update; 2551 2552 return instance; 2553 } 2554 2555 #define adv_record_create(rrtype, rdlen, rdata, host) \ 2556 adv_record_create_(rrtype, rdlen, rdata, host, __FILE__, __LINE__) 2557 static adv_record_t * 2558 adv_record_create_(uint16_t rrtype, uint16_t rdlen, uint8_t *rdata, adv_host_t *host, const char *file, int line) 2559 { 2560 2561 adv_record_t *new_record = calloc(1, sizeof(*new_record) + rdlen - 1); 2562 if (new_record == NULL) { 2563 ERROR("no memory for new_record"); 2564 return NULL; 2565 } 2566 new_record->rdata = malloc(rdlen); 2567 if (new_record->rdata == NULL) { 2568 ERROR("no memory for new_record->rdata"); 2569 free(new_record); 2570 return NULL; 2571 } 2572 new_record->host = host; 2573 RETAIN(host, adv_host); 2574 new_record->rrtype = rrtype; 2575 new_record->rdlen = rdlen; 2576 memcpy(new_record->rdata, rdata, rdlen); 2577 RETAIN(new_record, adv_record); 2578 return new_record; 2579 } 2580 2581 // Given a pair of service types which may or may not have subtypes, e.g. _foo._tcp, which doesn't have subtypes, or 2582 // _foo.tcp,bar, which does, return true if type1 matches the type2 for the base type, ignoring subtypes. 2583 static bool 2584 service_types_equal(const char *type1, const char *type2) 2585 { 2586 size_t len1; 2587 char *comma1 = strchr(type1, ','); 2588 if (comma1 == NULL) { 2589 len1 = strlen(type1); 2590 } else { 2591 len1 = comma1 - type1; 2592 } 2593 char *comma2 = strchr(type2, ','); 2594 size_t len2; 2595 if (comma2 != NULL) { 2596 len2 = comma2 - type2; 2597 } else { 2598 len2 = strlen(type2); 2599 } 2600 if (len1 != len2) { 2601 return false; 2602 } 2603 if (memcmp(type2, type1, len1)) { 2604 return false; 2605 } 2606 return true; 2607 } 2608 2609 DNSServiceAttributeRef 2610 srp_adv_host_tsr_attribute_generate(adv_host_t *host, char *time_buf, size_t time_buf_size) 2611 { 2612 message_t *message = NULL; 2613 if (host->update != NULL && host->update->client != NULL && host->update->client->message != NULL) { 2614 message = host->update->client->message; 2615 } else if (host->update == NULL && host->message != NULL) { 2616 message = host->message; 2617 } 2618 return srp_message_tsr_attribute_generate(message, host->key_id, time_buf, time_buf_size); 2619 } 2620 2621 static bool 2622 register_host_record(adv_host_t *host, adv_record_t *record, bool skipping) 2623 { 2624 int err; 2625 2626 // If this record is already registered, get rid of the old transaction. 2627 if (record->rref != NULL && !skipping) { 2628 srp_mdns_shared_record_remove(host->server_state, record); 2629 } 2630 2631 // If we don't yet have a shared connection, create one. 2632 if (!srp_mdns_shared_registration_txn_setup(host->server_state)) { 2633 return false; 2634 } 2635 2636 const DNSServiceRef service_ref = host->server_state->shared_registration_txn->sdref; 2637 2638 if (record->rrtype == dns_rrtype_a) { 2639 IPv4_ADDR_GEN_SRP(record->rdata, rdata_buf); 2640 INFO(PUB_S_SRP "DNSServiceRegisterRecord(%p %p %d %d %s %d %d %d " PRI_IPv4_ADDR_SRP " %d %p %p)", 2641 skipping ? "skipping " : "", service_ref, &record->rref, kDNSServiceFlagsShared, 2642 host->server_state->advertise_interface, host->registered_name, record->rrtype, dns_qclass_in, 2643 record->rdlen, IPv4_ADDR_PARAM_SRP(record->rdata, rdata_buf), 2644 ADDRESS_RECORD_TTL, register_host_record_completion, record); 2645 } else if (record->rrtype == dns_rrtype_aaaa) { 2646 SEGMENTED_IPv6_ADDR_GEN_SRP(record->rdata, rdata_buf); 2647 INFO(PUB_S_SRP "DNSServiceRegisterRecord(%p %p %d %d %s %d %d %d " PRI_SEGMENTED_IPv6_ADDR_SRP " %d %p %p)", 2648 skipping ? "skipping " : "", service_ref, &record->rref, kDNSServiceFlagsShared, 2649 host->server_state->advertise_interface, host->registered_name, record->rrtype, dns_qclass_in, 2650 record->rdlen, SEGMENTED_IPv6_ADDR_PARAM_SRP(record->rdata, rdata_buf), 2651 ADDRESS_RECORD_TTL, register_host_record_completion, record); 2652 } else { 2653 INFO(PUB_S_SRP "DNSServiceRegisterRecord(%p %p %d %d %s %d %d %d %p %d %p %p)", 2654 skipping ? "skipping " : "", service_ref, &record->rref, 2655 kDNSServiceFlagsShared, 2656 host->server_state->advertise_interface, host->registered_name, 2657 record->rrtype, dns_qclass_in, record->rdlen, record->rdata, ADDRESS_RECORD_TTL, 2658 register_host_record_completion, record); 2659 } 2660 // If we're skipping, we don't actually have to do any work. 2661 if (skipping) { 2662 return true; 2663 } 2664 2665 char time_buf[TSR_TIMESTAMP_STRING_LEN]; 2666 DNSServiceAttributeRef tsr_attribute = 2667 srp_adv_host_tsr_attribute_generate(host, time_buf, sizeof(time_buf)); 2668 if (tsr_attribute == NULL) { 2669 ERROR("Failed to create new DNSServiceAttributeRef"); 2670 return false; 2671 } else { 2672 err = dns_service_register_record_wa(host->server_state, service_ref, &record->rref, 2673 kDNSServiceFlagsKnownUnique, 2674 host->server_state->advertise_interface, host->registered_name, 2675 record->rrtype, dns_qclass_in, record->rdlen, record->rdata, 2676 ADDRESS_RECORD_TTL, tsr_attribute, register_host_record_completion, 2677 record); 2678 DNSServiceAttributeDeallocate(tsr_attribute); 2679 if (err == kDNSServiceErr_NoError) { 2680 INFO("DNSServiceRegisterRecord for " PRI_S_SRP ", TSR set to " PUB_S_SRP " (record %p rref %p)", 2681 host->name, time_buf, record, record->rref); 2682 } 2683 } 2684 2685 if (err != kDNSServiceErr_NoError) { 2686 if (err == kDNSServiceErr_ServiceNotRunning || err == kDNSServiceErr_DefunctConnection || 2687 err == kDNSServiceErr_BadParam || err == kDNSServiceErr_BadReference || err == 1) 2688 { 2689 if (err == 1) { // This is for an old bug that probably doesn't happen anymore. 2690 FAULT("bogus error code 1"); 2691 } 2692 INFO("DNSServiceRegisterRecord failed on host " PUB_S_SRP ": " PUB_S_SRP " (record %p)", host->name, 2693 err == kDNSServiceErr_ServiceNotRunning ? "not running" : "defunct", record); 2694 service_disconnected(host->server_state, (intptr_t)host->server_state->shared_registration_txn); 2695 } else { 2696 INFO("DNSServiceRegisterRecord failed: %d (record %p)", err, record); 2697 } 2698 return false; 2699 } 2700 record->shared_txn = (intptr_t)host->server_state->shared_registration_txn; 2701 RETAIN_HERE(record, adv_record); // for the callback 2702 if (host->update != NULL) { 2703 record->update_pending = true; 2704 } 2705 return true; 2706 } 2707 2708 static bool 2709 update_instance_tsr(adv_instance_t *instance, adv_instance_t *new_instance) 2710 { 2711 int err = kDNSServiceErr_NoError; 2712 bool success = false; 2713 2714 if (instance->txn == NULL) { 2715 ERROR("txn is NULL updating instance TSR."); 2716 goto out; 2717 } 2718 if (instance->txn->sdref == NULL) { 2719 ERROR("sdref is NULL when updating instance TSR."); 2720 goto out; 2721 } 2722 // Currently if we want to update the rdata, we need to do that separately from the TSR. 2723 if (new_instance != NULL) { 2724 if (instance->skip_update) { 2725 err = kDNSServiceErr_NoError; 2726 } else { 2727 err = dns_service_update_record(instance->host->server_state, instance->txn->sdref, 2728 NULL, 0, new_instance->txt_length, new_instance->txt_data, 0); 2729 } 2730 if (err != kDNSServiceErr_NoError) { 2731 INFO("DNSServiceUpdateRecord for instance " PRI_S_SRP " TXT record failed: %d (instance %p)", 2732 instance->instance_name, err, instance); 2733 goto out; 2734 } else { 2735 INFO("updated TXT record for " PRI_S_SRP " . " PRI_S_SRP " (instance %p sdref %p).", 2736 instance->instance_name, instance->service_type, instance, instance->txn->sdref); 2737 success = true; 2738 } 2739 } 2740 2741 DNSServiceAttributeRef attr; 2742 2743 if (instance->skip_update) { 2744 INFO("skipping DNSServiceUpdateRecord for instance " PRI_S_SRP " TSR (instance %p)", 2745 instance->instance_name, instance); 2746 } else { 2747 success = false; 2748 attr = DNSServiceAttributeCreate(); 2749 if (attr == NULL) { 2750 ERROR("failed to create new DNSServiceAttributeRef"); 2751 } else { 2752 uint32_t offset = 0; 2753 char time_buf[TSR_TIMESTAMP_STRING_LEN]; 2754 if (instance->update != NULL && instance->update->client != NULL && instance->update->client->message != NULL && 2755 instance->update->client->message->received_time != 0) 2756 { 2757 offset = (uint32_t)(srp_time() - instance->update->client->message->received_time); 2758 srp_format_time_offset(time_buf, sizeof(time_buf), offset); 2759 } else { 2760 static char msg[] = "now"; 2761 memcpy(time_buf, msg, sizeof(msg)); 2762 } 2763 if (_DNSSD_API_AVAILABLE_FALL_2024) { 2764 DNSServiceAttributeSetHostKeyHash(attr, instance->host->key_id); 2765 } 2766 DNSServiceAttributeSetTimestamp(attr, offset); 2767 err = dns_service_update_record_wa(instance->host->server_state, 2768 instance->txn->sdref, NULL, 0, 0, NULL, 0, attr); 2769 DNSServiceAttributeDeallocate(attr); 2770 if (err == kDNSServiceErr_NoError) { 2771 INFO("DNSServiceUpdateRecord for " PRI_S_SRP ", TSR set to " PUB_S_SRP " (instance %p sdref %p)", 2772 instance->host == NULL ? "<null>" : instance->host->name, time_buf, instance, instance->txn->sdref); 2773 success = true; 2774 } else { 2775 INFO("DNSServiceUpdateRecord for instance " PRI_S_SRP ", TSR failed: %d (instance %p sdref %p)", 2776 instance->instance_name, err, instance, instance->txn->sdref); 2777 } 2778 } 2779 } 2780 2781 out: 2782 if (success == false) { 2783 if (instance->txn != NULL) { 2784 // We should never get a bad reference error. 2785 if (err == kDNSServiceErr_BadReference || err == kDNSServiceErr_BadParam) { 2786 FAULT("we got a bad reference error: why?"); 2787 } 2788 // For all errors, we should cancel and release the transaction. 2789 ioloop_dnssd_txn_cancel_srp(instance->host->server_state, instance->txn); 2790 ioloop_dnssd_txn_release(instance->txn); 2791 instance->txn = NULL; 2792 } 2793 } else if (new_instance != NULL) { 2794 // If we have new_instance, the caller is going to get rid of it, so we need to 2795 // steal the (possibly changed) data from it and put it on instance. 2796 free(instance->txt_data); 2797 instance->txt_data = new_instance->txt_data; 2798 instance->txt_length = new_instance->txt_length; 2799 new_instance->txt_data = NULL; 2800 new_instance->txt_length = 0; 2801 } 2802 return success; 2803 } 2804 2805 static void 2806 update_host_tsr(adv_record_t *record, adv_update_t *update) 2807 { 2808 DNSServiceAttributeRef attr; 2809 int err; 2810 dnssd_txn_t *shared_txn; 2811 2812 if (record->host == NULL || record->rref == NULL) { 2813 ERROR("record->host[%p], record->rref[%p] when we update host TSR.", record->host, record->rref); 2814 return; 2815 } 2816 2817 shared_txn = record->host->server_state->shared_registration_txn; 2818 if (shared_txn == NULL) { 2819 ERROR("shared_txn is NULL when we update host TSR."); 2820 return; 2821 } 2822 if (shared_txn->sdref == NULL) { 2823 ERROR("shared_txn->sdref is NULL when we update host TSR."); 2824 return; 2825 } 2826 2827 attr = DNSServiceAttributeCreate(); 2828 if (attr == NULL) { 2829 ERROR("failed to create new DNSServiceAttributeRef"); 2830 } else { 2831 uint32_t offset = 0; 2832 char time_buf[TSR_TIMESTAMP_STRING_LEN]; 2833 if (update->client != NULL && update->client->message != NULL && update->client->message->received_time != 0) { 2834 offset = (uint32_t)(srp_time() - update->client->message->received_time); 2835 srp_format_time_offset(time_buf, sizeof(time_buf), offset); 2836 } else { 2837 static char msg[] = "now"; 2838 memcpy(time_buf, msg, sizeof(msg)); 2839 } 2840 if (_DNSSD_API_AVAILABLE_FALL_2024) { 2841 DNSServiceAttributeSetHostKeyHash(attr, record->host->key_id); 2842 } 2843 DNSServiceAttributeSetTimestamp(attr, offset); 2844 err = dns_service_update_record_wa(record->host->server_state, 2845 shared_txn->sdref, record->rref, 0, 0, NULL, 0, attr); 2846 DNSServiceAttributeDeallocate(attr); 2847 if (err == kDNSServiceErr_NoError) { 2848 INFO("DNSServiceUpdateRecord TSR for " PRI_S_SRP " set to " PUB_S_SRP " (record %p rref %p)", 2849 record->host == NULL ? "<null>" : record->host->name, time_buf, record, record->rref); 2850 } else { 2851 INFO("DNSServiceUpdateRecordWithAttribute for host tsr failed: %d (record %p rref %p)", 2852 err, record, record->rref); 2853 } 2854 } 2855 } 2856 2857 // When we need to register a host with mDNSResponder, start_host_update is called. This can be either because 2858 // we just got a new registration for a host, or if the daemon dies and we need to re-do the host registration. 2859 // This just registers the host; if that succeeds, then we register the service instances. 2860 static void 2861 start_host_update(adv_host_t *host) 2862 { 2863 adv_update_t *update = host->update; 2864 #ifdef USE_DNSSERVICE_QUEUING 2865 int err; 2866 #endif 2867 int i; 2868 2869 // No work to do? 2870 if (update == NULL) { 2871 ERROR("start_host_update: no work to do for host " PRI_S_SRP, host->registered_name); 2872 return; 2873 } 2874 2875 bool skip_host_updates = (update->client != NULL && update->client->skip_host_updates); 2876 2877 2878 update->num_records_started = 0; 2879 2880 // Add all of the addresses that have been registered. 2881 if (update->add_addresses != NULL) { 2882 for (i = 0; i < update->add_addresses->num; i++) { 2883 if (update->add_addresses->vec[i] != NULL) { 2884 if (!register_host_record(host, update->add_addresses->vec[i], skip_host_updates)) { 2885 update_failed(update, dns_rcode_servfail, true, true); 2886 return; 2887 } else if (!skip_host_updates) { 2888 update->num_records_started++; 2889 } 2890 } 2891 } 2892 } 2893 2894 // It's possible that some existing addresses are no longer registered because of a service disconnect. Check all the 2895 // existing addresses for this situation: if an existing address has no rref, and does not appear in update->remove_addrs, 2896 // then re-register it. 2897 if (host->addresses != NULL) { 2898 for (i = 0; i < host->addresses->num; i++) { 2899 adv_record_t *record = host->addresses->vec[i]; 2900 adv_record_t *remove_address = NULL; 2901 if (update->remove_addresses != NULL) { 2902 remove_address = update->remove_addresses->vec[i]; 2903 } 2904 if (remove_address == NULL && record != NULL && record->rref == NULL) { 2905 host->addresses->vec[i]->update = update; 2906 RETAIN_HERE(host->addresses->vec[i]->update, adv_update); 2907 if (!register_host_record(host, record, skip_host_updates)) { 2908 update_failed(update, dns_rcode_servfail, true, true); 2909 return; 2910 } else if (!skip_host_updates) { 2911 update->num_records_started++; 2912 } 2913 } 2914 } 2915 } 2916 2917 if (update->key != NULL) { 2918 if (!register_host_record(host, update->key, skip_host_updates)) { 2919 update_failed(update, dns_rcode_servfail, true, true); 2920 return; 2921 } else if (!skip_host_updates) { 2922 update->num_records_started++; 2923 } 2924 } 2925 2926 // If the shared transaction has changed since the key record was added, add it again. 2927 if (update->key == NULL && host->key_record != NULL && 2928 (host->key_record->shared_txn != (intptr_t)host->server_state->shared_registration_txn || 2929 host->key_record->rref == NULL)) 2930 { 2931 update->key = host->key_record; 2932 RETAIN_HERE(update->key, adv_record); 2933 RELEASE_HERE(host->key_record, adv_record); 2934 host->key_record = NULL; 2935 update->key->rref = NULL; 2936 update->key->update = update; 2937 RETAIN_HERE(update, adv_update); 2938 if (!register_host_record(host, update->key, skip_host_updates)) { 2939 update_failed(update, dns_rcode_servfail, true, true); 2940 return; 2941 } else if (!skip_host_updates) { 2942 update->num_records_started++; 2943 } 2944 } 2945 2946 if (update->num_records_started == 0) { 2947 adv_record_t *record = update->key != NULL ? update->key : (host->key_record != NULL ? host->key_record : NULL); 2948 if (record == NULL) { 2949 } else { 2950 if (record->rref == NULL) { 2951 if (!register_host_record(host, record, skip_host_updates)) { 2952 update_failed(update, dns_rcode_servfail, true, true); 2953 return; 2954 } else if (!skip_host_updates) { 2955 update->num_records_started++; 2956 } 2957 } else if (!skip_host_updates) { 2958 update_host_tsr(record, update); 2959 } 2960 } 2961 } 2962 2963 if (host->instances != NULL) { 2964 // For each service instance that's being added, register it. 2965 if (update->add_instances != NULL) { 2966 for (i = 0; i < update->add_instances->num; i++) { 2967 if (update->add_instances->vec[i] != NULL) { 2968 if (!register_instance(update->add_instances->vec[i])) { 2969 update_failed(update, dns_rcode_servfail, true, true); 2970 return; 2971 } 2972 } 2973 } 2974 } 2975 2976 // For each service instance that's being renewed, update its TSR if the original registration still exist, 2977 // Otherwise re-register the instance. 2978 if (update->renew_instances != NULL) { 2979 for (i = 0; i < update->renew_instances->num; i++) { 2980 if (update->renew_instances->vec[i] != NULL) { 2981 adv_instance_t *instance = update->renew_instances->vec[i]; 2982 bool must_update = true; 2983 bool renew_failed = instance->txn != NULL; 2984 if (instance->txn != NULL) { 2985 bool must_remove = false; 2986 // Make sure the instance is still registered and is registered on the current shared connection. 2987 if (instance->txn->sdref != NULL) { 2988 if (((intptr_t)host->server_state->shared_registration_txn == instance->shared_txn)) { 2989 if (update_instance_tsr(instance, NULL)) { 2990 must_remove = false; 2991 must_update = false; 2992 instance->recent_message = (ptrdiff_t)update->client->message; 2993 } else { 2994 INFO("instance " PRI_S_SRP " (%p) tsr update failed, re-registering", 2995 instance->instance_name, instance); 2996 must_remove = true; 2997 } 2998 } else { 2999 // If the shared transaction has changed, then the registration no longer exists, and 3000 // the sdref is no longer valid. 3001 INFO("instance " PRI_S_SRP " (%p) shared connection (%" PRIxPTR ") is stale, re-registering", 3002 instance->instance_name, instance, instance->shared_txn); 3003 instance->txn->sdref = NULL; 3004 must_remove = true; 3005 must_update = true; 3006 renew_failed = false; 3007 } 3008 } 3009 if (must_remove) { 3010 // If not, dispose of the transaction and re-register. 3011 if (instance->txn != NULL) { 3012 ioloop_dnssd_txn_cancel_srp(host->server_state, instance->txn); 3013 ioloop_dnssd_txn_release(instance->txn); 3014 instance->txn = NULL; 3015 } 3016 } 3017 } 3018 if (must_update) { 3019 if (renew_failed) { 3020 INFO(PRI_S_SRP " (%p): failed to update TSR, re-registering", instance->instance_name, instance); 3021 } 3022 if (!register_instance(update->renew_instances->vec[i])) { 3023 update_failed(update, dns_rcode_servfail, true, true); 3024 return; 3025 } 3026 } 3027 } 3028 } 3029 } 3030 3031 // Sanity check that the instance vector sizes match between host and update. 3032 if (update->update_instances != NULL && update->update_instances->num != host->instances->num) { 3033 FAULT("update instance count %d differs from host instance count %d", 3034 update->update_instances->num, host->instances->num); 3035 update_failed(update, dns_rcode_servfail, true, true); 3036 return; 3037 } 3038 if (update->remove_instances != NULL && update->remove_instances->num != host->instances->num) { 3039 FAULT("delete instance count %d differs from host instance count %d", 3040 update->remove_instances->num, host->instances->num); 3041 update_failed(update, dns_rcode_servfail, true, true); 3042 return; 3043 } 3044 for (i = 0; i < host->instances->num; i++) { 3045 adv_instance_t *update_instance = update->update_instances->vec[i]; 3046 if (update_instance != NULL && !update_instance->removed) { 3047 adv_instance_t *host_instance = host->instances->vec[i]; 3048 bool must_register = true; 3049 // Check to see if just the TXT record changes; in this case use DNSServiceUpdateRecord rather than re-registering 3050 // the instance. If we can't update, we have to remove and then add. We could do this as a pair of atomic transactions 3051 // if we used DNSServiceRegisterRecord rather than DNSServiceRegister, but currently we don't do that. 3052 // Of course if the previous registration is no longer valid, re-register. 3053 if (host_instance->txn != NULL && host_instance->txn->sdref != NULL && host->server_state != NULL && 3054 ((intptr_t)host->server_state->shared_registration_txn == host_instance->shared_txn)) 3055 { 3056 if (update_instance->port == host_instance->port && 3057 update_instance->txt_length != 0 && 3058 memcmp(update_instance->txt_data, host_instance->txt_data, update_instance->txt_length)) 3059 { 3060 // If we are able to update the TXT record using DNSServiceUpdateRecord, we don't actually need 3061 // this update instance. 3062 if (update_instance_tsr(host_instance, update_instance)) { 3063 host_instance->recent_message = (ptrdiff_t)update->client->message; 3064 RELEASE_HERE(update->update_instances->vec[i], adv_instance); 3065 update_instance = NULL; 3066 update->update_instances->vec[i] = NULL; 3067 must_register = false; 3068 } 3069 } 3070 } 3071 if (must_register) { 3072 if (host_instance->txn != NULL) { 3073 ioloop_dnssd_txn_cancel_srp(host->server_state, host->instances->vec[i]->txn); 3074 ioloop_dnssd_txn_release(host->instances->vec[i]->txn); 3075 host->instances->vec[i]->txn = NULL; 3076 } 3077 3078 if (!register_instance(update->update_instances->vec[i])) { 3079 INFO("register instance failed."); 3080 update_failed(update, dns_rcode_servfail, true, true); 3081 return; 3082 } 3083 } 3084 } 3085 } 3086 } 3087 3088 if (update->num_instances_started == 0 && update->num_records_started == 0) { 3089 INFO("no service or record updates, so we're finished."); 3090 srp_mdns_update_finished(update); 3091 return; 3092 } 3093 3094 } 3095 3096 // When a host has no update in progress, and there is a client update ready to process, we need to analyze 3097 // the client update to see what work needs to be done. This work is constructed as an translation from the 3098 // raw update sent by the client (host->clients) into a prepared update that can be used directly to 3099 // register the information with mDNSResponder. 3100 // 3101 // Normally a host will only have one prepared update in progress; however, if we lose our connection to 3102 // mDNSResponder, then we need to re-create the host advertisement. If there was an update in progress when 3103 // this happened, we then need to reapply that as well. In this case an update is constructed from the host, to 3104 // get the host into the intended state, and the in-progress update is pushed below that; when the host has 3105 // been re-created on the daemon, the pending update is popped back off the stack and restarted. 3106 static void 3107 prepare_update(adv_host_t *host, client_update_t *client_update) 3108 { 3109 host_addr_t *addr; 3110 int i, j; 3111 service_instance_t *instance; 3112 adv_record_vec_t *remove_addrs = NULL; 3113 int num_remove_addrs = 0; 3114 adv_record_vec_t *add_addrs = NULL; 3115 int num_add_addrs = 0; 3116 int num_update_instances = 0; 3117 int num_add_instances = 0; 3118 int num_remove_instances = 0; 3119 int num_renew_instances = 0; 3120 adv_instance_vec_t *update_instances = NULL, *add_instances = NULL; 3121 adv_instance_vec_t *remove_instances = NULL, *renew_instances = NULL; 3122 adv_update_t *update = NULL; 3123 3124 // Work to do: 3125 // - Figure out what address records to add and what address records to delete. 3126 // - Because we can only have one address record at a time currently, figure out which address record we want 3127 // - If we already have an address record published, and it's the same, do nothing 3128 // - else if we already have an address record published, and it's changed to a different address, do an update 3129 // - else if we have a new address record, publish it 3130 // - else publish the key to hold the name 3131 // - Go through the set of service instances, identifying deletes, changes and adds 3132 // - We don't currently allow deletes, but what that would look like would be an instance with no SRV or TXT 3133 // record. 3134 // - What about a delete that keeps the name but un-advertises the service? How would we indicate that? 3135 // Maybe if there's no service PTR for the service? 3136 // - Changes means that the contents of the text record changed, or the contents of the SRV record 3137 // changed (but not the hostname) or both. 3138 // - New means that we don't have a service with that service instance name on the host (and we previously 3139 // eliminated the possibility that it exists on some other host). 3140 3141 // Allocate the update structure. 3142 update = calloc(1, sizeof *update); 3143 if (update == NULL) { 3144 ERROR("no memory for update."); 3145 goto fail; 3146 } 3147 RETAIN_HERE(update, adv_update); // For the lifetime of this function 3148 3149 if (host->re_register_wakeup != NULL) { 3150 ioloop_cancel_wake_event(host->re_register_wakeup); 3151 } 3152 host->re_register_pending = false; 3153 update->start_time = srp_time(); 3154 3155 // The maximum number of addresses we could be deleting is all the ones the host currently has. 3156 if (host->addresses == NULL || host->addresses->num == 0) { 3157 num_remove_addrs = 0; 3158 remove_addrs = NULL; 3159 } else { 3160 num_remove_addrs = host->addresses->num; 3161 if (num_remove_addrs != 0) { 3162 remove_addrs = adv_record_vec_create(num_remove_addrs); 3163 // If we can't allocate space, just wait a bit. 3164 if (remove_addrs == NULL) { 3165 ERROR("no memory for remove_addrs"); 3166 goto fail; 3167 } 3168 remove_addrs->num = num_remove_addrs; 3169 } 3170 } 3171 3172 num_add_addrs = 0; 3173 for (addr = client_update->host->addrs; addr != NULL; addr = addr->next) { 3174 num_add_addrs++; 3175 } 3176 add_addrs = adv_record_vec_create(num_add_addrs); 3177 if (add_addrs == NULL) { 3178 ERROR("no memory for add_addrs"); 3179 goto fail; 3180 } 3181 3182 // Copy all of the addresses in the update into add_addresses 3183 num_add_addrs = 0; 3184 for (addr = client_update->host->addrs; addr; addr = addr->next) { 3185 bool add = true; 3186 for (i = 0; i < num_add_addrs; i++) { 3187 // If the client sends duplicate addresses, only add one of them. 3188 if (add_addrs->vec[i] != NULL && 3189 add_addrs->vec[i]->rrtype == addr->rr.type && 3190 add_addrs->vec[i]->rdlen == (addr->rr.type == dns_rrtype_a ? 4 : 16) && 3191 !memcmp(add_addrs->vec[i]->rdata, (uint8_t *)&addr->rr.data, add_addrs->vec[i]->rdlen)) 3192 { 3193 add = false; 3194 } 3195 } 3196 if (add) { 3197 adv_record_t *prepared_address = adv_record_create(addr->rr.type, addr->rr.type == dns_rrtype_a ? 4 : 16, 3198 (uint8_t *)&addr->rr.data, host); 3199 if (prepared_address == NULL) { 3200 ERROR("No memory for prepared address"); 3201 goto fail; 3202 } 3203 add_addrs->vec[num_add_addrs++] = prepared_address; 3204 } 3205 } 3206 add_addrs->num = num_add_addrs; 3207 for (i = 0; i < add_addrs->num; i++) { 3208 if (add_addrs->vec[i] != NULL) { 3209 add_addrs->vec[i]->update = update; 3210 RETAIN_HERE(add_addrs->vec[i]->update, adv_update); 3211 } 3212 } 3213 3214 #ifdef DEBUG_HOST_RECORDS_VERBOSE 3215 for (i = 0; i < 2; i++) { 3216 for (j = 0; j < (i ? num_add_addrs : num_remove_addrs); j++) { 3217 adv_record_t *address = i ? add_addrs->vec[j] : (host->addresses != NULL ? host->addresses->vec[j] : NULL); 3218 if (address == NULL) { 3219 INFO(PUB_S_SRP " before: %d NULL", i ? "add" : "rmv", j); 3220 } else { 3221 char foobuf[385], *foop = foobuf; 3222 for (unsigned long k = 0; k < address->rdlen && k * 3 + 1 < sizeof(foobuf); k++) { 3223 snprintf(foop, 4, k ? ":%02x" : "%02x", address->rdata[k]); 3224 foop += k ? 3 : 2; 3225 } 3226 *foop = 0; 3227 INFO(PUB_S_SRP " before: %d rrtype %d rdlen %d rdata " PRI_S_SRP, i ? "add" : "rmv", j, 3228 address->rrtype, address->rdlen, foobuf); 3229 } 3230 } 3231 } 3232 #endif // DEBUG_HOST_RECORDS_VERBOSE 3233 3234 // For every host address, see if it's in add_addresses. If it's not, it needs to be removed. 3235 // If it is, it doesn't need to be added. 3236 if (num_remove_addrs != 0) { 3237 for (i = 0; i < num_remove_addrs; i++) { 3238 if (host->addresses != NULL && host->addresses->vec[i] != NULL) { 3239 remove_addrs->vec[i] = host->addresses->vec[i]; 3240 RETAIN_HERE(remove_addrs->vec[i], adv_record); 3241 } 3242 for (j = 0; j < num_add_addrs; j++) { 3243 // If the address is present in both places, and has a valid registration, remove it from the list of 3244 // addresses to add, and also remove it from the list of addresses to remove. When we're done, all that 3245 // will be remaining in the list to remove will be addresses that weren't present in the add list. 3246 if (remove_addrs->vec[i] != NULL && add_addrs->vec[j] != NULL && 3247 remove_addrs->vec[i]->rref != NULL && host->server_state != NULL && 3248 (intptr_t)host->server_state->shared_registration_txn == remove_addrs->vec[i]->shared_txn && 3249 add_addrs->vec[j]->rrtype == remove_addrs->vec[i]->rrtype && 3250 add_addrs->vec[j]->rdlen == remove_addrs->vec[i]->rdlen && 3251 !memcmp(add_addrs->vec[j]->rdata, remove_addrs->vec[i]->rdata, remove_addrs->vec[i]->rdlen)) 3252 { 3253 RELEASE_HERE(remove_addrs->vec[i], adv_record); 3254 remove_addrs->vec[i] = NULL; 3255 RELEASE_HERE(add_addrs->vec[j], adv_record); 3256 add_addrs->vec[j] = NULL; 3257 } 3258 } 3259 } 3260 remove_addrs->num = num_remove_addrs; 3261 } 3262 3263 #ifdef DEBUG_HOST_RECORDS_VERBOSE 3264 for (i = 0; i < 2; i++) { 3265 for (j = 0; j < (i ? num_add_addrs : num_remove_addrs); j++) { 3266 adv_record_t *address = i ? add_addrs->vec[j] : (remove_addrs != NULL ? remove_addrs->vec[j] : NULL); 3267 if (address == NULL) { 3268 INFO(PUB_S_SRP " after: %d NULL", i ? "add" : "rmv", j); 3269 } else { 3270 char foobuf[385], *foop = foobuf; 3271 for (unsigned long k = 0; k < address->rdlen && k * 3 + 1 < sizeof(foobuf); k++) { 3272 snprintf(foop, 4, k ? ":%02x" : "%02x", address->rdata[k]); 3273 foop += k ? 3 : 2; 3274 } 3275 *foop = 0; 3276 INFO(PUB_S_SRP " after: %d rrtype %d rdlen %d rdata " PRI_S_SRP, i ? "add" : "rmv", j, 3277 address->rrtype, address->rdlen, foobuf); 3278 } 3279 } 3280 } 3281 #endif // DEBUG_HOST_RECORDS_VERBOSE 3282 3283 // Make a key record 3284 if (host->key_record == NULL) { 3285 update->key = adv_record_create(dns_rrtype_key, host->key_rdlen, host->key_rdata, host); 3286 if (update->key == NULL) { 3287 ERROR("no memory for key record"); 3288 goto fail; 3289 } 3290 update->key->update = update; 3291 RETAIN_HERE(update->key->update, adv_update); 3292 } 3293 3294 // We can never update more instances than currently exist for this host. 3295 num_update_instances = host->instances->num; 3296 num_remove_instances = host->instances->num; 3297 num_renew_instances = host->instances->num; 3298 3299 update_instances = adv_instance_vec_create(num_update_instances); 3300 if (update_instances == NULL) { 3301 ERROR("no memory for update_instances"); 3302 goto fail; 3303 } 3304 update_instances->num = num_update_instances; 3305 3306 remove_instances = adv_instance_vec_create(num_remove_instances); 3307 if (remove_instances == NULL) { 3308 ERROR("no memory for remove_instances"); 3309 goto fail; 3310 } 3311 remove_instances->num = num_remove_instances; 3312 3313 renew_instances = adv_instance_vec_create(num_renew_instances); 3314 if (renew_instances == NULL) { 3315 ERROR("no memory for renew_instances"); 3316 goto fail; 3317 } 3318 renew_instances->num = num_renew_instances; 3319 3320 // Handle removes. Service instance removes have to remove the whole service instance, not some subset. 3321 for (delete_t *dp = client_update->removes; dp; dp = dp->next) { 3322 // Removes can be for services or service instances. Because we're acting as an 3323 // Advertising Proxy and not a regular name server, we don't track service instances, 3324 // and so we don't need to match them here. This if statement checks to see if the 3325 // name could possibly be a service instance name followed by a service type. We 3326 // can then extract the putative service instance name and service type and compare; 3327 // if they match, they are in fact those things, and if they don't, we don't care. 3328 if (dp->name != NULL && dp->name->next != NULL && dp->name->next->next != NULL) { 3329 char instance_name[DNS_MAX_LABEL_SIZE_ESCAPED + 1]; 3330 char service_type[DNS_MAX_LABEL_SIZE_ESCAPED + 2]; 3331 3332 dns_name_print_to_limit(dp->name, dp->name->next, instance_name, sizeof(instance_name)); 3333 dns_name_print_to_limit(dp->name->next, dp->name->next->next->next, service_type, sizeof(service_type)); 3334 3335 for (i = 0; i < host->instances->num; i++) { 3336 adv_instance_t *remove_instance = host->instances->vec[i]; 3337 if (remove_instance != NULL) { 3338 if (!strcmp(instance_name, remove_instance->instance_name) && 3339 service_types_equal(service_type, remove_instance->service_type)) 3340 { 3341 remove_instances->vec[i] = remove_instance; 3342 RETAIN_HERE(remove_instances->vec[i], adv_instance); 3343 break; 3344 } 3345 } 3346 } 3347 } 3348 } 3349 3350 // The number of instances to add can be as many as there are instances in the update. 3351 num_add_instances = 0; 3352 for (instance = client_update->instances; instance; instance = instance->next) { 3353 num_add_instances++; 3354 } 3355 add_instances = adv_instance_vec_create(num_add_instances); 3356 if (add_instances == NULL) { 3357 ERROR("prepare_update: no memory for add_instances"); 3358 goto fail; 3359 } 3360 3361 // Convert all of the instances in the client update to adv_instance_t structures for easy comparison. 3362 // Any that are unchanged will have to be freed--oh well. 3363 i = 0; 3364 for (instance = client_update->instances; instance != NULL; instance = instance->next) { 3365 adv_instance_t *prepared_instance = adv_instance_create(instance, host, update); 3366 if (prepared_instance == NULL) { 3367 // prepare_instance logs. 3368 goto fail; 3369 } 3370 if (i >= num_add_instances) { 3371 FAULT("while preparing client update instances, i >= num_add_instances"); 3372 RELEASE_HERE(prepared_instance, adv_instance); 3373 prepared_instance = NULL; 3374 goto fail; 3375 } 3376 3377 prepared_instance->anycast = false; 3378 if (client_update != NULL && client_update->connection != NULL) { 3379 const struct sockaddr *server_addr = connection_get_local_address(client_update->message); 3380 if (server_addr && server_addr->sa_family == AF_INET6) { 3381 const struct in6_addr *const ipv6_address = &(((const struct sockaddr_in6 *)server_addr)->sin6_addr); 3382 uint16_t server_port = ntohs(((const struct sockaddr_in6 *)server_addr)->sin6_port); 3383 SEGMENTED_IPv6_ADDR_GEN_SRP(ipv6_address, addr_buf); 3384 INFO("server address " PRI_SEGMENTED_IPv6_ADDR_SRP "; server port %d", 3385 SEGMENTED_IPv6_ADDR_PARAM_SRP(ipv6_address, addr_buf), server_port); 3386 if (is_thread_mesh_anycast_address(ipv6_address) && server_port == 53) { 3387 prepared_instance->anycast = true; 3388 } 3389 } 3390 } 3391 add_instances->vec[i++] = prepared_instance; 3392 } 3393 add_instances->num = i; 3394 3395 // The instances in the update are now in add_instances. If they are updates, move them to update_instances. If 3396 // they are unchanged, free them and null them out, and remember the current instance in renew_instances. If they 3397 // are adds, leave them. 3398 for (i = 0; i < num_add_instances; i++) { 3399 adv_instance_t *add_instance = add_instances->vec[i]; 3400 3401 if (add_instance != NULL) { 3402 for (j = 0; j < host->instances->num; j++) { 3403 adv_instance_t *host_instance = host->instances->vec[j]; 3404 3405 // See if the instance names match. 3406 if (host_instance != NULL && 3407 !strcmp(add_instance->instance_name, host_instance->instance_name) && 3408 service_types_equal(add_instance->service_type, host_instance->service_type)) 3409 { 3410 // If the rdata is the same, and the service type is the same (including subtypes), and it's not 3411 // deleted, it's not an add or an update. 3412 if (!host_instance->removed && add_instance->txt_length == host_instance->txt_length && 3413 add_instance->port == host_instance->port && 3414 !strcmp(add_instance->service_type, host_instance->service_type) && 3415 (add_instance->txt_length == 0 || 3416 !memcmp(add_instance->txt_data, host_instance->txt_data, add_instance->txt_length))) 3417 { 3418 RELEASE_HERE(add_instances->vec[i], adv_instance); 3419 add_instances->vec[i] = NULL; 3420 renew_instances->vec[j] = host_instance; 3421 RETAIN_HERE(host_instance, adv_instance); 3422 renew_instances->vec[j]->update = update; 3423 RETAIN_HERE(renew_instances->vec[j]->update, adv_update); 3424 INFO(PRI_S_SRP "." PRI_S_SRP " renewed for host " PRI_S_SRP, 3425 host_instance->instance_name, host_instance->service_type, host->name); 3426 } else { 3427 update_instances->vec[j] = add_instance; 3428 RETAIN_HERE(update_instances->vec[j], adv_instance); 3429 RELEASE_HERE(add_instances->vec[i], adv_instance); 3430 add_instances->vec[i] = NULL; 3431 } 3432 break; 3433 } 3434 } 3435 } 3436 } 3437 3438 // At this point we have figured out all the work we need to do, so hang it off an update structure. 3439 update->host = host; 3440 RETAIN_HERE(update->host, adv_host); 3441 update->client = client_update; 3442 update->remove_addresses = remove_addrs; 3443 update->add_addresses = add_addrs; 3444 update->remove_instances = remove_instances; 3445 update->add_instances = add_instances; 3446 update->update_instances = update_instances; 3447 update->renew_instances = renew_instances; 3448 update->host_lease = client_update->host_lease; 3449 update->key_lease = client_update->key_lease; 3450 3451 // Register any added addresses with threadradiod before we actually advertise them, to avoid a spurious 3452 // address query. 3453 3454 host->update = update; 3455 RETAIN_HERE(host->update, adv_update); 3456 RELEASE_HERE(update, adv_update); 3457 update = NULL; 3458 3459 3460 start_host_update(host); 3461 return; 3462 3463 fail: 3464 if (client_update != NULL) { 3465 srp_parse_client_updates_free(client_update); 3466 client_update = NULL; 3467 } 3468 if (remove_addrs != NULL) { 3469 // Addresses in remove_addrs are owned by the host and don't need to be freed. 3470 RELEASE_HERE(remove_addrs, adv_record_vec); 3471 remove_addrs = NULL; 3472 } 3473 if (add_addrs != NULL) { 3474 RELEASE_HERE(add_addrs, adv_record_vec); 3475 add_addrs = NULL; 3476 } 3477 if (add_instances != NULL) { 3478 RELEASE_HERE(add_instances, adv_instance_vec); 3479 add_instances = NULL; 3480 } 3481 if (remove_instances != NULL) { 3482 RELEASE_HERE(remove_instances, adv_instance_vec); 3483 remove_instances = NULL; 3484 } 3485 if (update_instances != NULL) { 3486 RELEASE_HERE(update_instances, adv_instance_vec); 3487 update_instances = NULL; 3488 } 3489 if (update) { 3490 RELEASE_HERE(update, adv_update); 3491 } 3492 } 3493 3494 typedef enum { missed, match, conflict } instance_outcome_t; 3495 static instance_outcome_t 3496 compare_instance(adv_instance_t *instance, 3497 dns_host_description_t *new_host, adv_host_t *host, 3498 char *instance_name, char *service_type) 3499 { 3500 if (instance == NULL) { 3501 return missed; 3502 } 3503 if (host->removed) { 3504 return missed; 3505 } 3506 if (!strcmp(instance_name, instance->instance_name) && service_types_equal(service_type, instance->service_type)) { 3507 if (!dns_names_equal_text(new_host->name, host->name)) { 3508 return conflict; 3509 } 3510 return match; 3511 } 3512 return missed; 3513 } 3514 3515 bool 3516 srp_update_start(client_update_t *client_update) 3517 { 3518 dns_host_description_t *new_host = client_update->host; 3519 char new_host_name[DNS_MAX_NAME_SIZE_ESCAPED + 1]; 3520 srp_server_t *server_state = client_update->server_state; 3521 uint32_t key_id = 0; 3522 dns_name_print(new_host->name, new_host_name, sizeof new_host_name); 3523 adv_host_t *host = NULL; 3524 srpl_connection_t *srpl_connection = client_update->srpl_connection; 3525 message_t *raw_message = client_update->message; 3526 comm_t *connection = client_update->connection; 3527 3528 3529 // Compute a checksum on the key, ignoring up to three bytes at the end. 3530 for (client_update_t *update = client_update; update != NULL; update = update->next) { 3531 dns_host_description_t *update_host = update->host; 3532 3533 uint32_t update_key_id = 0; 3534 for (unsigned i = 0; i < update_host->key->data.key.len; i += 4) { 3535 update_key_id += ((update_host->key->data.key.key[i] << 24) | (update_host->key->data.key.key[i + 1] << 16) | 3536 (update_host->key->data.key.key[i + 2] << 8) | (update_host->key->data.key.key[i + 3])); 3537 } 3538 if (update == client_update) { 3539 key_id = update_key_id; 3540 } else if (key_id != update_key_id) { 3541 ERROR("update contains multiple key ids %x and %x", key_id, update_key_id); 3542 advertise_finished(NULL, new_host_name, server_state, 3543 srpl_connection, NULL, raw_message, dns_rcode_refused, NULL, false, true); 3544 goto cleanup; 3545 } 3546 } 3547 3548 char seenbuf[200]; 3549 char *already_seen = seenbuf; 3550 const char *plural = ""; 3551 3552 // For replicated updates, check the transaction IDs to make sure we aren't applying an update we've already gotten. 3553 if (srpl_connection != NULL) { 3554 for (host = server_state->hosts; host != NULL; host = host->next) { 3555 if (host->key_id == key_id && !strcmp(host->name, new_host_name)) { 3556 break; 3557 } 3558 } 3559 3560 if (host != NULL) { 3561 bool replay = true; 3562 while (client_update != NULL && replay) { 3563 replay = false; 3564 if (host->message != NULL && host->message->wire.id == client_update->message->wire.id) { 3565 replay = true; 3566 } else if (host->instances != NULL) { 3567 for (int i = 0; i < host->instances->num; i++) { 3568 adv_instance_t *instance = host->instances->vec[i]; 3569 if (instance != NULL) { 3570 if (instance->message != NULL && 3571 instance->message->wire.id == client_update->message->wire.id) 3572 { 3573 replay = true; 3574 break; 3575 } 3576 } 3577 } 3578 } 3579 if (replay) { 3580 client_update_t *skip_update = client_update; 3581 client_update = client_update->next; 3582 if (already_seen != seenbuf) { 3583 plural = "s"; 3584 } 3585 if (already_seen + 6 < &seenbuf[sizeof(seenbuf)]) { 3586 snprintf(already_seen, 6, " %04x", skip_update->message->wire.id); 3587 already_seen += 5; 3588 } 3589 skip_update->next = NULL; 3590 srp_parse_client_updates_free(skip_update); 3591 if (client_update != NULL) { 3592 new_host = client_update->host; 3593 } else { 3594 new_host = NULL; 3595 } 3596 } 3597 } 3598 } 3599 } 3600 if (already_seen != seenbuf) { 3601 INFO("host update for " PRI_S_SRP ", key id %" PRIx32 " " PUB_S_SRP " (skipped xid" PUB_S_SRP PUB_S_SRP ")", 3602 new_host_name, key_id, srpl_connection == NULL ? "" : srpl_connection->name, plural, seenbuf); 3603 } else { 3604 INFO("host update for " PRI_S_SRP ", key id %" PRIx32 " " PUB_S_SRP, 3605 new_host_name, key_id, srpl_connection == NULL ? "" : srpl_connection->name); 3606 } 3607 if (client_update == NULL) { 3608 advertise_finished(host, new_host_name, server_state, srpl_connection, 3609 NULL, raw_message, dns_rcode_noerror, NULL, false, true); 3610 return true; // It's safe to just return here because we've freed all the client updates. 3611 } 3612 3613 service_instance_t *instances = client_update->instances; 3614 delete_t *removes = client_update->removes; 3615 adv_host_t **p_hosts = NULL; 3616 char pres_name[DNS_MAX_NAME_SIZE_ESCAPED + 1]; 3617 service_instance_t *new_instance; 3618 instance_outcome_t outcome = missed; 3619 char instance_name[DNS_MAX_LABEL_SIZE_ESCAPED + 1]; 3620 char service_type[DNS_MAX_LABEL_SIZE_ESCAPED * 2 + 2]; 3621 host_addr_t *addr; 3622 const bool remove = client_update->host_lease == 0; 3623 const char *updatestr = client_update->host_lease == 0 ? "remove" : "update"; 3624 delete_t *dp; 3625 3626 3627 for (addr = new_host->addrs; addr != NULL; addr = addr->next) { 3628 if (addr->rr.type == dns_rrtype_a) { 3629 IPv4_ADDR_GEN_SRP(&addr->rr.data.a.s_addr, addr_buf); 3630 INFO("host " PUB_S_SRP " for " PRI_S_SRP ", address " PRI_IPv4_ADDR_SRP " " PUB_S_SRP, updatestr, 3631 new_host_name, IPv4_ADDR_PARAM_SRP(&addr->rr.data.a.s_addr, addr_buf), 3632 srpl_connection == NULL ? "" : srpl_connection->name); 3633 } else { 3634 SEGMENTED_IPv6_ADDR_GEN_SRP(addr->rr.data.aaaa.s6_addr, addr_buf); 3635 INFO("host " PUB_S_SRP " for " PRI_S_SRP ", address " PRI_SEGMENTED_IPv6_ADDR_SRP " " PUB_S_SRP, 3636 updatestr, new_host_name, SEGMENTED_IPv6_ADDR_PARAM_SRP(addr->rr.data.aaaa.s6_addr, addr_buf), 3637 srpl_connection == NULL ? "" : srpl_connection->name); 3638 } 3639 } 3640 for (new_instance = instances; new_instance != NULL; new_instance = new_instance->next) { 3641 extract_instance_name(instance_name, sizeof instance_name, service_type, sizeof service_type, new_instance); 3642 INFO("host " PUB_S_SRP " for " PRI_S_SRP ", instance name " PRI_S_SRP ", type " PRI_S_SRP 3643 ", port %d " PUB_S_SRP, updatestr, new_host_name, instance_name, service_type, 3644 new_instance->srv != NULL ? new_instance->srv->data.srv.port : -1, 3645 srpl_connection == NULL ? "" : srpl_connection->name); 3646 if (new_instance->txt != NULL) { 3647 char txt_buf[DNS_DATA_SIZE]; 3648 dns_txt_data_print(txt_buf, DNS_DATA_SIZE, new_instance->txt->data.txt.len, new_instance->txt->data.txt.data); 3649 INFO("text data for instance " PRI_S_SRP ": " PRI_S_SRP, instance_name, txt_buf); 3650 } 3651 } 3652 3653 // Look for matching service instance names. A service instance name that matches, but has a different 3654 // hostname, means that there is a conflict. We have to look through all the entries; the presence of 3655 // a matching hostname doesn't mean we are done UNLESS there's a matching service instance name pointing 3656 // to that hostname. 3657 for (host = server_state->hosts; host; host = host->next) { 3658 // If a host has been removed, it won't have any instances to compare against. Later on, if we find that 3659 // there is no matching host for this update, we look through the host list again and remove the 3660 // "removed" host if it has the same name, so we don't need to do anything further here. 3661 if (host->removed) { 3662 continue; 3663 } 3664 // We need to look for matches both in the registered instances for this registration, and also in 3665 // the list of new instances, in case we get a duplicate update while a previous update is in progress. 3666 for (new_instance = instances; new_instance; new_instance = new_instance->next) { 3667 extract_instance_name(instance_name, sizeof instance_name, service_type, sizeof service_type, new_instance); 3668 3669 // First check for a match or conflict in the host itself. 3670 for (int i = 0; i < host->instances->num; i++) { 3671 outcome = compare_instance(host->instances->vec[i], new_host, host, 3672 instance_name, service_type); 3673 if (outcome != missed) { 3674 goto found_something; 3675 } 3676 } 3677 3678 // Then look for the same thing in any subsequent updates that have been baked. 3679 if (host->update != NULL) { 3680 if (host->update->add_instances != NULL) { 3681 for (int i = 0; i < host->update->add_instances->num; i++) { 3682 outcome = compare_instance(host->update->add_instances->vec[i], new_host, host, 3683 instance_name, service_type); 3684 if (outcome != missed) { 3685 goto found_something; 3686 } 3687 } 3688 } 3689 } 3690 } 3691 } 3692 found_something: 3693 if (outcome == conflict) { 3694 ERROR("service instance name " PRI_S_SRP "/" PRI_S_SRP " already pointing to host " 3695 PRI_S_SRP ", not host " PRI_S_SRP, instance_name, service_type, host->name, new_host_name); 3696 advertise_finished(NULL, host->name, 3697 server_state, srpl_connection, connection, raw_message, dns_rcode_yxdomain, NULL, true, true); 3698 goto cleanup; 3699 } 3700 3701 // We may have received removes for individual records. In this case, we need to make sure they only remove 3702 // records that have been added to the host that matches. 3703 for (adv_host_t *rhp = server_state->hosts; rhp != NULL; rhp = rhp->next) { 3704 if (rhp->removed) { 3705 continue; 3706 } 3707 3708 // Look for removes that conflict 3709 for (dp = removes; dp != NULL; dp = dp->next) { 3710 // We only need to do this for service instance names. We don't really know what is and isn't a 3711 // service instance name, but if it /could/ be a service instance name, we compare; if it matches, 3712 // it is a service instance name, and if not, no problem. 3713 if (dp->name != NULL && dp->name->next != NULL && dp->name->next->next != NULL) { 3714 dns_name_print_to_limit(dp->name, dp->name->next, instance_name, sizeof(instance_name)); 3715 dns_name_print_to_limit(dp->name->next, dp->name->next->next->next, service_type, sizeof(service_type)); 3716 3717 // See if the delete deletes an instance on the host 3718 for (int i = 0; i < rhp->instances->num; i++) { 3719 adv_instance_t *instance = rhp->instances->vec[i]; 3720 if (instance != NULL) { 3721 if (!strcmp(instance_name, instance->instance_name) && 3722 service_types_equal(service_type, instance->service_type)) 3723 { 3724 if (!strcmp(new_host_name, rhp->name)) { 3725 ERROR("remove for " PRI_S_SRP "." PRI_S_SRP " matches instance on host " PRI_S_SRP, 3726 instance_name, service_type, rhp->name); 3727 dp->consumed = true; 3728 } else { 3729 ERROR("remove for " PRI_S_SRP "." PRI_S_SRP " conflicts with instance on host " PRI_S_SRP, 3730 instance_name, service_type, rhp->name); 3731 advertise_finished(NULL, rhp->name, server_state, srpl_connection, 3732 connection, raw_message, dns_rcode_formerr, NULL, true, true); 3733 goto cleanup; 3734 } 3735 } 3736 } 3737 } 3738 3739 // See if the remove removes an instance on an update on the host 3740 if (rhp->update) { 3741 if (rhp->update->add_instances != NULL) { 3742 for (int i = 0; i < rhp->update->add_instances->num; i++) { 3743 adv_instance_t *instance = rhp->update->add_instances->vec[i]; 3744 if (instance != NULL) { 3745 if (!strcmp(instance_name, instance->instance_name) && 3746 service_types_equal(service_type, instance->service_type)) 3747 { 3748 if (!strcmp(new_host_name, rhp->name)) { 3749 dp->consumed = true; 3750 } else { 3751 ERROR("remove for " PRI_S_SRP " conflicts with instance on update to host " PRI_S_SRP, 3752 instance->instance_name, rhp->name); 3753 advertise_finished(NULL, rhp->name, server_state, srpl_connection, 3754 connection, raw_message, dns_rcode_formerr, NULL, true, true); 3755 goto cleanup; 3756 } 3757 } 3758 } 3759 } 3760 } 3761 } 3762 } 3763 } 3764 } 3765 3766 // Log any unmatched deletes, but we don't consider these to be errors. 3767 for (dp = removes; dp != NULL; dp = dp->next) { 3768 if (!dp->consumed) { 3769 DNS_NAME_GEN_SRP(dp->name, name_buf); 3770 INFO("remove for " PRI_DNS_NAME_SRP " doesn't match any instance on any host.", 3771 DNS_NAME_PARAM_SRP(dp->name, name_buf)); 3772 } 3773 } 3774 3775 // If we fall off the end looking for a matching service instance, there isn't a matching 3776 // service instance, but there may be a matching host, so look for that. 3777 if (outcome == missed) { 3778 // Search for the new hostname in the list of hosts, which is sorted. 3779 for (p_hosts = &server_state->hosts; *p_hosts; p_hosts = &host->next) { 3780 host = *p_hosts; 3781 int comparison = strcasecmp(new_host_name, host->name); 3782 if (comparison == 0) { 3783 // If we get an update for a host that was removed, and it's not also a remove, 3784 // remove the host entry that's marking the remove. If this is a remove, just flag 3785 // it as a miss. 3786 if (host->removed) { 3787 outcome = missed; 3788 if (remove) { 3789 break; 3790 } 3791 // if remove is more recent than this message (for example, we firt receive remove 3792 // from the actual client and then receive a stale update message from a replication 3793 // peer), we don't apply this message and end processing here. 3794 if (host->remove_received_time > client_update->message->received_time) { 3795 INFO("update for host " PRI_S_SRP " which has been deleted.", host->name); 3796 advertise_finished(NULL, host->name, server_state, srpl_connection, 3797 connection, raw_message, dns_rcode_servfail, NULL, true, true); 3798 goto cleanup; 3799 } 3800 *p_hosts = host->next; 3801 host_invalidate(host); 3802 RELEASE_HERE(host, adv_host); 3803 host = NULL; 3804 break; 3805 } 3806 if (key_id == host->key_id && dns_keys_rdata_equal(new_host->key, &host->key)) { 3807 outcome = match; 3808 break; 3809 } 3810 ERROR("update for host " PRI_S_SRP " has key id %" PRIx32 3811 " which doesn't match host key id %" PRIx32 ".", 3812 host->name, key_id, host->key_id); 3813 advertise_finished(NULL, host->name, server_state, srpl_connection, 3814 connection, raw_message, dns_rcode_yxdomain, NULL, true, true); 3815 goto cleanup; 3816 } else if (comparison < 0) { 3817 break; 3818 } 3819 } 3820 } else { 3821 if (key_id != host->key_id || !dns_keys_rdata_equal(new_host->key, &host->key)) { 3822 ERROR("new host with name " PRI_S_SRP " and key id %" PRIx32 3823 " conflicts with existing host " PRI_S_SRP " with key id %" PRIx32, 3824 new_host_name, key_id, host->name, host->key_id); 3825 advertise_finished(NULL, host->name, server_state, srpl_connection, 3826 connection, raw_message, dns_rcode_yxdomain, NULL, true, true); 3827 goto cleanup; 3828 } 3829 } 3830 3831 // If we didn't find a matching host, we can make a new one. When we create it, it just has 3832 // a name and no records. The update that we then construct will have the missing records. 3833 // We don't want to do this for a remove, obviously. 3834 if (outcome == missed) { 3835 if (remove) { 3836 ERROR("Remove for host " PRI_S_SRP " which doesn't exist.", new_host_name); 3837 advertise_finished(NULL, new_host_name, server_state, srpl_connection, 3838 connection, raw_message, dns_rcode_noerror, NULL, true, true); 3839 goto cleanup; 3840 } 3841 host = calloc(1, sizeof *host); 3842 if (host == NULL) { 3843 ERROR("no memory for host data structure."); 3844 advertise_finished(NULL, new_host_name, server_state, srpl_connection, 3845 connection, raw_message, dns_rcode_servfail, NULL, true, true); 3846 goto cleanup; 3847 } 3848 RETAIN_HERE(host, adv_host); 3849 host->server_state = server_state; 3850 host->instances = adv_instance_vec_create(0); 3851 if (host->instances == NULL) { 3852 ERROR("no memory for host instance vector."); 3853 advertise_finished(NULL, new_host_name, server_state, srpl_connection, 3854 connection, raw_message, dns_rcode_servfail, NULL, true, true); 3855 RELEASE_HERE(host, adv_host); 3856 host = NULL; 3857 goto cleanup; 3858 } 3859 host->addresses = adv_record_vec_create(0); 3860 if (host->addresses == NULL) { 3861 ERROR("no memory for host address vector."); 3862 advertise_finished(NULL, new_host_name, server_state, srpl_connection, 3863 connection, raw_message, dns_rcode_servfail, NULL, true, true); 3864 RELEASE_HERE(host, adv_host); 3865 host = NULL; 3866 goto cleanup; 3867 } 3868 3869 host->retry_wakeup = ioloop_wakeup_create(); 3870 if (host->retry_wakeup != NULL) { 3871 host->lease_wakeup = ioloop_wakeup_create(); 3872 } 3873 if (host->lease_wakeup == NULL) { 3874 ERROR("no memory for wake event on host"); 3875 advertise_finished(NULL, new_host_name, server_state, srpl_connection, 3876 connection, raw_message, dns_rcode_servfail, NULL, true, true); 3877 RELEASE_HERE(host, adv_host); 3878 host = NULL; 3879 goto cleanup; 3880 } 3881 dns_name_print(new_host->name, pres_name, sizeof pres_name); 3882 host->name = strdup(pres_name); 3883 if (host->name == NULL) { 3884 RELEASE_HERE(host, adv_host); 3885 host = NULL; 3886 ERROR("no memory for hostname."); 3887 advertise_finished(NULL, new_host_name, server_state, srpl_connection, 3888 connection, raw_message, dns_rcode_servfail, NULL, true, true); 3889 goto cleanup; 3890 } 3891 host->key = *new_host->key; 3892 #ifndef __clang_analyzer__ 3893 // Normally this would be invalid, but we never use the name of the key record. 3894 host->key.name = NULL; 3895 #endif 3896 host->key_rdlen = new_host->key->data.key.len + 4; 3897 host->key_rdata = malloc(host->key_rdlen); 3898 if (host->key_rdata == NULL) { 3899 RELEASE_HERE(host, adv_host); 3900 host = NULL; 3901 ERROR("no memory for host key."); 3902 advertise_finished(NULL, new_host_name, server_state, srpl_connection, 3903 connection, raw_message, dns_rcode_servfail, NULL, true, true); 3904 goto cleanup; 3905 } 3906 memcpy(host->key_rdata, &new_host->key->data.key.flags, 2); 3907 host->key_rdata[2] = new_host->key->data.key.protocol; 3908 host->key_rdata[3] = new_host->key->data.key.algorithm; 3909 memcpy(&host->key_rdata[4], new_host->key->data.key.key, new_host->key->data.key.len); 3910 host->key.data.key.key = &host->key_rdata[4]; 3911 host->key_id = key_id; 3912 3913 // Insert this in the list where it would have sorted. The if test is because the optimizer doesn't notice that 3914 // p_hosts can never be null here--it will always be pointing to the end of the list of hosts if we get here. 3915 if (p_hosts != NULL) { 3916 host->next = *p_hosts; 3917 *p_hosts = host; 3918 } 3919 p_hosts = NULL; 3920 } 3921 3922 // If we are already updating this host, either this is a retransmission, or it's a new transaction. In the case 3923 // of a retransmission, we need to keep doing the work we've been asked to do, and hopefully we'll reply before the 3924 // client gives up. In the case of a new request, we aren't ready for it yet; the client really shouldn't have sent 3925 // it so quickly, but if it's behaving correctly, we should be done with the current update before it retransmits, 3926 // so we can safely ignore it. If we're getting a replication update, it can't be newer than the current update. 3927 // So we can ignore it--we'll send a replication update when we're done processing the client update. 3928 if (host->update != NULL) { 3929 #ifdef SRP_DETECT_STALLS 3930 time_t now = srp_time(); 3931 // It's possible that we could get an update that stalls due to a problem communicating with mDNSResponder 3932 // and that a timing race prevents this from being detected correctly. In this case, cancel the update and 3933 // let the retry go through. We don't want to do this unless there's a clear stall, so we're allowing ten 3934 // seconds. 3935 if (now - host->update->start_time > 10) { 3936 INFO("update has stalled, failing it silently."); 3937 update_failed(host->update, dns_rcode_servfail, false, false); 3938 service_disconnected(server_state, (intptr_t)server_state->shared_registration_txn); 3939 } else { 3940 #endif // SRP_DETECT_STALLS 3941 INFO("dropping retransmission of in-progress update for host " PRI_S_SRP, host->name); 3942 #if SRP_FEATURE_REPLICATION 3943 srp_replication_advertise_finished(host, host->name, server_state, srpl_connection, 3944 connection, dns_rcode_servfail, true); 3945 #endif 3946 cleanup: 3947 srp_parse_client_updates_free(client_update); 3948 return false; 3949 #ifdef SRP_DETECT_STALLS 3950 } 3951 #endif 3952 } 3953 3954 // If this is a remove, remove the host registrations and mark the host removed. We keep it around until the 3955 // lease expires to prevent replication accidentally re-adding a removed host as a result of a bad timing 3956 // coincidence. 3957 if (remove) { 3958 host_invalidate(host); 3959 // We need to propagate the remove message. 3960 if (host->message != NULL) { 3961 ioloop_message_release(host->message); 3962 } 3963 host->message = raw_message; 3964 // remember the time when the message that removes the host was received 3965 host->remove_received_time = host->message->received_time; 3966 ioloop_message_retain(host->message); 3967 advertise_finished(host, new_host_name, server_state, srpl_connection, 3968 connection, raw_message, dns_rcode_noerror, NULL, true, true); 3969 goto cleanup; 3970 } 3971 3972 // At this point we have an update and a host to which to apply it. We may already be doing an earlier 3973 // update, or not. Create a client update structure to hold the communication, so that when we are done, 3974 // we can respond. 3975 if (outcome == missed) { 3976 INFO("New host " PRI_S_SRP ", key id %" PRIx32 , host->name, host->key_id); 3977 } else { 3978 if (host->registered_name != host->name) { 3979 INFO("Renewing host " PRI_S_SRP ", alias " PRI_S_SRP ", key id %" PRIx32, 3980 host->name, host->registered_name, host->key_id); 3981 } else { 3982 INFO("Renewing host " PRI_S_SRP ", key id %" PRIx32, host->name, host->key_id); 3983 } 3984 } 3985 3986 if (host->registered_name == NULL) { 3987 host->registered_name = host->name; 3988 } 3989 3990 // We have to take the lease from the SRP update--the original registrar negotiated it, and if it's out 3991 // of our range, that's too bad (ish). 3992 if (raw_message->lease != 0) { 3993 INFO("basing lease time on message: raw_message->lease = %d, raw_message->key_lease = %d", 3994 raw_message->lease, raw_message->key_lease); 3995 client_update->host_lease = raw_message->lease; 3996 client_update->key_lease = raw_message->key_lease; 3997 } else { 3998 if (client_update->host_lease < server_state->max_lease_time) { 3999 if (client_update->host_lease < server_state->min_lease_time) { 4000 INFO("basing lease time on server_state->min_lease_time: %d", server_state->min_lease_time); 4001 client_update->host_lease = server_state->min_lease_time; 4002 } else { 4003 INFO("basing lease time on client_update->host_lease: %d", client_update->host_lease); 4004 // client_update->host_lease = client_update->host_lease; 4005 } 4006 } else { 4007 client_update->host_lease = server_state->max_lease_time; 4008 INFO("basing lease time on server_state->max_lease_time: %d", server_state->max_lease_time); 4009 } 4010 if (client_update->key_lease < server_state->key_max_lease_time) { 4011 if (client_update->key_lease < server_state->key_min_lease_time) { 4012 client_update->key_lease = server_state->key_min_lease_time; 4013 } else { 4014 // client_update->key_lease = client_update->key_lease; 4015 } 4016 } else { 4017 client_update->key_lease = server_state->key_max_lease_time; 4018 } 4019 } 4020 4021 #if SRP_FEATURE_REPLICATION 4022 if (srpl_connection != NULL) { 4023 host->srpl_connection = srpl_connection; 4024 srpl_connection_retain(host->srpl_connection); 4025 } 4026 #endif // SRP_FEATURE_REPLICATION 4027 4028 // Apply the update. 4029 prepare_update(host, client_update); 4030 return true; 4031 } 4032 4033 void 4034 srp_mdns_flush(srp_server_t *server_state) 4035 { 4036 adv_host_t *host, *host_next; 4037 4038 INFO("flushing all host entries."); 4039 for (host = server_state->hosts; host; host = host_next) { 4040 INFO("Flushing services and host entry for " PRI_S_SRP " (" PRI_S_SRP ")", 4041 host->name, host->registered_name); 4042 // Get rid of the updates before calling delete_host, which will fail if update is not NULL. 4043 if (host->update != NULL) { 4044 update_failed(host->update, dns_rcode_refused, false, true); 4045 } 4046 host_next = host->next; 4047 host_remove(host); 4048 } 4049 server_state->hosts = NULL; 4050 } 4051 4052 static void 4053 usage(void) 4054 { 4055 ERROR("srp-mdns-proxy [--max-lease-time <seconds>] [--min-lease-time <seconds>] [--log-stderr]"); 4056 ERROR(" [--enable-replication | --disable-replication]"); 4057 #if SRP_FEATURE_NAT64 4058 ERROR(" [--enable-nat64 | --disable-nat64]"); 4059 #endif 4060 exit(1); 4061 } 4062 4063 srp_server_t * 4064 server_state_create(const char *name, int max_lease_time, int min_lease_time, 4065 int key_max_lease_time, int key_min_lease_time) 4066 { 4067 srp_server_t *server_state = calloc(1, sizeof(*server_state)); 4068 if (server_state == NULL || (server_state->name = strdup(name)) == NULL) { 4069 ERROR("no memory for server state"); 4070 free(server_state); 4071 return NULL; 4072 } 4073 server_state->max_lease_time = max_lease_time; 4074 server_state->min_lease_time = min_lease_time; 4075 server_state->key_max_lease_time = key_max_lease_time; 4076 server_state->key_min_lease_time = key_min_lease_time; 4077 server_state->priority = PRIORITY_DEFAULT; 4078 #if TARGET_OS_TV 4079 #endif 4080 INFO("priority set to %d", server_state->priority); 4081 return server_state; 4082 } 4083 4084 static void 4085 object_allocation_stats_dump_callback(void *context) 4086 { 4087 srp_server_t *server_state = context; 4088 4089 ioloop_dump_object_allocation_stats(); 4090 4091 if (server_state->full_dump_count == 0) { 4092 srp_dump_server_stats(server_state, true, true); 4093 server_state->full_dump_count = 12; 4094 } else { 4095 srp_dump_server_stats(server_state, false, true); 4096 } 4097 --server_state->full_dump_count; 4098 4099 // Do the next object memory allocation statistics dump in five minutes 4100 ioloop_add_wake_event(server_state->object_allocation_stats_dump_wakeup, server_state, 4101 object_allocation_stats_dump_callback, NULL, 5 * 60 * 1000); 4102 } 4103 4104 int 4105 main(int argc, char **argv) 4106 { 4107 int i; 4108 char *end; 4109 int log_stderr = false; 4110 #ifdef SRP_TEST_SERVER 4111 char *test_to_run = NULL; 4112 bool normal_srp_startup = false; 4113 #else 4114 bool normal_srp_startup = true; 4115 #endif 4116 #if STUB_ROUTER 4117 bool stub_router_enabled = false; 4118 #endif 4119 bool thread_device_enabled = false; 4120 4121 srp_servers = server_state_create("srp-mdns-proxy", 4122 3600 * 27, // max lease time one day plus 20% 4123 30, // min lease time 30 seconds 4124 3600 * 24 * 7, // max key lease 7 days 4125 30); // min key lease time 30s 4126 if (srp_servers == NULL) { 4127 return 1; 4128 } 4129 4130 if (normal_srp_startup) { 4131 srp_servers->srp_replication_enabled = true; 4132 # if SRP_FEATURE_NAT64 4133 srp_servers->srp_nat64_enabled = true; 4134 # endif 4135 } 4136 4137 4138 // Set the advertise interface 4139 if (0) { 4140 #if STUB_ROUTER 4141 } else if (stub_router_enabled) { 4142 srp_servers->advertise_interface = kDNSServiceInterfaceIndexAny; 4143 #endif 4144 } else { 4145 srp_servers->advertise_interface = if_nametoindex("lo0"); 4146 } 4147 for (i = 1; i < argc; i++) { 4148 if (!strcmp(argv[i], "--max-lease-time")) { 4149 if (i + 1 == argc) { 4150 usage(); 4151 } 4152 srp_servers->max_lease_time = (uint32_t)strtoul(argv[i + 1], &end, 10); 4153 if (end == argv[i + 1] || end[0] != 0) { 4154 usage(); 4155 } 4156 i++; 4157 } else if (!strcmp(argv[i], "--min-lease-time")) { 4158 if (i + 1 == argc) { 4159 usage(); 4160 } 4161 srp_servers->min_lease_time = (uint32_t)strtoul(argv[i + 1], &end, 10); 4162 if (end == argv[i + 1] || end[0] != 0) { 4163 usage(); 4164 } 4165 i++; 4166 } else if (!strcmp(argv[i], "--log-stderr")) { 4167 log_stderr = true; 4168 #ifdef LOG_FPRINTF_STDERR 4169 } else if (!strcmp(argv[i], "--log-relative-timestamp")) { 4170 srp_log_timestamp_relative = true; 4171 #endif 4172 } else if (!strcmp(argv[i], "--enable-replication")) { 4173 srp_servers->srp_replication_enabled = true; 4174 } else if (!strcmp(argv[i], "--disable-replication")) { 4175 srp_servers->srp_replication_enabled = false; 4176 } else if (!strcmp(argv[i], "--fake-xpanid")) { 4177 if (i + 1 == argc) { 4178 usage(); 4179 } 4180 srp_servers->xpanid = strtoul(argv[i + 1], &end, 16); 4181 if (end == argv[i + 1] || end[0] != 0) { 4182 usage(); 4183 } 4184 #ifdef SRP_TEST_SERVER 4185 } else if (!strcmp(argv[i], "--test")) { 4186 if (i + 1 == argc) { 4187 usage(); 4188 } 4189 test_to_run = argv[i + 1]; 4190 i++; 4191 #endif 4192 #if SRP_FEATURE_NAT64 4193 } else if (!strcmp(argv[i], "--enable-nat64")) { 4194 srp_servers->srp_nat64_enabled = true; 4195 } else if (!strcmp(argv[i], "--disable-nat64")) { 4196 srp_servers->srp_nat64_enabled = false; 4197 #endif 4198 } else { 4199 usage(); 4200 } 4201 } 4202 4203 // Setup log category for srp-mdns-prox and dnssd-proxy. 4204 OPENLOG("srp-mdns-proxy", log_stderr); 4205 4206 #ifdef SRP_TEST_SERVER 4207 INFO("srp-test-server starting, compiled on " PUB_S_SRP ", " PUB_S_SRP, __DATE__, __TIME__); 4208 #else 4209 INFO("--------------------------------" 4210 "srp-mdns-proxy starting, compiled on " PUB_S_SRP ", " PUB_S_SRP 4211 "--------------------------------", __DATE__, __TIME__); 4212 #endif 4213 4214 if (!ioloop_init()) { 4215 return 1; 4216 } 4217 4218 if (normal_srp_startup) { 4219 #if THREAD_DEVICE 4220 if (0) { 4221 #if STUB_ROUTER 4222 } else if (stub_router_enabled) { 4223 srp_servers->route_state = route_state_create(srp_servers, "srp-mdns-proxy"); 4224 if (srp_servers->route_state == NULL) { 4225 return 1; 4226 } 4227 #endif // STUB_ROUTER 4228 } 4229 4230 if (!srp_mdns_shared_registration_txn_setup(srp_servers)) { 4231 return 1; 4232 } 4233 dns_service_op_not_to_be_freed = srp_servers->shared_registration_txn->sdref; 4234 #endif // THREAD_DEVICE 4235 4236 #if STUB_ROUTER 4237 if (stub_router_enabled) { 4238 // Set up the ULA early just in case we get an early registration, nat64 will use the ula 4239 route_ula_setup(srp_servers->route_state); 4240 } 4241 #endif 4242 4243 4244 #if (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY) 4245 if (!init_dnssd_proxy(srp_servers)) { 4246 ERROR("failed to setup dnssd-proxy"); 4247 } 4248 #endif // #if (SRP_FEATURE_COMBINED_SRP_DNSSD_PROXY) 4249 4250 #if STUB_ROUTER 4251 if (stub_router_enabled) { 4252 if (!start_icmp_listener()) { 4253 ERROR("failed to start icmp listener"); 4254 } 4255 } 4256 #endif 4257 4258 4259 infrastructure_network_startup(srp_servers->route_state); 4260 4261 if (adv_ctl_init(srp_servers) != kDNSServiceErr_NoError) { 4262 ERROR("Can't start advertising proxy control server."); 4263 } 4264 4265 // We require one open file per service and one per instance. 4266 struct rlimit limits; 4267 if (getrlimit(RLIMIT_NOFILE, &limits) < 0) { 4268 ERROR("getrlimit failed: " PUB_S_SRP, strerror(errno)); 4269 } 4270 4271 if (limits.rlim_cur < 1024) { 4272 if (limits.rlim_max < 1024) { 4273 INFO("file descriptor hard limit is %llu", (unsigned long long)limits.rlim_max); 4274 if (limits.rlim_cur != limits.rlim_max) { 4275 limits.rlim_cur = limits.rlim_max; 4276 } 4277 } else { 4278 limits.rlim_cur = 1024; 4279 } 4280 if (setrlimit(RLIMIT_NOFILE, &limits) < 0) { 4281 ERROR("setrlimit failed: " PUB_S_SRP, strerror(errno)); 4282 } 4283 } 4284 4285 srp_proxy_init("local"); 4286 #ifdef SRP_TEST_SERVER 4287 } else { 4288 ioloop_run_async(srp_test_server_run_test, test_to_run); 4289 #endif 4290 } 4291 4292 srp_servers->object_allocation_stats_dump_wakeup = ioloop_wakeup_create(); 4293 if (srp_servers->object_allocation_stats_dump_wakeup == NULL) { 4294 INFO("no memory for srp_servers->object_allocation_stats_dump_wakeup"); 4295 } else { 4296 // Do an object memory allocation statistics dump every five minutes, and a full database dump every half hour 4297 // starting after the first five minutes 4298 srp_servers->full_dump_count = 1; 4299 object_allocation_stats_dump_callback(srp_servers); 4300 } 4301 4302 ioloop(); 4303 } 4304 4305 // Local Variables: 4306 // mode: C 4307 // tab-width: 4 4308 // c-file-style: "bsd" 4309 // c-basic-offset: 4 4310 // fill-column: 120 4311 // indent-tabs-mode: nil 4312 // End: 4313