Statistics
| Branch: | Revision:

iof-bird-daemon / sysdep / unix / io.c @ afa8937a

History | View | Annotate | Download (19.1 KB)

1
/*
2
 *        BIRD Internet Routing Daemon -- Unix I/O
3
 *
4
 *        (c) 1998--1999 Martin Mares <mj@ucw.cz>
5
 *
6
 *        Can be freely distributed and used under the terms of the GNU GPL.
7
 */
8

    
9
#include <stdio.h>
10
#include <stdlib.h>
11
#include <string.h>
12
#include <sys/time.h>
13
#include <sys/types.h>
14
#include <sys/socket.h>
15
#include <sys/fcntl.h>
16
#include <sys/un.h>
17
#include <unistd.h>
18
#include <errno.h>
19

    
20
#ifndef HAVE_STRUCT_IP_MREQN
21
#include <net/if.h>
22
#endif
23

    
24
#include "nest/bird.h"
25
#include "lib/lists.h"
26
#include "lib/resource.h"
27
#include "lib/timer.h"
28
#include "lib/socket.h"
29
#include "lib/event.h"
30
#include "lib/string.h"
31
#include "nest/iface.h"
32

    
33
#ifdef IPV6
34
#include <linux/in6.h>                        /* FIXMEv6: glibc variant? */
35
#endif
36

    
37
#include "lib/unix.h"
38

    
39
/*
40
 *        Random Numbers
41
 */
42

    
43
u32
44
random_u32(void)
45
{
46
  long int rand_low, rand_high;
47

    
48
  rand_low = random();
49
  rand_high = random();
50
  return (rand_low & 0xffff) | ((rand_high & 0xffff) << 16);
51
}
52

    
53
/*
54
 *        Timers
55
 */
56

    
57
#define NEAR_TIMER_LIMIT 4
58

    
59
static list near_timers, far_timers;
60
static bird_clock_t first_far_timer = TIME_INFINITY;
61

    
62
bird_clock_t now;
63

    
64
static void
65
tm_free(resource *r)
66
{
67
  timer *t = (timer *) r;
68

    
69
  tm_stop(t);
70
}
71

    
72
static void
73
tm_dump(resource *r)
74
{
75
  timer *t = (timer *) r;
76

    
77
  debug("(code %p, data %p, ", t->hook, t->data);
78
  if (t->randomize)
79
    debug("rand %d, ", t->randomize);
80
  if (t->recurrent)
81
    debug("recur %d, ", t->recurrent);
82
  if (t->expires)
83
    debug("expires in %d sec)\n", t->expires - now);
84
  else
85
    debug("inactive)\n");
86
}
87

    
88
static struct resclass tm_class = {
89
  "Timer",
90
  sizeof(timer),
91
  tm_free,
92
  tm_dump
93
};
94

    
95
timer *
96
tm_new(pool *p)
97
{
98
  timer *t = ralloc(p, &tm_class);
99
  t->hook = NULL;
100
  t->data = NULL;
101
  t->randomize = 0;
102
  t->expires = 0;
103
  return t;
104
}
105

    
106
static inline void
107
tm_insert_near(timer *t)
108
{
109
  node *n = HEAD(near_timers);
110

    
111
  while (n->next && (SKIP_BACK(timer, n, n)->expires < t->expires))
112
    n = n->next;
113
  insert_node(&t->n, n->prev);
114
}
115

    
116
void
117
tm_start(timer *t, unsigned after)
118
{
119
  bird_clock_t when;
120

    
121
  if (t->randomize)
122
    after += random() % (t->randomize + 1);
123
  when = now + after;
124
  if (t->expires == when)
125
    return;
126
  if (t->expires)
127
    rem_node(&t->n);
128
  t->expires = when;
129
  if (after <= NEAR_TIMER_LIMIT)
130
    tm_insert_near(t);
131
  else
132
    {
133
      if (!first_far_timer || first_far_timer > when)
134
        first_far_timer = when;
135
      add_tail(&far_timers, &t->n);
136
    }
137
}
138

    
139
void
140
tm_stop(timer *t)
141
{
142
  if (t->expires)
143
    {
144
      rem_node(&t->n);
145
      t->expires = 0;
146
    }
147
}
148

    
149
static void
150
tm_dump_them(char *name, list *l)
151
{
152
  node *n;
153
  timer *t;
154

    
155
  debug("%s timers:\n", name);
156
  WALK_LIST(n, *l)
157
    {
158
      t = SKIP_BACK(timer, n, n);
159
      debug("%p ", t);
160
      tm_dump(&t->r);
161
    }
162
  debug("\n");
163
}
164

    
165
void
166
tm_dump_all(void)
167
{
168
  tm_dump_them("Near", &near_timers);
169
  tm_dump_them("Far", &far_timers);
170
}
171

    
172
static inline time_t
173
tm_first_shot(void)
174
{
175
  time_t x = first_far_timer;
176

    
177
  if (!EMPTY_LIST(near_timers))
178
    {
179
      timer *t = SKIP_BACK(timer, n, HEAD(near_timers));
180
      if (t->expires < x)
181
        x = t->expires;
182
    }
183
  return x;
184
}
185

    
186
static void
187
tm_shot(void)
188
{
189
  timer *t;
190
  node *n, *m;
191

    
192
  if (first_far_timer <= now)
193
    {
194
      bird_clock_t limit = now + NEAR_TIMER_LIMIT;
195
      first_far_timer = TIME_INFINITY;
196
      n = HEAD(far_timers);
197
      while (m = n->next)
198
        {
199
          t = SKIP_BACK(timer, n, n);
200
          if (t->expires <= limit)
201
            {
202
              rem_node(n);
203
              tm_insert_near(t);
204
            }
205
          else if (t->expires < first_far_timer)
206
            first_far_timer = t->expires;
207
          n = m;
208
        }
209
    }
210
  while ((n = HEAD(near_timers)) -> next)
211
    {
212
      int delay;
213
      t = SKIP_BACK(timer, n, n);
214
      if (t->expires > now)
215
        break;
216
      rem_node(n);
217
      delay = t->expires - now;
218
      t->expires = 0;
219
      if (t->recurrent)
220
        {
221
          int i = t->recurrent - delay;
222
          if (i < 0)
223
            i = 0;
224
          tm_start(t, i);
225
        }
226
      t->hook(t);
227
    }
228
}
229

    
230
bird_clock_t
231
tm_parse_date(char *x)
232
{
233
  struct tm tm;
234
  int n;
235
  time_t t;
236

    
237
  if (sscanf(x, "%d-%d-%d%n", &tm.tm_mday, &tm.tm_mon, &tm.tm_year, &n) != 3 || x[n])
238
    return 0;
239
  tm.tm_mon--;
240
  tm.tm_year -= 1900;
241
  tm.tm_hour = tm.tm_min = tm.tm_sec = 0;
242
  t = mktime(&tm);
243
  if (t == (time_t) -1)
244
    return 0;
245
  return t;
246
}
247

    
248
void
249
tm_format_date(char *x, bird_clock_t t)
250
{
251
  struct tm *tm;
252

    
253
  tm = localtime(&t);
254
  sprintf(x, "%02d-%02d-%04d", tm->tm_mday, tm->tm_mon+1, tm->tm_year+1900);
255
}
256

    
257
void
258
tm_format_reltime(char *x, bird_clock_t t)
259
{
260
  struct tm *tm;
261
  bird_clock_t delta = now - t;
262
  static char *month_names[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
263

    
264
  tm = localtime(&t);
265
  if (delta < 0)
266
    strcpy(x, "?fut?");
267
  else if (delta < 20*3600)
268
    bsprintf(x, "%02d:%02d", tm->tm_hour, tm->tm_min);
269
  else if (delta < 360*86400)
270
    bsprintf(x, "%s%02d", month_names[tm->tm_mon], tm->tm_mday);
271
  else
272
    bsprintf(x, "%d", tm->tm_year+1900);
273
}
274

    
275
/*
276
 *        Sockets
277
 */
278

    
279
#ifndef SOL_IP
280
#define SOL_IP IPPROTO_IP
281
#endif
282

    
283
static list sock_list;
284

    
285
static void
286
sk_free(resource *r)
287
{
288
  sock *s = (sock *) r;
289

    
290
  if (s->fd >= 0)
291
    rem_node(&s->n);
292
}
293

    
294
static void
295
sk_dump(resource *r)
296
{
297
  sock *s = (sock *) r;
298
  static char *sk_type_names[] = { "TCP<", "TCP>", "TCP", "UDP", "UDP/MC", "IP", "IP/MC", "MAGIC", "UNIX<", "UNIX", "DEL!" };
299

    
300
  debug("(%s, ud=%p, sa=%08x, sp=%d, da=%08x, dp=%d, tos=%d, ttl=%d, if=%s)\n",
301
        sk_type_names[s->type],
302
        s->data,
303
        s->saddr,
304
        s->sport,
305
        s->daddr,
306
        s->dport,
307
        s->tos,
308
        s->ttl,
309
        s->iface ? s->iface->name : "none");
310
}
311

    
312
static struct resclass sk_class = {
313
  "Socket",
314
  sizeof(sock),
315
  sk_free,
316
  sk_dump
317
};
318

    
319
sock *
320
sk_new(pool *p)
321
{
322
  sock *s = ralloc(p, &sk_class);
323
  s->pool = p;
324
  s->data = NULL;
325
  s->saddr = s->daddr = IPA_NONE;
326
  s->sport = s->dport = 0;
327
  s->tos = s->ttl = -1;
328
  s->iface = NULL;
329
  s->rbuf = NULL;
330
  s->rx_hook = NULL;
331
  s->rbsize = 0;
332
  s->tbuf = NULL;
333
  s->tx_hook = NULL;
334
  s->tbsize = 0;
335
  s->err_hook = NULL;
336
  s->fd = -1;
337
  return s;
338
}
339

    
340
#define ERR(x) do { err = x; goto bad; } while(0)
341
#define WARN(x) log(L_WARN "sk_setup: " x)
342

    
343
#ifdef IPV6
344

    
345
static inline void
346
set_inaddr(struct in6_addr *ia, ip_addr a)
347
{
348
  ipa_hton(a);
349
  memcpy(ia, &a, sizeof(a));
350
}
351

    
352
void
353
fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port)
354
{
355
  sa->sin6_family = AF_INET6;
356
  sa->sin6_port = htons(port);
357
  sa->sin6_flowinfo = 0;
358
  set_inaddr(&sa->sin6_addr, a);
359
}
360

    
361
void
362
get_sockaddr(sockaddr *sa, ip_addr *a, unsigned *port)
363
{
364
  if (sa->sin6_family != AF_INET6)
365
    bug("get_sockaddr called for wrong address family");
366
  if (port)
367
    *port = ntohs(sa->sin6_port);
368
  memcpy(a, &sa->sin6_addr, sizeof(*a));
369
  ipa_ntoh(*a);
370
}
371

    
372
#else
373

    
374
static inline void
375
set_inaddr(struct in_addr *ia, ip_addr a)
376
{
377
  ipa_hton(a);
378
  memcpy(&ia->s_addr, &a, sizeof(a));
379
}
380

    
381
void
382
fill_in_sockaddr(sockaddr *sa, ip_addr a, unsigned port)
383
{
384
  sa->sin_family = AF_INET;
385
  sa->sin_port = htons(port);
386
  set_inaddr(&sa->sin_addr, a);
387
}
388

    
389
void
390
get_sockaddr(sockaddr *sa, ip_addr *a, unsigned *port)
391
{
392
  if (sa->sin_family != AF_INET)
393
    bug("get_sockaddr called for wrong address family");
394
  if (port)
395
    *port = ntohs(sa->sin_port);
396
  memcpy(a, &sa->sin_addr.s_addr, sizeof(*a));
397
  ipa_ntoh(*a);
398
}
399

    
400
#endif
401

    
402
static char *
403
sk_setup(sock *s)
404
{
405
  int fd = s->fd;
406
  int one = 1;
407
  char *err;
408

    
409
  if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
410
    ERR("fcntl(O_NONBLOCK)");
411
  if (s->type == SK_UNIX)
412
    return NULL;
413
#ifdef IPV6
414
  if (s->ttl >= 0 && s->type != SK_UDP_MC && s->type != SK_IP_MC &&
415
      setsockopt(fd, SOL_IPV6, IPV6_UNICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
416
    ERR("IPV6_UNICAST_HOPS");
417
#else
418
  if ((s->tos >= 0) && setsockopt(fd, SOL_IP, IP_TOS, &s->tos, sizeof(s->tos)) < 0)
419
    WARN("IP_TOS");
420
  if (s->ttl >= 0)
421
    {
422
      if (setsockopt(fd, SOL_IP, IP_TTL, &s->ttl, sizeof(s->ttl)) < 0)
423
        ERR("IP_TTL");
424
      if (setsockopt(fd, SOL_SOCKET, SO_DONTROUTE, &one, sizeof(one)) < 0)
425
        ERR("SO_DONTROUTE");
426
    }
427
#endif
428
  /* FIXME: Set send/receive buffers? */
429
  /* FIXME: Set keepalive for TCP connections? */
430
  err = NULL;
431
bad:
432
  return err;
433
}
434

    
435
static void
436
sk_alloc_bufs(sock *s)
437
{
438
  if (!s->rbuf && s->rbsize)
439
    s->rbuf = mb_alloc(s->pool, s->rbsize);
440
  s->rpos = s->rbuf;
441
  if (!s->tbuf && s->tbsize)
442
    s->tbuf = mb_alloc(s->pool, s->tbsize);
443
  s->tpos = s->ttx = s->tbuf;
444
}
445

    
446
static void
447
sk_tcp_connected(sock *s)
448
{
449
  s->rx_hook(s, 0);
450
  s->type = SK_TCP;
451
  sk_alloc_bufs(s);
452
}
453

    
454
static int
455
sk_passive_connected(sock *s, struct sockaddr *sa, int al, int type)
456
{
457
  int fd = accept(s->fd, sa, &al);
458
  if (fd >= 0)
459
    {
460
      sock *t = sk_new(s->pool);
461
      char *err;
462
      t->type = type;
463
      t->fd = fd;
464
      add_tail(&sock_list, &t->n);
465
      s->rx_hook(t, 0);
466
      if (err = sk_setup(t))
467
        {
468
          log(L_ERR "Incoming connection: %s: %m", err);
469
          s->err_hook(s, errno);
470
          return 0;
471
        }
472
      sk_alloc_bufs(t);
473
      return 1;
474
    }
475
  else if (errno != EINTR && errno != EAGAIN)
476
    {
477
      log(L_ERR "accept: %m");
478
      s->err_hook(s, errno);
479
    }
480
  return 0;
481
}
482

    
483
int
484
sk_open(sock *s)
485
{
486
  int fd, e;
487
  sockaddr sa;
488
  int zero = 0;
489
  int one = 1;
490
  int type = s->type;
491
  int has_src = ipa_nonzero(s->saddr) || s->sport;
492
  int has_dest = ipa_nonzero(s->daddr);
493
  char *err;
494

    
495
  switch (type)
496
    {
497
    case SK_TCP_ACTIVE:
498
    case SK_TCP_PASSIVE:
499
      fd = socket(BIRD_PF, SOCK_STREAM, IPPROTO_TCP);
500
      break;
501
    case SK_UDP:
502
    case SK_UDP_MC:
503
      fd = socket(BIRD_PF, SOCK_DGRAM, IPPROTO_UDP);
504
      break;
505
    case SK_IP:
506
    case SK_IP_MC:
507
      fd = socket(BIRD_PF, SOCK_RAW, s->dport);
508
      break;
509
    case SK_MAGIC:
510
      fd = s->fd;
511
      break;
512
    default:
513
      bug("sk_open() called for invalid sock type %d", type);
514
    }
515
  if (fd < 0)
516
    die("sk_open: socket: %m");
517
  s->fd = fd;
518

    
519
  if (err = sk_setup(s))
520
    goto bad;
521
  switch (type)
522
    {
523
    case SK_UDP:
524
    case SK_IP:
525
      if (s->iface)                        /* It's a broadcast socket */
526
#ifdef IPV6
527
        bug("IPv6 has no broadcasts");
528
#else
529
        if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)) < 0)
530
          ERR("SO_BROADCAST");
531
#endif
532
      break;
533
    case SK_UDP_MC:
534
    case SK_IP_MC:
535
      {
536
#ifdef IPV6
537
        /* Fortunately, IPv6 socket interface is recent enough and therefore standardized */
538
        ASSERT(s->iface && s->iface->addr);
539
        if (has_dest)
540
          {
541
            int t = s->iface->index;
542
            if (setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_HOPS, &s->ttl, sizeof(s->ttl)) < 0)
543
              ERR("IPV6_MULTICAST_HOPS");
544
            if (setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
545
              ERR("IPV6_MULTICAST_LOOP");
546
            if (setsockopt(fd, SOL_IPV6, IPV6_MULTICAST_IF, &t, sizeof(t)) < 0)
547
              ERR("IPV6_MULTICAST_IF");
548
          }
549
        if (has_src)
550
          {
551
            struct ipv6_mreq mreq;
552
            set_inaddr(&mreq.ipv6mr_multiaddr, s->daddr);
553
            mreq.ipv6mr_ifindex = s->iface->index;
554
            if (setsockopt(fd, SOL_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
555
              ERR("IPV6_ADD_MEMBERSHIP");
556
          }
557
#else
558
        /* With IPv4 there are zillions of different socket interface variants. Ugh. */
559
#ifdef HAVE_STRUCT_IP_MREQN
560
        struct ip_mreqn mreq;
561
#define mreq_add mreq
562
        ASSERT(s->iface && s->iface->addr);
563
        mreq.imr_ifindex = s->iface->index;
564
        set_inaddr(&mreq.imr_address, s->iface->addr->ip);
565
#else
566
        struct in_addr mreq;
567
        struct ip_mreq mreq_add;
568
        ASSERT(s->iface && s->iface->addr);
569
        set_inaddr(&mreq, s->iface->addr->ip);
570
#ifdef SO_BINDTODEVICE
571
        {
572
          struct ifreq ifr;
573
          strcpy(ifr.ifr_name, s->iface->name);
574
          if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) < 0)
575
            ERR("SO_BINDTODEVICE");
576
          mreq_add.imr_interface.s_addr = INADDR_ANY;
577
        }
578
#else
579
#error Multicasts not supported on PtP devices                /* FIXME: Solve it somehow? */
580
        mreq_add.imr_interface = mreq;
581
#endif
582
#endif
583
        set_inaddr(&mreq_add.imr_multiaddr, s->daddr);
584
        if (has_dest)
585
          {
586
            if (
587
#ifdef IP_DEFAULT_MULTICAST_TTL
588
                s->ttl != IP_DEFAULT_MULTICAST_TTL &&
589
#endif
590
                setsockopt(fd, SOL_IP, IP_MULTICAST_TTL, &s->ttl, sizeof(s->ttl)) < 0)
591
              ERR("IP_MULTICAST_TTL");
592
            if (
593
#ifdef IP_DEFAULT_MULTICAST_LOOP
594
                IP_DEFAULT_MULTICAST_LOOP &&
595
#endif
596
                setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &zero, sizeof(zero)) < 0)
597
              ERR("IP_MULTICAST_LOOP");
598
            /* This defines where should we send _outgoing_ multicasts */
599
            if (setsockopt(fd, SOL_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq)) < 0)
600
              ERR("IP_MULTICAST_IF");
601
        }
602
      /* And this one sets interface for _receiving_ multicasts from */
603
      if (has_src && setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq_add, sizeof(mreq_add)) < 0)
604
        ERR("IP_ADD_MEMBERSHIP");
605
#endif
606
      break;
607
      }
608
    }
609
  if (has_src)
610
    {
611
      int port;
612

    
613
      if (type == SK_IP || type == SK_IP_MC)
614
        port = 0;
615
      else
616
        {
617
          port = s->sport;
618
          if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
619
            ERR("SO_REUSEADDR");
620
        }
621
      fill_in_sockaddr(&sa, s->saddr, port);
622
      if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
623
        ERR("bind");
624
    }
625
  fill_in_sockaddr(&sa, s->daddr, s->dport);
626
  switch (type)
627
    {
628
    case SK_TCP_ACTIVE:
629
      if (connect(fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0)
630
        sk_tcp_connected(s);
631
      else if (errno != EINTR && errno != EAGAIN)
632
        ERR("connect");
633
      break;
634
    case SK_TCP_PASSIVE:
635
      if (listen(fd, 8))
636
        ERR("listen");
637
      break;
638
    case SK_MAGIC:
639
      break;
640
    default:
641
#ifdef IPV6
642
#ifdef IPV6_MTU_DISCOVER
643
      {
644
        int dont = IPV6_PMTUDISC_DONT;
645
        if (setsockopt(fd, SOL_IPV6, IPV6_MTU_DISCOVER, &dont, sizeof(dont)) < 0)
646
          ERR("IPV6_MTU_DISCOVER");
647
      }
648
#endif
649
#else
650
#ifdef IP_PMTUDISC
651
      {
652
        int dont = IP_PMTUDISC_DONT;
653
        if (setsockopt(fd, SOL_IP, IP_PMTUDISC, &dont, sizeof(dont)) < 0)
654
          ERR("IP_PMTUDISC");
655
      }
656
#endif
657
#endif
658
    }
659

    
660
  sk_alloc_bufs(s);
661
  add_tail(&sock_list, &s->n);
662
  return 0;
663

    
664
bad:
665
  log(L_ERR "sk_open: %s: %m", err);
666
  close(fd);
667
  s->fd = -1;
668
  return -1;
669
}
670

    
671
int
672
sk_open_unix(sock *s, char *name)
673
{
674
  int fd;
675
  struct sockaddr_un sa;
676
  char *err;
677

    
678
  fd = socket(AF_UNIX, SOCK_STREAM, 0);
679
  if (fd < 0)
680
    die("sk_open_unix: socket: %m");
681
  s->fd = fd;
682
  if (err = sk_setup(s))
683
    goto bad;
684
  unlink(name);
685
  sa.sun_family = AF_UNIX;
686
  strcpy(sa.sun_path, name);
687
  if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
688
    ERR("bind");
689
  if (listen(fd, 8))
690
    ERR("listen");
691
  sk_alloc_bufs(s);
692
  add_tail(&sock_list, &s->n);
693
  return 0;
694

    
695
bad:
696
  log(L_ERR "sk_open_unix: %s: %m", err);
697
  close(fd);
698
  s->fd = -1;
699
  return -1;
700
}
701

    
702
static int
703
sk_maybe_write(sock *s)
704
{
705
  int e;
706

    
707
  switch (s->type)
708
    {
709
    case SK_TCP:
710
    case SK_MAGIC:
711
    case SK_UNIX:
712
      while (s->ttx != s->tpos)
713
        {
714
          e = write(s->fd, s->ttx, s->tpos - s->ttx);
715
          if (e < 0)
716
            {
717
              if (errno != EINTR && errno != EAGAIN)
718
                {
719
                  log(L_ERR "write: %m");
720
                  s->err_hook(s, errno);
721
                  return -1;
722
                }
723
              return 0;
724
            }
725
          s->ttx += e;
726
        }
727
      s->ttx = s->tpos = s->tbuf;
728
      return 1;
729
    case SK_UDP:
730
    case SK_UDP_MC:
731
    case SK_IP:
732
    case SK_IP_MC:
733
      {
734
        sockaddr sa;
735

    
736
        if (s->tbuf == s->tpos)
737
          return 1;
738
        fill_in_sockaddr(&sa, s->faddr, s->fport);
739
        e = sendto(s->fd, s->tbuf, s->tpos - s->tbuf, 0, (struct sockaddr *) &sa, sizeof(sa));
740
        if (e < 0)
741
          {
742
            if (errno != EINTR && errno != EAGAIN)
743
              {
744
                log(L_ERR "sendto: %m");
745
                s->err_hook(s, errno);
746
                return -1;
747
              }
748
            return 0;
749
          }
750
        s->tpos = s->tbuf;
751
        return 1;
752
      }
753
    default:
754
      bug("sk_maybe_write: unknown socket type %d", s->type);
755
    }
756
}
757

    
758
int
759
sk_send(sock *s, unsigned len)
760
{
761
  s->faddr = s->daddr;
762
  s->fport = s->dport;
763
  s->ttx = s->tbuf;
764
  s->tpos = s->tbuf + len;
765
  return sk_maybe_write(s);
766
}
767

    
768
int
769
sk_send_to(sock *s, unsigned len, ip_addr addr, unsigned port)
770
{
771
  s->faddr = addr;
772
  s->fport = port;
773
  s->ttx = s->tbuf;
774
  s->tpos = s->tbuf + len;
775
  return sk_maybe_write(s);
776
}
777

    
778
static int
779
sk_read(sock *s)
780
{
781
  switch (s->type)
782
    {
783
    case SK_TCP_ACTIVE:
784
      {
785
        sockaddr sa;
786
        fill_in_sockaddr(&sa, s->daddr, s->dport);
787
        if (connect(s->fd, (struct sockaddr *) &sa, sizeof(sa)) >= 0)
788
          sk_tcp_connected(s);
789
        else if (errno != EINTR && errno != EAGAIN)
790
          {
791
            log(L_ERR "connect: %m");
792
            s->err_hook(s, errno);
793
          }
794
        return 0;
795
      }
796
    case SK_TCP_PASSIVE:
797
      {
798
        sockaddr sa;
799
        return sk_passive_connected(s, (struct sockaddr *) &sa, sizeof(sa), SK_TCP);
800
      }
801
    case SK_UNIX_PASSIVE:
802
      {
803
        struct sockaddr_un sa;
804
        return sk_passive_connected(s, (struct sockaddr *) &sa, sizeof(sa), SK_UNIX);
805
      }
806
    case SK_TCP:
807
    case SK_UNIX:
808
      {
809
        int c = read(s->fd, s->rpos, s->rbuf + s->rbsize - s->rpos);
810

    
811
        if (c < 0)
812
          {
813
            if (errno != EINTR && errno != EAGAIN)
814
              {
815
                log(L_ERR "read: %m");
816
                s->err_hook(s, errno);
817
              }
818
          }
819
        else if (!c)
820
          s->err_hook(s, 0);
821
        else
822
          {
823
            s->rpos += c;
824
            if (s->rx_hook(s, s->rpos - s->rbuf))
825
              s->rpos = s->rbuf;
826
            return 1;
827
          }
828
        return 0;
829
      }
830
    case SK_MAGIC:
831
      return s->rx_hook(s, 0);
832
    default:
833
      {
834
        sockaddr sa;
835
        int al = sizeof(sa);
836
        int e = recvfrom(s->fd, s->rbuf, s->rbsize, 0, (struct sockaddr *) &sa, &al);
837

    
838
        if (e < 0)
839
          {
840
            if (errno != EINTR && errno != EAGAIN)
841
              {
842
                log(L_ERR "recvfrom: %m");
843
                s->err_hook(s, errno);
844
              }
845
            return 0;
846
          }
847
        s->rpos = s->rbuf + e;
848
        get_sockaddr(&sa, &s->faddr, &s->fport);
849
        s->rx_hook(s, e);
850
        return 1;
851
      }
852
    }
853
}
854

    
855
static void
856
sk_write(sock *s)
857
{
858
  while (s->ttx != s->tbuf && sk_maybe_write(s) > 0)
859
    s->tx_hook(s);
860
}
861

    
862
void
863
sk_dump_all(void)
864
{
865
  node *n;
866
  sock *s;
867

    
868
  debug("Open sockets:\n");
869
  WALK_LIST(n, sock_list)
870
    {
871
      s = SKIP_BACK(sock, n, n);
872
      debug("%p ", s);
873
      sk_dump(&s->r);
874
    }
875
  debug("\n");
876
}
877

    
878
#undef ERR
879
#undef WARN
880

    
881
/*
882
 *        Main I/O Loop
883
 */
884

    
885
volatile int async_config_flag;                /* Asynchronous reconfiguration/dump scheduled */
886
volatile int async_dump_flag;
887

    
888
void
889
io_init(void)
890
{
891
  init_list(&near_timers);
892
  init_list(&far_timers);
893
  init_list(&sock_list);
894
  init_list(&global_event_list);
895
  krt_io_init();
896
  now = time(NULL);
897
  srandom((int) now);
898
}
899

    
900
void
901
io_loop(void)
902
{
903
  fd_set rd, wr;
904
  struct timeval timo;
905
  time_t tout;
906
  int hi, events;
907
  sock *s;
908
  node *n, *p;
909

    
910
  /* FIXME: Use poll() if available */
911

    
912
  FD_ZERO(&rd);
913
  FD_ZERO(&wr);
914
  for(;;)
915
    {
916
      events = ev_run_list(&global_event_list);
917
      now = time(NULL);
918
      tout = tm_first_shot();
919
      if (tout <= now)
920
        {
921
          tm_shot();
922
          continue;
923
        }
924
      timo.tv_sec = events ? 0 : tout - now;
925
      timo.tv_usec = 0;
926

    
927
      hi = 0;
928
      WALK_LIST(n, sock_list)
929
        {
930
          s = SKIP_BACK(sock, n, n);
931
          if (s->rx_hook)
932
            {
933
              FD_SET(s->fd, &rd);
934
              if (s->fd > hi)
935
                hi = s->fd;
936
            }
937
          if (s->tx_hook && s->ttx != s->tpos)
938
            {
939
              FD_SET(s->fd, &wr);
940
              if (s->fd > hi)
941
                hi = s->fd;
942
            }
943
        }
944

    
945
      /*
946
       * Yes, this is racy. But even if the signal comes before this test
947
       * and entering select(), it gets caught on the next timer tick.
948
       */
949

    
950
      if (async_config_flag)
951
        {
952
          async_config();
953
          async_config_flag = 0;
954
          continue;
955
        }
956
      if (async_dump_flag)
957
        {
958
          async_dump();
959
          async_dump_flag = 0;
960
          continue;
961
        }
962
      if (async_shutdown_flag)
963
        {
964
          async_shutdown();
965
          async_shutdown_flag = 0;
966
          continue;
967
        }
968

    
969
      /* And finally enter select() to find active sockets */
970

    
971
      hi = select(hi+1, &rd, &wr, NULL, &timo);
972
      if (hi < 0)
973
        {
974
          if (errno == EINTR || errno == EAGAIN)
975
            continue;
976
          die("select: %m");
977
        }
978
      if (hi)
979
        {
980
          WALK_LIST_DELSAFE(n, p, sock_list)
981
            {
982
              s = SKIP_BACK(sock, n, n);
983
              if (FD_ISSET(s->fd, &rd))
984
                {
985
                  FD_CLR(s->fd, &rd);
986
                  while (sk_read(s))
987
                    ;
988
                }
989
              if (s->type != SK_DELETED && FD_ISSET(s->fd, &wr))
990
                {
991
                  FD_CLR(s->fd, &wr);
992
                  sk_write(s);
993
                }
994
              if (s->type == SK_DELETED)
995
                rfree(s);
996
            }
997
        }
998
    }
999
}