1/* 2 * OpenVPN -- An application to securely tunnel IP networks 3 * over a single TCP/UDP port, with support for SSL/TLS-based 4 * session authentication and key exchange, 5 * packet encryption, packet authentication, and 6 * packet compression. 7 * 8 * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net> 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 12 * as published by the Free Software Foundation. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program (see the file COPYING included with this 21 * distribution); if not, write to the Free Software Foundation, Inc., 22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#elif defined(_MSC_VER) 28#include "config-msvc.h" 29#endif 30 31#include "syshead.h" 32 33#include "proto.h" 34#include "error.h" 35 36#include "memdbg.h" 37 38/* 39 * If raw tunnel packet is IPv<X>, return true and increment 40 * buffer offset to start of IP header. 41 */ 42static 43bool 44is_ipv_X ( int tunnel_type, struct buffer *buf, int ip_ver ) 45{ 46 int offset; 47 const struct openvpn_iphdr *ih; 48 49 verify_align_4 (buf); 50 if (tunnel_type == DEV_TYPE_TUN) 51 { 52 if (BLEN (buf) < (int) sizeof (struct openvpn_iphdr)) 53 return false; 54 offset = 0; 55 } 56 else if (tunnel_type == DEV_TYPE_TAP) 57 { 58 const struct openvpn_ethhdr *eh; 59 if (BLEN (buf) < (int)(sizeof (struct openvpn_ethhdr) 60 + sizeof (struct openvpn_iphdr))) 61 return false; 62 eh = (const struct openvpn_ethhdr *) BPTR (buf); 63 if (ntohs (eh->proto) != OPENVPN_ETH_P_IPV4) 64 return false; 65 offset = sizeof (struct openvpn_ethhdr); 66 } 67 else 68 return false; 69 70 ih = (const struct openvpn_iphdr *) (BPTR (buf) + offset); 71 72 /* IP version is stored in the same bits for IPv4 or IPv6 header */ 73 if (OPENVPN_IPH_GET_VER (ih->version_len) == ip_ver) 74 return buf_advance (buf, offset); 75 else 76 return false; 77} 78 79bool 80is_ipv4 (int tunnel_type, struct buffer *buf) 81{ 82 return is_ipv_X( tunnel_type, buf, 4 ); 83} 84bool 85is_ipv6 (int tunnel_type, struct buffer *buf) 86{ 87 return is_ipv_X( tunnel_type, buf, 6 ); 88} 89 90#ifdef PACKET_TRUNCATION_CHECK 91 92void 93ipv4_packet_size_verify (const uint8_t *data, 94 const int size, 95 const int tunnel_type, 96 const char *prefix, 97 counter_type *errors) 98{ 99 if (size > 0) 100 { 101 struct buffer buf; 102 103 buf_set_read (&buf, data, size); 104 105 if (is_ipv4 (tunnel_type, &buf)) 106 { 107 const struct openvpn_iphdr *pip; 108 int hlen; 109 int totlen; 110 const char *msgstr = "PACKET SIZE INFO"; 111 unsigned int msglevel = D_PACKET_TRUNC_DEBUG; 112 113 if (BLEN (&buf) < (int) sizeof (struct openvpn_iphdr)) 114 return; 115 116 verify_align_4 (&buf); 117 pip = (struct openvpn_iphdr *) BPTR (&buf); 118 119 hlen = OPENVPN_IPH_GET_LEN (pip->version_len); 120 totlen = ntohs (pip->tot_len); 121 122 if (BLEN (&buf) != totlen) 123 { 124 msgstr = "PACKET TRUNCATION ERROR"; 125 msglevel = D_PACKET_TRUNC_ERR; 126 if (errors) 127 ++(*errors); 128 } 129 130 msg (msglevel, "%s %s: size=%d totlen=%d hlen=%d errcount=" counter_format, 131 msgstr, 132 prefix, 133 BLEN (&buf), 134 totlen, 135 hlen, 136 errors ? *errors : (counter_type)0); 137 } 138 } 139} 140 141#endif 142