Example #1
0
/*---------------------------------------------------------------------------*/
static void
recv_data(struct unicast_conn *c, const linkaddr_t *from)
{
  struct route_entry *e;
  linkaddr_t source;
    
  uip_len = packetbuf_copyto(&uip_buf[UIP_LLH_LEN]);

  source.u8[0] = BUF->srcipaddr.u8[2];
  source.u8[1] = BUF->srcipaddr.u8[3];

  e = route_lookup(&source);
  if(e == NULL) {
    route_add(&source, from, 10, 0);
  } else {
    route_refresh(e);
  }

  /* If we received data via a gateway, we refresh the gateway route.
   * Note: we refresh OUR gateway route, although we are not sure it forwarded the data. */
  if(!uip_ipaddr_maskcmp(&BUF->srcipaddr, &netaddr, &netmask)) {
    e = route_lookup(&gateway);
    if(e != NULL) {
      route_refresh(e);
    }
  }


  PRINTF("uip-over-mesh: %d.%d: recv_data with len %d\n",
	 linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1], uip_len);
  tcpip_input();
}
Example #2
0
/*---------------------------------------------------------------------------*/
static void
send_rrep(struct route_discovery_conn *c, const linkaddr_t *dest)
{
  struct rrep_hdr *rrepmsg;
  struct route_entry *rt;
  linkaddr_t saved_dest;
  
  linkaddr_copy(&saved_dest, dest);

  packetbuf_clear();
  dest = &saved_dest;
  rrepmsg = packetbuf_dataptr();
  packetbuf_set_datalen(sizeof(struct rrep_hdr));
  rrepmsg->hops = 0;
  linkaddr_copy(&rrepmsg->dest, dest);
  linkaddr_copy(&rrepmsg->originator, &linkaddr_node_addr);
  rt = route_lookup(dest);
  if(rt != NULL) {
    PRINTF("%d.%d: send_rrep to %d.%d via %d.%d\n",
	   linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1],
	   dest->u8[0],dest->u8[1],
	   rt->nexthop.u8[0],rt->nexthop.u8[1]);
    unicast_send(&c->rrepconn, &rt->nexthop);
  } else {
    PRINTF("%d.%d: no route for rrep to %d.%d\n",
	   linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1],
	   dest->u8[0],dest->u8[1]);
  }
}
Example #3
0
static uip_ipaddr_t *
lookup(uip_ipaddr_t *destipaddr, uip_ipaddr_t *nexthop)
{
  static rimeaddr_t rimeaddr;
  struct route_entry *route;
  int i;

  for(i = 1; i < sizeof(rimeaddr); i++) {
    rimeaddr.u8[i] = destipaddr->u8[sizeof(*destipaddr) - sizeof(rimeaddr) + i];
  }
  rimeaddr.u8[0] = 0;

  PRINTF("rimeroute: looking up ");
  PRINT6ADDR(destipaddr);
  PRINTF(" with Rime address ");
  PRINTRIMEADDR((&rimeaddr));
  PRINTF("\n");

  route = route_lookup(&rimeaddr);
  if(route == NULL) {
    process_post(&rimeroute_process, rimeroute_event, &rimeaddr);
    return NULL;
  }

  uip_ip6addr(nexthop, 0xfe80, 0, 0, 0, 0, 0, 0, 0);
  uip_netif_addr_autoconf_set(nexthop, (uip_lladdr_t *)&route->nexthop);
  PRINTF("rimeroute: ");
  PRINT6ADDR(destipaddr);
  PRINTF(" can be reached via ");
  PRINT6ADDR(nexthop);
  PRINTF("\n");

  return nexthop;
}
Example #4
0
/*---------------------------------------------------------------------------*/
static void
found_route(struct route_discovery_conn *rdc, const rimeaddr_t *dest)
{
  struct route_entry *rt;
  struct mesh_conn *c = (struct mesh_conn *)
    ((char *)rdc - offsetof(struct mesh_conn, route_discovery_conn));

  PRINTF("found_route\n");

  if(c->queued_data != NULL &&
     rimeaddr_cmp(dest, &c->queued_data_dest)) {
    queuebuf_to_packetbuf(c->queued_data);
    queuebuf_free(c->queued_data);
    c->queued_data = NULL;

    rt = route_lookup(dest);
    if(rt != NULL) {
      multihop_resend(&c->multihop, &rt->R_next_addr);
      if(c->cb->sent != NULL) {
        c->cb->sent(c);
      }
    } else {
      if(c->cb->timedout != NULL) {
        c->cb->timedout(c);
      }
    }
  }
}
Example #5
0
rimeaddr_t *
c_multihop_forward(struct pipe *p, struct stackmodule_i *module) {
	printf("multihop forward \n");
	struct route_entry *rt, *previous_rt;
	rimeaddr_t *tmpaddr = get_node_addr(module->stack_id, 0, 3);
	rt = route_lookup(tmpaddr);
	if (rt == NULL) {
		return NULL;
	} else {
		/*if(clock_time()*1000/CLOCK_SECOND < 50100 && rimeaddr_node_addr.u8[0] == 1) {
			previous_rt->nexthop.u8[0] = rt->nexthop.u8[0];
			previous_rt->cost = rt->cost;
		}
		if(clock_time()*1000/CLOCK_SECOND > 50100 && rimeaddr_node_addr.u8[0] == 1 && rt->nexthop.u8[0] == previous_rt->nexthop.u8[0] && previous_rt->cost == rt->cost) {
			route_remove(rt);
			rt = route_lookup(tmpaddr);
		}*/
		
		/*if(clock_time()*1000/CLOCK_SECOND < 50100) {
			previous_rt->nexthop.u8[0] = rt->nexthop.u8[0];
			previous_rt->cost = rt->cost;
		}
		if(clock_time()*1000/CLOCK_SECOND > 50100 && rt->nexthop.u8[0] == previous_rt->nexthop.u8[0] && previous_rt->cost == rt->cost) {
			route_remove(rt);
			return NULL;
		}*/		
		route_refresh(rt);
	}
	PRINTF("~c_multihop_forward \n");
	return &rt->nexthop;
}
Example #6
0
/*---------------------------------------------------------------------------*/
static rimeaddr_t *
data_packet_forward(struct multihop_conn *multihop,
		    const rimeaddr_t *originator,
		    const rimeaddr_t *dest,
		    const rimeaddr_t *prevhop, uint8_t hops)
{
  struct route_entry *rt;
  struct mesh_conn *c = (struct mesh_conn *)
    ((char *)multihop - offsetof(struct mesh_conn, multihop));

  rt = route_lookup(dest);
  if(rt == NULL) {
    if(c->queued_data != NULL) {
      queuebuf_free(c->queued_data);
    }

    PRINTF("data_packet_forward: queueing data, sending rreq\n");
    c->queued_data = queuebuf_new_from_packetbuf();
    rimeaddr_copy(&c->queued_data_dest, dest);
    route_discovery_discover(&c->route_discovery_conn, dest, PACKET_TIMEOUT);

    return NULL;
  } else {
    route_refresh(rt);
  }
  
  return &rt->R_next_addr;
}
Example #7
0
static int add_route(struct tree_item *root, const char *prefix,
		const char *route)
{
	int ix, err;

	/* We cache the route index here so we can avoid route_lookup()
	 * in the prefix_route() routing function.
	 */
	ix = route_lookup(&main_rt, (char *)route);
	if (ix < 0) {
		LM_CRIT("route name '%s' is not defined\n", route);
		return -1;
	}

	if (ix >= main_rt.entries) {
		LM_CRIT("route %d > n_entries (%d)\n", ix, main_rt.entries);
		return -1;
	}

	err = tree_item_add(root, prefix, route, ix);
	if (0 != err) {
		LM_CRIT("tree_item_add() failed (%d)\n", err);
		return err;
	}

	return 0;
}
Example #8
0
int pv_set_dlg_ctx(struct sip_msg* msg, pv_param_t *param,
		int op, pv_value_t *val)
{
	int n;
	char *rtp;

	if(param==NULL)
		return -1;

	if(val==NULL)
		n = 0;
	else
		n = val->ri;

	switch(param->pvn.u.isname.name.n)
	{
		case 1:
			_dlg_ctx.flags = n;
		break;
		case 2:
			_dlg_ctx.timeout = n;
		break;
		case 3:
			_dlg_ctx.to_bye = n;
		break;
		case 4:
			if(val->flags&PV_VAL_STR) {
				if(val->rs.s[val->rs.len]=='\0'
						&& val->rs.len<DLG_TOROUTE_SIZE) {
					_dlg_ctx.to_route = route_lookup(&main_rt, val->rs.s);
					strcpy(_dlg_ctx.to_route_name, val->rs.s);
				} else _dlg_ctx.to_route = 0;
			} else {
				if(n!=0) {
					rtp = int2str(n, NULL);
					_dlg_ctx.to_route = route_lookup(&main_rt, rtp);
					strcpy(_dlg_ctx.to_route_name, rtp);
				} else _dlg_ctx.to_route = 0;
			}
			if(_dlg_ctx.to_route <0) _dlg_ctx.to_route = 0;
		break;
		default:
			_dlg_ctx.on = n;
		break;
	}
	return 0;
}
Example #9
0
void rpc_evr_run(rpc_t *rpc, void *c)
{
	str evr_name = STR_NULL;
	str evr_data = STR_NULL;
	int ret = 0;
	int evr_id = -1;
	sr_kemi_eng_t *keng = NULL;
	sip_msg_t *fmsg = NULL;
	int rtbk = 0;
	char evr_buf[2];

	ret = rpc->scan(c, "s*s", &evr_name.s, &evr_data.s);
	if(ret<1) {
		LM_ERR("failed getting the parameters");
		rpc->fault(c, 500, "Invalid parameters");
		return;
	}
	evr_name.len = strlen(evr_name.s);
	if(ret<2) {
		evr_buf[0] = '\0';
		evr_data.s = evr_buf;
		evr_data.len = 0;
	} else {
		evr_data.len = strlen(evr_data.s);
	}

	pv_evr_data = &evr_data;
	keng = sr_kemi_eng_get();
	if(keng==NULL) {
		evr_id = route_lookup(&event_rt, evr_name.s);
		if(evr_id == -1) {
			pv_evr_data = NULL;
			LM_ERR("event route not found: %.*s\n", evr_name.len, evr_name.s);
			rpc->fault(c, 500, "Event route not found");
			return;
		}
	} else {
		evr_id = -1;
	}

	fmsg = faked_msg_next();
	rtbk = get_route_type();
	set_route_type(LOCAL_ROUTE);

	if(evr_id>=0) {
		if(event_rt.rlist[evr_id]!=NULL) {
			run_top_route(event_rt.rlist[evr_id], fmsg, 0);
		} else {
			LM_WARN("empty event route block [%.*s]\n",
					evr_name.len, evr_name.s);
		}
	} else {
		if(sr_kemi_route(keng, fmsg, EVENT_ROUTE, &evr_name, &evr_data)<0) {
			LM_ERR("error running event route kemi callback\n");
		}
	}
	set_route_type(rtbk);
	pv_evr_data = NULL;
}
Example #10
0
/*!
 * lookup tls event routes
 */
void tls_lookup_event_routes(void)
{
	_tls_evrt_connection_out=route_lookup(&event_rt, "tls:connection-out");
	if (_tls_evrt_connection_out>=0 && event_rt.rlist[_tls_evrt_connection_out]==0)
		_tls_evrt_connection_out=-1; /* disable */
	if(_tls_evrt_connection_out!=-1)
		forward_set_send_info(1);
}
Example #11
0
/*! Check if a route block exists - only request routes
 */
static int w_check_route_exists(struct sip_msg *msg, char *route)
{
	if (route_lookup(&main_rt, route)<0) {
		/* not found */
		return -1;
	}
	return 1;
}
Example #12
0
/*---------------------------------------------------------------------------*/
static void
rrep_packet_received(struct unicast_conn *uc, const rimeaddr_t *from)
{
    struct rrep_hdr *msg = packetbuf_dataptr();
    struct route_entry *rt;
    rimeaddr_t dest;
    struct route_discovery_conn *c = (struct route_discovery_conn *)
                                     ((char *)uc - offsetof(struct route_discovery_conn, rrepconn));

    PRINTF("%d.%d: rrep_packet_received from %d.%d towards %d.%d len %d\n",
           rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1],
           from->u8[0],from->u8[1],
           msg->dest.u8[0],msg->dest.u8[1],
           packetbuf_datalen());

    PRINTF("from %d.%d hops %d rssi %d lqi %d\n",
           from->u8[0], from->u8[1],
           msg->hops,
           packetbuf_attr(PACKETBUF_ATTR_RSSI),
           packetbuf_attr(PACKETBUF_ATTR_LINK_QUALITY));

    insert_route(&msg->originator, from, msg->hops);

    if(rimeaddr_cmp(&msg->dest, &rimeaddr_node_addr))
    {
        PRINTF("rrep for us!\n");
        rrep_pending = 0;
        ctimer_stop(&c->t);
        if(c->cb->new_route)
        {
            rimeaddr_t originator;

            /* If the callback modifies the packet, the originator address
               will be lost. Therefore, we need to copy it into a local
               variable before calling the callback. */
            rimeaddr_copy(&originator, &msg->originator);
            c->cb->new_route(c, &originator);
        }

    }
    else
    {
        rimeaddr_copy(&dest, &msg->dest);

        rt = route_lookup(&msg->dest);
        if(rt != NULL)
        {
            PRINTF("forwarding to %d.%d\n", rt->nexthop.u8[0], rt->nexthop.u8[1]);
            msg->hops++;
            unicast_send(&c->rrepconn, &rt->nexthop);
        }
        else
        {
            PRINTF("%d.%d: no route to %d.%d\n", rimeaddr_node_addr.u8[0], rimeaddr_node_addr.u8[1], msg->dest.u8[0], msg->dest.u8[1]);
        }
    }
}
Example #13
0
void service_dial(struct service *sv, const uint8_t uid[20])
{
    if(sv->state != STATE_IDLE) { WARN("Bad state to dial (%d)", sv->state); return; }
    sv->state = STATE_LOOKUP;
    memcpy(sv->dstid, uid, 20);
    route_lookup(sv->table, sv->srcid, sv->dstid, &sv->lookup);
    struct itimerspec its = { { 1, 0 }, { 1, 0 } };
    int res = timerfd_settime(sv->timerfd, 0, &its, NULL); assert(res == 0);
    lookup_handler(sv);
}
Example #14
0
static void wsconn_run_route(ws_connection_t *wsc)
{
	int rt, backup_rt;
	struct run_act_ctx ctx;
	sip_msg_t *fmsg;
	sr_kemi_eng_t *keng = NULL;
	str evrtname = str_init("websocket:closed");

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

	rt = route_lookup(&event_rt, evrtname.s);
	if (rt < 0 || event_rt.rlist[rt] == NULL)
	{
		if(ws_event_callback.len<=0 || ws_event_callback.s==NULL) {
			LM_DBG("event route does not exist");
			return;
		}
		keng = sr_kemi_eng_get();
		if(keng==NULL) {
			LM_DBG("event route callback engine does not exist");
			return;
		} else {
			rt = -1;
		}
	}

	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(EVENT_ROUTE);
	init_run_actions_ctx(&ctx);
	if(rt<0) {
		/* kemi script event route callback */
		if(keng && keng->froute(fmsg, EVENT_ROUTE,
					&ws_event_callback, &evrtname)<0) {
			LM_ERR("error running event route kemi callback\n");
		}
	} else {
		/* native cfg event route */
		run_top_route(event_rt.rlist[rt], fmsg, 0);
	}
	set_route_type(backup_rt);
}
Example #15
0
/*---------------------------------------------------------------------------*/
static rimeaddr_t *
data_packet_forward(struct multihop_conn *multihop,
		    const rimeaddr_t *originator,
		    const rimeaddr_t *dest,
		    const rimeaddr_t *prevhop, uint8_t hops)
{
  struct route_entry *rt;

  rt = route_lookup(dest);
  if(rt == NULL) {
    return NULL;
  }
  
  return &rt->nexthop;
}
Example #16
0
/*! Check if a route block exists - only request routes
 */
static int w_check_route_exists(struct sip_msg *msg, char *route)
{
	str s;

	if (fixup_get_svalue(msg, (gparam_p) route, &s) != 0)
	{
			LM_ERR("invalid route parameter\n");
			return -1;
	}
	if (route_lookup(&main_rt, s.s)<0) {
		/* not found */
		return -1;
	}
	return 1;
}
Example #17
0
/*! Run a request route block if it exists
 */
static int w_route_exists(struct sip_msg *msg, char *route)
{
	struct run_act_ctx ctx;
	int newroute, backup_rt, ret;

	newroute = route_lookup(&main_rt, route);
	if (newroute<0) {
		return -1;
	}
	backup_rt = get_route_type();
	set_route_type(REQUEST_ROUTE);
	init_run_actions_ctx(&ctx);
	ret = run_top_route(main_rt.rlist[newroute], msg, &ctx);
	set_route_type(backup_rt);
	return ret;
}
Example #18
0
/*---------------------------------------------------------------------------*/
static void
new_route(struct route_discovery_conn *c, const linkaddr_t *to)
{
  struct route_entry *rt;
  
  if(queued_packet) {
    PRINTF("uip-over-mesh: new route, sending queued packet\n");
    
    queuebuf_to_packetbuf(queued_packet);
    queuebuf_free(queued_packet);
    queued_packet = NULL;

    rt = route_lookup(&queued_receiver);
    if(rt) {
      route_decay(rt);
      send_data(&queued_receiver);
    }
  }
}
Example #19
0
/*---------------------------------------------------------------------------*/
static void
data_packet_received(struct multihop_conn *multihop,
		     const rimeaddr_t *from,
		     const rimeaddr_t *prevhop, uint8_t hops)
{
  struct mesh_conn *c = (struct mesh_conn *)
    ((char *)multihop - offsetof(struct mesh_conn, multihop));

  struct route_entry *rt;

  /* Refresh the route when we hear a packet from a neighbor. */
  rt = route_lookup(from);
  if(rt != NULL) {
    route_refresh(rt);
  }
  
  if(c->cb->recv) {
    c->cb->recv(c, from, hops);
  }
}
Example #20
0
int dlg_set_toroute(struct dlg_cell *dlg, str *route)
{
	if(dlg==NULL || route==NULL || route->len<=0)
		return 0;
	if(dlg->toroute_name.s!=NULL) {
		shm_free(dlg->toroute_name.s);
		dlg->toroute_name.s = NULL;
		dlg->toroute_name.len = 0;
	}
	dlg->toroute_name.s = (char*)shm_malloc((route->len+1)*sizeof(char));
	if(dlg->toroute_name.s==NULL) {
		LM_ERR("no more shared memory\n");
		return -1;
	}
	memcpy(dlg->toroute_name.s, route->s, route->len);
	dlg->toroute_name.len = route->len;
	dlg->toroute_name.s[dlg->toroute_name.len] = '\0';
	dlg->toroute = route_lookup(&main_rt, dlg->toroute_name.s);
	return 0;
}
Example #21
0
/*---------------------------------------------------------------------------*/
static rimeaddr_t *
data_packet_forward(struct multihop_conn *multihop,
		    const rimeaddr_t *originator,
		    const rimeaddr_t *dest,
		    const rimeaddr_t *prevhop, uint8_t hops)
{
  struct route_entry *rt;
  struct mesh_conn *c = (struct mesh_conn *)
    ((char *)multihop - offsetof(struct mesh_conn, multihop));

  rt = route_lookup(dest);
  if(rt == NULL) {
    route_discovery_discover(&c->route_discovery_conn, dest, PACKET_TIMEOUT);
    return NULL;
  } else {
    route_refresh(rt);
  }
  
  return &rt->nexthop;
}
Example #22
0
/*---------------------------------------------------------------------------*/
int
route_add(const rimeaddr_t *dest, const rimeaddr_t *nexthop,
	  uint8_t cost, uint8_t seqno)
{
  struct route_entry *e;

  /* Avoid inserting duplicate entries. */
  e = route_lookup(dest);
  if(e != NULL && rimeaddr_cmp(&e->nexthop, nexthop)) {
    list_remove(route_table, e);
  } else {
    /* Allocate a new entry or reuse the oldest entry with highest cost. */
    e = memb_alloc(&route_mem);
    if(e == NULL) {
      /* Remove oldest entry.  XXX */
      e = list_chop(route_table);
      PRINTF("route_add: removing entry to %d.%d with nexthop %d.%d and cost %d\n",
	     e->dest.u8[0], e->dest.u8[1],
	     e->nexthop.u8[0], e->nexthop.u8[1],
	     e->cost);
    }
  }

  rimeaddr_copy(&e->dest, dest);
  rimeaddr_copy(&e->nexthop, nexthop);
  e->cost = cost;
  e->seqno = seqno;
  e->time = 0;
  e->decay = 0;

  /* New entry goes first. */
  list_push(route_table, e);

  PRINTF("route_add: new entry to %d.%d with nexthop %d.%d and cost %d\n",
	 e->dest.u8[0], e->dest.u8[1],
	 e->nexthop.u8[0], e->nexthop.u8[1],
	 e->cost);
  
  return 0;
}
Example #23
0
int send_to_script(pv_value_t* val, jsonrpc_req_cmd_t* req_cmd)
{
	if(!(req_cmd)) return -1;

	if(req_cmd->route.len <= 0) return -1;

	jsonrpc_result_pv.setf(req_cmd->msg, &jsonrpc_result_pv.pvp, (int)EQ_T, val);

	int n = route_lookup(&main_rt, req_cmd->route.s);
	if(n<0) {
		ERR("no such route: %s\n", req_cmd->route.s);
		return -1;
	}

	struct action* route = main_rt.rlist[n];

	if(tmb.t_continue(req_cmd->t_hash, req_cmd->t_label, route)<0) {
		ERR("Failed to resume transaction\n");
		return -1;
	}
	return 0;
}
Example #24
0
/*! Run a request route block if it exists
 */
static int w_route_exists(struct sip_msg *msg, char *route)
{
	struct run_act_ctx ctx;
	int newroute, ret;
	str s;

	if (fixup_get_svalue(msg, (gparam_p) route, &s) != 0) {
			LM_ERR("invalid route parameter\n");
			return -1;
	}

	newroute = route_lookup(&main_rt, s.s);
	if (newroute<0) {
		return -1;
	}
	init_run_actions_ctx(&ctx);
	ret=run_actions(&ctx, main_rt.rlist[newroute], msg);
	if (ctx.run_flags & EXIT_R_F) {
		return 0;
	}
	return ret;
}
Example #25
0
File: sl.c Project: kiryu/kamailio
static int mod_init(void)
{
	if (init_sl_stats() < 0) {
		ERR("init_sl_stats failed\n");
		return -1;
	}
	if (sl_register_kstats()<0) {
		ERR("init k stats failed\n");
		return -1;
	}

	/* if SL loaded, filter ACKs on beginning */
	if (register_script_cb( sl_filter_ACK, PRE_SCRIPT_CB|REQUEST_CB, 0 )<0) {
		ERR("Failed to install SCRIPT callback\n");
		return -1;
	}
	if(sl_startup()<0)
	{
		ERR("Failed to do startup tasks\n");
		return -1;
	}

	if(sl_bind_tm!=0)
	{
		if(load_tm_api(&tmb)==-1)
		{
			LM_INFO("could not bind tm module - only stateless mode"
					" available\n");
			sl_bind_tm=0;
		}
	}

	_sl_filtered_ack_route=route_lookup(&event_rt, "sl:filtered-ack");
	if (_sl_filtered_ack_route>=0 && event_rt.rlist[_sl_filtered_ack_route]==0)
		_sl_filtered_ack_route=-1; /* disable */

	return 0;
}
Example #26
0
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_lookup(&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;
}
Example #27
0
static int mod_init(void)
{
	unsigned int n;

	if(dlg_ka_interval!=0 && dlg_ka_interval<30) {
		LM_ERR("ka interval too low (%d), has to be at least 30\n",
				dlg_ka_interval);
		return -1;
	}

	dlg_event_rt[DLG_EVENTRT_START] = route_lookup(&event_rt, "dialog:start");
	dlg_event_rt[DLG_EVENTRT_END] = route_lookup(&event_rt, "dialog:end");
	dlg_event_rt[DLG_EVENTRT_FAILED] = route_lookup(&event_rt, "dialog:failed");

#ifdef STATISTICS
	/* register statistics */
	if (register_module_stats( exports.name, mod_stats)!=0 ) {
		LM_ERR("failed to register %s statistics\n", exports.name);
		return -1;
	}
#endif

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

	if (rpc_register_array(rpc_methods)!=0) {
		LM_ERR("failed to register RPC commands\n");
		return -1;
	}

	if(faked_msg_init()<0)
		return -1;

	if(dlg_bridge_init_hdrs()<0)
		return -1;

	/* param checkings */
	if (dlg_flag==-1) {
		LM_ERR("no dlg flag set!!\n");
		return -1;
	} else if (dlg_flag>MAX_FLAG) {
		LM_ERR("invalid dlg flag %d!!\n",dlg_flag);
		return -1;
	}

	if (rr_param==0 || rr_param[0]==0) {
		LM_ERR("empty rr_param!!\n");
		return -1;
	} else if (strlen(rr_param)>MAX_DLG_RR_PARAM_NAME) {
		LM_ERR("rr_param too long (max=%d)!!\n", MAX_DLG_RR_PARAM_NAME);
		return -1;
	}

	if (timeout_spec.s) {
		if ( pv_parse_spec(&timeout_spec, &timeout_avp)==0 
				&& (timeout_avp.type!=PVT_AVP)){
			LM_ERR("malformed or non AVP timeout "
				"AVP definition in '%.*s'\n", timeout_spec.len,timeout_spec.s);
			return -1;
		}
	}

	if (default_timeout<=0) {
		LM_ERR("0 default_timeout not accepted!!\n");
		return -1;
	}

	if (ruri_pvar_param.s==NULL || ruri_pvar_param.len<=0) {
		LM_ERR("invalid r-uri PV string\n");
		return -1;
	}

	if(pv_parse_format(&ruri_pvar_param, &ruri_param_model) < 0
				|| ruri_param_model==NULL) {
		LM_ERR("malformed r-uri PV string: %s\n", ruri_pvar_param.s);
		return -1;
	}

	if (initial_cbs_inscript != 0 && initial_cbs_inscript != 1) {
		LM_ERR("invalid parameter for running initial callbacks in-script"
				" (must be either 0 or 1)\n");
		return -1;
	}

	if (seq_match_mode!=SEQ_MATCH_NO_ID &&
	seq_match_mode!=SEQ_MATCH_FALLBACK &&
	seq_match_mode!=SEQ_MATCH_STRICT_ID ) {
		LM_ERR("invalid value %d for seq_match_mode param!!\n",seq_match_mode);
		return -1;
	}

	if (detect_spirals != 0 && detect_spirals != 1) {
		LM_ERR("invalid value %d for detect_spirals param!!\n",detect_spirals);
		return -1;
	}

	if (dlg_timeout_noreset != 0 && dlg_timeout_noreset != 1) {
		LM_ERR("invalid value %d for timeout_noreset param!!\n",
				dlg_timeout_noreset);
		return -1;
	}

	/* if statistics are disabled, prevent their registration to core */
	if (dlg_enable_stats==0)
		exports.stats = 0;

	/* create profile hashes */
	if (add_profile_definitions( profiles_nv_s, 0)!=0 ) {
		LM_ERR("failed to add profiles without value\n");
		return -1;
	}
	if (add_profile_definitions( profiles_wv_s, 1)!=0 ) {
		LM_ERR("failed to add profiles with value\n");
		return -1;
	}

	/* load the TM API */
	if (load_tm_api(&d_tmb)!=0) {
		LM_ERR("can't load TM API\n");
		return -1;
	}

	/* load RR API also */
	if (load_rr_api(&d_rrb)!=0) {
		LM_ERR("can't load RR API\n");
		return -1;
	}

	/* register callbacks*/
	/* listen for all incoming requests  */
	if ( d_tmb.register_tmcb( 0, 0, TMCB_REQUEST_IN, dlg_onreq, 0, 0 ) <=0 ) {
		LM_ERR("cannot register TMCB_REQUEST_IN callback\n");
		return -1;
	}

	/* listen for all routed requests  */
	if ( d_rrb.register_rrcb( dlg_onroute, 0 ) <0 ) {
		LM_ERR("cannot register RR callback\n");
		return -1;
	}

	if (register_script_cb( profile_cleanup, POST_SCRIPT_CB|REQUEST_CB,0)<0) {
		LM_ERR("cannot register script callback");
		return -1;
	}
	if (register_script_cb(dlg_cfg_cb,
				PRE_SCRIPT_CB|REQUEST_CB,0)<0)
	{
		LM_ERR("cannot register pre-script ctx callback\n");
		return -1;
	}
	if (register_script_cb(dlg_cfg_cb,
				POST_SCRIPT_CB|REQUEST_CB,0)<0)
	{
		LM_ERR("cannot register post-script ctx callback\n");
		return -1;
	}

	if (register_script_cb( spiral_detect_reset, POST_SCRIPT_CB|REQUEST_CB,0)<0) {
		LM_ERR("cannot register req pre-script spiral detection reset callback\n");
		return -1;
	}

	if(dlg_timer_procs<=0) {
		if ( register_timer( dlg_timer_routine, 0, 1)<0 ) {
			LM_ERR("failed to register timer \n");
			return -1;
		}
	} else {
		register_sync_timers(1);
	}

	/* init handlers */
	init_dlg_handlers( rr_param, dlg_flag,
		timeout_spec.s?&timeout_avp:0, default_timeout, seq_match_mode);

	/* init timer */
	if (init_dlg_timer(dlg_ontimeout)!=0) {
		LM_ERR("cannot init timer list\n");
		return -1;
	}

	/* sanitize dlg_hash_zie */
	if (dlg_hash_size < 1){
		LM_WARN("hash_size is smaller "
				"then 1  -> rounding from %d to 1\n",
				dlg_hash_size);
		dlg_hash_size = 1;
	}
	/* initialized the hash table */
	for( n=0 ; n<(8*sizeof(n)) ; n++) {
		if (dlg_hash_size==(1<<n))
			break;
		if (n && dlg_hash_size<(1<<n)) {
			LM_WARN("hash_size is not a power "
				"of 2 as it should be -> rounding from %d to %d\n",
				dlg_hash_size, 1<<(n-1));
			dlg_hash_size = 1<<(n-1);
		}
	}

	if ( init_dlg_table(dlg_hash_size)<0 ) {
		LM_ERR("failed to create hash table\n");
		return -1;
	}

	/* if a database should be used to store the dialogs' information */
	dlg_db_mode = dlg_db_mode_param;
	if (dlg_db_mode==DB_MODE_NONE) {
		db_url.s = 0; db_url.len = 0;
	} else {
		if (dlg_db_mode!=DB_MODE_REALTIME &&
		dlg_db_mode!=DB_MODE_DELAYED && dlg_db_mode!=DB_MODE_SHUTDOWN ) {
			LM_ERR("unsupported db_mode %d\n", dlg_db_mode);
			return -1;
		}
		if ( !db_url.s || db_url.len==0 ) {
			LM_ERR("db_url not configured for db_mode %d\n", dlg_db_mode);
			return -1;
		}
		if (init_dlg_db(&db_url, dlg_hash_size, db_update_period,db_fetch_rows)!=0) {
			LM_ERR("failed to initialize the DB support\n");
			return -1;
		}
		run_load_callbacks();
	}

	destroy_dlg_callbacks( DLGCB_LOADED );

	/* timer process to send keep alive requests */
	if(dlg_ka_timer>0 && dlg_ka_interval>0)
		register_sync_timers(1);

	/* timer process to clean old unconfirmed dialogs */
	register_sync_timers(1);

	return 0;
}
Example #28
0
static int child_init(int rank)
{
	struct sip_msg *fmsg;
	struct run_act_ctx ctx;
	int rtb, rt;
	int i;
	sr_kemi_eng_t *keng = NULL;
	str evname = str_init("htable:mod-init");

	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 = -1;
	if(ht_event_callback.s==NULL || ht_event_callback.len<=0) {
		rt = route_lookup(&event_rt, evname.s);
		if(rt<0 || event_rt.rlist[rt]==NULL) {
			rt = -1;
		}
	} else {
		keng = sr_kemi_eng_get();
		if(keng==NULL) {
			LM_DBG("event callback (%s) set, but no cfg engine\n",
					ht_event_callback.s);
			goto done;
		}
	}
	if(rt>=0 || ht_event_callback.len>0) {
		LM_DBG("executing event_route[%s] (%d)\n", evname.s, 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);
		if(rt>=0) {
			run_top_route(event_rt.rlist[rt], fmsg, &ctx);
		} else {
			if(keng!=NULL) {
				if(keng->froute(fmsg, EVENT_ROUTE,
							&ht_event_callback, &evname)<0) {
					LM_ERR("error running event route kemi callback\n");
					return -1;
				}
			}
		}
		set_route_type(rtb);
		if(ctx.run_flags&DROP_R_F) {
			LM_ERR("exit due to 'drop' in event route\n");
			return -1;
		}
	}

done:
	return 0;
}
Example #29
0
rt_data_t* dr_load_routing_info( db_func_t *dr_dbf, db1_con_t* db_hdl,
							str *drd_table, str *drl_table, str* drr_table )
{
	int    int_vals[4];
	char * str_vals[5];
	str tmp;
	db_key_t columns[7];
	db1_res_t* res;
	db_row_t* row;
	rt_info_t *ri;
	rt_data_t *rdata;
	tmrec_t   *time_rec;
	unsigned int id;
	str s_id;
	int i,n;

	res = 0;
	ri = 0;
	rdata = 0;

	/* init new data structure */
	if ( (rdata=build_rt_data())==0 ) {
		LM_ERR("failed to build rdata\n");
		goto error;
	}

	/* read the destinations */
	if (dr_dbf->use_table( db_hdl, drd_table) < 0) {
		LM_ERR("cannot select table \"%.*s\"\n", drd_table->len,drd_table->s);
		goto error;
	}

	columns[0] = &dst_id_drd_col;
	columns[1] = &address_drd_col;
	columns[2] = &strip_drd_col;
	columns[3] = &prefix_drd_col;
	columns[4] = &type_drd_col;
	columns[5] = &attrs_drd_col;

	if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) {
		if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, 6, 0, 0 ) < 0) {
			LM_ERR("DB query failed\n");
			goto error;
		}
		if(dr_dbf->fetch_result(db_hdl, &res, dr_fetch_rows)<0) {
			LM_ERR("Error fetching rows\n");
			goto error;
		}
	} else {
		if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, 6, 0, &res) < 0) {
			LM_ERR("DB query failed\n");
			goto error;
		}
	}

	if (RES_ROW_N(res) == 0) {
		LM_WARN("table \"%.*s\" empty\n", drd_table->len,drd_table->s );
	}
	LM_DBG("%d records found in %.*s\n",
		RES_ROW_N(res), drd_table->len,drd_table->s);
	n = 0;
	do {
		for(i=0; i < RES_ROW_N(res); i++) {
			row = RES_ROWS(res) + i;
			/* DST_ID column */
			check_val( ROW_VALUES(row), DB1_INT, 1, 0);
			int_vals[0] = VAL_INT   (ROW_VALUES(row));
			/* ADDRESS column */
			check_val( ROW_VALUES(row)+1, DB1_STRING, 1, 1);
			str_vals[0] = (char*)VAL_STRING(ROW_VALUES(row)+1);
			/* STRIP column */
			check_val( ROW_VALUES(row)+2, DB1_INT, 1, 0);
			int_vals[1] = VAL_INT   (ROW_VALUES(row)+2);
			/* PREFIX column */
			check_val( ROW_VALUES(row)+3, DB1_STRING, 0, 0);
			str_vals[1] = (char*)VAL_STRING(ROW_VALUES(row)+3);
			/* TYPE column */
			check_val( ROW_VALUES(row)+4, DB1_INT, 1, 0);
			int_vals[2] = VAL_INT(ROW_VALUES(row)+4);
			/* ATTRS column */
			check_val( ROW_VALUES(row)+5, DB1_STRING, 0, 0);
			str_vals[2] = (char*)VAL_STRING(ROW_VALUES(row)+5);

			/* add the destinaton definition in */
			if ( add_dst( rdata, int_vals[0], str_vals[0], int_vals[1],
					str_vals[1], int_vals[2], str_vals[2])<0 ) {
				LM_ERR("failed to add destination id %d -> skipping\n",
					int_vals[0]);
				continue;
			}
			n++;
		}
		if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) {
			if(dr_dbf->fetch_result(db_hdl, &res, dr_fetch_rows)<0) {
				LM_ERR( "fetching rows (1)\n");
				goto error;
			}
		} else {
			break;
		}
	} while(RES_ROW_N(res)>0);

	dr_dbf->free_result(db_hdl, res);
	res = 0;

	if (n==0) {
		LM_WARN("no valid "
			"destinations set -> ignoring the routing rules\n");
		return rdata;
	}

	/* read the gw lists, if any */
	if (dr_dbf->use_table( db_hdl, drl_table) < 0) {
		LM_ERR("cannot select table \"%.*s\"\n", drl_table->len,drl_table->s);
		goto error;
	}

	columns[0] = &id_drl_col;
	columns[1] = &gwlist_drl_col;

	if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) {
		if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, 2, 0, 0 ) < 0) {
			LM_ERR("DB query failed\n");
			goto error;
		}
		if(dr_dbf->fetch_result(db_hdl, &res, dr_fetch_rows)<0) {
			LM_ERR("Error fetching rows\n");
			goto error;
		}
	} else {
		if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, 2, 0, &res) < 0) {
			LM_ERR("DB query failed\n");
			goto error;
		}
	}

	if (RES_ROW_N(res) == 0) {
		LM_DBG("table \"%.*s\" empty\n", drl_table->len,drl_table->s );
	} else {
		LM_DBG("%d records found in %.*s\n",
			RES_ROW_N(res), drl_table->len,drl_table->s);
		do {
			for(i=0; i < RES_ROW_N(res); i++) {
				row = RES_ROWS(res) + i;
				/* ID column */
				check_val( ROW_VALUES(row), DB1_INT, 1, 0);
				int_vals[0] = VAL_INT   (ROW_VALUES(row));
				/* GWLIST column */
				check_val( ROW_VALUES(row)+1, DB1_STRING, 1, 1);
				str_vals[0] = (char*)VAL_STRING(ROW_VALUES(row)+1);

				if (add_tmp_gw_list(int_vals[0], str_vals[0])!=0) {
					LM_ERR("failed to add temporary GW list\n");
					goto error;
				}
			}
			if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) {
				if(dr_dbf->fetch_result(db_hdl, &res, dr_fetch_rows)<0) {
					LM_ERR( "fetching rows (1)\n");
					goto error;
				}
			} else {
				break;
			}
		} while(RES_ROW_N(res)>0);
	}
	dr_dbf->free_result(db_hdl, res);
	res = 0;

	/* read the routing rules */
	if (dr_dbf->use_table( db_hdl, drr_table) < 0) {
		LM_ERR("cannot select table \"%.*s\"\n", drr_table->len, drr_table->s);
		goto error;
	}

	columns[0] = &rule_id_drr_col;
	columns[1] = &group_drr_col;
	columns[2] = &prefix_drr_col;
	columns[3] = &time_drr_col;
	columns[4] = &priority_drr_col;
	columns[5] = &routeid_drr_col;
	columns[6] = &dstlist_drr_col;

	if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) {
		if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, 7, 0, 0) < 0) {
			LM_ERR("DB query failed\n");
			goto error;
		}
		if(dr_dbf->fetch_result(db_hdl, &res, dr_fetch_rows)<0) {
			LM_ERR("Error fetching rows\n");
			goto error;
		}
	} else {
		if ( dr_dbf->query( db_hdl, 0, 0, 0, columns, 0, 7, 0, &res) < 0) {
			LM_ERR("DB query failed\n");
			goto error;
		}
	}

	if (RES_ROW_N(res) == 0) {
		LM_WARN("table \"%.*s\" is empty\n", drr_table->len, drr_table->s);
	}

	LM_DBG("%d records found in %.*s\n", RES_ROW_N(res),
		drr_table->len, drr_table->s);

	n = 0;
	do {
		for(i=0; i < RES_ROW_N(res); i++) {
			row = RES_ROWS(res) + i;
			/* RULE_ID column */
			check_val( ROW_VALUES(row), DB1_INT, 1, 0);
			int_vals[0] = VAL_INT (ROW_VALUES(row));
			/* GROUP column */
			check_val( ROW_VALUES(row)+1, DB1_STRING, 1, 1);
			str_vals[0] = (char*)VAL_STRING(ROW_VALUES(row)+1);
			/* PREFIX column - it may be null or empty */
			check_val( ROW_VALUES(row)+2, DB1_STRING, 0, 0);
			if ((ROW_VALUES(row)+2)->nul || VAL_STRING(ROW_VALUES(row)+2)==0){
				tmp.s = NULL;
				tmp.len = 0;
			} else {
				str_vals[1] = (char*)VAL_STRING(ROW_VALUES(row)+2);
				tmp.s = str_vals[1];
				tmp.len = strlen(str_vals[1]);
			}
			/* TIME column */
			check_val( ROW_VALUES(row)+3, DB1_STRING, 1, 1);
			str_vals[2] = (char*)VAL_STRING(ROW_VALUES(row)+3);
			/* PRIORITY column */
			check_val( ROW_VALUES(row)+4, DB1_INT, 1, 0);
			int_vals[2] = VAL_INT   (ROW_VALUES(row)+4);
			/* ROUTE_ID column */
			check_val( ROW_VALUES(row)+5, DB1_STRING, 1, 0);
			str_vals[3] = (char*)VAL_STRING(ROW_VALUES(row)+5);
			/* DSTLIST column */
			check_val( ROW_VALUES(row)+6, DB1_STRING, 1, 1);
			str_vals[4] = (char*)VAL_STRING(ROW_VALUES(row)+6);
			/* parse the time definition */
			if ((time_rec=parse_time_def(str_vals[2]))==0) {
				LM_ERR("bad time definition <%s> for rule id %d -> skipping\n",
					str_vals[2], int_vals[0]);
				continue;
			}
			/* lookup for the script route ID */
			if (str_vals[3][0] && str_vals[3][0]!='0') {
				int_vals[3] =  route_lookup(&main_rt, str_vals[3]);
				if (int_vals[3]==-1) {
					LM_WARN("route <%s> does not exist\n",str_vals[3]);
					int_vals[3] = 0;
				}
			} else {
				int_vals[3] = 0;
			}
			/* is gw_list a list or a list id? */
			if (str_vals[4][0]=='#') {
				s_id.s = str_vals[4]+1;
				s_id.len = strlen(s_id.s);
				if ( str2int( &s_id, &id)!=0 ||
				(str_vals[4]=get_tmp_gw_list(id))==NULL ) {
					LM_ERR("invalid reference to a GW list <%s> -> skipping\n",
						str_vals[4]);
					continue;
				}
			}
			/* build the routing rule */
			if ((ri = build_rt_info( int_vals[2], time_rec, int_vals[3],
					str_vals[4], rdata->pgw_l))== 0 ) {
				LM_ERR("failed to add routing info for rule id %d -> "
					"skipping\n", int_vals[0]);
				tmrec_free( time_rec );
				continue;
			}
			/* add the rule */
			if (add_rule( rdata, str_vals[0], &tmp, ri)!=0) {
				LM_ERR("failed to add rule id %d -> skipping\n", int_vals[0]);
				free_rt_info( ri );
				continue;
			}
			n++;
		}
		if (DB_CAPABILITY(*dr_dbf, DB_CAP_FETCH)) {
			if(dr_dbf->fetch_result(db_hdl, &res, dr_fetch_rows)<0) {
				LM_ERR( "fetching rows (1)\n");
				goto error;
			}
		} else {
			break;
		}
	} while(RES_ROW_N(res)>0);

	dr_dbf->free_result(db_hdl, res);
	res = 0;

	free_tmp_gw_list();

	if (n==0) {
		LM_WARN("no valid routing rules -> discarding all destinations\n");
		free_rt_data( rdata, 0 );
	}

	return rdata;
error:
	if (res)
		dr_dbf->free_result(db_hdl, res);
	if (rdata)
		free_rt_data( rdata, 1 );
	rdata = NULL;
	return 0;
}
Example #30
0
/*---------------------------------------------------------------------------*/
uint8_t
uip_over_mesh_send(void)
{
  linkaddr_t receiver;
  struct route_entry *rt;

  /* This function is called by the uip-fw module to send out an IP
     packet. We try to send the IP packet to the next hop route, or we
     queue the packet and send out a route request for the final
     receiver of the packet. */

  /* Packets destined to this network is sent using mesh, whereas
     packets destined to a network outside this network is sent towards
     the gateway node. */

  if(uip_ipaddr_maskcmp(&BUF->destipaddr, &netaddr, &netmask)) {
    receiver.u8[0] = BUF->destipaddr.u8[2];
    receiver.u8[1] = BUF->destipaddr.u8[3];
  } else {
    if(linkaddr_cmp(&gateway, &linkaddr_node_addr)) {
      PRINTF("uip_over_mesh_send: I am gateway, packet to %d.%d.%d.%d to local interface\n",
	     uip_ipaddr_to_quad(&BUF->destipaddr));
      if(gw_netif != NULL) {
	return gw_netif->output();
      }
      return UIP_FW_DROPPED;
    } else if(linkaddr_cmp(&gateway, &linkaddr_null)) {
      PRINTF("uip_over_mesh_send: No gateway setup, dropping packet\n");
      return UIP_FW_OK;
    } else {
      PRINTF("uip_over_mesh_send: forwarding packet to %d.%d.%d.%d towards gateway %d.%d\n",
	     uip_ipaddr_to_quad(&BUF->destipaddr),
	     gateway.u8[0], gateway.u8[1]);
      linkaddr_copy(&receiver, &gateway);
    }
  }

  PRINTF("uIP over mesh send to %d.%d with len %d\n",
	 receiver.u8[0], receiver.u8[1],
	 uip_len);
  
  
  packetbuf_copyfrom(&uip_buf[UIP_LLH_LEN], uip_len);

  /* Send TCP data with the PACKETBUF_ATTR_ERELIABLE set so that
     an underlying power-saving MAC layer knows that it should be
     waiting for an ACK. */
  if(BUF->proto == UIP_PROTO_TCP) {
    packetbuf_set_attr(PACKETBUF_ATTR_ERELIABLE, 1);
    packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, 1);
    /*    packetbuf_set_attr(PACKETBUF_ATTR_PACKET_TYPE, PACKETBUF_ATTR_PACKET_TYPE_STREAM);*/
  }

  rt = route_lookup(&receiver);
  if(rt == NULL) {
    PRINTF("uIP over mesh no route to %d.%d\n", receiver.u8[0], receiver.u8[1]);
    if(queued_packet == NULL) {
      queued_packet = queuebuf_new_from_packetbuf();
      linkaddr_copy(&queued_receiver, &receiver);
      route_discovery_discover(&route_discovery, &receiver, ROUTE_TIMEOUT);
    } else if(!linkaddr_cmp(&queued_receiver, &receiver)) {
      route_discovery_discover(&route_discovery, &receiver, ROUTE_TIMEOUT);
    }
  } else {
    route_decay(rt);
    send_data(&rt->nexthop);
  }
  return UIP_FW_OK;
}