00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 #include <stdio.h>
00061 #include "../../sr_module.h"
00062 #include "../../timer.h"
00063 #include "../../dprint.h"
00064 #include "../../error.h"
00065 #include "../../socket_info.h"
00066 #include "../../pvar.h"
00067 #include "../usrloc/ul_mod.h"
00068 #include "../sl/sl_api.h"
00069 #include "../../mod_fix.h"
00070
00071 #include "save.h"
00072 #include "lookup.h"
00073 #include "regpv.h"
00074 #include "reply.h"
00075 #include "reg_mod.h"
00076
00077
00078 MODULE_VERSION
00079
00080
00081
00082 static int mod_init(void);
00083 static int child_init(int);
00084 static void mod_destroy(void);
00085
00086 static int domain_fixup(void** param, int param_no);
00087 static int save_fixup(void** param, int param_no);
00088 static int unreg_fixup(void** param, int param_no);
00089 static int fetchc_fixup(void** param, int param_no);
00090
00091 static int add_sock_hdr(struct sip_msg* msg, char *str, char *foo);
00092
00093
00094 int default_expires = 3600;
00095 qvalue_t default_q = Q_UNSPECIFIED;
00096 int append_branches = 1;
00097 int case_sensitive = 0;
00098 int tcp_persistent_flag = -1;
00099 int min_expires = 60;
00100
00101 int max_expires = 0;
00102
00103 int max_contacts = 0;
00104 int retry_after = 0;
00105 int method_filtering = 0;
00106 int path_enabled = 0;
00107 int path_mode = PATH_MODE_STRICT;
00108
00109
00110
00111
00112 int path_use_params = 0;
00113
00114
00115 char *aor_avp_param =0;
00116
00117 unsigned short aor_avp_type=0;
00118 int_str aor_avp_name;
00119
00120
00121 char *reg_callid_avp_param = 0;
00122 unsigned short reg_callid_avp_type = 0;
00123 int_str reg_callid_avp_name;
00124
00125 char* rcv_avp_param = 0;
00126 unsigned short rcv_avp_type = 0;
00127 int_str rcv_avp_name;
00128
00129 int reg_use_domain = 0;
00130 char* realm_pref = "";
00131 str realm_prefix;
00132
00133 int sock_flag = -1;
00134 str sock_hdr_name = {0,0};
00135
00136 #define RCV_NAME "received"
00137 str rcv_param = str_init(RCV_NAME);
00138
00139 stat_var *accepted_registrations;
00140 stat_var *rejected_registrations;
00141 stat_var *max_expires_stat;
00142 stat_var *max_contacts_stat;
00143 stat_var *default_expire_stat;
00144
00145
00146 struct sl_binds slb;
00147
00148
00149
00150
00151 static pv_export_t mod_pvs[] = {
00152 { {"ulc", sizeof("ulc")-1}, PVT_OTHER, pv_get_ulc, pv_set_ulc,
00153 pv_parse_ulc_name, pv_parse_index, 0, 0 },
00154 { {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
00155 };
00156
00157
00158
00159
00160
00161 static cmd_export_t cmds[] = {
00162 {"save", (cmd_function)save, 1, save_fixup, 0,
00163 REQUEST_ROUTE | ONREPLY_ROUTE },
00164 {"save", (cmd_function)save, 2, save_fixup, 0,
00165 REQUEST_ROUTE | ONREPLY_ROUTE },
00166 {"lookup", (cmd_function)lookup, 1, domain_fixup, 0,
00167 REQUEST_ROUTE | FAILURE_ROUTE },
00168 {"registered", (cmd_function)registered, 1, domain_fixup, 0,
00169 REQUEST_ROUTE | FAILURE_ROUTE },
00170 {"add_sock_hdr", (cmd_function)add_sock_hdr, 1,fixup_str_null, 0,
00171 REQUEST_ROUTE },
00172 {"unregister", (cmd_function)unregister, 2, unreg_fixup, 0,
00173 REQUEST_ROUTE| FAILURE_ROUTE },
00174 {"reg_fetch_contacts", (cmd_function)pv_fetch_contacts, 3,
00175 fetchc_fixup, 0,
00176 REQUEST_ROUTE| FAILURE_ROUTE },
00177 {"reg_free_contacts", (cmd_function)pv_free_contacts, 1,
00178 fixup_str_null, 0,
00179 REQUEST_ROUTE| FAILURE_ROUTE },
00180 {0, 0, 0, 0, 0, 0}
00181 };
00182
00183
00184
00185
00186
00187 static param_export_t params[] = {
00188 {"default_expires", INT_PARAM, &default_expires },
00189 {"default_q", INT_PARAM, &default_q },
00190 {"append_branches", INT_PARAM, &append_branches },
00191 {"case_sensitive", INT_PARAM, &case_sensitive },
00192 {"tcp_persistent_flag",INT_PARAM, &tcp_persistent_flag },
00193 {"realm_prefix", STR_PARAM, &realm_pref },
00194 {"min_expires", INT_PARAM, &min_expires },
00195 {"max_expires", INT_PARAM, &max_expires },
00196 {"received_param", STR_PARAM, &rcv_param },
00197 {"received_avp", STR_PARAM, &rcv_avp_param },
00198 {"aor_avp", STR_PARAM, &aor_avp_param },
00199 {"reg_callid_avp", STR_PARAM, ®_callid_avp_param},
00200 {"max_contacts", INT_PARAM, &max_contacts },
00201 {"retry_after", INT_PARAM, &retry_after },
00202 {"sock_flag", INT_PARAM, &sock_flag },
00203 {"sock_hdr_name", STR_PARAM, &sock_hdr_name.s },
00204 {"method_filtering", INT_PARAM, &method_filtering },
00205 {"use_path", INT_PARAM, &path_enabled },
00206 {"path_mode", INT_PARAM, &path_mode },
00207 {"path_use_received", INT_PARAM, &path_use_params },
00208 {0, 0, 0}
00209 };
00210
00211
00212
00213 stat_export_t mod_stats[] = {
00214 {"max_expires", STAT_NO_RESET, &max_expires_stat },
00215 {"max_contacts", STAT_NO_RESET, &max_contacts_stat },
00216 {"default_expire", STAT_NO_RESET, &default_expire_stat },
00217 {"accepted_regs", 0, &accepted_registrations },
00218 {"rejected_regs", 0, &rejected_registrations },
00219 {0, 0, 0}
00220 };
00221
00222
00223
00224
00225
00226 struct module_exports exports = {
00227 "registrar",
00228 DEFAULT_DLFLAGS,
00229 cmds,
00230 params,
00231 mod_stats,
00232 0,
00233 mod_pvs,
00234 0,
00235 mod_init,
00236 0,
00237 mod_destroy,
00238 child_init,
00239 };
00240
00241
00242
00243
00244
00245 static int mod_init(void)
00246 {
00247 pv_spec_t avp_spec;
00248 str s;
00249 bind_usrloc_t bind_usrloc;
00250
00251
00252 if (load_sl_api(&slb)!=0) {
00253 LM_ERR("can't load SL API\n");
00254 return -1;
00255 }
00256
00257 realm_prefix.s = realm_pref;
00258 realm_prefix.len = strlen(realm_pref);
00259
00260 rcv_param.len = strlen(rcv_param.s);
00261
00262 if (rcv_avp_param && *rcv_avp_param) {
00263 s.s = rcv_avp_param; s.len = strlen(s.s);
00264 if (pv_parse_spec(&s, &avp_spec)==0
00265 || avp_spec.type!=PVT_AVP) {
00266 LM_ERR("malformed or non AVP %s AVP definition\n", rcv_avp_param);
00267 return -1;
00268 }
00269
00270 if(pv_get_avp_name(0, &avp_spec.pvp, &rcv_avp_name, &rcv_avp_type)!=0)
00271 {
00272 LM_ERR("[%s]- invalid AVP definition\n", rcv_avp_param);
00273 return -1;
00274 }
00275 } else {
00276 rcv_avp_name.n = 0;
00277 rcv_avp_type = 0;
00278 }
00279 if (aor_avp_param && *aor_avp_param) {
00280 s.s = aor_avp_param; s.len = strlen(s.s);
00281 if (pv_parse_spec(&s, &avp_spec)==0
00282 || avp_spec.type!=PVT_AVP) {
00283 LM_ERR("malformed or non AVP %s AVP definition\n", aor_avp_param);
00284 return -1;
00285 }
00286
00287 if(pv_get_avp_name(0, &avp_spec.pvp, &aor_avp_name, &aor_avp_type)!=0)
00288 {
00289 LM_ERR("[%s]- invalid AVP definition\n", aor_avp_param);
00290 return -1;
00291 }
00292 } else {
00293 aor_avp_name.n = 0;
00294 aor_avp_type = 0;
00295 }
00296
00297 if (reg_callid_avp_param && *reg_callid_avp_param) {
00298 s.s = reg_callid_avp_param; s.len = strlen(s.s);
00299 if (pv_parse_spec(&s, &avp_spec)==0
00300 || avp_spec.type!=PVT_AVP) {
00301 LM_ERR("malformed or non AVP %s AVP definition\n", reg_callid_avp_param);
00302 return -1;
00303 }
00304
00305 if(pv_get_avp_name(0, &avp_spec.pvp, ®_callid_avp_name, ®_callid_avp_type)!=0)
00306 {
00307 LM_ERR("[%s]- invalid AVP definition\n", reg_callid_avp_param);
00308 return -1;
00309 }
00310 } else {
00311 reg_callid_avp_name.n = 0;
00312 reg_callid_avp_type = 0;
00313 }
00314
00315 bind_usrloc = (bind_usrloc_t)find_export("ul_bind_usrloc", 1, 0);
00316 if (!bind_usrloc) {
00317 LM_ERR("can't bind usrloc\n");
00318 return -1;
00319 }
00320
00321
00322 if (default_q != Q_UNSPECIFIED) {
00323 if (default_q > MAX_Q) {
00324 LM_DBG("default_q = %d, lowering to MAX_Q: %d\n", default_q, MAX_Q);
00325 default_q = MAX_Q;
00326 } else if (default_q < MIN_Q) {
00327 LM_DBG("default_q = %d, raising to MIN_Q: %d\n", default_q, MIN_Q);
00328 default_q = MIN_Q;
00329 }
00330 }
00331
00332
00333 if (bind_usrloc(&ul) < 0) {
00334 return -1;
00335 }
00336
00337
00338
00339
00340 reg_use_domain = ul.use_domain;
00341
00342 if (sock_hdr_name.s) {
00343 sock_hdr_name.len = strlen(sock_hdr_name.s);
00344 if (sock_hdr_name.len==0 || sock_flag==-1) {
00345 LM_WARN("empty sock_hdr_name or sock_flag no set -> reseting\n");
00346 pkg_free(sock_hdr_name.s);
00347 sock_hdr_name.s = 0;
00348 sock_hdr_name.len = 0;
00349 sock_flag = -1;
00350 }
00351 } else if (sock_flag!=-1) {
00352 LM_WARN("sock_flag defined but no sock_hdr_name -> reseting flag\n");
00353 sock_flag = -1;
00354 }
00355
00356
00357 sock_flag = (sock_flag!=-1)?(1<<sock_flag):0;
00358 tcp_persistent_flag = (tcp_persistent_flag!=-1)?(1<<tcp_persistent_flag):0;
00359
00360 return 0;
00361 }
00362
00363
00364 static int child_init(int rank)
00365 {
00366 if (rank==1) {
00367
00368 update_stat( max_expires_stat, max_expires );
00369 update_stat( max_contacts_stat, max_contacts );
00370 update_stat( default_expire_stat, default_expires );
00371 }
00372
00373 return 0;
00374 }
00375
00376
00377
00378
00379
00380 static int domain_fixup(void** param, int param_no)
00381 {
00382 udomain_t* d;
00383
00384 if (param_no == 1) {
00385 if (ul.register_udomain((char*)*param, &d) < 0) {
00386 LM_ERR("failed to register domain\n");
00387 return E_UNSPEC;
00388 }
00389
00390 *param = (void*)d;
00391 }
00392 return 0;
00393 }
00394
00395
00396
00397
00398
00399 static int unreg_fixup(void** param, int param_no)
00400 {
00401 if (param_no == 1) {
00402 return domain_fixup(param, 1);
00403 } else if (param_no == 2) {
00404 return fixup_spve_null(param, 1);
00405 }
00406 return 0;
00407 }
00408
00409
00410
00411
00412
00413
00414 static int save_fixup(void** param, int param_no)
00415 {
00416 unsigned int flags;
00417 str s;
00418
00419 if (param_no == 1) {
00420 return domain_fixup(param,param_no);
00421 } else {
00422 s.s = (char*)*param;
00423 s.len = strlen(s.s);
00424 flags = 0;
00425 if ( (strno2int(&s, &flags )<0) || (flags>REG_SAVE_ALL_FL) ) {
00426 LM_ERR("bad flags <%s>\n", (char *)(*param));
00427 return E_CFG;
00428 }
00429 if (ul.db_mode==DB_ONLY && flags®_SAVE_MEM_FL) {
00430 LM_ERR("MEM flag set while using the DB_ONLY mode in USRLOC\n");
00431 return E_CFG;
00432 }
00433 pkg_free(*param);
00434 *param = (void*)(unsigned long int)flags;
00435 return 0;
00436 }
00437 }
00438
00439
00440
00441
00442
00443
00444 static int fetchc_fixup(void** param, int param_no)
00445 {
00446 if (param_no == 1) {
00447 return domain_fixup(param, 1);
00448 } else if (param_no == 2) {
00449 return fixup_spve_null(param, 1);
00450 } else if (param_no == 3) {
00451 return fixup_str_null(param, 1);
00452 }
00453 return 0;
00454 }
00455
00456
00457 static void mod_destroy(void)
00458 {
00459 free_contact_buf();
00460 }
00461
00462
00463 #include "../../data_lump.h"
00464 #include "../../ip_addr.h"
00465 #include "../../ut.h"
00466
00467 static int add_sock_hdr(struct sip_msg* msg, char *name, char *foo)
00468 {
00469 struct socket_info* si;
00470 struct lump* anchor;
00471 str *hdr_name;
00472 str hdr;
00473 char *p;
00474
00475 hdr_name = (str*)name;
00476 si = msg->rcv.bind_address;
00477
00478 if (parse_headers( msg, HDR_EOH_F, 0) == -1) {
00479 LM_ERR("failed to parse message\n");
00480 goto error;
00481 }
00482
00483 anchor = anchor_lump( msg, msg->unparsed-msg->buf, 0, 0);
00484 if (anchor==0) {
00485 LM_ERR("can't get anchor\n");
00486 goto error;
00487 }
00488
00489 hdr.len = hdr_name->len + 2 + si->sock_str.len + CRLF_LEN;
00490 if ( (hdr.s=(char*)pkg_malloc(hdr.len))==0 ) {
00491 LM_ERR("no more pkg mem\n");
00492 goto error;
00493 }
00494
00495 p = hdr.s;
00496 memcpy( p, hdr_name->s, hdr_name->len);
00497 p += hdr_name->len;
00498 *(p++) = ':';
00499 *(p++) = ' ';
00500
00501 memcpy( p, si->sock_str.s, si->sock_str.len);
00502 p += si->sock_str.len;
00503
00504 memcpy( p, CRLF, CRLF_LEN);
00505 p += CRLF_LEN;
00506
00507 if ( p-hdr.s!=hdr.len ) {
00508 LM_CRIT("buffer overflow (%d!=%d)\n", (int)(long)(p-hdr.s),hdr.len);
00509 goto error1;
00510 }
00511
00512 if (insert_new_lump_before( anchor, hdr.s, hdr.len, 0) == 0) {
00513 LM_ERR("can't insert lump\n");
00514 goto error1;
00515 }
00516
00517 return 1;
00518 error1:
00519 pkg_free(hdr.s);
00520 error:
00521 return -1;
00522 }
00523