io.c 43.7 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
#include "string_buffer.h"
28
29
30
#include "werror.h"
#include "xalloc.h"

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

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

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

48
49
#include <oop.h>

50
51
52
53
54
55
56
/* 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
57
58
59
60
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
61
#include <sys/un.h>
Niels Möller's avatar
Niels Möller committed
62
#include <arpa/inet.h>
63
#include <signal.h>
64
65
#include <sys/stat.h>

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

67
#define GABA_DEFINE
68
#include "io.h.x"
69
#undef GABA_DEFINE
70
71
72

#include "io.c.x"

73
74
/* Glue to liboop */

75
/* Because of signal handlers, there can be only one oop object. */
76
77
static oop_source_sys *global_oop_sys = NULL;
static oop_source *source = NULL;
78

79
80
void
io_init(void)
81
{
82
83
84
85
86
87
88
89
90
91
92
93
94
  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");

  assert(!global_oop_sys);
  global_oop_sys = oop_sys_new();
  if (!global_oop_sys)
95
    fatal("Failed to initialize liboop.\n");
96
97

  source = oop_sys_source(global_oop_sys);
98
99
}

100
void
101
io_final(void)
102
{
103
  assert(source);
104
  gc_final();
105

106
  /* There mustn't be any outstanding callbacks left. */
107
108
109
110
111
112
113
114
  oop_sys_delete(global_oop_sys);
  global_oop_sys = NULL;
  source = NULL;
}

void
io_run(void)
{
115
  void *res = oop_sys_run(global_oop_sys);
116

117
118
119
120
121
122
123
  /* FIXME: OOP_ERROR is not defined in liboop-0.7. Upgrade, and then
   * enable this check. */
#if 0
  if (res == OOP_ERROR)
    werror("oop_sys_run (errno = %i):  %z\n",
	   errno, STRERROR(errno));
#endif
124
  trace("io_run: Exiting\n");
125
126
127
}


128
/* OOP Callbacks */
129
static void *
130
lsh_oop_signal_callback(oop_source *s UNUSED, int sig, void *data)
131
132
133
{
  CAST(lsh_signal_handler, self, (struct lsh_object *) data);

134
  trace("lsh_oop_signal_callback: Signal %i, handler: %t\n",
135
	sig, self->action);
136
  
137
138
  assert(sig == self->signum);
  
139
  LSH_CALLBACK(self->action);
140

141
  return OOP_CONTINUE;
142
143
144
}

static void
145
lsh_oop_register_signal(struct lsh_signal_handler *handler)
146
{
147
148
149
  trace("lsh_oop_register_signal: signal: %i, handler: %t\n",
	handler->signum, handler);
  
150
  assert(source);
151
  if (handler->super.alive)
152
    source->on_signal(source, handler->signum, lsh_oop_signal_callback, handler);
153
154
}

155
static void
156
lsh_oop_cancel_signal(struct lsh_signal_handler *handler)
157
{
158
159
  trace("lsh_oop_cancel_signal: signal: %i, handler: %t\n",
	handler->signum, handler);
160

161
  assert(source);
162
163
  if (handler->super.alive)
    source->cancel_signal(source, handler->signum, lsh_oop_signal_callback, handler);
164
}
165
166

static void *
167
lsh_oop_fd_read_callback(oop_source *s UNUSED, int fileno, oop_event event, void *data)
168
169
170
171
{
  CAST(lsh_fd, fd, (struct lsh_object *) data);

  assert(fileno == fd->fd);
172
173
  assert(event == OOP_READ);
  assert(fd->super.alive);
174

175
  trace("lsh_oop_fd_read_callback: fd %i: %z\n",
176
177
178
	fd->fd, fd->label);

  FD_READ(fd);
179

180
  return OOP_CONTINUE;
181
182
}

183
184
void
lsh_oop_register_read_fd(struct lsh_fd *fd)
185
{
186
187
188
  trace("lsh_oop_register_read_fd: fd: %i, %z\n",
	fd->fd, fd->label);
  
189
  assert(source);
190
  if (fd->super.alive && !fd->want_read)
191
192
193
194
195
196
    {
      assert(fd->read);
      
      source->on_fd(source, fd->fd, OOP_READ, lsh_oop_fd_read_callback, fd);
      fd->want_read = 1;
    }
197
198
}

199
200
201
void
lsh_oop_cancel_read_fd(struct lsh_fd *fd)
{
202
203
204
  trace("lsh_oop_cancel_read_fd: fd: %i, %z\n",
	fd->fd, fd->label);
  
205
  assert(source);
206
207
208
209
210
211
  if (fd->super.alive)
    {
      source->cancel_fd(source, fd->fd, OOP_READ);
      fd->want_read = 0;
    }
}
212
213

static void *
214
lsh_oop_fd_write_callback(oop_source *s UNUSED, int fileno, oop_event event, void *data)
215
{
216
  CAST(lsh_fd, fd, (struct lsh_object *) data);
217

218
  assert(fileno == fd->fd);
219
  assert(event == OOP_WRITE);
220
221
  assert(fd->super.alive);
  
222
  trace("lsh_oop_fd_write_callback: fd %i: %z\n",
223
	fd->fd, fd->label);
224

225
  FD_WRITE(fd);
226

227
  return OOP_CONTINUE;
228
229
}

230
231
void
lsh_oop_register_write_fd(struct lsh_fd *fd)
232
{
233
234
235
  trace("lsh_oop_register_write_fd: fd: %i, %z\n",
	fd->fd, fd->label);
  
236
  assert(source);
237
  if (fd->super.alive && !fd->want_write)
238
239
240
241
242
243
244
    {
      assert(fd->write);
      
      source->on_fd(source, fd->fd, OOP_WRITE, lsh_oop_fd_write_callback, fd);
      fd->want_write = 1;
    }
}
245

246
247
void
lsh_oop_cancel_write_fd(struct lsh_fd *fd)
248
{
249
250
251
  trace("lsh_oop_cancel_write_fd: fd: %i, %z\n",
	fd->fd, fd->label);

252
  assert(source);
253
254
255
256
257
  if (fd->super.alive)
    {
      source->cancel_fd(source, fd->fd, OOP_WRITE);
      fd->want_write = 0;
    }
258
259
}

260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
static void *
lsh_oop_time_callback(oop_source *source UNUSED,
                      struct timeval time UNUSED, void *data)
{
  CAST(lsh_callout, callout, (struct lsh_object *) data);

  assert(callout->super.alive);

  trace("lsh_oop_time_callback: action: %t\n",
        callout->action);
  
  callout->super.alive = 0;

  LSH_CALLBACK(callout->action);

  return OOP_CONTINUE;
}

static void
lsh_oop_register_callout(struct lsh_callout *callout)
{
281
  assert(source);
282
283
284
  trace("lsh_oop_register_callout: action: %t\n",
        callout->action);

285
  if (callout->super.alive)
286
    source->on_time(source, callout->when, lsh_oop_time_callback, callout);
287
288
289
290
291
}

static void
lsh_oop_cancel_callout(struct lsh_callout *callout)
{
292
  assert(source);
293
294
  trace("lsh_oop_cancel_callout: action: %t\n",
        callout->action);
295
  if (callout->super.alive)
296
    source->cancel_time(source, callout->when, lsh_oop_time_callback, callout);
297
298
}

299

300
301
302
303
304
305
/* Calls trigged by a signal handler. */
/* GABA:
   (class
     (name lsh_signal_handler)
     (super resource)
     (vars
306
       (signum . int)
307
308
309
310
311
312
313
314
315
       (action object lsh_callback)))
*/

/* Scheduled calls. FIXME: For now, no scheduling in time. */
/* GABA:
   (class
     (name lsh_callout)
     (super resource)
     (vars
316
       (when . "struct timeval")
317
318
319
       (action object lsh_callback)))
*/

320

321
322
323
324
325
326
327
static void
do_kill_signal_handler(struct resource *s)
{
  CAST(lsh_signal_handler, self, s);

  if (self->super.alive)
    {
328
      lsh_oop_cancel_signal(self);
329
330
331
332
      self->super.alive = 0;
    }
}

333
struct resource *
334
io_signal_handler(int signum,
335
336
337
		  struct lsh_callback *action)
{
  NEW(lsh_signal_handler, handler);
338
339

  init_resource(&handler->super, do_kill_signal_handler);
340

341
  handler->signum = signum;
342
343
  handler->action = action;

344
  lsh_oop_register_signal(handler);
345
  gc_global(&handler->super);
346
347
348
349
  
  return &handler->super;
}

350
351
352
353
354
355
356
357
358
359
360
361
static void
do_kill_callout(struct resource *s)
{
  CAST(lsh_callout, self, s);

  if (self->super.alive)
    {
      lsh_oop_cancel_callout(self);
      self->super.alive = 0;
    }
}

362
struct resource *
363
io_callout(struct lsh_callback *action, unsigned seconds)
364
{
365
  NEW(lsh_callout, self);
366
  init_resource(&self->super, do_kill_callout);
367

368
369
370
371
372
373
374
375
376
377
378
  if (seconds)
    {
      /* NOTE: Using absolute times, like oop does, is a little
       * dangerous if the system time is changed abruptly. */
      if (gettimeofday(&self->when, NULL) < 0)
	fatal("io_callout: gettimeofday failed!\n");
      self->when.tv_sec += seconds;
    }
  else
    self->when = OOP_TIME_NOW;
  
379
  self->action = action;
380
      
381
382
  lsh_oop_register_callout(self);
  
383
384
  gc_global(&self->super);
  return &self->super;
385
}
Niels Möller's avatar
Niels Möller committed
386
387
388

/* Read-related callbacks */

389
390
391
static void
do_buffered_read(struct io_callback *s,
		 struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
392
393
394
{
  CAST(io_buffered_read, self, s);
  UINT8 *buffer = alloca(self->buffer_size);
395
396
397
  int res;

  assert(fd->want_read);   
398

399
#if 0
400
  /* If hanged_up is set, pretend that read returned 0 */
401
  res = fd->hanged_up ? 0 : read(fd->fd, buffer, self->buffer_size);
402
#endif
Niels Möller's avatar
Niels Möller committed
403

404
  res = read(fd->fd, buffer, self->buffer_size);
405
  
Niels Möller's avatar
Niels Möller committed
406
407
408
409
410
411
412
413
414
  if (res < 0)
    switch(errno)
      {
      case EINTR:
	break;
      case EWOULDBLOCK:
	werror("io.c: read_callback: Unexpected EWOULDBLOCK\n");
	break;
      case EPIPE:
415
	/* Getting EPIPE from read seems strange, but appearantly
416
	 * it happens sometimes. */
417
	werror("Unexpected EPIPE from read.\n");
Niels Möller's avatar
Niels Möller committed
418
      default:
Niels Möller's avatar
Niels Möller committed
419
420
421
	EXCEPTION_RAISE(fd->e, 
			make_io_exception(EXC_IO_READ, fd,
					  errno, NULL));
422
423
424
	/* Close the fd, unless it has a write callback. */
	close_fd_read(fd);
	
Niels Möller's avatar
Niels Möller committed
425
426
427
428
429
430
	break;
      }
  else if (res > 0)
    {
      UINT32 left = res;
    
431
      while (fd->super.alive && fd->read && left)
Niels Möller's avatar
Niels Möller committed
432
433
	{
	  UINT32 done;
Niels Möller's avatar
Niels Möller committed
434

435
	  /* NOTE: What to do if want_read is false? To improve the
436
	   * connection_lock mechanism, it must be possible to
437
438
	   * temporarily stop reading, which means that fd->want_read
	   * has to be cleared.
439
440
441
442
443
444
445
446
447
448
449
	   *
	   * 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.
450
	   *
451
	   * We now go with the second alternative. */
452

453
	  assert(self->handler);
Niels Möller's avatar
Niels Möller committed
454
455

	  /* NOTE: This call may replace self->handler */
Niels Möller's avatar
Niels Möller committed
456
	  done = READ_HANDLER(self->handler, left, buffer);
457
	  
Niels Möller's avatar
Niels Möller committed
458
459
	  buffer += done;
	  left -= done;
460

461
462
463
	  if (!fd->want_read)
	    debug("do_buffered_read: want_read = 0; handler needs a pause.\n");
	  
464
465
466
467
	  if (fd->want_read && !self->handler)
	    {
	      werror("do_buffered_read: Handler disappeared! Ignoring %i bytes\n",
		     left);
468
	      lsh_oop_cancel_read_fd(fd);
469
470
	      return;
	    }
Niels Möller's avatar
Niels Möller committed
471
472
473
	}

      if (left)
474
	verbose("read_buffered: fd died, %i buffered bytes discarded\n",
Niels Möller's avatar
Niels Möller committed
475
476
477
		left);
    }
  else
478
479
480
481
482
483
484
    {
      /* We have read EOF. Pass available == 0 to the handler */
      assert(fd->super.alive);
      assert(fd->read);
      assert(fd->want_read);
      assert(self->handler);

Niels Möller's avatar
Niels Möller committed
485
486
      /* Close the fd, unless it has a write callback. */
      close_fd_read(fd);
487
      
488
489
490
      READ_HANDLER(self->handler, 0, NULL);
    }
	
Niels Möller's avatar
Niels Möller committed
491
492
}

493
struct io_callback *
Niels Möller's avatar
Niels Möller committed
494
495
496
497
498
make_buffered_read(UINT32 buffer_size,
		   struct read_handler *handler)
{
  NEW(io_buffered_read, self);

499
  self->super.f = do_buffered_read;
Niels Möller's avatar
Niels Möller committed
500
501
502
503
504
505
  self->buffer_size = buffer_size;
  self->handler = handler;

  return &self->super;
}

506
507
508
static void
do_consuming_read(struct io_callback *c,
		  struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
509
{
510
  CAST_SUBTYPE(io_consuming_read, self, c);
Niels Möller's avatar
Niels Möller committed
511
512
  UINT32 wanted = READ_QUERY(self);

513
514
515
516
  assert(fd->want_read);
  
  if (!wanted)
    {
517
      lsh_oop_cancel_read_fd(fd);
518
    }
Niels Möller's avatar
Niels Möller committed
519
520
521
522
523
524
  else
    {
      struct lsh_string *s = lsh_string_alloc(wanted);
      int res = read(fd->fd, s->data, wanted);

      if (res < 0)
525
526
527
528
529
530
531
532
533
534
535
536
537
	{
	  switch(errno)
	    {
	    case EINTR:
	      break;
	    case EWOULDBLOCK:
	      werror("io.c: read_consume: Unexpected EWOULDBLOCK\n");
	      break;
	    case EPIPE:
	      /* 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");
538
	      /* Fall through */
539
540
541
542
543
544
545
546
	    default:
	      EXCEPTION_RAISE(fd->e, 
			      make_io_exception(EXC_IO_READ,
						fd, errno, NULL));
	      break;
	    }
	  lsh_string_free(s);
	}
Niels Möller's avatar
Niels Möller committed
547
548
549
      else if (res > 0)
	{
	  s->length = res;
550
	  A_WRITE(self->consumer, s);
Niels Möller's avatar
Niels Möller committed
551
552
	}
      else
553
	{
554
	  lsh_string_free(s);
555

Niels Möller's avatar
Niels Möller committed
556
	  /* Close the fd, unless it has a write callback. */
557
	  A_WRITE(self->consumer, NULL);
558
	  close_fd_read(fd);
559
	}
Niels Möller's avatar
Niels Möller committed
560
561
562
563
564
565
566
567
    }
}

/* 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)
{
568
  self->super.f = do_consuming_read;
Niels Möller's avatar
Niels Möller committed
569
570
  self->consumer = consumer;
}
571

572

Niels Möller's avatar
Niels Möller committed
573
/* Write related callbacks */
574
575
576
static void
do_write_callback(struct io_callback *s UNUSED,
		  struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
577
{
578
  /* CAST(io_write_callback, self, s); */
579
580
581
  assert(fd->super.alive);
  
  if (!write_buffer_pre_write(fd->write_buffer))
582
    {
583
584
      /* Buffer is empty */
      if (fd->write_buffer->closed)
585
        close_fd_write(fd);
586
587
      else
	lsh_oop_cancel_write_fd(fd);
588
    }
589
590
591
592
593
594
595
596
  else
    {
      UINT32 size;
      int res;

      size = MIN(fd->write_buffer->end - fd->write_buffer->start,
		 fd->write_buffer->block_size);
      assert(size);
Niels Möller's avatar
Niels Möller committed
597
  
598
599
600
601
602
603
604
605
606
607
608
609
610
      res = write(fd->fd,
		  fd->write_buffer->buffer + fd->write_buffer->start,
		  size);
      if (!res)
	fatal("Closed?");
      if (res < 0)
	switch(errno)
	  {
	  case EINTR:
	  case EAGAIN:
	    break;
	  case EPIPE:
	    debug("io.c: Broken pipe.\n");
Niels Möller's avatar
Niels Möller committed
611
	
612
613
614
615
616
617
	    /* Fall through */
	  default:
	    werror("io.c: write failed, %z\n", STRERROR(errno));
	    EXCEPTION_RAISE(fd->e,
			    make_io_exception(EXC_IO_WRITE, fd, errno, NULL));
	    close_fd(fd);
Niels Möller's avatar
Niels Möller committed
618
	
619
620
621
622
623
624
	    break;
	  }
      else
	write_buffer_consume(fd->write_buffer, res);
    }
}
625

626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
static struct io_callback io_write_callback =
{ STATIC_HEADER, do_write_callback };


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
642
643
644

/* Listen callback */

645
646
647
648
649
650
651
652
653
/* GABA:
   (class
     (name io_listen_callback)
     (super io_callback)
     (vars
       (c object command_continuation)
       (e object exception_handler)))
*/

Niels Möller's avatar
Niels Möller committed
654
static void
655
do_listen_callback(struct io_callback *s,
Niels Möller's avatar
Niels Möller committed
656
		   struct lsh_fd *fd)
Niels Möller's avatar
Niels Möller committed
657
{
658
  CAST(io_listen_callback, self, s);
659
660
661
662
663
664

#if WITH_IPV6
  struct sockaddr_storage peer;
#else
  struct sockaddr peer;
#endif
665
666

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

Niels Möller's avatar
Niels Möller committed
669
670
671
  conn = accept(fd->fd,
		(struct sockaddr *) &peer, &addr_len);
  if (conn < 0)
672
    {
673
      werror("io.c: accept failed, %z", STRERROR(errno));
Niels Möller's avatar
Niels Möller committed
674
      return;
675
    }
676
  trace("io.c: accept on fd %i\n", conn);
677
  COMMAND_RETURN(self->c,
678
		 make_listen_value(make_lsh_fd(conn, "accepted socket", self->e),
679
680
				   sockaddr2info(addr_len,
						 (struct sockaddr *) &peer)));
Niels Möller's avatar
Niels Möller committed
681
}
682

683
struct io_callback *
684
make_listen_callback(struct command_continuation *c,
685
686
687
688
689
690
691
692
693
		     struct exception_handler *e)
{
  NEW(io_listen_callback, self);
  self->super.f = do_listen_callback;
  self->c = c;
  self->e = e;
  
  return &self->super;
}
Niels Möller's avatar
Niels Möller committed
694

Niels Möller's avatar
Niels Möller committed
695
696
/* Connect callback */

697
698
699
700
701
702
703
704
705
706
707
/* 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
708
{
709
  CAST(io_connect_callback, self, s);
710
  int socket_error;
711
  socklen_t len = sizeof(socket_error);
712
  
713
  /* Check if the connection was successful */
714
715
  if ((getsockopt(fd->fd, SOL_SOCKET, SO_ERROR,
		  (char *) &socket_error, &len) < 0)
716
      || socket_error)
717
    {
718
      trace("io.c: connect_callback: Connect on fd %i failed.\n", fd->fd);
Niels Möller's avatar
Niels Möller committed
719
      EXCEPTION_RAISE(fd->e,
720
		      make_io_exception(EXC_IO_CONNECT, fd, 0, "connect failed."));
721
      close_fd(fd);
722
723
    }
  else
Niels Möller's avatar
Niels Möller committed
724
    {
725
      trace("io.c: connect_callback: fd %i connected.\n", fd->fd);
726
      fd->write = NULL;
727
      lsh_oop_cancel_write_fd(fd);
728
      fd->label = "connected socket";
729
      COMMAND_RETURN(self->c, fd);
730
    }
731
732
733
734
735
736
737
738
739
740
741
}

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;
742
743
}

744

Niels Möller's avatar
Niels Möller committed
745
/* This function is called if a connection this file somehow depends
746
747
748
749
750
751
752
753
 * 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
754
755
  /* We use close_fd_nicely, so that any data in the write buffer is
   * flushed before the fd is closed. */
756
  if (r->alive)
757
    close_fd_nicely(fd);
758
759
}

760
761
762
763
764
765
766
767
768
769
/* 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);

770
      if (e->fd)
771
	close_fd(e->fd);
772
773
774
775
776
    }
  EXCEPTION_RAISE(self->parent, x);
  return;
}

777

778
/* These functions are used by werror and friends */
Niels Möller's avatar
Niels Möller committed
779
780
781
782
783
784
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

/* 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;
}

849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
/* For fd:s in blocking mode. */
const struct exception *
read_raw(int fd, UINT32 length, UINT8 *data)
{
  while(length)
    {
      int done = read(fd, data, length);

      if (done < 0)
	switch(errno)
	  {
	  case EINTR:
	  case EAGAIN:
	    continue;
	  default:
	    return make_io_exception(EXC_IO_BLOCKING_READ,
				     NULL, errno, NULL);
	  }
      else if (done == 0)
	{
	  /* EOF. */
	  /* FIXME: Indicate the amount of data read, somehow. */
	  return make_io_exception(EXC_IO_BLOCKING_READ,
				   NULL, 0, NULL);
	}
	
      length -= done;
      data += done;
    }
  return NULL;
}
Niels Möller's avatar
Niels Möller committed
880

881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
struct lsh_string *
io_read_file_raw(int fd, UINT32 guess)
{
  struct string_buffer buffer;
  string_buffer_init(&buffer, guess);

  for (;;)
    {
      int res;
      
      if (!buffer.left)
        /* Roughly double the size of the buffer */
        string_buffer_grow(&buffer,
                           buffer.partial->length + buffer.total + 100);
      
      res = read(fd, buffer.current, buffer.left);
      
      if (res < 0)
        {
          if (errno == EINTR)
            continue;
          
          string_buffer_clear(&buffer);
          return NULL;
        }
      else if (!res)
        {
          /* EOF */
          return string_buffer_final(&buffer, buffer.left);
        }
      assert( (unsigned) res <= buffer.left);
      
      buffer.current += res;
      buffer.left -= res;
    }
}

Niels Möller's avatar
Niels Möller committed
918
919
/* Network utility functions */

920
/* Converts a string port number or service name to a port number.
921
922
 * Returns the port number in _host_ byte order, or 0 if lookup
 * fails. */
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943

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);
944
945
	  if (!serv)
	    return 0;
946
947
948
949
950
951
	  return ntohs(serv->s_port);
	}
    }
}


952
953
954
955
956
/* 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)
957
958
{
  int portno = get_portno(port, "tcp");
959
960
961
962
963
964
  if (!portno)
    portno = def;

  if (!portno)
    return NULL;

965
966
967
968
969
  else
    {
      NEW(address_info, info);
      
      info->port = portno;
970
      info->ip = host ? ssh_format("%lz", host) : NULL;
971
972
973
974
      
      return info;
    }
}
975

976
977
struct address_info *
make_address_info(struct lsh_string *host, UINT32 port)
978
979
980
981
982
983
984
985
{
  NEW(address_info, info);

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

986
987
988
struct address_info *
sockaddr2info(size_t addr_len UNUSED,
	      struct sockaddr *addr)
989
{
990
  NEW(address_info, info);
991
992
993
994
995
996
997
  
  switch(addr->sa_family)
    {
    case AF_INET:
      {
	struct sockaddr_in *in = (struct sockaddr_in *) addr;
	UINT32 ip = ntohl(in->sin_addr.s_addr);
998
	info->port = ntohs(in->sin_port);
999
1000
1001
1002
1003
	info->ip = ssh_format("%di.%di.%di.%di",
			      (ip >> 24) & 0xff,
			      (ip >> 16) & 0xff,
			      (ip >> 8) & 0xff,
			      ip & 0xff);
1004
1005
	return info;
      }
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
#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;
      }
1023
#endif
1024
1025
1026
1027
    case AF_UNIX:
      /* Silently return NULL. This happens when a gateway client
       * connects. */
      return NULL;
1028
    default:
1029
      werror("io.c: sockaddr2info: Unsupported address family.\n");
1030
      return NULL;
1031
1032
    }
}
1033

1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
#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? */
1053
1054
1055
struct sockaddr *
address_info2sockaddr(socklen_t *length,
		      struct address_info *a,
1056
1057
		      /* Preferred address families. Zero-terminated array. */
		      const int *preference,
1058
		      int lookup)
1059
{
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
  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;
1071

Niels Möller's avatar
Niels Möller committed
1072
1073
  /* Some systems have getaddrinfo, but still doesn't implement all of
   * RFC 2553 */
1074
1075
#if defined(HAVE_GETADDRINFO) && \
    defined(HAVE_GAI_STRERROR) && defined(HAVE_AI_NUMERICHOST)
1076
1077
1078
  {
    struct addrinfo hints;
    struct addrinfo *list;
1079
    struct addrinfo *chosen;
1080
    struct sockaddr *res;
1081
1082
1083
1084
1085
1086
1087
    const int default_preference
#if WITH_IPV6
      [3] = { AF_INET6, AF_INET }
#else
      [2] = { AF_INET, 0 }
#endif      
      ;
1088
1089
1090
    int err;
    /* FIXME: It seems ugly to have to convert the port number to a
     * string. */
1091
    struct lsh_string *service = ssh_format("%di", a->port);
1092
1093
1094
1095
1096
1097
1098
1099
1100

    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;
    
1101
    err = getaddrinfo(host, lsh_get_cstring(service), &hints, &list);
1102
1103
1104
1105
    lsh_string_free(service);

    if (err)
      {
1106
	debug("address_info2sockaddr: getaddrinfo failed (err = %i): %z\n",
1107
1108
1109
1110
	      err, gai_strerror(err));
	return NULL;
      }

1111
1112
1113
1114
1115
1116
1117
1118
1119
    chosen = choose_address(list,
			    preference ? preference : default_preference);
    if (!chosen)
      {
	freeaddrinfo(list);
	return NULL;
      }
    
    *length = chosen->ai_addrlen;
1120
1121
    
    res = lsh_space_alloc(*length);
1122
    memcpy(res, chosen->ai_addr, *length);
1123
1124
1125
1126
    freeaddrinfo(list);

    return res;
  }
1127
1128
1129
#else
/* !(defined(HAVE_GETADDRINFO) &&
     defined(HAVE_GAI_STRERROR) && defined(HAVE_AI_NUMERICHOST) */ 
1130
1131

#if WITH_IPV6
1132
#error IPv6 enabled, but getaddrinfo and friends were not found. 
1133
#endif
1134

1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
  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);
1147
1148
1149

      /* Use IPv4 only */
      addr->sin_family = AF_INET;
1150
1151
    
      if (!host)
1152
1153
	/* Any interface */
	addr->sin_addr.s_addr = INADDR_ANY;
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184

      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);
	    }
	}
1185
      return (struct sockaddr *) addr;
1186
1187
1188
1189
    }
#endif /* !HAVE_GETADDRINFO */  
}

1190

Niels Möller's avatar
Niels Möller committed
1191
1192
void io_set_nonblocking(int fd)
{
1193
1194
1195
1196
1197
1198
1199
  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
1200
1201
}

1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
void io_set_blocking(int fd)
{
  int old = fcntl(fd, F_GETFL);

  if (old < 0)
    fatal("io_set_blocking: fcntl(F_GETFL) failed, %z", STRERROR(errno));
  
  if (fcntl(fd, F_SETFL, old & ~O_NONBLOCK) < 0)
    fatal("io_set_blocking: fcntl(F_SETFL) failed, %z", STRERROR(errno));
}

1213
1214
void io_set_close_on_exec(int fd)
{
1215
1216
1217
1218
1219
1220
1221
1222
1223
  /* 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)
1224
    fatal("Can't set close-on-exec flag for fd %i: %z\n",
1225
	  fd, STRERROR(errno));
1226
1227
}

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

1229
1230
1231
1232
1233
1234
1235
1236
1237
/* 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);
}

1238
struct lsh_fd *