1 /**
2 * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
3 *
4 * This file is part of kamailio, a free SIP server.
5 *
6 * Kamailio is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (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 * \file
23 * \brief Kamailio uac :: The SIP UA registration client module
24 * \ingroup uac
25 * Module: \ref uac
26 */
27
28 #include <time.h>
29
30 #include "../../core/dprint.h"
31 #include "../../core/timer.h"
32
33 #include "../../core/mem/shm_mem.h"
34 #include "../../lib/srdb1/db.h"
35 #include "../../core/ut.h"
36 #include "../../core/trim.h"
37 #include "../../core/hashes.h"
38 #include "../../core/locking.h"
39 #include "../../core/parser/parse_uri.h"
40 #include "../../core/parser/parse_from.h"
41 #include "../../core/parser/parse_to.h"
42 #include "../../core/parser/parse_expires.h"
43 #include "../../core/parser/contact/parse_contact.h"
44 #include "../../core/rpc.h"
45 #include "../../core/rpc_lookup.h"
46 #include "../../core/rand/kam_rand.h"
47
48 #include "../../modules/tm/tm_load.h"
49
50 #include "auth.h"
51 #include "auth_hdr.h"
52 #include "uac_reg.h"
53
54 #define UAC_REG_DISABLED (1<<0) /* registration disabled */
55 #define UAC_REG_ONGOING (1<<1) /* registration on progress */
56 #define UAC_REG_ONLINE (1<<2) /* registered */
57 #define UAC_REG_AUTHSENT (1<<3) /* registration with auth in progress */
58 #define UAC_REG_INIT (1<<4) /* registration initialized */
59
60 #define MAX_UACH_SIZE 2048
61 #define UAC_REG_TM_CALLID_SIZE 90
62
63 int _uac_reg_gc_interval = 150;
64
65 typedef struct _reg_uac
66 {
67 unsigned int h_uuid;
68 unsigned int h_user;
69 str l_uuid;
70 str l_username;
71 str l_domain;
72 str r_username;
73 str r_domain;
74 str realm;
75 str auth_proxy;
76 str auth_username;
77 str auth_password;
78 str auth_ha1;
79 str callid;
80 str socket;
81 unsigned int cseq;
82 unsigned int flags;
83 unsigned int expires;
84 time_t timer_expires;
85 unsigned int reg_delay;
86 time_t reg_init;
87 gen_lock_t *lock;
88 } reg_uac_t;
89
90 typedef struct _reg_item
91 {
92 reg_uac_t *r;
93 struct _reg_item *next;
94 } reg_item_t;
95
96
97 typedef struct _reg_entry
98 {
99 unsigned int isize;
100 unsigned int usize;
101 reg_item_t *byuser;
102 reg_item_t *byuuid;
103 gen_lock_t lock;
104 } reg_entry_t;
105
106 typedef struct _reg_ht
107 {
108 unsigned int htsize;
109 time_t stime;
110 reg_entry_t *entries;
111 } reg_ht_t;
112
113 static reg_ht_t *_reg_htable = NULL;
114 static reg_ht_t *_reg_htable_gc = NULL;
115 static gen_lock_t *_reg_htable_gc_lock = NULL;
116
117 int reg_use_domain = 0;
118 int reg_timer_interval = 90;
119 int reg_retry_interval = 0;
120 int reg_htable_size = 4;
121 int reg_fetch_rows = 1000;
122 int reg_keep_callid = 0;
123 int reg_random_delay = 0;
124 int *reg_active = NULL;
125 str reg_contact_addr = STR_NULL;
126 str reg_db_url = STR_NULL;
127 str reg_db_table = str_init("uacreg");
128
129 str l_uuid_column = str_init("l_uuid");
130 str l_username_column = str_init("l_username");
131 str l_domain_column = str_init("l_domain");
132 str r_username_column = str_init("r_username");
133 str r_domain_column = str_init("r_domain");
134 str realm_column = str_init("realm");
135 str auth_username_column = str_init("auth_username");
136 str auth_password_column = str_init("auth_password");
137 str auth_ha1_column = str_init("auth_ha1");
138 str auth_proxy_column = str_init("auth_proxy");
139 str expires_column = str_init("expires");
140 str flags_column = str_init("flags");
141 str reg_delay_column = str_init("reg_delay");
142 str socket_column = str_init("socket");
143
144 str str_empty = str_init("");
145
146
147 extern struct tm_binds uac_tmb;
148 extern pv_spec_t auth_username_spec;
149 extern pv_spec_t auth_realm_spec;
150 extern pv_spec_t auth_password_spec;
151
152 counter_handle_t regtotal; /* Total number of registrations in memory */
153 counter_handle_t regactive; /* Active registrations - 200 OK */
154 counter_handle_t regdisabled; /* Disabled registrations */
155
156 /* Init reg active mode */
reg_active_init(int mode)157 int reg_active_init(int mode)
158 {
159 if(reg_active!=NULL) {
160 /* already allocated */
161 *reg_active = mode;
162 return 0;
163 }
164 reg_active = (int*)shm_malloc(sizeof(int));
165 if(reg_active==NULL) {
166 SHM_MEM_ERROR;
167 return -1;
168 }
169 *reg_active = mode;
170 return 0;
171 }
172
173 /* Init counters */
uac_reg_counter_init()174 static void uac_reg_counter_init()
175 {
176 LM_DBG("*** Initializing UAC reg counters\n");
177 counter_register(®total, "uac", "regtotal", 0, 0, 0, "Total number of registration accounts in memory", 0);
178 counter_register(®active, "uac", "regactive", 0, 0, 0, "Number of successfully registered accounts (200 OK)", 0);
179 counter_register(®disabled, "uac", "regdisabled", 0, 0, 0, "Counter of failed registrations (not 200 OK)", 0);
180 }
181
182
183 /**
184 * Init the in-memory registration database in hash table
185 */
uac_reg_init_ht(unsigned int sz)186 int uac_reg_init_ht(unsigned int sz)
187 {
188 int i;
189
190 _reg_htable_gc_lock = (gen_lock_t*)shm_malloc(sizeof(gen_lock_t));
191 if(_reg_htable_gc_lock == NULL)
192 {
193 SHM_MEM_ERROR;
194 return -1;
195 }
196 if(lock_init(_reg_htable_gc_lock)==0)
197 {
198 LM_ERR("cannot init global lock\n");
199 shm_free((void*)_reg_htable_gc_lock);
200 return -1;
201 }
202 _reg_htable_gc = (reg_ht_t*)shm_malloc(sizeof(reg_ht_t));
203 if(_reg_htable_gc==NULL)
204 {
205 SHM_MEM_ERROR;
206 lock_destroy(_reg_htable_gc_lock);
207 shm_free((void*)_reg_htable_gc_lock);
208 return -1;
209 }
210 memset(_reg_htable_gc, 0, sizeof(reg_ht_t));
211 _reg_htable_gc->htsize = sz;
212
213 _reg_htable_gc->entries =
214 (reg_entry_t*)shm_malloc(_reg_htable_gc->htsize*sizeof(reg_entry_t));
215 if(_reg_htable_gc->entries==NULL)
216 {
217 SHM_MEM_ERROR;
218 shm_free(_reg_htable_gc);
219 lock_destroy(_reg_htable_gc_lock);
220 shm_free((void*)_reg_htable_gc_lock);
221 return -1;
222 }
223 memset(_reg_htable_gc->entries, 0, _reg_htable_gc->htsize*sizeof(reg_entry_t));
224
225
226 _reg_htable = (reg_ht_t*)shm_malloc(sizeof(reg_ht_t));
227 if(_reg_htable==NULL)
228 {
229 SHM_MEM_ERROR;
230 shm_free(_reg_htable_gc->entries);
231 shm_free(_reg_htable_gc);
232 lock_destroy(_reg_htable_gc_lock);
233 shm_free((void*)_reg_htable_gc_lock);
234 return -1;
235 }
236 memset(_reg_htable, 0, sizeof(reg_ht_t));
237 _reg_htable->htsize = sz;
238
239 _reg_htable->entries =
240 (reg_entry_t*)shm_malloc(_reg_htable->htsize*sizeof(reg_entry_t));
241 if(_reg_htable->entries==NULL)
242 {
243 SHM_MEM_ERROR;
244 shm_free(_reg_htable_gc->entries);
245 shm_free(_reg_htable_gc);
246 shm_free(_reg_htable);
247 lock_destroy(_reg_htable_gc_lock);
248 shm_free((void*)_reg_htable_gc_lock);
249 return -1;
250 }
251 memset(_reg_htable->entries, 0, _reg_htable->htsize*sizeof(reg_entry_t));
252 for(i=0; i<_reg_htable->htsize; i++)
253 {
254 if(lock_init(&_reg_htable->entries[i].lock)==0)
255 {
256 LM_ERR("cannot initialize lock[%d] n", i);
257 i--;
258 while(i>=0)
259 {
260 lock_destroy(&_reg_htable->entries[i].lock);
261 i--;
262 }
263 shm_free(_reg_htable->entries);
264 shm_free(_reg_htable);
265 shm_free(_reg_htable_gc->entries);
266 shm_free(_reg_htable_gc);
267 lock_destroy(_reg_htable_gc_lock);
268 shm_free((void*)_reg_htable_gc_lock);
269 return -1;
270 }
271 }
272
273 /* Initialize uac reg counters */
274 uac_reg_counter_init();
275
276 return 0;
277 }
278
279 /**
280 *
281 */
uac_reg_free_ht(void)282 int uac_reg_free_ht(void)
283 {
284 int i;
285 reg_item_t *it = NULL;
286 reg_item_t *it0 = NULL;
287
288 if(_reg_htable_gc_lock != NULL)
289 {
290 lock_destroy(_reg_htable_gc_lock);
291 shm_free((void*)_reg_htable_gc_lock);
292 _reg_htable_gc_lock = NULL;
293 }
294 if(_reg_htable_gc!=NULL)
295 {
296 for(i=0; i<_reg_htable_gc->htsize; i++)
297 {
298 it = _reg_htable_gc->entries[i].byuuid;
299 while(it)
300 {
301 it0 = it;
302 it = it->next;
303 shm_free(it0);
304 }
305 it = _reg_htable_gc->entries[i].byuser;
306 while(it)
307 {
308 it0 = it;
309 it = it->next;
310 shm_free(it0->r);
311 shm_free(it0);
312 }
313 }
314 shm_free(_reg_htable_gc->entries);
315 shm_free(_reg_htable_gc);
316 _reg_htable_gc = NULL;
317 }
318
319 if(_reg_htable==NULL)
320 {
321 LM_DBG("no hash table\n");
322 return -1;
323 }
324 for(i=0; i<_reg_htable->htsize; i++)
325 {
326 lock_get(&_reg_htable->entries[i].lock);
327 /* free entries */
328 it = _reg_htable->entries[i].byuuid;
329 while(it)
330 {
331 it0 = it;
332 it = it->next;
333 shm_free(it0);
334 }
335 it = _reg_htable->entries[i].byuser;
336 while(it)
337 {
338 it0 = it;
339 it = it->next;
340 shm_free(it0->r);
341 shm_free(it0);
342 }
343 lock_destroy(&_reg_htable->entries[i].lock);
344 }
345 shm_free(_reg_htable->entries);
346 shm_free(_reg_htable);
347 _reg_htable = NULL;
348 return 0;
349 }
350
351 /**
352 *
353 */
uac_reg_reset_ht_gc(void)354 int uac_reg_reset_ht_gc(void)
355 {
356 int i;
357 reg_item_t *it = NULL;
358 reg_item_t *it0 = NULL;
359
360 if(_reg_htable_gc==NULL)
361 {
362 LM_DBG("no hash table\n");
363 return -1;
364 }
365 for(i=0; i<_reg_htable_gc->htsize; i++)
366 {
367 /* free entries */
368 it = _reg_htable_gc->entries[i].byuuid;
369 while(it)
370 {
371 it0 = it;
372 it = it->next;
373 shm_free(it0);
374 }
375 _reg_htable_gc->entries[i].byuuid = NULL;
376 _reg_htable_gc->entries[i].isize=0;
377 it = _reg_htable_gc->entries[i].byuser;
378 while(it)
379 {
380 it0 = it;
381 it = it->next;
382 shm_free(it0->r);
383 shm_free(it0);
384 }
385 _reg_htable_gc->entries[i].byuser = NULL;
386 _reg_htable_gc->entries[i].usize = 0;
387 }
388 /* Reset all counters */
389 counter_reset(regtotal);
390 counter_reset(regactive);
391 counter_reset(regdisabled);
392 return 0;
393 }
394
395 /**
396 *
397 */
uac_reg_ht_shift(void)398 int uac_reg_ht_shift(void)
399 {
400 time_t tn;
401 int i;
402
403 if(_reg_htable==NULL || _reg_htable_gc==NULL)
404 {
405 LM_ERR("data struct invalid\n");
406 return -1;
407 }
408 tn = time(NULL);
409
410 lock_get(_reg_htable_gc_lock);
411 if(_reg_htable_gc->stime > tn - _uac_reg_gc_interval) {
412 lock_release(_reg_htable_gc_lock);
413 LM_ERR("shifting in-memory table is not possible in less than %d secs\n",
414 _uac_reg_gc_interval);
415 return -1;
416 }
417 uac_reg_reset_ht_gc();
418 for(i=0; i<_reg_htable->htsize; i++)
419 {
420 /* shift entries */
421 _reg_htable_gc->entries[i].byuuid = _reg_htable->entries[i].byuuid;
422 _reg_htable_gc->entries[i].byuser = _reg_htable->entries[i].byuser;
423 _reg_htable_gc->stime = time(NULL);
424
425 /* reset active table entries */
426 _reg_htable->entries[i].byuuid = NULL;
427 _reg_htable->entries[i].isize=0;
428 _reg_htable->entries[i].byuser = NULL;
429 _reg_htable->entries[i].usize = 0;
430 }
431 lock_release(_reg_htable_gc_lock);
432 return 0;
433 }
434
435 #define reg_compute_hash(_s) get_hash1_raw((_s)->s,(_s)->len)
436 #define reg_get_entry(_h,_size) ((_h)&((_size)-1))
437
438 /**
439 *
440 */
reg_ht_add_byuuid(reg_uac_t * reg)441 int reg_ht_add_byuuid(reg_uac_t *reg)
442 {
443 unsigned int slot;
444 reg_item_t *ri = NULL;
445
446 if(_reg_htable==NULL)
447 {
448 LM_ERR("reg hash table not initialized\n");
449 return -1;
450 }
451
452 ri = (reg_item_t*)shm_malloc(sizeof(reg_item_t));
453 if(ri==NULL)
454 {
455 SHM_MEM_ERROR;
456 return -1;
457 }
458 memset(ri, 0, sizeof(reg_item_t));
459 slot = reg_get_entry(reg->h_uuid, _reg_htable->htsize);
460 ri->r = reg;
461 lock_get(&_reg_htable->entries[slot].lock);
462 ri->next = _reg_htable->entries[slot].byuuid;
463 _reg_htable->entries[slot].byuuid = ri;
464 _reg_htable->entries[slot].isize++;
465 lock_release(&_reg_htable->entries[slot].lock);
466 return 0;
467 }
468
469 /**
470 *
471 */
reg_ht_add_byuser(reg_uac_t * reg)472 int reg_ht_add_byuser(reg_uac_t *reg)
473 {
474 unsigned int slot;
475 reg_item_t *ri = NULL;
476
477 if(_reg_htable==NULL)
478 {
479 LM_ERR("reg hash table not initialized\n");
480 return -1;
481 }
482
483 ri = (reg_item_t*)shm_malloc(sizeof(reg_item_t));
484 if(ri==NULL)
485 {
486 SHM_MEM_ERROR;
487 return -1;
488 }
489 memset(ri, 0, sizeof(reg_item_t));
490 slot = reg_get_entry(reg->h_user, _reg_htable->htsize);
491 ri->r = reg;
492 lock_get(&_reg_htable->entries[slot].lock);
493 ri->next = _reg_htable->entries[slot].byuser;
494 _reg_htable->entries[slot].byuser = ri;
495 _reg_htable->entries[slot].usize++;
496 lock_release(&_reg_htable->entries[slot].lock);
497 return 0;
498 }
499
500 #define reg_copy_shm(dst, src, bsize) do { \
501 if((src)->s!=NULL) { \
502 (dst)->s = p; \
503 strncpy((dst)->s, (src)->s, (src)->len); \
504 (dst)->len = (src)->len; \
505 (dst)->s[(dst)->len] = '\0'; \
506 p = p + ((bsize)!=0?(bsize):(dst)->len) + 1; \
507 } \
508 } while(0);
509
510 /**
511 *
512 */
reg_ht_add(reg_uac_t * reg)513 int reg_ht_add(reg_uac_t *reg)
514 {
515 int len;
516 reg_uac_t *nr = NULL;
517 char *p;
518 int i;
519
520 if(reg==NULL || _reg_htable==NULL)
521 {
522 LM_ERR("bad parameters: %p/%p\n", reg, _reg_htable);
523 return -1;
524 }
525 len = reg->l_uuid.len + 1
526 + reg->l_username.len + 1
527 + reg->l_domain.len + 1
528 + reg->r_username.len + 1
529 + reg->r_domain.len + 1
530 + reg->realm.len + 1
531 + reg->auth_proxy.len + 1
532 + reg->auth_username.len + 1
533 + reg->auth_password.len + 1
534 + reg->auth_ha1.len + 1
535 + reg->socket.len + 1
536 + (reg_keep_callid ? UAC_REG_TM_CALLID_SIZE : 0) + 1;
537 nr = (reg_uac_t*)shm_malloc(sizeof(reg_uac_t) + len);
538 if(nr==NULL)
539 {
540 SHM_MEM_ERROR;
541 return -1;
542 }
543 memset(nr, 0, sizeof(reg_uac_t) + len);
544 nr->expires = reg->expires;
545 nr->flags = reg->flags;
546 if (reg->reg_delay)
547 nr->reg_delay = reg->reg_delay;
548 else if (reg_random_delay>0)
549 nr->reg_delay = kam_rand() % reg_random_delay;
550 nr->reg_init = time(NULL);
551 nr->h_uuid = reg_compute_hash(®->l_uuid);
552 nr->h_user = reg_compute_hash(®->l_username);
553
554 p = (char*)nr + sizeof(reg_uac_t);
555
556 reg_copy_shm(&nr->l_uuid, ®->l_uuid, 0);
557 reg_copy_shm(&nr->l_username, ®->l_username, 0);
558 reg_copy_shm(&nr->l_domain, ®->l_domain, 0);
559 reg_copy_shm(&nr->r_username, ®->r_username, 0);
560 reg_copy_shm(&nr->r_domain, ®->r_domain, 0);
561 reg_copy_shm(&nr->realm, ®->realm, 0);
562 reg_copy_shm(&nr->auth_proxy, ®->auth_proxy, 0);
563 reg_copy_shm(&nr->auth_username, ®->auth_username, 0);
564 reg_copy_shm(&nr->auth_password, ®->auth_password, 0);
565 reg_copy_shm(&nr->auth_ha1, ®->auth_ha1, 0);
566 reg_copy_shm(&nr->socket, ®->socket, 0);
567 reg_copy_shm(&nr->callid, &str_empty, reg_keep_callid ? UAC_REG_TM_CALLID_SIZE : 0);
568
569 for(i=0; i<nr->auth_ha1.len; i++) {
570 /* ha1 to lowercase */
571 if(nr->auth_ha1.s[i] >= 'A' && nr->auth_ha1.s[i] <= 'F') {
572 nr->auth_ha1.s[i] += 32;
573 }
574 }
575
576 reg_ht_add_byuser(nr);
577 reg_ht_add_byuuid(nr);
578 counter_inc(regtotal);
579
580 LM_DBG("added uuid: %.*s - l_user: %.*s\n", nr->l_uuid.len, nr->l_uuid.s,
581 nr->l_username.len, nr->l_username.s);
582 return 0;
583 }
584
585
586 /**
587 *
588 */
reg_ht_rm(reg_uac_t * reg)589 int reg_ht_rm(reg_uac_t *reg)
590 {
591 unsigned int slot1, slot2;
592 reg_item_t *it = NULL;
593 reg_item_t *prev = NULL;
594 int found = 0;
595
596 if (reg == NULL)
597 {
598 LM_ERR("bad parameter\n");
599 return -1;
600 }
601
602 /* by uuid */
603 slot1 = reg_get_entry(reg->h_uuid, _reg_htable->htsize);
604 it = _reg_htable->entries[slot1].byuuid;
605 while (it)
606 {
607 if (it->r == reg)
608 {
609 if (prev)
610 prev->next=it->next;
611 else
612 _reg_htable->entries[slot1].byuuid = it->next;
613 _reg_htable->entries[slot1].isize--;
614 shm_free(it);
615 found = 1;
616 break;
617 }
618 prev = it;
619 it = it->next;
620 }
621
622 /* by user */
623 prev = NULL;
624 slot2 = reg_get_entry(reg->h_user, _reg_htable->htsize);
625 if (slot2 != slot1) {
626 lock_get(&_reg_htable->entries[slot2].lock);
627 }
628 it = _reg_htable->entries[slot2].byuser;
629 while (it)
630 {
631 if (it->r == reg)
632 {
633 if (prev)
634 prev->next=it->next;
635 else
636 _reg_htable->entries[slot2].byuser = it->next;
637 _reg_htable->entries[slot2].usize--;
638 shm_free(it);
639 break;
640 }
641 prev = it;
642 it = it->next;
643 }
644
645 shm_free(reg);
646 if (slot2 != slot1) {
647 lock_release(&_reg_htable->entries[slot2].lock);
648 }
649 lock_release(&_reg_htable->entries[slot1].lock);
650
651 if (found) {
652 counter_add(regtotal, -1);
653 if(reg->flags & UAC_REG_ONLINE)
654 counter_add(regactive, -1);
655 if(reg->flags & UAC_REG_DISABLED)
656 counter_add(regdisabled, -1);
657 }
658 return 0;
659 }
660
661
reg_ht_get_byuuid(str * uuid)662 reg_uac_t *reg_ht_get_byuuid(str *uuid)
663 {
664 unsigned int hash;
665 unsigned int slot;
666 reg_item_t *it = NULL;
667
668 if(_reg_htable==NULL)
669 {
670 LM_ERR("reg hash table not initialized\n");
671 return NULL;
672 }
673
674 hash = reg_compute_hash(uuid);
675 slot = reg_get_entry(hash, _reg_htable->htsize);
676 lock_get(&_reg_htable->entries[slot].lock);
677 it = _reg_htable->entries[slot].byuuid;
678 while(it)
679 {
680 if((it->r->h_uuid==hash) && (it->r->l_uuid.len==uuid->len)
681 && (strncmp(it->r->l_uuid.s, uuid->s, uuid->len)==0))
682 {
683 it->r->lock = &_reg_htable->entries[slot].lock;
684 return it->r;
685 }
686 it = it->next;
687 }
688 lock_release(&_reg_htable->entries[slot].lock);
689 return NULL;
690 }
691
692 /**
693 *
694 */
reg_ht_get_byuser(str * user,str * domain)695 reg_uac_t *reg_ht_get_byuser(str *user, str *domain)
696 {
697 unsigned int hash;
698 unsigned int slot;
699 reg_item_t *it = NULL;
700
701 if(_reg_htable==NULL)
702 {
703 LM_ERR("reg hash table not initialized\n");
704 return NULL;
705 }
706
707 hash = reg_compute_hash(user);
708 slot = reg_get_entry(hash, _reg_htable->htsize);
709 lock_get(&_reg_htable->entries[slot].lock);
710 it = _reg_htable->entries[slot].byuser;
711 while(it)
712 {
713 if((it->r->h_user==hash) && (it->r->l_username.len==user->len)
714 && (strncmp(it->r->l_username.s, user->s, user->len)==0))
715 {
716 if(domain!=NULL && domain->s!=NULL)
717 {
718 if((it->r->l_domain.len==domain->len)
719 && (strncmp(it->r->l_domain.s, domain->s, domain->len)==0))
720 {
721 it->r->lock = &_reg_htable->entries[slot].lock;
722 return it->r;
723 }
724 } else {
725 it->r->lock = &_reg_htable->entries[slot].lock;
726 return it->r;
727 }
728 }
729 it = it->next;
730 }
731 lock_release(&_reg_htable->entries[slot].lock);
732 return NULL;
733 }
734
reg_ht_get_byfilter(reg_uac_t ** reg,str * attr,str * val)735 int reg_ht_get_byfilter(reg_uac_t **reg, str *attr, str *val)
736 {
737 int i;
738 str *rval;
739 reg_item_t *it;
740
741 /* try to use the hash table indices */
742 if(attr->len==6 && strncmp(attr->s, "l_uuid", 6)==0) {
743 *reg = reg_ht_get_byuuid(val);
744 return *reg != NULL;
745 }
746 if(attr->len==10 && strncmp(attr->s, "l_username", 10)==0) {
747 *reg = reg_ht_get_byuser(val, NULL);
748 return *reg != NULL;
749 }
750
751 /* check _all_ records */
752 for(i=0; i<_reg_htable->htsize; i++)
753 {
754 lock_get(&_reg_htable->entries[i].lock);
755 /* walk through entries */
756 it = _reg_htable->entries[i].byuuid;
757 while(it)
758 {
759 if(attr->len==10 && strncmp(attr->s, "r_username", 10)==0) {
760 rval = &it->r->r_username;
761 } else if(attr->len==13 && strncmp(attr->s, "auth_username", 13)==0) {
762 rval = &it->r->auth_username;
763 } else {
764 lock_release(&_reg_htable->entries[i].lock);
765 LM_ERR("unsupported filter attribute %.*s\n", attr->len, attr->s);
766 return -1;
767 }
768
769 if(rval->len==val->len && strncmp(val->s, rval->s, val->len)==0) {
770 /* found */
771 *reg = it->r;
772 (*reg)->lock = &_reg_htable->entries[i].lock;
773 return 1;
774 }
775 it = it->next;
776 }
777 lock_release(&_reg_htable->entries[i].lock);
778 }
779 *reg = NULL;
780 return 0;
781 }
782
uac_reg_tmdlg(dlg_t * tmdlg,sip_msg_t * rpl)783 int uac_reg_tmdlg(dlg_t *tmdlg, sip_msg_t *rpl)
784 {
785 if(tmdlg==NULL || rpl==NULL)
786 return -1;
787
788 if (parse_headers(rpl, HDR_EOH_F, 0) < 0) {
789 LM_ERR("error while parsing all headers in the reply\n");
790 return -1;
791 }
792 if(parse_to_header(rpl)<0 || parse_from_header(rpl)<0) {
793 LM_ERR("error while parsing From/To headers in the reply\n");
794 return -1;
795 }
796 memset(tmdlg, 0, sizeof(dlg_t));
797
798 str2int(&(get_cseq(rpl)->number), &tmdlg->loc_seq.value);
799 tmdlg->loc_seq.is_set = 1;
800
801 tmdlg->id.call_id = rpl->callid->body;
802 trim(&tmdlg->id.call_id);
803
804 if (get_from(rpl)->tag_value.len) {
805 tmdlg->id.loc_tag = get_from(rpl)->tag_value;
806 }
807 tmdlg->loc_uri = get_from(rpl)->uri;
808 tmdlg->rem_uri = get_to(rpl)->uri;
809 tmdlg->state= DLG_CONFIRMED;
810 return 0;
811 }
812
uac_reg_tm_callback(struct cell * t,int type,struct tmcb_params * ps)813 void uac_reg_tm_callback( struct cell *t, int type, struct tmcb_params *ps)
814 {
815 char *uuid;
816 str suuid;
817 reg_uac_t *ri = NULL;
818 contact_t* c;
819 int expires;
820 struct sip_uri puri;
821 struct hdr_field *hdr;
822 HASHHEX response;
823 str *new_auth_hdr = NULL;
824 static struct authenticate_body auth;
825 uac_credential_t cred;
826 char b_ruri[MAX_URI_SIZE];
827 str s_ruri;
828 char b_hdrs[MAX_UACH_SIZE];
829 str s_hdrs;
830 uac_req_t uac_r;
831 str method = {"REGISTER", 8};
832 int ret;
833 dlg_t tmdlg;
834
835 if(ps->param==NULL || *ps->param==0)
836 {
837 LM_DBG("uuid not received\n");
838 return;
839 }
840 uuid = *((char**)ps->param);
841 LM_DBG("completed with status %d [uuid: %s]\n",
842 ps->code, uuid);
843 suuid.s = uuid;
844 suuid.len = strlen(suuid.s);
845 ri = reg_ht_get_byuuid(&suuid);
846
847 if(ri==NULL)
848 {
849 LM_DBG("no user with uuid %s\n", uuid);
850 goto done;
851 }
852
853 if(ps->code == 200)
854 {
855 if (parse_headers(ps->rpl, HDR_EOH_F, 0) == -1)
856 {
857 LM_ERR("failed to parse headers\n");
858 goto error;
859 }
860 if (ps->rpl->contact==NULL)
861 {
862 LM_ERR("no Contact found\n");
863 goto error;
864 }
865 if (parse_contact(ps->rpl->contact) < 0)
866 {
867 LM_ERR("failed to parse Contact HF\n");
868 goto error;
869 }
870 if (((contact_body_t*)ps->rpl->contact->parsed)->star)
871 {
872 LM_DBG("* Contact found\n");
873 goto done;
874 }
875
876 if (contact_iterator(&c, ps->rpl, 0) < 0)
877 goto done;
878 while(c)
879 {
880 if(parse_uri(c->uri.s, c->uri.len, &puri)!=0)
881 {
882 LM_ERR("failed to parse c-uri\n");
883 goto error;
884 }
885 if(suuid.len==puri.user.len
886 && (strncmp(puri.user.s, suuid.s, suuid.len)==0))
887 {
888 /* calculate expires */
889 expires=0;
890 if(c->expires==NULL || c->expires->body.len<=0)
891 {
892 if(ps->rpl->expires!=NULL && parse_expires(ps->rpl->expires)==0)
893 expires = ((exp_body_t *)ps->rpl->expires->parsed)->val;
894 } else {
895 str2int(&c->expires->body, (unsigned int*)(&expires));
896 }
897 ri->timer_expires = ri->timer_expires + expires;
898 ri->flags |= UAC_REG_ONLINE;
899 if (reg_keep_callid && ps->rpl->callid->body.len < UAC_REG_TM_CALLID_SIZE) {
900 ri->callid.len = ps->rpl->callid->body.len;
901 memcpy(ri->callid.s, ps->rpl->callid->body.s, ri->callid.len);
902 str2int(&(get_cseq(ps->rpl)->number), &ri->cseq);
903 }
904 goto done;
905 }
906 if (contact_iterator(&c, ps->rpl, c) < 0)
907 {
908 LM_DBG("local contact not found\n");
909 goto done;
910 }
911 }
912
913 LM_DBG("sip response %d while registering [%.*s] with no match\n",
914 ps->code, ri->l_uuid.len, ri->l_uuid.s);
915 goto done;
916 }
917
918 if(ps->code == 401 || ps->code == 407)
919 {
920 if(ri->flags & UAC_REG_AUTHSENT)
921 {
922 LM_ERR("authentication failed for <%.*s>\n",
923 ri->l_uuid.len, ri->l_uuid.s);
924 goto error;
925 }
926 hdr = get_autenticate_hdr(ps->rpl, ps->code);
927 if (hdr==0)
928 {
929 LM_ERR("failed to extract authenticate hdr\n");
930 goto error;
931 }
932
933 LM_DBG("auth header body [%.*s]\n",
934 hdr->body.len, hdr->body.s);
935
936 if (parse_authenticate_body(&hdr->body, &auth)<0)
937 {
938 LM_ERR("failed to parse auth hdr body\n");
939 goto error;
940 }
941 if (ri->realm.len>0) {
942 /* only check if realms match if it is non-empty */
943 if(auth.realm.len!=ri->realm.len
944 || strncmp(auth.realm.s, ri->realm.s, ri->realm.len)!=0)
945 {
946 LM_ERR("realms do not match. requested realm: [%.*s]\n",
947 auth.realm.len, auth.realm.s);
948 goto error;
949 }
950 }
951 cred.aflags = 0;
952 cred.realm = auth.realm;
953 cred.user = ri->auth_username;
954 if(ri->auth_ha1.len > 0) {
955 cred.passwd = ri->auth_ha1;
956 cred.aflags |= UAC_FLCRED_HA1;
957 } else {
958 cred.passwd = ri->auth_password;
959 }
960 cred.next = NULL;
961
962 snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s",
963 ri->r_domain.len, ri->r_domain.s);
964 s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s);
965
966 do_uac_auth(&method, &s_ruri, &cred, &auth, response);
967 new_auth_hdr=build_authorization_hdr(ps->code, &s_ruri, &cred,
968 &auth, response);
969 if (new_auth_hdr==0)
970 {
971 LM_ERR("failed to build authorization hdr\n");
972 goto error;
973 }
974
975 snprintf(b_hdrs, MAX_UACH_SIZE,
976 "Contact: <sip:%.*s@%.*s>\r\n"
977 "Expires: %d\r\n"
978 "%.*s",
979 ri->l_uuid.len, ri->l_uuid.s,
980 reg_contact_addr.len, reg_contact_addr.s,
981 ri->expires,
982 new_auth_hdr->len, new_auth_hdr->s);
983 s_hdrs.s = b_hdrs; s_hdrs.len = strlen(s_hdrs.s);
984 pkg_free(new_auth_hdr->s);
985
986 memset(&uac_r, 0, sizeof(uac_r));
987 if(uac_reg_tmdlg(&tmdlg, ps->rpl)<0)
988 {
989 LM_ERR("failed to build tm dialog\n");
990 goto error;
991 }
992 tmdlg.rem_target = s_ruri;
993 if(ri->auth_proxy.len)
994 tmdlg.dst_uri = ri->auth_proxy;
995 uac_r.method = &method;
996 uac_r.headers = &s_hdrs;
997 uac_r.dialog = &tmdlg;
998 uac_r.cb_flags = TMCB_LOCAL_COMPLETED;
999 /* Callback function */
1000 uac_r.cb = uac_reg_tm_callback;
1001 /* Callback parameter */
1002 uac_r.cbp = (void*)uuid;
1003 ret = uac_tmb.t_request_within(&uac_r);
1004
1005 if(ret<0) {
1006 LM_ERR("failed to send request with authentication for [%.*s]",
1007 ri->l_uuid.len, ri->l_uuid.s);
1008 goto error;
1009 }
1010
1011 ri->flags |= UAC_REG_AUTHSENT;
1012 lock_release(ri->lock);
1013 return;
1014 }
1015
1016 if (ps->code == 423) /* Interval too brief, retry with longer expiry */
1017 {
1018 if (parse_headers(ps->rpl, HDR_EOH_F, 0) == -1) {
1019 LM_ERR("failed to parse headers\n");
1020 goto error;
1021 }
1022 if(ps->rpl->min_expires!=NULL && parse_expires(ps->rpl->min_expires)==0) {
1023 ri->expires = ((exp_body_t *)ps->rpl->min_expires->parsed)->val;
1024 } else {
1025 ri->expires *= 2;
1026 }
1027 LM_DBG("got 423 response while registering [%.*s], set new expires to %d\n",
1028 ri->l_uuid.len, ri->l_uuid.s, ri->expires);
1029 /* Retry will be done on next timer interval */
1030 goto done;
1031 } else
1032 {
1033 LM_ERR("got sip response %d while registering [%.*s]\n",
1034 ps->code, ri->l_uuid.len, ri->l_uuid.s);
1035 goto error;
1036 }
1037
1038 error:
1039 if(reg_retry_interval) {
1040 ri->timer_expires = time(NULL) + reg_retry_interval;
1041 } else {
1042 ri->flags |= UAC_REG_DISABLED;
1043 counter_inc(regdisabled);
1044 }
1045 ri->cseq = 0;
1046 done:
1047 if(ri) {
1048 ri->flags &= ~(UAC_REG_ONGOING|UAC_REG_AUTHSENT);
1049 lock_release(ri->lock);
1050 }
1051 shm_free(uuid);
1052 counter_inc(regactive);
1053 }
1054
uac_reg_update(reg_uac_t * reg,time_t tn)1055 int uac_reg_update(reg_uac_t *reg, time_t tn)
1056 {
1057 char *uuid;
1058 uac_req_t uac_r;
1059 str method = {"REGISTER", 8};
1060 int ret;
1061 char b_ruri[MAX_URI_SIZE];
1062 str s_ruri;
1063 char b_turi[MAX_URI_SIZE];
1064 str s_turi;
1065 char b_hdrs[MAX_UACH_SIZE];
1066 str s_hdrs;
1067 dlg_t tmdlg;
1068
1069 if(uac_tmb.t_request==NULL)
1070 return -1;
1071 if(reg->expires==0)
1072 return 1;
1073 if(reg->flags&UAC_REG_ONGOING) {
1074 if (reg->timer_expires > tn - reg_retry_interval)
1075 return 2;
1076 LM_DBG("record marked as ongoing registration (%d) - resetting\n",
1077 (int)reg->flags);
1078 reg->flags &= ~(UAC_REG_ONLINE|UAC_REG_AUTHSENT);
1079 }
1080 if(reg_active && *reg_active == 0)
1081 return 4;
1082 if(reg->flags&UAC_REG_DISABLED)
1083 return 4;
1084
1085 if(!(reg->flags & UAC_REG_INIT)) {
1086 if(reg->reg_delay>0) {
1087 if(tn < reg->reg_init+reg->reg_delay) {
1088 return 2;
1089 }
1090 }
1091 reg->flags |= UAC_REG_INIT;
1092 }
1093
1094 if(reg->timer_expires > tn + reg_timer_interval + 3)
1095 return 3;
1096 uuid = (char*)shm_malloc(reg->l_uuid.len+1);
1097 if(uuid==NULL)
1098 {
1099 SHM_MEM_ERROR;
1100 return -1;
1101 }
1102 reg->timer_expires = tn;
1103 reg->flags |= UAC_REG_ONGOING;
1104 counter_add(regactive, -1); /* Take it out of the active pool while re-registering */
1105 memcpy(uuid, reg->l_uuid.s, reg->l_uuid.len);
1106 uuid[reg->l_uuid.len] = '\0';
1107
1108 snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s",
1109 reg->r_domain.len, reg->r_domain.s);
1110 s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s);
1111
1112 snprintf(b_turi, MAX_URI_SIZE, "sip:%.*s@%.*s",
1113 reg->r_username.len, reg->r_username.s,
1114 reg->r_domain.len, reg->r_domain.s);
1115 s_turi.s = b_turi; s_turi.len = strlen(s_turi.s);
1116
1117 snprintf(b_hdrs, MAX_UACH_SIZE,
1118 "Contact: <sip:%.*s@%.*s>\r\n"
1119 "Expires: %d\r\n",
1120 reg->l_uuid.len, reg->l_uuid.s,
1121 reg_contact_addr.len, reg_contact_addr.s,
1122 reg->expires);
1123 s_hdrs.s = b_hdrs; s_hdrs.len = strlen(s_hdrs.s);
1124
1125 memset(&uac_r, '\0', sizeof(uac_r));
1126 uac_r.method = &method;
1127 uac_r.headers = &s_hdrs;
1128 uac_r.cb_flags = TMCB_LOCAL_COMPLETED;
1129 /* Callback function */
1130 uac_r.cb = uac_reg_tm_callback;
1131 /* Callback parameter */
1132 uac_r.cbp = (void*)uuid;
1133
1134 if(reg->socket.s != NULL && reg->socket.len > 0) {
1135 /* custom socket */
1136 LM_DBG("using custom socket %.*s to send request\n",
1137 reg->socket.len, reg->socket.s);
1138 uac_r.ssock = ®->socket;
1139 } else {
1140 /* default socket */
1141 if(uac_default_socket.s != NULL && uac_default_socket.len > 0) {
1142 LM_DBG("using configured default_socket to send request\n");
1143 uac_r.ssock = &uac_default_socket;
1144 }
1145 }
1146
1147 if (reg_keep_callid && reg->flags & UAC_REG_ONLINE
1148 && reg->cseq > 0 && reg->cseq < 2147483638
1149 && reg->callid.len > 0)
1150 {
1151 /* reregister, reuse callid and cseq */
1152 memset(&tmdlg, 0, sizeof(dlg_t));
1153 tmdlg.id.call_id = reg->callid;
1154 tmdlg.loc_seq.value = reg->cseq;
1155 tmdlg.loc_seq.is_set = 1;
1156 tmdlg.rem_target = s_ruri;
1157 tmdlg.loc_uri = s_turi;
1158 tmdlg.rem_uri = s_turi;
1159 tmdlg.state= DLG_CONFIRMED;
1160 if(reg->auth_proxy.len)
1161 tmdlg.dst_uri = reg->auth_proxy;
1162 uac_r.dialog = &tmdlg;
1163
1164 ret = uac_tmb.t_request_within(&uac_r);
1165 } else {
1166 ret = uac_tmb.t_request(&uac_r, /* UAC Req */
1167 &s_ruri, /* Request-URI */
1168 &s_turi, /* To */
1169 &s_turi, /* From */
1170 (reg->auth_proxy.len)?®->auth_proxy:NULL /* outbound uri */
1171 );
1172 }
1173 reg->flags &= ~UAC_REG_ONLINE;
1174
1175 if(ret<0)
1176 {
1177 LM_ERR("failed to send request for [%.*s]", reg->l_uuid.len, reg->l_uuid.s);
1178 shm_free(uuid);
1179 if (reg_retry_interval)
1180 reg->timer_expires = (tn ? tn : time(NULL)) + reg_retry_interval;
1181 else {
1182 reg->flags |= UAC_REG_DISABLED;
1183 counter_inc(regdisabled);
1184 }
1185 reg->flags &= ~UAC_REG_ONGOING;
1186 return -1;
1187 }
1188 return 0;
1189 }
1190
1191 /**
1192 *
1193 */
uac_reg_timer(unsigned int ticks)1194 void uac_reg_timer(unsigned int ticks)
1195 {
1196 int i;
1197 reg_item_t *it = NULL;
1198 time_t tn;
1199
1200 if(_reg_htable==NULL)
1201 return;
1202
1203 tn = time(NULL);
1204 for(i=0; i<_reg_htable->htsize; i++)
1205 {
1206 /* walk through entries */
1207 lock_get(&_reg_htable->entries[i].lock);
1208 it = _reg_htable->entries[i].byuuid;
1209 while(it)
1210 {
1211 uac_reg_update(it->r, tn);
1212 it = it->next;
1213 }
1214 lock_release(&_reg_htable->entries[i].lock);
1215 }
1216
1217 if(_reg_htable_gc!=NULL)
1218 {
1219 lock_get(_reg_htable_gc_lock);
1220 if(_reg_htable_gc->stime!=0
1221 && _reg_htable_gc->stime < tn - _uac_reg_gc_interval)
1222 uac_reg_reset_ht_gc();
1223 lock_release(_reg_htable_gc_lock);
1224 }
1225 }
1226
uac_reg_check_password(reg_uac_t * reg)1227 static int uac_reg_check_password(reg_uac_t *reg)
1228 {
1229 int i;
1230
1231 if(reg->auth_password.len<=0 && reg->auth_ha1.len<=0) {
1232 LM_ERR("no password value provided - ignoring record\n");
1233 return -1;
1234 }
1235
1236 if(reg->auth_ha1.len > 0 && reg->auth_ha1.len != HASHHEXLEN) {
1237 LM_ERR("invalid HA2 length: %d - ignoring record\n", reg->auth_ha1.len);
1238 return -1;
1239 }
1240 for(i=0; i<reg->auth_ha1.len; i++) {
1241 if(!((reg->auth_ha1.s[i]>='0' && reg->auth_ha1.s[i]<='9')
1242 || (reg->auth_ha1.s[i]>='a' && reg->auth_ha1.s[i]<='f')
1243 || (reg->auth_ha1.s[i]>='A' && reg->auth_ha1.s[i]<='F'))) {
1244 LM_ERR("invalid char %d in HA1 string: %.*s\n", i,
1245 reg->auth_ha1.len, reg->auth_ha1.s);
1246 return -1;
1247 }
1248 }
1249
1250 return 0;
1251 }
1252
1253 #define reg_db_set_attr(attr, pos, eval) do { \
1254 if(!VAL_NULL(&RES_ROWS(db_res)[i].values[pos])) { \
1255 reg->attr.s = \
1256 (char*)(RES_ROWS(db_res)[i].values[pos].val.string_val); \
1257 reg->attr.len = strlen(reg->attr.s); \
1258 if(reg->attr.len == 0) { \
1259 if(eval == 0) { \
1260 LM_ERR("empty value not allowed for column[%d]='%.*s' - ignoring record\n", \
1261 pos, db_cols[pos]->len, db_cols[pos]->s); \
1262 return -1; \
1263 } else { \
1264 reg->attr.s = NULL; \
1265 } \
1266 } \
1267 } \
1268 } while(0);
1269
1270
uac_reg_db_to_reg(reg_uac_t * reg,db1_res_t * db_res,int i,db_key_t * db_cols)1271 static int uac_reg_db_to_reg(reg_uac_t *reg, db1_res_t* db_res, int i, db_key_t *db_cols)
1272 {
1273 memset(reg, 0, sizeof(reg_uac_t));;
1274 /* check for NULL values ?!?! */
1275 reg_db_set_attr(l_uuid, 0, 0);
1276 reg_db_set_attr(l_username, 1, 0);
1277 reg_db_set_attr(l_domain, 2, 0);
1278 reg_db_set_attr(r_username, 3, 0);
1279 reg_db_set_attr(r_domain, 4, 0);
1280 /* realm may be empty */
1281 reg_db_set_attr(realm, 5, 1);
1282 reg_db_set_attr(auth_username, 6, 0);
1283 reg_db_set_attr(auth_password, 7, 1);
1284 reg_db_set_attr(auth_ha1, 8, 1);
1285 if(uac_reg_check_password(reg) < 0) {
1286 return -1;
1287 }
1288 reg_db_set_attr(auth_proxy, 9, 0);
1289 reg->expires = (unsigned int)RES_ROWS(db_res)[i].values[10].val.int_val;
1290 reg->flags = (unsigned int)RES_ROWS(db_res)[i].values[11].val.int_val;
1291 reg->reg_delay = (unsigned int)RES_ROWS(db_res)[i].values[12].val.int_val;
1292
1293 /* socket may be empty */
1294 reg_db_set_attr(socket, 13, 1);
1295
1296 return 0;
1297 }
1298
1299
1300 /**
1301 *
1302 */
uac_reg_load_db(void)1303 int uac_reg_load_db(void)
1304 {
1305 db1_con_t *reg_db_con = NULL;
1306 db_func_t reg_dbf;
1307 reg_uac_t reg;
1308 db_key_t db_cols[14] = {
1309 &l_uuid_column,
1310 &l_username_column,
1311 &l_domain_column,
1312 &r_username_column,
1313 &r_domain_column,
1314 &realm_column,
1315 &auth_username_column,
1316 &auth_password_column,
1317 &auth_ha1_column,
1318 &auth_proxy_column,
1319 &expires_column,
1320 &flags_column,
1321 ®_delay_column,
1322 &socket_column
1323 };
1324 db1_res_t* db_res = NULL;
1325 int i, ret;
1326
1327 /* binding to db module */
1328 if(reg_db_url.s==NULL)
1329 {
1330 LM_ERR("no db url\n");
1331 return -1;
1332 }
1333
1334 if(db_bind_mod(®_db_url, ®_dbf))
1335 {
1336 LM_ERR("database module not found\n");
1337 return -1;
1338 }
1339
1340 if (!DB_CAPABILITY(reg_dbf, DB_CAP_ALL))
1341 {
1342 LM_ERR("database module does not "
1343 "implement all functions needed by the module\n");
1344 return -1;
1345 }
1346
1347 /* open a connection with the database */
1348 reg_db_con = reg_dbf.init(®_db_url);
1349 if(reg_db_con==NULL)
1350 {
1351 LM_ERR("failed to connect to the database\n");
1352 return -1;
1353 }
1354
1355 if(db_check_table_version(®_dbf, reg_db_con, ®_db_table, UACREG_TABLE_VERSION) < 0) {
1356 DB_TABLE_VERSION_ERROR(reg_db_table);
1357 return -1;
1358 }
1359
1360 if (reg_dbf.use_table(reg_db_con, ®_db_table) < 0)
1361 {
1362 LM_ERR("failed to use_table\n");
1363 return -1;
1364 }
1365
1366 if (DB_CAPABILITY(reg_dbf, DB_CAP_FETCH)) {
1367 if(reg_dbf.query(reg_db_con, 0, 0, 0, db_cols, 0, 14, 0, 0) < 0)
1368 {
1369 LM_ERR("Error while querying db\n");
1370 return -1;
1371 }
1372 if(reg_dbf.fetch_result(reg_db_con, &db_res, reg_fetch_rows)<0)
1373 {
1374 LM_ERR("Error while fetching result\n");
1375 if (db_res)
1376 reg_dbf.free_result(reg_db_con, db_res);
1377 goto error;
1378 } else {
1379 if(RES_ROW_N(db_res)==0)
1380 {
1381 goto done;
1382 }
1383 }
1384 } else {
1385 if((ret=reg_dbf.query(reg_db_con, NULL, NULL, NULL, db_cols,
1386 0, 14, 0, &db_res))!=0
1387 || RES_ROW_N(db_res)<=0 )
1388 {
1389 reg_dbf.free_result(reg_db_con, db_res);
1390 if( ret==0)
1391 {
1392 return 0;
1393 } else {
1394 goto error;
1395 }
1396 }
1397 }
1398
1399 do {
1400 for(i=0; i<RES_ROW_N(db_res); i++)
1401 {
1402 if(uac_reg_db_to_reg(®, db_res, i, db_cols) < 0)
1403 continue;
1404 if(reg_ht_add(®)<0)
1405 {
1406 LM_ERR("Error adding reg to htable\n");
1407 goto error;
1408 }
1409 }
1410 if (DB_CAPABILITY(reg_dbf, DB_CAP_FETCH)) {
1411 if(reg_dbf.fetch_result(reg_db_con, &db_res, reg_fetch_rows)<0) {
1412 LM_ERR("Error while fetching!\n");
1413 if (db_res)
1414 reg_dbf.free_result(reg_db_con, db_res);
1415 goto error;
1416 }
1417 } else {
1418 break;
1419 }
1420 } while(RES_ROW_N(db_res)>0);
1421 reg_dbf.free_result(reg_db_con, db_res);
1422 reg_dbf.close(reg_db_con);
1423
1424 done:
1425 return 0;
1426
1427 error:
1428 if (reg_db_con) {
1429 reg_dbf.free_result(reg_db_con, db_res);
1430 reg_dbf.close(reg_db_con);
1431 }
1432 return -1;
1433 }
1434
1435 /**
1436 *
1437 */
uac_reg_db_refresh(str * pl_uuid)1438 int uac_reg_db_refresh(str *pl_uuid)
1439 {
1440 db1_con_t *reg_db_con = NULL;
1441 db_func_t reg_dbf;
1442 reg_uac_t reg;
1443 reg_uac_t *cur_reg;
1444 db_key_t db_cols[14] = {
1445 &l_uuid_column,
1446 &l_username_column,
1447 &l_domain_column,
1448 &r_username_column,
1449 &r_domain_column,
1450 &realm_column,
1451 &auth_username_column,
1452 &auth_password_column,
1453 &auth_ha1_column,
1454 &auth_proxy_column,
1455 &expires_column,
1456 &flags_column,
1457 ®_delay_column,
1458 &socket_column
1459 };
1460 db_key_t db_keys[1] = {&l_uuid_column};
1461 db_val_t db_vals[1];
1462
1463 db1_res_t* db_res = NULL;
1464 int ret;
1465
1466 /* binding to db module */
1467 if(reg_db_url.s==NULL)
1468 {
1469 LM_ERR("no db url\n");
1470 return -1;
1471 }
1472
1473 if(db_bind_mod(®_db_url, ®_dbf))
1474 {
1475 LM_ERR("database module not found\n");
1476 return -1;
1477 }
1478
1479 if (!DB_CAPABILITY(reg_dbf, DB_CAP_ALL))
1480 {
1481 LM_ERR("database module does not "
1482 "implement all functions needed by the module\n");
1483 return -1;
1484 }
1485
1486 /* open a connection with the database */
1487 reg_db_con = reg_dbf.init(®_db_url);
1488 if(reg_db_con==NULL)
1489 {
1490 LM_ERR("failed to connect to the database\n");
1491 return -1;
1492 }
1493 if (reg_dbf.use_table(reg_db_con, ®_db_table) < 0)
1494 {
1495 LM_ERR("failed to use_table\n");
1496 return -1;
1497 }
1498
1499 db_vals[0].type = DB1_STR;
1500 db_vals[0].nul = 0;
1501 db_vals[0].val.str_val.s = pl_uuid->s;
1502 db_vals[0].val.str_val.len = pl_uuid->len;
1503
1504 if((ret=reg_dbf.query(reg_db_con, db_keys, NULL, db_vals, db_cols,
1505 1 /*nr keys*/, 14 /*nr cols*/, 0, &db_res))!=0
1506 || RES_ROW_N(db_res)<=0 )
1507 {
1508 reg_dbf.free_result(reg_db_con, db_res);
1509 if( ret==0)
1510 {
1511 return 0;
1512 } else {
1513 goto error;
1514 }
1515 }
1516
1517 if (uac_reg_db_to_reg(®, db_res, 0, db_cols)==0)
1518 {
1519 lock_get(_reg_htable_gc_lock);
1520 if((cur_reg=reg_ht_get_byuuid(pl_uuid))!=NULL)
1521 {
1522 reg.flags |= (cur_reg->flags & (UAC_REG_ONGOING | UAC_REG_AUTHSENT));
1523 reg_ht_rm(cur_reg);
1524 }
1525 if(reg_ht_add(®)<0)
1526 {
1527 lock_release(_reg_htable_gc_lock);
1528 LM_ERR("Error adding reg to htable\n");
1529 goto error;
1530 }
1531 lock_release(_reg_htable_gc_lock);
1532 }
1533
1534 reg_dbf.free_result(reg_db_con, db_res);
1535 reg_dbf.close(reg_db_con);
1536
1537 return 1;
1538
1539 error:
1540 if (reg_db_con) {
1541 reg_dbf.free_result(reg_db_con, db_res);
1542 reg_dbf.close(reg_db_con);
1543 }
1544 return -1;
1545 }
1546
1547 /**
1548 *
1549 */
uac_reg_refresh(sip_msg_t * msg,str * l_uuid)1550 int uac_reg_refresh(sip_msg_t *msg, str *l_uuid)
1551 {
1552 int ret;
1553
1554 if(l_uuid==NULL || l_uuid->s==NULL || l_uuid->len<=0) {
1555 LM_ERR("invalid parameters\n");
1556 return -1;
1557 }
1558
1559 ret = uac_reg_db_refresh(l_uuid);
1560 if(ret==0) {
1561 LM_WARN("record not found: %.*s\n", l_uuid->len, l_uuid->s);
1562 return -1;
1563 } else if(ret<0) {
1564 LM_WARN("failed to refresh record: %.*s - check log messages\n",
1565 l_uuid->len, l_uuid->s);
1566 return -1;
1567 }
1568
1569 return 1;
1570 }
1571
1572 /**
1573 *
1574 */
uac_reg_lookup(struct sip_msg * msg,str * src,pv_spec_t * dst,int mode)1575 int uac_reg_lookup(struct sip_msg *msg, str *src, pv_spec_t *dst, int mode)
1576 {
1577 char b_ruri[MAX_URI_SIZE];
1578 str s_ruri;
1579 struct sip_uri puri;
1580 reg_uac_t *reg = NULL;
1581 pv_value_t val;
1582
1583 if(!pv_is_w(dst))
1584 {
1585 LM_ERR("dst is not w/\n");
1586 return -1;
1587 }
1588 if(mode==0)
1589 {
1590 reg = reg_ht_get_byuuid(src);
1591 if(reg==NULL)
1592 {
1593 LM_DBG("no uuid: %.*s\n", src->len, src->s);
1594 return -1;
1595 }
1596 snprintf(b_ruri, MAX_URI_SIZE, "sip:%.*s@%.*s",
1597 reg->l_username.len, reg->l_username.s,
1598 reg->l_domain.len, reg->l_domain.s);
1599 s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s);
1600 } else {
1601 if(parse_uri(src->s, src->len, &puri)!=0)
1602 {
1603 LM_ERR("failed to parse uri\n");
1604 return -2;
1605 }
1606 reg = reg_ht_get_byuser(&puri.user, (reg_use_domain)?&puri.host:NULL);
1607 if(reg==NULL)
1608 {
1609 LM_DBG("no user: %.*s\n", src->len, src->s);
1610 return -1;
1611 }
1612 snprintf(b_ruri, MAX_URI_SIZE, "%.*s",
1613 reg->l_uuid.len, reg->l_uuid.s);
1614 s_ruri.s = b_ruri; s_ruri.len = strlen(s_ruri.s);
1615 }
1616 lock_release(reg->lock);
1617 memset(&val, 0, sizeof(pv_value_t));
1618 val.flags |= PV_VAL_STR;
1619 val.rs = s_ruri;
1620 if(pv_set_spec_value(msg, dst, 0, &val)!=0)
1621 return -1;
1622
1623 return 1;
1624 }
1625
1626 /**
1627 *
1628 */
uac_reg_status(struct sip_msg * msg,str * src,int mode)1629 int uac_reg_status(struct sip_msg *msg, str *src, int mode)
1630 {
1631 struct sip_uri puri;
1632 reg_uac_t *reg = NULL;
1633 int ret;
1634
1635 if(mode==0)
1636 {
1637 reg = reg_ht_get_byuuid(src);
1638 if(reg==NULL)
1639 {
1640 LM_DBG("no uuid: %.*s\n", src->len, src->s);
1641 return -1;
1642 }
1643 } else {
1644 if(parse_uri(src->s, src->len, &puri)!=0)
1645 {
1646 LM_ERR("failed to parse uri\n");
1647 return -1;
1648 }
1649 reg = reg_ht_get_byuser(&puri.user, (reg_use_domain)?&puri.host:NULL);
1650 if(reg==NULL)
1651 {
1652 LM_DBG("no user: %.*s\n", src->len, src->s);
1653 return -1;
1654 }
1655 }
1656
1657 if ((reg->flags & UAC_REG_ONLINE) && (reg->timer_expires > time(NULL)))
1658 ret = 1;
1659 else if (reg->flags & UAC_REG_ONGOING)
1660 ret = -2;
1661 else if (reg->flags & UAC_REG_DISABLED)
1662 ret = -3;
1663 else
1664 ret = -99;
1665
1666 lock_release(reg->lock);
1667 return ret;
1668 }
1669
1670 /**
1671 *
1672 */
uac_reg_request_to(struct sip_msg * msg,str * src,unsigned int mode)1673 int uac_reg_request_to(struct sip_msg *msg, str *src, unsigned int mode)
1674 {
1675 char ruri[MAX_URI_SIZE];
1676 struct sip_uri puri;
1677 reg_uac_t *reg = NULL;
1678 pv_value_t val;
1679 struct action act;
1680 struct run_act_ctx ra_ctx;
1681 unsigned int umode;
1682 unsigned int amode;
1683
1684 umode = mode & UACREG_REQTO_MASK_USER;
1685 amode = mode & UACREG_REQTO_MASK_AUTH;
1686
1687 switch(umode)
1688 {
1689 case 0:
1690 reg = reg_ht_get_byuuid(src);
1691 break;
1692 case 1:
1693 if(reg_use_domain)
1694 {
1695 if (parse_uri(src->s, src->len, &puri)!=0)
1696 {
1697 LM_ERR("failed to parse uri\n");
1698 return -2;
1699 }
1700 reg = reg_ht_get_byuser(&puri.user, &puri.host);
1701 } else {
1702 reg = reg_ht_get_byuser(src, NULL);
1703 }
1704 break;
1705 default:
1706 LM_ERR("unknown mode: %d\n", mode);
1707 return -1;
1708 }
1709
1710 if(reg==NULL)
1711 {
1712 LM_DBG("no user: %.*s\n", src->len, src->s);
1713 return -1;
1714 }
1715
1716 // Set uri ($ru)
1717 snprintf(ruri, MAX_URI_SIZE, "sip:%.*s@%.*s",
1718 reg->r_username.len, reg->r_username.s,
1719 reg->r_domain.len, reg->r_domain.s);
1720 memset(&act, 0, sizeof(act));
1721 act.type = SET_URI_T;
1722 act.val[0].type = STRING_ST;
1723 act.val[0].u.string = ruri;
1724 init_run_actions_ctx(&ra_ctx);
1725 if (do_action(&ra_ctx, &act, msg) < 0) {
1726 LM_ERR("error while setting request uri\n");
1727 goto error;
1728 }
1729
1730 // Set auth_proxy ($du)
1731 if (set_dst_uri(msg, ®->auth_proxy) < 0) {
1732 LM_ERR("error while setting outbound proxy\n");
1733 goto error;
1734 }
1735
1736 memset(&val, 0, sizeof(pv_value_t));
1737 val.flags |= PV_VAL_STR;
1738
1739 // Set auth_realm
1740 val.rs = reg->realm;
1741 if(pv_set_spec_value(msg, &auth_realm_spec, 0, &val)!=0) {
1742 LM_ERR("error while setting auth_realm\n");
1743 goto error;
1744 }
1745
1746 // Set auth_username
1747 val.rs = reg->auth_username;
1748 if(pv_set_spec_value(msg, &auth_username_spec, 0, &val)!=0) {
1749 LM_ERR("error while setting auth_username\n");
1750 goto error;
1751 }
1752
1753 if(amode) {
1754 // set auth_ha1
1755 val.rs = reg->auth_ha1;
1756 } else {
1757 // set auth_password
1758 val.rs = reg->auth_password;
1759 }
1760 if(pv_set_spec_value(msg, &auth_password_spec, 0, &val)!=0) {
1761 LM_ERR("error while setting auth password (mode: %d)\n", amode);
1762 goto error;
1763 }
1764 lock_release(reg->lock);
1765 return 1;
1766
1767 error:
1768 lock_release(reg->lock);
1769 return -1;
1770 }
1771
1772 /**
1773 *
1774 */
uac_reg_update_flag(str * attr,str * val,int mode,int fval)1775 static int uac_reg_update_flag(str *attr, str *val, int mode, int fval)
1776 {
1777 reg_uac_t *reg = NULL;
1778 int ret;
1779
1780 if(_reg_htable==NULL) {
1781 LM_ERR("uac remote registrations not enabled\n");
1782 return -1;
1783 }
1784
1785 if(attr->len<=0 || attr->s==NULL || val->len<=0 || val->s==NULL) {
1786 LM_ERR("bad parameter values\n");
1787 return -1;
1788 }
1789
1790 ret = reg_ht_get_byfilter(®, attr, val);
1791 if (ret == 0) {
1792 LM_DBG("record not found for %.*s = %.*s\n", attr->len, attr->s,
1793 val->len, val->s);
1794 return -2;
1795 } else if (ret < 0) {
1796 LM_DBG("unsupported filter attribute %.*s = %.*s\n", attr->len, attr->s,
1797 val->len, val->s);
1798 return -3;
1799 }
1800
1801 if(mode==1) {
1802 reg->flags |= fval;
1803 } else {
1804 reg->flags &= ~fval;
1805 }
1806 reg->timer_expires = time(NULL) + 1;
1807
1808 lock_release(reg->lock);
1809 return 1;
1810 }
1811
1812 /**
1813 *
1814 */
uac_reg_enable(sip_msg_t * msg,str * attr,str * val)1815 int uac_reg_enable(sip_msg_t *msg, str *attr, str *val)
1816 {
1817 counter_add(regdisabled, -1);
1818 return uac_reg_update_flag(attr, val, 0, UAC_REG_DISABLED);
1819 }
1820
1821 /**
1822 *
1823 */
uac_reg_disable(sip_msg_t * msg,str * attr,str * val)1824 int uac_reg_disable(sip_msg_t *msg, str *attr, str *val)
1825 {
1826 counter_inc(regdisabled);
1827 return uac_reg_update_flag(attr, val, 1, UAC_REG_DISABLED);
1828 }
1829
1830 /**
1831 *
1832 */
rpc_uac_reg_add_node_helper(rpc_t * rpc,void * ctx,reg_uac_t * reg,time_t tn)1833 static int rpc_uac_reg_add_node_helper(rpc_t* rpc, void* ctx, reg_uac_t *reg, time_t tn)
1834 {
1835 void* th;
1836 str none = {"none", 4};
1837
1838 /* add entry node */
1839 if (rpc->add(ctx, "{", &th) < 0)
1840 {
1841 rpc->fault(ctx, 500, "Internal error creating rpc");
1842 return -1;
1843 }
1844 if (rpc->struct_add(th, "SSSSSSSSSSddddddS",
1845 "l_uuid", ®->l_uuid,
1846 "l_username", ®->l_username,
1847 "l_domain", ®->l_domain,
1848 "r_username", ®->r_username,
1849 "r_domain", ®->r_domain,
1850 "realm", ®->realm,
1851 "auth_username", ®->auth_username,
1852 "auth_password", (reg->auth_password.len)?
1853 ®->auth_password:&none,
1854 "auth_ha1", (reg->auth_ha1.len)?
1855 ®->auth_ha1:&none,
1856 "auth_proxy", (reg->auth_proxy.len)?
1857 ®->auth_proxy:&none,
1858 "expires", (int)reg->expires,
1859 "flags", (int)reg->flags,
1860 "diff_expires", (int)(reg->timer_expires - tn),
1861 "timer_expires", (int)reg->timer_expires,
1862 "reg_init", (int)reg->reg_init,
1863 "reg_delay", (int)reg->reg_delay,
1864 "socket", ®->socket
1865 )<0) {
1866 rpc->fault(ctx, 500, "Internal error adding item");
1867 return -1;
1868 }
1869 return 0;
1870 }
1871
1872 static const char* rpc_uac_reg_dump_doc[2] = {
1873 "Dump the contents of user registrations table.",
1874 0
1875 };
1876
rpc_uac_reg_dump(rpc_t * rpc,void * ctx)1877 static void rpc_uac_reg_dump(rpc_t* rpc, void* ctx)
1878 {
1879 int i;
1880 reg_item_t *reg = NULL;
1881 time_t tn;
1882
1883 if(_reg_htable==NULL)
1884 {
1885 rpc->fault(ctx, 500, "Not enabled");
1886 return;
1887 }
1888
1889 tn = time(NULL);
1890
1891 for(i=0; i<_reg_htable->htsize; i++)
1892 {
1893 lock_get(&_reg_htable->entries[i].lock);
1894 /* walk through entries */
1895 reg = _reg_htable->entries[i].byuuid;
1896 while(reg)
1897 {
1898 if (rpc_uac_reg_add_node_helper(rpc, ctx, reg->r, tn)<0)
1899 {
1900 lock_release(&_reg_htable->entries[i].lock);
1901 return;
1902 }
1903 reg = reg->next;
1904 }
1905 lock_release(&_reg_htable->entries[i].lock);
1906 }
1907 }
1908
1909 static const char* rpc_uac_reg_info_doc[2] = {
1910 "Return the details of registration for a particular record.",
1911 0
1912 };
1913
rpc_uac_reg_info(rpc_t * rpc,void * ctx)1914 static void rpc_uac_reg_info(rpc_t* rpc, void* ctx)
1915 {
1916 reg_uac_t *reg = NULL;
1917 str attr = {0};
1918 str val = {0};
1919 int ret;
1920
1921 if(_reg_htable==NULL)
1922 {
1923 rpc->fault(ctx, 500, "Not enabled");
1924 return;
1925 }
1926
1927 if(rpc->scan(ctx, "S.S", &attr, &val)<2)
1928 {
1929 rpc->fault(ctx, 400, "Invalid Parameters");
1930 return;
1931 }
1932 if(attr.len<=0 || attr.s==NULL || val.len<=0 || val.s==NULL)
1933 {
1934 LM_ERR("bad parameter values\n");
1935 rpc->fault(ctx, 400, "Invalid Parameter Values");
1936 return;
1937 }
1938
1939 ret = reg_ht_get_byfilter(®, &attr, &val);
1940 if (ret == 0) {
1941 rpc->fault(ctx, 404, "Record not found");
1942 return;
1943 } else if (ret < 0) {
1944 rpc->fault(ctx, 400, "Unsupported filter attribute");
1945 return;
1946 }
1947
1948 rpc_uac_reg_add_node_helper(rpc, ctx, reg, time(NULL));
1949 lock_release(reg->lock);
1950 return;
1951 }
1952
1953
rpc_uac_reg_update_flag(rpc_t * rpc,void * ctx,int mode,int fval)1954 static void rpc_uac_reg_update_flag(rpc_t* rpc, void* ctx, int mode, int fval)
1955 {
1956 reg_uac_t *reg = NULL;
1957 str attr = {0};
1958 str val = {0};
1959 int ret;
1960
1961 if(_reg_htable==NULL)
1962 {
1963 rpc->fault(ctx, 500, "Not enabled");
1964 return;
1965 }
1966
1967 if(rpc->scan(ctx, "S.S", &attr, &val)<2)
1968 {
1969 rpc->fault(ctx, 400, "Invalid Parameters");
1970 return;
1971 }
1972 if(attr.len<=0 || attr.s==NULL || val.len<=0 || val.s==NULL)
1973 {
1974 LM_ERR("bad parameter values\n");
1975 rpc->fault(ctx, 400, "Invalid Parameter Values");
1976 return;
1977 }
1978
1979 ret = reg_ht_get_byfilter(®, &attr, &val);
1980 if (ret == 0) {
1981 rpc->fault(ctx, 404, "Record not found");
1982 return;
1983 } else if (ret < 0) {
1984 rpc->fault(ctx, 400, "Unsupported filter attribute");
1985 return;
1986 }
1987
1988 if(mode==1) {
1989 reg->flags |= fval;
1990 } else {
1991 reg->flags &= ~fval;
1992 }
1993 reg->timer_expires = time(NULL) + 1;
1994
1995 lock_release(reg->lock);
1996 return;
1997 }
1998
1999 static const char* rpc_uac_reg_enable_doc[2] = {
2000 "Enable registration for a particular record.",
2001 0
2002 };
2003
rpc_uac_reg_enable(rpc_t * rpc,void * ctx)2004 static void rpc_uac_reg_enable(rpc_t* rpc, void* ctx)
2005 {
2006 rpc_uac_reg_update_flag(rpc, ctx, 0, UAC_REG_DISABLED);
2007 counter_add(regdisabled, -1);
2008 }
2009
2010 static const char* rpc_uac_reg_disable_doc[2] = {
2011 "Disable registration for a particular record.",
2012 0
2013 };
2014
rpc_uac_reg_disable(rpc_t * rpc,void * ctx)2015 static void rpc_uac_reg_disable(rpc_t* rpc, void* ctx)
2016 {
2017 rpc_uac_reg_update_flag(rpc, ctx, 1, UAC_REG_DISABLED);
2018 counter_inc(regdisabled);
2019 }
2020
2021 static const char* rpc_uac_reg_reload_doc[2] = {
2022 "Reload records from database.",
2023 0
2024 };
2025
rpc_uac_reg_reload(rpc_t * rpc,void * ctx)2026 static void rpc_uac_reg_reload(rpc_t* rpc, void* ctx)
2027 {
2028 int ret;
2029 if(uac_reg_ht_shift()<0) {
2030 rpc->fault(ctx, 500, "Failed to shift records - check log messages");
2031 return;
2032 }
2033 lock_get(_reg_htable_gc_lock);
2034 ret = uac_reg_load_db();
2035 lock_release(_reg_htable_gc_lock);
2036 if(ret<0) {
2037 rpc->fault(ctx, 500, "Failed to reload records - check log messages");
2038 return;
2039 }
2040 }
2041
2042 static const char* rpc_uac_reg_refresh_doc[2] = {
2043 "Refresh a record from database.",
2044 0
2045 };
2046
rpc_uac_reg_refresh(rpc_t * rpc,void * ctx)2047 static void rpc_uac_reg_refresh(rpc_t* rpc, void* ctx)
2048 {
2049 int ret;
2050 str l_uuid;
2051
2052 if(rpc->scan(ctx, "S", &l_uuid)<1)
2053 {
2054 rpc->fault(ctx, 400, "Invalid Parameters");
2055 return;
2056 }
2057
2058 ret = uac_reg_db_refresh(&l_uuid);
2059 if(ret==0) {
2060 rpc->fault(ctx, 404, "Record not found");
2061 return;
2062 } else if(ret<0) {
2063 rpc->fault(ctx, 500, "Failed to refresh record - check log messages");
2064 return;
2065 }
2066 }
2067
2068 static const char* rpc_uac_reg_remove_doc[2] = {
2069 "Remove a record from memory.",
2070 0
2071 };
2072
rpc_uac_reg_remove(rpc_t * rpc,void * ctx)2073 static void rpc_uac_reg_remove(rpc_t* rpc, void* ctx)
2074 {
2075 int ret;
2076 str l_uuid;
2077 reg_uac_t *reg;
2078
2079 if(rpc->scan(ctx, "S", &l_uuid)<1)
2080 {
2081 rpc->fault(ctx, 400, "Invalid Parameters");
2082 return;
2083 }
2084 reg = reg_ht_get_byuuid(&l_uuid);
2085 if (!reg) {
2086 rpc->fault(ctx, 404, "Record not found");
2087 return;
2088 }
2089
2090 ret = reg_ht_rm(reg);
2091 if(ret<0) {
2092 rpc->fault(ctx, 500, "Failed to remove record - check log messages");
2093 return;
2094 }
2095 }
2096
2097 static const char* rpc_uac_reg_add_doc[2] = {
2098 "Add a record to memory.",
2099 0
2100 };
2101
rpc_uac_reg_add(rpc_t * rpc,void * ctx)2102 static void rpc_uac_reg_add(rpc_t* rpc, void* ctx)
2103 {
2104 int ret;
2105 reg_uac_t reg;
2106 reg_uac_t *cur_reg;
2107
2108 if(rpc->scan(ctx, "SSSSSSSSSSdddS",
2109 ®.l_uuid,
2110 ®.l_username,
2111 ®.l_domain,
2112 ®.r_username,
2113 ®.r_domain,
2114 ®.realm,
2115 ®.auth_username,
2116 ®.auth_password,
2117 ®.auth_ha1,
2118 ®.auth_proxy,
2119 ®.expires,
2120 ®.flags,
2121 ®.reg_delay,
2122 ®.socket
2123 )<1)
2124 {
2125 rpc->fault(ctx, 400, "Invalid Parameters");
2126 return;
2127 }
2128
2129 if(reg.auth_password.len==1 && reg.auth_password.s[0] == '.') {
2130 reg.auth_password.s = NULL;
2131 reg.auth_password.len = 0;
2132 }
2133
2134 if(reg.auth_ha1.len==1 && reg.auth_ha1.s[0] == '.') {
2135 reg.auth_ha1.s = NULL;
2136 reg.auth_ha1.len = 0;
2137 }
2138
2139 if(uac_reg_check_password(®) < 0) {
2140 rpc->fault(ctx, 500, "Failed to add record - invalid password or ha1");
2141 return;
2142 }
2143
2144 cur_reg = reg_ht_get_byuuid(®.l_uuid);
2145 if (cur_reg) {
2146 lock_release(cur_reg->lock);
2147 rpc->fault(ctx, 409, "uuid already exists");
2148 return;
2149 }
2150
2151 ret = reg_ht_add(®);
2152 if(ret<0) {
2153 rpc->fault(ctx, 500, "Failed to add record - check log messages");
2154 return;
2155 }
2156 }
2157
2158
2159 static const char* rpc_uac_reg_active_doc[2] = {
2160 "Set remote registration active or inactive for all records.",
2161 0
2162 };
2163
rpc_uac_reg_active(rpc_t * rpc,void * ctx)2164 static void rpc_uac_reg_active(rpc_t* rpc, void* ctx)
2165 {
2166 int omode;
2167 int nmode;
2168 void* th;
2169
2170 if(reg_active==NULL) {
2171 rpc->fault(ctx, 500, "Not initialized");
2172 return;
2173 }
2174 if(rpc->scan(ctx, "d", &nmode)<1) {
2175 LM_ERR("missing parameter");
2176 rpc->fault(ctx, 500, "Missing parameter");
2177 return;
2178 }
2179 omode = *reg_active;
2180 *reg_active = (nmode)?1:0;
2181
2182 /* add entry node */
2183 if (rpc->add(ctx, "{", &th) < 0) {
2184 rpc->fault(ctx, 500, "Internal error creating rpc struct");
2185 return;
2186 }
2187 if(rpc->struct_add(th, "dd", "omode", omode, "nmode", nmode)<0) {
2188 rpc->fault(ctx, 500, "Internal error creating response");
2189 return;
2190 }
2191 }
2192
2193 rpc_export_t uac_reg_rpc[] = {
2194 {"uac.reg_dump", rpc_uac_reg_dump, rpc_uac_reg_dump_doc, RET_ARRAY},
2195 {"uac.reg_info", rpc_uac_reg_info, rpc_uac_reg_info_doc, 0},
2196 {"uac.reg_enable", rpc_uac_reg_enable, rpc_uac_reg_enable_doc, 0},
2197 {"uac.reg_disable", rpc_uac_reg_disable, rpc_uac_reg_disable_doc, 0},
2198 {"uac.reg_reload", rpc_uac_reg_reload, rpc_uac_reg_reload_doc, 0},
2199 {"uac.reg_refresh", rpc_uac_reg_refresh, rpc_uac_reg_refresh_doc, 0},
2200 {"uac.reg_remove", rpc_uac_reg_remove, rpc_uac_reg_remove_doc, 0},
2201 {"uac.reg_add", rpc_uac_reg_add, rpc_uac_reg_add_doc, 0},
2202 {"uac.reg_active", rpc_uac_reg_active, rpc_uac_reg_active_doc, 0},
2203 {0, 0, 0, 0}
2204 };
2205
uac_reg_init_rpc(void)2206 int uac_reg_init_rpc(void)
2207 {
2208 if (rpc_register_array(uac_reg_rpc)!=0)
2209 {
2210 LM_ERR("failed to register RPC commands\n");
2211 return -1;
2212 }
2213 return 0;
2214 }
2215