Пример #1
0
static int _recv(dev_eth_t *dev_eth, char *buf, int len) {
    dev_eth_tap_t *dev = (dev_eth_tap_t*)dev_eth;

    int nread = real_read(dev->tap_fd, buf, len);
    DEBUG("ng_tapnet: read %d bytes\n", nread);

    if (nread > 0) {
        ethernet_hdr_t *hdr = (ethernet_hdr_t *)buf;
        if (!(dev->promiscous) && !_is_addr_multicast(hdr->dst) &&
            !_is_addr_broadcast(hdr->dst) &&
            (memcmp(hdr->dst, dev->addr, ETHERNET_ADDR_LEN) != 0)) {
            DEBUG("ng_eth_dev: received for %02x:%02x:%02x:%02x:%02x:%02x\n"
                  "That's not me => Dropped\n",
                  hdr->dst[0], hdr->dst[1], hdr->dst[2],
                  hdr->dst[3], hdr->dst[4], hdr->dst[5]);
#ifdef __MACH__
            kill(_sigio_child_pid, SIGCONT);
#endif
            return 0;
        }
        /* work around lost signals */
        fd_set rfds;
        struct timeval t;
        memset(&t, 0, sizeof(t));
        FD_ZERO(&rfds);
        FD_SET(dev->tap_fd, &rfds);

        _native_in_syscall++; /* no switching here */

        if (real_select(dev->tap_fd + 1, &rfds, NULL, NULL, &t) == 1) {
            int sig = SIGIO;
            extern int _sig_pipefd[2];
            extern ssize_t (*real_write)(int fd, const void * buf, size_t count);
            real_write(_sig_pipefd[1], &sig, sizeof(int));
            _native_sigpend++;
            DEBUG("dev_eth_tap: sigpend++\n");
        }
        else {
#ifdef __MACH__
        kill(_sigio_child_pid, SIGCONT);
#endif
        }

        _native_in_syscall--;

        return nread;
    }
    else if (nread == -1) {
        if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
        }
        else {
            err(EXIT_FAILURE, "dev_eth_tap: read");
        }
    }
    else if (nread == 0) {
        DEBUG("_native_handle_tap_input: ignoring null-event");
    }
    else {
        errx(EXIT_FAILURE, "internal error _rx_event");
    }

    return -1;
}
Пример #2
0
void _native_handle_tap_input(void)
{
    int nread;
    union eth_frame frame;
    radio_packet_t p;

    DEBUG("_native_handle_tap_input\n");

    /* TODO: check whether this is an input or an output event
       TODO: refactor this into general io-signal multiplexer */

    nread = real_read(_native_tap_fd, &frame, sizeof(union eth_frame));
    DEBUG("_native_handle_tap_input - read %d bytes\n", nread);
    if (nread > 0) {
        if (ntohs(frame.field.header.ether_type) == NATIVE_ETH_PROTO) {
            nread = nread - ETHER_HDR_LEN;
            if ((nread - 1) <= 0) {
                DEBUG("_native_handle_tap_input: no payload\n");
            }
            else {
                unsigned long t = hwtimer_now();
                p.processing = 0;
                p.src = ntohs(frame.field.payload.nn_header.src);
                p.dst = ntohs(frame.field.payload.nn_header.dst);
                p.rssi = 0;
                p.lqi = 0;
                p.toa.seconds = HWTIMER_TICKS_TO_US(t)/1000000;
                p.toa.microseconds = HWTIMER_TICKS_TO_US(t)%1000000;
                /* XXX: check overflow */
                p.length = ntohs(frame.field.payload.nn_header.length);
                p.data = frame.field.payload.data;
                if (p.length > (nread - sizeof(struct nativenet_header))) {
                    warnx("_native_handle_tap_input: packet with malicious length field received, discarding");
                }
                else {
                    DEBUG("_native_handle_tap_input: received packet of length %" PRIu16 " for %" PRIu16 " from %" PRIu16 "\n", p.length, p.dst, p.src);
                    _nativenet_handle_packet(&p);
                }
            }
        }
        else {
            DEBUG("ignoring non-native frame\n");
        }

        /* work around lost signals */
        fd_set rfds;
        struct timeval t;
        memset(&t, 0, sizeof(t));
        FD_ZERO(&rfds);
        FD_SET(_native_tap_fd, &rfds);

        _native_in_syscall++; // no switching here
        if (select(_native_tap_fd +1, &rfds, NULL, NULL, &t) == 1) {
            int sig = SIGIO;
            extern int _sig_pipefd[2];
            extern ssize_t (*real_write)(int fd, const void *buf, size_t count);
            real_write(_sig_pipefd[1], &sig, sizeof(int));
            _native_sigpend++;
            DEBUG("_native_handle_tap_input: sigpend++\n");
        }
        else {
            DEBUG("_native_handle_tap_input: no more pending tap data\n");
#ifdef __MACH__
            kill(sigio_child_pid, SIGCONT);
#endif
        }
        _native_in_syscall--;
    }
    else if (nread == -1) {
        if ((errno == EAGAIN ) || (errno == EWOULDBLOCK)) {
            //warn("read");
        }
        else {
            err(EXIT_FAILURE, "_native_handle_tap_input: read");
        }
    }
    else {
        errx(EXIT_FAILURE, "internal error _native_handle_tap_input");
    }
}