1 /*
2 * Copyright (C) 2012 Smile Communications, jason.penton@smilecoms.com
3 * Copyright (C) 2012 Smile Communications, richard.good@smilecoms.com
4 * Copyright (C) 2019 Aleksandar Yosifov
5 *
6 * The initial version of this code was written by Dragos Vingarzan
7 * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
8 * Fruanhofer Institute. It was and still is maintained in a separate
9 * branch of the original SER. We are therefore migrating it to
10 * Kamailio/SR and look forward to maintaining it from here on out.
11 * 2011/2012 Smile Communications, Pty. Ltd.
12 * ported/maintained/improved by
13 * Jason Penton (jason(dot)penton(at)smilecoms.com and
14 * Richard Good (richard(dot)good(at)smilecoms.com) as part of an
15 * effort to add full IMS support to Kamailio/SR using a new and
16 * improved architecture
17 *
18 * NB: Alot of this code was originally part of OpenIMSCore,
19 * FhG Fokus.
20 * Copyright (C) 2004-2006 FhG Fokus
21 * Thanks for great work! This is an effort to
22 * break apart the various CSCF functions into logically separate
23 * components. We hope this will drive wider use. We also feel
24 * that in this way the architecture is more complete and thereby easier
25 * to manage in the Kamailio/SR environment
26 *
27 * This file is part of Kamailio, a free SIP server.
28 *
29 * Kamailio is free software; you can redistribute it and/or modify
30 * it under the terms of the GNU General Public License as published by
31 * the Free Software Foundation; either version 2 of the License, or
32 * (at your option) any later version
33 *
34 * Kamailio is distributed in the hope that it will be useful,
35 * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
37 * GNU General Public License for more details.
38 *
39 * You should have received a copy of the GNU General Public License
40 * along with this program; if not, write to the Free Software
41 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
42 *
43 */
44
45
46 #include <stdio.h>
47 #include "../../core/data_lump.h"
48 #include "../../core/ip_addr.h"
49 #include "../../core/ut.h"
50 #include "../../core/sr_module.h"
51 #include "../../core/timer.h"
52 #include "../../core/dprint.h"
53 #include "../../core/error.h"
54 #include "../../core/socket_info.h"
55 #include "../../core/pvar.h"
56 #include "../ims_usrloc_pcscf/usrloc.h"
57 #include "../../core/counters.h"
58 #include "../../modules/sl/sl.h"
59 #include "../../core/mod_fix.h"
60 #include "../../core/cfg/cfg_struct.h"
61 #include "../ims_ipsec_pcscf/cmd.h"
62
63 /* Bindings to PUA */
64 #include "../pua/pua_bind.h"
65 #include "notify.h"
66
67 #include "async_reginfo.h"
68
69 #include "ims_registrar_pcscf_mod.h"
70 #include "save.h"
71 #include "service_routes.h"
72 MODULE_VERSION
73
74 usrloc_api_t ul; /**!< Structure containing pointers to usrloc functions*/
75 sl_api_t slb; /**!< SL API structure */
76 struct tm_binds tmb; /**!< TM API structure */
77 pua_api_t pua; /**!< PUA API structure */
78 ipsec_pcscf_api_t ipsec_pcscf; /**!< Structure containing pointers to ipsec pcscf functions*/
79
80 int publish_reginfo = 0;
81 int subscribe_to_reginfo = 0;
82 int subscription_expires = 3600;
83 int ignore_reg_state = 0;
84 /**!< ignore port checks between received port on message and registration received port.
85 * this is useful for example if you register with UDP but possibly send invite over TCP (message too big) */
86 int ignore_contact_rxport_check = 0;
87
88 time_t time_now;
89
90 str pcscf_uri = str_init("sip:pcscf.ims.smilecoms.com:4060");
91 str force_icscf_uri = str_init("");
92
93 unsigned int pending_reg_expires = 30; /**!< parameter for expiry time of a pending registration before receiving confirmation from SCSCF */
94
95 int is_registered_fallback2ip = 0;
96
97 int reginfo_queue_size_threshold = 0; /**Threshold for size of reginfo queue after which a warning is logged */
98
99
100 char* rcv_avp_param = 0;
101 unsigned short rcv_avp_type = 0;
102 int_str rcv_avp_name;
103
104 // static str orig_prefix = {"sip:orig@",9};
105
106 /*! \brief Module init & destroy function */
107 static int mod_init(void);
108 static int child_init(int);
109 static void mod_destroy(void);
110 static int w_save(struct sip_msg* _m, char* _d, char* _cflags);
111 static int w_save_pending(struct sip_msg* _m, char* _d, char* _cflags);
112
113 static int w_follows_service_routes(struct sip_msg* _m, char* _d, char* _foo);
114 static int w_force_service_routes(struct sip_msg* _m, char* _d, char* _foo);
115 static int w_is_registered(struct sip_msg* _m, char* _d, char* _foo);
116 static int w_reginfo_handle_notify(struct sip_msg* _m, char* _d, char* _foo);
117
118 static int w_assert_identity(struct sip_msg* _m, char* _d, char* _preferred_uri);
119 static int w_assert_called_identity(struct sip_msg* _m, char* _d, char* _foo);
120
121 static int w_unregister(struct sip_msg* _m, char* _d, char* _aor, char* _received_host, char* _received_port);
122
123 /*! \brief Fixup functions */
124 static int domain_fixup(void** param, int param_no);
125 static int save_fixup2(void** param, int param_no);
126 static int assert_identity_fixup(void ** param, int param_no);
127
128 /* Pseudo-Variables */
129 static int pv_get_asserted_identity_f(struct sip_msg *, pv_param_t *, pv_value_t *);
130 static int pv_get_registration_contact_f(struct sip_msg *, pv_param_t *, pv_value_t *);
131 static int unregister_fixup(void ** param, int param_no);
132
133 /**
134 * Update the time.
135 */
pcscf_act_time()136 inline void pcscf_act_time()
137 {
138 time_now=time(0);
139 }
140
141 /*! \brief
142 * Exported functions
143 */
144 static cmd_export_t cmds[] = {
145 {"pcscf_save", (cmd_function)w_save, 1, save_fixup2, 0,ONREPLY_ROUTE },
146 {"pcscf_save_pending", (cmd_function)w_save_pending, 1, save_fixup2, 0,REQUEST_ROUTE },
147 {"pcscf_follows_service_routes",(cmd_function)w_follows_service_routes, 1, save_fixup2, 0,REQUEST_ROUTE },
148 {"pcscf_force_service_routes", (cmd_function)w_force_service_routes, 1, save_fixup2, 0,REQUEST_ROUTE },
149 {"pcscf_is_registered", (cmd_function)w_is_registered, 1, save_fixup2, 0,REQUEST_ROUTE|ONREPLY_ROUTE },
150 {"pcscf_assert_identity", (cmd_function)w_assert_identity, 2, assert_identity_fixup, 0,REQUEST_ROUTE },
151 {"pcscf_assert_called_identity",(cmd_function)w_assert_called_identity, 1, assert_identity_fixup, 0,ONREPLY_ROUTE },
152 {"reginfo_handle_notify", (cmd_function)w_reginfo_handle_notify, 1, domain_fixup, 0,REQUEST_ROUTE},
153 {"pcscf_unregister", (cmd_function)w_unregister, 4, unregister_fixup, 0,ANY_ROUTE},
154 {0, 0, 0, 0, 0, 0}
155 };
156
157
158 /*! \brief
159 * Exported parameters
160 */
161 static param_export_t params[] = {
162 {"pcscf_uri", PARAM_STR, &pcscf_uri },
163 {"pending_reg_expires", INT_PARAM, &pending_reg_expires },
164 {"received_avp", PARAM_STR, &rcv_avp_param },
165 {"is_registered_fallback2ip", INT_PARAM, &is_registered_fallback2ip },
166 {"publish_reginfo", INT_PARAM, &publish_reginfo },
167 {"subscribe_to_reginfo", INT_PARAM, &subscribe_to_reginfo },
168 {"subscription_expires", INT_PARAM, &subscription_expires },
169 {"ignore_contact_rxport_check", INT_PARAM, &ignore_contact_rxport_check },
170 {"ignore_reg_state", INT_PARAM, &ignore_reg_state },
171 {"force_icscf_uri", PARAM_STR, &force_icscf_uri },
172 {"reginfo_queue_size_threshold", INT_PARAM, ®info_queue_size_threshold },
173 // {"store_profile_dereg", INT_PARAM, &store_data_on_dereg},
174 {0, 0, 0}
175 };
176
177
178
179 static pv_export_t mod_pvs[] = {
180 {{"pcscf_asserted_identity", (sizeof("pcscf_asserted_identity")-1)}, /* The first identity of the contact. */
181 PVT_OTHER, pv_get_asserted_identity_f, 0, 0, 0, 0, 0},
182 {{"pcscf_registration_contact", (sizeof("pcscf_registration_contact")-1)}, /* The contact used during REGISTER */
183 PVT_OTHER, pv_get_registration_contact_f, 0, 0, 0, 0, 0},
184 {{0, 0}, 0, 0, 0, 0, 0, 0, 0}
185 };
186
187 /*! \brief
188 * Module exports structure
189 */
190 struct module_exports exports = {
191 "ims_registrar_pcscf",
192 DEFAULT_DLFLAGS, /* dlopen flags */
193 cmds, /* Exported functions */
194 params, /* Exported parameters */
195 0, /* exported RPC methods */
196 mod_pvs, /* exported pseudo-variables */
197 0, /* response handling function */
198 mod_init, /* module initialization function */
199 child_init, /* Per-child init function */
200 mod_destroy /* destroy function */
201 };
202
fix_parameters()203 int fix_parameters() {
204 str s;
205 pv_spec_t avp_spec;
206
207 if (rcv_avp_param && *rcv_avp_param) {
208 s.s = rcv_avp_param; s.len = strlen(s.s);
209 if (pv_parse_spec(&s, &avp_spec)==0
210 || avp_spec.type!=PVT_AVP) {
211 LM_ERR("malformed or non AVP %s AVP definition\n", rcv_avp_param);
212 return -1;
213 }
214
215 if(pv_get_avp_name(0, &avp_spec.pvp, &rcv_avp_name, &rcv_avp_type)!=0)
216 {
217 LM_ERR("[%s]- invalid AVP definition\n", rcv_avp_param);
218 return -1;
219 }
220 } else {
221 rcv_avp_name.n = 0;
222 rcv_avp_type = 0;
223 }
224
225 return 1;
226 }
227
228 /*! \brief
229 * Initialize parent
230 */
mod_init(void)231 static int mod_init(void) {
232 bind_usrloc_t bind_usrloc;
233 bind_pua_t bind_pua;
234 bind_ipsec_pcscf_t bind_ipsec_pcscf;
235
236 /*register space for event processor*/
237 register_procs(1);
238
239 if (!fix_parameters()) goto error;
240
241 /* bind the SL API */
242 if (sl_load_api(&slb) != 0) {
243 LM_ERR("cannot bind to SL API\n");
244 return -1;
245 }
246 LM_DBG("Successfully bound to SL module\n");
247
248 /* load the TM API */
249 if (load_tm_api(&tmb) != 0) {
250 LM_ERR("can't load TM API\n");
251 return -1;
252 }
253 LM_DBG("Successfully bound to TM module\n");
254
255 bind_usrloc = (bind_usrloc_t) find_export("ul_bind_ims_usrloc_pcscf", 1, 0);
256 if (!bind_usrloc) {
257 LM_ERR("can't bind ims_usrloc_pcscf\n");
258 return -1;
259 }
260
261 if (bind_usrloc(&ul) < 0) {
262 return -1;
263 }
264 LM_DBG("Successfully bound to PCSCF Usrloc module\n");
265
266 bind_ipsec_pcscf = (bind_ipsec_pcscf_t) find_export("bind_ims_ipsec_pcscf", 1, 0);
267 if (!bind_ipsec_pcscf) {
268 LM_ERR("can't bind ims_ipsec_pcscf\n");
269 return -1;
270 }
271
272 if (bind_ipsec_pcscf(&ipsec_pcscf) < 0) {
273 return -1;
274 }
275 LM_INFO("Successfully bound to PCSCF IPSEC module\n");
276
277 if(subscribe_to_reginfo == 1){
278 /* Bind to PUA: */
279 bind_pua = (bind_pua_t) find_export("bind_pua", 1, 0);
280 if (!bind_pua) {
281 LM_ERR("Can't bind pua\n");
282 return -1;
283 }
284 if (bind_pua(&pua) < 0) {
285 LM_ERR("Can't bind pua\n");
286 return -1;
287 }
288 /* Check for Publish/Subscribe methods */
289 if (pua.send_publish == NULL) {
290 LM_ERR("Could not import send_publish\n");
291 return -1;
292 }
293 if (pua.send_subscribe == NULL) {
294 LM_ERR("Could not import send_subscribe\n");
295 return -1;
296 }
297 if (pua.get_subs_list == NULL) {
298 LM_ERR("Could not import get_subs_list\n");
299 return -1;
300 }
301 LM_DBG("Successfully bound to PUA module\n");
302
303 /*init cdb cb event list*/
304 if (!init_reginfo_event_list()) {
305 LM_ERR("unable to initialise reginfo_event_list\n");
306 return -1;
307 }
308 LM_DBG("Successfully initialised reginfo_event_list\n");
309 }
310
311 return 0;
312
313 error:
314 return -1;
315 }
316
mod_destroy(void)317 static void mod_destroy(void)
318 {
319
320 }
321
child_init(int rank)322 static int child_init(int rank)
323 {
324
325 LM_DBG("Initialization of module in child [%d] \n", rank);
326 if ((subscribe_to_reginfo == 1) && (rank == PROC_MAIN)) {
327 LM_DBG("Creating RegInfo Event Processor process\n");
328 int pid = fork_process(PROC_SIPINIT, "RegInfo Event Processor", 1);
329 if (pid < 0)
330 return -1; //error
331 if (pid == 0) {
332 if (cfg_child_init())
333 return -1; //error
334 reginfo_event_process();
335 }
336 }
337
338 if (rank == PROC_MAIN || rank == PROC_TCP_MAIN)
339 return 0;
340 if (rank == 1) {
341 /* init stats */
342 //TODO if parameters are modified via cfg framework do i change them?
343 //update_stat( max_expires_stat, default_registrar_cfg.max_expires ); update_stat( max_contacts_stat, default_registrar_cfg.max_contacts ); update_stat( default_expire_stat, default_registrar_cfg.default_expires );
344 }
345
346 /* don't do anything for main process and TCP manager process */
347 if (rank == PROC_MAIN || rank == PROC_TCP_MAIN)
348 return 0;
349
350 return 0;
351 }
352
353 /* fixups */
domain_fixup(void ** param,int param_no)354 static int domain_fixup(void** param, int param_no)
355 {
356 udomain_t* d;
357
358 if (param_no == 1) {
359 if (ul.register_udomain((char*)*param, &d) < 0) {
360 LM_ERR("failed to register domain\n");
361 return E_UNSPEC;
362 }
363 *param = (void*)d;
364 }
365 return 0;
366 }
367
368 /*! \brief
369 * Fixup for "save" function - both domain and flags
370 */
save_fixup2(void ** param,int param_no)371 static int save_fixup2(void** param, int param_no)
372 {
373 if (param_no == 1) {
374 return domain_fixup(param,param_no);
375 }
376 return 0;
377 }
378
379 /*! \brief
380 * Fixup for "assert_identity" function - both domain and URI to be asserted
381 */
assert_identity_fixup(void ** param,int param_no)382 static int assert_identity_fixup(void ** param, int param_no) {
383 if (param_no == 1) {
384 return domain_fixup(param,param_no);
385 }
386 if (param_no == 2) {
387 pv_elem_t *model=NULL;
388 str s;
389
390 /* convert to str */
391 s.s = (char*)*param;
392 s.len = strlen(s.s);
393
394 model = NULL;
395 if(s.len==0) {
396 LM_ERR("no param!\n");
397 return E_CFG;
398 }
399 if(pv_parse_format(&s, &model)<0 || model==NULL) {
400 LM_ERR("wrong format [%s]!\n", s.s);
401 return E_CFG;
402 }
403 *param = (void*)model;
404 return 0;
405 }
406 return E_CFG;
407 }
408
409 /*! \brief
410 * Wrapper to save(location)
411 */
w_save(struct sip_msg * _m,char * _d,char * _cflags)412 static int w_save(struct sip_msg* _m, char* _d, char* _cflags)
413 {
414 return save(_m, (udomain_t*)_d, ((int)(unsigned long)_cflags));
415 }
416
w_save_pending(struct sip_msg * _m,char * _d,char * _cflags)417 static int w_save_pending(struct sip_msg* _m, char* _d, char* _cflags)
418 {
419 return save_pending(_m, (udomain_t*)_d);
420 }
421
w_follows_service_routes(struct sip_msg * _m,char * _d,char * _foo)422 static int w_follows_service_routes(struct sip_msg* _m, char* _d, char* _foo)
423 {
424 return check_service_routes(_m, (udomain_t*)_d);
425 }
426
w_force_service_routes(struct sip_msg * _m,char * _d,char * _foo)427 static int w_force_service_routes(struct sip_msg* _m, char* _d, char* _foo)
428 {
429 return force_service_routes(_m, (udomain_t*)_d);
430 }
431
w_is_registered(struct sip_msg * _m,char * _d,char * _foo)432 static int w_is_registered(struct sip_msg* _m, char* _d, char* _foo)
433 {
434 return is_registered(_m, (udomain_t*)_d);
435 }
436
w_reginfo_handle_notify(struct sip_msg * _m,char * _d,char * _foo)437 static int w_reginfo_handle_notify(struct sip_msg* _m, char* _d, char* _foo)
438 {
439 return reginfo_handle_notify(_m, _d, _foo);
440 }
441
w_assert_identity(struct sip_msg * _m,char * _d,char * _preferred_uri)442 static int w_assert_identity(struct sip_msg* _m, char* _d, char* _preferred_uri) {
443 pv_elem_t *model;
444 str identity;
445
446 if(_preferred_uri == NULL) {
447 LM_ERR("error - bad parameters\n");
448 return -1;
449 }
450
451 model = (pv_elem_t*)_preferred_uri;
452 if (pv_printf_s(_m, model, &identity)<0) {
453 LM_ERR("error - cannot print the format\n");
454 return -1;
455 }
456
457 return assert_identity( _m, (udomain_t*)_d, identity);
458 }
459
w_assert_called_identity(struct sip_msg * _m,char * _d,char * _foo)460 static int w_assert_called_identity(struct sip_msg* _m, char* _d, char* _foo) {
461 return assert_called_identity( _m, (udomain_t*)_d);
462 }
463
464 /*
465 * Get the asserted Identity for the current user
466 */
467 static int
pv_get_asserted_identity_f(struct sip_msg * msg,pv_param_t * param,pv_value_t * res)468 pv_get_asserted_identity_f(struct sip_msg *msg, pv_param_t *param,
469 pv_value_t *res)
470 {
471 str * ret_val = get_asserted_identity(msg);
472 if (ret_val != NULL) return pv_get_strval(msg, param, res, ret_val);
473 else return -1;
474 }
475
476
477 /*
478 * Get the asserted Identity for the current user
479 */
480 static int
pv_get_registration_contact_f(struct sip_msg * msg,pv_param_t * param,pv_value_t * res)481 pv_get_registration_contact_f(struct sip_msg *msg, pv_param_t *param,
482 pv_value_t *res)
483 {
484 str * ret_val = get_registration_contact(msg);
485 if (ret_val != NULL) return pv_get_strval(msg, param, res, ret_val);
486 else return -1;
487 }
488
489
490 /*! \brief
491 * Fixup for "assert_identity" function - both domain and URI to be asserted
492 */
unregister_fixup(void ** param,int param_no)493 static int unregister_fixup(void ** param, int param_no) {
494 if (param_no == 1) {
495 return domain_fixup(param,param_no);
496 } else {
497 pv_elem_t *model=NULL;
498 str s;
499
500 /* convert to str */
501 s.s = (char*)*param;
502 s.len = strlen(s.s);
503
504 model = NULL;
505 if(s.len==0) {
506 LM_ERR("no param!\n");
507 return E_CFG;
508 }
509 if(pv_parse_format(&s, &model)<0 || model==NULL) {
510 LM_ERR("wrong format [%s]!\n", s.s);
511 return E_CFG;
512 }
513 *param = (void*)model;
514 return 0;
515 }
516 return E_CFG;
517 }
518
519
w_unregister(struct sip_msg * _m,char * _d,char * _aor,char * _received_host,char * _received_port)520 static int w_unregister(struct sip_msg* _m, char* _d, char* _aor, char* _received_host, char* _received_port) {
521 pv_elem_t *model;
522 str aor;
523 str received_host;
524 str received_port;
525 int port = 0;
526
527 if ((_aor == NULL) || (_received_host == NULL) || (_received_port == NULL)) {
528 LM_ERR("error - bad parameters\n");
529 return -1;
530 }
531
532 model = (pv_elem_t*)_aor;
533 if (pv_printf_s(_m, model, &aor)<0) {
534 LM_ERR("error - cannot print the format\n");
535 return -1;
536 }
537 LM_DBG("URI: %.*s\n", aor.len, aor.s);
538
539 model = (pv_elem_t*)_received_host;
540 if (pv_printf_s(_m, model, &received_host)<0) {
541 LM_ERR("error - cannot print the format\n");
542 return -1;
543 }
544 LM_DBG("Received-Host: %.*s\n", received_host.len, received_host.s);
545
546 model = (pv_elem_t*)_received_port;
547 if (pv_printf_s(_m, model, &received_port)<0) {
548 LM_ERR("error - cannot print the format\n");
549 return -1;
550 }
551 LM_DBG("Received-Port: %.*s\n", received_port.len, received_port.s);
552 if (str2sint(&received_port, &port) != 0) {
553 LM_ERR("error - cannot convert %.*s to an int!\n", received_port.len, received_port.s);
554 return -1;
555 }
556
557 return pcscf_unregister((udomain_t*)_d, &aor, &received_host, port);
558 }
559
560