summaryrefslogtreecommitdiffstats
path: root/src/include/port-sockets.h
blob: b3ab9c906bb7bd6cb2d75bfca6f92c19aa68f807 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
#ifndef _PORT_SOCKET_H
#define _PORT_SOCKET_H
#if defined(_WIN32)

#include <winsock2.h>
#include <ws2tcpip.h>
#include <errno.h>

/* Some of our own infrastructure where the Winsock stuff was too hairy
 * to dump into a clean Unix program */

typedef WSABUF sg_buf;

#define SG_ADVANCE(SG, N)                       \
    ((SG)->len < (N)                            \
     ? (abort(), 0)                             \
     : ((SG)->buf += (N), (SG)->len -= (N), 0))

#define SG_LEN(SG)              ((SG)->len + 0)
#define SG_BUF(SG)              ((SG)->buf + 0)
#define SG_SET(SG, B, N)        ((SG)->buf = (char *)(B),(SG)->len = (N))

#define SOCKET_INITIALIZE()     0
#define SOCKET_CLEANUP()
#define SOCKET_ERRNO            (TranslatedWSAGetLastError())
#define SOCKET_SET_ERRNO(x)     (TranslatedWSASetLastError(x))
#define SOCKET_NFDS(f)          (0)     /* select()'s first arg is ignored */
#define SOCKET_READ(fd, b, l)   (recv(fd, b, l, 0))
#define SOCKET_WRITE(fd, b, l)  (send(fd, b, l, 0))
#define SOCKET_CONNECT          connect /* XXX */
#define SOCKET_GETSOCKNAME      getsockname /* XXX */
#define SOCKET_CLOSE            close /* XXX */
#define SOCKET_EINTR            WSAEINTR

/*
 * Return -1 for error or number of bytes written.  TMP is a temporary
 * variable; must be declared by the caller, and must be used by this macro (to
 * avoid compiler warnings).
 */
/* WSASend returns 0 or SOCKET_ERROR.  */
#define SOCKET_WRITEV_TEMP DWORD
#define SOCKET_WRITEV(FD, SG, LEN, TMP)                         \
    (WSASend((FD), (SG), (LEN), &(TMP), 0, 0, 0) ? -1 : (TMP))

#define SHUTDOWN_READ   SD_RECEIVE
#define SHUTDOWN_WRITE  SD_SEND
#define SHUTDOWN_BOTH   SD_BOTH

/*
 * Define any missing POSIX socket errors.  This is for compatibility with
 * older versions of MSVC (pre-2010).
 */
#ifndef EINPROGRESS
#define EINPROGRESS WSAEINPROGRESS
#endif
#ifndef EWOULDBLOCK
#define EWOULDBLOCK WSAEWOULDBLOCK
#endif
#ifndef ECONNRESET
#define ECONNRESET  WSAECONNRESET
#endif
#ifndef ECONNABORTED
#define ECONNABORTED WSAECONNABORTED
#endif
#ifndef ECONNREFUSED
#define ECONNREFUSED WSAECONNREFUSED
#endif
#ifndef EHOSTUNREACH
#define EHOSTUNREACH WSAEHOSTUNREACH
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT WSAETIMEDOUT
#endif

/* Translate posix_error to its Winsock counterpart and set the last Winsock
 * error to the result. */
static __inline void TranslatedWSASetLastError(int posix_error)
{
    int wsa_error;
    switch (posix_error) {
    case 0:
        wsa_error = 0; break;
    case EINPROGRESS:
        wsa_error = WSAEINPROGRESS; break;
    case EWOULDBLOCK:
        wsa_error = WSAEWOULDBLOCK; break;
    case ECONNRESET:
        wsa_error = WSAECONNRESET; break;
    case ECONNABORTED:
        wsa_error = WSAECONNABORTED; break;
    case ECONNREFUSED:
        wsa_error = WSAECONNREFUSED; break;
    case EHOSTUNREACH:
        wsa_error = WSAEHOSTUNREACH; break;
    case ETIMEDOUT:
        wsa_error = WSAETIMEDOUT; break;
    case EAFNOSUPPORT:
        wsa_error = WSAEAFNOSUPPORT; break;
    case EINVAL:
        wsa_error = WSAEINVAL; break;
    default:
        /* Ideally, we would log via k5-trace here, but we have no context. */
        wsa_error = WSAEINVAL; break;
    }
    WSASetLastError(wsa_error);
}

/*
 * Translate Winsock errors to their POSIX counterparts.  This is necessary for
 * MSVC 2010+, where both Winsock and POSIX errors are defined.
 */
static __inline int TranslatedWSAGetLastError()
{
    int err = WSAGetLastError();
    switch (err) {
    case 0:
        break;
    case WSAEINPROGRESS:
        err = EINPROGRESS; break;
    case WSAEWOULDBLOCK:
        err = EWOULDBLOCK; break;
    case WSAECONNRESET:
        err = ECONNRESET; break;
    case WSAECONNABORTED:
        err = ECONNABORTED; break;
    case WSAECONNREFUSED:
        err = ECONNREFUSED; break;
    case WSAEHOSTUNREACH:
        err = EHOSTUNREACH; break;
    case WSAETIMEDOUT:
        err = ETIMEDOUT; break;
    case WSAEAFNOSUPPORT:
        err = EAFNOSUPPORT; break;
    case WSAEINVAL:
        err = EINVAL; break;
    default:
        /* Ideally, we would log via k5-trace here, but we have no context. */
        err = EINVAL; break;
    }
    return err;
}

#elif defined(__palmos__)

/* If this source file requires it, define struct sockaddr_in (and possibly
 * other things related to network I/O). */

#include "autoconf.h"
#include <netdb.h>
typedef int socklen_t;

#else /* UNIX variants */

#include "autoconf.h"

#include <sys/types.h>
#include <netinet/in.h>         /* For struct sockaddr_in and in_addr */
#include <arpa/inet.h>          /* For inet_ntoa */
#include <netdb.h>

#ifndef HAVE_NETDB_H_H_ERRNO
extern int h_errno;             /* In case it's missing, e.g., HP-UX 10.20. */
#endif

#include <sys/param.h>          /* For MAXHOSTNAMELEN */
#include <sys/socket.h>         /* For SOCK_*, AF_*, etc */
#include <sys/time.h>           /* For struct timeval */
#include <net/if.h>             /* For struct ifconf, for localaddr.c */
#ifdef HAVE_SYS_UIO_H
#include <sys/uio.h>            /* For struct iovec, for sg_buf */
#endif
#ifdef HAVE_SYS_FILIO_H
#include <sys/filio.h>          /* For FIONBIO on Solaris.  */
#endif

/*
 * Either size_t or int or unsigned int is probably right.  Under
 * SunOS 4, it looks like int is desired, according to the accept man
 * page.
 */
#ifndef HAVE_SOCKLEN_T
typedef int socklen_t;
#endif

#ifndef HAVE_STRUCT_SOCKADDR_STORAGE
struct krb5int_sockaddr_storage {
    struct sockaddr_in s;
    /* Plenty of slop just in case we get an ipv6 address anyways.  */
    long extra[16];
};
#define sockaddr_storage krb5int_sockaddr_storage
#endif

/* Unix equivalents of Winsock calls */
#define SOCKET          int
#define INVALID_SOCKET  ((SOCKET)~0)
#define closesocket     close
#define ioctlsocket     ioctl
#define SOCKET_ERROR    (-1)

typedef struct iovec sg_buf;

#define SG_ADVANCE(SG, N)                               \
    ((SG)->iov_len < (N)                                \
     ? (abort(), 0)                                     \
     : ((SG)->iov_base = (char *) (SG)->iov_base + (N), \
        (SG)->iov_len -= (N), 0))

#define SG_LEN(SG)              ((SG)->iov_len + 0)
#define SG_BUF(SG)              ((char*)(SG)->iov_base + 0)
#define SG_SET(SG, B, L)        ((SG)->iov_base = (char*)(B), (SG)->iov_len = (L))

#define SOCKET_INITIALIZE()     (0)     /* No error (or anything else) */
#define SOCKET_CLEANUP()        /* nothing */
#define SOCKET_ERRNO            errno
#define SOCKET_SET_ERRNO(x)     (errno = (x))
#define SOCKET_NFDS(f)          ((f)+1) /* select() arg for a single fd */
#define SOCKET_READ             read
#define SOCKET_WRITE            write
#define SOCKET_CONNECT          connect
#define SOCKET_GETSOCKNAME      getsockname
#define SOCKET_CLOSE            close
#define SOCKET_EINTR            EINTR
#define SOCKET_WRITEV_TEMP int
/* Use TMP to avoid compiler warnings and keep things consistent with
 * Windows version. */
#define SOCKET_WRITEV(FD, SG, LEN, TMP)         \
    ((TMP) = writev((FD), (SG), (LEN)), (TMP))

#define SHUTDOWN_READ   0
#define SHUTDOWN_WRITE  1
#define SHUTDOWN_BOTH   2

#ifndef HAVE_INET_NTOP
#define inet_ntop(AF,SRC,DST,CNT)                                       \
    ((AF) == AF_INET                                                    \
     ? ((CNT) < 16                                                      \
        ? (SOCKET_SET_ERRNO(ENOSPC), (const char *)NULL)                \
        : (sprintf((DST), "%d.%d.%d.%d",                                \
                   ((const unsigned char *)(const void *)(SRC))[0] & 0xff, \
                   ((const unsigned char *)(const void *)(SRC))[1] & 0xff, \
                   ((const unsigned char *)(const void *)(SRC))[2] & 0xff, \
                   ((const unsigned char *)(const void *)(SRC))[3] & 0xff), \
           (DST)))                                                      \
     : (SOCKET_SET_ERRNO(EAFNOSUPPORT), (const char *)NULL))
#define HAVE_INET_NTOP
#endif

#endif /* _WIN32 */

#if !defined(_WIN32)
/* UNIX or ...?  */
# ifdef S_SPLINT_S
extern int socket (int, int, int) /*@*/;
# endif
#endif

#endif /*_PORT_SOCKET_H*/