nhelpr_funcs.c

Go to the documentation of this file.
00001 /*
00002  * $Id: nhelpr_funcs.c 5385 2008-12-25 06:08:54Z sobomax $
00003  *
00004  * Copyright (C) 2001-2003 FhG Fokus
00005  *
00006  * This file is part of Kamailio, a free SIP server.
00007  *
00008  * Kamailio is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version
00012  *
00013  * Kamailio is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License 
00019  * along with this program; if not, write to the Free Software 
00020  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00021  *
00022  * History:
00023  * --------
00024  *  2003-11-06  body len is computed using the message len (it's
00025  *               not taken any more from the msg. content-length) (andrei)
00026  *  2008-08-30  body len is taken from Conent-length header as it is more 
00027  *               reliable (UDP packages may contain garbage at the end)(bogdan)
00028  */
00029 
00030 #include <stdio.h>
00031 #include <stdlib.h>
00032 #include <sys/types.h>
00033 #include <unistd.h>
00034 #include "nhelpr_funcs.h"
00035 #include "../../dprint.h"
00036 #include "../../config.h"
00037 #include "../../ut.h"
00038 #include "../../forward.h"
00039 #include "../../resolve.h"
00040 #include "../../globals.h"
00041 #include "../../udp_server.h"
00042 #include "../../pt.h"
00043 #include "../../parser/msg_parser.h"
00044 #include "../../trim.h"
00045 #include "../../parser/parse_from.h"
00046 #include "../../parser/contact/parse_contact.h"
00047 #include "../../parser/parse_uri.h"
00048 #include "../../parser/parse_content.h"
00049 
00050 #define READ(val) \
00051    (*(val + 0) + (*(val + 1) << 8) + (*(val + 2) << 16) + (*(val + 3) << 24))
00052 #define advance(_ptr,_n,_str,_error) \
00053    do{\
00054       if ((_ptr)+(_n)>(_str).s+(_str).len)\
00055          goto _error;\
00056       (_ptr) = (_ptr) + (_n);\
00057    }while(0);
00058 #define one_of_16( _x , _t ) \
00059    (_x==_t[0]||_x==_t[15]||_x==_t[8]||_x==_t[2]||_x==_t[3]||_x==_t[4]\
00060    ||_x==_t[5]||_x==_t[6]||_x==_t[7]||_x==_t[1]||_x==_t[9]||_x==_t[10]\
00061    ||_x==_t[11]||_x==_t[12]||_x==_t[13]||_x==_t[14])
00062 #define one_of_8( _x , _t ) \
00063    (_x==_t[0]||_x==_t[7]||_x==_t[1]||_x==_t[2]||_x==_t[3]||_x==_t[4]\
00064    ||_x==_t[5]||_x==_t[6])
00065 
00066 
00067 
00068 int check_content_type(struct sip_msg *msg)
00069 {
00070    static unsigned int appl[16] = {
00071       0x6c707061/*appl*/,0x6c707041/*Appl*/,0x6c705061/*aPpl*/,
00072       0x6c705041/*APpl*/,0x6c507061/*apPl*/,0x6c507041/*ApPl*/,
00073       0x6c505061/*aPPl*/,0x6c505041/*APPl*/,0x4c707061/*appL*/,
00074       0x4c707041/*AppL*/,0x4c705061/*aPpL*/,0x4c705041/*APpL*/,
00075       0x4c507061/*apPL*/,0x4c507041/*ApPL*/,0x4c505061/*aPPL*/,
00076       0x4c505041/*APPL*/};
00077    static unsigned int icat[16] = {
00078       0x74616369/*icat*/,0x74616349/*Icat*/,0x74614369/*iCat*/,
00079       0x74614349/*ICat*/,0x74416369/*icAt*/,0x74416349/*IcAt*/,
00080       0x74414369/*iCAt*/,0x74414349/*ICAt*/,0x54616369/*icaT*/,
00081       0x54616349/*IcaT*/,0x54614369/*iCaT*/,0x54614349/*ICaT*/,
00082       0x54416369/*icAT*/,0x54416349/*IcAT*/,0x54414369/*iCAT*/,
00083       0x54414349/*ICAT*/};
00084    static unsigned int ion_[8] = {
00085       0x006e6f69/*ion_*/,0x006e6f49/*Ion_*/,0x006e4f69/*iOn_*/,
00086       0x006e4f49/*IOn_*/,0x004e6f69/*ioN_*/,0x004e6f49/*IoN_*/,
00087       0x004e4f69/*iON_*/,0x004e4f49/*ION_*/};
00088    static unsigned int sdp_[8] = {
00089       0x00706473/*sdp_*/,0x00706453/*Sdp_*/,0x00704473/*sDp_*/,
00090       0x00704453/*SDp_*/,0x00506473/*sdP_*/,0x00506453/*SdP_*/,
00091       0x00504473/*sDP_*/,0x00504453/*SDP_*/};
00092    str           str_type;
00093    unsigned int  x;
00094    char          *p;
00095 
00096    if (!msg->content_type)
00097    {
00098       LM_WARN("the header Content-TYPE is absent!"
00099          "let's assume the content is text/plain ;-)\n");
00100       return 1;
00101    }
00102 
00103    trim_len(str_type.len,str_type.s,msg->content_type->body);
00104    p = str_type.s;
00105    advance(p,4,str_type,error_1);
00106    x = READ(p-4);
00107    if (!one_of_16(x,appl))
00108       goto other;
00109    advance(p,4,str_type,error_1);
00110    x = READ(p-4);
00111    if (!one_of_16(x,icat))
00112       goto other;
00113    advance(p,3,str_type,error_1);
00114    x = READ(p-3) & 0x00ffffff;
00115    if (!one_of_8(x,ion_))
00116       goto other;
00117 
00118    /* skip spaces and tabs if any */
00119    while (*p==' ' || *p=='\t')
00120       advance(p,1,str_type,error_1);
00121    if (*p!='/')
00122    {
00123       LM_ERR("no / found after primary type\n");
00124       goto error;
00125    }
00126    advance(p,1,str_type,error_1);
00127    while ((*p==' ' || *p=='\t') && p+1<str_type.s+str_type.len)
00128       advance(p,1,str_type,error_1);
00129 
00130    advance(p,3,str_type,error_1);
00131    x = READ(p-3) & 0x00ffffff;
00132    if (!one_of_8(x,sdp_))
00133       goto other;
00134 
00135    if (*p==';'||*p==' '||*p=='\t'||*p=='\n'||*p=='\r'||*p==0) {
00136       LM_DBG("type <%.*s> found valid\n", (int)(p-str_type.s), str_type.s);
00137       return 1;
00138    } else {
00139       LM_ERR("bad end for type!\n");
00140       return -1;
00141    }
00142 
00143 error_1:
00144    LM_ERR("body ended :-(!\n");
00145 error:
00146    return -1;
00147 other:
00148    LM_ERR("invalid type for a message\n");
00149    return -1;
00150 }
00151 
00152 
00153 /*
00154  * Get message body and check Content-Type header field
00155  */
00156 int extract_body(struct sip_msg *msg, str *body )
00157 {
00158    char c;
00159    int skip;
00160    
00161    body->s = get_body(msg);
00162    if (body->s==0) {
00163       LM_ERR("failed to get the message body\n");
00164       goto error;
00165    }
00166    
00167    /*
00168     * Better use the content-len value - no need of any explicit
00169     * parcing as get_body() parsed all headers and Conten-Length
00170     * body header is automaticaly parsed when found.
00171     */
00172    body->len = get_content_length(msg);
00173    if (body->len==0) {
00174       LM_ERR("message body has length zero\n");
00175       goto error;
00176    }
00177    
00178    /* no need for parse_headers(msg, EOH), get_body will 
00179     * parse everything */
00180    /*is the content type correct?*/
00181    if (check_content_type(msg)==-1)
00182    {
00183       LM_ERR("content type mismatching\n");
00184       goto error;
00185    }
00186 
00187    for (skip = 0; skip < body->len; skip++) {
00188       c = body->s[body->len - skip - 1];
00189       if (c != '\r' && c != '\n')
00190          break;
00191    }
00192    if (skip == body->len) {
00193       LM_ERR("empty body");
00194       goto error;
00195    }
00196    body->len -= skip;
00197 
00198    /*LM_DBG("DEBUG:extract_body:=|%.*s|\n",body->len,body->s);*/
00199 
00200    return 1;
00201 error:
00202    return -1;
00203 }
00204 
00205 /*
00206  * ser_memmem() returns the location of the first occurrence of data
00207  * pattern b2 of size len2 in memory block b1 of size len1 or
00208  * NULL if none is found. Obtained from NetBSD.
00209  */
00210 void *
00211 ser_memmem(const void *b1, const void *b2, size_t len1, size_t len2)
00212 {
00213         /* Initialize search pointer */
00214         char *sp = (char *) b1;
00215 
00216         /* Initialize pattern pointer */
00217         char *pp = (char *) b2;
00218 
00219         /* Initialize end of search address space pointer */
00220         char *eos = sp + len1 - len2;
00221 
00222         /* Sanity check */
00223         if(!(b1 && b2 && len1 && len2))
00224                 return NULL;
00225 
00226         while (sp <= eos) {
00227                 if (*sp == *pp)
00228                         if (memcmp(sp, pp, len2) == 0)
00229                                 return sp;
00230 
00231                         sp++;
00232         }
00233 
00234         return NULL;
00235 }
00236 
00237 /*
00238  * Some helper functions taken verbatim from tm module.
00239  */
00240 
00241 /*
00242  * Extract Call-ID value
00243  * assumes the callid header is already parsed
00244  * (so make sure it is, before calling this function or
00245  *  it might fail even if the message _has_ a callid)
00246  */
00247 int
00248 get_callid(struct sip_msg* _m, str* _cid)
00249 {
00250 
00251         if ((parse_headers(_m, HDR_CALLID_F, 0) == -1)) {
00252                 LM_ERR("failed to parse call-id header\n");
00253                 return -1;
00254         }
00255 
00256         if (_m->callid == NULL) {
00257                 LM_ERR("call-id not found\n");
00258                 return -1;
00259         }
00260 
00261         _cid->s = _m->callid->body.s;
00262         _cid->len = _m->callid->body.len;
00263         trim(_cid);
00264         return 0;
00265 }
00266 
00267 /*
00268  * Extract tag from To header field of a response
00269  * assumes the to header is already parsed, so
00270  * make sure it really is before calling this function
00271  */
00272 int
00273 get_to_tag(struct sip_msg* _m, str* _tag)
00274 {
00275 
00276         if (!_m->to) {
00277                 LM_ERR("To header field missing\n");
00278                 return -1;
00279         }
00280 
00281         if (get_to(_m)->tag_value.len) {
00282                 _tag->s = get_to(_m)->tag_value.s;
00283                 _tag->len = get_to(_m)->tag_value.len;
00284         } else {
00285                 _tag->s = NULL; /* fixes gcc 4.0 warnings */
00286                 _tag->len = 0;
00287         }
00288 
00289         return 0;
00290 }
00291 
00292 /*
00293  * Extract tag from From header field of a request
00294  */
00295 int
00296 get_from_tag(struct sip_msg* _m, str* _tag)
00297 {
00298 
00299         if (parse_from_header(_m)<0) {
00300                 LM_ERR("failed to parse From header\n");
00301                 return -1;
00302         }
00303 
00304         if (get_from(_m)->tag_value.len) {
00305                 _tag->s = get_from(_m)->tag_value.s;
00306                 _tag->len = get_from(_m)->tag_value.len;
00307         } else {
00308                 _tag->s = NULL; /* fixes gcc 4.0 warnings */
00309                 _tag->len = 0;
00310         }
00311 
00312         return 0;
00313 }
00314 
00315 /*
00316  * Extract URI from the Contact header field
00317  */
00318 int
00319 get_contact_uri(struct sip_msg* _m, struct sip_uri *uri, contact_t** _c)
00320 {
00321 
00322         if ((parse_headers(_m, HDR_CONTACT_F, 0) == -1) || !_m->contact)
00323                 return -1;
00324         if (!_m->contact->parsed && parse_contact(_m->contact) < 0) {
00325                 LM_ERR("failed to parse Contact body\n");
00326                 return -1;
00327         }
00328         *_c = ((contact_body_t*)_m->contact->parsed)->contacts;
00329         if (*_c == NULL)
00330                 /* no contacts found */
00331                 return -1;
00332 
00333         if (parse_uri((*_c)->uri.s, (*_c)->uri.len, uri) < 0 || uri->host.len <= 0) {
00334                 LM_ERR("failed to parse Contact URI\n");
00335                 return -1;
00336         }
00337         return 0;
00338 }

Generated on Wed May 23 20:00:28 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6