- removed 2 warnings on Solaris
[sip-router] / main.c
1 /*
2  * $Id$
3  */
4
5 #include <stdio.h>
6 #include <errno.h>
7 #include <string.h>
8 #include <netdb.h>
9 #include <unistd.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <arpa/inet.h>
13 #include <sys/utsname.h>
14
15 #include "config.h"
16 #include "dprint.h"
17 #include "route.h"
18 #include "udp_server.h"
19 #include "globals.h"
20
21
22 static char id[]="@(#) $Id$";
23 static char version[]="sip_router 0.3";
24 static char help_msg[]= "\
25 Usage: sip_router -l address [-l address] [options]\n\
26 Options:\n\
27     -f file      Configuration file (default " CFG_FILE ")\n\
28     -p port      Listen on the specified port (default: 5060)\n\
29     -l address   Listen on the specified address (multiple -l mean\n\
30                  listening on more addresses). The default behaviour\n\
31                  is to listen on the addresses returned by uname(2)\n\
32 \n\
33     -n processes Number of child processes to fork per interface\n\
34                  (default: 8)\n\
35 \n\
36     -r           Use dns to check if is necessary to add a \"received=\"\n\
37                  field to a via\n\
38     -R           Same as `-r´ but use reverse dns;\n\
39                  (to use both use `-rR´)\n\
40 \n\
41     -v           Turn on \"via:\" host checking when forwarding replies\n\
42     -d           Debugging mode (multiple -d increase the level)\n\
43     -D           Do not fork into daemon mode\n\
44     -E           Log to stderr\n\
45     -V           Version number\n\
46     -h           This help message\n\
47 ";
48
49
50 /* debuging function */
51 /*
52 void receive_stdin_loop()
53 {
54         #define BSIZE 1024
55         char buf[BSIZE+1];
56         int len;
57         
58         while(1){
59                 len=fread(buf,1,BSIZE,stdin);
60                 buf[len+1]=0;
61                 receive_msg(buf, len);
62                 printf("-------------------------\n");
63         }
64 }
65 */
66
67 /* global vars */
68
69 char* cfg_file = 0;
70 unsigned short port_no = 0; /* port on which we listen */
71 int child_no = 0;           /* number of children processing requests */
72 int debug = 0;
73 int dont_fork = 0;
74 int log_stderr = 0;
75 int check_via =  0;        /* check if reply first via host==us */
76 int received_dns = 0;      /* use dns and/or rdns or to see if we need to 
77                               add a ;received=x.x.x.x to via: */
78
79 char* names[MAX_LISTEN];               /* our names */
80 unsigned long addresses[MAX_LISTEN];   /* our ips */
81 int addresses_no=0;                    /* number of names/ips */
82
83
84
85 int main(int argc, char** argv)
86 {
87
88         FILE* cfg_stream;
89         struct hostent* he;
90         int c,r;
91         char *tmp;
92         struct utsname myname;
93
94         /* process command line (get port no, cfg. file path etc) */
95         opterr=0;
96         while((c=getopt(argc,argv,"f:p:l:n:rRvdDEVh"))!=-1){
97                 switch(c){
98                         case 'f':
99                                         cfg_file=optarg;
100                                         break;
101                         case 'p':
102                                         port_no=strtol(optarg, &tmp, 10);
103                                         if (tmp &&(*tmp)){
104                                                 fprintf(stderr, "bad port number: -p %s\n", optarg);
105                                                 goto error;
106                                         }
107                                         break;
108                         case 'l':
109                                         /* add a new addr. to out address list */
110                                         if (addresses_no < MAX_LISTEN){
111                                                 names[addresses_no]=(char*)malloc(strlen(optarg)+1);
112                                                 if (names[addresses_no]==0){
113                                                         fprintf(stderr, "Out of memory.\n");
114                                                         goto error;
115                                                 }
116                                                 strncpy(names[addresses_no], optarg, strlen(optarg)+1);
117                                                 addresses_no++;
118                                         }else{
119                                                 fprintf(stderr, 
120                                                                         "Too many addresses (max. %d).\n",
121                                                                         MAX_LISTEN);
122                                                 goto error;
123                                         }
124                                         break;
125                         case 'n':
126                                         child_no=strtol(optarg, tmp, 10);
127                                         if (tmp &&(*tmp)){
128                                                 fprintf(stderr, "bad process number: -n %s\n", optarg);
129                                                 goto error;
130                                         }
131                                         break;
132                         case 'v':
133                                         check_via=1;
134                                         break;
135                         case 'r':
136                                         received_dns|=DO_DNS;
137                                         break;
138                         case 'R':
139                                         received_dns|=DO_REV_DNS;
140                         case 'd':
141                                         debug++;
142                                         break;
143                         case 'D':
144                                         dont_fork=1;
145                                         break;
146                         case 'E':
147                                         log_stderr=1;
148                                         break;
149                         case 'V':
150                                         printf("version: %s\n", version);
151                                         exit(0);
152                                         break;
153                         case 'h':
154                                         printf("version: %s\n", version);
155                                         printf("%s",help_msg);
156                                         exit(0);
157                                         break;
158                         case '?':
159                                         if (isprint(optopt))
160                                                 fprintf(stderr, "Unknown option `-%c'.\n", optopt);
161                                         else
162                                                 fprintf(stderr, 
163                                                                 "Unknown option character `\\x%x´.\n",
164                                                                 optopt);
165                                         goto error;
166                         case ':':
167                                         fprintf(stderr, 
168                                                                 "Option `-%c´ requires an argument.\n",
169                                                                 optopt);
170                                         goto error;
171                         default:
172                                         abort();
173                 }
174         }
175         
176         /* fill missing arguments with the default values*/
177         if (cfg_file==0) cfg_file=CFG_FILE;
178         if (port_no==0) port_no=SIP_PORT;
179         if (child_no==0) child_no=CHILD_NO;
180         if (addresses_no==0) {
181                 /* get our address, only the first one */
182                 if (uname (&myname) <0){
183                         fprintf(stderr, "cannot determine hostname, try -l address\n");
184                         goto error;
185                 }
186                 names[addresses_no]=(char*)malloc(strlen(myname.nodename)+1);
187                 if (names[addresses_no]==0){
188                         fprintf(stderr, "Out of memory.\n");
189                         goto error;
190                 }
191                 strncpy(names[addresses_no], myname.nodename,
192                                 strlen(myname.nodename)+1);
193                 addresses_no++;
194         }
195         
196         /* get ips */
197         printf("Listening on ");
198         for (r=0; r<addresses_no;r++){
199                 he=gethostbyname(names[r]);
200                 if (he==0){
201                         DPrint("ERROR: could not resolve %s\n", names[r]);
202                         goto error;
203                 }
204                 addresses[r]=*((long*)he->h_addr_list[0]);
205                 printf("%s [%s] : %d\n",names[r],
206                                 inet_ntoa(*(struct in_addr*)&addresses[r]),
207                                 (unsigned short)port_no);
208         }
209         
210         
211
212         /* load config file or die */
213         cfg_stream=fopen (cfg_file, "r");
214         if (cfg_stream==0){
215                 DPrint("ERROR: loading config file(%s): %s\n", cfg_file,
216                                 strerror(errno));
217                 goto error;
218         }
219
220         if (cfg_parse_stream(cfg_stream)!=0){
221                 DPrint("ERROR: config parser failure\n");
222                 goto error;
223         }
224         
225                 
226         print_rl();
227
228
229         /* init_daemon? */
230
231         /* only one address for now */
232         if (udp_init(addresses[0],port_no)==-1) goto error;
233         /* start/init other processes/threads ? */
234
235         /* receive loop */
236         udp_rcv_loop();
237
238
239 error:
240         return -1;
241
242 }