コード例 #1
0
ファイル: jsonrpc_io.c プロジェクト: adubovikov/kamailio
int result_cb(json_object *result, char *data, int error) 
{
	struct jsonrpc_pipe_cmd *cmd = (struct jsonrpc_pipe_cmd*)data;

	pv_spec_t *dst = cmd->cb_pv;
	pv_value_t val;

	const char* res = json_object_get_string(result);

	val.rs.s = (char*)res;
	val.rs.len = strlen(res);
	val.flags = PV_VAL_STR;

	dst->setf(0, &dst->pvp, (int)EQ_T, &val);

	int n;
	if (error) {
		n = route_get(&main_rt, cmd->err_route);
	} else {
		n = route_get(&main_rt, cmd->cb_route);
	}

	struct action *a = main_rt.rlist[n];
	tmb.t_continue(cmd->t_hash, cmd->t_label, a);	

	free_pipe_cmd(cmd);
	return 0;
}
コード例 #2
0
void evapi_init_environment(int dformat)
{
	memset(&_evapi_rts, 0, sizeof(evapi_evroutes_t));

	_evapi_rts.con_new = route_get(&event_rt, "evapi:connection-new");
	if (_evapi_rts.con_new < 0 || event_rt.rlist[_evapi_rts.con_new] == NULL)
		_evapi_rts.con_new = -1;
	_evapi_rts.con_closed = route_get(&event_rt, "evapi:connection-closed");
	if (_evapi_rts.con_closed < 0 || event_rt.rlist[_evapi_rts.con_closed] == NULL)
		_evapi_rts.con_closed = -1;
	_evapi_rts.msg_received = route_get(&event_rt, "evapi:message-received");
	if (_evapi_rts.msg_received < 0 || event_rt.rlist[_evapi_rts.msg_received] == NULL)
		_evapi_rts.msg_received = -1;
	_evapi_netstring_format = dformat;
}
コード例 #3
0
ファイル: kazoo.c プロジェクト: DileepNunna/kamailio
static int fire_init_event(int rank)
{
	struct sip_msg *fmsg;
	struct run_act_ctx ctx;
	int rtb, rt;

	LM_DBG("rank is (%d)\n", rank);
	if (rank!=PROC_INIT)
		return 0;

	rt = route_get(&event_rt, "kazoo:mod-init");
	if(rt>=0 && event_rt.rlist[rt]!=NULL) {
		LM_DBG("executing event_route[kazoo:mod-init] (%d)\n", rt);
		if(faked_msg_init()<0)
			return -1;
		fmsg = faked_msg_next();
		rtb = get_route_type();
		set_route_type(REQUEST_ROUTE);
		init_run_actions_ctx(&ctx);
		run_top_route(event_rt.rlist[rt], fmsg, &ctx);
		if(ctx.run_flags&DROP_R_F)
		{
			LM_ERR("exit due to 'drop' in event route\n");
			return -1;
		}
		set_route_type(rtb);
	}

	return 0;
}
コード例 #4
0
static int w_async_task_route(struct sip_msg* msg, char* rt, char* sec)
{
	cfg_action_t *act;
	str rn;
	int ri;

	if(msg==NULL)
		return -1;

	if(fixup_get_svalue(msg, (gparam_t*)rt, &rn)!=0)
	{
		LM_ERR("no async route block name\n");
		return -1;
	}

	ri = route_get(&main_rt, rn.s);
	if(ri<0)
	{
		LM_ERR("unable to find route block [%.*s]\n", rn.len, rn.s);
		return -1;
	}
	act = main_rt.rlist[ri];
	if(act==NULL)
	{
		LM_ERR("empty action lists in route block [%.*s]\n", rn.len, rn.s);
		return -1;
	}

	if(async_send_task(msg, act)<0)
		return -1;
	/* force exit in config */
	return 0;
}
コード例 #5
0
ファイル: shell-rime.c プロジェクト: EDAyele/ptunes
/*---------------------------------------------------------------------------*/
PROCESS_THREAD(shell_routes_process, ev, data)
{
  struct {
    uint16_t len;
    uint16_t dest;
    uint16_t nexthop;
    uint16_t hop_count;
    uint16_t seqno;
  } msg;
  int i;
  struct route_entry *r;
  
  PROCESS_BEGIN();

  memset(&msg, 0, sizeof(msg));
  msg.len = 4;
  for(i = 0; i < route_num(); ++i) {
    r = route_get(i);
    rimeaddr_copy((rimeaddr_t *)&msg.dest, &r->dest);
    rimeaddr_copy((rimeaddr_t *)&msg.nexthop, &r->nexthop);
    msg.hop_count = r->cost;
    msg.seqno = r->seqno;
    shell_output(&routes_command, &msg, sizeof(msg), "", 0);
  }
  
  PROCESS_END();
}
コード例 #6
0
ファイル: nsq_reader.c プロジェクト: GreenfieldTech/kamailio
int nsq_consumer_fire_event(char *routename)
{
	struct sip_msg *fmsg;
	struct run_act_ctx ctx;
	int rtb, rt;

	LM_DBG("searching event_route[%s]\n", routename);
	rt = route_get(&event_rt, routename);
	if (rt < 0 || event_rt.rlist[rt] == NULL) {
		LM_DBG("route %s does not exist\n", routename);
		return -2;
	}
	LM_DBG("executing event_route[%s] (%d)\n", routename, rt);
	if (faked_msg_init()<0) {
		return -2;
	}
	fmsg = faked_msg_next();
	rtb = get_route_type();
	set_route_type(REQUEST_ROUTE);
	init_run_actions_ctx(&ctx);
	run_top_route(event_rt.rlist[rt], fmsg, 0);
	set_route_type(rtb);

	return 0;
}
コード例 #7
0
ファイル: ht_api.c プロジェクト: carlosp/kamailio
void ht_expired_run_event_route(char *route)
{
	int rt, backup_rt;
	sip_msg_t *fmsg;

	if (route == NULL)
	{
		LM_ERR("bad route\n");
	}

	LM_DBG("ht_expired_run_event_route event_route[%s]\n", route);

	rt = route_get(&event_rt, route);

	if (rt < 0 || event_rt.rlist[rt] == NULL)
	{
		LM_DBG("route does not exist");
		return;
	}

	if (faked_msg_init() < 0)
	{
		LM_ERR("faked_msg_init() failed\n");
		return;
	}
	fmsg = faked_msg_next();
	fmsg->parsed_orig_ruri_ok = 0;

	backup_rt = get_route_type();

	set_route_type(EVENT_ROUTE);
	run_top_route(event_rt.rlist[rt], fmsg, 0);

	set_route_type(backup_rt);
}
コード例 #8
0
ファイル: uac_send.c プロジェクト: AlessioCasco/kamailio
void uac_req_run_event_route(sip_msg_t *msg, uac_send_info_t *tp, int rcode)
{
	char *evrtname = "uac:reply";
	int rt, backup_rt;
	struct run_act_ctx ctx;
	sip_msg_t *fmsg;

	rt = route_get(&event_rt, evrtname);
	if (rt < 0 || event_rt.rlist[rt] == NULL)
	{
		LM_DBG("event_route[uac:reply] does not exist\n");
		return;
	}

	uac_send_info_copy(tp, &_uac_req);
	_uac_req.evcode = rcode;
	if(msg==NULL)
	{
		_uac_req.evtype = 2;
		fmsg = faked_msg_get_next();
	} else {
		_uac_req.evtype = 1;
		fmsg = msg;
	}

	backup_rt = get_route_type();
	set_route_type(REQUEST_ROUTE);
	init_run_actions_ctx(&ctx);
	run_top_route(event_rt.rlist[rt], fmsg, 0);
	set_route_type(backup_rt);
}
コード例 #9
0
ファイル: tcpops.c プロジェクト: DileepNunna/kamailio
static void tcpops_tcp_closed_run_route(struct tcp_connection *con)
{
	int rt, backup_rt;
	struct run_act_ctx ctx;
	sip_msg_t *fmsg;
	LM_DBG("tcp_closed_run_route event_route[tcp:closed]\n");

	rt = route_get(&event_rt, "tcp:closed");
	if (rt < 0 || event_rt.rlist[rt] == NULL)
	{
		LM_DBG("route does not exist");
		return;
	}

	if (faked_msg_init() < 0)
	{
		LM_ERR("faked_msg_init() failed\n");
		return;
	}
	fmsg = faked_msg_next();
	fmsg->rcv = con->rcv;

	backup_rt = get_route_type();
	set_route_type(EVENT_ROUTE);
	init_run_actions_ctx(&ctx);
	run_top_route(event_rt.rlist[rt], fmsg, 0);
	set_route_type(backup_rt);
}
コード例 #10
0
ファイル: ws_conn.c プロジェクト: SipSeb/kamailio
static void wsconn_run_route(ws_connection_t *wsc)
{
	int rt, backup_rt;
	struct run_act_ctx ctx;
	sip_msg_t *fmsg;

	LM_DBG("wsconn_run_route event_route[websocket:closed]\n");

	rt = route_get(&event_rt, "websocket:closed");
	if (rt < 0 || event_rt.rlist[rt] == NULL)
	{
		LM_DBG("route does not exist");
		return;
	}

	if (faked_msg_init() < 0)
	{
		LM_ERR("faked_msg_init() failed\n");
		return;
	}
	
	fmsg = faked_msg_next();
	wsc->rcv.proto_reserved1 = wsc->id;
	fmsg->rcv = wsc->rcv;

	backup_rt = get_route_type();
	set_route_type(REQUEST_ROUTE);
	init_run_actions_ctx(&ctx);
	run_top_route(event_rt.rlist[rt], fmsg, 0);
	set_route_type(backup_rt);
}
コード例 #11
0
static int w_http_async_post(sip_msg_t *msg, char *query, char* post, char* rt)
{
	str sdata;
	str post_data;
	cfg_action_t *act;
	str rn;
	int ri;

	if(msg==NULL)
		return -1;

	if(fixup_get_svalue(msg, (gparam_t*)query, &sdata)!=0) {
		LM_ERR("unable to get data\n");
		return -1;
	}

	if(sdata.s==NULL || sdata.len == 0) {
		LM_ERR("invalid data parameter\n");
		return -1;
	}

	if(fixup_get_svalue(msg, (gparam_t*)post, &post_data)!=0) {
		LM_ERR("unable to get post data\n");
		return -1;
	}

	if(post_data.s==NULL || post_data.len == 0) {
		LM_ERR("invalid post data parameter\n");
		return -1;
	}

	if(fixup_get_svalue(msg, (gparam_t*)rt, &rn)!=0)
	{
		LM_ERR("no route block name\n");
		return -1;
	}

	ri = route_get(&main_rt, rn.s);
	if(ri<0)
	{
		LM_ERR("unable to find route block [%.*s]\n", rn.len, rn.s);
		return -1;
	}
	act = main_rt.rlist[ri];
	if(act==NULL)
	{
		LM_ERR("empty action lists in route block [%.*s]\n", rn.len, rn.s);
		return -1;
	}

	if(async_send_query(msg, &sdata, &post_data, act)<0)
		return -1;

	/* force exit in config */
	return 0;
}
コード例 #12
0
ファイル: corex_nio.c プロジェクト: 2pac/kamailio
/**
 * init nio function
 */
int nio_intercept_init(void)
{
	int route_no;
	pv_spec_t avp_spec;

	route_no=route_get(&event_rt, "network:msg");

	if (route_no==-1)
	{
		LM_ERR("failed to find event_route[network:msg]\n");
		return -1;
	}

	if (event_rt.rlist[route_no]==0)
	{
		LM_ERR("event_route[network:msg] is empty\n");
		return -1;
	}

	nio_route_no=route_no;
	
	if (nio_min_msg_len < 0)
	{
		LM_WARN("min_msg_len is less then zero, setting it to zero");
		nio_min_msg_len = 0;
	}

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

		if(pv_get_avp_name(0, &(avp_spec.pvp), &nio_msg_avp_name,
					&nio_msg_avp_type)!=0)
		{
			LM_ERR("[%.*s]- invalid AVP definition\n",
					nio_msg_avp_param.len, nio_msg_avp_param.s);
			return -1;
		}
	} else {
		LM_WARN("no AVP defined to store modified message\n");
	}

    /* register network hooks */
    sr_event_register_cb(SREV_NET_DATA_IN, nio_msg_received);
    sr_event_register_cb(SREV_NET_DATA_OUT, nio_msg_sent);
#ifdef USE_TCP
    tcp_set_clone_rcvbuf(1);
#endif
    return 0;
}
コード例 #13
0
ファイル: xhttp_mod.c プロジェクト: mehulsbhatt/voip-foip
static int mod_init(void)
{
	struct nonsip_hook nsh;
	int route_no;
	
	route_no=route_get(&event_rt, "xhttp:request");
	if (route_no==-1)
	{
		LM_ERR("failed to find event_route[xhttp:request]\n");
		return -1;
	}
	if (event_rt.rlist[route_no]==0)
	{
		LM_WARN("event_route[xhttp:request] is empty\n");
	}
	xhttp_route_no=route_no;
	
	/* bind the SL API */
	if (sl_load_api(&slb)!=0) {
		LM_ERR("cannot bind to SL API\n");
		return -1;
	}

	/* register non-sip hooks */
	memset(&nsh, 0, sizeof(nsh));
	nsh.name = "xhttp";
	nsh.destroy = 0;
	nsh.on_nonsip_req = xhttp_handler;
	if (register_nonsip_msg_hook(&nsh)<0)
	{
		LM_ERR("Failed to register non sip msg hooks\n");
		return -1;
	}

	if(xhttp_url_match!=NULL)
	{
		memset(&xhttp_url_match_regexp, 0, sizeof(regex_t));
		if (regcomp(&xhttp_url_match_regexp, xhttp_url_match, REG_EXTENDED)!=0) {
			LM_ERR("bad match re %s\n", xhttp_url_match);
			return E_BAD_RE;
		}
	}
	if(xhttp_url_skip!=NULL)
	{
		memset(&xhttp_url_skip_regexp, 0, sizeof(regex_t));
		if (regcomp(&xhttp_url_skip_regexp, xhttp_url_skip, REG_EXTENDED)!=0) {
			LM_ERR("bad skip re %s\n", xhttp_url_skip);
			return E_BAD_RE;
		}
	}
	return 0;
}
コード例 #14
0
ファイル: msrp_mod.c プロジェクト: halan/kamailio
static int msrp_frame_received(void *data)
{
	tcp_event_info_t *tev;
	static msrp_frame_t mf;
	sip_msg_t *fmsg;
	struct run_act_ctx ctx;
	int rtb, rt;


	tev = (tcp_event_info_t*)data;

	if(tev==NULL || tev->buf==NULL || tev->len<=0)
	{
		LM_DBG("invalid parameters\n");
		return -1;
	}

	memset(&mf, 0, sizeof(msrp_frame_t));
	mf.buf.s = tev->buf;
	mf.buf.len = tev->len;
	mf.tcpinfo = tev;
	if(msrp_parse_frame(&mf)<0)
	{
		LM_ERR("error parsing msrp frame\n");
		return -1;
	}
	msrp_reset_env();
	msrp_set_current_frame(&mf);
	rt = route_get(&event_rt, "msrp:frame-in");
	if(rt>=0 && event_rt.rlist[rt]!=NULL) {
		LM_DBG("executing event_route[msrp:frame-in] (%d)\n", rt);
		fmsg = msrp_fake_sipmsg(&mf);
		if(fmsg!=NULL)
			fmsg->rcv = *tev->rcv;
		rtb = get_route_type();
		set_route_type(REQUEST_ROUTE);
		init_run_actions_ctx(&ctx);
		run_top_route(event_rt.rlist[rt], fmsg, &ctx);
		if(ctx.run_flags&DROP_R_F)
		{
			LM_DBG("exit due to 'drop' in event route\n");
		}
		set_route_type(rtb);
		if(fmsg!=NULL)
			free_sip_msg(fmsg);
	}
	msrp_reset_env();
	msrp_destroy_frame(&mf);
	return 0;
}
コード例 #15
0
ファイル: ims_ocs_mod.c プロジェクト: GreenfieldTech/kamailio
/**
 * init module function
 */
static int mod_init(void) {
	LM_DBG("Loading...\n");
	event_route_ccr_orig = route_get(&event_rt, "ocs:ccr-orig");
	if (event_route_ccr_orig < 0) {
		LM_ERR("No ocs:ccr-orig event route found\n");
		goto error;
	}
	LM_DBG("Found Route ocs:ccr-orig: %i\n", event_route_ccr_orig);

	event_route_ccr_term = route_get(&event_rt, "ocs:ccr-term");
	if (event_route_ccr_term < 0) {
		LM_INFO("No ocs:ccr-term event route found\n");
	}
	LM_DBG("Found Route ocs:ccr-term: %i\n", event_route_ccr_term);


	callback_singleton = shm_malloc(sizeof (int));
	*callback_singleton = 0;

	cdp_avp = 0;
	/* load the CDP API */
	if (load_cdp_api(&cdpb) != 0) {
		LM_ERR("can't load CDP API\n");
        	goto error;
	    }

	cdp_avp = load_cdp_avp();
	if (!cdp_avp) {
		LM_ERR("can't load CDP_AVP API\n");
		goto error;
	}

	return 0;
error:
	LM_ERR("Failed to initialise ims_ocs module\n");
	return -1;
}
コード例 #16
0
ファイル: route-bsd.c プロジェクト: tixxdz/nmap
int
route_delete(route_t *r, const struct route_entry *entry)
{
	struct route_entry rtent;
	
	memcpy(&rtent, entry, sizeof(rtent));
	
	if (route_get(r, &rtent) < 0)
		return (-1);
	
	if (route_msg(r, RTM_DELETE, &rtent.route_dst, &rtent.route_gw) < 0)
		return (-1);
	
	return (0);
}
コード例 #17
0
ファイル: tmx_mod.c プロジェクト: AndreyRybkin/kamailio
static int w_t_continue(struct sip_msg* msg, char *idx, char *lbl, char *rtn)
{
	unsigned int tindex;
	unsigned int tlabel;
	str rtname;
	cfg_action_t *act;
	int ri;

	if(fixup_get_ivalue(msg, (gparam_p)idx, (int*)&tindex)<0)
	{
		LM_ERR("cannot get transaction index\n");
		return -1;
	}

	if(fixup_get_ivalue(msg, (gparam_p)lbl, (int*)&tlabel)<0)
	{
		LM_ERR("cannot get transaction label\n");
		return -1;
	}

	if(fixup_get_svalue(msg, (gparam_p)rtn, &rtname)<0)
	{
		LM_ERR("cannot get route block name\n");
		return -1;
	}

	ri = route_get(&main_rt, rtname.s);
	if(ri<0)
	{
		LM_ERR("unable to find route block [%.*s]\n", rtname.len, rtname.s);
		return -1;
	}
	act = main_rt.rlist[ri];
	if(act==NULL)
	{
		LM_ERR("empty action lists in route block [%.*s]\n",
				rtname.len, rtname.s);
		return -1;
	}

	if(_tmx_tmb.t_continue(tindex, tlabel, act)<0)
	{
		LM_ERR("resuming the processing of transaction [%u:%u] failed\n",
				tindex, tlabel);
		return -1;
	}
	return 1;
}
コード例 #18
0
ファイル: tm.c プロジェクト: Gaoithe/openimscore_ims
/* helper for fixup_on_* */
static int fixup_routes(char* r_type, struct route_list* rt, void** param)
{
	int i;
	
	i=route_get(rt, (char*)*param);
	if (i==-1){
		LOG(L_ERR, "ERROR: tm: fixup_routes: route_get failed\n");
		return E_UNSPEC;
	}
	if (rt->rlist[i]==0){
		LOG(L_WARN, "WARNING: %s(\"%s\"): empty/non existing route\n",
				r_type, (char*)*param);
	}
	*param=(void*)(long)i;
	return 0;
}
コード例 #19
0
ファイル: db2_ops.c プロジェクト: adubovikov/kamailio
static int dbops_foreach_fixup(void** param, int param_no) {
	if (param_no == 1) {
		return dbops_close_query_fixup(param, param_no);
	}
	else if (param_no == 2) {
		int n;
		n = route_get(&main_rt, (char*) *param);
		if (n == -1) {
			ERR(MODULE_NAME": db_foreach: bad route\n");
			return E_CFG;
		}
		pkg_free(*param);
		*param=(void*) (unsigned long) n;
	}
	return 0;
}
コード例 #20
0
ファイル: htable.c プロジェクト: aphistic/kamailio
static int child_init(int rank)
{
	struct sip_msg *fmsg;
	struct run_act_ctx ctx;
	int rtb, rt;
	int i;

	LM_DBG("rank is (%d)\n", rank);

	if(rank==PROC_MAIN) {
		if(ht_timer_procs>0) {
			for(i=0; i<ht_timer_procs; i++) {
				if(fork_sync_timer(PROC_TIMER, "HTable Timer", 1 /*socks flag*/,
						ht_timer, (void*)(long)i, ht_timer_interval)<0) {
					LM_ERR("failed to start timer routine as process\n");
					return -1; /* error */
				}
			}
		}
	}

	if (rank!=PROC_INIT)
		return 0;

	rt = route_get(&event_rt, "htable:mod-init");
	if(rt>=0 && event_rt.rlist[rt]!=NULL) {
		LM_DBG("executing event_route[htable:mod-init] (%d)\n", rt);
		if(faked_msg_init()<0)
			return -1;
		fmsg = faked_msg_next();
		rtb = get_route_type();
		set_route_type(REQUEST_ROUTE);
		init_run_actions_ctx(&ctx);
		run_top_route(event_rt.rlist[rt], fmsg, &ctx);
		if(ctx.run_flags&DROP_R_F)
		{
			LM_ERR("exit due to 'drop' in event route\n");
			return -1;
		}
		set_route_type(rtb);
	}

	return 0;
}
コード例 #21
0
int main(int argc, char* argv[]) {
    if (getuid() != 0) {
        printf("You need to be root\n");
        return 1;
    }

    route_t* router = route_open();

    struct route_entry entry;

    addr_pton("8.8.8.8", &entry.route_dst);

    route_get(router, &entry);

    printf("gateway is %s\n", addr_ntoa(&entry.route_gw));

    route_close(router);
    return 0;
}
コード例 #22
0
ファイル: networkd-route.c プロジェクト: Werkov/systemd
int route_add(
              Link *link,
              int family,
              const union in_addr_union *dst,
              unsigned char dst_prefixlen,
              unsigned char tos,
              uint32_t priority,
              uint32_t table,
              Route **ret) {

        Route *route;
        int r;

        r = route_get(link, family, dst, dst_prefixlen, tos, priority, table, &route);
        if (r == -ENOENT) {
                /* Route does not exist, create a new one */
                r = route_add_internal(link, &link->routes, family, dst, dst_prefixlen, tos, priority, table, &route);
                if (r < 0)
                        return r;
        } else if (r == 0) {
                /* Take over a foreign route */
                r = set_ensure_allocated(&link->routes, &route_hash_ops);
                if (r < 0)
                        return r;

                r = set_put(link->routes, route);
                if (r < 0)
                        return r;

                set_remove(link->routes_foreign, route);
        } else if (r == 1) {
                /* Route exists, do nothing */
                ;
        } else
                return r;

        if (ret)
                *ret = route;

        return 0;
}
コード例 #23
0
ファイル: async_mod.c プロジェクト: 4N7HR4X/kamailio
int ki_async_task_route(sip_msg_t* msg, str* rn)
{
	cfg_action_t *act;
	int ri;

	ri = route_get(&main_rt, rn->s);
	if(ri<0)
	{
		LM_ERR("unable to find route block [%.*s]\n", rn->len, rn->s);
		return -1;
	}
	act = main_rt.rlist[ri];
	if(act==NULL)
	{
		LM_ERR("empty action lists in route block [%.*s]\n", rn->len, rn->s);
		return -1;
	}

	if(async_send_task(msg, act)<0)
		return -1;
	/* force exit in config */
	return 0;
}
コード例 #24
0
ファイル: evrexec_mod.c プロジェクト: adubovikov/kamailio
int evrexec_param(modparam_t type, void *val)
{
	param_t* params_list = NULL;
	param_hooks_t phooks;
	param_t *pit=NULL;
	evrexec_task_t *it;
	evrexec_task_t tmp;
	sr_kemi_eng_t *keng = NULL;
	str s;

	if(val==NULL)
		return -1;
	s.s = (char*)val;
	s.len = strlen(s.s);
	if(s.s[s.len-1]==';')
		s.len--;
	if (parse_params(&s, CLASS_ANY, &phooks, &params_list)<0)
		return -1;
	memset(&tmp, 0, sizeof(evrexec_task_t));
	for (pit = params_list; pit; pit=pit->next) {
		if (pit->name.len==4
				&& strncasecmp(pit->name.s, "name", 4)==0) {
			tmp.ename = pit->body;
		} else if(pit->name.len==4
				&& strncasecmp(pit->name.s, "wait", 4)==0) {
			if(tmp.wait==0) {
				if (str2int(&pit->body, &tmp.wait) < 0) {
					LM_ERR("invalid wait: %.*s\n", pit->body.len, pit->body.s);
					return -1;
				}
			}
		} else if(pit->name.len==7
				&& strncasecmp(pit->name.s, "workers", 7)==0) {
			if(tmp.workers==0) {
				if (str2int(&pit->body, &tmp.workers) < 0) {
					LM_ERR("invalid workers: %.*s\n", pit->body.len, pit->body.s);
					return -1;
				}
			}
		} else {
			LM_ERR("invalid attribute: %.*s\n", pit->body.len, pit->body.s);
			return -1;
		}
	}
	if(tmp.ename.s==NULL || tmp.ename.len<=0) {
		LM_ERR("missing or invalid name attribute\n");
		free_params(params_list);
		return -1;
	}
	/* set '\0' at the end of route name */
	tmp.ename.s[tmp.ename.len] = '\0';
	keng = sr_kemi_eng_get();
	if(keng==NULL) {
		tmp.rtid = route_get(&event_rt, tmp.ename.s);
		if(tmp.rtid == -1) {
			LM_ERR("event route not found: %.*s\n", tmp.ename.len, tmp.ename.s);
			free_params(params_list);
			return -1;
		}
	} else {
		tmp.rtid = -1;
	}

	it = (evrexec_task_t*)pkg_malloc(sizeof(evrexec_task_t));
	if(it==0) {
		LM_ERR("no more pkg memory\n");
		free_params(params_list);
		return -1;
	}
	memcpy(it, &tmp, sizeof(evrexec_task_t));
	if(it->workers==0) it->workers=1;
	it->next = _evrexec_list;
	_evrexec_list = it;
	free_params(params_list);
	return 0;
}
コード例 #25
0
ファイル: msrp_mod.c プロジェクト: adubovikov/kamailio
static int msrp_frame_received(sr_event_param_t *evp)
{
	tcp_event_info_t *tev;
	static msrp_frame_t mf;
	sip_msg_t *fmsg;
	struct run_act_ctx ctx;
	int rtb, rt;
	sr_kemi_eng_t *keng = NULL;
	str evname = str_init("msrp:frame-in");

	tev = (tcp_event_info_t*)evp->data;

	if(tev==NULL || tev->buf==NULL || tev->len<=0)
	{
		LM_DBG("invalid parameters\n");
		return -1;
	}

	memset(&mf, 0, sizeof(msrp_frame_t));
	mf.buf.s = tev->buf;
	mf.buf.len = tev->len;
	mf.tcpinfo = tev;
	if(msrp_parse_frame(&mf)<0)
	{
		LM_ERR("error parsing msrp frame\n");
		return -1;
	}
	msrp_reset_env();
	msrp_set_current_frame(&mf);
	fmsg = msrp_fake_sipmsg(&mf);
	if(fmsg != NULL)
		fmsg->rcv = *tev->rcv;
	rtb = get_route_type();
	set_route_type(EVENT_ROUTE);
	init_run_actions_ctx(&ctx);
	if(msrp_event_callback.s == NULL || msrp_event_callback.len <= 0) {
		/* native cfg script execution */
		rt = route_get(&event_rt, evname.s);
		LM_DBG("executing event_route[msrp:frame-in] (%d)\n", rt);
		if(rt >= 0 && event_rt.rlist[rt] != NULL) {
			run_top_route(event_rt.rlist[rt], fmsg, &ctx);
		} else {
			LM_ERR("empty event route block for msrp handling\n");
		}
	} else {
		/* kemi script execution */
		keng = sr_kemi_eng_get();
		if(keng==NULL) {
			LM_ERR("event callback (%s) set, but no cfg engine\n",
					msrp_event_callback.s);
		} else {
			if(sr_kemi_ctx_route(keng, &ctx, fmsg, EVENT_ROUTE,
						&msrp_event_callback, &evname)<0) {
				LM_ERR("error running event route kemi callback\n");
			}
		}
	}
	if(ctx.run_flags & DROP_R_F) {
		LM_DBG("exit due to 'drop' in event route\n");
	}
	set_route_type(rtb);
	if(fmsg != NULL)
		free_sip_msg(fmsg);
	msrp_reset_env();
	msrp_destroy_frame(&mf);
	return 0;
}
コード例 #26
0
ファイル: registration.c プロジェクト: Jared-Prime/kamailio
/**
 * Perform User Authorization Request.
 * creates and send the user authorization query
 * @param msg - the SIP message
 * @returns true if OK, false if not
 */
int I_perform_user_authorization_request(struct sip_msg* msg, char* route, char* str1, char* str2) {
    str private_identity, public_identity, visited_network_id;
    int authorization_type = AVP_IMS_UAR_REGISTRATION;
    int expires = 3600;
    struct hdr_field *hdr;
    str realm;
    contact_t *c;
    int sos_reg = 0;
    contact_body_t *b = 0;
    str call_id;
    saved_uar_transaction_t* saved_t;
    tm_cell_t *t = 0;
    int intvalue_param;
    cfg_action_t* cfg_action;
    
    str route_name;

    if (fixup_get_ivalue(msg, (gparam_t*) str1, &intvalue_param) != 0) {
        LM_ERR("no int value param passed\n");
        return CSCF_RETURN_ERROR;
    }
    if (fixup_get_svalue(msg, (gparam_t*) route, &route_name) != 0) {
        LM_ERR("no async route block for assign_server_unreg\n");
        return -1;
    }
    
    LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s);
    int ri = route_get(&main_rt, route_name.s);
    if (ri < 0) {
        LM_ERR("unable to find route block [%.*s]\n", route_name.len, route_name.s);
        return -1;
    }
    cfg_action = main_rt.rlist[ri];
    if (cfg_action == NULL) {
        LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, route_name.s);
        return -1;
    }


    realm = cscf_get_realm_from_ruri(msg);

    //check if we received what we should, we do this even though it should be done in cfg file - double checking!
    if (msg->first_line.type != SIP_REQUEST) {
        LM_ERR("ERR:I_UAR: The message is not a request\n");
        return CSCF_RETURN_ERROR;
    }
    if (msg->first_line.u.request.method.len != 8 ||
            memcmp(msg->first_line.u.request.method.s, "REGISTER", 8) != 0) {
        LM_ERR("ERR:I_UAR: The method is not a REGISTER\n");
        return CSCF_RETURN_ERROR;
    }

    private_identity = cscf_get_private_identity(msg, realm);
    if (!private_identity.len) {
        LM_ERR("ERR:I_UAR: Private Identity not found, responding with 400\n");
        cscf_reply_transactional(msg, 400, MSG_400_NO_PRIVATE);
        return CSCF_RETURN_BREAK;
    }

    public_identity = cscf_get_public_identity(msg);
    if (!public_identity.len) {
        LM_ERR("ERR:I_UAR: Public Identity not found, responding with 400\n");
        cscf_reply_transactional(msg, 400, MSG_400_NO_PUBLIC);
        return CSCF_RETURN_BREAK;

    }

    b = cscf_parse_contacts(msg);

    if (!b || (!b->contacts && !b->star)) {
        LM_DBG("DBG:I_UAR: No contacts found\n");
        return CSCF_RETURN_ERROR;
    }

    for (c = b->contacts; c; c = c->next) {

        sos_reg = cscf_get_sos_uri_param(c->uri);
        if (sos_reg == -1) {
            //error case
            LM_ERR("ERR:I_UAR: MSG_400_MALFORMED_CONTACT, responding with 400\n");
            cscf_reply_transactional(msg, 400, MSG_400_MALFORMED_CONTACT);
            return CSCF_RETURN_BREAK;
        } else if (sos_reg == -2) {
            LM_ERR("ERR:I_UAR: MSG_500_SERVER_ERROR_OUT_OF_MEMORY, responding with 500\n");
            cscf_reply_transactional(msg, 500, MSG_500_SERVER_ERROR_OUT_OF_MEMORY);
            return CSCF_RETURN_BREAK;
        }
    }

    visited_network_id = cscf_get_visited_network_id(msg, &hdr);
    if (!visited_network_id.len) {
        LM_ERR("ERR:I_UAR: Visited Network Identity not found, responding with 400\n");
        cscf_reply_transactional(msg, 400, MSG_400_NO_VISITED);
        return CSCF_RETURN_BREAK;
    }

    if (atoi(str1)) authorization_type = AVP_IMS_UAR_REGISTRATION_AND_CAPABILITIES;
    else {
        expires = cscf_get_max_expires(msg, 0);
        if (expires == 0) authorization_type = AVP_IMS_UAR_DE_REGISTRATION;
    }

    LM_DBG("SENDING UAR: PI: [%.*s], PU: [%.*s], VNID: [%.*s]\n", private_identity.len, private_identity.s,
            public_identity.len, public_identity.s,
            visited_network_id.len, visited_network_id.s);

    //before we send lets suspend the transaction
    t = tmb.t_gett();
    if (t == NULL || t == T_UNDEFINED) {
        if (tmb.t_newtran(msg) < 0) {
            LM_ERR("cannot create the transaction for UAR async\n");
            cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR);
            return CSCF_RETURN_BREAK;
        }
        t = tmb.t_gett();
        if (t == NULL || t == T_UNDEFINED) {
            LM_ERR("cannot lookup the transaction\n");
            cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR);
            return CSCF_RETURN_BREAK;
        }
    }

    saved_t = shm_malloc(sizeof (saved_uar_transaction_t));
    if (!saved_t) {
        LM_ERR("no more memory trying to save transaction state\n");
        return CSCF_RETURN_ERROR;

    }
    memset(saved_t, 0, sizeof (saved_uar_transaction_t));
    saved_t->act = cfg_action;

    call_id = cscf_get_call_id(msg, 0);
    saved_t->callid.s = (char*) shm_malloc(call_id.len + 1);
    if (!saved_t->callid.s) {
    	LM_ERR("no more memory trying to save transaction state : callid\n");
    	shm_free(saved_t);
    	return CSCF_RETURN_ERROR;
    }
    memset(saved_t->callid.s, 0, call_id.len + 1);
    memcpy(saved_t->callid.s, call_id.s, call_id.len);
    saved_t->callid.len = call_id.len;

    LM_DBG("Setting default AVP return code used for async callbacks to default as ERROR \n");
    create_uaa_return_code(CSCF_RETURN_ERROR);
    
    LM_DBG("Suspending SIP TM transaction\n");
    if (tmb.t_suspend(msg, &saved_t->tindex, &saved_t->tlabel) < 0) {
        LM_ERR("failed to suspend the TM processing\n");
        free_saved_uar_transaction_data(saved_t);

        cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR);
        return CSCF_RETURN_BREAK;
    }

    if (cxdx_send_uar(msg, private_identity, public_identity, visited_network_id, authorization_type, sos_reg, saved_t) != 0) {
        LM_ERR("ERR:I_UAR: Error sending UAR or UAR time-out\n");
        tmb.t_cancel_suspend(saved_t->tindex, saved_t->tlabel);
        free_saved_uar_transaction_data(saved_t);
        cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR);
        return CSCF_RETURN_BREAK;

    }
    //we use async replies therefore we send break and not true when successful
    return CSCF_RETURN_BREAK;
}
コード例 #27
0
ファイル: timer.c プロジェクト: BackupTheBerlios/ser
/* timer_id=route_no,interval_ms[,"slow"|"fast"[,"enable"]] */
static int declare_timer(modparam_t type, char* param) {
	int n;
	unsigned int route_no, interval, enabled, flags;
	struct timer_action *pa;
	char *p, *save_p, c, *timer_name;
	str s;

	timer_name = 0;
	save_p = p = param;
	eat_alphanum(p);
	if (*p != '=' || p == save_p) goto err;
	*p = '\0';
	timer_name = save_p;
	p++;
	if (find_action_by_name(pkg_timer_actions, timer_name, -1) != NULL) {
		ERR(MODULE_NAME": declare_timer: timer '%s' already exists\n", timer_name);
		return E_CFG;
	}

	save_p = p;
	if (!get_next_part(&p, &s, ',')) goto err;

	c = s.s[s.len];
	s.s[s.len] = '\0';
	n = route_get(&main_rt, s.s);
	s.s[s.len] = c;
	if (n == -1) goto err;
	route_no = n;

	save_p = p;
	if (!get_next_part(&p, &s, ',')) goto err;
	if (str2int(&s, &interval) < 0) goto err;

	save_p = p;
	flags = 0;
	if (get_next_part(&p, &s, ',')) {
		if (s.len == 4 && strncasecmp(s.s, "FAST", 4)==0)
			flags = F_TIMER_FAST;
		else if (s.len == 4 && strncasecmp(s.s, "SLOW", 4)==0)
			;
		else goto err;
	}

	save_p = p;
	enabled = 0;
	if (get_next_part(&p, &s, ',')) {
		if (s.len == 6 && strncasecmp(s.s, "ENABLE", 6)==0)
			enabled = 1;
		else goto err;
	}

	
	pa = pkg_malloc(sizeof(*pa));   /* cannot use shmmem here! */
	if (!pa) {
		ERR(MODULE_NAME": cannot allocate timer data\n");
		return E_OUT_OF_MEM;
	}
	memset(pa, 0, sizeof(*pa));
	pa->timer_name = timer_name;
	pa->route_no = route_no;
	pa->interval = interval;
	pa->enable_on_start = enabled;
	pa->flags = flags;
	pa->next = pkg_timer_actions;
	pkg_timer_actions = pa;

	return 0;
err:
	ERR(MODULE_NAME": declare_timer: timer_name: '%s', error near '%s'\n", timer_name, save_p);
	return E_CFG;
}
コード例 #28
0
ファイル: location.c プロジェクト: AlessioCasco/kamailio
/**
 * Perform an LIR
 * @param msg - sip message
 * @returns 1 on success or 0 on failure
 */
int I_perform_location_information_request(struct sip_msg* msg, char* route, char* str1, char* str2) {
    str public_identity = {0, 0};
    int orig = 0;
    
    tm_cell_t *t = 0;
    saved_lir_transaction_t* saved_t;
    
    str route_name;
    
     cfg_action_t* cfg_action;

     if (fixup_get_svalue(msg, (gparam_t*) route, &route_name) != 0) {
        LM_ERR("no async route block for assign_server_unreg\n");
        return -1;
    }
    
    LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s);
    int ri = route_get(&main_rt, route_name.s);
    if (ri < 0) {
        LM_ERR("unable to find route block [%.*s]\n", route_name.len, route_name.s);
        return -1;
    }
    cfg_action = main_rt.rlist[ri];
    if (cfg_action == NULL) {
        LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, route_name.s);
        return -1;
    }
    
    LM_DBG("DBG:I_LIR: Starting ...\n");
    /* check if we received what we should */
    if (msg->first_line.type != SIP_REQUEST) {
        LM_ERR("ERR:I_LIR: The message is not a request\n");
        return CSCF_RETURN_BREAK;
    }

    /* check orig uri parameter in topmost Route */
    if (cscf_has_originating(msg, str1, str2) == CSCF_RETURN_TRUE) {
        orig = 1;
        LM_DBG("DBG:I_LIR: orig\n");
    }

    /* extract data from message */
    if (orig) {
        public_identity = cscf_get_asserted_identity(msg, 0);
    } else {
        public_identity = cscf_get_public_identity_from_requri(msg);
    }
    if (!public_identity.len) {
        LM_ERR("ERR:I_LIR: Public Identity not found, responding with 400\n");
        if (orig)
            cscf_reply_transactional(msg, 400, MSG_400_NO_PUBLIC_FROM);
        else
            cscf_reply_transactional(msg, 400, MSG_400_NO_PUBLIC);
        return CSCF_RETURN_BREAK;
    }
    
    
    //before we send lets suspend the transaction
    t = tmb.t_gett();
    if (t == NULL || t == T_UNDEFINED) {
        if (tmb.t_newtran(msg) < 0) {
            LM_ERR("cannot create the transaction for UAR async\n");
            cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR);
            return CSCF_RETURN_BREAK;
        }
        t = tmb.t_gett();
        if (t == NULL || t == T_UNDEFINED) {
            LM_ERR("cannot lookup the transaction\n");
            cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR);
            return CSCF_RETURN_BREAK;
        }
    }

    saved_t = shm_malloc(sizeof (saved_lir_transaction_t));
    if (!saved_t) {
        LM_ERR("no more memory trying to save transaction state\n");
        return CSCF_RETURN_ERROR;

    }
    memset(saved_t, 0, sizeof (saved_lir_transaction_t));
    saved_t->act = cfg_action;
    
    saved_t->orig = orig;
    
    LM_DBG("Setting default AVP return code used for async callbacks to default as ERROR \n");
    create_lia_return_code(CSCF_RETURN_ERROR);
    
    LM_DBG("Suspending SIP TM transaction\n");
    if (tmb.t_suspend(msg, &saved_t->tindex, &saved_t->tlabel) < 0) {
        LM_ERR("failed to suspend the TM processing\n");
        free_saved_lir_transaction_data(saved_t);

        cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR);
        return CSCF_RETURN_BREAK;
    }
    
    if (cxdx_send_lir(msg, public_identity, saved_t) != 0) {
        LM_ERR("ERR:I_LIR: Error sending LIR or LIR time-out\n");
        tmb.t_cancel_suspend(saved_t->tindex, saved_t->tlabel);
        free_saved_lir_transaction_data(saved_t);
        cscf_reply_transactional(msg, 480, MSG_480_DIAMETER_ERROR);
        
        if (public_identity.s && !orig)
        shm_free(public_identity.s); // shm_malloc in cscf_get_public_identity_from_requri		
        return CSCF_RETURN_BREAK;

    }
    if (public_identity.s && !orig)
        shm_free(public_identity.s); // shm_malloc in cscf_get_public_identity_from_requri		
    
    //we use async replies therefore we send break and not true when successful
    return CSCF_RETURN_BREAK;
}
コード例 #29
0
ファイル: ht_api.c プロジェクト: 4N7HR4X/kamailio
int ht_init_tables(void)
{
	ht_t *ht;
	int i;
	char route_name[64];

	ht = _ht_root;

	while(ht)
	{
		LM_DBG("initializing htable [%.*s] with nr. of slots: %d\n",
				ht->name.len, ht->name.s, ht->htsize);
		if(ht->name.len + sizeof("htable:expired:") < 64)
		{
			strcpy(route_name, "htable:expired:");
			strncat(route_name, ht->name.s, ht->name.len);
			ht->evrt_expired = route_get(&event_rt, route_name);

			if (ht->evrt_expired < 0
					|| event_rt.rlist[ht->evrt_expired] == NULL)
			{
				ht->evrt_expired = -1;
				LM_DBG("event route for expired items in [%.*s] does not exist\n",
						ht->name.len, ht->name.s);
			} else {
				LM_DBG("event route for expired items in [%.*s] exists\n",
						ht->name.len, ht->name.s);
			}
		} else {
			LM_WARN("event route name for expired items in htable [%.*s]"
					" is too long\n", ht->name.len, ht->name.s);
		}
		ht->entries = (ht_entry_t*)shm_malloc(ht->htsize*sizeof(ht_entry_t));
		if(ht->entries==NULL)
		{
			LM_ERR("no more shm for [%.*s]\n", ht->name.len, ht->name.s);
			shm_free(ht);
			return -1;
		}
		memset(ht->entries, 0, ht->htsize*sizeof(ht_entry_t));

		for(i=0; i<ht->htsize; i++)
		{
			if(lock_init(&ht->entries[i].lock)==0)
			{
				LM_ERR("cannot initialize lock[%d] in [%.*s]\n", i,
						ht->name.len, ht->name.s);
				i--;
				while(i>=0)
				{
					lock_destroy(&ht->entries[i].lock);
					i--;
				}
				shm_free(ht->entries);
				shm_free(ht);
				return -1;

			}
		}
		ht = ht->next;
	}

	return 0;
}
コード例 #30
0
ファイル: networkd-route.c プロジェクト: alex/systemd
int route_configure(
                Route *route,
                Link *link,
                sd_netlink_message_handler_t callback) {

        _cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
        _cleanup_(sd_event_source_unrefp) sd_event_source *expire = NULL;
        usec_t lifetime;
        int r;

        assert(link);
        assert(link->manager);
        assert(link->manager->rtnl);
        assert(link->ifindex > 0);
        assert(route->family == AF_INET || route->family == AF_INET6);

        if (route_get(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, NULL) <= 0 &&
            set_size(link->routes) >= ROUTES_PER_LINK_MAX)
                return -E2BIG;

        r = sd_rtnl_message_new_route(link->manager->rtnl, &req,
                                      RTM_NEWROUTE, route->family,
                                      route->protocol);
        if (r < 0)
                return log_error_errno(r, "Could not create RTM_NEWROUTE message: %m");

        if (!in_addr_is_null(route->family, &route->gw)) {
                if (route->family == AF_INET)
                        r = sd_netlink_message_append_in_addr(req, RTA_GATEWAY, &route->gw.in);
                else if (route->family == AF_INET6)
                        r = sd_netlink_message_append_in6_addr(req, RTA_GATEWAY, &route->gw.in6);
                if (r < 0)
                        return log_error_errno(r, "Could not append RTA_GATEWAY attribute: %m");

                r = sd_rtnl_message_route_set_family(req, route->family);
                if (r < 0)
                        return log_error_errno(r, "Could not set route family: %m");
        }

        if (route->dst_prefixlen) {
                if (route->family == AF_INET)
                        r = sd_netlink_message_append_in_addr(req, RTA_DST, &route->dst.in);
                else if (route->family == AF_INET6)
                        r = sd_netlink_message_append_in6_addr(req, RTA_DST, &route->dst.in6);
                if (r < 0)
                        return log_error_errno(r, "Could not append RTA_DST attribute: %m");

                r = sd_rtnl_message_route_set_dst_prefixlen(req, route->dst_prefixlen);
                if (r < 0)
                        return log_error_errno(r, "Could not set destination prefix length: %m");
        }

        if (route->src_prefixlen) {
                if (route->family == AF_INET)
                        r = sd_netlink_message_append_in_addr(req, RTA_SRC, &route->src.in);
                else if (route->family == AF_INET6)
                        r = sd_netlink_message_append_in6_addr(req, RTA_SRC, &route->src.in6);
                if (r < 0)
                        return log_error_errno(r, "Could not append RTA_SRC attribute: %m");

                r = sd_rtnl_message_route_set_src_prefixlen(req, route->src_prefixlen);
                if (r < 0)
                        return log_error_errno(r, "Could not set source prefix length: %m");
        }

        if (!in_addr_is_null(route->family, &route->prefsrc)) {
                if (route->family == AF_INET)
                        r = sd_netlink_message_append_in_addr(req, RTA_PREFSRC, &route->prefsrc.in);
                else if (route->family == AF_INET6)
                        r = sd_netlink_message_append_in6_addr(req, RTA_PREFSRC, &route->prefsrc.in6);
                if (r < 0)
                        return log_error_errno(r, "Could not append RTA_PREFSRC attribute: %m");
        }

        r = sd_rtnl_message_route_set_scope(req, route->scope);
        if (r < 0)
                return log_error_errno(r, "Could not set scope: %m");

        r = sd_rtnl_message_route_set_flags(req, route->flags);
        if (r < 0)
                return log_error_errno(r, "Could not set flags: %m");

        if (route->table != RT_TABLE_DEFAULT) {

                if (route->table < 256) {
                        r = sd_rtnl_message_route_set_table(req, route->table);
                        if (r < 0)
                                return log_error_errno(r, "Could not set route table: %m");
                } else {

                        r = sd_rtnl_message_route_set_table(req, RT_TABLE_UNSPEC);
                        if (r < 0)
                                return log_error_errno(r, "Could not set route table: %m");

                        /* Table attribute to allow more than 256. */
                        r = sd_netlink_message_append_data(req, RTA_TABLE, &route->table, sizeof(route->table));
                        if (r < 0)
                                return log_error_errno(r, "Could not append RTA_TABLE attribute: %m");
                }
        }

        r = sd_netlink_message_append_u32(req, RTA_PRIORITY, route->priority);
        if (r < 0)
                return log_error_errno(r, "Could not append RTA_PRIORITY attribute: %m");

        r = sd_netlink_message_append_u8(req, RTA_PREF, route->pref);
        if (r < 0)
                return log_error_errno(r, "Could not append RTA_PREF attribute: %m");

        r = sd_netlink_message_append_u32(req, RTA_OIF, link->ifindex);
        if (r < 0)
                return log_error_errno(r, "Could not append RTA_OIF attribute: %m");

        r = sd_netlink_call_async(link->manager->rtnl, req, callback, link, 0, NULL);
        if (r < 0)
                return log_error_errno(r, "Could not send rtnetlink message: %m");

        link_ref(link);

        lifetime = route->lifetime;

        r = route_add(link, route->family, &route->dst, route->dst_prefixlen, route->tos, route->priority, route->table, &route);
        if (r < 0)
                return log_error_errno(r, "Could not add route: %m");

        /* TODO: drop expiration handling once it can be pushed into the kernel */
        route->lifetime = lifetime;

        if (route->lifetime != USEC_INFINITY) {
                r = sd_event_add_time(link->manager->event, &expire, clock_boottime_or_monotonic(),
                                      route->lifetime, 0, route_expire_handler, route);
                if (r < 0)
                        return log_error_errno(r, "Could not arm expiration timer: %m");
        }

        sd_event_source_unref(route->expire);
        route->expire = expire;
        expire = NULL;

        return 0;
}