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

David Schultz das at FreeBSD.ORG
Tue May 3 15:47:26 PDT 2005


On Wed, May 04, 2005, Hajimu UMEMOTO wrote:
> Hi,
> 
> The ai_addrlen of a struct addrinfo 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.
> And, the n_net of a struct netent used to be an unsigned long integer.
> In XNS5, and subsequently in POSIX-2001, it was changed to an
> uint32_t.
> 
> I made a patch to correct these:
> 
>     http://www.imasy.or.jp/~ume/FreeBSD/netdb.h-padding.diff
> 
> To accomodate for this while preserving ABI compatibility with the old
> interface, we need to prepend or append 32 bits of padding, depending
> on the (LP64) architecture's endianness.  I wish to delete these
> padding before 6.0-RELEASE.
> 
> Please review it.

I have a subset of this (along with some other changes for POSIX)
in my tree---see the patch below.  My patch only includes the part
that can be done without breaking the ABI.  (Actually, doesn't
your patch *fix* the ABI with respect to FreeBSD 4.X?  It just
breaks it w.r.t. 5.X, I think.)

Assuming that people are willing to accept the ABI breakage (and
I'm not sure this is true), the patch looks reasonable.  I have
two minor comments:

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

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

Index: netdb.h
===================================================================
RCS file: /cvs/src/include/netdb.h,v
retrieving revision 1.34
diff -u -r1.34 netdb.h
--- netdb.h	14 Feb 2005 11:33:11 -0000	1.34
+++ netdb.h	21 Mar 2005 00:57:54 -0000
@@ -63,17 +63,19 @@
 
 #include <sys/cdefs.h>
 #include <sys/_types.h>
-
-#ifndef _SIZE_T_DECLARED
-typedef	__size_t	size_t;
-#define	_SIZE_T_DECLARED
-#endif
+#include <machine/_limits.h>
+#include <machine/endian.h>
 
 #ifndef _SOCKLEN_T_DECLARED
 typedef	__socklen_t	socklen_t;
 #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
@@ -100,13 +102,19 @@
 
 /*
  * Assumption here is that a network number
- * fits in an unsigned long -- probably a poor one.
+ * fits in 32 bits -- probably a poor one, but required by POSIX.
  */
 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	__unused;	/* ABI compat */
+#endif
+	uint32_t	n_net;		/* network # */
+#if __LONG_BIT == 64 && _BYTE_ORDER == _LITTLE_ENDIAN
+	uint32_t	__unused;	/* ABI compat */
+#endif
 };
 
 struct servent {
@@ -127,24 +135,32 @@
 	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 */
+	/* XXX ai_addrlen should have type socklen_t */
+	__size_t ai_addrlen;	/* length of ai_addr */
 	char	*ai_canonname;	/* canonical name for hostname */
 	struct	sockaddr *ai_addr;	/* binary address */
 	struct	addrinfo *ai_next;	/* next structure in linked list */
 };
 
+/* Highest reserved port number.  Keep in sync with netinet/in.h. */
+#define	IPPORT_RESERVED	1024
+
 /*
  * Error return codes from gethostbyname() and gethostbyaddr()
  * (left in h_errno).
  */
 
+#if __BSD_VISIBLE
 #define	NETDB_INTERNAL	-1	/* see errno */
 #define	NETDB_SUCCESS	0	/* no problem */
+#endif
 #define	HOST_NOT_FOUND	1 /* Authoritative Answer Host not found */
 #define	TRY_AGAIN	2 /* Non-Authoritative Host not found, or SERVERFAIL */
 #define	NO_RECOVERY	3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
 #define	NO_DATA		4 /* Valid name, no data record of requested type */
+#if __BSD_VISIBLE
 #define	NO_ADDRESS	NO_DATA		/* no address, look for MX record */
+#endif
 
 /*
  * Error return codes from getaddrinfo()
@@ -166,9 +182,14 @@
 #define	EAI_SERVICE	 9	/* servname not supported for ai_socktype */
 #define	EAI_SOCKTYPE	10	/* ai_socktype not supported */
 #define	EAI_SYSTEM	11	/* system error returned in errno */
+#if __BSD_VISIBLE
 #define	EAI_BADHINTS	12
 #define	EAI_PROTOCOL	13
-#define	EAI_MAX		14
+#endif
+#define	EAI_OVERFLOW	14	/* argument buffer overflowed */
+#if __BSD_VISIBLE
+#define	EAI_MAX		15
+#endif
 
 /*
  * Flag values for getaddrinfo()
@@ -177,23 +198,33 @@
 #define	AI_CANONNAME	0x00000002 /* fill ai_canonname */
 #define	AI_NUMERICHOST	0x00000004 /* prevent host name resolution */
 #define	AI_NUMERICSERV	0x00000008 /* prevent service name resolution */
+
+#if __BSD_VISIBLE
 /* valid flags for addrinfo (not a standard def, apps should not use it) */
 #define AI_MASK \
     (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | \
     AI_ADDRCONFIG)
+#endif
 
 #define	AI_ALL		0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
+#if __BSD_VISIBLE
 #define	AI_V4MAPPED_CFG	0x00000200 /* accept IPv4-mapped if kernel supports */
+#endif
 #define	AI_ADDRCONFIG	0x00000400 /* only if any address is assigned */
 #define	AI_V4MAPPED	0x00000800 /* accept IPv4-mapped IPv6 address */
+
+#if __BSD_VISIBLE
 /* special recommended flags for getipnodebyname */
 #define	AI_DEFAULT	(AI_V4MAPPED_CFG | AI_ADDRCONFIG)
+#endif
 
+#if __BSD_VISIBLE
 /*
  * Constants for getnameinfo()
  */
 #define	NI_MAXHOST	1025
 #define	NI_MAXSERV	32
+#endif
 
 /*
  * Flag values for getnameinfo()
@@ -203,72 +234,81 @@
 #define	NI_NAMEREQD	0x00000004
 #define	NI_NUMERICSERV	0x00000008
 #define	NI_DGRAM	0x00000010
-#if 1 /* obsolete */
+#if __BSD_VISIBLE /* obsolete */
 #define NI_WITHSCOPEID	0x00000020
 #endif
 
+#if __BSD_VISIBLE
 /*
  * Scope delimit character
  */
 #define	SCOPE_DELIMITER	'%'
+#endif
 
 __BEGIN_DECLS
 void		endhostent(void);
 void		endnetent(void);
-void		endnetgrent(void);
 void		endprotoent(void);
 void		endservent(void);
-void		freehostent(struct hostent *);
-struct hostent	*gethostbyaddr(const char *, int, int);
+struct hostent	*gethostbyaddr(const void *, int, int);
 struct hostent	*gethostbyname(const char *);
-struct hostent	*gethostbyname2(const char *, int);
 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	*getnetbyname(const char *);
 struct netent	*getnetent(void);
-int		getnetgrent(char **, char **, char **);
 struct protoent	*getprotobyname(const char *);
 struct protoent	*getprotobynumber(int);
 struct protoent	*getprotoent(void);
 struct servent	*getservbyname(const char *, const char *);
 struct servent	*getservbyport(int, const char *);
 struct servent	*getservent(void);
-void		herror(const char *);
-__const char	*hstrerror(int);
-int		innetgr(const char *, const char *, const char *, const char *);
+
+/* XXX Should replace __size_t with socklen_t below */
 void		sethostent(int);
 /* void		sethostfile(const char *); */
 void		setnetent(int);
 void		setprotoent(int);
-int		getaddrinfo(const char *, const char *,
-			    const struct addrinfo *, struct addrinfo **);
-int		getnameinfo(const struct sockaddr *, socklen_t, char *,
-			    size_t, char *, size_t, int);
+int		getaddrinfo(const char * __restrict, const char * __restrict,
+			    const struct addrinfo * __restrict,
+			    struct addrinfo ** __restrict);
+int		getnameinfo(const struct sockaddr * __restrict, socklen_t,
+			    char * __restrict, __size_t, char * __restrict,
+			    __size_t, int);
 void		freeaddrinfo(struct addrinfo *);
 const char	*gai_strerror(int);
-void		setnetgrent(const char *);
 void		setservent(int);
 
+#if __BSD_VISIBLE
+void		endnetgrent(void);
+void		freehostent(struct hostent *);
+struct hostent	*gethostbyname2(const char *, int);
+struct hostent	*getipnodebyaddr(const void *, __size_t, int, int *);
+struct hostent	*getipnodebyname(const char *, int, int, int *);
+int		getnetgrent(char **, char **, char **);
+void		herror(const char *);
+__const char	*hstrerror(int);
+int		innetgr(const char *, const char *, const char *, const char *);
+void		setnetgrent(const char *);
+#endif
+
 /*
  * PRIVATE functions specific to the FreeBSD implementation
  */
 
 /* DO NOT USE THESE, THEY ARE SUBJECT TO CHANGE AND ARE NOT PORTABLE!!! */
 int	* __h_error(void);
-void	_sethosthtent(int);
-void	_endhosthtent(void);
-void	_sethostdnsent(int);
-void	_endhostdnsent(void);
-void	_setnethtent(int);
-void	_endnethtent(void);
-void	_setnetdnsent(int);
-void	_endnetdnsent(void);
-struct hostent * _gethostbynisname(const char *, int);
-struct hostent * _gethostbynisaddr(const char *, int, int);
-void _map_v4v6_address(const char *, char *);
-void _map_v4v6_hostent(struct hostent *, char **, char **);
+void	__sethosthtent(int);
+void	__endhosthtent(void);
+void	__sethostdnsent(int);
+void	__endhostdnsent(void);
+void	__setnethtent(int);
+void	__endnethtent(void);
+void	__setnetdnsent(int);
+void	__endnetdnsent(void);
+struct hostent * __gethostbynisname(const char *, int);
+struct hostent * __gethostbynisaddr(const char *, int, int);
+void __map_v4v6_address(const char *, char *);
+void __map_v4v6_hostent(struct hostent *, char **, char **);
 __END_DECLS
 
 #endif /* !_NETDB_H_ */


More information about the freebsd-arch mailing list