encode_header.c

Go to the documentation of this file.
00001 /* $Id: encode_header.c 5192 2008-11-13 10:18:48Z eliasbaixas $
00002  *
00003  * Copyright (C) 2006-2007 VozTelecom Sistemas S.L
00004  *
00005  * This file is part of Kamailio, a free SIP server.
00006  *
00007  * Kamailio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version
00011  *
00012  * Kamailio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License 
00018  * along with this program; if not, write to the Free Software 
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 
00022 /*
00023  * =====================================================================================
00024  * 
00025  *        Filename:  xcontact.c
00026  * 
00027  *     Description:  Contact encoding functions
00028  * 
00029  *         Version:  1.0
00030  *         Created:  19/11/05 14:33:38 CET
00031  *        Revision:  none
00032  *        Compiler:  gcc
00033  * 
00034  *          Author:  Elias Baixas (EB), elias@conillera.net
00035  *         Company:  VozTele.com
00036  * 
00037  * =====================================================================================
00038  */
00039 #define _GNU_SOURCE
00040 #include <string.h>
00041 #include <unistd.h>
00042 #include <netinet/in.h>
00043 #include "../../str.h"
00044 #include "../../parser/msg_parser.h"
00045 #include "../../parser/hf.h"
00046 #include "../../parser/contact/parse_contact.h"
00047 #include "../../parser/contact/contact.h"
00048 #include "../../parser/digest/digest.h"
00049 #include "../../parser/digest/digest_parser.h"
00050 #include "../../parser/parse_rr.h"
00051 #include "../../parser/parse_content.h"
00052 #include "../../parser/parse_cseq.h"
00053 #include "../../parser/parse_expires.h"
00054 #include "../../parser/parse_methods.h"
00055 #include "../../dprint.h"
00056 #include "../../mem/mem.h"
00057 #include "encode_to_body.h"
00058 #include "encode_contact.h"
00059 #include "encode_digest.h"
00060 #include "encode_via.h"
00061 #include "encode_cseq.h"
00062 #include "encode_route.h"
00063 #include "encode_content_length.h"
00064 #include "encode_content_type.h"
00065 #include "encode_expires.h"
00066 #include "encode_allow.h"
00067 #include "xaddress.h"
00068 #include "encode_msg.h"
00069 #include "encode_header.h"
00070 
00071 #define REL_PTR(a,b) ((unsigned char)(b-a))
00072 #define MAX_CONTACT_LEN 50
00073 #define MAX_XHDR_LEN 255
00074 
00075 #define SEGREGATE 0x02
00076 #define ONLY_URIS 0x01
00077 #define HEADER_OFFSET_IDX 0
00078 #define HEADER_LEN_IDX (HEADER_OFFSET_IDX+2)
00079 #define HEADER_NAME_LEN_IDX (HEADER_LEN_IDX+2)
00080 #define HEADER_PAYLOAD_IDX (HEADER_NAME_LEN_IDX+1)
00081 
00082 /*
00083  * This function encodes an arbitrary header into a chunk of bytes,
00084  * ready to be sent to the Application Server.
00085  *
00086  * The header codes start with this encoded-bytes:
00087  * 2: SIP-MSG-START based pointer to the header (including header name)
00088  * 2: length of the header
00089  * 1: length of the header name
00090  */
00091 int encode_header(struct sip_msg *sipmsg,struct hdr_field *hdr,unsigned char *payload,int paylen)
00092 {
00093    int len=0;
00094    unsigned int integer,*methods=0;
00095    char *hdrstart,*tmp;
00096    unsigned short int ptr;
00097    struct to_body *tobody=0;
00098    struct via_body *viabody=0;
00099    struct cseq_body *cseqbody=0;
00100    char *msg,*myerror;
00101    int mlen;
00102 
00103    msg=sipmsg->buf;
00104    mlen=sipmsg->len;
00105    hdrstart = hdr->name.s;
00106    if(hdrstart-msg<0){
00107       LM_ERR("header(%.*s) does not belong to sip_msg(hdrstart<msg)\n",
00108            hdr->name.len,hdr->name.s);
00109       return -1;
00110    }
00111    ptr=htons((short int)(hdrstart-msg));
00112    if((hdrstart-msg)>mlen){
00113       LM_ERR("out of the sip_msg bounds (%d>%d)\n",ntohs(ptr),mlen);
00114       return -1;
00115    }
00116    if(hdr->len>(1<<16)){
00117       LM_ERR("length of header too long\n");
00118       return -1;
00119    }
00120    memcpy(payload,&ptr,2);
00121    ptr=htons((short int)(hdr->len));
00122    memcpy(payload+HEADER_LEN_IDX,&ptr,2);
00123    payload[HEADER_NAME_LEN_IDX]=(unsigned char)hdr->name.len;
00124    switch(hdr->type){
00125       case HDR_FROM_T:
00126       case HDR_TO_T:
00127       case HDR_REFER_TO_T:
00128       case HDR_RPID_T:
00129     if(!hdr->parsed){
00130        if((tobody=pkg_malloc(sizeof(struct to_body)))==0){
00131           myerror="Out of memory !!\n";
00132           goto error;
00133        }
00134        memset(tobody,0,sizeof(struct to_body));
00135        parse_to(hdr->body.s,hdr->body.s+hdr->body.len+1,tobody);
00136        if (tobody->error == PARSE_ERROR) {
00137           myerror="bad (REFER,TO,FROM,RPID) header\n";
00138           pkg_free(tobody);
00139           return 5;
00140           goto error;
00141        }
00142        hdr->parsed=(struct to_body*)tobody;
00143     }else
00144        tobody=(struct to_body*)hdr->parsed;
00145     if((len=encode_to_body(hdr->name.s,hdr->len,tobody,payload+5))<0){
00146        myerror="parsing from or to header\n";
00147        goto error;
00148     }else{
00149        return 5+len;
00150     }
00151     break;
00152       case HDR_CONTACT_T:
00153     if(!hdr->parsed)
00154        if(parse_contact(hdr)<0){
00155           myerror="parsing contact\n";
00156           goto error;
00157        }
00158     if((len=encode_contact_body(hdr->name.s,hdr->len,(contact_body_t*)hdr->parsed,payload+5))<0){
00159        myerror="encoding contact header\n";
00160        goto error;
00161     }else{
00162        return 5+len;
00163     }
00164     break;
00165       case HDR_ROUTE_T:
00166       case HDR_RECORDROUTE_T:
00167     if(!hdr->parsed)
00168        if(parse_rr(hdr)<0){
00169           myerror="encoding route or recordroute\n";
00170           goto error;
00171        }
00172     if((len=encode_route_body(hdr->name.s,hdr->len,(rr_t*)hdr->parsed,payload+5))<0){
00173        myerror="encoding route or recordroute header\n";
00174        goto error;
00175     }else{
00176        return 5+len;
00177     }
00178     break;
00179       case HDR_CONTENTLENGTH_T:
00180     if(!hdr->parsed){
00181        tmp=parse_content_length(hdr->body.s,hdr->body.s+hdr->body.len+1,(int*)&integer);
00182        if (tmp==0){
00183           myerror="bad content_length header\n";
00184           goto error;
00185        }
00186        hdr->parsed=(void*)(long)integer;
00187     }
00188     if((len=encode_contentlength(hdr->name.s,hdr->len,(long int)hdr->parsed,(char*)(payload+5)))<0){
00189        myerror="encoding content-length header\n";
00190        goto error;
00191     }else{
00192        return 5+len;
00193     }
00194     break;
00195       case HDR_VIA_T:
00196     if(!hdr->parsed){
00197        if((viabody=pkg_malloc(sizeof(struct via_body)))==0){
00198           myerror="out of memory\n";
00199           goto error;
00200        }
00201        memset(viabody,0,sizeof(struct via_body));
00202        if(parse_via(hdr->body.s,hdr->body.s+hdr->body.len+1,viabody)==0){
00203           myerror="encoding via \n";
00204           goto error;
00205        }
00206        hdr->parsed=viabody;
00207     }
00208     if((len=encode_via_body(hdr->name.s,hdr->len,(struct via_body*)hdr->parsed,payload+5))<0){
00209        myerror="encoding via header\n";
00210        goto error;
00211     }else{
00212        return 5+len;
00213     }
00214     break;
00215       case HDR_ACCEPT_T:
00216     if(!hdr->parsed){
00217        if(parse_accept_hdr(sipmsg)<0){
00218           return 5;
00219        }
00220     }
00221     if((len=encode_accept(hdr->name.s,hdr->len,(unsigned int*)hdr->parsed,(char*)(payload+5)))<0){
00222        myerror="encoding via header\n";
00223        goto error;
00224     }else{
00225        return 5+len;
00226     }
00227     break;
00228       case HDR_CONTENTTYPE_T:
00229     if(!hdr->parsed){
00230        if(parse_content_type_hdr(sipmsg)<0){
00231           myerror="encoding content-type header\n";
00232           goto error;
00233        }
00234     }
00235     if((len=encode_content_type(hdr->name.s,hdr->len,(unsigned int)(long int)hdr->parsed,(char*)(payload+5)))<0){
00236        myerror="encoding via header\n";
00237        goto error;
00238     }else{
00239        return 5+len;
00240     }
00241     break;
00242       case HDR_CSEQ_T:
00243     if(!hdr->parsed){
00244        if((cseqbody=pkg_malloc(sizeof(struct cseq_body)))==0){
00245           myerror="out of memory\n";
00246           goto error;
00247        }
00248        memset(cseqbody,0,sizeof(struct cseq_body));
00249        if(parse_cseq(hdr->name.s,hdr->body.s+hdr->body.len+1,cseqbody)==0){
00250           myerror="encoding cseq header\n";
00251           goto error;
00252        }
00253        hdr->parsed=cseqbody;
00254     }
00255     if((len=encode_cseq(hdr->name.s,hdr->len,(struct cseq_body*)hdr->parsed,payload+5))<0){
00256        myerror="encoding via header\n";
00257        goto error;
00258     }else{
00259        return 5+len;
00260     }
00261     break;
00262       case HDR_EXPIRES_T:
00263     if(!hdr->parsed){
00264        if(parse_expires(hdr)<0){
00265           myerror="encoding expires header\n";
00266           goto error;
00267        }
00268     }
00269     if((len=encode_expires(hdr->name.s,hdr->len,(exp_body_t *)hdr->parsed,payload+5))<0){
00270        myerror="encoding expires header\n";
00271        goto error;
00272     }else{
00273        return 5+len;
00274     }
00275     break;
00276       case HDR_ALLOW_T:
00277     if(!hdr->parsed){
00278        if((methods=pkg_malloc(sizeof(unsigned int)))==0){
00279           myerror="out of memory\n";
00280           goto error;
00281        }
00282        *methods=0;
00283        if(parse_methods(&hdr->body,methods)!=0){
00284           myerror="encoding allow header\n";
00285           pkg_free(methods);
00286           return 5;
00287           /*goto error;*/
00288        }
00289        hdr->parsed=methods;
00290     }
00291     if((len=encode_allow(hdr->name.s,hdr->len,(unsigned int*)hdr->parsed,(char*)(payload+5)))<0){
00292        myerror="encoding allow header\n";
00293        goto error;
00294     }else{
00295        return 5+len;
00296     }
00297     break;
00298       case HDR_AUTHORIZATION_T:
00299       case HDR_PROXYAUTH_T:
00300     if(!hdr->parsed){
00301        if(parse_credentials(hdr)<0){
00302           myerror="encoding a digest header\n";
00303           goto error;
00304        }
00305     }
00306     if((len=encode_digest(hdr->name.s,hdr->len,(dig_cred_t*)(&(((auth_body_t*)hdr->parsed)->digest)),payload+5))<0){
00307        myerror="encoding allow header\n";
00308        goto error;
00309     }else{
00310        return 5+len;
00311     }
00312     break;
00313       default:
00314     return 5;
00315    }
00316    return 1;
00317 error:
00318    if(tobody)
00319       pkg_free(tobody);
00320    if(cseqbody)
00321       pkg_free(cseqbody);
00322    if(viabody)
00323       free_via_list(viabody);
00324    if(methods)
00325       pkg_free(methods);
00326    LM_ERR("%s",myerror);
00327    return -1;
00328 }
00329 
00330 int print_encoded_header(FILE *fd,char *msg,int msglen,unsigned char *payload,int len,char type,char *prefix)
00331 {
00332    char *hdr_start_ptr;
00333    short int start_idx,i;
00334 
00335    memcpy(&start_idx,payload,2);
00336    start_idx=ntohs(start_idx);
00337 
00338    hdr_start_ptr = &msg[start_idx];
00339    memcpy(&i,payload+HEADER_LEN_IDX,2);
00340    i=ntohs(i);
00341 
00342    fprintf(fd,"%sHEADER NAME:[%.*s]\n",prefix,payload[HEADER_NAME_LEN_IDX],hdr_start_ptr);
00343    fprintf(fd,"%sHEADER:[%.*s]\n",prefix,i-2,hdr_start_ptr);
00344    fprintf(fd,"%sHEADER CODE=",prefix);
00345    for(i=0;i<len;i++)
00346       fprintf(fd,"%s%d%s",i==0?"[":":",payload[i],i==len-1?"]\n":"");
00347    if(len==4)
00348       return 1;
00349    switch(type){
00350       case HDR_FROM_T:/*from*/
00351       case HDR_TO_T:/*to*/
00352       case HDR_REFER_TO_T:/*refer-to*/
00353       case HDR_RPID_T:/*rpid= remote parte id*/
00354     memcpy(&i,payload+HEADER_LEN_IDX,2);
00355     i=ntohs(i);
00356     print_encoded_to_body(fd,hdr_start_ptr,i,&payload[HEADER_PAYLOAD_IDX],
00357           len-HEADER_PAYLOAD_IDX,strcat(prefix,"  "));
00358     prefix[strlen(prefix)-2]=0;
00359     break;
00360       case HDR_CONTACT_T:/*contact*/
00361     memcpy(&i,payload+HEADER_LEN_IDX,2);
00362     i=ntohs(i);
00363     print_encoded_contact_body(fd,hdr_start_ptr,i,&payload[HEADER_PAYLOAD_IDX],
00364           len-HEADER_PAYLOAD_IDX,strcat(prefix,"  "));
00365     prefix[strlen(prefix)-2]=0;
00366     break;
00367       case HDR_ROUTE_T:/*route*/
00368       case HDR_RECORDROUTE_T:/*record-route*/
00369     memcpy(&i,payload+HEADER_LEN_IDX,2);
00370     i=ntohs(i);
00371     print_encoded_route_body(fd,hdr_start_ptr,i,&payload[HEADER_PAYLOAD_IDX],
00372           len-HEADER_PAYLOAD_IDX,strcat(prefix,"  "));
00373     prefix[strlen(prefix)-2]=0;
00374     break;
00375       case HDR_CONTENTLENGTH_T:/*contentlength*/
00376     memcpy(&i,payload+HEADER_LEN_IDX,2);
00377     i=ntohs(i);
00378     print_encoded_contentlength(fd,hdr_start_ptr,i,&payload[HEADER_PAYLOAD_IDX],
00379           len-HEADER_PAYLOAD_IDX,strcat(prefix,"  "));
00380     prefix[strlen(prefix)-2]=0;
00381     break;
00382       case HDR_VIA_T:/*via*/
00383       case HDR_VIA2_T:/*via*/
00384     memcpy(&i,payload+HEADER_LEN_IDX,2);
00385     i=ntohs(i);
00386     print_encoded_via_body(fd,hdr_start_ptr,i,&payload[HEADER_PAYLOAD_IDX],
00387           len-HEADER_PAYLOAD_IDX,strcat(prefix,"  "));
00388     prefix[strlen(prefix)-2]=0;
00389     break;
00390       case HDR_ACCEPT_T:/*accept*/
00391     memcpy(&i,payload+HEADER_LEN_IDX,2);
00392     i=ntohs(i);
00393     print_encoded_accept(fd,hdr_start_ptr,i,&payload[HEADER_PAYLOAD_IDX],
00394           len-HEADER_PAYLOAD_IDX,strcat(prefix,"  "));
00395     prefix[strlen(prefix)-2]=0;
00396     break;
00397       case HDR_CONTENTTYPE_T:/*content-type*/
00398     memcpy(&i,payload+HEADER_LEN_IDX,2);
00399     i=ntohs(i);
00400     print_encoded_content_type(fd,hdr_start_ptr,i,&payload[HEADER_PAYLOAD_IDX],
00401           len-HEADER_PAYLOAD_IDX,strcat(prefix,"  "));
00402     prefix[strlen(prefix)-2]=0;
00403     break;
00404       case HDR_CSEQ_T:/*CSeq*/
00405     memcpy(&i,payload+HEADER_LEN_IDX,2);
00406     i=ntohs(i);
00407     print_encoded_cseq(fd,hdr_start_ptr,i,&payload[HEADER_PAYLOAD_IDX],
00408           len-HEADER_PAYLOAD_IDX,strcat(prefix,"  "));
00409     prefix[strlen(prefix)-2]=0;
00410     break;
00411       case HDR_EXPIRES_T:/*expires*/
00412     memcpy(&i,payload+HEADER_LEN_IDX,2);
00413     i=ntohs(i);
00414     print_encoded_expires(fd,hdr_start_ptr,i,&payload[HEADER_PAYLOAD_IDX],
00415           len-HEADER_PAYLOAD_IDX,strcat(prefix,"  "));
00416     prefix[strlen(prefix)-2]=0;
00417     break;
00418       case HDR_ALLOW_T:/*allow*/
00419     memcpy(&i,payload+HEADER_LEN_IDX,2);
00420     i=ntohs(i);
00421     print_encoded_allow(fd,hdr_start_ptr,i,&payload[HEADER_PAYLOAD_IDX],
00422           len-HEADER_PAYLOAD_IDX,strcat(prefix,"  "));
00423     prefix[strlen(prefix)-2]=0;
00424     break;
00425       case HDR_PROXYAUTH_T:/*proxy-authenticate*/
00426       case HDR_AUTHORIZATION_T:/*authorization*/
00427       /*case HDR_PROXYAUTHORIZATION_T:proxy-authorization*/
00428     memcpy(&i,payload+HEADER_LEN_IDX,2);
00429     i=ntohs(i);
00430     print_encoded_digest(fd,hdr_start_ptr,i,&payload[HEADER_PAYLOAD_IDX],
00431           len-HEADER_PAYLOAD_IDX,strcat(prefix,"  "));
00432     prefix[strlen(prefix)-2]=0;
00433     break;
00434       default:
00435     return 1;
00436    }
00437    return 1;
00438 }
00439 
00440 int dump_headers_test(char *msg,int msglen,unsigned char *payload,int len,char type,FILE* fd,char segregationLevel)
00441 {
00442    char *hdr_start_ptr;
00443    short int start_idx;
00444 
00445    memcpy(&start_idx,payload,2);
00446    start_idx=ntohs(start_idx);
00447 
00448    hdr_start_ptr = &msg[start_idx];
00449 
00450    switch(type){
00451       case 'f':/*from*/
00452       case 't':/*to*/
00453       case 'o':/*refer-to*/
00454       case 'p':/*rpid= remote parte id*/
00455     dump_to_body_test(hdr_start_ptr,payload[HEADER_LEN_IDX],&payload[HEADER_PAYLOAD_IDX],
00456           len-HEADER_PAYLOAD_IDX,fd,segregationLevel);
00457     break;
00458       case 'm':/*contact*/
00459     dump_contact_body_test(hdr_start_ptr,payload[HEADER_LEN_IDX],&payload[HEADER_PAYLOAD_IDX],
00460           len-HEADER_PAYLOAD_IDX,fd,segregationLevel,"");
00461     break;
00462       case 'r':/*route*/
00463       case 'R':/*record-route*/
00464     dump_route_body_test(hdr_start_ptr,payload[HEADER_LEN_IDX],&payload[HEADER_PAYLOAD_IDX],
00465           len-HEADER_PAYLOAD_IDX,fd,segregationLevel,"");
00466     break;
00467       case 'l':/*contentlength*/
00468     dump_standard_hdr_test(hdr_start_ptr,payload[HEADER_LEN_IDX],&payload[HEADER_PAYLOAD_IDX],
00469           len-HEADER_PAYLOAD_IDX,fd);
00470     break;
00471       case 'v':/*via*/
00472     dump_via_body_test(hdr_start_ptr,payload[HEADER_LEN_IDX],&payload[HEADER_PAYLOAD_IDX],
00473           len-HEADER_PAYLOAD_IDX,fd,segregationLevel);
00474     break;
00475       case 'A':/*Accept*/
00476     dump_standard_hdr_test(hdr_start_ptr,payload[HEADER_LEN_IDX],&payload[HEADER_PAYLOAD_IDX],
00477           len-HEADER_PAYLOAD_IDX,fd);
00478     break;
00479       case 'c':/*content-type*/
00480     dump_standard_hdr_test(hdr_start_ptr,payload[HEADER_LEN_IDX],&payload[HEADER_PAYLOAD_IDX],
00481           len-HEADER_PAYLOAD_IDX,fd);
00482     break;
00483       case 'S':/*CSeq*/
00484     dump_standard_hdr_test(hdr_start_ptr,payload[HEADER_LEN_IDX],&payload[HEADER_PAYLOAD_IDX],
00485           len-HEADER_PAYLOAD_IDX,fd);
00486     break;
00487       case 'P':/*expires*/
00488     dump_standard_hdr_test(hdr_start_ptr,payload[HEADER_LEN_IDX],&payload[HEADER_PAYLOAD_IDX],
00489           len-HEADER_PAYLOAD_IDX,fd);
00490     break;
00491       case 'a':/*allow*/
00492     dump_standard_hdr_test(hdr_start_ptr,payload[HEADER_LEN_IDX],&payload[HEADER_PAYLOAD_IDX],
00493           len-HEADER_PAYLOAD_IDX,fd);
00494     break;
00495       case 'h':/*proxy-authenticate*/
00496       case 'H':/*authorization*/
00497       case 'z':/*proxy-authorization*/
00498     dump_standard_hdr_test(hdr_start_ptr,payload[HEADER_LEN_IDX],&payload[HEADER_PAYLOAD_IDX],
00499           len-HEADER_PAYLOAD_IDX,fd);
00500     break;
00501       default:
00502     return 1;
00503    }
00504    return 1;
00505 }
00506 
00507 int dump_standard_hdr_test(char *hdr,int hdrlen,unsigned char *payload,int paylen,FILE* fd)
00508 {
00509    int i;
00510    i=htonl(hdrlen);
00511    fwrite(&i,1,4,fd);
00512    fwrite(hdr,1,hdrlen,fd);
00513    i=htonl(paylen);
00514    fwrite(&i,1,4,fd);
00515    fwrite(payload,1,paylen,fd);
00516    fwrite(&theSignal,1,4,fd);
00517    return 0;
00518 }

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