* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-/* @file
+/** @file
* @brief Implementation of OS-dependent operations.
* @version $Id$
*/
#include "config.h"
-#define _XOPEN_SOURCE 500 /**< make limits.h #define IOV_MAX */
+#define _XOPEN_SOURCE 600 /**< make limits.h #define IOV_MAX */
#define __EXTENSIONS__ 1 /**< make Solaris netinet/in.h know IPv6 */
#include "ircd_osdep.h"
#include "msgq.h"
+#include "ircd_log.h"
#include "res.h"
#include "s_bsd.h"
#include "sys.h"
* Solaris requires sys/time.h before struct rusage (indirectly) in
* netinet/in.h.
*/
-#include <assert.h>
+/* #include <assert.h> -- Now using assert in ircd_log.h */
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
/** Convert IRC socket address to native format.
* @param[out] v6 Native socket address.
* @param[in] irc IRC socket address.
- * @param[in] persist If non-zero, and \a irc is an IPv4 address,
- * create an AF_INET size address.
+ * @param[in] compat_fd If non-negative, an FD specifying address family.
* @return Length of address written to \a v6.
*/
-int sockaddr_from_irc(struct sockaddr_in6 *v6, const struct irc_sockaddr *irc, int persist)
+int sockaddr_from_irc(struct sockaddr_in6 *v6, const struct irc_sockaddr *irc, int compat_fd)
{
+ struct sockaddr_in6 sin6;
+ socklen_t slen;
+ int family;
+
+ assert(irc != 0);
+ slen = sizeof(sin6);
+ if ((0 <= compat_fd)
+ && (0 == getsockname(compat_fd, (struct sockaddr*)&sin6, &slen)))
+ family = sin6.sin6_family;
+ else if ((irc == &VirtualHost_v4) || irc_in_addr_is_ipv4(&irc->addr))
+ family = AF_INET;
+ else
+ family = AF_INET6;
+
memset(v6, 0, sizeof(*v6));
- if (!irc) {
- memset(v6, 0, sizeof(v6));
- v6->sin6_family = AF_INET6;
- return sizeof(*v6);
- }
- else if (persist && irc_in_addr_is_ipv4(&irc->addr)) {
+ if (family == AF_INET) {
struct sockaddr_in *v4 = (struct sockaddr_in*)v6;
v4->sin_family = AF_INET;
memcpy(&v4->sin_addr, &irc->addr.in6_16[6], sizeof(v4->sin_addr));
irc->port = ntohs(v4->sin_port);
}
-int sockaddr_from_irc(struct sockaddr_in *v4, const struct irc_sockaddr *irc, int persist)
+int sockaddr_from_irc(struct sockaddr_in *v4, const struct irc_sockaddr *irc, int compat_fd)
{
+ assert(irc != 0);
v4->sin_family = AF_INET;
if (irc) {
assert(!irc->addr.in6_16[0] && !irc->addr.in6_16[1] && !irc->addr.in6_16[2] && !irc->addr.in6_16[3] && !irc->addr.in6_16[4] && (!irc->addr.in6_16[5] || irc->addr.in6_16[5] == 0xffff));
} else{
memset(&v4, 0, sizeof(v4));
}
- (void)persist;
+ (void)compat_fd;
return sizeof(*v4);
}
#endif
/*
- * This is part of the STATS replies. There is no offical numeric for this
- * since this isnt an official command, in much the same way as HASH isnt.
+ * This is part of the STATS replies. There is no official numeric for this
+ * since this isn't an official command, in much the same way as HASH isn't.
* It is also possible that some systems wont support this call or have
* different field names for "struct rusage".
* -avalon
*count_out = 0;
errno = 0;
- size = sockaddr_from_irc(&addr, peer, 1);
+ size = sockaddr_from_irc(&addr, peer, fd);
+ assert((addr.sn_family == AF_INET) == irc_in_addr_is_ipv4(&peer->addr));
if (-1 < (res = sendto(fd, buf, length, flags, (struct sockaddr*)&addr, size))) {
if (count_out)
*count_out = (unsigned) res;
struct sockaddr_native addr;
int size, fd;
- size = sockaddr_from_irc(&addr, local, 1);
+ assert(local != 0);
+ size = sockaddr_from_irc(&addr, local, -1);
fd = socket(addr.sn_family, type, 0);
if (fd < 0) {
report_error(SOCKET_ERROR_MSG, port_name, errno);
struct sockaddr_native addr;
int size;
- size = sockaddr_from_irc(&addr, sin, 1);
+ size = sockaddr_from_irc(&addr, sin, fd);
if (connect(fd, (struct sockaddr*) &addr, size))
return (errno == EINPROGRESS) ? IO_BLOCKED : IO_FAILURE;
return IO_SUCCESS;