FreeBSD/contrib/ntp/ntpd/ntp_io.c
/*
 * link interface into list of known interfaces
 */
link interface into list of known interfaces
link interface into list of known interfaces
static void
add_interface(
	endpt *	ep
	)
{
	endpt **	pmclisthead;
	endpt *		scan;
	endpt *		scan_next;
	endpt *		unlinked;
	sockaddr_u *	addr;
	int		ep_local;
	int		scan_local;
	int		same_subnet;
	int		ep_univ_iid;	
	int		scan_univ_iid;	
	int		ep_privacy;	
	int		scan_privacy;	
	int		rc;
	ep->addr_refid = addr2refid(&ep->sin);
	LINK_TAIL_SLIST(ep_list, ep, elink, endpt);
	ninterfaces++;
#ifdef MCAST
	if (ep->ignore_packets || !(INT_MULTICAST & ep->flags) ||
	    INT_LOOPBACK & ep->flags)
		return;
# ifndef INCLUDE_IPV6_MULTICAST_SUPPORT
	if (AF_INET6 == ep->family)
		return;
# endif
	pmclisthead = (AF_INET == ep->family)
			 ? &mc4_list
			 : &mc6_list;
	if (AF_INET6 == ep->family) {
		ep_local =
		    IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(&ep->sin)) ||
		    IN6_IS_ADDR_SITELOCAL(PSOCK_ADDR6(&ep->sin));
		ep_univ_iid = IS_IID_UNIV(&ep->sin);
		ep_privacy = !!(INT_PRIVACY & ep->flags);
	} else {
		ep_local = FALSE;
		ep_univ_iid = FALSE;
		ep_privacy = FALSE;
	}
	DPRINTF(4, ("add_interface mcast-capable %s%s%s%s\n",
		    stoa(&ep->sin),
		    (ep_local) ? " link/scope-local" : "",
		    (ep_univ_iid) ? " univ-IID" : "",
		    (ep_privacy) ? " privacy" : ""));
	for (scan = *pmclisthead; scan != NULL; scan = scan_next) {
		scan_next = scan->mclink;
		if (ep->family != scan->family)
			continue;
		if (strcmp(ep->name, scan->name))
			continue;
		same_subnet = addr_samesubnet(&ep->sin, &ep->mask,
					      &scan->sin, &scan->mask);
		if (AF_INET6 == ep->family) {
			addr = &scan->sin;
			scan_local =
			    IN6_IS_ADDR_LINKLOCAL(PSOCK_ADDR6(addr)) ||
			    IN6_IS_ADDR_SITELOCAL(PSOCK_ADDR6(addr));
			scan_univ_iid = IS_IID_UNIV(addr);
			scan_privacy = !!(INT_PRIVACY & scan->flags);
		} else {
			scan_local = FALSE;
			scan_univ_iid = FALSE;
			scan_privacy = FALSE;
		}
		DPRINTF(4, ("add_interface mcast-capable scan %s%s%s%s\n",
			    stoa(&scan->sin),
			    (scan_local) ? " link/scope-local" : "",
			    (scan_univ_iid) ? " univ-IID" : "",
			    (scan_privacy) ? " privacy" : ""));
		if ((ep_local && !scan_local) || (same_subnet &&
		    ((ep_privacy && !scan_privacy) ||
		     (!ep_univ_iid && scan_univ_iid)))) {
			DPRINTF(4, ("did not add %s to %s of IPv6 multicast-capable list which already has %s\n",
				stoa(&ep->sin),
				(ep_local)
				    ? "tail"
				    : "head",
				stoa(&scan->sin)));
			return;
		}
		if ((scan_local && !ep_local) || (same_subnet &&
		    ((scan_privacy && !ep_privacy) ||
		     (!scan_univ_iid && ep_univ_iid)))) {
			UNLINK_SLIST(unlinked, *pmclisthead,
				     scan, mclink, endpt);
			DPRINTF(4, ("%s %s from IPv6 multicast-capable list to add %s\n",
				(unlinked != scan)
				    ? "Failed to remove"
				    : "removed",
				stoa(&scan->sin), stoa(&ep->sin)));
		}
	}
	if (ep_local)
		LINK_TAIL_SLIST(*pmclisthead, ep, mclink, endpt);
	else
		LINK_SLIST(*pmclisthead, ep, mclink);
	DPRINTF(4, ("added %s to %s of IPv%s multicast-capable unicast local address list\n",
		stoa(&ep->sin),
		(ep_local)
		    ? "tail"
		    : "head",
		(AF_INET == ep->family)
		    ? "4"
		    : "6"));
	if (INVALID_SOCKET == ep->fd)
		return;
	switch (AF(&ep->sin)) {
	case AF_INET :
		rc = setsockopt(ep->fd, IPPROTO_IP,
				IP_MULTICAST_IF,
				(void *)&NSRCADR(&ep->sin),
				sizeof(NSRCADR(&ep->sin)));
		if (rc)
			msyslog(LOG_ERR,
				"setsockopt IP_MULTICAST_IF %s fails: %m",
				stoa(&ep->sin));
		break;
# ifdef INCLUDE_IPV6_MULTICAST_SUPPORT
	case AF_INET6 :
		rc = setsockopt(ep->fd, IPPROTO_IPV6,
				 IPV6_MULTICAST_IF,
				 (void *)&ep->ifindex,
				 sizeof(ep->ifindex));
		if (rc && ep->ifindex != SCOPE(&ep->sin))
			msyslog(LOG_ERR,
				"setsockopt IPV6_MULTICAST_IF %u for %s fails: %m",
				ep->ifindex, stoa(&ep->sin));
		break;
# endif
	}
#endif	
}
static void add_interface ( endpt * ep ) { endpt * * pmclisthead ; endpt * scan ; endpt * scan_next ; endpt * unlinked ; sockaddr_u * addr ; int ep_local ; int scan_local ; int same_subnet ; int ep_univ_iid ; int scan_univ_iid ; int ep_privacy ; int scan_privacy ; int rc ; ep -> addr_refid = addr2refid ( & ep -> sin ) ; LINK_TAIL_SLIST ( ep_list , ep , elink , endpt ) ; ninterfaces ++ ; #ifdef MCAST if ( ep -> ignore_packets || ! ( INT_MULTICAST & ep -> flags ) || INT_LOOPBACK & ep -> flags ) return ; # ifndef INCLUDE_IPV6_MULTICAST_SUPPORT if ( AF_INET6 == ep -> family ) return ; # endif pmclisthead = ( AF_INET == ep -> family ) ? & mc4_list : & mc6_list ; if ( AF_INET6 == ep -> family ) { ep_local = IN6_IS_ADDR_LINKLOCAL ( PSOCK_ADDR6 ( & ep -> sin ) ) || IN6_IS_ADDR_SITELOCAL ( PSOCK_ADDR6 ( & ep -> sin ) ) ; ep_univ_iid = IS_IID_UNIV ( & ep -> sin ) ; ep_privacy = ! ! ( INT_PRIVACY & ep -> flags ) ; } else { ep_local = FALSE ; ep_univ_iid = FALSE ; ep_privacy = FALSE ; } DPRINTF ( 4 , ( " \n " , stoa ( & ep -> sin ) , ( ep_local ) ? " " : " " , ( ep_univ_iid ) ? " " : " " , ( ep_privacy ) ? " " : " " ) ) ; for ( scan = * pmclisthead ; scan != NULL ; scan = scan_next ) { scan_next = scan -> mclink ; if ( ep -> family != scan -> family ) continue ; if ( strcmp ( ep -> name , scan -> name ) ) continue ; same_subnet = addr_samesubnet ( & ep -> sin , & ep -> mask , & scan -> sin , & scan -> mask ) ; if ( AF_INET6 == ep -> family ) { addr = & scan -> sin ; scan_local = IN6_IS_ADDR_LINKLOCAL ( PSOCK_ADDR6 ( addr ) ) || IN6_IS_ADDR_SITELOCAL ( PSOCK_ADDR6 ( addr ) ) ; scan_univ_iid = IS_IID_UNIV ( addr ) ; scan_privacy = ! ! ( INT_PRIVACY & scan -> flags ) ; } else { scan_local = FALSE ; scan_univ_iid = FALSE ; scan_privacy = FALSE ; } DPRINTF ( 4 , ( " \n " , stoa ( & scan -> sin ) , ( scan_local ) ? " " : " " , ( scan_univ_iid ) ? " " : " " , ( scan_privacy ) ? " " : " " ) ) ; if ( ( ep_local && ! scan_local ) || ( same_subnet && ( ( ep_privacy && ! scan_privacy ) || ( ! ep_univ_iid && scan_univ_iid ) ) ) ) { DPRINTF ( 4 , ( " \n " , stoa ( & ep -> sin ) , ( ep_local ) ? " " : " " , stoa ( & scan -> sin ) ) ) ; return ; } if ( ( scan_local && ! ep_local ) || ( same_subnet && ( ( scan_privacy && ! ep_privacy ) || ( ! scan_univ_iid && ep_univ_iid ) ) ) ) { UNLINK_SLIST ( unlinked , * pmclisthead , scan , mclink , endpt ) ; DPRINTF ( 4 , ( " \n " , ( unlinked != scan ) ? " " : " " , stoa ( & scan -> sin ) , stoa ( & ep -> sin ) ) ) ; } } if ( ep_local ) LINK_TAIL_SLIST ( * pmclisthead , ep , mclink , endpt ) ; else LINK_SLIST ( * pmclisthead , ep , mclink ) ; DPRINTF ( 4 , ( " \n " , stoa ( & ep -> sin ) , ( ep_local ) ? " " : " " , ( AF_INET == ep -> family ) ? " " : " " ) ) ; if ( INVALID_SOCKET == ep -> fd ) return ; switch ( AF ( & ep -> sin ) ) { case AF_INET : rc = setsockopt ( ep -> fd , IPPROTO_IP , IP_MULTICAST_IF , ( void * ) & NSRCADR ( & ep -> sin ) , sizeof ( NSRCADR ( & ep -> sin ) ) ) ; if ( rc ) msyslog ( LOG_ERR , " " , stoa ( & ep -> sin ) ) ; break ; # ifdef INCLUDE_IPV6_MULTICAST_SUPPORT case AF_INET6 : rc = setsockopt ( ep -> fd , IPPROTO_IPV6 , IPV6_MULTICAST_IF , ( void * ) & ep -> ifindex , sizeof ( ep -> ifindex ) ) ; if ( rc && ep -> ifindex != SCOPE ( & ep -> sin ) ) msyslog ( LOG_ERR , " " , ep -> ifindex , stoa ( & ep -> sin ) ) ; break ; # endif } #endif }
link interface into list of known interfaces
link interface into list of known interfaces
/* iface ID from MAC address */ /* see RFC 4291 */ /* random local iface ID */ /* see RFC 4941 */ /* Calculate the refid */ /* link at tail so ntpdc -c ifstats index increases each row */ /* the rest is for enabled multicast-capable addresses only */ /*
	 * If we have multiple local addresses on the same network
	 * interface, and some are link- or site-local, do not multicast
	 * out from the link-/site-local addresses by default, to avoid
	 * duplicate manycastclient associations between v6 peers using
	 * link-local and global addresses.  link-local can still be
	 * chosen using "nic ignore myv6globalprefix::/64".
	 * Similarly, if we have multiple global addresses from the same
	 * prefix on the same network interface, multicast from one,
	 * preferring EUI-64, then static, then least RFC 4941 privacy
	 * addresses.
	 */ /*
	 * Add link/site local at the tail of the multicast-
	 * capable unicast interfaces list, so that ntpd will
	 * send from global addresses before link-/site-local
	 * ones.
	 */ /*
	 * select the local address from which to send to multicast.
	 */ /* do not complain if bound addr scope is ifindex */ /* MCAST */