summaryrefslogtreecommitdiff
path: root/net/libfetch
diff options
context:
space:
mode:
authortnn <tnn@pkgsrc.org>2009-08-06 14:02:38 +0000
committertnn <tnn@pkgsrc.org>2009-08-06 14:02:38 +0000
commit5da5d5a9fccb24f3845cff24268ae1513e226923 (patch)
tree699732a42aa717db1a255558085bfcd4578bd1c4 /net/libfetch
parente207841ddfcdb0a86451aa1e82c0db77084ad6ca (diff)
downloadpkgsrc-5da5d5a9fccb24f3845cff24268ae1513e226923.tar.gz
Fix strict aliasing issue which GCC 4.4 complained about.
While we know that "struct sockaddr_storage" has been engineered to alias to all the sockaddr structs, the compiler does not know about this. Thus, code like this may be unsafe to use: struct sockaddr_storage ss; struct sockaddr_in *sin = &ss; sin->sin_port = 0; /* dereferencing here breaks ISO C aliasing rules */ A workaround is to wrap the struct in a union, e.g: union anonymous { struct sockaddr_storage ss; struct sockaddr_in sin; } u; u.sin.sin_port = 0; -- Approved by: joerg
Diffstat (limited to 'net/libfetch')
-rw-r--r--net/libfetch/files/ftp.c81
1 files changed, 40 insertions, 41 deletions
diff --git a/net/libfetch/files/ftp.c b/net/libfetch/files/ftp.c
index 0ad6aa69bfa..9c33d779ec0 100644
--- a/net/libfetch/files/ftp.c
+++ b/net/libfetch/files/ftp.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ftp.c,v 1.27 2009/02/22 19:11:48 joerg Exp $ */
+/* $NetBSD: ftp.c,v 1.28 2009/08/06 14:02:38 tnn Exp $ */
/*-
* Copyright (c) 1998-2004 Dag-Erling Coïdan Smørgrav
* Copyright (c) 2008, 2009 Joerg Sonnenberger <joerg@NetBSD.org>
@@ -620,9 +620,12 @@ static fetchIO *
ftp_transfer(conn_t *conn, const char *oper, const char *file, const char *op_arg,
int mode, off_t offset, const char *flags)
{
- struct sockaddr_storage sa;
- struct sockaddr_in6 *sin6;
- struct sockaddr_in *sin4;
+ union anonymous {
+ struct sockaddr_storage ss;
+ struct sockaddr sa;
+ struct sockaddr_in6 sin6;
+ struct sockaddr_in sin4;
+ } u;
const char *bindaddr;
const char *filename;
int filenamelen, type;
@@ -650,16 +653,16 @@ ftp_transfer(conn_t *conn, const char *oper, const char *file, const char *op_ar
goto ouch;
/* find our own address, bind, and listen */
- l = sizeof(sa);
- if (getsockname(conn->sd, (struct sockaddr *)&sa, &l) == -1)
+ l = sizeof(u.ss);
+ if (getsockname(conn->sd, &u.sa, &l) == -1)
goto sysouch;
- if (sa.ss_family == AF_INET6)
- unmappedaddr((struct sockaddr_in6 *)&sa, &l);
+ if (u.ss.ss_family == AF_INET6)
+ unmappedaddr(&u.sin6, &l);
retry_mode:
/* open data socket */
- if ((sd = socket(sa.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+ if ((sd = socket(u.ss.ss_family, SOCK_STREAM, IPPROTO_TCP)) == -1) {
fetch_syserr();
return (NULL);
}
@@ -673,7 +676,7 @@ retry_mode:
/* send PASV command */
if (verbose)
fetch_info("setting passive mode");
- switch (sa.ss_family) {
+ switch (u.ss.ss_family) {
case AF_INET:
if ((e = ftp_cmd(conn, "PASV")) != FTP_PASSIVE_MODE)
goto ouch;
@@ -746,28 +749,26 @@ retry_mode:
goto sysouch;
/* construct sockaddr for data socket */
- l = sizeof(sa);
- if (getpeername(conn->sd, (struct sockaddr *)&sa, &l) == -1)
+ l = sizeof(u.ss);
+ if (getpeername(conn->sd, &u.sa, &l) == -1)
goto sysouch;
- if (sa.ss_family == AF_INET6)
- unmappedaddr((struct sockaddr_in6 *)&sa, &l);
- switch (sa.ss_family) {
+ if (u.ss.ss_family == AF_INET6)
+ unmappedaddr(&u.sin6, &l);
+ switch (u.ss.ss_family) {
case AF_INET6:
- sin6 = (struct sockaddr_in6 *)&sa;
if (e == FTP_EPASSIVE_MODE)
- sin6->sin6_port = htons(port);
+ u.sin6.sin6_port = htons(port);
else {
- memcpy(&sin6->sin6_addr, addr + 2, 16);
- memcpy(&sin6->sin6_port, addr + 19, 2);
+ memcpy(&u.sin6.sin6_addr, addr + 2, 16);
+ memcpy(&u.sin6.sin6_port, addr + 19, 2);
}
break;
case AF_INET:
- sin4 = (struct sockaddr_in *)&sa;
if (e == FTP_EPASSIVE_MODE)
- sin4->sin_port = htons(port);
+ u.sin4.sin_port = htons(port);
else {
- memcpy(&sin4->sin_addr, addr, 4);
- memcpy(&sin4->sin_port, addr + 4, 2);
+ memcpy(&u.sin4.sin_addr, addr, 4);
+ memcpy(&u.sin4.sin_port, addr + 4, 2);
}
break;
default:
@@ -780,9 +781,9 @@ retry_mode:
fetch_info("opening data connection");
bindaddr = getenv("FETCH_BIND_ADDRESS");
if (bindaddr != NULL && *bindaddr != '\0' &&
- fetch_bind(sd, sa.ss_family, bindaddr) != 0)
+ fetch_bind(sd, u.ss.ss_family, bindaddr) != 0)
goto sysouch;
- if (connect(sd, (struct sockaddr *)&sa, l) == -1)
+ if (connect(sd, &u.sa, l) == -1)
goto sysouch;
/* make the server initiate the transfer */
@@ -806,9 +807,9 @@ retry_mode:
char *ap;
char hname[INET6_ADDRSTRLEN];
- switch (sa.ss_family) {
+ switch (u.ss.ss_family) {
case AF_INET6:
- ((struct sockaddr_in6 *)&sa)->sin6_port = 0;
+ u.sin6.sin6_port = 0;
#ifdef IPV6_PORTRANGE
arg = low ? IPV6_PORTRANGE_DEFAULT : IPV6_PORTRANGE_HIGH;
if (setsockopt(sd, IPPROTO_IPV6, IPV6_PORTRANGE,
@@ -817,7 +818,7 @@ retry_mode:
#endif
break;
case AF_INET:
- ((struct sockaddr_in *)&sa)->sin_port = 0;
+ u.sin4.sin_port = 0;
#ifdef IP_PORTRANGE
arg = low ? IP_PORTRANGE_DEFAULT : IP_PORTRANGE_HIGH;
if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE,
@@ -828,19 +829,18 @@ retry_mode:
}
if (verbose)
fetch_info("binding data socket");
- if (bind(sd, (struct sockaddr *)&sa, l) == -1)
+ if (bind(sd, &u.sa, l) == -1)
goto sysouch;
if (listen(sd, 1) == -1)
goto sysouch;
/* find what port we're on and tell the server */
- if (getsockname(sd, (struct sockaddr *)&sa, &l) == -1)
+ if (getsockname(sd, &u.sa, &l) == -1)
goto sysouch;
- switch (sa.ss_family) {
+ switch (u.ss.ss_family) {
case AF_INET:
- sin4 = (struct sockaddr_in *)&sa;
- a = ntohl(sin4->sin_addr.s_addr);
- p = ntohs(sin4->sin_port);
+ a = ntohl(u.sin4.sin_addr.s_addr);
+ p = ntohs(u.sin4.sin_port);
e = ftp_cmd(conn, "PORT %d,%d,%d,%d,%d,%d",
(a >> 24) & 0xff, (a >> 16) & 0xff,
(a >> 8) & 0xff, a & 0xff,
@@ -849,18 +849,17 @@ retry_mode:
case AF_INET6:
#define UC(b) (((int)b)&0xff)
e = -1;
- sin6 = (struct sockaddr_in6 *)&sa;
- sin6->sin6_scope_id = 0;
- if (getnameinfo((struct sockaddr *)&sa, l,
+ u.sin6.sin6_scope_id = 0;
+ if (getnameinfo(&u.sa, l,
hname, sizeof(hname),
NULL, 0, NI_NUMERICHOST) == 0) {
e = ftp_cmd(conn, "EPRT |%d|%s|%d|", 2, hname,
- htons(sin6->sin6_port));
+ htons(u.sin6.sin6_port));
if (e == -1)
goto ouch;
}
if (e != FTP_OK) {
- ap = (char *)&sin6->sin6_addr;
+ ap = (char *)&u.sin6.sin6_addr;
e = ftp_cmd(conn,
"LPRT %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
6, 16,
@@ -869,8 +868,8 @@ retry_mode:
UC(ap[8]), UC(ap[9]), UC(ap[10]), UC(ap[11]),
UC(ap[12]), UC(ap[13]), UC(ap[14]), UC(ap[15]),
2,
- (ntohs(sin6->sin6_port) >> 8) & 0xff,
- ntohs(sin6->sin6_port) & 0xff);
+ (ntohs(u.sin6.sin6_port) >> 8) & 0xff,
+ ntohs(u.sin6.sin6_port) & 0xff);
}
break;
default: