1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
10 \*****************************************************************************/
15 #include <sys/types.h>
22 #include <sys/ioctl.h>
26 #include <sys/resource.h>
34 struct timeval now_tv;
35 struct timezone now_tz;
38 gettimeofday(&now_tv, &now_tz); \
39 now_d = ((double)(now_tv.tv_usec))/1000000 + now_tv.tv_sec; \
40 now = now_tv.tv_sec; \
41 now_tm = localtime(&now); \
43 //#define DEBUG_DURATION
48 pthread_mutex_t mutexd; // debug output mutex
49 //pthread_mutex_t mutext; // trace output mutex
50 pthread_mutex_t mutexe; // error output mutex
63 char *debug_prefix = 0;
66 int debug_newline = 1;
69 void debug(const char *function, int line, char *prefix, char *buffer)
71 /* if we have a new debug count, we add a mark */
72 if (last_debug != debug_count)
74 last_debug = debug_count;
76 printf("\033[34m--------------------- %04d.%02d.%02d %02d:%02d:%02d %06d\033[36m\n", now_tm->tm_year+1900, now_tm->tm_mon+1, now_tm->tm_mday, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec, debug_count%1000000);
77 if (options.deb&DEBUG_LOG && global_debug)
78 dprint(DBGM_MAN, 0, "--------------------- %04d.%02d.%02d %02d:%02d:%02d %06d\n", now_tm->tm_year+1900, now_tm->tm_mon+1, now_tm->tm_mday, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec, debug_count%1000000);
84 printf("\033[32m%06d %s\033[37m%s", debug_count%1000000, prefix?prefix:"", prefix?" ":"");
86 printf("(in %s() line %d): %s", function, line, buffer);
91 if (options.deb&DEBUG_LOG && global_debug)
96 dprint(DBGM_MAN, 0, "%s%s(in %s() line %d): %s", prefix?prefix:"", prefix?" ":"", function, line, buffer);
98 dprint(DBGM_MAN, 0, "%s%s: %s", prefix?prefix:"", prefix?" ":"", buffer);
104 if (buffer[strlen(buffer)-1] == '\n')
109 void _printdebug(const char *function, int line, unsigned long mask, const char *fmt, ...)
114 if (!(options.deb & mask))
116 pthread_mutex_lock(&mutexd);
119 VUNPRINT(buffer,sizeof(buffer)-1,fmt,args);
120 buffer[sizeof(buffer)-1]=0;
123 debug(function, line, debug_prefix, buffer);
125 pthread_mutex_unlock(&mutexd);
128 void _printerror(const char *function, int line, const char *fmt, ...)
133 pthread_mutex_lock(&mutexe);
136 VUNPRINT(buffer,sizeof(buffer)-1,fmt,args);
137 buffer[sizeof(buffer)-1]=0;
141 debug(function, line, "ERROR", buffer);
142 else /* only if we do not debug */
145 fprintf(stderr, "ERROR (in %s() line %d) %s", function, line, buffer);
147 fprintf(stderr, "ERROR %s", buffer);
150 pthread_mutex_unlock(&mutexe);
154 void sighandler(int sigset)
156 struct sched_param schedp;
158 if (sigset == SIGHUP)
160 if (sigset == SIGPIPE)
165 /* set scheduler & priority */
166 if (options.schedule > 1)
168 memset(&schedp, 0, sizeof(schedp));
169 schedp.sched_priority = 0;
170 sched_setscheduler(0, SCHED_OTHER, &schedp);
172 fprintf(stderr, "LCR: Signal received: %d\n", sigset);
173 PERROR("Signal received: %d\n", sigset);
181 int main(int argc, char *argv[])
184 int lockfd = -1; /* file lock */
185 struct message *message;
187 class Endpoint *epoint;
191 char prefix_string[64];
192 struct sched_param schedp;
193 char *debug_prefix = "alloc";
194 int created_mutexd = 0,/* created_mutext = 0,*/ created_mutexe = 0,
195 created_lock = 0, created_signal = 0, created_debug = 0;
196 #ifdef DEBUG_DURATION
197 time_t durationupdate;
198 double idle_duration, isdn_duration, port_duration, epoint_duration, call_duration, message_duration, admin_duration;
201 int idletime = 0, idlecheck = 0;
208 printf("\n** %s Version %s\n\n", NAME, VERSION_STRING);
215 printf("Usage: lcr (query | start | fork | rules | route)\n");
216 printf("query = Show available isdn ports.\n");
217 printf("start = Run lcr normally, abort with CTRL+C.\n");
218 printf("fork = Do daemon fork and run as background process.\n");
219 printf("interface = Get help of available interface syntax.\n");
220 printf("rules = Get help of available routing rule syntax.\n");
221 printf("rules [action] = Get individual help for given action.\n");
222 // printf("route = Show current routing as it is parsed.\n");
231 /* check for root (real or effective) */
232 if (getuid() && geteuid())
234 fprintf(stderr, "Please run %s as super-user.\n", NAME);
239 if (pthread_mutex_init(&mutexd, NULL))
241 fprintf(stderr, "cannot create 'PDEBUG' mutex\n");
245 // if (pthread_mutex_init(&mutext, NULL))
247 // fprintf(stderr, "cannot create 'trace' mutex\n");
250 // created_mutext = 1;
251 if (pthread_mutex_init(&mutexe, NULL))
253 fprintf(stderr, "cannot create 'PERROR' mutex\n");
259 if (!(strcasecmp(argv[1],"interface")))
267 if (!(strcasecmp(argv[1],"rules")))
277 /* query available isdn ports */
278 if (!(strcasecmp(argv[1],"query")))
286 if (read_options() == 0)
289 /* initialize stuff of the NT lib */
290 if (options.deb & DEBUG_STACK)
292 global_debug = 0xffffffff & ~DBGM_MSG;
293 // global_debug = DBGM_L3DATA;
295 global_debug = DBGM_MAN;
296 SPRINT(debug_log, "%s/debug.log", INSTALL_DATA);
297 if (options.deb & DEBUG_LOG)
298 debug_init(global_debug, debug_log, debug_log, debug_log);
300 debug_init(global_debug, NULL, NULL, NULL);
305 /* read ruleset(s) */
306 if (!(ruleset_first = ruleset_parse()))
309 /* set pointer to main ruleset */
310 ruleset_main = getrulesetbyname("main");
313 fprintf(stderr, "\n***\n -> Missing 'main' ruleset, causing ALL calls to be disconnected.\n***\n\n");
314 PDEBUG(DEBUG_LOG, "Missing 'main' ruleset, causing ALL calls to be disconnected.\n");
319 /* query available isdn ports */
320 if (!(strcasecmp(argv[1],"route")))
322 ruleset_debug(ruleset_first);
328 /* do fork in special cases */
329 if (!(strcasecmp(argv[1],"fork")))
338 fprintf(stderr, "Cannot fork!\n");
353 fprintf(stderr, "Cannot fork!\n");
358 printf("LCR: Starting daemon.\n");
364 if (!!strcasecmp(argv[1],"start"))
369 /* create lock and lock! */
370 if ((lockfd = open("/var/run/lcr.lock", O_CREAT, 0)) < 0)
372 fprintf(stderr, "Cannot create lock file: /var/run/lcr.lock\n");
375 if (flock(lockfd, LOCK_EX|LOCK_NB) < 0)
377 if (errno == EWOULDBLOCK)
378 fprintf(stderr, "LCR: Another LCR process is running. Please kill the other one.\n");
379 else fprintf(stderr, "Locking process failed: errno=%d\n", errno);
384 /* initialize admin socket */
387 fprintf(stderr, "Unable to initialize admin socket.\n");
391 /* generate alaw / ulaw tables */
392 generate_tables(options.law);
394 /* load tones (if requested) */
395 if (fetch_tones() == 0)
397 fprintf(stderr, "Unable to fetch tones into memory.\n");
401 /* read interfaces and open ports */
402 if (!read_interfaces())
404 PERROR_RUNTIME("No interfaces specified or failed to parse interface.conf.\n");
405 fprintf(stderr, "No interfaces specified or failed to parse interface.conf.\n");
409 interface_first = interface_newlist;
410 interface_newlist = NULL;
412 /* locking memory paging */
416 if (mlockall(MCL_CURRENT | MCL_FUTURE) >= 0)
426 fprintf(stderr, "Not enough memory to lock paging, exitting...\n");
429 fprintf(stderr, "No permission to lock paging, exitting...\n");
432 fprintf(stderr, "'Bad address' while locking paging, exitting...\n");
435 fprintf(stderr, "Unknown error %d while locking paging, exitting...\n", errno);
440 /* set real time scheduler & priority */
441 if (options.schedule > 1)
443 memset(&schedp, 0, sizeof(schedp));
444 schedp.sched_priority = options.schedule;
445 ret = sched_setscheduler(0, SCHED_RR, &schedp);
448 PERROR("Scheduling failed with given priority %d (errno = %d).\nCheck options.conf 'schedule', exitting...\n", options.schedule, errno);
453 /* signal handlers */
454 signal(SIGINT,sighandler);
455 signal(SIGHUP,sighandler);
456 signal(SIGTERM,sighandler);
457 signal(SIGPIPE,sighandler);
461 printf("%s %s started, waiting for calls...\n", NAME, VERSION_STRING);
463 #ifdef DEBUG_DURATION
465 durationupdate = now;
466 idle_duration = isdn_duration = port_duration = epoint_duration = call_duration = message_duration = admin_duration = 0;
471 /* all loops must be counted from the beginning since nodes might get freed during handler */
474 /* handle mISDN messages from kernel */
475 debug_prefix = "ISDN";
478 #ifdef DEBUG_DURATION
480 isdn_duration += (now_d - start_d);
485 /* loop through all port ports and call their handler */
490 debug_prefix = port->p_name;
492 ret = port->handler();
495 if (ret < 0) /* port has been destroyed */
499 #ifdef DEBUG_DURATION
501 port_duration += (now_d - start_d);
505 /* loop through all epoint and call their handler */
507 epoint = epoint_first;
510 debug_prefix = prefix_string;
511 SPRINT(prefix_string, "ep%ld", epoint->ep_serial);
513 ret = epoint->handler();
516 if (ret < 0) /* epoint has been destroyed */
518 epoint = epoint->next;
520 #ifdef DEBUG_DURATION
522 epoint_duration += (now_d - start_d);
526 /* loop through all calls and call their handler */
531 debug_prefix = "call";
533 ret = call->handler();
536 if (ret < 0) /* call has been destroyed */
540 #ifdef DEBUG_DURATION
542 call_duration += (now_d - start_d);
548 /* process any message */
550 debug_prefix = "message";
551 while ((message = message_get()))
554 switch(message->flow)
557 debug_prefix = "msg port->epoint";
558 epoint = find_epoint_id(message->id_to);
563 epoint->ep_app->ea_message_port(message->id_from, message->type, &message->param);
566 PDEBUG(DEBUG_MSG, "Warning: message %s from port %d to endpoint %d. endpoint doesn't have an application.\n", messages_txt[message->type], message->id_from, message->id_to);
570 PDEBUG(DEBUG_MSG, "Warning: message %s from port %d to endpoint %d. endpoint doesn't exist anymore.\n", messages_txt[message->type], message->id_from, message->id_to);
575 debug_prefix = "msg epoint->call";
576 call = find_call_id(message->id_to);
579 call->message_epoint(message->id_from, message->type, &message->param);
582 PDEBUG(DEBUG_MSG, "Warning: message %s from endpoint %d to call %d. call doesn't exist anymore\n", messages_txt[message->type], message->id_from, message->id_to);
587 debug_prefix = "msg call->epoint";
588 epoint = find_epoint_id(message->id_to);
593 epoint->ep_app->ea_message_call(message->id_from, message->type, &message->param);
596 PDEBUG(DEBUG_MSG, "Warning: message %s from call %d to endpoint %d. endpoint doesn't have an application.\n", messages_txt[message->type], message->id_from, message->id_to);
600 PDEBUG(DEBUG_MSG, "Warning: message %s from call %d to endpoint %d. endpoint doesn't exist anymore.\n", messages_txt[message->type], message->id_from, message->id_to);
605 debug_prefix = "msg epoint->port";
606 port = find_port_id(message->id_to);
609 port->message_epoint(message->id_from, message->type, &message->param);
613 PDEBUG(DEBUG_MSG, "Warning: message %s from endpoint %d to port %d. port doesn't exist anymore\n", messages_txt[message->type], message->id_from, message->id_to);
618 PERROR("Message flow %d unknown.\n", message->flow);
620 message_free(message);
622 debug_prefix = "message";
624 #ifdef DEBUG_DURATION
626 message_duration += (now_d - start_d);
634 #ifdef DEBUG_DURATION
636 admin_duration += (now_d - start_d);
642 /* check for child to exit (eliminate zombies) */
643 if (waitpid(-1, NULL, WNOHANG) > 0)
645 PDEBUG(DEBUG_EPOINT, "a child process (created by endpoint) has exitted.\n");
650 /* do idle checking */
651 if (idlecheck != now)
653 PDEBUG(DEBUG_IDLETIME, "Idle time : %d%%\n", idletime/10000);
657 #ifdef DEBUG_DURATION
659 idle_duration += (now_d - start_d);
661 if (durationupdate != now)
663 durationupdate = now;
664 printf("Idle:%3d ISDN:%3d Port:%3d Epoint:%3d Call:%3d Message:%3d Admin:%3d\n",
665 (int)(idle_duration*100),
666 (int)(isdn_duration*100),
667 (int)(port_duration*100),
668 (int)(epoint_duration*100),
669 (int)(call_duration*100),
670 (int)(message_duration*100),
671 (int)(admin_duration*100));
672 idle_duration = isdn_duration = port_duration = epoint_duration = call_duration = message_duration = admin_duration = 0;
678 /* did we do nothing? so we wait to give time to other processes */
681 usleep(4000); /* wait 32 samples */
685 printf("LCR terminated\n");
692 /* set scheduler & priority
694 if (options.schedule > 1)
696 memset(&schedp, 0, sizeof(schedp));
697 schedp.sched_priority = 0;
698 sched_setscheduler(0, SCHED_OTHER, &schedp);
703 signal(SIGINT,SIG_DFL);
704 signal(SIGHUP,SIG_DFL);
705 signal(SIGTERM,SIG_DFL);
706 signal(SIGPIPE,SIG_DFL);
709 /* destroy objects */
710 debug_prefix = "free";
726 /* free interfaces */
728 free_interfaces(interface_first);
729 interface_first = NULL;
731 /* close isdn ports */
732 mISDNport_close_all();
737 while ((message = message_get()))
740 message_free(message);
744 PDEBUG(DEBUG_MSG, "freed %d pending messages\n", i);
751 /* free admin socket */
756 flock(lockfd, LOCK_UN);
762 ruleset_free(ruleset_first);
763 ruleset_first = NULL;
767 if (pthread_mutex_destroy(&mutexe))
768 fprintf(stderr, "cannot destroy 'PERROR' mutex\n");
769 // if (created_mutext)
770 // if (pthread_mutex_destroy(&mutext))
771 // fprintf(stderr, "cannot destroy 'trace' mutex\n");
773 if (pthread_mutex_destroy(&mutexd))
774 fprintf(stderr, "cannot destroy 'PDEBUG' mutex\n");
781 /* display memory leak */
782 #define MEMCHECK(a, b) \
785 printf("\n******************************\n\007"); \
786 printf("\nERROR: %d %s\n", b, a); \
787 printf("\n******************************\n"); \
791 MEMCHECK("memory block(s) left (port.cpp)",pmemuse)
792 MEMCHECK("memory block(s) left (epoint.cpp)",ememuse)
793 MEMCHECK("memory block(s) left (call.cpp)",cmemuse)
794 MEMCHECK("memory block(s) left (message.c)",mmemuse)
795 MEMCHECK("memory block(s) left (route.c)",rmemuse)
796 MEMCHECK("memory block(s) left (args)",amemuse)
797 MEMCHECK("class(es) left",classuse)
798 MEMCHECK("file descriptor(s) left",fduse)
799 MEMCHECK("file handler(s) left",fhuse)
803 printf("LCR: Exit (code %d)\n", ret);
813 /* special debug function to detect buffer overflow
815 int budetect_stop = 0;
816 void budetect(const char *file, int line, char *function)
820 /* modify this function to detect race-bugs */
821 #warning DID YOU MODIFY THIS FUNCTION TO DETECT THE BUFFER OVERFLOW BUG?
823 class PmISDN *pmisdn;
824 struct mISDNport *mISDNport = mISDNport_first;
830 ii = mISDNport->b_num;
833 if (mISDNport->b_port[i])
838 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_ISDN)
840 pmisdn = (class PmISDN *)port;
841 if (pmisdn->p_isdn_crypt_listen)
843 PERROR_RUNTIME("************************************************\n");
844 PERROR_RUNTIME("** BUG detected in %s, line %d, function %s\n", file, line, function);
845 PERROR_RUNTIME("** p_isdn_crypt_listen = %d\n", pmisdn->p_isdn_crypt_listen);
846 PERROR_RUNTIME("************************************************\n");
850 if (port == mISDNport->b_port[i])
855 PERROR_RUNTIME("************************************************\n");
856 PERROR_RUNTIME("** BUG detected in %s, line %d, function %s\n", file, line, function);
857 PERROR_RUNTIME("** b_port not in list.\n");
858 PERROR_RUNTIME("************************************************\n");
865 mISDNport = mISDNport->next;