svn commit: r267874 - stable/10/lib/libc/net

Alexander V. Chernikov melifaro at FreeBSD.org
Wed Jun 25 18:00:52 UTC 2014


On 25.06.2014 21:10, Hajimu UMEMOTO wrote:
> Author: ume
> Date: Wed Jun 25 17:10:26 2014
> New Revision: 267874
> URL: http://svnweb.freebsd.org/changeset/base/267874
> 
> Log:
>   MFC r267616, 267640:
>   
>   Retooling addrconfig() to exclude addresses on loopback interfaces
>   when looking for configured addresses.
>   This change is based upon the code from the submitter, and made
>   following changes:
>   - Exclude addresses assigned on interfaces which are down, like NetBSD
>     does.
>   - Exclude addresses assigned on interfaces which are ifdisabled.
>   
>   Use SOCK_CLOEXEC.
>   
>   PR:		190824
>   Submitted by:	Justin McOmie
> 
> Modified:
>   stable/10/lib/libc/net/getaddrinfo.c
> Directory Properties:
>   stable/10/   (props changed)
> 
> Modified: stable/10/lib/libc/net/getaddrinfo.c
> ==============================================================================
> --- stable/10/lib/libc/net/getaddrinfo.c	Wed Jun 25 17:02:01 2014	(r267873)
> +++ stable/10/lib/libc/net/getaddrinfo.c	Wed Jun 25 17:10:26 2014	(r267874)
> @@ -62,12 +62,15 @@ __FBSDID("$FreeBSD$");
>  #include <sys/socket.h>
>  #include <net/if.h>
>  #include <netinet/in.h>
> +#include <net/if_types.h>
> +#include <ifaddrs.h>
>  #include <sys/queue.h>
>  #ifdef INET6
>  #include <net/if_var.h>
>  #include <sys/sysctl.h>
>  #include <sys/ioctl.h>
> -#include <netinet6/in6_var.h>	/* XXX */
> +#include <netinet6/in6_var.h>
> +#include <netinet6/nd6.h>
>  #endif
>  #include <arpa/inet.h>
>  #include <arpa/nameser.h>
> @@ -245,6 +248,9 @@ static int get_portmatch(const struct ad
>  static int get_port(struct addrinfo *, const char *, int);
>  static const struct afd *find_afd(int);
>  static int addrconfig(struct addrinfo *);
> +#ifdef INET6
> +static int is_ifdisabled(char *);
> +#endif
>  static void set_source(struct ai_order *, struct policyhead *);
>  static int comp_dst(const void *, const void *);
>  #ifdef INET6
> @@ -1525,10 +1531,11 @@ find_afd(int af)
>  }
>  
>  /*
> - * post-2553: AI_ADDRCONFIG check.  if we use getipnodeby* as backend, backend
> - * will take care of it.
> - * the semantics of AI_ADDRCONFIG is not defined well.  we are not sure
> - * if the code is right or not.
> + * post-2553: AI_ADDRCONFIG check.  Determines which address families are
RFC 2553 is obsoleted by RFC 3493.

> + * configured on the local system and correlates with pai->ai_family value.
> + * If an address family is not configured on the system, it will not be
> + * queried for.  For this purpose, loopback addresses are not considered
> + * configured addresses.
>   *
>   * XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with
>   * _dns_getaddrinfo.
> @@ -1536,38 +1543,64 @@ find_afd(int af)
>  static int
>  addrconfig(struct addrinfo *pai)
>  {
> -	int s, af;
> +	struct ifaddrs *ifaddrs, *ifa;
> +	int seen_inet = 0, seen_inet6 = 0;
>  
> -	/*
> -	 * TODO:
> -	 * Note that implementation dependent test for address
> -	 * configuration should be done everytime called
> -	 * (or apropriate interval),
> -	 * because addresses will be dynamically assigned or deleted.
> -	 */
> -	af = pai->ai_family;
> -	if (af == AF_UNSPEC) {
> -		if ((s = _socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0)
> -			af = AF_INET;
> -		else {
> -			_close(s);
> -			if ((s = _socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC,
> -			    0)) < 0)
> -				af = AF_INET6;
> -			else
> -				_close(s);
> +	if (getifaddrs(&ifaddrs) != 0)
> +		return 0;
Well, two socket() calls has some predictable cost, but getaddrinfo()
can be quite slow for system with many interfaces. It would be better to
introduce some kernel sysctls to report IPv4/IPv6 status...

It looks like style(9) needs to be altered, too..
> +
> +	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
> +		if (ifa->ifa_addr == NULL || (ifa->ifa_flags & IFF_UP) == 0)
> +			continue;
> +		if ((ifa->ifa_flags & IFT_LOOP) != 0)
> +			continue;
This is not correct. RFC 3493 talks about "loopback address" (and
specifies explicit IN6_IS_ADDR_LOOPBACK macro to test in IPv6 case) and
not about loopback interface.

> +		switch (ifa->ifa_addr->sa_family) {
> +		case AF_INET:
> +			seen_inet = 1;
> +			break;
> +#ifdef INET6
> +		case AF_INET6:
> +			if (!seen_inet6 && !is_ifdisabled(ifa->ifa_name))

> +				seen_inet6 = 1;
> +			break;
> +#endif
>  		}
>  	}
> -	if (af != AF_UNSPEC) {
> -		if ((s = _socket(af, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0)
> -			return 0;
> -		_close(s);
> +	freeifaddrs(ifaddrs);
> +
> +	switch(pai->ai_family) {
> +	case AF_INET6:
> +		return seen_inet6;
> +	case AF_INET:
> +		return seen_inet;
> +	case AF_UNSPEC:
> +		if (seen_inet == seen_inet6)
> +			return seen_inet;
> +		pai->ai_family = seen_inet ? AF_INET : AF_INET6;
> +		return 1;
>  	}
> -	pai->ai_family = af;
>  	return 1;
>  }
>  
>  #ifdef INET6
> +static int
> +is_ifdisabled(char *name)
> +{
> +	struct in6_ndireq nd;
> +	int fd;
> +
> +	if ((fd = _socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0)) < 0)
> +		return -1;
> +	memset(&nd, 0, sizeof(nd));
> +	strlcpy(nd.ifname, name, sizeof(nd.ifname));
> +	if (_ioctl(fd, SIOCGIFINFO_IN6, &nd) < 0) {
> +		_close(fd);
> +		return -1;
> +	}
> +	_close(fd);
> +	return ((nd.ndi.flags & ND6_IFF_IFDISABLED) != 0);
> +}
> +
>  /* convert a string to a scope identifier. XXX: IPv6 specific */
>  static int
>  ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
> 
> 



More information about the svn-src-all mailing list