FreeBSD/sys/netinet/sctp_asconf.c
/*
 * makes sure that the current kernel address list is consistent with the new
 * association (with all addrs bound) adds addresses as necessary
 */
makes sure that the current kernel address list is consistent with the new
association (with all addrs bound) adds addresses as necessary
makes sure that the current kernel address list is consistent with the new association ( with all addrs bound ) adds addresses as necessary
static void
sctp_check_address_list_all(struct sctp_tcb *stcb, struct mbuf *m, int offset,
    int length, struct sockaddr *init_addr,
    uint16_t local_scope, uint16_t site_scope,
    uint16_t ipv4_scope, uint16_t loopback_scope)
{
	struct sctp_vrf *vrf = NULL;
	struct sctp_ifn *sctp_ifn;
	struct sctp_ifa *sctp_ifa;
	uint32_t vrf_id;
#ifdef INET
	struct sockaddr_in *sin;
#endif
#ifdef INET6
	struct sockaddr_in6 *sin6;
#endif
	if (stcb) {
		vrf_id = stcb->asoc.vrf_id;
	} else {
		return;
	}
	SCTP_IPI_ADDR_RLOCK();
	vrf = sctp_find_vrf(vrf_id);
	if (vrf == NULL) {
		SCTP_IPI_ADDR_RUNLOCK();
		return;
	}
	LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
		if (loopback_scope == 0 && SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
			continue;
		}
		LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
			if (sctp_cmpaddr(&sctp_ifa->address.sa, init_addr)) {
				continue;
			}
			switch (sctp_ifa->address.sa.sa_family) {
#ifdef INET
			case AF_INET:
				sin = &sctp_ifa->address.sin;
				if (prison_check_ip4(stcb->sctp_ep->ip_inp.inp.inp_cred,
				    &sin->sin_addr) != 0) {
					continue;
				}
				if ((ipv4_scope == 0) &&
				    (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
					continue;
				}
				break;
#endif
#ifdef INET6
			case AF_INET6:
				sin6 = &sctp_ifa->address.sin6;
				if (prison_check_ip6(stcb->sctp_ep->ip_inp.inp.inp_cred,
				    &sin6->sin6_addr) != 0) {
					continue;
				}
				if ((local_scope == 0) &&
				    (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) {
					continue;
				}
				if ((site_scope == 0) &&
				    (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
					continue;
				}
				break;
#endif
			default:
				break;
			}
			if (!sctp_addr_in_initack(m, offset, length, &sctp_ifa->address.sa)) {
				sctp_addr_mgmt_assoc(stcb->sctp_ep, stcb,
				    sctp_ifa, SCTP_ADD_IP_ADDRESS,
				    SCTP_ADDR_LOCKED);
			}
		}		
	}			
	SCTP_IPI_ADDR_RUNLOCK();
}
static void sctp_check_address_list_all ( struct sctp_tcb * stcb , struct mbuf * m , int offset , int length , struct sockaddr * init_addr , uint16_t local_scope , uint16_t site_scope , uint16_t ipv4_scope , uint16_t loopback_scope ) { struct sctp_vrf * vrf = NULL ; struct sctp_ifn * sctp_ifn ; struct sctp_ifa * sctp_ifa ; uint32_t vrf_id ; #ifdef INET struct sockaddr_in * sin ; #endif #ifdef INET6 struct sockaddr_in6 * sin6 ; #endif if ( stcb ) { vrf_id = stcb -> asoc . vrf_id ; } else { return ; } SCTP_IPI_ADDR_RLOCK ( ) ; vrf = sctp_find_vrf ( vrf_id ) ; if ( vrf == NULL ) { SCTP_IPI_ADDR_RUNLOCK ( ) ; return ; } LIST_FOREACH ( sctp_ifn , & vrf -> ifnlist , next_ifn ) { if ( loopback_scope == 0 && SCTP_IFN_IS_IFT_LOOP ( sctp_ifn ) ) { continue ; } LIST_FOREACH ( sctp_ifa , & sctp_ifn -> ifalist , next_ifa ) { if ( sctp_cmpaddr ( & sctp_ifa -> address . sa , init_addr ) ) { continue ; } switch ( sctp_ifa -> address . sa . sa_family ) { #ifdef INET case AF_INET : sin = & sctp_ifa -> address . sin ; if ( prison_check_ip4 ( stcb -> sctp_ep -> ip_inp . inp . inp_cred , & sin -> sin_addr ) != 0 ) { continue ; } if ( ( ipv4_scope == 0 ) && ( IN4_ISPRIVATE_ADDRESS ( & sin -> sin_addr ) ) ) { continue ; } break ; #endif #ifdef INET6 case AF_INET6 : sin6 = & sctp_ifa -> address . sin6 ; if ( prison_check_ip6 ( stcb -> sctp_ep -> ip_inp . inp . inp_cred , & sin6 -> sin6_addr ) != 0 ) { continue ; } if ( ( local_scope == 0 ) && ( IN6_IS_ADDR_LINKLOCAL ( & sin6 -> sin6_addr ) ) ) { continue ; } if ( ( site_scope == 0 ) && ( IN6_IS_ADDR_SITELOCAL ( & sin6 -> sin6_addr ) ) ) { continue ; } break ; #endif default : break ; } if ( ! sctp_addr_in_initack ( m , offset , length , & sctp_ifa -> address . sa ) ) { sctp_addr_mgmt_assoc ( stcb -> sctp_ep , stcb , sctp_ifa , SCTP_ADD_IP_ADDRESS , SCTP_ADDR_LOCKED ) ; } } } SCTP_IPI_ADDR_RUNLOCK ( ) ; }
makes sure that the current kernel address list is consistent with the new
 association (with all addrs bound) adds addresses as necessary
makes sure that the current kernel address list is consistent with the new association ( with all addrs bound ) adds addresses as necessary
/* go through all our known interfaces */ /* skip loopback interface */ /* go through each interface address */ /* do i have it implicitly? */ /* private address not in scope */ /* check to see if in the init-ack */ /* try to add it */ /* end foreach ifa */ /* end foreach ifn */