Skip to content

Commit 66c888d

Browse files
author
Vadim Averin
committed
Apply patch with changes
1 parent 90031c1 commit 66c888d

File tree

2 files changed

+79
-55
lines changed

2 files changed

+79
-55
lines changed

ydb/library/yql/udfs/common/ip_base/lib/ip_base_udf.h

Lines changed: 78 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#include <ydb/library/yql/public/udf/udf_helpers.h>
44

5-
#include <util/draft/ip.h>
5+
#include <library/cpp/ipmath/ipmath.h>
66
#include <util/generic/buffer.h>
77

88
namespace {
@@ -13,39 +13,76 @@ namespace {
1313
using TUnboxedValue = NKikimr::NUdf::TUnboxedValue;
1414
using TUnboxedValuePod = NKikimr::NUdf::TUnboxedValuePod;
1515

16-
struct TSerializeIpVisitor {
17-
TStringRef operator()(const TIp4& ip) const {
18-
return TStringRef(reinterpret_cast<const char*>(&ip), 4);
19-
}
20-
TStringRef operator()(const TIp6& ip) const {
21-
return TStringRef(reinterpret_cast<const char*>(&ip.Data), 16);
22-
}
16+
struct TRawIp4 {
17+
ui8 a, b, c, d;
2318
};
2419

25-
SIMPLE_STRICT_UDF(TFromString, TOptionalString(TAutoMapString)) {
26-
try {
27-
TString input(args[0].AsStringRef());
28-
const TIp4Or6& ip = Ip4Or6FromString(input.c_str());
29-
return valueBuilder->NewString(std::visit(TSerializeIpVisitor(), ip));
30-
} catch (TSystemError&) {
31-
return TUnboxedValue();
20+
struct TRawIp6 {
21+
ui8 a1, a0, b1, b0, c1, c0, d1, d0, e1, e0, f1, f0, g1, g0, h1, h0;
22+
};
23+
24+
TIpv6Address DeserializeAddress(const TStringRef& str) {
25+
TIpv6Address addr;
26+
if (str.Size() == 4) {
27+
TRawIp4 addr4;
28+
memcpy(&addr4, str.Data(), sizeof addr4);
29+
addr = {addr4.a, addr4.b, addr4.c, addr4.d};
30+
} else if (str.Size() == 16) {
31+
TRawIp6 addr6;
32+
memcpy(&addr6, str.Data(), sizeof addr6);
33+
addr = {ui16(ui32(addr6.a1) << ui32(8) | ui32(addr6.a0)),
34+
ui16(ui32(addr6.b1) << ui32(8) | ui32(addr6.b0)),
35+
ui16(ui32(addr6.c1) << ui32(8) | ui32(addr6.c0)),
36+
ui16(ui32(addr6.d1) << ui32(8) | ui32(addr6.d0)),
37+
ui16(ui32(addr6.e1) << ui32(8) | ui32(addr6.e0)),
38+
ui16(ui32(addr6.f1) << ui32(8) | ui32(addr6.f0)),
39+
ui16(ui32(addr6.g1) << ui32(8) | ui32(addr6.g0)),
40+
ui16(ui32(addr6.h1) << ui32(8) | ui32(addr6.h0)),
41+
};
42+
} else {
43+
ythrow yexception() << "Incorrect size of input, expected "
44+
<< "4 or 16, got " << str.Size();
3245
}
46+
return addr;
3347
}
3448

35-
SIMPLE_UDF(TToString, char*(TAutoMapString)) {
36-
const auto& ref = args[0].AsStringRef();
37-
if (ref.Size() == 4) {
38-
TIp4 ip;
39-
memcpy(&ip, ref.Data(), sizeof(ip));
40-
return valueBuilder->NewString(Ip4Or6ToString(ip));
41-
} else if (ref.Size() == 16) {
42-
TIp6 ip;
43-
memcpy(&ip.Data, ref.Data(), sizeof(ip.Data));
44-
return valueBuilder->NewString(Ip4Or6ToString(ip));
49+
TMaybe<TString> SerializeAddress(const TIpv6Address& addr) {
50+
TString res;
51+
ui128 x = addr;
52+
if (addr.Type() == TIpv6Address::Ipv4) {
53+
TRawIp4 addr4 {
54+
ui8(x >> 24 & 0xff),
55+
ui8(x >> 16 & 0xff),
56+
ui8(x >> 8 & 0xff),
57+
ui8(x & 0xff)
58+
};
59+
res = TString(reinterpret_cast<const char *>(&addr4), sizeof addr4);
60+
} else if (addr.Type() == TIpv6Address::Ipv6) {
61+
TRawIp6 addr6 {
62+
ui8(x >> 120 & 0xff), ui8(x >> 112 & 0xff),
63+
ui8(x >> 104 & 0xff), ui8(x >> 96 & 0xff),
64+
ui8(x >> 88 & 0xff), ui8(x >> 80 & 0xff),
65+
ui8(x >> 72 & 0xff), ui8(x >> 64 & 0xff),
66+
ui8(x >> 56 & 0xff), ui8(x >> 48 & 0xff),
67+
ui8(x >> 40 & 0xff), ui8(x >> 32 & 0xff),
68+
ui8(x >> 24 & 0xff), ui8(x >> 16 & 0xff),
69+
ui8(x >> 8 & 0xff), ui8(x & 0xff)
70+
};
71+
res = TString(reinterpret_cast<const char *>(&addr6), sizeof addr6);
4572
} else {
46-
ythrow yexception() << "Incorrect size of input, expected "
47-
<< "4 or 16, got " << ref.Size();
73+
return Nothing();
4874
}
75+
return res;
76+
}
77+
78+
SIMPLE_STRICT_UDF(TFromString, TOptionalString(TAutoMapString)) {
79+
TIpv6Address addr = TIpv6Address::FromString(args[0].AsStringRef());
80+
auto res = SerializeAddress(addr);
81+
return res ? valueBuilder->NewString(res.GetRef()) : TUnboxedValue(TUnboxedValuePod());
82+
}
83+
84+
SIMPLE_UDF(TToString, char*(TAutoMapString)) {
85+
return valueBuilder->NewString(DeserializeAddress(args[0].AsStringRef()).ToString(false));
4986
}
5087

5188
SIMPLE_STRICT_UDF(TIsIPv4, bool(TOptionalString)) {
@@ -73,15 +110,8 @@ namespace {
73110
bool result = false;
74111
if (args[0]) {
75112
const auto ref = args[0].AsStringRef();
76-
if (ref.Size() == 16 && ref.Data()[10] == -1) {
77-
bool allZeroes = true;
78-
for (int i = 0; i < 10; ++i) {
79-
if (ref.Data()[i] != 0) {
80-
allZeroes = false;
81-
break;
82-
}
83-
}
84-
result = allZeroes;
113+
if (ref.Size() == 16) {
114+
result = DeserializeAddress(ref).Isv4MappedTov6();
85115
}
86116
}
87117
return TUnboxedValuePod(result);
@@ -92,10 +122,8 @@ namespace {
92122
if (ref.Size() == 16) {
93123
return valueBuilder->NewString(ref);
94124
} else if (ref.Size() == 4) {
95-
TIp4 ipv4;
96-
memcpy(&ipv4, ref.Data(), sizeof(ipv4));
97-
const TIp6 ipv6 = Ip6FromIp4(ipv4);
98-
return valueBuilder->NewString(TStringRef(reinterpret_cast<const char*>(&ipv6.Data), 16));
125+
auto addr6 = TIpv6Address::FromString("::ffff:" + DeserializeAddress(ref).ToString(false));
126+
return valueBuilder->NewString(SerializeAddress(addr6).GetRef());
99127
} else {
100128
ythrow yexception() << "Incorrect size of input, expected "
101129
<< "4 or 16, got " << ref.Size();
@@ -105,33 +133,28 @@ namespace {
105133
SIMPLE_UDF_WITH_OPTIONAL_ARGS(TGetSubnet, char*(TAutoMapString, TOptionalByte), 1) {
106134
const auto ref = args[0].AsStringRef();
107135
ui8 subnetSize = args[1].GetOrDefault<ui8>(0);
108-
136+
TIpv6Address addr = DeserializeAddress(ref);
109137
if (ref.Size() == 4) {
110138
if (!subnetSize) {
111139
subnetSize = 24;
112140
}
141+
if (subnetSize > 32) {
142+
subnetSize = 32;
143+
}
113144
} else if (ref.Size() == 16) {
114145
if (!subnetSize) {
115146
subnetSize = 64;
116147
}
148+
if (subnetSize > 128) {
149+
subnetSize = 128;
150+
}
117151
} else {
118152
ythrow yexception() << "Incorrect size of input, expected "
119153
<< "4 or 16, got " << ref.Size();
120154
}
121-
TBuffer result(ref.Data(), ref.Size());
122-
int bytesToMask = ref.Size() * 8 - subnetSize;
123-
ui8 currentByte = ref.Size() - 1;
124-
while (bytesToMask > 0) {
125-
if (bytesToMask > 8) {
126-
result.Data()[currentByte] = 0;
127-
} else {
128-
result.Data()[currentByte] = result.Data()[currentByte] & (0xff << bytesToMask);
129-
}
130-
bytesToMask -= 8;
131-
--currentByte;
132-
}
133-
134-
return valueBuilder->NewString(TStringRef(result.Data(), result.Size()));
155+
ui128 mask = ui128(-1) << int((addr.Type() == TIpv6Address::Ipv6 ? 128 : 32) - subnetSize);
156+
TIpv6Address beg(ui128(addr) & mask, addr.Type());
157+
return valueBuilder->NewString(SerializeAddress(beg).GetRef());
135158
}
136159

137160
#define EXPORTED_IP_BASE_UDF \

ydb/library/yql/udfs/common/ip_base/lib/ya.make

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ SRCS(
1212

1313
PEERDIR(
1414
ydb/library/yql/public/udf
15+
library/cpp/ipmath
1516
)
1617

1718
END()

0 commit comments

Comments
 (0)