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 10
 NAME=sip_router
11 11
 
12 12
 CC=gcc
13
-COPTS=-O2
13
+CFLAGS=-O2
14
+# on linux and freebsd keep it empty (e.g. LIBS= )
15
+# on solaris add -lxnet (e.g. LIBS= -lxnet)
16
+LIBS=
14 17
 ALLDEP=Makefile
15 18
 
16 19
 MKDEP=gcc -M
... ...
@@ -19,13 +24,13 @@ MKDEP=gcc -M
19 19
 #implicit rules
20 20
 
21 21
 %.o:%.c $(ALLDEP)
22
-	$(CC) $(COPTS) -c $< -o $@
22
+	$(CC) $(CFLAGS) -c $< -o $@
23 23
 
24 24
 %.d: %.c
25 25
 	$(MKDEP) $< >$@
26 26
 
27 27
 $(NAME): $(objs)
28
-	$(CC) $(COPTS) $(objs) -o $(NAME)
28
+	$(CC) $(CFLAGS) $(LIBS) $(objs) -o $(NAME)
29 29
 
30 30
 .PHONY: all
31 31
 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 15
 #include "route.h"
16 16
 #include "dprint.h"
17 17
 #include "udp_server.h"
18
+#include "globals.h"
18 19
 
19 20
 #define MAX_VIA_LINE_SIZE      240
20 21
 #define MAX_RECEIVED_SIZE  57
21 22
 
22 23
 
23 24
 
25
+/* checks if ip is in host(name) and ?host(ip)=name? 
26
+ * ip must be in network byte order!
27
+ *  resolver = DO_DNS | DO_REV_DNS; if 0 no dns check is made
28
+ * return 0 if equal */
29
+int check_address(unsigned long ip, char *name, int resolver)
30
+{
31
+	struct hostent* he;
32
+	int i;
33
+	
34
+	/* maybe we are lucky and name it's an ip */
35
+	if (strcmp(name, inet_ntoa( *(struct in_addr *)&ip ))==0)
36
+		return 0;
37
+	if (resolver&DO_DNS){ 
38
+		/* try all names ips */
39
+		he=gethostbyname(name);
40
+		for(i=0; he->h_addr_list[i];i++){
41
+			if (*(unsigned long*)he->h_addr_list[i]==ip)
42
+				return 0;
43
+		}
44
+	}
45
+	if (resolver&DO_REV_DNS){
46
+		/* try reverse dns */
47
+		he=gethostbyaddr(&ip, sizeof(ip), AF_INET);
48
+		if (strcmp(he->h_name, name)==0)
49
+			return 0;
50
+		for (i=0; he->h_aliases[i];i++){
51
+			if (strcmp(he->h_aliases[i],name)==0)
52
+				return 0;
53
+		}
54
+	}
55
+	return -1;
56
+}
57
+
58
+
59
+
24 60
 int forward_request(char * orig, char* buf, 
25 61
 					 unsigned int len,
26 62
 					 struct sip_msg* msg,
27
-					 struct route_elem* re)
63
+					 struct route_elem* re,
64
+					 unsigned long source_ip)
28 65
 {
29 66
 	unsigned int new_len, via_len, received_len;
30 67
 	char line_buf[MAX_VIA_LINE_SIZE];
... ...
@@ -36,11 +74,13 @@ int forward_request(char * orig, char* buf,
36 36
 	received_len=0;
37 37
 
38 38
 	via_len=snprintf(line_buf, MAX_VIA_LINE_SIZE, "Via: SIP/2.0/UDP %s:%d\r\n",
39
-						our_name, our_port);
39
+						names[0], port_no);
40 40
 	/* 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");
41
+	if (check_address(source_ip, msg->via1.host, received_dns)!=0){
42
+		received_len=snprintf(received_buf, MAX_RECEIVED_SIZE,
43
+								";received=%s", 
44
+								inet_ntoa(*(struct in_addr *)&source_ip));
45
+	}
44 46
 	
45 47
 	new_len=len+via_len+received_len;
46 48
 	new_buf=(char*)malloc(new_len+1);
... ...
@@ -120,13 +160,25 @@ int forward_reply(char * orig, char* buf,
120 120
 {
121 121
 
122 122
 
123
-	unsigned int new_len, via_len;
123
+	unsigned int new_len, via_len,r;
124 124
 	char* new_buf;
125 125
 	int offset, s_offset, size;
126 126
 	struct hostent* he;
127 127
 	struct sockaddr_in to;
128 128
 
129
+	new_buf=0;
129 130
 
131
+	/*check if first via host = us */
132
+	if (check_via){
133
+		for (r=0; r<addresses_no; r++)
134
+			if(strcmp(msg->via1.host, names[r])==0) break;
135
+		if (r==addresses_no){
136
+			DPrint("ERROR: forward_reply: host in first via != me : %s\n",
137
+					msg->via1.host);
138
+			/* send error msg back? */
139
+			goto error;
140
+		}
141
+	}
130 142
 	/* we must remove the first via */
131 143
 	via_len=msg->via1.size;
132 144
 	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 @@
0
+/*
1
+ * $Id*
2
+ *
3
+ * global variables
4
+ *
5
+ */
6
+
7
+
8
+#ifndef globals_h
9
+#define globals_h
10
+
11
+#define NO_DNS     0
12
+#define DO_DNS     1
13
+#define DO_REV_DNS 2
14
+
15
+
16
+extern char * cfg_file;
17
+extern unsigned short port_no;
18
+extern char * names[];
19
+extern unsigned long addresses[];
20
+extern int addresses_no;
21
+extern int child_no;
22
+extern int debug;
23
+extern int dont_fork;
24
+extern int log_stderr;
25
+extern int check_via;
26
+extern int received_dns;
27
+
28
+
29
+#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 31
 }
32 32
 */
33 33
 
34
-#define NAME "0.0.0.0"
34
+/* global vars */
35
+
36
+char* cfg_file = 0;
37
+unsigned short port_no = 0; /* port on which we listen */
38
+int child_no = 0;           /* number of children processing requests */
39
+int debug = 0;
40
+int dont_fork = 0;
41
+int log_stderr = 0;
42
+int check_via =  0;        /* check if reply first via host==us */
43
+int received_dns = 0;      /* use dns and/or rdns or to see if we need to 
44
+                              add a ;received=x.x.x.x to via: */
45
+
46
+char* names[MAX_LISTEN];               /* our names */
47
+unsigned long addresses[MAX_LISTEN];   /* our ips */
48
+int addresses_no=0;                    /* number of names/ips */
49
+
35 50
 
36 51
 
37 52
 int main(int argc, char** argv)
38 53
 {
39 54
 
40
-	char * cfg_file;
41 55
 	FILE* cfg_stream;
42 56
 	struct hostent* he;
57
+	int c,r;
58
+	char *tmp;
59
+	struct utsname myname;
43 60
 
44
-	cfg_file=CFG_FILE;
45
-	
46 61
 	/* 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;
62
+	opterr=0;
63
+	while((c=getopt(argc,argv,"f:p:l:n:rRvdDEVh"))!=-1){
64
+		switch(c){
65
+			case 'f':
66
+					cfg_file=optarg;
67
+					break;
68
+			case 'p':
69
+					port_no=strtol(optarg, &tmp, 10);
70
+					if (tmp &&(*tmp)){
71
+						fprintf(stderr, "bad port number: -p %s\n", optarg);
72
+						goto error;
73
+					}
74
+					break;
75
+			case 'l':
76
+					/* add a new addr. to out address list */
77
+					if (addresses_no < MAX_LISTEN){
78
+						names[addresses_no]=(char*)malloc(strlen(optarg)+1);
79
+						if (names[addresses_no]==0){
80
+							fprintf(stderr, "Out of memory.\n");
81
+							goto error;
82
+						}
83
+						strncpy(names[addresses_no], optarg, strlen(optarg)+1);
84
+						addresses_no++;
85
+					}else{
86
+						fprintf(stderr, 
87
+									"Too many addresses (max. %d).\n",
88
+									MAX_LISTEN);
89
+						goto error;
90
+					}
91
+					break;
92
+			case 'n':
93
+					child_no=strtol(optarg, tmp, 10);
94
+					if (tmp &&(*tmp)){
95
+						fprintf(stderr, "bad process number: -n %s\n", optarg);
96
+						goto error;
97
+					}
98
+					break;
99
+			case 'v':
100
+					check_via=1;
101
+					break;
102
+			case 'r':
103
+					received_dns|=DO_DNS;
104
+					break;
105
+			case 'R':
106
+					received_dns|=DO_REV_DNS;
107
+			case 'd':
108
+					debug++;
109
+					break;
110
+			case 'D':
111
+					dont_fork=1;
112
+					break;
113
+			case 'E':
114
+					log_stderr=1;
115
+					break;
116
+			case 'V':
117
+					printf("version: %s\n", version);
118
+					exit(0);
119
+					break;
120
+			case 'h':
121
+					printf("version: %s\n", version);
122
+					printf("%s",help_msg);
123
+					exit(0);
124
+					break;
125
+			case '?':
126
+					if (isprint(optopt))
127
+						fprintf(stderr, "Unknown option `-%c'.\n", optopt);
128
+					else
129
+						fprintf(stderr, 
130
+								"Unknown option character `\\x%x�.\n",
131
+								optopt);
132
+					goto error;
133
+			case ':':
134
+					fprintf(stderr, 
135
+								"Option `-%c� requires an argument.\n",
136
+								optopt);
137
+					goto error;
138
+			default:
139
+					abort();
140
+		}
141
+	}
142
+	
143
+	/* fill missing arguments with the default values*/
144
+	if (cfg_file==0) cfg_file=CFG_FILE;
145
+	if (port_no==0) port_no=SIP_PORT;
146
+	if (child_no==0) child_no=CHILD_NO;
147
+	if (addresses_no==0) {
148
+		/* get our address, only the first one */
149
+		if (uname (&myname) <0){
150
+			fprintf(stderr, "cannot determine hostname, try -l address\n");
151
+			goto error;
152
+		}
153
+		names[addresses_no]=(char*)malloc(strlen(myname.nodename)+1);
154
+		if (names[addresses_no]==0){
155
+			fprintf(stderr, "Out of memory.\n");
156
+			goto error;
157
+		}
158
+		strncpy(names[addresses_no], myname.nodename,
159
+				strlen(myname.nodename)+1);
160
+		addresses_no++;
161
+	}
162
+	
163
+	/* get ips */
164
+	printf("Listening on ");
165
+	for (r=0; r<addresses_no;r++){
166
+		he=gethostbyname(names[r]);
167
+		if (he==0){
168
+			DPrint("ERROR: could not resolve %s\n", names[r]);
169
+			goto error;
170
+		}
171
+		addresses[r]=*((long*)he->h_addr_list[0]);
172
+		printf("%s [%s] : %d\n",names[r],
173
+				inet_ntoa(*(struct in_addr*)&addresses[r]),
174
+				(unsigned short)port_no);
56 175
 	}
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 176
 	
63 177
 	
64 178
 
65 179
 	/* load config file or die */
66 180
 	cfg_stream=fopen (cfg_file, "r");
67 181
 	if (cfg_stream==0){
68
-		DPrint("ERROR: could not load config file: %s\n", strerror(errno));
182
+		DPrint("ERROR: loading config file(%s): %s\n", cfg_file,
183
+				strerror(errno));
69 184
 		goto error;
70 185
 	}
71 186
 
... ...
@@ -79,7 +227,9 @@ int main(int argc, char** argv)
79 79
 
80 80
 
81 81
 	/* init_daemon? */
82
-	if (udp_init(our_address,our_port)==-1) goto error;
82
+
83
+	/* only one address for now */
84
+	if (udp_init(addresses[0],port_no)==-1) goto error;
83 85
 	/* start/init other processes/threads ? */
84 86
 
85 87
 	/* 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 37
 	}
38 38
 	/* set sock opts? */
39 39
 	optval=1;
40
-	if (setsockopt(udp_sock, SOL_SOCKET, SO_REUSEPORT,
40
+	if (setsockopt(udp_sock, SOL_SOCKET, SO_REUSEADDR,
41 41
 					&optval, sizeof(optval)) ==-1)
42 42
 	{
43 43
 		DPrint("ERROR: udp_init: setsockopt: %s\n", strerror());
... ...
@@ -82,15 +78,17 @@ int udp_rcv_loop()
82 82
 		/*debugging, make print* msg work */
83 83
 		buf[len+1]=0;
84 84
 
85
-		receive_msg(buf, len, from, fromlen);
86
-
85
+		receive_msg(buf, len, ((struct sockaddr_in*)from)->sin_addr.s_addr);
86
+		
87 87
 	skip: /* do other stuff */
88 88
 		
89 89
 	}
90
-
90
+	
91
+	if (from) free(from);
91 92
 	return 0;
92 93
 	
93 94
 error:
95
+	if (from) free(from);
94 96
 	return -1;
95 97
 }
96 98
 
... ...
@@ -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