all: updated FSF address in GPL text
[sip-router] / modules / nathelper / nhelpr_funcs.c
1 /*
2  * $Id$
3  *
4  * Copyright (C) 2001-2003 FhG Fokus
5  *
6  * This file is part of Kamailio, a free SIP server.
7  *
8  * Kamailio 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  * Kamailio 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-11-06  body len is computed using the message len (it's
25  *               not taken any more from the msg. content-length) (andrei)
26  *  2008-08-30  body len is taken from Conent-length header as it is more 
27  *               reliable (UDP packages may contain garbage at the end)(bogdan)
28  */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <unistd.h>
34 #include "nhelpr_funcs.h"
35 #include "../../dprint.h"
36 #include "../../config.h"
37 #include "../../ut.h"
38 #include "../../forward.h"
39 #include "../../resolve.h"
40 #include "../../globals.h"
41 #include "../../udp_server.h"
42 #include "../../pt.h"
43 #include "../../parser/msg_parser.h"
44 #include "../../trim.h"
45 #include "../../parser/parse_from.h"
46 #include "../../parser/contact/parse_contact.h"
47 #include "../../parser/parse_uri.h"
48 #include "../../parser/parse_content.h"
49 #include "../../parser/parser_f.h"
50 #include "../../parser/sdp/sdp_helpr_funcs.h"
51
52 #define READ(val) \
53         (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
54 #define advance(_ptr,_n,_str,_error) \
55         do{\
56                 if ((_ptr)+(_n)>(_str).s+(_str).len)\
57                         goto _error;\
58                 (_ptr) = (_ptr) + (_n);\
59         }while(0);
60 #define one_of_16( _x , _t ) \
61         (_x==_t[0]||_x==_t[15]||_x==_t[8]||_x==_t[2]||_x==_t[3]||_x==_t[4]\
62         ||_x==_t[5]||_x==_t[6]||_x==_t[7]||_x==_t[1]||_x==_t[9]||_x==_t[10]\
63         ||_x==_t[11]||_x==_t[12]||_x==_t[13]||_x==_t[14])
64 #define one_of_8( _x , _t ) \
65         (_x==_t[0]||_x==_t[7]||_x==_t[1]||_x==_t[2]||_x==_t[3]||_x==_t[4]\
66         ||_x==_t[5]||_x==_t[6])
67
68
69
70 /**
71  * return:
72  * -1: error
73  *  1: text or sdp
74  *  2: multipart
75  */
76 int check_content_type(struct sip_msg *msg)
77 {
78         static unsigned int appl[16] = {
79                 0x6c707061/*appl*/,0x6c707041/*Appl*/,0x6c705061/*aPpl*/,
80                 0x6c705041/*APpl*/,0x6c507061/*apPl*/,0x6c507041/*ApPl*/,
81                 0x6c505061/*aPPl*/,0x6c505041/*APPl*/,0x4c707061/*appL*/,
82                 0x4c707041/*AppL*/,0x4c705061/*aPpL*/,0x4c705041/*APpL*/,
83                 0x4c507061/*apPL*/,0x4c507041/*ApPL*/,0x4c505061/*aPPL*/,
84                 0x4c505041/*APPL*/};
85         static unsigned int icat[16] = {
86                 0x74616369/*icat*/,0x74616349/*Icat*/,0x74614369/*iCat*/,
87                 0x74614349/*ICat*/,0x74416369/*icAt*/,0x74416349/*IcAt*/,
88                 0x74414369/*iCAt*/,0x74414349/*ICAt*/,0x54616369/*icaT*/,
89                 0x54616349/*IcaT*/,0x54614369/*iCaT*/,0x54614349/*ICaT*/,
90                 0x54416369/*icAT*/,0x54416349/*IcAT*/,0x54414369/*iCAT*/,
91                 0x54414349/*ICAT*/};
92         static unsigned int ion_[8] = {
93                 0x006e6f69/*ion_*/,0x006e6f49/*Ion_*/,0x006e4f69/*iOn_*/,
94                 0x006e4f49/*IOn_*/,0x004e6f69/*ioN_*/,0x004e6f49/*IoN_*/,
95                 0x004e4f69/*iON_*/,0x004e4f49/*ION_*/};
96         static unsigned int sdp_[8] = {
97                 0x00706473/*sdp_*/,0x00706453/*Sdp_*/,0x00704473/*sDp_*/,
98                 0x00704453/*SDp_*/,0x00506473/*sdP_*/,0x00506453/*SdP_*/,
99                 0x00504473/*sDP_*/,0x00504453/*SDP_*/};
100         str           str_type;
101         unsigned int  x;
102         char          *p;
103
104         if (!msg->content_type)
105         {
106                 LM_WARN("the header Content-TYPE is absent!"
107                         "let's assume the content is text/plain ;-)\n");
108                 return 1;
109         }
110
111         trim_len(str_type.len,str_type.s,msg->content_type->body);
112         if (str_type.len>=15 && (*str_type.s=='m' || *str_type.s=='M')
113                         && strncasecmp(str_type.s, "multipart/mixed", 15) == 0) {
114                 return 2;
115     }
116         p = str_type.s;
117         advance(p,4,str_type,error_1);
118         x = READ(p-4);
119         if (!one_of_16(x,appl))
120                 goto other;
121         advance(p,4,str_type,error_1);
122         x = READ(p-4);
123         if (!one_of_16(x,icat))
124                 goto other;
125         advance(p,3,str_type,error_1);
126         x = READ(p-3) & 0x00ffffff;
127         if (!one_of_8(x,ion_))
128                 goto other;
129
130         /* skip spaces and tabs if any */
131         while (*p==' ' || *p=='\t')
132                 advance(p,1,str_type,error_1);
133         if (*p!='/')
134         {
135                 LM_ERR("no / found after primary type\n");
136                 goto error;
137         }
138         advance(p,1,str_type,error_1);
139         while ((*p==' ' || *p=='\t') && p+1<str_type.s+str_type.len)
140                 advance(p,1,str_type,error_1);
141
142         advance(p,3,str_type,error_1);
143         x = READ(p-3) & 0x00ffffff;
144         if (!one_of_8(x,sdp_))
145                 goto other;
146
147         if (*p==';'||*p==' '||*p=='\t'||*p=='\n'||*p=='\r'||*p==0) {
148                 LM_DBG("type <%.*s> found valid\n", (int)(p-str_type.s), str_type.s);
149                 return 1;
150         } else {
151                 LM_ERR("bad end for type!\n");
152                 return -1;
153         }
154
155 error_1:
156         LM_ERR("body ended :-(!\n");
157 error:
158         return -1;
159 other:
160         LM_ERR("invalid type for a message\n");
161         return -1;
162 }
163
164 /*
165  * Get message body and check Content-Type header field
166  */
167 int extract_body(struct sip_msg *msg, str *body )
168 {
169         char c;
170         int skip;
171         int ret;
172         str mpdel;
173         char *rest, *p1, *p2;
174         struct hdr_field hf;
175         unsigned int mime;
176         
177         body->s = get_body(msg);
178         if (body->s==0) {
179                 LM_ERR("failed to get the message body\n");
180                 goto error;
181         }
182         
183         /*
184          * Better use the content-len value - no need of any explicit
185          * parcing as get_body() parsed all headers and Conten-Length
186          * body header is automaticaly parsed when found.
187          */
188         if (msg->content_length==0) {
189                 LM_ERR("failed to get the content length in message\n");
190                 goto error;
191         }
192
193         body->len = get_content_length(msg);
194         if (body->len==0) {
195                 LM_ERR("message body has length zero\n");
196                 goto error;
197         }
198
199         if (body->len + body->s > msg->buf + msg->len) {
200                 LM_ERR("content-length exceeds packet-length by %d\n",
201                                 (int)((body->len + body->s) - (msg->buf + msg->len)));
202                 goto error;
203         }
204
205         /* no need for parse_headers(msg, EOH), get_body will 
206          * parse everything */
207         /*is the content type correct?*/
208         if((ret = check_content_type(msg))==-1)
209         {
210                 LM_ERR("content type mismatching\n");
211                 goto error;
212         }
213
214         if(ret!=2)
215                 goto done;
216
217         /* multipart body */
218         if(get_mixed_part_delimiter(&msg->content_type->body,&mpdel) < 0) {
219                 goto error;
220         }
221         p1 = find_sdp_line_delimiter(body->s, body->s+body->len, mpdel);
222         if (p1 == NULL) {
223                 LM_ERR("empty multipart content\n");
224                 return -1;
225         }
226         p2=p1;
227         c = 0;
228         for(;;)
229         {
230                 p1 = p2;
231                 if (p1 == NULL || p1 >= body->s+body->len)
232                         break; /* No parts left */
233                 p2 = find_next_sdp_line_delimiter(p1, body->s+body->len,
234                                 mpdel, body->s+body->len);
235                 /* p2 is text limit for application parsing */
236                 rest = eat_line(p1 + mpdel.len + 2, p2 - p1 - mpdel.len - 2);
237                 if ( rest > p2 ) {
238                         LM_ERR("Unparsable <%.*s>\n", (int)(p1-p1), p1);
239                         return -1;
240                 }
241                 while( rest<p2 ) {
242                         memset(&hf,0, sizeof(struct hdr_field));
243                         rest = get_sdp_hdr_field(rest, p2, &hf);
244                         if(hf.type==HDR_EOH_T)
245                                 break;
246                         if(hf.type==HDR_ERROR_T)
247                                 return -1;
248                         if(hf.type==HDR_CONTENTTYPE_T) {
249                                 if(decode_mime_type(hf.body.s, hf.body.s + hf.body.len,
250                                                 &mime)==NULL)
251                                         return -1;
252                                 if (((((unsigned int)mime)>>16) == TYPE_APPLICATION)
253                                                 && ((mime&0x00ff) == SUBTYPE_SDP)) {
254                                         c = 1;
255                                 }
256                         }
257                 } /* end of while */
258                 if(c==1)
259                 {
260                         body->s = rest;
261                         body->len = p2-rest;
262                         goto done;
263                 }
264         }
265
266 error:
267         return -1;
268
269 done:
270         for (skip = 0; skip < body->len; skip++) {
271                 c = body->s[body->len - skip - 1];
272                 if (c != '\r' && c != '\n')
273                         break;
274         }
275         if (skip == body->len) {
276                 LM_ERR("empty body");
277                 goto error;
278         }
279         body->len -= skip;
280
281         /*LM_DBG("DEBUG:extract_body:=|%.*s|\n",body->len,body->s);*/
282         return 1;
283 }
284
285
286 /*
287  * Some helper functions taken verbatim from tm module.
288  */
289
290 /*
291  * Extract URI from the Contact header field
292  */
293 int
294 get_contact_uri(struct sip_msg* _m, struct sip_uri *uri, contact_t** _c)
295 {
296
297         if ((parse_headers(_m, HDR_CONTACT_F, 0) == -1) || !_m->contact)
298                 return -1;
299         if (!_m->contact->parsed && parse_contact(_m->contact) < 0) {
300                 LM_ERR("failed to parse Contact body\n");
301                 return -1;
302         }
303         *_c = ((contact_body_t*)_m->contact->parsed)->contacts;
304         if (*_c == NULL)
305                 /* no contacts found */
306                 return -1;
307
308         if (parse_uri((*_c)->uri.s, (*_c)->uri.len, uri) < 0 || uri->host.len <= 0) {
309                 LM_ERR("failed to parse Contact URI [%.*s]\n",
310                         (*_c)->uri.len, ((*_c)->uri.s)?(*_c)->uri.s:"");
311                 return -1;
312         }
313         return 0;
314 }