示例#1
0
文件: sixlownd.c 项目: maxmue/RIOT
void init_para_prob(ipv6_addr_t *src, ipv6_addr_t *dest, uint8_t code, uint32_t pointer, uint8_t *packet, uint8_t packet_len)
{
    struct para_prob_t *para_prob_buf;


    packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + PARA_PROB_LEN;

    memcpy(&(ipv6_buf[packet_length]), packet, min(MTU - packet_length, packet_len));

    ipv6_buf = get_ipv6_buf();
    ipv6_buf->version_trafficclass = IPV6_VER;
    ipv6_buf->trafficclass_flowlabel = 0;
    ipv6_buf->flowlabel = 0;
    ipv6_buf->nextheader = PROTO_NUM_ICMPV6;
    ipv6_buf->hoplimit = ND_HOPLIMIT;

    ipv6_ext_hdr_len = 0;
    icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len);
    icmp_buf->type = ICMP_PARA_PROB;
    icmp_buf->code = code;

    memcpy(&(ipv6_buf->destaddr.uint8[0]), &(dest->uint8[0]), 16);
    memcpy(&(ipv6_buf->srcaddr.uint8[0]), &(src->uint8[0]), 16);

    para_prob_buf = get_para_prob_buf(ipv6_ext_hdr_len);

    para_prob_buf->pointer = pointer;

    packet_length += min(MTU - packet_length, packet_len);

    ipv6_buf->length = packet_length - IPV6_HDR_LEN;

    icmp_buf->checksum = 0;
    icmp_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6);
}
示例#2
0
文件: sixlownd.c 项目: maxmue/RIOT
void init_nbr_adv(ipv6_addr_t *src, ipv6_addr_t *dst, ipv6_addr_t *tgt,
                  uint8_t rso, uint8_t sllao, uint8_t aro, uint8_t aro_state)
{
    ipv6_buf = get_ipv6_buf();
    ipv6_buf->version_trafficclass = IPV6_VER;
    ipv6_buf->trafficclass_flowlabel = 0;
    ipv6_buf->flowlabel = 0;
    ipv6_buf->nextheader = PROTO_NUM_ICMPV6;
    ipv6_buf->hoplimit = ND_HOPLIMIT;

    ipv6_ext_hdr_len = 0;
    icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len);
    icmp_buf->type = ICMP_NBR_ADV;
    icmp_buf->code = 0;

    memcpy(&(ipv6_buf->destaddr.uint8[0]), &(dst->uint8[0]), 16);
    memcpy(&(ipv6_buf->srcaddr.uint8[0]), &(src->uint8[0]), 16);

    nbr_adv_buf = get_nbr_adv_buf(ipv6_ext_hdr_len);
    nbr_adv_buf->rso = rso;

    memset(&(nbr_adv_buf->reserved[0]), 0, 3);
    memcpy(&(nbr_adv_buf->tgtaddr.uint8[0]), &(tgt->uint8[0]), 16);

    packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + NBR_ADV_LEN;

    if (sllao == OPT_SLLAO) {
        /* set sllao option */
        opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len);
        set_llao(opt_stllao_buf, OPT_SLLAO_TYPE, 1);
        opt_hdr_len += OPT_STLLAO_MIN_LEN;

        packet_length += OPT_STLLAO_MIN_LEN;
    }

    if (aro == OPT_ARO) {
        /* set aro option */
        opt_aro_buf = get_opt_aro_buf(ipv6_ext_hdr_len, opt_hdr_len);
        opt_aro_buf->type = OPT_ARO_TYPE;
        opt_aro_buf->length = OPT_ARO_LEN;
        opt_aro_buf->status = 0;    /* TODO */
        opt_aro_buf->reserved1 = 0;
        opt_aro_buf->reserved2 = 0;
        memcpy(&(opt_aro_buf->eui64), mac_get_eui(dst), 8);
        opt_hdr_len += OPT_ARO_HDR_LEN;

        packet_length += OPT_ARO_HDR_LEN;
    }

    ipv6_buf->length = packet_length - IPV6_HDR_LEN;

    icmp_buf->checksum = 0;
    icmp_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6);
}
示例#3
0
文件: sixlownd.c 项目: maxmue/RIOT
uint16_t icmpv6_csum(uint8_t proto)
{
    ipv6_buf = get_ipv6_buf();
    uint16_t sum;
    uint16_t len = ipv6_buf->length;
    sum = len + proto;

    sum = csum(sum, (uint8_t *)&ipv6_buf->srcaddr, 2 * sizeof(ipv6_addr_t));
    sum = csum(sum, (uint8_t *)get_icmpv6_buf(0), len);

    return (sum == 0) ? 0xffff : HTONS(sum);
}
示例#4
0
文件: sixlownd.c 项目: maxmue/RIOT
/* send router solicitation message - RFC4861 section 4.1 */
void init_rtr_sol(uint8_t sllao)
{
    ipv6_buf = get_ipv6_buf();
    icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len);

    packet_length = 0;

    icmp_buf->type = ICMP_RTR_SOL;
    icmp_buf->code = 0;
    ipv6_buf->version_trafficclass = IPV6_VER;
    ipv6_buf->trafficclass_flowlabel = 0;
    ipv6_buf->flowlabel = 0;
    ipv6_buf->nextheader = PROTO_NUM_ICMPV6;
    ipv6_buf->hoplimit = ND_HOPLIMIT;

    ipv6_set_all_rtrs_mcast_addr(&ipv6_buf->destaddr);
    //iface_find_src_ipaddr(&ipv6_buf->srcaddr, ADDR_STATE_PREFERRED,
    /*                      ADDR_TYPE_MULTICAST); */

    ipv6_get_saddr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr));

    opt_hdr_len = RTR_SOL_LEN;
    ipv6_buf->length = ICMPV6_HDR_LEN + RTR_SOL_LEN + OPT_STLLAO_MAX_LEN;

    if (sllao == OPT_SLLAO) {
        opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len);
        set_llao(opt_stllao_buf, OPT_SLLAO_TYPE, 2);
        packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len +
                        RTR_SOL_LEN + OPT_STLLAO_MAX_LEN;
    }
    else {
        packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + ipv6_ext_hdr_len +
                        RTR_SOL_LEN;
    }

    icmp_buf->checksum = 0;
    icmp_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6);

#if ENABLE_DEBUG
    printf("INFO: send router solicitation to: ");
    ipv6_print_addr(&ipv6_buf->destaddr);
#endif
    lowpan_init((ieee_802154_long_t *)&(ipv6_buf->destaddr.uint16[4]),
                (uint8_t *)ipv6_buf);
}
示例#5
0
文件: sixlownd.c 项目: maxmue/RIOT
void init_nbr_sol(ipv6_addr_t *src, ipv6_addr_t *dest, ipv6_addr_t *targ,
                  uint8_t sllao, uint8_t aro)
{
    ipv6_buf = get_ipv6_buf();
    ipv6_buf->version_trafficclass = IPV6_VER;
    ipv6_buf->trafficclass_flowlabel = 0;
    ipv6_buf->flowlabel = 0;
    ipv6_buf->nextheader = PROTO_NUM_ICMPV6;
    ipv6_buf->hoplimit = ND_HOPLIMIT;

    if (dest == NULL) {
        ipv6_set_sol_node_mcast_addr(targ, &(ipv6_buf->destaddr));
    }
    else {
        memcpy(&(ipv6_buf->destaddr.uint8[0]), &(dest->uint8[0]), 16);
    }

    ipv6_ext_hdr_len = 0;
    icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len);
    icmp_buf->type = ICMP_NBR_SOL;
    icmp_buf->code = 0;

    nbr_sol_buf = get_nbr_sol_buf(ipv6_ext_hdr_len);
    nbr_sol_buf->reserved = 0;
    memcpy(&(nbr_sol_buf->tgtaddr), targ, 16);
    opt_hdr_len = NBR_SOL_LEN;

    packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + NBR_SOL_LEN;

    if (ipv6_iface_addr_match(targ) == NULL) {
        if (src == NULL) {
            ipv6_get_saddr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr));
        }
        else {
            memcpy(&(ipv6_buf->srcaddr), src, 16);
        }

        if (sllao == OPT_SLLAO) {
            /* set sllao option */
            opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len);
            set_llao(opt_stllao_buf, OPT_SLLAO_TYPE, 1);
            opt_hdr_len += OPT_STLLAO_MIN_LEN;

            packet_length += OPT_STLLAO_MIN_LEN;
        }
    }

    if (aro == OPT_ARO) {
        /* set aro option */
        opt_aro_buf = get_opt_aro_buf(ipv6_ext_hdr_len, opt_hdr_len);
        opt_aro_buf->type = OPT_ARO_TYPE;
        opt_aro_buf->length = OPT_ARO_LEN;
        opt_aro_buf->status = 0;
        opt_aro_buf->reserved1 = 0;
        opt_aro_buf->reserved2 = 0;
        memcpy(&(opt_aro_buf->eui64), mac_get_eui(src), 8);
        opt_hdr_len += OPT_ARO_HDR_LEN;

        packet_length += OPT_ARO_HDR_LEN;
    }

    ipv6_buf->length = packet_length - IPV6_HDR_LEN;

    icmp_buf->checksum = 0;
    icmp_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6);
}
示例#6
0
文件: sixlownd.c 项目: maxmue/RIOT
void init_rtr_adv(ipv6_addr_t *addr, uint8_t sllao, uint8_t mtu, uint8_t pi, 
                  uint8_t sixco, uint8_t abro)
{
    lowpan_context_t *contexts = NULL;

    abr_cache_t *msg_abr = NULL;
    ipv6_buf = get_ipv6_buf();
    icmp_buf = get_icmpv6_buf(ipv6_ext_hdr_len);

    ipv6_buf->version_trafficclass = IPV6_VER;
    ipv6_buf->trafficclass_flowlabel = 0;
    ipv6_buf->flowlabel = 0;
    ipv6_buf->nextheader = PROTO_NUM_ICMPV6;
    ipv6_buf->hoplimit = ND_HOPLIMIT;

    if (addr == NULL) {
        /* not solicited */
        ipv6_set_all_nds_mcast_addr(&ipv6_buf->destaddr);
    }
    else {
        memcpy(&ipv6_buf->destaddr, addr, 16);
    }

    ipv6_get_saddr(&(ipv6_buf->srcaddr), &(ipv6_buf->destaddr));

    icmp_buf->type = ICMP_RTR_ADV;
    icmp_buf->code = 0;

    //TODO: gethoplimit func, set current ttl

    rtr_adv_buf = get_rtr_adv_buf(ipv6_ext_hdr_len);
    rtr_adv_buf->hoplimit = MULTIHOP_HOPLIMIT;
    /* set M and O flag, last 6 bits are zero */
    rtr_adv_buf->autoconfig_flags = (RTR_ADV_M_FLAG << 7) | (RTR_ADV_O_FLAG << 6);
    rtr_adv_buf->router_lifetime = HTONS(RTR_ADV_MAX_INTERVAL * RTR_ADV_MAX);
    rtr_adv_buf->reachable_time = 0;
    rtr_adv_buf->retrans_timer = 0;
    opt_hdr_len = RTR_ADV_LEN;

    packet_length = IPV6_HDR_LEN + ICMPV6_HDR_LEN + RTR_ADV_LEN;

    if (sllao == OPT_SLLAO) {
        /* set link layer address option */
        opt_stllao_buf = get_opt_stllao_buf(ipv6_ext_hdr_len, opt_hdr_len);
        set_llao(opt_stllao_buf, OPT_SLLAO_TYPE, 2);
        opt_hdr_len += OPT_STLLAO_MAX_LEN;
        packet_length += OPT_STLLAO_MAX_LEN;
    }

    if (mtu == OPT_MTU) {
        /* set MTU options */
        opt_mtu_buf = get_opt_mtu_buf(ipv6_ext_hdr_len, opt_hdr_len);
        opt_mtu_buf->type = OPT_MTU_TYPE;
        opt_mtu_buf->length = OPT_MTU_LEN;
        opt_mtu_buf->reserved = 0;
        opt_mtu_buf->mtu = HTONL(1500);
        opt_hdr_len += OPT_MTU_HDR_LEN;
        packet_length += OPT_MTU_HDR_LEN;
    }

    /* set payload length field */

    if (abro == OPT_ABRO) {
        /* set authoritive border router option */
        if (abr_count > 0) {
            msg_abr = abr_get_most_current();
            opt_abro_buf = get_opt_abro_buf(ipv6_ext_hdr_len, opt_hdr_len);
            opt_abro_buf->type = OPT_ABRO_TYPE;
            opt_abro_buf->length = OPT_ABRO_LEN;
            opt_abro_buf->version = HTONS(msg_abr->version);
            opt_abro_buf->reserved = 0;
            memcpy(&(opt_abro_buf->addr), &(msg_abr->abr_addr), sizeof(ipv6_addr_t));
        }
    }

    if (sixco == OPT_6CO) {
        /* set 6lowpan context option */
        int contexts_len = 0;
        mutex_lock(&lowpan_context_mutex);

        if (msg_abr == NULL) {
            contexts = lowpan_context_get();
            contexts_len = lowpan_context_len();
        }
        else {
            lowpan_context_t c_tmp[LOWPAN_CONTEXT_MAX];

            contexts_len = 0;

            for (int i = 0; i < LOWPAN_CONTEXT_MAX; i++) {
                lowpan_context_t *ctx = abr_get_context(msg_abr, i);

                if (ctx != NULL) {
                    memcpy(&(c_tmp[contexts_len++]), ctx, sizeof(lowpan_context_t));
                }
            }

            contexts = (lowpan_context_t *)calloc(contexts_len, sizeof(lowpan_context_t));
            memcpy(contexts, c_tmp, contexts_len);
        }

        for (int i = 0; i < contexts_len; i++) {
            opt_6co_hdr_buf = get_opt_6co_hdr_buf(ipv6_ext_hdr_len, opt_hdr_len);
            opt_6co_hdr_buf->type = OPT_6CO_TYPE;

            if (contexts[i].length > 64) {
                opt_6co_hdr_buf->length = OPT_6CO_MAX_LEN;
            }
            else {
                opt_6co_hdr_buf->length = OPT_6CO_MIN_LEN;
            }

            opt_6co_hdr_buf->c_length = contexts[i].length;
            opt_6co_hdr_buf->c_flags = set_opt_6co_flags(contexts[i].comp, contexts[i].num);
            opt_6co_hdr_buf->reserved = 0;
            opt_6co_hdr_buf->val_ltime = HTONS(contexts[i].lifetime);

            opt_hdr_len += OPT_6CO_HDR_LEN;
            packet_length += OPT_6CO_HDR_LEN;
            /* attach prefixes */
            opt_6co_prefix_buf = get_opt_6co_prefix_buf(ipv6_ext_hdr_len, opt_hdr_len);

            if (opt_6co_hdr_buf->c_length > 64) {
                memset((void *)opt_6co_prefix_buf, 0, 16);
                memcpy((void *)opt_6co_prefix_buf, (void *) & (contexts[i].prefix.uint8[0]), opt_6co_hdr_buf->c_length / 8);
                opt_hdr_len += 16;
                packet_length += 16;
            }
            else {
                memset((void *)opt_6co_prefix_buf, 0, 8);
                memcpy((void *)opt_6co_prefix_buf, (void *) & (contexts[i].prefix.uint8[0]), opt_6co_hdr_buf->c_length / 8);
                opt_hdr_len += 8;
                packet_length += 8;
            }

        }

        if (msg_abr != NULL && contexts != NULL) {
            free(contexts);
        }

        mutex_unlock(&lowpan_context_mutex, 0);
    }

    if (pi == OPT_PI) {
        /* set prefix option */
        for (int i = 0; i < OPT_PI_LIST_LEN; i++) {
            if (plist[i].inuse && plist[i].adv) {
                opt_pi_buf = get_opt_pi_buf(ipv6_ext_hdr_len, opt_hdr_len);
                memcpy(&(opt_pi_buf->addr.uint8[0]), &(plist[i].addr.uint8[0]), 16);
                opt_pi_buf->type = OPT_PI_TYPE;
                opt_pi_buf->length = OPT_PI_LEN;
                opt_pi_buf->prefix_length = plist[i].length;
                opt_pi_buf->l_a_reserved1 = plist[i].l_a_reserved1;
                opt_pi_buf->val_ltime = HTONL(plist[i].val_ltime);
                opt_pi_buf->pref_ltime = HTONL(plist[i].pref_ltime);
                opt_pi_buf->reserved2 = 0;
                packet_length += OPT_PI_HDR_LEN;
                opt_hdr_len += OPT_PI_HDR_LEN;
            }
        }
    }

    ipv6_buf->length = packet_length - IPV6_HDR_LEN;

    /* calculate checksum */
    icmp_buf->checksum = 0;
    icmp_buf->checksum = ~icmpv6_csum(PROTO_NUM_ICMPV6);
}
示例#7
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);
    }
}