2 * BIRD -- Linux Netlink Interface
4 * (c) 1999--2000 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
12 #include <sys/socket.h>
18 #include "nest/bird.h"
19 #include "nest/route.h"
20 #include "nest/protocol.h"
21 #include "nest/iface.h"
22 #include "lib/alloca.h"
23 #include "lib/timer.h"
26 #include "lib/socket.h"
27 #include "lib/string.h"
28 #include "conf/conf.h"
30 #include <asm/types.h>
32 #include <linux/netlink.h>
33 #include <linux/rtnetlink.h>
35 #ifndef MSG_TRUNC /* Hack: Several versions of glibc miss this one :( */
36 #define MSG_TRUNC 0x20
40 #define IFF_LOWER_UP 0x10000
44 * Synchronous Netlink interface
51 byte
*rx_buffer
; /* Receive buffer */
52 struct nlmsghdr
*last_hdr
; /* Recently received packet */
53 unsigned int last_size
;
56 #define NL_RX_SIZE 8192
58 static struct nl_sock nl_scan
= {.fd
= -1}; /* Netlink socket for synchronous scan */
59 static struct nl_sock nl_req
= {.fd
= -1}; /* Netlink socket for requests */
62 nl_open_sock(struct nl_sock
*nl
)
66 nl
->fd
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_ROUTE
);
68 die("Unable to open rtnetlink socket: %m");
70 nl
->rx_buffer
= xmalloc(NL_RX_SIZE
);
79 nl_open_sock(&nl_scan
);
80 nl_open_sock(&nl_req
);
84 nl_send(struct nl_sock
*nl
, struct nlmsghdr
*nh
)
86 struct sockaddr_nl sa
;
88 memset(&sa
, 0, sizeof(sa
));
89 sa
.nl_family
= AF_NETLINK
;
91 nh
->nlmsg_seq
= ++(nl
->seq
);
92 if (sendto(nl
->fd
, nh
, nh
->nlmsg_len
, 0, (struct sockaddr
*)&sa
, sizeof(sa
)) < 0)
93 die("rtnetlink sendto: %m");
98 nl_request_dump(int cmd
)
104 req
.nh
.nlmsg_type
= cmd
;
105 req
.nh
.nlmsg_len
= sizeof(req
);
106 req
.nh
.nlmsg_flags
= NLM_F_REQUEST
| NLM_F_DUMP
;
107 /* Is it important which PF_* is used for link-level interface scan?
108 It seems that some information is available only when PF_INET is used. */
109 req
.g
.rtgen_family
= (cmd
== RTM_GETLINK
) ? PF_INET
: BIRD_PF
;
110 nl_send(&nl_scan
, &req
.nh
);
113 static struct nlmsghdr
*
114 nl_get_reply(struct nl_sock
*nl
)
120 struct iovec iov
= { nl
->rx_buffer
, NL_RX_SIZE
};
121 struct sockaddr_nl sa
;
122 struct msghdr m
= { (struct sockaddr
*) &sa
, sizeof(sa
), &iov
, 1, NULL
, 0, 0 };
123 int x
= recvmsg(nl
->fd
, &m
, 0);
125 die("nl_get_reply: %m");
126 if (sa
.nl_pid
) /* It isn't from the kernel */
128 DBG("Non-kernel packet\n");
132 nl
->last_hdr
= (void *) nl
->rx_buffer
;
133 if (m
.msg_flags
& MSG_TRUNC
)
134 bug("nl_get_reply: got truncated reply which should be impossible");
136 if (NLMSG_OK(nl
->last_hdr
, nl
->last_size
))
138 struct nlmsghdr
*h
= nl
->last_hdr
;
139 nl
->last_hdr
= NLMSG_NEXT(h
, nl
->last_size
);
140 if (h
->nlmsg_seq
!= nl
->seq
)
142 log(L_WARN
"nl_get_reply: Ignoring out of sequence netlink packet (%x != %x)",
143 h
->nlmsg_seq
, nl
->seq
);
149 log(L_WARN
"nl_get_reply: Found packet remnant of size %d", nl
->last_size
);
154 static struct rate_limit rl_netlink_err
;
157 nl_error(struct nlmsghdr
*h
)
162 if (h
->nlmsg_len
< NLMSG_LENGTH(sizeof(struct nlmsgerr
)))
164 log(L_WARN
"Netlink: Truncated error message received");
167 e
= (struct nlmsgerr
*) NLMSG_DATA(h
);
170 log_rl(&rl_netlink_err
, L_WARN
"Netlink: %s", strerror(ec
));
174 static struct nlmsghdr
*
177 struct nlmsghdr
*h
= nl_get_reply(&nl_scan
);
179 if (h
->nlmsg_type
== NLMSG_DONE
)
181 if (h
->nlmsg_type
== NLMSG_ERROR
)
190 nl_exchange(struct nlmsghdr
*pkt
)
194 nl_send(&nl_req
, pkt
);
197 h
= nl_get_reply(&nl_req
);
198 if (h
->nlmsg_type
== NLMSG_ERROR
)
200 log(L_WARN
"nl_exchange: Unexpected reply received");
202 return nl_error(h
) ? -1 : 0;
209 static int nl_attr_len
;
212 nl_checkin(struct nlmsghdr
*h
, int lsize
)
214 nl_attr_len
= h
->nlmsg_len
- NLMSG_LENGTH(lsize
);
217 log(L_ERR
"nl_checkin: underrun by %d bytes", -nl_attr_len
);
220 return NLMSG_DATA(h
);
224 nl_parse_attrs(struct rtattr
*a
, struct rtattr
**k
, int ksize
)
226 int max
= ksize
/ sizeof(struct rtattr
*);
228 while (RTA_OK(a
, nl_attr_len
))
230 if (a
->rta_type
< max
)
232 a
= RTA_NEXT(a
, nl_attr_len
);
236 log(L_ERR
"nl_parse_attrs: remnant of size %d", nl_attr_len
);
244 nl_add_attr(struct nlmsghdr
*h
, unsigned bufsize
, unsigned code
,
245 void *data
, unsigned dlen
)
247 unsigned len
= RTA_LENGTH(dlen
);
248 unsigned pos
= NLMSG_ALIGN(h
->nlmsg_len
);
251 if (pos
+ len
> bufsize
)
252 bug("nl_add_attr: packet buffer overflow");
253 a
= (struct rtattr
*)((char *)h
+ pos
);
256 h
->nlmsg_len
= pos
+ len
;
257 memcpy(RTA_DATA(a
), data
, dlen
);
261 nl_add_attr_u32(struct nlmsghdr
*h
, unsigned bufsize
, int code
, u32 data
)
263 nl_add_attr(h
, bufsize
, code
, &data
, 4);
267 nl_add_attr_ipa(struct nlmsghdr
*h
, unsigned bufsize
, int code
, ip_addr ipa
)
270 nl_add_attr(h
, bufsize
, code
, &ipa
, sizeof(ipa
));
273 #define RTNH_SIZE (sizeof(struct rtnexthop) + sizeof(struct rtattr) + sizeof(ip_addr))
276 add_mpnexthop(char *buf
, ip_addr ipa
, unsigned iface
, unsigned char weight
)
278 struct rtnexthop
*nh
= (void *) buf
;
279 struct rtattr
*rt
= (void *) (buf
+ sizeof(*nh
));
280 nh
->rtnh_len
= RTNH_SIZE
;
282 nh
->rtnh_hops
= weight
;
283 nh
->rtnh_ifindex
= iface
;
284 rt
->rta_len
= sizeof(*rt
) + sizeof(ipa
);
285 rt
->rta_type
= RTA_GATEWAY
;
287 memcpy(buf
+ sizeof(*nh
) + sizeof(*rt
), &ipa
, sizeof(ipa
));
292 nl_add_multipath(struct nlmsghdr
*h
, unsigned bufsize
, struct mpnh
*nh
)
294 unsigned len
= sizeof(struct rtattr
);
295 unsigned pos
= NLMSG_ALIGN(h
->nlmsg_len
);
296 char *buf
= (char *)h
+ pos
;
297 struct rtattr
*rt
= (void *) buf
;
300 for (; nh
; nh
= nh
->next
)
303 if (pos
+ len
> bufsize
)
304 bug("nl_add_multipath: packet buffer overflow");
306 add_mpnexthop(buf
, nh
->gw
, nh
->iface
->index
, nh
->weight
);
310 rt
->rta_type
= RTA_MULTIPATH
;
312 h
->nlmsg_len
= pos
+ len
;
317 nl_parse_multipath(struct krt_proto
*p
, struct rtattr
*ra
)
319 /* Temporary buffer for multicast nexthops */
320 static struct mpnh
*nh_buffer
;
321 static int nh_buf_size
; /* in number of structures */
322 static int nh_buf_used
;
324 struct rtattr
*a
[RTA_CACHEINFO
+1];
325 struct rtnexthop
*nh
= RTA_DATA(ra
);
326 struct mpnh
*rv
, *first
, **last
;
327 int len
= RTA_PAYLOAD(ra
);
335 /* Use RTNH_OK(nh,len) ?? */
336 if ((len
< sizeof(*nh
)) || (len
< nh
->rtnh_len
))
339 if (nh_buf_used
== nh_buf_size
)
341 nh_buf_size
= nh_buf_size
? (nh_buf_size
* 2) : 4;
342 nh_buffer
= xrealloc(nh_buffer
, nh_buf_size
* sizeof(struct mpnh
));
344 *last
= rv
= nh_buffer
+ nh_buf_used
++;
348 rv
->weight
= nh
->rtnh_hops
;
349 rv
->iface
= if_find_by_index(nh
->rtnh_ifindex
);
353 /* Nonexistent RTNH_PAYLOAD ?? */
354 nl_attr_len
= nh
->rtnh_len
- RTNH_LENGTH(0);
355 nl_parse_attrs(RTNH_DATA(nh
), a
, sizeof(a
));
358 if (RTA_PAYLOAD(a
[RTA_GATEWAY
]) != sizeof(ip_addr
))
361 memcpy(&rv
->gw
, RTA_DATA(a
[RTA_GATEWAY
]), sizeof(ip_addr
));
364 neighbor
*ng
= neigh_find2(&p
->p
, &rv
->gw
, rv
->iface
,
365 (nh
->rtnh_flags
& RTNH_F_ONLINK
) ? NEF_ONLINK
: 0);
366 if (!ng
|| (ng
->scope
== SCOPE_HOST
))
372 len
-= NLMSG_ALIGN(nh
->rtnh_len
);
381 * Scanning of interfaces
385 nl_parse_link(struct nlmsghdr
*h
, int scan
)
388 struct rtattr
*a
[IFLA_WIRELESS
+1];
389 int new = h
->nlmsg_type
== RTM_NEWLINK
;
396 if (!(i
= nl_checkin(h
, sizeof(*i
))) || !nl_parse_attrs(IFLA_RTA(i
), a
, sizeof(a
)))
398 if (!a
[IFLA_IFNAME
] || RTA_PAYLOAD(a
[IFLA_IFNAME
]) < 2 ||
399 !a
[IFLA_MTU
] || RTA_PAYLOAD(a
[IFLA_MTU
]) != 4)
401 if (scan
|| !a
[IFLA_WIRELESS
])
402 log(L_ERR
"nl_parse_link: Malformed message received");
405 name
= RTA_DATA(a
[IFLA_IFNAME
]);
406 memcpy(&mtu
, RTA_DATA(a
[IFLA_MTU
]), sizeof(u32
));
408 ifi
= if_find_by_index(i
->ifi_index
);
411 DBG("KIF: IF%d(%s) goes down\n", i
->ifi_index
, name
);
419 DBG("KIF: IF%d(%s) goes up (mtu=%d,flg=%x)\n", i
->ifi_index
, name
, mtu
, i
->ifi_flags
);
420 if (ifi
&& strncmp(ifi
->name
, name
, sizeof(ifi
->name
)-1))
423 strncpy(f
.name
, name
, sizeof(f
.name
)-1);
424 f
.index
= i
->ifi_index
;
429 f
.flags
|= IF_ADMIN_UP
;
430 if (fl
& IFF_LOWER_UP
)
431 f
.flags
|= IF_LINK_UP
;
432 if (fl
& IFF_LOOPBACK
) /* Loopback */
433 f
.flags
|= IF_MULTIACCESS
| IF_LOOPBACK
| IF_IGNORE
;
434 else if (fl
& IFF_POINTOPOINT
) /* PtP */
435 f
.flags
|= IF_MULTICAST
;
436 else if (fl
& IFF_BROADCAST
) /* Broadcast */
437 f
.flags
|= IF_MULTIACCESS
| IF_BROADCAST
| IF_MULTICAST
;
439 f
.flags
|= IF_MULTIACCESS
; /* NBMA */
445 nl_parse_addr(struct nlmsghdr
*h
)
448 struct rtattr
*a
[IFA_ANYCAST
+1];
449 int new = h
->nlmsg_type
== RTM_NEWADDR
;
454 if (!(i
= nl_checkin(h
, sizeof(*i
))) || !nl_parse_attrs(IFA_RTA(i
), a
, sizeof(a
)))
456 if (i
->ifa_family
!= BIRD_AF
)
458 if (!a
[IFA_ADDRESS
] || RTA_PAYLOAD(a
[IFA_ADDRESS
]) != sizeof(ip_addr
)
460 || a
[IFA_LOCAL
] && RTA_PAYLOAD(a
[IFA_LOCAL
]) != sizeof(ip_addr
)
462 || !a
[IFA_LOCAL
] || RTA_PAYLOAD(a
[IFA_LOCAL
]) != sizeof(ip_addr
)
463 || (a
[IFA_BROADCAST
] && RTA_PAYLOAD(a
[IFA_BROADCAST
]) != sizeof(ip_addr
))
467 log(L_ERR
"nl_parse_addr: Malformed message received");
471 ifi
= if_find_by_index(i
->ifa_index
);
474 log(L_ERR
"KIF: Received address message for unknown interface %d", i
->ifa_index
);
478 bzero(&ifa
, sizeof(ifa
));
480 if (i
->ifa_flags
& IFA_F_SECONDARY
)
481 ifa
.flags
|= IA_SECONDARY
;
483 /* IFA_LOCAL can be unset for IPv6 interfaces */
484 memcpy(&ifa
.ip
, RTA_DATA(a
[IFA_LOCAL
] ? : a
[IFA_ADDRESS
]), sizeof(ifa
.ip
));
486 ifa
.pxlen
= i
->ifa_prefixlen
;
487 if (i
->ifa_prefixlen
> BITS_PER_IP_ADDRESS
)
489 log(L_ERR
"KIF: Invalid prefix length for interface %s: %d", ifi
->name
, i
->ifa_prefixlen
);
492 if (i
->ifa_prefixlen
== BITS_PER_IP_ADDRESS
)
495 memcpy(&addr
, RTA_DATA(a
[IFA_ADDRESS
]), sizeof(addr
));
497 ifa
.prefix
= ifa
.brd
= addr
;
499 /* It is either a host address or a peer address */
500 if (ipa_equal(ifa
.ip
, addr
))
501 ifa
.flags
|= IA_HOST
;
504 ifa
.flags
|= IA_PEER
;
510 ip_addr netmask
= ipa_mkmask(ifa
.pxlen
);
511 ifa
.prefix
= ipa_and(ifa
.ip
, netmask
);
512 ifa
.brd
= ipa_or(ifa
.ip
, ipa_not(netmask
));
513 if (i
->ifa_prefixlen
== BITS_PER_IP_ADDRESS
- 1)
514 ifa
.opposite
= ipa_opposite_m1(ifa
.ip
);
517 if (i
->ifa_prefixlen
== BITS_PER_IP_ADDRESS
- 2)
518 ifa
.opposite
= ipa_opposite_m2(ifa
.ip
);
520 if ((ifi
->flags
& IF_BROADCAST
) && a
[IFA_BROADCAST
])
523 memcpy(&xbrd
, RTA_DATA(a
[IFA_BROADCAST
]), sizeof(xbrd
));
525 if (ipa_equal(xbrd
, ifa
.prefix
) || ipa_equal(xbrd
, ifa
.brd
))
527 else if (ifi
->flags
& IF_TMP_DOWN
) /* Complain only during the first scan */
528 log(L_ERR
"KIF: Invalid broadcast address %I for %s", xbrd
, ifi
->name
);
533 scope
= ipa_classify(ifa
.ip
);
536 log(L_ERR
"KIF: Invalid interface address %I for %s", ifa
.ip
, ifi
->name
);
539 ifa
.scope
= scope
& IADDR_SCOPE_MASK
;
541 DBG("KIF: IF%d(%s): %s IPA %I, flg %x, net %I/%d, brd %I, opp %I\n",
542 ifi
->index
, ifi
->name
,
543 new ? "added" : "removed",
544 ifa
.ip
, ifa
.flags
, ifa
.prefix
, ifa
.pxlen
, ifa
.brd
, ifa
.opposite
);
552 kif_do_scan(struct kif_proto
*p UNUSED
)
558 nl_request_dump(RTM_GETLINK
);
559 while (h
= nl_get_scan())
560 if (h
->nlmsg_type
== RTM_NEWLINK
|| h
->nlmsg_type
== RTM_DELLINK
)
563 log(L_DEBUG
"nl_scan_ifaces: Unknown packet received (type=%d)", h
->nlmsg_type
);
565 nl_request_dump(RTM_GETADDR
);
566 while (h
= nl_get_scan())
567 if (h
->nlmsg_type
== RTM_NEWADDR
|| h
->nlmsg_type
== RTM_DELADDR
)
570 log(L_DEBUG
"nl_scan_ifaces: Unknown packet received (type=%d)", h
->nlmsg_type
);
579 static struct krt_proto
*nl_table_map
[NL_NUM_TABLES
];
586 if (a
->cast
!= RTC_UNICAST
)
593 if (a
->iface
== NULL
)
596 case RTD_UNREACHABLE
:
607 nh_bufsize(struct mpnh
*nh
)
610 for (; nh
!= NULL
; nh
= nh
->next
)
616 nl_send_route(struct krt_proto
*p
, rte
*e
, struct ea_list
*eattrs
, int new)
624 char buf
[128 + nh_bufsize(a
->nexthops
)];
627 DBG("nl_send_route(%I/%d,new=%d)\n", net
->n
.prefix
, net
->n
.pxlen
, new);
629 bzero(&r
.h
, sizeof(r
.h
));
630 bzero(&r
.r
, sizeof(r
.r
));
631 r
.h
.nlmsg_type
= new ? RTM_NEWROUTE
: RTM_DELROUTE
;
632 r
.h
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct rtmsg
));
633 r
.h
.nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
| (new ? NLM_F_CREATE
|NLM_F_EXCL
: 0);
635 r
.r
.rtm_family
= BIRD_AF
;
636 r
.r
.rtm_dst_len
= net
->n
.pxlen
;
638 r
.r
.rtm_table
= KRT_CF
->sys
.table_id
;
639 r
.r
.rtm_protocol
= RTPROT_BIRD
;
640 r
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
641 nl_add_attr_ipa(&r
.h
, sizeof(r
), RTA_DST
, net
->n
.prefix
);
644 if (new && e
->attrs
->source
== RTS_INHERIT
)
645 metric
= e
->u
.krt
.metric
;
646 if (ea
= ea_find(eattrs
, EA_KRT_METRIC
))
649 nl_add_attr_u32(&r
.h
, sizeof(r
), RTA_PRIORITY
, metric
);
651 if (ea
= ea_find(eattrs
, EA_KRT_PREFSRC
))
652 nl_add_attr_ipa(&r
.h
, sizeof(r
), RTA_PREFSRC
, *(ip_addr
*)ea
->u
.ptr
->data
);
654 if (ea
= ea_find(eattrs
, EA_KRT_REALM
))
655 nl_add_attr_u32(&r
.h
, sizeof(r
), RTA_FLOW
, ea
->u
.data
);
657 /* a->iface != NULL checked in krt_capable() for router and device routes */
662 r
.r
.rtm_type
= RTN_UNICAST
;
663 nl_add_attr_u32(&r
.h
, sizeof(r
), RTA_OIF
, a
->iface
->index
);
664 nl_add_attr_ipa(&r
.h
, sizeof(r
), RTA_GATEWAY
, a
->gw
);
667 r
.r
.rtm_type
= RTN_UNICAST
;
668 nl_add_attr_u32(&r
.h
, sizeof(r
), RTA_OIF
, a
->iface
->index
);
671 r
.r
.rtm_type
= RTN_BLACKHOLE
;
673 case RTD_UNREACHABLE
:
674 r
.r
.rtm_type
= RTN_UNREACHABLE
;
677 r
.r
.rtm_type
= RTN_PROHIBIT
;
680 r
.r
.rtm_type
= RTN_UNICAST
;
681 nl_add_multipath(&r
.h
, sizeof(r
), a
->nexthops
);
684 bug("krt_capable inconsistent with nl_send_route");
687 return nl_exchange(&r
.h
);
691 krt_replace_rte(struct krt_proto
*p
, net
*n
, rte
*new, rte
*old
, struct ea_list
*eattrs
)
696 * NULL for eattr of the old route is a little hack, but we don't
697 * get proper eattrs for old in rt_notify() anyway. NULL means no
698 * extended route attributes and therefore matches if the kernel
699 * route has any of them.
703 nl_send_route(p
, old
, NULL
, 0);
706 err
= nl_send_route(p
, new, eattrs
, 1);
709 n
->n
.flags
|= KRF_SYNC_ERROR
;
711 n
->n
.flags
&= ~KRF_SYNC_ERROR
;
715 #define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
718 nl_parse_route(struct nlmsghdr
*h
, int scan
)
722 struct rtattr
*a
[RTA_CACHEINFO
+1];
723 int new = h
->nlmsg_type
== RTM_NEWROUTE
;
725 ip_addr dst
= IPA_NONE
;
729 if (!(i
= nl_checkin(h
, sizeof(*i
))) || !nl_parse_attrs(RTM_RTA(i
), a
, sizeof(a
)))
731 if (i
->rtm_family
!= BIRD_AF
)
733 if ((a
[RTA_DST
] && RTA_PAYLOAD(a
[RTA_DST
]) != sizeof(ip_addr
)) ||
735 (a
[RTA_IIF
] && RTA_PAYLOAD(a
[RTA_IIF
]) != 4) ||
737 (a
[RTA_OIF
] && RTA_PAYLOAD(a
[RTA_OIF
]) != 4) ||
738 (a
[RTA_GATEWAY
] && RTA_PAYLOAD(a
[RTA_GATEWAY
]) != sizeof(ip_addr
)) ||
739 (a
[RTA_PRIORITY
] && RTA_PAYLOAD(a
[RTA_PRIORITY
]) != 4) ||
740 (a
[RTA_PREFSRC
] && RTA_PAYLOAD(a
[RTA_PREFSRC
]) != sizeof(ip_addr
)) ||
741 (a
[RTA_FLOW
] && RTA_PAYLOAD(a
[RTA_FLOW
]) != 4))
743 log(L_ERR
"KRT: Malformed message received");
749 memcpy(&dst
, RTA_DATA(a
[RTA_DST
]), sizeof(dst
));
754 memcpy(&oif
, RTA_DATA(a
[RTA_OIF
]), sizeof(oif
));
756 p
= nl_table_map
[i
->rtm_table
]; /* Do we know this table? */
757 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
->p
.name
: "(none)");
759 SKIP("unknown table %d\n", i
->rtm_table
);
766 if (i
->rtm_tos
!= 0) /* We don't support TOS */
767 SKIP("TOS %02x\n", i
->rtm_tos
);
771 SKIP("RTM_DELROUTE in scan\n");
773 int c
= ipa_classify_net(dst
);
774 if ((c
< 0) || !(c
& IADDR_HOST
) || ((c
& IADDR_SCOPE_MASK
) <= SCOPE_LINK
))
775 SKIP("strange class/scope\n");
777 // ignore rtm_scope, it is not a real scope
778 // if (i->rtm_scope != RT_SCOPE_UNIVERSE)
779 // SKIP("scope %u\n", i->rtm_scope);
781 switch (i
->rtm_protocol
)
784 SKIP("proto unspec\n");
786 case RTPROT_REDIRECT
:
787 src
= KRT_SRC_REDIRECT
;
791 src
= KRT_SRC_KERNEL
;
805 net
*net
= net_get(p
->p
.table
, dst
, i
->rtm_dst_len
);
808 .src
= p
->p
.main_source
,
809 .source
= RTS_INHERIT
,
810 .scope
= SCOPE_UNIVERSE
,
818 if (a
[RTA_MULTIPATH
])
820 ra
.dest
= RTD_MULTIPATH
;
821 ra
.nexthops
= nl_parse_multipath(p
, a
[RTA_MULTIPATH
]);
824 log(L_ERR
"KRT: Received strange multipath route %I/%d",
825 net
->n
.prefix
, net
->n
.pxlen
);
832 ra
.iface
= if_find_by_index(oif
);
835 log(L_ERR
"KRT: Received route %I/%d with unknown ifindex %u",
836 net
->n
.prefix
, net
->n
.pxlen
, oif
);
843 ra
.dest
= RTD_ROUTER
;
844 memcpy(&ra
.gw
, RTA_DATA(a
[RTA_GATEWAY
]), sizeof(ra
.gw
));
848 /* Silently skip strange 6to4 routes */
849 if (ipa_in_net(ra
.gw
, IPA_NONE
, 96))
853 ng
= neigh_find2(&p
->p
, &ra
.gw
, ra
.iface
,
854 (i
->rtm_flags
& RTNH_F_ONLINK
) ? NEF_ONLINK
: 0);
855 if (!ng
|| (ng
->scope
== SCOPE_HOST
))
857 log(L_ERR
"KRT: Received route %I/%d with strange next-hop %I",
858 net
->n
.prefix
, net
->n
.pxlen
, ra
.gw
);
864 ra
.dest
= RTD_DEVICE
;
869 ra
.dest
= RTD_BLACKHOLE
;
871 case RTN_UNREACHABLE
:
872 ra
.dest
= RTD_UNREACHABLE
;
875 ra
.dest
= RTD_PROHIBIT
;
877 /* FIXME: What about RTN_THROW? */
879 SKIP("type %d\n", i
->rtm_type
);
883 rte
*e
= rte_get_temp(&ra
);
886 e
->u
.krt
.proto
= i
->rtm_protocol
;
887 e
->u
.krt
.type
= i
->rtm_type
;
890 memcpy(&e
->u
.krt
.metric
, RTA_DATA(a
[RTA_PRIORITY
]), sizeof(e
->u
.krt
.metric
));
897 memcpy(&ps
, RTA_DATA(a
[RTA_PREFSRC
]), sizeof(ps
));
900 ea_list
*ea
= alloca(sizeof(ea_list
) + sizeof(eattr
));
901 ea
->next
= ra
.eattrs
;
903 ea
->flags
= EALF_SORTED
;
905 ea
->attrs
[0].id
= EA_KRT_PREFSRC
;
906 ea
->attrs
[0].flags
= 0;
907 ea
->attrs
[0].type
= EAF_TYPE_IP_ADDRESS
;
908 ea
->attrs
[0].u
.ptr
= alloca(sizeof(struct adata
) + sizeof(ps
));
909 ea
->attrs
[0].u
.ptr
->length
= sizeof(ps
);
910 memcpy(ea
->attrs
[0].u
.ptr
->data
, &ps
, sizeof(ps
));
915 ea_list
*ea
= alloca(sizeof(ea_list
) + sizeof(eattr
));
916 ea
->next
= ra
.eattrs
;
918 ea
->flags
= EALF_SORTED
;
920 ea
->attrs
[0].id
= EA_KRT_REALM
;
921 ea
->attrs
[0].flags
= 0;
922 ea
->attrs
[0].type
= EAF_TYPE_INT
;
923 memcpy(&ea
->attrs
[0].u
.data
, RTA_DATA(a
[RTA_FLOW
]), 4);
929 krt_got_route_async(p
, e
, new);
933 krt_do_scan(struct krt_proto
*p UNUSED
) /* CONFIG_ALL_TABLES_AT_ONCE => p is NULL */
937 nl_request_dump(RTM_GETROUTE
);
938 while (h
= nl_get_scan())
939 if (h
->nlmsg_type
== RTM_NEWROUTE
|| h
->nlmsg_type
== RTM_DELROUTE
)
940 nl_parse_route(h
, 1);
942 log(L_DEBUG
"nl_scan_fire: Unknown packet received (type=%d)", h
->nlmsg_type
);
946 * Asynchronous Netlink interface
949 static sock
*nl_async_sk
; /* BIRD socket for asynchronous notifications */
950 static byte
*nl_async_rx_buffer
; /* Receive buffer */
953 nl_async_msg(struct nlmsghdr
*h
)
955 switch (h
->nlmsg_type
)
959 DBG("KRT: Received async route notification (%d)\n", h
->nlmsg_type
);
960 nl_parse_route(h
, 0);
964 DBG("KRT: Received async link notification (%d)\n", h
->nlmsg_type
);
969 DBG("KRT: Received async address notification (%d)\n", h
->nlmsg_type
);
973 DBG("KRT: Received unknown async notification (%d)\n", h
->nlmsg_type
);
978 nl_async_hook(sock
*sk
, int size UNUSED
)
980 struct iovec iov
= { nl_async_rx_buffer
, NL_RX_SIZE
};
981 struct sockaddr_nl sa
;
982 struct msghdr m
= { (struct sockaddr
*) &sa
, sizeof(sa
), &iov
, 1, NULL
, 0, 0 };
987 x
= recvmsg(sk
->fd
, &m
, 0);
990 if (errno
== ENOBUFS
)
993 * Netlink reports some packets have been thrown away.
994 * One day we might react to it by asking for route table
995 * scan in near future.
997 return 1; /* More data are likely to be ready */
999 else if (errno
!= EWOULDBLOCK
)
1000 log(L_ERR
"Netlink recvmsg: %m");
1003 if (sa
.nl_pid
) /* It isn't from the kernel */
1005 DBG("Non-kernel packet\n");
1008 h
= (void *) nl_async_rx_buffer
;
1010 if (m
.msg_flags
& MSG_TRUNC
)
1012 log(L_WARN
"Netlink got truncated asynchronous message");
1015 while (NLMSG_OK(h
, len
))
1018 h
= NLMSG_NEXT(h
, len
);
1021 log(L_WARN
"nl_async_hook: Found packet remnant of size %d", len
);
1029 struct sockaddr_nl sa
;
1035 DBG("KRT: Opening async netlink socket\n");
1037 fd
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_ROUTE
);
1040 log(L_ERR
"Unable to open asynchronous rtnetlink socket: %m");
1044 bzero(&sa
, sizeof(sa
));
1045 sa
.nl_family
= AF_NETLINK
;
1047 sa
.nl_groups
= RTMGRP_LINK
| RTMGRP_IPV6_IFADDR
| RTMGRP_IPV6_ROUTE
;
1049 sa
.nl_groups
= RTMGRP_LINK
| RTMGRP_IPV4_IFADDR
| RTMGRP_IPV4_ROUTE
;
1051 if (bind(fd
, (struct sockaddr
*) &sa
, sizeof(sa
)) < 0)
1053 log(L_ERR
"Unable to bind asynchronous rtnetlink socket: %m");
1058 nl_async_rx_buffer
= xmalloc(NL_RX_SIZE
);
1060 sk
= nl_async_sk
= sk_new(krt_pool
);
1061 sk
->type
= SK_MAGIC
;
1062 sk
->rx_hook
= nl_async_hook
;
1065 bug("Netlink: sk_open failed");
1069 * Interface to the UNIX krt module
1072 static u8 nl_cf_table
[(NL_NUM_TABLES
+7) / 8];
1075 krt_sys_start(struct krt_proto
*p
)
1077 nl_table_map
[KRT_CF
->sys
.table_id
] = p
;
1084 krt_sys_shutdown(struct krt_proto
*p UNUSED
)
1086 nl_table_map
[KRT_CF
->sys
.table_id
] = NULL
;
1090 krt_sys_reconfigure(struct krt_proto
*p UNUSED
, struct krt_config
*n
, struct krt_config
*o
)
1092 return n
->sys
.table_id
== o
->sys
.table_id
;
1097 krt_sys_preconfig(struct config
*c UNUSED
)
1099 bzero(&nl_cf_table
, sizeof(nl_cf_table
));
1103 krt_sys_postconfig(struct krt_config
*x
)
1105 int id
= x
->sys
.table_id
;
1107 if (nl_cf_table
[id
/8] & (1 << (id
%8)))
1108 cf_error("Multiple kernel syncers defined for table #%d", id
);
1109 nl_cf_table
[id
/8] |= (1 << (id
%8));
1113 krt_sys_init_config(struct krt_config
*cf
)
1115 cf
->sys
.table_id
= RT_TABLE_MAIN
;
1119 krt_sys_copy_config(struct krt_config
*d
, struct krt_config
*s
)
1121 d
->sys
.table_id
= s
->sys
.table_id
;
1127 kif_sys_start(struct kif_proto
*p UNUSED
)
1134 kif_sys_shutdown(struct kif_proto
*p UNUSED
)