2
2
3
3
#include <ydb/library/yql/public/udf/udf_helpers.h>
4
4
5
- #include < util/draft/ip .h>
5
+ #include <library/cpp/ipmath/ipmath .h>
6
6
#include <util/generic/buffer.h>
7
7
8
8
namespace {
@@ -13,39 +13,76 @@ namespace {
13
13
using TUnboxedValue = NKikimr ::NUdf ::TUnboxedValue ;
14
14
using TUnboxedValuePod = NKikimr ::NUdf ::TUnboxedValuePod ;
15
15
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 ;
23
18
};
24
19
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 ();
32
45
}
46
+ return addr ;
33
47
}
34
48
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 );
45
72
} else {
46
- ythrow yexception () << " Incorrect size of input, expected "
47
- << " 4 or 16, got " << ref.Size ();
73
+ return Nothing ();
48
74
}
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));
49
86
}
50
87
51
88
SIMPLE_STRICT_UDF (TIsIPv4 , bool (TOptionalString )) {
@@ -73,15 +110,8 @@ namespace {
73
110
bool result = false;
74
111
if (args [0 ]) {
75
112
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 ();
85
115
}
86
116
}
87
117
return TUnboxedValuePod (result );
@@ -92,10 +122,8 @@ namespace {
92
122
if (ref .Size () == 16 ) {
93
123
return valueBuilder -> NewString (ref );
94
124
} 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 ());
99
127
} else {
100
128
ythrow yexception () << "Incorrect size of input, expected "
101
129
<< "4 or 16, got " << ref .Size ();
@@ -105,33 +133,28 @@ namespace {
105
133
SIMPLE_UDF_WITH_OPTIONAL_ARGS (TGetSubnet , char * (TAutoMapString , TOptionalByte ), 1 ) {
106
134
const auto ref = args [0 ].AsStringRef ();
107
135
ui8 subnetSize = args [1 ].GetOrDefault < ui8 > (0 );
108
-
136
+ TIpv6Address addr = DeserializeAddress ( ref );
109
137
if (ref .Size () == 4 ) {
110
138
if (!subnetSize ) {
111
139
subnetSize = 24 ;
112
140
}
141
+ if (subnetSize > 32 ) {
142
+ subnetSize = 32 ;
143
+ }
113
144
} else if (ref .Size () == 16 ) {
114
145
if (!subnetSize ) {
115
146
subnetSize = 64 ;
116
147
}
148
+ if (subnetSize > 128 ) {
149
+ subnetSize = 128 ;
150
+ }
117
151
} else {
118
152
ythrow yexception () << "Incorrect size of input, expected "
119
153
<< "4 or 16, got " << ref .Size ();
120
154
}
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 ());
135
158
}
136
159
137
160
#define EXPORTED_IP_BASE_UDF \
0 commit comments