1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 #ifndef _PORT_SOCKET_H 3 #define _PORT_SOCKET_H 4 #if defined(_WIN32) 5 6 #include <winsock2.h> 7 #include <ws2tcpip.h> 8 #include <errno.h> 9 10 /* Some of our own infrastructure where the Winsock stuff was too hairy 11 * to dump into a clean Unix program */ 12 13 typedef WSABUF sg_buf; 14 15 #define SG_ADVANCE(SG, N) \ 16 ((SG)->len < (N) \ 17 ? (abort(), 0) \ 18 : ((SG)->buf += (N), (SG)->len -= (N), 0)) 19 20 #define SG_LEN(SG) ((SG)->len + 0) 21 #define SG_BUF(SG) ((SG)->buf + 0) 22 #define SG_SET(SG, B, N) ((SG)->buf = (char *)(B),(SG)->len = (N)) 23 24 #define SOCKET_INITIALIZE() 0 25 #define SOCKET_CLEANUP() 26 #define SOCKET_ERRNO (TranslatedWSAGetLastError()) 27 #define SOCKET_SET_ERRNO(x) (TranslatedWSASetLastError(x)) 28 #define SOCKET_NFDS(f) (0) /* select()'s first arg is ignored */ 29 #define SOCKET_READ(fd, b, l) (recv(fd, b, l, 0)) 30 #define SOCKET_WRITE(fd, b, l) (send(fd, b, l, 0)) 31 #define SOCKET_CONNECT connect /* XXX */ 32 #define SOCKET_GETSOCKNAME getsockname /* XXX */ 33 #define SOCKET_CLOSE close /* XXX */ 34 #define SOCKET_EINTR WSAEINTR 35 36 /* 37 * Return -1 for error or number of bytes written. TMP is a temporary 38 * variable; must be declared by the caller, and must be used by this macro (to 39 * avoid compiler warnings). 40 */ 41 /* WSASend returns 0 or SOCKET_ERROR. */ 42 #define SOCKET_WRITEV_TEMP DWORD 43 #define SOCKET_WRITEV(FD, SG, LEN, TMP) \ 44 (WSASend((FD), (SG), (LEN), &(TMP), 0, 0, 0) ? \ 45 (ssize_t)-1 : (ssize_t)(TMP)) 46 47 #define SHUTDOWN_READ SD_RECEIVE 48 #define SHUTDOWN_WRITE SD_SEND 49 #define SHUTDOWN_BOTH SD_BOTH 50 51 /* 52 * Define any missing POSIX socket errors. This is for compatibility with 53 * older versions of MSVC (pre-2010). 54 */ 55 #ifndef EINPROGRESS 56 #define EINPROGRESS WSAEINPROGRESS 57 #endif 58 #ifndef EWOULDBLOCK 59 #define EWOULDBLOCK WSAEWOULDBLOCK 60 #endif 61 #ifndef ECONNRESET 62 #define ECONNRESET WSAECONNRESET 63 #endif 64 #ifndef ECONNABORTED 65 #define ECONNABORTED WSAECONNABORTED 66 #endif 67 #ifndef ECONNREFUSED 68 #define ECONNREFUSED WSAECONNREFUSED 69 #endif 70 #ifndef EHOSTUNREACH 71 #define EHOSTUNREACH WSAEHOSTUNREACH 72 #endif 73 #ifndef ETIMEDOUT 74 #define ETIMEDOUT WSAETIMEDOUT 75 #endif 76 77 /* Translate posix_error to its Winsock counterpart and set the last Winsock 78 * error to the result. */ 79 static __inline void TranslatedWSASetLastError(int posix_error) 80 { 81 int wsa_error; 82 switch (posix_error) { 83 case 0: 84 wsa_error = 0; break; 85 case EINPROGRESS: 86 wsa_error = WSAEINPROGRESS; break; 87 case EWOULDBLOCK: 88 wsa_error = WSAEWOULDBLOCK; break; 89 case ECONNRESET: 90 wsa_error = WSAECONNRESET; break; 91 case ECONNABORTED: 92 wsa_error = WSAECONNABORTED; break; 93 case ECONNREFUSED: 94 wsa_error = WSAECONNREFUSED; break; 95 case EHOSTUNREACH: 96 wsa_error = WSAEHOSTUNREACH; break; 97 case ETIMEDOUT: 98 wsa_error = WSAETIMEDOUT; break; 99 case EAFNOSUPPORT: 100 wsa_error = WSAEAFNOSUPPORT; break; 101 case EINVAL: 102 wsa_error = WSAEINVAL; break; 103 default: 104 /* Ideally, we would log via k5-trace here, but we have no context. */ 105 wsa_error = WSAEINVAL; break; 106 } 107 WSASetLastError(wsa_error); 108 } 109 110 /* 111 * Translate Winsock errors to their POSIX counterparts. This is necessary for 112 * MSVC 2010+, where both Winsock and POSIX errors are defined. 113 */ 114 static __inline int TranslatedWSAGetLastError() 115 { 116 int err = WSAGetLastError(); 117 switch (err) { 118 case 0: 119 break; 120 case WSAEINPROGRESS: 121 err = EINPROGRESS; break; 122 case WSAEWOULDBLOCK: 123 err = EWOULDBLOCK; break; 124 case WSAECONNRESET: 125 err = ECONNRESET; break; 126 case WSAECONNABORTED: 127 err = ECONNABORTED; break; 128 case WSAECONNREFUSED: 129 err = ECONNREFUSED; break; 130 case WSAEHOSTUNREACH: 131 err = EHOSTUNREACH; break; 132 case WSAETIMEDOUT: 133 err = ETIMEDOUT; break; 134 case WSAEAFNOSUPPORT: 135 err = EAFNOSUPPORT; break; 136 case WSAEINVAL: 137 err = EINVAL; break; 138 default: 139 /* Ideally, we would log via k5-trace here, but we have no context. */ 140 err = EINVAL; break; 141 } 142 return err; 143 } 144 145 #elif defined(__palmos__) 146 147 /* If this source file requires it, define struct sockaddr_in (and possibly 148 * other things related to network I/O). */ 149 150 #include "autoconf.h" 151 #include <netdb.h> 152 typedef int socklen_t; 153 154 #else /* UNIX variants */ 155 156 #include "autoconf.h" 157 158 #include <sys/types.h> 159 #include <netinet/in.h> /* For struct sockaddr_in and in_addr */ 160 #include <arpa/inet.h> /* For inet_ntoa */ 161 #include <netdb.h> 162 #include <string.h> /* For memset */ 163 164 #ifndef HAVE_NETDB_H_H_ERRNO 165 extern int h_errno; /* In case it's missing, e.g., HP-UX 10.20. */ 166 #endif 167 168 #include <sys/param.h> /* For MAXHOSTNAMELEN */ 169 #include <sys/socket.h> /* For SOCK_*, AF_*, etc */ 170 #include <sys/time.h> /* For struct timeval */ 171 #include <net/if.h> /* For struct ifconf, for localaddr.c */ 172 #ifdef HAVE_SYS_UIO_H 173 #include <sys/uio.h> /* For struct iovec, for sg_buf */ 174 #endif 175 #ifdef HAVE_SYS_FILIO_H 176 #include <sys/filio.h> /* For FIONBIO on Solaris. */ 177 #endif 178 179 /* 180 * Either size_t or int or unsigned int is probably right. Under 181 * SunOS 4, it looks like int is desired, according to the accept man 182 * page. 183 */ 184 #ifndef HAVE_SOCKLEN_T 185 typedef int socklen_t; 186 #endif 187 188 #ifndef HAVE_STRUCT_SOCKADDR_STORAGE 189 struct krb5int_sockaddr_storage { 190 struct sockaddr_in s; 191 /* Plenty of slop just in case we get an ipv6 address anyways. */ 192 long extra[16]; 193 }; 194 #define sockaddr_storage krb5int_sockaddr_storage 195 #endif 196 197 /* Unix equivalents of Winsock calls */ 198 #define SOCKET int 199 #define INVALID_SOCKET ((SOCKET)~0) 200 #define closesocket close 201 #define ioctlsocket ioctl 202 #define SOCKET_ERROR (-1) 203 204 typedef struct iovec sg_buf; 205 206 #define SG_ADVANCE(SG, N) \ 207 ((SG)->iov_len < (N) \ 208 ? (abort(), 0) \ 209 : ((SG)->iov_base = (char *) (SG)->iov_base + (N), \ 210 (SG)->iov_len -= (N), 0)) 211 212 #define SG_LEN(SG) ((SG)->iov_len + 0) 213 #define SG_BUF(SG) ((char*)(SG)->iov_base + 0) 214 #define SG_SET(SG, B, L) ((SG)->iov_base = (char*)(B), (SG)->iov_len = (L)) 215 216 #define SOCKET_INITIALIZE() (0) /* No error (or anything else) */ 217 #define SOCKET_CLEANUP() /* nothing */ 218 #define SOCKET_ERRNO errno 219 #define SOCKET_SET_ERRNO(x) (errno = (x)) 220 #define SOCKET_NFDS(f) ((f)+1) /* select() arg for a single fd */ 221 #define SOCKET_READ read 222 #define SOCKET_WRITE write 223 static inline int 224 socket_connect(int fd, const struct sockaddr *addr, socklen_t addrlen) 225 { 226 int st; 227 #ifdef SO_NOSIGPIPE 228 int set = 1; 229 #endif 230 231 st = connect(fd, addr, addrlen); 232 if (st == -1) 233 return st; 234 235 #ifdef SO_NOSIGPIPE 236 st = setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(set)); 237 if (st != 0) 238 st = -1; 239 #endif 240 241 return st; 242 } 243 #define SOCKET_CONNECT socket_connect 244 #define SOCKET_GETSOCKNAME getsockname 245 #define SOCKET_CLOSE close 246 #define SOCKET_EINTR EINTR 247 #define SOCKET_WRITEV_TEMP int 248 static inline ssize_t 249 socket_sendmsg(SOCKET fd, sg_buf *iov, int iovcnt) 250 { 251 struct msghdr msg; 252 int flags = 0; 253 254 #ifdef MSG_NOSIGNAL 255 flags |= MSG_NOSIGNAL; 256 #endif 257 258 memset(&msg, 0, sizeof(msg)); 259 msg.msg_iov = iov; 260 msg.msg_iovlen = iovcnt; 261 262 return sendmsg(fd, &msg, flags); 263 } 264 /* Use TMP to avoid compiler warnings and keep things consistent with 265 * Windows version. */ 266 #define SOCKET_WRITEV(FD, SG, LEN, TMP) \ 267 ((TMP) = socket_sendmsg((FD), (SG), (LEN)), (TMP)) 268 269 #define SHUTDOWN_READ 0 270 #define SHUTDOWN_WRITE 1 271 #define SHUTDOWN_BOTH 2 272 273 #ifndef HAVE_INET_NTOP 274 #define inet_ntop(AF,SRC,DST,CNT) \ 275 ((AF) == AF_INET \ 276 ? ((CNT) < 16 \ 277 ? (SOCKET_SET_ERRNO(ENOSPC), (const char *)NULL) \ 278 : (sprintf((DST), "%d.%d.%d.%d", \ 279 ((const unsigned char *)(const void *)(SRC))[0] & 0xff, \ 280 ((const unsigned char *)(const void *)(SRC))[1] & 0xff, \ 281 ((const unsigned char *)(const void *)(SRC))[2] & 0xff, \ 282 ((const unsigned char *)(const void *)(SRC))[3] & 0xff), \ 283 (DST))) \ 284 : (SOCKET_SET_ERRNO(EAFNOSUPPORT), (const char *)NULL)) 285 #define HAVE_INET_NTOP 286 #endif 287 288 #endif /* _WIN32 */ 289 290 #if !defined(_WIN32) 291 /* UNIX or ...? */ 292 # ifdef S_SPLINT_S 293 extern int socket (int, int, int) /*@*/; 294 # endif 295 #endif 296 297 #endif /*_PORT_SOCKET_H*/ 298