diff options
Diffstat (limited to 'zebra')
-rw-r--r-- | zebra/connected.c | 2 | ||||
-rw-r--r-- | zebra/debug.c | 2 | ||||
-rw-r--r-- | zebra/if_netlink.c | 5 | ||||
-rw-r--r-- | zebra/interface.c | 28 | ||||
-rw-r--r-- | zebra/irdp_packet.c | 2 | ||||
-rw-r--r-- | zebra/rib.h | 59 | ||||
-rw-r--r-- | zebra/rt_netlink.c | 451 | ||||
-rw-r--r-- | zebra/rtadv.c | 4 | ||||
-rw-r--r-- | zebra/rtread_netlink.c | 6 | ||||
-rw-r--r-- | zebra/zebra_rib.c | 189 |
10 files changed, 388 insertions, 360 deletions
diff --git a/zebra/connected.c b/zebra/connected.c index ad3e9607..f3e5396c 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -86,7 +86,7 @@ connected_announce (struct interface *ifp, struct connected *ifc) zebra_interface_address_add_update (ifp, ifc); - if (if_is_up(ifp)) + if (if_is_operative(ifp)) { if (ifc->address->family == AF_INET) connected_up_ipv4 (ifp, ifc); diff --git a/zebra/debug.c b/zebra/debug.c index 23c4de3a..175029b8 100644 --- a/zebra/debug.c +++ b/zebra/debug.c @@ -236,7 +236,7 @@ DEFUN (no_debug_zebra_rib, DEFUN (no_debug_zebra_rib_q, no_debug_zebra_rib_q_cmd, - "no debug zebra rib queueu", + "no debug zebra rib queue", NO_STR DEBUG_STR "Zebra configuration\n" diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c index c9c14760..701c81b6 100644 --- a/zebra/if_netlink.c +++ b/zebra/if_netlink.c @@ -22,12 +22,11 @@ #include <zebra.h> -/* Extern from rt_netlink.c */ -void interface_lookup_netlink (); +extern int interface_lookup_netlink (void); /* Interface information read by netlink. */ void -interface_list () +interface_list (void) { interface_lookup_netlink (); } diff --git a/zebra/interface.c b/zebra/interface.c index 184b42a0..ce506056 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -274,7 +274,7 @@ if_addr_wakeup (struct interface *ifp) /* Address check. */ if (p->family == AF_INET) { - if (! if_is_up (ifp)) + if (! if_is_operative (ifp)) { /* XXX: WTF is it trying to set flags here? * caller has just gotten a new interface, has been @@ -311,7 +311,7 @@ if_addr_wakeup (struct interface *ifp) #ifdef HAVE_IPV6 if (p->family == AF_INET6) { - if (! if_is_up (ifp)) + if (! if_is_operative (ifp)) { /* XXX: See long comment above */ if_set_flags (ifp, IFF_UP | IFF_RUNNING); @@ -379,7 +379,7 @@ if_delete_update (struct interface *ifp) zebra_if = ifp->info; - if (if_is_up(ifp)) + if (if_is_operative(ifp)) { zlog_err ("interface %s index %d is still up while being deleted.", ifp->name, ifp->ifindex); @@ -538,15 +538,25 @@ if_down (struct interface *ifp) if (p->family == AF_INET) connected_down_ipv4 (ifp, ifc); + } + } + + /* Examine all static routes which direct to the interface. */ + rib_update (); + #ifdef HAVE_IPV6 - else if (p->family == AF_INET6) + if (ifp->connected) + { + for (ALL_LIST_ELEMENTS (ifp->connected, node, next, ifc)) + { + p = ifc->address; + if (p->family == AF_INET6) connected_down_ipv6 (ifp, ifc); -#endif /* HAVE_IPV6 */ } } - /* Examine all static routes which direct to the interface. */ rib_update (); +#endif /* HAVE_IPV6 */ } void @@ -822,6 +832,7 @@ if_dump_vty (struct vty *vty, struct interface *ifp) #endif /* HAVE_NET_RT_IFLIST */ } +#if 0 /* Check supported address family. */ static int if_supported_family (int family) @@ -834,6 +845,7 @@ if_supported_family (int family) #endif /* HAVE_IPV6 */ return 0; } +#endif /* Wrapper hook point for zebra daemon so that ifindex can be set * DEFUN macro not used as extract.pl HAS to ignore this @@ -1205,7 +1217,7 @@ ip_address_install (struct vty *vty, struct interface *ifp, && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) { /* Some system need to up the interface to set IP address. */ - if (! if_is_up (ifp)) + if (! if_is_operative (ifp)) { if_set_flags (ifp, IFF_UP | IFF_RUNNING); if_refresh (ifp); @@ -1398,7 +1410,7 @@ ipv6_address_install (struct vty *vty, struct interface *ifp, && CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) { /* Some system need to up the interface to set IP address. */ - if (! if_is_up (ifp)) + if (! if_is_operative (ifp)) { if_set_flags (ifp, IFF_UP | IFF_RUNNING); if_refresh (ifp); diff --git a/zebra/irdp_packet.c b/zebra/irdp_packet.c index 3c5f1559..ae121ea1 100644 --- a/zebra/irdp_packet.c +++ b/zebra/irdp_packet.c @@ -231,7 +231,7 @@ int irdp_read_raw(struct thread *r) struct zebra_if *zi; struct irdp_interface *irdp; char buf[IRDP_RX_BUF]; - int ret, ifindex; + int ret, ifindex = 0; int irdp_sock = THREAD_FD (r); t_irdp_raw = thread_add_read (zebrad.master, irdp_read_raw, NULL, irdp_sock); diff --git a/zebra/rib.h b/zebra/rib.h index 887ed3c2..0d6ab815 100644 --- a/zebra/rib.h +++ b/zebra/rib.h @@ -38,10 +38,6 @@ union g_addr { struct rib { - /* Status Flags for the *route_node*, but kept in the head RIB.. */ - u_char rn_status; -#define RIB_ROUTE_QUEUED(x) (1 << (x)) - /* Link list. */ struct rib *next; struct rib *prev; @@ -49,20 +45,24 @@ struct rib /* Nexthop structure */ struct nexthop *nexthop; - /* Refrence count. */ + /* Reference count. */ unsigned long refcnt; /* Uptime. */ time_t uptime; - /* Type fo this route. */ - int type; + /* Metric */ + u_int32_t metric; /* Which routing table */ - int table; + u_int32_t table; - /* Metric */ - u_int32_t metric; + /* Type for this route. < ZEBRA_ROUTE_MAX */ + u_int8_t type; + + /* Status Flags for the *route_node*, but kept in the head RIB.. */ + u_char rn_status; +#define RIB_ROUTE_QUEUED (1 << 0) /* Distance. */ u_char distance; @@ -104,6 +104,13 @@ struct static_ipv4 struct static_ipv4 *prev; struct static_ipv4 *next; + /* Nexthop value. */ + union + { + struct in_addr ipv4; + char *ifname; + } gate; + /* Administrative distance. */ u_char distance; @@ -113,13 +120,6 @@ struct static_ipv4 #define STATIC_IPV4_IFNAME 2 #define STATIC_IPV4_BLACKHOLE 3 - /* Nexthop value. */ - union - { - struct in_addr ipv4; - char *ifname; - } gate; - /* bit flags */ u_char flags; /* @@ -136,6 +136,10 @@ struct static_ipv6 struct static_ipv6 *prev; struct static_ipv6 *next; + /* Nexthop value. */ + struct in6_addr ipv6; + char *ifname; + /* Administrative distance. */ u_char distance; @@ -144,11 +148,6 @@ struct static_ipv6 #define STATIC_IPV6_GATEWAY 1 #define STATIC_IPV6_GATEWAY_IFNAME 2 #define STATIC_IPV6_IFNAME 3 - - /* Nexthop value. */ - struct in6_addr ipv6; - char *ifname; - /* bit flags */ u_char flags; /* @@ -180,22 +179,24 @@ struct nexthop /* Interface index. */ char *ifname; unsigned int ifindex; + + /* Nexthop address or interface name. */ + union g_addr gate; + + unsigned int rifindex; + union g_addr rgate; + union g_addr src; - enum nexthop_types_t type; +/* Really enum nexthop_types_t but safe space */ + u_char type; u_char flags; #define NEXTHOP_FLAG_ACTIVE (1 << 0) /* This nexthop is alive. */ #define NEXTHOP_FLAG_FIB (1 << 1) /* FIB nexthop. */ #define NEXTHOP_FLAG_RECURSIVE (1 << 2) /* Recursive nexthop. */ - /* Nexthop address or interface name. */ - union g_addr gate; - /* Recursive lookup nexthop. */ u_char rtype; - unsigned int rifindex; - union g_addr rgate; - union g_addr src; }; /* Routing table instance. */ diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c index 0bf2d9eb..3e8048ba 100644 --- a/zebra/rt_netlink.c +++ b/zebra/rt_netlink.c @@ -41,6 +41,7 @@ #include "zebra/redistribute.h" #include "zebra/interface.h" #include "zebra/debug.h" +#include <stddef.h> /* Socket interface to kernel */ struct nlsock @@ -52,7 +53,7 @@ struct nlsock } netlink = { -1, 0, {0}, "netlink-listen"}, /* kernel messages */ netlink_cmd = { -1, 0, {0}, "netlink-cmd"}; /* command channel */ -struct message nlmsg_str[] = { +static struct message nlmsg_str[] = { {RTM_NEWROUTE, "RTM_NEWROUTE"}, {RTM_DELROUTE, "RTM_DELROUTE"}, {RTM_GETROUTE, "RTM_GETROUTE"}, @@ -65,7 +66,7 @@ struct message nlmsg_str[] = { {0, NULL} }; -const char *nexthop_types_desc[] = +static const char *nexthop_types_desc[] = { "none", "Directly connected", @@ -86,31 +87,43 @@ extern struct zebra_privs_t zserv_privs; extern u_int32_t nl_rcvbufsize; -/* Note: on netlink systems, there should be a 1-to-1 mapping between interface - names and ifindex values. */ -static void -set_ifindex(struct interface *ifp, unsigned int ifi_index) +static int +netlink_recvbuf (struct nlsock *nl, uint32_t newsize) { - struct interface *oifp; + u_int32_t oldsize; + socklen_t newlen = sizeof(newsize); + socklen_t oldlen = sizeof(oldsize); + int ret; - if (((oifp = if_lookup_by_index(ifi_index)) != NULL) && (oifp != ifp)) + ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen); + if (ret < 0) { - if (ifi_index == IFINDEX_INTERNAL) - zlog_err("Netlink is setting interface %s ifindex to reserved " - "internal value %u", ifp->name, ifi_index); - else - { - if (IS_ZEBRA_DEBUG_KERNEL) - zlog_debug("interface index %d was renamed from %s to %s", - ifi_index, oifp->name, ifp->name); - if (if_is_up(oifp)) - zlog_err("interface rename detected on up interface: index %d " - "was renamed from %s to %s, results are uncertain!", - ifi_index, oifp->name, ifp->name); - if_delete_update(oifp); - } + zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name, + safe_strerror (errno)); + return -1; } - ifp->ifindex = ifi_index; + + ret = setsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize, + sizeof(nl_rcvbufsize)); + if (ret < 0) + { + zlog (NULL, LOG_ERR, "Can't set %s receive buffer size: %s", nl->name, + safe_strerror (errno)); + return -1; + } + + ret = getsockopt(nl->sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen); + if (ret < 0) + { + zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name, + safe_strerror (errno)); + return -1; + } + + zlog (NULL, LOG_INFO, + "Setting netlink socket receive buffer size: %u -> %u", + oldsize, newsize); + return 0; } /* Make socket for Linux netlink interface. */ @@ -131,56 +144,6 @@ netlink_socket (struct nlsock *nl, unsigned long groups) return -1; } - ret = fcntl (sock, F_SETFL, O_NONBLOCK); - if (ret < 0) - { - zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", nl->name, - safe_strerror (errno)); - close (sock); - return -1; - } - - /* Set receive buffer size if it's set from command line */ - if (nl_rcvbufsize) - { - u_int32_t oldsize, oldlen; - u_int32_t newsize, newlen; - - oldlen = sizeof(oldsize); - newlen = sizeof(newsize); - - ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &oldsize, &oldlen); - if (ret < 0) - { - zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name, - safe_strerror (errno)); - close (sock); - return -1; - } - - ret = setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &nl_rcvbufsize, - sizeof(nl_rcvbufsize)); - if (ret < 0) - { - zlog (NULL, LOG_ERR, "Can't set %s receive buffer size: %s", nl->name, - safe_strerror (errno)); - close (sock); - return -1; - } - - ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &newsize, &newlen); - if (ret < 0) - { - zlog (NULL, LOG_ERR, "Can't get %s receive buffer size: %s", nl->name, - safe_strerror (errno)); - close (sock); - return -1; - } - - zlog (NULL, LOG_INFO, - "Setting netlink socket receive buffer size: %u -> %u", - oldsize, newsize); - } memset (&snl, 0, sizeof snl); snl.nl_family = AF_NETLINK; @@ -222,41 +185,6 @@ netlink_socket (struct nlsock *nl, unsigned long groups) return ret; } -int -set_netlink_blocking (struct nlsock *nl, int *flags) -{ - - /* Change socket flags for blocking I/O. */ - if ((*flags = fcntl (nl->sock, F_GETFL, 0)) < 0) - { - zlog (NULL, LOG_ERR, "%s:%i F_GETFL error: %s", - __FUNCTION__, __LINE__, safe_strerror (errno)); - return -1; - } - *flags &= ~O_NONBLOCK; - if (fcntl (nl->sock, F_SETFL, *flags) < 0) - { - zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s", - __FUNCTION__, __LINE__, safe_strerror (errno)); - return -1; - } - return 0; -} - -int -set_netlink_nonblocking (struct nlsock *nl, int *flags) -{ - /* Restore socket flags for nonblocking I/O */ - *flags |= O_NONBLOCK; - if (fcntl (nl->sock, F_SETFL, *flags) < 0) - { - zlog (NULL, LOG_ERR, "%s:%i F_SETFL error: %s", - __FUNCTION__, __LINE__, safe_strerror (errno)); - return -1; - } - return 0; -} - /* Get type specified information from netlink. */ static int netlink_request (int family, int type, struct nlsock *nl) @@ -286,7 +214,7 @@ netlink_request (int family, int type, struct nlsock *nl) req.nlh.nlmsg_len = sizeof req; req.nlh.nlmsg_type = type; req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST; - req.nlh.nlmsg_pid = 0; + req.nlh.nlmsg_pid = nl->snl.nl_pid; req.nlh.nlmsg_seq = ++nl->seq; req.g.rtgen_family = family; @@ -328,30 +256,23 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), while (1) { - char buf[4096]; + //increased from 4096 to 32768 as recvmsg overrun error + char buf[32768]; struct iovec iov = { buf, sizeof buf }; struct sockaddr_nl snl; struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 }; struct nlmsghdr *h; - int save_errno; - - if (zserv_privs.change (ZPRIVS_RAISE)) - zlog (NULL, LOG_ERR, "Can't raise privileges"); status = recvmsg (nl->sock, &msg, 0); - save_errno = errno; - - if (zserv_privs.change (ZPRIVS_LOWER)) - zlog (NULL, LOG_ERR, "Can't lower privileges"); - if (status < 0) { - if (save_errno == EINTR) + if (errno == EINTR) continue; - if (save_errno == EWOULDBLOCK || save_errno == EAGAIN) + if (errno == EWOULDBLOCK || errno == EAGAIN) break; + zlog (NULL, LOG_ERR, "%s recvmsg overrun: %s", - nl->name, safe_strerror(save_errno)); + nl->name, safe_strerror(errno)); continue; } @@ -368,13 +289,6 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), return -1; } - /* JF: Ignore messages that aren't from the kernel */ - if ( snl.nl_pid != 0 ) - { - zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl.nl_pid ); - continue; - } - for (h = (struct nlmsghdr *) buf; NLMSG_OK (h, (unsigned int) status); h = NLMSG_NEXT (h, status)) { @@ -386,6 +300,8 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), if (h->nlmsg_type == NLMSG_ERROR) { struct nlmsgerr *err = (struct nlmsgerr *) NLMSG_DATA (h); + int errnum = err->error; + int msg_type = err->msg.nlmsg_type; /* If the error field is zero, then this is an ACK */ if (err->error == 0) @@ -414,27 +330,24 @@ netlink_parse_info (int (*filter) (struct sockaddr_nl *, struct nlmsghdr *), return -1; } - /* Deal with Error Noise - MAG */ - { - int loglvl = LOG_ERR; - int errnum = err->error; - int msg_type = err->msg.nlmsg_type; - - if (nl == &netlink_cmd - && (-errnum == ENODEV || -errnum == ESRCH) - && (msg_type == RTM_NEWROUTE || msg_type == RTM_DELROUTE)) - loglvl = LOG_DEBUG; - - zlog (NULL, loglvl, "%s error: %s, type=%s(%u), " - "seq=%u, pid=%u", - nl->name, safe_strerror (-errnum), - lookup (nlmsg_str, msg_type), - msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid); - } - /* - ret = -1; - continue; - */ + /* Deal with errors that occur because of races in link handling */ + if (nl == &netlink_cmd + && ((msg_type == RTM_DELROUTE && + (-errnum == ENODEV || -errnum == ESRCH)) + || (msg_type == RTM_NEWROUTE && -errnum == EEXIST))) + { + if (IS_ZEBRA_DEBUG_KERNEL) + zlog_debug ("%s: error: %s type=%s(%u), seq=%u, pid=%u", + nl->name, safe_strerror (-errnum), + lookup (nlmsg_str, msg_type), + msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid); + return 0; + } + + zlog_err ("%s error: %s, type=%s(%u), seq=%u, pid=%u", + nl->name, safe_strerror (-errnum), + lookup (nlmsg_str, msg_type), + msg_type, err->msg.nlmsg_seq, err->msg.nlmsg_pid); return -1; } @@ -493,7 +406,7 @@ netlink_parse_rtattr (struct rtattr **tb, int max, struct rtattr *rta, /* Called from interface_lookup_netlink(). This function is only used during bootstrap. */ -int +static int netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; @@ -527,12 +440,26 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) #endif /* IFLA_WIRELESS */ if (tb[IFLA_IFNAME] == NULL) - return -1; + { + zlog_err("%s: missing interface name in message", __func__); + return -1; + } name = (char *) RTA_DATA (tb[IFLA_IFNAME]); + if (ifi->ifi_index == IFINDEX_INTERNAL) + { + zlog_err("%s: reserved ifindex", __func__); + return -1; + } + /* Add interface. */ - ifp = if_get_by_name (name); - set_ifindex(ifp, ifi->ifi_index); + ifp = if_lookup_by_index(ifi->ifi_index); + if (!ifp) + { + ifp = if_create(name, strlen(name)); + ifp->ifindex = ifi->ifi_index; + } + strncpy(ifp->name, name, INTERFACE_NAMSIZ); ifp->flags = ifi->ifi_flags & 0x0000fffff; ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); ifp->metric = 1; @@ -570,7 +497,7 @@ netlink_interface (struct sockaddr_nl *snl, struct nlmsghdr *h) } /* Lookup interface IPv4/IPv6 address. */ -int +static int netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; @@ -705,7 +632,7 @@ netlink_interface_addr (struct sockaddr_nl *snl, struct nlmsghdr *h) } /* Looking up routing table by netlink interface. */ -int +static int netlink_routing_table (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; @@ -822,7 +749,7 @@ struct message rtproto_str[] = { }; /* Routing information change from the kernel. */ -int +static int netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; @@ -963,7 +890,7 @@ netlink_route_change (struct sockaddr_nl *snl, struct nlmsghdr *h) return 0; } -int +static int netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) { int len; @@ -1001,21 +928,38 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) #endif /* IFLA_WIRELESS */ if (tb[IFLA_IFNAME] == NULL) - return -1; + { + zlog_err("%s: missing interface name", __func__); + return -1; + } name = (char *) RTA_DATA (tb[IFLA_IFNAME]); /* Add interface. */ if (h->nlmsg_type == RTM_NEWLINK) { - ifp = if_lookup_by_name (name); + unsigned long new_flags = ifi->ifi_flags & 0x0000fffff; + ifp = if_lookup_by_index (ifi->ifi_index); + + if (ifp && strcmp(ifp->name, name) != 0) + { + zlog_info("interface index %d was renamed from %s to %s", + ifi->ifi_index, ifp->name, name); + + strncpy(ifp->name, name, INTERFACE_NAMSIZ); + } if (ifp == NULL || !CHECK_FLAG (ifp->status, ZEBRA_INTERFACE_ACTIVE)) { if (ifp == NULL) - ifp = if_get_by_name (name); + { + ifp = if_create(name, strlen(name)); + ifp->ifindex = ifi->ifi_index; + } - set_ifindex(ifp, ifi->ifi_index); - ifp->flags = ifi->ifi_flags & 0x0000fffff; + zlog_info ("interface %s index %d %s added.", + name, ifi->ifi_index, if_flag_dump(new_flags)); + + ifp->flags = new_flags; ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); ifp->metric = 1; @@ -1025,30 +969,35 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) else { /* Interface status change. */ - set_ifindex(ifp, ifi->ifi_index); ifp->mtu6 = ifp->mtu = *(int *) RTA_DATA (tb[IFLA_MTU]); ifp->metric = 1; - if (if_is_operative (ifp)) - { - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (!if_is_operative (ifp)) - if_down (ifp); + if (new_flags != ifp->flags) + { + zlog_info ("interface %s index %d changed %s.", + name, ifi->ifi_index, if_flag_dump(new_flags)); + + if (if_is_operative (ifp)) + { + ifp->flags = new_flags; + if (!if_is_operative (ifp)) + if_down (ifp); + else + /* Must notify client daemons of new interface status. */ + zebra_interface_up_update (ifp); + } else - /* Must notify client daemons of new interface status. */ - zebra_interface_up_update (ifp); - } - else - { - ifp->flags = ifi->ifi_flags & 0x0000fffff; - if (if_is_operative (ifp)) - if_up (ifp); - } + { + ifp->flags = new_flags; + if (if_is_operative (ifp)) + if_up (ifp); + } + } } } else { - /* RTM_DELLINK. */ + // RTM_DELLINK. ifp = if_lookup_by_name (name); if (ifp == NULL) @@ -1057,16 +1006,25 @@ netlink_link_change (struct sockaddr_nl *snl, struct nlmsghdr *h) name); return 0; } + else + zlog_info ("interface %s index %d deleted.", + name, ifi->ifi_index); if_delete_update (ifp); } - return 0; } -int +static int netlink_information_fetch (struct sockaddr_nl *snl, struct nlmsghdr *h) { + /* JF: Ignore messages that aren't from the kernel */ + if ( snl->nl_pid != 0 ) + { + zlog ( NULL, LOG_ERR, "Ignoring message from pid %u", snl->nl_pid ); + return 0; + } + switch (h->nlmsg_type) { case RTM_NEWROUTE: @@ -1099,18 +1057,6 @@ int interface_lookup_netlink (void) { int ret; - int flags; - int snb_ret; - - /* - * Change netlink socket flags to blocking to ensure we get - * a reply via nelink_parse_info - */ - snb_ret = set_netlink_blocking (&netlink_cmd, &flags); - if (snb_ret < 0) - zlog (NULL, LOG_WARNING, - "%s:%i Warning: Could not set netlink socket to blocking.", - __FUNCTION__, __LINE__); /* Get interface information. */ ret = netlink_request (AF_PACKET, RTM_GETLINK, &netlink_cmd); @@ -1138,9 +1084,6 @@ interface_lookup_netlink (void) return ret; #endif /* HAVE_IPV6 */ - /* restore socket flags */ - if (snb_ret == 0) - set_netlink_nonblocking (&netlink_cmd, &flags); return 0; } @@ -1150,18 +1093,6 @@ int netlink_route_read (void) { int ret; - int flags; - int snb_ret; - - /* - * Change netlink socket flags to blocking to ensure we get - * a reply via nelink_parse_info - */ - snb_ret = set_netlink_blocking (&netlink_cmd, &flags); - if (snb_ret < 0) - zlog (NULL, LOG_WARNING, - "%s:%i Warning: Could not set netlink socket to blocking.", - __FUNCTION__, __LINE__); /* Get IPv4 routing table. */ ret = netlink_request (AF_INET, RTM_GETROUTE, &netlink_cmd); @@ -1181,15 +1112,12 @@ netlink_route_read (void) return ret; #endif /* HAVE_IPV6 */ - /* restore flags */ - if (snb_ret == 0) - set_netlink_nonblocking (&netlink_cmd, &flags); return 0; } /* Utility function comes from iproute2. Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */ -int +static int addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen) { int len; @@ -1209,7 +1137,7 @@ addattr_l (struct nlmsghdr *n, int maxlen, int type, void *data, int alen) return 0; } -int +static int rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen) { int len; @@ -1231,7 +1159,7 @@ rta_addattr_l (struct rtattr *rta, int maxlen, int type, void *data, int alen) /* Utility function comes from iproute2. Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> */ -int +static int addattr32 (struct nlmsghdr *n, int maxlen, int type, int data) { int len; @@ -1259,15 +1187,13 @@ netlink_talk_filter (struct sockaddr_nl *snl, struct nlmsghdr *h) } /* sendmsg() to netlink socket then recvmsg(). */ -int +static int netlink_talk (struct nlmsghdr *n, struct nlsock *nl) { int status; struct sockaddr_nl snl; struct iovec iov = { (void *) n, n->nlmsg_len }; struct msghdr msg = { (void *) &snl, sizeof snl, &iov, 1, NULL, 0, 0 }; - int flags = 0; - int snb_ret; int save_errno; memset (&snl, 0, sizeof snl); @@ -1298,31 +1224,16 @@ netlink_talk (struct nlmsghdr *n, struct nlsock *nl) return -1; } - /* - * Change socket flags for blocking I/O. - * This ensures we wait for a reply in netlink_parse_info(). - */ - snb_ret = set_netlink_blocking (nl, &flags); - if (snb_ret < 0) - zlog (NULL, LOG_WARNING, - "%s:%i Warning: Could not set netlink socket to blocking.", - __FUNCTION__, __LINE__); /* * Get reply from netlink socket. * The reply should either be an acknowlegement or an error. */ - status = netlink_parse_info (netlink_talk_filter, nl); - - /* Restore socket flags for nonblocking I/O */ - if (snb_ret == 0) - set_netlink_nonblocking (nl, &flags); - - return status; + return netlink_parse_info (netlink_talk_filter, nl); } /* Routing table change via netlink interface. */ -int +static int netlink_route (int cmd, int family, void *dest, int length, void *gate, int index, int zebra_flags, int table) { @@ -1397,7 +1308,7 @@ netlink_route (int cmd, int family, void *dest, int length, void *gate, } /* Routing table change via netlink interface. */ -int +static int netlink_route_multipath (int cmd, struct prefix *p, struct rib *rib, int family) { @@ -1860,7 +1771,7 @@ kernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate, #endif /* HAVE_IPV6 */ /* Interface address modification. */ -int +static int netlink_address (int cmd, int family, struct interface *ifp, struct connected *ifc) { @@ -1925,7 +1836,7 @@ kernel_address_delete_ipv4 (struct interface *ifp, struct connected *ifc) extern struct thread_master *master; /* Kernel route reflection. */ -int +static int kernel_read (struct thread *thread) { int ret; @@ -1938,45 +1849,26 @@ kernel_read (struct thread *thread) return 0; } -/* Filter out messages from self that occur on listener socket */ -static void netlink_install_filter (int sock) +/* Filter out messages from self that occur on listener socket, + caused by our actions on the command socket + */ +static void netlink_install_filter (int sock, __u32 pid) { - /* - * Filter is equivalent to netlink_route_change - * - * if (h->nlmsg_type == RTM_DELROUTE || h->nlmsg_type == RTM_NEWROUTE) { - * if (rtm->rtm_type != RTM_UNICAST) - * return 0; - * if (rtm->rtm_flags & RTM_F_CLONED) - * return 0; - * if (rtm->rtm_protocol == RTPROT_REDIRECT) - * return 0; - * if (rtm->rtm_protocol == RTPROT_KERNEL) - * return 0; - * if (rtm->rtm_protocol == RTPROT_ZEBRA && h->nlmsg_type == RTM_NEWROUTE) - * return 0; - * } - * return 0xffff; - */ struct sock_filter filter[] = { - /* 0*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), - /* 1*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 1, 0), - /* 2*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 0, 11), - /* 3*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, - sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_type)), - /* 4*/ BPF_JUMP(BPF_JMP|BPF_B, RTN_UNICAST, 0, 8), - /* 5*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, - sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_flags)), - /* 6*/ BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, RTM_F_CLONED, 6, 0), - /* 7*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_B, - sizeof(struct nlmsghdr) + offsetof(struct rtmsg, rtm_protocol)), - /* 8*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_REDIRECT, 4, 0), - /* 9*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_KERNEL, 0, 1), - /*10*/ BPF_JUMP(BPF_JMP+ BPF_B, RTPROT_ZEBRA, 0, 3), - /*11*/ BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), - /*12*/ BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 0, 1), - /*13*/ BPF_STMT(BPF_RET|BPF_K, 0), /* drop */ - /*14*/ BPF_STMT(BPF_RET|BPF_K, 0xffff), /* keep */ + /* 0: ldh [4] */ + BPF_STMT(BPF_LD|BPF_ABS|BPF_H, offsetof(struct nlmsghdr, nlmsg_type)), + /* 1: jeq 0x18 jt 3 jf 6 */ + BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_NEWROUTE), 1, 0), + /* 2: jeq 0x19 jt 3 jf 6 */ + BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htons(RTM_DELROUTE), 0, 3), + /* 3: ldw [12] */ + BPF_STMT(BPF_LD|BPF_ABS|BPF_W, offsetof(struct nlmsghdr, nlmsg_pid)), + /* 4: jeq XX jt 5 jf 6 */ + BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, htonl(pid), 0, 1), + /* 5: ret 0 (skip) */ + BPF_STMT(BPF_RET|BPF_K, 0), + /* 6: ret 0xffff (keep) */ + BPF_STMT(BPF_RET|BPF_K, 0xffff), }; struct sock_fprog prog = { @@ -2005,7 +1897,16 @@ kernel_init (void) /* Register kernel socket. */ if (netlink.sock > 0) { - netlink_install_filter (netlink.sock); + /* Only want non-blocking on the netlink event socket */ + if (fcntl (netlink.sock, F_SETFL, O_NONBLOCK) < 0) + zlog (NULL, LOG_ERR, "Can't set %s socket flags: %s", netlink.name, + safe_strerror (errno)); + + /* Set receive buffer size if it's set from command line */ + if (nl_rcvbufsize) + netlink_recvbuf (&netlink, nl_rcvbufsize); + + netlink_install_filter (netlink.sock, netlink_cmd.snl.nl_pid); thread_add_read (zebrad.master, kernel_read, NULL, netlink.sock); } } diff --git a/zebra/rtadv.c b/zebra/rtadv.c index 4bdb83d5..0097e28f 100644 --- a/zebra/rtadv.c +++ b/zebra/rtadv.c @@ -90,11 +90,13 @@ rtadv_new (void) return new; } +#if 0 static void rtadv_free (struct rtadv *rtadv) { XFREE (MTYPE_TMP, rtadv); } +#endif static int rtadv_recv_packet (int sock, u_char *buf, int buflen, @@ -451,7 +453,7 @@ rtadv_read (struct thread *thread) int len; u_char buf[RTADV_MSG_SIZE]; struct sockaddr_in6 from; - unsigned int ifindex; + unsigned int ifindex = 0; int hoplimit = -1; sock = THREAD_FD (thread); diff --git a/zebra/rtread_netlink.c b/zebra/rtread_netlink.c index 0b255a53..44715d94 100644 --- a/zebra/rtread_netlink.c +++ b/zebra/rtread_netlink.c @@ -21,11 +21,9 @@ */ #include <zebra.h> +extern void netlink_route_read (void); -/* Extern from rt_netlink.c */ -void netlink_route_read (); - -void route_read () +void route_read (void) { netlink_route_read (); } diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c index 4cb72ba8..545481d1 100644 --- a/zebra/zebra_rib.c +++ b/zebra/zebra_rib.c @@ -51,7 +51,7 @@ extern struct zebra_t zebrad; int rib_process_hold_time = 10; /* Each route type's string and default distance value. */ -struct +static const struct { int key; int distance; @@ -70,7 +70,7 @@ struct }; /* Vector for routing table. */ -vector vrf_vector; +static vector vrf_vector; /* Allocate new VRF. */ static struct vrf * @@ -93,6 +93,7 @@ vrf_alloc (const char *name) return vrf; } +#if 0 /* Free VRF. */ static void vrf_free (struct vrf *vrf) @@ -101,6 +102,7 @@ vrf_free (struct vrf *vrf) XFREE (MTYPE_VRF_NAME, vrf->name); XFREE (MTYPE_VRF, vrf); } +#endif /* Lookup VRF by identifier. */ struct vrf * @@ -109,6 +111,7 @@ vrf_lookup (u_int32_t id) return vector_lookup (vrf_vector, id); } +#if 0 /* Lookup VRF by name. */ static struct vrf * vrf_lookup_by_name (char *name) @@ -122,6 +125,7 @@ vrf_lookup_by_name (char *name) return vrf; return NULL; } +#endif /* Initialize VRF. */ static void @@ -336,6 +340,35 @@ nexthop_blackhole_add (struct rib *rib) return nexthop; } +static int +nexthop_isactive(const struct nexthop *nexthop) +{ + struct interface *ifp; + + switch(nexthop->type) + { + case NEXTHOP_TYPE_IPV4: + case NEXTHOP_TYPE_IPV6: + if (nexthop->ifindex == 0) + return 0; + /* fall through */ + case NEXTHOP_TYPE_IFINDEX: + case NEXTHOP_TYPE_IPV4_IFINDEX: + case NEXTHOP_TYPE_IPV6_IFINDEX: + ifp = if_lookup_by_index (nexthop->ifindex); + return (ifp && if_is_operative (ifp)); + + case NEXTHOP_TYPE_IFNAME: + case NEXTHOP_TYPE_IPV4_IFNAME: + case NEXTHOP_TYPE_IPV6_IFNAME: + ifp = if_lookup_by_name(nexthop->ifname); + return (ifp && if_is_operative (ifp)); + + default: + return 1; + } +} + /* If force flag is not set, do not modify falgs at all for uninstall the route from FIB. */ static int @@ -348,11 +381,12 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, struct rib *match; struct nexthop *newhop; - if (nexthop->type == NEXTHOP_TYPE_IPV4) - nexthop->ifindex = 0; - if (set) - UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); + { + UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE); + if (nexthop->type == NEXTHOP_TYPE_IPV4) + nexthop->ifindex = 0; + } /* Make lookup prefix. */ memset (&p, 0, sizeof (struct prefix_ipv4)); @@ -376,8 +410,12 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, /* Pick up selected route. */ for (match = rn->info; match; match = match->next) - if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - break; + { + if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) + continue; + if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) + break; + } /* If there is no selected route or matched route is EGP, go up tree. */ @@ -396,16 +434,32 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, { /* Directly point connected route. */ newhop = match->nexthop; - if (newhop && nexthop->type == NEXTHOP_TYPE_IPV4) - nexthop->ifindex = newhop->ifindex; - - return 1; + if (!newhop) + return 0; /* dead route */ + + if (nexthop_isactive (newhop)) + { + if (set) + { + if (nexthop->type == NEXTHOP_TYPE_IPV4) + nexthop->ifindex = newhop->ifindex; + } + else + { + if (nexthop->ifindex != newhop->ifindex || + CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + } + return 1; + } } - else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL)) + else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL) || + match->type == ZEBRA_ROUTE_STATIC) { for (newhop = match->nexthop; newhop; newhop = newhop->next) if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB) - && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE)) + && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE) + && nexthop_isactive (newhop)) { if (set) { @@ -418,7 +472,15 @@ nexthop_active_ipv4 (struct rib *rib, struct nexthop *nexthop, int set, || newhop->type == NEXTHOP_TYPE_IFNAME || newhop->type == NEXTHOP_TYPE_IPV4_IFINDEX) nexthop->rifindex = newhop->ifindex; + if (nexthop->type == NEXTHOP_TYPE_IPV4) + nexthop->ifindex = newhop->ifindex; } + else if (! CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE) + || newhop->ifindex != nexthop->ifindex + || nexthop->gate.ipv4.s_addr != newhop->gate.ipv4.s_addr) + SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + + return 1; } return 0; @@ -473,8 +535,12 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, /* Pick up selected route. */ for (match = rn->info; match; match = match->next) - if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - break; + { + if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) + continue; + if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) + break; + } /* If there is no selected route or matched route is EGP, go up tree. */ @@ -493,17 +559,35 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, { /* Directly point connected route. */ newhop = match->nexthop; + if (!newhop) + return 0; /* dead route */ - if (newhop && nexthop->type == NEXTHOP_TYPE_IPV6) + /* recursive route, remember index */ + if (nexthop->type == NEXTHOP_TYPE_IPV6) nexthop->ifindex = newhop->ifindex; - return 1; + if (nexthop_isactive (newhop)) + { + if (set) + { + if (nexthop->type == NEXTHOP_TYPE_IPV6) + nexthop->ifindex = newhop->ifindex; + } + else + { + if (nexthop->ifindex != newhop->ifindex || + CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE)) + SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + } + return 1; + } } else if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_INTERNAL)) { for (newhop = match->nexthop; newhop; newhop = newhop->next) if (CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_FIB) - && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE)) + && ! CHECK_FLAG (newhop->flags, NEXTHOP_FLAG_RECURSIVE) + && nexthop_isactive (newhop)) { if (set) { @@ -518,7 +602,15 @@ nexthop_active_ipv6 (struct rib *rib, struct nexthop *nexthop, int set, || newhop->type == NEXTHOP_TYPE_IPV6_IFINDEX || newhop->type == NEXTHOP_TYPE_IPV6_IFNAME) nexthop->rifindex = newhop->ifindex; + if (nexthop->type == NEXTHOP_TYPE_IPV6) + nexthop->ifindex = newhop->ifindex; } + else if (! CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE) + || newhop->ifindex != nexthop->ifindex + || !IPV6_ADDR_SAME(&nexthop->gate.ipv6, + &newhop->gate.ipv4)) + SET_FLAG (rib->flags, ZEBRA_FLAG_CHANGED); + return 1; } return 0; @@ -560,8 +652,13 @@ rib_match_ipv4 (struct in_addr addr) /* Pick up selected route. */ for (match = rn->info; match; match = match->next) - if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - break; + { + if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) + continue; + if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) + break; + } + /* If there is no selected route or matched route is EGP, go up tree. */ @@ -615,8 +712,12 @@ rib_lookup_ipv4 (struct prefix_ipv4 *p) /* Pick up selected route. */ for (match = rn->info; match; match = match->next) - if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - break; + { + if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) + continue; + if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) + break; + } if (! match || match->type == ZEBRA_ROUTE_BGP) return NULL; @@ -668,12 +769,12 @@ rib_lookup_ipv4_route (struct prefix_ipv4 *p, union sockunion * qgate) /* Find out if a "selected" RR for the discovered RIB entry exists ever. */ for (match = rn->info; match; match = match->next) - { - if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) - continue; - if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - break; - } + { + if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) + continue; + if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) + break; + } /* None such found :( */ if (!match) @@ -735,8 +836,12 @@ rib_match_ipv6 (struct in6_addr *addr) /* Pick up selected route. */ for (match = rn->info; match; match = match->next) - if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) - break; + { + if (CHECK_FLAG (match->status, RIB_ENTRY_REMOVED)) + continue; + if (CHECK_FLAG (match->flags, ZEBRA_FLAG_SELECTED)) + break; + } /* If there is no selected route or matched route is EGP, go up tree. */ @@ -795,7 +900,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, { case NEXTHOP_TYPE_IFINDEX: ifp = if_lookup_by_index (nexthop->ifindex); - if (ifp && if_is_operative(ifp)) + if (ifp && if_is_operative (ifp)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); @@ -804,7 +909,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, family = AFI_IP6; case NEXTHOP_TYPE_IFNAME: ifp = if_lookup_by_name (nexthop->ifname); - if (ifp && if_is_operative(ifp)) + if (ifp && if_is_operative (ifp)) { if (set) nexthop->ifindex = ifp->ifindex; @@ -838,7 +943,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, if (IN6_IS_ADDR_LINKLOCAL (&nexthop->gate.ipv6)) { ifp = if_lookup_by_index (nexthop->ifindex); - if (ifp && if_is_operative(ifp)) + if (ifp && if_is_operative (ifp)) SET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); else UNSET_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); @@ -867,8 +972,7 @@ nexthop_active_check (struct route_node *rn, struct rib *rib, return CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE); rmap = 0; - if (rib->type >= 0 && rib->type < ZEBRA_ROUTE_MAX && - proto_rm[family][rib->type]) + if (rib->type < ZEBRA_ROUTE_MAX && proto_rm[family][rib->type]) rmap = route_map_lookup_by_name (proto_rm[family][rib->type]); if (!rmap && proto_rm[family][ZEBRA_ROUTE_MAX]) rmap = route_map_lookup_by_name (proto_rm[family][ZEBRA_ROUTE_MAX]); @@ -1633,7 +1737,7 @@ void rib_dump (const char * func, const struct prefix_ipv4 * p, const struct rib zlog_debug ("%s: dumping RIB entry %p for %s/%d", func, rib, straddr1, p->prefixlen); zlog_debug ( - "%s: refcnt == %lu, uptime == %u, type == %u, table == %d", + "%s: refcnt == %lu, uptime == %lu, type == %u, table == %d", func, rib->refcnt, rib->uptime, @@ -2219,6 +2323,9 @@ static_add_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, /* Install into rib. */ static_install_ipv4 (p, si); + /* Scan for possible recursive route changes */ + rib_update(); + return 1; } @@ -2283,6 +2390,9 @@ static_delete_ipv4 (struct prefix *p, struct in_addr *gate, const char *ifname, route_unlock_node (rn); + /* Scan for possible recursive route changes */ + rib_update(); + return 1; } @@ -2765,6 +2875,8 @@ static_add_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, /* Install into rib. */ static_install_ipv6 (p, si); + /* Scan for possible recursive route changes */ + rib_update(); return 1; } @@ -2818,6 +2930,7 @@ static_delete_ipv6 (struct prefix *p, u_char type, struct in6_addr *gate, XFREE (0, si->ifname); XFREE (MTYPE_STATIC_IPV6, si); + rib_update(); return 1; } #endif /* HAVE_IPV6 */ @@ -2842,6 +2955,7 @@ rib_update (void) rib_queue_add (&zebrad, rn); } +#if 0 /* Interface goes up. */ static void rib_if_up (struct interface *ifp) @@ -2855,6 +2969,7 @@ rib_if_down (struct interface *ifp) { rib_update (); } +#endif /* Remove all routes which comes from non main table. */ static void |