connected.c
上传用户:xiaozhuqw
上传日期:2009-11-15
资源大小:1338k
文件大小:9k
- /*
- * 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 <zebra.h>
- #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 */