示例#1
0
文件: ip.c 项目: Rossano/RIOT
int ipv6_send_packet(ipv6_hdr_t *packet)
{
    uint16_t length = IPV6_HDR_LEN + NTOHS(packet->length);
    ndp_neighbor_cache_t *nce;

    ipv6_net_if_get_best_src_addr(&packet->srcaddr, &packet->destaddr);

    if (!ipv6_addr_is_multicast(&packet->destaddr) &&
        ndp_addr_is_on_link(&packet->destaddr)) {
        nce = ndp_get_ll_address(&packet->destaddr);


        if (nce == NULL || sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr,
                nce->lladdr_len,
                (uint8_t *)packet,
                length) < 0) {
            /* XXX: this is wrong, but until ND does not work correctly,
             *      this is the only way (aka the old way)*/
            uint16_t raddr = NTOHS(packet->destaddr.uint16[7]);
            sixlowpan_lowpan_sendto(0, &raddr, 2, (uint8_t *)packet, length);
            /* return -1; */
        }

        return length;
    }
    else {
        /* see if dest should be routed to a different next hop */
        if (ipv6_addr_is_multicast(&packet->destaddr)) {
            /* if_id will be ignored */
            uint16_t addr = 0xffff;
            return sixlowpan_lowpan_sendto(0, &addr, 2, (uint8_t *)packet,
                                           length);
        }

        if (ip_get_next_hop == NULL) {
            return -1;
        }

        ipv6_addr_t *dest = ip_get_next_hop(&packet->destaddr);

        if (dest == NULL) {
            return -1;
        }

        nce = ndp_get_ll_address(&packet->destaddr);

        if (nce == NULL || sixlowpan_lowpan_sendto(nce->if_id, &nce->lladdr,
                nce->lladdr_len,
                (uint8_t *)packet, length) < 0) {
            /* XXX: this is wrong, but until ND does not work correctly,
             *      this is the only way (aka the old way)*/
            uint16_t raddr = NTOHS(packet->destaddr.uint16[7]);
            sixlowpan_lowpan_sendto(0, &raddr, 2, (uint8_t *)packet, length);
            /* return -1; */
        }

        return length;
    }
}
示例#2
0
文件: ip.c 项目: A-L-E-X/RIOT
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);
    }
}