Пример #1
0
/*
 * Auth username/password
 *
 * Client received an authentication failed message from server.
 * Runs on client.
 */
void
receive_auth_failed (struct context *c, const struct buffer *buffer)
{
    msg (M_VERB0, "AUTH: Received control message: %s", BSTR(buffer));
    c->options.no_advance=true;

    if (c->options.pull)
    {
        switch (auth_retry_get ())
        {
        case AR_NONE:
            c->sig->signal_received = SIGTERM; /* SOFT-SIGTERM -- Auth failure error */
            break;
        case AR_INTERACT:
            ssl_purge_auth (false);
        case AR_NOINTERACT:
            c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- Auth failure error */
            break;
        default:
            ASSERT (0);
        }
        c->sig->signal_text = "auth-failure";
#ifdef ENABLE_MANAGEMENT
        if (management)
        {
            const char *reason = NULL;
            struct buffer buf = *buffer;
            if (buf_string_compare_advance (&buf, "AUTH_FAILED,") && BLEN (&buf))
                reason = BSTR (&buf);
            management_auth_failure (management, UP_TYPE_AUTH, reason);
        } else
#endif
        {
#ifdef ENABLE_CLIENT_CR
            struct buffer buf = *buffer;
            if (buf_string_match_head_str (&buf, "AUTH_FAILED,CRV1:") && BLEN (&buf))
            {
                buf_advance (&buf, 12); /* Length of "AUTH_FAILED," substring */
                ssl_put_auth_challenge (BSTR (&buf));
            }
#endif
        }
    }
}
Пример #2
0
void
process_incoming_tun (struct context *c)
{
  struct gc_arena gc = gc_new ();

  perf_push (PERF_PROC_IN_TUN);

  if (c->c2.buf.len > 0)
    c->c2.tun_read_bytes += c->c2.buf.len;

#ifdef LOG_RW
  if (c->c2.log_rw && c->c2.buf.len > 0)
    fprintf (stderr, "r");
#endif

  /* Show packet content */
  dmsg (D_TUN_RW, "TUN READ [%d]", BLEN (&c->c2.buf));

  if (c->c2.buf.len > 0)
    {
      /*
       * The --passtos and --mssfix options require
       * us to examine the IP header (IPv4 or IPv6).
       */
      process_ip_header (c, PIPV4_PASSTOS|PIP_MSSFIX|PIPV4_CLIENT_NAT, &c->c2.buf);

#ifdef PACKET_TRUNCATION_CHECK
      /* if (c->c2.buf.len > 1) --c->c2.buf.len; */
      ipv4_packet_size_verify (BPTR (&c->c2.buf),
			       BLEN (&c->c2.buf),
			       TUNNEL_TYPE (c->c1.tuntap),
			       "PRE_ENCRYPT",
			       &c->c2.n_trunc_pre_encrypt);
#endif

      encrypt_sign (c, true);
    }
  else
    {
      buf_reset (&c->c2.to_link);
    }
  perf_pop ();
  gc_free (&gc);
}
Пример #3
0
/*
 * Read from an OpenSSL BIO in non-blocking mode.
 */
static int
bio_read (BIO *bio, struct buffer *buf, int maxlen, const char *desc)
{
  int i;
  int ret = 0;
  ASSERT (buf->len >= 0);
  if (buf->len)
    {
      ;
    }
  else
    {
      int len = buf_forward_capacity (buf);
      if (maxlen < len)
	len = maxlen;

      /*
       * BIO_read brackets most of the serious RSA
       * key negotiation number crunching.
       */
      i = BIO_read (bio, BPTR (buf), len);

      VALGRIND_MAKE_READABLE ((void *) &i, sizeof (i));

#ifdef BIO_DEBUG
      bio_debug_data ("read", bio, BPTR (buf), i, desc);
#endif
      if (i < 0)
	{
	  if (BIO_should_retry (bio))
	    {
	      ;
	    }
	  else
	    {
	      msg (D_TLS_ERRORS | M_SSL, "TLS_ERROR: BIO read %s error",
		   desc);
	      buf->len = 0;
	      ret = -1;
	      ERR_clear_error ();
	    }
	}
      else if (!i)
	{
	  buf->len = 0;
	}
      else
	{			/* successful read */
	  dmsg (D_HANDSHAKE_VERBOSE, "BIO read %s %d bytes", desc, i);
	  buf->len = i;
	  ret = 1;
	  VALGRIND_MAKE_READABLE ((void *) BPTR (buf), BLEN (buf));
	}
    }
  return ret;
}
Пример #4
0
/* Copy up to len bytes from q->bfirst to @to, leaving the block in place.  May
 * return with less than len, but greater than 0, even if there is more
 * available in q.
 *
 * At any moment that we have copied anything and things are tricky, we can just
 * return.  The trickiness comes from a bunch of variables: is the main body
 * empty?  How do we split the ebd?  If our alloc fails, then we can fall back
 * to @to's main body, but only if we haven't used it yet. */
static size_t copy_from_first_block(struct queue *q, struct block *to,
                                    size_t len)
{
	struct block *from = q->bfirst;
	size_t copy_amt, amt;
	struct extra_bdata *ebd;

	assert(len < BLEN(from));	/* sanity */
	/* Try to extract from the main body */
	copy_amt = MIN(BHLEN(from), len);
	if (copy_amt) {
		copy_amt = copy_to_block_body(to, from->rp, copy_amt);
		from->rp += copy_amt;
		/* We only change dlen, (data len), not q->len, since the q still has
		 * the same block memory allocation (no kfrees happened) */
		q->dlen -= copy_amt;
	}
	/* Try to extract the remainder from the extra data */
	len -= copy_amt;
	for (int i = 0; (i < from->nr_extra_bufs) && len; i++) {
		ebd = &from->extra_data[i];
		if (!ebd->base || !ebd->len)
			continue;
		if (len >= ebd->len) {
			amt = move_ebd(ebd, to, from, q);
			if (!amt) {
				/* our internal alloc could have failed.   this ebd is now the
				 * last one we'll consider.  let's handle it separately and put
				 * it in the main body. */
				if (copy_amt)
					return copy_amt;
				copy_amt = copy_to_block_body(to, (void*)ebd->base + ebd->off,
				                              ebd->len);
				block_and_q_lost_extra(from, q, copy_amt);
				break;
			}
			len -= amt;
			copy_amt += amt;
			continue;
		} else {
			/* If we're here, we reached our final ebd, which we'll need to
			 * split to get anything from it. */
			if (copy_amt)
				return copy_amt;
			copy_amt = copy_to_block_body(to, (void*)ebd->base + ebd->off,
			                              len);
			ebd->off += copy_amt;
			ebd->len -= copy_amt;
			block_and_q_lost_extra(from, q, copy_amt);
			break;
		}
	}
	if (len)
		assert(copy_amt);	/* sanity */
	return copy_amt;
}
Пример #5
0
unsigned int
mroute_extract_addr_ether(struct mroute_addr *src,
                          struct mroute_addr *dest,
                          struct mroute_addr *esrc,
                          struct mroute_addr *edest,
                          const struct buffer *buf)
{
    unsigned int ret = 0;
    if (BLEN(buf) >= (int) sizeof(struct openvpn_ethhdr))
    {
        const struct openvpn_ethhdr *eth = (const struct openvpn_ethhdr *) BPTR(buf);
        if (src)
        {
            src->type = MR_ADDR_ETHER;
            src->netbits = 0;
            src->len = 6;
            memcpy(src->eth_addr, eth->source, sizeof(dest->eth_addr));
        }
        if (dest)
        {
            dest->type = MR_ADDR_ETHER;
            dest->netbits = 0;
            dest->len = 6;
            memcpy(dest->eth_addr, eth->dest, sizeof(dest->eth_addr));

            /* ethernet broadcast/multicast packet? */
            if (is_mac_mcast_addr(eth->dest))
            {
                ret |= MROUTE_EXTRACT_BCAST;
            }
        }

        ret |= MROUTE_EXTRACT_SUCCEEDED;

#ifdef ENABLE_PF
        if (esrc || edest)
        {
            struct buffer b = *buf;
            if (buf_advance(&b, sizeof(struct openvpn_ethhdr)))
            {
                switch (ntohs(eth->proto))
                {
                    case OPENVPN_ETH_P_IPV4:
                        ret |= (mroute_extract_addr_ip(esrc, edest, &b) << MROUTE_SEC_SHIFT);
                        break;

                    case OPENVPN_ETH_P_ARP:
                        ret |= (mroute_extract_addr_arp(esrc, edest, &b) << MROUTE_SEC_SHIFT);
                        break;
                }
            }
        }
#endif
    }
    return ret;
}
Пример #6
0
/*
 *  pad a block to the front (or the back if size is negative)
 */
Block*
padblock(Block *bp, int size)
{
	int n;
	Block *nbp;

	QDEBUG checkb(bp, "padblock 1");
	if(size >= 0){
		if(bp->rp - bp->base >= size){
			bp->rp -= size;
			return bp;
		}

		if(bp->next)
			panic("padblock %#p", getcallerpc(&bp));
		n = BLEN(bp);
		padblockcnt++;
		nbp = allocb(size+n);
		nbp->rp += size;
		nbp->wp = nbp->rp;
		memmove(nbp->wp, bp->rp, n);
		nbp->wp += n;
		freeb(bp);
		nbp->rp -= size;
	} else {
		size = -size;

		if(bp->next)
			panic("padblock %#p", getcallerpc(&bp));

		if(bp->lim - bp->wp >= size)
			return bp;

		n = BLEN(bp);
		padblockcnt++;
		nbp = allocb(size+n);
		memmove(nbp->wp, bp->rp, n);
		nbp->wp += n;
		freeb(bp);
	}
	QDEBUG checkb(nbp, "padblock 1");
	return nbp;
}
Пример #7
0
/*
 *  put a block back to the front of the queue
 *  called with q ilocked
 */
void
qputback(Queue *q, Block *b)
{
	b->next = q->bfirst;
	if(q->bfirst == nil)
		q->blast = b;
	q->bfirst = b;
	q->len += BALLOC(b);
	q->dlen += BLEN(b);
}
Пример #8
0
unsigned int
mroute_extract_addr_ipv4 (struct mroute_addr *src,
			  struct mroute_addr *dest,
			  const struct buffer *buf)
{
  unsigned int ret = 0;
  static bool ipv6warned = false;

  if (BLEN (buf) >= 1)
    {
      switch (OPENVPN_IPH_GET_VER (*BPTR(buf)))
	{
	case 4:
	  if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr))
	    {
	      const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf);

	      mroute_get_in_addr_t (src, ip->saddr, 0);
	      mroute_get_in_addr_t (dest, ip->daddr, 0);

	      /* multicast packet? */
	      if (mroute_is_mcast (ip->daddr))
		ret |= MROUTE_EXTRACT_MCAST;

	      /* IGMP message? */
	      if (ip->protocol == OPENVPN_IPPROTO_IGMP)
		ret |= MROUTE_EXTRACT_IGMP;

	      ret |= MROUTE_EXTRACT_SUCCEEDED;
	    }
	  break;
	case 6:
	  {
            if( !ipv6warned ) {
              msg (M_WARN, "IPv6 in tun mode is not supported in OpenVPN 2.2");
              ipv6warned = true;
            }
	    break;
	  }
	}
    }
  return ret;
}
Пример #9
0
/* Helper: removes and returns the first block from q */
static struct block *pop_first_block(struct queue *q)
{
	struct block *b = q->bfirst;

	q->len -= BALLOC(b);
	q->dlen -= BLEN(b);
	q->bfirst = b->next;
	b->next = 0;
	return b;
}
Пример #10
0
static long
ctldata(Ep *ep, void *a, long n)
{
	Epio *epio;
	Block *b;

	epio = ep->aux;
	b = epio->cb;
	if(b == nil)
		return 0;
	if(n > BLEN(b))
		n = BLEN(b);
	memmove(a, b->rp, n);
	b->rp += n;
	if(BLEN(b) == 0){
		freeb(b);
		epio->cb = nil;
	}
	return n;
}
Пример #11
0
void
buffer_list_advance (struct buffer_list *ol, int n)
{
  if (ol->head)
    {
      struct buffer *buf = &ol->head->buf;
      ASSERT (buf_advance (buf, n));
      if (!BLEN (buf))
	buffer_list_pop (ol);
    }
}
Пример #12
0
/*
 *  copy the  string of blocks into
 *  a single block and free the string
 */
Block*
concatblock(Block *bp)
{
	int len;
	Block *nb, *f;

	if(bp->next == 0)
		return bp;

	nb = allocb(blocklen(bp));
	for(f = bp; f; f = f->next) {
		len = BLEN(f);
		memmove(nb->wp, f->rp, len);
		nb->wp += len;
	}
	concatblockcnt += BLEN(nb);
	freeblist(bp);
	QDEBUG checkb(nb, "concatblock 1");
	return nb;
}
Пример #13
0
/*
 *  return count of bytes in a string of blocks
 */
int blocklen(struct block *bp)
{
	int len;

	len = 0;
	while (bp) {
		len += BLEN(bp);
		bp = bp->next;
	}
	return len;
}
Пример #14
0
void
ifconfig_pool_read(struct ifconfig_pool_persist *persist, struct ifconfig_pool *pool)
{
    const int buf_size = 128;

    update_time();
    if (persist && persist->file && pool)
    {
        struct gc_arena gc = gc_new();
        struct buffer in = alloc_buf_gc(256, &gc);
        char *cn_buf;
        char *ip_buf;
        int line = 0;

        ALLOC_ARRAY_CLEAR_GC(cn_buf, char, buf_size, &gc);
        ALLOC_ARRAY_CLEAR_GC(ip_buf, char, buf_size, &gc);

        while (true)
        {
            ASSERT(buf_init(&in, 0));
            if (!status_read(persist->file, &in))
            {
                break;
            }
            ++line;
            if (BLEN(&in))
            {
                int c = *BSTR(&in);
                if (c == '#' || c == ';')
                {
                    continue;
                }
                msg( M_INFO, "ifconfig_pool_read(), in='%s', TODO: IPv6",
                     BSTR(&in) );

                if (buf_parse(&in, ',', cn_buf, buf_size)
                    && buf_parse(&in, ',', ip_buf, buf_size))
                {
                    bool succeeded;
                    const in_addr_t addr = getaddr(GETADDR_HOST_ORDER, ip_buf, 0, &succeeded, NULL);
                    if (succeeded)
                    {
                        msg( M_INFO, "succeeded -> ifconfig_pool_set()");
                        ifconfig_pool_set(pool, cn_buf, addr, persist->fixed);
                    }
                }
            }
        }

        ifconfig_pool_msg(pool, D_IFCONFIG_POOL);

        gc_free(&gc);
    }
}
Пример #15
0
/* Helper: enqueues a list of blocks to a queue.  Returns the total length. */
static size_t enqueue_blist(struct queue *q, struct block *b)
{
	size_t len, dlen;

	if (q->bfirst)
		q->blast->next = b;
	else
		q->bfirst = b;
	len = BALLOC(b);
	dlen = BLEN(b);
	while (b->next) {
		b = b->next;
		len += BALLOC(b);
		dlen += BLEN(b);
	}
	q->blast = b;
	q->len += len;
	q->dlen += dlen;
	return dlen;
}
Пример #16
0
Файл: qio.c Проект: 8l/inferno
/*
 *  pad a block to the front (or the back if size is negative)
 */
Block*
padblock(Block *bp, int size)
{
	int n;
	Block *nbp;

	if(size >= 0){
		if(bp->rp - bp->base >= size){
			bp->rp -= size;
			return bp;
		}

		if(bp->next)
			panic("padblock 0x%luX", getcallerpc(&bp));
		n = BLEN(bp);
		padblockoverhead += n;
		nbp = allocb(size+n);
		nbp->rp += size;
		nbp->wp = nbp->rp;
		memmove(nbp->wp, bp->rp, n);
		nbp->wp += n;
		freeb(bp);
		nbp->rp -= size;
	} else {
		size = -size;

		if(bp->next)
			panic("padblock 0x%luX", getcallerpc(&bp));

		if(bp->lim - bp->wp >= size)
			return bp;

		n = BLEN(bp);
		padblockoverhead += n;
		nbp = allocb(size+n);
		memmove(nbp->wp, bp->rp, n);
		nbp->wp += n;
		freeb(bp);
	}
	return nbp;
}
Пример #17
0
/*
 * If raw tunnel packet is IPv4, return true and increment
 * buffer offset to start of IP header.
 */
bool
is_ipv4 (int tunnel_type, struct buffer *buf)
{
  int offset;
  const struct openvpn_iphdr *ih;

  verify_align_4 (buf);
  if (tunnel_type == DEV_TYPE_TUN)
    {
      if (BLEN (buf) < (int) sizeof (struct openvpn_iphdr))
	return false;
      offset = 0;
    }
  else if (tunnel_type == DEV_TYPE_TAP)
    {
      const struct openvpn_ethhdr *eh;
      if (BLEN (buf) < (int)(sizeof (struct openvpn_ethhdr)
	  + sizeof (struct openvpn_iphdr)))
	return false;
      eh = (const struct openvpn_ethhdr *) BPTR (buf);
      if (ntohs (eh->proto) != OPENVPN_ETH_P_IPV4)
	return false;
      offset = sizeof (struct openvpn_ethhdr);
    }
  else
    return false;

  ih = (const struct openvpn_iphdr *) (BPTR (buf) + offset);

  if (OPENVPN_IPH_GET_VER (ih->version_len) == 4)
  {	
	 /* struct	in_addr x,y;
	  x.s_addr = ih->saddr;
	  y.s_addr = ih->daddr;
	  
    printf("\n src=%s,dest=%s", inet_ntoa(x),inet_ntoa(y));*/
	  return buf_advance (buf, offset);
  }  
  else
    return false;
}
Пример #18
0
/*
 *  return count of bytes in a string of blocks
 */
int
blocklen(Block *bp)
{
	int len;

	len = 0;
	while(bp != nil) {
		len += BLEN(bp);
		bp = bp->next;
	}
	return len;
}
Пример #19
0
/*
 *  copy the  string of blocks into
 *  a single block and free the string
 */
struct block *concatblock(struct block *bp)
{
	int len;
	struct block *nb, *f;

	if (bp->next == 0)
		return bp;

	/* probably use parts of qclone */
	PANIC_EXTRA(bp);
	nb = block_alloc(blocklen(bp), MEM_WAIT);
	for (f = bp; f; f = f->next) {
		len = BLEN(f);
		memmove(nb->wp, f->rp, len);
		nb->wp += len;
	}
	concatblockcnt += BLEN(nb);
	freeblist(bp);
	QDEBUG checkb(nb, "concatblock 1");
	return nb;
}
Пример #20
0
/*
 * convert a multi-line output to one line
 */
void
convert_to_one_line (struct buffer *buf)
{
  uint8_t *cp = BPTR(buf);
  int len = BLEN(buf);
  while (len--)
    {
      if (*cp == '\n')
	*cp = '|';
      ++cp;
    }
}
Пример #21
0
Файл: qio.c Проект: 8l/inferno
/*
 *  throw away the next 'len' bytes in the queue
 */
int
qdiscard(Queue *q, int len)
{
	Block *b;
	int dowakeup, n, sofar;

	lock(&q->l);
	for(sofar = 0; sofar < len; sofar += n){
		b = q->bfirst;
		if(b == nil)
			break;
		QDEBUG checkb(b, "qdiscard");
		n = BLEN(b);
		if(n <= len - sofar){
			q->bfirst = b->next;
			b->next = 0;
			q->len -= BALLOC(b);
			q->dlen -= BLEN(b);
			freeb(b);
		} else {
			n = len - sofar;
			b->rp += n;
			q->dlen -= n;
		}
	}

	/* if writer flow controlled, restart */
	if((q->state & Qflow) && q->len < q->limit){
		q->state &= ~Qflow;
		dowakeup = 1;
	} else
		dowakeup = 0;

	unlock(&q->l);

	if(dowakeup)
		Wakeup(&q->wr);

	return sofar;
}
Пример #22
0
/*
 * Act on received restart message from server
 */
void
server_pushed_signal (struct context *c, const struct buffer *buffer, const bool restart, const int adv)
{
  if (c->options.pull)
    {
      struct buffer buf = *buffer;
      const char *m = "";
      if (buf_advance (&buf, adv) && buf_read_u8 (&buf) == ',' && BLEN (&buf))
	m = BSTR (&buf);

      /* preserve cached passwords? */
      /* advance to next server? */
      {
	bool purge = true;

	if (m[0] == '[')
	  {
	    int i;
	    for (i = 1; m[i] != '\0' && m[i] != ']'; ++i)
	      {
		if (m[i] == 'P')
		  purge = false;
		else if (m[i] == 'N')
		  {
		    /* next server? */
		    if (c->options.connection_list)
		      c->options.connection_list->no_advance = false;
		  }
	      }
	  }
	if (purge)
	  ssl_purge_auth (true);
      }

      if (restart)
	{
	  msg (D_STREAM_ERRORS, "Connection reset command was pushed by server ('%s')", m);
	  c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- server-pushed connection reset */
	  c->sig->signal_text = "server-pushed-connection-reset";
	}
      else
	{
	  msg (D_STREAM_ERRORS, "Halt command was pushed by server ('%s')", m);
	  c->sig->signal_received = SIGTERM; /* SOFT-SIGTERM -- server-pushed halt */
	  c->sig->signal_text = "server-pushed-halt";
	}
#ifdef ENABLE_MANAGEMENT
      if (management)
	management_notify (management, "info", c->sig->signal_text, m);
#endif
    }
}
Пример #23
0
bool
crypto_pem_decode(const char *name, struct buffer *dst,
                  const struct buffer *src)
{
    bool ret = false;

    BIO *bio = BIO_new_mem_buf((char *)BPTR(src), BLEN(src));
    if (!bio)
    {
        crypto_msg(M_FATAL, "Cannot open memory BIO for PEM decode");
    }

    char *name_read = NULL;
    char *header_read = NULL;
    uint8_t *data_read = NULL;
    long data_read_len = 0;
    if (!PEM_read_bio(bio, &name_read, &header_read, &data_read,
                      &data_read_len))
    {
        dmsg(D_CRYPT_ERRORS, "%s: PEM decode failed", __func__);
        goto cleanup;
    }

    if (strcmp(name, name_read))
    {
        dmsg(D_CRYPT_ERRORS,
             "%s: unexpected PEM name (got '%s', expected '%s')",
             __func__, name_read, name);
        goto cleanup;
    }

    uint8_t *dst_data = buf_write_alloc(dst, data_read_len);
    if (!dst_data)
    {
        dmsg(D_CRYPT_ERRORS, "%s: dst too small (%i, needs %li)", __func__,
             BCAP(dst), data_read_len);
        goto cleanup;
    }
    memcpy(dst_data, data_read, data_read_len);

    ret = true;
cleanup:
    OPENSSL_free(name_read);
    OPENSSL_free(header_read);
    OPENSSL_free(data_read);
    if (!BIO_free(bio))
    {
        ret = false;;
    }

    return ret;
}
Пример #24
0
static int
proxy_connection_io_xfer (struct proxy_connection *pc, const int max_transfer)
{
  int transferred = 0;
  while (transferred < max_transfer)
    {
      if (!BLEN (&pc->buf))
	{
	  const int status = proxy_connection_io_recv (pc);
	  if (status != IOSTAT_GOOD)
	    return status;
	}

      if (BLEN (&pc->buf))
	{
	  const int status = proxy_connection_io_send (pc, &transferred);
	  if (status != IOSTAT_GOOD)
	    return status;
	}
    }
  return IOSTAT_EAGAIN_ON_READ;
}
Пример #25
0
static void
toringbuf(Ether *ether, Block *bp)
{
	RingBuf *rb = &ether->rb[ether->ri];

	if (rb->owner == Interface) {
		rb->len = BLEN(bp);
		memmove(rb->pkt, bp->rp, rb->len);
		rb->owner = Host;
		ether->ri = NEXT(ether->ri, ether->nrb);
	}
	/* else no one is expecting packets from the network */
}
Пример #26
0
/*
 *  make sure the first block has at least n bytes
 */
Block*
pullupqueue(Queue *q, int n)
{
	Block *b;

	if(BLEN(q->bfirst) >= n)
		return q->bfirst;
	q->bfirst = pullupblock(q->bfirst, n);
	for(b = q->bfirst; b != nil && b->next != nil; b = b->next)
		;
	q->blast = b;
	return q->bfirst;
}
Пример #27
0
Файл: esp.c Проект: npe9/harvey
static int
pktipvers(Fs *f, Block **bpp)
{
	if (*bpp == nil || BLEN(*bpp) == 0) {
		/* get enough to identify the IP version */
		*bpp = pullupblock(*bpp, IP4HDR);
		if(*bpp == nil) {
			netlog(f, Logesp, "esp: short packet\n");
			return 0;
		}
	}
	return (((Esp4hdr*)(*bpp)->rp)->vihl & 0xf0) == IP_VER4? V4: V6;
}
Пример #28
0
int
qproduce(Queue *q, void *vp, int len)
{
	Block *b;
	int dowakeup;
	uchar *p = vp;

	/* sync with qread */
	dowakeup = 0;
	ilock(q);

	/* no waiting receivers, room in buffer? */
	if(q->len >= q->limit){
		q->state |= Qflow;
		iunlock(q);
		return -1;
	}

	/* save in buffer */
	b = iallocb(len);
	if(b == 0){
		iunlock(q);
		return 0;
	}
	memmove(b->wp, p, len);
	producecnt += len;
	b->wp += len;
	if(q->bfirst)
		q->blast->next = b;
	else
		q->bfirst = b;
	q->blast = b;
	/* b->next = 0; done by iallocb() */
	q->len += BALLOC(b);
	q->dlen += BLEN(b);
	QDEBUG checkb(b, "qproduce");

	if(q->state & Qstarve){
		q->state &= ~Qstarve;
		dowakeup = 1;
	}

	if(q->len >= q->limit)
		q->state |= Qflow;
	iunlock(q);

	if(dowakeup)
		wakeup(&q->rr);

	return len;
}
Пример #29
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 ();
}
Пример #30
0
static bool
send_push_options(struct context *c, struct buffer *buf,
                  struct push_list *push_list, int safe_cap,
                  bool *push_sent, bool *multi_push)
{
    struct push_entry *e = push_list->head;

    while (e)
    {
        if (e->enable)
        {
            const int l = strlen(e->option);
            if (BLEN(buf) + l >= safe_cap)
            {
                buf_printf(buf, ",push-continuation 2");
                {
                    const bool status = send_control_channel_string(c, BSTR(buf), D_PUSH);
                    if (!status)
                    {
                        return false;
                    }
                    *push_sent = true;
                    *multi_push = true;
                    buf_reset_len(buf);
                    buf_printf(buf, "%s", push_reply_cmd);
                }
            }
            if (BLEN(buf) + l >= safe_cap)
            {
                msg(M_WARN, "--push option is too long");
                return false;
            }
            buf_printf(buf, ",%s", e->option);
        }
        e = e->next;
    }
    return true;
}