Skip to content

Commit 41c753d

Browse files
jgautier-anssifabienfl-orc
authored andcommitted
OrcLib: Text: Fmt: add in_addr
1 parent ffb081d commit 41c753d

File tree

5 files changed

+193
-0
lines changed

5 files changed

+193
-0
lines changed

src/OrcLib/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,8 @@ set(SRC_TEXT
658658
"Text/Guid.cpp"
659659
"Text/Hex.h"
660660
"Text/HexDump.h"
661+
"Text/in_addr.h"
662+
"Text/in_addr.cpp"
661663
"Text/StdoutContainerAdapter.h"
662664
"Text/Tree.h"
663665
"Text/Tree.cpp"

src/OrcLib/OrcLib.h

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <type_traits>
3131

3232
#include <Windows.h>
33+
#include <winsock.h>
3334

3435
#include <Utils/Result.h>
3536

src/OrcLib/Text/Fmt/in_addr.h

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//
2+
// SPDX-License-Identifier: LGPL-2.1-or-later
3+
//
4+
// Copyright © 2023 ANSSI. All Rights Reserved.
5+
//
6+
// Author(s): fabienfl (ANSSI)
7+
//
8+
9+
#pragma once
10+
11+
#include "Text/in_addr.h"
12+
13+
namespace fmt_in_addr {
14+
15+
static const char* kNotApplicable = "<N/A>";
16+
static const wchar_t* kNotApplicableW = L"<N/A>";
17+
18+
} // namespace fmt_in_addr
19+
20+
template <>
21+
struct fmt::formatter<in_addr> : public fmt::formatter<std::string_view>
22+
{
23+
template <typename FormatContext>
24+
auto format(const in_addr& ip, FormatContext& ctx) -> decltype(ctx.out())
25+
{
26+
auto s = Orc::ToString(ip).value_or(fmt_in_addr::kNotApplicable);
27+
return formatter<std::string_view>::format(s, ctx);
28+
}
29+
};
30+
31+
template <>
32+
struct fmt::formatter<in_addr, wchar_t> : public fmt::formatter<std::wstring_view, wchar_t>
33+
{
34+
template <typename FormatContext>
35+
auto format(const in_addr& ip, FormatContext& ctx) -> decltype(ctx.out())
36+
{
37+
auto s = Orc::ToWString(ip).value_or(fmt_in_addr::kNotApplicableW);
38+
return formatter<std::wstring_view, wchar_t>::format(s, ctx);
39+
}
40+
};
41+
42+
template <>
43+
struct fmt::formatter<in6_addr> : public fmt::formatter<std::string_view>
44+
{
45+
template <typename FormatContext>
46+
auto format(const in6_addr& ip, FormatContext& ctx) -> decltype(ctx.out())
47+
{
48+
auto s = Orc::ToString(ip).value_or(fmt_in_addr::kNotApplicable);
49+
return formatter<std::string_view>::format(s, ctx);
50+
}
51+
};
52+
53+
template <>
54+
struct fmt::formatter<in6_addr, wchar_t> : public fmt::formatter<std::wstring_view, wchar_t>
55+
{
56+
template <typename FormatContext>
57+
auto format(const in6_addr& ip, FormatContext& ctx) -> decltype(ctx.out())
58+
{
59+
auto s = Orc::ToWString(ip).value_or(fmt_in_addr::kNotApplicableW);
60+
return formatter<std::wstring_view, wchar_t>::format(s, ctx);
61+
}
62+
};

src/OrcLib/Text/in_addr.cpp

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#include "in_addr.h"
2+
3+
#ifdef __has_include
4+
# if __has_include("ip2string.h")
5+
# define ENABLE_IP2STRING
6+
# endif
7+
#endif
8+
9+
#ifdef ENABLE_IP2STRING
10+
#include <ip2string.h>
11+
#include <Mstcpip.h>
12+
13+
#include "Log/Log.h"
14+
#include "Text/Fmt/in_addr.h"
15+
16+
#ifndef STATUS_SUCCESS
17+
# define STATUS_SUCCESS 0
18+
#endif
19+
20+
namespace {
21+
22+
const static size_t kDefaultStringSize = 256;
23+
24+
}
25+
26+
namespace Orc {
27+
28+
Result<std::string> ToString(const in_addr& ip)
29+
{
30+
std::string s;
31+
s.reserve(kDefaultStringSize);
32+
33+
ULONG size = s.size();
34+
auto status = RtlIpv4AddressToStringExA(&ip, 0, s.data(), &size);
35+
if (status != STATUS_SUCCESS)
36+
{
37+
std::error_code ec = SystemError(HRESULT_FROM_NT(status));
38+
Log::Error("Failed RtlIpv4AddressToStringExA [{}]", ec);
39+
return ec;
40+
}
41+
42+
s.resize(size);
43+
return s;
44+
}
45+
46+
Result<std::wstring> ToWString(const in_addr& ip)
47+
{
48+
std::wstring s;
49+
s.reserve(kDefaultStringSize);
50+
51+
ULONG size = s.size();
52+
auto status = RtlIpv4AddressToStringExW(&ip, 0, s.data(), &size);
53+
if (status != STATUS_SUCCESS)
54+
{
55+
std::error_code ec = SystemError(HRESULT_FROM_NT(status));
56+
Log::Error("Failed RtlIpv4AddressToStringExW [{}]", ec);
57+
return ec;
58+
}
59+
60+
s.resize(size);
61+
return s;
62+
}
63+
64+
Result<std::string> ToString(const in6_addr& ip)
65+
{
66+
std::string s;
67+
s.reserve(kDefaultStringSize);
68+
69+
ULONG size = s.size();
70+
auto status = RtlIpv6AddressToStringExA(&ip, 0, 0, s.data(), &size);
71+
if (status != STATUS_SUCCESS)
72+
{
73+
std::error_code ec = SystemError(HRESULT_FROM_NT(status));
74+
Log::Error("Failed RtlIpv6AddressToStringExA [{}]", ec);
75+
return ec;
76+
}
77+
78+
s.resize(size);
79+
return s;
80+
}
81+
82+
Result<std::wstring> ToWString(const in6_addr& ip)
83+
{
84+
std::wstring s;
85+
s.reserve(kDefaultStringSize);
86+
87+
ULONG size = s.size();
88+
auto status = RtlIpv6AddressToStringExW(&ip, 0, 0, s.data(), &size);
89+
if (status != STATUS_SUCCESS)
90+
{
91+
std::error_code ec = SystemError(HRESULT_FROM_NT(status));
92+
Log::Error("Failed RtlIpv6AddressToStringExW [{}]", ec);
93+
return ec;
94+
}
95+
96+
s.resize(size);
97+
return s;
98+
}
99+
100+
} // namespace Orc
101+
102+
#endif // ENABLE_IP2STRING

src/OrcLib/Text/in_addr.h

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//
2+
// SPDX-License-Identifier: LGPL-2.1-or-later
3+
//
4+
// Copyright © 2022 ANSSI. All Rights Reserved.
5+
//
6+
// Author(s): jeanga (ANSSI)
7+
//
8+
9+
#pragma once
10+
11+
#include <string>
12+
13+
#include <Utils/Result.h>
14+
15+
struct in_addr;
16+
struct in6_addr;
17+
18+
namespace Orc {
19+
20+
Result<std::string> ToString(const in_addr& ip);
21+
Result<std::wstring> ToWString(const in_addr& ip);
22+
23+
Result<std::string> ToString(const in6_addr& ip);
24+
Result<std::wstring> ToWString(const in6_addr& ip);
25+
26+
} // namespace Orc

0 commit comments

Comments
 (0)