Return to charon-nm.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / charon-nm |
1.1 ! misho 1: /* ! 2: * Copyright (C) 2012 Tobias Brunner ! 3: * HSR Hochschule fuer Technik Rapperswil ! 4: * ! 5: * This program is free software; you can redistribute it and/or modify it ! 6: * under the terms of the GNU General Public License as published by the ! 7: * Free Software Foundation; either version 2 of the License, or (at your ! 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. ! 9: * ! 10: * This program is distributed in the hope that it will be useful, but ! 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY ! 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ! 13: * for more details. ! 14: */ ! 15: ! 16: #include <stdio.h> ! 17: #include <syslog.h> ! 18: #include <signal.h> ! 19: #include <sys/types.h> ! 20: #include <unistd.h> ! 21: #include <errno.h> ! 22: ! 23: #include <daemon.h> ! 24: ! 25: #include <library.h> ! 26: #include <utils/backtrace.h> ! 27: #include <threading/thread.h> ! 28: ! 29: #include <nm/nm_backend.h> ! 30: ! 31: /** ! 32: * Default user and group ! 33: */ ! 34: #ifndef IPSEC_USER ! 35: #define IPSEC_USER NULL ! 36: #endif ! 37: ! 38: #ifndef IPSEC_GROUP ! 39: #define IPSEC_GROUP NULL ! 40: #endif ! 41: ! 42: /** ! 43: * Hook in library for debugging messages ! 44: */ ! 45: extern void (*dbg) (debug_t group, level_t level, char *fmt, ...); ! 46: ! 47: /** ! 48: * Simple logging hook for library logs, using syslog output ! 49: */ ! 50: static void dbg_syslog(debug_t group, level_t level, char *fmt, ...) ! 51: { ! 52: if (level <= 1) ! 53: { ! 54: char buffer[8192], groupstr[4]; ! 55: va_list args; ! 56: ! 57: va_start(args, fmt); ! 58: /* write in memory buffer first */ ! 59: vsnprintf(buffer, sizeof(buffer), fmt, args); ! 60: /* cache group name */ ! 61: snprintf(groupstr, sizeof(groupstr), "%N", debug_names, group); ! 62: syslog(LOG_DAEMON|LOG_INFO, "00[%s] %s", groupstr, buffer); ! 63: va_end(args); ! 64: } ! 65: } ! 66: ! 67: /** ! 68: * Run the daemon and handle unix signals ! 69: */ ! 70: static void run() ! 71: { ! 72: sigset_t set; ! 73: ! 74: /* handle SIGINT and SIGTERM in this handler */ ! 75: sigemptyset(&set); ! 76: sigaddset(&set, SIGINT); ! 77: sigaddset(&set, SIGTERM); ! 78: sigprocmask(SIG_BLOCK, &set, NULL); ! 79: ! 80: while (TRUE) ! 81: { ! 82: int sig; ! 83: ! 84: sig = sigwaitinfo(&set, NULL); ! 85: if (sig == -1) ! 86: { ! 87: if (errno == EINTR) ! 88: { /* ignore signals we didn't wait for */ ! 89: continue; ! 90: } ! 91: DBG1(DBG_DMN, "waiting for signal failed: %s", strerror(errno)); ! 92: return; ! 93: } ! 94: switch (sig) ! 95: { ! 96: case SIGINT: ! 97: { ! 98: DBG1(DBG_DMN, "signal of type SIGINT received. Shutting down"); ! 99: charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig); ! 100: return; ! 101: } ! 102: case SIGTERM: ! 103: { ! 104: DBG1(DBG_DMN, "signal of type SIGTERM received. Shutting down"); ! 105: charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig); ! 106: return; ! 107: } ! 108: } ! 109: } ! 110: } ! 111: ! 112: #ifndef DISABLE_SIGNAL_HANDLER ! 113: /** ! 114: * Handle SIGSEGV/SIGILL signals raised by threads ! 115: */ ! 116: static void segv_handler(int signal) ! 117: { ! 118: backtrace_t *backtrace; ! 119: ! 120: DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal); ! 121: backtrace = backtrace_create(2); ! 122: backtrace->log(backtrace, stderr, TRUE); ! 123: backtrace->destroy(backtrace); ! 124: ! 125: DBG1(DBG_DMN, "killing ourself, received critical signal"); ! 126: abort(); ! 127: } ! 128: #endif /* DISABLE_SIGNAL_HANDLER */ ! 129: ! 130: /** ! 131: * Lookup UID and GID ! 132: */ ! 133: static bool lookup_uid_gid() ! 134: { ! 135: char *name; ! 136: ! 137: name = lib->settings->get_str(lib->settings, "charon-nm.user", ! 138: IPSEC_USER); ! 139: if (name && !lib->caps->resolve_uid(lib->caps, name)) ! 140: { ! 141: return FALSE; ! 142: } ! 143: name = lib->settings->get_str(lib->settings, "charon-nm.group", ! 144: IPSEC_GROUP); ! 145: if (name && !lib->caps->resolve_gid(lib->caps, name)) ! 146: { ! 147: return FALSE; ! 148: } ! 149: return TRUE; ! 150: } ! 151: ! 152: /** ! 153: * Main function, starts NetworkManager backend. ! 154: */ ! 155: int main(int argc, char *argv[]) ! 156: { ! 157: struct sigaction action; ! 158: int status = SS_RC_INITIALIZATION_FAILED; ! 159: ! 160: /* logging for library during initialization, as we have no bus yet */ ! 161: dbg = dbg_syslog; ! 162: ! 163: /* LD causes a crash probably due to Glib */ ! 164: setenv("LEAK_DETECTIVE_DISABLE", "1", 1); ! 165: ! 166: /* initialize library */ ! 167: if (!library_init(NULL, "charon-nm")) ! 168: { ! 169: library_deinit(); ! 170: exit(SS_RC_LIBSTRONGSWAN_INTEGRITY); ! 171: } ! 172: ! 173: if (lib->integrity && ! 174: !lib->integrity->check_file(lib->integrity, "charon-nm", argv[0])) ! 175: { ! 176: dbg_syslog(DBG_DMN, 1, "integrity check of charon-nm failed"); ! 177: library_deinit(); ! 178: exit(SS_RC_DAEMON_INTEGRITY); ! 179: } ! 180: ! 181: if (!libcharon_init()) ! 182: { ! 183: dbg_syslog(DBG_DMN, 1, "initialization failed - aborting charon-nm"); ! 184: goto deinit; ! 185: } ! 186: ! 187: if (!lookup_uid_gid()) ! 188: { ! 189: dbg_syslog(DBG_DMN, 1, "invalid uid/gid - aborting charon-nm"); ! 190: goto deinit; ! 191: } ! 192: ! 193: /* make sure we log to the DAEMON facility by default */ ! 194: lib->settings->set_int(lib->settings, "charon-nm.syslog.daemon.default", ! 195: lib->settings->get_int(lib->settings, ! 196: "charon-nm.syslog.daemon.default", 1)); ! 197: charon->load_loggers(charon); ! 198: ! 199: /* default to random ports to avoid conflicts with regular charon */ ! 200: lib->settings->set_default_str(lib->settings, "charon-nm.port", "0"); ! 201: lib->settings->set_default_str(lib->settings, "charon-nm.port_nat_t", "0"); ! 202: ! 203: DBG1(DBG_DMN, "Starting charon NetworkManager backend (strongSwan "VERSION")"); ! 204: if (lib->integrity) ! 205: { ! 206: DBG1(DBG_DMN, "integrity tests enabled:"); ! 207: DBG1(DBG_DMN, "lib 'libstrongswan': passed file and segment integrity tests"); ! 208: DBG1(DBG_DMN, "lib 'libcharon': passed file and segment integrity tests"); ! 209: DBG1(DBG_DMN, "daemon 'charon-nm': passed file integrity test"); ! 210: } ! 211: ! 212: /* register NM backend to be loaded with plugins */ ! 213: nm_backend_register(); ! 214: ! 215: /* initialize daemon */ ! 216: if (!charon->initialize(charon, ! 217: lib->settings->get_str(lib->settings, "charon-nm.load", PLUGINS))) ! 218: { ! 219: DBG1(DBG_DMN, "initialization failed - aborting charon-nm"); ! 220: goto deinit; ! 221: } ! 222: lib->plugins->status(lib->plugins, LEVEL_CTRL); ! 223: ! 224: if (!lib->caps->drop(lib->caps)) ! 225: { ! 226: DBG1(DBG_DMN, "capability dropping failed - aborting charon-nm"); ! 227: goto deinit; ! 228: } ! 229: ! 230: /* add handler for fatal signals, ! 231: * INT and TERM are handled by sigwaitinfo() in run() */ ! 232: action.sa_flags = 0; ! 233: sigemptyset(&action.sa_mask); ! 234: sigaddset(&action.sa_mask, SIGINT); ! 235: sigaddset(&action.sa_mask, SIGTERM); ! 236: ! 237: /* optionally let the external system handle fatal signals */ ! 238: #ifndef DISABLE_SIGNAL_HANDLER ! 239: action.sa_handler = segv_handler; ! 240: sigaction(SIGSEGV, &action, NULL); ! 241: sigaction(SIGILL, &action, NULL); ! 242: sigaction(SIGBUS, &action, NULL); ! 243: #endif /* DISABLE_SIGNAL_HANDLER */ ! 244: ! 245: action.sa_handler = SIG_IGN; ! 246: sigaction(SIGPIPE, &action, NULL); ! 247: ! 248: pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL); ! 249: ! 250: /* start daemon (i.e. the threads in the thread-pool) */ ! 251: charon->start(charon); ! 252: ! 253: /* main thread goes to run loop */ ! 254: run(); ! 255: ! 256: status = 0; ! 257: ! 258: deinit: ! 259: libcharon_deinit(); ! 260: library_deinit(); ! 261: return status; ! 262: } ! 263: