Browse code

- added cmd line options, help - added check for via (replies) and check for received (requests) - minor bugfixes

Andrei Pelinescu-Onciul authored on 06/09/2001 02:24:00
Showing 11 changed files
... ...
@@ -2,6 +2,8 @@
2 2
 #
3 3
 # sip_router makefile
4 4
 #
5
+# WARNING: requires gmake (GNU Make)
6
+#
5 7
 
6 8
 sources= $(wildcard *.c)
7 9
 objs= $(sources:.c=.o)
... ...
@@ -10,7 +12,10 @@ depends= $(sources:.c=.d)
10 12
 NAME=sip_router
11 13
 
12 14
 CC=gcc
13
-COPTS=-O2
15
+CFLAGS=-O2
16
+# on linux and freebsd keep it empty (e.g. LIBS= )
17
+# on solaris add -lxnet (e.g. LIBS= -lxnet)
18
+LIBS=
14 19
 ALLDEP=Makefile
15 20
 
16 21
 MKDEP=gcc -M
... ...
@@ -19,13 +24,13 @@ MKDEP=gcc -M
19 24
 #implicit rules
20 25
 
21 26
 %.o:%.c $(ALLDEP)
22
-	$(CC) $(COPTS) -c $< -o $@
27
+	$(CC) $(CFLAGS) -c $< -o $@
23 28
 
24 29
 %.d: %.c
25 30
 	$(MKDEP) $< >$@
26 31
 
27 32
 $(NAME): $(objs)
28
-	$(CC) $(COPTS) $(objs) -o $(NAME)
33
+	$(CC) $(CFLAGS) $(LIBS) $(objs) -o $(NAME)
29 34
 
30 35
 .PHONY: all
31 36
 all: $(NAME)
... ...
@@ -15,4 +15,10 @@
15 15
 /* receive buffer size */
16 16
 #define BUF_SIZE 65507
17 17
 
18
+/* maximum number of addresses on which we will listen */
19
+#define MAX_LISTEN 16
20
+
21
+/* default number of child processes started */
22
+#define CHILD_NO    8
23
+
18 24
 #endif
... ...
@@ -8,6 +8,7 @@
8 8
 #include <sys/socket.h>
9 9
 #include <netdb.h>
10 10
 #include <netinet/in.h>
11
+#include <arpa/inet.h>
11 12
 
12 13
 #include "forward.h"
13 14
 #include "config.h"
... ...
@@ -15,16 +16,53 @@
15 16
 #include "route.h"
16 17
 #include "dprint.h"
17 18
 #include "udp_server.h"
19
+#include "globals.h"
18 20
 
19 21
 #define MAX_VIA_LINE_SIZE      240
20 22
 #define MAX_RECEIVED_SIZE  57
21 23
 
22 24
 
23 25
 
26
+/* checks if ip is in host(name) and ?host(ip)=name? 
27
+ * ip must be in network byte order!
28
+ *  resolver = DO_DNS | DO_REV_DNS; if 0 no dns check is made
29
+ * return 0 if equal */
30
+int check_address(unsigned long ip, char *name, int resolver)
31
+{
32
+	struct hostent* he;
33
+	int i;
34
+	
35
+	/* maybe we are lucky and name it's an ip */
36
+	if (strcmp(name, inet_ntoa( *(struct in_addr *)&ip ))==0)
37
+		return 0;
38
+	if (resolver&DO_DNS){ 
39
+		/* try all names ips */
40
+		he=gethostbyname(name);
41
+		for(i=0; he->h_addr_list[i];i++){
42
+			if (*(unsigned long*)he->h_addr_list[i]==ip)
43
+				return 0;
44
+		}
45
+	}
46
+	if (resolver&DO_REV_DNS){
47
+		/* try reverse dns */
48
+		he=gethostbyaddr(&ip, sizeof(ip), AF_INET);
49
+		if (strcmp(he->h_name, name)==0)
50
+			return 0;
51
+		for (i=0; he->h_aliases[i];i++){
52
+			if (strcmp(he->h_aliases[i],name)==0)
53
+				return 0;
54
+		}
55
+	}
56
+	return -1;
57
+}
58
+
59
+
60
+
24 61
 int forward_request(char * orig, char* buf, 
25 62
 					 unsigned int len,
26 63
 					 struct sip_msg* msg,
27
-					 struct route_elem* re)
64
+					 struct route_elem* re,
65
+					 unsigned long source_ip)
28 66
 {
29 67
 	unsigned int new_len, via_len, received_len;
30 68
 	char line_buf[MAX_VIA_LINE_SIZE];
... ...
@@ -36,11 +74,13 @@ int forward_request(char * orig, char* buf,
36 74
 	received_len=0;
37 75
 
38 76
 	via_len=snprintf(line_buf, MAX_VIA_LINE_SIZE, "Via: SIP/2.0/UDP %s:%d\r\n",
39
-						our_name, our_port);
77
+						names[0], port_no);
40 78
 	/* check if received needs to be added */
41
-	/* if check_address(source_ip, msg->via1.host) */
42
-	received_len=snprintf(received_buf, MAX_RECEIVED_SIZE, ";received=%s",
43
-							"10.11.12.13");
79
+	if (check_address(source_ip, msg->via1.host, received_dns)!=0){
80
+		received_len=snprintf(received_buf, MAX_RECEIVED_SIZE,
81
+								";received=%s", 
82
+								inet_ntoa(*(struct in_addr *)&source_ip));
83
+	}
44 84
 	
45 85
 	new_len=len+via_len+received_len;
46 86
 	new_buf=(char*)malloc(new_len+1);
... ...
@@ -120,13 +160,25 @@ int forward_reply(char * orig, char* buf,
120 160
 {
121 161
 
122 162
 
123
-	unsigned int new_len, via_len;
163
+	unsigned int new_len, via_len,r;
124 164
 	char* new_buf;
125 165
 	int offset, s_offset, size;
126 166
 	struct hostent* he;
127 167
 	struct sockaddr_in to;
128 168
 
169
+	new_buf=0;
129 170
 
171
+	/*check if first via host = us */
172
+	if (check_via){
173
+		for (r=0; r<addresses_no; r++)
174
+			if(strcmp(msg->via1.host, names[r])==0) break;
175
+		if (r==addresses_no){
176
+			DPrint("ERROR: forward_reply: host in first via != me : %s\n",
177
+					msg->via1.host);
178
+			/* send error msg back? */
179
+			goto error;
180
+		}
181
+	}
130 182
 	/* we must remove the first via */
131 183
 	via_len=msg->via1.size;
132 184
 	size=msg->via1.hdr-buf;
... ...
@@ -9,8 +9,12 @@
9 9
 #include "msg_parser.h"
10 10
 #include "route.h"
11 11
 
12
+
13
+int check_address(unsigned long ip, char *name, int resolver);
14
+
12 15
 int forward_request(char * orig, char* buf, unsigned int len,
13
-					 struct sip_msg* msg,  struct route_elem* re);
16
+					 struct sip_msg* msg,  struct route_elem* re,
17
+					 unsigned long source_ip);
14 18
 
15 19
 int forward_reply(char * orig, char* buf, unsigned int len, 
16 20
 					struct sip_msg* msg);
17 21
new file mode 100644
... ...
@@ -0,0 +1,30 @@
1
+/*
2
+ * $Id*
3
+ *
4
+ * global variables
5
+ *
6
+ */
7
+
8
+
9
+#ifndef globals_h
10
+#define globals_h
11
+
12
+#define NO_DNS     0
13
+#define DO_DNS     1
14
+#define DO_REV_DNS 2
15
+
16
+
17
+extern char * cfg_file;
18
+extern unsigned short port_no;
19
+extern char * names[];
20
+extern unsigned long addresses[];
21
+extern int addresses_no;
22
+extern int child_no;
23
+extern int debug;
24
+extern int dont_fork;
25
+extern int log_stderr;
26
+extern int check_via;
27
+extern int received_dns;
28
+
29
+
30
+#endif
... ...
@@ -6,12 +6,45 @@
6 6
 #include <errno.h>
7 7
 #include <string.h>
8 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>
9 14
 
10 15
 #include "config.h"
11 16
 #include "dprint.h"
12 17
 #include "route.h"
13 18
 #include "udp_server.h"
14
-
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
+";
15 48
 
16 49
 
17 50
 /* debuging function */
... ...
@@ -31,41 +64,156 @@ void receive_stdin_loop()
31 64
 }
32 65
 */
33 66
 
34
-#define NAME "0.0.0.0"
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
+
35 83
 
36 84
 
37 85
 int main(int argc, char** argv)
38 86
 {
39 87
 
40
-	char * cfg_file;
41 88
 	FILE* cfg_stream;
42 89
 	struct hostent* he;
90
+	int c,r;
91
+	char *tmp;
92
+	struct utsname myname;
43 93
 
44
-	cfg_file=CFG_FILE;
45
-	
46 94
 	/* process command line (get port no, cfg. file path etc) */
47
-	/* ...*/
48
-
49
-	our_port=SIP_PORT;
50
-	our_name=NAME;
51
-	/* get ip */
52
-	he=gethostbyname(our_name);
53
-	if (he==0){
54
-		DPrint("ERROR: could not resolve %s\n", our_name);
55
-		goto error;
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);
56 208
 	}
57
-	our_address=*((long*)he->h_addr_list[0]);
58
-	printf("Listening on %s[%x]:%d\n",our_name,
59
-				(unsigned long)our_address,
60
-				(unsigned short)our_port);
61
-		
62 209
 	
63 210
 	
64 211
 
65 212
 	/* load config file or die */
66 213
 	cfg_stream=fopen (cfg_file, "r");
67 214
 	if (cfg_stream==0){
68
-		DPrint("ERROR: could not load config file: %s\n", strerror(errno));
215
+		DPrint("ERROR: loading config file(%s): %s\n", cfg_file,
216
+				strerror(errno));
69 217
 		goto error;
70 218
 	}
71 219
 
... ...
@@ -79,7 +227,9 @@ int main(int argc, char** argv)
79 227
 
80 228
 
81 229
 	/* init_daemon? */
82
-	if (udp_init(our_address,our_port)==-1) goto error;
230
+
231
+	/* only one address for now */
232
+	if (udp_init(addresses[0],port_no)==-1) goto error;
83 233
 	/* start/init other processes/threads ? */
84 234
 
85 235
 	/* receive loop */
... ...
@@ -11,7 +11,7 @@
11 11
 #include "forward.h"
12 12
 
13 13
 
14
-int receive_msg(char* buf, unsigned int len)
14
+int receive_msg(char* buf, unsigned int len, unsigned long src_ip)
15 15
 {
16 16
 	struct sip_msg msg;
17 17
 	struct route_elem *re;
... ...
@@ -49,8 +49,8 @@ int receive_msg(char* buf, unsigned int len)
49 49
 		}
50 50
 		re->tx++;
51 51
 		/* send msg */
52
-		forward_request(orig, buf, len, &msg, re);
53 52
 		DPrint(" found route to: %s\n", re->host.h_name);
53
+		forward_request(orig, buf, len, &msg, re, src_ip);
54 54
 	}else if (msg.first_line.type==SIP_REPLY){
55 55
 		/* sanity checks */
56 56
 		if (msg.via1.error!=VIA_PARSE_OK){
... ...
@@ -64,11 +64,11 @@ int receive_msg(char* buf, unsigned int len)
64 64
 		/* check if via1 == us */
65 65
 		
66 66
 		/* send the msg */
67
-		forward_reply(orig, buf, len, &msg);
68
-		DPrint(" reply forwarded to %s:%d\n", 
69
-					msg.via2.host,
70
-					(unsigned short) msg.via2.port
71
-				);
67
+		if (forward_reply(orig, buf, len, &msg)==0){
68
+			DPrint(" reply forwarded to %s:%d\n", 
69
+						msg.via2.host,
70
+						(unsigned short) msg.via2.port);
71
+		}
72 72
 	}
73 73
 skip:
74 74
 	free(orig);
... ...
@@ -6,7 +6,7 @@
6 6
 #ifndef receive_h
7 7
 #define receive_h
8 8
 
9
-int receive_msg(char* buf, unsigned int len);
9
+int receive_msg(char* buf, unsigned int len, unsigned long src_ip);
10 10
 
11 11
 
12 12
 #endif
... ...
@@ -4,7 +4,8 @@
4 4
 #  method_re   sip_uri_re      dest_host
5 5
 # (warning: re cannot contain space)
6 6
 
7
-.*			.*				   fox.iptel.org
7
+#.*			.*				   centauri.fokus.gmd.de 
8
+.			.				   fox.iptel.org
8 9
 ^R.*        ^sip:.*@dorian.*   ekina.fokus.gmd.de        
9 10
 ^INVITE     .*                 ape:5061             # my laptop
10 11
 .           .                  192.168.46.55
... ...
@@ -15,10 +15,6 @@
15 15
 
16 16
 int udp_sock;
17 17
 
18
-char* our_name;
19
-unsigned long our_address;
20
-unsigned short our_port;
21
-
22 18
 
23 19
 
24 20
 int udp_init(unsigned long ip, unsigned short port)
... ...
@@ -37,7 +33,7 @@ int udp_init(unsigned long ip, unsigned short port)
37 33
 	}
38 34
 	/* set sock opts? */
39 35
 	optval=1;
40
-	if (setsockopt(udp_sock, SOL_SOCKET, SO_REUSEPORT,
36
+	if (setsockopt(udp_sock, SOL_SOCKET, SO_REUSEADDR,
41 37
 					&optval, sizeof(optval)) ==-1)
42 38
 	{
43 39
 		DPrint("ERROR: udp_init: setsockopt: %s\n", strerror());
... ...
@@ -82,15 +78,17 @@ int udp_rcv_loop()
82 78
 		/*debugging, make print* msg work */
83 79
 		buf[len+1]=0;
84 80
 
85
-		receive_msg(buf, len, from, fromlen);
86
-
81
+		receive_msg(buf, len, ((struct sockaddr_in*)from)->sin_addr.s_addr);
82
+		
87 83
 	skip: /* do other stuff */
88 84
 		
89 85
 	}
90
-
86
+	
87
+	if (from) free(from);
91 88
 	return 0;
92 89
 	
93 90
 error:
91
+	if (from) free(from);
94 92
 	return -1;
95 93
 }
96 94
 
... ...
@@ -9,10 +9,6 @@
9 9
 
10 10
 extern int udp_sock;
11 11
 
12
-extern char* our_name;
13
-extern unsigned long  our_address;
14
-extern unsigned short our_port;
15
-
16 12
 int udp_init(unsigned long ip, unsigned short port);
17 13
 int udp_rcv_loop();
18 14