k/registrar/sip_msg.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
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 
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 #include "config.h"
00043 #include <stdlib.h>
00044 
00045 static struct hdr_field* act_contact;
00046 
00050 static inline int get_expire_val(void)
00051 {
00052         int expires = cfg_get(registrar, registrar_cfg, default_expires);
00053         int range = cfg_get(registrar, registrar_cfg, default_expires_range);
00054         /* if no range is given just return default_expires */
00055         if(range == 0) return expires;
00056         /* select a random value in the range */
00057         return expires - (float)range/100 * expires + (float)(rand()%100)/100 * 2 * (float)range/100 * expires;
00058 }
00059 
00060 
00067 static inline int get_expires_hf(struct sip_msg* _m)
00068 {
00069         exp_body_t* p;
00070         if (_m->expires) {
00071                 p = (exp_body_t*)_m->expires->parsed;
00072                 if (p->valid) {
00073                         if (p->val != 0) {
00074                                 return p->val + act_time;
00075                         } else return 0;
00076                 } else {
00077                         return act_time + get_expire_val();
00078                 }
00079         } else
00080                 return act_time + get_expire_val();
00081 }
00082 
00083 
00088 int parse_message(struct sip_msg* _m)
00089 {
00090         struct hdr_field* ptr;
00091         
00092         if (parse_headers(_m, HDR_EOH_F, 0) == -1) {
00093                 rerrno = R_PARSE;
00094                 LM_ERR("failed to parse headers\n");
00095                 return -1;
00096         }
00097         
00098         if (!_m->to) {
00099                 rerrno = R_TO_MISS;
00100                 LM_ERR("To not found\n");
00101                 return -2;
00102         }
00103 
00104         if (!_m->callid) {
00105                 rerrno = R_CID_MISS;
00106                 LM_ERR("Call-ID not found\n");
00107                 return -3;
00108         }
00109 
00110         if (!_m->cseq) {
00111                 rerrno = R_CS_MISS;
00112                 LM_ERR("CSeq not found\n");
00113                 return -4;
00114         }
00115 
00116         if (_m->expires && !_m->expires->parsed && (parse_expires(_m->expires) < 0)) {
00117                 rerrno = R_PARSE_EXP;
00118                 LM_ERR("failed to parse expires body\n");
00119                 return -5;
00120         }
00121         
00122         if (_m->contact) {
00123                 ptr = _m->contact;
00124                 while(ptr) {
00125                         if (ptr->type == HDR_CONTACT_T) {
00126                                 if (!ptr->parsed && (parse_contact(ptr) < 0)) {
00127                                         rerrno = R_PARSE_CONT;
00128                                         LM_ERR("failed to parse Contact body\n");
00129                                         return -6;
00130                                 }
00131                         }
00132                         ptr = ptr->next;
00133                 }
00134         }
00135         
00136         return 0;
00137 }
00138 
00139 
00145 int check_contacts(struct sip_msg* _m, int* _s)
00146 {
00147         struct hdr_field* p;
00148         contact_t*  c;
00149         
00150         *_s = 0;
00151         /* Message without contacts is OK */
00152         if (_m->contact == 0) return 0;
00153         
00154         if (((contact_body_t*)_m->contact->parsed)->star == 1) {
00155                 /* The first Contact HF is star */
00156                 /* Expires must be zero */
00157                 if (get_expires_hf(_m) > 0) {
00158                         rerrno = R_STAR_EXP;
00159                         return 1;
00160                 }
00161                 
00162                 /* Message must contain no contacts */
00163                 if (((contact_body_t*)_m->contact->parsed)->contacts) {
00164                         rerrno = R_STAR_CONT;
00165                         return 1;
00166                 }
00167                 
00168                 /* Message must contain no other Contact HFs */
00169                 p = _m->contact->next;
00170                 while(p) {
00171                         if (p->type == HDR_CONTACT_T) {
00172                                 rerrno = R_STAR_CONT;
00173                                 return 1;
00174                         }
00175                         p = p->next;
00176                 }
00177                 
00178                 *_s = 1;
00179         } else { /* The first Contact HF is not star */
00180                 /* Message must contain no star Contact HF */
00181                 p = _m->contact->next;
00182                 while(p) {
00183                         if (p->type == HDR_CONTACT_T) {
00184                                 if (((contact_body_t*)p->parsed)->star == 1) {
00185                                         rerrno = R_STAR_CONT;
00186                                         return 1;
00187                                 }
00188                                 /* check also the lenght of all contacts */
00189                                 for(c=((contact_body_t*)p->parsed)->contacts ; c ; c=c->next) {
00190                                         if (c->uri.len > CONTACT_MAX_SIZE
00191                                         || (c->received && c->received->len>RECEIVED_MAX_SIZE) ) {
00192                                                 rerrno = R_CONTACT_LEN;
00193                                                 return 1;
00194                                         }
00195                                 }
00196                         }
00197                         p = p->next;
00198                 }
00199         }
00200         
00201         return 0;
00202 }
00203 
00204 
00208 contact_t* get_first_contact(struct sip_msg* _m)
00209 {
00210         if (_m->contact == 0) return 0;
00211         
00212         act_contact = _m->contact;
00213         return (((contact_body_t*)_m->contact->parsed)->contacts);
00214 }
00215 
00216 
00220 contact_t* get_next_contact(contact_t* _c)
00221 {
00222         struct hdr_field* p;
00223         if (_c->next == 0) {
00224                 p = act_contact->next;
00225                 while(p) {
00226                         if (p->type == HDR_CONTACT_T) {
00227                                 act_contact = p;
00228                                 return (((contact_body_t*)p->parsed)->contacts);
00229                         }
00230                         p = p->next;
00231                 }
00232                 return 0;
00233         } else {
00234                 return _c->next;
00235         }
00236 }
00237 
00238 
00248 void calc_contact_expires(struct sip_msg* _m, param_t* _ep, int* _e)
00249 {
00250         if (!_ep || !_ep->body.len) {
00251                 *_e = get_expires_hf(_m);
00252         } else {
00253                 if (str2int(&_ep->body, (unsigned int*)_e) < 0) {
00254                         *_e = get_expire_val();
00255                 }
00256                 /* Convert to absolute value */
00257                 if (*_e != 0) *_e += act_time;
00258         }
00259 
00260         if ((*_e != 0) && ((*_e - act_time) < cfg_get(registrar, registrar_cfg, min_expires))) {
00261                 *_e = cfg_get(registrar, registrar_cfg, min_expires) + act_time;
00262         }
00263 
00264         if ((*_e != 0) && cfg_get(registrar, registrar_cfg, max_expires) && ((*_e - act_time) > cfg_get(registrar, registrar_cfg, max_expires))) {
00265                 *_e = cfg_get(registrar, registrar_cfg, max_expires) + act_time;
00266         }
00267 }
00268 
00269 
00275 int calc_contact_q(param_t* _q, qvalue_t* _r)
00276 {
00277         if (!_q || (_q->body.len == 0)) {
00278                 *_r = cfg_get(registrar, registrar_cfg, default_q);
00279         } else {
00280                 if (str2q(_r, _q->body.s, _q->body.len) < 0) {
00281                         rerrno = R_INV_Q; /* Invalid q parameter */
00282                         LM_ERR("invalid q parameter\n");
00283                         return -1;
00284                 }
00285         }
00286         return 0;
00287 }