File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ipguard / system.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 21:59:41 2012 UTC (12 years, 3 months ago) by misho
Branches: ipguard, MAIN
CVS tags: v1_04p3, v1_04p0, v1_04, HEAD
ipguard

    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.1.1.1 2012/02/21 21:59:41 misho 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>