Annotation of embedaddon/ipguard/system.c, revision 1.1.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>