Annotation of embedaddon/strongswan/src/charon-systemd/charon-systemd.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2006-2018 Tobias Brunner
! 3: * Copyright (C) 2005-2014 Martin Willi
! 4: * Copyright (C) 2006 Daniel Roethlisberger
! 5: * Copyright (C) 2005 Jan Hutter
! 6: * HSR Hochschule fuer Technik Rapperswil
! 7: * Copyright (C) 2014 revosec AG
! 8: *
! 9: * This program is free software; you can redistribute it and/or modify it
! 10: * under the terms of the GNU General Public License as published by the
! 11: * Free Software Foundation; either version 2 of the License, or (at your
! 12: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 13: *
! 14: * This program is distributed in the hope that it will be useful, but
! 15: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 16: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 17: * for more details.
! 18: */
! 19:
! 20: #include <signal.h>
! 21: #include <stdio.h>
! 22: #include <pthread.h>
! 23: #include <sys/stat.h>
! 24: #include <sys/types.h>
! 25: #include <sys/utsname.h>
! 26: #include <unistd.h>
! 27: #include <errno.h>
! 28:
! 29: /* won't make sense from our logging hook */
! 30: #define SD_JOURNAL_SUPPRESS_LOCATION
! 31: #include <systemd/sd-daemon.h>
! 32: #include <systemd/sd-journal.h>
! 33:
! 34: #include <daemon.h>
! 35:
! 36: #include <library.h>
! 37: #include <utils/backtrace.h>
! 38: #include <threading/thread.h>
! 39: #include <threading/rwlock.h>
! 40:
! 41: /**
! 42: * Default user and group
! 43: */
! 44: #ifndef IPSEC_USER
! 45: #define IPSEC_USER NULL
! 46: #endif
! 47:
! 48: #ifndef IPSEC_GROUP
! 49: #define IPSEC_GROUP NULL
! 50: #endif
! 51:
! 52: /**
! 53: * hook in library for debugging messages
! 54: */
! 55: extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
! 56:
! 57: /**
! 58: * Logging hook for library logs, using stderr output
! 59: */
! 60: static void dbg_stderr(debug_t group, level_t level, char *fmt, ...)
! 61: {
! 62: va_list args;
! 63:
! 64: if (level <= 1)
! 65: {
! 66: va_start(args, fmt);
! 67: fprintf(stderr, "00[%N] ", debug_names, group);
! 68: vfprintf(stderr, fmt, args);
! 69: fprintf(stderr, "\n");
! 70: va_end(args);
! 71: }
! 72: }
! 73:
! 74: typedef struct journal_logger_t journal_logger_t;
! 75:
! 76: /**
! 77: * Logger implementation using systemd-journal
! 78: */
! 79: struct journal_logger_t {
! 80:
! 81: /**
! 82: * Public interface
! 83: */
! 84: custom_logger_t public;
! 85:
! 86: /**
! 87: * Configured loglevels
! 88: */
! 89: level_t levels[DBG_MAX];
! 90:
! 91: /**
! 92: * Lock for levels
! 93: */
! 94: rwlock_t *lock;
! 95: };
! 96:
! 97: METHOD(logger_t, vlog, void,
! 98: journal_logger_t *this, debug_t group, level_t level, int thread,
! 99: ike_sa_t *ike_sa, const char *fmt, va_list args)
! 100: {
! 101: char buf[4096], *msg = buf;
! 102: ssize_t len;
! 103: va_list copy;
! 104:
! 105: va_copy(copy, args);
! 106: len = vsnprintf(msg, sizeof(buf), fmt, copy);
! 107: va_end(copy);
! 108:
! 109: if (len >= sizeof(buf))
! 110: {
! 111: len++;
! 112: msg = malloc(len);
! 113: va_copy(copy, args);
! 114: len = vsnprintf(msg, len, fmt, copy);
! 115: va_end(copy);
! 116: }
! 117: if (len > 0)
! 118: {
! 119: char unique[64] = "", name[256] = "";
! 120: int priority;
! 121:
! 122: if (ike_sa)
! 123: {
! 124: snprintf(unique, sizeof(unique), "IKE_SA_UNIQUE_ID=%u",
! 125: ike_sa->get_unique_id(ike_sa));
! 126: if (ike_sa->get_peer_cfg(ike_sa))
! 127: {
! 128: snprintf(name, sizeof(name), "IKE_SA_NAME=%s",
! 129: ike_sa->get_name(ike_sa));
! 130: }
! 131: }
! 132: switch (level)
! 133: {
! 134: case LEVEL_AUDIT:
! 135: priority = LOG_NOTICE;
! 136: break;
! 137: case LEVEL_CTRL:
! 138: priority = LOG_INFO;
! 139: break;
! 140: default:
! 141: priority = LOG_DEBUG;
! 142: break;
! 143: }
! 144: sd_journal_send(
! 145: "MESSAGE=%s", msg,
! 146: "MESSAGE_ID=57d2708c-d607-43bd-8c39-66bf%.8x",
! 147: chunk_hash_static(chunk_from_str((char*)fmt)),
! 148: "PRIORITY=%d", priority,
! 149: "GROUP=%N", debug_names, group,
! 150: "LEVEL=%d", level,
! 151: "THREAD=%d", thread,
! 152: unique[0] ? unique : NULL,
! 153: name[0] ? name : NULL,
! 154: NULL);
! 155: }
! 156: if (msg != buf)
! 157: {
! 158: free(msg);
! 159: }
! 160: }
! 161:
! 162: METHOD(logger_t, get_level, level_t,
! 163: journal_logger_t *this, debug_t group)
! 164: {
! 165: level_t level;
! 166:
! 167: this->lock->read_lock(this->lock);
! 168: level = this->levels[group];
! 169: this->lock->unlock(this->lock);
! 170:
! 171: return level;
! 172: }
! 173:
! 174: METHOD(custom_logger_t, set_level, void,
! 175: journal_logger_t *this, debug_t group, level_t level)
! 176: {
! 177: this->lock->write_lock(this->lock);
! 178: this->levels[group] = level;
! 179: this->lock->unlock(this->lock);
! 180: }
! 181:
! 182: METHOD(custom_logger_t, logger_destroy, void,
! 183: journal_logger_t *this)
! 184: {
! 185: this->lock->destroy(this->lock);
! 186: free(this);
! 187: }
! 188:
! 189: static custom_logger_t *journal_logger_create(const char *name)
! 190: {
! 191: journal_logger_t *this;
! 192:
! 193: INIT(this,
! 194: .public = {
! 195: .logger = {
! 196: .vlog = _vlog,
! 197: .get_level = _get_level,
! 198: },
! 199: .set_level = _set_level,
! 200: .destroy = _logger_destroy,
! 201: },
! 202: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
! 203: );
! 204: return &this->public;
! 205: }
! 206:
! 207: /**
! 208: * Run the daemon and handle unix signals
! 209: */
! 210: static int run()
! 211: {
! 212: sigset_t set;
! 213:
! 214: sigemptyset(&set);
! 215: sigaddset(&set, SIGHUP);
! 216: sigaddset(&set, SIGTERM);
! 217: sigprocmask(SIG_BLOCK, &set, NULL);
! 218:
! 219: sd_notify(0, "READY=1\n");
! 220:
! 221: while (TRUE)
! 222: {
! 223: int sig;
! 224:
! 225: sig = sigwaitinfo(&set, NULL);
! 226: if (sig == -1)
! 227: {
! 228: if (errno == EINTR)
! 229: { /* ignore signals we didn't wait for */
! 230: continue;
! 231: }
! 232: DBG1(DBG_DMN, "waiting for signal failed: %s", strerror(errno));
! 233: return SS_RC_INITIALIZATION_FAILED;
! 234: }
! 235: switch (sig)
! 236: {
! 237: case SIGHUP:
! 238: {
! 239: DBG1(DBG_DMN, "signal of type SIGHUP received. Reloading "
! 240: "configuration");
! 241: if (lib->settings->load_files(lib->settings, lib->conf, FALSE))
! 242: {
! 243: charon->load_loggers(charon);
! 244: lib->plugins->reload(lib->plugins, NULL);
! 245: }
! 246: else
! 247: {
! 248: DBG1(DBG_DMN, "reloading config failed, keeping old");
! 249: }
! 250: break;
! 251: }
! 252: case SIGTERM:
! 253: {
! 254: DBG1(DBG_DMN, "SIGTERM received, shutting down");
! 255: charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
! 256: return 0;
! 257: }
! 258: }
! 259: }
! 260: }
! 261:
! 262: /**
! 263: * lookup UID and GID
! 264: */
! 265: static bool lookup_uid_gid()
! 266: {
! 267: char *name;
! 268:
! 269: name = lib->settings->get_str(lib->settings, "%s.user", IPSEC_USER,
! 270: lib->ns);
! 271: if (name && !lib->caps->resolve_uid(lib->caps, name))
! 272: {
! 273: return FALSE;
! 274: }
! 275: name = lib->settings->get_str(lib->settings, "%s.group", IPSEC_GROUP,
! 276: lib->ns);
! 277: if (name && !lib->caps->resolve_gid(lib->caps, name))
! 278: {
! 279: return FALSE;
! 280: }
! 281: return TRUE;
! 282: }
! 283:
! 284: #ifndef DISABLE_SIGNAL_HANDLER
! 285: /**
! 286: * Handle SIGSEGV/SIGILL signals raised by threads
! 287: */
! 288: static void segv_handler(int signal)
! 289: {
! 290: backtrace_t *backtrace;
! 291:
! 292: DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal);
! 293: backtrace = backtrace_create(2);
! 294: backtrace->log(backtrace, NULL, TRUE);
! 295: backtrace->log(backtrace, stderr, TRUE);
! 296: backtrace->destroy(backtrace);
! 297:
! 298: DBG1(DBG_DMN, "killing ourself, received critical signal");
! 299: abort();
! 300: }
! 301: #endif /* DISABLE_SIGNAL_HANDLER */
! 302:
! 303: /**
! 304: * Add namespace alias
! 305: */
! 306: static void __attribute__ ((constructor))register_namespace()
! 307: {
! 308: /* inherit settings from charon */
! 309: library_add_namespace("charon");
! 310: }
! 311:
! 312: /**
! 313: * Register journal logger
! 314: */
! 315: static void __attribute__ ((constructor))register_logger()
! 316: {
! 317: register_custom_logger("journal", journal_logger_create);
! 318: }
! 319:
! 320: /**
! 321: * Main function, starts the daemon.
! 322: */
! 323: int main(int argc, char *argv[])
! 324: {
! 325: struct sigaction action;
! 326: struct utsname utsname;
! 327: int status = SS_RC_INITIALIZATION_FAILED;
! 328:
! 329: dbg = dbg_stderr;
! 330:
! 331: if (uname(&utsname) != 0)
! 332: {
! 333: memset(&utsname, 0, sizeof(utsname));
! 334: }
! 335:
! 336: sd_notifyf(0, "STATUS=Starting charon-systemd, strongSwan %s, %s %s, %s",
! 337: VERSION, utsname.sysname, utsname.release, utsname.machine);
! 338:
! 339: atexit(library_deinit);
! 340: if (!library_init(NULL, "charon-systemd"))
! 341: {
! 342: sd_notifyf(0, "STATUS=libstrongswan initialization failed");
! 343: return SS_RC_INITIALIZATION_FAILED;
! 344: }
! 345: if (lib->integrity &&
! 346: !lib->integrity->check_file(lib->integrity, "charon-systemd", argv[0]))
! 347: {
! 348: sd_notifyf(0, "STATUS=integrity check of charon-systemd failed");
! 349: return SS_RC_INITIALIZATION_FAILED;
! 350: }
! 351: if (!libcharon_init())
! 352: {
! 353: sd_notifyf(0, "STATUS=libcharon initialization failed");
! 354: goto error;
! 355: }
! 356: if (!lookup_uid_gid())
! 357: {
! 358: sd_notifyf(0, "STATUS=unknown uid/gid");
! 359: goto error;
! 360: }
! 361: /* we registered the journal logger as custom logger, which gets its
! 362: * settings from <ns>.customlog.journal, let it fallback to <ns>.journal */
! 363: lib->settings->add_fallback(lib->settings, "%s.customlog.journal",
! 364: "%s.journal", lib->ns);
! 365: /* load the journal logger by default */
! 366: lib->settings->set_default_str(lib->settings, "%s.journal.default", "1",
! 367: lib->ns);
! 368:
! 369: charon->load_loggers(charon);
! 370:
! 371: if (!charon->initialize(charon,
! 372: lib->settings->get_str(lib->settings, "%s.load", PLUGINS, lib->ns)))
! 373: {
! 374: sd_notifyf(0, "STATUS=charon initialization failed");
! 375: goto error;
! 376: }
! 377: lib->plugins->status(lib->plugins, LEVEL_CTRL);
! 378:
! 379: if (!lib->caps->drop(lib->caps))
! 380: {
! 381: sd_notifyf(0, "STATUS=dropping capabilities failed");
! 382: goto error;
! 383: }
! 384:
! 385: /* add handler for fatal signals,
! 386: * INT, TERM and HUP are handled by sigwaitinfo() in run() */
! 387: action.sa_flags = 0;
! 388: sigemptyset(&action.sa_mask);
! 389: sigaddset(&action.sa_mask, SIGINT);
! 390: sigaddset(&action.sa_mask, SIGTERM);
! 391: sigaddset(&action.sa_mask, SIGHUP);
! 392:
! 393: /* optionally let the external system handle fatal signals */
! 394: #ifndef DISABLE_SIGNAL_HANDLER
! 395: action.sa_handler = segv_handler;
! 396: sigaction(SIGSEGV, &action, NULL);
! 397: sigaction(SIGILL, &action, NULL);
! 398: sigaction(SIGBUS, &action, NULL);
! 399: #endif /* DISABLE_SIGNAL_HANDLER */
! 400:
! 401: action.sa_handler = SIG_IGN;
! 402: sigaction(SIGPIPE, &action, NULL);
! 403:
! 404: pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
! 405:
! 406: charon->start(charon);
! 407:
! 408: sd_notifyf(0, "STATUS=charon-systemd running, strongSwan %s, %s %s, %s",
! 409: VERSION, utsname.sysname, utsname.release, utsname.machine);
! 410:
! 411: status = run();
! 412:
! 413: error:
! 414: libcharon_deinit();
! 415: return status;
! 416: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>