~ubuntu-branches/debian/sid/kamailio/sid

« back to all changes in this revision

Viewing changes to modules/rtpproxy-ng/rtpproxy_funcs.c

  • Committer: Package Import Robot
  • Author(s): Victor Seva
  • Date: 2014-01-06 11:47:13 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20140106114713-t8xidp4arzrnyeya
Tags: 4.1.1-1
* New upstream release
* debian/patches:
  - add upstream fixes
* Added tls outbound websocket autheph dnssec modules
  - openssl exception added to their license
* removing sparc and ia64 from supported archs
  for mono module (Closes: #728915)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 "rtpproxy_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
/*
 
166
 * Get message body and check Content-Type header field
 
167
 */
 
168
int extract_body(struct sip_msg *msg, str *body )
 
169
{
 
170
        char c;
 
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
                        if (rest < p2 && *rest == '\r') rest++;
 
261
                        if (rest < p2 && *rest == '\n') rest++;
 
262
                        if (rest < p2 && p2[-1] == '\n') p2--;
 
263
                        if (rest < p2 && p2[-1] == '\r') p2--;
 
264
                        body->s = rest;
 
265
                        body->len = p2-rest;
 
266
                        goto done;
 
267
                }
 
268
        }
 
269
 
 
270
error:
 
271
        return -1;
 
272
 
 
273
done:
 
274
        /*LM_DBG("DEBUG:extract_body:=|%.*s|\n",body->len,body->s);*/
 
275
        return 1;
 
276
}
 
277
 
 
278
/*
 
279
 * ser_memmem() returns the location of the first occurrence of data
 
280
 * pattern b2 of size len2 in memory block b1 of size len1 or
 
281
 * NULL if none is found. Obtained from NetBSD.
 
282
 */
 
283
void *
 
284
ser_memmem(const void *b1, const void *b2, size_t len1, size_t len2)
 
285
{
 
286
        /* Initialize search pointer */
 
287
        char *sp = (char *) b1;
 
288
 
 
289
        /* Initialize pattern pointer */
 
290
        char *pp = (char *) b2;
 
291
 
 
292
        /* Initialize end of search address space pointer */
 
293
        char *eos = sp + len1 - len2;
 
294
 
 
295
        /* Sanity check */
 
296
        if(!(b1 && b2 && len1 && len2))
 
297
                return NULL;
 
298
 
 
299
        while (sp <= eos) {
 
300
                if (*sp == *pp)
 
301
                        if (memcmp(sp, pp, len2) == 0)
 
302
                                return sp;
 
303
 
 
304
                        sp++;
 
305
        }
 
306
 
 
307
        return NULL;
 
308
}
 
309
 
 
310
/*
 
311
 * Some helper functions taken verbatim from tm module.
 
312
 */
 
313
 
 
314
/*
 
315
 * Extract Call-ID value
 
316
 * assumes the callid header is already parsed
 
317
 * (so make sure it is, before calling this function or
 
318
 *  it might fail even if the message _has_ a callid)
 
319
 */
 
320
int
 
321
get_callid(struct sip_msg* _m, str* _cid)
 
322
{
 
323
 
 
324
        if ((parse_headers(_m, HDR_CALLID_F, 0) == -1)) {
 
325
                LM_ERR("failed to parse call-id header\n");
 
326
                return -1;
 
327
        }
 
328
 
 
329
        if (_m->callid == NULL) {
 
330
                LM_ERR("call-id not found\n");
 
331
                return -1;
 
332
        }
 
333
 
 
334
        _cid->s = _m->callid->body.s;
 
335
        _cid->len = _m->callid->body.len;
 
336
        trim(_cid);
 
337
        return 0;
 
338
}
 
339
 
 
340
/*
 
341
 * Extract tag from To header field of a response
 
342
 */
 
343
int
 
344
get_to_tag(struct sip_msg* _m, str* _tag)
 
345
{
 
346
 
 
347
        if (parse_to_header(_m) < 0) {
 
348
                LM_ERR("To header field missing\n");
 
349
                return -1;
 
350
        }
 
351
 
 
352
        if (get_to(_m)->tag_value.len) {
 
353
                _tag->s = get_to(_m)->tag_value.s;
 
354
                _tag->len = get_to(_m)->tag_value.len;
 
355
        } else {
 
356
                _tag->s = NULL; /* fixes gcc 4.0 warnings */
 
357
                _tag->len = 0;
 
358
        }
 
359
 
 
360
        return 0;
 
361
}
 
362
 
 
363
/*
 
364
 * Extract tag from From header field of a request
 
365
 */
 
366
int
 
367
get_from_tag(struct sip_msg* _m, str* _tag)
 
368
{
 
369
 
 
370
        if (parse_from_header(_m)<0) {
 
371
                LM_ERR("failed to parse From header\n");
 
372
                return -1;
 
373
        }
 
374
 
 
375
        if (get_from(_m)->tag_value.len) {
 
376
                _tag->s = get_from(_m)->tag_value.s;
 
377
                _tag->len = get_from(_m)->tag_value.len;
 
378
        } else {
 
379
                _tag->s = NULL; /* fixes gcc 4.0 warnings */
 
380
                _tag->len = 0;
 
381
        }
 
382
 
 
383
        return 0;
 
384
}
 
385
 
 
386
/*
 
387
 * Extract URI from the Contact header field
 
388
 */
 
389
int
 
390
get_contact_uri(struct sip_msg* _m, struct sip_uri *uri, contact_t** _c)
 
391
{
 
392
 
 
393
        if ((parse_headers(_m, HDR_CONTACT_F, 0) == -1) || !_m->contact)
 
394
                return -1;
 
395
        if (!_m->contact->parsed && parse_contact(_m->contact) < 0) {
 
396
                LM_ERR("failed to parse Contact body\n");
 
397
                return -1;
 
398
        }
 
399
        *_c = ((contact_body_t*)_m->contact->parsed)->contacts;
 
400
        if (*_c == NULL)
 
401
                /* no contacts found */
 
402
                return -1;
 
403
 
 
404
        if (parse_uri((*_c)->uri.s, (*_c)->uri.len, uri) < 0 || uri->host.len <= 0) {
 
405
                LM_ERR("failed to parse Contact URI [%.*s]\n",
 
406
                        (*_c)->uri.len, ((*_c)->uri.s)?(*_c)->uri.s:"");
 
407
                return -1;
 
408
        }
 
409
        return 0;
 
410
}
 
411
 
 
412
/*
 
413
 * Extract branch from Via header
 
414
 */
 
415
int
 
416
get_via_branch(struct sip_msg* msg, int vianum, str* _branch)
 
417
{
 
418
        struct via_body *via;
 
419
        struct via_param *p;
 
420
 
 
421
        if (parse_via_header(msg, vianum, &via) < 0)
 
422
                return -1;
 
423
 
 
424
        for (p = via->param_lst; p; p = p->next)
 
425
        {
 
426
                if (p->name.len == strlen("branch")
 
427
                                && strncasecmp(p->name.s, "branch", strlen("branch")) == 0) {
 
428
                        _branch->s = p->value.s;
 
429
                        _branch->len = p->value.len;
 
430
                        return 0;
 
431
                }
 
432
        }
 
433
        return -1;
 
434
}