+ output_len= op - output_buf;
+ scanned= ip - input_buf;
+
+ input_waiting -= eaten;
+ memmove(input_buf, input_buf+eaten, input_waiting);
+ scanned -= eaten;
+}
+
+static void tx_packet(uint8_t *output_buf, const uint8_t *ip, int inlen) {
+ /* output_buf is passed as a parameter since it's in copydata's stack frame */
+ assert(!output_waiting);
+ uint8_t *op= output_buf;
+
+ *op++= SLIP_END;
+ while (inlen-- >0) {
+ uint8_t c= *ip++;
+ if (c==SLIP_END) { *op++= SLIP_ESC; *op++= SLIP_ESC_END; }
+ else if (c==SLIP_ESC) { *op++= SLIP_ESC; *op++= SLIP_ESC_ESC; }
+ else *op++= c;
+ }
+ *op++= SLIP_END;
+ assert(op <= output_buf + mtu*2+2);
+
+ output_waiting= op - output_buf;
+}
+
+static void copydata(void) __attribute__((noreturn));
+static void copydata(void) {
+ uint8_t output_buf[mtu*2+2];
+ uint8_t input_buf[mtu*2+2];
+ uint8_t rx_packet_buf[mtu];
+
+ int r, i;
+
+ struct pollfd polls[3];
+ memset(polls, 0, sizeof(polls));
+
+ polls[0].fd= 0; polls[0].events= POLLIN;
+ polls[1].fd= 1;
+ polls[2].fd= tunfd;
+
+ /* We don't do flow control on input packets; instead, we just throw
+ * away ones which the kernel doesn't accept. So we always poll for
+ * those.
+ *
+ * Output packets we buffer, so we poll only as appropriate for those.
+ */
+
+ /* Start by transmitting one END byte to say we're ready. */
+ output_buf[0]= SLIP_END;
+ output_waiting= 1;
+
+ for (;;) {
+ if (output_waiting) {
+ r= write(1, output_buf, output_waiting);
+ if (r<0) {
+ if (errno==EINTR) continue;
+ if (errno!=EAGAIN)
+ sysfatal("error writing SLIP output (packets being received)");
+ } else {
+ assert(r>0);
+ output_waiting -= r;
+ memmove(output_buf, output_buf+r, output_waiting);
+ }
+ }
+ if (output_waiting) {
+ polls[1].events |= POLLOUT;
+ polls[2].events &= ~POLLIN;
+ } else {
+ polls[1].events &= ~POLLOUT;
+ polls[2].events |= POLLIN;
+ }
+ r= poll(polls,3,-1);
+
+ if (r<0) {
+ if (errno==EINTR) continue;
+ sysfatal("poll() failed");
+ }
+ assert(r>0); /* we used an infinite timeout */
+
+ for (i=0; i<sizeof(polls)/sizeof(polls[0]); i++)
+ if (polls[i].revents & ~polls[i].events)
+ fatal("unexpected revents 0x%x for fd=%d",
+ polls[i].revents, polls[i].fd);
+
+ if (polls[0].events & POLLIN) {
+ int want= sizeof(input_buf) - input_waiting;
+ if (want<0) fatal("incoming packet necessarily exceeds MTU");
+ r= read(0, input_buf + input_waiting, want);
+ if (r>0) {
+ input_waiting += r;
+ assert(input_waiting <= sizeof(input_buf));
+ more_rx_data(input_buf, rx_packet_buf);
+ } else if (r==0) {
+ terminate(0);
+ } else {
+ if (!(errno==EINTR || errno==EAGAIN))
+ sysfatal("error reading input SLIP data (packets to transmit)");
+ }
+ }
+
+ /* We handle what would be (polls[1].events & POLLOUT) above,
+ * unconditionally. That eliminates the need to poll in the usual case */
+
+ if (polls[2].events & POLLIN) {
+ uint8_t packet_buf[mtu];
+ r= read(tunfd, packet_buf, mtu);
+ if (r>0) {
+ tx_packet(output_buf, packet_buf, r);
+ } else {
+ assert(r<0);
+ if (!(errno==EAGAIN || errno==EWOULDBLOCK))
+ sysfatal("error reading packet (being transmitted) from tun");
+ }
+ }
+ }