From 718e3744195351130f4ce7dbe0613f4b3e23df93 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 13 Dec 2002 20:15:29 +0000 Subject: Initial revision --- zebra/connected.c | 394 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 394 insertions(+) create mode 100644 zebra/connected.c (limited to 'zebra/connected.c') diff --git a/zebra/connected.c b/zebra/connected.c new file mode 100644 index 00000000..cb43074b --- /dev/null +++ b/zebra/connected.c @@ -0,0 +1,394 @@ +/* + * Address linked list routine. + * Copyright (C) 1997, 98 Kunihiro Ishiguro + * + * This file is part of GNU Zebra. + * + * GNU Zebra is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * GNU Zebra is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Zebra; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include + +#include "prefix.h" +#include "linklist.h" +#include "if.h" +#include "table.h" +#include "rib.h" +#include "table.h" +#include "log.h" + +#include "zebra/zserv.h" +#include "zebra/redistribute.h" + +/* If same interface address is already exist... */ +struct connected * +connected_check_ipv4 (struct interface *ifp, struct prefix *p) +{ + struct connected *ifc; + listnode node; + + for (node = listhead (ifp->connected); node; node = nextnode (node)) + { + ifc = getdata (node); + + if (prefix_same (ifc->address, p)) + return ifc; + } + return NULL; +} + +/* Called from if_up(). */ +void +connected_up_ipv4 (struct interface *ifp, struct connected *ifc) +{ + struct prefix_ipv4 p; + struct prefix_ipv4 *addr; + struct prefix_ipv4 *dest; + + if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) + return; + + addr = (struct prefix_ipv4 *) ifc->address; + dest = (struct prefix_ipv4 *) ifc->destination; + + memset (&p, 0, sizeof (struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = addr->prefixlen; + + /* Point-to-point check. */ + if (if_is_pointopoint (ifp)) + p.prefix = dest->prefix; + else + p.prefix = addr->prefix; + + /* Apply mask to the network. */ + apply_mask_ipv4 (&p); + + /* In case of connected address is 0.0.0.0/0 we treat it tunnel + address. */ + if (prefix_ipv4_any (&p)) + return; + + rib_add_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0, 0, 0); + + rib_update (); +} + +/* Add connected IPv4 route to the interface. */ +void +connected_add_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, + int prefixlen, struct in_addr *broad, char *label) +{ + struct prefix_ipv4 *p; + struct connected *ifc; + struct connected *current; + + /* Make connected structure. */ + ifc = connected_new (); + ifc->ifp = ifp; + ifc->flags = flags; + + /* Allocate new connected address. */ + p = prefix_ipv4_new (); + p->family = AF_INET; + p->prefix = *addr; + p->prefixlen = prefixlen; + ifc->address = (struct prefix *) p; + + /* If there is broadcast or pointopoint address. */ + if (broad) + { + p = prefix_ipv4_new (); + p->family = AF_INET; + p->prefix = *broad; + ifc->destination = (struct prefix *) p; + } + + /* Label of this address. */ + if (label) + 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)) + { + SET_FLAG (ifc->conf, ZEBRA_IFC_REAL); + + zebra_interface_address_add_update (ifp, ifc); + + if (if_is_up(ifp)) + connected_up_ipv4 (ifp, ifc); + } +} + +void +connected_down_ipv4 (struct interface *ifp, struct connected *ifc) +{ + struct prefix_ipv4 p; + struct prefix_ipv4 *addr; + struct prefix_ipv4 *dest; + + if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) + return; + + addr = (struct prefix_ipv4 *)ifc->address; + dest = (struct prefix_ipv4 *)ifc->destination; + + memset (&p, 0, sizeof (struct prefix_ipv4)); + p.family = AF_INET; + p.prefixlen = addr->prefixlen; + + if (if_is_pointopoint (ifp)) + p.prefix = dest->prefix; + else + p.prefix = addr->prefix; + + /* Apply mask to the network. */ + apply_mask_ipv4 (&p); + + /* In case of connected address is 0.0.0.0/0 we treat it tunnel + address. */ + if (prefix_ipv4_any (&p)) + return; + + rib_delete_ipv4 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0); + + rib_update (); +} + +/* Delete connected IPv4 route to the interface. */ +void +connected_delete_ipv4 (struct interface *ifp, int flags, struct in_addr *addr, + int prefixlen, struct in_addr *broad, char *label) +{ + struct prefix_ipv4 p; + struct connected *ifc; + + memset (&p, 0, sizeof (struct prefix_ipv4)); + p.family = AF_INET; + p.prefix = *addr; + p.prefixlen = prefixlen; + + ifc = connected_check_ipv4 (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_ipv4 (ifp, ifc); + + UNSET_FLAG (ifc->conf, ZEBRA_IFC_REAL); + } + + if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) + { + listnode_delete (ifp->connected, ifc); + connected_free (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; + listnode node; + + for (node = listhead (ifp->connected); node; node = nextnode (node)) + { + ifc = getdata (node); + + if (prefix_same (ifc->address, p)) + return ifc; + } + return 0; +} + +void +connected_up_ipv6 (struct interface *ifp, struct connected *ifc) +{ + struct prefix_ipv6 p; + struct prefix_ipv6 *addr; + struct prefix_ipv6 *dest; + + if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) + return; + + addr = (struct prefix_ipv6 *) ifc->address; + dest = (struct prefix_ipv6 *) ifc->destination; + + memset (&p, 0, sizeof (struct prefix_ipv6)); + p.family = AF_INET6; + p.prefixlen = addr->prefixlen; + + if (if_is_pointopoint (ifp) && dest) + { + if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix)) + p.prefix = addr->prefix; + else + p.prefix = dest->prefix; + } + else + p.prefix = addr->prefix; + + /* Apply mask to the network. */ + apply_mask_ipv6 (&p); + + if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix)) + return; + + rib_add_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0); + + rib_update (); +} + +/* Add connected IPv6 route to the interface. */ +void +connected_add_ipv6 (struct interface *ifp, struct in6_addr *addr, + int prefixlen, struct in6_addr *broad) +{ + struct prefix_ipv6 *p; + struct connected *ifc; + struct connected *current; + + /* Make connected structure. */ + ifc = connected_new (); + ifc->ifp = ifp; + + /* Allocate new connected address. */ + p = prefix_ipv6_new (); + p->family = AF_INET6; + IPV6_ADDR_COPY (&p->prefix, addr); + p->prefixlen = prefixlen; + ifc->address = (struct prefix *) p; + + /* If there is broadcast or pointopoint address. */ + if (broad) + { + p = prefix_ipv6_new (); + p->family = AF_INET6; + IPV6_ADDR_COPY (&p->prefix, broad); + 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); + } +} + +void +connected_down_ipv6 (struct interface *ifp, struct connected *ifc) +{ + struct prefix_ipv6 p; + struct prefix_ipv6 *addr; + struct prefix_ipv6 *dest; + + if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_REAL)) + return; + + addr = (struct prefix_ipv6 *) ifc->address; + dest = (struct prefix_ipv6 *) ifc->destination; + + memset (&p, 0, sizeof (struct prefix_ipv6)); + p.family = AF_INET6; + p.prefixlen = addr->prefixlen; + + if (if_is_pointopoint (ifp) && dest) + { + if (IN6_IS_ADDR_UNSPECIFIED (&dest->prefix)) + p.prefix = addr->prefix; + else + p.prefix = dest->prefix; + } + else + p.prefix = addr->prefix; + + apply_mask_ipv6 (&p); + + if (IN6_IS_ADDR_UNSPECIFIED (&p.prefix)) + return; + + rib_delete_ipv6 (ZEBRA_ROUTE_CONNECT, 0, &p, NULL, ifp->ifindex, 0); + + rib_update (); +} + +void +connected_delete_ipv6 (struct interface *ifp, struct in6_addr *address, + int prefixlen, struct in6_addr *broad) +{ + struct prefix_ipv6 p; + struct connected *ifc; + + memset (&p, 0, sizeof (struct prefix_ipv6)); + p.family = AF_INET6; + memcpy (&p.prefix, address, sizeof (struct in6_addr)); + p.prefixlen = prefixlen; + + ifc = connected_check_ipv6 (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); + } + + if (! CHECK_FLAG (ifc->conf, ZEBRA_IFC_CONFIGURED)) + { + listnode_delete (ifp->connected, ifc); + connected_free (ifc); + } +} +#endif /* HAVE_IPV6 */ -- cgit v1.2.1