core/common/NetworkUtil.cpp (154 lines of code) (raw):
/*
* Copyright 2025 iLogtail Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "NetworkUtil.h"
#include <cstdint>
#include <array>
#include <variant>
#include "common/StringTools.h"
#include "logger/Logger.h"
#if defined(__linux__)
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/un.h>
#endif
namespace logtail {
static const std::string EMPTY_STRING = "";
const std::string& GetStateString(uint16_t state) {
static const std::array<std::string, 14> TCP_STATE_STRINGS = {{"UNKNOWN_STATE",
"TCP_ESTABLISHED",
"TCP_SYN_SENT",
"TCP_SYN_RECV",
"TCP_FIN_WAIT1",
"TCP_FIN_WAIT2",
"TCP_TIME_WAIT",
"TCP_CLOSE",
"TCP_CLOSE_WAIT",
"TCP_LAST_ACK",
"TCP_LISTEN",
"TCP_CLOSING",
"TCP_NEW_SYN_RECV",
"TCP_MAX_STATES"}};
static const std::string INVALID_STATE = "INVALID_STATE";
if (state >= TCP_STATE_STRINGS.size()) {
return INVALID_STATE;
}
return TCP_STATE_STRINGS[state];
}
std::string GetAddrString(uint32_t ad) {
#if defined(__linux__)
auto addr = ntohl(ad);
struct in_addr ipAddr;
ipAddr.s_addr = htonl(addr);
char ip_str[INET_ADDRSTRLEN];
if (inet_ntop(AF_INET, &ipAddr, ip_str, INET_ADDRSTRLEN)) {
return ip_str;
}
#endif
return EMPTY_STRING;
}
const std::string& GetFamilyString(uint16_t family) {
#if defined(__linux__)
static const std::string FAMILY_INET = "AF_INET";
static const std::string FAMILY_INET6 = "AF_INET6";
static const std::string FAMILY_UNIX = "AF_UNIX";
static const std::string FAMILY_UNKNOWN = "UNKNOWN_FAMILY";
switch (family) {
case AF_INET:
return FAMILY_INET;
case AF_INET6:
return FAMILY_INET6;
case AF_UNIX:
return FAMILY_UNIX;
default:
return FAMILY_UNKNOWN;
}
#else
return EMPTY_STRING;
#endif
}
const std::string& GetProtocolString(uint16_t protocol) {
static const std::string PROTOCOL_ICMP = "ICMP";
static const std::string PROTOCOL_IGMP = "IGMP";
static const std::string PROTOCOL_IP = "IP";
static const std::string PROTOCOL_TCP = "TCP";
static const std::string PROTOCOL_UDP = "UDP";
static const std::string PROTOCOL_ENCAPSULATION = "ENCAP";
static const std::string PROTOCOL_OSPF = "OSPF";
static const std::string PROTOCOL_UNKNOWN = "Unknown";
switch (protocol) {
case 1:
return PROTOCOL_ICMP;
case 2:
return PROTOCOL_IGMP;
case 4:
return PROTOCOL_IP;
case 6:
return PROTOCOL_TCP;
case 17:
return PROTOCOL_UDP;
case 41:
return PROTOCOL_ENCAPSULATION;
case 89:
return PROTOCOL_OSPF;
default:
return PROTOCOL_UNKNOWN;
}
}
constexpr int kIPv4BitLen = 32;
constexpr int kIPv6BitLen = 128;
bool CIDRContainsForIPV4(uint32_t cidrIp, size_t prefixLen, uint32_t ip) {
LOG_DEBUG(sLogger, ("cidr ip", cidrIp)("ip", ip));
return ntohl(cidrIp) >> (kIPv4BitLen - prefixLen) == ntohl(ip) >> (kIPv4BitLen - prefixLen);
}
// The IPv4 IP is located in the last 32-bit word of IPv6 address.
constexpr int kIPv4Offset = 3;
bool ParseIPv4Addr(const std::string& addrStr, struct in_addr* inAddr) {
if (!inet_pton(AF_INET, addrStr.c_str(), inAddr)) {
return false;
}
return true;
}
bool ParseIPv6Addr(const std::string& addrStr, struct in6_addr* in6Addr) {
if (!inet_pton(AF_INET6, addrStr.c_str(), in6Addr)) {
return false;
}
return true;
}
bool ParseIPAddr(const std::string& addrStr, InetAddr* ipAddr) {
struct in_addr v4Addr = {};
struct in6_addr v6Addr = {};
v6Addr.s6_addr;
if (ParseIPv4Addr(addrStr, &v4Addr)) {
ipAddr->mFamily = InetAddrFamily::kIPv4;
ipAddr->mIp = v4Addr.s_addr;
} else if (ParseIPv6Addr(addrStr, &v6Addr)) {
ipAddr->mFamily = InetAddrFamily::kIPv6;
ipAddr->mIp = std::array<uint8_t, 16>();
std::copy(std::begin(v6Addr.s6_addr),
std::end(v6Addr.s6_addr),
std::get<std::array<uint8_t, 16>>(ipAddr->mIp).begin());
} else {
return false;
}
return true;
}
bool ParseCIDR(const std::string& cidrStr, CIDR* cidr) {
auto items = StringSpliter(cidrStr, "/");
if (items.size() != 2) {
return false;
}
int prefixLen = -1;
StringTo(items[1], prefixLen);
if (prefixLen < 0) {
return false;
}
InetAddr addr;
ParseIPAddr(items[0], &addr);
if (addr.mFamily == InetAddrFamily::kIPv4 && prefixLen > kIPv4BitLen) {
return false;
}
if (addr.mFamily == InetAddrFamily::kIPv6 && prefixLen > kIPv6BitLen) {
return false;
}
cidr->mAddr = std::move(addr);
cidr->mPrefixLength = prefixLen;
return true;
}
} // namespace logtail