FreeBSD/sys/netinet6/scope6.c
/*
 * This function is for checking sockaddr_in6 structure passed
 * from the application level (usually).
 *
 * sin6_scope_id should be set for link-local unicast, link-local and
 * interface-local  multicast addresses.
 *
 * If it is zero, then look into default zone ids. If default zone id is
 * not set or disabled, then return error.
 */
This function is for checking sockaddr_in6 structure passed
from the application level (usually).

sin6_scope_id should be set for link-local unicast, link-local and
interface-local  multicast addresses.

If it is zero, then look into default zone ids. If default zone id is
not set or disabled, then return error.
This function is for checking sockaddr_in6 structure passed from the application level ( usually ) . sin6_scope_id should be set for link - local unicast link - local and interface - local multicast addresses . If it is zero then look into default zone ids . If default zone id is not set or disabled then return error .
int
sa6_checkzone(struct sockaddr_in6 *sa6)
{
	int scope;
	scope = in6_addrscope(&sa6->sin6_addr);
	if (scope == IPV6_ADDR_SCOPE_GLOBAL)
		return (sa6->sin6_scope_id ? EINVAL: 0);
	if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr) &&
	    scope != IPV6_ADDR_SCOPE_LINKLOCAL &&
	    scope != IPV6_ADDR_SCOPE_INTFACELOCAL) {
		if (sa6->sin6_scope_id == 0 && V_ip6_use_defzone != 0)
			sa6->sin6_scope_id = V_sid_default.s6id_list[scope];
		return (0);
	}
	if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr)) {
		if (sa6->sin6_scope_id == 0)
			sa6->sin6_scope_id = in6_getscopezone(V_loif, scope);
		else if (sa6->sin6_scope_id != in6_getscopezone(V_loif, scope))
			return (EADDRNOTAVAIL);
	}
	if (sa6->sin6_scope_id != 0)
		return (0);
	if (V_ip6_use_defzone != 0)
		sa6->sin6_scope_id = V_sid_default.s6id_list[scope];
	return (sa6->sin6_scope_id ? 0: EADDRNOTAVAIL);
}
int sa6_checkzone ( struct sockaddr_in6 * sa6 ) { int scope ; scope = in6_addrscope ( & sa6 -> sin6_addr ) ; if ( scope == IPV6_ADDR_SCOPE_GLOBAL ) return ( sa6 -> sin6_scope_id ? EINVAL : 0 ) ; if ( IN6_IS_ADDR_MULTICAST ( & sa6 -> sin6_addr ) && scope != IPV6_ADDR_SCOPE_LINKLOCAL && scope != IPV6_ADDR_SCOPE_INTFACELOCAL ) { if ( sa6 -> sin6_scope_id == 0 && V_ip6_use_defzone != 0 ) sa6 -> sin6_scope_id = V_sid_default . s6id_list [ scope ] ; return ( 0 ) ; } if ( IN6_IS_ADDR_LOOPBACK ( & sa6 -> sin6_addr ) ) { if ( sa6 -> sin6_scope_id == 0 ) sa6 -> sin6_scope_id = in6_getscopezone ( V_loif , scope ) ; else if ( sa6 -> sin6_scope_id != in6_getscopezone ( V_loif , scope ) ) return ( EADDRNOTAVAIL ) ; } if ( sa6 -> sin6_scope_id != 0 ) return ( 0 ) ; if ( V_ip6_use_defzone != 0 ) sa6 -> sin6_scope_id = V_sid_default . s6id_list [ scope ] ; return ( sa6 -> sin6_scope_id ? 0 : EADDRNOTAVAIL ) ; }
This function is for checking sockaddr_in6 structure passed
 from the application level (usually).
This function is for checking sockaddr_in6 structure passed from the application level ( usually ) .
/*
	 * Since ::1 address always configured on the lo0, we can
	 * automatically set its zone id, when it is not specified.
	 * Return error, when specified zone id doesn't match with
	 * actual value.
	 */ /* XXX: we can validate sin6_scope_id here */ /* Return error if we can't determine zone id */