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.
11 #include <sys/socket.h>
17 #include "nest/bird.h"
18 #include "nest/route.h"
19 #include "nest/protocol.h"
20 #include "nest/iface.h"
21 #include "lib/alloca.h"
22 #include "lib/timer.h"
25 #include "lib/socket.h"
26 #include "lib/string.h"
27 #include "conf/conf.h"
29 #include <asm/types.h>
31 #include <linux/netlink.h>
32 #include <linux/rtnetlink.h>
34 #ifndef MSG_TRUNC /* Hack: Several versions of glibc miss this one :( */
35 #define MSG_TRUNC 0x20
39 #define IFF_LOWER_UP 0x10000
43 * Synchronous Netlink interface
50 byte
*rx_buffer
; /* Receive buffer */
51 struct nlmsghdr
*last_hdr
; /* Recently received packet */
52 unsigned int last_size
;
55 #define NL_RX_SIZE 8192
57 static struct nl_sock nl_scan
= {.fd
= -1}; /* Netlink socket for synchronous scan */
58 static struct nl_sock nl_req
= {.fd
= -1}; /* Netlink socket for requests */
61 nl_open_sock(struct nl_sock
*nl
)
65 nl
->fd
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_ROUTE
);
67 die("Unable to open rtnetlink socket: %m");
69 nl
->rx_buffer
= xmalloc(NL_RX_SIZE
);
78 nl_open_sock(&nl_scan
);
79 nl_open_sock(&nl_req
);
83 nl_send(struct nl_sock
*nl
, struct nlmsghdr
*nh
)
85 struct sockaddr_nl sa
;
87 memset(&sa
, 0, sizeof(sa
));
88 sa
.nl_family
= AF_NETLINK
;
90 nh
->nlmsg_seq
= ++(nl
->seq
);
91 if (sendto(nl
->fd
, nh
, nh
->nlmsg_len
, 0, (struct sockaddr
*)&sa
, sizeof(sa
)) < 0)
92 die("rtnetlink sendto: %m");
97 nl_request_dump(int cmd
)
103 req
.nh
.nlmsg_type
= cmd
;
104 req
.nh
.nlmsg_len
= sizeof(req
);
105 req
.nh
.nlmsg_flags
= NLM_F_REQUEST
| NLM_F_DUMP
;
106 /* Is it important which PF_* is used for link-level interface scan?
107 It seems that some information is available only when PF_INET is used. */
108 req
.g
.rtgen_family
= (cmd
== RTM_GETLINK
) ? PF_INET
: BIRD_PF
;
109 nl_send(&nl_scan
, &req
.nh
);
112 static struct nlmsghdr
*
113 nl_get_reply(struct nl_sock
*nl
)
119 struct iovec iov
= { nl
->rx_buffer
, NL_RX_SIZE
};
120 struct sockaddr_nl sa
;
121 struct msghdr m
= { (struct sockaddr
*) &sa
, sizeof(sa
), &iov
, 1, NULL
, 0, 0 };
122 int x
= recvmsg(nl
->fd
, &m
, 0);
124 die("nl_get_reply: %m");
125 if (sa
.nl_pid
) /* It isn't from the kernel */
127 DBG("Non-kernel packet\n");
131 nl
->last_hdr
= (void *) nl
->rx_buffer
;
132 if (m
.msg_flags
& MSG_TRUNC
)
133 bug("nl_get_reply: got truncated reply which should be impossible");
135 if (NLMSG_OK(nl
->last_hdr
, nl
->last_size
))
137 struct nlmsghdr
*h
= nl
->last_hdr
;
138 nl
->last_hdr
= NLMSG_NEXT(h
, nl
->last_size
);
139 if (h
->nlmsg_seq
!= nl
->seq
)
141 log(L_WARN
"nl_get_reply: Ignoring out of sequence netlink packet (%x != %x)",
142 h
->nlmsg_seq
, nl
->seq
);
148 log(L_WARN
"nl_get_reply: Found packet remnant of size %d", nl
->last_size
);
153 static struct rate_limit rl_netlink_err
;
156 nl_error(struct nlmsghdr
*h
)
161 if (h
->nlmsg_len
< NLMSG_LENGTH(sizeof(struct nlmsgerr
)))
163 log(L_WARN
"Netlink: Truncated error message received");
166 e
= (struct nlmsgerr
*) NLMSG_DATA(h
);
169 log_rl(&rl_netlink_err
, L_WARN
"Netlink: %s", strerror(ec
));
173 static struct nlmsghdr
*
176 struct nlmsghdr
*h
= nl_get_reply(&nl_scan
);
178 if (h
->nlmsg_type
== NLMSG_DONE
)
180 if (h
->nlmsg_type
== NLMSG_ERROR
)
189 nl_exchange(struct nlmsghdr
*pkt
)
193 nl_send(&nl_req
, pkt
);
196 h
= nl_get_reply(&nl_req
);
197 if (h
->nlmsg_type
== NLMSG_ERROR
)
199 log(L_WARN
"nl_exchange: Unexpected reply received");
201 return nl_error(h
) ? -1 : 0;
208 static int nl_attr_len
;
211 nl_checkin(struct nlmsghdr
*h
, int lsize
)
213 nl_attr_len
= h
->nlmsg_len
- NLMSG_LENGTH(lsize
);
216 log(L_ERR
"nl_checkin: underrun by %d bytes", -nl_attr_len
);
219 return NLMSG_DATA(h
);
223 nl_parse_attrs(struct rtattr
*a
, struct rtattr
**k
, int ksize
)
225 int max
= ksize
/ sizeof(struct rtattr
*);
227 while (RTA_OK(a
, nl_attr_len
))
229 if (a
->rta_type
< max
)
231 a
= RTA_NEXT(a
, nl_attr_len
);
235 log(L_ERR
"nl_parse_attrs: remnant of size %d", nl_attr_len
);
243 nl_add_attr(struct nlmsghdr
*h
, unsigned bufsize
, unsigned code
,
244 void *data
, unsigned dlen
)
246 unsigned len
= RTA_LENGTH(dlen
);
247 unsigned pos
= NLMSG_ALIGN(h
->nlmsg_len
);
250 if (pos
+ len
> bufsize
)
251 bug("nl_add_attr: packet buffer overflow");
252 a
= (struct rtattr
*)((char *)h
+ pos
);
255 h
->nlmsg_len
= pos
+ len
;
256 memcpy(RTA_DATA(a
), data
, dlen
);
260 nl_add_attr_u32(struct nlmsghdr
*h
, unsigned bufsize
, int code
, u32 data
)
262 nl_add_attr(h
, bufsize
, code
, &data
, 4);
266 nl_add_attr_ipa(struct nlmsghdr
*h
, unsigned bufsize
, int code
, ip_addr ipa
)
269 nl_add_attr(h
, bufsize
, code
, &ipa
, sizeof(ipa
));
272 #define RTNH_SIZE (sizeof(struct rtnexthop) + sizeof(struct rtattr) + sizeof(ip_addr))
275 add_mpnexthop(char *buf
, ip_addr ipa
, unsigned iface
, unsigned char weight
)
277 struct rtnexthop
*nh
= (void *) buf
;
278 struct rtattr
*rt
= (void *) (buf
+ sizeof(*nh
));
279 nh
->rtnh_len
= RTNH_SIZE
;
281 nh
->rtnh_hops
= weight
;
282 nh
->rtnh_ifindex
= iface
;
283 rt
->rta_len
= sizeof(*rt
) + sizeof(ipa
);
284 rt
->rta_type
= RTA_GATEWAY
;
286 memcpy(buf
+ sizeof(*nh
) + sizeof(*rt
), &ipa
, sizeof(ipa
));
291 nl_add_multipath(struct nlmsghdr
*h
, unsigned bufsize
, struct mpnh
*nh
)
293 unsigned len
= sizeof(struct rtattr
);
294 unsigned pos
= NLMSG_ALIGN(h
->nlmsg_len
);
295 char *buf
= (char *)h
+ pos
;
296 struct rtattr
*rt
= (void *) buf
;
299 for (; nh
; nh
= nh
->next
)
302 if (pos
+ len
> bufsize
)
303 bug("nl_add_multipath: packet buffer overflow");
305 add_mpnexthop(buf
, nh
->gw
, nh
->iface
->index
, nh
->weight
);
309 rt
->rta_type
= RTA_MULTIPATH
;
311 h
->nlmsg_len
= pos
+ len
;
316 nl_parse_multipath(struct krt_proto
*p
, struct rtattr
*ra
)
318 /* Temporary buffer for multicast nexthops */
319 static struct mpnh
*nh_buffer
;
320 static int nh_buf_size
; /* in number of structures */
321 static int nh_buf_used
;
323 struct rtattr
*a
[RTA_CACHEINFO
+1];
324 struct rtnexthop
*nh
= RTA_DATA(ra
);
325 struct mpnh
*rv
, *first
, **last
;
326 int len
= RTA_PAYLOAD(ra
);
334 /* Use RTNH_OK(nh,len) ?? */
335 if ((len
< sizeof(*nh
)) || (len
< nh
->rtnh_len
))
338 if (nh_buf_used
== nh_buf_size
)
340 nh_buf_size
= nh_buf_size
? (nh_buf_size
* 2) : 4;
341 nh_buffer
= xrealloc(nh_buffer
, nh_buf_size
* sizeof(struct mpnh
));
343 *last
= rv
= nh_buffer
+ nh_buf_used
++;
347 rv
->weight
= nh
->rtnh_hops
;
348 rv
->iface
= if_find_by_index(nh
->rtnh_ifindex
);
352 /* Nonexistent RTNH_PAYLOAD ?? */
353 nl_attr_len
= nh
->rtnh_len
- RTNH_LENGTH(0);
354 nl_parse_attrs(RTNH_DATA(nh
), a
, sizeof(a
));
357 if (RTA_PAYLOAD(a
[RTA_GATEWAY
]) != sizeof(ip_addr
))
360 memcpy(&rv
->gw
, RTA_DATA(a
[RTA_GATEWAY
]), sizeof(ip_addr
));
363 neighbor
*ng
= neigh_find2(&p
->p
, &rv
->gw
, rv
->iface
,
364 (nh
->rtnh_flags
& RTNH_F_ONLINK
) ? NEF_ONLINK
: 0);
365 if (!ng
|| (ng
->scope
== SCOPE_HOST
))
371 len
-= NLMSG_ALIGN(nh
->rtnh_len
);
380 * Scanning of interfaces
384 nl_parse_link(struct nlmsghdr
*h
, int scan
)
387 struct rtattr
*a
[IFLA_WIRELESS
+1];
388 int new = h
->nlmsg_type
== RTM_NEWLINK
;
395 if (!(i
= nl_checkin(h
, sizeof(*i
))) || !nl_parse_attrs(IFLA_RTA(i
), a
, sizeof(a
)))
397 if (!a
[IFLA_IFNAME
] || RTA_PAYLOAD(a
[IFLA_IFNAME
]) < 2 ||
398 !a
[IFLA_MTU
] || RTA_PAYLOAD(a
[IFLA_MTU
]) != 4)
400 if (scan
|| !a
[IFLA_WIRELESS
])
401 log(L_ERR
"nl_parse_link: Malformed message received");
404 name
= RTA_DATA(a
[IFLA_IFNAME
]);
405 memcpy(&mtu
, RTA_DATA(a
[IFLA_MTU
]), sizeof(u32
));
407 ifi
= if_find_by_index(i
->ifi_index
);
410 DBG("KIF: IF%d(%s) goes down\n", i
->ifi_index
, name
);
418 DBG("KIF: IF%d(%s) goes up (mtu=%d,flg=%x)\n", i
->ifi_index
, name
, mtu
, i
->ifi_flags
);
419 if (ifi
&& strncmp(ifi
->name
, name
, sizeof(ifi
->name
)-1))
422 strncpy(f
.name
, name
, sizeof(f
.name
)-1);
423 f
.index
= i
->ifi_index
;
428 f
.flags
|= IF_ADMIN_UP
;
429 if (fl
& IFF_LOWER_UP
)
430 f
.flags
|= IF_LINK_UP
;
431 if (fl
& IFF_LOOPBACK
) /* Loopback */
432 f
.flags
|= IF_MULTIACCESS
| IF_LOOPBACK
| IF_IGNORE
;
433 else if (fl
& IFF_POINTOPOINT
) /* PtP */
434 f
.flags
|= IF_MULTICAST
;
435 else if (fl
& IFF_BROADCAST
) /* Broadcast */
436 f
.flags
|= IF_MULTIACCESS
| IF_BROADCAST
| IF_MULTICAST
;
438 f
.flags
|= IF_MULTIACCESS
; /* NBMA */
444 nl_parse_addr(struct nlmsghdr
*h
)
447 struct rtattr
*a
[IFA_ANYCAST
+1];
448 int new = h
->nlmsg_type
== RTM_NEWADDR
;
453 if (!(i
= nl_checkin(h
, sizeof(*i
))) || !nl_parse_attrs(IFA_RTA(i
), a
, sizeof(a
)))
455 if (i
->ifa_family
!= BIRD_AF
)
457 if (!a
[IFA_ADDRESS
] || RTA_PAYLOAD(a
[IFA_ADDRESS
]) != sizeof(ip_addr
)
459 || a
[IFA_LOCAL
] && RTA_PAYLOAD(a
[IFA_LOCAL
]) != sizeof(ip_addr
)
461 || !a
[IFA_LOCAL
] || RTA_PAYLOAD(a
[IFA_LOCAL
]) != sizeof(ip_addr
)
462 || (a
[IFA_BROADCAST
] && RTA_PAYLOAD(a
[IFA_BROADCAST
]) != sizeof(ip_addr
))
466 log(L_ERR
"nl_parse_addr: Malformed message received");
470 ifi
= if_find_by_index(i
->ifa_index
);
473 log(L_ERR
"KIF: Received address message for unknown interface %d", i
->ifa_index
);
477 bzero(&ifa
, sizeof(ifa
));
479 if (i
->ifa_flags
& IFA_F_SECONDARY
)
480 ifa
.flags
|= IA_SECONDARY
;
482 /* IFA_LOCAL can be unset for IPv6 interfaces */
483 memcpy(&ifa
.ip
, RTA_DATA(a
[IFA_LOCAL
] ? : a
[IFA_ADDRESS
]), sizeof(ifa
.ip
));
485 ifa
.pxlen
= i
->ifa_prefixlen
;
486 if (i
->ifa_prefixlen
> BITS_PER_IP_ADDRESS
)
488 log(L_ERR
"KIF: Invalid prefix length for interface %s: %d", ifi
->name
, i
->ifa_prefixlen
);
491 if (i
->ifa_prefixlen
== BITS_PER_IP_ADDRESS
)
494 memcpy(&addr
, RTA_DATA(a
[IFA_ADDRESS
]), sizeof(addr
));
496 ifa
.prefix
= ifa
.brd
= addr
;
498 /* It is either a host address or a peer address */
499 if (ipa_equal(ifa
.ip
, addr
))
500 ifa
.flags
|= IA_HOST
;
503 ifa
.flags
|= IA_PEER
;
509 ip_addr netmask
= ipa_mkmask(ifa
.pxlen
);
510 ifa
.prefix
= ipa_and(ifa
.ip
, netmask
);
511 ifa
.brd
= ipa_or(ifa
.ip
, ipa_not(netmask
));
512 if (i
->ifa_prefixlen
== BITS_PER_IP_ADDRESS
- 1)
513 ifa
.opposite
= ipa_opposite_m1(ifa
.ip
);
516 if (i
->ifa_prefixlen
== BITS_PER_IP_ADDRESS
- 2)
517 ifa
.opposite
= ipa_opposite_m2(ifa
.ip
);
519 if ((ifi
->flags
& IF_BROADCAST
) && a
[IFA_BROADCAST
])
522 memcpy(&xbrd
, RTA_DATA(a
[IFA_BROADCAST
]), sizeof(xbrd
));
524 if (ipa_equal(xbrd
, ifa
.prefix
) || ipa_equal(xbrd
, ifa
.brd
))
526 else if (ifi
->flags
& IF_TMP_DOWN
) /* Complain only during the first scan */
527 log(L_ERR
"KIF: Invalid broadcast address %I for %s", xbrd
, ifi
->name
);
532 scope
= ipa_classify(ifa
.ip
);
535 log(L_ERR
"KIF: Invalid interface address %I for %s", ifa
.ip
, ifi
->name
);
538 ifa
.scope
= scope
& IADDR_SCOPE_MASK
;
540 DBG("KIF: IF%d(%s): %s IPA %I, flg %x, net %I/%d, brd %I, opp %I\n",
541 ifi
->index
, ifi
->name
,
542 new ? "added" : "removed",
543 ifa
.ip
, ifa
.flags
, ifa
.prefix
, ifa
.pxlen
, ifa
.brd
, ifa
.opposite
);
551 kif_do_scan(struct kif_proto
*p UNUSED
)
557 nl_request_dump(RTM_GETLINK
);
558 while (h
= nl_get_scan())
559 if (h
->nlmsg_type
== RTM_NEWLINK
|| h
->nlmsg_type
== RTM_DELLINK
)
562 log(L_DEBUG
"nl_scan_ifaces: Unknown packet received (type=%d)", h
->nlmsg_type
);
564 nl_request_dump(RTM_GETADDR
);
565 while (h
= nl_get_scan())
566 if (h
->nlmsg_type
== RTM_NEWADDR
|| h
->nlmsg_type
== RTM_DELADDR
)
569 log(L_DEBUG
"nl_scan_ifaces: Unknown packet received (type=%d)", h
->nlmsg_type
);
578 static struct krt_proto
*nl_table_map
[NL_NUM_TABLES
];
585 if (a
->cast
!= RTC_UNICAST
)
592 if (a
->iface
== NULL
)
595 case RTD_UNREACHABLE
:
606 nh_bufsize(struct mpnh
*nh
)
609 for (; nh
!= NULL
; nh
= nh
->next
)
615 nl_send_route(struct krt_proto
*p
, rte
*e
, struct ea_list
*eattrs
, int new)
623 char buf
[128 + nh_bufsize(a
->nexthops
)];
626 DBG("nl_send_route(%I/%d,new=%d)\n", net
->n
.prefix
, net
->n
.pxlen
, new);
628 bzero(&r
.h
, sizeof(r
.h
));
629 bzero(&r
.r
, sizeof(r
.r
));
630 r
.h
.nlmsg_type
= new ? RTM_NEWROUTE
: RTM_DELROUTE
;
631 r
.h
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct rtmsg
));
632 r
.h
.nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
| (new ? NLM_F_CREATE
|NLM_F_EXCL
: 0);
634 r
.r
.rtm_family
= BIRD_AF
;
635 r
.r
.rtm_dst_len
= net
->n
.pxlen
;
637 r
.r
.rtm_table
= KRT_CF
->sys
.table_id
;
638 r
.r
.rtm_protocol
= RTPROT_BIRD
;
639 r
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
640 nl_add_attr_ipa(&r
.h
, sizeof(r
), RTA_DST
, net
->n
.prefix
);
643 if (new && e
->attrs
->source
== RTS_INHERIT
)
644 metric
= e
->u
.krt
.metric
;
645 if (ea
= ea_find(eattrs
, EA_KRT_METRIC
))
648 nl_add_attr_u32(&r
.h
, sizeof(r
), RTA_PRIORITY
, metric
);
650 if (ea
= ea_find(eattrs
, EA_KRT_PREFSRC
))
651 nl_add_attr_ipa(&r
.h
, sizeof(r
), RTA_PREFSRC
, *(ip_addr
*)ea
->u
.ptr
->data
);
653 if (ea
= ea_find(eattrs
, EA_KRT_REALM
))
654 nl_add_attr_u32(&r
.h
, sizeof(r
), RTA_FLOW
, ea
->u
.data
);
656 /* a->iface != NULL checked in krt_capable() for router and device routes */
661 r
.r
.rtm_type
= RTN_UNICAST
;
662 nl_add_attr_u32(&r
.h
, sizeof(r
), RTA_OIF
, a
->iface
->index
);
663 nl_add_attr_ipa(&r
.h
, sizeof(r
), RTA_GATEWAY
, a
->gw
);
666 r
.r
.rtm_type
= RTN_UNICAST
;
667 nl_add_attr_u32(&r
.h
, sizeof(r
), RTA_OIF
, a
->iface
->index
);
670 r
.r
.rtm_type
= RTN_BLACKHOLE
;
672 case RTD_UNREACHABLE
:
673 r
.r
.rtm_type
= RTN_UNREACHABLE
;
676 r
.r
.rtm_type
= RTN_PROHIBIT
;
679 r
.r
.rtm_type
= RTN_UNICAST
;
680 nl_add_multipath(&r
.h
, sizeof(r
), a
->nexthops
);
683 bug("krt_capable inconsistent with nl_send_route");
686 return nl_exchange(&r
.h
);
690 krt_replace_rte(struct krt_proto
*p
, net
*n
, rte
*new, rte
*old
, struct ea_list
*eattrs
)
695 * NULL for eattr of the old route is a little hack, but we don't
696 * get proper eattrs for old in rt_notify() anyway. NULL means no
697 * extended route attributes and therefore matches if the kernel
698 * route has any of them.
702 nl_send_route(p
, old
, NULL
, 0);
705 err
= nl_send_route(p
, new, eattrs
, 1);
708 n
->n
.flags
|= KRF_SYNC_ERROR
;
710 n
->n
.flags
&= ~KRF_SYNC_ERROR
;
714 #define SKIP(ARG...) do { DBG("KRT: Ignoring route - " ARG); return; } while(0)
717 nl_parse_route(struct nlmsghdr
*h
, int scan
)
721 struct rtattr
*a
[RTA_CACHEINFO
+1];
722 int new = h
->nlmsg_type
== RTM_NEWROUTE
;
724 ip_addr dst
= IPA_NONE
;
728 if (!(i
= nl_checkin(h
, sizeof(*i
))) || !nl_parse_attrs(RTM_RTA(i
), a
, sizeof(a
)))
730 if (i
->rtm_family
!= BIRD_AF
)
732 if ((a
[RTA_DST
] && RTA_PAYLOAD(a
[RTA_DST
]) != sizeof(ip_addr
)) ||
734 (a
[RTA_IIF
] && RTA_PAYLOAD(a
[RTA_IIF
]) != 4) ||
736 (a
[RTA_OIF
] && RTA_PAYLOAD(a
[RTA_OIF
]) != 4) ||
737 (a
[RTA_GATEWAY
] && RTA_PAYLOAD(a
[RTA_GATEWAY
]) != sizeof(ip_addr
)) ||
738 (a
[RTA_PRIORITY
] && RTA_PAYLOAD(a
[RTA_PRIORITY
]) != 4) ||
739 (a
[RTA_PREFSRC
] && RTA_PAYLOAD(a
[RTA_PREFSRC
]) != sizeof(ip_addr
)) ||
740 (a
[RTA_FLOW
] && RTA_PAYLOAD(a
[RTA_FLOW
]) != 4))
742 log(L_ERR
"KRT: Malformed message received");
748 memcpy(&dst
, RTA_DATA(a
[RTA_DST
]), sizeof(dst
));
753 memcpy(&oif
, RTA_DATA(a
[RTA_OIF
]), sizeof(oif
));
755 p
= nl_table_map
[i
->rtm_table
]; /* Do we know this table? */
756 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)");
758 SKIP("unknown table %d\n", i
->rtm_table
);
765 if (i
->rtm_tos
!= 0) /* We don't support TOS */
766 SKIP("TOS %02x\n", i
->rtm_tos
);
770 SKIP("RTM_DELROUTE in scan\n");
772 int c
= ipa_classify_net(dst
);
773 if ((c
< 0) || !(c
& IADDR_HOST
) || ((c
& IADDR_SCOPE_MASK
) <= SCOPE_LINK
))
774 SKIP("strange class/scope\n");
776 // ignore rtm_scope, it is not a real scope
777 // if (i->rtm_scope != RT_SCOPE_UNIVERSE)
778 // SKIP("scope %u\n", i->rtm_scope);
780 switch (i
->rtm_protocol
)
783 SKIP("proto unspec\n");
785 case RTPROT_REDIRECT
:
786 src
= KRT_SRC_REDIRECT
;
790 src
= KRT_SRC_KERNEL
;
804 net
*net
= net_get(p
->p
.table
, dst
, i
->rtm_dst_len
);
808 .source
= RTS_INHERIT
,
809 .scope
= SCOPE_UNIVERSE
,
817 if (a
[RTA_MULTIPATH
])
819 ra
.dest
= RTD_MULTIPATH
;
820 ra
.nexthops
= nl_parse_multipath(p
, a
[RTA_MULTIPATH
]);
823 log(L_ERR
"KRT: Received strange multipath route %I/%d",
824 net
->n
.prefix
, net
->n
.pxlen
);
831 ra
.iface
= if_find_by_index(oif
);
834 log(L_ERR
"KRT: Received route %I/%d with unknown ifindex %u",
835 net
->n
.prefix
, net
->n
.pxlen
, oif
);
842 ra
.dest
= RTD_ROUTER
;
843 memcpy(&ra
.gw
, RTA_DATA(a
[RTA_GATEWAY
]), sizeof(ra
.gw
));
847 /* Silently skip strange 6to4 routes */
848 if (ipa_in_net(ra
.gw
, IPA_NONE
, 96))
852 ng
= neigh_find2(&p
->p
, &ra
.gw
, ra
.iface
,
853 (i
->rtm_flags
& RTNH_F_ONLINK
) ? NEF_ONLINK
: 0);
854 if (!ng
|| (ng
->scope
== SCOPE_HOST
))
856 log(L_ERR
"KRT: Received route %I/%d with strange next-hop %I",
857 net
->n
.prefix
, net
->n
.pxlen
, ra
.gw
);
863 ra
.dest
= RTD_DEVICE
;
866 * In Linux IPv6, 'native' device routes have proto
867 * RTPROT_BOOT and not RTPROT_KERNEL (which they have in
868 * IPv4 and which is expected). We cannot distinguish
869 * 'native' and user defined device routes, so we ignore all
870 * such device routes and for consistency, we have the same
871 * behavior in IPv4. Anyway, users should use RTPROT_STATIC
872 * for their 'alien' routes.
875 if (i
->rtm_protocol
== RTPROT_BOOT
)
876 src
= KRT_SRC_KERNEL
;
881 ra
.dest
= RTD_BLACKHOLE
;
883 case RTN_UNREACHABLE
:
884 ra
.dest
= RTD_UNREACHABLE
;
887 ra
.dest
= RTD_PROHIBIT
;
889 /* FIXME: What about RTN_THROW? */
891 SKIP("type %d\n", i
->rtm_type
);
895 rte
*e
= rte_get_temp(&ra
);
898 e
->u
.krt
.proto
= i
->rtm_protocol
;
899 e
->u
.krt
.type
= i
->rtm_type
;
902 memcpy(&e
->u
.krt
.metric
, RTA_DATA(a
[RTA_PRIORITY
]), sizeof(e
->u
.krt
.metric
));
909 memcpy(&ps
, RTA_DATA(a
[RTA_PREFSRC
]), sizeof(ps
));
912 ea_list
*ea
= alloca(sizeof(ea_list
) + sizeof(eattr
));
913 ea
->next
= ra
.eattrs
;
915 ea
->flags
= EALF_SORTED
;
917 ea
->attrs
[0].id
= EA_KRT_PREFSRC
;
918 ea
->attrs
[0].flags
= 0;
919 ea
->attrs
[0].type
= EAF_TYPE_IP_ADDRESS
;
920 ea
->attrs
[0].u
.ptr
= alloca(sizeof(struct adata
) + sizeof(ps
));
921 ea
->attrs
[0].u
.ptr
->length
= sizeof(ps
);
922 memcpy(ea
->attrs
[0].u
.ptr
->data
, &ps
, sizeof(ps
));
927 ea_list
*ea
= alloca(sizeof(ea_list
) + sizeof(eattr
));
928 ea
->next
= ra
.eattrs
;
930 ea
->flags
= EALF_SORTED
;
932 ea
->attrs
[0].id
= EA_KRT_REALM
;
933 ea
->attrs
[0].flags
= 0;
934 ea
->attrs
[0].type
= EAF_TYPE_INT
;
935 memcpy(&ea
->attrs
[0].u
.data
, RTA_DATA(a
[RTA_FLOW
]), 4);
941 krt_got_route_async(p
, e
, new);
945 krt_do_scan(struct krt_proto
*p UNUSED
) /* CONFIG_ALL_TABLES_AT_ONCE => p is NULL */
949 nl_request_dump(RTM_GETROUTE
);
950 while (h
= nl_get_scan())
951 if (h
->nlmsg_type
== RTM_NEWROUTE
|| h
->nlmsg_type
== RTM_DELROUTE
)
952 nl_parse_route(h
, 1);
954 log(L_DEBUG
"nl_scan_fire: Unknown packet received (type=%d)", h
->nlmsg_type
);
958 * Asynchronous Netlink interface
961 static sock
*nl_async_sk
; /* BIRD socket for asynchronous notifications */
962 static byte
*nl_async_rx_buffer
; /* Receive buffer */
965 nl_async_msg(struct nlmsghdr
*h
)
967 switch (h
->nlmsg_type
)
971 DBG("KRT: Received async route notification (%d)\n", h
->nlmsg_type
);
972 nl_parse_route(h
, 0);
976 DBG("KRT: Received async link notification (%d)\n", h
->nlmsg_type
);
981 DBG("KRT: Received async address notification (%d)\n", h
->nlmsg_type
);
985 DBG("KRT: Received unknown async notification (%d)\n", h
->nlmsg_type
);
990 nl_async_hook(sock
*sk
, int size UNUSED
)
992 struct iovec iov
= { nl_async_rx_buffer
, NL_RX_SIZE
};
993 struct sockaddr_nl sa
;
994 struct msghdr m
= { (struct sockaddr
*) &sa
, sizeof(sa
), &iov
, 1, NULL
, 0, 0 };
999 x
= recvmsg(sk
->fd
, &m
, 0);
1002 if (errno
== ENOBUFS
)
1005 * Netlink reports some packets have been thrown away.
1006 * One day we might react to it by asking for route table
1007 * scan in near future.
1009 return 1; /* More data are likely to be ready */
1011 else if (errno
!= EWOULDBLOCK
)
1012 log(L_ERR
"Netlink recvmsg: %m");
1015 if (sa
.nl_pid
) /* It isn't from the kernel */
1017 DBG("Non-kernel packet\n");
1020 h
= (void *) nl_async_rx_buffer
;
1022 if (m
.msg_flags
& MSG_TRUNC
)
1024 log(L_WARN
"Netlink got truncated asynchronous message");
1027 while (NLMSG_OK(h
, len
))
1030 h
= NLMSG_NEXT(h
, len
);
1033 log(L_WARN
"nl_async_hook: Found packet remnant of size %d", len
);
1041 struct sockaddr_nl sa
;
1043 static int nl_open_tried
= 0;
1049 DBG("KRT: Opening async netlink socket\n");
1051 fd
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_ROUTE
);
1054 log(L_ERR
"Unable to open asynchronous rtnetlink socket: %m");
1058 bzero(&sa
, sizeof(sa
));
1059 sa
.nl_family
= AF_NETLINK
;
1061 sa
.nl_groups
= RTMGRP_LINK
| RTMGRP_IPV6_IFADDR
| RTMGRP_IPV6_ROUTE
;
1063 sa
.nl_groups
= RTMGRP_LINK
| RTMGRP_IPV4_IFADDR
| RTMGRP_IPV4_ROUTE
;
1065 if (bind(fd
, (struct sockaddr
*) &sa
, sizeof(sa
)) < 0)
1067 log(L_ERR
"Unable to bind asynchronous rtnetlink socket: %m");
1071 sk
= nl_async_sk
= sk_new(krt_pool
);
1072 sk
->type
= SK_MAGIC
;
1073 sk
->rx_hook
= nl_async_hook
;
1076 bug("Netlink: sk_open failed");
1078 if (!nl_async_rx_buffer
)
1079 nl_async_rx_buffer
= xmalloc(NL_RX_SIZE
);
1083 * Interface to the UNIX krt module
1086 static u8 nl_cf_table
[(NL_NUM_TABLES
+7) / 8];
1089 krt_sys_start(struct krt_proto
*p
)
1091 nl_table_map
[KRT_CF
->sys
.table_id
] = p
;
1098 krt_sys_shutdown(struct krt_proto
*p UNUSED
)
1103 krt_sys_reconfigure(struct krt_proto
*p UNUSED
, struct krt_config
*n
, struct krt_config
*o
)
1105 return n
->sys
.table_id
== o
->sys
.table_id
;
1110 krt_sys_preconfig(struct config
*c UNUSED
)
1112 bzero(&nl_cf_table
, sizeof(nl_cf_table
));
1116 krt_sys_postconfig(struct krt_config
*x
)
1118 int id
= x
->sys
.table_id
;
1120 if (nl_cf_table
[id
/8] & (1 << (id
%8)))
1121 cf_error("Multiple kernel syncers defined for table #%d", id
);
1122 nl_cf_table
[id
/8] |= (1 << (id
%8));
1126 krt_sys_init_config(struct krt_config
*cf
)
1128 cf
->sys
.table_id
= RT_TABLE_MAIN
;
1132 krt_sys_copy_config(struct krt_config
*d
, struct krt_config
*s
)
1134 d
->sys
.table_id
= s
->sys
.table_id
;
1140 kif_sys_start(struct kif_proto
*p UNUSED
)
1147 kif_sys_shutdown(struct kif_proto
*p UNUSED
)