Beispiel #1
0
/**
 * Initializes the Peer Manager.
 * The initial list of peers is taken from the configuration provided
 * @param config - configuration for initial peers
 * @returns 1
 */
int peer_manager_init(dp_config *config)
{
	int i;
	peer *p;
	LM_DBG("peer_manager_init(): Peer Manager initialization...\n");
	peer_list = shm_malloc(sizeof(peer_list_t));
	peer_list->head = 0;
	peer_list->tail = 0;
	peer_list_lock = lock_alloc();
	peer_list_lock = lock_init(peer_list_lock);

	hopbyhop_id = shm_malloc(sizeof(AAAMsgIdentifier));
	endtoend_id = shm_malloc(sizeof(AAAMsgIdentifier));
	msg_id_lock = lock_alloc();
	msg_id_lock = lock_init(msg_id_lock);

	kam_srand((unsigned int)time(0));
	*hopbyhop_id = kam_rand();
	*endtoend_id = (time(0)&0xFFF)<<20;
	*endtoend_id |= kam_rand() & 0xFFFFF;

	for(i=0;i<config->peers_cnt;i++){
		p = new_peer(config->peers[i].fqdn,config->peers[i].realm,config->peers[i].port,config->peers[i].src_addr);
		if (!p) continue;
		p->is_dynamic = 0;
		add_peer(p);
	}

	add_timer(1,0,&peer_timer,0);

	return 1;
}
Beispiel #2
0
/*
 * Secret parameter was not used so we generate
 * a random value here
 */
static inline int generate_random_secret(void)
{
	int i;

	sec_rand1 = (char*)pkg_malloc(RAND_SECRET_LEN);
	sec_rand2 = (char*)pkg_malloc(RAND_SECRET_LEN);
	if (!sec_rand1 || !sec_rand2) {
		LM_ERR("No memory left\n");
		if (sec_rand1){
			pkg_free(sec_rand1);
			sec_rand1=0;
		}
		return -1;
	}

	/* srandom(time(0));  -- seeded by core */

	for(i = 0; i < RAND_SECRET_LEN; i++) {
		sec_rand1[i] = 32 + (int)(95.0 * kam_rand() / (KAM_RAND_MAX + 1.0));
	}

	secret1.s = sec_rand1;
	secret1.len = RAND_SECRET_LEN;

	for(i = 0; i < RAND_SECRET_LEN; i++) {
		sec_rand2[i] = 32 + (int)(95.0 * kam_rand() / (KAM_RAND_MAX + 1.0));
	}

	secret2.s = sec_rand2;
	secret2.len = RAND_SECRET_LEN;

	/* DBG("Generated secret: '%.*s'\n", secret.len, secret.s); */

	return 0;
}
Beispiel #3
0
int select_sys_unique(str* res, select_t* s, struct sip_msg* msg) {
	#define UNIQUE_ID_PID_LEN 4
	#define UNIQUE_ID_TIME_LEN 8
	#define UNIQUE_ID_FIX_LEN (UNIQUE_ID_PID_LEN+1+UNIQUE_ID_TIME_LEN+1)
	#define UNIQUE_ID_RAND_LEN 8
	static char uniq_id[UNIQUE_ID_FIX_LEN+UNIQUE_ID_RAND_LEN];
	static int uniq_for_pid = -1;
	int i;

	if (uniq_for_pid != getpid()) {
		/* first call for this process */
		int cb, rb, x, l;
		char *c;
		/* init gloabally uniq part */
		c = int2str_base_0pad(getpid(), &l, 16, UNIQUE_ID_PID_LEN);
		memcpy(uniq_id, c, UNIQUE_ID_PID_LEN);
		uniq_id[UNIQUE_ID_PID_LEN] = '-';
		c = int2str_base_0pad(time(NULL), &l, 16, UNIQUE_ID_TIME_LEN);
		memcpy(uniq_id+UNIQUE_ID_PID_LEN+1, c, UNIQUE_ID_TIME_LEN);
		uniq_id[UNIQUE_ID_PID_LEN+1+UNIQUE_ID_TIME_LEN] = '-';

		/* init random part */
		for (i = KAM_RAND_MAX, rb=0; i; rb++, i>>=1);
		for (i = UNIQUE_ID_FIX_LEN, cb = 0, x = 0; i < UNIQUE_ID_FIX_LEN+UNIQUE_ID_RAND_LEN; i++) {
			if (!cb) {
				cb = rb;
				x = kam_rand();
			}
			uniq_id[i] = fourbits2char[x & 0x0F];
			x >>= rb;
			cb -= rb;
		}
		uniq_for_pid = getpid();
	}
Beispiel #4
0
/*!
 * \brief Initialize the global dialog table
 * \param size size of the table
 * \return 0 on success, -1 on failure
 */
int init_dlg_table(unsigned int size)
{
	unsigned int i;

	dlg_ka_list_head = (dlg_ka_t **)shm_malloc(sizeof(dlg_ka_t *));
	if(dlg_ka_list_head==NULL) {
		LM_ERR("no more shm mem (h)\n");
		goto error0;
	}
	dlg_ka_list_tail = (dlg_ka_t **)shm_malloc(sizeof(dlg_ka_t *));
	if(dlg_ka_list_tail==NULL) {
		LM_ERR("no more shm mem (t)\n");
		goto error0;
	}
	*dlg_ka_list_head = NULL;
	*dlg_ka_list_tail = NULL;
	dlg_ka_list_lock = (gen_lock_t*)shm_malloc(sizeof(gen_lock_t));
	if(dlg_ka_list_lock==NULL) {
		LM_ERR("no more shm mem (l)\n");
		goto error0;
	}
	lock_init(dlg_ka_list_lock);

	d_table = (struct dlg_table*)shm_malloc
		( sizeof(struct dlg_table) + size*sizeof(struct dlg_entry));
	if (d_table==0) {
		LM_ERR("no more shm mem (1)\n");
		goto error0;
	}

	memset( d_table, 0, sizeof(struct dlg_table) );
	d_table->size = size;
	d_table->entries = (struct dlg_entry*)(d_table+1);

	for( i=0 ; i<size; i++ ) {
		memset( &(d_table->entries[i]), 0, sizeof(struct dlg_entry) );
		if(lock_init(&d_table->entries[i].lock)<0) {
			LM_ERR("failed to init lock for slot: %d\n", i);
			goto error1;
		}
		d_table->entries[i].next_id = kam_rand() % (3*size);
	}

	return 0;
error1:
	shm_free( d_table );
	d_table = NULL;
error0:
	if(dlg_ka_list_head!=NULL)
		shm_free(dlg_ka_list_head);
	if(dlg_ka_list_tail!=NULL)
		shm_free(dlg_ka_list_tail);
	dlg_ka_list_head = NULL;
	dlg_ka_list_tail = NULL;
	return -1;
}
Beispiel #5
0
/*! \brief
 *  Return an expire value in the range [ default_expires - range%, default_expires + range% ]
 */
static inline int get_expire_val(void) {
	int expires = cfg_get(registrar, registrar_cfg, default_expires);
	int range = cfg_get(registrar, registrar_cfg, default_expires_range);
	/* if no range is given just return default_expires */
	if (range == 0)
		return expires;
	/* select a random value in the range */
	return expires - (float) range / 100 * expires
			+ (float) (kam_rand() % 100) / 100 * 2 * (float) range / 100 * expires;
}
Beispiel #6
0
/* \brief
 * Return randomized expires between expires-range% and expires.
 * RFC allows only value less or equal to the one provided by UAC.
 */
static inline int randomize_expires( int expires, int range )
{
	int range_min;

	/* if no range is given just return expires */
	if(range == 0)
		return expires;

	range_min = expires - (float)range/100 * expires;

	return range_min + (float)(kam_rand()%100)/100 * ( expires - range_min );
}
Beispiel #7
0
static int pl_drop(struct sip_msg * msg, unsigned int low, unsigned int high)
{
	str hdr;
	int ret;

	LM_DBG("(%d, %d)\n", low, high);

	if (slb.freply != 0) {
		if (low != 0 && high != 0) {
			hdr.s = (char *)pkg_malloc(64);
			if (hdr.s == 0) {
				LM_ERR("Can't allocate memory for Retry-After header\n");
				return 0;
			}
			hdr.len = 0;
			if (! hdr.s) {
				LM_ERR("no memory for hdr\n");
				return 0;
			}

			if (high == low) {
				hdr.len = snprintf(hdr.s, 63, "Retry-After: %d\r\n", low);
			} else {
				hdr.len = snprintf(hdr.s, 63, "Retry-After: %d\r\n", 
					low + kam_rand() % (high - low + 1));
			}

			if (add_lump_rpl(msg, hdr.s, hdr.len, LUMP_RPL_HDR)==0) {
				LM_ERR("Can't add header\n");
				pkg_free(hdr.s);
				return 0;
			}

			ret = slb.freply(msg, pl_drop_code, &pl_drop_reason);

			pkg_free(hdr.s);
		} else {
			ret = slb.freply(msg, pl_drop_code, &pl_drop_reason);
		}
	} else {
		LM_ERR("Can't send reply\n");
		return 0;
	}
	return ret;
}
Beispiel #8
0
static int pv_get_random_val(struct sip_msg *msg, pv_param_t *param,
		pv_value_t *res)
{
	int n;
	int l = 0;
	char *ch;

	if(msg==NULL || res==NULL)
		return -1;

	n = kam_rand();
	ch = int2str(n , &l);
	res->rs.s = ch;
	res->rs.len = l;
	res->ri = n;
	res->flags = PV_VAL_STR|PV_VAL_INT|PV_TYPE_INT;

	return 0;
}
Beispiel #9
0
static int rand_event(struct sip_msg *bar, char *foo1, char *foo2)
{
	double tmp;
	/* most of the time this will be disabled completly. Tis will also fix the
	 * problem with the corner cases if rand() returned zero or RAND_MAX */
	if ((*probability) == 0) return -1;
	if ((*probability) == 100) return 1;

	tmp = ((double) kam_rand() / KAM_RAND_MAX);
	LM_DBG("generated random %f\n", tmp);
	if (tmp < ((double) (*probability) / 100)) {
		LM_DBG("return true\n");
		return 1;
	}
	else {
		LM_DBG("return false\n");
		return -1;
	}
}
Beispiel #10
0
int xl_child_init(int rank)
{
	int i, x, rb, cb;

	for (i=KAM_RAND_MAX, rb=0; i; rb++, i>>=1);

	cb=x=0; /* x asiignment to make gcc happy */
	for (i=0; i<UNIQUE_ID_LEN; i++) {
		if (!cb) {
			cb=rb;
			x=kam_rand();
		}
		UNIQUE_ID[i]=fourbits2char[x&0x0F];
		x>>=rb;
		cb-=rb;
	}

	return 0;
}
Beispiel #11
0
/**
 * writes the uri dest using the flags and rule list of rf_head
 *
 * @param rf_head the head of the route flags list
 * @param flags user defined flags
 * @param dest the returned new destination URI
 * @param msg the sip message
 * @param user the localpart of the uri to be rewritten
 * @param hash_source the SIP header used for hashing
 * @param alg the algorithm used for hashing
 * @param descavp the name of the AVP where the description is stored
 *
 * @return 0 on success, -1 on failure, 1 on empty rule list
 */
static int rewrite_on_rule(struct route_flags *rf_head, flag_t flags, str * dest,
		struct sip_msg * msg, const str * user, const enum hash_source hash_source,
		const enum hash_algorithm alg, gparam_t *descavp) {
	struct route_flags * rf;
	struct route_rule * rr;
	int prob;

	assert(rf_head != NULL);

	LM_DBG("searching for matching routing rules");
	for (rf = rf_head; rf != NULL; rf = rf->next) {
		/* LM_DBG("actual flags %i, searched flags %i, mask %i and match %i", rf->flags, flags, rf->mask, flags&rf->mask); */
		if ((flags&rf->mask) == rf->flags) break;
	}

	if (rf==NULL) {
		LM_INFO("did not find a match for flags %d\n", flags);
		return -1;
	}

	if (rf->rule_list == NULL) {
		LM_INFO("empty rule list\n");
		return 1;
	}

	switch (alg) {
		case alg_crc32:
		{
			static avp_value_t used_dests[MAX_DESTINATIONS];
			static int no_dests = 0;
			avp_value_t cr_new_uri;

			if(rf->dice_max == 0) {
				LM_ERR("invalid dice_max value\n");
				return -1;
			}
			if ((prob = hash_func(msg, hash_source, rf->dice_max)) < 0) {
				LM_ERR("could not hash message with CRC32");
				return -1;
			}

			/* This auto-magically takes the last rule if anything is broken.
			 * Sometimes the hash result is zero. If the first rule is off
			 * (has a probablility of zero) then it has also a dice_to of
			 * zero and the message could not be routed at all if we use
			 * '<' here. Thus the '<=' is necessary.
			 *
			 * cr_uri_already_used is a function that checks that the selected
			 * rule has not been previously used as a failed destinatin
			 */

			for (rr = rf->rule_list;
				rr->next!= NULL && rr->dice_to <= prob ; rr = rr->next) {}

			//LM_DBG("CR: candidate hashed destination is: <%.*s>\n", rr->host.len, rr->host.s);
			if (cr_avoid_failed_dests) {
				if (is_route_type(FAILURE_ROUTE) && (mode == CARRIERROUTE_MODE_DB) ){
					build_used_uris_list(used_dests, &no_dests);

					if (cr_uri_already_used(rr->host, used_dests, no_dests) ) {
						//LM_DBG("CR: selecting new destination !!! \n");
						for (rr = rf->rule_list;
									rr!= NULL && cr_uri_already_used(rr->host, used_dests, no_dests); rr = rr->next) {}
						/* are there any destinations that were not already used? */
						if (rr == NULL) {
							LM_NOTICE("All gateways from this group were already used\n");
							return -1;
						}

						/* this is a hack: we do not take probabilities into consideration if first destination
						 * was previously tried */

						do {
							int rule_no = kam_rand() % rf->rule_num;
							//LM_DBG("CR: trying rule_no=%d \n", rule_no);
							for (rr = rf->rule_list; (rule_no > 0) && (rr->next!=NULL) ; rule_no-- , rr = rr->next) {}
						} while (cr_uri_already_used(rr->host, used_dests, no_dests));
						LM_DBG("CR: candidate selected destination is: <%.*s>\n", rr->host.len, rr->host.s);
					}
				}
			}
			/*This should be regarded as an ELSE branch for the if above
			 * ( status exists for mode == CARRIERROUTE_MODE_FILE */
			if (!rr->status) {
				if (!rr->backup) {
					LM_ERR("all routes are off\n");
					return -1;
				} else {
					if (!rr->backup->rr) {
						LM_ERR("all routes are off\n");
						return -1;
					}
					rr = rr->backup->rr;
				}
			}

			if (cr_avoid_failed_dests) {
				//LM_DBG("CR: destination is: <%.*s>\n", rr->host.len, rr->host.s);
				cr_new_uri.s = rr->host;
				/* insert used destination into avp, in case corresponding request fails and
				 * another destination has to be used; this new destination must not be one
				 * that failed before
				 */

				if (mode == CARRIERROUTE_MODE_DB){
					if ( add_avp( AVP_VAL_STR | AVP_NAME_STR, cr_uris_avp, cr_new_uri) < 0){
						LM_ERR("set AVP failed\n");
						return -1;
					}
					//print_cr_uri_avp();
				}
			}
			break;
		}
		case alg_crc32_nofallback:
			if ((prob = (hash_func(msg, hash_source, rf->max_targets))) < 0) {
				LM_ERR("could not hash message with CRC32");
				return -1;
			}
			/* Instead of search the whole rule_list if there is something broken
			 * this function just tries only a backup rule and otherwise
			 * returns -1. This way we get an error
			 */
			if ((rr = get_rule_by_hash(rf, prob + 1)) == NULL) {
				LM_CRIT("no route found\n");
				return -1;
			}
			break;
		default:
			LM_ERR("invalid hash algorithm\n");
			return -1;
	}
	return actually_rewrite(rr, dest, msg, user, descavp);
}
Beispiel #12
0
int fork_tcp_process(int child_id, char *desc, int r, int *reader_fd_1)
{
	int pid, child_process_no;
	int sockfd[2];
	int reader_fd[2]; /* for comm. with the tcp children read  */
	int ret;
	int i;
	unsigned int new_seed1;
	unsigned int new_seed2;

	/* init */
	sockfd[0]=sockfd[1]=-1;
	reader_fd[0]=reader_fd[1]=-1;
	ret=-1;

	if (!is_main){
		LM_CRIT("called from a non \"main\" process\n");
		goto error;
	}
	if (tcp_main_pid){
		LM_CRIT("called _after_ starting tcp main\n");
		goto error;
	}
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
		LM_ERR("socketpair failed: %s\n", strerror(errno));
		goto error;
	}
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, reader_fd)<0){
		LM_ERR("socketpair failed: %s\n", strerror(errno));
		goto error;
	}
	if (tcp_fix_child_sockets(reader_fd)<0){
		LM_ERR("failed to set non blocking on child sockets\n");
		/* continue, it's not critical (it will go slower under
		 * very high connection rates) */
	}
	lock_get(process_lock);
	/* set the local process_no */
	if (*process_count>=estimated_proc_no) {
		LM_CRIT("Process limit of %d exceeded. Simulating fork fail\n",
					estimated_proc_no);
		lock_release(process_lock);
		goto error;
	}

	child_process_no = *process_count;
	new_seed1=kam_rand();
	new_seed2=random();
	pid = fork();
	if (pid<0) {
		lock_release(process_lock);
		ret=pid;
		goto end;
	}
	if (pid==0){
		is_main=0; /* a forked process cannot be the "main" one */
		process_no=child_process_no;
		/* close unneeded unix sockets */
		close_extra_socks(child_id, process_no);
		/* same for unneeded tcp_children <-> tcp_main unix socks */
		for (i=0; i<r; i++){
			if (tcp_children[i].unix_sock>=0){
				close(tcp_children[i].unix_sock);
				/* tcp_children is per process, so it's safe to change
				 * the unix_sock to -1 */
				tcp_children[i].unix_sock=-1;
			}
		}
		daemon_status_on_fork_cleanup();
		kam_srand(new_seed1);
		fastrand_seed(kam_rand());
		srandom(new_seed2+time(0));
		shm_malloc_on_fork();
#ifdef PROFILING
		monstartup((u_long) &_start, (u_long) &etext);
#endif
#ifdef FORK_DONT_WAIT
		/* record pid twice to avoid the child using it, before
-		 * parent gets a chance to set it*/
		pt[process_no].pid=getpid();
#else
		/* wait for parent to get out of critical zone */
		lock_get(process_lock);
		lock_release(process_lock);
#endif
		close(sockfd[0]);
		unix_tcp_sock=sockfd[1];
		close(reader_fd[0]);
		if (reader_fd_1) *reader_fd_1=reader_fd[1];
		if ((child_id!=PROC_NOCHLDINIT) && (init_child(child_id) < 0)) {
			LM_ERR("init_child failed for process %d, pid %d, \"%s\"\n",
				process_no, pt[process_no].pid, pt[process_no].desc);
			return -1;
		}
		return pid;
	} else {
		/* parent */
		(*process_count)++;
#ifdef FORK_DONT_WAIT
		lock_release(process_lock);
#endif
		/* add the process to the list in shm */
		pt[child_process_no].pid=pid;
		pt[child_process_no].unix_sock=sockfd[0];
		pt[child_process_no].idx=r;
		if (desc){
			snprintf(pt[child_process_no].desc, MAX_PT_DESC, "%s child=%d",
						desc, r);
		}
#ifdef FORK_DONT_WAIT
#else
		lock_release(process_lock);
#endif

		close(sockfd[1]);
		close(reader_fd[1]);

		tcp_children[r].pid=pid;
		tcp_children[r].proc_no=child_process_no;
		tcp_children[r].busy=0;
		tcp_children[r].n_reqs=0;
		tcp_children[r].unix_sock=reader_fd[0];

		ret=pid;
		goto end;
	}
error:
	if (sockfd[0]!=-1) close(sockfd[0]);
	if (sockfd[1]!=-1) close(sockfd[1]);
	if (reader_fd[0]!=-1) close(reader_fd[0]);
	if (reader_fd[1]!=-1) close(reader_fd[1]);
end:
	return ret;
}
Beispiel #13
0
/**
 * Forks a new process.
 * @param child_id - rank, if equal to PROC_NOCHLDINIT init_child will not be
 *                   called for the new forked process (see sr_module.h)
 * @param desc - text description for the process table
 * @param make_sock - if to create a unix socket pair for it
 * @returns the pid of the new process
 */
int fork_process(int child_id, char *desc, int make_sock)
{
	int pid, child_process_no;
	int ret;
	unsigned int new_seed1;
	unsigned int new_seed2;
#ifdef USE_TCP
	int sockfd[2];
#endif

	if(unlikely(fork_delay>0))
		sleep_us(fork_delay);

	ret=-1;
	#ifdef USE_TCP
		sockfd[0]=sockfd[1]=-1;
		if(make_sock && !tcp_disable){
			if (!is_main){
				LM_CRIT("called from a non "
						"\"main\" process! If forking from a module's "
						"child_init() fork only if rank==PROC_MAIN or"
						" give up tcp send support (use 0 for make_sock)\n");
				goto error;
			}
			if (tcp_main_pid){
				LM_CRIT("called, but tcp main is already started\n");
				goto error;
			}
			if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockfd)<0){
				LM_ERR("socketpair failed: %s\n",
							strerror(errno));
				goto error;
			}
		}
	#endif
	lock_get(process_lock);
	if (*process_count>=estimated_proc_no) {
		LM_CRIT("Process limit of %d exceeded. Will simulate fork fail.\n",
				estimated_proc_no);
		lock_release(process_lock);
		goto error;
	}

	child_process_no = *process_count;
	new_seed1=kam_rand();
	new_seed2=random();
	pid = fork();
	if (pid<0) {
		lock_release(process_lock);
		ret=pid;
		goto error;
	}else if (pid==0){
		/* child */
		is_main=0; /* a forked process cannot be the "main" one */
		process_no=child_process_no;
		daemon_status_on_fork_cleanup();
		/* close tcp unix sockets if this is not tcp main */
#ifdef USE_TCP
		close_extra_socks(child_id, process_no);
#endif /* USE_TCP */
		kam_srand(new_seed1);
		fastrand_seed(kam_rand());
		srandom(new_seed2+time(0));
		shm_malloc_on_fork();
#ifdef PROFILING
		monstartup((u_long) &_start, (u_long) &etext);
#endif
#ifdef FORK_DONT_WAIT
		/* record pid twice to avoid the child using it, before
		 * parent gets a chance to set it*/
		pt[process_no].pid=getpid();
#else
		/* wait for parent to get out of critical zone.
		 * this is actually relevant as the parent updates
		 * the pt & process_count. */
		lock_get(process_lock);
		lock_release(process_lock);
#endif
		#ifdef USE_TCP
			if (make_sock && !tcp_disable){
				close(sockfd[0]);
				unix_tcp_sock=sockfd[1];
			}
		#endif
		if ((child_id!=PROC_NOCHLDINIT) && (init_child(child_id) < 0)) {
			LM_ERR("init_child failed for process %d, pid %d, \"%s\"\n",
					process_no, pt[process_no].pid, pt[process_no].desc);
			return -1;
		}
		return pid;
	} else {
		/* parent */
		(*process_count)++;
#ifdef FORK_DONT_WAIT
		lock_release(process_lock);
#endif
		/* add the process to the list in shm */
		pt[child_process_no].pid=pid;
		if (desc){
			strncpy(pt[child_process_no].desc, desc, MAX_PT_DESC-1);
		}
		#ifdef USE_TCP
			if (make_sock && !tcp_disable){
				close(sockfd[1]);
				pt[child_process_no].unix_sock=sockfd[0];
				pt[child_process_no].idx=-1; /* this is not a "tcp" process*/
			}
		#endif
#ifdef FORK_DONT_WAIT
#else
		lock_release(process_lock);
#endif
		ret=pid;
		goto end;
	}
error:
#ifdef USE_TCP
	if (sockfd[0]!=-1) close(sockfd[0]);
	if (sockfd[1]!=-1) close(sockfd[1]);
#endif
end:
	return ret;
}
Beispiel #14
0
static int update_pw_dialogs_dbonlymode(subs_t* subs, subs_t** subs_array)
{
	db_key_t query_cols[5], db_cols[3];
	db_val_t query_vals[5], db_vals[3];
	db_key_t result_cols[26];
	int n_query_cols=0, n_result_cols=0, n_update_cols=0;
	int event_col, pres_uri_col, watcher_user_col, watcher_domain_col;
	int r_pres_uri_col,r_to_user_col,r_to_domain_col;
	int r_from_user_col,r_from_domain_col,r_callid_col;
	int r_to_tag_col,r_from_tag_col,r_sockinfo_col;
	int r_event_id_col,r_local_contact_col,r_contact_col;
	int r_record_route_col, r_reason_col;
	int r_event_col, r_local_cseq_col, r_remote_cseq_col;
	int r_status_col, r_version_col;
	int r_expires_col, r_watcher_user_col, r_watcher_domain_col;
	int r_flags_col, r_user_agent_col;
	db1_res_t *result= NULL;
	db_val_t *row_vals;
	db_row_t *rows;
	int nr_rows, loop;
	subs_t s, *cs;
	str ev_sname;

	if(pa_db == NULL)
	{
		LM_ERR("null database connection\n");
		return(-1);
	}

	if (pa_dbf.use_table(pa_db, &active_watchers_table) < 0)
	{
		LM_ERR("use table failed\n");
		return(-1);
	}

	query_cols[event_col=n_query_cols]= &str_event_col;
	query_vals[event_col].nul= 0;
	query_vals[event_col].type= DB1_STR;
	query_vals[event_col].val.str_val= subs->event->name ;
	n_query_cols++;

	query_cols[pres_uri_col=n_query_cols]= &str_presentity_uri_col;
	query_vals[pres_uri_col].nul= 0;
	query_vals[pres_uri_col].type= DB1_STR;
	query_vals[pres_uri_col].val.str_val= subs->pres_uri;
	n_query_cols++;

	query_cols[watcher_user_col=n_query_cols]= &str_watcher_username_col;
	query_vals[watcher_user_col].nul= 0;
	query_vals[watcher_user_col].type= DB1_STR;
	query_vals[watcher_user_col].val.str_val= subs->watcher_user;
	n_query_cols++;

	query_cols[watcher_domain_col=n_query_cols]= &str_watcher_domain_col;
	query_vals[watcher_domain_col].nul= 0;
	query_vals[watcher_domain_col].type= DB1_STR;
	query_vals[watcher_domain_col].val.str_val= subs->watcher_domain;
	n_query_cols++;


	result_cols[r_to_user_col=n_result_cols++] = &str_to_user_col;
	result_cols[r_to_domain_col=n_result_cols++] = &str_to_domain_col;
	result_cols[r_from_user_col=n_result_cols++] = &str_from_user_col;
	result_cols[r_from_domain_col=n_result_cols++] = &str_from_domain_col;
	result_cols[r_watcher_user_col=n_result_cols++] = &str_watcher_username_col;
	result_cols[r_watcher_domain_col=n_result_cols++] = &str_watcher_domain_col;
	result_cols[r_callid_col=n_result_cols++] = &str_callid_col;
	result_cols[r_to_tag_col=n_result_cols++] = &str_to_tag_col;
	result_cols[r_from_tag_col=n_result_cols++] = &str_from_tag_col;
	result_cols[r_sockinfo_col=n_result_cols++] = &str_socket_info_col;
	result_cols[r_event_id_col=n_result_cols++] = &str_event_id_col;
	result_cols[r_local_contact_col=n_result_cols++] = &str_local_contact_col;
	result_cols[r_record_route_col=n_result_cols++] = &str_record_route_col;
	result_cols[r_reason_col=n_result_cols++] = &str_reason_col;
	result_cols[r_local_cseq_col=n_result_cols++] = &str_local_cseq_col;
	result_cols[r_version_col=n_result_cols++] = &str_version_col;
	result_cols[r_expires_col=n_result_cols++] = &str_expires_col;
	result_cols[r_event_col=n_result_cols++] = &str_event_col;
	result_cols[r_pres_uri_col=n_result_cols++] = &str_presentity_uri_col;
	result_cols[r_contact_col=n_result_cols++] = &str_contact_col;

	/* these ones are unused for some reason !!! */
	result_cols[r_remote_cseq_col=n_result_cols++] = &str_remote_cseq_col;
	result_cols[r_status_col=n_result_cols++] = &str_status_col;
	/*********************************************/

	result_cols[r_flags_col=n_result_cols++] = &str_flags_col;
	result_cols[r_user_agent_col=n_result_cols++] = &str_user_agent_col;

	if(pa_dbf.query(pa_db, query_cols, 0, query_vals, result_cols,
				n_query_cols, n_result_cols, 0, &result )< 0)
	{
		LM_ERR("Can't query db\n");
		if(result) pa_dbf.free_result(pa_db, result);
		return(-1);
	}

	if(result == NULL) return(-1);

	nr_rows = RES_ROW_N(result);

	LM_DBG("found %d matching dialogs\n", nr_rows);

	if (nr_rows <= 0)
	{
		pa_dbf.free_result(pa_db, result);
		return 0;
	}

	rows = RES_ROWS(result);
	/* get the results and fill in return data structure */
	for (loop=0; loop <nr_rows; loop++)
	{
		row_vals = ROW_VALUES(&rows[loop]);

		memset(&s, 0, sizeof(subs_t));
		s.status= subs->status;

		s.reason.s= subs->reason.s;
		s.reason.len= s.reason.s?strlen(s.reason.s):0;	//>>>>>>>>>>

		s.pres_uri.s= (char*)row_vals[r_pres_uri_col].val.string_val;
		s.pres_uri.len= s.pres_uri.s?strlen(s.pres_uri.s):0;

		s.to_user.s= (char*)row_vals[r_to_user_col].val.string_val;
		s.to_user.len= s.to_user.s?strlen(s.to_user.s):0;

		s.to_domain.s= (char*)row_vals[r_to_domain_col].val.string_val;
		s.to_domain.len= s.to_domain.s?strlen(s.to_domain.s):0;

		s.from_user.s= (char*)row_vals[r_from_user_col].val.string_val;
		s.from_user.len= s.from_user.s?strlen(s.from_user.s):0;

		s.from_domain.s= (char*)row_vals[r_from_domain_col].val.string_val;
		s.from_domain.len= s.from_domain.s?strlen(s.from_domain.s):0;

		s.watcher_user.s= (char*)row_vals[r_watcher_user_col].val.string_val;
		s.watcher_user.len= s.watcher_user.s?strlen(s.watcher_user.s):0;

		s.watcher_domain.s= (char*)row_vals[r_watcher_domain_col].val.string_val;
		s.watcher_domain.len= s.watcher_domain.s?strlen(s.watcher_domain.s):0;

		s.event_id.s=(char*)row_vals[r_event_id_col].val.string_val;
		s.event_id.len= (s.event_id.s)?strlen(s.event_id.s):0;

		s.to_tag.s= (char*)row_vals[r_to_tag_col].val.string_val;
		s.to_tag.len= s.to_tag.s?strlen(s.to_tag.s):0;

		s.from_tag.s= (char*)row_vals[r_from_tag_col].val.string_val;
		s.from_tag.len= s.from_tag.s?strlen(s.from_tag.s):0;

		s.callid.s= (char*)row_vals[r_callid_col].val.string_val;
		s.callid.len= s.callid.s?strlen(s.callid.s):0;

		s.record_route.s=  (char*)row_vals[r_record_route_col].val.string_val;
		s.record_route.len= (s.record_route.s)?strlen(s.record_route.s):0;

		s.contact.s= (char*)row_vals[r_contact_col].val.string_val;
		s.contact.len= s.contact.s?strlen(s.contact.s):0;

		s.sockinfo_str.s = (char*)row_vals[r_sockinfo_col].val.string_val;
		s.sockinfo_str.len = s.sockinfo_str.s?strlen(s.sockinfo_str.s):0;

		s.local_contact.s = (char*)row_vals[r_local_contact_col].val.string_val;
		s.local_contact.len = s.local_contact.s?strlen(s.local_contact.s):0;

		ev_sname.s= (char*)row_vals[r_event_col].val.string_val;
		ev_sname.len= ev_sname.s?strlen(ev_sname.s):0;

		s.event = contains_event(&ev_sname, NULL);

		if(s.event == NULL)
		{
			LM_ERR("event not found and set to NULL\n");
		}

		s.local_cseq = row_vals[r_local_cseq_col].val.int_val;

		s.expires = row_vals[r_expires_col].val.int_val;

		if( s.expires > (int)time(NULL) + expires_offset)
			s.expires -= (int)time(NULL);
		else
			s.expires = 0;

		s.version = row_vals[r_version_col].val.int_val;

		s.flags = row_vals[r_flags_col].val.int_val;
		s.user_agent.s=  (char*)row_vals[r_user_agent_col].val.string_val;
		s.user_agent.len= (s.user_agent.s)?strlen(s.user_agent.s):0;


		cs = mem_copy_subs(&s, PKG_MEM_TYPE);
		if (cs == NULL)
		{
			LM_ERR("while copying subs_t structure\n");
			/* tidy up and return */
			pa_dbf.free_result(pa_db, result);
			return(-1);
		}
		cs->local_cseq++;
		cs->next= (*subs_array);
		(*subs_array)= cs;

		printf_subs(cs);
	}

	pa_dbf.free_result(pa_db, result);

	if (pres_notifier_processes == 0 && subs->status == TERMINATED_STATUS)
	{
		/* delete the records */
		if(pa_dbf.delete(pa_db, query_cols, 0, query_vals, n_query_cols)< 0)
		{
			LM_ERR("sql delete failed\n");
			return(-1);
		}

		return(0);
	}

	/* otherwise we update the records */
	db_cols[n_update_cols] = &str_status_col;
	db_vals[n_update_cols].type = DB1_INT;
	db_vals[n_update_cols].nul = 0;
	db_vals[n_update_cols].val.int_val = subs->status;
	n_update_cols++;

	db_cols[n_update_cols] = &str_reason_col;
	db_vals[n_update_cols].type = DB1_STR;
	db_vals[n_update_cols].nul = 0;
	db_vals[n_update_cols].val.str_val= subs->reason;
	n_update_cols++;

	db_cols[n_update_cols] = &str_updated_col;
	db_vals[n_update_cols].type = DB1_INT;
	db_vals[n_update_cols].nul = 0;
	if (subs->callid.len == 0 || subs->from_tag.len == 0)
	{
		db_vals[n_update_cols].val.int_val = (int) ((kam_rand() / (KAM_RAND_MAX + 1.0)) *
				(pres_waitn_time * pres_notifier_poll_rate
				 * pres_notifier_processes));
	} else {
		db_vals[n_update_cols].val.int_val =
			core_case_hash(&subs->callid, &subs->from_tag, 0) %
			(pres_waitn_time * pres_notifier_poll_rate
			 * pres_notifier_processes);
	}
	n_update_cols++;

	if(pa_dbf.update(pa_db, query_cols, 0, query_vals,
				db_cols,db_vals,n_query_cols,n_update_cols) < 0)
	{
		LM_ERR("DB update failed\n");
		return(-1);
	}

	return(0);
}