23 | 23 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,137 @@ |
1 |
+/* |
|
2 |
+ * $Id$ |
|
3 |
+ */ |
|
4 |
+ |
|
5 |
+ |
|
6 |
+#include <string.h> |
|
7 |
+ |
|
8 |
+#include "forward.h" |
|
9 |
+#include "msg_parser.h" |
|
10 |
+#include "route.h" |
|
11 |
+#include "dprint.h" |
|
12 |
+ |
|
13 |
+#define MAX_VIA_LINE_SIZE 240 |
|
14 |
+#define MAX_RECEIVED_SIZE 57 |
|
15 |
+ |
|
16 |
+#define our_address "dorian.fokus.gmd.de" |
|
17 |
+#define our_port 1234 |
|
18 |
+ |
|
19 |
+ |
|
20 |
+int forward_request(char * orig, char* buf, |
|
21 |
+ unsigned int len, |
|
22 |
+ struct sip_msg* msg, |
|
23 |
+ struct route_elem* re) |
|
24 |
+{ |
|
25 |
+ unsigned int new_len, via_len, received_len; |
|
26 |
+ char line_buf[MAX_VIA_LINE_SIZE]; |
|
27 |
+ char received_buf[MAX_RECEIVED_SIZE]; |
|
28 |
+ char* new_buf; |
|
29 |
+ int offset, s_offset, size; |
|
30 |
+ |
|
31 |
+ received_len=0; |
|
32 |
+ printf("0\n"); |
|
33 |
+ |
|
34 |
+ via_len=snprintf(line_buf, MAX_VIA_LINE_SIZE, "Via: SIP/2.0/UDP %s:%d\r\n", |
|
35 |
+ our_address, our_port); |
|
36 |
+ /* check if received needs to be added */ |
|
37 |
+ /* if check_address(source_ip, msg->via1.host) */ |
|
38 |
+ received_len=snprintf(received_buf, MAX_RECEIVED_SIZE, ";received=%s", |
|
39 |
+ "10.11.12.13"); |
|
40 |
+ |
|
41 |
+ new_len=len+via_len+received_len; |
|
42 |
+ new_buf=(char*)malloc(new_len+1); |
|
43 |
+ if (new_buf==0){ |
|
44 |
+ DPrint("ERROR: forward_request: out of memory\n"); |
|
45 |
+ goto error; |
|
46 |
+ } |
|
47 |
+ printf("1\n"); |
|
48 |
+ /* copy msg till first via */ |
|
49 |
+ offset=s_offset=0; |
|
50 |
+ size=msg->via1.hdr-buf; |
|
51 |
+ memcpy(new_buf, orig, size); |
|
52 |
+ offset+=size; |
|
53 |
+ s_offset+=size; |
|
54 |
+ printf("2\n"); |
|
55 |
+ /* add our via */ |
|
56 |
+ memcpy(new_buf+offset, line_buf, via_len); |
|
57 |
+ offset+=via_len; |
|
58 |
+ printf("3\n"); |
|
59 |
+ /* modify original via if neccesarry (received=...)*/ |
|
60 |
+ if (received_len){ |
|
61 |
+ if (msg->via1.params){ |
|
62 |
+ size= msg->via1.params-msg->via1.hdr-1; /*compensate for ';' */ |
|
63 |
+ }else{ |
|
64 |
+ size= msg->via1.host-msg->via1.hdr+strlen(msg->via1.host); |
|
65 |
+ if (msg->via1.port!=0){ |
|
66 |
+ size+=strlen(msg->via1.hdr+size+1); |
|
67 |
+ } |
|
68 |
+ } |
|
69 |
+ memcpy(new_buf+offset, orig+s_offset, |
|
70 |
+ size); |
|
71 |
+ offset+=size; |
|
72 |
+ s_offset+=size; |
|
73 |
+ printf("4\n"); |
|
74 |
+ memcpy(new_buf+offset, received_buf, received_len); |
|
75 |
+ printf("5\n"); |
|
76 |
+ offset+=received_len; |
|
77 |
+ } |
|
78 |
+ /* copy the rest of the msg */ |
|
79 |
+ memcpy(new_buf+offset, orig+s_offset, len-s_offset); |
|
80 |
+ printf("6\n"); |
|
81 |
+ new_buf[new_len]=0; |
|
82 |
+ |
|
83 |
+ /* send it! */ |
|
84 |
+ printf("Sending:\n%s.\n", new_buf); |
|
85 |
+ |
|
86 |
+ return 0; |
|
87 |
+error: |
|
88 |
+ return -1; |
|
89 |
+ |
|
90 |
+} |
|
91 |
+ |
|
92 |
+ |
|
93 |
+ |
|
94 |
+/* removes first via & sends msg to the second */ |
|
95 |
+int forward_reply(char * orig, char* buf, |
|
96 |
+ unsigned int len, |
|
97 |
+ struct sip_msg* msg) |
|
98 |
+{ |
|
99 |
+ |
|
100 |
+ |
|
101 |
+ unsigned int new_len, via_len; |
|
102 |
+ char* new_buf; |
|
103 |
+ int offset, s_offset, size; |
|
104 |
+ |
|
105 |
+ |
|
106 |
+ /* we must remove first via */ |
|
107 |
+ via_len=msg->via1.size; |
|
108 |
+ size=msg->via1.hdr-buf; |
|
109 |
+ if (msg->via1.next){ |
|
110 |
+ via_len-=strlen(msg->via1.hdr)+1; /* +1 from ':' */ |
|
111 |
+ size+=strlen(msg->via1.hdr)+1; |
|
112 |
+ } |
|
113 |
+ new_len=len-size; |
|
114 |
+ printf("r1\n"); |
|
115 |
+ new_buf=(char*)malloc(new_len); |
|
116 |
+ if (new_buf==0){ |
|
117 |
+ DPrint("ERROR: forward_reply: out of memory\n"); |
|
118 |
+ goto error; |
|
119 |
+ } |
|
120 |
+ printf("r2\n"); |
|
121 |
+ memcpy(new_buf, orig, size); |
|
122 |
+ offset=size; |
|
123 |
+ s_offset=size+via_len; |
|
124 |
+ printf("r3\n"); |
|
125 |
+ memcpy(new_buf+offset,orig+s_offset, len-s_offset); |
|
126 |
+ printf("r4\n"); |
|
127 |
+ /* send it! */ |
|
128 |
+ printf("Sending: to %s:%d, \n%s.\n", |
|
129 |
+ msg->via2.host, |
|
130 |
+ (unsigned short)msg->via2.port, |
|
131 |
+ new_buf); |
|
132 |
+ |
|
133 |
+ return 0; |
|
134 |
+ |
|
135 |
+error: |
|
136 |
+ return -1; |
|
137 |
+} |
0 | 138 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,18 @@ |
1 |
+/* |
|
2 |
+ * $Id$ |
|
3 |
+ */ |
|
4 |
+ |
|
5 |
+ |
|
6 |
+#ifndef forward_h |
|
7 |
+#define forward_h |
|
8 |
+ |
|
9 |
+#include "msg_parser.h" |
|
10 |
+#include "route.h" |
|
11 |
+ |
|
12 |
+int forward_request(char * orig, char* buf, unsigned int len, |
|
13 |
+ struct sip_msg* msg, struct route_elem* re); |
|
14 |
+ |
|
15 |
+int forward_reply(char * orig, char* buf, unsigned int len, |
|
16 |
+ struct sip_msg* msg); |
|
17 |
+ |
|
18 |
+#endif |
... | ... |
@@ -12,6 +12,24 @@ |
12 | 12 |
#define CFG_FILE "./sip_router.cfg" |
13 | 13 |
|
14 | 14 |
|
15 |
+/* debuging function */ |
|
16 |
+ |
|
17 |
+void receive_stdin_loop() |
|
18 |
+{ |
|
19 |
+ #define BSIZE 1024 |
|
20 |
+ char buf[BSIZE+1]; |
|
21 |
+ int len; |
|
22 |
+ |
|
23 |
+ while(1){ |
|
24 |
+ len=fread(buf,1,BSIZE,stdin); |
|
25 |
+ buf[len+1]=0; |
|
26 |
+ receive_msg(buf, len); |
|
27 |
+ printf("-------------------------\n"); |
|
28 |
+ } |
|
29 |
+} |
|
30 |
+ |
|
31 |
+ |
|
32 |
+ |
|
15 | 33 |
int main(int argc, char** argv) |
16 | 34 |
{ |
17 | 35 |
|
... | ... |
@@ -40,10 +58,12 @@ int main(int argc, char** argv) |
40 | 58 |
|
41 | 59 |
|
42 | 60 |
|
43 |
- /* start other processes/threads ? */ |
|
61 |
+ /* start/init other processes/threads ? */ |
|
44 | 62 |
|
45 | 63 |
/* receive loop */ |
46 | 64 |
|
65 |
+ receive_stdin_loop(); |
|
66 |
+ |
|
47 | 67 |
|
48 | 68 |
error: |
49 | 69 |
return -1; |
... | ... |
@@ -5,14 +5,18 @@ |
5 | 5 |
* |
6 | 6 |
*/ |
7 | 7 |
|
8 |
-#include "msg_parser.h" |
|
9 |
-#include "string.h" |
|
8 |
+#include <string.h> |
|
10 | 9 |
|
10 |
+#include "msg_parser.h" |
|
11 | 11 |
#include "parser_f.h" |
12 | 12 |
#include "dprint.h" |
13 | 13 |
|
14 | 14 |
|
15 | 15 |
|
16 |
+#define DEBUG |
|
17 |
+ |
|
18 |
+ |
|
19 |
+ |
|
16 | 20 |
/* parses the first line, returns pointer to next line & fills fl; |
17 | 21 |
also modifies buffer (to avoid extra copy ops) */ |
18 | 22 |
char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl) |
... | ... |
@@ -313,3 +317,145 @@ error: |
313 | 317 |
return tmp; |
314 | 318 |
} |
315 | 319 |
|
320 |
+ |
|
321 |
+ |
|
322 |
+/* returns 0 if ok, -1 for errors */ |
|
323 |
+int parse_msg(char* buf, unsigned int len, struct sip_msg* msg) |
|
324 |
+{ |
|
325 |
+ |
|
326 |
+ char *tmp, *bar; |
|
327 |
+ char* rest; |
|
328 |
+ char* first_via; |
|
329 |
+ char* second_via; |
|
330 |
+ struct msg_start fl; |
|
331 |
+ struct hdr_field hf; |
|
332 |
+ struct via_body vb1, vb2; |
|
333 |
+ int offset; |
|
334 |
+ int r; |
|
335 |
+ |
|
336 |
+ |
|
337 |
+ /* eat crlf from the beginning */ |
|
338 |
+ for (tmp=buf; (*tmp=='\n' || *tmp=='\r')&& |
|
339 |
+ tmp-buf < len ; tmp++); |
|
340 |
+ offset=tmp-buf; |
|
341 |
+ rest=parse_first_line(tmp, len-offset, &fl); |
|
342 |
+ offset+=rest-tmp; |
|
343 |
+ tmp=rest; |
|
344 |
+ switch(fl.type){ |
|
345 |
+ case SIP_INVALID: |
|
346 |
+ DPrint("invalid message\n"); |
|
347 |
+ goto error; |
|
348 |
+ break; |
|
349 |
+ case SIP_REQUEST: |
|
350 |
+ DPrint("SIP Request:\n"); |
|
351 |
+ DPrint(" method: <%s>\n",fl.u.request.method); |
|
352 |
+ DPrint(" uri: <%s>\n",fl.u.request.uri); |
|
353 |
+ DPrint(" version: <%s>\n",fl.u.request.version); |
|
354 |
+ break; |
|
355 |
+ case SIP_REPLY: |
|
356 |
+ DPrint("SIP Reply (status):\n"); |
|
357 |
+ DPrint(" version: <%s>\n",fl.u.reply.version); |
|
358 |
+ DPrint(" status: <%s>\n",fl.u.reply.status); |
|
359 |
+ DPrint(" reason: <%s>\n",fl.u.reply.reason); |
|
360 |
+ break; |
|
361 |
+ default: |
|
362 |
+ DPrint("unknown type %d\n",fl.type); |
|
363 |
+ } |
|
364 |
+ |
|
365 |
+ /*find first Via: */ |
|
366 |
+ hf.type=HDR_ERROR; |
|
367 |
+ first_via=0; |
|
368 |
+ second_via=0; |
|
369 |
+ do{ |
|
370 |
+ rest=get_hdr_field(tmp, len-offset, &hf); |
|
371 |
+ offset+=rest-tmp; |
|
372 |
+ switch (hf.type){ |
|
373 |
+ case HDR_ERROR: |
|
374 |
+ DPrint("ERROR: bad header field\n"); |
|
375 |
+ goto error; |
|
376 |
+ case HDR_EOH: |
|
377 |
+ goto skip; |
|
378 |
+ case HDR_VIA: |
|
379 |
+ if (first_via==0){ |
|
380 |
+ first_via=hf.body; |
|
381 |
+ vb1.hdr=hf.name; |
|
382 |
+ /* replace cr/lf with space in first via */ |
|
383 |
+ for (bar=first_via;(first_via) && (*bar);bar++) |
|
384 |
+ if ((*bar=='\r')||(*bar=='\n')) *bar=' '; |
|
385 |
+ #ifdef DEBUG |
|
386 |
+ printf("first via: <%s>\n", first_via); |
|
387 |
+ #endif |
|
388 |
+ bar=parse_via_body(first_via, strlen(first_via), &vb1); |
|
389 |
+ if (vb1.error!=VIA_PARSE_OK){ |
|
390 |
+ DPrint("ERROR: parsing via body: %s\n", first_via); |
|
391 |
+ goto error; |
|
392 |
+ } |
|
393 |
+ vb1.size=bar-first_via+first_via-vb1.hdr; |
|
394 |
+ |
|
395 |
+ /* compact via */ |
|
396 |
+ if (vb1.next) { |
|
397 |
+ second_via=vb1.next; |
|
398 |
+ /* not interested in the rest of the header */ |
|
399 |
+ goto skip; |
|
400 |
+ } |
|
401 |
+ }else if (second_via==0){ |
|
402 |
+ second_via=hf.body; |
|
403 |
+ vb2.hdr=hf.name; |
|
404 |
+ goto skip; |
|
405 |
+ } |
|
406 |
+ break; |
|
407 |
+ } |
|
408 |
+ #ifdef DEBUG |
|
409 |
+ printf("header field type %d, name=<%s>, body=<%s>\n", |
|
410 |
+ hf.type, hf.name, hf.body); |
|
411 |
+ #endif |
|
412 |
+ tmp=rest; |
|
413 |
+ }while(hf.type!=HDR_EOH && rest-buf < len); |
|
414 |
+ |
|
415 |
+skip: |
|
416 |
+ /* replace cr/lf with space in the second via */ |
|
417 |
+ for (tmp=second_via;(second_via) && (*tmp);tmp++) |
|
418 |
+ if ((*tmp=='\r')||(*tmp=='\n')) *tmp=' '; |
|
419 |
+ |
|
420 |
+ if (second_via) { |
|
421 |
+ tmp=parse_via_body(second_via, strlen(second_via), &vb2); |
|
422 |
+ if (vb2.error!=VIA_PARSE_OK){ |
|
423 |
+ DPrint("ERROR: parsing via body: %s\n", second_via); |
|
424 |
+ goto error; |
|
425 |
+ } |
|
426 |
+ vb2.size=tmp-second_via; |
|
427 |
+ if (vb2.hdr) vb2.size+=second_via-vb2.hdr; |
|
428 |
+ } |
|
429 |
+ |
|
430 |
+ |
|
431 |
+#ifdef DEBUG |
|
432 |
+ /* dump parsed data */ |
|
433 |
+ printf(" first via: <%s/%s/%s> <%s:%d>", |
|
434 |
+ vb1.name, vb1.version, vb1.transport, vb1.host, vb1.port); |
|
435 |
+ if (vb1.params) printf(";<%s>", vb1.params); |
|
436 |
+ if (vb1.comment) printf(" <%s>", vb1.comment); |
|
437 |
+ printf ("\n"); |
|
438 |
+ if (second_via){ |
|
439 |
+ printf(" second via: <%s/%s/%s> <%s:%d>", |
|
440 |
+ vb2.name, vb2.version, vb2.transport, vb2.host, vb2.port); |
|
441 |
+ if (vb2.params) printf(";<%s>", vb2.params); |
|
442 |
+ if (vb2.comment) printf(" <%s>", vb2.comment); |
|
443 |
+ printf ("\n"); |
|
444 |
+ } |
|
445 |
+#endif |
|
446 |
+ |
|
447 |
+ /* copy data into msg */ |
|
448 |
+ memcpy(&(msg->first_line), &fl, sizeof(struct msg_start)); |
|
449 |
+ memcpy(&(msg->via1), &vb1, sizeof(struct via_body)); |
|
450 |
+ memcpy(&(msg->via2), &vb2, sizeof(struct via_body)); |
|
451 |
+ |
|
452 |
+#ifdef DEBUG |
|
453 |
+ printf ("exiting parse_msg\n"); |
|
454 |
+#endif |
|
455 |
+ |
|
456 |
+ return 0; |
|
457 |
+ |
|
458 |
+error: |
|
459 |
+ return -1; |
|
460 |
+} |
|
461 |
+ |
... | ... |
@@ -48,6 +48,7 @@ struct hdr_field{ /* format: name':' body */ |
48 | 48 |
|
49 | 49 |
struct via_body{ /* format: name/version/transport host:port;params comment */ |
50 | 50 |
int error; |
51 |
+ char *hdr; /* contains "Via" or "v" */ |
|
51 | 52 |
char* name; |
52 | 53 |
char* version; |
53 | 54 |
char* transport; |
... | ... |
@@ -55,9 +56,16 @@ struct via_body{ /* format: name/version/transport host:port;params comment */ |
55 | 56 |
int port; |
56 | 57 |
char* params; |
57 | 58 |
char* comment; |
59 |
+ int size; /* full size, including hdr */ |
|
58 | 60 |
char* next; /* pointer to next via body string if compact via or null */ |
59 | 61 |
}; |
60 | 62 |
|
63 |
+struct sip_msg{ |
|
64 |
+ struct msg_start first_line; |
|
65 |
+ struct via_body via1; |
|
66 |
+ struct via_body via2; |
|
67 |
+}; |
|
68 |
+ |
|
61 | 69 |
|
62 | 70 |
|
63 | 71 |
char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl); |
... | ... |
@@ -65,11 +73,8 @@ char* get_hdr_field(char *buffer, unsigned int len, struct hdr_field* hdr_f); |
65 | 73 |
int field_name(char *s); |
66 | 74 |
char* parse_hostport(char* buf, char** host, short int* port); |
67 | 75 |
char* parse_via_body(char* buffer,unsigned int len, struct via_body * vb); |
68 |
- |
|
69 |
- |
|
76 |
+int parse_msg(char* buf, unsigned int len, struct sip_msg* msg); |
|
70 | 77 |
|
71 | 78 |
|
72 | 79 |
|
73 | 80 |
#endif |
74 |
- |
|
75 |
- |
76 | 81 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,80 @@ |
1 |
+/* |
|
2 |
+ *$Id$ |
|
3 |
+ */ |
|
4 |
+ |
|
5 |
+#include <string.h> |
|
6 |
+ |
|
7 |
+#include "receive.h" |
|
8 |
+#include "dprint.h" |
|
9 |
+#include "route.h" |
|
10 |
+#include "msg_parser.h" |
|
11 |
+#include "forward.h" |
|
12 |
+ |
|
13 |
+ |
|
14 |
+int receive_msg(char* buf, unsigned int len) |
|
15 |
+{ |
|
16 |
+ struct sip_msg msg; |
|
17 |
+ struct route_elem *re; |
|
18 |
+ char * orig; |
|
19 |
+ |
|
20 |
+ /* make a copy of the message */ |
|
21 |
+ orig=(char*) malloc(len); |
|
22 |
+ if (orig==0){ |
|
23 |
+ DPrint("ERROR: memory allocation failure\n"); |
|
24 |
+ goto error; |
|
25 |
+ } |
|
26 |
+ memcpy(orig, buf, len); |
|
27 |
+ |
|
28 |
+ if (parse_msg(buf,len, &msg)!=0){ |
|
29 |
+ goto error; |
|
30 |
+ } |
|
31 |
+ |
|
32 |
+ if (msg.first_line.type==SIP_REQUEST){ |
|
33 |
+ /* sanity checks */ |
|
34 |
+ if (msg.via1.error!=VIA_PARSE_OK){ |
|
35 |
+ /* no via, send back error ? */ |
|
36 |
+ goto skip; |
|
37 |
+ } |
|
38 |
+ /* check if neccesarry to add receive? */ |
|
39 |
+ |
|
40 |
+ /* find route */ |
|
41 |
+ re=route_match( msg.first_line.u.request.method, |
|
42 |
+ msg.first_line.u.request.uri, |
|
43 |
+ &rlist |
|
44 |
+ ); |
|
45 |
+ if (re==0){ |
|
46 |
+ /* no route found, send back error msg? */ |
|
47 |
+ DPrint("WARNING: no route found!\n"); |
|
48 |
+ goto skip; |
|
49 |
+ } |
|
50 |
+ re->tx++; |
|
51 |
+ /* send msg */ |
|
52 |
+ forward_request(orig, buf, len, &msg, re); |
|
53 |
+ DPrint(" found route to: %s\n", re->host.h_name); |
|
54 |
+ }else if (msg.first_line.type==SIP_REPLY){ |
|
55 |
+ /* sanity checks */ |
|
56 |
+ if (msg.via1.error!=VIA_PARSE_OK){ |
|
57 |
+ /* no via, send back error ? */ |
|
58 |
+ goto skip; |
|
59 |
+ } |
|
60 |
+ if (msg.via2.error!=VIA_PARSE_OK){ |
|
61 |
+ /* no second via => error? */ |
|
62 |
+ goto skip; |
|
63 |
+ } |
|
64 |
+ /* check if via1 == us */ |
|
65 |
+ |
|
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 |
+ ); |
|
72 |
+ } |
|
73 |
+skip: |
|
74 |
+ free(orig); |
|
75 |
+ return 0; |
|
76 |
+error: |
|
77 |
+ return -1; |
|
78 |
+ |
|
79 |
+} |
|
80 |
+ |