void border_process_lowpan(void) { msg_t m; struct ipv6_hdr_t *ipv6_buf; while(1) { msg_receive(&m); ipv6_buf = (struct ipv6_hdr_t *)m.content.ptr; if(ipv6_buf->nextheader == PROTO_NUM_ICMPV6) { struct icmpv6_hdr_t *icmp_buf = (struct icmpv6_hdr_t *)(((uint8_t *)ipv6_buf) + IPV6_HDR_LEN); if(icmp_buf->type == ICMP_REDIRECT) { continue; } if(icmpv6_demultiplex(icmp_buf) == 0) { continue; } /* Here, other ICMPv6 message types for ND may follow. */ } /* TODO: Bei ICMPv6-Paketen entsprechende LoWPAN-Optionen verarbeiten und entfernen */ multiplex_send_ipv6_over_uart(ipv6_buf); } }
void *ipv6_process(void *arg) { (void) arg; msg_t m_recv_lowpan, m_send_lowpan; msg_t m_recv, m_send; uint8_t i; uint16_t packet_length; msg_init_queue(ip_msg_queue, IP_PKT_RECV_BUF_SIZE); while (1) { msg_receive(&m_recv_lowpan); ipv6_buf = (ipv6_hdr_t *)m_recv_lowpan.content.ptr; /* identifiy packet */ nextheader = &ipv6_buf->nextheader; for (i = 0; i < SIXLOWIP_MAX_REGISTERED; i++) { if (sixlowip_reg[i]) { msg_t m_send; m_send.type = IPV6_PACKET_RECEIVED; m_send.content.ptr = (char *) ipv6_buf; msg_send(&m_send, sixlowip_reg[i], 1); } } /* destination is our address */ if (is_our_address(&ipv6_buf->destaddr)) { switch (*nextheader) { case (IPV6_PROTO_NUM_ICMPV6): { icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len); /* checksum test*/ if (ipv6_csum(ipv6_buf, (uint8_t *) icmp_buf, NTOHS(ipv6_buf->length), IPV6_PROTO_NUM_ICMPV6) != 0xffff) { DEBUG("ERROR: wrong checksum\n"); } icmpv6_demultiplex(icmp_buf); break; } case (IPV6_PROTO_NUM_TCP): { if (tcp_packet_handler_pid != KERNEL_PID_UNDEF) { m_send.content.ptr = (char *) ipv6_buf; msg_send_receive(&m_send, &m_recv, tcp_packet_handler_pid); } else { DEBUG("INFO: No TCP handler registered.\n"); } break; } case (IPV6_PROTO_NUM_UDP): { if (udp_packet_handler_pid != KERNEL_PID_UNDEF) { m_send.content.ptr = (char *) ipv6_buf; msg_send_receive(&m_send, &m_recv, udp_packet_handler_pid); } else { DEBUG("INFO: No UDP handler registered.\n"); } break; } case (IPV6_PROTO_NUM_NONE): { DEBUG("INFO: Packet with no Header following the IPv6 Header received.\n"); break; } default: DEBUG("INFO: Unknown next header\n"); break; } } /* destination is foreign address */ else { DEBUG("That's not for me, destination is %s\n", ipv6_addr_to_str(addr_str, IPV6_MAX_ADDR_STR_LEN, &ipv6_buf->destaddr)); packet_length = IPV6_HDR_LEN + NTOHS(ipv6_buf->length); ndp_neighbor_cache_t *nce; ipv6_addr_t *dest; if (ip_get_next_hop == NULL) { dest = &ipv6_buf->destaddr; } else { dest = ip_get_next_hop(&ipv6_buf->destaddr); } if ((dest == NULL) || ((--ipv6_buf->hoplimit) == 0)) { DEBUG("!!! Packet not for me, routing handler is set, but I "\ " have no idea where to send or the hop limit is exceeded.\n"); msg_reply(&m_recv_lowpan, &m_send_lowpan); continue; } nce = ndp_get_ll_address(dest); /* copy received packet to send buffer */ memcpy(ipv6_get_buf_send(), ipv6_get_buf(), packet_length); /* send packet to node ID derived from dest IP */ if (nce != NULL) { sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr, nce->lladdr_len, (uint8_t *)ipv6_get_buf_send(), packet_length); } else { /* XXX: this is wrong, but until ND does work correctly, * this is the only way (aka the old way)*/ uint16_t raddr = dest->uint16[7]; sixlowpan_lowpan_sendto(0, &raddr, 2, (uint8_t *)ipv6_get_buf_send(), packet_length); } } msg_reply(&m_recv_lowpan, &m_send_lowpan); } }