Esempio n. 1
0
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);
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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);
}