xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/ser-tcp.c (revision 8b657b0747480f8989760d71343d6dd33f8d4cf9)
1 /* Serial interface for raw TCP connections on Un*x like systems.
2 
3    Copyright (C) 1992-2023 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #include "defs.h"
21 #include "serial.h"
22 #include "ser-base.h"
23 #include "ser-tcp.h"
24 #include "gdbcmd.h"
25 #include "cli/cli-decode.h"
26 #include "cli/cli-setshow.h"
27 #include "gdbsupport/filestuff.h"
28 #include "gdbsupport/netstuff.h"
29 
30 #include <sys/types.h>
31 
32 #ifdef HAVE_SYS_FILIO_H
33 #include <sys/filio.h>  /* For FIONBIO.  */
34 #endif
35 #ifdef HAVE_SYS_IOCTL_H
36 #include <sys/ioctl.h>  /* For FIONBIO.  */
37 #endif
38 
39 #include "gdbsupport/gdb_sys_time.h"
40 
41 #ifdef USE_WIN32API
42 #include <ws2tcpip.h>
43 #ifndef ETIMEDOUT
44 #define ETIMEDOUT WSAETIMEDOUT
45 #endif
46 /* Gnulib defines close too, but gnulib's replacement
47    doesn't call closesocket unless we import the
48    socketlib module.  */
49 #undef close
50 #define close(fd) closesocket (fd)
51 #define ioctl ioctlsocket
52 #else
53 #include <netinet/in.h>
54 #include <arpa/inet.h>
55 #include <netdb.h>
56 #include <sys/socket.h>
57 #include <netinet/tcp.h>
58 #endif
59 
60 #include <signal.h>
61 #include "gdbsupport/gdb_select.h"
62 #include <algorithm>
63 
64 #ifndef HAVE_SOCKLEN_T
65 typedef int socklen_t;
66 #endif
67 
68 /* For "set tcp" and "show tcp".  */
69 
70 static struct cmd_list_element *tcp_set_cmdlist;
71 static struct cmd_list_element *tcp_show_cmdlist;
72 
73 /* Whether to auto-retry refused connections.  */
74 
75 static bool tcp_auto_retry = true;
76 
77 /* Timeout period for connections, in seconds.  */
78 
79 static unsigned int tcp_retry_limit = 15;
80 
81 /* How many times per second to poll deprecated_ui_loop_hook.  */
82 
83 #define POLL_INTERVAL 5
84 
85 /* Helper function to wait a while.  If SOCK is not -1, wait on its
86    file descriptor.  Otherwise just wait on a timeout, updating
87    *POLLS.  Returns -1 on timeout or interrupt, otherwise the value of
88    select.  */
89 
90 static int
91 wait_for_connect (int sock, unsigned int *polls)
92 {
93   struct timeval t;
94   int n;
95 
96   /* While we wait for the connect to complete,
97      poll the UI so it can update or the user can
98      interrupt.  */
99   if (deprecated_ui_loop_hook && deprecated_ui_loop_hook (0))
100     {
101       errno = EINTR;
102       return -1;
103     }
104 
105   /* Check for timeout.  */
106   if (*polls > tcp_retry_limit * POLL_INTERVAL)
107     {
108       errno = ETIMEDOUT;
109       return -1;
110     }
111 
112   /* Back off to polling once per second after the first POLL_INTERVAL
113      polls.  */
114   if (*polls < POLL_INTERVAL)
115     {
116       t.tv_sec = 0;
117       t.tv_usec = 1000000 / POLL_INTERVAL;
118     }
119   else
120     {
121       t.tv_sec = 1;
122       t.tv_usec = 0;
123     }
124 
125   if (sock >= 0)
126     {
127       fd_set rset, wset, eset;
128 
129       FD_ZERO (&rset);
130       FD_SET (sock, &rset);
131       wset = rset;
132       eset = rset;
133 
134       /* POSIX systems return connection success or failure by signalling
135 	 wset.  Windows systems return success in wset and failure in
136 	 eset.
137 
138 	 We must call select here, rather than gdb_select, because
139 	 the serial structure has not yet been initialized - the
140 	 MinGW select wrapper will not know that this FD refers
141 	 to a socket.  */
142       n = select (sock + 1, &rset, &wset, &eset, &t);
143     }
144   else
145     /* Use gdb_select here, since we have no file descriptors, and on
146        Windows, plain select doesn't work in that case.  */
147     n = interruptible_select (0, NULL, NULL, NULL, &t);
148 
149   /* If we didn't time out, only count it as one poll.  */
150   if (n > 0 || *polls < POLL_INTERVAL)
151     (*polls)++;
152   else
153     (*polls) += POLL_INTERVAL;
154 
155   return n;
156 }
157 
158 /* Try to connect to the host represented by AINFO.  If the connection
159    succeeds, return its socket.  Otherwise, return -1 and set ERRNO
160    accordingly.  POLLS is used when 'connect' returns EINPROGRESS, and
161    we need to invoke 'wait_for_connect' to obtain the status.  */
162 
163 static int
164 try_connect (const struct addrinfo *ainfo, unsigned int *polls)
165 {
166   int sock = gdb_socket_cloexec (ainfo->ai_family, ainfo->ai_socktype,
167 				 ainfo->ai_protocol);
168 
169   if (sock < 0)
170     return -1;
171 
172   /* Set socket nonblocking.  */
173 #ifdef USE_WIN32API
174   u_long ioarg = 1;
175 #else
176   int ioarg = 1;
177 #endif
178 
179   ioctl (sock, FIONBIO, &ioarg);
180 
181   /* Use Non-blocking connect.  connect() will return 0 if connected
182      already.  */
183   if (connect (sock, ainfo->ai_addr, ainfo->ai_addrlen) < 0)
184     {
185 #ifdef USE_WIN32API
186       int err = WSAGetLastError();
187 #else
188       int err = errno;
189 #endif
190 
191       /* If we've got a "connection refused" error, just return
192 	 -1.  The caller will know what to do.  */
193       if (
194 #ifdef USE_WIN32API
195 	  err == WSAECONNREFUSED
196 #else
197 	  err == ECONNREFUSED
198 #endif
199 	  )
200 	{
201 	  close (sock);
202 	  errno = err;
203 	  return -1;
204 	}
205 
206       if (
207 	  /* Any other error (except EINPROGRESS) will be "swallowed"
208 	     here.  We return without specifying a return value, and
209 	     set errno if the caller wants to inspect what
210 	     happened.  */
211 #ifdef USE_WIN32API
212 	  /* Under Windows, calling "connect" with a non-blocking socket
213 	     results in WSAEWOULDBLOCK, not WSAEINPROGRESS.  */
214 	  err != WSAEWOULDBLOCK
215 #else
216 	  err != EINPROGRESS
217 #endif
218 	  )
219 	{
220 	  close (sock);
221 	  errno = err;
222 	  return -1;
223 	}
224 
225       /* Looks like we need to wait for the connect.  */
226       int n;
227 
228       do
229 	n = wait_for_connect (sock, polls);
230       while (n == 0);
231 
232       if (n < 0)
233 	{
234 	  int saved_errno = errno;
235 
236 	  /* A negative value here means that we either timed out or
237 	     got interrupted by the user.  Just return.  */
238 	  close (sock);
239 	  errno = saved_errno;
240 	  return -1;
241 	}
242     }
243 
244   /* Got something.  Is it an error?  */
245   int err;
246   socklen_t len = sizeof (err);
247 
248   /* On Windows, the fourth parameter to getsockopt is a "char *";
249      on UNIX systems it is generally "void *".  The cast to "char *"
250      is OK everywhere, since in C++ any data pointer type can be
251      implicitly converted to "void *".  */
252   int ret = getsockopt (sock, SOL_SOCKET, SO_ERROR, (char *) &err, &len);
253 
254   if (ret < 0)
255     {
256       int saved_errno = errno;
257 
258       close (sock);
259       errno = saved_errno;
260       return -1;
261     }
262   else if (ret == 0 && err != 0)
263     {
264       close (sock);
265       errno = err;
266       return -1;
267     }
268 
269   /* The connection succeeded.  Return the socket.  */
270   return sock;
271 }
272 
273 /* Open a tcp socket.  */
274 
275 int
276 net_open (struct serial *scb, const char *name)
277 {
278   struct addrinfo hint;
279   struct addrinfo *ainfo;
280 
281   memset (&hint, 0, sizeof (hint));
282   /* Assume no prefix will be passed, therefore we should use
283      AF_UNSPEC.  */
284   hint.ai_family = AF_UNSPEC;
285   hint.ai_socktype = SOCK_STREAM;
286   hint.ai_protocol = IPPROTO_TCP;
287 
288   parsed_connection_spec parsed = parse_connection_spec (name, &hint);
289 
290   if (parsed.port_str.empty ())
291     error (_("Missing port on hostname '%s'"), name);
292 
293   int r = getaddrinfo (parsed.host_str.c_str (),
294 		       parsed.port_str.c_str (),
295 		       &hint, &ainfo);
296 
297   if (r != 0)
298     {
299       gdb_printf (gdb_stderr, _("%s: cannot resolve name: %s\n"),
300 		  name, gai_strerror (r));
301       errno = ENOENT;
302       return -1;
303     }
304 
305   scoped_free_addrinfo free_ainfo (ainfo);
306 
307   /* Flag to indicate whether we've got a connection refused.  It will
308      be true if any of the connections tried was refused.  */
309   bool got_connrefused;
310   /* If a connection succeeds, SUCCESS_AINFO will point to the
311      'struct addrinfo' that succeed.  */
312   struct addrinfo *success_ainfo = NULL;
313   unsigned int polls = 0;
314 
315   /* Assume the worst.  */
316   scb->fd = -1;
317 
318   do
319     {
320       got_connrefused = false;
321 
322       for (addrinfo *iter = ainfo; iter != NULL; iter = iter->ai_next)
323 	{
324 	  /* Iterate over the list of possible addresses to connect
325 	     to.  For each, we'll try to connect and see if it
326 	     succeeds.  */
327 	  int sock = try_connect (iter, &polls);
328 
329 	  if (sock >= 0)
330 	    {
331 	      /* We've gotten a successful connection.  Save its
332 		 'struct addrinfo', the socket, and break.  */
333 	      success_ainfo = iter;
334 	      scb->fd = sock;
335 	      break;
336 	    }
337 	  else if (
338 #ifdef USE_WIN32API
339 	  errno == WSAECONNREFUSED
340 #else
341 	  errno == ECONNREFUSED
342 #endif
343 		   )
344 	    got_connrefused = true;
345 	}
346     }
347   /* Just retry if:
348 
349      - tcp_auto_retry is true, and
350      - We haven't gotten a connection yet, and
351      - Any of our connection attempts returned with ECONNREFUSED, and
352      - wait_for_connect signals that we can keep going.  */
353   while (tcp_auto_retry
354 	 && success_ainfo == NULL
355 	 && got_connrefused
356 	 && wait_for_connect (-1, &polls) >= 0);
357 
358   if (success_ainfo == NULL)
359     {
360       net_close (scb);
361       return -1;
362     }
363 
364   /* Turn off nonblocking.  */
365 #ifdef USE_WIN32API
366   u_long ioarg = 0;
367 #else
368   int ioarg = 0;
369 #endif
370 
371   ioctl (scb->fd, FIONBIO, &ioarg);
372 
373   if (success_ainfo->ai_protocol == IPPROTO_TCP)
374     {
375       /* Disable Nagle algorithm.  Needed in some cases.  */
376       int tmp = 1;
377 
378       setsockopt (scb->fd, IPPROTO_TCP, TCP_NODELAY,
379 		  (char *) &tmp, sizeof (tmp));
380     }
381 
382 #ifdef SIGPIPE
383   /* If we don't do this, then GDB simply exits
384      when the remote side dies.  */
385   signal (SIGPIPE, SIG_IGN);
386 #endif
387 
388   return 0;
389 }
390 
391 void
392 net_close (struct serial *scb)
393 {
394   if (scb->fd == -1)
395     return;
396 
397   close (scb->fd);
398   scb->fd = -1;
399 }
400 
401 int
402 net_read_prim (struct serial *scb, size_t count)
403 {
404   /* Need to cast to silence -Wpointer-sign on MinGW, as Winsock's
405      'recv' takes 'char *' as second argument, while 'scb->buf' is
406      'unsigned char *'.  */
407   return recv (scb->fd, (char *) scb->buf, count, 0);
408 }
409 
410 int
411 net_write_prim (struct serial *scb, const void *buf, size_t count)
412 {
413   /* On Windows, the second parameter to send is a "const char *"; on
414      UNIX systems it is generally "const void *".  The cast to "const
415      char *" is OK everywhere, since in C++ any data pointer type can
416      be implicitly converted to "const void *".  */
417   return send (scb->fd, (const char *) buf, count, 0);
418 }
419 
420 int
421 ser_tcp_send_break (struct serial *scb)
422 {
423   /* Send telnet IAC and BREAK characters.  */
424   return (serial_write (scb, "\377\363", 2));
425 }
426 
427 #ifndef USE_WIN32API
428 
429 /* The TCP ops.  */
430 
431 static const struct serial_ops tcp_ops =
432 {
433   "tcp",
434   net_open,
435   net_close,
436   NULL,
437   ser_base_readchar,
438   ser_base_write,
439   ser_base_flush_output,
440   ser_base_flush_input,
441   ser_tcp_send_break,
442   ser_base_raw,
443   ser_base_get_tty_state,
444   ser_base_copy_tty_state,
445   ser_base_set_tty_state,
446   ser_base_print_tty_state,
447   ser_base_setbaudrate,
448   ser_base_setstopbits,
449   ser_base_setparity,
450   ser_base_drain_output,
451   ser_base_async,
452   net_read_prim,
453   net_write_prim
454 };
455 
456 #endif /* USE_WIN32API */
457 
458 void _initialize_ser_tcp ();
459 void
460 _initialize_ser_tcp ()
461 {
462 #ifdef USE_WIN32API
463   /* Do nothing; the TCP serial operations will be initialized in
464      ser-mingw.c.  */
465 #else
466   serial_add_interface (&tcp_ops);
467 #endif /* USE_WIN32API */
468 
469   add_setshow_prefix_cmd ("tcp", class_maintenance,
470 			  _("\
471 TCP protocol specific variables.\n\
472 Configure variables specific to remote TCP connections."),
473 			  _("\
474 TCP protocol specific variables.\n\
475 Configure variables specific to remote TCP connections."),
476 			  &tcp_set_cmdlist, &tcp_show_cmdlist,
477 			  &setlist, &showlist);
478 
479   add_setshow_boolean_cmd ("auto-retry", class_obscure,
480 			   &tcp_auto_retry, _("\
481 Set auto-retry on socket connect."), _("\
482 Show auto-retry on socket connect."),
483 			   NULL, NULL, NULL,
484 			   &tcp_set_cmdlist, &tcp_show_cmdlist);
485 
486   add_setshow_uinteger_cmd ("connect-timeout", class_obscure,
487 			    &tcp_retry_limit, _("\
488 Set timeout limit in seconds for socket connection."), _("\
489 Show timeout limit in seconds for socket connection."), _("\
490 If set to \"unlimited\", GDB will keep attempting to establish a\n\
491 connection forever, unless interrupted with Ctrl-c.\n\
492 The default is 15 seconds."),
493 			    NULL, NULL,
494 			    &tcp_set_cmdlist, &tcp_show_cmdlist);
495 }
496