static void nhrp_interface_update_nbma(struct interface *ifp) { struct nhrp_interface *nifp = ifp->info, *nbmanifp = NULL; struct interface *nbmaifp = NULL; union sockunion nbma; sockunion_family(&nbma) = AF_UNSPEC; if (nifp->source) nbmaifp = if_lookup_by_name(nifp->source); switch (ifp->ll_type) { case ZEBRA_LLT_IPGRE: { struct in_addr saddr = {0}; netlink_gre_get_info(ifp->ifindex, &nifp->grekey, &nifp->linkidx, &saddr); debugf(NHRP_DEBUG_IF, "%s: GRE: %x %x %x", ifp->name, nifp->grekey, nifp->linkidx, saddr.s_addr); if (saddr.s_addr) sockunion_set(&nbma, AF_INET, (u_char *) &saddr.s_addr, sizeof(saddr.s_addr)); else if (!nbmaifp && nifp->linkidx != IFINDEX_INTERNAL) nbmaifp = if_lookup_by_index(nifp->linkidx); } break; default: break; } if (nbmaifp) nbmanifp = nbmaifp->info; if (nbmaifp != nifp->nbmaifp) { if (nifp->nbmaifp) notifier_del(&nifp->nbmanifp_notifier); nifp->nbmaifp = nbmaifp; if (nbmaifp) { notifier_add(&nifp->nbmanifp_notifier, &nbmanifp->notifier_list, nhrp_interface_interface_notifier); debugf(NHRP_DEBUG_IF, "%s: bound to %s", ifp->name, nbmaifp->name); } } if (nbmaifp) { if (sockunion_family(&nbma) == AF_UNSPEC) nbma = nbmanifp->afi[AFI_IP].addr; nhrp_interface_update_mtu(ifp, AFI_IP); nhrp_interface_update_source(ifp); } if (!sockunion_same(&nbma, &nifp->nbma)) { nifp->nbma = nbma; nhrp_interface_update(nifp->ifp); debugf(NHRP_DEBUG_IF, "%s: NBMA address changed", ifp->name); notifier_call(&nifp->notifier_list, NOTIFY_INTERFACE_NBMA_CHANGED); } nhrp_interface_update(ifp); }
struct bfd_peer * bfd_peer_lookup (union sockunion *su, int ifindex, u_char peer_type) { struct bfd_peer *peer; struct listnode *node; for (node = listhead (bfd_peer_list); node; nextnode (node)) { peer = getdata (node); if (sockunion_same (&peer->su, su) && peer->ifindex == ifindex && peer->type == peer_type) return peer; } return NULL; }
static void nhrp_interface_update_address(struct interface *ifp, afi_t afi, int force) { const int family = afi2family(afi); struct nhrp_interface *nifp = ifp->info; struct nhrp_afi_data *if_ad = &nifp->afi[afi]; struct nhrp_cache *nc; struct connected *c, *best; struct listnode *cnode; union sockunion addr; char buf[PREFIX_STRLEN]; /* Select new best match preferring primary address */ best = NULL; for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) { if (PREFIX_FAMILY(c->address) != family) continue; if (best == NULL) { best = c; continue; } if ((best->flags & ZEBRA_IFA_SECONDARY) && !(c->flags & ZEBRA_IFA_SECONDARY)) { best = c; continue; } if (!(best->flags & ZEBRA_IFA_SECONDARY) && (c->flags & ZEBRA_IFA_SECONDARY)) continue; if (best->address->prefixlen > c->address->prefixlen) { best = c; continue; } if (best->address->prefixlen < c->address->prefixlen) continue; } /* On NHRP interfaces a host prefix is required */ if (best && if_ad->configured && best->address->prefixlen != 8 * prefix_blen(best->address)) { zlog_notice("%s: %s is not a host prefix", ifp->name, prefix2str(best->address, buf, sizeof buf)); best = NULL; } /* Update address if it changed */ if (best) prefix2sockunion(best->address, &addr); else memset(&addr, 0, sizeof(addr)); if (!force && sockunion_same(&if_ad->addr, &addr)) return; if (sockunion_family(&if_ad->addr) != AF_UNSPEC) { nc = nhrp_cache_get(ifp, &if_ad->addr, 0); if (nc) nhrp_cache_update_binding(nc, NHRP_CACHE_LOCAL, -1, NULL, 0, NULL); } debugf(NHRP_DEBUG_KERNEL, "%s: IPv%d address changed to %s", ifp->name, afi == AFI_IP ? 4 : 6, best ? prefix2str(best->address, buf, sizeof buf) : "(none)"); if_ad->addr = addr; if (if_ad->configured && sockunion_family(&if_ad->addr) != AF_UNSPEC) { nc = nhrp_cache_get(ifp, &addr, 1); if (nc) nhrp_cache_update_binding(nc, NHRP_CACHE_LOCAL, 0, NULL, 0, NULL); } notifier_call(&nifp->notifier_list, NOTIFY_INTERFACE_ADDRESS_CHANGED); }