LCOV - code coverage report
Current view: top level - cib - cib_remote.c (source / functions) Hit Total Coverage
Test: Pacemaker code coverage Lines: 0 300 0.0 %
Date: 2024-05-07 11:09:47 Functions: 0 15 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2008-2024 the Pacemaker project contributors
       3             :  *
       4             :  * The version control history for this file may have further details.
       5             :  *
       6             :  * This source code is licensed under the GNU Lesser General Public License
       7             :  * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
       8             :  */
       9             : 
      10             : #include <crm_internal.h>
      11             : 
      12             : #include <unistd.h>
      13             : #include <stdlib.h>
      14             : #include <stdio.h>
      15             : #include <stdarg.h>
      16             : #include <string.h>
      17             : #include <netdb.h>
      18             : #include <termios.h>
      19             : #include <sys/socket.h>
      20             : 
      21             : #include <glib.h>
      22             : 
      23             : #include <crm/crm.h>
      24             : #include <crm/cib/internal.h>
      25             : #include <crm/common/ipc_internal.h>
      26             : #include <crm/common/mainloop.h>
      27             : #include <crm/common/xml.h>
      28             : #include <crm/common/remote_internal.h>
      29             : #include <crm/common/output_internal.h>
      30             : 
      31             : #ifdef HAVE_GNUTLS_GNUTLS_H
      32             : 
      33             : #  include <gnutls/gnutls.h>
      34             : 
      35             : #  define TLS_HANDSHAKE_TIMEOUT_MS 5000
      36             : 
      37             : static gnutls_anon_client_credentials_t anon_cred_c;
      38             : static gboolean remote_gnutls_credentials_init = FALSE;
      39             : 
      40             : #endif // HAVE_GNUTLS_GNUTLS_H
      41             : 
      42             : #include <arpa/inet.h>
      43             : 
      44             : typedef struct cib_remote_opaque_s {
      45             :     int port;
      46             :     char *server;
      47             :     char *user;
      48             :     char *passwd;
      49             :     gboolean encrypted;
      50             :     pcmk__remote_t command;
      51             :     pcmk__remote_t callback;
      52             :     pcmk__output_t *out;
      53             : } cib_remote_opaque_t;
      54             : 
      55             : static int
      56           0 : cib_remote_perform_op(cib_t *cib, const char *op, const char *host,
      57             :                       const char *section, xmlNode *data,
      58             :                       xmlNode **output_data, int call_options,
      59             :                       const char *user_name)
      60             : {
      61             :     int rc;
      62           0 :     int remaining_time = 0;
      63             :     time_t start_time;
      64             : 
      65           0 :     xmlNode *op_msg = NULL;
      66           0 :     xmlNode *op_reply = NULL;
      67             : 
      68           0 :     cib_remote_opaque_t *private = cib->variant_opaque;
      69             : 
      70           0 :     if (cib->state == cib_disconnected) {
      71           0 :         return -ENOTCONN;
      72             :     }
      73             : 
      74           0 :     if (output_data != NULL) {
      75           0 :         *output_data = NULL;
      76             :     }
      77             : 
      78           0 :     if (op == NULL) {
      79           0 :         crm_err("No operation specified");
      80           0 :         return -EINVAL;
      81             :     }
      82             : 
      83           0 :     rc = cib__create_op(cib, op, host, section, data, call_options, user_name,
      84             :                         NULL, &op_msg);
      85           0 :     if (rc != pcmk_ok) {
      86           0 :         return rc;
      87             :     }
      88             : 
      89           0 :     if (pcmk_is_set(call_options, cib_transaction)) {
      90           0 :         rc = cib__extend_transaction(cib, op_msg);
      91           0 :         free_xml(op_msg);
      92           0 :         return rc;
      93             :     }
      94             : 
      95           0 :     crm_trace("Sending %s message to the CIB manager", op);
      96           0 :     if (!(call_options & cib_sync_call)) {
      97           0 :         pcmk__remote_send_xml(&private->callback, op_msg);
      98             :     } else {
      99           0 :         pcmk__remote_send_xml(&private->command, op_msg);
     100             :     }
     101           0 :     free_xml(op_msg);
     102             : 
     103           0 :     if ((call_options & cib_discard_reply)) {
     104           0 :         crm_trace("Discarding reply");
     105           0 :         return pcmk_ok;
     106             : 
     107           0 :     } else if (!(call_options & cib_sync_call)) {
     108           0 :         return cib->call_id;
     109             :     }
     110             : 
     111           0 :     crm_trace("Waiting for a synchronous reply");
     112             : 
     113           0 :     start_time = time(NULL);
     114           0 :     remaining_time = cib->call_timeout ? cib->call_timeout : 60;
     115             : 
     116           0 :     rc = pcmk_rc_ok;
     117           0 :     while (remaining_time > 0 && (rc != ENOTCONN)) {
     118           0 :         int reply_id = -1;
     119           0 :         int msg_id = cib->call_id;
     120             : 
     121           0 :         rc = pcmk__read_remote_message(&private->command,
     122             :                                        remaining_time * 1000);
     123           0 :         op_reply = pcmk__remote_message_xml(&private->command);
     124             : 
     125           0 :         if (!op_reply) {
     126           0 :             break;
     127             :         }
     128             : 
     129           0 :         crm_element_value_int(op_reply, PCMK__XA_CIB_CALLID, &reply_id);
     130             : 
     131           0 :         if (reply_id == msg_id) {
     132           0 :             break;
     133             : 
     134           0 :         } else if (reply_id < msg_id) {
     135           0 :             crm_debug("Received old reply: %d (wanted %d)", reply_id, msg_id);
     136           0 :             crm_log_xml_trace(op_reply, "Old reply");
     137             : 
     138           0 :         } else if ((reply_id - 10000) > msg_id) {
     139             :             /* wrap-around case */
     140           0 :             crm_debug("Received old reply: %d (wanted %d)", reply_id, msg_id);
     141           0 :             crm_log_xml_trace(op_reply, "Old reply");
     142             :         } else {
     143           0 :             crm_err("Received a __future__ reply:" " %d (wanted %d)", reply_id, msg_id);
     144             :         }
     145             : 
     146           0 :         free_xml(op_reply);
     147           0 :         op_reply = NULL;
     148             : 
     149             :         /* wasn't the right reply, try and read some more */
     150           0 :         remaining_time = time(NULL) - start_time;
     151             :     }
     152             : 
     153             :     /* if(IPC_ISRCONN(native->command_channel) == FALSE) { */
     154             :     /*      crm_err("The CIB manager disconnected: %d",  */
     155             :     /*              native->command_channel->ch_status); */
     156             :     /*      cib->state = cib_disconnected; */
     157             :     /* } */
     158             : 
     159           0 :     if (rc == ENOTCONN) {
     160           0 :         crm_err("Disconnected while waiting for reply.");
     161           0 :         return -ENOTCONN;
     162           0 :     } else if (op_reply == NULL) {
     163           0 :         crm_err("No reply message - empty");
     164           0 :         return -ENOMSG;
     165             :     }
     166             : 
     167           0 :     crm_trace("Synchronous reply received");
     168             : 
     169             :     /* Start processing the reply... */
     170           0 :     if (crm_element_value_int(op_reply, PCMK__XA_CIB_RC, &rc) != 0) {
     171           0 :         rc = -EPROTO;
     172             :     }
     173             : 
     174           0 :     if (rc == -pcmk_err_diff_resync) {
     175             :         /* This is an internal value that clients do not and should not care about */
     176           0 :         rc = pcmk_ok;
     177             :     }
     178             : 
     179           0 :     if (rc == pcmk_ok || rc == -EPERM) {
     180           0 :         crm_log_xml_debug(op_reply, "passed");
     181             : 
     182             :     } else {
     183             : /*  } else if(rc == -ETIME) { */
     184           0 :         crm_err("Call failed: %s", pcmk_strerror(rc));
     185           0 :         crm_log_xml_warn(op_reply, "failed");
     186             :     }
     187             : 
     188           0 :     if (output_data == NULL) {
     189             :         /* do nothing more */
     190             : 
     191           0 :     } else if (!(call_options & cib_discard_reply)) {
     192           0 :         xmlNode *wrapper = pcmk__xe_first_child(op_reply, PCMK__XE_CIB_CALLDATA,
     193             :                                                 NULL, NULL);
     194           0 :         xmlNode *tmp = pcmk__xe_first_child(wrapper, NULL, NULL, NULL);
     195             : 
     196           0 :         if (tmp == NULL) {
     197           0 :             crm_trace("No output in reply to \"%s\" command %d", op, cib->call_id - 1);
     198             :         } else {
     199           0 :             *output_data = pcmk__xml_copy(NULL, tmp);
     200             :         }
     201             :     }
     202             : 
     203           0 :     free_xml(op_reply);
     204             : 
     205           0 :     return rc;
     206             : }
     207             : 
     208             : static int
     209           0 : cib_remote_callback_dispatch(gpointer user_data)
     210             : {
     211             :     int rc;
     212           0 :     cib_t *cib = user_data;
     213           0 :     cib_remote_opaque_t *private = cib->variant_opaque;
     214             : 
     215           0 :     xmlNode *msg = NULL;
     216             : 
     217           0 :     crm_info("Message on callback channel");
     218             : 
     219           0 :     rc = pcmk__read_remote_message(&private->callback, -1);
     220             : 
     221           0 :     msg = pcmk__remote_message_xml(&private->callback);
     222           0 :     while (msg) {
     223           0 :         const char *type = crm_element_value(msg, PCMK__XA_T);
     224             : 
     225           0 :         crm_trace("Activating %s callbacks...", type);
     226             : 
     227           0 :         if (pcmk__str_eq(type, PCMK__VALUE_CIB, pcmk__str_none)) {
     228           0 :             cib_native_callback(cib, msg, 0, 0);
     229             : 
     230           0 :         } else if (pcmk__str_eq(type, PCMK__VALUE_CIB_NOTIFY, pcmk__str_none)) {
     231           0 :             g_list_foreach(cib->notify_list, cib_native_notify, msg);
     232             : 
     233             :         } else {
     234           0 :             crm_err("Unknown message type: %s", type);
     235             :         }
     236             : 
     237           0 :         free_xml(msg);
     238           0 :         msg = pcmk__remote_message_xml(&private->callback);
     239             :     }
     240             : 
     241           0 :     if (rc == ENOTCONN) {
     242           0 :         return -1;
     243             :     }
     244             : 
     245           0 :     return 0;
     246             : }
     247             : 
     248             : static int
     249           0 : cib_remote_command_dispatch(gpointer user_data)
     250             : {
     251             :     int rc;
     252           0 :     cib_t *cib = user_data;
     253           0 :     cib_remote_opaque_t *private = cib->variant_opaque;
     254             : 
     255           0 :     rc = pcmk__read_remote_message(&private->command, -1);
     256             : 
     257           0 :     free(private->command.buffer);
     258           0 :     private->command.buffer = NULL;
     259           0 :     crm_err("received late reply for remote cib connection, discarding");
     260             : 
     261           0 :     if (rc == ENOTCONN) {
     262           0 :         return -1;
     263             :     }
     264           0 :     return 0;
     265             : }
     266             : 
     267             : static int
     268           0 : cib_tls_close(cib_t *cib)
     269             : {
     270           0 :     cib_remote_opaque_t *private = cib->variant_opaque;
     271             : 
     272             : #ifdef HAVE_GNUTLS_GNUTLS_H
     273           0 :     if (private->encrypted) {
     274           0 :         if (private->command.tls_session) {
     275           0 :             gnutls_bye(*(private->command.tls_session), GNUTLS_SHUT_RDWR);
     276           0 :             gnutls_deinit(*(private->command.tls_session));
     277           0 :             gnutls_free(private->command.tls_session);
     278             :         }
     279             : 
     280           0 :         if (private->callback.tls_session) {
     281           0 :             gnutls_bye(*(private->callback.tls_session), GNUTLS_SHUT_RDWR);
     282           0 :             gnutls_deinit(*(private->callback.tls_session));
     283           0 :             gnutls_free(private->callback.tls_session);
     284             :         }
     285           0 :         private->command.tls_session = NULL;
     286           0 :         private->callback.tls_session = NULL;
     287           0 :         if (remote_gnutls_credentials_init) {
     288           0 :             gnutls_anon_free_client_credentials(anon_cred_c);
     289           0 :             gnutls_global_deinit();
     290           0 :             remote_gnutls_credentials_init = FALSE;
     291             :         }
     292             :     }
     293             : #endif
     294             : 
     295           0 :     if (private->command.tcp_socket) {
     296           0 :         shutdown(private->command.tcp_socket, SHUT_RDWR);       /* no more receptions */
     297           0 :         close(private->command.tcp_socket);
     298             :     }
     299           0 :     if (private->callback.tcp_socket) {
     300           0 :         shutdown(private->callback.tcp_socket, SHUT_RDWR);      /* no more receptions */
     301           0 :         close(private->callback.tcp_socket);
     302             :     }
     303           0 :     private->command.tcp_socket = 0;
     304           0 :     private->callback.tcp_socket = 0;
     305             : 
     306           0 :     free(private->command.buffer);
     307           0 :     free(private->callback.buffer);
     308           0 :     private->command.buffer = NULL;
     309           0 :     private->callback.buffer = NULL;
     310             : 
     311           0 :     return 0;
     312             : }
     313             : 
     314             : static void
     315           0 : cib_remote_connection_destroy(gpointer user_data)
     316             : {
     317           0 :     crm_err("Connection destroyed");
     318             : #ifdef HAVE_GNUTLS_GNUTLS_H
     319           0 :     cib_tls_close(user_data);
     320             : #endif
     321           0 : }
     322             : 
     323             : static int
     324           0 : cib_tls_signon(cib_t *cib, pcmk__remote_t *connection, gboolean event_channel)
     325             : {
     326           0 :     cib_remote_opaque_t *private = cib->variant_opaque;
     327             :     int rc;
     328             : 
     329           0 :     xmlNode *answer = NULL;
     330           0 :     xmlNode *login = NULL;
     331             : 
     332             :     static struct mainloop_fd_callbacks cib_fd_callbacks = { 0, };
     333             : 
     334           0 :     cib_fd_callbacks.dispatch =
     335           0 :         event_channel ? cib_remote_callback_dispatch : cib_remote_command_dispatch;
     336           0 :     cib_fd_callbacks.destroy = cib_remote_connection_destroy;
     337             : 
     338           0 :     connection->tcp_socket = -1;
     339             : #ifdef HAVE_GNUTLS_GNUTLS_H
     340           0 :     connection->tls_session = NULL;
     341             : #endif
     342           0 :     rc = pcmk__connect_remote(private->server, private->port, 0, NULL,
     343             :                               &(connection->tcp_socket), NULL, NULL);
     344           0 :     if (rc != pcmk_rc_ok) {
     345           0 :         crm_info("Remote connection to %s:%d failed: %s " CRM_XS " rc=%d",
     346             :                  private->server, private->port, pcmk_rc_str(rc), rc);
     347           0 :         return -ENOTCONN;
     348             :     }
     349             : 
     350           0 :     if (private->encrypted) {
     351             :         /* initialize GnuTls lib */
     352             : #ifdef HAVE_GNUTLS_GNUTLS_H
     353           0 :         if (remote_gnutls_credentials_init == FALSE) {
     354           0 :             crm_gnutls_global_init();
     355           0 :             gnutls_anon_allocate_client_credentials(&anon_cred_c);
     356           0 :             remote_gnutls_credentials_init = TRUE;
     357             :         }
     358             : 
     359             :         /* bind the socket to GnuTls lib */
     360           0 :         connection->tls_session = pcmk__new_tls_session(connection->tcp_socket,
     361             :                                                         GNUTLS_CLIENT,
     362             :                                                         GNUTLS_CRD_ANON,
     363             :                                                         anon_cred_c);
     364           0 :         if (connection->tls_session == NULL) {
     365           0 :             cib_tls_close(cib);
     366           0 :             return -1;
     367             :         }
     368             : 
     369           0 :         if (pcmk__tls_client_handshake(connection, TLS_HANDSHAKE_TIMEOUT_MS)
     370             :                 != pcmk_rc_ok) {
     371           0 :             crm_err("Session creation for %s:%d failed", private->server, private->port);
     372             : 
     373           0 :             gnutls_deinit(*connection->tls_session);
     374           0 :             gnutls_free(connection->tls_session);
     375           0 :             connection->tls_session = NULL;
     376           0 :             cib_tls_close(cib);
     377           0 :             return -1;
     378             :         }
     379             : #else
     380             :         return -EPROTONOSUPPORT;
     381             : #endif
     382             :     }
     383             : 
     384             :     /* login to server */
     385           0 :     login = pcmk__xe_create(NULL, PCMK__XE_CIB_COMMAND);
     386           0 :     crm_xml_add(login, PCMK_XA_OP, "authenticate");
     387           0 :     crm_xml_add(login, PCMK_XA_USER, private->user);
     388           0 :     crm_xml_add(login, PCMK__XA_PASSWORD, private->passwd);
     389           0 :     crm_xml_add(login, PCMK__XA_HIDDEN, PCMK__VALUE_PASSWORD);
     390             : 
     391           0 :     pcmk__remote_send_xml(connection, login);
     392           0 :     free_xml(login);
     393             : 
     394           0 :     rc = pcmk_ok;
     395           0 :     if (pcmk__read_remote_message(connection, -1) == ENOTCONN) {
     396           0 :         rc = -ENOTCONN;
     397             :     }
     398             : 
     399           0 :     answer = pcmk__remote_message_xml(connection);
     400             : 
     401           0 :     crm_log_xml_trace(answer, "Reply");
     402           0 :     if (answer == NULL) {
     403           0 :         rc = -EPROTO;
     404             : 
     405             :     } else {
     406             :         /* grab the token */
     407           0 :         const char *msg_type = crm_element_value(answer, PCMK__XA_CIB_OP);
     408           0 :         const char *tmp_ticket = crm_element_value(answer,
     409             :                                                    PCMK__XA_CIB_CLIENTID);
     410             : 
     411           0 :         if (!pcmk__str_eq(msg_type, CRM_OP_REGISTER, pcmk__str_casei)) {
     412           0 :             crm_err("Invalid registration message: %s", msg_type);
     413           0 :             rc = -EPROTO;
     414             : 
     415           0 :         } else if (tmp_ticket == NULL) {
     416           0 :             rc = -EPROTO;
     417             : 
     418             :         } else {
     419           0 :             connection->token = strdup(tmp_ticket);
     420             :         }
     421             :     }
     422           0 :     free_xml(answer);
     423           0 :     answer = NULL;
     424             : 
     425           0 :     if (rc != 0) {
     426           0 :         cib_tls_close(cib);
     427           0 :         return rc;
     428             :     }
     429             : 
     430           0 :     crm_trace("remote client connection established");
     431           0 :     connection->source = mainloop_add_fd("cib-remote", G_PRIORITY_HIGH,
     432             :                                          connection->tcp_socket, cib,
     433             :                                          &cib_fd_callbacks);
     434           0 :     return rc;
     435             : }
     436             : 
     437             : static int
     438           0 : cib_remote_signon(cib_t *cib, const char *name, enum cib_conn_type type)
     439             : {
     440           0 :     int rc = pcmk_ok;
     441           0 :     cib_remote_opaque_t *private = cib->variant_opaque;
     442           0 :     xmlNode *hello = NULL;
     443             : 
     444           0 :     if (private->passwd == NULL) {
     445           0 :         if (private->out == NULL) {
     446             :             /* If no pcmk__output_t is set, just assume that a text prompt
     447             :              * is good enough.
     448             :              */
     449           0 :             pcmk__text_prompt("Password", false, &(private->passwd));
     450             :         } else {
     451           0 :             private->out->prompt("Password", false, &(private->passwd));
     452             :         }
     453             :     }
     454             : 
     455           0 :     if (private->server == NULL || private->user == NULL) {
     456           0 :         rc = -EINVAL;
     457             :     }
     458             : 
     459           0 :     if (rc == pcmk_ok) {
     460           0 :         rc = cib_tls_signon(cib, &(private->command), FALSE);
     461             :     }
     462             : 
     463           0 :     if (rc == pcmk_ok) {
     464           0 :         rc = cib_tls_signon(cib, &(private->callback), TRUE);
     465             :     }
     466             : 
     467           0 :     if (rc == pcmk_ok) {
     468           0 :         rc = cib__create_op(cib, CRM_OP_REGISTER, NULL, NULL, NULL, cib_none,
     469             :                             NULL, name, &hello);
     470             :     }
     471             : 
     472           0 :     if (rc == pcmk_ok) {
     473           0 :         rc = pcmk__remote_send_xml(&private->command, hello);
     474           0 :         rc = pcmk_rc2legacy(rc);
     475           0 :         free_xml(hello);
     476             :     }
     477             : 
     478           0 :     if (rc == pcmk_ok) {
     479           0 :         crm_info("Opened connection to %s:%d for %s",
     480             :                  private->server, private->port, name);
     481           0 :         cib->state = cib_connected_command;
     482           0 :         cib->type = cib_command;
     483             : 
     484             :     } else {
     485           0 :         crm_info("Connection to %s:%d for %s failed: %s\n",
     486             :                  private->server, private->port, name, pcmk_strerror(rc));
     487             :     }
     488             : 
     489           0 :     return rc;
     490             : }
     491             : 
     492             : static int
     493           0 : cib_remote_signoff(cib_t *cib)
     494             : {
     495           0 :     int rc = pcmk_ok;
     496             : 
     497           0 :     crm_debug("Disconnecting from the CIB manager");
     498             : #ifdef HAVE_GNUTLS_GNUTLS_H
     499           0 :     cib_tls_close(cib);
     500             : #endif
     501             : 
     502           0 :     cib->cmds->end_transaction(cib, false, cib_none);
     503           0 :     cib->state = cib_disconnected;
     504           0 :     cib->type = cib_no_connection;
     505             : 
     506           0 :     return rc;
     507             : }
     508             : 
     509             : static int
     510           0 : cib_remote_free(cib_t *cib)
     511             : {
     512           0 :     int rc = pcmk_ok;
     513             : 
     514           0 :     crm_warn("Freeing CIB");
     515           0 :     if (cib->state != cib_disconnected) {
     516           0 :         rc = cib_remote_signoff(cib);
     517           0 :         if (rc == pcmk_ok) {
     518           0 :             cib_remote_opaque_t *private = cib->variant_opaque;
     519             : 
     520           0 :             free(private->server);
     521           0 :             free(private->user);
     522           0 :             free(private->passwd);
     523           0 :             free(cib->cmds);
     524           0 :             free(cib->user);
     525           0 :             free(private);
     526           0 :             free(cib);
     527             :         }
     528             :     }
     529             : 
     530           0 :     return rc;
     531             : }
     532             : 
     533             : static int
     534           0 : cib_remote_inputfd(cib_t * cib)
     535             : {
     536           0 :     cib_remote_opaque_t *private = cib->variant_opaque;
     537             : 
     538           0 :     return private->callback.tcp_socket;
     539             : }
     540             : 
     541             : static int
     542           0 : cib_remote_register_notification(cib_t * cib, const char *callback, int enabled)
     543             : {
     544           0 :     xmlNode *notify_msg = pcmk__xe_create(NULL, PCMK__XE_CIB_COMMAND);
     545           0 :     cib_remote_opaque_t *private = cib->variant_opaque;
     546             : 
     547           0 :     crm_xml_add(notify_msg, PCMK__XA_CIB_OP, PCMK__VALUE_CIB_NOTIFY);
     548           0 :     crm_xml_add(notify_msg, PCMK__XA_CIB_NOTIFY_TYPE, callback);
     549           0 :     crm_xml_add_int(notify_msg, PCMK__XA_CIB_NOTIFY_ACTIVATE, enabled);
     550           0 :     pcmk__remote_send_xml(&private->callback, notify_msg);
     551           0 :     free_xml(notify_msg);
     552           0 :     return pcmk_ok;
     553             : }
     554             : 
     555             : static int
     556           0 : cib_remote_set_connection_dnotify(cib_t * cib, void (*dnotify) (gpointer user_data))
     557             : {
     558           0 :     return -EPROTONOSUPPORT;
     559             : }
     560             : 
     561             : /*!
     562             :  * \internal
     563             :  * \brief Get the given CIB connection's unique client identifiers
     564             :  *
     565             :  * These can be used to check whether this client requested the action that
     566             :  * triggered a CIB notification.
     567             :  *
     568             :  * \param[in]  cib       CIB connection
     569             :  * \param[out] async_id  If not \p NULL, where to store asynchronous client ID
     570             :  * \param[out] sync_id   If not \p NULL, where to store synchronous client ID
     571             :  *
     572             :  * \return Legacy Pacemaker return code (specifically, \p pcmk_ok)
     573             :  *
     574             :  * \note This is the \p cib_remote variant implementation of
     575             :  *       \p cib_api_operations_t:client_id().
     576             :  * \note The client IDs are assigned during CIB sign-on.
     577             :  */
     578             : static int
     579           0 : cib_remote_client_id(const cib_t *cib, const char **async_id,
     580             :                      const char **sync_id)
     581             : {
     582           0 :     cib_remote_opaque_t *private = cib->variant_opaque;
     583             : 
     584           0 :     if (async_id != NULL) {
     585             :         // private->callback is the channel for async requests
     586           0 :         *async_id = private->callback.token;
     587             :     }
     588           0 :     if (sync_id != NULL) {
     589             :         // private->command is the channel for sync requests
     590           0 :         *sync_id = private->command.token;
     591             :     }
     592           0 :     return pcmk_ok;
     593             : }
     594             : 
     595             : cib_t *
     596           0 : cib_remote_new(const char *server, const char *user, const char *passwd, int port,
     597             :                gboolean encrypted)
     598             : {
     599           0 :     cib_remote_opaque_t *private = NULL;
     600           0 :     cib_t *cib = cib_new_variant();
     601             : 
     602           0 :     if (cib == NULL) {
     603           0 :         return NULL;
     604             :     }
     605             : 
     606           0 :     private = calloc(1, sizeof(cib_remote_opaque_t));
     607             : 
     608           0 :     if (private == NULL) {
     609           0 :         free(cib);
     610           0 :         return NULL;
     611             :     }
     612             : 
     613           0 :     cib->variant = cib_remote;
     614           0 :     cib->variant_opaque = private;
     615             : 
     616           0 :     private->server = pcmk__str_copy(server);
     617           0 :     private->user = pcmk__str_copy(user);
     618           0 :     private->passwd = pcmk__str_copy(passwd);
     619           0 :     private->port = port;
     620           0 :     private->encrypted = encrypted;
     621             : 
     622             :     /* assign variant specific ops */
     623           0 :     cib->delegate_fn = cib_remote_perform_op;
     624           0 :     cib->cmds->signon = cib_remote_signon;
     625           0 :     cib->cmds->signoff = cib_remote_signoff;
     626           0 :     cib->cmds->free = cib_remote_free;
     627           0 :     cib->cmds->inputfd = cib_remote_inputfd; // Deprecated method
     628             : 
     629           0 :     cib->cmds->register_notification = cib_remote_register_notification;
     630           0 :     cib->cmds->set_connection_dnotify = cib_remote_set_connection_dnotify;
     631             : 
     632           0 :     cib->cmds->client_id = cib_remote_client_id;
     633             : 
     634           0 :     return cib;
     635             : }
     636             : 
     637             : void
     638           0 : cib__set_output(cib_t *cib, pcmk__output_t *out)
     639             : {
     640             :     cib_remote_opaque_t *private;
     641             : 
     642           0 :     if (cib->variant != cib_remote) {
     643           0 :         return;
     644             :     }
     645             : 
     646           0 :     private = cib->variant_opaque;
     647           0 :     private->out = out;
     648             : }

Generated by: LCOV version 1.14