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>