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