This source file includes following definitions.
- ipc_proxy_get_provider
 
- ipc_proxy_accept
 
- crmd_proxy_accept
 
- attrd_proxy_accept
 
- stonith_proxy_accept
 
- pacemakerd_proxy_accept
 
- cib_proxy_accept_rw
 
- cib_proxy_accept_ro
 
- ipc_proxy_forward_client
 
- ipc_proxy_dispatch
 
- ipc_proxy_shutdown_req
 
- ipc_proxy_closed
 
- ipc_proxy_destroy
 
- ipc_proxy_add_provider
 
- ipc_proxy_remove_provider
 
- ipc_proxy_init
 
- ipc_proxy_cleanup
 
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 #include <crm_internal.h>
  11 
  12 #include <glib.h>
  13 #include <unistd.h>
  14 
  15 #include "pacemaker-execd.h"
  16 #include <crm/crm.h>
  17 #include <crm/msg_xml.h>
  18 #include <crm/services.h>
  19 #include <crm/common/mainloop.h>
  20 #include <crm/common/ipc.h>
  21 #include <crm/common/ipc_internal.h>
  22 #include <crm/cib/internal.h>
  23 #include <crm/fencing/internal.h>
  24 
  25 static qb_ipcs_service_t *cib_ro = NULL;
  26 static qb_ipcs_service_t *cib_rw = NULL;
  27 static qb_ipcs_service_t *cib_shm = NULL;
  28 
  29 static qb_ipcs_service_t *attrd_ipcs = NULL;
  30 static qb_ipcs_service_t *crmd_ipcs = NULL;
  31 static qb_ipcs_service_t *stonith_ipcs = NULL;
  32 static qb_ipcs_service_t *pacemakerd_ipcs = NULL;
  33 
  34 
  35 static GList *ipc_providers = NULL;
  36 
  37 static GHashTable *ipc_clients = NULL;
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 pcmk__client_t *
  50 ipc_proxy_get_provider(void)
     
  51 {
  52     return ipc_providers? (pcmk__client_t *) (ipc_providers->data) : NULL;
  53 }
  54 
  55 
  56 
  57 
  58 
  59 
  60 
  61 
  62 
  63 
  64 
  65 
  66 static int32_t
  67 ipc_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid, const char *ipc_channel)
     
  68 {
  69     pcmk__client_t *client;
  70     pcmk__client_t *ipc_proxy = ipc_proxy_get_provider();
  71     xmlNode *msg;
  72 
  73     if (ipc_proxy == NULL) {
  74         crm_warn("Cannot proxy IPC connection from uid %d gid %d to %s "
  75                  "because not connected to cluster", uid, gid, ipc_channel);
  76         return -EREMOTEIO;
  77     }
  78 
  79     
  80 
  81 
  82     client = pcmk__new_client(c, uid, gid);
  83     if (client == NULL) {
  84         return -EREMOTEIO;
  85     }
  86 
  87     
  88 
  89     client->userdata = strdup(ipc_proxy->id);
  90     client->name = crm_strdup_printf("proxy-%s-%d-%.8s", ipc_channel, client->pid, client->id);
  91 
  92     
  93 
  94 
  95     pcmk__set_client_flags(client, pcmk__client_to_proxy);
  96 
  97     g_hash_table_insert(ipc_clients, client->id, client);
  98 
  99     msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
 100     crm_xml_add(msg, F_LRMD_IPC_OP, LRMD_IPC_OP_NEW);
 101     crm_xml_add(msg, F_LRMD_IPC_IPC_SERVER, ipc_channel);
 102     crm_xml_add(msg, F_LRMD_IPC_SESSION, client->id);
 103     lrmd_server_send_notify(ipc_proxy, msg);
 104     free_xml(msg);
 105     crm_debug("Accepted IPC proxy connection (session ID %s) "
 106               "from uid %d gid %d on channel %s",
 107               client->id, uid, gid, ipc_channel);
 108     return 0;
 109 }
 110 
 111 static int32_t
 112 crmd_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
     
 113 {
 114     return ipc_proxy_accept(c, uid, gid, CRM_SYSTEM_CRMD);
 115 }
 116 
 117 static int32_t
 118 attrd_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
     
 119 {
 120     return ipc_proxy_accept(c, uid, gid, T_ATTRD);
 121 }
 122 
 123 static int32_t
 124 stonith_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
     
 125 {
 126     return ipc_proxy_accept(c, uid, gid, "stonith-ng");
 127 }
 128 
 129 static int32_t
 130 pacemakerd_proxy_accept(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
     
 131 {
 132     return -EREMOTEIO;
 133 }
 134 
 135 static int32_t
 136 cib_proxy_accept_rw(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
     
 137 {
 138     return ipc_proxy_accept(c, uid, gid, PCMK__SERVER_BASED_RW);
 139 }
 140 
 141 static int32_t
 142 cib_proxy_accept_ro(qb_ipcs_connection_t * c, uid_t uid, gid_t gid)
     
 143 {
 144     return ipc_proxy_accept(c, uid, gid, PCMK__SERVER_BASED_RO);
 145 }
 146 
 147 void
 148 ipc_proxy_forward_client(pcmk__client_t *ipc_proxy, xmlNode *xml)
     
 149 {
 150     const char *session = crm_element_value(xml, F_LRMD_IPC_SESSION);
 151     const char *msg_type = crm_element_value(xml, F_LRMD_IPC_OP);
 152     xmlNode *msg = get_message_xml(xml, F_LRMD_IPC_MSG);
 153     pcmk__client_t *ipc_client;
 154     int rc = pcmk_rc_ok;
 155 
 156     
 157 
 158 
 159 
 160     if (pcmk__str_eq(msg_type, LRMD_IPC_OP_SHUTDOWN_ACK, pcmk__str_casei)) {
 161         handle_shutdown_ack();
 162         return;
 163     }
 164 
 165     if (pcmk__str_eq(msg_type, LRMD_IPC_OP_SHUTDOWN_NACK, pcmk__str_casei)) {
 166         handle_shutdown_nack();
 167         return;
 168     }
 169 
 170     ipc_client = pcmk__find_client_by_id(session);
 171     if (ipc_client == NULL) {
 172         xmlNode *msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
 173         crm_xml_add(msg, F_LRMD_IPC_OP, LRMD_IPC_OP_DESTROY);
 174         crm_xml_add(msg, F_LRMD_IPC_SESSION, session);
 175         lrmd_server_send_notify(ipc_proxy, msg);
 176         free_xml(msg);
 177         return;
 178     }
 179 
 180     
 181 
 182 
 183 
 184 
 185 
 186 
 187 
 188 
 189 
 190 
 191 
 192 
 193 
 194     if (pcmk__str_eq(msg_type, LRMD_IPC_OP_EVENT, pcmk__str_casei)) {
 195         crm_trace("Sending event to %s", ipc_client->id);
 196         rc = pcmk__ipc_send_xml(ipc_client, 0, msg, crm_ipc_server_event);
 197 
 198     } else if (pcmk__str_eq(msg_type, LRMD_IPC_OP_RESPONSE, pcmk__str_casei)) {
 199         int msg_id = 0;
 200 
 201         crm_element_value_int(xml, F_LRMD_IPC_MSG_ID, &msg_id);
 202         crm_trace("Sending response to %d - %s", ipc_client->request_id, ipc_client->id);
 203         rc = pcmk__ipc_send_xml(ipc_client, msg_id, msg, FALSE);
 204 
 205         CRM_LOG_ASSERT(msg_id == ipc_client->request_id);
 206         ipc_client->request_id = 0;
 207 
 208     } else if (pcmk__str_eq(msg_type, LRMD_IPC_OP_DESTROY, pcmk__str_casei)) {
 209         qb_ipcs_disconnect(ipc_client->ipcs);
 210 
 211     } else {
 212         crm_err("Unknown ipc proxy msg type %s" , msg_type);
 213     }
 214 
 215     if (rc != pcmk_rc_ok) {
 216         crm_warn("Could not proxy IPC to client %s: %s " CRM_XS " rc=%d",
 217                  ipc_client->id, pcmk_rc_str(rc), rc);
 218     }
 219 }
 220 
 221 static int32_t
 222 ipc_proxy_dispatch(qb_ipcs_connection_t * c, void *data, size_t size)
     
 223 {
 224     uint32_t id = 0;
 225     uint32_t flags = 0;
 226     pcmk__client_t *client = pcmk__find_client(c);
 227     pcmk__client_t *ipc_proxy = pcmk__find_client_by_id(client->userdata);
 228     xmlNode *request = NULL;
 229     xmlNode *msg = NULL;
 230 
 231     if (!ipc_proxy) {
 232         qb_ipcs_disconnect(client->ipcs);
 233         return 0;
 234     }
 235 
 236     
 237 
 238 
 239 
 240 
 241 
 242 
 243 
 244 
 245 
 246 
 247 
 248 
 249     request = pcmk__client_data2xml(client, data, &id, &flags);
 250 
 251     if (!request) {
 252         return 0;
 253     }
 254 
 255     CRM_CHECK(client != NULL, crm_err("Invalid client");
 256               free_xml(request); return FALSE);
 257     CRM_CHECK(client->id != NULL, crm_err("Invalid client: %p", client);
 258               free_xml(request); return FALSE);
 259 
 260     
 261 
 262 
 263     pcmk__set_ipc_flags(flags, pcmk__client_name(client), crm_ipc_proxied);
 264     client->request_id = id;
 265 
 266     msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
 267     crm_xml_add(msg, F_LRMD_IPC_OP, LRMD_IPC_OP_REQUEST);
 268     crm_xml_add(msg, F_LRMD_IPC_SESSION, client->id);
 269     crm_xml_add(msg, F_LRMD_IPC_CLIENT, pcmk__client_name(client));
 270     crm_xml_add(msg, F_LRMD_IPC_USER, client->user);
 271     crm_xml_add_int(msg, F_LRMD_IPC_MSG_ID, id);
 272     crm_xml_add_int(msg, F_LRMD_IPC_MSG_FLAGS, flags);
 273     add_message_xml(msg, F_LRMD_IPC_MSG, request);
 274     lrmd_server_send_notify(ipc_proxy, msg);
 275     free_xml(request);
 276     free_xml(msg);
 277 
 278     return 0;
 279 }
 280 
 281 
 282 
 283 
 284 
 285 
 286 
 287 
 288 
 289 int
 290 ipc_proxy_shutdown_req(pcmk__client_t *ipc_proxy)
     
 291 {
 292     xmlNode *msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
 293     int rc;
 294 
 295     crm_xml_add(msg, F_LRMD_IPC_OP, LRMD_IPC_OP_SHUTDOWN_REQ);
 296 
 297     
 298 
 299 
 300     crm_xml_add(msg, F_LRMD_IPC_SESSION, "0");
 301 
 302     rc = (lrmd_server_send_notify(ipc_proxy, msg) != pcmk_rc_ok)? -1 : 0;
 303     free_xml(msg);
 304     return rc;
 305 }
 306 
 307 static int32_t
 308 ipc_proxy_closed(qb_ipcs_connection_t * c)
     
 309 {
 310     pcmk__client_t *client = pcmk__find_client(c);
 311     pcmk__client_t *ipc_proxy;
 312 
 313     if (client == NULL) {
 314         return 0;
 315     }
 316 
 317     ipc_proxy = pcmk__find_client_by_id(client->userdata);
 318 
 319     crm_trace("Connection %p", c);
 320 
 321     if (ipc_proxy) {
 322         xmlNode *msg = create_xml_node(NULL, T_LRMD_IPC_PROXY);
 323         crm_xml_add(msg, F_LRMD_IPC_OP, LRMD_IPC_OP_DESTROY);
 324         crm_xml_add(msg, F_LRMD_IPC_SESSION, client->id);
 325         lrmd_server_send_notify(ipc_proxy, msg);
 326         free_xml(msg);
 327     }
 328 
 329     g_hash_table_remove(ipc_clients, client->id);
 330 
 331     free(client->userdata);
 332     client->userdata = NULL;
 333     pcmk__free_client(client);
 334     return 0;
 335 }
 336 
 337 static void
 338 ipc_proxy_destroy(qb_ipcs_connection_t * c)
     
 339 {
 340     crm_trace("Connection %p", c);
 341     ipc_proxy_closed(c);
 342 }
 343 
 344 static struct qb_ipcs_service_handlers crmd_proxy_callbacks = {
 345     .connection_accept = crmd_proxy_accept,
 346     .connection_created = NULL,
 347     .msg_process = ipc_proxy_dispatch,
 348     .connection_closed = ipc_proxy_closed,
 349     .connection_destroyed = ipc_proxy_destroy
 350 };
 351 
 352 static struct qb_ipcs_service_handlers attrd_proxy_callbacks = {
 353     .connection_accept = attrd_proxy_accept,
 354     .connection_created = NULL,
 355     .msg_process = ipc_proxy_dispatch,
 356     .connection_closed = ipc_proxy_closed,
 357     .connection_destroyed = ipc_proxy_destroy
 358 };
 359 
 360 static struct qb_ipcs_service_handlers stonith_proxy_callbacks = {
 361     .connection_accept = stonith_proxy_accept,
 362     .connection_created = NULL,
 363     .msg_process = ipc_proxy_dispatch,
 364     .connection_closed = ipc_proxy_closed,
 365     .connection_destroyed = ipc_proxy_destroy
 366 };
 367 
 368 static struct qb_ipcs_service_handlers pacemakerd_proxy_callbacks = {
 369     .connection_accept = pacemakerd_proxy_accept,
 370     .connection_created = NULL,
 371     .msg_process = NULL,
 372     .connection_closed = NULL,
 373     .connection_destroyed = NULL
 374 };
 375 
 376 static struct qb_ipcs_service_handlers cib_proxy_callbacks_ro = {
 377     .connection_accept = cib_proxy_accept_ro,
 378     .connection_created = NULL,
 379     .msg_process = ipc_proxy_dispatch,
 380     .connection_closed = ipc_proxy_closed,
 381     .connection_destroyed = ipc_proxy_destroy
 382 };
 383 
 384 static struct qb_ipcs_service_handlers cib_proxy_callbacks_rw = {
 385     .connection_accept = cib_proxy_accept_rw,
 386     .connection_created = NULL,
 387     .msg_process = ipc_proxy_dispatch,
 388     .connection_closed = ipc_proxy_closed,
 389     .connection_destroyed = ipc_proxy_destroy
 390 };
 391 
 392 void
 393 ipc_proxy_add_provider(pcmk__client_t *ipc_proxy)
     
 394 {
 395     
 396     ipc_providers = g_list_prepend(ipc_providers, ipc_proxy);
 397 }
 398 
 399 void
 400 ipc_proxy_remove_provider(pcmk__client_t *ipc_proxy)
     
 401 {
 402     GHashTableIter iter;
 403     pcmk__client_t *ipc_client = NULL;
 404     char *key = NULL;
 405     GList *remove_these = NULL;
 406     GList *gIter = NULL;
 407 
 408     ipc_providers = g_list_remove(ipc_providers, ipc_proxy);
 409 
 410     g_hash_table_iter_init(&iter, ipc_clients);
 411     while (g_hash_table_iter_next(&iter, (gpointer *) & key, (gpointer *) & ipc_client)) {
 412         const char *proxy_id = ipc_client->userdata;
 413         if (pcmk__str_eq(proxy_id, ipc_proxy->id, pcmk__str_casei)) {
 414             crm_info("ipc proxy connection for client %s pid %d destroyed because cluster node disconnected.",
 415                 ipc_client->id, ipc_client->pid);
 416             
 417 
 418             remove_these = g_list_append(remove_these, ipc_client);
 419         }
 420     }
 421 
 422     for (gIter = remove_these; gIter != NULL; gIter = gIter->next) {
 423         ipc_client = gIter->data;
 424 
 425         
 426         qb_ipcs_disconnect(ipc_client->ipcs);
 427     }
 428 
 429     
 430     g_list_free(remove_these);
 431 }
 432 
 433 void
 434 ipc_proxy_init(void)
     
 435 {
 436     ipc_clients = pcmk__strkey_table(NULL, NULL);
 437 
 438     pcmk__serve_based_ipc(&cib_ro, &cib_rw, &cib_shm, &cib_proxy_callbacks_ro,
 439                           &cib_proxy_callbacks_rw);
 440     pcmk__serve_attrd_ipc(&attrd_ipcs, &attrd_proxy_callbacks);
 441     pcmk__serve_fenced_ipc(&stonith_ipcs, &stonith_proxy_callbacks);
 442     pcmk__serve_pacemakerd_ipc(&pacemakerd_ipcs, &pacemakerd_proxy_callbacks);
 443     crmd_ipcs = pcmk__serve_controld_ipc(&crmd_proxy_callbacks);
 444     if (crmd_ipcs == NULL) {
 445         crm_err("Failed to create controller: exiting and inhibiting respawn");
 446         crm_warn("Verify pacemaker and pacemaker_remote are not both enabled");
 447         crm_exit(CRM_EX_FATAL);
 448     }
 449 }
 450 
 451 void
 452 ipc_proxy_cleanup(void)
     
 453 {
 454     if (ipc_providers) {
 455         g_list_free(ipc_providers);
 456         ipc_providers = NULL;
 457     }
 458     if (ipc_clients) {
 459         g_hash_table_destroy(ipc_clients);
 460         ipc_clients = NULL;
 461     }
 462     pcmk__stop_based_ipc(cib_ro, cib_rw, cib_shm);
 463     qb_ipcs_destroy(attrd_ipcs);
 464     qb_ipcs_destroy(stonith_ipcs);
 465     qb_ipcs_destroy(pacemakerd_ipcs);
 466     qb_ipcs_destroy(crmd_ipcs);
 467     cib_ro = NULL;
 468     cib_rw = NULL;
 469     cib_shm = NULL;
 470 }