OpenVPN 3 Core Library
Loading...
Searching...
No Matches
ptb.hpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12// Generates ICMP "packet too big" response
13
14#pragma once
15
17#include <openvpn/ip/csum.hpp>
18#include <openvpn/ip/ip4.hpp>
19#include <openvpn/ip/ip6.hpp>
20#include <openvpn/ip/icmp4.hpp>
21#include <openvpn/ip/icmp6.hpp>
22#include <openvpn/ip/ping6.hpp>
25
26namespace openvpn {
27class Ptb
28{
29 public:
30 static void generate_icmp_ptb(BufferAllocated &buf, std::uint16_t nexthop_mtu)
31 {
32 if (buf.empty())
33 return;
34
35 switch (IPCommon::version(buf[0]))
36 {
37 case IPCommon::IPv4:
38 if (buf.length() <= sizeof(struct IPv4Header))
39 break;
40
41 generate_icmp4_ptb(buf, nexthop_mtu);
42 break;
43
44 case IPCommon::IPv6:
45 if (buf.length() <= sizeof(struct IPv6Header))
46 break;
47
48 generate_icmp6_ptb(buf, nexthop_mtu);
49 break;
50 }
51 }
52
53 private:
54 static void generate_icmp6_ptb(BufferAllocated &buf, std::uint16_t nexthop_mtu)
55 {
56 // ICMPv6 data includes original IPv6 header and as many bytes of payload as possible
57 auto data_size = std::min(buf.length(), std::max(sizeof(ICMPv6), static_cast<size_t>(nexthop_mtu) - sizeof(ICMPv6)));
58
59 // sanity check
60 // we use headroom for adding IPv6 + ICMPv6 headers
61 if ((buf.offset() < sizeof(ICMPv6)) || (buf.capacity() < (sizeof(ICMPv6) + data_size)))
62 return;
63
64 IPv6Header *ipv6 = (IPv6Header *)buf.c_data();
65
66 uint8_t *b = buf.prepend_alloc(sizeof(ICMPv6));
67 ICMPv6 *icmp = (ICMPv6 *)b;
68
69 // IPv6 header
70 icmp->head.version_prio = (6 << 4);
71 icmp->head.flow_lbl[0] = 0;
72 icmp->head.flow_lbl[1] = 0;
73 icmp->head.flow_lbl[2] = 0;
74 icmp->head.payload_len = htons(static_cast<uint16_t>(sizeof(ICMPv6) - sizeof(IPv6Header) + data_size));
76 icmp->head.hop_limit = 64;
77 icmp->head.saddr = ipv6->daddr;
78 icmp->head.daddr = ipv6->saddr;
79
80 // ICMP header
82 icmp->code = 0;
83 icmp->mtu = htonl(nexthop_mtu);
84 icmp->checksum = 0;
85 icmp->checksum = Ping6::csum_icmp(icmp, sizeof(ICMPv6) + data_size);
86
87 buf.set_size(sizeof(ICMPv6) + data_size);
88 }
89
90 static void generate_icmp4_ptb(BufferAllocated &buf, std::uint16_t nexthop_mtu)
91 {
92 // ICMP data includes original IP header and first 8 bytes of payload
93 auto data_size = sizeof(IPv4Header) + ICMPv4::MIN_DATA_SIZE;
94
95 // sanity check
96 // we use headroom for adding IPv4 + ICMPv4 headers
97 if ((buf.offset() < sizeof(ICMPv4)) || (buf.capacity() < (sizeof(ICMPv4) + data_size)))
98 return;
99
100 IPv4Header *ipv4 = (IPv4Header *)buf.c_data();
101
102 uint8_t *b = buf.prepend_alloc(sizeof(ICMPv4));
103 ICMPv4 *icmp = (ICMPv4 *)b;
104
105 icmp->head.saddr = ipv4->daddr;
106 icmp->head.daddr = ipv4->saddr;
108 icmp->head.tos = 0;
109 icmp->head.tot_len = htons(static_cast<uint16_t>(sizeof(ICMPv4) + data_size));
110 icmp->head.id = 0;
111 icmp->head.frag_off = 0;
112 icmp->head.ttl = 64;
114 icmp->head.check = 0;
115 icmp->head.check = IPChecksum::checksum(b, sizeof(IPv4Header));
116
119 icmp->unused = 0;
120 icmp->nexthop_mtu = htons(nexthop_mtu);
121 icmp->checksum = 0;
122 icmp->checksum = IPChecksum::checksum(b + sizeof(IPv4Header), sizeof(ICMPv4) - sizeof(IPv4Header) + data_size);
123
124 buf.set_size(sizeof(ICMPv4) + data_size);
125 }
126};
127} // namespace openvpn
const T * c_data() const
Returns a const pointer to the start of the buffer.
Definition buffer.hpp:1194
T * prepend_alloc(const size_t size)
Allocate space for prepending data to the buffer.
Definition buffer.hpp:1597
size_t length() const
Returns the length of the buffer.
Definition buffer.hpp:1188
size_t capacity() const
Returns the capacity (raw size) of the allocated buffer in T objects.
Definition buffer.hpp:1212
bool empty() const
Returns true if the buffer is empty.
Definition buffer.hpp:1236
size_t offset() const
Returns the current offset (headroom) into the buffer.
Definition buffer.hpp:1218
void set_size(const size_t size)
After an external method, operating on the array as a mutable unsigned char buffer,...
Definition buffer.hpp:1384
static void generate_icmp_ptb(BufferAllocated &buf, std::uint16_t nexthop_mtu)
Definition ptb.hpp:30
static void generate_icmp4_ptb(BufferAllocated &buf, std::uint16_t nexthop_mtu)
Definition ptb.hpp:90
static void generate_icmp6_ptb(BufferAllocated &buf, std::uint16_t nexthop_mtu)
Definition ptb.hpp:54
std::uint16_t checksum(const void *data, const size_t size)
Definition csum.hpp:158
unsigned int version(const std::uint8_t version_len_prio)
Definition ipcommon.hpp:35
std::uint16_t csum_icmp(const ICMPv6 *icmp, const size_t len)
Definition ping6.hpp:83
std::uint8_t type
Definition icmp4.hpp:40
std::uint16_t checksum
Definition icmp4.hpp:45
std::uint8_t code
Definition icmp4.hpp:41
std::uint16_t nexthop_mtu
Definition icmp4.hpp:56
std::uint16_t unused
Definition icmp4.hpp:55
struct IPv4Header head
Definition icmp4.hpp:35
std::uint8_t code
Definition icmp6.hpp:41
std::uint16_t checksum
Definition icmp6.hpp:45
std::uint8_t type
Definition icmp6.hpp:40
std::uint32_t mtu
Definition icmp6.hpp:53
struct IPv6Header head
Definition icmp6.hpp:35
std::uint8_t tos
Definition ip4.hpp:44
std::uint8_t ttl
Definition ip4.hpp:55
std::uint8_t protocol
Definition ip4.hpp:57
std::uint32_t daddr
Definition ip4.hpp:61
std::uint8_t version_len
Definition ip4.hpp:42
std::uint16_t check
Definition ip4.hpp:59
std::uint16_t frag_off
Definition ip4.hpp:53
std::uint16_t id
Definition ip4.hpp:46
static std::uint8_t ver_len(const unsigned int version, const unsigned int len)
Definition ip4.hpp:30
std::uint16_t tot_len
Definition ip4.hpp:45
std::uint32_t saddr
Definition ip4.hpp:60
struct in6_addr saddr
Definition ip6.hpp:35
std::uint8_t hop_limit
Definition ip6.hpp:33
std::uint16_t payload_len
Definition ip6.hpp:31
std::uint8_t flow_lbl[3]
Definition ip6.hpp:29
struct in6_addr daddr
Definition ip6.hpp:36
std::uint8_t version_prio
Definition ip6.hpp:27
std::uint8_t nexthdr
Definition ip6.hpp:32
remote_address ipv6
reroute_gw ipv4