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