OpenVPN 3 Core Library
Loading...
Searching...
No Matches
bufip.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// Fast formatting of IP addresses to a Buffer object.
13// Formatting should be indistinguishable from inet_ntop().
14
15#pragma once
16
19#include <openvpn/common/socktypes.hpp> // for ntohs
20
21namespace openvpn::BufferFormat {
22
23static inline void ipv4(Buffer &buf, const std::uint32_t addr) // addr is big-endian
24{
26
27 Decimal::write(buf, addr & 0xff);
28 buf.push_back('.');
29 Decimal::write(buf, (addr >> 8) & 0xff);
30 buf.push_back('.');
31 Decimal::write(buf, (addr >> 16) & 0xff);
32 buf.push_back('.');
33 Decimal::write(buf, addr >> 24);
34}
35
36static inline void ipv6(Buffer &buf, const void *addr)
37{
39
40 // address the IPv6 address as an array of 8 hextets
41 const std::uint16_t *a = static_cast<const std::uint16_t *>(addr);
42
43 // first pass -- look for any extended zero hextet series
44 size_t zero_start = 0;
45 size_t zero_extent = 0;
46 {
47 bool zero = false;
48 size_t start = 0;
49 for (size_t i = 0; i < 8; ++i)
50 {
51 if (zero)
52 {
53 if (a[i])
54 {
55 const size_t extent = i - start;
56 if (extent > zero_extent)
57 {
58 zero_start = start;
59 zero_extent = extent;
60 }
61 zero = false;
62 }
63 }
64 else
65 {
66 if (!a[i])
67 {
68 start = i;
69 zero = true;
70 }
71 }
72 }
73
74 // zero residual state?
75 if (zero)
76 {
77 const size_t extent = 8 - start;
78 if (extent > zero_extent)
79 {
80 zero_start = start;
81 zero_extent = extent;
82 }
83 }
84 }
85
86 // special case for IPv4
87 if (zero_start == 0)
88 {
89 if (zero_extent == 5 && a[5] == 0xffff)
90 {
91 buf_append_string(buf, "::ffff:");
92 ipv4(buf, *reinterpret_cast<const std::uint32_t *>(a + 6));
93 return;
94 }
95 else if (zero_extent == 6)
96 {
97 buf_append_string(buf, "::");
98 ipv4(buf, *reinterpret_cast<const std::uint32_t *>(a + 6));
99 return;
100 }
101 }
102
103 // second pass -- now write the hextets
104 {
105 enum State
106 {
107 INITIAL,
108 ZERO,
109 NORMAL,
110 };
111
112 State state = INITIAL;
113 for (size_t i = 0; i < 8; ++i)
114 {
115 const std::uint16_t hextet = ntohs(a[i]);
116 if (i == zero_start && zero_extent >= 2)
117 state = ZERO;
118 switch (state)
119 {
120 case INITIAL:
121 Hex::write(buf, hextet);
122 state = NORMAL;
123 break;
124 case ZERO:
125 if (!hextet)
126 break;
127 buf.push_back(':');
128 state = NORMAL;
129 // fallthrough
130 case NORMAL:
131 buf.push_back(':');
132 Hex::write(buf, hextet);
133 break;
134 }
135 }
136
137 // process residual state
138 if (state == ZERO)
139 buf_append_string(buf, "::");
140 }
141}
142} // namespace openvpn::BufferFormat
static void write(Buffer &buf, T value)
Definition buffmt.hpp:75
void push_back(const T &value)
Append a T object to the end of the array, resizing the array if necessary.
Definition buffer.hpp:1482
void buf_append_string(Buffer &buf, const std::string &str)
Definition bufstr.hpp:82
remote_address ipv6
reroute_gw ipv4