Beispiel #1
0
/*
 * Return true if the AOR in the Request-URI is registered,
 * it is similar to lookup but registered neither rewrites
 * the Request-URI nor appends branches
 */
int registered(struct sip_msg* _m, char* _t, char* _s)
{
	str uid;
	urecord_t* r;
        ucontact_t* ptr;
	int res;

	if (get_to_uid(&uid, _m) < 0) return -1;

	ul.lock_udomain((udomain_t*)_t);
	res = ul.get_urecord((udomain_t*)_t, &uid, &r);

	if (res < 0) {
		ul.unlock_udomain((udomain_t*)_t);
		LOG(L_ERR, "registered(): Error while querying usrloc\n");
		return -1;
	}

	if (res == 0) {
		ptr = r->contacts;
		while (ptr && !VALID_CONTACT(ptr, act_time)) {
			ptr = ptr->next;
		}

		if (ptr) {
			ul.unlock_udomain((udomain_t*)_t);
			DBG("registered(): '%.*s' found in usrloc\n", uid.len, ZSW(uid.s));
			return 1;
		}
	}

	ul.unlock_udomain((udomain_t*)_t);
	DBG("registered(): '%.*s' not found in usrloc\n", uid.len, ZSW(uid.s));
	return -1;
}
Beispiel #2
0
/*! \brief
 * Calculate the length of buffer needed to
 * print contacts
 */
static inline unsigned int calc_buf_len(ucontact_t* c)
{
	unsigned int len;
	int qlen;

	len = 0;
	while(c) {
		if (VALID_CONTACT(c, act_time)) {
			if (len) len += CONTACT_SEP_LEN;
			len += 2 /* < > */ + c->c.len;
			qlen = len_q(c->q);
			if (qlen) len += Q_PARAM_LEN + qlen;
			len += EXPIRES_PARAM_LEN + INT2STR_MAX_LEN;
			if (c->received.s) {
				len += 1 /* ; */ 
					+ rcv_param.len 
					+ 1 /* = */ 
					+ 1 /* dquote */ 
					+ c->received.len
					+ 1 /* dquote */
					;
			}
		}
		c = c->next;
	}

	if (len) len += CONTACT_BEGIN_LEN + CRLF_LEN;
	return len;
}
Beispiel #3
0
/*!
 * \brief Write through timer, used for WRITE_THROUGH db_mode
 *
 * Write through timer, used for WRITE_THROUGH db_mode. Process all
 * contacts from the record, delete all expired ones from the DB.
 * \param _r processed record
 * \note currently unused, this mode is also handled by the wb_timer
 */
static inline void wt_timer(urecord_t* _r)
{
	ucontact_t* ptr, *t;

	ptr = _r->contacts;

	while(ptr) {
		if (!VALID_CONTACT(ptr, act_time)) {
			/* run callbacks for EXPIRE event */
			if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {
				run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
			}

			LM_DBG("Binding '%.*s','%.*s' has expired\n",
				ptr->aor->len, ZSW(ptr->aor->s),
				ptr->c.len, ZSW(ptr->c.s));

			t = ptr;
			ptr = ptr->next;

			if (db_delete_ucontact(t) < 0) {
				LM_ERR("deleting contact from database failed\n");
			}
			mem_delete_ucontact(_r, t);
			update_stat( _r->slot->d->expires, 1);
		} else {
			ptr = ptr->next;
		}
	}
}
Beispiel #4
0
/*! \brief
 * Calculate the length of buffer needed to
 * print contacts
 */
static inline unsigned int calc_buf_len(impurecord_t* impurec) {
    unsigned int len;
    int qlen;
    int i=0;
    ucontact_t* c;

    len = 0;
    while (i<MAX_CONTACTS_PER_IMPU && (c=impurec->newcontacts[i])) {
        if (VALID_CONTACT(c, act_time)) {
            if (len) len += CONTACT_SEP_LEN;
            len += 2 /* < > */ + c->c.len;
            qlen = len_q(c->q);
            if (qlen) len += Q_PARAM_LEN + qlen;
            len += EXPIRES_PARAM_LEN + INT2STR_MAX_LEN;
            if (c->received.s) {
                len += 1 /* ; */
                        + rcv_param.len
                        + 1 /* = */
                        + 1 /* dquote */
                        + c->received.len
                        + 1 /* dquote */
                        ;
            }
        }
	i++;
    }

    if (len) len += CONTACT_BEGIN_LEN + CRLF_LEN;
    return len;
}
Beispiel #5
0
/*!
 * \brief Write-back timer, used for WRITE_BACK db_mode
 *
 * Write-back timer, used for WRITE_BACK db_mode. Process
 * all contacts from the record, delete expired ones from the DB.
 * Furthermore it updates changed contacts, and also insert new
 * ones in the DB.
 * \param _r processed record
 */
static inline void wb_timer(urecord_t* _r)
{
	ucontact_t* ptr, *t;
	cstate_t old_state;
	int op;

	ptr = _r->contacts;

	while(ptr) {
		if (!VALID_CONTACT(ptr, act_time)) {
			/* run callbacks for EXPIRE event */
			if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {
				run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
			}

			LM_DBG("Binding '%.*s','%.*s' has expired\n",
				ptr->aor->len, ZSW(ptr->aor->s),
				ptr->c.len, ZSW(ptr->c.s));
			update_stat( _r->slot->d->expires, 1);

			t = ptr;
			ptr = ptr->next;

			/* Should we remove the contact from the database ? */
			if (st_expired_ucontact(t) == 1) {
				if (db_delete_ucontact(t) < 0) {
					LM_ERR("failed to delete contact from the database\n");
				}
			}

			mem_delete_ucontact(_r, t);
		} else {
			/* Determine the operation we have to do */
			old_state = ptr->state;
			op = st_flush_ucontact(ptr);

			switch(op) {
			case 0: /* do nothing, contact is synchronized */
				break;

			case 1: /* insert */
				if (db_insert_ucontact(ptr) < 0) {
					LM_ERR("inserting contact into database failed\n");
					ptr->state = old_state;
				}
				break;

			case 2: /* update */
				if (db_update_ucontact(ptr) < 0) {
					LM_ERR("updating contact in db failed\n");
					ptr->state = old_state;
				}
				break;
			}

			ptr = ptr->next;
		}
	}
}
Beispiel #6
0
/*! \brief the is_registered() function
 * Return true if the AOR in the Request-URI is registered,
 * it is similar to lookup but registered neither rewrites
 * the Request-URI nor appends branches
 */
int registered(struct sip_msg* _m, udomain_t* _d, str* _uri)
{
	str uri, aor;
	urecord_t* r;
	ucontact_t* ptr;
	int res;
	int_str match_callid=(int_str)0;

	if(_uri!=NULL)
	{
		uri = *_uri;
	} else {
		if (_m->new_uri.s) uri = _m->new_uri;
		else uri = _m->first_line.u.request.uri;
	}
	
	if (extract_aor(&uri, &aor, NULL) < 0) {
		LM_ERR("failed to extract address of record\n");
		return -1;
	}
	
	ul.lock_udomain(_d, &aor);
	res = ul.get_urecord(_d, &aor, &r);

	if (res < 0) {
		ul.unlock_udomain(_d, &aor);
		LM_ERR("failed to query usrloc\n");
		return -1;
	}

	if (res == 0) {
		
		if (reg_callid_avp_name.n) {
			struct usr_avp *avp =
				search_first_avp( reg_callid_avp_type, reg_callid_avp_name, &match_callid, 0);
			if (!(avp && is_avp_str_val(avp)))
				match_callid.n = 0;
				match_callid.s.s = NULL;
		} else {
			match_callid.n = 0;
			match_callid.s.s = NULL;
		}

		for (ptr = r->contacts; ptr; ptr = ptr->next) {
			if(!VALID_CONTACT(ptr, act_time)) continue;
			if (match_callid.s.s && /* optionally enforce tighter matching w/ Call-ID */
				memcmp(match_callid.s.s,ptr->callid.s,match_callid.s.len))
				continue;
			ul.release_urecord(r);
			ul.unlock_udomain(_d, &aor);
			LM_DBG("'%.*s' found in usrloc\n", aor.len, ZSW(aor.s));
			return 1;
		}
	}

	ul.unlock_udomain(_d, &aor);
	LM_DBG("'%.*s' not found in usrloc\n", aor.len, ZSW(aor.s));
	return -1;
}
Beispiel #7
0
static int test_max_contacts(struct sip_msg* _m, urecord_t* _r, contact_t* _c,
		ucontact_info_t *ci, int mc)
{
	int num;
	int e;
	ucontact_t* ptr, *cont;
	int ret;

	num = 0;
	ptr = _r->contacts;
	while(ptr) {
		if (VALID_CONTACT(ptr, act_time)) {
			num++;
		}
		ptr = ptr->next;
	}
	LM_DBG("%d valid contacts\n", num);

	for( ; _c ; _c = get_next_contact(_c) ) {
		/* calculate expires */
		calc_contact_expires(_m, _c->expires, &e);

		ret = ul.get_ucontact_by_instance( _r, &_c->uri, ci, &cont);
		if (ret==-1) {
			LM_ERR("invalid cseq for aor <%.*s>\n",_r->aor.len,_r->aor.s);
			rerrno = R_INV_CSEQ;
			return -1;
		} else if (ret==-2) {
			continue;
		}
		if (ret > 0) {
			/* Contact not found */
			if (e != 0) num++;
		} else {
			if (e == 0) num--;
		}
	}

	LM_DBG("%d contacts after commit\n", num);
	if (num > mc) {
		LM_INFO("too many contacts for AOR <%.*s>\n", _r->aor.len, _r->aor.s);
		rerrno = R_TOO_MANY;
		return -1;
	}

	return 0;
}
Beispiel #8
0
/**
 * Check that the IMPU at the Term S has at least one valid contact...
 * @param _m - msg
 * @param _t - t
 * @param _s - s
 * @return true if there is at least one valid contact. false if not
 */
int term_impu_has_contact(struct sip_msg* _m, udomain_t* _d, char* _s) {
    impurecord_t* r;
    str aor, uri;
    ucontact_t* ptr;
    int res;
    int ret;
    int i = 0;

    if (_m->new_uri.s) uri = _m->new_uri;
    else uri = _m->first_line.u.request.uri;

    if (extract_aor(&uri, &aor) < 0) {
        LM_ERR("failed to extract address of record\n");
        return -3;
    }

    get_act_time();

    ul.lock_udomain(_d, &aor);
    res = ul.get_impurecord(_d, &aor, &r);
    if (res != 0) {
        LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
        ul.unlock_udomain(_d, &aor);
        return -1;
    }

    while (i < MAX_CONTACTS_PER_IMPU && (ptr = r->newcontacts[i])) {
        if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) {
            LM_DBG("Found a valid contact [%.*s]\n", ptr->c.len, ptr->c.s);
            i++;
            ret = 1;
            break;
        }
        i++;
    }

    /* look first for an un-expired and supported contact */
    if (ptr == 0) {
        /* nothing found */
        ret = -1;
    }

    ul.unlock_udomain(_d, &aor);

    return ret;
}
Beispiel #9
0
/*
 * This routine is used when db_mode is
 * set to WRITE_THROUGH
 */
static inline int wt_timer(urecord_t* _r)
{
	ucontact_t* ptr, *t;
	int not = 0;
	
	ptr = _r->contacts;
	
	while(ptr) {
		if (!VALID_CONTACT(ptr, act_time)) {
			/* run callbacks for EXPIRE event */
			if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {
				run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
			}

			notify_watchers(_r, ptr, PRES_OFFLINE);

			LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n",
			    ptr->uid->len, ZSW(ptr->uid->s),
			    ptr->c.len, ZSW(ptr->c.s));
			
			t = ptr;
			ptr = ptr->next;
			
			     /* it was the last contact and it was in normal
			      * state, so notify */
			if (!ptr && t->state == CS_SYNC) not=1;
		
			if (db_delete_ucontact(t) < 0) {
				LOG(L_ERR, "wt_timer(): Error while deleting contact from "
				    "database\n");
			}

			delete_reg_avps(t);			
			mem_delete_ucontact(_r, t);
			_r->slot->d->expired++;
		} else {
			     /* the contact was unregistered and is not marked 
			      * for replication so remove it, but the notify was
			      * already done during unregister */
			ptr = ptr->next;
		}
	}
	
	return 0;
}
Beispiel #10
0
/*!
+ * \brief Match a contact record to a contact string and path
+ * \param ptr contact record
+ * \param _c contact string
+ * \param _path path
+ * \return ptr on successfull match, 0 when they not match
+ */
static inline struct ucontact* contact_path_match(unsigned int slot, str* _c, str *_path) {
    ucontact_t* ptr = contact_list->slot[slot].first;
    /* if no path is preset (in REGISTER request) or use_path is not configured
       in registrar module, default to contact_match() */
    if (_path == NULL) return contact_match(slot, _c);

    while (ptr) {
        if ((_c->len == ptr->c.len) && (_path->len == ptr->path.len)
                && !memcmp(_c->s, ptr->c.s, _c->len)
                && !memcmp(_path->s, ptr->path.s, _path->len)
                && VALID_CONTACT(ptr, act_time)
           ) {
            return ptr;
        }

        ptr = ptr->next;
    }
    return 0;
}
Beispiel #11
0
int lookup_path_to_contact(struct sip_msg* _m, char* contact_uri) {
    ucontact_t* contact;
    str s_contact_uri;
    str path_dst;

    get_act_time();
    if (get_str_fparam(&s_contact_uri, _m, (fparam_t*) contact_uri) < 0) {
        LM_ERR("failed to get RURI\n");
        return -1;
    }
    LM_DBG("Looking up contact [%.*s]\n", s_contact_uri.len, s_contact_uri.s);

    if (ul.get_ucontact(NULL, &s_contact_uri, 0, 0, 0, &contact) == 0) { //get_contact returns with lock

        if (!VALID_CONTACT(contact, act_time)) {
            LM_DBG("Contact is not valid...ignoring\n");
            ul.release_ucontact(contact);
        } else {
            LM_DBG("CONTACT FOUND and path is [%.*s]\n", contact->path.len, contact->path.s);

            if (get_path_dst_uri(&contact->path, &path_dst) < 0) {
                LM_ERR("failed to get dst_uri for Path\n");
                ul.release_ucontact(contact);
                return -1;
            }
            if (set_path_vector(_m, &contact->path) < 0) {
                LM_ERR("failed to set path vector\n");
                ul.release_ucontact(contact);
                return -1;
            }
            if (set_dst_uri(_m, &path_dst) < 0) {
                LM_ERR("failed to set dst_uri of Path\n");
                ul.release_ucontact(contact);
                return -1;
            }

            ul.release_ucontact(contact);
            return 1;
        }
    }
    LM_DBG("no contact found for [%.*s]\n", s_contact_uri.len, s_contact_uri.s);
    return -1;
}
Beispiel #12
0
/*
 * Build Contact HF for reply
 */
static inline int print_contacts(FILE* _o, ucontact_t* _c)
{
	int cnt = 0;

	while(_c) {
		if (VALID_CONTACT(_c, act_time)) {
			cnt++;
			if (cnt==1) {
				fputs( "200 OK\n", _o);
			}
			fprintf(_o, "<%.*s>;q=%s;expires=%d\n",
				_c->c.len, ZSW(_c->c.s),
				q2str(_c->q, 0), (int)(_c->expires - act_time));
		}

		_c = _c->next;
	}

	return cnt;
}
Beispiel #13
0
/*
 * Return true if the AOR in the Request-URI is registered,
 * it is similar to lookup but registered neither rewrites
 * the Request-URI nor appends branches
 */
int registered(struct sip_msg* _m, char* _t, char* _s)
{
	str uri, aor;
	urecord_t* r;
	ucontact_t* ptr;
	int res;

	if (_m->new_uri.s) uri = _m->new_uri;
	else uri = _m->first_line.u.request.uri;
	
	if (extract_aor(&uri, &aor) < 0) {
		LOG(L_ERR, "registered(): Error while extracting address of record\n");
		return -1;
	}
	
	ul.lock_udomain((udomain_t*)_t);
	res = ul.get_urecord((udomain_t*)_t, &aor, &r);

	if (res < 0) {
		ul.unlock_udomain((udomain_t*)_t);
		LOG(L_ERR, "registered(): Error while querying usrloc\n");
		return -1;
	}

	if (res == 0) {
		ptr = r->contacts;
		while (ptr && !VALID_CONTACT(ptr, act_time)) {
			ptr = ptr->next;
		}

		if (ptr) {
			ul.unlock_udomain((udomain_t*)_t);
			DBG("registered(): '%.*s' found in usrloc\n", aor.len, ZSW(aor.s));
			return 1;
		}
	}

	ul.unlock_udomain((udomain_t*)_t);
	DBG("registered(): '%.*s' not found in usrloc\n", aor.len, ZSW(aor.s));
	return -1;
}
Beispiel #14
0
static int test_max_contacts(struct sip_msg* _m, urecord_t* _r, contact_t* _c)
{
	int num;
	int e;
	ucontact_t* ptr, *cont;
	
	num = 0;
	ptr = _r->contacts;
	while(ptr) {
		if (VALID_CONTACT(ptr, act_time)) {
			num++;
		}
		ptr = ptr->next;
	}
	DBG("test_max_contacts: %d valid contacts\n", num);
	
	while(_c) {
		if (calc_contact_expires(_m, _c->expires, &e) < 0) {
			LOG(L_ERR, "test_max_contacts: Error while calculating expires\n");
			return -1;
		}
		
		if (ul.get_ucontact(_r, &_c->uri, &cont) > 0) {
			     /* Contact not found */
			if (e != 0) num++;
		} else {
			if (e == 0) num--;
		}
		
		_c = get_next_contact(_c);
	}
	
	DBG("test_max_contacts: %d contacts after commit\n", num);
	if (num > max_contacts) {
		rerrno = R_TOO_MANY;
		return 1;
	}
	
	return 0;
}
Beispiel #15
0
/*
 * Return true if the AOR in the Request-URI is registered,
 * it is similar to lookup but registered neither rewrites
 * the Request-URI nor appends branches
 */
int registered2(struct sip_msg* _m, char* _t, char* p2)
{
	str uid, aor;
	urecord_t* r;
        ucontact_t* ptr;
	int res;

	if (get_str_fparam(&aor, _m, (fparam_t*)p2) != 0) {
	    ERR("Unable to get the AOR value\n");
	    return -1;
	}

	if (get_to_uid(&uid, _m) < 0) return -1;

	ul.lock_udomain((udomain_t*)_t);
	res = ul.get_urecord((udomain_t*)_t, &uid, &r);

	if (res < 0) {
		ul.unlock_udomain((udomain_t*)_t);
		LOG(L_ERR, "registered(): Error while querying usrloc\n");
		return -1;
	}

	if (res == 0) {
		ptr = r->contacts;
		while (ptr && (!VALID_CONTACT(ptr, act_time) || !VALID_AOR(ptr, aor))) {
			ptr = ptr->next;
		}

		if (ptr) {
			ul.unlock_udomain((udomain_t*)_t);
			DBG("registered(): '%.*s' found in usrloc\n", uid.len, ZSW(uid.s));
			return 1;
		}
	}

	ul.unlock_udomain((udomain_t*)_t);
	DBG("registered(): '%.*s' not found in usrloc\n", uid.len, ZSW(uid.s));
	return -1;
}
Beispiel #16
0
/*
 * Build Contact HF for reply
 */
static inline int print_contacts(rpc_t* rpc, void* ctx, ucontact_t* _c)
{
	int cnt = 0;
	void* handle;
	
	while(_c) {
		if (VALID_CONTACT(_c, act_time)) {
			cnt++;

            if (rpc->add(ctx, "{", &handle) < 0) return -1;
            rpc->struct_add(handle, "SfdSS",
							"contact", &_c->c,
							"q", q2double(_c->q),
							"expires", (int)(_c->expires - act_time),
							"ua", &_c->user_agent,
							"recv", &_c->received);
		}
		
		_c = _c->next;
	}
	
	return cnt;
}
Beispiel #17
0
/*
 * This timer routine is used when
 * db_mode is set to NO_DB or READONLY
 */
static inline int nodb_timer(urecord_t* _r)
{
	ucontact_t* ptr, *t;
	int not = 0;

	ptr = _r->contacts;

	while(ptr) {
		if (!VALID_CONTACT(ptr, act_time)) {
			/* run callbacks for EXPIRE event */
			if (exists_ulcb_type(UL_CONTACT_EXPIRE))
				run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);

			notify_watchers(_r, ptr, PRES_OFFLINE);
	
			LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n",
			    ptr->uid->len, ZSW(ptr->uid->s),
			    ptr->c.len, ZSW(ptr->c.s));
			
			t = ptr;
			ptr = ptr->next;
			
			     /* it was the last contact and it was in normal
			      * state, so notify */
			if (!ptr && t->state == CS_NEW) not=1;
			
			delete_reg_avps(t);
			mem_delete_ucontact(_r, t);
			_r->slot->d->expired++;
		} else {
			ptr = ptr->next;
		}
	}

	return 0;
}
Beispiel #18
0
/*! \brief
 * Message contained some contacts and appropriate
 * record was found, so we have to walk through
 * all contacts and do the following:
 * 1) If contact in usrloc doesn't exists and
 *    expires > 0, insert new contact
 * 2) If contact in usrloc exists and expires
 *    > 0, update the contact
 * 3) If contact in usrloc exists and expires
 *    == 0, delete contact
 */
static inline int update_contacts(struct sip_msg* _m, urecord_t* _r,
										contact_t* _c, struct save_ctx *_sctx)
{
	ucontact_info_t *ci;
	ucontact_t* c;
	int e;
	unsigned int cflags;
	int ret;
	int num;
#ifdef USE_TCP
	int e_max;
	int tcp_check;
	struct sip_uri uri;
#endif

	/* mem flag */
	cflags = (_sctx->flags&REG_SAVE_MEMORY_FLAG)?FL_MEM:FL_NONE;

	/* pack the contact_info */
	if ( (ci=pack_ci( _m, 0, 0, cflags, _sctx->flags))==0 ) {
		LM_ERR("failed to initial pack contact info\n");
		goto error;
	}

	/* count how many contacts we have right now */
	num = 0;
	if (_sctx->max_contacts) {
		c = _r->contacts;
		while(c) {
			if (VALID_CONTACT(c, act_time)) num++;
			c = c->next;
		}
	}

#ifdef USE_TCP
	if ( (_m->flags&tcp_persistent_flag) &&
	(_m->rcv.proto==PROTO_TCP||_m->rcv.proto==PROTO_TLS)) {
		e_max = -1;
		tcp_check = 1;
	} else {
		e_max = tcp_check = 0;
	}
#endif

	for( ; _c ; _c = get_next_contact(_c) ) {
		/* calculate expires */
		calc_contact_expires(_m, _c->expires, &e);

		/* search for the contact*/
		ret = ul.get_ucontact( _r, &_c->uri, ci->callid, ci->cseq, &c);
		if (ret==-1) {
			LM_ERR("invalid cseq for aor <%.*s>\n",_r->aor.len,_r->aor.s);
			rerrno = R_INV_CSEQ;
			goto error;
		} else if (ret==-2) {
			continue;
		}

		if ( ret > 0 ) {
			/* Contact not found -> expired? */
			if (e==0)
				continue;

			/* we need to add a new contact -> too many ?? */
			if (_sctx->max_contacts && num>=_sctx->max_contacts) {
				if (_sctx->flags&REG_SAVE_FORCE_REG_FLAG) {
					/* we are overflowing the number of maximum contacts,
					   so remove the first (oldest) one to prevent this */
					if (_r==NULL || _r->contacts==NULL) {
						LM_CRIT("BUG - overflow detected with r=%p and "
							"contacts=%p\n",_r,_r->contacts);
						goto error;
					}
					if (ul.delete_ucontact( _r, _r->contacts)!=0) {
						LM_ERR("failed to remove contact\n");
						goto error;
					}
				} else {
					LM_INFO("too many contacts for AOR <%.*s>, max=%d\n",
						_r->aor.len, _r->aor.s, _sctx->max_contacts);
					rerrno = R_TOO_MANY;
					return -1;
				}
			}

			/* pack the contact_info */
			if ( (ci=pack_ci( 0, _c, e, 0, _sctx->flags))==0 ) {
				LM_ERR("failed to extract contact info\n");
				goto error;
			}

			if (ul.insert_ucontact( _r, &_c->uri, ci, &c) < 0) {
				rerrno = R_UL_INS_C;
				LM_ERR("failed to insert contact\n");
				goto error;
			}
		} else {
			/* Contact found */
			if (e == 0) {
				/* it's expired */
				if (_sctx->flags&REG_SAVE_MEMORY_FLAG) {
					c->flags |= FL_MEM;
				} else {
					c->flags &= ~FL_MEM;
				}

				if (ul.delete_ucontact(_r, c) < 0) {
					rerrno = R_UL_DEL_C;
					LM_ERR("failed to delete contact\n");
					goto error;
				}
			} else {
				/* do update */
				/* pack the contact specific info */
				if ( (ci=pack_ci( 0, _c, e, 0, _sctx->flags))==0 ) {
					LM_ERR("failed to pack contact specific info\n");
					goto error;
				}

				if (ul.update_ucontact(_r, c, ci) < 0) {
					rerrno = R_UL_UPD_C;
					LM_ERR("failed to update contact\n");
					goto error;
				}
			}
		}
#ifdef USE_TCP
		if (tcp_check) {
			/* parse contact uri to see if transport is TCP */
			if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) {
				LM_ERR("failed to parse contact <%.*s>\n", 
						_c->uri.len, _c->uri.s);
			} else if (uri.proto==PROTO_TCP || uri.proto==PROTO_TLS) {
				if (e_max>0) {
					LM_WARN("multiple TCP contacts on single REGISTER\n");
				}
				if (e>e_max) e_max = e;
			}
		}
#endif
	}

#ifdef USE_TCP
	if ( tcp_check && e_max>-1 ) {
		if (e_max) e_max -= act_time;
		force_tcp_conn_lifetime( &_m->rcv , e_max + 10 );
	}
#endif

	return 0;
error:
	return -1;
}
Beispiel #19
0
/*!
 * \brief Expires timer for NO_DB db_mode
 *
 * Expires timer for NO_DB db_mode, process all contacts from
 * the record, delete the expired ones from memory.
 * \param _r processed record
 */
static inline void process_impurecord(impurecord_t* _r) {
    int flag, mustdeleteimpu = 1, n, k;
    unsigned int sl;
    ucontact_t* ptr;
    int hascontacts;
    udomain_t* _d;
    reg_subscriber *s;
    subs_t* sub_dialog;

    get_act_time();

    s = _r->shead;
    LM_DBG("Checking validity of IMPU: <%.*s> registration subscriptions\n", _r->public_identity.len, _r->public_identity.s);
    while (s) {
        if (!valid_subscriber(s, act_time)) {
            LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> expired and removed.\n",
                   s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s);
            delete_subscriber(_r, s);
        } else {
            LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> is valid and expires in %d seconds.\n",
                   s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s,
                   (unsigned int) (s->expires - time(NULL)));
            sl = core_hash(&s->call_id, &s->to_tag, sub_dialog_hash_size);
            LM_DBG("Hash size: <%i>", sub_dialog_hash_size);
            LM_DBG("Searching sub dialog hash info with call_id: <%.*s> and ttag <%.*s> ftag <%.*s> and hash code <%i>", s->call_id.len, s->call_id.s, s->to_tag.len, s->to_tag.s, s->from_tag.len, s->from_tag.s, sl);
            /* search the record in hash table */
            lock_get(&sub_dialog_table[sl].lock);
            sub_dialog = pres_search_shtable(sub_dialog_table, s->call_id, s->to_tag, s->from_tag, sl);
            if (sub_dialog == NULL) {
                LM_ERR("DBG:registrar_timer: Subscription has no dialog record in hash table\n");
            } else {
                LM_DBG("DBG:registrar_timer: Subscription has dialog record in hash table with presentity uri <%.*s>\n", sub_dialog->pres_uri.len, sub_dialog->pres_uri.s);
            }
            lock_release(&sub_dialog_table[sl].lock);
            mustdeleteimpu = 0;
        }
        s = s->next;
    }

    LM_DBG("\tPublic Identity %.*s, Barred: [%d], State: [%s]\n",
           _r->public_identity.len, _r->public_identity.s,
           _r->barring,
           get_impu_regstate_as_string(_r->reg_state));
    flag = 0;
    hascontacts = 0;
    num_contacts_to_expire = 0;
    for (k = 0; (k < _r->num_contacts) && (k < MAX_CONTACTS_PER_IMPU); k++) {
        if ((ptr = _r->newcontacts[k])) {
            flag = 1;
            if (!VALID_CONTACT(ptr, act_time)) {
                if (ptr->state == CONTACT_DELETED) {
                    LM_DBG("Contact: <%.*s> has been deleted - unlinking from IMPU\n", ptr->c.len, ptr->c.s);
                    contacts_to_expire[num_contacts_to_expire] = ptr;
                    num_contacts_to_expire++;
                } else if (ptr->state == CONTACT_EXPIRE_PENDING_NOTIFY) {
                    LM_DBG("Contact: <%.*s> is in state CONTACT_EXPIRE_PENDING_NOTIFY....running callback\n", ptr->c.len, ptr->c.s);
                    if (exists_ulcb_type(_r->cbs, UL_IMPU_DELETE_CONTACT)) {
                        LM_DBG("Running callback UL_IMPU_DELETE_CONTACT for contact [%.*s] and impu [%.*s]\n", ptr->c.len, ptr->c.s, _r->public_identity.len, _r->public_identity.s);
                        run_ul_callbacks(_r->cbs, UL_IMPU_DELETE_CONTACT, _r, ptr);
                    }
                    hascontacts = 1;    // we do this because the impu must only be deleted if in state deleted....
                    mustdeleteimpu = 0;
                } else if (ptr->state == CONTACT_VALID) {
                    LM_DBG("Contact: <%.*s> is in state valid but it has expired.... ignoring as the contact check will set the appropriate action/state\n", ptr->c.len, ptr->c.s);
                    mustdeleteimpu = 0;
                    hascontacts = 1;
                } else {
                    LM_WARN("Bogus state for contact [%.*s] - state: %d... ignoring", ptr->c.len, ptr->c.s, ptr->state);
                    mustdeleteimpu = 0;
                    hascontacts = 1;
                }
            } else {
                LM_DBG("\t\tContact #%i - %.*s, Ref [%d] (expires in %ld seconds) (State: %d)\n",
                       k, ptr->c.len, ptr->c.s, ptr->ref_count, ptr->expires - act_time, ptr->state);
                mustdeleteimpu = 0;
                hascontacts = 1;
            }
        } else {
            LM_WARN("num_contacts and actual data not consistent... .aborting\n");
            break;
        }
    }

    if (num_contacts_to_expire > 0) {
        LM_DBG("\tThere are %d contacts to expire/unlink\n", num_contacts_to_expire);
        for (n = 0; n < num_contacts_to_expire; n++) {
            ptr = contacts_to_expire[n];
            LM_DBG("\t\texpiring contact %i: [%.*s] in slot [%d]\n", n, contacts_to_expire[n]->c.len, contacts_to_expire[n]->c.s, contacts_to_expire[n]->sl);
            sl = ptr->sl;
            lock_contact_slot_i(sl);
            unlink_contact_from_impu(_r, ptr, 1, 0 /*implicit dereg of contact from IMPU*/);
            unlock_contact_slot_i(sl);
        }
    }

    if (!flag)
        LM_DBG("no contacts\n");

    if (mustdeleteimpu) {
        register_udomain("location", &_d);
        delete_impurecord(_d, &_r->public_identity, _r);
    } else {
        if (!hascontacts) {
            LM_DBG("This impu is not to be deleted but has no contacts - changing state to IMPU_UNREGISTERED\n");
            _r->reg_state = IMPU_UNREGISTERED;
        }
    }
}
Beispiel #20
0
/*! \brief
 * Allocate a memory buffer and print Contact
 * header fields into it
 */
int build_contact(ucontact_t* c)
{
	char *p, *cp;
	int fl, len;

	contact.data_len = calc_buf_len(c);
	if (!contact.data_len) return 0;

	if (!contact.buf || (contact.buf_len < contact.data_len)) {
		if (contact.buf) pkg_free(contact.buf);
		contact.buf = (char*)pkg_malloc(contact.data_len);
		if (!contact.buf) {
			contact.data_len = 0;
			contact.buf_len = 0;
			LM_ERR("no pkg memory left\n");
			return -1;
		} else {
			contact.buf_len = contact.data_len;
		}
	}

	p = contact.buf;
	
	memcpy(p, CONTACT_BEGIN, CONTACT_BEGIN_LEN);
	p += CONTACT_BEGIN_LEN;

	fl = 0;
	while(c) {
		if (VALID_CONTACT(c, act_time)) {
			if (fl) {
				memcpy(p, CONTACT_SEP, CONTACT_SEP_LEN);
				p += CONTACT_SEP_LEN;
			} else {
				fl = 1;
			}

			*p++ = '<';
			memcpy(p, c->c.s, c->c.len);
			p += c->c.len;
			*p++ = '>';

			len = len_q(c->q);
			if (len) {
				memcpy(p, Q_PARAM, Q_PARAM_LEN);
				p += Q_PARAM_LEN;
				memcpy(p, q2str(c->q, 0), len);
				p += len;
			}

			memcpy(p, EXPIRES_PARAM, EXPIRES_PARAM_LEN);
			p += EXPIRES_PARAM_LEN;
			cp = int2str((int)(c->expires - act_time), &len);
			memcpy(p, cp, len);
			p += len;

			if (c->received.s) {
				*p++ = ';';
				memcpy(p, rcv_param.s, rcv_param.len);
				p += rcv_param.len;
				*p++ = '=';
				*p++ = '\"';
				memcpy(p, c->received.s, c->received.len);
				p += c->received.len;
				*p++ = '\"';
			}
		}

		c = c->next;
	}

	memcpy(p, CRLF, CRLF_LEN);
	p += CRLF_LEN;

	contact.data_len = p - contact.buf;

	LM_DBG("created Contact HF: %.*s\n", contact.data_len, contact.buf);
	return 0;
}
Beispiel #21
0
/*! \brief
 * Lookup contact in the database and rewrite Request-URI
 * \return: -1 : not found
 *          -2 : found but method not allowed
 *          -3 : error
 */
int lookup(struct sip_msg* _m, udomain_t* _d) {
    impurecord_t* r;
    str aor, uri;
    ucontact_t* ptr;
    int res;
    int ret;
    str path_dst;
    flag_t old_bflags;
    int i = 0;


    if (_m->new_uri.s) uri = _m->new_uri;
    else uri = _m->first_line.u.request.uri;

    if (extract_aor(&uri, &aor) < 0) {
	LM_ERR("failed to extract address of record\n");
	return -3;
    }

    get_act_time();

    ul.lock_udomain(_d, &aor);
    res = ul.get_impurecord(_d, &aor, &r);
    if (res > 0) {
	LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
	ul.unlock_udomain(_d, &aor);
	return -1;
    }
    ret = -1;

    while (i < MAX_CONTACTS_PER_IMPU && (ptr = r->newcontacts[i])) {
	if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) {
	    LM_DBG("Found a valid contact [%.*s]\n", ptr->c.len, ptr->c.s);
	    i++;
	    break;
	}
	i++;
    }

    /* look first for an un-expired and suported contact */
    if (ptr == 0) {
	/* nothing found */
	goto done;
    }

    ret = 1;
    if (ptr) {
	if (rewrite_uri(_m, &ptr->c) < 0) {
	    LM_ERR("unable to rewrite Request-URI\n");
	    ret = -3;
	    goto done;
	}

	/* reset next hop address */
	reset_dst_uri(_m);

	/* If a Path is present, use first path-uri in favour of
	 * received-uri because in that case the last hop towards the uac
	 * has to handle NAT. - agranig */
	if (ptr->path.s && ptr->path.len) {
	    if (get_path_dst_uri(&ptr->path, &path_dst) < 0) {
		LM_ERR("failed to get dst_uri for Path\n");
		ret = -3;
		goto done;
	    }
	    if (set_path_vector(_m, &ptr->path) < 0) {
		LM_ERR("failed to set path vector\n");
		ret = -3;
		goto done;
	    }
	    if (set_dst_uri(_m, &path_dst) < 0) {
		LM_ERR("failed to set dst_uri of Path\n");
		ret = -3;
		goto done;
	    }
	} else if (ptr->received.s && ptr->received.len) {
	    if (set_dst_uri(_m, &ptr->received) < 0) {
		ret = -3;
		goto done;
	    }
	}

	set_ruri_q(ptr->q);

	old_bflags = 0;
	getbflagsval(0, &old_bflags);
	setbflagsval(0, old_bflags | ptr->cflags);

	if (ptr->sock)
	    set_force_socket(_m, ptr->sock);

	ptr = ptr->next;
    }

    /* Append branches if enabled */
    if (!cfg_get(registrar, registrar_cfg, append_branches)) goto done;

    //the last i was the first valid contact we found - let's go through the rest of valid contacts and append the branches.
    while (i < MAX_CONTACTS_PER_IMPU && (ptr = r->newcontacts[i])) {
	if (VALID_CONTACT(ptr, act_time) && allowed_method(_m, ptr)) {
	    path_dst.len = 0;
	    if (ptr->path.s && ptr->path.len
		    && get_path_dst_uri(&ptr->path, &path_dst) < 0) {
		LM_ERR("failed to get dst_uri for Path\n");
		continue;
	    }

	    /* The same as for the first contact applies for branches
	     * regarding path vs. received. */
	    if (km_append_branch(_m, &ptr->c, path_dst.len ? &path_dst : &ptr->received,
		    &ptr->path, ptr->q, ptr->cflags, ptr->sock) == -1) {
		LM_ERR("failed to append a branch\n");
		/* Also give a chance to the next branches*/
		continue;
	    }
	}
	i++;
    }

done:
    ul.unlock_udomain(_d, &aor);
    return ret;
}
Beispiel #22
0
/*!
 * \brief Dumps the contacts of an AOR
 * \param cmd mi_root containing the parameter
 * \param param not used
 * \note expects 2 nodes: the table name and the AOR
 * \return mi_root with the result or 0 on failure
 */
struct mi_root* mi_usrloc_show_contact(struct mi_root *cmd, void *param)
{
	struct mi_root *rpl_tree;
	struct mi_node *rpl, *node;
	udomain_t *dom;
	urecord_t *rec;
	ucontact_t* con;
	str *aor;
	int ret;

	node = cmd->node.kids;
	if (node==NULL || node->next==NULL || node->next->next!=NULL)
		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);

	/* look for table */
	dom = mi_find_domain( &node->value );
	if (dom==NULL)
		return init_mi_tree( 404, "Table not found", 15);

	/* process the aor */
	aor = &node->next->value;
	if ( mi_fix_aor(aor)!=0 )
		return init_mi_tree( 400, "Domain missing in AOR", 21);

	lock_udomain( dom, aor);

	ret = get_urecord( dom, aor, &rec);
	if (ret == 1) {
		unlock_udomain( dom, aor);
		return init_mi_tree( 404, "AOR not found", 13);
	}

	get_act_time();
	rpl_tree = 0;
	rpl = 0;

	for( con=rec->contacts ; con ; con=con->next) {
		if (VALID_CONTACT( con, act_time)) {
			if (rpl_tree==0) {
				rpl_tree = init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
				if (rpl_tree==0)
					goto error;
				rpl = &rpl_tree->node;
			}

			node = addf_mi_node_child( rpl, 0, "Contact", 7,
				"<%.*s>;q=%s;expires=%d;flags=0x%X;cflags=0x%X;socket=<%.*s>;"
				"methods=0x%X"
				"%s%.*s%s" /*received*/
				"%s%.*s%s" /*user-agent*/
				"%s%.*s%s" /*path*/
				"%s%.*s" /*instance*/
			        ";reg-id=%u",
				con->c.len, ZSW(con->c.s),
				q2str(con->q, 0), (int)(con->expires - act_time),
				con->flags, con->cflags,
				con->sock?con->sock->sock_str.len:3,
					con->sock?con->sock->sock_str.s:"NULL",
				con->methods,
				con->received.len?";received=<":"",con->received.len,
					ZSW(con->received.s), con->received.len?">":"",
				con->user_agent.len?";user_agent=<":"",con->user_agent.len,
					ZSW(con->user_agent.s), con->user_agent.len?">":"",
				con->path.len?";path=<":"", con->path.len,
					ZSW(con->path.s), con->path.len?">":"",
				con->instance.len?";+sip.instance=":"", con->instance.len,
				        ZSW(con->instance.s),
				con->reg_id
				);
			if (node==0)
				goto error;
		}
	}

	unlock_udomain( dom, aor);

	if (rpl_tree==0)
		return init_mi_tree( 404 , "AOR has no contacts", 18);

	return rpl_tree;
error:
	if (rpl_tree)
		free_mi_tree( rpl_tree );
	unlock_udomain( dom, aor);
	return 0;
}
Beispiel #23
0
/*
 * Lookup contact in the database and rewrite Request-URI
 */
int lookup(struct sip_msg* _m, char* _t, char* _s)
{
	urecord_t* r;
	str uid;
	ucontact_t* ptr;
	int res;
	unsigned int nat;
	str new_uri; 	

	nat = 0;
	
	if (get_to_uid(&uid, _m) < 0) return -1;

	get_act_time();

	ul.lock_udomain((udomain_t*)_t);
	res = ul.get_urecord((udomain_t*)_t, &uid, &r);
	if (res < 0) {
		LOG(L_ERR, "lookup(): Error while querying usrloc\n");
		ul.unlock_udomain((udomain_t*)_t);
		return -2;
	}
	
	if (res > 0) {
		DBG("lookup(): '%.*s' Not found in usrloc\n", uid.len, ZSW(uid.s));
		ul.unlock_udomain((udomain_t*)_t);
		return -3;
	}

	ptr = r->contacts;
	while ((ptr) && !VALID_CONTACT(ptr, act_time))
		ptr = ptr->next;
	
	if (ptr) {
		if (ptr->received.s && ptr->received.len) {
			if (received_to_uri){
				if (add_received(&new_uri, &ptr->c, &ptr->received)<0){
					LOG(L_ERR, "ERROR: lookup(): out of memory\n");
					return -4;
				}
			/* replace the msg uri */
			if (_m->new_uri.s)      pkg_free(_m->new_uri.s);
			_m->new_uri=new_uri;
			_m->parsed_uri_ok=0;
			ruri_mark_new();
			goto skip_rewrite_uri;
			}else if (set_dst_uri(_m, &ptr->received) < 0) {
				ul.unlock_udomain((udomain_t*)_t);
				return -4;
			}
		}
		
		if (rewrite_uri(_m, &ptr->c) < 0) {
			LOG(L_ERR, "lookup(): Unable to rewrite Request-URI\n");
			ul.unlock_udomain((udomain_t*)_t);
			return -4;
		}

		if (ptr->sock) {
			set_force_socket(_m, ptr->sock);
		}

skip_rewrite_uri:

		set_ruri_q(ptr->q);

		nat |= ptr->flags & FL_NAT;
		ptr = ptr->next;
	} else {
		     /* All contacts expired */
		ul.unlock_udomain((udomain_t*)_t);
		return -5;
	}
	
	     /* Append branches if enabled */
	if (!append_branches) goto skip;

	while(ptr) {
		if (VALID_CONTACT(ptr, act_time)) {
			if (received_to_uri && ptr->received.s && ptr->received.len){
				if (add_received(&new_uri, &ptr->c, &ptr->received)<0){
					LOG(L_ERR, "ERROR: lookup(): branch: out of memory\n");
					goto cont; /* try to continue */
				}
				if (append_branch(_m, &new_uri, 0, 0, ptr->q, 0, 0) == -1) {
					LOG(L_ERR, "lookup(): Error while appending a branch\n");
					pkg_free(new_uri.s);
					if (ser_error==E_TOO_MANY_BRANCHES) goto skip;
					else goto cont; /* try to continue, maybe we have an
							                   oversized contact */
				}
				pkg_free(new_uri.s); /* append_branch doesn't free it */
			}else{
				if (append_branch(_m, &ptr->c, &ptr->received, 0 /* path */,
									ptr->q, 0 /* brflags*/, ptr->sock) == -1) {
					LOG(L_ERR, "lookup(): Error while appending a branch\n");
					goto skip; /* Return OK here so the function succeeds */
				}
			}
			
			nat |= ptr->flags & FL_NAT; 
		} 
cont:
		ptr = ptr->next; 
	}
	
 skip:
	ul.unlock_udomain((udomain_t*)_t);
	if (nat) setflag(_m, load_nat_flag);
	return 1;
}
Beispiel #24
0
/*
 * Lookup contact in the database and rewrite Request-URI,
 * and filter them by aor
 */
int lookup2(struct sip_msg* msg, char* table, char* p2)
{
	urecord_t* r;
	str uid;
	ucontact_t* ptr;
	int res;
	unsigned int nat;
	str new_uri, aor;
	fparam_t* fp;

	nat = 0;
	fp = (fparam_t*)p2;
	
	if (get_str_fparam(&aor, msg, (fparam_t*)p2) != 0) {
	    ERR("Unable to get the AOR value\n");
	    return -1;
	}

	if (get_to_uid(&uid, msg) < 0) return -1;
	get_act_time();

	ul.lock_udomain((udomain_t*)table);
	res = ul.get_urecord((udomain_t*)table, &uid, &r);
	if (res < 0) {
		ERR("Error while querying usrloc\n");
		ul.unlock_udomain((udomain_t*)table);
		return -2;
	}
	
	if (res > 0) {
		DBG("'%.*s' Not found in usrloc\n", uid.len, ZSW(uid.s));
		ul.unlock_udomain((udomain_t*)table);
		return -3;
	}

	ptr = r->contacts;
	while (ptr && (!VALID_CONTACT(ptr, act_time) || !VALID_AOR(ptr, aor)))
	    ptr = ptr->next;
	
	if (ptr) {
	       if (ptr->received.s && ptr->received.len) {
			if (received_to_uri){
				if (add_received(&new_uri, &ptr->c, &ptr->received) < 0) {
					ERR("Out of memory\n");
					return -4;
				}
			/* replace the msg uri */
			if (msg->new_uri.s) pkg_free(msg->new_uri.s);
			msg->new_uri = new_uri;
			msg->parsed_uri_ok = 0;
			ruri_mark_new();
			goto skip_rewrite_uri;
			} else if (set_dst_uri(msg, &ptr->received) < 0) {
			        ul.unlock_udomain((udomain_t*)table);
				return -4;
			}
		}
		
		if (rewrite_uri(msg, &ptr->c) < 0) {
			ERR("Unable to rewrite Request-URI\n");
			ul.unlock_udomain((udomain_t*)table);
			return -4;
		}

		if (ptr->sock) {
			set_force_socket(msg, ptr->sock);
		}

skip_rewrite_uri:
		set_ruri_q(ptr->q);

		nat |= ptr->flags & FL_NAT;
		ptr = ptr->next;
	} else {
		     /* All contacts expired */
		ul.unlock_udomain((udomain_t*)table);
		return -5;
	}
	
	     /* Append branches if enabled */
	if (!append_branches) goto skip;

	while(ptr) {
		if (VALID_CONTACT(ptr, act_time) && VALID_AOR(ptr, aor)) {
			if (received_to_uri && ptr->received.s && ptr->received.len) {
				if (add_received(&new_uri, &ptr->c, &ptr->received) < 0) {
					ERR("branch: out of memory\n");
					goto cont; /* try to continue */
				}
				if (append_branch(msg, &new_uri, 0, 0, ptr->q, 0, 0) == -1) {
					ERR("Error while appending a branch\n");
					pkg_free(new_uri.s);
					if (ser_error == E_TOO_MANY_BRANCHES) goto skip;
					else goto cont; /* try to continue, maybe we have an
							                   oversized contact */
				}
				pkg_free(new_uri.s); /* append_branch doesn't free it */
			} else {
				if (append_branch(msg, &ptr->c, &ptr->received, 0 /* path */,
									 ptr->q, 0, ptr->sock) == -1) {
					ERR("Error while appending a branch\n");
					goto skip; /* Return OK here so the function succeeds */
				}
			}
			
			nat |= ptr->flags & FL_NAT; 
		} 
cont:
		ptr = ptr->next; 
	}
	
 skip:
	ul.unlock_udomain((udomain_t*)table);
	if (nat) setflag(msg, load_nat_flag);
	return 1;
}
Beispiel #25
0
int process_contact(udomain_t * domain, urecord_t ** ul_record, str aor, str callid,
		int cseq, int expires, int event, str contact_uri) {
	str no_str = {0, 0};
	static str no_ua = str_init("n/a");
	static ucontact_info_t ci;
	ucontact_t * ul_contact;

	if (*ul_record == NULL) {
		switch(event) {
			case EVENT_REGISTERED:
			case EVENT_CREATED:
			case EVENT_REFRESHED:
				/* In case, no record exists and new one should be created,
				   create a new entry for this user in the usrloc-DB */
				if (ul.insert_urecord(domain, &aor, ul_record) < 0) {
					LM_ERR("failed to insert new user-record\n");
					return RESULT_ERROR;
				}
				break;
			default:
				/* No entry in usrloc and the contact is expired, deleted, unregistered, whatever:
                                   We do not need to do anything. */
				return RESULT_NO_CONTACTS;
				break;
		}
	}
	
	/* Make sure, no crap is in the structure: */
	memset( &ci, 0, sizeof(ucontact_info_t));	
	/* Get callid of the message */
	ci.callid = &callid;
	/* Get CSeq number of the message */
	ci.cseq = cseq;
	ci.sock = NULL;
	/* additional info from message */
	ci.user_agent = &no_ua;
	ci.last_modified = time(0);

	/* set expire time */
	ci.expires = time(0) + expires;

	/* set ruid */
	if(sruid_next(&_reginfo_sruid) < 0) {
		LM_ERR("failed to generate ruid");
	} else {
		ci.ruid = _reginfo_sruid.uid;
	}

	/* Now we start looking for the contact: */
	if (((*ul_record)->contacts == 0)
		|| (ul.get_ucontact(*ul_record, &contact_uri, &callid, &no_str, cseq+1, &ul_contact) != 0)) {
		if (ul.insert_ucontact(*ul_record, &contact_uri, &ci, &ul_contact) < 0) {
			LM_ERR("failed to insert new contact\n");
			return RESULT_ERROR;
		}
	} else {
		if (ul.update_ucontact(*ul_record, ul_contact, &ci) < 0) {
			LM_ERR("failed to update contact\n");
			return RESULT_ERROR;
		}
	}
	ul_contact = (*ul_record)->contacts;
	while (ul_contact) {
		if (VALID_CONTACT(ul_contact, time(0))) return RESULT_CONTACTS_FOUND;
		ul_contact = ul_contact->next;
	}

	return RESULT_NO_CONTACTS;
}
Beispiel #26
0
/*! \brief
 * Message contained some contacts and appropriate
 * record was found, so we have to walk through
 * all contacts and do the following:
 * 1) If contact in usrloc doesn't exists and
 *    expires > 0, insert new contact
 * 2) If contact in usrloc exists and expires
 *    > 0, update the contact
 * 3) If contact in usrloc exists and expires
 *    == 0, delete contact
 */
static inline int update_contacts(struct sip_msg* _m, urecord_t* _r,
										contact_t* _c, struct save_ctx *_sctx)
{
	ucontact_info_t *ci;
	ucontact_t *c, *c_last, *c_it;
	int e;
	unsigned int cflags;
	int ret;
	int num;
	int e_max;
	int tcp_check;
	struct sip_uri uri;

	/* mem flag */
	cflags = (_sctx->flags&REG_SAVE_MEMORY_FLAG)?FL_MEM:FL_NONE;

	/* pack the contact_info */
	if ( (ci=pack_ci( _m, 0, 0, cflags, _sctx->flags))==0 ) {
		LM_ERR("failed to initial pack contact info\n");
		goto error;
	}

	/* count how many contacts we have right now */
	num = 0;
	if (_sctx->max_contacts) {
		c = _r->contacts;
		while(c) {
			if (VALID_CONTACT(c, act_time)) num++;
			c = c->next;
		}
	}

	if (is_tcp_based_proto(_m->rcv.proto) && (_m->flags&tcp_persistent_flag)) {
		e_max = -1;
		tcp_check = 1;
	} else {
		e_max = tcp_check = 0;
	}

	for( ; _c ; _c = get_next_contact(_c) ) {
		/* calculate expires */
		calc_contact_expires(_m, _c->expires, &e, _sctx);

		/* search for the contact*/
		ret = ul.get_ucontact( _r, &_c->uri, ci->callid, ci->cseq, &c);
		if (ret==-1) {
			LM_ERR("invalid cseq for aor <%.*s>\n",_r->aor.len,_r->aor.s);
			rerrno = R_INV_CSEQ;
			goto error;
		} else if (ret==-2) {
			continue;
		}

		if ( ret > 0 ) {
			/* Contact not found -> expired? */
			if (e==0)
				continue;

			/* we need to add a new contact -> too many ?? */
			while (_sctx->max_contacts && num>=_sctx->max_contacts) {
				if (_sctx->flags&REG_SAVE_FORCE_REG_FLAG) {
					/* we are overflowing the number of maximum contacts,
					   so remove the oldest valid one to prevent this */
					for( c_it=_r->contacts,c_last=NULL ; c_it ;
					c_it=c_it->next )
						if (VALID_CONTACT(c_it, act_time))
							c_last=c_it;
					if (c_last==NULL) {
						LM_CRIT("BUG - overflow detected but no valid "
							"contacts found :( \n");
						goto error;
					}
					LM_DBG("overflow on inserting new contact -> removing "
						"<%.*s>\n", c_last->c.len, c_last->c.s);
					if (ul.delete_ucontact( _r, c_last, 0)!=0) {
						LM_ERR("failed to remove contact\n");
						goto error;
					}
					num--;
				} else {
					LM_INFO("too many contacts for AOR <%.*s>, max=%d\n",
						_r->aor.len, _r->aor.s, _sctx->max_contacts);
					rerrno = R_TOO_MANY;
					return -1;
				}
			}

			/* pack the contact_info */
			if ( (ci=pack_ci( 0, _c, e, 0, _sctx->flags))==0 ) {
				LM_ERR("failed to extract contact info\n");
				goto error;
			}

			if (ul.insert_ucontact( _r, &_c->uri, ci, &c, 0) < 0) {
				rerrno = R_UL_INS_C;
				LM_ERR("failed to insert contact\n");
				goto error;
			}
		} else {
			/* Contact found */
			if (e == 0) {
				/* it's expired */
				if (_sctx->flags&REG_SAVE_MEMORY_FLAG) {
					c->flags |= FL_MEM;
				} else {
					c->flags &= ~FL_MEM;
				}

				if (ul.delete_ucontact(_r, c, 0) < 0) {
					rerrno = R_UL_DEL_C;
					LM_ERR("failed to delete contact\n");
					goto error;
				}
			} else {
				/* do update */
				/* if the contact to be updated is not valid, it will be after
				 * update, so need to compensate the total number of contact */
				if ( !VALID_CONTACT(c,act_time) )
					num++;
				while ( _sctx->max_contacts && num>_sctx->max_contacts ) {
					if (_sctx->flags&REG_SAVE_FORCE_REG_FLAG) {
						/* we are overflowing the number of maximum contacts,
						   so remove the first (oldest) one to prevent this 
						   (but not the one to be updated !) */
						for( c_it=_r->contacts,c_last=NULL ; c_it ;
						c_it=c_it->next )
							if (VALID_CONTACT(c_it, act_time) && c_it!=c)
								c_last=c_it;
						if (c_last==NULL) {
							LM_CRIT("BUG - overflow detected but no "
								"valid contacts found :( \n");
							goto error;
						}
						LM_DBG("overflow on update -> removing contact "
							"<%.*s>\n", c_last->c.len, c_last->c.s);
						if (ul.delete_ucontact( _r, c_last, 0)!=0) {
							LM_ERR("failed to remove contact\n");
							goto error;
						}
						num--;
					} else {
						LM_INFO("too many contacts for AOR <%.*s>, max=%d\n",
							_r->aor.len, _r->aor.s, _sctx->max_contacts);
						rerrno = R_TOO_MANY;
						return -1;
					}
				}

				/* pack the contact specific info */
				if ( (ci=pack_ci( 0, _c, e, 0, _sctx->flags))==0 ) {
					LM_ERR("failed to pack contact specific info\n");
					goto error;
				}

				if (ul.update_ucontact(_r, c, ci, 0) < 0) {
					rerrno = R_UL_UPD_C;
					LM_ERR("failed to update contact\n");
					goto error;
				}
			}
		}
		if (tcp_check) {
			/* parse contact uri to see if transport is TCP */
			if (parse_uri( _c->uri.s, _c->uri.len, &uri)<0) {
				LM_ERR("failed to parse contact <%.*s>\n",
						_c->uri.len, _c->uri.s);
			} else if (is_tcp_based_proto(uri.proto)) {
				if (e_max>0) {
					LM_WARN("multiple TCP contacts on single REGISTER\n");
				}
				if (e>e_max) e_max = e;
			}
		}
	}

	if ( tcp_check && e_max>-1 ) {
		if (e_max) e_max -= act_time;
		trans_set_dst_attr( &_m->rcv, DST_FCNTL_SET_LIFETIME,
			(void*)(long)(e_max + 10) );
	}

	return 0;
error:
	return -1;
}
Beispiel #27
0
/*
 * Write-back timer
 */
static inline int wb_timer(urecord_t* _r)
{
	ucontact_t* ptr, *t;
	int op;
	int not = 0;

	ptr = _r->contacts;

	while(ptr) {
		if (!VALID_CONTACT(ptr, act_time)) {
			/* run callbacks for EXPIRE event */
			if (exists_ulcb_type(UL_CONTACT_EXPIRE)) {
				run_ul_callbacks( UL_CONTACT_EXPIRE, ptr);
			}

			notify_watchers(_r, ptr, PRES_OFFLINE);
	
			LOG(L_NOTICE, "Binding '%.*s','%.*s' has expired\n",
			    ptr->uid->len, ZSW(ptr->uid->s),
			    ptr->c.len, ZSW(ptr->c.s));
			if (ptr->next == 0) not=1;
			_r->slot->d->expired++;

			t = ptr;
			ptr = ptr->next;
			
			     /* Should we remove the contact from the database ? */
			if (st_expired_ucontact(t) == 1) {
				if (db_delete_ucontact(t) < 0) {
					LOG(L_ERR, "wb_timer(): Can't delete contact from the database\n");
				}
			}
			
			delete_reg_avps(t);
			mem_delete_ucontact(_r, t);
		} else {
			     /* Determine the operation we have to do */
			op = st_flush_ucontact(ptr);
			
			switch(op) {
			case 0: /* do nothing, contact is synchronized */
				break;

			case 1: /* insert */
				if (db_store_ucontact(ptr) < 0) {
					LOG(L_ERR, "wb_timer(): Error while inserting contact into database\n");
				}
				break;

			case 2: /* update */
				if (db_store_ucontact(ptr) < 0) {
					LOG(L_ERR, "wb_timer(): Error while updating contact in db\n");
				}
				break;

			case 4: /* delete */
				if (db_delete_ucontact(ptr) < 0) {
					LOG(L_ERR, "wb_timer(): Can't delete contact from database\n");
				}
				     /* fall through to the next case statement */

			case 3: /* delete from memory */
				delete_reg_avps(ptr);
				mem_delete_ucontact(_r, ptr);
				break;
			}

			ptr = ptr->next;
		}
	}

	return 0;
}
Beispiel #28
0
/*! \brief
 * Lookup contact in the database and rewrite Request-URI
 * \return: -1 : not found
 *          -2 : found but method not allowed
 *          -3 : error
 */
int lookup(struct sip_msg* _m, char* _t, char* _f, char* _s)
{
	unsigned int flags;
	urecord_t* r;
	str aor, uri;
	ucontact_t* ptr,*it;
	int res;
	int ret;
	str path_dst;
	str flags_s;
	char* ua = NULL;
	char* re_end = NULL;
	int re_len = 0;
	char tmp;
	regex_t ua_re;
	int regexp_flags = 0;
	regmatch_t ua_match;
	pv_value_t val;
	int_str istr;
	str sip_instance = {0,0},call_id = {0,0};

	/* branch index */
	int idx;

	/* temporary branch values*/
	int tlen;
	char *turi;

	qvalue_t tq;

	flags = 0;
	if (_f && _f[0]!=0) {
		if (fixup_get_svalue( _m, (gparam_p)_f, &flags_s)!=0) {
			LM_ERR("invalid owner uri parameter");
			return -1;
		}
		for( res=0 ; res< flags_s.len ; res++ ) {
			switch (flags_s.s[res]) {
				case 'm': flags |= REG_LOOKUP_METHODFILTER_FLAG; break;
				case 'b': flags |= REG_LOOKUP_NOBRANCH_FLAG; break;
				case 'r': flags |= REG_BRANCH_AOR_LOOKUP_FLAG; break;
				case 'u':
					if (flags_s.s[res+1] != '/') {
						LM_ERR("no regexp after 'u' flag");
						break;
					}
					res++;
					if ((re_end = strrchr(flags_s.s+res+1, '/')) == NULL) {
						LM_ERR("no regexp after 'u' flag");
						break;
					}
					res++;
					re_len = re_end-flags_s.s-res;
					if (re_len == 0) {
						LM_ERR("empty regexp");
						break;
					}
					ua = flags_s.s+res;
					flags |= REG_LOOKUP_UAFILTER_FLAG;
					LM_DBG("found regexp /%.*s/", re_len, ua);
					res += re_len;
					break;
				case 'i': regexp_flags |= REG_ICASE; break;
				case 'e': regexp_flags |= REG_EXTENDED; break;
				default: LM_WARN("unsuported flag %c \n",flags_s.s[res]);
			}
		}
	}
	if (flags&REG_BRANCH_AOR_LOOKUP_FLAG) {
		/* extract all the branches for further usage */
		nbranches = 0;
		while (
			(turi=get_branch(nbranches, &tlen, &tq, NULL, NULL, NULL, NULL))
				) {
			/* copy uri */
			branch_uris[nbranches].s = urimem[nbranches];
			if (tlen) {
				memcpy(branch_uris[nbranches].s, turi, tlen);
				branch_uris[nbranches].len = tlen;
			} else {
				*branch_uris[nbranches].s  = '\0';
				branch_uris[nbranches].len = 0;
			}

			nbranches++;
		}
		clear_branches();
		idx=0;
	}


	if (_s) {
		if (pv_get_spec_value( _m, (pv_spec_p)_s, &val)!=0) {
			LM_ERR("failed to get PV value\n");
			return -1;
		}
		if ( (val.flags&PV_VAL_STR)==0 ) {
			LM_ERR("PV vals is not string\n");
			return -1;
		}
		uri = val.rs;
	} else {
		if (_m->new_uri.s) uri = _m->new_uri;
		else uri = _m->first_line.u.request.uri;
	}

	if (extract_aor(&uri, &aor,&sip_instance,&call_id) < 0) {
		LM_ERR("failed to extract address of record\n");
		return -3;
	}

	get_act_time();

	ul.lock_udomain((udomain_t*)_t, &aor);
	res = ul.get_urecord((udomain_t*)_t, &aor, &r);
	if (res > 0) {
		LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
		ul.unlock_udomain((udomain_t*)_t, &aor);
		return -1;
	}

	if (flags & REG_LOOKUP_UAFILTER_FLAG) {
		tmp = *(ua+re_len);
		*(ua+re_len) = '\0';
		if (regcomp(&ua_re, ua, regexp_flags) != 0) {
			LM_ERR("bad regexp '%s'\n", ua);
			*(ua+re_len) = tmp;
			return -1;
		}
		*(ua+re_len) = tmp;
	}


	ptr = r->contacts;
	ret = -1;
	/* look first for an un-expired and suported contact */
search_valid_contact:
	while ( (ptr) &&
	!(VALID_CONTACT(ptr,act_time) && (ret=-2) && allowed_method(_m,ptr,flags)))
		ptr = ptr->next;
	if (ptr==0) {
		/* nothing found */
		LM_DBG("nothing found !\n");
		goto done;
	}

	ua_re_check(
		ret = -1;
		ptr = ptr->next;
		goto search_valid_contact
	);

	if (sip_instance.len && sip_instance.s) {
		LM_DBG("ruri has gruu in lookup\n");
		/* uri has GRUU */
		if (ptr->instance.len-2 != sip_instance.len ||
				memcmp(ptr->instance.s+1,sip_instance.s,sip_instance.len)) {
			LM_DBG("no match to sip instace - [%.*s] - [%.*s]\n",ptr->instance.len-2,ptr->instance.s+1,
					sip_instance.len,sip_instance.s);
			/* not the targeted instance, search some more */
			ptr = ptr->next;
			goto search_valid_contact;
		}

		LM_DBG("matched sip instace\n");
	}

	if (call_id.len && call_id.s) {
		/* decide whether GRUU is expired or not
		 *
		 * first - match call-id */
		if (ptr->callid.len != call_id.len ||
				memcmp(ptr->callid.s,call_id.s,call_id.len)) {
			LM_DBG("no match to call id - [%.*s] - [%.*s]\n",ptr->callid.len,ptr->callid.s,
					call_id.len,call_id.s);
			ptr = ptr->next;
			goto search_valid_contact;
		}

		/* matched call-id, check if there are newer contacts with
		 * same sip instace bup newer last_modified */

		it = ptr->next;
		while ( it ) {
			if (VALID_CONTACT(it,act_time)) {
				if (it->instance.len-2 == sip_instance.len && sip_instance.s &&
						memcmp(it->instance.s+1,sip_instance.s,sip_instance.len) == 0)
					if (it->last_modified > ptr->last_modified) {
						/* same instance id, but newer modified -> expired GRUU, no match at all */
						break;
					}
			}
			it=it->next;
		}

		if (it != NULL) {
			ret = -1;
			goto done;
		}
	}

	LM_DBG("found a complete match\n");

	ret = 1;
	if (ptr) {
		LM_DBG("setting as ruri <%.*s>\n",ptr->c.len,ptr->c.s);
		if (set_ruri(_m, &ptr->c) < 0) {
			LM_ERR("unable to rewrite Request-URI\n");
			ret = -3;
			goto done;
		}

		/* If a Path is present, use first path-uri in favour of
		 * received-uri because in that case the last hop towards the uac
		 * has to handle NAT. - agranig */
		if (ptr->path.s && ptr->path.len) {
			if (get_path_dst_uri(&ptr->path, &path_dst) < 0) {
				LM_ERR("failed to get dst_uri for Path\n");
				ret = -3;
				goto done;
			}
			if (set_path_vector(_m, &ptr->path) < 0) {
				LM_ERR("failed to set path vector\n");
				ret = -3;
				goto done;
			}
			if (set_dst_uri(_m, &path_dst) < 0) {
				LM_ERR("failed to set dst_uri of Path\n");
				ret = -3;
				goto done;
			}
		} else if (ptr->received.s && ptr->received.len) {
			if (set_dst_uri(_m, &ptr->received) < 0) {
				ret = -3;
				goto done;
			}
		}

		set_ruri_q( _m, ptr->q);

		setbflag( _m, 0, ptr->cflags);

		if (ptr->sock)
			_m->force_send_socket = ptr->sock;

		/* populate the 'attributes' avp */
		if (attr_avp_name != -1) {
			istr.s = ptr->attr;
			if (add_avp_last(AVP_VAL_STR, attr_avp_name, istr) != 0) {
				LM_ERR("Failed to populate attr avp!\n");
			}
		}

		ptr = ptr->next;
	}

	/* Append branches if enabled */
	/* If we got to this point and the URI had a ;gr parameter and it was matched
	 * to a contact. No point in branching */
	if ( flags&REG_LOOKUP_NOBRANCH_FLAG || (sip_instance.len && sip_instance.s) ) goto done;
	LM_DBG("looking for branches\n");

	do {
		for( ; ptr ; ptr = ptr->next ) {
			if (VALID_CONTACT(ptr, act_time) && allowed_method(_m,ptr,flags)) {
				path_dst.len = 0;
				if(ptr->path.s && ptr->path.len
				&& get_path_dst_uri(&ptr->path, &path_dst) < 0) {
					LM_ERR("failed to get dst_uri for Path\n");
					continue;
				}

				ua_re_check(continue);

				/* The same as for the first contact applies for branches
				 * regarding path vs. received. */
				LM_DBG("setting branch <%.*s>\n",ptr->c.len,ptr->c.s);
				if (append_branch(_m,&ptr->c,path_dst.len?&path_dst:&ptr->received,
				&ptr->path, ptr->q, ptr->cflags, ptr->sock) == -1) {
					LM_ERR("failed to append a branch\n");
					/* Also give a chance to the next branches*/
					continue;
				}

				/* populate the 'attributes' avp */
				if (attr_avp_name != -1) {
					istr.s = ptr->attr;
					if (add_avp_last(AVP_VAL_STR, attr_avp_name, istr) != 0) {
						LM_ERR("Failed to populate attr avp!\n");
					}
				}
			}
		}
		/* 0 branches condition also filled; idx initially -1*/
		if (!(flags&REG_BRANCH_AOR_LOOKUP_FLAG) || idx == nbranches)
			goto done;


		/* relsease old aor lock */
		ul.unlock_udomain((udomain_t*)_t, &aor);
		ul.release_urecord(r, 0);

		/* idx starts from -1 */
		uri = branch_uris[idx];
		if (extract_aor(&uri, &aor, NULL, &call_id) < 0) {
			LM_ERR("failed to extract address of record for branch uri\n");
			return -3;
		}

		/* release old urecord */

		/* get lock on new aor */
		LM_DBG("getting contacts from aor [%.*s]"
					"in branch %d\n", aor.len, aor.s, idx);
		ul.lock_udomain((udomain_t*)_t, &aor);
		res = ul.get_urecord((udomain_t*)_t, &aor, &r);

		if (res > 0) {
			LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
			goto done;
		}
		idx++;
		ptr = r->contacts;
	} while (1);
Beispiel #29
0
/*! \brief
 * Calculate the length of buffer needed to
 * print contacts
 * - mode specifies if GRUU header params are added
 */
static inline unsigned int calc_buf_len(ucontact_t* c, str *host, int mode)
{
	unsigned int len;
	int qlen;

	len = 0;
	while(c) {
		if (VALID_CONTACT(c, act_time)) {
			if (len) len += CONTACT_SEP_LEN;
			len += 2 /* < > */ + c->c.len;
			qlen = len_q(c->q);
			if (qlen) len += Q_PARAM_LEN + qlen;
			len += EXPIRES_PARAM_LEN + INT2STR_MAX_LEN;
			if (rcv_param.len>0 && c->received.s) {
				len += 1 /* ; */ 
					+ rcv_param.len 
					+ 1 /* = */ 
					+ 1 /* dquote */ 
					+ c->received.len
					+ 1 /* dquote */
					;
			}
			if (reg_gruu_enabled==1 && c->instance.len>0 && mode==1) {
				/* pub-gruu */
				len += PUB_GRUU_PARAM_LEN
					+ 1 /* " */
					+ 4 /* sip: */
					+ c->aor->len
					+ 1 /* @ */
					+ host->len
					+ GR_PARAM_LEN
					+ c->instance.len
					+ 1 /* " */
					;
				/* temp-gruu */
				len += TMP_GRUU_PARAM_LEN
					+ 1 /* " */
					+ 4 /* sip: */
					+ c->ruid.len
					+ 1 /* 'sep' */
					+ 8 /* max hex int */
					+ 1 /* @ */
					+ host->len
					+ GR_PARAM_LEN
					- 1 /* = */
					+ 1 /* " */
					;
			}
			if (c->instance.len>0) {
				/* +sip-instance */
				len += SIP_INSTANCE_PARAM_LEN
					+ 1 /* " */
					+ c->instance.len
					+ 1 /* " */
					;
			}
			if (c->reg_id>0) {
				/* reg-id */
				len += REG_ID_PARAM_LEN + INT2STR_MAX_LEN;
			}
		}
		c = c->next;
	}

	if (len) len += CONTACT_BEGIN_LEN + CRLF_LEN;
	return len;
}
Beispiel #30
0
/*!
 * \brief Expires timer for NO_DB db_mode
 *
 * Expires timer for NO_DB db_mode, process all contacts from
 * the record, delete the expired ones from memory.
 * \param _r processed record
 */
static inline void nodb_timer(impurecord_t* _r) {
    ucontact_t* ptr, *t;
    
    unsigned int hash_code = 0;

    reg_subscriber *s;
    subs_t* sub_dialog;

    get_act_time();

    s = _r->shead;
    LM_DBG("Checking validity of IMPU: <%.*s> registration subscriptions\n", _r->public_identity.len, _r->public_identity.s);
    while (s) {
        if (!valid_subscriber(s)) {
            LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> expired and removed.\n",
                    s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s);
            delete_subscriber(_r, s);
        } else {
            LM_DBG("DBG:registrar_timer: Subscriber with watcher_contact <%.*s> and presentity uri <%.*s> is valid and expires in %d seconds.\n",
                    s->watcher_contact.len, s->watcher_contact.s, s->presentity_uri.len, s->presentity_uri.s,
                    (unsigned int) (s->expires - time(NULL)));
	    hash_code = core_hash(&s->call_id, &s->to_tag, sub_dialog_hash_size);
	    LM_DBG("Hash size: <%i>", sub_dialog_hash_size);
	    LM_DBG("Searching sub dialog hash info with call_id: <%.*s> and ttag <%.*s> ftag <%.*s> and hash code <%i>", s->call_id.len, s->call_id.s, s->to_tag.len, s->to_tag.s, s->from_tag.len, s->from_tag.s, hash_code);
	    /* search the record in hash table */
	    lock_get(&sub_dialog_table[hash_code].lock);
	    sub_dialog= pres_search_shtable(sub_dialog_table, s->call_id, s->to_tag, s->from_tag, hash_code);
	    if(sub_dialog== NULL)
	    {
		LM_ERR("DBG:registrar_timer: Subscription has no dialog record in hash table\n");
	    }else {
		LM_DBG("DBG:registrar_timer: Subscription has dialog record in hash table with presentity uri <%.*s>\n", sub_dialog->pres_uri.len, sub_dialog->pres_uri.s);
	    }
	    
	    lock_release(&sub_dialog_table[hash_code].lock);
        }
        s = s->next;
    }

    ptr = _r->contacts;
    LM_DBG("Checking validity of IMPU: <%.*s> contacts\n", _r->public_identity.len, _r->public_identity.s);

    while (ptr) {
        if (!VALID_CONTACT(ptr, act_time)) {
            /* run callbacks for EXPIRE event */
            if (exists_ulcb_type(ptr->cbs, UL_CONTACT_EXPIRE))
                run_ul_callbacks(ptr->cbs, UL_CONTACT_EXPIRE, _r, ptr);

            if (exists_ulcb_type(_r->cbs, UL_IMPU_EXPIRE_CONTACT)) {
                run_ul_callbacks(_r->cbs, UL_IMPU_EXPIRE_CONTACT, _r, ptr);
            }

            LM_DBG("Binding '%.*s','%.*s' has expired\n",
                    ptr->aor->len, ZSW(ptr->aor->s),
                    ptr->c.len, ZSW(ptr->c.s));

            t = ptr;
            ptr = ptr->next;

			if (db_mode == WRITE_THROUGH && db_delete_ucontact(_r, t) != 0) {
				LM_ERR("error removing contact from DB [%.*s]... will still remove from memory\n", t->c.len, t->c.s);
			}

            mem_delete_ucontact(_r, t);
            update_stat(_r->slot->d->expires, 1);
        } else {
            LM_DBG("IMPU:<%.*s> - contact:<%.*s> is valid and expires in %d seconds\n", _r->public_identity.len, _r->public_identity.s,
                    ptr->c.len, ptr->c.s,
                    (unsigned int) (ptr->expires - time(NULL)));
            ptr = ptr->next;
        }
    }
}