Annotation of embedaddon/strongswan/src/charon-nm/charon-nm.c, revision 1.1.1.2

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:                        case SIGTERM:
                     98:                        {
1.1.1.2 ! misho      99:                                DBG1(DBG_DMN, "%s received, shutting down",
        !           100:                                         sig == SIGINT ? "SIGINT" : "SIGTERM");
1.1       misho     101:                                charon->bus->alert(charon->bus, ALERT_SHUTDOWN_SIGNAL, sig);
                    102:                                return;
                    103:                        }
                    104:                }
                    105:        }
                    106: }
                    107: 
                    108: #ifndef DISABLE_SIGNAL_HANDLER
                    109: /**
                    110:  * Handle SIGSEGV/SIGILL signals raised by threads
                    111:  */
                    112: static void segv_handler(int signal)
                    113: {
                    114:        backtrace_t *backtrace;
                    115: 
                    116:        DBG1(DBG_DMN, "thread %u received %d", thread_current_id(), signal);
                    117:        backtrace = backtrace_create(2);
                    118:        backtrace->log(backtrace, stderr, TRUE);
                    119:        backtrace->destroy(backtrace);
                    120: 
                    121:        DBG1(DBG_DMN, "killing ourself, received critical signal");
                    122:        abort();
                    123: }
                    124: #endif /* DISABLE_SIGNAL_HANDLER */
                    125: 
                    126: /**
                    127:  * Lookup UID and GID
                    128:  */
                    129: static bool lookup_uid_gid()
                    130: {
                    131:        char *name;
                    132: 
                    133:        name = lib->settings->get_str(lib->settings, "charon-nm.user",
                    134:                                                                  IPSEC_USER);
                    135:        if (name && !lib->caps->resolve_uid(lib->caps, name))
                    136:        {
                    137:                return FALSE;
                    138:        }
                    139:        name = lib->settings->get_str(lib->settings, "charon-nm.group",
                    140:                                                                  IPSEC_GROUP);
                    141:        if (name && !lib->caps->resolve_gid(lib->caps, name))
                    142:        {
                    143:                return FALSE;
                    144:        }
                    145:        return TRUE;
                    146: }
                    147: 
                    148: /**
                    149:  * Main function, starts NetworkManager backend.
                    150:  */
                    151: int main(int argc, char *argv[])
                    152: {
                    153:        struct sigaction action;
                    154:        int status = SS_RC_INITIALIZATION_FAILED;
                    155: 
                    156:        /* logging for library during initialization, as we have no bus yet */
                    157:        dbg = dbg_syslog;
                    158: 
                    159:        /* LD causes a crash probably due to Glib */
                    160:        setenv("LEAK_DETECTIVE_DISABLE", "1", 1);
                    161: 
                    162:        /* initialize library */
                    163:        if (!library_init(NULL, "charon-nm"))
                    164:        {
                    165:                library_deinit();
                    166:                exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
                    167:        }
                    168: 
                    169:        if (lib->integrity &&
                    170:                !lib->integrity->check_file(lib->integrity, "charon-nm", argv[0]))
                    171:        {
                    172:                dbg_syslog(DBG_DMN, 1, "integrity check of charon-nm failed");
                    173:                library_deinit();
                    174:                exit(SS_RC_DAEMON_INTEGRITY);
                    175:        }
                    176: 
                    177:        if (!libcharon_init())
                    178:        {
                    179:                dbg_syslog(DBG_DMN, 1, "initialization failed - aborting charon-nm");
                    180:                goto deinit;
                    181:        }
                    182: 
                    183:        if (!lookup_uid_gid())
                    184:        {
                    185:                dbg_syslog(DBG_DMN, 1, "invalid uid/gid - aborting charon-nm");
                    186:                goto deinit;
                    187:        }
                    188: 
                    189:        /* make sure we log to the DAEMON facility by default */
                    190:        lib->settings->set_int(lib->settings, "charon-nm.syslog.daemon.default",
                    191:                lib->settings->get_int(lib->settings,
                    192:                                                           "charon-nm.syslog.daemon.default", 1));
                    193:        charon->load_loggers(charon);
                    194: 
                    195:        /* default to random ports to avoid conflicts with regular charon */
                    196:        lib->settings->set_default_str(lib->settings, "charon-nm.port", "0");
                    197:        lib->settings->set_default_str(lib->settings, "charon-nm.port_nat_t", "0");
                    198: 
                    199:        DBG1(DBG_DMN, "Starting charon NetworkManager backend (strongSwan "VERSION")");
                    200:        if (lib->integrity)
                    201:        {
                    202:                DBG1(DBG_DMN, "integrity tests enabled:");
                    203:                DBG1(DBG_DMN, "lib    'libstrongswan': passed file and segment integrity tests");
                    204:                DBG1(DBG_DMN, "lib    'libcharon': passed file and segment integrity tests");
                    205:                DBG1(DBG_DMN, "daemon 'charon-nm': passed file integrity test");
                    206:        }
                    207: 
                    208:        /* register NM backend to be loaded with plugins */
                    209:        nm_backend_register();
                    210: 
                    211:        /* initialize daemon */
                    212:        if (!charon->initialize(charon,
                    213:                        lib->settings->get_str(lib->settings, "charon-nm.load", PLUGINS)))
                    214:        {
                    215:                DBG1(DBG_DMN, "initialization failed - aborting charon-nm");
                    216:                goto deinit;
                    217:        }
                    218:        lib->plugins->status(lib->plugins, LEVEL_CTRL);
                    219: 
                    220:        if (!lib->caps->drop(lib->caps))
                    221:        {
                    222:                DBG1(DBG_DMN, "capability dropping failed - aborting charon-nm");
                    223:                goto deinit;
                    224:        }
                    225: 
                    226:        /* add handler for fatal signals,
                    227:         * INT and TERM are handled by sigwaitinfo() in run() */
                    228:        action.sa_flags = 0;
                    229:        sigemptyset(&action.sa_mask);
                    230:        sigaddset(&action.sa_mask, SIGINT);
                    231:        sigaddset(&action.sa_mask, SIGTERM);
                    232: 
                    233:        /* optionally let the external system handle fatal signals */
                    234: #ifndef DISABLE_SIGNAL_HANDLER
                    235:        action.sa_handler = segv_handler;
                    236:        sigaction(SIGSEGV, &action, NULL);
                    237:        sigaction(SIGILL, &action, NULL);
                    238:        sigaction(SIGBUS, &action, NULL);
                    239: #endif /* DISABLE_SIGNAL_HANDLER */
                    240: 
                    241:        action.sa_handler = SIG_IGN;
                    242:        sigaction(SIGPIPE, &action, NULL);
                    243: 
                    244:        pthread_sigmask(SIG_SETMASK, &action.sa_mask, NULL);
                    245: 
                    246:        /* start daemon (i.e. the threads in the thread-pool) */
                    247:        charon->start(charon);
                    248: 
                    249:        /* main thread goes to run loop */
                    250:        run();
                    251: 
                    252:        status = 0;
                    253: 
                    254: deinit:
                    255:        libcharon_deinit();
                    256:        library_deinit();
                    257:        return status;
                    258: }
                    259: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>