/* node connect/disconnect handlers */ static int node_action_handler(merlin_node *node, int prev_state) { switch (node->state) { case STATE_CONNECTED: /* * If we've received the timestamp marker from our module, * We need to send our own timestamp to the other end so * they know how to sort us in case we're a peer to them. */ if (ipc.info.start.tv_sec && ipc_is_connected(0)) { node_send_ctrl_active(node, CTRL_GENERIC, &ipc.info, 100); } break; case STATE_PENDING: case STATE_NEGOTIATING: case STATE_NONE: /* only send INACTIVE if we haven't already */ if (prev_state == STATE_CONNECTED) { db_mark_node_inactive(node); ldebug("Sending IPC control INACTIVE for '%s'", node->name); return ipc_send_ctrl(CTRL_INACTIVE, node->id); } } return 1; }
neb_cb_result * merlin_mod_hook(int cb, void *data) { merlin_event pkt; int result = 0; neb_cb_result *neb_result = NULL; static time_t last_pulse = 0, last_flood_warning = 0; time_t now; if (!data) { lerr("eventbroker module called with NULL data"); return neb_cb_result_create(-1); } else if (cb < 0 || cb > NEBCALLBACK_NUMITEMS) { lerr("merlin_mod_hook() called with invalid callback id"); return neb_cb_result_create(-1); } /* * must reset this here so events we don't check for * dupes are always sent properly */ check_dupes = 0; /* self-heal nodes that have missed out on the fact that we're up */ now = time(NULL); if(!last_pulse || now - last_pulse > 15) node_send_ctrl_active(&ipc, CTRL_GENERIC, &ipc.info); last_pulse = now; memset(&pkt, 0, sizeof(pkt)); pkt.hdr.type = cb; pkt.hdr.selection = DEST_BROADCAST; switch (cb) { case NEBCALLBACK_NOTIFICATION_DATA: neb_result = hook_notification(&pkt, data); break; case NEBCALLBACK_CONTACT_NOTIFICATION_METHOD_DATA: result = hook_contact_notification_method(&pkt, data); break; case NEBCALLBACK_HOST_CHECK_DATA: result = hook_host_result(&pkt, data); break; case NEBCALLBACK_SERVICE_CHECK_DATA: result = hook_service_result(&pkt, data); break; case NEBCALLBACK_COMMENT_DATA: result = hook_comment(&pkt, data); break; case NEBCALLBACK_DOWNTIME_DATA: result = hook_downtime(&pkt, data); break; case NEBCALLBACK_EXTERNAL_COMMAND_DATA: result = hook_external_command(&pkt, data); break; case NEBCALLBACK_FLAPPING_DATA: /* * flapping doesn't go to the network. check processing * will generate flapping alerts on all nodes anyway, */ case NEBCALLBACK_PROGRAM_STATUS_DATA: case NEBCALLBACK_PROCESS_DATA: /* these make no sense to ship across the wire */ pkt.hdr.code = MAGIC_NONET; result = send_generic(&pkt, data); break; case NEBCALLBACK_HOST_STATUS_DATA: case NEBCALLBACK_SERVICE_STATUS_DATA: /* * Don't handle status updates coming from Naemon. * If we need to send status updates for any reason it is done through * Merlin directly. For normal state updates, we let each node handle * check results so they keep their own state. */ break; case NEBCALLBACK_EVENT_HANDLER_DATA: result = hook_event_handler(&pkt, data); break; default: lerr("Unhandled callback '%s' in merlin_hook()", callback_name(cb)); } if (neb_result != NULL) { /* * We have a rich callback result, propagate return code * to preserve flood warnings */ result = neb_cb_result_returncode(neb_result); } else { /* * No rich callback result, create one */ neb_result = neb_cb_result_create_full(result, "No callback result description available"); } if (result < 0 && now - last_flood_warning > 30) { /* log a warning every 30 seconds */ last_flood_warning = now; lwarn("Daemon is flooded and backlogging failed"); } return neb_result; }