Example #1
0
/**
 * init module function
 */
static int mod_init(void)
{
	pv_spec_t avp_spec;

	LM_DBG("initializing ...\n");

	/* Load stuff from DB */
	init_db_url( ds_db_url , 0 /*cannot be null*/);

	ds_table_name.len = strlen(ds_table_name.s);
	ds_set_id_col.len = strlen(ds_set_id_col.s);
	ds_dest_uri_col.len = strlen(ds_dest_uri_col.s);
	ds_dest_sock_col.len = strlen(ds_dest_sock_col.s);
	ds_dest_state_col.len = strlen(ds_dest_state_col.s);
	ds_dest_weight_col.len = strlen(ds_dest_weight_col.s);
	ds_dest_attrs_col.len = strlen(ds_dest_attrs_col.s);

	/* handle AVPs spec */
	dst_avp_param.len = strlen(dst_avp_param.s);
	if (pv_parse_spec(&dst_avp_param, &avp_spec)==0
	|| avp_spec.type!=PVT_AVP) {
		LM_ERR("malformed or non AVP %.*s AVP definition\n",
			dst_avp_param.len, dst_avp_param.s);
		return -1;
	}
	if(pv_get_avp_name(0, &(avp_spec.pvp), &dst_avp_name,&dst_avp_type)!=0) {
		LM_ERR("[%.*s]- invalid AVP definition\n", dst_avp_param.len,
			dst_avp_param.s);
		return -1;
	}

	grp_avp_param.len=strlen(grp_avp_param.s);
	if (pv_parse_spec(&grp_avp_param, &avp_spec)==0
	|| avp_spec.type!=PVT_AVP) {
		LM_ERR("malformed or non AVP %.*s AVP definition\n",
			grp_avp_param.len, grp_avp_param.s);
		return -1;
	}
	if(pv_get_avp_name(0, &(avp_spec.pvp), &grp_avp_name,&grp_avp_type)!=0) {
		LM_ERR("[%.*s]- invalid AVP definition\n", grp_avp_param.len,
			grp_avp_param.s);
		return -1;
	}

	cnt_avp_param.len=strlen(cnt_avp_param.s);
	if (pv_parse_spec(&cnt_avp_param, &avp_spec)==0
	|| avp_spec.type!=PVT_AVP) {
		LM_ERR("malformed or non AVP %.*s AVP definition\n",
			cnt_avp_param.len, cnt_avp_param.s);
		return -1;
	}
	if(pv_get_avp_name(0, &(avp_spec.pvp), &cnt_avp_name,&cnt_avp_type)!=0) {
		LM_ERR("[%.*s]- invalid AVP definition\n", cnt_avp_param.len,
			cnt_avp_param.s);
		return -1;
	}

	sock_avp_param.len=strlen(sock_avp_param.s);
	if (pv_parse_spec(&sock_avp_param, &avp_spec)==0
	|| avp_spec.type!=PVT_AVP) {
		LM_ERR("malformed or non AVP %.*s AVP definition\n",
			sock_avp_param.len, sock_avp_param.s);
		return -1;
	}
	if(pv_get_avp_name(0, &(avp_spec.pvp), &sock_avp_name,&sock_avp_type)!=0){
		LM_ERR("[%.*s]- invalid AVP definition\n", sock_avp_param.len,
			sock_avp_param.s);
		return -1;
	}

	if (attrs_avp_param.s && (attrs_avp_param.len=strlen(attrs_avp_param.s)) > 0) {
		if (pv_parse_spec(&attrs_avp_param, &avp_spec)==0
		|| avp_spec.type!=PVT_AVP) {
			LM_ERR("malformed or non AVP %.*s AVP definition\n",
					attrs_avp_param.len, attrs_avp_param.s);
			return -1;
		}

		if (pv_get_avp_name(0, &(avp_spec.pvp), &attrs_avp_name,
		&attrs_avp_type)!=0){
			LM_ERR("[%.*s]- invalid AVP definition\n", attrs_avp_param.len,
					attrs_avp_param.s);
			return -1;
		}
	} else {
		attrs_avp_name = -1;
		attrs_avp_type = 0;
	}

	if (hash_pvar_param.s && (hash_pvar_param.len=strlen(hash_pvar_param.s))>0 ) {
		if(pv_parse_format(&hash_pvar_param, &hash_param_model) < 0
				|| hash_param_model==NULL) {
			LM_ERR("malformed PV string: %s\n", hash_pvar_param.s);
			return -1;
		}
	} else {
		hash_param_model = NULL;
	}

	if (ds_setid_pvname.s && (ds_setid_pvname.len=strlen(ds_setid_pvname.s))>0 ) {
		if(pv_parse_spec(&ds_setid_pvname, &ds_setid_pv)==NULL
				|| !pv_is_w(&ds_setid_pv))
		{
			LM_ERR("[%s]- invalid setid_pvname\n", ds_setid_pvname.s);
			return -1;
		}
	}

	pvar_algo_param.len = strlen(pvar_algo_param.s);
	if (pvar_algo_param.len)
		ds_pvar_parse_pattern(pvar_algo_param);

	if (init_ds_bls()!=0) {
		LM_ERR("failed to init DS blacklists\n");
		return E_CFG;
	}

	if (init_ds_data()!=0) {
		LM_ERR("failed to init DS data holder\n");
		return -1;
	}

	/* open DB connection to load provisioning data */
	if (init_ds_db()!= 0) {
		LM_ERR("failed to init database support\n");
		return -1;
	}

	/* do the actula data load */
	if (ds_reload_db()!=0) {
		LM_ERR("failed to load data from DB\n");
		return -1;
	}

	/* close DB connection */
	ds_disconnect_db();

	/* Only, if the Probing-Timer is enabled the TM-API needs to be loaded: */
	if (ds_ping_interval > 0)
	{
		load_tm_f load_tm;
		str host;
		int port,proto;

		if (ds_ping_from.s)
			ds_ping_from.len = strlen(ds_ping_from.s);
		if (ds_ping_method.s)
			ds_ping_method.len = strlen(ds_ping_method.s);
		/* parse the list of reply codes to be counted as success */
		if(options_reply_codes_str.s) {
			options_reply_codes_str.len = strlen(options_reply_codes_str.s);
			if(parse_reply_codes( &options_reply_codes_str, &options_reply_codes,
			&options_codes_no )< 0) {
				LM_ERR("Bad format for options_reply_code parameter"
						" - Need a code list separated by commas\n");
				return -1;
			}
		}
		/* parse and look for the socket to ping from */
		if (probing_sock_s && probing_sock_s[0]!=0 ) {
			if (parse_phostport( probing_sock_s, strlen(probing_sock_s),
			&host.s, &host.len, &port, &proto)!=0 ) {
				LM_ERR("socket description <%s> is not valid\n",
					probing_sock_s);
				return -1;
			}
			probing_sock = grep_sock_info( &host, port, proto);
			if (probing_sock==NULL) {
				LM_ERR("socket <%s> is not local to opensips (we must listen "
					"on it\n", probing_sock_s);
				return -1;
			}
		}
		/* TM-Bindings */
		load_tm=(load_tm_f)find_export("load_tm", 0, 0);
		if (load_tm==NULL) {
			LM_ERR("failed to bind to the TM-Module - required for probing\n");
			return -1;
		}
		/* let the auto-loading function load all TM stuff */
		if (load_tm( &tmb ) == -1) {
			LM_ERR("could not load the TM-functions - disable DS ping\n");
			return -1;
		}
		/* Register the PING-Timer */
		if (register_timer("ds-pinger",ds_check_timer,NULL,ds_ping_interval)<0){
			LM_ERR("failed to register timer for probing!\n");
			return -1;
		}
	}

	/* register timer to flush the state of destination back to DB */
	if (register_timer("ds-flusher",ds_flusher_routine,NULL, 30)<0){
		LM_ERR("failed to register timer for DB flushing!\n");
		return -1;
	}

	dispatch_evi_id = evi_publish_event(dispatcher_event);
	if (dispatch_evi_id == EVI_ERROR)
		LM_ERR("cannot register dispatcher event\n");
	return 0;
}
Example #2
0
/*! \brief
*/
static struct socket_info *get_sock_val(struct sip_msg *msg)
{
	struct socket_info *sock;
	struct hdr_field *hf;
	str xsockname = str_init("socket");
	sr_xavp_t *vavp = NULL;
	str socks;
	str hosts;
	int port;
	int proto;
	char c = 0;

	if(sock_hdr_name.len>0) {
		if (parse_headers( msg, HDR_EOH_F, 0) == -1) {
			LM_ERR("failed to parse message\n");
			return 0;
		}

		for (hf=msg->headers; hf; hf=hf->next) {
			if (cmp_hdrname_str(&hf->name, &sock_hdr_name)==0)
				break;
		}

		/* hdr found? */
		if (hf==0)
			return 0;

		trim_len( socks.len, socks.s, hf->body );
		if (socks.len==0)
			return 0;

		/*FIXME: This is a hack */
		c = socks.s[socks.len];
		socks.s[socks.len] = '\0';
	} else {
		/* xavp */
		if(reg_xavp_cfg.s!=NULL)
			vavp = xavp_get_child_with_sval(&reg_xavp_cfg, &xsockname);
		if(vavp==NULL || vavp->val.v.s.len<=0)
			return 0;
		socks = vavp->val.v.s;
	}
	if (parse_phostport( socks.s, &hosts.s, &hosts.len,
				&port, &proto)!=0) {
		socks.s[socks.len] = c;
		LM_ERR("bad socket <%.*s> in \n",
				socks.len, socks.s);
		return 0;
	}
	if(sock_hdr_name.len>0 && c!=0) {
		socks.s[socks.len] = c;
	}
	sock = grep_sock_info(&hosts,(unsigned short)port,(unsigned short)proto);
	if (sock==0) {
		LM_ERR("non-local socket <%.*s>\n",	socks.len, socks.s);
		return 0;
	}

	LM_DBG("%d:<%.*s>:%d -> p=%p\n", proto,socks.len,socks.s,port_no,sock );

	return sock;
}
Example #3
0
static void core_sctp_options(rpc_t* rpc, void* c)
{
#ifdef USE_SCTP
	void *handle;
	struct cfg_group_sctp t;
	char* param;
	struct socket_info* si;
	char* host;
	str hs;
	int hlen;
	int port;
	int proto;

	param=0;
	if (!sctp_disable){
		/* look for optional socket parameter */
		if (rpc->scan(c, "*s", &param)>0){
			si=0;
			if (strcasecmp(param, "default")==0){
				si=sendipv4_sctp?sendipv4_sctp:sendipv6_sctp;
			}else if (strcasecmp(param, "first")==0){
				si=sctp_listen;
			}else{
				if (parse_phostport(param, &host, &hlen, &port, &proto)!=0){
					rpc->fault(c, 500, "bad param (use address, address:port,"
										" default or first)");
					return;
				}
				if (proto && proto!=PROTO_SCTP){
					rpc->fault(c, 500, "bad protocol in param (only SCTP"
										" allowed)");
					return;
				}
				hs.s=host;
				hs.len=hlen;
				si=grep_sock_info(&hs, port, PROTO_SCTP);
				if (si==0){
					rpc->fault(c, 500, "not listening on sctp %s", param);
					return;
				}
			}
			if (si==0 || si->socket==-1){
				rpc->fault(c, 500, "could not find a sctp socket");
				return;
			}
			memset(&t, 0, sizeof(t));
			if (sctp_get_cfg_from_sock(si->socket, &t)!=0){
				rpc->fault(c, 500, "failed to get socket options");
				return;
			}
		}else{
			sctp_options_get(&t);
		}
		rpc->add(c, "{", &handle);
		rpc->struct_add(handle, "ddddddddddddddddddd",
			"sctp_socket_rcvbuf",	t.so_rcvbuf,
			"sctp_socket_sndbuf",	t.so_sndbuf,
			"sctp_autoclose",		t.autoclose,
			"sctp_send_ttl",	t.send_ttl,
			"sctp_send_retries",	t.send_retries,
			"sctp_assoc_tracking",	t.assoc_tracking,
			"sctp_assoc_reuse",	t.assoc_reuse,
			"sctp_max_assocs", t.max_assocs,
			"sctp_srto_initial",	t.srto_initial,
			"sctp_srto_max",		t.srto_max,
			"sctp_srto_min",		t.srto_min,
			"sctp_asocmaxrxt",	t.asocmaxrxt,
			"sctp_init_max_attempts",	t.init_max_attempts,
			"sctp_init_max_timeo",t.init_max_timeo,
			"sctp_hbinterval",	t.hbinterval,
			"sctp_pathmaxrxt",	t.pathmaxrxt,
			"sctp_sack_delay",	t.sack_delay,
			"sctp_sack_freq",	t.sack_freq,
			"sctp_max_burst",	t.max_burst
		);
	}else{
		rpc->fault(c, 500, "sctp support disabled");
	}
#else
	rpc->fault(c, 500, "sctp support not compiled");
#endif
}
Example #4
0
/* Actions are composed as follows:
 * (the action length and type as always= 5 bytes)
 *
 * TODO performance speedup: instead of using
 * dynamically allocated memory for headers,body,totag,reason and my_msg
 * use static buffers.
 *
 */
int ac_sl_msg(as_p the_as,char *action,int len)
{
   struct sip_msg *my_msg;
   str *uri;
   struct proxy_l *proxy;
   rr_t *my_route;
   int k,retval;
   unsigned int flags;
   enum sip_protos proto;

   my_msg=NULL;
   k=0;

   net2hostL(flags,action,k);
   k++;
   proxy=0;

   if(!(my_msg = parse_ac_msg(HDR_EOH_F,action+k,len-k))){
      LM_ERR("out of memory!\n");
      goto error;
   }
   if(my_msg->first_line.type == SIP_REQUEST)
      LM_DBG("forwarding request:\"%.*s\" statelessly \n",my_msg->first_line.u.request.method.len+1+\
	    my_msg->first_line.u.request.uri.len,my_msg->first_line.u.request.method.s);
   else
      LM_DBG("forwarding reply:\"%.*s\" statelessly \n",my_msg->first_line.u.reply.status.len+1+\
	    my_msg->first_line.u.reply.reason.len,my_msg->first_line.u.reply.status.s);

   if (my_msg->route) {
      if (parse_rr(my_msg->route) < 0) {
	 LM_ERR( "Error while parsing Route body\n");
	 goto error;
      }
      my_route = (rr_t*)my_msg->route->parsed;
      uri=&(my_route->nameaddr.uri);
   }else{
      uri = GET_RURI(my_msg);
   }
   my_msg->force_send_socket=grep_sock_info(&my_msg->via1->host,my_msg->via1->port,my_msg->via1->proto);
   /* or also could be:
      my_msg->force_send_socket=the_as->binds[processor_id].bind_address;
      not sure which is better...
      */
   proxy=uri2proxy(uri,PROTO_NONE);
   if (proxy==0) {
      LM_ERR("unable to create proxy from URI \n");
      goto error;
   }
   proto=proxy->proto; /* uri2proxy set it correctly */
   //TODO my_msg->recvd
   if(0>forward_sl_request(my_msg,proxy,proto))
      goto error;
   retval=0;
   goto exit;
error:
   retval = -1;
exit:
   if(proxy){
      free_proxy(proxy);
      pkg_free(proxy);
   }
   if(my_msg){
      free_sip_msg_lite(my_msg);
      pkg_free(my_msg);
   }
   return retval;
}
Example #5
0
int b2b_entities_restore(void)
{
	db_res_t *result= NULL;
	db_row_t *rows = NULL;
	db_val_t *row_vals= NULL;
	int i;
	dlg_leg_t leg, *new_leg;
	b2b_dlg_t dlg, *shm_dlg= NULL;
	unsigned int hash_index, local_index;
	int nr_rows;
	str* b2b_key;
	str sockinfo_str;
	str host;
	int port, proto;
	b2b_table htable;
	int type;
	int no_rows = 10;

	if(b2be_db == NULL)
	{
		LM_DBG("NULL database connection\n");
		return 0;
	}
	if(b2be_dbf.use_table(b2be_db, &b2be_dbtable)< 0)
	{
		LM_ERR("sql use table failed\n");
		return -1;
	}
	if (DB_CAPABILITY(b2be_dbf, DB_CAP_FETCH))
	{
		if(b2be_dbf.query(b2be_db,0,0,0,qcols, 0,
			DB_COLS_NO, 0, 0) < 0)
		{
			LM_ERR("Error while querying (fetch) database\n");
			return -1;
		}
		no_rows = estimate_available_rows( DB_COLS_NO*128, DB_COLS_NO);
		if (no_rows==0) no_rows = 10;
		if(b2be_dbf.fetch_result(b2be_db,&result,no_rows)<0)
		{
			LM_ERR("fetching rows failed\n");
			return -1;
		}
	}
	else
	{
		if (b2be_dbf.query (b2be_db, 0, 0, 0,qcols,0, DB_COLS_NO,
					0, &result) < 0)
		{
			LM_ERR("querying presentity\n");
			return -1;
		}
	}

	nr_rows = RES_ROW_N(result);

	do {
		LM_DBG("loading information from database %i records\n", nr_rows);

		rows = RES_ROWS(result);

		/* for every row */
		for(i=0; i<nr_rows; i++)
		{
			row_vals = ROW_VALUES(rows +i);
			memset(&dlg, 0, sizeof(b2b_dlg_t));

			type           = row_vals[0].val.int_val;
			dlg.tag[1].s   = (char*)row_vals[2].val.string_val;
			dlg.tag[1].len = dlg.tag[1].s?strlen(dlg.tag[1].s):0;
			dlg.callid.s   = (char*)row_vals[3].val.string_val;
			dlg.callid.len = dlg.callid.s?strlen(dlg.callid.s):0;

			if(type == B2B_SERVER)/* extract hash and local index */
			{
				htable = server_htable;
				if(b2b_parse_key(&dlg.tag[1], &hash_index, &local_index) < 0)
				{
					LM_ERR("Wrong format for b2b key [%.*s]\n", dlg.tag[1].len, dlg.tag[1].s);
					goto error;
				}
			}
			else
			{
				htable = client_htable;

				if(b2b_parse_key(&dlg.callid, &hash_index, &local_index) < 0)
				{
					LM_ERR("Wrong format for b2b key [%.*s]\n", dlg.callid.len, dlg.callid.s);
					goto error;
				}
			}
			dlg.id               = local_index;
			dlg.state            = row_vals[13].val.int_val;
			dlg.ruri.s           = (char*)row_vals[4].val.string_val;
			dlg.ruri.len         = strlen(dlg.ruri.s);
			dlg.from_uri.s       = (char*)row_vals[5].val.string_val;
			dlg.from_uri.len     = strlen(dlg.from_uri.s);
			dlg.from_dname.s     = (char*)row_vals[6].val.string_val;
			dlg.from_dname.len   = strlen(dlg.from_dname.s);
			dlg.to_uri.s         = (char*)row_vals[7].val.string_val;
			dlg.to_uri.len       = strlen(dlg.to_uri.s);
			dlg.to_dname.s       = (char*)row_vals[8].val.string_val;
			dlg.to_dname.len     = strlen(dlg.to_dname.s);
			dlg.tag[0].s         = (char*)row_vals[1].val.string_val;
			dlg.tag[0].len       = dlg.tag[0].s?strlen(dlg.tag[0].s):0;
			dlg.cseq[0]          = row_vals[14].val.int_val;
			dlg.cseq[1]          = row_vals[15].val.int_val;
			dlg.route_set[0].s   = (char*)row_vals[9].val.string_val;
			dlg.route_set[0].len = dlg.route_set[0].s?strlen(dlg.route_set[0].s):0;
			dlg.route_set[1].s   = (char*)row_vals[10].val.string_val;
			dlg.route_set[1].len = dlg.route_set[1].s?strlen(dlg.route_set[1].s):0;
			dlg.contact[0].s     = (char*)row_vals[19].val.string_val;
			dlg.contact[0].len   = dlg.contact[0].s?strlen(dlg.contact[0].s):0;
			dlg.contact[1].s     = (char*)row_vals[20].val.string_val;
			dlg.contact[1].len   = dlg.contact[1].s?strlen(dlg.contact[1].s):0;
			dlg.last_method      = row_vals[16].val.int_val;
			dlg.last_reply_code  = row_vals[17].val.int_val;
			dlg.last_invite_cseq = row_vals[18].val.int_val;
			dlg.param.s          = (char*)row_vals[12].val.string_val;
			dlg.param.len        = strlen(dlg.param.s);
			sockinfo_str.s       = (char*)row_vals[11].val.string_val;
			if(sockinfo_str.s)
			{
				sockinfo_str.len = strlen(sockinfo_str.s);
				if(sockinfo_str.len)
				{
					if (parse_phostport (sockinfo_str.s, sockinfo_str.len, &host.s,
							&host.len, &port, &proto )< 0)
					{
						LM_ERR("bad format for stored sockinfo string [%.*s]\n",
								sockinfo_str.len, sockinfo_str.s);
						goto error;
					}
					dlg.send_sock = grep_sock_info(&host, (unsigned short) port,
							(unsigned short) proto);
				}
			}
			dlg.db_flag = NO_UPDATEDB_FLAG;
			shm_dlg = b2b_dlg_copy(&dlg);
			if(shm_dlg == NULL)
			{
				LM_ERR("Failed to create new dialog structure\n");
				goto error;
			}
			b2b_key= b2b_htable_insert(htable,shm_dlg,hash_index,type, 1);
			if(b2b_key == NULL)
			{
				LM_ERR("Failed to insert new record\n");
				goto error;
			}
			pkg_free(b2b_key);

			memset(&leg, 0, sizeof(dlg_leg_t));
			leg.tag.s= (char*)row_vals[21].val.string_val;
			if(!leg.tag.s)
			{
				continue;
			}
			leg.tag.len       = strlen(leg.tag.s);
			leg.contact.s     = (char*)row_vals[23].val.string_val;
			leg.contact.len   = leg.contact.s?strlen(leg.contact.s):0;
			leg.route_set.len = leg.route_set.s?strlen(leg.route_set.s):0;
			leg.cseq          = row_vals[22].val.int_val;

			new_leg = b2b_dup_leg(&leg, SHM_MEM_TYPE);
			if(new_leg== NULL)
			{
				LM_ERR("Failed to construct b2b leg structure\n");
				goto error;
			}
			shm_dlg->legs = new_leg;
		}

		/* any more data to be fetched ?*/
		if (DB_CAPABILITY(b2be_dbf, DB_CAP_FETCH)) {
			if (b2be_dbf.fetch_result( b2be_db, &result, no_rows) < 0)
			{
				LM_ERR("fetching more rows failed\n");
				goto error;
			}
			nr_rows = RES_ROW_N(result);
		} else {
			nr_rows = 0;
		}
	}while (nr_rows>0);

	b2be_dbf.free_result(b2be_db, result);

	return 0;

error:
	if(result)
		b2be_dbf.free_result(b2be_db, result);
	return -1;
}
Example #6
0
/**
 * init module function
 */
static int mod_init(void)
{
	pv_spec_t avp_spec;
	str host;
	int port, proto;

	if(register_mi_mod(exports.name, mi_cmds)!=0)
	{
		LM_ERR("failed to register MI commands\n");
		return -1;
	}
	if(ds_ping_active_init()<0) {
		return -1;
	}

	if(ds_init_rpc()<0)
	{
		LM_ERR("failed to register RPC commands\n");
		return -1;
	}

	if(cfg_declare("dispatcher", dispatcher_cfg_def,
				&default_dispatcher_cfg, cfg_sizeof(dispatcher),
				&dispatcher_cfg)){
		LM_ERR("Fail to declare the configuration\n");
		return -1;
	}

	/* Initialize the counter */
	ds_ping_reply_codes = (int**)shm_malloc(sizeof(unsigned int*));
	*ds_ping_reply_codes = 0;
	ds_ping_reply_codes_cnt = (int*)shm_malloc(sizeof(int));
	*ds_ping_reply_codes_cnt = 0;
	if(ds_ping_reply_codes_str.s) {
		cfg_get(dispatcher, dispatcher_cfg, ds_ping_reply_codes_str)
			= ds_ping_reply_codes_str;
		if(ds_parse_reply_codes()< 0)
		{
			return -1;
		}
	}
	/* copy threshholds to config */
	cfg_get(dispatcher, dispatcher_cfg, probing_threshold)
		= probing_threshold;
	cfg_get(dispatcher, dispatcher_cfg, inactive_threshold)
		= inactive_threshold;

	if (ds_default_socket.s && ds_default_socket.len > 0) {
		if (parse_phostport( ds_default_socket.s, &host.s, &host.len,
				&port, &proto)!=0) {
			LM_ERR("bad socket <%.*s>\n", ds_default_socket.len, ds_default_socket.s);
			return -1;
		}
		ds_default_sockinfo = grep_sock_info( &host, (unsigned short)port, proto);
		if (ds_default_sockinfo==0) {
			LM_WARN("non-local socket <%.*s>\n", ds_default_socket.len, ds_default_socket.s);
			return -1;
		}
		LM_INFO("default dispatcher socket set to <%.*s>\n", ds_default_socket.len, ds_default_socket.s);
	}

	if(init_data()!= 0)
		return -1;

	if(ds_db_url.s)
	{
		if(init_ds_db()!= 0)
		{
			LM_ERR("could not initiate a connect to the database\n");
			return -1;
		}
	} else {
		if(ds_load_list(dslistfile)!=0) {
			LM_ERR("no dispatching list loaded from file\n");
			return -1;
		} else {
			LM_DBG("loaded dispatching list\n");
		}
	}

	if (dst_avp_param.s && dst_avp_param.len > 0)
	{
		if (pv_parse_spec(&dst_avp_param, &avp_spec)==0
				|| avp_spec.type!=PVT_AVP)
		{
			LM_ERR("malformed or non AVP %.*s AVP definition\n",
					dst_avp_param.len, dst_avp_param.s);
			return -1;
		}

		if(pv_get_avp_name(0, &(avp_spec.pvp), &dst_avp_name, &dst_avp_type)!=0)
		{
			LM_ERR("[%.*s]- invalid AVP definition\n", dst_avp_param.len,
					dst_avp_param.s);
			return -1;
		}
	} else {
		dst_avp_name.n = 0;
		dst_avp_type = 0;
	}
	if (grp_avp_param.s && grp_avp_param.len > 0)
	{
		if (pv_parse_spec(&grp_avp_param, &avp_spec)==0
				|| avp_spec.type!=PVT_AVP)
		{
			LM_ERR("malformed or non AVP %.*s AVP definition\n",
					grp_avp_param.len, grp_avp_param.s);
			return -1;
		}

		if(pv_get_avp_name(0, &(avp_spec.pvp), &grp_avp_name, &grp_avp_type)!=0)
		{
			LM_ERR("[%.*s]- invalid AVP definition\n", grp_avp_param.len,
					grp_avp_param.s);
			return -1;
		}
	} else {
		grp_avp_name.n = 0;
		grp_avp_type = 0;
	}
	if (cnt_avp_param.s && cnt_avp_param.len > 0)
	{
		if (pv_parse_spec(&cnt_avp_param, &avp_spec)==0
				|| avp_spec.type!=PVT_AVP)
		{
			LM_ERR("malformed or non AVP %.*s AVP definition\n",
					cnt_avp_param.len, cnt_avp_param.s);
			return -1;
		}

		if(pv_get_avp_name(0, &(avp_spec.pvp), &cnt_avp_name, &cnt_avp_type)!=0)
		{
			LM_ERR("[%.*s]- invalid AVP definition\n", cnt_avp_param.len,
					cnt_avp_param.s);
			return -1;
		}
	} else {
		cnt_avp_name.n = 0;
		cnt_avp_type = 0;
	}
	if (dstid_avp_param.s && dstid_avp_param.len > 0)
	{
		if (pv_parse_spec(&dstid_avp_param, &avp_spec)==0
				|| avp_spec.type!=PVT_AVP)
		{
			LM_ERR("malformed or non AVP %.*s AVP definition\n",
					dstid_avp_param.len, dstid_avp_param.s);
			return -1;
		}

		if(pv_get_avp_name(0, &(avp_spec.pvp), &dstid_avp_name,
					&dstid_avp_type)!=0)
		{
			LM_ERR("[%.*s]- invalid AVP definition\n", dstid_avp_param.len,
					dstid_avp_param.s);
			return -1;
		}
	} else {
		dstid_avp_name.n = 0;
		dstid_avp_type = 0;
	}

	if (attrs_avp_param.s && attrs_avp_param.len > 0)
	{
		if (pv_parse_spec(&attrs_avp_param, &avp_spec)==0
				|| avp_spec.type!=PVT_AVP)
		{
			LM_ERR("malformed or non AVP %.*s AVP definition\n",
					attrs_avp_param.len, attrs_avp_param.s);
			return -1;
		}

		if(pv_get_avp_name(0, &(avp_spec.pvp), &attrs_avp_name,
					&attrs_avp_type)!=0)
		{
			LM_ERR("[%.*s]- invalid AVP definition\n", attrs_avp_param.len,
					attrs_avp_param.s);
			return -1;
		}
	} else {
		attrs_avp_name.n = 0;
		attrs_avp_type = 0;
	}

	if (sock_avp_param.s && sock_avp_param.len > 0)
	{
		if (pv_parse_spec(&sock_avp_param, &avp_spec)==0
				|| avp_spec.type!=PVT_AVP)
		{
			LM_ERR("malformed or non AVP %.*s AVP definition\n",
					sock_avp_param.len, sock_avp_param.s);
			return -1;
		}

		if(pv_get_avp_name(0, &(avp_spec.pvp), &sock_avp_name,
					&sock_avp_type)!=0)
		{
			LM_ERR("[%.*s]- invalid AVP definition\n", sock_avp_param.len,
					sock_avp_param.s);
			return -1;
		}
	} else {
		sock_avp_name.n = 0;
		sock_avp_type = 0;
	}

	if (hash_pvar_param.s && *hash_pvar_param.s) {
		if(pv_parse_format(&hash_pvar_param, &hash_param_model) < 0
				|| hash_param_model==NULL) {
			LM_ERR("malformed PV string: %s\n", hash_pvar_param.s);
			return -1;
		}
	} else {
		hash_param_model = NULL;
	}

	if(ds_setid_pvname.s!=0)
	{
		if(pv_parse_spec(&ds_setid_pvname, &ds_setid_pv)==NULL
				|| !pv_is_w(&ds_setid_pv))
		{
			LM_ERR("[%s]- invalid setid_pvname\n", ds_setid_pvname.s);
			return -1;
		}
	}

	if(ds_attrs_pvname.s!=0)
	{
		if(pv_parse_spec(&ds_attrs_pvname, &ds_attrs_pv)==NULL
				|| !pv_is_w(&ds_attrs_pv))
		{
			LM_ERR("[%s]- invalid attrs_pvname\n", ds_attrs_pvname.s);
			return -1;
		}
	}

	if (dstid_avp_param.s && dstid_avp_param.len > 0)
	{
		if(ds_hash_size>0)
		{
			if(ds_hash_load_init(1<<ds_hash_size, ds_hash_expire,
						ds_hash_initexpire)<0)
				return -1;
			if(ds_timer_mode==1) {
				if(sr_wtimer_add(ds_ht_timer, NULL, ds_hash_check_interval)<0)
					return -1;
			} else {
				if(register_timer(ds_ht_timer, NULL, ds_hash_check_interval)<0)
					return -1;
			}
		} else {
			LM_ERR("call load dispatching DSTID_AVP set but no size"
					" for hash table (see ds_hash_size parameter)\n");
			return -1;
		}
	}
	/* Only, if the Probing-Timer is enabled the TM-API needs to be loaded: */
	if (ds_ping_interval > 0)
	{
		/*****************************************************
		 * TM-Bindings
		 *****************************************************/
		if (load_tm_api( &tmb ) == -1)
		{
			LM_ERR("could not load the TM-functions - disable DS ping\n");
			return -1;
		}
		/*****************************************************
		 * Register the PING-Timer
		 *****************************************************/
		if(ds_timer_mode==1) {
			if(sr_wtimer_add(ds_check_timer, NULL, ds_ping_interval)<0)
				return -1;
		} else {
			if(register_timer(ds_check_timer, NULL, ds_ping_interval)<0)
				return -1;
		}
	}

	return 0;
}
Example #7
0
/*!
 * \brief Convert database values into ucontact_info
 *
 * Convert database values into ucontact_info,
 * expects 12 rows (contact, expirs, q, callid, cseq, flags,
 * ua, received, path, socket, methods, last_modified)
 * \param vals database values
 * \param contact contact
 * \return pointer to the ucontact_info on success, 0 on failure
 */
static inline ucontact_info_t* dbrow2info( db_val_t *vals, str *contact)
{
    static ucontact_info_t ci;
    static str callid, ua, received, host, path;
    int port, proto;
    char *p;

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

    contact->s = (char*)VAL_STRING(vals);
    if (VAL_NULL(vals) || contact->s==0 || contact->s[0]==0) {
        LM_CRIT("bad contact\n");
        return 0;
    }
    contact->len = strlen(contact->s);

    if (VAL_NULL(vals+1)) {
        LM_CRIT("empty expire\n");
        return 0;
    }
    ci.expires = VAL_TIME(vals+1);

    if (VAL_NULL(vals+2)) {
        LM_CRIT("empty q\n");
        return 0;
    }
    ci.q = double2q(VAL_DOUBLE(vals+2));

    if (VAL_NULL(vals+4)) {
        LM_CRIT("empty cseq_nr\n");
        return 0;
    }
    ci.cseq = VAL_INT(vals+4);

    callid.s = (char*)VAL_STRING(vals+3);
    if (VAL_NULL(vals+3) || !callid.s || !callid.s[0]) {
        LM_CRIT("bad callid\n");
        return 0;
    }
    callid.len  = strlen(callid.s);
    ci.callid = &callid;

    if (VAL_NULL(vals+5)) {
        LM_CRIT("empty flag\n");
        return 0;
    }
    ci.flags  = VAL_BITMAP(vals+5);

    if (VAL_NULL(vals+6)) {
        LM_CRIT("empty cflag\n");
        return 0;
    }
    ci.cflags  = VAL_BITMAP(vals+6);

    ua.s  = (char*)VAL_STRING(vals+7);
    if (VAL_NULL(vals+7) || !ua.s || !ua.s[0]) {
        ua.s = 0;
        ua.len = 0;
    } else {
        ua.len = strlen(ua.s);
    }
    ci.user_agent = &ua;

    received.s  = (char*)VAL_STRING(vals+8);
    if (VAL_NULL(vals+8) || !received.s || !received.s[0]) {
        received.len = 0;
        received.s = 0;
    } else {
        received.len = strlen(received.s);
    }
    ci.received = received;

    path.s  = (char*)VAL_STRING(vals+9);
    if (VAL_NULL(vals+9) || !path.s || !path.s[0]) {
        path.len = 0;
        path.s = 0;
    } else {
        path.len = strlen(path.s);
    }
    ci.path= &path;

    /* socket name */
    p  = (char*)VAL_STRING(vals+10);
    if (VAL_NULL(vals+10) || p==0 || p[0]==0) {
        ci.sock = 0;
    } else {
        if (parse_phostport( p, &host.s, &host.len,
                             &port, &proto)!=0) {
            LM_ERR("bad socket <%s>\n", p);
            return 0;
        }
        ci.sock = grep_sock_info( &host, (unsigned short)port, proto);
        if (ci.sock==0) {
            LM_INFO("non-local socket <%s>...ignoring\n", p);
        }
    }

    /* supported methods */
    if (VAL_NULL(vals+11)) {
        ci.methods = ALL_METHODS;
    } else {
        ci.methods = VAL_BITMAP(vals+11);
    }

    /* last modified time */
    if (!VAL_NULL(vals+12)) {
        ci.last_modified = VAL_TIME(vals+12);
    }

    /* record internal uid */
    if (!VAL_NULL(vals+13)) {
        ci.ruid.s = (char*)VAL_STRING(vals+13);
        ci.ruid.len = strlen(ci.ruid.s);
    }

    /* sip instance */
    if (!VAL_NULL(vals+14)) {
        ci.instance.s = (char*)VAL_STRING(vals+14);
        ci.instance.len = strlen(ci.instance.s);
    }

    /* reg-id */
    if (!VAL_NULL(vals+15)) {
        ci.reg_id = VAL_UINT(vals+15);
    }

    return &ci;
}
Example #8
0
static int trace_send_hep_duplicate(str *body, str *from, str *to, struct dest_info * dst2)
{
	struct dest_info dst;
	struct socket_info *si;
	struct dest_info* dst_fin = NULL;
	struct proxy_l * p=NULL /* make gcc happy */;
	void* buffer = NULL;
	union sockaddr_union from_su;
	union sockaddr_union to_su;
	unsigned int len, buflen, proto;
	struct hep_hdr hdr;
	struct hep_iphdr hep_ipheader;
	struct hep_timehdr hep_time;
	struct timeval tvb;
	struct timezone tz;

	struct hep_ip6hdr hep_ip6header;

	if(body->s==NULL || body->len <= 0)
		return -1;

	if(dup_uri_str.s==0 || dup_uri==NULL)
		return 0;


	gettimeofday( &tvb, &tz );


	/* message length */
	len = body->len 
		+ sizeof(struct hep_ip6hdr)
		+ sizeof(struct hep_hdr) + sizeof(struct hep_timehdr);;


	/* The packet is too big for us */
	if (unlikely(len>BUF_SIZE)){
		goto error;
	}

	/* Convert proto:ip:port to sockaddress union SRC IP */
	if (pipport2su(from->s, &from_su, &proto)==-1 || (pipport2su(to->s, &to_su, &proto)==-1))
		goto error;

	/* check if from and to are in the same family*/
	if(from_su.s.sa_family != to_su.s.sa_family) {
		LM_ERR("interworking detected ?\n");
		goto error;
	}

	if (!dst2){
		init_dest_info(&dst);
		/* create a temporary proxy*/
		dst.proto = PROTO_UDP;
		p=mk_proxy(&dup_uri->host, (dup_uri->port_no)?dup_uri->port_no:SIP_PORT,
				dst.proto);
		if (p==0)
		{
			LM_ERR("bad host name in uri\n");
			goto error;
		}

		hostent2su(&dst.to, &p->host, p->addr_idx, (p->port)?p->port:SIP_PORT);
		LM_DBG("setting up the socket_info\n");
		dst_fin = &dst;
	} else {
		dst_fin = dst2;
	}

	if (force_send_sock_str.s) {
		LM_DBG("force_send_sock activated, grep for the sock_info\n");
		si = grep_sock_info(&force_send_sock_uri->host,
				(force_send_sock_uri->port_no)?force_send_sock_uri->port_no:SIP_PORT,
				PROTO_UDP);
		if (!si) {
			LM_WARN("cannot grep socket info\n");
		} else {
			LM_DBG("found socket while grep: [%.*s] [%.*s]\n", si->name.len, si->name.s, si->address_str.len, si->address_str.s);
			dst_fin->send_sock = si;
		}
	}

	if (dst_fin->send_sock == 0) {
		dst_fin->send_sock=get_send_socket(0, &dst_fin->to, dst_fin->proto);
		if (dst_fin->send_sock == 0) {
			LM_ERR("can't forward to af %d, proto %d no corresponding"
					" listening socket\n", dst_fin->to.s.sa_family, dst_fin->proto);
			goto error;
		}
	}

	/* Version && proto && length */
	hdr.hp_l = sizeof(struct hep_hdr);
	hdr.hp_v = hep_version;
	hdr.hp_p = proto;

	/* AND the last */
	if (from_su.s.sa_family==AF_INET){
		/* prepare the hep headers */

		hdr.hp_f = AF_INET;
		hdr.hp_sport = htons(from_su.sin.sin_port);
		hdr.hp_dport = htons(to_su.sin.sin_port);

		hep_ipheader.hp_src = from_su.sin.sin_addr;
		hep_ipheader.hp_dst = to_su.sin.sin_addr;

		len = sizeof(struct hep_iphdr);
	}
	else if (from_su.s.sa_family==AF_INET6){
		/* prepare the hep6 headers */

		hdr.hp_f = AF_INET6;

		hdr.hp_sport = htons(from_su.sin6.sin6_port);
		hdr.hp_dport = htons(to_su.sin6.sin6_port);

		hep_ip6header.hp6_src = from_su.sin6.sin6_addr;
		hep_ip6header.hp6_dst = to_su.sin6.sin6_addr;

		len = sizeof(struct hep_ip6hdr);
	}
	else {
		LM_ERR("Unsupported protocol family\n");
		goto error;;
	}

	hdr.hp_l +=len;
	if (hep_version == 2){
		len += sizeof(struct hep_timehdr);
	}
	len += sizeof(struct hep_hdr) + body->len;
	buffer = (void *)pkg_malloc(len+1);
	if (buffer==0){
		LM_ERR("out of memory\n");
		goto error;
	}

	/* Copy job */
	memset(buffer, '\0', len+1);

	/* copy hep_hdr */
	memcpy((void*)buffer, &hdr, sizeof(struct hep_hdr));
	buflen = sizeof(struct hep_hdr);

	/* hep_ip_hdr */
	if(from_su.s.sa_family==AF_INET) {
		memcpy((void*)buffer + buflen, &hep_ipheader, sizeof(struct hep_iphdr));
		buflen += sizeof(struct hep_iphdr);
	}
	else {
		memcpy((void*)buffer+buflen, &hep_ip6header, sizeof(struct hep_ip6hdr));
		buflen += sizeof(struct hep_ip6hdr);
	}

	if(hep_version == 2) {

		hep_time.tv_sec = tvb.tv_sec;
		hep_time.tv_usec = tvb.tv_usec;
		hep_time.captid = hep_capture_id;

		memcpy((void*)buffer+buflen, &hep_time, sizeof(struct hep_timehdr));
		buflen += sizeof(struct hep_timehdr);
	}

	/* PAYLOAD */
	memcpy((void*)(buffer + buflen) , (void*)body->s, body->len);
	buflen +=body->len;

	if (msg_send_buffer(dst_fin, buffer, buflen, 1)<0)
	{
		LM_ERR("cannot send hep duplicate message\n");
		goto error;
	}

	if (p) {
		free_proxy(p); /* frees only p content, not p itself */
		pkg_free(p);
	}
	pkg_free(buffer);
	return 0;
error:
	if(p)
	{
		free_proxy(p); /* frees only p content, not p itself */
		pkg_free(p);
	}
	if(buffer) pkg_free(buffer);
	return -1;
}
Example #9
0
/*!
 * \brief Previous hop was a strict router, handle this case
 * \param _m SIP message
 * \return -1 on error, 1 on success
 */
static inline int after_strict(struct sip_msg* _m)
{
	int res, rem_len;
	struct hdr_field* hdr;
	struct sip_uri puri;
	rr_t* rt, *prev;
	char* rem_off;
	str uri;
	struct socket_info *si;

	hdr = _m->route;
	rt = (rr_t*)hdr->parsed;
	uri = rt->nameaddr.uri;

	/* reset rr handling static vars for safety in error case */
	routed_msg_id = 0;
	routed_params.s = NULL;
	routed_params.len = 0;

	if (parse_uri(uri.s, uri.len, &puri) < 0) {
		LM_ERR("failed to parse the first route URI\n");
		return RR_ERROR;
	}

	if ( enable_double_rr && is_2rr(&puri.params) && is_myself(&puri)) {
		/* double route may occure due different IP and port, so force as
		 * send interface the one advertise in second Route */
		si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
		if (si) {
			set_force_socket(_m, si);
		} else {
			if (enable_socket_mismatch_warning)
				LM_WARN("no socket found for match second RR\n");
		}

		if (!rt->next) {
			/* No next route in the same header, remove the whole header
			 * field immediately
			 */
			if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
				LM_ERR("failed to remove Route HF\n");
				return RR_ERROR;
			}
			res = find_next_route(_m, &hdr);
			if (res < 0) {
				LM_ERR("searching next route failed\n");
				return RR_ERROR;
			}
			if (res > 0) { /* No next route found */
				LM_DBG("after_strict: No next URI found\n");
				return NOT_RR_DRIVEN;
			}
			rt = (rr_t*)hdr->parsed;
		} else rt = rt->next;

		/* parse the new found uri */
		uri = rt->nameaddr.uri;
		if (parse_uri(uri.s, uri.len, &puri) < 0) {
			LM_ERR("failed to parse URI\n");
			return RR_ERROR;
		}
	}

	/* set the hooks for the param
	 * important note: RURI is already parsed by the above function, so 
	 * we just used it without any checking */
	routed_msg_id = _m->id;
	routed_params = _m->parsed_uri.params;

	if (is_strict(&puri.params)) {
		LM_DBG("Next hop: '%.*s' is strict router\n", uri.len, ZSW(uri.s));
		/* Previous hop was a strict router and the next hop is strict
		 * router too. There is no need to save R-URI again because it
		 * is saved already. In fact, in this case we will behave exactly
		 * like a strict router. */

		/* Note: when there is only one Route URI left (endpoint), it will
		 * always be a strict router because endpoints don't use ;lr parameter
		 * In this case we will simply put the URI in R-URI and forward it, 
		 * which will work perfectly */
		if(get_maddr_uri(&uri, &puri)!=0) {
			LM_ERR("failed to check maddr\n");
			return RR_ERROR;
		}
		if (rewrite_uri(_m, &uri) < 0) {
			LM_ERR("failed to rewrite request URI\n");
			return RR_ERROR;
		}
		
		if (rt->next) {
			rem_off = hdr->body.s;
			rem_len = rt->next->nameaddr.name.s - hdr->body.s;
		} else {
			rem_off = hdr->name.s;
			rem_len = hdr->len;
		}
		if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
			LM_ERR("failed to remove Route HF\n");
			return RR_ERROR;
		}
	} else {
		LM_DBG("Next hop: '%.*s' is loose router\n",
			uri.len, ZSW(uri.s));

		if(get_maddr_uri(&uri, &puri)!=0) {
			LM_ERR("failed to check maddr\n");
			return RR_ERROR;
		}
		if (set_dst_uri(_m, &uri) < 0) {
			LM_ERR("failed to set dst_uri\n");
			return RR_ERROR;
		}

		/* Next hop is a loose router - Which means that is is not endpoint yet
		 * In This case we have to recover from previous strict routing, that 
		 * means we have to find the last Route URI and put in in R-URI and 
		 * remove the last Route URI. */
		if (rt != hdr->parsed) {
			/* There is a previous route uri which was 2nd uri of mine
			 * and must be removed here */
			rem_off = hdr->body.s;
			rem_len = rt->nameaddr.name.s - hdr->body.s;
			if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
				LM_ERR("failed to remove Route HF\n");
				return RR_ERROR;
			}
		}


		res = find_rem_target(_m, &hdr, &rt, &prev);
		if (res < 0) {
			LM_ERR("searching for last Route URI failed\n");
			return RR_ERROR;
		} else if (res > 0) {
			/* No remote target is an error */
			return RR_ERROR;
		}

		uri = rt->nameaddr.uri;
		if(get_maddr_uri(&uri, 0)!=0) {
			LM_ERR("checking maddr failed\n");
			return RR_ERROR;
		}
		if (rewrite_uri(_m, &uri) < 0) {
			LM_ERR("failed to rewrite R-URI\n");
			return RR_ERROR;
		}

		/* The first character if uri will be either '<' when it is the 
		 * only URI in a Route header field or ',' if there is more than 
		 * one URI in the header field */
		LM_DBG("The last route URI: '%.*s'\n", rt->nameaddr.uri.len,
				ZSW(rt->nameaddr.uri.s));

		if (prev) {
			rem_off = prev->nameaddr.name.s + prev->len;
			rem_len = rt->nameaddr.name.s + rt->len - rem_off;
		} else {
			rem_off = hdr->name.s;
			rem_len = hdr->len;
		}
		if (!del_lump(_m, rem_off - _m->buf, rem_len, 0)) {
			LM_ERR("failed to remove Route HF\n");
			return RR_ERROR;
		}
	}
	
	/* run RR callbacks only if we have Route URI parameters */
	if(routed_params.len > 0)
		run_rr_callbacks( _m, &routed_params );

	return RR_DRIVEN;
}
Example #10
0
/*!
 * \brief Previous hop was a loose router, handle this case
 * \param _m SIP message
 * \param preloaded do we have a preloaded route set
 * \return -1 on failure, 1 on success
 */
static inline int after_loose(struct sip_msg* _m, int preloaded)
{
	struct hdr_field* hdr;
	struct sip_uri puri;
	rr_t* rt;
	int res;
	int status = RR_DRIVEN;
	str uri;
	struct socket_info *si;
	int uri_is_myself, next_is_strict;
	int use_ob = 0;

	hdr = _m->route;
	rt = (rr_t*)hdr->parsed;
	uri = rt->nameaddr.uri;

	/* reset rr handling static vars for safety in error case */
	routed_msg_id = 0;

	if (parse_uri(uri.s, uri.len, &puri) < 0) {
		LM_ERR("failed to parse the first route URI\n");
		return RR_ERROR;
	}

	next_is_strict = is_strict(&puri.params);
	routed_params = puri.params;
	uri_is_myself = is_myself(&puri);

	/* IF the URI was added by me, remove it */
	if (uri_is_myself>0)
	{
		LM_DBG("Topmost route URI: '%.*s' is me\n",
			uri.len, ZSW(uri.s));
		/* set the hooks for the params */
		routed_msg_id = _m->id;

		if ((use_ob = process_outbound(_m, puri.user)) < 0) {
			LM_INFO("failed to process outbound flow-token\n");
			return FLOW_TOKEN_BROKEN;
		}

		if (!rt->next) {
			/* No next route in the same header, remove the whole header
			 * field immediately
			 */
			if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
				LM_ERR("failed to remove Route HF\n");
				return RR_ERROR;
			}

			res = find_next_route(_m, &hdr);
			if (res < 0) {
				LM_ERR("failed to find next route\n");
				return RR_ERROR;
			}
			if (res > 0) { /* No next route found */
				LM_DBG("No next URI found\n");
				status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN);
				goto done;
			}
			rt = (rr_t*)hdr->parsed;
		} else rt = rt->next;

		if (enable_double_rr && is_2rr(&puri.params)) {
			/* double route may occure due different IP and port, so force as
			 * send interface the one advertise in second Route */
			if (parse_uri(rt->nameaddr.uri.s,rt->nameaddr.uri.len,&puri)<0) {
				LM_ERR("failed to parse the double route URI\n");
				return RR_ERROR;
			}

			if (!use_ob) {
				si = grep_sock_info( &puri.host, puri.port_no, puri.proto);
				if (si) {
					set_force_socket(_m, si);
				} else {
					if (enable_socket_mismatch_warning)
						LM_WARN("no socket found for match second RR\n");
				}
			}

			if (!rt->next) {
				/* No next route in the same header, remove the whole header
				 * field immediately */
				if (!del_lump(_m, hdr->name.s - _m->buf, hdr->len, 0)) {
					LM_ERR("failed to remove Route HF\n");
					return RR_ERROR;
				}
				res = find_next_route(_m, &hdr);
				if (res < 0) {
					LM_ERR("failed to find next route\n");
					return RR_ERROR;
					}
				if (res > 0) { /* No next route found */
					LM_DBG("no next URI found\n");
					status = (preloaded ? NOT_RR_DRIVEN : RR_DRIVEN);
					goto done;
				}
				rt = (rr_t*)hdr->parsed;
			} else rt = rt->next;
		}
		
		uri = rt->nameaddr.uri;
		if (parse_uri(uri.s, uri.len, &puri) < 0) {
			LM_ERR("failed to parse the first route URI\n");
			return RR_ERROR;
		}
	} else {
#ifdef ENABLE_USER_CHECK
		/* check if it the ignored user */
		if(uri_is_myself < 0)
			return NOT_RR_DRIVEN;
#endif
		LM_DBG("Topmost URI is NOT myself\n");
		routed_params.s = NULL;
		routed_params.len = 0;
	}

	LM_DBG("URI to be processed: '%.*s'\n", uri.len, ZSW(uri.s));
	if (next_is_strict) {
		LM_DBG("Next URI is a strict router\n");
		if (handle_sr(_m, hdr, rt) < 0) {
			LM_ERR("failed to handle strict router\n");
			return RR_ERROR;
		}
	} else {
		/* Next hop is loose router */
		LM_DBG("Next URI is a loose router\n");

		if (!use_ob) {
			if(get_maddr_uri(&uri, &puri)!=0) {
				LM_ERR("checking maddr failed\n");
				return RR_ERROR;
			}
		
			if (set_dst_uri(_m, &uri) < 0) {
				LM_ERR("failed to set dst_uri\n");
				return RR_ERROR;
			}
			/* dst_uri changed, so it makes sense to re-use the current uri for
			forking */
			ruri_mark_new(); /* re-use uri for serial forking */
		}

		/* There is a previous route uri which was 2nd uri of mine
		 * and must be removed here */
		if (rt != hdr->parsed) {
			if (!del_lump(_m, hdr->body.s - _m->buf, 
			rt->nameaddr.name.s - hdr->body.s, 0)) {
				LM_ERR("failed to remove Route HF\n");
				return RR_ERROR;
			}
		}
	}

done:
	if (use_ob == 1)
		status = RR_OB_DRIVEN;

	/* run RR callbacks only if we have Route URI parameters */
	if(routed_params.len > 0)
		run_rr_callbacks( _m, &routed_params );
	return status;
}
Example #11
0
/*load groups of destinations from DB*/
int ds_load_db(void)
{
	int i, id, nr_rows, setn, cnt;
	int flags;
	int weight;
	struct socket_info *sock;
	str uri;
	str attrs;
	str host;
	int port, proto;
	db_res_t * res;
	db_val_t * values;
	db_row_t * rows;

	db_key_t query_cols[6] = {&ds_set_id_col, &ds_dest_uri_col,
			&ds_dest_sock_col, &ds_dest_flags_col,
			&ds_dest_weight_col, &ds_dest_attrs_col};

	if( (*crt_idx) != (*next_idx))
	{
		LM_WARN("load command already generated, aborting reload...\n");
		return 0;
	}

	if(ds_db_handle == NULL){
			LM_ERR("invalid DB handler\n");
			return -1;
	}

	if (ds_dbf.use_table(ds_db_handle, &ds_table_name) < 0)
	{
		LM_ERR("error in use_table\n");
		return -1;
	}

	/*select the whole table and all the columns*/
	if(ds_dbf.query(ds_db_handle,0,0,0,query_cols,0,6,0,&res) < 0)
	{
		LM_ERR("error while querying database\n");
		return -1;
	}

	*next_idx = (*crt_idx + 1)%2;
	destroy_list(*next_idx);

	nr_rows = RES_ROW_N(res);
	rows = RES_ROWS(res);
	if(nr_rows == 0)
	{
		LM_WARN("no dispatching data in the db -- empty destination set\n");
		goto load_done;
	}

	setn = 0;
	cnt = 0;

	for(i=0; i<nr_rows; i++)
	{
		values = ROW_VALUES(rows+i);

		/* id */
		if (VAL_NULL(values)) {
			LM_ERR("ds ID column cannot be NULL -> skipping\n");
			continue;
		}
		id = VAL_INT(values);

		/* uri */
		get_str_from_dbval( "URI", values+1,
			1/*not_null*/, 1/*not_empty*/, uri, err2);

		/* sock */
		get_str_from_dbval( "SOCKET", values+2,
			0/*not_null*/, 0/*not_empty*/, attrs, err2);
		if ( attrs.len ) {
			if (parse_phostport( attrs.s, attrs.len, &host.s, &host.len,
			&port, &proto)!=0){
				LM_ERR("socket description <%.*s> is not valid -> ignoring\n",
					attrs.len,attrs.s);
				sock = NULL;
			} else {
				sock = grep_sock_info( &host, port, proto);
				if (sock == NULL) {
					LM_ERR("socket <%.*s> is not local to opensips (we must "
						"listen on it) -> ignoring it\n", attrs.len, attrs.s);
				}
			}
		} else {
			sock = NULL;
		}

		/* flags */
		if (VAL_NULL(values+3)) {
			flags = 0;
		} else {
			flags = VAL_INT(values+3);
		}

		/* weight */
		if (VAL_NULL(values+4)) {
			weight = 1;
		} else {
			weight = VAL_INT(values+4);
		}

		/* attrs */
		get_str_from_dbval( "ATTRIBUTES", values+5,
			0/*not_null*/, 0/*not_empty*/, attrs, err2);

		if(add_dest2list(id, uri, sock, flags, weight, attrs, *next_idx,
		&setn) != 0) {
			LM_WARN("failed to add destination <%.*s> in group %d\n",uri.len,uri.s,id);
			continue;
		} else {
			cnt ++;
		}

	}

	if (cnt==0) {
		LM_WARN("No record loaded from db, running on empty set\n");
	} else {
		if(reindex_dests(*next_idx, setn)!=0)
		{
			LM_ERR("error on reindex\n");
			goto err2;
		}
	}

load_done:
	/*update data*/
	_ds_list_nr = setn;
	*crt_idx = *next_idx;
	ds_dbf.free_result(ds_db_handle, res);

	return 0;

err2:
	destroy_list(*next_idx);
	ds_dbf.free_result(ds_db_handle, res);
	*next_idx = *crt_idx; 

	return -1;
}
Example #12
0
int dp_apply_policy(struct sip_msg* _msg, char* _s1, char* _s2) {

	str *domain;
	int_str val;
	struct usr_avp *avp;

	char duri[MAX_URI_SIZE];
	str duri_str;
	int len, didsomething;
	char *at; /* pointer to current location inside duri */

	str host;
	int port, proto;
	struct socket_info* si;

	if (route_type != REQUEST_ROUTE) {
		LM_ERR("unsupported route type\n");
		return -1;
	}

	/*
	 * set the send_socket
	 */

	/* search for send_socket AVP */
	avp = search_first_avp(0, send_socket_name, &val, 0);
	if (avp) {
		if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
			LM_ERR("empty or non-string send_socket_avp, "
					"return with error ...\n");
			return -1;
		}
		LM_DBG("send_socket_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
		/* parse phostport */
		if (parse_phostport(val.s.s, val.s.len, &(host.s), &(host.len), &port, &proto)) {
			LM_ERR("could not parse send_socket, return with error ...\n");
			return -1;
		}
		si = grep_sock_info( &host, (unsigned short) port, (unsigned short) proto);
		if (si) {
			_msg->force_send_socket = si;
		} else {
			LM_WARN("could not find socket for"
					"send_socket '%.*s'\n", val.s.len, ZSW(val.s.s));
		}
	} else {
		LM_DBG("send_socket_avp not found\n");
	}

	/*
	 * set the destination URI
	 */

	didsomething = 0; /* if no AVP is set, there is no need to set the DURI in the end */
	
	if (parse_sip_msg_uri(_msg) < 0) {
		LM_ERR("failed to parse R-URI\n");
		return -1;
	}

	at = (char *)&(duri[0]);
	len = 0;
	if ( (len + 4) >  MAX_URI_SIZE) {
		LM_ERR("duri buffer to small to add uri schema\n");
		return -1;
	}
	memcpy(at, "sip:", 4); at = at + 4; len = len + 4;

	domain = &(_msg->parsed_uri.host);
	LM_DBG("domain is %.*s.\n", domain->len, ZSW(domain->s));

	/* search for prefix and add it to duri buffer */
	avp = search_first_avp(0, domain_prefix_name, &val, 0);
	if (avp) {
		if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
			LM_ERR("empty or non-string domain_prefix_avp, return with error ...\n");
			return -1;
		}
		LM_DBG("domain_prefix_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
		if ( (len + val.s.len +1) >  MAX_URI_SIZE) {
			LM_ERR("duri buffer to small to add domain prefix\n");
			return -1;
		}
		memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
		*at = '.'; at = at + 1;	/* add . as delimiter between prefix and domain */
		didsomething = 1;
	} else {
		LM_DBG("domain_prefix_avp not found\n");
	}


	/* add domain to duri buffer */
	avp = search_first_avp(0, domain_replacement_name, &val, 0);
	if (avp) {
		if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
			LM_ERR("empty or non-string domain_replacement_avp, return with"
					"error ...\n");
			return -1;
		}
		LM_DBG("domain_replacement_avp found='%.*s'\n",val.s.len, ZSW(val.s.s));
		if ( (len + val.s.len +1) >  MAX_URI_SIZE) {
			LM_ERR("duri buffer to small to add domain replacement\n");
			return -1;
		}
		memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
		didsomething = 1;
	} else {
	    LM_DBG("domain_replacement_avp not found, using original domain '"
				"%.*s'\n",domain->len, domain->s);
	    if ( (len + domain->len) >  MAX_URI_SIZE) {
		LM_ERR("duri buffer to small to add domain\n");
		return -1;
	    }
	    memcpy(at, domain->s, domain->len); at = at + domain->len;
	}
	
	/* search for suffix and add it to duri buffer */
	avp = search_first_avp(0, domain_suffix_name, &val, 0);
	if (avp) {
		if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
			LM_ERR("empty or non-string domain_suffix_avp,return with error .."
					"\n");
			return -1;
		}
		LM_DBG("domain_suffix_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
		if ( (len + val.s.len + 1) >  MAX_URI_SIZE) {
			LM_ERR("duri buffer to small to add domain suffix\n");
			return -1;
		}
		*at = '.'; at = at + 1;	/* add . as delimiter between domain and suffix */
		memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
		didsomething = 1;
	} else {
		LM_DBG("domain_suffix_avp not found\n");
	}

	/* search for port override and add it to duri buffer */
	avp = search_first_avp(0, port_override_name, &val, 0);
	if (avp) {
		if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
			LM_ERR("empty or non-string port_override_avp, return with error ...\n");
			return -1;
		}
		LM_DBG("port_override_avp found = '%.*s'\n", val.s.len, ZSW(val.s.s));
		/* We do not check if the port is valid */
		if ( (len + val.s.len + 1) >  MAX_URI_SIZE) {
			LM_ERR("duri buffer to small to add domain suffix\n");
			return -1;
		}
		*at = ':'; at = at + 1;	/* add : as delimiter between domain and port */
		memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
		didsomething = 1;
	} else {
		LM_DBG("port_override_avp not found, using original port\n");
		if (_msg->parsed_uri.port.len) {
			LM_DBG("port found in RURI, reusing it for DURI\n");
			if ( (len + _msg->parsed_uri.port.len + 1) >  MAX_URI_SIZE) {
				LM_ERR("duri buffer to small to copy port\n");
				return -1;
			}
			*at = ':'; at = at + 1;	
			/* add : as delimiter between domain and port */
			memcpy(at, _msg->parsed_uri.port.s, _msg->parsed_uri.port.len); 
			at = at + _msg->parsed_uri.port.len;
		} else {
			LM_DBG("port not found in RURI, no need to copy it to DURI\n");
		}
	}

	/* search for transport override and add it to duri buffer */
	avp = search_first_avp(0, transport_override_name, &val, 0);
	if (avp) {
		if ( !(avp->flags&AVP_VAL_STR) ||  !val.s.s || !val.s.len) {
			LM_ERR("empty or non-string transport_override_avp, "
					"return with error ...\n");
			return -1;
		}
		LM_DBG("transport_override_avp found='%.*s'\n",val.s.len, ZSW(val.s.s));

		if ( (len + val.s.len + 11) >  MAX_URI_SIZE) {
			LM_ERR("duri buffer to small to add transport override\n");
			return -1;
		}
		/* add : as transport parameter to duri; NOTE: no checks if transport parameter is valid  */
		memcpy(at, ";transport=", 11); at = at + 11;
		memcpy(at, val.s.s, val.s.len); at = at + val.s.len;
		didsomething = 1;
	} else {
		LM_DBG("transport_override_avp not found, using original transport\n");
		if (_msg->parsed_uri.transport.len) {
			LM_DBG("transport found in RURI, reusing it for DURI\n");
			if ( (len + _msg->parsed_uri.transport.len + 1) >  MAX_URI_SIZE) {
				LM_ERR("duri buffer to small to copy transport\n");
				return -1;
			}
			*at = ';'; at = at + 1; /* add : as delimiter between domain and port */
			memcpy(at, _msg->parsed_uri.transport.s, _msg->parsed_uri.transport.len); at = at + _msg->parsed_uri.transport.len;
		} else {
			LM_DBG("transport not found in RURI, no need to copy it to DURI\n");
		}
	}

	/* write new target DURI into DURI */
	if (didsomething == 0) {
		LM_DBG("no domainpolicy AVP set, no need to push new DURI\n");
		return 2;
	}
	duri_str.s = (char *)&(duri[0]);
	duri_str.len = at - duri_str.s;
	LM_DBG("new DURI is '%.*s'\n",duri_str.len, ZSW(duri_str.s));
	set_dst_uri(_msg, &duri_str);

	return 1;
}
Example #13
0
/** rpc t_uac version-
  * It expects the following list of strings as parameters:
  *  method
  *  request_uri
  *  dst_uri (next hop) -- can be empty (either "" or ".", which is still
  *                        supported for backwards compatibility with fifo)
  *  send_socket (socket from which the message will be sent)
  *  headers (message headers separated by CRLF, at least From and To
  *           must be present)
  *  body (optional, might be null or completely missing)
  *
  * If all the parameters are ok it will call t_uac() using them.
  * Note: this version will  wait for the transaction final reply
  * only if reply_wait is set to 1. Otherwise the rpc reply will be sent 
  * immediately and it will be success if the paremters were ok and t_uac did
  * not report any error.
  * Note: reply waiting (reply_wait==1) is not yet supported.
  * @param rpc - rpc handle
  * @param  c - rpc current context
  * @param reply_wait - if 1 do not generate a rpc reply until final response
  *                     for the transaction arrives, if 0 immediately send
  *                     an rpc reply (see above).
  */
static void rpc_t_uac(rpc_t* rpc, void* c, int reply_wait)
{
	/* rpc params */
	str method, ruri, nexthop, send_socket, headers, body;
	/* other internal vars.*/
	str hfb, callid;
	struct sip_uri p_uri, pnexthop;
	struct sip_msg faked_msg;
	struct socket_info* ssock;
	str saddr;
	int sport, sproto;
	int ret, sip_error, err_ret, fromtag, cseq_is, cseq;
	char err_buf[MAX_REASON_LEN];
	dlg_t dlg;
	uac_req_t uac_req;
	rpc_delayed_ctx_t* dctx;
	
	body.s=0;
	body.len=0;
	dctx=0;
	if (reply_wait && (rpc->capabilities == 0 ||
						!(rpc->capabilities(c) & RPC_DELAYED_REPLY))) {
		rpc->fault(c, 600, "Reply wait/async mode not supported"
							" by this rpc transport");
		return;
	}
	ret=rpc->scan(c, "SSSSS*S",
					&method, &ruri, &nexthop, &send_socket, &headers, &body);
	if (ret<5 && ! (-ret == 5)){
		rpc->fault(c, 400, "too few parameters (%d/5)", ret?ret:-ret);
		return;
	}
	/* check and parse parameters */
	if (method.len==0){
		rpc->fault(c, 400, "Empty method");
		return;
	}
	if (parse_uri(ruri.s, ruri.len, &p_uri)<0){
		rpc->fault(c, 400, "Invalid request uri \"%s\"", ruri.s);
		return;
	}
	/* old fifo & unixsock backwards compatibility for nexthop: '.' is still
	   allowed */
	if (nexthop.len==1 && nexthop.s[0]=='.'){
		/* empty nextop */
		nexthop.len=0;
		nexthop.s=0;
	}else if (nexthop.len==0){
		nexthop.s=0;
	}else if (parse_uri(nexthop.s, nexthop.len, &pnexthop)<0){
		rpc->fault(c, 400, "Invalid next-hop uri \"%s\"", nexthop.s);
		return;
	}
	/* kamailio backwards compatibility for send_socket: '.' is still
	   allowed for an empty socket */
	ssock=0;
	saddr.s=0;
	saddr.len=0;
	if (send_socket.len==1 && send_socket.s[0]=='.'){
		/* empty send socket */
		send_socket.len=0;
	}else if (send_socket.len &&
				(parse_phostport(send_socket.s, &saddr.s, &saddr.len,
								&sport, &sproto)!=0 ||
				 				/* check also if it's not a MH addr. */
				 				saddr.len==0 || saddr.s[0]=='(')
				){
		rpc->fault(c, 400, "Invalid send socket \"%s\"", send_socket.s);
		return;
	}else if (saddr.len && (ssock=grep_sock_info(&saddr, sport, sproto))==0){
		rpc->fault(c, 400, "No local socket for \"%s\"", send_socket.s);
		return;
	}
	/* check headers using the SIP parser to look in the header list */
	memset(&faked_msg, 0, sizeof(struct sip_msg));
	faked_msg.len=headers.len;
	faked_msg.buf=faked_msg.unparsed=headers.s;
	if (parse_headers(&faked_msg, HDR_EOH_F, 0)==-1){
		rpc->fault(c, 400, "Invalid headers");
		return;
	}
	/* at this moment all the parameters are parsed => more sanity checks */
	if (rpc_uac_check_msg(rpc, c, &faked_msg, &method, &body, &fromtag,
							&cseq_is, &cseq, &callid)<0)
		goto error;
	hfb.s=get_hfblock(nexthop.len? &nexthop: &ruri, faked_msg.headers,
						PROTO_NONE, ssock, &hfb.len);
	if (hfb.s==0){
		rpc->fault(c, 500, "out of memory");
		goto error;
	}
	/* proceed to transaction creation */
	memset(&dlg, 0, sizeof(dlg_t));
	/* fill call-id if call-id present or else generate a callid */
	if (callid.s && callid.len) dlg.id.call_id=callid;
	else generate_callid(&dlg.id.call_id);
	
	/* We will not fill in dlg->id.rem_tag because
	 * if present it will be printed within To HF
	 */
	
	/* Generate fromtag if not present */
	if (!fromtag) {
		generate_fromtag(&dlg.id.loc_tag, &dlg.id.call_id);
	}
	
	/* Fill in CSeq */
	if (cseq_is) dlg.loc_seq.value = cseq;
	else dlg.loc_seq.value = DEFAULT_CSEQ;
	dlg.loc_seq.is_set = 1;
	
	dlg.loc_uri = faked_msg.from->body;
	dlg.rem_uri = faked_msg.to->body;
	dlg.rem_target = ruri;
	dlg.dst_uri = nexthop;
	dlg.send_sock=ssock;
	
	memset(&uac_req, 0, sizeof(uac_req));
	uac_req.method=&method;
	uac_req.headers=&hfb;
	uac_req.body=body.len?&body:0;
	uac_req.dialog=&dlg;
	if (reply_wait){
		dctx=rpc->delayed_ctx_new(c);
		if (dctx==0){
			rpc->fault(c, 500, "internal error: failed to create context");
			return;
		}
		uac_req.cb=rpc_uac_callback;
		uac_req.cbp=dctx;
		uac_req.cb_flags=TMCB_LOCAL_COMPLETED;
		/* switch to dctx, in case adding the callback fails and we
		   want to still send a reply */
		rpc=&dctx->rpc;
		c=dctx->reply_ctx;
	}
	ret = t_uac(&uac_req);
	
	if (ret <= 0) {
		err_ret = err2reason_phrase(ret, &sip_error, err_buf,
			sizeof(err_buf), "RPC/UAC") ;
		if (err_ret > 0 )
		{
			rpc->fault(c, sip_error, "%s", err_buf);
		} else {
			rpc->fault(c, 500, "RPC/UAC error");
		}
		if (dctx)
			rpc->delayed_ctx_close(dctx);
		goto error01;
	}
error01:
	if (hfb.s) pkg_free(hfb.s);
error:
	if (faked_msg.headers) free_hdr_field_lst(faked_msg.headers);
}
Example #14
0
static inline int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
								unsigned int part_idx, unsigned int part_max)
{
	static char query_buf[512];
	static str query_str;

	struct socket_info *sock;
	unsigned int dbflags;
	db_res_t* res = NULL;
	db_row_t *row;
	dlist_t *dom;
	char *p, *p1;
	char now_s[25];
	int now_len;
	int port, proto, p_len, p1_len;
	str host;
	int i;
	void *cp;
	int shortage, needed;

	cp = buf;
	shortage = 0;
	/* Reserve space for terminating 0000 */
	len -= sizeof(p_len);

	/* get the current time in DB format */
	now_len = 25;
	if (db_time2str( time(0), now_s, &now_len)!=0) {
		LM_ERR("failed to print now time\n");
		return -1;
	}

	for (dom = root; dom!=NULL ; dom=dom->next) {
		/* build query */
		i = snprintf( query_buf, sizeof(query_buf), "select %.*s, %.*s, %.*s,"
#ifdef ORACLE_USRLOC
			" %.*s, %.*s from %s where %.*s > %.*s and "
			"bitand(%.*s, %d) = %d and mod(id, %u) = %u",
#else
			" %.*s, %.*s from %s where %.*s > %.*s and %.*s & %d = %d and "
			"id %% %u = %u",
#endif
			received_col.len, received_col.s,
			contact_col.len, contact_col.s,
			sock_col.len, sock_col.s,
			cflags_col.len, cflags_col.s,
			path_col.len, path_col.s,
			dom->d->name->s,
			expires_col.len, expires_col.s,
			now_len, now_s,
			cflags_col.len, cflags_col.s,
			flags, flags, part_max, part_idx);
		if ( i>=sizeof(query_buf) ) {
			LM_ERR("DB query too long\n");
			return -1;
		}
		query_str.s = query_buf;
		query_str.len = i;
		if ( ul_dbf.raw_query( ul_dbh, &query_str, &res)<0 ) {
			LM_ERR("raw_query failed\n");
			return -1;
		}
		if( RES_ROW_N(res)==0 ) {
			ul_dbf.free_result(ul_dbh, res);
			continue;
		}

		for(i = 0; i < RES_ROW_N(res); i++) {
			row = RES_ROWS(res) + i;

			/* received */
			p = (char*)VAL_STRING(ROW_VALUES(row));
			if ( VAL_NULL(ROW_VALUES(row)) || p==0 || p[0]==0 ) {
				/* contact */
				p = (char*)VAL_STRING(ROW_VALUES(row)+1);
				if (VAL_NULL(ROW_VALUES(row)+1) || p==0 || p[0]==0) {
					LM_ERR("empty contact -> skipping\n");
					continue;
				}
			}
			p_len = strlen(p);

			/* path */
			p1 = (char*)VAL_STRING(ROW_VALUES(row)+4);
			if (VAL_NULL(ROW_VALUES(row)+4) || p1==0 || p1[0]==0){
				p1 = NULL;
				p1_len = 0;
			} else {
				p1_len = strlen(p1);
			}

			needed = (int)(sizeof(p_len)+p_len+sizeof(sock)+sizeof(dbflags)+
				sizeof(p1_len)+p1_len);
			if (len < needed) {
				shortage += needed ;
				continue;
			}

			/* write received/contact */
			memcpy(cp, &p_len, sizeof(p_len));
			cp = (char*)cp + sizeof(p_len);
			memcpy(cp, p, p_len);
			cp = (char*)cp + p_len;

			/* sock */
			p  = (char*)VAL_STRING(ROW_VALUES(row) + 2);
			if (VAL_NULL(ROW_VALUES(row)+2) || p==0 || p[0]==0){
				sock = 0;
			} else {
				if (parse_phostport( p, strlen(p), &host.s, &host.len,
				&port, &proto)!=0) {
					LM_ERR("bad socket <%s>...ignoring\n", p);
					sock = 0;
				} else {
					sock = grep_sock_info( &host, (unsigned short)port, proto);
					if (sock==0) {
						LM_DBG("non-local socket <%s>...ignoring\n", p);
					}
				}
			}

			/* flags */
			dbflags = VAL_BITMAP(ROW_VALUES(row) + 3);

			/* write sock and flags */
			memcpy(cp, &sock, sizeof(sock));
			cp = (char*)cp + sizeof(sock);
			memcpy(cp, &dbflags, sizeof(dbflags));
			cp = (char*)cp + sizeof(dbflags);

			/* write path */
			memcpy(cp, &p1_len, sizeof(p1_len));
			cp = (char*)cp + sizeof(p1_len);
			memcpy(cp, p1, p1_len);
			cp = (char*)cp + p1_len;

			len -= needed;
		} /* row cycle */

		ul_dbf.free_result(ul_dbh, res);
	} /* domain cycle */

	/* len < 0 is possible, if size of the buffer < sizeof(c->c.len) */
	if (len >= 0)
		memset(cp, 0, sizeof(p_len));

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

	shortage -= len;

	return shortage > 0 ? shortage : 0;
}
Example #15
0
static int get_all_db_ucontacts(void *buf, int len, unsigned int flags,
                                unsigned int part_idx, unsigned int part_max)
{
	static char query_buf[512];
	static str query_str;
	static struct sip_uri puri;

	struct socket_info *sock;
	struct proxy_l next_hop;
	db_res_t *res = NULL;
	db_row_t *row;
	db_val_t *val;
	dlist_t *dom;
	str uri, host, flag_list;
	int i, no_rows = 10;
	int now_len;
	char now_s[25];
	char *p, *p1;
	int port, proto, p_len, p1_len;
	unsigned int dbflags;
	int needed;
	int shortage = 0;

	shortage = 0;
	/* Reserve space for terminating 0000 */
	len -= sizeof p_len;

	/* get the current time in DB format */
	now_len = 25;
	if (db_time2str(time(NULL), now_s, &now_len) != 0) {
		LM_ERR("failed to print now time\n");
		return -1;
	}

	LM_DBG("buf: %p. flags: %d\n", buf, flags);

	/* for each table */
	for (dom = root; dom; dom = dom->next) {
		if (db_check_table_version(&ul_dbf, ul_dbh, dom->d->name, UL_TABLE_VERSION))
			goto error;

		/* read the destinations */
		if (ul_dbf.use_table(ul_dbh, dom->d->name) < 0) {
			LM_ERR("cannot select table \"%.*s\"\n", dom->d->name->len,
			       dom->d->name->s);
			goto error;
		}

		i = snprintf(query_buf, sizeof query_buf, "select %.*s, %.*s, %.*s,"
#ifdef ORACLE_USRLOC
		" %.*s, %.*s from %s where %.*s > %.*s and mod(id, %u) = %u",
#else
		" %.*s, %.*s from %s where %.*s > %.*s and id %% %u = %u",
#endif
			received_col.len, received_col.s,
			contact_col.len, contact_col.s,
			sock_col.len, sock_col.s,
			cflags_col.len, cflags_col.s,
			path_col.len, path_col.s,
			dom->d->name->s,
			expires_col.len, expires_col.s,
			now_len, now_s,
			part_max, part_idx);

		LM_DBG("query: %.*s\n", (int)(sizeof query_buf), query_buf);
		if (i >= sizeof query_buf) {
			LM_ERR("DB query too long\n");
			goto error;
		}

		query_str.s = query_buf;
		query_str.len = i;

		if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
			if (ul_dbf.raw_query(ul_dbh, &query_str, 0) < 0) {
				LM_ERR("raw_query failed\n");
				goto error;
			}

			no_rows = estimate_available_rows(20+128+20+128+64, 5);
			if (no_rows == 0)
				no_rows = 10;

			LM_DBG("fetching %d rows\n", no_rows);

			if (ul_dbf.fetch_result(ul_dbh, &res, no_rows) < 0) {
				LM_ERR("Error fetching rows\n");
				goto error;
			}
		} else if (ul_dbf.raw_query(ul_dbh, &query_str, &res) < 0) {
			LM_ERR("raw_query failed\n");
			goto error;
		}

		do {
			for (i = 0; i < RES_ROW_N(res); i++) {
				row = RES_ROWS(res) + i;
				val = ROW_VALUES(row) + 3; /* cflags */
				flag_list.s   = (char *)VAL_STRING(val);
				flag_list.len = strlen(flag_list.s);

				LM_DBG("contact cflags: '%.*s'\n", flag_list.len, flag_list.s);

				/* contact is not flagged at all */
				if (flags && (val->nul || !flag_list.s))
					continue;

				dbflags = flag_list_to_bitmask(&flag_list,
				                FLAG_TYPE_BRANCH, FLAG_DELIM);

				LM_DBG("masks: param: %d --- %d :db\n", flags, dbflags);

				/* check if contact flags match the given bitmask */
				if ((dbflags & flags) != flags)
					continue;

				/* received */
				p = (char*)VAL_STRING(ROW_VALUES(row));
				if (VAL_NULL(ROW_VALUES(row)) || !p || !p[0]) {
					/* contact */
					p = (char*)VAL_STRING(ROW_VALUES(row) + 1);
					if (VAL_NULL(ROW_VALUES(row) + 1) || !p || *p == '\0') {
						LM_ERR("empty contact -> skipping\n");
						continue;
					}
				}
				p_len = strlen(p);

				/* path */
				p1 = (char*)VAL_STRING(ROW_VALUES(row) + 4);
				if (VAL_NULL(ROW_VALUES(row) + 4) || !p1 || *p1 == '\0') {
					p1 = NULL;
					p1_len = 0;
				} else
					p1_len = strlen(p1);

				needed = (int)(p_len + sizeof p_len + p1_len + sizeof p1_len +
				               sizeof sock + sizeof dbflags + sizeof next_hop);

				LM_DBG("len: %d, needed: %d\n", len, needed);

				if (len < needed) {
					shortage += needed;
					continue;
				}

				/* determine and parse the URI of this contact's next hop */
				if (p1_len > 0) {
					/* send to first URI in path */
					host.s   = p1;
					host.len = p1_len;
					if (get_path_dst_uri(&host, &uri) < 0) {
						LM_ERR("failed to get dst_uri for Path\n");
						continue;
					}
					if (parse_uri(uri.s, uri.len, &puri) < 0) {
						LM_ERR("failed to parse path URI of next hop: '%*.s'\n",
						        p1_len, p1);
						return -1;
					}
				} else {
					if (parse_uri(p, p_len, &puri) < 0) {
						LM_ERR("failed to parse contact of next hop: '%*.s'\n",
						        p_len, p);
						return -1;
					}
				}

				/* write received/contact */
				memcpy(buf, &p_len, sizeof p_len);
				buf += sizeof p_len;
				memcpy(buf, p, p_len);
				buf += p_len;

				/* write path */
				memcpy(buf, &p1_len, sizeof p1_len);
				buf += sizeof p1_len;
				memcpy(buf, p1, p1_len);
				buf += p1_len;

				/* sock */
				p  = (char*)VAL_STRING(ROW_VALUES(row) + 2);
				if (VAL_NULL(ROW_VALUES(row)+2) || !p || *p == '\0') {
					sock = NULL;
				} else {
					if (parse_phostport(p, strlen(p), &host.s, &host.len,
					    &port, &proto) != 0) {
						LM_ERR("bad socket <%s>...ignoring\n", p);
						sock = NULL;
					} else {
						sock = grep_sock_info(&host, (unsigned short)port, proto);
						if (!sock)
							LM_DBG("non-local socket <%s>...ignoring\n", p);
					}
				}

				/* write sock and flags */
				memcpy(buf, &sock, sizeof sock);
				buf += sizeof sock;
				memcpy(buf, &dbflags, sizeof dbflags);
				buf += sizeof dbflags;

				memset(&next_hop, 0, sizeof next_hop);
				next_hop.port  = puri.port_no;
				next_hop.proto = puri.proto;
				next_hop.name  = puri.host;

				/* write the next hop */
				memcpy(buf, &next_hop, sizeof next_hop);
				buf += sizeof next_hop;

				len -= needed;
			}

			if (DB_CAPABILITY(ul_dbf, DB_CAP_FETCH)) {
				if (ul_dbf.fetch_result(ul_dbh, &res, no_rows) < 0) {
					LM_ERR("fetching rows (1)\n");
					goto error;
				}
			} else
				break;

		} while (RES_ROW_N(res) > 0);

		ul_dbf.free_result(ul_dbh, res);
	}

	/* len < 0 is possible, if size of the buffer < sizeof c->c.len */
	if (len >= 0)
		memset(buf, 0, sizeof p_len);

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

	shortage -= len;

	return shortage > 0 ? shortage : 0;

error:
	if (res)
		ul_dbf.free_result(ul_dbh, res);
	return -1;
}