Statistics
| Branch: | Revision:

iof-bird-daemon / sysdep / bsd / krt-sock.c @ c01a9466

History | View | Annotate | Download (21.9 KB)

1
/*
2
 *        BIRD -- BSD Routing Table Syncing
3
 *
4
 *        (c) 2004 Ondrej Filip <feela@network.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 <ctype.h>
12
#include <fcntl.h>
13
#include <unistd.h>
14
#include <sys/param.h>
15
#include <sys/types.h>
16
#include <sys/socket.h>
17
#include <sys/sysctl.h>
18
#include <sys/ioctl.h>
19
#include <netinet/in.h>
20
#include <net/route.h>
21
#include <net/if.h>
22
#include <net/if_dl.h>
23

    
24
#undef LOCAL_DEBUG
25

    
26
#include "nest/bird.h"
27
#include "nest/iface.h"
28
#include "nest/route.h"
29
#include "nest/protocol.h"
30
#include "nest/iface.h"
31
#include "lib/timer.h"
32
#include "lib/unix.h"
33
#include "lib/krt.h"
34
#include "lib/string.h"
35
#include "lib/socket.h"
36

    
37

    
38
/*
39
 * There are significant differences in multiple tables support between BSD variants.
40
 *
41
 * OpenBSD has table_id field for routes in route socket protocol, therefore all
42
 * tables could be managed by one kernel socket. FreeBSD lacks such field,
43
 * therefore multiple sockets (locked to specific table using SO_SETFIB socket
44
 * option) must be used.
45
 *
46
 * Both FreeBSD and OpenBSD uses separate scans for each table. In OpenBSD,
47
 * table_id is specified explicitly as sysctl scan argument, while in FreeBSD it
48
 * is handled implicitly by changing default table using setfib() syscall.
49
 *
50
 * KRT_SHARED_SOCKET        - use shared kernel socked instead of one for each krt_proto
51
 * KRT_USE_SETFIB_SCAN        - use setfib() for sysctl() route scan
52
 * KRT_USE_SETFIB_SOCK        - use SO_SETFIB socket option for kernel sockets
53
 * KRT_USE_SYSCTL_7        - use 7-th arg of sysctl() as table id for route scans
54
 * KRT_USE_SYSCTL_NET_FIBS - use net.fibs sysctl() for dynamic max number of fibs
55
 */
56

    
57
#ifdef __FreeBSD__
58
#define KRT_MAX_TABLES 256
59
#define KRT_USE_SETFIB_SCAN
60
#define KRT_USE_SETFIB_SOCK
61
#define KRT_USE_SYSCTL_NET_FIBS
62
#endif
63

    
64
#ifdef __OpenBSD__
65
#define KRT_MAX_TABLES (RT_TABLEID_MAX+1)
66
#define KRT_SHARED_SOCKET
67
#define KRT_USE_SYSCTL_7
68
#endif
69

    
70
#ifndef KRT_MAX_TABLES
71
#define KRT_MAX_TABLES 1
72
#endif
73

    
74

    
75

    
76
/* Dynamic max number of tables */
77

    
78
int krt_max_tables;
79

    
80
#ifdef KRT_USE_SYSCTL_NET_FIBS
81

    
82
static int
83
krt_get_max_tables(void)
84
{
85
  int fibs;
86
  size_t fibs_len = sizeof(fibs);
87

    
88
  if (sysctlbyname("net.fibs", &fibs, &fibs_len, NULL, 0) < 0)
89
  {
90
    log(L_WARN "KRT: unable to get max number of fib tables: %m");
91
    return 1;
92
  }
93

    
94
  return MIN(fibs, KRT_MAX_TABLES);
95
}
96

    
97
#else
98

    
99
static int
100
krt_get_max_tables(void)
101
{
102
  return KRT_MAX_TABLES;
103
}
104

    
105
#endif /* KRT_USE_SYSCTL_NET_FIBS */
106

    
107

    
108
/* setfib() syscall for FreeBSD scans */
109

    
110
#ifdef KRT_USE_SETFIB_SCAN
111

    
112
/*
113
static int krt_default_fib;
114

115
static int
116
krt_get_active_fib(void)
117
{
118
  int fib;
119
  size_t fib_len = sizeof(fib);
120

121
  if (sysctlbyname("net.my_fibnum", &fib, &fib_len, NULL, 0) < 0)
122
  {
123
    log(L_WARN "KRT: unable to get active fib number: %m");
124
    return 0;
125
  }
126

127
  return fib;
128
}
129
*/
130

    
131
extern int setfib(int fib);
132

    
133
#endif /* KRT_USE_SETFIB_SCAN */
134

    
135

    
136
/* table_id -> krt_proto map */
137

    
138
#ifdef KRT_SHARED_SOCKET
139
static struct krt_proto *krt_table_map[KRT_MAX_TABLES];
140
#endif
141

    
142

    
143
/* Route socket message processing */
144

    
145
int
146
krt_capable(rte *e)
147
{
148
  rta *a = e->attrs;
149

    
150
  return
151
    a->cast == RTC_UNICAST &&
152
    (a->dest == RTD_ROUTER
153
     || a->dest == RTD_DEVICE
154
#ifdef RTF_REJECT
155
     || a->dest == RTD_UNREACHABLE
156
#endif
157
#ifdef RTF_BLACKHOLE
158
     || a->dest == RTD_BLACKHOLE
159
#endif
160
     );
161
}
162

    
163
#ifndef RTAX_MAX
164
#define RTAX_MAX 8
165
#endif
166

    
167
struct ks_msg
168
{
169
  struct rt_msghdr rtm;
170
  struct sockaddr_storage buf[RTAX_MAX];
171
};
172

    
173
#define ROUNDUP(a) \
174
        ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
175

    
176
#define NEXTADDR(w, u) \
177
        if (msg.rtm.rtm_addrs & (w)) {\
178
          l = ROUNDUP(((struct sockaddr *)&(u))->sa_len);\
179
          memmove(body, &(u), l); body += l;}
180

    
181
#define GETADDR(p, F) \
182
  bzero(p, sizeof(*p));\
183
  if ((addrs & (F)) && ((struct sockaddr *)body)->sa_len) {\
184
    unsigned int l = ROUNDUP(((struct sockaddr *)body)->sa_len);\
185
    memcpy(p, body, (l > sizeof(*p) ? sizeof(*p) : l));\
186
    body += l;}
187

    
188
static int
189
krt_send_route(struct krt_proto *p, int cmd, rte *e)
190
{
191
  net *net = e->net;
192
  rta *a = e->attrs;
193
  static int msg_seq;
194
  struct iface *j, *i = a->iface;
195
  int l;
196
  struct ks_msg msg;
197
  char *body = (char *)msg.buf;
198
  sockaddr gate, mask, dst;
199
  ip_addr gw;
200

    
201
  DBG("krt-sock: send %I/%d via %I\n", net->n.prefix, net->n.pxlen, a->gw);
202

    
203
  bzero(&msg,sizeof (struct rt_msghdr));
204
  msg.rtm.rtm_version = RTM_VERSION;
205
  msg.rtm.rtm_type = cmd;
206
  msg.rtm.rtm_seq = msg_seq++;
207
  msg.rtm.rtm_addrs = RTA_DST;
208
  msg.rtm.rtm_flags = RTF_UP | RTF_PROTO1;
209

    
210
  if (net->n.pxlen == MAX_PREFIX_LENGTH)
211
    msg.rtm.rtm_flags |= RTF_HOST;
212
  else
213
    msg.rtm.rtm_addrs |= RTA_NETMASK;
214

    
215
#ifdef KRT_SHARED_SOCKET
216
  msg.rtm.rtm_tableid = KRT_CF->sys.table_id;
217
#endif
218

    
219
#ifdef RTF_REJECT
220
  if(a->dest == RTD_UNREACHABLE)
221
    msg.rtm.rtm_flags |= RTF_REJECT;
222
#endif
223
#ifdef RTF_BLACKHOLE
224
  if(a->dest == RTD_BLACKHOLE)
225
    msg.rtm.rtm_flags |= RTF_BLACKHOLE;
226
#endif
227

    
228
  /* This is really very nasty, but I'm not able
229
   * to add "(reject|blackhole)" route without
230
   * gateway set
231
   */
232
  if(!i)
233
  {
234
    i = HEAD(iface_list);
235

    
236
    WALK_LIST(j, iface_list)
237
    {
238
      if (j->flags & IF_LOOPBACK)
239
      {
240
        i = j;
241
        break;
242
      }
243
    }
244
  }
245

    
246
  gw = a->gw;
247

    
248
#ifdef IPV6
249
  /* Embed interface ID to link-local address */
250
  if (ipa_has_link_scope(gw))
251
    _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
252
#endif
253

    
254
  fill_in_sockaddr(&dst, net->n.prefix, NULL, 0);
255
  fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), NULL, 0);
256
  fill_in_sockaddr(&gate, gw, NULL, 0);
257

    
258
  switch (a->dest)
259
  {
260
    case RTD_ROUTER:
261
      msg.rtm.rtm_flags |= RTF_GATEWAY;
262
      msg.rtm.rtm_addrs |= RTA_GATEWAY;
263
      break;
264
#ifdef RTF_REJECT
265
    case RTD_UNREACHABLE:
266
#endif
267
#ifdef RTF_BLACKHOLE
268
    case RTD_BLACKHOLE:
269
#endif
270
    case RTD_DEVICE:
271
      if(i)
272
      {
273
#ifdef RTF_CLONING
274
        if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS)        /* PTP */
275
          msg.rtm.rtm_flags |= RTF_CLONING;
276
#endif
277

    
278
        if(!i->addr) {
279
          log(L_ERR "KRT: interface %s has no IP addess", i->name);
280
          return -1;
281
        }
282

    
283
        fill_in_sockaddr(&gate, i->addr->ip, NULL, 0);
284
        msg.rtm.rtm_addrs |= RTA_GATEWAY;
285
      }
286
      break;
287
    default:
288
      bug("krt-sock: unknown flags, but not filtered");
289
  }
290

    
291
  msg.rtm.rtm_index = i->index;
292

    
293
  NEXTADDR(RTA_DST, dst);
294
  NEXTADDR(RTA_GATEWAY, gate);
295
  NEXTADDR(RTA_NETMASK, mask);
296

    
297
  l = body - (char *)&msg;
298
  msg.rtm.rtm_msglen = l;
299

    
300
  if ((l = write(p->sys.sk->fd, (char *)&msg, l)) < 0) {
301
    log(L_ERR "KRT: Error sending route %I/%d to kernel: %m", net->n.prefix, net->n.pxlen);
302
    return -1;
303
  }
304

    
305
  return 0;
306
}
307

    
308
void
309
krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old,
310
                struct ea_list *eattrs UNUSED)
311
{
312
  int err = 0;
313

    
314
  if (old)
315
    krt_send_route(p, RTM_DELETE, old);
316

    
317
  if (new)
318
    err = krt_send_route(p, RTM_ADD, new);
319

    
320
  if (err < 0)
321
    n->n.flags |= KRF_SYNC_ERROR;
322
  else
323
    n->n.flags &= ~KRF_SYNC_ERROR;
324
}
325

    
326
#define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
327

    
328
static void
329
krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
330
{
331
  /* p is NULL iff KRT_SHARED_SOCKET and !scan */
332

    
333
  rte *e;
334
  net *net;
335
  sockaddr dst, gate, mask;
336
  ip_addr idst, igate, imask;
337
  void *body = (char *)msg->buf;
338
  int new = (msg->rtm.rtm_type == RTM_ADD);
339
  char *errmsg = "KRT: Invalid route received";
340
  int flags = msg->rtm.rtm_flags;
341
  int addrs = msg->rtm.rtm_addrs;
342
  int src;
343
  byte src2;
344

    
345
  if (!(flags & RTF_UP) && scan)
346
    SKIP("not up in scan\n");
347

    
348
  if (!(flags & RTF_DONE) && !scan)
349
    SKIP("not done in async\n");
350

    
351
  if (flags & RTF_LLINFO)
352
    SKIP("link-local\n");
353

    
354
#ifdef KRT_SHARED_SOCKET
355
  if (!scan)
356
  {
357
    int table_id = msg->rtm.rtm_tableid;
358
    p = (table_id < KRT_MAX_TABLES) ? krt_table_map[table_id] : NULL;
359

    
360
    if (!p)
361
      SKIP("unknown table id %d\n", table_id);
362
  }
363
#endif
364

    
365
  GETADDR(&dst, RTA_DST);
366
  GETADDR(&gate, RTA_GATEWAY);
367
  GETADDR(&mask, RTA_NETMASK);
368

    
369
  if (sa_family_check(&dst))
370
    get_sockaddr(&dst, &idst, NULL, NULL, 0);
371
  else
372
    SKIP("invalid DST");
373

    
374
  /* We will check later whether we have valid gateway addr */
375
  if (sa_family_check(&gate))
376
    get_sockaddr(&gate, &igate, NULL, NULL, 0);
377
  else
378
    igate = IPA_NONE;
379

    
380
  /* We do not test family for RTA_NETMASK, because BSD sends us
381
     some strange values, but interpreting them as IPv4/IPv6 works */
382
  get_sockaddr(&mask, &imask, NULL, NULL, 0);
383

    
384
  int c = ipa_classify_net(idst);
385
  if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
386
    SKIP("strange class/scope\n");
387

    
388
  int pxlen = (flags & RTF_HOST) ? MAX_PREFIX_LENGTH : ipa_mklen(imask);
389
  if (pxlen < 0)
390
    { log(L_ERR "%s (%I) - netmask %I", errmsg, idst, imask); return; }
391

    
392
  if ((flags & RTF_GATEWAY) && ipa_zero(igate))
393
    { log(L_ERR "%s (%I/%d) - missing gateway", errmsg, idst, pxlen); return; }
394

    
395
  u32 self_mask = RTF_PROTO1;
396
  u32 alien_mask = RTF_STATIC | RTF_PROTO1 | RTF_GATEWAY;
397

    
398
  src2 = (flags & RTF_STATIC) ? 1 : 0;
399
  src2 |= (flags & RTF_PROTO1) ? 2 : 0;
400

    
401
#ifdef RTF_PROTO2
402
  alien_mask |= RTF_PROTO2;
403
  src2 |= (flags & RTF_PROTO2) ? 4 : 0;
404
#endif
405

    
406
#ifdef RTF_PROTO3
407
  alien_mask |= RTF_PROTO3;
408
  src2 |= (flags & RTF_PROTO3) ? 8 : 0;
409
#endif
410

    
411
#ifdef RTF_REJECT
412
  alien_mask |= RTF_REJECT;
413
#endif
414

    
415
#ifdef RTF_BLACKHOLE
416
  alien_mask |= RTF_BLACKHOLE;
417
#endif
418

    
419
  if (flags & (RTF_DYNAMIC | RTF_MODIFIED))
420
    src = KRT_SRC_REDIRECT;
421
  else if (flags & self_mask)
422
    {
423
      if (!scan)
424
        SKIP("echo\n");
425
      src = KRT_SRC_BIRD;
426
    }
427
  else if (flags & alien_mask)
428
    src = KRT_SRC_ALIEN;
429
  else
430
    src = KRT_SRC_KERNEL;
431

    
432
  net = net_get(p->p.table, idst, pxlen);
433

    
434
  rta a = {
435
    .proto = &p->p,
436
    .source = RTS_INHERIT,
437
    .scope = SCOPE_UNIVERSE,
438
    .cast = RTC_UNICAST
439
  };
440

    
441
  /* reject/blackhole routes have also set RTF_GATEWAY,
442
     we wil check them first. */
443

    
444
#ifdef RTF_REJECT
445
  if(flags & RTF_REJECT) {
446
    a.dest = RTD_UNREACHABLE;
447
    goto done;
448
  }
449
#endif
450

    
451
#ifdef RTF_BLACKHOLE
452
  if(flags & RTF_BLACKHOLE) {
453
    a.dest = RTD_BLACKHOLE;
454
    goto done;
455
  }
456
#endif
457

    
458
  a.iface = if_find_by_index(msg->rtm.rtm_index);
459
  if (!a.iface)
460
    {
461
      log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u",
462
          net->n.prefix, net->n.pxlen, msg->rtm.rtm_index);
463
      return;
464
    }
465

    
466
  if (flags & RTF_GATEWAY)
467
  {
468
    neighbor *ng;
469
    a.dest = RTD_ROUTER;
470
    a.gw = igate;
471

    
472
#ifdef IPV6
473
    /* Clean up embedded interface ID returned in link-local address */
474
    if (ipa_has_link_scope(a.gw))
475
      _I0(a.gw) = 0xfe800000;
476
#endif
477

    
478
    ng = neigh_find2(&p->p, &a.gw, a.iface, 0);
479
    if (!ng || (ng->scope == SCOPE_HOST))
480
      {
481
        /* Ignore routes with next-hop 127.0.0.1, host routes with such
482
           next-hop appear on OpenBSD for address aliases. */
483
        if (ipa_classify(a.gw) == (IADDR_HOST | SCOPE_HOST))
484
          return;
485

    
486
        log(L_ERR "KRT: Received route %I/%d with strange next-hop %I",
487
            net->n.prefix, net->n.pxlen, a.gw);
488
        return;
489
      }
490
  }
491
  else
492
    a.dest = RTD_DEVICE;
493

    
494
 done:
495
  e = rte_get_temp(&a);
496
  e->net = net;
497
  e->u.krt.src = src;
498
  e->u.krt.proto = src2;
499

    
500
  /* These are probably too Linux-specific */
501
  e->u.krt.type = 0;
502
  e->u.krt.metric = 0;
503

    
504
  if (scan)
505
    krt_got_route(p, e);
506
  else
507
    krt_got_route_async(p, e, new);
508
}
509

    
510
static void
511
krt_read_ifannounce(struct ks_msg *msg)
512
{
513
  struct if_announcemsghdr *ifam = (struct if_announcemsghdr *)&msg->rtm;
514

    
515
  if (ifam->ifan_what == IFAN_ARRIVAL)
516
  {
517
    /* Not enough info to create the iface, so we just trigger iface scan */
518
    kif_request_scan();
519
  }
520
  else if (ifam->ifan_what == IFAN_DEPARTURE)
521
  {
522
    struct iface *iface = if_find_by_index(ifam->ifan_index);
523

    
524
    /* Interface is destroyed */
525
    if (!iface)
526
    {
527
      DBG("KRT: unknown interface (%s, #%d) going down. Ignoring\n", ifam->ifan_name, ifam->ifan_index);
528
      return;
529
    }
530

    
531
    if_delete(iface);
532
  }
533

    
534
  DBG("KRT: IFANNOUNCE what: %d index %d name %s\n", ifam->ifan_what, ifam->ifan_index, ifam->ifan_name);
535
}
536

    
537
static void
538
krt_read_ifinfo(struct ks_msg *msg)
539
{
540
  struct if_msghdr *ifm = (struct if_msghdr *)&msg->rtm;
541
  void *body = (void *)(ifm + 1);
542
  struct sockaddr_dl *dl = NULL;
543
  unsigned int i;
544
  struct iface *iface = NULL, f = {};
545
  int fl = ifm->ifm_flags;
546
  int nlen = 0;
547

    
548
  for (i = 1; i<=RTA_IFP; i <<= 1)
549
  {
550
    if (i & ifm->ifm_addrs)
551
    {
552
      if (i == RTA_IFP)
553
      {
554
        dl = (struct sockaddr_dl *)body;
555
        break;
556
      }
557
      body += ROUNDUP(((struct sockaddr *)&(body))->sa_len);
558
    }
559
  }
560

    
561
  if (dl && (dl->sdl_family != AF_LINK))
562
  {
563
    log(L_WARN "Ignoring strange IFINFO");
564
    return;
565
  }
566

    
567
  if (dl)
568
    nlen = MIN(sizeof(f.name)-1, dl->sdl_nlen);
569

    
570
  /* Note that asynchronous IFINFO messages do not contain iface
571
     name, so we have to found an existing iface by iface index */
572

    
573
  iface = if_find_by_index(ifm->ifm_index);
574
  if (!iface)
575
  {
576
    /* New interface */
577
    if (!dl)
578
      return;        /* No interface name, ignoring */
579

    
580
    memcpy(f.name, dl->sdl_data, nlen);
581
    DBG("New interface '%s' found\n", f.name);
582
  }
583
  else if (dl && memcmp(iface->name, dl->sdl_data, nlen))
584
  {
585
    /* Interface renamed */
586
    if_delete(iface);
587
    memcpy(f.name, dl->sdl_data, nlen);
588
  }
589
  else
590
  {
591
    /* Old interface */
592
    memcpy(f.name, iface->name, sizeof(f.name));
593
  }
594

    
595
  f.index = ifm->ifm_index;
596
  f.mtu = ifm->ifm_data.ifi_mtu;
597

    
598
  if (fl & IFF_UP)
599
    f.flags |= IF_ADMIN_UP;
600
  if (ifm->ifm_data.ifi_link_state != LINK_STATE_DOWN)
601
    f.flags |= IF_LINK_UP;          /* up or unknown */
602
  if (fl & IFF_LOOPBACK)            /* Loopback */
603
    f.flags |= IF_MULTIACCESS | IF_LOOPBACK | IF_IGNORE;
604
  else if (fl & IFF_POINTOPOINT)    /* PtP */
605
    f.flags |= IF_MULTICAST;
606
  else if (fl & IFF_BROADCAST)      /* Broadcast */
607
    f.flags |= IF_MULTIACCESS | IF_BROADCAST | IF_MULTICAST;
608
  else
609
    f.flags |= IF_MULTIACCESS;      /* NBMA */
610

    
611
  if_update(&f);
612
}
613

    
614
static void
615
krt_read_addr(struct ks_msg *msg)
616
{
617
  struct ifa_msghdr *ifam = (struct ifa_msghdr *)&msg->rtm;
618
  void *body = (void *)(ifam + 1);
619
  sockaddr addr, mask, brd;
620
  struct iface *iface = NULL;
621
  struct ifa ifa;
622
  struct sockaddr null;
623
  ip_addr iaddr, imask, ibrd;
624
  int addrs = ifam->ifam_addrs;
625
  int scope, masklen = -1;
626
  int new = (ifam->ifam_type == RTM_NEWADDR);
627

    
628
  /* Strange messages with zero (invalid) ifindex appear on OpenBSD */
629
  if (ifam->ifam_index == 0)
630
    return;
631

    
632
  if(!(iface = if_find_by_index(ifam->ifam_index)))
633
  {
634
    log(L_ERR "KIF: Received address message for unknown interface %d", ifam->ifam_index);
635
    return;
636
  }
637

    
638
  GETADDR (&null, RTA_DST);
639
  GETADDR (&null, RTA_GATEWAY);
640
  GETADDR (&mask, RTA_NETMASK);
641
  GETADDR (&null, RTA_GENMASK);
642
  GETADDR (&null, RTA_IFP);
643
  GETADDR (&addr, RTA_IFA);
644
  GETADDR (&null, RTA_AUTHOR);
645
  GETADDR (&brd, RTA_BRD);
646

    
647
  /* Some other family address */
648
  if (!sa_family_check(&addr))
649
    return;
650

    
651
  get_sockaddr(&addr, &iaddr, NULL, NULL, 0);
652
  get_sockaddr(&mask, &imask, NULL, NULL, 0);
653
  get_sockaddr(&brd, &ibrd, NULL, NULL, 0);
654

    
655
  if ((masklen = ipa_mklen(imask)) < 0)
656
  {
657
    log("Invalid masklen");
658
    return;
659
  }
660

    
661
  bzero(&ifa, sizeof(ifa));
662

    
663
  ifa.iface = iface;
664

    
665
  memcpy(&ifa.ip, &iaddr, sizeof(ip_addr));
666
  ifa.pxlen = masklen;
667
  memcpy(&ifa.brd, &ibrd, sizeof(ip_addr));
668

    
669
  scope = ipa_classify(ifa.ip);
670
  if (scope < 0)
671
  {
672
    log(L_ERR "KIF: Invalid interface address %I for %s", ifa.ip, iface->name);
673
    return;
674
  }
675
  ifa.scope = scope & IADDR_SCOPE_MASK;
676

    
677
#ifdef IPV6
678
  /* Clean up embedded interface ID returned in link-local address */
679
  if (ipa_has_link_scope(ifa.ip))
680
    _I0(ifa.ip) = 0xfe800000;
681
#endif
682

    
683
#ifdef IPV6
684
  /* Why not the same check also for IPv4? */
685
  if ((iface->flags & IF_MULTIACCESS) || (masklen != BITS_PER_IP_ADDRESS))
686
#else
687
  if (iface->flags & IF_MULTIACCESS)
688
#endif
689
  {
690
    ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(masklen));
691

    
692
    if (masklen == BITS_PER_IP_ADDRESS)
693
      ifa.flags |= IA_HOST;
694

    
695
    if (masklen == (BITS_PER_IP_ADDRESS - 1))
696
      ifa.opposite = ipa_opposite_m1(ifa.ip);
697

    
698
#ifndef IPV6
699
    if (masklen == (BITS_PER_IP_ADDRESS - 2))
700
      ifa.opposite = ipa_opposite_m2(ifa.ip);
701
#endif
702
  }
703
  else         /* PtP iface */
704
  {
705
    ifa.flags |= IA_PEER;
706
    ifa.prefix = ifa.opposite = ifa.brd;
707
  }
708

    
709
  if (new)
710
    ifa_update(&ifa);
711
  else
712
    ifa_delete(&ifa);
713
}
714

    
715
static void
716
krt_read_msg(struct proto *p, struct ks_msg *msg, int scan)
717
{
718
  /* p is NULL iff KRT_SHARED_SOCKET and !scan */
719

    
720
  switch (msg->rtm.rtm_type)
721
  {
722
    case RTM_GET:
723
      if(!scan) return;
724
    case RTM_ADD:
725
    case RTM_DELETE:
726
      krt_read_route(msg, (struct krt_proto *)p, scan);
727
      break;
728
    case RTM_IFANNOUNCE:
729
      krt_read_ifannounce(msg);
730
      break;
731
    case RTM_IFINFO:
732
      krt_read_ifinfo(msg);
733
      break;
734
    case RTM_NEWADDR:
735
    case RTM_DELADDR:
736
      krt_read_addr(msg);
737
      break;
738
    default:
739
      break;
740
  }
741
}
742

    
743

    
744
/* Sysctl based scans */
745

    
746
static byte *krt_buffer;
747
static size_t krt_buflen, krt_bufmin;
748
static struct proto *krt_buffer_owner;
749

    
750
static byte *
751
krt_buffer_update(struct proto *p, size_t *needed)
752
{
753
  size_t req = *needed;
754

    
755
  if ((req > krt_buflen) ||
756
      ((p == krt_buffer_owner) && (req < krt_bufmin)))
757
  {
758
    /* min buflen is 32 kB, step is 8 kB, or 128 kB if > 1 MB */
759
    size_t step = (req < 0x100000) ? 0x2000 : 0x20000;
760
    krt_buflen = (req < 0x6000) ? 0x8000 : (req + step);
761
    krt_bufmin = (req < 0x8000) ? 0 : (req - 2*step);
762

    
763
    if (krt_buffer) 
764
      mb_free(krt_buffer);
765
    krt_buffer = mb_alloc(krt_pool, krt_buflen);
766
    krt_buffer_owner = p;
767
  }
768

    
769
  *needed = krt_buflen;
770
  return krt_buffer;
771
}
772

    
773
static void
774
krt_buffer_release(struct proto *p)
775
{
776
  if (p == krt_buffer_owner)
777
  {
778
    mb_free(krt_buffer);
779
    krt_buffer = NULL;
780
    krt_buflen = 0;
781
    krt_buffer_owner = 0;
782
  }
783
}
784

    
785
static void
786
krt_sysctl_scan(struct proto *p, int cmd, int table_id)
787
{
788
  byte *buf, *next;
789
  int mib[7], mcnt;
790
  size_t needed;
791
  struct ks_msg *m;
792
  int retries = 3;
793
  int rv;
794

    
795
  mib[0] = CTL_NET;
796
  mib[1] = PF_ROUTE;
797
  mib[2] = 0;
798
  mib[3] = BIRD_PF;
799
  mib[4] = cmd;
800
  mib[5] = 0;
801
  mcnt = 6;
802

    
803
#ifdef KRT_USE_SYSCTL_7
804
  if (table_id >= 0)
805
  {
806
    mib[6] = table_id;
807
    mcnt = 7;
808
  }
809
#endif
810

    
811
#ifdef KRT_USE_SETFIB_SCAN
812
  if (table_id > 0)
813
    if (setfib(table_id) < 0)
814
    {
815
      log(L_ERR "KRT: setfib(%d) failed: %m", table_id);
816
      return;
817
    }
818
#endif
819

    
820
 try:
821
  rv = sysctl(mib, mcnt, NULL, &needed, NULL, 0);
822
  if (rv < 0)
823
  {
824
    /* OpenBSD returns EINVAL for not yet used tables */
825
    if ((errno == EINVAL) && (table_id > 0))
826
      goto exit;
827

    
828
    log(L_ERR "KRT: Route scan estimate failed: %m");
829
    goto exit;
830
  }
831

    
832
  /* The table is empty */
833
  if (needed == 0)
834
    goto exit;
835

    
836
  buf = krt_buffer_update(p, &needed);
837

    
838
  rv = sysctl(mib, mcnt, buf, &needed, NULL, 0);
839
  if (rv < 0)
840
  {
841
    /* The buffer size changed since last sysctl ('needed' is not changed) */
842
    if ((errno == ENOMEM) && retries--)
843
      goto try;
844

    
845
    log(L_ERR "KRT: Route scan failed: %m");
846
    goto exit;
847
  }
848

    
849
#ifdef KRT_USE_SETFIB_SCAN
850
  if (table_id > 0)
851
    if (setfib(0) < 0)
852
      die("KRT: setfib(%d) failed: %m", 0);
853
#endif
854

    
855
  /* Process received messages */
856
  for (next = buf; next < (buf + needed); next += m->rtm.rtm_msglen)
857
  {
858
    m = (struct ks_msg *)next;
859
    krt_read_msg(p, m, 1);
860
  }
861

    
862
  return;
863

    
864
 exit:
865
  krt_buffer_release(p);
866

    
867
#ifdef KRT_USE_SETFIB_SCAN
868
  if (table_id > 0)
869
    if (setfib(0) < 0)
870
      die("KRT: setfib(%d) failed: %m", 0);
871
#endif
872
}
873

    
874
void
875
krt_do_scan(struct krt_proto *p)
876
{
877
  krt_sysctl_scan(&p->p, NET_RT_DUMP, KRT_CF->sys.table_id);
878
}
879

    
880
void
881
kif_do_scan(struct kif_proto *p)
882
{
883
  if_start_update();
884
  krt_sysctl_scan(&p->p, NET_RT_IFLIST, -1);
885
  if_end_update();
886
}
887

    
888

    
889
/* Kernel sockets */
890

    
891
static int
892
krt_sock_hook(sock *sk, int size UNUSED)
893
{
894
  struct ks_msg msg;
895
  int l = read(sk->fd, (char *)&msg, sizeof(msg));
896

    
897
  if (l <= 0)
898
    log(L_ERR "krt-sock: read failed");
899
  else
900
    krt_read_msg((struct proto *) sk->data, &msg, 0);
901

    
902
  return 0;
903
}
904

    
905
static sock *
906
krt_sock_open(pool *pool, void *data, int table_id)
907
{
908
  sock *sk;
909
  int fd;
910

    
911
  fd = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
912
  if (fd < 0)
913
    die("Cannot open kernel socket for routes");
914

    
915
#ifdef KRT_USE_SETFIB_SOCK
916
  if (table_id > 0)
917
  {
918
    if (setsockopt(fd, SOL_SOCKET, SO_SETFIB, &table_id, sizeof(table_id)) < 0)
919
      die("Cannot set FIB %d for kernel socket: %m", table_id);
920
  }
921
#endif
922

    
923
  sk = sk_new(pool);
924
  sk->type = SK_MAGIC;
925
  sk->rx_hook = krt_sock_hook;
926
  sk->fd = fd;
927
  sk->data = data;
928

    
929
  if (sk_open(sk) < 0)
930
    bug("krt-sock: sk_open failed");
931

    
932
  return sk;
933
}
934

    
935

    
936
#ifdef KRT_SHARED_SOCKET
937

    
938
static sock *krt_sock;
939
static int krt_sock_count;
940

    
941

    
942
static void
943
krt_sock_open_shared(void)
944
{
945
  if (!krt_sock_count)
946
    krt_sock = krt_sock_open(krt_pool, NULL, -1);
947
  
948
  krt_sock_count++;
949
}
950

    
951
static void
952
krt_sock_close_shared(void)
953
{
954
  krt_sock_count--;
955

    
956
  if (!krt_sock_count)
957
  {
958
    rfree(krt_sock);
959
    krt_sock = NULL;
960
  }
961
}
962

    
963
void
964
krt_sys_start(struct krt_proto *p)
965
{
966
  krt_table_map[KRT_CF->sys.table_id] = p;
967

    
968
  krt_sock_open_shared();
969
  p->sys.sk = krt_sock;
970
}
971

    
972
void
973
krt_sys_shutdown(struct krt_proto *p)
974
{
975
  krt_sock_close_shared();
976
  p->sys.sk = NULL;
977

    
978
  krt_table_map[KRT_CF->sys.table_id] = NULL;
979

    
980
  krt_buffer_release(&p->p);
981
}
982

    
983
#else
984

    
985
void
986
krt_sys_start(struct krt_proto *p)
987
{
988
  p->sys.sk = krt_sock_open(p->p.pool, p, KRT_CF->sys.table_id);
989
}
990

    
991
void
992
krt_sys_shutdown(struct krt_proto *p)
993
{
994
  rfree(p->sys.sk);
995
  p->sys.sk = NULL;
996

    
997
  krt_buffer_release(&p->p);
998
}
999

    
1000
#endif /* KRT_SHARED_SOCKET */
1001

    
1002

    
1003
/* KRT configuration callbacks */
1004

    
1005
static u32 krt_table_cf[(KRT_MAX_TABLES+31) / 32];
1006

    
1007
int
1008
krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o)
1009
{
1010
  return n->sys.table_id == o->sys.table_id;
1011
}
1012

    
1013
void
1014
krt_sys_preconfig(struct config *c UNUSED)
1015
{
1016
  krt_max_tables = krt_get_max_tables();
1017
  bzero(&krt_table_cf, sizeof(krt_table_cf));
1018
}
1019

    
1020
void
1021
krt_sys_postconfig(struct krt_config *x)
1022
{
1023
  u32 *tbl = krt_table_cf;
1024
  int id = x->sys.table_id;
1025

    
1026
  if (tbl[id/32] & (1 << (id%32)))
1027
    cf_error("Multiple kernel syncers defined for table #%d", id);
1028

    
1029
  tbl[id/32] |= (1 << (id%32));
1030
}
1031

    
1032
void krt_sys_init_config(struct krt_config *c)
1033
{
1034
  c->sys.table_id = 0; /* Default table */
1035
}
1036

    
1037
void krt_sys_copy_config(struct krt_config *d, struct krt_config *s)
1038
{
1039
  d->sys.table_id = s->sys.table_id;
1040
}
1041

    
1042

    
1043
/* KIF misc code */
1044

    
1045
void
1046
kif_sys_start(struct kif_proto *p UNUSED)
1047
{
1048
}
1049

    
1050
void
1051
kif_sys_shutdown(struct kif_proto *p)
1052
{
1053
  krt_buffer_release(&p->p);
1054
}
1055