From: Aidan Van Dyk Date: Sat, 23 May 2009 12:22:02 +0000 (+0000) Subject: Socket fixes for BSD 4.4 sockets X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a05ab07fa537df9b3223f207d6a677ee0604b9e4;p=thirdparty%2FHylaFAX.git Socket fixes for BSD 4.4 sockets Giovanni Bechis reported things not working on OpenBSD, which uses the BSD 4.4 sockaddr struct which doesn't have sa_family as the first member. So we can't rely on a family being the first member of our union either. (cherry picked from commit 9695174b15fa8839ec7203c4c6def1a1b87e5f5d) --- diff --git a/hfaxd/InetFaxServer.c++ b/hfaxd/InetFaxServer.c++ index 1a263549..8ae87d40 100644 --- a/hfaxd/InetFaxServer.c++ +++ b/hfaxd/InetFaxServer.c++ @@ -87,11 +87,11 @@ InetSuperServer::startServer(void) * Somethings broken here, let's pick some conservative defaults */ memset(&addr, 0, sizeof(addr)); - addr.family = AF_INET; + Socket::family(addr) = AF_INET; addr.in.sin_port = htons(FAX_DEFPORT); } - int s = socket(addr.family, SOCK_STREAM, 0); + int s = socket(Socket::family(addr), SOCK_STREAM, 0); if (s >= 0) { int on = 1; if (Socket::setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) >= 0) { @@ -119,7 +119,7 @@ InetFaxServer::InetFaxServer() swaitint = 5; // interval between retries memset(&data_dest, 0, sizeof (data_dest)); - data_dest.family = AF_INET6; // We'll allow AF_INET6 by default. + Socket::family(data_dest) = AF_INET6; // We'll allow AF_INET6 by default. hostent* hp = Socket::gethostbyname(hostname); @@ -211,7 +211,7 @@ logDebug("checkHostIdentity(\"%s\")", name); if (getaddrinfo(name, NULL, &hints, &ai) == 0) { for (struct addrinfo *aip = ai; aip != NULL; aip = aip->ai_next) { Socket::Address *addr = (Socket::Address*)aip->ai_addr; - if (aip->ai_family != peer_addr.family) + if (aip->ai_family != Socket::family(peer_addr)) continue; if ( (aip->ai_family == AF_INET6 && memcmp(&addr->in6.sin6_addr, &peer_addr.in6.sin6_addr, sizeof(struct in6_addr)) ==0) @@ -287,7 +287,7 @@ InetFaxServer::setupNetwork(int fd) char hostbuf[128]; - remoteaddr = inet_ntop(peer_addr.family, Socket::addr(peer_addr), hostbuf, sizeof(hostbuf)); + remoteaddr = inet_ntop(Socket::family(peer_addr), Socket::addr(peer_addr), hostbuf, sizeof(hostbuf)); getnameinfo((struct sockaddr*)&peer_addr, Socket::socklen(peer_addr), hostbuf, sizeof(hostbuf), NULL, 0, 0); @@ -378,8 +378,8 @@ InetFaxServer::passiveCmd(void) { if (tokenBody[0] == 'E') { pasv_addr = ctrl_addr; - logDebug("Extended passive requested for family %d", pasv_addr.family); - pdata = socket(pasv_addr.family, SOCK_STREAM, 0); + logDebug("Extended passive requested for family %d", Socket::family(pasv_addr)); + pdata = socket(Socket::family(pasv_addr), SOCK_STREAM, 0); if (pdata >= 0) { Socket::port(pasv_addr) = 0; if (!setupPassiveDataSocket(pdata, pasv_addr)) @@ -392,7 +392,7 @@ InetFaxServer::passiveCmd(void) perror_reply(425, "Cannot setup extended passive connection", errno); return; } - if (ctrl_addr.family != AF_INET) { + if (Socket::family(ctrl_addr) != AF_INET) { reply(500, "Cannot use PASV with IPv6 connections"); return; } @@ -444,7 +444,7 @@ InetFaxServer::getDataSocket(const char* mode) { if (data >= 0) return (fdopen(data, mode)); - int s = socket(data_dest.family, SOCK_STREAM, 0); + int s = socket(Socket::family(data_dest), SOCK_STREAM, 0); if (s < 0) goto bad; { int on = 1; diff --git a/hfaxd/SuperServer.c++ b/hfaxd/SuperServer.c++ index ef0a9364..983fdbc5 100644 --- a/hfaxd/SuperServer.c++ +++ b/hfaxd/SuperServer.c++ @@ -68,7 +68,7 @@ SuperServer::inputReady(int fd) _exit(-1); } #ifdef IPV6_ADDRFORM - if (addr.family == AF_INET6) { + if (Socket::family(addr) == AF_INET6) { struct in6_addr& a = addr.in6.sin6_addr; if ( (a.s6_addr32[0] == 0 && a.s6_addr32[1] == 0 && a.s6_addr32[2] == htonl(0xFFFF)) || (a.s6_addr32[0] == 0 && a.s6_addr32[1] == 0 && a.s6_addr32[2] == 0 && ntohl(a.s6_addr32[3]) > 1) ) { diff --git a/libhylafax/InetTransport.c++ b/libhylafax/InetTransport.c++ index 445a02ba..8adab065 100644 --- a/libhylafax/InetTransport.c++ +++ b/libhylafax/InetTransport.c++ @@ -120,11 +120,11 @@ InetTransport::callServer(fxStr& emsg) { Socket::Address *addr = (Socket::Address*)aip->ai_addr; char buf[256]; // For inet_ntop use - fxAssert(aip->ai_family == addr->family, "addrinfo ai_family doesn't match in_addr->ai_info"); + fxAssert(aip->ai_family == Socket::family(*addr), "addrinfo ai_family doesn't match in_addr->ai_info"); if (client.getVerbose()) client.traceServer(NLS::TEXT("Trying %s [%d] (%s) at port %u..."), - (const char*)client.getHost(), addr->family, - inet_ntop(addr->family, Socket::addr(*addr), buf, sizeof(buf)), + (const char*)client.getHost(), Socket::family(*addr), + inet_ntop(Socket::family(*addr), Socket::addr(*addr), buf, sizeof(buf)), ntohs(Socket::port(*addr))); int fd = socket (aip->ai_family, aip->ai_socktype, aip->ai_protocol); if (fd != -1 && ( connect(fd, aip->ai_addr, aip->ai_addrlen) == 0)) @@ -282,7 +282,7 @@ InetTransport::initDataConnV6(fxStr& emsg) client.printWarning(NLS::TEXT("Couldn't parse last response \"%s\""), (const char*)client.getLastResponse()); return(false); } - } else if (err == FaxClient::ERROR && data_addr.family == AF_INET) { + } else if (err == FaxClient::ERROR && Socket::family(data_addr) == AF_INET) { client.printWarning(NLS::TEXT("EPSV not supported, trying PASV since we're AF_INET\n")); if (client.command("PASV") != FaxClient::COMPLETE) @@ -311,7 +311,7 @@ InetTransport::initDataConnV6(fxStr& emsg) Socket::port(data_addr) = 0; // let system allocate port } - int fd = socket(data_addr.family, SOCK_STREAM, IPPROTO_TCP); + int fd = socket(Socket::family(data_addr), SOCK_STREAM, IPPROTO_TCP); if (fd < 0) { emsg = fxStr::format("socket: %s", strerror(errno)); return (false); @@ -320,10 +320,10 @@ InetTransport::initDataConnV6(fxStr& emsg) if (Socket::connect(fd, &data_addr.in, Socket::socklen(data_addr)) >= 0) { if (client.getVerbose()) client.traceServer("Connected to %s at port %u.", - inet_ntop(data_addr.family, Socket::addr(data_addr), buf, sizeof(buf)), ntohs(Socket::port(data_addr))); + inet_ntop(Socket::family(data_addr), Socket::addr(data_addr), buf, sizeof(buf)), ntohs(Socket::port(data_addr))); } else { emsg = fxStr::format("Can not reach server at %s at port %u (%s).", - inet_ntop(data_addr.family, Socket::addr(data_addr), buf, sizeof(buf)), ntohs(Socket::port(data_addr)), strerror(errno)); + inet_ntop(Socket::family(data_addr), Socket::addr(data_addr), buf, sizeof(buf)), ntohs(Socket::port(data_addr)), strerror(errno)); goto bad; } } else { @@ -348,9 +348,9 @@ InetTransport::initDataConnV6(fxStr& emsg) hostbuf, sizeof(hostbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV); int err = client.command("EPRT |%d|%s|%s|", - (data_addr.family == AF_INET6 ? 2 : 1), + (Socket::family(data_addr) == AF_INET6 ? 2 : 1), hostbuf, portbuf); - if (err == FaxClient::ERROR && data_addr.family == AF_INET) + if (err == FaxClient::ERROR && Socket::family(data_addr) == AF_INET) { if (client.getVerbose()) client.printWarning(NLS::TEXT("EPRT not supported, trying PORT")); diff --git a/libhylafax/Socket.h b/libhylafax/Socket.h index 3d6b8bea..f3baf72f 100644 --- a/libhylafax/Socket.h +++ b/libhylafax/Socket.h @@ -68,7 +68,7 @@ public: union Address { - sa_family_t family; + struct sockaddr s; struct sockaddr_in in; struct sockaddr_in6 in6; struct sockaddr_un un; @@ -79,6 +79,8 @@ public: static socklen_t socklen(const Address& a); static size_t addrlen(const Address& a); + + static sa_family_t& family(Address& a); static in_port_t& port(Address& a); static void* addr (Address& a); }; @@ -132,7 +134,7 @@ inline struct hostent* Socket::gethostbyname(const char* name) inline socklen_t Socket::socklen (const Address& a) { - switch (a.family) + switch (a.s.sa_family) { case AF_INET: return sizeof(a.in); @@ -146,7 +148,7 @@ inline socklen_t Socket::socklen (const Address& a) inline size_t Socket::addrlen (const Address& a) { - switch (a.family) + switch (a.s.sa_family) { case AF_INET: return sizeof(a.in.sin_addr); @@ -156,9 +158,14 @@ inline size_t Socket::addrlen (const Address& a) fxAssert(true, "Socket::addrlen on invalid Address"); return 0; // DEAD CODE } +inline sa_family_t& Socket::family (Address& a) +{ + return a.s.sa_family; +} + inline in_port_t& Socket::port (Address& a) { - switch (a.family) + switch (a.s.sa_family) { case AF_INET: return a.in.sin_port; @@ -171,7 +178,7 @@ inline in_port_t& Socket::port (Address& a) inline void* Socket::addr (Address& a) { - switch (a.family) + switch (a.s.sa_family) { case AF_INET: return (void*) &a.in.sin_addr;