1 /* Serial port emulation using sockets.
2    Copyright (C) 1998-2013 Free Software Foundation, Inc.
3    Contributed by Cygnus Solutions.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17 
18 /* FIXME: will obviously need to evolve.
19    - connectionless sockets might be more appropriate.  */
20 
21 #include "sim-main.h"
22 
23 #ifdef HAVE_STRING_H
24 #include <string.h>
25 #else
26 #ifdef HAVE_STRINGS_H
27 #include <strings.h>
28 #endif
29 #endif
30 #include <signal.h>
31 #ifdef HAVE_STDLIB_H
32 #include <stdlib.h>
33 #endif
34 #ifdef HAVE_FCNTL_H
35 #include <fcntl.h>
36 #endif
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40 
41 #include <errno.h>
42 #include <sys/types.h>
43 #include <sys/time.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
46 #include <netdb.h>
47 #include <sys/socket.h>
48 
49 #ifndef __CYGWIN32__
50 #include <netinet/tcp.h>
51 #endif
52 
53 #include "sim-assert.h"
54 #include "sim-options.h"
55 
56 #include "dv-sockser.h"
57 
58 #ifndef HAVE_SOCKLEN_T
59 typedef int socklen_t;
60 #endif
61 
62 /* Get definitions for both O_NONBLOCK and O_NDELAY.  */
63 
64 #ifndef O_NDELAY
65 #ifdef FNDELAY
66 #define O_NDELAY FNDELAY
67 #else /* ! defined (FNDELAY) */
68 #define O_NDELAY 0
69 #endif /* ! defined (FNDELAY) */
70 #endif /* ! defined (O_NDELAY) */
71 
72 #ifndef O_NONBLOCK
73 #ifdef FNBLOCK
74 #define O_NONBLOCK FNBLOCK
75 #else /* ! defined (FNBLOCK) */
76 #define O_NONBLOCK 0
77 #endif /* ! defined (FNBLOCK) */
78 #endif /* ! defined (O_NONBLOCK) */
79 
80 
81 /* Compromise between eating cpu and properly busy-waiting.
82    One could have an option to set this but for now that seems
83    like featuritis.  */
84 #define DEFAULT_TIMEOUT 1000 /* microseconds */
85 
86 /* FIXME: These should allocated at run time and kept with other simulator
87    state (duh...).  Later.  */
88 const char * sockser_addr = NULL;
89 /* Timeout in microseconds during status flag computation.
90    Setting this to zero achieves proper busy wait semantics but eats cpu.  */
91 static unsigned int sockser_timeout = DEFAULT_TIMEOUT;
92 static int sockser_listen_fd = -1;
93 static int sockser_fd = -1;
94 
95 /* FIXME: use tree properties when they're ready.  */
96 
97 typedef enum {
98   OPTION_ADDR = OPTION_START
99 } SOCKSER_OPTIONS;
100 
101 static DECLARE_OPTION_HANDLER (sockser_option_handler);
102 
103 static const OPTION sockser_options[] =
104 {
105   { { "sockser-addr", required_argument, NULL, OPTION_ADDR },
106       '\0', "SOCKET ADDRESS", "Set serial emulation socket address",
107       sockser_option_handler, NULL },
108   { { NULL, no_argument, NULL, 0 }, '\0', NULL, NULL, NULL, NULL }
109 };
110 
111 static SIM_RC
sockser_option_handler(SIM_DESC sd,sim_cpu * cpu,int opt,char * arg,int is_command)112 sockser_option_handler (SIM_DESC sd, sim_cpu *cpu, int opt,
113 			char *arg, int is_command)
114 {
115   switch (opt)
116     {
117     case OPTION_ADDR :
118       sockser_addr = arg;
119       break;
120     }
121 
122   return SIM_RC_OK;
123 }
124 
125 static SIM_RC
dv_sockser_init(SIM_DESC sd)126 dv_sockser_init (SIM_DESC sd)
127 {
128   struct hostent *hostent;
129   struct sockaddr_in sockaddr;
130   char hostname[100];
131   const char *port_str;
132   int tmp,port;
133 
134   if (STATE_ENVIRONMENT (sd) != OPERATING_ENVIRONMENT
135       || sockser_addr == NULL)
136     return SIM_RC_OK;
137 
138   if (*sockser_addr == '/')
139     {
140       /* support for these can come later */
141       sim_io_eprintf (sd, "sockser init: unix domain sockets not supported: `%s'\n",
142 		      sockser_addr);
143       return SIM_RC_FAIL;
144     }
145 
146   port_str = strchr (sockser_addr, ':');
147   if (!port_str)
148     {
149       sim_io_eprintf (sd, "sockser init: missing port number: `%s'\n",
150 		      sockser_addr);
151       return SIM_RC_FAIL;
152     }
153   tmp = port_str - sockser_addr;
154   if (tmp >= sizeof hostname)
155     tmp = sizeof (hostname) - 1;
156   strncpy (hostname, sockser_addr, tmp);
157   hostname[tmp] = '\000';
158   port = atoi (port_str + 1);
159 
160   hostent = gethostbyname (hostname);
161   if (! hostent)
162     {
163       sim_io_eprintf (sd, "sockser init: unknown host: %s\n",
164 		      hostname);
165       return SIM_RC_FAIL;
166     }
167 
168   sockser_listen_fd = socket (PF_INET, SOCK_STREAM, 0);
169   if (sockser_listen_fd == -1)
170     {
171       sim_io_eprintf (sd, "sockser init: unable to get socket: %s\n",
172 		      strerror (errno));
173       return SIM_RC_FAIL;
174     }
175 
176   sockaddr.sin_family = PF_INET;
177   sockaddr.sin_port = htons (port);
178   memcpy (&sockaddr.sin_addr.s_addr, hostent->h_addr,
179 	  sizeof (struct in_addr));
180 
181   tmp = 1;
182   if (setsockopt (sockser_listen_fd, SOL_SOCKET, SO_REUSEADDR, (void*)& tmp, sizeof (tmp)) < 0)
183     {
184       sim_io_eprintf (sd, "sockser init: unable to set SO_REUSEADDR: %s\n",
185 		      strerror (errno));
186     }
187   if (bind (sockser_listen_fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) < 0)
188     {
189       sim_io_eprintf (sd, "sockser init: unable to bind socket address: %s\n",
190 		      strerror (errno));
191       close (sockser_listen_fd);
192       sockser_listen_fd = -1;
193       return SIM_RC_FAIL;
194     }
195   if (listen (sockser_listen_fd, 1) < 0)
196     {
197       sim_io_eprintf (sd, "sockser init: unable to set up listener: %s\n",
198 		      strerror (errno));
199       close (sockser_listen_fd);
200       sockser_listen_fd = -1;
201       return SIM_RC_OK;
202     }
203 
204   /* Handle writes to missing client -> SIGPIPE.
205      ??? Need a central signal management module.  */
206   {
207     RETSIGTYPE (*orig) ();
208     orig = signal (SIGPIPE, SIG_IGN);
209     /* If a handler is already set up, don't mess with it.  */
210     if (orig != SIG_DFL && orig != SIG_IGN)
211       signal (SIGPIPE, orig);
212   }
213 
214   return SIM_RC_OK;
215 }
216 
217 static void
dv_sockser_uninstall(SIM_DESC sd)218 dv_sockser_uninstall (SIM_DESC sd)
219 {
220   if (sockser_listen_fd != -1)
221     {
222       close (sockser_listen_fd);
223       sockser_listen_fd = -1;
224     }
225   if (sockser_fd != -1)
226     {
227       close (sockser_fd);
228       sockser_fd = -1;
229     }
230 }
231 
232 SIM_RC
dv_sockser_install(SIM_DESC sd)233 dv_sockser_install (SIM_DESC sd)
234 {
235   SIM_ASSERT (STATE_MAGIC (sd) == SIM_MAGIC_NUMBER);
236   if (sim_add_option_table (sd, NULL, sockser_options) != SIM_RC_OK)
237     return SIM_RC_FAIL;
238   sim_module_add_init_fn (sd, dv_sockser_init);
239   sim_module_add_uninstall_fn (sd, dv_sockser_uninstall);
240   return SIM_RC_OK;
241 }
242 
243 static int
connected_p(SIM_DESC sd)244 connected_p (SIM_DESC sd)
245 {
246   int numfds,flags;
247   struct timeval tv;
248   fd_set readfds;
249   struct sockaddr sockaddr;
250   socklen_t addrlen;
251 
252   if (sockser_listen_fd == -1)
253     return 0;
254 
255   if (sockser_fd >= 0)
256     {
257       /* FIXME: has client gone away? */
258       return 1;
259     }
260 
261   /* Not connected.  Connect with a client if there is one.  */
262 
263   FD_ZERO (&readfds);
264   FD_SET (sockser_listen_fd, &readfds);
265 
266   /* ??? One can certainly argue this should be done differently,
267      but for now this is sufficient.  */
268   tv.tv_sec = 0;
269   tv.tv_usec = sockser_timeout;
270 
271   numfds = select (sockser_listen_fd + 1, &readfds, 0, 0, &tv);
272   if (numfds <= 0)
273     return 0;
274 
275   addrlen = sizeof (sockaddr);
276   sockser_fd = accept (sockser_listen_fd, &sockaddr, &addrlen);
277   if (sockser_fd == -1)
278     return 0;
279 
280   /* Set non-blocking i/o.  */
281   flags = fcntl (sockser_fd, F_GETFL);
282   flags |= O_NONBLOCK | O_NDELAY;
283   if (fcntl (sockser_fd, F_SETFL, flags) == -1)
284     {
285       sim_io_eprintf (sd, "unable to set nonblocking i/o");
286       close (sockser_fd);
287       sockser_fd = -1;
288       return 0;
289     }
290   return 1;
291 }
292 
293 int
dv_sockser_status(SIM_DESC sd)294 dv_sockser_status (SIM_DESC sd)
295 {
296   int numrfds,numwfds,status;
297   struct timeval tv;
298   fd_set readfds,writefds;
299 
300   /* status to return if the socket isn't set up, or select fails */
301   status = DV_SOCKSER_INPUT_EMPTY | DV_SOCKSER_OUTPUT_EMPTY |
302 	   DV_SOCKSER_DISCONNECTED;
303 
304   if (! connected_p (sd))
305     return status;
306 
307   FD_ZERO (&readfds);
308   FD_ZERO (&writefds);
309   FD_SET (sockser_fd, &readfds);
310   FD_SET (sockser_fd, &writefds);
311 
312   /* ??? One can certainly argue this should be done differently,
313      but for now this is sufficient.  The read is done separately
314      from the write to enforce the delay which we heuristically set to
315      once every SOCKSER_TIMEOUT_FREQ tries.
316      No, this isn't great for SMP situations, blah blah blah.  */
317 
318   {
319     static int n;
320 #define SOCKSER_TIMEOUT_FREQ 42
321     if (++n == SOCKSER_TIMEOUT_FREQ)
322       n = 0;
323     if (n == 0)
324       {
325 	tv.tv_sec = 0;
326 	tv.tv_usec = sockser_timeout;
327 	numrfds = select (sockser_fd + 1, &readfds, 0, 0, &tv);
328 	tv.tv_sec = 0;
329 	tv.tv_usec = 0;
330 	numwfds = select (sockser_fd + 1, 0, &writefds, 0, &tv);
331       }
332     else /* do both selects at once */
333       {
334 	tv.tv_sec = 0;
335 	tv.tv_usec = 0;
336 	numrfds = numwfds = select (sockser_fd + 1, &readfds, &writefds, 0, &tv);
337       }
338   }
339 
340   status = 0;
341   if (numrfds <= 0 || ! FD_ISSET (sockser_fd, &readfds))
342     status |= DV_SOCKSER_INPUT_EMPTY;
343   if (numwfds <= 0 || FD_ISSET (sockser_fd, &writefds))
344     status |= DV_SOCKSER_OUTPUT_EMPTY;
345   return status;
346 }
347 
348 int
dv_sockser_write_buffer(SIM_DESC sd,const unsigned char * buffer,unsigned nr_bytes)349 dv_sockser_write_buffer (SIM_DESC sd, const unsigned char *buffer,
350 			 unsigned nr_bytes)
351 {
352   int n;
353 
354   if (! connected_p (sd))
355     return -1;
356   n = write (sockser_fd, buffer, nr_bytes);
357   if (n == -1)
358     {
359       if (errno == EPIPE)
360 	{
361 	  close (sockser_fd);
362 	  sockser_fd = -1;
363 	}
364       return -1;
365     }
366   if (n != nr_bytes)
367     return -1;
368   return nr_bytes;
369 }
370 
371 int
dv_sockser_write(SIM_DESC sd,unsigned char c)372 dv_sockser_write (SIM_DESC sd, unsigned char c)
373 {
374   return dv_sockser_write_buffer (sd, &c, 1);
375 }
376 
377 int
dv_sockser_read(SIM_DESC sd)378 dv_sockser_read (SIM_DESC sd)
379 {
380   unsigned char c;
381   int n;
382 
383   if (! connected_p (sd))
384     return -1;
385   n = read (sockser_fd, &c, 1);
386   /* ??? We're assuming semantics that may not be correct for all hosts.
387      In particular (from cvssrc/src/server.c), this assumes that we are using
388      BSD or POSIX nonblocking I/O.  System V nonblocking I/O returns zero if
389      there is nothing to read.  */
390   if (n == 0)
391     {
392       close (sockser_fd);
393       sockser_fd = -1;
394       return -1;
395     }
396   if (n != 1)
397     return -1;
398   return c;
399 }
400