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