+static bool swn_server_registration_message_filter(struct messaging_rec *rec, void *private_data)
+{
+ struct swn_service_registration *reg = NULL;
+ struct policy_handle context_handle;
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
+ bool match;
+
+ if (rec->msg_type != MSG_RPCD_WITNESS_REGISTRATION_UPDATE) {
+ return false;
+ }
+
+ if (rec->num_fds != 0) {
+ return false;
+ }
+
+ if (rec->buf.length < 20) {
+ return false;
+ }
+
+ reg = talloc_get_type_abort(private_data, struct swn_service_registration);
+
+ blob = data_blob_const(rec->buf.data, 20);
+ ndr_err = ndr_pull_struct_blob_all_noalloc(&blob, &context_handle,
+ (ndr_pull_flags_fn_t)ndr_pull_policy_handle);
+ SMB_ASSERT(NDR_ERR_CODE_IS_SUCCESS(ndr_err));
+
+ match = ndr_policy_handle_equal(&context_handle, ®->key.handle);
+ if (!match) {
+ return false;
+ }
+
+ return true;
+}
+
+static void swn_server_registration_client_move_to_node(
+ struct swn_service_registration *reg,
+ struct rpcd_witness_registration_update_move_to_node *move)
+{
+ reg->move_notification.triggered = true;
+ reg->move_notification.new_node = move->new_node;
+ reg->move_notification.new_ip = (struct samba_sockaddr) {
+ .sa_socklen = 0,
+ };
+
+ tevent_queue_start(reg->async_notify.queue);
+}
+
+static void swn_server_registration_client_move_to_ip(
+ struct swn_service_registration *reg,
+ const char *new_ip_str)
+{
+ struct samba_sockaddr new_ip = {
+ .sa_socklen = 0,
+ };
+ bool ok;
+
+ ok = is_ipaddress(new_ip_str);
+ if (!ok) {
+ return;
+ }
+ ok = interpret_string_addr(&new_ip.u.ss,
+ new_ip_str,
+ AI_PASSIVE|AI_NUMERICHOST);
+ if (!ok) {
+ return;
+ }
+
+ reg->move_notification.triggered = true;
+ reg->move_notification.new_node = NONCLUSTER_VNN;
+ reg->move_notification.new_ip = new_ip;
+
+ tevent_queue_start(reg->async_notify.queue);
+}
+
+static void swn_server_registration_client_move_to_ipv4(
+ struct swn_service_registration *reg,
+ struct rpcd_witness_registration_update_move_to_ipv4 *move)
+{
+ swn_server_registration_client_move_to_ip(reg, move->new_ipv4);
+}
+
+static void swn_server_registration_client_move_to_ipv6(
+ struct swn_service_registration *reg,
+ struct rpcd_witness_registration_update_move_to_ipv6 *move)
+{
+ swn_server_registration_client_move_to_ip(reg, move->new_ipv6);
+}
+
+static void swn_server_registration_share_move_to_node(
+ struct swn_service_registration *reg,
+ struct rpcd_witness_registration_update_move_to_node *move)
+{
+ if (!reg->share_notification.required) {
+ return;
+ }
+
+ reg->share_notification.triggered = true;
+ reg->share_notification.new_node = move->new_node;
+ reg->share_notification.new_ip = (struct samba_sockaddr) {
+ .sa_socklen = 0,
+ };
+
+ tevent_queue_start(reg->async_notify.queue);
+}
+
+static void swn_server_registration_share_move_to_ip(
+ struct swn_service_registration *reg,
+ const char *new_ip_str)
+{
+ struct samba_sockaddr new_ip = {
+ .sa_socklen = 0,
+ };
+ bool ok;
+
+ ok = is_ipaddress(new_ip_str);
+ if (!ok) {
+ return;
+ }
+ ok = interpret_string_addr(&new_ip.u.ss,
+ new_ip_str,
+ AI_PASSIVE|AI_NUMERICHOST);
+ if (!ok) {
+ return;
+ }
+
+ if (!reg->share_notification.required) {
+ return;
+ }
+
+ reg->share_notification.triggered = true;
+ reg->share_notification.new_node = NONCLUSTER_VNN;
+ reg->share_notification.new_ip = new_ip;
+
+ tevent_queue_start(reg->async_notify.queue);
+}
+
+static void swn_server_registration_share_move_to_ipv4(
+ struct swn_service_registration *reg,
+ struct rpcd_witness_registration_update_move_to_ipv4 *move)
+{
+ swn_server_registration_share_move_to_ip(reg, move->new_ipv4);
+}
+
+static void swn_server_registration_share_move_to_ipv6(
+ struct swn_service_registration *reg,
+ struct rpcd_witness_registration_update_move_to_ipv6 *move)
+{
+ swn_server_registration_share_move_to_ip(reg, move->new_ipv6);
+}
+
+static void swn_server_registration_force_response(
+ struct swn_service_registration *reg,
+ struct rpcd_witness_registration_update_force_response *response)
+{
+ reg->forced_response.triggered = true;
+ reg->forced_response.response = talloc_move(reg, &response->response);
+ reg->forced_response.result = response->result;
+
+ tevent_queue_start(reg->async_notify.queue);
+}
+
+static void swn_server_registration_message_done(struct tevent_req *subreq)
+{
+ struct swn_service_registration *reg =
+ tevent_req_callback_data(subreq,
+ struct swn_service_registration);
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct messaging_rec *rec = NULL;
+ struct rpcd_witness_registration_updateB update_blob;
+ enum ndr_err_code ndr_err;
+ NTSTATUS status;
+ int ret;
+
+ SMB_ASSERT(reg->msg.subreq == subreq);
+ reg->msg.subreq = NULL;
+
+ ret = messaging_filtered_read_recv(subreq, frame, &rec);
+ TALLOC_FREE(subreq);
+ if (ret != 0) {
+ status = map_nt_error_from_unix_common(ret);
+ DBG_ERR("messaging_filtered_read_recv() - %s\n",
+ nt_errstr(status));
+ goto wait_for_next;
+ }
+
+ DBG_DEBUG("MSG_RPCD_WITNESS_REGISTRATION_UPDATE: received...\n");
+
+ ndr_err = ndr_pull_struct_blob(&rec->buf, frame, &update_blob,
+ (ndr_pull_flags_fn_t)ndr_pull_rpcd_witness_registration_updateB);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ status = ndr_map_error2ntstatus(ndr_err);
+ DBG_ERR("ndr_pull_struct_blob - %s\n", nt_errstr(status));
+ goto wait_for_next;
+ }
+
+ if (DEBUGLVL(DBGLVL_DEBUG)) {
+ NDR_PRINT_DEBUG(rpcd_witness_registration_updateB, &update_blob);
+ }
+
+ switch (update_blob.type) {
+ case RPCD_WITNESS_REGISTRATION_UPDATE_CLIENT_MOVE_TO_NODE:
+ swn_server_registration_client_move_to_node(reg,
+ &update_blob.update.client_move_to_node);
+ break;
+ case RPCD_WITNESS_REGISTRATION_UPDATE_CLIENT_MOVE_TO_IPV4:
+ swn_server_registration_client_move_to_ipv4(reg,
+ &update_blob.update.client_move_to_ipv4);
+ break;
+ case RPCD_WITNESS_REGISTRATION_UPDATE_CLIENT_MOVE_TO_IPV6:
+ swn_server_registration_client_move_to_ipv6(reg,
+ &update_blob.update.client_move_to_ipv6);
+ break;
+ case RPCD_WITNESS_REGISTRATION_UPDATE_SHARE_MOVE_TO_NODE:
+ swn_server_registration_share_move_to_node(reg,
+ &update_blob.update.share_move_to_node);
+ break;
+ case RPCD_WITNESS_REGISTRATION_UPDATE_SHARE_MOVE_TO_IPV4:
+ swn_server_registration_share_move_to_ipv4(reg,
+ &update_blob.update.share_move_to_ipv4);
+ break;
+ case RPCD_WITNESS_REGISTRATION_UPDATE_SHARE_MOVE_TO_IPV6:
+ swn_server_registration_share_move_to_ipv6(reg,
+ &update_blob.update.share_move_to_ipv6);
+ break;
+ case RPCD_WITNESS_REGISTRATION_UPDATE_FORCE_UNREGISTER:
+ TALLOC_FREE(reg);
+ TALLOC_FREE(frame);
+ return;
+ case RPCD_WITNESS_REGISTRATION_UPDATE_FORCE_RESPONSE:
+ swn_server_registration_force_response(reg,
+ &update_blob.update.force_response);
+ break;
+ }
+
+wait_for_next:
+ TALLOC_FREE(frame);
+ reg->msg.subreq = messaging_filtered_read_send(reg,
+ reg->msg.ev_ctx,
+ reg->msg.msg_ctx,
+ swn_server_registration_message_filter,
+ reg);
+ if (reg->msg.subreq == NULL) {
+ DBG_ERR("messaging_filtered_read_send() failed\n");
+ return;
+ }
+ tevent_req_set_callback(reg->msg.subreq,
+ swn_server_registration_message_done,
+ reg);
+}
+