/src/opensips/parser/msg_parser.c
Line | Count | Source |
1 | | /* |
2 | | * sip msg. header proxy parser |
3 | | * |
4 | | * Copyright (C) 2001-2003 FhG Fokus |
5 | | * |
6 | | * This file is part of opensips, a free SIP server. |
7 | | * |
8 | | * opensips is free software; you can redistribute it and/or modify |
9 | | * it under the terms of the GNU General Public License as published by |
10 | | * the Free Software Foundation; either version 2 of the License, or |
11 | | * (at your option) any later version |
12 | | * |
13 | | * opensips is distributed in the hope that it will be useful, |
14 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | * GNU General Public License for more details. |
17 | | * |
18 | | * You should have received a copy of the GNU General Public License |
19 | | * along with this program; if not, write to the Free Software |
20 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
21 | | * |
22 | | * History: |
23 | | * --------- |
24 | | * 2003-02-28 scratchpad compatibility abandoned (jiri) |
25 | | * 2003-01-29 scrathcpad removed (jiri) |
26 | | * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri) |
27 | | * 2003-03-31 removed msg->repl_add_rm (andrei) |
28 | | * 2003-04-26 ZSW (jiri) |
29 | | * 2003-05-01 parser extended to support Accept header field (janakj) |
30 | | * 2005-03-02 free_via_list(vb) on via parse error (andrei) |
31 | | * 2006-02-17 Session-Expires, Min-SE (dhsueh@somanetworks.com) |
32 | | * 2006-03-02 header of same type are linked as sibling (bogdan) |
33 | | * 2006-11-28 Added statistic support for bad message headers. |
34 | | * (Jeffrey Magder - SOMA Networks) |
35 | | * 2008-09-09 Added sdp parsing support (osas) |
36 | | */ |
37 | | |
38 | | |
39 | | #include <string.h> |
40 | | #include <stdlib.h> |
41 | | |
42 | | #include "msg_parser.h" |
43 | | #include "parser_f.h" |
44 | | #include "../ut.h" |
45 | | #include "../error.h" |
46 | | #include "../dprint.h" |
47 | | #include "../data_lump.h" |
48 | | #include "../data_lump_rpl.h" |
49 | | #include "../mem/mem.h" |
50 | | #include "../error.h" |
51 | | #include "../globals.h" |
52 | | #include "../core_stats.h" |
53 | | #include "../errinfo.h" |
54 | | #include "../dset.h" |
55 | | #include "../sdp_ops.h" |
56 | | #include "parse_hname2.h" |
57 | | #include "parse_uri.h" |
58 | | #include "parse_content.h" |
59 | | #include "../msg_callbacks.h" |
60 | | |
61 | | #ifdef DEBUG_DMALLOC |
62 | | #include <mem/dmalloc.h> |
63 | | #endif |
64 | | |
65 | | |
66 | 0 | #define parse_hname(_b,_e,_h) parse_hname2((_b),(_e),(_h)) |
67 | | |
68 | | /* number of via's encountered */ |
69 | | int via_cnt; |
70 | | |
71 | | /* returns pointer to next header line, and fill hdr_f ; |
72 | | * if at end of header returns pointer to the last crlf (always buf)*/ |
73 | | char* get_hdr_field_aux(char* buf, char* end, struct hdr_field* hdr,int sip_well_known_parse) |
74 | 0 | { |
75 | |
|
76 | 0 | char* tmp; |
77 | 0 | char *match; |
78 | 0 | struct via_body *vb; |
79 | 0 | struct cseq_body* cseq_b; |
80 | 0 | struct to_body* to_b; |
81 | 0 | int integer; |
82 | |
|
83 | 0 | if ((*buf)=='\n' || (*buf)=='\r'){ |
84 | | /* double crlf or lflf or crcr */ |
85 | 0 | LM_DBG("found end of header\n"); |
86 | 0 | hdr->type=HDR_EOH_T; |
87 | 0 | return buf; |
88 | 0 | } |
89 | | |
90 | 0 | tmp=parse_hname(buf, end, hdr); |
91 | 0 | if (hdr->type==HDR_ERROR_T){ |
92 | 0 | LM_ERR("bad header\n"); |
93 | 0 | goto error_bad_hdr; |
94 | 0 | } |
95 | | |
96 | | /* eliminate leading whitespace */ |
97 | 0 | tmp=eat_lws_end(tmp, end); |
98 | 0 | if (tmp>=end) { |
99 | 0 | LM_ERR("hf empty\n"); |
100 | 0 | goto error_bad_hdr; |
101 | 0 | } |
102 | | |
103 | | /* if header-field well-known, parse it, find its end otherwise ; |
104 | | * after leaving the hdr->type switch, tmp should be set to the |
105 | | * next header field |
106 | | */ |
107 | 0 | switch(hdr->type){ |
108 | 0 | case HDR_VIA_T: |
109 | | /* keep number of vias parsed -- we want to report it in |
110 | | replies for diagnostic purposes */ |
111 | 0 | via_cnt++; |
112 | 0 | if (sip_well_known_parse) { |
113 | 0 | vb=pkg_malloc(sizeof(struct via_body)); |
114 | 0 | if (vb==0){ |
115 | 0 | LM_ERR("out of pkg memory\n"); |
116 | 0 | goto error; |
117 | 0 | } |
118 | 0 | memset(vb,0,sizeof(struct via_body)); |
119 | 0 | hdr->body.s=tmp; |
120 | 0 | tmp=parse_via(tmp, end, vb); |
121 | 0 | if (vb->error==PARSE_ERROR){ |
122 | 0 | LM_ERR("bad via\n"); |
123 | 0 | free_via_list(vb); |
124 | 0 | set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, |
125 | 0 | "error parsing Via"); |
126 | 0 | set_err_reply(400, "bad Via header"); |
127 | 0 | goto error; |
128 | 0 | } |
129 | 0 | hdr->parsed=vb; |
130 | 0 | vb->hdr.s=hdr->name.s; |
131 | 0 | vb->hdr.len=hdr->name.len; |
132 | 0 | hdr->body.len=tmp-hdr->body.s; |
133 | 0 | } else { |
134 | | /* just skip over it */ |
135 | 0 | hdr->body.s=tmp; |
136 | | /* find end of header */ |
137 | | /* find lf */ |
138 | 0 | do{ |
139 | 0 | match=q_memchr(tmp, '\n', end-tmp); |
140 | 0 | if (match){ |
141 | 0 | match++; |
142 | 0 | }else { |
143 | 0 | LM_ERR("bad body for <%.*s>(%d)\n", |
144 | 0 | hdr->name.len, hdr->name.s, hdr->type); |
145 | 0 | tmp=end; |
146 | 0 | goto error_bad_hdr; |
147 | 0 | } |
148 | 0 | tmp=match; |
149 | 0 | }while( match<end &&( (*match==' ')||(*match=='\t') ) ); |
150 | 0 | tmp=match; |
151 | 0 | hdr->body.len=match-hdr->body.s; |
152 | 0 | } |
153 | 0 | break; |
154 | 0 | case HDR_CSEQ_T: |
155 | 0 | if (sip_well_known_parse) { |
156 | 0 | cseq_b=pkg_malloc(sizeof(struct cseq_body)); |
157 | 0 | if (cseq_b==0){ |
158 | 0 | LM_ERR("out of pkg memory\n"); |
159 | 0 | goto error; |
160 | 0 | } |
161 | 0 | memset(cseq_b, 0, sizeof(struct cseq_body)); |
162 | 0 | hdr->body.s=tmp; |
163 | 0 | tmp=parse_cseq(tmp, end, cseq_b); |
164 | 0 | if (cseq_b->error==PARSE_ERROR){ |
165 | 0 | LM_ERR("bad cseq\n"); |
166 | 0 | pkg_free(cseq_b); |
167 | 0 | set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, |
168 | 0 | "error parsing CSeq`"); |
169 | 0 | set_err_reply(400, "bad CSeq header"); |
170 | 0 | goto error; |
171 | 0 | } |
172 | 0 | hdr->parsed=cseq_b; |
173 | 0 | hdr->body.len=tmp-hdr->body.s; |
174 | 0 | LM_DBG("cseq <%.*s>: <%.*s> <%.*s>\n", |
175 | 0 | hdr->name.len, ZSW(hdr->name.s), |
176 | 0 | cseq_b->number.len, ZSW(cseq_b->number.s), |
177 | 0 | cseq_b->method.len, cseq_b->method.s); |
178 | 0 | } else { |
179 | | /* just skip over it */ |
180 | 0 | hdr->body.s=tmp; |
181 | | /* find end of header */ |
182 | | /* find lf */ |
183 | 0 | do{ |
184 | 0 | match=q_memchr(tmp, '\n', end-tmp); |
185 | 0 | if (match){ |
186 | 0 | match++; |
187 | 0 | }else { |
188 | 0 | LM_ERR("bad body for <%.*s>(%d)\n", |
189 | 0 | hdr->name.len, hdr->name.s, hdr->type); |
190 | 0 | tmp=end; |
191 | 0 | goto error_bad_hdr; |
192 | 0 | } |
193 | 0 | tmp=match; |
194 | 0 | }while( match<end &&( (*match==' ')||(*match=='\t') ) ); |
195 | 0 | tmp=match; |
196 | 0 | hdr->body.len=match-hdr->body.s; |
197 | 0 | } |
198 | 0 | break; |
199 | 0 | case HDR_TO_T: |
200 | 0 | if (sip_well_known_parse) { |
201 | 0 | to_b=pkg_malloc(sizeof(struct to_body)); |
202 | 0 | if (to_b==0){ |
203 | 0 | LM_ERR("out of pkg memory\n"); |
204 | 0 | goto error; |
205 | 0 | } |
206 | 0 | memset(to_b, 0, sizeof(struct to_body)); |
207 | 0 | hdr->body.s=tmp; |
208 | 0 | tmp=parse_to(tmp, end,to_b); |
209 | 0 | if (to_b->error==PARSE_ERROR){ |
210 | 0 | LM_ERR("bad to header\n"); |
211 | 0 | pkg_free(to_b); |
212 | 0 | set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, |
213 | 0 | "error parsing To header"); |
214 | 0 | set_err_reply(400, "bad header"); |
215 | 0 | goto error; |
216 | 0 | } |
217 | 0 | hdr->parsed=to_b; |
218 | 0 | hdr->body.len=tmp-hdr->body.s; |
219 | 0 | LM_DBG("<%.*s> [%d]; uri=[%.*s] \n", |
220 | 0 | hdr->name.len, ZSW(hdr->name.s), |
221 | 0 | hdr->body.len, to_b->uri.len,ZSW(to_b->uri.s)); |
222 | 0 | LM_DBG("to body [%.*s]\n",to_b->body.len, ZSW(to_b->body.s)); |
223 | 0 | } else { |
224 | | /* just skip over it */ |
225 | 0 | hdr->body.s=tmp; |
226 | | /* find end of header */ |
227 | | /* find lf */ |
228 | 0 | do{ |
229 | 0 | match=q_memchr(tmp, '\n', end-tmp); |
230 | 0 | if (match){ |
231 | 0 | match++; |
232 | 0 | }else { |
233 | 0 | LM_ERR("bad body for <%.*s>(%d)\n", |
234 | 0 | hdr->name.len, hdr->name.s, hdr->type); |
235 | 0 | tmp=end; |
236 | 0 | goto error_bad_hdr; |
237 | 0 | } |
238 | 0 | tmp=match; |
239 | 0 | }while( match<end &&( (*match==' ')||(*match=='\t') ) ); |
240 | 0 | tmp=match; |
241 | 0 | hdr->body.len=match-hdr->body.s; |
242 | 0 | } |
243 | 0 | break; |
244 | 0 | case HDR_CONTENTLENGTH_T: |
245 | 0 | if (sip_well_known_parse) { |
246 | 0 | hdr->body.s=tmp; |
247 | 0 | tmp=parse_content_length(tmp,end, &integer); |
248 | 0 | if (tmp==0){ |
249 | 0 | LM_ERR("bad content_length header\n"); |
250 | 0 | set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, |
251 | 0 | "error parsing Content-Length"); |
252 | 0 | set_err_reply(400, "bad Content-Length header"); |
253 | 0 | goto error; |
254 | 0 | } |
255 | 0 | hdr->parsed=(void*)(long)integer; |
256 | 0 | hdr->body.len=tmp-hdr->body.s; |
257 | 0 | LM_DBG("content_length=%d\n", (int)(long)hdr->parsed); |
258 | 0 | } else { |
259 | | /* just skip over it */ |
260 | 0 | hdr->body.s=tmp; |
261 | | /* find end of header */ |
262 | | /* find lf */ |
263 | 0 | do{ |
264 | 0 | match=q_memchr(tmp, '\n', end-tmp); |
265 | 0 | if (match){ |
266 | 0 | match++; |
267 | 0 | }else { |
268 | 0 | LM_ERR("bad body for <%.*s>(%d)\n", |
269 | 0 | hdr->name.len, hdr->name.s, hdr->type); |
270 | 0 | tmp=end; |
271 | 0 | goto error_bad_hdr; |
272 | 0 | } |
273 | 0 | tmp=match; |
274 | 0 | }while( match<end &&( (*match==' ')||(*match=='\t') ) ); |
275 | 0 | tmp=match; |
276 | 0 | hdr->body.len=match-hdr->body.s; |
277 | 0 | } |
278 | 0 | break; |
279 | 0 | case HDR_SUPPORTED_T: |
280 | 0 | case HDR_CONTENTTYPE_T: |
281 | 0 | case HDR_FROM_T: |
282 | 0 | case HDR_CALLID_T: |
283 | 0 | case HDR_CONTACT_T: |
284 | 0 | case HDR_ROUTE_T: |
285 | 0 | case HDR_RECORDROUTE_T: |
286 | 0 | case HDR_PATH_T: |
287 | 0 | case HDR_MAXFORWARDS_T: |
288 | 0 | case HDR_AUTHORIZATION_T: |
289 | 0 | case HDR_EXPIRES_T: |
290 | 0 | case HDR_PROXYAUTH_T: |
291 | 0 | case HDR_PROXYREQUIRE_T: |
292 | 0 | case HDR_UNSUPPORTED_T: |
293 | 0 | case HDR_ALLOW_T: |
294 | 0 | case HDR_EVENT_T: |
295 | 0 | case HDR_ACCEPT_T: |
296 | 0 | case HDR_ACCEPTLANGUAGE_T: |
297 | 0 | case HDR_ORGANIZATION_T: |
298 | 0 | case HDR_PRIORITY_T: |
299 | 0 | case HDR_SUBJECT_T: |
300 | 0 | case HDR_USERAGENT_T: |
301 | 0 | case HDR_CONTENTDISPOSITION_T: |
302 | 0 | case HDR_ACCEPTDISPOSITION_T: |
303 | 0 | case HDR_DIVERSION_T: |
304 | 0 | case HDR_RPID_T: |
305 | 0 | case HDR_REFER_TO_T: |
306 | 0 | case HDR_SESSION_EXPIRES_T: |
307 | 0 | case HDR_MIN_SE_T: |
308 | 0 | case HDR_MIN_EXPIRES_T: |
309 | 0 | case HDR_PPI_T: |
310 | 0 | case HDR_PAI_T: |
311 | 0 | case HDR_PRIVACY_T: |
312 | 0 | case HDR_RETRY_AFTER_T: |
313 | 0 | case HDR_CALL_INFO_T: |
314 | 0 | case HDR_WWW_AUTHENTICATE_T: |
315 | 0 | case HDR_PROXY_AUTHENTICATE_T: |
316 | 0 | case HDR_FEATURE_CAPS_T: |
317 | 0 | case HDR_REPLACES_T: |
318 | 0 | case HDR_TO_PATH_T: |
319 | 0 | case HDR_FROM_PATH_T: |
320 | 0 | case HDR_MESSAGE_ID_T: |
321 | 0 | case HDR_BYTE_RANGE_T: |
322 | 0 | case HDR_FAILURE_REPORT_T: |
323 | 0 | case HDR_SUCCESS_REPORT_T: |
324 | 0 | case HDR_STATUS_T: |
325 | 0 | case HDR_USE_PATH_T: |
326 | 0 | case HDR_SECURITY_CLIENT_T: |
327 | 0 | case HDR_SECURITY_SERVER_T: |
328 | 0 | case HDR_SECURITY_VERIFY_T: |
329 | 0 | case HDR_OTHER_T: |
330 | | /* just skip over it */ |
331 | 0 | hdr->body.s=tmp; |
332 | | /* find end of header */ |
333 | | /* find lf */ |
334 | 0 | do{ |
335 | 0 | match=q_memchr(tmp, '\n', end-tmp); |
336 | 0 | if (match){ |
337 | 0 | match++; |
338 | 0 | }else { |
339 | 0 | LM_ERR("bad body for <%.*s>(%d)\n", |
340 | 0 | hdr->name.len, hdr->name.s, hdr->type); |
341 | 0 | tmp=end; |
342 | 0 | goto error_bad_hdr; |
343 | 0 | } |
344 | 0 | tmp=match; |
345 | 0 | }while( match<end &&( (*match==' ')||(*match=='\t') ) ); |
346 | 0 | tmp=match; |
347 | 0 | hdr->body.len=match-hdr->body.s; |
348 | 0 | break; |
349 | 0 | default: |
350 | 0 | LM_CRIT("unknown header type %d\n", hdr->type); |
351 | 0 | goto error; |
352 | 0 | } |
353 | | /* jku: if \r covered by current length, shrink it */ |
354 | 0 | trim_r( hdr->body ); |
355 | 0 | hdr->len=tmp-hdr->name.s; |
356 | 0 | return tmp; |
357 | | |
358 | 0 | error_bad_hdr: |
359 | 0 | set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, |
360 | 0 | "error parsing headers"); |
361 | 0 | set_err_reply(400, "bad headers"); |
362 | 0 | error: |
363 | 0 | LM_DBG("error exit\n"); |
364 | 0 | update_stat( bad_msg_hdr, 1); |
365 | 0 | hdr->type=HDR_ERROR_T; |
366 | 0 | hdr->len=tmp-hdr->name.s; |
367 | 0 | return tmp; |
368 | 0 | } |
369 | | |
370 | | /* parse the headers and adds them to msg->headers and msg->to, from etc. |
371 | | * It stops when all the headers requested in flags were parsed, on error |
372 | | * (bad header) or end of headers */ |
373 | | /* note: it continues where it previously stopped and goes ahead until |
374 | | end is encountered or desired HFs are found; if you call it twice |
375 | | for the same HF which is present only once, it will fail the second |
376 | | time; if you call it twice and the HF is found on second time too, |
377 | | it's not replaced in the well-known HF pointer but just added to |
378 | | header list; if you want to use a dumb convenience function which will |
379 | | give you the first occurrence of a header you are interested in, |
380 | | look at check_transaction_quadruple |
381 | | */ |
382 | | int parse_headers_aux(struct sip_msg* msg, hdr_flags_t flags, int next, int sip_well_known_parse) |
383 | 0 | { |
384 | 0 | struct hdr_field *hf; |
385 | 0 | char* tmp; |
386 | 0 | char* rest; |
387 | 0 | char* end; |
388 | 0 | hdr_flags_t orig_flag; |
389 | |
|
390 | 0 | #define link_sibling_hdr(_hook, _hdr) _add_last(_hdr, msg->_hook, sibling) |
391 | |
|
392 | 0 | end=msg->buf+msg->len; |
393 | 0 | tmp=msg->unparsed; |
394 | |
|
395 | 0 | if (next) { |
396 | 0 | orig_flag = msg->parsed_flag; |
397 | 0 | msg->parsed_flag &= ~flags; |
398 | 0 | }else |
399 | 0 | orig_flag=0; |
400 | |
|
401 | 0 | LM_DBG("flags=%llx\n", (unsigned long long)flags); |
402 | 0 | while( tmp<end && (flags & msg->parsed_flag) != flags){ |
403 | 0 | hf=pkg_malloc(sizeof(struct hdr_field)); |
404 | 0 | if (hf==0){ |
405 | 0 | ser_error=E_OUT_OF_MEM; |
406 | 0 | LM_ERR("pkg memory allocation failed\n"); |
407 | 0 | goto error; |
408 | 0 | } |
409 | 0 | memset(hf,0, sizeof(struct hdr_field)); |
410 | 0 | hf->type=HDR_ERROR_T; |
411 | 0 | rest=get_hdr_field_aux(tmp, msg->buf+msg->len, hf,sip_well_known_parse); |
412 | 0 | switch (hf->type){ |
413 | 0 | case HDR_ERROR_T: |
414 | 0 | LM_INFO("bad header field\n"); |
415 | 0 | goto error; |
416 | 0 | case HDR_EOH_T: |
417 | 0 | msg->eoh=tmp; /* or rest?*/ |
418 | 0 | msg->parsed_flag|=HDR_EOH_F; |
419 | 0 | pkg_free(hf); |
420 | 0 | goto skip; |
421 | 0 | case HDR_OTHER_T: /*do nothing*/ |
422 | 0 | case HDR_TO_PATH_T: |
423 | 0 | case HDR_FROM_PATH_T: |
424 | 0 | case HDR_MESSAGE_ID_T: |
425 | 0 | case HDR_BYTE_RANGE_T: |
426 | 0 | case HDR_FAILURE_REPORT_T: |
427 | 0 | case HDR_SUCCESS_REPORT_T: |
428 | 0 | case HDR_STATUS_T: |
429 | 0 | case HDR_USE_PATH_T: |
430 | 0 | break; |
431 | 0 | case HDR_CALLID_T: |
432 | 0 | if (msg->callid==0) msg->callid=hf; |
433 | 0 | msg->parsed_flag|=HDR_CALLID_F; |
434 | 0 | break; |
435 | 0 | case HDR_TO_T: |
436 | 0 | if (msg->to==0) msg->to=hf; |
437 | 0 | msg->parsed_flag|=HDR_TO_F; |
438 | 0 | break; |
439 | 0 | case HDR_CSEQ_T: |
440 | 0 | if (msg->cseq==0) msg->cseq=hf; |
441 | 0 | msg->parsed_flag|=HDR_CSEQ_F; |
442 | 0 | break; |
443 | 0 | case HDR_FROM_T: |
444 | 0 | if (msg->from==0) msg->from=hf; |
445 | 0 | msg->parsed_flag|=HDR_FROM_F; |
446 | 0 | break; |
447 | 0 | case HDR_CONTACT_T: |
448 | 0 | link_sibling_hdr(contact,hf); |
449 | 0 | msg->parsed_flag|=HDR_CONTACT_F; |
450 | 0 | break; |
451 | 0 | case HDR_MAXFORWARDS_T: |
452 | 0 | if(msg->maxforwards==0) msg->maxforwards=hf; |
453 | 0 | msg->parsed_flag|=HDR_MAXFORWARDS_F; |
454 | 0 | break; |
455 | 0 | case HDR_ROUTE_T: |
456 | 0 | link_sibling_hdr(route,hf); |
457 | 0 | msg->parsed_flag|=HDR_ROUTE_F; |
458 | 0 | break; |
459 | 0 | case HDR_RECORDROUTE_T: |
460 | 0 | link_sibling_hdr(record_route,hf); |
461 | 0 | msg->parsed_flag|=HDR_RECORDROUTE_F; |
462 | 0 | break; |
463 | 0 | case HDR_PATH_T: |
464 | 0 | link_sibling_hdr(path,hf); |
465 | 0 | msg->parsed_flag|=HDR_PATH_F; |
466 | 0 | break; |
467 | 0 | case HDR_CONTENTTYPE_T: |
468 | 0 | if (msg->content_type==0) msg->content_type = hf; |
469 | 0 | msg->parsed_flag|=HDR_CONTENTTYPE_F; |
470 | 0 | break; |
471 | 0 | case HDR_CONTENTLENGTH_T: |
472 | 0 | if (msg->content_length==0) msg->content_length = hf; |
473 | 0 | msg->parsed_flag|=HDR_CONTENTLENGTH_F; |
474 | 0 | break; |
475 | 0 | case HDR_AUTHORIZATION_T: |
476 | 0 | link_sibling_hdr(authorization,hf); |
477 | 0 | msg->parsed_flag|=HDR_AUTHORIZATION_F; |
478 | 0 | break; |
479 | 0 | case HDR_EXPIRES_T: |
480 | 0 | if (msg->expires==0) msg->expires = hf; |
481 | 0 | msg->parsed_flag|=HDR_EXPIRES_F; |
482 | 0 | break; |
483 | 0 | case HDR_PROXYAUTH_T: |
484 | 0 | link_sibling_hdr(proxy_auth,hf); |
485 | 0 | msg->parsed_flag|=HDR_PROXYAUTH_F; |
486 | 0 | break; |
487 | 0 | case HDR_PROXYREQUIRE_T: |
488 | 0 | link_sibling_hdr(proxy_require,hf); |
489 | 0 | msg->parsed_flag|=HDR_PROXYREQUIRE_F; |
490 | 0 | break; |
491 | 0 | case HDR_SUPPORTED_T: |
492 | 0 | link_sibling_hdr(supported,hf); |
493 | 0 | msg->parsed_flag|=HDR_SUPPORTED_F; |
494 | 0 | break; |
495 | 0 | case HDR_UNSUPPORTED_T: |
496 | 0 | link_sibling_hdr(unsupported,hf); |
497 | 0 | msg->parsed_flag|=HDR_UNSUPPORTED_F; |
498 | 0 | break; |
499 | 0 | case HDR_ALLOW_T: |
500 | 0 | link_sibling_hdr(allow,hf); |
501 | 0 | msg->parsed_flag|=HDR_ALLOW_F; |
502 | 0 | break; |
503 | 0 | case HDR_EVENT_T: |
504 | 0 | link_sibling_hdr(event,hf); |
505 | 0 | msg->parsed_flag|=HDR_EVENT_F; |
506 | 0 | break; |
507 | 0 | case HDR_ACCEPT_T: |
508 | 0 | link_sibling_hdr(accept,hf); |
509 | 0 | msg->parsed_flag|=HDR_ACCEPT_F; |
510 | 0 | break; |
511 | 0 | case HDR_ACCEPTLANGUAGE_T: |
512 | 0 | link_sibling_hdr(accept_language,hf); |
513 | 0 | msg->parsed_flag|=HDR_ACCEPTLANGUAGE_F; |
514 | 0 | break; |
515 | 0 | case HDR_ORGANIZATION_T: |
516 | 0 | if (msg->organization==0) msg->organization = hf; |
517 | 0 | msg->parsed_flag|=HDR_ORGANIZATION_F; |
518 | 0 | break; |
519 | 0 | case HDR_PRIORITY_T: |
520 | 0 | if (msg->priority==0) msg->priority = hf; |
521 | 0 | msg->parsed_flag|=HDR_PRIORITY_F; |
522 | 0 | break; |
523 | 0 | case HDR_SUBJECT_T: |
524 | 0 | if (msg->subject==0) msg->subject = hf; |
525 | 0 | msg->parsed_flag|=HDR_SUBJECT_F; |
526 | 0 | break; |
527 | 0 | case HDR_USERAGENT_T: |
528 | 0 | if (msg->user_agent==0) msg->user_agent = hf; |
529 | 0 | msg->parsed_flag|=HDR_USERAGENT_F; |
530 | 0 | break; |
531 | 0 | case HDR_CONTENTDISPOSITION_T: |
532 | 0 | if (msg->content_disposition==0) msg->content_disposition = hf; |
533 | 0 | msg->parsed_flag|=HDR_CONTENTDISPOSITION_F; |
534 | 0 | break; |
535 | 0 | case HDR_ACCEPTDISPOSITION_T: |
536 | 0 | link_sibling_hdr(accept_disposition,hf); |
537 | 0 | msg->parsed_flag|=HDR_ACCEPTDISPOSITION_F; |
538 | 0 | break; |
539 | 0 | case HDR_DIVERSION_T: |
540 | 0 | link_sibling_hdr(diversion,hf); |
541 | 0 | msg->parsed_flag|=HDR_DIVERSION_F; |
542 | 0 | break; |
543 | 0 | case HDR_RPID_T: |
544 | 0 | if (msg->rpid==0) msg->rpid = hf; |
545 | 0 | msg->parsed_flag|=HDR_RPID_F; |
546 | 0 | break; |
547 | 0 | case HDR_CALL_INFO_T: |
548 | 0 | link_sibling_hdr(call_info,hf); |
549 | 0 | msg->parsed_flag|=HDR_CALL_INFO_F; |
550 | 0 | break; |
551 | 0 | case HDR_WWW_AUTHENTICATE_T: |
552 | 0 | link_sibling_hdr(www_authenticate,hf); |
553 | 0 | msg->parsed_flag|=HDR_WWW_AUTHENTICATE_F; |
554 | 0 | break; |
555 | 0 | case HDR_PROXY_AUTHENTICATE_T: |
556 | 0 | link_sibling_hdr(proxy_authenticate,hf); |
557 | 0 | msg->parsed_flag|=HDR_PROXY_AUTHENTICATE_F; |
558 | 0 | break; |
559 | 0 | case HDR_REFER_TO_T: |
560 | 0 | if (msg->refer_to==0) msg->refer_to = hf; |
561 | 0 | msg->parsed_flag|=HDR_REFER_TO_F; |
562 | 0 | break; |
563 | 0 | case HDR_SESSION_EXPIRES_T: |
564 | 0 | if ( msg->session_expires == 0 ) msg->session_expires = hf; |
565 | 0 | msg->parsed_flag |= HDR_SESSION_EXPIRES_F; |
566 | 0 | break; |
567 | 0 | case HDR_MIN_SE_T: |
568 | 0 | if ( msg->min_se == 0 ) msg->min_se = hf; |
569 | 0 | msg->parsed_flag |= HDR_MIN_SE_F; |
570 | 0 | break; |
571 | 0 | case HDR_MIN_EXPIRES_T: |
572 | 0 | if ( msg->min_expires == 0 ) msg->min_expires = hf; |
573 | 0 | msg->parsed_flag |= HDR_MIN_EXPIRES_F; |
574 | 0 | break; |
575 | 0 | case HDR_PPI_T: |
576 | 0 | link_sibling_hdr(ppi,hf); |
577 | 0 | msg->parsed_flag|=HDR_PPI_F; |
578 | 0 | break; |
579 | 0 | case HDR_PAI_T: |
580 | 0 | link_sibling_hdr(pai,hf); |
581 | 0 | msg->parsed_flag|=HDR_PAI_F; |
582 | 0 | break; |
583 | 0 | case HDR_PRIVACY_T: |
584 | 0 | if (msg->privacy==0) msg->privacy = hf; |
585 | 0 | msg->parsed_flag|=HDR_PRIVACY_F; |
586 | 0 | break; |
587 | 0 | case HDR_RETRY_AFTER_T: |
588 | 0 | break; |
589 | 0 | case HDR_VIA_T: |
590 | 0 | link_sibling_hdr(h_via1,hf); |
591 | 0 | msg->parsed_flag|=HDR_VIA_F; |
592 | 0 | LM_DBG("via found, flags=%llx\n", (unsigned long long)flags); |
593 | 0 | if (sip_well_known_parse && msg->via1==0) { |
594 | 0 | LM_DBG("this is the first via\n"); |
595 | 0 | msg->h_via1=hf; |
596 | 0 | msg->via1=hf->parsed; |
597 | 0 | if (msg->via1->next){ |
598 | 0 | msg->via2=msg->via1->next; |
599 | 0 | msg->parsed_flag|=HDR_VIA2_F; |
600 | 0 | } |
601 | 0 | } |
602 | 0 | break; |
603 | 0 | case HDR_FEATURE_CAPS_T: |
604 | 0 | link_sibling_hdr(feature_caps, hf); |
605 | 0 | msg->parsed_flag |= HDR_FEATURE_CAPS_F; |
606 | 0 | break; |
607 | 0 | case HDR_REPLACES_T: |
608 | 0 | link_sibling_hdr(replaces, hf); |
609 | 0 | msg->parsed_flag |= HDR_REPLACES_F; |
610 | 0 | break; |
611 | 0 | case HDR_SECURITY_CLIENT_T: |
612 | 0 | link_sibling_hdr(security_client, hf); |
613 | 0 | msg->parsed_flag |= HDR_SECURITY_CLIENT_F; |
614 | 0 | break; |
615 | 0 | case HDR_SECURITY_SERVER_T: |
616 | 0 | link_sibling_hdr(security_server, hf); |
617 | 0 | msg->parsed_flag |= HDR_SECURITY_SERVER_F; |
618 | 0 | break; |
619 | 0 | case HDR_SECURITY_VERIFY_T: |
620 | 0 | link_sibling_hdr(security_verify, hf); |
621 | 0 | msg->parsed_flag |= HDR_SECURITY_VERIFY_F; |
622 | 0 | break; |
623 | 0 | default: |
624 | 0 | LM_CRIT("unknown header type %d\n", hf->type); |
625 | 0 | goto error; |
626 | 0 | } |
627 | | /* add the header to the list*/ |
628 | 0 | if (msg->last_header==0){ |
629 | 0 | msg->headers=hf; |
630 | 0 | msg->last_header=hf; |
631 | 0 | }else{ |
632 | 0 | msg->last_header->next=hf; |
633 | 0 | msg->last_header=hf; |
634 | 0 | } |
635 | | #ifdef EXTRA_DEBUG |
636 | | LM_DBG("header field type %d, name=<%.*s>, body=<%.*s>\n", |
637 | | hf->type, |
638 | | hf->name.len, ZSW(hf->name.s), |
639 | | hf->body.len, ZSW(hf->body.s)); |
640 | | #endif |
641 | 0 | tmp=rest; |
642 | 0 | } |
643 | 0 | skip: |
644 | 0 | msg->unparsed=tmp; |
645 | 0 | return 0; |
646 | | |
647 | 0 | error: |
648 | 0 | ser_error=E_BAD_REQ; |
649 | 0 | if (hf) pkg_free(hf); |
650 | 0 | if (next) msg->parsed_flag |= orig_flag; |
651 | 0 | return -1; |
652 | 0 | } |
653 | | |
654 | | /* clones the headers list from the `from` sip_msg |
655 | | * into the `to` sip_msg structure */ |
656 | | int clone_headers(struct sip_msg *from_msg, struct sip_msg *to_msg) |
657 | 0 | { |
658 | 0 | int hdrs_no, i; |
659 | 0 | struct hdr_field *hdrs; |
660 | 0 | struct hdr_field *hdr; |
661 | |
|
662 | 0 | #define link_sibling_hdr_case(_hook, _hdr_type) \ |
663 | 0 | case _hdr_type: \ |
664 | 0 | _add_last(&hdrs[i], to_msg->_hook, sibling);\ |
665 | 0 | break |
666 | 0 | #define link_hdr_case(_hook, _hdr_type) \ |
667 | 0 | case _hdr_type: \ |
668 | 0 | to_msg->_hook=&hdrs[i];\ |
669 | 0 | break |
670 | | |
671 | | /* |
672 | | * we need to duplicate the headers because the hdr->parsed field resides |
673 | | * in shm memory, so there might be a different process that access the |
674 | | * parsed field and find the structure parsed by the current process in |
675 | | * pkg |
676 | | */ |
677 | 0 | for (hdrs_no = 0, hdr = from_msg->headers; hdr; hdr = hdr->next) |
678 | 0 | hdrs_no++; |
679 | |
|
680 | 0 | hdrs = pkg_malloc(hdrs_no * sizeof(struct hdr_field)); |
681 | 0 | if (!hdrs) { |
682 | 0 | LM_ERR("could not allocate %d contact headers!\n", hdrs_no); |
683 | 0 | return -1; |
684 | 0 | } |
685 | | |
686 | | /* reset all header fields before populating new ones */ |
687 | 0 | to_msg->h_via1 = NULL; |
688 | 0 | to_msg->callid = NULL; |
689 | 0 | to_msg->to = NULL; |
690 | 0 | to_msg->cseq = NULL; |
691 | 0 | to_msg->from = NULL; |
692 | 0 | to_msg->contact = NULL; |
693 | 0 | to_msg->maxforwards = NULL; |
694 | 0 | to_msg->route = NULL; |
695 | 0 | to_msg->record_route = NULL; |
696 | 0 | to_msg->path = NULL; |
697 | 0 | to_msg->content_type = NULL; |
698 | 0 | to_msg->content_length = NULL; |
699 | 0 | to_msg->authorization = NULL; |
700 | 0 | to_msg->expires = NULL; |
701 | 0 | to_msg->proxy_auth = NULL; |
702 | 0 | to_msg->supported = NULL; |
703 | 0 | to_msg->proxy_require = NULL; |
704 | 0 | to_msg->unsupported = NULL; |
705 | 0 | to_msg->allow = NULL; |
706 | 0 | to_msg->event = NULL; |
707 | 0 | to_msg->accept = NULL; |
708 | 0 | to_msg->accept_language = NULL; |
709 | 0 | to_msg->organization = NULL; |
710 | 0 | to_msg->priority = NULL; |
711 | 0 | to_msg->subject = NULL; |
712 | 0 | to_msg->user_agent = NULL; |
713 | 0 | to_msg->content_disposition = NULL; |
714 | 0 | to_msg->accept_disposition = NULL; |
715 | 0 | to_msg->diversion = NULL; |
716 | 0 | to_msg->rpid = NULL; |
717 | 0 | to_msg->refer_to = NULL; |
718 | 0 | to_msg->session_expires = NULL; |
719 | 0 | to_msg->min_se = NULL; |
720 | 0 | to_msg->ppi = NULL; |
721 | 0 | to_msg->pai = NULL; |
722 | 0 | to_msg->privacy = NULL; |
723 | 0 | to_msg->call_info = NULL; |
724 | 0 | to_msg->www_authenticate = NULL; |
725 | 0 | to_msg->proxy_authenticate = NULL; |
726 | 0 | to_msg->min_expires = NULL; |
727 | 0 | to_msg->feature_caps = NULL; |
728 | 0 | to_msg->replaces = NULL; |
729 | 0 | to_msg->security_client = NULL; |
730 | 0 | to_msg->security_server = NULL; |
731 | 0 | to_msg->security_verify = NULL; |
732 | |
|
733 | 0 | for (i = 0, hdr = from_msg->headers; hdr; i++, hdr = hdr->next) { |
734 | 0 | memcpy(&hdrs[i], hdr, sizeof(struct hdr_field)); |
735 | | /* fix next and sibling */ |
736 | 0 | hdrs[i].next = &hdrs[i + 1]; |
737 | 0 | hdrs[i].sibling = NULL; |
738 | 0 | switch(hdr->type) { |
739 | 0 | link_sibling_hdr_case(h_via1, HDR_VIA_T); |
740 | 0 | link_hdr_case (callid, HDR_CALLID_T); |
741 | 0 | link_hdr_case (to, HDR_TO_T); |
742 | 0 | link_hdr_case (cseq, HDR_CSEQ_T); |
743 | 0 | link_hdr_case (from, HDR_FROM_T); |
744 | 0 | link_sibling_hdr_case(contact, HDR_CONTACT_T); |
745 | 0 | link_hdr_case (maxforwards, HDR_MAXFORWARDS_T); |
746 | 0 | link_sibling_hdr_case(route, HDR_ROUTE_T); |
747 | 0 | link_sibling_hdr_case(record_route, HDR_RECORDROUTE_T); |
748 | 0 | link_sibling_hdr_case(path, HDR_PATH_T); |
749 | 0 | link_hdr_case (content_type, HDR_CONTENTTYPE_T); |
750 | 0 | link_hdr_case (content_length, HDR_CONTENTLENGTH_T); |
751 | 0 | link_sibling_hdr_case(authorization, HDR_AUTHORIZATION_T); |
752 | 0 | link_hdr_case (expires, HDR_EXPIRES_T); |
753 | 0 | link_sibling_hdr_case(proxy_auth, HDR_PROXYAUTH_T); |
754 | 0 | link_sibling_hdr_case(supported, HDR_SUPPORTED_T); |
755 | 0 | link_sibling_hdr_case(proxy_require, HDR_PROXYREQUIRE_T); |
756 | 0 | link_sibling_hdr_case(unsupported, HDR_UNSUPPORTED_T); |
757 | 0 | link_sibling_hdr_case(allow, HDR_ALLOW_T); |
758 | 0 | link_sibling_hdr_case(event, HDR_EVENT_T); |
759 | 0 | link_sibling_hdr_case(accept, HDR_ACCEPT_T); |
760 | 0 | link_sibling_hdr_case(accept_language, HDR_ACCEPTLANGUAGE_T); |
761 | 0 | link_hdr_case (organization, HDR_ORGANIZATION_T); |
762 | 0 | link_hdr_case (priority, HDR_PRIORITY_T); |
763 | 0 | link_hdr_case (subject, HDR_SUBJECT_T); |
764 | 0 | link_hdr_case (user_agent, HDR_USERAGENT_T); |
765 | 0 | link_hdr_case (content_disposition, HDR_CONTENTDISPOSITION_T); |
766 | 0 | link_sibling_hdr_case(accept_disposition, HDR_ACCEPTDISPOSITION_T); |
767 | 0 | link_sibling_hdr_case(diversion, HDR_DIVERSION_T); |
768 | 0 | link_hdr_case (rpid, HDR_RPID_T); |
769 | 0 | link_hdr_case (refer_to, HDR_REFER_TO_T); |
770 | 0 | link_hdr_case (session_expires, HDR_SESSION_EXPIRES_T); |
771 | 0 | link_hdr_case (min_se, HDR_MIN_SE_T); |
772 | 0 | link_sibling_hdr_case(ppi, HDR_PPI_T); |
773 | 0 | link_sibling_hdr_case(pai, HDR_PAI_T); |
774 | 0 | link_hdr_case (privacy, HDR_PRIVACY_T); |
775 | 0 | link_sibling_hdr_case(call_info, HDR_CALL_INFO_T); |
776 | 0 | link_sibling_hdr_case(www_authenticate, HDR_WWW_AUTHENTICATE_T); |
777 | 0 | link_sibling_hdr_case(proxy_authenticate, HDR_PROXY_AUTHENTICATE_T); |
778 | 0 | link_hdr_case (min_expires, HDR_MIN_EXPIRES_T); |
779 | 0 | link_sibling_hdr_case(feature_caps, HDR_FEATURE_CAPS_T); |
780 | 0 | link_hdr_case (replaces, HDR_REPLACES_T); |
781 | 0 | link_sibling_hdr_case(security_client, HDR_SECURITY_CLIENT_T); |
782 | 0 | link_sibling_hdr_case(security_server, HDR_SECURITY_SERVER_T); |
783 | 0 | link_sibling_hdr_case(security_verify, HDR_SECURITY_VERIFY_T); |
784 | | |
785 | | /* not used in sip_msg, used in MSRP */ |
786 | 0 | case HDR_TO_PATH_T: |
787 | 0 | case HDR_FROM_PATH_T: |
788 | 0 | case HDR_MESSAGE_ID_T: |
789 | 0 | case HDR_BYTE_RANGE_T: |
790 | 0 | case HDR_FAILURE_REPORT_T: |
791 | 0 | case HDR_SUCCESS_REPORT_T: |
792 | 0 | case HDR_STATUS_T: |
793 | 0 | case HDR_USE_PATH_T: |
794 | | |
795 | | /* not having shortcut */ |
796 | 0 | case HDR_RETRY_AFTER_T: |
797 | 0 | case HDR_VIA2_T: |
798 | | |
799 | | /* not actual hdrs */ |
800 | 0 | case HDR_OTHER_T: |
801 | 0 | case HDR_ERROR_T: |
802 | 0 | case HDR_EOH_T: |
803 | 0 | break; |
804 | | /* we do not have a "default" on purpose, so we get |
805 | | * a compile err/war where a new HDR is added and we do |
806 | | * not handle it here. |
807 | | default: |
808 | | LM_ERR("unknown header type %d\n", hdr->type); |
809 | | break; |
810 | | */ |
811 | 0 | } |
812 | 0 | } |
813 | 0 | hdrs[i - 1].next = 0; |
814 | 0 | to_msg->headers = hdrs; |
815 | 0 | #undef link_hdr_case |
816 | 0 | #undef link_sibling_hdr_case |
817 | 0 | return 0; |
818 | 0 | } |
819 | | |
820 | | |
821 | | /* returns 0 if ok, -1 for errors */ |
822 | | int parse_msg_opt(char* buf, unsigned int len, struct sip_msg* msg, |
823 | | int free_on_err) |
824 | 0 | { |
825 | |
|
826 | 0 | char *tmp; |
827 | 0 | char* rest; |
828 | 0 | struct msg_start *fl; |
829 | 0 | int offset; |
830 | 0 | hdr_flags_t flags; |
831 | | |
832 | | /* eat crlf from the beginning */ |
833 | 0 | for (tmp=buf; (unsigned int)(tmp-buf) < len |
834 | 0 | && (*tmp=='\n' || *tmp=='\r'); tmp++); |
835 | 0 | offset=tmp-buf; |
836 | 0 | fl=&(msg->first_line); |
837 | 0 | rest=parse_first_line(tmp, len-offset, fl); |
838 | |
|
839 | 0 | offset+=rest-tmp; |
840 | 0 | tmp=rest; |
841 | 0 | switch(fl->type){ |
842 | 0 | case SIP_INVALID: |
843 | 0 | LM_DBG("invalid message\n"); |
844 | | /* if failed to parse the first line, we simply consider that the whole |
845 | | buffer was parsed, so that nothing is left to be parsed :) - this will |
846 | | do the trick and make "msg" struct acceptable for following parsing |
847 | | attempts */ |
848 | 0 | msg->unparsed = msg->buf + msg->len; |
849 | 0 | goto error; |
850 | 0 | break; |
851 | 0 | case SIP_REQUEST: |
852 | 0 | LM_DBG("SIP Request:\n"); |
853 | 0 | LM_DBG(" method: <%.*s>\n",fl->u.request.method.len, |
854 | 0 | ZSW(fl->u.request.method.s)); |
855 | 0 | LM_DBG(" uri: <%.*s>\n",fl->u.request.uri.len, |
856 | 0 | ZSW(fl->u.request.uri.s)); |
857 | 0 | LM_DBG(" version: <%.*s>\n",fl->u.request.version.len, |
858 | 0 | ZSW(fl->u.request.version.s)); |
859 | 0 | flags=HDR_EOH_F; |
860 | 0 | break; |
861 | 0 | case SIP_REPLY: |
862 | 0 | LM_DBG("SIP Reply (status):\n"); |
863 | 0 | LM_DBG(" version: <%.*s>\n",fl->u.reply.version.len, |
864 | 0 | ZSW(fl->u.reply.version.s)); |
865 | 0 | LM_DBG(" status: <%.*s>\n", fl->u.reply.status.len, |
866 | 0 | ZSW(fl->u.reply.status.s)); |
867 | 0 | LM_DBG(" reason: <%.*s>\n", fl->u.reply.reason.len, |
868 | 0 | ZSW(fl->u.reply.reason.s)); |
869 | 0 | flags=HDR_EOH_F; |
870 | 0 | break; |
871 | 0 | default: |
872 | 0 | LM_DBG("unknown type %d\n",fl->type); |
873 | 0 | goto error; |
874 | 0 | } |
875 | 0 | msg->unparsed=tmp; |
876 | | /*find first Via: */ |
877 | 0 | if (parse_headers(msg, flags, 0)==-1) goto parse_error; |
878 | | |
879 | | #ifdef EXTRA_DEBUG |
880 | | /* dump parsed data */ |
881 | | if (msg->via1){ |
882 | | LM_DBG(" first via: <%.*s/%.*s/%.*s> <%.*s:%.*s(%d)>\n", |
883 | | msg->via1->name.len, |
884 | | ZSW(msg->via1->name.s), |
885 | | msg->via1->version.len, |
886 | | ZSW(msg->via1->version.s), |
887 | | msg->via1->transport.len, |
888 | | ZSW(msg->via1->transport.s), |
889 | | msg->via1->host.len, |
890 | | ZSW(msg->via1->host.s), |
891 | | msg->via1->port_str.len, |
892 | | ZSW(msg->via1->port_str.s), |
893 | | msg->via1->port); |
894 | | if (msg->via1->params.s) LM_DBG(";<%.*s>\n", |
895 | | msg->via1->params.len, ZSW(msg->via1->params.s)); |
896 | | if (msg->via1->comment.s) |
897 | | LM_DBG(" <%.*s>\n", |
898 | | msg->via1->comment.len, ZSW(msg->via1->comment.s)); |
899 | | LM_DBG ("\n"); |
900 | | } |
901 | | if (msg->via2){ |
902 | | LM_DBG(" first via: <%.*s/%.*s/%.*s> <%.*s:%.*s(%d)>\n", |
903 | | msg->via2->name.len, |
904 | | ZSW(msg->via2->name.s), |
905 | | msg->via2->version.len, |
906 | | ZSW(msg->via2->version.s), |
907 | | msg->via2->transport.len, |
908 | | ZSW(msg->via2->transport.s), |
909 | | msg->via2->host.len, |
910 | | ZSW(msg->via2->host.s), |
911 | | msg->via2->port_str.len, |
912 | | ZSW(msg->via2->port_str.s), |
913 | | msg->via2->port); |
914 | | if (msg->via2->params.s) LM_DBG(";<%.*s>\n", |
915 | | msg->via2->params.len, ZSW(msg->via2->params.s)); |
916 | | if (msg->via2->comment.s) LM_DBG(" <%.*s>\n", |
917 | | msg->via2->comment.len, ZSW(msg->via2->comment.s)); |
918 | | LM_DBG ("\n"); |
919 | | } |
920 | | #endif |
921 | | |
922 | | |
923 | | #ifdef EXTRA_DEBUG |
924 | | LM_DBG("exiting\n"); |
925 | | #endif |
926 | | |
927 | 0 | return 0; |
928 | | |
929 | 0 | parse_error: |
930 | 0 | if (free_on_err) { |
931 | | /* Free the SIP message if it has already been created to |
932 | | * prevent memory leaks */ |
933 | 0 | free_sip_msg(msg); |
934 | 0 | memset(msg, 0, sizeof(*msg)); |
935 | 0 | } |
936 | |
|
937 | 0 | error: |
938 | | /* more debugging, msg->orig is/should be null terminated*/ |
939 | 0 | LM_ERR("message=<%.*s>\n", (int)len, ZSW(buf)); |
940 | 0 | return -1; |
941 | 0 | } |
942 | | |
943 | | |
944 | | |
945 | | void free_reply_lump( struct lump_rpl *lump) |
946 | 0 | { |
947 | 0 | struct lump_rpl *foo, *bar; |
948 | 0 | for(foo=lump;foo;) |
949 | 0 | { |
950 | 0 | bar=foo->next; |
951 | 0 | free_lump_rpl(foo); |
952 | 0 | foo = bar; |
953 | 0 | } |
954 | 0 | } |
955 | | |
956 | | |
957 | | /* Free only the content, not the msg structure itself |
958 | | * NOTE: the function doesn't do any cleanup/reset of the subfields */ |
959 | | void free_sip_msg(struct sip_msg* msg) |
960 | 0 | { |
961 | 0 | if (msg->msg_cb) |
962 | 0 | msg_callback_process(msg, MSG_DESTROY, NULL); |
963 | 0 | if (msg->new_uri.s) |
964 | 0 | pkg_free(msg->new_uri.s); |
965 | 0 | if (msg->set_global_address.s) |
966 | 0 | pkg_free(msg->set_global_address.s); |
967 | 0 | if (msg->set_global_port.s) |
968 | 0 | pkg_free(msg->set_global_port.s); |
969 | 0 | if (msg->dst_uri.s) |
970 | 0 | pkg_free(msg->dst_uri.s); |
971 | 0 | if (msg->path_vec.s) |
972 | 0 | pkg_free(msg->path_vec.s); |
973 | 0 | if (msg->headers) |
974 | 0 | free_hdr_field_lst(msg->headers); |
975 | 0 | if (msg->add_rm) |
976 | 0 | free_lump_list(msg->add_rm); |
977 | 0 | if (msg->body_lumps) |
978 | 0 | free_lump_list(msg->body_lumps); |
979 | 0 | if (msg->sdp_ops ) |
980 | 0 | free_sdp_ops(msg->sdp_ops); |
981 | 0 | if (msg->reply_lump) |
982 | 0 | free_reply_lump(msg->reply_lump); |
983 | 0 | if (msg->body ) |
984 | 0 | free_sip_body(msg->body); |
985 | | /* don't free anymore -- now a pointer to a static buffer */ |
986 | 0 | } |
987 | | |
988 | | |
989 | | /* make sure all HFs needed for transaction identification have been |
990 | | parsed; return 0 if those HFs can't be found |
991 | | */ |
992 | | |
993 | | int check_transaction_quadruple( struct sip_msg* msg ) |
994 | 0 | { |
995 | 0 | if ( parse_headers(msg, HDR_FROM_F|HDR_TO_F|HDR_CALLID_F|HDR_CSEQ_F,0)!=-1 |
996 | 0 | && msg->from && msg->to && msg->callid && msg->cseq ) { |
997 | 0 | return 1; |
998 | 0 | } else { |
999 | 0 | ser_error=E_BAD_TUPEL; |
1000 | 0 | return 0; |
1001 | 0 | } |
1002 | 0 | } |
1003 | | |
1004 | | |
1005 | | /* |
1006 | | * Make a private copy of the string and assign it to new_uri |
1007 | | */ |
1008 | | int set_ruri(struct sip_msg *msg, str *uri) |
1009 | 0 | { |
1010 | 0 | if (!msg || !uri) { |
1011 | 0 | LM_ERR("invalid parameter value\n"); |
1012 | 0 | return -1; |
1013 | 0 | } |
1014 | | |
1015 | | /* strange/corrupt input: best to assume it's an empty URI */ |
1016 | 0 | if (!uri->s || uri->len == 0) { |
1017 | 0 | pkg_free(msg->new_uri.s); |
1018 | 0 | memset(&msg->new_uri, 0, sizeof msg->new_uri); |
1019 | 0 | return 0; |
1020 | 0 | } |
1021 | | |
1022 | 0 | if (msg->new_uri.s && (msg->new_uri.len >= uri->len)) { |
1023 | 0 | memcpy(msg->new_uri.s, uri->s, uri->len); |
1024 | 0 | msg->new_uri.len = uri->len; |
1025 | 0 | } else { |
1026 | 0 | msg->new_uri.s = pkg_realloc(msg->new_uri.s, uri->len + 1); |
1027 | 0 | if (!msg->new_uri.s) { |
1028 | 0 | LM_ERR("not enough pkg memory (%d)\n",uri->len); |
1029 | 0 | return -1; |
1030 | 0 | } |
1031 | | |
1032 | 0 | memcpy(msg->new_uri.s, uri->s, uri->len); |
1033 | 0 | msg->new_uri.len = uri->len; |
1034 | 0 | } |
1035 | | |
1036 | 0 | set_ruri_q(msg, Q_UNSPECIFIED); |
1037 | 0 | msg->parsed_uri_ok = 0; |
1038 | 0 | return 0; |
1039 | 0 | } |
1040 | | |
1041 | | |
1042 | | |
1043 | | /* |
1044 | | * Make a private copy of the string and assign it to dst_uri |
1045 | | */ |
1046 | | int set_dst_uri(struct sip_msg *msg, str *uri) |
1047 | 0 | { |
1048 | 0 | if (!msg || !uri) { |
1049 | 0 | LM_ERR("invalid parameter value\n"); |
1050 | 0 | return -1; |
1051 | 0 | } |
1052 | | |
1053 | | /* strange/corrupt input: best to assume it's an empty URI */ |
1054 | 0 | if (!uri->s || uri->len == 0) { |
1055 | 0 | pkg_free(msg->dst_uri.s); |
1056 | 0 | memset(&msg->dst_uri, 0, sizeof msg->dst_uri); |
1057 | 0 | return 0; |
1058 | 0 | } |
1059 | | |
1060 | 0 | if (msg->dst_uri.s && (msg->dst_uri.len >= uri->len)) { |
1061 | 0 | memcpy(msg->dst_uri.s, uri->s, uri->len); |
1062 | 0 | msg->dst_uri.len = uri->len; |
1063 | 0 | } else { |
1064 | 0 | msg->dst_uri.s = pkg_realloc(msg->dst_uri.s, uri->len); |
1065 | 0 | if (!msg->dst_uri.s) { |
1066 | 0 | LM_ERR("not enough pkg memory\n"); |
1067 | 0 | return -1; |
1068 | 0 | } |
1069 | | |
1070 | 0 | memcpy(msg->dst_uri.s, uri->s, uri->len); |
1071 | 0 | msg->dst_uri.len = uri->len; |
1072 | 0 | } |
1073 | | |
1074 | 0 | return 0; |
1075 | 0 | } |
1076 | | |
1077 | | void reset_dst_uri(struct sip_msg *msg) |
1078 | 0 | { |
1079 | 0 | if(msg->dst_uri.s!=0) |
1080 | 0 | pkg_free(msg->dst_uri.s); |
1081 | 0 | msg->dst_uri.s = 0; |
1082 | 0 | msg->dst_uri.len = 0; |
1083 | 0 | } |
1084 | | |
1085 | | int set_dst_host_port(struct sip_msg *msg, str *host, str *port) |
1086 | 0 | { |
1087 | 0 | char *tmp, *end, *crt, *new_uri; |
1088 | 0 | int len; |
1089 | 0 | struct sip_uri uri; |
1090 | 0 | int user = 0; |
1091 | |
|
1092 | 0 | tmp = msg->dst_uri.s; |
1093 | 0 | len = msg->dst_uri.len; |
1094 | |
|
1095 | 0 | if (tmp == NULL || len == 0) { |
1096 | 0 | LM_ERR("failure - null uri\n"); |
1097 | 0 | return -1; |
1098 | 0 | } |
1099 | 0 | if (host && (host->s == NULL || host->len == 0)) { |
1100 | 0 | LM_ERR("cannot set a null uri domain\n"); |
1101 | 0 | return -1; |
1102 | 0 | } |
1103 | 0 | if (parse_uri(tmp, len, &uri)<0) { |
1104 | 0 | LM_ERR("bad uri <%.*s>, dropping packet\n", len, tmp); |
1105 | 0 | return -1; |
1106 | 0 | } |
1107 | 0 | new_uri=pkg_malloc(MAX_URI_SIZE); |
1108 | 0 | if (new_uri == NULL) { |
1109 | 0 | LM_ERR("memory allocation failure\n"); |
1110 | 0 | return -1; |
1111 | 0 | } |
1112 | 0 | end=new_uri+MAX_URI_SIZE; |
1113 | 0 | crt=new_uri; |
1114 | 0 | len = (uri.user.len?uri.user.s:uri.host.s) - tmp; |
1115 | 0 | if (crt+len>end) goto error_uri; |
1116 | 0 | memcpy(crt,tmp,len); |
1117 | 0 | crt += len; |
1118 | | /* user */ |
1119 | 0 | tmp = uri.user.s; |
1120 | 0 | len = uri.user.len; |
1121 | 0 | if (tmp) { |
1122 | 0 | if (crt+len>end) goto error_uri; |
1123 | 0 | memcpy(crt,tmp,len); |
1124 | 0 | crt += len; |
1125 | 0 | user = 1; |
1126 | 0 | } |
1127 | | /* passwd */ |
1128 | 0 | tmp = uri.passwd.s; |
1129 | 0 | len = uri.passwd.len; |
1130 | 0 | if (tmp) { |
1131 | 0 | if (crt+len+1>end) goto error_uri; |
1132 | 0 | *crt++=':'; |
1133 | 0 | memcpy(crt, tmp, len); |
1134 | 0 | crt += len; |
1135 | 0 | } |
1136 | | /* host */ |
1137 | 0 | if (host) { |
1138 | 0 | tmp = host->s; |
1139 | 0 | len = host->len; |
1140 | 0 | } else { |
1141 | 0 | tmp = uri.host.s; |
1142 | 0 | len = uri.host.len; |
1143 | 0 | } |
1144 | 0 | if (tmp) { |
1145 | 0 | if (user) { |
1146 | 0 | if (crt+1>end) goto error_uri; |
1147 | 0 | *crt++='@'; |
1148 | 0 | } |
1149 | 0 | if (crt+len+1>end) goto error_uri; |
1150 | 0 | memcpy(crt, tmp, len); |
1151 | 0 | crt += len; |
1152 | 0 | } |
1153 | | /* port */ |
1154 | 0 | if (port) { |
1155 | 0 | tmp = port->s; |
1156 | 0 | len = port->len; |
1157 | 0 | } else { |
1158 | 0 | tmp = uri.port.s; |
1159 | 0 | len = uri.port.len; |
1160 | 0 | } |
1161 | 0 | if (tmp && len > 0) { |
1162 | 0 | if (crt+len+1>end) goto error_uri; |
1163 | 0 | *crt++=':'; |
1164 | 0 | memcpy(crt, tmp, len); |
1165 | 0 | crt += len; |
1166 | 0 | } |
1167 | | /* params */ |
1168 | 0 | tmp=uri.params.s; |
1169 | 0 | if (tmp){ |
1170 | 0 | len=uri.params.len; if(crt+len+1>end) goto error_uri; |
1171 | 0 | *crt++=';'; |
1172 | 0 | memcpy(crt,tmp,len); |
1173 | 0 | crt += len; |
1174 | 0 | } |
1175 | | /* headers */ |
1176 | 0 | tmp=uri.headers.s; |
1177 | 0 | if (tmp){ |
1178 | 0 | len=uri.headers.len; if(crt+len+1>end) goto error_uri; |
1179 | 0 | *crt++='?'; |
1180 | 0 | memcpy(crt,tmp,len); |
1181 | 0 | crt += len; |
1182 | 0 | } |
1183 | 0 | *crt=0; /* null terminate the thing */ |
1184 | | /* copy it to the msg */ |
1185 | 0 | pkg_free(msg->dst_uri.s); |
1186 | 0 | msg->dst_uri.s=new_uri; |
1187 | 0 | msg->dst_uri.len=crt-new_uri; |
1188 | | |
1189 | 0 | return 0; |
1190 | | |
1191 | 0 | error_uri: |
1192 | 0 | pkg_free(new_uri); |
1193 | 0 | return -1; |
1194 | 0 | } |
1195 | | |
1196 | | int rewrite_ruri(struct sip_msg *msg, str *sval, int ival, |
1197 | | enum rw_ruri_part part) |
1198 | 0 | { |
1199 | 0 | int user = 0; |
1200 | 0 | char *tmp, *new_uri, *end, *crt; |
1201 | 0 | int len; |
1202 | 0 | struct sip_uri uri; |
1203 | |
|
1204 | 0 | if (msg->new_uri.s) { |
1205 | 0 | tmp=msg->new_uri.s; |
1206 | 0 | len=msg->new_uri.len; |
1207 | 0 | }else{ |
1208 | 0 | tmp=msg->first_line.u.request.uri.s; |
1209 | 0 | len=msg->first_line.u.request.uri.len; |
1210 | 0 | } |
1211 | 0 | if (parse_uri(tmp, len, &uri)<0){ |
1212 | 0 | LM_ERR("bad uri <%.*s>, dropping packet\n", len, tmp); |
1213 | 0 | return -1; |
1214 | 0 | } |
1215 | | |
1216 | 0 | new_uri=pkg_malloc(MAX_URI_SIZE); |
1217 | 0 | if (new_uri==0){ |
1218 | 0 | LM_ERR("memory allocation failure\n"); |
1219 | 0 | return -1; |
1220 | 0 | } |
1221 | 0 | end=new_uri+MAX_URI_SIZE; |
1222 | 0 | crt=new_uri; |
1223 | | /* begin copying */ |
1224 | 0 | len = (uri.user.len?uri.user.s:uri.host.s) - tmp; |
1225 | 0 | if (crt+len>end) goto error; |
1226 | 0 | memcpy(crt,tmp,len);crt+=len; |
1227 | |
|
1228 | 0 | if (part==RW_RURI_PREFIX) { |
1229 | 0 | if (crt+sval->len>end) goto error; |
1230 | 0 | memcpy( crt, sval->s, sval->len); |
1231 | 0 | crt+=sval->len; |
1232 | | /* whatever we had before, with prefix we have username |
1233 | | now */ |
1234 | 0 | user=1; |
1235 | 0 | } |
1236 | | |
1237 | 0 | if ((part==RW_RURI_USER)||(part==RW_RURI_USERPASS)) { |
1238 | 0 | tmp=sval->s; |
1239 | 0 | len=sval->len; |
1240 | 0 | } else if (part==RW_RURI_STRIP) { |
1241 | 0 | if (ival>uri.user.len) { |
1242 | 0 | LM_WARN("too long strip asked; " |
1243 | 0 | " deleting username: %d of <%.*s>\n", |
1244 | 0 | ival, uri.user.len, uri.user.s); |
1245 | 0 | len=0; |
1246 | 0 | } else if (ival==uri.user.len) { |
1247 | 0 | len=0; |
1248 | 0 | } else { |
1249 | 0 | tmp=uri.user.s + ival; |
1250 | 0 | len=uri.user.len - ival; |
1251 | 0 | } |
1252 | 0 | } else if (part==RW_RURI_STRIP_TAIL) { |
1253 | 0 | if (ival>uri.user.len) { |
1254 | 0 | LM_WARN("too long strip_tail asked;" |
1255 | 0 | " deleting username: %d of <%.*s>\n", |
1256 | 0 | ival, uri.user.len, uri.user.s); |
1257 | 0 | len=0; |
1258 | 0 | } else if (ival==uri.user.len) { |
1259 | 0 | len=0; |
1260 | 0 | } else { |
1261 | 0 | tmp=uri.user.s; |
1262 | 0 | len=uri.user.len - ival; |
1263 | 0 | } |
1264 | 0 | } else { |
1265 | 0 | tmp=uri.user.s; |
1266 | 0 | len=uri.user.len; |
1267 | 0 | } |
1268 | |
|
1269 | 0 | if (len){ |
1270 | 0 | if(crt+len>end) goto error; |
1271 | 0 | memcpy(crt,tmp,len);crt+=len; |
1272 | 0 | user=1; /* we have an user field so mark it */ |
1273 | 0 | } |
1274 | | |
1275 | 0 | if (part==RW_RURI_USERPASS) tmp=0; |
1276 | 0 | else tmp=uri.passwd.s; |
1277 | | /* passwd */ |
1278 | 0 | if (tmp){ |
1279 | 0 | len=uri.passwd.len; if(crt+len+1>end) goto error; |
1280 | 0 | *crt=':'; crt++; |
1281 | 0 | memcpy(crt,tmp,len);crt+=len; |
1282 | 0 | } |
1283 | | /* host */ |
1284 | 0 | if (user || tmp){ /* add @ */ |
1285 | 0 | if(crt+1>end) goto error; |
1286 | 0 | *crt='@'; crt++; |
1287 | 0 | } |
1288 | 0 | if ((part==RW_RURI_HOST) ||(part==RW_RURI_HOSTPORT)) { |
1289 | 0 | tmp=sval->s; |
1290 | 0 | len=sval->len; |
1291 | 0 | } else { |
1292 | 0 | tmp=uri.host.s; |
1293 | 0 | len = uri.host.len; |
1294 | 0 | } |
1295 | 0 | if (tmp){ |
1296 | 0 | if(crt+len>end) goto error; |
1297 | 0 | memcpy(crt,tmp,len);crt+=len; |
1298 | 0 | } |
1299 | | /* port */ |
1300 | 0 | if (part==RW_RURI_HOSTPORT) tmp=0; |
1301 | 0 | else if (part==RW_RURI_PORT) { |
1302 | 0 | tmp=sval->s; |
1303 | 0 | len=sval->len; |
1304 | 0 | } else { |
1305 | 0 | tmp=uri.port.s; |
1306 | 0 | len = uri.port.len; |
1307 | 0 | } |
1308 | 0 | if (tmp && len>0){ |
1309 | 0 | if(crt+len+1>end) goto error; |
1310 | 0 | *crt=':'; crt++; |
1311 | 0 | memcpy(crt,tmp,len);crt+=len; |
1312 | 0 | } |
1313 | | /* params */ |
1314 | 0 | tmp=uri.params.s; |
1315 | 0 | if (tmp){ |
1316 | | /* include in param string the starting ';' */ |
1317 | 0 | len=uri.params.len+1; |
1318 | 0 | tmp--; |
1319 | 0 | if(crt+len+1>end) goto error; |
1320 | | /* if a maddr param is present, strip it out */ |
1321 | 0 | if (uri.maddr.len && |
1322 | 0 | (part==RW_RURI_HOSTPORT || part==RW_RURI_HOST)) { |
1323 | 0 | memcpy(crt,tmp,uri.maddr.s-tmp-1); |
1324 | 0 | crt+=uri.maddr.s-tmp-1; |
1325 | 0 | memcpy(crt,uri.maddr_val.s+uri.maddr_val.len, |
1326 | 0 | tmp+len-uri.maddr_val.s-uri.maddr_val.len); |
1327 | 0 | crt+=tmp+len-uri.maddr_val.s-uri.maddr_val.len; |
1328 | 0 | } else { |
1329 | 0 | memcpy(crt,tmp,len);crt+=len; |
1330 | 0 | } |
1331 | 0 | } |
1332 | | /* headers */ |
1333 | 0 | tmp=uri.headers.s; |
1334 | 0 | if (tmp){ |
1335 | 0 | len=uri.headers.len; if(crt+len+1>end) goto error; |
1336 | 0 | *crt='?'; crt++; |
1337 | 0 | memcpy(crt,tmp,len);crt+=len; |
1338 | 0 | } |
1339 | 0 | *crt=0; /* null terminate the thing */ |
1340 | | /* copy it to the msg */ |
1341 | 0 | if (msg->new_uri.s) pkg_free(msg->new_uri.s); |
1342 | 0 | msg->new_uri.s=new_uri; |
1343 | 0 | msg->new_uri.len=crt-new_uri; |
1344 | 0 | msg->parsed_uri_ok=0; |
1345 | |
|
1346 | 0 | return 0; |
1347 | | |
1348 | 0 | error: |
1349 | 0 | LM_ERR("uri too long\n"); |
1350 | 0 | if (new_uri) |
1351 | 0 | pkg_free(new_uri); |
1352 | 0 | return -1; |
1353 | 0 | } |
1354 | | |
1355 | | /* |
1356 | | * Make a private copy of the string and assign it to path_vec |
1357 | | */ |
1358 | | int set_path_vector(struct sip_msg *msg, str *path) |
1359 | 0 | { |
1360 | 0 | if (!msg || !path) { |
1361 | 0 | LM_ERR("invalid parameter value\n"); |
1362 | 0 | return -1; |
1363 | 0 | } |
1364 | | |
1365 | | /* strange/corrupt input: best to assume it's an empty URI */ |
1366 | 0 | if (!path->s || path->len == 0) { |
1367 | 0 | pkg_free(msg->path_vec.s); |
1368 | 0 | memset(&msg->path_vec, 0, sizeof msg->path_vec); |
1369 | 0 | return 0; |
1370 | 0 | } |
1371 | | |
1372 | 0 | if (msg->path_vec.s && (msg->path_vec.len >= path->len)) { |
1373 | 0 | memcpy(msg->path_vec.s, path->s, path->len); |
1374 | 0 | msg->path_vec.len = path->len; |
1375 | 0 | } else { |
1376 | 0 | msg->path_vec.s = pkg_realloc(msg->path_vec.s, path->len); |
1377 | 0 | if (!msg->path_vec.s) { |
1378 | 0 | LM_ERR("not enough pkg memory\n"); |
1379 | 0 | return -1; |
1380 | 0 | } |
1381 | | |
1382 | 0 | memcpy(msg->path_vec.s, path->s, path->len); |
1383 | 0 | msg->path_vec.len = path->len; |
1384 | 0 | } |
1385 | | |
1386 | 0 | return 0; |
1387 | 0 | } |
1388 | | |
1389 | | void clear_path_vector(struct sip_msg *msg) |
1390 | 0 | { |
1391 | 0 | if (msg->path_vec.s) { |
1392 | 0 | pkg_free(msg->path_vec.s); |
1393 | 0 | memset(&msg->path_vec, 0, sizeof msg->path_vec); |
1394 | 0 | } |
1395 | 0 | } |
1396 | | |
1397 | | /* convenience macros */ |
1398 | 0 | #define LC(_cp) ((*(_cp))|0x20) |
1399 | | #define SET_FOUND(_new_state) \ |
1400 | 0 | do{\ |
1401 | 0 | fill->s=b;fill->len=p-b;\ |
1402 | 0 | LM_DBG("hdr %d extracted as <%.*s>\n",\ |
1403 | 0 | flag,fill->len,fill->s);\ |
1404 | 0 | flags&=~(flag);\ |
1405 | 0 | if (flags) {state=_new_state;}\ |
1406 | 0 | else {goto done;}\ |
1407 | 0 | }while(0) |
1408 | | #define GET_CSEQ() \ |
1409 | 0 | do{\ |
1410 | 0 | for(p++;p<end&&isspace((int)*p);p++);\ |
1411 | 0 | for(fill->s=b;p<end&&isdigit((int)*p);p++);\ |
1412 | 0 | fill->len=p-fill->s;\ |
1413 | 0 | if ( (flags&=~(flag))==0) goto done;\ |
1414 | 0 | state=1;\ |
1415 | 0 | }while(0) |
1416 | | int extract_ftc_hdrs( char *buf, int len, str *from, str *to, str *cseq,str *callid) |
1417 | 0 | { |
1418 | 0 | char *end, *p; |
1419 | 0 | char *b; |
1420 | 0 | str *fill; |
1421 | 0 | int state; |
1422 | 0 | int flags; |
1423 | 0 | int flag; |
1424 | |
|
1425 | 0 | p = buf; |
1426 | 0 | end = buf+len; |
1427 | 0 | state = 1; |
1428 | 0 | b = 0; |
1429 | 0 | flags = ((from!=0)?0x1:0) | ((to!=0)?0x2:0) | ((cseq!=0)?0x4:0) |
1430 | 0 | | ((callid!=0)?0x8:0); |
1431 | 0 | flag = 0; |
1432 | 0 | fill = 0; |
1433 | |
|
1434 | 0 | LM_DBG("flags = %d\n",flags); |
1435 | |
|
1436 | 0 | while(p<end) { |
1437 | 0 | switch (*p) { |
1438 | 0 | case '\n': |
1439 | 0 | case '\r': |
1440 | 0 | switch (state) { |
1441 | 0 | case 4: state=5;break; |
1442 | 0 | case 5: state=6;break; |
1443 | 0 | case 6: if(!(*p=='\n' && *(p-1)=='\r')) SET_FOUND(1);break; |
1444 | 0 | default : state=2;break; |
1445 | 0 | } |
1446 | 0 | break; |
1447 | 0 | case ' ': |
1448 | 0 | case '\t': |
1449 | 0 | switch (state) { |
1450 | 0 | case 4: case 6: state=5; break; |
1451 | 0 | case 2: state=1; break;/*folded line*/ |
1452 | 0 | } |
1453 | 0 | break; |
1454 | 0 | case ':': |
1455 | 0 | switch (state) { |
1456 | 0 | case 4:case 5: state=5;if(flag==0x04)GET_CSEQ();break; |
1457 | 0 | case 6: SET_FOUND(1);break;/*found*/ |
1458 | 0 | case 2: state=1;break; |
1459 | 0 | } |
1460 | 0 | break; |
1461 | 0 | case 'f': |
1462 | 0 | case 'F': |
1463 | 0 | if (state==5) break; |
1464 | 0 | if (state==6) SET_FOUND(2);/*found*/; |
1465 | 0 | if (state!=2) {state = 1;break;} |
1466 | | /* hdr starting with 'f' */ |
1467 | 0 | if (from==0) break; |
1468 | 0 | b = p; |
1469 | 0 | if (p+3<end && LC(p+1)=='r' && LC(p+2)=='o' && LC(p+3)=='m') |
1470 | 0 | p+=3; |
1471 | 0 | state = 4; /* "f" or "from" found */ |
1472 | 0 | fill = from; |
1473 | 0 | flag = 0x1; |
1474 | 0 | break; |
1475 | 0 | case 't': |
1476 | 0 | case 'T': |
1477 | 0 | if (state==5) break; |
1478 | 0 | if (state==6) SET_FOUND(2);/*found*/; |
1479 | 0 | if (state!=2) {state = 1;break;} |
1480 | | /* hdr starting with 't' */ |
1481 | 0 | if (to==0) break; |
1482 | 0 | b = p; |
1483 | 0 | if (p+1<end && LC(p+1)=='o') |
1484 | 0 | p+=1; |
1485 | 0 | state = 4; /* "t" or "to" found */ |
1486 | 0 | fill = to; |
1487 | 0 | flag = 0x2; |
1488 | 0 | break; |
1489 | 0 | case 'c': |
1490 | 0 | case 'C': |
1491 | 0 | if (state==5) break; |
1492 | 0 | if (state==6) SET_FOUND(2);/*found*/; |
1493 | 0 | if (state!=2) {state = 1;break;} |
1494 | | /* hdr starting with 'c' */ |
1495 | 0 | if (cseq==0 && callid == 0) break; |
1496 | 0 | if (cseq && p+3<end && LC(p+1)=='s' && LC(p+2)=='e' && LC(p+3)=='q') { |
1497 | 0 | b = p; |
1498 | 0 | p+=3; |
1499 | 0 | state = 4; /* "cseq" found */ |
1500 | 0 | fill = cseq; |
1501 | 0 | flag = 0x4; |
1502 | 0 | } else if (callid && p+6<end && LC(p+1)=='a' && LC(p+2) == 'l' && |
1503 | 0 | LC(p+3) == 'l' && LC(p+4) == '-' && LC(p+5) == 'i' && |
1504 | 0 | LC(p+6) == 'd') { |
1505 | 0 | b = p; |
1506 | 0 | p+=6; |
1507 | 0 | state = 4; /* callid found */ |
1508 | 0 | fill = callid; |
1509 | 0 | flag = 0x8; |
1510 | 0 | } |
1511 | 0 | break; |
1512 | 0 | case 'I': |
1513 | 0 | case 'i': |
1514 | 0 | if (state==5) break; |
1515 | 0 | if (state==6) SET_FOUND(2);/*found*/; |
1516 | 0 | if (state!=2) {state = 1;break;} |
1517 | 0 | if (callid == 0) break; |
1518 | 0 | b = p; |
1519 | 0 | state=4; /* callid found */ |
1520 | 0 | fill = callid; |
1521 | 0 | flag=0x8; |
1522 | 0 | break; |
1523 | 0 | default: |
1524 | 0 | switch (state) { |
1525 | 0 | case 2:case 4: state=1; break; |
1526 | 0 | case 6: SET_FOUND(1);break;/*found*/; |
1527 | 0 | } |
1528 | 0 | } |
1529 | 0 | p++; |
1530 | 0 | } |
1531 | | |
1532 | 0 | LM_CRIT("no hdrs found in outgoing buffer\n"); |
1533 | 0 | return -1; |
1534 | 0 | done: |
1535 | 0 | return 0; |
1536 | 0 | } |
1537 | | |
1538 | | |
1539 | | int delete_headers(struct sip_msg *msg, struct hdr_field *hdr) |
1540 | 0 | { |
1541 | 0 | for (; hdr; hdr = hdr->sibling) { |
1542 | 0 | if (!del_lump(msg, hdr->name.s - msg->buf, hdr->len, hdr->type)) { |
1543 | 0 | LM_ERR("failed to delete contact '%.*s'\n", hdr->name.len, |
1544 | 0 | hdr->name.s); |
1545 | 0 | return -1; |
1546 | 0 | } |
1547 | 0 | } |
1548 | | |
1549 | 0 | return 0; |
1550 | 0 | } |