Пример #1
0
/*---------------------------------------------------------------------------*/
void
uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
{
  uint8_t best = 0;             /* number of bit in common with best match */
  uint8_t n = 0;
  uip_ds6_addr_t *matchaddr = NULL;

  if(!uip_is_addr_link_local(dst) && !uip_is_addr_mcast(dst)) {
    /* find longest match */
    for(locaddr = uip_ds6_if.addr_list;
        locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
      /* Only preferred global (not link-local) addresses */
      if(locaddr->isused && locaddr->state == ADDR_PREFERRED &&
         !uip_is_addr_link_local(&locaddr->ipaddr)) {
        n = get_match_length(dst, &locaddr->ipaddr);
        if(n >= best) {
          best = n;
          matchaddr = locaddr;
        }
      }
    }
  } else {
    matchaddr = uip_ds6_get_link_local(ADDR_PREFERRED);
  }

  /* use the :: (unspecified address) as source if no match found */
  if(matchaddr == NULL) {
    uip_create_unspecified(src);
  } else {
    uip_ipaddr_copy(src, &matchaddr->ipaddr);
  }
#if UIP_CONF_LOOPBACK
  // FIXME: there's probably a better way to do this
  if(uip_is_addr_loopback(dst)) {
    uip_ipaddr_copy(src, dst);
  }
#endif /* UIP_CONF_LOOPBACK */
}
Пример #2
0
/*---------------------------------------------------------------------------*/
void
uip_process()
{
  PRINTF("NEW packet\n");

  /* Check validity of the IP header. */
  if((UIP_IP_BUF->vtc & 0xf0) != 0x60)  { /* IP version and header length. */
    PRINTF("Wrong IP Version\n");
    goto drop;
  }
  /*
   * Check the size of the packet. If the size reported to us in
   * uip_len is smaller the size reported in the IP header, we assume
   * that the packet has been corrupted in transit. If the size of
   * uip_len is larger than the size reported in the IP packet header,
   * the packet has been padded and we set uip_len to the correct
   * value..
   */

  if((UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] <= uip_len) {
    uip_len = (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + UIP_IPH_LEN;
    /*
     * The length reported in the IPv6 header is the
     * length of the payload that follows the
     * header. However, uIP uses the uip_len variable
     * for holding the size of the entire packet,
     * including the IP header. For IPv4 this is not a
     * problem as the length field in the IPv4 header
     * contains the length of the entire packet. But
     * for IPv6 we need to add the size of the IPv6
     * header (40 bytes).
     */
  } else {
    PRINTF("Wrong Length\n");
    goto drop;
  }
  
  PRINTF("IPv6 packet received from ");
  PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
  PRINTF(" to ");
  PRINT6ADDR(&UIP_IP_BUF->destipaddr);
  PRINTF("\n");

  if(uip_is_addr_mcast(&UIP_IP_BUF->srcipaddr)){
    PRINTF("Dropping packet, src is mcast\n");
    goto drop;
  }

  /*
   * Next header field processing. In IPv6, we can have extension headers,
   * if present, the Hop-by-Hop Option must be processed before forwarding
   * the packet.
   */
  uip_next_hdr = &UIP_IP_BUF->proto;
  uip_ext_len = 0;
  uip_ext_bitmap = 0;
  if (*uip_next_hdr == UIP_PROTO_HBHO) {
#if UIP_CONF_IPV6_CHECKS
    uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_HBHO;
#endif /*UIP_CONF_IPV6_CHECKS*/
    switch(ext_hdr_options_process()) {
      case 0:
        /*continue*/
        uip_next_hdr = &UIP_EXT_BUF->next;
        uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
        break;
      case 1:
        /*silently discard*/
        goto drop;
      case 2:
        /* send icmp error message (created in ext_hdr_options_process)
         * and discard*/
        goto send;
    }
  }


  /* TBD Some Parameter problem messages */
  if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr) &&
     !uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) {
    if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr) &&
       !uip_is_addr_link_local(&UIP_IP_BUF->destipaddr) &&
       !uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr) &&
       !uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr) &&
       !uip_is_addr_loopback(&UIP_IP_BUF->destipaddr)) {


      /* Check MTU */
      if(uip_len > UIP_LINK_MTU) {
        uip_icmp6_error_output(ICMP6_PACKET_TOO_BIG, 0, UIP_LINK_MTU);
        goto send;
      }
      /* Check Hop Limit */
      if(UIP_IP_BUF->ttl <= 1) {
        uip_icmp6_error_output(ICMP6_TIME_EXCEEDED,
                               ICMP6_TIME_EXCEED_TRANSIT, 0);
        goto send;
      }

      UIP_IP_BUF->ttl = UIP_IP_BUF->ttl - 1;
      PRINTF("Forwarding packet to ");
      PRINT6ADDR(&UIP_IP_BUF->destipaddr);
      PRINTF("\n");
      goto send;
    } else {
      if((uip_is_addr_link_local(&UIP_IP_BUF->srcipaddr)) &&
         (!uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) &&
         (!uip_is_addr_loopback(&UIP_IP_BUF->destipaddr)) &&
         (!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) &&
         (!uip_ds6_is_addr_onlink((&UIP_IP_BUF->destipaddr)))) {
        PRINTF("LL source address with off link destination, dropping\n");
        uip_icmp6_error_output(ICMP6_DST_UNREACH,
                               ICMP6_DST_UNREACH_NOTNEIGHBOR, 0);
        goto send;
      }
      PRINTF("Dropping packet, not for me and link local or multicast\n");
      goto drop;
    }
  }

  while(1) {
    switch(*uip_next_hdr){
      case UIP_PROTO_ICMP6:
        /* ICMPv6 */
        goto icmp6_input;
      case UIP_PROTO_HBHO:
        PRINTF("Processing hbh header\n");
        /* Hop by hop option header */
#if UIP_CONF_IPV6_CHECKS
        /* Hop by hop option header. If we saw one HBH already, drop */
        if(uip_ext_bitmap & UIP_EXT_HDR_BITMAP_HBHO) {
          goto bad_hdr;
        } else {
          uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_HBHO;
        }
#endif /*UIP_CONF_IPV6_CHECKS*/
        switch(ext_hdr_options_process()) {
          case 0:
            /*continue*/
            uip_next_hdr = &UIP_EXT_BUF->next;
            uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
            break;
          case 1:
            /*silently discard*/
            goto drop;
          case 2:
            /* send icmp error message (created in ext_hdr_options_process)
             * and discard*/
            goto send;
        }
        break;
      case UIP_PROTO_DESTO:
#if UIP_CONF_IPV6_CHECKS
        /* Destination option header. if we saw two already, drop */
        PRINTF("Processing desto header\n");
        if(uip_ext_bitmap & UIP_EXT_HDR_BITMAP_DESTO1) {
          if(uip_ext_bitmap & UIP_EXT_HDR_BITMAP_DESTO2) {
            goto bad_hdr;
          } else{
            uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_DESTO2;
          }
        } else {
          uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_DESTO1;
        }
#endif /*UIP_CONF_IPV6_CHECKS*/
        switch(ext_hdr_options_process()) {
          case 0:
            /*continue*/
            uip_next_hdr = &UIP_EXT_BUF->next;
            uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
            break;
          case 1:
            /*silently discard*/
            goto drop;
          case 2:
            /* send icmp error message (created in ext_hdr_options_process)
             * and discard*/
            goto send;
        }
        break;
      case UIP_PROTO_ROUTING:
#if UIP_CONF_IPV6_CHECKS
        /* Routing header. If we saw one already, drop */
        if(uip_ext_bitmap & UIP_EXT_HDR_BITMAP_ROUTING) {
          goto bad_hdr;
        } else {
          uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_ROUTING;
        }
#endif /*UIP_CONF_IPV6_CHECKS*/
        /*
         * Routing Header  length field is in units of 8 bytes, excluding
         * As per RFC2460 section 4.4, if routing type is unrecognized:
         * if segments left = 0, ignore the header
         * if segments left > 0, discard packet and send icmp error pointing
         * to the routing type
         */

        PRINTF("Processing Routing header\n");
        if(UIP_ROUTING_BUF->seg_left > 0) {
          uip_icmp6_error_output(ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, UIP_IPH_LEN + uip_ext_len + 2);
          goto send;
        }
        uip_next_hdr = &UIP_EXT_BUF->next;
        uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
        break;
      case UIP_PROTO_FRAG:
        /* Fragmentation header:call the reassembly function, then leave */
        goto drop;
      case UIP_PROTO_NONE:
        goto drop;
      default:
        goto bad_hdr;
    }
  }
  bad_hdr:
  /*
   * RFC 2460 send error message parameterr problem, code unrecognized
   * next header, pointing to the next header field
   */
  uip_icmp6_error_output(ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER, (u32_t)(uip_next_hdr - (uint8_t *)UIP_IP_BUF));
  goto send;
  /* End of headers processing */
  
  icmp6_input:
  /* This is IPv6 ICMPv6 processing code. */
  PRINTF("icmp6_input: length %d\n", uip_len);

#if UIP_CONF_IPV6_CHECKS
  /* Compute and check the ICMP header checksum */
  if(uip_icmp6chksum() != 0xffff) {
    goto drop;
  }
#endif /*UIP_CONF_IPV6_CHECKS*/

  /*
   * Here we process incoming ICMPv6 packets
   * For echo request, we send echo reply
   * For ND pkts, we call the appropriate function in uip-nd6.c
   * We do not treat Error messages for now
   * If no pkt is to be sent as an answer to the incoming one, we
   * "goto drop". Else we just break; then at the after the "switch"
   * we "goto send"
   */
  switch(UIP_ICMP_BUF->type) {
    case ICMP6_NS:
      uip_len = 0;
      break;
    case ICMP6_NA:
      uip_len = 0;
      break;
    case ICMP6_RS:
      uip_len = 0;
      break;
    case ICMP6_RA:
      uip_len = 0;
      break;
    case ICMP6_RPL:
      uip_rpl_input();
      break;
    case ICMP6_ECHO_REQUEST:
      uip_icmp6_echo_request_input();
      break;
    case ICMP6_ECHO_REPLY:
      /** \note We don't implement any application callback for now */
      PRINTF("Received an icmp6 echo reply\n");
      uip_len = 0;
      break;
    default:
      PRINTF("Unknown icmp6 message type %d\n", UIP_ICMP_BUF->type);
      uip_len = 0;
      break;
  }

  if(uip_len > 0) {
    goto send;
  } else {
    goto drop;
  }
  /* End of IPv6 ICMP processing. */

  UIP_IP_BUF->vtc = 0x60;
  UIP_IP_BUF->tcflow = 0x00;
  UIP_IP_BUF->flow = 0x00;
 send:
  PRINTF("Sending packet with length %d (%d)\n", uip_len,
         (UIP_IP_BUF->len[0] << 8) | UIP_IP_BUF->len[1]);
  /* Return and let the caller do the actual transmission. */
  return;

 drop:
  uip_len = 0;
  uip_ext_len = 0;
  uip_ext_bitmap = 0;
  return;
}