예제 #1
0
파일: notify.c 프로젝트: 4N7HR4X/kamailio
int unregister_watcher(str* _f, str* _t, notcb_t _c, void* _data)
{
	udomain_t* d;
	urecord_t* r;

	if (find_domain(&dom, &d) > 0) {
		LOG(L_ERR, "unregister_watcher(): Domain '%.*s' not found\n", dom.len, ZSW(dom.s));
		return -1;
	}
	
	lock_udomain(d);
	
	if (get_urecord(d, _t, &r) > 0) {
		unlock_udomain(d);
		DBG("unregister_watcher(): Record not found\n");
		return 0;
	}

	remove_watcher(r, _c, _data);
	release_urecord(r);

	unlock_udomain(d);

	return 0;
}
예제 #2
0
int timer_udomain(udomain_t* _d)
{
	struct urecord* ptr, *t;

	lock_udomain(_d);

	ptr = _d->d_ll.first;

	while(ptr) {
		if (timer_urecord(ptr) < 0) {
			LOG(L_ERR, "timer_udomain(): Error in timer_urecord\n");
			unlock_udomain(_d);
			return -1;
		}
		
		     /* Remove the entire record
		      * if it is empty
		      */
		if (ptr->contacts == 0) {
			t = ptr;
			ptr = ptr->d_ll.next;
			mem_delete_urecord(_d, t);
		} else {
			ptr = ptr->d_ll.next;
		}
	}
	
	unlock_udomain(_d);
/*	process_del_list(_d->name); */
/*	process_ins_list(_d->name); */
	return 0;
}
예제 #3
0
/**
 * Note: prevents the creation of any duplicate AoR
 */
static int receive_urecord_insert(bin_packet_t *packet)
{
	str d, aor;
	urecord_t *r;
	udomain_t *domain;

	bin_pop_str(packet, &d);
	bin_pop_str(packet, &aor);

	if (find_domain(&d, &domain) != 0) {
		LM_ERR("domain '%.*s' is not local\n", d.len, d.s);
		goto out_err;
	}

	lock_udomain(domain, &aor);

	if (get_urecord(domain, &aor, &r) == 0)
		goto out;

	if (insert_urecord(domain, &aor, &r, 1) != 0) {
		unlock_udomain(domain, &aor);
		goto out_err;
	}

out:
	unlock_udomain(domain, &aor);

	return 0;

out_err:
	LM_ERR("failed to replicate event locally. dom: '%.*s', aor: '%.*s'\n",
		d.len, d.s, aor.len, aor.s);
	return -1;
}
예제 #4
0
static int receive_urecord_delete(bin_packet_t *packet)
{
	str d, aor;
	udomain_t *domain;

	bin_pop_str(packet, &d);
	bin_pop_str(packet, &aor);

	if (find_domain(&d, &domain) != 0) {
		LM_ERR("domain '%.*s' is not local\n", d.len, d.s);
		goto out_err;
	}

	lock_udomain(domain, &aor);

	if (delete_urecord(domain, &aor, NULL, 1) != 0) {
		unlock_udomain(domain, &aor);
		goto out_err;
	}

	unlock_udomain(domain, &aor);

	return 0;

out_err:
	LM_ERR("failed to process replication event. dom: '%.*s', aor: '%.*s'\n",
		d.len, d.s, aor.len, aor.s);
	return -1;
}
예제 #5
0
파일: notify.c 프로젝트: 4N7HR4X/kamailio
int register_watcher(str* _f, str* _t, notcb_t _c, void* _data)
{
	udomain_t* d;
	urecord_t* r;

	if (find_domain(&dom, &d) > 0) {
		LOG(L_ERR, "register_watcher(): Domain '%.*s' not found\n", dom.len, ZSW(dom.s));
		return -1;
	}

	lock_udomain(d);

	if (get_urecord(d, _t, &r) > 0) {
		if (insert_urecord(d, _t, &r) < 0) {
			unlock_udomain(d);
			LOG(L_ERR, "register_watcher(): Error while creating a new record\n");
			return -2;
		}
	}

	if (add_watcher(r, _c, _data) < 0) {
		LOG(L_ERR, "register_watcher(): Error while adding a watcher\n");
		release_urecord(r);
		unlock_udomain(d);
		return -3;
	}

	unlock_udomain(d);

	return 0;
}
예제 #6
0
파일: ul_mi.c 프로젝트: tripped/kamailio
/*!
 * \brief Delete a address of record including its contacts
 * \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
 */
struct mi_root* mi_usrloc_rm_aor(struct mi_root *cmd, void *param)
{
	struct mi_node *node;
	udomain_t *dom;
	str *aor;

	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);
	if (delete_urecord( dom, aor, 0) < 0) {
		unlock_udomain( dom, aor);
		return init_mi_tree( 500, "Failed to delete AOR", 20);
	}

	unlock_udomain( dom, aor);
	return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
}
예제 #7
0
파일: ul_rpc.c 프로젝트: 4N7HR4X/kamailio
static void rpc_add_contact(rpc_t* rpc, void* c)
{
	udomain_t* d;
	int expires, flags, sid;
	double q;
	qvalue_t qval;
	
	str table, uid, contact;
	
	if (rpc->scan(c, "SSSdfd", &table, &uid, &contact, &expires, &q, &flags) < 6) return;
	qval = double2q(q);
	if (rpc->scan(c, "d", &sid) < 1) sid = -1;

	rpc_find_domain(&table, &d);
	if (d) {
		lock_udomain(d);
		
		if (add_contact(d, &uid, &contact, expires, qval, flags, sid) < 0) {
			unlock_udomain(d);
			ERR("Error while adding contact ('%.*s','%.*s') in table '%.*s'\n",
				uid.len, ZSW(uid.s), contact.len, ZSW(contact.s), table.len, ZSW(table.s));
			rpc->fault(c, 500, "Error while adding Contact");
			return;
		}
		unlock_udomain(d);
	} else {
		rpc->fault(c, 400, "Table Not Found");
	}
}
예제 #8
0
static int receive_ucontact_delete(bin_packet_t *packet)
{
	udomain_t *domain;
	urecord_t *record;
	ucontact_t *contact;
	str d, aor, contact_str, callid;
	int cseq, rc;

	bin_pop_str(packet, &d);
	bin_pop_str(packet,&aor);
	bin_pop_str(packet,&contact_str);
	bin_pop_str(packet,&callid);
	bin_pop_int(packet,&cseq);

	if (find_domain(&d, &domain) != 0) {
		LM_ERR("domain '%.*s' is not local\n", d.len, d.s);
		goto error;
	}

	lock_udomain(domain, &aor);

	/* failure in retrieving a urecord may be ok, because packet order in UDP
	 * is not guaranteed, so urecord_delete commands may arrive before
	 * ucontact_delete's */
	if (get_urecord(domain, &aor, &record) != 0) {
		LM_INFO("failed to fetch local urecord - ignoring request "
			"(ci: '%.*s')\n", callid.len, callid.s);
		unlock_udomain(domain, &aor);
		return 0;
	}

	/* simply specify a higher cseq and completely avoid any complications */
	rc = get_ucontact(record, &contact_str, &callid, cseq + 1, &contact);
	if (rc != 0 && rc != 2) {
		LM_ERR("contact '%.*s' not found: (ci: '%.*s')\n", contact_str.len,
			contact_str.s, callid.len, callid.s);
		unlock_udomain(domain, &aor);
		goto error;
	}

	if (skip_replicated_db_ops)
		contact->flags |= FL_MEM;

	if (delete_ucontact(record, contact, 1) != 0) {
		LM_ERR("failed to delete ucontact '%.*s' (ci: '%.*s')\n",
			contact_str.len, contact_str.s, callid.len, callid.s);
		unlock_udomain(domain, &aor);
		goto error;
	}

	unlock_udomain(domain, &aor);

	return 0;

error:
	LM_ERR("failed to process replication event. dom: '%.*s', aor: '%.*s'\n",
	        d.len, d.s, aor.len, aor.s);
	return -1;
}
예제 #9
0
/*!
 * \brief Delete a contact from an AOR record
 * \param cmd mi_root containing the parameter
 * \param param not used
 * \note expects 3 nodes: the table name, the AOR and contact
 * \return mi_root with the result or 0 on failure
 */
struct mi_root* mi_usrloc_rm_contact(struct mi_root *cmd, void *param)
{
	struct mi_node *node;
	udomain_t *dom;
	urecord_t *rec;
	ucontact_t* con;
	str *aor, *contact;
	int ret;

	node = cmd->node.kids;
	if (node==NULL || node->next==NULL || node->next->next==NULL ||
	node->next->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);
	}

	contact = &node->next->next->value;
	set_mi_ul_cid();
	ret = get_ucontact( rec, contact, &mi_ul_cid, &mi_ul_path, MI_UL_CSEQ+1, &con);
	if (ret < 0) {
		unlock_udomain( dom, aor);
		return 0;
	}
	if (ret > 0) {
		unlock_udomain( dom, aor);
		return init_mi_tree( 404, "Contact not found", 17);
	}

	if (delete_ucontact(rec, con) < 0) {
		unlock_udomain( dom, aor);
		return 0;
	}

	release_urecord(rec);
	unlock_udomain( dom, aor);
	return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
}
예제 #10
0
void external_delete_subscriber(reg_subscriber *s, udomain_t* _t, int lock_domain) {
    LM_DBG("Deleting subscriber");
    impurecord_t* urec;
   
    LM_DBG("Updating reg subscription in IMPU record");

    if(lock_domain) lock_udomain(_t, &s->presentity_uri);
    int res = get_impurecord(_t, &s->presentity_uri, &urec);
    if (res != 0) {
        if(lock_domain) unlock_udomain(_t, &s->presentity_uri);
        return;
    }

    delete_subscriber(urec, s);

    if(lock_domain) unlock_udomain(_t, &s->presentity_uri);

}
예제 #11
0
파일: ul_rpc.c 프로젝트: 4N7HR4X/kamailio
static void rpc_delete_uid(rpc_t* rpc, void* c)
{
	udomain_t* d;
	str uid, t;
	
	if (rpc->scan(c, "SS", &t, &uid) < 2) return;
	
	rpc_find_domain(&t, &d);
	if (d) {
		lock_udomain(d);
		if (delete_urecord(d, &uid) < 0) {
			ERR("Error while deleting user %.*s\n", uid.len, uid.s);
			unlock_udomain(d);
			rpc->fault(c, 500, "Error While Deleting Record");
			return;
		}
		unlock_udomain(d);
	} else {
		rpc->fault(c, 400, "Table Not Found");
	}
}
예제 #12
0
파일: ul_rpc.c 프로젝트: 4N7HR4X/kamailio
static void rpc_show_contacts(rpc_t* rpc, void* c)
{
	udomain_t* d;
	urecord_t* r;
	int res;
	str t, uid;
	
	if (rpc->scan(c, "SS", &t, &uid) < 2) return;
	
	rpc_find_domain(&t, &d);
	if (d) {
		lock_udomain(d);
		
		res = get_urecord(d, &uid, &r);
		if (res < 0) {
			rpc->fault(c, 500, "Error While Searching AOR");
			ERR("Error while looking for username %.*s in table %.*s\n", uid.len, uid.s, t.len, t.s);
			unlock_udomain(d);
			return;
		}
		
		if (res > 0) {
			rpc->fault(c, 404, "AOR Not Found");
			unlock_udomain(d);
			return;
		}
		
		get_act_time();
		
		if (!print_contacts(rpc, c, r->contacts)) {
			unlock_udomain(d);
			rpc->fault(c, 404, "No Registered Contacts Found");
			return;
		}
		
		unlock_udomain(d);
	} else {
		rpc->fault(c, 400, "Table Not Found");
	}
}
예제 #13
0
void external_delete_subscriber(reg_subscriber *s, udomain_t* _t, int lock_domain) {
    LM_DBG("Deleting subscriber");
    impurecord_t* urec;
   
    LM_DBG("Updating reg subscription in IMPU record");

    if(lock_domain) lock_udomain(_t, &s->presentity_uri);
    int res = get_impurecord(_t, &s->presentity_uri, &urec);
    if (res != 0) {
        if(lock_domain) unlock_udomain(_t, &s->presentity_uri);
        return;
    }

    if (urec->shead == s) urec->shead = s->next;
    else s->prev->next = s->next;
    if (urec->stail == s) urec->stail = s->prev;
    else s->next->prev = s->prev;
    LM_DBG("About to free subscriber memory");
    free_subscriber(s);

    if(lock_domain) unlock_udomain(_t, &s->presentity_uri);

}
예제 #14
0
파일: reg_avps.c 프로젝트: 4N7HR4X/kamailio
int read_reg_avps(struct sip_msg *m, char* _domain, char* fp)
{
	urecord_t* r = NULL;
	struct ucontact *contact = NULL;
	udomain_t *d;
	str uid;
	
	if (!use_reg_avps()) return 1;

	d = (udomain_t*)_domain;
	if (get_str_fparam(&uid, m, (fparam_t*)fp) < 0) {
		ERR("invalid parameter\n");
		return -1;
	}
	
/*	INFO("reading avps for uid=%.*s\n", uid.len, ZSW(uid.s)); */

	lock_udomain(d);
	
	if (get_urecord(d, &uid, &r) != 0) {
		unlock_udomain(d);
		WARN("urecord not found\n");
		return -1;
	}

	if (get_ucontact(r, &m->new_uri, &contact) != 0) {
		unlock_udomain(d);
		WARN("ucontact not found\n");
		return -1;
	}

	load_reg_avps(contact);
	
	unlock_udomain(d);
	
	return 1;
}
예제 #15
0
/*
 * Free all memory allocated for
 * the domain
 */
void free_udomain(udomain_t* _d)
{
	int i;
	
	lock_udomain(_d);
	if (_d->table) {
		for(i = 0; i < UDOMAIN_HASH_SIZE; i++) {
			deinit_slot(_d->table + i);
		}
		shm_free(_d->table);
	}
	unlock_udomain(_d);
	lock_destroy(&_d->lock);/* destroy the lock (required for SYSV sems!)*/

        shm_free(_d);
}
예제 #16
0
파일: ul_rpc.c 프로젝트: 4N7HR4X/kamailio
static void rpc_delete_contact(rpc_t* rpc, void* ctx)
{
	udomain_t* d;
	urecord_t* r;
	ucontact_t* con;
	str uid, t, c;
	int res;
	
	if (rpc->scan(ctx, "SSS", &t, &uid, &c) < 3) return;
	
	rpc_find_domain(&t, &d);
	
	if (d) {
		lock_udomain(d);
		
		res = get_urecord(d, &uid, &r);
		if (res < 0) {
			rpc->fault(ctx, 500, "Error While Searching Table");
			ERR("Error while looking for uid %.*s in table %.*s\n", uid.len, uid.s, t.len, t.s);
			unlock_udomain(d);
			return;
		}
		
		if (res > 0) {
			rpc->fault(ctx, 404, "AOR Not Found");
			unlock_udomain(d);
			return;
		}
		
		res = get_ucontact(r, &c, &con);
		if (res < 0) {
			rpc->fault(ctx, 500, "Error While Searching for Contact");
			ERR("Error while looking for contact %.*s\n", c.len, c.s);
			unlock_udomain(d);
			return;
		}
		
		if (res > 0) {
			rpc->fault(ctx, 404, "Contact Not Found");
			unlock_udomain(d);
			return;
		}
		
		if (delete_ucontact(r, con) < 0) {
			rpc->fault(ctx, 500, "Error While Deleting Contact");
			unlock_udomain(d);
			return;
		}
		
		release_urecord(r);
		unlock_udomain(d);
	} else {
		rpc->fault(ctx, 404, "Table Not Found");
	}
}
예제 #17
0
파일: ul_rpc.c 프로젝트: aallamaa/kamailio
static void ul_rpc_show_impu(rpc_t* rpc, void* ctx)
{
	int i, j;
	str impu;
	int res;
	udomain_t* domain;
	struct impurecord* impu_rec;
	ucontact_t* contact;
	void *ah, *sh, *ch, *cdh, *sdh, *sph, *spi;
	char numstr[21+16]; //enough for all numbers up to 64bits + longest length of field name (16)

	if (rpc->scan(ctx, "S", &impu) < 1) {
		rpc->fault(ctx, 400, "required IMPU argument");
		return;
	}

	LM_DBG("searching for impu <%.*s>\n", impu.len, impu.s);

	res = get_udomain("location", &domain);
	if (res != 0) {
		LM_ERR("Failed to get domain\n");
		return;
	}

	lock_udomain(domain, &impu);
	res = get_impurecord(domain, &impu, &impu_rec);
	if (res != 0) {
		unlock_udomain(domain, &impu);
		return;
	}

	//now print the data for this IMPU record
	if (rpc->add(ctx, "{", &ah) < 0) {
		rpc->fault(ctx, 500, "Internal error creating IMPU struct");
		unlock_udomain(domain, &impu);
		return;
	}

	if (rpc->struct_add(ah, "SsdSSSS",
			"impu", &impu,
			"state", get_impu_regstate_as_string(impu_rec->reg_state),
			"barring", impu_rec->barring,
			"ccf1", &impu_rec->ccf1,
			"ccf2", &impu_rec->ccf2,
			"ecf1", &impu_rec->ecf1,
			"ecf2", &impu_rec->ecf2
			) < 0) {
		rpc->fault(ctx, 500, "Internal error adding impu data");
		unlock_udomain(domain, &impu);
		return;
	}

	if (rpc->struct_add(ah, "{", "subscription", &sh) < 0) {
		rpc->fault(ctx, 500, "Internal error adding impu subscription data");
		unlock_udomain(domain, &impu);
		return;
	}

	ims_subscription* subscription = impu_rec->s;
	lock_get(subscription->lock);
	//add subscription data
	if (rpc->struct_add(sh, "S{", "impi", &subscription->private_identity, "service profiles", &sph) < 0) {
		rpc->fault(ctx, 500, "Internal error adding impu subscription data");
		lock_release(subscription->lock);
		unlock_udomain(domain, &impu);
		return;
	}

	//add subscription detail information
	for (i=0; i<subscription->service_profiles_cnt; i++) {
		sprintf(numstr, "%d", i+1);
		if (rpc->struct_add(sph, "{", numstr, &sdh) < 0) {
			rpc->fault(ctx, 500, "Internal error adding impu subscription detail data");
			lock_release(subscription->lock);
			unlock_udomain(domain, &impu);
			return;
		}
		if (rpc->struct_add(sdh, "{", "impus", &spi) < 0) {
				rpc->fault(ctx, 500, "Internal error adding impu subscription data");
				lock_release(subscription->lock);
				unlock_udomain(domain, &impu);
				return;
		}

		for (j=0; j<subscription->service_profiles[i].public_identities_cnt; j++) {
			sprintf(numstr, "%d", j+1);
			if (rpc->struct_add(spi, "S", numstr, &subscription->service_profiles[i].public_identities[j].public_identity) < 0) {
					rpc->fault(ctx, 500, "Internal error adding impu subscription detail data");
					lock_release(subscription->lock);
					unlock_udomain(domain, &impu);
					return;
			}
		}
	}

	lock_release(subscription->lock);

	//add contact data
	if (rpc->struct_add(ah, "{", "contacts", &ch) < 0) {
		rpc->fault(ctx, 500, "Internal error adding impu contact data");
		unlock_udomain(domain, &impu);
		return;
	}
	contact = impu_rec->contacts;
	while (contact) {
		//contact is not null terminated so we need to create a null terminated version
		if (!contact_buf.s || (contact_buf.len <= contact->c.len)) {
			if (contact_buf.s && contact_buf.len <= contact->c.len){
				pkg_free(contact_buf.s);
			}
			contact_buflen = contact->c.len + 1;
			contact_buf.s = (char*)pkg_malloc(contact_buflen);
			if (!contact_buf.s) {
				LM_ERR("no more pkg memory");
				rpc->fault(ctx, 500, "Internal error adding impu contact header");
				unlock_udomain(domain, &impu);
				return;
			}
		}
		memcpy(contact_buf.s, contact->c.s, contact->c.len);
		contact_buf.s[contact->c.len] = '\0';
		contact_buf.len = contact->c.len;

		LM_DBG("contact is %s\n", contact_buf.s);
		if (rpc->struct_add(ch, "{", contact_buf.s, &cdh) < 0) {
			rpc->fault(ctx, 500, "Internal error adding impu contact header");
			unlock_udomain(domain, &impu);
			return;
		}
		if (rpc->struct_add(cdh, "dS",
				"expires", contact->expires - time(NULL),
				"client", &contact->user_agent) < 0) {
			rpc->fault(ctx, 500, "Internal error adding impu contact data");
			unlock_udomain(domain, &impu);
			return;
		}
		contact = contact->next;
	}

	unlock_udomain(domain, &impu);

}
예제 #18
0
파일: ul_fifo.c 프로젝트: OPSF/uClinux
static int ul_rm_contact(FILE* pipe, char* response_file)
{
	char table[MAX_TABLE];
	char user[MAX_USER];
	char contact[MAX_CONTACT_LEN];
	udomain_t* d;
	urecord_t* r;
	ucontact_t* con;
	str aor, t, c;
	int res;
	char* at;

	if (!read_line(table, MAX_TABLE, pipe, &t.len) || t.len ==0) {
		fifo_reply(response_file, 
			   "400 ul_rm_contact: table name expected\n");
		LOG(L_ERR, "ERROR: ul_rm_contact: table name expected\n");
		return 1;
	}
	if (!read_line(user, MAX_USER, pipe, &aor.len) || aor.len==0) {
		fifo_reply(response_file, 
			   "400 ul_rm_contact: user name expected\n");
		LOG(L_ERR, "ERROR: ul_rm_contact: user name expected\n");
		return 1;
	}

	at = memchr(user, '@', aor.len);

	if (use_domain) {
		if (!at) {
			fifo_reply(response_file,
				   "400 ul_rm_contact: user@domain expected\n");
			LOG(L_ERR, "ERROR: ul_rm_contact: Domain missing\n");
			return 1;
		}
	} else {
		if (at) {
			aor.len = at - user;
		}
	}


	if (!read_line(contact, MAX_CONTACT_LEN, pipe, &c.len) || c.len == 0) {
		fifo_reply(response_file,
			   "400 ul_rm_contact: contact expected\n");
		LOG(L_ERR, "ERROR: ul_rm_contact: contact expected\n");
		return 1;
	}

	aor.s = user;
	strlower(&aor);

	t.s = table;
	c.s = contact;

	fifo_find_domain(&t, &d);

	LOG(L_INFO, "INFO: deleting user-loc contact (%s,%s,%s)\n",
	    table, user, contact );


	if (d) {
		lock_udomain(d);

		res = get_urecord(d, &aor, &r);
		if (res < 0) {
			fifo_reply(response_file, "500 Error while looking for username %s in table %s\n", user, table);
			LOG(L_ERR, "ERROR: ul_rm_contact: Error while looking for username %s in table %s\n", user, table);
			unlock_udomain(d);
			return 1;
		}
		
		if (res > 0) {
			fifo_reply(response_file, "404 Username %s in table %s not found\n", user, table);
			unlock_udomain(d);
			return 1;
		}

		res = get_ucontact(r, &c, &con);
		if (res < 0) {
			fifo_reply(response_file, "500 Error while looking for contact %s\n", contact);
			LOG(L_ERR, "ERROR: ul_rm_contact: Error while looking for contact %s\n", contact);
			unlock_udomain(d);
			return 1;
		}			

		if (res > 0) {
			fifo_reply(response_file, "404 Contact %s in table %s not found\n", contact, table);
			unlock_udomain(d);
			return 1;
		}

		if (delete_ucontact(r, con) < 0) {
			fifo_reply(response_file, "500 ul_rm_contact: Error while deleting contact %s\n", contact);
			unlock_udomain(d);
			return 1;
		}

		release_urecord(r);
		unlock_udomain(d);
		fifo_reply(response_file, "200 Contact (%s, %s) deleted from table %s\n", 
			user, contact, table);
		return 1;
	} else {
		fifo_reply(response_file, "400 table (%s) not found\n", table);
		return 1;
	}

}
예제 #19
0
파일: ul_mi.c 프로젝트: tripped/kamailio
/*!
 * \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;
}
예제 #20
0
파일: ul_fifo.c 프로젝트: OPSF/uClinux
static inline int ul_show_contact(FILE* pipe, char* response_file)
{
	char table[MAX_TABLE];
	char user[MAX_USER];
	FILE* reply_file;
	udomain_t* d;
	urecord_t* r;
	int res;
	str t, aor;
	char* at;

	if (!read_line(table, MAX_TABLE, pipe, &t.len) || t.len ==0) {
		fifo_reply(response_file, 
			   "400 ul_show_contact: table name expected\n");
		LOG(L_ERR, "ERROR: ul_show_contact: table name expected\n");
		return 1;
	}
	if (!read_line(user, MAX_USER, pipe, &aor.len) || aor.len==0) {
		fifo_reply(response_file, 
			   "400 ul_show_contact: user name expected\n");
		LOG(L_ERR, "ERROR: ul_show_contact: user name expected\n");
		return 1;
	}
	
	at = memchr(user, '@', aor.len);

	if (use_domain) {
		if (!at) {
			fifo_reply(response_file,
				   "400 ul_show_contact: user@domain expected\n");
			LOG(L_ERR, "ERROR: ul_show_contact: Domain missing\n");
			return 1;
		}
	} else {
		if (at) {
			aor.len = at - user;
		}
	}

	aor.s = user;
	strlower(&aor);

	t.s = table;
	
	fifo_find_domain(&t, &d);

	if (d) {
		lock_udomain(d);	

		res = get_urecord(d, &aor, &r);
		if (res < 0) {
			fifo_reply(response_file, "500 Error while looking for username %s in table %s\n", user, table);
			LOG(L_ERR, "ERROR: ul_show_contact: Error while looking for username %s in table %s\n", user, table);
			unlock_udomain(d);
			return 1;
		}
		
		if (res > 0) {
			fifo_reply(response_file, "404 Username %s in table %s not found\n", user, table);
			unlock_udomain(d);
			return 1;
		}
		
		get_act_time();

		reply_file=open_reply_pipe(response_file);
		if (reply_file==0) {
			LOG(L_ERR, "ERROR: ul_show_contact: file not opened\n");
			unlock_udomain(d);
			return 1;
		}

		if (!print_contacts(reply_file, r->contacts)) {
			unlock_udomain(d);
			fprintf(reply_file, "404 No registered contacts found\n");
			fclose(reply_file);
			return 1;
		}

		fclose(reply_file);
		unlock_udomain(d);
		return 1;
	} else {
		fifo_reply(response_file, "400 table (%s) not found\n", table);
		return 1;
	}
}
예제 #21
0
파일: ul_mi.c 프로젝트: tripped/kamailio
/*!
 * \brief Add a new contact for an address of record
 * \param cmd mi_root containing the parameter
 * \param param not used
 * \note Expects 7 nodes: table name, AOR, contact, expires, Q,
 * useless - backward compatible, flags, cflags, methods
 * \return mi_root with the result
 */
struct mi_root* mi_usrloc_add(struct mi_root *cmd, void *param)
{
	ucontact_info_t ci;
	urecord_t* r;
	ucontact_t* c;
	struct mi_node *node;
	udomain_t *dom;
	str *aor, *contact;
	unsigned int ui_val;
	int n;

	for( n=0,node = cmd->node.kids; n<9 && node ; n++,node=node->next );
	if (n!=9 || node!=0)
		return init_mi_tree( 400, MI_MISSING_PARM_S, MI_MISSING_PARM_LEN);

	node = cmd->node.kids;

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

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

	/* contact (param 3) */
	node = node->next;
	contact = &node->value;

	memset( &ci, 0, sizeof(ucontact_info_t));

	/* expire (param 4) */
	node = node->next;
	if (str2int( &node->value, &ui_val) < 0)
		goto bad_syntax;
	ci.expires = ui_val;

	/* q value (param 5) */
	node = node->next;
	if (str2q( &ci.q, node->value.s, node->value.len) < 0)
		goto bad_syntax;

	/* unused value (param 6) FIXME */
	node = node->next;

	/* flags value (param 7) */
	node = node->next;
	if (str2int( &node->value, (unsigned int*)&ci.flags) < 0)
		goto bad_syntax;

	/* branch flags value (param 8) */
	node = node->next;
	if (str2int( &node->value, (unsigned int*)&ci.cflags) < 0)
		goto bad_syntax;

	/* methods value (param 9) */
	node = node->next;
	if (str2int( &node->value, (unsigned int*)&ci.methods) < 0)
		goto bad_syntax;

	if(sruid_next(&_ul_sruid)<0)
		goto error;
	ci.ruid = _ul_sruid.uid;

	lock_udomain( dom, aor);

	n = get_urecord( dom, aor, &r);
	if ( n==1) {
		if (insert_urecord( dom, aor, &r) < 0)
			goto lock_error;
		c = 0;
	} else {
		if (get_ucontact( r, contact, &mi_ul_cid, &mi_ul_path, MI_UL_CSEQ+1, &c) < 0)
			goto lock_error;
	}

	get_act_time();

	ci.callid = &mi_ul_cid;
	ci.user_agent = &mi_ul_ua;
	ci.cseq = MI_UL_CSEQ;
	/* 0 expires means permanent contact */
	if (ci.expires!=0)
		ci.expires += act_time;

	if (c) {
		if (update_ucontact( r, c, &ci) < 0)
			goto release_error;
	} else {
		if ( insert_ucontact( r, contact, &ci, &c) < 0 )
			goto release_error;
	}

	release_urecord(r);

	unlock_udomain( dom, aor);

	return init_mi_tree( 200, MI_OK_S, MI_OK_LEN);
bad_syntax:
	return init_mi_tree( 400, MI_BAD_PARM_S, MI_BAD_PARM_LEN);
release_error:
	release_urecord(r);
lock_error:
	unlock_udomain( dom, aor);
error:
	return init_mi_tree( 500, MI_INTERNAL_ERR_S, MI_INTERNAL_ERR_LEN);
}
예제 #22
0
static int receive_ucontact_insert(bin_packet_t *packet)
{
	static ucontact_info_t ci;
	static str d, aor, host, contact_str, callid,
		user_agent, path, attr, st, sock;
	udomain_t *domain;
	urecord_t *record;
	ucontact_t *contact;
	int rc, port, proto;

	memset(&ci, 0, sizeof ci);

	bin_pop_str(packet, &d);
	bin_pop_str(packet, &aor);

	if (find_domain(&d, &domain) != 0) {
		LM_ERR("domain '%.*s' is not local\n", d.len, d.s);
		goto error;
	}

	bin_pop_str(packet, &contact_str);

	bin_pop_str(packet, &st);
	memcpy(&ci.contact_id, st.s, sizeof ci.contact_id);

	bin_pop_str(packet, &callid);
	ci.callid = &callid;

	bin_pop_str(packet, &user_agent);
	ci.user_agent = &user_agent;

	bin_pop_str(packet, &path);
	ci.path = &path;

	bin_pop_str(packet, &attr);
	ci.attr = &attr;

	bin_pop_str(packet, &ci.received);
	bin_pop_str(packet, &ci.instance);

	bin_pop_str(packet, &st);
	memcpy(&ci.expires, st.s, sizeof ci.expires);

	bin_pop_str(packet, &st);
	memcpy(&ci.q, st.s, sizeof ci.q);

	bin_pop_str(packet, &sock);

	if (sock.s && sock.s[0]) {
		if (parse_phostport(sock.s, sock.len, &host.s, &host.len,
			&port, &proto) != 0) {
			LM_ERR("bad socket <%.*s>\n", sock.len, sock.s);
			goto error;
		}

		ci.sock = grep_sock_info(&host, (unsigned short) port,
			(unsigned short) proto);
		if (!ci.sock)
			LM_DBG("non-local socket <%.*s>\n", sock.len, sock.s);
	} else {
		ci.sock =  NULL;
	}

	bin_pop_int(packet, &ci.cseq);
	bin_pop_int(packet, &ci.flags);
	bin_pop_int(packet, &ci.cflags);
	bin_pop_int(packet, &ci.methods);

	bin_pop_str(packet, &st);
	memcpy(&ci.last_modified, st.s, sizeof ci.last_modified);

	if (skip_replicated_db_ops)
		ci.flags |= FL_MEM;

	lock_udomain(domain, &aor);

	if (get_urecord(domain, &aor, &record) != 0) {
		LM_INFO("failed to fetch local urecord - creating new one "
			"(ci: '%.*s') \n", callid.len, callid.s);

		if (insert_urecord(domain, &aor, &record, 1) != 0) {
			LM_ERR("failed to insert new record\n");
			unlock_udomain(domain, &aor);
			goto error;
		}
	}

	rc = get_ucontact(record, &contact_str, &callid, ci.cseq, &contact);
	switch (rc) {
	case -2:
		/* received data is consistent with what we have */
	case -1:
		/* received data is older than what we have */
		break;
	case 0:
		/* received data is newer than what we have */
		if (update_ucontact(record, contact, &ci, 1) != 0) {
			LM_ERR("failed to update ucontact (ci: '%.*s')\n", callid.len, callid.s);
			unlock_udomain(domain, &aor);
			goto error;
		}
		break;
	case 1:
		if (insert_ucontact(record, &contact_str, &ci, &contact, 1) != 0) {
			LM_ERR("failed to insert ucontact (ci: '%.*s')\n", callid.len, callid.s);
			unlock_udomain(domain, &aor);
			goto error;
		}
		break;
	}

	unlock_udomain(domain, &aor);
	return 0;

error:
	LM_ERR("failed to process replication event. dom: '%.*s', aor: '%.*s'\n",
		d.len, d.s, aor.len, aor.s);
	return -1;
}
예제 #23
0
/*!
 * \brief Load all records from a udomain
 *
 * Load all records from a udomain, useful to populate the
 * memory cache on startup.
 * \param _c database connection
 * \param _d loaded domain
 * \return 0 on success, -1 on failure
 */
int preload_udomain(db1_con_t* _c, udomain_t* _d)
{
	pcontact_info_t *ci;
	db_row_t *row;
	db_key_t columns[18];
	db1_res_t* res = NULL;
	str aor, contact;
	int i, n;

	pcontact_t* c;

	LM_DBG("pre-loading domain from DB\n");

	columns[0] = &domain_col;
	columns[1] = &aor_col;
	columns[2] = &contact_col;
	columns[3] = &received_col;
	columns[4] = &rx_session_id_col;
	columns[5] = &reg_state_col;
	columns[6] = &expires_col;
	columns[7] = &socket_col;
	columns[8] = &service_routes_col;
	columns[9] = &public_ids_col;
	columns[10] = &path_col;

	if (ul_dbf.use_table(_c, _d->name) < 0) {
		LM_ERR("sql use_table failed\n");
		return -1;
	}

#ifdef EXTRA_DEBUG
	LM_NOTICE("load start time [%d]\n", (int)time(NULL));
#endif

	if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
		if (ul_dbf.query(_c, 0, 0, 0, columns, 0, 11, 0, 0) < 0) {
			LM_ERR("db_query (1) failed\n");
			return -1;
		}
		if(ul_dbf.fetch_result(_c, &res, ul_fetch_rows)<0) {
			LM_ERR("fetching rows failed\n");
			return -1;
		}
	} else {
		if (ul_dbf.query(_c, 0, 0, 0, columns, 0, 11, 0, &res) < 0) {
			LM_ERR("db_query failed\n");
			return -1;
		}
	}

	if (RES_ROW_N(res) == 0) {
		LM_DBG("table is empty\n");
		ul_dbf.free_result(_c, res);
		return 0;
	}

	LM_DBG("%d rows returned in preload\n", RES_ROW_N(res));

	n = 0;
	do {
		LM_DBG("loading records - cycle [%d]\n", ++n);
		for(i = 0; i < RES_ROW_N(res); i++) {
			row = RES_ROWS(res) + i;

			aor.s = (char*) VAL_STRING(ROW_VALUES(row) + 1);
			if (VAL_NULL(ROW_VALUES(row) + 1) || aor.s == 0 || aor.s[0] == 0) {
				LM_CRIT("empty aor record in table %s...skipping\n", _d->name->s);
				continue;
			}
			aor.len = strlen(aor.s);

			ci = dbrow2info( ROW_VALUES(row)+1, &contact);
			if (ci==0) {
				LM_ERR("usrloc record for %.*s in table %s\n",
						aor.len, aor.s, _d->name->s);
				continue;
			}
			lock_udomain(_d, &aor);

			if ( (mem_insert_pcontact(_d, &aor, ci, &c)) != 0) {
				LM_ERR("inserting contact failed\n");
				unlock_udomain(_d, &aor);
				goto error1;
			}
			unlock_udomain(_d, &aor);
		}

		if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
			if(ul_dbf.fetch_result(_c, &res, ul_fetch_rows)<0) {
				LM_ERR("fetching rows (1) failed\n");
				ul_dbf.free_result(_c, res);
				return -1;
			}
		} else {
			break;
		}
	} while(RES_ROW_N(res)>0);

	ul_dbf.free_result(_c, res);

#ifdef EXTRA_DEBUG
	LM_NOTICE("load end time [%d]\n", (int)time(NULL));
#endif

	return 0;
error1:
	free_pcontact(c);

	ul_dbf.free_result(_c, res);
	return -1;
}
예제 #24
0
/* update an existing impurecord. if one doesnt exist it will be created.
 * make sure yuo lock the domain before calling this and unlock it afterwards
 * return: 0 on success, -1 on failure
 */
int update_impurecord(struct udomain* _d, str* public_identity, int reg_state, int send_sar_on_delete, int barring, int is_primary, ims_subscription** s, str* ccf1, str* ccf2, str* ecf1, str* ecf2, struct impurecord** _r) {
    int res;

    res = get_impurecord(_d, public_identity, _r);
    if (res != 0) {
        if (reg_state != IMPU_NOT_REGISTERED && s) {
            LM_DBG("No existing impu record for <%.*s>.... creating new one\n", public_identity->len, public_identity->s);
            res = insert_impurecord(_d, public_identity, reg_state, barring, s, ccf1, ccf2, ecf1, ecf2, _r);

            //for the first time we create an IMPU we must set the primary record (we don't worry about it on updates - ignored)
            (*_r)->is_primary = is_primary; //TODO = this should prob move to insert_impurecord fn

            if (reg_state == IMPU_UNREGISTERED) {
                //update unreg expiry so the unreg record is not stored 'forever'
                (*_r)->expires = time(NULL) + unreg_validity;
            }
            if (res != 0) {
                LM_ERR("Unable to insert new IMPU for <%.*s>\n", public_identity->len, public_identity->s);
                return -1;
            } else {
                run_ul_callbacks(NULL, UL_IMPU_INSERT, *_r, NULL);
                return 0;
            }
        } else {
            LM_DBG("no IMPU found to update and data not valid to create new one - not a problem record was probably removed as it has no contacts\n");
            return 0;
        }

    }

    //if we get here, we have a record to update
    LM_DBG("updating IMPU record with public identity for <%.*s>\n", public_identity->len, public_identity->s);
    (*_r)->reg_state = reg_state;
    if (reg_state == IMPU_UNREGISTERED) {
        //update unreg expiry so the unreg record is not stored 'forever'
        (*_r)->expires = time(NULL) + unreg_validity;
    }
    if (barring >= 0) (*_r)->barring = barring;
    
    if (send_sar_on_delete >= 0) (*_r)->send_sar_on_delete = send_sar_on_delete;
    
    if (ccf1) {
        if ((*_r)->ccf1.s)
            shm_free((*_r)->ccf1.s);
        STR_SHM_DUP((*_r)->ccf1, *ccf1, "SHM CCF1");
    }
    if (ccf2) {
        if ((*_r)->ccf2.s)
            shm_free((*_r)->ccf2.s);
        STR_SHM_DUP((*_r)->ccf2, *ccf2, "SHM CCF2");
    }
    if (ecf1) {
        if ((*_r)->ecf1.s)
            shm_free((*_r)->ecf1.s);
        STR_SHM_DUP((*_r)->ecf1, *ecf1, "SHM ECF1");
    }
    if (ecf2) {
        if ((*_r)->ecf2.s)
            shm_free((*_r)->ecf2.s);
        STR_SHM_DUP((*_r)->ecf2, *ecf2, "SHM ECF2");
    }

    if (s) {
        LM_DBG("we have a new ims_subscription\n");
        if ((*_r)->s) {
            lock_get((*_r)->s->lock);
            if ((*_r)->s->ref_count == 1) {
                LM_DBG("freeing user data as no longer referenced\n");
                free_ims_subscription_data((*_r)->s); //no need to release lock after this. its gone ;)
                (*_r)->s = 0;
            } else {
                (*_r)->s->ref_count--;
                LM_DBG("new ref count for ims sub is %d\n", (*_r)->s->ref_count);
                lock_release((*_r)->s->lock);
            }
        }
        (*_r)->s = *s;
        lock_get((*_r)->s->lock);
        (*_r)->s->ref_count++;
        lock_release((*_r)->s->lock);
    }

    run_ul_callbacks((*_r)->cbs, UL_IMPU_UPDATE, *_r, NULL);
    return 0;

out_of_memory:
    unlock_udomain(_d, public_identity);
    return -1;
}
예제 #25
0
static int receive_ucontact_update(bin_packet_t *packet)
{
	static ucontact_info_t ci;
	static str d, aor, host, contact_str, callid,
		user_agent, path, attr, st, sock;
	udomain_t *domain;
	urecord_t *record;
	ucontact_t *contact;
	int port, proto;
	int rc;

	memset(&ci, 0, sizeof ci);

	bin_pop_str(packet, &d);
	bin_pop_str(packet, &aor);

	if (find_domain(&d, &domain) != 0) {
		LM_ERR("domain '%.*s' is not local\n", d.len, d.s);
		goto error;
	}

	bin_pop_str(packet, &contact_str);

	bin_pop_str(packet, &callid);
	ci.callid = &callid;

	bin_pop_str(packet, &user_agent);
	ci.user_agent = &user_agent;

	bin_pop_str(packet, &path);
	ci.path = &path;

	bin_pop_str(packet, &attr);
	ci.attr = &attr;

	bin_pop_str(packet, &ci.received);
	bin_pop_str(packet, &ci.instance);

	bin_pop_str(packet, &st);
	memcpy(&ci.expires, st.s, sizeof ci.expires);

	bin_pop_str(packet, &st);
	memcpy(&ci.q, st.s, sizeof ci.q);

	bin_pop_str(packet, &sock);

	if (sock.s && sock.s[0]) {
		if (parse_phostport(sock.s, sock.len, &host.s, &host.len,
			&port, &proto) != 0) {
			LM_ERR("bad socket <%.*s>\n", sock.len, sock.s);
			goto error;
		}

		ci.sock = grep_sock_info(&host, (unsigned short) port,
			(unsigned short) proto);
		if (!ci.sock)
			LM_DBG("non-local socket <%.*s>\n", sock.len, sock.s);
	} else {
		ci.sock = NULL;
	}

	bin_pop_int(packet, &ci.cseq);
	bin_pop_int(packet, &ci.flags);
	bin_pop_int(packet, &ci.cflags);
	bin_pop_int(packet, &ci.methods);

	bin_pop_str(packet, &st);
	memcpy(&ci.last_modified, st.s, sizeof ci.last_modified);

	bin_pop_str(packet, &st);
	ci.packed_kv_storage = &st;

	if (skip_replicated_db_ops)
		ci.flags |= FL_MEM;

	lock_udomain(domain, &aor);

	/* failure in retrieving a urecord may be ok, because packet order in UDP
	 * is not guaranteed, so update commands may arrive before inserts */
	if (get_urecord(domain, &aor, &record) != 0) {
		LM_INFO("failed to fetch local urecord - create new record and contact"
			" (ci: '%.*s')\n", callid.len, callid.s);

		if (insert_urecord(domain, &aor, &record, 1) != 0) {
			LM_ERR("failed to insert urecord\n");
			unlock_udomain(domain, &aor);
			goto error;
		}

		if (insert_ucontact(record, &contact_str, &ci, &contact, 1) != 0) {
			LM_ERR("failed (ci: '%.*s')\n", callid.len, callid.s);
			unlock_udomain(domain, &aor);
			goto error;
		}
	} else {
		rc = get_ucontact(record, &contact_str, &callid, ci.cseq + 1, &contact);
		if (rc == 1) {
			LM_INFO("contact '%.*s' not found, inserting new (ci: '%.*s')\n",
				contact_str.len, contact_str.s, callid.len, callid.s);

			if (insert_ucontact(record, &contact_str, &ci, &contact, 1) != 0) {
				LM_ERR("failed to insert ucontact (ci: '%.*s')\n",
					callid.len, callid.s);
				unlock_udomain(domain, &aor);
				goto error;
			}
		} else if (rc == 0) {
			if (update_ucontact(record, contact, &ci, 1) != 0) {
				LM_ERR("failed to update ucontact '%.*s' (ci: '%.*s')\n",
					contact_str.len, contact_str.s, callid.len, callid.s);
				unlock_udomain(domain, &aor);
				goto error;
			}
		} /* XXX: for -2 and -1, the master should have already handled
			 these errors - so we can skip them - razvanc */
	}

	unlock_udomain(domain, &aor);

	return 0;

error:
	LM_ERR("failed to process replication event. dom: '%.*s', aor: '%.*s'\n",
		d.len, d.s, aor.len, aor.s);
	return -1;
}
예제 #26
0
파일: udomain.c 프로젝트: Gitlab11/kamailio
/*!
 * \brief release the lock on the impurecord - effectively the domain slot
 * \param _d domain
 * \param _r impurecord to release (unlock)
 */
void release_impurecord(udomain_t* _d, struct impurecord* _r) {
    unlock_udomain(_d, &_r->public_identity);
}
예제 #27
0
파일: ul_fifo.c 프로젝트: OPSF/uClinux
int static ul_rm( FILE *pipe, char *response_file )
{
	char table[MAX_TABLE];
	char user[MAX_USER];
	udomain_t* d;
	str aor, t;
	char* at;

	if (!read_line(table, MAX_TABLE, pipe, &t.len) || t.len ==0) {
		fifo_reply(response_file, 
			   "400 ul_rm: table name expected\n");
		LOG(L_ERR, "ERROR: ul_rm: table name expected\n");
		return 1;
	}
	if (!read_line(user, MAX_USER, pipe, &aor.len) || aor.len==0) {
		fifo_reply(response_file, 
			   "400 ul_rm: user name expected\n");
		LOG(L_ERR, "ERROR: ul_rm: user name expected\n");
		return 1;
	}

	at = memchr(user, '@', aor.len);

	if (use_domain) {
		if (!at) {
			fifo_reply(response_file,
				   "400 ul_rm: username@domain expected\n");
			LOG(L_ERR, "ERROR: ul_rm: Domain missing\n");
			return 1;
		}
	} else {
		if (at) {
			aor.len = at - user;
		}
	}

	aor.s = user;
	strlower(&aor);

	t.s = table;

	fifo_find_domain(&t, &d);

	LOG(L_INFO, "INFO: deleting user-loc (%s,%s)\n",
	    table, user );
	
	if (d) {
		lock_udomain(d);
		if (delete_urecord(d, &aor) < 0) {
			LOG(L_ERR, "ul_rm(): Error while deleting user %s\n", user);
			unlock_udomain(d);
			fifo_reply(response_file, "500 Error while deleting user %s\n", user);
			return 1;
		}
		unlock_udomain(d);
		fifo_reply(response_file, "200 user (%s, %s) deleted\n", 
			table, user);
		return 1;
	} else {
		fifo_reply(response_file, "400 table (%s) not found\n", table);
		return 1;
	}
}
예제 #28
0
파일: dlist.c 프로젝트: OPSF/uClinux
/*
 * Return list of all contacts for all currently registered
 * users in all domains. Caller must provide buffer of
 * sufficient length for fitting all those contacts. In the
 * case when buffer was exhausted, the function returns
 * estimated amount of additional space needed, in this
 * case the caller is expected to repeat the call using
 * this value as the hint.
 *
 * Information is packed into the buffer as follows:
 *
 * +------------+----------+------------+-----------
 * |contact1.len|contact1.s|contact2.len|contact2.s|
 * +------------+----------+------------+-----------
 * |.......................|contactN.len|contactN.s|
 * +------------+----------+------------+----------+
 * |000000000000|
 * +------------+
 */
int get_all_ucontacts(void *buf, int len, unsigned int flags)
{
	dlist_t *p;
	urecord_t *r;
	ucontact_t *c;
	void *cp;
	int shortage;

	cp = buf;
	shortage = 0;
	/* Reserve space for terminating 0000 */
	len -= sizeof(c->c.len);
	for (p = root; p != NULL; p = p->next) {
		lock_udomain(p->d);
		if (p->d->d_ll.n <= 0) {
			unlock_udomain(p->d);
			continue;
		}
		for (r = p->d->d_ll.first; r != NULL; r = r->d_ll.next) {
			for (c = r->contacts; c != NULL; c = c->next) {
				if (c->c.len <= 0)
					continue;
				     /*
				      * List only contacts that have all requested
				      * flags set
				      */
				if ((c->flags & flags) != flags)
					continue;
				if (c->received.s) {
					if (len >= (int)(sizeof(c->received.len) + c->received.len)) {
						memcpy(cp, &c->received.len, sizeof(c->received.len));
						cp = (char*)cp + sizeof(c->received.len);
						memcpy(cp, c->received.s, c->received.len);
						cp = (char*)cp + c->received.len;
						len -= sizeof(c->received.len) + c->received.len;
					} else {
						shortage += sizeof(c->received.len) + c->received.len;
					}
				} else {
					if (len >= (int)(sizeof(c->c.len) + c->c.len)) {
						memcpy(cp, &c->c.len, sizeof(c->c.len));
						cp = (char*)cp + sizeof(c->c.len);
						memcpy(cp, c->c.s, c->c.len);
						cp = (char*)cp + c->c.len;
						len -= sizeof(c->c.len) + c->c.len;
					} else {
						shortage += sizeof(c->c.len) + c->c.len;
					}
				}
			}
		}
		unlock_udomain(p->d);
	}
	/* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
	if (len >= 0)
		memset(cp, 0, sizeof(c->c.len));

	/* Shouldn't happen */
	if (shortage > 0 && len > shortage) {
		abort();
	}

	shortage -= len;

	return shortage > 0 ? shortage : 0;
}
예제 #29
0
int preload_udomain(db_con_t* _c, udomain_t* _d)
{
	char b[256];
	db_key_t columns[11];
	db_res_t* res;
	db_row_t* row;
	int i, cseq;
	unsigned int flags;
	struct socket_info* sock;
	str uid, contact, callid, ua, received, instance, aor;
	str* rec;
	time_t expires;
	qvalue_t q;

	urecord_t* r;
	ucontact_t* c;

	columns[0] = uid_col.s;
	columns[1] = contact_col.s;
	columns[2] = expires_col.s;
	columns[3] = q_col.s;
	columns[4] = callid_col.s;
	columns[5] = cseq_col.s;
	columns[6] = flags_col.s;
	columns[7] = user_agent_col.s;
	columns[8] = received_col.s;
	columns[9] = instance_col.s;
	columns[10] = aor_col.s;
	
	memcpy(b, _d->name->s, _d->name->len);
	b[_d->name->len] = '\0';

	if (ul_dbf.use_table(_c, b) < 0) {
		LOG(L_ERR, "preload_udomain(): Error in use_table\n");
		return -1;
	}

	if (ul_dbf.query(_c, 0, 0, 0, columns, 0, 11, 0, &res) < 0) {
		LOG(L_ERR, "preload_udomain(): Error while doing db_query\n");
		return -1;
	}

	if (RES_ROW_N(res) == 0) {
		DBG("preload_udomain(): Table is empty\n");
		ul_dbf.free_result(_c, res);
		return 0;
	}

	lock_udomain(_d);

	for(i = 0; i < RES_ROW_N(res); i++) {
		row = RES_ROWS(res) + i;
		
		uid.s      = (char*)VAL_STRING(ROW_VALUES(row));
		if (uid.s == 0) {
			LOG(L_CRIT, "preload_udomain: ERROR: bad uid "
							"record in table %s\n", b);
			LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n");
			continue;
		} else {
			uid.len = strlen(uid.s);
		}

		contact.s = (char*)VAL_STRING(ROW_VALUES(row) + 1);
		if (contact.s == 0) {
			LOG(L_CRIT, "preload_udomain: ERROR: bad contact "
							"record in table %s\n", b);
			LOG(L_CRIT, "preload_udomain: ERROR: for username %.*s\n",
							uid.len, uid.s);
			LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n");
			continue;
		} else {
			contact.len = strlen(contact.s);
		}
		expires     = VAL_TIME  (ROW_VALUES(row) + 2);
		q           = double2q(VAL_DOUBLE(ROW_VALUES(row) + 3));
		cseq        = VAL_INT   (ROW_VALUES(row) + 5);
		callid.s    = (char*)VAL_STRING(ROW_VALUES(row) + 4);
		if (callid.s == 0) {
			LOG(L_CRIT, "preload_udomain: ERROR: bad callid record in"
							" table %s\n", b);
			LOG(L_CRIT, "preload_udomain: ERROR: for username %.*s,"
							" contact %.*s\n",
							uid.len, uid.s, contact.len, contact.s);
			LOG(L_CRIT, "preload_udomain: ERROR: skipping...\n");
			continue;
		} else {
			callid.len  = strlen(callid.s);
		}

		flags  = VAL_BITMAP(ROW_VALUES(row) + 6);

		ua.s  = (char*)VAL_STRING(ROW_VALUES(row) + 7);
		if (ua.s) {
			ua.len = strlen(ua.s);
		} else {
			ua.len = 0;
		}

		if (!VAL_NULL(ROW_VALUES(row) + 8)) {
			received.s  = (char*)VAL_STRING(ROW_VALUES(row) + 8);
			if (received.s) {
				received.len = strlen(received.s);
				rec = &received;

				sock = find_socket(&received);
			} else {
				received.len = 0;
				rec = 0;
				sock = 0;
			}
		} else {
			received.s = 0;
			received.len = 0;
			rec = 0;
			sock = 0;
		}

		if (!VAL_NULL(ROW_VALUES(row) + 9)) {
			instance.s  = (char*)VAL_STRING(ROW_VALUES(row) + 9);
			if (instance.s) {
				instance.len = strlen(instance.s);
			} else {
				instance.len = 0;
			}
		} else {
			instance.s = 0;
			instance.len = 0;
		}

		if (!VAL_NULL(ROW_VALUES(row) + 10)) {
			aor.s  = (char*)VAL_STRING(ROW_VALUES(row) + 10);
			if (aor.s) {
				aor.len = strlen(aor.s);
			} else {
				aor.len = 0;
			}
		} else {
			aor.s = 0;
			aor.len = 0;
		}

		if (get_urecord(_d, &uid, &r) > 0) {
			if (mem_insert_urecord(_d, &uid, &r) < 0) {
				LOG(L_ERR, "preload_udomain(): Can't create a record\n");
				ul_dbf.free_result(_c, res);
				unlock_udomain(_d);
				return -2;
			}
		}
		
		if (mem_insert_ucontact(r, &aor, &contact, expires, q, &callid, cseq, flags, &c, &ua, rec, sock, &instance) < 0) {
			LOG(L_ERR, "preload_udomain(): Error while inserting contact\n");
			ul_dbf.free_result(_c, res);
			unlock_udomain(_d);
			return -3;
		}

		db_read_reg_avps(_c, c);

		     /* We have to do this, because insert_ucontact sets state to CS_NEW
		      * and we have the contact in the database already
			  * we also store zombies in database so we have to restore
			  * the correct state
		      */
		c->state = CS_SYNC;
	}

	ul_dbf.free_result(_c, res);
	unlock_udomain(_d);
	return 0;
}
예제 #30
0
파일: ul_fifo.c 프로젝트: OPSF/uClinux
static int ul_add(FILE* pipe, char* response_file)
{
	char table_s[MAX_TABLE];
	char user_s[MAX_USER];
	char contact_s[MAX_CONTACT_LEN];
	char expires_s[MAX_EXPIRES_LEN];
	char q_s[MAX_Q_LEN];
	char rep_s[MAX_REPLICATE_LEN];
	char flags_s[MAX_FLAGS_LEN];
	udomain_t* d;
	int exp_i, flags_i;
	char* at;
	qvalue_t qval;

	str table, user, contact, expires, q, rep, flags;

	if (!read_line(table_s, MAX_TABLE, pipe, &table.len) || table.len == 0) {
		fifo_reply(response_file,
			   "400 ul_add: table name expected\n");
		LOG(L_ERR, "ERROR: ul_add: table name expected\n");
		return 1;
	}
	
	if (!read_line(user_s, MAX_USER, pipe, &user.len) || user.len  == 0) {
		fifo_reply(response_file,
			   "400 ul_add: aor name expected\n");
		LOG(L_ERR, "ERROR: ul_add: aor expected\n");
		return 1;
	}

	at = memchr(user_s, '@', user.len);

	if (use_domain) {
		if (!at) {
			fifo_reply(response_file,
				   "400 ul_add: username@domain expected\n");
			LOG(L_ERR, "ERROR: ul_add: Domain missing\n");
			return 1;
		}
	} else {
		if (at) {
			user.len = at - user_s;
		}
	}

	if (!read_line(contact_s, MAX_CONTACT_LEN, pipe, &contact.len) || contact.len == 0) {
		fifo_reply(response_file,
			   "400 ul_add: contact expected\n");
		LOG(L_ERR, "ERROR: ul_add: contact expected\n");
		return 1;
	}
	
	if (!read_line(expires_s, MAX_EXPIRES_LEN, pipe, &expires.len) || expires.len == 0) {
		fifo_reply(response_file,
			   "400 ul_add: expires expected\n");
		LOG(L_ERR, "ERROR: ul_add: expires expected\n");
		return 1;
	}
	
	if (!read_line(q_s, MAX_Q, pipe, &q.len) || q.len == 0) {
		fifo_reply(response_file,
			   "400 ul_add: q expected\n");
		LOG(L_ERR, "ERROR: ul_add: q expected\n");
		return 1;
	}

	     /* Kept for backwards compatibility */
	if (!read_line(rep_s, MAX_REPLICATE_LEN, pipe, &rep.len) || rep.len == 0) {
		fifo_reply(response_file,
			   "400 ul_add: replicate expected\n");
		LOG(L_ERR, "ERROR: ul_add: replicate expected\n");
		return 1;
	}

	if (!read_line(flags_s, MAX_FLAGS_LEN, pipe, &flags.len) || flags.len == 0) {
		fifo_reply(response_file,
			   "400 ul_add: flags expected\n");
		LOG(L_ERR, "ERROR: ul_add: flags expected\n");
		return 1;
	}
	
	table.s = table_s;
	user.s = user_s;
	strlower(&user);

	contact.s = contact_s;
	expires.s = expires_s;
	q.s = q_s;
	flags.s = flags_s;
	
	fifo_find_domain(&table, &d);
	
	if (d) {
		if (str2int(&expires, (unsigned int*)&exp_i) < 0) {
			fifo_reply(response_file, "400 Invalid expires format\n");
			return 1;
		}

		if (str2q(&qval, q.s, q.len) < 0) {
			fifo_reply(response_file, "400 Invalid q value\n");
			return 1;
		}

		if (str2int(&flags, (unsigned int*)&flags_i) < 0) {
			fifo_reply(response_file, "400 Invalid flags format\n");
			return 1;
		}
		
		lock_udomain(d);
		
		if (add_contact(d, &user, &contact, exp_i, qval, flags_i) < 0) {
			unlock_udomain(d);
			LOG(L_ERR, "ul_add(): Error while adding contact ('%.*s','%.*s') in table '%.*s'\n",
			    user.len, ZSW(user.s), contact.len, ZSW(contact.s), table.len, ZSW(table.s));
			fifo_reply(response_file, "500 Error while adding contact\n"
				   " ('%.*s','%.*s') in table '%.*s'\n",
				   user.len, ZSW(user.s), contact.len, ZSW(contact.s), table.len, ZSW(table.s));
			return 1;
		}
		unlock_udomain(d);
		
		fifo_reply(response_file, "200 Added to table\n"
				"('%.*s','%.*s') to '%.*s'\n",
			   user.len, ZSW(user.s), contact.len, ZSW(contact.s), table.len, ZSW(table.s));
		return 1;
	} else {
		fifo_reply(response_file, "400 Table '%.*s' not found in memory, use save(\"%.*s\") or lookup(\"%.*s\") in the configuration script first\n", 
			table.len, ZSW(table.s), table.len, ZSW(table.s), table.len, ZSW(table.s));
		return 1;
	}
}