예제 #1
0
static void _send_to_iface(kernel_pid_t iface, gnrc_pktsnip_t *pkt)
{
    ((gnrc_netif_hdr_t *)pkt->data)->if_pid = iface;
    gnrc_ipv6_netif_t *if_entry = gnrc_ipv6_netif_get(iface);

    assert(if_entry != NULL);
    if (gnrc_pkt_len(pkt->next) > if_entry->mtu) {
        DEBUG("ipv6: packet too big\n");
        gnrc_pktbuf_release(pkt);
        return;
    }
#ifdef MODULE_NETSTATS_IPV6
    if_entry->stats.tx_success++;
    if_entry->stats.tx_bytes += gnrc_pkt_len(pkt->next);
#endif

#ifdef MODULE_GNRC_SIXLOWPAN
    if (if_entry->flags & GNRC_IPV6_NETIF_FLAGS_SIXLOWPAN) {
        DEBUG("ipv6: send to 6LoWPAN instead\n");
        if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_SIXLOWPAN, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) {
            DEBUG("ipv6: no 6LoWPAN thread found");
            gnrc_pktbuf_release(pkt);
        }
        return;
    }
#endif
    if (gnrc_netapi_send(iface, pkt) < 1) {
        DEBUG("ipv6: unable to send packet\n");
        gnrc_pktbuf_release(pkt);
    }
}
예제 #2
0
void gnrc_icmpv6_echo_req_handle(gnrc_netif_t *netif, ipv6_hdr_t *ipv6_hdr,
                                 icmpv6_echo_t *echo, uint16_t len)
{
    uint8_t *payload = ((uint8_t *)echo) + sizeof(icmpv6_echo_t);
    gnrc_pktsnip_t *hdr, *pkt;

    if ((echo == NULL) || (len < sizeof(icmpv6_echo_t))) {
        DEBUG("icmpv6_echo: echo was NULL or len (%" PRIu16
              ") was < sizeof(icmpv6_echo_t)\n", len);
        return;
    }

    pkt = gnrc_icmpv6_echo_build(ICMPV6_ECHO_REP, byteorder_ntohs(echo->id),
                                 byteorder_ntohs(echo->seq), payload,
                                 len - sizeof(icmpv6_echo_t));

    if (pkt == NULL) {
        DEBUG("icmpv6_echo: no space left in packet buffer\n");
        return;
    }

    if (ipv6_addr_is_multicast(&ipv6_hdr->dst)) {
        hdr = gnrc_ipv6_hdr_build(pkt, NULL, &ipv6_hdr->src);
    }
    else {
        hdr = gnrc_ipv6_hdr_build(pkt, &ipv6_hdr->dst, &ipv6_hdr->src);
    }

    if (hdr == NULL) {
        DEBUG("icmpv6_echo: no space left in packet buffer\n");
        gnrc_pktbuf_release(pkt);
        return;
    }

    pkt = hdr;
    hdr = gnrc_netif_hdr_build(NULL, 0, NULL, 0);

    if (netif != NULL) {
        ((gnrc_netif_hdr_t *)hdr->data)->if_pid = netif->pid;
    }
    else {
        /* ipv6_hdr->dst is loopback address */
        ((gnrc_netif_hdr_t *)hdr->data)->if_pid = KERNEL_PID_UNDEF;
    }

    LL_PREPEND(pkt, hdr);

    if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_IPV6, GNRC_NETREG_DEMUX_CTX_ALL,
                                   pkt)) {
        DEBUG("icmpv6_echo: no receivers for IPv6 packets\n");
        gnrc_pktbuf_release(pkt);
    }
}
예제 #3
0
void _gnrc_rpl_send(gnrc_pktsnip_t *pkt, ipv6_addr_t *src, ipv6_addr_t *dst,
        ipv6_addr_t *dodag_id)
{
    gnrc_pktsnip_t *hdr;
    ipv6_addr_t all_RPL_nodes = GNRC_RPL_ALL_NODES_ADDR, ll_addr;
    kernel_pid_t iface = gnrc_ipv6_netif_find_by_addr(NULL, &all_RPL_nodes);
    if (iface == KERNEL_PID_UNDEF) {
        DEBUG("RPL: no suitable interface found for this destination address\n");
        gnrc_pktbuf_release(pkt);
        return;
    }

    if (src == NULL) {
        ipv6_addr_t *tmp = NULL;
        if (dodag_id != NULL) {
            tmp = gnrc_ipv6_netif_match_prefix(iface, dodag_id);
        }
        else if (dodag_id == NULL) {
            tmp = gnrc_ipv6_netif_find_best_src_addr(iface, &all_RPL_nodes);
        }

        if (tmp == NULL) {
            DEBUG("RPL: no suitable src address found\n");
            gnrc_pktbuf_release(pkt);
            return;
        }

        memcpy(&ll_addr, tmp, sizeof(ll_addr));
        ipv6_addr_set_link_local_prefix(&ll_addr);
        src = &ll_addr;
    }

    if (dst == NULL) {
        dst = &all_RPL_nodes;
    }

    hdr = gnrc_ipv6_hdr_build(pkt, (uint8_t *)src, sizeof(ipv6_addr_t), (uint8_t *)dst,
                            sizeof(ipv6_addr_t));

    if (hdr == NULL) {
        DEBUG("RPL: Send - no space left in packet buffer\n");
        gnrc_pktbuf_release(pkt);
        return;
    }

    if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_IPV6, GNRC_NETREG_DEMUX_CTX_ALL,hdr)) {
        DEBUG("RPL: cannot send packet: no subscribers found.\n");
        gnrc_pktbuf_release(hdr);
    }

}
void gnrc_rpl_send(gnrc_pktsnip_t *pkt, kernel_pid_t iface, ipv6_addr_t *src, ipv6_addr_t *dst,
                   ipv6_addr_t *dodag_id)
{
    (void)dodag_id;
    gnrc_pktsnip_t *hdr;
    if (iface == KERNEL_PID_UNDEF) {
        if ((iface = gnrc_ipv6_netif_find_by_addr(NULL, &ipv6_addr_all_rpl_nodes))
            == KERNEL_PID_UNDEF) {
            DEBUG("RPL: no suitable interface found for this destination address\n");
            gnrc_pktbuf_release(pkt);
            return;
        }
    }

    if (src == NULL) {
        src = gnrc_ipv6_netif_match_prefix(iface, &ipv6_addr_link_local_prefix);

        if (src == NULL) {
            DEBUG("RPL: no suitable src address found\n");
            gnrc_pktbuf_release(pkt);
            return;
        }
    }

    if (dst == NULL) {
        dst = (ipv6_addr_t *) &ipv6_addr_all_rpl_nodes;
    }

    hdr = gnrc_ipv6_hdr_build(pkt, src, dst);

    if (hdr == NULL) {
        DEBUG("RPL: Send - no space left in packet buffer\n");
        gnrc_pktbuf_release(pkt);
        return;
    }

    pkt = hdr;

    hdr = gnrc_netif_hdr_build(NULL, 0, NULL, 0);
    ((gnrc_netif_hdr_t *)hdr->data)->if_pid = iface;
    LL_PREPEND(pkt, hdr);

    if (!gnrc_netapi_dispatch_send(GNRC_NETTYPE_IPV6, GNRC_NETREG_DEMUX_CTX_ALL, pkt)) {
        DEBUG("RPL: cannot send packet: no subscribers found.\n");
        gnrc_pktbuf_release(pkt);
    }
}
예제 #5
0
int conn_udp_sendto(const void *data, size_t len, const void *src, size_t src_len,
                    const void *dst, size_t dst_len, int family, uint16_t sport,
                    uint16_t dport)
{
    gnrc_pktsnip_t *pkt, *hdr = NULL;

    pkt = gnrc_pktbuf_add(NULL, (void *)data, len, GNRC_NETTYPE_UNDEF); /* data will only be copied */
    hdr = gnrc_udp_hdr_build(pkt, (uint8_t *)&sport, sizeof(uint16_t), (uint8_t *)&dport,
                             sizeof(uint16_t));
    if (hdr == NULL) {
        gnrc_pktbuf_release(pkt);
        return -ENOMEM;
    }
    pkt = hdr;
    switch (family) {
#ifdef MODULE_GNRC_IPV6
        case AF_INET6:
            if (((src != NULL) && (src_len != sizeof(ipv6_addr_t))) ||
                (dst_len != sizeof(ipv6_addr_t))) {
                gnrc_pktbuf_release(pkt);
                return -EINVAL;
            }
            /* addr will only be copied */
            hdr = gnrc_ipv6_hdr_build(pkt, (uint8_t *)src, src_len, (uint8_t *)dst, dst_len);
            if (hdr == NULL) {
                gnrc_pktbuf_release(pkt);
                return -ENOMEM;
            }
            pkt = hdr;
            break;
#endif /* MODULE_GNRC_IPV6 */
        default:
            (void)hdr;
            (void)src;
            (void)src_len;
            (void)dst;
            (void)dst_len;
            gnrc_pktbuf_release(pkt);
            return -EAFNOSUPPORT;
    }

    gnrc_netapi_dispatch_send(GNRC_NETTYPE_UDP, GNRC_NETREG_DEMUX_CTX_ALL, pkt);

    return len;
}
예제 #6
0
파일: gnrc_conn_ip.c 프로젝트: JMR-b/RIOT
int conn_ip_sendto(const void *data, size_t len, const void *src, size_t src_len,
                   void *dst, size_t dst_len, int family, int proto)
{
    gnrc_pktsnip_t *pkt, *hdr = NULL;
    gnrc_nettype_t l3_type;

    pkt = gnrc_pktbuf_add(NULL, (void *)data, len, GNRC_NETTYPE_UNDEF); /* data will only be copied */

    switch (family) {
#ifdef MODULE_GNRC_IPV6
        case AF_INET6:
            if (((src != NULL) && (src_len != sizeof(ipv6_addr_t))) ||
                (dst_len != sizeof(ipv6_addr_t)) ||
                (((unsigned)proto) > 256U)) {
                gnrc_pktbuf_release(pkt);
                return -EINVAL;
            }
            /* addr will only be copied */
            hdr = gnrc_ipv6_hdr_build(pkt, (uint8_t *)src, src_len, (uint8_t *)dst, dst_len);
            if (hdr == NULL) {
                gnrc_pktbuf_release(pkt);
                return -ENOMEM;
            }
            /* set next header to connection's proto */
            ipv6_hdr_t *ipv6_hdr = hdr->data;
            ipv6_hdr->nh = (uint8_t)proto;
            pkt = hdr;
            l3_type = GNRC_NETTYPE_IPV6;
            break;
#endif /* MODULE_GNRC_IPV6 */
        default:
            (void)src;
            (void)src_len;
            (void)dst;
            (void)dst_len;
            (void)proto;
            (void)hdr;
            gnrc_pktbuf_release(pkt);
            return -EAFNOSUPPORT;
    }

    gnrc_netapi_dispatch_send(l3_type, GNRC_NETREG_DEMUX_CTX_ALL, pkt);

    return len;
}
예제 #7
0
tftp_state _tftp_send(gnrc_pktsnip_t *buf, tftp_context_t *ctxt, size_t len)
{
    network_uint16_t src_port, dst_port;
    gnrc_pktsnip_t *udp, *ip;

    assert(len <= TFTP_DEFAULT_DATA_SIZE);

    /* down-size the packet to it's used size */
    if (len > TFTP_DEFAULT_DATA_SIZE) {
        DEBUG("tftp: can't reallocate to bigger packet, buffer overflowed\n");
        gnrc_pktbuf_release(buf);

        if (ctxt->stop_cb) {
            ctxt->stop_cb(TFTP_INTERN_ERROR, "buffer overflowed");
        }

        return TS_FAILED;
    }
    else if (gnrc_pktbuf_realloc_data(buf, len) != 0) {
        assert(false);

        DEBUG("tftp: failed to reallocate data snippet\n");
        gnrc_pktbuf_release(buf);

        /* inform the user that we can't reallocate */
        if (ctxt->stop_cb) {
            ctxt->stop_cb(TFTP_INTERN_ERROR, "no reallocate");
        }

        return TS_FAILED;
    }

    /* allocate UDP header, set source port := destination port */
    src_port.u16 = ctxt->src_port;
    dst_port.u16 = ctxt->dst_port;
    udp = gnrc_udp_hdr_build(buf, src_port.u16, dst_port.u16);
    if (udp == NULL) {
        DEBUG("tftp: error unable to allocate UDP header\n");
        gnrc_pktbuf_release(buf);

        if (ctxt->stop_cb) {
            ctxt->stop_cb(TFTP_INTERN_ERROR, "no udp allocate");
        }

        return TS_FAILED;
    }

    /* allocate IPv6 header */
    ip = gnrc_ipv6_hdr_build(udp, NULL, &(ctxt->peer));
    if (ip == NULL) {
        DEBUG("tftp: error unable to allocate IPv6 header\n");
        gnrc_pktbuf_release(udp);

        if (ctxt->stop_cb) {
            ctxt->stop_cb(TFTP_INTERN_ERROR, "no ip allocate");
        }

        return TS_FAILED;
    }

    /* send packet */
    if (gnrc_netapi_dispatch_send(GNRC_NETTYPE_UDP, GNRC_NETREG_DEMUX_CTX_ALL,
                                  ip) == 0) {
        /* if send failed inform the user */
        DEBUG("tftp: error unable to locate UDP thread\n");
        gnrc_pktbuf_release(ip);

        if (ctxt->stop_cb) {
            ctxt->stop_cb(TFTP_INTERN_ERROR, "no dispatch send");
        }

        return TS_FAILED;
    }

    /* only set timeout if enabled for this block */
    if (ctxt->block_timeout) {
        ctxt->timer_msg.type = TFTP_TIMEOUT_MSG;
        xtimer_set_msg(&(ctxt->timer), ctxt->block_timeout, &(ctxt->timer_msg), thread_getpid());
        DEBUG("tftp: set timeout %" PRIu32 " ms\n", ctxt->block_timeout / MS_IN_USEC);
    }

    return TS_BUSY;
}