registrar/sip_msg.c

Go to the documentation of this file.
00001 /*
00002  * $Id: sip_msg.c 4518 2008-07-28 15:39:28Z henningw $
00003  *
00004  * SIP message related functions
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 
00025 /*!
00026  * \file
00027  * \brief SIP registrar module - SIP message related functions
00028  * \ingroup registrar   
00029  */  
00030 
00031 
00032 
00033 #include "../../parser/hf.h"
00034 #include "../../dprint.h"
00035 #include "../../parser/parse_expires.h"  
00036 #include "../../ut.h"
00037 #include "../../qvalue.h"
00038 #include "reg_mod.h"                     /* Module parameters */
00039 #include "regtime.h"                     /* act_time */
00040 #include "rerrno.h"
00041 #include "sip_msg.h"
00042 
00043 
00044 static struct hdr_field* act_contact;
00045 
00046 
00047 /*! \brief
00048  * Return value of Expires header field
00049  * if the HF exists converted to absolute
00050  * time, if the HF doesn't exist, returns
00051  * default value;
00052  */
00053 static inline int get_expires_hf(struct sip_msg* _m)
00054 {
00055    exp_body_t* p;
00056    
00057    if (_m->expires) {
00058       p = (exp_body_t*)_m->expires->parsed;
00059       if (p->valid) {
00060          if (p->val != 0) {
00061             return p->val + act_time;
00062          } else return 0;
00063       } else return act_time + default_expires;
00064    } else {
00065       return act_time + default_expires;
00066    }
00067 }
00068 
00069 
00070 /*! \brief
00071  * Parse the whole message and bodies of all header fields
00072  * that will be needed by registrar
00073  */
00074 int parse_message(struct sip_msg* _m)
00075 {
00076    struct hdr_field* ptr;
00077    
00078    if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
00079       rerrno = R_PARSE;
00080       LM_ERR("failed to parse headers\n");
00081       return -1;
00082    }
00083    
00084    if (!_m->to) {
00085       rerrno = R_TO_MISS;
00086       LM_ERR("To not found\n");
00087       return -2;
00088    }
00089 
00090    if (!_m->callid) {
00091       rerrno = R_CID_MISS;
00092       LM_ERR("Call-ID not found\n");
00093       return -3;
00094    }
00095 
00096    if (!_m->cseq) {
00097       rerrno = R_CS_MISS;
00098       LM_ERR("CSeq not found\n");
00099       return -4;
00100    }
00101 
00102    if (_m->expires && !_m->expires->parsed && (parse_expires(_m->expires) < 0)) {
00103       rerrno = R_PARSE_EXP;
00104       LM_ERR("failed to parse expires body\n");
00105       return -5;
00106    }
00107    
00108    if (_m->contact) {
00109       ptr = _m->contact;
00110       while(ptr) {
00111          if (ptr->type == HDR_CONTACT_T) {
00112             if (!ptr->parsed && (parse_contact(ptr) < 0)) {
00113                rerrno = R_PARSE_CONT;
00114                LM_ERR("failed to parse Contact body\n");
00115                return -6;
00116             }
00117          }
00118          ptr = ptr->next;
00119       }
00120    }
00121    
00122    return 0;
00123 }
00124 
00125 
00126 /*! \brief
00127  * Check if the originating REGISTER message was formed correctly
00128  * The whole message must be parsed before calling the function
00129  * _s indicates whether the contact was star
00130  */
00131 int check_contacts(struct sip_msg* _m, int* _s)
00132 {
00133    struct hdr_field* p;
00134    contact_t*  c;
00135    
00136    *_s = 0;
00137    /* Message without contacts is OK */
00138    if (_m->contact == 0) return 0;
00139    
00140    if (((contact_body_t*)_m->contact->parsed)->star == 1) {
00141       /* The first Contact HF is star */
00142       /* Expires must be zero */
00143       if (get_expires_hf(_m) > 0) {
00144          rerrno = R_STAR_EXP;
00145          return 1;
00146       }
00147       
00148       /* Message must contain no contacts */
00149       if (((contact_body_t*)_m->contact->parsed)->contacts) {
00150          rerrno = R_STAR_CONT;
00151          return 1;
00152       }
00153       
00154       /* Message must contain no other Contact HFs */
00155       p = _m->contact->next;
00156       while(p) {
00157          if (p->type == HDR_CONTACT_T) {
00158             rerrno = R_STAR_CONT;
00159             return 1;
00160          }
00161          p = p->next;
00162       }
00163       
00164       *_s = 1;
00165    } else { /* The first Contact HF is not star */
00166       /* Message must contain no star Contact HF */
00167       p = _m->contact->next;
00168       while(p) {
00169          if (p->type == HDR_CONTACT_T) {
00170             if (((contact_body_t*)p->parsed)->star == 1) {
00171                rerrno = R_STAR_CONT;
00172                return 1;
00173             }
00174             /* check also the lenght of all contacts */
00175             for(c=((contact_body_t*)p->parsed)->contacts ; c ; c=c->next) {
00176                if (c->uri.len > CONTACT_MAX_SIZE
00177                || (c->received && c->received->len>RECEIVED_MAX_SIZE) ) {
00178                   rerrno = R_CONTACT_LEN;
00179                   return 1;
00180                }
00181             }
00182          }
00183          p = p->next;
00184       }
00185    }
00186    
00187    return 0;
00188 }
00189 
00190 
00191 /*! \brief
00192  * Get the first contact in message
00193  */
00194 contact_t* get_first_contact(struct sip_msg* _m)
00195 {
00196    if (_m->contact == 0) return 0;
00197    
00198    act_contact = _m->contact;
00199    return (((contact_body_t*)_m->contact->parsed)->contacts);
00200 }
00201 
00202 
00203 /*! \brief
00204  * Get next contact in message
00205  */
00206 contact_t* get_next_contact(contact_t* _c)
00207 {
00208    struct hdr_field* p;
00209    if (_c->next == 0) {
00210       p = act_contact->next;
00211       while(p) {
00212          if (p->type == HDR_CONTACT_T) {
00213             act_contact = p;
00214             return (((contact_body_t*)p->parsed)->contacts);
00215          }
00216          p = p->next;
00217       }
00218       return 0;
00219    } else {
00220       return _c->next;
00221    }
00222 }
00223 
00224 
00225 /*! \brief
00226  * Calculate absolute expires value per contact as follows:
00227  * 1) If the contact has expires value, use the value. If it
00228  *    is not zero, add actual time to it
00229  * 2) If the contact has no expires parameter, use expires
00230  *    header field in the same way
00231  * 3) If the message contained no expires header field, use
00232  *    the default value
00233  */
00234 void calc_contact_expires(struct sip_msg* _m, param_t* _ep, int* _e)
00235 {
00236    if (!_ep || !_ep->body.len) {
00237       *_e = get_expires_hf(_m);
00238    } else {
00239       if (str2int(&_ep->body, (unsigned int*)_e) < 0) {
00240          *_e = default_expires;
00241       }
00242       /* Convert to absolute value */
00243       if (*_e != 0) *_e += act_time;
00244    }
00245 
00246    if ((*_e != 0) && ((*_e - act_time) < min_expires)) {
00247       *_e = min_expires + act_time;
00248    }
00249 
00250    if ((*_e != 0) && max_expires && ((*_e - act_time) > max_expires)) {
00251       *_e = max_expires + act_time;
00252    }
00253 }
00254 
00255 
00256 /*! \brief
00257  * Calculate contact q value as follows:
00258  * 1) If q parameter exists, use it
00259  * 2) If the parameter doesn't exist, use the default value
00260  */
00261 int calc_contact_q(param_t* _q, qvalue_t* _r)
00262 {
00263    if (!_q || (_q->body.len == 0)) {
00264       *_r = default_q;
00265    } else {
00266       if (str2q(_r, _q->body.s, _q->body.len) < 0) {
00267          rerrno = R_INV_Q; /* Invalid q parameter */
00268          LM_ERR("invalid q parameter\n");
00269          return -1;
00270       }
00271    }
00272    return 0;
00273 }

Generated on Thu May 24 10:00:30 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6