Exemplo n.º 1
0
void hello_send(void *arg)
{
	RREP *rrep;
	u8_t flags = 0;
	struct in_addr dest;
	struct timeval now;
	long time_diff;
	
	gettimeofday(&now, NULL);

	if(timeval_diff(&now, &this_host.last_forward_time) > ACTIVE_ROUTE_TIMEOUT)
	{
		hello_stop();
		return;
	}

	time_diff = timeval_diff(&now, &this_host.last_broadcast_time);

	if(time_diff >= HELLO_INTERVAL)
	{
		rrep = rrep_create(flags, 0, 0, this_host.dev.ipaddr, this_host.seqno, this_host.dev.ipaddr, ALLOWED_HELLO_LOSS * HELLO_INTERVAL);

	/////////No ext	
	
		dest.s_addr = AODV_BROADCAST;
		aodv_socket_send((AODV_msg *)rrep, dest, RREP_SIZE, 1, &this_host.dev);

		timer_set_timeout(&hello_timer, HELLO_INTERVAL);
	}
	else
	{
		timer_set_timeout(&hello_timer, HELLO_INTERVAL - time_diff);
	}
}
Exemplo n.º 2
0
// Invoked when a value is delivered
void on_deliver(void* cmd_value, size_t cmd_size, void * arg) {
	client * cl = arg;
	
	cl->current_inst_number += 1;
	
	client_proposal * c;
	unsigned i;
	
	//Check if the delivered values was sent from this process.
	for(i = 0; i < CONCURRENT_VALUES; i++) {
		c = &cl->pending_values[i];
		submit_cmd_msg * msg = c->submit_msg;
		
		//If so, submit another one
		if(cmd_size == msg->cmd_size &&
		memcmp(msg->cmd_value, cmd_value, cmd_size) == 0) {
			// printf("CMD %u accepted in instance %lu\n", i, current_inst_number);
			
			cl->deliver_count += 1;
			cl->deliver_bytes += cmd_size;

			gettimeofday(&cl->current_time, NULL);
			save_latency(cl, &c->submit_time, &cl->current_time);
			
			generate_random_value(c->submit_msg);
			submit_value(cl->us, c->submit_msg);
			save_submit_time(c, &cl->current_time);
			timer_set_timeout(&cl->current_time, &c->timeout, &cl->value_timeout_interval);
			
			break;
		}
	}
}
Exemplo n.º 3
0
size_t modem_readline(char *buffer, size_t max, uint32_t timeout) {
  timer_set_timeout(timeout * 1000);
  size_t idx = 0;
  while (idx < max) {
    if (!timer_timeout_remaining()) break;

    int c = modem_read();
    if (c == -1) {
      // nothing in the buffer, allow some sleep
      __WFI();
      continue;
    }

    if (c == '\r') continue;
    if (c == '\n') {
      if (!idx) {
        idx = 0;
        continue;
      }
      break;
    }
    if (max - idx && isprint(c)) buffer[idx++] = (char) c;
  }

  buffer[idx] = 0;
  return idx;
}
Exemplo n.º 4
0
void NS_CLASS local_repair_timeout(void *arg)
{
    rt_table_t *rt;
    struct in_addr rerr_dest;
    RERR *rerr = NULL;

    rt = (rt_table_t *) arg;

    if (!rt)
        return;

    rerr_dest.s_addr = AODV_BROADCAST;	/* Default destination */

    /* Unset the REPAIR flag */
    rt->flags &= ~RT_REPAIR;

#ifndef NS_PORT
    nl_send_del_route_msg(rt->dest_addr, rt->next_hop, rt->hcnt);
#endif
    /* Route should already be invalidated. */

    if (rt->nprec) {

        rerr = rerr_create(0, rt->dest_addr, rt->dest_seqno);

        if (rt->nprec == 1) {
            rerr_dest = FIRST_PREC(rt->precursors)->neighbor;

            aodv_socket_send((AODV_msg *) rerr, rerr_dest,
                             RERR_CALC_SIZE(rerr), 1,
                             &DEV_IFINDEX(rt->ifindex));
        } else {
            int i;

            for (i = 0; i < MAX_NR_INTERFACES; i++) {
                if (!DEV_NR(i).enabled)
                    continue;
                aodv_socket_send((AODV_msg *) rerr, rerr_dest,
                                 RERR_CALC_SIZE(rerr), 1,
                                 &DEV_NR(i));
            }
        }
        DEBUG(LOG_DEBUG, 0, "Sending RERR about %s to %s",
              ip_to_str(rt->dest_addr), ip_to_str(rerr_dest));
    }
    precursor_list_destroy(rt);

    /* Purge any packets that may be queued */
    /* packet_queue_set_verdict(rt->dest_addr, PQ_DROP); */

    rt->rt_timer.handler = &NS_CLASS route_delete_timeout;
    timer_set_timeout(&rt->rt_timer, DELETE_PERIOD);

    DEBUG(LOG_DEBUG, 0, "%s removed in %u msecs",
          ip_to_str(rt->dest_addr), DELETE_PERIOD);
}
Exemplo n.º 5
0
void NS_CLASS rrep_send(RREP * rrep, rt_table_t * rev_rt,
			rt_table_t * fwd_rt, int size)
{
	u_int8_t rrep_flags = 0;
	struct in_addr dest;

	if (!rev_rt) {
		DEBUG(LOG_WARNING, 0, "Can't send RREP, rev_rt = NULL!");
		return;
	}

	dest.s_addr = rrep->dest_addr;

	/* Check if we should request a RREP-ACK */
	if ((rev_rt->state == VALID && rev_rt->flags & RT_UNIDIR) ||
	    (rev_rt->hcnt == 1 && unidir_hack)) {
		rt_table_t *neighbor = rt_table_find(rev_rt->next_hop);

		if (neighbor && neighbor->state == VALID
		    && !neighbor->ack_timer.used) {
			/* If the node we received a RREQ for is a neighbor we are
			   probably facing a unidirectional link... Better request a
			   RREP-ack */
			rrep_flags |= RREP_ACK;
			neighbor->flags |= RT_UNIDIR;

			/* Must remove any pending hello timeouts when we set the
			   RT_UNIDIR flag, else the route may expire after we begin to
			   ignore hellos... */
			timer_remove(&neighbor->hello_timer);
			neighbor_link_break(neighbor);

			DEBUG(LOG_DEBUG, 0, "Link to %s is unidirectional!",
			      ip_to_str(neighbor->dest_addr));

			timer_set_timeout(&neighbor->ack_timer, NEXT_HOP_WAIT);
		}
	}

	DEBUG(LOG_DEBUG, 0, "Sending RREP to next hop %s about %s->%s",
	      ip_to_str(rev_rt->next_hop), ip_to_str(rev_rt->dest_addr),
	      ip_to_str(dest));

	aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, size, MAXTTL,
			 &DEV_IFINDEX(rev_rt->ifindex));

	/* Update precursor lists */
	if (fwd_rt) {
		precursor_add(fwd_rt, rev_rt->next_hop);
		precursor_add(rev_rt, fwd_rt->next_hop);
	}

	if (!llfeedback && optimized_hellos)
		hello_start();
}
Exemplo n.º 6
0
void activity_layer_reset(ActivityLayer *activity_layer)
{
    activity_layer->reset_loop = false;
    activity_layer->block1_prog = 0;
    activity_layer->block2_prog = 0;
    activity_layer->block3_prog = 0;

    layer_mark_dirty(&activity_layer->layer);

    timer_set_timeout(&activity_layer->animation_timer, ACTIVITY_RESET_MS);
}
Exemplo n.º 7
0
void NS_CLASS rrep_forward(RREP * rrep, int size, rt_table_t * rev_rt,
			   rt_table_t * fwd_rt, int ttl)
{
	/* Sanity checks... */
	if (!fwd_rt || !rev_rt) {
		DEBUG(LOG_WARNING, 0,
		      "Could not forward RREP because of NULL route!");
		return;
	}

	if (!rrep) {
		DEBUG(LOG_WARNING, 0, "No RREP to forward!");
		return;
	}

	DEBUG(LOG_DEBUG, 0, "Forwarding RREP to %s",
	      ip_to_str(rev_rt->next_hop));

	/* Here we should do a check if we should request a RREP_ACK,
	   i.e we suspect a unidirectional link.. But how? */
	if (0) {
		rt_table_t *neighbor;

		/* If the source of the RREP is not a neighbor we must find the
		   neighbor (link) entry which is the next hop towards the RREP
		   source... */
		if (rev_rt->dest_addr.s_addr != rev_rt->next_hop.s_addr)
			neighbor = rt_table_find(rev_rt->next_hop);
		else
			neighbor = rev_rt;

		if (neighbor && !neighbor->ack_timer.used) {
			/* If the node we received a RREQ for is a neighbor we are
			   probably facing a unidirectional link... Better request a
			   RREP-ack */
			rrep->a = 1;
			neighbor->flags |= RT_UNIDIR;

			timer_set_timeout(&neighbor->ack_timer, NEXT_HOP_WAIT);
		}
	}

	rrep = (RREP *) aodv_socket_queue_msg((AODV_msg *) rrep, size);
	rrep->hcnt = fwd_rt->hcnt;	/* Update the hopcount */

	aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop, size, ttl,
			 &DEV_IFINDEX(rev_rt->ifindex));

	precursor_add(fwd_rt, rev_rt->next_hop);
	precursor_add(rev_rt, fwd_rt->next_hop);

	rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT);
}
Exemplo n.º 8
0
//Custom init for the learner
void client_pl_init(void * arg) {
	client * cl = arg;
	
	printf("FastClient: submitting %d values of size [%lu...%lu]\n", 
		CONCURRENT_VALUES, MIN_VAL_SIZE, MAX_VAL_SIZE);
	
	
	//Use an udp sender instead of a submit_proxy
	cl->us = udp_sender_init(
		lptopo_get_leader_addr(learner_get_topolo_mngr(cl->l)), 
		lptopo_get_leader_clients_port(learner_get_topolo_mngr(cl->l)),
		learner_get_config_mngr(cl->l));
	// No autoflush, it's manual for this client
	assert(cl->us != NULL);
	udp_sender_enable_autoflush(cl->us, 25);
	
	//Periodically check for timeouts
	cl->periodic_check =  
	set_periodic_event(
	    &cl->value_timeout_interval,  /*Interval for this event*/
	    values_timeout_check, /*Called periodically*/
	    cl /*Argument passed to above function*/
	    );

	//Periodically print statistics
	cl->periodic_stats =  
	set_periodic_event(
	    &cl->print_stats_interval,  /*Interval for this event*/
	    print_stats, /*Called periodically*/
	    cl /*Argument passed to above function*/
	    );

	printf("Client initialization completed\n");
	cl->start_time = time(NULL);
	
	gettimeofday(&cl->current_time, NULL);

	//Submit the initial amount of values
	client_proposal * c;
	unsigned i;
	for(i = 0; i < CONCURRENT_VALUES; i++) {
		c = &cl->pending_values[i];
		// c->submit_msg = malloc(sizeof(submit_cmd_msg) + MAX_VAL_SIZE);
		c->submit_msg = (submit_cmd_msg*) &cl->values_buffer[i * (MAX_VAL_SIZE + sizeof(submit_cmd_msg))];
		generate_random_value(c->submit_msg);
		submit_value(cl->us, c->submit_msg);
		save_submit_time(c, &cl->current_time);
		timer_set_timeout(&cl->current_time, &c->timeout, &cl->value_timeout_interval);
	}
}
Exemplo n.º 9
0
size_t modem_read_binary(uint8_t *buffer, size_t max, uint32_t timeout) {
  timer_set_timeout(timeout * 1000);
  size_t idx = 0;
  while (idx < max) {
    if (!timer_timeout_remaining()) break;
    int c = modem_read();
    if (c == -1) {
      // nothing in the buffer, allow some sleep
      __WFI();
      continue;
    }
    if (max - idx) buffer[idx++] = (uint8_t) c;
  }

  return idx;
}
Exemplo n.º 10
0
void NS_CLASS local_repair_timeout(void *arg)
{
    rt_table_t *rt;
    u_int32_t rerr_dest = AODV_BROADCAST;
    RERR *rerr = NULL;

    rt = (rt_table_t *) arg;

    if (!rt)
	return;

    /* Unset the REPAIR flag */
    rt->flags &= ~RT_REPAIR;

    rt->rt_timer.handler = &NS_CLASS route_delete_timeout;
    timer_set_timeout(&rt->rt_timer, DELETE_PERIOD);

    DEBUG(LOG_DEBUG, 0, "%s removed in %u msecs",
	  ip_to_str(rt->dest_addr), DELETE_PERIOD);

    /* Route should already be invalidated. */

    if (rt->nprec) {

	rerr = rerr_create(0, rt->dest_addr, rt->dest_seqno);

	if (rt->nprec == 1) {
	    rerr_dest = FIRST_PREC(rt->precursors)->neighbor;

	    aodv_socket_send((AODV_msg *) rerr, rerr_dest, 
			     RERR_CALC_SIZE(rerr), 1,
			     &DEV_IFINDEX(rt->ifindex));
	} else {
	    int i;

	    for (i = 0; i < MAX_NR_INTERFACES; i++) {
		if (!DEV_NR(i).enabled)
		    continue;
		aodv_socket_send((AODV_msg *) rerr, rerr_dest,
				 RERR_CALC_SIZE(rerr), 1, &DEV_NR(i));
	    }
	}
	DEBUG(LOG_DEBUG, 0, "Sending RERR about %s to %s",
	      ip_to_str(rt->dest_addr), ip_to_str(rerr_dest));
    }
    precursor_list_destroy(rt);
}
Exemplo n.º 11
0
void modem_send(const char *pattern, ...) {
  char cmd[BOARD_CELL_BUFSIZE];

  // cleanup the input buffer and check for URC messages
  uint32_t remaining = timer_timeout_remaining();
  while (modem_readline(cmd, BOARD_CELL_BUFSIZE - 1, 100)) check_urc(cmd);
  timer_set_timeout(remaining);

  cmd[0] = '\0';

  va_list ap;
  va_start(ap, pattern);
  vsnprintf(cmd, BOARD_CELL_BUFSIZE, pattern, ap);
  va_end(ap);

  CIODEBUG("GSM (%02d) <- '%s'\r\n", strlen(cmd), cmd);
  modem_writeline(cmd);
}
Exemplo n.º 12
0
//Check that the sent values did not time-out
// The timed-out values are re-sent
void values_timeout_check(void* arg) {
	client * cl = arg;
	
	gettimeofday(&cl->current_time, NULL);
	
	client_proposal * c;
	unsigned i;
	for(i = 0; i < CONCURRENT_VALUES; i++) {
		c = &cl->pending_values[i];
		if(timer_is_expired(&c->timeout, &cl->current_time)) {
			cl->timeout_count += 1;
			// printf("Value %u timed-out\n", i);
			submit_value(cl->us, c->submit_msg);
			save_submit_time(c, &cl->current_time);
			timer_set_timeout(&cl->current_time, &c->timeout, &cl->value_timeout_interval);
		}
	}
	
}
Exemplo n.º 13
0
static void packet_input(int fd)
#endif
{
    rt_table_t *fwd_rt, *rev_rt, *next_hop_rt = NULL;
    struct in_addr dest_addr, src_addr;
    u_int8_t rreq_flags = 0;
    unsigned int ifindex;
    struct ip_data *ipd = NULL;
    int pkt_flags = 0;

#ifdef NS_PORT
    ifindex = NS_IFINDEX;	/* Always use ns interface */
    fwd_rt = NULL;		/* For broadcast we provide no next hop */
    ipd = NULL;			/* No ICMP messaging */

    struct hdr_cmn *ch = HDR_CMN(p);
    struct hdr_ip *ih = HDR_IP(p);

    src_addr.s_addr = ih->saddr();
    dest_addr.s_addr = ih->daddr();

    /* If this is a TCP packet and we don't have a route, we should
       set the gratuituos flag in the RREQ. */
    if (ch->ptype() == PT_TCP) {
	rreq_flags |= RREQ_GRATUITOUS;
    }
#else
    int status;
    char buf[sizeof(struct nlmsghdr)+sizeof(ipq_packet_msg_t)+BUFSIZE];
    char *dev_name;
    ipq_packet_msg_t *pkt;
    struct iphdr *ip;
    struct udphdr *udp;
    struct icmphdr *icmp = NULL;

    status =  ipq_read(h, buf, sizeof(buf), -1);
    
    if (status < 0) {
	DEBUG(LOG_DEBUG, 0, "%s", ipq_errstr());
	ipq_perror(NULL);
	return;
    }

    if (ipq_message_type(buf) == NLMSG_ERROR) {
	fprintf(stderr,
		"ERROR packet_input: Check that the ip_queue.o module is loaded.\n");
	die(h);
    }

    pkt = ipq_get_packet(buf);

#ifdef DEBUG_PACKET
    DEBUG(LOG_DEBUG, 0, "Protocol %u indev=%s outdev=%s\n",
	  pkt->hw_protocol, pkt->indev_name, pkt->outdev_name);
#endif

    if (pkt->hook == 0)
	dev_name = pkt->indev_name;
    else if (pkt->hook == 3)
	dev_name = pkt->outdev_name;
    else
	dev_name = NULL;

    /* We know from kaodv.c that this is an IP packet */
    ip = (struct iphdr *) pkt->payload;

    dest_addr.s_addr = ip->daddr;
    src_addr.s_addr = ip->saddr;

    switch (ip->protocol) {
	/* Don't process AODV control packets (UDP on port 654). They
	   are accounted for on the aodv socket */
    case IPPROTO_UDP:
	udp = (struct udphdr *) ((char *) ip + (ip->ihl << 2));
	if (ntohs(udp->dest) == AODV_PORT || ntohs(udp->source) == AODV_PORT)
	    goto accept;
	break;
	/* If this is a TCP packet and we don't have a route, we should
	   set the gratuituos flag in the RREQ. */
    case IPPROTO_TCP:
	rreq_flags |= RREQ_GRATUITOUS;
	break;
	/* We set the gratuitous flag also on ICMP ECHO requests, since
	   the destination will also need a route back for the reply... */
    case IPPROTO_ICMP:
	icmp = (struct icmphdr *) ((char *) ip + (ip->ihl << 2));
	if (icmp->type == ICMP_ECHO)
	    rreq_flags |= RREQ_GRATUITOUS;
#ifdef DEBUG_PACKET
	DEBUG(LOG_INFO, 0, "setting G flag for RREQ to %s",
	      ip_to_str(dest_addr));
#endif

	break;
#ifdef CONFIG_GATEWAY
    case IPPROTO_MIPE:
	if (internet_gw_mode) {
	    
	    ip = ip_pkt_decapsulate(ip);

	    if (ip == NULL) {
	      DEBUG(LOG_ERR, 0, "Decapsulation failed...");
	      exit(-1);
	    }
	    pkt_flags |= PKT_DEC;
	}
	break;
#endif /* CONFIG_GATEWAY */
    }

#ifdef DEBUG_PACKET
    DEBUG(LOG_INFO, 0, "pkt to %s", ip_to_str(dest_addr));
#endif

    if (dev_name) {
	ifindex = name2index(dev_name);
	if (ifindex < 0) {
	    DEBUG(LOG_ERR, 0, "name2index error!");
	    return;
	}
    } else
	ifindex = 0;
#endif				/* NS_PORT */

    /* If the packet is not interesting we just let it go through... */
    if (dest_addr.s_addr == AODV_BROADCAST ||
	dest_addr.s_addr == DEV_IFINDEX(ifindex).broadcast.s_addr) {
#ifdef NS_PORT
	/* Limit Non AODV broadcast packets (Rolf Winter
	 * <[email protected]). */
	ih->ttl() = ih->ttl() - 1;                
       
	if(ih->ttl() < 1)        
	    Packet::free(p);                
	else
	    sendPacket(p, dest_addr, 0.0);
	return;
#else
	goto accept;
#endif
    }
    
    /* Find the entry of the neighboring node and the destination  (if any). */
    rev_rt = rt_table_find(src_addr);
    fwd_rt = rt_table_find(dest_addr);

#ifdef CONFIG_GATEWAY
    /* Check if we have a route and it is an Internet destination (Should be
     * encapsulated and routed through the gateway). */
    if (fwd_rt && (fwd_rt->state == VALID) && 
	(fwd_rt->flags & RT_INET_DEST)) {
	/* The destination should be relayed through the IG */

	rt_table_update_timeout(fwd_rt, ACTIVE_ROUTE_TIMEOUT);
#ifdef NS_PORT
	p = pkt_encapsulate(p, fwd_rt->next_hop);

	if (p == NULL) {
	    DEBUG(LOG_ERR, 0, "IP Encapsulation failed!");
	   return;	    
	}
	/* Update pointers to headers */
	ch = HDR_CMN(p);
	ih = HDR_IP(p);
#else
	ip = ip_pkt_encapsulate(ip, fwd_rt->next_hop, BUFSIZE);

	if (ip == NULL) {
	    DEBUG(LOG_ERR, 0, "Minimal IP Encapsulation failed!");
	    exit(-1);	    
	}
#endif
	dest_addr = fwd_rt->next_hop;
	fwd_rt = rt_table_find(dest_addr);
	pkt_flags |= PKT_ENC;
    }
#endif /* CONFIG_GATEWAY */

    /* UPDATE TIMERS on active forward and reverse routes...  */

    /* When forwarding a packet, we update the lifetime of the
       destination's routing table entry, as well as the entry for the
       next hop neighbor (if not the same). AODV draft 10, section
       6.2. */
    if (fwd_rt && fwd_rt->state == VALID &&
	dest_addr.s_addr != DEV_IFINDEX(ifindex).ipaddr.s_addr) {

	rt_table_update_timeout(fwd_rt, ACTIVE_ROUTE_TIMEOUT);

	next_hop_rt = rt_table_find(fwd_rt->next_hop);
	
	if (next_hop_rt && next_hop_rt->state == VALID && 
	    next_hop_rt->dest_addr.s_addr != fwd_rt->dest_addr.s_addr)
	    rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT);

    }
    /* Also update the reverse route and reverse next hop along the
       path back, since routes between originators and the destination
       are expected to be symmetric. */
    if (rev_rt && rev_rt->state == VALID) {
	
	rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT);

	next_hop_rt = rt_table_find(rev_rt->next_hop);

	if (next_hop_rt && next_hop_rt->state == VALID &&
	    rev_rt && next_hop_rt->dest_addr.s_addr != rev_rt->dest_addr.s_addr)
	    rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT);

	/* Update HELLO timer of next hop neighbor if active */   
	if (!llfeedback && next_hop_rt->hello_timer.used) {
	    struct timeval now;
	
	    gettimeofday(&now, NULL);
	    hello_update_timeout(next_hop_rt, &now, 
				 ALLOWED_HELLO_LOSS * HELLO_INTERVAL);
	}
    }

    /* OK, the timeouts have been updated. Now see if either: 1. The
       packet is for this node -> ACCEPT. 2. The packet is not for this
       node -> Send RERR (someone want's this node to forward packets
       although there is no route) or Send RREQ. */

    /* If the packet is destined for this node, then just accept it. */
    if (memcmp(&dest_addr, &DEV_IFINDEX(ifindex).ipaddr, 
	       sizeof(struct in_addr)) == 0) {

#ifdef NS_PORT
	ch->size() -= IP_HDR_LEN;    // cut off IP header size 4/7/99 -dam
	target_->recv(p, (Handler*)0);
	p = 0;
	return;
#else
	goto accept;
#endif
    }
    if (!fwd_rt || fwd_rt->state == INVALID ||
	(fwd_rt->hcnt == 1 && (fwd_rt->flags & RT_UNIDIR))) {

	/* Check if the route is marked for repair or is INVALID. In
	 * that case, do a route discovery. */
	if (fwd_rt && (fwd_rt->flags & RT_REPAIR))
	    goto route_discovery;

	/* If a packet is received on the NF_IP_PRE_ROUTING hook,
	   i.e. inbound on the interface and we don't have a route to
	   the destination, we should send an RERR to the source and
	   then drop the package... */
	/* NF_IP_PRE_ROUTING = 0 */
#ifdef NS_PORT
#define PACKET_IS_INBOUND ch->direction() == hdr_cmn::UP
#else
#define PACKET_IS_INBOUND pkt->hook == 0
#endif

	if (PACKET_IS_INBOUND) {

	    struct in_addr rerr_dest;
	    RERR *rerr;
#ifdef NS_PORT
	    struct in_addr nh;
	    nh.s_addr = ch->prev_hop_;
	    
	    DEBUG(LOG_DEBUG, 0,
		  "No route, src=%s dest=%s prev_hop=%s - DROPPING!",
		  ip_to_str(src_addr), ip_to_str(dest_addr),
		  ip_to_str(nh));
#endif
	    if (fwd_rt) {
		rerr = rerr_create(0, fwd_rt->dest_addr,
				   fwd_rt->dest_seqno);

		rt_table_update_timeout(fwd_rt, DELETE_PERIOD);
	    } else
		rerr = rerr_create(0, dest_addr, 0);
	    
	    DEBUG(LOG_DEBUG, 0, "Sending RERR to prev hop %s for unknown dest %s", ip_to_str(src_addr), ip_to_str(dest_addr));
	    
	    /* Unicast the RERR to the source of the data transmission
	     * if possible, otherwise we broadcast it. */
	    
	    if (rev_rt && rev_rt->state == VALID)
		rerr_dest = rev_rt->next_hop;
	    else
		rerr_dest.s_addr = AODV_BROADCAST;

	    aodv_socket_send((AODV_msg *) rerr, rerr_dest,
			     RERR_CALC_SIZE(rerr), 1, &DEV_IFINDEX(ifindex));

	    if (wait_on_reboot) {
		DEBUG(LOG_DEBUG, 0, "Wait on reboot timer reset.");
		timer_set_timeout(&worb_timer, DELETE_PERIOD);
	    }
#ifdef NS_PORT
	    /* DEBUG(LOG_DEBUG, 0, "Dropping pkt uid=%d", ch->uid()); */
	    drop(p, DROP_RTR_NO_ROUTE);
#else
	    status = ipq_set_verdict(h, pkt->packet_id, NF_DROP, 0, NULL);
	    
	    if (status < 0)
		die(h);
#endif
	    return;
	}

      route_discovery:
	/* Buffer packets... Packets are queued by the ip_queue.o
	   module already. We only need to save the handle id, and
	   return the proper verdict when we know what to do... */

#ifdef NS_PORT
	packet_queue_add(p, dest_addr);
#else
	packet_queue_add(pkt->packet_id, dest_addr, ip);
	
#ifdef CONFIG_GATEWAY
	/* In gateway mode we handle packets in userspace */
	ipq_set_verdict(h, pkt->packet_id, NF_DROP, 0, NULL);
#endif
	/* Already seeking the destination? Then do not allocate any
	   memory or generate a RREQ. */
	if (seek_list_find(dest_addr))
	    return;

	/* If the request is generated locally by an application, we save
	   the IP header + 64 bits of data for sending an ICMP Destination
	   Host Unreachable in case we don't find a route... */
	if (src_addr.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr && ip &&
	    pkt->data_len >= (ip->ihl << 2) + 8) {
	    ipd = (struct ip_data *) malloc(sizeof(struct ip_data));
	    if (ipd == NULL) {
		perror("Malloc for IP data failed!");
		exit(-1);
	    }
	    /* IP header + 64 bits data (8 bytes) */
	    ipd->len = (ip->ihl << 2) + 8;
	    memcpy(ipd->data, ip, ipd->len);
	} else
	    ipd = NULL;
#endif
	if (fwd_rt && (fwd_rt->flags & RT_REPAIR))
	    rreq_local_repair(fwd_rt, src_addr, ipd);
	else
	    rreq_route_discovery(dest_addr, rreq_flags, ipd);

	return;

    } else {

#ifdef NS_PORT
	/* DEBUG(LOG_DEBUG, 0, "Sending pkt uid=%d", ch->uid()); */
	sendPacket(p, fwd_rt->next_hop, 0.0);
#else	
      accept:

	if (pkt_flags & PKT_ENC || (pkt_flags & PKT_DEC))
	    status = ipq_set_verdict(h, pkt->packet_id, NF_ACCEPT, 
				     ntohs(ip->tot_len), (unsigned char *)ip);
	else
	    status = ipq_set_verdict(h, pkt->packet_id, NF_ACCEPT, 0, NULL);
	
	if (status < 0)
	    die(h);

#endif
	/* When forwarding data, make sure we are sending HELLO messages */
	gettimeofday(&this_host.fwd_time, NULL);

	if (!llfeedback && optimized_hellos)
	    hello_start();
    }
}
Exemplo n.º 14
0
void NS_CLASS print_rt_table(void *arg)
{
    char rt_buf[2048], ifname[64], seqno_str[11];
    int len = 0;
    int i = 0;
    rt_table_t *entry;
    precursor_t *pr;
    struct timeval now;
    struct tm *time;

    if (rt_tbl.num_entries == 0)
	goto schedule;

    gettimeofday(&now, NULL);

#ifdef NS_PORT
    time = gmtime(&now.tv_sec);
#else
    time = localtime(&now.tv_sec);
#endif

    len +=
	sprintf(rt_buf,
		"# Time: %02d:%02d:%02d.%03ld IP: %s seqno: %u entries/active: %u/%u\n",
		time->tm_hour, time->tm_min, time->tm_sec, now.tv_usec / 1000,
		devs_ip_to_str(), this_host.seqno, rt_tbl.num_entries,
		rt_tbl.num_active);
    len +=
	sprintf(rt_buf + len,
		"%-15s %-15s %-3s %-3s %-5s %-6s %-5s %-5s %-15s\n",
		"Destination", "Next hop", "HC", "St.", "Seqno", "Expire",
		"Flags", "Iface", "Precursors");

    write(log_rt_fd, rt_buf, len);
    len = 0;

    for (i = 0; i < RT_TABLESIZE; i++) {
	entry = rt_tbl.tbl[i];
	while (entry != NULL) {

	    if (entry->flags & RT_INV_SEQNO)
		sprintf(seqno_str, "-");
	    else
		sprintf(seqno_str, "%u", entry->dest_seqno);

	    /* Print routing table entries one by one... */
	    if (entry->precursors == NULL)
		len += sprintf(rt_buf + len,
			       "%-15s %-15s %-3d %-3s %-5s %-6lu %-5s %-5s\n",
			       ip_to_str(entry->dest_addr),
			       ip_to_str(entry->next_hop), entry->hcnt,
			       state_to_str(entry->state), seqno_str,
			       (entry->hcnt == 255) ? 0 :
			       timeval_diff(&entry->rt_timer.timeout, &now),
			       rt_flags_to_str(entry->flags),
			       if_indextoname(entry->ifindex, ifname));

	    else {
		len += sprintf(rt_buf + len,
			       "%-15s %-15s %-3d %-3s %-5s %-6lu %-5s %-5s %-15s\n",
			       ip_to_str(entry->dest_addr),
			       ip_to_str(entry->next_hop), entry->hcnt,
			       state_to_str(entry->state), seqno_str,
			       (entry->hcnt == 255) ? 0 :
			       timeval_diff(&entry->rt_timer.timeout, &now),
			       rt_flags_to_str(entry->flags),
			       if_indextoname(entry->ifindex, ifname),
			       ip_to_str(entry->precursors->neighbor));

		/* Print all precursors for the current routing entry */
		for (pr = entry->precursors->next; pr != NULL; pr = pr->next) {
		    len += sprintf(rt_buf + len, "%64s %-15s\n", "*",
				   ip_to_str(pr->neighbor));

		    /* Since the precursor list is grown dynamically
		     * the write buffer should be flushed for every
		     * entry to avoid buffer overflows */
		    write(log_rt_fd, rt_buf, len);
		    len = 0;

		}
	    }
	    if (len > 0) {
		write(log_rt_fd, rt_buf, len);
		len = 0;
	    }
	    entry = entry->next;
	}
    }
    /* Schedule a new printing of routing table... */
  schedule:
    timer_set_timeout(&rt_log_timer, rt_log_interval);
}
Exemplo n.º 15
0
Arquivo: main.c Projeto: azhgul/AODV-1
int main(int argc, char **argv)
{
    static char *ifname = NULL;	/* Name of interface to attach to */
    fd_set rfds, readers;
    int n, nfds = 0, i;
    int daemonize = 0;
    struct timeval *timeout;
    struct timespec timeout_spec;
    struct sigaction sigact;
    sigset_t mask, origmask;

    /* Remember the name of the executable... */
    progname = strrchr(argv[0], '/');

    if (progname)
	progname++;
    else
	progname = argv[0];

    /* Use debug output as default */
    debug = 1;

    memset (&sigact, 0, sizeof(struct sigaction));
    sigact.sa_handler = signal_handler;
        
    /* This server should shut down on these signals. */
    sigaction(SIGTERM, &sigact, 0);
    sigaction(SIGHUP, &sigact, 0);
    sigaction(SIGINT, &sigact, 0);
    
    sigaddset(&mask, SIGTERM);
    sigaddset(&mask, SIGHUP);
    sigaddset(&mask, SIGINT);
    /* Only capture segmentation faults when we are not debugging... */
#ifndef DEBUG
    sigaddset(&mask, SIGSEGV);
#endif

    /* Block the signals we are watching here so that we can
     * handle them in pselect instead. */
    sigprocmask(SIG_BLOCK, &mask, &origmask);

    /* Parse command line: */
    while (1) {
	int opt;

	opt = getopt_long(argc, argv, "i:fjln:dghoq:r:s:c:uwxDLRV", longopts, 0);

	if (opt == EOF)
	    break;

	switch (opt) {
	case 0:
	    break;
	case 'd':
	    debug = 0;
	    daemonize = 1;
	    break;
	case 'f':
	    llfeedback = 1;
	    active_route_timeout = ACTIVE_ROUTE_TIMEOUT_LLF;
	    break;
	case 'g':
	    rreq_gratuitous = !rreq_gratuitous;
	    break;
	case 'i':
	    ifname = optarg;
	    break;
	case 'j':
	    hello_jittering = !hello_jittering;
	    break;
	case 'l':
	    log_to_file = !log_to_file;
	    break;
	case 'n':
	    if (optarg && isdigit(*optarg)) {
		receive_n_hellos = atoi(optarg);
		if (receive_n_hellos < 2) {
		    fprintf(stderr, "-n should be at least 2!\n");
		    exit(-1);
		}
	    }
	    break;
	case 'o':
	    optimized_hellos = !optimized_hellos;
	    break;
	case 'q':
	    if (optarg && isdigit(*optarg))
		qual_threshold = atoi(optarg);
	    break;
	case 'r':
	    if (optarg && isdigit(*optarg))
		rt_log_interval = atof(optarg) * 1000;
	    break;
	case 's':
		if (optarg && isdigit(*optarg))
		inet_aton(optarg, &server_addr);
		break;
	case 'c':
		if (optarg && isdigit(*optarg))
		{
			node_discovery_mode = !node_discovery_mode;
			discovery_internal = atof(optarg) * 1000 * 60;
		}
		break;
	case 'u':
	    unidir_hack = !unidir_hack;
	    break;
	case 'w':
	    internet_gw_mode = !internet_gw_mode;
	    break;
	case 'x':
	    expanding_ring_search = !expanding_ring_search;
	    break;
	case 'L':
	    local_repair = !local_repair;
	    break;
	case 'D':
	    wait_on_reboot = !wait_on_reboot;
	    break;
	case 'R':
	    ratelimit = !ratelimit;
	    break;
	case 'V':
	    printf
		("\nAODV-UU v%s, %s © Uppsala University & Ericsson AB.\nAuthor: Erik Nordström, <*****@*****.**>\n\n",
		 AODV_UU_VERSION, DRAFT_VERSION);
	    exit(0);
	    break;
	case '?':
	case ':':
	    exit(0);
	default:
	    usage(0);
	}
    }
    /* Check that we are running as root */
    if (geteuid() != 0) {
	fprintf(stderr, "must be root\n");
	exit(1);
    }

    /* Detach from terminal */
    if (daemonize) {
	if (fork() != 0)
	    exit(0);
	/* Close stdin, stdout and stderr... */
	/*  close(0); */
	close(1); 
	close(2);
	setsid();
    }
    /* Make sure we cleanup at exit... */
    atexit((void *) &cleanup);

    /* Initialize data structures and services... */
    rt_table_init();
    log_init();
    /*   packet_queue_init(); */
    host_init(ifname);
    /*   packet_input_init(); */
    nl_init();
    nl_send_conf_msg();
    aodv_socket_init();
#ifdef LLFEEDBACK
    if (llfeedback) {
	llf_init();
    }
#endif

    /* Set sockets to watch... */
    FD_ZERO(&readers);
    for (i = 0; i < nr_callbacks; i++) {
	FD_SET(callbacks[i].fd, &readers);
	if (callbacks[i].fd >= nfds)
	    nfds = callbacks[i].fd + 1;
    }

    /* Set the wait on reboot timer... */
    if (wait_on_reboot) {
		timer_init(&worb_timer, wait_on_reboot_timeout, &wait_on_reboot);
		timer_set_timeout(&worb_timer, DELETE_PERIOD);
		alog(LOG_NOTICE, 0, __FUNCTION__,
			 "In wait on reboot for %d milliseconds. Disable with \"-D\".",
			 DELETE_PERIOD);
    }
    
    if(node_discovery_mode && internet_gw_mode)
    {
		timer_init(&discovery_timer, node_discovery_timeout, NULL);
		timer_set_timeout(&discovery_timer, discovery_internal);
		DEBUG(LOG_DEBUG, 0, "This is gateway and set with node discovery\n");
	}

    /* Schedule the first Hello */
    if (!optimized_hellos && !llfeedback)
	hello_start();

    if (rt_log_interval)
	log_rt_table_init();

    while (1) {
	memcpy((char *) &rfds, (char *) &readers, sizeof(rfds));

	timeout = timer_age_queue();
	
	timeout_spec.tv_sec = timeout->tv_sec;
	timeout_spec.tv_nsec = timeout->tv_usec * 1000;

	if ((n = pselect(nfds, &rfds, NULL, NULL, &timeout_spec, &origmask)) < 0) {
	    if (errno != EINTR)
		alog(LOG_WARNING, errno, __FUNCTION__,
		     "Failed select (main loop)");
	    continue;
	}

	if (n > 0) {
	    for (i = 0; i < nr_callbacks; i++) {
		if (FD_ISSET(callbacks[i].fd, &rfds)) {
		    /* We don't want any timer SIGALRM's while executing the
		       callback functions, therefore we block the timer... */
		    (*callbacks[i].func) (callbacks[i].fd);
		}
	    }
	}
    }				/* Main loop */
    return 0;
}
Exemplo n.º 16
0
void activity_layer_step(ActivityLayer *activity_layer)
{
    int max = (ACTIVITY_BLOCK_MAX_SIZE - ACTIVITY_BLOCK_MIN_SIZE) / 2;

    // When in a reset loop, animate out the 3rd block
    if (activity_layer->reset_loop) {
        if (activity_layer->block3_prog > 0) {
            activity_layer->block3_prog--;
            if (activity_layer->block2_prog > 0) {
                activity_layer->block2_prog--;
            }
            if (activity_layer->block1_prog > 0) {
                activity_layer->block1_prog--;
            }
            if (activity_layer->block3_prog == 0) {
                activity_layer->reset_loop = false;

                // Alter the animation timing during a reset to take a little extra time
                timer_set_timeout(&activity_layer->animation_timer, ACTIVITY_RESET_MS);
            }
        }

        layer_mark_dirty(&activity_layer->layer);
        return;
    }

    // Set the animation timing, because this can be changed in a reset loop
    timer_set_timeout(&activity_layer->animation_timer, ACTIVITY_PULSE_MS);

    if (activity_layer->block3_prog > 0) {
        if (activity_layer->block3_prog < max) {
            activity_layer->block3_prog++;

            // Enter a reset loop when
            if (activity_layer->block3_prog == max) {
                activity_layer->reset_loop = true;
            }
        }

        if (activity_layer->block2_prog > 0) {
            activity_layer->block2_prog--;
        }
        if (activity_layer->block1_prog > 0) {
            activity_layer->block1_prog--;
        }
    }

    else if (activity_layer->block2_prog > 0) {
        if (activity_layer->block2_prog < max) {
            activity_layer->block2_prog++;
        }
        else {
            activity_layer->block3_prog++;
        }

        if (activity_layer->block1_prog > 0) {
            activity_layer->block1_prog--;
        }
    }

    else {
        if (activity_layer->block1_prog < max) {
            activity_layer->block1_prog++;
            if (activity_layer->block3_prog > 0) {
                activity_layer->block3_prog--;
            }
        }
        else {
            activity_layer->block2_prog++;
        }
    }
    
    layer_mark_dirty(&activity_layer->layer);
}
Exemplo n.º 17
0
void NS_CLASS log_rt_table_init()
{
    rt_log_timer.handler = &NS_CLASS print_rt_table;
    rt_log_timer.data = NULL;
    timer_set_timeout(&rt_log_timer, rt_log_interval);
}
Exemplo n.º 18
0
void NS_CLASS packet_queue_timeout(void *arg)
{
    packet_queue_garbage_collect();
    timer_set_timeout(&PQ.garbage_collect_timer, GARBAGE_COLLECT_TIME);
}
Exemplo n.º 19
0
void hello_update_timeout(rt_table_t *rt, struct timeval *now, long time)
{
	timer_set_timeout(&rt->hello_timer, time + HELLO_DELAY);
	memcpy(&rt->last_hello_time, now, sizeof(struct timeval));
}
Exemplo n.º 20
0
void NS_CLASS route_discovery_timeout(void *arg)
{
    struct timeval now;
    seek_list_t *seek_entry;
    rt_table_t *rt, *repair_rt;
    seek_entry = (seek_list_t *) arg;

#define TTL_VALUE seek_entry->ttl

    /* Sanity check... */
    if (!seek_entry)
        return;

    gettimeofday(&now, NULL);

    DEBUG(LOG_DEBUG, 0, "%s", ip_to_str(seek_entry->dest_addr));

    if (seek_entry->reqs < RREQ_RETRIES) {

        if (expanding_ring_search) {

            if (TTL_VALUE < TTL_THRESHOLD)
                TTL_VALUE += TTL_INCREMENT;
            else {
                TTL_VALUE = NET_DIAMETER;
                seek_entry->reqs++;
            }
            /* Set a new timer for seeking this destination */
            timer_set_timeout(&seek_entry->seek_timer, RING_TRAVERSAL_TIME);
        } else {
            seek_entry->reqs++;
            timer_set_timeout(&seek_entry->seek_timer,
                              seek_entry->reqs * 2 * NET_TRAVERSAL_TIME);
        }
        /* AODV should use a binary exponential backoff RREP waiting
           time. */
        DEBUG(LOG_DEBUG, 0, "Seeking %s ttl=%d wait=%d",
              ip_to_str(seek_entry->dest_addr),
              TTL_VALUE, 2 * TTL_VALUE * NODE_TRAVERSAL_TIME);

        /* A routing table entry waiting for a RREP should not be expunged
           before 2 * NET_TRAVERSAL_TIME... */
        rt = rt_table_find(seek_entry->dest_addr);

        if (rt && timeval_diff(&rt->rt_timer.timeout, &now) <
                (2 * NET_TRAVERSAL_TIME))
            rt_table_update_timeout(rt, 2 * NET_TRAVERSAL_TIME);

        rreq_send(seek_entry->dest_addr, seek_entry->dest_seqno,
                  TTL_VALUE, seek_entry->flags);

    } else {

        DEBUG(LOG_DEBUG, 0, "NO ROUTE FOUND!");

#ifdef NS_PORT
        packet_queue_set_verdict(seek_entry->dest_addr, PQ_DROP);
#else
        nl_send_no_route_found_msg(seek_entry->dest_addr);
#endif
        repair_rt = rt_table_find(seek_entry->dest_addr);

        seek_list_remove(seek_entry);

        /* If this route has been in repair, then we should timeout
           the route at this point. */
        if (repair_rt && (repair_rt->flags & RT_REPAIR)) {
            DEBUG(LOG_DEBUG, 0, "REPAIR for %s failed!",
                  ip_to_str(repair_rt->dest_addr));
            local_repair_timeout(repair_rt);
        }
    }
}
Exemplo n.º 21
0
static void nl_callback(int sock)
{
	int len, attrlen;
	socklen_t addrlen;
	struct nlmsghdr *nlm;
	struct nlmsgerr *nlmerr;
	char buf[BUFLEN];
	struct in_addr dest_addr, src_addr;	
	struct ifaddrmsg *ifm;
	struct rtattr *rta;
	kaodv_rt_msg_t *m;
	rt_table_t *rt, *fwd_rt, *rev_rt = NULL;
		
	addrlen = sizeof(peer);


	len = recvfrom(sock, buf, BUFLEN, 0, (struct sockaddr *)&peer, &addrlen);

	if (len <= 0)
		return;
	
	nlm = (struct nlmsghdr *)buf;

	switch (nlm->nlmsg_type) {
	case NLMSG_ERROR:
		nlmerr = NLMSG_DATA(nlm);
		if (nlmerr->error == 0) {
			DEBUG(LOG_DEBUG, 0, "NLMSG_ACK");
		} else
			DEBUG(LOG_DEBUG, 0, "NLMSG_ERROR, error=%d", 
			      nlmerr->error);
		break;
	case RTM_NEWLINK:
		DEBUG(LOG_DEBUG, 0, "RTM_NEWADDR");
		break;
	case RTM_NEWADDR:
		DEBUG(LOG_DEBUG, 0, "RTM_NEWADDR");

		ifm = NLMSG_DATA(nlm);

		rta = (struct rtattr *)((char *)ifm + sizeof(ifm));
		
		attrlen = nlm->nlmsg_len - 
			sizeof(struct nlmsghdr) - 
			sizeof(struct ifaddrmsg);
		
		for (; RTA_OK(rta, attrlen); rta = RTA_NEXT(rta, attrlen)) {

			if (rta->rta_type == IFA_ADDRESS) {
				struct in_addr ifaddr;
				
				memcpy(&ifaddr, RTA_DATA(rta), RTA_PAYLOAD(rta));
				
				DEBUG(LOG_DEBUG, 0, 
				      "Interface index %d changed address to %s", 
				      ifm->ifa_index, ip_to_str(ifaddr));
				
			}
		}
		break;
	case KAODVM_TIMEOUT:
		m = NLMSG_DATA(nlm);
		dest_addr.s_addr = m->dst;

		DEBUG(LOG_DEBUG, 0,
		      "Got TIMEOUT msg from kernel for %s",
		      ip_to_str(dest_addr));

		rt = rt_table_find(dest_addr);

		if (rt && rt->state == VALID)
			route_expire_timeout(rt);
		else
			DEBUG(LOG_DEBUG, 0,
			      "Got rt timeoute event but there is no route");
		break;
	case KAODVM_NOROUTE:
		m = NLMSG_DATA(nlm);
		dest_addr.s_addr = m->dst;

		DEBUG(LOG_DEBUG, 0,
		      "Got NOROUTE msg from kernel for %s",
		      ip_to_str(dest_addr));

		rreq_route_discovery(dest_addr, 0, NULL);
		break;
	case KAODVM_REPAIR:
		m = NLMSG_DATA(nlm);
		dest_addr.s_addr = m->dst;
		src_addr.s_addr = m->src;

		DEBUG(LOG_DEBUG, 0, "Got REPAIR msg from kernel for %s",
		      ip_to_str(dest_addr));

		fwd_rt = rt_table_find(dest_addr);

		if (fwd_rt)
			rreq_local_repair(fwd_rt, src_addr, NULL);

		break;
	case KAODVM_ROUTE_UPDATE:
		m = NLMSG_DATA(nlm);
		dest_addr.s_addr = m->dst;
		src_addr.s_addr = m->src;
	
		if (dest_addr.s_addr == AODV_BROADCAST ||
		    dest_addr.s_addr ==
		    DEV_IFINDEX(m->ifindex).broadcast.s_addr)
			return;

		fwd_rt = rt_table_find(dest_addr);
		rev_rt = rt_table_find(src_addr);

		rt_table_update_route_timeouts(fwd_rt, rev_rt);

		break;
	case KAODVM_SEND_RERR:
		m = NLMSG_DATA(nlm);
		dest_addr.s_addr = m->dst;
		src_addr.s_addr = m->src;

		if (dest_addr.s_addr == AODV_BROADCAST ||
		    dest_addr.s_addr ==
		    DEV_IFINDEX(m->ifindex).broadcast.s_addr)
			return;

		fwd_rt = rt_table_find(dest_addr);
		rev_rt = rt_table_find(src_addr);

		do {
			struct in_addr rerr_dest;
			RERR *rerr;

			DEBUG(LOG_DEBUG, 0,
			      "Sending RERR for unsolicited message from %s to dest %s",
			      ip_to_str(src_addr),
			      ip_to_str(dest_addr));

			if (fwd_rt) {
				rerr = rerr_create(0, fwd_rt->dest_addr,
						   fwd_rt->dest_seqno);

				rt_table_update_timeout(fwd_rt,
							DELETE_PERIOD);
			} else
				rerr = rerr_create(0, dest_addr, 0);

			/* Unicast the RERR to the source of the data transmission
			 * if possible, otherwise we broadcast it. */

			if (rev_rt && rev_rt->state == VALID)
				rerr_dest = rev_rt->next_hop;
			else
				rerr_dest.s_addr = AODV_BROADCAST;

			aodv_socket_send((AODV_msg *) rerr, rerr_dest,
					 RERR_CALC_SIZE(rerr), 1,
					 &DEV_IFINDEX(m->ifindex));

			if (wait_on_reboot) {
				DEBUG(LOG_DEBUG, 0,
				      "Wait on reboot timer reset.");
				timer_set_timeout(&worb_timer,
						  DELETE_PERIOD);
			}
		} while (0);
		break;
	default:
		DEBUG(LOG_DEBUG, 0, "Got mesg type=%d\n", nlm->nlmsg_type);
	}
}