Example #1
0
/* Used to update neighbor when non-hello AODV message is received... */
void hello_process_non_hello(AODV_msg *aodv_msg, u_int32_t source) {
  rt_table_t *entry = NULL;
  u_int32_t seqno = 0;

  switch(aodv_msg->type) {
  case AODV_RREQ:
    if(((RREQ *)aodv_msg)->src_addr == source)
      seqno = ((RREQ *)aodv_msg)->src_seqno;
    break;
  case AODV_RREP:
    break;
  case AODV_RERR:
    break;
  default:
    break;
  }
  entry = rt_table_find(source);
  
  /* Check message type, and if we can retrieve a sequence number */
  if(entry == NULL)
    entry = rt_table_insert(source, source, 1, seqno,  
	 		    ACTIVE_ROUTE_TIMEOUT, NEIGHBOR);  
  else {
    /* Don't update anything if this is a uni-directional link... */
    if(entry->flags & UNIDIR)
      return;
    
    if(seqno == 0)
      rt_table_update_timeout(entry, ACTIVE_ROUTE_TIMEOUT);
    else
      rt_table_update(entry, source, 1, seqno,
		      ACTIVE_ROUTE_TIMEOUT, NEIGHBOR);
  }
  
  hello_update_timeout(entry, ALLOWED_HELLO_LOSS*HELLO_INTERVAL);
}
Example #2
0
void rt_table_insert_neighbor(u_int32_t neigh) {
  
  if(rt_table_find(neigh) == NULL)
    rt_table_insert(neigh, neigh, 1, 0, ALLOWED_HELLO_LOSS*HELLO_INTERVAL, 
		    NEIGHBOR);
}
Example #3
0
void
rrep_process(RREP * rrep, int rreplen, u_int32_t ip_src, u_int32_t ip_dst,
	     int ip_ttl, unsigned int ifindex)
{
    u_int32_t rrep_dest, rrep_orig, rrep_lifetime, rrep_seqno;
    rt_table_t *fwd_rt, *rev_rt;

    /* Convert to correct byte order on affeected fields: */
    rrep_dest = ntohl(rrep->dest_addr);
    rrep_orig = ntohl(rrep->orig_addr);
    rrep_seqno = ntohl(rrep->dest_seqno);
    rrep_lifetime = ntohl(rrep->lifetime);

    if (rreplen < RREP_SIZE) {
	log(LOG_WARNING, 0,
	    "rrep_process: IP data field too short (%u bytes)"
	    " from %s to %s", rreplen, ip_to_str(ip_src),
	    ip_to_str(ip_dst));
	return;
    }

    /* Ignore messages which aim to a create a route to one self */
    if (memcmp(&rrep_dest, &DEV_IFINDEX(ifindex).ipaddr, sizeof(u_int32_t)) == 0 &&
	memcmp(&rrep_orig, &DEV_IFINDEX(ifindex).ipaddr, sizeof(u_int32_t)) == 0)
	return;

    /* Check if this was a hello message... */
    if (ip_ttl == 1) {
	if (memcmp(&ip_src, &DEV_IFINDEX(ifindex).ipaddr, sizeof(u_int32_t)) != 0)
	    hello_process(rrep, rreplen, ifindex);
	return;
    }
#ifdef DEBUG
    log(LOG_DEBUG, 0, "RREP_process: from=%s about %s->%s",
	ip_to_str(ip_src), ip_to_str(rrep_orig), ip_to_str(rrep_dest));
    log_pkt_fields((AODV_msg *) rrep);
#endif

    /* When a node receives a RREP, it first increments the hop count in
       the RREP, to account for the extra hop */
    rrep->hcnt++;

    /* ---------- CHECK IF WE SHOULD MAKE A FORWARD ROUTE ------------
       We update or insert a forward route only if:

       (i) the Destination Sequence Number in the RREP is greater than
       the node's copy of the destination sequence number, or

       (ii) the sequence numbers are the same, but the route is no
       longer active or the Hop Count in RREP is smaller than the hop
       count in route table entry. */

    fwd_rt = rt_table_find(rrep_dest);

    if (fwd_rt == NULL) {
	/* We didn't have an existing entry, so we insert a new one. */
	fwd_rt = rt_table_insert(rrep_dest, ip_src, rrep->hcnt,
				 rrep_seqno, rrep_lifetime, FWD_ROUTE, ifindex);
    } else if ((rrep_seqno > fwd_rt->dest_seqno) ||
	       (((rrep_seqno == fwd_rt->dest_seqno) &&
		 IS_INFTY(fwd_rt->hcnt)) ||
		(fwd_rt->flags & UNIDIR) || (rrep->hcnt < fwd_rt->hcnt))) {
	fwd_rt = rt_table_update(fwd_rt, ip_src, rrep->hcnt,
				 rrep_seqno, rrep_lifetime, FWD_ROUTE);
    } else
	return;


    /* Check if this RREP was for us (i.e. we previously made a RREQ
       for this host). */
    if (memcmp(&rrep_orig, &DEV_IFINDEX(ifindex).ipaddr, sizeof(u_int32_t)) == 0) {

	/* Remove destination from seeking list since a route has been
	   found. */
	if (seek_list_remove(rrep_dest))
	    packet_buff_send(rrep_dest);

	/* If the RREP_ACK flag is set we must send a RREP
	   acknowledgement to the destination that replied... */
	if (rrep->a) {
	    RREP_ack *rrep_ack;

	    rrep_ack = rrep_ack_create();
	    aodv_socket_send((AODV_msg *) rrep_ack, fwd_rt->next_hop,
			     NEXT_HOP_WAIT, MAXTTL, 
			     &DEV_IFINDEX(fwd_rt->ifindex));
	    /* Remove RREP_ACK flag... */
	    rrep->a = 0;
	}

    } else {
	/* --- Here we FORWARD the RREP on the REVERSE route --- */
	/* If the current node is not the source node as indicated by the
	   Source IP Address in the RREP message AND a forward route has
	   been created or updated as described before, the node consults
	   its route table entry for the source node to determine the next
	   hop for the RREP packet, and then forwards the RREP towards the
	   source with its Hop Count incremented by one. */
	if ((rev_rt = rt_table_find_active(rrep_orig)) != NULL) {

	    /* 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 != rev_rt->next_hop)
		    neighbor = rt_table_find(rev_rt->next_hop);
		else
		    neighbor = rev_rt;

		if (neighbor != NULL && !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 |= UNIDIR;

		    timer_add_msec(&neighbor->ack_timer, NEXT_HOP_WAIT);
		}
	    }
	    rrep = (RREP *) aodv_socket_queue_msg((AODV_msg *) rrep, rreplen);
	    aodv_socket_send((AODV_msg *) rrep, rev_rt->next_hop,
			     RREP_SIZE, --ip_ttl, &DEV_IFINDEX(rev_rt->ifindex));

	    /* The neighboring nodes to which a RREP was forwarded should be 
	       added as a precursor node. */
	    if (fwd_rt != NULL)
		precursor_add(fwd_rt, rev_rt->next_hop);

	    /* At each node the (reverse) route used to forward the RREP
	       has its lifetime changed to current time plus
	       ACTIVE_ROUTE_TIMEOUT. */
	    rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT);
	}
    }

}
Example #4
0
/* Process a hello message */
void hello_process(RREP *hello, int rreplen) {
  u_int32_t hello_dst;
  u_int32_t hello_interval = HELLO_INTERVAL;
  u_int32_t ext_neighbor;
  rt_table_t *entry;
  AODV_ext *ext = NULL;
  int i, unidir_link = 1;
  
  hello_dst = ntohl(hello->dest_addr);

  /* Check for hello interval extension: */
  ext = (AODV_ext *)((char *)hello + RREP_SIZE);
  
  while(rreplen > RREP_SIZE) {
    switch(ext->type) {
    case RREP_HELLO_INTERVAL_EXT:
      if(ext->length == 4) {
	memcpy(&hello_interval, AODV_EXT_DATA(ext), 4);
#ifdef DEBUG_HELLO
	log(LOG_INFO, 0, "HELLO_process: Hello extension interval=%lu!", 
	    hello_interval);
#endif
      } else
	log(LOG_WARNING, 0, "hello_process: Bad hello interval extension!");
      break;
    case RREP_HELLO_NEIGHBOR_SET_EXT:
#ifdef DEBUG_HELLO
      log(LOG_INFO, 0, "HELLO_process: RREP_HELLO_NEIGHBOR_SET_EXT");
#endif
      for(i = 0; i < ext->length; i = i + 4) {
	ext_neighbor = ntohl(*(u_int32_t *)((char *)AODV_EXT_DATA(ext) + i));

	if(memcmp(&ext_neighbor, &this_host->ipaddr, 4) == 0)
	  unidir_link = 0;
      }
      break;
    default:
      log(LOG_WARNING, 0, "hello_process: Bad extension!! type=%d, length=%d", 
	  ext->type, ext->length);
      ext = NULL;
      break;
    }
    if(ext == NULL)
      break;

    rreplen -= AODV_EXT_SIZE(ext);
    ext = AODV_EXT_NEXT(ext);
    
  }
  
#ifdef DEBUG_HELLO
  log(LOG_DEBUG, 0, "processHello: rcvd HELLO from %s, seqno %lu", 
      ip_to_str(hello_dst), hello->dest_seqno);
#endif

  if((entry = rt_table_find(hello_dst)) == NULL) {
    /* No active or expired route in the routing table. So we add a
       new entry... */
    if(unidir_hack && unidir_link) {
      entry = rt_table_insert(hello_dst, hello_dst, 1, hello->dest_seqno,  
			      ACTIVE_ROUTE_TIMEOUT, NEIGHBOR | UNIDIR);  
#ifdef DEBUG
      log(LOG_INFO, 0, "hello_process: %s is UNI-DIR!!!", 
	  ip_to_str(entry->dest));
#endif
    } else {
      entry = rt_table_insert(hello_dst, hello_dst, 1, hello->dest_seqno,  
			    ACTIVE_ROUTE_TIMEOUT, NEIGHBOR);  
#ifdef DEBUG
        log(LOG_INFO, 0, "hello_process: %s is BI-DIR!!!", 
	  ip_to_str(entry->dest));
#endif
    }
      
  } else {

    if(unidir_hack && unidir_link) {
#ifdef DEBUG
      if(!(entry->flags & UNIDIR))
	log(LOG_INFO, 0, "hello_process: %s is UNI-DIR!!!", 
	    ip_to_str(entry->dest));
#endif
      entry->flags |= UNIDIR;
    } else if(entry->flags & UNIDIR) {
      entry->flags ^= UNIDIR;
#ifdef DEBUG
      log(LOG_INFO, 0, "hello_process: %s is BI-DIR!!!", 
	  ip_to_str(entry->dest));
#endif
    }
    /* Update sequence numbers if the hello contained new info... */
    if(hello->dest_seqno < entry->dest_seqno)
      hello->dest_seqno = entry->dest_seqno;
    
    if(entry->flags & UNIDIR)
      entry->dest_seqno = hello->dest_seqno;
    else {
      rt_table_update(entry, hello_dst, 1, hello->dest_seqno,
		      ACTIVE_ROUTE_TIMEOUT, NEIGHBOR);
    } 
  }
  /* Only update hello timeout for routes which are not unidir */
  /* if(!(entry->flags & UNIDIR)) */
  hello_update_timeout(entry, ALLOWED_HELLO_LOSS*hello_interval);
  
  return;
}
Example #5
0
void hello_process(RREP *hello, s32_t len)
{
	u32_t hello_seqno, timeout, hello_interval = HELLO_INTERVAL;
	u8_t state, flags = 0;
	struct in_addr hello_dest;
	rt_table_t *rt;
	struct  timeval now;

	gettimeofday(&now, NULL);

	hello_dest.s_addr = hello->dest_addr;
	hello_seqno = ntohl(hello->dest_seqno);

	rt = rt_table_check(hello_dest);

	if(rt)
		flags = rt->flags;

	if(receive_n_hellos)
		state = INVALID;
	else
		state = VALID;

	timeout = ALLOWED_HELLO_LOSS * hello_interval + ROUTE_TIMEOUT_SLACK;

	if(!rt)
	{
		rt = rt_table_insert(hello_dest, hello_dest, 1, hello_seqno, timeout, state, flags);

		if(flags & RT_UNIDIR)
		{
			DEBUG(LOG_INFO, 0, "%s new NEIGHBOR, link UNI_DIR", ip_to_str(rt->dest_addr));
		}
		else
		{
			DEBUG(LOG_INFO, 0, "%s new NEIGHBOR", ip_to_str(rt->dest_addr));
		}

		rt->hello_cnt = 1;
	}
	else
	{
		if((flags & RT_UNIDIR) && rt->state == VALID && rt->hopcnt > 1)
		{
			hello_update_timeout(rt, &now, ALLOWED_HELLO_LOSS *hello_interval);
			return;
		}

		if(receive_n_hellos && rt->hello_cnt < (receive_n_hellos - 1))
		{
			if(timeval_diff(&now, &rt->last_hello_time) < (long)(hello_interval + hello_interval / 2))
				rt->hello_cnt++;
			else
				rt->hello_cnt = 1;

			memcpy(&rt->last_hello_time, &now, sizeof(struct timeval));
			return;
		}

		rt_table_update(rt, hello_dest, 1, hello_seqno, timeout, VALID, flags);

		hello_update_timeout(rt, &now, ALLOWED_HELLO_LOSS * hello_interval);
	}	
}
Example #6
0
void NS_CLASS rrep_process(RREP * rrep, int rreplen, struct in_addr ip_src,
			   struct in_addr ip_dst, int ip_ttl,
			   unsigned int ifindex)
{
	u_int32_t rrep_lifetime, rrep_seqno, rrep_new_hcnt;
	u_int8_t pre_repair_hcnt = 0, pre_repair_flags = 0;
	rt_table_t *fwd_rt, *rev_rt;
	AODV_ext *ext;
	unsigned int extlen = 0;
	int rt_flags = 0;
	struct in_addr rrep_dest, rrep_orig;
#ifdef CONFIG_GATEWAY
	struct in_addr inet_dest_addr;
	int inet_rrep = 0;
#endif

	/* Convert to correct byte order on affeected fields: */
	rrep_dest.s_addr = rrep->dest_addr;
	rrep_orig.s_addr = rrep->orig_addr;
	rrep_seqno = ntohl(rrep->dest_seqno);
	rrep_lifetime = ntohl(rrep->lifetime);
	/* Increment RREP hop count to account for intermediate node... */
	rrep_new_hcnt = rrep->hcnt + 1;

	if (rreplen < (int)RREP_SIZE) {
		alog(LOG_WARNING, 0, __FUNCTION__,
		     "IP data field too short (%u bytes)"
		     " from %s to %s", rreplen, ip_to_str(ip_src),
		     ip_to_str(ip_dst));
		return;
	}

	/* Ignore messages which aim to a create a route to one self */
	if (rrep_dest.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr)
		return;

	DEBUG(LOG_DEBUG, 0, "from %s about %s->%s",
	      ip_to_str(ip_src), ip_to_str(rrep_orig), ip_to_str(rrep_dest));
#ifdef DEBUG_OUTPUT
	log_pkt_fields((AODV_msg *) rrep);
#endif

	/* Determine whether there are any extensions */
	ext = (AODV_ext *) ((char *)rrep + RREP_SIZE);

	while ((rreplen - extlen) > RREP_SIZE) {
		switch (ext->type) {
		case RREP_EXT:
			DEBUG(LOG_INFO, 0, "RREP include EXTENSION");
			/* Do something here */
			break;
#ifdef CONFIG_GATEWAY
		case RREP_INET_DEST_EXT:
			if (ext->length == sizeof(u_int32_t)) {

				/* Destination address in RREP is the gateway address, while the
				 * extension holds the real destination */
				memcpy(&inet_dest_addr, AODV_EXT_DATA(ext),
				       ext->length);

				DEBUG(LOG_DEBUG, 0, "RREP_INET_DEST_EXT: <%s>",
				      ip_to_str(inet_dest_addr));
				/* This was a RREP from a gateway */
				rt_flags |= RT_GATEWAY;
				inet_rrep = 1;
				break;
			}
#endif
		default:
			alog(LOG_WARNING, 0, __FUNCTION__,
			     "Unknown or bad extension %d", ext->type);
			break;
		}
		extlen += AODV_EXT_SIZE(ext);
		ext = AODV_EXT_NEXT(ext);
	}

	/* ---------- CHECK IF WE SHOULD MAKE A FORWARD ROUTE ------------ */

	fwd_rt = rt_table_find(rrep_dest);
	rev_rt = rt_table_find(rrep_orig);

	if (!fwd_rt) {
		/* We didn't have an existing entry, so we insert a new one. */
		fwd_rt =
		    rt_table_insert(rrep_dest, ip_src, rrep_new_hcnt,
				    rrep_seqno, rrep_lifetime, VALID, rt_flags,
				    ifindex);
	} else if (fwd_rt->dest_seqno == 0
		   || (int32_t) rrep_seqno > (int32_t) fwd_rt->dest_seqno
		   || (rrep_seqno == fwd_rt->dest_seqno
		       && (fwd_rt->state == INVALID || fwd_rt->flags & RT_UNIDIR
			   || rrep_new_hcnt < fwd_rt->hcnt))) {
		pre_repair_hcnt = fwd_rt->hcnt;
		pre_repair_flags = fwd_rt->flags;

		fwd_rt =
		    rt_table_update(fwd_rt, ip_src, rrep_new_hcnt, rrep_seqno,
				    rrep_lifetime, VALID,
				    rt_flags | fwd_rt->flags);
	} else {
		if (fwd_rt->hcnt > 1) {
			DEBUG(LOG_DEBUG, 0,
			      "Dropping RREP, fwd_rt->hcnt=%d fwd_rt->seqno=%ld",
			      fwd_rt->hcnt, fwd_rt->dest_seqno);
		}
		return;
	}

	/* If the RREP_ACK flag is set we must send a RREP
	   acknowledgement to the destination that replied... */
	if (rrep->a) {
		RREP_ack *rrep_ack;

		rrep_ack = rrep_ack_create();
		aodv_socket_send((AODV_msg *) rrep_ack, fwd_rt->next_hop,
				 NEXT_HOP_WAIT, MAXTTL,
				 &DEV_IFINDEX(fwd_rt->ifindex));
		/* Remove RREP_ACK flag... */
		rrep->a = 0;
	}

	/* Check if this RREP was for us (i.e. we previously made a RREQ
	   for this host). */
	if (rrep_orig.s_addr == DEV_IFINDEX(ifindex).ipaddr.s_addr) {
#ifdef CONFIG_GATEWAY
		if (inet_rrep) {
			rt_table_t *inet_rt;
			inet_rt = rt_table_find(inet_dest_addr);

			/* Add a "fake" route indicating that this is an Internet
			 * destination, thus should be encapsulated and routed through a
			 * gateway... */
			if (!inet_rt)
				rt_table_insert(inet_dest_addr, rrep_dest,
						rrep_new_hcnt, 0, rrep_lifetime,
						VALID, RT_INET_DEST, ifindex);
			else if (inet_rt->state == INVALID
				 || rrep_new_hcnt < inet_rt->hcnt) {
				rt_table_update(inet_rt, rrep_dest,
						rrep_new_hcnt, 0, rrep_lifetime,
						VALID,
						RT_INET_DEST | inet_rt->flags);
			} else {
				DEBUG(LOG_DEBUG, 0,
				      "INET Response, but no update %s",
				      ip_to_str(inet_dest_addr));
			}
		}
#endif				/* CONFIG_GATEWAY */

		/* If the route was previously in repair, a NO DELETE RERR should be
		   sent to the source of the route, so that it may choose to reinitiate
		   route discovery for the destination. Fixed a bug here that caused the
		   repair flag to be unset and the RERR never being sent. Thanks to
		   McWood <*****@*****.**> for discovering this. */
		if (pre_repair_flags & RT_REPAIR) {
			if (fwd_rt->hcnt > pre_repair_hcnt) {
				RERR *rerr;
				u_int8_t rerr_flags = 0;
				struct in_addr dest;

				dest.s_addr = AODV_BROADCAST;

				rerr_flags |= RERR_NODELETE;
				rerr =
				    rerr_create(rerr_flags, fwd_rt->dest_addr,
						fwd_rt->dest_seqno);

				if (fwd_rt->nprec)
					aodv_socket_send((AODV_msg *) rerr,
							 dest,
							 RERR_CALC_SIZE(rerr),
							 1,
							 &DEV_IFINDEX(fwd_rt->
								      ifindex));
			}
		}
	} else {
		/* --- Here we FORWARD the RREP on the REVERSE route --- */
		if (rev_rt && rev_rt->state == VALID) {
			rrep_forward(rrep, rreplen, rev_rt, fwd_rt, --ip_ttl);
		} else {
			DEBUG(LOG_DEBUG, 0,
			      "Could not forward RREP - NO ROUTE!!!");
		}
	}

	if (!llfeedback && optimized_hellos)
		hello_start();
}