@@ -136,15 +136,125 @@ describe('IP Utils', () => {
136
136
expect ( net_utils . is_localhost ( 'google.com' ) ) . toBe ( false ) ;
137
137
} ) ;
138
138
139
- it ( 'should return true for private IPv4 addresses or false to any other address' , ( ) => {
139
+ it ( 'should return true for the IPv6 loopback address ::1' , ( ) => {
140
+ const buf = Buffer . alloc ( 16 ) ;
141
+ buf [ 15 ] = 1 ; // last byte is 1
142
+ expect ( net_utils . is_ipv6_loopback_buffer ( buf ) ) . toBe ( true ) ;
143
+ } ) ;
144
+
145
+ it ( 'should return false for :: (all zeros)' , ( ) => {
146
+ const buf = Buffer . alloc ( 16 ) ; // all zeros
147
+ expect ( net_utils . is_ipv6_loopback_buffer ( buf ) ) . toBe ( false ) ;
148
+ } ) ;
149
+
150
+ it ( 'should return false for random non-loopback IPv6 address' , ( ) => {
151
+ const buf = Buffer . from ( [
152
+ 0x20 , 0x01 , 0x0d , 0xb8 ,
153
+ 0x85 , 0xa3 , 0x00 , 0x00 ,
154
+ 0x00 , 0x00 , 0x8a , 0x2e ,
155
+ 0x03 , 0x70 , 0x73 , 0x34
156
+ ] ) ;
157
+ expect ( net_utils . is_ipv6_loopback_buffer ( buf ) ) . toBe ( false ) ;
158
+ } ) ;
159
+
160
+ it ( 'should return false if last byte is not 1' , ( ) => {
161
+ const buf = Buffer . alloc ( 16 ) ;
162
+ buf [ 15 ] = 2 ; // last byte is 2
163
+ expect ( net_utils . is_ipv6_loopback_buffer ( buf ) ) . toBe ( false ) ;
164
+ } ) ;
165
+
166
+ it ( 'should return false if first 15 bytes are not all zero' , ( ) => {
167
+ const buf = Buffer . alloc ( 16 ) ;
168
+ buf [ 0 ] = 1 ; // first byte not zero
169
+ buf [ 15 ] = 1 ; // last byte correct
170
+ expect ( net_utils . is_ipv6_loopback_buffer ( buf ) ) . toBe ( false ) ;
171
+ } ) ;
172
+
173
+ it ( 'should return false for buffers of incorrect length' , ( ) => {
174
+ const shortBuf = Buffer . alloc ( 8 ) ;
175
+ expect ( net_utils . is_ipv6_loopback_buffer ( shortBuf ) ) . toBe ( false ) ;
176
+
177
+ const longBuf = Buffer . alloc ( 32 ) ;
178
+ longBuf [ 31 ] = 1 ;
179
+ expect ( net_utils . is_ipv6_loopback_buffer ( longBuf ) ) . toBe ( false ) ;
180
+ } ) ;
181
+
182
+ it ( 'should return true for 10/8' , ( ) => {
140
183
expect ( net_utils . is_private ( '10.0.0.1' ) ) . toBe ( true ) ;
184
+ expect ( net_utils . is_private ( '10.255.255.255' ) ) . toBe ( true ) ;
185
+ } ) ;
186
+
187
+ it ( 'should return true for 172.16.0.0 – 172.31.255.255' , ( ) => {
141
188
expect ( net_utils . is_private ( '172.16.0.1' ) ) . toBe ( true ) ;
142
- expect ( net_utils . is_private ( '192.168.1.1' ) ) . toBe ( true ) ;
189
+ expect ( net_utils . is_private ( '172.31.255.254' ) ) . toBe ( true ) ;
190
+ expect ( net_utils . is_private ( '172.15.0.1' ) ) . toBe ( false ) ; // outside range
191
+ expect ( net_utils . is_private ( '172.32.0.1' ) ) . toBe ( false ) ; // outside range
192
+ } ) ;
193
+
194
+ it ( 'should return true for 192.168/16' , ( ) => {
195
+ expect ( net_utils . is_private ( '192.168.0.1' ) ) . toBe ( true ) ;
196
+ expect ( net_utils . is_private ( '192.168.255.255' ) ) . toBe ( true ) ;
197
+ } ) ;
198
+
199
+ it ( 'should return true for loopback 127/8' , ( ) => {
200
+ expect ( net_utils . is_private ( '127.0.0.1' ) ) . toBe ( true ) ;
201
+ expect ( net_utils . is_private ( '127.255.255.255' ) ) . toBe ( true ) ;
202
+ } ) ;
203
+
204
+ it ( 'should return true for link-local 169.254/16' , ( ) => {
205
+ expect ( net_utils . is_private ( '169.254.1.1' ) ) . toBe ( true ) ;
206
+ } ) ;
207
+
208
+ it ( 'should return false for public IPv4' , ( ) => {
143
209
expect ( net_utils . is_private ( '8.8.8.8' ) ) . toBe ( false ) ;
144
210
expect ( net_utils . is_private ( '1.1.1.1' ) ) . toBe ( false ) ;
145
- expect ( net_utils . is_private ( '2001:db8::1' ) ) . toBe ( false ) ;
211
+ expect ( net_utils . is_private ( '172.32.0.1' ) ) . toBe ( false ) ;
212
+ expect ( net_utils . is_private ( '172.15.0.1' ) ) . toBe ( false ) ;
213
+ } ) ;
214
+
215
+ // IPv4 with CIDR
216
+ it ( 'should correctly handle IPv4 addresses with CIDR' , ( ) => {
217
+ expect ( net_utils . is_private ( '10.1.2.3/24' ) ) . toBe ( true ) ;
218
+ expect ( net_utils . is_private ( '8.8.8.8/32' ) ) . toBe ( false ) ;
219
+ } ) ;
220
+
221
+ // IPv6 unspecified (::)
222
+ it ( 'should return true for ::' , ( ) => {
223
+ expect ( net_utils . is_private ( '::' ) ) . toBe ( true ) ;
224
+ } ) ;
225
+
226
+ // IPv6 loopback (::1)
227
+ it ( 'should return true for ::1' , ( ) => {
228
+ expect ( net_utils . is_private ( '::1' ) ) . toBe ( true ) ;
146
229
} ) ;
147
230
231
+ // IPv6 ULA fc00::/7
232
+ it ( 'should return true for fc00::/7' , ( ) => {
233
+ expect ( net_utils . is_private ( 'fc00::1' ) ) . toBe ( true ) ;
234
+ expect ( net_utils . is_private ( 'fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff' ) ) . toBe ( true ) ;
235
+ expect ( net_utils . is_private ( 'fe00::1' ) ) . toBe ( false ) ;
236
+ } ) ;
237
+
238
+ // IPv6 link-local fe80::/10
239
+ it ( 'should return true for fe80::/10' , ( ) => {
240
+ expect ( net_utils . is_private ( 'fe80::1' ) ) . toBe ( true ) ;
241
+ expect ( net_utils . is_private ( 'febf::1' ) ) . toBe ( true ) ;
242
+ expect ( net_utils . is_private ( 'fec0::1' ) ) . toBe ( false ) ;
243
+ } ) ;
244
+
245
+ // IPv4-mapped IPv6
246
+ it ( 'should correctly detect IPv4-mapped IPv6 addresses' , ( ) => {
247
+ expect ( net_utils . is_private ( '::ffff:10.0.0.1' ) ) . toBe ( true ) ;
248
+ expect ( net_utils . is_private ( '::ffff:8.8.8.8' ) ) . toBe ( false ) ;
249
+ expect ( net_utils . is_private ( '::ffff:192.168.1.1' ) ) . toBe ( true ) ;
250
+ } ) ;
251
+
252
+ // Invalid addresses
253
+ it ( 'should return false for invalid addresses' , ( ) => {
254
+ expect ( net_utils . is_private ( 'invalid' ) ) . toBe ( false ) ;
255
+ expect ( net_utils . is_private ( '300.300.300.300' ) ) . toBe ( false ) ;
256
+ expect ( net_utils . is_private ( '::gggg' ) ) . toBe ( false ) ;
257
+ } ) ;
148
258
149
259
it ( 'should return true for public addresses or false for private addresses' , ( ) => {
150
260
expect ( net_utils . is_public ( '10.0.0.1' ) ) . toBe ( false ) ;
@@ -155,4 +265,65 @@ describe('IP Utils', () => {
155
265
expect ( net_utils . is_public ( '2001:db8::1' ) ) . toBe ( true ) ;
156
266
} ) ;
157
267
268
+ it ( 'should return a 4-byte buffer for IPv4' , ( ) => {
269
+ const buf = net_utils . ip_to_buffer_safe ( '192.168.1.1' ) ;
270
+ expect ( buf ) . toBeInstanceOf ( Buffer ) ;
271
+ expect ( buf . length ) . toBe ( 4 ) ;
272
+ expect ( buf ) . toEqual ( Buffer . from ( [ 192 , 168 , 1 , 1 ] ) ) ;
273
+ } ) ;
274
+
275
+ it ( 'should return a 16-byte buffer for IPv6' , ( ) => {
276
+ const buf = net_utils . ip_to_buffer_safe ( '::1' ) ;
277
+ expect ( buf ) . toBeInstanceOf ( Buffer ) ;
278
+ expect ( buf . length ) . toBe ( 16 ) ;
279
+ // Loopback IPv6 is all zeros except last byte
280
+ expect ( buf [ 15 ] ) . toBe ( 1 ) ;
281
+ } ) ;
282
+
283
+ it ( 'should return null for invalid IP' , ( ) => {
284
+ expect ( net_utils . ip_to_buffer_safe ( 'invalid' ) ) . toBeNull ( ) ;
285
+ expect ( net_utils . ip_to_buffer_safe ( '300.300.300.300' ) ) . toBeNull ( ) ;
286
+ expect ( net_utils . ip_to_buffer_safe ( '::gggg' ) ) . toBeNull ( ) ;
287
+ } ) ;
288
+
289
+ // IPv4 equality
290
+ it ( 'should return true for identical IPv4 addresses' , ( ) => {
291
+ expect ( net_utils . is_equal ( '192.168.1.1' , '192.168.1.1' ) ) . toBe ( true ) ;
292
+ } ) ;
293
+
294
+ it ( 'should return false for different IPv4 addresses' , ( ) => {
295
+ expect ( net_utils . is_equal ( '192.168.1.1' , '192.168.1.2' ) ) . toBe ( false ) ;
296
+ } ) ;
297
+
298
+ // IPv6 equality
299
+ it ( 'should return true for identical IPv6 addresses' , ( ) => {
300
+ expect ( net_utils . is_equal ( '::1' , '::1' ) ) . toBe ( true ) ;
301
+ } ) ;
302
+
303
+ it ( 'should return false for different IPv6 addresses' , ( ) => {
304
+ expect ( net_utils . is_equal ( '::1' , '::2' ) ) . toBe ( false ) ;
305
+ } ) ;
306
+
307
+ // IPv4 vs IPv6-mapped IPv4
308
+ it ( 'should return true for IPv4 and its IPv6-mapped equivalent' , ( ) => {
309
+ expect ( net_utils . is_equal ( '127.0.0.1' , '::ffff:127.0.0.1' ) ) . toBe ( true ) ;
310
+ expect ( net_utils . is_equal ( '192.168.1.1' , '::ffff:192.168.1.1' ) ) . toBe ( true ) ;
311
+ } ) ;
312
+
313
+ it ( 'should return false for IPv4 and non-matching IPv6-mapped address' , ( ) => {
314
+ expect ( net_utils . is_equal ( '192.168.1.1' , '::ffff:192.168.1.2' ) ) . toBe ( false ) ;
315
+ } ) ;
316
+
317
+ // Invalid IPs
318
+ it ( 'should return false if either address is invalid' , ( ) => {
319
+ expect ( net_utils . is_equal ( 'invalid' , '192.168.1.1' ) ) . toBe ( false ) ;
320
+ expect ( net_utils . is_equal ( '192.168.1.1' , 'invalid' ) ) . toBe ( false ) ;
321
+ expect ( net_utils . is_equal ( 'invalid' , 'also.invalid' ) ) . toBe ( false ) ;
322
+ } ) ;
323
+
324
+ // Mixed IPv4 and IPv6
325
+ it ( 'should return false for IPv4 and unrelated IPv6' , ( ) => {
326
+ expect ( net_utils . is_equal ( '192.168.1.1' , '::1' ) ) . toBe ( false ) ;
327
+ } ) ;
328
+
158
329
} ) ;
0 commit comments