io.c 35.3 KB
Newer Older
Niels Möller's avatar
Niels Möller committed
1
/* io.c
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 *
 * $Id$ */

/* lsh, an implementation of the ssh protocol
 *
 * Copyright (C) 1998 Niels Mller
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
J.H.M. Dassen's avatar
J.H.M. Dassen committed
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Niels Möller's avatar
Niels Möller committed
22
23
 */

24
#include "io.h"
25
26

#include "format.h"
27
28
29
#include "werror.h"
#include "xalloc.h"

Niels Möller's avatar
Niels Möller committed
30
31
32
#include <assert.h>
#include <string.h>

33
#if HAVE_UNISTD_H
Niels Möller's avatar
Niels Möller committed
34
#include <unistd.h>
35
#endif
36
37

#ifdef HAVE_POLL
38
39
40
41
42
# if HAVE_POLL_H
#  include <poll.h>
# elif HAVE_SYS_POLL_H
#  include <sys/poll.h>
# endif
43
#else
44
# include "jpoll.h"
45
46
#endif

47
48
49
50
51
52
53
/* Workaround for some version of FreeBSD. */
#ifdef POLLRDNORM
# define MY_POLLIN (POLLIN | POLLRDNORM)
#else /* !POLLRDNORM */
# define MY_POLLIN POLLIN
#endif /* !POLLRDNORM */

Niels Möller's avatar
Niels Möller committed
54
55
56
57
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
58
#include <sys/un.h>
Niels Möller's avatar
Niels Möller committed
59
#include <arpa/inet.h>
60
#include <signal.h>
61
62
#include <sys/stat.h>

Niels Möller's avatar
Niels Möller committed
63

64
#define GABA_DEFINE
65
#include "io.h.x"
66
#undef GABA_DEFINE
67
68
69

#include "io.c.x"

Niels Möller's avatar
Niels Möller committed
70
71
72

/* Backend loop */

Niels Möller's avatar
Niels Möller committed
73
74
75
76
77
/* If there's nothing to do for this amount of time (ms), do
 * spontaneous gc. */

#define IDLE_TIME 100

Niels Möller's avatar
Niels Möller committed
78
79
80
81
int io_iter(struct io_backend *b)
{
  unsigned long nfds; /* FIXME: Should be nfds_t if that type is defined */
  struct pollfd *fds;
82
83
  struct lsh_fd **active_fds;
  
Niels Möller's avatar
Niels Möller committed
84
85
  /* FIXME: Callouts not implemented */
  /* int timeout; */
Niels Möller's avatar
Niels Möller committed
86
87
88
  int res;

  {
89
90
91
    struct lsh_fd *fd;
    int need_close;
    
92
    /* Prepare fd:s. This phase calls the prepare-methods, also closes
Niels Möller's avatar
Niels Möller committed
93
94
     * and unlinks any fd:s that should be closed, and also counts how
     * many fd:s there are. */
95
96

    for (fd = b->files; fd; fd = fd->next)
Niels Möller's avatar
Niels Möller committed
97
      {
98
	if (fd->super.alive && fd->prepare)
99
	  FD_PREPARE(fd);
100
101
102
103
104
105
106
107
108
109
110
111
112
113
      }
    
    /* Note that calling a close callback might cause other files to
     * be closed as well, so we need a double loop.
     *
     * FIXME: How can we improve this? We could keep a stack of closed
     * files, but that will require backpointers from the fd:s to the
     * backend (so that kill_fd() can find the top of the stack). */

    do
      {
	struct lsh_fd **fd_p;
	need_close = 0;
	nfds = 0;
Niels Möller's avatar
Niels Möller committed
114
	
115
	for(fd_p = &b->files; (fd = *fd_p); )
Niels Möller's avatar
Niels Möller committed
116
	  {
117
	    if (!fd->super.alive)
Niels Möller's avatar
Niels Möller committed
118
	      {
119
120
121
122
123
124
125
126
127
128
		if (fd->fd < 0)
		  /* Unlink the file object, but don't close any
		   * underlying file. */
		  ;
		else
		  {
		    /* Used by write fd:s to make sure that writing to its
		     * buffer fails. */
		    if (fd->write_close)
		      FD_WRITE_CLOSE(fd);
Niels Möller's avatar
Niels Möller committed
129
		
130
131
132
133
134
135
		    if (fd->close_callback)
		      {
			CLOSE_CALLBACK(fd->close_callback, fd->close_reason);
			need_close = 1;
		      }
		    trace("io.c: Closing fd %i.\n", fd->fd);
Niels Möller's avatar
Niels Möller committed
136
		
137
138
139
140
141
		    close(fd->fd);
		  }
		/* Unlink this fd */
		*fd_p = fd->next;
		continue;
Niels Möller's avatar
Niels Möller committed
142
	      }
143

144
145
	    if (fd->want_read || fd->want_write)
	      nfds++;
146

147
148
149
	    fd_p = &fd->next;
	  }
      } while (need_close);
Niels Möller's avatar
Niels Möller committed
150
151
152
153
154
155
156
157
  }

  if (!nfds)
    /* Nothing more to do.
     *
     * NOTE: There might be some callouts left, but we won't wait for them. */
    return 0;

158
159
160
  fds = alloca(sizeof(struct pollfd) * nfds);
  active_fds = alloca(sizeof(struct lsh_fd *) *nfds);
  
Niels Möller's avatar
Niels Möller committed
161
162
163
  /* Fill out fds-array */
  {
    struct lsh_fd *fd;
164
    unsigned long i;
Niels Möller's avatar
Niels Möller committed
165
166
    int all_events = 0;
    
167
    for (fd = b->files, i = 0; fd; fd = fd->next)
Niels Möller's avatar
Niels Möller committed
168
      {
169
170
	assert(fd->super.alive);
	
171
172
	if (fd->want_read || fd->want_write)
	  {
173
174
	    assert(i < nfds);

175
	    active_fds[i] = fd;
Niels Möller's avatar
Niels Möller committed
176

177
178
179
180
	    fds[i].fd = fd->fd;
	    fds[i].events = 0;
	    
	    if (fd->want_read)
181
	      fds[i].events |= MY_POLLIN;
Niels Möller's avatar
Niels Möller committed
182

183
184
	    if (fd->want_write)
	      fds[i].events |= POLLOUT;
Niels Möller's avatar
Niels Möller committed
185

186
187
188
	    all_events |= fds[i].events;
	    i++;
	  }
Niels Möller's avatar
Niels Möller committed
189
190
      }
    assert(i == nfds);
191
    assert(all_events);
Niels Möller's avatar
Niels Möller committed
192
193
  }

Niels Möller's avatar
Niels Möller committed
194
  res = poll(fds, nfds, IDLE_TIME);
Niels Möller's avatar
Niels Möller committed
195

Niels Möller's avatar
Niels Möller committed
196
197
198
199
200
  if (!res)
    {
      gc_maybe(&b->super, 0);
      res = poll(fds, nfds, -1);
    }
201
202
  else
    gc_maybe(&b->super, 1);
Niels Möller's avatar
Niels Möller committed
203
  
Niels Möller's avatar
Niels Möller committed
204
205
206
207
208
209
210
211
212
213
214
215
  if (!res)
    {
      /* Callouts are not implemented */
      fatal("Unexpected timeout\n");
    }
  if (res < 0)
    switch(errno)
      {
      case EAGAIN:
      case EINTR:
	return 1;
      default:
216
	fatal("io_iter: poll failed: %z", STRERROR(errno));
Niels Möller's avatar
Niels Möller committed
217
218
219
220
      }
  
  {
    /* Do io. Note that the callback functions may add new fds to the
221
222
     * head of the list, or clear the alive flag on any fd. But this
     * is less of a problem now, as we use the active_fd array.*/
Niels Möller's avatar
Niels Möller committed
223

224
    /* struct lsh_fd *fd; */
225
    unsigned long i;
Niels Möller's avatar
Niels Möller committed
226
    
227
    for(i=0; i<nfds; i++)
Niels Möller's avatar
Niels Möller committed
228
      {
229
	struct lsh_fd *fd = active_fds[i];
Niels Möller's avatar
Niels Möller committed
230
	assert(i<nfds);
231
232

	debug("io.c: poll for fd %i: events = 0x%xi, revents = 0x%xi.\n",
233
 	      fds[i].fd, fds[i].events, fds[i].revents);
Niels Möller's avatar
Niels Möller committed
234
	
235
	if (!fd->super.alive)
Niels Möller's avatar
Niels Möller committed
236
237
	  continue;

238
239
240
	/* On systems without poll(), we use jpoll.c to emulate some
	 * of poll(), but we lack POLLNVAL, POLLPRI and POLLHUP. */
#ifdef POLLNVAL
241
242
243
244
245
246
247
248
	if (fds[i].revents & POLLNVAL)
	  {
	    werror("io.c: poll request on fd %i, for events of type %xi\n"
		   "      return POLLNVAL, revents = %xi\n",
		   fds[i].fd, fds[i].events, fds[i].revents);
	    kill_fd(fd);
	    continue;
	  }
249
#endif /* POLLNVAL */
250

251
#ifdef POLLHUP
252
253
254
255
256
257
258
	/* FIXME: According to Solaris' man page, POLLHUP is mutually
	 * exclusive with POLLOUT, but orthogonal to POLLIN.
	 *
	 * However, on my system (sparc-linux) POLLHUP is set when we
	 * get EOF on an fd we are reading. This will cause an i/o
	 * exception to be raised rather than the ordinary EOF
	 * handling. */
259
260
	if (fds[i].revents & POLLHUP)
	  {
261
262
	    if (fd->want_write)
	      /* Will raise an i/o error */
263
	      FD_WRITE(fd);
264
265
266
	    else if (fd->want_read)
	      /* Ought to behave like EOF, but might raise an i/o
	       * error instead. */
267
	      FD_READ(fd);
268
	    else
269
270
271
272
	      {
		werror("io.c: poll said POLLHUP on an inactive fd.\n");
		close_fd(fd, CLOSE_EOF);
	      }
273
274
	    continue;
	  }
275
#endif /* POLLHUP */
276

277
#ifdef POLLPRI
278
279
280
	if (fds[i].revents & POLLPRI)
	  {
	    werror("io.c: Peer is trying to send Out of Band data. Hanging up.\n");
281
282

	    /* FIXME: Should we raise any exception here? */
283
284
285
286
287

	    close_fd(fd, CLOSE_PROTOCOL_FAILURE); 

	    continue;
	  }
288
#endif /* POLLPRI */
Niels Möller's avatar
Niels Möller committed
289
	if (fds[i].revents & POLLOUT)
290
	  FD_WRITE(fd);
Niels Möller's avatar
Niels Möller committed
291

292
	if (!fd->super.alive)
Niels Möller's avatar
Niels Möller committed
293
294
	  continue;

295
	if (fds[i].revents & MY_POLLIN)
296
	  FD_READ(fd);
Niels Möller's avatar
Niels Möller committed
297
298
299
300
301
302
      }
    assert(i == nfds);
  }

  return 1;
}
Niels Möller's avatar
Niels Möller committed
303

Niels Möller's avatar
Niels Möller committed
304

Niels Möller's avatar
Niels Möller committed
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
void io_run(struct io_backend *b)
{
  struct sigaction pipe;
  memset(&pipe, 0, sizeof(pipe));

  pipe.sa_handler = SIG_IGN;
  sigemptyset(&pipe.sa_mask);
  pipe.sa_flags = 0;
  
  if (sigaction(SIGPIPE, &pipe, NULL) < 0)
    fatal("Failed to ignore SIGPIPE.\n");
  
  while(io_iter(b))
    ;
}

void init_backend(struct io_backend *b)
{
  b->files = NULL;
#if 0
  b->callouts = 0;
#endif
}


/* Read-related callbacks */

332
333
334
static void
do_buffered_read(struct io_callback *s,
		 struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
335
336
337
338
339
340
341
342
343
344
345
346
347
348
{
  CAST(io_buffered_read, self, s);
  UINT8 *buffer = alloca(self->buffer_size);
  int res = read(fd->fd, buffer, self->buffer_size);

  if (res < 0)
    switch(errno)
      {
      case EINTR:
	break;
      case EWOULDBLOCK:
	werror("io.c: read_callback: Unexpected EWOULDBLOCK\n");
	break;
      case EPIPE:
349
350
351
	/* Getting EPIPE from read() seems strange, but appearantly
	 * it happens sometimes. */
	werror("Unexpected EPIPE.\n");
Niels Möller's avatar
Niels Möller committed
352
      default:
Niels Möller's avatar
Niels Möller committed
353
354
355
	EXCEPTION_RAISE(fd->e, 
			make_io_exception(EXC_IO_READ, fd,
					  errno, NULL));
Niels Möller's avatar
Niels Möller committed
356
357
358
359
360
361
	break;
      }
  else if (res > 0)
    {
      UINT32 left = res;
    
362
      while (fd->super.alive && fd->read && left)
Niels Möller's avatar
Niels Möller committed
363
364
	{
	  UINT32 done;
Niels Möller's avatar
Niels Möller committed
365

366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
	  /* FIXME: What to do if want_read is false?
	   * To improve the connection_lock() mechanism,
	   * it must be possible to temporarily stop reading, which means that
	   * fd->want_read has to be cleared.
	   *
	   * But when doing this, we have to keep the data that we
	   * have read, some of which is buffered here, on the stack,
	   * and the rest inside the read-handler.
	   *
	   * There are two alternatives: Save our buffer here, or
	   * continue looping, letting the read-handler process it
	   * into packets. In the latter case, the ssh_connection
	   * could keep a queue of waiting packets, but it would still
	   * have to clear the want_read flag, to prevent that queue
	   * from growing arbitrarily large.
	   */

	  assert(fd->want_read); assert(self->handler);
Niels Möller's avatar
Niels Möller committed
384
385

	  /* NOTE: This call may replace self->handler */
Niels Möller's avatar
Niels Möller committed
386
	  done = READ_HANDLER(self->handler, left, buffer);
Niels Möller's avatar
Niels Möller committed
387
388
389

	  buffer += done;
	  left -= done;
390
391
392
393
394
395
396
397

	  if (fd->want_read && !self->handler)
	    {
	      werror("do_buffered_read: Handler disappeared! Ignoring %i bytes\n",
		     left);
	      fd->want_read = 0;
	      return;
	    }
Niels Möller's avatar
Niels Möller committed
398
399
400
401
402
403
404
	}

      if (left)
	verbose("read_buffered(): fd died, %i buffered bytes discarded\n",
		left);
    }
  else
405
406
407
408
409
410
411
    {
      /* We have read EOF. Pass available == 0 to the handler */
      assert(fd->super.alive);
      assert(fd->read);
      assert(fd->want_read);
      assert(self->handler);

412
      close_fd_nicely(fd, 0);
413
414
415
      READ_HANDLER(self->handler, 0, NULL);
    }
	
Niels Möller's avatar
Niels Möller committed
416
417
}

418
struct io_callback *
Niels Möller's avatar
Niels Möller committed
419
420
421
422
423
make_buffered_read(UINT32 buffer_size,
		   struct read_handler *handler)
{
  NEW(io_buffered_read, self);

424
  self->super.f = do_buffered_read;
Niels Möller's avatar
Niels Möller committed
425
426
427
428
429
430
  self->buffer_size = buffer_size;
  self->handler = handler;

  return &self->super;
}

431
432
433
static void
do_consuming_read(struct io_callback *c,
		  struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
434
{
435
  CAST_SUBTYPE(io_consuming_read, self, c);
Niels Möller's avatar
Niels Möller committed
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
  UINT32 wanted = READ_QUERY(self);

  if (!wanted)
    {
      fd->want_read = 0;
    }
  else
    {
      struct lsh_string *s = lsh_string_alloc(wanted);
      int res = read(fd->fd, s->data, wanted);

      if (res < 0)
	switch(errno)
	  {
	  case EINTR:
	    break;
	  case EWOULDBLOCK:
	    werror("io.c: read_consume: Unexpected EWOULDBLOCK\n");
	    break;
	  case EPIPE:
456
457
458
459
	    /* FIXME: I don't understand why reading should return
	     * EPIPE, but it happens occasionally under linux. Perhaps
	     * we should treat it as EOF instead? */
	    werror("io.c: read_consume: Unexpected EPIPE.\n");
Niels Möller's avatar
Niels Möller committed
460
	  default:
Niels Möller's avatar
Niels Möller committed
461
462
463
	    EXCEPTION_RAISE(fd->e, 
			    make_io_exception(EXC_IO_READ,
					      fd, errno, NULL));
Niels Möller's avatar
Niels Möller committed
464
465
466
467
468
	    break;
	  }
      else if (res > 0)
	{
	  s->length = res;
469
	  A_WRITE(self->consumer, s);
Niels Möller's avatar
Niels Möller committed
470
471
	}
      else
472
473
474
475
476
	{
	  close_fd_nicely(fd, 0);
	  A_WRITE(self->consumer, NULL);
	}
      
Niels Möller's avatar
Niels Möller committed
477
478
479
480
481
482
483
484
    }
}

/* NOTE: Doesn't initialize the query field. That should be done in
 * the subclass's constructor. */
void init_consuming_read(struct io_consuming_read *self,
			 struct abstract_write *consumer)
{
485
  self->super.f = do_consuming_read;
Niels Möller's avatar
Niels Möller committed
486
487
  self->consumer = consumer;
}
488

489

Niels Möller's avatar
Niels Möller committed
490
/* Write related callbacks */
491
492
493
static void
do_write_callback(struct io_callback *s UNUSED,
		  struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
494
{
495
  /* CAST(io_write_callback, self, s); */
Niels Möller's avatar
Niels Möller committed
496
497
498
  UINT32 size;
  int res;
  
499
500
  size = MIN(fd->write_buffer->end - fd->write_buffer->start,
	     fd->write_buffer->block_size);
Niels Möller's avatar
Niels Möller committed
501
502
503
  assert(size);
  
  res = write(fd->fd,
504
	      fd->write_buffer->buffer + fd->write_buffer->start,
Niels Möller's avatar
Niels Möller committed
505
506
507
508
509
510
511
512
513
514
	      size);
  if (!res)
    fatal("Closed?");
  if (res < 0)
    switch(errno)
      {
      case EINTR:
      case EAGAIN:
	break;
      case EPIPE:
515
516
	debug("io.c: Broken pipe.\n");
	close_fd(fd, CLOSE_BROKEN_PIPE);
Niels Möller's avatar
Niels Möller committed
517
518
	break;
      default:
519
	werror("io.c: write failed, %z\n", STRERROR(errno));
Niels Möller's avatar
Niels Möller committed
520
521
	EXCEPTION_RAISE(fd->e,
			make_io_exception(EXC_IO_WRITE, fd, errno, NULL));
522
	close_fd(fd, CLOSE_WRITE_FAILED);
Niels Möller's avatar
Niels Möller committed
523
524
525
526
	
	break;
      }
  else
527
    write_buffer_consume(fd->write_buffer, res);
Niels Möller's avatar
Niels Möller committed
528
}  
529

530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
static struct io_callback io_write_callback =
{ STATIC_HEADER, do_write_callback };

static void
do_write_prepare(struct lsh_fd *fd)
{
  /* CAST(io_write_callback, self, s); */

  assert(fd->write_buffer);

  if (! (fd->want_write = write_buffer_pre_write(fd->write_buffer))
      && fd->write_buffer->closed)
    close_fd(fd, CLOSE_EOF);
}

static void
do_write_close(struct lsh_fd *fd)
{
  /* CAST(io_write_callback, self, s); */

  assert(fd->write_buffer);

  write_buffer_close(fd->write_buffer);
}

struct listen_value *
make_listen_value(struct lsh_fd *fd,
		  struct address_info *peer)
{
  NEW(listen_value, self);

  self->fd = fd;
  self->peer = peer;

  return self;
}

Niels Möller's avatar
Niels Möller committed
567
568
569

/* Listen callback */

570
571
572
573
574
575
576
577
578
579
/* GABA:
   (class
     (name io_listen_callback)
     (super io_callback)
     (vars
       (backend object io_backend)
       (c object command_continuation)
       (e object exception_handler)))
*/

Niels Möller's avatar
Niels Möller committed
580
static void
581
do_listen_callback(struct io_callback *s,
Niels Möller's avatar
Niels Möller committed
582
		   struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
583
{
584
  CAST(io_listen_callback, self, s);
585
586
587
588
589
590

#if WITH_IPV6
  struct sockaddr_storage peer;
#else
  struct sockaddr peer;
#endif
591
592

  socklen_t addr_len = sizeof(peer);
Niels Möller's avatar
Niels Möller committed
593
  int conn;
594

Niels Möller's avatar
Niels Möller committed
595
596
597
  conn = accept(fd->fd,
		(struct sockaddr *) &peer, &addr_len);
  if (conn < 0)
598
    {
599
      werror("io.c: accept() failed, %z", STRERROR(errno));
Niels Möller's avatar
Niels Möller committed
600
      return;
601
    }
602
  trace("io.c: accept() on fd %i\n", conn);
603
604
605
606
607
  COMMAND_RETURN(self->c,
		 make_listen_value(make_lsh_fd(self->backend,
					       conn, self->e),
				   sockaddr2info(addr_len,
						 (struct sockaddr *) &peer)));
Niels Möller's avatar
Niels Möller committed
608
}
609

610
611
612
613
614
615
616
617
618
619
620
621
622
struct io_callback *
make_listen_callback(struct io_backend *backend,
		     struct command_continuation *c,
		     struct exception_handler *e)
{
  NEW(io_listen_callback, self);
  self->super.f = do_listen_callback;
  self->backend = backend;
  self->c = c;
  self->e = e;
  
  return &self->super;
}
Niels Möller's avatar
Niels Möller committed
623

Niels Möller's avatar
Niels Möller committed
624
625
626

/* Connect callback */

627
628
629
630
631
632
633
634
635
636
637
/* GABA:
   (class
     (name io_connect_callback)
     (super io_callback)
     (vars
       (c object command_continuation)))
*/

static void
do_connect_callback(struct io_callback *s,
		    struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
638
{
639
  CAST(io_connect_callback, self, s);
640
  int socket_error;
641
  socklen_t len = sizeof(socket_error);
642
  
643
  /* Check if the connection was successful */
644
645
  if ((getsockopt(fd->fd, SOL_SOCKET, SO_ERROR,
		  (char *) &socket_error, &len) < 0)
646
      || socket_error)
647
    {
648
      debug("io.c: connect_callback: Connect failed.\n");
Niels Möller's avatar
Niels Möller committed
649
      EXCEPTION_RAISE(fd->e,
650
		      make_io_exception(EXC_IO_CONNECT, fd, 0, "connect() failed."));
651
      kill_fd(fd);
652
653
    }
  else
Niels Möller's avatar
Niels Möller committed
654
    {
655
656
657
      fd->write = NULL;
      fd->want_write = 0;
      COMMAND_RETURN(self->c, fd);
658
    }
659
660
661
662
663
664
665
666
667
668
669
}

static struct io_callback *
make_connect_callback(struct command_continuation *c)
{
  NEW(io_connect_callback, self);

  self->super.f = do_connect_callback;
  self->c = c;

  return &self->super;
670
671
}

672

Niels Möller's avatar
Niels Möller committed
673
/* This function is called if a connection this file somehow depends
674
675
676
677
678
679
680
681
 * on disappears. For instance, the connection may have spawned a
 * child process, and this file may be the stdin of that process. */

/* To kill a file, mark it for closing and the backend will do the work. */
static void do_kill_fd(struct resource *r)
{
  CAST_SUBTYPE(lsh_fd, fd, r);

Niels Möller's avatar
Niels Möller committed
682
683
684
  /* NOTE: We use the zero close reason for files killed this way.
   * Close callbacks are still called, but they should probably not do
   * anything if reason == 0. */
685
686

  /* FIXME: Should we use close_fd() or close_fd_nicely() ? */
687
688
689
690
  if (r->alive)
    close_fd(fd, 0);
}

691
692
693
694
695
696
697
698
699
700
/* Closes the file on i/o errors, and passes the exception on */

static void
do_exc_io_handler(struct exception_handler *self,
		  const struct exception *x)
{
  if (x->type & EXC_IO)
    {
      CAST_SUBTYPE(io_exception, e, x);

701
702
      if (e->fd)
	close_fd(e->fd, 0);
703
704
705
706
707
    }
  EXCEPTION_RAISE(self->parent, x);
  return;
}

Niels Möller's avatar
Niels Möller committed
708
/* Initializes a file structure, and adds it to the backend's list. */
Niels Möller's avatar
Niels Möller committed
709
710
static void init_file(struct io_backend *b, struct lsh_fd *f, int fd,
		      struct exception_handler *e)
Niels Möller's avatar
Niels Möller committed
711
712
{
  f->fd = fd;
Niels Möller's avatar
Niels Möller committed
713

714
  f->e = make_exception_handler(do_exc_io_handler, e, HANDLER_CONTEXT);
715
  
Niels Möller's avatar
Niels Möller committed
716
717
718
719
  f->close_reason = -1; /* Invalid reason */
  f->close_callback = NULL;

  f->prepare = NULL;
720

Niels Möller's avatar
Niels Möller committed
721
722
723
724
725
  f->want_read = 0;
  f->read = NULL;

  f->want_write = 0;
  f->write = NULL;
726
727
  f->write_close = NULL;
  
728
729
  f->super.alive = 1;
  f->super.kill = do_kill_fd;
Niels Möller's avatar
Niels Möller committed
730
731
732
733

  f->next = b->files;
  b->files = f;
}
734

735
#if 0
736
737
738
/* Blocking read from a file descriptor (i.e. don't use the backend).
 * The fd should *not* be in non-blocking mode. */

Niels Möller's avatar
Niels Möller committed
739
740
741
742
743
744
745
746
747
/* FIXME: How to do this when moving from return codes to exceptions? */

/* FIXME: The entire blocking_read mechanism should be replaced by
 * ordinary commands and non-blocking i/o command. Right now, it is
 * used to read key-files, so that change probably has to wait until
 * the parser is rewritten. */


#define BLOCKING_READ_SIZE 4096
748

Niels Möller's avatar
Niels Möller committed
749
int blocking_read(int fd, struct read_handler *handler)
750
{  
Niels Möller's avatar
Niels Möller committed
751
  UINT8 *buffer = alloca(BLOCKING_READ_SIZE);
Niels Möller's avatar
Niels Möller committed
752
  
Niels Möller's avatar
Niels Möller committed
753
  for (;;)
754
    {
Niels Möller's avatar
Niels Möller committed
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
      int res = read(fd, buffer, BLOCKING_READ_SIZE);
      if (res < 0)
	switch(errno)
	  {
	  case EINTR:
	    break;
	  case EWOULDBLOCK:
	    fatal("blocking_read: Unexpected EWOULDBLOCK! fd in non-blocking mode?\n");
	  default:
	    werror("blocking_read: read() failed (errno = %i): %z\n",
		   errno, strerror(errno));
	    return 0;
	  }
      else if (!res)
	return 1;
      else
771
	{
Niels Möller's avatar
Niels Möller committed
772
773
774
775
776
777
	  UINT32 got = res;
	  UINT32 done = 0;

	  while (handler
		 && (done < got))
	    done += READ_HANDLER(handler, got - done, buffer + done);
778
779
	}
    }
Niels Möller's avatar
Niels Möller committed
780
  /* FIXME: Not reached. Hmm. */
Niels Möller's avatar
Niels Möller committed
781
782
  close(fd);
  return !handler;
783
}
784
#endif
Niels Möller's avatar
Niels Möller committed
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859

/* These functions are used by werror() and friends */

/* For fd:s in blocking mode. */
const struct exception *
write_raw(int fd, UINT32 length, const UINT8 *data)
{
  while(length)
    {
      int written = write(fd, data, length);

      if (written < 0)
	switch(errno)
	  {
	  case EINTR:
	  case EAGAIN:
	    continue;
	  default:
	    return make_io_exception(EXC_IO_BLOCKING_WRITE,
				     NULL, errno, NULL);
	  }
      
      length -= written;
      data += written;
    }
  return NULL;
}

const struct exception *
write_raw_with_poll(int fd, UINT32 length, const UINT8 *data)
{
  while(length)
    {
      struct pollfd pfd;
      int res;
      int written;
      
      pfd.fd = fd;
      pfd.events = POLLOUT;

      res = poll(&pfd, 1, -1);

      if (res < 0)
	switch(errno)
	  {
	  case EINTR:
	  case EAGAIN:
	    continue;
	  default:
	    return make_io_exception(EXC_IO_BLOCKING_WRITE,
				     NULL, errno, NULL);
	  }
      
      written = write(fd, data, length);

      if (written < 0)
	switch(errno)
	  {
	  case EINTR:
	  case EAGAIN:
	    continue;
	  default:
	    return make_io_exception(EXC_IO_BLOCKING_WRITE,
				     NULL, errno, NULL);
	  }
      
      length -= written;
      data += written;
    }
  return NULL;
}


/* Network utility functions */

860
/* Converts a string port number or service name to a port number.
861
862
 * Returns the port number in _host_ byte order, or 0 if lookup
 * fails. */
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883

int get_portno(const char *service, const char *protocol)
{
  if (service == NULL)
    return 0;
  else
    {
      char *end;
      long portno;

      portno = strtol(service, &end, 10);
      if (portno > 0
	  &&  portno <= 65535
	  &&  end != service
	  &&  *end == '\0')
	  return portno;
      else
	{
	  struct servent * serv;

	  serv = getservbyname(service, protocol);
884
885
	  if (!serv)
	    return 0;
886
887
888
889
890
891
	  return ntohs(serv->s_port);
	}
    }
}


892
893
894
895
896
/* If def != 0, use that value as a fallback if the lookup fails. */
struct address_info *
make_address_info_c(const char *host,
		    const char *port,
		    int def)
897
898
{
  int portno = get_portno(port, "tcp");
899
900
901
902
903
904
  if (!portno)
    portno = def;

  if (!portno)
    return NULL;

905
906
907
908
909
  else
    {
      NEW(address_info, info);
      
      info->port = portno;
910
      info->ip = host ? ssh_format("%lz", host) : NULL;
911
912
913
914
      
      return info;
    }
}
915

916
917
struct address_info *
make_address_info(struct lsh_string *host, UINT32 port)
918
919
920
921
922
923
924
925
{
  NEW(address_info, info);

  info->port = port; /* htons(port); */
  info->ip = host;
  return info;
}

926
927
928
struct address_info *
sockaddr2info(size_t addr_len UNUSED,
	      struct sockaddr *addr)
929
{
930
  NEW(address_info, info);
931
932
933
934
935
936
937
  
  switch(addr->sa_family)
    {
    case AF_INET:
      {
	struct sockaddr_in *in = (struct sockaddr_in *) addr;
	UINT32 ip = ntohl(in->sin_addr.s_addr);
938
	info->port = ntohs(in->sin_port);
939
940
941
942
943
	info->ip = ssh_format("%di.%di.%di.%di",
			      (ip >> 24) & 0xff,
			      (ip >> 16) & 0xff,
			      (ip >> 8) & 0xff,
			      ip & 0xff);
944
945
	return info;
      }
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
#if WITH_IPV6
    case AF_INET6:
      {
	struct sockaddr_in6 *in = (struct sockaddr_in6 *) addr;
	UINT8 *ip = in->sin6_addr.s6_addr;
	info->port = ntohs(in->sin6_port);
	info->ip = ssh_format("%xi:%xi:%xi:%xi:%xi:%xi:%xi:%xi",
			      (ip[0]  << 8) | ip[1],
			      (ip[2]  << 8) | ip[3],
			      (ip[4]  << 8) | ip[5],
			      (ip[6]  << 8) | ip[7],
			      (ip[8]  << 8) | ip[9],
			      (ip[10] << 8) | ip[11],
			      (ip[12] << 8) | ip[13],
			      (ip[14] << 8) | ip[15]);
	return info;
      }
963
964
965
966
967
#endif
    default:
      fatal("io.c: format_addr(): Unsupported address family.\n");
    }
}
968

969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
#if HAVE_GETADDRINFO
static struct addrinfo *
choose_address(struct addrinfo *list,
	       const int *preference)
{
  int i;
  for (i = 0; preference[i]; i++)
    {
      struct addrinfo *p;
      for (p = list; p; p = p->ai_next)
	if (preference[i] == p->ai_family)
	  return p;
    }
  return NULL;
}
#endif /* HAVE_GETADDRINFO */

/* FIXME: Perhaps this function should be changed to return a list of
 * sockaddr:s? */
988
989
990
struct sockaddr *
address_info2sockaddr(socklen_t *length,
		      struct address_info *a,
991
992
		      /* Preferred address families. Zero-terminated array. */
		      const int *preference,
993
		      int lookup)
994
{
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
  char *host;

  if (a->ip)
    {
      host = alloca(a->ip->length + 1);
  
      memcpy(host, a->ip->data, a->ip->length);
      host[a->ip->length] = '\0';
    }
  else
    host = NULL;
  
#if HAVE_GETADDRINFO
  {
    struct addrinfo hints;
    struct addrinfo *list;
1011
    struct addrinfo *chosen;
1012
    struct sockaddr *res;
1013
1014
1015
1016
1017
1018
1019
    const int default_preference
#if WITH_IPV6
      [3] = { AF_INET6, AF_INET }
#else
      [2] = { AF_INET, 0 }
#endif      
      ;
1020
1021
1022
    int err;
    /* FIXME: It seems ugly to have to convert the port number to a
     * string. */
1023
    struct lsh_string *service = ssh_format("%di%c", a->port, 0);
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = PF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE;

    if (!lookup)
      hints.ai_flags |= AI_NUMERICHOST;
    
    err = getaddrinfo(host, service->data, &hints, &list);
    lsh_string_free(service);

    if (err)
      {
	debug("address_info2sockaddr: getaddrinfo failed (err = %d): %s\n",
	      err, gai_strerror(err));
	return NULL;
      }

1043
1044
1045
1046
1047
1048
1049
1050
1051
    chosen = choose_address(list,
			    preference ? preference : default_preference);
    if (!chosen)
      {
	freeaddrinfo(list);
	return NULL;
      }
    
    *length = chosen->ai_addrlen;
1052
1053
    
    res = lsh_space_alloc(*length);
1054
    memcpy(res, chosen->ai_addr, *length);
1055
1056
1057
1058
1059
1060
1061
1062
1063
    freeaddrinfo(list);

    return res;
  }
#else /* !HAVE_GETADDRINFO */

#if WITH_IPV6
#warning IPv6 enabled, but getaddrinfo() was not found. 
#endif
1064

1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
  if (a->ip && memchr(a->ip->data, ':', a->ip->length))
    {
      debug("address_info2sockaddr: Literal IPv6 used. Failing.\n");
      return NULL;
    }
  else
    {
      struct sockaddr_in *addr;
      NEW_SPACE(addr);

      *length = sizeof(*addr);
      addr->sin_port = htons(a->port);
    
      if (!host)
	{
	  /* Use INADDR_ANY (and IPv4 only) */

	  addr->sin_family = AF_INET;
	  addr->sin_addr.s_addr = INADDR_ANY;

	  return (struct sockaddr *) addr;
	}
      else
	{
	  /* First check for numerical ip-number */
#if HAVE_INET_ATON
	  if (!inet_aton(host, &addr->sin_addr))
#else /* !HAVE_INET_ATON */
	    /* NOTE: It is wrong to work with ((unsigned long int) -1)
	     * directly, as this breaks Linux/Alpha systems. But
	     * INADDR_NONE isn't portable. That's what inet_aton is for;
	     * see the GNU libc documentation. */
# ifndef INADDR_NONE
# define INADDR_NONE ((unsigned long int) -1)
# endif /* !INADDR_NONE */
	  addr->sin_addr.s_addr = inet_addr(host);
	  if (addr->sin_addr.s_addr == INADDR_NONE)
#endif  /* !HAVE_INET_ATON */
	    {
	      struct hostent *hp;

	      if (! (lookup 
		     && (hp = gethostbyname(host))
		     && (hp->h_addrtype == AF_INET)))
		{
		  lsh_space_free(addr);
		  return NULL;
		}

	      memcpy(&addr->sin_addr, hp->h_addr, hp->h_length);
	    }
	  return (struct sockaddr *) addr;
	}
    }
#endif /* !HAVE_GETADDRINFO */  
}

1122

Niels Möller's avatar
Niels Möller committed
1123
1124
void io_set_nonblocking(int fd)
{
1125
1126
1127
1128
1129
1130
1131
  int old = fcntl(fd, F_GETFL);

  if (old < 0)
    fatal("io_set_nonblocking: fcntl(F_GETFL) failed, %z", STRERROR(errno));
  
  if (fcntl(fd, F_SETFL, old | O_NONBLOCK) < 0)
    fatal("io_set_nonblocking: fcntl(F_SETFL) failed, %z", STRERROR(errno));
Niels Möller's avatar
Niels Möller committed
1132
1133
}

1134
1135
void io_set_close_on_exec(int fd)
{
1136
1137
1138
1139
1140
1141
1142
1143
1144
  /* NOTE: There's only one documented flag bit, so reading the old
   * value should be redundant. */
  
  int old = fcntl(fd, F_GETFD);

  if (old < 0)
    fatal("io_set_nonblocking: fcntl(F_GETFD) failed, %z", STRERROR(errno));
  
  if (fcntl(fd, F_SETFD, old | 1) < 0)
1145
    fatal("Can't set close-on-exec flag for fd %i: %z\n",
1146
	  fd, STRERROR(errno));
1147
1148
}

Niels Möller's avatar
Niels Möller committed
1149

1150
1151
1152
1153
1154
1155
1156
1157
1158
/* ALL file descripters handled by the backend should use non-blocking mode,
 * and have the close-on-exec flag set. */

void io_init_fd(int fd)
{
  io_set_nonblocking(fd);
  io_set_close_on_exec(fd);
}

1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
struct lsh_fd *
make_lsh_fd(struct io_backend *b,
	    int fd,
	    struct exception_handler *e)
{
  NEW(lsh_fd, f);

  io_init_fd(fd);
  init_file(b, f, fd, e);

  return f;
}

Niels Möller's avatar
Niels Möller committed
1172
/* Some code is taken from Thomas Bellman's tcputils. */
1173
struct lsh_fd *
1174
io_connect(struct io_backend *b,
1175
1176
	   struct sockaddr *remote,
	   socklen_t remote_length,
1177
	   struct command_continuation *c,
1178
	   struct exception_handler *e)
Niels Möller's avatar
Niels Möller committed
1179
{
1180
  int s = socket(remote->sa_family, SOCK_STREAM, 0);
1181
  struct lsh_fd *fd;
Niels Möller's avatar
Niels Möller committed
1182
  
1183
1184
  if (s<0)
    return NULL;
Niels Möller's avatar
Niels Möller committed
1185

1186
  trace("io.c: Connecting using fd %i\n", s);
1187
  
1188
  io_init_fd(s);
Niels Möller's avatar
Niels Möller committed
1189

1190
#if 0
1191
1192
1193
1194
1195
1196
1197
  if (local  &&  bind(s, (struct sockaddr *)local, sizeof *local) < 0)
    {
      int saved_errno = errno;
      close(s);
      errno = saved_errno;
      return NULL;
    }
1198
1199
1200
#endif
  
  if ( (connect(s, remote, remote_length) < 0)
1201
1202
1203
1204
1205
1206
1207
1208
       && (errno != EINPROGRESS) )       
    {
      int saved_errno = errno;
      close(s);
      errno = saved_errno;
      return NULL;
    }

1209
1210
1211
1212
  fd = make_lsh_fd(b, s, e);
  
  fd->want_write = 1;
  fd->write = make_connect_callback(c);
1213
    
1214
  return fd;
Niels Möller's avatar
Niels Möller committed
1215
1216
}

1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
struct lsh_fd *
io_listen(struct io_backend *b,
	  struct sockaddr *local,
	  socklen_t length,
	  struct io_callback *callback,
	  struct exception_handler *e)
{
  int s = socket(local->sa_family, SOCK_STREAM, 0);
  struct lsh_fd *fd;
  
  if (s<0)
    return NULL;

  trace("io.c: Listening on fd %i\n", s);
  
  io_init_fd(s);

  {
    int yes = 1;
    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&yes, sizeof yes);
  }

  if (bind(s, (struct sockaddr *)local, length) < 0)
    {
      close(s);
      return NULL;
    }

  if (listen(s, 256) < 0) 
    {
      close(s);
      return NULL;
    }

  fd = make_lsh_fd(b, s, e);

  fd->want_read = 1;
  fd->read = callback;

  return fd;
}

1259
1260
1261

/* AF_LOCAL sockets */

1262
static void
1263
safe_popd(int old_cd, const char *directory)
1264
{
1265
1266
  while (fchdir(old_cd) < 0)
    if (errno != EINTR)
1267
      fatal("io.c: Failed to cd back from %z (errno = %i): %z\n",
1268
1269
1270
1271
1272
1273
1274
1275
	    directory, errno, STRERROR(errno));
      
  close(old_cd);
}

/* Changes the cwd, making sure that it it has reasonable permissions,
 * and that we can change back later. */
static int
1276
safe_pushd(const char *directory,
1277
1278
1279
1280
1281
1282
1283
1284
	   int create)
{
  int old_cd;
  struct stat sbuf;

  if (create)
    {  
      /* First create the directory, in case it doesn't yet exist. */
1285
      if ( (mkdir(directory, 0700) < 0)
1286
1287
	   && (errno != EEXIST) )
	{
1288
	  werror("io.c: Creating directory %z failed "
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
		 "(errno = %i): %z\n", directory, errno, STRERROR(errno));
	}
    }
    
  /* cd to it, but first save old cwd */

  old_cd = open(".", O_RDONLY);
  if (old_cd < 0)
    {
      werror("io.c: open(\".\") failed.\n");
      return -1;
    }

  /* Test if we are allowed to cd to our current working directory. */
  while (fchdir(old_cd) < 0)
    if (errno != EINTR)
      {
	werror("io.c: fchdir(\".\") failed (errno = %i): %z\n",
	       errno, strerror(errno));
	close(old_cd);
	return -1;
      }

  /* As far as I have been able to determine, all checks for
   * fchdir:ability is performed at the time the directory was opened.
   * Even if the directory is chmod:et to zero, or unlinked, we can
   * probably fchdir to it later. */

1317
  while (chdir(directory) < 0)
1318
1319
1320
1321
1322
1323
1324
1325
    if (errno != EINTR)
      {
	close(old_cd);
	return -1;
      }

  /* Check that it has reasonable permissions */
  if (stat(".", &sbuf) < 0)
1326
    {
1327
      werror("io.c: Failed to stat() \".\" (supposed to be %z).\n"
1328
	     "  (errno = %i): %z\n", directory, errno, STRERROR(errno));
1329

1330
1331
1332
      safe_popd(old_cd, directory);
      return -1;
    }
1333

1334
1335
  if (sbuf.st_uid != getuid())
    {
1336
      werror("io.c: Socket directory %z not owned by user.\n", directory);
1337
1338
1339

      safe_popd(old_cd, directory);
      return -1;
1340
    }
1341
1342
1343
    
  if (sbuf.st_mode & (S_IRWXG | S_IRWXO))
    {
1344
      werror("io.c: Permission bits on %z are too loose.\n", directory);
1345
1346
1347
1348
1349
1350

            safe_popd(old_cd, directory);
      return -1;
    }

  return old_cd;
1351
}
1352

1353
1354

/* Requires DIRECTORY and NAME to be NUL-terminated */
1355
1356
1357
1358
1359
1360
1361
struct lsh_fd *
io_listen_local(struct io_backend *b,
		struct lsh_string *directory,
		struct lsh_string *name,
		struct io_callback *callback,
		struct exception_handler *e)
{
1362
  int old_cd;
1363

1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
  mode_t old_umask;
  struct sockaddr_un *local;
  socklen_t local_length;

  struct lsh_fd *fd;
  
  assert(directory && NUL_TERMINATED(directory));
  assert(name && NUL_TERMINATED(name));

  /* NAME should not be a plain filename, with no directory separators.
   * In particular, it should not be an absolute filename. */
  assert(!memchr(name->data, '/', name->length));

  local_length = OFFSETOF(struct sockaddr_un, sun_path) + name->length;
  local = alloca(local_length);

Niels Möller's avatar
Niels Möller committed
1380
  local->sun_family = AF_UNIX;
1381
1382
  memcpy(local->sun_path, name->data, name->length);

1383