static void _sigio_child(ng_tapnet_t *dev) { pid_t parent = _native_pid; if ((_sigio_child_pid = real_fork()) == -1) { err(EXIT_FAILURE, "sigio_child: fork"); } if (_sigio_child_pid > 0) { /* return in parent process */ return; } /* watch tap interface and signal parent process if data is * available */ fd_set rfds; while (1) { FD_ZERO(&rfds); FD_SET(dev->tap_fd, &rfds); if (real_select(dev->tap_fd + 1, &rfds, NULL, NULL, NULL) == 1) { kill(parent, SIGIO); } else { kill(parent, SIGKILL); err(EXIT_FAILURE, "osx_sigio_child: select"); } pause(); } }
static void _continue_reading(netdev2_tap_t *dev) { /* 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("netdev2_tap: sigpend++\n"); } else { DEBUG("netdev2_tap: native_async_read_continue\n"); native_async_read_continue(dev->tap_fd); } _native_in_syscall--; }
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { int retval; print_trace ("%*sselect(%d, %p, %p, %p, %p)=...\n", indent, "", n, readfds, writefds, exceptfds, timeout); indent+=2; /* call the real select function */ retval = real_select (n, readfds, writefds, exceptfds, timeout); indent-=2; print_trace ("%*sselect(%d, %p, %p, %p, %p)=%d\n", indent, "", n, readfds, writefds, exceptfds, timeout, retval); return retval; }
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; }