modules_k/registrar/reg_mod.c

Go to the documentation of this file.
00001 /*
00002  * $Id$
00003  *
00004  * Registrar module interface
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-11  updated to the new module exports interface (andrei)
00027  *  2003-03-16  flags export parameter added (janakj)
00028  *  2003-03-21  save_noreply added, provided by Maxim Sobolev
00029  *              <sobomax@portaone.com> (janakj)
00030  *  2005-07-11  added sip_natping_flag for nat pinging with SIP method
00031  *              instead of UDP package (bogdan)
00032  *  2006-09-19  AOR may be provided via an AVP instead of being fetched
00033  *              from URI (bogdan)
00034  *  2006-10-04  removed the "desc_time_order" parameter, as its functionality
00035  *              was moved to usrloc (Carsten Bock, BASIS AudioNet GmbH)
00036  *  2006-11-22  save_noreply and save_memory merged into save();
00037  *              removed the module parameter "use_domain" - now it is
00038  *              imported from usrloc module (bogdan)
00039  *  2006-11-28  Added statistics tracking for the number of accepted/rejected
00040  *              registrations, as well as for the max expiry time, max 
00041  *              contacts and default expiry time(Jeffrey Magder-SOMA Networks)
00042  *  2007-02-24  sip_natping_flag moved into branch flags, so migrated to 
00043  *              nathelper module (bogdan)
00044  *  2009-12-09  Commented out tcp_persistent_flag param, because sr_3.0 tm
00045  *              does not support it (Juha)
00046  *
00047  */
00048 
00062 #include <stdio.h>
00063 #include "../../sr_module.h"
00064 #include "../../timer.h"
00065 #include "../../dprint.h"
00066 #include "../../error.h"
00067 #include "../../socket_info.h"
00068 #include "../../pvar.h"
00069 #include "../../modules_k/usrloc/usrloc.h"
00070 #include "../../lib/kcore/statistics.h"
00071 #include "../../lib/srutils/sruid.h"
00072 #include "../../modules/sl/sl.h"
00073 #include "../../mod_fix.h"
00074 
00075 #include "save.h"
00076 #include "api.h"
00077 #include "lookup.h"
00078 #include "regpv.h"
00079 #include "reply.h"
00080 #include "reg_mod.h"
00081 #include "config.h"
00082 
00083 MODULE_VERSION
00084 
00085 usrloc_api_t ul;
00088 static int  mod_init(void);
00089 static int  child_init(int);
00090 static void mod_destroy(void);
00091 static int w_save2(struct sip_msg* _m, char* _d, char* _cflags);
00092 static int w_save3(struct sip_msg* _m, char* _d, char* _cflags, char* _uri);
00093 static int w_lookup(struct sip_msg* _m, char* _d, char* _p2);
00094 static int w_registered(struct sip_msg* _m, char* _d, char* _uri);
00095 static int w_unregister(struct sip_msg* _m, char* _d, char* _uri);
00096 
00098 static int domain_fixup(void** param, int param_no);
00099 static int domain_uri_fixup(void** param, int param_no);
00100 static int save_fixup(void** param, int param_no);
00101 static int unreg_fixup(void** param, int param_no);
00102 static int fetchc_fixup(void** param, int param_no);
00104 static int add_sock_hdr(struct sip_msg* msg, char *str, char *foo);
00105 
00106 int tcp_persistent_flag = -1;                   
00107 int method_filtering = 0;                       
00108 int path_enabled = 0;                           
00109 int path_mode = PATH_MODE_STRICT;               
00114 int path_use_params = 0;                        
00117 /* sruid to get internal uid */
00118 sruid_t _reg_sruid;
00119 
00120 int reg_gruu_enabled = 1;
00121 
00122 /* Populate this AVP if testing for specific registration instance. */
00123 char *reg_callid_avp_param = 0;
00124 unsigned short reg_callid_avp_type = 0;
00125 int_str reg_callid_avp_name;
00126 
00127 char* rcv_avp_param = 0;
00128 unsigned short rcv_avp_type = 0;
00129 int_str rcv_avp_name;
00130 
00131 str reg_xavp_cfg = {0};
00132 str reg_xavp_rcd = {0};
00133 
00134 int reg_use_domain = 0;
00135 
00136 int sock_flag = -1;
00137 str sock_hdr_name = {0,0};
00138 
00139 #define RCV_NAME "received"
00140 str rcv_param = str_init(RCV_NAME);
00141 
00142 stat_var *accepted_registrations;
00143 stat_var *rejected_registrations;
00144 stat_var *max_expires_stat;
00145 stat_var *max_contacts_stat;
00146 stat_var *default_expire_stat;
00147 stat_var *default_expire_range_stat;
00149 sl_api_t slb;
00150 
00154 static pv_export_t mod_pvs[] = {
00155         { {"ulc", sizeof("ulc")-1}, PVT_OTHER, pv_get_ulc, pv_set_ulc,
00156                 pv_parse_ulc_name, pv_parse_index, 0, 0 },
00157         { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
00158 };
00159 
00160 
00164 static cmd_export_t cmds[] = {
00165         {"save",         (cmd_function)w_save2,       1,  save_fixup, 0,
00166                         REQUEST_ROUTE | ONREPLY_ROUTE },
00167         {"save",         (cmd_function)w_save2,       2,  save_fixup, 0,
00168                         REQUEST_ROUTE | ONREPLY_ROUTE },
00169         {"save",         (cmd_function)w_save3,       3,  save_fixup, 0,
00170                         REQUEST_ROUTE | ONREPLY_ROUTE },
00171         {"lookup",       (cmd_function)w_lookup,      1,  domain_uri_fixup, 0,
00172                         REQUEST_ROUTE | FAILURE_ROUTE },
00173         {"lookup",       (cmd_function)w_lookup,      2,  domain_uri_fixup, 0,
00174                         REQUEST_ROUTE | FAILURE_ROUTE },
00175         {"registered",   (cmd_function)w_registered,  1,  domain_uri_fixup, 0,
00176                         REQUEST_ROUTE | FAILURE_ROUTE },
00177         {"registered",   (cmd_function)w_registered,  2,  domain_uri_fixup, 0,
00178                         REQUEST_ROUTE | FAILURE_ROUTE },
00179         {"add_sock_hdr", (cmd_function)add_sock_hdr,  1,  fixup_str_null, 0,
00180                         REQUEST_ROUTE },
00181         {"unregister",   (cmd_function)w_unregister,  2,  unreg_fixup, 0,
00182                         REQUEST_ROUTE| FAILURE_ROUTE },
00183         {"reg_fetch_contacts", (cmd_function)pv_fetch_contacts, 3, 
00184                         fetchc_fixup, 0,
00185                         REQUEST_ROUTE| FAILURE_ROUTE },
00186         {"reg_free_contacts", (cmd_function)pv_free_contacts,   1,
00187                         fixup_str_null, 0,
00188                         REQUEST_ROUTE| FAILURE_ROUTE },
00189         {"bind_registrar",  (cmd_function)bind_registrar,  0,
00190                 0, 0, 0},
00191         {0, 0, 0, 0, 0, 0}
00192 };
00193 
00194 
00198 static param_export_t params[] = {
00199         {"default_expires",    INT_PARAM, &default_registrar_cfg.default_expires                },
00200         {"default_expires_range", INT_PARAM, &default_registrar_cfg.default_expires_range       },
00201         {"default_q",          INT_PARAM, &default_registrar_cfg.default_q                      },
00202         {"append_branches",    INT_PARAM, &default_registrar_cfg.append_branches                },
00203         {"case_sensitive",     INT_PARAM, &default_registrar_cfg.case_sensitive                 },
00204         /*      {"tcp_persistent_flag",INT_PARAM, &tcp_persistent_flag }, */
00205         {"realm_prefix",       PARAM_STR, &default_registrar_cfg.realm_pref                     },
00206         {"min_expires",        INT_PARAM, &default_registrar_cfg.min_expires                    },
00207         {"max_expires",        INT_PARAM, &default_registrar_cfg.max_expires                    },
00208         {"received_param",     STR_PARAM, &rcv_param                                            },
00209         {"received_avp",       STR_PARAM, &rcv_avp_param                                        },
00210         {"reg_callid_avp",     STR_PARAM, &reg_callid_avp_param                                 },
00211         {"max_contacts",       INT_PARAM, &default_registrar_cfg.max_contacts                   },
00212         {"retry_after",        INT_PARAM, &default_registrar_cfg.retry_after                    },
00213         {"sock_flag",          INT_PARAM, &sock_flag                                            },
00214         {"sock_hdr_name",      STR_PARAM, &sock_hdr_name.s                                      },
00215         {"method_filtering",   INT_PARAM, &method_filtering                                     },
00216         {"use_path",           INT_PARAM, &path_enabled                                         },
00217         {"path_mode",          INT_PARAM, &path_mode                                            },
00218         {"path_use_received",  INT_PARAM, &path_use_params                                      },
00219         {"xavp_cfg",           STR_PARAM, &reg_xavp_cfg.s                                       },
00220         {"xavp_rcd",           STR_PARAM, &reg_xavp_rcd.s                                       },
00221         {"gruu_enabled",       INT_PARAM, &reg_gruu_enabled                                     },
00222         {0, 0, 0}
00223 };
00224 
00225 
00227 stat_export_t mod_stats[] = {
00228         {"max_expires",       STAT_NO_RESET, &max_expires_stat        },
00229         {"max_contacts",      STAT_NO_RESET, &max_contacts_stat       },
00230         {"default_expire",    STAT_NO_RESET, &default_expire_stat     },
00231         {"default_expires_range", STAT_NO_RESET, &default_expire_range_stat },
00232         {"accepted_regs",                 0, &accepted_registrations  },
00233         {"rejected_regs",                 0, &rejected_registrations  },
00234         {0, 0, 0}
00235 };
00236 
00237 
00238 
00242 struct module_exports exports = {
00243         "registrar", 
00244         DEFAULT_DLFLAGS, /* dlopen flags */
00245         cmds,        /* Exported functions */
00246         params,      /* Exported parameters */
00247         mod_stats,   /* exported statistics */
00248         0,           /* exported MI functions */
00249         mod_pvs,     /* exported pseudo-variables */
00250         0,           /* extra processes */
00251         mod_init,    /* module initialization function */
00252         0,
00253         mod_destroy, /* destroy function */
00254         child_init,  /* Per-child init function */
00255 };
00256 
00257 
00261 static int mod_init(void)
00262 {
00263         pv_spec_t avp_spec;
00264         str s;
00265         bind_usrloc_t bind_usrloc;
00266         qvalue_t dq;
00267 
00268 
00269         if(sruid_init(&_reg_sruid, '-', "uloc", SRUID_INC)<0)
00270                 return -1;
00271 
00272 #ifdef STATISTICS
00273         /* register statistics */
00274         if (register_module_stats( exports.name, mod_stats)!=0 ) {
00275                 LM_ERR("failed to register core statistics\n");
00276                 return -1;
00277         }
00278 #endif
00279 
00280         /* bind the SL API */
00281         if (sl_load_api(&slb)!=0) {
00282                 LM_ERR("cannot bind to SL API\n");
00283                 return -1;
00284         }
00285 
00286         rcv_param.len = strlen(rcv_param.s);
00287         
00288         if(cfg_declare("registrar", registrar_cfg_def, &default_registrar_cfg, cfg_sizeof(registrar), &registrar_cfg)){
00289                 LM_ERR("Fail to declare the configuration\n");
00290                 return -1;
00291         }
00292                                                         
00293                                                         
00294 
00295         if (rcv_avp_param && *rcv_avp_param) {
00296                 s.s = rcv_avp_param; s.len = strlen(s.s);
00297                 if (pv_parse_spec(&s, &avp_spec)==0
00298                                 || avp_spec.type!=PVT_AVP) {
00299                         LM_ERR("malformed or non AVP %s AVP definition\n", rcv_avp_param);
00300                         return -1;
00301                 }
00302 
00303                 if(pv_get_avp_name(0, &avp_spec.pvp, &rcv_avp_name, &rcv_avp_type)!=0)
00304                 {
00305                         LM_ERR("[%s]- invalid AVP definition\n", rcv_avp_param);
00306                         return -1;
00307                 }
00308         } else {
00309                 rcv_avp_name.n = 0;
00310                 rcv_avp_type = 0;
00311         }
00312 
00313         if (reg_callid_avp_param && *reg_callid_avp_param) {
00314                 s.s = reg_callid_avp_param; s.len = strlen(s.s);
00315                 if (pv_parse_spec(&s, &avp_spec)==0
00316                         || avp_spec.type!=PVT_AVP) {
00317                         LM_ERR("malformed or non AVP %s AVP definition\n", reg_callid_avp_param);
00318                         return -1;
00319                 }
00320 
00321                 if(pv_get_avp_name(0, &avp_spec.pvp, &reg_callid_avp_name, &reg_callid_avp_type)!=0)
00322                 {
00323                         LM_ERR("[%s]- invalid AVP definition\n", reg_callid_avp_param);
00324                         return -1;
00325                 }
00326         } else {
00327                 reg_callid_avp_name.n = 0;
00328                 reg_callid_avp_type = 0;
00329         }
00330 
00331         bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0);
00332         if (!bind_usrloc) {
00333                 LM_ERR("can't bind usrloc\n");
00334                 return -1;
00335         }
00336 
00337         /* Normalize default_q parameter */
00338         dq = cfg_get(registrar, registrar_cfg, default_q);
00339         if ( dq!= Q_UNSPECIFIED) {
00340                 if (dq > MAX_Q) {
00341                         LM_DBG("default_q = %d, lowering to MAX_Q: %d\n", dq, MAX_Q);
00342                         dq = MAX_Q;
00343                 } else if (dq < MIN_Q) {
00344                         LM_DBG("default_q = %d, raising to MIN_Q: %d\n", dq, MIN_Q);
00345                         dq = MIN_Q;
00346                 }
00347         }
00348         cfg_get(registrar, registrar_cfg, default_q) = dq;
00349 
00350         if (bind_usrloc(&ul) < 0) {
00351                 return -1;
00352         }
00353 
00354         /*
00355          * Import use_domain parameter from usrloc
00356          */
00357         reg_use_domain = ul.use_domain;
00358 
00359         if (sock_hdr_name.s) {
00360                 sock_hdr_name.len = strlen(sock_hdr_name.s);
00361                 if (sock_hdr_name.len==0 || sock_flag==-1) {
00362                         LM_WARN("empty sock_hdr_name or sock_flag no set -> reseting\n");
00363                         pkg_free(sock_hdr_name.s);
00364                         sock_hdr_name.s = 0;
00365                         sock_hdr_name.len = 0;
00366                         sock_flag = -1;
00367                 }
00368         } else if (sock_flag!=-1) {
00369                 LM_WARN("sock_flag defined but no sock_hdr_name -> reseting flag\n");
00370                 sock_flag = -1;
00371         }
00372 
00373         /* fix the flags */
00374         sock_flag = (sock_flag!=-1)?(1<<sock_flag):0;
00375         tcp_persistent_flag = (tcp_persistent_flag!=-1)?(1<<tcp_persistent_flag):0;
00376 
00377         if (reg_xavp_cfg.s) {
00378                 reg_xavp_cfg.len = strlen(reg_xavp_cfg.s);
00379         }
00380         if (reg_xavp_rcd.s) {
00381                 reg_xavp_rcd.len = strlen(reg_xavp_rcd.s);
00382         }
00383         return 0;
00384 }
00385 
00386 
00387 static int child_init(int rank)
00388 {
00389         if(sruid_init(&_reg_sruid, '-', "uloc", SRUID_INC)<0)
00390                 return -1;
00391         if (rank==1) {
00392                 /* init stats */
00393                 //TODO if parameters are modified via cfg framework do i change them?
00394                 update_stat( max_expires_stat, default_registrar_cfg.max_expires );
00395                 update_stat( max_contacts_stat, default_registrar_cfg.max_contacts );
00396                 update_stat( default_expire_stat, default_registrar_cfg.default_expires );
00397         }
00398 
00399         return 0;
00400 }
00401 
00405 static int w_save2(struct sip_msg* _m, char* _d, char* _cflags)
00406 {
00407         return save(_m, (udomain_t*)_d, ((int)(unsigned long)_cflags), NULL);
00408 }
00409 
00413 static int w_save3(struct sip_msg* _m, char* _d, char* _cflags, char* _uri)
00414 {
00415         str uri;
00416         if(fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0)
00417         {
00418                 LM_ERR("invalid uri parameter\n");
00419                 return -1;
00420         }
00421 
00422         return save(_m, (udomain_t*)_d, ((int)(unsigned long)_cflags), &uri);
00423 }
00424 
00428 static int w_lookup(struct sip_msg* _m, char* _d, char* _uri)
00429 {
00430         str uri = {0};
00431         if(_uri!=NULL && (fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0))
00432         {
00433                 LM_ERR("invalid uri parameter\n");
00434                 return -1;
00435         }
00436 
00437         return lookup(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL);
00438 }
00439 
00440 static int w_registered(struct sip_msg* _m, char* _d, char* _uri)
00441 {
00442         str uri = {0};
00443         if(_uri!=NULL && (fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0))
00444         {
00445                 LM_ERR("invalid uri parameter\n");
00446                 return -1;
00447         }
00448         return registered(_m, (udomain_t*)_d, (uri.len>0)?&uri:NULL);
00449 }
00450 
00451 static int w_unregister(struct sip_msg* _m, char* _d, char* _uri)
00452 {
00453         str uri = {0};
00454         if(fixup_get_svalue(_m, (gparam_p)_uri, &uri)!=0 || uri.len<=0)
00455         {
00456                 LM_ERR("invalid uri parameter\n");
00457                 return -1;
00458         }
00459 
00460         return unregister(_m, (udomain_t*)_d, &uri);
00461 }
00462 
00466 static int domain_fixup(void** param, int param_no)
00467 {
00468         udomain_t* d;
00469 
00470         if (param_no == 1) {
00471                 if (ul.register_udomain((char*)*param, &d) < 0) {
00472                         LM_ERR("failed to register domain\n");
00473                         return E_UNSPEC;
00474                 }
00475 
00476                 *param = (void*)d;
00477         }
00478         return 0;
00479 }
00480 
00484 static int domain_uri_fixup(void** param, int param_no)
00485 {
00486         if (param_no == 1) {
00487                 return domain_fixup(param, 1);
00488         } else if (param_no == 2) {
00489                 return fixup_spve_null(param, 1);
00490         }
00491         return 0;
00492 }
00493 
00494 
00499 static int unreg_fixup(void** param, int param_no)
00500 {
00501         if (param_no == 1) {
00502                 return domain_fixup(param, 1);
00503         } else if (param_no == 2) {
00504                 return fixup_spve_null(param, 1);
00505         }
00506         return 0;
00507 }
00508 
00509 
00510 
00514 static int save_fixup(void** param, int param_no)
00515 {
00516         unsigned int flags;
00517         str s;
00518 
00519         if (param_no == 1) {
00520                 return domain_fixup(param,param_no);
00521         } else if (param_no == 2) {
00522                 s.s = (char*)*param;
00523                 s.len = strlen(s.s);
00524                 flags = 0;
00525                 if ( (strno2int(&s, &flags )<0) || (flags>REG_SAVE_ALL_FL) ) {
00526                         LM_ERR("bad flags <%s>\n", (char *)(*param));
00527                         return E_CFG;
00528                 }
00529                 if (ul.db_mode==DB_ONLY && flags&REG_SAVE_MEM_FL) {
00530                         LM_ERR("MEM flag set while using the DB_ONLY mode in USRLOC\n");
00531                         return E_CFG;
00532                 }
00533                 pkg_free(*param);
00534                 *param = (void*)(unsigned long int)flags;
00535         } else if (param_no == 3) {
00536                 return fixup_spve_null(param, 1);
00537         }
00538         return 0;
00539 }
00540 
00546 static int fetchc_fixup(void** param, int param_no)
00547 {
00548         if (param_no == 1) {
00549                 return domain_fixup(param, 1);
00550         } else if (param_no == 2) {
00551                 return fixup_spve_null(param, 1);
00552         } else if (param_no == 3) {
00553                 return fixup_str_null(param, 1);
00554         }
00555         return 0;
00556 }
00557 
00558 
00559 static void mod_destroy(void)
00560 {
00561         free_contact_buf();
00562 }
00563 
00564 
00565 #include "../../data_lump.h"
00566 #include "../../ip_addr.h"
00567 #include "../../ut.h"
00568 
00569 static int add_sock_hdr(struct sip_msg* msg, char *name, char *foo)
00570 {
00571         struct socket_info* si;
00572         struct lump* anchor;
00573         str *hdr_name;
00574         str hdr;
00575         char *p;
00576 
00577         hdr_name = (str*)name;
00578         si = msg->rcv.bind_address;
00579 
00580         if (parse_headers( msg, HDR_EOH_F, 0) == -1) {
00581                 LM_ERR("failed to parse message\n");
00582                 goto error;
00583         }
00584 
00585         anchor = anchor_lump( msg, msg->unparsed-msg->buf, 0, 0);
00586         if (anchor==0) {
00587                 LM_ERR("can't get anchor\n");
00588                 goto error;
00589         }
00590 
00591         hdr.len = hdr_name->len + 2 + si->sock_str.len + CRLF_LEN;
00592         if ( (hdr.s=(char*)pkg_malloc(hdr.len))==0 ) {
00593                 LM_ERR("no more pkg mem\n");
00594                 goto error;
00595         }
00596 
00597         p = hdr.s;
00598         memcpy( p, hdr_name->s, hdr_name->len);
00599         p += hdr_name->len;
00600         *(p++) = ':';
00601         *(p++) = ' ';
00602 
00603         memcpy( p, si->sock_str.s, si->sock_str.len);
00604         p += si->sock_str.len;
00605 
00606         memcpy( p, CRLF, CRLF_LEN);
00607         p += CRLF_LEN;
00608 
00609         if ( p-hdr.s!=hdr.len ) {
00610                 LM_CRIT("buffer overflow (%d!=%d)\n", (int)(long)(p-hdr.s),hdr.len);
00611                 goto error1;
00612         }
00613 
00614         if (insert_new_lump_before( anchor, hdr.s, hdr.len, 0) == 0) {
00615                 LM_ERR("can't insert lump\n");
00616                 goto error1;
00617         }
00618 
00619         return 1;
00620 error1:
00621         pkg_free(hdr.s);
00622 error:
00623         return -1;
00624 }
00625 
00626 void default_expires_stats_update(str* gname, str* name){
00627         update_stat(default_expire_stat, cfg_get(registrar, registrar_cfg, default_expires));
00628 }
00629 
00630 void max_expires_stats_update(str* gname, str* name){
00631         update_stat(max_expires_stat, cfg_get(registrar, registrar_cfg, max_expires));
00632 }
00633 
00634 void default_expires_range_update(str* gname, str* name){
00635         update_stat(default_expire_range_stat, cfg_get(registrar, registrar_cfg, default_expires_range));
00636 }