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>