88 *
99 *
1010 * 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 $
1212 *
1313 * This file and the IPV6 implementation were initially provided by
1414 * Nigel Kukard <nkukard@lbsd.net>, Linux Based Systems Design
3434#endif
3535#include <arpa/inet.h>
3636#include <sys/file.h>
37- #endif
37+
38+ #endif /* !defined(_MSC_VER) && !defined(__BORLANDC__) */
3839
3940#include "libpq/ip.h"
4041
@@ -265,9 +266,16 @@ getnameinfo_unix(const struct sockaddr_un * sa, int salen,
265266
266267 return 0 ;
267268}
269+
268270#endif /* HAVE_UNIX_SOCKETS */
269271
270272
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+ */
271279int
272280rangeSockAddr (const struct sockaddr_storage * addr ,
273281 const struct sockaddr_storage * netaddr ,
@@ -287,6 +295,39 @@ rangeSockAddr(const struct sockaddr_storage * addr,
287295 return 0 ;
288296}
289297
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+
290331/*
291332 * SockAddr_cidr_mask - make a network mask of the appropriate family
292333 * and required number of significant bits
@@ -358,34 +399,74 @@ SockAddr_cidr_mask(struct sockaddr_storage ** mask, char *numbits, int family)
358399 return 0 ;
359400}
360401
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 )
364414{
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 ;
371418
419+ memcpy (& addr4 , addr , sizeof (addr4 ));
420+ s_addr = ntohl (addr4 .sin_addr .s_addr );
372421
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 )
378448{
449+ struct sockaddr_in addr4 ;
450+ struct sockaddr_in6 addr6 ;
451+ uint32 s_addr ;
379452 int i ;
380453
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 );
387456
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 ));
389470}
390471
391- #endif
472+ #endif /* HAVE_IPV6 */
0 commit comments