]> git.ipfire.org Git - ipfire-2.x.git/blob - src/ibod/ibod.c
CGI fuer DHCP gefixt und if Skripte zurueckgesetzt
[ipfire-2.x.git] / src / ibod / ibod.c
1 /* Customised version of ibod - GUI code removed by Mark Wormgoor
2 * Buffer overflow fixes by Robert Kerr
3 *
4 * ibod originally by Bjoern Smith
5 */
6
7 static char *rcsId = "$Id: ibod.c,v 1.1.1.1.8.1 2005/05/07 12:46:16 rkerr Exp $";
8 static char *rcsSymbol = "$Symbol$";
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <stdio.h>
13 #include <signal.h>
14 #include <sys/time.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <fcntl.h>
18 #include <sys/socket.h>
19 #include <netinet/in.h>
20 #include <linux/isdn.h>
21 #include <syslog.h>
22 #include <errno.h>
23 #include "ibod.h"
24
25 static int setattr();
26 static void reread(int sig);
27 static void pipehndl(int sig);
28 static void setinterval();
29 static void get_if_state();
30 static int bring_up_slave();
31 static int bring_down_slave();
32 static Conf cf;
33 static struct timeval timeout, tv_last, tv_up;
34 static int usageflags[ISDN_MAX_CHANNELS];
35 static char phone[ISDN_MAX_CHANNELS][20];
36 static Siobytes iobytes[ISDN_MAX_CHANNELS];
37 static unsigned long in_bytes_last, out_bytes_last;
38 static unsigned long in_bytes_per_sec, out_bytes_per_sec;
39 static unsigned long channels_last;
40 static int channels_now;
41
42 main(int argc, char *argv[])
43 {
44 openlog("ibod", LOG_PID, LOG_DAEMON);
45
46 channels_last = -1;
47
48 /* Setup initial attributes */
49 if (setattr() == -1) {
50 closelog();
51 exit(1);
52 }
53
54 setinterval();
55
56 /* Setup handlig of signal SIGHUP and SIGPIPE */
57 signal(SIGHUP, reread);
58 signal(SIGPIPE, pipehndl);
59
60 do {
61 setinterval();
62
63 usleep(timeout.tv_usec);
64
65 /* Gate state of interface */
66 get_if_state();
67
68 } while (1);
69 }
70
71
72 static int setattr()
73 {
74 FILE *fd;
75 char config_filename[MAX_STR_LEN] = IBOD_DEFAULT_DIR "/ibod.cf";
76 char linebuf[MAX_STR_LEN];
77 char *key, *value;
78 int val;
79
80 strcpy(cf.dev, DEVICE);
81 cf.enable = ENABLE;
82 cf.interval = INTERVAL;
83 cf.filter = FILTER;
84 cf.limit = LIMIT;
85 cf.stayup = STAYUP;
86 cf.stayup_time = STAYUP_TIME;
87
88 /* Open config file */
89 if ((fd = fopen(config_filename, "r")) == NULL) {
90 syslog(LOG_ERR, "%s: %s\n", config_filename, strerror(errno));
91 return -1;
92 }
93
94 /* Loop over the config file to setup attributes */
95 while (fgets(linebuf, MAX_STR_LEN, fd) != NULL) {
96
97 if (*linebuf == '#') /* Ignore comments */
98 continue;
99
100 key = strtok(linebuf, " \t");
101 value = strtok(NULL, " \t\n");
102
103 if (strcmp(key, "DEVICE") == 0) {
104 if (strcmp(cf.dev, value) != 0)
105 syslog(LOG_NOTICE,
106 "Parameter DEVICE reconfigured to %s\n", value);
107 snprintf(cf.dev, 32,"%s", value);
108 }
109
110 if (strcmp(key, "ENABLE") == 0) {
111 val = atoi(value);
112 if (cf.enable != val)
113 syslog(LOG_NOTICE,
114 "Parameter ENABLE reconfigured to %d\n", val);
115 cf.enable = val;
116 }
117
118 if (strcmp(key, "INTERVAL") == 0) {
119 val = atoi(value);
120 if (cf.interval != val)
121 syslog(LOG_NOTICE,
122 "Parameter INTERVAL reconfigured to %d\n", val);
123 cf.interval = atoi(value);
124 }
125
126 if (strcmp(key, "FILTER") == 0) {
127 val = atoi(value);
128 if (cf.filter != val)
129 syslog(LOG_NOTICE,
130 "Parameter FILTER reconfigured to %d\n", val);
131 cf.filter = atoi(value);
132 }
133
134 if (strcmp(key, "LIMIT") == 0) {
135 val = atoi(value);
136 if (cf.limit != val)
137 syslog(LOG_NOTICE,
138 "Parameter LIMIT reconfigured to %d\n", val);
139 cf.limit = atoi(value);
140 }
141
142 if (strcmp(key, "STAYUP") == 0) {
143 val = atoi(value);
144 if (cf.stayup != val)
145 syslog(LOG_NOTICE,
146 "Parameter STAYUP reconfigured to %d\n", val);
147 cf.stayup = atoi(value);
148 }
149
150 if (strcmp(key, "STAYUP_TIME") == 0) {
151 val = atoi(value);
152 if (cf.stayup_time != val)
153 syslog(LOG_NOTICE,
154 "Parameter STAYUP_TIME reconfigured to %d\n", val);
155 cf.stayup_time = atoi(value);
156 }
157 }
158
159 fclose(fd);
160 return 0;
161 }
162
163
164
165 static void setinterval()
166 {
167 timeout.tv_sec = cf.interval / 1000;
168 timeout.tv_usec = (cf.interval % 1000) * 1000;
169 }
170
171
172 static void reread(int sig)
173 {
174 (void) setattr();
175
176 setinterval();
177
178 signal(SIGHUP, reread);
179 }
180
181
182 static void pipehndl(int sig)
183 {
184 syslog(LOG_ERR, "caught SIGPIPE: %s\n", sys_errlist[errno]);
185
186 signal(SIGPIPE, pipehndl);
187 }
188
189
190 static void get_if_state()
191 {
192 static char buf[4096];
193 struct timeval tv_now;
194 int ms_delta;
195 int in_bytes_now, out_bytes_now;
196 int fd;
197 int i;
198
199 /* Open the info device */
200 if ((fd = open(ISDN_INFO_DEV, O_RDONLY | O_NDELAY)) < 0) {
201 syslog(LOG_ERR, "%s: %s\n", ISDN_INFO_DEV, sys_errlist[errno]);
202 closelog();
203 exit(1);
204 }
205
206 /* Whats the time now */
207 gettimeofday(&tv_now, NULL);
208 ms_delta = (tv_now.tv_sec * 1000 + tv_now.tv_usec / 1000) -
209 (tv_last.tv_sec * 1000 + tv_last.tv_usec / 1000);
210 tv_last = tv_now;
211
212 /* Get info from interface */
213 if (read(fd, buf, sizeof(buf))> 0) {
214 sscanf(strstr(buf, "usage:"),
215 "usage: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
216 &usageflags[0], &usageflags[1], &usageflags[2], &usageflags[3],
217 &usageflags[4], &usageflags[5], &usageflags[6], &usageflags[7],
218 &usageflags[8], &usageflags[9], &usageflags[10], &usageflags[11],
219 &usageflags[12], &usageflags[13], &usageflags[14], &usageflags[15]);
220 sscanf(strstr(buf, "phone:"),
221 "phone: %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s",
222 phone[0], phone[1], phone[2], phone[3],
223 phone[4], phone[5], phone[6], phone[7],
224 phone[8], phone[8], phone[10], phone[11],
225 phone[12], phone[13], phone[14], phone[15]);
226 }
227
228 in_bytes_now = 0;
229 out_bytes_now = 0;
230 channels_now = 0;
231
232 /* Get byte in/out for all channels */
233 if (ioctl(fd, IIOCGETCPS, &iobytes)) {
234 syslog(LOG_ERR, "%s: %s\n", IIOCGETCPS, sys_errlist[errno]);
235 closelog();
236 exit(1);
237 }
238 close(fd);
239
240 /* Count number of open channes and total in/out bytes */
241 for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
242 if (usageflags[i]) {
243 channels_now++;
244 in_bytes_now += iobytes[i].ibytes;
245 out_bytes_now += iobytes[i].obytes;
246 }
247 }
248
249 if (channels_last == -1 || channels_now < channels_last) {
250 channels_last = channels_now;
251 in_bytes_last = in_bytes_now;
252 out_bytes_last = out_bytes_now;
253 return;
254 }
255
256 /* Calculate the total through put in bytes/sec */
257 if (cf.filter < 1) {
258 in_bytes_per_sec =
259 (in_bytes_now - in_bytes_last) * 1000 / ms_delta;
260 out_bytes_per_sec =
261 (out_bytes_now - out_bytes_last) * 1000 / ms_delta;
262 }
263 else {
264 in_bytes_per_sec = (in_bytes_per_sec * (cf.filter - 1) +
265 (in_bytes_now - in_bytes_last) * 1000 / ms_delta) / cf.filter;
266 out_bytes_per_sec = (out_bytes_per_sec * (cf.filter - 1) +
267 (out_bytes_now - out_bytes_last) * 1000 / ms_delta) / cf.filter;
268 }
269
270 in_bytes_last = in_bytes_now;
271 out_bytes_last = out_bytes_now;
272
273 if (channels_now == 0) {
274 channels_last = channels_now;
275 return;
276 }
277
278 /* Take up or down slave channel */
279
280 if (cf.enable == 0) {
281 channels_last = channels_now;
282 return;
283 }
284
285 if (channels_now == 1 &&
286 (in_bytes_per_sec > cf.limit || out_bytes_per_sec > cf.limit)) {
287
288 /* Bring up slave interface */
289 if (bring_up_slave() == -1)
290 exit(1);
291
292 /* Start stay up timer */
293 gettimeofday(&tv_up, NULL);
294 }
295
296 if ((channels_now > 1) &&
297 (in_bytes_per_sec <= cf.limit) &&
298 (out_bytes_per_sec <= cf.limit) &&
299 (cf.stayup == 0)) {
300
301 /* Check that the min stay up timer has expired */
302 gettimeofday(&tv_now, NULL);
303 if (tv_now.tv_sec - tv_up.tv_sec > cf.stayup_time) {
304
305 /* Bring down slave interface */
306 if (bring_down_slave() == -1)
307 exit(1);
308 }
309 }
310
311 channels_last = channels_now;
312 }
313
314
315 static int bring_up_slave()
316 {
317 int fd, rc;
318
319 if ((fd = open(ISDN_CTLR_DEV, O_RDWR)) < 0) {
320 syslog(LOG_ERR, "%s: %s\n", ISDN_CTLR_DEV, sys_errlist[errno]);
321 closelog();
322 return -1;
323 }
324
325 if ((rc = ioctl(fd, IIOCNETALN, cf.dev)) < 0) {
326 syslog(LOG_ERR, "%s: %s\n", cf.dev, sys_errlist[errno]);
327 closelog();
328 return -1;
329 }
330
331 close(fd);
332
333 if (! rc) {
334 syslog(LOG_NOTICE, "added new link\n");
335 channels_now = 2;
336 }
337
338 return 0;
339 }
340
341
342 static int bring_down_slave()
343 {
344 int fd, rc;
345
346 if ((fd = open(ISDN_CTLR_DEV, O_RDWR)) < 0) {
347 syslog(LOG_ERR, "%s: %s\n", ISDN_CTLR_DEV, sys_errlist[errno]);
348 closelog();
349 return -1;
350 }
351
352 if ((rc = ioctl(fd, IIOCNETDLN, cf.dev)) < 0) {
353 syslog(LOG_ERR, "%s: %s\n", cf.dev, sys_errlist[errno]);
354 closelog();
355 return -1;
356 }
357
358 close(fd);
359
360 if (rc)
361 syslog(LOG_ERR, "unable to remove additional link: %d\n", rc);
362 else {
363 syslog(LOG_NOTICE, "removed link\n");
364 }
365
366 return 0;
367 }