contact_ops.c

Go to the documentation of this file.
00001 /*
00002  * $Id: contact_ops.c 5690 2009-03-12 15:56:14Z osas $
00003  *
00004  * mangler module
00005  *
00006  * Copyright (C) 2001-2003 FhG Fokus
00007  *
00008  * This file is part of Kamailio, a free SIP server.
00009  *
00010  * Kamailio is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version
00014  *
00015  * Kamailio is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License 
00021  * along with this program; if not, write to the Free Software 
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *
00024  * History:
00025  * --------
00026  *  2003-04-07 first version.  
00027  */
00028 
00029 #define STRICT_CHECK 1
00030 
00031 #include "contact_ops.h"
00032 #include "utils.h"
00033 #include "../../mem/mem.h"
00034 #include "../../data_lump.h"
00035 #include "../../parser/hf.h"
00036 #include "../../parser/parse_uri.h"
00037 #include "../../parser/contact/parse_contact.h"
00038 #include "../../ut.h"
00039 
00040 #include <stdio.h>
00041 #include <string.h>
00042 
00043 
00044 //#define DEBUG
00045 int
00046 encode_contact (struct sip_msg *msg, char *encoding_prefix,char *public_ip)
00047 {
00048 
00049    contact_body_t *cb;
00050    contact_t *c;
00051    str uri;
00052    str newUri;
00053    int res;
00054    char separator;
00055 
00056 
00057 
00058    /*
00059     * I have a list of contacts in contact->parsed which is of type contact_body_t 
00060     * inside i have a contact->parsed->contact which is the head of the list of contacts
00061     * inside it is a 
00062     * str uri;
00063     * struct contact *next;
00064     * I just have to visit each uri and encode each uri according to a scheme
00065     */
00066    
00067    if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) ||
00068             (msg->contact == NULL) ))
00069       {
00070       LM_ERR("no Contact header present\n");
00071       return -1;
00072       }
00073 
00074 
00075    separator = DEFAULT_SEPARATOR[0];
00076    if (contact_flds_separator != NULL)
00077       if (strlen(contact_flds_separator)>=1)
00078          separator = contact_flds_separator[0];
00079 
00080    if (msg->contact->parsed == NULL)   parse_contact (msg->contact);
00081    if (msg->contact->parsed != NULL)
00082    {
00083       cb = (contact_body_t *) msg->contact->parsed;
00084       c = cb->contacts;
00085       /* we visit each contact */
00086       if (c != NULL)
00087       {
00088          uri = c->uri;
00089          res = encode_uri (uri, encoding_prefix, public_ip,separator, &newUri);
00090          
00091          if (res != 0)
00092             {
00093             LM_ERR("failed encoding contact.Code %d\n", res);
00094 #ifdef STRICT_CHECK
00095             return res;
00096 #endif
00097             }
00098          else
00099             if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0)
00100             {
00101                LM_ERR("lumping failed in mangling port \n");
00102                return -2;
00103             }
00104          
00105          /* encoding next contacts too?*/
00106 #ifdef ENCODE_ALL_CONTACTS
00107          while (c->next != NULL)
00108          {
00109             c = c->next;
00110             uri = c->uri;
00111             
00112             res = encode_uri (uri, encoding_prefix,public_ip,separator,&newUri);
00113             if (res != 0)
00114                {
00115                LM_ERR("failed encode_uri.Code %d\n",res);
00116 #ifdef STRICT_CHECK
00117             return res;
00118 #endif
00119                }
00120             else
00121             if (patch (msg, uri.s, uri.len, newUri.s, newUri.len)< 0)
00122             {
00123                LM_ERR("lumping failed in mangling port \n");
00124                return -3;
00125             }
00126          } /* while */
00127 #endif /* ENCODE_ALL_CONTACTS */
00128       } /* if c != NULL */
00129 
00130    } /* end if */
00131    else /* after parsing still NULL */
00132       {
00133          LM_ERR("unable to parse Contact header\n");
00134          return -4;
00135       }
00136    return 1;
00137 }
00138 
00139 int
00140 decode_contact (struct sip_msg *msg,char *unused1,char *unused2)
00141 {
00142 
00143    str uri;
00144    str newUri;
00145    char separator;
00146    int res;
00147 
00148    uri.s = 0;
00149    uri.len = 0;
00150 
00151 #ifdef DEBUG
00152    fprintf (stdout,"---START--------DECODE CONTACT-----------------\n");
00153         fprintf (stdout,"%.*s\n",50,msg->buf);
00154    fprintf (stdout, "INITIAL.s=[%.*s]\n", uri.len, uri.s);
00155 #endif
00156 
00157    separator = DEFAULT_SEPARATOR[0];
00158    if (contact_flds_separator != NULL)
00159       if (strlen(contact_flds_separator)>=1)
00160          separator = contact_flds_separator[0];
00161       
00162    if ((msg->new_uri.s == NULL) || (msg->new_uri.len == 0))
00163       {
00164       uri = msg->first_line.u.request.uri;
00165       if (uri.s == NULL) return -1;
00166       }
00167    
00168       res = decode_uri (uri, separator, &newUri);
00169    
00170 #ifdef DEBUG
00171       if (res == 0) fprintf (stdout, "newuri.s=[%.*s]\n", newUri.len, newUri.s);
00172 #endif
00173       if (res != 0)
00174       {
00175          LM_ERR("failed decoding contact.Code %d\n", res);
00176 #ifdef STRICT_CHECK
00177             return res;
00178 #endif
00179       }
00180       else
00181          /* we do not modify the original first line */
00182          if ((msg->new_uri.s == NULL) || (msg->new_uri.len == 0)) msg->new_uri = newUri;
00183             else
00184                {
00185                   pkg_free(msg->new_uri.s);
00186                   msg->new_uri = newUri;
00187                }
00188          
00189          
00190       /*
00191       if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0)
00192       {
00193          LM_ERR("lumping failed in mangling port \n");
00194          return -2;
00195       }
00196       */
00197    return 1;
00198 }
00199 
00200 int
00201 decode_contact_header (struct sip_msg *msg,char *unused1,char *unused2)
00202 {
00203 
00204    contact_body_t *cb;
00205    contact_t *c;
00206    str uri;
00207    str newUri;
00208    char separator;
00209    int res;
00210    
00211    
00212 #ifdef DEBUG
00213    fprintf (stdout,"---START--------DECODE CONTACT HEADER-----------------\n");
00214 #endif
00215 
00216    if ((msg->contact == NULL)&&((parse_headers(msg,HDR_CONTACT_F,0) == -1) ||
00217             (msg->contact== NULL) ))
00218       {
00219       LM_ERR("no Contact header present\n");
00220       return -1;
00221       }
00222 
00223    separator = DEFAULT_SEPARATOR[0];
00224    if (contact_flds_separator != NULL)
00225       if (strlen(contact_flds_separator)>=1)
00226          separator = contact_flds_separator[0];
00227 
00228 #ifdef DEBUG
00229    fprintf (stdout,"Using separator %c\n",separator);
00230    str* ruri;
00231    ruri = GET_RURI(msg);
00232    fprintf (stdout,"[len = %d]New uri is->%*.s\n",ruri->len,ruri->len,ruri->s);
00233    ruri = &msg->first_line.u.request.uri;
00234    fprintf (stdout, "INITIAL.s=[%.*s]\n", ruri->len, ruri->s);
00235 #endif
00236       
00237    if (msg->contact->parsed == NULL) parse_contact (msg->contact);
00238    if (msg->contact->parsed != NULL)
00239    {
00240       cb = (contact_body_t *) msg->contact->parsed;
00241       c = cb->contacts;
00242       // we visit each contact 
00243     if (c != NULL)
00244      {
00245       uri = c->uri;
00246 
00247       res = decode_uri (uri, separator, &newUri);
00248 #ifdef DEBUG
00249       fprintf (stdout, "newuri.s=[%.*s]\n", newUri.len, newUri.s);
00250 #endif
00251       if (res != 0)
00252       {
00253          LM_ERR("failed decoding contact.Code %d\n", res);
00254 #ifdef STRICT_CHECK
00255             return res;
00256 #endif
00257       }
00258       else
00259       if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0)
00260       {
00261          LM_ERR("lumping failed in mangling port \n");
00262          return -2;
00263       }
00264 
00265 #ifdef DECODE_ALL_CONTACTS
00266       while (c->next != NULL)
00267       {
00268          c = c->next;
00269          uri = c->uri;
00270 
00271          res = decode_uri (uri, separator, &newUri);
00272          if (res != 0)
00273             {
00274             LM_ERR("failed decoding contact.Code %d\n",res);
00275 #ifdef STRICT_CHECK
00276             return res;
00277 #endif
00278             }
00279          else
00280          if (patch (msg, uri.s, uri.len, newUri.s, newUri.len) < 0)
00281          {
00282             LM_ERR("lumping failed in mangling port \n");
00283             return -3;
00284          }
00285       } // end while 
00286 #endif
00287       } // if c!= NULL 
00288    } // end if 
00289    else // after parsing still NULL 
00290       {
00291          LM_ERR("unable to parse Contact header\n");
00292          return -4;
00293       }
00294 #ifdef DEBUG
00295    fprintf (stdout,"---END--------DECODE CONTACT HEADER-----------------\n");fflush(stdout);
00296 #endif
00297    return 1;
00298 }
00299 
00300 
00301 
00302 
00303 int
00304 encode2format (str uri, struct uri_format *format)
00305 {
00306    int foo;
00307    char *string, *pos, *start, *end;
00308    struct sip_uri sipUri;
00309 
00310 
00311    if (uri.s == NULL)
00312       return -1;
00313    string = uri.s;
00314 
00315 
00316    pos = memchr (string, '<', uri.len);
00317    if (pos != NULL)  /* we are only interested of chars inside <> */
00318    {
00319       start = memchr (string, ':', uri.len);
00320       if (start == NULL)   return -2;
00321       if (start - pos < 4) return -3;
00322       start = start - 3;
00323       end = strchr (start, '>');
00324       if (end == NULL)
00325          return -4;  /* must be a match to < */
00326    }
00327    else        /* we do not have  <> */
00328    {
00329       start = memchr (string, ':', uri.len);
00330       if (start == NULL)
00331          return -5;
00332       if (start - pos < 3)
00333          return -6;
00334       start = start - 3;
00335       end = string + uri.len;
00336    }
00337    memset(format,0,sizeof(struct uri_format));
00338    format->first = start - string + 4; /*sip: */
00339    format->second = end - string;
00340    /* --------------------------testing ------------------------------- */
00341    /* sip:gva@pass@10.0.0.1;;transport=udp>;expires=2 INCORECT BEHAVIOR OF parse_uri,myfunction works good */
00342    foo = parse_uri (start, end - start, &sipUri);
00343    if (foo != 0)
00344    {
00345       LM_ERR("parse_uri failed on [%.*s].Code %d \n",uri.len,uri.s,foo);
00346 #ifdef DEBUG
00347       fprintf (stdout, "PARSING uri with parse uri not ok %d\n", foo);
00348 #endif
00349       return foo-10;
00350    }
00351 
00352    
00353    format->username = sipUri.user;
00354    format->password = sipUri.passwd;
00355    format->ip = sipUri.host;
00356    format->port = sipUri.port;
00357    format->protocol = sipUri.transport_val;
00358    
00359 #ifdef DEBUG   
00360    fprintf (stdout, "transport=[%.*s] transportval=[%.*s]\n", sipUri.transport.len,sipUri.transport.s,sipUri.transport_val.len,sipUri.transport_val.s);
00361    fprintf(stdout,"First %d,second %d\n",format->first,format->second);
00362    #endif
00363    
00364    return 0;
00365 
00366 }
00367 
00368 
00369 int
00370 encode_uri (str uri, char *encoding_prefix, char *public_ip,char separator, str * result)
00371 {
00372    struct uri_format format;
00373    char *pos;
00374    int foo,res;
00375 
00376    
00377    result->s = NULL;
00378    result->len = 0;
00379    if (uri.len <= 1)
00380       return -1;  /* no contact or an invalid one */
00381    if (public_ip == NULL) 
00382       {
00383          LM_ERR("invalid NULL value for public_ip parameter\n");
00384          return -2;
00385       }
00386 #ifdef DEBUG
00387    fprintf (stdout, "Primit cerere de encodare a [%.*s] cu %s-%s\n", uri.len,uri.s, encoding_prefix, public_ip);
00388 #endif
00389    fflush (stdout);
00390    foo = encode2format (uri, &format);
00391    if (foo < 0)
00392       {
00393       LM_ERR("unable to encode Contact URI [%.*s].Return code %d\n",uri.len,uri.s,foo);
00394       return foo - 20;
00395       }
00396 #ifdef DEBUG
00397    fprintf(stdout,"user=%.*s ip=%.*s port=%.*s protocol=%.*s\n",format.username.len,format.username.s,format.ip.len,format.ip.s,
00398         format.port.len,format.port.s,format.protocol.len,format.protocol.s);   
00399 #endif
00400 
00401    /* a complete uri would be sip:username@ip:port;transport=protocol goes to
00402     * sip:enc_pref*username*ip*port*protocol@public_ip
00403     */
00404 
00405    foo = 1;    /*strlen(separator); */
00406    result->len = format.first + uri.len - format.second +   //ar trebui sa sterg 1
00407       strlen (encoding_prefix) + foo +
00408       format.username.len + foo +
00409       format.password.len + foo +
00410       format.ip.len + foo + format.port.len + foo +
00411       format.protocol.len + 1 + strlen (public_ip);
00412    /* adding one comes from @ */
00413    result->s = pkg_malloc (result->len);
00414    pos = result->s;
00415    if (pos == NULL)
00416       {
00417 #ifdef DEBUG
00418          fprintf (stdout, "Unable to alloc result [%d] end=%d\n",result->len, format.second);
00419 #endif
00420          LM_ERR("unable to alloc pkg memory\n");
00421          return -3;
00422       }
00423 #ifdef DEBUG
00424    fprintf (stdout, "[pass=%d][Allocated %d bytes][first=%d][lengthsec=%d]\nAdding [%d] ->%.*s\n",format.password.len,result->len,format.first,uri.len-format.second,format.first, format.first,uri.s);fflush (stdout);
00425 #endif
00426       
00427    res = snprintf(pos,result->len,"%.*s%s%c%.*s%c%.*s%c%.*s%c%.*s%c%.*s@",format.first,uri.s,encoding_prefix,separator,
00428    format.username.len,format.username.s,separator,format.password.len,format.password.s,
00429    separator,format.ip.len,format.ip.s,separator,format.port.len,format.port.s,separator,format.protocol.len,format.protocol.s);
00430 
00431    if ((res < 0 )||(res>result->len)) 
00432       {
00433          LM_ERR("unable to construct new uri.\n");
00434          if (result->s != NULL) pkg_free(result->s);
00435          return -4;
00436       }
00437 #ifdef DEBUG
00438    fprintf(stdout,"res= %d\npos=%s\n",res,pos);
00439 #endif
00440    pos = pos + res ;/* overwriting the \0 from snprintf */
00441    memcpy (pos, public_ip, strlen (public_ip));
00442    pos = pos + strlen (public_ip);
00443    memcpy (pos, uri.s + format.second, uri.len - format.second);
00444 
00445 #ifdef DEBUG   
00446    fprintf (stdout, "Adding2 [%d] ->%.*s\n", uri.len - format.second,uri.len - format.second, uri.s + format.second);
00447    fprintf (stdout, "NEW NEW uri is->[%.*s]\n", result->len, result->s);
00448 #endif
00449 
00450    /* Because called parse_uri format contains pointers to the inside of msg,must not deallocate */
00451 
00452    return 0;
00453 }
00454 
00455 
00456 int
00457 decode2format (str uri, char separator, struct uri_format *format)
00458 {
00459    char *start, *end, *pos,*lastpos;
00460    str tmp;
00461    enum {EX_PREFIX=0,EX_USER,EX_PASS,EX_IP,EX_PORT,EX_PROT,EX_FINAL} state;
00462 
00463    //memset (format, 0, sizeof ((struct uri_format)));
00464 
00465    if (uri.s == NULL)
00466       {
00467       LM_ERR("invalid parameter uri.It is NULL\n");
00468       return -1;
00469       }
00470    /* sip:enc_pref*username*password*ip*port*protocol@public_ip */
00471    
00472    start = memchr (uri.s, ':', uri.len);
00473    if (start == NULL)
00474    {
00475       LM_ERR("invalid SIP uri.Missing :\n");
00476       return -2;
00477    }        /* invalid uri */
00478    start = start + 1;   /* jumping over sip: ATENTIE LA BUFFER OVERFLOW DACA E DOAR sip: */
00479    format->first = start - uri.s;
00480    
00481    /* start */
00482 
00483    end = memchr(start,'@',uri.len-(start-uri.s));
00484    if (end == NULL) 
00485       {
00486       LM_ERR("invalid SIP uri.Missing @\n");
00487       return -3;/* no host address found */
00488       }
00489 
00490 #ifdef DEBUG
00491       fprintf (stdout, "Decoding %.*s\n",end-start,start);
00492 #endif
00493    
00494    state = EX_PREFIX;
00495    lastpos = start;
00496    
00497    for (pos = start;pos<end;pos++)
00498       {
00499          if (*pos == separator)
00500             {
00501                /* we copy between lastpos and pos */
00502                tmp.len = pos - lastpos;
00503                if (tmp.len>0) tmp.s = lastpos;
00504                   else tmp.s = NULL;
00505                switch (state)
00506                   {
00507                      case EX_PREFIX: state = EX_USER;break;
00508                      case EX_USER:format->username = tmp;state = EX_PASS;break;
00509                      case EX_PASS:format->password = tmp;state = EX_IP;break;
00510                      case EX_IP:format->ip = tmp;state = EX_PORT;break;
00511                      case EX_PORT:format->port = tmp;state = EX_PROT;break;
00512                      default:
00513                         {
00514                         /* this should not happen, we should find @ not separator */
00515                         return -4;
00516                         break;
00517                         }
00518                   }
00519                   
00520                lastpos = pos+1;
00521             
00522             }
00523          else
00524          if (((*pos) == '>')||(*pos == ';'))
00525             {
00526             /* invalid chars inside username part */
00527             return -5;
00528             }
00529       }
00530       
00531       
00532    /* we must be in state EX_PROT and protocol is between lastpos and end@ */
00533    if (state != EX_PROT) return -6;
00534    format->protocol.len = end - lastpos;
00535    if (format->protocol.len>0) format->protocol.s = lastpos;
00536       else format->protocol.s = NULL;
00537    /* I should check perhaps that   after @ there is something */
00538       
00539 #ifdef DEBUG
00540       fprintf (stdout, "username=%.*s\n", format->username.len,format->username.s);
00541       fprintf (stdout, "password=%.*s\n", format->password.len,format->password.s);
00542       fprintf (stdout, "ip=%.*s\n", format->ip.len, format->ip.s);
00543       fprintf (stdout, "port=%.*s\n", format->port.len,format->port.s);
00544       fprintf (stdout, "protocol=%.*s\n", format->protocol.len,format->protocol.s);
00545 #endif
00546 
00547    /* looking for the end of public ip */
00548    start = end;/*we are now at @ */
00549    for(pos = start;pos<uri.s+uri.len;pos++)
00550       {
00551          if ((*pos == ';')||(*pos == '>'))
00552             {
00553             /* found end */
00554             format->second = pos - uri.s;
00555             return 0;
00556             }
00557       }
00558    /* if we are here we did not find > or ; */
00559    format->second = uri.len;
00560    return 0;   
00561    
00562 }
00563 
00564 
00565 int
00566 decode_uri (str uri, char separator, str * result)
00567 {
00568    char *pos;
00569    struct uri_format format;
00570    int foo;
00571 
00572    result->s = NULL;
00573    result->len = 0;
00574 
00575    if ((uri.len <= 0) || (uri.s == NULL))
00576       {
00577       LM_ERR("invalid value for uri\n");
00578       return -1;
00579       }
00580 
00581    foo = decode2format (uri, separator, &format);
00582    if (foo < 0)
00583       {
00584       LM_ERR("failed to decode Contact uri .Error code %d\n",foo);
00585       return foo - 20;
00586       }
00587    /* sanity check */
00588    if (format.ip.len <= 0)
00589       {
00590          LM_ERR("unable to decode host address \n");
00591          return -2;/* should I quit or ignore ? */
00592       }        
00593 
00594    if ((format.password.len > 0) && (format.username.len <= 0))
00595       {
00596          LM_ERR("password decoded but no username available\n");
00597          return -3;
00598       }
00599       
00600    /* a complete uri would be sip:username:password@ip:port;transport=protocol goes to
00601     * sip:enc_pref#username#password#ip#port#protocol@public_ip
00602     */
00603    result->len = format.first + (uri.len - format.second);  /* not NULL terminated */
00604    if (format.username.len > 0) result->len += format.username.len + 1; //: or @
00605    if (format.password.len > 0) result->len += format.password.len + 1; //@
00606       
00607    /* if (format.ip.len > 0) */       result->len += format.ip.len;
00608       
00609    if (format.port.len > 0)     result->len += 1 + format.port.len;  //:
00610    if (format.protocol.len > 0) result->len += 1 + 10 + format.protocol.len;  //;transport=
00611 #ifdef DEBUG
00612    fprintf (stdout, "Result size is %d.Original Uri size is %d\n",result->len, uri.len);
00613 #endif
00614    
00615    /* adding one comes from * */
00616    result->s = pkg_malloc (result->len);
00617    if (result->s == NULL)
00618       {
00619          LM_ERR("unable to allocate pkg memory\n");
00620          return -4;
00621       }
00622    pos = result->s;
00623 #ifdef DEBUG
00624    fprintf (stdout, "Adding [%d] ->%.*s\n", format.first, format.first,uri.s);fflush (stdout);
00625 #endif
00626    memcpy (pos, uri.s, format.first);  /* till sip: */
00627    pos = pos + format.first;
00628    
00629    if (format.username.len > 0)
00630    {
00631       memcpy (pos, format.username.s, format.username.len);
00632       pos = pos + format.username.len;
00633       if (format.password.len > 0)
00634          memcpy (pos, ":", 1);
00635       else
00636          memcpy (pos, "@", 1);
00637       pos = pos + 1;
00638    }
00639    if (format.password.len > 0)
00640    {
00641       memcpy (pos, format.password.s, format.password.len);
00642       pos = pos + format.password.len;
00643       memcpy (pos, "@", 1);
00644       pos = pos + 1;
00645    }
00646    /* if (format.ip.len > 0) */
00647 
00648       memcpy (pos, format.ip.s, format.ip.len);
00649       pos = pos + format.ip.len;
00650    
00651    if (format.port.len > 0)
00652    {
00653       memcpy (pos, ":", 1);
00654       pos = pos + 1;
00655       memcpy (pos, format.port.s, format.port.len);
00656       pos = pos + format.port.len;
00657    }
00658    if (format.protocol.len > 0)
00659    {
00660       memcpy (pos, ";transport=", 11);
00661       pos = pos + 11;
00662       memcpy (pos, format.protocol.s, format.protocol.len);
00663       pos = pos + format.protocol.len;
00664    }
00665 
00666 #ifdef DEBUG
00667    fprintf (stdout, "Adding2 [%d] ->%.*s\n", uri.len - format.second,uri.len - format.second, uri.s + format.second);fflush (stdout);
00668 #endif
00669 
00670    memcpy (pos, uri.s + format.second, uri.len - format.second);  /* till end: */
00671 
00672 #ifdef DEBUG
00673    fprintf (stdout, "New decoded uri is->[%.*s]\n", result->len,result->s);
00674 #endif
00675 
00676    return 0;
00677 }
00678 

Generated on Mon May 21 18:00:25 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6