diff options
| author | David Lamparter <equinox@opensourcerouting.org> | 2021-06-23 16:35:44 +0200 | 
|---|---|---|
| committer | David Lamparter <equinox@opensourcerouting.org> | 2021-11-17 11:17:44 +0100 | 
| commit | 1e9044be8d4325fa82f01d72eb6c8581dcd6fd06 (patch) | |
| tree | 587f2a6a425b6328de693f0e39bd79c0e4e82d47 /lib/if.c | |
| parent | 7022e70d744105999ebd087701650c01d4faa3e0 (diff) | |
*: clean up ifp-by-local-address function(s)
Most users of if_lookup_address_exact only cared about whether the
address is any local address.  Split that off into a separate function.
For the users that actually need the ifp - which I'm about to add a few
of - change it to prefer returning interfaces that are UP.
(Function name changed due to slight change in behavior re. UP state, to
avoid possible bugs from this change.)
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'lib/if.c')
| -rw-r--r-- | lib/if.c | 43 | 
1 files changed, 29 insertions, 14 deletions
@@ -455,36 +455,51 @@ static struct interface *if_lookup_by_index_all_vrf(ifindex_t ifindex)  	return NULL;  } -/* Lookup interface by IP address. */ -struct interface *if_lookup_exact_address(const void *src, int family, +/* Lookup interface by IP address. + * + * supersedes if_lookup_exact_address(), which didn't care about up/down + * state.  but all users we have either only care if the address is local + * (=> use if_address_is_local() please), or care about UP interfaces before + * anything else + * + * to accept only UP interfaces, check if_is_up() on the returned ifp. + */ +struct interface *if_lookup_address_local(const void *src, int family,  					  vrf_id_t vrf_id)  {  	struct vrf *vrf = vrf_lookup_by_id(vrf_id);  	struct listnode *cnode; -	struct interface *ifp; +	struct interface *ifp, *best_down = NULL;  	struct prefix *p;  	struct connected *c; +	if (family != AF_INET && family != AF_INET6) +		return NULL; +  	FOR_ALL_INTERFACES (vrf, ifp) {  		for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {  			p = c->address; -			if (p && (p->family == family)) { -				if (family == AF_INET) { -					if (IPV4_ADDR_SAME( -						    &p->u.prefix4, +			if (!p || p->family != family) +				continue; + +			if (family == AF_INET) { +				if (!IPV4_ADDR_SAME(&p->u.prefix4,  						    (struct in_addr *)src)) -						return ifp; -				} else if (family == AF_INET6) { -					if (IPV6_ADDR_SAME( -						    &p->u.prefix6, +					continue; +			} else if (family == AF_INET6) { +				if (!IPV6_ADDR_SAME(&p->u.prefix6,  						    (struct in6_addr *)src)) -						return ifp; -				} +					continue;  			} + +			if (if_is_up(ifp)) +				return ifp; +			if (!best_down) +				best_down = ifp;  		}  	} -	return NULL; +	return best_down;  }  /* Lookup interface by IP address. */  | 
