Statistics
| Branch: | Revision:

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

History | View | Annotate | Download (24.6 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 "sysdep/unix/timer.h"
32
#include "sysdep/unix/unix.h"
33
#include "sysdep/unix/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
/* Dynamic max number of tables */
76

    
77
int krt_max_tables;
78

    
79
#ifdef KRT_USE_SYSCTL_NET_FIBS
80

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

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

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

    
96
#else
97

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

    
104
#endif /* KRT_USE_SYSCTL_NET_FIBS */
105

    
106

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

    
109
#ifdef KRT_USE_SETFIB_SCAN
110

    
111
/*
112
static int krt_default_fib;
113

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

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

126
  return fib;
127
}
128
*/
129

    
130
extern int setfib(int fib);
131

    
132
#endif /* KRT_USE_SETFIB_SCAN */
133

    
134

    
135
/* table_id -> krt_proto map */
136

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

    
141

    
142
/* Route socket message processing */
143

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

    
149
  /* XXXX device routes are broken */
150
  return
151
    ((a->dest == RTD_UNICAST && ipa_nonzero(a->nh.gw) && !a->nh.next) /* No multipath support */
152
#ifdef RTF_REJECT
153
     || a->dest == RTD_UNREACHABLE
154
#endif
155
#ifdef RTF_BLACKHOLE
156
     || a->dest == RTD_BLACKHOLE
157
#endif
158
     );
159
}
160

    
161
#ifndef RTAX_MAX
162
#define RTAX_MAX 8
163
#endif
164

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

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

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

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

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

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

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

    
207
  /* XXXX */
208
  if (net_pxlen(net->n.addr) == net_max_prefix_length[net->n.addr->type])
209
    msg.rtm.rtm_flags |= RTF_HOST;
210
  else
211
    msg.rtm.rtm_addrs |= RTA_NETMASK;
212

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

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

    
226
  /*
227
   * This is really very nasty, but I'm not able to add reject/blackhole route
228
   * without gateway address.
229
   */
230
  if (!i)
231
  {
232
    WALK_LIST(j, iface_list)
233
    {
234
      if (j->flags & IF_LOOPBACK)
235
      {
236
        i = j;
237
        break;
238
      }
239
    }
240

    
241
    if (!i)
242
    {
243
      log(L_ERR "KRT: Cannot find loopback iface");
244
      return -1;
245
    }
246
  }
247

    
248
  int af = AF_UNSPEC;
249

    
250
  switch (net->n.addr->type) {
251
    case NET_IP4:
252
      af = AF_INET;
253
      break;
254
    case NET_IP6:
255
      af = AF_INET6;
256
      break;
257
    default:
258
      log(L_ERR "KRT: Not sending route %N to kernel", net->n.addr);
259
      return -1;
260
  }
261

    
262
  sockaddr_fill(&dst,  af, net_prefix(net->n.addr), NULL, 0);
263
  sockaddr_fill(&mask, af, net_pxmask(net->n.addr), NULL, 0);
264

    
265
  switch (a->dest)
266
  {
267
  case RTD_UNICAST:
268
    if (ipa_nonzero(a->nh.gw))
269
    {
270
      ip_addr gw = a->nh.gw;
271

    
272
      /* Embed interface ID to link-local address */
273
      if (ipa_is_link_local(gw))
274
        _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
275

    
276
      sockaddr_fill(&gate, af, gw, NULL, 0);
277
      msg.rtm.rtm_flags |= RTF_GATEWAY;
278
      msg.rtm.rtm_addrs |= RTA_GATEWAY;
279
      break;
280
    }
281

    
282
#ifdef RTF_REJECT
283
  case RTD_UNREACHABLE:
284
#endif
285
#ifdef RTF_BLACKHOLE
286
  case RTD_BLACKHOLE:
287
#endif
288
  {
289
    /* Fallback for all other valid cases */
290

    
291
#ifdef RTF_CLONING
292
    if (cmd == RTM_ADD && (i->flags & IF_MULTIACCESS) != IF_MULTIACCESS)        /* PTP */
293
      msg.rtm.rtm_flags |= RTF_CLONING;
294
#endif
295

    
296
    struct ifa *addr = (net->n.addr->type == NET_IP4) ? i->addr4 : (i->addr6 ?: i->llv6);
297

    
298
    if (!addr)
299
    {
300
      log(L_ERR "KRT: interface %s has no IP addess", i->name);
301
      return -1;
302
    }
303

    
304
    sockaddr_fill(&gate, af, addr->ip, i, 0);
305
    msg.rtm.rtm_addrs |= RTA_GATEWAY;
306
    break;
307
  }
308

    
309
  default:
310
    bug("krt-sock: unknown flags, but not filtered");
311
  }
312

    
313
  msg.rtm.rtm_index = i->index;
314

    
315
  NEXTADDR(RTA_DST, dst);
316
  NEXTADDR(RTA_GATEWAY, gate);
317
  NEXTADDR(RTA_NETMASK, mask);
318

    
319
  l = body - (char *)&msg;
320
  msg.rtm.rtm_msglen = l;
321

    
322
  if ((l = write(p->sys.sk->fd, (char *)&msg, l)) < 0) {
323
    log(L_ERR "KRT: Error sending route %N to kernel: %m", net->n.addr);
324
    return -1;
325
  }
326

    
327
  return 0;
328
}
329

    
330
void
331
krt_replace_rte(struct krt_proto *p, net *n, rte *new, rte *old,
332
                struct ea_list *eattrs UNUSED)
333
{
334
  int err = 0;
335

    
336
  if (old)
337
    krt_send_route(p, RTM_DELETE, old);
338

    
339
  if (new)
340
    err = krt_send_route(p, RTM_ADD, new);
341

    
342
  if (err < 0)
343
    n->n.flags |= KRF_SYNC_ERROR;
344
  else
345
    n->n.flags &= ~KRF_SYNC_ERROR;
346
}
347

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

    
350
static void
351
krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
352
{
353
  /* p is NULL iff KRT_SHARED_SOCKET and !scan */
354

    
355
  int ipv6;
356
  rte *e;
357
  net *net;
358
  sockaddr dst, gate, mask;
359
  ip_addr idst, igate, imask;
360
  net_addr ndst;
361
  void *body = (char *)msg->buf;
362
  int new = (msg->rtm.rtm_type != RTM_DELETE);
363
  char *errmsg = "KRT: Invalid route received";
364
  int flags = msg->rtm.rtm_flags;
365
  int addrs = msg->rtm.rtm_addrs;
366
  int src;
367
  byte src2;
368

    
369
  if (!(flags & RTF_UP) && scan)
370
    SKIP("not up in scan\n");
371

    
372
  if (!(flags & RTF_DONE) && !scan)
373
    SKIP("not done in async\n");
374

    
375
  if (flags & RTF_LLINFO)
376
    SKIP("link-local\n");
377

    
378
  GETADDR(&dst, RTA_DST);
379
  GETADDR(&gate, RTA_GATEWAY);
380
  GETADDR(&mask, RTA_NETMASK);
381

    
382
  switch (dst.sa.sa_family) {
383
    case AF_INET:
384
      ipv6 = 0;
385
      break;
386
    case AF_INET6:
387
      ipv6 = 1;
388
      break;
389
    default:
390
      SKIP("invalid DST");
391
  }
392

    
393
  /* We do not test family for RTA_NETMASK, because BSD sends us
394
     some strange values, but interpreting them as IPv4/IPv6 works */
395
  mask.sa.sa_family = dst.sa.sa_family;
396

    
397
  idst  = ipa_from_sa(&dst);
398
  imask = ipa_from_sa(&mask);
399
  igate = (gate.sa.sa_family == dst.sa.sa_family) ? ipa_from_sa(&gate) : IPA_NONE;
400

    
401
#ifdef KRT_SHARED_SOCKET
402
  if (!scan)
403
  {
404
    int table_id = msg->rtm.rtm_tableid;
405
    p = (table_id < KRT_MAX_TABLES) ? krt_table_map[table_id][ipv6] : NULL;
406

    
407
    if (!p)
408
      SKIP("unknown table id %d\n", table_id);
409
  }
410
#endif
411
  if ((!ipv6) && (p->p.main_channel->table->addr_type != NET_IP4))
412
    SKIP("reading only IPv4 routes");
413
  if (  ipv6  && (p->p.main_channel->table->addr_type != NET_IP6))
414
    SKIP("reading only IPv6 routes");
415

    
416
  int c = ipa_classify_net(idst);
417
  if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
418
    SKIP("strange class/scope\n");
419

    
420
  int pxlen;
421
  if (ipv6)
422
    pxlen = (flags & RTF_HOST) ? IP6_MAX_PREFIX_LENGTH : ip6_masklen(&ipa_to_ip6(imask));
423
  else
424
    pxlen = (flags & RTF_HOST) ? IP4_MAX_PREFIX_LENGTH : ip4_masklen(ipa_to_ip4(imask));
425

    
426
  if (pxlen < 0)
427
    { log(L_ERR "%s (%I) - netmask %I", errmsg, idst, imask); return; }
428

    
429
  if (ipv6)
430
    net_fill_ip6(&ndst, ipa_to_ip6(idst), pxlen);
431
  else
432
    net_fill_ip4(&ndst, ipa_to_ip4(idst), pxlen);
433

    
434
  if ((flags & RTF_GATEWAY) && ipa_zero(igate))
435
    { log(L_ERR "%s (%N) - missing gateway", errmsg, ndst); return; }
436

    
437
  u32 self_mask = RTF_PROTO1;
438
  u32 alien_mask = RTF_STATIC | RTF_PROTO1 | RTF_GATEWAY;
439

    
440
  src2 = (flags & RTF_STATIC) ? 1 : 0;
441
  src2 |= (flags & RTF_PROTO1) ? 2 : 0;
442

    
443
#ifdef RTF_PROTO2
444
  alien_mask |= RTF_PROTO2;
445
  src2 |= (flags & RTF_PROTO2) ? 4 : 0;
446
#endif
447

    
448
#ifdef RTF_PROTO3
449
  alien_mask |= RTF_PROTO3;
450
  src2 |= (flags & RTF_PROTO3) ? 8 : 0;
451
#endif
452

    
453
#ifdef RTF_REJECT
454
  alien_mask |= RTF_REJECT;
455
#endif
456

    
457
#ifdef RTF_BLACKHOLE
458
  alien_mask |= RTF_BLACKHOLE;
459
#endif
460

    
461
  if (flags & (RTF_DYNAMIC | RTF_MODIFIED))
462
    src = KRT_SRC_REDIRECT;
463
  else if (flags & self_mask)
464
    {
465
      if (!scan)
466
        SKIP("echo\n");
467
      src = KRT_SRC_BIRD;
468
    }
469
  else if (flags & alien_mask)
470
    src = KRT_SRC_ALIEN;
471
  else
472
    src = KRT_SRC_KERNEL;
473

    
474
  net = net_get(p->p.main_channel->table, &ndst);
475

    
476
  rta a = {
477
    .src = p->p.main_source,
478
    .source = RTS_INHERIT,
479
    .scope = SCOPE_UNIVERSE,
480
  };
481

    
482
  /* reject/blackhole routes have also set RTF_GATEWAY,
483
     we wil check them first. */
484

    
485
#ifdef RTF_REJECT
486
  if(flags & RTF_REJECT) {
487
    a.dest = RTD_UNREACHABLE;
488
    goto done;
489
  }
490
#endif
491

    
492
#ifdef RTF_BLACKHOLE
493
  if(flags & RTF_BLACKHOLE) {
494
    a.dest = RTD_BLACKHOLE;
495
    goto done;
496
  }
497
#endif
498

    
499
  a.nh.iface = if_find_by_index(msg->rtm.rtm_index);
500
  if (!a.nh.iface)
501
    {
502
      log(L_ERR "KRT: Received route %N with unknown ifindex %u",
503
          net->n.addr, msg->rtm.rtm_index);
504
      return;
505
    }
506

    
507
  a.dest = RTD_UNICAST;
508
  if (flags & RTF_GATEWAY)
509
  {
510
    neighbor *ng;
511
    a.nh.gw = igate;
512

    
513
    /* Clean up embedded interface ID returned in link-local address */
514
    if (ipa_is_link_local(a.nh.gw))
515
      _I0(a.nh.gw) = 0xfe800000;
516

    
517
    ng = neigh_find2(&p->p, &a.nh.gw, a.nh.iface, 0);
518
    if (!ng || (ng->scope == SCOPE_HOST))
519
      {
520
        /* Ignore routes with next-hop 127.0.0.1, host routes with such
521
           next-hop appear on OpenBSD for address aliases. */
522
        if (ipa_classify(a.nh.gw) == (IADDR_HOST | SCOPE_HOST))
523
          return;
524

    
525
        log(L_ERR "KRT: Received route %N with strange next-hop %I",
526
            net->n.addr, a.nh.gw);
527
        return;
528
      }
529
  }
530

    
531
 done:
532
  e = rte_get_temp(&a);
533
  e->net = net;
534
  e->u.krt.src = src;
535
  e->u.krt.proto = src2;
536
  e->u.krt.seen = 0;
537
  e->u.krt.best = 0;
538
  e->u.krt.metric = 0;
539

    
540
  if (scan)
541
    krt_got_route(p, e);
542
  else
543
    krt_got_route_async(p, e, new);
544
}
545

    
546
static void
547
krt_read_ifannounce(struct ks_msg *msg)
548
{
549
  struct if_announcemsghdr *ifam = (struct if_announcemsghdr *)&msg->rtm;
550

    
551
  if (ifam->ifan_what == IFAN_ARRIVAL)
552
  {
553
    /* Not enough info to create the iface, so we just trigger iface scan */
554
    kif_request_scan();
555
  }
556
  else if (ifam->ifan_what == IFAN_DEPARTURE)
557
  {
558
    struct iface *iface = if_find_by_index(ifam->ifan_index);
559

    
560
    /* Interface is destroyed */
561
    if (!iface)
562
    {
563
      DBG("KRT: unknown interface (%s, #%d) going down. Ignoring\n", ifam->ifan_name, ifam->ifan_index);
564
      return;
565
    }
566

    
567
    if_delete(iface);
568
  }
569

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

    
573
static void
574
krt_read_ifinfo(struct ks_msg *msg, int scan)
575
{
576
  struct if_msghdr *ifm = (struct if_msghdr *)&msg->rtm;
577
  void *body = (void *)(ifm + 1);
578
  struct sockaddr_dl *dl = NULL;
579
  uint i;
580
  struct iface *iface = NULL, f = {};
581
  int fl = ifm->ifm_flags;
582
  int nlen = 0;
583

    
584
  for (i = 1; i<=RTA_IFP; i <<= 1)
585
  {
586
    if (i & ifm->ifm_addrs)
587
    {
588
      if (i == RTA_IFP)
589
      {
590
        dl = (struct sockaddr_dl *)body;
591
        break;
592
      }
593
      body += ROUNDUP(((struct sockaddr *)&(body))->sa_len);
594
    }
595
  }
596

    
597
  if (dl && (dl->sdl_family != AF_LINK))
598
  {
599
    log(L_WARN "Ignoring strange IFINFO");
600
    return;
601
  }
602

    
603
  if (dl)
604
    nlen = MIN(sizeof(f.name)-1, dl->sdl_nlen);
605

    
606
  /* Note that asynchronous IFINFO messages do not contain iface
607
     name, so we have to found an existing iface by iface index */
608

    
609
  iface = if_find_by_index(ifm->ifm_index);
610
  if (!iface)
611
  {
612
    /* New interface */
613
    if (!dl)
614
      return;        /* No interface name, ignoring */
615

    
616
    memcpy(f.name, dl->sdl_data, nlen);
617
    DBG("New interface '%s' found\n", f.name);
618
  }
619
  else if (dl && memcmp(iface->name, dl->sdl_data, nlen))
620
  {
621
    /* Interface renamed */
622
    if_delete(iface);
623
    memcpy(f.name, dl->sdl_data, nlen);
624
  }
625
  else
626
  {
627
    /* Old interface */
628
    memcpy(f.name, iface->name, sizeof(f.name));
629
  }
630

    
631
  f.index = ifm->ifm_index;
632
  f.mtu = ifm->ifm_data.ifi_mtu;
633

    
634
  if (fl & IFF_UP)
635
    f.flags |= IF_ADMIN_UP;
636
  if (ifm->ifm_data.ifi_link_state != LINK_STATE_DOWN)
637
    f.flags |= IF_LINK_UP;          /* up or unknown */
638
  if (fl & IFF_LOOPBACK)            /* Loopback */
639
    f.flags |= IF_MULTIACCESS | IF_LOOPBACK | IF_IGNORE;
640
  else if (fl & IFF_POINTOPOINT)    /* PtP */
641
    f.flags |= IF_MULTICAST;
642
  else if (fl & IFF_BROADCAST)      /* Broadcast */
643
    f.flags |= IF_MULTIACCESS | IF_BROADCAST | IF_MULTICAST;
644
  else
645
    f.flags |= IF_MULTIACCESS;      /* NBMA */
646

    
647
  iface = if_update(&f);
648

    
649
  if (!scan)
650
    if_end_partial_update(iface);
651
}
652

    
653
static void
654
krt_read_addr(struct ks_msg *msg, int scan)
655
{
656
  struct ifa_msghdr *ifam = (struct ifa_msghdr *)&msg->rtm;
657
  void *body = (void *)(ifam + 1);
658
  sockaddr addr, mask, brd;
659
  struct iface *iface = NULL;
660
  struct ifa ifa;
661
  struct sockaddr null;
662
  ip_addr iaddr, imask, ibrd;
663
  int addrs = ifam->ifam_addrs;
664
  int scope, masklen = -1;
665
  int new = (ifam->ifam_type == RTM_NEWADDR);
666

    
667
  /* Strange messages with zero (invalid) ifindex appear on OpenBSD */
668
  if (ifam->ifam_index == 0)
669
    return;
670

    
671
  if(!(iface = if_find_by_index(ifam->ifam_index)))
672
  {
673
    log(L_ERR "KIF: Received address message for unknown interface %d", ifam->ifam_index);
674
    return;
675
  }
676

    
677
  GETADDR (&null, RTA_DST);
678
  GETADDR (&null, RTA_GATEWAY);
679
  GETADDR (&mask, RTA_NETMASK);
680
  GETADDR (&null, RTA_GENMASK);
681
  GETADDR (&null, RTA_IFP);
682
  GETADDR (&addr, RTA_IFA);
683
  GETADDR (&null, RTA_AUTHOR);
684
  GETADDR (&brd, RTA_BRD);
685

    
686
  /* Is addr family IP4 or IP6? */
687
  int ipv6;
688
  switch (addr.sa.sa_family) {
689
    case AF_INET: ipv6 = 0; break;
690
    case AF_INET6: ipv6 = 1; break;
691
    default: return;
692
  }
693

    
694
  /* We do not test family for RTA_NETMASK, because BSD sends us
695
     some strange values, but interpreting them as IPv4/IPv6 works */
696
  mask.sa.sa_family = addr.sa.sa_family;
697

    
698
  iaddr = ipa_from_sa(&addr);
699
  imask = ipa_from_sa(&mask);
700
  ibrd  = ipa_from_sa(&brd);
701

    
702
  if ((ipv6 ? (masklen = ip6_masklen(&ipa_to_ip6(imask))) : (masklen = ip4_masklen(ipa_to_ip4(imask)))) < 0)
703
  {
704
    log(L_ERR "KIF: Invalid mask %I for %s", imask, iface->name);
705
    return;
706
  }
707

    
708
  /* Clean up embedded interface ID returned in link-local address */
709

    
710
  if (ipa_is_link_local(iaddr))
711
    _I0(iaddr) = 0xfe800000;
712

    
713
  if (ipa_is_link_local(ibrd))
714
    _I0(ibrd) = 0xfe800000;
715

    
716

    
717
  bzero(&ifa, sizeof(ifa));
718
  ifa.iface = iface;
719
  ifa.ip = iaddr;
720

    
721
  scope = ipa_classify(ifa.ip);
722
  if (scope < 0)
723
  {
724
    log(L_ERR "KIF: Invalid interface address %I for %s", ifa.ip, iface->name);
725
    return;
726
  }
727
  ifa.scope = scope & IADDR_SCOPE_MASK;
728

    
729
  if (masklen < (ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH))
730
  {
731
    net_fill_ipa(&ifa.prefix, ifa.ip, masklen);
732
    net_normalize(&ifa.prefix);
733

    
734
    if (masklen == ((ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH) - 1))
735
      ifa.opposite = ipa_opposite_m1(ifa.ip);
736

    
737
    if ((!ipv6) && (masklen == IP4_MAX_PREFIX_LENGTH - 2))
738
      ifa.opposite = ipa_opposite_m2(ifa.ip);
739

    
740
    if (iface->flags & IF_BROADCAST)
741
      ifa.brd = ibrd;
742

    
743
    if (!(iface->flags & IF_MULTIACCESS))
744
      ifa.opposite = ibrd;
745
  }
746
  else if (!(iface->flags & IF_MULTIACCESS) && ipa_nonzero(ibrd))
747
  {
748
    net_fill_ipa(&ifa.prefix, ibrd, (ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH));
749
    ifa.opposite = ibrd;
750
    ifa.flags |= IA_PEER;
751
  }
752
  else
753
  {
754
    net_fill_ipa(&ifa.prefix, ifa.ip, (ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH));
755
    ifa.flags |= IA_HOST;
756
  }
757

    
758
  if (new)
759
    ifa_update(&ifa);
760
  else
761
    ifa_delete(&ifa);
762

    
763
  if (!scan)
764
    if_end_partial_update(iface);
765
}
766

    
767
static void
768
krt_read_msg(struct proto *p, struct ks_msg *msg, int scan)
769
{
770
  /* p is NULL iff KRT_SHARED_SOCKET and !scan */
771

    
772
  switch (msg->rtm.rtm_type)
773
  {
774
    case RTM_GET:
775
      if(!scan) return;
776
    case RTM_ADD:
777
    case RTM_DELETE:
778
    case RTM_CHANGE:
779
      krt_read_route(msg, (struct krt_proto *)p, scan);
780
      break;
781
    case RTM_IFANNOUNCE:
782
      krt_read_ifannounce(msg);
783
      break;
784
    case RTM_IFINFO:
785
      krt_read_ifinfo(msg, scan);
786
      break;
787
    case RTM_NEWADDR:
788
    case RTM_DELADDR:
789
      krt_read_addr(msg, scan);
790
      break;
791
    default:
792
      break;
793
  }
794
}
795

    
796

    
797
/* Sysctl based scans */
798

    
799
static byte *krt_buffer;
800
static size_t krt_buflen, krt_bufmin;
801
static struct proto *krt_buffer_owner;
802

    
803
static byte *
804
krt_buffer_update(struct proto *p, size_t *needed)
805
{
806
  size_t req = *needed;
807

    
808
  if ((req > krt_buflen) ||
809
      ((p == krt_buffer_owner) && (req < krt_bufmin)))
810
  {
811
    /* min buflen is 32 kB, step is 8 kB, or 128 kB if > 1 MB */
812
    size_t step = (req < 0x100000) ? 0x2000 : 0x20000;
813
    krt_buflen = (req < 0x6000) ? 0x8000 : (req + step);
814
    krt_bufmin = (req < 0x8000) ? 0 : (req - 2*step);
815

    
816
    if (krt_buffer) 
817
      mb_free(krt_buffer);
818
    krt_buffer = mb_alloc(krt_pool, krt_buflen);
819
    krt_buffer_owner = p;
820
  }
821

    
822
  *needed = krt_buflen;
823
  return krt_buffer;
824
}
825

    
826
static void
827
krt_buffer_release(struct proto *p)
828
{
829
  if (p == krt_buffer_owner)
830
  {
831
    mb_free(krt_buffer);
832
    krt_buffer = NULL;
833
    krt_buflen = 0;
834
    krt_buffer_owner = 0;
835
  }
836
}
837

    
838
static void
839
krt_sysctl_scan(struct proto *p, int cmd, int table_id)
840
{
841
  byte *buf, *next;
842
  int mib[7], mcnt;
843
  size_t needed;
844
  struct ks_msg *m;
845
  int retries = 3;
846
  int rv;
847

    
848
  mib[0] = CTL_NET;
849
  mib[1] = PF_ROUTE;
850
  mib[2] = 0;
851
  mib[3] = 0; // Set AF to 0 for all available families
852
  mib[4] = cmd;
853
  mib[5] = 0;
854
  mcnt = 6;
855

    
856
#ifdef KRT_USE_SYSCTL_7
857
  if (table_id >= 0)
858
  {
859
    mib[6] = table_id;
860
    mcnt = 7;
861
  }
862
#endif
863

    
864
#ifdef KRT_USE_SETFIB_SCAN
865
  if (table_id > 0)
866
    if (setfib(table_id) < 0)
867
    {
868
      log(L_ERR "KRT: setfib(%d) failed: %m", table_id);
869
      return;
870
    }
871
#endif
872

    
873
 try:
874
  rv = sysctl(mib, mcnt, NULL, &needed, NULL, 0);
875
  if (rv < 0)
876
  {
877
    /* OpenBSD returns EINVAL for not yet used tables */
878
    if ((errno == EINVAL) && (table_id > 0))
879
      goto exit;
880

    
881
    log(L_ERR "KRT: Route scan estimate failed: %m");
882
    goto exit;
883
  }
884

    
885
  /* The table is empty */
886
  if (needed == 0)
887
    goto exit;
888

    
889
  buf = krt_buffer_update(p, &needed);
890

    
891
  rv = sysctl(mib, mcnt, buf, &needed, NULL, 0);
892
  if (rv < 0)
893
  {
894
    /* The buffer size changed since last sysctl ('needed' is not changed) */
895
    if ((errno == ENOMEM) && retries--)
896
      goto try;
897

    
898
    log(L_ERR "KRT: Route scan failed: %m");
899
    goto exit;
900
  }
901

    
902
#ifdef KRT_USE_SETFIB_SCAN
903
  if (table_id > 0)
904
    if (setfib(0) < 0)
905
      die("KRT: setfib(%d) failed: %m", 0);
906
#endif
907

    
908
  /* Process received messages */
909
  for (next = buf; next < (buf + needed); next += m->rtm.rtm_msglen)
910
  {
911
    m = (struct ks_msg *)next;
912
    krt_read_msg(p, m, 1);
913
  }
914

    
915
  return;
916

    
917
 exit:
918
  krt_buffer_release(p);
919

    
920
#ifdef KRT_USE_SETFIB_SCAN
921
  if (table_id > 0)
922
    if (setfib(0) < 0)
923
      die("KRT: setfib(%d) failed: %m", 0);
924
#endif
925
}
926

    
927
void
928
krt_do_scan(struct krt_proto *p)
929
{
930
  krt_sysctl_scan(&p->p, NET_RT_DUMP, KRT_CF->sys.table_id);
931
}
932

    
933
void
934
kif_do_scan(struct kif_proto *p)
935
{
936
  if_start_update();
937
  krt_sysctl_scan(&p->p, NET_RT_IFLIST, -1);
938
  if_end_update();
939
}
940

    
941

    
942
/* Kernel sockets */
943

    
944
static int
945
krt_sock_hook(sock *sk, uint size UNUSED)
946
{
947
  struct ks_msg msg;
948
  int l = read(sk->fd, (char *)&msg, sizeof(msg));
949

    
950
  if (l <= 0)
951
    log(L_ERR "krt-sock: read failed");
952
  else
953
    krt_read_msg((struct proto *) sk->data, &msg, 0);
954

    
955
  return 0;
956
}
957

    
958
static void
959
krt_sock_err_hook(sock *sk, int e UNUSED)
960
{
961
  krt_sock_hook(sk, 0);
962
}
963

    
964
static sock *
965
krt_sock_open(pool *pool, void *data, int table_id UNUSED)
966
{
967
  sock *sk;
968
  int fd;
969

    
970
  fd = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
971
  if (fd < 0)
972
    die("Cannot open kernel socket for routes");
973

    
974
#ifdef KRT_USE_SETFIB_SOCK
975
  if (table_id > 0)
976
  {
977
    if (setsockopt(fd, SOL_SOCKET, SO_SETFIB, &table_id, sizeof(table_id)) < 0)
978
      die("Cannot set FIB %d for kernel socket: %m", table_id);
979
  }
980
#endif
981

    
982
  sk = sk_new(pool);
983
  sk->type = SK_MAGIC;
984
  sk->rx_hook = krt_sock_hook;
985
  sk->err_hook = krt_sock_err_hook;
986
  sk->fd = fd;
987
  sk->data = data;
988

    
989
  if (sk_open(sk) < 0)
990
    bug("krt-sock: sk_open failed");
991

    
992
  return sk;
993
}
994

    
995
static u32 krt_table_cf[(KRT_MAX_TABLES+31) / 32][2];
996

    
997
#ifdef KRT_SHARED_SOCKET
998

    
999
static sock *krt_sock;
1000
static int krt_sock_count;
1001

    
1002

    
1003
static void
1004
krt_sock_open_shared(void)
1005
{
1006
  if (!krt_sock_count)
1007
    krt_sock = krt_sock_open(krt_pool, NULL, -1);
1008
  
1009
  krt_sock_count++;
1010
}
1011

    
1012
static void
1013
krt_sock_close_shared(void)
1014
{
1015
  krt_sock_count--;
1016

    
1017
  if (!krt_sock_count)
1018
  {
1019
    rfree(krt_sock);
1020
    krt_sock = NULL;
1021
  }
1022
}
1023

    
1024
int
1025
krt_sys_start(struct krt_proto *p)
1026
{
1027
  int id = KRT_CF->sys.table_id;
1028

    
1029
  if (krt_table_cf[id/32][!!(p->af == AF_INET6)] & (1 << (id%32)))
1030
    {
1031
      log(L_ERR "%s: Multiple kernel syncers defined for table #%d", p->p.name, id);
1032
      return 0;
1033
    }
1034

    
1035
  krt_table_cf[id/32][!!(p->af == AF_INET6)] |= (1 << (id%32));
1036

    
1037
  krt_table_map[KRT_CF->sys.table_id][!!(p->af == AF_INET6)] = p;
1038

    
1039
  krt_sock_open_shared();
1040
  p->sys.sk = krt_sock;
1041

    
1042
  return 1;
1043
}
1044

    
1045
void
1046
krt_sys_shutdown(struct krt_proto *p)
1047
{
1048
  krt_table_cf[(KRT_CF->sys.table_id)/32][!!(p->af == AF_INET6)] &= ~(1 << ((KRT_CF->sys.table_id)%32));
1049

    
1050
  krt_sock_close_shared();
1051
  p->sys.sk = NULL;
1052

    
1053
  krt_table_map[KRT_CF->sys.table_id][!!(p->af == AF_INET6)] = NULL;
1054

    
1055
  krt_buffer_release(&p->p);
1056
}
1057

    
1058
#else
1059

    
1060
int
1061
krt_sys_start(struct krt_proto *p)
1062
{
1063
  int id = KRT_CF->sys.table_id;
1064

    
1065
  if (krt_table_cf[id/32][!!(p->af == AF_INET6)] & (1 << (id%32)))
1066
    {
1067
      log(L_ERR "%s: Multiple kernel syncers defined for table #%d", p->p.name, id);
1068
      return 0;
1069
    }
1070

    
1071
  krt_table_cf[id/32][!!(p->af == AF_INET6)] |= (1 << (id%32));
1072

    
1073
  p->sys.sk = krt_sock_open(p->p.pool, p, KRT_CF->sys.table_id);
1074
  return 1;
1075
}
1076

    
1077
void
1078
krt_sys_shutdown(struct krt_proto *p)
1079
{
1080
  krt_table_cf[(KRT_CF->sys.table_id)/32][!!(p->af == AF_INET6)] &= ~(1 << ((KRT_CF->sys.table_id)%32));
1081

    
1082
  rfree(p->sys.sk);
1083
  p->sys.sk = NULL;
1084

    
1085
  krt_buffer_release(&p->p);
1086
}
1087

    
1088
#endif /* KRT_SHARED_SOCKET */
1089

    
1090

    
1091
/* KRT configuration callbacks */
1092

    
1093
int
1094
krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o)
1095
{
1096
  return n->sys.table_id == o->sys.table_id;
1097
}
1098

    
1099
void
1100
krt_sys_preconfig(struct config *c UNUSED)
1101
{
1102
  krt_max_tables = krt_get_max_tables();
1103
  bzero(&krt_table_cf, sizeof(krt_table_cf));
1104
}
1105

    
1106
void krt_sys_init_config(struct krt_config *c)
1107
{
1108
  c->sys.table_id = 0; /* Default table */
1109
}
1110

    
1111
void krt_sys_copy_config(struct krt_config *d, struct krt_config *s)
1112
{
1113
  d->sys.table_id = s->sys.table_id;
1114
}
1115

    
1116

    
1117
/* KIF misc code */
1118

    
1119
void
1120
kif_sys_start(struct kif_proto *p UNUSED)
1121
{
1122
}
1123

    
1124
void
1125
kif_sys_shutdown(struct kif_proto *p)
1126
{
1127
  krt_buffer_release(&p->p);
1128
}
1129

    
1130
int
1131
kif_update_sysdep_addr(struct iface *i)
1132
{
1133
  static int fd = -1;
1134

    
1135
  if (fd < 0)
1136
    fd = socket(AF_INET, SOCK_DGRAM, 0);
1137

    
1138
  struct ifreq ifr;
1139
  memset(&ifr, 0, sizeof(ifr));
1140
  strncpy(ifr.ifr_name, i->name, IFNAMSIZ);
1141

    
1142
  int rv = ioctl(fd, SIOCGIFADDR, (char *) &ifr);
1143
  if (rv < 0)
1144
    return 0;
1145

    
1146
  ip4_addr old = i->sysdep;
1147
  i->sysdep = ip4_from_ipa(ipa_from_sa4(&ifr.ifr_addr);
1148

    
1149
  return !ip4_equal(i->sysdep, addr);
1150
}