//void process_data_from_event(NewDataEvent *e) int resolve_protocol_type(NewDataEvent *e) { struct uip_tcpip_hdr * tcpip_hdr; struct uip_icmp_hdr * icmp_hdr; int rtc; tcpip_hdr = ( struct uip_tcpip_hdr *) &e->buf[UIP_LLH_LEN]; //only process IPV6 Packets if (IP_VERSION_V6 != tcpip_hdr->vtc) return ( IP_VERSION_NOT_SUPPORTED); if ( !uip_is_multicast(tcpip_hdr->destipaddr) && !uip_is_hostaddr(&tcpip_hdr->destipaddr) ) { e->super.sig = SEND_DATA_SIG; QF_publish((QEvent *) e); return ( IP_MULI_CAST_CHECK ); } //if not multicast and not for my interfaces //find target interface through prefix //send to if (tcpip_hdr->proto == UIP_PROTO_ICMP6) { icmp_hdr = (struct uip_icmp_hdr *)&e->buf[uip_l2_l3_hdr_len]; switch(icmp_hdr->type) { case ICMP6_NS: uip_nd6_io_ns_input((NewDataEvent *)e); break; case ICMP6_NA: uip_nd6_io_na_input((NewDataEvent *) e); break; case ICMP6_RA: //uip_nd6_io_ra_input(); break; case ICMP6_RS: //uip_nd6_io_rs_input(); break; case ICMP6_ECHO_REQUEST: uip_icmp6_echo_request_input((NewDataEvent *)e); break; case ICMP6_ECHO_REPLY: /** \note We don't implement any application callback for now */ uip_icmp6_echo_reply_input((NewDataEvent *)e); printf("Received an icmp6 echo reply\n"); break; default: printf("Unknown icmp6 message type %d\n", icmp_hdr->type); break; } rtc=UIP_PROTO_ICMP6; } if (tcpip_hdr->proto == UIP_PROTO_UDP) rtc=UIP_PROTO_UDP; return (rtc); }
/*---------------------------------------------------------------------------*/ 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; }