]> git.ipfire.org Git - thirdparty/bird.git/blob - sysdep/linux/netlink/netlink.c
a70428efe33d513c1fc84661a176655362d5c41d
[thirdparty/bird.git] / sysdep / linux / netlink / netlink.c
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 static int nl_sync_fd = -1; /* Unix socket for synchronous netlink actions */
42 static u32 nl_sync_seq; /* Sequence number of last request sent */
43
44 static byte *nl_rx_buffer; /* Receive buffer */
45 #define NL_RX_SIZE 8192
46
47 static struct nlmsghdr *nl_last_hdr; /* Recently received packet */
48 static unsigned int nl_last_size;
49
50 static void
51 nl_open(void)
52 {
53 if (nl_sync_fd < 0)
54 {
55 nl_sync_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
56 if (nl_sync_fd < 0)
57 die("Unable to open rtnetlink socket: %m");
58 nl_sync_seq = now;
59 nl_rx_buffer = xmalloc(NL_RX_SIZE);
60 }
61 }
62
63 static void
64 nl_send(struct nlmsghdr *nh)
65 {
66 struct sockaddr_nl sa;
67
68 memset(&sa, 0, sizeof(sa));
69 sa.nl_family = AF_NETLINK;
70 nh->nlmsg_pid = 0;
71 nh->nlmsg_seq = ++nl_sync_seq;
72 if (sendto(nl_sync_fd, nh, nh->nlmsg_len, 0, (struct sockaddr *)&sa, sizeof(sa)) < 0)
73 die("rtnetlink sendto: %m");
74 nl_last_hdr = NULL;
75 }
76
77 static void
78 nl_request_dump(int cmd)
79 {
80 struct {
81 struct nlmsghdr nh;
82 struct rtgenmsg g;
83 } req;
84 req.nh.nlmsg_type = cmd;
85 req.nh.nlmsg_len = sizeof(req);
86 req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
87 req.g.rtgen_family = BIRD_PF;
88 nl_send(&req.nh);
89 }
90
91 static struct nlmsghdr *
92 nl_get_reply(void)
93 {
94 for(;;)
95 {
96 if (!nl_last_hdr)
97 {
98 struct iovec iov = { nl_rx_buffer, NL_RX_SIZE };
99 struct sockaddr_nl sa;
100 struct msghdr m = { (struct sockaddr *) &sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
101 int x = recvmsg(nl_sync_fd, &m, 0);
102 if (x < 0)
103 die("nl_get_reply: %m");
104 if (sa.nl_pid) /* It isn't from the kernel */
105 {
106 DBG("Non-kernel packet\n");
107 continue;
108 }
109 nl_last_size = x;
110 nl_last_hdr = (void *) nl_rx_buffer;
111 if (m.msg_flags & MSG_TRUNC)
112 bug("nl_get_reply: got truncated reply which should be impossible");
113 }
114 if (NLMSG_OK(nl_last_hdr, nl_last_size))
115 {
116 struct nlmsghdr *h = nl_last_hdr;
117 nl_last_hdr = NLMSG_NEXT(h, nl_last_size);
118 if (h->nlmsg_seq != nl_sync_seq)
119 {
120 log(L_WARN "nl_get_reply: Ignoring out of sequence netlink packet (%x != %x)",
121 h->nlmsg_seq, nl_sync_seq);
122 continue;
123 }
124 return h;
125 }
126 if (nl_last_size)
127 log(L_WARN "nl_get_reply: Found packet remnant of size %d", nl_last_size);
128 nl_last_hdr = NULL;
129 }
130 }
131
132 static int
133 nl_error(struct nlmsghdr *h)
134 {
135 struct nlmsgerr *e;
136 int ec;
137
138 if (h->nlmsg_len < NLMSG_LENGTH(sizeof(struct nlmsgerr)))
139 {
140 log(L_WARN "Netlink: Truncated error message received");
141 return ENOBUFS;
142 }
143 e = (struct nlmsgerr *) NLMSG_DATA(h);
144 ec = -e->error;
145 if (ec)
146 log(L_WARN "Netlink: %s", strerror(ec));
147 return ec;
148 }
149
150 static struct nlmsghdr *
151 nl_get_scan(void)
152 {
153 struct nlmsghdr *h = nl_get_reply();
154
155 if (h->nlmsg_type == NLMSG_DONE)
156 return NULL;
157 if (h->nlmsg_type == NLMSG_ERROR)
158 {
159 nl_error(h);
160 return NULL;
161 }
162 return h;
163 }
164
165 static int
166 nl_exchange(struct nlmsghdr *pkt)
167 {
168 struct nlmsghdr *h;
169
170 nl_send(pkt);
171 for(;;)
172 {
173 h = nl_get_reply();
174 if (h->nlmsg_type == NLMSG_ERROR)
175 break;
176 log(L_WARN "nl_exchange: Unexpected reply received");
177 }
178 return nl_error(h);
179 }
180
181 /*
182 * Netlink attributes
183 */
184
185 static int nl_attr_len;
186
187 static void *
188 nl_checkin(struct nlmsghdr *h, int lsize)
189 {
190 nl_attr_len = h->nlmsg_len - NLMSG_LENGTH(lsize);
191 if (nl_attr_len < 0)
192 {
193 log(L_ERR "nl_checkin: underrun by %d bytes", -nl_attr_len);
194 return NULL;
195 }
196 return NLMSG_DATA(h);
197 }
198
199 static int
200 nl_parse_attrs(struct rtattr *a, struct rtattr **k, int ksize)
201 {
202 int max = ksize / sizeof(struct rtattr *);
203 bzero(k, ksize);
204 while (RTA_OK(a, nl_attr_len))
205 {
206 if (a->rta_type < max)
207 k[a->rta_type] = a;
208 a = RTA_NEXT(a, nl_attr_len);
209 }
210 if (nl_attr_len)
211 {
212 log(L_ERR "nl_parse_attrs: remnant of size %d", nl_attr_len);
213 return 0;
214 }
215 else
216 return 1;
217 }
218
219 static void
220 nl_add_attr_u32(struct nlmsghdr *h, unsigned maxsize, int code, u32 data)
221 {
222 unsigned len = RTA_LENGTH(4);
223 struct rtattr *a;
224
225 if (NLMSG_ALIGN(h->nlmsg_len) + len > maxsize)
226 bug("nl_add_attr32: packet buffer overflow");
227 a = (struct rtattr *)((char *)h + NLMSG_ALIGN(h->nlmsg_len));
228 a->rta_type = code;
229 a->rta_len = len;
230 memcpy(RTA_DATA(a), &data, 4);
231 h->nlmsg_len = NLMSG_ALIGN(h->nlmsg_len) + len;
232 }
233
234 static void
235 nl_add_attr_ipa(struct nlmsghdr *h, unsigned maxsize, int code, ip_addr ipa)
236 {
237 unsigned len = RTA_LENGTH(sizeof(ipa));
238 struct rtattr *a;
239
240 if (NLMSG_ALIGN(h->nlmsg_len) + len > maxsize)
241 bug("nl_add_attr_ipa: packet buffer overflow");
242 a = (struct rtattr *)((char *)h + NLMSG_ALIGN(h->nlmsg_len));
243 a->rta_type = code;
244 a->rta_len = len;
245 ipa_hton(ipa);
246 memcpy(RTA_DATA(a), &ipa, sizeof(ipa));
247 h->nlmsg_len = NLMSG_ALIGN(h->nlmsg_len) + len;
248 }
249
250 /*
251 * Scanning of interfaces
252 */
253
254 static void
255 nl_parse_link(struct nlmsghdr *h, int scan)
256 {
257 struct ifinfomsg *i;
258 struct rtattr *a[IFLA_STATS+1];
259 int new = h->nlmsg_type == RTM_NEWLINK;
260 struct iface f;
261 struct iface *ifi;
262 char *name;
263 u32 mtu;
264 unsigned int fl;
265
266 if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFLA_RTA(i), a, sizeof(a)))
267 return;
268 if (!a[IFLA_IFNAME] || RTA_PAYLOAD(a[IFLA_IFNAME]) < 2 ||
269 !a[IFLA_MTU] || RTA_PAYLOAD(a[IFLA_MTU]) != 4)
270 {
271 log(L_ERR "nl_parse_link: Malformed message received");
272 return;
273 }
274 name = RTA_DATA(a[IFLA_IFNAME]);
275 memcpy(&mtu, RTA_DATA(a[IFLA_MTU]), sizeof(u32));
276
277 ifi = if_find_by_index(i->ifi_index);
278 if (!new)
279 {
280 DBG("KIF: IF%d(%s) goes down\n", i->ifi_index, name);
281 if (ifi && !scan)
282 {
283 memcpy(&f, ifi, sizeof(struct iface));
284 f.flags |= IF_ADMIN_DOWN;
285 if_update(&f);
286 }
287 }
288 else
289 {
290 DBG("KIF: IF%d(%s) goes up (mtu=%d,flg=%x)\n", i->ifi_index, name, mtu, i->ifi_flags);
291 if (ifi)
292 memcpy(&f, ifi, sizeof(f));
293 else
294 {
295 bzero(&f, sizeof(f));
296 f.index = i->ifi_index;
297 }
298 strncpy(f.name, RTA_DATA(a[IFLA_IFNAME]), sizeof(f.name)-1);
299 f.mtu = mtu;
300 f.flags = 0;
301 fl = i->ifi_flags;
302 if (fl & IFF_UP)
303 f.flags |= IF_LINK_UP;
304 if (fl & IFF_LOOPBACK) /* Loopback */
305 f.flags |= IF_MULTIACCESS | IF_LOOPBACK | IF_IGNORE;
306 else if (fl & IFF_POINTOPOINT) /* PtP */
307 f.flags |= IF_MULTICAST;
308 else if (fl & IFF_BROADCAST) /* Broadcast */
309 f.flags |= IF_MULTIACCESS | IF_BROADCAST | IF_MULTICAST;
310 else
311 f.flags |= IF_MULTIACCESS; /* NBMA */
312 if_update(&f);
313 }
314 }
315
316 static void
317 nl_parse_addr(struct nlmsghdr *h)
318 {
319 struct ifaddrmsg *i;
320 struct rtattr *a[IFA_ANYCAST+1];
321 int new = h->nlmsg_type == RTM_NEWADDR;
322 struct ifa ifa;
323 struct iface *ifi;
324 int scope;
325
326 if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFA_RTA(i), a, sizeof(a)))
327 return;
328 if (i->ifa_family != BIRD_AF)
329 return;
330 if (!a[IFA_ADDRESS] || RTA_PAYLOAD(a[IFA_ADDRESS]) != sizeof(ip_addr)
331 #ifdef IPV6
332 || a[IFA_LOCAL] && RTA_PAYLOAD(a[IFA_LOCAL]) != sizeof(ip_addr)
333 #else
334 || !a[IFA_LOCAL] || RTA_PAYLOAD(a[IFA_LOCAL]) != sizeof(ip_addr)
335 || (a[IFA_BROADCAST] && RTA_PAYLOAD(a[IFA_BROADCAST]) != sizeof(ip_addr))
336 #endif
337 )
338 {
339 log(L_ERR "nl_parse_addr: Malformed message received");
340 return;
341 }
342
343 ifi = if_find_by_index(i->ifa_index);
344 if (!ifi)
345 {
346 log(L_ERR "KIF: Received address message for unknown interface %d", i->ifa_index);
347 return;
348 }
349
350 bzero(&ifa, sizeof(ifa));
351 ifa.iface = ifi;
352 if (i->ifa_flags & IFA_F_SECONDARY)
353 ifa.flags |= IA_SECONDARY;
354
355 /* IFA_LOCAL can be unset for IPv6 interfaces */
356 memcpy(&ifa.ip, RTA_DATA(a[IFA_LOCAL] ? : a[IFA_ADDRESS]), sizeof(ifa.ip));
357 ipa_ntoh(ifa.ip);
358 ifa.pxlen = i->ifa_prefixlen;
359 if (i->ifa_prefixlen > BITS_PER_IP_ADDRESS ||
360 i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 1)
361 {
362 log(L_ERR "KIF: Invalid prefix length for interface %s: %d", ifi->name, i->ifa_prefixlen);
363 new = 0;
364 }
365 if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS)
366 {
367 ifa.flags |= IA_UNNUMBERED;
368 memcpy(&ifa.opposite, RTA_DATA(a[IFA_ADDRESS]), sizeof(ifa.opposite));
369 ipa_ntoh(ifa.opposite);
370 ifa.prefix = ifa.brd = ifa.opposite;
371 }
372 else
373 {
374 ip_addr netmask = ipa_mkmask(ifa.pxlen);
375 ip_addr xbrd;
376 ifa.prefix = ipa_and(ifa.ip, netmask);
377 ifa.brd = ipa_or(ifa.ip, ipa_not(netmask));
378 #ifndef IPV6
379 if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 2)
380 ifa.opposite = ipa_opposite(ifa.ip, i->ifa_prefixlen);
381 if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST])
382 {
383 memcpy(&xbrd, RTA_DATA(a[IFA_BROADCAST]), sizeof(xbrd));
384 ipa_ntoh(xbrd);
385 if (ipa_equal(xbrd, ifa.prefix) || ipa_equal(xbrd, ifa.brd))
386 ifa.brd = xbrd;
387 else
388 log(L_ERR "KIF: Invalid broadcast address %I for %s", xbrd, ifi->name);
389 }
390 #endif
391 }
392
393 scope = ipa_classify(ifa.ip);
394 if (scope < 0)
395 {
396 log(L_ERR "KIF: Invalid interface address %I for %s", ifa.ip, ifi->name);
397 return;
398 }
399 ifa.scope = scope & IADDR_SCOPE_MASK;
400
401 DBG("KIF: IF%d(%s): %s IPA %I, flg %x, net %I/%d, brd %I, opp %I\n",
402 ifi->index, ifi->name,
403 new ? "added" : "removed",
404 ifa.ip, ifa.flags, ifa.prefix, ifa.pxlen, ifa.brd, ifa.opposite);
405 if (new)
406 ifa_update(&ifa);
407 else
408 ifa_delete(&ifa);
409 }
410
411 void
412 krt_if_scan(struct kif_proto *p UNUSED)
413 {
414 struct nlmsghdr *h;
415
416 if_start_update();
417
418 nl_request_dump(RTM_GETLINK);
419 while (h = nl_get_scan())
420 if (h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)
421 nl_parse_link(h, 1);
422 else
423 log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
424
425 nl_request_dump(RTM_GETADDR);
426 while (h = nl_get_scan())
427 if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
428 nl_parse_addr(h);
429 else
430 log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
431
432 if_end_update();
433 }
434
435 /*
436 * Routes
437 */
438
439 static struct krt_proto *nl_table_map[NL_NUM_TABLES];
440
441 int
442 krt_capable(rte *e)
443 {
444 rta *a = e->attrs;
445
446 if (a->cast != RTC_UNICAST
447 #if 0
448 && a->cast != RTC_ANYCAST
449 #endif
450 )
451 return 0;
452 if (a->source == RTS_DEVICE) /* Kernel takes care of device routes itself */
453 return 0;
454 switch (a->dest)
455 {
456 case RTD_ROUTER:
457 case RTD_DEVICE:
458 case RTD_BLACKHOLE:
459 case RTD_UNREACHABLE:
460 case RTD_PROHIBIT:
461 break;
462 default:
463 return 0;
464 }
465 return 1;
466 }
467
468 static void
469 nl_send_route(struct krt_proto *p, rte *e, int new)
470 {
471 net *net = e->net;
472 rta *a = e->attrs;
473 struct {
474 struct nlmsghdr h;
475 struct rtmsg r;
476 char buf[128];
477 } r;
478
479 DBG("nl_send_route(%I/%d,new=%d)\n", net->n.prefix, net->n.pxlen, new);
480
481 bzero(&r.h, sizeof(r.h));
482 bzero(&r.r, sizeof(r.r));
483 r.h.nlmsg_type = new ? RTM_NEWROUTE : RTM_DELROUTE;
484 r.h.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
485 r.h.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (new ? NLM_F_CREATE|NLM_F_REPLACE : 0);
486
487 r.r.rtm_family = BIRD_AF;
488 r.r.rtm_dst_len = net->n.pxlen;
489 r.r.rtm_tos = 0;
490 r.r.rtm_table = KRT_CF->scan.table_id;
491 r.r.rtm_protocol = RTPROT_BIRD;
492 r.r.rtm_scope = RT_SCOPE_UNIVERSE;
493 nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix);
494 switch (a->dest)
495 {
496 case RTD_ROUTER:
497 r.r.rtm_type = RTN_UNICAST;
498 nl_add_attr_ipa(&r.h, sizeof(r), RTA_GATEWAY, a->gw);
499 break;
500 case RTD_DEVICE:
501 r.r.rtm_type = RTN_UNICAST;
502 nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
503 break;
504 case RTD_BLACKHOLE:
505 r.r.rtm_type = RTN_BLACKHOLE;
506 break;
507 case RTD_UNREACHABLE:
508 r.r.rtm_type = RTN_UNREACHABLE;
509 break;
510 case RTD_PROHIBIT:
511 r.r.rtm_type = RTN_PROHIBIT;
512 break;
513 default:
514 bug("krt_capable inconsistent with nl_send_route");
515 }
516
517 nl_exchange(&r.h);
518 }
519
520 void
521 krt_set_notify(struct krt_proto *p, net *n UNUSED, rte *new, rte *old)
522 {
523 if (old && new)
524 {
525 /*
526 * We should check whether priority and TOS is identical as well,
527 * but we don't use these and default value is always equal to default value. :-)
528 */
529 nl_send_route(p, new, 1);
530 }
531 else
532 {
533 if (old)
534 {
535 if (!old->attrs->iface || (old->attrs->iface->flags & IF_UP))
536 nl_send_route(p, old, 0);
537 /* else the kernel has already flushed it */
538 }
539 if (new)
540 nl_send_route(p, new, 1);
541 }
542 }
543
544 static struct iface *
545 krt_temp_iface(struct krt_proto *p, unsigned index)
546 {
547 struct iface *i, *j;
548
549 WALK_LIST(i, p->scan.temp_ifs)
550 if (i->index == index)
551 return i;
552 i = mb_allocz(p->p.pool, sizeof(struct iface));
553 if (j = if_find_by_index(index))
554 strcpy(i->name, j->name);
555 else
556 strcpy(i->name, "?");
557 i->index = index;
558 add_tail(&p->scan.temp_ifs, &i->n);
559 return i;
560 }
561
562 static void
563 nl_parse_route(struct nlmsghdr *h, int scan)
564 {
565 struct krt_proto *p;
566 struct rtmsg *i;
567 struct rtattr *a[RTA_CACHEINFO+1];
568 int new = h->nlmsg_type == RTM_NEWROUTE;
569 ip_addr dst;
570 rta ra;
571 rte *e;
572 net *net;
573 u32 oif;
574 int src;
575
576 if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(RTM_RTA(i), a, sizeof(a)))
577 return;
578 if (i->rtm_family != BIRD_AF)
579 return;
580 if ((a[RTA_DST] && RTA_PAYLOAD(a[RTA_DST]) != sizeof(ip_addr)) ||
581 (a[RTA_OIF] && RTA_PAYLOAD(a[RTA_OIF]) != 4) ||
582 (a[RTA_PRIORITY] && RTA_PAYLOAD(a[RTA_PRIORITY]) != 4) ||
583 #ifdef IPV6
584 (a[RTA_IIF] && RTA_PAYLOAD(a[RTA_IIF]) != 4) ||
585 #endif
586 (a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)))
587 {
588 log(L_ERR "nl_parse_route: Malformed message received");
589 return;
590 }
591
592 p = nl_table_map[i->rtm_table]; /* Do we know this table? */
593 if (!p)
594 return;
595
596 #ifdef IPV6
597 if (a[RTA_IIF])
598 {
599 DBG("KRT: Ignoring route with IIF set\n");
600 return;
601 }
602 #else
603 if (i->rtm_tos != 0) /* We don't support TOS */
604 {
605 DBG("KRT: Ignoring route with TOS %02x\n", i->rtm_tos);
606 return;
607 }
608 #endif
609
610 if (scan && !new)
611 {
612 DBG("KRT: Ignoring route deletion\n");
613 return;
614 }
615
616 if (a[RTA_DST])
617 {
618 memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst));
619 ipa_ntoh(dst);
620 }
621 else
622 dst = IPA_NONE;
623 if (a[RTA_OIF])
624 memcpy(&oif, RTA_DATA(a[RTA_OIF]), sizeof(oif));
625 else
626 oif = ~0;
627
628 DBG("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);
629
630 switch (i->rtm_protocol)
631 {
632 case RTPROT_REDIRECT:
633 src = KRT_SRC_REDIRECT;
634 break;
635 case RTPROT_KERNEL:
636 DBG("Route originated in kernel, ignoring\n");
637 return;
638 case RTPROT_BIRD:
639 #ifdef IPV6
640 case RTPROT_BOOT:
641 /* Current Linux kernels don't remember rtm_protocol for IPv6 routes and supply RTPROT_BOOT instead */
642 #endif
643 if (!scan)
644 {
645 DBG("Echo of our own route, ignoring\n");
646 return;
647 }
648 src = KRT_SRC_BIRD;
649 break;
650 default:
651 src = KRT_SRC_ALIEN;
652 }
653
654 net = net_get(p->p.table, dst, i->rtm_dst_len);
655 ra.proto = &p->p;
656 ra.source = RTS_INHERIT;
657 ra.scope = SCOPE_UNIVERSE;
658 ra.cast = RTC_UNICAST;
659 ra.flags = ra.aflags = 0;
660 ra.from = IPA_NONE;
661 ra.gw = IPA_NONE;
662 ra.iface = NULL;
663 ra.eattrs = NULL;
664
665 switch (i->rtm_type)
666 {
667 case RTN_UNICAST:
668 if (oif == ~0U)
669 {
670 log(L_ERR "KRT: Mysterious route with no OIF (%I/%d)", net->n.prefix, net->n.pxlen);
671 return;
672 }
673 if (a[RTA_GATEWAY])
674 {
675 neighbor *ng;
676 ra.dest = RTD_ROUTER;
677 memcpy(&ra.gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ra.gw));
678 ipa_ntoh(ra.gw);
679 ng = neigh_find(&p->p, &ra.gw, 0);
680 if (ng && ng->scope)
681 ra.iface = ng->iface;
682 else
683 /* FIXME: Remove this warning? Handle it somehow... */
684 log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", ra.gw, net->n.prefix, net->n.pxlen);
685 }
686 else
687 {
688 ra.dest = RTD_DEVICE;
689 ra.iface = krt_temp_iface(p, oif);
690 }
691 break;
692 case RTN_BLACKHOLE:
693 ra.dest = RTD_BLACKHOLE;
694 break;
695 case RTN_UNREACHABLE:
696 ra.dest = RTD_UNREACHABLE;
697 break;
698 case RTN_PROHIBIT:
699 ra.dest = RTD_PROHIBIT;
700 break;
701 /* FIXME: What about RTN_THROW? */
702 default:
703 DBG("KRT: Ignoring route with type=%d\n", i->rtm_type);
704 return;
705 }
706
707 if (i->rtm_scope != RT_SCOPE_UNIVERSE)
708 {
709 DBG("KRT: Ignoring route with scope=%d\n", i->rtm_scope);
710 return;
711 }
712
713 e = rte_get_temp(&ra);
714 e->net = net;
715 e->u.krt.src = src;
716 e->u.krt.proto = i->rtm_protocol;
717 e->u.krt.type = i->rtm_type;
718 if (a[RTA_PRIORITY])
719 memcpy(&e->u.krt.metric, RTA_DATA(a[RTA_PRIORITY]), sizeof(e->u.krt.metric));
720 else
721 e->u.krt.metric = 0;
722 if (scan)
723 krt_got_route(p, e);
724 else
725 krt_got_route_async(p, e, new);
726 }
727
728 void
729 krt_scan_fire(struct krt_proto *p UNUSED) /* CONFIG_ALL_TABLES_AT_ONCE => p is NULL */
730 {
731 struct nlmsghdr *h;
732
733 nl_request_dump(RTM_GETROUTE);
734 while (h = nl_get_scan())
735 if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)
736 nl_parse_route(h, 1);
737 else
738 log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type);
739 }
740
741 /*
742 * Asynchronous Netlink interface
743 */
744
745 static sock *nl_async_sk; /* BIRD socket for asynchronous notifications */
746 static byte *nl_async_rx_buffer; /* Receive buffer */
747
748 static void
749 nl_async_msg(struct nlmsghdr *h)
750 {
751 switch (h->nlmsg_type)
752 {
753 case RTM_NEWROUTE:
754 case RTM_DELROUTE:
755 DBG("KRT: Received async route notification (%d)\n", h->nlmsg_type);
756 nl_parse_route(h, 0);
757 break;
758 case RTM_NEWLINK:
759 case RTM_DELLINK:
760 DBG("KRT: Received async link notification (%d)\n", h->nlmsg_type);
761 nl_parse_link(h, 0);
762 break;
763 case RTM_NEWADDR:
764 case RTM_DELADDR:
765 DBG("KRT: Received async address notification (%d)\n", h->nlmsg_type);
766 nl_parse_addr(h);
767 break;
768 default:
769 DBG("KRT: Received unknown async notification (%d)\n", h->nlmsg_type);
770 }
771 }
772
773 static int
774 nl_async_hook(sock *sk, int size UNUSED)
775 {
776 struct iovec iov = { nl_async_rx_buffer, NL_RX_SIZE };
777 struct sockaddr_nl sa;
778 struct msghdr m = { (struct sockaddr *) &sa, sizeof(sa), &iov, 1, NULL, 0, 0 };
779 struct nlmsghdr *h;
780 int x;
781 unsigned int len;
782
783 nl_last_hdr = NULL; /* Discard packets accidentally remaining in the rxbuf */
784 x = recvmsg(sk->fd, &m, 0);
785 if (x < 0)
786 {
787 if (errno == ENOBUFS)
788 {
789 /*
790 * Netlink reports some packets have been thrown away.
791 * One day we might react to it by asking for route table
792 * scan in near future.
793 */
794 return 1; /* More data are likely to be ready */
795 }
796 else if (errno != EWOULDBLOCK)
797 log(L_ERR "Netlink recvmsg: %m");
798 return 0;
799 }
800 if (sa.nl_pid) /* It isn't from the kernel */
801 {
802 DBG("Non-kernel packet\n");
803 return 1;
804 }
805 h = (void *) nl_async_rx_buffer;
806 len = x;
807 if (m.msg_flags & MSG_TRUNC)
808 {
809 log(L_WARN "Netlink got truncated asynchronous message");
810 return 1;
811 }
812 while (NLMSG_OK(h, len))
813 {
814 nl_async_msg(h);
815 h = NLMSG_NEXT(h, len);
816 }
817 if (len)
818 log(L_WARN "nl_async_hook: Found packet remnant of size %d", len);
819 return 1;
820 }
821
822 static void
823 nl_open_async(void)
824 {
825 sock *sk;
826 struct sockaddr_nl sa;
827 int fd;
828 static int nl_open_tried = 0;
829
830 if (nl_open_tried)
831 return;
832 nl_open_tried = 1;
833
834 DBG("KRT: Opening async netlink socket\n");
835
836 fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
837 if (fd < 0)
838 {
839 log(L_ERR "Unable to open asynchronous rtnetlink socket: %m");
840 return;
841 }
842
843 bzero(&sa, sizeof(sa));
844 sa.nl_family = AF_NETLINK;
845 #ifdef IPV6
846 sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE;
847 #else
848 sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
849 #endif
850 if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
851 {
852 log(L_ERR "Unable to bind asynchronous rtnetlink socket: %m");
853 return;
854 }
855
856 sk = nl_async_sk = sk_new(krt_pool);
857 sk->type = SK_MAGIC;
858 sk->rx_hook = nl_async_hook;
859 sk->fd = fd;
860 if (sk_open(sk))
861 bug("Netlink: sk_open failed");
862
863 if (!nl_async_rx_buffer)
864 nl_async_rx_buffer = xmalloc(NL_RX_SIZE);
865 }
866
867 /*
868 * Interface to the UNIX krt module
869 */
870
871 static u8 nl_cf_table[(NL_NUM_TABLES+7) / 8];
872
873 void
874 krt_scan_preconfig(struct config *c UNUSED)
875 {
876 bzero(&nl_cf_table, sizeof(nl_cf_table));
877 }
878
879 void
880 krt_scan_postconfig(struct krt_config *x)
881 {
882 int id = x->scan.table_id;
883
884 if (nl_cf_table[id/8] & (1 << (id%8)))
885 cf_error("Multiple kernel syncers defined for table #%d", id);
886 nl_cf_table[id/8] |= (1 << (id%8));
887 }
888
889 void
890 krt_scan_construct(struct krt_config *x)
891 {
892 #ifndef IPV6
893 x->scan.table_id = RT_TABLE_MAIN;
894 #else
895 x->scan.table_id = 254;
896 #endif
897 }
898
899 void
900 krt_scan_start(struct krt_proto *p, int first)
901 {
902 init_list(&p->scan.temp_ifs);
903 nl_table_map[KRT_CF->scan.table_id] = p;
904 if (first)
905 {
906 nl_open();
907 nl_open_async();
908 }
909 }
910
911 void
912 krt_scan_shutdown(struct krt_proto *p UNUSED, int last UNUSED)
913 {
914 }
915
916 void
917 krt_if_start(struct kif_proto *p UNUSED)
918 {
919 nl_open();
920 nl_open_async();
921 }