void read_incoming_tun (struct context *c) { /* * Setup for read() call on TUN/TAP device. */ /*ASSERT (!c->c2.to_link.len);*/ perf_push (PERF_READ_IN_TUN); c->c2.buf = c->c2.buffers->read_tun_buf; #ifdef TUN_PASS_BUFFER read_tun_buffered (c->c1.tuntap, &c->c2.buf, MAX_RW_SIZE_TUN (&c->c2.frame)); #else ASSERT (buf_init (&c->c2.buf, FRAME_HEADROOM (&c->c2.frame))); ASSERT (buf_safe (&c->c2.buf, MAX_RW_SIZE_TUN (&c->c2.frame))); c->c2.buf.len = read_tun (c->c1.tuntap, BPTR (&c->c2.buf), MAX_RW_SIZE_TUN (&c->c2.frame)); #endif #ifdef PACKET_TRUNCATION_CHECK ipv4_packet_size_verify (BPTR (&c->c2.buf), BLEN (&c->c2.buf), TUNNEL_TYPE (c->c1.tuntap), "READ_TUN", &c->c2.n_trunc_tun_read); #endif /* Was TUN/TAP interface stopped? */ if (tuntap_stop (c->c2.buf.len)) { register_signal (c, SIGTERM, "tun-stop"); msg (M_INFO, "TUN/TAP interface has been stopped, exiting"); perf_pop (); return; } /* Was TUN/TAP I/O operation aborted? */ if (tuntap_abort(c->c2.buf.len)) { register_signal(c, SIGHUP, "tun-abort"); c->persist.restart_sleep_seconds = 10; msg(M_INFO, "TUN/TAP I/O operation aborted, restarting"); perf_pop(); return; } /* Check the status return from read() */ check_status (c->c2.buf.len, "read from TUN/TAP", NULL, c->c1.tuntap); perf_pop (); }
/* allocate a buffer for socket or tun layer */ void alloc_buf_sock_tun (struct buffer *buf, const struct frame *frame, const bool tuntap_buffer, const unsigned int align_mask) { /* allocate buffer for overlapped I/O */ *buf = alloc_buf (BUF_SIZE (frame)); ASSERT (buf_init (buf, FRAME_HEADROOM_ADJ (frame, align_mask))); buf->len = tuntap_buffer ? MAX_RW_SIZE_TUN (frame) : MAX_RW_SIZE_LINK (frame); ASSERT (buf_safe (buf, 0)); }
void process_outgoing_tun (struct context *c) { struct gc_arena gc = gc_new (); /* * Set up for write() call to TUN/TAP * device. */ if (c->c2.to_tun.len <= 0) return; perf_push (PERF_PROC_OUT_TUN); /* * The --mssfix option requires * us to examine the IPv4 header. */ process_ipv4_header (c, PIPV4_MSSFIX|PIPV4_EXTRACT_DHCP_ROUTER|PIPV4_CLIENT_NAT|PIPV4_OUTGOING, &c->c2.to_tun); if (c->c2.to_tun.len <= MAX_RW_SIZE_TUN (&c->c2.frame)) { /* * Write to TUN/TAP device. */ int size; #ifdef LOG_RW if (c->c2.log_rw) fprintf (stderr, "w"); #endif dmsg (D_TUN_RW, "TUN WRITE [%d]", BLEN (&c->c2.to_tun)); #ifdef PACKET_TRUNCATION_CHECK ipv4_packet_size_verify (BPTR (&c->c2.to_tun), BLEN (&c->c2.to_tun), TUNNEL_TYPE (c->c1.tuntap), "WRITE_TUN", &c->c2.n_trunc_tun_write); #endif #ifdef TUN_PASS_BUFFER size = write_tun_buffered (c->c1.tuntap, &c->c2.to_tun); #else size = write_tun (c->c1.tuntap, BPTR (&c->c2.to_tun), BLEN (&c->c2.to_tun)); #endif if (size > 0) c->c2.tun_write_bytes += size; check_status (size, "write to TUN/TAP", NULL, c->c1.tuntap); /* check written packet size */ if (size > 0) { /* Did we write a different size packet than we intended? */ if (size != BLEN (&c->c2.to_tun)) msg (D_LINK_ERRORS, "TUN/TAP packet was destructively fragmented on write to %s (tried=%d,actual=%d)", c->c1.tuntap->actual_name, BLEN (&c->c2.to_tun), size); /* indicate activity regarding --inactive parameter */ register_activity (c, size); } } else { /* * This should never happen, probably indicates some kind * of MTU mismatch. */ msg (D_LINK_ERRORS, "tun packet too large on write (tried=%d,max=%d)", c->c2.to_tun.len, MAX_RW_SIZE_TUN (&c->c2.frame)); } buf_reset (&c->c2.to_tun); perf_pop (); gc_free (&gc); }
void check_send_occ_msg_dowork (struct context *c) { bool doit = false; c->c2.buf = c->c2.buffers->aux_buf; ASSERT (buf_init (&c->c2.buf, FRAME_HEADROOM (&c->c2.frame))); ASSERT (buf_safe (&c->c2.buf, MAX_RW_SIZE_TUN (&c->c2.frame))); ASSERT (buf_write (&c->c2.buf, occ_magic, OCC_STRING_SIZE)); switch (c->c2.occ_op) { case OCC_REQUEST: if (!buf_write_u8 (&c->c2.buf, OCC_REQUEST)) break; dmsg (D_PACKET_CONTENT, "SENT OCC_REQUEST"); doit = true; break; case OCC_REPLY: if (!c->c2.options_string_local) break; if (!buf_write_u8 (&c->c2.buf, OCC_REPLY)) break; if (!buf_write (&c->c2.buf, c->c2.options_string_local, strlen (c->c2.options_string_local) + 1)) break; dmsg (D_PACKET_CONTENT, "SENT OCC_REPLY"); doit = true; break; case OCC_MTU_REQUEST: if (!buf_write_u8 (&c->c2.buf, OCC_MTU_REQUEST)) break; dmsg (D_PACKET_CONTENT, "SENT OCC_MTU_REQUEST"); doit = true; break; case OCC_MTU_REPLY: if (!buf_write_u8 (&c->c2.buf, OCC_MTU_REPLY)) break; if (!buf_write_u16 (&c->c2.buf, c->c2.max_recv_size_local)) break; if (!buf_write_u16 (&c->c2.buf, c->c2.max_send_size_local)) break; dmsg (D_PACKET_CONTENT, "SENT OCC_MTU_REPLY"); doit = true; break; case OCC_MTU_LOAD_REQUEST: if (!buf_write_u8 (&c->c2.buf, OCC_MTU_LOAD_REQUEST)) break; if (!buf_write_u16 (&c->c2.buf, c->c2.occ_mtu_load_size)) break; dmsg (D_PACKET_CONTENT, "SENT OCC_MTU_LOAD_REQUEST"); doit = true; break; case OCC_MTU_LOAD: { int need_to_add; if (!buf_write_u8 (&c->c2.buf, OCC_MTU_LOAD)) break; need_to_add = min_int (c->c2.occ_mtu_load_size, EXPANDED_SIZE (&c->c2.frame)) - OCC_STRING_SIZE - sizeof (uint8_t) - EXTRA_FRAME (&c->c2.frame); while (need_to_add > 0) { /* * Fill the load test packet with pseudo-random bytes. */ if (!buf_write_u8 (&c->c2.buf, get_random () & 0xFF)) break; --need_to_add; } dmsg (D_PACKET_CONTENT, "SENT OCC_MTU_LOAD min_int(%d-%d-%d-%d,%d) size=%d", c->c2.occ_mtu_load_size, OCC_STRING_SIZE, (int) sizeof (uint8_t), EXTRA_FRAME (&c->c2.frame), MAX_RW_SIZE_TUN (&c->c2.frame), BLEN (&c->c2.buf)); doit = true; } break; case OCC_EXIT: if (!buf_write_u8 (&c->c2.buf, OCC_EXIT)) break; dmsg (D_PACKET_CONTENT, "SENT OCC_EXIT"); doit = true; break; } if (doit) { /* * We will treat the packet like any other outgoing packet, * compress, encrypt, sign, etc. */ encrypt_sign (c, true); } c->c2.occ_op = -1; }
/* * Should we ping the remote? */ void check_ping_send_dowork (struct context *c) { c->c2.buf = c->c2.buffers->aux_buf; ASSERT (buf_init (&c->c2.buf, FRAME_HEADROOM (&c->c2.frame))); ASSERT (buf_safe (&c->c2.buf, MAX_RW_SIZE_TUN (&c->c2.frame))); ASSERT (buf_write (&c->c2.buf, ping_string, sizeof (ping_string))); /* * We will treat the ping like any other outgoing packet, * encrypt, sign, etc. */ encrypt_sign (c, true); dmsg (D_PING, "SENT PING"); }