Statistics
| Branch: | Revision:

iof-bird-daemon / sysdep / linux / netlink / netlink.c @ ba321706

History | View | Annotate | Download (21.3 KB)

1
/*
2
 *        BIRD -- Linux Netlink Interface
3
 *
4
 *        (c) 1999--2000 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 <fcntl.h>
11
#include <net/if.h>
12
#include <sys/socket.h>
13
#include <sys/uio.h>
14
#include <errno.h>
15

    
16
#undef LOCAL_DEBUG
17

    
18
#include "nest/bird.h"
19
#include "nest/route.h"
20
#include "nest/protocol.h"
21
#include "nest/iface.h"
22
#include "lib/timer.h"
23
#include "lib/unix.h"
24
#include "lib/krt.h"
25
#include "lib/socket.h"
26
#include "lib/string.h"
27
#include "conf/conf.h"
28

    
29
#include <asm/types.h>
30
#include <linux/netlink.h>
31
#include <linux/rtnetlink.h>
32

    
33
#ifndef MSG_TRUNC                        /* Hack: Several versions of glibc miss this one :( */
34
#define MSG_TRUNC 0x20
35
#endif
36

    
37
/*
38
 *        Synchronous Netlink interface
39
 */
40

    
41
struct nl_sock
42
{
43
  int fd;
44
  u32 seq;
45
  byte *rx_buffer;                        /* Receive buffer */
46
  struct nlmsghdr *last_hdr;                /* Recently received packet */
47
  unsigned int last_size;
48
};
49

    
50
#define NL_RX_SIZE 8192
51

    
52
static struct nl_sock nl_scan = {.fd = -1};        /* Netlink socket for synchronous scan */
53
static struct nl_sock nl_req  = {.fd = -1};        /* Netlink socket for requests */
54

    
55
static void
56
nl_open_sock(struct nl_sock *nl)
57
{
58
  if (nl->fd < 0)
59
    {
60
      nl->fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
61
      if (nl->fd < 0)
62
        die("Unable to open rtnetlink socket: %m");
63
      nl->seq = now;
64
      nl->rx_buffer = xmalloc(NL_RX_SIZE);
65
      nl->last_hdr = NULL;
66
      nl->last_size = 0;
67
    }
68
}
69

    
70
static void
71
nl_open(void)
72
{
73
  nl_open_sock(&nl_scan);
74
  nl_open_sock(&nl_req);
75
}
76

    
77
static void
78
nl_send(struct nl_sock *nl, struct nlmsghdr *nh)
79
{
80
  struct sockaddr_nl sa;
81

    
82
  memset(&sa, 0, sizeof(sa));
83
  sa.nl_family = AF_NETLINK;
84
  nh->nlmsg_pid = 0;
85
  nh->nlmsg_seq = ++(nl->seq);
86
  if (sendto(nl->fd, nh, nh->nlmsg_len, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0)
87
    die("rtnetlink sendto: %m");
88
  nl->last_hdr = NULL;
89
}
90

    
91
static void
92
nl_request_dump(int cmd)
93
{
94
  struct {
95
    struct nlmsghdr nh;
96
    struct rtgenmsg g;
97
  } req;
98
  req.nh.nlmsg_type = cmd;
99
  req.nh.nlmsg_len = sizeof(req);
100
  req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
101
  req.g.rtgen_family = BIRD_PF;
102
  nl_send(&nl_scan, &req.nh);
103
}
104

    
105
static struct nlmsghdr *
106
nl_get_reply(struct nl_sock *nl)
107
{
108
  for(;;)
109
    {
110
      if (!nl->last_hdr)
111
        {
112
          struct iovec iov = { nl->rx_buffer, NL_RX_SIZE };
113
          struct sockaddr_nl sa;
114
          struct msghdr m = { (struct sockaddr *) &sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
115
          int x = recvmsg(nl->fd, &m, 0);
116
          if (x < 0)
117
            die("nl_get_reply: %m");
118
          if (sa.nl_pid)                /* It isn't from the kernel */
119
            {
120
              DBG("Non-kernel packet\n");
121
              continue;
122
            }
123
          nl->last_size = x;
124
          nl->last_hdr = (void *) nl->rx_buffer;
125
          if (m.msg_flags & MSG_TRUNC)
126
            bug("nl_get_reply: got truncated reply which should be impossible");
127
        }
128
      if (NLMSG_OK(nl->last_hdr, nl->last_size))
129
        {
130
          struct nlmsghdr *h = nl->last_hdr;
131
          nl->last_hdr = NLMSG_NEXT(h, nl->last_size);
132
          if (h->nlmsg_seq != nl->seq)
133
            {
134
              log(L_WARN "nl_get_reply: Ignoring out of sequence netlink packet (%x != %x)",
135
                  h->nlmsg_seq, nl->seq);
136
              continue;
137
            }
138
          return h;
139
        }
140
      if (nl->last_size)
141
        log(L_WARN "nl_get_reply: Found packet remnant of size %d", nl->last_size);
142
      nl->last_hdr = NULL;
143
    }
144
}
145

    
146
static struct rate_limit rl_netlink_err;
147

    
148
static int
149
nl_error(struct nlmsghdr *h)
150
{
151
  struct nlmsgerr *e;
152
  int ec;
153

    
154
  if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
155
    {
156
      log(L_WARN "Netlink: Truncated error message received");
157
      return ENOBUFS;
158
    }
159
  e = (struct nlmsgerr *) NLMSG_DATA(h);
160
  ec = -e->error;
161
  if (ec)
162
    log_rl(&rl_netlink_err, L_WARN "Netlink: %s", strerror(ec));
163
  return ec;
164
}
165

    
166
static struct nlmsghdr *
167
nl_get_scan(void)
168
{
169
  struct nlmsghdr *h = nl_get_reply(&nl_scan);
170

    
171
  if (h->nlmsg_type == NLMSG_DONE)
172
    return NULL;
173
  if (h->nlmsg_type == NLMSG_ERROR)
174
    {
175
      nl_error(h);
176
      return NULL;
177
    }
178
  return h;
179
}
180

    
181
static int
182
nl_exchange(struct nlmsghdr *pkt)
183
{
184
  struct nlmsghdr *h;
185

    
186
  nl_send(&nl_req, pkt);
187
  for(;;)
188
    {
189
      h = nl_get_reply(&nl_req);
190
      if (h->nlmsg_type == NLMSG_ERROR)
191
        break;
192
      log(L_WARN "nl_exchange: Unexpected reply received");
193
    }
194
  return nl_error(h);
195
}
196

    
197
/*
198
 *        Netlink attributes
199
 */
200

    
201
static int nl_attr_len;
202

    
203
static void *
204
nl_checkin(struct nlmsghdr *h, int lsize)
205
{
206
  nl_attr_len = h->nlmsg_len - NLMSG_LENGTH(lsize);
207
  if (nl_attr_len < 0)
208
    {
209
      log(L_ERR "nl_checkin: underrun by %d bytes", -nl_attr_len);
210
      return NULL;
211
    }
212
  return NLMSG_DATA(h);
213
}
214

    
215
static int
216
nl_parse_attrs(struct rtattr *a, struct rtattr **k, int ksize)
217
{
218
  int max = ksize / sizeof(struct rtattr *);
219
  bzero(k, ksize);
220
  while (RTA_OK(a, nl_attr_len))
221
    {
222
      if (a->rta_type < max)
223
        k[a->rta_type] = a;
224
      a = RTA_NEXT(a, nl_attr_len);
225
    }
226
  if (nl_attr_len)
227
    {
228
      log(L_ERR "nl_parse_attrs: remnant of size %d", nl_attr_len);
229
      return 0;
230
    }
231
  else
232
    return 1;
233
}
234

    
235
static void
236
nl_add_attr_u32(struct nlmsghdr *h, unsigned maxsize, int code, u32 data)
237
{
238
  unsigned len = RTA_LENGTH(4);
239
  struct rtattr *a;
240

    
241
  if (NLMSG_ALIGN(h->nlmsg_len) + len > maxsize)
242
    bug("nl_add_attr32: packet buffer overflow");
243
  a = (struct rtattr *)((char *)h + NLMSG_ALIGN(h->nlmsg_len));
244
  a->rta_type = code;
245
  a->rta_len = len;
246
  memcpy(RTA_DATA(a), &data, 4);
247
  h->nlmsg_len = NLMSG_ALIGN(h->nlmsg_len) + len;
248
}
249

    
250
static void
251
nl_add_attr_ipa(struct nlmsghdr *h, unsigned maxsize, int code, ip_addr ipa)
252
{
253
  unsigned len = RTA_LENGTH(sizeof(ipa));
254
  struct rtattr *a;
255

    
256
  if (NLMSG_ALIGN(h->nlmsg_len) + len > maxsize)
257
    bug("nl_add_attr_ipa: packet buffer overflow");
258
  a = (struct rtattr *)((char *)h + NLMSG_ALIGN(h->nlmsg_len));
259
  a->rta_type = code;
260
  a->rta_len = len;
261
  ipa_hton(ipa);
262
  memcpy(RTA_DATA(a), &ipa, sizeof(ipa));
263
  h->nlmsg_len = NLMSG_ALIGN(h->nlmsg_len) + len;
264
}
265

    
266
/*
267
 *        Scanning of interfaces
268
 */
269

    
270
static void
271
nl_parse_link(struct nlmsghdr *h, int scan)
272
{
273
  struct ifinfomsg *i;
274
  struct rtattr *a[IFLA_WIRELESS+1];
275
  int new = h->nlmsg_type == RTM_NEWLINK;
276
  struct iface f;
277
  struct iface *ifi;
278
  char *name;
279
  u32 mtu;
280
  unsigned int fl;
281

    
282
  if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFLA_RTA(i), a, sizeof(a)))
283
    return;
284
  if (!a[IFLA_IFNAME] || RTA_PAYLOAD(a[IFLA_IFNAME]) < 2 ||
285
      !a[IFLA_MTU] || RTA_PAYLOAD(a[IFLA_MTU]) != 4)
286
    {
287
      if (scan || !a[IFLA_WIRELESS])
288
        log(L_ERR "nl_parse_link: Malformed message received");
289
      return;
290
    }
291
  name = RTA_DATA(a[IFLA_IFNAME]);
292
  memcpy(&mtu, RTA_DATA(a[IFLA_MTU]), sizeof(u32));
293

    
294
  ifi = if_find_by_index(i->ifi_index);
295
  if (!new)
296
    {
297
      DBG("KIF: IF%d(%s) goes down\n", i->ifi_index, name);
298
      if (ifi && !scan)
299
        {
300
          memcpy(&f, ifi, sizeof(struct iface));
301
          f.flags |= IF_ADMIN_DOWN;
302
          if_update(&f);
303
        }
304
    }
305
  else
306
    {
307
      DBG("KIF: IF%d(%s) goes up (mtu=%d,flg=%x)\n", i->ifi_index, name, mtu, i->ifi_flags);
308
      if (ifi)
309
        memcpy(&f, ifi, sizeof(f));
310
      else
311
        {
312
          bzero(&f, sizeof(f));
313
          f.index = i->ifi_index;
314
        }
315
      strncpy(f.name, RTA_DATA(a[IFLA_IFNAME]), sizeof(f.name)-1);
316
      f.mtu = mtu;
317
      f.flags = 0;
318
      fl = i->ifi_flags;
319
      if (fl & IFF_UP)
320
        f.flags |= IF_LINK_UP;
321
      if (fl & IFF_LOOPBACK)                /* Loopback */
322
        f.flags |= IF_MULTIACCESS | IF_LOOPBACK | IF_IGNORE;
323
      else if (fl & IFF_POINTOPOINT)        /* PtP */
324
        f.flags |= IF_MULTICAST;
325
      else if (fl & IFF_BROADCAST)        /* Broadcast */
326
        f.flags |= IF_MULTIACCESS | IF_BROADCAST | IF_MULTICAST;
327
      else
328
        f.flags |= IF_MULTIACCESS;        /* NBMA */
329
      if_update(&f);
330
    }
331
}
332

    
333
static void
334
nl_parse_addr(struct nlmsghdr *h)
335
{
336
  struct ifaddrmsg *i;
337
  struct rtattr *a[IFA_ANYCAST+1];
338
  int new = h->nlmsg_type == RTM_NEWADDR;
339
  struct ifa ifa;
340
  struct iface *ifi;
341
  int scope;
342

    
343
  if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFA_RTA(i), a, sizeof(a)))
344
    return;
345
  if (i->ifa_family != BIRD_AF)
346
    return;
347
  if (!a[IFA_ADDRESS] || RTA_PAYLOAD(a[IFA_ADDRESS]) != sizeof(ip_addr)
348
#ifdef IPV6
349
      || a[IFA_LOCAL] && RTA_PAYLOAD(a[IFA_LOCAL]) != sizeof(ip_addr)
350
#else
351
      || !a[IFA_LOCAL] || RTA_PAYLOAD(a[IFA_LOCAL]) != sizeof(ip_addr)
352
      || (a[IFA_BROADCAST] && RTA_PAYLOAD(a[IFA_BROADCAST]) != sizeof(ip_addr))
353
#endif
354
      )
355
    {
356
      log(L_ERR "nl_parse_addr: Malformed message received");
357
      return;
358
    }
359

    
360
  ifi = if_find_by_index(i->ifa_index);
361
  if (!ifi)
362
    {
363
      log(L_ERR "KIF: Received address message for unknown interface %d", i->ifa_index);
364
      return;
365
    }
366

    
367
  bzero(&ifa, sizeof(ifa));
368
  ifa.iface = ifi;
369
  if (i->ifa_flags & IFA_F_SECONDARY)
370
    ifa.flags |= IA_SECONDARY;
371

    
372
  /* IFA_LOCAL can be unset for IPv6 interfaces */
373
  memcpy(&ifa.ip, RTA_DATA(a[IFA_LOCAL] ? : a[IFA_ADDRESS]), sizeof(ifa.ip));
374
  ipa_ntoh(ifa.ip);
375
  ifa.pxlen = i->ifa_prefixlen;
376
  if (i->ifa_prefixlen > BITS_PER_IP_ADDRESS)
377
    {
378
      log(L_ERR "KIF: Invalid prefix length for interface %s: %d", ifi->name, i->ifa_prefixlen);
379
      new = 0;
380
    }
381
  if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS)
382
    {
383
      ifa.flags |= IA_UNNUMBERED;
384
      memcpy(&ifa.opposite, RTA_DATA(a[IFA_ADDRESS]), sizeof(ifa.opposite));
385
      ipa_ntoh(ifa.opposite);
386
      ifa.prefix = ifa.brd = ifa.opposite;
387
    }
388
  else
389
    {
390
      ip_addr netmask = ipa_mkmask(ifa.pxlen);
391
      ifa.prefix = ipa_and(ifa.ip, netmask);
392
      ifa.brd = ipa_or(ifa.ip, ipa_not(netmask));
393
      if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 1)
394
        ifa.opposite = ipa_opposite_m1(ifa.ip);
395

    
396
#ifndef IPV6
397
      if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 2)
398
        ifa.opposite = ipa_opposite_m2(ifa.ip);
399

    
400
      if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST])
401
        {
402
          ip_addr xbrd;
403
          memcpy(&xbrd, RTA_DATA(a[IFA_BROADCAST]), sizeof(xbrd));
404
          ipa_ntoh(xbrd);
405
          if (ipa_equal(xbrd, ifa.prefix) || ipa_equal(xbrd, ifa.brd))
406
            ifa.brd = xbrd;
407
          else if (ifi->flags & IF_TMP_DOWN) /* Complain only during the first scan */
408
            log(L_ERR "KIF: Invalid broadcast address %I for %s", xbrd, ifi->name);
409
        }
410
#endif
411
    }
412

    
413
  scope = ipa_classify(ifa.ip);
414
  if (scope < 0)
415
    {
416
      log(L_ERR "KIF: Invalid interface address %I for %s", ifa.ip, ifi->name);
417
      return;
418
    }
419
  ifa.scope = scope & IADDR_SCOPE_MASK;
420

    
421
  DBG("KIF: IF%d(%s): %s IPA %I, flg %x, net %I/%d, brd %I, opp %I\n",
422
      ifi->index, ifi->name,
423
      new ? "added" : "removed",
424
      ifa.ip, ifa.flags, ifa.prefix, ifa.pxlen, ifa.brd, ifa.opposite);
425
  if (new)
426
    ifa_update(&ifa);
427
  else
428
    ifa_delete(&ifa);
429
}
430

    
431
void
432
krt_if_scan(struct kif_proto *p UNUSED)
433
{
434
  struct nlmsghdr *h;
435

    
436
  if_start_update();
437

    
438
  nl_request_dump(RTM_GETLINK);
439
  while (h = nl_get_scan())
440
    if (h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)
441
      nl_parse_link(h, 1);
442
    else
443
      log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
444

    
445
  nl_request_dump(RTM_GETADDR);
446
  while (h = nl_get_scan())
447
    if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
448
      nl_parse_addr(h);
449
    else
450
      log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
451

    
452
  if_end_update();
453
}
454

    
455
/*
456
 *        Routes
457
 */
458

    
459
static struct krt_proto *nl_table_map[NL_NUM_TABLES];
460

    
461
int
462
krt_capable(rte *e)
463
{
464
  rta *a = e->attrs;
465

    
466
  if (a->cast != RTC_UNICAST)
467
    return 0;
468

    
469
  switch (a->dest)
470
    {
471
    case RTD_ROUTER:
472
      if (ipa_has_link_scope(a->gw) && (a->iface == NULL))
473
        return 0;
474
    case RTD_DEVICE:
475
    case RTD_BLACKHOLE:
476
    case RTD_UNREACHABLE:
477
    case RTD_PROHIBIT:
478
      break;
479
    default:
480
      return 0;
481
    }
482
  return 1;
483
}
484

    
485
static void
486
nl_send_route(struct krt_proto *p, rte *e, int new)
487
{
488
  net *net = e->net;
489
  rta *a = e->attrs;
490
  struct {
491
    struct nlmsghdr h;
492
    struct rtmsg r;
493
    char buf[128];
494
  } r;
495

    
496
  DBG("nl_send_route(%I/%d,new=%d)\n", net->n.prefix, net->n.pxlen, new);
497

    
498
  bzero(&r.h, sizeof(r.h));
499
  bzero(&r.r, sizeof(r.r));
500
  r.h.nlmsg_type = new ? RTM_NEWROUTE : RTM_DELROUTE;
501
  r.h.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
502
  r.h.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (new ? NLM_F_CREATE|NLM_F_EXCL : 0);
503

    
504
  r.r.rtm_family = BIRD_AF;
505
  r.r.rtm_dst_len = net->n.pxlen;
506
  r.r.rtm_tos = 0;
507
  r.r.rtm_table = KRT_CF->scan.table_id;
508
  r.r.rtm_protocol = RTPROT_BIRD;
509
  r.r.rtm_scope = RT_SCOPE_UNIVERSE;
510
  nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix);
511
  switch (a->dest)
512
    {
513
    case RTD_ROUTER:
514
      r.r.rtm_type = RTN_UNICAST;
515
      nl_add_attr_ipa(&r.h, sizeof(r), RTA_GATEWAY, a->gw);
516

    
517
      /* a->iface != NULL checked in krt_capable() */
518
      if (ipa_has_link_scope(a->gw))
519
        nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
520

    
521
      break;
522
    case RTD_DEVICE:
523
      if (!a->iface)
524
        return;
525
      r.r.rtm_type = RTN_UNICAST;
526
      nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
527
      break;
528
    case RTD_BLACKHOLE:
529
      r.r.rtm_type = RTN_BLACKHOLE;
530
      break;
531
    case RTD_UNREACHABLE:
532
      r.r.rtm_type = RTN_UNREACHABLE;
533
      break;
534
    case RTD_PROHIBIT:
535
      r.r.rtm_type = RTN_PROHIBIT;
536
      break;
537
    default:
538
      bug("krt_capable inconsistent with nl_send_route");
539
    }
540

    
541
  nl_exchange(&r.h);
542
}
543

    
544
void
545
krt_set_notify(struct krt_proto *p, net *n UNUSED, rte *new, rte *old)
546
{
547
  if (old)
548
    nl_send_route(p, old, 0);
549

    
550
  if (new)
551
    nl_send_route(p, new, 1);
552
}
553

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

    
556
static void
557
nl_parse_route(struct nlmsghdr *h, int scan)
558
{
559
  struct krt_proto *p;
560
  struct rtmsg *i;
561
  struct rtattr *a[RTA_CACHEINFO+1];
562
  int new = h->nlmsg_type == RTM_NEWROUTE;
563
  ip_addr dst;
564
  rta ra;
565
  rte *e;
566
  net *net;
567
  u32 oif;
568
  int src;
569

    
570
  if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(RTM_RTA(i), a, sizeof(a)))
571
    return;
572
  if (i->rtm_family != BIRD_AF)
573
    return;
574
  if ((a[RTA_DST] && RTA_PAYLOAD(a[RTA_DST]) != sizeof(ip_addr)) ||
575
      (a[RTA_OIF] && RTA_PAYLOAD(a[RTA_OIF]) != 4) ||
576
      (a[RTA_PRIORITY] && RTA_PAYLOAD(a[RTA_PRIORITY]) != 4) ||
577
#ifdef IPV6
578
      (a[RTA_IIF] && RTA_PAYLOAD(a[RTA_IIF]) != 4) ||
579
#endif
580
      (a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)))
581
    {
582
      log(L_ERR "KRT: Malformed message received");
583
      return;
584
    }
585

    
586
  if (a[RTA_DST])
587
    {
588
      memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst));
589
      ipa_ntoh(dst);
590
    }
591
  else
592
    dst = IPA_NONE;
593

    
594
  if (a[RTA_OIF])
595
    memcpy(&oif, RTA_DATA(a[RTA_OIF]), sizeof(oif));
596
  else
597
    oif = ~0;
598

    
599
  DBG("KRT: Got %I/%d, type=%d, oif=%d, table=%d, prid=%d, proto=%s\n", dst, i->rtm_dst_len, i->rtm_type, oif, i->rtm_table, i->rtm_protocol, p->p.name);
600

    
601
  p = nl_table_map[i->rtm_table];        /* Do we know this table? */
602
  if (!p)
603
    SKIP("unknown table %d", i->rtm_table);
604

    
605
#ifdef IPV6
606
  if (a[RTA_IIF])
607
    SKIP("IIF set\n");
608
#else
609
  if (i->rtm_tos != 0)                        /* We don't support TOS */
610
    SKIP("TOS %02x\n", i->rtm_tos);
611
#endif
612

    
613
  if (scan && !new)
614
    SKIP("RTM_DELROUTE in scan\n");
615

    
616
  int c = ipa_classify_net(dst);
617
  if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
618
    SKIP("strange class/scope\n");
619

    
620
  // ignore rtm_scope, it is not a real scope
621
  // if (i->rtm_scope != RT_SCOPE_UNIVERSE)
622
  //   SKIP("scope %u\n", i->rtm_scope);
623

    
624
  switch (i->rtm_protocol)
625
    {
626
    case RTPROT_UNSPEC:
627
      SKIP("proto unspec\n");
628

    
629
    case RTPROT_REDIRECT:
630
      src = KRT_SRC_REDIRECT;
631
      break;
632

    
633
    case RTPROT_KERNEL:
634
      src = KRT_SRC_KERNEL;
635
      return;
636

    
637
    case RTPROT_BIRD:
638
      if (!scan)
639
        SKIP("echo\n");
640
      src = KRT_SRC_BIRD;
641
      break;
642

    
643
    case RTPROT_BOOT:
644
    default:
645
      src = KRT_SRC_ALIEN;
646
    }
647

    
648
  net = net_get(p->p.table, dst, i->rtm_dst_len);
649
  ra.proto = &p->p;
650
  ra.source = RTS_INHERIT;
651
  ra.scope = SCOPE_UNIVERSE;
652
  ra.cast = RTC_UNICAST;
653
  ra.flags = ra.aflags = 0;
654
  ra.from = IPA_NONE;
655
  ra.gw = IPA_NONE;
656
  ra.iface = NULL;
657
  ra.eattrs = NULL;
658

    
659
  switch (i->rtm_type)
660
    {
661
    case RTN_UNICAST:
662
      ra.iface = if_find_by_index(oif);
663
      if (!ra.iface)
664
        {
665
          log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u",
666
              net->n.prefix, net->n.pxlen, oif);
667
          return;
668
        }
669

    
670
      if (a[RTA_GATEWAY])
671
        {
672
          neighbor *ng;
673
          ra.dest = RTD_ROUTER;
674
          memcpy(&ra.gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ra.gw));
675
          ipa_ntoh(ra.gw);
676

    
677
          ng = neigh_find2(&p->p, &ra.gw, ra.iface,
678
                           (i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
679
          if (!ng || (ng->scope == SCOPE_HOST))
680
            {
681
              log(L_ERR "KRT: Received route %I/%d with strange next-hop %I",
682
                  net->n.prefix, net->n.pxlen, ra.gw);
683
              return;
684
            }
685
        }
686
      else
687
        {
688
          ra.dest = RTD_DEVICE;
689

    
690
          /*
691
           * In Linux IPv6, 'native' device routes have proto
692
           * RTPROT_BOOT and not RTPROT_KERNEL (which they have in
693
           * IPv4 and which is expected). We cannot distinguish
694
           * 'native' and user defined device routes, so we ignore all
695
           * such device routes and for consistency, we have the same
696
           * behavior in IPv4. Anyway, users should use RTPROT_STATIC
697
           * for their 'alien' routes.
698
           */
699

    
700
          if (i->rtm_protocol == RTPROT_BOOT)
701
            src = KRT_SRC_KERNEL;
702
        }
703

    
704
      break;
705
    case RTN_BLACKHOLE:
706
      ra.dest = RTD_BLACKHOLE;
707
      break;
708
    case RTN_UNREACHABLE:
709
      ra.dest = RTD_UNREACHABLE;
710
      break;
711
    case RTN_PROHIBIT:
712
      ra.dest = RTD_PROHIBIT;
713
      break;
714
    /* FIXME: What about RTN_THROW? */
715
    default:
716
      SKIP("type %d\n", i->rtm_type);
717
      return;
718
    }
719

    
720
  e = rte_get_temp(&ra);
721
  e->net = net;
722
  e->u.krt.src = src;
723
  e->u.krt.proto = i->rtm_protocol;
724
  e->u.krt.type = i->rtm_type;
725
  if (a[RTA_PRIORITY])
726
    memcpy(&e->u.krt.metric, RTA_DATA(a[RTA_PRIORITY]), sizeof(e->u.krt.metric));
727
  else
728
    e->u.krt.metric = 0;
729
  if (scan)
730
    krt_got_route(p, e);
731
  else
732
    krt_got_route_async(p, e, new);
733
}
734

    
735
void
736
krt_scan_fire(struct krt_proto *p UNUSED)        /* CONFIG_ALL_TABLES_AT_ONCE => p is NULL */
737
{
738
  struct nlmsghdr *h;
739

    
740
  nl_request_dump(RTM_GETROUTE);
741
  while (h = nl_get_scan())
742
    if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)
743
      nl_parse_route(h, 1);
744
    else
745
      log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type);
746
}
747

    
748
/*
749
 *        Asynchronous Netlink interface
750
 */
751

    
752
static sock *nl_async_sk;                /* BIRD socket for asynchronous notifications */
753
static byte *nl_async_rx_buffer;        /* Receive buffer */
754

    
755
static void
756
nl_async_msg(struct nlmsghdr *h)
757
{
758
  switch (h->nlmsg_type)
759
    {
760
    case RTM_NEWROUTE:
761
    case RTM_DELROUTE:
762
      DBG("KRT: Received async route notification (%d)\n", h->nlmsg_type);
763
      nl_parse_route(h, 0);
764
      break;
765
    case RTM_NEWLINK:
766
    case RTM_DELLINK:
767
      DBG("KRT: Received async link notification (%d)\n", h->nlmsg_type);
768
      nl_parse_link(h, 0);
769
      break;
770
    case RTM_NEWADDR:
771
    case RTM_DELADDR:
772
      DBG("KRT: Received async address notification (%d)\n", h->nlmsg_type);
773
      nl_parse_addr(h);
774
      break;
775
    default:
776
      DBG("KRT: Received unknown async notification (%d)\n", h->nlmsg_type);
777
    }
778
}
779

    
780
static int
781
nl_async_hook(sock *sk, int size UNUSED)
782
{
783
  struct iovec iov = { nl_async_rx_buffer, NL_RX_SIZE };
784
  struct sockaddr_nl sa;
785
  struct msghdr m = { (struct sockaddr *) &sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
786
  struct nlmsghdr *h;
787
  int x;
788
  unsigned int len;
789

    
790
  x = recvmsg(sk->fd, &m, 0);
791
  if (x < 0)
792
    {
793
      if (errno == ENOBUFS)
794
        {
795
          /*
796
           *  Netlink reports some packets have been thrown away.
797
           *  One day we might react to it by asking for route table
798
           *  scan in near future.
799
           */
800
          return 1;        /* More data are likely to be ready */
801
        }
802
      else if (errno != EWOULDBLOCK)
803
        log(L_ERR "Netlink recvmsg: %m");
804
      return 0;
805
    }
806
  if (sa.nl_pid)                /* It isn't from the kernel */
807
    {
808
      DBG("Non-kernel packet\n");
809
      return 1;
810
    }
811
  h = (void *) nl_async_rx_buffer;
812
  len = x;
813
  if (m.msg_flags & MSG_TRUNC)
814
    {
815
      log(L_WARN "Netlink got truncated asynchronous message");
816
      return 1;
817
    }
818
  while (NLMSG_OK(h, len))
819
    {
820
      nl_async_msg(h);
821
      h = NLMSG_NEXT(h, len);
822
    }
823
  if (len)
824
    log(L_WARN "nl_async_hook: Found packet remnant of size %d", len);
825
  return 1;
826
}
827

    
828
static void
829
nl_open_async(void)
830
{
831
  sock *sk;
832
  struct sockaddr_nl sa;
833
  int fd;
834
  static int nl_open_tried = 0;
835

    
836
  if (nl_open_tried)
837
    return;
838
  nl_open_tried = 1;
839

    
840
  DBG("KRT: Opening async netlink socket\n");
841

    
842
  fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
843
  if (fd < 0)
844
    {
845
      log(L_ERR "Unable to open asynchronous rtnetlink socket: %m");
846
      return;
847
    }
848

    
849
  bzero(&sa, sizeof(sa));
850
  sa.nl_family = AF_NETLINK;
851
#ifdef IPV6
852
  sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE;
853
#else
854
  sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
855
#endif
856
  if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
857
    {
858
      log(L_ERR "Unable to bind asynchronous rtnetlink socket: %m");
859
      return;
860
    }
861

    
862
  sk = nl_async_sk = sk_new(krt_pool);
863
  sk->type = SK_MAGIC;
864
  sk->rx_hook = nl_async_hook;
865
  sk->fd = fd;
866
  if (sk_open(sk))
867
    bug("Netlink: sk_open failed");
868

    
869
  if (!nl_async_rx_buffer)
870
    nl_async_rx_buffer = xmalloc(NL_RX_SIZE);
871
}
872

    
873
/*
874
 *        Interface to the UNIX krt module
875
 */
876

    
877
static u8 nl_cf_table[(NL_NUM_TABLES+7) / 8];
878

    
879
void
880
krt_scan_preconfig(struct config *c UNUSED)
881
{
882
  bzero(&nl_cf_table, sizeof(nl_cf_table));
883
}
884

    
885
void
886
krt_scan_postconfig(struct krt_config *x)
887
{
888
  int id = x->scan.table_id;
889

    
890
  if (nl_cf_table[id/8] & (1 << (id%8)))
891
    cf_error("Multiple kernel syncers defined for table #%d", id);
892
  nl_cf_table[id/8] |= (1 << (id%8));
893
}
894

    
895
void
896
krt_scan_construct(struct krt_config *x)
897
{
898
#ifndef IPV6
899
  x->scan.table_id = RT_TABLE_MAIN;
900
#else
901
  x->scan.table_id = 254;
902
#endif
903
}
904

    
905
void
906
krt_scan_start(struct krt_proto *p, int first)
907
{
908
  init_list(&p->scan.temp_ifs);
909
  nl_table_map[KRT_CF->scan.table_id] = p;
910
  if (first)
911
    {
912
      nl_open();
913
      nl_open_async();
914
    }
915
}
916

    
917
void
918
krt_scan_shutdown(struct krt_proto *p UNUSED, int last UNUSED)
919
{
920
}
921

    
922
void
923
krt_if_start(struct kif_proto *p UNUSED)
924
{
925
  nl_open();
926
  nl_open_async();
927
}