return -1;
}
-static void *DetectEngineLiveRuleSwap(void *arg)
-{
- SCEnter();
-
- int i = 0;
- int no_of_detect_tvs = 0;
- DetectEngineCtx *old_de_ctx = NULL;
- ThreadVars *tv = NULL;
-
- if (SCSetThreadName("LiveRuleSwap") < 0) {
- SCLogWarning(SC_ERR_THREAD_INIT, "Unable to set thread name");
- }
-
- SCLogNotice("rule reload starting");
-
- ThreadVars *tv_local = (ThreadVars *)arg;
-
- /* block usr2. usr2 to be handled by the main thread only */
- UtilSignalBlock(SIGUSR2);
-
- if (tv_local->thread_setup_flags != 0)
- TmThreadSetupOptions(tv_local);
-
- /* release TmThreadSpawn */
- TmThreadsSetFlag(tv_local, THV_INIT_DONE);
-
- ConfDeInit();
- ConfInit();
-
- /* re-load the yaml file */
- if (conf_filename != NULL) {
- if (ConfYamlLoadFile(conf_filename) != 0) {
- /* Error already displayed. */
- exit(EXIT_FAILURE);
- }
-
- ConfNode *file;
- ConfNode *includes = ConfGetNode("include");
- if (includes != NULL) {
- TAILQ_FOREACH(file, &includes->head, next) {
- char *ifile = ConfLoadCompleteIncludePath(file->val);
- SCLogInfo("Live Rule Swap: Including: %s", ifile);
-
- if (ConfYamlLoadFile(ifile) != 0) {
- /* Error already displayed. */
- exit(EXIT_FAILURE);
- }
- }
- }
- } /* if (conf_filename != NULL) */
-
-#if 0
- ConfDump();
-#endif
-
- SCMutexLock(&tv_root_lock);
-
- tv = tv_root[TVT_PPT];
- while (tv) {
- /* obtain the slots for this TV */
- TmSlot *slots = tv->tm_slots;
- while (slots != NULL) {
- TmModule *tm = TmModuleGetById(slots->tm_id);
-
- if (suricata_ctl_flags != 0) {
- TmThreadsSetFlag(tv_local, THV_CLOSED);
-
- SCLogInfo("rule reload interupted by engine shutdown");
-
- UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
- SCMutexUnlock(&tv_root_lock);
- pthread_exit(NULL);
- }
-
- if (!(tm->flags & TM_FLAG_DETECT_TM)) {
- slots = slots->slot_next;
- continue;
- }
- no_of_detect_tvs++;
- break;
- }
-
- tv = tv->next;
- }
-
- if (no_of_detect_tvs == 0) {
- TmThreadsSetFlag(tv_local, THV_CLOSED);
- UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
- SCLogInfo("===== Live rule swap FAILURE =====");
- pthread_exit(NULL);
- }
-
- DetectEngineThreadCtx *old_det_ctx[no_of_detect_tvs];
- DetectEngineThreadCtx *new_det_ctx[no_of_detect_tvs];
- ThreadVars *detect_tvs[no_of_detect_tvs];
- memset(old_det_ctx, 0x00, (no_of_detect_tvs * sizeof(DetectEngineThreadCtx *)));
- memset(new_det_ctx, 0x00, (no_of_detect_tvs * sizeof(DetectEngineThreadCtx *)));
- memset(detect_tvs, 0x00, (no_of_detect_tvs * sizeof(ThreadVars *)));
-
- SCMutexUnlock(&tv_root_lock);
-
- DetectEngineCtx *de_ctx = DetectEngineCtxInit();
- if (de_ctx == NULL) {
- SCLogError(SC_ERR_LIVE_RULE_SWAP, "Allocation failure in live "
- "swap. Let's get out of here.");
- goto error;
- }
-
- if (SigLoadSignatures(de_ctx, NULL, FALSE) < 0) {
- SCLogError(SC_ERR_NO_RULES_LOADED, "Loading signatures failed.");
- if (de_ctx->failure_fatal)
- exit(EXIT_FAILURE);
- DetectEngineCtxFree(de_ctx);
- SCLogError(SC_ERR_LIVE_RULE_SWAP, "Failure encountered while "
- "loading new ruleset with live swap.");
- SCLogError(SC_ERR_LIVE_RULE_SWAP, "rule reload failed");
- TmThreadsSetFlag(tv_local, THV_CLOSED);
- UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
- pthread_exit(NULL);
- }
-
- SCThresholdConfInitContext(de_ctx, NULL);
-
- /* start the process of swapping detect threads ctxs */
-
- SCMutexLock(&tv_root_lock);
-
- /* all receive threads are part of packet processing threads */
- tv = tv_root[TVT_PPT];
- while (tv) {
- /* obtain the slots for this TV */
- TmSlot *slots = tv->tm_slots;
- while (slots != NULL) {
- TmModule *tm = TmModuleGetById(slots->tm_id);
-
- if (suricata_ctl_flags != 0) {
- TmThreadsSetFlag(tv_local, THV_CLOSED);
-
- SCLogInfo("rule reload interupted by engine shutdown");
-
- UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
- SCMutexUnlock(&tv_root_lock);
- pthread_exit(NULL);
- }
-
- if (!(tm->flags & TM_FLAG_DETECT_TM)) {
- slots = slots->slot_next;
- continue;
- }
-
- old_det_ctx[i] = SC_ATOMIC_GET(slots->slot_data);
- detect_tvs[i] = tv;
- TmEcode r = DetectEngineThreadCtxInitForLiveRuleSwap(tv, (void *)de_ctx,
- (void **)&new_det_ctx[i]);
- i++;
- if (r == TM_ECODE_FAILED) {
- SCLogError(SC_ERR_LIVE_RULE_SWAP, "Detect engine thread init "
- "failure in live rule swap. Let's get out of here");
- SCMutexUnlock(&tv_root_lock);
- goto error;
- }
- SCLogDebug("live rule swap created new det_ctx - %p and de_ctx "
- "- %p\n", new_det_ctx, de_ctx);
- break;
- }
-
- tv = tv->next;
- }
-
- i = 0;
- tv = tv_root[TVT_PPT];
- while (tv) {
- TmSlot *slots = tv->tm_slots;
- while (slots != NULL) {
- if (suricata_ctl_flags != 0) {
- TmThreadsSetFlag(tv_local, THV_CLOSED);
-
- SCLogInfo("rule reload interupted by engine shutdown");
-
- UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
- SCMutexUnlock(&tv_root_lock);
- pthread_exit(NULL);
- }
-
- TmModule *tm = TmModuleGetById(slots->tm_id);
- if (!(tm->flags & TM_FLAG_DETECT_TM)) {
- slots = slots->slot_next;
- continue;
- }
- SCLogDebug("swapping new det_ctx - %p with older one - %p",
- new_det_ctx[i], SC_ATOMIC_GET(slots->slot_data));
- (void)SC_ATOMIC_SET(slots->slot_data, new_det_ctx[i++]);
- break;
- }
- tv = tv->next;
- }
-
- SCMutexUnlock(&tv_root_lock);
-
- SCLogInfo("Live rule swap has swapped %d old det_ctx's with new ones, "
- "along with the new de_ctx", no_of_detect_tvs);
-
- for (i = 0; i < no_of_detect_tvs; i++) {
- int break_out = 0;
- int pseudo_pkt_inserted = 0;
- usleep(1000);
- while (SC_ATOMIC_GET(new_det_ctx[i]->so_far_used_by_detect) != 1) {
- if (suricata_ctl_flags != 0) {
- break_out = 1;
- break;
- }
-
- if (pseudo_pkt_inserted == 0) {
- pseudo_pkt_inserted = 1;
- if (detect_tvs[i]->inq != NULL) {
- Packet *p = PacketGetFromAlloc();
- if (p != NULL) {
- p->flags |= PKT_PSEUDO_STREAM_END;
- PacketQueue *q = &trans_q[detect_tvs[i]->inq->id];
- SCMutexLock(&q->mutex_q);
-
- PacketEnqueue(q, p);
- SCCondSignal(&q->cond_q);
- SCMutexUnlock(&q->mutex_q);
- }
- }
- }
- usleep(1000);
- }
- if (break_out)
- break;
- SCLogDebug("new_det_ctx - %p used by detect engine", new_det_ctx[i]);
- }
-
- /* this is to make sure that if someone initiated shutdown during a live
- * rule swap, the live rule swap won't clean up the old det_ctx and
- * de_ctx, till all detect threads have stopped working and sitting
- * silently after setting RUNNING_DONE flag and while waiting for
- * THV_DEINIT flag */
- if (i != no_of_detect_tvs) {
- ThreadVars *tv = tv_root[TVT_PPT];
- while (tv) {
- /* obtain the slots for this TV */
- TmSlot *slots = tv->tm_slots;
- while (slots != NULL) {
- TmModule *tm = TmModuleGetById(slots->tm_id);
-
- if (!(tm->flags & TM_FLAG_DETECT_TM)) {
- slots = slots->slot_next;
- continue;
- }
-
- while (!TmThreadsCheckFlag(tv, THV_RUNNING_DONE)) {
- usleep(100);
- }
-
- slots = slots->slot_next;
- }
-
- tv = tv->next;
- }
- }
-
- /* free all the ctxs */
- old_de_ctx = old_det_ctx[0]->de_ctx;
- for (i = 0; i < no_of_detect_tvs; i++) {
- SCLogDebug("Freeing old_det_ctx - %p used by detect",
- old_det_ctx[i]);
- DetectEngineThreadCtxDeinit(NULL, old_det_ctx[i]);
- }
- DetectEngineCtxFree(old_de_ctx);
-
- SRepReloadComplete();
-
- /* reset the handler */
- UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
-
- TmThreadsSetFlag(tv_local, THV_CLOSED);
-
- SCLogNotice("rule reload complete");
-
- pthread_exit(NULL);
-
- error:
- for (i = 0; i < no_of_detect_tvs; i++) {
- if (new_det_ctx[i] != NULL)
- DetectEngineThreadCtxDeinit(NULL, new_det_ctx[i]);
- }
- DetectEngineCtxFree(de_ctx);
- TmThreadsSetFlag(tv_local, THV_CLOSED);
- UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2);
- SCLogInfo("===== Live rule swap FAILURE =====");
- pthread_exit(NULL);
-}
-
-void DetectEngineSpawnLiveRuleSwapMgmtThread(void)
-{
- SCEnter();
-
- SCLogDebug("Spawning mgmt thread for live rule swap");
-
- ThreadVars *tv = TmThreadCreateMgmtThread("DetectEngineLiveRuleSwap",
- DetectEngineLiveRuleSwap, 0);
- if (tv == NULL) {
- SCLogError(SC_ERR_THREAD_CREATE, "Live rule swap thread spawn failed");
- exit(EXIT_FAILURE);
- }
-
- TmThreadSetCPU(tv, MANAGEMENT_CPU_SET);
-
- if (TmThreadSpawn(tv) != 0) {
- SCLogError(SC_ERR_THREAD_SPAWN, "TmThreadSpawn failed for "
- "DetectEngineLiveRuleSwap");
- exit(EXIT_FAILURE);
- }
-
- SCReturn;
-}
-
static DetectEngineCtx *DetectEngineCtxInitReal(int minimal)
{
DetectEngineCtx *de_ctx;
void SignalHandlerSigusr2Disabled(int sig)
{
SCLogInfo("Live rule reload not enabled in config.");
-
- return;
}
void SignalHandlerSigusr2StartingUp(int sig)
{
SCLogInfo("Live rule reload only possible after engine completely started.");
-
- return;
}
void SignalHandlerSigusr2DelayedDetect(int sig)
void SignalHandlerSigusr2SigFileStartup(int sig)
{
SCLogInfo("Live rule reload not possible if -s or -S option used at runtime.");
-
- return;
-}
-
-void SignalHandlerSigusr2Idle(int sig)
-{
- if (run_mode == RUNMODE_UNKNOWN || run_mode == RUNMODE_UNITTEST) {
- SCLogInfo("Ruleset load signal USR2 triggered for wrong runmode");
- return;
- }
-
- SCLogInfo("Ruleset load in progress. New ruleset load "
- "allowed after current is done");
-
- return;
}
+/**
+ * SIGUSR2 handler. Just set sigusr2_count. The main loop will act on
+ * it.
+ */
void SignalHandlerSigusr2(int sig)
{
-#if 0
- if (run_mode == RUNMODE_UNKNOWN || run_mode == RUNMODE_UNITTEST) {
- SCLogInfo("Ruleset load signal USR2 triggered for wrong runmode");
- return;
- }
-
- if (suricata_ctl_flags != 0) {
- SCLogInfo("Live rule swap no longer possible. Engine in shutdown mode.");
- return;
- }
-
- UtilSignalHandlerSetup(SIGUSR2, SignalHandlerSigusr2Idle);
-
- DetectEngineSpawnLiveRuleSwapMgmtThread();
-
- return;
-#endif
sigusr2_count = 1;
}
SCPrintElapsedTime(&suri);
- if (suri.rule_reload == 1) {
- /* wait if live rule swap is in progress */
- if (UtilSignalIsHandler(SIGUSR2, SignalHandlerSigusr2Idle)) {
- SCLogInfo("Live rule swap in progress. Waiting for it to end "
- "before we shut the engine/threads down");
- while (UtilSignalIsHandler(SIGUSR2, SignalHandlerSigusr2Idle)) {
- /* sleep for 0.5 seconds */
- usleep(500000);
- }
- SCLogInfo("Received notification that live rule swap is done. "
- "Continuing with engine/threads shutdown");
- }
- }
-
/* before TmThreadKillThreads, as otherwise that kills it
* but more slowly */
if (suri.run_mode != RUNMODE_UNIX_SOCKET) {