1 /* Kernel routing table updates using netlink over GNU/Linux system.
2 * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24 /* Hack for GNU libc version 2. */
26 #define MSG_TRUNC 0x20
27 #endif /* MSG_TRUNC */
33 #include "connected.h"
37 #include "zebra/zserv.h"
38 #include "zebra/redistribute.h"
39 #include "zebra/interface.h"
40 #include "zebra/debug.h"
42 /* Socket interface to kernel */
47 struct sockaddr_nl snl
;
49 } netlink
= { -1, 0, {0}, "netlink-listen" }, /* kernel messages */
50 netlink_cmd
= { -1, 0, {0}, "netlink-cmd" }, /* command channel */
51 netlink_addr
= {-1, 0, {0}, "netlink-addr" }; /* address channel */
53 struct message nlmsg_str
[] =
55 {RTM_NEWROUTE
, "RTM_NEWROUTE"},
56 {RTM_DELROUTE
, "RTM_DELROUTE"},
57 {RTM_GETROUTE
, "RTM_GETROUTE"},
58 {RTM_NEWLINK
, "RTM_NEWLINK"},
59 {RTM_DELLINK
, "RTM_DELLINK"},
60 {RTM_GETLINK
, "RTM_GETLINK"},
61 {RTM_NEWADDR
, "RTM_NEWADDR"},
62 {RTM_DELADDR
, "RTM_DELADDR"},
63 {RTM_GETADDR
, "RTM_GETADDR"},
67 extern int rtm_table_default
;
69 /* Make socket for Linux netlink interface. */
71 netlink_socket (struct nlsock
*nl
, unsigned long groups
)
74 struct sockaddr_nl snl
;
78 sock
= socket (AF_NETLINK
, SOCK_RAW
, NETLINK_ROUTE
);
81 zlog (NULL
, LOG_ERR
, "Can't open %s socket: %s", nl
->name
,
86 ret
= fcntl (sock
, F_SETFL
, O_NONBLOCK
);
89 zlog (NULL
, LOG_ERR
, "Can't set %s socket flags: %s", nl
->name
,
95 memset (&snl
, 0, sizeof snl
);
96 snl
.nl_family
= AF_NETLINK
;
97 snl
.nl_groups
= groups
;
99 /* Bind the socket to the netlink structure for anything. */
100 ret
= bind (sock
, (struct sockaddr
*) &snl
, sizeof snl
);
103 zlog (NULL
, LOG_ERR
, "Can't bind %s socket to group 0x%x: %s",
104 nl
->name
, snl
.nl_groups
, strerror (errno
));
109 /* multiple netlink sockets will have different nl_pid */
110 namelen
= sizeof snl
;
111 ret
= getsockname (sock
, (struct sockaddr
*) &snl
, &namelen
);
112 if (ret
< 0 || namelen
!= sizeof snl
)
114 zlog (NULL
, LOG_ERR
, "Can't get %s socket name: %s", nl
->name
,
125 /* Get type specified information from netlink. */
127 netlink_request (int family
, int type
, struct nlsock
*nl
)
130 struct sockaddr_nl snl
;
139 /* Check netlink socket. */
142 zlog (NULL
, LOG_ERR
, "%s socket isn't active.", nl
->name
);
146 memset (&snl
, 0, sizeof snl
);
147 snl
.nl_family
= AF_NETLINK
;
149 req
.nlh
.nlmsg_len
= sizeof req
;
150 req
.nlh
.nlmsg_type
= type
;
151 req
.nlh
.nlmsg_flags
= NLM_F_ROOT
| NLM_F_MATCH
| NLM_F_REQUEST
;
152 req
.nlh
.nlmsg_pid
= 0;
153 req
.nlh
.nlmsg_seq
= ++nl
->seq
;
154 req
.g
.rtgen_family
= family
;
156 ret
= sendto (nl
->sock
, (void*) &req
, sizeof req
, 0,
157 (struct sockaddr
*) &snl
, sizeof snl
);
160 zlog (NULL
, LOG_ERR
, "%s sendto failed: %s", nl
->name
, strerror (errno
));
166 /* Receive message from netlink interface and pass those information
167 to the given function. */
169 netlink_parse_info (int (*filter
) (struct sockaddr_nl
*, struct nlmsghdr
*),
179 struct iovec iov
= { buf
, sizeof buf
};
180 struct sockaddr_nl snl
;
181 struct msghdr msg
= { (void*)&snl
, sizeof snl
, &iov
, 1, NULL
, 0, 0};
184 status
= recvmsg (nl
->sock
, &msg
, 0);
190 if (errno
== EWOULDBLOCK
|| errno
== EAGAIN
)
192 zlog (NULL
, LOG_ERR
, "%s recvmsg overrun", nl
->name
);
198 zlog (NULL
, LOG_ERR
, "Ignoring non kernel message from pid %u",
205 zlog (NULL
, LOG_ERR
, "%s EOF", nl
->name
);
209 if (msg
.msg_namelen
!= sizeof snl
)
211 zlog (NULL
, LOG_ERR
, "%s sender address length error: length %d",
212 nl
->name
, msg
.msg_namelen
);
216 for (h
= (struct nlmsghdr
*) buf
; NLMSG_OK (h
, status
);
217 h
= NLMSG_NEXT (h
, status
))
219 /* Finish of reading. */
220 if (h
->nlmsg_type
== NLMSG_DONE
)
223 /* Error handling. */
224 if (h
->nlmsg_type
== NLMSG_ERROR
)
226 struct nlmsgerr
*err
= (struct nlmsgerr
*) NLMSG_DATA (h
);
228 /* If the error field is zero, then this is an ACK */
231 if (IS_ZEBRA_DEBUG_KERNEL
)
233 zlog_info("%s: %s ACK: type=%s(%u), seq=%u, pid=%d",
234 __FUNCTION__
, nl
->name
,
235 lookup (nlmsg_str
, err
->msg
.nlmsg_type
),
236 err
->msg
.nlmsg_type
, err
->msg
.nlmsg_seq
,
240 /* return if not a multipart message, otherwise continue */
241 if(!(h
->nlmsg_flags
& NLM_F_MULTI
))
248 if (h
->nlmsg_len
< NLMSG_LENGTH (sizeof (struct nlmsgerr
)))
250 zlog (NULL
, LOG_ERR
, "%s error: message truncated",
254 zlog (NULL
, LOG_ERR
, "%s error: %s, type=%s(%u), seq=%u, pid=%d",
255 nl
->name
, strerror (-err
->error
),
256 lookup (nlmsg_str
, err
->msg
.nlmsg_type
),
257 err
->msg
.nlmsg_type
, err
->msg
.nlmsg_seq
,
266 /* OK we got netlink message. */
267 if (IS_ZEBRA_DEBUG_KERNEL
)
268 zlog_info ("netlink_parse_info: %s type %s(%u), seq=%u, pid=%d",
270 lookup (nlmsg_str
, h
->nlmsg_type
), h
->nlmsg_type
,
271 h
->nlmsg_seq
, h
->nlmsg_pid
);
273 /* skip unsolicited messages originating from command socket */
274 if (nl
!= &netlink_cmd
&& h
->nlmsg_pid
== netlink_cmd
.snl
.nl_pid
)
276 if (IS_ZEBRA_DEBUG_KERNEL
)
277 zlog_info ("netlink_parse_info: %s packet comes from %s",
278 nl
->name
, netlink_cmd
.name
);
282 error
= (*filter
) (&snl
, h
);
285 zlog (NULL
, LOG_ERR
, "%s filter function error", nl
->name
);
290 /* After error care. */
291 if (msg
.msg_flags
& MSG_TRUNC
)
293 zlog (NULL
, LOG_ERR
, "%s error: message truncated", nl
->name
);
298 zlog (NULL
, LOG_ERR
, "%s error: data remnant size %d", nl
->name
,
306 /* Utility function for parse rtattr. */
308 netlink_parse_rtattr (struct rtattr
**tb
, int max
, struct rtattr
*rta
, int len
)
310 while (RTA_OK(rta
, len
))
312 if (rta
->rta_type
<= max
)
313 tb
[rta
->rta_type
] = rta
;
314 rta
= RTA_NEXT(rta
,len
);
318 /* Called from interface_lookup_netlink(). This function is only used
321 netlink_interface (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
)
324 struct ifinfomsg
*ifi
;
325 struct rtattr
*tb
[IFLA_MAX
+ 1];
326 struct interface
*ifp
;
330 ifi
= NLMSG_DATA (h
);
332 if (h
->nlmsg_type
!= RTM_NEWLINK
)
335 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct ifinfomsg
));
339 /* Looking up interface name. */
340 memset (tb
, 0, sizeof tb
);
341 netlink_parse_rtattr (tb
, IFLA_MAX
, IFLA_RTA (ifi
), len
);
342 if (tb
[IFLA_IFNAME
] == NULL
)
344 name
= (char *)RTA_DATA(tb
[IFLA_IFNAME
]);
347 ifp
= if_get_by_name (name
);
349 ifp
->ifindex
= ifi
->ifi_index
;
350 ifp
->flags
= ifi
->ifi_flags
& 0x0000fffff;
351 ifp
->mtu
= *(int *)RTA_DATA (tb
[IFLA_MTU
]);
354 /* Hardware type and address. */
355 ifp
->hw_type
= ifi
->ifi_type
;
357 if (tb
[IFLA_ADDRESS
])
361 hw_addr_len
= RTA_PAYLOAD(tb
[IFLA_ADDRESS
]);
363 if (hw_addr_len
> INTERFACE_HWADDR_MAX
)
364 zlog_warn ("Hardware address is too large: %d", hw_addr_len
);
367 ifp
->hw_addr_len
= hw_addr_len
;
368 memcpy (ifp
->hw_addr
, RTA_DATA(tb
[IFLA_ADDRESS
]), hw_addr_len
);
370 for (i
= 0; i
< hw_addr_len
; i
++)
371 if (ifp
->hw_addr
[i
] != 0)
374 if (i
== hw_addr_len
)
375 ifp
->hw_addr_len
= 0;
377 ifp
->hw_addr_len
= hw_addr_len
;
386 /* Lookup interface IPv4/IPv6 address. */
388 netlink_interface_addr (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
)
391 struct ifaddrmsg
*ifa
;
392 struct rtattr
*tb
[IFA_MAX
+ 1];
393 struct interface
*ifp
;
399 ifa
= NLMSG_DATA (h
);
401 if (ifa
->ifa_family
!= AF_INET
403 && ifa
->ifa_family
!= AF_INET6
404 #endif /* HAVE_IPV6 */
408 if (h
->nlmsg_type
!= RTM_NEWADDR
&& h
->nlmsg_type
!= RTM_DELADDR
)
411 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof (struct ifaddrmsg
));
415 memset (tb
, 0, sizeof tb
);
416 netlink_parse_rtattr (tb
, IFA_MAX
, IFA_RTA (ifa
), len
);
418 ifp
= if_lookup_by_index (ifa
->ifa_index
);
421 zlog_err ("netlink_interface_addr can't find interface by index %d",
426 if (tb
[IFA_ADDRESS
] == NULL
)
427 tb
[IFA_ADDRESS
] = tb
[IFA_LOCAL
];
429 if (ifp
->flags
& IFF_POINTOPOINT
)
433 addr
= RTA_DATA (tb
[IFA_LOCAL
]);
435 broad
= RTA_DATA (tb
[IFA_ADDRESS
]);
442 addr
= RTA_DATA (tb
[IFA_ADDRESS
]);
450 addr
= RTA_DATA (tb
[IFA_ADDRESS
]);
454 if (tb
[IFA_BROADCAST
])
455 broad
= RTA_DATA(tb
[IFA_BROADCAST
]);
461 if (ifa
->ifa_flags
& IFA_F_SECONDARY
)
462 SET_FLAG (flags
, ZEBRA_IFA_SECONDARY
);
466 label
= (char *) RTA_DATA (tb
[IFA_LABEL
]);
468 if (ifp
&& label
&& strcmp (ifp
->name
, label
) == 0)
471 /* Register interface address to the interface. */
472 if (ifa
->ifa_family
== AF_INET
)
474 if (h
->nlmsg_type
== RTM_NEWADDR
)
475 connected_add_ipv4 (ifp
, flags
,
476 (struct in_addr
*) addr
, ifa
->ifa_prefixlen
,
477 (struct in_addr
*) broad
, label
);
479 connected_delete_ipv4 (ifp
, flags
,
480 (struct in_addr
*) addr
, ifa
->ifa_prefixlen
,
481 (struct in_addr
*) broad
, label
);
484 if (ifa
->ifa_family
== AF_INET6
)
486 if (h
->nlmsg_type
== RTM_NEWADDR
)
487 connected_add_ipv6 (ifp
,
488 (struct in6_addr
*) addr
, ifa
->ifa_prefixlen
,
489 (struct in6_addr
*) broad
);
491 connected_delete_ipv6 (ifp
,
492 (struct in6_addr
*) addr
, ifa
->ifa_prefixlen
,
493 (struct in6_addr
*) broad
);
495 #endif /* HAVE_IPV6*/
500 /* Looking up routing table by netlink interface. */
502 netlink_routing_table (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
)
506 struct rtattr
*tb
[RTA_MAX
+ 1];
509 char anyaddr
[16] = {0};
516 rtm
= NLMSG_DATA (h
);
518 if (h
->nlmsg_type
!= RTM_NEWROUTE
)
520 if (rtm
->rtm_type
!= RTN_UNICAST
)
523 table
= rtm
->rtm_table
;
524 #if 0 /* we weed them out later in rib_weed_tables () */
525 if (table
!= RT_TABLE_MAIN
&& table
!= rtm_table_default
)
529 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof (struct rtmsg
));
533 memset (tb
, 0, sizeof tb
);
534 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
536 if (rtm
->rtm_flags
& RTM_F_CLONED
)
538 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
540 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
543 if (rtm
->rtm_src_len
!= 0)
546 /* Route which inserted by Zebra. */
547 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
)
548 flags
|= ZEBRA_FLAG_SELFROUTE
;
555 index
= *(int *) RTA_DATA (tb
[RTA_OIF
]);
558 dest
= RTA_DATA (tb
[RTA_DST
]);
562 /* Multipath treatment is needed. */
564 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
566 if (rtm
->rtm_family
== AF_INET
)
568 struct prefix_ipv4 p
;
570 memcpy (&p
.prefix
, dest
, 4);
571 p
.prefixlen
= rtm
->rtm_dst_len
;
573 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL
, flags
, &p
, gate
, index
, table
, 0, 0);
576 if (rtm
->rtm_family
== AF_INET6
)
578 struct prefix_ipv6 p
;
580 memcpy (&p
.prefix
, dest
, 16);
581 p
.prefixlen
= rtm
->rtm_dst_len
;
583 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL
, flags
, &p
, gate
, index
, table
);
585 #endif /* HAVE_IPV6 */
590 struct message rtproto_str
[] =
592 {RTPROT_REDIRECT
, "redirect"},
593 {RTPROT_KERNEL
, "kernel"},
594 {RTPROT_BOOT
, "boot"},
595 {RTPROT_STATIC
, "static"},
596 {RTPROT_GATED
, "GateD"},
597 {RTPROT_RA
, "router advertisement"},
599 {RTPROT_ZEBRA
, "Zebra"},
601 {RTPROT_BIRD
, "BIRD"},
602 #endif /* RTPROT_BIRD */
606 /* Routing information change from the kernel. */
608 netlink_route_change (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
)
612 struct rtattr
*tb
[RTA_MAX
+ 1];
614 char anyaddr
[16] = {0};
621 rtm
= NLMSG_DATA (h
);
623 if (! (h
->nlmsg_type
== RTM_NEWROUTE
|| h
->nlmsg_type
== RTM_DELROUTE
))
625 /* If this is not route add/delete message print warning. */
626 zlog_warn ("Kernel message: %d\n", h
->nlmsg_type
);
630 /* Connected route. */
631 if (IS_ZEBRA_DEBUG_KERNEL
)
632 zlog_info ("%s %s %s proto %s",
633 h
->nlmsg_type
== RTM_NEWROUTE
? "RTM_NEWROUTE" : "RTM_DELROUTE",
634 rtm
->rtm_family
== AF_INET
? "ipv4" : "ipv6",
635 rtm
->rtm_type
== RTN_UNICAST
? "unicast" : "multicast",
636 lookup (rtproto_str
, rtm
->rtm_protocol
));
638 if (rtm
->rtm_type
!= RTN_UNICAST
)
643 table
= rtm
->rtm_table
;
644 if (table
!= RT_TABLE_MAIN
&& table
!= rtm_table_default
)
649 len
= h
->nlmsg_len
- NLMSG_LENGTH(sizeof (struct rtmsg
));
653 memset (tb
, 0, sizeof tb
);
654 netlink_parse_rtattr (tb
, RTA_MAX
, RTM_RTA (rtm
), len
);
656 if (rtm
->rtm_flags
& RTM_F_CLONED
)
658 if (rtm
->rtm_protocol
== RTPROT_REDIRECT
)
660 if (rtm
->rtm_protocol
== RTPROT_KERNEL
)
663 if (rtm
->rtm_protocol
== RTPROT_ZEBRA
&& h
->nlmsg_type
== RTM_NEWROUTE
)
666 if (rtm
->rtm_src_len
!= 0)
668 zlog_warn ("netlink_route_change(): no src len");
677 index
= *(int *) RTA_DATA (tb
[RTA_OIF
]);
680 dest
= RTA_DATA (tb
[RTA_DST
]);
685 gate
= RTA_DATA (tb
[RTA_GATEWAY
]);
687 if (rtm
->rtm_family
== AF_INET
)
689 struct prefix_ipv4 p
;
691 memcpy (&p
.prefix
, dest
, 4);
692 p
.prefixlen
= rtm
->rtm_dst_len
;
694 if (IS_ZEBRA_DEBUG_KERNEL
)
696 if (h
->nlmsg_type
== RTM_NEWROUTE
)
697 zlog_info ("RTM_NEWROUTE %s/%d",
698 inet_ntoa (p
.prefix
), p
.prefixlen
);
700 zlog_info ("RTM_DELROUTE %s/%d",
701 inet_ntoa (p
.prefix
), p
.prefixlen
);
704 if (h
->nlmsg_type
== RTM_NEWROUTE
)
705 rib_add_ipv4 (ZEBRA_ROUTE_KERNEL
, 0, &p
, gate
, index
, table
, 0, 0);
707 rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL
, 0, &p
, gate
, index
, table
);
711 if (rtm
->rtm_family
== AF_INET6
)
713 struct prefix_ipv6 p
;
717 memcpy (&p
.prefix
, dest
, 16);
718 p
.prefixlen
= rtm
->rtm_dst_len
;
720 if (IS_ZEBRA_DEBUG_KERNEL
)
722 if (h
->nlmsg_type
== RTM_NEWROUTE
)
723 zlog_info ("RTM_NEWROUTE %s/%d",
724 inet_ntop (AF_INET6
, &p
.prefix
, buf
, BUFSIZ
),
727 zlog_info ("RTM_DELROUTE %s/%d",
728 inet_ntop (AF_INET6
, &p
.prefix
, buf
, BUFSIZ
),
732 if (h
->nlmsg_type
== RTM_NEWROUTE
)
733 rib_add_ipv6 (ZEBRA_ROUTE_KERNEL
, 0, &p
, gate
, index
, 0);
735 rib_delete_ipv6 (ZEBRA_ROUTE_KERNEL
, 0, &p
, gate
, index
, 0);
737 #endif /* HAVE_IPV6 */
743 netlink_link_change (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
)
746 struct ifinfomsg
*ifi
;
747 struct rtattr
*tb
[IFLA_MAX
+ 1];
748 struct interface
*ifp
;
751 ifi
= NLMSG_DATA (h
);
753 if (! (h
->nlmsg_type
== RTM_NEWLINK
|| h
->nlmsg_type
== RTM_DELLINK
))
755 /* If this is not link add/delete message so print warning. */
756 zlog_warn ("netlink_link_change: wrong kernel message %d\n",
761 len
= h
->nlmsg_len
- NLMSG_LENGTH (sizeof (struct ifinfomsg
));
765 /* Looking up interface name. */
766 memset (tb
, 0, sizeof tb
);
767 netlink_parse_rtattr (tb
, IFLA_MAX
, IFLA_RTA (ifi
), len
);
768 if (tb
[IFLA_IFNAME
] == NULL
)
770 name
= (char *)RTA_DATA(tb
[IFLA_IFNAME
]);
773 if (h
->nlmsg_type
== RTM_NEWLINK
)
775 ifp
= if_lookup_by_name (name
);
777 if (ifp
== NULL
|| ! CHECK_FLAG (ifp
->status
, ZEBRA_INTERFACE_ACTIVE
))
780 ifp
= if_get_by_name (name
);
782 ifp
->ifindex
= ifi
->ifi_index
;
783 ifp
->flags
= ifi
->ifi_flags
& 0x0000fffff;
784 ifp
->mtu
= *(int *)RTA_DATA (tb
[IFLA_MTU
]);
787 /* If new link is added. */
792 /* Interface status change. */
793 ifp
->ifindex
= ifi
->ifi_index
;
794 ifp
->mtu
= *(int *)RTA_DATA (tb
[IFLA_MTU
]);
799 ifp
->flags
= ifi
->ifi_flags
& 0x0000fffff;
800 if (! if_is_up (ifp
))
805 ifp
->flags
= ifi
->ifi_flags
& 0x0000fffff;
814 ifp
= if_lookup_by_name (name
);
818 zlog (NULL
, LOG_WARNING
, "interface %s is deleted but can't find",
823 if_delete_update (ifp
);
830 netlink_information_fetch (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
)
832 switch (h
->nlmsg_type
)
835 return netlink_route_change (snl
, h
);
838 return netlink_route_change (snl
, h
);
841 return netlink_link_change (snl
, h
);
844 return netlink_link_change (snl
, h
);
847 return netlink_interface_addr (snl
, h
);
850 return netlink_interface_addr (snl
, h
);
853 zlog_warn ("Unknown netlink nlmsg_type %d\n", h
->nlmsg_type
);
859 /* Interface lookup by netlink socket. */
861 interface_lookup_netlink ()
865 /* Get interface information. */
866 ret
= netlink_request (AF_PACKET
, RTM_GETLINK
, &netlink_cmd
);
869 ret
= netlink_parse_info (netlink_interface
, &netlink_cmd
);
873 /* Get IPv4 address of the interfaces. */
874 ret
= netlink_request (AF_INET
, RTM_GETADDR
, &netlink_cmd
);
877 ret
= netlink_parse_info (netlink_interface_addr
, &netlink_cmd
);
882 /* Get IPv6 address of the interfaces. */
883 ret
= netlink_request (AF_INET6
, RTM_GETADDR
, &netlink_cmd
);
886 ret
= netlink_parse_info (netlink_interface_addr
, &netlink_cmd
);
889 #endif /* HAVE_IPV6 */
894 /* Routing table read function using netlink interface. Only called
897 netlink_route_read ()
901 /* Get IPv4 routing table. */
902 ret
= netlink_request (AF_INET
, RTM_GETROUTE
, &netlink_cmd
);
905 ret
= netlink_parse_info (netlink_routing_table
, &netlink_cmd
);
910 /* Get IPv6 routing table. */
911 ret
= netlink_request (AF_INET6
, RTM_GETROUTE
, &netlink_cmd
);
914 ret
= netlink_parse_info (netlink_routing_table
, &netlink_cmd
);
917 #endif /* HAVE_IPV6 */
922 /* Utility function comes from iproute2.
923 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
925 addattr_l (struct nlmsghdr
*n
, int maxlen
, int type
, void *data
, int alen
)
930 len
= RTA_LENGTH(alen
);
932 if (NLMSG_ALIGN(n
->nlmsg_len
) + len
> maxlen
)
935 rta
= (struct rtattr
*) (((char*)n
) + NLMSG_ALIGN (n
->nlmsg_len
));
936 rta
->rta_type
= type
;
938 memcpy (RTA_DATA(rta
), data
, alen
);
939 n
->nlmsg_len
= NLMSG_ALIGN (n
->nlmsg_len
) + len
;
945 rta_addattr_l (struct rtattr
*rta
, int maxlen
, int type
, void *data
, int alen
)
948 struct rtattr
*subrta
;
950 len
= RTA_LENGTH(alen
);
952 if (RTA_ALIGN(rta
->rta_len
) + len
> maxlen
)
955 subrta
= (struct rtattr
*) (((char*)rta
) + RTA_ALIGN (rta
->rta_len
));
956 subrta
->rta_type
= type
;
957 subrta
->rta_len
= len
;
958 memcpy (RTA_DATA(subrta
), data
, alen
);
959 rta
->rta_len
= NLMSG_ALIGN (rta
->rta_len
) + len
;
964 /* Utility function comes from iproute2.
965 Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */
967 addattr32 (struct nlmsghdr
*n
, int maxlen
, int type
, int data
)
974 if (NLMSG_ALIGN (n
->nlmsg_len
) + len
> maxlen
)
977 rta
= (struct rtattr
*) (((char*)n
) + NLMSG_ALIGN (n
->nlmsg_len
));
978 rta
->rta_type
= type
;
980 memcpy (RTA_DATA(rta
), &data
, 4);
981 n
->nlmsg_len
= NLMSG_ALIGN (n
->nlmsg_len
) + len
;
987 netlink_talk_filter (struct sockaddr_nl
*snl
, struct nlmsghdr
*h
)
989 zlog_warn ("netlink_talk: ignoring message type 0x%04x", h
->nlmsg_type
);
993 /* sendmsg() to netlink socket then recvmsg(). */
995 netlink_talk (struct nlmsghdr
*n
, struct nlsock
*nl
)
998 struct sockaddr_nl snl
;
999 struct iovec iov
= { (void*) n
, n
->nlmsg_len
};
1000 struct msghdr msg
= {(void*) &snl
, sizeof snl
, &iov
, 1, NULL
, 0, 0};
1003 memset (&snl
, 0, sizeof snl
);
1004 snl
.nl_family
= AF_NETLINK
;
1006 n
->nlmsg_seq
= ++netlink_cmd
.seq
;
1008 /* Request an acknowledgement by setting NLM_F_ACK */
1009 n
->nlmsg_flags
|= NLM_F_ACK
;
1011 if (IS_ZEBRA_DEBUG_KERNEL
)
1012 zlog_info ("netlink_talk: %s type %s(%u), seq=%u", netlink_cmd
.name
,
1013 lookup (nlmsg_str
, n
->nlmsg_type
), n
->nlmsg_type
,
1016 /* Send message to netlink interface. */
1017 status
= sendmsg (nl
->sock
, &msg
, 0);
1020 zlog (NULL
, LOG_ERR
, "netlink_talk sendmsg() error: %s",
1026 * Change socket flags for blocking I/O.
1027 * This ensures we wait for a reply in netlink_parse_info().
1029 if((flags
= fcntl(nl
->sock
, F_GETFL
, 0)) < 0)
1031 zlog (NULL
, LOG_ERR
, "%s:%i F_GETFL error: %s",
1032 __FUNCTION__
, __LINE__
, strerror (errno
));
1034 flags
&= ~O_NONBLOCK
;
1035 if(fcntl(nl
->sock
, F_SETFL
, flags
) < 0)
1037 zlog (NULL
, LOG_ERR
, "%s:%i F_SETFL error: %s",
1038 __FUNCTION__
, __LINE__
, strerror (errno
));
1042 * Get reply from netlink socket.
1043 * The reply should either be an acknowlegement or an error.
1045 status
= netlink_parse_info (netlink_talk_filter
, nl
);
1047 /* Restore socket flags for nonblocking I/O */
1048 flags
|= O_NONBLOCK
;
1049 if(fcntl(nl
->sock
, F_SETFL
, flags
) < 0)
1051 zlog (NULL
, LOG_ERR
, "%s:%i F_SETFL error: %s",
1052 __FUNCTION__
, __LINE__
, strerror (errno
));
1058 /* Routing table change via netlink interface. */
1060 netlink_route (int cmd
, int family
, void *dest
, int length
, void *gate
,
1061 int index
, int zebra_flags
, int table
)
1065 struct sockaddr_nl snl
;
1075 memset (&req
, 0, sizeof req
);
1077 bytelen
= (family
== AF_INET
? 4 : 16);
1079 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1080 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1081 req
.n
.nlmsg_type
= cmd
;
1082 req
.r
.rtm_family
= family
;
1083 req
.r
.rtm_table
= table
;
1084 req
.r
.rtm_dst_len
= length
;
1086 if (zebra_flags
& ZEBRA_FLAG_BLACKHOLE
)
1091 if (cmd
== RTM_NEWROUTE
)
1094 req
.r
.rtm_protocol
= RTPROT_ZEBRA
;
1096 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1099 req
.r
.rtm_type
= RTN_BLACKHOLE
;
1101 req
.r
.rtm_type
= RTN_UNICAST
;
1105 addattr_l (&req
.n
, sizeof req
, RTA_DST
, dest
, bytelen
);
1110 addattr_l (&req
.n
, sizeof req
, RTA_GATEWAY
, gate
, bytelen
);
1112 addattr32 (&req
.n
, sizeof req
, RTA_OIF
, index
);
1115 /* Destination netlink address. */
1116 memset (&snl
, 0, sizeof snl
);
1117 snl
.nl_family
= AF_NETLINK
;
1119 /* Talk to netlink socket. */
1120 ret
= netlink_talk (&req
.n
, &netlink
);
1127 /* Routing table change via netlink interface. */
1129 netlink_route_multipath (int cmd
, struct prefix
*p
, struct rib
*rib
,
1133 struct sockaddr_nl snl
;
1134 struct nexthop
*nexthop
= NULL
;
1135 int nexthop_num
= 0;
1146 memset (&req
, 0, sizeof req
);
1148 bytelen
= (family
== AF_INET
? 4 : 16);
1150 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof (struct rtmsg
));
1151 req
.n
.nlmsg_flags
= NLM_F_CREATE
| NLM_F_REQUEST
;
1152 req
.n
.nlmsg_type
= cmd
;
1153 req
.r
.rtm_family
= family
;
1154 req
.r
.rtm_table
= rib
->table
;
1155 req
.r
.rtm_dst_len
= p
->prefixlen
;
1157 #ifdef RTM_F_EQUALIZE
1158 req
.r
.rtm_flags
|= RTM_F_EQUALIZE
;
1159 #endif /* RTM_F_EQUALIZE */
1161 if (rib
->flags
& ZEBRA_FLAG_BLACKHOLE
)
1166 if (cmd
== RTM_NEWROUTE
)
1168 req
.r
.rtm_protocol
= RTPROT_ZEBRA
;
1169 req
.r
.rtm_scope
= RT_SCOPE_UNIVERSE
;
1172 req
.r
.rtm_type
= RTN_BLACKHOLE
;
1174 req
.r
.rtm_type
= RTN_UNICAST
;
1177 addattr_l (&req
.n
, sizeof req
, RTA_DST
, &p
->u
.prefix
, bytelen
);
1180 addattr32 (&req
.n
, sizeof req
, RTA_PRIORITY
, rib
->metric
);
1184 if (cmd
== RTM_NEWROUTE
)
1185 for (nexthop
= rib
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
1186 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1190 /* Multipath case. */
1191 if (rib
->nexthop_active_num
== 1 || MULTIPATH_NUM
== 1)
1193 for (nexthop
= rib
->nexthop
; nexthop
; nexthop
= nexthop
->next
)
1195 if ((cmd
== RTM_NEWROUTE
1196 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1197 || (cmd
== RTM_DELROUTE
1198 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1200 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1202 if (nexthop
->rtype
== NEXTHOP_TYPE_IPV4
1203 || nexthop
->rtype
== NEXTHOP_TYPE_IPV4_IFINDEX
)
1204 addattr_l (&req
.n
, sizeof req
, RTA_GATEWAY
,
1205 &nexthop
->rgate
.ipv4
, bytelen
);
1207 if (nexthop
->rtype
== NEXTHOP_TYPE_IPV6
1208 || nexthop
->rtype
== NEXTHOP_TYPE_IPV6_IFINDEX
1209 || nexthop
->rtype
== NEXTHOP_TYPE_IPV6_IFNAME
)
1210 addattr_l (&req
.n
, sizeof req
, RTA_GATEWAY
,
1211 &nexthop
->rgate
.ipv6
, bytelen
);
1212 #endif /* HAVE_IPV6 */
1213 if (nexthop
->rtype
== NEXTHOP_TYPE_IFINDEX
1214 || nexthop
->rtype
== NEXTHOP_TYPE_IFNAME
1215 || nexthop
->rtype
== NEXTHOP_TYPE_IPV4_IFINDEX
1216 || nexthop
->rtype
== NEXTHOP_TYPE_IPV6_IFINDEX
1217 || nexthop
->rtype
== NEXTHOP_TYPE_IPV6_IFNAME
)
1218 addattr32 (&req
.n
, sizeof req
, RTA_OIF
,
1223 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
1224 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
1225 addattr_l (&req
.n
, sizeof req
, RTA_GATEWAY
,
1226 &nexthop
->gate
.ipv4
, bytelen
);
1228 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
1229 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFNAME
1230 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1231 addattr_l (&req
.n
, sizeof req
, RTA_GATEWAY
,
1232 &nexthop
->gate
.ipv6
, bytelen
);
1233 #endif /* HAVE_IPV6 */
1234 if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
1235 || nexthop
->type
== NEXTHOP_TYPE_IFNAME
1236 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
1237 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
1238 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFNAME
)
1239 addattr32 (&req
.n
, sizeof req
, RTA_OIF
, nexthop
->ifindex
);
1242 if (cmd
== RTM_NEWROUTE
)
1243 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1253 struct rtattr
*rta
= (void *) buf
;
1254 struct rtnexthop
*rtnh
;
1256 rta
->rta_type
= RTA_MULTIPATH
;
1257 rta
->rta_len
= RTA_LENGTH(0);
1258 rtnh
= RTA_DATA(rta
);
1261 for (nexthop
= rib
->nexthop
;
1262 nexthop
&& (MULTIPATH_NUM
== 0 || nexthop_num
< MULTIPATH_NUM
);
1263 nexthop
= nexthop
->next
)
1265 if ((cmd
== RTM_NEWROUTE
1266 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_ACTIVE
))
1267 || (cmd
== RTM_DELROUTE
1268 && CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
)))
1272 rtnh
->rtnh_len
= sizeof (*rtnh
);
1273 rtnh
->rtnh_flags
= 0;
1274 rtnh
->rtnh_hops
= 0;
1275 rta
->rta_len
+= rtnh
->rtnh_len
;
1277 if (CHECK_FLAG (nexthop
->flags
, NEXTHOP_FLAG_RECURSIVE
))
1279 if (nexthop
->rtype
== NEXTHOP_TYPE_IPV4
1280 || nexthop
->rtype
== NEXTHOP_TYPE_IPV4_IFINDEX
)
1282 rta_addattr_l (rta
, 4096, RTA_GATEWAY
,
1283 &nexthop
->rgate
.ipv4
, bytelen
);
1284 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + 4;
1287 if (nexthop
->rtype
== NEXTHOP_TYPE_IPV6
1288 || nexthop
->rtype
== NEXTHOP_TYPE_IPV6_IFNAME
1289 || nexthop
->rtype
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1290 rta_addattr_l (rta
, 4096, RTA_GATEWAY
,
1291 &nexthop
->rgate
.ipv6
, bytelen
);
1292 #endif /* HAVE_IPV6 */
1294 if (nexthop
->rtype
== NEXTHOP_TYPE_IFINDEX
1295 || nexthop
->rtype
== NEXTHOP_TYPE_IFNAME
1296 || nexthop
->rtype
== NEXTHOP_TYPE_IPV4_IFINDEX
1297 || nexthop
->rtype
== NEXTHOP_TYPE_IPV6_IFINDEX
1298 || nexthop
->rtype
== NEXTHOP_TYPE_IPV6_IFNAME
)
1299 rtnh
->rtnh_ifindex
= nexthop
->rifindex
;
1301 rtnh
->rtnh_ifindex
= 0;
1305 if (nexthop
->type
== NEXTHOP_TYPE_IPV4
1306 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
)
1308 rta_addattr_l (rta
, 4096, RTA_GATEWAY
,
1309 &nexthop
->gate
.ipv4
, bytelen
);
1310 rtnh
->rtnh_len
+= sizeof (struct rtattr
) + 4;
1313 if (nexthop
->type
== NEXTHOP_TYPE_IPV6
1314 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFNAME
1315 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1316 rta_addattr_l (rta
, 4096, RTA_GATEWAY
,
1317 &nexthop
->gate
.ipv6
, bytelen
);
1318 #endif /* HAVE_IPV6 */
1320 if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
1321 || nexthop
->type
== NEXTHOP_TYPE_IFNAME
1322 || nexthop
->type
== NEXTHOP_TYPE_IPV4_IFINDEX
1323 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFNAME
1324 || nexthop
->type
== NEXTHOP_TYPE_IPV6_IFINDEX
)
1325 rtnh
->rtnh_ifindex
= nexthop
->ifindex
;
1327 rtnh
->rtnh_ifindex
= 0;
1329 rtnh
= RTNH_NEXT(rtnh
);
1331 if (cmd
== RTM_NEWROUTE
)
1332 SET_FLAG (nexthop
->flags
, NEXTHOP_FLAG_FIB
);
1336 if (rta
->rta_len
> RTA_LENGTH (0))
1337 addattr_l (&req
.n
, 1024, RTA_MULTIPATH
, RTA_DATA(rta
),
1341 /* If there is no useful nexthop then return. */
1342 if (nexthop_num
== 0)
1344 if (IS_ZEBRA_DEBUG_KERNEL
)
1345 zlog_info ("netlink_route_multipath(): No useful nexthop.");
1351 /* Destination netlink address. */
1352 memset (&snl
, 0, sizeof snl
);
1353 snl
.nl_family
= AF_NETLINK
;
1355 if (family
== AF_INET
)
1360 /* Talk to netlink socket. */
1361 return netlink_talk (&req
.n
, nl
);
1365 kernel_add_ipv4 (struct prefix
*p
, struct rib
*rib
)
1367 return netlink_route_multipath (RTM_NEWROUTE
, p
, rib
, AF_INET
);
1371 kernel_delete_ipv4 (struct prefix
*p
, struct rib
*rib
)
1373 return netlink_route_multipath (RTM_DELROUTE
, p
, rib
, AF_INET
);
1378 kernel_add_ipv6 (struct prefix
*p
, struct rib
*rib
)
1380 return netlink_route_multipath (RTM_NEWROUTE
, p
, rib
, AF_INET6
);
1384 kernel_delete_ipv6 (struct prefix
*p
, struct rib
*rib
)
1386 return netlink_route_multipath (RTM_DELROUTE
, p
, rib
, AF_INET6
);
1389 /* Delete IPv6 route from the kernel. */
1391 kernel_delete_ipv6_old (struct prefix_ipv6
*dest
, struct in6_addr
*gate
,
1392 int index
, int flags
, int table
)
1394 return netlink_route (RTM_DELROUTE
, AF_INET6
, &dest
->prefix
, dest
->prefixlen
,
1395 gate
, index
, flags
, table
);
1397 #endif /* HAVE_IPV6 */
1399 /* Interface address modification. */
1401 netlink_address (int cmd
, int family
, struct interface
*ifp
,
1402 struct connected
*ifc
)
1410 struct ifaddrmsg ifa
;
1415 memset (&req
, 0, sizeof req
);
1417 bytelen
= (family
== AF_INET
? 4 : 16);
1419 req
.n
.nlmsg_len
= NLMSG_LENGTH (sizeof(struct ifaddrmsg
));
1420 req
.n
.nlmsg_flags
= NLM_F_REQUEST
;
1421 req
.n
.nlmsg_type
= cmd
;
1422 req
.ifa
.ifa_family
= family
;
1424 req
.ifa
.ifa_index
= ifp
->ifindex
;
1425 req
.ifa
.ifa_prefixlen
= p
->prefixlen
;
1427 addattr_l (&req
.n
, sizeof req
, IFA_LOCAL
, &p
->u
.prefix
, bytelen
);
1429 if (family
== AF_INET
&& cmd
== RTM_NEWADDR
)
1431 if (if_is_broadcast (ifp
) && ifc
->destination
)
1433 p
= ifc
->destination
;
1434 addattr_l(&req
.n
, sizeof req
, IFA_BROADCAST
, &p
->u
.prefix
, bytelen
);
1438 if (CHECK_FLAG (ifc
->flags
, ZEBRA_IFA_SECONDARY
))
1439 SET_FLAG (req
.ifa
.ifa_flags
, IFA_F_SECONDARY
);
1442 addattr_l (&req
.n
, sizeof req
, IFA_LABEL
, ifc
->label
,
1443 strlen (ifc
->label
) + 1);
1445 return netlink_talk (&req
.n
, &netlink_cmd
);
1449 kernel_address_add_ipv4 (struct interface
*ifp
, struct connected
*ifc
)
1451 return netlink_address (RTM_NEWADDR
, AF_INET
, ifp
, ifc
);
1455 kernel_address_delete_ipv4 (struct interface
*ifp
, struct connected
*ifc
)
1457 return netlink_address (RTM_DELADDR
, AF_INET
, ifp
, ifc
);
1462 extern struct thread_master
*master
;
1464 /* Kernel route reflection. */
1466 kernel_read (struct thread
*thread
)
1471 sock
= THREAD_FD (thread
);
1472 ret
= netlink_parse_info (netlink_information_fetch
, &netlink
);
1473 thread_add_read (master
, kernel_read
, NULL
, netlink
.sock
);
1478 /* Exported interface function. This function simply calls
1479 netlink_socket (). */
1483 unsigned long groups
;
1485 groups
= RTMGRP_LINK
|RTMGRP_IPV4_ROUTE
|RTMGRP_IPV4_IFADDR
;
1487 groups
|= RTMGRP_IPV6_ROUTE
|RTMGRP_IPV6_IFADDR
;
1488 #endif /* HAVE_IPV6 */
1489 netlink_socket (&netlink
, groups
);
1490 netlink_socket (&netlink_cmd
, 0);
1492 /* Register kernel socket. */
1493 if (netlink
.sock
> 0)
1494 thread_add_read (master
, kernel_read
, NULL
, netlink
.sock
);