Exemplo n.º 1
0
void
uip_ds6_route_info_callback(uip_nd6_opt_route_info * rio,
                            uip_ip6addr_t * next_hop)
{
    PRINTF("RIO received\n");
    //TODO Preferences ?
    uip_ds6_route_t *found;

    if((found = uip_ds6_route_lookup(&rio->prefix)) == NULL
            && rio->rlifetime != 0) {
        //New route
        PRINTF("New route received\n");
        PRINTF("type=%d, flags=%d, length=%d, lifetime=%"PRIu32", Preflen=%d, prefix=",
               rio->type, rio->flagsreserved, rio->len, uip_ntohl(rio->rlifetime), rio->preflen);
        uip_ds6_route_t *new_route;

        if((new_route =
                    uip_ds6_route_add(&rio->prefix, rio->preflen, next_hop)) == NULL) {
            PRINTF("error when adding route\n");
        } else {
            PRINTF("Route added\n");
            new_route->state.lifetime = uip_ntohl(rio->rlifetime);
        }
    } else {
        PRINTF("Route already exists\n");
        if(rio->rlifetime == 0) {
            uip_ds6_route_rm(found);
        } else {
            found->state.lifetime = uip_ntohl(rio->rlifetime);
        }
    }
}
Exemplo n.º 2
0
/*---------------------------------------------------------------------------*/
static void
handle_incoming_rerr(void)
{
  struct uaodv_msg_rerr *rm = (struct uaodv_msg_rerr *)uip_appdata;
  struct uaodv_rt_entry *rt;

  print_debug("RERR %d.%d.%d.%d -> %d.%d.%d.%d"
	      " unreach=%d.%d.%d.%d seq=%lu\n",
	      uip_ipaddr_to_quad(&BUF->srcipaddr),
	      uip_ipaddr_to_quad(&BUF->destipaddr),
	      uip_ipaddr_to_quad((uip_ipaddr_t *)&rm->unreach[0]),
	      uip_ntohl(rm->unreach[0].seqno));

  if(uip_ipaddr_cmp(&rm->unreach[0].addr, &uip_hostaddr))
    return;

  rt = uaodv_rt_lookup_any(&rm->unreach[0].addr);
  if(rt != NULL && uip_ipaddr_cmp(&rt->nexthop, uip_udp_sender())) {
    if((rm->flags & UAODV_RERR_UNKNOWN) || rm->unreach[0].seqno == 0
       || SCMP32(rt->hseqno, uip_ntohl(rm->unreach[0].seqno)) <= 0) {
      rt->is_bad = 1;
      if(rm->flags & UAODV_RERR_UNKNOWN) {
	rm->flags &= ~UAODV_RERR_UNKNOWN;
	rm->unreach[0].seqno = uip_htonl(rt->hseqno);
      }
      print_debug("RERR rebroadcast\n");
      uip_udp_packet_send(bcastconn, rm, sizeof(struct uaodv_msg_rerr));
    }
  }
}
Exemplo n.º 3
0
/*---------------------------------------------------------------------------*/
struct uaodv_rt_entry *
uaodv_rt_add(uip_ipaddr_t *dest, uip_ipaddr_t *nexthop,
	     unsigned hop_count, const uint32_t *seqno)
{
  struct uaodv_rt_entry *e;

  /* Avoid inserting duplicate entries. */
  e = uaodv_rt_lookup_any(dest);
  if(e != NULL) {
    list_remove(route_table, e);    
  } else {
    /* Allocate a new entry or reuse the oldest. */
    e = memb_alloc(&route_mem);
    if(e == NULL) {
      e = list_chop(route_table); /* Remove oldest entry. */
    }
  }

  uip_ipaddr_copy(&e->dest, dest);
  uip_ipaddr_copy(&e->nexthop, nexthop);
  e->hop_count = hop_count;
  e->hseqno = uip_ntohl(*seqno);
  e->is_bad = 0;

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

  return e;
}
Exemplo n.º 4
0
/*---------------------------------------------------------------------------*/
static void
tcpip_handler(void)
{
  if(uip_newdata() && (uip_datalen()==48)) {
    CurrTime = uip_ntohl(((struct ntpformat *)uip_appdata)->seconds) - NTP_EPOCH;
    StartTime = clock_seconds();
  }
}
Exemplo n.º 5
0
/*---------------------------------------------------------------------------*/
static void
tcpip_handler(void)
{
  if(uip_newdata()) {
    count++;
    PRINTF("In: [0x%08lx], TTL %u, total %u\n",
        uip_ntohl((unsigned long) *((uint32_t *)(uip_appdata))),
        UIP_IP_BUF->ttl, count);
  }
  return;
}
Exemplo n.º 6
0
void time_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) {
    const uint8_t *payload = 0;
    size_t pay_len = REST.get_request_payload(request, &payload);

    if (payload && pay_len == 4) {
        uint32_t time;
        memcpy(&time, payload, 4);
        time = uip_ntohl(time);
        clock_set_seconds(time);
        REST.set_response_status(response, CHANGED_2_04);
    } else {
        REST.set_response_status(response, BAD_REQUEST_4_00);
        memcpy(buffer, "32 bit Unixzeit in Network-Byte-Order benötigt.", 48);
        REST.set_response_payload(response, buffer, 48);
    }
}
Exemplo n.º 7
0
/*---------------------------------------------------------------------------*/
static void
multicast_send(void)
{
  uint32_t id;

  id = uip_htonl(seq_id);
  memset(buf, 0, MAX_PAYLOAD_LEN);
  memcpy(buf, &id, sizeof(seq_id));

  PRINTF("Send to: ");
  PRINT6ADDR(&mcast_conn->ripaddr);
  PRINTF(" Remote Port %u,", uip_ntohs(mcast_conn->rport));
  PRINTF(" (msg=0x%08lx)", (unsigned long)uip_ntohl(*((uint32_t *)buf)));
  PRINTF(" %lu bytes\n", (unsigned long)sizeof(id));

  seq_id++;
  uip_udp_packet_send(mcast_conn, buf, sizeof(id));
}
Exemplo n.º 8
0
/*---------------------------------------------------------------------------*/
void ntp_adjust_time()
{
	struct ntp_msg *pkt;          // pointer to incomming packet
	/* timestamps for offset calculation */
	// t1 == ts
	//#ifdef REMOTE_HOST              // variables needed only for NTP unicast mode
	struct time_spec rects;       // t2

	struct time_spec xmtts;       // t3
	//#endif /* REMOTE_HOST */
	struct time_spec dstts;       // t4

	/* timestamp for local clock adjustment */
	struct time_spec adjts;

	if(uip_newdata()) {
		// get destination (t4) timestamp
		clock_get_time(&dstts);

		// check if received packet is complete
		if((uip_datalen() != NTP_MSGSIZE_NOAUTH) && (uip_datalen() != NTP_MSGSIZE)) {
			PRINTF("Received malformed NTP packet\n");
			return;
		}

		pkt = uip_appdata;

    // check if the server is synchronised
	/*#if 0 {                          // change to 1 for strict check
		if(((pkt->status & LI_ALARM) == LI_ALARM)
		   || (pkt->stratum > NTP_MAXSTRATUM) || (pkt->stratum == 0)
		   || ((pkt->xmttime.int_partl) == (uint32_t) 0))
	#else*/
		if((pkt->stratum > NTP_MAXSTRATUM) || (pkt->xmttime.int_partl) == (uint32_t) 0) {
	//#endif
			PRINTF("Received NTP packet from unsynchronised server\n");
			return;
		}

		/* Compute adjustment */
		if((pkt->status & MODEMASK) == MODE_BROADCAST)  {    // in broadcast mode compute time from xmt and dst
			PRINTF("MODE_BROADCAST\n");
			// local clock offset THETA = t3 - t4
			adjts.sec = (uip_ntohl(pkt->xmttime.int_partl) - JAN_1970) - dstts.sec;
			adjts.nsec = fractionl_to_nsec(uip_htonl(pkt->xmttime.fractionl)) - dstts.nsec;
		}
#ifdef BROADCAST_MODE             // if only NTP broadcast mode supported
		else {                      // in broadcast only mode, no other calcualtion is possible
			PRINTF("Received NTP non-broadcast mode message\n");
			return;
		}
#else
		else {                       // in client-server mode calculate local clock offset
			if(ts.sec != (uip_ntohl(pkt->orgtime.int_partl) - JAN_1970)) {
				PRINTF("Orgtime mismatch between received NTP packet and timestamp sent by us\n");
				return;
			}

			/* Compute local clock offset THETA = ((t2 - t1) + (t3 - t4)) / 2
			* for seconds part
			*/
			rects.sec = uip_htonl(pkt->rectime.int_partl) - JAN_1970;
			xmtts.sec = uip_htonl(pkt->xmttime.int_partl) - JAN_1970;
			adjts.sec = ((rects.sec - ts.sec) + (xmtts.sec - dstts.sec)) / 2;
			PRINTF("ts = %ld, rects = %ld, dstts = %ld, xmtts = %ld \n", ts.sec, rects.sec, dstts.sec, xmtts.sec);

			/* Compute local clock offset for fraction part */
			rects.nsec = fractionl_to_nsec(uip_htonl(pkt->rectime.fractionl));
			xmtts.nsec = fractionl_to_nsec(uip_htonl(pkt->xmttime.fractionl));

			/* Correct fraction parts if seconds are adjacent */
			if(adjts.sec == 0) {
			if(ts.sec < rects.sec)  // server received packet in other second
				ts.nsec -= 1000000000;
			if(xmtts.sec < dstts.sec)       // our client received packet in other second
				dstts.nsec += 1000000000;
			}
			adjts.nsec = ((rects.nsec - ts.nsec) + (xmtts.nsec - dstts.nsec)) / 2;
		}

		/* Set our timestamp to zero to avoid processing the same packet more than once */
		ts.sec = 0;
#endif 

		PRINTF("Local clock offset = %ld sec %ld nsec\n", adjts.sec, adjts.nsec);
		/* Set or adjust local clock */
		if(ABS(adjts.sec) >= ADJUST_THRESHOLD) {
			PRINTF("Setting the time to xmttime from server\n");
			clock_set_time(uip_ntohl(pkt->xmttime.int_partl) - JAN_1970,uip_ntohl(pkt->xmttime.fractionl));
		} else {
			//with ADJUST_THRESHOLD = 0, following code would never be touch
			PRINTF("Adjusting the time for %ld and %ld\n", adjts.sec, adjts.nsec);
			clock_adjust_time(&adjts);
		}
	}
Exemplo n.º 9
0
/*---------------------------------------------------------------------------*/
static void
handle_incoming_rrep(void)
{
  struct uaodv_msg_rrep *rm = (struct uaodv_msg_rrep *)uip_appdata;
  struct uaodv_rt_entry *rt;

  /* Useless HELLO message? */
  if(uip_ipaddr_cmp(&BUF->destipaddr, &uip_broadcast_addr)) {
#ifdef AODV_RESPOND_TO_HELLOS
    uint32_t net_seqno;
#ifdef CC2420_RADIO
    int ret = cc2420_check_remote(uip_udp_sender()->u16[1]);

    if(ret == REMOTE_YES) {
      print_debug("HELLO drop is remote\n");
      return;
    } else if (ret == REMOTE_NO) {
      /* Is neigbour, accept it. */
    } else if(cc2420_last_rssi < RSSI_THRESHOLD) {
      print_debug("HELLO drop %d %d\n", cc2420_last_rssi, cc2420_last_correlation);
      return;
    }
#endif
    /* Sometimes it helps to send a non-requested RREP in response! */
    net_seqno = uip_htonl(my_hseqno);
    send_rrep(&uip_hostaddr, &BUF->srcipaddr, &BUF->srcipaddr, &net_seqno, 0);
#endif
    return;
  }

  print_debug("RREP %d.%d.%d.%d -> %d.%d.%d.%d"
	      " dest=%d.%d.%d.%d seq=%lu hops=%u orig=%d.%d.%d.%d\n",
	      uip_ipaddr_to_quad(&BUF->srcipaddr),
	      uip_ipaddr_to_quad(&BUF->destipaddr),
	      uip_ipaddr_to_quad(&rm->dest_addr), uip_ntohl(rm->dest_seqno),
	      rm->hop_count,
	      uip_ipaddr_to_quad(&rm->orig_addr));

  rt = uaodv_rt_lookup(&rm->dest_addr);

  /* New forward route? */
  if(rt == NULL || (SCMP32(uip_ntohl(rm->dest_seqno), rt->hseqno) > 0)) {
    print_debug("Inserting3\n");
    rt = uaodv_rt_add(&rm->dest_addr, uip_udp_sender(),
		      rm->hop_count, &rm->dest_seqno);
#ifdef CC2420_RADIO
    /* This link is ok since he is unicasting back to us! */
    cc2420_recv_ok(uip_udp_sender());
    print_debug("RREP recv ok %d %d\n",
		cc2420_last_rssi, cc2420_last_correlation);
#endif
  } else {
    print_debug("Not inserting\n");
  }

  /* Forward RREP towards originator? */
  if(uip_ipaddr_cmp(&rm->orig_addr, &uip_hostaddr)) {
    print_debug("ROUTE FOUND\n");
    if(rm->flags & UAODV_RREP_ACK) {
      struct uaodv_msg_rrep_ack *ack = (void *)uip_appdata;
      ack->type = UAODV_RREP_ACK_TYPE;
      ack->reserved = 0;
      sendto(uip_udp_sender(), ack, sizeof(*ack));
    }
  } else {
    rt = uaodv_rt_lookup(&rm->orig_addr);

    if(rt == NULL) {
      print_debug("RREP received, but no route back to originator... :-( \n");
      return;
    }

    if(rm->flags & UAODV_RREP_ACK) {
      print_debug("RREP with ACK request (ignored)!\n");
      /* Don't want any RREP-ACKs in return! */
      rm->flags &= ~UAODV_RREP_ACK;
    }

    rm->hop_count++;

    print_debug("Fwd RREP to %d.%d.%d.%d\n", uip_ipaddr_to_quad(&rt->nexthop));

    sendto(&rt->nexthop, rm, sizeof(struct uaodv_msg_rrep));
  }
}
Exemplo n.º 10
0
/*---------------------------------------------------------------------------*/
static void
handle_incoming_rreq(void)
{
  struct uaodv_msg_rreq *rm = (struct uaodv_msg_rreq *)uip_appdata;
  uip_ipaddr_t dest_addr, orig_addr;
  struct uaodv_rt_entry *rt, *fw = NULL;
  
  print_debug("RREQ %d.%d.%d.%d -> %d.%d.%d.%d ttl=%u"
	      " orig=%d.%d.%d.%d seq=%lu hops=%u dest=%d.%d.%d.%d seq=%lu\n",
	      uip_ipaddr_to_quad(&BUF->srcipaddr),
	      uip_ipaddr_to_quad(&BUF->destipaddr),
	      BUF->ttl,
	      uip_ipaddr_to_quad(&rm->orig_addr), uip_ntohl(rm->orig_seqno),
	      rm->hop_count,
	      uip_ipaddr_to_quad(&rm->dest_addr), uip_ntohl(rm->dest_seqno));

  if(uip_ipaddr_cmp(&rm->orig_addr, &uip_hostaddr)) {
    return;			/* RREQ looped back! */
  }

#ifdef CC2420_RADIO
 {
   int ret = cc2420_check_remote(uip_udp_sender()->u16[1]);

   if(ret == REMOTE_YES) {
     print_debug("RREQ drop is remote\n");
     return;
   } else if (ret == REMOTE_NO) {
     /* Is neigbour, accept it. */
   } else if(cc2420_last_rssi < RSSI_THRESHOLD) {
     print_debug("RREQ drop %d %d\n", cc2420_last_rssi,
		 cc2420_last_correlation);
     return;
   }
 }
#endif

#ifdef AODV_BAD_HOP_EXTENSION
  if(uip_len > (sizeof(*rm) + 2)) {
    struct uaodv_bad_hop_ext *ext = (void *)(uip_appdata + sizeof(*rm));
    uint8_t *end = uip_appdata + uip_len;
    for(;
	(uint8_t *)ext < end;
	ext = (void *)((uint8_t *)ext + ext->length + 2)) {
      uint8_t *eend = (uint8_t *)ext + ext->length;
      if(eend > end)
	eend = end;

      if(ext->type == RREQ_BAD_HOP_EXT) {
	uip_ipaddr_t *a;
	for(a = ext->addrs; (uint8_t *)a < eend; a++) {
	  if(uip_ipaddr_cmp(a, &uip_hostaddr)) {
	    print_debug("BAD_HOP drop\n");
	    return;
	  }
	}
      }
    }
  }
#endif /* AODV_BAD_HOP_EXTENSION */

  /* New reverse route? */
  rt = uaodv_rt_lookup(&rm->orig_addr);
  if(rt == NULL
     || (SCMP32(uip_ntohl(rm->orig_seqno), rt->hseqno) > 0) /* New route. */
     || (SCMP32(uip_ntohl(rm->orig_seqno), rt->hseqno) == 0
	 && rm->hop_count < rt->hop_count)) { /* Better route. */
    print_debug("Inserting1\n");
    rt = uaodv_rt_add(&rm->orig_addr, uip_udp_sender(),
		      rm->hop_count, &rm->orig_seqno);
  }
    
  /* Check if it is for our address or a fresh route. */
  if(uip_ipaddr_cmp(&rm->dest_addr, &uip_hostaddr)
     || rm->flags & UAODV_RREQ_DESTONLY) {
    fw = NULL;
  } else {
    fw = uaodv_rt_lookup(&rm->dest_addr);
    if(!(rm->flags & UAODV_RREQ_UNKSEQNO)
       && fw != NULL
       && SCMP32(fw->hseqno, uip_ntohl(rm->dest_seqno)) <= 0) {
      fw = NULL;
    }
  }

  if (fw != NULL) {
    uint32_t net_seqno;

    print_debug("RREQ for known route\n");
    uip_ipaddr_copy(&dest_addr, &rm->dest_addr);
    uip_ipaddr_copy(&orig_addr, &rm->orig_addr);
    net_seqno = uip_htonl(fw->hseqno);
    send_rrep(&dest_addr, &rt->nexthop, &orig_addr, &net_seqno,
	      fw->hop_count + 1);
  } else if(uip_ipaddr_cmp(&rm->dest_addr, &uip_hostaddr)) {
    uint32_t net_seqno;

    print_debug("RREQ for our address\n");
    uip_ipaddr_copy(&dest_addr, &rm->dest_addr);
    uip_ipaddr_copy(&orig_addr, &rm->orig_addr);

    my_hseqno++;
    if(!(rm->flags & UAODV_RREQ_UNKSEQNO)
       && SCMP32(my_hseqno, uip_ntohl(rm->dest_seqno)) < 0) {
      print_debug("New my_hseqno %lu\n", my_hseqno); /* We have rebooted. */
      my_hseqno = uip_ntohl(rm->dest_seqno) + 1;
    }
    net_seqno = uip_htonl(my_hseqno);
    send_rrep(&dest_addr, &rt->nexthop, &orig_addr, &net_seqno, 0);
  } else if(BUF->ttl > 1) {
    int len;

    /* Have we seen this RREQ before? */
    if(fwc_lookup(&rm->orig_addr, &rm->rreq_id)) {
      print_debug("RREQ cached, not fwd\n");
      return;
    }
    fwc_add(&rm->orig_addr, &rm->rreq_id);

    print_debug("RREQ fwd\n");
    rm->hop_count++;
    bcastconn->ttl = BUF->ttl - 1;
    len = sizeof(struct uaodv_msg_rreq);
    len += add_rreq_extensions(rm + 1);
    uip_udp_packet_send(bcastconn, rm, len);
  }
}
Exemplo n.º 11
0
/*
 * Process a Router Advertisement
 *
 * - Possible actions when receiving a RA: add router to router list,
 *   recalculate reachable time, update link hop limit, update retrans timer.
 * - If MTU option: update MTU.
 * - If SLLAO option: update entry in neighbor cache
 * - If prefix option: start autoconf, add prefix to prefix list
 */
void
ra_input(void)
{
  PRINTF("Received RA from");
  PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
  PRINTF("to");
  PRINT6ADDR(&UIP_IP_BUF->destipaddr);
  PRINTF("\n");
  UIP_STAT(++uip_stat.nd6.recv);

#if UIP_CONF_IPV6_CHECKS
  if((UIP_IP_BUF->ttl != UIP_ND6_HOP_LIMIT) ||
     (!uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) ||
     (UIP_ICMP_BUF->icode != 0)) {
    PRINTF("RA received is bad");
    goto discard;
  }
#endif /*UIP_CONF_IPV6_CHECKS */

  if(UIP_ND6_RA_BUF->cur_ttl != 0) {
    uip_ds6_if.cur_hop_limit = UIP_ND6_RA_BUF->cur_ttl;
    PRINTF("uip_ds6_if.cur_hop_limit %u\n", uip_ds6_if.cur_hop_limit);
  }

  if(UIP_ND6_RA_BUF->reachable_time != 0) {
    if(uip_ds6_if.base_reachable_time !=
       uip_ntohl(UIP_ND6_RA_BUF->reachable_time)) {
      uip_ds6_if.base_reachable_time = uip_ntohl(UIP_ND6_RA_BUF->reachable_time);
      uip_ds6_if.reachable_time = uip_ds6_compute_reachable_time();
    }
  }
  if(UIP_ND6_RA_BUF->retrans_timer != 0) {
    uip_ds6_if.retrans_timer = uip_ntohl(UIP_ND6_RA_BUF->retrans_timer);
  }

  /* Options processing */
  nd6_opt_offset = UIP_ND6_RA_LEN;
  while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
    if(UIP_ND6_OPT_HDR_BUF->len == 0) {
      PRINTF("RA received is bad");
      goto discard;
    }
    switch (UIP_ND6_OPT_HDR_BUF->type) {
    case UIP_ND6_OPT_SLLAO:
      PRINTF("Processing SLLAO option in RA\n");
      nd6_opt_llao = (uint8_t *) UIP_ND6_OPT_HDR_BUF;
      nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
      if(nbr == NULL) {
        nbr = uip_ds6_nbr_add(&UIP_IP_BUF->srcipaddr,
                              (uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
			      1, NBR_STALE);
      } else {
        uip_lladdr_t *lladdr = uip_ds6_nbr_get_ll(nbr);
        if(nbr->state == NBR_INCOMPLETE) {
          nbr->state = NBR_STALE;
        }
        if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
		  lladdr, UIP_LLADDR_LEN) != 0) {
          memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
		 UIP_LLADDR_LEN);
          nbr->state = NBR_STALE;
        }
        nbr->isrouter = 1;
      }
      break;
    case UIP_ND6_OPT_MTU:
      PRINTF("Processing MTU option in RA\n");
      uip_ds6_if.link_mtu =
        uip_ntohl(((uip_nd6_opt_mtu *) UIP_ND6_OPT_HDR_BUF)->mtu);
      break;
    case UIP_ND6_OPT_PREFIX_INFO:
      PRINTF("Processing PREFIX option in RA\n");
      nd6_opt_prefix_info = (uip_nd6_opt_prefix_info *) UIP_ND6_OPT_HDR_BUF;
      if((uip_ntohl(nd6_opt_prefix_info->validlt) >=
          uip_ntohl(nd6_opt_prefix_info->preferredlt))
         && (!uip_is_addr_link_local(&nd6_opt_prefix_info->prefix))) {
        /* on-link flag related processing */
        if(nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_ONLINK) {
          prefix =
            uip_ds6_prefix_lookup(&nd6_opt_prefix_info->prefix,
                                  nd6_opt_prefix_info->preflen);
          if(prefix == NULL) {
            if(nd6_opt_prefix_info->validlt != 0) {
              if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) {
                prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
                                            nd6_opt_prefix_info->preflen,
                                            uip_ntohl(nd6_opt_prefix_info->
                                                  validlt));
              } else {
                prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
                                            nd6_opt_prefix_info->preflen, 0);
              }
            }
          } else {
            switch (nd6_opt_prefix_info->validlt) {
            case 0:
              uip_ds6_prefix_rm(prefix);
              break;
            case UIP_ND6_INFINITE_LIFETIME:
              prefix->isinfinite = 1;
              break;
            default:
              PRINTF("Updating timer of prefix");
              PRINT6ADDR(&prefix->ipaddr);
              PRINTF("new value %lu\n", uip_ntohl(nd6_opt_prefix_info->validlt));
              stimer_set(&prefix->vlifetime,
                         uip_ntohl(nd6_opt_prefix_info->validlt));
              prefix->isinfinite = 0;
              break;
            }
          }
        }
        /* End of on-link flag related processing */
        /* autonomous flag related processing */
        if((nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_AUTONOMOUS)
           && (nd6_opt_prefix_info->validlt != 0)
           && (nd6_opt_prefix_info->preflen == UIP_DEFAULT_PREFIX_LEN)) {
	  
          uip_ipaddr_copy(&ipaddr, &nd6_opt_prefix_info->prefix);
          uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
          addr = uip_ds6_addr_lookup(&ipaddr);
          if((addr != NULL) && (addr->type == ADDR_AUTOCONF)) {
            if(nd6_opt_prefix_info->validlt != UIP_ND6_INFINITE_LIFETIME) {
              /* The processing below is defined in RFC4862 section 5.5.3 e */
              if((uip_ntohl(nd6_opt_prefix_info->validlt) > 2 * 60 * 60) ||
                 (uip_ntohl(nd6_opt_prefix_info->validlt) >
                  stimer_remaining(&addr->vlifetime))) {
                PRINTF("Updating timer of address");
                PRINT6ADDR(&addr->ipaddr);
                PRINTF("new value %lu\n",
                       uip_ntohl(nd6_opt_prefix_info->validlt));
                stimer_set(&addr->vlifetime,
                           uip_ntohl(nd6_opt_prefix_info->validlt));
              } else {
                stimer_set(&addr->vlifetime, 2 * 60 * 60);
                PRINTF("Updating timer of address ");
                PRINT6ADDR(&addr->ipaddr);
                PRINTF("new value %lu\n", (unsigned long)(2 * 60 * 60));
              }
              addr->isinfinite = 0;
            } else {
              addr->isinfinite = 1;
            }
          } else {
            if(uip_ntohl(nd6_opt_prefix_info->validlt) ==
               UIP_ND6_INFINITE_LIFETIME) {
              uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
            } else {
              uip_ds6_addr_add(&ipaddr, uip_ntohl(nd6_opt_prefix_info->validlt),
                               ADDR_AUTOCONF);
            }
          }
        }
        /* End of autonomous flag related processing */
      }
      break;
    default:
      PRINTF("ND option not supported in RA");
      break;
    }
    nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
  }

  defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr);
  if(UIP_ND6_RA_BUF->router_lifetime != 0) {
    if(nbr != NULL) {
      nbr->isrouter = 1;
    }
    if(defrt == NULL) {
      uip_ds6_defrt_add(&UIP_IP_BUF->srcipaddr,
                        (unsigned
                         long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime)));
    } else {
      stimer_set(&(defrt->lifetime),
                 (unsigned long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime)));
    }
  } else {
    if(defrt != NULL) {
      uip_ds6_defrt_rm(defrt);
    }
  }

#if UIP_CONF_IPV6_QUEUE_PKT
  /* If the nbr just became reachable (e.g. it was in NBR_INCOMPLETE state
   * and we got a SLLAO), check if we had buffered a pkt for it */
  /*  if((nbr != NULL) && (nbr->queue_buf_len != 0)) {
    uip_len = nbr->queue_buf_len;
    memcpy(UIP_IP_BUF, nbr->queue_buf, uip_len);
    nbr->queue_buf_len = 0;
    return;
    }*/
  if(nbr != NULL && uip_packetqueue_buflen(&nbr->packethandle) != 0) {
    uip_len = uip_packetqueue_buflen(&nbr->packethandle);
    memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
    uip_packetqueue_free(&nbr->packethandle);
    return;
  }

#endif /*UIP_CONF_IPV6_QUEUE_PKT */

discard:
  uip_len = 0;
  return;
}