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) { ng_ethernet_hdr_t *hdr = (ng_ethernet_hdr_t *)buf; if (!(dev->promiscous) && !_is_addr_multicast(hdr->dst) && !_is_addr_broadcast(hdr->dst) && (memcmp(hdr->dst, dev->addr, NG_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; }
static int _recv(netdev2_t *netdev2, void *buf, size_t len, void *info) { netdev2_tap_t *dev = (netdev2_tap_t*)netdev2; (void)info; if (!buf) { if (len > 0) { /* no memory available in pktbuf, discarding the frame */ DEBUG("netdev2_tap: discarding the frame\n"); /* repeating `real_read` for small size on tap device results in * freeze for some reason. Using a large buffer for now. */ /* uint8_t buf[4]; while (real_read(dev->tap_fd, buf, sizeof(buf)) > 0) { } */ static uint8_t buf[ETHERNET_FRAME_LEN]; real_read(dev->tap_fd, buf, sizeof(buf)); _continue_reading(dev); } /* no way of figuring out packet size without racey buffering, * so we return the maximum possible size */ return ETHERNET_FRAME_LEN; } int nread = real_read(dev->tap_fd, buf, len); DEBUG("netdev2_tap: 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("netdev2_tap: 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]); native_async_read_continue(dev->tap_fd); return 0; } _continue_reading(dev); #ifdef MODULE_NETSTATS_L2 netdev2->stats.rx_count++; netdev2->stats.rx_bytes += nread; #endif return nread; } else if (nread == -1) { if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { } else { err(EXIT_FAILURE, "netdev2_tap: read"); } } else if (nread == 0) { DEBUG("_native_handle_tap_input: ignoring null-event"); } else { errx(EXIT_FAILURE, "internal error _rx_event"); } return -1; }