OpenVPN
proto.c
Go to the documentation of this file.
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-2018 OpenVPN 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 along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #elif defined(_MSC_VER)
27 #include "config-msvc.h"
28 #endif
29 
30 #include "syshead.h"
31 
32 #include "proto.h"
33 #include "error.h"
34 
35 #include "memdbg.h"
36 
37 /*
38  * If raw tunnel packet is IPv<X>, return true and increment
39  * buffer offset to start of IP header.
40  */
41 static
42 bool
43 is_ipv_X( int tunnel_type, struct buffer *buf, int ip_ver )
44 {
45  int offset;
46  const struct openvpn_iphdr *ih;
47 
48  verify_align_4(buf);
49  if (tunnel_type == DEV_TYPE_TUN)
50  {
51  if (BLEN(buf) < (int) sizeof(struct openvpn_iphdr))
52  {
53  return false;
54  }
55  offset = 0;
56  }
57  else if (tunnel_type == DEV_TYPE_TAP)
58  {
59  const struct openvpn_ethhdr *eh;
60  if (BLEN(buf) < (int)(sizeof(struct openvpn_ethhdr)
61  + sizeof(struct openvpn_iphdr)))
62  {
63  return false;
64  }
65  eh = (const struct openvpn_ethhdr *) BPTR(buf);
66  if (ntohs(eh->proto) != (ip_ver == 6 ? OPENVPN_ETH_P_IPV6 : OPENVPN_ETH_P_IPV4))
67  {
68  return false;
69  }
70  offset = sizeof(struct openvpn_ethhdr);
71  }
72  else
73  {
74  return false;
75  }
76 
77  ih = (const struct openvpn_iphdr *) (BPTR(buf) + offset);
78 
79  /* IP version is stored in the same bits for IPv4 or IPv6 header */
80  if (OPENVPN_IPH_GET_VER(ih->version_len) == ip_ver)
81  {
82  return buf_advance(buf, offset);
83  }
84  else
85  {
86  return false;
87  }
88 }
89 
90 bool
91 is_ipv4(int tunnel_type, struct buffer *buf)
92 {
93  return is_ipv_X( tunnel_type, buf, 4 );
94 }
95 bool
96 is_ipv6(int tunnel_type, struct buffer *buf)
97 {
98  return is_ipv_X( tunnel_type, buf, 6 );
99 }
100 
101 
102 uint16_t
103 ip_checksum(const sa_family_t af, const uint8_t *payload, const int len_payload,
104  const uint8_t *src_addr, const uint8_t *dest_addr, const int proto)
105 {
106  uint32_t sum = 0;
107  int addr_len = (af == AF_INET) ? 4 : 16;
108 
109  /*
110  * make 16 bit words out of every two adjacent 8 bit words and */
111  /* calculate the sum of all 16 bit words
112  */
113  for (int i = 0; i < len_payload; i += 2)
114  {
115  sum += (uint16_t)(((payload[i] << 8) & 0xFF00)
116  +((i + 1 < len_payload) ? (payload[i + 1] & 0xFF) : 0));
117 
118  }
119 
120  /*
121  * add the pseudo header which contains the IP source and destination
122  * addresses
123  */
124  for (int i = 0; i < addr_len; i += 2)
125  {
126  sum += (uint16_t)((src_addr[i] << 8) & 0xFF00) + (src_addr[i + 1] & 0xFF);
127 
128  }
129  for (int i = 0; i < addr_len; i += 2)
130  {
131  sum += (uint16_t)((dest_addr[i] << 8) & 0xFF00) + (dest_addr[i + 1] & 0xFF);
132  }
133 
134  /* the length of the payload */
135  sum += (uint16_t)len_payload;
136 
137  /* The next header or proto field*/
138  sum += (uint16_t)proto;
139 
140  /*
141  * keep only the last 16 bits of the 32 bit calculated sum and add
142  * the carries
143  */
144  while (sum >> 16)
145  {
146  sum = (sum & 0xFFFF) + (sum >> 16);
147  }
148 
149  /* Take the one's complement of sum */
150  return ((uint16_t) ~sum);
151 }
152 
153 #ifdef PACKET_TRUNCATION_CHECK
154 
155 void
156 ipv4_packet_size_verify(const uint8_t *data,
157  const int size,
158  const int tunnel_type,
159  const char *prefix,
160  counter_type *errors)
161 {
162  if (size > 0)
163  {
164  struct buffer buf;
165 
166  buf_set_read(&buf, data, size);
167 
168  if (is_ipv4(tunnel_type, &buf))
169  {
170  const struct openvpn_iphdr *pip;
171  int hlen;
172  int totlen;
173  const char *msgstr = "PACKET SIZE INFO";
174  unsigned int msglevel = D_PACKET_TRUNC_DEBUG;
175 
176  if (BLEN(&buf) < (int) sizeof(struct openvpn_iphdr))
177  {
178  return;
179  }
180 
181  verify_align_4(&buf);
182  pip = (struct openvpn_iphdr *) BPTR(&buf);
183 
184  hlen = OPENVPN_IPH_GET_LEN(pip->version_len);
185  totlen = ntohs(pip->tot_len);
186 
187  if (BLEN(&buf) != totlen)
188  {
189  msgstr = "PACKET TRUNCATION ERROR";
190  msglevel = D_PACKET_TRUNC_ERR;
191  if (errors)
192  {
193  ++(*errors);
194  }
195  }
196 
197  msg(msglevel, "%s %s: size=%d totlen=%d hlen=%d errcount=" counter_format,
198  msgstr,
199  prefix,
200  BLEN(&buf),
201  totlen,
202  hlen,
203  errors ? *errors : (counter_type)0);
204  }
205  }
206 }
207 
208 #endif /* ifdef PACKET_TRUNCATION_CHECK */
uint8_t version_len
Definition: proto.h:87
#define OPENVPN_IPH_GET_LEN(v)
Definition: proto.h:86
#define OPENVPN_ETH_P_IPV6
Definition: proto.h:61
#define D_PACKET_TRUNC_DEBUG
Definition: errlevel.h:139
static bool buf_advance(struct buffer *buf, int size)
Definition: buffer.h:639
unsigned short sa_family_t
Definition: syshead.h:447
#define D_PACKET_TRUNC_ERR
Definition: errlevel.h:100
#define OPENVPN_IPH_GET_VER(v)
Definition: proto.h:85
uint16_t proto
Definition: proto.h:63
#define BPTR(buf)
Definition: buffer.h:124
uint16_t ip_checksum(const sa_family_t af, const uint8_t *payload, const int len_payload, const uint8_t *src_addr, const uint8_t *dest_addr, const int proto)
Calculates an IP or IPv6 checksum with a pseudo header as required by TCP, UDP and ICMPv6...
Definition: proto.c:103
#define counter_format
Definition: common.h:39
#define OPENVPN_ETH_P_IPV4
Definition: proto.h:60
#define DEV_TYPE_TUN
Definition: proto.h:37
unsigned __int32 uint32_t
Definition: config-msvc.h:121
unsigned int counter_type
Definition: common.h:38
#define msg
Definition: error.h:173
uint8_t * data
Pointer to the allocated memory.
Definition: buffer.h:68
#define BLEN(buf)
Definition: buffer.h:127
unsigned __int8 uint8_t
Definition: config-msvc.h:123
uint16_t tot_len
Definition: proto.h:90
bool is_ipv6(int tunnel_type, struct buffer *buf)
Definition: proto.c:96
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
static bool is_ipv_X(int tunnel_type, struct buffer *buf, int ip_ver)
Definition: proto.c:43
#define verify_align_4(ptr)
Definition: buffer.h:981
bool is_ipv4(int tunnel_type, struct buffer *buf)
Definition: proto.c:91
unsigned __int16 uint16_t
Definition: config-msvc.h:122
static void buf_set_read(struct buffer *buf, const uint8_t *data, int size)
Definition: buffer.h:335
#define DEV_TYPE_TAP
Definition: proto.h:38