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, ®_db_url },
176 {"reg_db_table", PARAM_STR, ®_db_table },
177 {"reg_contact_addr", PARAM_STR, ®_contact_addr },
178 {"reg_timer_interval", INT_PARAM, ®_timer_interval },
179 {"reg_retry_interval", INT_PARAM, ®_retry_interval },
180 {"reg_keep_callid", INT_PARAM, ®_keep_callid },
181 {"reg_random_delay", INT_PARAM, ®_random_delay },
182 {"reg_active", INT_PARAM, ®_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