[CFR] correct type of addrinfo.ai_addrlen and netent.n_net

Hajimu UMEMOTO ume at FreeBSD.ORG
Mon May 9 08:55:20 PDT 2005


Hi,

>>>>> On Tue, 3 May 2005 18:44:09 -0400
>>>>> David Schultz <das at FreeBSD.ORG> said:

das> - You should use socklen_t instead of uint32_t, as appropriate.

Are you mean netent.n_net?  If so, it is because of POSIX.

das> - It's probably better to use the machine/endian.h macros to test
das>   endianness instead of hard-coding every architecture.

Yes.  How about this patch?

--- include/netdb.h.orig	Thu Apr 28 04:12:56 2005
+++ include/netdb.h	Mon May  9 15:45:55 2005
@@ -63,6 +63,8 @@
 
 #include <sys/cdefs.h>
 #include <sys/_types.h>
+#include <machine/_limits.h>
+#include <machine/endian.h>
 
 #ifndef _SIZE_T_DECLARED
 typedef	__size_t	size_t;
@@ -74,6 +76,11 @@
 #define	_SOCKLEN_T_DECLARED
 #endif
 
+#ifndef _UINT32_T_DECLARED
+typedef	__uint32_t	uint32_t;
+#define	_UINT32_T_DECLARED
+#endif
+
 #ifndef _PATH_HEQUIV
 # define	_PATH_HEQUIV	"/etc/hosts.equiv"
 #endif
@@ -99,14 +106,27 @@
 };
 
 /*
- * Assumption here is that a network number
- * fits in an unsigned long -- probably a poor one.
+ * Note: n_net used to be an unsigned long integer.
+ * In XNS5, and subsequently in POSIX-2001 it was changed to an
+ * uint32_t.
+ * To accomodate for this while preserving binary compatibility with
+ * the old interface, we prepend or append 32 bits of padding,
+ * depending on the (LP64) architecture's endianness.
+ *
+ * This should be deleted the next time the libc major number is
+ * incremented.
  */
 struct netent {
 	char		*n_name;	/* official name of net */
 	char		**n_aliases;	/* alias list */
 	int		n_addrtype;	/* net address type */
-	unsigned long	n_net;		/* network # */
+#if __LONG_BIT == 64 && _BYTE_ORDER == _BIG_ENDIAN
+	uint32_t	__n_pad0;	/* ABI compatibility */
+#endif
+	uint32_t	n_net;		/* network # */
+#if __LONG_BIT == 64 && _BYTE_ORDER == _LITTLE_ENDIAN
+	uint32_t	__n_pad0;	/* ABI compatibility */
+#endif
 };
 
 struct servent {
@@ -122,12 +142,29 @@
 	int	p_proto;	/* protocol # */
 };
 
+/*
+ * Note: ai_addrlen used to be a size_t, per RFC 2553.
+ * In XNS5.2, and subsequently in POSIX-2001 and RFC 3493 it was
+ * changed to a socklen_t.
+ * To accomodate for this while preserving binary compatibility with the
+ * old interface, we prepend or append 32 bits of padding, depending on
+ * the (LP64) architecture's endianness.
+ *
+ * This should be deleted the next time the libc major number is
+ * incremented.
+ */
 struct addrinfo {
 	int	ai_flags;	/* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
 	int	ai_family;	/* PF_xxx */
 	int	ai_socktype;	/* SOCK_xxx */
 	int	ai_protocol;	/* 0 or IPPROTO_xxx for IPv4 and IPv6 */
-	size_t	ai_addrlen;	/* length of ai_addr */
+#if __LONG_BIT == 64 && _BYTE_ORDER == _BIG_ENDIAN
+	uint32_t __ai_pad0;	/* ABI compatibility */
+#endif
+	socklen_t ai_addrlen;	/* length of ai_addr */
+#if __LONG_BIT == 64 && _BYTE_ORDER == _LITTLE_ENDIAN
+	uint32_t __ai_pad0;	/* ABI compatibility */
+#endif
 	char	*ai_canonname;	/* canonical name for hostname */
 	struct	sockaddr *ai_addr;	/* binary address */
 	struct	addrinfo *ai_next;	/* next structure in linked list */
@@ -225,7 +262,7 @@
 struct hostent	*gethostent(void);
 struct hostent	*getipnodebyaddr(const void *, size_t, int, int *);
 struct hostent	*getipnodebyname(const char *, int, int, int *);
-struct netent	*getnetbyaddr(unsigned long, int);
+struct netent	*getnetbyaddr(uint32_t, int);
 struct netent	*getnetbyname(const char *);
 struct netent	*getnetent(void);
 int		getnetgrent(char **, char **, char **);


das> -#if 1 /* obsolete */
das> +#if __BSD_VISIBLE /* obsolete */
das>  #define NI_WITHSCOPEID	0x00000020
das>  #endif

It reminds me one more issue.  I wish to nuke NI_WITHSCOPEID before
6.0-RELEASE.  NetBSD and OpenBSD did so already.

das> +int		getaddrinfo(const char * __restrict, const char * __restrict,
das> +			    const struct addrinfo * __restrict,
das> +			    struct addrinfo ** __restrict);
das> +int		getnameinfo(const struct sockaddr * __restrict, socklen_t,
das> +			    char * __restrict, __size_t, char * __restrict,
das> +			    __size_t, int);

The 4th and 6th arguments are buffer length for return value, and they
are size_t in spec.  So, they should not be mixuped with others.

das> -struct hostent	*getipnodebyaddr(const void *, size_t, int, int *);
das> +struct hostent	*getipnodebyaddr(const void *, __size_t, int, int *);

It is thorny issue.  I think it is a bug, and it should be int.
However, getipnodebyaddr() was defined in RFC 2553, then was
deprecated in RFC 3493.  So, I think it will never be revised.

Sincerely,

--
Hajimu UMEMOTO @ Internet Mutual Aid Society Yokohama, Japan
ume at mahoroba.org  ume@{,jp.}FreeBSD.org
http://www.imasy.org/~ume/


More information about the freebsd-arch mailing list