1 /* srp-replication.h 2 * 3 * Copyright (c) 2020-2023 Apple Computer, 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 * http://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 structure definitions and external definitions for the SRP Replication code. 18 */ 19 20 #ifndef __SRP_REPLICATION_H__ 21 #define __SRP_REPLICATION_H__ 22 23 // States: each state has a function, which bears the name of the state. The function takes an 24 // srpl_connection_t and an srpl_event_t. The function is called once on entering the 25 // state, once on leaving the state, and once whenever an event arrives while in the state. 26 // 27 // Whenever this function is called, it returns a next state. If the next state is 28 // "invalid," that means that there is no state change. 29 // 30 // Events: Events can be triggered by connection activities, e.g. connect, disconnect, add_address, etc. 31 // They can also be triggered by the arrival of messages on connections. 32 // They can also be triggered by happenings on the srp server. 33 // Events are never sent by state actions. 34 // Each event has a single function which sends the event. That function may in some cases force 35 // a state change (e.g., a disconnect event). This is the exception, not the rule. Events are 36 // otherwise handled by the state action function for the current state. 37 // 38 // In some cases, an event that's expected to be delivered asynchronously arrives synchronously because 39 // no asynchronous action was required. In this case, the action that can trigger this synchronous event 40 // has to also handle the event. Since the event is normally expected to be delivered asynchronously, 41 // the right solution in this case is to queue the event for later delivery. 42 // 43 // An example of this pattern is in srpl_advertise_finished_event_defer. Because events are normally automatic 44 // variables, any event that needs to be deferred has to be allocated and its contents (if any) copied. The 45 // srpl_connection_t is stashed on the event; srpl_deferred_event_deliver is then called asynchronously to deliver the 46 // event, release the reference to the srpl_connection_t, and free the event data structure. 47 48 enum srpl_state { 49 srpl_state_invalid = 0, // Only as a return value, means do not move to a new state 50 51 // Connection-related states 52 srpl_state_disconnected, 53 srpl_state_next_address_get, 54 srpl_state_connect, 55 srpl_state_idle, 56 srpl_state_reconnect_wait, 57 srpl_state_retry_delay_send, 58 srpl_state_disconnect, 59 srpl_state_disconnect_wait, 60 srpl_state_connecting, 61 62 // Session establishment 63 srpl_state_session_send, 64 srpl_state_session_response_wait, 65 srpl_state_session_evaluate, 66 srpl_state_sync_wait, 67 68 // Requesting and getting remote candidate list 69 srpl_state_send_candidates_send, 70 srpl_state_send_candidates_wait, 71 72 // Waiting for candidate to arrive 73 srpl_state_candidate_check, 74 75 // Waiting for a host to arrive after requesting it 76 srpl_state_candidate_host_wait, 77 srpl_state_candidate_host_prepare, 78 srpl_state_candidate_host_contention_wait, 79 srpl_state_candidate_host_re_evaluate, 80 srpl_state_candidate_host_apply, 81 srpl_state_candidate_host_apply_wait, 82 83 // Getting request for candidate list and sending them. 84 srpl_state_send_candidates_received, 85 srpl_state_send_candidates_remaining_check, 86 srpl_state_next_candidate_send, 87 srpl_state_next_candidate_send_wait, 88 srpl_state_candidate_host_send, 89 srpl_state_candidate_host_response_wait, 90 91 // When we're done sending candidates 92 srpl_state_send_candidates_response_send, 93 94 // Ready states 95 srpl_state_ready, 96 srpl_state_srp_client_update_send, 97 srpl_state_srp_client_ack_evaluate, 98 srpl_state_stashed_host_check, 99 srpl_state_stashed_host_apply, 100 srpl_state_stashed_host_finished, 101 102 // States for connections received by this server 103 srpl_state_session_message_wait, 104 srpl_state_session_response_send, 105 srpl_state_send_candidates_message_wait, 106 107 #ifdef SRP_TEST_SERVER 108 // States for testing 109 srpl_state_test_event_intercept, 110 #endif 111 }; 112 113 enum srpl_event_type { 114 srpl_event_invalid = 0, 115 srpl_event_address_add, 116 srpl_event_address_remove, 117 srpl_event_server_disconnect, 118 srpl_event_reconnect_timer_expiry, 119 srpl_event_disconnected, 120 srpl_event_connected, 121 srpl_event_session_response_received, 122 srpl_event_send_candidates_response_received, 123 srpl_event_candidate_received, 124 srpl_event_host_message_received, 125 srpl_event_srp_client_update_finished, 126 srpl_event_advertise_finished, 127 srpl_event_candidate_response_received, 128 srpl_event_host_response_received, 129 srpl_event_session_message_received, 130 srpl_event_send_candidates_message_received, 131 srpl_event_do_sync, 132 }; 133 enum srpl_candidate_disposition { srpl_candidate_yes, srpl_candidate_no, srpl_candidate_conflict }; 134 135 typedef struct srpl_instance_service srpl_instance_service_t; 136 typedef struct srpl_connection srpl_connection_t; 137 typedef struct srpl_instance srpl_instance_t; 138 typedef struct srpl_domain srpl_domain_t; 139 typedef struct address_query address_query_t; 140 typedef struct unclaimed_connection unclaimed_connection_t; 141 typedef enum srpl_state srpl_state_t; 142 typedef enum srpl_event_type srpl_event_type_t; 143 typedef struct srpl_event srpl_event_t; 144 typedef struct srpl_candidate srpl_candidate_t; 145 typedef enum srpl_candidate_disposition srpl_candidate_disposition_t; 146 typedef struct srpl_srp_client_queue_entry srpl_srp_client_queue_entry_t; 147 typedef struct srpl_srp_client_update_result srpl_srp_client_update_result_t; 148 typedef struct srpl_host_update srpl_host_update_t; 149 typedef struct srpl_advertise_finished_result srpl_advertise_finished_result_t; 150 typedef struct srpl_session srpl_session_t; 151 #ifdef SRP_TEST_SERVER 152 typedef struct test_packet_state test_packet_state_t; 153 #endif 154 155 typedef void (*address_change_callback_t)(void *NULLABLE context, addr_t *NULLABLE address, bool added, bool more, int err); 156 typedef void (*address_query_cancel_callback_t)(void *NULLABLE context); 157 typedef enum { 158 address_query_next_address_gotten, // success 159 address_query_next_address_empty, // no addresses at all 160 address_query_cycle_complete // all addresses have been tried 161 } address_query_result_t; 162 163 #define ADDRESS_QUERY_MAX_ADDRESSES 20 164 struct address_query { 165 int ref_count; 166 dnssd_txn_t *NULLABLE aaaa_query, *NULLABLE a_query; 167 addr_t addresses[ADDRESS_QUERY_MAX_ADDRESSES]; // If there are more than this many viable addresses, too bad? 168 uint32_t address_interface[ADDRESS_QUERY_MAX_ADDRESSES]; 169 int num_addresses, cur_address; 170 address_change_callback_t NULLABLE change_callback; 171 address_query_cancel_callback_t NULLABLE cancel_callback; 172 void *NULLABLE context; 173 char *NONNULL hostname; 174 }; 175 176 struct srpl_candidate { 177 dns_label_t *NULLABLE name; 178 uint32_t key_id; // key id from adv_host_t 179 uint32_t update_offset; // Offset in seconds before the time candidate message was sent that update was received. 180 time_t update_time; // the time of registration received from remote 181 time_t local_time; // our time of registration when we fetched the host 182 message_t *NULLABLE message; // The SRP message. 183 adv_host_t *NULLABLE host; // the host, when it's been fetched 184 }; 185 186 struct srpl_advertise_finished_result { 187 char *NULLABLE hostname; 188 srp_server_t *NULLABLE server_state; 189 int rcode; 190 }; 191 192 // 1: local > remote 193 // 0: local == remote 194 // -1: local < remote 195 // -2: undefined result. 196 enum { 197 EQUAL = 0, 198 LOCAL_LARGER = 1, 199 LOCAL_SMALLER = -1, 200 UNDEFINED = -2, 201 }; 202 203 typedef enum { 204 srpl_event_content_type_none = 0, 205 srpl_event_content_type_address, 206 srpl_event_content_type_session, 207 srpl_event_content_type_candidate, 208 srpl_event_content_type_rcode, 209 srpl_event_content_type_candidate_disposition, 210 srpl_event_content_type_host_update, 211 srpl_event_content_type_client_result, 212 srpl_event_content_type_advertise_finished_result, 213 } srpl_event_content_type_t; 214 215 typedef srpl_state_t (*srpl_action_t)(srpl_connection_t *NONNULL connection, srpl_event_t *NULLABLE event); 216 217 struct srpl_srp_client_update_result { 218 adv_host_t *NONNULL host; 219 int rcode; 220 }; 221 222 struct srpl_host_update { 223 message_t *NULLABLE *NULLABLE messages; 224 intptr_t orig_buffer; 225 uint64_t server_stable_id; 226 dns_name_t *NULLABLE hostname; 227 uint32_t update_offset; 228 int num_messages, max_messages, messages_processed; 229 int rcode; 230 unsigned num_bytes; 231 }; 232 233 struct srpl_session { 234 uint64_t partner_id; 235 dns_name_t *NULLABLE domain_name; 236 uint16_t remote_version; 237 bool new_partner; 238 }; 239 240 struct srpl_event { 241 char *NONNULL name; 242 srpl_event_content_type_t content_type; 243 union { 244 addr_t address; 245 srpl_session_t session; 246 srpl_srp_client_update_result_t client_result; 247 srpl_candidate_t *NULLABLE candidate; 248 int rcode; 249 srpl_candidate_disposition_t disposition; 250 srpl_host_update_t host_update; 251 srpl_advertise_finished_result_t advertise_finished; 252 } content; 253 message_t *NULLABLE message; 254 srpl_event_type_t event_type; 255 srpl_connection_t *NULLABLE srpl_connection; // if the event's been deferred, otherwise ALWAYS NULL. 256 }; 257 258 struct srpl_srp_client_queue_entry { 259 srpl_srp_client_queue_entry_t *NULLABLE next; 260 adv_host_t *NONNULL host; 261 bool sent; 262 }; 263 264 struct srpl_connection { 265 int ref_count; 266 uint64_t remote_partner_id; 267 char *NONNULL name; 268 char *NONNULL state_name; 269 comm_t *NULLABLE connection; 270 const char *NULLABLE connection_null_reason; // for debugging, records why we NULLed connection. 271 struct timeval connection_null_time; // When connection was set to NULL 272 addr_t connected_address; 273 srpl_candidate_t *NULLABLE candidate; 274 dso_state_t *NULLABLE dso; 275 srpl_instance_t *NULLABLE instance; 276 wakeup_t *NULLABLE reconnect_wakeup; 277 wakeup_t *NULLABLE state_timeout; // how long the srpl connecton could stay in a state before we assume it's gone. 278 message_t *NULLABLE message; 279 adv_host_t *NULLABLE *NULLABLE candidates; 280 srpl_host_update_t stashed_host; 281 srpl_srp_client_queue_entry_t *NULLABLE client_update_queue; 282 wakeup_t *NULLABLE keepalive_send_wakeup; 283 wakeup_t *NULLABLE keepalive_receive_wakeup; 284 #ifdef SRP_TEST_SERVER 285 void (*NULLABLE advertise_finished_callback)(test_state_t *NONNULL state); 286 void (*NULLABLE srpl_advertise_finished_callback)(srpl_connection_t *NONNULL connection); 287 test_state_t *NULLABLE test_state; 288 srpl_connection_t *NULLABLE next; 289 srp_server_t *NONNULL server; 290 #endif 291 time_t last_message_sent; 292 time_t last_message_received; 293 time_t state_start_time; 294 int num_candidates; 295 int current_candidate; 296 int retry_delay; // How long to send when we send a retry_delay message 297 int keepalive_interval; 298 srpl_state_t state, next_state; 299 uint32_t variation_mask; // Protocol variations to support pre-standard TLV formats 300 bool is_server; 301 bool new_partner; 302 bool database_synchronized; 303 bool candidates_not_generated; // If this is true, we haven't generated a candidates list yet. 304 }; 305 306 struct srpl_instance_service { 307 int ref_count; 308 srpl_instance_t *NULLABLE instance; 309 dnssd_txn_t *NULLABLE txt_txn; 310 dnssd_txn_t *NULLABLE srv_txn; 311 srpl_instance_service_t *NULLABLE next; 312 srpl_domain_t *NONNULL domain; 313 wakeup_t *NULLABLE resolve_wakeup; 314 wakeup_t *NULLABLE discontinue_timeout; 315 uint8_t *NULLABLE txt_rdata; 316 uint8_t *NULLABLE srv_rdata; 317 uint8_t *NULLABLE ptr_rdata; 318 uint8_t *NULLABLE addr_rdata; 319 char *NULLABLE host_name; 320 char *NULLABLE full_service_name; 321 address_query_t *NULLABLE address_query; 322 int num_copies; // Tracks adds and deletes from the DNSServiceBrowse for this instance. 323 uint32_t ifindex; 324 uint16_t outgoing_port; 325 uint16_t txt_length; 326 uint16_t srv_length; 327 uint16_t ptr_length; 328 bool have_srv_record, have_txt_record; 329 // True if we've already started a resolve for this instance, to prevent starting a second resolve if the instance 330 // is seen on more than one interface. 331 bool resolve_started; 332 bool discontinuing; // True if we are in the process of discontinuing this instance. 333 bool got_new_info; // True if we have received new information since the last time we did a reconfirm. 334 }; 335 336 struct srpl_instance { 337 int ref_count; 338 srpl_instance_t *NULLABLE next; 339 srpl_domain_t *NONNULL domain; 340 srpl_connection_t *NULLABLE connection; 341 wakeup_t *NULLABLE reconnect_timeout; 342 char *NULLABLE instance_name; 343 srpl_instance_service_t *NONNULL services; 344 uint64_t partner_id; 345 uint64_t dataset_id; 346 uint32_t priority; 347 bool have_partner_id; 348 bool have_dataset_id; 349 bool have_priority; 350 bool sync_to_join; // True if sync with the remote partner is required to join the replication 351 bool sync_fail; // True if sync with the remote partner is declared fail 352 bool discovered_in_window; // True if the instance is discovered in partner discovery window 353 bool is_me; 354 bool discontinuing; // True if we are in the process of discontinuing this instance. 355 bool unmatched; // True if this is an incoming connection that hasn't been associated with a real instance. 356 bool matched_unidentified; // True if an address from address callback matches an unidentified connection 357 bool added_address; // True if address callback adds an address to the instance 358 bool version_mismatch; // True if the version mismatches 359 }; 360 361 typedef enum { 362 SRPL_OPSTATE_STARTUP = 0, 363 SRPL_OPSTATE_ROUTINE = 1 364 } srpl_opstate_t; 365 366 struct srpl_domain { 367 uint64_t partner_id; // SRP replication partner ID 368 uint64_t dataset_id; 369 bool have_dataset_id; 370 bool dataset_id_committed; 371 bool partner_discovery_pending; 372 int ref_count; 373 srpl_opstate_t srpl_opstate; 374 srpl_domain_t *NULLABLE next; 375 char *NONNULL name; 376 srpl_instance_t *NULLABLE instances; 377 srpl_instance_service_t *NULLABLE unresolved_services; 378 dnssd_txn_t *NULLABLE query; 379 srp_server_t *NULLABLE server_state; 380 dnssd_txn_t *NULLABLE srpl_advertise_txn; 381 wakeup_t *NULLABLE srpl_register_wakeup; 382 wakeup_t *NULLABLE partner_discovery_timeout; 383 }; 384 385 #define SRP_THREAD_DOMAIN "thread.home.arpa." 386 387 #define DSO_TLV_HEADER_SIZE 4 // opcode (u16) + length (u16) 388 #define DSO_MESSAGE_MIN_LENGTH DNS_HEADER_SIZE + DSO_TLV_HEADER_SIZE + 1 389 390 391 #define SRPL_RETRY_DELAY_LENGTH DSO_MESSAGE_MIN_LENGTH + sizeof(uint32_t) 392 #define SRPL_SESSION_MESSAGE_LENGTH (DSO_MESSAGE_MIN_LENGTH + \ 393 sizeof(uint64_t) + \ 394 DNS_MAX_NAME_SIZE + DSO_TLV_HEADER_SIZE + \ 395 DSO_TLV_HEADER_SIZE + sizeof(uint16_t) + \ 396 DSO_TLV_HEADER_SIZE + sizeof(uint16_t)) 397 #define SRPL_SEND_CANDIDATES_LENGTH DSO_MESSAGE_MIN_LENGTH 398 #define SRPL_CANDIDATE_MESSAGE_LENGTH (DSO_MESSAGE_MIN_LENGTH + \ 399 DNS_MAX_NAME_SIZE + DSO_TLV_HEADER_SIZE + \ 400 sizeof(uint32_t) + DSO_TLV_HEADER_SIZE + \ 401 sizeof(uint32_t) + DSO_TLV_HEADER_SIZE) 402 #define SRPL_KEEPALIVE_MESSAGE_LENGTH (DSO_MESSAGE_MIN_LENGTH + \ 403 DNS_MAX_NAME_SIZE + DSO_TLV_HEADER_SIZE + \ 404 sizeof(uint32_t) + DSO_TLV_HEADER_SIZE + \ 405 sizeof(uint32_t) + DSO_TLV_HEADER_SIZE) 406 #define SRPL_CANDIDATE_RESPONSE_LENGTH DSO_MESSAGE_MIN_LENGTH + DSO_TLV_HEADER_SIZE 407 #define SRPL_HOST_MESSAGE_LENGTH (DSO_MESSAGE_MIN_LENGTH + \ 408 DNS_MAX_NAME_SIZE + DSO_TLV_HEADER_SIZE + \ 409 sizeof(uint32_t) + DSO_TLV_HEADER_SIZE + \ 410 sizeof(uint32_t) + DSO_TLV_HEADER_SIZE) 411 #define SRPL_HOST_RESPONSE_LENGTH DSO_MESSAGE_MIN_LENGTH 412 413 #define SRPL_UPDATE_JITTER_WINDOW 10 414 415 #define MIN_PARTNER_DISCOVERY_INTERVAL 4000 // minimum partner discovery time interval in milliseconds 416 #define MAX_PARTNER_DISCOVERY_INTERVAL 7500 // maximum partner discovery time interval in milliseconds 417 #define PARTNER_DISCOVERY_INTERVAL_RANGE (MAX_PARTNER_DISCOVERY_INTERVAL - \ 418 MIN_PARTNER_DISCOVERY_INTERVAL + 1) 419 #define DEFAULT_KEEPALIVE_WAKEUP_EXPIRY (5 * 60 * 1000) // five minutes 420 421 #define PARTNER_ID_BITS 64 422 #define LOWER56_BIT_MASK 0xFFFFFFFFFFFFFFULL 423 424 // SRP Replication protocol versioning 425 // Protocol version number 1: outdated and no longer being used. This version was supposed to 426 // support multi host messages but did not really work. After making 427 // it work, we increment the version number to 3. 428 // Protocol version number 2: to support anycast service 429 // Protocol version number 3: to support multi host messages 430 #define SRPL_VERSION_ANYCAST 2 431 #define SRPL_VERSION_MULTI_HOST_MESSAGE 3 432 #define SRPL_VERSION_EDNS0_TSR 4 433 #define SRPL_CURRENT_VERSION SRPL_VERSION_EDNS0_TSR 434 435 // Variation bits. 436 #define SRPL_VARIATION_MULTI_HOST_MESSAGE 1 437 #define SRPL_SUPPORTS(srpl_connection, variation) \ 438 (((srpl_connection)->variation_mask & (variation)) != 0) 439 440 // Exported functions... 441 srpl_connection_t *NULLABLE srpl_connection_create(srpl_instance_t *NONNULL instance, bool outgoing); 442 void srpl_connection_next_state(srpl_connection_t *NONNULL srpl_connection, srpl_state_t state); 443 void srpl_startup(srp_server_t *NONNULL srp_server); 444 void srpl_shutdown(srp_server_t *NONNULL server_state); 445 void srpl_disable(srp_server_t *NONNULL srp_server); 446 void srpl_drop_srpl_connection(srp_server_t *NONNULL srp_server); 447 void srpl_undrop_srpl_connection(srp_server_t *NONNULL srp_server); 448 void srpl_drop_srpl_advertisement(srp_server_t *NONNULL srp_server); 449 void srpl_undrop_srpl_advertisement(srp_server_t *NONNULL srp_server); 450 void srpl_dso_server_message(comm_t *NONNULL connection, message_t *NULLABLE message, dso_state_t *NONNULL dso, 451 srp_server_t *NONNULL server_state); 452 void srpl_advertise_finished_event_send(char *NONNULL host, int rcode, srp_server_t *NONNULL server_state); 453 void srpl_srp_client_update_finished_event_send(adv_host_t *NONNULL host, int rcode); 454 #define srpl_connection_release(connection) srpl_connection_release_(connection, __FILE__, __LINE__) 455 void srpl_connection_release_(srpl_connection_t *NONNULL srpl_connection, const char *NONNULL file, int line); 456 #define srpl_connection_retain(connection) srpl_connection_retain_(connection, __FILE__, __LINE__) 457 void srpl_connection_retain_(srpl_connection_t *NONNULL srpl_connection, const char *NONNULL file, int line); 458 srpl_domain_t *NULLABLE srpl_domain_create_or_copy(srp_server_t *NONNULL server_state, const char *NONNULL domain_name); 459 void srpl_dump_connection_states(srp_server_t *NONNULL server_state); 460 void srpl_change_server_priority(srp_server_t *NONNULL server_state, uint32_t new); 461 #endif // __SRP_REPLICATION_H__ 462 463 // Local Variables: 464 // mode: C 465 // tab-width: 4 466 // c-file-style: "bsd" 467 // c-basic-offset: 4 468 // fill-column: 120 469 // indent-tabs-mode: nil 470 // End: 471