From owner-svn-src-head@FreeBSD.ORG Wed Nov 5 12:13:11 2008 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 296661065675; Wed, 5 Nov 2008 12:13:11 +0000 (UTC) (envelope-from des@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 17EF98FC1B; Wed, 5 Nov 2008 12:13:11 +0000 (UTC) (envelope-from des@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id mA5CDAJ8026522; Wed, 5 Nov 2008 12:13:10 GMT (envelope-from des@svn.freebsd.org) Received: (from des@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mA5CDA36026521; Wed, 5 Nov 2008 12:13:10 GMT (envelope-from des@svn.freebsd.org) Message-Id: <200811051213.mA5CDA36026521@svn.freebsd.org> From: Dag-Erling Smorgrav Date: Wed, 5 Nov 2008 12:13:10 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r184683 - head/lib/libutil X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 Nov 2008 12:13:11 -0000 Author: des Date: Wed Nov 5 12:13:10 2008 New Revision: 184683 URL: http://svn.freebsd.org/changeset/base/184683 Log: Like many other functions that handle sockaddrs, realhostname_sa() takes a struct sockaddr * that it casts internally to the appropriate type based on sa_family. However, struct sockaddr has very lax alignment requirements, which causes the compiler to complain when you cast a struct sockaddr * to, say, a struct sockaddr_in6 *. I find it reasonable to assume that the pointer we received is in fact correctly aligned. Therefore, we can work around the compiler warnings by casting to void * before casting to the desired type. For readability's sake, this is done with macros. The same technique should prove useful in other parts of the tree that deal with socket addresses. MFC after: 3 weeks Modified: head/lib/libutil/realhostname.c Modified: head/lib/libutil/realhostname.c ============================================================================== --- head/lib/libutil/realhostname.c Wed Nov 5 12:02:25 2008 (r184682) +++ head/lib/libutil/realhostname.c Wed Nov 5 12:13:10 2008 (r184683) @@ -83,6 +83,18 @@ realhostname(char *host, size_t hsize, c return result; } +/* + * struct sockaddr has very lax alignment requirements, since all its + * members are char or equivalent. This is a problem when trying to + * dereference a struct sockaddr_in6 * that was passed in as a struct + * sockaddr *. Although we know (or trust) that the passed-in struct was + * properly aligned, the compiler doesn't, and (rightly) complains. These + * macros perform the cast in a way that the compiler will accept. + */ +#define SOCKADDR_IN6(p) ((struct sockaddr_in6 *)(void *)(p)) +#define SOCKADDR_IN(p) ((struct sockaddr_in *)(void *)(p)) +#define SOCKINET(p) ((struct sockinet *)(void *)(p)) + int realhostname_sa(char *host, size_t hsize, struct sockaddr *addr, int addrlen) { @@ -96,10 +108,10 @@ realhostname_sa(char *host, size_t hsize /* IPv4 mapped IPv6 addr consideraton, specified in rfc2373. */ if (addr->sa_family == AF_INET6 && addrlen == sizeof(struct sockaddr_in6) && - IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)addr)->sin6_addr)) { + IN6_IS_ADDR_V4MAPPED(&SOCKADDR_IN6(addr)->sin6_addr)) { struct sockaddr_in6 *sin6; - sin6 = (struct sockaddr_in6 *)addr; + sin6 = SOCKADDR_IN6(addr); memset(&lsin, 0, sizeof(lsin)); lsin.sin_len = sizeof(struct sockaddr_in); @@ -142,15 +154,16 @@ realhostname_sa(char *host, size_t hsize } if (sa->sa_len == addrlen && sa->sa_family == addr->sa_family) { - ((struct sockinet *)sa)->si_port = ((struct sockinet *)addr)->si_port; + SOCKINET(sa)->si_port = SOCKINET(addr)->si_port; #ifdef INET6 /* * XXX: sin6_socpe_id may not been * filled by DNS */ if (sa->sa_family == AF_INET6 && - ((struct sockaddr_in6 *)sa)->sin6_scope_id == 0) - ((struct sockaddr_in6 *)sa)->sin6_scope_id = ((struct sockaddr_in6 *)addr)->sin6_scope_id; + SOCKADDR_IN6(sa)->sin6_scope_id == 0) + SOCKADDR_IN6(sa)->sin6_scope_id = + SOCKADDR_IN6(addr)->sin6_scope_id; #endif if (!memcmp(sa, addr, sa->sa_len)) { result = HOSTNAME_FOUND;