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