예제 #1
0
static inline void _addr_set_multicast(uint8_t *dst, gnrc_pktsnip_t *payload)
{
    switch (payload->type) {
#ifdef MODULE_IPV6
        case GNRC_NETTYPE_IPV6:
            dst[0] = 0x33;
            dst[1] = 0x33;
            memcpy(dst + 2, ((uint8_t *)payload->data) + _IPV6_DST_OFFSET, 4);
            /* TODO change to proper types when gnrc_ipv6_hdr_t got merged */
            break;
#endif
        default:
            _addr_set_broadcast(dst);
            break;
    }
}
예제 #2
0
static inline void _addr_set_multicast(uint8_t *dst, ng_pktsnip_t *payload)
{
    switch (payload->type) {
#ifdef MODULE_NG_IPV6
        case NG_NETTYPE_IPV6:
            dst[0] = 0x33;
            dst[1] = 0x33;
            if ((payload != NULL) && (payload->data != NULL)) {
                ipv6_hdr_t *hdr = payload->data;
                uint16_t *prefix = (uint16_t *)(&dst[2]);
                prefix[0] = hdr->dst.u16[6].u16;
                prefix[1] = hdr->dst.u16[7].u16;
            }
            break;
#endif
        default:
            _addr_set_broadcast(dst);
            break;
    }
}
예제 #3
0
static int _marshall_ethernet(ng_netdev_eth_t *dev, uint8_t *buffer, ng_pktsnip_t *pkt)
{
    int data_len = 0;
    ethernet_hdr_t *hdr = (ethernet_hdr_t *)buffer;
    ng_netif_hdr_t *netif_hdr;
    ng_pktsnip_t *payload;

    if (pkt == NULL) {
        DEBUG("ng_netdev_eth: pkt was NULL");
        return -EINVAL;
    }

    payload = pkt->next;

    if (pkt->type != NG_NETTYPE_NETIF) {
        DEBUG("ng_netdev_eth: First header was not generic netif header\n");
        return -EBADMSG;
    }

    if (payload) {
        hdr->type = byteorder_htons(ng_nettype_to_ethertype(payload->type));
    }
    else {
        hdr->type = byteorder_htons(ETHERTYPE_UNKNOWN);
    }

    netif_hdr = pkt->data;

    /* set ethernet header */
    if (netif_hdr->src_l2addr_len == ETHERNET_ADDR_LEN) {
        memcpy(hdr->dst, ng_netif_hdr_get_src_addr(netif_hdr),
               netif_hdr->src_l2addr_len);
    }
    else {
        dev_eth_t *ethdev = dev->ethdev;
        ethdev->driver->get_mac_addr(ethdev, hdr->src);
    }

    if (netif_hdr->flags & NG_NETIF_HDR_FLAGS_BROADCAST) {
        _addr_set_broadcast(hdr->dst);
    }
    else if (netif_hdr->flags & NG_NETIF_HDR_FLAGS_MULTICAST) {
        _addr_set_multicast(hdr->dst, payload);
    }
    else if (netif_hdr->dst_l2addr_len == ETHERNET_ADDR_LEN) {
        memcpy(hdr->dst, ng_netif_hdr_get_dst_addr(netif_hdr),
               ETHERNET_ADDR_LEN);
    }
    else {
        DEBUG("ng_netdev_eth: destination address had unexpected format\n");
        return -EBADMSG;
    }

    DEBUG("ng_netdev_eth: send to %02x:%02x:%02x:%02x:%02x:%02x\n",
          hdr->dst[0], hdr->dst[1], hdr->dst[2],
          hdr->dst[3], hdr->dst[4], hdr->dst[5]);

    data_len += sizeof(ethernet_hdr_t);

    while (payload != NULL) {
        if ((data_len + payload->size) > ETHERNET_MAX_LEN) {
            DEBUG("ng_netdev_eth: Packet too big for ethernet frame\n");
            return -ENOBUFS;
        }

        memcpy(send_buffer + data_len, payload->data, payload->size);

        data_len += payload->size;
        payload = payload->next;
    }

    /* Pad to minimum payload size.
     * Linux does this on its own, but it doesn't hurt to do it here.
     * As of now only tuntaposx needs this. */
    if (data_len < (ETHERNET_MIN_LEN)) {
        DEBUG("ng_netdev_eth: padding data! (%d -> ", data_len);
        memset(send_buffer + data_len, 0, ETHERNET_MIN_LEN - data_len);
        data_len = ETHERNET_MIN_LEN;
        DEBUG("%d)\n", data_len);
    }

    return data_len;
}
예제 #4
0
static int _send(gnrc_netdev2_t *gnrc_netdev2, gnrc_pktsnip_t *pkt)
{
    ethernet_hdr_t hdr;
    gnrc_netif_hdr_t *netif_hdr;
    gnrc_pktsnip_t *payload;

    netdev2_t *dev = gnrc_netdev2->dev;

    if (pkt == NULL) {
        DEBUG("gnrc_netdev2_eth: pkt was NULL");
        return -EINVAL;
    }

    payload = pkt->next;

    if (pkt->type != GNRC_NETTYPE_NETIF) {
        DEBUG("gnrc_netdev2_eth: First header was not generic netif header\n");
        return -EBADMSG;
    }

    if (payload) {
        hdr.type = byteorder_htons(gnrc_nettype_to_ethertype(payload->type));
    }
    else {
        hdr.type = byteorder_htons(ETHERTYPE_UNKNOWN);
    }

    netif_hdr = pkt->data;

    /* set ethernet header */
    if (netif_hdr->src_l2addr_len == ETHERNET_ADDR_LEN) {
        memcpy(hdr.dst, gnrc_netif_hdr_get_src_addr(netif_hdr),
               netif_hdr->src_l2addr_len);
    }
    else {
        dev->driver->get(dev, NETOPT_ADDRESS, hdr.src, ETHERNET_ADDR_LEN);
    }

    if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_BROADCAST) {
        _addr_set_broadcast(hdr.dst);
    }
    else if (netif_hdr->flags & GNRC_NETIF_HDR_FLAGS_MULTICAST) {
        _addr_set_multicast(hdr.dst, payload);
    }
    else if (netif_hdr->dst_l2addr_len == ETHERNET_ADDR_LEN) {
        memcpy(hdr.dst, gnrc_netif_hdr_get_dst_addr(netif_hdr),
               ETHERNET_ADDR_LEN);
    }
    else {
        DEBUG("gnrc_netdev2_eth: destination address had unexpected format\n");
        return -EBADMSG;
    }

    DEBUG("gnrc_netdev2_eth: send to %02x:%02x:%02x:%02x:%02x:%02x\n",
          hdr.dst[0], hdr.dst[1], hdr.dst[2],
          hdr.dst[3], hdr.dst[4], hdr.dst[5]);

    size_t n;
    pkt = gnrc_pktbuf_get_iovec(pkt, &n);
    struct iovec *vector = (struct iovec *)pkt->data;
    vector[0].iov_base = (char*)&hdr;
    vector[0].iov_len = sizeof(ethernet_hdr_t);
    dev->driver->send(dev, vector, n);

    gnrc_pktbuf_release(pkt);

    return 0;
}