📄 bgp_zebra.c
字号:
} } return 0;}#endif /* HAVE_IPV6 */intbgp_nexthop_set (union sockunion *local, union sockunion *remote, struct bgp_nexthop *nexthop, struct peer *peer){ int ret = 0; struct interface *ifp = NULL; memset (nexthop, 0, sizeof (struct bgp_nexthop)); if (!local) return -1; if (!remote) return -1; if (local->sa.sa_family == AF_INET) { nexthop->v4 = local->sin.sin_addr; ifp = if_lookup_by_ipv4 (&local->sin.sin_addr); }#ifdef HAVE_IPV6 if (local->sa.sa_family == AF_INET6) { if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr)) { if (peer->ifname) ifp = if_lookup_by_index (if_nametoindex (peer->ifname)); } else ifp = if_lookup_by_ipv6 (&local->sin6.sin6_addr); }#endif /* HAVE_IPV6 */ if (!ifp) return -1; nexthop->ifp = ifp; /* IPv4 connection. */ if (local->sa.sa_family == AF_INET) {#ifdef HAVE_IPV6 /* IPv6 nexthop*/ ret = if_get_ipv6_global (ifp, &nexthop->v6_global); /* There is no global nexthop. */ if (!ret) if_get_ipv6_local (ifp, &nexthop->v6_global); else if_get_ipv6_local (ifp, &nexthop->v6_local);#endif /* HAVE_IPV6 */ }#ifdef HAVE_IPV6 /* IPv6 connection. */ if (local->sa.sa_family == AF_INET6) { struct interface *direct = NULL; /* IPv4 nexthop. I don't care about it. */ if (peer->local_id.s_addr) nexthop->v4 = peer->local_id; /* Global address*/ if (! IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr)) { memcpy (&nexthop->v6_global, &local->sin6.sin6_addr, IPV6_MAX_BYTELEN); /* If directory connected set link-local address. */ direct = if_lookup_by_ipv6 (&remote->sin6.sin6_addr); if (direct) if_get_ipv6_local (ifp, &nexthop->v6_local); } else /* Link-local address. */ { ret = if_get_ipv6_global (ifp, &nexthop->v6_global); /* If there is no global address. Set link-local address as global. I know this break RFC specification... */ if (!ret) memcpy (&nexthop->v6_global, &local->sin6.sin6_addr, IPV6_MAX_BYTELEN); else memcpy (&nexthop->v6_local, &local->sin6.sin6_addr, IPV6_MAX_BYTELEN); } } if (IN6_IS_ADDR_LINKLOCAL (&local->sin6.sin6_addr) || if_lookup_by_ipv6 (&remote->sin6.sin6_addr)) peer->shared_network = 1; else peer->shared_network = 0; /* KAME stack specific treatment. */#ifdef KAME if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_global) && IN6_LINKLOCAL_IFINDEX (nexthop->v6_global)) { SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_global, 0); } if (IN6_IS_ADDR_LINKLOCAL (&nexthop->v6_local) && IN6_LINKLOCAL_IFINDEX (nexthop->v6_local)) { SET_IN6_LINKLOCAL_IFINDEX (nexthop->v6_local, 0); }#endif /* KAME */#endif /* HAVE_IPV6 */ return ret;}#ifdef HAVE_IPV6unsigned intbgp_ifindex_by_nexthop (struct in6_addr *addr){ listnode ifnode; listnode cnode; struct interface *ifp; struct connected *connected; struct prefix_ipv6 p; 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)) { struct prefix *cp; connected = getdata (cnode); cp = connected->address; if (cp->family == AF_INET6) { if (prefix_match (cp, (struct prefix *)&p)) return ifp->ifindex; } } } return 0;}#endif /* HAVE_IPV6 */voidbgp_zebra_announce (struct prefix *p, struct bgp_info *info, struct bgp *bgp){ int flags; u_char distance; struct peer *peer; if (zclient->sock < 0) return; if (! zclient->redist[ZEBRA_ROUTE_BGP]) return; flags = 0; peer = info->peer; if (peer_sort (peer) == BGP_PEER_IBGP || peer_sort (peer) == BGP_PEER_CONFED) { SET_FLAG (flags, ZEBRA_FLAG_IBGP); SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); } if ((peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1) || CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP)) SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); if (p->family == AF_INET) { struct zapi_ipv4 api; struct in_addr *nexthop; api.flags = flags; nexthop = &info->attr->nexthop; api.type = ZEBRA_ROUTE_BGP; api.message = 0; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; api.nexthop = &nexthop; api.ifindex_num = 0; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; distance = bgp_distance_apply (p, info, bgp); if (distance) { SET_FLAG (api.message, ZAPI_MESSAGE_DISTANCE); api.distance = distance; } zapi_ipv4_add (zclient, (struct prefix_ipv4 *) p, &api); }#ifdef HAVE_IPV6 /* We have to think about a IPv6 link-local address curse. */ if (p->family == AF_INET6) { unsigned int ifindex; struct in6_addr *nexthop; struct zapi_ipv6 api; ifindex = 0; nexthop = NULL; /* Only global address nexthop exists. */ if (info->attr->mp_nexthop_len == 16) nexthop = &info->attr->mp_nexthop_global; /* If both global and link-local address present. */ if (info->attr->mp_nexthop_len == 32) { /* Workaround for Cisco's nexthop bug. */ if (IN6_IS_ADDR_UNSPECIFIED (&info->attr->mp_nexthop_global) && peer->su_remote->sa.sa_family == AF_INET6) nexthop = &peer->su_remote->sin6.sin6_addr; else nexthop = &info->attr->mp_nexthop_local; if (info->peer->nexthop.ifp) ifindex = info->peer->nexthop.ifp->ifindex; } if (nexthop == NULL) return; if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex) { if (info->peer->ifname) ifindex = if_nametoindex (info->peer->ifname); else if (info->peer->nexthop.ifp) ifindex = info->peer->nexthop.ifp->ifindex; } /* Make Zebra API structure. */ api.flags = flags; api.type = ZEBRA_ROUTE_BGP; api.message = 0; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; api.nexthop = &nexthop; SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); api.ifindex_num = 1; api.ifindex = &ifindex; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; zapi_ipv6_add (zclient, (struct prefix_ipv6 *) p, &api); }#endif /* HAVE_IPV6 */}voidbgp_zebra_withdraw (struct prefix *p, struct bgp_info *info){ int flags; struct peer *peer; if (zclient->sock < 0) return; if (! zclient->redist[ZEBRA_ROUTE_BGP]) return; peer = info->peer; flags = 0; if (peer_sort (peer) == BGP_PEER_IBGP) { SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); SET_FLAG (flags, ZEBRA_FLAG_IBGP); } if ((peer_sort (peer) == BGP_PEER_EBGP && peer->ttl != 1) || CHECK_FLAG (peer->flags, PEER_FLAG_ENFORCE_MULTIHOP)) SET_FLAG (flags, ZEBRA_FLAG_INTERNAL); if (p->family == AF_INET) { struct zapi_ipv4 api; struct in_addr *nexthop; api.flags = flags; nexthop = &info->attr->nexthop; api.type = ZEBRA_ROUTE_BGP; api.message = 0; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; api.nexthop = &nexthop; api.ifindex_num = 0; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; zapi_ipv4_delete (zclient, (struct prefix_ipv4 *) p, &api); }#ifdef HAVE_IPV6 /* We have to think about a IPv6 link-local address curse. */ if (p->family == AF_INET6) { struct zapi_ipv6 api; unsigned int ifindex; struct in6_addr *nexthop; ifindex = 0; nexthop = NULL; /* Only global address nexthop exists. */ if (info->attr->mp_nexthop_len == 16) nexthop = &info->attr->mp_nexthop_global; /* If both global and link-local address present. */ if (info->attr->mp_nexthop_len == 32) { nexthop = &info->attr->mp_nexthop_local; if (info->peer->nexthop.ifp) ifindex = info->peer->nexthop.ifp->ifindex; } if (nexthop == NULL) return; if (IN6_IS_ADDR_LINKLOCAL (nexthop) && ! ifindex) if (info->peer->ifname) ifindex = if_nametoindex (info->peer->ifname); api.flags = flags; api.type = ZEBRA_ROUTE_BGP; api.message = 0; SET_FLAG (api.message, ZAPI_MESSAGE_NEXTHOP); api.nexthop_num = 1; api.nexthop = &nexthop; SET_FLAG (api.message, ZAPI_MESSAGE_IFINDEX); api.ifindex_num = 1; api.ifindex = &ifindex; SET_FLAG (api.message, ZAPI_MESSAGE_METRIC); api.metric = info->attr->med; zapi_ipv6_delete (zclient, (struct prefix_ipv6 *) p, &api); }#endif /* HAVE_IPV6 */}/* Other routes redistribution into BGP. */intbgp_redistribute_set (struct bgp *bgp, afi_t afi, int type){ /* Set flag to BGP instance. */ bgp->redist[afi][type] = 1; /* Return if already redistribute flag is set. */ if (zclient->redist[type]) return CMD_WARNING; zclient->redist[type] = 1; /* Return if zebra connection is not established. */ if (zclient->sock < 0) return CMD_WARNING; /* Send distribute add message to zebra. */ zebra_redistribute_send (ZEBRA_REDISTRIBUTE_ADD, zclient->sock, type); return CMD_SUCCESS;}/* Redistribute with route-map specification. */intbgp_redistribute_rmap_set (struct bgp *bgp, afi_t afi, int type, char *name){ if (bgp->rmap[afi][type].name && (strcmp (bgp->rmap[afi][type].name, name) == 0)) return 0; if (bgp->rmap[afi][type].name) free (bgp->rmap[afi][type].name); bgp->rmap[afi][type].name = strdup (name); bgp->rmap[afi][type].map = route_map_lookup_by_name (name); return 1;}/* Redistribute with metric specification. */intbgp_redistribute_metric_set (struct bgp *bgp, afi_t afi, int type, u_int32_t metric){ if (bgp->redist_metric_flag[afi][type] && bgp->redist_metric[afi][type] == metric) return 0; bgp->redist_metric_flag[afi][type] = 1; bgp->redist_metric[afi][type] = metric; return 1;}/* Unset redistribution. */intbgp_redistribute_unset (struct bgp *bgp, afi_t afi, int type){ /* Unset flag from BGP instance. */ bgp->redist[afi][type] = 0; /* Unset route-map. */ if (bgp->rmap[afi][type].name) free (bgp->rmap[afi][type].name); bgp->rmap[afi][type].name = NULL; bgp->rmap[afi][type].map = NULL; /* Unset metric. */ bgp->redist_metric_flag[afi][type] = 0; bgp->redist_metric[afi][type] = 0; /* Return if zebra connection is disabled. */ if (! zclient->redist[type]) return CMD_WARNING; zclient->redist[type] = 0; if (bgp->redist[AFI_IP][type] == 0 && bgp->redist[AFI_IP6][type] == 0 && zclient->sock >= 0) /* Send distribute delete message to zebra. */ zebra_redistribute_send (ZEBRA_REDISTRIBUTE_DELETE, zclient->sock, type); /* Withdraw redistributed routes from current BGP's routing table. */ bgp_redistribute_withdraw (bgp, afi, type); return CMD_SUCCESS;}/* Unset redistribution route-map configuration. */intbgp_redistribute_routemap_unset (struct bgp *bgp, afi_t afi, int type){ if (! bgp->rmap[afi][type].name) return 0; /* Unset route-map. */ free (bgp->rmap[afi][type].name); bgp->rmap[afi][type].name = NULL; bgp->rmap[afi][type].map = NULL; return 1;}/* Unset redistribution metric configuration. */intbgp_redistribute_metric_unset (struct bgp *bgp, afi_t afi, int type){ if (! bgp->redist_metric_flag[afi][type]) return 0; /* Unset metric. */ bgp->redist_metric_flag[afi][type] = 0; bgp->redist_metric[afi][type] = 0; return 1;}voidbgp_zclient_reset (){ zclient_reset (zclient);}voidbgp_zebra_init (int enable){ /* Set default values. */ zclient = zclient_new (); zclient_init (zclient, ZEBRA_ROUTE_BGP); zclient->interface_add = bgp_interface_add; zclient->interface_delete = bgp_interface_delete; zclient->interface_address_add = bgp_interface_address_add; zclient->interface_address_delete = bgp_interface_address_delete; zclient->ipv4_route_add = zebra_read_ipv4; zclient->ipv4_route_delete = zebra_read_ipv4; zclient->interface_up = bgp_interface_up; zclient->interface_down = bgp_interface_down;#ifdef HAVE_IPV6 zclient->ipv6_route_add = zebra_read_ipv6; zclient->ipv6_route_delete = zebra_read_ipv6;#endif /* HAVE_IPV6 */ /* Interface related init. */ if_init ();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -