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;
209 printf("\n** %s Version %s\n\n", NAME, VERSION_STRING);
216 printf("Usage: lcr (query | start | fork | rules | route)\n");
217 printf("query = Show available isdn ports.\n");
218 printf("start = Run lcr normally, abort with CTRL+C.\n");
219 printf("fork = Do daemon fork and run as background process.\n");
220 printf("interface = Get help of available interface syntax.\n");
221 printf("rules = Get help of available routing rule syntax.\n");
222 printf("rules [action] = Get individual help for given action.\n");
223 // printf("route = Show current routing as it is parsed.\n");
232 /* check for root (real or effective) */
233 if (getuid() && geteuid())
235 fprintf(stderr, "Please run %s as super-user.\n", NAME);
240 if (pthread_mutex_init(&mutexd, NULL))
242 fprintf(stderr, "cannot create 'PDEBUG' mutex\n");
246 // if (pthread_mutex_init(&mutext, NULL))
248 // fprintf(stderr, "cannot create 'trace' mutex\n");
251 // created_mutext = 1;
252 if (pthread_mutex_init(&mutexe, NULL))
254 fprintf(stderr, "cannot create 'PERROR' mutex\n");
260 if (!(strcasecmp(argv[1],"interface")))
268 if (!(strcasecmp(argv[1],"rules")))
278 /* query available isdn ports */
279 if (!(strcasecmp(argv[1],"query")))
287 if (read_options() == 0)
290 /* initialize stuff of the NT lib */
291 if (options.deb & DEBUG_STACK)
293 global_debug = 0xffffffff & ~DBGM_MSG;
294 // global_debug = DBGM_L3DATA;
296 global_debug = DBGM_MAN;
297 SPRINT(debug_log, "%s/debug.log", INSTALL_DATA);
298 if (options.deb & DEBUG_LOG)
299 debug_init(global_debug, debug_log, debug_log, debug_log);
301 debug_init(global_debug, NULL, NULL, NULL);
306 /* read ruleset(s) */
307 if (!(ruleset_first = ruleset_parse()))
310 /* set pointer to main ruleset */
311 ruleset_main = getrulesetbyname("main");
314 fprintf(stderr, "\n***\n -> Missing 'main' ruleset, causing ALL calls to be disconnected.\n***\n\n");
315 PDEBUG(DEBUG_LOG, "Missing 'main' ruleset, causing ALL calls to be disconnected.\n");
320 /* query available isdn ports */
321 if (!(strcasecmp(argv[1],"route")))
323 ruleset_debug(ruleset_first);
329 /* do fork in special cases */
330 if (!(strcasecmp(argv[1],"fork")))
339 fprintf(stderr, "Cannot fork!\n");
354 fprintf(stderr, "Cannot fork!\n");
359 printf("LCR: Starting daemon.\n");
365 if (!!strcasecmp(argv[1],"start"))
370 /* create lock and lock! */
371 if ((lockfd = open("/var/run/lcr.lock", O_CREAT, 0)) < 0)
373 fprintf(stderr, "Cannot create lock file: /var/run/lcr.lock\n");
376 if (flock(lockfd, LOCK_EX|LOCK_NB) < 0)
378 if (errno == EWOULDBLOCK)
379 fprintf(stderr, "LCR: Another LCR process is running. Please kill the other one.\n");
380 else fprintf(stderr, "Locking process failed: errno=%d\n", errno);
385 /* initialize admin socket */
388 fprintf(stderr, "Unable to initialize admin socket.\n");
392 /* generate alaw / ulaw tables */
393 generate_tables(options.law);
395 /* load tones (if requested) */
396 if (fetch_tones() == 0)
398 fprintf(stderr, "Unable to fetch tones into memory.\n");
402 /* read interfaces and open ports */
403 if (!read_interfaces())
405 PERROR_RUNTIME("No interfaces specified or failed to parse interface.conf.\n");
406 fprintf(stderr, "No interfaces specified or failed to parse interface.conf.\n");
410 interface_first = interface_newlist;
411 interface_newlist = NULL;
413 /* locking memory paging */
417 if (mlockall(MCL_CURRENT | MCL_FUTURE) >= 0)
427 fprintf(stderr, "Not enough memory to lock paging, exitting...\n");
430 fprintf(stderr, "No permission to lock paging, exitting...\n");
433 fprintf(stderr, "'Bad address' while locking paging, exitting...\n");
436 fprintf(stderr, "Unknown error %d while locking paging, exitting...\n", errno);
441 /* set real time scheduler & priority */
442 if (options.schedule > 1)
444 memset(&schedp, 0, sizeof(schedp));
445 schedp.sched_priority = options.schedule;
446 ret = sched_setscheduler(0, SCHED_RR, &schedp);
449 PERROR("Scheduling failed with given priority %d (errno = %d).\nCheck options.conf 'schedule', exitting...\n", options.schedule, errno);
454 /* signal handlers */
455 signal(SIGINT,sighandler);
456 signal(SIGHUP,sighandler);
457 signal(SIGTERM,sighandler);
458 signal(SIGPIPE,sighandler);
462 SPRINT(tracetext, "%s %s started, waiting for calls...", NAME, VERSION_STRING);
463 start_trace(0, NULL, NULL, NULL, 0, 0, 0, tracetext);
464 printf("%s\n", tracetext);
467 #ifdef DEBUG_DURATION
469 durationupdate = now;
470 idle_duration = isdn_duration = port_duration = epoint_duration = call_duration = message_duration = admin_duration = 0;
475 /* all loops must be counted from the beginning since nodes might get freed during handler */
478 /* handle mISDN messages from kernel */
479 debug_prefix = "ISDN";
482 #ifdef DEBUG_DURATION
484 isdn_duration += (now_d - start_d);
489 /* loop through all port ports and call their handler */
494 debug_prefix = port->p_name;
496 ret = port->handler();
499 if (ret < 0) /* port has been destroyed */
503 #ifdef DEBUG_DURATION
505 port_duration += (now_d - start_d);
509 /* loop through all epoint and call their handler */
511 epoint = epoint_first;
514 debug_prefix = prefix_string;
515 SPRINT(prefix_string, "ep%ld", epoint->ep_serial);
517 ret = epoint->handler();
520 if (ret < 0) /* epoint has been destroyed */
522 epoint = epoint->next;
524 #ifdef DEBUG_DURATION
526 epoint_duration += (now_d - start_d);
530 /* loop through all calls and call their handler */
535 debug_prefix = "call";
537 ret = call->handler();
540 if (ret < 0) /* call has been destroyed */
544 #ifdef DEBUG_DURATION
546 call_duration += (now_d - start_d);
552 /* process any message */
554 debug_prefix = "message";
555 while ((message = message_get()))
558 switch(message->flow)
561 debug_prefix = "msg port->epoint";
562 epoint = find_epoint_id(message->id_to);
567 epoint->ep_app->ea_message_port(message->id_from, message->type, &message->param);
570 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);
574 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);
579 debug_prefix = "msg epoint->call";
580 call = find_call_id(message->id_to);
583 call->message_epoint(message->id_from, message->type, &message->param);
586 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);
591 debug_prefix = "msg call->epoint";
592 epoint = find_epoint_id(message->id_to);
597 epoint->ep_app->ea_message_call(message->id_from, message->type, &message->param);
600 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);
604 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);
609 debug_prefix = "msg epoint->port";
610 port = find_port_id(message->id_to);
613 port->message_epoint(message->id_from, message->type, &message->param);
617 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);
622 PERROR("Message flow %d unknown.\n", message->flow);
624 message_free(message);
626 debug_prefix = "message";
628 #ifdef DEBUG_DURATION
630 message_duration += (now_d - start_d);
638 #ifdef DEBUG_DURATION
640 admin_duration += (now_d - start_d);
646 /* check for child to exit (eliminate zombies) */
647 if (waitpid(-1, NULL, WNOHANG) > 0)
649 PDEBUG(DEBUG_EPOINT, "a child process (created by endpoint) has exitted.\n");
654 /* do idle checking */
655 if (idlecheck != now)
657 PDEBUG(DEBUG_IDLETIME, "Idle time : %d%%\n", idletime/10000);
661 #ifdef DEBUG_DURATION
663 idle_duration += (now_d - start_d);
665 if (durationupdate != now)
667 durationupdate = now;
668 printf("Idle:%3d ISDN:%3d Port:%3d Epoint:%3d Call:%3d Message:%3d Admin:%3d\n",
669 (int)(idle_duration*100),
670 (int)(isdn_duration*100),
671 (int)(port_duration*100),
672 (int)(epoint_duration*100),
673 (int)(call_duration*100),
674 (int)(message_duration*100),
675 (int)(admin_duration*100));
676 idle_duration = isdn_duration = port_duration = epoint_duration = call_duration = message_duration = admin_duration = 0;
682 /* did we do nothing? so we wait to give time to other processes */
685 usleep(4000); /* wait 32 samples */
689 printf("LCR terminated\n");
696 /* set scheduler & priority
698 if (options.schedule > 1)
700 memset(&schedp, 0, sizeof(schedp));
701 schedp.sched_priority = 0;
702 sched_setscheduler(0, SCHED_OTHER, &schedp);
707 signal(SIGINT,SIG_DFL);
708 signal(SIGHUP,SIG_DFL);
709 signal(SIGTERM,SIG_DFL);
710 signal(SIGPIPE,SIG_DFL);
713 /* destroy objects */
714 debug_prefix = "free";
730 /* free interfaces */
732 free_interfaces(interface_first);
733 interface_first = NULL;
735 /* close isdn ports */
736 mISDNport_close_all();
741 while ((message = message_get()))
744 message_free(message);
748 PDEBUG(DEBUG_MSG, "freed %d pending messages\n", i);
755 /* free admin socket */
760 flock(lockfd, LOCK_UN);
766 ruleset_free(ruleset_first);
767 ruleset_first = NULL;
771 if (pthread_mutex_destroy(&mutexe))
772 fprintf(stderr, "cannot destroy 'PERROR' mutex\n");
773 // if (created_mutext)
774 // if (pthread_mutex_destroy(&mutext))
775 // fprintf(stderr, "cannot destroy 'trace' mutex\n");
777 if (pthread_mutex_destroy(&mutexd))
778 fprintf(stderr, "cannot destroy 'PDEBUG' mutex\n");
785 /* display memory leak */
786 #define MEMCHECK(a, b) \
789 SPRINT(tracetext, a, NAME); \
790 start_trace(0, NULL, NULL, NULL, 0, 0, 0, tracetext); \
791 if (ret) add_trace("blocks", NULL, "%d", b); \
793 printf("\n******************************\n\007"); \
794 printf("\nERROR: %d %s\n", b, a); \
795 printf("\n******************************\n"); \
799 MEMCHECK("memory block(s) left (port.cpp)",pmemuse)
800 MEMCHECK("memory block(s) left (epoint.cpp)",ememuse)
801 MEMCHECK("memory block(s) left (call.cpp)",cmemuse)
802 MEMCHECK("memory block(s) left (message.c)",mmemuse)
803 MEMCHECK("memory block(s) left (route.c)",rmemuse)
804 MEMCHECK("memory block(s) left (args)",amemuse)
805 MEMCHECK("class(es) left",classuse)
806 MEMCHECK("file descriptor(s) left",fduse)
807 MEMCHECK("file handler(s) left",fhuse)
810 SPRINT(tracetext, "%s exit", NAME);
811 printf("%s\n", tracetext);
812 start_trace(0, NULL, NULL, NULL, 0, 0, 0, tracetext);
814 add_trace("error", NULL, "%d", ret);
821 /* special debug function to detect buffer overflow
823 int budetect_stop = 0;
824 void budetect(const char *file, int line, char *function)
828 /* modify this function to detect race-bugs */
829 #warning DID YOU MODIFY THIS FUNCTION TO DETECT THE BUFFER OVERFLOW BUG?
831 class PmISDN *pmisdn;
832 struct mISDNport *mISDNport = mISDNport_first;
838 ii = mISDNport->b_num;
841 if (mISDNport->b_port[i])
846 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_ISDN)
848 pmisdn = (class PmISDN *)port;
849 if (pmisdn->p_isdn_crypt_listen)
851 PERROR_RUNTIME("************************************************\n");
852 PERROR_RUNTIME("** BUG detected in %s, line %d, function %s\n", file, line, function);
853 PERROR_RUNTIME("** p_isdn_crypt_listen = %d\n", pmisdn->p_isdn_crypt_listen);
854 PERROR_RUNTIME("************************************************\n");
858 if (port == mISDNport->b_port[i])
863 PERROR_RUNTIME("************************************************\n");
864 PERROR_RUNTIME("** BUG detected in %s, line %d, function %s\n", file, line, function);
865 PERROR_RUNTIME("** b_port not in list.\n");
866 PERROR_RUNTIME("************************************************\n");
873 mISDNport = mISDNport->next;