From ca16218df74a43491e34a577db5023c89a7e79c8 Mon Sep 17 00:00:00 2001 From: paul Date: Mon, 12 Sep 2005 16:58:52 +0000 Subject: 2005-09-12 Paul Jakma * (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. --- zebra/connected.c | 158 ++++++++++++++++++++++++------------------------------ 1 file changed, 69 insertions(+), 89 deletions(-) (limited to 'zebra/connected.c') 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 */ -- cgit v1.2.1