modules_k/registrar/lookup.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Lookup contacts in usrloc
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-03-12 added support for zombie state (nils)
00027  */
00035 #include <string.h>
00036 #include "../../ut.h"
00037 #include "../../dset.h"
00038 #include "../../str.h"
00039 #include "../../xavp.h"
00040 #include "../../config.h"
00041 #include "../../action.h"
00042 #include "../../mod_fix.h"
00043 #include "../../parser/parse_rr.h"
00044 #include "../usrloc/usrloc.h"
00045 #include "common.h"
00046 #include "regtime.h"
00047 #include "reg_mod.h"
00048 #include "lookup.h"
00049 #include "config.h"
00050 
00051 #define allowed_method(_msg, _c) \
00052         ( !method_filtering || ((_msg)->REQ_METHOD)&((_c)->methods) )
00053 
00054 
00058 int reg_cmp_instances(str *i1, str *i2)
00059 {
00060         str inst1;
00061         str inst2;
00062 
00063         if(i1==NULL || i2==NULL || i1->len<=0 || i2->len<=0)
00064                 return -1;
00065 
00066         inst1 = *i1;
00067         inst2 = *i2;
00068         if(inst1.len>2 && inst1.s[0]=='<' && inst1.s[inst1.len-1]=='>')
00069         {
00070                 inst1.s++;
00071                 inst1.len -=2;
00072         }
00073         if(inst2.len>2 && inst2.s[0]=='<' && inst2.s[inst2.len-1]=='>')
00074         {
00075                 inst2.s++;
00076                 inst2.len -=2;
00077         }
00078         if(inst1.len>0 && inst1.len==inst2.len
00079                                                 && memcmp(inst1.s, inst2.s, inst2.len)==0)
00080                 return 0;
00081         return -1;
00082 }
00083 
00090 int lookup(struct sip_msg* _m, udomain_t* _d, str* _uri)
00091 {
00092         urecord_t* r;
00093         str aor, uri;
00094         sip_uri_t puri;
00095         ucontact_t* ptr = 0;
00096         int res;
00097         int ret;
00098         str path_dst;
00099         flag_t old_bflags;
00100         int i;
00101         str inst = {0};
00102         unsigned int ahash = 0;
00103         sr_xavp_t *xavp=NULL;
00104         sr_xavp_t *list=NULL;
00105         str xname = {"ruid", 4};
00106         sr_xval_t xval;
00107 
00108         ret = -1;
00109 
00110         if (_m->new_uri.s) uri = _m->new_uri;
00111         else uri = _m->first_line.u.request.uri;
00112         
00113         if (extract_aor((_uri)?_uri:&uri, &aor, &puri) < 0) {
00114                 LM_ERR("failed to extract address of record\n");
00115                 return -3;
00116         }
00117         /* check if gruu */
00118         if(puri.gr.s!=NULL)
00119         {
00120                 if(puri.gr_val.len>0) {
00121                         /* pub-gruu */
00122                         inst = puri.gr_val;
00123                         LM_DBG("looking up pub gruu [%.*s]\n", inst.len, inst.s);
00124                 } else {
00125                         /* temp-gruu */
00126                         ahash = 0;
00127                         inst = puri.user;
00128                         for(i=inst.len-1; i>=0; i--)
00129                         {
00130                                 if(inst.s[i]==REG_GRUU_SEP)
00131                                         break;
00132                                 ahash <<= 4;
00133                                 if(inst.s[i] >='0' && inst.s[i] <='9') ahash+=inst.s[i] -'0';
00134                                 else if (inst.s[i] >='a' && inst.s[i] <='f') ahash+=inst.s[i] -'a'+10;
00135                                 else if (inst.s[i] >='A' && inst.s[i] <='F') ahash+=inst.s[i] -'A'+10;
00136                                 else {
00137                                         LM_ERR("failed to extract temp gruu - invalid hash\n");
00138                                         return -3;
00139                                 }
00140                         }
00141                         if(i<0) {
00142                                 LM_ERR("failed to extract temp gruu - invalid format\n");
00143                                 return -3;
00144                         }
00145                         inst.len = i;
00146                         LM_DBG("looking up temp gruu [%u / %.*s]\n", ahash, inst.len, inst.s);
00147                 }
00148         }
00149 
00150         get_act_time();
00151 
00152         if(puri.gr.s==NULL || puri.gr_val.len>0)
00153         {
00154                 /* aor or pub-gruu lookup */
00155                 ul.lock_udomain(_d, &aor);
00156                 res = ul.get_urecord(_d, &aor, &r);
00157                 if (res > 0) {
00158                         LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
00159                         ul.unlock_udomain(_d, &aor);
00160                         return -1;
00161                 }
00162 
00163                 ptr = r->contacts;
00164                 ret = -1;
00165                 /* look first for an un-expired and suported contact */
00166                 while (ptr) {
00167                         if(VALID_CONTACT(ptr,act_time)) {
00168                                 if(allowed_method(_m,ptr)) {
00169                                         /* match on instance, if pub-gruu */
00170                                         if(inst.len>0) {
00171                                                 if(reg_cmp_instances(&inst, &ptr->instance)==0)
00172                                                 {
00173                                                         /* pub-gruu - found by instance */
00174                                                         LM_DBG("contact for [%.*s] found by pub gruu [%.*s]\n",
00175                                                                 aor.len, ZSW(aor.s), inst.len, inst.s);
00176                                                         break;
00177                                                 }
00178                                         } else {
00179                                                 /* no-gruu - found by address */
00180                                                 LM_DBG("contact for [%.*s] found by address\n",
00181                                                                 aor.len, ZSW(aor.s));
00182                                                 break;
00183                                         }
00184                                 } else {
00185                                         LM_DBG("contact for [%.*s] cannot handle the SIP method\n",
00186                                                         aor.len, ZSW(aor.s));
00187                                         ret = -2;
00188                                 }
00189                         }
00190                         ptr = ptr->next;
00191                 }
00192                 if (ptr==0) {
00193                         /* nothing found */
00194                         LM_DBG("'%.*s' has no valid contact in usrloc\n", aor.len, ZSW(aor.s));
00195                         goto done;
00196                 }
00197         } else {
00198                 /* temp-gruu lookup */
00199                 res = ul.get_urecord_by_ruid(_d, ahash, &inst, &r, &ptr);
00200                 if(res<0) {
00201                         LM_DBG("temp gruu '%.*s' not found in usrloc\n", aor.len, ZSW(aor.s));
00202                         return -1;
00203                 }
00204                 aor = *ptr->aor;
00205                 /* test if un-expired and suported contact */
00206                 if( (ptr) && !(VALID_CONTACT(ptr,act_time)
00207                                         && (ret=-2) && allowed_method(_m,ptr)))
00208                         goto done;
00209                 LM_DBG("contact for [%.*s] found by temp gruu [%.*s / %u]\n",
00210                                                         aor.len, ZSW(aor.s), inst.len, inst.s, ahash);
00211         }
00212 
00213         ret = 1;
00214         if (ptr) {
00215                 if (rewrite_uri(_m, &ptr->c) < 0) {
00216                         LM_ERR("unable to rewrite Request-URI\n");
00217                         ret = -3;
00218                         goto done;
00219                 }
00220 
00221                 /* reset next hop address */
00222                 reset_dst_uri(_m);
00223 
00224                 /* add xavp with details of the record (ruid, ...) */
00225                 if(reg_xavp_rcd.s!=NULL)
00226                 {
00227                         list = xavp_get(&reg_xavp_rcd, NULL);
00228                         xavp = list;
00229                         memset(&xval, 0, sizeof(sr_xval_t));
00230                         xval.type = SR_XTYPE_STR;
00231                         xval.v.s = ptr->ruid;
00232                         xavp_add_value(&xname, &xval, &xavp);
00233                         if(list==NULL)
00234                         {
00235                                 /* no reg_xavp_rcd xavp in root list - add it */
00236                                 xval.type = SR_XTYPE_XAVP;
00237                                 xval.v.xavp = xavp;
00238                                 xavp_add_value(&reg_xavp_rcd, &xval, NULL);
00239                         }
00240                 }
00241                 /* If a Path is present, use first path-uri in favour of
00242                  * received-uri because in that case the last hop towards the uac
00243                  * has to handle NAT. - agranig */
00244                 if (ptr->path.s && ptr->path.len) {
00245                         if (get_path_dst_uri(&ptr->path, &path_dst) < 0) {
00246                                 LM_ERR("failed to get dst_uri for Path\n");
00247                                 ret = -3;
00248                                 goto done;
00249                         }
00250                         if (set_path_vector(_m, &ptr->path) < 0) {
00251                                 LM_ERR("failed to set path vector\n");
00252                                 ret = -3;
00253                                 goto done;
00254                         }
00255                         if (set_dst_uri(_m, &path_dst) < 0) {
00256                                 LM_ERR("failed to set dst_uri of Path\n");
00257                                 ret = -3;
00258                                 goto done;
00259                         }
00260                 } else if (ptr->received.s && ptr->received.len) {
00261                         if (set_dst_uri(_m, &ptr->received) < 0) {
00262                                 ret = -3;
00263                                 goto done;
00264                         }
00265                 }
00266 
00267                 set_ruri_q(ptr->q);
00268 
00269                 old_bflags = 0;
00270                 getbflagsval(0, &old_bflags);
00271                 setbflagsval(0, old_bflags|ptr->cflags);
00272 
00273                 if (ptr->sock)
00274                         set_force_socket(_m, ptr->sock);
00275 
00276                 ptr = ptr->next;
00277         }
00278 
00279         /* if was gruu, no more branches */
00280         if(inst.len>0) goto done;
00281 
00282         /* Append branches if enabled */
00283         if (!cfg_get(registrar, registrar_cfg, append_branches)) goto done;
00284 
00285         for( ; ptr ; ptr = ptr->next ) {
00286                 if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) {
00287                         path_dst.len = 0;
00288                         if(ptr->path.s && ptr->path.len 
00289                         && get_path_dst_uri(&ptr->path, &path_dst) < 0) {
00290                                 LM_ERR("failed to get dst_uri for Path\n");
00291                                 continue;
00292                         }
00293 
00294                         /* The same as for the first contact applies for branches 
00295                          * regarding path vs. received. */
00296                         if (km_append_branch(_m,&ptr->c,path_dst.len?&path_dst:&ptr->received,
00297                         &ptr->path, ptr->q, ptr->cflags, ptr->sock) == -1) {
00298                                 LM_ERR("failed to append a branch\n");
00299                                 /* Also give a chance to the next branches*/
00300                                 continue;
00301                         }
00302                 }
00303         }
00304 
00305 done:
00306         ul.release_urecord(r);
00307         ul.unlock_udomain(_d, &aor);
00308         return ret;
00309 }
00310 
00311 
00317 int registered(struct sip_msg* _m, udomain_t* _d, str* _uri)
00318 {
00319         str uri, aor;
00320         urecord_t* r;
00321         ucontact_t* ptr;
00322         int res;
00323         int_str match_callid=(int_str)0;
00324 
00325         if(_uri!=NULL)
00326         {
00327                 uri = *_uri;
00328         } else {
00329                 if (_m->new_uri.s) uri = _m->new_uri;
00330                 else uri = _m->first_line.u.request.uri;
00331         }
00332         
00333         if (extract_aor(&uri, &aor, NULL) < 0) {
00334                 LM_ERR("failed to extract address of record\n");
00335                 return -1;
00336         }
00337         
00338         ul.lock_udomain(_d, &aor);
00339         res = ul.get_urecord(_d, &aor, &r);
00340 
00341         if (res < 0) {
00342                 ul.unlock_udomain(_d, &aor);
00343                 LM_ERR("failed to query usrloc\n");
00344                 return -1;
00345         }
00346 
00347         if (res == 0) {
00348                 
00349                 if (reg_callid_avp_name.n) {
00350                         struct usr_avp *avp =
00351                                 search_first_avp( reg_callid_avp_type, reg_callid_avp_name, &match_callid, 0);
00352                         if (!(avp && is_avp_str_val(avp)))
00353                                 match_callid.n = 0;
00354                                 match_callid.s.s = NULL;
00355                 } else {
00356                         match_callid.n = 0;
00357                         match_callid.s.s = NULL;
00358                 }
00359 
00360                 for (ptr = r->contacts; ptr; ptr = ptr->next) {
00361                         if(!VALID_CONTACT(ptr, act_time)) continue;
00362                         if (match_callid.s.s && /* optionally enforce tighter matching w/ Call-ID */
00363                                 memcmp(match_callid.s.s,ptr->callid.s,match_callid.s.len))
00364                                 continue;
00365                         ul.release_urecord(r);
00366                         ul.unlock_udomain(_d, &aor);
00367                         LM_DBG("'%.*s' found in usrloc\n", aor.len, ZSW(aor.s));
00368                         return 1;
00369                 }
00370         }
00371 
00372         ul.unlock_udomain(_d, &aor);
00373         LM_DBG("'%.*s' not found in usrloc\n", aor.len, ZSW(aor.s));
00374         return -1;
00375 }