Example #1
0
/** Daemon main run loop. */
int daemon_main (int argc, const char *argv[]) {
    const char *buf;
    size_t sz;

    if (strcmp (APP.logpath, "@syslog") == 0) {
        log_open_syslog ("opticon-agent", APP.loglevel);
    }
    else {
        log_open_file (APP.logpath, APP.loglevel);
    }
    
    probelist_start (&APP.probes);
    APP.resender = authresender_create (APP.transport);
    
    time_t tlast = time (NULL);
    time_t nextslow = tlast + 5;
    time_t nextsend = tlast + 10;
    time_t lastkeyrotate = 0;
    int slowround = 0;

    log_info ("Daemonized");
    while (1) {
        time_t tnow = tlast = time (NULL);
        
        slowround = 0;
        
        /* If a slow round is due at this time, use the excuse to send an
           authentication packet */
        if (nextslow <= tnow) {
            slowround = 1;
            uint32_t sid = APP.auth.sessionid;
            if (! sid) sid = gen_sessionid();
            log_debug ("Authenticating session <%08x>", sid);
            APP.auth.sessionid = sid;
            APP.auth.serial = 0;
            APP.auth.tenantid = APP.tenantid;
            APP.auth.hostid = APP.hostid;
            
            /* Only rotate the AES key every half hour */
            if (tnow - lastkeyrotate > 1800) {
                APP.auth.sessionkey = aeskey_create();
                lastkeyrotate = tnow;
            }
            APP.auth.tenantkey = APP.collectorkey;
            
            /* Dispatch */
            ioport *io_authpkt = ioport_wrap_authdata (&APP.auth,
                                                       gen_serial());
            
            sz = ioport_read_available (io_authpkt);
            buf = ioport_get_buffer (io_authpkt);
            outtransport_send (APP.transport, (void*) buf, sz);
            authresender_schedule (APP.resender, buf, sz);
            ioport_close (io_authpkt);
            
            /* Schedule next slow round */
            nextslow = nextslow + 300;
        }
        
        log_debug ("Poking probes");

        probe *p = APP.probes.first;
        time_t wakenext = tnow + 300;

        /* Go over the probes to figure out whether we should kick them */        
        while (p) {
            time_t firewhen = p->lastpulse + p->interval;
            if (firewhen <= tnow) {
                conditional_signal (&p->pulse);
                p->lastpulse = tnow;
            }
            
            /* Figure out whether the next event for this probe is sooner
               than the next wake-up time we determined so far */
            if (p->lastpulse + p->interval < wakenext) {
                wakenext = p->lastpulse + p->interval;
            }
            
            p = p->next;
        }
        
        int collected = 0;
        int ncollected = 0;
        host *h = host_alloc();
        var *vnagios = var_alloc();
        var *vchkwarn = var_get_array_forkey (vnagios, "chkwarn");
        var *vchkalert = var_get_array_forkey (vnagios, "chkalert");
        
        /* If we're in a slow round, we already know we're scheduled. Otherwise,
           see if the next scheduled moment for sending a (fast lane) packet
           has passed. */
        if (slowround || (tnow >= nextsend)) {
            h->uuid = APP.hostid;
            host_begin_update (h, time (NULL));

            if (! slowround) while (nextsend <= tnow) nextsend += 60;
            log_debug ("Collecting probes");
        
            /* Go over the probes again, picking up the ones relevant to the
               current round being performed */
            p = APP.probes.first;
            while (p) {
                pthread_mutex_lock (&p->vlock);
                volatile var *v = p->vcurrent;
                /* See if data for this probe has been collected since the last kick */
                if (v && (p->lastdispatch <= p->lastreply)) {
                    /* Filter probes for the current lane */
                    if ((slowround && p->interval>60) ||
                        ((!slowround) && p->interval<61)) {
                        log_debug ("Collecting <%s>", p->call);
                        
                        if (p->type == PROBE_NAGIOS) {
                            /* Check for alert/warning state and
                             * summarize before adding to host struct */
                             int pstatus = var_get_int_forkey ((var*)v, "status");
                             if (pstatus) {
                                 var *arr;
                                 switch (pstatus) {
                                    case 1:
                                        var_add_str (vchkwarn, p->id);
                                        break;
                                    
                                    default:
                                        var_add_str (vchkalert, p->id);
                                        break;
                                }
                                collected++;
                            }
                            ncollected++;
                        }
                        else {
                            host_import (h, (var *) v);
                            collected++;
                        }
                        p->lastdispatch = tnow;
                    }
                }
                else {
                    if (tnow - p->lastreply > (2*(p->interval))) {
                        log_warn ("Probe <%s> seems stuck after %i seconds",
                                  p->call, tnow - p->lastreply);
                    }
                }
                pthread_mutex_unlock (&p->vlock);
                p = p->next;
            }
        }
        
        /* Add the chk tree with nagios self-checks to the data */
        if (ncollected) host_import (h, vnagios);
         
        /* If any data was collected, encode it */
        if (collected) {
            log_debug ("Encoding probes");
        
            ioport *encoded = ioport_create_buffer (NULL, 4096);
            if (! encoded) {
                log_warn ("Error creating ioport");
                ioport_close (encoded);
                host_delete (h);
                continue;
            }
        
            if (! codec_encode_host (APP.codec, encoded, h)) {
                log_warn ("Error encoding host");
                ioport_close (encoded);
                host_delete (h);
                continue;
            }

            if (APP.dumppath) {
                FILE *pktf = fopen (APP.dumppath,"a");
                fprintf (pktf, "\n--- %s ---\n\n", slowround?"Slow":"Fast");
                ioport *dump = ioport_create_filewriter (pktf);
                log_debug ("dump %llx", dump);
                codec *jsonc = codec_create_json();
                log_debug ("jsonc %llx", jsonc);
                codec_encode_host (jsonc, dump, h);
                codec_release (jsonc);
                ioport_close (dump);
                fclose (pktf);
            }
        
            log_debug ("Encoded %i bytes", ioport_read_available (encoded));

            ioport *wrapped = ioport_wrap_meterdata (APP.auth.sessionid,
                                                     gen_serial(),
                                                     APP.auth.sessionkey,
                                                     encoded);
        
        
            if (! wrapped) {
                log_error ("Error wrapping");
                ioport_close (encoded);
                host_delete (h);
                continue;
            }
        
            sz = ioport_read_available (wrapped);
            buf = ioport_get_buffer (wrapped);
        
            /* Send it off into space */
            outtransport_send (APP.transport, (void*) buf, sz);
            log_info ("%s lane packet sent: %i bytes", 
                      slowround ? "Slow":"Fast", sz);

            ioport_close (wrapped);
            ioport_close (encoded);
        }
        
        /* Done with the host object */
        host_delete (h);

        /* Figure out what the next scheduled wake-up time is */
        tnow = time (NULL);
        if (nextsend < wakenext) wakenext = nextsend;
        if (nextslow < wakenext) wakenext = nextslow;
        if (wakenext > tnow) {
            log_debug ("Sleeping for %i seconds", (wakenext-tnow));
            sleep (wakenext-tnow);
        }
    }
    return 666;
}
Example #2
0
static int log_open_journal(void) {

        static const union sockaddr_union sa = {
                .un.sun_family = AF_UNIX,
                .un.sun_path = "/run/systemd/journal/socket",
        };

        int r;

        if (journal_fd >= 0)
                return 0;

        journal_fd = create_log_socket(SOCK_DGRAM);
        if (journal_fd < 0) {
                r = journal_fd;
                goto fail;
        }

        if (connect(journal_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0) {
                r = -errno;
                goto fail;
        }

        return 0;

fail:
        log_close_journal();
        return r;
}

int log_open(void) {
        int r;

        /* If we don't use the console we close it here, to not get
         * killed by SAK. If we don't use syslog we close it here so
         * that we are not confused by somebody deleting the socket in
         * the fs. If we don't use /dev/kmsg we still keep it open,
         * because there is no reason to close it. */

        if (log_target == LOG_TARGET_NULL) {
                log_close_journal();
                log_close_syslog();
                log_close_console();
                return 0;
        }

        if ((log_target != LOG_TARGET_AUTO && log_target != LOG_TARGET_SAFE) ||
            getpid() == 1 ||
            isatty(STDERR_FILENO) <= 0) {

                if (log_target == LOG_TARGET_AUTO ||
                    log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
                    log_target == LOG_TARGET_JOURNAL) {
                        r = log_open_journal();
                        if (r >= 0) {
                                log_close_syslog();
                                log_close_console();
                                return r;
                        }
                }

                if (log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
                    log_target == LOG_TARGET_SYSLOG) {
                        r = log_open_syslog();
                        if (r >= 0) {
                                log_close_journal();
                                log_close_console();
                                return r;
                        }
                }

                if (log_target == LOG_TARGET_AUTO ||
                    log_target == LOG_TARGET_SAFE ||
                    log_target == LOG_TARGET_JOURNAL_OR_KMSG ||
                    log_target == LOG_TARGET_SYSLOG_OR_KMSG ||
                    log_target == LOG_TARGET_KMSG) {
                        r = log_open_kmsg();
                        if (r >= 0) {
                                log_close_journal();
                                log_close_syslog();
                                log_close_console();
                                return r;
                        }
                }
        }

        log_close_journal();
        log_close_syslog();

        return log_open_console();
}
Example #3
0
int
main (int argc, char *argv[])
{
    int   fd = -1;
    char *log_identity = argv[0];
    int   log_priority = LOG_INFO;
    int   log_options = LOG_OPT_PRIORITY;

#ifndef NDEBUG
    log_priority = LOG_DEBUG;
    log_options |= LOG_OPT_TIMESTAMP;
#endif /* NDEBUG */
    log_open_file (stderr, log_identity, log_priority, log_options);

    disable_core_dumps ();
    conf = create_conf ();
    parse_cmdline (conf, argc, argv);
    auth_recv_init (conf->auth_server_dir, conf->auth_client_dir,
        conf->got_force);

    if (!conf->got_foreground) {
        fd = daemonize_init (argv[0]);
        if (conf->got_syslog) {
            log_open_file (NULL, NULL, 0, 0);
            log_open_syslog (log_identity, LOG_DAEMON);
        }
        else {
            open_logfile (conf->logfile_name, log_priority, conf->got_force);
        }
    }
    handle_signals ();
    lookup_ip_addr (conf);
    write_pidfile (conf->pidfile_name, conf->got_force);
    if (conf->got_mlockall) {
        lock_memory ();
    }
    crypto_init ();
    if (random_init (conf->seed_name) < 0) {
        if (conf->seed_name) {
            free (conf->seed_name);
            conf->seed_name = NULL;
        }
    }
    create_subkeys (conf);
    conf->gids = gids_create (conf->gids_update_secs, conf->got_group_stat);
    replay_init ();
    timer_init ();
    sock_create (conf);

    if (!conf->got_foreground) {
        daemonize_fini (fd);
    }
    log_msg (LOG_NOTICE, "Starting %s daemon (pid %d)",
        META_ALIAS, (int) getpid ());

    job_accept (conf);

    sock_destroy (conf);
    timer_fini ();
    replay_fini ();
    gids_destroy (conf->gids);
    random_fini (conf->seed_name);
    crypto_fini ();
    destroy_conf (conf);

    log_msg (LOG_NOTICE, "Stopping %s daemon (pid %d)",
        META_ALIAS, (int) getpid ());

    exit (EMUNGE_SUCCESS);
}