예제 #1
0
int rrep_add_hello_ext(RREP * rrep, int offset, u_int32_t interval)
{
    AODV_ext *ext;

    ext = (AODV_ext *) ((char *) rrep + RREP_SIZE + offset);
    ext->type = RREP_HELLO_INTERVAL_EXT;
    ext->length = sizeof(interval);
    memcpy(AODV_EXT_DATA(ext), &interval, sizeof(interval));

    return (offset + AODV_EXT_SIZE(ext));
}
예제 #2
0
AODV_ext *NS_CLASS rrep_add_ext(RREP * rrep, int type, unsigned int offset,
				int len, char *data)
{
	AODV_ext *ext = NULL;

	if (offset < RREP_SIZE)
		return NULL;

	ext = (AODV_ext *) ((char *)rrep + offset);

	ext->type = type;
	ext->length = len;

	memcpy(AODV_EXT_DATA(ext), data, len);

	return ext;
}
예제 #3
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;
}
예제 #4
0
/**
 * send a hello packet
 * 
 * @param arg not used!
 */
void aodv_hello_send (void *arg)
{
  int i, j;
  struct pbuf *p;
  struct in_addr addr;
  struct in_addr dest_broadcast;
  
  struct aodv_ext *ext = NULL;
  u16_t ext_size = 0;
  
  if (aodv_wait_on_reboot_get()) {
    goto __reset_timer;
  }
  
  /* RFC3561
   *
   * dest ip    == local ip
   * dest seqno == aodv_host_state.seqno
   * hops       == 0
   * lifetime   == ALLOWED_HELLO_LOSS * HELLO_INTERVAL
   *  
   */
  dest_broadcast.s_addr = INADDR_BROADCAST; /* broadcast */
  
#if AODV_HELLO_NEIGHBOR
  /* extension which contain our neighbor set */
  for (j = 0; j < AODV_RT_TABLESIZE; j++) {
    struct aodv_rtnode *rt;
    for (rt  = aodv_rt_tbl.hash_tbl[j];
         rt != NULL;
         rt  = rt->next) {
      /* If an entry has an active hello timer, we assume
         that we are receiving hello messages from that
         node... */
      if (__AODV_TIMER_ISINQ(&rt->hello_timer)) {
        ext_size += sizeof(struct in_addr);
        if (ext_size >= 252) { /* max save 63 node */
          break;
        }
      }
    }
  }
  
  if (ext_size) { /* have RREP_HELLO_NEIGHBOR_SET_EXT extern */
    ext_size += AODV_EXT_HDR_SIZE;
  }
#else
  (void)j; /* no warning */
#endif /* AODV_HELLO_NEIGHBOR */
  
  /* extension which contain hello interval */
  ext_size += (AODV_EXT_HDR_SIZE + 4);
  
  /* TODO: in lwip broadcast packet is always used defaute netif output, 
   * so adov netif must be default one! 
   */
  for (i = 0; i < AODV_MAX_NETIF; i++) {
    if (aodv_netif[i]) {
      addr.s_addr = aodv_netif[i]->ip_addr.addr;
      p = aodv_rrep_create(0, 0, 0, &addr, aodv_host_state.seqno, &addr, 
                           ALLOWED_HELLO_LOSS * HELLO_INTERVAL, ext_size, NULL);
      if (p) {
        u32_t interval = htonl(HELLO_INTERVAL);
        struct aodv_rrep *rrep = (struct aodv_rrep *)p->payload;
        
        ext = (struct aodv_ext *)((char *)rrep + RREP_SIZE);
        
#if AODV_HELLO_NEIGHBOR
        ext->type = RREP_HELLO_NEIGHBOR_SET_EXT;
        ext->length = 0;
        
        /* Assemble a RREP extension which contain our neighbor set... */
        for (j = 0; j < AODV_RT_TABLESIZE; j++) {
          struct aodv_rtnode *rt;
          for (rt  = aodv_rt_tbl.hash_tbl[j];
               rt != NULL;
               rt  = rt->next) {
            if (__AODV_TIMER_ISINQ(&rt->hello_timer)) {
              memcpy((AODV_EXT_DATA(ext) + ext->length),
                     &rt->dest_addr, sizeof(struct in_addr));
              ext->length += sizeof(struct in_addr);
              if (ext->length >= 252) { /* max save 63 node */
                break;
              }
            }
          }
        }
        
        /* add hello interval extern */
        if (ext->length != 0) { /* have RREP_HELLO_NEIGHBOR_SET_EXT extern */
          ext = AODV_EXT_NEXT(ext);
        }
#endif /* AODV_HELLO_NEIGHBOR */
        
        ext->type = RREP_HELLO_INTERVAL_EXT;
        ext->length = 4;
        memcpy(AODV_EXT_DATA(ext), &interval, 4);
        
        aodv_udp_sendto(p, &dest_broadcast, 1, i);
        pbuf_free(p);
      }
    }
  }
  
__reset_timer:
  aodv_timer_set_timeout(&hello_timer, HELLO_INTERVAL + HELLO_RAND());
}
예제 #5
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();
}