예제 #1
0
파일: mss.c 프로젝트: angelol/iOpenVPN
/*
 * Lower MSS on TCP SYN packets to fix MTU
 * problems which arise from protocol
 * encapsulation.
 */
void
mss_fixup (struct buffer *buf, int maxmss)
{
  const struct openvpn_iphdr *pip;
  int hlen;

  if (BLEN (buf) < (int) sizeof (struct openvpn_iphdr))
    return;
  
  verify_align_4 (buf);
  pip = (struct openvpn_iphdr *) BPTR (buf);

  hlen = OPENVPN_IPH_GET_LEN (pip->version_len);

  if (pip->protocol == OPENVPN_IPPROTO_TCP
      && ntohs (pip->tot_len) == BLEN (buf)
      && (ntohs (pip->frag_off) & OPENVPN_IP_OFFMASK) == 0
      && hlen <= BLEN (buf)
      && BLEN (buf) - hlen
         >= (int) sizeof (struct openvpn_tcphdr))
    {
      struct buffer newbuf = *buf;
      if (buf_advance (&newbuf, hlen))
	{
	  struct openvpn_tcphdr *tc = (struct openvpn_tcphdr *) BPTR (&newbuf);
	  if (tc->flags & OPENVPN_TCPH_SYN_MASK)
	    mss_fixup_dowork (&newbuf, (uint16_t) maxmss);
	}
    }
}
예제 #2
0
파일: proto.c 프로젝트: angelol/iOpenVPN
/*
 * 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)
    return buf_advance (buf, offset);
  else
    return false;
}
예제 #3
0
파일: proto.c 프로젝트: anlaneg/openvpn
/*
 * If raw tunnel packet is IPv<X>, return true and increment
 * buffer offset to start of IP header.
 */
static
bool
is_ipv_X( int tunnel_type, struct buffer *buf, int ip_ver )
{
    int offset;
    const struct openvpn_iphdr *ih;

    verify_align_4(buf);
    if (tunnel_type == DEV_TYPE_TUN)
    {
    	//tun类型,不包含以太头
        if (BLEN(buf) < (int) sizeof(struct openvpn_iphdr))
        {
            return false;
        }
        offset = 0;
    }
    else if (tunnel_type == DEV_TYPE_TAP)
    {
    	//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) != (ip_ver == 6 ? OPENVPN_ETH_P_IPV6 : OPENVPN_ETH_P_IPV4))
        {
        	//非指定协议,返回false
            return false;
        }
        offset = sizeof(struct openvpn_ethhdr);
    }
    else
    {
        return false;
    }

    //指向ip头部
    ih = (const struct openvpn_iphdr *) (BPTR(buf) + offset);

    /* IP version is stored in the same bits for IPv4 or IPv6 header */
    if (OPENVPN_IPH_GET_VER(ih->version_len) == ip_ver)
    {
    	//为对应ip协议,使buf指向对应的ip头部
        return buf_advance(buf, offset);
    }
    else
    {
    	//非对应的ip协议,返回false
        return false;
    }
}
예제 #4
0
파일: proto.c 프로젝트: neuhalje/openvpn
void
ipv4_packet_size_verify(const uint8_t *data,
                        const int size,
                        const int tunnel_type,
                        const char *prefix,
                        counter_type *errors)
{
    if (size > 0)
    {
        struct buffer buf;

        buf_set_read(&buf, data, size);

        if (is_ipv4(tunnel_type, &buf))
        {
            const struct openvpn_iphdr *pip;
            int hlen;
            int totlen;
            const char *msgstr = "PACKET SIZE INFO";
            unsigned int msglevel = D_PACKET_TRUNC_DEBUG;

            if (BLEN(&buf) < (int) sizeof(struct openvpn_iphdr))
            {
                return;
            }

            verify_align_4(&buf);
            pip = (struct openvpn_iphdr *) BPTR(&buf);

            hlen = OPENVPN_IPH_GET_LEN(pip->version_len);
            totlen = ntohs(pip->tot_len);

            if (BLEN(&buf) != totlen)
            {
                msgstr = "PACKET TRUNCATION ERROR";
                msglevel = D_PACKET_TRUNC_ERR;
                if (errors)
                {
                    ++(*errors);
                }
            }

            msg(msglevel, "%s %s: size=%d totlen=%d hlen=%d errcount=" counter_format,
                msgstr,
                prefix,
                BLEN(&buf),
                totlen,
                hlen,
                errors ? *errors : (counter_type)0);
        }
    }
}
예제 #5
0
파일: mss.c 프로젝트: angelol/iOpenVPN
void
mss_fixup_dowork (struct buffer *buf, uint16_t maxmss)
{
  int hlen, olen, optlen;
  uint8_t *opt;
  uint16_t *mss;
  int accumulate;
  struct openvpn_tcphdr *tc;

  ASSERT (BLEN (buf) >= (int) sizeof (struct openvpn_tcphdr));

  verify_align_4 (buf);
  tc = (struct openvpn_tcphdr *) BPTR (buf);
  hlen = OPENVPN_TCPH_GET_DOFF (tc->doff_res);

  /* Invalid header length or header without options. */
  if (hlen <= (int) sizeof (struct openvpn_tcphdr)
      || hlen > BLEN (buf))
    return;

  for (olen = hlen - sizeof (struct openvpn_tcphdr),
	 opt = (uint8_t *)(tc + 1);
       olen > 0;
       olen -= optlen, opt += optlen) {
    if (*opt == OPENVPN_TCPOPT_EOL)
      break;
    else if (*opt == OPENVPN_TCPOPT_NOP)
      optlen = 1;
    else {
      optlen = *(opt + 1);
      if (optlen <= 0 || optlen > olen)
        break;
      if (*opt == OPENVPN_TCPOPT_MAXSEG) {
        if (optlen != OPENVPN_TCPOLEN_MAXSEG)
          continue;
        mss = (uint16_t *)(opt + 2);
        if (ntohs (*mss) > maxmss) {
          dmsg (D_MSS, "MSS: %d -> %d",
               (int) ntohs (*mss),
	       (int) maxmss);
          accumulate = *mss;
          *mss = htons (maxmss);
          accumulate -= *mss;
          ADJUST_CHECKSUM (accumulate, tc->check);
        }
      }
    }
  }
}
예제 #6
0
파일: proto.c 프로젝트: jmadhav/lib
/*
 * 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;
}