dao_ack_input(void)
{
#if RPL_WITH_DAO_ACK

  uint8_t *buffer;
  uint8_t instance_id;
  uint8_t sequence;
  uint8_t status;
  rpl_instance_t *instance;
  rpl_parent_t *parent;

  buffer = UIP_ICMP_PAYLOAD;

  instance_id = buffer[0];
  sequence = buffer[2];
  status = buffer[3];

  instance = rpl_get_instance(instance_id);
  if(instance == NULL) {
    uipbuf_clear();
    return;
  }

  if(RPL_IS_STORING(instance)) {
    parent = rpl_find_parent(instance->current_dag, &UIP_IP_BUF->srcipaddr);
    if(parent == NULL) {
      /* not a known instance - drop the packet and ignore */
      uipbuf_clear();
      return;
    }
  } else {
    parent = NULL;
  }

  if(instance->current_dag->rank == ROOT_RANK(instance)) {
    LOG_DBG("DODAG root received a DAO ACK, ignoring it\n");
    uipbuf_clear();
    return;
  }

  LOG_INFO("Received a DAO %s with sequence number %d (%d) and status %d from ",
         status < 128 ? "ACK" : "NACK",
         sequence, instance->my_dao_seqno, status);
  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
  LOG_INFO_("\n");

  if(sequence == instance->my_dao_seqno) {
    instance->has_downward_route = status < 128;

    /* always stop the retransmit timer when the ACK arrived */
    ctimer_stop(&instance->dao_retransmit_timer);

    /* Inform objective function on status of the DAO ACK */
    if(RPL_IS_STORING(instance) && instance->of->dao_ack_callback) {
      instance->of->dao_ack_callback(parent, status);
    }

#if RPL_REPAIR_ON_DAO_NACK
    if(status >= RPL_DAO_ACK_UNABLE_TO_ACCEPT) {
      /*
       * Failed the DAO transmission - need to remove the default route.
       * Trigger a local repair since we can not get our DAO in.
       */
      rpl_local_repair(instance);
    }
#endif

  } else if(RPL_IS_STORING(instance)) {
    /* this DAO ACK should be forwarded to another recently registered route */
    uip_ds6_route_t *re;
    const uip_ipaddr_t *nexthop;
    if((re = find_route_entry_by_dao_ack(sequence)) != NULL) {
      /* pick the recorded seq no from that node and forward DAO ACK - and
         clear the pending flag*/
      RPL_ROUTE_CLEAR_DAO_PENDING(re);

      nexthop = uip_ds6_route_nexthop(re);
      if(nexthop == NULL) {
        LOG_WARN("No next hop to fwd DAO ACK to\n");
      } else {
        LOG_INFO("Fwd DAO ACK to:");
        LOG_INFO_6ADDR(nexthop);
        LOG_INFO_("\n");
        buffer[2] = re->state.dao_seqno_in;
        uip_icmp6_send(nexthop, ICMP6_RPL, RPL_CODE_DAO_ACK, 4);
      }

      if(status >= RPL_DAO_ACK_UNABLE_TO_ACCEPT) {
        /* this node did not get in to the routing tables above... - remove */
        uip_ds6_route_rm(re);
      }
    } else {
      LOG_WARN("No route entry found to forward DAO ACK (seqno %u)\n", sequence);
    }
  }
#endif /* RPL_WITH_DAO_ACK */
  uipbuf_clear();
}
dao_ack_input(void)
{
#if RPL_WITH_DAO_ACK

  uint8_t *buffer;
  uint8_t instance_id;
  uint8_t sequence;
  uint8_t status;
  rpl_instance_t *instance;
  rpl_parent_t *parent;

  buffer = UIP_ICMP_PAYLOAD;

  instance_id = buffer[0];
  sequence = buffer[2];
  status = buffer[3];

  instance = rpl_get_instance(instance_id);
  if(instance == NULL) {
    uipbuf_clear();
    return;
  }

  if(RPL_IS_STORING(instance)) {
    parent = rpl_find_parent(instance->current_dag, &UIP_IP_BUF->srcipaddr);
    if(parent == NULL) {
       
      uipbuf_clear();
      return;
    }
  } else {
    parent = NULL;
  }

  if(instance->current_dag->rank == ROOT_RANK(instance)) {
    LOG_DBG("DODAG root received a DAO ACK, ignoring it\n");
    uipbuf_clear();
    return;
  }

  LOG_INFO("Received a DAO %s with sequence number %d (%d) and status %d from ",
         status < 128 ? "ACK" : "NACK",
         sequence, instance->my_dao_seqno, status);
  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
  LOG_INFO_("\n");

  if(sequence == instance->my_dao_seqno) {
    instance->has_downward_route = status < 128;

     
    ctimer_stop(&instance->dao_retransmit_timer);

     
    if(RPL_IS_STORING(instance) && instance->of->dao_ack_callback) {
      instance->of->dao_ack_callback(parent, status);
    }

#if RPL_REPAIR_ON_DAO_NACK
    if(status >= RPL_DAO_ACK_UNABLE_TO_ACCEPT) {
       
      rpl_local_repair(instance);
    }
#endif

  } else if(RPL_IS_STORING(instance)) {
     
    uip_ds6_route_t *re;
    const uip_ipaddr_t *nexthop;
    if((re = find_route_entry_by_dao_ack(sequence)) != NULL) {
       
      RPL_ROUTE_CLEAR_DAO_PENDING(re);

      nexthop = uip_ds6_route_nexthop(re);
      if(nexthop == NULL) {
        LOG_WARN("No next hop to fwd DAO ACK to\n");
      } else {
        LOG_INFO("Fwd DAO ACK to:");
        LOG_INFO_6ADDR(nexthop);
        LOG_INFO_("\n");
        buffer[2] = re->state.dao_seqno_in;
        uip_icmp6_send(nexthop, ICMP6_RPL, RPL_CODE_DAO_ACK, 4);
      }

      if(status >= RPL_DAO_ACK_UNABLE_TO_ACCEPT) {
         
        uip_ds6_route_rm(re);
      }
    } else {
      LOG_WARN("No route entry found to forward DAO ACK (seqno %u)\n", sequence);
    }
  }
#endif  
  uipbuf_clear();
}