Home | History | Annotate | Line # | Download | only in ServiceRegistration
      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