1/* $NetBSD$ */ 2/* 3 * Copyright (c) 2007 Niels Provos <provos@citi.umich.edu> 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32#ifdef WIN32 33#include <winsock2.h> 34#define WIN32_LEAN_AND_MEAN 35#include <windows.h> 36#undef WIN32_LEAN_AND_MEAN 37#endif 38 39#include <sys/types.h> 40#ifdef HAVE_SYS_SOCKET_H 41#include <sys/socket.h> 42#endif 43#ifdef HAVE_UNISTD_H 44#include <unistd.h> 45#endif 46#ifdef HAVE_FCNTL_H 47#include <fcntl.h> 48#endif 49#ifdef HAVE_STDLIB_H 50#include <stdlib.h> 51#endif 52#include <errno.h> 53#if defined WIN32 && !defined(HAVE_GETTIMEOFDAY_H) 54#include <sys/timeb.h> 55#endif 56#include <stdio.h> 57 58#include "evutil.h" 59#include "log.h" 60 61int 62evutil_socketpair(int family, int type, int protocol, int fd[2]) 63{ 64#ifndef WIN32 65 return socketpair(family, type, protocol, fd); 66#else 67 /* This code is originally from Tor. Used with permission. */ 68 69 /* This socketpair does not work when localhost is down. So 70 * it's really not the same thing at all. But it's close enough 71 * for now, and really, when localhost is down sometimes, we 72 * have other problems too. 73 */ 74 int listener = -1; 75 int connector = -1; 76 int acceptor = -1; 77 struct sockaddr_in listen_addr; 78 struct sockaddr_in connect_addr; 79 int size; 80 int saved_errno = -1; 81 82 if (protocol 83#ifdef AF_UNIX 84 || family != AF_UNIX 85#endif 86 ) { 87 EVUTIL_SET_SOCKET_ERROR(WSAEAFNOSUPPORT); 88 return -1; 89 } 90 if (!fd) { 91 EVUTIL_SET_SOCKET_ERROR(WSAEINVAL); 92 return -1; 93 } 94 95 listener = socket(AF_INET, type, 0); 96 if (listener < 0) 97 return -1; 98 memset(&listen_addr, 0, sizeof(listen_addr)); 99 listen_addr.sin_family = AF_INET; 100 listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 101 listen_addr.sin_port = 0; /* kernel chooses port. */ 102 if (bind(listener, (struct sockaddr *) &listen_addr, sizeof (listen_addr)) 103 == -1) 104 goto tidy_up_and_fail; 105 if (listen(listener, 1) == -1) 106 goto tidy_up_and_fail; 107 108 connector = socket(AF_INET, type, 0); 109 if (connector < 0) 110 goto tidy_up_and_fail; 111 /* We want to find out the port number to connect to. */ 112 size = sizeof(connect_addr); 113 if (getsockname(listener, (struct sockaddr *) &connect_addr, &size) == -1) 114 goto tidy_up_and_fail; 115 if (size != sizeof (connect_addr)) 116 goto abort_tidy_up_and_fail; 117 if (connect(connector, (struct sockaddr *) &connect_addr, 118 sizeof(connect_addr)) == -1) 119 goto tidy_up_and_fail; 120 121 size = sizeof(listen_addr); 122 acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size); 123 if (acceptor < 0) 124 goto tidy_up_and_fail; 125 if (size != sizeof(listen_addr)) 126 goto abort_tidy_up_and_fail; 127 EVUTIL_CLOSESOCKET(listener); 128 /* Now check we are talking to ourself by matching port and host on the 129 two sockets. */ 130 if (getsockname(connector, (struct sockaddr *) &connect_addr, &size) == -1) 131 goto tidy_up_and_fail; 132 if (size != sizeof (connect_addr) 133 || listen_addr.sin_family != connect_addr.sin_family 134 || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr 135 || listen_addr.sin_port != connect_addr.sin_port) 136 goto abort_tidy_up_and_fail; 137 fd[0] = connector; 138 fd[1] = acceptor; 139 140 return 0; 141 142 abort_tidy_up_and_fail: 143 saved_errno = WSAECONNABORTED; 144 tidy_up_and_fail: 145 if (saved_errno < 0) 146 saved_errno = WSAGetLastError(); 147 if (listener != -1) 148 EVUTIL_CLOSESOCKET(listener); 149 if (connector != -1) 150 EVUTIL_CLOSESOCKET(connector); 151 if (acceptor != -1) 152 EVUTIL_CLOSESOCKET(acceptor); 153 154 EVUTIL_SET_SOCKET_ERROR(saved_errno); 155 return -1; 156#endif 157} 158 159int 160evutil_make_socket_nonblocking(int fd) 161{ 162#ifdef WIN32 163 { 164 unsigned long nonblocking = 1; 165 ioctlsocket(fd, FIONBIO, (unsigned long*) &nonblocking); 166 } 167#else 168 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) { 169 event_warn("fcntl(O_NONBLOCK)"); 170 return -1; 171} 172#endif 173 return 0; 174} 175 176ev_int64_t 177evutil_strtoll(const char *s, char **endptr, int base) 178{ 179#ifdef HAVE_STRTOLL 180 return (ev_int64_t)strtoll(s, endptr, base); 181#elif SIZEOF_LONG == 8 182 return (ev_int64_t)strtol(s, endptr, base); 183#elif defined(WIN32) && defined(_MSC_VER) && _MSC_VER < 1300 184 /* XXXX on old versions of MS APIs, we only support base 185 * 10. */ 186 ev_int64_t r; 187 if (base != 10) 188 return 0; 189 r = (ev_int64_t) _atoi64(s); 190 while (isspace(*s)) 191 ++s; 192 while (isdigit(*s)) 193 ++s; 194 if (endptr) 195 *endptr = (char*) s; 196 return r; 197#elif defined(WIN32) 198 return (ev_int64_t) _strtoi64(s, endptr, base); 199#else 200#error "I don't know how to parse 64-bit integers." 201#endif 202} 203 204#ifndef _EVENT_HAVE_GETTIMEOFDAY 205int 206evutil_gettimeofday(struct timeval *tv, struct timezone *tz) 207{ 208 struct _timeb tb; 209 210 if(tv == NULL) 211 return -1; 212 213 _ftime(&tb); 214 tv->tv_sec = (long) tb.time; 215 tv->tv_usec = ((int) tb.millitm) * 1000; 216 return 0; 217} 218#endif 219 220int 221evutil_snprintf(char *buf, size_t buflen, const char *format, ...) 222{ 223 int r; 224 va_list ap; 225 va_start(ap, format); 226 r = evutil_vsnprintf(buf, buflen, format, ap); 227 va_end(ap); 228 return r; 229} 230 231int 232evutil_vsnprintf(char *buf, size_t buflen, const char *format, va_list ap) 233{ 234#ifdef _MSC_VER 235 int r = _vsnprintf(buf, buflen, format, ap); 236 buf[buflen-1] = '\0'; 237 if (r >= 0) 238 return r; 239 else 240 return _vscprintf(format, ap); 241#else 242 int r = vsnprintf(buf, buflen, format, ap); 243 buf[buflen-1] = '\0'; 244 return r; 245#endif 246} 247