8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.19 2003/08/04 02:39:59 momjian Exp $
11
+ * $Header: /cvsroot/pgsql/src/backend/libpq/ip.c,v 1.20 2003/09/05 20:31:36 tgl Exp $
12
12
*
13
13
* This file and the IPV6 implementation were initially provided by
14
14
* Nigel Kukard <nkukard@lbsd.net>, Linux Based Systems Design
34
34
#endif
35
35
#include <arpa/inet.h>
36
36
#include <sys/file.h>
37
- #endif
37
+
38
+ #endif /* !defined(_MSC_VER) && !defined(__BORLANDC__) */
38
39
39
40
#include "libpq/ip.h"
40
41
@@ -265,9 +266,16 @@ getnameinfo_unix(const struct sockaddr_un * sa, int salen,
265
266
266
267
return 0 ;
267
268
}
269
+
268
270
#endif /* HAVE_UNIX_SOCKETS */
269
271
270
272
273
+ /*
274
+ * rangeSockAddr - is addr within the subnet specified by netaddr/netmask ?
275
+ *
276
+ * Note: caller must already have verified that all three addresses are
277
+ * in the same address family; and AF_UNIX addresses are not supported.
278
+ */
271
279
int
272
280
rangeSockAddr (const struct sockaddr_storage * addr ,
273
281
const struct sockaddr_storage * netaddr ,
@@ -287,6 +295,39 @@ rangeSockAddr(const struct sockaddr_storage * addr,
287
295
return 0 ;
288
296
}
289
297
298
+ static int
299
+ rangeSockAddrAF_INET (const struct sockaddr_in * addr ,
300
+ const struct sockaddr_in * netaddr ,
301
+ const struct sockaddr_in * netmask )
302
+ {
303
+ if (((addr - > sin_addr .s_addr ^ netaddr - > sin_addr .s_addr ) &
304
+ netmask - > sin_addr .s_addr ) == 0 )
305
+ return 1 ;
306
+ else
307
+ return 0 ;
308
+ }
309
+
310
+
311
+ #ifdef HAVE_IPV6
312
+ static int
313
+ rangeSockAddrAF_INET6 (const struct sockaddr_in6 * addr ,
314
+ const struct sockaddr_in6 * netaddr ,
315
+ const struct sockaddr_in6 * netmask )
316
+ {
317
+ int i ;
318
+
319
+ for (i = 0 ; i < 16 ; i + + )
320
+ {
321
+ if (((addr - > sin6_addr .s6_addr [i ] ^ netaddr - > sin6_addr .s6_addr [i ]) &
322
+ netmask - > sin6_addr .s6_addr [i ]) != 0 )
323
+ return 0 ;
324
+ }
325
+
326
+ return 1 ;
327
+ }
328
+
329
+ #endif
330
+
290
331
/*
291
332
* SockAddr_cidr_mask - make a network mask of the appropriate family
292
333
* and required number of significant bits
@@ -358,34 +399,74 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family)
358
399
return 0 ;
359
400
}
360
401
361
- static int
362
- rangeSockAddrAF_INET (const struct sockaddr_in * addr , const struct sockaddr_in * netaddr ,
363
- const struct sockaddr_in * netmask )
402
+
403
+ #ifdef HAVE_IPV6
404
+
405
+ /*
406
+ * promote_v4_to_v6_addr --- convert an AF_INET addr to AF_INET6, using
407
+ * the standard convention for IPv4 addresses mapped into IPv6 world
408
+ *
409
+ * The passed addr is modified in place. Note that we only worry about
410
+ * setting the fields that rangeSockAddr will look at.
411
+ */
412
+ void
413
+ promote_v4_to_v6_addr (struct sockaddr_storage * addr )
364
414
{
365
- if (((addr - > sin_addr .s_addr ^ netaddr - > sin_addr .s_addr ) &
366
- netmask - > sin_addr .s_addr ) == 0 )
367
- return 1 ;
368
- else
369
- return 0 ;
370
- }
415
+ struct sockaddr_in addr4 ;
416
+ struct sockaddr_in6 addr6 ;
417
+ uint32 s_addr ;
371
418
419
+ memcpy (& addr4 , addr , sizeof (addr4 ));
420
+ s_addr = ntohl (addr4 .sin_addr .s_addr );
372
421
373
- #ifdef HAVE_IPV6
374
- static int
375
- rangeSockAddrAF_INET6 (const struct sockaddr_in6 * addr ,
376
- const struct sockaddr_in6 * netaddr ,
377
- const struct sockaddr_in6 * netmask )
422
+ memset (& addr6 , 0 , sizeof (addr6 ));
423
+
424
+ addr6 .sin6_family = AF_INET6 ;
425
+
426
+ addr6 .sin6_addr .s6_addr [10 ] = 0xff ;
427
+ addr6 .sin6_addr .s6_addr [11 ] = 0xff ;
428
+ addr6 .sin6_addr .s6_addr [12 ] = (s_addr >> 24 ) & 0xFF ;
429
+ addr6 .sin6_addr .s6_addr [13 ] = (s_addr >> 16 ) & 0xFF ;
430
+ addr6 .sin6_addr .s6_addr [14 ] = (s_addr >> 8 ) & 0xFF ;
431
+ addr6 .sin6_addr .s6_addr [15 ] = (s_addr ) & 0xFF ;
432
+
433
+ memcpy (addr , & addr6 , sizeof (addr6 ));
434
+ }
435
+
436
+ /*
437
+ * promote_v4_to_v6_mask --- convert an AF_INET netmask to AF_INET6, using
438
+ * the standard convention for IPv4 addresses mapped into IPv6 world
439
+ *
440
+ * This must be different from promote_v4_to_v6_addr because we want to
441
+ * set the high-order bits to 1's not 0's.
442
+ *
443
+ * The passed addr is modified in place. Note that we only worry about
444
+ * setting the fields that rangeSockAddr will look at.
445
+ */
446
+ void
447
+ promote_v4_to_v6_mask (struct sockaddr_storage * addr )
378
448
{
449
+ struct sockaddr_in addr4 ;
450
+ struct sockaddr_in6 addr6 ;
451
+ uint32 s_addr ;
379
452
int i ;
380
453
381
- for (i = 0 ; i < 16 ; i + + )
382
- {
383
- if (((addr - > sin6_addr .s6_addr [i ] ^ netaddr - > sin6_addr .s6_addr [i ]) &
384
- netmask - > sin6_addr .s6_addr [i ]) != 0 )
385
- return 0 ;
386
- }
454
+ memcpy (& addr4 , addr , sizeof (addr4 ));
455
+ s_addr = ntohl (addr4 .sin_addr .s_addr );
387
456
388
- return 1 ;
457
+ memset (& addr6 , 0 , sizeof (addr6 ));
458
+
459
+ addr6 .sin6_family = AF_INET6 ;
460
+
461
+ for (i = 0 ; i < 12 ; i + + )
462
+ addr6 .sin6_addr .s6_addr [i ] = 0xff ;
463
+
464
+ addr6 .sin6_addr .s6_addr [12 ] = (s_addr >> 24 ) & 0xFF ;
465
+ addr6 .sin6_addr .s6_addr [13 ] = (s_addr >> 16 ) & 0xFF ;
466
+ addr6 .sin6_addr .s6_addr [14 ] = (s_addr >> 8 ) & 0xFF ;
467
+ addr6 .sin6_addr .s6_addr [15 ] = (s_addr ) & 0xFF ;
468
+
469
+ memcpy (addr , & addr6 , sizeof (addr6 ));
389
470
}
390
471
391
- #endif
472
+ #endif /* HAVE_IPV6 */
0 commit comments