/* system.c * * Copyright (c) 2005 SeaD * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include "ipguard.h" static int SIGNAL = 0; static FILE *log_fp = NULL, *pid_fp = NULL; void exit_ipguard(int reason) { snprintf(s, 4, "%d", reason); log_str(NOTICE, "Exit on reason", s); if (buffer_num) buffer_destroy(); packet_destroy(); pair_destroy(); pid_unlink(); log_close(); exit(reason); } void rand_mac(char *mac) { char c[] = " "; register int n; for (n = 0; n < MAC_SIZE; n++) if (mac[n] == MAC_RAND) { snprintf(c, 2, "%1x", rand() % 16); mac[n] = c[0]; } } void sig_init(void) { if (signal(SIGINT, sig_func) == SIG_ERR) { log_str(ERROR, "signal(SIGINT):", strerror(errno)); exit(EXIT_FAILURE); } if (signal(SIGTERM, sig_func) == SIG_ERR) { log_str(ERROR, "signal(SIGTERM):", strerror(errno)); exit(EXIT_FAILURE); } if (signal(SIGHUP, sig_func) == SIG_ERR) { log_str(ERROR, "signal(SIGHUP):", strerror(errno)); exit(EXIT_FAILURE); } if (signal(SIGUSR1, sig_func) == SIG_ERR) { log_str(ERROR, "signal(SIGUSR1):", strerror(errno)); exit(EXIT_FAILURE); } } void sig_func(int signal) { SIGNAL = signal; if (verbose) { snprintf(s, 4, "%d", signal); log_str(NOTICE, "SIGNAL received", s); } } void sig_catch(void) { if (SIGNAL == SIGINT) { exit_ipguard(SIGINT); } if (SIGNAL == SIGTERM) { exit_ipguard(SIGTERM); } if (SIGNAL == SIGHUP) { ethers_reinit(); log_reopen(); SIGNAL = 0; } if (SIGNAL == SIGUSR1) { pair_dump(); if (buffer_num) buffer_dump(); stat_dump(); SIGNAL = 0; } } void log_open(void) { if (!(log_fp = fopen(log_name, "a"))) { fprintf(stderr, "fopen(%s): %s\n", log_name, strerror(errno)); exit(EXIT_FAILURE); } } void log_str(int pri, char *ent, char *err) { char p[10]; switch (pri) { case ERROR: strncpy(p, "error", 10); break; case WARNING: strncpy(p, "warning", 10); break; case NOTICE: strncpy(p, "notice", 10); break; default: strncpy(p, "unknown", 10); break; } if (dont_fork) fprintf(stderr, "%s %s\n", ent, err); fprintf(log_fp, "%s %s %s %s\n", time_get(), p, ent, err); fflush(log_fp); } void log_close(void) { fclose(log_fp); } void log_reopen(void) { log_close(); log_open(); log_str(NOTICE, "Log file reopened:", log_name); } void pid_check(void) { struct stat ps; int pid = 0; if (stat(pid_name, &ps) == -1) { if (errno == ENOENT) return; else { snprintf(s, 128, "stat(%s):", pid_name); log_str(WARNING, s, strerror(errno)); exit(EXIT_FAILURE); } } else { if (!(pid_fp = fopen(pid_name, "r"))) { snprintf(s, 128, "fopen(%s):", pid_name); log_str(ERROR, s, strerror(errno)); } fscanf(pid_fp, "%d", &pid); fclose(pid_fp); if (pid) { snprintf(s, 64, "Already running, pid: %u", pid); log_str(WARNING, s, ""); exit(EXIT_FAILURE); } else { snprintf(s, 64, "Wrong pid file found: %s", pid_name); log_str(WARNING, s, ""); exit(EXIT_FAILURE); } } } void pid_creat(void) { pid_check(); if (!(pid_fp = fopen(pid_name, "w"))) { snprintf(s, 128, "fopen(%s):", pid_name); log_str(ERROR, s, strerror(errno)); exit(EXIT_FAILURE); } fprintf(pid_fp, "%d\n", getpid()); fclose(pid_fp); } void pid_unlink(void) { if (unlink(pid_name) == -1) { snprintf(s, 128, "unlink(%s):", pid_name); log_str(ERROR, s, strerror(errno)); exit(EXIT_FAILURE); } } char *time_get(void) { static char cur_time[16]; time_t t; t = time(&t); strncpy(cur_time, (char *) ctime(&t) + 4, 15); cur_time[15] = '\0'; return (cur_time); } void ethers_stat(void) { struct stat es; static time_t ethers_mtime = 0, count = 0; time_t t; if ((t = time(&t)) < count) return; count = t + ethers_update; if (!ethers_mtime) { if (stat(ethers_name, &es) == -1) { snprintf(s, 128, "stat(%s):", ethers_name); log_str(WARNING, s, strerror(errno)); } ethers_mtime = es.st_mtime; } if (stat(ethers_name, &es) == -1) { snprintf(s, 128, "stat(%s):", ethers_name); log_str(WARNING, s, strerror(errno)); } if (ethers_mtime < es.st_mtime) { ethers_reinit(); ethers_mtime = es.st_mtime; } }