Beispiel #1
0
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 ();
}
Beispiel #2
0
/* 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));
}
Beispiel #3
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);
}
Beispiel #4
0
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");
}