- ipv6 support (-DUSE_IPV6)
[sip-router] / main.c
1 /*
2  * $Id$
3  */
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <errno.h>
8 #include <ctype.h>
9 #include <string.h>
10 #include <netdb.h>
11 #include <unistd.h>
12 #include <sys/socket.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
15 #include <sys/utsname.h>
16 #include <sys/types.h>
17 #include <sys/mman.h>
18 #include <sys/fcntl.h>
19 #include <sys/time.h>
20 #include <sys/wait.h>
21 #include <signal.h>
22
23 #include "config.h"
24 #include "dprint.h"
25 #include "route.h"
26 #include "udp_server.h"
27 #include "globals.h"
28 #include "mem/mem.h"
29 #ifdef SHM_MEM
30 #include "mem/shm_mem.h"
31 #endif
32 #include "sr_module.h"
33 #include "timer.h"
34 #include "parser/msg_parser.h"
35 #include "ip_addr.h"
36 #include "resolve.h"
37
38
39
40 #include "stats.h"
41
42 #ifdef DEBUG_DMALLOC
43 #include <dmalloc.h>
44 #endif
45
46 static char id[]="@(#) $Id$";
47 static char version[]=  NAME " " VERSION " (" ARCH "/" OS ")" ;
48 static char compiled[]= __TIME__ __DATE__ ;
49 static char flags[]=
50 "STATS:"
51 #ifdef STATS
52 "On"
53 #else
54 "Off"
55 #endif
56 #ifdef USE_IPV6
57 ", USE_IPV6"
58 #endif
59 #ifdef NO_DEBUG
60 ", NO_DEBUG"
61 #endif
62 #ifdef NO_LOG
63 ", NO_LOG"
64 #endif
65 #ifdef EXTRA_DEBUG
66 ", EXTRA_DEBUG"
67 #endif
68 #ifdef DNS_IP_HACK
69 ", DNS_IP_HACK"
70 #endif
71 #ifdef SHM_MEM
72 ", SHM_MEM"
73 #endif
74 #ifdef SHM_MMAP
75 ", SHM_MMAP"
76 #endif
77 #ifdef PKG_MALLOC
78 ", PKG_MALLOC"
79 #endif
80 #ifdef VQ_MALLOC
81 ", VQ_MALLOC"
82 #endif
83 #ifdef F_MALLOC
84 ", F_MALLOC"
85 #endif
86 #ifdef USE_SHM_MEM
87 ", USE_SHM_MEM"
88 #endif
89 #ifdef DBG_QM_MALLOC
90 ", DBG_QM_MALLOC"
91 #endif
92 #ifdef DEBUG_DMALLOC
93 ", DEBUG_DMALLOC"
94 #endif
95 #ifdef SILENT_FR
96 ", SILENT_FR"
97 #endif
98 #ifdef USE_SYNONIM
99 ", USE_SYNONIM"
100 #endif
101 #ifdef NOISY_REPLIES
102 ", NOISY_REPLIES"
103 #endif
104 #ifdef VERY_NOISY_REPLIES
105 ", VERY_NOISY_REPLIES"
106 #endif
107 #ifdef NEW_HNAME
108 ", NEW_HNAME"
109 #endif
110 #ifdef FAST_LOCK
111 ", FAST_LOCK"
112 #ifdef BUSY_WAIT
113 "-BUSY_WAIT"
114 #endif
115 #ifdef ADAPTIVE_WAIT
116 "-ADAPTIVE_WAIT"
117 #endif
118 #ifdef NOSMP
119 "-NOSMP"
120 #endif
121 #endif /*FAST_LOCK*/
122 ;
123
124 static char help_msg[]= "\
125 Usage: " NAME " -l address [-l address] [options]\n\
126 Options:\n\
127     -c           Perform loop checks and compute branches\n\
128     -f file      Configuration file (default " CFG_FILE ")\n\
129     -p port      Listen on the specified port (default: 5060)\n\
130     -l address   Listen on the specified address (multiple -l mean\n\
131                  listening on more addresses). The default behaviour\n\
132                  is to listen on the addresses returned by uname(2)\n\
133 \n\
134     -n processes Number of child processes to fork per interface\n\
135                  (default: 8)\n\
136 \n\
137     -r           Use dns to check if is necessary to add a \"received=\"\n\
138                  field to a via\n\
139     -R           Same as `-r´ but use reverse dns;\n\
140                  (to use both use `-rR´)\n\
141 \n\
142     -v           Turn on \"via:\" host checking when forwarding replies\n\
143     -d           Debugging mode (multiple -d increase the level)\n\
144     -D           Do not fork into daemon mode\n\
145     -E           Log to stderr\n\
146     -V           Version number\n\
147     -h           This help message\n\
148     -b nr        Maximum receive buffer size which will not be exceeded by\n\
149                  auto-probing procedure even if  OS allows\n\
150     -m nr        Size of shared memory allocated in Megabytes\n\
151     -w  dir      change the working directory to \"dir\" (default \"/\")\n\
152     -t  dir      chroot to \"dir\"\n\
153     -u uid       change uid \n\
154     -g gid       change gid \n\
155     -P file      create a pid file\n"
156 #ifdef STATS
157 "    -s file     File to which statistics is dumped (disabled otherwise)\n"
158 #endif
159 ;
160
161 /* print compile-time constants */
162 void print_ct_constants()
163 {
164 #ifdef ADAPTIVE_WAIT
165         printf("ADAPTIVE_WAIT_LOOPS=%d, ", ADAPTIVE_WAIT_LOOPS);
166 #endif
167 /*
168 #ifdef SHM_MEM
169         printf("SHM_MEM_SIZE=%d, ", SHM_MEM_SIZE);
170 #endif
171 */
172         printf("MAX_RECV_BUFFER_SIZE %d, MAX_LISTEN %d,"
173                         " MAX_URI_SIZE %d, MAX_PROCESSES %d, BUF_SIZE %d\n",
174                 MAX_RECV_BUFFER_SIZE, MAX_LISTEN, MAX_URI_SIZE, MAX_PROCESSES,
175                 BUF_SIZE );
176 }
177
178 /* debuging function */
179 /*
180 void receive_stdin_loop()
181 {
182         #define BSIZE 1024
183         char buf[BSIZE+1];
184         int len;
185
186         while(1){
187                 len=fread(buf,1,BSIZE,stdin);
188                 buf[len+1]=0;
189                 receive_msg(buf, len);
190                 printf("-------------------------\n");
191         }
192 }
193 */
194
195 /* global vars */
196
197 char* cfg_file = 0;
198 unsigned short port_no = 0; /* port on which we listen */
199 char port_no_str[MAX_PORT_LEN];
200 int port_no_str_len=0;
201 unsigned int maxbuffer = MAX_RECV_BUFFER_SIZE; /* maximum buffer size we do
202                                                                                                   not want to exceed durig the
203                                                                                                   auto-probing procedure; may 
204                                                                                                   be re-configured */
205 int children_no = 0;                    /* number of children processing requests */
206 int *pids=0;                                    /*array with childrens pids, 0= main proc,
207                                                                         alloc'ed in shared mem if possible*/
208 int debug = 0;
209 int dont_fork = 0;
210 int log_stderr = 0;
211 int check_via =  0;        /* check if reply first via host==us */
212 int loop_checks = 0;    /* calculate branches and check for loops/spirals */
213 int received_dns = 0;      /* use dns and/or rdns or to see if we need to 
214                               add a ;received=x.x.x.x to via: */
215 char* working_dir = 0;
216 char* chroot_dir = 0;
217 int uid = 0;
218 int gid = 0;
219
220 char* names[MAX_LISTEN];              /* our names */
221 int names_len[MAX_LISTEN];            /* lengths of the names*/
222 struct ip_addr addresses[MAX_LISTEN]; /* our ips */
223 int addresses_no=0;                   /* number of names/ips */
224 struct ip_addr* bind_address;        /* listen address of the crt. process */
225
226 /* ipc related globals */
227 int process_no = 0;
228 process_bm_t process_bit = 0;
229 #ifdef ROUTE_SRV
230 #endif
231
232 /* cfg parsing */
233 int cfg_errors=0;
234
235 /* shared memory (in MB) */
236 unsigned int shm_mem_size=SHM_MEM_SIZE * 1024 * 1024;
237
238 #define MAX_FD 32 /* maximum number of inherited open file descriptors,
239                     (normally it shouldn't  be bigger  than 3) */
240
241
242 extern FILE* yyin;
243 extern int yyparse();
244
245
246 static int is_main=0; /* flag = is this the  "main" process? */
247
248 char* pid_file = 0; /* filename as asked by use */
249 char *pid_fn = 0; /* and with port number appended */
250
251 /* daemon init, return 0 on success, -1 on error */
252 int daemonize(char*  name)
253 {
254         FILE *pid_stream;
255         pid_t pid;
256         int r, p;
257
258         int pid_fn_len;
259
260         p=-1;
261
262         if (log_stderr==0)
263                 openlog(name, LOG_PID|LOG_CONS, LOG_LOCAL1 /*LOG_DAEMON*/);
264                 /* LOG_CONS, LOG_PERRROR ? */
265
266
267         if (chroot_dir&&(chroot(chroot_dir)<0)){
268                 LOG(L_CRIT, "Cannot chroot to %s: %s\n", chroot_dir, strerror(errno));
269                 goto error;
270         }
271         
272         if (chdir(working_dir)<0){
273                 LOG(L_CRIT,"cannot chdir to %s: %s\n", working_dir, strerror(errno));
274                 goto error;
275         }
276
277         if (gid&&(setgid(gid)<0)){
278                 LOG(L_CRIT, "cannot change gid to %d: %s\n", gid, strerror(errno));
279                 goto error;
280         }
281         
282         if(uid&&(setuid(uid)<0)){
283                 LOG(L_CRIT, "cannot change uid to %d: %s\n", uid, strerror(errno));
284                 goto error;
285         }
286
287         /* fork to become!= group leader*/
288         if ((pid=fork())<0){
289                 LOG(L_CRIT, "Cannot fork:%s\n", strerror(errno));
290                 goto error;
291         }
292         if (pid!=0){
293                 /* parent process => exit*/
294                 exit(0);
295         }
296         /* become session leader to drop the ctrl. terminal */
297         if (setsid()<0){
298                 LOG(L_WARN, "setsid failed: %s\n",strerror(errno));
299         }
300         /* fork again to drop group  leadership */
301         if ((pid=fork())<0){
302                 LOG(L_CRIT, "Cannot  fork:%s\n", strerror(errno));
303                 goto error;
304         }
305         if (pid!=0){
306                 /*parent process => exit */
307                 exit(0);
308         }
309
310         /* added by noh: create a pid file for the main process */
311         if (pid_file!=0){
312
313                 /* added port number; -jiri */
314                 pid_fn_len = strlen(pid_file) + 5 /* long port number */ 
315                         + 1 /* dot */ + 1 /* ZT */ ;
316                 pid_fn = malloc( pid_fn_len );
317                 if (!pid_fn) {
318                         LOG(L_ERR, "ERROR: There is really no memory for ser\n");
319                         goto error;
320                 }
321                 if (snprintf(pid_fn, pid_fn_len, "%s.%d", pid_file, port_no )==-1) {
322                         LOG(L_ERR, "ERROR: pidfile printig failed -- perhaps too high port?\n");
323                         goto error;
324                 }
325                 
326                         
327                 if ((pid_stream=fopen(pid_fn, "r"))!=NULL){
328                         fscanf(pid_stream, "%d", &p);
329                         fclose(pid_stream);
330                         if (p==-1){
331                                 LOG(L_CRIT, "pid file %s exists, but doesn't contain a valid"
332                                         " pid number\n", pid_fn);
333                                 goto error;
334                         }
335                         if (kill((pid_t)p, 0)==0 || errno==EPERM){
336                                 LOG(L_CRIT, "running process found in the pid file %s\n",
337                                         pid_fn);
338                                 goto error;
339                         }else{
340                                 LOG(L_WARN, "pid file contains old pid, replacing pid\n");
341                         }
342                 }
343                 pid=getpid();
344                 if ((pid_stream=fopen(pid_fn, "w"))==NULL){
345                         LOG(L_WARN, "unable to create pid file %s: %s\n", 
346                                 pid_fn, strerror(errno));
347                         goto error;
348                 }else{
349                         fprintf(pid_stream, "%i\n", (int)pid);
350                         fclose(pid_stream);
351                 }
352         }
353         
354         /* close any open file descriptors */
355         if (log_stderr==0)
356                 for (r=0;r<MAX_FD; r++){
357                         if ((r==3) && log_stderr)  continue;
358                         close(r);
359                 }
360         return  0;
361
362 error:
363         return -1;
364 }
365
366
367
368 /* main loop */
369 int main_loop()
370 {
371         int r, i;
372         pid_t pid;
373
374         /* one "main" process and n children handling i/o */
375
376
377         if (dont_fork){
378 #ifdef STATS
379                 setstats( 0 );
380 #endif
381                 /* only one address */
382                 if (udp_init(&addresses[0],port_no)==-1) goto error;
383
384                 /* we need another process to act as the timer*/
385                 if (timer_list){
386                                 process_no++;
387                                 if ((pid=fork())<0){
388                                         LOG(L_CRIT,  "ERRROR: main_loop: Cannot fork\n");
389                                         goto error;
390                                 }
391                                 
392                                 if (pid==0){
393                                         /* child */
394                                         /* timer!*/
395                                         process_bit = 0;
396                                         for(;;){
397                                                 sleep(TIMER_TICK);
398                                                 timer_ticker();
399                                         }
400                                 }else{
401                                                 pids[process_no]=pid; /*should be shared mem anway*/
402                                 }
403                 }
404                 /* main process, receive loop */
405                 is_main=1;
406                 pids[0]=getpid();
407                 process_bit = 1;
408                 process_no=0; /*main process number*/
409                 
410                      /* We will call child_init even if we
411                       * do not fork
412                       */
413
414                 if (init_child(0) < 0) {
415                         LOG(L_ERR, "init_child failed\n");
416                         goto error;
417                 }
418                 
419                 return udp_rcv_loop();
420         }else{
421                 for(r=0;r<addresses_no;r++){
422                         /* create the listening socket (for each address)*/
423                         if (udp_init(&addresses[r], port_no)==-1) goto error;
424                         for(i=0;i<children_no;i++){
425                                 if ((pid=fork())<0){
426                                         LOG(L_CRIT,  "main_loop: Cannot fork\n");
427                                         goto error;
428                                 }
429                                 if (pid==0){
430                                              /* child */
431
432                                         if (init_child(i) < 0) {
433                                                 LOG(L_ERR, "init_child failed\n");
434                                                 goto error;
435                                         }
436
437                                         process_no=i+1; /*0=main*/
438                                         process_bit = 1 << i;
439 #ifdef STATS
440                                         setstats( i );
441 #endif
442                                         return udp_rcv_loop();
443                                 }else{
444                                                 pids[i+1]=pid; /*should be in shared mem.*/
445                                 }
446                         }
447                         /*parent*/
448                         /*close(udp_sock)*/; /*if it's closed=>sendto invalid fd errors?*/
449                 }
450         }
451         /*this is the main process*/
452         pids[process_no]=getpid();
453         process_bit = 0;
454         is_main=1;
455         if (timer_list){
456                 for(;;){
457                         /* debug:  instead of doing something usefull */
458                         /* (placeholder for timers, etc.) */
459                         sleep(TIMER_TICK);
460                         /* if we received a signal => TIMER_TICK may have not elapsed*/
461                         timer_ticker();
462                 }
463         }else{
464                 for(;;) sleep(LONG_SLEEP);
465         }
466         
467         /*return 0; */
468  error:
469         return -1;
470
471 }
472
473
474 /* added by jku; allows for regular exit on a specific signal;
475    good for profiling which only works if exited regularly and
476    not by default signal handlers
477 */      
478
479 static void sig_usr(int signo)
480 {
481         pid_t   chld;
482         int     chld_status;
483
484         if (signo==SIGINT || signo==SIGPIPE) {  /* exit gracefuly */
485                 DPrint("INT received, program terminates\n");
486 #               ifdef STATS
487                 /* print statistics on exit only for the first process */
488                 if (stats->process_index==0 && stat_file )
489                         if (dump_all_statistic()==0)
490                                 printf("statistic dumped to %s\n", stat_file );
491                         else
492                                 printf("statistics dump to %s failed\n", stat_file );
493 #               endif
494                 /* WARNING: very dangerous, might be unsafe*/
495                 if (is_main)
496                         destroy_modules();
497 #ifdef PKG_MALLOC
498                 LOG(L_INFO, "Memory status (pkg):\n");
499                 pkg_status();
500 #               endif
501 #ifdef SHM_MEM
502                 if (is_main){
503                         LOG(L_INFO, "Memory status (shm):\n");
504                         shm_status();
505                         /*zero all shmem  alloc vars, that will still use*/
506                         pids=0;
507                         shm_mem_destroy();
508                 }
509 #endif
510                 dprint("Thank you for flying " NAME "\n");
511                 exit(0);
512         } else if (signo==SIGTERM) { /* exit gracefully as daemon */
513                 DPrint("TERM received, program terminates\n");
514                 if (is_main){
515 #ifdef STATS
516                         dump_all_statistic();
517 #endif
518                         if (pid_fn) {
519                                 unlink(pid_fn);
520                                 free(pid_fn);
521                         }
522                 }
523                 exit(0);
524         } else if (signo==SIGUSR1) { /* statistic */
525 #ifdef STATS
526                 dump_all_statistic();
527 #endif
528 #ifdef PKG_MALLOC
529                 LOG(L_INFO, "Memory status (pkg):\n");
530                 pkg_status();
531 #endif
532 #ifdef SHM_MEM
533                 LOG(L_INFO, "Memory status (shm):\n");
534                 shm_status();
535 #endif
536         } else if (signo==SIGCHLD) {
537                 while ((chld=waitpid( -1, &chld_status, WNOHANG ))>0) {
538                         if (WIFEXITED(chld_status)) 
539                                 LOG(L_INFO, "child process %d exited normally, status=%d\n",
540                                         chld, WEXITSTATUS(chld_status));
541                         else if (WIFSIGNALED(chld_status)) {
542                                 LOG(L_INFO, "child process %d exited by a signal %d\n",
543                                         chld, WTERMSIG(chld_status));
544 #                               ifdef WCOREDUMP
545                                 LOG(L_INFO, "core was %sgenerated\n", WCOREDUMP(chld_status) ?
546                                         "" : "not" );
547 #                               endif
548                         } else if (WIFSTOPPED(chld_status)) 
549                                 LOG(L_INFO, "child process %d stopped by a signal %d\n",
550                                         chld, WSTOPSIG(chld_status));
551                 }
552         }
553 }
554
555
556 void test();
557
558 int main(int argc, char** argv)
559 {
560
561         FILE* cfg_stream;
562         struct hostent* he;
563         int c,r;
564         char *tmp;
565         struct utsname myname;
566         char *options;
567
568         /* added by jku: add exit handler */
569         if (signal(SIGINT, sig_usr) == SIG_ERR ) {
570                 DPrint("ERROR: no SIGINT signal handler can be installed\n");
571                 goto error;
572         }
573         /* if we debug and write to a pipe, we want to exit nicely too */
574         if (signal(SIGPIPE, sig_usr) == SIG_ERR ) {
575                 DPrint("ERROR: no SIGINT signal handler can be installed\n");
576                 goto error;
577         }
578
579         if (signal(SIGUSR1, sig_usr)  == SIG_ERR ) {
580                 DPrint("ERROR: no SIGUSR1 signal handler can be installed\n");
581                 goto error;
582         }
583         if (signal(SIGCHLD , sig_usr)  == SIG_ERR ) {
584                 DPrint("ERROR: no SIGCHLD signal handler can be installed\n");
585                 goto error;
586         }
587         if (signal(SIGTERM , sig_usr)  == SIG_ERR ) {
588                 DPrint("ERROR: no SIGTERM signal handler can be installed\n");
589                 goto error;
590         }
591
592         //memtest();
593         //hashtest();
594
595         /* process command line (get port no, cfg. file path etc) */
596         opterr=0;
597         options=
598 #ifdef STATS
599         "s:"
600 #endif
601         "f:p:m:b:l:n:rRvcdDEVhw:t:u:g:P:";
602         
603         while((c=getopt(argc,argv,options))!=-1){
604                 switch(c){
605                         case 'f':
606                                         cfg_file=optarg;
607                                         break;
608                         case 's':
609                                 #ifdef STATS
610                                         stat_file=optarg;
611                                 #endif
612                                         break;
613                         case 'p':
614                                         port_no=strtol(optarg, &tmp, 10);
615                                         if (tmp &&(*tmp)){
616                                                 fprintf(stderr, "bad port number: -p %s\n", optarg);
617                                                 goto error;
618                                         }
619                                         break;
620
621                         case 'm':
622                                         shm_mem_size=strtol(optarg, &tmp, 10) * 1024 * 1024;
623                                         if (tmp &&(*tmp)){
624                                                 fprintf(stderr, "bad shmem size number: -m %s\n", optarg);
625                                                 goto error;
626                                         };
627                                         LOG(L_INFO, "ser: shared memory allocated: %d MByte\n", shm_mem_size );
628                                         break;
629
630                         case 'b':
631                                         maxbuffer=strtol(optarg, &tmp, 10);
632                                         if (tmp &&(*tmp)){
633                                                 fprintf(stderr, "bad max buffer size number: -p %s\n", optarg);
634                                                 goto error;
635                                         }
636                                         break;
637                         case 'l':
638                                         /* add a new addr. to our address list */
639                                         if (addresses_no < MAX_LISTEN){
640                                                 names[addresses_no]=(char*)malloc(strlen(optarg)+1);
641                                                 if (names[addresses_no]==0){
642                                                         fprintf(stderr, "Out of memory.\n");
643                                                         goto error;
644                                                 }
645                                                 strncpy(names[addresses_no], optarg, strlen(optarg)+1);
646                                                 addresses_no++;
647                                         }else{
648                                                 fprintf(stderr, 
649                                                                         "Too many addresses (max. %d).\n",
650                                                                         MAX_LISTEN);
651                                                 goto error;
652                                         }
653                                         break;
654                         case 'n':
655                                         children_no=strtol(optarg, &tmp, 10);
656                                         if ((tmp==0) ||(*tmp)){
657                                                 fprintf(stderr, "bad process number: -n %s\n", optarg);
658                                                 goto error;
659                                         }
660                                         break;
661                         case 'v':
662                                         check_via=1;
663                                         break;
664                         case 'c':
665                                         loop_checks=1;
666                                         break;
667                         case 'r':
668                                         received_dns|=DO_DNS;
669                                         break;
670                         case 'R':
671                                         received_dns|=DO_REV_DNS;
672                         case 'd':
673                                         debug++;
674                                         break;
675                         case 'D':
676                                         dont_fork=1;
677                                         break;
678                         case 'E':
679                                         log_stderr=1;
680                                         break;
681                         case 'V':
682                                         printf("version: %s\n", version);
683                                         printf("flags: %s\n", flags );
684                                         print_ct_constants();
685                                         printf("%s\n",id);
686                                         printf("%s compiled on %s with %s\n", __FILE__,
687                                                         compiled, COMPILER );
688                                         
689                                         exit(0);
690                                         break;
691                         case 'h':
692                                         printf("version: %s\n", version);
693                                         printf("%s",help_msg);
694                                         exit(0);
695                                         break;
696                         case 'w':
697                                         working_dir=optarg;
698                                         break;
699                         case 't':
700                                         chroot_dir=optarg;
701                                         break;
702                         case 'u':
703                                         uid=strtol(optarg, &tmp, 10);
704                                         if ((tmp==0) ||(*tmp)){
705                                                 fprintf(stderr, "bad uid number: -u %s\n", optarg);
706                                                 goto error;
707                                         }
708                                         /* test if string?*/
709                                         break;
710                         case 'g':
711                                         gid=strtol(optarg, &tmp, 10);
712                                         if ((tmp==0) ||(*tmp)){
713                                                 fprintf(stderr, "bad gid number: -g %s\n", optarg);
714                                                 goto error;
715                                         }
716                                         break;
717                         case 'P':
718                                         pid_file=optarg;
719                                         break;
720                         case '?':
721                                         if (isprint(optopt))
722                                                 fprintf(stderr, "Unknown option `-%c´.\n", optopt);
723                                         else
724                                                 fprintf(stderr, 
725                                                                 "Unknown option character `\\x%x´.\n",
726                                                                 optopt);
727                                         goto error;
728                         case ':':
729                                         fprintf(stderr, 
730                                                                 "Option `-%c´ requires an argument.\n",
731                                                                 optopt);
732                                         goto error;
733                         default:
734                                         abort();
735                 }
736         }
737         
738         /* fill missing arguments with the default values*/
739         if (cfg_file==0) cfg_file=CFG_FILE;
740
741         /* load config file or die */
742         cfg_stream=fopen (cfg_file, "r");
743         if (cfg_stream==0){
744                 fprintf(stderr, "ERROR: loading config file(%s): %s\n", cfg_file,
745                                 strerror(errno));
746                 goto error;
747         }
748
749 #ifdef NEW_HNAME
750     init_htable();
751 #endif
752
753         /*init mallocs (before parsing cfg !)*/
754         if (init_mallocs()==-1)
755                 goto error;
756
757         /*init timer, before parsing the cfg!*/
758         if (init_timer()<0){
759                 LOG(L_CRIT, "could not initialize timer, exiting...\n");
760                 goto error;
761         }
762
763         /*register builtin  modules*/
764         register_builtin_modules();
765
766         yyin=cfg_stream;
767         if ((yyparse()!=0)||(cfg_errors)){
768                 fprintf(stderr, "ERROR: bad config file (%d errors)\n", cfg_errors);
769                 goto error;
770         }
771         
772         if (init_modules() != 0) {
773                 fprintf(stderr, "ERROR: error while initializing modules\n");
774                 goto error;
775         }
776
777         print_rl();
778         /* fix routing lists */
779         if ( (r=fix_rls())!=0){
780                 fprintf(stderr, "ERROR: error %x while trying to fix configuration\n",
781                                                 r);
782                 goto error;
783         };
784
785         /* fix parameters */
786         if (port_no<=0) port_no=SIP_PORT;
787         port_no_str_len=snprintf(port_no_str, MAX_PORT_LEN, ":%d", 
788                                 (unsigned short) port_no);
789         if (port_no_str_len<0){
790                 fprintf(stderr, "ERROR: bad port number: %d\n", port_no);
791                 goto error;
792         }
793         /* on some system snprintf return really strange things if it does not 
794            have  enough space */
795         port_no_str_len=
796                                 (port_no_str_len<MAX_PORT_LEN)?port_no_str_len:MAX_PORT_LEN;
797
798         
799         if (children_no<=0) children_no=CHILD_NO;
800         else if (children_no >= MAX_PROCESSES ) {
801                 fprintf(stderr, "ERROR: too many children processes configured;"
802                                 " maximum is %d\n",
803                         MAX_PROCESSES-1 );
804                 goto error;
805         }
806         
807         if (working_dir==0) working_dir="/";
808         /*alloc pids*/
809 #ifdef SHM_MEM
810         pids=shm_malloc(sizeof(int)*(children_no+1));
811 #else
812         pids=malloc(sizeof(int)*(children_no+1));
813 #endif
814         if (pids==0){
815                 fprintf(stderr, "ERROR: out  of memory\n");
816                 goto error;
817         }
818         memset(pids, 0, sizeof(int)*(children_no+1));
819
820         if (addresses_no==0) {
821                 /* get our address, only the first one */
822                 if (uname (&myname) <0){
823                         fprintf(stderr, "cannot determine hostname, try -l address\n");
824                         goto error;
825                 }
826                 names[addresses_no]=(char*)malloc(strlen(myname.nodename)+1);
827                 if (names[addresses_no]==0){
828                         fprintf(stderr, "Out of memory.\n");
829                         goto error;
830                 }
831                 strncpy(names[addresses_no], myname.nodename,
832                                 strlen(myname.nodename)+1);
833                 addresses_no++;
834         }
835
836         /*get name lens*/
837         for(r=0; r<addresses_no; r++){
838                 names_len[r]=strlen(names[r]);
839         }
840
841         
842         /* get ips */
843         printf("Listening on ");
844         for (r=0; r<addresses_no;r++){
845                 he=resolvehost(names[r]);
846                 if (he==0){
847                         DPrint("ERROR: could not resolve %s\n", names[r]);
848                         goto error;
849                 }
850                 hostent2ip_addr(&addresses[r], he, 0); /*convert to ip_addr format*/
851                 /*memcpy(&addresses[r], he->h_addr_list[0], sizeof(int));*/
852                 /*addresses[r]=*((long*)he->h_addr_list[0]);*/
853                 printf("%s [",names[r]);
854                 stdout_print_ip(&addresses[r]);
855                 printf("]:%d\n", (unsigned short)port_no);
856         }
857
858 #ifdef STATS
859         if (init_stats(  dont_fork ? 1 : children_no  )==-1) goto error;
860 #endif
861
862         
863         /* init_daemon? */
864         if (!dont_fork){
865                 if ( daemonize(argv[0]) <0 ) goto error;
866         }
867
868         return main_loop();
869
870
871 error:
872         return -1;
873
874 }
875