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(&regtotal, "uac", "regtotal", 0, 0, 0, "Total number of registration accounts in memory", 0);
178 	counter_register(&regactive, "uac", "regactive", 0, 0, 0, "Number of successfully registered accounts (200 OK)", 0);
179 	counter_register(&regdisabled, "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(&reg->l_uuid);
552 	nr->h_user = reg_compute_hash(&reg->l_username);
553 
554 	p = (char*)nr + sizeof(reg_uac_t);
555 
556 	reg_copy_shm(&nr->l_uuid, &reg->l_uuid, 0);
557 	reg_copy_shm(&nr->l_username, &reg->l_username, 0);
558 	reg_copy_shm(&nr->l_domain, &reg->l_domain, 0);
559 	reg_copy_shm(&nr->r_username, &reg->r_username, 0);
560 	reg_copy_shm(&nr->r_domain, &reg->r_domain, 0);
561 	reg_copy_shm(&nr->realm, &reg->realm, 0);
562 	reg_copy_shm(&nr->auth_proxy, &reg->auth_proxy, 0);
563 	reg_copy_shm(&nr->auth_username, &reg->auth_username, 0);
564 	reg_copy_shm(&nr->auth_password, &reg->auth_password, 0);
565 	reg_copy_shm(&nr->auth_ha1, &reg->auth_ha1, 0);
566 	reg_copy_shm(&nr->socket, &reg->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 = &reg->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)?&reg->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 		&reg_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(&reg_db_url, &reg_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(&reg_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(&reg_dbf, reg_db_con, &reg_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, &reg_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(&reg, db_res, i, db_cols) < 0)
1403 				continue;
1404 			if(reg_ht_add(&reg)<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 		&reg_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(&reg_db_url, &reg_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(&reg_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, &reg_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(&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(&reg)<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, &reg->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(&reg, 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",        &reg->l_uuid,
1846 				"l_username",    &reg->l_username,
1847 				"l_domain",      &reg->l_domain,
1848 				"r_username",    &reg->r_username,
1849 				"r_domain",      &reg->r_domain,
1850 				"realm",         &reg->realm,
1851 				"auth_username", &reg->auth_username,
1852 				"auth_password", (reg->auth_password.len)?
1853 										&reg->auth_password:&none,
1854 				"auth_ha1",      (reg->auth_ha1.len)?
1855 										&reg->auth_ha1:&none,
1856 				"auth_proxy",    (reg->auth_proxy.len)?
1857 										&reg->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",        &reg->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(&reg, &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(&reg, &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 				&reg.l_uuid,
2110 				&reg.l_username,
2111 				&reg.l_domain,
2112 				&reg.r_username,
2113 				&reg.r_domain,
2114 				&reg.realm,
2115 				&reg.auth_username,
2116 				&reg.auth_password,
2117 				&reg.auth_ha1,
2118 				&reg.auth_proxy,
2119 				&reg.expires,
2120 				&reg.flags,
2121 				&reg.reg_delay,
2122 				&reg.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(&reg) < 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(&reg.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(&reg);
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