1 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,912 +0,0 @@ |
1 |
-/* |
|
2 |
- * $Id$ |
|
3 |
- * |
|
4 |
- * sip msg. header proxy parser |
|
5 |
- * |
|
6 |
- */ |
|
7 |
- |
|
8 |
-#include <string.h> |
|
9 |
-#include <stdlib.h> |
|
10 |
- |
|
11 |
-#include "msg_parser.h" |
|
12 |
-#include "parser_f.h" |
|
13 |
-#include "ut.h" |
|
14 |
-#include "error.h" |
|
15 |
-#include "dprint.h" |
|
16 |
-#include "data_lump_rpl.h" |
|
17 |
-#include "mem/mem.h" |
|
18 |
- |
|
19 |
-#ifdef DEBUG_DMALLOC |
|
20 |
-#include <mem/dmalloc.h> |
|
21 |
-#endif |
|
22 |
- |
|
23 |
- |
|
24 |
- |
|
25 |
- |
|
26 |
- |
|
27 |
-/* parses the first line, returns pointer to next line & fills fl; |
|
28 |
- also modifies buffer (to avoid extra copy ops) */ |
|
29 |
-char* parse_first_line(char* buffer, unsigned int len, struct msg_start * fl) |
|
30 |
-{ |
|
31 |
- |
|
32 |
- char *tmp; |
|
33 |
- char* second; |
|
34 |
- char* third; |
|
35 |
- char* nl; |
|
36 |
- int offset; |
|
37 |
- /* int l; */ |
|
38 |
- char* end; |
|
39 |
- char s1,s2,s3; |
|
40 |
- char *prn; |
|
41 |
- unsigned int t; |
|
42 |
- |
|
43 |
- /* grammar: |
|
44 |
- request = method SP uri SP version CRLF |
|
45 |
- response = version SP status SP reason CRLF |
|
46 |
- (version = "SIP/2.0") |
|
47 |
- */ |
|
48 |
- |
|
49 |
- |
|
50 |
- end=buffer+len; |
|
51 |
- /* see if it's a reply (status) */ |
|
52 |
- |
|
53 |
- /* jku -- parse well-known methods */ |
|
54 |
- |
|
55 |
- /* drop messages which are so short they are for sure useless; |
|
56 |
- utilize knowledge of minimum size in parsing the first |
|
57 |
- token |
|
58 |
- */ |
|
59 |
- if (len <=16 ) { |
|
60 |
- LOG(L_INFO, "ERROR: parse_first_line: message too short: %d\n", len); |
|
61 |
- goto error1; |
|
62 |
- } |
|
63 |
- |
|
64 |
- tmp=buffer; |
|
65 |
- /* is it perhaps a reply, ie does it start with "SIP...." ? */ |
|
66 |
- if ( (*tmp=='S' || *tmp=='s') && |
|
67 |
- strncasecmp( tmp+1, SIP_VERSION+1, SIP_VERSION_LEN-1)==0 && |
|
68 |
- (*(tmp+SIP_VERSION_LEN)==' ')) { |
|
69 |
- fl->type=SIP_REPLY; |
|
70 |
- fl->u.reply.version.len=SIP_VERSION_LEN; |
|
71 |
- tmp=buffer+SIP_VERSION_LEN; |
|
72 |
- } else IFISMETHOD( INVITE, 'I' ) |
|
73 |
- else IFISMETHOD( CANCEL, 'C') |
|
74 |
- else IFISMETHOD( ACK, 'A' ) |
|
75 |
- else IFISMETHOD( BYE, 'B' ) |
|
76 |
- /* if you want to add another method XXX, include METHOD_XXX in |
|
77 |
- H-file (this is the value which you will take later in |
|
78 |
- processing and define XXX_LEN as length of method name; |
|
79 |
- then just call IFISMETHOD( XXX, 'X' ) ... 'X' is the first |
|
80 |
- latter; everything must be capitals |
|
81 |
- */ |
|
82 |
- else { |
|
83 |
- /* neither reply, nor any of known method requests, |
|
84 |
- let's believe it is an unknown method request |
|
85 |
- */ |
|
86 |
- tmp=eat_token_end(buffer,buffer+len); |
|
87 |
- if ((tmp==buffer)||(tmp>=end)){ |
|
88 |
- LOG(L_INFO, "ERROR:parse_first_line: empty or bad first line\n"); |
|
89 |
- goto error1; |
|
90 |
- } |
|
91 |
- if (*tmp!=' ') { |
|
92 |
- LOG(L_INFO, "ERROR:parse_first_line: method not followed by SP\n"); |
|
93 |
- goto error1; |
|
94 |
- } |
|
95 |
- fl->type=SIP_REQUEST; |
|
96 |
- fl->u.request.method_value=METHOD_OTHER; |
|
97 |
- fl->u.request.method.len=tmp-buffer; |
|
98 |
- } |
|
99 |
- |
|
100 |
- |
|
101 |
- /* identifying type of message over now; |
|
102 |
- tmp points at space after; go ahead */ |
|
103 |
- |
|
104 |
- fl->u.request.method.s=buffer; /* store ptr to first token */ |
|
105 |
- (*tmp)=0; /* mark the 1st token end */ |
|
106 |
- second=tmp+1; /* jump to second token */ |
|
107 |
- offset=second-buffer; |
|
108 |
- |
|
109 |
-/* EoJku */ |
|
110 |
- |
|
111 |
- /* next element */ |
|
112 |
- tmp=eat_token_end(second, second+len-offset); |
|
113 |
- if (tmp>=end){ |
|
114 |
- goto error; |
|
115 |
- } |
|
116 |
- offset+=tmp-second; |
|
117 |
- third=eat_space_end(tmp, tmp+len-offset); |
|
118 |
- offset+=third-tmp; |
|
119 |
- if ((third==tmp)||(tmp>=end)){ |
|
120 |
- goto error; |
|
121 |
- } |
|
122 |
- *tmp=0; /* mark the end of the token */ |
|
123 |
- fl->u.request.uri.s=second; |
|
124 |
- fl->u.request.uri.len=tmp-second; |
|
125 |
- |
|
126 |
- /* jku: parse status code */ |
|
127 |
- if (fl->type==SIP_REPLY) { |
|
128 |
- if (fl->u.request.uri.len!=3) { |
|
129 |
- LOG(L_INFO, "ERROR:parse_first_line: len(status code)!=3: %s\n", |
|
130 |
- second ); |
|
131 |
- goto error; |
|
132 |
- } |
|
133 |
- s1=*second; s2=*(second+1);s3=*(second+2); |
|
134 |
- if (s1>='0' && s1<='9' && |
|
135 |
- s2>='0' && s2<='9' && |
|
136 |
- s3>='0' && s3<='9' ) { |
|
137 |
- fl->u.reply.statuscode=(s1-'0')*100+10*(s2-'0')+(s3-'0'); |
|
138 |
- } else { |
|
139 |
- LOG(L_INFO, "ERROR:parse_first_line: status_code non-numerical: %s\n", |
|
140 |
- second ); |
|
141 |
- goto error; |
|
142 |
- } |
|
143 |
- } |
|
144 |
- /* EoJku */ |
|
145 |
- |
|
146 |
- /* last part: for a request it must be the version, for a reply |
|
147 |
- * it can contain almost anything, including spaces, so we don't care |
|
148 |
- * about it*/ |
|
149 |
- if (fl->type==SIP_REQUEST){ |
|
150 |
- tmp=eat_token_end(third,third+len-offset); |
|
151 |
- offset+=tmp-third; |
|
152 |
- if ((tmp==third)||(tmp>=end)){ |
|
153 |
- goto error; |
|
154 |
- } |
|
155 |
- if (! is_empty_end(tmp, tmp+len-offset)){ |
|
156 |
- goto error; |
|
157 |
- } |
|
158 |
- }else{ |
|
159 |
- tmp=eat_token2_end(third,third+len-offset,'\r'); /* find end of line |
|
160 |
- ('\n' or '\r') */ |
|
161 |
- if (tmp>=end){ /* no crlf in packet => invalid */ |
|
162 |
- goto error; |
|
163 |
- } |
|
164 |
- offset+=tmp-third; |
|
165 |
- } |
|
166 |
- nl=eat_line(tmp,len-offset); |
|
167 |
- if (nl>=end){ /* no crlf in packet or only 1 line > invalid */ |
|
168 |
- goto error; |
|
169 |
- } |
|
170 |
- *tmp=0; |
|
171 |
- fl->u.request.version.s=third; |
|
172 |
- fl->u.request.version.len=tmp-third; |
|
173 |
- |
|
174 |
- return nl; |
|
175 |
- |
|
176 |
-error: |
|
177 |
- LOG(L_INFO, "ERROR:parse_first_line: bad %s first line\n", |
|
178 |
- (fl->type==SIP_REPLY)?"reply(status)":"request"); |
|
179 |
- |
|
180 |
- LOG(L_INFO, "ERROR: at line 0 char %d: \n", offset ); |
|
181 |
- prn=pkg_malloc( offset ); |
|
182 |
- if (prn) { |
|
183 |
- for (t=0; t<offset; t++) |
|
184 |
- if (*(buffer+t)) *(prn+t)=*(buffer+t); |
|
185 |
- else *(prn+t)='�'; |
|
186 |
- LOG(L_INFO, "ERROR: parsed so far: %.*s\n", offset, prn ); |
|
187 |
- pkg_free( prn ); |
|
188 |
- }; |
|
189 |
-error1: |
|
190 |
- fl->type=SIP_INVALID; |
|
191 |
- LOG(L_INFO, "ERROR:parse_first_line: bad message\n"); |
|
192 |
- /* skip line */ |
|
193 |
- nl=eat_line(buffer,len); |
|
194 |
- return nl; |
|
195 |
-} |
|
196 |
- |
|
197 |
- |
|
198 |
- |
|
199 |
-/* returns pointer to next header line, and fill hdr_f ; |
|
200 |
- * if at end of header returns pointer to the last crlf (always buf)*/ |
|
201 |
-char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr) |
|
202 |
-{ |
|
203 |
- |
|
204 |
- char* tmp; |
|
205 |
- char *match; |
|
206 |
- struct via_body *vb; |
|
207 |
- struct cseq_body* cseq_b; |
|
208 |
- struct to_body* to_b; |
|
209 |
- |
|
210 |
- if ((*buf)=='\n' || (*buf)=='\r'){ |
|
211 |
- /* double crlf or lflf or crcr */ |
|
212 |
- DBG("found end of header\n"); |
|
213 |
- hdr->type=HDR_EOH; |
|
214 |
- return buf; |
|
215 |
- } |
|
216 |
- |
|
217 |
- tmp=parse_hname(buf, end, hdr); |
|
218 |
- if (hdr->type==HDR_ERROR){ |
|
219 |
- LOG(L_ERR, "ERROR: get_hdr_field: bad header\n"); |
|
220 |
- goto error; |
|
221 |
- } |
|
222 |
- switch(hdr->type){ |
|
223 |
- case HDR_VIA: |
|
224 |
- vb=pkg_malloc(sizeof(struct via_body)); |
|
225 |
- if (vb==0){ |
|
226 |
- LOG(L_ERR, "get_hdr_field: out of memory\n"); |
|
227 |
- goto error; |
|
228 |
- } |
|
229 |
- memset(vb,0,sizeof(struct via_body)); |
|
230 |
- |
|
231 |
- hdr->body.s=tmp; |
|
232 |
- tmp=parse_via(tmp, end, vb); |
|
233 |
- if (vb->error==VIA_PARSE_ERROR){ |
|
234 |
- LOG(L_ERR, "ERROR: get_hdr_field: bad via\n"); |
|
235 |
- pkg_free(vb); |
|
236 |
- goto error; |
|
237 |
- } |
|
238 |
- hdr->parsed=vb; |
|
239 |
- vb->hdr.s=hdr->name.s; |
|
240 |
- vb->hdr.len=hdr->name.len; |
|
241 |
- hdr->body.len=tmp-hdr->body.s; |
|
242 |
- break; |
|
243 |
- case HDR_CSEQ: |
|
244 |
- cseq_b=pkg_malloc(sizeof(struct cseq_body)); |
|
245 |
- if (cseq_b==0){ |
|
246 |
- LOG(L_ERR, "get_hdr_field: out of memory\n"); |
|
247 |
- goto error; |
|
248 |
- } |
|
249 |
- memset(cseq_b, 0, sizeof(struct cseq_body)); |
|
250 |
- hdr->body.s=tmp; |
|
251 |
- tmp=parse_cseq(tmp, end, cseq_b); |
|
252 |
- if (cseq_b->error==PARSE_ERROR){ |
|
253 |
- LOG(L_ERR, "ERROR: get_hdr_field: bad cseq\n"); |
|
254 |
- pkg_free(cseq_b); |
|
255 |
- goto error; |
|
256 |
- } |
|
257 |
- hdr->parsed=cseq_b; |
|
258 |
- hdr->body.len=tmp-hdr->body.s; |
|
259 |
- DBG("get_hdr_field: cseq <%s>: <%s> <%s>\n", |
|
260 |
- hdr->name.s, cseq_b->number.s, cseq_b->method.s); |
|
261 |
- break; |
|
262 |
- case HDR_TO: |
|
263 |
- to_b=pkg_malloc(sizeof(struct to_body)); |
|
264 |
- if (to_b==0){ |
|
265 |
- LOG(L_ERR, "get_hdr_field: out of memory\n"); |
|
266 |
- goto error; |
|
267 |
- } |
|
268 |
- memset(to_b, 0, sizeof(struct to_body)); |
|
269 |
- hdr->body.s=tmp; |
|
270 |
- tmp=parse_to(tmp, end,to_b); |
|
271 |
- if (to_b->error==PARSE_ERROR){ |
|
272 |
- LOG(L_ERR, "ERROR: get_hdr_field: bad to header\n"); |
|
273 |
- pkg_free(to_b); |
|
274 |
- goto error; |
|
275 |
- } |
|
276 |
- hdr->parsed=to_b; |
|
277 |
- hdr->body.len=tmp-hdr->body.s; |
|
278 |
- DBG("DEBUG: get_hdr_field: <%s> [%d]; uri=[%.*s] \n", |
|
279 |
- hdr->name.s, hdr->body.len, to_b->uri.len,to_b->uri.s); |
|
280 |
- DBG("DEBUG: to body [%.*s]\n",to_b->body.len,to_b->body.s); |
|
281 |
- break; |
|
282 |
- case HDR_FROM: |
|
283 |
- case HDR_CALLID: |
|
284 |
- case HDR_CONTACT: |
|
285 |
- case HDR_ROUTE: /* janakj, HDR_ROUTE was missing here */ |
|
286 |
- case HDR_RECORDROUTE: |
|
287 |
- case HDR_MAXFORWARDS: |
|
288 |
- case HDR_OTHER: |
|
289 |
- /* just skip over it */ |
|
290 |
- hdr->body.s=tmp; |
|
291 |
- /* find end of header */ |
|
292 |
- |
|
293 |
- /* find lf */ |
|
294 |
- do{ |
|
295 |
- match=q_memchr(tmp, '\n', end-tmp); |
|
296 |
- if (match){ |
|
297 |
- match++; |
|
298 |
- }else { |
|
299 |
- tmp=end; |
|
300 |
- LOG(L_ERR, |
|
301 |
- "ERROR: get_hdr_field: bad body for <%s>(%d)\n", |
|
302 |
- hdr->name.s, hdr->type); |
|
303 |
- goto error; |
|
304 |
- } |
|
305 |
- tmp=match; |
|
306 |
- }while( match<end &&( (*match==' ')||(*match=='\t') ) ); |
|
307 |
- *(match-1)=0; /*null terminate*/ |
|
308 |
- hdr->body.len=match-hdr->body.s; |
|
309 |
- break; |
|
310 |
- default: |
|
311 |
- LOG(L_CRIT, "BUG: get_hdr_field: unknown header type %d\n", |
|
312 |
- hdr->type); |
|
313 |
- goto error; |
|
314 |
- } |
|
315 |
- |
|
316 |
- /* jku: if \r covered by current length, shrink it */ |
|
317 |
- trim_r( hdr->body ); |
|
318 |
- return tmp; |
|
319 |
-error: |
|
320 |
- DBG("get_hdr_field: error exit\n"); |
|
321 |
- hdr->type=HDR_ERROR; |
|
322 |
- return tmp; |
|
323 |
-} |
|
324 |
- |
|
325 |
- |
|
326 |
- |
|
327 |
-char* parse_hostport(char* buf, str* host, short int* port) |
|
328 |
-{ |
|
329 |
- char *tmp; |
|
330 |
- int err; |
|
331 |
- |
|
332 |
- host->s=buf; |
|
333 |
- for(tmp=buf;(*tmp)&&(*tmp!=':');tmp++); |
|
334 |
- host->len=tmp-buf; |
|
335 |
- if (*tmp==0){ |
|
336 |
- *port=0; |
|
337 |
- }else{ |
|
338 |
- *tmp=0; |
|
339 |
- *port=str2s((unsigned char*)(tmp+1), strlen(tmp+1), &err); |
|
340 |
- if (err ){ |
|
341 |
- LOG(L_INFO, |
|
342 |
- "ERROR: hostport: trailing chars in port number: %s\n", |
|
343 |
- tmp+1); |
|
344 |
- /* report error? */ |
|
345 |
- } |
|
346 |
- } |
|
347 |
- return host->s; |
|
348 |
-} |
|
349 |
- |
|
350 |
- |
|
351 |
- |
|
352 |
-/*BUGGY*/ |
|
353 |
-char * parse_cseq(char *buf, char* end, struct cseq_body* cb) |
|
354 |
-{ |
|
355 |
- char *t, *m, *m_end; |
|
356 |
- char c; |
|
357 |
- |
|
358 |
- cb->error=PARSE_ERROR; |
|
359 |
- t=eat_space_end(buf, end); |
|
360 |
- if (t>=end) goto error; |
|
361 |
- |
|
362 |
- cb->number.s=t; |
|
363 |
- t=eat_token_end(t, end); |
|
364 |
- if (t>=end) goto error; |
|
365 |
- m=eat_space_end(t, end); |
|
366 |
- m_end=eat_token_end(m, end); |
|
367 |
- *t=0; /*null terminate it*/ |
|
368 |
- cb->number.len=t-cb->number.s; |
|
369 |
- |
|
370 |
- if (m_end>=end) goto error; |
|
371 |
- if (m_end==m){ |
|
372 |
- /* null method*/ |
|
373 |
- LOG(L_ERR, "ERROR:parse_cseq: no method found\n"); |
|
374 |
- goto error; |
|
375 |
- } |
|
376 |
- cb->method.s=m; |
|
377 |
- t=m_end; |
|
378 |
- c=*t; |
|
379 |
- *t=0; /*null terminate it*/ |
|
380 |
- cb->method.len=t-cb->method.s; |
|
381 |
- t++; |
|
382 |
- /*check if the header ends here*/ |
|
383 |
- if (c=='\n') goto check_continue; |
|
384 |
- do{ |
|
385 |
- for (;(t<end)&&((*t==' ')||(*t=='\t')||(*t=='\r'));t++); |
|
386 |
- if (t>=end) goto error; |
|
387 |
- if (*t!='\n'){ |
|
388 |
- LOG(L_ERR, "ERROR:parse_cseq: unexpected char <%c> at end of" |
|
389 |
- " cseq\n", *t); |
|
390 |
- goto error; |
|
391 |
- } |
|
392 |
- t++; |
|
393 |
-check_continue: |
|
394 |
- ; |
|
395 |
- }while( (t<end) && ((*t==' ')||(*t=='\t')) ); |
|
396 |
- |
|
397 |
- cb->error=PARSE_OK; |
|
398 |
- return t; |
|
399 |
-error: |
|
400 |
- LOG(L_ERR, "ERROR: parse_cseq: bad cseq\n"); |
|
401 |
- return t; |
|
402 |
-} |
|
403 |
- |
|
404 |
- |
|
405 |
- |
|
406 |
-/* buf= pointer to begining of uri (sip:x@foo.bar:5060;a=b?h=i) |
|
407 |
- len= len of uri |
|
408 |
-returns: fills uri & returns <0 on error or 0 if ok */ |
|
409 |
-int parse_uri(char *buf, int len, struct sip_uri* uri) |
|
410 |
-{ |
|
411 |
- char* next, *end; |
|
412 |
- char *user, *passwd, *host, *port, *params, *headers; |
|
413 |
- int host_len, port_len, params_len, headers_len; |
|
414 |
- int ret; |
|
415 |
- |
|
416 |
- |
|
417 |
- ret=0; |
|
418 |
- end=buf+len; |
|
419 |
- memset(uri, 0, sizeof(struct sip_uri)); /* zero it all, just to be sure */ |
|
420 |
- /* look for "sip:"*/; |
|
421 |
- next=q_memchr(buf, ':', len); |
|
422 |
- if ((next==0)||(strncmp(buf,"sip",next-buf)!=0)){ |
|
423 |
- LOG(L_DBG, "ERROR: parse_uri: bad sip uri\n"); |
|
424 |
- ret=E_UNSPEC; |
|
425 |
- goto error; |
|
426 |
- } |
|
427 |
- buf=next+1; /* next char after ':' */ |
|
428 |
- if (buf>end){ |
|
429 |
- LOG(L_DBG, "ERROR: parse_uri: uri too short\n"); |
|
430 |
- ret=E_UNSPEC; |
|
431 |
- goto error; |
|
432 |
- } |
|
433 |
- /*look for '@' */ |
|
434 |
- next=q_memchr(buf,'@', end-buf); |
|
435 |
- if (next==0){ |
|
436 |
- /* no '@' found, => no userinfo */ |
|
437 |
- uri->user.s=0; |
|
438 |
- uri->passwd.s=0; |
|
439 |
- host=buf; |
|
440 |
- }else{ |
|
441 |
- /* found it */ |
|
442 |
- user=buf; |
|
443 |
- /* try to find passwd */ |
|
444 |
- passwd=q_memchr(user,':', next-user); |
|
445 |
- if (passwd==0){ |
|
446 |
- /* no ':' found => no password */ |
|
447 |
- uri->passwd.s=0; |
|
448 |
- uri->user.s=(char*)pkg_malloc(next-user+1); |
|
449 |
- if (uri->user.s==0){ |
|
450 |
- LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n"); |
|
451 |
- ret=E_OUT_OF_MEM; |
|
452 |
- goto error; |
|
453 |
- } |
|
454 |
- memcpy(uri->user.s, user, next-user); |
|
455 |
- uri->user.len=next-user; |
|
456 |
- uri->user.s[next-user]=0; /* null terminate it, |
|
457 |
- usefull for easy printing*/ |
|
458 |
- }else{ |
|
459 |
- uri->user.s=(char*)pkg_malloc(passwd-user+1); |
|
460 |
- if (uri->user.s==0){ |
|
461 |
- LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n"); |
|
462 |
- ret=E_OUT_OF_MEM; |
|
463 |
- goto error; |
|
464 |
- } |
|
465 |
- memcpy(uri->user.s, user, passwd-user); |
|
466 |
- uri->user.len=passwd-user; |
|
467 |
- uri->user.s[passwd-user]=0; |
|
468 |
- passwd++; /*skip ':' */ |
|
469 |
- uri->passwd.s=(char*)pkg_malloc(next-passwd+1); |
|
470 |
- if (uri->passwd.s==0){ |
|
471 |
- LOG(L_ERR,"ERROR:parse_uri: memory allocation failure\n"); |
|
472 |
- ret=E_OUT_OF_MEM; |
|
473 |
- goto error; |
|
474 |
- } |
|
475 |
- memcpy(uri->passwd.s, passwd, next-passwd); |
|
476 |
- uri->passwd.len=next-passwd; |
|
477 |
- uri->passwd.s[next-passwd]=0; |
|
478 |
- } |
|
479 |
- host=next+1; /* skip '@' */ |
|
480 |
- } |
|
481 |
- /* try to find the rest */ |
|
482 |
- if(host>=end){ |
|
483 |
- LOG(L_DBG, "ERROR: parse_uri: missing hostport\n"); |
|
484 |
- ret=E_UNSPEC; |
|
485 |
- goto error; |
|
486 |
- } |
|
487 |
- headers=q_memchr(host,'?',end-host); |
|
488 |
- params=q_memchr(host,';',end-host); |
|
489 |
- port=q_memchr(host,':',end-host); |
|
490 |
- host_len=(port)?port-host:(params)?params-host:(headers)?headers-host: |
|
491 |
- end-host; |
|
492 |
- /* get host */ |
|
493 |
- uri->host.s=pkg_malloc(host_len+1); |
|
494 |
- if (uri->host.s==0){ |
|
495 |
- LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n"); |
|
496 |
- ret=E_OUT_OF_MEM; |
|
497 |
- goto error; |
|
498 |
- } |
|
499 |
- memcpy(uri->host.s, host, host_len); |
|
500 |
- uri->host.len=host_len; |
|
501 |
- uri->host.s[host_len]=0; |
|
502 |
- /* get port*/ |
|
503 |
- if ((port)&&(port+1<end)){ |
|
504 |
- port++; |
|
505 |
- if ( ((params) &&(params<port))||((headers) &&(headers<port)) ){ |
|
506 |
- /* error -> invalid uri we found ';' or '?' before ':' */ |
|
507 |
- LOG(L_DBG, "ERROR: parse_uri: malformed sip uri\n"); |
|
508 |
- ret=E_UNSPEC; |
|
509 |
- goto error; |
|
510 |
- } |
|
511 |
- port_len=(params)?params-port:(headers)?headers-port:end-port; |
|
512 |
- uri->port.s=pkg_malloc(port_len+1); |
|
513 |
- if (uri->port.s==0){ |
|
514 |
- LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n"); |
|
515 |
- ret=E_OUT_OF_MEM; |
|
516 |
- goto error; |
|
517 |
- } |
|
518 |
- memcpy(uri->port.s, port, port_len); |
|
519 |
- uri->port.len=port_len; |
|
520 |
- uri->port.s[port_len]=0; |
|
521 |
- }else uri->port.s=0; |
|
522 |
- /* get params */ |
|
523 |
- if ((params)&&(params+1<end)){ |
|
524 |
- params++; |
|
525 |
- if ((headers) && (headers<params)){ |
|
526 |
- /* error -> invalid uri we found '?' or '?' before ';' */ |
|
527 |
- LOG(L_DBG, "ERROR: parse_uri: malformed sip uri\n"); |
|
528 |
- ret=E_UNSPEC; |
|
529 |
- goto error; |
|
530 |
- } |
|
531 |
- params_len=(headers)?headers-params:end-params; |
|
532 |
- uri->params.s=pkg_malloc(params_len+1); |
|
533 |
- if (uri->params.s==0){ |
|
534 |
- LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n"); |
|
535 |
- ret=E_OUT_OF_MEM; |
|
536 |
- goto error; |
|
537 |
- } |
|
538 |
- memcpy(uri->params.s, params, params_len); |
|
539 |
- uri->params.len=params_len; |
|
540 |
- uri->params.s[params_len]=0; |
|
541 |
- }else uri->params.s=0; |
|
542 |
- /*get headers */ |
|
543 |
- if ((headers)&&(headers+1<end)){ |
|
544 |
- headers++; |
|
545 |
- headers_len=end-headers; |
|
546 |
- uri->headers.s=pkg_malloc(headers_len+1); |
|
547 |
- if(uri->headers.s==0){ |
|
548 |
- LOG(L_ERR, "ERROR: parse_uri: memory allocation error\n"); |
|
549 |
- ret=E_OUT_OF_MEM; |
|
550 |
- goto error; |
|
551 |
- } |
|
552 |
- memcpy(uri->headers.s, headers, headers_len); |
|
553 |
- uri->headers.len=headers_len; |
|
554 |
- uri->headers.s[headers_len]=0; |
|
555 |
- }else uri->headers.s=0; |
|
556 |
- |
|
557 |
- return ret; |
|
558 |
-error: |
|
559 |
- free_uri(uri); |
|
560 |
- return ret; |
|
561 |
-} |
|
562 |
- |
|
563 |
- |
|
564 |
-/* parse the headers and adds them to msg->headers and msg->to, from etc. |
|
565 |
- * It stops when all the headers requested in flags were parsed, on error |
|
566 |
- * (bad header) or end of headers */ |
|
567 |
-/* note: it continues where it previously stopped and goes ahead until |
|
568 |
- end is encountered or desired HFs are found; if you call it twice |
|
569 |
- for the same HF which is present only once, it will fail the second |
|
570 |
- time; if you call it twice and the HF is found on second time too, |
|
571 |
- it's not replaced in the well-known HF pointer but just added to |
|
572 |
- header list; if you want to use a dumbie convenience function which will |
|
573 |
- give you the first occurance of a header you are interested in, |
|
574 |
- look at check_transaction_quadruple |
|
575 |
-*/ |
|
576 |
-int parse_headers(struct sip_msg* msg, int flags) |
|
577 |
-{ |
|
578 |
- struct hdr_field* hf; |
|
579 |
- char* tmp; |
|
580 |
- char* rest; |
|
581 |
- char* end; |
|
582 |
- |
|
583 |
- end=msg->buf+msg->len; |
|
584 |
- tmp=msg->unparsed; |
|
585 |
- |
|
586 |
- DBG("parse_headers: flags=%d\n", flags); |
|
587 |
- while( tmp<end && (flags & msg->parsed_flag) != flags){ |
|
588 |
- hf=pkg_malloc(sizeof(struct hdr_field)); |
|
589 |
- if (hf==0){ |
|
590 |
- LOG(L_ERR, "ERROR:parse_headers: memory allocation error\n"); |
|
591 |
- goto error; |
|
592 |
- } |
|
593 |
- memset(hf,0, sizeof(struct hdr_field)); |
|
594 |
- hf->type=HDR_ERROR; |
|
595 |
- rest=get_hdr_field(tmp, msg->buf+msg->len, hf); |
|
596 |
- switch (hf->type){ |
|
597 |
- case HDR_ERROR: |
|
598 |
- LOG(L_INFO,"ERROR: bad header field\n"); |
|
599 |
- goto error; |
|
600 |
- case HDR_EOH: |
|
601 |
- msg->eoh=tmp; /* or rest?*/ |
|
602 |
- msg->parsed_flag|=HDR_EOH; |
|
603 |
- pkg_free(hf); |
|
604 |
- goto skip; |
|
605 |
- case HDR_OTHER: /*do nothing*/ |
|
606 |
- break; |
|
607 |
- case HDR_CALLID: |
|
608 |
- if (msg->callid==0) msg->callid=hf; |
|
609 |
- msg->parsed_flag|=HDR_CALLID; |
|
610 |
- break; |
|
611 |
- case HDR_TO: |
|
612 |
- if (msg->to==0) msg->to=hf; |
|
613 |
- msg->parsed_flag|=HDR_TO; |
|
614 |
- break; |
|
615 |
- case HDR_CSEQ: |
|
616 |
- if (msg->cseq==0) msg->cseq=hf; |
|
617 |
- msg->parsed_flag|=HDR_CSEQ; |
|
618 |
- break; |
|
619 |
- case HDR_FROM: |
|
620 |
- if (msg->from==0) msg->from=hf; |
|
621 |
- msg->parsed_flag|=HDR_FROM; |
|
622 |
- break; |
|
623 |
- case HDR_CONTACT: |
|
624 |
- if (msg->contact==0) msg->contact=hf; |
|
625 |
- msg->parsed_flag|=HDR_CONTACT; |
|
626 |
- break; |
|
627 |
- case HDR_MAXFORWARDS: |
|
628 |
- if(msg->maxforwards==0) msg->maxforwards=hf; |
|
629 |
- msg->parsed_flag|=HDR_MAXFORWARDS; |
|
630 |
- break; |
|
631 |
- case HDR_ROUTE: |
|
632 |
- if (msg->route==0) msg->route=hf; |
|
633 |
- msg->parsed_flag|=HDR_ROUTE; |
|
634 |
- break; |
|
635 |
- case HDR_RECORDROUTE: |
|
636 |
- if (msg->record_route==0) msg->record_route = hf; |
|
637 |
- msg->parsed_flag|=HDR_RECORDROUTE; |
|
638 |
- break; |
|
639 |
- case HDR_VIA: |
|
640 |
- msg->parsed_flag|=HDR_VIA; |
|
641 |
- DBG("parse_headers: Via found, flags=%d\n", flags); |
|
642 |
- if (msg->via1==0) { |
|
643 |
- DBG("parse_headers: this is the first via\n"); |
|
644 |
- msg->h_via1=hf; |
|
645 |
- msg->via1=hf->parsed; |
|
646 |
- if (msg->via1->next){ |
|
647 |
- msg->via2=msg->via1->next; |
|
648 |
- msg->parsed_flag|=HDR_VIA2; |
|
649 |
- } |
|
650 |
- }else if (msg->via2==0){ |
|
651 |
- msg->h_via2=hf; |
|
652 |
- msg->via2=hf->parsed; |
|
653 |
- msg->parsed_flag|=HDR_VIA2; |
|
654 |
- DBG("parse_headers: this is the second via\n"); |
|
655 |
- } |
|
656 |
- break; |
|
657 |
- default: |
|
658 |
- LOG(L_CRIT, "BUG: parse_headers: unknown header type %d\n", |
|
659 |
- hf->type); |
|
660 |
- goto error; |
|
661 |
- } |
|
662 |
- /* add the header to the list*/ |
|
663 |
- if (msg->last_header==0){ |
|
664 |
- msg->headers=hf; |
|
665 |
- msg->last_header=hf; |
|
666 |
- }else{ |
|
667 |
- msg->last_header->next=hf; |
|
668 |
- msg->last_header=hf; |
|
669 |
- } |
|
670 |
- #ifdef EXTRA_DEBUG |
|
671 |
- DBG("header field type %d, name=<%s>, body=<%s>\n", |
|
672 |
- hf->type, hf->name.s, hf->body.s); |
|
673 |
- #endif |
|
674 |
- tmp=rest; |
|
675 |
- } |
|
676 |
-skip: |
|
677 |
- msg->unparsed=tmp; |
|
678 |
- return 0; |
|
679 |
- |
|
680 |
-error: |
|
681 |
- if (hf) pkg_free(hf); |
|
682 |
- return -1; |
|
683 |
-} |
|
684 |
- |
|
685 |
- |
|
686 |
- |
|
687 |
- |
|
688 |
- |
|
689 |
-/* returns 0 if ok, -1 for errors */ |
|
690 |
-int parse_msg(char* buf, unsigned int len, struct sip_msg* msg) |
|
691 |
-{ |
|
692 |
- |
|
693 |
- char *tmp; |
|
694 |
- char* rest; |
|
695 |
- char* first_via; |
|
696 |
- char* second_via; |
|
697 |
- struct msg_start *fl; |
|
698 |
- int offset; |
|
699 |
- int flags; |
|
700 |
- |
|
701 |
- /* eat crlf from the beginning */ |
|
702 |
- for (tmp=buf; (*tmp=='\n' || *tmp=='\r')&& |
|
703 |
- tmp-buf < len ; tmp++); |
|
704 |
- offset=tmp-buf; |
|
705 |
- fl=&(msg->first_line); |
|
706 |
- rest=parse_first_line(tmp, len-offset, fl); |
|
707 |
-#if 0 |
|
708 |
- rest=parse_fline(tmp, buf+len, fl); |
|
709 |
-#endif |
|
710 |
- offset+=rest-tmp; |
|
711 |
- tmp=rest; |
|
712 |
- switch(fl->type){ |
|
713 |
- case SIP_INVALID: |
|
714 |
- DBG("parse_msg: invalid message\n"); |
|
715 |
- goto error; |
|
716 |
- break; |
|
717 |
- case SIP_REQUEST: |
|
718 |
- DBG("SIP Request:\n"); |
|
719 |
- DBG(" method: <%s>\n",fl->u.request.method.s); |
|
720 |
- DBG(" uri: <%s>\n",fl->u.request.uri.s); |
|
721 |
- DBG(" version: <%s>\n",fl->u.request.version.s); |
|
722 |
- flags=HDR_VIA; |
|
723 |
- break; |
|
724 |
- case SIP_REPLY: |
|
725 |
- DBG("SIP Reply (status):\n"); |
|
726 |
- DBG(" version: <%s>\n",fl->u.reply.version.s); |
|
727 |
- DBG(" status: <%s>\n",fl->u.reply.status.s); |
|
728 |
- DBG(" reason: <%s>\n",fl->u.reply.reason.s); |
|
729 |
- flags=HDR_VIA | HDR_VIA2; |
|
730 |
- break; |
|
731 |
- default: |
|
732 |
- DBG("unknown type %d\n",fl->type); |
|
733 |
- goto error; |
|
734 |
- } |
|
735 |
- msg->unparsed=tmp; |
|
736 |
- /*find first Via: */ |
|
737 |
- first_via=0; |
|
738 |
- second_via=0; |
|
739 |
- if (parse_headers(msg, flags)==-1) goto error; |
|
740 |
- |
|
741 |
-#ifdef EXTRA_DEBUG |
|
742 |
- /* dump parsed data */ |
|
743 |
- if (msg->via1){ |
|
744 |
- DBG(" first via: <%s/%s/%s> <%s:%s(%d)>", |
|
745 |
- msg->via1->name.s, msg->via1->version.s, |
|
746 |
- msg->via1->transport.s, msg->via1->host.s, |
|
747 |
- msg->via1->port_str.s, msg->via1->port); |
|
748 |
- if (msg->via1->params.s) DBG(";<%s>", msg->via1->params.s); |
|
749 |
- if (msg->via1->comment.s) DBG(" <%s>", msg->via1->comment.s); |
|
750 |
- DBG ("\n"); |
|
751 |
- } |
|
752 |
- if (msg->via2){ |
|
753 |
- DBG(" first via: <%s/%s/%s> <%s:%s(%d)>", |
|
754 |
- msg->via2->name.s, msg->via2->version.s, |
|
755 |
- msg->via2->transport.s, msg->via2->host.s, |
|
756 |
- msg->via2->port_str.s, msg->via2->port); |
|
757 |
- if (msg->via2->params.s) DBG(";<%s>", msg->via2->params.s); |
|
758 |
- if (msg->via2->comment.s) DBG(" <%s>", msg->via2->comment.s); |
|
759 |
- DBG ("\n"); |
|
760 |
- } |
|
761 |
-#endif |
|
762 |
- |
|
763 |
- |
|
764 |
-#ifdef EXTRA_DEBUG |
|
765 |
- DBG("exiting parse_msg\n"); |
|
766 |
-#endif |
|
767 |
- |
|
768 |
- return 0; |
|
769 |
- |
|
770 |
-error: |
|
771 |
- /* more debugging, msg->orig is/should be null terminated*/ |
|
772 |
- LOG(L_ERR, "ERROR: parse_msg: ip source=%x dest=%x; message=<%s>\n", |
|
773 |
- msg->src_ip, msg->dst_ip, |
|
774 |
- msg->orig); |
|
775 |
- return -1; |
|
776 |
-} |
|
777 |
- |
|
778 |
- |
|
779 |
- |
|
780 |
-void free_uri(struct sip_uri* u) |
|
781 |
-{ |
|
782 |
- if (u){ |
|
783 |
- if (u->user.s) pkg_free(u->user.s); |
|
784 |
- if (u->passwd.s) pkg_free(u->passwd.s); |
|
785 |
- if (u->host.s) pkg_free(u->host.s); |
|
786 |
- if (u->port.s) pkg_free(u->port.s); |
|
787 |
- if (u->params.s) pkg_free(u->params.s); |
|
788 |
- if (u->headers.s) pkg_free(u->headers.s); |
|
789 |
- } |
|
790 |
-} |
|
791 |
- |
|
792 |
-void free_reply_lump( struct lump_rpl *lump) |
|
793 |
-{ |
|
794 |
- struct lump_rpl *foo, *bar; |
|
795 |
- for(foo=lump;foo;) |
|
796 |
- { |
|
797 |
- bar=foo->next; |
|
798 |
- free_lump_rpl(foo); |
|
799 |
- foo = bar; |
|
800 |
- } |
|
801 |
-} |
|
802 |
- |
|
803 |
-void free_via_param_list(struct via_param* vp) |
|
804 |
-{ |
|
805 |
- struct via_param* foo; |
|
806 |
- while(vp){ |
|
807 |
- foo=vp; |
|
808 |
- vp=vp->next; |
|
809 |
- pkg_free(foo); |
|
810 |
- } |
|
811 |
-} |
|
812 |
- |
|
813 |
- |
|
814 |
- |
|
815 |
-void free_via_list(struct via_body* vb) |
|
816 |
-{ |
|
817 |
- struct via_body* foo; |
|
818 |
- while(vb){ |
|
819 |
- foo=vb; |
|
820 |
- vb=vb->next; |
|
821 |
- if (foo->param_lst) free_via_param_list(foo->param_lst); |
|
822 |
- pkg_free(foo); |
|
823 |
- } |
|
824 |
-} |
|
825 |
- |
|
826 |
-void free_to(struct to_body* tb) |
|
827 |
-{ |
|
828 |
- struct to_param *tp=tb->param_lst; |
|
829 |
- struct to_param *foo; |
|
830 |
- while (tp){ |
|
831 |
- foo = tp->next; |
|
832 |
- pkg_free(tp); |
|
833 |
- tp=foo; |
|
834 |
- } |
|
835 |
- pkg_free(tb); |
|
836 |
-} |
|
837 |
- |
|
838 |
-/* frees a hdr_field structure, |
|
839 |
- * WARNING: it frees only parsed (and not name.s, body.s)*/ |
|
840 |
-void clean_hdr_field(struct hdr_field* hf) |
|
841 |
-{ |
|
842 |
- if (hf->parsed){ |
|
843 |
- switch(hf->type){ |
|
844 |
- case HDR_VIA: |
|
845 |
- free_via_list(hf->parsed); |
|
846 |
- break; |
|
847 |
- case HDR_TO: |
|
848 |
- free_to(hf->parsed); |
|
849 |
- break; |
|
850 |
- case HDR_CSEQ: |
|
851 |
- pkg_free(hf->parsed); |
|
852 |
- break; |
|
853 |
- default: |
|
854 |
- LOG(L_CRIT, "BUG: clean_hdr_field: unknown header type %d\n", |
|
855 |
- hf->type); |
|
856 |
- } |
|
857 |
- } |
|
858 |
-} |
|
859 |
- |
|
860 |
- |
|
861 |
- |
|
862 |
-/* frees a hdr_field list, |
|
863 |
- * WARNING: frees only ->parsed and ->next*/ |
|
864 |
-void free_hdr_field_lst(struct hdr_field* hf) |
|
865 |
-{ |
|
866 |
- struct hdr_field* foo; |
|
867 |
- |
|
868 |
- while(hf){ |
|
869 |
- foo=hf; |
|
870 |
- hf=hf->next; |
|
871 |
- clean_hdr_field(foo); |
|
872 |
- pkg_free(foo); |
|
873 |
- } |
|
874 |
-} |
|
875 |
- |
|
876 |
- |
|
877 |
- |
|
878 |
-/*only the content*/ |
|
879 |
-void free_sip_msg(struct sip_msg* msg) |
|
880 |
-{ |
|
881 |
- if (msg->new_uri.s) { pkg_free(msg->new_uri.s); msg->new_uri.len=0; } |
|
882 |
- if (msg->headers) free_hdr_field_lst(msg->headers); |
|
883 |
- if (msg->add_rm) free_lump_list(msg->add_rm); |
|
884 |
- if (msg->repl_add_rm) free_lump_list(msg->repl_add_rm); |
|
885 |
- if (msg->reply_lump) free_reply_lump(msg->reply_lump); |
|
886 |
- pkg_free(msg->orig); |
|
887 |
- /* don't free anymore -- now a pointer to a static buffer */ |
|
888 |
-# ifdef DYN_BUF |
|
889 |
- pkg_free(msg->buf); |
|
890 |
-# endif |
|
891 |
-} |
|
892 |
- |
|
893 |
- |
|
894 |
-#if 0 |
|
895 |
-/* it's a macro now*/ |
|
896 |
-/* make sure all HFs needed for transaction identification have been |
|
897 |
- parsed; return 0 if those HFs can't be found |
|
898 |
-*/ |
|
899 |
-int check_transaction_quadruple( struct sip_msg* msg ) |
|
900 |
-{ |
|
901 |
- return |
|
902 |
- (parse_headers(msg, HDR_FROM|HDR_TO|HDR_CALLID|HDR_CSEQ)!=-1 && |
|
903 |
- msg->from && msg->to && msg->callid && msg->cseq); |
|
904 |
- /* replaced by me ( :) andrei) |
|
905 |
- ( (msg->from || (parse_headers( msg, HDR_FROM)!=-1 && msg->from)) && |
|