xref: /freebsd/crypto/krb5/src/include/port-sockets.h (revision f1c4c3daccbaf3820f0e2224de53df12fc952fcc)
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. */
TranslatedWSASetLastError(int posix_error)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  */
TranslatedWSAGetLastError(void)114 static __inline int TranslatedWSAGetLastError(void)
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 <sys/un.h>             /* For struct sockaddr_un */
161 #include <arpa/inet.h>          /* For inet_ntoa */
162 #include <netdb.h>
163 #include <string.h>             /* For memset */
164 
165 #ifndef HAVE_NETDB_H_H_ERRNO
166 extern int h_errno;             /* In case it's missing, e.g., HP-UX 10.20. */
167 #endif
168 
169 #include <sys/param.h>          /* For MAXHOSTNAMELEN */
170 #include <sys/socket.h>         /* For SOCK_*, AF_*, etc */
171 #include <sys/time.h>           /* For struct timeval */
172 #include <net/if.h>             /* For struct ifconf, for localaddr.c */
173 #ifdef HAVE_SYS_UIO_H
174 #include <sys/uio.h>            /* For struct iovec, for sg_buf */
175 #endif
176 #ifdef HAVE_SYS_FILIO_H
177 #include <sys/filio.h>          /* For FIONBIO on Solaris.  */
178 #endif
179 
180 /*
181  * Either size_t or int or unsigned int is probably right.  Under
182  * SunOS 4, it looks like int is desired, according to the accept man
183  * page.
184  */
185 #ifndef HAVE_SOCKLEN_T
186 typedef int socklen_t;
187 #endif
188 
189 #ifndef HAVE_STRUCT_SOCKADDR_STORAGE
190 struct krb5int_sockaddr_storage {
191     struct sockaddr_in s;
192     /* Plenty of slop just in case we get an ipv6 address anyways.  */
193     long extra[16];
194 };
195 #define sockaddr_storage krb5int_sockaddr_storage
196 #endif
197 
198 /* Unix equivalents of Winsock calls */
199 #define SOCKET          int
200 #define INVALID_SOCKET  ((SOCKET)~0)
201 #define closesocket     close
202 #define ioctlsocket     ioctl
203 #define SOCKET_ERROR    (-1)
204 
205 typedef struct iovec sg_buf;
206 
207 #define SG_ADVANCE(SG, N)                               \
208     ((SG)->iov_len < (N)                                \
209      ? (abort(), 0)                                     \
210      : ((SG)->iov_base = (char *) (SG)->iov_base + (N), \
211         (SG)->iov_len -= (N), 0))
212 
213 #define SG_LEN(SG)              ((SG)->iov_len + 0)
214 #define SG_BUF(SG)              ((char*)(SG)->iov_base + 0)
215 #define SG_SET(SG, B, L)        ((SG)->iov_base = (char*)(B), (SG)->iov_len = (L))
216 
217 #define SOCKET_INITIALIZE()     (0)     /* No error (or anything else) */
218 #define SOCKET_CLEANUP()        /* nothing */
219 #define SOCKET_ERRNO            errno
220 #define SOCKET_SET_ERRNO(x)     (errno = (x))
221 #define SOCKET_NFDS(f)          ((f)+1) /* select() arg for a single fd */
222 #define SOCKET_READ             read
223 #define SOCKET_WRITE            write
224 static inline int
socket_connect(int fd,const struct sockaddr * addr,socklen_t addrlen)225 socket_connect(int fd, const struct sockaddr *addr, socklen_t addrlen)
226 {
227     int st;
228 #ifdef SO_NOSIGPIPE
229     int set = 1;
230 #endif
231 
232     st = connect(fd, addr, addrlen);
233     if (st == -1)
234         return st;
235 
236 #ifdef SO_NOSIGPIPE
237     st = setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &set, sizeof(set));
238     if (st != 0)
239         st = -1;
240 #endif
241 
242     return st;
243 }
244 #define SOCKET_CONNECT          socket_connect
245 #define SOCKET_GETSOCKNAME      getsockname
246 #define SOCKET_CLOSE            close
247 #define SOCKET_EINTR            EINTR
248 #define SOCKET_WRITEV_TEMP int
249 static inline ssize_t
socket_sendmsg(SOCKET fd,sg_buf * iov,int iovcnt)250 socket_sendmsg(SOCKET fd, sg_buf *iov, int iovcnt)
251 {
252     struct msghdr msg;
253     int flags = 0;
254 
255 #ifdef MSG_NOSIGNAL
256     flags |= MSG_NOSIGNAL;
257 #endif
258 
259     memset(&msg, 0, sizeof(msg));
260     msg.msg_iov = iov;
261     msg.msg_iovlen = iovcnt;
262 
263     return sendmsg(fd, &msg, flags);
264 }
265 /* Use TMP to avoid compiler warnings and keep things consistent with
266  * Windows version. */
267 #define SOCKET_WRITEV(FD, SG, LEN, TMP)                 \
268     ((TMP) = socket_sendmsg((FD), (SG), (LEN)), (TMP))
269 
270 #define SHUTDOWN_READ   0
271 #define SHUTDOWN_WRITE  1
272 #define SHUTDOWN_BOTH   2
273 
274 #ifndef HAVE_INET_NTOP
275 #define inet_ntop(AF,SRC,DST,CNT)                                       \
276     ((AF) == AF_INET                                                    \
277      ? ((CNT) < 16                                                      \
278         ? (SOCKET_SET_ERRNO(ENOSPC), (const char *)NULL)                \
279         : (sprintf((DST), "%d.%d.%d.%d",                                \
280                    ((const unsigned char *)(const void *)(SRC))[0] & 0xff, \
281                    ((const unsigned char *)(const void *)(SRC))[1] & 0xff, \
282                    ((const unsigned char *)(const void *)(SRC))[2] & 0xff, \
283                    ((const unsigned char *)(const void *)(SRC))[3] & 0xff), \
284            (DST)))                                                      \
285      : (SOCKET_SET_ERRNO(EAFNOSUPPORT), (const char *)NULL))
286 #define HAVE_INET_NTOP
287 #endif
288 
289 #endif /* _WIN32 */
290 
291 #if !defined(_WIN32)
292 /* UNIX or ...?  */
293 # ifdef S_SPLINT_S
294 extern int socket (int, int, int) /*@*/;
295 # endif
296 #endif
297 
298 #endif /*_PORT_SOCKET_H*/
299