exec_hf.c

Go to the documentation of this file.
00001 /*
00002  * $Id: exec_hf.c 4518 2008-07-28 15:39:28Z henningw $
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-02-28 scratchpad compatibility abandoned
00025  *  2003-01-29 scratchpad removed
00026  *  2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
00027  *  2003-03-19  all mallocs/frees replaced w/ pkg_malloc/pkg_free (andrei)
00028  */
00029 
00030 /* functions for creating environment variables out of a request's
00031  * header; known compact header field names are translated to
00032  * canonical form; multiple header field occurrences are merged
00033  * into a single variable
00034  *
00035  * known limitations: 
00036  * - compact header field names unknown to parser will not be translated to 
00037  *   canonical form. Thus, environment variables may have either name and 
00038  *   users have to check for both of them.
00039  * - symbols in header field names will be translated to underscore
00040  *
00041  */
00042 
00043 #include <stdlib.h>
00044 
00045 #include "../../parser/msg_parser.h"
00046 #include "../../parser/parse_to.h"
00047 #include "../../parser/parse_via.h"
00048 #include "../../parser/parse_uri.h"
00049 #include "../../mem/mem.h"
00050 #include "../../dprint.h"
00051 #include "../../md5utils.h"
00052 #include "exec_hf.h"
00053 
00054 /* should be environment variables set by header fields ? */
00055 unsigned int setvars=1;
00056 
00057 /* insert a new header field into the structure; */
00058 static int insert_hf( struct hf_wrapper **list, struct hdr_field *hf )
00059 {
00060    struct hf_wrapper *w; /* new wrapper */
00061    struct hf_wrapper *i;
00062 
00063    w=(struct hf_wrapper *)pkg_malloc(sizeof(struct hf_wrapper));
00064    if (!w) {
00065       LM_ERR("ran out of pkg mem\n");
00066       return 0;
00067    }
00068    memset(w, 0, sizeof(struct hf_wrapper));
00069    w->var_type=W_HF;w->u.hf=hf; 
00070    w->prefix=HF_PREFIX; w->prefix_len=HF_PREFIX_LEN;
00071 
00072    /* is there another hf of the same type?... */
00073    for(i=*list; i; i=i->next_other) {
00074       if (i->var_type==W_HF && i->u.hf->type==hf->type) {
00075          /* if it is OTHER, check name too */
00076          if (hf->type==HDR_OTHER_T && (hf->name.len!=i->u.hf->name.len
00077                || strncasecmp(i->u.hf->name.s, hf->name.s, 
00078                   hf->name.len)!=0))
00079             continue;
00080          /* yes, we found a hf of same type */
00081          w->next_same=i->next_same;
00082          w->next_other=i->next_other;
00083          i->next_same=w;
00084          break;
00085       }
00086    }
00087    /* ... no previous HF of the same type found */
00088    if (i==0) {
00089       w->next_other=*list;
00090       *list=w;
00091    }
00092    return 1;
00093 }
00094 
00095 static void release_hf_struct( struct hf_wrapper *list )
00096 {
00097    struct hf_wrapper *i, *j, *nexts, *nexto;
00098 
00099    i=list;
00100    while(i) {
00101       nexto=i->next_other;
00102       j=i->next_same;
00103       pkg_free(i);
00104       /* release list of same type hf */
00105       while(j) {
00106          nexts=j->next_same;
00107          pkg_free(j);
00108          j=nexts;
00109       }
00110       i=nexto;
00111    }
00112 }
00113 
00114 /* if that is some of well-known header fields which have compact
00115  * form, return canonical form ... returns 1 and sets params;
00116  * 0 is returned otherwise */
00117 static int compacthdr_type2str(hdr_types_t  type, char **hname, int *hlen )
00118 {
00119    switch(type) {
00120       /* HDR_CONTENT_ENCODING: 'e' -- unsupported by parser */
00121       /* HDR_SUBJECT: 's' -- unsupported by parser */
00122       case HDR_VIA_T /* v */ : 
00123          *hname=VAR_VIA;
00124          *hlen=VAR_VIA_LEN;
00125          break;
00126       case HDR_CONTENTTYPE_T /* c */ : 
00127          *hname=VAR_CTYPE;
00128          *hlen=VAR_CTYPE_LEN;
00129          break;
00130       case HDR_FROM_T /* f */: 
00131          *hname=VAR_FROM;
00132          *hlen=VAR_FROM_LEN;
00133          break;
00134       case HDR_CALLID_T /* i */: 
00135          *hname=VAR_CALLID;
00136          *hlen=VAR_CALLID_LEN;
00137          break;
00138       case HDR_SUPPORTED_T /* k */: 
00139          *hname=VAR_SUPPORTED;
00140          *hlen=VAR_SUPPORTED_LEN;
00141          break;
00142       case HDR_CONTENTLENGTH_T /* l */: 
00143          *hname=VAR_CLEN;
00144          *hlen=VAR_CLEN_LEN;
00145          break;
00146       case HDR_CONTACT_T /* m */: 
00147          *hname=VAR_CONTACT;
00148          *hlen=VAR_CONTACT_LEN;
00149          break;
00150       case HDR_TO_T /* t */: 
00151          *hname=VAR_TO;
00152          *hlen=VAR_TO_LEN;
00153          break;
00154       case HDR_EVENT_T /* o */: 
00155          *hname=VAR_EVENT;
00156          *hlen=VAR_EVENT_LEN;
00157          break;
00158       default: 
00159          return 0;
00160    }
00161    return 1;
00162 }
00163 
00164 
00165 static int canonize_headername(str *orig, char **hname, int *hlen )
00166 {
00167    char *c;
00168    int i;
00169 
00170    *hlen=orig->len;
00171    *hname=pkg_malloc(*hlen);
00172    if (!*hname) {
00173       LM_ERR("no pkg mem for hname\n");
00174       return 0;
00175    }
00176    for (c=orig->s, i=0; i<*hlen; i++, c++) {
00177       /* lowercase to uppercase */
00178       if (*c>='a' && *c<='z') 
00179          *((*hname)+i)=*c-('a'-'A');
00180          /* uppercase and numbers stay "as is" */
00181       else if ((*c>='A' && *c<='Z')||(*c>='0' && *c<='9')) 
00182          *((*hname)+i)=*c;
00183       /* legal symbols will be translated to underscore */
00184       else if (strchr(UNRESERVED_MARK HNV_UNRESERVED, *c)
00185             || (*c==ESCAPE))
00186          *((*hname)+i)=HFN_SYMBOL;
00187       else {
00188          LM_ERR("print_var unexpected char '%c' in hfname %.*s\n", 
00189                *c, *hlen, orig->s );
00190          *((*hname)+i)=HFN_SYMBOL;
00191       }
00192    }
00193    return 1;
00194 }
00195 
00196 
00197 static int print_av_var(struct hf_wrapper *w)
00198 {
00199    int env_len;
00200    char *env;
00201    char *c;
00202 
00203    env_len=w->u.av.attr.len+1/*assignment*/+w->u.av.val.len+1/*ZT*/;
00204    env=pkg_malloc(env_len);
00205    if (!env) {
00206       LM_ERR("no pkg mem\n");
00207       return 0;
00208    }
00209    c=env;
00210    memcpy(c, w->u.av.attr.s, w->u.av.attr.len); c+=w->u.av.attr.len;
00211    *c=EV_ASSIGN;c++;
00212    memcpy(c, w->u.av.val.s, w->u.av.val.len);c+=w->u.av.val.len;
00213    *c=0; /* zero termination */
00214    w->envvar=env;
00215    return 1;
00216 }
00217 
00218 /* creates a malloc-ed string with environment variable; returns 1 on success,
00219  * 0 on failure  */
00220 static int print_hf_var(struct hf_wrapper *w, int offset)
00221 {
00222    char *hname;
00223    int hlen;
00224    short canonical;
00225    char *envvar;
00226    int envvar_len;
00227    struct hf_wrapper *wi;
00228    char *c;
00229 
00230    /* make -Wall happy */
00231    hname=0;hlen=0;envvar=0;
00232 
00233    /* Make sure header names with possible compact forms
00234     * will be printed canonically
00235     */
00236    canonical=compacthdr_type2str(w->u.hf->type, &hname, &hlen);
00237    /* header field has not been made canonical using a table;
00238     * do it now by uppercasing header-field name */
00239    if (!canonical) {
00240       if (!canonize_headername(&w->u.hf->name, &hname, &hlen)) {
00241          LM_ERR("canonize_hn error\n");
00242          return 0;
00243       }
00244    } 
00245    /* now we have a header name, let us generate the var */
00246    envvar_len=w->u.hf->body.len;
00247    for(wi=w->next_same; wi; wi=wi->next_same) { /* other values, separated */
00248       envvar_len+=1 /* separator */ + wi->u.hf->body.len;
00249    }
00250    envvar=pkg_malloc(w->prefix_len+hlen+1/*assignment*/+envvar_len+1/*ZT*/);
00251    if (!envvar) {
00252       LM_ERR("no pkg mem\n");
00253       goto error00;
00254    }
00255    memcpy(envvar, w->prefix, w->prefix_len); c=envvar+w->prefix_len;
00256    memcpy(c, hname, hlen ); c+=hlen;
00257    *c=EV_ASSIGN;c++;
00258    memcpy(c, w->u.hf->body.s+offset, w->u.hf->body.len );
00259    c+=w->u.hf->body.len;
00260    for (wi=w->next_same; wi; wi=wi->next_same) {
00261       *c=HF_SEPARATOR;c++;
00262       memcpy(c, wi->u.hf->body.s+offset, wi->u.hf->body.len );
00263       c+=wi->u.hf->body.len;
00264    }
00265    *c=0; /* zero termination */
00266    LM_DBG("%s\n", envvar );
00267    
00268    w->envvar=envvar;
00269    if (!canonical) pkg_free(hname);
00270    return 1;
00271 
00272 error00:
00273    if (!canonical) pkg_free(hname);
00274    return 0;
00275 }
00276 
00277 static int print_var(struct hf_wrapper *w, int offset)
00278 {
00279    switch(w->var_type) {
00280       case W_HF: 
00281          return print_hf_var(w, offset);
00282       case W_AV: 
00283          return print_av_var(w);
00284       default:
00285             LM_CRIT("unknown type: %d\n", w->var_type );
00286          return 0;
00287    }
00288 }
00289 
00290 static void release_vars(struct hf_wrapper *list) 
00291 {
00292    while(list) {
00293       if (list->envvar) {
00294          pkg_free(list->envvar);
00295          list->envvar=0;
00296       }
00297       list=list->next_other;
00298    }
00299 }
00300 
00301 /* create ordered HF structure in pkg memory */
00302 static int build_hf_struct(struct sip_msg *msg, struct hf_wrapper **list)
00303 {
00304    struct hdr_field *h;
00305 
00306    *list=0;
00307    /* create ordered header-field structure */
00308    for (h=msg->headers; h; h=h->next) {
00309       if (!insert_hf(list,h)) {
00310          LM_ERR("insert_hf failed\n");
00311          goto error00;
00312       }
00313    }
00314    return 1;
00315 error00:
00316    release_hf_struct(*list);
00317    *list=0;
00318    return 0;
00319 
00320 }
00321 
00322 /* create env vars in malloc memory */
00323 static int create_vars(struct hf_wrapper *list, int offset)
00324 {
00325    int var_cnt;
00326    struct hf_wrapper *w;
00327 
00328    /* create variables now */
00329    var_cnt=0;
00330    for(w=list;w;w=w->next_other) {
00331       if (!print_var(w, offset)) {
00332          LM_ERR("create_vars failed\n");
00333          return 0;
00334       }
00335       var_cnt++;
00336    }
00337 
00338    return var_cnt;
00339 }
00340 
00341 environment_t *replace_env(struct hf_wrapper *list)
00342 {
00343    int var_cnt;
00344    char **cp;
00345    struct hf_wrapper *w;
00346    char **new_env;
00347    int i;
00348    environment_t *backup_env;
00349 
00350    backup_env=(environment_t *)pkg_malloc(sizeof(environment_t));
00351    if (!backup_env) {
00352       LM_ERR("no pkg mem for backup env\n");
00353       return 0;
00354    }
00355 
00356    /* count length of current env list */
00357    var_cnt=0;
00358    for (cp=environ; *cp; cp++) var_cnt++;
00359    backup_env->old_cnt=var_cnt;
00360    /* count length of our extensions */
00361    for(w=list;w;w=w->next_other) var_cnt++;
00362    new_env=pkg_malloc((var_cnt+1)*sizeof(char *));
00363    if (!new_env) {
00364       LM_ERR("no pkg mem\n");
00365       return 0;
00366    }
00367    /* put all var pointers into new environment */
00368    i=0;
00369    for (cp=environ; *cp; cp++) { /* replicate old env */
00370       new_env[i]=*cp;
00371       i++;
00372    }
00373    for (w=list;w;w=w->next_other) { /* append new env */
00374       new_env[i]=w->envvar;
00375       i++;
00376    }
00377    new_env[i]=0; /* zero termination */
00378    /* install new environment */
00379    backup_env->env=environ;
00380    environ=new_env;
00381    /* return previous environment */
00382    return backup_env;
00383 }
00384 
00385 void unset_env(environment_t *backup_env)
00386 {
00387    char **cur_env, **cur_env0;
00388    int i;
00389 
00390    /* switch-over to backup environment */
00391    cur_env0=cur_env=environ;
00392    environ=backup_env->env;
00393    i=0;
00394    /* release environment */
00395    while(*cur_env) {
00396       /* leave previously existing vars alone */
00397       if (i>=backup_env->old_cnt) {
00398          pkg_free(*cur_env);
00399       }
00400       cur_env++;
00401       i++;
00402    }
00403    pkg_free(cur_env0);
00404    pkg_free(backup_env);
00405 }
00406 
00407 static int append_var(char *name, char *value, int len, struct hf_wrapper **list)
00408 {
00409    struct hf_wrapper *w;
00410 
00411    w=(struct hf_wrapper *)pkg_malloc(sizeof(struct hf_wrapper));
00412    if (!w) {
00413       LM_ERR("ran out of pkg mem\n");
00414       return 0;
00415    }
00416    memset(w, 0, sizeof(struct hf_wrapper)); 
00417    w->var_type=W_AV;
00418    w->u.av.attr.s=name;
00419    w->u.av.attr.len=strlen(name);
00420    w->u.av.val.s=value;
00421    /* NULL strings considered empty, if len unknown, calculate it now */
00422    w->u.av.val.len= value==0?0:(len==0? strlen(value) : len);
00423    w->next_other=*list;
00424    *list=w;
00425    return 1;
00426 }
00427 
00428 static int append_fixed_vars(struct sip_msg *msg, struct hf_wrapper **list)
00429 {
00430    static char tid[MD5_LEN];
00431    str *uri;
00432    struct sip_uri parsed_uri, oparsed_uri;
00433    char *val;
00434    int val_len;
00435 
00436    /* source ip */
00437    if (!append_var(EV_SRCIP, ip_addr2a(&msg->rcv.src_ip), 0, list)) {
00438       LM_ERR("append_var SRCIP failed \n");
00439       return 0;
00440    }
00441    /* request URI */
00442    uri=msg->new_uri.s && msg->new_uri.len ? 
00443       &msg->new_uri : &msg->first_line.u.request.uri;
00444    if (!append_var(EV_RURI, uri->s, uri->len, list )) {
00445       LM_ERR("append_var URI failed\n");
00446       return 0;
00447    }
00448    /* userpart of request URI */
00449    if (parse_uri(uri->s, uri->len, &parsed_uri)<0) {
00450       LM_WARN("uri not parsed\n");
00451    } else {
00452       if (!append_var(EV_USER, parsed_uri.user.s, 
00453                parsed_uri.user.len, list)) {
00454          LM_ERR("append_var USER failed\n");
00455          goto error;
00456       }
00457    }
00458    /* original URI */
00459    if (!append_var(EV_ORURI, msg->first_line.u.request.uri.s,
00460             msg->first_line.u.request.uri.len, list)) {
00461       LM_ERR("append_var O-URI failed\n");
00462       goto error;
00463    }
00464    /* userpart of request URI */
00465    if (parse_uri(msg->first_line.u.request.uri.s, 
00466             msg->first_line.u.request.uri.len, 
00467             &oparsed_uri)<0) {
00468       LM_WARN("orig URI not parsed\n");
00469    } else {
00470       if (!append_var(EV_OUSER, oparsed_uri.user.s, 
00471                oparsed_uri.user.len, list)) {
00472          LM_ERR("ppend_var OUSER failed\n");
00473          goto error;
00474       }
00475    }
00476    /* tid, transaction id == via/branch */
00477    if (!char_msg_val(msg, tid)) {
00478       LM_WARN("no tid can be determined\n");
00479       val=0; val_len=0;
00480    } else {
00481       val=tid;val_len=MD5_LEN;
00482    }
00483    if (!append_var(EV_TID, val,val_len, list)) {
00484       LM_ERR("append_var TID failed\n");
00485       goto error;
00486    }
00487 
00488    /* did, dialogue id == To-tag */
00489    if (!(msg->to && get_to(msg) ))  {
00490       LM_ERR("no to-tag\n");
00491       val=0; val_len=0;
00492    } else {
00493       val=get_to(msg)->tag_value.s;
00494       val_len=get_to(msg)->tag_value.len;
00495    }
00496    if (!append_var(EV_DID, val, val_len, list)) {
00497       LM_ERR("append_var DID failed\n");
00498       goto error;
00499    }
00500    return 1;
00501 error:
00502    return 0;
00503 }
00504 
00505 environment_t *set_env(struct sip_msg *msg)
00506 {
00507    struct hf_wrapper *hf_list;
00508    environment_t *backup_env;
00509 
00510    /* parse all so that we can pass all header fields to script */
00511    if (parse_headers(msg, HDR_EOH_F, 0)==-1) {
00512       LM_ERR("parsing failed\n");
00513       return 0;
00514    }
00515 
00516    hf_list=0;
00517    /* create a temporary structure with ordered header fields
00518     * and create environment variables out of it */
00519    if (!build_hf_struct(msg, &hf_list)) {
00520       LM_ERR("build_hf_struct failed\n");
00521       return 0;
00522    }
00523    if (!append_fixed_vars(msg, &hf_list)) {
00524       LM_ERR("append_fixed_vars failed\n");
00525       goto error01;
00526    }
00527    /* create now the strings for environment variables */
00528    if (!create_vars(hf_list, 0)) {
00529       LM_ERR("create_vars failed\n");
00530       goto error00;
00531    }
00532    /* install the variables in current environment */
00533    backup_env=replace_env(hf_list);
00534    if (!backup_env) {
00535       LM_ERR("replace_env failed\n");
00536       goto error00;
00537    }
00538    /* release the ordered HF structure -- we only need the vars now */
00539    release_hf_struct(hf_list);
00540    return backup_env;
00541 
00542 error00:
00543    release_vars(hf_list); /* release variables */
00544 error01:
00545    release_hf_struct(hf_list); /* release temporary ordered HF struct */
00546    return 0;
00547 }
00548 

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