diff options
-rw-r--r-- | zebra/ChangeLog | 28 | ||||
-rw-r--r-- | zebra/connected.c | 158 | ||||
-rw-r--r-- | zebra/connected.h | 5 | ||||
-rw-r--r-- | zebra/interface.c | 8 | ||||
-rw-r--r-- | zebra/kernel_socket.c | 25 |
5 files changed, 124 insertions, 100 deletions
diff --git a/zebra/ChangeLog b/zebra/ChangeLog index 61b8b41a..6225ce1a 100644 --- a/zebra/ChangeLog +++ b/zebra/ChangeLog @@ -1,3 +1,31 @@ +2005-09-12 Paul Jakma <paul.jakma@sun.com> + + * (general) RTM_CHANGE and implicit withdraw on RTM_NEWADDR + support. + * connected.c: (connected_withdraw) new function. withdraw a + connected subnet address set from zebra, and pass information + along to clients. + (connected_announce) similar, but to announce a new connected + subnet address set. + (connected_check_ipv4) renamed to connected_check, as its + AFI independent. + (connected_add_ipv{4,6}) Remove the connected address announce + stuff, use connected_announce instead. + If connected_check indicates address is already present, + treat it as an implicit withdraw of the existing address, ie + remove the old address details and replace with the new + details. + (connected_delete_ipv{4,6}) Use connected_withdraw. + (connected_check_ipv6) deleted in favour of connected_check. + * connected.h: Rename connected_check_ipv4 to connected_check. + delete connected_check_ipv6. + * interface.c: Use connected_check rather than the AFI specific + symbols. + * kernel_socket.c: (rtm_read) RTM_CHANGE support. Create a + rib delete event for the existing route, before adding route + again. + (kernel_read) we can handle RTM_CHANGE now. + 2005-08-27 Hasso Tepper <hasso at quagga.net> * zebra_rib.c, rib.h: Add distance and metric arguments to the diff --git a/zebra/connected.c b/zebra/connected.c index 68269088..7599d24d 100644 --- a/zebra/connected.c +++ b/zebra/connected.c @@ -35,9 +35,63 @@ #include "zebra/interface.h" #include "zebra/connected.h" +/* withdraw a connected address */ +static void +connected_withdraw (struct connected *ifc) +{ + if (! ifc) + return; + + /* Update interface address information to protocol daemon. */ + if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) + { + zebra_interface_address_delete_update (ifc->ifp, ifc); + + if_subnet_delete (ifc->ifp, ifc); + + if (ifc->address->family == AF_INET) + connected_down_ipv4 (ifc->ifp, ifc); + else + connected_down_ipv6 (ifc->ifp, ifc); + + UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); + } + + listnode_delete (ifc->ifp->connected, ifc); + connected_free (ifc); +} + +static void +connected_announce (struct interface *ifp, struct connected *ifc) +{ + if (!ifc) + return; + + listnode_add (ifp->connected, ifc); + + /* Update interface address information to protocol daemon. */ + if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) + { + if (ifc->address->family == AF_INET) + if_subnet_add (ifp, ifc); + + SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); + + zebra_interface_address_add_update (ifp, ifc); + + if (if_is_up(ifp)) + { + if (ifc->address->family == AF_INET) + connected_up_ipv4 (ifp, ifc); + else + connected_up_ipv6 (ifp, ifc); + } + } +} + /* If same interface address is already exist... */ struct connected * -connected_check_ipv4 (struct interface *ifp, struct prefix *p) +connected_check (struct interface *ifp, struct prefix *p) { struct connected *ifc; struct listnode *node; @@ -106,7 +160,7 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, p->prefix = *addr; p->prefixlen = prefixlen; ifc->address = (struct prefix *) p; - + /* If there is broadcast or pointopoint address. */ if (broad) { @@ -163,29 +217,10 @@ connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, ifc->label = strdup (label); /* Check same connected route. */ - current = connected_check_ipv4 (ifp, (struct prefix *) ifc->address); - if (current) - { - connected_free (ifc); - ifc = current; - } - else - { - listnode_add (ifp->connected, ifc); - } - - /* Update interface address information to protocol daemon. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - { - if_subnet_add (ifp, ifc); - - SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - - zebra_interface_address_add_update (ifp, ifc); - - if (if_is_up(ifp)) - connected_up_ipv4 (ifp, ifc); - } + if ((current = connected_check (ifp, (struct prefix *) ifc->address))) + connected_withdraw (current); /* implicit withdraw - freebsd does this */ + + connected_announce (ifp, ifc); } void @@ -237,41 +272,14 @@ connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, p.prefix = *addr; p.prefixlen = prefixlen; - ifc = connected_check_ipv4 (ifp, (struct prefix *) &p); + ifc = connected_check (ifp, (struct prefix *) &p); if (! ifc) return; - - /* Update interface address information to protocol daemon. */ - if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - { - zebra_interface_address_delete_update (ifp, ifc); - - if_subnet_delete (ifp, ifc); - - connected_down_ipv4 (ifp, ifc); - - UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - } - - listnode_delete (ifp->connected, ifc); - connected_free (ifc); + + connected_withdraw (ifc); } #ifdef HAVE_IPV6 -/* If same interface address is already exist... */ -struct connected * -connected_check_ipv6 (struct interface *ifp, struct prefix *p) -{ - struct connected *ifc; - struct listnode *node; - - for (ALL_LIST_ELEMENTS_RO (ifp->connected, node, ifc)) - if (prefix_same (ifc->address, p)) - return ifc; - - return 0; -} - void connected_up_ipv6 (struct interface *ifp, struct connected *ifc) { @@ -342,27 +350,10 @@ connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr, ifc->destination = (struct prefix *) p; } - current = connected_check_ipv6 (ifp, (struct prefix *) ifc->address); - if (current) - { - connected_free (ifc); - ifc = current; - } - else - { - listnode_add (ifp->connected, ifc); - } - - /* Update interface address information to protocol daemon. */ - if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - { - SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - - zebra_interface_address_add_update (ifp, ifc); - - if (if_is_up(ifp)) - connected_up_ipv6 (ifp, ifc); - } + if ((current = connected_check (ifp, (struct prefix *) ifc->address))) + connected_withdraw (current); /* implicit update of existing address */ + + connected_announce (ifp, ifc); } void @@ -414,21 +405,10 @@ connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address, memcpy (&p.prefix, address, sizeof (struct in6_addr)); p.prefixlen = prefixlen; - ifc = connected_check_ipv6 (ifp, (struct prefix *) &p); + ifc = connected_check (ifp, (struct prefix *) &p); if (! ifc) return; - /* Update interface address information to protocol daemon. */ - if (CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) - { - zebra_interface_address_delete_update (ifp, ifc); - - connected_down_ipv6 (ifp, ifc); - - UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); - } - - listnode_delete (ifp->connected, ifc); - connected_free (ifc); + connected_withdraw (ifc); } #endif /* HAVE_IPV6 */ diff --git a/zebra/connected.h b/zebra/connected.h index 726092ae..73166eb5 100644 --- a/zebra/connected.h +++ b/zebra/connected.h @@ -24,7 +24,7 @@ #define _ZEBRA_CONNECTED_H extern struct connected * -connected_check_ipv4 (struct interface *ifp, struct prefix *p); +connected_check (struct interface *ifp, struct prefix *p); extern void connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, @@ -38,9 +38,6 @@ extern void connected_up_ipv4 (struct interface *, struct connected *); extern void connected_down_ipv4 (struct interface *, struct connected *); #ifdef HAVE_IPV6 -extern struct connected * -connected_check_ipv6 (struct interface *ifp, struct prefix *p); - extern void connected_add_ipv6 (struct interface *ifp, struct in6_addr *address, u_char prefixlen, struct in6_addr *broad); diff --git a/zebra/interface.c b/zebra/interface.c index 92e43d97..49fffcf5 100644 --- a/zebra/interface.c +++ b/zebra/interface.c @@ -1150,7 +1150,7 @@ ip_address_install (struct vty *vty, struct interface *ifp, return CMD_WARNING; } - ifc = connected_check_ipv4 (ifp, (struct prefix *) &cp); + ifc = connected_check (ifp, (struct prefix *) &cp); if (! ifc) { ifc = connected_new (); @@ -1236,7 +1236,7 @@ ip_address_uninstall (struct vty *vty, struct interface *ifp, } /* Check current interface address. */ - ifc = connected_check_ipv4 (ifp, (struct prefix *) &cp); + ifc = connected_check (ifp, (struct prefix *) &cp); if (! ifc) { vty_out (vty, "%% Can't find address%s", VTY_NEWLINE); @@ -1346,7 +1346,7 @@ ipv6_address_install (struct vty *vty, struct interface *ifp, return CMD_WARNING; } - ifc = connected_check_ipv6 (ifp, (struct prefix *) &cp); + ifc = connected_check (ifp, (struct prefix *) &cp); if (! ifc) { ifc = connected_new (); @@ -1425,7 +1425,7 @@ ipv6_address_uninstall (struct vty *vty, struct interface *ifp, } /* Check current interface address. */ - ifc = connected_check_ipv6 (ifp, (struct prefix *) &cp); + ifc = connected_check (ifp, (struct prefix *) &cp); if (! ifc) { vty_out (vty, "%% Can't find address%s", VTY_NEWLINE); diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c index fe7411ee..f391d53a 100644 --- a/zebra/kernel_socket.c +++ b/zebra/kernel_socket.c @@ -623,8 +623,17 @@ rtm_read (struct rt_msghdr *rtm) p.prefixlen = IPV4_MAX_PREFIXLEN; else p.prefixlen = ip_masklen (mask.sin.sin_addr); - - if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD) + + /* Change, delete the old prefix, we have no further information + * to specify the route really + */ + if (rtm->rtm_type == RTM_CHANGE) + rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, + NULL, 0, 0); + + if (rtm->rtm_type == RTM_GET + || rtm->rtm_type == RTM_ADD + || rtm->rtm_type == RTM_CHANGE) rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin.sin_addr, 0, 0, 0, 0); else @@ -652,7 +661,16 @@ rtm_read (struct rt_msghdr *rtm) } #endif /* KAME */ - if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD) + /* CHANGE: delete the old prefix, we have no further information + * to specify the route really + */ + if (rtm->rtm_type == RTM_CHANGE) + rib_delete_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, + NULL, 0, 0); + + if (rtm->rtm_type == RTM_GET + || rtm->rtm_type == RTM_ADD + || rtm->rtm_type == RTM_CHANGE) rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gate.sin6.sin6_addr, ifindex, 0, 0, 0); else @@ -920,6 +938,7 @@ kernel_read (struct thread *thread) { case RTM_ADD: case RTM_DELETE: + case RTM_CHANGE: rtm_read (rtm); break; case RTM_IFINFO: |