📄 bgp_zebra.c
字号:
/* zebra client Copyright (C) 1997, 98, 99 Kunihiro IshiguroThis file is part of GNU Zebra.GNU Zebra is free software; you can redistribute it and/or modify itunder the terms of the GNU General Public License as published by theFree Software Foundation; either version 2, or (at your option) anylater version.GNU Zebra is distributed in the hope that it will be useful, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Zebra; see the file COPYING. If not, write to theFree Software Foundation, Inc., 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. */#include <zebra.h>#include "command.h"#include "stream.h"#include "network.h"#include "prefix.h"#include "log.h"#include "sockunion.h"#include "zclient.h"#include "routemap.h"#include "thread.h"#include "bgpd/bgpd.h"#include "bgpd/bgp_route.h"#include "bgpd/bgp_attr.h"#include "bgpd/bgp_nexthop.h"#include "bgpd/bgp_zebra.h"#include "bgpd/bgp_fsm.h"/* All information about zebra. */static struct zclient *zclient = NULL;/* Update default router id. */intbgp_if_update (struct interface *ifp){ struct bgp *bgp; listnode cn; struct listnode *nn; struct listnode *nm; struct peer *peer; for (cn = listhead (ifp->connected); cn; nextnode (cn)) { struct connected *co; struct in_addr addr; co = getdata (cn); if (co->address->family == AF_INET) { addr = co->address->u.prefix4; /* Ignore NET127. */ if (IPV4_NET127 (ntohl (addr.s_addr))) continue; LIST_LOOP (bm->bgp, bgp, nn) { /* Respect configured router id */ if (! (bgp->config & BGP_CONFIG_ROUTER_ID)) if (ntohl (bgp->router_id.s_addr) < ntohl (addr.s_addr)) { bgp->router_id = addr; LIST_LOOP (bgp->peer, peer, nm) { peer->local_id = addr; } } } } } return 0;}intbgp_if_update_all (){ listnode node; struct interface *ifp; for (node = listhead (iflist); node; node = nextnode (node)) { ifp = getdata (node); bgp_if_update (ifp); } return 0;}/* Inteface addition message from zebra. */intbgp_interface_add (int command, struct zclient *zclient, zebra_size_t length){ struct interface *ifp; ifp = zebra_interface_add_read (zclient->ibuf); bgp_if_update (ifp); return 0;}intbgp_interface_delete (int command, struct zclient *zclient, zebra_size_t length){ struct stream *s; struct interface *ifp; s = zclient->ibuf; ifp = zebra_interface_state_read (s); return 0;}intbgp_interface_up (int command, struct zclient *zclient, zebra_size_t length){ struct stream *s; struct interface *ifp; struct connected *c; listnode node; s = zclient->ibuf; ifp = zebra_interface_state_read (s); if (! ifp) return 0; for (node = listhead (ifp->connected); node; nextnode (node)) { c = getdata (node); bgp_connected_add (c); } return 0;}intbgp_interface_down (int command, struct zclient *zclient, zebra_size_t length){ struct stream *s; struct interface *ifp; struct connected *c; listnode node; s = zclient->ibuf; ifp = zebra_interface_state_read (s); if (! ifp) return 0; for (node = listhead (ifp->connected); node; nextnode (node)) { c = getdata (node); bgp_connected_delete (c); } /* Fast external-failover (Currently IPv4 only) */ { struct listnode *nn, *nm; struct bgp *bgp; struct peer *peer; struct interface *peer_if; LIST_LOOP (bm->bgp, bgp, nn) { if (CHECK_FLAG (bgp->flags, BGP_FLAG_NO_FAST_EXT_FAILOVER)) continue; LIST_LOOP (bgp->peer, peer, nm) { if (peer->ttl != 1) continue; if (peer->su.sa.sa_family == AF_INET) peer_if = if_lookup_by_ipv4 (&peer->su.sin.sin_addr); else continue; if (ifp == peer_if) BGP_EVENT_ADD (peer, BGP_Stop); } } } return 0;}intbgp_interface_address_add (int command, struct zclient *zclient, zebra_size_t length){ struct connected *ifc; ifc = zebra_interface_address_add_read (zclient->ibuf); if (ifc == NULL) return 0; bgp_if_update (ifc->ifp); if (if_is_up (ifc->ifp)) bgp_connected_add (ifc); return 0;}intbgp_interface_address_delete (int command, struct zclient *zclient, zebra_size_t length){ struct connected *ifc; ifc = zebra_interface_address_delete_read (zclient->ibuf); if (ifc == NULL) return 0; bgp_if_update (ifc->ifp); if (if_is_up (ifc->ifp)) bgp_connected_delete (ifc); connected_free (ifc); return 0;}/* Zebra route add and delete treatment. */intzebra_read_ipv4 (int command, struct zclient *zclient, zebra_size_t length){ struct stream *s; struct zapi_ipv4 api; unsigned long ifindex; struct in_addr nexthop; struct prefix_ipv4 p; s = zclient->ibuf; ifindex = 0; nexthop.s_addr = 0; /* Type, flags, message. */ api.type = stream_getc (s); api.flags = stream_getc (s); api.message = stream_getc (s); /* IPv4 prefix. */ memset (&p, 0, sizeof (struct prefix_ipv4)); p.family = AF_INET; p.prefixlen = stream_getc (s); stream_get (&p.prefix, s, PSIZE (p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { api.nexthop_num = stream_getc (s); nexthop.s_addr = stream_get_ipv4 (s); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (s); ifindex = stream_getl (s); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); else api.metric = 0; if (command == ZEBRA_IPV4_ROUTE_ADD) bgp_redistribute_add ((struct prefix *)&p, &nexthop, api.metric, api.type); else bgp_redistribute_delete ((struct prefix *)&p, api.type); return 0;}#ifdef HAVE_IPV6/* Zebra route add and delete treatment. */intzebra_read_ipv6 (int command, struct zclient *zclient, zebra_size_t length){ struct stream *s; struct zapi_ipv6 api; unsigned long ifindex; struct in6_addr nexthop; struct prefix_ipv6 p; s = zclient->ibuf; ifindex = 0; memset (&nexthop, 0, sizeof (struct in6_addr)); /* Type, flags, message. */ api.type = stream_getc (s); api.flags = stream_getc (s); api.message = stream_getc (s); /* IPv6 prefix. */ memset (&p, 0, sizeof (struct prefix_ipv6)); p.family = AF_INET6; p.prefixlen = stream_getc (s); stream_get (&p.prefix, s, PSIZE (p.prefixlen)); /* Nexthop, ifindex, distance, metric. */ if (CHECK_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP)) { api.nexthop_num = stream_getc (s); stream_get (&nexthop, s, 16); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_IFINDEX)) { api.ifindex_num = stream_getc (s); ifindex = stream_getl (s); } if (CHECK_FLAG (api.message, ZAPI_MESSAGE_DISTANCE)) api.distance = stream_getc (s); else api.distance = 0; if (CHECK_FLAG (api.message, ZAPI_MESSAGE_METRIC)) api.metric = stream_getl (s); else api.metric = 0; /* Simply ignore link-local address. */ if (IN6_IS_ADDR_LINKLOCAL (&p.prefix)) return 0; if (command == ZEBRA_IPV6_ROUTE_ADD) bgp_redistribute_add ((struct prefix *)&p, NULL, api.metric, api.type); else bgp_redistribute_delete ((struct prefix *) &p, api.type); return 0;}#endif /* HAVE_IPV6 */struct interface *if_lookup_by_ipv4 (struct in_addr *addr){ listnode ifnode; listnode cnode; struct interface *ifp; struct connected *connected; struct prefix_ipv4 p; struct prefix *cp; p.family = AF_INET; p.prefix = *addr; p.prefixlen = IPV4_MAX_BITLEN; for (ifnode = listhead (iflist); ifnode; nextnode (ifnode)) { ifp = getdata (ifnode); for (cnode = listhead (ifp->connected); cnode; nextnode (cnode)) { connected = getdata (cnode); cp = connected->address; if (cp->family == AF_INET) if (prefix_match (cp, (struct prefix *)&p)) return ifp; } } return NULL;}struct interface *if_lookup_by_ipv4_exact (struct in_addr *addr){ listnode ifnode; listnode cnode; struct interface *ifp; struct connected *connected; struct prefix *cp; for (ifnode = listhead (iflist); ifnode; nextnode (ifnode)) { ifp = getdata (ifnode); for (cnode = listhead (ifp->connected); cnode; nextnode (cnode)) { connected = getdata (cnode); cp = connected->address; if (cp->family == AF_INET) if (IPV4_ADDR_SAME (&cp->u.prefix4, addr)) return ifp; } } return NULL;}#ifdef HAVE_IPV6struct interface *if_lookup_by_ipv6 (struct in6_addr *addr){ listnode ifnode; listnode cnode; struct interface *ifp; struct connected *connected; struct prefix_ipv6 p; struct prefix *cp; p.family = AF_INET6; p.prefix = *addr; p.prefixlen = IPV6_MAX_BITLEN; for (ifnode = listhead (iflist); ifnode; nextnode (ifnode)) { ifp = getdata (ifnode); for (cnode = listhead (ifp->connected); cnode; nextnode (cnode)) { connected = getdata (cnode); cp = connected->address; if (cp->family == AF_INET6) if (prefix_match (cp, (struct prefix *)&p)) return ifp; } } return NULL;}struct interface *if_lookup_by_ipv6_exact (struct in6_addr *addr){ listnode ifnode; listnode cnode; struct interface *ifp; struct connected *connected; struct prefix *cp; for (ifnode = listhead (iflist); ifnode; nextnode (ifnode)) { ifp = getdata (ifnode); for (cnode = listhead (ifp->connected); cnode; nextnode (cnode)) { connected = getdata (cnode); cp = connected->address; if (cp->family == AF_INET6) if (IPV6_ADDR_SAME (&cp->u.prefix6, addr)) return ifp; } } return NULL;}intif_get_ipv6_global (struct interface *ifp, struct in6_addr *addr){ listnode cnode; struct connected *connected; struct prefix *cp; for (cnode = listhead (ifp->connected); cnode; nextnode (cnode)) { connected = getdata (cnode); cp = connected->address; if (cp->family == AF_INET6) if (! IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6)) { memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN); return 1; } } return 0;}intif_get_ipv6_local (struct interface *ifp, struct in6_addr *addr){ listnode cnode; struct connected *connected; struct prefix *cp; for (cnode = listhead (ifp->connected); cnode; nextnode (cnode)) { connected = getdata (cnode); cp = connected->address; if (cp->family == AF_INET6) if (IN6_IS_ADDR_LINKLOCAL (&cp->u.prefix6)) { memcpy (addr, &cp->u.prefix6, IPV6_MAX_BYTELEN); return 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -