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; }
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"); } }