Beispiel #1
0
/*---------------------------------------------------------------------------*/
void
uip_ds6_send_rs(void)
{
#if CONF_6LOWPAN_ND
  uint16_t r;
#endif /* CONF_6LOWPAN_ND */

  if((uip_ds6_defrt_choose() == NULL)
     && (rscount < UIP_ND6_MAX_RTR_SOLICITATIONS)) {
    PRINTF("Sending RS %u\n", rscount);
    uip_nd6_rs_output();
    rscount++;
    etimer_set(&uip_ds6_timer_rs,
               UIP_ND6_RTR_SOLICITATION_INTERVAL * CLOCK_SECOND);
#if CONF_6LOWPAN_ND
  } else if(uip_ds6_defrt_choose() == NULL) {
    /* Slower retransmissions */
    PRINTF("Sending RS slower %u\n", rscount);
    uip_nd6_rs_output();
    rscount++;
    r = (((uint16_t)random_rand()) % ((2 << (rscount - 1) - 1) + 1)) * UIP_ND6_RTR_SOLICITATION_INTERVAL;
    if(r >= UIP_ND6_MAX_RTR_SOLICITATION_INTERVAL) {
      r = UIP_ND6_MAX_RTR_SOLICITATION_INTERVAL;
    }
    etimer_set(&uip_ds6_timer_rs, r * CLOCK_SECOND);
#endif /* CONF_6LOWPAN_ND */
  } else {
    PRINTF("Router found ? (boolean): %u\n",
           (uip_ds6_defrt_choose() != NULL));
    etimer_stop(&uip_ds6_timer_rs);
  }
  return;
}
Beispiel #2
0
/*---------------------------------------------------------------------------*/
void
uip_ds6_send_rs(void)
{
  if((uip_ds6_defrt_choose() == NULL)
     && (rscount < UIP_ND6_MAX_RTR_SOLICITATIONS)) {
    PRINTF("Sending RS %u\n", rscount);
    uip_nd6_rs_output();
    rscount++;
    etimer_set(&uip_ds6_timer_rs,
               UIP_ND6_RTR_SOLICITATION_INTERVAL * CLOCK_SECOND);
  } else {
    PRINTF("Router found ? (boolean): %u\n",
           (uip_ds6_defrt_choose() != NULL));
    etimer_stop(&uip_ds6_timer_rs);
  }
  return;
}
Beispiel #3
0
/*---------------------------------------------------------------------------*/
static void
echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data,
                   uint16_t datalen)
{
    if(uip_ip6addr_cmp(source, uip_ds6_defrt_choose())) {
        def_rt_rssi = sicslowpan_get_last_rssi();
    }
}
Beispiel #4
0
/* Useful for debugging so allow external calls */
void
raven_ping6(void)
{
#define PING_GOOGLE 0

    UIP_IP_BUF->vtc = 0x60;
    UIP_IP_BUF->tcflow = 1;
    UIP_IP_BUF->flow = 0;
    UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
	UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit;
#if PING_GOOGLE
    if (seqno==1) {
	   uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose());   //the default router
	} else if (seqno==2) {
	   uip_ip6addr(&UIP_IP_BUF->destipaddr,0x2001,0x4860,0x800f,0x0000,0x0000,0x0000,0x0000,0x0093);  //ipv6.google.com
	} else if (seqno==3) {
	   uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose());   //the default router
	} else {
//	   uip_ip6addr(&UIP_IP_BUF->destipaddr,0x2001,0x0420,0x5FFF,0x007D,0x02D0,0xB7FF,0xFE23,0xE6DB);  //?.cisco.com
	   uip_ip6addr(&UIP_IP_BUF->destipaddr,0x2001,0x0420,0x0000,0x0010,0x0250,0x8bff,0xfee8,0xf800);  //six.cisco.com
	}	
#else
	  uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, uip_ds6_defrt_choose());    //the default router
#endif

    uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
    UIP_ICMP_BUF->type = ICMP6_ECHO_REQUEST;
    UIP_ICMP_BUF->icode = 0;
    /* set identifier and sequence number to 0 */
    memset((void *)UIP_ICMP_BUF + UIP_ICMPH_LEN, 0, 4);
    /* put one byte of data */
    memset((void *)UIP_ICMP_BUF + UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN,
           count, PING6_DATALEN);
     
    
    uip_len = UIP_ICMPH_LEN + UIP_ICMP6_ECHO_REQUEST_LEN + UIP_IPH_LEN + PING6_DATALEN;
    UIP_IP_BUF->len[0] = (uint8_t)((uip_len - 40) >> 8);
    UIP_IP_BUF->len[1] = (uint8_t)((uip_len - 40) & 0x00FF);
    
    UIP_ICMP_BUF->icmpchksum = 0;
    UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
   
    
    tcpip_ipv6_output();
}
Beispiel #5
0
/*---------------------------------------------------------------------------*/
static void
ping_parent(void)
{
    if(uip_ds6_get_global(ADDR_PREFERRED) == NULL) {
        return;
    }

    uip_icmp6_send(uip_ds6_defrt_choose(), ICMP6_ECHO_REQUEST, 0,
                   CC26XX_WEB_DEMO_ECHO_REQ_PAYLOAD_LEN);
}
Beispiel #6
0
void
uip_ds6_send_rs(uip_ds6_defrt_t *defrt)
{
  u8_t unicast_rs = 0;

	if (!timer_expired(&uip_ds6_timer_rs)) {
		return;
	}
	locdefrt = NULL;
	/* First check whether we can unicast the RS to a specific router rather than
	 * multicasting it. */
	if ((defrt != NULL) && (defrt->isused)){
	  /* Mark this router as "sending_rs" in case it wasn't marked already */
	  defrt->sending_rs = 1;
	  locdefrt = defrt;
	  unicast_rs = 1;
  } else {
    for(locdefrt = uip_ds6_defrt_list;
        locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) {
      if((locdefrt->isused) && (locdefrt->sending_rs)) {
        unicast_rs = 1;
        break;
      }
    }
  }

	if (unicast_rs) {
    if (locdefrt->rscount < UIP_ND6_MAX_RTR_SOLICITATIONS) {
      /* Unicast RS and update count and timer */
      uip_nd6_rs_output(&locdefrt->ipaddr);
      locdefrt->rscount = locdefrt->rscount > 10 ? locdefrt->rscount : locdefrt->rscount + 1;
      timer_set(&uip_ds6_timer_rs, rs_rtx_time(locdefrt->rscount) * CLOCK_SECOND);
      return;
    } else {
      /* Switch to multicast */
      locdefrt->sending_rs = 0;
      rscount = locdefrt->rscount;
      locdefrt->rscount = 0;
    }
	}
	/* Multicast RS and update RS count and timer */
	uip_nd6_rs_output(NULL);
	if(uip_ds6_defrt_choose() == NULL) {
	 	rscount = rscount > 10 ? rscount : rscount + 1;
	} else {
   	rscount = 0;
  }
  /* Make sure we do not send rs more frequently than UIP_ND6_RTR_SOLICITATION_INTERVAL */
	timer_set(&uip_ds6_timer_rs, rs_rtx_time(rscount) * CLOCK_SECOND);
}
/*---------------------------------------------------------------------------*/
static void
print_network_status(void)
{
  int i;
  uint8_t state;
  uip_ds6_defrt_t *default_route;
  uip_ds6_route_t *route;

  PRINTA("--- Network status ---\n");
  
  /* Our IPv6 addresses */
  PRINTA("- Server IPv6 addresses:\n");
  for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
    state = uip_ds6_if.addr_list[i].state;
    if(uip_ds6_if.addr_list[i].isused &&
       (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) {
      PRINTA("-%d- ",i);
      uip_debug_ipaddr_print(&uip_ds6_if.addr_list[i].ipaddr);
      PRINTA("\n");
    }
  }
  
  /* Our default route */
  PRINTA("- Default route:\n");
  default_route = uip_ds6_defrt_lookup(uip_ds6_defrt_choose());
  if(default_route != NULL) {
    PRINTA("-- ");
    uip_debug_ipaddr_print(&default_route->ipaddr);;
    PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)default_route->lifetime.interval);
  } else {
    PRINTA("-- None\n");
  }

  /* Our routing entries */
  PRINTA("- Routing entries (%u in total):\n", uip_ds6_route_num_routes());
  route = uip_ds6_route_head();
  while(route != NULL) {
    PRINTA("-- ");
    uip_debug_ipaddr_print(&route->ipaddr);
    PRINTA(" via ");
    uip_debug_ipaddr_print(uip_ds6_route_nexthop(route));
    PRINTA(" (lifetime: %lu seconds)\n", (unsigned long)route->state.lifetime);
    route = uip_ds6_route_next(route); 
  }
  
  PRINTA("----------------------\n");
}
Beispiel #8
0
void
tcpip_ipv6_output(void)
{
    uip_ds6_nbr_t *nbr = NULL;
    uip_ipaddr_t *nexthop;

    if(uip_len == 0) {
        return;
    }

    if(uip_len > UIP_LINK_MTU) {
        UIP_LOG("tcpip_ipv6_output: Packet to big");
        uip_len = 0;
        return;
    }

    if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)) {
        UIP_LOG("tcpip_ipv6_output: Destination address unspecified");
        uip_len = 0;
        return;
    }

    if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
        /* Next hop determination */
        nbr = NULL;
        if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)) {
            nexthop = &UIP_IP_BUF->destipaddr;
        } else {
            uip_ds6_route_t* locrt;
            locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr);
            if(locrt == NULL) {
                if((nexthop = uip_ds6_defrt_choose()) == NULL) {
#ifdef UIP_FALLBACK_INTERFACE
                    PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n",
                           uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40));
                    if(uip_ext_len > 0) {
                        extern void remove_ext_hdr(void);
                        uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40);
                        remove_ext_hdr();
                        /* This should be copied from the ext header... */
                        UIP_IP_BUF->proto = proto;
                    }
                    UIP_FALLBACK_INTERFACE.output();
#else
                    PRINTF("tcpip_ipv6_output: Destination off-link but no route\n");
#endif /* !UIP_FALLBACK_INTERFACE */
                    uip_len = 0;
                    return;
                }
            } else {
                nexthop = &locrt->nexthop;
            }
#if TCPIP_CONF_ANNOTATE_TRANSMISSIONS
            if(nexthop != NULL) {
                printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
            }
#endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */
        }
        /* End of next hop determination */
#if UIP_CONF_IPV6_RPL
        if(rpl_update_header_final(nexthop)) {
            uip_len = 0;
            return;
        }
#endif /* UIP_CONF_IPV6_RPL */
        if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) {
#if UIP_ND6_SEND_NA
            if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) {
                uip_len = 0;
                return;
            } else {
#if UIP_CONF_IPV6_QUEUE_PKT
                /* Copy outgoing pkt in the queuing buffer for later transmit. */
                if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
                    memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
                    uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
                }
#endif
                /* RFC4861, 7.2.2:
                 * "If the source address of the packet prompting the solicitation is the
                 * same as one of the addresses assigned to the outgoing interface, that
                 * address SHOULD be placed in the IP Source Address of the outgoing
                 * solicitation.  Otherwise, any one of the addresses assigned to the
                 * interface should be used."*/
                if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) {
                    uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr);
                } else {
                    uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr);
                }

                stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000);
                nbr->nscount = 1;
            }
#endif /* UIP_ND6_SEND_NA */
        } else {
#if UIP_ND6_SEND_NA
            if(nbr->state == NBR_INCOMPLETE) {
                PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n");
#if UIP_CONF_IPV6_QUEUE_PKT
                /* Copy outgoing pkt in the queuing buffer for later transmit and set
                   the destination nbr to nbr. */
                if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
                    memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
                    uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
                }
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/
                uip_len = 0;
                return;
            }
            /* Send in parallel if we are running NUD (nbc state is either STALE,
               DELAY, or PROBE). See RFC 4861, section 7.7.3 on node behavior. */
            if(nbr->state == NBR_STALE) {
                nbr->state = NBR_DELAY;
                stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME);
                nbr->nscount = 0;
                PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n");
            }
#endif /* UIP_ND6_SEND_NA */

            tcpip_output(&nbr->lladdr);

#if UIP_CONF_IPV6_QUEUE_PKT
            /*
             * Send the queued packets from here, may not be 100% perfect though.
             * This happens in a few cases, for example when instead of receiving a
             * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves
             * to STALE, and you must both send a NA and the queued packet.
             */
            if(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);
                tcpip_output(&nbr->lladdr);
            }
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/

            uip_len = 0;
            return;
        }
    }

    /* Multicast IP destination address. */
    tcpip_output(NULL);
    uip_len = 0;
    uip_ext_len = 0;
}
Beispiel #9
0
void
tcpip_ipv6_output(void)
{
  uip_ds6_nbr_t *nbr = NULL;
  uip_ipaddr_t* nexthop;
  
  if(uip_len == 0) {
    return;
  }
  
  if(uip_len > UIP_LINK_MTU) {
    UIP_LOG("tcpip_ipv6_output: Packet to big");
    uip_len = 0;
    return;
  }
  if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){
    UIP_LOG("tcpip_ipv6_output: Destination address unspecified");
    uip_len = 0;
    return;
  }
  if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
    /* Next hop determination */
    nbr = NULL;
    if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){
      nexthop = &UIP_IP_BUF->destipaddr;
    } else {
      uip_ds6_route_t* locrt;
      locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr);
      if(locrt == NULL) {
        if((nexthop = uip_ds6_defrt_choose()) == NULL) {
#ifdef UIP_FALLBACK_INTERFACE
	  UIP_FALLBACK_INTERFACE.output();
#else
          PRINTF("tcpip_ipv6_output: Destination off-link but no route\n");
#endif
          uip_len = 0;
          return;
        }
      } else {
        nexthop = &locrt->nexthop;
      }
    }
    /* end of next hop determination */
   // if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) {
	if(0){
	/* 
	 * I-D.ietf.6lowpan-nd 5.7: As all prefixes but the link-local prefix are
	 * always assumed to be off-link, multicast-based address resolution between
	 * neighbors is not needed.
	 * In addition, there are neither INCOMPLETE, STALE, DELAY, nor PROBE NCEs 
	 * in 6LoWPAN-ND.
	 */	
		return;
    } else {
    	tcpip_output(&(nbr->lladdr));
      uip_len = 0;
      return;
    }
  }
   
  /*multicast IP destination address */
  tcpip_output(NULL);
  uip_len = 0;
  uip_ext_len = 0;
   
}
Beispiel #10
0
void
tcpip_ipv6_output(void)
{
  uip_ds6_nbr_t *nbr = NULL;
  uip_ipaddr_t *nexthop;

  if(uip_len == 0) {
    return;
  }

  if(uip_len > UIP_LINK_MTU) {
    UIP_LOG("tcpip_ipv6_output: Packet to big");
    uip_clear_buf();
    return;
  }

  if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){
    UIP_LOG("tcpip_ipv6_output: Destination address unspecified");
    uip_clear_buf();
    return;
  }

  if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
    /* Next hop determination */
    nbr = NULL;

    /* We first check if the destination address is on our immediate
       link. If so, we simply use the destination address as our
       nexthop address. */
    if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){
      nexthop = &UIP_IP_BUF->destipaddr;
    } else {
      uip_ds6_route_t *route;
      /* Check if we have a route to the destination address. */
      route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr);

      /* No route was found - we send to the default route instead. */
      if(route == NULL) {
        PRINTF("tcpip_ipv6_output: no route found, using default route\n");
        nexthop = uip_ds6_defrt_choose();
        if(nexthop == NULL) {
#ifdef UIP_FALLBACK_INTERFACE
	  PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", 
		 uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40));
	  if(uip_ext_len > 0) {
	    extern void remove_ext_hdr(void);
	    uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40);
	    remove_ext_hdr();
	    /* This should be copied from the ext header... */
	    UIP_IP_BUF->proto = proto;
	  }
	  /* Inform the other end that the destination is not reachable. If it's
	   * not informed routes might get lost unexpectedly until there's a need
	   * to send a new packet to the peer */
	  if(UIP_FALLBACK_INTERFACE.output() < 0) {
	    PRINTF("FALLBACK: output error. Reporting DST UNREACH\n");
	    uip_icmp6_error_output(ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_ADDR, 0);
	    uip_flags = 0;
	    tcpip_ipv6_output();
	    return;
	  }
#else
          PRINTF("tcpip_ipv6_output: Destination off-link but no route\n");
#endif /* !UIP_FALLBACK_INTERFACE */
          uip_clear_buf();
          return;
        }

      } else {
        /* A route was found, so we look up the nexthop neighbor for
           the route. */
        nexthop = uip_ds6_route_nexthop(route);

        /* If the nexthop is dead, for example because the neighbor
           never responded to link-layer acks, we drop its route. */
        if(nexthop == NULL) {
#if UIP_CONF_IPV6_RPL
          /* If we are running RPL, and if we are the root of the
             network, we'll trigger a global repair berfore we remove
             the route. */
          rpl_dag_t *dag;
          rpl_instance_t *instance;

          dag = (rpl_dag_t *)route->state.dag;
          if(dag != NULL) {
            instance = dag->instance;

            rpl_repair_root(instance->instance_id);
          }
#endif /* UIP_CONF_IPV6_RPL */
          uip_ds6_route_rm(route);

          /* We don't have a nexthop to send the packet to, so we drop
             it. */
          return;
        }
      }
#if TCPIP_CONF_ANNOTATE_TRANSMISSIONS
      if(nexthop != NULL) {
        static uint8_t annotate_last;
        static uint8_t annotate_has_last = 0;

        if(annotate_has_last) {
          printf("#L %u 0; red\n", annotate_last);
        }
        printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
        annotate_last = nexthop->u8[sizeof(uip_ipaddr_t) - 1];
        annotate_has_last = 1;
      }
#endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */
    }

    /* End of next hop determination */

#if UIP_CONF_IPV6_RPL
    if(rpl_update_header_final(nexthop)) {
      uip_clear_buf();
      return;
    }
#endif /* UIP_CONF_IPV6_RPL */
    nbr = uip_ds6_nbr_lookup(nexthop);
    if(nbr == NULL) {
#if UIP_ND6_SEND_NA
      if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) {
        uip_clear_buf();
        return;
      } else {
#if UIP_CONF_IPV6_QUEUE_PKT
        /* Copy outgoing pkt in the queuing buffer for later transmit. */
        if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
          memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
          uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
        }
#endif
      /* RFC4861, 7.2.2:
       * "If the source address of the packet prompting the solicitation is the
       * same as one of the addresses assigned to the outgoing interface, that
       * address SHOULD be placed in the IP Source Address of the outgoing
       * solicitation.  Otherwise, any one of the addresses assigned to the
       * interface should be used."*/
       if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){
          uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr);
        } else {
          uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr);
        }

        stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000);
        nbr->nscount = 1;
        /* Send the first NS try from here (multicast destination IP address). */
      }
#else /* UIP_ND6_SEND_NA */
      uip_len = 0;
      return;  
#endif /* UIP_ND6_SEND_NA */
    } else {
#if UIP_ND6_SEND_NA
      if(nbr->state == NBR_INCOMPLETE) {
        PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n");
#if UIP_CONF_IPV6_QUEUE_PKT
        /* Copy outgoing pkt in the queuing buffer for later transmit and set
           the destination nbr to nbr. */
        if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
          memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
          uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
        }
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/
        uip_clear_buf();
        return;
      }
      /* Send in parallel if we are running NUD (nbc state is either STALE,
         DELAY, or PROBE). See RFC 4861, section 7.3.3 on node behavior. */
      if(nbr->state == NBR_STALE) {
        nbr->state = NBR_DELAY;
        stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME);
        nbr->nscount = 0;
        PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n");
      }
#endif /* UIP_ND6_SEND_NA */

      tcpip_output(uip_ds6_nbr_get_ll(nbr));

#if UIP_CONF_IPV6_QUEUE_PKT
      /*
       * Send the queued packets from here, may not be 100% perfect though.
       * This happens in a few cases, for example when instead of receiving a
       * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves
       * to STALE, and you must both send a NA and the queued packet.
       */
      if(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);
        tcpip_output(uip_ds6_nbr_get_ll(nbr));
      }
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/

      uip_clear_buf();
      return;
    }
  }
  /* Multicast IP destination address. */
  tcpip_output(NULL);
  uip_clear_buf();
}
Beispiel #11
0
static void
timeout_handler(void)
{
  static int seq_id;
  char buf[MAX_PAYLOAD_LEN];
  int i;
  uip_ipaddr_t *globaladdr = NULL;
  uip_ipaddr_t newdest_addr;
  uint16_t dest_port = use_user_dest_addr ? user_dest_port : 3000;
  int has_dest=0;

  if ( use_user_dest_addr ) {
	uip_ipaddr_copy(&newdest_addr, &user_dest_addr);
	has_dest=1;
  } else if((globaladdr = &uip_ds6_get_global(-1)->ipaddr) != NULL) {
#if UIP_CONF_IPV6_RPL
    rpl_dag_t *dag = rpl_get_any_dag();
    uip_ipaddr_copy(&newdest_addr, globaladdr);
    memcpy(&newdest_addr.u8[8], &dag->dag_id.u8[8], sizeof(uip_ipaddr_t) / 2);
    has_dest = dag == NULL ? 0 : 1;
#else
    uip_ipaddr_t * defrt = uip_ds6_defrt_choose();
    if ( defrt != NULL ) {
      uip_ipaddr_copy(&newdest_addr, defrt);
      has_dest=1;
    }
#endif
  }

  if (client_conn == NULL) {
    if (has_dest) {
        /* At least one prefix announced : building of the global address to reach using prefixes */
        memcpy(dest_addr, &newdest_addr, sizeof(uip_ipaddr_t));
        PRINTF("UDP-CLIENT: address destination: ");
        PRINT6ADDR(dest_addr);
        PRINTF("\n");
        client_conn = udp_new(dest_addr, UIP_HTONS(dest_port), NULL);

        udp_bind(client_conn, UIP_HTONS(3001));
		PRINTF("Created a connection with the server ");
		PRINT6ADDR(&client_conn->ripaddr);
		PRINTF(" local/remote port %u/%u\n",
		UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport));
		print_local_addresses();
    } else {
      PRINTF("No address configured yet\n");
    }
  }
  if (client_conn != NULL) {
    if(memcmp(&client_conn->ripaddr, &newdest_addr, sizeof(uip_ipaddr_t)) != 0) {
      PRINTF("UPD-CLIENT : new address, connection changed\n");
      memcpy(dest_addr, &newdest_addr, sizeof(uip_ipaddr_t));
      client_conn = udp_new(dest_addr, UIP_HTONS(3000), NULL);
      udp_bind(client_conn, UIP_HTONS(3001));
      PRINTF("Created a connection with the server ");
      PRINT6ADDR(&client_conn->ripaddr);
      PRINTF(" local/remote port %u/%u\n",
      UIP_HTONS(client_conn->lport), UIP_HTONS(client_conn->rport));
      print_local_addresses();
    }
    if ( udp_client_run ) {
      PRINTF("Client sending to: ");
      PRINT6ADDR(&client_conn->ripaddr);
      i = sprintf(buf, "%d | ", ++seq_id);
#if UIP_CONF_IPV6_RPL
      rpl_dag_t *dag = rpl_get_any_dag();
      add_ipaddr(buf + i, &dag->instance->def_route->ipaddr);
#endif
      PRINTF(" (msg: %s)\n", buf);
      #if SEND_TOO_LARGE_PACKET_TO_TEST_FRAGMENTATION
      uip_udp_packet_send(client_conn, buf, UIP_APPDATA_SIZE);
      #else /* SEND_TOO_LARGE_PACKET_TO_TEST_FRAGMENTATION */
      uip_udp_packet_send(client_conn, buf, strlen(buf));
      #endif /* SEND_TOO_LARGE_PACKET_TO_TEST_FRAGMENTATION */
    }
  }
}
Beispiel #12
0
void
tcpip_ipv6_output(void)
{
  uip_ds6_nbr_t *nbr = NULL;
  uip_ipaddr_t *nexthop;
  uip_ds6_route_t *route = NULL;

  if(uip_len == 0) {
    return;
  }

  PRINTF("IPv6 packet send from ");
  PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
  PRINTF(" to ");
  PRINT6ADDR(&UIP_IP_BUF->destipaddr);
  PRINTF("\n");

  if(uip_len > UIP_LINK_MTU) {
    UIP_LOG("tcpip_ipv6_output: Packet to big");
    uip_clear_buf();
    return;
  }

  if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){
    UIP_LOG("tcpip_ipv6_output: Destination address unspecified");
    uip_clear_buf();
    return;
  }

  if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
    /* Next hop determination */
    nbr = NULL;

    /* We first check if the destination address is on our immediate
       link. If so, we simply use the destination address as our
       nexthop address. */
    if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){
      nexthop = &UIP_IP_BUF->destipaddr;
    } else {
      /* Check if we have a route to the destination address. */
      route = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr);

      /* No route was found - we send to the default route instead. */
      if(route == NULL) {
#if CETIC_6LBR_SMARTBRIDGE
        if (uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64)) {
          /* In smart-bridge mode, there is no route towards hosts on the Ethernet side
          Therefore we have to check the destination and assume the host is on-link */
          nexthop = &UIP_IP_BUF->destipaddr;
        } else
#endif
#if CETIC_6LBR_ROUTER && UIP_CONF_IPV6_RPL
        if (is_dodag_root() && uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64)) {
          //In router mode, we drop packets towards unknown mote
          PRINTF("Dropping wsn packet with no route\n");
          uip_len = 0;
          return;
        } else
#endif
#if CETIC_6LBR_IP64
        if(ip64_addr_is_ip64(&UIP_IP_BUF->destipaddr)) {
#if UIP_CONF_IPV6_RPL
          rpl_remove_header();
#endif
          IP64_CONF_UIP_FALLBACK_INTERFACE.output();
          uip_len = 0;
          uip_ext_len = 0;
          return;
        }
        else
#endif
        {
          PRINTF("tcpip_ipv6_output: no route found, using default route\n");
          nexthop = uip_ds6_defrt_choose();
        }
        if(nexthop == NULL) {
#ifdef UIP_FALLBACK_INTERFACE
	  PRINTF("FALLBACK: removing ext hdrs & setting proto %d %d\n", 
		 uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40));
	  if(uip_ext_len > 0) {
	    extern void remove_ext_hdr(void);
	    uint8_t proto = *((uint8_t *)UIP_IP_BUF + 40);
	    remove_ext_hdr();
	    /* This should be copied from the ext header... */
	    UIP_IP_BUF->proto = proto;
	  }
	  UIP_FALLBACK_INTERFACE.output();
#else
          PRINTF("tcpip_ipv6_output: Destination off-link but no route\n");
#endif /* !UIP_FALLBACK_INTERFACE */
          uip_clear_buf();
          return;
        }

      } else {
        /* A route was found, so we look up the nexthop neighbor for
           the route. */
        nexthop = uip_ds6_route_nexthop(route);

        /* If the nexthop is dead, for example because the neighbor
           never responded to link-layer acks, we drop its route. */
        if(nexthop == NULL) {
#if UIP_CONF_IPV6_RPL
          /* If we are running RPL, and if we are the root of the
             network, we'll trigger a DIO before we remove
             the route. */
          rpl_dag_t *dag;

          dag = (rpl_dag_t *)route->state.dag;
          if(dag != NULL) {
            rpl_reset_dio_timer(dag->instance);
          }
#endif /* UIP_CONF_IPV6_RPL */
          uip_ds6_route_rm(route);

          /* We don't have a nexthop to send the packet to, so we drop
             it. */
          return;
        }
      }
#if TCPIP_CONF_ANNOTATE_TRANSMISSIONS
      if(nexthop != NULL) {
        static uint8_t annotate_last;
        static uint8_t annotate_has_last = 0;

        if(annotate_has_last) {
          printf("#L %u 0; red\n", annotate_last);
        }
        printf("#L %u 1; red\n", nexthop->u8[sizeof(uip_ipaddr_t) - 1]);
        annotate_last = nexthop->u8[sizeof(uip_ipaddr_t) - 1];
        annotate_has_last = 1;
      }
#endif /* TCPIP_CONF_ANNOTATE_TRANSMISSIONS */
    }

    /* End of next hop determination */

#if UIP_CONF_IPV6_RPL
    if(rpl_update_header_final(nexthop)) {
      uip_clear_buf();
      return;
    }
#endif /* UIP_CONF_IPV6_RPL */
    nbr = uip_ds6_nbr_lookup(nexthop);
    if(nbr == NULL) {
#if UIP_ND6_SEND_NA
#if CETIC_6LBR && UIP_CONF_IPV6_RPL
      /* Don't perform NUD if it has been disabled for WSN */
      if((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_WSN_NUD) != 0 &&
         uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64) &&
         route != NULL) {
        uip_clear_buf();
        return;
      }
#endif
      if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) {
        uip_clear_buf();
        return;
      } else {
#if UIP_CONF_IPV6_QUEUE_PKT
        /* Copy outgoing pkt in the queuing buffer for later transmit. */
        if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
          memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
          uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
        }
#endif
      /* RFC4861, 7.2.2:
       * "If the source address of the packet prompting the solicitation is the
       * same as one of the addresses assigned to the outgoing interface, that
       * address SHOULD be placed in the IP Source Address of the outgoing
       * solicitation.  Otherwise, any one of the addresses assigned to the
       * interface should be used."*/
       if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){
          uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr);
        } else {
          uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr);
        }

        stimer_set(&nbr->sendns, uip_ds6_if.retrans_timer / 1000);
        nbr->nscount = 1;
        /* Send the first NS try from here (multicast destination IP address). */
      }
#else /* UIP_ND6_SEND_NA */
      uip_len = 0;
      return;  
#endif /* UIP_ND6_SEND_NA */
    } else {
#if UIP_ND6_SEND_NA
      if(nbr->state == NBR_INCOMPLETE) {
        PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n");
#if UIP_CONF_IPV6_QUEUE_PKT
        /* Copy outgoing pkt in the queuing buffer for later transmit and set
           the destination nbr to nbr. */
        if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
          memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
          uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
        }
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/
        uip_clear_buf();
        return;
      }
      /* Send in parallel if we are running NUD (nbc state is either STALE,
         DELAY, or PROBE). See RFC 4861, section 7.3.3 on node behavior. */
#if CETIC_6LBR && UIP_CONF_IPV6_RPL
      /* Don't update nbr state if we don't want to perform NUD for WSN */
      if((nvm_data.global_flags & CETIC_GLOBAL_DISABLE_WSN_NUD) == 0 ||
         !uip_ipaddr_prefixcmp(&wsn_net_prefix, &UIP_IP_BUF->destipaddr, 64) ||
         route == NULL)
#endif
      if(nbr->state == NBR_STALE) {
        nbr->state = NBR_DELAY;
        stimer_set(&nbr->reachable, UIP_ND6_DELAY_FIRST_PROBE_TIME);
        nbr->nscount = 0;
        PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n");
      }
#endif /* UIP_ND6_SEND_NA */

      tcpip_output(uip_ds6_nbr_get_ll(nbr));

#if UIP_CONF_IPV6_QUEUE_PKT
      /*
       * Send the queued packets from here, may not be 100% perfect though.
       * This happens in a few cases, for example when instead of receiving a
       * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves
       * to STALE, and you must both send a NA and the queued packet.
       */
      if(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);
        tcpip_output(uip_ds6_nbr_get_ll(nbr));
      }
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/

      uip_clear_buf();
      return;
    }
  }
  /* Multicast IP destination address. */
  tcpip_output(NULL);
  uip_clear_buf();
}
Beispiel #13
0
/*---------------------------------------------------------------------------*/
void
uip_ds6_periodic(void)
{
	/* This flag signals whether we allow or not to send a packet in the current 
	 * invocation. */
  u8_t allow_output = 1;

  /* minimum lifetime */
  min_lifetime = 0xFFFFFFFF;
  /* router with minimum lifetime */
  min_defrt = NULL;
	
	/* Periodic processing on registrations */
	for(locreg = uip_ds6_reg_list;
      locreg < uip_ds6_reg_list + UIP_DS6_REG_LIST_SIZE; locreg++) {
  	if (locreg->isused) {
  		if (stimer_expired(&locreg->reg_lifetime)) {
  			uip_ds6_reg_rm(locreg);
  		} else if (allow_output) {
  			/* If no output is allowed, it is pointless to enter here in this invocation */
  			if (uip_ds6_if.registration_in_progress) {
  				/* There is a registration in progress */
  				if ((locreg == uip_ds6_if.registration_in_progress) && 
  						(timer_expired(&locreg->registration_timer))) {
	      		/* We already sent a NS message for this address but there has been no response */
	      		if(locreg->reg_count >= UIP_ND6_MAX_UNICAST_SOLICIT) {
			  			/* NUD failed. Signal the need for next-hop determination by deleting the 
			   			 * NCE (RFC 4861) */
			   			uip_ds6_reg_rm(locreg); 
			  			/* And then, delete neighbor and corresponding router (as hosts only keep
			  			 * NCEs for routers in 6lowpan-nd) */ 
			  			locnbr = uip_ds6_nbr_lookup(&locreg->defrt->ipaddr); 
			  			uip_ds6_nbr_rm(locnbr);
			  			uip_ds6_defrt_rm(locreg->defrt);
			  			/* Since we are deleting a default router, we must delete also all 
			  			 * registrations with that router.
			  			 * Be careful here, uip_ds6_reg_cleanup_defrt() modifies the value of locreg!*/
			  			uip_ds6_reg_cleanup_defrt(locreg->defrt);
		      		/* We will also need to start sending RS, as specified in I-D.ietf-6lowpan-nd 
		      		 * for NUD failure case */
		      		uip_ds6_send_rs(NULL);
		      		uip_ds6_if.registration_in_progress = NULL;
  					} else {
  						locreg->reg_count++;
		      		timer_restart(&locreg->registration_timer);
		   	 			uip_nd6_ns_output(&locreg->addr->ipaddr, &locreg->defrt->ipaddr, 
		          			            &locreg->defrt->ipaddr, 1, UIP_ND6_REGISTRATION_LIFETIME);
 						}
  					allow_output = 0; /* Prevent this invocation from sending anything else */
  				}
  			} else {
  				/* There are no registrations in progress, let's see this entry needs (re)registration
  				 * or deletion */
  				if ((locreg->state == REG_GARBAGE_COLLECTIBLE) || 
  						(locreg->state == REG_TO_BE_UNREGISTERED) || 
  						((locreg->state == REG_REGISTERED) && 
	 						(stimer_remaining(&locreg->reg_lifetime) < stimer_elapsed(&locreg->reg_lifetime)))) {
 						/* Issue (re)registration */
				  	uip_ds6_if.registration_in_progress = locreg;
				  	locreg->reg_count++;
				  	timer_set(&locreg->registration_timer, (uip_ds6_if.retrans_timer / 1000) * (CLOCK_SECOND /* FIXME @@@jwg!!!!*/+250));
				  	if (locreg->state == REG_TO_BE_UNREGISTERED) {
					  	uip_nd6_ns_output(&locreg->addr->ipaddr, &locreg->defrt->ipaddr, 
				      	   			        &locreg->defrt->ipaddr, 1, 0);
				  	} else {
				  		uip_nd6_ns_output(&locreg->addr->ipaddr, &locreg->defrt->ipaddr, 
				      	   			        &locreg->defrt->ipaddr, 1, UIP_ND6_REGISTRATION_LIFETIME);
				  	}   	   			       
			      allow_output = 0; /* Prevent this invocation from sending anything else */
  				}
  			}
  		}
  	}
  }

  
  /* Periodic processing on unicast addresses */
  for(locaddr = uip_ds6_if.addr_list;
      locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
    if(locaddr->isused) {
      if((!locaddr->isinfinite) && (stimer_expired(&locaddr->vlifetime))) {
        uip_ds6_addr_rm(locaddr);
      } else if (allow_output) {
        if (stimer_remaining(&locaddr->vlifetime) < min_lifetime) {
          min_lifetime = stimer_remaining(&locaddr->vlifetime);
          min_defrt = locaddr->defrt;
        }
      }
    }
  }
  
  /* Periodic processing on default routers */
	if (uip_ds6_defrt_choose() == NULL) {
	  if (allow_output) {
	    /* If default router list is empty, start sending RS */
	    uip_ds6_send_rs(NULL);
	    allow_output = 0; /* Prevent this invocation from sending anything else */
	  }
	} else {
    for(locdefrt = uip_ds6_defrt_list;
        locdefrt < uip_ds6_defrt_list + UIP_DS6_DEFRT_NB; locdefrt++) {
      if((locdefrt->isused) && (!locdefrt->isinfinite)) {
        if (stimer_expired(&(locdefrt->lifetime))) {
          uip_ds6_defrt_rm(locdefrt);
          /* If default router list is empty, we will start sending RS in
           * the next invocation of ds6_periodic() */
        } else {
          if (allow_output) {
            if (stimer_remaining(&locdefrt->lifetime) < min_lifetime) {
              min_lifetime = stimer_remaining(&locdefrt->lifetime);
              min_defrt = locdefrt;
            }
          }
        }
      }
    }
	}
	
#if !UIP_CONF_ROUTER
  /* Periodic processing on prefixes */
  for (locprefix = uip_ds6_prefix_list;
      locprefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; locprefix++) {
    if((locprefix->isused) && (!locprefix->isinfinite)) {
    	if (stimer_expired(&locprefix->vlifetime)) {
      	uip_ds6_prefix_rm(locprefix);
    	} else if (allow_output) {
    		if (stimer_remaining(&locprefix->vlifetime) < min_lifetime) {
    			min_lifetime = stimer_remaining(&locprefix->vlifetime);
    			min_defrt = locprefix->defrt;
    		}
    	}
    }
  }
#endif /* !UIP_CONF_ROUTER */

#if CONF_6LOWPAN_ND_6CO
	/* Periodic processing on contexts */
  for(loccontext = uip_ds6_addr_context_table;
      loccontext < uip_ds6_addr_context_table + SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS; loccontext++) {
    if(loccontext->state != NOT_IN_USE) {
    	if (stimer_expired(&loccontext->vlifetime)) {
    		if (loccontext->state != EXPIRED) {
    			loccontext->state = IN_USE_UNCOMPRESS_ONLY;
    			stimer_set(&loccontext->vlifetime, 2 * loccontext->defrt_lifetime);
    		} else {
      		uip_ds6_context_rm(loccontext);
    		}
    	} else if (allow_output) {
    		if (stimer_remaining(&loccontext->vlifetime) < min_lifetime) {
    			min_lifetime = stimer_remaining(&loccontext->vlifetime);
    			min_defrt = loccontext->defrt;
    		}
    	}
    }
  }
#endif /* CONF_6LOWPAN_ND_6CO */

	/* Start sending RS well before the minimum of the lifetimes (def. router, 
	 * context, or prefix) expires */
	if ((allow_output) && (min_lifetime < UIP_DS6_LIFETIME_THRESHOLD)) {
	  /* Start sending RSs to the router with minimum lifetime (if possible) */
		uip_ds6_send_rs(min_defrt);
		allow_output = 0;
	}

  /* Periodic processing on neighbors */
  for(locnbr = uip_ds6_nbr_cache; locnbr < uip_ds6_nbr_cache + UIP_DS6_NBR_NB;
      locnbr++) {
    if(locnbr->isused) {
      switch (locnbr->state) {
#if UIP_CONF_ROUTER
/* There can not be INCOMPLETE NCEs in a host in 6lowpan-nd */
      case NBR_INCOMPLETE:
    		if (allow_output) {  
	        if(locnbr->nscount >= UIP_ND6_MAX_MULTICAST_SOLICIT) {
	          uip_ds6_nbr_rm(locnbr);
	        } else if(stimer_expired(&(locnbr->sendns))) {
	          locnbr->nscount++;
	          PRINTF("NBR_INCOMPLETE: NS %u\n", locnbr->nscount);
	          uip_nd6_ns_output(NULL, NULL, &locnbr->ipaddr);
	          stimer_set(&(locnbr->sendns), uip_ds6_if.retrans_timer / 1000);
						allow_output = 0;
	        }
    		}  
        break;
#endif /* UIP_CONF_ROUTER */
      case NBR_REACHABLE:
        if(stimer_expired(&(locnbr->reachable))) {
          PRINTF("REACHABLE: moving to STALE (");
          PRINT6ADDR(&locnbr->ipaddr);
          PRINTF(")\n");
          locnbr->state = NBR_STALE;
          NEIGHBOR_STATE_CHANGED(locnbr);
        }
        break;
      case NBR_DELAY:
    		if (allow_output) {  
	        if(stimer_expired(&(locnbr->reachable))) {
	          locnbr->state = NBR_PROBE;
	          locnbr->nscount = 1;
	          NEIGHBOR_STATE_CHANGED(locnbr);
	          PRINTF("DELAY: moving to PROBE + NS %u\n", locnbr->nscount);
	          uip_nd6_ns_output(NULL, &locnbr->ipaddr, &locnbr->ipaddr, 0, 0);
	          stimer_set(&(locnbr->sendns), uip_ds6_if.retrans_timer / 1000);
	          allow_output = 0;
	        }
    		}  
        break;
      case NBR_PROBE:
    		if (allow_output) {  
	        if(locnbr->nscount >= UIP_ND6_MAX_UNICAST_SOLICIT) {
	          PRINTF("PROBE END \n");
	          if((locdefrt = uip_ds6_defrt_lookup(&locnbr->ipaddr)) != NULL) {
	            uip_ds6_defrt_rm(locdefrt);
	          }
	          uip_ds6_nbr_rm(locnbr);
	        } else if(stimer_expired(&(locnbr->sendns))) {
	          locnbr->nscount++;
	          PRINTF("PROBE: NS %u\n", locnbr->nscount);
	          uip_nd6_ns_output(NULL, &locnbr->ipaddr, &locnbr->ipaddr, 0, 0);
	          stimer_set(&(locnbr->sendns), uip_ds6_if.retrans_timer / 1000);
	          allow_output = 0;
	        }
    		}  
        break;
      default:
        break;
      }
    }
  }

#if UIP_CONF_ROUTER & UIP_ND6_SEND_RA 
  /* Periodic RA sending */
  if(stimer_expired(&uip_ds6_timer_ra)) {
    uip_ds6_send_ra_periodic();
  }
#endif /* UIP_CONF_ROUTER & UIP_ND6_SEND_RA */
  etimer_reset(&uip_ds6_timer_periodic);
  return;
}
Beispiel #14
0
void
tcpip_ipv6_output(void)
{
    static uip_ds6_nbr_t *nbr = NULL;
    static uip_ipaddr_t* nexthop;

    if(uip_len == 0) {
        return;
    }

    if(uip_len > UIP_LINK_MTU) {
        UIP_LOG("tcpip_ipv6_output: Packet to big");
        uip_len = 0;
        return;
    }
    if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)) {
        UIP_LOG("tcpip_ipv6_output: Destination address unspecified");
        uip_len = 0;
        return;
    }
    if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
        /* Next hop determination */
        nbr = NULL;
        if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)) {
            nexthop = &UIP_IP_BUF->destipaddr;
        } else {
            uip_ds6_route_t* locrt;
            locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr);
            if(locrt == NULL) {
                if((nexthop = uip_ds6_defrt_choose()) == NULL) {
#ifdef UIP_FALLBACK_INTERFACE
                    UIP_FALLBACK_INTERFACE.output();
#else
                    PRINTF("tcpip_ipv6_output: Destination off-link but no route\n");
#endif
                    uip_len = 0;
                    return;
                }
            } else {
                nexthop = &locrt->nexthop;
            }
        }
        /* end of next hop determination */
        if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) {
            //      printf("add1 %d\n", nexthop->u8[15]);
            if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) {
                //        printf("add n\n");
                uip_len = 0;
                return;
            } else {
#if UIP_CONF_IPV6_QUEUE_PKT
                /* copy outgoing pkt in the queuing buffer for later transmmit */
                if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
                    memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
                    uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
                }
#endif
                /* RFC4861, 7.2.2:
                 * "If the source address of the packet prompting the solicitation is the
                 * same as one of the addresses assigned to the outgoing interface, that
                 * address SHOULD be placed in the IP Source Address of the outgoing
                 * solicitation.  Otherwise, any one of the addresses assigned to the
                 * interface should be used."*/
                if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)) {
                    uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr);
                } else {
                    uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr);
                }

                stimer_set(&(nbr->sendns), uip_ds6_if.retrans_timer / 1000);
                nbr->nscount = 1;
            }
        } else {
            if(nbr->state == NBR_INCOMPLETE) {
                PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n");
#if UIP_CONF_IPV6_QUEUE_PKT
                /* copy outgoing pkt in the queuing buffer for later transmmit and set
                   the destination nbr to nbr */
                if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
                    memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
                    uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
                }
                /*        memcpy(nbr->queue_buf, UIP_IP_BUF, uip_len);
                          nbr->queue_buf_len = uip_len;*/
                uip_len = 0;
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/
                return;
            }
            /* if running NUD (nbc->state == STALE, DELAY, or PROBE ) keep
               sending in parallel see rfc 4861 Node behavior in section 7.7.3*/

            if(nbr->state == NBR_STALE) {
                nbr->state = NBR_DELAY;
                stimer_set(&(nbr->reachable),
                           UIP_ND6_DELAY_FIRST_PROBE_TIME);
                nbr->nscount = 0;
                PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n");
            }

            stimer_set(&(nbr->sendns),
                       uip_ds6_if.retrans_timer / 1000);

            tcpip_output(&(nbr->lladdr));


#if UIP_CONF_IPV6_QUEUE_PKT
            /* Send the queued packets from here, may not be 100% perfect though.
             * This happens in a few cases, for example when instead of receiving a
             * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves
             *to STALE, and you must both send a NA and the queued packet
             */
            /*      if(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;
              tcpip_output(&(nbr->lladdr));
              }*/
            if(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);
                tcpip_output(&(nbr->lladdr));
            }
#endif /*UIP_CONF_IPV6_QUEUE_PKT*/

            uip_len = 0;
            return;
        }
    }

    /*multicast IP destination address */
    tcpip_output(NULL);
    uip_len = 0;
    uip_ext_len = 0;

}
Beispiel #15
0
/*---------------------------------------------------------------------------*/
static void
publish(void)
{
  /* Publish MQTT topic in IBM quickstart format */
  int len;
  int remaining = APP_BUFFER_SIZE;

  seq_nr_value++;

  buf_ptr = app_buffer;

  len = snprintf(buf_ptr, remaining,
                 "{"
                 "\"d\":{"
                 "\"Seq #\":%d,"
                 "\"Uptime (sec)\":%lu", seq_nr_value, clock_seconds());

  if(len < 0 || len >= remaining) {
    printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len);
    return;
  }

  remaining -= len;
  buf_ptr += len;

  /* Put our Default route's string representation in a buffer */
  char def_rt_str[64];
  memset(def_rt_str, 0, sizeof(def_rt_str));
  ipaddr_sprintf(def_rt_str, sizeof(def_rt_str), uip_ds6_defrt_choose());

  len = snprintf(buf_ptr, remaining, ",\"Def Route\":\"%s\",\"RSSI (dBm)\":%d",
                 def_rt_str, def_rt_rssi);

  if(len < 0 || len >= remaining) {
    printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len);
    return;
  }
  remaining -= len;
  buf_ptr += len;

  len = snprintf(buf_ptr, remaining, ",\"On-Chip Temp (deg.C)\":%d",
                 temperature_sensor.value(0));

  if(len < 0 || len >= remaining) {
    printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len);
    return;
  }
  remaining -= len;
  buf_ptr += len;

  len = snprintf(buf_ptr, remaining, "}}");

  if(len < 0 || len >= remaining) {
    printf("Buffer too short. Have %d, need %d + \\0\n", remaining, len);
    return;
  }

  mqtt_publish(&conn, NULL, pub_topic, (uint8_t *)app_buffer,
               strlen(app_buffer), MQTT_QOS_LEVEL_0, MQTT_RETAIN_OFF);

  DBG("APP - Publish!\n");
}
Beispiel #16
0
void device_handler(void* request, void* response, uint8_t *buffer, uint16_t preferred_size, int32_t *offset) {
    const char *uri_path = NULL;
    uint8_t uri_len = REST.get_url(request, &uri_path);

    if (uri_len == 1) {
        if (*offset >= LEN_D_CORE) {
            coap_set_status_code(response, BAD_OPTION_4_02);
            coap_set_payload(response, "BlockOutOfScope", 15);
            return;
        }

        flash_getVar(buffer, RES_D_CORE + *offset, preferred_size);
        if (LEN_D_CORE - *offset < preferred_size) {
            preferred_size = LEN_D_CORE - *offset;
            *offset = -1;
        } else {
            *offset += preferred_size;
        }

        REST.set_header_content_type(response, APPLICATION_LINK_FORMAT);
        REST.set_response_payload(response, buffer, preferred_size);
        return;
    }

    //*************************************************************************
    //*  DEVICE NAME                                                          *
    //*************************************************************************
    if (uri_path[2] == 'n' && uri_path[3] == 'a') {
        flash_getVar(buffer, RES_NAME, LEN_NAME);
        REST.set_header_content_type(response, TEXT_PLAIN);
        REST.set_response_payload(response, buffer, strlen(buffer));
    }

    //*************************************************************************
    //*  DEVICE MODEL                                                         *
    //*************************************************************************
    if (uri_path[2] == 'm') {
        flash_getVar(buffer, RES_MODEL, LEN_MODEL);
        REST.set_header_content_type(response, TEXT_PLAIN);
        REST.set_response_payload(response, buffer, strlen(buffer));
        return;
    }

    //*************************************************************************
    //*  DEVICE IDENTIFIER                                                    *
    //*************************************************************************
    if (uri_path[2] == 'u') {
        leds_on(LEDS_GREEN);
        send_hello = 0;

        flash_getVar(buffer, RES_UUID, LEN_UUID);
        REST.set_header_content_type(response, APPLICATION_OCTET_STREAM);
        REST.set_response_payload(response, buffer, LEN_UUID);
    }

    //*************************************************************************
    //*  DEVICE TIME                                                          *
    //*************************************************************************
    if (uri_path[2] == 't') {
        uint32_t time = uip_htonl(clock_seconds());
        memcpy(buffer, &time, 4);
        REST.set_header_content_type(response, APPLICATION_OCTET_STREAM);
        REST.set_response_payload(response, buffer, 4);
    }

    //*************************************************************************
    //*  DEVICE PSK                                                           *
    //*************************************************************************
    if (uri_path[2] == 'p') {
        getPSK(buffer);
        REST.set_header_content_type(response, APPLICATION_OCTET_STREAM);
        REST.set_response_payload(response, buffer, LEN_PSK);
    }

    //*************************************************************************
    //*  DEVICE DEFAULT ROUTE                                                 *
    //*************************************************************************
    if (uri_path[2] == 'r') {
        uip_ipaddr_t *addr = uip_ds6_defrt_choose();
        memcpy(buffer, addr, 16);
        REST.set_header_content_type(response, APPLICATION_OCTET_STREAM);
        REST.set_response_payload(response, buffer, 16);
    }

    //*************************************************************************
    //*  DEVICE NEIGHBOURS                                                    *
    //*************************************************************************
    if (uri_path[2] == 'n' && uri_path[3] == 'b') {
        uint32_t o = *offset / 16;
        uint32_t bfr_ptr = 0;
        uint32_t i;
        uip_ds6_nbr_t *nbr = nbr_table_head(ds6_neighbors);
        for (i = 0; i < (o+2); i++) {
            if (i >= o) {
                memcpy(buffer + bfr_ptr, &nbr->ipaddr, 16);
                bfr_ptr += 16;
            }

            nbr = nbr_table_next(ds6_neighbors, nbr);
            if (nbr == NULL) {
                if (bfr_ptr == 0) {
                  coap_set_status_code(response, BAD_OPTION_4_02);
                  coap_set_payload(response, "BlockOutOfScope", 15);
                  return;
                }
                break;
            }
        }
        if (nbr == NULL) {
            *offset = -1;
        } else {
           *offset += bfr_ptr;
        }
        REST.set_header_content_type(response, APPLICATION_OCTET_STREAM);
        REST.set_response_payload(response, buffer, bfr_ptr);
    }
}