1*13571821Stholo /****************************************************************
2*13571821Stholo **
3*13571821Stholo ** PORTTCP.C - Support for portable TCP/IP
4*13571821Stholo **
5*13571821Stholo ****************************************************************/
6*13571821Stholo
7*13571821Stholo #define TCPIP_IBM_NOHIDE
8*13571821Stholo #include <stdio.h>
9*13571821Stholo #include "tcpip.h"
10*13571821Stholo
11*13571821Stholo /*
12*13571821Stholo * Common unknown error buffer
13*13571821Stholo */
14*13571821Stholo static char ErrUnknownBuf[36];
15*13571821Stholo
16*13571821Stholo #ifndef SockStrError
17*13571821Stholo
18*13571821Stholo /****************************************************************
19*13571821Stholo * Routine: SockStrError
20*13571821Stholo * Returns: Pointer to static buffer
21*13571821Stholo * Action : Convert SOCK_ERRNO into error text
22*13571821Stholo ****************************************************************/
23*13571821Stholo
24*13571821Stholo const char *
SockStrError(int SockErrno)25*13571821Stholo SockStrError(int SockErrno)
26*13571821Stholo {
27*13571821Stholo #if defined (TCPIP_IBM) && defined (IBM_CPP)
28*13571821Stholo switch (SockErrno)
29*13571821Stholo {
30*13571821Stholo case SOCEPERM: return "Not owner";
31*13571821Stholo case SOCESRCH: return "No such process";
32*13571821Stholo case SOCEINTR: return "Interrupted system call";
33*13571821Stholo case SOCENXIO: return "No such device or address";
34*13571821Stholo case SOCEBADF: return "Bad file number";
35*13571821Stholo case SOCEACCES: return "Permission denied";
36*13571821Stholo case SOCEFAULT: return "Bad address";
37*13571821Stholo case SOCEINVAL: return "Invalid argument";
38*13571821Stholo case SOCEMFILE: return "Too many open files";
39*13571821Stholo case SOCEPIPE: return "Broken pipe";
40*13571821Stholo case SOCEOS2ERR: return "OS/2 Error";
41*13571821Stholo case SOCEWOULDBLOCK: return "Operation would block";
42*13571821Stholo case SOCEINPROGRESS: return "Operation now in progress";
43*13571821Stholo case SOCEALREADY: return "Operation already in progress";
44*13571821Stholo case SOCENOTSOCK: return "Socket operation on non-socket";
45*13571821Stholo case SOCEDESTADDRREQ: return "Destination address required";
46*13571821Stholo case SOCEMSGSIZE: return "Message too long";
47*13571821Stholo case SOCEPROTOTYPE: return "Protocol wrong type for socket";
48*13571821Stholo case SOCENOPROTOOPT: return "Protocol not available";
49*13571821Stholo case SOCEPROTONOSUPPORT: return "Protocol not supported";
50*13571821Stholo case SOCESOCKTNOSUPPORT: return "Socket type not supported";
51*13571821Stholo case SOCEOPNOTSUPP: return "Operation not supported on socket";
52*13571821Stholo case SOCEPFNOSUPPORT: return "Protocol family not supported";
53*13571821Stholo case SOCEAFNOSUPPORT:
54*13571821Stholo return "Address family not supported by protocol family";
55*13571821Stholo case SOCEADDRINUSE: return "Address already in use";
56*13571821Stholo case SOCEADDRNOTAVAIL: return "Can't assign requested address";
57*13571821Stholo case SOCENETDOWN: return "Network is down";
58*13571821Stholo case SOCENETUNREACH: return "Network is unreachable";
59*13571821Stholo case SOCENETRESET: return "Network dropped connection on reset";
60*13571821Stholo case SOCECONNABORTED: return "Software caused connection abort";
61*13571821Stholo case SOCECONNRESET: return "Connection reset by peer";
62*13571821Stholo case SOCENOBUFS: return "No buffer space available";
63*13571821Stholo case SOCEISCONN: return "Socket is already connected";
64*13571821Stholo case SOCENOTCONN: return "Socket is not connected";
65*13571821Stholo case SOCESHUTDOWN: return "Can't send after socket shutdown";
66*13571821Stholo case SOCETOOMANYREFS: return "Too many references: can't splice";
67*13571821Stholo case SOCETIMEDOUT: return "Connection timed out";
68*13571821Stholo case SOCECONNREFUSED: return "Connection refused";
69*13571821Stholo case SOCELOOP: return "Too many levels of symbolic links";
70*13571821Stholo case SOCENAMETOOLONG: return "File name too long";
71*13571821Stholo case SOCEHOSTDOWN: return "Host is down";
72*13571821Stholo case SOCEHOSTUNREACH: return "No route to host";
73*13571821Stholo case SOCENOTEMPTY: return "Directory not empty";
74*13571821Stholo
75*13571821Stholo default:
76*13571821Stholo sprintf( ErrUnknownBuf, "SockStrErrno( %d ) unknown", SockErrno );
77*13571821Stholo return ErrUnknownBuf;
78*13571821Stholo }
79*13571821Stholo #else
80*13571821Stholo #error SockStrError not supported for this OS
81*13571821Stholo #endif
82*13571821Stholo }
83*13571821Stholo
84*13571821Stholo #endif /* SockStrError */
85*13571821Stholo
86*13571821Stholo
87*13571821Stholo /****************************************************************
88*13571821Stholo * Routine: HostStrError
89*13571821Stholo * Returns: Pointer to static buffer
90*13571821Stholo * Action : Convert HOST_ERRNO into error text
91*13571821Stholo ****************************************************************/
92*13571821Stholo
93*13571821Stholo const char *
HostStrError(int HostErrno)94*13571821Stholo HostStrError(int HostErrno)
95*13571821Stholo {
96*13571821Stholo switch (HostErrno)
97*13571821Stholo {
98*13571821Stholo case HOST_NOT_FOUND:
99*13571821Stholo return "Host not found";
100*13571821Stholo case TRY_AGAIN:
101*13571821Stholo return "Host not found (suggest try again)";
102*13571821Stholo case NO_RECOVERY:
103*13571821Stholo return "Non-recoverable error: FORMERR, REFUSED, NOTIMP";
104*13571821Stholo case NO_DATA:
105*13571821Stholo return "No Data (valid name, but no record of requested type)";
106*13571821Stholo
107*13571821Stholo default:
108*13571821Stholo sprintf( ErrUnknownBuf, "HostStrErrno( %d ) unknown", HostErrno );
109*13571821Stholo return ErrUnknownBuf;
110*13571821Stholo }
111*13571821Stholo }
112*13571821Stholo
113*13571821Stholo
114*13571821Stholo #if defined( TCPIP_IBM )
115*13571821Stholo /****************************************************************
116*13571821Stholo * Routine: IbmSockSend
117*13571821Stholo * Returns: same as send
118*13571821Stholo * Action : Do the right thing for IBM TCP/IP which includes
119*13571821Stholo * the following two stupidities:
120*13571821Stholo * 1) Never try to send more than 32K
121*13571821Stholo * 2) Never pass a buffer that crosses a 64K boundary
122*13571821Stholo * If Flags is non-zero, this function only attempts
123*13571821Stholo * to deal with condition (1) above.
124*13571821Stholo ****************************************************************/
125*13571821Stholo
126*13571821Stholo int
IbmSockSend(int Socket,const void * Buffer,int Len,int Flags)127*13571821Stholo IbmSockSend (int Socket, const void *Buffer, int Len, int Flags)
128*13571821Stholo {
129*13571821Stholo int Sent, ToSend, TotalSent = 0;
130*13571821Stholo
131*13571821Stholo const char *Tmp = Buffer;
132*13571821Stholo
133*13571821Stholo /*
134*13571821Stholo * If Flags have been passed in, the 64K boundary optimization
135*13571821Stholo * can not be performed. For example, MSG_PEEK would not work
136*13571821Stholo * correctly.
137*13571821Stholo */
138*13571821Stholo if (Flags)
139*13571821Stholo return send (Socket, (char *) Buffer, min (0x7FFF, Len), Flags);
140*13571821Stholo
141*13571821Stholo do
142*13571821Stholo {
143*13571821Stholo /* Never send across a 64K boundary */
144*13571821Stholo ToSend = min (Len, (int) (0x10000 - (0xFFFF & (long) Tmp)));
145*13571821Stholo
146*13571821Stholo /* Never send more than 32K */
147*13571821Stholo if (ToSend > 0x7FFF)
148*13571821Stholo ToSend = 0x7FFF;
149*13571821Stholo
150*13571821Stholo Sent = send (Socket, (char *) Tmp, ToSend, 0);
151*13571821Stholo if (Sent < 0)
152*13571821Stholo {
153*13571821Stholo if ((TotalSent > 0) && (SOCK_ERRNO == EWOULDBLOCK))
154*13571821Stholo return TotalSent;
155*13571821Stholo if (SOCK_ERRNO == EINTR)
156*13571821Stholo continue;
157*13571821Stholo return Sent;
158*13571821Stholo }
159*13571821Stholo if (Sent < ToSend)
160*13571821Stholo return TotalSent + Sent;
161*13571821Stholo
162*13571821Stholo Tmp += Sent;
163*13571821Stholo TotalSent += Sent;
164*13571821Stholo Len -= Sent;
165*13571821Stholo } while (Len > 0);
166*13571821Stholo
167*13571821Stholo return TotalSent;
168*13571821Stholo }
169*13571821Stholo
170*13571821Stholo
171*13571821Stholo
172*13571821Stholo /****************************************************************
173*13571821Stholo * Routine: IbmSockRecv
174*13571821Stholo * Returns: same as recv
175*13571821Stholo * Action : Do the right thing for IBM TCP/IP which includes
176*13571821Stholo * the following two stupidities:
177*13571821Stholo * 1) Never try to recv more than 32K
178*13571821Stholo * 2) Never pass a buffer that crosses a 64K boundary
179*13571821Stholo * If Flags is non-zero, this function only attempts
180*13571821Stholo * to deal with condition (1) above.
181*13571821Stholo ****************************************************************/
182*13571821Stholo
183*13571821Stholo int
IbmSockRecv(int Socket,const void * Buffer,int Len,int Flags)184*13571821Stholo IbmSockRecv (int Socket, const void *Buffer, int Len, int Flags)
185*13571821Stholo {
186*13571821Stholo int Recvd, ToRecv, TotalRecvd = 0;
187*13571821Stholo
188*13571821Stholo char *Tmp = Buffer;
189*13571821Stholo
190*13571821Stholo /* If Flags have been passed in, the 64K boundary optimization
191*13571821Stholo probably can not be performed. */
192*13571821Stholo
193*13571821Stholo if (Flags)
194*13571821Stholo return recv (Socket, Buffer, min (0x7FFF, Len), Flags);
195*13571821Stholo
196*13571821Stholo do
197*13571821Stholo {
198*13571821Stholo /* Never send across a 64K boundary */
199*13571821Stholo ToRecv = min( Len, (int)( 0x10000 - ( 0xFFFF & (long)Tmp )));
200*13571821Stholo
201*13571821Stholo /* Never send more than 32K */
202*13571821Stholo if( ToRecv > 0x7FFF )
203*13571821Stholo ToRecv = 0x7FFF;
204*13571821Stholo
205*13571821Stholo Recvd = recv (Socket, Tmp, ToRecv, 0);
206*13571821Stholo if (Recvd <= 0)
207*13571821Stholo {
208*13571821Stholo if ((TotalRecvd > 0)
209*13571821Stholo && (Recvd == 0 || (SOCK_ERRNO == EWOULDBLOCK )))
210*13571821Stholo return TotalRecvd;
211*13571821Stholo if (SOCK_ERRNO == EINTR)
212*13571821Stholo continue;
213*13571821Stholo
214*13571821Stholo return Recvd;
215*13571821Stholo }
216*13571821Stholo if (Recvd < ToRecv)
217*13571821Stholo return TotalRecvd + Recvd;
218*13571821Stholo
219*13571821Stholo Tmp += Recvd;
220*13571821Stholo TotalRecvd += Recvd;
221*13571821Stholo Len -= Recvd;
222*13571821Stholo } while (Len > 0);
223*13571821Stholo
224*13571821Stholo return TotalRecvd;
225*13571821Stholo }
226*13571821Stholo #endif /* defined( TCPIP_IBM ) */
227*13571821Stholo
228