1 /*
2  * Copyright (C) 2005 Voice Sistem SRL
3  *
4  * This file is part of Kamailio, a free SIP server.
5  *
6  * Kamailio is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * Kamailio is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  *
20  */
21 
22 /*!
23  * \file
24  * \brief Kamailio uac :: The SIP UA client module
25  * \ingroup uac
26  * Module: \ref uac
27  */
28 
29 /*! \defgroup uac The SIP UA Client module
30  *
31  */
32 
33 
34 #include <stdio.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 
39 #include "../../core/sr_module.h"
40 #include "../../core/dprint.h"
41 #include "../../core/error.h"
42 #include "../../core/pvar.h"
43 #include "../../core/pt.h"
44 #include "../../core/timer.h"
45 #include "../../core/mem/mem.h"
46 #include "../../core/parser/parse_from.h"
47 #include "../../modules/tm/tm_load.h"
48 #include "../../modules/tm/t_hooks.h"
49 #include "../../core/mod_fix.h"
50 #include "../../core/kemi.h"
51 #include "../../core/rpc.h"
52 #include "../../core/rpc_lookup.h"
53 #include "../../core/rand/kam_rand.h"
54 #include "../../core/cfg/cfg_struct.h"
55 #include "../dialog/dlg_load.h"
56 
57 #include "../rr/api.h"
58 
59 #include "replace.h"
60 #include "auth.h"
61 #include "uac_send.h"
62 #include "uac_reg.h"
63 #include "api.h"
64 
65 
66 MODULE_VERSION
67 
68 
69 /* local variable used for init */
70 static char* restore_mode_str = NULL;
71 static char* auth_username_avp = NULL;
72 static char* auth_realm_avp = NULL;
73 static char* auth_password_avp = NULL;
74 unsigned short restore_from_avp_type;
75 int_str restore_from_avp_name;
76 unsigned short restore_to_avp_type;
77 int_str restore_to_avp_name;
78 static int uac_restore_dlg = 0;
79 static int reg_active_param = 1;
80 
81 /* global param variables */
82 str rr_from_param = str_init("vsf");
83 str rr_to_param = str_init("vst");
84 str uac_passwd = str_init("");
85 str restore_from_avp = STR_NULL;
86 str restore_to_avp = STR_NULL;
87 int restore_mode = UAC_AUTO_RESTORE;
88 struct tm_binds uac_tmb;
89 struct rr_binds uac_rrb;
90 pv_spec_t auth_username_spec;
91 pv_spec_t auth_realm_spec;
92 pv_spec_t auth_password_spec;
93 str uac_default_socket = STR_NULL;
94 struct socket_info * uac_default_sockinfo = NULL;
95 
96 str uac_event_callback = STR_NULL;
97 
98 static int w_replace_from(struct sip_msg* msg, char* p1, char* p2);
99 static int w_restore_from(struct sip_msg* msg, char* p1, char* p2);
100 static int w_replace_to(struct sip_msg* msg, char* p1, char* p2);
101 static int w_restore_to(struct sip_msg* msg, char* p1, char* p2);
102 static int w_uac_auth(struct sip_msg* msg, char* str, char* str2);
103 static int w_uac_auth_mode(struct sip_msg* msg, char* pmode, char* str2);
104 static int w_uac_reg_lookup(struct sip_msg* msg, char* src, char* dst);
105 static int w_uac_reg_status(struct sip_msg* msg, char* src, char* dst);
106 static int w_uac_reg_request_to(struct sip_msg* msg, char* src, char* mode_s);
107 static int w_uac_reg_enable(struct sip_msg* msg, char* pfilter, char* pval);
108 static int w_uac_reg_disable(struct sip_msg* msg, char* pfilter, char* pval);
109 static int w_uac_reg_refresh(struct sip_msg* msg, char* pluuid, char* p2);
110 static int mod_init(void);
111 static void mod_destroy(void);
112 static int child_init(int rank);
113 
114 extern int reg_timer_interval;
115 extern int _uac_reg_gc_interval;
116 
117 static pv_export_t mod_pvs[] = {
118 	{ {"uac_req", sizeof("uac_req")-1}, PVT_OTHER, pv_get_uac_req, pv_set_uac_req,
119 		pv_parse_uac_req_name, 0, 0, 0 },
120 	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
121 };
122 
123 
124 /* Exported functions */
125 static cmd_export_t cmds[]={
126 	{"uac_replace_from",  (cmd_function)w_replace_from,  2, fixup_spve_spve, 0,
127 		REQUEST_ROUTE | BRANCH_ROUTE },
128 	{"uac_replace_from",  (cmd_function)w_replace_from,  1, fixup_spve_spve, 0,
129 		REQUEST_ROUTE | BRANCH_ROUTE },
130 	{"uac_restore_from",  (cmd_function)w_restore_from,  0,		  0, 0,
131 		REQUEST_ROUTE },
132 	{"uac_replace_to",  (cmd_function)w_replace_to,  2, fixup_spve_spve, 0,
133 		REQUEST_ROUTE | BRANCH_ROUTE },
134 	{"uac_replace_to",  (cmd_function)w_replace_to,  1, fixup_spve_spve, 0,
135 		REQUEST_ROUTE | BRANCH_ROUTE },
136 	{"uac_restore_to",  (cmd_function)w_restore_to,  0, 0, 0, REQUEST_ROUTE },
137 	{"uac_auth",	  (cmd_function)w_uac_auth,       0, 0, 0, FAILURE_ROUTE },
138 	{"uac_auth",      (cmd_function)w_uac_auth_mode,  1,
139 			fixup_igp_null, fixup_free_igp_null, FAILURE_ROUTE },
140 	{"uac_auth_mode", (cmd_function)w_uac_auth_mode,  1,
141 			fixup_igp_null, fixup_free_igp_null, FAILURE_ROUTE },
142 	{"uac_req_send",  (cmd_function)w_uac_req_send,   0, 0, 0, ANY_ROUTE},
143 	{"uac_reg_lookup",  (cmd_function)w_uac_reg_lookup,  2, fixup_spve_pvar,
144 		fixup_free_spve_pvar, ANY_ROUTE },
145 	{"uac_reg_status",  (cmd_function)w_uac_reg_status,  1, fixup_spve_null, 0,
146 		ANY_ROUTE },
147 	{"uac_reg_request_to",  (cmd_function)w_uac_reg_request_to,  2,
148 		fixup_spve_igp, fixup_free_spve_igp,
149 		REQUEST_ROUTE | FAILURE_ROUTE | BRANCH_ROUTE },
150 	{"uac_reg_enable",   (cmd_function)w_uac_reg_enable,   2, fixup_spve_spve,
151 		fixup_free_spve_spve, ANY_ROUTE },
152 	{"uac_reg_disable",  (cmd_function)w_uac_reg_disable,  2, fixup_spve_spve,
153 		fixup_free_spve_spve, ANY_ROUTE },
154 	{"uac_reg_refresh",  (cmd_function)w_uac_reg_refresh,  1, fixup_spve_null,
155 		fixup_free_spve_null, ANY_ROUTE },
156 	{"bind_uac", (cmd_function)bind_uac,		  1,  0, 0, 0},
157 	{0,0,0,0,0,0}
158 };
159 
160 
161 
162 /* Exported parameters */
163 static param_export_t params[] = {
164 	{"rr_from_store_param", PARAM_STR,			&rr_from_param       },
165 	{"rr_to_store_param",   PARAM_STR,			&rr_to_param       },
166 	{"restore_mode",	PARAM_STRING,			&restore_mode_str      },
167 	{"restore_dlg",	 	INT_PARAM,			&uac_restore_dlg       },
168 	{"restore_passwd",      PARAM_STR,			&uac_passwd	  },
169 	{"restore_from_avp",	PARAM_STR,			&restore_from_avp },
170 	{"restore_to_avp",	PARAM_STR,			&restore_to_avp },
171 	{"credential",		PARAM_STRING|USE_FUNC_PARAM,	(void*)&add_credential },
172 	{"auth_username_avp",	PARAM_STRING,			&auth_username_avp     },
173 	{"auth_realm_avp",	PARAM_STRING,			&auth_realm_avp	},
174 	{"auth_password_avp",	PARAM_STRING,			&auth_password_avp     },
175 	{"reg_db_url",		PARAM_STR,			&reg_db_url	  },
176 	{"reg_db_table",	PARAM_STR,			&reg_db_table	},
177 	{"reg_contact_addr",	PARAM_STR,			&reg_contact_addr    },
178 	{"reg_timer_interval",	INT_PARAM,			&reg_timer_interval	},
179 	{"reg_retry_interval",	INT_PARAM,	  		&reg_retry_interval    },
180 	{"reg_keep_callid",	INT_PARAM,			&reg_keep_callid       },
181 	{"reg_random_delay",	INT_PARAM,			&reg_random_delay      },
182 	{"reg_active",	INT_PARAM,			&reg_active_param      },
183 	{"reg_gc_interval",		INT_PARAM,	&_uac_reg_gc_interval	},
184 	{"default_socket",	PARAM_STR, &uac_default_socket},
185 	{"event_callback",	PARAM_STR,	&uac_event_callback},
186 	{0, 0, 0}
187 };
188 
189 
190 
191 struct module_exports exports= {
192 	"uac",           /* module name */
193 	DEFAULT_DLFLAGS, /* dlopen flags */
194 	cmds,            /* cmd exports */
195 	params,          /* param exports */
196 	0,               /* RPC method exports */
197 	mod_pvs,         /* pseudo-variables exports */
198 	0,               /* response handling function */
199 	mod_init,        /* module initialization function */
200 	child_init,      /* per-child init function */
201 	mod_destroy
202 };
203 
204 
parse_auth_avp(char * avp_spec,pv_spec_t * avp,char * txt)205 inline static int parse_auth_avp( char *avp_spec, pv_spec_t *avp, char *txt)
206 {
207 	str s;
208 	s.s = avp_spec; s.len = strlen(s.s);
209 	if (pv_parse_spec(&s, avp)==NULL) {
210 		LM_ERR("malformed or non AVP %s AVP definition\n",txt);
211 		return -1;
212 	}
213 	return 0;
214 }
215 
216 
mod_init(void)217 static int mod_init(void)
218 {
219 	pv_spec_t avp_spec;
220 	str host;
221 	int port, proto;
222 
223 	if (restore_mode_str && *restore_mode_str) {
224 		if (strcasecmp(restore_mode_str,"none")==0) {
225 			restore_mode = UAC_NO_RESTORE;
226 		} else if (strcasecmp(restore_mode_str,"manual")==0) {
227 			restore_mode = UAC_MANUAL_RESTORE;
228 		} else if (strcasecmp(restore_mode_str,"auto")==0) {
229 			restore_mode = UAC_AUTO_RESTORE;
230 		} else {
231 			LM_ERR("unsupported value '%s' for restore_mode\n",  restore_mode_str);
232 			goto error;
233 		}
234 	}
235 
236 	if ( (rr_from_param.len==0 || rr_to_param.len==0) && restore_mode!=UAC_NO_RESTORE)
237 	{
238 		LM_ERR("rr_store_param cannot be empty if FROM is restoreable\n");
239 		goto error;
240 	}
241 
242 	/* parse the auth AVP spesc, if any */
243 	if ( auth_username_avp || auth_password_avp || auth_realm_avp) {
244 		if (!auth_username_avp || !auth_password_avp || !auth_realm_avp) {
245 			LM_ERR("partial definition of auth AVP!");
246 			goto error;
247 		}
248 		if ( parse_auth_avp(auth_realm_avp, &auth_realm_spec, "realm")<0
249 				|| parse_auth_avp(auth_username_avp, &auth_username_spec, "username")<0
250 				|| parse_auth_avp(auth_password_avp, &auth_password_spec, "password")<0
251 		   ) {
252 			goto error;
253 		}
254 	} else {
255 		memset( &auth_realm_spec, 0, sizeof(pv_spec_t));
256 		memset( &auth_password_spec, 0, sizeof(pv_spec_t));
257 		memset( &auth_username_spec, 0, sizeof(pv_spec_t));
258 	}
259 
260 	/* load the TM API - FIXME it should be loaded only
261 	 * if NO_RESTORE and AUTH */
262 	if (load_tm_api(&uac_tmb)!=0) {
263 		LM_ERR("can't load TM API\n");
264 		goto error;
265 	}
266 
267 	if (restore_mode!=UAC_NO_RESTORE) {
268 		/* load the RR API */
269 		if (load_rr_api(&uac_rrb)!=0) {
270 			LM_ERR("can't load RR API\n");
271 			goto error;
272 		}
273 
274 
275 		if(restore_from_avp.s) {
276 
277 			if (pv_parse_spec(&restore_from_avp, &avp_spec)==0	|| avp_spec.type!=PVT_AVP) {
278 				LM_ERR("malformed or non AVP %.*s AVP definition\n", restore_from_avp.len, restore_from_avp.s);
279 				return -1;
280 			}
281 
282 			if(pv_get_avp_name(0, &avp_spec.pvp, &restore_from_avp_name, &restore_from_avp_type)!=0) {
283 				LM_ERR("[%.*s]- invalid AVP definition\n", restore_from_avp.len, restore_from_avp.s);
284 				return -1;
285 			}
286 
287 			restore_from_avp_type |= AVP_VAL_STR;
288 
289 		}
290 
291 		if(restore_to_avp.s) {
292 
293 			if (pv_parse_spec(&restore_to_avp, &avp_spec)==0	|| avp_spec.type!=PVT_AVP) {
294 				LM_ERR("malformed or non AVP %.*s AVP definition\n", restore_to_avp.len, restore_to_avp.s);
295 				return -1;
296 			}
297 
298 			if(pv_get_avp_name(0, &avp_spec.pvp, &restore_to_avp_name, &restore_to_avp_type)!=0) {
299 				LM_ERR("[%.*s]- invalid AVP definition\n", restore_to_avp.len, restore_to_avp.s);
300 				return -1;
301 			}
302 
303 			restore_to_avp_type |= AVP_VAL_STR;
304 
305 		}
306 
307 
308 		if (restore_mode==UAC_AUTO_RESTORE) {
309 			/* we need the append_fromtag on in RR */
310 
311 			if (uac_restore_dlg==0) {
312 				if (!uac_rrb.append_fromtag) {
313 					LM_ERR("'append_fromtag' RR param is not enabled!"
314 							" - required by AUTO restore mode\n");
315 					goto error;
316 				}
317 			} else {
318 				if (uac_init_dlg()!=0) {
319 					LM_ERR("failed to find dialog API - is dialog module loaded?\n");
320 					goto error;
321 				}
322 			}
323 
324 			/* get all requests doing loose route */
325 			if (uac_rrb.register_rrcb( rr_checker, 0)!=0) {
326 				LM_ERR("failed to install RR callback\n");
327 				goto error;
328 			}
329 		}
330 	}
331 
332 	if(reg_db_url.s && reg_db_url.len>=0)
333 	{
334 		if(!reg_contact_addr.s || reg_contact_addr.len<=0)
335 		{
336 			LM_ERR("contact address parameter not set\n");
337 			goto error;
338 		}
339 		if(reg_active_init(reg_active_param)<0) {
340 			LM_ERR("failed to init reg active mode\n");
341 			goto error;
342 		}
343 		if(reg_htable_size>14)
344 			reg_htable_size = 14;
345 		if(reg_htable_size<2)
346 			reg_htable_size = 2;
347 
348 		reg_htable_size = 1<<reg_htable_size;
349 		if(uac_reg_init_rpc()!=0)
350 		{
351 			LM_ERR("failed to register RPC commands\n");
352 			goto error;
353 		}
354 		if(uac_reg_init_ht(reg_htable_size)<0)
355 		{
356 			LM_ERR("failed to init reg htable\n");
357 			goto error;
358 		}
359 
360 		register_procs(1);
361 		/* add child to update local config framework structures */
362 		cfg_register_child(1);
363 	}
364 
365 	if(uac_default_socket.s && uac_default_socket.len > 0) {
366 		if(parse_phostport(
367 				   uac_default_socket.s, &host.s, &host.len, &port, &proto)
368 				!= 0) {
369 			LM_ERR("bad socket <%.*s>\n", uac_default_socket.len,
370 					uac_default_socket.s);
371 			return -1;
372 		}
373 		uac_default_sockinfo =
374 				grep_sock_info(&host, (unsigned short)port, proto);
375 		if(uac_default_sockinfo == 0) {
376 			LM_ERR("non-local socket <%.*s>\n", uac_default_socket.len,
377 					uac_default_socket.s);
378 			return -1;
379 		}
380 		LM_INFO("default uac socket set to <%.*s>\n",
381 				uac_default_socket.len, uac_default_socket.s);
382 	}
383 	init_from_replacer();
384 
385 	uac_req_init();
386 
387 	return 0;
388 error:
389 	return -1;
390 }
391 
child_init(int rank)392 static int child_init(int rank)
393 {
394 	int pid;
395 
396 	if (rank!=PROC_MAIN)
397 		return 0;
398 
399 	if(!reg_db_url.s || reg_db_url.len<=0)
400 		return 0;
401 
402 	pid=fork_process(PROC_TIMER, "TIMER UAC REG", 1);
403 	if (pid<0)
404 	{
405 		LM_ERR("failed to register timer routine as process\n");
406 		return -1;
407 	}
408 	if (pid==0){
409 		/* child */
410 		/* initialize the config framework */
411 		if (cfg_child_init())
412 			return -1;
413 
414 		uac_reg_load_db();
415 		LM_DBG("run initial uac registration routine\n");
416 		uac_reg_timer(0);
417 		for(;;){
418 			/* update the local config framework structures */
419 			cfg_update();
420 
421 			sleep(reg_timer_interval);
422 			uac_reg_timer(get_ticks());
423 		}
424 	}
425 	/* parent */
426 	return 0;
427 }
428 
mod_destroy(void)429 static void mod_destroy(void)
430 {
431 	destroy_credentials();
432 }
433 
434 
435 /************************** wrapper functions ******************************/
436 
ki_restore_from(struct sip_msg * msg)437 static int ki_restore_from(struct sip_msg *msg)
438 {
439 	/* safety checks - must be a request */
440 	if (msg->first_line.type!=SIP_REQUEST) {
441 		LM_ERR("called for something not request\n");
442 		return -1;
443 	}
444 
445 	return (restore_uri(msg,&rr_from_param,&restore_from_avp,1)==0)?1:-1;
446 }
447 
w_restore_from(struct sip_msg * msg,char * p1,char * p2)448 static int w_restore_from(struct sip_msg *msg, char *p1, char *p2)
449 {
450 	return ki_restore_from(msg);
451 }
452 
ki_replace_from(sip_msg_t * msg,str * pdsp,str * puri)453 int ki_replace_from(sip_msg_t *msg, str *pdsp, str *puri)
454 {
455 	str *uri = NULL;
456 	str *dsp = NULL;
457 
458 	dsp = pdsp;
459 	uri = (puri && puri->len) ? puri : NULL;
460 
461 	if(parse_from_header(msg) < 0) {
462 		LM_ERR("failed to find/parse FROM hdr\n");
463 		return -1;
464 	}
465 
466 	LM_DBG("dsp=%p (len=%d) , uri=%p (len=%d)\n", dsp, dsp ? dsp->len : 0, uri,
467 			uri ? uri->len : 0);
468 
469 	return (replace_uri(msg, dsp, uri, msg->from, &rr_from_param,
470 					&restore_from_avp, 1)==0)? 1 : -1;
471 }
472 
ki_replace_from_uri(sip_msg_t * msg,str * puri)473 static int ki_replace_from_uri(sip_msg_t* msg, str* puri)
474 {
475 	return ki_replace_from(msg, NULL, puri);
476 }
477 
w_replace_from(struct sip_msg * msg,char * p1,char * p2)478 int w_replace_from(struct sip_msg* msg, char* p1, char* p2)
479 {
480 	str uri_s;
481 	str dsp_s;
482 	str *dsp = NULL;
483 
484 	if (p2==NULL) {
485 		p2 = p1;
486 		p1 = NULL;
487 		dsp = NULL;
488 	}
489 
490 	/* p1 display , p2 uri */
491 	if(p1 != NULL) {
492 		if(fixup_get_svalue(msg, (gparam_t *)p1, &dsp_s) < 0) {
493 			LM_ERR("cannot get the display name value\n");
494 			return -1;
495 		}
496 		dsp = &dsp_s;
497 	}
498 
499 	/* compute the URI string; if empty string -> make it NULL */
500 	if(fixup_get_svalue(msg, (gparam_t *)p2, &uri_s) < 0) {
501 		LM_ERR("cannot get the uri value\n");
502 		return -1;
503 	}
504 	return ki_replace_from(msg, dsp, &uri_s);
505 }
506 
replace_from_api(sip_msg_t * msg,str * pd,str * pu)507 int replace_from_api(sip_msg_t *msg, str* pd, str* pu)
508 {
509 	str *uri;
510 	str *dsp;
511 	if (parse_from_header(msg)<0 ) {
512 		LM_ERR("failed to find/parse FROM hdr\n");
513 		return -1;
514 	}
515 
516 	uri = (pu!=NULL && pu->len>0)?pu:NULL;
517 	dsp = (pd!=NULL && pd->len>0)?pd:NULL;
518 
519 	LM_DBG("dsp=%p (len=%d) , uri=%p (len=%d)\n", dsp, dsp?dsp->len:0,
520 			uri, uri?uri->len:0);
521 
522 	return replace_uri(msg, dsp, uri, msg->from, &rr_from_param, &restore_from_avp, 1);
523 }
524 
ki_restore_to(struct sip_msg * msg)525 static int ki_restore_to(struct sip_msg *msg)
526 {
527 	/* safety checks - must be a request */
528 	if (msg->first_line.type!=SIP_REQUEST) {
529 		LM_ERR("called for something not request\n");
530 		return -1;
531 	}
532 
533 	return (restore_uri(msg,&rr_to_param,&restore_to_avp,0)==0)?1:-1;
534 }
535 
w_restore_to(struct sip_msg * msg,char * p1,char * p2)536 static int w_restore_to(struct sip_msg *msg, char *p1, char *p2)
537 {
538 	return ki_restore_to(msg);
539 }
540 
ki_replace_to(sip_msg_t * msg,str * pdsp,str * puri)541 static int ki_replace_to(sip_msg_t* msg, str* pdsp, str* puri)
542 {
543 	str *uri = NULL;
544 	str *dsp = NULL;
545 
546 	dsp = pdsp;
547 	uri = (puri && puri->len) ? puri : NULL;
548 
549 	/* parse TO hdr */
550 	if ( msg->to==0 && (parse_headers(msg,HDR_TO_F,0)!=0 || msg->to==0) ) {
551 		LM_ERR("failed to parse TO hdr\n");
552 		return -1;
553 	}
554 
555 	LM_DBG("dsp=%p (len=%d) , uri=%p (len=%d)\n",
556 			dsp, dsp?dsp->len:0, uri, uri?uri->len:0);
557 
558 	return (replace_uri(msg, dsp, uri, msg->to, &rr_to_param,
559 				&restore_to_avp, 0)==0)?1:-1;
560 }
561 
ki_replace_to_uri(sip_msg_t * msg,str * puri)562 static int ki_replace_to_uri(sip_msg_t* msg, str* puri)
563 {
564 	return ki_replace_to(msg, NULL, puri);
565 }
566 
w_replace_to(struct sip_msg * msg,char * p1,char * p2)567 static int w_replace_to(struct sip_msg* msg, char* p1, char* p2)
568 {
569 	str uri_s;
570 	str dsp_s;
571 	str *dsp = NULL;
572 
573 	if (p2==NULL) {
574 		p2 = p1;
575 		p1 = NULL;
576 		dsp = NULL;
577 	}
578 
579 	/* p1 display , p2 uri */
580 	if(p1 != NULL) {
581 		if(fixup_get_svalue(msg, (gparam_t *)p1, &dsp_s) < 0) {
582 			LM_ERR("cannot get the display name value\n");
583 			return -1;
584 		}
585 		dsp = &dsp_s;
586 	}
587 
588 	/* compute the URI string; if empty string -> make it NULL */
589 	if(fixup_get_svalue(msg, (gparam_t *)p2, &uri_s) < 0) {
590 		LM_ERR("cannot get the uri value\n");
591 		return -1;
592 	}
593 	return ki_replace_to(msg, dsp, &uri_s);
594 }
595 
596 
replace_to_api(sip_msg_t * msg,str * pd,str * pu)597 int replace_to_api(sip_msg_t *msg, str* pd, str* pu)
598 {
599 	str *uri;
600 	str *dsp;
601 	if ( msg->to==0 && (parse_headers(msg,HDR_TO_F,0)!=0 || msg->to==0) ) {
602 		LM_ERR("failed to find/parse TO hdr\n");
603 		return -1;
604 	}
605 
606 	uri = (pu!=NULL && pu->len>0)?pu:NULL;
607 	dsp = (pd!=NULL && pd->len>0)?pd:NULL;
608 
609 	LM_DBG("dsp=%p (len=%d) , uri=%p (len=%d)\n", dsp, dsp?dsp->len:0,
610 			uri, uri?uri->len:0);
611 
612 	return replace_uri(msg, dsp, uri, msg->to, &rr_to_param, &restore_to_avp, 0);
613 }
614 
615 
w_uac_auth(struct sip_msg * msg,char * str,char * str2)616 static int w_uac_auth(struct sip_msg* msg, char* str, char* str2)
617 {
618 	return (uac_auth(msg)==0)?1:-1;
619 }
620 
ki_uac_auth(struct sip_msg * msg)621 static int ki_uac_auth(struct sip_msg* msg)
622 {
623 	return (uac_auth(msg)==0)?1:-1;
624 }
625 
w_uac_auth_mode(struct sip_msg * msg,char * pmode,char * str2)626 static int w_uac_auth_mode(struct sip_msg* msg, char* pmode, char* str2)
627 {
628 	int imode = 0;
629 
630 	if(fixup_get_ivalue(msg, (gparam_t*)pmode, &imode)<0) {
631 		LM_ERR("failed to get the mode parameter\n");
632 		return -1;
633 	}
634 	return (uac_auth_mode(msg, imode)==0)?1:-1;
635 }
636 
ki_uac_auth_mode(sip_msg_t * msg,int mode)637 static int ki_uac_auth_mode(sip_msg_t* msg, int mode)
638 {
639 	return (uac_auth_mode(msg, mode)==0)?1:-1;
640 }
641 
w_uac_reg_lookup(struct sip_msg * msg,char * src,char * dst)642 static int w_uac_reg_lookup(struct sip_msg* msg, char* src, char* dst)
643 {
644 	pv_spec_t *dpv;
645 	str sval;
646 
647 	if(fixup_get_svalue(msg, (gparam_t*)src, &sval)<0) {
648 		LM_ERR("cannot get the uuid parameter\n");
649 		return -1;
650 	}
651 
652 	dpv = (pv_spec_t*)dst;
653 
654 	return uac_reg_lookup(msg, &sval, dpv, 0);
655 }
656 
ki_uac_reg_lookup(sip_msg_t * msg,str * userid,str * sdst)657 static int ki_uac_reg_lookup(sip_msg_t* msg, str* userid, str* sdst)
658 {
659 	pv_spec_t *dpv = NULL;
660 	dpv = pv_cache_get(sdst);
661 	if(dpv==NULL) {
662 		LM_ERR("cannot get pv spec for [%.*s]\n", sdst->len, sdst->s);
663 		return -1;
664 	}
665 	return uac_reg_lookup(msg, userid, dpv, 0);
666 }
667 
w_uac_reg_status(struct sip_msg * msg,char * src,char * p2)668 static int w_uac_reg_status(struct sip_msg* msg, char* src, char* p2)
669 {
670 	str sval;
671 
672 	if(fixup_get_svalue(msg, (gparam_t*)src, &sval)<0) {
673 		LM_ERR("cannot get the uuid parameter\n");
674 		return -1;
675 	}
676 
677 	return uac_reg_status(msg, &sval, 0);
678 }
679 
ki_uac_reg_status(sip_msg_t * msg,str * sruuid)680 static int ki_uac_reg_status(sip_msg_t *msg, str *sruuid)
681 {
682 	return uac_reg_status(msg, sruuid, 0);
683 }
684 
w_uac_reg_enable(struct sip_msg * msg,char * pfilter,char * pval)685 static int w_uac_reg_enable(struct sip_msg* msg, char* pfilter, char* pval)
686 {
687 	str sfilter;
688 	str sval;
689 
690 	if(fixup_get_svalue(msg, (gparam_t*)pfilter, &sfilter)<0) {
691 		LM_ERR("cannot get the filter parameter\n");
692 		return -1;
693 	}
694 	if(fixup_get_svalue(msg, (gparam_t*)pval, &sval)<0) {
695 		LM_ERR("cannot get the value parameter\n");
696 		return -1;
697 	}
698 	return uac_reg_enable(msg, &sfilter, &sval);
699 }
700 
w_uac_reg_disable(struct sip_msg * msg,char * pfilter,char * pval)701 static int w_uac_reg_disable(struct sip_msg* msg, char* pfilter, char* pval)
702 {
703 	str sfilter;
704 	str sval;
705 
706 	if(fixup_get_svalue(msg, (gparam_t*)pfilter, &sfilter)<0) {
707 		LM_ERR("cannot get the filter parameter\n");
708 		return -1;
709 	}
710 	if(fixup_get_svalue(msg, (gparam_t*)pval, &sval)<0) {
711 		LM_ERR("cannot get the value parameter\n");
712 		return -1;
713 	}
714 	return uac_reg_disable(msg, &sfilter, &sval);
715 }
716 
w_uac_reg_refresh(struct sip_msg * msg,char * pluuid,char * p2)717 static int w_uac_reg_refresh(struct sip_msg* msg, char* pluuid, char* p2)
718 {
719 	str sluuid;
720 
721 	if(fixup_get_svalue(msg, (gparam_t*)pluuid, &sluuid)<0) {
722 		LM_ERR("cannot get the local uuid parameter\n");
723 		return -1;
724 	}
725 	return uac_reg_refresh(msg, &sluuid);
726 }
727 
w_uac_reg_request_to(struct sip_msg * msg,char * src,char * pmode)728 static int w_uac_reg_request_to(struct sip_msg* msg, char* src, char* pmode)
729 {
730 	str sval;
731 	int imode;
732 
733 	if(fixup_get_svalue(msg, (gparam_t*)src, &sval)<0) {
734 		LM_ERR("cannot get the uuid parameter\n");
735 		return -1;
736 	}
737 	if(fixup_get_ivalue(msg, (gparam_t*)pmode, &imode)<0) {
738 		LM_ERR("cannot get the mode parameter\n");
739 		return -1;
740 	}
741 
742 	if (imode > (UACREG_REQTO_MASK_USER|UACREG_REQTO_MASK_AUTH)) {
743 		LM_ERR("invalid mode\n");
744 		return -1;
745 	}
746 
747 	return uac_reg_request_to(msg, &sval, (unsigned int)imode);
748 }
749 
ki_uac_reg_request_to(sip_msg_t * msg,str * userid,int imode)750 static int ki_uac_reg_request_to(sip_msg_t *msg, str *userid, int imode)
751 {
752 	if (imode > 1) {
753 		LM_ERR("invalid mode\n");
754 		return -1;
755 	}
756 
757 	return uac_reg_request_to(msg, userid, (unsigned int)imode);
758 }
759 
bind_uac(uac_api_t * uacb)760 int bind_uac(uac_api_t *uacb)
761 {
762 	if (uacb == NULL) {
763 		LM_WARN("bind_uac: Cannot load uac API into a NULL pointer\n");
764 		return -1;
765 	}
766 
767 	memset(uacb, 0, sizeof(uac_api_t));
768 	uacb->replace_from = replace_from_api;
769 	uacb->replace_to = replace_to_api;
770 	uacb->req_send = uac_req_send;
771 	return 0;
772 }
773 
774 /**
775  *
776  */
777 /* clang-format off */
778 static sr_kemi_t sr_kemi_uac_exports[] = {
779 	{ str_init("uac"), str_init("uac_auth"),
780 		SR_KEMIP_INT, ki_uac_auth,
781 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
782 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
783 	},
784 	{ str_init("uac"), str_init("uac_auth_mode"),
785 		SR_KEMIP_INT, ki_uac_auth_mode,
786 		{ SR_KEMIP_INT, SR_KEMIP_NONE, SR_KEMIP_NONE,
787 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
788 	},
789 	{ str_init("uac"), str_init("uac_req_send"),
790 		SR_KEMIP_INT, ki_uac_req_send,
791 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
792 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
793 	},
794 	{ str_init("uac"), str_init("uac_replace_from_uri"),
795 		SR_KEMIP_INT, ki_replace_from_uri,
796 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
797 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
798 	},
799 	{ str_init("uac"), str_init("uac_replace_from"),
800 		SR_KEMIP_INT, ki_replace_from,
801 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
802 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
803 	},
804 	{ str_init("uac"), str_init("uac_restore_from"),
805 		SR_KEMIP_INT, ki_restore_from,
806 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
807 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
808 	},
809 	{ str_init("uac"), str_init("uac_replace_to_uri"),
810 		SR_KEMIP_INT, ki_replace_to_uri,
811 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
812 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
813 	},
814 	{ str_init("uac"), str_init("uac_replace_to"),
815 		SR_KEMIP_INT, ki_replace_to,
816 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
817 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
818 	},
819 	{ str_init("uac"), str_init("uac_restore_to"),
820 		SR_KEMIP_INT, ki_restore_to,
821 		{ SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE,
822 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
823 	},
824 	{ str_init("uac"), str_init("uac_reg_lookup"),
825 		SR_KEMIP_INT, ki_uac_reg_lookup,
826 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
827 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
828 	},
829 	{ str_init("uac"), str_init("uac_reg_status"),
830 		SR_KEMIP_INT, ki_uac_reg_status,
831 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
832 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
833 	},
834 	{ str_init("uac"), str_init("uac_reg_request_to"),
835 		SR_KEMIP_INT, ki_uac_reg_request_to,
836 		{ SR_KEMIP_STR, SR_KEMIP_INT, SR_KEMIP_NONE,
837 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
838 	},
839 	{ str_init("uac"), str_init("uac_reg_enable"),
840 		SR_KEMIP_INT, uac_reg_enable,
841 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
842 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
843 	},
844 	{ str_init("uac"), str_init("uac_reg_disable"),
845 		SR_KEMIP_INT, uac_reg_disable,
846 		{ SR_KEMIP_STR, SR_KEMIP_STR, SR_KEMIP_NONE,
847 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
848 	},
849 	{ str_init("uac"), str_init("uac_reg_refresh"),
850 		SR_KEMIP_INT, uac_reg_refresh,
851 		{ SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE,
852 			SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE }
853 	},
854 
855 	{ {0, 0}, {0, 0}, 0, NULL, { 0, 0, 0, 0, 0, 0 } }
856 };
857 /* clang-format on */
858 
859 /**
860  *
861  */
mod_register(char * path,int * dlflags,void * p1,void * p2)862 int mod_register(char *path, int *dlflags, void *p1, void *p2)
863 {
864 	sr_kemi_modules_add(sr_kemi_uac_exports);
865 	return 0;
866 }
867