OpenVPN 3 Core Library
Loading...
Searching...
No Matches
test_parseargv.cpp
Go to the documentation of this file.
1#include "test_common.hpp"
2#include <iostream>
3
8
9using namespace openvpn;
10
11static std::string expected = "0 [errors-to-stderr]\n"
12 "1 [log] [/Library/Application Support/OpenVPN/log/ovpn3_yonan_net_p0977.log]\n"
13 "2 [config] [stdin]\n"
14 "3 [proto-force] [udp]\n"
15 "4 [management] [/Library/Application Support/OpenVPN/sock/ovpn-6QSai9SzvRcm.sock] [unix]\n"
16 "5 [setenv] [UV_ASCLI_VER] [2.0.18.200]\n"
17 "6 [setenv] [UV_PLAT_REL] [12.5.0]\n"
18 "7 [auth-nocache]\n"
19 "8 [management-hold]\n"
20 "9 [management-client]\n"
21 "10 [management-query-passwords]\n"
22 "11 [management-query-remote]\n"
23 "12 [management-up-down]\n"
24 "13 [management-client-user] [root]\n"
25 "14 [allow-pull-fqdn]\n"
26 "15 [auth-retry] [interact]\n"
27 "16 [push-peer-info]\n"
28 "17 [setenv] [UV_ASCLI_VER] [2.0.18.200]\n"
29 "18 [setenv] [UV_PLAT_REL] [12.5.0]\n";
30
31static const char *input[] = {
32 // clang-format off
33 "unittest",
34 "--errors-to-stderr",
35 "--log", "/Library/Application Support/OpenVPN/log/ovpn3_yonan_net_p0977.log",
36 "--config", "stdin",
37 "--proto-force", "udp",
38 "--management", "/Library/Application Support/OpenVPN/sock/ovpn-6QSai9SzvRcm.sock",
39 "unix",
40 "--setenv", "UV_ASCLI_VER", "2.0.18.200",
41 "--setenv", "UV_PLAT_REL", "12.5.0",
42 "--auth-nocache",
43 "--management-hold",
44 "--management-client",
45 "--management-query-passwords",
46 "--management-query-remote",
47 "--management-up-down",
48 "--management-client-user", "root",
49 "--allow-pull-fqdn",
50 "--auth-retry", "interact",
51 "--push-peer-info",
52 "--setenv", "UV_ASCLI_VER", "2.0.18.200",
53 "--setenv", "UV_PLAT_REL", "12.5.0"
54 // clang-format on
55};
56
57TEST(argv, parse)
58{
59 const OptionList opt = OptionList::parse_from_argv_static(string::from_argv(sizeof(input) / sizeof(char *),
60 const_cast<char **>(input),
61 true));
63}
64
65static const char config[] = "listen 1.2.3.4 1000 tcp 2\n"
66 "listen 0.0.0.0 4000 tcp 4*N\n"
67 "listen ::0 8000 tcp\n"
68 "listen sock/ststrack-%s.sock unix-stream\n";
69
70TEST(argv, portoffset1)
71{
73 const Listen::List ll1(opt1, "listen", Listen::List::Nominal, 4);
74
75 EXPECT_EQ(
76 "listen 1.2.3.4 1000 TCPv4 2\nlisten 0.0.0.0 4000 TCPv4 16\nlisten ::0 8000 TCPv6 1\nlisten sock/ststrack-%s.sock UnixStream 1\n",
77 ll1.to_string());
78
79 std::string exp2("listen 1.2.3.4 1000 TCPv4 0\nlisten 1.2.3.4 1001 TCPv4 0\n");
80
81 for (int i = 4000; i < 4016; i++)
82 exp2 += "listen 0.0.0.0 " + std::to_string(i) + " TCPv4 0\n";
83
84 exp2 += "listen ::0 8000 TCPv6 0\n"
85 "listen sock/ststrack-0.sock UnixStream 0\n";
86
87 const Listen::List ll2 = ll1.expand_ports_by_n_threads(100);
88 EXPECT_EQ(exp2, ll2.to_string());
89}
90
91TEST(argv, portoffset2)
92{
94 const Listen::List ll(opt, "listen", Listen::List::Nominal, 4);
95 for (unsigned int unit = 0; unit < 4; ++unit)
96 {
97 std::stringstream exp;
98 exp << "listen 1.2.3.4 " << 1000 + unit << " TCPv4 0\n";
99 ;
100 exp << "listen 0.0.0.0 400" << unit << " TCPv4 0\n";
101 exp << "listen ::0 800" << unit << " TCPv6 0\n";
102 exp << "listen sock/ststrack-" << unit << ".sock UnixStream 0\n";
103
104 const Listen::List llu = ll.expand_ports_by_unit(unit);
105 EXPECT_EQ(exp.str(), llu.to_string());
106 }
107}
108
109static void extract_auth_token(const OptionList &opt)
110{
111 const Option &o = opt.get("auth-token");
112 o.min_args(2);
113 ASSERT_EQ("auth-token SESS_ID_wJdhHMc7tr9GwbMNEW6b+A==", o.render(0));
114}
115
116static void verify_topology(const OptionList &opt)
117{
118 const Option &o = opt.get("topology");
119 o.min_args(2);
120 if (o.ref(1) != "subnet")
121 throw option_error("only topology subnet supported");
122}
123
124static void extract_ifconfig(const OptionList &opt)
125{
126 const Option &o = opt.get("ifconfig");
127 o.exact_args(3);
128 std::string ip = IP::Addr::validate(o.ref(1), "ifconfig-ip");
129 std::string mask = IP::Addr::validate(o.ref(2), "ifconfig-net");
130 ASSERT_EQ("5.5.8.4", ip);
131 ASSERT_EQ("255.255.252.0", mask);
132}
133
134TEST(argv, parsetest)
135{
136 const std::string opt_csv = "explicit-exit-notify,topology subnet,route-delay 5 30,dhcp-pre-release,dhcp-renew,dhcp-release,route-metric 101,ping 5,ping-restart 40,redirect-gateway def1,redirect-gateway bypass-dhcp,redirect-gateway autolocal,route-gateway 5.5.8.1,dhcp-option DNS 172.16.0.23,register-dns,auth-token SESS_ID_wJdhHMc7tr9GwbMNEW6b+A==,comp-lzo no,ifconfig 5.5.8.4 255.255.252.0";
137 OptionList opt;
138 OptionList::Limits limits("parsetest limit out of range", 2048, 16, 8, 512, 64);
139 opt.parse_from_csv(opt_csv, &limits);
140 opt.update_map();
141 ASSERT_EQ("explicit-exit-notify\n"
142 "topology subnet\n"
143 "route-delay 5 30\n"
144 "dhcp-pre-release\n"
145 "dhcp-renew\n"
146 "dhcp-release\n"
147 "route-metric 101\n"
148 "ping 5\n"
149 "ping-restart 40\n"
150 "redirect-gateway def1\n"
151 "redirect-gateway bypass-dhcp\n"
152 "redirect-gateway autolocal\n"
153 "route-gateway 5.5.8.1\n"
154 "dhcp-option DNS 172.16.0.23\n"
155 "register-dns\n"
156 "auth-token SESS_ID_wJdhHMc7tr9GwbMNEW6b+A==\n"
157 "comp-lzo no\n"
158 "ifconfig 5.5.8.4 255.255.252.0\n",
159 opt.render(0));
161 extract_ifconfig(opt);
162 verify_topology(opt);
163 ASSERT_EQ(1066u, limits.get_bytes());
164}
165
166static void csv_test(const std::string &str)
167{
168 std::vector<std::string> list = Split::by_char<std::vector<std::string>, StandardLex, Split::NullLimit>(str, ',');
169 std::stringstream s;
170 std::copy(list.begin(), list.end(), std::ostream_iterator<std::string>(s, "\n"));
171 ASSERT_EQ("this\n"
172 "is\n"
173 "\n"
174 "a\n"
175 "\"foo,bar\"\n"
176 "test\n",
177 s.str());
178}
179
180static void space_test(const std::string &str, const std::string &expected)
181{
182 std::vector<std::string> list = Split::by_space<std::vector<std::string>, StandardLex, SpaceMatch, Split::NullLimit>(str);
183 std::stringstream s;
184 std::copy(list.begin(), list.end(), std::ostream_iterator<std::string>(s, "\n"));
185
186 ASSERT_EQ(expected, s.str());
187}
188
189static void options_csv_test(const std::string &str, const std::string &elem)
190{
192 ASSERT_EQ(getSortedString("V4\n"
193 "dev-type tun\n"
194 "link-mtu 1558\n"
195 "tun-mtu 1500\n"
196 "proto UDPv4\n"
197 "comp-lzo\n"
198 "keydir 1\n"
199 "cipher AES-256-CBC\n"
200 "auth SHA1\n"
201 "keysize 256\n"
202 "tls-auth\n"
203 "key-method 2\n"
204 "tls-client\n"),
205 getSortedString(olist.render(0)));
206
207 ASSERT_EQ(getSortedString("tls-client [ 12 ]\n"
208 "key-method [ 11 ]\n"
209 "tls-auth [ 10 ]\n"
210 "link-mtu [ 2 ]\n"
211 "auth [ 8 ]\n"
212 "V4 [ 0 ]\n"
213 "comp-lzo [ 5 ]\n"
214 "tun-mtu [ 3 ]\n"
215 "proto [ 4 ]\n"
216 "keysize [ 9 ]\n"
217 "keydir [ 6 ]\n"
218 "dev-type [ 1 ]\n"
219 "cipher [ 7 ]\n"),
220 getSortedString(olist.render_map()));
221
222 if (!elem.empty())
223 {
224 OptionList::IndexMap::const_iterator e = olist.map().find(elem);
225 ASSERT_TRUE(e != olist.map().end());
226 }
227}
228
229TEST(argv, parsetest1)
230{
231 csv_test("this,is,,a,\"foo,bar\",test");
232 space_test(R"( this is a "foo \\ bar" test of something \"rather\" grt )", "this\nis\na\nfoo \\ bar\ntest\nof\nsomething\n\"rather\"\ngrt\n");
233 space_test(R"(this is a te""st a "" b)", "this\nis\na\ntest\na\n\nb\n");
234 options_csv_test("V4,dev-type tun,link-mtu 1558,tun-mtu 1500,proto UDPv4,comp-lzo,keydir 1,cipher AES-256-CBC,auth SHA1,keysize 256,tls-auth,key-method 2,tls-client",
235 "");
236}
237
238TEST(argv, QuotesTest)
239{
240 auto str = "\"abc,def\",\'abc,def\',\"abc',def\",\'abc\"def\',\'abc\"";
241 std::vector<std::string> list = Split::by_char<std::vector<std::string>, StandardLex, Split::NullLimit>(str, ',');
242 std::stringstream s;
243 std::copy(list.begin(), list.end(), std::ostream_iterator<std::string>(s, "\n"));
244 ASSERT_EQ("\"abc,def\"\n"
245 "\'abc,def'\n"
246 "\"abc',def\"\n"
247 "\'abc\"def\'\n"
248 "\'abc\"\n",
249 s.str());
250}
static std::string validate(const std::string &ipstr, const TITLE &title, const Version required_version)
Definition ip.hpp:131
List expand_ports_by_n_threads(const size_t max_size) const
std::string to_string() const
List expand_ports_by_unit(const unsigned int unit) const
std::uint64_t get_bytes() const
Definition options.hpp:636
static OptionList parse_from_argv_static(const std::vector< std::string > &argv)
Definition options.hpp:875
const IndexMap & map() const
Definition options.hpp:1562
std::string render_map() const
Definition options.hpp:1497
static OptionList parse_from_csv_static(const std::string &str, Limits *lim)
Definition options.hpp:844
void parse_from_csv(const std::string &str, Limits *lim)
Definition options.hpp:890
const Option & get(const std::string &name) const
Definition options.hpp:1254
static OptionList parse_from_config_static(const std::string &str, Limits *lim)
Definition options.hpp:859
std::string render(const unsigned int flags) const
Definition options.hpp:1465
void exact_args(const size_t n) const
Definition options.hpp:136
void min_args(const size_t n) const
Definition options.hpp:129
const std::string & ref(const size_t i) const
Definition options.hpp:353
std::string render(const unsigned int flags) const
Definition options.hpp:264
std::vector< std::string > from_argv(int argc, char *argv[], const bool skip_first)
Definition string.hpp:541
os<< "Session Name: "<< tbc-> session_name<< '\n';os<< "Layer: "<< tbc-> layer str()<< '\n'
std::string getSortedString(const std::string &output)
static void extract_ifconfig(const OptionList &opt)
static void space_test(const std::string &str, const std::string &expected)
static void verify_topology(const OptionList &opt)
static std::string expected
TEST(argv, parse)
static void csv_test(const std::string &str)
static void extract_auth_token(const OptionList &opt)
static const char config[]
static void options_csv_test(const std::string &str, const std::string &elem)
static const char * input[]