Browse code

Initial revision

Andrei Pelinescu-Onciul authored on 03/09/2001 21:27:11
Showing 24 changed files
1 1
new file mode 100644
2 2
Binary files /dev/null and b/.cfg_parser.c.swp differ
3 3
new file mode 100644
4 4
Binary files /dev/null and b/.cfg_parser.h.swp differ
5 5
new file mode 100644
6 6
Binary files /dev/null and b/.main.c.swp differ
7 7
new file mode 100644
8 8
Binary files /dev/null and b/.msg_parser.c.swp differ
9 9
new file mode 100644
10 10
Binary files /dev/null and b/.msg_parser.h.swp differ
11 11
new file mode 100644
12 12
Binary files /dev/null and b/.parser_f.c.swp differ
13 13
new file mode 100644
14 14
Binary files /dev/null and b/.parser_f.h.swp differ
15 15
new file mode 100644
16 16
Binary files /dev/null and b/.route.c.swp differ
17 17
new file mode 100644
18 18
Binary files /dev/null and b/.route.h.swp differ
19 19
new file mode 100644
20 20
Binary files /dev/null and b/.sip_router.cfg.swp differ
21 21
new file mode 100644
22 22
Binary files /dev/null and b/.test.c.swp differ
23 23
new file mode 100644
... ...
@@ -0,0 +1,126 @@
0
+/*
1
+ * $Id$
2
+ */
3
+
4
+#include <errno.h>
5
+#include <string.h>
6
+#include <stdio.h>
7
+
8
+#include "cfg_parser.h"
9
+#include "dprint.h"
10
+#include "parser_f.h"
11
+#include "route.h"
12
+
13
+
14
+
15
+
16
+/* params: null terminated text line => fills cl
17
+ * returns 0, or on error -1. */
18
+int cfg_parse_line(char* line, struct cfg_line* cl)
19
+{
20
+	/* format:
21
+		line = rule | comment
22
+		comment = SP* '#'.*
23
+		rule = SP* method_re SP* uri_re SP* ip_address comment?
24
+	*/
25
+		
26
+	char* tmp;
27
+	char* end;
28
+	
29
+	end=line+strlen(line);
30
+	tmp=eat_space(line, end-line);
31
+	if ((tmp==end)||(is_empty(tmp, end-tmp))) {
32
+		cl->type=CFG_EMPTY;
33
+		goto skip;
34
+	}
35
+	if (*tmp=='#'){
36
+		cl->type=CFG_COMMENT;
37
+		goto skip;
38
+	}
39
+	cl->method=tmp;
40
+	tmp=eat_token(cl->method,end-cl->method);
41
+	if (tmp==end) goto error;
42
+	printf("%d\n", tmp-line);
43
+	*tmp=0;
44
+	tmp++;
45
+	cl->uri=eat_space(tmp,end-tmp);
46
+	if (tmp==end) goto error;
47
+	tmp=eat_token(cl->uri,end-cl->uri);
48
+	if (tmp==end) goto error;
49
+	printf("%d\n", tmp-line);
50
+	*tmp=0;
51
+	tmp++;
52
+	cl->address=eat_space(tmp,end-tmp);
53
+	if (tmp==end) goto error;
54
+	tmp=eat_token(cl->address, end-cl->address);
55
+	printf("%d(%02x)\n", tmp-line, *tmp);
56
+	if (tmp<end) {
57
+		*tmp=0;
58
+		if (tmp+1<end){
59
+			if (!is_empty(tmp+1,end-tmp-1)){
60
+				printf("%d(%02x) e: %d\n", tmp-line, *tmp, end-line);
61
+				/* check if comment */
62
+				tmp=eat_space(tmp+1, end-tmp-1);
63
+				printf("%d(%02x) e: %d\n", tmp-line, *tmp, end-line);
64
+				if (*tmp!='#'){
65
+					/* extra chars at the end of line */
66
+					goto error;
67
+				}
68
+			}
69
+		}
70
+	}
71
+		
72
+	cl->type=CFG_RULE;
73
+skip:
74
+	return 0;
75
+error:
76
+	cl->type=CFG_ERROR;
77
+	return -1;
78
+}
79
+
80
+
81
+
82
+/* parses the cfg, returns 0 on success, line no otherwise */
83
+int cfg_parse_stream(FILE* stream)
84
+{
85
+	int line;
86
+	struct cfg_line cl;
87
+	char buf[MAX_LINE_SIZE];
88
+	int ret;
89
+
90
+	line=1;
91
+	while(!feof(stream)){
92
+		if (fgets(buf, MAX_LINE_SIZE, stream)){
93
+			cfg_parse_line(buf, &cl);
94
+			switch (cl.type){
95
+				case CFG_RULE:
96
+					if ((ret=add_rule(&cl, &rlist))!=0){
97
+						DPrint("ERROR: could not compile rule at line %d\n",
98
+							line);
99
+						DPrint(" ----: add_rule returned %d\n", ret);
100
+						goto error;
101
+					}
102
+					break;
103
+				case CFG_COMMENT:
104
+				case CFG_SKIP:
105
+					break;
106
+				case CFG_ERROR:
107
+					DPrint("ERROR: bad config line (%d):%s\n", line, buf);
108
+					goto error;
109
+					break;
110
+			}
111
+			line++;
112
+		}else{
113
+			if (ferror(stream)){
114
+				DPrint("ERROR: reading configuration: %s\n", strerror(errno));
115
+				goto error;
116
+			}
117
+			break;
118
+		}
119
+	}
120
+	return 0;
121
+
122
+error:
123
+	return line;
124
+}
125
+
0 126
new file mode 100644
... ...
@@ -0,0 +1,29 @@
0
+/*
1
+ * $Id$
2
+ */
3
+
4
+#ifndef  cfg_parser_h
5
+#define cfg_parser_h
6
+
7
+#include <stdio.h>
8
+
9
+#define CFG_EMPTY   0
10
+#define CFG_COMMENT 1
11
+#define CFG_SKIP    2
12
+#define CFG_RULE    3
13
+#define CFG_ERROR  -1
14
+
15
+#define MAX_LINE_SIZE 800
16
+
17
+struct cfg_line{
18
+	int type;
19
+	char* method;
20
+	char* uri;
21
+	char* address;
22
+};
23
+
24
+
25
+int cfg_parse_line(char* line, struct cfg_line* cl);
26
+int cfg_parse_stream(FILE* stream);
27
+
28
+#endif
0 29
new file mode 100644
... ...
@@ -0,0 +1,21 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * debug print 
4
+ *
5
+ */
6
+ 
7
+#include "dprint.h"
8
+ 
9
+#include <stdarg.h>
10
+#include <stdio.h>
11
+
12
+void dprint(char * format, ...)
13
+{
14
+	va_list ap;
15
+
16
+	va_start(ap, format);
17
+	vfprintf(stderr,format,ap);
18
+	fflush(stderr);
19
+	va_end(ap);
20
+}
0 21
new file mode 100644
... ...
@@ -0,0 +1,20 @@
0
+/*
1
+ * $Id$
2
+ */
3
+
4
+
5
+#ifndef dprint_h
6
+#define dprint_h
7
+
8
+
9
+
10
+void dprint (char* format, ...);
11
+
12
+#ifdef NO_DEBUG
13
+	#define DPrint(fmt, args...)
14
+#else
15
+	#define DPrint(fmt,args...) dprint(fmt, ## args);
16
+#endif
17
+
18
+
19
+#endif /* ifndef dprint_h */
0 20
new file mode 100644
... ...
@@ -0,0 +1,51 @@
0
+/*
1
+ * $Id$
2
+ */
3
+
4
+#include <stdio.h>
5
+#include <errno.h>
6
+#include <string.h>
7
+
8
+#include "dprint.h"
9
+#include "route.h"
10
+
11
+#define CFG_FILE "./sip_router.cfg"
12
+
13
+
14
+int main(int argc, char** argv)
15
+{
16
+
17
+	char * cfg_file;
18
+	FILE* cfg_stream;
19
+
20
+	cfg_file=CFG_FILE;
21
+	
22
+	/* process command line (get port no, cfg. file path etc) */
23
+	/* ...*/
24
+
25
+	/* load config file or die */
26
+	cfg_stream=fopen (cfg_file, "r");
27
+	if (cfg_stream==0){
28
+		DPrint("ERROR: could not load config file: %s\n", strerror(errno));
29
+		goto error;
30
+	}
31
+
32
+	if (cfg_parse_stream(cfg_stream)!=0){
33
+		DPrint("ERROR: config parser failure\n");
34
+		goto error;
35
+	}
36
+	
37
+		
38
+	print_rl();
39
+
40
+
41
+
42
+	/* start other processes/threads ? */
43
+
44
+	/* receive loop */
45
+
46
+
47
+error:
48
+	return -1;
49
+
50
+}
0 51
new file mode 100644
... ...
@@ -0,0 +1,315 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * sip msg. header proxy parser 
4
+ *
5
+ */
6
+
7
+#include "msg_parser.h"
8
+#include "string.h"
9
+
10
+#include "parser_f.h"
11
+#include "dprint.h"
12
+
13
+
14
+
15
+/* parses the first line, returns pointer to  next line  & fills fl;
16
+   also  modifies buffer (to avoid extra copy ops) */
17
+char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl)
18
+{
19
+	
20
+	char *tmp;
21
+	char* second;
22
+	char* third;
23
+	char* nl;
24
+	int offset;
25
+	
26
+	/* grammar:
27
+		request  =  method SP uri SP version CRLF
28
+		response =  version SP status  SP reason  CRLF
29
+		(version = "SIP/2.0")
30
+	*/
31
+	
32
+
33
+	/* see if it's a reply (status) */
34
+	tmp=eat_token(buffer, len);
35
+	if (tmp==buffer){
36
+		DPrint("ERROR: empty  or bad first line\n");
37
+		goto error1;
38
+	}
39
+	if ((strlen(SIP_VERSION)==(tmp-buffer)) &&
40
+		(memcmp(buffer,SIP_VERSION,tmp-buffer)==0)){
41
+		
42
+		fl->type=SIP_REPLY;
43
+	}else{
44
+		fl->type=SIP_REQUEST;
45
+	}
46
+	
47
+	offset=tmp-buffer;
48
+	second=eat_space(tmp, len-offset);
49
+	offset+=second-tmp;
50
+	if (second==tmp){
51
+		goto error;
52
+	}
53
+	*tmp=0; /* mark the end of the token */
54
+	fl->u.request.method=buffer;
55
+	
56
+	/* next element */
57
+	tmp=eat_token(second, len-offset);
58
+	offset+=tmp-second;
59
+	third=eat_space(tmp, len-offset);
60
+	offset+=third-tmp;
61
+	if(third==tmp){
62
+		goto error;
63
+	}
64
+	*tmp=0; /* mark the end of the token */
65
+	fl->u.request.uri=second;
66
+	/*  last part */
67
+	tmp=eat_token(third,len-offset);
68
+	offset+=tmp-third;
69
+	if (tmp==third){
70
+		goto error;
71
+	}
72
+	if (! is_empty(tmp, len-offset)){		
73
+		goto error;
74
+	}
75
+	nl=eat_line(tmp,len-offset);
76
+	*tmp=0;
77
+	fl->u.request.version=third;
78
+	
79
+	return nl;
80
+
81
+error:
82
+	DPrint("ERROR: bad %s first line\n", 
83
+		(fl->type==SIP_REPLY)?"reply(status)":"request");
84
+error1:
85
+	fl->type=SIP_INVALID;
86
+	DPrint("ERROR: at line 0 char %d\n", offset);
87
+	/* skip  line */
88
+	nl=eat_line(buffer,len);
89
+	return nl;
90
+}
91
+
92
+
93
+/* returns integer field name type */
94
+int field_name(char *s)
95
+{
96
+	if ((strcmp(s, "Via")==0 )||(strcmp(s,"v")==0))
97
+		return  HDR_VIA;
98
+	if ((strcmp(s, "To")==0)||(strcmp(s,"t")==0))
99
+		return HDR_TO;
100
+	return HDR_OTHER;
101
+}
102
+
103
+
104
+
105
+
106
+/* returns pointer to next header line, and fill hdr_f */
107
+char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f)
108
+{
109
+	/* grammar (rfc822):
110
+		field = field-name ":" field-body CRLF
111
+		field-body = text [ CRLF SP field-body ]
112
+	   (CRLF in the field body must be removed)
113
+	*/
114
+
115
+	char* tmp;
116
+	char* nl;
117
+	char* body;
118
+	int offset;
119
+
120
+	if ((*buffer=='\n')||(*buffer=='\r')){
121
+		/* double crlf */
122
+		tmp=eat_line(buffer,len);
123
+		hdr_f->type=HDR_EOH;
124
+		return tmp;
125
+	}
126
+	
127
+	tmp=eat_token2(buffer, len, ':');
128
+	if ((tmp==buffer) || (tmp-buffer==len) ||
129
+		(is_empty(buffer, tmp-buffer-1))|| (*tmp!=':')){
130
+		hdr_f->type=HDR_ERROR;
131
+		goto error;
132
+	}
133
+	*tmp=0;
134
+	hdr_f->type=field_name(buffer);
135
+	body= ++tmp;
136
+	hdr_f->name=buffer;
137
+	offset=tmp-buffer;
138
+	/* get all the lines in this field  body */
139
+	do{
140
+		nl=eat_line(tmp, len-offset);
141
+		offset+=nl-tmp;
142
+		tmp=nl;
143
+	
144
+	}while( (*tmp==' ' ||  *tmp=='\t') && (offset<len) );
145
+	if (offset==len){
146
+		hdr_f->type=HDR_ERROR;
147
+		DPrint("ERROR: field body too  long\n");
148
+		goto error;
149
+	}
150
+	*(tmp-1)=0; /* should be an LF */
151
+	hdr_f->body=body;
152
+error:
153
+	return tmp;
154
+}
155
+
156
+
157
+
158
+char* parse_hostport(char* buf, char** host, short int* port)
159
+{
160
+	char *tmp;
161
+	char *invalid;
162
+	
163
+	*host=buf;
164
+	for(tmp=buf;(*tmp)&&(*tmp!=':');tmp++);
165
+	if (*tmp==0){
166
+		*port=0;
167
+	}else{
168
+		*tmp=0;
169
+		invalid=0;
170
+		*port=strtol(tmp+1, &invalid, 10);
171
+		if ((invalid!=0)&&(*invalid)){
172
+			DPrint("ERROR: hostport: trailing chars in port number: %s(%x)\n",
173
+					invalid, invalid);
174
+			/* report error? */
175
+		}
176
+	}
177
+	return *host;
178
+}
179
+
180
+
181
+
182
+/* parses a via body, returns next via (for compact vias) & fills vb,
183
+ * the buffer should be null terminated! */
184
+char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb)
185
+{
186
+	/* format: sent-proto sent-by  *(";" params) [comment] 
187
+
188
+	           sent-proto = name"/"version"/"transport
189
+		   sent-by    = host [":" port]
190
+		   
191
+	*/
192
+
193
+	char* tmp;
194
+	char *name,*version, *transport, *comment, *params, *hostport;
195
+	char * next_via;
196
+	char * host;
197
+	short int port;
198
+	int offset;
199
+	
200
+
201
+	name=version=transport=comment=params=hostport=next_via=host=0;
202
+	name=eat_space(buffer, len);
203
+	if (name-buffer==len) goto error;
204
+	offset=name-buffer;
205
+	tmp=name;
206
+
207
+	version=eat_token2(tmp,len-offset,'/');
208
+	if (version+1-buffer>=len) goto error;
209
+	*version=0;
210
+	version++;
211
+	offset+=version-tmp;
212
+	
213
+	transport=eat_token2(tmp,len-offset,'/');
214
+	if (transport+1-buffer>=len) goto error;
215
+	*transport=0;
216
+	transport++;
217
+	offset+=transport-tmp;
218
+	
219
+	tmp=eat_token(transport,len-offset);
220
+	if (tmp+1-buffer>=len) goto error;
221
+	*tmp=0;
222
+	tmp++;
223
+	offset+=tmp-transport;
224
+	
225
+	hostport=eat_space(tmp,len-offset);
226
+	if (hostport+1-buffer>=len) goto error;
227
+	offset+=hostport-tmp;
228
+
229
+	/* find end of hostport */
230
+ 	for(tmp=hostport; (tmp-buffer)<len &&
231
+			(*tmp!=' ')&&(*tmp!=';')&&(*tmp!=','); tmp++);
232
+	if (tmp-buffer<len){
233
+		switch (*tmp){
234
+			case ' ':
235
+				*tmp=0;
236
+				/*the rest is comment? */
237
+				if (tmp+1-buffer<len){
238
+					tmp++;
239
+					comment=tmp;
240
+					/* eat the comment */
241
+					for(;((tmp-buffer)<len)&&
242
+						(*tmp!=',');tmp++);
243
+					/* mark end of compact via (also end of comment)*/
244
+					if (tmp-buffer<len){
245
+						*tmp=0;
246
+					}else break;
247
+					/* eat space & ',' */
248
+					for(tmp=tmp+1;((tmp-buffer)<len)&&
249
+						(*tmp==' '|| *tmp==',');tmp++);
250
+					
251
+				}
252
+				break;
253
+
254
+			case ';':
255
+				*tmp=0;
256
+				if (tmp+1-buffer>=len) goto error;
257
+				tmp++;
258
+				params=tmp;
259
+				/* eat till end, first space  or ',' */
260
+				for(;((tmp-buffer)<len)&&
261
+					(*tmp!=' '&& *tmp!=',');tmp++);
262
+				if (tmp-buffer==len)  break;
263
+				if (*tmp==' '){
264
+					/* eat comment */
265
+					*tmp=0;
266
+					tmp++;
267
+					comment=tmp;
268
+					for(;((tmp-buffer)<len)&&
269
+						(*tmp!=',');tmp++);
270
+					if (tmp-buffer==len)  break;
271
+				}
272
+				/* mark end of via*/
273
+				*tmp=0;
274
+				/* eat space & ',' */
275
+				for(tmp=tmp+1;((tmp-buffer)<len)&&
276
+					(*tmp==' '|| *tmp==',');tmp++);
277
+				break;
278
+
279
+			case ',':
280
+				*tmp=0;
281
+				if (tmp+1-buffer<len){
282
+					/* eat space and ',' */
283
+					for(tmp=tmp+1; 
284
+						((tmp-buffer)<len)&&
285
+						(*tmp==' '|| *tmp==',');
286
+					   tmp++);
287
+				}
288
+		}
289
+	}
290
+	/* if we are not at the end of the body => we found another compact via */
291
+	if (tmp-buffer<len) next_via=tmp;
292
+	
293
+	/* parse hostport */
294
+	parse_hostport(hostport, &host, &port);
295
+	vb->name=name;
296
+	vb->version=version;
297
+	vb->transport=transport;
298
+	vb->host=host;
299
+	vb->port=port;
300
+	vb->params=params;
301
+	vb->comment=comment;
302
+	vb->next=next_via;
303
+	vb->error=VIA_PARSE_OK;
304
+
305
+	
306
+	/* tmp points to end of body or to next via (if compact)*/
307
+	
308
+	return tmp;
309
+
310
+error:
311
+	vb->error=VIA_PARSE_ERROR;
312
+	return tmp;
313
+}
314
+
0 315
new file mode 100644
... ...
@@ -0,0 +1,75 @@
0
+/*
1
+ * $Id$
2
+ */
3
+
4
+#ifndef msg_parser_h
5
+#define msg_parser_h
6
+
7
+
8
+#define SIP_REQUEST 1
9
+#define SIP_REPLY   2
10
+#define SIP_INVALID 0
11
+
12
+
13
+#define HDR_ERROR 0
14
+/* end of header */
15
+#define HDR_EOH   -1
16
+#define HDR_OTHER 1
17
+#define HDR_VIA   2
18
+#define HDR_TO    3
19
+
20
+#define VIA_PARSE_OK	1
21
+#define VIA_PARSE_ERROR -1
22
+
23
+#define SIP_VERSION	"SIP/2.0"
24
+
25
+
26
+struct msg_start{
27
+	int type;
28
+	union {
29
+		struct {
30
+			char* method;
31
+			char* uri;
32
+			char* version;
33
+		}request;
34
+		struct {
35
+			char* version;
36
+			char* status;
37
+			char* reason;
38
+		}reply;
39
+	}u;
40
+};
41
+
42
+struct hdr_field{   /* format: name':' body */
43
+	int type;
44
+	char* name;
45
+	char* body;
46
+};
47
+
48
+struct via_body{  /* format: name/version/transport host:port;params comment */
49
+	int error;
50
+	char* name;
51
+	char* version;
52
+	char* transport;
53
+	char* host;
54
+	int port;
55
+	char* params;
56
+	char* comment;
57
+	char* next; /* pointer to next via body string if compact via or null */
58
+};
59
+
60
+
61
+
62
+char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl);
63
+char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field*  hdr_f);
64
+int field_name(char *s);
65
+char* parse_hostport(char* buf, char** host, short int* port);
66
+char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb);
67
+
68
+
69
+
70
+
71
+
72
+#endif
73
+ 
74
+
0 75
new file mode 100644
... ...
@@ -0,0 +1,72 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * parser helper  functions
4
+ *
5
+ */
6
+
7
+#include  "parser_f.h"
8
+
9
+/* returns pointer to next line or end of buffer */
10
+char* eat_line(char* buffer, unsigned int len)
11
+{
12
+	char* nl;
13
+	char c;
14
+
15
+	for(nl=buffer;(nl<buffer+len)&& (*nl!='\r')&&(*nl!='\n') ;nl++);
16
+	c=*nl;
17
+	if (nl+1<buffer+len)  nl++;
18
+	if ((nl+1<buffer+len) &&
19
+			((c=='\r' && *nl=='\n')|| (c=='\n' && *nl=='\r'))) 
20
+		nl++;
21
+	return nl;
22
+}
23
+
24
+
25
+
26
+/* returns pointer to first non  white char or to the end  of the buffer */
27
+char* eat_space(char* buffer, unsigned int len)
28
+{
29
+	char* p;
30
+
31
+	for(p=buffer;(p<buffer+len)&& (*p==' ' || *p=='\t') ;p++);
32
+	return p;
33
+}
34
+
35
+
36
+
37
+/* returns pointer after the token (first whitespace char or CR/LF) */
38
+char* eat_token(char* buffer, unsigned int len)
39
+{
40
+	char *p;
41
+
42
+	for (p=buffer;(p<buffer+len)&&
43
+			(*p!=' ')&&(*p!='\t')&&(*p!='\n')&&(*p!='\r');
44
+		p++);
45
+	return p;
46
+}
47
+
48
+
49
+
50
+/* returns pointer after the token (first delim char or CR/LF) */
51
+char* eat_token2(char* buffer, unsigned int len, char delim)
52
+{
53
+	char *p;
54
+
55
+	for (p=buffer;(p<buffer+len)&&
56
+			(*p!=delim)&&(*p!='\n')&&(*p!='\r');
57
+		p++);
58
+	return p;
59
+}
60
+
61
+
62
+
63
+/* returns true if line started  at buffer contains only white space */
64
+int is_empty(char* buffer, unsigned int len)
65
+{
66
+	char *p;
67
+	
68
+	p=eat_space(buffer, len);
69
+	if ((p < buffer+len ) && (*p=='\r' || *p=='\n')) return 1;
70
+	return 0;
71
+}
0 72
new file mode 100644
... ...
@@ -0,0 +1,15 @@
0
+/* 
1
+ * $Id$
2
+ */
3
+
4
+#ifndef parser_f_h
5
+#define parser_f_h
6
+
7
+char* eat_line(char* buffer, unsigned int len);
8
+char* eat_space(char* buffer, unsigned int len);
9
+char* eat_token(char* buffer, unsigned int len);
10
+char* eat_token2(char* buffer, unsigned int len, char delim);
11
+int is_empty(char* buffer, unsigned int len);
12
+
13
+#endif
14
+ 
0 15
new file mode 100644
... ...
@@ -0,0 +1,230 @@
0
+/*
1
+ * $Id$
2
+ *
3
+ * SIP routing engine
4
+ *
5
+ */
6
+ 
7
+#include <sys/types.h>
8
+#include <regex.h>
9
+#include <netdb.h>
10
+#include <string.h>
11
+
12
+#include "route.h"
13
+#include "cfg_parser.h"
14
+#include "dprint.h"
15
+
16
+/* main routing list */
17
+struct route_elem* rlist=0;
18
+
19
+
20
+
21
+void free_re(struct route_elem* r)
22
+{
23
+	int i;
24
+	if (r){
25
+			regfree(&(r->method));
26
+			regfree(&(r->uri));
27
+			
28
+			if (r->host.h_name)      free(r->host.h_name);
29
+			if (r->host.h_aliases){
30
+				for (i=0; r->host.h_aliases[i]; i++)
31
+					free(r->host.h_aliases[i]);
32
+				free(r->host.h_aliases);
33
+			}
34
+			if (r->host.h_addr_list){
35
+				for (i=0; r->host.h_addr_list[i]; i++)
36
+					free(r->host.h_addr_list[i]);
37
+				free(r->host.h_addr_list);
38
+			}
39
+			free(r);
40
+	}
41
+}
42
+
43
+
44
+
45
+struct route_elem* init_re()
46
+{
47
+	struct route_elem* r;
48
+	r=(struct route_elem *) malloc(sizeof(struct route_elem));
49
+	if (r==0) return 0;
50
+	memset((void*)r, 0, sizeof (struct route_elem));
51
+	return r;
52
+}
53
+
54
+
55
+
56
+void push(struct route_elem* re, struct route_elem** head)
57
+{
58
+	struct route_elem *t;
59
+	re->next=0;
60
+	if (*head==0){
61
+		*head=re;
62
+		return;
63
+	}
64
+	for (t=*head; t->next;t=t->next);
65
+	t->next=re;
66
+}
67
+
68
+
69
+
70
+void clear_rlist(struct route_elem** rl)
71
+{
72
+	struct route_elem *t, *u;
73
+
74
+	if (*rl==0) return;
75
+	u=0;
76
+	for (t=*rl; t; u=t, t=t->next){
77
+		if (u) free_re(u);
78
+	}
79
+	*rl=0;
80
+}
81
+
82
+
83
+
84
+int add_rule(struct cfg_line* cl, struct route_elem** head)
85
+{
86
+	
87
+	struct route_elem* re;
88
+	struct hostent * he;
89
+	int ret;
90
+	int i,len, len2;
91
+
92
+
93
+	re=init_re();
94
+	if (re==0) return E_OUT_OF_MEM;
95
+
96
+	if (regcomp(&(re->method), cl->method, REG_EXTENDED|REG_NOSUB|REG_ICASE)){
97
+		DPrint("ERROR: bad re \"%s\"\n", cl->method);
98
+		ret=E_BAD_RE;
99
+		goto error;
100
+	}
101
+	if (regcomp(&(re->uri), cl->uri, REG_EXTENDED|REG_NOSUB|REG_ICASE) ){
102
+		DPrint("ERROR: bad re \"%s\"\n", cl->uri);
103
+		ret=E_BAD_RE;
104
+		goto error;
105
+	}
106
+
107
+	
108
+	he=gethostbyname(cl->address);
109
+	if (he==0){
110
+		DPrint("ERROR: cannot resolve \"%s\"\n", cl->address);
111
+		ret=E_BAD_ADDRESS;
112
+		goto error;
113
+	}
114
+	
115
+	/* start copying the host entry.. */
116
+	/* copy h_name */
117
+	len=strlen(he->h_name)+1;
118
+	re->host.h_name=(char*)malloc(len);
119
+	if (re->host.h_name) strncpy(re->host.h_name, he->h_name, len);
120
+	else{
121
+		ret=E_OUT_OF_MEM;
122
+		goto error;
123
+	}
124
+
125
+	/* copy h_aliases */
126
+	for (len=0;he->h_aliases[len];len++);
127
+	re->host.h_aliases=(char**)malloc(len+1);
128
+	if (re->host.h_aliases==0){
129
+		ret=E_OUT_OF_MEM;
130
+		goto error;
131
+	}
132
+	memset((void*)re->host.h_aliases, 0, sizeof(char*) * (len+1) );
133
+	for (i=0;i<len;i++){
134
+		len2=strlen(he->h_aliases[i])+1;
135
+		re->host.h_aliases[i]=(char*)malloc(len2);
136
+		if (re->host.h_aliases==0){
137
+			ret=E_OUT_OF_MEM;
138
+			goto error;
139
+		}
140
+		strncpy(re->host.h_aliases[i], he->h_aliases[i], len2);
141
+	}
142
+	/* copy h_addr_list */
143
+	for (len=0;he->h_addr_list[len];len++);
144
+	re->host.h_addr_list=(char**)malloc(len+1);
145
+	if (re->host.h_addr_list==0){
146
+		ret=E_OUT_OF_MEM;
147
+		goto error;
148
+	}
149
+	memset((void*)re->host.h_addr_list, 0, sizeof(char*) * (len+1) );
150
+	for (i=0;i<len;i++){
151
+		re->host.h_addr_list[i]=(char*)malloc(he->h_length+1);
152
+		if (re->host.h_addr_list==0){
153
+			ret=E_OUT_OF_MEM;
154
+			goto error;
155
+		}
156
+		memcpy(re->host.h_addr_list[i], he->h_addr_list[i], he->h_length+1);
157
+	}
158
+	/* copy h_addr_type & length */
159
+	re->host.h_addrtype=he->h_addrtype;
160
+	re->host.h_length=he->h_length;
161
+	/*finished hostent copy */
162
+
163
+	
164
+	
165
+	re->current_addr_idx=0;
166
+	re->ok=1;
167
+
168
+	push(re,head);
169
+	return 0;
170
+	
171
+error:
172
+		free_re(re);
173
+		return ret;
174
+}
175
+
176
+
177
+
178
+struct route_elem* route_match(char* method, char* uri, struct route_elem** rl)
179
+{
180
+	struct route_elem* t;
181
+	if (*rl==0){
182
+		DPrint("WARNING: empty routing table\n");
183
+		return 0;
184
+	}
185
+	for (t=*rl; t; t=t->next){
186
+		if (regexec(&(t->method), method, 0, 0, 0)==0){
187
+			/* we have a method mach !!! */
188
+			if (regexec(&(t->uri), uri, 0, 0, 0)==0){
189
+				/* we have a full match */
190
+				return t;
191
+			}
192
+		}
193
+	}
194
+	/* no match :( */
195
+	return 0;
196
+}
197
+
198
+
199
+
200
+/* debug function, prints main routing table */
201
+void print_rl()
202
+{
203
+	struct route_elem* t;
204
+	int i,j;
205
+
206
+	if (rlist==0){
207
+		DPrint("the routing table is emty\n");
208
+		return;
209
+	}
210
+	
211
+	for (t=rlist,i=0; t; i++, t=t->next){
212
+		DPrint("%2d.to=%s ; route ok=%d\n", i,
213
+				t->host.h_name, t->ok);
214
+		DPrint("   ips: ");
215
+		for (j=0; t->host.h_addr_list[j]; j++)
216
+			DPrint("%d.%d.%d.%d ",
217
+				(unsigned char) t->host.h_addr_list[j][0],
218
+				(unsigned char) t->host.h_addr_list[j][1],
219
+			    (unsigned char) t->host.h_addr_list[j][2],
220
+				(unsigned char) t->host.h_addr_list[j][3]
221
+				  );
222
+				
223
+		DPrint("\n   Statistics: tx=%d, errors=%d, tx_bytes=%d, idx=%d\n",
224
+				t->tx, t->errors, t->tx_bytes, t->current_addr_idx);
225
+	}
226
+
227
+}
228
+
229
+
0 230
new file mode 100644
... ...
@@ -0,0 +1,46 @@
0
+/*
1
+ * $Id$
2
+ */
3
+
4
+#ifndef route_h
5
+#define route_h
6
+
7
+#include <sys/types.h>
8
+#include <regex.h>
9
+#include <netdb.h>
10
+
11
+#include "cfg_parser.h"
12
+
13
+#define E_OUT_OF_MEM  -2
14
+#define E_BAD_RE      -3
15
+#define E_BAD_ADDRESS -4
16
+
17
+struct route_elem{
18
+	struct route_elem* next;
19
+	regex_t method;
20
+	regex_t uri;
21
+	struct hostent host;
22
+	int current_addr_idx;
23
+	int ok; /* set to 0 if an error was found sendig a pkt*/
24
+	/*counters*/
25
+	int errors;
26
+	int tx;
27
+	int tx_bytes;
28
+};
29
+
30
+/* main "routing table" */
31
+extern struct route_elem* rlist;
32
+
33
+
34
+void free_re(struct route_elem* re);
35
+struct route_elem* init_re();
36
+void push(struct route_elem* re, struct route_elem** head);
37
+void clear_rlist(struct route_elem** rl);
38
+int add_rule(struct cfg_line* cl, struct route_elem** head);
39
+struct route_elem* route_match(char* method, char* uri, struct route_elem** rl);void print_rl();
40
+
41
+
42
+
43
+
44
+
45
+#endif
0 46
new file mode 100644
... ...
@@ -0,0 +1,13 @@
0
+# $Id$
1
+
2
+# format:
3
+#  method_re   sip_uri_re      dest_host
4
+# (warning: re cannot contain space)
5
+
6
+^R.*        ^sip:.*@dorian.*   ekina.fokus.gmd.de        
7
+^INVITE     .*                 ape             # my laptop
8
+.           .                  192.168.46.55
9
+.*			.*andrei		   helios.fokus.gmd.de
10
+
11
+
12
+# end
0 13
new file mode 100644
... ...
@@ -0,0 +1,134 @@
0
+/*
1
+ * tst  
2
+ */
3
+
4
+#include <stdio.h>
5
+#include <string.h>
6
+
7
+#include "msg_parser.h"
8
+#include "dprint.h"
9
+
10
+#define BSIZE 1024
11
+char buf[BSIZE+1];
12
+
13
+void main()
14
+{
15
+	char* rest;
16
+	char* tmp;
17
+	char* first_via;
18
+	char* second_via;
19
+	struct msg_start fl;
20
+	struct hdr_field hf;
21
+	struct via_body vb1, vb2;
22
+
23
+	int len;
24
+	int offset;
25
+	int r;
26
+
27
+	while(!feof(stdin)){
28
+		len=fread(buf,1,BSIZE,stdin);
29
+		buf[len+1]=0;
30
+		printf("read <%s>(%d)\n",buf,strlen(buf));
31
+		fflush(stdin);
32
+	
33
+		/* eat crlf from the beginning */
34
+		for (tmp=buf; (*tmp=='\n' || *tmp=='\r')&&
35
+				tmp-buf < len ; tmp++);
36
+		offset=tmp-buf;
37
+		rest=parse_first_line(tmp, len-offset, &fl);
38
+		offset+=rest-tmp;
39
+		tmp=rest;
40
+		switch(fl.type){
41
+			case SIP_INVALID:
42
+				printf("invalid message\n");
43
+				break;
44
+			case SIP_REQUEST:
45
+				printf("SIP Request:\n");
46
+				printf(" method:  <%s>\n",fl.u.request.method);
47
+				printf(" uri:     <%s>\n",fl.u.request.uri);
48
+				printf(" version: <%s>\n",fl.u.request.version);
49
+				break;
50
+			case SIP_REPLY:
51
+				printf("SIP Reply  (status):\n");
52
+				printf(" version: <%s>\n",fl.u.reply.version);
53
+				printf(" status:  <%s>\n",fl.u.reply.status);
54
+				printf(" reason:  <%s>\n",fl.u.reply.reason);
55
+				break;
56
+			default:
57
+				printf("unknown type %d\n",fl.type);
58
+		}
59
+		
60
+		/*find first Via: */
61
+		hf.type=HDR_ERROR;
62
+		first_via=0;
63
+		second_via=0;
64
+		do{
65
+			rest=get_hdr_field(tmp, len-offset, &hf);
66
+			offset+=rest-tmp;
67
+			tmp=rest;
68
+			switch (hf.type){
69
+				case HDR_ERROR:
70
+					DPrint("ERROR: bad header  field\n");
71
+					goto  error;
72
+				case HDR_EOH: 
73
+					goto eoh;
74
+				case HDR_VIA:
75
+					if (first_via==0) first_via=hf.body;
76
+					else if (second_via==0) second_via=hf.body;
77
+					break;
78
+			}
79
+			printf("header field type %d, name=<%s>, body=<%s>\n",
80
+				hf.type, hf.name, hf.body);
81
+
82
+		
83
+		}while(hf.type!=HDR_EOH && rest-buf < len);
84
+
85
+	eoh:
86
+		/* replace cr/lf with space in first via */
87
+		for (tmp=first_via;(first_via) && (*tmp);tmp++)
88
+			if ((*tmp=='\r')||(*tmp=='\n'))	*tmp=' ';
89
+
90
+		printf("first via: <%s>\n", first_via);
91
+		tmp=parse_via_body(first_via, strlen(first_via), &vb1);
92
+		if (vb1.error!=VIA_PARSE_OK){
93
+			DPrint("ERROR: parsing via body: %s\n", first_via);
94
+			goto error;
95
+		}
96
+		/* compact via */
97
+		if (vb1.next) second_via=vb1.next;
98
+		if (second_via) {
99
+			tmp=parse_via_body(second_via, strlen(second_via), &vb2);
100
+			if (vb2.error!=VIA_PARSE_OK){
101
+				DPrint("ERROR: parsing via body: %s\n", second_via);
102
+				goto error;
103
+			}
104
+		}
105
+		
106
+		/* dump parsed data */
107
+		printf(" first  via: <%s/%s/%s> <%s:%d>",
108
+				vb1.name, vb1.version, vb1.transport, vb1.host, vb1.port);
109
+		if (vb1.params) printf(";<%s>", vb1.params);
110
+		if (vb1.comment) printf(" <%s>", vb1.comment);
111
+		printf ("\n");
112
+		if (second_via){
113
+			printf(" second via: <%s/%s/%s> <%s:%d>",
114
+					vb2.name, vb2.version, vb2.transport, vb2.host, vb2.port);
115
+			if (vb2.params) printf(";<%s>", vb2.params);
116
+			if (vb2.comment) printf(" <%s>", vb2.comment);
117
+			printf ("\n");
118
+		}
119
+
120
+		
121
+
122
+	error:
123
+		/* find endof msg */
124
+		printf("rest:(buffer=%x, rest=%x)\n%s\n.\n",buf,rest,rest);
125
+
126
+		for (r=0; r<len+1;r++)
127
+			printf("%02x ", buf[r]);
128
+		printf("\n*rest=%02x\n",*rest);
129
+		
130
+	}
131
+}
132
+				
133
+