Annotation of embedaddon/ipguard/system.c, revision 1.1

1.1     ! misho       1: /*  system.c
        !             2:  *
        !             3:  * Copyright (c) 2010 SeaD <sead at deep.perm.ru>
        !             4:  *
        !             5:  * Redistribution and use in source and binary forms, with or without
        !             6:  * modification, are permitted provided that the following conditions
        !             7:  * are met:
        !             8:  * 1. Redistributions of source code must retain the above copyright
        !             9:  *    notice, this list of conditions and the following disclaimer.
        !            10:  * 2. Redistributions in binary form must reproduce the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer in the
        !            12:  *    documentation and/or other materials provided with the distribution.
        !            13:  *
        !            14:  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
        !            15:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            16:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            17:  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
        !            18:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            19:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            20:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            21:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            22:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            23:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            24:  * SUCH DAMAGE.
        !            25:  *
        !            26:  *  $Id: system.c,v 1.15 2010/07/12 03:46:36 sead Exp $
        !            27:  *
        !            28:  */
        !            29: 
        !            30: #include <pwd.h>
        !            31: #include <signal.h>
        !            32: #include <paths.h>
        !            33: #include <fcntl.h>
        !            34: #include <sys/stat.h>
        !            35: #include <sys/types.h>
        !            36: 
        !            37: #ifdef __linux__
        !            38: # include <time.h>
        !            39: #endif  /* __linux__ */
        !            40: 
        !            41: #include "ipguard.h"
        !            42: 
        !            43: static int SIGNAL = 0;
        !            44: static FILE *log_fp = NULL, *pid_fp = NULL;
        !            45: 
        !            46: void exit_ipguard(int reason) {
        !            47:     if (verbose) {
        !            48:         snprintf(s, 64, "Exit on reason %d (pid: %u)", reason, getpid());
        !            49:         log_str(NOTICE, s, "");
        !            50:     }
        !            51:     packet_destroy();
        !            52:     pid_unlink();
        !            53:     log_close();
        !            54:     exit(reason);
        !            55: }
        !            56: 
        !            57: void sig_init(void) {
        !            58:     if (signal(SIGINT, sig_func) == SIG_ERR) {
        !            59:         log_str(ERROR, "signal(SIGINT):", strerror(errno));
        !            60:         exit(EXIT_FAILURE);
        !            61:     }
        !            62:     if (signal(SIGTERM, sig_func) == SIG_ERR) {
        !            63:         log_str(ERROR, "signal(SIGTERM):", strerror(errno));
        !            64:         exit(EXIT_FAILURE);
        !            65:     }
        !            66:     if (signal(SIGHUP, sig_func) == SIG_ERR) {
        !            67:         log_str(ERROR, "signal(SIGHUP):", strerror(errno));
        !            68:         exit(EXIT_FAILURE);
        !            69:     }
        !            70:     if (signal(SIGUSR1, sig_func) == SIG_ERR) {
        !            71:         log_str(ERROR, "signal(SIGUSR1):", strerror(errno));
        !            72:         exit(EXIT_FAILURE);
        !            73:     }
        !            74:     if (signal(SIGUSR2, sig_func) == SIG_ERR) {
        !            75:         log_str(ERROR, "signal(SIGUSR2):", strerror(errno));
        !            76:         exit(EXIT_FAILURE);
        !            77:     }
        !            78: }
        !            79: 
        !            80: void sig_func(int signal) {
        !            81:     if (verbose) {
        !            82:         snprintf(s, 4, "%d", signal);
        !            83:         log_str(NOTICE, "SIGNAL received", s);
        !            84:     }
        !            85:     SIGNAL = signal;
        !            86:     if ((SIGNAL == SIGINT) || (SIGNAL == SIGTERM)) exit_ipguard(SIGNAL);
        !            87: }
        !            88: 
        !            89: void sig_catch(void) {
        !            90:     switch (SIGNAL) {
        !            91:         case SIGHUP: ethers_reinit(); if (!getuid()) log_reopen(); SIGNAL = 0; break;
        !            92:         case SIGUSR1: pair_dump(); if (buffer_num) buffer_dump(); stat_dump(); SIGNAL = 0; break;
        !            93:         case SIGUSR2: buffer_dump2ethers(); SIGNAL = 0; break;
        !            94:     }
        !            95: }
        !            96: 
        !            97: void log_open(void) {
        !            98:     if (!(log_fp = fopen(log_name, "a"))) {
        !            99:         fprintf(stderr, "fopen(%s): %s\n", log_name, strerror(errno));
        !           100:         exit(EXIT_FAILURE);
        !           101:     }
        !           102: }
        !           103: 
        !           104: void log_str(int pri, char *ent, char *err) {
        !           105:     char p[10];
        !           106: 
        !           107:     switch (pri) {
        !           108:         case ERROR: strncpy(p, "error", 10); break;
        !           109:         case WARNING: strncpy(p, "warning", 10); break;
        !           110:         case NOTICE: strncpy(p, "notice", 10); break;
        !           111:         case INFO: strncpy(p, "info", 10); break;
        !           112:         default: strncpy(p, "unknown", 10); break;
        !           113:     }
        !           114:     if (debug > 1) fprintf(stderr, "%s ", time_get());
        !           115:     if (debug) fprintf(stderr, "%s %s\n", ent, err);
        !           116:     fprintf(log_fp, "%s %s %s %s\n", time_get(), p, ent, err);
        !           117:     fflush(log_fp);
        !           118: }
        !           119: 
        !           120: void log_close(void) {
        !           121:     if (fclose(log_fp)) {
        !           122:         fprintf(stderr, "fclose(%s): %s\n", log_name, strerror(errno));
        !           123:     }
        !           124: }
        !           125: 
        !           126: void log_reopen(void) {
        !           127:     log_close(); log_open();
        !           128:     log_str(NOTICE, "Log file reopened:", log_name);
        !           129: }
        !           130: 
        !           131: void pid_check(void) {
        !           132:     struct stat ps;
        !           133:     int pid = 0;
        !           134: 
        !           135:     if (stat(pid_name, &ps) == -1) {
        !           136:         if (errno == ENOENT) return;
        !           137:         else {
        !           138:             snprintf(s, 128, "stat(%s):", pid_name);
        !           139:             log_str(ERROR, s, strerror(errno));
        !           140:             exit(EXIT_FAILURE);
        !           141:         }
        !           142:     } else {
        !           143:         if (!(pid_fp = fopen(pid_name, "r"))) {
        !           144:             snprintf(s, 128, "fopen(%s):", pid_name);
        !           145:             log_str(WARNING, s, strerror(errno));
        !           146:         }
        !           147:         fscanf(pid_fp, "%d", &pid);
        !           148:         fclose(pid_fp);
        !           149:         if (pid) {
        !           150:             if (kill(pid, 0)) {
        !           151:                 snprintf(s, 64, "Removing stale pid: %u", pid);
        !           152:                 log_str(WARNING, s, "");
        !           153:                 pid_unlink();
        !           154:             } else {
        !           155:                 snprintf(s, 64, "Already running, pid: %u", pid);
        !           156:                 log_str(ERROR, s, "");
        !           157:                 exit(EXIT_FAILURE);
        !           158:             }
        !           159:         } else {
        !           160:             snprintf(s, 64, "Wrong pid file found: %s", pid_name);
        !           161:             log_str(ERROR, s, "");
        !           162:             exit(EXIT_FAILURE);
        !           163:         }
        !           164:     }
        !           165: }
        !           166: 
        !           167: void pid_creat(void) {
        !           168:     pid_check();
        !           169:     if (!(pid_fp = fopen(pid_name, "w"))) {
        !           170:         snprintf(s, 128, "fopen(%s):", pid_name);
        !           171:         log_str(ERROR, s, strerror(errno));
        !           172:         exit(EXIT_FAILURE);
        !           173:     }
        !           174:     fprintf(pid_fp, "%d\n", getpid());
        !           175:     fclose(pid_fp);
        !           176: }
        !           177: 
        !           178: void pid_unlink(void) {
        !           179:     if (unlink(pid_name) == -1) {
        !           180:         snprintf(s, 128, "unlink(%s):", pid_name);
        !           181:         log_str(NOTICE, s, strerror(errno));
        !           182:     }
        !           183: }
        !           184: 
        !           185: void daemonize(void) {
        !           186:     int pid, null;
        !           187: 
        !           188:     if ((pid = fork()) == -1) {
        !           189:         log_str(ERROR, "fork():", strerror(errno));
        !           190:         exit(EXIT_FAILURE);
        !           191:     } else if (pid > 0) exit(EXIT_SUCCESS);
        !           192: 
        !           193:     if ((null = open(_PATH_DEVNULL, O_RDWR)) == -1) {
        !           194:         log_str(ERROR, "open(_PATH_DEVNULL):", strerror(errno));
        !           195:         exit(EXIT_FAILURE);
        !           196:     }
        !           197: 
        !           198:     if (dup2(null, 0) == -1) {
        !           199:         log_str(ERROR, "dup2(STDIN):", strerror(errno));
        !           200:         exit(EXIT_FAILURE);
        !           201:     }
        !           202:     if (dup2(null, 1) == -1) {
        !           203:         log_str(ERROR, "dup2(STDOUT):", strerror(errno));
        !           204:         exit(EXIT_FAILURE);
        !           205:     }
        !           206:     if (dup2(null, 2) == -1) {
        !           207:         log_str(ERROR, "dup2(STDERR):", strerror(errno));
        !           208:         exit(EXIT_FAILURE);
        !           209:     }
        !           210: 
        !           211:     if (setsid() == -1) {
        !           212:         log_str(ERROR, "setsid():", strerror(errno));
        !           213:         exit(EXIT_FAILURE);
        !           214:     }
        !           215: 
        !           216:     if (chdir("/") == -1) {
        !           217:         log_str(ERROR, "chdir(/):", strerror(errno));
        !           218:         exit(EXIT_FAILURE);
        !           219:     }
        !           220: }
        !           221: 
        !           222: void set_user(void) {
        !           223:     struct passwd *pw;
        !           224:     int uid = 0, gid = 0;
        !           225: 
        !           226:     if ((pw = getpwnam(suser))) {
        !           227:         uid = pw->pw_uid;
        !           228:         gid = pw->pw_gid;
        !           229:     } else if (!(uid = atoi(suser))) {
        !           230:         pw = getpwuid(uid);
        !           231:         gid = pw->pw_gid;
        !           232:     } else {
        !           233:         log_str(ERROR, "Invalid user", suser);
        !           234:         exit(EXIT_FAILURE);
        !           235:     }
        !           236: 
        !           237:     if (setgid(gid) == -1) {
        !           238:         log_str(ERROR, "setgid():", strerror(errno));
        !           239:         exit(EXIT_FAILURE);
        !           240:     }
        !           241:     if (setuid(uid) == -1) {
        !           242:         log_str(ERROR, "setuid():", strerror(errno));
        !           243:         exit(EXIT_FAILURE);
        !           244:     }
        !           245: 
        !           246:     snprintf(s, 128, "%u/%u", uid, gid);
        !           247:     if (verbose) log_str(NOTICE, "Running as uid/gid:", s);
        !           248: }
        !           249: 
        !           250: void mac_rand(char *mac) {
        !           251:     char c[] = "  ";
        !           252:     register int n;
        !           253: 
        !           254:     for (n = 0; n < 18; n++)
        !           255:         if (mac[n] == 'x') { snprintf(c, 2, "%1x", rand() % 16); mac[n] = c[0]; }
        !           256: }
        !           257: 
        !           258: void mac_regen(char *mac) {
        !           259:     static time_t count = 0;
        !           260:     time_t t;
        !           261:     char c[] = "  ";
        !           262:     register int n;
        !           263: 
        !           264:     if ((t = time(&t)) < count) return;
        !           265:     count = t + fake_regen;
        !           266: 
        !           267:     if (debug > 1) fprintf(stderr, "FAKE REGEN: pre %-17s ", mac);
        !           268: 
        !           269:     for (n = 0; n < 18; n++)
        !           270:         if ((mac[n] >= '0' && mac[n] <= '9') ||
        !           271:             (mac[n] >= 'A' && mac[n] <= 'F') ||
        !           272:             (mac[n] >= 'a' && mac[n] <= 'f'))
        !           273:             { snprintf(c, 2, "%1x", rand() % 16); mac[n] = c[0]; }
        !           274: 
        !           275:     if (debug > 1) fprintf(stderr, "new %-17s\n", mac);
        !           276: }
        !           277: 
        !           278: char *time_get(void) {
        !           279:     static char cur_time[16];
        !           280:     time_t t;
        !           281: 
        !           282:     t = time(&t);
        !           283:     strncpy(cur_time, (char *) ctime(&t) + 4, 15);
        !           284:     cur_time[15] = '\0';
        !           285:     return cur_time;
        !           286: }    
        !           287: 
        !           288: void ethers_stat(void) {
        !           289:     struct stat es;
        !           290:     static time_t ethers_mtime = 0, count = 0;
        !           291:     time_t t;
        !           292: 
        !           293:     if ((t = time(&t)) < count) return;
        !           294:     count = t + ethers_update;
        !           295: 
        !           296:     if (stat(ethers_name, &es) == -1) {
        !           297:         snprintf(s, 128, "stat(%s):", ethers_name);
        !           298:         log_str(WARNING, s, strerror(errno));
        !           299:         return;
        !           300:     }
        !           301: 
        !           302:     if (!ethers_mtime) ethers_mtime = es.st_mtime;
        !           303: 
        !           304:     if (ethers_mtime < es.st_mtime) {
        !           305:         ethers_reinit(); ethers_mtime = es.st_mtime;
        !           306:     }
        !           307: }

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