1 /* This is mostly emulation of socklib.c from xpilot used by koules before.
2  * It was removed because of copyright problems. Current implementation is
3  * completly rewrote just partially compatible with socklib API. It implements
4  * just few calls used by koules and in a bit different way. It is not drop-in
5  * replacement for socklib.
6  */
7 #if defined(__sparc)
8 #define __EXTENSIONS__
9 #endif
10 #include <unistd.h>
11 #include <sys/types.h>
12 #include <sys/param.h>
13 #include <sys/ioctl.h>
14 #if (SVR4)
15 #include <sys/filio.h>
16 #endif
17 #ifdef __hpux
18 #include <time.h>
19 #else
20 #include <sys/time.h>
21 #endif
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <netinet/tcp.h>
25 #include <arpa/inet.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <netdb.h>
30 #include <signal.h>
31 #include <setjmp.h>
32 #include <errno.h>
33 #if defined(__sparc)
34 #include <sys/fcntl.h>
35 #endif
36 #if defined(__sun__)
37 #include <arpa/nameser.h>
38 #include <resolv.h>
39 #endif
40 
41 #include "sock.h"
42 static struct timeval timeout;
43 static struct sockaddr_in lastaddr;
44 
45 
SetTimeout(int s,int us)46 void SetTimeout(int s,int us)
47 {
48   timeout.tv_sec=s;
49   timeout.tv_usec=us;
50 }
51 
GetPortNum(int fd)52 int GetPortNum(int fd)
53 {
54   struct sockaddr_in a;
55   int s=sizeof(a);
56   if(getsockname(fd,(struct sockaddr *)&a,&s)<0) return -1;
57   return(ntohs(a.sin_port));
58 }
GetSockAddr(int fd)59 char *GetSockAddr(int fd)
60 {
61   struct sockaddr_in a;
62   int s=sizeof(a);
63   if(getsockname(fd,(struct sockaddr *)&a,&s)<0) return NULL;
64   return(inet_ntoa(a.sin_addr));
65 }
SetSocketReceiveBufferSize(int fd,int size)66 int SetSocketReceiveBufferSize(int fd,int size)
67 {
68 	return(setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (void *)&size, sizeof(size)));
69 }
SetSocketSendBufferSize(int fd,int size)70 int SetSocketSendBufferSize(int fd,int size)
71 {
72 	return(setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (void *)&size, sizeof(size)));
73 }
74 
75 
SetSocketNonBlocking(int fd,int flag)76 int SetSocketNonBlocking (int fd, int flag)
77 {
78 /*
79  * This code is copied from original socklib library. I hope it is not
80  * problem... I want to avoid compilation problems on some systems...
81  *
82  * There are some problems on some particular systems (suns) with
83  * getting sockets to be non-blocking.  Just try all possible ways
84  * until one of them succeeds.  Please keep us informed by e-mail
85  * to xpilot@cs.uit.no.
86  */
87 
88 #ifndef USE_FCNTL_O_NONBLOCK
89 #ifndef USE_FCNTL_O_NDELAY
90 #ifndef USE_FCNTL_FNDELAY
91 #ifndef USE_IOCTL_FIONBIO
92 
93 #if defined(_SEQUENT_) || defined(__svr4__) || defined(SVR4)
94 #define USE_FCNTL_O_NDELAY
95 #elif defined(__sun__) && defined(FNDELAY)
96 #define USE_FCNTL_FNDELAY
97 #elif defined(FIONBIO)
98 #define USE_IOCTL_FIONBIO
99 #elif defined(FNDELAY)
100 #define USE_FCNTL_FNDELAY
101 #elif defined(O_NONBLOCK)
102 #define USE_FCNTL_O_NONBLOCK
103 #else
104 #define USE_FCNTL_O_NDELAY
105 #endif
106 
107 #endif
108 #endif
109 #endif
110 #endif
111 
112 #ifdef USE_FCNTL_FNDELAY
113   if (fcntl (fd, F_SETFL, (flag != 0) ? FNDELAY : 0) != -1)
114     return 0;
115   fprintf (stderr, "fcntl FNDELAY failed in file \"%s\", line %d: %s\n",
116 	   __FILE__, __LINE__, strerror (errno));
117 #endif
118 
119 #ifdef USE_IOCTL_FIONBIO
120   if (ioctl (fd, FIONBIO, &flag) != -1)
121     return 0;
122   fprintf (stderr, "ioctl FIONBIO failed in file \"%s\", line %d: %s\n",
123 	   __FILE__, __LINE__, strerror (errno));
124 #endif
125 
126 #ifdef USE_FCNTL_O_NONBLOCK
127   if (fcntl (fd, F_SETFL, (flag != 0) ? O_NONBLOCK : 0) != -1)
128     return 0;
129   fprintf (stderr, "fcntl O_NONBLOCK failed in file \"%s\", line %d: %s\n",
130 	   __FILE__, __LINE__, strerror (errno));
131 #endif
132 
133 #ifdef USE_FCNTL_O_NDELAY
134   if (fcntl (fd, F_SETFL, (flag != 0) ? O_NDELAY : 0) != -1)
135     return 0;
136   fprintf (stderr, "fcntl O_NDELAY failed in file \"%s\", line %d: %s\n",
137 	   __FILE__, __LINE__, strerror (errno));
138 #endif
139 
140   return (-1);
141 }
142 
GetSocketError(int fd)143 int GetSocketError(int fd)
144 {
145 	int size=sizeof(errno);
146 	return (getsockopt(fd,SOL_SOCKET,SO_ERROR,(char *)&errno,&size));
147 }
148 
SocketReadable(int fd)149 int SocketReadable(int fd)
150 {
151 	fd_set fds;
152         FD_ZERO(&fds);
153 	FD_SET(fd,&fds);
154 	if (select (fd + 1, &fds, NULL, NULL, &timeout) == -1) return ((errno == EINTR) ? 0 : -1);
155 	return(FD_ISSET(fd,&fds));
156 }
157 
CreateDgramSocket(int port)158 int CreateDgramSocket(int port)
159 {
160         struct sockaddr_in addr;
161 	int fd;
162 
163 	fd=socket(AF_INET, SOCK_DGRAM, 0);
164 	if (fd<0) return -1;
165 	memset(&addr,0,sizeof(addr));
166 	addr.sin_addr.s_addr=INADDR_ANY;
167 	addr.sin_port=htons(port);
168 	addr.sin_family=AF_INET;
169 	if(bind(fd,(struct sockaddr *)&addr,sizeof(struct sockaddr_in))<0) {
170 			fd=errno;
171 			close(fd);
172 			errno=fd;
173 			return -1;
174 			}
175         return fd;
176 
177 }
DgramConnect(int fd,char * host,int port)178 int DgramConnect(int fd, char *host, int port)
179 {
180 	struct sockaddr_in addr;
181 	memset(&addr,0,sizeof(addr));
182 	addr.sin_addr.s_addr = inet_addr (host);
183 	if(addr.sin_addr.s_addr==-1) return -1;
184 	addr.sin_family = AF_INET;
185 	addr.sin_port = htons (port);
186 	return(connect (fd, (struct sockaddr *) &addr, sizeof (addr)));
187 }
DgramSend(int fd,char * host,int port,char * sbuf,int size)188 int DgramSend(int fd, char *host, int port, char *sbuf, int size)
189 {
190 	struct sockaddr_in addr;
191 	struct hostent *hp;
192 #if 0
193 	if (!rand()%10) return 0;/*Internet emulation :))))))) */
194 	if (rand()%2) {size=rand()%size;}
195 #endif
196 	memset(&addr,0,sizeof(addr));
197 	addr.sin_addr.s_addr = inet_addr (host);
198 	if(addr.sin_addr.s_addr==-1) {
199 		if (addr.sin_addr.s_addr == (int) -1)
200 		{
201 			hp = gethostbyname (host);
202 			if (hp == NULL)
203 			{
204 				fprintf(stderr,"Host '%s' unknown\n",host);
205 				return -1;
206 			}
207 			else
208 				addr.sin_addr.s_addr = ((struct in_addr *) (hp->h_addr))->s_addr;
209 		}
210 
211 	}
212 	addr.sin_family = AF_INET;
213 	addr.sin_port = htons (port);
214         return(sendto (fd, sbuf, size, 0, (struct sockaddr *) &addr,
215 		                     sizeof (struct sockaddr_in)));
216 
217 }
DgramReceiveAny(int fd,char * buf,int size)218 int DgramReceiveAny(int fd,char *buf, int size)
219 {
220 	int len=sizeof (struct sockaddr_in);
221 	return(recvfrom (fd, buf, size, 0, (struct sockaddr *) &lastaddr, &len));
222 }
DgramReceiveConnected(int fd,char * buf,int size)223 int DgramReceiveConnected(int fd,char *buf, int size)
224 {
225 	return(recv (fd, buf, size, 0));
226 }
SocketClose(int fd)227 int SocketClose (int fd)
228 {
229        shutdown (fd, 2);
230        if (close (fd) == -1)
231           {
232 	       return (-1);
233           }
234      return (1);
235 }
DgramLastaddr(void)236 char *DgramLastaddr (void)
237 {
238 	  return (inet_ntoa (lastaddr.sin_addr));
239 }
DgramLastport(void)240 int DgramLastport (void)
241 {
242 	  return (ntohs ((int) lastaddr.sin_port));
243 }
244 
245 
246